@dogsbay/format-dogsbay-md 0.2.0-beta.4 → 0.2.0-beta.41
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/attributes.d.ts +16 -1
- package/dist/attributes.d.ts.map +1 -1
- package/dist/attributes.js +14 -2
- package/dist/attributes.js.map +1 -1
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +44 -3
- package/dist/cli.js.map +1 -1
- package/dist/directives.js +23 -1
- package/dist/directives.js.map +1 -1
- package/dist/index.d.ts +4 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/dist/inline.d.ts +17 -0
- package/dist/inline.d.ts.map +1 -1
- package/dist/inline.js +116 -5
- package/dist/inline.js.map +1 -1
- package/dist/nav-file.d.ts +24 -3
- package/dist/nav-file.d.ts.map +1 -1
- package/dist/nav-file.js +31 -11
- package/dist/nav-file.js.map +1 -1
- package/dist/nav.d.ts +7 -0
- package/dist/nav.d.ts.map +1 -1
- package/dist/nav.js +14 -2
- package/dist/nav.js.map +1 -1
- package/dist/parse.d.ts.map +1 -1
- package/dist/parse.js +328 -4
- package/dist/parse.js.map +1 -1
- package/dist/plugin-containers.d.ts +1 -1
- package/dist/plugin-containers.d.ts.map +1 -1
- package/dist/plugin-containers.js +13 -0
- package/dist/plugin-containers.js.map +1 -1
- package/dist/renderers/diagrams.d.ts +25 -0
- package/dist/renderers/diagrams.d.ts.map +1 -0
- package/dist/renderers/diagrams.js +71 -0
- package/dist/renderers/diagrams.js.map +1 -0
- package/dist/renderers/mermaid.d.ts +24 -0
- package/dist/renderers/mermaid.d.ts.map +1 -0
- package/dist/renderers/mermaid.js +135 -0
- package/dist/renderers/mermaid.js.map +1 -0
- package/dist/serialize.js +80 -6
- package/dist/serialize.js.map +1 -1
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +18 -1
- package/dist/types.js.map +1 -1
- package/package.json +5 -2
package/dist/attributes.d.ts
CHANGED
|
@@ -8,12 +8,27 @@
|
|
|
8
8
|
export interface RenderedAttrs {
|
|
9
9
|
id?: string;
|
|
10
10
|
classes?: string[];
|
|
11
|
-
|
|
11
|
+
/**
|
|
12
|
+
* Props captured from `TreeNode.props`. Primitive values (string,
|
|
13
|
+
* number, boolean) round-trip through inline `{key="value"}` form.
|
|
14
|
+
* Arrays / plain objects are preserved here too — `renderAttrs`
|
|
15
|
+
* skips them (inline form can't represent them) but the
|
|
16
|
+
* directive renderer's `shouldUseYaml` branch picks them up and
|
|
17
|
+
* routes the directive to YAML body form, where complex values
|
|
18
|
+
* survive intact.
|
|
19
|
+
*/
|
|
20
|
+
props?: Record<string, unknown>;
|
|
12
21
|
}
|
|
13
22
|
/**
|
|
14
23
|
* Render an attribute block.
|
|
15
24
|
* Returns `{ #id .a .b key="value" }` or "" if no attrs.
|
|
16
25
|
* Leading space included so callers can append directly to content.
|
|
26
|
+
*
|
|
27
|
+
* Inline form can only carry primitive values. Arrays / objects in
|
|
28
|
+
* `props` are silently skipped here — the caller is expected to have
|
|
29
|
+
* already routed those to YAML body form (see `shouldUseYaml` in
|
|
30
|
+
* directives.ts). If a non-primitive does reach this point, dropping
|
|
31
|
+
* it is the safest fallback (there's no inline syntax for it).
|
|
17
32
|
*/
|
|
18
33
|
export declare function renderAttrs(attrs: RenderedAttrs): string;
|
|
19
34
|
/**
|
package/dist/attributes.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"attributes.d.ts","sourceRoot":"","sources":["../src/attributes.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,MAAM,WAAW,aAAa;IAC5B,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,
|
|
1
|
+
{"version":3,"file":"attributes.d.ts","sourceRoot":"","sources":["../src/attributes.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,MAAM,WAAW,aAAa;IAC5B,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB;;;;;;;;OAQG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACjC;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,aAAa,GAAG,MAAM,CA6BxD;AAED;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAGrD;AAED;;;;;GAKG;AACH,wBAAgB,UAAU,CACxB,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,EAC1C,WAAW,GAAE,MAAM,EAAO,GACzB,aAAa,CAiCf"}
|
package/dist/attributes.js
CHANGED
|
@@ -9,6 +9,12 @@
|
|
|
9
9
|
* Render an attribute block.
|
|
10
10
|
* Returns `{ #id .a .b key="value" }` or "" if no attrs.
|
|
11
11
|
* Leading space included so callers can append directly to content.
|
|
12
|
+
*
|
|
13
|
+
* Inline form can only carry primitive values. Arrays / objects in
|
|
14
|
+
* `props` are silently skipped here — the caller is expected to have
|
|
15
|
+
* already routed those to YAML body form (see `shouldUseYaml` in
|
|
16
|
+
* directives.ts). If a non-primitive does reach this point, dropping
|
|
17
|
+
* it is the safest fallback (there's no inline syntax for it).
|
|
12
18
|
*/
|
|
13
19
|
export function renderAttrs(attrs) {
|
|
14
20
|
const parts = [];
|
|
@@ -29,6 +35,10 @@ export function renderAttrs(attrs) {
|
|
|
29
35
|
parts.push(key);
|
|
30
36
|
continue;
|
|
31
37
|
}
|
|
38
|
+
// Skip arrays / plain objects — inline form can't represent
|
|
39
|
+
// them. They survive via the YAML body branch upstream.
|
|
40
|
+
if (typeof value === "object")
|
|
41
|
+
continue;
|
|
32
42
|
parts.push(`${key}=${escapeAttrValue(String(value))}`);
|
|
33
43
|
}
|
|
34
44
|
}
|
|
@@ -71,8 +81,10 @@ export function splitProps(props, excludeKeys = []) {
|
|
|
71
81
|
}
|
|
72
82
|
if (value === null || value === undefined)
|
|
73
83
|
continue;
|
|
74
|
-
|
|
75
|
-
|
|
84
|
+
// Pass arrays / objects through. Inline-form rendering will skip
|
|
85
|
+
// them (`renderAttrs`); YAML-body rendering preserves them
|
|
86
|
+
// (`attrsToYaml`). The `shouldUseYaml` heuristic in directives.ts
|
|
87
|
+
// detects their presence and routes the directive accordingly.
|
|
76
88
|
cleanProps[key] = value;
|
|
77
89
|
}
|
|
78
90
|
if (Object.keys(cleanProps).length > 0) {
|
package/dist/attributes.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"attributes.js","sourceRoot":"","sources":["../src/attributes.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;
|
|
1
|
+
{"version":3,"file":"attributes.js","sourceRoot":"","sources":["../src/attributes.ts"],"names":[],"mappings":"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"}
|
package/dist/cli.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,YAAY,EAAgC,MAAM,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,YAAY,EAAgC,MAAM,gBAAgB,CAAC;AAoKjF,eAAO,MAAM,MAAM,EAAE,YAcpB,CAAC"}
|
package/dist/cli.js
CHANGED
|
@@ -9,6 +9,7 @@ import { join, relative, basename } from "node:path";
|
|
|
9
9
|
import { parseMeta } from "@dogsbay/types";
|
|
10
10
|
import { dogsbayMdToTree } from "./parse.js";
|
|
11
11
|
import { buildNavFromDirectory } from "./nav.js";
|
|
12
|
+
import { renderDiagrams } from "./renderers/diagrams.js";
|
|
12
13
|
/**
|
|
13
14
|
* Detect whether a directory contains a Dogsbay MD source tree.
|
|
14
15
|
*
|
|
@@ -61,22 +62,51 @@ async function importDogsbayMd(source, opts) {
|
|
|
61
62
|
const taxonomyNames = Array.isArray(opts.taxonomyNames)
|
|
62
63
|
? opts.taxonomyNames
|
|
63
64
|
: undefined;
|
|
65
|
+
// Pre-parse pass — opt-out via `diagrams: false`. When enabled
|
|
66
|
+
// (default), `code` fences with `lang: mermaid` get transformed
|
|
67
|
+
// to `diagram` nodes with pre-rendered SVG. Fail-open: if mmdc
|
|
68
|
+
// (mermaid-cli) isn't installed the code block is left as-is and
|
|
69
|
+
// a one-line warning is printed. See plans/mermaid-dogsbay-md.md.
|
|
70
|
+
const diagramsOn = opts.diagrams !== false;
|
|
64
71
|
for (const { filePath, slug } of files) {
|
|
65
72
|
const content = readFileSync(filePath, "utf-8");
|
|
66
73
|
const { tree, frontmatter } = dogsbayMdToTree(content);
|
|
74
|
+
if (diagramsOn) {
|
|
75
|
+
await renderDiagrams(tree);
|
|
76
|
+
}
|
|
67
77
|
const title = String(frontmatter.title
|
|
68
78
|
?? prettifyName(basename(slug)));
|
|
69
|
-
// Extract heading metadata for TOC
|
|
79
|
+
// Extract heading metadata for TOC AND backfill `node.props.slug`
|
|
80
|
+
// so format-astro's headingToAstro emits a matching `id` on the
|
|
81
|
+
// rendered `<h2>` / `<h3>`. Without this, the TOC's
|
|
82
|
+
// `<a href="#quick-start">` had nothing to scroll to — the
|
|
83
|
+
// heading was emitted without an id because the tree didn't
|
|
84
|
+
// carry the slug. Mirrors format-mkdocs/src/loader.ts:312.
|
|
85
|
+
//
|
|
86
|
+
// Duplicate slugs get `-1`, `-2` suffixes so two `## Foo`
|
|
87
|
+
// headings on the same page produce distinct anchors. Same
|
|
88
|
+
// collision-handling shape as MkDocs.
|
|
70
89
|
const headings = [];
|
|
90
|
+
const seen = new Map();
|
|
71
91
|
for (const node of tree) {
|
|
72
92
|
if (node.type === "heading" && node.inline) {
|
|
73
93
|
const text = node.inline
|
|
74
94
|
.map((n) => (n.type === "text" ? n.text : ""))
|
|
75
95
|
.join("")
|
|
76
96
|
.trim();
|
|
97
|
+
let slug = node.props?.slug;
|
|
98
|
+
if (!slug) {
|
|
99
|
+
const baseSlug = slugify(text);
|
|
100
|
+
const count = seen.get(baseSlug) ?? 0;
|
|
101
|
+
slug = count === 0 ? baseSlug : `${baseSlug}-${count}`;
|
|
102
|
+
seen.set(baseSlug, count + 1);
|
|
103
|
+
if (!node.props)
|
|
104
|
+
node.props = { level: 1 };
|
|
105
|
+
node.props.slug = slug;
|
|
106
|
+
}
|
|
77
107
|
headings.push({
|
|
78
108
|
depth: node.props?.level ?? 1,
|
|
79
|
-
slug
|
|
109
|
+
slug,
|
|
80
110
|
text,
|
|
81
111
|
});
|
|
82
112
|
}
|
|
@@ -95,7 +125,18 @@ async function importDogsbayMd(source, opts) {
|
|
|
95
125
|
}
|
|
96
126
|
const navFilePath = opts.nav || undefined;
|
|
97
127
|
const hrefPrefix = typeof opts.hrefPrefix === "string" ? opts.hrefPrefix : undefined;
|
|
98
|
-
|
|
128
|
+
// `--strict` at the CLI layer maps to "fail" here. `loadNavFile`
|
|
129
|
+
// already throws on the first miss in fail mode; the build
|
|
130
|
+
// surfaces the throw as a fatal error and exits non-zero.
|
|
131
|
+
// See plans/site-build-strict.md.
|
|
132
|
+
const missingNavTargets = opts.missingNavTargets === "fail"
|
|
133
|
+
? "fail"
|
|
134
|
+
: undefined;
|
|
135
|
+
const nav = buildNavFromDirectory(source, {
|
|
136
|
+
navFilePath,
|
|
137
|
+
hrefPrefix,
|
|
138
|
+
missingFile: missingNavTargets,
|
|
139
|
+
});
|
|
99
140
|
return { pages, nav };
|
|
100
141
|
}
|
|
101
142
|
function prettifyName(slug) {
|
package/dist/cli.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAC1E,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AAErD,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAC3C,OAAO,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAC7C,OAAO,EAAE,qBAAqB,EAAE,MAAM,UAAU,CAAC;
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
|
package/dist/directives.js
CHANGED
|
@@ -38,6 +38,17 @@ export function renderBlockDirective(input, ctx) {
|
|
|
38
38
|
}
|
|
39
39
|
/**
|
|
40
40
|
* Decide if a set of attributes warrants YAML body form.
|
|
41
|
+
*
|
|
42
|
+
* Forced when:
|
|
43
|
+
* - prop count exceeds the threshold (default 3),
|
|
44
|
+
* - any string value contains a newline (inline form normalises
|
|
45
|
+
* newlines to spaces, which loses author intent),
|
|
46
|
+
* - any value is a boolean (the inline shorthand `{flag}` parses
|
|
47
|
+
* as the empty string, not `true`, so booleans don't round-
|
|
48
|
+
* trip — caught during Phase 4 autodoc-directive tests), OR
|
|
49
|
+
* - any value is an array / object / nested structure (inline
|
|
50
|
+
* form has no syntax for those — without YAML they get
|
|
51
|
+
* dropped by `renderAttrs`).
|
|
41
52
|
*/
|
|
42
53
|
function shouldUseYaml(attrs, ctx) {
|
|
43
54
|
const propCount = (attrs.id ? 1 : 0) +
|
|
@@ -45,11 +56,22 @@ function shouldUseYaml(attrs, ctx) {
|
|
|
45
56
|
Object.keys(attrs.props ?? {}).length;
|
|
46
57
|
if (propCount > ctx.yamlThreshold)
|
|
47
58
|
return true;
|
|
48
|
-
// Multi-line or complex string values force YAML
|
|
49
59
|
if (attrs.props) {
|
|
50
60
|
for (const value of Object.values(attrs.props)) {
|
|
61
|
+
// Multi-line strings would lose their structure in inline form.
|
|
51
62
|
if (typeof value === "string" && value.includes("\n"))
|
|
52
63
|
return true;
|
|
64
|
+
// Booleans don't round-trip through the inline-attrs form —
|
|
65
|
+
// `{flag}` parses as "" (empty string). YAML preserves the
|
|
66
|
+
// type. Same logic applies to numbers in principle, but
|
|
67
|
+
// numbers do survive inline (parsed back as strings; consumers
|
|
68
|
+
// tolerate that). Booleans break consumers that check `=== true`.
|
|
69
|
+
if (typeof value === "boolean")
|
|
70
|
+
return true;
|
|
71
|
+
// Arrays / nested objects can't be expressed in inline form at
|
|
72
|
+
// all; only YAML body preserves them.
|
|
73
|
+
if (value !== null && typeof value === "object")
|
|
74
|
+
return true;
|
|
53
75
|
}
|
|
54
76
|
}
|
|
55
77
|
return false;
|
package/dist/directives.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"directives.js","sourceRoot":"","sources":["../src/directives.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,OAAO,EAAE,WAAW,EAAE,UAAU,EAAsB,MAAM,iBAAiB,CAAC;AAC9E,OAAO,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AACjD,OAAO,EAAE,UAAU,EAAkB,MAAM,WAAW,CAAC;AAgBvD;;;GAGG;AACH,MAAM,UAAU,oBAAoB,CAClC,KAA2B,EAC3B,GAAoB;IAEpB,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,YAAY,GAAG,EAAE,EAAE,IAAI,GAAG,EAAE,EAAE,GAAG,KAAK,CAAC;IAC5D,MAAM,YAAY,GAAG,KAAK,CAAC,YAAY,IAAI,GAAG,CAAC,cAAc,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IAExE,MAAM,KAAK,GAAG,UAAU,CAAC,KAAK,EAAE,YAAY,CAAC,CAAC;IAC9C,MAAM,OAAO,GAAG,YAAY,IAAI,aAAa,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;IAE1D,MAAM,KAAK,GAAG,kBAAkB,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,GAAG,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;IAElE,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,MAAM,OAAO,GAAG,WAAW,CAAC,KAAK,CAAC,CAAC;QACnC,MAAM,MAAM,GAAG,OAAO,CAAC,CAAC,CAAC,GAAG,KAAK,GAAG,IAAI,GAAG,OAAO,EAAE,CAAC,CAAC,CAAC,GAAG,KAAK,GAAG,IAAI,EAAE,CAAC;QACzE,OAAO,GAAG,MAAM,KAAK,IAAI,KAAK,KAAK,EAAE,CAAC;IACxC,CAAC;IAED,uEAAuE;IACvE,MAAM,QAAQ,GAAG,WAAW,CAAC,KAAK,CAAC,CAAC;IACpC,MAAM,IAAI,GAAG,UAAU,CAAC,QAAQ,CAAC,CAAC;IAClC,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,IAAI,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC;IAE1D,IAAI,CAAC,IAAI,EAAE,CAAC;QACV,OAAO,GAAG,KAAK,GAAG,IAAI,KAAK,MAAM,KAAK,KAAK,EAAE,CAAC;IAChD,CAAC;IACD,OAAO,GAAG,KAAK,GAAG,IAAI,KAAK,MAAM,KAAK,IAAI,KAAK,KAAK,EAAE,CAAC;AACzD,CAAC;AAED
|
|
1
|
+
{"version":3,"file":"directives.js","sourceRoot":"","sources":["../src/directives.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -6,5 +6,8 @@ export type { ParseResult, ParseOptions } from "./parse.js";
|
|
|
6
6
|
export { buildNavFromDirectory } from "./nav.js";
|
|
7
7
|
export type { BuildNavOptions } from "./nav.js";
|
|
8
8
|
export { loadNavFile } from "./nav-file.js";
|
|
9
|
-
export type { NavFile, NavFileItem, LoadNavFileOptions } from "./nav-file.js";
|
|
9
|
+
export type { NavFile, NavFileItem, LoadNavFileOptions, MissingNavTarget, } from "./nav-file.js";
|
|
10
|
+
export { renderDiagrams } from "./renderers/diagrams.js";
|
|
11
|
+
export type { RenderDiagramsOptions } from "./renderers/diagrams.js";
|
|
12
|
+
export { renderMermaidSvg, setMmdcOverride, findMmdc } from "./renderers/mermaid.js";
|
|
10
13
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAClE,YAAY,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAEnD,OAAO,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAEhD,OAAO,EAAE,eAAe,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAC1D,YAAY,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAE5D,OAAO,EAAE,qBAAqB,EAAE,MAAM,UAAU,CAAC;AACjD,YAAY,EAAE,eAAe,EAAE,MAAM,UAAU,CAAC;AAEhD,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAC5C,YAAY,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAClE,YAAY,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAEnD,OAAO,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAEhD,OAAO,EAAE,eAAe,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAC1D,YAAY,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAE5D,OAAO,EAAE,qBAAqB,EAAE,MAAM,UAAU,CAAC;AACjD,YAAY,EAAE,eAAe,EAAE,MAAM,UAAU,CAAC;AAEhD,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAC5C,YAAY,EACV,OAAO,EACP,WAAW,EACX,kBAAkB,EAClB,gBAAgB,GACjB,MAAM,eAAe,CAAC;AAEvB,OAAO,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAC;AACzD,YAAY,EAAE,qBAAqB,EAAE,MAAM,yBAAyB,CAAC;AACrE,OAAO,EAAE,gBAAgB,EAAE,eAAe,EAAE,QAAQ,EAAE,MAAM,wBAAwB,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -7,4 +7,6 @@ export { inlineToDogsbayMd } from "./inline.js";
|
|
|
7
7
|
export { dogsbayMdToTree, parseInline } from "./parse.js";
|
|
8
8
|
export { buildNavFromDirectory } from "./nav.js";
|
|
9
9
|
export { loadNavFile } from "./nav-file.js";
|
|
10
|
+
export { renderDiagrams } from "./renderers/diagrams.js";
|
|
11
|
+
export { renderMermaidSvg, setMmdcOverride, findMmdc } from "./renderers/mermaid.js";
|
|
10
12
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,8DAA8D;AAC9D,EAAE;AACF,kDAAkD;AAClD,mCAAmC;AAEnC,OAAO,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAGlE,OAAO,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAEhD,OAAO,EAAE,eAAe,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAG1D,OAAO,EAAE,qBAAqB,EAAE,MAAM,UAAU,CAAC;AAGjD,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,8DAA8D;AAC9D,EAAE;AACF,kDAAkD;AAClD,mCAAmC;AAEnC,OAAO,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAGlE,OAAO,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAEhD,OAAO,EAAE,eAAe,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAG1D,OAAO,EAAE,qBAAqB,EAAE,MAAM,UAAU,CAAC;AAGjD,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAQ5C,OAAO,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAC;AAEzD,OAAO,EAAE,gBAAgB,EAAE,eAAe,EAAE,QAAQ,EAAE,MAAM,wBAAwB,CAAC"}
|
package/dist/inline.d.ts
CHANGED
|
@@ -4,6 +4,23 @@
|
|
|
4
4
|
import type { InlineNode } from "@dogsbay/types";
|
|
5
5
|
/**
|
|
6
6
|
* Serialize a flat array of inline nodes to markdown.
|
|
7
|
+
*
|
|
8
|
+
* Stack-based emit: maintains a stack of currently-open formatting
|
|
9
|
+
* marks and, between successive text nodes, opens/closes only the
|
|
10
|
+
* delta between current-stack and desired-formats. This produces:
|
|
11
|
+
*
|
|
12
|
+
* - `*foo bar*` (not `*foo** **bar*`) for sibling italic text runs,
|
|
13
|
+
* fixing the multi-line-emphasis case where the parser splits
|
|
14
|
+
* `*a\nb*` into three italic text nodes.
|
|
15
|
+
* - `*foo \`code\` bar*` (not `*foo*\`code\`*bar*`) for italic
|
|
16
|
+
* text bracketing inline code — non-text nodes don't disturb the
|
|
17
|
+
* open-format stack, so the wrapper stays open across them.
|
|
18
|
+
* - `**This is *not* news.**` (not `**This is *****not***** news.**`)
|
|
19
|
+
* for bold-around-italic — only italic opens/closes between the
|
|
20
|
+
* three text spans; the outer bold stays open the whole time.
|
|
21
|
+
*
|
|
22
|
+
* Round-trip stable on every case validated against the parser's
|
|
23
|
+
* output (see roundtrip.test.ts).
|
|
7
24
|
*/
|
|
8
25
|
export declare function inlineToDogsbayMd(nodes: InlineNode[] | undefined): string;
|
|
9
26
|
//# sourceMappingURL=inline.d.ts.map
|
package/dist/inline.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"inline.d.ts","sourceRoot":"","sources":["../src/inline.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"inline.d.ts","sourceRoot":"","sources":["../src/inline.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,OAAO,KAAK,EAAe,UAAU,EAAY,MAAM,gBAAgB,CAAC;AAgBxE;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,UAAU,EAAE,GAAG,SAAS,GAAG,MAAM,CA2CzE"}
|
package/dist/inline.js
CHANGED
|
@@ -1,11 +1,87 @@
|
|
|
1
1
|
import { escapeAttrValue } from "./attributes.js";
|
|
2
|
+
// Canonical nesting order: outermost → innermost. Strike outer, italic
|
|
3
|
+
// middle, bold inner. Matches the historical renderText() ordering and
|
|
4
|
+
// CommonMark community convention (`***strong-em***` reads as em(strong)).
|
|
5
|
+
const FORMAT_ORDER = ["strikethrough", "italic", "bold"];
|
|
6
|
+
const FORMAT_MARK = {
|
|
7
|
+
strikethrough: "~~",
|
|
8
|
+
italic: "*",
|
|
9
|
+
bold: "**",
|
|
10
|
+
};
|
|
2
11
|
/**
|
|
3
12
|
* Serialize a flat array of inline nodes to markdown.
|
|
13
|
+
*
|
|
14
|
+
* Stack-based emit: maintains a stack of currently-open formatting
|
|
15
|
+
* marks and, between successive text nodes, opens/closes only the
|
|
16
|
+
* delta between current-stack and desired-formats. This produces:
|
|
17
|
+
*
|
|
18
|
+
* - `*foo bar*` (not `*foo** **bar*`) for sibling italic text runs,
|
|
19
|
+
* fixing the multi-line-emphasis case where the parser splits
|
|
20
|
+
* `*a\nb*` into three italic text nodes.
|
|
21
|
+
* - `*foo \`code\` bar*` (not `*foo*\`code\`*bar*`) for italic
|
|
22
|
+
* text bracketing inline code — non-text nodes don't disturb the
|
|
23
|
+
* open-format stack, so the wrapper stays open across them.
|
|
24
|
+
* - `**This is *not* news.**` (not `**This is *****not***** news.**`)
|
|
25
|
+
* for bold-around-italic — only italic opens/closes between the
|
|
26
|
+
* three text spans; the outer bold stays open the whole time.
|
|
27
|
+
*
|
|
28
|
+
* Round-trip stable on every case validated against the parser's
|
|
29
|
+
* output (see roundtrip.test.ts).
|
|
4
30
|
*/
|
|
5
31
|
export function inlineToDogsbayMd(nodes) {
|
|
6
32
|
if (!nodes || nodes.length === 0)
|
|
7
33
|
return "";
|
|
8
|
-
|
|
34
|
+
const out = [];
|
|
35
|
+
const stack = [];
|
|
36
|
+
for (const node of nodes) {
|
|
37
|
+
if (node.type === "text") {
|
|
38
|
+
const desired = desiredFormatSet(node);
|
|
39
|
+
// Keep the stack prefix while every entry is still wanted;
|
|
40
|
+
// pop the first unwanted format and everything above it. This
|
|
41
|
+
// avoids unnecessary close/reopen pairs — e.g. when we go from
|
|
42
|
+
// {bold} to {bold, italic}, we just open italic INSIDE the
|
|
43
|
+
// already-open bold rather than closing bold, opening italic,
|
|
44
|
+
// reopening bold (which produces the dreaded `*****`).
|
|
45
|
+
let keep = 0;
|
|
46
|
+
while (keep < stack.length && desired.has(stack[keep]))
|
|
47
|
+
keep++;
|
|
48
|
+
while (stack.length > keep) {
|
|
49
|
+
out.push(FORMAT_MARK[stack.pop()]);
|
|
50
|
+
}
|
|
51
|
+
// Add still-missing formats. Canonical order is used only when
|
|
52
|
+
// the stack is empty; otherwise additions append on top of
|
|
53
|
+
// whatever's already nested. Both nestings round-trip to the
|
|
54
|
+
// same tree.
|
|
55
|
+
for (const fmt of FORMAT_ORDER) {
|
|
56
|
+
if (desired.has(fmt) && !stack.includes(fmt)) {
|
|
57
|
+
out.push(FORMAT_MARK[fmt]);
|
|
58
|
+
stack.push(fmt);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
out.push(escapeInlineText(node.text));
|
|
62
|
+
}
|
|
63
|
+
else {
|
|
64
|
+
// Non-text inline (code, link, image, …) doesn't carry format
|
|
65
|
+
// flags; leave the open-format stack alone so a wrapper that
|
|
66
|
+
// bridges across it (like `*foo \`code\` bar*`) survives.
|
|
67
|
+
out.push(renderInline(node));
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
// Close anything still open at the end.
|
|
71
|
+
while (stack.length > 0) {
|
|
72
|
+
out.push(FORMAT_MARK[stack.pop()]);
|
|
73
|
+
}
|
|
74
|
+
return out.join("");
|
|
75
|
+
}
|
|
76
|
+
function desiredFormatSet(node) {
|
|
77
|
+
const s = new Set();
|
|
78
|
+
if (node.strikethrough)
|
|
79
|
+
s.add("strikethrough");
|
|
80
|
+
if (node.italic)
|
|
81
|
+
s.add("italic");
|
|
82
|
+
if (node.bold)
|
|
83
|
+
s.add("bold");
|
|
84
|
+
return s;
|
|
9
85
|
}
|
|
10
86
|
function renderInline(node) {
|
|
11
87
|
switch (node.type) {
|
|
@@ -37,9 +113,11 @@ function renderInline(node) {
|
|
|
37
113
|
}
|
|
38
114
|
}
|
|
39
115
|
function renderText(node) {
|
|
116
|
+
// Single-node fallback for callers that bypass inlineToDogsbayMd.
|
|
117
|
+
// The grouped path strips format flags before emitting body content;
|
|
118
|
+
// this branch handles the rare standalone case (e.g. nodeToDogsbayMd
|
|
119
|
+
// on a lone text node).
|
|
40
120
|
let text = escapeInlineText(node.text);
|
|
41
|
-
// Apply annotations from outside in: strikethrough, italic, bold
|
|
42
|
-
// Order produces canonical output: ~~*_**text**_*~~
|
|
43
121
|
if (node.bold)
|
|
44
122
|
text = `**${text}**`;
|
|
45
123
|
if (node.italic)
|
|
@@ -52,13 +130,46 @@ function renderLink(node) {
|
|
|
52
130
|
const label = inlineToDogsbayMd(node.children);
|
|
53
131
|
const href = escapeLinkDest(node.href);
|
|
54
132
|
const title = node.title ? ` ${escapeAttrValue(node.title)}` : "";
|
|
55
|
-
|
|
133
|
+
const attrs = renderInlineAttrs(node.attrs);
|
|
134
|
+
return `[${label}](${href}${title})${attrs}`;
|
|
135
|
+
}
|
|
136
|
+
/**
|
|
137
|
+
* Render an inline attribute block (`{.class #id key="val"}`) for
|
|
138
|
+
* InlineLink (and, in future phases, InlineImage / InlineSpan).
|
|
139
|
+
*
|
|
140
|
+
* Mirrors the block-level `renderAttrs` ordering: id, classes, then
|
|
141
|
+
* remaining keys. Returns "" when no attrs are present so the caller
|
|
142
|
+
* can append unconditionally.
|
|
143
|
+
*/
|
|
144
|
+
function renderInlineAttrs(attrs) {
|
|
145
|
+
if (!attrs)
|
|
146
|
+
return "";
|
|
147
|
+
const parts = [];
|
|
148
|
+
if (attrs.id)
|
|
149
|
+
parts.push(`#${attrs.id}`);
|
|
150
|
+
if (attrs.class) {
|
|
151
|
+
for (const cls of attrs.class.split(/\s+/)) {
|
|
152
|
+
if (cls)
|
|
153
|
+
parts.push(`.${cls}`);
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
for (const [key, value] of Object.entries(attrs)) {
|
|
157
|
+
if (value === undefined)
|
|
158
|
+
continue;
|
|
159
|
+
if (key === "id" || key === "class")
|
|
160
|
+
continue;
|
|
161
|
+
parts.push(`${key}=${escapeAttrValue(String(value))}`);
|
|
162
|
+
}
|
|
163
|
+
if (parts.length === 0)
|
|
164
|
+
return "";
|
|
165
|
+
return `{${parts.join(" ")}}`;
|
|
56
166
|
}
|
|
57
167
|
function renderImage(node) {
|
|
58
168
|
const alt = node.alt ? escapeInlineText(node.alt) : "";
|
|
59
169
|
const src = escapeLinkDest(node.src);
|
|
60
170
|
const title = node.title ? ` ${escapeAttrValue(node.title)}` : "";
|
|
61
|
-
|
|
171
|
+
const attrs = renderInlineAttrs(node.attrs);
|
|
172
|
+
return `${attrs}`;
|
|
62
173
|
}
|
|
63
174
|
function renderInlineCode(text) {
|
|
64
175
|
// Choose a backtick run that doesn't appear in the content
|
package/dist/inline.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"inline.js","sourceRoot":"","sources":["../src/inline.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,eAAe,EAA2B,MAAM,iBAAiB,CAAC;
|
|
1
|
+
{"version":3,"file":"inline.js","sourceRoot":"","sources":["../src/inline.ts"],"names":[],"mappings":"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"}
|
package/dist/nav-file.d.ts
CHANGED
|
@@ -15,14 +15,35 @@ export interface NavFileItem {
|
|
|
15
15
|
children?: NavFileItem[];
|
|
16
16
|
}
|
|
17
17
|
export type NavFile = NavFileItem[];
|
|
18
|
+
/** One nav-file `file:` reference that failed to resolve. */
|
|
19
|
+
export interface MissingNavTarget {
|
|
20
|
+
/** Raw `file:` value as authored in the nav file. */
|
|
21
|
+
file: string;
|
|
22
|
+
/** Absolute path the resolver looked at. */
|
|
23
|
+
resolvedAbs: string;
|
|
24
|
+
}
|
|
18
25
|
export interface LoadNavFileOptions {
|
|
19
26
|
/** Prefix for resolved hrefs. Default: "/docs" */
|
|
20
27
|
hrefPrefix?: string;
|
|
21
28
|
/**
|
|
22
|
-
*
|
|
23
|
-
*
|
|
29
|
+
* Behaviour when a `file:` reference doesn't exist:
|
|
30
|
+
* - "warn" (default): log via console.warn, emit a label-only
|
|
31
|
+
* nav entry, keep going.
|
|
32
|
+
* - "fail": throw an Error on the first miss.
|
|
33
|
+
* - "collect": silently fall back to label-only and push every
|
|
34
|
+
* miss to `onMissingTarget` (no console.warn). The audit rule
|
|
35
|
+
* `structure/nav-target-exists` uses this mode to surface
|
|
36
|
+
* misses as structured Issues without duplicating the file
|
|
37
|
+
* resolution logic.
|
|
38
|
+
*/
|
|
39
|
+
missingFile?: "warn" | "fail" | "collect";
|
|
40
|
+
/**
|
|
41
|
+
* Callback invoked once per missing file reference when
|
|
42
|
+
* `missingFile === "collect"`. Pushed entries are
|
|
43
|
+
* deduplication-friendly (file + resolvedAbs); callers typically
|
|
44
|
+
* pass an array's `.push.bind(arr)`.
|
|
24
45
|
*/
|
|
25
|
-
|
|
46
|
+
onMissingTarget?: (target: MissingNavTarget) => void;
|
|
26
47
|
}
|
|
27
48
|
/**
|
|
28
49
|
* Load + parse a nav file at the given path. Returns a normalized
|
package/dist/nav-file.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"nav-file.d.ts","sourceRoot":"","sources":["../src/nav-file.ts"],"names":[],"mappings":"AAmBA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,gBAAgB,CAAC;AAE9C;;;;GAIG;AACH,MAAM,WAAW,WAAW;IAC1B,mCAAmC;IACnC,KAAK,EAAE,MAAM,CAAC;IACd,+DAA+D;IAC/D,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,gEAAgE;IAChE,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,mBAAmB;IACnB,QAAQ,CAAC,EAAE,WAAW,EAAE,CAAC;CAC1B;AAED,MAAM,MAAM,OAAO,GAAG,WAAW,EAAE,CAAC;AAEpC,MAAM,WAAW,kBAAkB;IACjC,kDAAkD;IAClD,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB
|
|
1
|
+
{"version":3,"file":"nav-file.d.ts","sourceRoot":"","sources":["../src/nav-file.ts"],"names":[],"mappings":"AAmBA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,gBAAgB,CAAC;AAE9C;;;;GAIG;AACH,MAAM,WAAW,WAAW;IAC1B,mCAAmC;IACnC,KAAK,EAAE,MAAM,CAAC;IACd,+DAA+D;IAC/D,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,gEAAgE;IAChE,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,mBAAmB;IACnB,QAAQ,CAAC,EAAE,WAAW,EAAE,CAAC;CAC1B;AAED,MAAM,MAAM,OAAO,GAAG,WAAW,EAAE,CAAC;AAEpC,6DAA6D;AAC7D,MAAM,WAAW,gBAAgB;IAC/B,qDAAqD;IACrD,IAAI,EAAE,MAAM,CAAC;IACb,4CAA4C;IAC5C,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,kBAAkB;IACjC,kDAAkD;IAClD,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB;;;;;;;;;;OAUG;IACH,WAAW,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAAC;IAC1C;;;;;OAKG;IACH,eAAe,CAAC,EAAE,CAAC,MAAM,EAAE,gBAAgB,KAAK,IAAI,CAAC;CACtD;AAED;;;;;;;;;GASG;AACH,wBAAgB,WAAW,CACzB,IAAI,EAAE,MAAM,EACZ,UAAU,EAAE,MAAM,EAClB,OAAO,GAAE,kBAAuB,GAC/B,OAAO,EAAE,CA+BX"}
|
package/dist/nav-file.js
CHANGED
|
@@ -48,7 +48,7 @@ export function loadNavFile(path, contentDir, options = {}) {
|
|
|
48
48
|
const normalized = normalizeNavFile(parsed, absolutePath);
|
|
49
49
|
const hrefPrefix = options.hrefPrefix ?? "/docs";
|
|
50
50
|
const missingFileMode = options.missingFile ?? "warn";
|
|
51
|
-
return convertItems(normalized, contentDir, hrefPrefix, missingFileMode);
|
|
51
|
+
return convertItems(normalized, contentDir, hrefPrefix, missingFileMode, options.onMissingTarget);
|
|
52
52
|
}
|
|
53
53
|
// ── JSON parsing ─────────────────────────────────────────────────
|
|
54
54
|
function parseJsonNav(raw, sourcePath) {
|
|
@@ -202,10 +202,10 @@ const EXTERNAL_HREF_RE = /^(?:https?:\/\/|\/|mailto:|tel:|#)/i;
|
|
|
202
202
|
* type). Resolves `file` references to slugs, passes external `href`
|
|
203
203
|
* values through, and warns/fails on missing files per options.
|
|
204
204
|
*/
|
|
205
|
-
function convertItems(items, contentDir, hrefPrefix, missingFileMode) {
|
|
206
|
-
return items.map((item) => convertItem(item, contentDir, hrefPrefix, missingFileMode));
|
|
205
|
+
function convertItems(items, contentDir, hrefPrefix, missingFileMode, onMissingTarget) {
|
|
206
|
+
return items.map((item) => convertItem(item, contentDir, hrefPrefix, missingFileMode, onMissingTarget));
|
|
207
207
|
}
|
|
208
|
-
function convertItem(item, contentDir, hrefPrefix, missingFileMode) {
|
|
208
|
+
function convertItem(item, contentDir, hrefPrefix, missingFileMode, onMissingTarget) {
|
|
209
209
|
const result = { label: item.label };
|
|
210
210
|
if (item.href) {
|
|
211
211
|
// External / absolute URL — pass through unchanged
|
|
@@ -220,13 +220,26 @@ function convertItem(item, contentDir, hrefPrefix, missingFileMode) {
|
|
|
220
220
|
else {
|
|
221
221
|
const fileAbs = resolve(contentDir, item.file);
|
|
222
222
|
if (!existsSync(fileAbs)) {
|
|
223
|
+
// Same actionable phrasing across warn / fail / collect AND
|
|
224
|
+
// the audit rule (structure/nav-target-exists). Users see
|
|
225
|
+
// one consistent fix regardless of where the failure
|
|
226
|
+
// surfaces. Update both sides together.
|
|
223
227
|
const message = `Nav file references missing file: ${item.file} ` +
|
|
224
|
-
`(resolved
|
|
228
|
+
`(resolved to ${fileAbs}). To fix: rename the file to ` +
|
|
229
|
+
`match, correct the path in the nav file, or remove the ` +
|
|
230
|
+
`entry.`;
|
|
225
231
|
if (missingFileMode === "fail") {
|
|
226
232
|
throw new Error(message);
|
|
227
233
|
}
|
|
228
|
-
|
|
229
|
-
|
|
234
|
+
if (missingFileMode === "collect") {
|
|
235
|
+
onMissingTarget?.({ file: item.file, resolvedAbs: fileAbs });
|
|
236
|
+
}
|
|
237
|
+
else {
|
|
238
|
+
// "warn" — log + produce a label-only nav entry. The audit
|
|
239
|
+
// rule structure/nav-target-exists is the structured
|
|
240
|
+
// surface for this same condition.
|
|
241
|
+
console.warn(`[dogsbay] ${message}`);
|
|
242
|
+
}
|
|
230
243
|
}
|
|
231
244
|
else {
|
|
232
245
|
result.href = fileToHref(item.file, hrefPrefix);
|
|
@@ -234,19 +247,26 @@ function convertItem(item, contentDir, hrefPrefix, missingFileMode) {
|
|
|
234
247
|
}
|
|
235
248
|
}
|
|
236
249
|
if (item.children) {
|
|
237
|
-
result.children = convertItems(item.children, contentDir, hrefPrefix, missingFileMode);
|
|
250
|
+
result.children = convertItems(item.children, contentDir, hrefPrefix, missingFileMode, onMissingTarget);
|
|
238
251
|
}
|
|
239
252
|
return result;
|
|
240
253
|
}
|
|
241
254
|
/**
|
|
242
|
-
* Convert a relative
|
|
255
|
+
* Convert a relative content file path into a public-facing URL, e.g.
|
|
243
256
|
* "docs-as-code/welcome.md" → "/docs/docs-as-code/welcome".
|
|
257
|
+
*
|
|
258
|
+
* Both `.md` (imported markdown) and `.astro` (passthrough Astro pages
|
|
259
|
+
* — see plans/passthrough-astro-pages.md) collapse to the same slug
|
|
260
|
+
* shape, so authors can mix the two in nav.yml without thinking about
|
|
261
|
+
* how each path will be processed. Whether a path becomes a generated
|
|
262
|
+
* page or a passthrough page is decided downstream by the source file
|
|
263
|
+
* extension; this slug helper just produces a stable URL.
|
|
244
264
|
*/
|
|
245
265
|
function fileToHref(file, hrefPrefix) {
|
|
246
266
|
// Normalize path separators to forward slashes (Windows compat)
|
|
247
267
|
const normalized = file.replace(/\\/g, "/").replace(/^\.\//, "");
|
|
248
|
-
// Strip .md extension. index
|
|
249
|
-
let slug = normalized.replace(/\.md$/i, "");
|
|
268
|
+
// Strip .md / .astro extension. index.* becomes the directory itself.
|
|
269
|
+
let slug = normalized.replace(/\.(md|astro)$/i, "");
|
|
250
270
|
if (slug.endsWith("/index"))
|
|
251
271
|
slug = slug.slice(0, -"/index".length);
|
|
252
272
|
if (slug === "index")
|