|
1 | | -const notionCalloutPattern = />\s(ℹ️|⚠️|💡|❗|🔥)\s(.*)\n/gmu; |
2 | | -const calloutsToAdmonitions = { |
3 | | - /* prettier-ignore */ "ℹ️": "note", |
4 | | - "💡": "tip", |
5 | | - "❗": "info", |
6 | | - "⚠️": "caution", |
7 | | - "🔥": "danger", |
8 | | -}; |
9 | | - |
10 | | -export function tweakForDocusaurus(input: string): string { |
| 1 | +import chalk from "chalk"; |
| 2 | + |
| 3 | +export function tweakForDocusaurus(input: string): { |
| 4 | + body: string; |
| 5 | + imports: string; |
| 6 | +} { |
| 7 | + const output = notionCalloutsToAdmonitions(input); |
| 8 | + const { body, imports } = notionEmbedsToMDX(output); |
| 9 | + return { body, imports }; |
| 10 | +} |
| 11 | +// In Notion, you can embed videos & such. To show these |
| 12 | +// in Docusaurus, we have to |
| 13 | +// * switch to .MDX instead of just .MD |
| 14 | +// * import the required react libraries |
| 15 | +// * insert some JSX for each embed |
| 16 | +function notionEmbedsToMDX(input: string): { |
| 17 | + body: string; |
| 18 | + imports: string; |
| 19 | +} { |
| 20 | + /* Note: the notion api tells us that the embedded type is video, but this information is lost by the time |
| 21 | + we got through notion-to-md: |
| 22 | + { |
| 23 | + ... |
| 24 | + "type": "video", |
| 25 | + "video": { |
| 26 | + "caption": [], |
| 27 | + "type": "external", |
| 28 | + "external": { |
| 29 | + "url": "https://www.youtube.com/watch?v=FXIrojSK3Jo" |
| 30 | + } |
| 31 | + } |
| 32 | + }, |
| 33 | +
|
| 34 | + For now, we're just using this regex to notice youtube and vimeo. |
| 35 | + */ |
| 36 | + |
| 37 | + // NOTE: currently notion-to-md seems to be dropping the "Caption" entirely. |
| 38 | + |
| 39 | + const video = { |
| 40 | + import: `import ReactPlayer from "react-player";`, |
| 41 | + output: `<ReactPlayer controls url="$1" />`, |
| 42 | + }; |
| 43 | + const gif = { |
| 44 | + import: `import GifPlayer from "react-gif-player";`, |
| 45 | + output: `<GifPlayer gif="$1" />`, |
| 46 | + }; |
| 47 | + const embeds = { |
| 48 | + youtube: { |
| 49 | + regex: /\[.*\]\((.*youtube\.com\/watch.*)\)/gm, //youtube.com/watch |
| 50 | + ...video, |
| 51 | + }, |
| 52 | + vimeo: { |
| 53 | + regex: /\[.*\]\((.*player\.vimeo.*)\)/gm, // player.vimeo |
| 54 | + ...video, |
| 55 | + }, |
| 56 | + imgur: { |
| 57 | + regex: /\[embed\]\((.*imgur\.com\/.*)\)/gm, // imgur.com |
| 58 | + ...gif, |
| 59 | + }, |
| 60 | + gifExtension: { |
| 61 | + // ending in .gif. I once saw a gif coming form Notion that wasn't a full |
| 62 | + // url, which wouldn't work, hence the "http" requirement |
| 63 | + regex: /\[.*\]\((http.*(\.(gif|GIF)))\)/gm, |
| 64 | + ...gif, |
| 65 | + }, |
| 66 | + }; |
| 67 | + |
| 68 | + let body = input; |
| 69 | + let match; |
| 70 | + const imports = new Set<string>(); |
| 71 | + |
| 72 | + // eslint-disable-next-line @typescript-eslint/no-unused-vars |
| 73 | + for (const [k, v] of Object.entries(embeds)) { |
| 74 | + while ((match = v.regex.exec(input)) !== null) { |
| 75 | + const string = match[0]; |
| 76 | + const url = match[1]; |
| 77 | + console.log(chalk.green(`${string} --> ${v.output.replace("$1", url)}`)); |
| 78 | + body = body.replace(string, v.output.replace("$1", url)); |
| 79 | + imports.add(v.import); |
| 80 | + } |
| 81 | + } |
| 82 | + |
| 83 | + return { body, imports: [...imports].join("\n") }; |
| 84 | +} |
| 85 | + |
| 86 | +// In Notion, you can make a callout and change its emoji. We map 5 of these |
| 87 | +// to the 5 Docusaurus admonition styles. |
| 88 | +function notionCalloutsToAdmonitions(input: string): string { |
| 89 | + const notionCalloutPattern = />\s(ℹ️|⚠️|💡|❗|🔥)\s(.*)\n/gmu; |
| 90 | + const calloutsToAdmonitions = { |
| 91 | + /* prettier-ignore */ "ℹ️": "note", |
| 92 | + "💡": "tip", |
| 93 | + "❗": "info", |
| 94 | + "⚠️": "caution", |
| 95 | + "🔥": "danger", |
| 96 | + }; |
11 | 97 | let output = input; |
12 | 98 | let match; |
13 | 99 | while ((match = notionCalloutPattern.exec(input)) !== null) { |
|
0 commit comments