@dogsbay/format-dogsbay-md 0.2.0-beta.121 → 0.2.0-beta.123

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.
Files changed (115) hide show
  1. package/dist/attributes.d.ts +0 -1
  2. package/dist/attributes.js +0 -1
  3. package/dist/browser.d.ts +0 -1
  4. package/dist/browser.js +0 -1
  5. package/dist/capabilities.d.ts +25 -0
  6. package/dist/capabilities.js +91 -0
  7. package/dist/cli.d.ts +0 -1
  8. package/dist/cli.js +2 -1
  9. package/dist/code-regions.d.ts +0 -1
  10. package/dist/code-regions.js +0 -1
  11. package/dist/directive-guard.d.ts +0 -1
  12. package/dist/directive-guard.js +0 -1
  13. package/dist/directive-preserve.d.ts +0 -1
  14. package/dist/directive-preserve.js +0 -1
  15. package/dist/directives.d.ts +0 -1
  16. package/dist/directives.js +0 -1
  17. package/dist/escape.d.ts +0 -1
  18. package/dist/escape.js +0 -1
  19. package/dist/frontmatter.d.ts +0 -1
  20. package/dist/frontmatter.js +0 -1
  21. package/dist/headings.d.ts +0 -7
  22. package/dist/headings.js +43 -3
  23. package/dist/index.d.ts +1 -1
  24. package/dist/index.js +1 -1
  25. package/dist/inline.d.ts +0 -1
  26. package/dist/inline.js +0 -1
  27. package/dist/minja-mask.d.ts +0 -1
  28. package/dist/minja-mask.js +0 -1
  29. package/dist/nav-file.d.ts +0 -1
  30. package/dist/nav-file.js +0 -1
  31. package/dist/nav.d.ts +0 -1
  32. package/dist/nav.js +0 -1
  33. package/dist/parse-attrs.d.ts +0 -1
  34. package/dist/parse-attrs.js +0 -1
  35. package/dist/parse.d.ts +0 -1
  36. package/dist/parse.js +15 -16
  37. package/dist/plugin-block-leaf.d.ts +0 -1
  38. package/dist/plugin-block-leaf.js +0 -1
  39. package/dist/plugin-containers.d.ts +1 -2
  40. package/dist/plugin-containers.js +3 -1
  41. package/dist/plugin-inline-directives.d.ts +0 -1
  42. package/dist/plugin-inline-directives.js +0 -1
  43. package/dist/plugin-mark.d.ts +0 -1
  44. package/dist/plugin-mark.js +0 -1
  45. package/dist/plugin-math.d.ts +0 -1
  46. package/dist/plugin-math.js +0 -1
  47. package/dist/renderers/diagrams.d.ts +0 -1
  48. package/dist/renderers/diagrams.js +0 -1
  49. package/dist/renderers/mermaid.d.ts +0 -1
  50. package/dist/renderers/mermaid.js +0 -1
  51. package/dist/serialize.d.ts +0 -1
  52. package/dist/serialize.js +47 -8
  53. package/dist/template-pages.d.ts +0 -1
  54. package/dist/template-pages.js +0 -1
  55. package/dist/types.d.ts +0 -1
  56. package/dist/types.js +0 -1
  57. package/dist/yaml.d.ts +0 -1
  58. package/dist/yaml.js +0 -1
  59. package/package.json +4 -4
  60. package/dist/attributes.d.ts.map +0 -1
  61. package/dist/attributes.js.map +0 -1
  62. package/dist/browser.d.ts.map +0 -1
  63. package/dist/browser.js.map +0 -1
  64. package/dist/cli.d.ts.map +0 -1
  65. package/dist/cli.js.map +0 -1
  66. package/dist/code-regions.d.ts.map +0 -1
  67. package/dist/code-regions.js.map +0 -1
  68. package/dist/directive-guard.d.ts.map +0 -1
  69. package/dist/directive-guard.js.map +0 -1
  70. package/dist/directive-preserve.d.ts.map +0 -1
  71. package/dist/directive-preserve.js.map +0 -1
  72. package/dist/directives.d.ts.map +0 -1
  73. package/dist/directives.js.map +0 -1
  74. package/dist/escape.d.ts.map +0 -1
  75. package/dist/escape.js.map +0 -1
  76. package/dist/frontmatter.d.ts.map +0 -1
  77. package/dist/frontmatter.js.map +0 -1
  78. package/dist/headings.d.ts.map +0 -1
  79. package/dist/headings.js.map +0 -1
  80. package/dist/index.d.ts.map +0 -1
  81. package/dist/index.js.map +0 -1
  82. package/dist/inline.d.ts.map +0 -1
  83. package/dist/inline.js.map +0 -1
  84. package/dist/minja-mask.d.ts.map +0 -1
  85. package/dist/minja-mask.js.map +0 -1
  86. package/dist/nav-file.d.ts.map +0 -1
  87. package/dist/nav-file.js.map +0 -1
  88. package/dist/nav.d.ts.map +0 -1
  89. package/dist/nav.js.map +0 -1
  90. package/dist/parse-attrs.d.ts.map +0 -1
  91. package/dist/parse-attrs.js.map +0 -1
  92. package/dist/parse.d.ts.map +0 -1
  93. package/dist/parse.js.map +0 -1
  94. package/dist/plugin-block-leaf.d.ts.map +0 -1
  95. package/dist/plugin-block-leaf.js.map +0 -1
  96. package/dist/plugin-containers.d.ts.map +0 -1
  97. package/dist/plugin-containers.js.map +0 -1
  98. package/dist/plugin-inline-directives.d.ts.map +0 -1
  99. package/dist/plugin-inline-directives.js.map +0 -1
  100. package/dist/plugin-mark.d.ts.map +0 -1
  101. package/dist/plugin-mark.js.map +0 -1
  102. package/dist/plugin-math.d.ts.map +0 -1
  103. package/dist/plugin-math.js.map +0 -1
  104. package/dist/renderers/diagrams.d.ts.map +0 -1
  105. package/dist/renderers/diagrams.js.map +0 -1
  106. package/dist/renderers/mermaid.d.ts.map +0 -1
  107. package/dist/renderers/mermaid.js.map +0 -1
  108. package/dist/serialize.d.ts.map +0 -1
  109. package/dist/serialize.js.map +0 -1
  110. package/dist/template-pages.d.ts.map +0 -1
  111. package/dist/template-pages.js.map +0 -1
  112. package/dist/types.d.ts.map +0 -1
  113. package/dist/types.js.map +0 -1
  114. package/dist/yaml.d.ts.map +0 -1
  115. package/dist/yaml.js.map +0 -1
