Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ The export configuration items may contain the following keys:
| notion_filter | A [notion filter object](https://developers.notion.com/reference/post-database-query-filter) to be applied to the database. |
| notion_sorts | A [notion sorts object](https://developers.notion.com/reference/post-database-query-sort) to be applied to the database. |
| property_map | A mapping between the name of properties in Notion, and the name of the properties in the exported files. Set the new value to `null` to discard the property.|
| keep_unmapped_properties | Defaults to `true`. When set to `false`, the `property_map` acts as an allowlist: any property not in the map is dropped from the export. This prevents properties added or renamed in Notion from leaking into the exported files. The `id_property` and `url_property` are always kept. |
| keep_unmapped_properties | Defaults to `true`. When set to `false`, the `property_map` acts as an allowlist: any Notion property not in the map is dropped from the export. This prevents properties added or renamed in Notion from leaking into the exported files. The `id_property`, the `url_property`, and properties injected by plugins are always kept. |

## Example Configuration Files

Expand Down
7 changes: 5 additions & 2 deletions n2y/export.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,13 +54,16 @@ def _page_properties(
page.client.logger.warning(msg, original, page.notion_url, original, new)
if not keep_unmapped_properties:
# Treat the property map as an allowlist so that properties added or
# renamed in Notion don't leak into the exported files.
# renamed in Notion don't leak into the exported files. Only properties
# that exist in Notion are dropped; properties injected by plugins
# (which won't appear in the page's notion_data) are always kept.
notion_property_names = set(page.notion_data["properties"].keys())
kept_properties = {new for new in property_map.values() if new}
kept_properties.update(p for p in (id_property, url_property) if p)
properties = {
name: value
for name, value in properties.items()
if name in kept_properties
if name in kept_properties or name not in notion_property_names
}
return properties

Expand Down
17 changes: 10 additions & 7 deletions tests/test_audit_end_to_end.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,19 +25,22 @@ def test_audit():
status, stdoutput = run_n2yaudit([object_id])
assert status == 3

external_mention_in_top_page = "https://www.notion.so/Audited-cfa8ff07bba244c8b967c9b6a7a954c1#aa4fa886f8244c818de8018bb3491806" # noqa: E501
external_mention_in_child_page = "https://www.notion.so/Child-f3e3628fc80c470ea68994fa7ec0ff17#d1d32ff6f0cb4c71a2f1c4ec55e00086" # noqa: E501
internal_mention_in_child_page = "https://www.notion.so/Child-f3e3628fc80c470ea68994fa7ec0ff17#eab91ccc32924221ac3f0a74225a33dd" # noqa: E501
external_mention_in_child_database = "https://www.notion.so/B-4412005dcec24ff2827abbc367c90b29#6373a0b5c2804fbe9dfac167ce6948a0" # noqa: E501
internal_mention_in_database_in_column = "https://www.notion.so/Audited-cfa8ff07bba244c8b967c9b6a7a954c1#21a13c06ef86462e882a181c6cb52a64" # noqa: E501
# Only the page-slug#block-id fragment is asserted (not the full URL)
# because Notion has changed the URL host/path over time (e.g. from
# www.notion.so/<slug> to app.notion.com/p/<slug>).
external_mention_in_top_page = "Audited-cfa8ff07bba244c8b967c9b6a7a954c1#aa4fa886f8244c818de8018bb3491806" # noqa: E501
external_mention_in_child_page = "Child-f3e3628fc80c470ea68994fa7ec0ff17#d1d32ff6f0cb4c71a2f1c4ec55e00086" # noqa: E501
internal_mention_in_child_page = "Child-f3e3628fc80c470ea68994fa7ec0ff17#eab91ccc32924221ac3f0a74225a33dd" # noqa: E501
external_mention_in_child_database = "B-4412005dcec24ff2827abbc367c90b29#6373a0b5c2804fbe9dfac167ce6948a0" # noqa: E501
internal_mention_in_database_in_column = "Audited-cfa8ff07bba244c8b967c9b6a7a954c1#21a13c06ef86462e882a181c6cb52a64" # noqa: E501

# NOTE: When you try to get a link for a "LinkToPageBlock" in the Notion UI,
# it appears to give you the URL for the linked page or database, and not to
# the block itself. Thus, these two links were extracted using a debugger
# when running this test.

external_link_in_top_page = "https://www.notion.so/Audited-cfa8ff07bba244c8b967c9b6a7a954c1#c22d76d50c704761b0e729531e6cc24b" # noqa: E501
internal_link_in_top_page = "https://www.notion.so/Audited-cfa8ff07bba244c8b967c9b6a7a954c1#3e2e2fb2e9bf4a1f8b00bbb18a9d97e9" # noqa: E501
external_link_in_top_page = "Audited-cfa8ff07bba244c8b967c9b6a7a954c1#c22d76d50c704761b0e729531e6cc24b" # noqa: E501
internal_link_in_top_page = "Audited-cfa8ff07bba244c8b967c9b6a7a954c1#3e2e2fb2e9bf4a1f8b00bbb18a9d97e9" # noqa: E501

assert external_mention_in_top_page in stdoutput
assert external_mention_in_child_page in stdoutput
Expand Down
10 changes: 10 additions & 0 deletions tests/test_export.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,16 @@ def test_page_properties_drop_unmapped_keeps_id_and_url(page):
assert set(properties) == {"id", "url"}


def test_page_properties_drop_unmapped_keeps_plugin_injected(page):
# Plugins may inject extra properties (e.g. embedded mention data) that
# don't exist in the page's notion_data; the allowlist must keep them.
page.properties["injected"] = page.properties["property"]
properties = _page_properties(
page, property_map={"property": "p"}, keep_unmapped_properties=False
)
assert properties == {"p": "P\n", "injected": "P\n"}


def test_page_properties_drop_unmapped_keeps_mapped_title(page):
properties = _page_properties(
page, property_map={"title": "title"}, keep_unmapped_properties=False
Expand Down
Loading