From e2a94033f38a8e7f9e4fde9816c2e4a58ab8dc15 Mon Sep 17 00:00:00 2001 From: Dion Amago Date: Tue, 27 Dec 2022 11:19:14 -0800 Subject: [PATCH 1/2] Internal mermaid clickable links --- README.md | 49 ++++++++++++++++++++------- src/index.ts | 5 +++ src/linksMermaid.ts | 80 +++++++++++++++++++++++++++++++++++++++++++++ src/pull.ts | 9 +++++ 4 files changed, 132 insertions(+), 11 deletions(-) create mode 100644 src/linksMermaid.ts diff --git a/README.md b/README.md index 6c84d92..c55972b 100644 --- a/README.md +++ b/README.md @@ -112,20 +112,47 @@ NOTE: if you just localize an image, it will not get picked up. You also must lo Here is a working Github Action script to copy and customize: https://github.com/BloomBooks/bloom-docs/blob/master/.github/workflows/release.yml +# Links within mermaid code blocks + +Mermaid code blocks can contain clickable links to other notion documents. This works great in notion, but to convert you might need to add the flag: + +``` + --slug-prefix +``` + +where `` might be e.g. `blog` if the root of the converted documents is are your blogs and they live in the directory "./blog". + +This converts the `An internal page` node below into a clickable link in your published site: + +```mermaid +graph LR + A[An internal page] --> B(Somewhere else) + click A "https://www.notion.so/Introduction-to-docu-notion-779f83504bd94642a9b87b2afc810aaa" +``` + +``` +graph LR + A[An internal page] --> B(Somewhere else) + click A "https://www.notion.so/Introduction-to-docu-notion-779f83504bd94642a9b87b2afc810aaa" +``` + + + # Command line Usage: docu-notion -n -r [options] Options: -| flag | required? | description | -| ------------------------------------- | --------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | -| -n, --notion-token | required | notion api token, which looks like `secret_3bc1b50XFYb15123RHF243x43450XFY33250XFYa343` | -| -r, --root-page | required | The 31 character ID of the page which is the root of your docs page in notion. The code will look like `9120ec9960244ead80fa2ef4bc1bba25`. This page must have a child page named 'Outline' | -| -m, --markdown-output-path | | Root of the hierarchy for md files. WARNING: node-pull-mdx will delete files from this directory. Note also that if it finds localized images, it will create an i18n/ directory as a sibling. (default: "./docs") | -| -t, --status-tag | | Database pages without a Notion page property 'status' matching this will be ignored. Use '\*' to ignore status altogether. (default: `Publish`) | -| --locales | | Comma-separated list of iso 639-2 codes, the same list as in docusaurus.config.js, minus the primary (i.e. 'en'). This is needed for image localization. (default: []) | -| -l, --log-level | | Log level (choices: `info`, `verbose`, `debug`) | -| -i, --img-output-path | | Path to directory where images will be stored. If this is not included, images will be placed in the same directory as the document that uses them, which then allows for localization of screenshots. | -| -p, --img-prefix-in-markdown | | When referencing an image from markdown, prefix with this path instead of the full img-output-path. Should be used only in conjunction with --img-output-path. | -| -h, --help | | display help for command | +| flag | required? | description | +| ---------------------------- | --------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | +| -n, --notion-token | required | notion api token, which looks like `secret_3bc1b50XFYb15123RHF243x43450XFY33250XFYa343` | +| -r, --root-page | required | The 31 character ID of the page which is the root of your docs page in notion. The code will look like `9120ec9960244ead80fa2ef4bc1bba25`. This page must have a child page named 'Outline' | +| -m, --markdown-output-path | | Root of the hierarchy for md files. WARNING: node-pull-mdx will delete files from this directory. Note also that if it finds localized images, it will create an i18n/ directory as a sibling. (default: "./docs") | +| -t, --status-tag | | Database pages without a Notion page property 'status' matching this will be ignored. Use '\*' to ignore status altogether. (default: `Publish`) | +| --locales | | Comma-separated list of iso 639-2 codes, the same list as in docusaurus.config.js, minus the primary (i.e. 'en'). This is needed for image localization. (default: []) | +| -l, --log-level | | Log level (choices: `info`, `verbose`, `debug`) | +| -i, --img-output-path | | Path to directory where images will be stored. If this is not included, images will be placed in the same directory as the document that uses them, which then allows for localization of screenshots. | +| -p, --img-prefix-in-markdown | | When referencing an image from markdown, prefix with this path instead of the full img-output-path. Should be used only in conjunction with --img-output-path. | +| -s, --slug-prefix | | Code block mermaid diagrams can contain document links that are not processed by docusaurus. docu-notion prefixes the document slug with this value to correct this (default ""). | +| -h, --help | | display help for command | diff --git a/src/index.ts b/src/index.ts index 8ad512a..4132c7b 100644 --- a/src/index.ts +++ b/src/index.ts @@ -19,6 +19,11 @@ program "-r, --root-page ", "The 31 character ID of the page which is the root of your docs page in notion. The code will look like 9120ec9960244ead80fa2ef4bc1bba25. This page must have a child page named 'Outline'" ) + .option( + "-s, --slug-prefix ", + "Prefix to add to all slugs. This is useful if you want to host your docs on a subdomain, e.g. docs.example.com.", + "" + ) .option( "-m, --markdown-output-path ", "Root of the hierarchy for md files. WARNING: node-pull-mdx will delete files from this directory. Note also that if it finds localized images, it will create an i18n/ directory as a sibling.", diff --git a/src/linksMermaid.ts b/src/linksMermaid.ts new file mode 100644 index 0000000..9b6814f --- /dev/null +++ b/src/linksMermaid.ts @@ -0,0 +1,80 @@ +import { join } from "path"; +import { LayoutStrategy } from "./LayoutStrategy"; +import { verbose, warning } from "./log"; +import { NotionPage } from "./NotionPage"; + +export function convertMermaidInternalLinks( + markdown: string, + pages: NotionPage[], + layoutStrategy: LayoutStrategy, + slugPrefix: string +): string { + // Eg url="https://www.notion.so/Introduction-to-docu-notion-779f83504bd94642a9b87b2afc810a97" + const convertHref = (url: string) => { + // Do not convert non-notion links + if (!url.startsWith("https://www.notion.so/")) { + return url; + } + const notionId = url.split("-").pop() || ""; + + const page = pages.find(p => { + return p.matchesLinkId(notionId); + }); + if (page) { + let convertedLink = layoutStrategy.getLinkPathForPage(page); + + if (slugPrefix) { + convertedLink = + (slugPrefix.startsWith("/") ? "" : "/") + + join(slugPrefix, convertedLink); + } + + verbose(`Converting Link ${url} --> ${convertedLink}`); + return convertedLink; + } + + // About this situation. See https://github.com/sillsdev/docu-notion/issues/9 + warning( + `Could not find the target of this link. Note that links to outline sections are not supported. ${url}. https://github.com/sillsdev/docu-notion/issues/9` + ); + + return url; + }; + + return transformMermaidLinks(markdown, convertHref); +} + +function transformMermaidLinks( + pageMarkdown: string, + convertHref: (url: string) => string +) { + // The mermaid interactive click syntax: + // https://mermaid.js.org/syntax/flowchart.html#interaction + // NB this processing is just for internal link navigation + const linkRegExp = + /\s*click\s+([A-za-z][A-za-z0-9_-]*)\s+"(https:\/\/www\.notion\.so\/\S*)"/g; + let output = pageMarkdown; + let match; + + // The key to understanding this while is that linkRegExp actually has state, and + // it gives you a new one each time. https://stackoverflow.com/a/1520853/723299 + + while ((match = linkRegExp.exec(pageMarkdown)) !== null) { + const originalLink = match[0]; + + const hrefFromNotion = match[2]; + const hrefForDocusaurus = convertHref(hrefFromNotion); + + if (hrefForDocusaurus) { + output = output.replace( + match[0], + `\n click ${match[1]} "${hrefForDocusaurus}"` + ); + verbose(`transformed link: ${originalLink}-->${hrefForDocusaurus}`); + } else { + verbose(`Maybe problem with link ${JSON.stringify(match)}`); + } + } + + return output; +} diff --git a/src/pull.ts b/src/pull.ts index 9b37b35..e00226c 100644 --- a/src/pull.ts +++ b/src/pull.ts @@ -17,10 +17,12 @@ import { error, heading, info, logDebug, verbose, warning } from "./log"; import { convertInternalLinks } from "./links"; import { ListBlockChildrenResponseResult } from "notion-to-md/build/types"; import chalk from "chalk"; +import { convertMermaidInternalLinks } from "./linksMermaid"; export type Options = { notionToken: string; rootPage: string; + slugPrefix: string; locales: string[]; markdownOutputPath: string; imgOutputPath: string; @@ -263,6 +265,13 @@ async function outputPage(page: NotionPage) { // Improve: maybe this could be another markdown-to-md "custom transformer" markdown = convertInternalLinks(markdown, pages, layoutStrategy); + // Improve: maybe this could be another markdown-to-md "custom transformer" + markdown = convertMermaidInternalLinks( + markdown, + pages, + layoutStrategy, + options.slugPrefix + ); // Improve: maybe this could be another markdown-to-md "custom transformer" const { body, imports } = tweakForDocusaurus(markdown); From 097fe65f92822024e005873263a72cfbfd322f53 Mon Sep 17 00:00:00 2001 From: Dion Amago Date: Tue, 27 Dec 2022 11:32:07 -0800 Subject: [PATCH 2/2] Better cli arg name --- README.md | 2 +- src/index.ts | 4 ++-- src/pull.ts | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index c55972b..8419c1c 100644 --- a/README.md +++ b/README.md @@ -154,5 +154,5 @@ Options: | -l, --log-level | | Log level (choices: `info`, `verbose`, `debug`) | | -i, --img-output-path | | Path to directory where images will be stored. If this is not included, images will be placed in the same directory as the document that uses them, which then allows for localization of screenshots. | | -p, --img-prefix-in-markdown | | When referencing an image from markdown, prefix with this path instead of the full img-output-path. Should be used only in conjunction with --img-output-path. | -| -s, --slug-prefix | | Code block mermaid diagrams can contain document links that are not processed by docusaurus. docu-notion prefixes the document slug with this value to correct this (default ""). | +| -s, --mermaid-slug-prefix | | Code block mermaid diagrams can contain document links that are not processed by docusaurus. docu-notion prefixes the document slug with this value to correct this (default ""). | | -h, --help | | display help for command | diff --git a/src/index.ts b/src/index.ts index 4132c7b..aa24223 100644 --- a/src/index.ts +++ b/src/index.ts @@ -20,8 +20,8 @@ program "The 31 character ID of the page which is the root of your docs page in notion. The code will look like 9120ec9960244ead80fa2ef4bc1bba25. This page must have a child page named 'Outline'" ) .option( - "-s, --slug-prefix ", - "Prefix to add to all slugs. This is useful if you want to host your docs on a subdomain, e.g. docs.example.com.", + "-s, --mermaid-slug-prefix ", + "Prefix to add to document slugs for mermaid internal diagram links", "" ) .option( diff --git a/src/pull.ts b/src/pull.ts index e00226c..63aefae 100644 --- a/src/pull.ts +++ b/src/pull.ts @@ -22,7 +22,7 @@ import { convertMermaidInternalLinks } from "./linksMermaid"; export type Options = { notionToken: string; rootPage: string; - slugPrefix: string; + mermaidSlugPrefix: string; locales: string[]; markdownOutputPath: string; imgOutputPath: string; @@ -270,7 +270,7 @@ async function outputPage(page: NotionPage) { markdown, pages, layoutStrategy, - options.slugPrefix + options.mermaidSlugPrefix ); // Improve: maybe this could be another markdown-to-md "custom transformer"