@markii/stdlib 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.
@@ -22,8 +22,22 @@
22
22
  * `'unsafe-image-src'` — a component-built `<img>` (the standard `figure`)
23
23
  * had its `src` refused as an unsafe URL scheme; the component rendered
24
24
  * without the image, with a quiet marker.
25
+ *
26
+ * `'form-mismatch'` — a registered block component was written as an
27
+ * inline directive (`:callout[x]`); it rendered as the inline fallback
28
+ * marker instead of the component.
29
+ *
30
+ * `'no-engine-view'` — a directive names a component of an INSTALLED pack
31
+ * that ships no view for this render engine (a React-only pack in the
32
+ * terminal, a terminal-only component in an editor preview). It rendered
33
+ * the fallback box, labeled as a missing view rather than an unknown
34
+ * component. Only reported when the host passed `unavailableComponents`.
35
+ *
36
+ * `'code-renderer-failed'` — a host's `renderCode` callback threw for an
37
+ * ordinary fenced code block; the block rendered as usual. Carries no
38
+ * directive or attribute.
25
39
  */
26
- export type DiagnosticKind = 'invalid-attribute-value' | 'unsafe-image-src';
40
+ export type DiagnosticKind = 'invalid-attribute-value' | 'unsafe-image-src' | 'form-mismatch' | 'no-engine-view' | 'code-renderer-failed';
27
41
  export interface DiagnosticEvent {
28
42
  readonly kind: DiagnosticKind;
29
43
  /** The directive name the event happened on, when there is a single unambiguous one. */
@@ -43,3 +57,36 @@ export type OnDiagnostic = (event: DiagnosticEvent) => void;
43
57
  * guard cannot drift between them.
44
58
  */
45
59
  export declare function reportDiagnostic(onDiagnostic: OnDiagnostic | undefined, event: DiagnosticEvent): void;
60
+ /**
61
+ * One component of an installed pack that the current render cannot draw,
62
+ * as plain data a host hands to a renderer's `unavailableComponents`
63
+ * option. The renderer uses it only to tell this case apart from a typo:
64
+ * the fallback box keeps its structure and the label changes.
65
+ *
66
+ * `directive` is the composed directive name (`ana_meter`), `pack` the
67
+ * pack's namespace, and `engines` the engine ids (`react`, `ansi`) the
68
+ * component DOES ship a view for.
69
+ *
70
+ * `loadFailed` marks a component whose pack could not be loaded for this
71
+ * render's engine at all (its view script threw, registered nothing, or
72
+ * registered another namespace). The renderer then words the fallback as a
73
+ * failed pack rather than a missing view. Absent means the pack loaded and
74
+ * simply has no view for the component.
75
+ */
76
+ export interface UnavailableComponent {
77
+ readonly directive: string;
78
+ readonly pack: string;
79
+ readonly engines: readonly string[];
80
+ readonly loadFailed?: true;
81
+ }
82
+ /** A lookup from a directive name to its `UnavailableComponent`, or `undefined`. */
83
+ export type UnavailableComponentLookup = (directive: string) => UnavailableComponent | undefined;
84
+ /**
85
+ * Builds the lookup a renderer queries per directive. Backed by a `Map`
86
+ * (never a plain object), so a directive named `constructor` or
87
+ * `__proto__` cannot resolve through the prototype chain. An omitted or
88
+ * empty list gives `undefined`, so a renderer given no option takes
89
+ * exactly the path it took before the option existed. Entries that are not
90
+ * well-formed are skipped, and the first entry for a name wins.
91
+ */
92
+ export declare function createUnavailableComponentLookup(components: readonly UnavailableComponent[] | undefined): UnavailableComponentLookup | undefined;
@@ -32,3 +32,36 @@ export function reportDiagnostic(onDiagnostic, event) {
32
32
  // A throwing callback must never break rendering.
33
33
  }
34
34
  }
