@sillsdev/docu-notion 0.16.0 → 0.16.2-alpha.1

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.
@@ -0,0 +1,6 @@
1
+ /// <reference types="node" />
2
+ export declare enum AssetType {
3
+ Image = "image",
4
+ Video = "video"
5
+ }
6
+ export declare function writeAsset(path: string, buffer: Buffer): void;
package/dist/assets.js ADDED
@@ -0,0 +1,50 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || function (mod) {
19
+ if (mod && mod.__esModule) return mod;
20
+ var result = {};
21
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
+ __setModuleDefault(result, mod);
23
+ return result;
24
+ };
25
+ Object.defineProperty(exports, "__esModule", { value: true });
26
+ exports.writeAsset = exports.AssetType = void 0;
27
+ const fs = __importStar(require("fs-extra"));
28
+ const Path = __importStar(require("path"));
29
+ const log_1 = require("./log");
30
+ var AssetType;
31
+ (function (AssetType) {
32
+ AssetType["Image"] = "image";
33
+ AssetType["Video"] = "video";
34
+ })(AssetType = exports.AssetType || (exports.AssetType = {}));
35
+ function writeAsset(path, buffer) {
36
+ // Note: it's tempting to not spend time writing this out if we already have
37
+ // it from a previous run. But we don't really know it's the same. A) it
38
+ // could just have the same name, B) it could have been previously
39
+ // unlocalized and thus filled with a copy of the primary language image
40
+ // while and now is localized.
41
+ if (fs.pathExistsSync(path)) {
42
+ (0, log_1.verbose)("Replacing asset " + path);
43
+ }
44
+ else {
45
+ (0, log_1.verbose)("Adding asset " + path);
46
+ fs.mkdirsSync(Path.dirname(path));
47
+ }
48
+ fs.createWriteStream(path).write(buffer); // async but we're not waiting
49
+ }
50
+ exports.writeAsset = writeAsset;
package/dist/images.js CHANGED
@@ -39,9 +39,9 @@ exports.cleanupOldImages = exports.parseImageBlock = exports.markdownToMDImageTr
39
39
  const fs = __importStar(require("fs-extra"));
40
40
  const file_type_1 = __importDefault(require("file-type"));
41
41
  const axios_1 = __importDefault(require("axios"));
42
- const Path = __importStar(require("path"));
43
42
  const MakeImagePersistencePlan_1 = require("./MakeImagePersistencePlan");
44
43
  const log_1 = require("./log");
44
+ const assets_1 = require("./assets");
45
45
  // We handle several things here:
46
46
  // 1) copy images locally instead of leaving them in Notion
47
47
  // 2) change the links to point here
@@ -142,10 +142,12 @@ function readPrimaryImage(imageSet) {
142
142
  }
143
143
  function saveImage(imageSet) {
144
144
  return __awaiter(this, void 0, void 0, function* () {
145
- writeImageIfNew(imageSet.primaryFileOutputPath, imageSet.primaryBuffer);
145
+ const path = imageSet.primaryFileOutputPath;
146
+ imageWasSeen(path);
147
+ (0, assets_1.writeAsset)(path, imageSet.primaryBuffer);
146
148
  for (const localizedImage of imageSet.localizedUrls) {
147
149
  let buffer = imageSet.primaryBuffer;
148
- // if we have a urls for the localized screenshot, download it
150
+ // if we have a url for the localized screenshot, download it
149
151
  if ((localizedImage === null || localizedImage === void 0 ? void 0 : localizedImage.url.length) > 0) {
150
152
  (0, log_1.verbose)(`Retrieving ${localizedImage.iso632Code} version...`);
151
153
  const response = yield fetch(localizedImage.url);
@@ -157,26 +159,12 @@ function saveImage(imageSet) {
157
159
  // otherwise, we're going to fall back to outputting the primary image here
158
160
  }
159
161
  const directory = `./i18n/${localizedImage.iso632Code}/docusaurus-plugin-content-docs/current/${imageSet.pageInfo.relativeFilePathToFolderContainingPage}`;
160
- writeImageIfNew((directory + "/" + imageSet.outputFileName).replaceAll("//", "/"), buffer);
162
+ const newPath = (directory + "/" + imageSet.outputFileName).replaceAll("//", "/");
163
+ imageWasSeen(newPath);
164
+ (0, assets_1.writeAsset)(newPath, buffer);
161
165
  }
162
166
  });
163
167
  }
164
- function writeImageIfNew(path, buffer) {
165
- imageWasSeen(path);
166
- // Note: it's tempting to not spend time writing this out if we already have
167
- // it from a previous run. But we don't really know it's the same. A) it
168
- // could just have the same name, B) it could have been previously
169
- // unlocalized and thus filled with a copy of the primary language image
170
- // while and now is localized.
171
- if (fs.pathExistsSync(path)) {
172
- (0, log_1.verbose)("Replacing image " + path);
173
- }
174
- else {
175
- (0, log_1.verbose)("Adding image " + path);
176
- fs.mkdirsSync(Path.dirname(path));
177
- }
178
- fs.createWriteStream(path).write(buffer); // async but we're not waiting
179
- }
180
168
  function parseImageBlock(image) {
181
169
  var _a;
182
170
  if (!locales)
@@ -1,33 +1,103 @@
1
1
  "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || function (mod) {
19
+ if (mod && mod.__esModule) return mod;
20
+ var result = {};
21
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
+ __setModuleDefault(result, mod);
23
+ return result;
24
+ };
25
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
26
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
27
+ return new (P || (P = Promise))(function (resolve, reject) {
28
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
29
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
30
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
31
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
32
+ });
33
+ };
2
34
  Object.defineProperty(exports, "__esModule", { value: true });
