xbintsc 0.5.51 → 0.5.52

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.
Files changed (122) hide show
  1. package/dist/src/cli/help.d.ts +1 -1
  2. package/dist/src/driver/version.d.ts +1 -1
  3. package/dist/src/driver/version.js +1 -1
  4. package/dist/src/extensions/gui/features.d.ts +9 -6
  5. package/dist/src/extensions/gui/features.js +14 -9
  6. package/dist/src/extensions/gui/features.js.map +1 -1
  7. package/dist/tests/e2e/gui-css-coverage.test.d.ts +9 -0
  8. package/dist/tests/e2e/gui-css-coverage.test.js +333 -0
  9. package/dist/tests/e2e/gui-css-coverage.test.js.map +1 -0
  10. package/dist/tests/e2e/gui-css-features.test.d.ts +6 -0
  11. package/dist/tests/e2e/gui-css-features.test.js +270 -0
  12. package/dist/tests/e2e/gui-css-features.test.js.map +1 -0
  13. package/dist/tests/e2e/gui-effects.test.js +92 -11
  14. package/dist/tests/e2e/gui-effects.test.js.map +1 -1
  15. package/dist/tests/e2e/gui-font-face.test.d.ts +10 -0
  16. package/dist/tests/e2e/gui-font-face.test.js +142 -0
  17. package/dist/tests/e2e/gui-font-face.test.js.map +1 -0
  18. package/dist/tests/e2e/gui-fonts.test.d.ts +10 -0
  19. package/dist/tests/e2e/gui-fonts.test.js +150 -0
  20. package/dist/tests/e2e/gui-fonts.test.js.map +1 -0
  21. package/dist/tests/e2e/gui-helpers.d.ts +5 -0
  22. package/dist/tests/e2e/gui-helpers.js +4 -0
  23. package/dist/tests/e2e/gui-helpers.js.map +1 -1
  24. package/dist/tests/e2e/gui-layout.test.js +3 -2
  25. package/dist/tests/e2e/gui-layout.test.js.map +1 -1
  26. package/dist/tests/e2e/gui-track-sizing.test.d.ts +6 -0
  27. package/dist/tests/e2e/gui-track-sizing.test.js +173 -0
  28. package/dist/tests/e2e/gui-track-sizing.test.js.map +1 -0
  29. package/dist/tests/e2e/gui-transform.test.js +3 -2
  30. package/dist/tests/e2e/gui-transform.test.js.map +1 -1
  31. package/dist/tests/extensions/gui-features.test.js +8 -1
  32. package/dist/tests/extensions/gui-features.test.js.map +1 -1
  33. package/doc/ai/extensions.md +10 -5
  34. package/doc/ai/zh-CN/extensions.md +9 -4
  35. package/doc/gui/animation.md +39 -9
  36. package/doc/gui/build.md +6 -5
  37. package/doc/gui/dom.md +20 -4
  38. package/doc/gui/known-issues.md +31 -23
  39. package/doc/gui/layout.md +30 -7
  40. package/doc/gui/rendering.md +84 -26
  41. package/doc/gui.md +62 -14
  42. package/doc/zh-CN/gui/animation.md +33 -10
  43. package/doc/zh-CN/gui/build.md +5 -5
  44. package/doc/zh-CN/gui/dom.md +16 -3
  45. package/doc/zh-CN/gui/known-issues.md +21 -12
  46. package/doc/zh-CN/gui/layout.md +22 -5
  47. package/doc/zh-CN/gui/rendering.md +61 -20
  48. package/doc/zh-CN/gui.md +53 -15
  49. package/package.json +7 -7
  50. package/runtime/ext_gui/animation_values.cpp +425 -0
  51. package/runtime/ext_gui/animation_values.h +64 -0
  52. package/runtime/ext_gui/css.cpp +172 -21
  53. package/runtime/ext_gui/css.h +75 -4
  54. package/runtime/ext_gui/css_match.cpp +4 -0
  55. package/runtime/ext_gui/css_sheet.cpp +218 -2
  56. package/runtime/ext_gui/document.cpp +42 -192
  57. package/runtime/ext_gui/document.h +25 -12
  58. package/runtime/ext_gui/document_animation.cpp +428 -0
  59. package/runtime/ext_gui/effect_values.cpp +245 -21
  60. package/runtime/ext_gui/gradient_values.cpp +24 -0
  61. package/runtime/ext_gui/grid_values.cpp +23 -0
  62. package/runtime/ext_gui/gui_cursor.cpp +50 -0
  63. package/runtime/ext_gui/gui_events.cpp +16 -4
  64. package/runtime/ext_gui/gui_internal.h +3 -0
  65. package/runtime/ext_gui/image_api.h +3 -1
  66. package/runtime/ext_gui/image_feature.cpp +4 -2
  67. package/runtime/ext_gui/inline_svg.cpp +95 -8
  68. package/runtime/ext_gui/inline_svg.h +5 -1
  69. package/runtime/ext_gui/layout.cpp +3 -2
  70. package/runtime/ext_gui/layout.h +6 -0
  71. package/runtime/ext_gui/layout_flex.cpp +134 -29
  72. package/runtime/ext_gui/layout_flow.cpp +58 -7
  73. package/runtime/ext_gui/layout_flow_internal.h +39 -4
  74. package/runtime/ext_gui/layout_grid.cpp +31 -0
  75. package/runtime/ext_gui/layout_inline.cpp +26 -2
  76. package/runtime/ext_gui/layout_vertical.cpp +196 -0
  77. package/runtime/ext_gui/paint.cpp +67 -9
  78. package/runtime/ext_gui/paint.h +61 -8
  79. package/runtime/ext_gui/paint_backdrop.cpp +211 -0
  80. package/runtime/ext_gui/paint_background.cpp +175 -97
  81. package/runtime/ext_gui/paint_effects.cpp +12 -6
  82. package/runtime/ext_gui/paint_internal.h +27 -0
  83. package/runtime/ext_gui/paint_outline.cpp +44 -0
  84. package/runtime/ext_gui/paint_shadow.cpp +368 -0
  85. package/runtime/ext_gui/renderer.cpp +15 -7
  86. package/runtime/ext_gui/renderer.h +10 -1
  87. package/runtime/ext_gui/renderer_backdrop.cpp +374 -0
  88. package/runtime/ext_gui/renderer_bitmap.cpp +82 -0
  89. package/runtime/ext_gui/renderer_gradient.cpp +51 -17
  90. package/runtime/ext_gui/renderer_image.cpp +6 -1
  91. package/runtime/ext_gui/renderer_internal.h +21 -0
  92. package/runtime/ext_gui/renderer_layer.cpp +27 -1
  93. package/runtime/ext_gui/renderer_text.cpp +2 -1
  94. package/runtime/ext_gui/style.cpp +62 -8
  95. package/runtime/ext_gui/style.h +111 -4
  96. package/runtime/ext_gui/style_cascade.cpp +83 -0
  97. package/runtime/ext_gui/style_internal.h +13 -1
  98. package/runtime/ext_gui/style_length.cpp +92 -0
  99. package/runtime/ext_gui/style_print.cpp +83 -2
  100. package/runtime/ext_gui/style_svg.cpp +40 -0
  101. package/runtime/ext_gui/style_text.cpp +302 -0
  102. package/runtime/ext_gui/style_ui.cpp +150 -0
  103. package/runtime/ext_gui/style_values.cpp +76 -62
  104. package/runtime/ext_gui/style_values_internal.h +23 -0
  105. package/runtime/ext_gui/text.cpp +4 -2
  106. package/runtime/ext_gui/text.h +11 -4
  107. package/runtime/ext_gui/text_cache.cpp +11 -2
  108. package/runtime/ext_gui/text_font_db.cpp +427 -0
  109. package/runtime/ext_gui/text_font_paths.cpp +250 -0
  110. package/runtime/ext_gui/text_font_paths.h +39 -0
  111. package/runtime/ext_gui/text_font_sfnt.cpp +396 -0
  112. package/runtime/ext_gui/text_font_sfnt.h +44 -0
  113. package/runtime/ext_gui/text_fonts.cpp +348 -0
  114. package/runtime/ext_gui/text_fonts.h +78 -0
  115. package/runtime/ext_gui/text_fonts_internal.h +77 -0
  116. package/runtime/ext_gui/text_hb.cpp +63 -179
  117. package/runtime/ext_gui/text_stb.cpp +49 -193
  118. package/runtime/ext_gui/transform.cpp +107 -9
  119. package/runtime/ext_gui/transform.h +5 -0
  120. package/runtime/ext_gui/window.cpp +1 -1
  121. package/src/driver/version.ts +1 -1
  122. package/src/extensions/gui/features.ts +13 -9
