@dogsbay/serialize-core 0.2.0-beta.128 → 0.2.0-beta.130

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/index.d.ts CHANGED
@@ -16,7 +16,7 @@
16
16
  * Plus format-agnostic text helpers (`text.ts`) and an unknown-node fallback
17
17
  * that reports instead of silently dropping (`unknown.ts`).
18
18
  */
19
- export { leafInline, leafHtml, hasInline, hasContent, codeText, codeLang, tabTitle, tabValue, cardFields, cardBodySources, headingLevel, headingText, headingFragment, slugifyHeadingText, calloutVariant, calloutTitle, listStart, mediaSrc, renderLeaf, type CardFields, } from "./reads.js";
19
+ export { leafInline, leafHtml, hasInline, hasContent, codeText, codeLang, tabTitle, tabValue, cardFields, cardBodySources, headingLevel, headingText, headingFragment, slugifyHeadingText, calloutVariant, calloutTitle, stepLead, stepTitle, listStart, mediaSrc, renderLeaf, type CardFields, } from "./reads.js";
20
20
  export { walkInline, applyTextFlags, inlinePlainText, markdownInlineEmitters, htmlInlineEmitters, escapeHtml, escapeAttr, codeSpan, type InlineContext, type InlineEmitters, type InlineWalkOptions, } from "./inline.js";
21
21
  export { ExportLedger, formatLedgerReport, formatCapabilityTable, unsupportedFeatures, validateCapabilities, validateLedgerAgainstCapabilities, type SupportLevel, type CapabilityDeclaration, type LossAction, type ExportLedgerEntry, type LedgerSummaryRow, } from "./capability.js";
22
22
  export { MATRIX_ROWS, formatCapabilityMatrix, missingMatrixCells, splitGroupChildren, renderAroundGroup, isDetailsSheet, type MatrixRow, type MatrixGroup, type MatrixColumn } from "./matrix.js";
package/dist/index.js CHANGED
@@ -16,7 +16,7 @@
16
16
  * Plus format-agnostic text helpers (`text.ts`) and an unknown-node fallback
17
17
  * that reports instead of silently dropping (`unknown.ts`).
18
18
  */
19
- export { leafInline, leafHtml, hasInline, hasContent, codeText, codeLang, tabTitle, tabValue, cardFields, cardBodySources, headingLevel, headingText, headingFragment, slugifyHeadingText, calloutVariant, calloutTitle, listStart, mediaSrc, renderLeaf, } from "./reads.js";
19
+ export { leafInline, leafHtml, hasInline, hasContent, codeText, codeLang, tabTitle, tabValue, cardFields, cardBodySources, headingLevel, headingText, headingFragment, slugifyHeadingText, calloutVariant, calloutTitle, stepLead, stepTitle, listStart, mediaSrc, renderLeaf, } from "./reads.js";
20
20
  export { walkInline, applyTextFlags, inlinePlainText, markdownInlineEmitters, htmlInlineEmitters, escapeHtml, escapeAttr, codeSpan, } from "./inline.js";
21
21
  export { ExportLedger, formatLedgerReport, formatCapabilityTable, unsupportedFeatures, validateCapabilities, validateLedgerAgainstCapabilities, } from "./capability.js";
22
22
  export { MATRIX_ROWS, formatCapabilityMatrix, missingMatrixCells, splitGroupChildren, renderAroundGroup, isDetailsSheet } from "./matrix.js";
package/dist/reads.d.ts CHANGED
@@ -139,6 +139,28 @@ export declare function calloutVariant(node: TreeNode, fallback?: string): strin
139
139
  * "deliberately untitled" from "absent".
140
140
  */
141
141
  export declare function calloutTitle(node: TreeNode): string | undefined;
142
+ /**
143
+ * A step's `title` prop to draw as its lead (Mintlify/MDX `<Step title="…">`), or undefined.
144
+ * The dogsbay-md parser never sets it (a step's title is its own first line); an importer that
145
+ * also writes the title into the content (format-mdx's Steps parser adds `<strong>title</strong>`)
146
+ * is not drawn twice: a title the step's text already starts with is skipped.
147
+ */
148
+ export declare function stepTitle(node: TreeNode): string | undefined;
149
+ /**
150
+ * A step's title written as its leading bold run on a line of its own, split from the detail:
151
+ * `1. **Stop the writer**` then `Run …` on the next line is ONE paragraph to Markdown, so every
152
+ * renderer drew the title and the detail on one line. The documents skill teaches that form, and
153
+ * it is what Mintlify's `<Step title>` imports as. The line end is what decides it: the
154
+ * dogsbay-md parser marks bold that ends its line (`lineEnd`), and a hard break counts too. So
155
+ * `1. **Click** Save.` and `**Optional:** configure X` stay one line. The bold run is bold text
156
+ * and links whose text is all bold. The title's nodes lose `bold` (the renderer wraps them in
157
+ * its title element) and `lineEnd`; the detail loses a leading break and leading space.
158
+ * Undefined when the step does not start with such a run, or is only the bold text.
159
+ */
160
+ export declare function stepLead(inline: InlineNode[] | undefined): {
161
+ title: InlineNode[];
162
+ rest: InlineNode[];
163
+ } | undefined;
142
164
  /** An ordered list's start number, or undefined when it starts at 1. */
143
165
  export declare function listStart(node: TreeNode): number | undefined;
144
166
  /** An image/media source, tolerating `props.src` and `props.url`. */
package/dist/reads.js CHANGED
@@ -211,6 +211,84 @@ export function calloutTitle(node) {
211
211
  // title back — so the empty string is preserved and only absence is undefined.
212
212
  return typeof title === "string" ? title : undefined;
213
213
  }
