uxml-preview 0.1.0 → 0.2.0
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/CHANGELOG.md +97 -1
- package/README.md +84 -46
- package/dist/controls/registry.d.ts +59 -2
- package/dist/controls/theme.d.ts +87 -0
- package/dist/index.d.ts +24 -6
- package/dist/index.js +1108 -791
- package/dist/layout/yoga.d.ts +34 -1
- package/dist/model/types.d.ts +33 -2
- package/dist/parser/entities.d.ts +19 -0
- package/dist/render/paint.d.ts +14 -2
- package/dist/style/resolve.d.ts +50 -2
- package/dist/style/selector.d.ts +50 -9
- package/package.json +86 -59
package/dist/layout/yoga.d.ts
CHANGED
|
@@ -42,9 +42,31 @@ export interface LayoutOptions {
|
|
|
42
42
|
*/
|
|
43
43
|
measureText: MeasureText;
|
|
44
44
|
}
|
|
45
|
+
/**
|
|
46
|
+
* A laid-out element the file never mentioned, built by a control.
|
|
47
|
+
*
|
|
48
|
+
* Separate from `boxes` rather than sharing its keys: `NodeId` identifies
|
|
49
|
+
* something in the document, and these have no document to be in. Giving them
|
|
50
|
+
* borrowed ids would make "which node is this?" answerable with a lie, and an
|
|
51
|
+
* editor asking that question needs to hear "this one is not yours".
|
|
52
|
+
*/
|
|
53
|
+
export interface LayoutPart {
|
|
54
|
+
/** Unity's name, e.g. `unity-content-viewport`. */
|
|
55
|
+
name: string;
|
|
56
|
+
/** The element whose control built it. */
|
|
57
|
+
owner: NodeId;
|
|
58
|
+
box: LayoutBox;
|
|
59
|
+
/** Fixed styling, with `builtin-theme` provenance on every value. */
|
|
60
|
+
style: ComputedStyle;
|
|
61
|
+
}
|
|
45
62
|
export interface LayoutTree {
|
|
46
63
|
/** Computed box per element, in panel coordinates. */
|
|
47
64
|
boxes: ReadonlyMap<NodeId, LayoutBox>;
|
|
65
|
+
/**
|
|
66
|
+
* Parts each element's control built, outermost first. The element's own
|
|
67
|
+
* children were laid out inside the last one.
|
|
68
|
+
*/
|
|
69
|
+
parts: ReadonlyMap<NodeId, readonly LayoutPart[]>;
|
|
48
70
|
/** Elements that were laid out, parents before children. */
|
|
49
71
|
painted: readonly ElementNode[];
|
|
50
72
|
warnings: readonly Warning[];
|
|
@@ -60,4 +82,15 @@ export interface LayoutTree {
|
|
|
60
82
|
* Deps/Effects: creates Yoga nodes; the returned tree owns them until disposed.
|
|
61
83
|
* Requires: `loadLayoutEngine()` must have resolved.
|
|
62
84
|
*/
|
|
63
|
-
export declare function layoutDocument(root: ElementNode, styles: ReadonlyMap<NodeId, ComputedStyle>,
|
|
85
|
+
export declare function layoutDocument(root: ElementNode, styles: ReadonlyMap<NodeId, ComputedStyle>,
|
|
86
|
+
/**
|
|
87
|
+
* Style per control part, from the cascade.
|
|
88
|
+
*
|
|
89
|
+
* Taken rather than computed. This module used to build part styles itself
|
|
90
|
+
* from the registry's fixed declarations, which meant author USS could never
|
|
91
|
+
* reach them — `#unity-content-container { flex-direction: row }` had nowhere
|
|
92
|
+
* to land, because the part did not exist until after the cascade had run.
|
|
93
|
+
* Resolving parts alongside elements is what fixes that, and computing them
|
|
94
|
+
* in two places would put the second cascade back.
|
|
95
|
+
*/
|
|
96
|
+
partStyles: ReadonlyMap<NodeId, ReadonlyMap<string, ComputedStyle>>, options: LayoutOptions): LayoutTree;
|
package/dist/model/types.d.ts
CHANGED
|
@@ -251,8 +251,10 @@ export interface UxmlDocument {
|
|
|
251
251
|
* Where a computed value came from.
|
|
252
252
|
*
|
|
253
253
|
* Phase 8 needs this to answer "write to the inline style, or edit the rule?".
|
|
254
|
-
* Every variant points into the model, so the editor
|
|
255
|
-
* declaration's span and rewrite exactly that text.
|
|
254
|
+
* Every variant *except `builtin-theme`* points into the model, so the editor
|
|
255
|
+
* can jump straight to the declaration's span and rewrite exactly that text.
|
|
256
|
+
* `builtin-theme` is the one that does not, and it says so rather than
|
|
257
|
+
* inventing a location — an editor must branch on it, not follow it.
|
|
256
258
|
*
|
|
257
259
|
* Note the inline variant indexes declarations parsed on demand from the
|
|
258
260
|
* element's `style` attribute — those declarations are not stored on the node.
|
|
@@ -268,11 +270,40 @@ export type StyleOrigin = {
|
|
|
268
270
|
sheet: number;
|
|
269
271
|
item: number;
|
|
270
272
|
declIndex: number;
|
|
273
|
+
/**
|
|
274
|
+
* Pseudo-class states the matched selector required, e.g. `['hover']`.
|
|
275
|
+
*
|
|
276
|
+
* Absent when the rule applies unconditionally. Present, it means the
|
|
277
|
+
* value is only true while those states hold — an editor showing "this
|
|
278
|
+
* came from line 12" without it would be telling half the truth, and a
|
|
279
|
+
* user would edit the base appearance while looking at the hover one.
|
|
280
|
+
*/
|
|
281
|
+
states?: readonly string[];
|
|
271
282
|
} | {
|
|
272
283
|
kind: 'inherited';
|
|
273
284
|
from: NodeId;
|
|
274
285
|
origin: StyleOrigin;
|
|
275
286
|
}
|
|
287
|
+
/**
|
|
288
|
+
* A control default this renderer supplies, standing in for Unity's theme
|
|
289
|
+
* stylesheet. **There is no file and no span**: the declaration exists in this
|
|
290
|
+
* library, not in the user's project.
|
|
291
|
+
*
|
|
292
|
+
* Its own variant rather than a `rule` with an invented path, because an
|
|
293
|
+
* editor offering "jump to the declaration" must be able to tell that there
|
|
294
|
+
* is nowhere to jump — pointing at a file that does not exist is worse than
|
|
295
|
+
* saying the value is not editable.
|
|
296
|
+
*
|
|
297
|
+
* `unityVersion` records where the value was measured. Theme values move
|
|
298
|
+
* between Unity versions, and when one stops matching this is the first thing
|
|
299
|
+
* to check.
|
|
300
|
+
*/
|
|
301
|
+
| {
|
|
302
|
+
kind: 'builtin-theme';
|
|
303
|
+
selector: string;
|
|
304
|
+
property: string;
|
|
305
|
+
unityVersion: string;
|
|
306
|
+
}
|
|
276
307
|
/** USS default, which is not always the CSS default — `flex-direction` is `column`. */
|
|
277
308
|
| {
|
|
278
309
|
kind: 'default';
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* XML entity decoding, for the moment a stored attribute becomes a real value.
|
|
3
|
+
*
|
|
4
|
+
* The parser deliberately keeps attribute values exactly as written — that is
|
|
5
|
+
* what makes serialization byte-exact — so `&` survives in the model. Any
|
|
6
|
+
* consumer that means to *use* the value rather than re-emit it has to decode
|
|
7
|
+
* first, and there are two: painted text, and paths handed to the host's
|
|
8
|
+
* resolver hooks. A `<Style src="…?a=1&b=2">` reaching `resolveImport`
|
|
9
|
+
* undecoded gives the host `amp;b=2` to parse, which is not a thing.
|
|
10
|
+
*/
|
|
11
|
+
/**
|
|
12
|
+
* Purpose: turn stored attribute text into the value it stands for.
|
|
13
|
+
* Ensures: never throws. A numeric reference outside the Unicode range
|
|
14
|
+
* makes `String.fromCodePoint` raise a RangeError, and one bad
|
|
15
|
+
* character must not take down a render (CLAUDE.md rule 6).
|
|
16
|
+
* Unreadable references are left as written, which also
|
|
17
|
+
* round-trips.
|
|
18
|
+
*/
|
|
19
|
+
export declare function decodeEntities(text: string): string;
|
package/dist/render/paint.d.ts
CHANGED
|
@@ -1,8 +1,20 @@
|
|
|
1
1
|
import { ElementNode, NodeId, Warning } from '../model/types';
|
|
2
2
|
import { ComputedStyle } from '../style/resolve';
|
|
3
|
-
import { LayoutBox } from '../layout/yoga';
|
|
3
|
+
import { LayoutBox, LayoutPart } from '../layout/yoga';
|
|
4
4
|
import { CssMapOptions } from './css-map';
|
|
5
5
|
export declare const NODE_ATTRIBUTE = "data-uxml-node";
|
|
6
|
+
/**
|
|
7
|
+
* Marks an element a control built rather than one the file asked for, and
|
|
8
|
+
* carries Unity's name for it.
|
|
9
|
+
*
|
|
10
|
+
* Deliberately not `data-uxml-node`: these have no node. An editor that traced
|
|
11
|
+
* a click back through the node attribute would get an id that belongs to
|
|
12
|
+
* something else, and would then offer to edit the wrong element. Here it finds
|
|
13
|
+
* a different attribute and can say "this part is not yours to change".
|
|
14
|
+
*/
|
|
15
|
+
export declare const PART_ATTRIBUTE = "data-uxml-part";
|
|
16
|
+
/** The element whose control built a part. Lets a click land on its owner. */
|
|
17
|
+
export declare const PART_OWNER_ATTRIBUTE = "data-uxml-part-owner";
|
|
6
18
|
export interface PaintResult {
|
|
7
19
|
warnings: Warning[];
|
|
8
20
|
/** Painted element per model node, for hit-testing and for tests. */
|
|
@@ -16,4 +28,4 @@ export interface PaintOptions extends CssMapOptions {
|
|
|
16
28
|
* Deps/Effects: replaces the container's children. The caller owns disposal.
|
|
17
29
|
* Requires: `boxes` must come from a layout of this same tree.
|
|
18
30
|
*/
|
|
19
|
-
export declare function paint(root: ElementNode, boxes: ReadonlyMap<NodeId, LayoutBox>, styles: ReadonlyMap<NodeId, ComputedStyle>, container: HTMLElement, options: PaintOptions): PaintResult;
|
|
31
|
+
export declare function paint(root: ElementNode, boxes: ReadonlyMap<NodeId, LayoutBox>, parts: ReadonlyMap<NodeId, readonly LayoutPart[]>, styles: ReadonlyMap<NodeId, ComputedStyle>, container: HTMLElement, options: PaintOptions): PaintResult;
|
package/dist/style/resolve.d.ts
CHANGED
|
@@ -7,20 +7,68 @@ export interface ComputedValue {
|
|
|
7
7
|
}
|
|
8
8
|
export type ComputedStyle = ReadonlyMap<string, ComputedValue>;
|
|
9
9
|
export interface ResolveOptions {
|
|
10
|
-
/**
|
|
10
|
+
/**
|
|
11
|
+
* Pseudo-classes to treat as active on every element, e.g. `new Set(['hover'])`.
|
|
12
|
+
*
|
|
13
|
+
* Blunt, and kept for the case where that is what you want. Per-element
|
|
14
|
+
* control is `states`.
|
|
15
|
+
*/
|
|
11
16
|
activeStates?: ReadonlySet<string>;
|
|
17
|
+
/**
|
|
18
|
+
* Pseudo-classes to activate per element, keyed by USS selector.
|
|
19
|
+
*
|
|
20
|
+
* ```ts
|
|
21
|
+
* { '#UseButton': ['hover'], '#DropButton': ['disabled'] }
|
|
22
|
+
* ```
|
|
23
|
+
*
|
|
24
|
+
* States are explicit input, never mouse events: a render that depends on
|
|
25
|
+
* where the pointer is cannot be compared to anything twice.
|
|
26
|
+
*
|
|
27
|
+
* Keys are matched against the tree **without** any state applied, so a key
|
|
28
|
+
* cannot switch itself on, and `:hover` in a key is meaningless.
|
|
29
|
+
*/
|
|
30
|
+
states?: Readonly<Record<string, readonly string[]>>;
|
|
12
31
|
}
|
|
13
32
|
export interface ResolveResult {
|
|
14
33
|
styles: ReadonlyMap<NodeId, ComputedStyle>;
|
|
34
|
+
/**
|
|
35
|
+
* Style per control part, keyed by the owning element and then Unity's name
|
|
36
|
+
* for the part.
|
|
37
|
+
*
|
|
38
|
+
* Parts are resolved here rather than in the layout, because that is what
|
|
39
|
+
* lets author USS reach them: `#unity-content-container { flex-direction: row }`
|
|
40
|
+
* is how a real project lays out a scroll region's contents, and a part built
|
|
41
|
+
* after the cascade had already run could never receive it.
|
|
42
|
+
*/
|
|
43
|
+
partStyles: ReadonlyMap<NodeId, ReadonlyMap<string, ComputedStyle>>;
|
|
15
44
|
warnings: readonly Warning[];
|
|
16
45
|
}
|
|
46
|
+
/**
|
|
47
|
+
* Where a declaration sits in the cascade's outermost comparison.
|
|
48
|
+
*
|
|
49
|
+
* Unity's control defaults are not "a stylesheet that loaded first" — they are
|
|
50
|
+
* a lower origin, the way a browser's user-agent sheet is, so **an author rule
|
|
51
|
+
* beats them regardless of specificity**. Measured, not reasoned: the
|
|
52
|
+
* `states-disabled` case writes `Button { margin: 0 }` (a type selector, 0,0,1)
|
|
53
|
+
* against the theme's `.unity-button` (a class, 0,1,0), and Unity puts the
|
|
54
|
+
* button at x=0. Specificity alone would have put it at x=3.
|
|
55
|
+
*
|
|
56
|
+
* This is the axis the cascade was missing. Without it the theme wins ties it
|
|
57
|
+
* should lose, and every value added to `theme.ts` spreads the error.
|
|
58
|
+
*/
|
|
59
|
+
export declare const enum Rank {
|
|
60
|
+
BuiltinTheme = 0,
|
|
61
|
+
Author = 1
|
|
62
|
+
}
|
|
17
63
|
/** One declaration that competed, winner or not. */
|
|
18
64
|
export interface Candidate {
|
|
19
65
|
property: string;
|
|
20
66
|
value: string;
|
|
21
67
|
origin: StyleOrigin;
|
|
68
|
+
/** Compared before specificity. A built-in default never beats author USS. */
|
|
69
|
+
rank: Rank;
|
|
22
70
|
specificity: Specificity;
|
|
23
|
-
/** Position in cascade order; higher wins a specificity tie. */
|
|
71
|
+
/** Position in cascade order; higher wins a specificity tie within a rank. */
|
|
24
72
|
order: number;
|
|
25
73
|
winner: boolean;
|
|
26
74
|
}
|
package/dist/style/selector.d.ts
CHANGED
|
@@ -1,7 +1,21 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
1
|
+
import { Selector } from '../model/types';
|
|
2
|
+
/**
|
|
3
|
+
* How to interrogate whatever is being matched.
|
|
4
|
+
*
|
|
5
|
+
* Deps: every function here is read during matching, including for ancestors —
|
|
6
|
+
* `.panel:hover .item` asks the ancestor for its states, not the element's.
|
|
7
|
+
*/
|
|
8
|
+
export interface MatchContext<T> {
|
|
9
|
+
/**
|
|
10
|
+
* The style parent, which is not always the layout parent.
|
|
11
|
+
*
|
|
12
|
+
* Measured, and it decides the shape of this whole design: a slot inside a
|
|
13
|
+
* ScrollView sits physically inside `unity-content-container`, yet
|
|
14
|
+
* `#Grid > .slot` reaches it in Unity. So an element from the file keeps its
|
|
15
|
+
* file parent here, and the parts a control builds are transparent to it.
|
|
16
|
+
* See `child-combinator-through-parts` and the 2026-08-06 decision rows.
|
|
17
|
+
*/
|
|
18
|
+
parentOf: (target: T) => T | null;
|
|
5
19
|
/**
|
|
6
20
|
* The element `:root` refers to.
|
|
7
21
|
*
|
|
@@ -11,11 +25,38 @@ export interface MatchContext {
|
|
|
11
25
|
* keeps the usual custom-property token pattern working, since values
|
|
12
26
|
* declared there inherit down the whole tree.
|
|
13
27
|
*/
|
|
14
|
-
|
|
15
|
-
/** Pseudo-classes
|
|
16
|
-
|
|
28
|
+
isRoot: (target: T) => boolean;
|
|
29
|
+
/** Pseudo-classes active on this target, e.g. `hover`. */
|
|
30
|
+
statesOf: (target: T) => ReadonlySet<string>;
|
|
31
|
+
/** What a type selector compares against — the C# class name, not a tag. */
|
|
32
|
+
typeNameOf: (target: T) => string;
|
|
33
|
+
/** What `#name` compares against. */
|
|
34
|
+
idOf: (target: T) => string | undefined;
|
|
35
|
+
/** Written classes plus any the control adds, e.g. `unity-button`. */
|
|
36
|
+
classesOf: (target: T) => readonly string[];
|
|
17
37
|
}
|
|
18
|
-
export declare function matchesSelector(selector: Selector,
|
|
38
|
+
export declare function matchesSelector<T>(selector: Selector, target: T, ctx: MatchContext<T>): boolean;
|
|
39
|
+
/**
|
|
40
|
+
* Purpose: the state pseudo-classes a selector depends on, in source order.
|
|
41
|
+
* Ensures: `:root` is excluded — it names a position in the tree, not a
|
|
42
|
+
* state, and cannot be switched on or off.
|
|
43
|
+
*
|
|
44
|
+
* Used for provenance: a value from `.unity-button:hover` is only true while
|
|
45
|
+
* hovering, and an editor that does not know this rewrites the wrong rule.
|
|
46
|
+
*/
|
|
47
|
+
export declare function statesRequiredBy(selector: Selector): string[];
|
|
48
|
+
/**
|
|
49
|
+
* Purpose: names and classes in a selector that belong to Unity, not the author.
|
|
50
|
+
* Ensures: returns the `unity-` prefixed fragments only.
|
|
51
|
+
*
|
|
52
|
+
* An author writing `#unity-text-input` or `.unity-scroll-view__content-container`
|
|
53
|
+
* is aiming at a part a control builds. If nothing matches, that is not an
|
|
54
|
+
* unused rule — it is a rule that cannot work, and saying nothing about it is
|
|
55
|
+
* the silent loss CLAUDE.md rule 6 exists to prevent.
|
|
56
|
+
*/
|
|
57
|
+
export declare function unityFragmentsIn(selectors: readonly Selector[]): string[];
|
|
19
58
|
/** The first unsupported fragment in a selector group, if any. */
|
|
20
59
|
export declare function unsupportedFragment(selectors: readonly Selector[]): string | null;
|
|
21
|
-
export declare function buildParentMap
|
|
60
|
+
export declare function buildParentMap<T extends {
|
|
61
|
+
children: readonly T[];
|
|
62
|
+
}>(root: T): Map<T, T | null>;
|
package/package.json
CHANGED
|
@@ -1,59 +1,86 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "uxml-preview",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "Preview Unity UI Toolkit UXML/USS in a browser without the Unity Editor. Uses Yoga (WebAssembly), the same layout engine UI Toolkit uses: 242 of 244 element coordinates identical to Unity 6. Parses and writes files back byte-for-byte.",
|
|
5
|
-
"keywords": [
|
|
6
|
-
"unity",
|
|
7
|
-
"
|
|
8
|
-
"
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
"
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
"
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
"
|
|
30
|
-
"
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
"
|
|
38
|
-
"
|
|
39
|
-
"
|
|
40
|
-
"
|
|
41
|
-
"
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
"
|
|
52
|
-
"
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
"
|
|
57
|
-
},
|
|
58
|
-
"
|
|
59
|
-
|
|
1
|
+
{
|
|
2
|
+
"name": "uxml-preview",
|
|
3
|
+
"version": "0.2.0",
|
|
4
|
+
"description": "Preview Unity UI Toolkit UXML/USS in a browser without the Unity Editor. Uses Yoga (WebAssembly), the same layout engine UI Toolkit uses: 242 of 244 element coordinates identical to Unity 6. Parses and writes files back byte-for-byte.",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"unity",
|
|
7
|
+
"unity3d",
|
|
8
|
+
"ui-toolkit",
|
|
9
|
+
"uitk",
|
|
10
|
+
"uielements",
|
|
11
|
+
"uxml",
|
|
12
|
+
"uss",
|
|
13
|
+
"yoga",
|
|
14
|
+
"yoga-layout",
|
|
15
|
+
"flexbox",
|
|
16
|
+
"webassembly",
|
|
17
|
+
"renderer",
|
|
18
|
+
"preview",
|
|
19
|
+
"game-ui",
|
|
20
|
+
"typescript",
|
|
21
|
+
"editor-tooling",
|
|
22
|
+
"unity-editor",
|
|
23
|
+
"css-to-uss"
|
|
24
|
+
],
|
|
25
|
+
"license": "Apache-2.0",
|
|
26
|
+
"type": "module",
|
|
27
|
+
"main": "./dist/index.js",
|
|
28
|
+
"module": "./dist/index.js",
|
|
29
|
+
"types": "./dist/index.d.ts",
|
|
30
|
+
"exports": {
|
|
31
|
+
".": {
|
|
32
|
+
"types": "./dist/index.d.ts",
|
|
33
|
+
"import": "./dist/index.js"
|
|
34
|
+
}
|
|
35
|
+
},
|
|
36
|
+
"files": [
|
|
37
|
+
"dist",
|
|
38
|
+
"README.md",
|
|
39
|
+
"LICENSE",
|
|
40
|
+
"THIRD-PARTY-NOTICES.md",
|
|
41
|
+
"CHANGELOG.md"
|
|
42
|
+
],
|
|
43
|
+
"sideEffects": false,
|
|
44
|
+
"engines": {
|
|
45
|
+
"node": ">=18"
|
|
46
|
+
},
|
|
47
|
+
"publishConfig": {
|
|
48
|
+
"access": "public"
|
|
49
|
+
},
|
|
50
|
+
"repository": {
|
|
51
|
+
"type": "git",
|
|
52
|
+
"url": "git+https://github.com/ReuHomi/uxml-preview.git"
|
|
53
|
+
},
|
|
54
|
+
"homepage": "https://reuhomi.github.io/uxml-preview/",
|
|
55
|
+
"bugs": {
|
|
56
|
+
"url": "https://github.com/ReuHomi/uxml-preview/issues"
|
|
57
|
+
},
|
|
58
|
+
"scripts": {
|
|
59
|
+
"dev": "vite",
|
|
60
|
+
"build": "tsc --noEmit && vite build",
|
|
61
|
+
"build:site": "vite build --config vite.playground.config.ts",
|
|
62
|
+
"preview:site": "vite preview --config vite.playground.config.ts",
|
|
63
|
+
"test": "vitest run",
|
|
64
|
+
"test:watch": "vitest",
|
|
65
|
+
"test:roundtrip": "vitest run tests/roundtrip",
|
|
66
|
+
"test:golden": "vitest run tests/golden --passWithNoTests",
|
|
67
|
+
"golden:emit": "node --experimental-strip-types --no-warnings scripts/emit-golden-cases.mjs",
|
|
68
|
+
"golden:update": "node scripts/update-golden.mjs",
|
|
69
|
+
"typecheck": "tsc --noEmit",
|
|
70
|
+
"prepublishOnly": "npm run typecheck && npm run test && npm run build"
|
|
71
|
+
},
|
|
72
|
+
"dependencies": {
|
|
73
|
+
"yoga-layout": "^3.2.1"
|
|
74
|
+
},
|
|
75
|
+
"devDependencies": {
|
|
76
|
+
"@types/node": "^22.0.0",
|
|
77
|
+
"jsdom": "^30.0.1",
|
|
78
|
+
"pixelmatch": "^6.0.0",
|
|
79
|
+
"pngjs": "^7.0.0",
|
|
80
|
+
"typescript": "^5.6.0",
|
|
81
|
+
"vite": "^6.0.0",
|
|
82
|
+
"vite-plugin-dts": "^4.3.0",
|
|
83
|
+
"vitest": "^2.1.0"
|
|
84
|
+
},
|
|
85
|
+
"packageManager": "pnpm@9.12.0"
|
|
86
|
+
}
|