@luckyfishes/markdown-core 0.1.0 → 0.2.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/README.md +399 -14
- package/dist/index.cjs +1209 -0
- package/dist/index.d.cts +140 -0
- package/dist/index.js +16 -3
- package/package.json +7 -4
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,1209 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __create = Object.create;
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
var __export = (target, all) => {
|
|
9
|
+
for (var name in all)
|
|
10
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
11
|
+
};
|
|
12
|
+
var __copyProps = (to, from, except, desc) => {
|
|
13
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
14
|
+
for (let key of __getOwnPropNames(from))
|
|
15
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
16
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
17
|
+
}
|
|
18
|
+
return to;
|
|
19
|
+
};
|
|
20
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
21
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
22
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
23
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
24
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
25
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
26
|
+
mod
|
|
27
|
+
));
|
|
28
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
29
|
+
|
|
30
|
+
// src/index.ts
|
|
31
|
+
var index_exports = {};
|
|
32
|
+
__export(index_exports, {
|
|
33
|
+
DEFAULT_CODE_FENCE_COMPONENT_MAPPINGS: () => DEFAULT_CODE_FENCE_COMPONENT_MAPPINGS,
|
|
34
|
+
DEFAULT_CUSTOM_SYNTAX_COMPONENT_NAMES: () => DEFAULT_CUSTOM_SYNTAX_COMPONENT_NAMES,
|
|
35
|
+
FOOTNOTES_HEADING_ID: () => FOOTNOTES_HEADING_ID,
|
|
36
|
+
FOOTNOTES_HEADING_TEXT: () => FOOTNOTES_HEADING_TEXT,
|
|
37
|
+
YAML_PROP_PREFIX: () => YAML_PROP_PREFIX,
|
|
38
|
+
createCodeFenceComponentPlugin: () => createCodeFenceComponentPlugin,
|
|
39
|
+
createCustomSyntaxRemarkPlugin: () => createCustomSyntaxRemarkPlugin,
|
|
40
|
+
createMarkdownPreset: () => createMarkdownPreset,
|
|
41
|
+
extractHeadings: () => extractHeadings,
|
|
42
|
+
rehypeFootnotesHeading: () => rehypeFootnotesHeading,
|
|
43
|
+
remarkSuperSub: () => remarkSuperSub,
|
|
44
|
+
resolveCustomSyntaxComponentNames: () => resolveCustomSyntaxComponentNames
|
|
45
|
+
});
|
|
46
|
+
module.exports = __toCommonJS(index_exports);
|
|
47
|
+
|
|
48
|
+
// src/footnotes.ts
|
|
49
|
+
var FOOTNOTES_HEADING_TEXT = "Footnotes";
|
|
50
|
+
var FOOTNOTES_HEADING_ID = "footnote-label";
|
|
51
|
+
function resolveFootnotesHeadingDepth(depths) {
|
|
52
|
+
return depths.includes(1) ? 1 : 2;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
// src/preset.ts
|
|
56
|
+
var import_remark_gfm2 = __toESM(require("remark-gfm"), 1);
|
|
57
|
+
|
|
58
|
+
// src/module-interop.ts
|
|
59
|
+
function resolveModuleDefault(value) {
|
|
60
|
+
if (value && typeof value === "object" && "default" in value) {
|
|
61
|
+
return value.default;
|
|
62
|
+
}
|
|
63
|
+
return value;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
// src/rehype/code-fence-components.ts
|
|
67
|
+
var import_unist_util_visit = require("unist-util-visit");
|
|
68
|
+
var DEFAULT_CODE_FENCE_COMPONENT_MAPPINGS = {
|
|
69
|
+
chart: { componentName: "ChartBlock", propName: "spec" },
|
|
70
|
+
mermaid: { componentName: "MermaidDiagram", propName: "chart" },
|
|
71
|
+
music: { componentName: "MusicScore", propName: "score" }
|
|
72
|
+
};
|
|
73
|
+
function hasLanguage(node, language) {
|
|
74
|
+
const className = node.properties?.className;
|
|
75
|
+
const targetClass = `language-${language}`;
|
|
76
|
+
if (typeof className === "string") {
|
|
77
|
+
return className.split(/\s+/).includes(targetClass);
|
|
78
|
+
}
|
|
79
|
+
if (Array.isArray(className)) {
|
|
80
|
+
return className.some((name) => `${name}` === targetClass);
|
|
81
|
+
}
|
|
82
|
+
return false;
|
|
83
|
+
}
|
|
84
|
+
function extractText(node) {
|
|
85
|
+
if (node.type === "text") {
|
|
86
|
+
return node.value ?? "";
|
|
87
|
+
}
|
|
88
|
+
if (!node.children || node.children.length === 0) {
|
|
89
|
+
return "";
|
|
90
|
+
}
|
|
91
|
+
return node.children.map((child) => extractText(child)).join("");
|
|
92
|
+
}
|
|
93
|
+
function createCodeFenceComponentPlugin(mappings = DEFAULT_CODE_FENCE_COMPONENT_MAPPINGS) {
|
|
94
|
+
const resolvedMappings = {
|
|
95
|
+
...DEFAULT_CODE_FENCE_COMPONENT_MAPPINGS,
|
|
96
|
+
...mappings
|
|
97
|
+
};
|
|
98
|
+
return (tree) => {
|
|
99
|
+
(0, import_unist_util_visit.visit)(
|
|
100
|
+
tree,
|
|
101
|
+
"element",
|
|
102
|
+
(node, index, parent) => {
|
|
103
|
+
if (!parent || typeof index !== "number") {
|
|
104
|
+
return;
|
|
105
|
+
}
|
|
106
|
+
if (node.tagName !== "pre") {
|
|
107
|
+
return;
|
|
108
|
+
}
|
|
109
|
+
const [codeNode] = node.children ?? [];
|
|
110
|
+
if (!codeNode || codeNode.type !== "element" || codeNode.tagName !== "code") {
|
|
111
|
+
return;
|
|
112
|
+
}
|
|
113
|
+
const match = Object.entries(resolvedMappings).find(
|
|
114
|
+
([language2]) => hasLanguage(codeNode, language2)
|
|
115
|
+
);
|
|
116
|
+
if (!match) {
|
|
117
|
+
return;
|
|
118
|
+
}
|
|
119
|
+
const [language, mapping] = match;
|
|
120
|
+
const value = extractText(codeNode).trim();
|
|
121
|
+
parent.children = parent.children ?? [];
|
|
122
|
+
parent.children[index] = {
|
|
123
|
+
type: "element",
|
|
124
|
+
tagName: mapping.componentName,
|
|
125
|
+
properties: {
|
|
126
|
+
[mapping.propName]: value,
|
|
127
|
+
"data-language": language
|
|
128
|
+
},
|
|
129
|
+
children: []
|
|
130
|
+
};
|
|
131
|
+
}
|
|
132
|
+
);
|
|
133
|
+
};
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
// src/rehype/footnotes-heading.ts
|
|
137
|
+
var import_unist_util_visit2 = require("unist-util-visit");
|
|
138
|
+
function hasFootnotesSection(node) {
|
|
139
|
+
return node.tagName === "section" && Object.prototype.hasOwnProperty.call(node.properties ?? {}, "dataFootnotes");
|
|
140
|
+
}
|
|
141
|
+
function removeSrOnlyClass(className) {
|
|
142
|
+
if (typeof className === "string") {
|
|
143
|
+
return className.split(/\s+/).filter((name) => name && name !== "sr-only");
|
|
144
|
+
}
|
|
145
|
+
if (Array.isArray(className)) {
|
|
146
|
+
return className.filter((name) => `${name}` !== "sr-only");
|
|
147
|
+
}
|
|
148
|
+
return className;
|
|
149
|
+
}
|
|
150
|
+
function isHeadingTag(tagName) {
|
|
151
|
+
return tagName === "h1" || tagName === "h2" || tagName === "h3";
|
|
152
|
+
}
|
|
153
|
+
function resolveHeadingTagName(tree) {
|
|
154
|
+
const depths = [];
|
|
155
|
+
(0, import_unist_util_visit2.visit)(tree, "element", (node) => {
|
|
156
|
+
if (!isHeadingTag(node.tagName)) {
|
|
157
|
+
return;
|
|
158
|
+
}
|
|
159
|
+
const depth = Number(node.tagName.slice(1));
|
|
160
|
+
if (!Number.isNaN(depth)) {
|
|
161
|
+
depths.push(depth);
|
|
162
|
+
}
|
|
163
|
+
});
|
|
164
|
+
return `h${resolveFootnotesHeadingDepth(depths)}`;
|
|
165
|
+
}
|
|
166
|
+
function createHeadingNode(tagName, headingId, headingText) {
|
|
167
|
+
return {
|
|
168
|
+
type: "element",
|
|
169
|
+
tagName,
|
|
170
|
+
properties: {
|
|
171
|
+
id: headingId
|
|
172
|
+
},
|
|
173
|
+
children: [
|
|
174
|
+
{
|
|
175
|
+
type: "text",
|
|
176
|
+
value: headingText
|
|
177
|
+
}
|
|
178
|
+
]
|
|
179
|
+
};
|
|
180
|
+
}
|
|
181
|
+
function rehypeFootnotesHeading(options) {
|
|
182
|
+
const headingId = options?.headingId ?? FOOTNOTES_HEADING_ID;
|
|
183
|
+
const headingText = options?.headingText ?? FOOTNOTES_HEADING_TEXT;
|
|
184
|
+
return (tree) => {
|
|
185
|
+
const headingTagName = resolveHeadingTagName(tree);
|
|
186
|
+
(0, import_unist_util_visit2.visit)(tree, "element", (node) => {
|
|
187
|
+
if (!hasFootnotesSection(node)) {
|
|
188
|
+
return;
|
|
189
|
+
}
|
|
190
|
+
node.children = node.children ?? [];
|
|
191
|
+
const existingHeading = node.children.find(
|
|
192
|
+
(child) => child.type === "element" && (child.tagName === "h1" || child.tagName === "h2") && child.properties?.id === headingId
|
|
193
|
+
);
|
|
194
|
+
if (existingHeading) {
|
|
195
|
+
existingHeading.tagName = headingTagName;
|
|
196
|
+
existingHeading.properties = {
|
|
197
|
+
...existingHeading.properties,
|
|
198
|
+
className: removeSrOnlyClass(existingHeading.properties?.className),
|
|
199
|
+
id: headingId
|
|
200
|
+
};
|
|
201
|
+
existingHeading.children = [
|
|
202
|
+
{
|
|
203
|
+
type: "text",
|
|
204
|
+
value: headingText
|
|
205
|
+
}
|
|
206
|
+
];
|
|
207
|
+
return;
|
|
208
|
+
}
|
|
209
|
+
node.children.unshift(
|
|
210
|
+
createHeadingNode(headingTagName, headingId, headingText)
|
|
211
|
+
);
|
|
212
|
+
});
|
|
213
|
+
};
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
// src/remark/custom-syntax/utils.ts
|
|
217
|
+
var import_gray_matter = __toESM(require("gray-matter"), 1);
|
|
218
|
+
var import_remark_gfm = __toESM(require("remark-gfm"), 1);
|
|
219
|
+
var import_remark_parse = __toESM(require("remark-parse"), 1);
|
|
220
|
+
var import_unified = require("unified");
|
|
221
|
+
var remarkGfmPlugin = resolveModuleDefault(import_remark_gfm.default);
|
|
222
|
+
var remarkParsePlugin = resolveModuleDefault(import_remark_parse.default);
|
|
223
|
+
var YAML_PROP_PREFIX = "__YAML__";
|
|
224
|
+
var YAML_BODY_SPLIT_RE = /^---\s*$/;
|
|
225
|
+
var COMPONENT_START_RE = /^::([A-Za-z][A-Za-z0-9_]*)\s*$/;
|
|
226
|
+
var DETAILS_START_RE = /^::\s*details(?:\s+(\[open\]))?(?:\s+(.*\S))?\s*$/i;
|
|
227
|
+
var DOUBLE_BLOCK_START_RE = /^::(?:[A-Za-z][A-Za-z0-9_]*|\s+details(?:\s+.*)?)\s*$/i;
|
|
228
|
+
var BLOCK_END_RE = /^::\s*$/;
|
|
229
|
+
var LEGACY_COMPONENT_RE = /<(AreaChart|ChartTooltip|XAxis|GitHubCalendarCard|MermaidDiagram|Card)\b/;
|
|
230
|
+
var LEGACY_CHART_BLOCK_COMPONENTS = /* @__PURE__ */ new Set([
|
|
231
|
+
"AreaChart",
|
|
232
|
+
"Area",
|
|
233
|
+
"Grid",
|
|
234
|
+
"ChartTooltip",
|
|
235
|
+
"XAxis"
|
|
236
|
+
]);
|
|
237
|
+
function createSourceLineResult(source) {
|
|
238
|
+
return {
|
|
239
|
+
lines: source.split(/\r?\n/)
|
|
240
|
+
};
|
|
241
|
+
}
|
|
242
|
+
function getLine(lines, lineNumber) {
|
|
243
|
+
return lines[lineNumber - 1] ?? "";
|
|
244
|
+
}
|
|
245
|
+
function getNodeSource(source, node) {
|
|
246
|
+
const start = node.position?.start?.offset;
|
|
247
|
+
const end = node.position?.end?.offset;
|
|
248
|
+
if (typeof start !== "number" || typeof end !== "number") {
|
|
249
|
+
return "";
|
|
250
|
+
}
|
|
251
|
+
return source.slice(start, end);
|
|
252
|
+
}
|
|
253
|
+
function parseYamlProps(yamlSource) {
|
|
254
|
+
const trimmed = yamlSource.trim();
|
|
255
|
+
if (!trimmed) {
|
|
256
|
+
return {};
|
|
257
|
+
}
|
|
258
|
+
const { data } = (0, import_gray_matter.default)(`---
|
|
259
|
+
${yamlSource}
|
|
260
|
+
---
|
|
261
|
+
`);
|
|
262
|
+
return data ?? {};
|
|
263
|
+
}
|
|
264
|
+
function escapeHtmlAttr(raw) {
|
|
265
|
+
return raw.replaceAll("&", "&").replaceAll('"', """).replaceAll("<", "<").replaceAll(">", ">");
|
|
266
|
+
}
|
|
267
|
+
function serializeAttrValue(value) {
|
|
268
|
+
if (typeof value === "string") {
|
|
269
|
+
return escapeHtmlAttr(value);
|
|
270
|
+
}
|
|
271
|
+
return `${YAML_PROP_PREFIX}${encodeURIComponent(JSON.stringify(value))}`;
|
|
272
|
+
}
|
|
273
|
+
function createAttribute(name, value) {
|
|
274
|
+
return {
|
|
275
|
+
type: "mdxJsxAttribute",
|
|
276
|
+
name,
|
|
277
|
+
value: value == null ? null : serializeAttrValue(value)
|
|
278
|
+
};
|
|
279
|
+
}
|
|
280
|
+
function createText(value) {
|
|
281
|
+
return {
|
|
282
|
+
type: "text",
|
|
283
|
+
value
|
|
284
|
+
};
|
|
285
|
+
}
|
|
286
|
+
function createFlowElement(name, props = {}, children = []) {
|
|
287
|
+
const node = {
|
|
288
|
+
type: "mdxJsxFlowElement",
|
|
289
|
+
name,
|
|
290
|
+
attributes: Object.entries(props).map(
|
|
291
|
+
([key, value]) => createAttribute(key, value)
|
|
292
|
+
),
|
|
293
|
+
children
|
|
294
|
+
};
|
|
295
|
+
return node;
|
|
296
|
+
}
|
|
297
|
+
function createInlineTextElement(name, props = {}, text = "") {
|
|
298
|
+
const node = {
|
|
299
|
+
type: "mdxJsxTextElement",
|
|
300
|
+
name,
|
|
301
|
+
attributes: Object.entries(props).map(
|
|
302
|
+
([key, value]) => createAttribute(key, value)
|
|
303
|
+
),
|
|
304
|
+
children: text ? [createText(text)] : []
|
|
305
|
+
};
|
|
306
|
+
return node;
|
|
307
|
+
}
|
|
308
|
+
function parseMarkdownFragment(markdown) {
|
|
309
|
+
return (0, import_unified.unified)().use(remarkParsePlugin).use(remarkGfmPlugin).parse(markdown);
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
// src/remark/custom-syntax/handlers/component-block.ts
|
|
313
|
+
function findBlockEnd(lines, startLine, isNestedStart) {
|
|
314
|
+
let cursor = startLine + 1;
|
|
315
|
+
let nestedDepth = 0;
|
|
316
|
+
let innerFenceMarker = null;
|
|
317
|
+
while (cursor <= lines.length) {
|
|
318
|
+
const current = lines[cursor - 1] ?? "";
|
|
319
|
+
if (innerFenceMarker) {
|
|
320
|
+
if (current.trimStart().startsWith(innerFenceMarker)) {
|
|
321
|
+
innerFenceMarker = null;
|
|
322
|
+
}
|
|
323
|
+
cursor += 1;
|
|
324
|
+
continue;
|
|
325
|
+
}
|
|
326
|
+
const trimmedCurrent = current.trimStart();
|
|
327
|
+
if (trimmedCurrent.startsWith("```")) {
|
|
328
|
+
innerFenceMarker = "```";
|
|
329
|
+
cursor += 1;
|
|
330
|
+
continue;
|
|
331
|
+
}
|
|
332
|
+
if (trimmedCurrent.startsWith("~~~")) {
|
|
333
|
+
innerFenceMarker = "~~~";
|
|
334
|
+
cursor += 1;
|
|
335
|
+
continue;
|
|
336
|
+
}
|
|
337
|
+
if (isNestedStart(current) && !BLOCK_END_RE.test(current)) {
|
|
338
|
+
nestedDepth += 1;
|
|
339
|
+
cursor += 1;
|
|
340
|
+
continue;
|
|
341
|
+
}
|
|
342
|
+
if (BLOCK_END_RE.test(current)) {
|
|
343
|
+
if (nestedDepth === 0) {
|
|
344
|
+
return cursor;
|
|
345
|
+
}
|
|
346
|
+
nestedDepth -= 1;
|
|
347
|
+
}
|
|
348
|
+
cursor += 1;
|
|
349
|
+
}
|
|
350
|
+
return -1;
|
|
351
|
+
}
|
|
352
|
+
var componentBlockHandler = {
|
|
353
|
+
kind: "block",
|
|
354
|
+
match: ({ children, index, getNodeSource: getNodeSource2 }) => {
|
|
355
|
+
const node = children[index];
|
|
356
|
+
if (!node) {
|
|
357
|
+
return false;
|
|
358
|
+
}
|
|
359
|
+
const snippet = getNodeSource2(node);
|
|
360
|
+
const firstLine = snippet.split(/\r?\n/, 1)[0]?.trim() ?? "";
|
|
361
|
+
return COMPONENT_START_RE.test(firstLine);
|
|
362
|
+
},
|
|
363
|
+
name: "component-block",
|
|
364
|
+
transform: (context) => {
|
|
365
|
+
const node = context.children[context.index];
|
|
366
|
+
const startLine = node.position?.start?.line;
|
|
367
|
+
if (!startLine) {
|
|
368
|
+
return { consumed: 1, nodes: [node] };
|
|
369
|
+
}
|
|
370
|
+
const openingLine = context.getLine(startLine).trim();
|
|
371
|
+
const componentMatch = openingLine.match(COMPONENT_START_RE);
|
|
372
|
+
if (!componentMatch) {
|
|
373
|
+
return { consumed: 1, nodes: [node] };
|
|
374
|
+
}
|
|
375
|
+
const componentName = componentMatch[1];
|
|
376
|
+
if (LEGACY_CHART_BLOCK_COMPONENTS.has(componentName)) {
|
|
377
|
+
throw new Error(
|
|
378
|
+
`Legacy chart block syntax "::${componentName}" is not supported. Use \`\`\`chart JSON code blocks instead. (line ${startLine})`
|
|
379
|
+
);
|
|
380
|
+
}
|
|
381
|
+
const endLine = findBlockEnd(
|
|
382
|
+
context.lines,
|
|
383
|
+
startLine,
|
|
384
|
+
(line) => COMPONENT_START_RE.test(line)
|
|
385
|
+
);
|
|
386
|
+
if (endLine === -1) {
|
|
387
|
+
throw new Error(
|
|
388
|
+
`Unclosed "::${componentName}" block at line ${startLine}`
|
|
389
|
+
);
|
|
390
|
+
}
|
|
391
|
+
const blockLines = context.lines.slice(startLine, endLine - 1);
|
|
392
|
+
const splitAt = blockLines.findIndex(
|
|
393
|
+
(line) => YAML_BODY_SPLIT_RE.test(line)
|
|
394
|
+
);
|
|
395
|
+
const yamlLines = splitAt === -1 ? blockLines : blockLines.slice(0, splitAt);
|
|
396
|
+
const bodyLines = splitAt === -1 ? [] : blockLines.slice(splitAt + 1);
|
|
397
|
+
const props = context.parseYamlProps(yamlLines.join("\n"));
|
|
398
|
+
const bodyMarkdown = bodyLines.join("\n");
|
|
399
|
+
const children = bodyMarkdown ? context.transformFragment(bodyMarkdown) : [];
|
|
400
|
+
return {
|
|
401
|
+
consumed: context.consumeThroughLine(endLine),
|
|
402
|
+
nodes: [context.createFlowElement(componentName, props, children)]
|
|
403
|
+
};
|
|
404
|
+
}
|
|
405
|
+
};
|
|
406
|
+
|
|
407
|
+
// src/remark/custom-syntax/handlers/details-block.ts
|
|
408
|
+
function findDetailsEnd(lines, startLine) {
|
|
409
|
+
let cursor = startLine + 1;
|
|
410
|
+
let nestedDepth = 0;
|
|
411
|
+
let innerFenceMarker = null;
|
|
412
|
+
while (cursor <= lines.length) {
|
|
413
|
+
const current = lines[cursor - 1] ?? "";
|
|
414
|
+
if (innerFenceMarker) {
|
|
415
|
+
if (current.trimStart().startsWith(innerFenceMarker)) {
|
|
416
|
+
innerFenceMarker = null;
|
|
417
|
+
}
|
|
418
|
+
cursor += 1;
|
|
419
|
+
continue;
|
|
420
|
+
}
|
|
421
|
+
const trimmedCurrent = current.trimStart();
|
|
422
|
+
if (trimmedCurrent.startsWith("```")) {
|
|
423
|
+
innerFenceMarker = "```";
|
|
424
|
+
cursor += 1;
|
|
425
|
+
continue;
|
|
426
|
+
}
|
|
427
|
+
if (trimmedCurrent.startsWith("~~~")) {
|
|
428
|
+
innerFenceMarker = "~~~";
|
|
429
|
+
cursor += 1;
|
|
430
|
+
continue;
|
|
431
|
+
}
|
|
432
|
+
if (DOUBLE_BLOCK_START_RE.test(current) && !BLOCK_END_RE.test(current)) {
|
|
433
|
+
nestedDepth += 1;
|
|
434
|
+
cursor += 1;
|
|
435
|
+
continue;
|
|
436
|
+
}
|
|
437
|
+
if (BLOCK_END_RE.test(current)) {
|
|
438
|
+
if (nestedDepth === 0) {
|
|
439
|
+
return cursor;
|
|
440
|
+
}
|
|
441
|
+
nestedDepth -= 1;
|
|
442
|
+
}
|
|
443
|
+
cursor += 1;
|
|
444
|
+
}
|
|
445
|
+
return -1;
|
|
446
|
+
}
|
|
447
|
+
var detailsBlockHandler = {
|
|
448
|
+
kind: "container",
|
|
449
|
+
match: ({ children, index, getNodeSource: getNodeSource2 }) => {
|
|
450
|
+
const node = children[index];
|
|
451
|
+
if (!node) {
|
|
452
|
+
return false;
|
|
453
|
+
}
|
|
454
|
+
const snippet = getNodeSource2(node);
|
|
455
|
+
const firstLine = snippet.split(/\r?\n/, 1)[0]?.trim() ?? "";
|
|
456
|
+
return DETAILS_START_RE.test(firstLine);
|
|
457
|
+
},
|
|
458
|
+
name: "details-block",
|
|
459
|
+
priority: 10,
|
|
460
|
+
transform: (context) => {
|
|
461
|
+
const node = context.children[context.index];
|
|
462
|
+
const startLine = node.position?.start?.line;
|
|
463
|
+
if (!startLine) {
|
|
464
|
+
return { consumed: 1, nodes: [node] };
|
|
465
|
+
}
|
|
466
|
+
const openingLine = context.getLine(startLine).trim();
|
|
467
|
+
const detailsMatch = openingLine.match(DETAILS_START_RE);
|
|
468
|
+
if (!detailsMatch) {
|
|
469
|
+
return { consumed: 1, nodes: [node] };
|
|
470
|
+
}
|
|
471
|
+
const endLine = findDetailsEnd(context.lines, startLine);
|
|
472
|
+
if (endLine === -1) {
|
|
473
|
+
throw new Error(`Unclosed ":: details" block at line ${startLine}`);
|
|
474
|
+
}
|
|
475
|
+
const bodyMarkdown = context.lines.slice(startLine, endLine - 1).join("\n");
|
|
476
|
+
const summaryText = detailsMatch[2]?.trim() ?? "";
|
|
477
|
+
const children = [
|
|
478
|
+
context.createFlowElement("summary", {}, [
|
|
479
|
+
context.createText(summaryText || "Details")
|
|
480
|
+
]),
|
|
481
|
+
...context.transformFragment(bodyMarkdown)
|
|
482
|
+
];
|
|
483
|
+
const props = detailsMatch[1] ? { open: true } : {};
|
|
484
|
+
return {
|
|
485
|
+
consumed: context.consumeThroughLine(endLine),
|
|
486
|
+
nodes: [context.createFlowElement("details", props, children)]
|
|
487
|
+
};
|
|
488
|
+
}
|
|
489
|
+
};
|
|
490
|
+
|
|
491
|
+
// src/remark/custom-syntax/handlers/inline-component.ts
|
|
492
|
+
var INLINE_COMPONENT_DEFINITIONS = {
|
|
493
|
+
badge: {
|
|
494
|
+
buildProps: ({ option, params }) => {
|
|
495
|
+
const shape = params.shape || params.variant || option || "default";
|
|
496
|
+
return { shape };
|
|
497
|
+
},
|
|
498
|
+
resolveComponentName: (context) => context.componentNames.badge
|
|
499
|
+
},
|
|
500
|
+
tip: {
|
|
501
|
+
buildProps: ({ body, option, params }) => ({
|
|
502
|
+
text: body,
|
|
503
|
+
tip: params.tip || params.tooltip || params.message || option || "",
|
|
504
|
+
copy: params.copy === "false" ? false : params.copy ? true : option === "copy" ? true : params.value ? true : false,
|
|
505
|
+
value: params.value || ""
|
|
506
|
+
}),
|
|
507
|
+
resolveComponentName: (context) => context.componentNames.tip
|
|
508
|
+
}
|
|
509
|
+
};
|
|
510
|
+
function parseInlineComponentParams(option) {
|
|
511
|
+
const trimmed = option.trim();
|
|
512
|
+
if (!trimmed) {
|
|
513
|
+
return {
|
|
514
|
+
option: trimmed,
|
|
515
|
+
params: {}
|
|
516
|
+
};
|
|
517
|
+
}
|
|
518
|
+
if (!trimmed.includes("=") && !trimmed.includes(",")) {
|
|
519
|
+
return {
|
|
520
|
+
option: trimmed,
|
|
521
|
+
params: {}
|
|
522
|
+
};
|
|
523
|
+
}
|
|
524
|
+
const params = {};
|
|
525
|
+
let hasInvalidSegment = false;
|
|
526
|
+
for (const segment of trimmed.split(",")) {
|
|
527
|
+
const entry = segment.trim();
|
|
528
|
+
if (!entry) {
|
|
529
|
+
continue;
|
|
530
|
+
}
|
|
531
|
+
const separatorIndex = entry.indexOf("=");
|
|
532
|
+
if (separatorIndex === -1) {
|
|
533
|
+
params[entry] = "true";
|
|
534
|
+
continue;
|
|
535
|
+
}
|
|
536
|
+
const key = entry.slice(0, separatorIndex).trim();
|
|
537
|
+
const value = entry.slice(separatorIndex + 1).trim();
|
|
538
|
+
if (!key) {
|
|
539
|
+
hasInvalidSegment = true;
|
|
540
|
+
break;
|
|
541
|
+
}
|
|
542
|
+
params[key] = value;
|
|
543
|
+
}
|
|
544
|
+
if (hasInvalidSegment) {
|
|
545
|
+
return {
|
|
546
|
+
option: trimmed,
|
|
547
|
+
params: {}
|
|
548
|
+
};
|
|
549
|
+
}
|
|
550
|
+
return {
|
|
551
|
+
option: "",
|
|
552
|
+
params
|
|
553
|
+
};
|
|
554
|
+
}
|
|
555
|
+
var INLINE_COMPONENT_RE = /(^|[^\\]):([A-Za-z][A-Za-z0-9_-]*)\[([^\]]*)\]\(([^)]*)\)/g;
|
|
556
|
+
function extractInlineText(children) {
|
|
557
|
+
return children.map(
|
|
558
|
+
(child) => child.type === "text" ? typeof child.value === "string" ? child.value : "" : "children" in child ? extractInlineText(child.children) : ""
|
|
559
|
+
).join("");
|
|
560
|
+
}
|
|
561
|
+
function buildInlineComponentNode(context, name, body, rawOption) {
|
|
562
|
+
const definition = INLINE_COMPONENT_DEFINITIONS[name];
|
|
563
|
+
if (!definition) {
|
|
564
|
+
return null;
|
|
565
|
+
}
|
|
566
|
+
const parsedOption = parseInlineComponentParams(rawOption);
|
|
567
|
+
return context.createInlineTextElement(
|
|
568
|
+
definition.resolveComponentName(context),
|
|
569
|
+
definition.buildProps({
|
|
570
|
+
body,
|
|
571
|
+
name,
|
|
572
|
+
option: parsedOption.option,
|
|
573
|
+
params: parsedOption.params
|
|
574
|
+
}),
|
|
575
|
+
body
|
|
576
|
+
);
|
|
577
|
+
}
|
|
578
|
+
function isInlineLinkCandidate(node) {
|
|
579
|
+
return node?.type === "link";
|
|
580
|
+
}
|
|
581
|
+
var inlineComponentHandler = {
|
|
582
|
+
kind: "inline",
|
|
583
|
+
match: (nodes, index) => {
|
|
584
|
+
const current = nodes[index];
|
|
585
|
+
const next = nodes[index + 1];
|
|
586
|
+
if (current?.type === "text" && typeof current.value === "string" && /(^|[^\\]):([A-Za-z][A-Za-z0-9_-]*)$/.test(current.value) && isInlineLinkCandidate(next)) {
|
|
587
|
+
return true;
|
|
588
|
+
}
|
|
589
|
+
if (current?.type !== "text" || typeof current.value !== "string") {
|
|
590
|
+
return false;
|
|
591
|
+
}
|
|
592
|
+
INLINE_COMPONENT_RE.lastIndex = 0;
|
|
593
|
+
return INLINE_COMPONENT_RE.test(current.value);
|
|
594
|
+
},
|
|
595
|
+
name: "inline-component",
|
|
596
|
+
transform: (nodes, index, context) => {
|
|
597
|
+
const current = nodes[index];
|
|
598
|
+
const next = nodes[index + 1];
|
|
599
|
+
if (current?.type !== "text" || typeof current.value !== "string") {
|
|
600
|
+
return { consumed: 1, nodes: current ? [current] : [] };
|
|
601
|
+
}
|
|
602
|
+
const markerMatch = current.value.match(
|
|
603
|
+
/^(.*?)(?<!\\):([A-Za-z][A-Za-z0-9_-]*)$/
|
|
604
|
+
);
|
|
605
|
+
if (markerMatch && isInlineLinkCandidate(next)) {
|
|
606
|
+
const leadingText = markerMatch[1] ?? "";
|
|
607
|
+
const name = markerMatch[2];
|
|
608
|
+
const body = extractInlineText(next.children);
|
|
609
|
+
const componentNode = buildInlineComponentNode(
|
|
610
|
+
context,
|
|
611
|
+
name,
|
|
612
|
+
body,
|
|
613
|
+
next.url
|
|
614
|
+
);
|
|
615
|
+
if (!componentNode) {
|
|
616
|
+
return { consumed: 1, nodes: [current] };
|
|
617
|
+
}
|
|
618
|
+
return {
|
|
619
|
+
consumed: 2,
|
|
620
|
+
nodes: [
|
|
621
|
+
...leadingText ? [context.createText(leadingText)] : [],
|
|
622
|
+
componentNode
|
|
623
|
+
]
|
|
624
|
+
};
|
|
625
|
+
}
|
|
626
|
+
const output = [];
|
|
627
|
+
const source = current.value;
|
|
628
|
+
let lastIndex = 0;
|
|
629
|
+
INLINE_COMPONENT_RE.lastIndex = 0;
|
|
630
|
+
for (const match of source.matchAll(INLINE_COMPONENT_RE)) {
|
|
631
|
+
const fullMatch = match[0];
|
|
632
|
+
const prefix = match[1] ?? "";
|
|
633
|
+
const name = match[2];
|
|
634
|
+
const body = match[3] ?? "";
|
|
635
|
+
const rawOption = match[4] ?? "";
|
|
636
|
+
const start = match.index ?? 0;
|
|
637
|
+
const matchStart = start + prefix.length;
|
|
638
|
+
const before = source.slice(lastIndex, matchStart);
|
|
639
|
+
if (before) {
|
|
640
|
+
output.push(context.createText(before));
|
|
641
|
+
}
|
|
642
|
+
const componentNode = buildInlineComponentNode(
|
|
643
|
+
context,
|
|
644
|
+
name,
|
|
645
|
+
body,
|
|
646
|
+
rawOption
|
|
647
|
+
);
|
|
648
|
+
if (componentNode) {
|
|
649
|
+
output.push(componentNode);
|
|
650
|
+
} else {
|
|
651
|
+
output.push(context.createText(fullMatch.slice(prefix.length)));
|
|
652
|
+
}
|
|
653
|
+
lastIndex = start + fullMatch.length;
|
|
654
|
+
}
|
|
655
|
+
if (lastIndex < source.length) {
|
|
656
|
+
output.push(context.createText(source.slice(lastIndex)));
|
|
657
|
+
}
|
|
658
|
+
return {
|
|
659
|
+
consumed: 1,
|
|
660
|
+
nodes: output.length > 0 ? output : [current]
|
|
661
|
+
};
|
|
662
|
+
}
|
|
663
|
+
};
|
|
664
|
+
|
|
665
|
+
// src/remark/custom-syntax/handlers/legacy-guard.ts
|
|
666
|
+
var legacyGuardBlockHandler = {
|
|
667
|
+
kind: "block",
|
|
668
|
+
match: ({ children, index, getNodeSource: getNodeSource2 }) => {
|
|
669
|
+
const node = children[index];
|
|
670
|
+
if (!node) {
|
|
671
|
+
return false;
|
|
672
|
+
}
|
|
673
|
+
if (node.type === "html" && typeof node.value === "string" && LEGACY_COMPONENT_RE.test(node.value)) {
|
|
674
|
+
return true;
|
|
675
|
+
}
|
|
676
|
+
const snippet = getNodeSource2(node);
|
|
677
|
+
const firstLine = snippet.split(/\r?\n/, 1)[0]?.trim() ?? "";
|
|
678
|
+
const match = firstLine.match(COMPONENT_START_RE);
|
|
679
|
+
return Boolean(match && LEGACY_CHART_BLOCK_COMPONENTS.has(match[1]));
|
|
680
|
+
},
|
|
681
|
+
name: "legacy-guard-block",
|
|
682
|
+
priority: 100,
|
|
683
|
+
transform: (context) => {
|
|
684
|
+
const node = context.children[context.index];
|
|
685
|
+
const startLine = node?.position?.start?.line ?? context.index + 1;
|
|
686
|
+
if (node?.type === "html" && typeof node.value === "string" && LEGACY_COMPONENT_RE.test(node.value)) {
|
|
687
|
+
throw new Error(
|
|
688
|
+
`Legacy MDX component syntax is not supported. Use "::ComponentName" with YAML props instead. (line ${startLine})`
|
|
689
|
+
);
|
|
690
|
+
}
|
|
691
|
+
const openingLine = context.getLine(startLine).trim();
|
|
692
|
+
const match = openingLine.match(COMPONENT_START_RE);
|
|
693
|
+
if (match && LEGACY_CHART_BLOCK_COMPONENTS.has(match[1])) {
|
|
694
|
+
throw new Error(
|
|
695
|
+
`Legacy chart block syntax "::${match[1]}" is not supported. Use \`\`\`chart JSON code blocks instead. (line ${startLine})`
|
|
696
|
+
);
|
|
697
|
+
}
|
|
698
|
+
return { consumed: 1, nodes: node ? [node] : [] };
|
|
699
|
+
}
|
|
700
|
+
};
|
|
701
|
+
|
|
702
|
+
// src/remark/custom-syntax/handlers/tabs-block.ts
|
|
703
|
+
var TABS_START_RE = /^::tabs\s*$/i;
|
|
704
|
+
function findTabsEnd(lines, startLine) {
|
|
705
|
+
let cursor = startLine + 1;
|
|
706
|
+
let nestedDepth = 0;
|
|
707
|
+
let innerFenceMarker = null;
|
|
708
|
+
while (cursor <= lines.length) {
|
|
709
|
+
const current = lines[cursor - 1] ?? "";
|
|
710
|
+
if (innerFenceMarker) {
|
|
711
|
+
if (current.trimStart().startsWith(innerFenceMarker)) {
|
|
712
|
+
innerFenceMarker = null;
|
|
713
|
+
}
|
|
714
|
+
cursor += 1;
|
|
715
|
+
continue;
|
|
716
|
+
}
|
|
717
|
+
const trimmedCurrent = current.trimStart();
|
|
718
|
+
if (trimmedCurrent.startsWith("```")) {
|
|
719
|
+
innerFenceMarker = "```";
|
|
720
|
+
cursor += 1;
|
|
721
|
+
continue;
|
|
722
|
+
}
|
|
723
|
+
if (trimmedCurrent.startsWith("~~~")) {
|
|
724
|
+
innerFenceMarker = "~~~";
|
|
725
|
+
cursor += 1;
|
|
726
|
+
continue;
|
|
727
|
+
}
|
|
728
|
+
if (TABS_START_RE.test(current)) {
|
|
729
|
+
nestedDepth += 1;
|
|
730
|
+
cursor += 1;
|
|
731
|
+
continue;
|
|
732
|
+
}
|
|
733
|
+
if (BLOCK_END_RE.test(current)) {
|
|
734
|
+
if (nestedDepth === 0) {
|
|
735
|
+
return cursor;
|
|
736
|
+
}
|
|
737
|
+
nestedDepth -= 1;
|
|
738
|
+
}
|
|
739
|
+
cursor += 1;
|
|
740
|
+
}
|
|
741
|
+
return -1;
|
|
742
|
+
}
|
|
743
|
+
function splitTabSections(value) {
|
|
744
|
+
const lines = value.split(/\r?\n/);
|
|
745
|
+
const sections = [];
|
|
746
|
+
let currentSection = [];
|
|
747
|
+
let yamlSource = "";
|
|
748
|
+
let yamlCaptured = false;
|
|
749
|
+
let inInnerFence = null;
|
|
750
|
+
for (const line of lines) {
|
|
751
|
+
const trimmed = line.trim();
|
|
752
|
+
if (inInnerFence) {
|
|
753
|
+
if (trimmed.startsWith(inInnerFence)) {
|
|
754
|
+
inInnerFence = null;
|
|
755
|
+
}
|
|
756
|
+
currentSection.push(line);
|
|
757
|
+
continue;
|
|
758
|
+
}
|
|
759
|
+
if (trimmed.startsWith("```")) {
|
|
760
|
+
inInnerFence = "```";
|
|
761
|
+
currentSection.push(line);
|
|
762
|
+
continue;
|
|
763
|
+
}
|
|
764
|
+
if (trimmed.startsWith("~~~")) {
|
|
765
|
+
inInnerFence = "~~~";
|
|
766
|
+
currentSection.push(line);
|
|
767
|
+
continue;
|
|
768
|
+
}
|
|
769
|
+
if (YAML_BODY_SPLIT_RE.test(line)) {
|
|
770
|
+
if (!yamlCaptured) {
|
|
771
|
+
yamlSource = currentSection.join("\n");
|
|
772
|
+
yamlCaptured = true;
|
|
773
|
+
} else {
|
|
774
|
+
sections.push(currentSection.join("\n"));
|
|
775
|
+
}
|
|
776
|
+
currentSection = [];
|
|
777
|
+
continue;
|
|
778
|
+
}
|
|
779
|
+
currentSection.push(line);
|
|
780
|
+
}
|
|
781
|
+
sections.push(currentSection.join("\n"));
|
|
782
|
+
return {
|
|
783
|
+
sections,
|
|
784
|
+
yamlSource
|
|
785
|
+
};
|
|
786
|
+
}
|
|
787
|
+
var tabsBlockHandler = {
|
|
788
|
+
kind: "container",
|
|
789
|
+
match: ({ children, index, getNodeSource: getNodeSource2 }) => {
|
|
790
|
+
const node = children[index];
|
|
791
|
+
if (!node) {
|
|
792
|
+
return false;
|
|
793
|
+
}
|
|
794
|
+
const snippet = getNodeSource2(node);
|
|
795
|
+
const firstLine = snippet.split(/\r?\n/, 1)[0]?.trim() ?? "";
|
|
796
|
+
return TABS_START_RE.test(firstLine);
|
|
797
|
+
},
|
|
798
|
+
name: "tabs-block",
|
|
799
|
+
priority: 20,
|
|
800
|
+
transform: (context) => {
|
|
801
|
+
const node = context.children[context.index];
|
|
802
|
+
const startLine = node.position?.start?.line;
|
|
803
|
+
if (!startLine) {
|
|
804
|
+
return { consumed: 1, nodes: [node] };
|
|
805
|
+
}
|
|
806
|
+
const openingLine = context.getLine(startLine).trim();
|
|
807
|
+
if (!TABS_START_RE.test(openingLine)) {
|
|
808
|
+
return { consumed: 1, nodes: [node] };
|
|
809
|
+
}
|
|
810
|
+
const endLine = findTabsEnd(context.lines, startLine);
|
|
811
|
+
if (endLine === -1) {
|
|
812
|
+
throw new Error(`Unclosed "::tabs" block at line ${startLine}`);
|
|
813
|
+
}
|
|
814
|
+
const blockLines = context.lines.slice(startLine, endLine - 1);
|
|
815
|
+
const { sections, yamlSource } = splitTabSections(blockLines.join("\n"));
|
|
816
|
+
const props = context.parseYamlProps(yamlSource);
|
|
817
|
+
const labels = Array.isArray(props.tabs) ? props.tabs : [];
|
|
818
|
+
delete props.tabs;
|
|
819
|
+
const tabsData = sections.map((section) => section.trim()).filter((section, index) => section.length > 0 || index < labels.length).map((section, index) => ({
|
|
820
|
+
content: section,
|
|
821
|
+
label: typeof labels[index] === "string" ? labels[index] : `Tab ${index + 1}`,
|
|
822
|
+
value: `tab-${index}`
|
|
823
|
+
}));
|
|
824
|
+
if (tabsData.length === 0) {
|
|
825
|
+
return {
|
|
826
|
+
consumed: context.consumeThroughLine(endLine),
|
|
827
|
+
nodes: []
|
|
828
|
+
};
|
|
829
|
+
}
|
|
830
|
+
const defaultValue = typeof props.defaultValue === "string" ? props.defaultValue : tabsData[0]?.value ?? "";
|
|
831
|
+
const tabsProps = { ...props, defaultValue };
|
|
832
|
+
const tabsListChildren = tabsData.map(
|
|
833
|
+
(tab) => context.createFlowElement(
|
|
834
|
+
context.componentNames.tabsTrigger,
|
|
835
|
+
{ value: tab.value },
|
|
836
|
+
[context.createText(tab.label)]
|
|
837
|
+
)
|
|
838
|
+
);
|
|
839
|
+
const tabsContentChildren = tabsData.map(
|
|
840
|
+
(tab) => context.createFlowElement(
|
|
841
|
+
context.componentNames.tabsContent,
|
|
842
|
+
{ value: tab.value },
|
|
843
|
+
[...context.transformFragment(tab.content)]
|
|
844
|
+
)
|
|
845
|
+
);
|
|
846
|
+
return {
|
|
847
|
+
consumed: context.consumeThroughLine(endLine),
|
|
848
|
+
nodes: [
|
|
849
|
+
context.createFlowElement(context.componentNames.tabs, tabsProps, [
|
|
850
|
+
context.createFlowElement(
|
|
851
|
+
context.componentNames.tabsList,
|
|
852
|
+
{},
|
|
853
|
+
tabsListChildren
|
|
854
|
+
),
|
|
855
|
+
...tabsContentChildren
|
|
856
|
+
])
|
|
857
|
+
]
|
|
858
|
+
};
|
|
859
|
+
}
|
|
860
|
+
};
|
|
861
|
+
|
|
862
|
+
// src/remark/custom-syntax/types.ts
|
|
863
|
+
var DEFAULT_CUSTOM_SYNTAX_COMPONENT_NAMES = {
|
|
864
|
+
badge: "Badge",
|
|
865
|
+
tip: "Tip",
|
|
866
|
+
tabs: "Tabs",
|
|
867
|
+
tabsList: "TabsList",
|
|
868
|
+
tabsTrigger: "TabsTrigger",
|
|
869
|
+
tabsContent: "TabsContent"
|
|
870
|
+
};
|
|
871
|
+
function resolveCustomSyntaxComponentNames(options) {
|
|
872
|
+
return {
|
|
873
|
+
...DEFAULT_CUSTOM_SYNTAX_COMPONENT_NAMES,
|
|
874
|
+
...options?.componentNames
|
|
875
|
+
};
|
|
876
|
+
}
|
|
877
|
+
|
|
878
|
+
// src/remark/custom-syntax/plugin.ts
|
|
879
|
+
var BLOCK_HANDLERS = [
|
|
880
|
+
legacyGuardBlockHandler,
|
|
881
|
+
detailsBlockHandler,
|
|
882
|
+
tabsBlockHandler,
|
|
883
|
+
componentBlockHandler
|
|
884
|
+
].sort((left, right) => (right.priority ?? 0) - (left.priority ?? 0));
|
|
885
|
+
var INLINE_HANDLERS = [
|
|
886
|
+
inlineComponentHandler
|
|
887
|
+
].sort((left, right) => (right.priority ?? 0) - (left.priority ?? 0));
|
|
888
|
+
function isParent(value) {
|
|
889
|
+
return Boolean(value && typeof value === "object" && "children" in value);
|
|
890
|
+
}
|
|
891
|
+
function isGeneratedMdxNode(value) {
|
|
892
|
+
const nodeType = value.type;
|
|
893
|
+
return nodeType === "mdxJsxFlowElement" || nodeType === "mdxJsxTextElement";
|
|
894
|
+
}
|
|
895
|
+
function transformInlineChildren(parent, source, options) {
|
|
896
|
+
const nextChildren = [];
|
|
897
|
+
let index = 0;
|
|
898
|
+
const componentNames = resolveCustomSyntaxComponentNames(options);
|
|
899
|
+
while (index < parent.children.length) {
|
|
900
|
+
const handler = INLINE_HANDLERS.find(
|
|
901
|
+
(candidate) => candidate.match(parent.children, index, {
|
|
902
|
+
componentNames,
|
|
903
|
+
createInlineTextElement,
|
|
904
|
+
createText,
|
|
905
|
+
getNodeSource: (node) => getNodeSource(source, node),
|
|
906
|
+
source
|
|
907
|
+
})
|
|
908
|
+
);
|
|
909
|
+
if (!handler) {
|
|
910
|
+
nextChildren.push(parent.children[index]);
|
|
911
|
+
index += 1;
|
|
912
|
+
continue;
|
|
913
|
+
}
|
|
914
|
+
const result = handler.transform(parent.children, index, {
|
|
915
|
+
componentNames,
|
|
916
|
+
createInlineTextElement,
|
|
917
|
+
createText,
|
|
918
|
+
getNodeSource: (node) => getNodeSource(source, node),
|
|
919
|
+
source
|
|
920
|
+
});
|
|
921
|
+
nextChildren.push(...result.nodes);
|
|
922
|
+
index += result.consumed;
|
|
923
|
+
}
|
|
924
|
+
parent.children = nextChildren;
|
|
925
|
+
}
|
|
926
|
+
function transformBlockChildren(parent, source, transformTree2, options) {
|
|
927
|
+
const { lines } = createSourceLineResult(source);
|
|
928
|
+
const originalChildren = parent.children;
|
|
929
|
+
const nextChildren = [];
|
|
930
|
+
let index = 0;
|
|
931
|
+
const componentNames = resolveCustomSyntaxComponentNames(options);
|
|
932
|
+
while (index < originalChildren.length) {
|
|
933
|
+
const handler = BLOCK_HANDLERS.find(
|
|
934
|
+
(candidate) => candidate.match({
|
|
935
|
+
children: originalChildren,
|
|
936
|
+
componentNames,
|
|
937
|
+
getNodeSource: (node) => getNodeSource(source, node),
|
|
938
|
+
index,
|
|
939
|
+
lines,
|
|
940
|
+
source
|
|
941
|
+
})
|
|
942
|
+
);
|
|
943
|
+
if (!handler) {
|
|
944
|
+
nextChildren.push(originalChildren[index]);
|
|
945
|
+
index += 1;
|
|
946
|
+
continue;
|
|
947
|
+
}
|
|
948
|
+
const result = handler.transform({
|
|
949
|
+
children: originalChildren,
|
|
950
|
+
componentNames,
|
|
951
|
+
index,
|
|
952
|
+
lines,
|
|
953
|
+
source,
|
|
954
|
+
consumeThroughLine: (endLine) => {
|
|
955
|
+
let cursor = index;
|
|
956
|
+
while (cursor < originalChildren.length) {
|
|
957
|
+
const childEndLine = originalChildren[cursor]?.position?.end?.line;
|
|
958
|
+
if (typeof childEndLine === "number" && childEndLine >= endLine) {
|
|
959
|
+
return cursor - index + 1;
|
|
960
|
+
}
|
|
961
|
+
cursor += 1;
|
|
962
|
+
}
|
|
963
|
+
return originalChildren.length - index;
|
|
964
|
+
},
|
|
965
|
+
createFlowElement,
|
|
966
|
+
createInlineTextElement,
|
|
967
|
+
createText,
|
|
968
|
+
getLine: (lineNumber) => getLine(lines, lineNumber),
|
|
969
|
+
getNodeSource: (node) => getNodeSource(source, node),
|
|
970
|
+
parseYamlProps,
|
|
971
|
+
transformFragment: (markdown) => {
|
|
972
|
+
const fragmentTree = parseMarkdownFragment(markdown);
|
|
973
|
+
return transformTree2(fragmentTree, markdown, options).children;
|
|
974
|
+
}
|
|
975
|
+
});
|
|
976
|
+
nextChildren.push(...result.nodes);
|
|
977
|
+
index += result.consumed;
|
|
978
|
+
}
|
|
979
|
+
parent.children = nextChildren;
|
|
980
|
+
}
|
|
981
|
+
function transformTree(tree, sourceOverride = "", options) {
|
|
982
|
+
const source = sourceOverride;
|
|
983
|
+
const walk = (node) => {
|
|
984
|
+
if (!isParent(node)) {
|
|
985
|
+
return;
|
|
986
|
+
}
|
|
987
|
+
transformBlockChildren(node, source, transformTree, options);
|
|
988
|
+
transformInlineChildren(node, source, options);
|
|
989
|
+
for (const child of node.children) {
|
|
990
|
+
if (isGeneratedMdxNode(child)) {
|
|
991
|
+
continue;
|
|
992
|
+
}
|
|
993
|
+
walk(child);
|
|
994
|
+
}
|
|
995
|
+
};
|
|
996
|
+
walk(tree);
|
|
997
|
+
return tree;
|
|
998
|
+
}
|
|
999
|
+
function createCustomSyntaxRemarkPlugin(options) {
|
|
1000
|
+
return (tree, file) => {
|
|
1001
|
+
const source = typeof file?.value === "string" ? file.value : "";
|
|
1002
|
+
transformTree(tree, source, options);
|
|
1003
|
+
};
|
|
1004
|
+
}
|
|
1005
|
+
|
|
1006
|
+
// src/remark/supersub.ts
|
|
1007
|
+
function isParent2(node) {
|
|
1008
|
+
return Array.isArray(node.children);
|
|
1009
|
+
}
|
|
1010
|
+
function isWhitespace(char) {
|
|
1011
|
+
return char !== void 0 && /\s/.test(char);
|
|
1012
|
+
}
|
|
1013
|
+
function canOpenMarker(value, index, marker) {
|
|
1014
|
+
const previousChar = value[index - 1];
|
|
1015
|
+
const nextChar = value[index + 1];
|
|
1016
|
+
if (!nextChar || isWhitespace(nextChar)) {
|
|
1017
|
+
return false;
|
|
1018
|
+
}
|
|
1019
|
+
if (marker === "~") {
|
|
1020
|
+
return previousChar !== "~" && nextChar !== "~";
|
|
1021
|
+
}
|
|
1022
|
+
return true;
|
|
1023
|
+
}
|
|
1024
|
+
function isValidWrappedContent(content) {
|
|
1025
|
+
return Boolean(content.trim()) && content.trim() === content;
|
|
1026
|
+
}
|
|
1027
|
+
function findClosingMarker(value, startIndex, marker) {
|
|
1028
|
+
for (let index = startIndex; index < value.length; index += 1) {
|
|
1029
|
+
if (value[index] !== marker) {
|
|
1030
|
+
continue;
|
|
1031
|
+
}
|
|
1032
|
+
const previousChar = value[index - 1];
|
|
1033
|
+
const nextChar = value[index + 1];
|
|
1034
|
+
if (previousChar === "\\") {
|
|
1035
|
+
continue;
|
|
1036
|
+
}
|
|
1037
|
+
if (marker === "~" && (previousChar === "~" || nextChar === "~")) {
|
|
1038
|
+
continue;
|
|
1039
|
+
}
|
|
1040
|
+
const content = value.slice(startIndex, index);
|
|
1041
|
+
if (isValidWrappedContent(content)) {
|
|
1042
|
+
return index;
|
|
1043
|
+
}
|
|
1044
|
+
}
|
|
1045
|
+
return -1;
|
|
1046
|
+
}
|
|
1047
|
+
function createTextNode(value) {
|
|
1048
|
+
return { type: "text", value };
|
|
1049
|
+
}
|
|
1050
|
+
function createWrappedNode(marker, value) {
|
|
1051
|
+
return {
|
|
1052
|
+
type: "mdxJsxTextElement",
|
|
1053
|
+
name: marker === "^" ? "sup" : "sub",
|
|
1054
|
+
attributes: [],
|
|
1055
|
+
children: [{ type: "text", value }]
|
|
1056
|
+
};
|
|
1057
|
+
}
|
|
1058
|
+
function transformTextNode(value) {
|
|
1059
|
+
const output = [];
|
|
1060
|
+
let buffer = "";
|
|
1061
|
+
let changed = false;
|
|
1062
|
+
for (let index = 0; index < value.length; index += 1) {
|
|
1063
|
+
const char = value[index];
|
|
1064
|
+
if ((char === "^" || char === "~") && canOpenMarker(value, index, char)) {
|
|
1065
|
+
const closingIndex = findClosingMarker(value, index + 1, char);
|
|
1066
|
+
if (closingIndex !== -1) {
|
|
1067
|
+
if (buffer) {
|
|
1068
|
+
output.push(createTextNode(buffer));
|
|
1069
|
+
buffer = "";
|
|
1070
|
+
}
|
|
1071
|
+
output.push(
|
|
1072
|
+
createWrappedNode(char, value.slice(index + 1, closingIndex))
|
|
1073
|
+
);
|
|
1074
|
+
index = closingIndex;
|
|
1075
|
+
changed = true;
|
|
1076
|
+
continue;
|
|
1077
|
+
}
|
|
1078
|
+
}
|
|
1079
|
+
buffer += char;
|
|
1080
|
+
}
|
|
1081
|
+
if (!changed) {
|
|
1082
|
+
return null;
|
|
1083
|
+
}
|
|
1084
|
+
if (buffer) {
|
|
1085
|
+
output.push(createTextNode(buffer));
|
|
1086
|
+
}
|
|
1087
|
+
return output;
|
|
1088
|
+
}
|
|
1089
|
+
function transformNode(node) {
|
|
1090
|
+
if (!isParent2(node)) {
|
|
1091
|
+
return;
|
|
1092
|
+
}
|
|
1093
|
+
const nextChildren = [];
|
|
1094
|
+
for (const child of node.children) {
|
|
1095
|
+
if (child.type === "text" && typeof child.value === "string") {
|
|
1096
|
+
const transformed = transformTextNode(child.value);
|
|
1097
|
+
if (transformed) {
|
|
1098
|
+
nextChildren.push(...transformed);
|
|
1099
|
+
continue;
|
|
1100
|
+
}
|
|
1101
|
+
}
|
|
1102
|
+
transformNode(child);
|
|
1103
|
+
nextChildren.push(child);
|
|
1104
|
+
}
|
|
1105
|
+
node.children = nextChildren;
|
|
1106
|
+
}
|
|
1107
|
+
function remarkSuperSub() {
|
|
1108
|
+
return (tree) => {
|
|
1109
|
+
transformNode(tree);
|
|
1110
|
+
};
|
|
1111
|
+
}
|
|
1112
|
+
|
|
1113
|
+
// src/preset.ts
|
|
1114
|
+
var remarkGfmPlugin2 = resolveModuleDefault(import_remark_gfm2.default);
|
|
1115
|
+
function createMarkdownPreset(options) {
|
|
1116
|
+
const customSyntaxPlugin = options?.customSyntax ? function customSyntaxPresetPlugin() {
|
|
1117
|
+
return createCustomSyntaxRemarkPlugin(options.customSyntax);
|
|
1118
|
+
} : createCustomSyntaxRemarkPlugin;
|
|
1119
|
+
const codeFencePlugin = options?.codeFenceMappings ? function codeFencePresetPlugin() {
|
|
1120
|
+
return createCodeFenceComponentPlugin(options.codeFenceMappings);
|
|
1121
|
+
} : createCodeFenceComponentPlugin;
|
|
1122
|
+
const footnotesPlugin = options?.footnotes ? function footnotesPresetPlugin() {
|
|
1123
|
+
return rehypeFootnotesHeading(options.footnotes);
|
|
1124
|
+
} : rehypeFootnotesHeading;
|
|
1125
|
+
return {
|
|
1126
|
+
remarkPlugins: [
|
|
1127
|
+
customSyntaxPlugin,
|
|
1128
|
+
[remarkGfmPlugin2, { singleTilde: false }],
|
|
1129
|
+
remarkSuperSub
|
|
1130
|
+
],
|
|
1131
|
+
rehypePlugins: [
|
|
1132
|
+
codeFencePlugin,
|
|
1133
|
+
footnotesPlugin
|
|
1134
|
+
]
|
|
1135
|
+
};
|
|
1136
|
+
}
|
|
1137
|
+
|
|
1138
|
+
// src/toc/extract-headings.ts
|
|
1139
|
+
var import_github_slugger = __toESM(require("github-slugger"), 1);
|
|
1140
|
+
var import_remark_gfm3 = __toESM(require("remark-gfm"), 1);
|
|
1141
|
+
var import_remark_parse2 = __toESM(require("remark-parse"), 1);
|
|
1142
|
+
var import_unified2 = require("unified");
|
|
1143
|
+
var import_unist_util_visit3 = require("unist-util-visit");
|
|
1144
|
+
var remarkGfmPlugin3 = resolveModuleDefault(import_remark_gfm3.default);
|
|
1145
|
+
var remarkParsePlugin2 = resolveModuleDefault(import_remark_parse2.default);
|
|
1146
|
+
function extractText2(children) {
|
|
1147
|
+
return children.map((child) => {
|
|
1148
|
+
if ("value" in child && typeof child.value === "string") {
|
|
1149
|
+
return child.value;
|
|
1150
|
+
}
|
|
1151
|
+
if ("alt" in child && typeof child.alt === "string") {
|
|
1152
|
+
return child.alt;
|
|
1153
|
+
}
|
|
1154
|
+
if ("children" in child && Array.isArray(child.children)) {
|
|
1155
|
+
return extractText2(child.children);
|
|
1156
|
+
}
|
|
1157
|
+
return "";
|
|
1158
|
+
}).join("");
|
|
1159
|
+
}
|
|
1160
|
+
function extractHeadings(markdown, options) {
|
|
1161
|
+
const tree = (0, import_unified2.unified)().use(remarkParsePlugin2).use(remarkGfmPlugin3).parse(markdown);
|
|
1162
|
+
const slugger = new import_github_slugger.default();
|
|
1163
|
+
const headings = [];
|
|
1164
|
+
const headingId = options?.headingId ?? FOOTNOTES_HEADING_ID;
|
|
1165
|
+
const headingText = options?.headingText ?? FOOTNOTES_HEADING_TEXT;
|
|
1166
|
+
let hasFootnotes = false;
|
|
1167
|
+
(0, import_unist_util_visit3.visit)(tree, "heading", (node) => {
|
|
1168
|
+
if (node.depth !== 1 && node.depth !== 2 && node.depth !== 3) {
|
|
1169
|
+
return;
|
|
1170
|
+
}
|
|
1171
|
+
const text = extractText2(node.children).trim();
|
|
1172
|
+
if (!text) {
|
|
1173
|
+
return;
|
|
1174
|
+
}
|
|
1175
|
+
headings.push({
|
|
1176
|
+
depth: node.depth,
|
|
1177
|
+
text,
|
|
1178
|
+
id: slugger.slug(text)
|
|
1179
|
+
});
|
|
1180
|
+
});
|
|
1181
|
+
(0, import_unist_util_visit3.visit)(tree, "footnoteDefinition", () => {
|
|
1182
|
+
hasFootnotes = true;
|
|
1183
|
+
});
|
|
1184
|
+
if (hasFootnotes) {
|
|
1185
|
+
headings.push({
|
|
1186
|
+
depth: resolveFootnotesHeadingDepth(
|
|
1187
|
+
headings.map((heading) => heading.depth)
|
|
1188
|
+
),
|
|
1189
|
+
text: headingText,
|
|
1190
|
+
id: headingId
|
|
1191
|
+
});
|
|
1192
|
+
}
|
|
1193
|
+
return headings;
|
|
1194
|
+
}
|
|
1195
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
1196
|
+
0 && (module.exports = {
|
|
1197
|
+
DEFAULT_CODE_FENCE_COMPONENT_MAPPINGS,
|
|
1198
|
+
DEFAULT_CUSTOM_SYNTAX_COMPONENT_NAMES,
|
|
1199
|
+
FOOTNOTES_HEADING_ID,
|
|
1200
|
+
FOOTNOTES_HEADING_TEXT,
|
|
1201
|
+
YAML_PROP_PREFIX,
|
|
1202
|
+
createCodeFenceComponentPlugin,
|
|
1203
|
+
createCustomSyntaxRemarkPlugin,
|
|
1204
|
+
createMarkdownPreset,
|
|
1205
|
+
extractHeadings,
|
|
1206
|
+
rehypeFootnotesHeading,
|
|
1207
|
+
remarkSuperSub,
|
|
1208
|
+
resolveCustomSyntaxComponentNames
|
|
1209
|
+
});
|