@@ -45,4 +45,3 @@ export declare function escapeAttrValue(value: string): string;
45
45
  * This is the common glue between TreeNode.props and attribute output.
46
46
  */
47
47
  export declare function splitProps(props: Record<string, unknown> | undefined, excludeKeys?: string[]): RenderedAttrs;
48
- //# sourceMappingURL=attributes.d.ts.map
@@ -92,4 +92,3 @@ export function splitProps(props, excludeKeys = []) {
92
92
  }
93
93
  return result;
94
94
  }
95
- //# sourceMappingURL=attributes.js.map
package/dist/browser.d.ts CHANGED
@@ -20,4 +20,3 @@ export { maskMinjaInCode, unmaskMinjaInCode, maskAllMinjaOpeners, isMinjaProcess
20
20
  export { extractHeadings, slugifyHeadingText, type HeadingInfo } from "./headings.js";
21
21
  export { splitFrontmatter, type Frontmatter } from "./frontmatter.js";
22
22
  export { TemplatePages, TemplatePageError, declaresParams, ATTRIBUTE_BLOCK_OPEN, type TemplatePagesOptions } from "./template-pages.js";
23
- //# sourceMappingURL=browser.d.ts.map
package/dist/browser.js CHANGED
@@ -19,4 +19,3 @@ export { maskMinjaInCode, unmaskMinjaInCode, maskAllMinjaOpeners, isMinjaProcess
19
19
  export { extractHeadings, slugifyHeadingText } from "./headings.js";
20
20
  export { splitFrontmatter } from "./frontmatter.js";
21
21
  export { TemplatePages, TemplatePageError, declaresParams, ATTRIBUTE_BLOCK_OPEN } from "./template-pages.js";
22
- //# sourceMappingURL=browser.js.map
@@ -0,0 +1,25 @@
1
+ /**
2
+ * What the Dogsbay MD exporter can and cannot represent — a CONTRACT (the
3
+ * format-docusaurus pattern): one cell per `MATRIX_ROWS` type of the
4
+ * component × format matrix, checked by `validateCapabilities` and by
5
+ * tests/capabilities.test.ts.
6
+ *
7
+ * Dogsbay MD is the CANONICAL source format, so the bar for `full` is a
8
+ * round trip: `treeToDogsbayMd` → `dogsbayMdToTree` gives back the same tree
9
+ * (modulo canonical spelling — `:::tab[One]` comes back as the deflist tab
10
+ * form, a trailing newline on raw HTML). Each `full` below was measured that
11
+ * way, not assumed.
12
+ *
13
+ * Support levels: full — round-trips · partial — survives with reduced
14
+ * fidelity (the note says how) · none — dropped or flattened (the note says
15
+ * what is lost).
16
+ *
17
+ * Types with no `case` in `renderNode` fall to `renderUnknown`: with the
18
+ * default `unknownNodes: "html"` it writes `node.html` if present, else the
19
+ * children (the wrapper and its props are lost), else
20
+ * `<!-- unsupported: <type> -->`. Nothing is recorded — there is no export
21
+ * ledger in this package yet — so every partial/none here is a loss the
22
+ * exporter does not report.
23
+ */
24
+ import type { CapabilityDeclaration } from "@dogsbay/serialize-core";
25
+ export declare const DOGSBAY_MD_CAPABILITIES: CapabilityDeclaration[];
@@ -0,0 +1,91 @@
1
+ export const DOGSBAY_MD_CAPABILITIES = [
2
+ // ── Blocks ───────────────────────────────────────────────
3
+ { feature: "heading", support: "full", rendersAs: "`#`–`######` with `{#id .class}` attrs" },
4
+ { feature: "paragraph", support: "full" },
5
+ { feature: "blockquote", support: "full", rendersAs: "`> …`" },
6
+ { feature: "unordered-list", support: "full", rendersAs: "`- item`" },
7
+ { feature: "ordered-list", support: "full", rendersAs: "`1. item`" },
8
+ { feature: "hr", support: "full", rendersAs: "`---`" },
9
+ {
10
+ feature: "table",
11
+ support: "partial",
12
+ rendersAs: "GFM pipe table + `{caption=\"…\"}`; an HTML `<table>` when a cell holds blocks, a row has `th` cells, or the table is headerless",
13
+ note: "A simple table round-trips. The HTML fallback re-parses as a raw `html` node, not a `table`; inside it blocks other than paragraph/list/code/callout/table collapse to their content and kbd/icon/math/footnote-ref degrade to text.",
14
+ },
15
+ { feature: "code", support: "full", rendersAs: "fenced block with language, `title=\"…\"` and line-highlight meta" },
16
+ { feature: "math-block", support: "full", rendersAs: "`$$ … $$`" },
17
+ { feature: "deflist", support: "full", rendersAs: "`Term` / `: definition`" },
18
+ { feature: "figure", support: "full", rendersAs: "`:::figure{caption=\"…\"}`; a captionless figure is written as its content" },
19
+ { feature: "footnote-list", support: "full", rendersAs: "`[^label]: …` definitions" },
20
+ { feature: "html", support: "full", rendersAs: "the raw HTML, verbatim" },
21
+ {
22
+ feature: "html-container",
23
+ support: "partial",
24
+ rendersAs: "`node.html` verbatim, or the container's children as blocks",
25
+ note: "Content is kept; a children-only container (the shape the mkdocs md_in_html, asciidoc and mdx importers produce) loses its wrapper tag and attributes.",
26
+ },
27
+ {
28
+ feature: "diagram",
29
+ support: "partial",
30
+ rendersAs: "a ```mermaid fence with the diagram source",
31
+ note: "The source round-trips (it re-parses as a code fence, which the build turns back into a diagram); a pre-rendered SVG is not kept.",
32
+ },
33
+ { feature: "youtube", support: "full", rendersAs: "`:::youtube{#id title=\"…\"}`" },
34
+ // ── Components ───────────────────────────────────────────
35
+ { feature: "callout", support: "full", rendersAs: "GitHub alert `> [!NOTE]`; `:::type[Title]{…}` for a custom title or a non-GitHub type" },
36
+ { feature: "details", support: "full", rendersAs: "`:::details{title=\"…\"}`" },
37
+ { feature: "details-sheet", support: "full", rendersAs: "`:::details{title=\"…\" sheet}`" },
38
+ { feature: "theme", support: "full", rendersAs: "`:::theme{name=\"dark\"}` around the content" },
39
+ { feature: "tabs-variant", support: "full", rendersAs: "`:::tabs{variant=\"pills\"}`" },
40
+ { feature: "tone", support: "full", rendersAs: "`tone=\"…\"` on `:::cards` or `:::card`" },
41
+ { feature: "tabs", support: "full", rendersAs: "`:::tabs` with the deflist tab form (`Label` / `: body`)" },
42
+ { feature: "steps", support: "full", rendersAs: "`:::steps` around an ordered list" },
43
+ { feature: "accordion", support: "full", rendersAs: "`:::accordion` with deflist items" },
44
+ { feature: "cards", support: "full", rendersAs: "`:::cards` — compact YAML list when every card body is paragraphs, `:::card` directives otherwise" },
45
+ { feature: "card", support: "full", rendersAs: "`:::card{title href …}`" },
46
+ { feature: "link-card", support: "full", rendersAs: "`:::link-card{title href}` with the description as body" },
47
+ { feature: "files", support: "full", rendersAs: "`:::files` around the nested list" },
48
+ { feature: "grid", support: "full", rendersAs: "`::::grid` / `:::grid-item`" },
49
+ { feature: "link-button", support: "full", rendersAs: "`:::button{href}`" },
50
+ { feature: "related", support: "full", rendersAs: "bold caption + `{._additional-resources}` + the link list (the shape the parser folds back)" },
51
+ {
52
+ feature: "example",
53
+ support: "partial",
54
+ rendersAs: "its children, unwrapped",
55
+ note: "No case: `renderUnknown` writes the children only. The `:::example` wrapper (live preview + shown source) is lost and the content re-parses as ordinary blocks; unrecorded.",
56
+ },
57
+ {
58
+ feature: "container",
59
+ support: "partial",
60
+ rendersAs: "`:::name` for this format's own generic containers; the children otherwise",
61
+ note: "A container parsed from Dogsbay MD (`meta.container` + `meta.name`) round-trips. A `container` from another importer has no name to write: its wrapper and props (class, id) are dropped and only the children survive; unrecorded.",
62
+ },
63
+ {
64
+ feature: "annotation-list",
65
+ support: "partial",
66
+ rendersAs: "each item's content as a separate paragraph",
67
+ note: "No case: `renderUnknown` writes the children, and the list items render without list markers — numbering and the link to the code block's `(n)` markers are lost; unrecorded.",
68
+ },
69
+ // ── API reference ────────────────────────────────────────
70
+ {
71
+ feature: "endpoint",
72
+ support: "partial",
73
+ rendersAs: "`## METHOD /path` + summary/description + Parameters table + request-body/response lists + code-sample fences",
74
+ note: "Readable Markdown, but not a structure: it re-parses as headings/tables/lists, never an `endpoint`. Schemas beyond name/type/required/description, and spec raw HTML (escaped as `&lt;`), are not carried.",
75
+ },
76
+ { feature: "api-doc", support: "full", rendersAs: "`:::api-doc{…}`" },
77
+ { feature: "api-class", support: "full", rendersAs: "`:::api-class{…}`" },
78
+ { feature: "api-member", support: "full", rendersAs: "`:::api-member{…}`" },
79
+ { feature: "api-params", support: "full", rendersAs: "`:::api-params` with a YAML `params:` body" },
80
+ { feature: "api-source", support: "full", rendersAs: "`:::api-source{…}`" },
81
+ // ── Inline ───────────────────────────────────────────────
82
+ { feature: "link", support: "full", rendersAs: "`[text](href \"title\")`" },
83
+ { feature: "image", support: "full", rendersAs: "`![alt](src \"title\"){attrs}`" },
84
+ { feature: "kbd", support: "full", rendersAs: "`:kbd[Ctrl+S]`" },
85
+ { feature: "math", support: "full", rendersAs: "`$…$`" },
86
+ { feature: "highlight", support: "full", rendersAs: "`==…==`" },
87
+ { feature: "badge", support: "full", rendersAs: "`:badge[Text]{variant=…}`" },
88
+ { feature: "icon", support: "full", rendersAs: "`:icon[name]`" },
89
+ { feature: "footnote-ref", support: "full", rendersAs: "`[^label]`" },
90
+ { feature: "html-inline", support: "full", rendersAs: "the raw HTML, verbatim" },
91
+ ];
package/dist/cli.d.ts CHANGED
@@ -18,4 +18,3 @@ import type { FormatPlugin } from "@dogsbay/types";
18
18
  */
19
19
  export declare function carriedFrontmatter(fm: Record<string, unknown> | undefined): Record<string, unknown>;
20
20
  export declare const plugin: FormatPlugin;
21
- //# sourceMappingURL=cli.d.ts.map
package/dist/cli.js CHANGED
@@ -12,6 +12,7 @@ import { dogsbayMdToTree } from "./parse.js";
12
12
  import { treeToDogsbayMd } from "./serialize.js";
13
13
  import { buildNavFromDirectory } from "./nav.js";
14
14
  import { renderDiagrams } from "./renderers/diagrams.js";
15
+ import { DOGSBAY_MD_CAPABILITIES } from "./capabilities.js";
15
16
  /**
16
17
  * Detect whether a directory contains a Dogsbay MD source tree.
17
18
  *
@@ -350,6 +351,7 @@ export const plugin = {
350
351
  name: "dogsbay-md",
351
352
  canImport: true,
352
353
  canExport: true,
354
+ capabilities: DOGSBAY_MD_CAPABILITIES,
353
355
  detectSource: detectDogsbayMdSource,
354
356
  importOptions: [
355
357
  {
@@ -364,4 +366,3 @@ export const plugin = {
364
366
  return exportDogsbayMd(pages, nav, output, opts);
365
367
  },
366
368
  };
367
- //# sourceMappingURL=cli.js.map
@@ -86,4 +86,3 @@ export declare function transformProseSegments(source: string, transform: (prose
86
86
  */
87
87
  export declare function fenceOpenBefore(source: string): boolean[];
88
88
  export {};
89
- //# sourceMappingURL=code-regions.d.ts.map
@@ -212,4 +212,3 @@ export function fenceOpenBefore(source) {
212
212
  states.push(state.open);
213
213
  return states;
214
214
  }
215
- //# sourceMappingURL=code-regions.js.map
@@ -8,4 +8,3 @@
8
8
  * validation, which is the first line.
9
9
  */
10
10
  export declare function assertDirectiveField(what: string, value: string): string;
11
- //# sourceMappingURL=directive-guard.d.ts.map
@@ -13,4 +13,3 @@ export function assertDirectiveField(what, value) {
13
13
  throw new Error(`cannot serialize ${what} containing "${marker}": ${JSON.stringify(value)}`);
14
14
  return value;
15
15
  }
16
- //# sourceMappingURL=directive-guard.js.map
@@ -63,4 +63,3 @@ export interface RestoreOptions {
63
63
  nodesFor?: "all" | "include";
64
64
  }
65
65
  export declare function restoreDirectives(tree: TreeNode[], table: DirectiveSpan[], options?: RestoreOptions): TreeNode[];
66
- //# sourceMappingURL=directive-preserve.d.ts.map
@@ -407,4 +407,3 @@ export function restoreDirectives(tree, table, options = {}) {
407
407
  sweep(node, table);
408
408
  return folded;
409
409
  }
410
- //# sourceMappingURL=directive-preserve.js.map
@@ -16,4 +16,3 @@ export interface DirectiveRenderInput {
16
16
  * the component, option threshold, and prop complexity.
17
17
  */
18
18
  export declare function renderBlockDirective(input: DirectiveRenderInput, ctx: ResolvedOptions): string;
19
- //# sourceMappingURL=directives.d.ts.map
@@ -95,4 +95,3 @@ function attrsToYaml(attrs) {
95
95
  }
96
96
  return result;
97
97
  }
98
- //# sourceMappingURL=directives.js.map
package/dist/escape.d.ts CHANGED
@@ -58,4 +58,3 @@ export declare const indent: typeof coreIndent;
58
58
  * the last byte of every emitted file.
59
59
  */
60
60
  export declare function normalizeTrailingWhitespace(content: string): string;
61
- //# sourceMappingURL=escape.d.ts.map
package/dist/escape.js CHANGED
@@ -147,4 +147,3 @@ export function normalizeTrailingWhitespace(content) {
147
147
  }
148
148
  return out.join("\n").replace(/\s*$/, "\n");
149
149
  }
150
- //# sourceMappingURL=escape.js.map
@@ -9,4 +9,3 @@ export interface Frontmatter {
9
9
  * body is malformed — callers that want a fallback should catch.
10
10
  */
11
11
  export declare function splitFrontmatter(source: string): Frontmatter;
12
- //# sourceMappingURL=frontmatter.d.ts.map
@@ -64,4 +64,3 @@ export function splitFrontmatter(source) {
64
64
  content,
65
65
  };
66
66
  }
67
- //# sourceMappingURL=frontmatter.js.map
@@ -40,11 +40,4 @@ export interface HeadingInfo {
40
40
  }
41
41
  import { slugifyHeadingText } from "@dogsbay/serialize-core";
42
42
  export { slugifyHeadingText };
43
- /**
44
- * Extract top-level heading metadata AND backfill `props.slug` on
45
- * headings that lack an explicit one — exactly the site build's
46
- * anchor-id assignment. Mutates the tree (by design: serialization and
47
- * rendering read the backfilled slug).
48
- */
49
43
  export declare function extractHeadings(tree: TreeNode[]): HeadingInfo[];
50
- //# sourceMappingURL=headings.d.ts.map
package/dist/headings.js CHANGED
@@ -19,7 +19,7 @@ function collectInlineText(nodes) {
19
19
  }
20
20
  // ONE slug rule for the platform: the site build, the TOC and every
21
21
  // exporter's heading links read the same function (serialize-core).
22
- import { slugifyHeadingText } from "@dogsbay/serialize-core";
22
+ import { isDetailsSheet, slugifyHeadingText } from "@dogsbay/serialize-core";
23
23
  export { slugifyHeadingText };
24
24
  /**
25
25
  * Extract top-level heading metadata AND backfill `props.slug` on
@@ -27,9 +27,19 @@ export { slugifyHeadingText };
27
27
  * anchor-id assignment. Mutates the tree (by design: serialization and
28
28
  * rendering read the backfilled slug).
29
29
  */
30
+ /**
31
+ * The page's own level: top-level nodes, and the content of transparent
32
+ * wrappers. A `:::theme` band only changes colours, so a heading inside it is
33
+ * still a page heading (DITA `<section outputclass="db-theme-dark">` wraps
34
+ * its section title); walking only the top level left it with no id and no
35
+ * table-of-contents entry.
36
+ */
37
+ function pageLevel(tree) {
38
+ return tree.flatMap((n) => (n.type === "theme" ? pageLevel(n.children ?? []) : [n]));
39
+ }
30
40
  export function extractHeadings(tree) {
31
41
  const slots = [];
32
- for (const node of tree) {
42
+ for (const node of pageLevel(tree)) {
33
43
  if (node.type !== "heading" || !node.inline)
34
44
  continue;
35
45
  const text = node.inline
@@ -97,6 +107,37 @@ export function extractHeadings(tree) {
97
107
  slot.slug = slug;
98
108
  taken.add(slug);
99
109
  }
110
+ // PASS 3 — a side sheet with no id gets one from its title, so a link
111
+ // written as for a heading (`[options](#advanced-options)`) opens it (#101).
112
+ // Sheets come last and yield: they cannot move a heading's anchor.
113
+ const ids = new Set();
114
+ const walk = (nodes) => {
115
+ for (const n of nodes ?? []) {
116
+ const id = n.props?.id;
117
+ if (typeof id === "string" && id)
118
+ ids.add(id);
119
+ walk(n.children);
120
+ }
121
+ };
122
+ walk(tree);
123
+ const sheets = (nodes) => {
124
+ for (const n of nodes ?? []) {
125
+ if (n.type === "details" && isDetailsSheet(n.props) && !n.props?.id) {
126
+ const title = String(n.props?.title ?? n.props?.summary ?? "");
127
+ const base = slugifyHeadingText(title);
128
+ if (base) {
129
+ let slug = base;
130
+ for (let k = 1; taken.has(slug) || ids.has(slug); k++)
131
+ slug = `${base}-${k}`;
132
+ taken.add(slug);
133
+ ids.add(slug);
134
+ n.props = { ...n.props, id: slug };
135
+ }
136
+ }
137
+ sheets(n.children);
138
+ }
139
+ };
140
+ sheets(tree);
100
141
  const headings = [];
101
142
  for (const slot of slots) {
102
143
  const slug = slot.slug ?? "";
@@ -113,4 +154,3 @@ export function extractHeadings(tree) {
113
154
  }
114
155
  return headings;
115
156
  }
116
- //# sourceMappingURL=headings.js.map
package/dist/index.d.ts CHANGED
@@ -1,5 +1,6 @@
1
1
  export { treeToDogsbayMd, nodeToDogsbayMd } from "./serialize.js";
2
2
  export type { SerializeOptions } from "./types.js";
3
+ export { DOGSBAY_MD_CAPABILITIES } from "./capabilities.js";
3
4
  export { inlineToDogsbayMd } from "./inline.js";
4
5
  export { dogsbayMdToTree, parseInline } from "./parse.js";
5
6
  export { extractHeadings, slugifyHeadingText, type HeadingInfo } from "./headings.js";
@@ -14,4 +15,3 @@ export { renderDiagrams } from "./renderers/diagrams.js";
14
15
  export type { RenderDiagramsOptions } from "./renderers/diagrams.js";
15
16
  export { renderMermaidSvg, setMmdcOverride, findMmdc } from "./renderers/mermaid.js";
16
17
  export { TemplatePages, TemplatePageError, declaresParams, ATTRIBUTE_BLOCK_OPEN, type TemplatePagesOptions } from "./template-pages.js";
17
- //# sourceMappingURL=index.d.ts.map
package/dist/index.js CHANGED
@@ -3,6 +3,7 @@
3
3
  // Spec: dogsbay-research/content/formats/dogsbay-markdown-spec.md
4
4
  // Plan: plans/format-dogsbay-md.md
5
5
  export { treeToDogsbayMd, nodeToDogsbayMd } from "./serialize.js";
6
+ export { DOGSBAY_MD_CAPABILITIES } from "./capabilities.js";
6
7
  export { inlineToDogsbayMd } from "./inline.js";
7
8
  export { dogsbayMdToTree, parseInline } from "./parse.js";
8
9
  export { extractHeadings, slugifyHeadingText } from "./headings.js";
@@ -13,4 +14,3 @@ export { loadNavFile } from "./nav-file.js";
13
14
  export { renderDiagrams } from "./renderers/diagrams.js";
14
15
  export { renderMermaidSvg, setMmdcOverride, findMmdc } from "./renderers/mermaid.js";
15
16
  export { TemplatePages, TemplatePageError, declaresParams, ATTRIBUTE_BLOCK_OPEN } from "./template-pages.js";
16
- //# sourceMappingURL=index.js.map
package/dist/inline.d.ts CHANGED
@@ -3,4 +3,3 @@
3
3
  */
4
4
  import type { InlineNode } from "@dogsbay/types";
5
5
  export declare function inlineToDogsbayMd(nodes: InlineNode[] | undefined): string;
6
- //# sourceMappingURL=inline.d.ts.map
package/dist/inline.js CHANGED
@@ -352,4 +352,3 @@ function escapeLinkDest(dest) {
352
352
  }
353
353
  return dest;
354
354
  }
355
- //# sourceMappingURL=inline.js.map
@@ -61,4 +61,3 @@ export declare function stripInlineMinjaMarkers(text: string): string;
61
61
  * touched (shared grammar).
62
62
  */
63
63
  export declare function stripFenceMinjaMarkers(text: string): string;
64
- //# sourceMappingURL=minja-mask.d.ts.map
@@ -125,4 +125,3 @@ export function stripFenceMinjaMarkers(text) {
125
125
  return removed ? out.replace(/\s+$/, "") : info;
126
126
  });
127
127
  }
128
- //# sourceMappingURL=minja-mask.js.map
@@ -58,4 +58,3 @@ export interface LoadNavFileOptions {
58
58
  * to compute slugs.
59
59
  */
60
60
  export declare function loadNavFile(path: string, contentDir: string, options?: LoadNavFileOptions): NavItem[];
61
- //# sourceMappingURL=nav-file.d.ts.map
package/dist/nav-file.js CHANGED
@@ -331,4 +331,3 @@ function fileToHref(file, hrefPrefix) {
331
331
  const prefix = hrefPrefix.endsWith("/") ? hrefPrefix.slice(0, -1) : hrefPrefix;
332
332
  return slug ? `${prefix}/${slug}` : prefix;
333
333
  }
334
- //# sourceMappingURL=nav-file.js.map
package/dist/nav.d.ts CHANGED
@@ -38,4 +38,3 @@ export interface BuildNavOptions {
38
38
  * Sorting falls back to filename alphabetical when order is not set.
39
39
  */
40
40
  export declare function buildNavFromDirectory(contentDir: string, options?: BuildNavOptions): NavItem[];
41
- //# sourceMappingURL=nav.d.ts.map
package/dist/nav.js CHANGED
@@ -185,4 +185,3 @@ function prettifyName(slug) {
185
185
  .join(" ");
186
186
  }
187
187
  void statSync; // reserved for future use (e.g. mtime-based caching)
188
- //# sourceMappingURL=nav.js.map
@@ -21,4 +21,3 @@ export declare function parseAttrs(inner: string): ParsedAttrs;
21
21
  * `id` and `classes` become `id` and `class`; other props flow through.
22
22
  */
23
23
  export declare function attrsToProps(attrs: ParsedAttrs): Record<string, unknown>;
24
- //# sourceMappingURL=parse-attrs.d.ts.map
@@ -114,4 +114,3 @@ export function attrsToProps(attrs) {
114
114
  }
115
115
  return props;
116
116
  }
117
- //# sourceMappingURL=parse-attrs.js.map
package/dist/parse.d.ts CHANGED
@@ -26,4 +26,3 @@ export declare function dogsbayMdToTree(source: string, options?: ParseOptions):
26
26
  * Parse a single inline string to InlineNode[] (useful for testing).
27
27
  */
28
28
  export declare function parseInline(source: string): InlineNode[];
29
- //# sourceMappingURL=parse.d.ts.map
package/dist/parse.js CHANGED
@@ -1130,11 +1130,9 @@ function accordionFromChildren(props, children) {
1130
1130
  }
1131
1131
  return { type: "accordion", props, children: items };
1132
1132
  }
1133
- // Directive form: explicit `:::accordion-item` children
1134
- const itemKids = children.filter((c) => c.type === "accordion-item");
1135
- if (itemKids.length > 0) {
1136
- return { type: "accordion", props, children: itemKids };
1137
- }
1133
+ // Directive form: explicit `:::accordion-item` children. Other blocks (an
1134
+ // intro paragraph) stay too: every renderer places them around the group
1135
+ // (serialize-core `renderAroundGroup`); filtering them here deleted them.
1138
1136
  return { type: "accordion", props, children };
1139
1137
  }
