@markii/html 0.17.0-next.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.
@@ -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
- function makeTransform(registry, ctx, scope, resolveHref, unavailable) {
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.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.17.0-next.0",
58
- "@markii/runtime": "^0.17.0-next.0",
59
- "@markii/stdlib": "^0.17.0-next.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"