@markii/html 0.17.0-next.0 → 0.17.0-next.2
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/failure-presentation.d.ts +2 -0
- package/dist/failure-presentation.js +4 -0
- package/dist/index.d.ts +1 -1
- package/dist/render.d.ts +23 -0
- package/dist/render.js +37 -6
- package/package.json +4 -4
|
@@ -34,6 +34,8 @@ export declare const NOTICE_ATTRIBUTE = "data-mk-notice";
|
|
|
34
34
|
export declare function invalidAttributeValueTitle(directive: string, attribute: string, value: string): string;
|
|
35
35
|
/** The `title` tooltip for `NOTICE_ATTRIBUTE` on a `figure` with a refused `src`. Ported verbatim from `@markii/react`. */
|
|
36
36
|
export declare function unsafeImageSrcTitle(directive: string): string;
|
|
37
|
+
/** The diagnostic text for a host `renderCode` callback that threw; the code block rendered as usual. Identical across the engines. */
|
|
38
|
+
export declare function codeRendererFailedTitle(): string;
|
|
37
39
|
/** The diagnostic text for a registered block component written as an inline directive, which renders as the inline fallback instead. */
|
|
38
40
|
export declare function formMismatchTitle(directive: string): string;
|
|
39
41
|
/**
|
|
@@ -82,6 +82,10 @@ export function invalidAttributeValueTitle(directive, attribute, value) {
|
|
|
82
82
|
export function unsafeImageSrcTitle(directive) {
|
|
83
83
|
return `${directive}: image source was refused as unsafe and was not shown`;
|
|
84
84
|
}
|
|
85
|
+
/** The diagnostic text for a host `renderCode` callback that threw; the code block rendered as usual. Identical across the engines. */
|
|
86
|
+
export function codeRendererFailedTitle() {
|
|
87
|
+
return 'code block: the host code renderer failed, so the plain block was shown';
|
|
88
|
+
}
|
|
85
89
|
/** The diagnostic text for a registered block component written as an inline directive, which renders as the inline fallback instead. */
|
|
86
90
|
export function formMismatchTitle(directive) {
|
|
87
91
|
return `${directive}: block component was written inline and was not rendered`;
|
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { renderMarkToHtml, renderMarkNodeToHtml, renderMarkInlineToHtml, type RenderMarkOptions, } from './render.js';
|
|
1
|
+
export { renderMarkToHtml, renderMarkNodeToHtml, renderMarkInlineToHtml, type RenderCode, type RenderCodeBlock, type RenderMarkOptions, } from './render.js';
|
|
2
2
|
export { type ResolveImageSrc } from './image-resolve.js';
|
|
3
3
|
export { type ResolveHref } from './href-resolve.js';
|
|
4
4
|
export { escapeHtml } from './escape.js';
|
package/dist/render.d.ts
CHANGED
|
@@ -12,6 +12,15 @@ import type { ResolveHref } from './href-resolve.js';
|
|
|
12
12
|
* `@markii/react`'s identical `MarkRoot` type alias.
|
|
13
13
|
*/
|
|
14
14
|
type MarkRoot = ReturnType<typeof parse>;
|
|
15
|
+
/** A fenced code block as offered to `RenderMarkOptions.renderCode`. */
|
|
16
|
+
export interface RenderCodeBlock {
|
|
17
|
+
/** The info-string language, or `undefined` when the fence names none. */
|
|
18
|
+
readonly lang: string | undefined;
|
|
19
|
+
/** The raw code text, without the fence lines. */
|
|
20
|
+
readonly code: string;
|
|
21
|
+
}
|
|
22
|
+
/** The `renderCode` callback: host HTML for a code block, or `undefined` to render it as usual. */
|
|
23
|
+
export type RenderCode = (code: RenderCodeBlock) => string | undefined;
|
|
15
24
|
/**
|
|
16
25
|
* Renders Markii text to a static HTML string using `registry` to resolve
|
|
17
26
|
* directive names. Pipeline: `@markii/core`'s `toHast` (parse -> tag directive
|
|
@@ -65,6 +74,20 @@ type MarkRoot = ReturnType<typeof parse>;
|
|
|
65
74
|
* `RenderMarkOptions`, so the two engines cannot diverge.
|
|
66
75
|
*/
|
|
67
76
|
export interface RenderMarkOptions {
|
|
77
|
+
/**
|
|
78
|
+
* Replaces the output for an ordinary fenced code block. Called with the
|
|
79
|
+
* info-string language (`undefined` when the fence names none) and the
|
|
80
|
+
* raw code text. Return an HTML string to use it, or `undefined` to render
|
|
81
|
+
* the block as usual. Never called for script fences (the collapsed
|
|
82
|
+
* `{name=...}` markers) or for inline code.
|
|
83
|
+
*
|
|
84
|
+
* The returned string is HOST-TRUSTED output and is inserted as-is, with
|
|
85
|
+
* no escaping and no sanitizing: the host owns the escaping. Escape the
|
|
86
|
+
* code text yourself if you wrap it in markup. A callback that throws
|
|
87
|
+
* renders the block as usual and reports a `'code-renderer-failed'`
|
|
88
|
+
* event through `onDiagnostic`.
|
|
89
|
+
*/
|
|
90
|
+
readonly renderCode?: RenderCode;
|
|
68
91
|
readonly resolveImageSrc?: ResolveImageSrc;
|
|
69
92
|
readonly resolveHref?: ResolveHref;
|
|
70
93
|
readonly onDiagnostic?: OnDiagnostic;
|
package/dist/render.js
CHANGED
|
@@ -4,7 +4,7 @@ import { readRegistryComponent, registryLayoutAxis, resolveDirectiveAlias, } fro
|
|
|
4
4
|
import { resolveLayoutAttributes } from './layout.js';
|
|
5
5
|
import { escapeHtml } from './escape.js';
|
|
6
6
|
import { resolveScopedPath } from './resolve.js';
|
|
7
|
-
import { failureKindClass, failureTitle, EMPTY_INLINE_MARKER_CLASS, emptyInlineTitle, formMismatchTitle, INLINE_FALLBACK_SEPARATOR, invalidAttributeValueTitle, NO_ENGINE_VIEW_LABEL, noEngineViewTitle, } from './failure-presentation.js';
|
|
7
|
+
import { failureKindClass, failureTitle, EMPTY_INLINE_MARKER_CLASS, emptyInlineTitle, codeRendererFailedTitle, formMismatchTitle, INLINE_FALLBACK_SEPARATOR, invalidAttributeValueTitle, NO_ENGINE_VIEW_LABEL, noEngineViewTitle, } from './failure-presentation.js';
|
|
8
8
|
import { createUnavailableComponentLookup, formatValue, getContract, reportDiagnostic, INTERACTIVE_ATTRIBUTE, } from '@markii/stdlib';
|
|
9
9
|
import { resolveImageAttribute } from './image-resolve.js';
|
|
10
10
|
import { resolveHrefAttribute } from './href-resolve.js';
|
|
@@ -507,7 +507,35 @@ function applyHrefResolver(node, resolveHref) {
|
|
|
507
507
|
node.properties.href = resolveHrefAttribute(href, resolveHref);
|
|
508
508
|
}
|
|
509
509
|
}
|
|
510
|
-
|
|
510
|
+
/**
|
|
511
|
+
* Offers one ordinary fenced code block (a `<pre>` holding a `<code>`) to the
|
|
512
|
+
* host's `renderCode`. Returns the host's HTML, or `undefined` to render the
|
|
513
|
+
* block as usual: no callback, a callback that declines, or one that throws
|
|
514
|
+
* (reported through `onDiagnostic`, never breaking the render). A callback
|
|
515
|
+
* result that is not a string is treated as declining.
|
|
516
|
+
*/
|
|
517
|
+
function applyRenderCode(node, renderCode, onDiagnostic) {
|
|
518
|
+
if (!renderCode)
|
|
519
|
+
return undefined;
|
|
520
|
+
const codeNode = findChildElement(node, 'code');
|
|
521
|
+
if (!codeNode)
|
|
522
|
+
return undefined;
|
|
523
|
+
try {
|
|
524
|
+
const result = renderCode({
|
|
525
|
+
lang: getLanguage(codeNode) || undefined,
|
|
526
|
+
code: getCodeText(codeNode),
|
|
527
|
+
});
|
|
528
|
+
return typeof result === 'string' ? result : undefined;
|
|
529
|
+
}
|
|
530
|
+
catch {
|
|
531
|
+
reportDiagnostic(onDiagnostic, {
|
|
532
|
+
kind: 'code-renderer-failed',
|
|
533
|
+
message: codeRendererFailedTitle(),
|
|
534
|
+
});
|
|
535
|
+
return undefined;
|
|
536
|
+
}
|
|
537
|
+
}
|
|
538
|
+
function makeTransform(registry, ctx, scope, resolveHref, unavailable, renderCode) {
|
|
511
539
|
function transform(node) {
|
|
512
540
|
if (node.type !== 'element')
|
|
513
541
|
return node;
|
|
@@ -518,6 +546,9 @@ function makeTransform(registry, ctx, scope, resolveHref, unavailable) {
|
|
|
518
546
|
const marker = renderScriptMarker(node);
|
|
519
547
|
if (marker !== undefined)
|
|
520
548
|
return raw(marker);
|
|
549
|
+
const custom = applyRenderCode(node, renderCode, ctx.onDiagnostic);
|
|
550
|
+
if (custom !== undefined)
|
|
551
|
+
return raw(custom);
|
|
521
552
|
}
|
|
522
553
|
if (node.tagName === 'img') {
|
|
523
554
|
applyImageResolver(node, ctx.resolveImageSrc);
|
|
@@ -536,15 +567,15 @@ function renderFailureFallback(error) {
|
|
|
536
567
|
`<p class="mk-unknown__label">failed to render document</p>` +
|
|
537
568
|
`<pre class="mk-unknown__content">${escapeHtml(message)}</pre></div>`);
|
|
538
569
|
}
|
|
539
|
-
function renderRoot(root, registry, scope, resolveImageSrc, resolveHref, onDiagnostic, unavailable) {
|
|
570
|
+
function renderRoot(root, registry, scope, resolveImageSrc, resolveHref, onDiagnostic, unavailable, renderCode) {
|
|
540
571
|
const ctx = createBaseContext(scope, resolveImageSrc, onDiagnostic);
|
|
541
|
-
const transform = makeTransform(registry, ctx, scope, resolveHref, unavailable);
|
|
572
|
+
const transform = makeTransform(registry, ctx, scope, resolveHref, unavailable, renderCode);
|
|
542
573
|
root.children = root.children.map(transform);
|
|
543
574
|
return serialize(root.children);
|
|
544
575
|
}
|
|
545
576
|
export function renderMarkToHtml(text, registry, store, vault, options) {
|
|
546
577
|
try {
|
|
547
|
-
return renderRoot(toHast(text), registry, { store: options?.store ?? store, vault: options?.vault ?? vault }, options?.resolveImageSrc, options?.resolveHref, options?.onDiagnostic, createUnavailableComponentLookup(options?.unavailableComponents));
|
|
578
|
+
return renderRoot(toHast(text), registry, { store: options?.store ?? store, vault: options?.vault ?? vault }, options?.resolveImageSrc, options?.resolveHref, options?.onDiagnostic, createUnavailableComponentLookup(options?.unavailableComponents), options?.renderCode);
|
|
548
579
|
}
|
|
549
580
|
catch (error) {
|
|
550
581
|
return renderFailureFallback(error);
|
|
@@ -565,7 +596,7 @@ export function renderMarkToHtml(text, registry, store, vault, options) {
|
|
|
565
596
|
*/
|
|
566
597
|
export function renderMarkNodeToHtml(node, registry, store, vault, options) {
|
|
567
598
|
try {
|
|
568
|
-
return renderRoot(nodeOrRootToHast(node), registry, { store: options?.store ?? store, vault: options?.vault ?? vault }, options?.resolveImageSrc, options?.resolveHref, options?.onDiagnostic, createUnavailableComponentLookup(options?.unavailableComponents));
|
|
599
|
+
return renderRoot(nodeOrRootToHast(node), registry, { store: options?.store ?? store, vault: options?.vault ?? vault }, options?.resolveImageSrc, options?.resolveHref, options?.onDiagnostic, createUnavailableComponentLookup(options?.unavailableComponents), options?.renderCode);
|
|
569
600
|
}
|
|
570
601
|
catch (error) {
|
|
571
602
|
return renderFailureFallback(error);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@markii/html",
|
|
3
|
-
"version": "0.17.0-next.
|
|
3
|
+
"version": "0.17.0-next.2",
|
|
4
4
|
"description": "A framework-free static HTML renderer for Markii (.mk.md): a registry-driven hast-to-HTML string engine. Zero React; for stopped-changing documents (publish, CI, email, archive).",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"markdown",
|
|
@@ -54,9 +54,9 @@
|
|
|
54
54
|
},
|
|
55
55
|
"dependencies": {
|
|
56
56
|
"hast-util-to-html": "^9.0.0",
|
|
57
|
-
"@markii/core": "^0.17.0-next.
|
|
58
|
-
"@markii/runtime": "^0.17.0-next.
|
|
59
|
-
"@markii/stdlib": "^0.17.0-next.
|
|
57
|
+
"@markii/core": "^0.17.0-next.2",
|
|
58
|
+
"@markii/runtime": "^0.17.0-next.2",
|
|
59
|
+
"@markii/stdlib": "^0.17.0-next.2"
|
|
60
60
|
},
|
|
61
61
|
"devDependencies": {
|
|
62
62
|
"@types/hast": "^3.0.4"
|