@ox-content/unplugin 2.90.0 → 3.0.0-alpha.10
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.d.mts +29 -6
- package/dist/src.mjs +81 -12
- package/package.json +6 -6
package/dist/index.d.mts
CHANGED
|
@@ -277,11 +277,24 @@ interface OxContentOptions {
|
|
|
277
277
|
* @default true
|
|
278
278
|
*/
|
|
279
279
|
gfm?: boolean;
|
|
280
|
+
/**
|
|
281
|
+
* Enable MDX JSX, ESM, and expressions.
|
|
282
|
+
*
|
|
283
|
+
* When omitted, MDX is enabled for `.mdx` files only. Explicit `true` or
|
|
284
|
+
* `false` overrides extension-based detection.
|
|
285
|
+
* @default inferred from the source extension
|
|
286
|
+
*/
|
|
287
|
+
mdx?: boolean;
|
|
280
288
|
/**
|
|
281
289
|
* Enable footnotes.
|
|
282
290
|
* @default true
|
|
283
291
|
*/
|
|
284
292
|
footnotes?: boolean;
|
|
293
|
+
/**
|
|
294
|
+
* Render footnotes as a semantic ordered section with numeric markers.
|
|
295
|
+
* @default false
|
|
296
|
+
*/
|
|
297
|
+
semanticFootnotes?: boolean;
|
|
285
298
|
/**
|
|
286
299
|
* Enable tables.
|
|
287
300
|
* @default true
|
|
@@ -302,11 +315,6 @@ interface OxContentOptions {
|
|
|
302
315
|
* @default false
|
|
303
316
|
*/
|
|
304
317
|
highlight?: boolean;
|
|
305
|
-
/**
|
|
306
|
-
* Syntax highlighting theme.
|
|
307
|
-
* @default 'github-dark'
|
|
308
|
-
*/
|
|
309
|
-
highlightTheme?: string;
|
|
310
318
|
/**
|
|
311
319
|
* Opt-in line annotations for fenced code blocks.
|
|
312
320
|
*
|
|
@@ -327,6 +335,13 @@ interface OxContentOptions {
|
|
|
327
335
|
* @default false
|
|
328
336
|
*/
|
|
329
337
|
mermaid?: boolean;
|
|
338
|
+
/**
|
|
339
|
+
* Enable `$…$` inline and `$$…$$` block math.
|
|
340
|
+
* @default false
|
|
341
|
+
*/
|
|
342
|
+
math?: boolean | {
|
|
343
|
+
enabled?: boolean;
|
|
344
|
+
};
|
|
330
345
|
/**
|
|
331
346
|
* Parse YAML frontmatter.
|
|
332
347
|
* @default true
|
|
@@ -392,14 +407,17 @@ interface ResolvedDocsConfig {
|
|
|
392
407
|
interface ResolvedOptions {
|
|
393
408
|
srcDir: string;
|
|
394
409
|
gfm: boolean;
|
|
410
|
+
mdx?: boolean;
|
|
395
411
|
footnotes: boolean;
|
|
412
|
+
/** Present after `resolveOptions`. Omitted in hand-built fixtures means off. */
|
|
413
|
+
semanticFootnotes?: boolean;
|
|
396
414
|
tables: boolean;
|
|
397
415
|
taskLists: boolean;
|
|
398
416
|
strikethrough: boolean;
|
|
399
417
|
highlight: boolean;
|
|
400
|
-
highlightTheme: string;
|
|
401
418
|
codeAnnotations: ResolvedCodeAnnotationsOptions;
|
|
402
419
|
mermaid: boolean;
|
|
420
|
+
math: boolean;
|
|
403
421
|
frontmatter: boolean;
|
|
404
422
|
toc: boolean;
|
|
405
423
|
tocMaxDepth: number;
|
|
@@ -448,6 +466,11 @@ interface OxContentMdastOptions {
|
|
|
448
466
|
* @default true
|
|
449
467
|
*/
|
|
450
468
|
gfm?: boolean;
|
|
469
|
+
/**
|
|
470
|
+
* Enable MDX JSX, ESM, and expression nodes.
|
|
471
|
+
* @default false
|
|
472
|
+
*/
|
|
473
|
+
mdx?: boolean;
|
|
451
474
|
/**
|
|
452
475
|
* Enable footnotes.
|
|
453
476
|
* @default true
|
package/dist/src.mjs
CHANGED
|
@@ -86,6 +86,11 @@ const KIND_DELETE = 19;
|
|
|
86
86
|
const KIND_FOOTNOTE_REFERENCE = 20;
|
|
87
87
|
const KIND_DEFINITION = 21;
|
|
88
88
|
const KIND_FOOTNOTE_DEFINITION = 22;
|
|
89
|
+
const KIND_MDX_JSX_FLOW = 23;
|
|
90
|
+
const KIND_MDX_JSX_TEXT = 24;
|
|
91
|
+
const KIND_MDX_ESM = 25;
|
|
92
|
+
const KIND_MDX_FLOW_EXPRESSION = 26;
|
|
93
|
+
const KIND_MDX_TEXT_EXPRESSION = 27;
|
|
89
94
|
const FLAG_ORDERED = 1;
|
|
90
95
|
const FLAG_SPREAD = 2;
|
|
91
96
|
const FLAG_CHECKED_PRESENT = 4;
|
|
@@ -309,6 +314,35 @@ function deserializeMdastFromRaw(buffer, source) {
|
|
|
309
314
|
if (str1 !== void 0) node.label = str1;
|
|
310
315
|
return node;
|
|
311
316
|
}
|
|
317
|
+
case KIND_MDX_JSX_FLOW: return {
|
|
318
|
+
type: "mdxJsxFlowElement",
|
|
319
|
+
name: str0 ?? null,
|
|
320
|
+
attributes: parseMdxAttributes(str1),
|
|
321
|
+
children: children ?? [],
|
|
322
|
+
position
|
|
323
|
+
};
|
|
324
|
+
case KIND_MDX_JSX_TEXT: return {
|
|
325
|
+
type: "mdxJsxTextElement",
|
|
326
|
+
name: str0 ?? null,
|
|
327
|
+
attributes: parseMdxAttributes(str1),
|
|
328
|
+
children: children ?? [],
|
|
329
|
+
position
|
|
330
|
+
};
|
|
331
|
+
case KIND_MDX_ESM: return {
|
|
332
|
+
type: "mdxjsEsm",
|
|
333
|
+
value: str0 ?? "",
|
|
334
|
+
position
|
|
335
|
+
};
|
|
336
|
+
case KIND_MDX_FLOW_EXPRESSION: return {
|
|
337
|
+
type: "mdxFlowExpression",
|
|
338
|
+
value: str0 ?? "",
|
|
339
|
+
position
|
|
340
|
+
};
|
|
341
|
+
case KIND_MDX_TEXT_EXPRESSION: return {
|
|
342
|
+
type: "mdxTextExpression",
|
|
343
|
+
value: str0 ?? "",
|
|
344
|
+
position
|
|
345
|
+
};
|
|
312
346
|
default: throw new Error(`[ox-content] Unsupported mdast raw node kind: ${kind}`);
|
|
313
347
|
}
|
|
314
348
|
};
|
|
@@ -316,6 +350,17 @@ function deserializeMdastFromRaw(buffer, source) {
|
|
|
316
350
|
if (root.type !== "root" || !Array.isArray(root.children)) throw new Error("[ox-content] Native parser returned an invalid mdast root.");
|
|
317
351
|
return root;
|
|
318
352
|
}
|
|
353
|
+
function parseMdxAttributes(value) {
|
|
354
|
+
if (value === void 0) return [];
|
|
355
|
+
let attributes;
|
|
356
|
+
try {
|
|
357
|
+
attributes = JSON.parse(value);
|
|
358
|
+
} catch {
|
|
359
|
+
throw new Error("[ox-content] mdast raw transfer contains invalid MDX attributes.");
|
|
360
|
+
}
|
|
361
|
+
if (!Array.isArray(attributes)) throw new Error("[ox-content] mdast raw transfer contains invalid MDX attributes.");
|
|
362
|
+
return attributes;
|
|
363
|
+
}
|
|
319
364
|
function readSourceOrigin(buffer, view) {
|
|
320
365
|
const section = parseTransferEnvelope(buffer)?.sections.get(MDAST_SECTION_SOURCE_ORIGIN$1);
|
|
321
366
|
if (!section) return;
|
|
@@ -451,6 +496,7 @@ const require$1 = createRequire(import.meta.url);
|
|
|
451
496
|
let cachedNapiBindings$1;
|
|
452
497
|
const DEFAULT_MDAST_OPTIONS = {
|
|
453
498
|
gfm: true,
|
|
499
|
+
mdx: false,
|
|
454
500
|
footnotes: true,
|
|
455
501
|
taskLists: true,
|
|
456
502
|
tables: true,
|
|
@@ -483,6 +529,7 @@ function parseMarkdownToMdast(source, options = {}) {
|
|
|
483
529
|
const resolvedOptions = resolveMdastOptions(options);
|
|
484
530
|
const parserOptions = {
|
|
485
531
|
gfm: resolvedOptions.gfm,
|
|
532
|
+
mdx: resolvedOptions.mdx,
|
|
486
533
|
footnotes: resolvedOptions.footnotes,
|
|
487
534
|
taskLists: resolvedOptions.taskLists,
|
|
488
535
|
tables: resolvedOptions.tables,
|
|
@@ -550,6 +597,7 @@ function requireNapiMethod$1(method, name) {
|
|
|
550
597
|
function resolveMdastOptions(options) {
|
|
551
598
|
return {
|
|
552
599
|
gfm: options.gfm ?? DEFAULT_MDAST_OPTIONS.gfm,
|
|
600
|
+
mdx: options.mdx ?? DEFAULT_MDAST_OPTIONS.mdx,
|
|
553
601
|
footnotes: options.footnotes ?? DEFAULT_MDAST_OPTIONS.footnotes,
|
|
554
602
|
taskLists: options.taskLists ?? DEFAULT_MDAST_OPTIONS.taskLists,
|
|
555
603
|
tables: options.tables ?? DEFAULT_MDAST_OPTIONS.tables,
|
|
@@ -590,6 +638,21 @@ function slugify$1(text) {
|
|
|
590
638
|
return text.toLowerCase().replace(/[^\p{L}\p{N}\s-]+/gu, " ").trim().split(/\s+/).filter(Boolean).join("-");
|
|
591
639
|
}
|
|
592
640
|
//#endregion
|
|
641
|
+
//#region src/source-path.ts
|
|
642
|
+
function sourcePathname(id) {
|
|
643
|
+
return id.split("?")[0].split("#")[0];
|
|
644
|
+
}
|
|
645
|
+
function isConfiguredSourceFile(id, extensions) {
|
|
646
|
+
const pathname = sourcePathname(id).toLowerCase();
|
|
647
|
+
return extensions.some((extension) => pathname.endsWith(extension.toLowerCase()));
|
|
648
|
+
}
|
|
649
|
+
function isMdxSourceFile(id) {
|
|
650
|
+
return sourcePathname(id).toLowerCase().endsWith(".mdx");
|
|
651
|
+
}
|
|
652
|
+
function resolveMdxForSourceFile(id, configured) {
|
|
653
|
+
return configured ?? isMdxSourceFile(id);
|
|
654
|
+
}
|
|
655
|
+
//#endregion
|
|
593
656
|
//#region src/transform.ts
|
|
594
657
|
/**
|
|
595
658
|
* Markdown transformation logic for @ox-content/unplugin.
|
|
@@ -612,7 +675,7 @@ const PREPARED_SOURCE_SECTION_SOURCE_ORIGIN = 3;
|
|
|
612
675
|
* Note: This requires the @ox-content/napi package to be built.
|
|
613
676
|
*/
|
|
614
677
|
async function transformMarkdown(source, filePath, options) {
|
|
615
|
-
const transformed = hasMarkdownItPlugins(options) ? await transformWithMarkdownIt(source, filePath, options) : hasUnifiedPlugins(options) ? await transformWithUnified(source, filePath, options) : transformWithNativePipeline(loadNapiBindings(), source, options);
|
|
678
|
+
const transformed = hasMarkdownItPlugins(options) ? await transformWithMarkdownIt(source, filePath, options) : hasUnifiedPlugins(options) ? await transformWithUnified(source, filePath, options) : transformWithNativePipeline(loadNapiBindings(), source, filePath, options);
|
|
616
679
|
let nextHtml = transformed.html;
|
|
617
680
|
for (const plugin of options.plugin.oxContent) nextHtml = await plugin(nextHtml);
|
|
618
681
|
return {
|
|
@@ -633,14 +696,16 @@ function loadNapiBindings() {
|
|
|
633
696
|
throw new Error("[ox-content] Failed to load @ox-content/napi. Please ensure the NAPI module is built. Run: mise run build:napi");
|
|
634
697
|
}
|
|
635
698
|
}
|
|
636
|
-
function createNapiTransformOptions(options) {
|
|
699
|
+
function createNapiTransformOptions(options, filePath) {
|
|
637
700
|
const codeAnnotations = options.codeAnnotations ?? {
|
|
638
701
|
enabled: false,
|
|
639
702
|
metaKey: "annotate"
|
|
640
703
|
};
|
|
641
704
|
return {
|
|
642
705
|
gfm: options.gfm,
|
|
706
|
+
mdx: resolveMdxForSourceFile(filePath, options.mdx),
|
|
643
707
|
footnotes: options.footnotes,
|
|
708
|
+
semanticFootnotes: options.semanticFootnotes,
|
|
644
709
|
taskLists: options.taskLists,
|
|
645
710
|
tables: options.tables,
|
|
646
711
|
strikethrough: options.strikethrough,
|
|
@@ -648,7 +713,8 @@ function createNapiTransformOptions(options) {
|
|
|
648
713
|
frontmatter: options.frontmatter,
|
|
649
714
|
tocMaxDepth: options.tocMaxDepth,
|
|
650
715
|
codeAnnotations: codeAnnotations.enabled,
|
|
651
|
-
codeAnnotationMetaKey: codeAnnotations.metaKey
|
|
716
|
+
codeAnnotationMetaKey: codeAnnotations.metaKey,
|
|
717
|
+
math: options.math
|
|
652
718
|
};
|
|
653
719
|
}
|
|
654
720
|
function parseFrontmatterJson(json) {
|
|
@@ -672,8 +738,8 @@ function hasMarkdownItPlugins(options) {
|
|
|
672
738
|
function hasMdastOrRemarkPlugins(options) {
|
|
673
739
|
return options.plugin.mdast.length > 0 || options.plugin.remark.length > 0;
|
|
674
740
|
}
|
|
675
|
-
function transformWithNativePipeline(napi, source, options) {
|
|
676
|
-
const result = napi.transform(source, createNapiTransformOptions(options));
|
|
741
|
+
function transformWithNativePipeline(napi, source, filePath, options) {
|
|
742
|
+
const result = napi.transform(source, createNapiTransformOptions(options, filePath));
|
|
677
743
|
if (result.errors.length > 0) console.warn("[ox-content] Transform warnings:", result.errors);
|
|
678
744
|
const flatToc = result.toc.map((item) => ({
|
|
679
745
|
...item,
|
|
@@ -685,8 +751,8 @@ function transformWithNativePipeline(napi, source, options) {
|
|
|
685
751
|
toc: options.toc ? buildTocTree(flatToc) : []
|
|
686
752
|
};
|
|
687
753
|
}
|
|
688
|
-
function transformWithNativeMdastPipeline(napi, source, options) {
|
|
689
|
-
return deserializeNativeMdastTransform(requireNapiMethod(napi.transformMdastRaw, "transformMdastRaw")(source, createNapiTransformOptions(options)));
|
|
754
|
+
function transformWithNativeMdastPipeline(napi, source, filePath, options) {
|
|
755
|
+
return deserializeNativeMdastTransform(requireNapiMethod(napi.transformMdastRaw, "transformMdastRaw")(source, createNapiTransformOptions(options, filePath)));
|
|
690
756
|
}
|
|
691
757
|
function deserializeNativeMdastTransform(buffer) {
|
|
692
758
|
const envelope = parseTransferEnvelope(buffer);
|
|
@@ -781,7 +847,7 @@ async function transformWithUnified(fullSource, filePath, options) {
|
|
|
781
847
|
const { plugins: remarkPlugins, options: remarkRehypeOptions } = extractUnifiedPluginWithOptions(options.plugin.remark, remarkRehype);
|
|
782
848
|
const { plugins: rehypePlugins, options: rehypeStringifyOptions } = extractUnifiedPluginWithOptions(options.plugin.rehype, rehypeStringify);
|
|
783
849
|
const parserStrategy = detectUnifiedParserStrategy(fullSource, filePath, options, remarkPlugins);
|
|
784
|
-
const nativePayload = parserStrategy === "native" ? transformWithNativeMdastPipeline(loadNapiBindings(), fullSource, options) : null;
|
|
850
|
+
const nativePayload = parserStrategy === "native" ? transformWithNativeMdastPipeline(loadNapiBindings(), fullSource, filePath, options) : null;
|
|
785
851
|
const preparedInput = parserStrategy === "native" ? null : prepareSourceWithRust(loadNapiBindings(), fullSource, options);
|
|
786
852
|
const markdownContent = nativePayload?.content ?? preparedInput?.content ?? fullSource;
|
|
787
853
|
const frontmatter = nativePayload?.frontmatter ?? preparedInput?.frontmatter ?? {};
|
|
@@ -790,7 +856,7 @@ async function transformWithUnified(fullSource, filePath, options) {
|
|
|
790
856
|
const processor = unified();
|
|
791
857
|
applyUnifiedPlugins(processor, options.plugin.mdast.map((plugin) => isOxContentMdastPlugin(plugin) ? toUnifiedMdastPlugin(plugin, mdastContext) : plugin));
|
|
792
858
|
applyUnifiedPlugins(processor, remarkPlugins);
|
|
793
|
-
installUnifiedParser(processor, parserStrategy, options, nativePayload?.tree);
|
|
859
|
+
installUnifiedParser(processor, parserStrategy, options, filePath, nativePayload?.tree);
|
|
794
860
|
let toc = [];
|
|
795
861
|
processor.use(() => {
|
|
796
862
|
return (tree) => {
|
|
@@ -867,7 +933,7 @@ function applyMarkdownItPlugins(markdownIt, plugins) {
|
|
|
867
933
|
function isOxContentMdastPlugin(plugin) {
|
|
868
934
|
return Boolean(plugin) && typeof plugin === "object" && "transform" in plugin;
|
|
869
935
|
}
|
|
870
|
-
function installUnifiedParser(processor, strategy, options, nativeTree) {
|
|
936
|
+
function installUnifiedParser(processor, strategy, options, filePath, nativeTree) {
|
|
871
937
|
if (strategy === "custom") return;
|
|
872
938
|
if (strategy === "remark") {
|
|
873
939
|
processor.use(remarkParse);
|
|
@@ -881,6 +947,7 @@ function installUnifiedParser(processor, strategy, options, nativeTree) {
|
|
|
881
947
|
}
|
|
882
948
|
processor.use(oxContentMdast, {
|
|
883
949
|
gfm: options.gfm,
|
|
950
|
+
mdx: resolveMdxForSourceFile(filePath, options.mdx),
|
|
884
951
|
footnotes: options.footnotes,
|
|
885
952
|
taskLists: options.taskLists,
|
|
886
953
|
tables: options.tables,
|
|
@@ -1222,14 +1289,16 @@ function resolveOptions(options) {
|
|
|
1222
1289
|
return {
|
|
1223
1290
|
srcDir: options.srcDir ?? "docs",
|
|
1224
1291
|
gfm: options.gfm ?? true,
|
|
1292
|
+
mdx: options.mdx,
|
|
1225
1293
|
footnotes: options.footnotes ?? true,
|
|
1294
|
+
semanticFootnotes: options.semanticFootnotes ?? false,
|
|
1226
1295
|
tables: options.tables ?? true,
|
|
1227
1296
|
taskLists: options.taskLists ?? true,
|
|
1228
1297
|
strikethrough: options.strikethrough ?? true,
|
|
1229
1298
|
highlight: options.highlight ?? false,
|
|
1230
|
-
highlightTheme: options.highlightTheme ?? "github-dark",
|
|
1231
1299
|
codeAnnotations: resolveCodeAnnotationsOptions(options.codeAnnotations),
|
|
1232
1300
|
mermaid: options.mermaid ?? false,
|
|
1301
|
+
math: options.math === true || typeof options.math === "object" && options.math.enabled !== false,
|
|
1233
1302
|
frontmatter: options.frontmatter ?? true,
|
|
1234
1303
|
toc: options.toc ?? true,
|
|
1235
1304
|
tocMaxDepth: options.tocMaxDepth ?? 3,
|
|
@@ -1264,7 +1333,7 @@ function resolveCodeAnnotationsOptions(options) {
|
|
|
1264
1333
|
* Check if the file should be processed.
|
|
1265
1334
|
*/
|
|
1266
1335
|
function isMarkdownFile(id, options) {
|
|
1267
|
-
return options.extensions
|
|
1336
|
+
return isConfiguredSourceFile(id, options.extensions);
|
|
1268
1337
|
}
|
|
1269
1338
|
/**
|
|
1270
1339
|
* The unplugin factory function.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ox-content/unplugin",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "3.0.0-alpha.10",
|
|
4
4
|
"description": "Universal plugin for Ox Content - Markdown processing for webpack, rollup, esbuild, vite, and more",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"esbuild",
|
|
@@ -65,11 +65,11 @@
|
|
|
65
65
|
"remark-rehype": "^11.1.1",
|
|
66
66
|
"unified": "^11.0.5",
|
|
67
67
|
"unplugin": "^3.3.0",
|
|
68
|
-
"@ox-content/napi": "
|
|
68
|
+
"@ox-content/napi": "3.0.0-alpha.10"
|
|
69
69
|
},
|
|
70
70
|
"devDependencies": {
|
|
71
|
-
"@types/markdown-it": "^14.
|
|
72
|
-
"@types/node": "^26.
|
|
71
|
+
"@types/markdown-it": "^14.2.0",
|
|
72
|
+
"@types/node": "^26.2.0",
|
|
73
73
|
"@typescript/native-preview": "^7.0.0-dev.20260707.2",
|
|
74
74
|
"esbuild": "^0.28.1",
|
|
75
75
|
"rehype-autolink-headings": "^7.1.0",
|
|
@@ -84,10 +84,10 @@
|
|
|
84
84
|
"remark-math": "^6.0.0",
|
|
85
85
|
"remark-smartypants": "^3.0.3",
|
|
86
86
|
"remark-toc": "^9.0.0",
|
|
87
|
-
"rollup": "^4.62.
|
|
87
|
+
"rollup": "^4.62.5",
|
|
88
88
|
"typescript": "^7.0.2",
|
|
89
89
|
"vite": "npm:@voidzero-dev/vite-plus-core@0.2.8",
|
|
90
|
-
"vite-plus": "0.2.
|
|
90
|
+
"vite-plus": "0.2.9",
|
|
91
91
|
"webpack": "^5.109.2"
|
|
92
92
|
},
|
|
93
93
|
"scripts": {
|