@dogsbay/format-dogsbay-md 0.2.0-beta.138 → 0.2.0-beta.139

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.
@@ -8,9 +8,9 @@
8
8
  * here: the parser passes any leaf through as a node of that type, and only a
9
9
  * renderer knows whether it can draw it (render-html reports the ones it can't).
10
10
  */
11
- import { BLOCK_LEAF_DIRECTIVES, GENERIC_CONTAINER } from "./plugin-containers.js";
11
+ import { BLOCK_LEAF_DIRECTIVES, GENERIC_CONTAINER, LEAF_ONLY_DIRECTIVES } from "./plugin-containers.js";
12
12
  import { LABEL_PROP } from "./plugin-inline-directives.js";
13
- import { unknownProps } from "./directive-props.js";
13
+ import { DIRECTIVE_PROPS, unknownProps } from "./directive-props.js";
14
14
  import * as yaml from "js-yaml";
15
15
  /**
16
16
  * Whether a source line closes a container opened with `colons` colons. The
@@ -74,6 +74,24 @@ function codeLineSet(tokens) {
74
74
  export const KNOWN_INLINE_DIRECTIVES = new Set(["kbd", "icon", "math", "mark", "highlight", "button", "badge"]);
75
75
  /** Directives that are blocks: `::name{…}` draws one only on a line of its own (parse.ts mapContainerToTreeNode). */
76
76
  const BLOCK_DIRECTIVES = new Set(BLOCK_LEAF_DIRECTIVES);
77
+ /** Whether the text at `at` is in a code span on its line or escaped, so no directive token starts there. */
78
+ function notThisToken(text, at) {
79
+ if (at < 0)
80
+ return true;
81
+ if (text[at - 1] === "\\")
82
+ return true;
83
+ const lineStart = text.lastIndexOf("\n", at - 1) + 1;
84
+ return ((text.slice(lineStart, at).match(/`/g) ?? []).length % 2) === 1;
85
+ }
86
+ /** How to write a block directive that was given a `[label]`: its own name prop, and a closer when it has a body. */
87
+ function blockForm(tag) {
88
+ if (LEAF_ONLY_DIRECTIVES.includes(tag))
89
+ return `Write ::${tag}{…} on a line of its own`;
90
+ const props = DIRECTIVE_PROPS[tag] ?? [];
91
+ const key = (tag === "tab" || tag === "accordion-item") && props.includes("label") ? "label" : props.includes("title") ? "title" : props.includes("label") ? "label" : undefined;
92
+ const form = `Write :::${tag}${key ? `{${key}="…"}` : "{…}"}, its content, then a ::: closer`;
93
+ return tag === "tab" ? `${form} (inside :::tabs), or a definition list: the term is the tab's name` : form;
94
+ }
77
95
  /** Inline tokens markdown-it-attrs can give attributes to that the parser has no field for (links and images keep theirs). */
78
96
  const ATTRLESS_INLINE = { strong_open: "bold text", em_open: "italic text", s_open: "struck-through text", code_inline: "inline code" };
79
97
  /**
@@ -256,12 +274,31 @@ export function collectDiagnostics(tokens, lines, lineOf) {
256
274
  if (child.type === "dogsbay_inline_directive_open" && child.meta?.labelless)
257
275
  continue;
258
276
  const form = child.type === "dogsbay_leaf_directive" ? `::${child.tag}` : `:${child.tag}[`;
259
- const at = text.indexOf(form, from);
277
+ let at = text.indexOf(form, from);
278
+ // `::tab[Helm]` starting a line of a paragraph (not a table cell): text because of its
279
+ // `[label]`, which a block takes none of. A `::tab` the search met first in a code span
280
+ // or escaped is not this token, so the line start wins over it.
281
+ let labelled = false;
282
+ if (child.type === "dogsbay_leaf_directive" && BLOCK_DIRECTIVES.has(child.tag) && tok.map) {
283
+ const m = new RegExp(`(^|\\n)[ \\t]*::${child.tag}\\[`, "g");
284
+ m.lastIndex = from;
285
+ const hit = m.exec(text);
286
+ const pos = hit ? hit.index + hit[0].indexOf("::") : -1;
287
+ if (pos >= 0 && (pos === at || notThisToken(text, at))) {
288
+ at = pos;
289
+ labelled = true;
290
+ }
291
+ }
260
292
  from = at >= 0 ? at + form.length : from;
261
293
  const offset = at >= 0 ? (text.slice(0, at).match(/\n/g) ?? []).length : 0;
262
294
  const shown = child.type === "dogsbay_leaf_directive" ? `::${child.tag}` : `:${child.tag}[…]`;
263
295
  if (child.type === "dogsbay_leaf_directive" && BLOCK_DIRECTIVES.has(child.tag)) {
264
- add(base + offset, "block-directive-inline", `${shown} is a block directive — inside a line of text it is shown as text; put it on a line of its own`);
296
+ if (labelled) {
297
+ add(base + offset, "block-directive-inline", `${shown}[…] is shown as text: a block directive takes no [label]. ${blockForm(child.tag)}`);
298
+ }
299
+ else {
300
+ add(base + offset, "block-directive-inline", `${shown} is a block directive — inside a line of text it is shown as text; put it on a line of its own`);
301
+ }
265
302
  }
266
303
  else {
267
304
  add(base + offset, "unknown-inline", `${shown} is not a known inline directive — it is shown as text`, child.tag);
package/dist/serialize.js CHANGED
@@ -948,7 +948,7 @@ function termLabel(text) {
948
948
  .replace(/\{/g, "\\{");
949
949
  }
950
950
  function renderTabItem(node, ctx) {
951
- const label = termLabel(String(node.props?.label ?? node.props?.title ?? "Tab"));
951
+ const label = termLabel(String(node.props?.label ?? node.props?.title ?? node.props?.value ?? "Tab"));
952
952
  const content = (node.children ?? []).map((c) => renderNode(c, ctx)).join("\n\n");
953
953
  // Definition list: term on one line, `: body` with continuation indented
954
954
  const [first, ...rest] = content.split("\n");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dogsbay/format-dogsbay-md",
3
- "version": "0.2.0-beta.138",
3
+ "version": "0.2.0-beta.139",
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.138",
44
- "@dogsbay/minja": "0.2.0-beta.138",
45
- "@dogsbay/serialize-core": "0.2.0-beta.138",
46
- "@dogsbay/types": "0.2.0-beta.138"
43
+ "@dogsbay/corpus": "0.2.0-beta.139",
44
+ "@dogsbay/minja": "0.2.0-beta.139",
45
+ "@dogsbay/serialize-core": "0.2.0-beta.139",
46
+ "@dogsbay/types": "0.2.0-beta.139"
47
47
  },
48
48
  "license": "MIT",
49
49
  "repository": {