@@ -4,4 +4,4 @@
4
4
  * It lives apart from the command dispatch so the executable entry point stays
5
5
  * under the repository's per-file line budget; the text is data, not logic.
6
6
  */
7
- export declare const HELP = "xbintsc 0.5.51 - TypeScript binary compiler\n\nUsage:\n xbintsc build <file.ts> [options] Compile to a native binary\n xbintsc run <file.ts> [-- args] Compile and execute\n xbintsc check <file.ts> Parse, bind and check without linking\n xbintsc watch <file.ts> [options] Rebuild whenever the source tree changes\n xbintsc emit <file.ts> Print LLVM IR\n xbintsc doctor Report the resolved toolchain\n xbintsc version Print the version\n xbintsc help Show this message\n\nOptions:\n -o, --output <path> Output path\n --out <dir> Output directory (default: build/)\n --emit <kind> exe | obj | ir (default: exe)\n -O0..-O3 Optimization level (default: -O2)\n --ext <names> Comma separated extensions (e.g. node,gui)\n --feature <names> Force optional link features on (media,gpu,images,shaping,webgl,all)\n --no-feature <n> Keep optional link features out even when detected\n --ext-native <m> Register a C++/Rust extension from a JSON manifest\n (comma separated for several)\n --config <path> Use a project config (default: auto-detect\n xbintsc.config.json)\n --no-config Do not read any project config\n --icon <path> Embed an application icon (PNG/ICO/ICNS)\n --bundle macOS: also produce a .app bundle\n --app-name <name> Bundle / display name\n --app-id <id> macOS bundle identifier (e.g. com.example.demo)\n --force Ignore the incremental cache\n --verbose Print progress information\n --time Print per-phase build timings\n --debug Emit debug info (DWARF/CodeView) and keep frame pointers\n --check Run the semantic checker (default)\n --no-check Skip the semantic checker; only erase type syntax\n --lto Compile program and runtime to LTO bitcode; link with lld\n --pgo-generate [dir] Build an instrumented binary writing profiles to dir\n --pgo-use [dir] Build with the profiles collected from --pgo-generate\n --json Print diagnostics as a JSON array on stdout\n --no-hints Do not append the \"hint: \u2026 see <doc>\" line to failures\n\nxbintsc compiles a subset of TypeScript to a native binary. Types are erased;\nonly inference-free facts (names, redeclarations, call arity) are checked.\nNode built-ins need --ext node, packages in node_modules are bundled at build\ntime, and clang 16+ is required to link.\n\nInstalled as a project dependency (npm):\n npx xbintsc doctor\n npx xbintsc build <entry.ts> --out build\n npx xbintsc run <entry.ts>\nThe first build compiles the C runtime; later builds reuse the cache.\n\nDocs: doc/ai/README.md (task guide) - doc/ai/language-support.md (subset) -\ndoc/ai/troubleshooting.md (failures) - llms.txt (index of every document).\nWhen installed from npm, these live under node_modules/xbintsc/doc/ and\nnode_modules/xbintsc/doc/npm-package.md is the project guide.\n";
7
+ export declare const HELP = "xbintsc 0.5.52 - TypeScript binary compiler\n\nUsage:\n xbintsc build <file.ts> [options] Compile to a native binary\n xbintsc run <file.ts> [-- args] Compile and execute\n xbintsc check <file.ts> Parse, bind and check without linking\n xbintsc watch <file.ts> [options] Rebuild whenever the source tree changes\n xbintsc emit <file.ts> Print LLVM IR\n xbintsc doctor Report the resolved toolchain\n xbintsc version Print the version\n xbintsc help Show this message\n\nOptions:\n -o, --output <path> Output path\n --out <dir> Output directory (default: build/)\n --emit <kind> exe | obj | ir (default: exe)\n -O0..-O3 Optimization level (default: -O2)\n --ext <names> Comma separated extensions (e.g. node,gui)\n --feature <names> Force optional link features on (media,gpu,images,shaping,webgl,all)\n --no-feature <n> Keep optional link features out even when detected\n --ext-native <m> Register a C++/Rust extension from a JSON manifest\n (comma separated for several)\n --config <path> Use a project config (default: auto-detect\n xbintsc.config.json)\n --no-config Do not read any project config\n --icon <path> Embed an application icon (PNG/ICO/ICNS)\n --bundle macOS: also produce a .app bundle\n --app-name <name> Bundle / display name\n --app-id <id> macOS bundle identifier (e.g. com.example.demo)\n --force Ignore the incremental cache\n --verbose Print progress information\n --time Print per-phase build timings\n --debug Emit debug info (DWARF/CodeView) and keep frame pointers\n --check Run the semantic checker (default)\n --no-check Skip the semantic checker; only erase type syntax\n --lto Compile program and runtime to LTO bitcode; link with lld\n --pgo-generate [dir] Build an instrumented binary writing profiles to dir\n --pgo-use [dir] Build with the profiles collected from --pgo-generate\n --json Print diagnostics as a JSON array on stdout\n --no-hints Do not append the \"hint: \u2026 see <doc>\" line to failures\n\nxbintsc compiles a subset of TypeScript to a native binary. Types are erased;\nonly inference-free facts (names, redeclarations, call arity) are checked.\nNode built-ins need --ext node, packages in node_modules are bundled at build\ntime, and clang 16+ is required to link.\n\nInstalled as a project dependency (npm):\n npx xbintsc doctor\n npx xbintsc build <entry.ts> --out build\n npx xbintsc run <entry.ts>\nThe first build compiles the C runtime; later builds reuse the cache.\n\nDocs: doc/ai/README.md (task guide) - doc/ai/language-support.md (subset) -\ndoc/ai/troubleshooting.md (failures) - llms.txt (index of every document).\nWhen installed from npm, these live under node_modules/xbintsc/doc/ and\nnode_modules/xbintsc/doc/npm-package.md is the project guide.\n";
@@ -9,4 +9,4 @@
9
9
  * `main`/`master` only (see `.githooks/pre-commit`), so feature branches never