3
35
  exports.standardVideoTransformer = void 0;
36
+ const Path = __importStar(require("path"));
4
37
  const log_1 = require("../log");
38
+ const assets_1 = require("../assets");
5
39
  exports.standardVideoTransformer = {
6
40
  name: "video",
7
41
  notionToMarkdownTransforms: [
8
42
  {
9
43
  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
- },
44
+ getStringFromBlock: (context, block) => markdownToMDVideoTransformer(block, context),
31
45
  },
32
46
  ],
33
47
  };
48
+ function markdownToMDVideoTransformer(block, context) {
49
+ return __awaiter(this, void 0, void 0, function* () {
50
+ const videoBlock = block;
51
+ const video = videoBlock.video;
52
+ let url = "";
53
+ switch (video.type) {
54
+ case "external":
55
+ url = `"${video.external.url}"`;
56
+ break;
57
+ case "file":
58
+ // The url we get for a Notion-hosted asset expires after an hour, so we have to download it locally.
59
+ url = yield downloadVideoAndConvertUrl(context, video.file.url, videoBlock.id);
60
+ break;
61
+ default:
62
+ // video.type can only be "external" or "file" as of the writing of this code, so typescript
63
+ // isn't happy trying to turn video.type into a string. But this default in our switch is
64
+ // just attempting some future-proofing. Thus the strange typing/stringifying below.
65
+ (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.`);
66
+ return "";
67
+ }
68
+ context.imports.push(`import ReactPlayer from "react-player";`);
69
+ return `<ReactPlayer controls url=${url} />`;
70
+ });
71
+ }
72
+ // ENHANCE: One day, we may want to allow for options of where to place the files, how
73
+ // to name them, etc. Or we could at least follow the image options.
74
+ // But for now, I'm just trying to fix the bug that Notion-hosted videos don't work at all.
75
+ function downloadVideoAndConvertUrl(context, notionVideoUrl, blockId) {
76
+ return __awaiter(this, void 0, void 0, function* () {
77
+ // Get the file name from the url. Ignore query parameters and fragments.
78
+ let newFileName = notionVideoUrl.split("?")[0].split("#")[0].split("/").pop();
79
+ if (!newFileName) {
80
+ // If something went wrong, fall back to the block ID.
81
+ // But at least try to get the extension from the url.
82
+ const extension = notionVideoUrl
83
+ .split("?")[0]
84
+ .split("#")[0]
85
+ .split(".")
86
+ .pop();
87
+ newFileName = blockId + (extension ? "." + extension : "");
88
+ }
89
+ const newPath = Path.posix.join(context.pageInfo.directoryContainingMarkdown, newFileName);
90
+ const response = yield fetch(notionVideoUrl);
91
+ const arrayBuffer = yield response.arrayBuffer();
92
+ const buffer = Buffer.from(arrayBuffer);
93
+ (0, assets_1.writeAsset)(newPath, buffer);
94
+ // Add an import statement for the video file.
95
+ // Otherwise, the docusaurus build won't include the video file in the build.
96
+ const countVideoImports = context.imports.filter(i => {
97
+ return /import video\d+/.exec(i);
98
+ }).length;
99
+ const importName = `video${countVideoImports + 1}`;
100
+ context.imports.push(`import ${importName} from "./${newFileName}";`);
101
+ return `{${importName}}`;
102
+ });
103
+ }
@@ -1,4 +1,27 @@
1
1
  "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || function (mod) {
19
+ if (mod && mod.__esModule) return mod;
20
+ var result = {};
21
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
+ __setModuleDefault(result, mod);
23
+ return result;
24
+ };
2
25
  var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
26
  function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
27
  return new (P || (P = Promise))(function (resolve, reject) {
@@ -9,9 +32,31 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
9
32
  });
10
33
  };
11
34
  Object.defineProperty(exports, "__esModule", { value: true });
35
+ const fs = __importStar(require("fs-extra"));
12
36
  const log_1 = require("../log");
13
37
  const VideoTransformer_1 = require("./VideoTransformer");
14
38
  const pluginTestRun_1 = require("./pluginTestRun");
39
+ beforeAll(() => __awaiter(void 0, void 0, void 0, function* () {
40
+ try {
41
+ if (yield fs.pathExists(pluginTestRun_1.kTemporaryTestDirectory)) {
42
+ yield fs.emptyDir(pluginTestRun_1.kTemporaryTestDirectory);
43
+ }
44
+ else {
45
+ yield fs.mkdirp(pluginTestRun_1.kTemporaryTestDirectory);
46
+ }
47
+ }
48
+ catch (err) {
49
+ console.error("Error in beforeAll:", err);
50
+ }
51
+ }));
52
+ afterAll(() => __awaiter(void 0, void 0, void 0, function* () {
53
+ try {
54
+ yield fs.remove(pluginTestRun_1.kTemporaryTestDirectory);
55
+ }
56
+ catch (err) {
57
+ console.error("Error in afterAll:", err);
58
+ }
59
+ }));
15
60
  test("youtube embedded", () => __awaiter(void 0, void 0, void 0, function* () {
16
61
  const config = { plugins: [VideoTransformer_1.standardVideoTransformer] };
17
62
  const result = yield (0, pluginTestRun_1.blocksToMarkdown)(config, [
@@ -89,6 +134,8 @@ test("video link, not embedded", () => __awaiter(void 0, void 0, void 0, functio
89
134
  test("direct upload to to Notion (embedded)", () => __awaiter(void 0, void 0, void 0, function* () {
90
135
  (0, log_1.setLogLevel)("verbose");
91
136
  const config = { plugins: [VideoTransformer_1.standardVideoTransformer] };
137
+ const fileName1 = "first_video.mp4";
138
+ const fileName2 = "second_video.mp4";
92
139
  const result = yield (0, pluginTestRun_1.blocksToMarkdown)(config, [
93
140
  {
94
141
  object: "block",
@@ -102,11 +149,35 @@ test("direct upload to to Notion (embedded)", () => __awaiter(void 0, void 0, vo
102
149
  caption: [],
103
150
  type: "file",
104
151
  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",
152
+ url: `https://s3.us-west-2.amazonaws.com/secure.notion-static.com/f6bc4746-011e-2124-86ca-ed4337d70891/${fileName1}?X-Blah-blah`,
153
+ },
154
+ },
155
+ },
156
+ {
157
+ object: "block",
158
+ id: "12f7db3b-4412-4be9-a3f7-6ac423fee94b",
159
+ parent: {
160
+ type: "page_id",
161
+ page_id: "edaffeb2-ece8-4d44-976f-351e6b5757bb",
162
+ },
163
+ type: "video",
164
+ video: {
165
+ caption: [],
166
+ type: "file",
167
+ file: {
168
+ url: `https://s3.us-west-2.amazonaws.com/secure.notion-static.com/f6bc4746-011e-2124-86ca-ed4337d70891/${fileName2}?X-Blah-blah`,
106
169
  },
107
170
  },
108
171
  },
109
172
  ]);