1140
1138
  /**
@@ -1180,9 +1178,14 @@ function linkCardFromChildren(props, children) {
1180
1178
  return { type: "link-card", props, children };
1181
1179
  }
1182
1180
  function tabsFromChildren(props, children) {
1183
- // Preferred: children is a single deflist
1184
- if (children.length === 1 && children[0].type === "deflist") {
1185
- const dl = children[0];
1181
+ // Preferred: the definition-list form. An intro or outro paragraph around
1182
+ // the ONE deflist stays where it is (renderAroundGroup places it), as in the
1183
+ // directive form; requiring the deflist to be the only child turned the
1184
+ // whole group into a plain list with no warning (#102). Two deflists and no
1185
+ // :::tab: which one is the tabs is a guess, so neither is converted.
1186
+ const deflists = children.filter((c) => c.type === "deflist");
1187
+ if (deflists.length === 1 && !children.some((c) => c.type === "tab")) {
1188
+ const dl = deflists[0];
1186
1189
  const tabs = [];
1187
1190
  const list = dl.children ?? [];
1188
1191
  for (let i = 0; i < list.length; i++) {
@@ -1200,14 +1203,11 @@ function tabsFromChildren(props, children) {
1200
1203
  }
1201
1204
  }
1202
1205
  }
1203
- return { type: "tabs", props, children: tabs };
1204
- }
1205
- // Directive form: children are explicit :::tab containers
1206
- const tabs = children.filter((c) => c.type === "tab");
1207
- if (tabs.length > 0) {
1208
- return { type: "tabs", props, children: tabs };
1206
+ return { type: "tabs", props, children: children.flatMap((c) => (c === dl ? tabs : [c])) };
1209
1207
  }
1210
- // Fallback — unknown shape
1208
+ // Directive form: explicit :::tab containers. Other blocks (an intro, text
1209
+ // between tabs) stay: every renderer places them around the group
1210
+ // (serialize-core `renderAroundGroup`); filtering them here deleted them.
1211
1211
  return { type: "tabs", props, children };
1212
1212
  }
1213
1213
  function stepsFromChildren(props, children) {
@@ -1726,4 +1726,3 @@ function inlineDirectiveToNode(name, labelText, labelInline, attrs) {
1726
1726
  }
1727
1727
  }
1728
1728
  }
1729
- //# sourceMappingURL=parse.js.map
@@ -16,4 +16,3 @@
16
16
  */
