@markii/html 0.16.0 → 0.17.0-next.1
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/LICENSE +21 -0
- package/dist/failure-presentation.d.ts +23 -0
- package/dist/failure-presentation.js +32 -0
- package/dist/index.d.ts +1 -1
- package/dist/render.d.ts +32 -1
- package/dist/render.js +80 -17
- package/package.json +4 -4
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 sadigaxund
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -34,3 +34,26 @@ 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;
|
|
39
|
+
/** The diagnostic text for a registered block component written as an inline directive, which renders as the inline fallback instead. */
|
|
40
|
+
export declare function formMismatchTitle(directive: string): string;
|
|
41
|
+
/**
|
|
42
|
+
* The words of a fallback label for a directive that names a component of
|
|
43
|
+
* an installed pack with no view in this engine. Followed by the directive
|
|
44
|
+
* name in a `<code>` element. A static HTML file is what this engine makes,
|
|
45
|
+
* so that is what the label calls the missing view.
|
|
46
|
+
*/
|
|
47
|
+
export declare const NO_ENGINE_VIEW_LABEL = "no HTML view for";
|
|
48
|
+
/**
|
|
49
|
+
* The diagnostic text for the same case (also the fallback box's tooltip):
|
|
50
|
+
* the pack, and the engines the component does ship a view for.
|
|
51
|
+
*/
|
|
52
|
+
export declare function noEngineViewTitle(directive: string, pack: string, engines: readonly string[]): string;
|
|
53
|
+
/**
|
|
54
|
+
* The visible separator between an inline fallback's label and its content,
|
|
55
|
+
* emitted as real text (`mk-unknown__separator`) so a copy or a plain-text
|
|
56
|
+
* export reads the same as `@markii/ansi`'s output. An inline fallback with
|
|
57
|
+
* no content shows the bare label and no separator.
|
|
58
|
+
*/
|
|
59
|
+
export declare const INLINE_FALLBACK_SEPARATOR = ": ";
|
|
@@ -82,3 +82,35 @@ 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
|
+
}
|
|
89
|
+
/** The diagnostic text for a registered block component written as an inline directive, which renders as the inline fallback instead. */
|
|
90
|
+
export function formMismatchTitle(directive) {
|
|
91
|
+
return `${directive}: block component was written inline and was not rendered`;
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* The words of a fallback label for a directive that names a component of
|
|
95
|
+
* an installed pack with no view in this engine. Followed by the directive
|
|
96
|
+
* name in a `<code>` element. A static HTML file is what this engine makes,
|
|
97
|
+
* so that is what the label calls the missing view.
|
|
98
|
+
*/
|
|
99
|
+
export const NO_ENGINE_VIEW_LABEL = 'no HTML view for';
|
|
100
|
+
/**
|
|
101
|
+
* The diagnostic text for the same case (also the fallback box's tooltip):
|
|
102
|
+
* the pack, and the engines the component does ship a view for.
|
|
103
|
+
*/
|
|
104
|
+
export function noEngineViewTitle(directive, pack, engines) {
|
|
105
|
+
const has = engines.length > 0
|
|
106
|
+
? `it has views for: ${engines.join(', ')}`
|
|
107
|
+
: 'it has no views for any engine';
|
|
108
|
+
return `The ${pack} pack has no HTML view for this component; ${has}`;
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* The visible separator between an inline fallback's label and its content,
|
|
112
|
+
* emitted as real text (`mk-unknown__separator`) so a copy or a plain-text
|
|
113
|
+
* export reads the same as `@markii/ansi`'s output. An inline fallback with
|
|
114
|
+
* no content shows the bare label and no separator.
|
|
115
|
+
*/
|
|
116
|
+
export const INLINE_FALLBACK_SEPARATOR = ': ';
|
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
|
@@ -2,7 +2,7 @@ import { parse } from '@markii/core';
|
|
|
2
2
|
import type { MarkNode } from '@markii/core';
|
|
3
3
|
import type { ValueStore, VaultStore } from '@markii/runtime';
|
|
4
4
|
import type { HtmlRegistry } from './registry.js';
|
|
5
|
-
import type { OnDiagnostic } from '@markii/stdlib';
|
|
5
|
+
import type { OnDiagnostic, UnavailableComponent } from '@markii/stdlib';
|
|
6
6
|
import type { ResolveImageSrc } from './image-resolve.js';
|
|
7
7
|
import type { ResolveHref } from './href-resolve.js';
|
|
8
8
|
/**
|
|
@@ -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,9 +74,31 @@ 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;
|
|
94
|
+
/**
|
|
95
|
+
* Components of installed packs that this render cannot draw, as plain
|
|
96
|
+
* data from the host. A directive named here renders the usual fallback
|
|
97
|
+
* box labeled "no HTML view for" instead of "unknown component", and
|
|
98
|
+
* `onDiagnostic` gets a `'no-engine-view'` event. Omitted, the render is
|
|
99
|
+
* unchanged.
|
|
100
|
+
*/
|
|
101
|
+
readonly unavailableComponents?: readonly UnavailableComponent[];
|
|
71
102
|
/**
|
|
72
103
|
* The note's own last-run values, the same thing the third positional
|
|
73
104
|
* parameter takes. Offered here as well so a caller that already builds
|
package/dist/render.js
CHANGED
|
@@ -4,8 +4,8 @@ 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, invalidAttributeValueTitle, } from './failure-presentation.js';
|
|
8
|
-
import { formatValue, getContract, reportDiagnostic, INTERACTIVE_ATTRIBUTE, } from '@markii/stdlib';
|
|
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
|
+
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';
|
|
11
11
|
function isMarkRoot(node) {
|
|
@@ -213,6 +213,8 @@ function isRegisteredInline(entry) {
|
|
|
213
213
|
/** The fallback label line, worded for the reason and the form the directive was written in. Returns HTML. */
|
|
214
214
|
function fallbackLabel(name, inline, reason) {
|
|
215
215
|
const code = `<code>${escapeHtml(name)}</code>`;
|
|
216
|
+
if (reason === 'no-engine-view')
|
|
217
|
+
return `${NO_ENGINE_VIEW_LABEL} ${code}`;
|
|
216
218
|
if (reason === 'form-mismatch') {
|
|
217
219
|
return inline
|
|
218
220
|
? `block component ${code} written inline`
|
|
@@ -220,24 +222,39 @@ function fallbackLabel(name, inline, reason) {
|
|
|
220
222
|
}
|
|
221
223
|
return `unknown component ${code}`;
|
|
222
224
|
}
|
|
225
|
+
/**
|
|
226
|
+
* The separator an inline fallback's label ends with when the fallback has
|
|
227
|
+
* content to show after it, matching `@markii/ansi`'s `label: content`.
|
|
228
|
+
* Nested inside the label span so it takes the label's styling.
|
|
229
|
+
*/
|
|
230
|
+
function inlineSeparator(childrenHtml) {
|
|
231
|
+
return childrenHtml.trim() === ''
|
|
232
|
+
? ''
|
|
233
|
+
: `<span class="mk-unknown__separator">${INLINE_FALLBACK_SEPARATOR}</span>`;
|
|
234
|
+
}
|
|
223
235
|
/**
|
|
224
236
|
* The unknown-directive fallback, matching `@markii/react`'s `UnknownDirective`
|
|
225
237
|
* markup and class names byte-for-byte so one stylesheet covers both renderers.
|
|
226
238
|
* An inline directive is built from `<span>`s (it lives inside a paragraph); a
|
|
227
239
|
* block directive gets the dashed `<div>` box with its inner content preserved.
|
|
228
240
|
*/
|
|
229
|
-
function unknownDirective(name, inline, childrenHtml, reason) {
|
|
230
|
-
const reasonClass = reason === 'form-mismatch'
|
|
241
|
+
function unknownDirective(name, inline, childrenHtml, reason, title) {
|
|
242
|
+
const reasonClass = reason === 'form-mismatch'
|
|
243
|
+
? ' mk-unknown--mismatch'
|
|
244
|
+
: reason === 'no-engine-view'
|
|
245
|
+
? ' mk-unknown--no-view'
|
|
246
|
+
: '';
|
|
247
|
+
const titleAttr = title === undefined ? '' : ` title="${escapeHtml(title)}"`;
|
|
231
248
|
const label = fallbackLabel(name, inline, reason);
|
|
232
249
|
if (inline) {
|
|
233
|
-
return (`<span class="mk-unknown mk-unknown--inline${reasonClass}">` +
|
|
234
|
-
`<span class="mk-unknown__label">${label}</span>` +
|
|
250
|
+
return (`<span class="mk-unknown mk-unknown--inline${reasonClass}"${titleAttr}>` +
|
|
251
|
+
`<span class="mk-unknown__label">${label}${inlineSeparator(childrenHtml)}</span>` +
|
|
235
252
|
`${childrenHtml}</span>`);
|
|
236
253
|
}
|
|
237
254
|
const content = childrenHtml
|
|
238
255
|
? `<div class="mk-unknown__content">${childrenHtml}</div>`
|
|
239
256
|
: '';
|
|
240
|
-
return (`<div class="mk-unknown mk-unknown--block${reasonClass}">` +
|
|
257
|
+
return (`<div class="mk-unknown mk-unknown--block${reasonClass}"${titleAttr}>` +
|
|
241
258
|
`<p class="mk-unknown__label">${label}</p>${content}</div>`);
|
|
242
259
|
}
|
|
243
260
|
/**
|
|
@@ -251,7 +268,7 @@ function componentError(name, inline, childrenHtml) {
|
|
|
251
268
|
const code = `<code>${escapeHtml(name)}</code>`;
|
|
252
269
|
if (inline) {
|
|
253
270
|
return (`<span class="mk-unknown mk-unknown--inline mk-unknown--error">` +
|
|
254
|
-
`<span class="mk-unknown__label">component ${code} failed to render</span>` +
|
|
271
|
+
`<span class="mk-unknown__label">component ${code} failed to render${inlineSeparator(childrenHtml)}</span>` +
|
|
255
272
|
`${childrenHtml}</span>`);
|
|
256
273
|
}
|
|
257
274
|
const content = childrenHtml
|
|
@@ -365,7 +382,7 @@ function invalidEnumAttribute(name, attributes) {
|
|
|
365
382
|
return undefined;
|
|
366
383
|
}
|
|
367
384
|
/** Resolves one directive (registry component, `:value[...]`, or the fallback) given its layout-stripped attributes. Never throws. */
|
|
368
|
-
function renderDirectiveContent(name, kind, attributes, childrenHtml, plainLabel, registry, ctx, scope, layoutClassName) {
|
|
385
|
+
function renderDirectiveContent(name, kind, attributes, childrenHtml, plainLabel, registry, ctx, scope, layoutClassName, unavailable) {
|
|
369
386
|
if (name === VALUE_DIRECTIVE_NAME) {
|
|
370
387
|
return ctx.valueMarker(plainLabel, attributes.format ?? undefined, attributes.decimals ?? undefined);
|
|
371
388
|
}
|
|
@@ -373,9 +390,24 @@ function renderDirectiveContent(name, kind, attributes, childrenHtml, plainLabel
|
|
|
373
390
|
const entry = Object.hasOwn(registry, name) ? registry[name] : undefined;
|
|
374
391
|
const component = readRegistryComponent(entry);
|
|
375
392
|
if (!entry || component == null) {
|
|
393
|
+
const missingView = unavailable?.(name);
|
|
394
|
+
if (missingView !== undefined) {
|
|
395
|
+
const title = noEngineViewTitle(name, missingView.pack, missingView.engines);
|
|
396
|
+
reportDiagnostic(ctx.onDiagnostic, {
|
|
397
|
+
kind: 'no-engine-view',
|
|
398
|
+
directive: name,
|
|
399
|
+
message: title,
|
|
400
|
+
});
|
|
401
|
+
return unknownDirective(name, inline, childrenHtml, 'no-engine-view', title);
|
|
402
|
+
}
|
|
376
403
|
return unknownDirective(name || '(unnamed)', inline, childrenHtml, 'unregistered');
|
|
377
404
|
}
|
|
378
405
|
if (isFormMismatch(entry, kind)) {
|
|
406
|
+
reportDiagnostic(ctx.onDiagnostic, {
|
|
407
|
+
kind: 'form-mismatch',
|
|
408
|
+
directive: name,
|
|
409
|
+
message: formMismatchTitle(name),
|
|
410
|
+
});
|
|
379
411
|
return unknownDirective(name || '(unnamed)', inline, childrenHtml, 'form-mismatch');
|
|
380
412
|
}
|
|
381
413
|
const binding = resolveDataAttribute(attributes, scope);
|
|
@@ -417,7 +449,7 @@ function renderDirectiveContent(name, kind, attributes, childrenHtml, plainLabel
|
|
|
417
449
|
return rendered;
|
|
418
450
|
}
|
|
419
451
|
/** Turns one `<mk-directive>` element (children already transformed) into its HTML string, including the layout wrapper for block directives. */
|
|
420
|
-
function renderDirective(element, registry, ctx, scope) {
|
|
452
|
+
function renderDirective(element, registry, ctx, scope, unavailable) {
|
|
421
453
|
const written = stringProperty(element, 'data-mk-name') ?? '';
|
|
422
454
|
const kind = stringProperty(element, 'data-mk-kind');
|
|
423
455
|
const rawAttributes = parseAttributes(stringProperty(element, 'data-mk-attrs'));
|
|
@@ -436,7 +468,7 @@ function renderDirective(element, registry, ctx, scope) {
|
|
|
436
468
|
const ownedAxis = registryLayoutAxis(registry, name);
|
|
437
469
|
const { attributes, className } = resolveLayoutAttributes(aliased, ownedAxis);
|
|
438
470
|
const isLayoutScope = ownedAxis !== undefined && isBlock;
|
|
439
|
-
const content = renderDirectiveContent(name, kind, attributes, childrenHtml, plainLabel, registry, ctx, scope, isLayoutScope ? className : undefined);
|
|
471
|
+
const content = renderDirectiveContent(name, kind, attributes, childrenHtml, plainLabel, registry, ctx, scope, isLayoutScope ? className : undefined, unavailable);
|
|
440
472
|
return isBlock && className && !isLayoutScope
|
|
441
473
|
? `<div class="${escapeHtml(className)}">${content}</div>`
|
|
442
474
|
: content;
|
|
@@ -475,17 +507,48 @@ function applyHrefResolver(node, resolveHref) {
|
|
|
475
507
|
node.properties.href = resolveHrefAttribute(href, resolveHref);
|
|
476
508
|
}
|
|
477
509
|
}
|
|
478
|
-
|
|
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) {
|
|
479
539
|
function transform(node) {
|
|
480
540
|
if (node.type !== 'element')
|
|
481
541
|
return node;
|
|
482
542
|
node.children = node.children.map((child) => transform(child));
|
|
483
543
|
if (node.tagName === DIRECTIVE_TAG)
|
|
484
|
-
return raw(renderDirective(node, registry, ctx, scope));
|
|
544
|
+
return raw(renderDirective(node, registry, ctx, scope, unavailable));
|
|
485
545
|
if (node.tagName === 'pre') {
|
|
486
546
|
const marker = renderScriptMarker(node);
|
|
487
547
|
if (marker !== undefined)
|
|
488
548
|
return raw(marker);
|
|
549
|
+
const custom = applyRenderCode(node, renderCode, ctx.onDiagnostic);
|
|
550
|
+
if (custom !== undefined)
|
|
551
|
+
return raw(custom);
|
|
489
552
|
}
|
|
490
553
|
if (node.tagName === 'img') {
|
|
491
554
|
applyImageResolver(node, ctx.resolveImageSrc);
|
|
@@ -504,15 +567,15 @@ function renderFailureFallback(error) {
|
|
|
504
567
|
`<p class="mk-unknown__label">failed to render document</p>` +
|
|
505
568
|
`<pre class="mk-unknown__content">${escapeHtml(message)}</pre></div>`);
|
|
506
569
|
}
|
|
507
|
-
function renderRoot(root, registry, scope, resolveImageSrc, resolveHref, onDiagnostic) {
|
|
570
|
+
function renderRoot(root, registry, scope, resolveImageSrc, resolveHref, onDiagnostic, unavailable, renderCode) {
|
|
508
571
|
const ctx = createBaseContext(scope, resolveImageSrc, onDiagnostic);
|
|
509
|
-
const transform = makeTransform(registry, ctx, scope, resolveHref);
|
|
572
|
+
const transform = makeTransform(registry, ctx, scope, resolveHref, unavailable, renderCode);
|
|
510
573
|
root.children = root.children.map(transform);
|
|
511
574
|
return serialize(root.children);
|
|
512
575
|
}
|
|
513
576
|
export function renderMarkToHtml(text, registry, store, vault, options) {
|
|
514
577
|
try {
|
|
515
|
-
return renderRoot(toHast(text), registry, { store: options?.store ?? store, vault: options?.vault ?? vault }, options?.resolveImageSrc, options?.resolveHref, options?.onDiagnostic);
|
|
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);
|
|
516
579
|
}
|
|
517
580
|
catch (error) {
|
|
518
581
|
return renderFailureFallback(error);
|
|
@@ -533,7 +596,7 @@ export function renderMarkToHtml(text, registry, store, vault, options) {
|
|
|
533
596
|
*/
|
|
534
597
|
export function renderMarkNodeToHtml(node, registry, store, vault, options) {
|
|
535
598
|
try {
|
|
536
|
-
return renderRoot(nodeOrRootToHast(node), registry, { store: options?.store ?? store, vault: options?.vault ?? vault }, options?.resolveImageSrc, options?.resolveHref, options?.onDiagnostic);
|
|
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);
|
|
537
600
|
}
|
|
538
601
|
catch (error) {
|
|
539
602
|
return renderFailureFallback(error);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@markii/html",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.17.0-next.1",
|
|
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.
|
|
58
|
-
"@markii/runtime": "^0.
|
|
59
|
-
"@markii/stdlib": "^0.
|
|
57
|
+
"@markii/core": "^0.17.0-next.1",
|
|
58
|
+
"@markii/runtime": "^0.17.0-next.1",
|
|
59
|
+
"@markii/stdlib": "^0.17.0-next.1"
|
|
60
60
|
},
|
|
61
61
|
"devDependencies": {
|
|
62
62
|
"@types/hast": "^3.0.4"
|