@tinacms/mdx 0.0.0-20220718185604 → 0.60.3
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/dist/index.cjs +887 -738
- package/dist/index.es.js +546 -406
- package/dist/{parse/plate-spec.d.ts → index.js} +4 -2
- package/dist/mdx.es.js +1092 -0
- package/dist/mdx.umd.js +1097 -0
- package/dist/parse/acorn.d.ts +2 -3
- package/dist/parse/acorn.js +201 -0
- package/dist/parse/index.d.ts +8 -2
- package/dist/parse/index.js +144 -0
- package/dist/parse/mdx.js +75 -0
- package/dist/parse/plate.d.ts +15 -2
- package/dist/parse/plate.js +1 -0
- package/dist/parse/remarkToPlate.d.ts +16 -1
- package/dist/parse/remarkToPlate.js +380 -0
- package/dist/stringify/acorn.d.ts +7 -2
- package/dist/stringify/acorn.js +241 -0
- package/dist/stringify/index.d.ts +15 -0
- package/dist/stringify/index.js +195 -0
- package/dist/stringify/marks.js +250 -0
- package/dist/tests/autotest/_config.d.ts +4 -0
- package/dist/tests/autotest/_config.js +159 -0
- package/dist/tests/autotest/_runner.test.d.ts +1 -0
- package/dist/tests/autotest/_runner.test.js +77 -0
- package/dist/tests/autotest/autoformat block elements in list items.test.d.ts +1 -0
- package/dist/tests/autotest/autoformat block elements in list items.test.js +33 -0
- package/dist/tests/autotest/autoformat blockquote.result.test.d.ts +1 -0
- package/dist/tests/autotest/autoformat blockquote.result.test.js +18 -0
- package/dist/tests/autotest/autoformat blockquote.test.d.ts +1 -0
- package/dist/tests/autotest/autoformat blockquote.test.js +18 -0
- package/dist/tests/autotest/autoformat list item.test.d.ts +1 -0
- package/dist/tests/autotest/autoformat list item.test.js +31 -0
- package/dist/tests/autotest/autoformat mdx with nested null children.test.d.ts +1 -0
- package/dist/tests/autotest/autoformat mdx with nested null children.test.js +23 -0
- package/dist/tests/autotest/autoformat syntax changes.test.d.ts +1 -0
- package/dist/tests/autotest/autoformat syntax changes.test.js +90 -0
- package/dist/tests/autotest/blockquote.test.d.ts +1 -0
- package/dist/tests/autotest/blockquote.test.js +17 -0
- package/dist/tests/autotest/break.test.d.ts +1 -0
- package/dist/tests/autotest/break.test.js +26 -0
- package/dist/tests/autotest/code block.test.d.ts +1 -0
- package/dist/tests/autotest/code block.test.js +27 -0
- package/dist/tests/autotest/image.test.d.ts +1 -0
- package/dist/tests/autotest/image.test.js +52 -0
- package/dist/tests/autotest/invalid mdx with a closing tag.test.d.ts +1 -0
- package/dist/tests/autotest/invalid mdx with a closing tag.test.js +27 -0
- package/dist/tests/autotest/invalid mdx with a const expression.test.d.ts +1 -0
- package/dist/tests/autotest/invalid mdx with a const expression.test.js +27 -0
- package/dist/tests/autotest/invalid mdx with an expression {{}}.test.d.ts +1 -0
- package/dist/tests/autotest/invalid mdx with an expression {{}}.test.js +27 -0
- package/dist/tests/autotest/invalid mdx with an expression.test.d.ts +1 -0
- package/dist/tests/autotest/invalid mdx with an expression.test.js +27 -0
- package/dist/tests/autotest/invalid mdx with an import statment.test.d.ts +1 -0
- package/dist/tests/autotest/invalid mdx with an import statment.test.js +27 -0
- package/dist/tests/autotest/kitchen sink.test.d.ts +1 -0
- package/dist/tests/autotest/kitchen sink.test.js +144 -0
- package/dist/tests/autotest/links.test.d.ts +1 -0
- package/dist/tests/autotest/links.test.js +29 -0
- package/dist/tests/autotest/lists.test.d.ts +1 -0
- package/dist/tests/autotest/lists.test.js +110 -0
- package/dist/tests/autotest/marks.test.d.ts +1 -0
- package/dist/tests/autotest/marks.test.js +102 -0
- package/dist/tests/autotest/mdx field with a scalar field as a list.test.d.ts +1 -0
- package/dist/tests/autotest/mdx field with a scalar field as a list.test.js +22 -0
- package/dist/tests/autotest/mdx which hasnt been registered returns html.test.d.ts +1 -0
- package/dist/tests/autotest/mdx which hasnt been registered returns html.test.js +26 -0
- package/dist/tests/autotest/mdx with a boolean field.test.d.ts +1 -0
- package/dist/tests/autotest/mdx with a boolean field.test.js +22 -0
- package/dist/tests/autotest/mdx with a number field.test.d.ts +1 -0
- package/dist/tests/autotest/mdx with a number field.test.js +22 -0
- package/dist/tests/autotest/mdx with a srtring field.test.d.ts +1 -0
- package/dist/tests/autotest/mdx with a srtring field.test.js +28 -0
- package/dist/tests/autotest/mdx with multiple rich-text fields.test.d.ts +1 -0
- package/dist/tests/autotest/mdx with multiple rich-text fields.test.js +53 -0
- package/dist/tests/autotest/mdx with nested children.test.d.ts +1 -0
- package/dist/tests/autotest/mdx with nested children.test.js +35 -0
- package/dist/tests/autotest/mdx with nested null children.test.d.ts +1 -0
- package/dist/tests/autotest/mdx with nested null children.test.js +23 -0
- package/dist/tests/autotest/mdx with number list field.test.d.ts +1 -0
- package/dist/tests/autotest/mdx with number list field.test.js +22 -0
- package/dist/tests/autotest/mdx with object list field.test.d.ts +1 -0
- package/dist/tests/autotest/mdx with object list field.test.js +25 -0
- package/dist/tests/autotest/mdx with object with templates.test.d.ts +1 -0
- package/dist/tests/autotest/mdx with object with templates.test.js +41 -0
- package/dist/tests/autotest/shortcodes.test.d.ts +1 -0
- package/dist/tests/autotest/shortcodes.test.js +51 -0
- package/dist/tests/setup.d.ts +14 -0
- package/dist/tests/setup.js +70 -0
- package/package.json +13 -14
- package/dist/stringify/mdx.d.ts +0 -38
package/dist/mdx.es.js
ADDED
|
@@ -0,0 +1,1092 @@
|
|
|
1
|
+
import { remark } from "remark";
|
|
2
|
+
import remarkMdx from "remark-mdx";
|
|
3
|
+
import { visit } from "unist-util-visit";
|
|
4
|
+
import flatten from "lodash.flatten";
|
|
5
|
+
import { toMarkdown } from "mdast-util-to-markdown";
|
|
6
|
+
import { mdxJsxToMarkdown } from "mdast-util-mdx-jsx";
|
|
7
|
+
import { format } from "prettier";
|
|
8
|
+
const extractAttributes = (attributes, fields, imageCallback) => {
|
|
9
|
+
const properties = {};
|
|
10
|
+
attributes.forEach((attribute) => {
|
|
11
|
+
assertType(attribute, "mdxJsxAttribute");
|
|
12
|
+
const field = fields.find((field2) => field2.name === attribute.name);
|
|
13
|
+
if (!field) {
|
|
14
|
+
throw new Error(`Unable to find field definition for property "${attribute.name}"`);
|
|
15
|
+
}
|
|
16
|
+
properties[attribute.name] = extractAttribute(attribute, field, imageCallback);
|
|
17
|
+
});
|
|
18
|
+
return properties;
|
|
19
|
+
};
|
|
20
|
+
const extractAttribute = (attribute, field, imageCallback) => {
|
|
21
|
+
switch (field.type) {
|
|
22
|
+
case "boolean":
|
|
23
|
+
case "number":
|
|
24
|
+
return extractScalar(extractExpression(attribute), field);
|
|
25
|
+
case "datetime":
|
|
26
|
+
case "string":
|
|
27
|
+
if (field.list) {
|
|
28
|
+
return extractScalar(extractExpression(attribute), field);
|
|
29
|
+
} else {
|
|
30
|
+
return extractString(attribute, field);
|
|
31
|
+
}
|
|
32
|
+
case "image":
|
|
33
|
+
if (field.list) {
|
|
34
|
+
const values = extractScalar(extractExpression(attribute), field);
|
|
35
|
+
return values.split(",").map((value) => imageCallback(value));
|
|
36
|
+
} else {
|
|
37
|
+
const value = extractString(attribute, field);
|
|
38
|
+
return imageCallback(value);
|
|
39
|
+
}
|
|
40
|
+
case "reference":
|
|
41
|
+
if (field.list) {
|
|
42
|
+
return extractScalar(extractExpression(attribute), field);
|
|
43
|
+
} else {
|
|
44
|
+
return extractString(attribute, field);
|
|
45
|
+
}
|
|
46
|
+
case "object":
|
|
47
|
+
return extractObject(extractExpression(attribute), field);
|
|
48
|
+
case "rich-text":
|
|
49
|
+
const JSXString = extractJSXFragment(extractExpression(attribute), attribute, field);
|
|
50
|
+
if (JSXString) {
|
|
51
|
+
return parseMDX(JSXString, field, imageCallback);
|
|
52
|
+
} else {
|
|
53
|
+
return {};
|
|
54
|
+
}
|
|
55
|
+
default:
|
|
56
|
+
throw new Error(`Extract attribute: Unhandled field type ${field.type}`);
|
|
57
|
+
}
|
|
58
|
+
};
|
|
59
|
+
const extractScalar = (attribute, field) => {
|
|
60
|
+
if (field.list) {
|
|
61
|
+
assertType(attribute.expression, "ArrayExpression");
|
|
62
|
+
return attribute.expression.elements.map((element) => {
|
|
63
|
+
assertHasType(element);
|
|
64
|
+
assertType(element, "Literal");
|
|
65
|
+
return element.value;
|
|
66
|
+
});
|
|
67
|
+
} else {
|
|
68
|
+
assertType(attribute.expression, "Literal");
|
|
69
|
+
return attribute.expression.value;
|
|
70
|
+
}
|
|
71
|
+
};
|
|
72
|
+
const extractObject = (attribute, field) => {
|
|
73
|
+
if (field.list) {
|
|
74
|
+
assertType(attribute.expression, "ArrayExpression");
|
|
75
|
+
return attribute.expression.elements.map((element) => {
|
|
76
|
+
assertHasType(element);
|
|
77
|
+
assertType(element, "ObjectExpression");
|
|
78
|
+
return extractObjectExpression(element, field);
|
|
79
|
+
});
|
|
80
|
+
} else {
|
|
81
|
+
assertType(attribute.expression, "ObjectExpression");
|
|
82
|
+
return extractObjectExpression(attribute.expression, field);
|
|
83
|
+
}
|
|
84
|
+
};
|
|
85
|
+
const extractObjectExpression = (expression, field) => {
|
|
86
|
+
const properties = {};
|
|
87
|
+
expression.properties.forEach((property) => {
|
|
88
|
+
assertType(property, "Property");
|
|
89
|
+
const { key, value } = extractKeyValue(property, field);
|
|
90
|
+
properties[key] = value;
|
|
91
|
+
});
|
|
92
|
+
return properties;
|
|
93
|
+
};
|
|
94
|
+
const getField = (objectField, name) => {
|
|
95
|
+
if (objectField.fields) {
|
|
96
|
+
if (typeof objectField.fields === "string") {
|
|
97
|
+
throw new Error("Global templates not supported");
|
|
98
|
+
}
|
|
99
|
+
return objectField.fields.find((f) => f.name === name);
|
|
100
|
+
}
|
|
101
|
+
};
|
|
102
|
+
const extractJSXFragment = (attribute, baseAttribute, field) => {
|
|
103
|
+
if (field.list)
|
|
104
|
+
;
|
|
105
|
+
else {
|
|
106
|
+
if (attribute.expression.type === "JSXFragment") {
|
|
107
|
+
assertHasType(attribute.expression);
|
|
108
|
+
if (attribute.expression.children[0]) {
|
|
109
|
+
const firstChild = attribute.expression.children[0];
|
|
110
|
+
if (attribute.expression.children[0].type === "JSXText") {
|
|
111
|
+
const child = firstChild;
|
|
112
|
+
return child.value.trim();
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
throwError(field);
|
|
118
|
+
};
|
|
119
|
+
const extractKeyValue = (property, parentField) => {
|
|
120
|
+
assertType(property.key, "Identifier");
|
|
121
|
+
const key = property.key.name;
|
|
122
|
+
const field = getField(parentField, key);
|
|
123
|
+
if ((field == null ? void 0 : field.type) === "object") {
|
|
124
|
+
if (field.list) {
|
|
125
|
+
assertType(property.value, "ArrayExpression");
|
|
126
|
+
const value = property.value.elements.map((element) => {
|
|
127
|
+
assertHasType(element);
|
|
128
|
+
assertType(element, "ObjectExpression");
|
|
129
|
+
return extractObjectExpression(element, field);
|
|
130
|
+
});
|
|
131
|
+
return { key, value };
|
|
132
|
+
} else {
|
|
133
|
+
assertType(property.value, "ObjectExpression");
|
|
134
|
+
const value = extractObjectExpression(property.value, field);
|
|
135
|
+
return { key, value };
|
|
136
|
+
}
|
|
137
|
+
} else {
|
|
138
|
+
assertType(property.value, "Literal");
|
|
139
|
+
return { key, value: property.value.value };
|
|
140
|
+
}
|
|
141
|
+
};
|
|
142
|
+
const extractStatement = (attribute) => {
|
|
143
|
+
var _a, _b;
|
|
144
|
+
const body = (_b = (_a = attribute.data) == null ? void 0 : _a.estree) == null ? void 0 : _b.body;
|
|
145
|
+
if (body) {
|
|
146
|
+
if (body[0]) {
|
|
147
|
+
assertType(body[0], "ExpressionStatement");
|
|
148
|
+
return body[0];
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
throw new Error(`Unable to extract body from expression`);
|
|
152
|
+
};
|
|
153
|
+
const extractString = (attribute, field) => {
|
|
154
|
+
if (attribute.type === "mdxJsxAttribute") {
|
|
155
|
+
if (typeof attribute.value === "string") {
|
|
156
|
+
return attribute.value;
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
return extractScalar(extractExpression(attribute), field);
|
|
160
|
+
};
|
|
161
|
+
const extractExpression = (attribute) => {
|
|
162
|
+
assertType(attribute, "mdxJsxAttribute");
|
|
163
|
+
assertHasType(attribute.value);
|
|
164
|
+
assertType(attribute.value, "mdxJsxAttributeValueExpression");
|
|
165
|
+
return extractStatement(attribute.value);
|
|
166
|
+
};
|
|
167
|
+
function assertType(val, type) {
|
|
168
|
+
if (val.type !== type) {
|
|
169
|
+
throw new Error(`Expected type to be ${type} but received ${val.type}. ${MDX_PARSE_ERROR_MSG}`);
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
function assertHasType(val) {
|
|
173
|
+
if (val) {
|
|
174
|
+
if (typeof val !== "string") {
|
|
175
|
+
return;
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
throw new Error(`Expect value to be an object with property "type"`);
|
|
179
|
+
}
|
|
180
|
+
const throwError = (field) => {
|
|
181
|
+
throw new Error(`Unexpected expression for field "${field.name}"${field.list ? ' with "list": true' : ""}`);
|
|
182
|
+
};
|
|
183
|
+
function mdxJsxElement(node, field, imageCallback) {
|
|
184
|
+
var _a;
|
|
185
|
+
const template = (_a = field.templates) == null ? void 0 : _a.find((template2) => {
|
|
186
|
+
const templateName = typeof template2 === "string" ? template2 : template2.name;
|
|
187
|
+
return templateName === node.name;
|
|
188
|
+
});
|
|
189
|
+
if (typeof template === "string") {
|
|
190
|
+
throw new Error("Global templates not yet supported");
|
|
191
|
+
}
|
|
192
|
+
if (!template) {
|
|
193
|
+
const string = toMarkdown({ type: "root", children: [node] }, {
|
|
194
|
+
extensions: [mdxJsxToMarkdown()],
|
|
195
|
+
listItemIndent: "one"
|
|
196
|
+
});
|
|
197
|
+
return {
|
|
198
|
+
type: node.type === "mdxJsxFlowElement" ? "html" : "html_inline",
|
|
199
|
+
value: string.trim(),
|
|
200
|
+
children: [{ type: "text", text: "" }]
|
|
201
|
+
};
|
|
202
|
+
}
|
|
203
|
+
if (template.match) {
|
|
204
|
+
const value = node.children[0].value;
|
|
205
|
+
if (node.type === "mdxJsxFlowElement") {
|
|
206
|
+
return {
|
|
207
|
+
type: node.type,
|
|
208
|
+
name: node.name,
|
|
209
|
+
children: [{ type: "text", text: "" }],
|
|
210
|
+
props: { text: value }
|
|
211
|
+
};
|
|
212
|
+
} else {
|
|
213
|
+
return {
|
|
214
|
+
type: node.type,
|
|
215
|
+
name: node.name,
|
|
216
|
+
children: [{ type: "text", text: "" }],
|
|
217
|
+
props: { text: value }
|
|
218
|
+
};
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
const props = extractAttributes(node.attributes, template.fields, imageCallback);
|
|
222
|
+
const childField = template.fields.find((field2) => field2.name === "children");
|
|
223
|
+
if (childField) {
|
|
224
|
+
const childProps = remarkToSlate(node, childField, imageCallback);
|
|
225
|
+
props.children = childProps;
|
|
226
|
+
}
|
|
227
|
+
return {
|
|
228
|
+
type: node.type,
|
|
229
|
+
name: node.name,
|
|
230
|
+
children: [{ type: "text", text: "" }],
|
|
231
|
+
props
|
|
232
|
+
};
|
|
233
|
+
}
|
|
234
|
+
const remarkToSlate = (root, field, imageCallback) => {
|
|
235
|
+
const content = (content2) => {
|
|
236
|
+
switch (content2.type) {
|
|
237
|
+
case "blockquote":
|
|
238
|
+
const children = [];
|
|
239
|
+
content2.children.map((child) => {
|
|
240
|
+
const inlineElements = unwrapBlockContent(child);
|
|
241
|
+
inlineElements.forEach((child2) => {
|
|
242
|
+
children.push(child2);
|
|
243
|
+
});
|
|
244
|
+
});
|
|
245
|
+
return {
|
|
246
|
+
type: "blockquote",
|
|
247
|
+
children
|
|
248
|
+
};
|
|
249
|
+
case "heading":
|
|
250
|
+
return heading(content2);
|
|
251
|
+
case "code":
|
|
252
|
+
return code(content2);
|
|
253
|
+
case "paragraph":
|
|
254
|
+
return paragraph(content2);
|
|
255
|
+
case "mdxJsxFlowElement":
|
|
256
|
+
return mdxJsxElement(content2, field, imageCallback);
|
|
257
|
+
case "thematicBreak":
|
|
258
|
+
return {
|
|
259
|
+
type: "hr",
|
|
260
|
+
children: [{ type: "text", text: "" }]
|
|
261
|
+
};
|
|
262
|
+
case "listItem":
|
|
263
|
+
return {
|
|
264
|
+
type: "li",
|
|
265
|
+
children: [
|
|
266
|
+
{
|
|
267
|
+
type: "lic",
|
|
268
|
+
children: flatten(content2.children.map((child) => unwrapBlockContent(child)))
|
|
269
|
+
}
|
|
270
|
+
]
|
|
271
|
+
};
|
|
272
|
+
case "list":
|
|
273
|
+
return list(content2);
|
|
274
|
+
case "html":
|
|
275
|
+
return html(content2);
|
|
276
|
+
case "mdxjsEsm":
|
|
277
|
+
throw new Error(`Unexpected expression ${content2.value} ${MDX_PARSE_ERROR_MSG}`);
|
|
278
|
+
default:
|
|
279
|
+
throw new Error(`Content: ${content2.type} is not yet supported`);
|
|
280
|
+
}
|
|
281
|
+
};
|
|
282
|
+
const html = (content2) => {
|
|
283
|
+
return {
|
|
284
|
+
type: "html",
|
|
285
|
+
value: content2.value,
|
|
286
|
+
children: [{ type: "text", text: "" }]
|
|
287
|
+
};
|
|
288
|
+
};
|
|
289
|
+
const html_inline = (content2) => {
|
|
290
|
+
return {
|
|
291
|
+
type: "html_inline",
|
|
292
|
+
value: content2.value,
|
|
293
|
+
children: [{ type: "text", text: "" }]
|
|
294
|
+
};
|
|
295
|
+
};
|
|
296
|
+
const list = (content2) => {
|
|
297
|
+
return {
|
|
298
|
+
type: content2.ordered ? "ol" : "ul",
|
|
299
|
+
children: content2.children.map((child) => listItem(child))
|
|
300
|
+
};
|
|
301
|
+
};
|
|
302
|
+
const listItem = (content2) => {
|
|
303
|
+
return {
|
|
304
|
+
type: "li",
|
|
305
|
+
children: content2.children.map((child) => {
|
|
306
|
+
switch (child.type) {
|
|
307
|
+
case "list":
|
|
308
|
+
return list(child);
|
|
309
|
+
case "heading":
|
|
310
|
+
case "paragraph":
|
|
311
|
+
return {
|
|
312
|
+
type: "lic",
|
|
313
|
+
children: flatten(child.children.map((child2) => phrasingContent(child2)))
|
|
314
|
+
};
|
|
315
|
+
case "blockquote": {
|
|
316
|
+
return {
|
|
317
|
+
...blockquote(child),
|
|
318
|
+
type: "lic"
|
|
319
|
+
};
|
|
320
|
+
}
|
|
321
|
+
case "mdxJsxFlowElement":
|
|
322
|
+
return {
|
|
323
|
+
type: "lic",
|
|
324
|
+
children: [
|
|
325
|
+
mdxJsxElement({ ...child, type: "mdxJsxTextElement" }, field, imageCallback)
|
|
326
|
+
]
|
|
327
|
+
};
|
|
328
|
+
case "code":
|
|
329
|
+
case "thematicBreak":
|
|
330
|
+
case "table":
|
|
331
|
+
case "html":
|
|
332
|
+
throw new Error(`${content2.type} inside list item is not supported`);
|
|
333
|
+
default:
|
|
334
|
+
throw new Error(`Unknown list item of type ${content2.type}`);
|
|
335
|
+
}
|
|
336
|
+
})
|
|
337
|
+
};
|
|
338
|
+
};
|
|
339
|
+
const unwrapBlockContent = (content2) => {
|
|
340
|
+
const flattenPhrasingContent = (children) => {
|
|
341
|
+
const children2 = children.map((child) => phrasingContent(child));
|
|
342
|
+
return flatten(Array.isArray(children2) ? children2 : [children2]);
|
|
343
|
+
};
|
|
344
|
+
switch (content2.type) {
|
|
345
|
+
case "heading":
|
|
346
|
+
case "paragraph":
|
|
347
|
+
return flattenPhrasingContent(content2.children);
|
|
348
|
+
default:
|
|
349
|
+
throw new Error(`UnwrapBlock: Unknown block content of type ${content2.type}`);
|
|
350
|
+
}
|
|
351
|
+
};
|
|
352
|
+
const code = (content2) => {
|
|
353
|
+
const extra = {};
|
|
354
|
+
if (content2.lang)
|
|
355
|
+
extra["lang"] = content2.lang;
|
|
356
|
+
return {
|
|
357
|
+
type: "code_block",
|
|
358
|
+
...extra,
|
|
359
|
+
value: content2.value,
|
|
360
|
+
children: [{ type: "text", text: "" }]
|
|
361
|
+
};
|
|
362
|
+
};
|
|
363
|
+
const link = (content2) => {
|
|
364
|
+
return {
|
|
365
|
+
type: "a",
|
|
366
|
+
url: content2.url,
|
|
367
|
+
title: content2.title,
|
|
368
|
+
children: flatten(content2.children.map((child) => staticPhrasingContent(child)))
|
|
369
|
+
};
|
|
370
|
+
};
|
|
371
|
+
const heading = (content2) => {
|
|
372
|
+
return {
|
|
373
|
+
type: ["h1", "h2", "h3", "h4", "h5", "h6"][content2.depth - 1],
|
|
374
|
+
children: flatten(content2.children.map(phrasingContent))
|
|
375
|
+
};
|
|
376
|
+
};
|
|
377
|
+
const staticPhrasingContent = (content2) => {
|
|
378
|
+
switch (content2.type) {
|
|
379
|
+
case "mdxJsxTextElement":
|
|
380
|
+
return mdxJsxElement(content2, field, imageCallback);
|
|
381
|
+
case "text":
|
|
382
|
+
return text(content2);
|
|
383
|
+
case "inlineCode":
|
|
384
|
+
case "emphasis":
|
|
385
|
+
case "image":
|
|
386
|
+
case "strong":
|
|
387
|
+
return phrashingMark(content2);
|
|
388
|
+
default:
|
|
389
|
+
throw new Error(`StaticPhrasingContent: ${content2.type} is not yet supported`);
|
|
390
|
+
}
|
|
391
|
+
};
|
|
392
|
+
const phrasingContent = (content2) => {
|
|
393
|
+
switch (content2.type) {
|
|
394
|
+
case "text":
|
|
395
|
+
return text(content2);
|
|
396
|
+
case "link":
|
|
397
|
+
return link(content2);
|
|
398
|
+
case "image":
|
|
399
|
+
return image(content2);
|
|
400
|
+
case "mdxJsxTextElement":
|
|
401
|
+
return mdxJsxElement(content2, field, imageCallback);
|
|
402
|
+
case "emphasis":
|
|
403
|
+
return phrashingMark(content2);
|
|
404
|
+
case "strong":
|
|
405
|
+
return phrashingMark(content2);
|
|
406
|
+
case "break":
|
|
407
|
+
return breakContent();
|
|
408
|
+
case "inlineCode":
|
|
409
|
+
return phrashingMark(content2);
|
|
410
|
+
case "html":
|
|
411
|
+
return html_inline(content2);
|
|
412
|
+
default:
|
|
413
|
+
throw new Error(`PhrasingContent: ${content2.type} is not yet supported`);
|
|
414
|
+
}
|
|
415
|
+
};
|
|
416
|
+
const breakContent = () => {
|
|
417
|
+
return {
|
|
418
|
+
type: "break",
|
|
419
|
+
children: [
|
|
420
|
+
{
|
|
421
|
+
type: "text",
|
|
422
|
+
text: ""
|
|
423
|
+
}
|
|
424
|
+
]
|
|
425
|
+
};
|
|
426
|
+
};
|
|
427
|
+
const phrashingMark = (node, marks = []) => {
|
|
428
|
+
const accum = [];
|
|
429
|
+
switch (node.type) {
|
|
430
|
+
case "emphasis": {
|
|
431
|
+
const children = flatten(node.children.map((child) => phrashingMark(child, [...marks, "italic"])));
|
|
432
|
+
children.forEach((child) => {
|
|
433
|
+
accum.push(child);
|
|
434
|
+
});
|
|
435
|
+
break;
|
|
436
|
+
}
|
|
437
|
+
case "inlineCode": {
|
|
438
|
+
const markProps2 = {};
|
|
439
|
+
marks.forEach((mark) => markProps2[mark] = true);
|
|
440
|
+
accum.push({
|
|
441
|
+
type: "text",
|
|
442
|
+
text: node.value,
|
|
443
|
+
code: true,
|
|
444
|
+
...markProps2
|
|
445
|
+
});
|
|
446
|
+
break;
|
|
447
|
+
}
|
|
448
|
+
case "strong": {
|
|
449
|
+
const children = flatten(node.children.map((child) => phrashingMark(child, [...marks, "bold"])));
|
|
450
|
+
children.forEach((child) => {
|
|
451
|
+
accum.push(child);
|
|
452
|
+
});
|
|
453
|
+
break;
|
|
454
|
+
}
|
|
455
|
+
case "image": {
|
|
456
|
+
accum.push(image(node));
|
|
457
|
+
break;
|
|
458
|
+
}
|
|
459
|
+
case "link": {
|
|
460
|
+
const children = flatten(node.children.map((child) => phrashingMark(child, marks)));
|
|
461
|
+
accum.push({ type: "a", url: node.url, title: node.title, children });
|
|
462
|
+
break;
|
|
463
|
+
}
|
|
464
|
+
case "text":
|
|
465
|
+
const markProps = {};
|
|
466
|
+
marks.forEach((mark) => markProps[mark] = true);
|
|
467
|
+
accum.push({ type: "text", text: node.value, ...markProps });
|
|
468
|
+
break;
|
|
469
|
+
default:
|
|
470
|
+
throw new Error(`Unexpected inline element of type ${node.type}`);
|
|
471
|
+
}
|
|
472
|
+
return accum;
|
|
473
|
+
};
|
|
474
|
+
const image = (content2) => {
|
|
475
|
+
return {
|
|
476
|
+
type: "img",
|
|
477
|
+
url: imageCallback(content2.url),
|
|
478
|
+
alt: content2.alt,
|
|
479
|
+
caption: content2.title,
|
|
480
|
+
children: [{ type: "text", text: "" }]
|
|
481
|
+
};
|
|
482
|
+
};
|
|
483
|
+
const text = (content2) => {
|
|
484
|
+
return {
|
|
485
|
+
type: "text",
|
|
486
|
+
text: content2.value
|
|
487
|
+
};
|
|
488
|
+
};
|
|
489
|
+
const blockquote = (content2) => {
|
|
490
|
+
const children = [];
|
|
491
|
+
content2.children.map((child) => {
|
|
492
|
+
const inlineElements = unwrapBlockContent(child);
|
|
493
|
+
inlineElements.forEach((child2) => {
|
|
494
|
+
children.push(child2);
|
|
495
|
+
});
|
|
496
|
+
});
|
|
497
|
+
return {
|
|
498
|
+
type: "blockquote",
|
|
499
|
+
children
|
|
500
|
+
};
|
|
501
|
+
};
|
|
502
|
+
const paragraph = (content2) => {
|
|
503
|
+
const children = flatten(content2.children.map(phrasingContent));
|
|
504
|
+
if (children.length === 1) {
|
|
505
|
+
if (children[0]) {
|
|
506
|
+
if (children[0].type === "html_inline") {
|
|
507
|
+
return {
|
|
508
|
+
...children[0],
|
|
509
|
+
type: "html"
|
|
510
|
+
};
|
|
511
|
+
}
|
|
512
|
+
}
|
|
513
|
+
}
|
|
514
|
+
return {
|
|
515
|
+
type: "p",
|
|
516
|
+
children
|
|
517
|
+
};
|
|
518
|
+
};
|
|
519
|
+
return {
|
|
520
|
+
type: "root",
|
|
521
|
+
children: root.children.map((child) => content(child))
|
|
522
|
+
};
|
|
523
|
+
};
|
|
524
|
+
const markdownToAst = (value, field) => {
|
|
525
|
+
var _a;
|
|
526
|
+
const templatesWithMatchers = (_a = field.templates) == null ? void 0 : _a.filter((template) => template.match);
|
|
527
|
+
let preprocessedString = value;
|
|
528
|
+
templatesWithMatchers == null ? void 0 : templatesWithMatchers.forEach((template) => {
|
|
529
|
+
if (typeof template === "string") {
|
|
530
|
+
throw new Error("Global templates are not supported");
|
|
531
|
+
}
|
|
532
|
+
if (template.match) {
|
|
533
|
+
preprocessedString = preprocessedString.replaceAll(template.match.start, `<${template.name}>\``);
|
|
534
|
+
preprocessedString = preprocessedString.replaceAll(template.match.end, `\`</${template.name}>`);
|
|
535
|
+
}
|
|
536
|
+
});
|
|
537
|
+
const tree = remark().use(remarkMdx).parse(preprocessedString);
|
|
538
|
+
if (!tree) {
|
|
539
|
+
throw new Error("Error parsing markdown");
|
|
540
|
+
}
|
|
541
|
+
visit(tree, (node) => {
|
|
542
|
+
delete node.position;
|
|
543
|
+
});
|
|
544
|
+
return tree;
|
|
545
|
+
};
|
|
546
|
+
const MDX_PARSE_ERROR_MSG = "TinaCMS supports a stricter version of markdown and a subset of MDX - learn more: https://tina.io/docs/editing/mdx/#differences-from-other-mdx-implementations";
|
|
547
|
+
const parseMDX = (value, field, imageCallback) => {
|
|
548
|
+
let tree;
|
|
549
|
+
try {
|
|
550
|
+
tree = markdownToAst(value, field);
|
|
551
|
+
} catch (e) {
|
|
552
|
+
if (e.position) {
|
|
553
|
+
throw new Error(`Unable to parse markdown at line: ${e.position.start.line}, column: ${e.position.start.column}. ${MDX_PARSE_ERROR_MSG}`);
|
|
554
|
+
}
|
|
555
|
+
throw new Error(`Unable to parse markdown, ${MDX_PARSE_ERROR_MSG}`);
|
|
556
|
+
}
|
|
557
|
+
if (tree) {
|
|
558
|
+
return remarkToSlate(tree, field, imageCallback);
|
|
559
|
+
} else {
|
|
560
|
+
return { type: "root", children: [] };
|
|
561
|
+
}
|
|
562
|
+
};
|
|
563
|
+
const stringifyPropsInline = (element, field, imageCallback) => {
|
|
564
|
+
return stringifyProps(element, field, true, imageCallback);
|
|
565
|
+
};
|
|
566
|
+
function stringifyProps(element, parentField, flatten2, imageCallback) {
|
|
567
|
+
var _a;
|
|
568
|
+
const attributes = [];
|
|
569
|
+
const children = [];
|
|
570
|
+
const template = (_a = parentField.templates) == null ? void 0 : _a.find((template2) => {
|
|
571
|
+
if (typeof template2 === "string") {
|
|
572
|
+
throw new Error("Global templates not supported");
|
|
573
|
+
}
|
|
574
|
+
return template2.name === element.name;
|
|
575
|
+
});
|
|
576
|
+
if (!template || typeof template === "string") {
|
|
577
|
+
throw new Error(`Unable to find template for JSX element ${element.name}`);
|
|
578
|
+
}
|
|
579
|
+
Object.entries(element.props).forEach(([name, value]) => {
|
|
580
|
+
const field = template.fields.find((field2) => field2.name === name);
|
|
581
|
+
if (!field) {
|
|
582
|
+
if (name === "children") {
|
|
583
|
+
return;
|
|
584
|
+
}
|
|
585
|
+
throw new Error(`No field definition found for property ${name}`);
|
|
586
|
+
}
|
|
587
|
+
switch (field.type) {
|
|
588
|
+
case "reference":
|
|
589
|
+
if (field.list) {
|
|
590
|
+
if (Array.isArray(value)) {
|
|
591
|
+
attributes.push({
|
|
592
|
+
type: "mdxJsxAttribute",
|
|
593
|
+
name,
|
|
594
|
+
value: {
|
|
595
|
+
type: "mdxJsxAttributeValueExpression",
|
|
596
|
+
value: `[${value.map((item) => `"${item}"`).join(", ")}]`
|
|
597
|
+
}
|
|
598
|
+
});
|
|
599
|
+
}
|
|
600
|
+
} else {
|
|
601
|
+
if (typeof value === "string") {
|
|
602
|
+
attributes.push({
|
|
603
|
+
type: "mdxJsxAttribute",
|
|
604
|
+
name,
|
|
605
|
+
value
|
|
606
|
+
});
|
|
607
|
+
}
|
|
608
|
+
}
|
|
609
|
+
break;
|
|
610
|
+
case "datetime":
|
|
611
|
+
case "string":
|
|
612
|
+
if (field.list) {
|
|
613
|
+
if (Array.isArray(value)) {
|
|
614
|
+
attributes.push({
|
|
615
|
+
type: "mdxJsxAttribute",
|
|
616
|
+
name,
|
|
617
|
+
value: {
|
|
618
|
+
type: "mdxJsxAttributeValueExpression",
|
|
619
|
+
value: `[${value.map((item) => `"${item}"`).join(", ")}]`
|
|
620
|
+
}
|
|
621
|
+
});
|
|
622
|
+
}
|
|
623
|
+
} else {
|
|
624
|
+
attributes.push({
|
|
625
|
+
type: "mdxJsxAttribute",
|
|
626
|
+
name,
|
|
627
|
+
value
|
|
628
|
+
});
|
|
629
|
+
}
|
|
630
|
+
break;
|
|
631
|
+
case "image":
|
|
632
|
+
if (field.list) {
|
|
633
|
+
if (Array.isArray(value)) {
|
|
634
|
+
attributes.push({
|
|
635
|
+
type: "mdxJsxAttribute",
|
|
636
|
+
name,
|
|
637
|
+
value: {
|
|
638
|
+
type: "mdxJsxAttributeValueExpression",
|
|
639
|
+
value: `[${value.map((item) => `"${imageCallback(item)}"`).join(", ")}]`
|
|
640
|
+
}
|
|
641
|
+
});
|
|
642
|
+
}
|
|
643
|
+
} else {
|
|
644
|
+
attributes.push({
|
|
645
|
+
type: "mdxJsxAttribute",
|
|
646
|
+
name,
|
|
647
|
+
value: imageCallback(value)
|
|
648
|
+
});
|
|
649
|
+
}
|
|
650
|
+
break;
|
|
651
|
+
case "number":
|
|
652
|
+
case "boolean":
|
|
653
|
+
if (field.list) {
|
|
654
|
+
attributes.push({
|
|
655
|
+
type: "mdxJsxAttribute",
|
|
656
|
+
name,
|
|
657
|
+
value: {
|
|
658
|
+
type: "mdxJsxAttributeValueExpression",
|
|
659
|
+
value: `[${value.map((item) => `${item}`).join(", ")}]`
|
|
660
|
+
}
|
|
661
|
+
});
|
|
662
|
+
} else {
|
|
663
|
+
attributes.push({
|
|
664
|
+
type: "mdxJsxAttribute",
|
|
665
|
+
name,
|
|
666
|
+
value: {
|
|
667
|
+
type: "mdxJsxAttributeValueExpression",
|
|
668
|
+
value
|
|
669
|
+
}
|
|
670
|
+
});
|
|
671
|
+
}
|
|
672
|
+
break;
|
|
673
|
+
case "object":
|
|
674
|
+
attributes.push({
|
|
675
|
+
type: "mdxJsxAttribute",
|
|
676
|
+
name,
|
|
677
|
+
value: {
|
|
678
|
+
type: "mdxJsxAttributeValueExpression",
|
|
679
|
+
value: stringifyObj(value, flatten2)
|
|
680
|
+
}
|
|
681
|
+
});
|
|
682
|
+
break;
|
|
683
|
+
case "rich-text":
|
|
684
|
+
if (typeof value === "string") {
|
|
685
|
+
throw new Error(`Unexpected string for rich-text, ensure the value has been properly parsed`);
|
|
686
|
+
}
|
|
687
|
+
if (field.list) {
|
|
688
|
+
throw new Error(`Rich-text list is not supported`);
|
|
689
|
+
} else {
|
|
690
|
+
const joiner = flatten2 ? " " : "\n";
|
|
691
|
+
let val = "";
|
|
692
|
+
if (field.name === "children") {
|
|
693
|
+
const root = rootElement(value, field, imageCallback);
|
|
694
|
+
root.children.forEach((child) => {
|
|
695
|
+
children.push(child);
|
|
696
|
+
});
|
|
697
|
+
return;
|
|
698
|
+
} else {
|
|
699
|
+
const stringValue = stringifyMDX(value, field, imageCallback);
|
|
700
|
+
val = stringValue.trim().split("\n").map((str) => ` ${str.trim()}`).join(joiner);
|
|
701
|
+
}
|
|
702
|
+
if (flatten2) {
|
|
703
|
+
attributes.push({
|
|
704
|
+
type: "mdxJsxAttribute",
|
|
705
|
+
name,
|
|
706
|
+
value: {
|
|
707
|
+
type: "mdxJsxAttributeValueExpression",
|
|
708
|
+
value: `<>${val.trim()}</>`
|
|
709
|
+
}
|
|
710
|
+
});
|
|
711
|
+
} else {
|
|
712
|
+
attributes.push({
|
|
713
|
+
type: "mdxJsxAttribute",
|
|
714
|
+
name,
|
|
715
|
+
value: {
|
|
716
|
+
type: "mdxJsxAttributeValueExpression",
|
|
717
|
+
value: `<>
|
|
718
|
+
${val}
|
|
719
|
+
</>`
|
|
720
|
+
}
|
|
721
|
+
});
|
|
722
|
+
}
|
|
723
|
+
}
|
|
724
|
+
break;
|
|
725
|
+
default:
|
|
726
|
+
throw new Error(`Stringify props: ${field.type} not yet supported`);
|
|
727
|
+
}
|
|
728
|
+
});
|
|
729
|
+
if (template.match) {
|
|
730
|
+
if (attributes[0] && typeof attributes[0].value === "string") {
|
|
731
|
+
return {
|
|
732
|
+
attributes: [],
|
|
733
|
+
children: [{ type: "inlineCode", value: attributes[0].value }]
|
|
734
|
+
};
|
|
735
|
+
}
|
|
736
|
+
}
|
|
737
|
+
return { attributes, children };
|
|
738
|
+
}
|
|
739
|
+
function stringifyObj(obj, flatten2) {
|
|
740
|
+
const dummyFunc = `const dummyFunc = `;
|
|
741
|
+
const res = format(`${dummyFunc}${JSON.stringify(obj)}`, {
|
|
742
|
+
parser: "acorn",
|
|
743
|
+
trailingComma: "none",
|
|
744
|
+
semi: false
|
|
745
|
+
}).trim().replace(dummyFunc, "");
|
|
746
|
+
return flatten2 ? res.replaceAll("\n", "").replaceAll(" ", " ") : res;
|
|
747
|
+
}
|
|
748
|
+
const matches = (a, b) => {
|
|
749
|
+
return a.some((v) => b.includes(v));
|
|
750
|
+
};
|
|
751
|
+
const replaceLinksWithTextNodes = (content) => {
|
|
752
|
+
const newItems = [];
|
|
753
|
+
content.forEach((item) => {
|
|
754
|
+
if (item.type === "a") {
|
|
755
|
+
if (item.children.length === 1) {
|
|
756
|
+
const firstChild = item.children[0];
|
|
757
|
+
if ((firstChild == null ? void 0 : firstChild.type) === "text") {
|
|
758
|
+
newItems.push({
|
|
759
|
+
...firstChild,
|
|
760
|
+
linkifyTextNode: (a) => {
|
|
761
|
+
return {
|
|
762
|
+
type: "link",
|
|
763
|
+
url: item.url,
|
|
764
|
+
title: item.title,
|
|
765
|
+
children: [
|
|
766
|
+
{
|
|
767
|
+
type: "text",
|
|
768
|
+
value: a.value
|
|
769
|
+
}
|
|
770
|
+
]
|
|
771
|
+
};
|
|
772
|
+
}
|
|
773
|
+
});
|
|
774
|
+
} else {
|
|
775
|
+
newItems.push(item);
|
|
776
|
+
}
|
|
777
|
+
} else {
|
|
778
|
+
newItems.push(item);
|
|
779
|
+
}
|
|
780
|
+
} else {
|
|
781
|
+
newItems.push(item);
|
|
782
|
+
}
|
|
783
|
+
});
|
|
784
|
+
return newItems;
|
|
785
|
+
};
|
|
786
|
+
const inlineElementExceptLink = (content, field, imageCallback) => {
|
|
787
|
+
switch (content.type) {
|
|
788
|
+
case "a":
|
|
789
|
+
throw new Error(`Unexpected node of type "a", link elements should be processed after all inline elements have resolved`);
|
|
790
|
+
case "img":
|
|
791
|
+
return {
|
|
792
|
+
type: "image",
|
|
793
|
+
url: imageCallback(content.url),
|
|
794
|
+
alt: content.alt,
|
|
795
|
+
title: content.caption
|
|
796
|
+
};
|
|
797
|
+
case "break":
|
|
798
|
+
return {
|
|
799
|
+
type: "break"
|
|
800
|
+
};
|
|
801
|
+
case "mdxJsxTextElement": {
|
|
802
|
+
const { attributes, children } = stringifyPropsInline(content, field, imageCallback);
|
|
803
|
+
return {
|
|
804
|
+
type: "mdxJsxTextElement",
|
|
805
|
+
name: content.name,
|
|
806
|
+
attributes,
|
|
807
|
+
children
|
|
808
|
+
};
|
|
809
|
+
}
|
|
810
|
+
case "html_inline": {
|
|
811
|
+
return {
|
|
812
|
+
type: "html",
|
|
813
|
+
value: content.value
|
|
814
|
+
};
|
|
815
|
+
}
|
|
816
|
+
default:
|
|
817
|
+
if (!content.type && typeof content.text === "string") {
|
|
818
|
+
return {
|
|
819
|
+
type: "text",
|
|
820
|
+
value: content.text
|
|
821
|
+
};
|
|
822
|
+
}
|
|
823
|
+
throw new Error(`InlineElement: ${content.type} is not supported`);
|
|
824
|
+
}
|
|
825
|
+
};
|
|
826
|
+
const eat = (c, field, imageCallback) => {
|
|
827
|
+
const content = replaceLinksWithTextNodes(c);
|
|
828
|
+
const first = content[0];
|
|
829
|
+
if (!first) {
|
|
830
|
+
return [];
|
|
831
|
+
}
|
|
832
|
+
if (first && (first == null ? void 0 : first.type) !== "text") {
|
|
833
|
+
return [
|
|
834
|
+
inlineElementExceptLink(first, field, imageCallback),
|
|
835
|
+
...eat(content.slice(1), field, imageCallback)
|
|
836
|
+
];
|
|
837
|
+
}
|
|
838
|
+
const marks = getMarks(first);
|
|
839
|
+
if (marks.length === 0) {
|
|
840
|
+
if (first.linkifyTextNode) {
|
|
841
|
+
return [
|
|
842
|
+
first.linkifyTextNode({ type: "text", value: first.text }),
|
|
843
|
+
...eat(content.slice(1), field, imageCallback)
|
|
844
|
+
];
|
|
845
|
+
} else {
|
|
846
|
+
return [
|
|
847
|
+
{ type: "text", value: first.text },
|
|
848
|
+
...eat(content.slice(1), field, imageCallback)
|
|
849
|
+
];
|
|
850
|
+
}
|
|
851
|
+
}
|
|
852
|
+
let nonMatchingSiblingIndex = 0;
|
|
853
|
+
if (content.slice(1).every((content2, index) => {
|
|
854
|
+
if (matches(marks, getMarks(content2))) {
|
|
855
|
+
return true;
|
|
856
|
+
} else {
|
|
857
|
+
nonMatchingSiblingIndex = index;
|
|
858
|
+
return false;
|
|
859
|
+
}
|
|
860
|
+
})) {
|
|
861
|
+
nonMatchingSiblingIndex = content.length - 1;
|
|
862
|
+
}
|
|
863
|
+
const matchingSiblings = content.slice(1, nonMatchingSiblingIndex + 1);
|
|
864
|
+
const markCounts = {};
|
|
865
|
+
marks.forEach((mark) => {
|
|
866
|
+
let count2 = 1;
|
|
867
|
+
matchingSiblings.every((sibling, index) => {
|
|
868
|
+
if (getMarks(sibling).includes(mark)) {
|
|
869
|
+
count2 = index + 1;
|
|
870
|
+
return true;
|
|
871
|
+
}
|
|
872
|
+
});
|
|
873
|
+
markCounts[mark] = count2;
|
|
874
|
+
});
|
|
875
|
+
let count = 0;
|
|
876
|
+
let markToProcess = null;
|
|
877
|
+
Object.entries(markCounts).forEach(([mark, markCount]) => {
|
|
878
|
+
const m = mark;
|
|
879
|
+
if (markCount > count) {
|
|
880
|
+
count = markCount;
|
|
881
|
+
markToProcess = m;
|
|
882
|
+
}
|
|
883
|
+
});
|
|
884
|
+
if (!markToProcess) {
|
|
885
|
+
return [
|
|
886
|
+
{
|
|
887
|
+
type: "text",
|
|
888
|
+
value: first.text
|
|
889
|
+
},
|
|
890
|
+
...eat(content.slice(1), field, imageCallback)
|
|
891
|
+
];
|
|
892
|
+
}
|
|
893
|
+
if (markToProcess === "inlineCode") {
|
|
894
|
+
if (nonMatchingSiblingIndex) {
|
|
895
|
+
throw new Error(`Marks inside inline code are not supported`);
|
|
896
|
+
}
|
|
897
|
+
return [
|
|
898
|
+
{
|
|
899
|
+
type: markToProcess,
|
|
900
|
+
value: first.text
|
|
901
|
+
},
|
|
902
|
+
...eat(content.slice(nonMatchingSiblingIndex + 1), field, imageCallback)
|
|
903
|
+
];
|
|
904
|
+
}
|
|
905
|
+
return [
|
|
906
|
+
{
|
|
907
|
+
type: markToProcess,
|
|
908
|
+
children: eat([
|
|
909
|
+
...[first, ...matchingSiblings].map((sibling) => cleanNode(sibling, markToProcess))
|
|
910
|
+
], field, imageCallback)
|
|
911
|
+
},
|
|
912
|
+
...eat(content.slice(nonMatchingSiblingIndex + 1), field, imageCallback)
|
|
913
|
+
];
|
|
914
|
+
};
|
|
915
|
+
const cleanNode = (node, mark) => {
|
|
916
|
+
if (!mark) {
|
|
917
|
+
return node;
|
|
918
|
+
}
|
|
919
|
+
const cleanedNode = {};
|
|
920
|
+
const markToClear = {
|
|
921
|
+
strong: "bold",
|
|
922
|
+
emphasis: "italic",
|
|
923
|
+
inlineCode: "code"
|
|
924
|
+
}[mark];
|
|
925
|
+
Object.entries(node).map(([key, value]) => {
|
|
926
|
+
if (key !== markToClear) {
|
|
927
|
+
cleanedNode[key] = value;
|
|
928
|
+
}
|
|
929
|
+
});
|
|
930
|
+
if (node.linkifyTextNode) {
|
|
931
|
+
cleanedNode.callback = node.linkifyTextNode;
|
|
932
|
+
}
|
|
933
|
+
return cleanedNode;
|
|
934
|
+
};
|
|
935
|
+
const stringifyMDX = (value, field, imageCallback) => {
|
|
936
|
+
var _a;
|
|
937
|
+
const res = toMarkdown(rootElement(value, field, imageCallback), {
|
|
938
|
+
extensions: [mdxJsxToMarkdown()],
|
|
939
|
+
listItemIndent: "one"
|
|
940
|
+
});
|
|
941
|
+
const templatesWithMatchers = (_a = field.templates) == null ? void 0 : _a.filter((template) => template.match);
|
|
942
|
+
let preprocessedString = res;
|
|
943
|
+
templatesWithMatchers == null ? void 0 : templatesWithMatchers.forEach((template) => {
|
|
944
|
+
if (typeof template === "string") {
|
|
945
|
+
throw new Error("Global templates are not supported");
|
|
946
|
+
}
|
|
947
|
+
if (template.match) {
|
|
948
|
+
preprocessedString = preprocessedString.replaceAll(`<${template.name}>\``, `${template.match.start} `);
|
|
949
|
+
preprocessedString = preprocessedString.replaceAll(`\`</${template.name}>`, ` ${template.match.end}`);
|
|
950
|
+
}
|
|
951
|
+
});
|
|
952
|
+
return preprocessedString;
|
|
953
|
+
};
|
|
954
|
+
const rootElement = (content, field, imageCallback) => {
|
|
955
|
+
const children = [];
|
|
956
|
+
content.children.forEach((child) => {
|
|
957
|
+
const value = blockElement(child, field, imageCallback);
|
|
958
|
+
if (value) {
|
|
959
|
+
children.push(value);
|
|
960
|
+
}
|
|
961
|
+
});
|
|
962
|
+
return {
|
|
963
|
+
type: "root",
|
|
964
|
+
children
|
|
965
|
+
};
|
|
966
|
+
};
|
|
967
|
+
const blockElement = (content, field, imageCallback) => {
|
|
968
|
+
switch (content.type) {
|
|
969
|
+
case "h1":
|
|
970
|
+
case "h2":
|
|
971
|
+
case "h3":
|
|
972
|
+
case "h4":
|
|
973
|
+
case "h5":
|
|
974
|
+
case "h6":
|
|
975
|
+
return {
|
|
976
|
+
type: "heading",
|
|
977
|
+
depth: { h1: 1, h2: 2, h3: 3, h4: 4, h5: 5, h6: 6 }[content.type],
|
|
978
|
+
children: eat(content.children, field, imageCallback)
|
|
979
|
+
};
|
|
980
|
+
case "p":
|
|
981
|
+
if (content.children.length === 1) {
|
|
982
|
+
const onlyChild = content.children[0];
|
|
983
|
+
if (onlyChild && onlyChild.type === "text" && onlyChild.text === "") {
|
|
984
|
+
return null;
|
|
985
|
+
}
|
|
986
|
+
}
|
|
987
|
+
return {
|
|
988
|
+
type: "paragraph",
|
|
989
|
+
children: eat(content.children, field, imageCallback)
|
|
990
|
+
};
|
|
991
|
+
case "code_block":
|
|
992
|
+
return {
|
|
993
|
+
type: "code",
|
|
994
|
+
lang: content.lang,
|
|
995
|
+
value: content.value
|
|
996
|
+
};
|
|
997
|
+
case "mdxJsxFlowElement":
|
|
998
|
+
const { children, attributes } = stringifyProps(content, field, false, imageCallback);
|
|
999
|
+
return {
|
|
1000
|
+
type: "mdxJsxFlowElement",
|
|
1001
|
+
name: content.name,
|
|
1002
|
+
attributes,
|
|
1003
|
+
children
|
|
1004
|
+
};
|
|
1005
|
+
case "blockquote":
|
|
1006
|
+
return {
|
|
1007
|
+
type: "blockquote",
|
|
1008
|
+
children: [
|
|
1009
|
+
{
|
|
1010
|
+
type: "paragraph",
|
|
1011
|
+
children: eat(content.children, field, imageCallback)
|
|
1012
|
+
}
|
|
1013
|
+
]
|
|
1014
|
+
};
|
|
1015
|
+
case "hr":
|
|
1016
|
+
return {
|
|
1017
|
+
type: "thematicBreak"
|
|
1018
|
+
};
|
|
1019
|
+
case "ol":
|
|
1020
|
+
case "ul":
|
|
1021
|
+
return {
|
|
1022
|
+
type: "list",
|
|
1023
|
+
ordered: content.type === "ol",
|
|
1024
|
+
spread: false,
|
|
1025
|
+
children: content.children.map((child) => listItemElement(child, field, imageCallback))
|
|
1026
|
+
};
|
|
1027
|
+
case "html": {
|
|
1028
|
+
return {
|
|
1029
|
+
type: "html",
|
|
1030
|
+
value: content.value
|
|
1031
|
+
};
|
|
1032
|
+
}
|
|
1033
|
+
default:
|
|
1034
|
+
throw new Error(`BlockElement: ${content.type} is not yet supported`);
|
|
1035
|
+
}
|
|
1036
|
+
};
|
|
1037
|
+
const listItemElement = (content, field, imageCallback) => {
|
|
1038
|
+
return {
|
|
1039
|
+
type: "listItem",
|
|
1040
|
+
spread: false,
|
|
1041
|
+
children: content.children.map((child) => {
|
|
1042
|
+
if (child.type === "lic") {
|
|
1043
|
+
return {
|
|
1044
|
+
type: "paragraph",
|
|
1045
|
+
children: eat(child.children, field, imageCallback)
|
|
1046
|
+
};
|
|
1047
|
+
}
|
|
1048
|
+
return blockContentElement(child, field, imageCallback);
|
|
1049
|
+
})
|
|
1050
|
+
};
|
|
1051
|
+
};
|
|
1052
|
+
const blockContentElement = (content, field, imageCallback) => {
|
|
1053
|
+
switch (content.type) {
|
|
1054
|
+
case "blockquote":
|
|
1055
|
+
return {
|
|
1056
|
+
type: "blockquote",
|
|
1057
|
+
children: content.children.map((child) => blockContentElement(child, field, imageCallback))
|
|
1058
|
+
};
|
|
1059
|
+
case "p":
|
|
1060
|
+
return {
|
|
1061
|
+
type: "paragraph",
|
|
1062
|
+
children: eat(content.children, field, imageCallback)
|
|
1063
|
+
};
|
|
1064
|
+
case "ol":
|
|
1065
|
+
case "ul":
|
|
1066
|
+
return {
|
|
1067
|
+
type: "list",
|
|
1068
|
+
ordered: content.type === "ol",
|
|
1069
|
+
spread: false,
|
|
1070
|
+
children: content.children.map((child) => listItemElement(child, field, imageCallback))
|
|
1071
|
+
};
|
|
1072
|
+
default:
|
|
1073
|
+
throw new Error(`BlockContentElement: ${content.type} is not yet supported`);
|
|
1074
|
+
}
|
|
1075
|
+
};
|
|
1076
|
+
const getMarks = (content) => {
|
|
1077
|
+
const marks = [];
|
|
1078
|
+
if (content.type !== "text") {
|
|
1079
|
+
return [];
|
|
1080
|
+
}
|
|
1081
|
+
if (content.bold) {
|
|
1082
|
+
marks.push("strong");
|
|
1083
|
+
}
|
|
1084
|
+
if (content.italic) {
|
|
1085
|
+
marks.push("emphasis");
|
|
1086
|
+
}
|
|
1087
|
+
if (content.code) {
|
|
1088
|
+
marks.push("inlineCode");
|
|
1089
|
+
}
|
|
1090
|
+
return marks;
|
|
1091
|
+
};
|
|
1092
|
+
export { parseMDX, stringifyMDX };
|