35
+ /**
36
+ * Builds the lookup a renderer queries per directive. Backed by a `Map`
37
+ * (never a plain object), so a directive named `constructor` or
38
+ * `__proto__` cannot resolve through the prototype chain. An omitted or
39
+ * empty list gives `undefined`, so a renderer given no option takes
40
+ * exactly the path it took before the option existed. Entries that are not
41
+ * well-formed are skipped, and the first entry for a name wins.
42
+ */
43
+ export function createUnavailableComponentLookup(components) {
44
+ if (!Array.isArray(components) || components.length === 0)
45
+ return undefined;
46
+ const byName = new Map();
47
+ for (const entry of components) {
48
+ if (entry === null || typeof entry !== 'object')
49
+ continue;
50
+ const { directive, pack, engines, loadFailed } = entry;
51
+ if (typeof directive !== 'string' || typeof pack !== 'string')
52
+ continue;
53
+ if (!Array.isArray(engines))
54
+ continue;
55
+ if (byName.has(directive))
56
+ continue;
57
+ byName.set(directive, {
58
+ directive,
59
+ pack,
60
+ engines: engines.filter((e) => typeof e === 'string'),
61
+ ...(loadFailed === true ? { loadFailed: true } : {}),
62
+ });
63
+ }
64
+ if (byName.size === 0)
65
+ return undefined;
66
+ return (directive) => byName.get(directive);
67
+ }
@@ -22,7 +22,7 @@
22
22
  * how a note renders.
23
23
  *
24
24
  * Pure and host-neutral: no editor API, no filesystem, no `node:*`. It is
25
- * re-exported from `@markii/host/browser`, and
25
+ * re-exported from `@markii/host`'s main entry, and
26
26
  * `apps/vscode/src/browser-entry.probe.test.ts` is the gate for that.
27
27
  */
28
28
  /** A container-directive fence pair enclosing an insertion point. */
@@ -22,7 +22,7 @@
22
22
  * how a note renders.
23
23
  *
24
24
  * Pure and host-neutral: no editor API, no filesystem, no `node:*`. It is
25
- * re-exported from `@markii/host/browser`, and
25
+ * re-exported from `@markii/host`'s main entry, and
26
26
  * `apps/vscode/src/browser-entry.probe.test.ts` is the gate for that.
27
27
  */
28
28
  /**
package/dist/index.d.ts CHANGED
@@ -3,5 +3,5 @@ export { ALIGN_PRESETS, LAYOUT_ATTRIBUTE_KEYS, LAYOUT_ATTRIBUTES, WIDTH_PRESETS,
3
3
  export { TEXT_ALIGN_ATTRIBUTE, TEXT_ALIGN_COMPONENTS, TEXT_ALIGN_PRESETS, type TextAlignPreset, } from './text-align.js';
4
4
  export { formatValue, isNumericLike, FORMAT_ATTRIBUTE, DECIMALS_ATTRIBUTE, type ValueFormat, } from './value-format.js';
5
5
  export { deriveTableShape, type TableShape } from './table-shape.js';
6
- export { reportDiagnostic, type DiagnosticEvent, type DiagnosticKind, type OnDiagnostic, } from './diagnostics.js';
6
+ export { reportDiagnostic, createUnavailableComponentLookup, type UnavailableComponent, type UnavailableComponentLookup, type DiagnosticEvent, type DiagnosticKind, type OnDiagnostic, } from './diagnostics.js';
7
7
  export { INTERACTIVE_ATTRIBUTE } from './interactive.js';
package/dist/index.js CHANGED
@@ -3,5 +3,5 @@ export { ALIGN_PRESETS, LAYOUT_ATTRIBUTE_KEYS, LAYOUT_ATTRIBUTES, WIDTH_PRESETS,
3
3
  export { TEXT_ALIGN_ATTRIBUTE, TEXT_ALIGN_COMPONENTS, TEXT_ALIGN_PRESETS, } from './text-align.js';
4
4
  export { formatValue, isNumericLike, FORMAT_ATTRIBUTE, DECIMALS_ATTRIBUTE, } from './value-format.js';
5
5
  export { deriveTableShape } from './table-shape.js';
6
- export { reportDiagnostic, } from './diagnostics.js';
6
+ export { reportDiagnostic, createUnavailableComponentLookup, } from './diagnostics.js';
7
7
  export { INTERACTIVE_ATTRIBUTE } from './interactive.js';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@markii/stdlib",
3
- "version": "0.16.0",
3
+ "version": "0.17.0-next.1",
4
4
  "description": "Neutral, framework-agnostic standard component contracts for Mark (.mk.md) — the kind/attribute-schema seam every renderer (e.g. @markii/react) implements against. No React, zero dependencies.",
5
5
  "keywords": [
6
6
  "markdown",