214
+ /**
215
+ * A step's `title` prop to draw as its lead (Mintlify/MDX `<Step title="…">`), or undefined.
216
+ * The dogsbay-md parser never sets it (a step's title is its own first line); an importer that
217
+ * also writes the title into the content (format-mdx's Steps parser adds `<strong>title</strong>`)
218
+ * is not drawn twice: a title the step's text already starts with is skipped.
219
+ */
220
+ export function stepTitle(node) {
221
+ const title = typeof node.props?.title === "string" ? node.props.title.trim() : "";
222
+ if (!title)
223
+ return undefined;
224
+ const first = node.inline?.length ? node.inline : undefined;
225
+ const firstChild = node.children?.[0];
226
+ const text = (nodes) => (nodes ?? []).map((n) => ("text" in n && typeof n.text === "string" ? n.text : "children" in n && Array.isArray(n.children) ? text(n.children) : "")).join("");
227
+ const html = firstChild && !first ? leafHtml(firstChild) : undefined;
228
+ const lead = (first ? text(first)
229
+ : html !== undefined ? decodeEntities(html.replace(/<[^>]*>/g, ""))
230
+ : firstChild ? text(leafInline(firstChild))
231
+ : "").trim();
232
+ // The whole title, then the end of the lead or a non-word character: "A" is not in "Apple pie"
233
+ return lead.startsWith(title) && !/^[\p{L}\p{N}_]/u.test(lead.slice(title.length)) ? undefined : title;
234
+ }
235
+ /**
236
+ * A step's title written as its leading bold run on a line of its own, split from the detail:
237
+ * `1. **Stop the writer**` then `Run …` on the next line is ONE paragraph to Markdown, so every
238
+ * renderer drew the title and the detail on one line. The documents skill teaches that form, and
239
+ * it is what Mintlify's `<Step title>` imports as. The line end is what decides it: the
240
+ * dogsbay-md parser marks bold that ends its line (`lineEnd`), and a hard break counts too. So
241
+ * `1. **Click** Save.` and `**Optional:** configure X` stay one line. The bold run is bold text
242
+ * and links whose text is all bold. The title's nodes lose `bold` (the renderer wraps them in
243
+ * its title element) and `lineEnd`; the detail loses a leading break and leading space.
244
+ * Undefined when the step does not start with such a run, or is only the bold text.
245
+ */
246
+ export function stepLead(inline) {
247
+ if (!inline?.length)
248
+ return undefined;
249
+ const textOf = (n) => ("text" in n && typeof n.text === "string" ? n.text : undefined);
250
+ const flag = (n, k) => n[k] === true;
251
+ const bold = (n) => {
252
+ if (n.type === "link") {
253
+ const texts = n.children.filter((c) => c.type === "text");
254
+ return texts.length > 0 && texts.every((c) => flag(c, "bold"));
255
+ }
256
+ return flag(n, "bold");
257
+ };
258
+ let i = 0;
259
+ while (i < inline.length && textOf(inline[i]) === "" && !bold(inline[i]))
260
+ i++;
261
+ const start = i;
262
+ while (i < inline.length && bold(inline[i]))
263
+ i++;
264
+ if (i === start)
265
+ return undefined;
266
+ let j = i;
267
+ while (j < inline.length && textOf(inline[j]) === "")
268
+ j++;
269
+ const hardBreak = inline[j]?.type === "break";
270
+ if (!flag(inline[i - 1], "lineEnd") && !hardBreak)
271
+ return undefined;
272
+ const plain = (n) => n.type === "link"
273
+ ? { ...n, lineEnd: undefined, children: n.children.map((c) => ({ ...c, bold: undefined })) }
274
+ : { ...n, bold: undefined, lineEnd: undefined };
275
+ const title = inline.slice(start, i).map(plain);
276
+ const rest = inline.slice(hardBreak ? j + 1 : i);
277
+ const first = rest[0] && textOf(rest[0]);
278
+ if (first !== undefined)
279
+ rest[0] = { ...rest[0], text: first.replace(/^\s+/, "") };
280
+ if (!rest.some((n) => textOf(n) !== ""))
281
+ return undefined;
282
+ return { title, rest };
283
+ }
284
+ /** The five XML entities and numeric references, for comparing an html lead with a title. */
285
+ function decodeEntities(s) {
286
+ return s
287
+ .replace(/&#(\d+);/g, (_, d) => String.fromCodePoint(Number(d)))
288
+ .replace(/&#x([0-9a-f]+);/gi, (_, h) => String.fromCodePoint(parseInt(h, 16)))
289
+ .replace(/&lt;/g, "<").replace(/&gt;/g, ">").replace(/&quot;/g, '"').replace(/&#39;|&apos;/g, "'")
290
+ .replace(/&amp;/g, "&");
291
+ }
214
292
  /** An ordered list's start number, or undefined when it starts at 1. */
215
293
  export function listStart(node) {
216
294
  const raw = node.props?.start;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dogsbay/serialize-core",
3
- "version": "0.2.0-beta.128",
3
+ "version": "0.2.0-beta.130",
4
4
  "description": "Shared serializer core — shape-tolerant TreeNode reads, a generic inline walker, fence/indent utilities, and the export capability ledger every format exporter builds on",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -22,7 +22,7 @@
22
22
  },
23
23
  "license": "MIT",
24
24
  "dependencies": {
25
- "@dogsbay/types": "0.2.0-beta.128"
25
+ "@dogsbay/types": "0.2.0-beta.130"
26
26
  },
27
27
  "repository": {
28
28
  "type": "git",