10
10
  * change this line and merging two of them cannot conflict here.
11
11
  */
12
- export declare const COMPILER_VERSION = "0.5.51";
12
+ export declare const COMPILER_VERSION = "0.5.52";
@@ -9,5 +9,5 @@
9
9
  * `main`/`master` only (see `.githooks/pre-commit`), so feature branches never
10
10
  * change this line and merging two of them cannot conflict here.
11
11
  */
12
- export const COMPILER_VERSION = "0.5.51";
12
+ export const COMPILER_VERSION = "0.5.52";
13
13
  //# sourceMappingURL=version.js.map
@@ -8,14 +8,15 @@
8
8
  * The DOM media surface lives in `gui.a`; only decoding is optional, and an
9
9
  * element without the backend still exists and fires `error`.
10
10
  * - `gpu` — glslang (+ SPIRV-Cross on macOS), the GLSL→SPIR-V translator used
11
- * by WebGL *and* by the `mix-blend-mode` offscreen compositor. The engine's
12
- * own shaders are precompiled, so a DOM/2D-canvas page never needs it.
11
+ * by WebGL *and* by the `mix-blend-mode` / `backdrop-filter` offscreen
12
+ * compositor. The engine's own shaders are precompiled, so a DOM page
13
+ * never needs it.
13
14
  *
