@dogsbay/format-dogsbay-md 0.2.0-beta.0

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 (65) hide show
  1. package/dist/attributes.d.ts +33 -0
  2. package/dist/attributes.d.ts.map +1 -0
  3. package/dist/attributes.js +83 -0
  4. package/dist/attributes.js.map +1 -0
  5. package/dist/cli.d.ts +3 -0
  6. package/dist/cli.d.ts.map +1 -0
  7. package/dist/cli.js +129 -0
  8. package/dist/cli.js.map +1 -0
  9. package/dist/directives.d.ts +19 -0
  10. package/dist/directives.d.ts.map +1 -0
  11. package/dist/directives.js +76 -0
  12. package/dist/directives.js.map +1 -0
  13. package/dist/escape.d.ts +42 -0
  14. package/dist/escape.d.ts.map +1 -0
  15. package/dist/escape.js +79 -0
  16. package/dist/escape.js.map +1 -0
  17. package/dist/index.d.ts +10 -0
  18. package/dist/index.d.ts.map +1 -0
  19. package/dist/index.js +10 -0
  20. package/dist/index.js.map +1 -0
  21. package/dist/inline.d.ts +9 -0
  22. package/dist/inline.d.ts.map +1 -0
  23. package/dist/inline.js +122 -0
  24. package/dist/inline.js.map +1 -0
  25. package/dist/nav-file.d.ts +38 -0
  26. package/dist/nav-file.d.ts.map +1 -0
  27. package/dist/nav-file.js +257 -0
  28. package/dist/nav-file.js.map +1 -0
  29. package/dist/nav.d.ts +34 -0
  30. package/dist/nav.d.ts.map +1 -0
  31. package/dist/nav.js +169 -0
  32. package/dist/nav.js.map +1 -0
  33. package/dist/parse-attrs.d.ts +24 -0
  34. package/dist/parse-attrs.d.ts.map +1 -0
  35. package/dist/parse-attrs.js +117 -0
  36. package/dist/parse-attrs.js.map +1 -0
  37. package/dist/parse.d.ts +18 -0
  38. package/dist/parse.d.ts.map +1 -0
  39. package/dist/parse.js +1076 -0
  40. package/dist/parse.js.map +1 -0
  41. package/dist/plugin-block-leaf.d.ts +19 -0
  42. package/dist/plugin-block-leaf.d.ts.map +1 -0
  43. package/dist/plugin-block-leaf.js +81 -0
  44. package/dist/plugin-block-leaf.js.map +1 -0
  45. package/dist/plugin-containers.d.ts +11 -0
  46. package/dist/plugin-containers.d.ts.map +1 -0
  47. package/dist/plugin-containers.js +63 -0
  48. package/dist/plugin-containers.js.map +1 -0
  49. package/dist/plugin-inline-directives.d.ts +18 -0
  50. package/dist/plugin-inline-directives.d.ts.map +1 -0
  51. package/dist/plugin-inline-directives.js +121 -0
  52. package/dist/plugin-inline-directives.js.map +1 -0
  53. package/dist/serialize.d.ts +25 -0
  54. package/dist/serialize.d.ts.map +1 -0
  55. package/dist/serialize.js +712 -0
  56. package/dist/serialize.js.map +1 -0
  57. package/dist/types.d.ts +40 -0
  58. package/dist/types.d.ts.map +1 -0
  59. package/dist/types.js +10 -0
  60. package/dist/types.js.map +1 -0
  61. package/dist/yaml.d.ts +22 -0
  62. package/dist/yaml.d.ts.map +1 -0
  63. package/dist/yaml.js +113 -0
  64. package/dist/yaml.js.map +1 -0
  65. package/package.json +55 -0