110
173
  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" />`);
174
+ expect(result).toContain(`import video1 from "./${fileName1}";`);
175
+ expect(result).toContain(`import video2 from "./${fileName2}";`);
176
+ expect(result).toContain(`<ReactPlayer controls url={video1} />`);
177
+ expect(result).toContain(`<ReactPlayer controls url={video2} />`);
178
+ // Wait half a second for the files to be written
179
+ yield new Promise(resolve => setTimeout(resolve, 500));
180
+ // We should have actually created files in "tempTestFileDir/"
181
+ expect(yield fs.pathExists("tempTestFileDir/" + fileName1)).toBe(true);
182
+ expect(yield fs.pathExists("tempTestFileDir/" + fileName2)).toBe(true);
112
183
  }));
@@ -29,7 +29,8 @@ function convertInternalUrl(context, url) {
29
29
  exports.convertInternalUrl = convertInternalUrl;
30
30
  // handles the whole markdown link, including the label
31
31
  function convertInternalLink(context, markdownLink) {
32
- const linkRegExp = /\[([^\]]+)?\]\(\/?([^),^/]+)\)/g;
32
+ // match both [foo](/123) and [bar](https://www.notion.so/123) <-- the "mention" link style
33
+ const linkRegExp = /\[([^\]]+)?\]\((?:https?:\/\/www\.notion\.so\/|\/)?([^),^/]+)\)/g;
33
34
  const match = linkRegExp.exec(markdownLink);