14
15
  * Detection is static: the compiler sees imported `.html`/`.css` assets and all
15
16
  * bundled modules, so it can recognise `<video>`/`<audio>`, `getContext("webgl")`
16
- * and `mix-blend-mode`. When markup can be built at run time the usage collector
17
- * sets `dynamicMarkup`, which conservatively enables both features; users who
18
- * know better can shrink the binary with `--no-feature`.
17
+ * and `mix-blend-mode`/`backdrop-filter`. When markup can be built at run time
18
+ * the usage collector sets `dynamicMarkup`, which conservatively enables both
19
+ * features; users who know better can shrink the binary with `--no-feature`.
19
20
  */
20
21
  import type { LinkFeature, ProgramUsage } from "../link-feature.js";
21
22
  /** True when the program may create or drive a media element. */
@@ -26,6 +27,8 @@ export declare function hasGpuUsage(usage: ProgramUsage): boolean;
26
27
  export declare function hasWebglUsage(usage: ProgramUsage): boolean;
27
28
  /** True when the program may draw a bitmap or SVG. */
28
29
  export declare function hasImageUsage(usage: ProgramUsage): boolean;
29
- /** True when the program may need full OpenType shaping (non-Latin text). */
30
+ /** True when the program may need full OpenType shaping. Non-Latin text needs it
31
+ * for shaping, and an author `@font-face` often points at a CFF/OTF font that
32
+ * the default stb_truetype backend cannot outline. */
30
33
  export declare function hasShapingUsage(usage: ProgramUsage): boolean;
31
34
  export declare const guiLinkFeatures: readonly LinkFeature[];
@@ -8,14 +8,15 @@
8
8
  * The DOM media surface lives in `gui.a`; only decoding is optional, and an
9
9
  * element without the backend still exists and fires `error`.
10
10
  * - `gpu` — glslang (+ SPIRV-Cross on macOS), the GLSL→SPIR-V translator used
11
- * by WebGL *and* by the `mix-blend-mode` offscreen compositor. The engine's
12
- * own shaders are precompiled, so a DOM/2D-canvas page never needs it.
11
+ * by WebGL *and* by the `mix-blend-mode` / `backdrop-filter` offscreen
12
+ * compositor. The engine's own shaders are precompiled, so a DOM page
13
+ * never needs it.
13
14
  *
14
15
  * Detection is static: the compiler sees imported `.html`/`.css` assets and all
15
16
  * bundled modules, so it can recognise `<video>`/`<audio>`, `getContext("webgl")`
16
- * and `mix-blend-mode`. When markup can be built at run time the usage collector
17
- * sets `dynamicMarkup`, which conservatively enables both features; users who
18
- * know better can shrink the binary with `--no-feature`.
17
+ * and `mix-blend-mode`/`backdrop-filter`. When markup can be built at run time
18
+ * the usage collector sets `dynamicMarkup`, which conservatively enables both
19
+ * features; users who know better can shrink the binary with `--no-feature`.
19
20
  */
20
21
  import { join } from "node:path";
21
22
  import { findRuntimeDir, platformSlug } from "../../driver/paths.js";
@@ -25,7 +26,7 @@ const MEDIA_TAG = /<(?:video|audio)\b/i;
25
26
  /** A literal tag name handed to `createElement("video")`. */
26
27
  const MEDIA_TAG_NAME = /^(?:video|audio)$/i;
27
28
  /** Anything that needs the GLSL translator. */