@@ -0,0 +1,33 @@
1
+ /**
2
+ * Attribute rendering — produces `{ #id .class1 .class2 key="value" }` blocks
3
+ * following the markdown-it-attrs syntax.
4
+ *
5
+ * Ordering convention: id first, then classes, then key=value attributes.
6
+ * Empty attrs return "".
7
+ */
8
+ export interface RenderedAttrs {
9
+ id?: string;
10
+ classes?: string[];
11
+ props?: Record<string, string | number | boolean | undefined>;
12
+ }
13
+ /**
14
+ * Render an attribute block.
15
+ * Returns `{ #id .a .b key="value" }` or "" if no attrs.
16
+ * Leading space included so callers can append directly to content.
17
+ */
18
+ export declare function renderAttrs(attrs: RenderedAttrs): string;
19
+ /**
20
+ * Escape an attribute value for inclusion in {key="value"}.
21
+ * Always double-quotes; escapes embedded quotes and backslashes.
22
+ * Normalizes newlines to spaces since attribute values must be single-line
23
+ * (multi-line values should use YAML body form, not {attrs}).
24
+ */
25
+ export declare function escapeAttrValue(value: string): string;
26
+ /**
27
+ * Split a free-form props record into RenderedAttrs, extracting `id` and `class`/`className`
28
+ * into their structured form. Unknown keys stay in `props`.
29
+ *
30
+ * This is the common glue between TreeNode.props and attribute output.
31
+ */
32
+ export declare function splitProps(props: Record<string, unknown> | undefined, excludeKeys?: string[]): RenderedAttrs;
33
+ //# sourceMappingURL=attributes.d.ts.map
@@ -0,0 +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,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,SAAS,CAAC,CAAC;CAC/D;AAED;;;;GAIG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,aAAa,GAAG,MAAM,CA0BxD;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,CA8Bf"}
@@ -0,0 +1,83 @@
1
+ /**
2
+ * Attribute rendering — produces `{ #id .class1 .class2 key="value" }` blocks
3
+ * following the markdown-it-attrs syntax.
4
+ *
5
+ * Ordering convention: id first, then classes, then key=value attributes.
6
+ * Empty attrs return "".
7
+ */
8
+ /**
9
+ * Render an attribute block.
10
+ * Returns `{ #id .a .b key="value" }` or "" if no attrs.
11
+ * Leading space included so callers can append directly to content.
12
+ */
13
+ export function renderAttrs(attrs) {
14
+ const parts = [];
15
+ if (attrs.id) {
16
+ parts.push(`#${attrs.id}`);
17
+ }
18
+ if (attrs.classes) {
19
+ for (const cls of attrs.classes) {
20
+ if (cls)
21
+ parts.push(`.${cls}`);
22
+ }
23
+ }
24
+ if (attrs.props) {
25
+ for (const [key, value] of Object.entries(attrs.props)) {
26
+ if (value === undefined || value === null || value === false)
27
+ continue;
28
+ if (value === true) {
29
+ parts.push(key);
30
+ continue;
31
+ }
32
+ parts.push(`${key}=${escapeAttrValue(String(value))}`);
33
+ }
34
+ }
35
+ if (parts.length === 0)
36
+ return "";
37
+ return `{${parts.join(" ")}}`;
38
+ }
39
+ /**
40
+ * Escape an attribute value for inclusion in {key="value"}.
41
+ * Always double-quotes; escapes embedded quotes and backslashes.
42
+ * Normalizes newlines to spaces since attribute values must be single-line
43
+ * (multi-line values should use YAML body form, not {attrs}).
44
+ */
45
+ export function escapeAttrValue(value) {
46
+ const normalized = value.replace(/\r?\n/g, " ").replace(/\s+/g, " ");
47
+ return `"${normalized.replace(/\\/g, "\\\\").replace(/"/g, '\\"')}"`;
48
+ }
49
+ /**
50
+ * Split a free-form props record into RenderedAttrs, extracting `id` and `class`/`className`
51
+ * into their structured form. Unknown keys stay in `props`.
52
+ *
53
+ * This is the common glue between TreeNode.props and attribute output.
54
+ */
55
+ export function splitProps(props, excludeKeys = []) {
56
+ const result = {};
57
+ if (!props)
58
+ return result;
59
+ const exclude = new Set(excludeKeys);
60
+ const cleanProps = {};
61
+ for (const [key, value] of Object.entries(props)) {
62
+ if (exclude.has(key))
63
+ continue;
64
+ if (key === "id" && typeof value === "string") {
65
+ result.id = value;
66
+ continue;
67
+ }
68
+ if ((key === "class" || key === "className") && typeof value === "string") {
69
+ result.classes = value.split(/\s+/).filter(Boolean);
70
+ continue;
71
+ }
72
+ if (value === null || value === undefined)
73
+ continue;
74
+ if (typeof value === "object")
75
+ continue; // skip nested structures
76
+ cleanProps[key] = value;
77
+ }
78
+ if (Object.keys(cleanProps).length > 0) {
79
+ result.props = cleanProps;
80
+ }
81
+ return result;
82
+ }
83
+ //# sourceMappingURL=attributes.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"attributes.js","sourceRoot":"","sources":["../src/attributes.ts"],"names":[],"mappings":"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"}
package/dist/cli.d.ts ADDED
@@ -0,0 +1,3 @@
1
+ import type { FormatPlugin } from "@dogsbay/types";
2
+ export declare const plugin: FormatPlugin;
3
+ //# sourceMappingURL=cli.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,YAAY,EAAgC,MAAM,gBAAgB,CAAC;AA2HjF,eAAO,MAAM,MAAM,EAAE,YAcpB,CAAC"}
package/dist/cli.js ADDED
@@ -0,0 +1,129 @@
1
+ /**
2
+ * FormatPlugin for Dogsbay MD as a source format.
3
+ *
4
+ * Reads a directory of .md files, parses each via dogsbayMdToTree, builds nav
5
+ * from directory structure + frontmatter, returns ExportPage[] + NavItem[].
6
+ */
7
+ import { existsSync, readdirSync, readFileSync, statSync } from "node:fs";
8
+ import { join, relative, basename } from "node:path";
9
+ import { parseMeta } from "@dogsbay/types";
10
+ import { dogsbayMdToTree } from "./parse.js";
11
+ import { buildNavFromDirectory } from "./nav.js";
12
+ /**
13
+ * Detect whether a directory contains a Dogsbay MD source tree.
14
+ *
15
+ * Heuristic: at least one .md file with frontmatter in the directory or
16
+ * any immediate subdirectory. We don't fail if the heuristic misses — the
17
+ * CLI allows explicit --from dogsbay-md.
18
+ */
19
+ function detectDogsbayMdSource(path) {
20
+ if (!existsSync(path))
21
+ return false;
22
+ try {
23
+ const st = statSync(path);
24
+ if (!st.isDirectory())
25
+ return false;
26
+ const entries = readdirSync(path, { recursive: true });
27
+ return entries.some((e) => e.endsWith(".md"));
28
+ }
29
+ catch {
30
+ return false;
31
+ }
32
+ }
33
+ function walkMdFiles(dir, root, out = []) {
34
+ for (const entry of readdirSync(dir, { withFileTypes: true })) {
35
+ const full = join(dir, entry.name);
36
+ if (entry.isDirectory()) {
37
+ walkMdFiles(full, root, out);
38
+ }
39
+ else if (entry.name.endsWith(".md")) {
40
+ const rel = relative(root, full).replace(/\\/g, "/");
41
+ const slug = rel.replace(/\.md$/, "");
42
+ out.push({ filePath: full, slug });
43
+ }
44
+ }
45
+ return out;
46
+ }
47
+ async function importDogsbayMd(source, opts) {
48
+ if (!existsSync(source)) {
49
+ throw new Error(`Source directory not found: ${source}`);
50
+ }
51
+ const st = statSync(source);
52
+ if (!st.isDirectory()) {
53
+ throw new Error(`Source must be a directory: ${source}`);
54
+ }
55
+ const files = walkMdFiles(source, source);
56
+ const pages = [];
57
+ // Taxonomy names declared in dogsbay.config.yml's `taxonomies:` block;
58
+ // wired through cli's import-content.ts. parseMeta uses these to lift
59
+ // user-declared taxonomy keys (e.g. `audience`, `product`) into
60
+ // meta.taxonomies. Absent for standalone CLI invocations.
61
+ const taxonomyNames = Array.isArray(opts.taxonomyNames)
62
+ ? opts.taxonomyNames
63
+ : undefined;
64
+ for (const { filePath, slug } of files) {
65
+ const content = readFileSync(filePath, "utf-8");
66
+ const { tree, frontmatter } = dogsbayMdToTree(content);
67
+ const title = String(frontmatter.title
68
+ ?? prettifyName(basename(slug)));
69
+ // Extract heading metadata for TOC
70
+ const headings = [];
71
+ for (const node of tree) {
72
+ if (node.type === "heading" && node.inline) {
73
+ const text = node.inline
74
+ .map((n) => (n.type === "text" ? n.text : ""))
75
+ .join("")
76
+ .trim();
77
+ headings.push({
78
+ depth: node.props?.level ?? 1,
79
+ slug: node.props?.slug ?? slugify(text),
80
+ text,
81
+ });
82
+ }
83
+ }
84
+ const redirect = frontmatter.redirect;
85
+ const meta = parseMeta(frontmatter, { slug, taxonomyNames });
86
+ pages.push({
87
+ slug,
88
+ title,
89
+ tree,
90
+ headings,
91
+ redirect,
92
+ frontmatter,
93
+ meta,
94
+ });
95
+ }
96
+ const navFilePath = opts.nav || undefined;
97
+ const hrefPrefix = typeof opts.hrefPrefix === "string" ? opts.hrefPrefix : undefined;
98
+ const nav = buildNavFromDirectory(source, { navFilePath, hrefPrefix });
99
+ return { pages, nav };
100
+ }
101
+ function prettifyName(slug) {
102
+ return slug
103
+ .split(/[-_]/)
104
+ .map((w) => w.charAt(0).toUpperCase() + w.slice(1))
105
+ .join(" ");
106
+ }
107
+ function slugify(text) {
108
+ return text
109
+ .toLowerCase()
110
+ .replace(/[^\w\s-]/g, "")
111
+ .trim()
112
+ .replace(/\s+/g, "-");
113
+ }
114
+ export const plugin = {
115
+ name: "dogsbay-md",
116
+ canImport: true,
117
+ canExport: false,
118
+ detectSource: detectDogsbayMdSource,
119
+ importOptions: [
120
+ {
121
+ flags: "--nav <path>",
122
+ description: "Path to an explicit nav file (.json/.yml/.yaml). Overrides heuristic auto-detection of nav.json / nav.yml / nav.yaml in the content root.",
123
+ },
124
+ ],
125
+ async import(source, opts) {
126
+ return importDogsbayMd(source, opts);
127
+ },
128
+ };
129
+ //# sourceMappingURL=cli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,19 @@
1
+ import type { ResolvedOptions } from "./types.js";
2
+ export interface DirectiveRenderInput {
3
+ /** Directive name, e.g. "card", "tabs", "steps" */
4
+ name: string;
5
+ /** Props to emit as attrs or YAML body */
6
+ props?: Record<string, unknown>;
7
+ /** Keys to exclude from props (already rendered elsewhere) */
8
+ excludeProps?: string[];
9
+ /** Body content (already serialized markdown) */
10
+ body?: string;
11
+ /** Opts into YAML body form for prop-heavy cases */
12
+ yamlEligible?: boolean;
13
+ }
14
+ /**
15
+ * Render a block directive. Chooses attrs-form vs yaml-body form based on
16
+ * the component, option threshold, and prop complexity.
17
+ */
18
+ export declare function renderBlockDirective(input: DirectiveRenderInput, ctx: ResolvedOptions): string;
19
+ //# sourceMappingURL=directives.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"directives.d.ts","sourceRoot":"","sources":["../src/directives.ts"],"names":[],"mappings":"AAcA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAElD,MAAM,WAAW,oBAAoB;IACnC,mDAAmD;IACnD,IAAI,EAAE,MAAM,CAAC;IACb,0CAA0C;IAC1C,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAChC,8DAA8D;IAC9D,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;IACxB,iDAAiD;IACjD,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,oDAAoD;IACpD,YAAY,CAAC,EAAE,OAAO,CAAC;CACxB;AAED;;;GAGG;AACH,wBAAgB,oBAAoB,CAClC,KAAK,EAAE,oBAAoB,EAC3B,GAAG,EAAE,eAAe,GACnB,MAAM,CAwBR"}
@@ -0,0 +1,76 @@
1
+ /**
2
+ * Directive rendering for block components (card, tabs, steps, cards, api-endpoint, ...).
3
+ *
4
+ * Two attribute forms:
5
+ * - Inline: `:::name{key="value" .class}` — compact, for simple prop sets
6
+ * - YAML: `:::name\n---\nkey: value\n---\nbody` — for prop-heavy components
7
+ *
8
+ * Heuristic: use YAML when the prop count exceeds threshold OR any string value
9
+ * contains a newline OR a nested object/array is present. Only components on
10
+ * the YAML opt-in list use the YAML form; others always use inline attrs.
11
+ */
12
+ import { renderAttrs, splitProps } from "./attributes.js";
13
+ import { pickDirectiveFence } from "./escape.js";
14
+ import { renderYaml } from "./yaml.js";
15
+ /**
16
+ * Render a block directive. Chooses attrs-form vs yaml-body form based on
17
+ * the component, option threshold, and prop complexity.
18
+ */
19
+ export function renderBlockDirective(input, ctx) {
20
+ const { name, props, excludeProps = [], body = "" } = input;
21
+ const yamlEligible = input.yamlEligible ?? ctx.yamlComponents.has(name);
22
+ const attrs = splitProps(props, excludeProps);
23
+ const useYaml = yamlEligible && shouldUseYaml(attrs, ctx);
24
+ const fence = pickDirectiveFence(useYaml ? body + "\n---" : body);
25
+ if (!useYaml) {
26
+ const attrStr = renderAttrs(attrs);
27
+ const opener = attrStr ? `${fence}${name}${attrStr}` : `${fence}${name}`;
28
+ return `${opener}\n${body}\n${fence}`;
29
+ }
30
+ // YAML body form — emit all props (including id, classes) as yaml keys
31
+ const yamlData = attrsToYaml(attrs);
32
+ const yaml = renderYaml(yamlData);
33
+ const header = yaml.length > 0 ? `---\n${yaml}\n---` : "";
34
+ if (!body) {
35
+ return `${fence}${name}\n${header}\n${fence}`;
36
+ }
37
+ return `${fence}${name}\n${header}\n${body}\n${fence}`;
38
+ }
39
+ /**
40
+ * Decide if a set of attributes warrants YAML body form.
41
+ */
42
+ function shouldUseYaml(attrs, ctx) {
43
+ const propCount = (attrs.id ? 1 : 0) +
44
+ (attrs.classes?.length ?? 0) +
45
+ Object.keys(attrs.props ?? {}).length;
46
+ if (propCount > ctx.yamlThreshold)
47
+ return true;
48
+ // Multi-line or complex string values force YAML
49
+ if (attrs.props) {
50
+ for (const value of Object.values(attrs.props)) {
51
+ if (typeof value === "string" && value.includes("\n"))
52
+ return true;
53
+ }
54
+ }
55
+ return false;
56
+ }
57
+ /**
58
+ * Convert RenderedAttrs back into a yaml-shaped object.
59
+ */
60
+ function attrsToYaml(attrs) {
61
+ const result = {};
62
+ if (attrs.id)
63
+ result.id = attrs.id;
64
+ if (attrs.classes && attrs.classes.length > 0) {
65
+ result.class = attrs.classes.join(" ");
66
+ }
67
+ if (attrs.props) {
68
+ for (const [key, value] of Object.entries(attrs.props)) {
69
+ if (value === undefined)
70
+ continue;
71
+ result[key] = value;
72
+ }
73
+ }
74
+ return result;
75
+ }
76
+ //# sourceMappingURL=directives.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"directives.js","sourceRoot":"","sources":["../src/directives.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,42 @@
1
+ /**
2
+ * Escape helpers for Dogsbay Markdown output.
3
+ *
4
+ * Two rules drive everything here:
5
+ * 1. Content must round-trip through a markdown-it parser cleanly.
6
+ * 2. When ambiguous, prefer escaping — a reader never sees broken syntax.
7
+ */
8
+ /**
9
+ * Escape markdown-active characters in text content.
10
+ * Only escapes what would change parsing; leaves everything else alone.
11
+ */
12
+ export declare function escapeText(text: string): string;
13
+ /**
14
+ * Escape text that appears inside an attribute `{...}` block.
15
+ * Double-quotes already handled by escapeAttrValue; this is for bareword values.
16
+ */
17
+ export declare function escapeAttrBareword(text: string): string;
18
+ /**
19
+ * Pick a code fence delimiter that doesn't collide with the content.
20
+ * Returns the shortest fence longer than any backtick/tilde run in the content.
21
+ *
22
+ * @param content - code to be fenced
23
+ * @param preferredChar - backtick or tilde; defaults to backtick
24
+ * @returns fence string (e.g. "```", "````", "~~~~~")
25
+ */
26
+ export declare function pickCodeFence(content: string, preferredChar?: "`" | "~"): string;
27
+ /**
28
+ * Pick a container directive fence of colons that doesn't collide with content.
29
+ * Minimum is 3 colons (`:::`); scales up when content contains longer runs.
30
+ */
31
+ export declare function pickDirectiveFence(content: string): string;
32
+ /**
33
+ * Indent every non-empty line of `content` by `spaces`.
34
+ * Preserves blank lines untouched.
35
+ */
36
+ export declare function indent(content: string, spaces: number): string;
37
+ /**
38
+ * Normalize trailing whitespace: ensure single trailing newline, strip
39
+ * more than two consecutive blank lines.
40
+ */
41
+ export declare function normalizeTrailingWhitespace(content: string): string;
42
+ //# sourceMappingURL=escape.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"escape.d.ts","sourceRoot":"","sources":["../src/escape.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH;;;GAGG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAI/C;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAMvD;AAED;;;;;;;GAOG;AACH,wBAAgB,aAAa,CAC3B,OAAO,EAAE,MAAM,EACf,aAAa,GAAE,GAAG,GAAG,GAAS,GAC7B,MAAM,CAOR;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAO1D;AAED;;;GAGG;AACH,wBAAgB,MAAM,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAM9D;AAED;;;GAGG;AACH,wBAAgB,2BAA2B,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAKnE"}
package/dist/escape.js ADDED
@@ -0,0 +1,79 @@
1
+ /**
2
+ * Escape helpers for Dogsbay Markdown output.
3
+ *
4
+ * Two rules drive everything here:
5
+ * 1. Content must round-trip through a markdown-it parser cleanly.
6
+ * 2. When ambiguous, prefer escaping — a reader never sees broken syntax.
7
+ */
8
+ /**
9
+ * Escape markdown-active characters in text content.
10
+ * Only escapes what would change parsing; leaves everything else alone.
11
+ */
12
+ export function escapeText(text) {
13
+ return text
14
+ .replace(/\\/g, "\\\\")
15
+ .replace(/([*_`~[\]()<>#|{}])/g, "\\$1");
16
+ }
17
+ /**
18
+ * Escape text that appears inside an attribute `{...}` block.
19
+ * Double-quotes already handled by escapeAttrValue; this is for bareword values.
20
+ */
21
+ export function escapeAttrBareword(text) {
22
+ // Barewords must not contain whitespace, quotes, or braces.
23
+ if (/[\s"'{}]/.test(text)) {
24
+ return `"${text.replace(/\\/g, "\\\\").replace(/"/g, '\\"')}"`;
25
+ }
26
+ return text;
27
+ }
28
+ /**
29
+ * Pick a code fence delimiter that doesn't collide with the content.
30
+ * Returns the shortest fence longer than any backtick/tilde run in the content.
31
+ *
32
+ * @param content - code to be fenced
33
+ * @param preferredChar - backtick or tilde; defaults to backtick
34
+ * @returns fence string (e.g. "```", "````", "~~~~~")
35
+ */
36
+ export function pickCodeFence(content, preferredChar = "`") {
37
+ const pattern = new RegExp(`${preferredChar === "`" ? "`" : "~"}{3,}`, "g");
38
+ let maxRun = 2;
39
+ for (const match of content.matchAll(pattern)) {
40
+ if (match[0].length > maxRun)
41
+ maxRun = match[0].length;
42
+ }
43
+ return preferredChar.repeat(maxRun + 1);
44
+ }
45
+ /**
46
+ * Pick a container directive fence of colons that doesn't collide with content.
47
+ * Minimum is 3 colons (`:::`); scales up when content contains longer runs.
48
+ */
49
+ export function pickDirectiveFence(content) {
50
+ const pattern = /:{3,}/g;
51
+ let maxRun = 2;
52
+ for (const match of content.matchAll(pattern)) {
53
+ if (match[0].length > maxRun)
54
+ maxRun = match[0].length;
55
+ }
56
+ return ":".repeat(maxRun + 1);
57
+ }
58
+ /**
59
+ * Indent every non-empty line of `content` by `spaces`.
60
+ * Preserves blank lines untouched.
61
+ */
62
+ export function indent(content, spaces) {
63
+ const pad = " ".repeat(spaces);
64
+ return content
65
+ .split("\n")
66
+ .map((line) => (line.length > 0 ? pad + line : line))
67
+ .join("\n");
68
+ }
69
+ /**
70
+ * Normalize trailing whitespace: ensure single trailing newline, strip
71
+ * more than two consecutive blank lines.
72
+ */
73
+ export function normalizeTrailingWhitespace(content) {
74
+ return content
75
+ .replace(/\n{3,}/g, "\n\n")
76
+ .replace(/[ \t]+$/gm, "")
77
+ .replace(/\s*$/, "\n");
78
+ }
79
+ //# sourceMappingURL=escape.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"escape.js","sourceRoot":"","sources":["../src/escape.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH;;;GAGG;AACH,MAAM,UAAU,UAAU,CAAC,IAAY;IACrC,OAAO,IAAI;SACR,OAAO,CAAC,KAAK,EAAE,MAAM,CAAC;SACtB,OAAO,CAAC,sBAAsB,EAAE,MAAM,CAAC,CAAC;AAC7C,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,kBAAkB,CAAC,IAAY;IAC7C,4DAA4D;IAC5D,IAAI,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;QAC1B,OAAO,IAAI,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,KAAK,CAAC,GAAG,CAAC;IACjE,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,aAAa,CAC3B,OAAe,EACf,gBAA2B,GAAG;IAE9B,MAAM,OAAO,GAAG,IAAI,MAAM,CAAC,GAAG,aAAa,KAAK,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,MAAM,EAAE,GAAG,CAAC,CAAC;IAC5E,IAAI,MAAM,GAAG,CAAC,CAAC;IACf,KAAK,MAAM,KAAK,IAAI,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC;QAC9C,IAAI,KAAK,CAAC,CAAC,CAAC,CAAC,MAAM,GAAG,MAAM;YAAE,MAAM,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC;IACzD,CAAC;IACD,OAAO,aAAa,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;AAC1C,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,kBAAkB,CAAC,OAAe;IAChD,MAAM,OAAO,GAAG,QAAQ,CAAC;IACzB,IAAI,MAAM,GAAG,CAAC,CAAC;IACf,KAAK,MAAM,KAAK,IAAI,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC;QAC9C,IAAI,KAAK,CAAC,CAAC,CAAC,CAAC,MAAM,GAAG,MAAM;YAAE,MAAM,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC;IACzD,CAAC;IACD,OAAO,GAAG,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;AAChC,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,MAAM,CAAC,OAAe,EAAE,MAAc;IACpD,MAAM,GAAG,GAAG,GAAG,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;IAC/B,OAAO,OAAO;SACX,KAAK,CAAC,IAAI,CAAC;SACX,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;SACpD,IAAI,CAAC,IAAI,CAAC,CAAC;AAChB,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,2BAA2B,CAAC,OAAe;IACzD,OAAO,OAAO;SACX,OAAO,CAAC,SAAS,EAAE,MAAM,CAAC;SAC1B,OAAO,CAAC,WAAW,EAAE,EAAE,CAAC;SACxB,OAAO,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;AAC3B,CAAC"}
@@ -0,0 +1,10 @@
1
+ export { treeToDogsbayMd, nodeToDogsbayMd } from "./serialize.js";
2
+ export type { SerializeOptions } from "./types.js";
3
+ export { inlineToDogsbayMd } from "./inline.js";
4
+ export { dogsbayMdToTree, parseInline } from "./parse.js";
5
+ export type { ParseResult, ParseOptions } from "./parse.js";
6
+ export { buildNavFromDirectory } from "./nav.js";
7
+ export type { BuildNavOptions } from "./nav.js";
8
+ export { loadNavFile } from "./nav-file.js";
9
+ export type { NavFile, NavFileItem, LoadNavFileOptions } from "./nav-file.js";
10
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +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,EAAE,OAAO,EAAE,WAAW,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,10 @@
1
+ // Dogsbay Markdown dialect — canonical format for TreeNode[].
2
+ //
3
+ // Spec: research/formats/dogsbay-markdown-spec.md
4
+ // Plan: plans/format-dogsbay-md.md
5
+ export { treeToDogsbayMd, nodeToDogsbayMd } from "./serialize.js";
6
+ export { inlineToDogsbayMd } from "./inline.js";
7
+ export { dogsbayMdToTree, parseInline } from "./parse.js";
8
+ export { buildNavFromDirectory } from "./nav.js";
9
+ export { loadNavFile } from "./nav-file.js";
10
+ //# sourceMappingURL=index.js.map
@@ -0,0 +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"}
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Inline serialization — InlineNode[] → markdown text with inline formatting.
3
+ */
4
+ import type { InlineNode } from "@dogsbay/types";
5
+ /**
6
+ * Serialize a flat array of inline nodes to markdown.
7
+ */
8
+ export declare function inlineToDogsbayMd(nodes: InlineNode[] | undefined): string;
9
+ //# sourceMappingURL=inline.d.ts.map
@@ -0,0 +1 @@
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;AAG3D;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,UAAU,EAAE,GAAG,SAAS,GAAG,MAAM,CAGzE"}