34
35
  if (match === null) {
35
36
  (0, log_1.warning)(`[standardInternalLinkConversion] Could not parse link ${markdownLink}`);
@@ -96,7 +97,9 @@ exports.standardInternalLinkConversion = {
96
97
  // (has some other text that's been turned into a link) or "raw".
97
98
  // Raw links come in without a leading slash, e.g. [link_to_page](4a6de8c0-b90b-444b-8a7b-d534d6ec71a4)
98
99
  // Inline links come in with a leading slash, e.g. [pointer to the introduction](/4a6de8c0b90b444b8a7bd534d6ec71a4)
99
- match: /\[([^\]]+)?\]\((?!mailto:)(\/?[^),^/]+)\)/,
100
+ // "Mention" links come in as full URLs, e.g. [link_to_page](https://www.notion.so/62f1187010214b0883711a1abb277d31)
101
+ // YOu can create them either with @+the name of a page, or by pasting a URL and then selecting the "Mention" option.
102
+ match: /\[([^\]]+)?\]\((?!mailto:)(https:\/\/www\.notion\.so\/[^),^/]+|\/?[^),^/]+)\)/,
100
103
  convert: convertInternalLink,
101
104
  },
102
105
  };
@@ -38,6 +38,43 @@ test("urls that show up as raw text get left that way", () => __awaiter(void 0,
38
38
  });
39
39
  expect(results.trim()).toBe("https://github.com");
40
40
  }));
