uxml-preview 0.3.0 → 0.4.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 CHANGED
@@ -1,6 +1,79 @@
1
1
  # Changelog
2
2
 
3
- ## 0.3.0 — Unreleased
3
+ ## 0.4.0 — 2026-08-12
4
+
5
+ ### Added
6
+
7
+ - The Unity golden dumper can run from the command line, records the Unity
8
+ revision, editor scale, accessible font settings, and timestamp beside each
9
+ measurement, rejects `-nographics` and `-quit` up front, and exits non-zero
10
+ unless it writes exactly one JSON file per discovered case.
11
+
12
+ ### Changed
13
+
14
+ - Relative `@import` requests are deduplicated by `(url, from)`, matching Unity's
15
+ parent-relative loading. Root-fixed imports (`project://…` or a path beginning
16
+ with `/`) are globally deduplicated, and nested `<Style>` attachments now keep
17
+ their Unity subtree scope. The rule comes from five Unity measurement cases,
18
+ including the otherwise surprising split between `Packages/...` (relative)
19
+ and `/Packages/...` (root-fixed).
20
+
21
+ - **Issue #1: `resolveImport` now receives a second argument,
22
+ `from: string | null`** —
23
+ the URL of the stylesheet containing the import being resolved, `null` for
24
+ a `<Style src="…">` reference. Without it, a relative `@import` inside an
25
+ imported sheet was unresolvable in principle: `a.uss` importing `"b.uss"`
26
+ means a path relative to `a.uss`, and the host had no way to learn `a.uss`'s
27
+ own URL at the point it resolved `b.uss`. `from` is always the exact string
28
+ this hook received as `url` for the containing sheet, never reconstructed —
29
+ matters most for nested imports, where it is the immediate parent, not the
30
+ original sheet. **Non-breaking**: existing one-argument callbacks keep
31
+ working unchanged, same as `resolveAsset`'s `form` argument in 0.3.0.
32
+ - With this, `resolveImport` joins `resolveAsset` at two positional arguments.
33
+ Per the "코어에 무언가를 더하기 전에" rule in CLAUDE.md, the next argument
34
+ either hook would need is the point to switch to an options object instead
35
+ of adding a third positional one.
36
+
37
+ ### Fixed
38
+
39
+ - **Issue #2: inline `style="…"` asset URLs reach `resolveAsset`
40
+ XML-entity-decoded**,
41
+ matching what a `<Style src>`-loaded `.uss` file's URLs already got (that
42
+ file was never XML, so it never had entities to decode; an inline attribute
43
+ is XML text and did). `background-image: url('…&guid=…')` written inline
44
+ used to reach the hook as `&apos;…&amp;guid=…&apos;` — wrapper quotes and
45
+ ampersands both literal — because `inlineDeclarations` (style/resolve.ts)
46
+ parses straight from the raw XML source. Fixed at `assetPath()`
47
+ (render/css-map.ts), immediately before the `url()`/`resource()` wrapper is
48
+ parsed and right before the value leaves the model for the hook — the same
49
+ point `<Style src>` and painted text already decode at, not at parse time
50
+ (decoding then would corrupt the byte-exact round-trip source slices).
51
+ Confirmed against two real URLs from the external corpus in
52
+ `ReuHomi/vscode-uxml-preview` (`examples/external`, commit `dbda387`) where
53
+ this caused `asset-unresolved` for 7 URLs across 2 files. Scope: only the
54
+ asset-URL value reaching `resolveAsset`; other inline-style property values
55
+ still carry undecoded entities in the model (unaffected here, since no
56
+ other current consumer inspects their text — `-unity-font-definition`'s
57
+ `resource(...)` value is only checked for presence, never read).
58
+
59
+ ### Docs
60
+
61
+ - **`docs/accuracy.md`'s "which controls this covers" table now has a stated,
62
+ computed rule** instead of being left unverified. It never added up on its
63
+ own terms (17+1+6+5+1 = 30, not the stated 31) and the original counting
64
+ rule was never written down, so it is now defined explicitly — classify
65
+ `inventory` as the representative screen, then each other case by the first
66
+ of `<ui:ScrollView`, `<ui:Button`, `<ui:Label` its UXML contains, else
67
+ `VisualElement` only — and computed from `tests/golden/cases.ts` rather than
68
+ hand-counted. Updated numbers: `Button` 6→10, `ScrollView` 5→4 (`VisualElement`
69
+ only, `Label`, and the representative screen are unchanged). Mirrored into
70
+ `docs/accuracy.en.md`, which is not machine-checked.
71
+ - **The drift guard now covers this table's five numbers too**, in
72
+ `docs/accuracy.md` only. Same shape as the three headline figures: recomputed
73
+ live and failing (not skipping) if it can't find a row to check. Confirmed by
74
+ breaking a count and by removing a row's label, both on purpose.
75
+
76
+ ## 0.3.0 — 2026-08-09
4
77
 
5
78
  Four fixes the VSCode extension (`vscode-uxml-preview`) hit while consuming
6
79
  this package as a dependency — not speculative additions.
package/README.md CHANGED
@@ -47,8 +47,8 @@ directly in a web browser. It uses **Yoga** — the same layout engine Unity UI
47
47
  itself uses — compiled to WebAssembly, so results match the Unity Editor rather than
48
48
  approximating it.
49
49
 
50
- Measured against Unity 6000.0.40f1: **548 of 564 element coordinates identical**
51
- across 33 layout cases, including a full working screen. Ten of the sixteen
50
+ Measured against Unity 6000.0.40f1: **660 of 676 element coordinates identical**
51
+ across 40 layout cases, including a full working screen. Ten of the sixteen
52
52
  differences are font metrics rather than layout — a browser cannot measure
