uxml-preview 0.1.0 → 0.3.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 +166 -1
- package/README.md +93 -51
- package/dist/controls/registry.d.ts +59 -2
- package/dist/controls/theme.d.ts +87 -0
- package/dist/index.d.ts +36 -8
- package/dist/index.js +1198 -860
- package/dist/known-divergences.d.ts +36 -0
- package/dist/layout/yoga.d.ts +34 -1
- package/dist/model/types.d.ts +39 -3
- package/dist/parser/entities.d.ts +19 -0
- package/dist/render/css-map.d.ts +10 -1
- 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/dist/unity-project/index.d.ts +14 -0
- package/dist/unity-project/index.js +41 -0
- package/package.json +90 -59
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Differences from Unity that measurement has confirmed and that fixing the
|
|
3
|
+
* renderer cannot close. `docs/accuracy.md` describes 16 divergent values;
|
|
4
|
+
* all but one class of them are listed below.
|
|
5
|
+
*
|
|
6
|
+
* The 1px cases (3 values) are excluded on purpose: they sit inside the
|
|
7
|
+
* golden tests' own 0.5px-tighter-than-plan tolerance. That is a test
|
|
8
|
+
* judgement parameter, not a rendering limitation — listing it here would
|
|
9
|
+
* tell a host to worry about a difference the renderer did not actually make.
|
|
10
|
+
*
|
|
11
|
+
* If a fourth category is ever promoted here, extend this list and the
|
|
12
|
+
* pinned entry count in tests/known-divergences.test.ts together — do not
|
|
13
|
+
* let the list grow silently, since `id` is a contract hosts key off.
|
|
14
|
+
*/
|
|
15
|
+
export interface KnownDivergence {
|
|
16
|
+
/** Stable identifier. Hosts may key off this; do not rename. */
|
|
17
|
+
readonly id: string;
|
|
18
|
+
/**
|
|
19
|
+
* Why this cannot simply be fixed.
|
|
20
|
+
*
|
|
21
|
+
* 'unreproducible' — the difference comes from something we cannot
|
|
22
|
+
* reproduce at all, such as font metrics that move with the platform.
|
|
23
|
+
* 'unspecified' — Unity's own rule for this case is not specified,
|
|
24
|
+
* so there is no target to match yet.
|
|
25
|
+
* 'upstream' — the difference is fully reproducible and deterministic,
|
|
26
|
+
* but it lives in something this renderer depends on rather than in this
|
|
27
|
+
* renderer's own code — the place that would need to change is not this
|
|
28
|
+
* repository.
|
|
29
|
+
*/
|
|
30
|
+
readonly kind: 'unreproducible' | 'unspecified' | 'upstream';
|
|
31
|
+
/** One line, for a diagnostics list. */
|
|
32
|
+
readonly summary: string;
|
|
33
|
+
/** What is different and why, for someone deciding whether to care. */
|
|
34
|
+
readonly detail: string;
|
|
35
|
+
}
|
|
36
|
+
export declare const KNOWN_DIVERGENCES: readonly KnownDivergence[];
|
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
|
@@ -244,15 +244,22 @@ export interface UxmlDocument {
|
|
|
244
244
|
* own `source`, which is why the source text lives on the sheet.
|
|
245
245
|
*/
|
|
246
246
|
sheets: StyleSheet[];
|
|
247
|
-
/**
|
|
247
|
+
/**
|
|
248
|
+
* Parse-time only — `'malformed'` (bad syntax) and `'import-unresolved'`
|
|
249
|
+
* (a `<Style src="…">` or `@import` that `resolveImport` could not read).
|
|
250
|
+
* Support judgments (unsupported controls/properties/selectors/units,
|
|
251
|
+
* unresolved assets) happen downstream, in `RenderResult.warnings`.
|
|
252
|
+
*/
|
|
248
253
|
warnings: Warning[];
|
|
249
254
|
}
|
|
250
255
|
/**
|
|
251
256
|
* Where a computed value came from.
|
|
252
257
|
*
|
|
253
258
|
* 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.
|
|
259
|
+
* Every variant *except `builtin-theme`* points into the model, so the editor
|
|
260
|
+
* can jump straight to the declaration's span and rewrite exactly that text.
|
|
261
|
+
* `builtin-theme` is the one that does not, and it says so rather than
|
|
262
|
+
* inventing a location — an editor must branch on it, not follow it.
|
|
256
263
|
*
|
|
257
264
|
* Note the inline variant indexes declarations parsed on demand from the
|
|
258
265
|
* element's `style` attribute — those declarations are not stored on the node.
|
|
@@ -268,11 +275,40 @@ export type StyleOrigin = {
|
|
|
268
275
|
sheet: number;
|
|
269
276
|
item: number;
|
|
270
277
|
declIndex: number;
|
|
278
|
+
/**
|
|
279
|
+
* Pseudo-class states the matched selector required, e.g. `['hover']`.
|
|
280
|
+
*
|
|
281
|
+
* Absent when the rule applies unconditionally. Present, it means the
|
|
282
|
+
* value is only true while those states hold — an editor showing "this
|
|
283
|
+
* came from line 12" without it would be telling half the truth, and a
|
|
284
|
+
* user would edit the base appearance while looking at the hover one.
|
|
285
|
+
*/
|
|
286
|
+
states?: readonly string[];
|
|
271
287
|
} | {
|
|
272
288
|
kind: 'inherited';
|
|
273
289
|
from: NodeId;
|
|
274
290
|
origin: StyleOrigin;
|
|
275
291
|
}
|
|
292
|
+
/**
|
|
293
|
+
* A control default this renderer supplies, standing in for Unity's theme
|
|
294
|
+
* stylesheet. **There is no file and no span**: the declaration exists in this
|
|
295
|
+
* library, not in the user's project.
|
|
296
|
+
*
|
|
297
|
+
* Its own variant rather than a `rule` with an invented path, because an
|
|
298
|
+
* editor offering "jump to the declaration" must be able to tell that there
|
|
299
|
+
* is nowhere to jump — pointing at a file that does not exist is worse than
|
|
300
|
+
* saying the value is not editable.
|
|
301
|
+
*
|
|
302
|
+
* `unityVersion` records where the value was measured. Theme values move
|
|
303
|
+
* between Unity versions, and when one stops matching this is the first thing
|
|
304
|
+
* to check.
|
|
305
|
+
*/
|
|
306
|
+
| {
|
|
307
|
+
kind: 'builtin-theme';
|
|
308
|
+
selector: string;
|
|
309
|
+
property: string;
|
|
310
|
+
unityVersion: string;
|
|
311
|
+
}
|
|
276
312
|
/** USS default, which is not always the CSS default — `flex-direction` is `column`. */
|
|
277
313
|
| {
|
|
278
314
|
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/css-map.d.ts
CHANGED
|
@@ -1,7 +1,16 @@
|
|
|
1
1
|
import { NodeId, Warning } from '../model/types';
|
|
2
2
|
import { ComputedStyle } from '../style/resolve';
|
|
3
3
|
export interface CssMapOptions {
|
|
4
|
-
|
|
4
|
+
/**
|
|
5
|
+
* `form` tells `url("...")` apart from `resource("...")` — Unity resolves
|
|
6
|
+
* them differently: `url()` is a path (relative to the project or
|
|
7
|
+
* absolute), `resource()` names an asset inside a Resources folder by its
|
|
8
|
+
* Unity resource path (no extension). A host that ignores `form` and
|
|
9
|
+
* treats every path the same will resolve `resource("foo")` as a literal
|
|
10
|
+
* file path, which silently draws the wrong image whenever a same-named
|
|
11
|
+
* file happens to sit alongside it — or resolves nothing at all.
|
|
12
|
+
*/
|
|
13
|
+
resolveAsset?: ((path: string, form: 'url' | 'resource') => string | null) | undefined;
|
|
5
14
|
}
|
|
6
15
|
export interface CssMapResult {
|
|
7
16
|
declarations: Record<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>;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export interface GuidIndex {
|
|
2
|
+
/** Absolute path of the asset with this GUID, or null. */
|
|
3
|
+
get(guid: string): string | null;
|
|
4
|
+
/** Number of entries. Lets a host report an empty scan. */
|
|
5
|
+
readonly size: number;
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* Purpose: resolve a `project://database/Assets/...` reference whose file has
|
|
9
|
+
* moved, by walking `.meta` files for their `guid:` line instead.
|
|
10
|
+
* Deps/Effects: reads the directory tree under `projectRoot`; unreadable
|
|
11
|
+
* `.meta` files are skipped rather than thrown, so one bad file cannot fail
|
|
12
|
+
* the whole scan.
|
|
13
|
+
*/
|
|
14
|
+
export declare function buildGuidIndex(projectRoot: string): Promise<GuidIndex>;
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { readdir as c, readFile as u } from "node:fs/promises";
|
|
2
|
+
import { join as s } from "node:path";
|
|
3
|
+
const l = /* @__PURE__ */ new Set(["Library", "Temp", "obj", ".git"]), f = /^guid:\s*([0-9a-fA-F]+)/m;
|
|
4
|
+
async function y(n) {
|
|
5
|
+
const t = /* @__PURE__ */ new Map();
|
|
6
|
+
return await o(n, t), {
|
|
7
|
+
get(e) {
|
|
8
|
+
return t.get(e) ?? null;
|
|
9
|
+
},
|
|
10
|
+
get size() {
|
|
11
|
+
return t.size;
|
|
12
|
+
}
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
async function o(n, t) {
|
|
16
|
+
const e = await c(n, { withFileTypes: !0 });
|
|
17
|
+
for (const i of e) {
|
|
18
|
+
const a = s(n, i.name);
|
|
19
|
+
if (i.isDirectory()) {
|
|
20
|
+
if (l.has(i.name)) continue;
|
|
21
|
+
await o(a, t);
|
|
22
|
+
continue;
|
|
23
|
+
}
|
|
24
|
+
if (!i.name.endsWith(".meta")) continue;
|
|
25
|
+
const r = await m(a);
|
|
26
|
+
r !== null && t.set(r, a.slice(0, -5));
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
async function m(n) {
|
|
30
|
+
var e;
|
|
31
|
+
let t;
|
|
32
|
+
try {
|
|
33
|
+
t = await u(n, "utf8");
|
|
34
|
+
} catch {
|
|
35
|
+
return null;
|
|
36
|
+
}
|
|
37
|
+
return ((e = f.exec(t)) == null ? void 0 : e[1]) ?? null;
|
|
38
|
+
}
|
|
39
|
+
export {
|
|
40
|
+
y as buildGuidIndex
|
|
41
|
+
};
|
package/package.json
CHANGED
|
@@ -1,59 +1,90 @@
|
|
|
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:
|
|
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.3.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: 548 of 564 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
|
+
"./unity-project": {
|
|
36
|
+
"types": "./dist/unity-project/index.d.ts",
|
|
37
|
+
"import": "./dist/unity-project/index.js"
|
|
38
|
+
}
|
|
39
|
+
},
|
|
40
|
+
"files": [
|
|
41
|
+
"dist",
|
|
42
|
+
"README.md",
|
|
43
|
+
"LICENSE",
|
|
44
|
+
"THIRD-PARTY-NOTICES.md",
|
|
45
|
+
"CHANGELOG.md"
|
|
46
|
+
],
|
|
47
|
+
"sideEffects": false,
|
|
48
|
+
"engines": {
|
|
49
|
+
"node": ">=18"
|
|
50
|
+
},
|
|
51
|
+
"publishConfig": {
|
|
52
|
+
"access": "public"
|
|
53
|
+
},
|
|
54
|
+
"repository": {
|
|
55
|
+
"type": "git",
|
|
56
|
+
"url": "git+https://github.com/ReuHomi/uxml-preview.git"
|
|
57
|
+
},
|
|
58
|
+
"homepage": "https://reuhomi.github.io/uxml-preview/",
|
|
59
|
+
"bugs": {
|
|
60
|
+
"url": "https://github.com/ReuHomi/uxml-preview/issues"
|
|
61
|
+
},
|
|
62
|
+
"scripts": {
|
|
63
|
+
"dev": "vite",
|
|
64
|
+
"build": "tsc --noEmit && vite build",
|
|
65
|
+
"build:site": "vite build --config vite.playground.config.ts",
|
|
66
|
+
"preview:site": "vite preview --config vite.playground.config.ts",
|
|
67
|
+
"test": "vitest run",
|
|
68
|
+
"test:watch": "vitest",
|
|
69
|
+
"test:roundtrip": "vitest run tests/roundtrip",
|
|
70
|
+
"test:golden": "vitest run tests/golden --passWithNoTests",
|
|
71
|
+
"golden:emit": "node --experimental-strip-types --no-warnings scripts/emit-golden-cases.mjs",
|
|
72
|
+
"golden:update": "node scripts/update-golden.mjs",
|
|
73
|
+
"typecheck": "tsc --noEmit",
|
|
74
|
+
"prepublishOnly": "npm run typecheck && npm run test && npm run build"
|
|
75
|
+
},
|
|
76
|
+
"dependencies": {
|
|
77
|
+
"yoga-layout": "^3.2.1"
|
|
78
|
+
},
|
|
79
|
+
"devDependencies": {
|
|
80
|
+
"@types/node": "^22.0.0",
|
|
81
|
+
"jsdom": "^30.0.1",
|
|
82
|
+
"pixelmatch": "^6.0.0",
|
|
83
|
+
"pngjs": "^7.0.0",
|
|
84
|
+
"typescript": "^5.6.0",
|
|
85
|
+
"vite": "^6.0.0",
|
|
86
|
+
"vite-plugin-dts": "^4.3.0",
|
|
87
|
+
"vitest": "^2.1.0"
|
|
88
|
+
},
|
|
89
|
+
"packageManager": "pnpm@9.12.0"
|
|
90
|
+
}
|