17
17
  import type MarkdownIt from "markdown-it";
18
18
  export declare function blockLeafDirectivePlugin(md: MarkdownIt): void;
19
- //# sourceMappingURL=plugin-block-leaf.d.ts.map
@@ -78,4 +78,3 @@ function blockLeafRule(state, startLine, endLine, silent) {
78
78
  state.line = startLine + 1;
79
79
  return true;
80
80
  }
81
- //# sourceMappingURL=plugin-block-leaf.js.map
@@ -6,11 +6,10 @@
6
6
  * nest. Same-name nesting requires more colons (::::).
7
7
  */
8
8
  import type MarkdownIt from "markdown-it";
9
- export declare const KNOWN_BLOCK_DIRECTIVES: readonly ["tabs", "tab", "steps", "step", "cards", "card", "grid", "grid-item", "details", "callout", "note", "tip", "info", "important", "warning", "caution", "danger", "success", "hint", "attention", "error", "failure", "bug", "question", "abstract", "quote", "button", "figure", "math", "api-endpoint", "api-params", "api-response", "config", "files", "example", "accordion", "accordion-item", "link-card", "autodoc", "api-class", "api-member", "api-doc", "api-source", "youtube", "openapi"];
9
+ export declare const KNOWN_BLOCK_DIRECTIVES: readonly ["tabs", "tab", "steps", "step", "cards", "card", "grid", "grid-item", "details", "callout", "note", "tip", "info", "important", "warning", "caution", "danger", "success", "hint", "attention", "error", "failure", "bug", "question", "abstract", "quote", "button", "figure", "math", "api-endpoint", "api-params", "api-response", "config", "files", "example", "accordion", "accordion-item", "link-card", "autodoc", "api-class", "api-member", "api-doc", "api-source", "youtube", "openapi", "theme"];
10
10
  /**
11
11
  * The token name for a `:::name` block with a name no renderer knows. It becomes a node of that
12
12
  * type (parse.ts), which renderers show as a plain container and report, rather than literal text.
13
13
  */
