uxml-preview 0.6.1 → 0.7.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.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,300 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.7.1 —
4
+
5
+ A patch for two things a consumer measured on 2026-10-22 (vscode-uxml-preview,
6
+ Chromium 152 on Windows). Layout, measurement and every accuracy figure are
7
+ unchanged: only what is drawn changes, and one warning message.
8
+
9
+ ### Fixes
10
+
11
+ - **Text is painted in the font it was measured in.** With no
12
+ `-unity-font-definition` the measurer used `sans-serif` while the painter set
13
+ no `font-family`, so the text inherited the host page's font. In a VS Code
14
+ webview (`"Segoe WPC", "Segoe UI", sans-serif`) "Start Game 한글" measured
15
+ 101.71px at 14px and was drawn 98.47px wide. Every painted text now sets
16
+ `font-family` from the same `fontList` the measurer uses (`sans-serif`, or
17
+ your font followed by `sans-serif`). Visible effect: a host page that sets its
18
+ own font no longer changes the preview's text; the five text-bearing
19
+ visual snapshots gain `font-family: sans-serif`. A font you set through
20
+ `resolveFont` is applied exactly as before.
21
+ - **The `font-fallback` message names the theme's default font.** It said "The
22
+ editor default font (Inter-Regular SDF)" under both themes. Unity's runtime
23
+ panel reports `NotInter-Regular` (24 of 24 dumps, both versions), so the
24
+ runtime theme now says "The runtime default font (NotInter-Regular)". Hangul
25
+ height (1–4px) was measured in both panels; the Han and Kana figures (height,
26
+ width 6–87px) only in the editor panel, so the runtime message adds "These
27
+ figures were measured in the editor panel; the runtime panel has not been
28
+ measured for them." The editor message is unchanged byte for byte. `reason`,
29
+ `kind`, `subject` and `affectsLayout` are the same in both themes. Warning
30
+ text is not an API: read the structured fields.
31
+
32
+ ### Docs
33
+
34
+ Four behaviour descriptions in the public docs were wrong or out of date (found by
35
+ a 0.7.0 doc audit, each checked against the source, tests and committed dumps):
36
+
37
+ - A `disabled` forced through `states` does not dim, add `unity-disabled` or reach
38
+ parts and children; only `enabled="false"` does (`supported`).
39
+ - Text height and letter spacing follow the **resolved** `-unity-text-generator`
40
+ (runtime theme Standard, editor theme Advanced), not the theme; `textHeight`
41
+ without its sixth argument is still Advanced (`supported`, `uss-vs-css`).
42
+ - Whether runs of spaces collapse follows the generator, not the version; a runtime
43
+ Label's runs and a TextField's trailing spaces are measured, unimplemented known
44
+ differences (0.8 candidates), not unmeasured (`supported`, `accuracy`, `uss-vs-css`).
45
+ - `white-space: pre` does not wrap to the width (`pre-wrap` does), and a word longer
46
+ than the box breaks between characters (`supported`, `uss-vs-css`).
47
+
48
+ ## 0.7.0 — 2026-10-21
49
+
50
+ Unity's runtime theme, by default. A preview of a game screen now looks like the
51
+ game: the values come from a real runtime panel (PanelSettings + UIDocument in
52
+ Play mode) on Unity 6.3, and the editor theme stays one option away.
53
+
54
+ ### Behavior changes
55
+
56
+ - **The default theme is `'runtime'`.** `render`, `resolveStyles` and
57
+ `layoutDocument` take `theme: 'runtime' | 'editor'`; `RenderResult.theme`
58
+ says which was drawn. Without the option, every render changes:
59
+ - text: 14px, colour #1b1b1b (editor: 12px, #d2d2d2)
60
+ - Label: margin 4 4 2 2, padding 4 2 4 1 (editor: 0; 0 2 0 1)
61
+ - Button: margin 2 4, padding 10 12, border 1 #959595, background #bcbcbc,
62
+ radius 0 (editor: margin 1 3, padding 1 6, border 1 #303030 with a
63
+ #242424 bottom, background #585858, radius 3, text #eeeeee)
64
+ - a scrolling ScrollView reserves 24px for its scroller (editor: 13px)
65
+ - the core paints nothing behind the panel, as Unity paints nothing behind
66
+ a runtime panel. Runtime text is dark: a host drawing on a dark backdrop
67
+ has to supply one. Pass `theme: 'editor'` for the 0.6.x drawing plus the
68
+ values below.
69
+ - **Both themes now carry their measured values**, where 0.6.x had only the
70
+ Button margin and text alignment: panel text size and colour (inherited by
71
+ every element, origin `builtin-theme`), Label padding, Button padding,
72
+ border, colours and `:hover` / `:active` / `:focus` / `:disabled` colours.
73
+ - **Label and Button do not shrink** (`flex-shrink: 0`, measured on both
74
+ themes). `inventory`'s `ItemDesc` now lands where Unity puts it.
75
+ - **Only the element written `enabled="false"` is dimmed.** Unity gives that
76
+ element `unity-disabled` and opacity 0.5 and leaves its descendants at 1; a
77
+ disabled button inside a disabled panel was 0.25 here. A `disabled` forced
78
+ through `states` does not dim at all (see "A state forced through `states`
79
+ stays on that element" below).
80
+ - **The runtime theme paints CJK without kinsoku**, as Unity's runtime panel
81
+ does. The editor theme keeps the browser's line breaking (a known
82
+ difference at one 60px Chinese case, Unity 6.3 editor).
83
+ - An unknown `theme` value warns (`malformed`, reason `invalid-value`) and
84
+ draws the default.
85
+ - **Applying the theme is no longer a warning.** "Built-in control defaults
86
+ applied, as measured on Unity <version>" and "<ScrollView> drawn with built-in
87
+ child elements measured on Unity <version>" are gone: a measured theme value
88
+ is not a difference from Unity, and both were measured the same on
89
+ 6000.0.40f1 and 6.3. `version-dependent` now comes only from values the dumps
90
+ show differ by version, both on the editor theme:
91
+ - a Button with no text: 4px high on 6000.0.40f1, 19px on 6000.3.25f1 (the
92
+ editor theme draws 6000.0.40f1's)
93
+ - letter- or word-spacing with no `-unity-text-generator`: the editor theme's
94
+ default generator is standard on 6000.0.40f1 and advanced on 6000.3.25f1
95
+ (drawn as advanced)
96
+ - a GroupBox whose `text` is only spaces: its title is 0px high on 6000.0.40f1
97
+ and 15px on 6000.3.25f1 (advanced generator; drawn as 15). Under an explicit
98
+ standard generator both versions measure 0 and nothing is warned. The runtime
99
+ theme draws that title 0px high on both versions, unwarned. The same holds for
100
+ a Label or Button whose text is only spaces (Label 0px vs 15px, Button 4px
101
+ vs 19px; the runtime theme draws the text 0px high)
102
+ A host that keyed anything off the removed warnings loses that signal.
103
+ - **Text is measured by its generator's rules.** The runtime theme resolves
104
+ `-unity-text-generator: standard`, as Unity's runtime panel does on both
105
+ versions; the editor theme resolves advanced (the 6.3 editor's default). The
106
+ resolved value — not the theme — now picks the rules, measured on the text
107
+ cohort: Standard text is `floor(fs·r + (n−1)·fs·lineHeight/pointSize) + 1`
108
+ high (r = (ascent − descent) / pointSize) and measured and painted without
109
+ kerning (`font-kerning: none`); Advanced keeps `ceil(n·fs·r)` and kerning.
110
+ On the runtime theme a whole-number line height gains 1px, later lines
111
+ advance by `lineHeight`, and kerned pairs (Jua's English, 2–4px) widen. An
112
+ author's `-unity-text-generator: standard` on the editor theme measures the
113
+ same way. `textHeight` takes the generator as an optional sixth argument
114
+ (advanced when left out).
115
+ - **A text wider than the width it is offered is clipped to it**, as Unity
116
+ does (measured, `g-clamp`, both versions and themes): in a row, in a column
117
+ with `align-items: flex-start`, with or without `overflow: hidden`. An
118
+ absolutely placed text and a TextField's inner text are not clipped, as in
119
+ Unity. A long no-wrap Label in a narrow box now has the box's width instead
120
+ of overflowing it. No accuracy figure moved. The same holds for the height
121
+ (`g-clamp-h`): a text offered a smaller height is clipped to it, down to its
122
+ padding and border — a TextField's inner text included.
123
+ - **A focused TextField's label takes the focus colour** (runtime #00526a,
124
+ editor #81b4ff), as Toggle and RadioButton labels do.
125
+
126
+ ### New controls
127
+
128
+ - **GroupBox and Box are drawn** instead of falling back with an
129
+ `unsupported-control` warning (bundle B). GroupBox builds Unity's title
130
+ Label before its children when it has `text` (a part named
131
+ `unity-group-box__label`, reachable from author USS by that class); Box
132
+ carries its border and background. Both match the `c07-GroupBox` and
133
+ `c07-Box` dumps on both themes.
134
+ - **TextField is drawn** (bundle C): single-line and multiline, placeholder,
135
+ password (the mask only; the value never reaches the DOM), disabled, with or
136
+ without a label. It builds Unity's parts — the label (`unity-text-field__label`),
137
+ `#unity-text-input`, the multiline container and the inner text
138
+ (`unity-text-element--inner-input-field-component`) — which author USS reaches
139
+ by Unity's names. Matches the 6.3 `c07-TextField`, `c-textfield` and
140
+ `c-textfield-hook` dumps on both themes. The caret, the selection and editing
141
+ are not drawn. A host that counted TextField's `unsupported-control` warning
142
+ loses it.
143
+ - **Toggle and RadioButton are drawn** (bundle E): label, text, checked
144
+ (`value="true"`), disabled. Checked is the `:checked` state on the control and
145
+ its input part, as in Unity; the radio checkmark appears only when checked.
146
+ The check mark is this preview's drawing (Unity's textures cannot be loaded).
147
+ - **A state forced through `states` stays on that element.** Measured
148
+ (e-disabled, both versions): a forced `disabled` neither dims (no
149
+ `unity-disabled`) nor reaches the element's parts or children; forced
150
+ hover/focus/active do not reach parts either. 0.7.0's earlier handling dimmed
151
+ a forced-disabled element at 0.5 (an inference, now reversed).
152
+ `enabled="false"` still disables the whole subtree and dims once.
153
+ - **Slider and SliderInt are drawn** (bundle D): label, input, drag container,
154
+ tracker, dragger and its border, and with `show-input-field` a TextField
155
+ showing the value. The dragger sits where Unity puts it for any value —
156
+ t = clamp((value - low) / (high - low), 0, 1) along the drag container less
157
+ the dragger, upward for `direction="Vertical"` — measured in eleven steps
158
+ both ways, a range, a reversed range and an out-of-range value. Dragging is
159
+ not drawn. A host that used Slider as its example of an unsupported
160
+ control loses that example.
161
+ - **ProgressBar, TextElement and RepeatButton are drawn** (bundle F).
162
+ ProgressBar builds Unity's container, background, bar and title; the bar
163
+ width follows Unity's rule, floor(background width - 2) x clamp(value) /
164
+ high-value, measured on fourteen values, ranges and widths. On the editor
165
+ theme a bar at or below low-value warns `version-dependent` (1px on
166
+ 6000.0.40f1, 0 on 6.3; drawn as 6.3). TextElement and RepeatButton are plain
167
+ text, as in Unity — a RepeatButton does not look like a button. A host that
168
+ counted their `unsupported-control` warnings loses them.
169
+ - **The editor theme's Toggle box is drawn** (E2): Unity draws it from a
170
+ built-in texture; the preview paints it in colours measured off Unity's
171
+ screen, so an unchecked Toggle no longer disappears on the editor theme.
172
+
173
+ ### Classes
174
+
175
+ - **Every drawn control carries Unity's classes**, parts included (A2, held by
176
+ `tests/contract-070/classes.test.ts` against every 0.7.0 dump). Label and
177
+ Button gain `unity-text-element`, so an author rule on that class now reaches
178
+ them as it does in Unity. ScrollView gains `unity-scroll-view--scroll` and a
179
+ `mode` class (`--vertical`, `--horizontal`, `--vertical-horizontal`), and its
180
+ three parts their `unity-scroll-view__*` classes. Classes only: no coordinate
181
+ moved. The scrollers inside a ScrollView are still not built.
182
+
183
+ ### Review fixes (adversarial review, 2026-10-21)
184
+
185
+ Each found by the review or while fixing it, measured on Unity where Unity
186
+ decides it, and pinned (`tests/contract-070/review-*.test.ts`,
187
+ `c1-nowrap.test.ts`, `n3-part-fonts.test.ts`, and in a real browser
188
+ `tests/text-cohort/paint-r15.mjs`, now part of `pnpm test:text`).
189
+
190
+ - **A Label or Button does not wrap unless the author says so.** Unity
191
+ resolves `white-space: nowrap` on both; the theme sheets now give it to
192
+ `.unity-label` and `.unity-button`. A long label in a narrow column is one
193
+ clipped line, as in Unity, not several. TextElement and RepeatButton still
194
+ wrap.
195
+ - **Text is painted where it was measured.** A line break (`
196
+ `) is a painted
197
+ line whatever the `white-space`; the painted line height is the measured
198
+ advance (Standard `lineHeight`, Advanced ascent − descent); kerning follows
199
+ each text's own generator; `pre-wrap` keeps runs of spaces when it wraps.
200
+ - **A wrapping text is as wide as Unity makes it.** The editor theme
201
+ (Advanced) takes its longest line; the runtime theme (Standard) takes the
202
+ width up to the last glyph that fit where a line broke — the line, its space
203
+ and the start of the next word — floor + 1. Both used to take the longest
204
+ line. Measured on probes that use each sentence once (`r1w-wrap`,
205
+ `r1w-wrap2`): 22 of 24 texts match, two are known differences (below).
206
+ - **A word longer than the line breaks between characters**, Latin and Hangul,
207
+ measured and painted, in a TextElement, a Label with `white-space: normal`
208
+ and a multiline TextField (`r1w-long`, both versions and themes). It used to
209
+ overflow the line as one piece. See Corrections.
210
+ - **A TextField keeps runs of spaces in its value**, measured and painted.
211
+ - **An author font reaches a control's part text** (field labels, the
212
+ TextField's text, GroupBox and ProgressBar titles), as Unity draws them.
213
+ - **Attribute values are read as Unity reads them:** booleans ignore case
214
+ (`"True"`; `"1"` is not true), `direction` ignores case, `inverted` mirrors a
215
+ slider, SliderInt takes whole numbers, a value that is not a number falls back
216
+ to the default and is warned (`malformed`, `invalid-value`), `Infinity` is
217
+ clamped, the old names `text=` and `maskCharacter=` work.
218
+ - **ProgressBar:** the fill is `width × clamp(value, low, high) / high` (it was
219
+ empty whenever the value was at low).
220
+ - **Text edges:** absolutely placed text is not wrapped; an empty TextField is
221
+ clipped like one with a value; a multiline TextField's text keeps its
222
+ wrapped height in a fixed-height field.
223
+ - **States:** a forced `disabled` no longer matches `:enabled`; a state USS
224
+ does not have (`:selected`) is warned and not applied; a forced `:checked`
225
+ reaches the input part and draws the check mark.
226
+ - **Author rules beat the painter's stand-ins** for the editor check box
227
+ (background, radius, tint).
228
+ - **Warnings that were missing:** a non-px `font-size`; an unknown
229
+ `-unity-text-generator` (the theme's generator stands); an inherited author
230
+ generator no longer reads as "drawn as advanced"; a host font without a
231
+ FaceInfo under the Standard generator; a FaceInfo with no usable
232
+ `pointSize`.
233
+ - **Yoga nodes are freed when layout throws** (a host measure function that
234
+ throws used to leave the tree allocated).
235
+
236
+ ### Accuracy — previous and new figures
237
+
238
+ | Set | 0.6.1 | 0.7.0 | Why |
239
+ |---|---:|---:|---|
240
+ | Runtime theme coordinates (Unity 6.3 runtime panel) | — | 1122 / 1148 | new set (662/676 on the original 40 cases); the settings screen adds 472 values and 12 text-width mismatches; the 26 left are the editor set's known divergences |
241
+ | Editor theme coordinates (Unity 6000.0.40f1) | 660 / 676 | 1122 / 1148 | Label `flex-shrink: 0` (`ItemDesc` y, height) gave 662/676; the settings screen (two cases, all 15 drawn controls) adds 472 values, 12 of them the footer's text widths |
242
+ | Template cohort | 215 / 220 | 215 / 220 | unchanged; G3-4 text-width deltas moved by the Label padding |
243
+ | Text cohort, editor (Chromium vs Unity) | 92/92 · 84/92 · 92/92 · 157/159 | unchanged | |
244
+ | Text cohort, runtime panel (new set) | — | 92/92 · 84/92 · 92/92 · 159/159 (both versions) | measured with the Standard rules (before them: 60/92 heights, 89/92 widths); the 8 plain heights left are Inter's Hangul fallback rows, as on the editor; `noto-jp-zh-20-w60` (203 vs 201) is a fallback glyph starting the last line, a known difference. None unexplained |
245
+
246
+ Every Unity baseline is now a solo dump, each probe or case in its own Unity
247
+ process: under the Standard text generator a text's width depends on what the
248
+ same process drew before (0-2px). The inventory's nine text-metric values moved
249
+ by 1px on Unity's side (291/93 -> 292/92), still counted as mismatches.
250
+
251
+ The acceptance screen (`settings`, `settings-ko`: every drawn control on one
252
+ screen, design section 6) is in both golden sets, and a contract test judges
253
+ the same screen with Unity's own text sizes (the dump's `MeasureTextSize`, or
254
+ Unity's layout width where that is 1-2px wider): every box and part matches but
255
+ one half-pixel title. It checks the boxes given the text sizes, not the text
256
+ widths (`docs/accuracy.md`).
257
+
258
+ ### Known differences
259
+
260
+ - Scrollbars reserve their width and are not drawn.
261
+ - Half-pixel rounding: a centred text whose position falls on a half pixel is
262
+ rounded up by Unity and down by this preview (a ProgressBar title, 1px in x).
263
+ Decided after measuring per alignment.
264
+ - A glyph the given font does not have, starting the last line: the runtime
265
+ preview's box can be taller than Unity's (2px in the measured pair). The text
266
+ cohort's `noto-jp-zh-20-w60` is this case: Noto Sans JP has no `张`, Unity draws
267
+ it with a fallback font, 201 against the Standard rule's 203. Thirteen probes
268
+ dumped alone (`tests/text-cohort/fallback-zh/`) show the 2px only when the
269
+ fallback glyph starts the last line. Not reproduced: the preview does not know
270
+ a font's glyph coverage.
271
+ - Unity side: on the runtime panel, writing the same text earlier in a
272
+ document with a different wrap setting makes a later copy of it shorter.
273
+ Not reproduced.
274
+ - The editor theme's kinsoku (one 60px Chinese case on the 6.3 editor).
275
+ - The runtime theme's wrapping width, in two of 24 measured texts: a Korean
276
+ sentence in 100px is 4px wider than Unity's 83 (Unity takes its longest line
277
+ there), and a 10px sentence 2px wider than Unity's 77. Heights match.
278
+
279
+ ### For consumers
280
+
281
+ `docs/design/0.7.0-handoff.md` lists what changes, every consumer task, and the
282
+ classified failures of the consumers' own tests against this core:
283
+ vscode-uxml-preview 4 (1 already on 0.6.1, 3 using a now-drawn control as the
284
+ unsupported example), uxml-author 32 (17 already on 0.6.1; 3 such examples, 1
285
+ `version-dependent` sample that no longer warns, 11 skill-document lists and
286
+ "cannot draw" sentences).
287
+
288
+ ### Corrections
289
+
290
+ - `white-space: pre` does not wrap to the width in Unity either. 0.6.0 said it
291
+ did, from evidence that could not tell the two apart (`pre-wrap2`).
292
+ - 0.6.1's "a Korean or Latin word wider than the box is not split" was
293
+ inferred, not measured: none of the cohort's cases had a word wider than its
294
+ box. Measured, Unity breaks a word longer than the line between characters
295
+ (`r1w-wrap2`, `r1w-long`, both versions and themes), and the preview now
296
+ follows it.
297
+
3
298
  ## 0.6.1 — 2026-10-16
4
299
 
5
300
  Japanese and Chinese text, first. The Japanese and Simplified Chinese READMEs
package/README.ja.md CHANGED
@@ -5,6 +5,8 @@
5
5
  **Unity UI Toolkit の UXML/USS を、Unity エディタなしでブラウザ上に描画します。レイアウトには
6
6
  UI Toolkit 自身が使用する Yoga エンジンを採用し、描画結果は実際の Unity と突き合わせて検証しています。**
7
7
 
8
+ ![uxml-preview 0.7.0:左に UXML・USS で書いた設定画面、右にブラウザで描画した結果](https://raw.githubusercontent.com/ReuHomi/uxml-preview/main/docs/media/promo-0.7.0.gif)
9
+
8
10
  [![プレイグラウンド画面:上部にプレビュー画面、下部に各警告の理由と Unity 側の実際の挙動を表示](https://raw.githubusercontent.com/ReuHomi/uxml-preview/main/docs/media/playground.png)](https://reuhomi.github.io/uxml-preview/)
9
11
 
10
12
  ### ▶ [プレイグラウンドを開く](https://reuhomi.github.io/uxml-preview/)
@@ -18,8 +20,11 @@ UI Toolkit 自身が使用する Yoga エンジンを採用し、描画結果は
18
20
 
19
21
  ## 検証方法
20
22
 
21
- - **座標:** 完成画面1件を含む40個のレイアウトケースにおいて、要素の座標値 660 / 676 が Unity 6000.0.40f1 と一致しています。[すべての差異とその内訳 →](https://github.com/ReuHomi/uxml-preview/blob/main/docs/accuracy.en.md) 同じケースを Unity 6.3(6000.3.25f1)で再ダンプしたところ、同日に取得した 6000.0.40f1 のダンプとすべての配置が一致しました。[6.3 での再測定 →](https://github.com/ReuHomi/uxml-preview/blob/main/docs/accuracy.en.md#unity-63-lts-re-measurement-2026-10-15)
22
- - **テキスト:** 実際のブラウザで描画し、Unity 6000.3.25f1 と Label 単位で比較しました。行数 92 / 92、高さ 84 / 92、幅 92 / 92(誤差 1px または 1% 以内)。高さが異なるケースはすべて、ハングルを含まない欧文フォント Inter で韓国語、または韓国語と欧文が混在するテキストを指定したものです。Unity はこれをフォールバックフォントで描画しますが、本プレビューではまさにその状況を警告として通知します。[テキスト検証セット →](https://github.com/ReuHomi/uxml-preview/blob/main/docs/accuracy.en.md#text-cohort-separate-set-measured-2026-10-16)
23
+ - **座標・ランタイムテーマ(既定):** 同じ42個のレイアウトケースにおいて、要素の座標値 1122 / 1148 が実際の Unity 6.3 ランタイムパネル(6000.3.25f1、PanelSettings + UIDocument、Play モード)と一致しています。残る差異はすべてエディターテーマにもあるものです。[測定方法 →](https://github.com/ReuHomi/uxml-preview/blob/main/docs/accuracy.en.md#runtime-theme-separate-set-measured-2026-10-17)
24
+ - **座標・エディターテーマ:** 完成画面3件(インベントリ、描画する15種のコントロールをすべて使った設定画面の英語版・韓国語版)を含む42個のレイアウトケースにおいて、要素の座標値 1122 / 1148 が Unity 6000.0.40f1 と一致しています。[すべての差異とその内訳 →](https://github.com/ReuHomi/uxml-preview/blob/main/docs/accuracy.en.md) 同じケースを Unity 6.3(6000.3.25f1)で再ダンプしたところ、同日に取得した 6000.0.40f1 のダンプとすべての配置が一致しました。[6.3 での再測定 →](https://github.com/ReuHomi/uxml-preview/blob/main/docs/accuracy.en.md#unity-63-lts-re-measurement-2026-10-15)
25
+ - **テキスト、ランタイムテーマ(既定):** 実際のブラウザで描画し、実際の Unity ランタイムパネル(6000.0.40f1 と 6000.3.25f1、プローブごとに別の Unity プロセス)と Label 単位で比較しました。行数 92 / 92、高さ 84 / 92、幅 92 / 92(誤差 1px または 1% 以内)、ボックス境界での改行ケース 159 / 159。高さが異なるケースはすべて、ハングルを含まない欧文フォント Inter で韓国語、または韓国語と欧文が混在するテキストを指定したものです。Unity はこれをフォールバックフォントで描画しますが、本プレビューではまさにその状況を警告として通知します。[ランタイムのテキストセット →](https://github.com/ReuHomi/uxml-preview/blob/main/docs/accuracy.en.md#runtime-panel-separate-set-measured-2026-10-19--item-t)
26
+ - **テキスト、エディターテーマ:** 同じ 92 個の Label を Unity 6000.3.25f1 のエディターと比較 — 92 / 92、84 / 92、92 / 92、改行ケース 157 / 159(残る 2 件:中国語 1 ケースでのエディターの禁則処理と、ボックス境界での 1px の自然幅の差)。[テキスト検証セット →](https://github.com/ReuHomi/uxml-preview/blob/main/docs/accuracy.en.md#text-cohort-separate-set-measured-2026-10-16)
27
+ - **測定条件:** 座標の数値は、テキストサイズを与えたときのレイアウトを測っています(ハーネスはテキストを固定関数で測り、テキスト計測はテキストの数値が別に測ります)。テキストの数値は Unity と同じフォントファイルを渡した条件での値です。フォントを渡さない場合はブラウザーの既定フォントで測るため、文字幅が数 px 異なり、複数行のテキストでは行数が変わることがあります。[条件 →](https://github.com/ReuHomi/uxml-preview/blob/main/docs/accuracy.en.md)
23
28
  - **Unity バージョン:** 基準バージョンは Unity 6.3 LTS です。USS プロパティかどうかの判定は Unity 公式のプロパティ一覧(6.6 まで)に基づいており、6.7 は LTS になるまでサポート対象外です。[サポート範囲 →](https://github.com/ReuHomi/uxml-preview/blob/main/docs/supported.en.md)
24
29
  - **一致しない箇所は見過ごさず、警告として報告します。** 未サポートのコントロール・プロパティ・値は、その理由とともに(測定済みの場合は Unity 側が代わりにどう振る舞うかも含めて)警告として返されます。[警告について →](https://github.com/ReuHomi/uxml-preview/blob/main/docs/api.en.md#warnings)
25
30
 
package/README.ko.md CHANGED
@@ -5,6 +5,8 @@
5
5
  **Unity UI Toolkit의 UXML/USS를 Unity 에디터 없이 브라우저에서 그립니다. 배치는 UI Toolkit이
6
6
  쓰는 엔진인 Yoga가 하고, 결과는 Unity와 대조해 측정했습니다.**
7
7
 
8
+ ![uxml-preview 0.7.0: 왼쪽에 UXML·USS로 쓴 설정 화면, 오른쪽에 브라우저가 그린 결과](https://raw.githubusercontent.com/ReuHomi/uxml-preview/main/docs/media/promo-0.7.0.gif)
9
+
8
10
  [![놀이터 화면: 위에는 화면, 아래에는 경고마다 이유와 Unity가 대신 하는 일](https://raw.githubusercontent.com/ReuHomi/uxml-preview/main/docs/media/playground.png)](https://reuhomi.github.io/uxml-preview/)
9
11
 
10
12
  ### ▶ [놀이터 열기](https://reuhomi.github.io/uxml-preview/)
@@ -18,8 +20,11 @@
18
20
 
19
21
  ## 어떻게 확인했나
20
22
 
21
- - **좌표:** 완성된 화면 하나를 포함한 배치 케이스 40개에서, 요소 좌표 값 660 / 676이 Unity 6000.0.40f1과 같습니다. [다른 곳은 전부 이름을 붙여 적었습니다 →](https://github.com/ReuHomi/uxml-preview/blob/main/docs/accuracy.md) 같은 케이스를 Unity 6.3(6000.3.25f1)에서 다시 덤프했더니, 같은 날 다시 뜬 6000.0.40f1 덤프와 배치가 모두 같았습니다. [6.3 재측정 →](https://github.com/ReuHomi/uxml-preview/blob/main/docs/accuracy.md#unity-63-lts-재측정-2026-10-15)
22
- - **텍스트:** 실제 브라우저에서 그려 Unity 6000.3.25f1과 Label 단위로 대조했습니다. 줄 수 92 / 92, 높이 84 / 92, 너비 92 / 92(1px 또는 1% 이내). 높이가 다른 것은 모두 라틴 글꼴 Inter로 쓴 한글·혼합 문장입니다 — Inter에 한글이 없어 Unity가 대체 폰트로 그리고, 미리보기는 바로 그 경우에 경고합니다. [텍스트 코호트 →](https://github.com/ReuHomi/uxml-preview/blob/main/docs/accuracy.md#텍스트-코호트-별도-검증-세트-2026-10-16-측정)
23
+ - **좌표, 런타임 테마(기본값):** 같은 배치 케이스 42개에서 요소 좌표 값 1122 / 1148이 실제 Unity 6.3 런타임 패널(6000.3.25f1, PanelSettings + UIDocument, Play 모드)과 같습니다. 남은 차이는 모두 에디터 테마에도 있는 것입니다. [어떻게 쟀나 →](https://github.com/ReuHomi/uxml-preview/blob/main/docs/accuracy.md#런타임-테마-별도-세트-2026-10-17-측정)
24
+ - **좌표, 에디터 테마:** 완성된 화면 셋(인벤토리, 그리는 컨트롤 15종을 모두 쓴 설정 화면의 영어·한국어판)을 포함한 배치 케이스 42개에서, 요소 좌표 값 1122 / 1148이 Unity 6000.0.40f1과 같습니다. [다른 곳은 전부 이름을 붙여 적었습니다 →](https://github.com/ReuHomi/uxml-preview/blob/main/docs/accuracy.md) 같은 케이스를 Unity 6.3(6000.3.25f1)에서 다시 덤프했더니, 같은 날 다시 뜬 6000.0.40f1 덤프와 배치가 모두 같았습니다. [6.3 재측정 →](https://github.com/ReuHomi/uxml-preview/blob/main/docs/accuracy.md#unity-63-lts-재측정-2026-10-15)
25
+ - **텍스트, 런타임 테마(기본):** 실제 브라우저에서 그려 실제 Unity 런타임 패널(6000.0.40f1과 6000.3.25f1, 프로브마다 따로 띄운 Unity)과 Label 단위로 대조했습니다. 줄 수 92 / 92, 높이 84 / 92, 너비 92 / 92(1px 또는 1% 이내), 상자 경계의 줄바꿈 케이스 159 / 159. 높이가 다른 것은 모두 라틴 글꼴 Inter로 쓴 한글·혼합 문장입니다 — Inter에 한글이 없어 Unity가 대체 폰트로 그리고, 미리보기는 바로 그 경우에 경고합니다. [런타임 텍스트 세트 →](https://github.com/ReuHomi/uxml-preview/blob/main/docs/accuracy.md#런타임-패널-별도-세트-2026-10-19-측정--항목-t)
26
+ - **텍스트, 에디터 테마:** 같은 92개 Label을 Unity 6000.3.25f1 에디터와 대조 — 92 / 92, 84 / 92, 92 / 92, 줄바꿈 케이스 157 / 159(남은 둘: 중국어 한 케이스의 에디터 금칙, 상자 경계에서 1px 다른 자연 폭). [텍스트 코호트 →](https://github.com/ReuHomi/uxml-preview/blob/main/docs/accuracy.md#텍스트-코호트-별도-검증-세트-2026-10-16-측정)
27
+ - **어떤 조건에서 쟀나:** 좌표 수치는 글 크기가 주어졌을 때의 배치를 잽니다 — 하네스는 글을 고정 함수로 재고, 글 측정은 텍스트 수치가 따로 잽니다. 텍스트 수치는 Unity와 같은 글꼴 파일을 넘겨준 조건에서 잰 값입니다. 글꼴을 넘기지 않으면 브라우저 기본 글꼴로 재며, 글자 폭이 몇 px 다르고 여러 줄 글의 줄 수가 달라질 수 있습니다. [조건 →](https://github.com/ReuHomi/uxml-preview/blob/main/docs/accuracy.md)
23
28
  - **Unity 버전:** 기준은 Unity 6.3 LTS입니다. USS 속성인지는 Unity 공식 속성표(6.6까지)로 판정하고, 6.7은 LTS가 나올 때까지 지원하지 않습니다. [지원 범위 →](https://github.com/ReuHomi/uxml-preview/blob/main/docs/supported.md)
24
29
  - **맞지 않는 곳은 조용히 넘기지 않고 경고로 알립니다.** 지원하지 않는 컨트롤·속성·값은 이유와 함께, 측정한 경우에는 Unity가 대신 어떻게 하는지까지 경고로 돌아옵니다. [경고 →](https://github.com/ReuHomi/uxml-preview/blob/main/docs/api.md#경고)
25
30
 
package/README.md CHANGED
@@ -5,6 +5,8 @@
5
5
  **Render Unity UI Toolkit UXML/USS in a browser, without the Unity Editor — laid
6
6
  out by Yoga, the engine UI Toolkit itself uses, and measured against Unity.**
7
7
 
8
+ ![uxml-preview 0.7.0: a settings screen written in UXML and USS on the left, drawn in the browser on the right](https://raw.githubusercontent.com/ReuHomi/uxml-preview/main/docs/media/promo-0.7.0.gif)
9
+
8
10
  [![The playground: a screen, and under it each warning with its reason and what Unity does instead](https://raw.githubusercontent.com/ReuHomi/uxml-preview/main/docs/media/playground.png)](https://reuhomi.github.io/uxml-preview/)
9
11
 
10
12
  ### ▶ [Open the playground](https://reuhomi.github.io/uxml-preview/)
@@ -18,8 +20,11 @@ all runs in the page.
18
20
 
19
21
  ## How it is verified
20
22
 
21
- - **Coordinates:** 660 / 676 element coordinate values identical to Unity 6000.0.40f1, over 40 layout cases including a complete screen. [Every difference, named →](https://github.com/ReuHomi/uxml-preview/blob/main/docs/accuracy.en.md) Re-dumped on Unity 6.3 (6000.3.25f1), every one of those cases laid out exactly as in a 6000.0.40f1 dump taken the same day. [The 6.3 re-measurement →](https://github.com/ReuHomi/uxml-preview/blob/main/docs/accuracy.en.md#unity-63-lts-re-measurement-2026-10-15)
22
- - **Text:** drawn in a real browser and compared with Unity 6000.3.25f1 Label by Label — line count 92 / 92, height 84 / 92, width 92 / 92 within 1px or 1%. Every height that differs is Korean or mixed text set in Inter, a Latin font with no Hangul, which Unity draws with a fallback font; the preview warns about exactly that. [The text cohort →](https://github.com/ReuHomi/uxml-preview/blob/main/docs/accuracy.en.md#text-cohort-separate-set-measured-2026-10-16)
23
+ - **Coordinates, runtime theme (the default):** 1122 / 1148 element coordinate values identical to a real Unity 6.3 runtime panel (6000.3.25f1, PanelSettings + UIDocument in Play mode), over the same 42 layout cases. Every value left over is one the editor theme also has. [How it was measured →](https://github.com/ReuHomi/uxml-preview/blob/main/docs/accuracy.en.md#runtime-theme-separate-set-measured-2026-10-17)
24
+ - **Coordinates, editor theme:** 1122 / 1148 element coordinate values identical to Unity 6000.0.40f1, over 42 layout cases including three complete screens (an inventory, and a settings screen with all 15 drawn controls, in English and Korean). [Every difference, named →](https://github.com/ReuHomi/uxml-preview/blob/main/docs/accuracy.en.md) Re-dumped on Unity 6.3 (6000.3.25f1), every one of those cases laid out exactly as in a 6000.0.40f1 dump taken the same day. [The 6.3 re-measurement →](https://github.com/ReuHomi/uxml-preview/blob/main/docs/accuracy.en.md#unity-63-lts-re-measurement-2026-10-15)
25
+ - **Text, runtime theme (the default):** drawn in a real browser and compared Label by Label with a real Unity runtime panel (6000.0.40f1 and 6000.3.25f1, each probe in its own Unity process) — line count 92 / 92, height 84 / 92, width 92 / 92 within 1px or 1%, and 159 / 159 line-break cases at box edges. Every height that differs is Korean or mixed text set in Inter, a Latin font with no Hangul, which Unity draws with a fallback font; the preview warns about exactly that. [The runtime text set →](https://github.com/ReuHomi/uxml-preview/blob/main/docs/accuracy.en.md#runtime-panel-separate-set-measured-2026-10-19--item-t)
26
+ - **Text, editor theme:** the same 92 Labels against Unity 6000.3.25f1's editor — 92 / 92, 84 / 92, 92 / 92, and 157 / 159 line-break cases (the two left: the editor's kinsoku in one Chinese case, and a 1px natural width at a box edge). [The text cohort →](https://github.com/ReuHomi/uxml-preview/blob/main/docs/accuracy.en.md#text-cohort-separate-set-measured-2026-10-16)
27
+ - **Under what conditions:** the coordinate figures measure layout given the text sizes — the harness measures text with a fixed function, and the text figures measure text separately. The text figures are measured with the same font file Unity uses passed to the preview; without a font, the preview measures with the browser's default font, so text widths can differ by a few pixels and wrapped text can break into a different number of lines. [Conditions →](https://github.com/ReuHomi/uxml-preview/blob/main/docs/accuracy.en.md)
23
28
  - **Unity version:** the reference is Unity 6.3 LTS. A property is USS if Unity's official property table lists it, up to 6.6; 6.7 is not supported until it is an LTS. [What is supported →](https://github.com/ReuHomi/uxml-preview/blob/main/docs/supported.en.md)
24
29
  - **What does not match is reported, not glossed over.** An unsupported control, property or value comes back as a warning that says why, and — where it was measured — what Unity does instead. [Warnings →](https://github.com/ReuHomi/uxml-preview/blob/main/docs/api.en.md#warnings)
25
30
 
package/README.zh-CN.md CHANGED
@@ -5,6 +5,8 @@
5
5
  **无需 Unity 编辑器,即可在浏览器中渲染 Unity UI Toolkit 的 UXML/USS——由 UI Toolkit 自身使用的
6
6
  Yoga 引擎负责布局,并与 Unity 实测结果进行了比对验证。**
7
7
 
8
+ ![uxml-preview 0.7.0:左侧是用 UXML 和 USS 编写的设置界面,右侧是浏览器中的渲染结果](https://raw.githubusercontent.com/ReuHomi/uxml-preview/main/docs/media/promo-0.7.0.gif)
9
+
8
10
  [![在线体验页面:上方为预览画面,下方列出每条警告的原因及 Unity 的实际处理方式](https://raw.githubusercontent.com/ReuHomi/uxml-preview/main/docs/media/playground.png)](https://reuhomi.github.io/uxml-preview/)
9
11
 
10
12
  ### ▶ [打开在线体验 (Playground)](https://reuhomi.github.io/uxml-preview/)
@@ -18,8 +20,11 @@ Yoga 引擎负责布局,并与 Unity 实测结果进行了比对验证。**
18
20
 
19
21
  ## 验证方式
20
22
 
21
- - **坐标:** 在包含完整界面在内的 40 个布局用例中,660 / 676 个元素坐标值与 Unity 6000.0.40f1 完全一致。[查看全部差异明细 →](https://github.com/ReuHomi/uxml-preview/blob/main/docs/accuracy.en.md) 在 Unity 6.3(6000.3.25f1)中重新导出这批用例后,所有布局结果均与当天导出的 6000.0.40f1 结果一致。[6.3 重新测量结果 →](https://github.com/ReuHomi/uxml-preview/blob/main/docs/accuracy.en.md#unity-63-lts-re-measurement-2026-10-15)
22
- - **文本:** 在真实浏览器中绘制,并与 Unity 6000.3.25f1 逐个 Label 进行比对——行数 92 / 92、高度 84 / 92、宽度 92 / 92(误差在 1px 或 1% 以内)。所有高度存在差异的用例,均是使用了不含韩文字符的拉丁字体 Inter 来排版韩文或混排文本;此时 Unity 会改用回退字体绘制,而本预览工具会针对该情况发出明确警告。[文本测试集 →](https://github.com/ReuHomi/uxml-preview/blob/main/docs/accuracy.en.md#text-cohort-separate-set-measured-2026-10-16)
23
+ - **坐标·运行时主题(默认):** 在同样的 42 个布局用例中,1122 / 1148 个元素坐标值与真实的 Unity 6.3 运行时面板(6000.3.25f1,PanelSettings + UIDocument,Play 模式)完全一致。剩余差异均为编辑器主题同样存在的差异。[测量方法 →](https://github.com/ReuHomi/uxml-preview/blob/main/docs/accuracy.en.md#runtime-theme-separate-set-measured-2026-10-17)
24
+ - **坐标·编辑器主题:** 在包含三个完整界面(物品栏,以及使用全部 15 种已绘制控件的设置界面英文版和韩文版)在内的 42 个布局用例中,1122 / 1148 个元素坐标值与 Unity 6000.0.40f1 完全一致。[查看全部差异明细 →](https://github.com/ReuHomi/uxml-preview/blob/main/docs/accuracy.en.md) 在 Unity 6.3(6000.3.25f1)中重新导出这批用例后,所有布局结果均与当天导出的 6000.0.40f1 结果一致。[6.3 重新测量结果 →](https://github.com/ReuHomi/uxml-preview/blob/main/docs/accuracy.en.md#unity-63-lts-re-measurement-2026-10-15)
25
+ - **文本,运行时主题(默认):** 在真实浏览器中绘制,并与真实的 Unity 运行时面板(6000.0.40f1 与 6000.3.25f1,每个探针单独启动一个 Unity 进程)逐个 Label 进行比对——行数 92 / 92、高度 84 / 92、宽度 92 / 92(误差在 1px 或 1% 以内),框边界处的换行用例 159 / 159。所有高度存在差异的用例,均是使用了不含韩文字符的拉丁字体 Inter 来排版韩文或混排文本;此时 Unity 会改用回退字体绘制,而本预览工具会针对该情况发出明确警告。[运行时文本测试集 →](https://github.com/ReuHomi/uxml-preview/blob/main/docs/accuracy.en.md#runtime-panel-separate-set-measured-2026-10-19--item-t)
26
+ - **文本,编辑器主题:** 同样的 92 个 Label 与 Unity 6000.3.25f1 编辑器比对——92 / 92、84 / 92、92 / 92,换行用例 157 / 159(其余 2 个:一个中文用例中编辑器的禁则处理,以及框边界处 1px 的自然宽度差)。[文本测试集 →](https://github.com/ReuHomi/uxml-preview/blob/main/docs/accuracy.en.md#text-cohort-separate-set-measured-2026-10-16)
27
+ - **测量条件:** 坐标数值测量的是给定文字尺寸时的布局(测试工具用固定函数测量文字,文字测量由文本数值单独衡量)。文本数值是在向预览传入与 Unity 相同的字体文件的条件下测得的。若不传入字体,预览会用浏览器默认字体测量,文字宽度可能相差几个像素,多行文本的行数也可能不同。[条件 →](https://github.com/ReuHomi/uxml-preview/blob/main/docs/accuracy.en.md)
23
28
  - **Unity 版本:** 基准版本为 Unity 6.3 LTS。某项属性是否属于 USS,依据 Unity 官方属性表(截至 6.6)判定;6.7 在推出 LTS 版本之前暂不支持。[支持范围 →](https://github.com/ReuHomi/uxml-preview/blob/main/docs/supported.en.md)
24
29
  - **不一致之处会明确报告,绝不静默忽略。** 遇到不支持的控件、属性或值时,工具会返回警告并说明原因;对于已实测的情况,还会一并告知 Unity 的实际处理方式。[警告说明 →](https://github.com/ReuHomi/uxml-preview/blob/main/docs/api.en.md#warnings)
25
30
 
@@ -1,4 +1,16 @@
1
1
  import { ElementNode } from '../model/types';
2
+ export declare function uxmlBoolean(value: string | undefined): boolean | undefined;
3
+ export declare function isVertical(value: string | undefined): boolean;
4
+ /**
5
+ * Purpose: match k-slider/k-progress dumps (bundle-A plan §32) for display and layout.
6
+ * Ensures: values are finite and clamped; invalid input retains the attribute default.
7
+ */
8
+ export declare function numericControlValue(node: ElementNode): {
9
+ low: number;
10
+ high: number;
11
+ value: number;
12
+ invalid: boolean;
13
+ };
2
14
  /**
3
15
  * An element a control builds for itself, which the file never mentions.
4
16
  *
@@ -11,8 +23,18 @@ import { ElementNode } from '../model/types';
11
23
  * observed in `tests/golden/unity/scrollview-*.json`, not invented.
12
24
  */
13
25
  export interface ControlPart {
14
- /** Unity's name, e.g. `unity-content-viewport`. */
26
+ /** Unity name, or class identity for the unnamed GroupBox title. */
15
27
  name: string;
28
+ /** Earlier part index, or null for the owner; omitted preserves the wrapper chain. */
29
+ parent?: number | null;
30
+ textValue?: string;
31
+ /** Text parts are measured leaves; a leading Label is a sibling of the wrapper chain. */
32
+ kind?: 'leading-text' | 'text';
33
+ /** Attribute text is decoded only for the derived rendering, never in the AST. */
34
+ textAttribute?: 'text' | 'label' | 'value' | 'title';
35
+ typeName?: string;
36
+ unnamed?: boolean;
37
+ classes?: readonly string[];
16
38
  /**
17
39
  * USS this part always carries, because the control fixes it.
18
40
  *
@@ -26,10 +48,14 @@ export interface ControlSpec {
26
48
  /** Renders the `text` attribute as its own content. */
27
49
  hasText: boolean;
28
50
  /**
29
- * Elements the control inserts between itself and the file's children,
30
- * outermost first. The file's children go inside the last one.
51
+ * Parts are parent-before-child. Explicit parent indices describe branches.
52
+ * Otherwise these are elements inserted between the control and file children,
53
+ * outermost first. File children go inside the last wrapper; leading text
54
+ * parts are siblings before them and exist only for non-empty owner text.
31
55
  */
32
56
  parts: readonly ControlPart[];
57
+ /** File children follow all parts; omitted uses the last non-text part, or owner. */
58
+ fileChildrenHost?: 'owner' | 'last-part';
33
59
  /**
34
60
  * USS classes Unity's own constructor puts on this control, which the theme
35
61
  * stylesheet then targets. Not in the `class` attribute and not in the model:
@@ -58,10 +84,12 @@ export declare function resolveControl(node: ElementNode): ResolvedControl;
58
84
  export declare function isRoot(node: ElementNode): boolean;
59
85
  /**
60
86
  * Purpose: the USS classes Unity would have added to this element.
61
- * Ensures: empty for anything with no renderer of its own — a fallback box
62
- * must not pick up theme styling meant for a control we do not
63
- * actually draw.
87
+ * Ensures: control classes and own disabled class remain outside the model.
64
88
  */
65
89
  export declare function implicitClassesOf(node: ElementNode): readonly string[];
66
90
  /** Controls with a renderer of their own. Everything else still draws. */
67
91
  export declare function supportedControlNames(): string[];
92
+ /** Ensures: password values are masked before measurement or DOM painting. */
93
+ export declare function partTextOf(node: ElementNode, part: ControlPart): string | undefined;
94
+ /** Ensures: legacy wrapper chains and explicit part trees share one parent contract. */
95
+ export declare function partParentIndex(parts: readonly ControlPart[], index: number): number | null;