@owomark/processor 0.1.6 → 0.1.8

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.js CHANGED
@@ -30,7 +30,8 @@ function walk(node) {
30
30
  type: "element",
31
31
  tagName: "div",
32
32
  properties: { className: ["math-display-block"] },
33
- children: codeEl.children
33
+ children: codeEl.children,
34
+ position: child.position ?? codeEl.position
34
35
  };
35
36
  }
36
37
  }
@@ -140,43 +141,15 @@ function pushSplitTextNodes(target, textNode) {
140
141
  }
141
142
 
142
143
  // src/processor/remark-side-annotation.ts
143
- var STRUCTURAL_TYPES = {
144
- ":": "plain",
145
- "}": "brace",
146
- "{": "left-brace",
147
- "]": "bracket",
148
- "[": "left-bracket",
149
- "|": "line",
150
- "-": "dash",
151
- "->": "arrow",
152
- "=>": "fat-arrow",
153
- "~>": "wave-arrow"
154
- };
155
- var SEMANTIC_TYPES = {
156
- "!": "warning",
157
- "?": "question"
158
- };
159
- var COMPOUND_TYPES = {
160
- "}->": "brace-arrow",
161
- "}=>": "brace-fat-arrow",
162
- "]->": "bracket-arrow",
163
- "]=>": "bracket-fat-arrow",
164
- "|->": "line-arrow",
165
- "|=>": "line-fat-arrow",
166
- "}!": "brace-warning",
167
- "}?": "brace-question"
168
- };
169
- var TYPE_TABLE = {
170
- ...STRUCTURAL_TYPES,
171
- ...SEMANTIC_TYPES,
172
- ...COMPOUND_TYPES
173
- };
174
- var TYPE_SYMBOLS_SORTED = Object.keys(TYPE_TABLE).sort(
175
- (a, b) => b.length - a.length
176
- );
177
- var TYPE_BY_KEYWORD = Object.fromEntries(
178
- Object.entries(TYPE_TABLE).map(([symbol, keyword]) => [keyword, symbol])
179
- );
144
+ import {
145
+ SIDE_ANNOTATION_SYMBOL_BY_KEYWORD,
146
+ SIDE_ANNOTATION_TYPE_SYMBOLS_SORTED as TYPE_SYMBOLS_SORTED,
147
+ SIDE_ANNOTATION_TYPE_TABLE as TYPE_TABLE,
148
+ SIDE_NOTE_DEFINITION_RE as NOTE_DEF_RE,
149
+ SIDE_NOTE_REF_RE as NOTE_REF_RE
150
+ } from "@owomark/core/semantic/syntax";
151
+ var TYPE_BY_KEYWORD = SIDE_ANNOTATION_SYMBOL_BY_KEYWORD;
152
+ var TYPE_TABLE_LOOKUP = TYPE_TABLE;
180
153
  function makeSideAnnotationNode(opts) {
181
154
  const classNames = ["side-annotation", `side-type-${opts.sideType}`];
182
155
  if (opts.orphan) classNames.push("side-orphan");
@@ -205,8 +178,6 @@ var INLINE_ANNOTATION_RE = /(?:^|(?<=\s))\(>((?:[^ ()\\]|\\.)+?) ((?:[^)\\]|\\.)
205
178
  var CONTINUATION_RE = /(?:^|(?<=\s))\(>\+\)\s*$/m;
206
179
  var CONTINUATION_RE_GLOBAL = /(?:^|(?<=\s))\(>\+\)\s*$/gm;
207
180
  var ESCAPE_RE = /\(\\>/;
208
- var NOTE_DEF_RE = /^\[>([\w-]+)\]:\s*(?:\{type=([^}"]+|"[^"]*")\}\s*)?/;
209
- var NOTE_REF_RE = /^\[>([\w-]+)\]$/;
210
181
  function remarkSideAnnotation() {
211
182
  return (tree) => {
212
183
  const noteDefinitions = collectNoteDefinitions(tree);
@@ -228,7 +199,7 @@ function collectNoteDefinitions(tree) {
228
199
  let typeSymbol = ":";
229
200
  if (match[2]) {
230
201
  const raw = match[2].replace(/^"|"$/g, "");
231
- if (TYPE_TABLE[raw]) {
202
+ if (TYPE_TABLE_LOOKUP[raw]) {
232
203
  typeSymbol = raw;
233
204
  } else if (TYPE_BY_KEYWORD[raw]) {
234
205
  typeSymbol = TYPE_BY_KEYWORD[raw];
@@ -263,7 +234,7 @@ function collectNoteDefinitions(tree) {
263
234
  type: "sideNoteDefinition",
264
235
  identifier: id,
265
236
  sideTypeSymbol: typeSymbol,
266
- sideType: TYPE_TABLE[typeSymbol] || "plain",
237
+ sideType: TYPE_TABLE_LOOKUP[typeSymbol] || "plain",
267
238
  children: contentChildren
268
239
  });
269
240
  toRemove.push(i);
@@ -287,7 +258,7 @@ function processDirectiveContainers(tree, noteDefinitions) {
287
258
  const refMatch = NOTE_REF_RE.exec(label.trim());
288
259
  if (refMatch) {
289
260
  noteRef = refMatch[1];
290
- const def = noteDefinitions.get(noteRef);
261
+ const def = noteDefinitions.get(refMatch[1]);
291
262
  if (def) {
292
263
  sideType = def.sideType;
293
264
  sideTypeSymbol = def.sideTypeSymbol;
@@ -567,7 +538,7 @@ function parseInlineAnnotationText(inner) {
567
538
  if (spaceIdx < 0) return null;
568
539
  const typeCandidate = inner.slice(0, spaceIdx);
569
540
  if (!typeCandidate) return null;
570
- const sideType = TYPE_TABLE[typeCandidate];
541
+ const sideType = TYPE_TABLE_LOOKUP[typeCandidate];
571
542
  if (sideType) {
572
543
  const content2 = inner.slice(spaceIdx + 1).replace(/\\([)])/g, "$1").trim();
573
544
  if (!content2) return null;
@@ -699,6 +670,7 @@ function splitDirectiveLabelParagraph(paragraph) {
699
670
  }
700
671
 
701
672
  // src/processor/rehype-side-annotation.ts
673
+ import { SIDE_ANNOTATION_RENDERER_KEY_BY_TYPE } from "@owomark/core/semantic/syntax";
702
674
  var STROKE_WIDTH = "1.5";
703
675
  function el(tagName, properties, children = []) {
704
676
  return { type: "element", tagName, properties, children };
@@ -952,6 +924,7 @@ function visit(node) {
952
924
  function transform(node) {
953
925
  const properties = node.properties ?? {};
954
926
  const sideType = String(properties["data-side-type"] || "plain");
927
+ const rendererKey = SIDE_ANNOTATION_RENDERER_KEY_BY_TYPE[sideType] ?? sideType;
955
928
  const sideText = properties["data-side-text"] ? String(properties["data-side-text"]) : null;
956
929
  const isOrphan = properties["data-side-orphan"] != null;
957
930
  const mainContent = el("div", { class: "side-annotation-main" }, node.children);
@@ -959,7 +932,7 @@ function transform(node) {
959
932
  if (isOrphan) {
960
933
  asideChildren.push(SVG_GENERATORS["line"]());
961
934
  } else {
962
- const svgGen = SVG_GENERATORS[sideType];
935
+ const svgGen = SVG_GENERATORS[rendererKey];
963
936
  if (svgGen) {
964
937
  asideChildren.push(svgGen());
965
938
  }
@@ -997,7 +970,7 @@ function sideAnnotationSyntax() {
997
970
  }
998
971
  };
999
972
  }
1000
- function tokenizeSideAnnotation(effects, ok, nok) {
973
+ function tokenizeSideAnnotation(effects, ok2, nok) {
1001
974
  return start;
1002
975
  function start(code) {
1003
976
  if (code !== CODE_OPEN_PAREN) return nok(code);
@@ -1021,7 +994,7 @@ function tokenizeSideAnnotation(effects, ok, nok) {
1021
994
  if (code === CODE_CLOSE_PAREN) {
1022
995
  effects.consume(code);
1023
996
  effects.exit("sideAnnotationMarker");
1024
- return ok;
997
+ return ok2;
1025
998
  }
1026
999
  effects.consume(code);
1027
1000
  return content;
@@ -1060,6 +1033,37 @@ function remarkMicromarkSideAnnotation() {
1060
1033
  fromMarkdownExtensions.push(sideAnnotationFromMarkdown());
1061
1034
  }
1062
1035
 
1036
+ // src/processor/remark-code-block-metadata.ts
1037
+ function visit2(node, visitor) {
1038
+ visitor(node);
1039
+ if (!Array.isArray(node.children)) {
1040
+ return;
1041
+ }
1042
+ for (const child of node.children) {
1043
+ visit2(child, visitor);
1044
+ }
1045
+ }
1046
+ function remarkCodeBlockMetadata() {
1047
+ return (tree) => {
1048
+ visit2(tree, (node) => {
1049
+ if (node.type !== "code") {
1050
+ return;
1051
+ }
1052
+ const hProperties = node.data?.hProperties ?? {};
1053
+ const language = typeof node.lang === "string" && node.lang.trim() ? node.lang.trim() : null;
1054
+ const meta = typeof node.meta === "string" && node.meta.trim() ? node.meta.trim() : null;
1055
+ node.data = {
1056
+ ...node.data,
1057
+ hProperties: {
1058
+ ...hProperties,
1059
+ ...language ? { "data-language": language } : {},
1060
+ ...meta ? { "data-meta": meta } : {}
1061
+ }
1062
+ };
1063
+ });
1064
+ };
1065
+ }
1066
+
1063
1067
  // src/processor/remark-markdown-sandbox.ts
1064
1068
  var DEFAULT_OUTER_FENCE_TICKS = 4;
1065
1069
  var SANDBOX_ROOT_CLASS = "owo-markdown-sandbox";
@@ -1295,6 +1299,7 @@ async function transformChildren(node, sourceLines, options, sandboxCount) {
1295
1299
  const sandboxId = createSandboxId(codeNode.position?.start?.line, sandboxCount.value - 1);
1296
1300
  const nestedProcessor = options.createProcessor({
1297
1301
  ...options.processorOptions,
1302
+ canonicalDocument: void 0,
1298
1303
  enableMarkdownSandbox: false,
1299
1304
  enableSideAnnotation: meta.options.sideAnnotation ?? options.processorOptions.enableSideAnnotation,
1300
1305
  enableMath: meta.options.math ?? options.processorOptions.enableMath,
@@ -1343,6 +1348,769 @@ function markdownSandboxHandler(_state, node) {
1343
1348
  };
1344
1349
  }
1345
1350
 
1351
+ // ../../node_modules/unist-util-visit/node_modules/unist-util-is/lib/index.js
1352
+ var convert = (
1353
+ /**
1354
+ * @type {(
1355
+ * (<Kind extends Node>(test: PredicateTest<Kind>) => AssertPredicate<Kind>) &
1356
+ * ((test?: Test) => AssertAnything)
1357
+ * )}
1358
+ */
1359
+ /**
1360
+ * @param {Test} [test]
1361
+ * @returns {AssertAnything}
1362
+ */
1363
+ (function(test) {
1364
+ if (test === void 0 || test === null) {
1365
+ return ok;
1366
+ }
1367
+ if (typeof test === "string") {
1368
+ return typeFactory(test);
1369
+ }
1370
+ if (typeof test === "object") {
1371
+ return Array.isArray(test) ? anyFactory(test) : propsFactory(test);
1372
+ }
1373
+ if (typeof test === "function") {
1374
+ return castFactory(test);
1375
+ }
1376
+ throw new Error("Expected function, string, or object as test");
1377
+ })
1378
+ );
1379
+ function anyFactory(tests) {
1380
+ const checks = [];
1381
+ let index = -1;
1382
+ while (++index < tests.length) {
1383
+ checks[index] = convert(tests[index]);
1384
+ }
1385
+ return castFactory(any);
1386
+ function any(...parameters) {
1387
+ let index2 = -1;
1388
+ while (++index2 < checks.length) {
1389
+ if (checks[index2].call(this, ...parameters)) return true;
1390
+ }
1391
+ return false;
1392
+ }
1393
+ }
1394
+ function propsFactory(check) {
1395
+ return castFactory(all);
1396
+ function all(node) {
1397
+ let key;
1398
+ for (key in check) {
1399
+ if (node[key] !== check[key]) return false;
1400
+ }
1401
+ return true;
1402
+ }
1403
+ }
1404
+ function typeFactory(check) {
1405
+ return castFactory(type);
1406
+ function type(node) {
1407
+ return node && node.type === check;
1408
+ }
1409
+ }
1410
+ function castFactory(check) {
1411
+ return assertion;
1412
+ function assertion(node, ...parameters) {
1413
+ return Boolean(
1414
+ node && typeof node === "object" && "type" in node && // @ts-expect-error: fine.
1415
+ Boolean(check.call(this, node, ...parameters))
1416
+ );
1417
+ }
1418
+ }
1419
+ function ok() {
1420
+ return true;
1421
+ }
1422
+
1423
+ // ../../node_modules/unist-util-visit/node_modules/unist-util-visit-parents/lib/color.js
1424
+ function color(d) {
1425
+ return "\x1B[33m" + d + "\x1B[39m";
1426
+ }
1427
+
1428
+ // ../../node_modules/unist-util-visit/node_modules/unist-util-visit-parents/lib/index.js
1429
+ var CONTINUE = true;
1430
+ var EXIT = false;
1431
+ var SKIP = "skip";
1432
+ var visitParents = (
1433
+ /**
1434
+ * @type {(
1435
+ * (<Tree extends Node, Check extends Test>(tree: Tree, test: Check, visitor: BuildVisitor<Tree, Check>, reverse?: boolean | null | undefined) => void) &
1436
+ * (<Tree extends Node>(tree: Tree, visitor: BuildVisitor<Tree>, reverse?: boolean | null | undefined) => void)
1437
+ * )}
1438
+ */
1439
+ /**
1440
+ * @param {Node} tree
1441
+ * @param {Test} test
1442
+ * @param {Visitor<Node>} visitor
1443
+ * @param {boolean | null | undefined} [reverse]
1444
+ * @returns {void}
1445
+ */
1446
+ (function(tree, test, visitor, reverse) {
1447
+ if (typeof test === "function" && typeof visitor !== "function") {
1448
+ reverse = visitor;
1449
+ visitor = test;
1450
+ test = null;
1451
+ }
1452
+ const is2 = convert(test);
1453
+ const step = reverse ? -1 : 1;
1454
+ factory(tree, void 0, [])();
1455
+ function factory(node, index, parents) {
1456
+ const value = node && typeof node === "object" ? node : {};
1457
+ if (typeof value.type === "string") {
1458
+ const name = (
1459
+ // `hast`
1460
+ typeof value.tagName === "string" ? value.tagName : (
1461
+ // `xast`
1462
+ typeof value.name === "string" ? value.name : void 0
1463
+ )
1464
+ );
1465
+ Object.defineProperty(visit4, "name", {
1466
+ value: "node (" + color(node.type + (name ? "<" + name + ">" : "")) + ")"
1467
+ });
1468
+ }
1469
+ return visit4;
1470
+ function visit4() {
1471
+ let result = [];
1472
+ let subresult;
1473
+ let offset;
1474
+ let grandparents;
1475
+ if (!test || is2(node, index, parents[parents.length - 1] || null)) {
1476
+ result = toResult(visitor(node, parents));
1477
+ if (result[0] === EXIT) {
1478
+ return result;
1479
+ }
1480
+ }
1481
+ if (node.children && result[0] !== SKIP) {
1482
+ offset = (reverse ? node.children.length : -1) + step;
1483
+ grandparents = parents.concat(node);
1484
+ while (offset > -1 && offset < node.children.length) {
1485
+ subresult = factory(node.children[offset], offset, grandparents)();
1486
+ if (subresult[0] === EXIT) {
1487
+ return subresult;
1488
+ }
1489
+ offset = typeof subresult[1] === "number" ? subresult[1] : offset + step;
1490
+ }
1491
+ }
1492
+ return result;
1493
+ }
1494
+ }
1495
+ })
1496
+ );
1497
+ function toResult(value) {
1498
+ if (Array.isArray(value)) {
1499
+ return value;
1500
+ }
1501
+ if (typeof value === "number") {
1502
+ return [CONTINUE, value];
1503
+ }
1504
+ return [value];
1505
+ }
1506
+
1507
+ // ../../node_modules/unist-util-visit/lib/index.js
1508
+ var visit3 = (
1509
+ /**
1510
+ * @type {(
1511
+ * (<Tree extends Node, Check extends Test>(tree: Tree, test: Check, visitor: BuildVisitor<Tree, Check>, reverse?: boolean | null | undefined) => void) &
1512
+ * (<Tree extends Node>(tree: Tree, visitor: BuildVisitor<Tree>, reverse?: boolean | null | undefined) => void)
1513
+ * )}
1514
+ */
1515
+ /**
1516
+ * @param {Node} tree
1517
+ * @param {Test} test
1518
+ * @param {Visitor} visitor
1519
+ * @param {boolean | null | undefined} [reverse]
1520
+ * @returns {void}
1521
+ */
1522
+ (function(tree, test, visitor, reverse) {
1523
+ if (typeof test === "function" && typeof visitor !== "function") {
1524
+ reverse = visitor;
1525
+ visitor = test;
1526
+ test = null;
1527
+ }
1528
+ visitParents(tree, test, overload, reverse);
1529
+ function overload(node, parents) {
1530
+ const parent = parents[parents.length - 1];
1531
+ return visitor(
1532
+ node,
1533
+ parent ? parent.children.indexOf(node) : null,
1534
+ parent
1535
+ );
1536
+ }
1537
+ })
1538
+ );
1539
+
1540
+ // src/processor/owo-component-registry.ts
1541
+ import {
1542
+ componentRegistry,
1543
+ getComponentDescriptorByDirective
1544
+ } from "@owomark/core/semantic/components";
1545
+ function toComponentRegistryEntry(descriptor) {
1546
+ return {
1547
+ directiveName: descriptor.directiveName,
1548
+ componentName: descriptor.componentName,
1549
+ kind: descriptor.componentKind,
1550
+ allowedAttrs: descriptor.allowedAttrs,
1551
+ requiredAttrs: descriptor.requiredAttrs,
1552
+ requiredParent: descriptor.requiredParent,
1553
+ allowedChildDirective: descriptor.allowedChildDirectives[0] ?? null,
1554
+ payloadStrategy: descriptor.payloadStrategy
1555
+ };
1556
+ }
1557
+ var entries = componentRegistry.list().map(toComponentRegistryEntry);
1558
+ var COMPONENT_REGISTRY = new Map(
1559
+ entries.map((e) => [e.directiveName, e])
1560
+ );
1561
+ function isKnownDirective(name) {
1562
+ return COMPONENT_REGISTRY.has(name);
1563
+ }
1564
+ function getComponentEntry(name) {
1565
+ const entry = COMPONENT_REGISTRY.get(name);
1566
+ if (entry) return entry;
1567
+ const descriptor = getComponentDescriptorByDirective(name);
1568
+ return descriptor ? toComponentRegistryEntry(descriptor) : void 0;
1569
+ }
1570
+
1571
+ // src/processor/owo-components-diagnostics.ts
1572
+ var SOURCE = "owo-components";
1573
+ function reportDisabledFlag(file, name, position) {
1574
+ file.message(
1575
+ `Component directive ":::${name}" requires enableComponents to be enabled`,
1576
+ { place: position, source: SOURCE }
1577
+ );
1578
+ }
1579
+ function reportUnknownComponent(file, name, position) {
1580
+ file.message(
1581
+ `Unknown component directive ":::${name}"`,
1582
+ { place: position, source: SOURCE }
1583
+ );
1584
+ }
1585
+ function reportInvalidAttr(file, name, attr, position) {
1586
+ file.message(
1587
+ `Attribute "${attr}" is not allowed on ":::${name}"`,
1588
+ { place: position, source: SOURCE }
1589
+ );
1590
+ }
1591
+ function reportMissingAttr(file, name, attr, position) {
1592
+ file.message(
1593
+ `":::${name}" requires attribute "${attr}"`,
1594
+ { place: position, source: SOURCE }
1595
+ );
1596
+ }
1597
+ function reportInvalidNesting(file, name, expectedParent, position) {
1598
+ file.message(
1599
+ `":::${name}" must be inside ":::${expectedParent}"`,
1600
+ { place: position, source: SOURCE }
1601
+ );
1602
+ }
1603
+ function reportInvalidChildren(file, parentName, expectedChild, position) {
1604
+ file.message(
1605
+ `":::${parentName}" children must all be ":::${expectedChild}"`,
1606
+ { place: position, source: SOURCE }
1607
+ );
1608
+ }
1609
+ function reportMissingPayload(file, name, what, position) {
1610
+ file.message(
1611
+ `":::${name}" requires ${what}`,
1612
+ { place: position, source: SOURCE }
1613
+ );
1614
+ }
1615
+ function reportConflictingPayload(file, name, what, position) {
1616
+ file.message(
1617
+ `":::${name}" ${what}`,
1618
+ { place: position, source: SOURCE }
1619
+ );
1620
+ }
1621
+
1622
+ // src/processor/remark-owo-components.ts
1623
+ function escapeHtml2(text) {
1624
+ return text.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;");
1625
+ }
1626
+ function findCodeBlock(children) {
1627
+ for (const child of children) {
1628
+ if (child.type === "code") return child;
1629
+ }
1630
+ return null;
1631
+ }
1632
+ function countCodeBlocks(children) {
1633
+ return children.filter((c) => c.type === "code").length;
1634
+ }
1635
+ function hasContainerDirectiveChildren(children, name) {
1636
+ return children.some(
1637
+ (c) => c.type === "containerDirective" && c.name === name
1638
+ );
1639
+ }
1640
+ function allChildrenAreDirective(children, name) {
1641
+ const meaningful = children.filter(
1642
+ (c) => c.type !== "paragraph" || !isBlankParagraph(c)
1643
+ );
1644
+ return meaningful.length > 0 && meaningful.every(
1645
+ (c) => c.type === "containerDirective" && c.name === name
1646
+ );
1647
+ }
1648
+ function isBlankParagraph(node) {
1649
+ if (node.type !== "paragraph") return false;
1650
+ const children = node.children;
1651
+ if (!children || children.length === 0) return true;
1652
+ return children.every((c) => c.type === "text" && !c.value?.trim());
1653
+ }
1654
+ function getDirectiveChildren(children, name) {
1655
+ return children.filter(
1656
+ (c) => c.type === "containerDirective" && c.name === name
1657
+ );
1658
+ }
1659
+ function extractTextContent(children) {
1660
+ let text = "";
1661
+ for (const child of children) {
1662
+ if (child.type === "text") {
1663
+ text += child.value ?? "";
1664
+ } else if (child.children) {
1665
+ text += extractTextContent(child.children);
1666
+ }
1667
+ }
1668
+ return text;
1669
+ }
1670
+ function getPosition(node) {
1671
+ return node.position?.start;
1672
+ }
1673
+ function validateAttrs(file, node, entry) {
1674
+ const attrs = node.attributes ?? {};
1675
+ let valid = true;
1676
+ for (const key of Object.keys(attrs)) {
1677
+ if (!entry.allowedAttrs.includes(key)) {
1678
+ reportInvalidAttr(file, entry.directiveName, key, getPosition(node));
1679
+ }
1680
+ }
1681
+ for (const key of entry.requiredAttrs) {
1682
+ if (!attrs[key]?.trim()) {
1683
+ reportMissingAttr(file, entry.directiveName, key, getPosition(node));
1684
+ valid = false;
1685
+ }
1686
+ }
1687
+ return valid;
1688
+ }
1689
+ function mdastHtmlNode(html) {
1690
+ return { type: "html", value: html };
1691
+ }
1692
+ function mdastWrapper(hName, className, children) {
1693
+ const cls = Array.isArray(className) ? className : [className];
1694
+ return {
1695
+ type: "paragraph",
1696
+ data: { hName, hProperties: { className: cls } },
1697
+ children
1698
+ };
1699
+ }
1700
+ function transformNote(node) {
1701
+ const title = node.attributes?.title;
1702
+ node.data = {
1703
+ hName: "aside",
1704
+ hProperties: { className: ["mdx-note"] }
1705
+ };
1706
+ if (title && node.children) {
1707
+ node.children.unshift(mdastHtmlNode(
1708
+ `<div class="mdx-note-title">${escapeHtml2(title)}</div>`
1709
+ ));
1710
+ }
1711
+ if (node.children) {
1712
+ const wrapper = mdastWrapper(
1713
+ "div",
1714
+ "mdx-note-body",
1715
+ title ? node.children.slice(1) : [...node.children]
1716
+ );
1717
+ node.children = title ? [node.children[0], wrapper] : [wrapper];
1718
+ }
1719
+ }
1720
+ function transformCallout(node) {
1721
+ const type = node.attributes?.type ?? "info";
1722
+ const ICONS2 = { info: "i", warn: "!", error: "\xD7", success: "\u2713" };
1723
+ const icon = ICONS2[type] ?? ICONS2.info;
1724
+ node.data = {
1725
+ hName: "div",
1726
+ hProperties: {
1727
+ className: ["mdx-callout", `mdx-callout-${type}`],
1728
+ "data-callout-type": type
1729
+ }
1730
+ };
1731
+ if (node.children) {
1732
+ node.children.unshift(mdastHtmlNode(
1733
+ `<span class="mdx-callout-icon">${escapeHtml2(icon)}</span>`
1734
+ ));
1735
+ const contentChildren = node.children.slice(1);
1736
+ const wrapper = mdastWrapper("div", "mdx-callout-content", contentChildren);
1737
+ node.children = [node.children[0], wrapper];
1738
+ }
1739
+ }
1740
+ function transformDetails(node) {
1741
+ const summary = node.attributes?.summary ?? "";
1742
+ const open = node.attributes?.open;
1743
+ node.data = {
1744
+ hName: "details",
1745
+ hProperties: {
1746
+ className: ["mdx-details"],
1747
+ ...open === "true" ? { open: true } : {}
1748
+ }
1749
+ };
1750
+ if (node.children) {
1751
+ node.children.unshift(mdastHtmlNode(
1752
+ `<summary class="mdx-details-summary">${escapeHtml2(summary)}</summary>`
1753
+ ));
1754
+ const bodyChildren = node.children.slice(1);
1755
+ const wrapper = mdastWrapper("div", "mdx-details-body", bodyChildren);
1756
+ node.children = [node.children[0], wrapper];
1757
+ }
1758
+ }
1759
+ function transformKbd(node) {
1760
+ node.data = {
1761
+ hName: "kbd",
1762
+ hProperties: { className: ["mdx-kbd"] }
1763
+ };
1764
+ }
1765
+ function makeRenderedNode(node, html) {
1766
+ node.type = "owoComponentRendered";
1767
+ node.children = [];
1768
+ node.data = { html };
1769
+ }
1770
+ function renderCodeDemoSingle(attrs, code, fenceLang) {
1771
+ const title = attrs.title ?? "";
1772
+ const language = attrs.language ?? (fenceLang || "text");
1773
+ const titleHtml = title ? `<figcaption>${escapeHtml2(title)}</figcaption>` : "";
1774
+ return `<figure class="mdx-code-demo" data-code-demo>${titleHtml}<pre data-language="${escapeHtml2(language)}"><code>${escapeHtml2(code)}</code></pre></figure>`;
1775
+ }
1776
+ function renderCodeDemoMultiTab(attrs, tabs) {
1777
+ const title = attrs.title ?? "";
1778
+ const titleHtml = title ? `<figcaption>${escapeHtml2(title)}</figcaption>` : "";
1779
+ const groupId = `mdx-code-tabs-${Math.random().toString(36).slice(2, 8)}`;
1780
+ const tabListItems = tabs.map(
1781
+ (tab, i) => `<label class="mdx-tabs-trigger"><input type="radio" name="${groupId}" class="mdx-tabs-radio"${i === 0 ? " checked" : ""}><span>${escapeHtml2(tab.label)}</span></label>`
1782
+ ).join("");
1783
+ const panels = tabs.map(
1784
+ (tab) => `<div class="mdx-tabs-panel"><pre data-language="${escapeHtml2(tab.language)}"><code>${escapeHtml2(tab.code)}</code></pre></div>`
1785
+ ).join("");
1786
+ return `<figure class="mdx-code-demo" data-code-demo>${titleHtml}<div class="mdx-tabs"><div class="mdx-tabs-list" role="tablist">${tabListItems}</div>${panels}</div></figure>`;
1787
+ }
1788
+ function renderFileTree(text) {
1789
+ const entries2 = [];
1790
+ for (const line of text.split("\n")) {
1791
+ const trimmed = line.replace(/^[\s\-*]*/, "");
1792
+ if (!trimmed) continue;
1793
+ const leadingSpaces = line.match(/^(\s*)/)?.[1].length ?? 0;
1794
+ const depth = Math.floor(leadingSpaces / 2);
1795
+ const isDir = trimmed.endsWith("/");
1796
+ const name = isDir ? trimmed.slice(0, -1) : trimmed;
1797
+ entries2.push({ name, isDir, depth });
1798
+ }
1799
+ const items = entries2.map((entry) => {
1800
+ const icon = entry.isDir ? "\u{1F4C1}" : "\u{1F4C4}";
1801
+ const cls = entry.isDir ? "mdx-file-tree-dir" : "mdx-file-tree-file";
1802
+ return `<div class="mdx-file-tree-entry ${cls}" style="padding-left: ${entry.depth * 1.25 + 0.5}rem"><span class="mdx-file-tree-icon">${icon}</span><span class="mdx-file-tree-name">${escapeHtml2(entry.name)}</span></div>`;
1803
+ }).join("");
1804
+ return `<div class="mdx-file-tree">${items}</div>`;
1805
+ }
1806
+ function renderLinkCard(attrs, summaryText) {
1807
+ const href = attrs.href ?? "";
1808
+ const title = attrs.title ?? "";
1809
+ const description = attrs.description ?? summaryText;
1810
+ const domain = attrs.domain;
1811
+ const titleHtml = `<div class="mdx-link-card-title">${escapeHtml2(title)}</div>`;
1812
+ const descHtml = description ? `<div class="mdx-link-card-desc">${escapeHtml2(description)}</div>` : "";
1813
+ const domainHtml = domain ? `<div class="mdx-link-card-domain">${escapeHtml2(domain)}</div>` : "";
1814
+ return `<a class="mdx-link-card" href="${escapeHtml2(href)}">${titleHtml}${descHtml}${domainHtml}</a>`;
1815
+ }
1816
+ function transformSteps(node) {
1817
+ const stepNodes = getDirectiveChildren(node.children ?? [], "step");
1818
+ node.data = {
1819
+ hName: "div",
1820
+ hProperties: { className: ["mdx-steps"] }
1821
+ };
1822
+ const items = [];
1823
+ for (let i = 0; i < stepNodes.length; i++) {
1824
+ const step = stepNodes[i];
1825
+ const title = step.attributes?.title;
1826
+ const titleNode = title ? mdastHtmlNode(`<h4 class="mdx-step-title">${escapeHtml2(title)}</h4>`) : null;
1827
+ const bodyChildren = step.children ?? [];
1828
+ const bodyNode = bodyChildren.length > 0 ? mdastWrapper("div", "mdx-step-body", bodyChildren) : null;
1829
+ const line = i < stepNodes.length - 1 ? mdastHtmlNode('<div class="mdx-steps-line"></div>') : null;
1830
+ const indicatorChildren = [
1831
+ mdastHtmlNode(`<span class="mdx-steps-number">${i + 1}</span>`)
1832
+ ];
1833
+ if (line) indicatorChildren.push(line);
1834
+ const stepContentChildren = [];
1835
+ if (titleNode) stepContentChildren.push(titleNode);
1836
+ if (bodyNode) stepContentChildren.push(bodyNode);
1837
+ const stepInner = mdastWrapper("div", "mdx-step", stepContentChildren);
1838
+ const indicatorWrapper = mdastWrapper("div", "mdx-steps-indicator", indicatorChildren);
1839
+ const contentWrapper = mdastWrapper("div", "mdx-steps-content", [stepInner]);
1840
+ items.push(mdastWrapper("div", "mdx-steps-item", [indicatorWrapper, contentWrapper]));
1841
+ }
1842
+ node.children = items;
1843
+ }
1844
+ function transformTabs(node) {
1845
+ const tabNodes = getDirectiveChildren(node.children ?? [], "tab");
1846
+ const groupId = `mdx-tabs-${Math.random().toString(36).slice(2, 8)}`;
1847
+ node.data = {
1848
+ hName: "div",
1849
+ hProperties: { className: ["mdx-tabs"] }
1850
+ };
1851
+ const triggers = [];
1852
+ const panels = [];
1853
+ for (let i = 0; i < tabNodes.length; i++) {
1854
+ const tab = tabNodes[i];
1855
+ const label = tab.attributes?.label ?? `Tab ${i + 1}`;
1856
+ triggers.push(mdastHtmlNode(
1857
+ `<label class="mdx-tabs-trigger"><input type="radio" name="${groupId}" class="mdx-tabs-radio"${i === 0 ? " checked" : ""}><span>${escapeHtml2(label)}</span></label>`
1858
+ ));
1859
+ panels.push(mdastWrapper("div", "mdx-tabs-panel", tab.children ?? []));
1860
+ }
1861
+ const tabList = mdastWrapper("div", "mdx-tabs-list", triggers);
1862
+ tabList.data.hProperties.role = "tablist";
1863
+ node.children = [tabList, ...panels];
1864
+ }
1865
+ function remarkOwoComponents(options) {
1866
+ const { enabled } = options;
1867
+ return function transform2(tree, file) {
1868
+ visit3(tree, (node, _index, parent) => {
1869
+ const directive = node;
1870
+ if (directive.type === "textDirective") {
1871
+ return handleTextDirective(directive, parent ?? void 0, file, enabled);
1872
+ }
1873
+ if (directive.type !== "containerDirective") return;
1874
+ const { name } = directive;
1875
+ if (name === "side") return;
1876
+ const entry = COMPONENT_REGISTRY.get(name);
1877
+ if (!entry) {
1878
+ reportUnknownComponent(file, name, getPosition(directive));
1879
+ return;
1880
+ }
1881
+ if (!enabled) {
1882
+ reportDisabledFlag(file, name, getPosition(directive));
1883
+ return;
1884
+ }
1885
+ validateAttrs(file, directive, entry);
1886
+ if (entry.requiredParent) {
1887
+ const parentDirective = parent;
1888
+ if (!parentDirective || parentDirective.type !== "containerDirective" || parentDirective.name !== entry.requiredParent) {
1889
+ reportInvalidNesting(file, name, entry.requiredParent, getPosition(directive));
1890
+ return;
1891
+ }
1892
+ }
1893
+ if (entry.allowedChildDirective && directive.children) {
1894
+ const childName = entry.allowedChildDirective;
1895
+ const hasChildDirectives = hasContainerDirectiveChildren(directive.children, childName);
1896
+ if (entry.kind === "block-parent") {
1897
+ if (!allChildrenAreDirective(directive.children, childName)) {
1898
+ if (directive.children.some((c) => !isBlankParagraph(c))) {
1899
+ reportInvalidChildren(file, name, childName, getPosition(directive));
1900
+ }
1901
+ }
1902
+ }
1903
+ if (name === "code-demo" && hasChildDirectives) {
1904
+ const hasTopLevelCode = countCodeBlocks(directive.children) > 0;
1905
+ if (hasTopLevelCode) {
1906
+ reportConflictingPayload(file, name, "cannot mix top-level code blocks with :::code-tab children", getPosition(directive));
1907
+ return;
1908
+ }
1909
+ if (!allChildrenAreDirective(directive.children, "code-tab")) {
1910
+ reportInvalidChildren(file, name, "code-tab", getPosition(directive));
1911
+ }
1912
+ const codeTabNodes = getDirectiveChildren(directive.children, "code-tab");
1913
+ for (const ct of codeTabNodes) {
1914
+ validateAttrs(file, ct, COMPONENT_REGISTRY.get("code-tab"));
1915
+ const codeCount = countCodeBlocks(ct.children ?? []);
1916
+ if (codeCount === 0) {
1917
+ reportMissingPayload(file, "code-tab", "a fenced code block", getPosition(ct));
1918
+ } else if (codeCount > 1) {
1919
+ reportConflictingPayload(file, "code-tab", "must contain exactly one fenced code block", getPosition(ct));
1920
+ }
1921
+ }
1922
+ const tabs = codeTabNodes.map((ct) => {
1923
+ const code = findCodeBlock(ct.children ?? []);
1924
+ return {
1925
+ label: ct.attributes?.label ?? "",
1926
+ language: ct.attributes?.language ?? code?.lang ?? "text",
1927
+ code: code?.value ?? ""
1928
+ };
1929
+ });
1930
+ makeRenderedNode(directive, renderCodeDemoMultiTab(directive.attributes ?? {}, tabs));
1931
+ return SKIP;
1932
+ }
1933
+ }
1934
+ switch (name) {
1935
+ case "note":
1936
+ transformNote(directive);
1937
+ return SKIP;
1938
+ case "callout":
1939
+ transformCallout(directive);
1940
+ return SKIP;
1941
+ case "details":
1942
+ transformDetails(directive);
1943
+ return SKIP;
1944
+ case "kbd":
1945
+ transformKbd(directive);
1946
+ return SKIP;
1947
+ case "code-demo": {
1948
+ const codeBlock = findCodeBlock(directive.children ?? []);
1949
+ if (!codeBlock) {
1950
+ reportMissingPayload(file, name, "a fenced code block", getPosition(directive));
1951
+ return;
1952
+ }
1953
+ if (countCodeBlocks(directive.children ?? []) > 1) {
1954
+ reportConflictingPayload(file, name, "must contain exactly one fenced code block (or use :::code-tab)", getPosition(directive));
1955
+ return;
1956
+ }
1957
+ makeRenderedNode(
1958
+ directive,
1959
+ renderCodeDemoSingle(directive.attributes ?? {}, codeBlock.value, codeBlock.lang ?? "")
1960
+ );
1961
+ return SKIP;
1962
+ }
1963
+ case "file-tree": {
1964
+ const codeBlock = findCodeBlock(directive.children ?? []);
1965
+ if (!codeBlock) {
1966
+ reportMissingPayload(file, name, "a fenced code block", getPosition(directive));
1967
+ return;
1968
+ }
1969
+ makeRenderedNode(directive, renderFileTree(codeBlock.value));
1970
+ return SKIP;
1971
+ }
1972
+ case "link-card": {
1973
+ const attrs = directive.attributes ?? {};
1974
+ const hasDesc = Boolean(attrs.description);
1975
+ const bodyText = extractTextContent(directive.children ?? []).trim();
1976
+ if (hasDesc && bodyText) {
1977
+ reportConflictingPayload(file, name, 'cannot have both "description" attribute and body text', getPosition(directive));
1978
+ }
1979
+ makeRenderedNode(directive, renderLinkCard(attrs, bodyText));
1980
+ return SKIP;
1981
+ }
1982
+ case "steps":
1983
+ transformSteps(directive);
1984
+ return SKIP;
1985
+ case "tabs":
1986
+ transformTabs(directive);
1987
+ return SKIP;
1988
+ case "step":
1989
+ case "tab":
1990
+ case "code-tab":
1991
+ break;
1992
+ }
1993
+ });
1994
+ };
1995
+ }
1996
+ function handleTextDirective(node, _parent, file, enabled) {
1997
+ if (node.name === "kbd") {
1998
+ if (!enabled) {
1999
+ reportDisabledFlag(file, node.name, getPosition(node));
2000
+ return;
2001
+ }
2002
+ transformKbd(node);
2003
+ return SKIP;
2004
+ }
2005
+ const entry = COMPONENT_REGISTRY.get(node.name);
2006
+ if (entry && entry.kind !== "inline-text") {
2007
+ reportInvalidNesting(file, node.name, "block context (use ::: syntax)", getPosition(node));
2008
+ }
2009
+ }
2010
+ function owoComponentRenderedHandler(_state, node) {
2011
+ return {
2012
+ type: "raw",
2013
+ value: node.data?.html ?? ""
2014
+ };
2015
+ }
2016
+
2017
+ // src/processor/source-normalization.ts
2018
+ import {
2019
+ collectMathFenceNormalizationRewrites
2020
+ } from "@owomark/core/semantic/syntax";
2021
+ function splitLogicalLines(source) {
2022
+ const lines = source.split("\n");
2023
+ if (source.endsWith("\n")) {
2024
+ lines.pop();
2025
+ }
2026
+ return lines;
2027
+ }
2028
+ function createIdentitySourceMap(source) {
2029
+ const lineCount = splitLogicalLines(source).length;
2030
+ return {
2031
+ normalizedToSourceLine: Array.from({ length: lineCount }, (_, index) => index + 1),
2032
+ normalizedToSourceColumn: Array.from({ length: lineCount }, () => 1),
2033
+ segments: []
2034
+ };
2035
+ }
2036
+ function applySourceRewrites(source, sourceMap, rewrites) {
2037
+ if (rewrites.length === 0) {
2038
+ return { source, sourceMap };
2039
+ }
2040
+ const inputLines = splitLogicalLines(source);
2041
+ const outputLines = [];
2042
+ const normalizedToSourceLine = [];
2043
+ const normalizedToSourceColumn = [];
2044
+ const segments = [...sourceMap.segments];
2045
+ let lineNumber = 1;
2046
+ let rewriteIndex = 0;
2047
+ while (lineNumber <= inputLines.length) {
2048
+ const rewrite = rewrites[rewriteIndex];
2049
+ if (rewrite && rewrite.startLine === lineNumber) {
2050
+ const normalizedStartLine = outputLines.length + 1;
2051
+ outputLines.push(...rewrite.replacementLines);
2052
+ for (const mapping of rewrite.lineMappings) {
2053
+ const sourceLine = sourceMap.normalizedToSourceLine[mapping.sourceLine - 1] ?? mapping.sourceLine;
2054
+ const sourceColumnBase = sourceMap.normalizedToSourceColumn[mapping.sourceLine - 1] ?? 1;
2055
+ normalizedToSourceLine.push(sourceLine);
2056
+ normalizedToSourceColumn.push(sourceColumnBase + mapping.sourceColumn - 1);
2057
+ }
2058
+ segments.push({
2059
+ kind: rewrite.kind,
2060
+ normalizedStartLine,
2061
+ normalizedEndLine: outputLines.length,
2062
+ sourceStartLine: sourceMap.normalizedToSourceLine[rewrite.startLine - 1] ?? rewrite.startLine,
2063
+ sourceEndLine: sourceMap.normalizedToSourceLine[rewrite.endLine - 1] ?? rewrite.endLine
2064
+ });
2065
+ lineNumber = rewrite.endLine + 1;
2066
+ rewriteIndex += 1;
2067
+ continue;
2068
+ }
2069
+ outputLines.push(inputLines[lineNumber - 1]);
2070
+ normalizedToSourceLine.push(sourceMap.normalizedToSourceLine[lineNumber - 1] ?? lineNumber);
2071
+ normalizedToSourceColumn.push(sourceMap.normalizedToSourceColumn[lineNumber - 1] ?? 1);
2072
+ lineNumber += 1;
2073
+ }
2074
+ const normalizedSource = outputLines.join("\n");
2075
+ return {
2076
+ source: source.endsWith("\n") ? `${normalizedSource}
2077
+ ` : normalizedSource,
2078
+ sourceMap: {
2079
+ normalizedToSourceLine,
2080
+ normalizedToSourceColumn,
2081
+ segments
2082
+ }
2083
+ };
2084
+ }
2085
+ function normalizeOwoMarkSource(source, options) {
2086
+ const baseMap = createIdentitySourceMap(source);
2087
+ if (options?.enableMath === false) {
2088
+ return { source, sourceMap: baseMap };
2089
+ }
2090
+ const rewrites = collectMathFenceNormalizationRewrites(source).map((rewrite) => ({
2091
+ kind: rewrite.kind,
2092
+ startLine: rewrite.startLine,
2093
+ endLine: rewrite.endLine,
2094
+ replacementLines: rewrite.replacementLines,
2095
+ lineMappings: rewrite.lineMappings
2096
+ }));
2097
+ return applySourceRewrites(source, baseMap, rewrites);
2098
+ }
2099
+ function remapNormalizedLine(line, sourceMap) {
2100
+ if (typeof line !== "number" || line < 1) return line;
2101
+ return sourceMap?.normalizedToSourceLine[line - 1] ?? line;
2102
+ }
2103
+ function remapNormalizedColumn(line, column, sourceMap) {
2104
+ if (typeof line !== "number" || typeof column !== "number" || line < 1 || column < 1) {
2105
+ return column;
2106
+ }
2107
+ const baseColumn = sourceMap?.normalizedToSourceColumn[line - 1];
2108
+ if (typeof baseColumn !== "number") {
2109
+ return column;
2110
+ }
2111
+ return baseColumn + column - 1;
2112
+ }
2113
+
1346
2114
  // src/processor/remark-mdx-source-lines.ts
1347
2115
  function setMdxAttribute(node, name, value) {
1348
2116
  const attributes = Array.isArray(node.attributes) ? node.attributes : [];
@@ -1362,20 +2130,7 @@ function setMdxAttribute(node, name, value) {
1362
2130
  node.attributes = attributes;
1363
2131
  }
1364
2132
  function remapLine(line, sourceMap) {
1365
- if (typeof line !== "number" || !sourceMap?.segments.length) return line;
1366
- let delta = 0;
1367
- for (const segment of sourceMap.segments) {
1368
- if (line < segment.normalizedStartLine) {
1369
- break;
1370
- }
1371
- if (line <= segment.normalizedEndLine) {
1372
- if (line === segment.normalizedStartLine) return segment.sourceStartLine;
1373
- if (line === segment.normalizedEndLine) return segment.sourceEndLine;
1374
- return segment.sourceStartLine + (line - segment.normalizedStartLine - 1);
1375
- }
1376
- delta += segment.normalizedEndLine - segment.normalizedStartLine + 1 - (segment.sourceEndLine - segment.sourceStartLine + 1);
1377
- }
1378
- return line - delta;
2133
+ return remapNormalizedLine(line, sourceMap);
1379
2134
  }
1380
2135
  function stampMdxJsxNode(node, sourceMap) {
1381
2136
  const startLine = remapLine(node.position?.start?.line, sourceMap);
@@ -1424,6 +2179,11 @@ var CONTAINER_TAGS = /* @__PURE__ */ new Set([
1424
2179
  "details",
1425
2180
  "summary"
1426
2181
  ]);
2182
+ var MATH_LEAF_CLASSES = /* @__PURE__ */ new Set([
2183
+ "katex-display",
2184
+ "math-display",
2185
+ "math-display-block"
2186
+ ]);
1427
2187
  function liHasAnchorDescendant(node) {
1428
2188
  if (!Array.isArray(node.children)) return false;
1429
2189
  for (const child of node.children) {
@@ -1452,7 +2212,7 @@ function walk4(node) {
1452
2212
  stampAnchorAttributes(node);
1453
2213
  } else if (tag === "div") {
1454
2214
  const classes = node.properties?.className || [];
1455
- if (classes.includes("katex-display") || classes.includes("math-display")) {
2215
+ if (classes.some((className) => MATH_LEAF_CLASSES.has(className))) {
1456
2216
  stampAnchorAttributes(node);
1457
2217
  return;
1458
2218
  }
@@ -1470,7 +2230,10 @@ function rehypeSourceLines() {
1470
2230
 
1471
2231
  // src/processor/plugin-registry.ts
1472
2232
  var BUILTIN_PLUGINS = /* @__PURE__ */ new Map([
1473
- ["rehype-source-lines", rehypeSourceLines]
2233
+ ["rehype-source-lines", {
2234
+ plugin: rehypeSourceLines,
2235
+ workerSafe: true
2236
+ }]
1474
2237
  ]);
1475
2238
  var GLOBAL_KEY = "__owomark_custom_plugins__";
1476
2239
  function getCustomPlugins() {
@@ -1484,9 +2247,15 @@ function registerPlugin(name, plugin) {
1484
2247
  function allBuiltinDescriptors(descriptors) {
1485
2248
  return descriptors.every((d) => BUILTIN_PLUGINS.has(d.name));
1486
2249
  }
2250
+ function isWorkerSafeBuiltinDescriptor(descriptor) {
2251
+ return BUILTIN_PLUGINS.get(descriptor.name)?.workerSafe === true;
2252
+ }
2253
+ function allWorkerSafeBuiltinDescriptors(descriptors) {
2254
+ return descriptors.every((d) => BUILTIN_PLUGINS.get(d.name)?.workerSafe === true);
2255
+ }
1487
2256
  function resolveDescriptors(descriptors) {
1488
2257
  return descriptors.map((d) => {
1489
- const plugin = BUILTIN_PLUGINS.get(d.name) ?? getCustomPlugins().get(d.name);
2258
+ const plugin = BUILTIN_PLUGINS.get(d.name)?.plugin ?? getCustomPlugins().get(d.name);
1490
2259
  if (!plugin) {
1491
2260
  throw new Error(`[owomark] Unknown plugin descriptor: "${d.name}". Register it first via registerPlugin().`);
1492
2261
  }
@@ -1568,8 +2337,75 @@ function CodeDemo({
1568
2337
  );
1569
2338
  }
1570
2339
 
2340
+ // src/mdx-components/code-tab.ts
2341
+ import { createElement as createElement4 } from "react";
2342
+ function CodeTab({
2343
+ label,
2344
+ language,
2345
+ children,
2346
+ className,
2347
+ ...domProps
2348
+ }) {
2349
+ return createElement4(
2350
+ "div",
2351
+ {
2352
+ ...domProps,
2353
+ className: mergeClassName("mdx-code-tab", className),
2354
+ "data-label": label,
2355
+ "data-language": language
2356
+ },
2357
+ children
2358
+ );
2359
+ }
2360
+
2361
+ // src/mdx-components/details.ts
2362
+ import { createElement as createElement5 } from "react";
2363
+ function Details({
2364
+ summary,
2365
+ open,
2366
+ children,
2367
+ className,
2368
+ ...domProps
2369
+ }) {
2370
+ return createElement5(
2371
+ "details",
2372
+ {
2373
+ ...domProps,
2374
+ className: mergeClassName("mdx-details", className),
2375
+ open: open === "true" || void 0
2376
+ },
2377
+ createElement5("summary", { className: "mdx-details-summary" }, summary),
2378
+ createElement5("div", { className: "mdx-details-body" }, children)
2379
+ );
2380
+ }
2381
+
2382
+ // src/mdx-components/link-card.ts
2383
+ import { createElement as createElement6 } from "react";
2384
+ function LinkCard({
2385
+ href,
2386
+ title,
2387
+ description,
2388
+ domain,
2389
+ children,
2390
+ className,
2391
+ ...domProps
2392
+ }) {
2393
+ const desc = description || (children ? children : null);
2394
+ return createElement6(
2395
+ "a",
2396
+ {
2397
+ ...domProps,
2398
+ className: mergeClassName("mdx-link-card", className),
2399
+ href
2400
+ },
2401
+ createElement6("div", { className: "mdx-link-card-title" }, title),
2402
+ desc ? createElement6("div", { className: "mdx-link-card-desc" }, desc) : null,
2403
+ domain ? createElement6("div", { className: "mdx-link-card-domain" }, domain) : null
2404
+ );
2405
+ }
2406
+
1571
2407
  // src/mdx-components/steps.ts
1572
- import { createElement as createElement4, Children } from "react";
2408
+ import { createElement as createElement7, Children } from "react";
1573
2409
  function Steps({ children, className, ...domProps }) {
1574
2410
  const items = [];
1575
2411
  Children.forEach(children, (child) => {
@@ -1577,41 +2413,41 @@ function Steps({ children, className, ...domProps }) {
1577
2413
  items.push(child);
1578
2414
  }
1579
2415
  });
1580
- return createElement4(
2416
+ return createElement7(
1581
2417
  "div",
1582
2418
  {
1583
2419
  ...domProps,
1584
2420
  className: mergeClassName("mdx-steps", className)
1585
2421
  },
1586
2422
  items.map(
1587
- (item, i) => createElement4(
2423
+ (item, i) => createElement7(
1588
2424
  "div",
1589
2425
  { className: "mdx-steps-item", key: i },
1590
- createElement4(
2426
+ createElement7(
1591
2427
  "div",
1592
2428
  { className: "mdx-steps-indicator" },
1593
- createElement4("span", { className: "mdx-steps-number" }, String(i + 1)),
1594
- i < items.length - 1 && createElement4("div", { className: "mdx-steps-line" })
2429
+ createElement7("span", { className: "mdx-steps-number" }, String(i + 1)),
2430
+ i < items.length - 1 && createElement7("div", { className: "mdx-steps-line" })
1595
2431
  ),
1596
- createElement4("div", { className: "mdx-steps-content" }, item)
2432
+ createElement7("div", { className: "mdx-steps-content" }, item)
1597
2433
  )
1598
2434
  )
1599
2435
  );
1600
2436
  }
1601
2437
  function Step({ title, children, className, ...domProps }) {
1602
- return createElement4(
2438
+ return createElement7(
1603
2439
  "div",
1604
2440
  {
1605
2441
  ...domProps,
1606
2442
  className: mergeClassName("mdx-step", className)
1607
2443
  },
1608
- title && createElement4("h4", { className: "mdx-step-title" }, title),
1609
- children && createElement4("div", { className: "mdx-step-body" }, children)
2444
+ title && createElement7("h4", { className: "mdx-step-title" }, title),
2445
+ children && createElement7("div", { className: "mdx-step-body" }, children)
1610
2446
  );
1611
2447
  }
1612
2448
 
1613
2449
  // src/mdx-components/tabs.ts
1614
- import { createElement as createElement5, Children as Children2 } from "react";
2450
+ import { createElement as createElement8, Children as Children2 } from "react";
1615
2451
  function Tabs({ children, className, ...domProps }) {
1616
2452
  const tabs = [];
1617
2453
  Children2.forEach(children, (child) => {
@@ -1620,36 +2456,36 @@ function Tabs({ children, className, ...domProps }) {
1620
2456
  }
1621
2457
  });
1622
2458
  const groupId = `mdx-tabs-${Math.random().toString(36).slice(2, 8)}`;
1623
- return createElement5(
2459
+ return createElement8(
1624
2460
  "div",
1625
2461
  {
1626
2462
  ...domProps,
1627
2463
  className: mergeClassName("mdx-tabs", className)
1628
2464
  },
1629
- createElement5(
2465
+ createElement8(
1630
2466
  "div",
1631
2467
  { className: "mdx-tabs-list", role: "tablist" },
1632
2468
  tabs.map(
1633
- (tab, i) => createElement5(
2469
+ (tab, i) => createElement8(
1634
2470
  "label",
1635
2471
  { className: "mdx-tabs-trigger", key: i },
1636
- createElement5("input", {
2472
+ createElement8("input", {
1637
2473
  type: "radio",
1638
2474
  name: groupId,
1639
2475
  className: "mdx-tabs-radio",
1640
2476
  defaultChecked: i === 0
1641
2477
  }),
1642
- createElement5("span", null, tab.label)
2478
+ createElement8("span", null, tab.label)
1643
2479
  )
1644
2480
  )
1645
2481
  ),
1646
2482
  tabs.map(
1647
- (tab, i) => createElement5("div", { className: "mdx-tabs-panel", key: i }, tab.content)
2483
+ (tab, i) => createElement8("div", { className: "mdx-tabs-panel", key: i }, tab.content)
1648
2484
  )
1649
2485
  );
1650
2486
  }
1651
2487
  function Tab({ label: _label, children, className, ...domProps }) {
1652
- return createElement5(
2488
+ return createElement8(
1653
2489
  "div",
1654
2490
  {
1655
2491
  ...domProps,
@@ -1660,9 +2496,9 @@ function Tab({ label: _label, children, className, ...domProps }) {
1660
2496
  }
1661
2497
 
1662
2498
  // src/mdx-components/file-tree.ts
1663
- import { createElement as createElement6 } from "react";
2499
+ import { createElement as createElement9 } from "react";
1664
2500
  function parseFileTree(text) {
1665
- const entries = [];
2501
+ const entries2 = [];
1666
2502
  for (const line of text.split("\n")) {
1667
2503
  const trimmed = line.replace(/^[\s\-\*]*/, "");
1668
2504
  if (!trimmed) continue;
@@ -1670,29 +2506,29 @@ function parseFileTree(text) {
1670
2506
  const depth = Math.floor(leadingSpaces / 2);
1671
2507
  const isDir = trimmed.endsWith("/");
1672
2508
  const name = isDir ? trimmed.slice(0, -1) : trimmed;
1673
- entries.push({ name, isDir, depth });
2509
+ entries2.push({ name, isDir, depth });
1674
2510
  }
1675
- return entries;
2511
+ return entries2;
1676
2512
  }
1677
2513
  function FileTree({ children, className, ...domProps }) {
1678
2514
  const text = extractText(children);
1679
- const entries = parseFileTree(text);
1680
- return createElement6(
2515
+ const entries2 = parseFileTree(text);
2516
+ return createElement9(
1681
2517
  "div",
1682
2518
  {
1683
2519
  ...domProps,
1684
2520
  className: mergeClassName("mdx-file-tree", className)
1685
2521
  },
1686
- entries.map(
1687
- (entry, i) => createElement6(
2522
+ entries2.map(
2523
+ (entry, i) => createElement9(
1688
2524
  "div",
1689
2525
  {
1690
2526
  className: `mdx-file-tree-entry ${entry.isDir ? "mdx-file-tree-dir" : "mdx-file-tree-file"}`,
1691
2527
  style: { paddingLeft: `${entry.depth * 1.25 + 0.5}rem` },
1692
2528
  key: i
1693
2529
  },
1694
- createElement6("span", { className: "mdx-file-tree-icon" }, entry.isDir ? "\u{1F4C1}" : "\u{1F4C4}"),
1695
- createElement6("span", { className: "mdx-file-tree-name" }, entry.name)
2530
+ createElement9("span", { className: "mdx-file-tree-icon" }, entry.isDir ? "\u{1F4C1}" : "\u{1F4C4}"),
2531
+ createElement9("span", { className: "mdx-file-tree-name" }, entry.name)
1696
2532
  )
1697
2533
  )
1698
2534
  );
@@ -1708,9 +2544,9 @@ function extractText(node) {
1708
2544
  }
1709
2545
 
1710
2546
  // src/mdx-components/kbd.ts
1711
- import { createElement as createElement7 } from "react";
2547
+ import { createElement as createElement10 } from "react";
1712
2548
  function Kbd({ children, className, ...domProps }) {
1713
- return createElement7(
2549
+ return createElement10(
1714
2550
  "kbd",
1715
2551
  {
1716
2552
  ...domProps,
@@ -1725,6 +2561,9 @@ var DEFAULT_MDX_COMPONENTS = {
1725
2561
  Callout,
1726
2562
  Note,
1727
2563
  CodeDemo,
2564
+ CodeTab,
2565
+ Details,
2566
+ LinkCard,
1728
2567
  Steps,
1729
2568
  Step,
1730
2569
  Tabs,
@@ -1868,7 +2707,16 @@ function collectIndentedCodeRewrites(source, root) {
1868
2707
  return stripIndentedCodeIndent(withoutPrefix);
1869
2708
  });
1870
2709
  const fence = getFence(normalizedLines);
2710
+ const lineMappings = [
2711
+ { sourceLine: startLine, sourceColumn: preservedPrefixColumns + 1 },
2712
+ ...normalizedLines.map((_, offset) => ({
2713
+ sourceLine: startLine + offset,
2714
+ sourceColumn: preservedPrefixColumns + 5
2715
+ })),
2716
+ { sourceLine: endLine, sourceColumn: preservedPrefixColumns + 1 }
2717
+ ];
1871
2718
  rewrites.push({
2719
+ kind: "indented-code",
1872
2720
  startLine,
1873
2721
  endLine,
1874
2722
  replacementLines: [
@@ -1876,8 +2724,7 @@ function collectIndentedCodeRewrites(source, root) {
1876
2724
  ...normalizedLines.map((line) => `${prefix}${line}`),
1877
2725
  `${prefix}${fence}`
1878
2726
  ],
1879
- preservedPrefixColumns,
1880
- removedIndentColumns: 4
2727
+ lineMappings
1881
2728
  });
1882
2729
  }
1883
2730
  }
@@ -1890,47 +2737,6 @@ function collectIndentedCodeRewrites(source, root) {
1890
2737
  rewrites.sort((left, right) => left.startLine - right.startLine);
1891
2738
  return rewrites;
1892
2739
  }
1893
- function buildCompilePlan(source, rewrites) {
1894
- if (rewrites.length === 0) {
1895
- return {
1896
- compileSource: source,
1897
- sourceMap: { segments: [] }
1898
- };
1899
- }
1900
- const sourceLines = source.split("\n");
1901
- const outputLines = [];
1902
- const segments = [];
1903
- let lineNumber = 1;
1904
- let rewriteIndex = 0;
1905
- while (lineNumber <= sourceLines.length) {
1906
- const rewrite = rewrites[rewriteIndex];
1907
- if (rewrite && rewrite.startLine === lineNumber) {
1908
- const normalizedStartLine = outputLines.length + 1;
1909
- outputLines.push(...rewrite.replacementLines);
1910
- const normalizedEndLine = outputLines.length;
1911
- segments.push({
1912
- kind: "indented-code",
1913
- normalizedStartLine,
1914
- normalizedEndLine,
1915
- sourceStartLine: rewrite.startLine,
1916
- sourceEndLine: rewrite.endLine,
1917
- preservedPrefixColumns: rewrite.preservedPrefixColumns,
1918
- removedIndentColumns: rewrite.removedIndentColumns
1919
- });
1920
- lineNumber = rewrite.endLine + 1;
1921
- rewriteIndex += 1;
1922
- continue;
1923
- }
1924
- outputLines.push(sourceLines[lineNumber - 1]);
1925
- lineNumber += 1;
1926
- }
1927
- const normalizedSource = outputLines.join("\n");
1928
- return {
1929
- compileSource: source.endsWith("\n") ? `${normalizedSource}
1930
- ` : normalizedSource,
1931
- sourceMap: { segments }
1932
- };
1933
- }
1934
2740
  function collectMdxSyntaxMetadata(root) {
1935
2741
  const componentNames = /* @__PURE__ */ new Set();
1936
2742
  const stack = [root];
@@ -1957,26 +2763,31 @@ function collectMdxSyntaxMetadata(root) {
1957
2763
  }
1958
2764
  function inspectMdxSource(source, options) {
1959
2765
  try {
1960
- const markdownTree = parseMarkdownTree(source, options);
1961
- const rewrites = collectIndentedCodeRewrites(source, markdownTree);
1962
- const { compileSource, sourceMap } = buildCompilePlan(source, rewrites);
1963
- const mdxProbeSource = buildMaskedSource(compileSource, parseMarkdownTree(compileSource, options));
2766
+ const normalized = normalizeOwoMarkSource(source, { enableMath: options?.enableMath });
2767
+ const markdownTree = parseMarkdownTree(normalized.source, options);
2768
+ const rewrites = collectIndentedCodeRewrites(normalized.source, markdownTree);
2769
+ const compilePlan = applySourceRewrites(normalized.source, normalized.sourceMap, rewrites);
2770
+ const mdxProbeSource = buildMaskedSource(
2771
+ compilePlan.source,
2772
+ parseMarkdownTree(compilePlan.source, options)
2773
+ );
1964
2774
  const mdxTree = createParser("production", options).use(remarkMdx).parse(mdxProbeSource);
1965
2775
  const { reason, componentNames } = collectMdxSyntaxMetadata(mdxTree);
1966
2776
  return {
1967
2777
  hasMdxSyntax: reason !== void 0,
1968
2778
  reason,
1969
2779
  componentNames,
1970
- compileSource,
1971
- sourceMap
2780
+ compileSource: compilePlan.source,
2781
+ sourceMap: compilePlan.sourceMap
1972
2782
  };
1973
2783
  } catch {
2784
+ const fallback = normalizeOwoMarkSource(source, { enableMath: options?.enableMath });
1974
2785
  return {
1975
2786
  hasMdxSyntax: true,
1976
2787
  reason: "parse-failed-fallback",
1977
2788
  componentNames: [],
1978
- compileSource: source,
1979
- sourceMap: { segments: [] }
2789
+ compileSource: fallback.source,
2790
+ sourceMap: fallback.sourceMap
1980
2791
  };
1981
2792
  }
1982
2793
  }
@@ -1993,37 +2804,10 @@ function detectMdxSyntax(source, options) {
1993
2804
  return { hasMdxSyntax, reason };
1994
2805
  }
1995
2806
  function remapMdxLineNumber(line, sourceMap) {
1996
- if (typeof line !== "number" || !sourceMap?.segments.length) return line;
1997
- let delta = 0;
1998
- for (const segment of sourceMap.segments) {
1999
- if (line < segment.normalizedStartLine) {
2000
- break;
2001
- }
2002
- if (line <= segment.normalizedEndLine) {
2003
- if (line === segment.normalizedStartLine) return segment.sourceStartLine;
2004
- if (line === segment.normalizedEndLine) return segment.sourceEndLine;
2005
- return segment.sourceStartLine + (line - segment.normalizedStartLine - 1);
2006
- }
2007
- delta += segment.normalizedEndLine - segment.normalizedStartLine + 1 - (segment.sourceEndLine - segment.sourceStartLine + 1);
2008
- }
2009
- return line - delta;
2807
+ return remapNormalizedLine(line, sourceMap);
2010
2808
  }
2011
2809
  function remapMdxColumnNumber(line, column, sourceMap) {
2012
- if (typeof line !== "number" || typeof column !== "number" || !sourceMap?.segments.length) {
2013
- return column;
2014
- }
2015
- for (const segment of sourceMap.segments) {
2016
- if (line < segment.normalizedStartLine) break;
2017
- if (line > segment.normalizedEndLine) continue;
2018
- if (line === segment.normalizedStartLine || line === segment.normalizedEndLine) {
2019
- return segment.preservedPrefixColumns + 1;
2020
- }
2021
- if (column <= segment.preservedPrefixColumns) {
2022
- return column;
2023
- }
2024
- return column + segment.removedIndentColumns;
2025
- }
2026
- return column;
2810
+ return remapNormalizedColumn(line, column, sourceMap);
2027
2811
  }
2028
2812
  function remapMdxErrorDetails(error, sourceMap) {
2029
2813
  if (error && typeof error === "object") {
@@ -2051,6 +2835,560 @@ function remapMdxErrorDetails(error, sourceMap) {
2051
2835
  return { message: String(error) };
2052
2836
  }
2053
2837
 
2838
+ // src/processor/index.ts
2839
+ import { parseMarkdownToDocument as parseMarkdownToDocument2 } from "@owomark/core";
2840
+
2841
+ // src/processor/canonical-mdast.ts
2842
+ import {
2843
+ CARDS_FAMILY_CUSTOM_BLOCK_KEY,
2844
+ isCardsFamilyAttributes,
2845
+ parseInlineSideAnnotationFromText,
2846
+ parseMarkdownToDocument,
2847
+ stripInlineSideAnnotationTail,
2848
+ stripSideContinuationTail
2849
+ } from "@owomark/core";
2850
+ function createInlineMathNode(value) {
2851
+ return {
2852
+ type: "inlineMath",
2853
+ value,
2854
+ data: {
2855
+ hName: "code",
2856
+ hProperties: { className: ["language-math", "math-inline"] },
2857
+ hChildren: [{ type: "text", value }]
2858
+ }
2859
+ };
2860
+ }
2861
+ function splitMixedDoubleDollarText(value) {
2862
+ const nodes = [];
2863
+ let cursor = 0;
2864
+ const re = /\$\$([^$\n]+)\$\$/g;
2865
+ let match;
2866
+ while ((match = re.exec(value)) != null) {
2867
+ if (match.index > cursor) {
2868
+ nodes.push({ type: "text", value: value.slice(cursor, match.index) });
2869
+ }
2870
+ nodes.push(createInlineMathNode(match[1]));
2871
+ cursor = match.index + match[0].length;
2872
+ }
2873
+ if (cursor < value.length) {
2874
+ nodes.push({ type: "text", value: value.slice(cursor) });
2875
+ }
2876
+ return nodes.length > 0 ? nodes : [{ type: "text", value }];
2877
+ }
2878
+ function countLines(raw) {
2879
+ return raw === "" ? 1 : raw.split("\n").length;
2880
+ }
2881
+ function createPosition(startLine, endLine, offset, raw, sourceMap) {
2882
+ const normalizedEndColumn = raw.length === 0 ? 1 : (raw.split("\n").at(-1)?.length ?? 0) + 1;
2883
+ const remappedStartLine = remapNormalizedLine(startLine, sourceMap) ?? startLine;
2884
+ const remappedEndLine = remapNormalizedLine(endLine, sourceMap) ?? endLine;
2885
+ const remappedStartColumn = remapNormalizedColumn(startLine, 1, sourceMap) ?? 1;
2886
+ const remappedEndColumn = remapNormalizedColumn(endLine, normalizedEndColumn, sourceMap) ?? normalizedEndColumn;
2887
+ return {
2888
+ start: {
2889
+ line: remappedStartLine,
2890
+ column: remappedStartColumn,
2891
+ offset
2892
+ },
2893
+ end: {
2894
+ line: remappedEndLine,
2895
+ column: remappedEndColumn,
2896
+ offset: offset + raw.length
2897
+ }
2898
+ };
2899
+ }
2900
+ function advanceState(state, raw, sourceMap) {
2901
+ const startLine = state.line;
2902
+ const endLine = startLine + countLines(raw) - 1;
2903
+ const position = createPosition(startLine, endLine, state.offset, raw, sourceMap);
2904
+ state.line = endLine + 1;
2905
+ state.offset += raw.length + 1;
2906
+ return position;
2907
+ }
2908
+ function updateContainerPosition(node, child) {
2909
+ if (!child.position) {
2910
+ return;
2911
+ }
2912
+ if (!node.position) {
2913
+ node.position = {
2914
+ start: { ...child.position.start },
2915
+ end: { ...child.position.end }
2916
+ };
2917
+ return;
2918
+ }
2919
+ node.position.end = { ...child.position.end };
2920
+ }
2921
+ function appendChild(parent, child) {
2922
+ parent.children ??= [];
2923
+ parent.children.push(child);
2924
+ updateContainerPosition(parent, child);
2925
+ }
2926
+ function frameKey(frame) {
2927
+ return `${frame.kind}:${frame.depth}`;
2928
+ }
2929
+ function ancestryKey(frames) {
2930
+ return frames.map(frameKey).join("/");
2931
+ }
2932
+ function parseDirectiveAttributes(raw) {
2933
+ const attributes = {};
2934
+ const match = raw.match(/\{([^}]*)\}\s*$/);
2935
+ if (!match) {
2936
+ return attributes;
2937
+ }
2938
+ const content = match[1].trim();
2939
+ if (!content) {
2940
+ return attributes;
2941
+ }
2942
+ const attrRe = /([A-Za-z0-9_-]+)\s*=\s*(?:"([^"]*)"|'([^']*)'|([^\s]+))/g;
2943
+ let attrMatch;
2944
+ while ((attrMatch = attrRe.exec(content)) != null) {
2945
+ attributes[attrMatch[1]] = attrMatch[2] ?? attrMatch[3] ?? attrMatch[4] ?? "";
2946
+ }
2947
+ return attributes;
2948
+ }
2949
+ function parseFenceMeta(block) {
2950
+ const opener = block.syntaxRaw.split("\n")[0] ?? "";
2951
+ const match = opener.match(/^[`~]{3,}([^\s]*)\s*(.*)$/);
2952
+ if (!match) {
2953
+ return null;
2954
+ }
2955
+ const meta = match[2]?.trim() ?? "";
2956
+ return meta.length > 0 ? meta : null;
2957
+ }
2958
+ function inlineToMdast(nodes, options) {
2959
+ return nodes.flatMap((node) => {
2960
+ switch (node.kind) {
2961
+ case "text":
2962
+ return options.enableMath === false ? [{ type: "text", value: node.text }] : splitMixedDoubleDollarText(node.text);
2963
+ case "softBreak":
2964
+ return options.preserveSoftLineBreaks === false ? [{ type: "break" }] : [{ type: "text", value: "\n" }];
2965
+ case "strong":
2966
+ return [{ type: "strong", children: inlineToMdast(node.children, options) }];
2967
+ case "emphasis":
2968
+ return [{ type: "emphasis", children: inlineToMdast(node.children, options) }];
2969
+ case "delete":
2970
+ return [{ type: "delete", children: inlineToMdast(node.children, options) }];
2971
+ case "inlineCode":
2972
+ return [{ type: "inlineCode", value: node.text }];
2973
+ case "inlineMath":
2974
+ return options.enableMath === false ? [{ type: "text", value: `$${node.text}$` }] : [createInlineMathNode(node.text)];
2975
+ case "html":
2976
+ return [{ type: "html", value: node.text }];
2977
+ case "link":
2978
+ return [{ type: "link", url: node.url, children: inlineToMdast(node.children, options) }];
2979
+ case "image":
2980
+ return [{
2981
+ type: "image",
2982
+ url: node.url,
2983
+ alt: node.alt.map((child) => child.kind === "text" ? child.text : "").join("")
2984
+ }];
2985
+ }
2986
+ });
2987
+ }
2988
+ function inlineFromParagraphSource(source, options) {
2989
+ const document = parseMarkdownToDocument(source);
2990
+ const paragraph = document.conformance.blocks.find((block) => block.kind === "paragraph");
2991
+ return paragraph?.kind === "paragraph" ? inlineToMdast(paragraph.inline, options) : [{ type: "text", value: source }];
2992
+ }
2993
+ function attachBlockToParent(parent, blockNode) {
2994
+ appendChild(parent, blockNode);
2995
+ }
2996
+ function createSideAnnotationNode(block, position, options) {
2997
+ const strippedInlineMarkdown = block.raw.split("\n").map((line) => {
2998
+ if (parseInlineSideAnnotationFromText(line)) {
2999
+ return stripInlineSideAnnotationTail(line);
3000
+ }
3001
+ if (line.includes("(>+)")) {
3002
+ return stripSideContinuationTail(line);
3003
+ }
3004
+ return line;
3005
+ }).join("\n");
3006
+ const memberMarkdown = block.sideAnnotationKind === "inline" || block.sideAnnotationKind === "continuation-chain" ? strippedInlineMarkdown : block.members.map((member) => member.syntaxRaw).join("\n\n");
3007
+ const children = block.sideAnnotationKind === "continuation-chain" ? [{
3008
+ type: "paragraph",
3009
+ children: strippedInlineMarkdown.split("\n").flatMap((line, index, lines) => {
3010
+ const lineChildren = inlineFromParagraphSource(line, options);
3011
+ if (index === lines.length - 1) {
3012
+ return lineChildren;
3013
+ }
3014
+ return [...lineChildren, { type: "break" }];
3015
+ })
3016
+ }] : block.sideAnnotationKind !== "container" && block.sideAnnotationKind !== "reference-container" && !strippedInlineMarkdown.includes("\n\n") ? [{
3017
+ type: "paragraph",
3018
+ children: strippedInlineMarkdown.split("\n").flatMap((line, index, lines) => {
3019
+ const lineChildren = inlineFromParagraphSource(line, options);
3020
+ if (index === lines.length - 1) {
3021
+ return lineChildren;
3022
+ }
3023
+ return [...lineChildren, { type: "break" }];
3024
+ })
3025
+ }] : buildRootFromDocument(parseMarkdownToDocument(memberMarkdown), options).children ?? [];
3026
+ return {
3027
+ type: "sideAnnotation",
3028
+ data: {
3029
+ hName: "div",
3030
+ hProperties: {
3031
+ className: [
3032
+ "side-annotation",
3033
+ `side-type-${block.sideType}`,
3034
+ ...block.orphan ? ["side-orphan"] : []
3035
+ ],
3036
+ "data-side-type": block.sideType,
3037
+ ...block.annotationText ? { "data-side-text": block.annotationText } : {},
3038
+ ...block.orphan ? { "data-side-orphan": "true" } : {}
3039
+ }
3040
+ },
3041
+ sideType: block.sideType,
3042
+ sideTypeSymbol: block.sideTypeSymbol,
3043
+ noteRef: block.noteRef ?? null,
3044
+ inlineText: block.annotationText ?? null,
3045
+ orphan: block.orphan ?? false,
3046
+ position,
3047
+ children
3048
+ };
3049
+ }
3050
+ function createDirectiveContainerNode(block, position, options) {
3051
+ const lines = block.syntaxRaw.split("\n");
3052
+ const opener = lines[0] ?? "";
3053
+ const innerMarkdown = lines.slice(1, -1).join("\n");
3054
+ return {
3055
+ type: "containerDirective",
3056
+ name: block.directiveName,
3057
+ attributes: parseDirectiveAttributes(opener),
3058
+ position,
3059
+ children: buildRootFromDocument(parseMarkdownToDocument(innerMarkdown), options).children ?? []
3060
+ };
3061
+ }
3062
+ function createCustomBlockNodes(block, position, options) {
3063
+ const cardsAttributes = isCardsFamilyAttributes(block.customBlockAttributes) ? block.customBlockAttributes : null;
3064
+ if (block.customBlockKey === CARDS_FAMILY_CUSTOM_BLOCK_KEY && cardsAttributes) {
3065
+ return [{
3066
+ type: "cardsContainer",
3067
+ position,
3068
+ data: {
3069
+ hName: "section",
3070
+ hProperties: {
3071
+ className: ["owo-cards"],
3072
+ "data-owo-cards": "",
3073
+ "data-owo-cards-cols": String(cardsAttributes.layout.cols)
3074
+ }
3075
+ },
3076
+ children: cardsAttributes.cards.map((card) => {
3077
+ const bodyRoot = buildRootFromDocument(parseMarkdownToDocument(card.bodyMarkdown), options);
3078
+ const children = [];
3079
+ if (card.title) {
3080
+ children.push({
3081
+ type: "cardsTitle",
3082
+ position,
3083
+ data: {
3084
+ hName: "header",
3085
+ hProperties: {
3086
+ className: ["owo-card-title"]
3087
+ }
3088
+ },
3089
+ children: [{ type: "text", value: card.title }]
3090
+ });
3091
+ }
3092
+ children.push({
3093
+ type: "cardsBody",
3094
+ position,
3095
+ data: {
3096
+ hName: "div",
3097
+ hProperties: {
3098
+ className: ["owo-card-body"]
3099
+ }
3100
+ },
3101
+ children: bodyRoot.children ?? []
3102
+ });
3103
+ return {
3104
+ type: "cardsItem",
3105
+ position,
3106
+ data: {
3107
+ hName: "article",
3108
+ hProperties: {
3109
+ className: ["owo-card", ...card.tone ? [`owo-card-tone-${card.tone}`] : []],
3110
+ "data-owo-card": "",
3111
+ ...card.tone ? { "data-owo-card-tone": card.tone } : {}
3112
+ }
3113
+ },
3114
+ children
3115
+ };
3116
+ })
3117
+ }];
3118
+ }
3119
+ switch (block.customBlockRuntime.processorFallback) {
3120
+ case "skip-block":
3121
+ return [];
3122
+ case "unwrap-children": {
3123
+ const innerMarkdown = block.syntaxRaw.split("\n").slice(1, -1).join("\n");
3124
+ if (!innerMarkdown.trim()) {
3125
+ return [];
3126
+ }
3127
+ return (buildRootFromDocument(parseMarkdownToDocument(innerMarkdown), options).children ?? []).map((child) => ({
3128
+ ...child,
3129
+ position: child.position ?? position
3130
+ }));
3131
+ }
3132
+ case "render-raw":
3133
+ default:
3134
+ return [{
3135
+ type: "paragraph",
3136
+ position,
3137
+ children: [{ type: "text", value: block.raw }]
3138
+ }];
3139
+ }
3140
+ }
3141
+ function buildLeafNode(block, position, options) {
3142
+ switch (block.type) {
3143
+ case "paragraph":
3144
+ return [{
3145
+ type: "paragraph",
3146
+ children: inlineToMdast(block.conformanceInline ?? [], options),
3147
+ position
3148
+ }];
3149
+ case "heading":
3150
+ return [{
3151
+ type: "heading",
3152
+ depth: block.headingLevel,
3153
+ children: inlineToMdast(block.conformanceInline ?? [], options),
3154
+ position
3155
+ }];
3156
+ case "code-fence":
3157
+ return [{
3158
+ type: "code",
3159
+ lang: block.language || null,
3160
+ meta: parseFenceMeta(block),
3161
+ value: block.syntaxRaw.split("\n").slice(1, -1).join("\n"),
3162
+ position
3163
+ }];
3164
+ case "math-block":
3165
+ if (options.enableMath === false) {
3166
+ return [{
3167
+ type: "paragraph",
3168
+ children: [{ type: "text", value: block.raw }],
3169
+ position
3170
+ }];
3171
+ }
3172
+ return [{
3173
+ type: "math",
3174
+ meta: null,
3175
+ value: block.syntaxRaw.includes("\n") ? block.syntaxRaw.split("\n").slice(1, -1).join("\n") : block.syntaxRaw.slice(2, -2),
3176
+ data: {
3177
+ hName: "pre",
3178
+ hChildren: [{
3179
+ type: "element",
3180
+ tagName: "code",
3181
+ properties: { className: ["language-math", "math-display"] },
3182
+ children: [{
3183
+ type: "text",
3184
+ value: block.syntaxRaw.includes("\n") ? block.syntaxRaw.split("\n").slice(1, -1).join("\n") : block.syntaxRaw.slice(2, -2)
3185
+ }]
3186
+ }]
3187
+ },
3188
+ position
3189
+ }];
3190
+ case "table":
3191
+ return block.conformanceTableNode != null ? [block.conformanceTableNode(position)] : [];
3192
+ case "html-block":
3193
+ return [{ type: "html", value: block.syntaxRaw, position }];
3194
+ case "thematic-break":
3195
+ return [{ type: "thematicBreak", position }];
3196
+ case "side-annotation":
3197
+ if (options.enableSideAnnotation === false) {
3198
+ return [{
3199
+ type: "paragraph",
3200
+ children: [{ type: "text", value: block.raw }],
3201
+ position
3202
+ }];
3203
+ }
3204
+ return [createSideAnnotationNode(block, position, options)];
3205
+ case "directive-container":
3206
+ if (options.enableComponents === false && block.directiveName !== "side") {
3207
+ return [{
3208
+ type: "paragraph",
3209
+ children: [{ type: "text", value: block.raw }],
3210
+ position
3211
+ }];
3212
+ }
3213
+ return [createDirectiveContainerNode(block, position, options)];
3214
+ case "custom-block":
3215
+ return createCustomBlockNodes(block, position, options);
3216
+ case "blockquote":
3217
+ return [{
3218
+ type: "paragraph",
3219
+ children: inlineToMdast(block.conformanceInline ?? [], options),
3220
+ position
3221
+ }];
3222
+ default:
3223
+ return [];
3224
+ }
3225
+ }
3226
+ function ensureListContext(stack, parent, kind, depth, ancestry) {
3227
+ const key = ancestryKey(ancestry);
3228
+ const existing = stack.find((entry) => entry.kind === kind && entry.depth === depth && entry.ancestryKey === key);
3229
+ if (existing) {
3230
+ return existing;
3231
+ }
3232
+ const node = {
3233
+ type: "list",
3234
+ ordered: kind === "ordered-list",
3235
+ children: []
3236
+ };
3237
+ appendChild(parent, node);
3238
+ const created = {
3239
+ kind,
3240
+ depth,
3241
+ ancestryKey: key,
3242
+ node,
3243
+ currentListItem: null
3244
+ };
3245
+ stack.push(created);
3246
+ return created;
3247
+ }
3248
+ function buildRootFromBlocks(blocks, options) {
3249
+ const root = { type: "root", children: [] };
3250
+ const state = { line: 1, offset: 0 };
3251
+ const listStack = [];
3252
+ const containerMap = /* @__PURE__ */ new Map([["", root]]);
3253
+ for (const rawBlock of blocks) {
3254
+ const position = advanceState(state, rawBlock.raw, options.sourceMap);
3255
+ const block = rawBlock;
3256
+ if (rawBlock.type === "paragraph" && rawBlock.raw.trim() === "") {
3257
+ continue;
3258
+ }
3259
+ const effectiveAncestry = rawBlock.type === "blockquote" ? [
3260
+ ...rawBlock.ancestry,
3261
+ ...Array.from({ length: rawBlock.depth }, (_, index) => ({
3262
+ kind: "blockquote",
3263
+ depth: index + 1
3264
+ }))
3265
+ ] : rawBlock.ancestry;
3266
+ let parent = root;
3267
+ let ancestryFrames = [];
3268
+ for (const frame of effectiveAncestry) {
3269
+ ancestryFrames = [...ancestryFrames, { kind: frame.kind, depth: frame.depth }];
3270
+ const key = ancestryKey(ancestryFrames);
3271
+ const cached = containerMap.get(key);
3272
+ if (cached) {
3273
+ parent = cached;
3274
+ continue;
3275
+ }
3276
+ let node;
3277
+ if (frame.kind === "blockquote") {
3278
+ node = { type: "blockquote", children: [] };
3279
+ } else if (frame.kind === "unordered-list" || frame.kind === "ordered-list") {
3280
+ node = { type: "list", ordered: frame.kind === "ordered-list", children: [] };
3281
+ } else {
3282
+ node = { type: "listItem", children: [] };
3283
+ }
3284
+ appendChild(parent, node);
3285
+ containerMap.set(key, node);
3286
+ parent = node;
3287
+ }
3288
+ if (rawBlock.type === "unordered-list" || rawBlock.type === "ordered-list") {
3289
+ const listContext = ensureListContext(listStack, parent, rawBlock.type, rawBlock.depth, rawBlock.ancestry);
3290
+ const listItem = { type: "listItem", children: [], position };
3291
+ appendChild(listContext.node, listItem);
3292
+ listContext.currentListItem = listItem;
3293
+ const paragraph = {
3294
+ type: "paragraph",
3295
+ children: inlineToMdast(block.conformanceInline ?? [], options),
3296
+ position
3297
+ };
3298
+ appendChild(listItem, paragraph);
3299
+ const syntheticFrames = [
3300
+ ...rawBlock.ancestry.map((frame) => ({ kind: frame.kind, depth: frame.depth })),
3301
+ { kind: rawBlock.type, depth: rawBlock.depth },
3302
+ { kind: "list-item", depth: rawBlock.depth }
3303
+ ];
3304
+ containerMap.set(ancestryKey(syntheticFrames), listItem);
3305
+ updateContainerPosition(listContext.node, listItem);
3306
+ continue;
3307
+ }
3308
+ for (const node of buildLeafNode(block, position, options)) {
3309
+ attachBlockToParent(parent, node);
3310
+ }
3311
+ }
3312
+ return root;
3313
+ }
3314
+ function buildRootFromDocument(document, options = {}) {
3315
+ const conformanceBlocks = [...document.conformance.blocks];
3316
+ function shiftConformanceForBlock(block) {
3317
+ if (block.type === "side-annotation" || block.type === "side-note-definition" || block.type === "directive-container" || block.type === "custom-block" || block.type === "reference-definition" || block.type === "paragraph" && block.raw.trim() === "") {
3318
+ return null;
3319
+ }
3320
+ return conformanceBlocks.shift() ?? null;
3321
+ }
3322
+ const enrichedBlocks = [];
3323
+ for (let index = 0; index < document.blocks.length; index += 1) {
3324
+ const block = document.blocks[index];
3325
+ const conformance = shiftConformanceForBlock(block);
3326
+ const sourceBlockCount = conformance?.kind === "paragraph" || conformance?.kind === "blockquote" ? conformance.sourceBlockCount ?? 1 : 1;
3327
+ const sourceBlocks = document.blocks.slice(index, index + sourceBlockCount);
3328
+ const mergedRaw = sourceBlocks.map((entry) => entry.raw).join("\n");
3329
+ const mergedSyntaxRaw = sourceBlocks.map((entry) => entry.syntaxRaw).join("\n");
3330
+ const mergedEndLine = sourceBlocks[sourceBlocks.length - 1]?.endLine ?? block.endLine;
3331
+ enrichedBlocks.push({
3332
+ ...block,
3333
+ raw: mergedRaw,
3334
+ syntaxRaw: mergedSyntaxRaw,
3335
+ endLine: mergedEndLine,
3336
+ conformanceInline: conformance?.kind === "paragraph" || conformance?.kind === "heading" || conformance?.kind === "blockquote" || conformance?.kind === "listItem" ? conformance.inline : void 0,
3337
+ conformanceTableNode: conformance?.kind === "table" ? (position) => ({
3338
+ type: "table",
3339
+ children: conformance.rows.map((row) => ({
3340
+ type: "tableRow",
3341
+ children: row.cells.map((cell) => ({
3342
+ type: "tableCell",
3343
+ children: [{ type: "paragraph", children: inlineToMdast(cell.inline, options) }]
3344
+ }))
3345
+ })),
3346
+ position
3347
+ }) : null
3348
+ });
3349
+ index += sourceBlockCount - 1;
3350
+ }
3351
+ return buildRootFromBlocks(enrichedBlocks, options);
3352
+ }
3353
+
3354
+ // src/processor/mdx-execution-plan.ts
3355
+ function planMdxCompileExecution(options) {
3356
+ if (options.enableCodeHighlight !== false) {
3357
+ return {
3358
+ target: "main-thread",
3359
+ reason: "code-highlighting-not-worker-safe"
3360
+ };
3361
+ }
3362
+ if (options.extraRemarkPlugins?.length) {
3363
+ return {
3364
+ target: "main-thread",
3365
+ reason: "extra-remark-plugins-not-worker-safe"
3366
+ };
3367
+ }
3368
+ if (options.extraRehypePlugins?.length) {
3369
+ return {
3370
+ target: "main-thread",
3371
+ reason: "extra-rehype-plugins-not-worker-safe"
3372
+ };
3373
+ }
3374
+ if (options.extraRemarkDescriptors?.length && !allWorkerSafeBuiltinDescriptors(options.extraRemarkDescriptors)) {
3375
+ return {
3376
+ target: "main-thread",
3377
+ reason: "extra-remark-descriptors-not-worker-safe"
3378
+ };
3379
+ }
3380
+ if (options.extraRehypeDescriptors?.length && !allWorkerSafeBuiltinDescriptors(options.extraRehypeDescriptors)) {
3381
+ return {
3382
+ target: "main-thread",
3383
+ reason: "extra-rehype-descriptors-not-worker-safe"
3384
+ };
3385
+ }
3386
+ return {
3387
+ target: "worker",
3388
+ reason: "worker-safe"
3389
+ };
3390
+ }
3391
+
2054
3392
  // src/processor/index.ts
2055
3393
  var DEFAULT_CODE_THEME = "vitesse-light";
2056
3394
  function buildRemarkPlugins(options) {
@@ -2058,7 +3396,7 @@ function buildRemarkPlugins(options) {
2058
3396
  const enableSideAnnotation = options.enableSideAnnotation !== false;
2059
3397
  const enableMarkdownSandbox = options.enableMarkdownSandbox !== false;
2060
3398
  const plugins = [
2061
- remarkParse2,
3399
+ options.canonicalDocument == null ? remarkParse2 : createCanonicalDocumentParser(options.canonicalDocument, options),
2062
3400
  remarkGfm2
2063
3401
  ];
2064
3402
  if (enableMath) {
@@ -2066,6 +3404,9 @@ function buildRemarkPlugins(options) {
2066
3404
  plugins.push(remarkNormalizeStandaloneMath);
2067
3405
  }
2068
3406
  plugins.push(remarkDirective2);
3407
+ plugins.push([remarkOwoComponents, {
3408
+ enabled: options.enableComponents !== false
3409
+ }]);
2069
3410
  if (options.mode !== "preview") {
2070
3411
  if (enableSideAnnotation) {
2071
3412
  plugins.push(remarkMicromarkSideAnnotation);
@@ -2075,6 +3416,7 @@ function buildRemarkPlugins(options) {
2075
3416
  if (!options.preserveSoftLineBreaks) {
2076
3417
  plugins.push(remarkConvertSoftBreaksToHardBreaks);
2077
3418
  }
3419
+ plugins.push(remarkCodeBlockMetadata);
2078
3420
  if (enableSideAnnotation) {
2079
3421
  plugins.push(remarkSideAnnotation);
2080
3422
  }
@@ -2097,6 +3439,16 @@ function buildRemarkPlugins(options) {
2097
3439
  }
2098
3440
  return plugins;
2099
3441
  }
3442
+ function createCanonicalDocumentParser(document, options) {
3443
+ return function canonicalDocumentParser() {
3444
+ this.parser = () => buildRootFromDocument(document, {
3445
+ enableSideAnnotation: options.enableSideAnnotation,
3446
+ enableMath: options.enableMath,
3447
+ enableComponents: options.enableComponents,
3448
+ sourceMap: options.sourceMap
3449
+ });
3450
+ };
3451
+ }
2100
3452
  function buildRehypePlugins(options) {
2101
3453
  const enableMath = options.enableMath !== false;
2102
3454
  const enableSideAnnotation = options.enableSideAnnotation !== false;
@@ -2135,24 +3487,31 @@ function createOwoMarkProcessor(options) {
2135
3487
  return createUnifiedProcessor(opts);
2136
3488
  }
2137
3489
  function createUnifiedProcessor(opts) {
2138
- const remarkPlugins = buildRemarkPlugins(opts);
2139
3490
  const rehypePlugins = buildRehypePlugins(opts);
2140
- let proc = unified2();
2141
- for (const plugin of remarkPlugins) {
2142
- proc = applyPlugin2(proc, plugin);
2143
- }
2144
- proc = proc.use(remarkRehype, {
2145
- handlers: {
2146
- markdownSandbox: markdownSandboxHandler
2147
- }
2148
- });
2149
- for (const plugin of rehypePlugins) {
2150
- proc = applyPlugin2(proc, plugin);
2151
- }
2152
- proc = proc.use(rehypeStringify, { allowDangerousHtml: true });
2153
3491
  return {
2154
3492
  async process(source) {
2155
- const result = await proc.process(source);
3493
+ const normalized = normalizeOwoMarkSource(source, { enableMath: opts.enableMath });
3494
+ const canonicalDocument = opts.canonicalDocument ?? parseMarkdownToDocument2(normalized.source);
3495
+ const remarkPlugins = buildRemarkPlugins({
3496
+ ...opts,
3497
+ canonicalDocument,
3498
+ sourceMap: normalized.sourceMap
3499
+ });
3500
+ let runtimeProc = unified2();
3501
+ for (const plugin of remarkPlugins) {
3502
+ runtimeProc = applyPlugin2(runtimeProc, plugin);
3503
+ }
3504
+ runtimeProc = runtimeProc.use(remarkRehype, {
3505
+ handlers: {
3506
+ markdownSandbox: markdownSandboxHandler,
3507
+ owoComponentRendered: owoComponentRenderedHandler
3508
+ }
3509
+ });
3510
+ for (const plugin of rehypePlugins) {
3511
+ runtimeProc = applyPlugin2(runtimeProc, plugin);
3512
+ }
3513
+ runtimeProc = runtimeProc.use(rehypeStringify, { allowDangerousHtml: true });
3514
+ const result = await runtimeProc.process(normalized.source);
2156
3515
  return { value: String(result), toString: () => String(result) };
2157
3516
  }
2158
3517
  };
@@ -2267,29 +3626,41 @@ function getOwoMarkPlugins(options) {
2267
3626
  return { remarkPlugins, rehypePlugins };
2268
3627
  }
2269
3628
  export {
3629
+ COMPONENT_REGISTRY,
2270
3630
  Callout,
2271
3631
  CodeDemo,
3632
+ CodeTab,
2272
3633
  DEFAULT_MDX_COMPONENTS,
3634
+ Details,
2273
3635
  FileTree,
2274
3636
  Kbd,
3637
+ LinkCard,
2275
3638
  Note,
2276
3639
  Step,
2277
3640
  Steps,
2278
3641
  Tab,
2279
3642
  Tabs,
2280
3643
  allBuiltinDescriptors,
3644
+ allWorkerSafeBuiltinDescriptors,
2281
3645
  analyzeMdxSyntax,
2282
3646
  createOwoMarkProcessor,
2283
3647
  detectMdxSyntax,
3648
+ getComponentEntry,
2284
3649
  getOwoMarkPlugins,
2285
3650
  inspectMdxSource,
3651
+ isKnownDirective,
3652
+ isWorkerSafeBuiltinDescriptor,
3653
+ owoComponentRenderedHandler,
3654
+ planMdxCompileExecution,
2286
3655
  registerPlugin,
2287
3656
  rehypeMathDisplayFix,
2288
3657
  rehypeSideAnnotation,
2289
3658
  rehypeSourceLines,
2290
3659
  remapMdxErrorDetails,
3660
+ remarkCodeBlockMetadata,
2291
3661
  remarkConvertSoftBreaksToHardBreaks,
2292
3662
  remarkMicromarkSideAnnotation,
3663
+ remarkOwoComponents,
2293
3664
  remarkSideAnnotation,
2294
3665
  resolveDescriptors
2295
3666
  };