14
14
  export declare const GENERIC_CONTAINER = "dogsbay_generic";
15
15
  export declare function containersPlugin(md: MarkdownIt): void;
16
- //# sourceMappingURL=plugin-containers.d.ts.map
@@ -61,6 +61,9 @@ export const KNOWN_BLOCK_DIRECTIVES = [
61
61
  // expanded into endpoint cards from the spec at build time (the
62
62
  // Swagger UI / Redoc embed). See packages/cli/src/resolve-openapi.ts.
63
63
  "openapi",
64
+ // A scoped theme, `:::theme{name="dark"}`: its content in another token
65
+ // set (plans/dita-variants-themes.md). A wrapper, so it takes blocks.
66
+ "theme",
64
67
  ];
65
68
  /**
66
69
  * The token name for a `:::name` block with a name no renderer knows. It becomes a node of that
@@ -108,4 +111,3 @@ export function containersPlugin(md) {
108
111
  render: () => "",
109
112
  });
110
113
  }
111
- //# sourceMappingURL=plugin-containers.js.map
@@ -15,4 +15,3 @@
15
15
  */
16
16
  import type MarkdownIt from "markdown-it";
17
17
  export declare function inlineDirectivesPlugin(md: MarkdownIt): void;
18
- //# sourceMappingURL=plugin-inline-directives.d.ts.map
@@ -118,4 +118,3 @@ function inlineDirectiveRule(state, silent) {
118
118
  state.pos = pos;
119
119
  return true;
120
120
  }
