@dogsbay/render-html 0.2.0-beta.121 → 0.2.0-beta.122
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/css/docs.css +5 -1
- package/dist/capabilities.d.ts +25 -0
- package/dist/capabilities.js +115 -0
- package/dist/css-tools.d.ts +0 -5
- package/dist/css-tools.js +10 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/render.d.ts +0 -6
- package/dist/render.js +21 -3
- package/package.json +4 -4
package/css/docs.css
CHANGED
|
@@ -91,7 +91,11 @@
|
|
|
91
91
|
& .heading-anchor { text-decoration: none; opacity: 0; margin-right: 0.25rem; transition: opacity 0.2s; }
|
|
92
92
|
& h1:hover .heading-anchor, & h2:hover .heading-anchor, & h3:hover .heading-anchor, & h4:hover .heading-anchor { opacity: 0.4; }
|
|
93
93
|
|
|
94
|
-
|
|
94
|
+
/* Raw HTML <details> only. CollapsibleAlert (:::details, collapsible
|
|
95
|
+
callouts) is a <details> too, with its own border and spacing; it
|
|
96
|
+
carries data-variant, and without the exclusion it got a second border
|
|
97
|
+
and 1rem of padding around its title bar. */
|
|
98
|
+
& details:not(.dba-api *):not([data-variant]) { border: 1px solid var(--border); border-radius: 0.5rem; padding: 1rem; margin: 1rem 0; }
|
|
95
99
|
& summary:not(.dba-api *) { cursor: pointer; font-weight: 600; }
|
|
96
100
|
|
|
97
101
|
/* mark is emitted by the highlight directive AND can arrive as raw HTML
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* What the HTML renderer can and cannot represent — a CONTRACT (the
|
|
3
|
+
* format-docusaurus pattern): `validateCapabilities` rejects any non-full
|
|
4
|
+
* entry without a note, and `tests/capabilities.test.ts` asserts every
|
|
5
|
+
* `MATRIX_ROWS` type is declared exactly once. Measured against `render.ts`
|
|
6
|
+
* and `api.ts` by rendering real nodes, not read off the switch.
|
|
7
|
+
*
|
|
8
|
+
* This renderer has no export ledger. What it does record goes to the
|
|
9
|
+
* caller's RenderContext: `unknown` (node types and directives it has no
|
|
10
|
+
* case for, the example fallback panel, unresolved includes), `missingIcons`
|
|
11
|
+
* and `unsafeUrls`. dogsbay-ssg and @dogsbay/render turn those into build
|
|
12
|
+
* warnings. A degradation that lands in none of them is SILENT, and the
|
|
13
|
+
* notes below say so where it happens.
|
|
14
|
+
*
|
|
15
|
+
* Several cells depend on what the caller passes: math is `full` only with a
|
|
16
|
+
* `math` function (KaTeX), a diagram only with an `svg` prop or a `diagram`
|
|
17
|
+
* renderer, an icon only when the built-in Lucide set or the `icons`
|
|
18
|
+
* resolver knows it. Those are declared `partial`, because the renderer on
|
|
19
|
+
* its own does not guarantee them.
|
|
20
|
+
*
|
|
21
|
+
* Support levels: full — renders faithfully, with the Astro components'
|
|
22
|
+
* markup · partial — survives with reduced fidelity · none — dropped.
|
|
23
|
+
*/
|
|
24
|
+
import type { CapabilityDeclaration } from "@dogsbay/serialize-core";
|
|
25
|
+
export declare const RENDER_HTML_CAPABILITIES: CapabilityDeclaration[];
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
export const RENDER_HTML_CAPABILITIES = [
|
|
2
|
+
// ── Blocks ───────────────────────────────────────────────
|
|
3
|
+
{ feature: "heading", support: "full", rendersAs: "`<hN>` with a unique id and a hover pilcrow; h2/h3 join the TOC" },
|
|
4
|
+
{ feature: "paragraph", support: "full", rendersAs: "`<p>` (a lone titled image becomes a figure with `imageCaptions: \"title\"`)" },
|
|
5
|
+
{ feature: "blockquote", support: "full", rendersAs: "`<blockquote>`" },
|
|
6
|
+
{ feature: "unordered-list", support: "full", rendersAs: "`<ul>`, task items as disabled checkboxes" },
|
|
7
|
+
{ feature: "ordered-list", support: "full", rendersAs: "`<ol>` with `start`" },
|
|
8
|
+
{ feature: "hr", support: "full", rendersAs: "`<hr>`" },
|
|
9
|
+
{ feature: "table", support: "full", rendersAs: "scrollable `<table>` with caption, alignment, colspan/rowspan" },
|
|
10
|
+
{
|
|
11
|
+
feature: "code",
|
|
12
|
+
support: "full",
|
|
13
|
+
rendersAs: "`<db-code-block>` (CodeBlock / CodeRich markup); highlighted only when a Highlighter is passed, plain text otherwise",
|
|
14
|
+
},
|
|
15
|
+
{
|
|
16
|
+
feature: "math-block",
|
|
17
|
+
support: "partial",
|
|
18
|
+
rendersAs: "KaTeX HTML + MathML when `ctx.math` is passed",
|
|
19
|
+
note: "Without a math renderer the LaTeX source is shown in a `<pre><code class=\"math-display\">` — readable, not typeset. Not recorded.",
|
|
20
|
+
},
|
|
21
|
+
{ feature: "deflist", support: "full", rendersAs: "`<dl>` / `<dt>` / `<dd>`" },
|
|
22
|
+
{ feature: "figure", support: "full", rendersAs: "`<figure>` with `<figcaption>`" },
|
|
23
|
+
{ feature: "footnote-list", support: "full", rendersAs: "`<section role=\"doc-endnotes\">` with backlinks" },
|
|
24
|
+
{
|
|
25
|
+
feature: "html",
|
|
26
|
+
support: "full",
|
|
27
|
+
rendersAs: "the HTML as authored, links rewritten, script URLs refused (reported in `unsafeUrls`); filtered by `ctx.rawHtml` when the host passes a sanitizer",
|
|
28
|
+
},
|
|
29
|
+
{ feature: "html-container", support: "full", rendersAs: "its HTML as authored, or a `div.db-html-container` around its children" },
|
|
30
|
+
{
|
|
31
|
+
feature: "diagram",
|
|
32
|
+
support: "partial",
|
|
33
|
+
rendersAs: "`<figure class=\"diagram\">` around the SVG",
|
|
34
|
+
note: "Rendered only when the node carries an `svg` prop or the host passes `ctx.diagram`; otherwise the diagram SOURCE is shown as a code block. Not recorded.",
|
|
35
|
+
},
|
|
36
|
+
{
|
|
37
|
+
feature: "youtube",
|
|
38
|
+
support: "partial",
|
|
39
|
+
rendersAs: "a link card to youtube.com/watch (optional local poster image)",
|
|
40
|
+
note: "Deliberately no embed: the page must work offline and make no request to YouTube. The Astro pipeline embeds on click.",
|
|
41
|
+
},
|
|
42
|
+
// ── Components ───────────────────────────────────────────
|
|
43
|
+
{ feature: "callout", support: "full", rendersAs: "Alert markup (12 variants, aliases mapped); collapsible → CollapsibleAlert `<details>`" },
|
|
44
|
+
{ feature: "details", support: "full", rendersAs: "CollapsibleAlert `<details>`, as the Astro serializer" },
|
|
45
|
+
{ feature: "details-sheet", support: "full", rendersAs: "`<db-details-sheet>` around the CollapsibleAlert `<details>` (a right-hand native `<dialog>` when the element script runs; a collapsible block with `js: none`)" },
|
|
46
|
+
{
|
|
47
|
+
feature: "tabs",
|
|
48
|
+
support: "full",
|
|
49
|
+
rendersAs: "`<db-tabs>` with Tabs.astro markup, synced groups by label; a child that is not a tab stays in reading order around the group",
|
|
50
|
+
},
|
|
51
|
+
{ feature: "steps", support: "full", rendersAs: "`<ol class=\"steps-list\">`; a non-step child is wrapped in its own `<li>`" },
|
|
52
|
+
{
|
|
53
|
+
feature: "accordion",
|
|
54
|
+
support: "full",
|
|
55
|
+
rendersAs: "`<db-accordion>` with Accordion.astro markup; a child that is not an item stays in reading order around the group",
|
|
56
|
+
},
|
|
57
|
+
{ feature: "cards", support: "full", rendersAs: "a responsive card grid `<div>`" },
|
|
58
|
+
{ feature: "card", support: "full", rendersAs: "Card.astro markup; icon, title, description, body; linked when `href` is set" },
|
|
59
|
+
{ feature: "link-card", support: "full", rendersAs: "LinkCard.astro markup; a body of several blocks renders as a linked Card" },
|
|
60
|
+
{ feature: "grid", support: "full", rendersAs: "a 1–6 column grid; grid-item spans and placeholder cells" },
|
|
61
|
+
{ feature: "link-button", support: "full", rendersAs: "an `<a>` with Button.astro's classes and variant" },
|
|
62
|
+
{ feature: "related", support: "full", rendersAs: "`<nav class=\"related-resources\">`" },
|
|
63
|
+
{
|
|
64
|
+
feature: "example",
|
|
65
|
+
support: "partial",
|
|
66
|
+
rendersAs: "a figure: the rendered content, then its source in a collapsed panel",
|
|
67
|
+
note: "The Astro component's optional plain-Markdown panel (`fallback=true`) needs a second Markdown renderer and is left out; reported in `ctx.unknown`.",
|
|
68
|
+
},
|
|
69
|
+
{
|
|
70
|
+
feature: "container",
|
|
71
|
+
support: "partial",
|
|
72
|
+
rendersAs: "`<div data-directive=\"name\">` with its title and content",
|
|
73
|
+
note: "A `:::name` directive no renderer knows: content kept, but no component behaviour or styling. Reported in `ctx.unknown` as `:::name`.",
|
|
74
|
+
},
|
|
75
|
+
{
|
|
76
|
+
feature: "annotation-list",
|
|
77
|
+
support: "partial",
|
|
78
|
+
rendersAs: "a tinted box holding the annotation list (format-astro's wrapBlock)",
|
|
79
|
+
note: "The annotations are not attached to the code block's `(1)` markers as pop-ups; they read as a list below the code, as in the Astro pipeline.",
|
|
80
|
+
},
|
|
81
|
+
// ── API reference ────────────────────────────────────────
|
|
82
|
+
{ feature: "endpoint", support: "full", rendersAs: "ApiLayout + EndpointCard + code panel; descriptions are CommonMark with raw HTML off" },
|
|
83
|
+
{ feature: "api-doc", support: "full", rendersAs: "ApiDoc: prose with its code blocks split out" },
|
|
84
|
+
{ feature: "api-class", support: "full", rendersAs: "ApiSymbol: kind badge, heading, signature, bases, body" },
|
|
85
|
+
{ feature: "api-member", support: "full", rendersAs: "ApiSymbol, one level below its parent" },
|
|
86
|
+
{ feature: "api-params", support: "full", rendersAs: "ApiParams two-column table" },
|
|
87
|
+
{ feature: "api-source", support: "full", rendersAs: "ApiSource: a `<details>` with the source code" },
|
|
88
|
+
// ── Inline ───────────────────────────────────────────────
|
|
89
|
+
{ feature: "link", support: "full", rendersAs: "`<a>` via `ctx.link`; inline buttons with Button.astro classes; script URLs become `#` and are reported" },
|
|
90
|
+
{ feature: "image", support: "full", rendersAs: "`<img>` via `ctx.asset`, lazy; optional zoom marker" },
|
|
91
|
+
{ feature: "kbd", support: "full", rendersAs: "one `<kbd>` keycap per key, joined by `+`" },
|
|
92
|
+
{
|
|
93
|
+
feature: "math",
|
|
94
|
+
support: "partial",
|
|
95
|
+
rendersAs: "KaTeX HTML + MathML when `ctx.math` is passed",
|
|
96
|
+
note: "Without a math renderer the LaTeX source is shown as `<code class=\"db-math\">`. Not recorded.",
|
|
97
|
+
},
|
|
98
|
+
{ feature: "highlight", support: "full", rendersAs: "`<mark>`" },
|
|
99
|
+
{ feature: "badge", support: "full", rendersAs: "Badge.astro `<span>` with its variant" },
|
|
100
|
+
{
|
|
101
|
+
feature: "icon",
|
|
102
|
+
support: "partial",
|
|
103
|
+
rendersAs: "Icon.astro markup around the resolved SVG or emoji",
|
|
104
|
+
note: "Resolved by `ctx.icons` or the built-in Lucide subset only; an unknown name becomes an empty `span.db-icon-missing`, reported in `ctx.missingIcons`.",
|
|
105
|
+
},
|
|
106
|
+
{ feature: "footnote-ref", support: "full", rendersAs: "`<sup>` noteref; repeat references get distinct ids" },
|
|
107
|
+
{ feature: "html-inline", support: "full", rendersAs: "the HTML as authored, links rewritten, filtered by `ctx.rawHtml` when passed" },
|
|
108
|
+
// ── Concerns the renderer records ────────────────────────
|
|
109
|
+
{
|
|
110
|
+
feature: "unrecognised node types",
|
|
111
|
+
support: "partial",
|
|
112
|
+
rendersAs: "block: its HTML, or a `div.db-<type>` with its inline and children; inline: nothing",
|
|
113
|
+
note: "Reported in `ctx.unknown` (blocks by type, inline as `inline:<type>`). An unknown INLINE node is dropped; an unknown block keeps its content.",
|
|
114
|
+
},
|
|
115
|
+
];
|
package/dist/css-tools.d.ts
CHANGED
|
@@ -1,8 +1,3 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Every class name in the page's class attributes, entity-decoded. Markup
|
|
3
|
-
* from other tools (KaTeX, Mermaid), between the foreign markers, is skipped:
|
|
4
|
-
* its class names are not Tailwind utilities.
|
|
5
|
-
*/
|
|
6
1
|
export declare function pageClasses(html: string, into?: Set<string>): Set<string>;
|
|
7
2
|
/**
|
|
8
3
|
* Whitespace and comment removal. Tailwind's own minifier (Lightning CSS)
|
package/dist/css-tools.js
CHANGED
|
@@ -11,11 +11,20 @@ const FOREIGN_BLOCK = new RegExp(`${FOREIGN_START}[\\s\\S]*?${FOREIGN_END}`, "g"
|
|
|
11
11
|
* from other tools (KaTeX, Mermaid), between the foreign markers, is skipped:
|
|
12
12
|
* its class names are not Tailwind utilities.
|
|
13
13
|
*/
|
|
14
|
+
const TAG = /<[a-zA-Z][^\s/>]*(?:\s+[^\s"'>/=]+(?:\s*=\s*(?:"[^"]*"|'[^']*'|[^\s"'=<>`]+))?|\s*\/)*\s*>/g;
|
|
14
15
|
export function pageClasses(html, into = new Set()) {
|
|
15
16
|
const page = html.includes(FOREIGN_START) ? html.replace(FOREIGN_BLOCK, "") : html;
|
|
16
17
|
// Only inside tags: text that merely looks like class="…" (escaped prose, code) must
|
|
17
18
|
// not become CSS. A class compiled from text once wrote `</style>` into the stylesheet.
|
|
18
|
-
|
|
19
|
+
// A quoted attribute value may contain `>` (`[&>svg]:size-4`, valid HTML):
|
|
20
|
+
// a tag pattern that stopped at the first `>` cut the tag mid-class and lost
|
|
21
|
+
// the WHOLE class list (the accordion trigger, callout icons, diagrams).
|
|
22
|
+
// So tags are read with HTML's attribute grammar: a quote opens a value ONLY
|
|
23
|
+
// right after `=`. Allowing quotes anywhere let an unquoted value with an
|
|
24
|
+
// apostrophe (`title=it's`) run on past the real `>` into the text, and
|
|
25
|
+
// text after it became CSS (review). A tag that does not parse is skipped:
|
|
26
|
+
// a missing style, never text compiled as CSS.
|
|
27
|
+
for (const tag of page.matchAll(TAG))
|
|
19
28
|
for (const m of tag[0].matchAll(/\sclass\s*=\s*(?:"([^"]*)"|'([^']*)')/g))
|
|
20
29
|
for (const tok of (m[1] ?? m[2]).split(/\s+/))
|
|
21
30
|
if (tok)
|
package/dist/index.d.ts
CHANGED
package/dist/index.js
CHANGED
package/dist/render.d.ts
CHANGED
|
@@ -1,9 +1,3 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* TreeNode → HTML. Emits plain semantic HTML plus light-DOM custom
|
|
3
|
-
* elements (`db-tabs`, `db-accordion`, `db-code-block`) whose markup
|
|
4
|
-
* contract comes from `@dogsbay/elements`. Everything is a string, so
|
|
5
|
-
* rendering is synchronous and runs anywhere.
|
|
6
|
-
*/
|
|
7
1
|
import type { InlineNode, TreeNode } from "@dogsbay/types";
|
|
8
2
|
import { FOREIGN_END, FOREIGN_START } from "./html.js";
|
|
9
3
|
import { type Highlighter } from "./lines.js";
|
package/dist/render.js
CHANGED
|
@@ -1,3 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* TreeNode → HTML. Emits plain semantic HTML plus light-DOM custom
|
|
3
|
+
* elements (`db-tabs`, `db-accordion`, `db-code-block`) whose markup
|
|
4
|
+
* contract comes from `@dogsbay/elements`. Everything is a string, so
|
|
5
|
+
* rendering is synchronous and runs anywhere.
|
|
6
|
+
*/
|
|
7
|
+
import { isDetailsSheet, renderAroundGroup } from "@dogsbay/serialize-core";
|
|
1
8
|
import { parseInline } from "@dogsbay/format-dogsbay-md/browser";
|
|
2
9
|
import { attrs, esc, FOREIGN_END, FOREIGN_START, passthrough, slugify, unesc } from "./html.js";
|
|
3
10
|
import { CALLOUTS, hasIcon, icon } from "./icons.js";
|
|
@@ -359,11 +366,11 @@ function block(n, ctx) {
|
|
|
359
366
|
// Tight, like the Astro Step: the lead text is not wrapped in <p>.
|
|
360
367
|
return `<li>${renderInline(n.inline, ctx)}${renderBlocks(n.children, ctx)}</li>`;
|
|
361
368
|
case "tabs":
|
|
362
|
-
return
|
|
369
|
+
return renderAroundGroup(n, "tab", (g) => tabs(g, ctx), (c) => renderBlocks([c], ctx), "");
|
|
363
370
|
case "tab":
|
|
364
371
|
return renderBlocks(n.children, ctx);
|
|
365
372
|
case "accordion":
|
|
366
|
-
return
|
|
373
|
+
return renderAroundGroup(n, "accordion-item", (g) => accordion(g, ctx), (c) => renderBlocks([c], ctx), "");
|
|
367
374
|
case "accordion-item":
|
|
368
375
|
return accordion({ type: "accordion", children: [n] }, ctx);
|
|
369
376
|
case "details":
|
|
@@ -478,6 +485,12 @@ function block(n, ctx) {
|
|
|
478
485
|
ctx.unknown.add("include (unresolved)");
|
|
479
486
|
return `<!-- unresolved include: ${esc(target)} -->\n`;
|
|
480
487
|
}
|
|
488
|
+
// Raw HTML (a one-line `<details>` body) or an importer's wrapper: known,
|
|
489
|
+
// so not reported as unknown (that warned on content that rendered fine)
|
|
490
|
+
case "html-container":
|
|
491
|
+
if (n.html && !n.children?.length)
|
|
492
|
+
return rewriteHtml(n.html, ctx);
|
|
493
|
+
return `<div${attrs(passthrough(p, "db-html-container"))}>${renderBlocks(n.children, ctx)}</div>\n`;
|
|
481
494
|
default: {
|
|
482
495
|
ctx.unknown.add(n.type);
|
|
483
496
|
if (n.html && !n.children?.length)
|
|
@@ -786,7 +799,12 @@ function details(n, ctx) {
|
|
|
786
799
|
// `variant` as documented, then `type`, as the Astro pipeline reads it.
|
|
787
800
|
const type = (str(p.variant) ?? str(p.type) ?? "").toLowerCase();
|
|
788
801
|
const variant = ALERT_VARIANT[VARIANT_ALIAS[type] ?? type] ? VARIANT_ALIAS[type] ?? type : "note";
|
|
789
|
-
|
|
802
|
+
const html = collapsibleAlert(variant, renderInline(parseInline(title), ctx), renderBlocks(n.children, ctx), p.open != null && p.open !== false, p);
|
|
803
|
+
// `sheet`: the same details, which <db-details-sheet> opens as a side
|
|
804
|
+
// sheet when its script runs (and which stays a details when it does not)
|
|
805
|
+
if (!isDetailsSheet(p))
|
|
806
|
+
return html;
|
|
807
|
+
return `<db-details-sheet${attrs({ "close-label": ctx.t("close") || "Close" })}>${html.trimEnd()}</db-details-sheet>\n`;
|
|
790
808
|
}
|
|
791
809
|
function figure(n, ctx) {
|
|
792
810
|
const p = (n.props ?? {});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dogsbay/render-html",
|
|
3
|
-
"version": "0.2.0-beta.
|
|
3
|
+
"version": "0.2.0-beta.122",
|
|
4
4
|
"description": "Dogsbay MD TreeNode → HTML with the Astro components' markup and classes. No highlighter, math or CSS compiler unless you pass one; Worker- and browser-safe",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -30,9 +30,9 @@
|
|
|
30
30
|
"dependencies": {
|
|
31
31
|
"htmlparser2": "^10.1.0",
|
|
32
32
|
"markdown-it": "^14.3.0",
|
|
33
|
-
"@dogsbay/format-dogsbay-md": "0.2.0-beta.
|
|
34
|
-
"@dogsbay/serialize-core": "0.2.0-beta.
|
|
35
|
-
"@dogsbay/types": "0.2.0-beta.
|
|
33
|
+
"@dogsbay/format-dogsbay-md": "0.2.0-beta.122",
|
|
34
|
+
"@dogsbay/serialize-core": "0.2.0-beta.122",
|
|
35
|
+
"@dogsbay/types": "0.2.0-beta.122"
|
|
36
36
|
},
|
|
37
37
|
"peerDependencies": {
|
|
38
38
|
"katex": "^0.16.0"
|