@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,199 @@
|
|
|
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 CalloutTransformer_1 = require("./CalloutTransformer");
|
|
14
|
+
const externalLinks_1 = require("./externalLinks");
|
|
15
|
+
const internalLinks_1 = require("./internalLinks");
|
|
16
|
+
let block;
|
|
17
|
+
beforeEach(() => {
|
|
18
|
+
block = {
|
|
19
|
+
has_children: false,
|
|
20
|
+
archived: false,
|
|
21
|
+
type: "callout",
|
|
22
|
+
callout: {
|
|
23
|
+
rich_text: [
|
|
24
|
+
{
|
|
25
|
+
type: "text",
|
|
26
|
+
text: { content: "This is information callout", link: null },
|
|
27
|
+
annotations: {
|
|
28
|
+
bold: false,
|
|
29
|
+
italic: false,
|
|
30
|
+
strikethrough: false,
|
|
31
|
+
underline: false,
|
|
32
|
+
code: false,
|
|
33
|
+
color: "default",
|
|
34
|
+
},
|
|
35
|
+
plain_text: "This is the callout",
|
|
36
|
+
href: null,
|
|
37
|
+
},
|
|
38
|
+
],
|
|
39
|
+
icon: { type: "emoji", emoji: "ℹ️" },
|
|
40
|
+
color: "gray_background",
|
|
41
|
+
},
|
|
42
|
+
};
|
|
43
|
+
});
|
|
44
|
+
test("smoketest callout", () => __awaiter(void 0, void 0, void 0, function* () {
|
|
45
|
+
const config = { plugins: [CalloutTransformer_1.standardCalloutTransformer] };
|
|
46
|
+
block.callout.icon.emoji = "ℹ️";
|
|
47
|
+
let results = yield (0, pluginTestRun_1.blocksToMarkdown)(config, [
|
|
48
|
+
block,
|
|
49
|
+
]);
|
|
50
|
+
expect(results).toContain("\n:::note\n\nThis is the callout\n\n:::\n");
|
|
51
|
+
block.callout.icon.emoji = "❗";
|
|
52
|
+
results = yield (0, pluginTestRun_1.blocksToMarkdown)(config, [block]);
|
|
53
|
+
expect(results).toContain(":::info");
|
|
54
|
+
}));
|
|
55
|
+
test("external link inside callout, bold preserved", () => __awaiter(void 0, void 0, void 0, function* () {
|
|
56
|
+
const config = {
|
|
57
|
+
plugins: [
|
|
58
|
+
CalloutTransformer_1.standardCalloutTransformer,
|
|
59
|
+
internalLinks_1.standardInternalLinkConversion,
|
|
60
|
+
externalLinks_1.standardExternalLinkConversion,
|
|
61
|
+
],
|
|
62
|
+
};
|
|
63
|
+
const results = yield (0, pluginTestRun_1.blocksToMarkdown)(config, [
|
|
64
|
+
{
|
|
65
|
+
type: "callout",
|
|
66
|
+
callout: {
|
|
67
|
+
rich_text: [
|
|
68
|
+
{
|
|
69
|
+
type: "text",
|
|
70
|
+
text: { content: "Callouts inline ", link: null },
|
|
71
|
+
annotations: {
|
|
72
|
+
bold: false,
|
|
73
|
+
italic: false,
|
|
74
|
+
strikethrough: false,
|
|
75
|
+
underline: false,
|
|
76
|
+
code: false,
|
|
77
|
+
color: "default",
|
|
78
|
+
},
|
|
79
|
+
plain_text: "Callouts inline ",
|
|
80
|
+
href: null,
|
|
81
|
+
},
|
|
82
|
+
{
|
|
83
|
+
type: "text",
|
|
84
|
+
text: {
|
|
85
|
+
content: "great page",
|
|
86
|
+
link: { url: `https://github.com` },
|
|
87
|
+
},
|
|
88
|
+
annotations: {
|
|
89
|
+
bold: true,
|
|
90
|
+
italic: false,
|
|
91
|
+
strikethrough: false,
|
|
92
|
+
underline: false,
|
|
93
|
+
code: false,
|
|
94
|
+
color: "default",
|
|
95
|
+
},
|
|
96
|
+
plain_text: "great page",
|
|
97
|
+
href: `https://github.com`,
|
|
98
|
+
},
|
|
99
|
+
{
|
|
100
|
+
type: "text",
|
|
101
|
+
text: { content: ".", link: null },
|
|
102
|
+
annotations: {
|
|
103
|
+
bold: false,
|
|
104
|
+
italic: false,
|
|
105
|
+
strikethrough: false,
|
|
106
|
+
underline: false,
|
|
107
|
+
code: false,
|
|
108
|
+
color: "default",
|
|
109
|
+
},
|
|
110
|
+
plain_text: ".",
|
|
111
|
+
href: null,
|
|
112
|
+
},
|
|
113
|
+
],
|
|
114
|
+
icon: { type: "emoji", emoji: "⚠️" },
|
|
115
|
+
color: "gray_background",
|
|
116
|
+
},
|
|
117
|
+
},
|
|
118
|
+
]);
|
|
119
|
+
expect(results.trim()).toBe(`:::caution
|
|
120
|
+
|
|
121
|
+
Callouts inline [**great page**](https://github.com).
|
|
122
|
+
|
|
123
|
+
:::`);
|
|
124
|
+
}));
|
|
125
|
+
test("internal link inside callout, bold preserved", () => __awaiter(void 0, void 0, void 0, function* () {
|
|
126
|
+
const config = {
|
|
127
|
+
plugins: [
|
|
128
|
+
CalloutTransformer_1.standardCalloutTransformer,
|
|
129
|
+
internalLinks_1.standardInternalLinkConversion,
|
|
130
|
+
externalLinks_1.standardExternalLinkConversion,
|
|
131
|
+
],
|
|
132
|
+
};
|
|
133
|
+
const slugTargetPage = (0, pluginTestRun_1.makeSamplePageObject)({
|
|
134
|
+
slug: "hello-world",
|
|
135
|
+
name: "Hello World",
|
|
136
|
+
id: "123",
|
|
137
|
+
});
|
|
138
|
+
const results = yield (0, pluginTestRun_1.blocksToMarkdown)(config, [
|
|
139
|
+
{
|
|
140
|
+
type: "callout",
|
|
141
|
+
callout: {
|
|
142
|
+
rich_text: [
|
|
143
|
+
{
|
|
144
|
+
type: "text",
|
|
145
|
+
text: { content: "Callouts inline ", link: null },
|
|
146
|
+
annotations: {
|
|
147
|
+
bold: false,
|
|
148
|
+
italic: false,
|
|
149
|
+
strikethrough: false,
|
|
150
|
+
underline: false,
|
|
151
|
+
code: false,
|
|
152
|
+
color: "default",
|
|
153
|
+
},
|
|
154
|
+
plain_text: "Callouts inline ",
|
|
155
|
+
href: null,
|
|
156
|
+
},
|
|
157
|
+
{
|
|
158
|
+
type: "text",
|
|
159
|
+
text: {
|
|
160
|
+
content: "great page",
|
|
161
|
+
link: { url: `/123#456` },
|
|
162
|
+
},
|
|
163
|
+
annotations: {
|
|
164
|
+
bold: true,
|
|
165
|
+
italic: false,
|
|
166
|
+
strikethrough: false,
|
|
167
|
+
underline: false,
|
|
168
|
+
code: false,
|
|
169
|
+
color: "default",
|
|
170
|
+
},
|
|
171
|
+
plain_text: "great page",
|
|
172
|
+
href: `/123#456`,
|
|
173
|
+
},
|
|
174
|
+
{
|
|
175
|
+
type: "text",
|
|
176
|
+
text: { content: ".", link: null },
|
|
177
|
+
annotations: {
|
|
178
|
+
bold: false,
|
|
179
|
+
italic: false,
|
|
180
|
+
strikethrough: false,
|
|
181
|
+
underline: false,
|
|
182
|
+
code: false,
|
|
183
|
+
color: "default",
|
|
184
|
+
},
|
|
185
|
+
plain_text: " the end.",
|
|
186
|
+
href: null,
|
|
187
|
+
},
|
|
188
|
+
],
|
|
189
|
+
icon: { type: "emoji", emoji: "⚠️" },
|
|
190
|
+
color: "gray_background",
|
|
191
|
+
},
|
|
192
|
+
},
|
|
193
|
+
], [slugTargetPage]);
|
|
194
|
+
expect(results.trim()).toBe(`:::caution
|
|
195
|
+
|
|
196
|
+
Callouts inline [**great page**](/hello-world#456) the end.
|
|
197
|
+
|
|
198
|
+
:::`);
|
|
199
|
+
}));
|
|
@@ -0,0 +1,34 @@
|
|
|
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.standardColumnListTransformer = void 0;
|
|
13
|
+
function notionColumnListToMarkdown(notionToMarkdown, getBlockChildren, block) {
|
|
14
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
15
|
+
// Enhance: The @notionhq/client, which uses the official API, cannot yet get at column formatting information (column_ratio)
|
|
16
|
+
// However https://github1s.com/NotionX/react-notion-x/blob/master/packages/react-notion-x/src/block.tsx#L528 can get it.
|
|
17
|
+
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
|
|
18
|
+
if (!has_children)
|
|
19
|
+
return "";
|
|
20
|
+
const column_list_children = yield getBlockChildren(id);
|
|
21
|
+
const column_list_promise = column_list_children.map((column) => __awaiter(this, void 0, void 0, function* () { return yield notionToMarkdown.blockToMarkdown(column); }));
|
|
22
|
+
const columns = yield Promise.all(column_list_promise);
|
|
23
|
+
return `<div class='notion-row'>\n${columns.join("\n\n")}\n</div>`;
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
exports.standardColumnListTransformer = {
|
|
27
|
+
name: "standardColumnListTransformer",
|
|
28
|
+
notionToMarkdownTransforms: [
|
|
29
|
+
{
|
|
30
|
+
type: "column_list",
|
|
31
|
+
getStringFromBlock: (context, block) => notionColumnListToMarkdown(context.notionToMarkdown, context.getBlockChildren, block),
|
|
32
|
+
},
|
|
33
|
+
],
|
|
34
|
+
};
|
|
@@ -0,0 +1,67 @@
|
|
|
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.standardColumnTransformer = void 0;
|
|
13
|
+
const notion_client_1 = require("notion-client");
|
|
14
|
+
exports.standardColumnTransformer = {
|
|
15
|
+
name: "standardColumnTransformer",
|
|
16
|
+
notionToMarkdownTransforms: [
|
|
17
|
+
{
|
|
18
|
+
type: "column",
|
|
19
|
+
getStringFromBlock: (context, block) => notionColumnToMarkdown(context.notionToMarkdown, context.getBlockChildren, block),
|
|
20
|
+
},
|
|
21
|
+
],
|
|
22
|
+
};
|
|
23
|
+
// This runs when notion-to-md encounters a column block
|
|
24
|
+
function notionColumnToMarkdown(notionToMarkdown, getBlockChildren, block) {
|
|
25
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
26
|
+
//console.log(JSON.stringify(block));
|
|
27
|
+
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
|
|
28
|
+
if (!has_children)
|
|
29
|
+
return "";
|
|
30
|
+
const children = yield getBlockChildren(id);
|
|
31
|
+
const childrenPromises = children.map((column) => __awaiter(this, void 0, void 0, function* () { return yield notionToMarkdown.blockToMarkdown(column); }));
|
|
32
|
+
const childrenStrings = yield Promise.all(childrenPromises);
|
|
33
|
+
const columnWidth = yield getColumnWidth(block);
|
|
34
|
+
// note: it would look better in the markup with \n, but that
|
|
35
|
+
// causes notion-to-md to give us ":::A" instead of \n for some reason.
|
|
36
|
+
return (`<div class='notion-column' style={{width: '${columnWidth}'}}>\n\n${childrenStrings.join("\n\n")}\n\n</div>` +
|
|
37
|
+
// Spacer between columns. CSS takes care of hiding this for the last column
|
|
38
|
+
// and when the screen is too narrow for multiple columns.
|
|
39
|
+
`<div className='notion-spacer' />`);
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
// The official API doesn't give us access to the format information, including column_ratio.
|
|
43
|
+
// So we use 'notion-client' which uses the unofficial API.
|
|
44
|
+
// Once the official API gives us access to the format information, we can remove this
|
|
45
|
+
// and the 'notion-client' dependency.
|
|
46
|
+
// This logic was mostly taken from react-notion-x (sister project of notion-client).
|
|
47
|
+
function getColumnWidth(block) {
|
|
48
|
+
var _a, _b, _c, _d;
|
|
49
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
50
|
+
const unofficialNotionClient = new notion_client_1.NotionAPI();
|
|
51
|
+
const blockId = block.id;
|
|
52
|
+
// Yes, it is odd to call 'getPage' for a block, but that's how we access the format info.
|
|
53
|
+
const recordMap = yield unofficialNotionClient.getPage(blockId);
|
|
54
|
+
const blockResult = recordMap.block[blockId];
|
|
55
|
+
// ENHANCE: could we use https://github.com/NotionX/react-notion-x/tree/master/packages/notion-types
|
|
56
|
+
// to get away from "any", which might be particularly helpful in the future
|
|
57
|
+
// since this is using the unofficial (reverse engineered?) API.
|
|
58
|
+
const columnFormat = (_a = blockResult === null || blockResult === void 0 ? void 0 : blockResult.value) === null || _a === void 0 ? void 0 : _a.format;
|
|
59
|
+
const columnRatio = (columnFormat === null || columnFormat === void 0 ? void 0 : columnFormat.column_ratio) || 0.5;
|
|
60
|
+
const parentBlock = (_c = recordMap.block[(_b = blockResult === null || blockResult === void 0 ? void 0 : blockResult.value) === null || _b === void 0 ? void 0 : _b.parent_id]) === null || _c === void 0 ? void 0 : _c.value;
|
|
61
|
+
// I'm not sure why we wouldn't get a parent, but the react-notion-x has
|
|
62
|
+
// this fallback to a guess based on the columnRatio.
|
|
63
|
+
const columnCount = ((_d = parentBlock === null || parentBlock === void 0 ? void 0 : parentBlock.content) === null || _d === void 0 ? void 0 : _d.length) || Math.max(2, Math.ceil(1.0 / columnRatio));
|
|
64
|
+
const spacerWidth = `min(32px, 4vw)`; // This matches the value in css for 'notion-spacer'.
|
|
65
|
+
return `calc((100% - (${spacerWidth} * ${columnCount - 1})) * ${columnRatio})`;
|
|
66
|
+
});
|
|
67
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.standardEscapeHtmlBlockModifier = void 0;
|
|
4
|
+
exports.standardEscapeHtmlBlockModifier = {
|
|
5
|
+
name: "standardEscapeHtmlBlockModifier",
|
|
6
|
+
notionBlockModifications: [
|
|
7
|
+
{
|
|
8
|
+
modify: (block) => {
|
|
9
|
+
escapeHtml(block);
|
|
10
|
+
},
|
|
11
|
+
},
|
|
12
|
+
],
|
|
13
|
+
};
|
|
14
|
+
function escapeHtml(block) {
|
|
15
|
+
var _a, _b;
|
|
16
|
+
//console.log("escapeHtml called with\n", JSON.stringify(block, null, 2));
|
|
17
|
+
const blockContent = block[block.type]; // e.g. block["paragraph"] gives an array of the strings that make up the paragraph
|
|
18
|
+
if ((_a = blockContent.rich_text) === null || _a === void 0 ? void 0 : _a.length) {
|
|
19
|
+
for (let i = 0; i < blockContent.rich_text.length; i++) {
|
|
20
|
+
const rt = blockContent.rich_text[i];
|
|
21
|
+
// See https://github.com/sillsdev/docu-notion/issues/21.
|
|
22
|
+
// For now, we just do a simple replace of < an > with < and >
|
|
23
|
+
// but only if the text will not be displayed as code.
|
|
24
|
+
// If it will be displayed as code,
|
|
25
|
+
// a) nothing will be trying to parse it, so it is safe.
|
|
26
|
+
// b) at no point does anything interpret the escaped character **back** to html;
|
|
27
|
+
// so it will be displayed as "<" or ">".
|
|
28
|
+
// We may have to add more complex logic here in the future if we
|
|
29
|
+
// want to start letting html through which we **do** want to parse.
|
|
30
|
+
// For example, we could assume that text in a valid html structure should be parsed.
|
|
31
|
+
if ((rt === null || rt === void 0 ? void 0 : rt.plain_text) &&
|
|
32
|
+
block.type !== "code" &&
|
|
33
|
+
rt.type !== "code" &&
|
|
34
|
+
!((_b = rt.annotations) === null || _b === void 0 ? void 0 : _b.code)) {
|
|
35
|
+
rt.plain_text = rt.plain_text
|
|
36
|
+
.replaceAll("<", "<")
|
|
37
|
+
.replaceAll(">", ">");
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,130 @@
|
|
|
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 EscapeHtmlBlockModifier_1 = require("./EscapeHtmlBlockModifier");
|
|
14
|
+
let blocks;
|
|
15
|
+
beforeEach(() => {
|
|
16
|
+
blocks = [
|
|
17
|
+
{
|
|
18
|
+
object: "block",
|
|
19
|
+
id: "503533c3-c1cc-4f5f-89bc-95472486d16c",
|
|
20
|
+
parent: {
|
|
21
|
+
type: "page_id",
|
|
22
|
+
page_id: "a623852e-3552-40cf-89a9-7e3adbc07e9c",
|
|
23
|
+
},
|
|
24
|
+
created_time: "2023-01-12T20:25:00.000Z",
|
|
25
|
+
last_edited_time: "2023-01-12T20:36:00.000Z",
|
|
26
|
+
created_by: {
|
|
27
|
+
object: "user",
|
|
28
|
+
id: "11fb7f16-0560-4aee-ab88-ed75a850cfc4",
|
|
29
|
+
},
|
|
30
|
+
last_edited_by: {
|
|
31
|
+
object: "user",
|
|
32
|
+
id: "11fb7f16-0560-4aee-ab88-ed75a850cfc4",
|
|
33
|
+
},
|
|
34
|
+
has_children: false,
|
|
35
|
+
archived: false,
|
|
36
|
+
type: "paragraph",
|
|
37
|
+
paragraph: {
|
|
38
|
+
rich_text: [
|
|
39
|
+
{
|
|
40
|
+
type: "text",
|
|
41
|
+
text: { content: "2 < 3 > 1", link: null },
|
|
42
|
+
annotations: {
|
|
43
|
+
bold: true,
|
|
44
|
+
italic: true,
|
|
45
|
+
strikethrough: false,
|
|
46
|
+
underline: false,
|
|
47
|
+
code: false,
|
|
48
|
+
color: "yellow",
|
|
49
|
+
},
|
|
50
|
+
plain_text: "2 < 3 > 1",
|
|
51
|
+
href: null,
|
|
52
|
+
},
|
|
53
|
+
],
|
|
54
|
+
color: "default",
|
|
55
|
+
},
|
|
56
|
+
},
|
|
57
|
+
{
|
|
58
|
+
object: "block",
|
|
59
|
+
id: "5bd7b925-9d87-435a-bbfb-df97e07e7d39",
|
|
60
|
+
parent: {
|
|
61
|
+
type: "page_id",
|
|
62
|
+
page_id: "a623852e-3552-40cf-89a9-7e3adbc07e9c",
|
|
63
|
+
},
|
|
64
|
+
created_time: "2023-01-12T20:26:00.000Z",
|
|
65
|
+
last_edited_time: "2023-01-12T20:36:00.000Z",
|
|
66
|
+
created_by: {
|
|
67
|
+
object: "user",
|
|
68
|
+
id: "11fb7f16-0560-4aee-ab88-ed75a850cfc4",
|
|
69
|
+
},
|
|
70
|
+
last_edited_by: {
|
|
71
|
+
object: "user",
|
|
72
|
+
id: "11fb7f16-0560-4aee-ab88-ed75a850cfc4",
|
|
73
|
+
},
|
|
74
|
+
has_children: false,
|
|
75
|
+
archived: false,
|
|
76
|
+
type: "paragraph",
|
|
77
|
+
paragraph: {
|
|
78
|
+
rich_text: [
|
|
79
|
+
{
|
|
80
|
+
type: "text",
|
|
81
|
+
text: { content: "This is code: if(1 < 3)", link: null },
|
|
82
|
+
annotations: {
|
|
83
|
+
bold: false,
|
|
84
|
+
italic: false,
|
|
85
|
+
strikethrough: false,
|
|
86
|
+
underline: false,
|
|
87
|
+
code: true,
|
|
88
|
+
color: "default",
|
|
89
|
+
},
|
|
90
|
+
plain_text: "This is code: if(1 < 3)",
|
|
91
|
+
href: null,
|
|
92
|
+
},
|
|
93
|
+
],
|
|
94
|
+
color: "default",
|
|
95
|
+
},
|
|
96
|
+
},
|
|
97
|
+
{
|
|
98
|
+
object: "block",
|
|
99
|
+
id: "bdd2569a-8b0d-450e-ba03-4315e5f726b8",
|
|
100
|
+
parent: {
|
|
101
|
+
type: "page_id",
|
|
102
|
+
page_id: "a623852e-3552-40cf-89a9-7e3adbc07e9c",
|
|
103
|
+
},
|
|
104
|
+
created_time: "2023-01-12T20:27:00.000Z",
|
|
105
|
+
last_edited_time: "2023-01-12T20:27:00.000Z",
|
|
106
|
+
created_by: {
|
|
107
|
+
object: "user",
|
|
108
|
+
id: "11fb7f16-0560-4aee-ab88-ed75a850cfc4",
|
|
109
|
+
},
|
|
110
|
+
last_edited_by: {
|
|
111
|
+
object: "user",
|
|
112
|
+
id: "11fb7f16-0560-4aee-ab88-ed75a850cfc4",
|
|
113
|
+
},
|
|
114
|
+
has_children: false,
|
|
115
|
+
archived: false,
|
|
116
|
+
type: "paragraph",
|
|
117
|
+
paragraph: { rich_text: [], color: "default" },
|
|
118
|
+
},
|
|
119
|
+
];
|
|
120
|
+
});
|
|
121
|
+
test("smoketest ", () => __awaiter(void 0, void 0, void 0, function* () {
|
|
122
|
+
const config = { plugins: [EscapeHtmlBlockModifier_1.standardEscapeHtmlBlockModifier] };
|
|
123
|
+
let results = yield (0, pluginTestRun_1.blocksToMarkdown)(config, blocks);
|
|
124
|
+
// shouldn't escape inside a code block
|
|
125
|
+
expect(results).toContain("This is code: if(1 < 3)");
|
|
126
|
+
// should escape outside a code block
|
|
127
|
+
expect(results).toContain("2 < 3 > 1");
|
|
128
|
+
// that line is also bold and italic
|
|
129
|
+
expect(results).toContain("_**2 < 3 > 1**_");
|
|
130
|
+
}));
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,46 @@
|
|
|
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 HeadingTransformer_1 = require("./HeadingTransformer");
|
|
14
|
+
test("Adds anchor to headings", () => __awaiter(void 0, void 0, void 0, function* () {
|
|
15
|
+
//setLogLevel("verbose");
|
|
16
|
+
const headingBlockId = "86f746f4-1c79-4ba1-a2f6-a1d59c2f9d23";
|
|
17
|
+
const config = { plugins: [HeadingTransformer_1.standardHeadingTransformer] };
|
|
18
|
+
const result = yield (0, pluginTestRun_1.blocksToMarkdown)(config, [
|
|
19
|
+
{
|
|
20
|
+
object: "block",
|
|
21
|
+
id: headingBlockId,
|
|
22
|
+
type: "heading_1",
|
|
23
|
+
heading_1: {
|
|
24
|
+
rich_text: [
|
|
25
|
+
{
|
|
26
|
+
type: "text",
|
|
27
|
+
text: { content: "Heading One", link: null },
|
|
28
|
+
annotations: {
|
|
29
|
+
bold: false,
|
|
30
|
+
italic: false,
|
|
31
|
+
strikethrough: false,
|
|
32
|
+
underline: false,
|
|
33
|
+
code: false,
|
|
34
|
+
color: "default",
|
|
35
|
+
},
|
|
36
|
+
plain_text: "Heading One",
|
|
37
|
+
href: null,
|
|
38
|
+
},
|
|
39
|
+
],
|
|
40
|
+
is_toggleable: false,
|
|
41
|
+
color: "default",
|
|
42
|
+
},
|
|
43
|
+
},
|
|
44
|
+
]);
|
|
45
|
+
expect(result.trim()).toBe(`# Heading One {#${headingBlockId.replaceAll("-", "")}}`);
|
|
46
|
+
}));
|
|
@@ -0,0 +1,63 @@
|
|
|
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.standardHeadingTransformer = void 0;
|
|
13
|
+
const log_1 = require("../log");
|
|
14
|
+
// Makes links to headings work in docusaurus
|
|
15
|
+
// https://github.com/sillsdev/docu-notion/issues/20
|
|
16
|
+
function headingTransformer(notionToMarkdown, block) {
|
|
17
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
18
|
+
// First, remove the prefix we added to the heading type
|
|
19
|
+
block.type = block.type.replace("DN_", "");
|
|
20
|
+
const markdown = yield notionToMarkdown.blockToMarkdown(block);
|
|
21
|
+
(0, log_1.logDebug)("headingTransformer, markdown of a heading before adding id", markdown);
|
|
22
|
+
// To make heading links work in docusaurus, we append an id. E.g.
|
|
23
|
+
// ### Hello World {#my-explicit-id}
|
|
24
|
+
// See https://docusaurus.io/docs/markdown-features/toc#heading-ids.
|
|
25
|
+
// For some reason, inline links come in without the dashes, so we have to strip
|
|
26
|
+
// dashes here to match them.
|
|
27
|
+
//console.log("block.id", block.id)
|
|
28
|
+
const blockIdWithoutDashes = block.id.replaceAll("-", "");
|
|
29
|
+
// Finally, append the block id so that it can be the target of a link.
|
|
30
|
+
return `${markdown} {#${blockIdWithoutDashes}}`;
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
exports.standardHeadingTransformer = {
|
|
34
|
+
name: "standardHeadingTransformer",
|
|
35
|
+
// AP wrote: We have to do this because if
|
|
36
|
+
// we simply set a custom transformer to heading_n, it will keep
|
|
37
|
+
// recursively calling this code, with blockToMarkdown using the custom transformer
|
|
38
|
+
// over and over. Instead, we want blockToMarkdown to give us the normal
|
|
39
|
+
// result, to which we will append the block ID to enable heading links.
|
|
40
|
+
notionBlockModifications: [
|
|
41
|
+
{
|
|
42
|
+
modify: (block) => {
|
|
43
|
+
// "as any" needed because we're putting a value in that is not allowed by the real type
|
|
44
|
+
block.type = block.type.replace("heading", "DN_heading");
|
|
45
|
+
},
|
|
46
|
+
},
|
|
47
|
+
],
|
|
48
|
+
// then when it comes time to do markdown conversions, we'll get called for each of these
|
|
49
|
+
notionToMarkdownTransforms: [
|
|
50
|
+
{
|
|
51
|
+
type: "DN_heading_1",
|
|
52
|
+
getStringFromBlock: (context, block) => headingTransformer(context.notionToMarkdown, block),
|
|
53
|
+
},
|
|
54
|
+
{
|
|
55
|
+
type: "DN_heading_2",
|
|
56
|
+
getStringFromBlock: (context, block) => headingTransformer(context.notionToMarkdown, block),
|
|
57
|
+
},
|
|
58
|
+
{
|
|
59
|
+
type: "DN_heading_3",
|
|
60
|
+
getStringFromBlock: (context, block) => headingTransformer(context.notionToMarkdown, block),
|
|
61
|
+
},
|
|
62
|
+
],
|
|
63
|
+
};
|