@markii/ansi 0.17.0-next.3 → 0.17.0-next.5
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 +0 -2
- package/dist/failure-presentation.js +0 -4
- package/dist/glyphs.d.ts +2 -0
- package/dist/glyphs.js +2 -0
- package/dist/interactive.d.ts +11 -1
- package/dist/interactive.js +41 -5
- package/dist/render.d.ts +2 -7
- package/dist/render.js +11 -45
- package/package.json +5 -5
|
@@ -39,8 +39,6 @@ export declare function invalidAttributeValueTitle(directive: string, attribute:
|
|
|
39
39
|
export declare function unsafeImageSrcTitle(directive: string): string;
|
|
40
40
|
/** The diagnostic text for a host `renderCode` callback that threw; the code block rendered as usual. Wording identical to `@markii/html`'s `codeRendererFailedTitle`. */
|
|
41
41
|
export declare function codeRendererFailedTitle(): string;
|
|
42
|
-
/** The diagnostic text for a directive that names no registered component; the unknown-component box was shown. */
|
|
43
|
-
export declare function unknownDirectiveTitle(directive: string): string;
|
|
44
42
|
/** The diagnostic text for a registered block component written as an inline directive. Wording identical to `@markii/html`'s `formMismatchTitle`. */
|
|
45
43
|
export declare function formMismatchTitle(directive: string): string;
|
|
46
44
|
/**
|
|
@@ -103,10 +103,6 @@ export function unsafeImageSrcTitle(directive) {
|
|
|
103
103
|
export function codeRendererFailedTitle() {
|
|
104
104
|
return 'code block: the host code renderer failed, so the plain block was shown';
|
|
105
105
|
}
|
|
106
|
-
/** The diagnostic text for a directive that names no registered component; the unknown-component box was shown. */
|
|
107
|
-
export function unknownDirectiveTitle(directive) {
|
|
108
|
-
return `${directive}: unknown component, shown as a placeholder`;
|
|
109
|
-
}
|
|
110
106
|
/** The diagnostic text for a registered block component written as an inline directive. Wording identical to `@markii/html`'s `formMismatchTitle`. */
|
|
111
107
|
export function formMismatchTitle(directive) {
|
|
112
108
|
return `${directive}: block component was written inline and was not rendered`;
|
package/dist/glyphs.d.ts
CHANGED
|
@@ -68,6 +68,8 @@ export interface GlyphSet {
|
|
|
68
68
|
readonly emptyValue: string;
|
|
69
69
|
/** The key legend on the live viewer's status line. */
|
|
70
70
|
readonly keyLegend: string;
|
|
71
|
+
/** The same legend with the re-run key listed second, used only when the host supplies a re-run callback. */
|
|
72
|
+
readonly keyLegendRerun: string;
|
|
71
73
|
}
|
|
72
74
|
/** The glyph set for `style`; anything other than `'ascii'` gets the unicode set. */
|
|
73
75
|
export declare function glyphsFor(style: BoxStyle | undefined): GlyphSet;
|
package/dist/glyphs.js
CHANGED
|
@@ -46,6 +46,7 @@ const UNICODE = {
|
|
|
46
46
|
starEmpty: '☆',
|
|
47
47
|
emptyValue: '—',
|
|
48
48
|
keyLegend: 'q quit ↑↓/jk focus ←→/tab switch enter open/close space/pgdn scroll g/G top/end',
|
|
49
|
+
keyLegendRerun: 'q quit r run ↑↓/jk focus ←→/tab switch enter open/close space/pgdn scroll g/G top/end',
|
|
49
50
|
};
|
|
50
51
|
const ASCII = {
|
|
51
52
|
topLeft: '+',
|
|
@@ -77,6 +78,7 @@ const ASCII = {
|
|
|
77
78
|
starEmpty: '.',
|
|
78
79
|
emptyValue: '-',
|
|
79
80
|
keyLegend: 'q quit up/down/jk focus left/right/tab switch enter open/close space/pgdn scroll g/G top/end',
|
|
81
|
+
keyLegendRerun: 'q quit r run up/down/jk focus left/right/tab switch enter open/close space/pgdn scroll g/G top/end',
|
|
80
82
|
};
|
|
81
83
|
const GLYPHS = {
|
|
82
84
|
unicode: UNICODE,
|
package/dist/interactive.d.ts
CHANGED
|
@@ -55,6 +55,16 @@ export interface InteractiveRootProps {
|
|
|
55
55
|
focusables: readonly FocusableDescriptor[];
|
|
56
56
|
/** Called when the reader presses `q`. The engine owns no process state: it never calls `process.exit` itself. */
|
|
57
57
|
onExit?: () => void;
|
|
58
|
+
/**
|
|
59
|
+
* Called when the reader presses `r`. The host runs whatever it runs and
|
|
60
|
+
* returns when it is done; the engine owns no run, process, or script
|
|
61
|
+
* state. While the returned promise is pending the status line reads
|
|
62
|
+
* "running" and further `r` presses are ignored. A rejection ends the
|
|
63
|
+
* wait like a resolution. Absent, `r` does nothing and the legend omits it.
|
|
64
|
+
*/
|
|
65
|
+
onRerun?: () => void | Promise<void>;
|
|
66
|
+
/** The legend to show instead of `keyLegend` when `onRerun` is given: the render's `GlyphSet.keyLegendRerun`. */
|
|
67
|
+
rerunLegend?: string;
|
|
58
68
|
color: ColorLevel;
|
|
59
69
|
theme: AnsiTheme;
|
|
60
70
|
/** The key legend on the status line, identical regardless of what is focused: the render's `GlyphSet.keyLegend`, so it follows the box style. */
|
|
@@ -81,4 +91,4 @@ export interface InteractiveRootProps {
|
|
|
81
91
|
* default (uninteractive) value there, so a string render never sees a
|
|
82
92
|
* focus marker, a glyph, or a status line.
|
|
83
93
|
*/
|
|
84
|
-
export declare function InteractiveRoot({ focusables, onExit, color, theme, keyLegend, viewportRows, width, children, }: InteractiveRootProps): ReactNode;
|
|
94
|
+
export declare function InteractiveRoot({ focusables, onExit, onRerun, rerunLegend, color, theme, keyLegend, viewportRows, width, children, }: InteractiveRootProps): ReactNode;
|
package/dist/interactive.js
CHANGED
|
@@ -86,7 +86,7 @@ export function useFocusAnchor(focusId) {
|
|
|
86
86
|
* default (uninteractive) value there, so a string render never sees a
|
|
87
87
|
* focus marker, a glyph, or a status line.
|
|
88
88
|
*/
|
|
89
|
-
export function InteractiveRoot({ focusables, onExit, color, theme, keyLegend, viewportRows, width, children, }) {
|
|
89
|
+
export function InteractiveRoot({ focusables, onExit, onRerun, rerunLegend, color, theme, keyLegend, viewportRows, width, children, }) {
|
|
90
90
|
const focusableCount = focusables.length;
|
|
91
91
|
const [focusIndex, setFocusIndex] = useState(0);
|
|
92
92
|
// `focusId -> the label its last active-panel report carried`. Only a
|
|
@@ -119,11 +119,42 @@ export function InteractiveRoot({ focusables, onExit, color, theme, keyLegend, v
|
|
|
119
119
|
return;
|
|
120
120
|
setOffset(target === 'top' ? 0 : maxOffset());
|
|
121
121
|
};
|
|
122
|
+
const [running, setRunning] = useState(false);
|
|
123
|
+
// A ref, not the state: two presses in one tick must start one run.
|
|
124
|
+
const runningRef = useRef(false);
|
|
125
|
+
const mounted = useRef(true);
|
|
126
|
+
useEffect(() => {
|
|
127
|
+
mounted.current = true;
|
|
128
|
+
return () => {
|
|
129
|
+
mounted.current = false;
|
|
130
|
+
};
|
|
131
|
+
}, []);
|
|
132
|
+
const startRerun = () => {
|
|
133
|
+
if (onRerun === undefined || runningRef.current)
|
|
134
|
+
return;
|
|
135
|
+
runningRef.current = true;
|
|
136
|
+
setRunning(true);
|
|
137
|
+
const finish = () => {
|
|
138
|
+
runningRef.current = false;
|
|
139
|
+
if (mounted.current)
|
|
140
|
+
setRunning(false);
|
|
141
|
+
};
|
|
142
|
+
try {
|
|
143
|
+
Promise.resolve(onRerun()).then(finish, finish);
|
|
144
|
+
}
|
|
145
|
+
catch {
|
|
146
|
+
finish();
|
|
147
|
+
}
|
|
148
|
+
};
|
|
122
149
|
useInput((input, key) => {
|
|
123
150
|
if (input === 'q') {
|
|
124
151
|
onExit?.();
|
|
125
152
|
return;
|
|
126
153
|
}
|
|
154
|
+
if (input === 'r') {
|
|
155
|
+
startRerun();
|
|
156
|
+
return;
|
|
157
|
+
}
|
|
127
158
|
if (viewport !== undefined) {
|
|
128
159
|
const page = Math.max(1, viewport - 1);
|
|
129
160
|
if (key.pageDown || input === ' ' || (key.ctrl && input === 'f')) {
|
|
@@ -222,13 +253,18 @@ export function InteractiveRoot({ focusables, onExit, color, theme, keyLegend, v
|
|
|
222
253
|
const focusedLabel = focused && focusedId !== undefined
|
|
223
254
|
? (activeLabels[focusedId] ?? focused.label)
|
|
224
255
|
: undefined;
|
|
225
|
-
const statusLabel =
|
|
226
|
-
?
|
|
227
|
-
:
|
|
256
|
+
const statusLabel = running
|
|
257
|
+
? 'running'
|
|
258
|
+
: focused
|
|
259
|
+
? `${focused.kind} "${focusedLabel}"`
|
|
260
|
+
: 'nothing focusable';
|
|
261
|
+
const legend = onRerun !== undefined && rerunLegend !== undefined
|
|
262
|
+
? rerunLegend
|
|
263
|
+
: keyLegend;
|
|
228
264
|
// Cut to the width on plain text: the status line must stay one row (the
|
|
229
265
|
// viewport math counts it as one), and a label or legend that wrapped
|
|
230
266
|
// would push the document up.
|
|
231
|
-
const statusLine = dim(cutToWidth(`${statusLabel} ${
|
|
267
|
+
const statusLine = dim(cutToWidth(`${statusLabel} ${legend}`, width), color);
|
|
232
268
|
const status = _jsx(Text, { children: statusLine });
|
|
233
269
|
if (viewport === undefined) {
|
|
234
270
|
return (_jsx(FocusContext.Provider, { value: api, children: _jsxs(Box, { flexDirection: "column", children: [children, status] }) }));
|
package/dist/render.d.ts
CHANGED
|
@@ -57,13 +57,6 @@ export interface RenderMarkOptions {
|
|
|
57
57
|
readonly resolveImageSrc?: ResolveImageSrc;
|
|
58
58
|
readonly resolveHref?: ResolveHref;
|
|
59
59
|
readonly onDiagnostic?: OnDiagnostic;
|
|
60
|
-
/**
|
|
61
|
-
* Also report a directive that names no registered component as an
|
|
62
|
-
* `'unknown-directive'` event. Off by default: the fallback box already
|
|
63
|
-
* marks it in the output. A host that places findings in the note's
|
|
64
|
-
* source (a language server) turns it on.
|
|
65
|
-
*/
|
|
66
|
-
readonly reportUnknownDirectives?: boolean;
|
|
67
60
|
/**
|
|
68
61
|
* Components of installed packs that this render cannot draw, as plain
|
|
69
62
|
* data from the host. A directive named here renders the usual fallback
|
|
@@ -133,5 +126,7 @@ export declare function renderMarkInlineToAnsi(text: string, registry?: AnsiRegi
|
|
|
133
126
|
*/
|
|
134
127
|
export declare function buildMarkElement(document: string | MarkNode | MarkRoot, registry?: AnsiRegistry, options?: RenderMarkOptions & {
|
|
135
128
|
readonly onExit?: () => void;
|
|
129
|
+
/** Called when the reader presses `r`; see `InteractiveRoot`'s `onRerun`. The legend lists the key only when this is given. */
|
|
130
|
+
readonly onRerun?: () => void | Promise<void>;
|
|
136
131
|
}): ReactElement;
|
|
137
132
|
export {};
|
package/dist/render.js
CHANGED
|
@@ -15,8 +15,8 @@ import { sanitizeBlockText, sanitizeUrlText, stripControlCharacters, } from './s
|
|
|
15
15
|
import { readRegistryComponent, registryLayoutAxis, registrySelfLayout, resolveDirectiveAlias, } from './registry.js';
|
|
16
16
|
import { applyLayout, resolveLayoutAttributes, } from './layout.js';
|
|
17
17
|
import { resolveScopedPath } from './resolve.js';
|
|
18
|
-
import { dataStateSuffix, emptyInlineTitle, failureToken, codeRendererFailedTitle, formMismatchTitle, NO_ENGINE_VIEW_LABEL, noEngineViewTitle, packLoadFailedLabel, packLoadFailedTitle, invalidAttributeValueLabel, invalidAttributeValueTitle, unsafeImageSrcLabel,
|
|
19
|
-
import { createUnavailableComponentLookup, formatValue,
|
|
18
|
+
import { dataStateSuffix, emptyInlineTitle, failureToken, codeRendererFailedTitle, formMismatchTitle, NO_ENGINE_VIEW_LABEL, noEngineViewTitle, packLoadFailedLabel, packLoadFailedTitle, invalidAttributeValueLabel, invalidAttributeValueTitle, unsafeImageSrcLabel, unsafeImageSrcTitle, } from './failure-presentation.js';
|
|
19
|
+
import { createUnavailableComponentLookup, formatValue, invalidEnumAttribute, reportDiagnostic, } from '@markii/stdlib';
|
|
20
20
|
import { resolveImageAttribute, } from './image-resolve.js';
|
|
21
21
|
import { resolveHrefAttribute } from './href-resolve.js';
|
|
22
22
|
import { defaultAnsiRegistry } from './components/index.js';
|
|
@@ -289,23 +289,6 @@ function resolveDataAttribute(attributes, scope) {
|
|
|
289
289
|
dataFailureKind: resolved.status === 'error' ? resolved.failureKind : undefined,
|
|
290
290
|
};
|
|
291
291
|
}
|
|
292
|
-
/** Whether one of `name`'s `@markii/stdlib` contract attributes with a closed `enum` is present with a value outside it. */
|
|
293
|
-
function invalidEnumAttribute(name, attributes) {
|
|
294
|
-
const contract = getContract(name);
|
|
295
|
-
if (!contract)
|
|
296
|
-
return undefined;
|
|
297
|
-
for (const [attribute, schema] of Object.entries(contract.attributes)) {
|
|
298
|
-
const enumValues = schema.enum;
|
|
299
|
-
if (!enumValues)
|
|
300
|
-
continue;
|
|
301
|
-
const value = attributes[attribute];
|
|
302
|
-
if (value === undefined || value === null || value === '')
|
|
303
|
-
continue;
|
|
304
|
-
if (!enumValues.includes(value))
|
|
305
|
-
return { attribute, value };
|
|
306
|
-
}
|
|
307
|
-
return undefined;
|
|
308
|
-
}
|
|
309
292
|
/** Resolves a `data=`/`:value[]` name against `scope`. Never throws. */
|
|
310
293
|
function resolveValue(scope, name) {
|
|
311
294
|
const trimmed = name.trim();
|
|
@@ -412,11 +395,6 @@ function renderDirectiveContentString(name, kind, isBlock, attributes, childrenT
|
|
|
412
395
|
});
|
|
413
396
|
return unknownDirective(name, inline, safeChildrenText(childrenText), missingView.loadFailed ? 'pack-load-failed' : 'no-engine-view', width, wctx.color, wctx.glyphs, missingView.pack);
|
|
414
397
|
}
|
|
415
|
-
reportDiagnostic(wctx.onDiagnostic, {
|
|
416
|
-
kind: 'unknown-directive',
|
|
417
|
-
directive: name || '(unnamed)',
|
|
418
|
-
message: unknownDirectiveTitle(name || '(unnamed)'),
|
|
419
|
-
});
|
|
420
398
|
return unknownDirective(name || '(unnamed)', inline, safeChildrenText(childrenText), 'unregistered', width, wctx.color, wctx.glyphs);
|
|
421
399
|
}
|
|
422
400
|
if (isFormMismatch(entry, kind)) {
|
|
@@ -460,6 +438,11 @@ function renderDirectiveContentString(name, kind, isBlock, attributes, childrenT
|
|
|
460
438
|
}
|
|
461
439
|
if (isRegisteredInline(entry) &&
|
|
462
440
|
safeChildrenText(childrenText).trim() === '') {
|
|
441
|
+
reportDiagnostic(wctx.onDiagnostic, {
|
|
442
|
+
kind: 'empty-inline',
|
|
443
|
+
directive: name,
|
|
444
|
+
message: emptyInlineTitle(name),
|
|
445
|
+
});
|
|
463
446
|
rendered = `${rendered}${dim(` (${emptyInlineTitle(name)})`, wctx.color)}`;
|
|
464
447
|
}
|
|
465
448
|
return rendered;
|
|
@@ -1475,23 +1458,6 @@ function buildWalkContext(registry, scope, color, theme, glyphs, interactive, re
|
|
|
1475
1458
|
focusables: undefined,
|
|
1476
1459
|
};
|
|
1477
1460
|
}
|
|
1478
|
-
/**
|
|
1479
|
-
* The `onDiagnostic` a render hands its walk: the caller's own, minus
|
|
1480
|
-
* `'unknown-directive'` events unless `reportUnknownDirectives` asked for
|
|
1481
|
-
* them. The fallback box already marks an unknown directive in the output,
|
|
1482
|
-
* so a host that does not place findings in a source (the viewer, an
|
|
1483
|
-
* export) keeps the quiet diagnostics surface it always had.
|
|
1484
|
-
*/
|
|
1485
|
-
function diagnosticsFor(options) {
|
|
1486
|
-
const downstream = options?.onDiagnostic;
|
|
1487
|
-
if (downstream === undefined || options?.reportUnknownDirectives === true) {
|
|
1488
|
-
return downstream;
|
|
1489
|
-
}
|
|
1490
|
-
return (event) => {
|
|
1491
|
-
if (event.kind !== 'unknown-directive')
|
|
1492
|
-
downstream(event);
|
|
1493
|
-
};
|
|
1494
|
-
}
|
|
1495
1461
|
/** The columns assumed when a caller supplies no `width` option. */
|
|
1496
1462
|
const DEFAULT_WIDTH = 80;
|
|
1497
1463
|
/** Builds the root Ink element for `root`, given every resolved render input. Exported for `buildMarkElement` (the live-viewer entry point) as well as this module's own three string-producing entry points. */
|
|
@@ -1525,7 +1491,7 @@ async function renderRootToString(root, registry, scope, color, theme, glyphs, i
|
|
|
1525
1491
|
export async function renderMarkToAnsi(text, registry = defaultAnsiRegistry, store, vault, options) {
|
|
1526
1492
|
const color = resolveColorOption(options?.color);
|
|
1527
1493
|
try {
|
|
1528
|
-
return await renderRootToString(toHast(text), registry, { store: options?.store ?? store, vault: options?.vault ?? vault }, color, options?.theme ?? defaultAnsiTheme, glyphsFor(options?.box), options?.interactive ?? false, options?.resolveImageSrc, options?.resolveHref,
|
|
1494
|
+
return await renderRootToString(toHast(text), registry, { store: options?.store ?? store, vault: options?.vault ?? vault }, color, options?.theme ?? defaultAnsiTheme, glyphsFor(options?.box), options?.interactive ?? false, options?.resolveImageSrc, options?.resolveHref, options?.onDiagnostic, createUnavailableComponentLookup(options?.unavailableComponents), options?.width ?? DEFAULT_WIDTH, options?.renderCode);
|
|
1529
1495
|
}
|
|
1530
1496
|
catch (error) {
|
|
1531
1497
|
return renderFailureFallback(error, color);
|
|
@@ -1540,7 +1506,7 @@ export async function renderMarkToAnsi(text, registry = defaultAnsiRegistry, sto
|
|
|
1540
1506
|
export async function renderMarkNodeToAnsi(node, registry = defaultAnsiRegistry, store, vault, options) {
|
|
1541
1507
|
const color = resolveColorOption(options?.color);
|
|
1542
1508
|
try {
|
|
1543
|
-
return await renderRootToString(nodeOrRootToHast(node), registry, { store: options?.store ?? store, vault: options?.vault ?? vault }, color, options?.theme ?? defaultAnsiTheme, glyphsFor(options?.box), options?.interactive ?? false, options?.resolveImageSrc, options?.resolveHref,
|
|
1509
|
+
return await renderRootToString(nodeOrRootToHast(node), registry, { store: options?.store ?? store, vault: options?.vault ?? vault }, color, options?.theme ?? defaultAnsiTheme, glyphsFor(options?.box), options?.interactive ?? false, options?.resolveImageSrc, options?.resolveHref, options?.onDiagnostic, createUnavailableComponentLookup(options?.unavailableComponents), options?.width ?? DEFAULT_WIDTH, options?.renderCode);
|
|
1544
1510
|
}
|
|
1545
1511
|
catch (error) {
|
|
1546
1512
|
return renderFailureFallback(error, color);
|
|
@@ -1604,7 +1570,7 @@ export function buildMarkElement(document, registry = defaultAnsiRegistry, optio
|
|
|
1604
1570
|
root = { type: 'root', children: [] };
|
|
1605
1571
|
}
|
|
1606
1572
|
const unavailable = createUnavailableComponentLookup(options?.unavailableComponents);
|
|
1607
|
-
const content = buildRootElement(root, registry, scope, color, theme, glyphs, interactive, options?.resolveImageSrc, options?.resolveHref,
|
|
1573
|
+
const content = buildRootElement(root, registry, scope, color, theme, glyphs, interactive, options?.resolveImageSrc, options?.resolveHref, options?.onDiagnostic, unavailable, width, options?.renderCode);
|
|
1608
1574
|
if (!interactive)
|
|
1609
1575
|
return content;
|
|
1610
1576
|
// The walk above already assigned every focusable component's `focusId`
|
|
@@ -1626,5 +1592,5 @@ export function buildMarkElement(document, registry = defaultAnsiRegistry, optio
|
|
|
1626
1592
|
countingWctx.focusCounter = counter;
|
|
1627
1593
|
countingWctx.focusables = focusables;
|
|
1628
1594
|
renderBlocksElement(root.children, width, '', countingWctx);
|
|
1629
|
-
return (_jsx(InteractiveRoot, { focusables: focusables, onExit: options?.onExit, color: color, theme: theme, keyLegend: glyphs.keyLegend, viewportRows: options?.viewportRows, width: width, children: content }));
|
|
1595
|
+
return (_jsx(InteractiveRoot, { focusables: focusables, onExit: options?.onExit, onRerun: options?.onRerun, rerunLegend: glyphs.keyLegendRerun, color: color, theme: theme, keyLegend: glyphs.keyLegend, viewportRows: options?.viewportRows, width: width, children: content }));
|
|
1630
1596
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@markii/ansi",
|
|
3
|
-
"version": "0.17.0-next.
|
|
3
|
+
"version": "0.17.0-next.5",
|
|
4
4
|
"description": "The terminal renderer for Markii (.mk.md): a registry-driven hast-to-terminal engine built on Ink. Renders a note once as a string with optional color, for a pipe or a log, or as a live Ink tree a host can mount.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"markdown",
|
|
@@ -51,15 +51,15 @@
|
|
|
51
51
|
"regenerate:fixtures": "npm run build:dist && node scripts/regenerate-ansi-fixtures.ts"
|
|
52
52
|
},
|
|
53
53
|
"dependencies": {
|
|
54
|
-
"@markii/core": "^0.17.0-next.
|
|
55
|
-
"@markii/pack": "^0.17.0-next.
|
|
56
|
-
"@markii/stdlib": "^0.17.0-next.
|
|
54
|
+
"@markii/core": "^0.17.0-next.5",
|
|
55
|
+
"@markii/pack": "^0.17.0-next.5",
|
|
56
|
+
"@markii/stdlib": "^0.17.0-next.5",
|
|
57
57
|
"ink": "^7.1.1",
|
|
58
58
|
"react": "^19.2.0"
|
|
59
59
|
},
|
|
60
60
|
"devDependencies": {
|
|
61
61
|
"@types/hast": "^3.0.4",
|
|
62
|
-
"@markii/runtime": "^0.17.0-next.
|
|
62
|
+
"@markii/runtime": "^0.17.0-next.5",
|
|
63
63
|
"@types/react": "^19.2.0"
|
|
64
64
|
}
|
|
65
65
|
}
|