@dogsbay/format-dogsbay-md 0.2.0-beta.140 → 0.2.0-beta.142

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/browser.d.ts CHANGED
@@ -15,6 +15,7 @@ export { dogsbayMdToTree, parseInline, containerOpenBefore, type ParseResult, ty
15
15
  export { KNOWN_INLINE_DIRECTIVES, type ParseDiagnostic } from "./diagnostics.js";
16
16
  export { KNOWN_BLOCK_DIRECTIVES, LEAF_ONLY_DIRECTIVES, BLOCK_LEAF_DIRECTIVES } from "./plugin-containers.js";
17
17
  export { treeToDogsbayMd, nodeToDogsbayMd } from "./serialize.js";
18
+ export { DIRECTIVE_PROPS, PASSTHROUGH_PROP, unknownProps } from "./directive-props.js";
18
19
  export type { SerializeOptions } from "./types.js";
19
20
  export { inlineToDogsbayMd } from "./inline.js";
20
21
  export { transformCodeRegions, transformProseLines, transformProseSegments, fenceOpenBefore, createFenceTracker, } from "./code-regions.js";
package/dist/browser.js CHANGED
@@ -16,6 +16,8 @@ export { KNOWN_INLINE_DIRECTIVES } from "./diagnostics.js";
16
16
  // The `:::name` blocks the parser knows (an editor completes names from it)
17
17
  export { KNOWN_BLOCK_DIRECTIVES, LEAF_ONLY_DIRECTIVES, BLOCK_LEAF_DIRECTIVES } from "./plugin-containers.js";
18
18
  export { treeToDogsbayMd, nodeToDogsbayMd } from "./serialize.js";
19
+ // The props each known directive draws (an editor completes prop names from it)
20
+ export { DIRECTIVE_PROPS, PASSTHROUGH_PROP, unknownProps } from "./directive-props.js";
19
21
  export { inlineToDogsbayMd } from "./inline.js";
20
22
  export { transformCodeRegions, transformProseLines, transformProseSegments, fenceOpenBefore, createFenceTracker, } from "./code-regions.js";
21
23
  export { maskMinjaInCode, unmaskMinjaInCode, maskAllMinjaOpeners, isMinjaProcessedFence, stripInlineMinjaMarkers, stripFenceMinjaMarkers } from "./minja-mask.js";
@@ -2,7 +2,7 @@ export interface ParseDiagnostic {
2
2
  /** 1-based line in the source (front matter counted). */
3
3
  line: number;
4
4
  /** Stable kind, for filtering. */
5
- code: "unclosed-container" | "stray-closer" | "unknown-container" | "unknown-inline" | "block-directive-inline" | "bad-attributes" | "closer-mismatch" | "dropped-attributes" | "missing-label" | "leaf-as-block" | "nesting-unchecked" | "unknown-prop";
5
+ code: "unclosed-container" | "stray-closer" | "unknown-container" | "unknown-inline" | "block-directive-inline" | "bad-attributes" | "closer-mismatch" | "dropped-attributes" | "missing-label" | "leaf-as-block" | "nesting-unchecked" | "unknown-prop" | "props-yaml";
6
6
  message: string;
7
7
  /**
8
8
  * The directive's name, without colons, on `unknown-container` and `unknown-inline`: a host that
package/dist/parse.js CHANGED
@@ -100,7 +100,18 @@ export function dogsbayMdToTree(source, options) {
100
100
  attachTableAttrsRow(tokens, content);
101
101
  // Before tokensToTree: it changes nothing these read, but read the parse as markdown-it left it
102
102
  // A lone-CR source never gets here with diagnostics (see the top), so `lineOf` is set
103
- const diagnostics = options?.diagnostics ? collectDiagnostics(tokens, content.split(/\r\n|\n/), lineOf ?? (() => undefined)) : undefined;
103
+ let diagnostics = options?.diagnostics ? collectDiagnostics(tokens, content.split(/\r\n|\n/), lineOf ?? (() => undefined)) : undefined;
104
+ if (diagnostics && lineOf && yamlLifted.badProps.length) {
105
+ for (const bad of yamlLifted.badProps) {
106
+ // The line YAML stops at, mapped itself: protected directives can add or stash lines in
107
+ // the block, and an unlifted block's lines go to the output one for one
108
+ const line = lineOf(bad.line0 + bad.offset);
109
+ if (line === undefined)
110
+ continue;
111
+ diagnostics.push({ line, code: "props-yaml", message: `This reads like a props block, but its YAML does not load (line ${line}: ${bad.message}), so it is read as a rule and text` });
112
+ }
113
+ diagnostics = diagnostics.sort((a, b) => a.line - b.line);
114
+ }
104
115
  let tree = foldRelated(tokensToTree(tokens, options?.sourceLines ? lineOf : undefined));
105
116
  if (directiveTable) {
106
117
  // `preserve` restores every construct as a first-class node. `resolve-first`
@@ -243,6 +254,7 @@ function preprocessYamlBodies(source) {
243
254
  const lines = source.split("\n");
244
255
  const out = [];
245
256
  const lineMap = [];
257
+ const badProps = [];
246
258
  // Which lines are fenced code: a `:::card` shown inside a ```markdown example is text, and the
247
259
  // lift must not read its `---` block (it rewrote a docs page's example, 2026-10-27).
248
260
  const fence = createFenceTracker();
@@ -284,12 +296,39 @@ function preprocessYamlBodies(source) {
284
296
  i = j + 1; // skip past the closing `---`
285
297
  continue;
286
298
  }
299
+ // Not lifted, but written as props whose YAML does not load: it stays a rule and text, and
300
+ // a diagnostic says why (the playground's editor highlights it as props)
301
+ const bad = j < lines.length && !fenced ? propsYamlError(lines, i + 2, j) : undefined;
302
+ if (bad)
303
+ badProps.push({ line0: out.length, offset: 2 + bad.line, message: bad.message });
287
304
  }
288
305
  out.push(line);
289
306
  lineMap.push(i);
290
307
  i++;
291
308
  }
292
- return { source: out.join("\n"), lineMap };
309
+ return { source: out.join("\n"), lineMap, badProps };
310
+ }
311
+ /**
312
+ * Why the text between a directive's `---` lines is meant as props but does not load: it opens
313
+ * with a prop-shaped, lower-case `key:` and holds no container line, and js-yaml refuses it. Anything else
314
+ * (a rule, then prose, then a rule) is not props and gets nothing.
315
+ */
316
+ function propsYamlError(lines, from, to) {
317
+ // Lower-case first, as props are: `Note: see [x` after a rule is prose
318
+ if (from >= to || !/^(?:[a-z_][\w.-]*|"[^"]*"|'[^']*'):(?:[ \t]|\r?$)/.test(lines[from]))
319
+ return undefined;
320
+ for (let k = from; k < to; k++)
321
+ if (CONTAINER_LINE.test(lines[k]))
322
+ return undefined;
323
+ try {
324
+ yaml.load(lines.slice(from, to).join("\n"));
325
+ return undefined;
326
+ }
327
+ catch (err) {
328
+ const e = err;
329
+ const line = Math.min(Math.max(e.mark?.line ?? 0, 0), to - from - 1);
330
+ return { line, message: e.reason ?? "it is not YAML" };
331
+ }
293
332
  }
294
333
  /**
295
334
  * Parse a single inline string to InlineNode[] (useful for testing).
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dogsbay/format-dogsbay-md",
3
- "version": "0.2.0-beta.140",
3
+ "version": "0.2.0-beta.142",
4
4
  "description": "Dogsbay Markdown dialect — canonical format for TreeNode[] with directives, YAML bodies, and intelligent fallbacks",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -40,10 +40,10 @@
40
40
  "markdown-it-footnote": "^4.0.0",
41
41
  "markdown-it-front-matter": "^0.2.4",
42
42
  "pele": "1.6.0",
43
- "@dogsbay/corpus": "0.2.0-beta.140",
44
- "@dogsbay/minja": "0.2.0-beta.140",
45
- "@dogsbay/types": "0.2.0-beta.140",
46
- "@dogsbay/serialize-core": "0.2.0-beta.140"
43
+ "@dogsbay/corpus": "0.2.0-beta.142",
44
+ "@dogsbay/minja": "0.2.0-beta.142",
45
+ "@dogsbay/types": "0.2.0-beta.142",
46
+ "@dogsbay/serialize-core": "0.2.0-beta.142"
47
47
  },
48
48
  "license": "MIT",
49
49
  "repository": {