@ox-content/unplugin 2.90.0 → 3.0.0-alpha.2
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 +22 -6
- package/dist/src.mjs +79 -12
- package/package.json +6 -6
package/dist/index.d.mts
CHANGED
|
@@ -277,6 +277,14 @@ 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
|
|
@@ -302,11 +310,6 @@ interface OxContentOptions {
|
|
|
302
310
|
* @default false
|
|
303
311
|
*/
|
|
304
312
|
highlight?: boolean;
|
|
305
|
-
/**
|
|
306
|
-
* Syntax highlighting theme.
|
|
307
|
-
* @default 'github-dark'
|
|
308
|
-
*/
|
|
309
|
-
highlightTheme?: string;
|
|
310
313
|
/**
|
|
311
314
|
* Opt-in line annotations for fenced code blocks.
|
|
312
315
|
*
|
|
@@ -327,6 +330,13 @@ interface OxContentOptions {
|
|
|
327
330
|
* @default false
|
|
328
331
|
*/
|
|
329
332
|
mermaid?: boolean;
|
|
333
|
+
/**
|
|
334
|
+
* Enable `$…$` inline and `$$…$$` block math.
|
|
335
|
+
* @default false
|
|
336
|
+
*/
|
|
337
|
+
math?: boolean | {
|
|
338
|
+
enabled?: boolean;
|
|
339
|
+
};
|
|
330
340
|
/**
|
|
331
341
|
* Parse YAML frontmatter.
|
|
332
342
|
* @default true
|
|
@@ -392,14 +402,15 @@ interface ResolvedDocsConfig {
|
|
|
392
402
|
interface ResolvedOptions {
|
|
393
403
|
srcDir: string;
|
|
394
404
|
gfm: boolean;
|
|
405
|
+
mdx?: boolean;
|
|
395
406
|
footnotes: boolean;
|
|
396
407
|
tables: boolean;
|
|
397
408
|
taskLists: boolean;
|
|
398
409
|
strikethrough: boolean;
|
|
399
410
|
highlight: boolean;
|
|
400
|
-
highlightTheme: string;
|
|
401
411
|
codeAnnotations: ResolvedCodeAnnotationsOptions;
|
|
402
412
|
mermaid: boolean;
|
|
413
|
+
math: boolean;
|
|
403
414
|
frontmatter: boolean;
|
|
404
415
|
toc: boolean;
|
|
405
416
|
tocMaxDepth: number;
|
|
@@ -448,6 +459,11 @@ interface OxContentMdastOptions {
|
|
|
448
459
|
* @default true
|
|
449
460
|
*/
|
|
450
461
|
gfm?: boolean;
|
|
462
|
+
/**
|
|
463
|
+
* Enable MDX JSX, ESM, and expression nodes.
|
|
464
|
+
* @default false
|
|
465
|
+
*/
|
|
466
|
+
mdx?: boolean;
|
|
451
467
|
/**
|
|
452
468
|
* Enable footnotes.
|
|
453
469
|
* @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,13 +696,14 @@ 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,
|
|
644
708
|
taskLists: options.taskLists,
|
|
645
709
|
tables: options.tables,
|
|
@@ -648,7 +712,8 @@ function createNapiTransformOptions(options) {
|
|
|
648
712
|
frontmatter: options.frontmatter,
|
|
649
713
|
tocMaxDepth: options.tocMaxDepth,
|
|
650
714
|
codeAnnotations: codeAnnotations.enabled,
|
|
651
|
-
codeAnnotationMetaKey: codeAnnotations.metaKey
|
|
715
|
+
codeAnnotationMetaKey: codeAnnotations.metaKey,
|
|
716
|
+
math: options.math
|
|
652
717
|
};
|
|
653
718
|
}
|
|
654
719
|
function parseFrontmatterJson(json) {
|
|
@@ -672,8 +737,8 @@ function hasMarkdownItPlugins(options) {
|
|
|
672
737
|
function hasMdastOrRemarkPlugins(options) {
|
|
673
738
|
return options.plugin.mdast.length > 0 || options.plugin.remark.length > 0;
|
|
674
739
|
}
|
|
675
|
-
function transformWithNativePipeline(napi, source, options) {
|
|
676
|
-
const result = napi.transform(source, createNapiTransformOptions(options));
|
|
740
|
+
function transformWithNativePipeline(napi, source, filePath, options) {
|
|
741
|
+
const result = napi.transform(source, createNapiTransformOptions(options, filePath));
|
|
677
742
|
if (result.errors.length > 0) console.warn("[ox-content] Transform warnings:", result.errors);
|
|
678
743
|
const flatToc = result.toc.map((item) => ({
|
|
679
744
|
...item,
|
|
@@ -685,8 +750,8 @@ function transformWithNativePipeline(napi, source, options) {
|
|
|
685
750
|
toc: options.toc ? buildTocTree(flatToc) : []
|
|
686
751
|
};
|
|
687
752
|
}
|
|
688
|
-
function transformWithNativeMdastPipeline(napi, source, options) {
|
|
689
|
-
return deserializeNativeMdastTransform(requireNapiMethod(napi.transformMdastRaw, "transformMdastRaw")(source, createNapiTransformOptions(options)));
|
|
753
|
+
function transformWithNativeMdastPipeline(napi, source, filePath, options) {
|
|
754
|
+
return deserializeNativeMdastTransform(requireNapiMethod(napi.transformMdastRaw, "transformMdastRaw")(source, createNapiTransformOptions(options, filePath)));
|
|
690
755
|
}
|
|
691
756
|
function deserializeNativeMdastTransform(buffer) {
|
|
692
757
|
const envelope = parseTransferEnvelope(buffer);
|
|
@@ -781,7 +846,7 @@ async function transformWithUnified(fullSource, filePath, options) {
|
|
|
781
846
|
const { plugins: remarkPlugins, options: remarkRehypeOptions } = extractUnifiedPluginWithOptions(options.plugin.remark, remarkRehype);
|
|
782
847
|
const { plugins: rehypePlugins, options: rehypeStringifyOptions } = extractUnifiedPluginWithOptions(options.plugin.rehype, rehypeStringify);
|
|
783
848
|
const parserStrategy = detectUnifiedParserStrategy(fullSource, filePath, options, remarkPlugins);
|
|
784
|
-
const nativePayload = parserStrategy === "native" ? transformWithNativeMdastPipeline(loadNapiBindings(), fullSource, options) : null;
|
|
849
|
+
const nativePayload = parserStrategy === "native" ? transformWithNativeMdastPipeline(loadNapiBindings(), fullSource, filePath, options) : null;
|
|
785
850
|
const preparedInput = parserStrategy === "native" ? null : prepareSourceWithRust(loadNapiBindings(), fullSource, options);
|
|
786
851
|
const markdownContent = nativePayload?.content ?? preparedInput?.content ?? fullSource;
|
|
787
852
|
const frontmatter = nativePayload?.frontmatter ?? preparedInput?.frontmatter ?? {};
|
|
@@ -790,7 +855,7 @@ async function transformWithUnified(fullSource, filePath, options) {
|
|
|
790
855
|
const processor = unified();
|
|
791
856
|
applyUnifiedPlugins(processor, options.plugin.mdast.map((plugin) => isOxContentMdastPlugin(plugin) ? toUnifiedMdastPlugin(plugin, mdastContext) : plugin));
|
|
792
857
|
applyUnifiedPlugins(processor, remarkPlugins);
|
|
793
|
-
installUnifiedParser(processor, parserStrategy, options, nativePayload?.tree);
|
|
858
|
+
installUnifiedParser(processor, parserStrategy, options, filePath, nativePayload?.tree);
|
|
794
859
|
let toc = [];
|
|
795
860
|
processor.use(() => {
|
|
796
861
|
return (tree) => {
|
|
@@ -867,7 +932,7 @@ function applyMarkdownItPlugins(markdownIt, plugins) {
|
|
|
867
932
|
function isOxContentMdastPlugin(plugin) {
|
|
868
933
|
return Boolean(plugin) && typeof plugin === "object" && "transform" in plugin;
|
|
869
934
|
}
|
|
870
|
-
function installUnifiedParser(processor, strategy, options, nativeTree) {
|
|
935
|
+
function installUnifiedParser(processor, strategy, options, filePath, nativeTree) {
|
|
871
936
|
if (strategy === "custom") return;
|
|
872
937
|
if (strategy === "remark") {
|
|
873
938
|
processor.use(remarkParse);
|
|
@@ -881,6 +946,7 @@ function installUnifiedParser(processor, strategy, options, nativeTree) {
|
|
|
881
946
|
}
|
|
882
947
|
processor.use(oxContentMdast, {
|
|
883
948
|
gfm: options.gfm,
|
|
949
|
+
mdx: resolveMdxForSourceFile(filePath, options.mdx),
|
|
884
950
|
footnotes: options.footnotes,
|
|
885
951
|
taskLists: options.taskLists,
|
|
886
952
|
tables: options.tables,
|
|
@@ -1222,14 +1288,15 @@ function resolveOptions(options) {
|
|
|
1222
1288
|
return {
|
|
1223
1289
|
srcDir: options.srcDir ?? "docs",
|
|
1224
1290
|
gfm: options.gfm ?? true,
|
|
1291
|
+
mdx: options.mdx,
|
|
1225
1292
|
footnotes: options.footnotes ?? true,
|
|
1226
1293
|
tables: options.tables ?? true,
|
|
1227
1294
|
taskLists: options.taskLists ?? true,
|
|
1228
1295
|
strikethrough: options.strikethrough ?? true,
|
|
1229
1296
|
highlight: options.highlight ?? false,
|
|
1230
|
-
highlightTheme: options.highlightTheme ?? "github-dark",
|
|
1231
1297
|
codeAnnotations: resolveCodeAnnotationsOptions(options.codeAnnotations),
|
|
1232
1298
|
mermaid: options.mermaid ?? false,
|
|
1299
|
+
math: options.math === true || typeof options.math === "object" && options.math.enabled !== false,
|
|
1233
1300
|
frontmatter: options.frontmatter ?? true,
|
|
1234
1301
|
toc: options.toc ?? true,
|
|
1235
1302
|
tocMaxDepth: options.tocMaxDepth ?? 3,
|
|
@@ -1264,7 +1331,7 @@ function resolveCodeAnnotationsOptions(options) {
|
|
|
1264
1331
|
* Check if the file should be processed.
|
|
1265
1332
|
*/
|
|
1266
1333
|
function isMarkdownFile(id, options) {
|
|
1267
|
-
return options.extensions
|
|
1334
|
+
return isConfiguredSourceFile(id, options.extensions);
|
|
1268
1335
|
}
|
|
1269
1336
|
/**
|
|
1270
1337
|
* 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.2",
|
|
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.2"
|
|
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": {
|