@sillsdev/docu-notion 0.13.4 → 0.14.0-alpha.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -10,6 +10,8 @@ Example Site: https://sillsdev.github.io/docu-notion-sample-site/
10
10
 
11
11
  First, prepare your markdown-based static file system like [Docusaurus](https://docusaurus.io/). For a shortcut with github actions, search, and deployment to github pages, you can just copy [this template](https://github.com/sillsdev/docu-notion-sample-site).
12
12
 
13
+ If you do not use the above sample, you will need to manually add [notion-styles.css](src/css/notion-styles.css) to your site. This enables multi-column layouts and another other special styling that we need to make the output of docu-notion look right.
14
+
13
15
  ## 2. In Notion, duplicate the docu-notion template
14
16
 
15
17
  Go to [this template page](https://hattonjohn.notion.site/Documentation-Template-Docusaurus-0e998b32da3c47edad0f62a25b49818c). Duplicate it into your own workspace.
@@ -17,13 +19,13 @@ You can name it anything you like, e.g. "Documentation Root".
17
19
 
18
20
  ## 3. Create a Notion Integration
19
21
 
20
- In order for docu-notion to read your site via Notion's API, you need to create what Notion calls an "integration". Follow [these instructions](https://developers.notion.com/docs/getting-started) to make an integration and get your token. Limit your integration to "READ" access.
22
+ In order for docu-notion to read your site via Notion's API, you need to create what Notion calls an "integration". Follow [these instructions](https://developers.notion.com/docs/getting-started) to make an integration and get your token. Remember to limit your integration to "READ" access.
21
23
 
22
- ## 4. "Invite" your Notion Integration to read you page
24
+ ## 4. Connect your Integration
23
25
 
24
- In Notion, click "Share" on the root of your documentation and "invite" your integration to it.
26
+ Go to the page that will be the root of your site. This page should have, as direct children, your "Outline" (required) and "Database" (optional) pages. Follow [these instructions](https://developers.notion.com/docs/create-a-notion-integration#give-your-integration-page-permissions).
25
27
 
26
- ![image](https://user-images.githubusercontent.com/8448/168930238-1dcf46df-a690-4839-bf4c-c63157f104d8.png)
28
+ <img width="318" alt="image" src="https://github.com/sillsdev/docu-notion/assets/8448/810c6dca-f9ab-4370-93b4-dc1479332af7">
27
29
 
28
30
  ## 5. Add your pages under your Outline page.
29
31
 
@@ -35,7 +37,7 @@ First, determine the id of your root page by clicking "Share" and looking at the
35
37
  https://www.notion.so/hattonjohn/My-Docs-0456aa5842946bdbea3a4f37c97a0e5
36
38
  means that the id is "0456aa5842946PRETEND4f37c97a0e5".
37
39
 
38
- Determine where you want the markdown files and images to land. The following works well for Docusaurus instances:
40
+ Try it out:
39
41
 
40
42
  ```
41
43
  npx @sillsdev/docu-notion -n secret_PRETEND123456789PRETEND123456789PRETEND6789 -r 0456aa5842946PRETEND4f37c97a0e5"
@@ -8,8 +8,8 @@ const ColumnListTransformer_1 = require("../plugins/ColumnListTransformer");
8
8
  const ColumnTransformer_1 = require("../plugins/ColumnTransformer");
9
9
  const EscapeHtmlBlockModifier_1 = require("../plugins/EscapeHtmlBlockModifier");
10
10
  const HeadingTransformer_1 = require("../plugins/HeadingTransformer");
11
- const NumberedListTransformer_1 = require("../plugins/NumberedListTransformer");
12
11
  const TableTransformer_1 = require("../plugins/TableTransformer");
12
+ const VideoTransformer_1 = require("../plugins/VideoTransformer");
13
13
  const externalLinks_1 = require("../plugins/externalLinks");
14
14
  const defaultConfig = {
15
15
  plugins: [
@@ -23,15 +23,13 @@ const defaultConfig = {
23
23
  images_1.standardImageTransformer,
24
24
  CalloutTransformer_1.standardCalloutTransformer,
25
25
  TableTransformer_1.standardTableTransformer,
26
- NumberedListTransformer_1.standardNumberedListTransformer,
26
+ VideoTransformer_1.standardVideoTransformer,
27
27
  // Link modifiers, which are special because they can read metadata from all the pages in order to figure out the correct url
28
28
  internalLinks_1.standardInternalLinkConversion,
29
29
  externalLinks_1.standardExternalLinkConversion,
30
30
  // Regexps plus javascript `import`s that operate on the Markdown output
31
31
  embedTweaks_1.imgurGifEmbed,
32
32
  embedTweaks_1.gifEmbed,
33
- embedTweaks_1.youtubeEmbed,
34
- embedTweaks_1.vimeoEmbed,
35
33
  ],
36
34
  };
37
35
  exports.default = defaultConfig;
@@ -1,58 +1,60 @@
1
- /* Note, I haven't figure out how a Docusaurus app can actually include this, yet.
2
- So currently this has to be duplicated by the client.
3
- */
4
-
5
- /* Copied from
6
- https://github1s.com/NotionX/react-notion-x/blob/master/packages/react-notion-x/src/styles.css#L934
7
- and
8
- https://github1s.com/NotionX/react-notion-x/blob/master/packages/react-notion-x/src/styles.css#L1063
9
- */
10
- .notion-column {
11
- display: flex;
12
- flex-direction: column;
13
- padding-top: 12px;
14
- padding-bottom: 12px;
15
- }
16
-
17
- .notion-column > *:first-child {
18
- margin-top: 0;
19
- margin-left: 0;
20
- margin-right: 0;
21
- }
22
-
23
- .notion-column > *:last-child {
24
- margin-left: 0;
25
- margin-right: 0;
26
- margin-bottom: 0;
27
- }
28
-
29
- .notion-row {
30
- display: flex;
31
- overflow: hidden;
32
- width: 100%;
33
- max-width: 100%;
34
- }
35
-
36
- @media (max-width: 640px) {
37
- .notion-row {
38
- flex-direction: column;
39
- }
40
-
41
- .notion-row .notion-column {
42
- width: 100% !important;
43
- }
44
-
45
- .notion-row .notion-spacer {
46
- display: none;
47
- }
48
- }
49
-
50
- .notion-spacer {
51
- /* This matches the value in ColumnTransformer.ts */
52
- width: calc(min(32px, 4vw));
53
- }
54
-
55
- .notion-spacer:last-child {
56
- display: none;
57
- }
58
- /* End copied from NotionX */
1
+ /* This should be added to the docusaurus.config.js in order to show some notion things correctly.
2
+ See the option: --css-output-directory
3
+ See the docusaurus docs: https://docusaurus.io/docs/styling-layout
4
+ See the use in the docu-notion-sample-site: https://github.com/sillsdev/docu-notion-sample-site/blob/main/docusaurus.config.js
5
+ */
6
+
7
+ /* Copied from
8
+ https://github1s.com/NotionX/react-notion-x/blob/master/packages/react-notion-x/src/styles.css#L934
9
+ and
10
+ https://github1s.com/NotionX/react-notion-x/blob/master/packages/react-notion-x/src/styles.css#L1063
11
+ */
12
+ .notion-column {
13
+ display: flex;
14
+ flex-direction: column;
15
+ padding-top: 12px;
16
+ padding-bottom: 12px;
17
+ }
18
+
19
+ .notion-column > *:first-child {
20
+ margin-top: 0;
21
+ margin-left: 0;
22
+ margin-right: 0;
23
+ }
24
+
25
+ .notion-column > *:last-child {
26
+ margin-left: 0;
27
+ margin-right: 0;
28
+ margin-bottom: 0;
29
+ }
30
+
31
+ .notion-row {
32
+ display: flex;
33
+ overflow: hidden;
34
+ width: 100%;
35
+ max-width: 100%;
36
+ }
37
+
38
+ @media (max-width: 640px) {
39
+ .notion-row {
40
+ flex-direction: column;
41
+ }
42
+
43
+ .notion-row .notion-column {
44
+ width: 100% !important;
45
+ }
46
+
47
+ .notion-row .notion-spacer {
48
+ display: none;
49
+ }
50
+ }
51
+
52
+ .notion-spacer {
53
+ /* This matches the value in ColumnTransformer.ts */
54
+ width: calc(min(32px, 4vw));
55
+ }
56
+
57
+ .notion-spacer:last-child {
58
+ display: none;
59
+ }
60
+ /* End copied from NotionX */
@@ -0,0 +1,97 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ var __importDefault = (this && this.__importDefault) || function (mod) {
12
+ return (mod && mod.__esModule) ? mod : { "default": mod };
13
+ };
14
+ Object.defineProperty(exports, "__esModule", { value: true });
15
+ const notion_to_md_1 = require("notion-to-md");
16
+ const HierarchicalNamedLayoutStrategy_1 = require("./HierarchicalNamedLayoutStrategy");
17
+ const transform_1 = require("./transform");
18
+ const internalLinks_1 = require("./plugins/internalLinks");
19
+ const pull_1 = require("./pull");
20
+ const default_docunotion_config_1 = __importDefault(require("./config/default.docunotion.config"));
21
+ test("Latex Rendering", () => __awaiter(void 0, void 0, void 0, function* () {
22
+ const pages = new Array();
23
+ const counts = {
24
+ output_normally: 0,
25
+ skipped_because_empty: 0,
26
+ skipped_because_status: 0,
27
+ skipped_because_level_cannot_have_content: 0,
28
+ };
29
+ const notionClient = (0, pull_1.initNotionClient)("");
30
+ const layoutStrategy = new HierarchicalNamedLayoutStrategy_1.HierarchicalNamedLayoutStrategy();
31
+ const config = default_docunotion_config_1.default;
32
+ const context = {
33
+ getBlockChildren: (id) => {
34
+ return new Promise(resolve => resolve(new Array()));
35
+ },
36
+ directoryContainingMarkdown: "",
37
+ relativeFilePathToFolderContainingPage: "",
38
+ layoutStrategy: layoutStrategy,
39
+ notionToMarkdown: new notion_to_md_1.NotionToMarkdown({ notionClient }),
40
+ options: {
41
+ notionToken: "",
42
+ rootPage: "",
43
+ locales: [""],
44
+ markdownOutputPath: "",
45
+ imgOutputPath: "",
46
+ imgPrefixInMarkdown: "",
47
+ statusTag: "",
48
+ },
49
+ pages: pages,
50
+ counts: counts,
51
+ imports: [],
52
+ convertNotionLinkToLocalDocusaurusLink: (url) => (0, internalLinks_1.convertInternalUrl)(context, url),
53
+ };
54
+ const blocks = [
55
+ {
56
+ object: "block",
57
+ id: "169e1c47-6706-4518-adca-73086b2738ac",
58
+ parent: {
59
+ type: "page_id",
60
+ page_id: "2acc11a4-82a9-4759-b429-fa011c164888",
61
+ },
62
+ created_time: "2023-08-18T15:51:00.000Z",
63
+ last_edited_time: "2023-08-18T15:51:00.000Z",
64
+ created_by: {
65
+ object: "user",
66
+ id: "af5c163e-82b1-49d1-9f1c-539907bb9fb9",
67
+ },
68
+ last_edited_by: {
69
+ object: "user",
70
+ id: "af5c163e-82b1-49d1-9f1c-539907bb9fb9",
71
+ },
72
+ has_children: false,
73
+ archived: false,
74
+ type: "paragraph",
75
+ paragraph: {
76
+ rich_text: [
77
+ {
78
+ type: "equation",
79
+ equation: { expression: "x" },
80
+ annotations: {
81
+ bold: false,
82
+ italic: false,
83
+ strikethrough: false,
84
+ underline: false,
85
+ code: false,
86
+ color: "default",
87
+ },
88
+ plain_text: "x",
89
+ href: null,
90
+ },
91
+ ],
92
+ color: "default",
93
+ },
94
+ },
95
+ ];
96
+ expect(yield (0, transform_1.getMarkdownFromNotionBlocks)(context, config, blocks)).toContain("$x$");
97
+ }));
@@ -28,16 +28,14 @@ function notionColumnToMarkdown(notionToMarkdown, getBlockChildren, block) {
28
28
  const { id, has_children } = block; // "any" because the notion api type system is complex with a union that don't know how to help TS to cope with
29
29
  if (!has_children)
30
30
  return "";
31
- const children = yield getBlockChildren(id);
32
- const childrenPromises = children.map((column) => __awaiter(this, void 0, void 0, function* () { return yield notionToMarkdown.blockToMarkdown(column); }));
33
- const childrenStrings = yield Promise.all(childrenPromises);
31
+ const columnChildren = yield getBlockChildren(id);
32
+ const childrenMdBlocksArray = yield Promise.all(columnChildren.map((child) => __awaiter(this, void 0, void 0, function* () { return yield notionToMarkdown.blocksToMarkdown([child]); })));
33
+ const childrenMarkdown = childrenMdBlocksArray.map(mdBlockArray => notionToMarkdown.toMarkdownString(mdBlockArray).parent);
34
34
  const columnWidth = yield getColumnWidth(block);
35
- // note: it would look better in the markup with \n, but that
36
- // causes notion-to-md to give us ":::A" instead of \n for some reason.
37
- return (`<div class='notion-column' style={{width: '${columnWidth}'}}>\n\n${childrenStrings.join("\n\n")}\n\n</div>` +
35
+ return (`<div class='notion-column' style={{width: '${columnWidth}'}}>\n\n${childrenMarkdown.join("\n")}\n</div>` +
38
36
  // Spacer between columns. CSS takes care of hiding this for the last column
39
37
  // and when the screen is too narrow for multiple columns.
40
- `<div className='notion-spacer' />`);
38
+ `<div className='notion-spacer'></div>`);
41
39
  });
42
40
  }
43
41
  // The official API doesn't give us access to the format information, including column_ratio.
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,118 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ const pluginTestRun_1 = require("./pluginTestRun");
13
+ const ColumnTransformer_1 = require("./ColumnTransformer");
14
+ // Even though we can set up most tests with our own children
15
+ // so that we aren't relying on real data from Notion,
16
+ // we can't prevent the notion-to-md library from making an API call
17
+ // every time it processes a block with has_children:true.
18
+ // So for these tests with children, we need any valid API key.
19
+ const runTestsWhichRequireAnyValidApiKey = !!process.env.DOCU_NOTION_INTEGRATION_TOKEN;
20
+ // To test grandchildren, we can't get around notion-to-md making an API call
21
+ // to get real children. So we need a specific notion record.
22
+ // For that reason, we don't try to run these tests unless the user changes this flag.
23
+ // But it is an important test; grandchildren in columns were broken.
24
+ // See https://github.com/sillsdev/docu-notion/issues/70.
25
+ const runManualTestsWhichRequireSpecificNotionRecords = false;
26
+ const columnBlock = {
27
+ object: "block",
28
+ id: "e6d2d7b7-b1ed-464a-86d2-bb5f6be78a03",
29
+ has_children: true,
30
+ type: "column",
31
+ column: {},
32
+ };
33
+ function getResults(children) {
34
+ return __awaiter(this, void 0, void 0, function* () {
35
+ return yield (0, pluginTestRun_1.blocksToMarkdown)({ plugins: [ColumnTransformer_1.standardColumnTransformer] }, [columnBlock], undefined, children, process.env.DOCU_NOTION_INTEGRATION_TOKEN);
36
+ });
37
+ }
38
+ const columnWrapperStart = "<div class='notion-column' style=\\{\\{width: '.*?'\\}\\}>\\n\\n";
39
+ const columnWrapperEnd = "\\n\\n<\\/div><div className='notion-spacer'><\\/div>";
40
+ if (runTestsWhichRequireAnyValidApiKey) {
41
+ columnBlock.has_children = true;
42
+ test("requires API key - column with paragraph", () => __awaiter(void 0, void 0, void 0, function* () {
43
+ const results = yield getResults([getTestParagraphBlock()]);
44
+ expect(results).toMatch(new RegExp(`${columnWrapperStart}\\s*?my paragraph\\s*?${columnWrapperEnd}`));
45
+ }), 20000);
46
+ test("requires API key - column with two paragraphs", () => __awaiter(void 0, void 0, void 0, function* () {
47
+ const results = yield getResults([
48
+ getTestParagraphBlock(1),
49
+ getTestParagraphBlock(2),
50
+ ]);
51
+ expect(results).toMatch(new RegExp(`${columnWrapperStart}\\s*?my paragraph 1\\s+?my paragraph 2\\s*?${columnWrapperEnd}`));
52
+ }), 20000);
53
+ test("requires API key - column with numbered list", () => __awaiter(void 0, void 0, void 0, function* () {
54
+ const results = yield getResults([
55
+ getNumberedListItemBlock(1),
56
+ getNumberedListItemBlock(2),
57
+ ]);
58
+ expect(results).toMatch(new RegExp(`${columnWrapperStart}\\s*?1\\. Numbered list item 1\\s+?2\\. Numbered list item 2\\s*?${columnWrapperEnd}`, "s"));
59
+ }), 20000);
60
+ if (runManualTestsWhichRequireSpecificNotionRecords) {
61
+ test("manual test - requires specific notion record and API key - column with numbered list with sublist", () => __awaiter(void 0, void 0, void 0, function* () {
62
+ const realNumberedListBlock = getNumberedListItemBlock(1);
63
+ realNumberedListBlock.id = "ca08d14b-9b70-4f6f-9d17-9fd74b57afeb";
64
+ realNumberedListBlock.has_children = true;
65
+ const results = yield getResults([realNumberedListBlock]);
66
+ expect(results).toMatch(new RegExp(`${columnWrapperStart}\\s*?1\\. Numbered list item 1\\s+?- unordered sub-bullet\\s*?${columnWrapperEnd}`, "s"));
67
+ }), 20000);
68
+ }
69
+ }
70
+ else {
71
+ // This test prevents an error when runTestsWhichRequireAnyValidApiKey is false
72
+ // due to having a test suite with no tests.
73
+ test("no column transformer tests were run because there is no API key provided", () => {
74
+ expect(true).toBe(true);
75
+ });
76
+ }
77
+ function getNumberedListItemBlock(identifier) {
78
+ const content = identifier
79
+ ? `Numbered list item ${identifier}`
80
+ : `Numbered list item`;
81
+ return {
82
+ object: "block",
83
+ type: "numbered_list_item",
84
+ numbered_list_item: {
85
+ rich_text: [
86
+ {
87
+ type: "text",
88
+ text: { content: content },
89
+ annotations: {
90
+ code: false,
91
+ },
92
+ plain_text: content,
93
+ },
94
+ ],
95
+ },
96
+ };
97
+ }
98
+ function getTestParagraphBlock(identifier) {
99
+ const content = identifier ? `my paragraph ${identifier}` : `my paragraph`;
100
+ return {
101
+ object: "block",
102
+ type: "paragraph",
103
+ paragraph: {
104
+ rich_text: [
105
+ {
106
+ type: "text",
107
+ text: {
108
+ content: content,
109
+ },
110
+ annotations: {
111
+ code: false,
112
+ },
113
+ plain_text: content,
114
+ },
115
+ ],
116
+ },
117
+ };
118
+ }
@@ -0,0 +1,2 @@
1
+ import { IPlugin } from "./pluginTypes";
2
+ export declare const standardVideoTransformer: IPlugin;
@@ -0,0 +1,33 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.standardVideoTransformer = void 0;
4
+ const log_1 = require("../log");
5
+ exports.standardVideoTransformer = {
6
+ name: "video",
7
+ notionToMarkdownTransforms: [
8
+ {
9
+ type: "video",
10
+ getStringFromBlock: (context, block) => {
11
+ const video = block.video;
12
+ let url = "";
13
+ switch (video.type) {
14
+ case "external":
15
+ url = video.external.url;
16
+ break;
17
+ case "file":
18
+ url = video.file.url;
19
+ break;
20
+ default:
21
+ // video.type can only be "external" or "file" as of the writing of this code, so typescript
22
+ // isn't happy trying to turn video.type into a string. But this default in our switch is
23
+ // just attempting some future-proofing. Thus the strange typing/stringifying below.
24
+ (0, log_1.warning)(`[standardVideoTransformer] Found Notion "video" block with type ${JSON.stringify(video.type)}. The best docu-notion can do for now is ignore it.`);
25
+ return "";
26
+ break;
27
+ }
28
+ context.imports.push(`import ReactPlayer from "react-player";`);
29
+ return `<ReactPlayer controls url="${url}" />`;
30
+ },
31
+ },
32
+ ],
33
+ };
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,112 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ const log_1 = require("../log");
13
+ const VideoTransformer_1 = require("./VideoTransformer");
14
+ const pluginTestRun_1 = require("./pluginTestRun");
15
+ test("youtube embedded", () => __awaiter(void 0, void 0, void 0, function* () {
16
+ const config = { plugins: [VideoTransformer_1.standardVideoTransformer] };
17
+ const result = yield (0, pluginTestRun_1.blocksToMarkdown)(config, [
18
+ {
19
+ object: "block",
20
+ type: "video",
21
+ video: {
22
+ caption: [
23
+ {
24
+ type: "text",
25
+ text: {
26
+ content: "A video about editing in Notion",
27
+ link: null,
28
+ },
29
+ plain_text: "A video about editing in Notion",
30
+ href: null,
31
+ },
32
+ ],
33
+ type: "external",
34
+ external: { url: "https://www.youtube.com/watch?v=FXIrojSK3Jo" },
35
+ },
36
+ },
37
+ ]);
38
+ expect(result).toContain(`import ReactPlayer from "react-player";`);
39
+ expect(result).toContain(`<ReactPlayer controls url="https://www.youtube.com/watch?v=FXIrojSK3Jo" />`);
40
+ }));
41
+ test("vimeo embedded", () => __awaiter(void 0, void 0, void 0, function* () {
42
+ (0, log_1.setLogLevel)("verbose");
43
+ const config = { plugins: [VideoTransformer_1.standardVideoTransformer] };
44
+ const result = yield (0, pluginTestRun_1.blocksToMarkdown)(config, [
45
+ {
46
+ object: "block",
47
+ type: "video",
48
+ video: {
49
+ caption: [],
50
+ type: "external",
51
+ external: { url: "https://vimeo.com/4613611xx" },
52
+ },
53
+ },
54
+ ]);
55
+ expect(result).toContain(`import ReactPlayer from "react-player";`);
56
+ expect(result).toContain(`<ReactPlayer controls url="https://vimeo.com/4613611xx" />`);
57
+ }));
58
+ test("video link, not embedded", () => __awaiter(void 0, void 0, void 0, function* () {
59
+ (0, log_1.setLogLevel)("verbose");
60
+ const config = { plugins: [VideoTransformer_1.standardVideoTransformer] };
61
+ const result = yield (0, pluginTestRun_1.blocksToMarkdown)(config, [
62
+ {
63
+ object: "block",
64
+ type: "paragraph",
65
+ paragraph: {
66
+ rich_text: [
67
+ {
68
+ type: "text",
69
+ text: {
70
+ content: "https://vimeo.com/4613611xx",
71
+ link: {
72
+ url: "https://vimeo.com/4613611xx",
73
+ },
74
+ },
75
+ annotations: {
76
+ code: false,
77
+ },
78
+ plain_text: "https://vimeo.com/4613611xx",
79
+ href: "https://vimeo.com/4613611xx",
80
+ },
81
+ ],
82
+ color: "default",
83
+ },
84
+ },
85
+ ]);
86
+ expect(result).toContain("[https://vimeo.com/4613611xx](https://vimeo.com/4613611xx)");
87
+ expect(result).not.toContain(`import`);
88
+ }));
89
+ test("direct upload to to Notion (embedded)", () => __awaiter(void 0, void 0, void 0, function* () {
90
+ (0, log_1.setLogLevel)("verbose");
91
+ const config = { plugins: [VideoTransformer_1.standardVideoTransformer] };
92
+ const result = yield (0, pluginTestRun_1.blocksToMarkdown)(config, [
93
+ {
94
+ object: "block",
95
+ id: "12f7db3b-4412-4be9-a3f7-6ac423fee94a",
96
+ parent: {
97
+ type: "page_id",
98
+ page_id: "edaffeb2-ece8-4d44-976f-351e6b5757bb",
99
+ },
100
+ type: "video",
101
+ video: {
102
+ caption: [],
103
+ type: "file",
104
+ file: {
105
+ url: "https://s3.us-west-2.amazonaws.com/secure.notion-static.com/f6bc4746-011e-2124-86ca-ed4337d70891/people_fre_motionAsset_p3.mp4?X-Blah-blah",
106
+ },
107
+ },
108
+ },
109
+ ]);
110
+ expect(result).toContain(`import ReactPlayer from "react-player";`);
111
+ expect(result).toContain(`<ReactPlayer controls url="https://s3.us-west-2.amazonaws.com/secure.notion-static.com/f6bc4746-011e-2124-86ca-ed4337d70891/people_fre_motionAsset_p3.mp4?X-Blah-blah" />`);
112
+ }));
@@ -1,5 +1,3 @@
1
1
  import { IPlugin } from "./pluginTypes";
2
2
  export declare const gifEmbed: IPlugin;
3
3
  export declare const imgurGifEmbed: IPlugin;
4
- export declare const youtubeEmbed: IPlugin;
5
- export declare const vimeoEmbed: IPlugin;
@@ -1,13 +1,13 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.vimeoEmbed = exports.youtubeEmbed = exports.imgurGifEmbed = exports.gifEmbed = void 0;
3
+ exports.imgurGifEmbed = exports.gifEmbed = void 0;
4
4
  exports.gifEmbed = {
5
5
  name: "gif",
6
6
  regexMarkdownModifications: [
7
7
  {
8
8
  // I once saw a gif coming from Notion that wasn't a full
9
9
  // url, which wouldn't work, hence the "http" requirement
10
- regex: /\[.*\]\((http.*(\.(gif|GIF)))\)/,
10
+ regex: /\[.*?\]\((http.*?(\.(gif|GIF)))\)/,
11
11
  replacementPattern: `![]($1)`,
12
12
  },
13
13
  ],
@@ -16,31 +16,9 @@ exports.imgurGifEmbed = {
16
16
  name: "imgur",
17
17
  regexMarkdownModifications: [
18
18
  {
19
- regex: /\[.*\]\((.*imgur\.com\/.*)\)/,
19
+ regex: /\[.*?\]\((.*?imgur\.com\/.*?)\)/,
20
20
  // imgur links to gifs need a .gif at the end, but the url they give you doesn't have one.
21
21
  replacementPattern: `![]($1.gif)`,
22
22
  },
23
23
  ],
24
24
  };
25
- exports.youtubeEmbed = {
26
- name: "youtube",
27
- regexMarkdownModifications: [
28
- {
29
- regex: /\[.*\]\((.*youtube\.com\/watch.*)\)/,
30
- imports: [`import ReactPlayer from "react-player";`],
31
- replacementPattern: `<ReactPlayer controls url="$1" />`,
32
- },
33
- ],
34
- };
35
- exports.vimeoEmbed = {
36
- name: "vimeo",
37
- regexMarkdownModifications: [
38
- {
39
- regex: /\[.*\]\((https:\/\/.*vimeo.*)\)/,
40
- // we use to have the following, but the above should handle both the player an not-player urls.
41
- //regex: /\[.*\]\((.*player\.vimeo.*)\)/gm, // player.vimeo
42
- imports: [`import ReactPlayer from "react-player";`],
43
- replacementPattern: `<ReactPlayer controls url="$1" />`,
44
- },
45
- ],
46
- };