@dogsbay/format-astro 0.2.0-beta.129 → 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.
@@ -9,9 +9,8 @@ export const ASTRO_CAPABILITIES = [
9
9
  { feature: "table", support: "full", rendersAs: "`<Table>` (block content in cells; caption prop or slot)" },
10
10
  {
11
11
  feature: "code",
12
- support: "partial",
13
- rendersAs: "`<CodeBlock>`, or `<CodeRich>` with line numbers / highlights / diff / `[!code]` notation",
14
- note: "Title, language, highlights, line numbers, diff marks and copyText survive. The `collapse` fence option is consumed and not emitted: the block renders expanded, unrecorded.",
12
+ support: "full",
13
+ rendersAs: "`<CodeBlock>`, or `<CodeRich>` with line numbers / highlights / diff / `[!code]` notation / `collapse` (line runs behind a toggle)",
15
14
  },
16
15
  { feature: "math-block", support: "full", rendersAs: "`<MathKatex display>` (KaTeX at build time)" },
17
16
  { feature: "deflist", support: "full", rendersAs: "`<dl><dt><dd>`" },
@@ -34,12 +33,7 @@ export const ASTRO_CAPABILITIES = [
34
33
  { feature: "tabs-variant", support: "full", rendersAs: "TabsList/TabsTrigger given the variant's classes (TAB_VARIANTS), merged over their base" },
35
34
  { feature: "tone", support: "full", rendersAs: "each card's border and tint from the tone (CARD_TONE_CLASSES); a group tone applies to every card without one" },
36
35
  { feature: "tabs", support: "full", rendersAs: "`<Tabs>` / `<TabsTrigger>` / `<TabsContent>` (`<db-tabs>`), sync keys kept" },
37
- {
38
- feature: "steps",
39
- support: "partial",
40
- rendersAs: "`<Steps>` / `<Step>` / `<SubSteps>`",
41
- note: "A step's body renders; a `title` PROP on a step is not emitted (titles carried in the step's own content, as dogsbay-md writes them, survive).",
42
- },
36
+ { feature: "steps", support: "full", rendersAs: "`<Steps>` / `<Step>` / `<SubSteps>`; a step's `title` prop (Mintlify `<Step title>`) leads it in bold" },
43
37
  {
44
38
  feature: "accordion",
45
39
  support: "full",
@@ -48,15 +42,10 @@ export const ASTRO_CAPABILITIES = [
48
42
  {
49
43
  feature: "cards",
50
44
  support: "partial",
51
- rendersAs: "`<Grid>` of `<Card>`",
52
- note: "The grid is always `cols={[1, 2]}`: a `cols` prop is ignored. When the group has `card` children, any non-card child is dropped; in the MkDocs list form, non-list children are dropped and a list item whose content is inline (a tight list) renders an EMPTY card.",
53
- },
54
- {
55
- feature: "card",
56
- support: "partial",
57
- rendersAs: "`<Card>` with title, description, body and optional link",
58
- note: "Outside a card group, an icon that is an image PATH is passed to `<Icon name>`, which renders nothing for it — the logo disappears (inside a group it becomes an `<img>`).",
45
+ rendersAs: "`<Grid>` of `<Card>`; `cols` (1–6) is one column on a phone and up to `cols` wider, as render-html",
46
+ note: "When the group has `card` children, any non-card child is dropped; in the MkDocs list form, non-list children are dropped and a list item whose content is inline (a tight list) renders an EMPTY card.",
59
47
  },
48
+ { feature: "card", support: "full", rendersAs: "`<Card>` with title, description, body, optional link, and an icon NAME (`<Icon>`) or image PATH (`<img>`)" },
60
49
  { feature: "link-card", support: "full", rendersAs: "`<LinkCard>`; with body content, a linked `<Card>`" },
61
50
  { feature: "files", support: "full", rendersAs: "`<FileTree items>`, folders from nesting or a trailing `/`" },
62
51
  { feature: "grid", support: "full", rendersAs: "`<Grid cols gap rows>` / `<GridItem>`" },
package/dist/serialize.js CHANGED
@@ -1,4 +1,4 @@
1
- import { walkInline, applyTextFlags, renderLeaf, indent, isSafeHref, apiPageLayout, apiSymbolLevels, renderAroundGroup, isDetailsSheet, } from "@dogsbay/serialize-core";
1
+ import { walkInline, applyTextFlags, renderLeaf, indent, isSafeHref, apiPageLayout, apiSymbolLevels, renderAroundGroup, isDetailsSheet, stepLead, stepTitle, } from "@dogsbay/serialize-core";
2
2
  import { parseInline } from "@dogsbay/format-dogsbay-md";
3
3
  import { decorateDiff, hasDiffMarks } from "./diff-decoration.js";
4
4
  import { TAB_GLYPH, tabDiffSignal } from "@dogsbay/render-html/diff";
@@ -367,9 +367,16 @@ function nodeToAstroBase(node, ctx) {
367
367
  case "steps":
368
368
  ctx.imports.add("steps");
369
369
  return `<Steps>\n${childrenToAstro(node, ctx)}\n</Steps>`;
370
- case "step":
370
+ case "step": {
371
371
  ctx.imports.add("steps");
372
- return `<Step>\n${leafContent(node, ctx)}\n</Step>`;
372
+ // A `title` prop (Mintlify `<Step title>`) leads the step in bold, as render-html draws it
373
+ // The title on its own line (Steps.astro: `.step-title` is a block): from the prop, or the
374
+ // step's leading bold run (stepLead), which Markdown otherwise runs into the detail
375
+ const title = stepTitle(node);
376
+ const split = title ? undefined : stepLead(node.inline);
377
+ const lead = title ? `<strong class="step-title">${escapeTemplate(title)}</strong>\n` : split ? `<strong class="step-title">${renderInline(split.title, ctx)}</strong>\n` : "";
378
+ return `<Step>\n${lead}${leafContent(split ? { ...node, inline: split.rest } : node, ctx)}\n</Step>`;
379
+ }
373
380
  case "substeps":
374
381
  ctx.imports.add("substeps");
375
382
  ctx.imports.add("steps");
@@ -738,7 +745,9 @@ function codeToAstro(node, ctx, figure) {
738
745
  const copyText = node.props?.copyText;
739
746
  const diffAdd = lineSpec(node.props?.diffAdd, node.props?.ins);
740
747
  const diffRemove = lineSpec(node.props?.diffRemove, node.props?.del);
741
- const isRich = lineNumbers || highlights || code.includes("[!code") || Boolean(diffAdd || diffRemove);
748
+ // Expressive Code's `collapse`: line runs folded behind a toggle (`{2-4, 9}` or `2-4,9`)
749
+ const collapse = lineSpec(node.props?.collapse)?.replace(/[{}\s]/g, "") || undefined;
750
+ const isRich = lineNumbers || highlights || code.includes("[!code") || Boolean(diffAdd || diffRemove) || Boolean(collapse);
742
751
  const classAttr = mergeClassAttr(figure?.classes ?? "", node.props?.class);
743
752
  const figureAttrs = figure?.attrs ?? "";
744
753
  // The component with its caption slot filled, or self-closing
@@ -763,6 +772,8 @@ function codeToAstro(node, ctx, figure) {
763
772
  attrs.push(`diffAdd="${escapeAttr(diffAdd)}"`);
764
773
  if (diffRemove)
765
774
  attrs.push(`diffRemove="${escapeAttr(diffRemove)}"`);
775
+ if (collapse)
776
+ attrs.push(`collapse="${escapeAttr(collapse)}"`);
766
777
  return close("CodeRich", `<CodeRich ${attrs.join(" ")}${classAttr}${passthrough}${figureAttrs}`);
767
778
  }
768
779
  ctx.imports.add("code");
@@ -1460,6 +1471,18 @@ function wholeCardLink(yes, fn) {
1460
1471
  }
1461
1472
  /** A card's title: not-prose, or docs.css's h3 rule (1.25rem, 2rem above) applies inside the card. */
1462
1473
  const CARD_TITLE_CLASS = "not-prose m-0 border-0 p-0 text-base font-semibold";
1474
+ /**
1475
+ * A card group's columns, responsive as render-html draws them (its GRID_COLS): one column on a
1476
+ * phone, then up to `cols` (1–6) by Grid's breakpoints (0, 640, 768, 1024). Default 2. A list
1477
+ * (`cols="1,2,3"`) is the author's own breakpoints and passes through.
1478
+ */
1479
+ function cardCols(raw) {
1480
+ const list = coerceNumericList(raw, [2]);
1481
+ if (list.length > 1)
1482
+ return list;
1483
+ const n = Math.min(6, Math.max(1, Math.round(list[0]) || 2));
1484
+ return n === 1 ? [1] : n === 2 ? [1, 2] : n <= 4 ? [1, 2, 2, n] : [1, 3, 3, n];
1485
+ }
1463
1486
  function cardsToAstro(node, ctx) {
1464
1487
  ctx.imports.add("grid");
1465
1488
  ctx.imports.add("card");
@@ -1515,7 +1538,7 @@ function cardsToAstro(node, ctx) {
1515
1538
  }
1516
1539
  return `<Card${cardClassAttr}${cardPass}>\n<CardContent class="p-0">\n${iconHtml}\n${titleHtml}\n${desc}\n</CardContent>\n</Card>`;
1517
1540
  }).join("\n");
1518
- return `<Grid cols={[1, 2]} gap={4}${outerClass}${outerPass}>\n${cards}\n</Grid>`;
1541
+ return `<Grid cols={[${cardCols(node.props?.cols).join(", ")}]} gap={4}${outerClass}${outerPass}>\n${cards}\n</Grid>`;
1519
1542
  }
1520
1543
  // MkDocs pattern: children are unordered-list items
1521
1544
  const items = (node.children ?? [])
@@ -1525,10 +1548,10 @@ function cardsToAstro(node, ctx) {
1525
1548
  const cards = items
1526
1549
  .map((item) => `<Card>\n<CardContent>\n${childrenToAstro(item, ctx)}\n</CardContent>\n</Card>`)
1527
1550
  .join("\n");
1528
- return `<Grid cols={[1, 2]} gap={4}>\n${cards}\n</Grid>`;
1551
+ return `<Grid cols={[${cardCols(node.props?.cols).join(", ")}]} gap={4}>\n${cards}\n</Grid>`;
1529
1552
  }
1530
1553
  // Fallback: render children directly in grid
1531
- return `<Grid cols={[1, 2]} gap={4}>\n${childrenToAstro(node, ctx)}\n</Grid>`;
1554
+ return `<Grid cols={[${cardCols(node.props?.cols).join(", ")}]} gap={4}>\n${childrenToAstro(node, ctx)}\n</Grid>`;
1532
1555
  }
1533
1556
  /**
1534
1557
  * Render a standalone `card` TreeNode (outside `:::cards`).
@@ -1549,13 +1572,8 @@ function standaloneCardToAstro(node, ctx) {
1549
1572
  || (node.inline ? wholeCardLink(!!href, () => inlineToTemplate(node.inline)) : "")
1550
1573
  || (description ? escapeTemplate(description) : "");
1551
1574
  const descTag = blocks ? "div" : "p";
1552
- // Icon renders inline before the title (same shape as the
1553
- // cards-list path). Resolved at build time via @dogsbay/icons.
1554
- let iconHtml = "";
1555
- if (icon) {
1556
- ctx.imports.add("icon");
1557
- iconHtml = `<Icon name="${escapeAttr(icon)}" class="size-5 mb-2 text-muted-foreground" />`;
1558
- }
1575
+ // Icon renders inline before the title, a name or an image path, as in a card group
1576
+ const iconHtml = icon ? cardIconHtml(icon, title, ctx) : "";
1559
1577
  const titleHtml = title
1560
1578
  ? `<h3 class="${CARD_TITLE_CLASS}">${escapeTemplate(title)}</h3>`
1561
1579
  : "";
package/dist/theme-css.js CHANGED
@@ -128,7 +128,10 @@ export function generateGlobalCss() {
128
128
  & li > * + *:not(.dba-api *) { margin-top: 0.75rem; }
129
129
 
130
130
  & ul:not(.dba-api *) { list-style: disc; padding-left: 1.5rem; margin: 0.75rem 0; }
131
- & ol:not(.dba-api *) { list-style: decimal; padding-left: 1.5rem; margin: 0.75rem 0; }
131
+ /* Not a step list, nor a list inside one: Steps.astro draws their numbers as circles, and this
132
+ rule (one class and an element) outranked its .steps-list { list-style: none }, so each step
133
+ showed its "2." beside its circle */
134
+ & ol:not(.dba-api *):not(.steps-list, .sub-steps-list, .steps-list ol) { list-style: decimal; padding-left: 1.5rem; margin: 0.75rem 0; }
132
135
  & li:not(.dba-api *) { margin: 0.25rem 0; }
133
136
  & li > ul:not(.dba-api *), & li > ol:not(.dba-api *) { margin: 0.25rem 0; }
134
137
  /* A file tree draws its own folder and file icons (files/markup.ts): the list rules above gave it bullets too */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dogsbay/format-astro",
3
- "version": "0.2.0-beta.129",
3
+ "version": "0.2.0-beta.130",
4
4
  "description": "Astro format plugin for Dogsbay — export TreeNode[] to Astro component markup",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -32,12 +32,12 @@
32
32
  "license": "MIT",
33
33
  "dependencies": {
34
34
  "markdown-it": "^14.3.0",
35
- "@dogsbay/format-dogsbay-md": "0.2.0-beta.129",
36
- "@dogsbay/serialize-core": "0.2.0-beta.129",
37
- "@dogsbay/render-html": "0.2.0-beta.129",
38
- "@dogsbay/site-files": "0.2.0-beta.129",
39
- "@dogsbay/types": "0.2.0-beta.129",
40
- "@dogsbay/ui": "0.2.0-beta.129"
35
+ "@dogsbay/format-dogsbay-md": "0.2.0-beta.130",
36
+ "@dogsbay/render-html": "0.2.0-beta.130",
37
+ "@dogsbay/serialize-core": "0.2.0-beta.130",
38
+ "@dogsbay/site-files": "0.2.0-beta.130",
39
+ "@dogsbay/types": "0.2.0-beta.130",
40
+ "@dogsbay/ui": "0.2.0-beta.130"
41
41
  },
42
42
  "repository": {
43
43
  "type": "git",