@sillsdev/docu-notion 0.12.0
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/LICENSE +21 -0
- package/README.md +135 -0
- package/dist/FlatGuidLayoutStrategy.d.ts +6 -0
- package/dist/FlatGuidLayoutStrategy.js +25 -0
- package/dist/HierarchicalNamedLayoutStrategy.d.ts +7 -0
- package/dist/HierarchicalNamedLayoutStrategy.js +80 -0
- package/dist/LayoutStrategy.d.ts +12 -0
- package/dist/LayoutStrategy.js +83 -0
- package/dist/MakeImagePersistencePlan.d.ts +2 -0
- package/dist/MakeImagePersistencePlan.js +66 -0
- package/dist/NotionImage-CaptionReading.spec.d.ts +1 -0
- package/dist/NotionImage-CaptionReading.spec.js +233 -0
- package/dist/NotionPage.d.ts +44 -0
- package/dist/NotionPage.js +194 -0
- package/dist/config/configuration.d.ts +5 -0
- package/dist/config/configuration.js +86 -0
- package/dist/config/default.docunotion.config.d.ts +3 -0
- package/dist/config/default.docunotion.config.js +37 -0
- package/dist/images.d.ts +24 -0
- package/dist/images.js +230 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.js +37 -0
- package/dist/log.d.ts +11 -0
- package/dist/log.js +61 -0
- package/dist/makeImagePersistencePlan.spec.d.ts +1 -0
- package/dist/makeImagePersistencePlan.spec.js +35 -0
- package/dist/notion-styles.css +58 -0
- package/dist/plugins/CalloutTransformer.d.ts +24 -0
- package/dist/plugins/CalloutTransformer.js +88 -0
- package/dist/plugins/CalloutTransformer.spec.d.ts +1 -0
- package/dist/plugins/CalloutTransformer.spec.js +199 -0
- package/dist/plugins/ColumnListTransformer.d.ts +2 -0
- package/dist/plugins/ColumnListTransformer.js +34 -0
- package/dist/plugins/ColumnTransformer.d.ts +2 -0
- package/dist/plugins/ColumnTransformer.js +67 -0
- package/dist/plugins/EscapeHtmlBlockModifier.d.ts +2 -0
- package/dist/plugins/EscapeHtmlBlockModifier.js +41 -0
- package/dist/plugins/EscapeHtmlBlockModifier.spec.d.ts +1 -0
- package/dist/plugins/EscapeHtmlBlockModifier.spec.js +130 -0
- package/dist/plugins/HeadingTranformer.spec.d.ts +1 -0
- package/dist/plugins/HeadingTranformer.spec.js +46 -0
- package/dist/plugins/HeadingTransformer.d.ts +2 -0
- package/dist/plugins/HeadingTransformer.js +63 -0
- package/dist/plugins/NumberedListTransformer.d.ts +2 -0
- package/dist/plugins/NumberedListTransformer.js +55 -0
- package/dist/plugins/NumberedListTransformer.spec.d.ts +1 -0
- package/dist/plugins/NumberedListTransformer.spec.js +86 -0
- package/dist/plugins/TableTransformer.d.ts +5 -0
- package/dist/plugins/TableTransformer.js +70 -0
- package/dist/plugins/embedTweaks.d.ts +5 -0
- package/dist/plugins/embedTweaks.js +46 -0
- package/dist/plugins/embedTweaks.spec.d.ts +1 -0
- package/dist/plugins/embedTweaks.spec.js +230 -0
- package/dist/plugins/externalLinks.d.ts +2 -0
- package/dist/plugins/externalLinks.js +26 -0
- package/dist/plugins/externalLinks.spec.d.ts +1 -0
- package/dist/plugins/externalLinks.spec.js +132 -0
- package/dist/plugins/internalLinks.d.ts +6 -0
- package/dist/plugins/internalLinks.js +78 -0
- package/dist/plugins/internalLinks.spec.d.ts +1 -0
- package/dist/plugins/internalLinks.spec.js +442 -0
- package/dist/plugins/pluginTestRun.d.ts +10 -0
- package/dist/plugins/pluginTestRun.js +248 -0
- package/dist/plugins/pluginTypes.d.ts +42 -0
- package/dist/plugins/pluginTypes.js +2 -0
- package/dist/pull.d.ts +12 -0
- package/dist/pull.js +253 -0
- package/dist/run.d.ts +1 -0
- package/dist/run.js +35 -0
- package/dist/transform.d.ts +6 -0
- package/dist/transform.js +195 -0
- package/dist/types.d.ts +8 -0
- package/dist/types.js +2 -0
- package/package.json +96 -0
|
@@ -0,0 +1,233 @@
|
|
|
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 images_1 = require("./images");
|
|
13
|
+
const kPrimaryImageUrl = "https://s3.us-west-2.amazonaws.com/primaryImage.png?Blah=foo";
|
|
14
|
+
/* didn't work?
|
|
15
|
+
beforeAll(async () => {
|
|
16
|
+
console.log("before");
|
|
17
|
+
await initImageHandling("", "", []);
|
|
18
|
+
console.log("azfter");
|
|
19
|
+
});
|
|
20
|
+
*/
|
|
21
|
+
/* eslint-disable @typescript-eslint/require-await */
|
|
22
|
+
test("finds primary image url", () => __awaiter(void 0, void 0, void 0, function* () {
|
|
23
|
+
yield (0, images_1.initImageHandling)("", "", []);
|
|
24
|
+
const img = (0, images_1.parseImageBlock)(kImageBlockWithTwoLocalizedImages.image);
|
|
25
|
+
expect(img.primaryUrl).toBe(kPrimaryImageUrl);
|
|
26
|
+
}));
|
|
27
|
+
test("primary caption content after image links are removed", () => __awaiter(void 0, void 0, void 0, function* () {
|
|
28
|
+
yield (0, images_1.initImageHandling)("", "", []);
|
|
29
|
+
const img = (0, images_1.parseImageBlock)(kImageBlockWithTwoLocalizedImagesWrappedWithActualCaptionText.image);
|
|
30
|
+
// carriage returns seem to mess up the markdown, so should be removed
|
|
31
|
+
expect(img.caption).toBe("Caption before images. Caption after images.");
|
|
32
|
+
}));
|
|
33
|
+
test("gets localized image links", () => __awaiter(void 0, void 0, void 0, function* () {
|
|
34
|
+
yield (0, images_1.initImageHandling)("", "", []);
|
|
35
|
+
const img = (0, images_1.parseImageBlock)(kImageBlockWithTwoLocalizedImagesWrappedWithActualCaptionText.image);
|
|
36
|
+
expect(img.localizedUrls.length).toBe(2);
|
|
37
|
+
expect(img.localizedUrls[0].iso632Code).toBe("fr");
|
|
38
|
+
expect(img.localizedUrls[1].iso632Code).toBe("es");
|
|
39
|
+
expect(img.localizedUrls[0].url).toBe("https://i.imgur.com/pYmE7OJ.png");
|
|
40
|
+
expect(img.localizedUrls[1].url).toBe("https://i.imgur.com/8paSZ0i.png");
|
|
41
|
+
}));
|
|
42
|
+
const kImageBlockWithTwoLocalizedImagesWrappedWithActualCaptionText = {
|
|
43
|
+
object: "block",
|
|
44
|
+
id: "20b821b4-7c5b-41dc-8e30-92c23c125580",
|
|
45
|
+
parent: { type: "page_id", page_id: "9dd05134-0401-47f6-b159-1e6b76b9aad3" },
|
|
46
|
+
created_time: "2022-07-25T23:05:00.000Z",
|
|
47
|
+
last_edited_time: "2022-07-26T15:31:00.000Z",
|
|
48
|
+
created_by: { object: "user", id: "11fb7f16-0560-4aee-ab88-ed75a850cfc4" },
|
|
49
|
+
last_edited_by: {
|
|
50
|
+
object: "user",
|
|
51
|
+
id: "11fb7f16-0560-4aee-ab88-ed75a850cfc4",
|
|
52
|
+
},
|
|
53
|
+
has_children: false,
|
|
54
|
+
archived: false,
|
|
55
|
+
type: "image",
|
|
56
|
+
image: {
|
|
57
|
+
caption: [
|
|
58
|
+
{
|
|
59
|
+
type: "text",
|
|
60
|
+
text: { content: "Caption before images. fr-", link: null },
|
|
61
|
+
annotations: {
|
|
62
|
+
bold: false,
|
|
63
|
+
italic: false,
|
|
64
|
+
strikethrough: false,
|
|
65
|
+
underline: false,
|
|
66
|
+
code: false,
|
|
67
|
+
color: "default",
|
|
68
|
+
},
|
|
69
|
+
plain_text: "Caption before images.\nfr ",
|
|
70
|
+
href: null,
|
|
71
|
+
},
|
|
72
|
+
{
|
|
73
|
+
type: "text",
|
|
74
|
+
text: {
|
|
75
|
+
content: "https://i.imgur.com/pYmE7OJ.png",
|
|
76
|
+
link: { url: "https://i.imgur.com/pYmE7OJ.png" },
|
|
77
|
+
},
|
|
78
|
+
annotations: {
|
|
79
|
+
bold: false,
|
|
80
|
+
italic: false,
|
|
81
|
+
strikethrough: false,
|
|
82
|
+
underline: false,
|
|
83
|
+
code: false,
|
|
84
|
+
color: "default",
|
|
85
|
+
},
|
|
86
|
+
plain_text: "https://i.imgur.com/pYmE7OJ.png",
|
|
87
|
+
href: "https://i.imgur.com/pYmE7OJ.png",
|
|
88
|
+
},
|
|
89
|
+
{
|
|
90
|
+
type: "text",
|
|
91
|
+
text: { content: " es-", link: null },
|
|
92
|
+
annotations: {
|
|
93
|
+
bold: false,
|
|
94
|
+
italic: false,
|
|
95
|
+
strikethrough: false,
|
|
96
|
+
underline: false,
|
|
97
|
+
code: false,
|
|
98
|
+
color: "default",
|
|
99
|
+
},
|
|
100
|
+
plain_text: "\nES ",
|
|
101
|
+
href: null,
|
|
102
|
+
},
|
|
103
|
+
{
|
|
104
|
+
type: "text",
|
|
105
|
+
text: {
|
|
106
|
+
content: "https://i.imgur.com/8paSZ0i.png",
|
|
107
|
+
link: { url: "https://i.imgur.com/8paSZ0i.png" },
|
|
108
|
+
},
|
|
109
|
+
annotations: {
|
|
110
|
+
bold: false,
|
|
111
|
+
italic: false,
|
|
112
|
+
strikethrough: false,
|
|
113
|
+
underline: false,
|
|
114
|
+
code: false,
|
|
115
|
+
color: "default",
|
|
116
|
+
},
|
|
117
|
+
plain_text: "https://i.imgur.com/8paSZ0i.png",
|
|
118
|
+
href: "https://i.imgur.com/8paSZ0i.png",
|
|
119
|
+
},
|
|
120
|
+
{
|
|
121
|
+
type: "text",
|
|
122
|
+
text: { content: "\nCaption after images", link: null },
|
|
123
|
+
annotations: {
|
|
124
|
+
bold: false,
|
|
125
|
+
italic: false,
|
|
126
|
+
strikethrough: false,
|
|
127
|
+
underline: false,
|
|
128
|
+
code: false,
|
|
129
|
+
color: "default",
|
|
130
|
+
},
|
|
131
|
+
plain_text: "\nCaption after images.",
|
|
132
|
+
href: null,
|
|
133
|
+
},
|
|
134
|
+
],
|
|
135
|
+
type: "file",
|
|
136
|
+
file: {
|
|
137
|
+
url: kPrimaryImageUrl,
|
|
138
|
+
expiry_time: "2022-07-26T16:35:44.029Z",
|
|
139
|
+
},
|
|
140
|
+
},
|
|
141
|
+
};
|
|
142
|
+
const kImageBlockWithTwoLocalizedImages = {
|
|
143
|
+
object: "block",
|
|
144
|
+
id: "20b821b4-7c5b-41dc-8e30-92c23c125580",
|
|
145
|
+
parent: {
|
|
146
|
+
type: "page_id",
|
|
147
|
+
page_id: "9dd05134-0401-47f6-b159-1e6b76b9aad3",
|
|
148
|
+
},
|
|
149
|
+
created_time: "2022-07-25T23:05:00.000Z",
|
|
150
|
+
last_edited_time: "2022-07-25T23:07:00.000Z",
|
|
151
|
+
created_by: {
|
|
152
|
+
object: "user",
|
|
153
|
+
id: "11fb7f16-0560-4aee-ab88-ed75a850cfc4",
|
|
154
|
+
},
|
|
155
|
+
last_edited_by: {
|
|
156
|
+
object: "user",
|
|
157
|
+
id: "11fb7f16-0560-4aee-ab88-ed75a850cfc4",
|
|
158
|
+
},
|
|
159
|
+
has_children: false,
|
|
160
|
+
archived: false,
|
|
161
|
+
type: "image",
|
|
162
|
+
image: {
|
|
163
|
+
caption: [
|
|
164
|
+
{
|
|
165
|
+
type: "text",
|
|
166
|
+
text: { content: "fr-", link: null },
|
|
167
|
+
annotations: {
|
|
168
|
+
bold: false,
|
|
169
|
+
italic: false,
|
|
170
|
+
strikethrough: false,
|
|
171
|
+
underline: false,
|
|
172
|
+
code: false,
|
|
173
|
+
color: "default",
|
|
174
|
+
},
|
|
175
|
+
plain_text: "fr-",
|
|
176
|
+
href: null,
|
|
177
|
+
},
|
|
178
|
+
{
|
|
179
|
+
type: "text",
|
|
180
|
+
text: {
|
|
181
|
+
content: "https://i.imgur.com/pYmE7OJ.png",
|
|
182
|
+
link: { url: "https://i.imgur.com/pYmE7OJ.png" },
|
|
183
|
+
},
|
|
184
|
+
annotations: {
|
|
185
|
+
bold: false,
|
|
186
|
+
italic: false,
|
|
187
|
+
strikethrough: false,
|
|
188
|
+
underline: false,
|
|
189
|
+
code: false,
|
|
190
|
+
color: "default",
|
|
191
|
+
},
|
|
192
|
+
plain_text: "https://i.imgur.com/pYmE7OJ.png",
|
|
193
|
+
href: "https://i.imgur.com/pYmE7OJ.png",
|
|
194
|
+
},
|
|
195
|
+
{
|
|
196
|
+
type: "text",
|
|
197
|
+
text: { content: " es-", link: null },
|
|
198
|
+
annotations: {
|
|
199
|
+
bold: false,
|
|
200
|
+
italic: false,
|
|
201
|
+
strikethrough: false,
|
|
202
|
+
underline: false,
|
|
203
|
+
code: false,
|
|
204
|
+
color: "default",
|
|
205
|
+
},
|
|
206
|
+
plain_text: " es-",
|
|
207
|
+
href: null,
|
|
208
|
+
},
|
|
209
|
+
{
|
|
210
|
+
type: "text",
|
|
211
|
+
text: {
|
|
212
|
+
content: "https://i.imgur.com/8paSZ0i.png",
|
|
213
|
+
link: { url: "https://i.imgur.com/8paSZ0i.png" },
|
|
214
|
+
},
|
|
215
|
+
annotations: {
|
|
216
|
+
bold: false,
|
|
217
|
+
italic: false,
|
|
218
|
+
strikethrough: false,
|
|
219
|
+
underline: false,
|
|
220
|
+
code: false,
|
|
221
|
+
color: "default",
|
|
222
|
+
},
|
|
223
|
+
plain_text: "https://i.imgur.com/8paSZ0i.png",
|
|
224
|
+
href: "https://i.imgur.com/8paSZ0i.png",
|
|
225
|
+
},
|
|
226
|
+
],
|
|
227
|
+
type: "file",
|
|
228
|
+
file: {
|
|
229
|
+
url: kPrimaryImageUrl,
|
|
230
|
+
expiry_time: "2022-07-26T00:19:09.096Z",
|
|
231
|
+
},
|
|
232
|
+
},
|
|
233
|
+
};
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { GetPageResponse } from "@notionhq/client/build/src/api-endpoints";
|
|
2
|
+
import { ListBlockChildrenResponseResults } from "notion-to-md/build/types";
|
|
3
|
+
export declare enum PageType {
|
|
4
|
+
DatabasePage = 0,
|
|
5
|
+
Simple = 1
|
|
6
|
+
}
|
|
7
|
+
export declare class NotionPage {
|
|
8
|
+
metadata: GetPageResponse;
|
|
9
|
+
pageId: string;
|
|
10
|
+
order: number;
|
|
11
|
+
layoutContext: string;
|
|
12
|
+
foundDirectlyInOutline: boolean;
|
|
13
|
+
constructor(args: {
|
|
14
|
+
layoutContext: string;
|
|
15
|
+
pageId: string;
|
|
16
|
+
order: number;
|
|
17
|
+
metadata: GetPageResponse;
|
|
18
|
+
foundDirectlyInOutline: boolean;
|
|
19
|
+
});
|
|
20
|
+
matchesLinkId(id: string): boolean;
|
|
21
|
+
get type(): PageType;
|
|
22
|
+
get nameOrTitle(): string;
|
|
23
|
+
nameForFile(): string;
|
|
24
|
+
private get title();
|
|
25
|
+
private get name();
|
|
26
|
+
private explicitSlug;
|
|
27
|
+
get slug(): string;
|
|
28
|
+
get hasExplicitSlug(): boolean;
|
|
29
|
+
get keywords(): string | undefined;
|
|
30
|
+
get status(): string | undefined;
|
|
31
|
+
getPlainTextProperty(property: string, defaultIfEmpty: string): string;
|
|
32
|
+
getSelectProperty(property: string): string | undefined;
|
|
33
|
+
getContentInfo(children: ListBlockChildrenResponseResults): Promise<{
|
|
34
|
+
childPageIdsAndOrder: {
|
|
35
|
+
id: string;
|
|
36
|
+
order: number;
|
|
37
|
+
}[];
|
|
38
|
+
linksPageIdsAndOrder: {
|
|
39
|
+
id: string;
|
|
40
|
+
order: number;
|
|
41
|
+
}[];
|
|
42
|
+
hasParagraphs: boolean;
|
|
43
|
+
}>;
|
|
44
|
+
}
|
|
@@ -0,0 +1,194 @@
|
|
|
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
|
+
exports.NotionPage = exports.PageType = void 0;
|
|
13
|
+
const internalLinks_1 = require("./plugins/internalLinks");
|
|
14
|
+
// Notion has 2 kinds of pages: a normal one which is just content, and what I'm calling a "database page", which has whatever properties you put on it.
|
|
15
|
+
// docu-notion supports the later via links from outline pages. That is, you put the database pages in a database, then separately, in the outline, you
|
|
16
|
+
// create pages for each node of the outline and then add links from those to the database pages. In this way, we get the benefits of database
|
|
17
|
+
// pages (metadata, workflow, etc) and also normal pages (order, position in the outline).
|
|
18
|
+
var PageType;
|
|
19
|
+
(function (PageType) {
|
|
20
|
+
PageType[PageType["DatabasePage"] = 0] = "DatabasePage";
|
|
21
|
+
PageType[PageType["Simple"] = 1] = "Simple";
|
|
22
|
+
})(PageType = exports.PageType || (exports.PageType = {}));
|
|
23
|
+
class NotionPage {
|
|
24
|
+
constructor(args) {
|
|
25
|
+
this.layoutContext = args.layoutContext;
|
|
26
|
+
this.pageId = args.pageId;
|
|
27
|
+
this.order = args.order;
|
|
28
|
+
this.metadata = args.metadata;
|
|
29
|
+
this.foundDirectlyInOutline = args.foundDirectlyInOutline;
|
|
30
|
+
// review: this is expensive to learn as it takes another api call... I
|
|
31
|
+
// think? We can tell if it's a database because it has a "Name" instead of a
|
|
32
|
+
// "tile" and "parent": "type": "database_id". But do we need to differentiate
|
|
33
|
+
//this.type = PageType.Unknown;
|
|
34
|
+
}
|
|
35
|
+
matchesLinkId(id) {
|
|
36
|
+
const { baseLinkId } = (0, internalLinks_1.parseLinkId)(id);
|
|
37
|
+
const match = baseLinkId === this.pageId || // from a link_to_page.pageId, which still has the dashes
|
|
38
|
+
baseLinkId === this.pageId.replaceAll("-", ""); // from inline links, which are lacking the dashes
|
|
39
|
+
// logDebug(
|
|
40
|
+
// `matchedLinkId`,
|
|
41
|
+
// `comparing pageId:${this.pageId} to id ${id} --> ${match.toString()}`
|
|
42
|
+
// );
|
|
43
|
+
return match;
|
|
44
|
+
}
|
|
45
|
+
get type() {
|
|
46
|
+
/*
|
|
47
|
+
{
|
|
48
|
+
"object": "page",
|
|
49
|
+
"parent": {
|
|
50
|
+
"type": "page_id",
|
|
51
|
+
or
|
|
52
|
+
"type": "database_id",
|
|
53
|
+
...
|
|
54
|
+
},
|
|
55
|
+
*/
|
|
56
|
+
return this.metadata.parent.type === "database_id"
|
|
57
|
+
? PageType.DatabasePage
|
|
58
|
+
: PageType.Simple;
|
|
59
|
+
}
|
|
60
|
+
// In Notion, pages from the Database have names and simple pages have titles.
|
|
61
|
+
get nameOrTitle() {
|
|
62
|
+
return this.type === PageType.DatabasePage ? this.name : this.title;
|
|
63
|
+
}
|
|
64
|
+
nameForFile() {
|
|
65
|
+
var _a;
|
|
66
|
+
// In Notion, pages from the Database have names and simple pages have titles.
|
|
67
|
+
return this.type === PageType.Simple
|
|
68
|
+
? this.title
|
|
69
|
+
: // if it's a Database page, then we'll use the slug unless there is none, then we'd rather have the
|
|
70
|
+
// page name than an ugly id for the file name
|
|
71
|
+
((_a = this.explicitSlug()) === null || _a === void 0 ? void 0 : _a.replace(/^\//, "")) || this.name;
|
|
72
|
+
}
|
|
73
|
+
// TODO: let's go farther in hiding this separate title vs name stuff. This seems like an implementation detail on the Notion side.
|
|
74
|
+
// In Notion, pages from the Outline have "title"'s.
|
|
75
|
+
get title() {
|
|
76
|
+
return this.getPlainTextProperty("title", "title missing");
|
|
77
|
+
}
|
|
78
|
+
// In Notion, pages from the Database have "Name"s.
|
|
79
|
+
get name() {
|
|
80
|
+
return this.getPlainTextProperty("Name", "name missing");
|
|
81
|
+
}
|
|
82
|
+
explicitSlug() {
|
|
83
|
+
const explicitSlug = this.getPlainTextProperty("Slug", "");
|
|
84
|
+
if (explicitSlug) {
|
|
85
|
+
if (explicitSlug === "/")
|
|
86
|
+
return explicitSlug; // the root page
|
|
87
|
+
else
|
|
88
|
+
return ("/" +
|
|
89
|
+
encodeURIComponent(explicitSlug
|
|
90
|
+
.replace(/^\//, "")
|
|
91
|
+
// If for some reason someone types in a slug with special characters,
|
|
92
|
+
//we really don't want to see ugly entities in the URL, so first
|
|
93
|
+
// we replace a bunch of likely suspects with dashes. This will not
|
|
94
|
+
// adequately handle the case where there is one pag with slug:"foo-bar"
|
|
95
|
+
// and another with "foo?bar". Both will come out "foo-bar"
|
|
96
|
+
.replaceAll(" ", "-")
|
|
97
|
+
.replaceAll("?", "-")
|
|
98
|
+
.replaceAll("/", "-")
|
|
99
|
+
.replaceAll("#", "-")
|
|
100
|
+
.replaceAll("&", "-")
|
|
101
|
+
.replaceAll("%", "-")
|
|
102
|
+
// remove consecutive dashes
|
|
103
|
+
.replaceAll("--", "-")));
|
|
104
|
+
return undefined; // this page has no slug property
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
get slug() {
|
|
108
|
+
var _a;
|
|
109
|
+
return (_a = this.explicitSlug()) !== null && _a !== void 0 ? _a : "/" + this.pageId;
|
|
110
|
+
}
|
|
111
|
+
get hasExplicitSlug() {
|
|
112
|
+
return this.explicitSlug() !== undefined;
|
|
113
|
+
}
|
|
114
|
+
get keywords() {
|
|
115
|
+
return this.getPlainTextProperty("Keywords", "");
|
|
116
|
+
}
|
|
117
|
+
get status() {
|
|
118
|
+
return this.getSelectProperty("Status");
|
|
119
|
+
}
|
|
120
|
+
getPlainTextProperty(property, defaultIfEmpty) {
|
|
121
|
+
/* Notion strings look like this
|
|
122
|
+
"properties": {
|
|
123
|
+
"slug": {
|
|
124
|
+
"type": "rich_text",
|
|
125
|
+
...
|
|
126
|
+
"rich_text": [
|
|
127
|
+
{
|
|
128
|
+
...
|
|
129
|
+
"plain_text": "/",
|
|
130
|
+
}
|
|
131
|
+
]
|
|
132
|
+
},
|
|
133
|
+
"Name": {
|
|
134
|
+
"type": "title",
|
|
135
|
+
"title": [
|
|
136
|
+
{
|
|
137
|
+
...
|
|
138
|
+
"plain_text": "Intro",
|
|
139
|
+
}
|
|
140
|
+
]
|
|
141
|
+
*/
|
|
142
|
+
var _a;
|
|
143
|
+
//console.log("metadata:\n" + JSON.stringify(this.metadata, null, 2));
|
|
144
|
+
const p = (_a = this.metadata.properties) === null || _a === void 0 ? void 0 : _a[property];
|
|
145
|
+
//console.log(`prop ${property} = ${JSON.stringify(p)}`);
|
|
146
|
+
if (!p)
|
|
147
|
+
return defaultIfEmpty;
|
|
148
|
+
const textArray = p[p.type];
|
|
149
|
+
//console.log("textarray:" + JSON.stringify(textArray, null, 2));
|
|
150
|
+
return textArray && textArray.length
|
|
151
|
+
? textArray[0].plain_text
|
|
152
|
+
: defaultIfEmpty;
|
|
153
|
+
}
|
|
154
|
+
getSelectProperty(property) {
|
|
155
|
+
/* Notion select values look like this
|
|
156
|
+
"properties": {
|
|
157
|
+
"Status": {
|
|
158
|
+
"id": "oB~%3D",
|
|
159
|
+
"type": "select",
|
|
160
|
+
"select": {
|
|
161
|
+
"id": "1",
|
|
162
|
+
"name": "Ready For Review",
|
|
163
|
+
"color": "red"
|
|
164
|
+
}
|
|
165
|
+
},
|
|
166
|
+
*/
|
|
167
|
+
var _a, _b;
|
|
168
|
+
const p = (_a = this.metadata.properties) === null || _a === void 0 ? void 0 : _a[property];
|
|
169
|
+
if (!p) {
|
|
170
|
+
throw new Error(`missing ${property} in ${JSON.stringify(this.metadata, null, 2)}`);
|
|
171
|
+
return undefined;
|
|
172
|
+
}
|
|
173
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
|
|
174
|
+
return ((_b = p.select) === null || _b === void 0 ? void 0 : _b.name) || undefined;
|
|
175
|
+
}
|
|
176
|
+
getContentInfo(children) {
|
|
177
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
178
|
+
for (let i = 0; i < children.length; i++) {
|
|
179
|
+
children[i].order = i;
|
|
180
|
+
}
|
|
181
|
+
return {
|
|
182
|
+
childPageIdsAndOrder: children
|
|
183
|
+
.filter((b) => b.type === "child_page")
|
|
184
|
+
.map((b) => ({ id: b.id, order: b.order })),
|
|
185
|
+
linksPageIdsAndOrder: children
|
|
186
|
+
.filter((b) => b.type === "link_to_page")
|
|
187
|
+
.map((b) => ({ id: b.link_to_page.page_id, order: b.order })),
|
|
188
|
+
hasParagraphs: children.some(b => b.type === "paragraph" &&
|
|
189
|
+
b.paragraph.rich_text.length > 0),
|
|
190
|
+
};
|
|
191
|
+
});
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
exports.NotionPage = NotionPage;
|
|
@@ -0,0 +1,86 @@
|
|
|
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
|
+
};
|
|
34
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
35
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
36
|
+
};
|
|
37
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
38
|
+
exports.loadConfigAsync = void 0;
|
|
39
|
+
const Cosmic = __importStar(require("cosmiconfig"));
|
|
40
|
+
const default_docunotion_config_1 = __importDefault(require("./default.docunotion.config"));
|
|
41
|
+
const log_1 = require("../log");
|
|
42
|
+
const cosmiconfig_typescript_loader_1 = require("cosmiconfig-typescript-loader");
|
|
43
|
+
const process_1 = require("process");
|
|
44
|
+
// read the plugins from the config file
|
|
45
|
+
// and add them to the map
|
|
46
|
+
function loadConfigAsync() {
|
|
47
|
+
var _a, _b, _c, _d, _e;
|
|
48
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
49
|
+
let config = default_docunotion_config_1.default;
|
|
50
|
+
try {
|
|
51
|
+
const cosmic = Cosmic.cosmiconfig("docu-notion", {
|
|
52
|
+
loaders: {
|
|
53
|
+
".ts": (0, cosmiconfig_typescript_loader_1.TypeScriptLoader)(),
|
|
54
|
+
},
|
|
55
|
+
searchPlaces: [`docu-notion.config.ts`],
|
|
56
|
+
});
|
|
57
|
+
const found = yield cosmic.search();
|
|
58
|
+
if (found) {
|
|
59
|
+
(0, log_1.verbose)(`Loading config from ${found.filepath}`);
|
|
60
|
+
}
|
|
61
|
+
else {
|
|
62
|
+
(0, log_1.verbose)(`Did not find configuration file, using defaults.`);
|
|
63
|
+
}
|
|
64
|
+
const pluginsWithInitializers = (_b = (_a = found === null || found === void 0 ? void 0 : found.config) === null || _a === void 0 ? void 0 : _a.plugins) === null || _b === void 0 ? void 0 : _b.filter((p) => p.init !== undefined);
|
|
65
|
+
const initializers = pluginsWithInitializers === null || pluginsWithInitializers === void 0 ? void 0 : pluginsWithInitializers.map((p) => () => p.init(p));
|
|
66
|
+
yield Promise.all(initializers || []);
|
|
67
|
+
(_d = (_c = found === null || found === void 0 ? void 0 : found.config) === null || _c === void 0 ? void 0 : _c.plugins) === null || _d === void 0 ? void 0 : _d.forEach((plugin) => __awaiter(this, void 0, void 0, function* () {
|
|
68
|
+
if (plugin.init !== undefined) {
|
|
69
|
+
(0, log_1.verbose)(`Initializing plugin ${plugin.name}...`);
|
|
70
|
+
yield plugin.init(plugin);
|
|
71
|
+
}
|
|
72
|
+
}));
|
|
73
|
+
// for now, all we have is plugins
|
|
74
|
+
config = {
|
|
75
|
+
plugins: default_docunotion_config_1.default.plugins.concat(((_e = found === null || found === void 0 ? void 0 : found.config) === null || _e === void 0 ? void 0 : _e.plugins) || []),
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
catch (e) {
|
|
79
|
+
(0, log_1.error)(e.message);
|
|
80
|
+
(0, process_1.exit)(1);
|
|
81
|
+
}
|
|
82
|
+
(0, log_1.verbose)(`Active plugins: [${config.plugins.map(p => p.name).join(", ")}]`);
|
|
83
|
+
return config;
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
exports.loadConfigAsync = loadConfigAsync;
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const embedTweaks_1 = require("../plugins/embedTweaks");
|
|
4
|
+
const images_1 = require("../images");
|
|
5
|
+
const internalLinks_1 = require("../plugins/internalLinks");
|
|
6
|
+
const CalloutTransformer_1 = require("../plugins/CalloutTransformer");
|
|
7
|
+
const ColumnListTransformer_1 = require("../plugins/ColumnListTransformer");
|
|
8
|
+
const ColumnTransformer_1 = require("../plugins/ColumnTransformer");
|
|
9
|
+
const EscapeHtmlBlockModifier_1 = require("../plugins/EscapeHtmlBlockModifier");
|
|
10
|
+
const HeadingTransformer_1 = require("../plugins/HeadingTransformer");
|
|
11
|
+
const NumberedListTransformer_1 = require("../plugins/NumberedListTransformer");
|
|
12
|
+
const TableTransformer_1 = require("../plugins/TableTransformer");
|
|
13
|
+
const externalLinks_1 = require("../plugins/externalLinks");
|
|
14
|
+
const defaultConfig = {
|
|
15
|
+
plugins: [
|
|
16
|
+
// Notion "Block" JSON modifiers
|
|
17
|
+
EscapeHtmlBlockModifier_1.standardEscapeHtmlBlockModifier,
|
|
18
|
+
HeadingTransformer_1.standardHeadingTransformer,
|
|
19
|
+
// Notion to Markdown transformers. Most things get transformed correctly by the notion-to-markdown library,
|
|
20
|
+
// but some things need special handling.
|
|
21
|
+
ColumnTransformer_1.standardColumnTransformer,
|
|
22
|
+
ColumnListTransformer_1.standardColumnListTransformer,
|
|
23
|
+
images_1.standardImageTransformer,
|
|
24
|
+
CalloutTransformer_1.standardCalloutTransformer,
|
|
25
|
+
TableTransformer_1.standardTableTransformer,
|
|
26
|
+
NumberedListTransformer_1.standardNumberedListTransformer,
|
|
27
|
+
// Link modifiers, which are special because they can read metadata from all the pages in order to figure out the correct url
|
|
28
|
+
internalLinks_1.standardInternalLinkConversion,
|
|
29
|
+
externalLinks_1.standardExternalLinkConversion,
|
|
30
|
+
// Regexps plus javascript `import`s that operate on the Markdown output
|
|
31
|
+
embedTweaks_1.imgurGifEmbed,
|
|
32
|
+
embedTweaks_1.gifEmbed,
|
|
33
|
+
embedTweaks_1.youtubeEmbed,
|
|
34
|
+
embedTweaks_1.vimeoEmbed,
|
|
35
|
+
],
|
|
36
|
+
};
|
|
37
|
+
exports.default = defaultConfig;
|
package/dist/images.d.ts
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/// <reference types="node" />
|
|
2
|
+
import { FileTypeResult } from "file-type";
|
|
3
|
+
import { ListBlockChildrenResponseResult } from "notion-to-md/build/types";
|
|
4
|
+
import { IPlugin } from "./plugins/pluginTypes";
|
|
5
|
+
export type ImageSet = {
|
|
6
|
+
primaryUrl: string;
|
|
7
|
+
caption?: string;
|
|
8
|
+
localizedUrls: Array<{
|
|
9
|
+
iso632Code: string;
|
|
10
|
+
url: string;
|
|
11
|
+
}>;
|
|
12
|
+
pathToParentDocument?: string;
|
|
13
|
+
relativePathToParentDocument?: string;
|
|
14
|
+
primaryBuffer?: Buffer;
|
|
15
|
+
fileType?: FileTypeResult;
|
|
16
|
+
primaryFileOutputPath?: string;
|
|
17
|
+
outputFileName?: string;
|
|
18
|
+
filePathToUseInMarkdown?: string;
|
|
19
|
+
};
|
|
20
|
+
export declare function initImageHandling(prefix: string, outputPath: string, incomingLocales: string[]): Promise<void>;
|
|
21
|
+
export declare const standardImageTransformer: IPlugin;
|
|
22
|
+
export declare function markdownToMDImageTransformer(block: ListBlockChildrenResponseResult, fullPathToDirectoryContainingMarkdown: string, relativePathToThisPage: string): Promise<string>;
|
|
23
|
+
export declare function parseImageBlock(image: any): ImageSet;
|
|
24
|
+
export declare function cleanupOldImages(): Promise<void>;
|