From 55ed8ca559b3991a32124ffe743d3bc5b6dda13a Mon Sep 17 00:00:00 2001 From: Hatton Date: Wed, 1 May 2024 16:02:46 -0600 Subject: [PATCH] fix: Convert Notion's "mention" style links to internal pages, #97 --- src/plugins/internalLinks.spec.ts | 42 +++++++++++++++++++++++++++++++ src/plugins/internalLinks.ts | 9 +++++-- src/pull.ts | 2 +- 3 files changed, 50 insertions(+), 3 deletions(-) diff --git a/src/plugins/internalLinks.spec.ts b/src/plugins/internalLinks.spec.ts index 2124e08..e6e7dd2 100644 --- a/src/plugins/internalLinks.spec.ts +++ b/src/plugins/internalLinks.spec.ts @@ -31,6 +31,48 @@ test("urls that show up as raw text get left that way", async () => { expect(results.trim()).toBe("https://github.com"); }); +// See https://github.com/sillsdev/docu-notion/issues/97 +test("mention-style link to an existing page", async () => { + const targetPageId = "123"; + const targetPage: NotionPage = makeSamplePageObject({ + slug: undefined, + name: "Hello World", + id: targetPageId, + }); + + const results = await getMarkdown( + { + type: "paragraph", + paragraph: { + rich_text: [ + { + type: "mention", + mention: { + type: "page", + page: { + id: `${targetPageId}`, + }, + }, + annotations: { + bold: false, + italic: false, + strikethrough: false, + underline: false, + code: false, + color: "default", + }, + plain_text: "foo", + href: `https://www.notion.so/${targetPageId}`, + }, + ], + color: "default", + }, + }, + targetPage + ); + expect(results.trim()).toBe(`[foo](/${targetPageId})`); +}); + test("link to an existing page on this site that has no slug", async () => { const targetPageId = "123"; const targetPage: NotionPage = makeSamplePageObject({ diff --git a/src/plugins/internalLinks.ts b/src/plugins/internalLinks.ts index c73de27..5713065 100644 --- a/src/plugins/internalLinks.ts +++ b/src/plugins/internalLinks.ts @@ -40,7 +40,9 @@ function convertInternalLink( context: IDocuNotionContext, markdownLink: string ): string { - const linkRegExp = /\[([^\]]+)?\]\(\/?([^),^/]+)\)/g; + // match both [foo](/123) and [bar](https://www.notion.so/123) <-- the "mention" link style + const linkRegExp = + /\[([^\]]+)?\]\((?:https?:\/\/www\.notion\.so\/|\/)?([^),^/]+)\)/g; const match = linkRegExp.exec(markdownLink); if (match === null) { warning( @@ -125,7 +127,10 @@ export const standardInternalLinkConversion: IPlugin = { // (has some other text that's been turned into a link) or "raw". // Raw links come in without a leading slash, e.g. [link_to_page](4a6de8c0-b90b-444b-8a7b-d534d6ec71a4) // Inline links come in with a leading slash, e.g. [pointer to the introduction](/4a6de8c0b90b444b8a7bd534d6ec71a4) - match: /\[([^\]]+)?\]\((?!mailto:)(\/?[^),^/]+)\)/, + // "Mention" links come in as full URLs, e.g. [link_to_page](https://www.notion.so/62f1187010214b0883711a1abb277d31) + // YOu can create them either with @+the name of a page, or by pasting a URL and then selecting the "Mention" option. + match: + /\[([^\]]+)?\]\((?!mailto:)(https:\/\/www\.notion\.so\/[^),^/]+|\/?[^),^/]+)\)/, convert: convertInternalLink, }, }; diff --git a/src/pull.ts b/src/pull.ts index 61fd717..3cc901b 100644 --- a/src/pull.ts +++ b/src/pull.ts @@ -216,7 +216,7 @@ async function getPagesRecursively( pageInfo.childPageIdsAndOrder.length ) { error( - `Skipping "${pageInTheOutline.nameOrTitle}" and its children. docu-notion does not support pages that are both levels and have content at the same time.` + `Skipping "${pageInTheOutline.nameOrTitle}" and its children. docu-notion does not support pages that are both levels and have text content (paragraphs) at the same time. Normally outline pages should just be composed of 1) links to other pages and 2) child pages (other levels of the outline). Note that @-mention style links appear as text paragraphs to docu-notion so must not be used to form the outline.` ); ++counts.skipped_because_level_cannot_have_content; return;