From eb26c0727b97c59eb17b291d356a390bebf7f19f Mon Sep 17 00:00:00 2001 From: Andrew Polk Date: Tue, 8 Aug 2023 16:39:46 -0700 Subject: [PATCH] fix: Use video player only for embedded videos (#60) --- src/config/default.docunotion.config.ts | 11 +--- src/plugins/VideoTransformer.spec.ts | 87 +++++++++++++++++++++++++ src/plugins/VideoTransformer.ts | 19 ++++++ src/plugins/embedTweaks.spec.ts | 60 +---------------- src/plugins/embedTweaks.ts | 23 ------- src/plugins/externalLinks.spec.ts | 19 +++++- src/plugins/pluginTypes.ts | 3 + src/transform.ts | 17 ++--- 8 files changed, 137 insertions(+), 102 deletions(-) create mode 100644 src/plugins/VideoTransformer.spec.ts create mode 100644 src/plugins/VideoTransformer.ts diff --git a/src/config/default.docunotion.config.ts b/src/config/default.docunotion.config.ts index ee3dad4..6029250 100644 --- a/src/config/default.docunotion.config.ts +++ b/src/config/default.docunotion.config.ts @@ -1,9 +1,4 @@ -import { - gifEmbed, - imgurGifEmbed, - vimeoEmbed, - youtubeEmbed, -} from "../plugins/embedTweaks"; +import { gifEmbed, imgurGifEmbed } from "../plugins/embedTweaks"; import { standardImageTransformer } from "../images"; import { standardInternalLinkConversion } from "../plugins/internalLinks"; import { standardCalloutTransformer } from "../plugins/CalloutTransformer"; @@ -13,6 +8,7 @@ import { standardEscapeHtmlBlockModifier } from "../plugins/EscapeHtmlBlockModif import { standardHeadingTransformer } from "../plugins/HeadingTransformer"; import { standardNumberedListTransformer } from "../plugins/NumberedListTransformer"; import { standardTableTransformer } from "../plugins/TableTransformer"; +import { standardVideoTransformer } from "../plugins/VideoTransformer"; import { standardExternalLinkConversion } from "../plugins/externalLinks"; import { IDocuNotionConfig } from "./configuration"; @@ -30,6 +26,7 @@ const defaultConfig: IDocuNotionConfig = { standardCalloutTransformer, standardTableTransformer, standardNumberedListTransformer, + standardVideoTransformer, // Link modifiers, which are special because they can read metadata from all the pages in order to figure out the correct url standardInternalLinkConversion, @@ -38,8 +35,6 @@ const defaultConfig: IDocuNotionConfig = { // Regexps plus javascript `import`s that operate on the Markdown output imgurGifEmbed, gifEmbed, - youtubeEmbed, - vimeoEmbed, ], }; diff --git a/src/plugins/VideoTransformer.spec.ts b/src/plugins/VideoTransformer.spec.ts new file mode 100644 index 0000000..4433af8 --- /dev/null +++ b/src/plugins/VideoTransformer.spec.ts @@ -0,0 +1,87 @@ +import { setLogLevel } from "../log"; +import { NotionBlock } from "../types"; +import { standardVideoTransformer } from "./VideoTransformer"; +import { blocksToMarkdown } from "./pluginTestRun"; + +test("youtube embedded", async () => { + const config = { plugins: [standardVideoTransformer] }; + const result = await blocksToMarkdown(config, [ + { + object: "block", + type: "video", + video: { + caption: [ + { + type: "text", + text: { + content: "A video about editing in Notion", + link: null, + }, + plain_text: "A video about editing in Notion", + href: null, + }, + ], + type: "external", + external: { url: "https://www.youtube.com/watch?v=FXIrojSK3Jo" }, + }, + } as unknown as NotionBlock, + ]); + expect(result).toContain(`import ReactPlayer from "react-player";`); + expect(result).toContain( + `` + ); +}); + +test("vimeo embedded", async () => { + setLogLevel("verbose"); + const config = { plugins: [standardVideoTransformer] }; + const result = await blocksToMarkdown(config, [ + { + object: "block", + type: "video", + video: { + caption: [], + type: "external", + external: { url: "https://vimeo.com/4613611xx" }, + }, + } as unknown as NotionBlock, + ]); + expect(result).toContain(`import ReactPlayer from "react-player";`); + expect(result).toContain( + `` + ); +}); + +test("video link, not embedded", async () => { + setLogLevel("verbose"); + const config = { plugins: [standardVideoTransformer] }; + const result = await blocksToMarkdown(config, [ + { + object: "block", + type: "paragraph", + paragraph: { + rich_text: [ + { + type: "text", + text: { + content: "https://vimeo.com/4613611xx", + link: { + url: "https://vimeo.com/4613611xx", + }, + }, + annotations: { + code: false, + }, + plain_text: "https://vimeo.com/4613611xx", + href: "https://vimeo.com/4613611xx", + }, + ], + color: "default", + }, + } as unknown as NotionBlock, + ]); + expect(result).toContain( + "[https://vimeo.com/4613611xx](https://vimeo.com/4613611xx)" + ); + expect(result).not.toContain(`import`); +}); diff --git a/src/plugins/VideoTransformer.ts b/src/plugins/VideoTransformer.ts new file mode 100644 index 0000000..c72841a --- /dev/null +++ b/src/plugins/VideoTransformer.ts @@ -0,0 +1,19 @@ +import { IPlugin } from "./pluginTypes"; + +export const standardVideoTransformer: IPlugin = { + name: "video", + notionToMarkdownTransforms: [ + { + type: "video", + getStringFromBlock: async (context, block) => { + const blockAsAny = block as any; + if (blockAsAny?.video?.external?.url) { + context.imports = [`import ReactPlayer from "react-player";`]; + return ``; + } else return await context.notionToMarkdown.blockToMarkdown(block); + }, + }, + ], +}; diff --git a/src/plugins/embedTweaks.spec.ts b/src/plugins/embedTweaks.spec.ts index 2491f21..1084a0c 100644 --- a/src/plugins/embedTweaks.spec.ts +++ b/src/plugins/embedTweaks.spec.ts @@ -2,65 +2,7 @@ import { NotionBlock } from "../types"; import { IPlugin } from "./pluginTypes"; import { setLogLevel } from "../log"; import { blocksToMarkdown } from "./pluginTestRun"; -import { - gifEmbed, - imgurGifEmbed, - vimeoEmbed, - youtubeEmbed, -} from "./embedTweaks"; - -test("youtube", async () => { - const config = { plugins: [youtubeEmbed] }; - const result = await blocksToMarkdown(config, [ - { - object: "block", - id: "e6ddd1d4-36d4-4925-94c1-5dff4662c1f3", - has_children: false, - archived: false, - type: "video", - video: { - caption: [ - { - type: "text", - text: { - content: "A video about editing in Notion", - link: null, - }, - plain_text: "A video about editing in Notion", - href: null, - }, - ], - type: "external", - external: { url: "https://www.youtube.com/watch?v=FXIrojSK3Jo" }, - }, - } as unknown as NotionBlock, - ]); - expect(result).toContain(`import ReactPlayer from "react-player";`); - expect(result).toContain( - `` - ); -}); - -test("vimeo", async () => { - setLogLevel("verbose"); - const config = { plugins: [vimeoEmbed] }; - const result = await blocksToMarkdown(config, [ - { - object: "block", - id: "39ff83a3-2fb5-4411-a715-960656a177ff", - type: "video", - video: { - caption: [], - type: "external", - external: { url: "https://vimeo.com/4613611xx" }, - }, - } as unknown as NotionBlock, - ]); - expect(result).toContain(`import ReactPlayer from "react-player";`); - expect(result).toContain( - `` - ); -}); +import { gifEmbed, imgurGifEmbed } from "./embedTweaks"; test("imgur", async () => { setLogLevel("verbose"); diff --git a/src/plugins/embedTweaks.ts b/src/plugins/embedTweaks.ts index 4111cdb..455abde 100644 --- a/src/plugins/embedTweaks.ts +++ b/src/plugins/embedTweaks.ts @@ -22,26 +22,3 @@ export const imgurGifEmbed: IPlugin = { }, ], }; -export const youtubeEmbed: IPlugin = { - name: "youtube", - regexMarkdownModifications: [ - { - regex: /\[.*\]\((.*youtube\.com\/watch.*)\)/, //youtube.com/watch - imports: [`import ReactPlayer from "react-player";`], - replacementPattern: ``, - }, - ], -}; -export const vimeoEmbed: IPlugin = { - name: "vimeo", - regexMarkdownModifications: [ - { - regex: /\[.*\]\((https:\/\/.*vimeo.*)\)/, - // we use to have the following, but the above should handle both the player an not-player urls. - //regex: /\[.*\]\((.*player\.vimeo.*)\)/gm, // player.vimeo - - imports: [`import ReactPlayer from "react-player";`], - replacementPattern: ``, - }, - ], -}; diff --git a/src/plugins/externalLinks.spec.ts b/src/plugins/externalLinks.spec.ts index 578d8f6..9ba7298 100644 --- a/src/plugins/externalLinks.spec.ts +++ b/src/plugins/externalLinks.spec.ts @@ -1,5 +1,4 @@ -import { setLogLevel, verbose } from "../log"; -import { NotionPage } from "../NotionPage"; +import { setLogLevel } from "../log"; import { oneBlockToMarkdown } from "./pluginTestRun"; import { standardExternalLinkConversion } from "./externalLinks"; @@ -15,6 +14,22 @@ test("links turned into bookmarks", async () => { expect(results.trim()).toBe("[https://github.com](https://github.com)"); }); +test("video links turned into bookmarks", async () => { + setLogLevel("debug"); + const results = await getMarkdown({ + object: "block", + type: "bookmark", + bookmark: { + caption: [], + url: "https://vimeo.com/4613611xx", + }, + }); + expect(results).toContain( + "[https://vimeo.com/4613611xx](https://vimeo.com/4613611xx)" + ); + expect(results).not.toContain(`import`); +}); + test("external link inside callout", async () => { const results = await getMarkdown({ type: "callout", diff --git a/src/plugins/pluginTypes.ts b/src/plugins/pluginTypes.ts index 7c3eb5c..78b22a7 100644 --- a/src/plugins/pluginTypes.ts +++ b/src/plugins/pluginTypes.ts @@ -74,4 +74,7 @@ export type IDocuNotionContext = { convertNotionLinkToLocalDocusaurusLink: (url: string) => string | undefined; pages: NotionPage[]; counts: ICounts; + + // If the output is creating things like react elements, you can import their definitions here + imports?: string[]; }; diff --git a/src/transform.ts b/src/transform.ts index 94cb21a..652cea6 100644 --- a/src/transform.ts +++ b/src/transform.ts @@ -56,16 +56,13 @@ export async function getMarkdownFromNotionBlocks( //console.log("markdown after link fixes", markdown); // simple regex-based tweaks. These are usually related to docusaurus - const { imports, body } = await doTransformsOnMarkdown( - context, - config, - markdown - ); + const body = await doTransformsOnMarkdown(context, config, markdown); // console.log("markdown after regex fixes", markdown); // console.log("body after regex", body); - return `${imports}\n${body}`; + const uniqueImports = [...new Set(context.imports)]; + return `${[...uniqueImports].join("\n")}\n${body}`; } // operations on notion blocks before they are converted to markdown @@ -106,7 +103,6 @@ async function doTransformsOnMarkdown( let body = input; //console.log("body before regex: " + body); let match; - const imports = new Set(); // eslint-disable-next-line @typescript-eslint/no-unused-vars for (const mod of regexMods) { @@ -143,15 +139,16 @@ async function doTransformsOnMarkdown( body = precedingPart + partStartingFromThisMatch.replace(original, replacement); + // add any library imports - mod.imports?.forEach(imp => imports.add(imp)); + if (!context.imports) context.imports = []; + mod.imports?.forEach(imp => context.imports!.push(imp)); } } } } logDebug("doTransformsOnMarkdown", "body after regex: " + body); - const uniqueImports = [...new Set(imports)]; - return { body, imports: [...uniqueImports].join("\n") }; + return body; } async function doNotionToMarkdown(