41
+ // See https://github.com/sillsdev/docu-notion/issues/97
42
+ test("mention-style link to an existing page", () => __awaiter(void 0, void 0, void 0, function* () {
43
+ const targetPageId = "123";
44
+ const targetPage = (0, pluginTestRun_1.makeSamplePageObject)({
45
+ slug: undefined,
46
+ name: "Hello World",
47
+ id: targetPageId,
48
+ });
49
+ const results = yield getMarkdown({
50
+ type: "paragraph",
51
+ paragraph: {
52
+ rich_text: [
53
+ {
54
+ type: "mention",
55
+ mention: {
56
+ type: "page",
57
+ page: {
58
+ id: `${targetPageId}`,
59
+ },
60
+ },
61
+ annotations: {
62
+ bold: false,
63
+ italic: false,
64
+ strikethrough: false,
65
+ underline: false,
66
+ code: false,
67
+ color: "default",
68
+ },
69
+ plain_text: "foo",
70
+ href: `https://www.notion.so/${targetPageId}`,
71
+ },
72
+ ],
73
+ color: "default",
74
+ },
75
+ }, targetPage);
76
+ expect(results.trim()).toBe(`[foo](/${targetPageId})`);
77
+ }));
41
78
  test("link to an existing page on this site that has no slug", () => __awaiter(void 0, void 0, void 0, function* () {
42
79
  const targetPageId = "123";
43
80
  const targetPage = (0, pluginTestRun_1.makeSamplePageObject)({
@@ -517,7 +554,78 @@ test("internal link inside codeblock ignored", () => __awaiter(void 0, void 0, v
517
554
  }, targetPage);
518
555
  expect(results.trim()).toContain("this should not change [link](https://www.notion.so/native/metapages/mypage)");
519
556
  }));
520
- function getMarkdown(block, targetPage) {
557
+ test("multiple internal links in a paragraph", () => __awaiter(void 0, void 0, void 0, function* () {
558
+ const targetPageAId = "123";
559
+ const targetPageA = (0, pluginTestRun_1.makeSamplePageObject)({
560
+ slug: undefined,
561
+ name: "Hello World A",
562
+ id: targetPageAId,
563
+ });
564
+ const targetPageBId = "456";
565
+ const targetPageB = (0, pluginTestRun_1.makeSamplePageObject)({
566
+ slug: undefined,
567
+ name: "Hello World B",
568
+ id: targetPageBId,
569
+ });
570
+ const results = yield getMarkdown({
571
+ type: "paragraph",
572
+ paragraph: {
573
+ rich_text: [
574
+ {
575
+ type: "text",
576
+ text: {
577
+ content: "A",
578
+ link: { url: `/${targetPageAId}` },
579
+ },
580
+ annotations: {
581
+ bold: false,
582
+ italic: false,
583
+ strikethrough: false,
584
+ underline: false,
585
+ code: false,
586
+ color: "default",
587
+ },
588
+ plain_text: "A",
589
+ href: `/${targetPageAId}`,
590
+ },
591
+ {
592
+ type: "text",
593
+ text: { content: " ", link: null },
594
+ annotations: {
595
+ bold: false,
596
+ italic: false,
597
+ strikethrough: false,
598
+ underline: false,
599
+ code: false,
600
+ color: "default",
601
+ },
602
+ plain_text: " ",
603
+ href: null,
604
+ },
605
+ {
606
+ type: "text",
607
+ text: {
608
+ content: "B",
609
+ link: { url: `/${targetPageBId}` },
610
+ },
611
+ annotations: {
612
+ bold: false,
613
+ italic: false,
614
+ strikethrough: false,
615
+ underline: false,
616
+ code: false,
617
+ color: "default",
618
+ },
619
+ plain_text: "B",
620
+ href: `/${targetPageBId}`,
621
+ },
622
+ ],
623
+ color: "default",
624
+ },
625
+ }, targetPageA, targetPageB);
626
+ expect(results.trim()).toBe(`[A](/${targetPageAId}) [B](/${targetPageBId})`);
627
+ }));
628
+ function getMarkdown(block, targetPage, targetPage2) {
521
629
  return __awaiter(this, void 0, void 0, function* () {
522
630
  const config = {
523
631
  plugins: [
@@ -526,6 +634,6 @@ function getMarkdown(block, targetPage) {
526
634
  externalLinks_1.standardExternalLinkConversion,
527
635
  ],
528
636
  };
529
- return yield (0, pluginTestRun_1.oneBlockToMarkdown)(config, block, targetPage);
637
+ return yield (0, pluginTestRun_1.oneBlockToMarkdown)(config, block, targetPage, targetPage2);
530
638
  });
531
639
  }
@@ -1,10 +1,11 @@
1
1
  import { NotionPage } from "../NotionPage";
2
2
  import { IDocuNotionConfig } from "../config/configuration";
3
3
  import { NotionBlock } from "../types";
4
+ export declare const kTemporaryTestDirectory = "tempTestFileDir";
4
5
  export declare function blocksToMarkdown(config: IDocuNotionConfig, blocks: NotionBlock[], pages?: NotionPage[], children?: NotionBlock[], validApiKey?: string): Promise<string>;
5
6
  export declare function makeSamplePageObject(options: {
6
7
  slug?: string;
7
8
  name?: string;
8
9
  id?: string;
9
10
  }): NotionPage;
10
- export declare function oneBlockToMarkdown(config: IDocuNotionConfig, block: Record<string, unknown>, targetPage?: NotionPage): Promise<string>;
11
+ export declare function oneBlockToMarkdown(config: IDocuNotionConfig, block: Record<string, unknown>, targetPage?: NotionPage, targetPage2?: NotionPage): Promise<string>;
@@ -9,7 +9,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
9
9
  });
10
10
  };
11
11
  Object.defineProperty(exports, "__esModule", { value: true });
12
- exports.oneBlockToMarkdown = exports.makeSamplePageObject = exports.blocksToMarkdown = void 0;
12
+ exports.oneBlockToMarkdown = exports.makeSamplePageObject = exports.blocksToMarkdown = exports.kTemporaryTestDirectory = void 0;
13
13
  const client_1 = require("@notionhq/client");
14
14
  const notion_to_md_1 = require("notion-to-md");
15
15
  const HierarchicalNamedLayoutStrategy_1 = require("../HierarchicalNamedLayoutStrategy");
@@ -17,6 +17,7 @@ const NotionPage_1 = require("../NotionPage");
17
17
  const transform_1 = require("../transform");
18
18
  const internalLinks_1 = require("./internalLinks");
19
19
  const pull_1 = require("../pull");
20
+ exports.kTemporaryTestDirectory = "tempTestFileDir";
20
21
  function blocksToMarkdown(config, blocks, pages,
21
22
  // Notes on children:
22
23
  // - These children will apply to each block in blocks. (could enhance but not needed yet)
@@ -50,7 +51,7 @@ children, validApiKey) {
50
51
  imports: [],
51
52
  //TODO might be needed for some tests, e.g. the image transformer...
52
53
  pageInfo: {
53
- directoryContainingMarkdown: "not yet",
54
+ directoryContainingMarkdown: exports.kTemporaryTestDirectory,
54
55
  relativeFilePathToFolderContainingPage: "not yet",
55
56
  slug: "not yet",
56
57
  },
@@ -226,7 +227,7 @@ function makeSamplePageObject(options) {
226
227
  return p;
227
228
  }
228
229
  exports.makeSamplePageObject = makeSamplePageObject;
229
- function oneBlockToMarkdown(config, block, targetPage) {
230
+ function oneBlockToMarkdown(config, block, targetPage, targetPage2) {
230
231
  return __awaiter(this, void 0, void 0, function* () {
231
232
  // just in case someone expects these other properties that aren't normally relevant,
232
233
  // we merge the given block properties into an actual, full block
@@ -258,7 +259,7 @@ function oneBlockToMarkdown(config, block, targetPage) {
258
259
  slug: "dummy2",
259
260
  name: "Dummy2",
260
261
  });
261
- return yield blocksToMarkdown(config, [fullBlock], targetPage ? [dummyPage1, targetPage, dummyPage2] : undefined);
262
+ return yield blocksToMarkdown(config, [fullBlock], targetPage ? [dummyPage1, targetPage, targetPage2 !== null && targetPage2 !== void 0 ? targetPage2 : dummyPage2] : undefined);
262
263
  });
263
264
  }
264
265
  exports.oneBlockToMarkdown = oneBlockToMarkdown;
package/dist/pull.js CHANGED
@@ -163,7 +163,7 @@ function getPagesRecursively(options, incomingContext, pageIdOfThisParent, order
163
163
  if (!rootLevel &&
164
164
  pageInfo.hasParagraphs &&
165
165
  pageInfo.childPageIdsAndOrder.length) {
166
- (0, log_1.error)(`Skipping "${pageInTheOutline.nameOrTitle}" and its children. docu-notion does not support pages that are both levels and have content at the same time.`);
166
+ (0, log_1.error)(`Skipping "${pageInTheOutline.nameOrTitle}" and its children. docu-notion does not support pages that are both levels and have text content (paragraphs) at the same time. Normally outline pages should just be composed of 1) links to other pages and 2) child pages (other levels of the outline). Note that @-mention style links appear as text paragraphs to docu-notion so must not be used to form the outline.`);
167
167
  ++counts.skipped_because_level_cannot_have_content;
168
168
  return;
169
169
  }
package/dist/transform.js CHANGED
@@ -149,7 +149,7 @@ function doNotionToMarkdown(docunotionContext, blocks) {
149
149
  // Raw links come in without a leading slash, e.g. [link_to_page](4a6de8c0-b90b-444b-8a7b-d534d6ec71a4)
150
150
  // Inline links come in with a leading slash, e.g. [pointer to the introduction](/4a6de8c0b90b444b8a7bd534d6ec71a4)
151
151
  function doLinkFixes(context, markdown, config) {
152
- const linkRegExp = /\[.*\]\([^\)]*\)/g;
152
+ const linkRegExp = /\[.*?\]\([^\)]*?\)/g;
153
153
  (0, log_1.logDebug)("markdown before link fixes", markdown);
154
154
  let match;
155
155
  // since we're going to make changes to the markdown,
package/package.json CHANGED
@@ -91,5 +91,5 @@
91
91
  "volta": {
92
92
  "node": "18.16.0"
93
93
  },
94
- "version": "0.16.0"
94
+ "version": "0.16.2-alpha.1"
95
95
  }