121
- //# sourceMappingURL=plugin-inline-directives.js.map
@@ -10,4 +10,3 @@
10
10
  */
11
11
  import type MarkdownIt from "markdown-it";
12
12
  export declare function markPlugin(md: MarkdownIt): void;
13
- //# sourceMappingURL=plugin-mark.d.ts.map
@@ -72,4 +72,3 @@ export function markPlugin(md) {
72
72
  return false;
73
73
  });
74
74
  }
75
- //# sourceMappingURL=plugin-mark.js.map
@@ -20,4 +20,3 @@
20
20
  */
21
21
  import type MarkdownIt from "markdown-it";
22
22
  export declare function mathPlugin(md: MarkdownIt): void;
23
- //# sourceMappingURL=plugin-math.d.ts.map
@@ -88,4 +88,3 @@ export function mathPlugin(md) {
88
88
  });
89
89
  md.inline.ruler.before("escape", "math_inline", mathInline);
90
90
  }
91
- //# sourceMappingURL=plugin-math.js.map
@@ -22,4 +22,3 @@ export interface RenderDiagramsOptions {
22
22
  * the build log when many fences are present.
23
23
  */
24
24
  export declare function renderDiagrams(tree: TreeNode[], options?: RenderDiagramsOptions): Promise<void>;
25
- //# sourceMappingURL=diagrams.d.ts.map
@@ -68,4 +68,3 @@ export async function renderDiagrams(tree, options) {
68
68
  }
69
69
  await walk(tree);
70
70
  }
71
- //# sourceMappingURL=diagrams.js.map
@@ -21,4 +21,3 @@ export declare function findMmdc(): string | null;
21
21
  * identical diagrams across pages or rebuilds.
22
22
  */
23
23
  export declare function renderMermaidSvg(code: string): Promise<string | null>;
24
- //# sourceMappingURL=mermaid.d.ts.map
@@ -149,4 +149,3 @@ export async function renderMermaidSvg(code) {
149
149
  catch { /* ignore */ }
150
150
  }
151
151
  }
152
- //# sourceMappingURL=mermaid.js.map
@@ -22,4 +22,3 @@ export declare function treeToDogsbayMd(nodes: TreeNode[], options?: SerializeOp
22
22
  * Exposed for chunker to emit one node per file.
23
23
  */
24
24
  export declare function nodeToDogsbayMd(node: TreeNode, options?: SerializeOptions): string;
25
- //# sourceMappingURL=serialize.d.ts.map