28
- const GPU_TOKEN = /webgl|mix-blend-mode|mixBlendMode/i;
29
+ const GPU_TOKEN = /webgl|mix-blend-mode|mixBlendMode|backdrop-filter|backdropFilter/i;
29
30
  /** True when the program may create or drive a media element. */
30
31
  export function hasMediaUsage(usage) {
31
32
  if (usage.dynamicMarkup)
@@ -40,7 +41,7 @@ export function hasMediaUsage(usage) {
40
41
  export function hasGpuUsage(usage) {
41
42
  if (usage.dynamicMarkup)
42
43
  return true;
43
- if (usage.identifiers.has("mixBlendMode"))
44
+ if (usage.identifiers.has("mixBlendMode") || usage.identifiers.has("backdropFilter"))
44
45
  return true;
45
46
  if (usage.getContext.some((kind) => kind === undefined || /webgl/i.test(kind)))
46
47
  return true;
@@ -64,11 +65,15 @@ export function hasImageUsage(usage) {
64
65
  }
65
66
  return usage.strings.some((value) => /<img\b|<svg\b|background-image|url\(|\.svg\b|drawImage|createImageBitmap/i.test(value));
66
67
  }
67
- /** True when the program may need full OpenType shaping (non-Latin text). */
68
+ /** True when the program may need full OpenType shaping. Non-Latin text needs it
69
+ * for shaping, and an author `@font-face` often points at a CFF/OTF font that
70
+ * the default stb_truetype backend cannot outline. */
68
71
  export function hasShapingUsage(usage) {
69
72
  if (usage.dynamicMarkup)
70
73
  return true;
71
74
  return usage.strings.some((value) => {
75
+ if (/@font-face\b/i.test(value))
76
+ return true;
72
77
  for (const character of value) {
73
78
  if ((character.codePointAt(0) ?? 0) > 0x7f)
74
79
  return true;
@@ -110,7 +115,7 @@ export const guiLinkFeatures = [
110
115
  },
111
116
  {
112
117
  name: "gpu",
113
- description: "GLSL translation (WebGL and mix-blend-mode) via glslang",
118
+ description: "GLSL translation (WebGL, mix-blend-mode and backdrop-filter) via glslang",
114
119
  /**
115
120
  * `gpu_bridge.c` is linked only when the feature is active. It calls into
116
121
  * `gpu_feature.cpp` inside `gui.a`, which installs the shader-translation
@@ -1 +1 @@
1
- {"version":3,"file":"features.js","sourceRoot":"","sources":["../../../../src/extensions/gui/features.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"features.js","sourceRoot":"","sources":["../../../../src/extensions/gui/features.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,9 @@
1
+ /**
2
+ * End-to-end coverage for the CSS surface used by the Inside the Ropes
3
+ * stylesheets: typography, inline flex/grid, grid-area, aspect-ratio, auto
4
+ * margins, percentage radii, outlines, vertical text, SVG presentation
5
+ * properties and sized background tiles. Assertions use layout geometry,
6
+ * `computedStyle`, `paintList` and the `inlineSvg` diagnostic, so they are
7
+ * deterministic without reading GPU pixels.
8
+ */
9
+ export {};
@@ -0,0 +1,333 @@
1
+ /**
2
+ * End-to-end coverage for the CSS surface used by the Inside the Ropes
3
+ * stylesheets: typography, inline flex/grid, grid-area, aspect-ratio, auto
4
+ * margins, percentage radii, outlines, vertical text, SVG presentation
5
+ * properties and sized background tiles. Assertions use layout geometry,
6
+ * `computedStyle`, `paintList` and the `inlineSvg` diagnostic, so they are
7
+ * deterministic without reading GPU pixels.
8
+ */
9
+ import { afterAll, beforeAll, describe, expect, it } from "vitest";
10
+ import { createGuiHarness, guiAvailable } from "./gui-helpers.js";
11
+ const harness = createGuiHarness();
12
+ describe.skipIf(!guiAvailable)("gui extension — CSS coverage", () => {
13
+ beforeAll(() => harness.setup());
14
+ afterAll(() => harness.cleanup());
15
+ it("applies letter-spacing and text-transform to layout and paint", () => {
16
+ const { value, stdout } = harness.compileAndRun("typography", `
17
+ import { createWindow, run } from "gui";
18
+
19
+ const HTML = \`
20
+ <html><head><style>
21
+ body { margin: 0; }
22
+ #a, #b, #c {
23
+ position: absolute; top: 0; font-size: 20px; white-space: nowrap;
24
+ }
25
+ #a { left: 0; }
26
+ #b { left: 200px; letter-spacing: 2px; }
27
+ #c { left: 350px; text-transform: uppercase; }
28
+ </style></head><body>
29
+ <div id="a">abc</div><div id="b">abc</div><div id="c">abc</div>
30
+ </body></html>\`;
31
+
32
+ const win = createWindow({ title: "typography", width: 500, height: 120 });
33
+ win.on("ready", () => {
34
+ const a = win.getBoundingClientRect("#a");
35
+ const b = win.getBoundingClientRect("#b");
36
+ console.log("delta=" + (b.width - a.width).toFixed(1));
37
+ console.log("spacing=" + win.computedStyle("#b", "letter-spacing"));
38
+ console.log("transform=" + win.computedStyle("#c", "text-transform"));
39
+ console.log(win.paintList());
40
+ win.close();
41
+ });
42
+ win.loadHTML(HTML);
43
+ run();
44
+ `);
45
+ // Three characters, two pixels each, including the trailing one.
46
+ expect(value("delta")).toBe("6.0");
47
+ expect(value("spacing")).toBe("2px");
48
+ expect(value("transform")).toBe("uppercase");
49
+ expect(stdout).toContain('"ABC"');
50
+ });
51
+ it("resolves currentColor and percentage border radii", () => {
52
+ const { value, stdout } = harness.compileAndRun("colors-radius", `
53
+ import { createWindow, run } from "gui";
54
+
55
+ const HTML = \`
56
+ <html><head><style>
57
+ body { margin: 0; }
58
+ #dot {
59
+ color: #ff0000;
60
+ background: currentColor;
61
+ width: 20px; height: 20px;
62
+ border-radius: 50%;
63
+ }
64
+ </style></head><body><div id="dot"></div></body></html>\`;
65
+
66
+ const win = createWindow({ title: "colors", width: 200, height: 120 });
67
+ win.on("ready", () => {
68
+ console.log("bg=" + win.computedStyle("#dot", "background-color"));
69
+ console.log("radius=" + win.computedStyle("#dot", "border-radius"));
70
+ console.log(win.paintList());
71
+ win.close();
72
+ });
73
+ win.loadHTML(HTML);
74
+ run();
75
+ `);
76
+ expect(value("bg")).toBe("rgb(255, 0, 0)");
77
+ expect(value("radius")).toBe("50%");
78
+ expect(stdout).toContain("r=10.0 color=#ff0000ff");
79
+ });
80
+ it("lays out inline-flex and inline-grid boxes atomically", () => {
81
+ const { value } = harness.compileAndRun("inline-containers", `
82
+ import { createWindow, run } from "gui";
83
+
84
+ const HTML = \`
85
+ <html><head><style>
86
+ body { margin: 0; }
87
+ #row { display: inline-flex; gap: 10px; }
88
+ #row i { display: block; width: 20px; height: 20px; background: #222; }
89
+ #key {
90
+ display: inline-grid; place-items: center;
91
+ width: 17px; height: 17px; vertical-align: -3px;
92
+ background: #333;
93
+ }
94
+ </style></head><body>
95
+ <div id="line"><span id="row"><i></i><i></i></span><span id="key">W</span></div>
96
+ </body></html>\`;
97
+
98
+ const win = createWindow({ title: "inline", width: 400, height: 120 });
99
+ win.on("ready", () => {
100
+ const row = win.getBoundingClientRect("#row");
101
+ const key = win.getBoundingClientRect("#key");
102
+ console.log("row=" + row.width.toFixed(1) + "x" + row.height.toFixed(1));
103
+ console.log("key=" + key.width.toFixed(1) + "x" + key.height.toFixed(1));
104
+ console.log("flex=" + win.computedStyle("#row", "display"));
105
+ console.log("grid=" + win.computedStyle("#key", "display"));
106
+ console.log("align=" + win.computedStyle("#key", "vertical-align"));
107
+ win.close();
108
+ });
109
+ win.loadHTML(HTML);
110
+ run();
111
+ `);
112
+ expect(value("row")).toBe("50.0x20.0");
113
+ expect(value("key")).toBe("17.0x17.0");
114
+ expect(value("flex")).toBe("inline-flex");
115
+ expect(value("grid")).toBe("inline-grid");
116
+ expect(value("align")).toBe("-3px");
117
+ });
118
+ it("places grid-area items and derives height from aspect-ratio", () => {
119
+ const { value } = harness.compileAndRun("grid-aspect", `
120
+ import { createWindow, run } from "gui";
121
+
122
+ const HTML = \`
123
+ <html><head><style>
124
+ body { margin: 0; }
125
+ #grid {
126
+ display: grid;
127
+ grid-template-columns: repeat(3, 30px);
128
+ grid-template-rows: repeat(3, 30px);
129
+ }
130
+ #cell { grid-area: 2 / 3; background: #444; }
131
+ #ratio { width: 300px; aspect-ratio: 3 / 4; background: #555; }
132
+ </style></head><body>
133
+ <div id="grid"><div id="cell"></div></div>
134
+ <div id="ratio"></div>
135
+ </body></html>\`;
136
+
137
+ const win = createWindow({ title: "grid", width: 500, height: 500 });
138
+ win.on("ready", () => {
139
+ const cell = win.getBoundingClientRect("#cell");
140
+ const ratio = win.getBoundingClientRect("#ratio");
141
+ console.log("cell=" + cell.x.toFixed(1) + "," + cell.y.toFixed(1));
142
+ console.log("ratio=" + ratio.width.toFixed(1) + "x" + ratio.height.toFixed(1));
143
+ console.log("area=" + win.computedStyle("#cell", "grid-area"));
144
+ console.log("ar=" + win.computedStyle("#ratio", "aspect-ratio"));
145
+ win.close();
146
+ });
147
+ win.loadHTML(HTML);
148
+ run();
149
+ `);
150
+ expect(value("cell")).toBe("60.0,30.0");
151
+ expect(value("ratio")).toBe("300.0x400.0");
152
+ expect(value("area")).toBe("2 / 3 / 0 / 0");
153
+ expect(value("ar")).toBe("0.75");
154
+ });
155
+ it("paints focus-visible outlines and applies :active transforms", () => {
156
+ const { value, stdout } = harness.compileAndRun("outline-active", `
157
+ import { createWindow, run } from "gui";
158
+
159
+ const HTML = \`
160
+ <html><head><style>
161
+ body { margin: 0; }
162
+ #btn {
163
+ position: absolute; left: 10px; top: 10px;
164
+ width: 60px; height: 30px;
165
+ background: #111;
166
+ border: 0;
167
+ outline: 2px solid #ff0000;
168
+ outline-offset: 3px;
169
+ }
170
+ #btn:focus-visible { outline-color: #00ff00; }
171
+ #btn:active { transform: translateY(5px); }
172
+ </style></head><body><button id="btn">go</button></body></html>\`;
173
+
174
+ const win = createWindow({ title: "outline", width: 200, height: 120 });
175
+ win.on("ready", () => {
176
+ const doc = win.document;
177
+ const btn: any = doc.querySelector("#btn");
178
+ btn.focus();
179
+ console.log("color=" + win.computedStyle("#btn", "outline-color"));
180
+ console.log("width=" + win.computedStyle("#btn", "outline-width"));
181
+ console.log("offset=" + win.computedStyle("#btn", "outline-offset"));
182
+ console.log(win.paintList());
183
+ win.sendEvent("mousedown", { x: 20, y: 20, button: 0 });
184
+ console.log("active=" + win.computedStyle("#btn", "transform"));
185
+ win.sendEvent("mouseup", { x: 20, y: 20, button: 0 });
186
+ console.log("released=" + win.computedStyle("#btn", "transform"));
187
+ win.close();
188
+ });
189
+ win.loadHTML(HTML);
190
+ run();
191
+ `);
192
+ expect(value("color")).toBe("rgb(0, 255, 0)");
193
+ expect(value("width")).toBe("2px");
194
+ expect(value("offset")).toBe("3px");
195
+ expect(stdout).toContain("rect x=7.0 y=7.0 w=66.0 h=2.0");
196
+ expect(value("active")).toContain("translateY(5px)");
197
+ expect(value("released")).toBe("none");
198
+ });
199
+ it("lays vertical writing mode text out in a column and rotates it", () => {
200
+ const { value, stdout } = harness.compileAndRun("vertical", `
201
+ import { createWindow, run } from "gui";
202
+
203
+ const HTML = \`
204
+ <html><head><style>
205
+ body { margin: 0; }
206
+ #v {
207
+ position: absolute; left: 200px; top: 0;
208
+ writing-mode: vertical-rl;
209
+ font-size: 10px;
210
+ }
211
+ </style></head><body><div id="v">ABCD</div></body></html>\`;
212
+
213
+ const win = createWindow({ title: "vertical", width: 400, height: 200 });
214
+ win.on("ready", () => {
215
+ const v = win.getBoundingClientRect("#v");
216
+ console.log("rect=" + v.width.toFixed(1) + "," + v.height.toFixed(1));
217
+ console.log("mode=" + win.computedStyle("#v", "writing-mode"));
218
+ console.log(win.paintList());
219
+ win.close();
220
+ });
221
+ win.loadHTML(HTML);
222
+ run();
223
+ `);
224
+ const size = value("rect").split(",");
225
+ const width = Number(size[0] ?? 0);
226
+ const height = Number(size[1] ?? 0);
227
+ expect(width).toBeLessThan(20);
228
+ expect(height).toBeGreaterThan(width);
229
+ expect(value("mode")).toBe("vertical-rl");
230
+ expect(stdout).toContain(",1,-1,");
231
+ });
232
+ it("injects document CSS into the serialized inline SVG", () => {
233
+ const { value } = harness.compileAndRun("svg-css", `
234
+ import { createWindow, run } from "gui";
235
+
236
+ const HTML = \`
237
+ <html><head><style>
238
+ body { margin: 0; }
239
+ .ring { fill: none; stroke: #ff0000; stroke-width: 2; }
240
+ .glow { fill: #00ff00; stroke: rgba(0, 0, 255, 0.5); }
241
+ </style></head><body>
242
+ <svg id="icon" viewBox="0 0 20 20">
243
+ <circle class="ring" cx="10" cy="10" r="8"></circle>
244
+ <rect class="glow" x="1" y="1" width="4" height="4"></rect>
245
+ </svg>
246
+ </body></html>\`;
247
+
248
+ const win = createWindow({ title: "svg", width: 120, height: 120 });
249
+ win.on("ready", () => {
250
+ const info: any = win.inlineSvg("#icon");
251
+ console.log("shapes=" + info.shapes);
252
+ console.log("ring=" + (info.markup.indexOf("style=\\"fill:none;stroke:#ff0000;stroke-width:2\\"") >= 0));
253
+ console.log("glow=" + (info.markup.indexOf("fill:#00ff00") >= 0));
254
+ console.log("opacity=" + (info.markup.indexOf("stroke-opacity:0.500") >= 0));
255
+ win.close();
256
+ });
257
+ win.loadHTML(HTML);
258
+ run();
259
+ `);
260
+ expect(value("shapes")).toBe("2");
261
+ expect(value("ring")).toBe("true");
262
+ expect(value("glow")).toBe("true");
263
+ expect(value("opacity")).toBe("true");
264
+ });
265
+ it("tiles an image background at background-size", () => {
266
+ const image = harness.imageSrc(harness.logoPath);
267
+ const { stdout } = harness.compileAndRun("background-size", `
268
+ import { createWindow, run } from "gui";
269
+
270
+ const HTML = \`
271
+ <html><head><style>
272
+ body { margin: 0; }
273
+ #bg { width: 250px; height: 120px; background-image: url("${image}"); background-size: 100px 100px; }
274
+ </style></head><body><div id="bg"></div></body></html>\`;
275
+
276
+ const win = createWindow({ title: "tiles", width: 500, height: 300 });
277
+ win.on("ready", () => {
278
+ console.log(win.paintList());
279
+ win.close();
280
+ });
281
+ win.loadHTML(HTML);
282
+ run();
283
+ `);
284
+ const tiles = stdout.split("\n").filter((line) => line.includes("w=100.0 h=100.0"));
285
+ expect(tiles.length).toBe(6);
286
+ expect(stdout).toContain("image x=0.0 y=0.0 w=100.0 h=100.0");
287
+ });
288
+ it("distributes auto margins, inherits fonts and copies clip-path", () => {
289
+ const { value } = harness.compileAndRun("auto-margins", `
290
+ import { createWindow, run } from "gui";
291
+
292
+ const HTML = \`
293
+ <html><head><style>
294
+ body { margin: 0; font-size: 30px; }
295
+ button { font: inherit; }
296
+ #center { width: 100px; height: 10px; margin: 0 auto; background: #666; }
297
+ #flex { display: flex; width: 300px; height: 10px; }
298
+ #hint { width: 20px; height: 10px; margin-left: auto; background: #777; }
299
+ #outer {
300
+ width: 100px; height: 100px;
301
+ clip-path: polygon(0 0, 100% 0, 100% 100%, 0 100%);
302
+ }
303
+ #outer::before { content: ""; clip-path: inherit; }
304
+ </style></head><body>
305
+ <div id="center"></div>
306
+ <div id="flex"><div id="hint"></div></div>
307
+ <div id="outer"></div>
308
+ <button id="b">x</button>
309
+ </body></html>\`;
310
+
311
+ const win = createWindow({ title: "margins", width: 400, height: 300 });
312
+ win.on("ready", () => {
313
+ const center = win.getBoundingClientRect("#center");
314
+ const hint = win.getBoundingClientRect("#hint");
315
+ console.log("center=" + center.x.toFixed(1));
316
+ console.log("hint=" + hint.x.toFixed(1));
317
+ console.log("font=" + win.computedStyle("#b", "font-size"));
318
+ const outer: any = win.document.querySelector("#outer");
319
+ const inherited: any = getComputedStyle(outer, "::before").getPropertyValue("clip-path");
320
+ const own: any = getComputedStyle(outer).getPropertyValue("clip-path");
321
+ console.log("clip=" + (inherited === own) + ":" + own);
322
+ win.close();
323
+ });
324
+ win.loadHTML(HTML);
325
+ run();
326
+ `);
327
+ expect(value("center")).toBe("150.0");
328
+ expect(value("hint")).toBe("280.0");
329
+ expect(value("font")).toBe("30px");
330
+ expect(value("clip")).toContain("true:polygon(");
331
+ });
332
+ });
333
+ //# sourceMappingURL=gui-css-coverage.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gui-css-coverage.test.js","sourceRoot":"","sources":["../../../tests/e2e/gui-css-coverage.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ /**
2
+ * End-to-end tests for the CSS features that need more than a value parser:
3
+ * `calc()`, `box-shadow`, Gaussian `text-shadow`, `backdrop-filter`, CSS
4
+ * transitions (arbitrary properties + cubic-bezier/steps) and `@keyframes`.
5
+ */
6
+ export {};