53
53
  Unity's font asset. All sixteen are named in
54
54
  [`docs/accuracy.en.md`](docs/accuracy.en.md).
@@ -210,12 +210,12 @@ Checked by comparing element geometry against the Unity Editor, case by case.
210
210
  Geometry rather than pixels: Unity draws text with its own font asset and a
211
211
  browser does not, so a pixel diff would measure the font more than the layout.
212
212
 
213
- Measured against Unity on 2026-08-06, over 33 cases and 141 elements:
213
+ Measured against Unity on 2026-08-12, over 40 cases and 169 elements:
214
214
 
215
215
  | | |
216
216
  |---|---|
217
- | Cases matching exactly | **31 / 33** |
218
- | Values within 0.5px | **548 / 564 (97.2%)** |
217
+ | Cases matching exactly | **38 / 40** |
218
+ | Values within 0.5px | **660 / 676 (97.6%)** |
219
219
 
220
220
  The sixteen divergences are four different things, and the distinction matters
221
221
  more than the ratio: **ten are text metrics**, three are 1px, two are a
@@ -246,7 +246,7 @@ as nested flex, and computed values have to be resolved to fixed numbers or
246
246
  calculated in C#.
247
247
 
248
248
  **How close is the output to Unity?**
249
- 548 of 564 element coordinates identical against Unity 6000.0.40f1, across 33
249
+ 660 of 676 element coordinates identical against Unity 6000.0.40f1, across 40
250
250
  layout cases including a complete inventory screen. Geometry is compared rather
251
251
  than screenshots, because Unity draws text with its own font asset — which is
252
252
  also why ten of the sixteen differences are font metrics rather than layout.
@@ -280,8 +280,8 @@ Apache-2.0
280
280
  **Yoga**를 WebAssembly로 그대로 사용하기 때문에, 결과를 "비슷하게 흉내내는" 것이 아니라
281
281
  유니티 에디터와 일치시킵니다.
282
282
 
283
- Unity 6000.0.40f1과 대조한 결과, 실무형 화면을 포함한 레이아웃 케이스 33개에서
284
- **요소 좌표 564개 중 548개가 일치**합니다. 어긋난 16개 중 **10개는 레이아웃이 아니라
283
+ Unity 6000.0.40f1과 대조한 결과, 실무형 화면을 포함한 레이아웃 케이스 40개에서
284
+ **요소 좌표 676개 중 660개가 일치**합니다. 어긋난 16개 중 **10개는 레이아웃이 아니라
285
285
  폰트 메트릭** 차이입니다 — 브라우저는 유니티 폰트 에셋을 잴 수 없습니다.
286
286
  16개 전부 [`docs/accuracy.md`](docs/accuracy.md)에 이름과 사유를 적어뒀습니다.
287
287
 
@@ -414,8 +414,8 @@ pnpm build
414
414
  계산이 필요한 값은 고정값으로 풀거나 C#에서 계산해야 합니다.
415
415
 
416
416
  **유니티와 얼마나 같나요?**
417
- Unity 6000.0.40f1 기준, 인벤토리 화면 전체를 포함한 레이아웃 케이스 33개에서
418
- **요소 좌표 564개 중 548개 일치**입니다. 스크린샷이 아니라 좌표를 비교하는데,
417
+ Unity 6000.0.40f1 기준, 인벤토리 화면 전체를 포함한 레이아웃 케이스 40개에서
418
+ **요소 좌표 676개 중 660개 일치**입니다. 스크린샷이 아니라 좌표를 비교하는데,
419
419
  유니티가 자기 폰트 에셋으로 글자를 그리기 때문입니다 — 그리고 그 사실 때문에
420
420
  불일치 16개 중 **10개가 레이아웃이 아니라 폰트 메트릭**입니다. 전부
421
421
  [`docs/accuracy.md`](docs/accuracy.md)에 이름이 적혀 있습니다.
package/dist/index.d.ts CHANGED
@@ -37,8 +37,23 @@ export interface ParseOptions {
37
37
  * `project://database/Assets/UI/base.uss`, which only the host application
38
38
  * knows how to turn into file contents, and there is no reason for a host to
39
39
  * implement that lookup twice.
40
+ *
41
+ * `from` is the URL of the stylesheet containing this import — exactly the
42
+ * string this hook received as `url` when that containing sheet was itself
43
+ * resolved, unmodified. `null` for a `<Style src="…">` reference, which is
44
+ * not contained in any stylesheet. A relative `@import` cannot be resolved
45
+ * without this: `a.uss` importing `"b.uss"` means a path relative to `a.uss`,
46
+ * not to the UXML document, and there is no other way for the host to learn
47
+ * `a.uss`'s own URL at the point it resolves `b.uss`.
48
+ *
49
+ * Non-breaking: this is an added argument, not a replacement one, so an
50
+ * existing one-argument callback keeps working unchanged.
51
+ *
52
+ * Relative imports are deduplicated by `(url, from)`, so two parent sheets
53
+ * may resolve the same spelling to different files. Root-fixed URLs —
54
+ * `project://…` or a path beginning with `/` — are deduplicated by URL alone.
40
55
  */
41
- resolveImport?: (url: string) => string | null;
56
+ resolveImport?: (url: string, from: string | null) => string | null;
42
57
  }
43
58
  export declare function parse(uxml: string, uss?: string, options?: ParseOptions): UxmlDocument;
44
59
  /**