Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Internal mermaid clickable links #33

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
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
49 changes: 38 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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 <path>
```

where `<path>` 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 <token> -r <root> [options]

Options:

| flag | required? | description |
| ------------------------------------- | --------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| -n, --notion-token <string> | required | notion api token, which looks like `secret_3bc1b50XFYb15123RHF243x43450XFY33250XFYa343` |
| -r, --root-page <string> | 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 <string> | | 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 <string> | | Database pages without a Notion page property 'status' matching this will be ignored. Use '\*' to ignore status altogether. (default: `Publish`) |
| --locales <codes> | | 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 <level> | | Log level (choices: `info`, `verbose`, `debug`) |
| -i, --img-output-path <string> | | 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 <string> | | 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, --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 |
5 changes: 5 additions & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,11 @@ program
"-r, --root-page <string>",
"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, --mermaid-slug-prefix <string>",
"Prefix to add to document slugs for mermaid internal diagram links",
""
)
.option(
"-m, --markdown-output-path <string>",
"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.",
Expand Down
80 changes: 80 additions & 0 deletions src/linksMermaid.ts
Original file line number Diff line number Diff line change
@@ -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;
}
9 changes: 9 additions & 0 deletions src/pull.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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;
mermaidSlugPrefix: string;
locales: string[];
markdownOutputPath: string;
imgOutputPath: string;
Expand Down Expand Up @@ -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.mermaidSlugPrefix
);

// Improve: maybe this could be another markdown-to-md "custom transformer"
const { body, imports } = tweakForDocusaurus(markdown);
Expand Down