@kurot/cli 1.2.0 → 2.0.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 +47 -0
- package/README.md +115 -303
- package/dist/core/components/discover-components.d.ts.map +1 -1
- package/dist/core/components/discover-components.js +12 -11
- package/dist/core/components/discover-components.js.map +1 -1
- package/dist/core/config.d.ts +8 -16
- package/dist/core/config.d.ts.map +1 -1
- package/dist/core/config.js +12 -4
- package/dist/core/config.js.map +1 -1
- package/dist/core/dev-server.d.ts +1 -1
- package/dist/core/dev-server.js +13 -13
- package/dist/core/dev-server.js.map +1 -1
- package/dist/core/diagnostics/codes.d.ts +3 -6
- package/dist/core/diagnostics/codes.d.ts.map +1 -1
- package/dist/core/diagnostics/codes.js +4 -10
- package/dist/core/diagnostics/codes.js.map +1 -1
- package/dist/core/diagnostics/output.d.ts +1 -1
- package/dist/core/diagnostics/output.d.ts.map +1 -1
- package/dist/core/{exml → kui}/ast.d.ts +17 -107
- package/dist/core/kui/ast.d.ts.map +1 -0
- package/dist/core/kui/ast.js +8 -0
- package/dist/core/{exml → kui}/ast.js.map +1 -1
- package/dist/core/kui/codegen.d.ts.map +1 -0
- package/dist/core/{exml → kui}/codegen.js +17 -176
- package/dist/core/kui/codegen.js.map +1 -0
- package/dist/core/kui/index.d.ts +29 -0
- package/dist/core/kui/index.d.ts.map +1 -0
- package/dist/core/kui/index.js +23 -0
- package/dist/core/kui/index.js.map +1 -0
- package/dist/core/{exml/exml-diagnostics.d.ts → kui/kui-diagnostics.d.ts} +2 -2
- package/dist/core/kui/kui-diagnostics.d.ts.map +1 -0
- package/dist/core/{exml/exml-diagnostics.js → kui/kui-diagnostics.js} +4 -4
- package/dist/core/kui/kui-diagnostics.js.map +1 -0
- package/dist/core/kui/kui-parser.d.ts +7 -0
- package/dist/core/kui/kui-parser.d.ts.map +1 -0
- package/dist/core/kui/kui-parser.js +157 -0
- package/dist/core/kui/kui-parser.js.map +1 -0
- package/dist/core/{exml → kui}/registry.d.ts +3 -26
- package/dist/core/kui/registry.d.ts.map +1 -0
- package/dist/core/{exml → kui}/registry.js +12 -43
- package/dist/core/kui/registry.js.map +1 -0
- package/dist/core/{exml → kui}/skin-module-builder.d.ts +6 -6
- package/dist/core/kui/skin-module-builder.d.ts.map +1 -0
- package/dist/core/{exml → kui}/skin-module-builder.js +7 -6
- package/dist/core/kui/skin-module-builder.js.map +1 -0
- package/dist/core/{exml → kui}/skin-parts-declaration.d.ts +1 -1
- package/dist/core/kui/skin-parts-declaration.d.ts.map +1 -0
- package/dist/core/kui/skin-parts-declaration.js +182 -0
- package/dist/core/kui/skin-parts-declaration.js.map +1 -0
- package/dist/core/kui/source-location.d.ts.map +1 -0
- package/dist/core/kui/source-location.js.map +1 -0
- package/dist/core/namespace-external-plugin.d.ts +1 -1
- package/dist/core/namespace-external-plugin.js +1 -1
- package/dist/core/plugins/compile-custom-namespaces.d.ts +3 -3
- package/dist/core/plugins/compile-custom-namespaces.js +3 -3
- package/dist/core/plugins/compile-kui.d.ts +6 -0
- package/dist/core/plugins/compile-kui.d.ts.map +1 -0
- package/dist/core/plugins/compile-kui.js +143 -0
- package/dist/core/plugins/compile-kui.js.map +1 -0
- package/dist/core/plugins/copy-assets.d.ts +3 -3
- package/dist/core/plugins/copy-assets.d.ts.map +1 -1
- package/dist/core/plugins/copy-assets.js +7 -6
- package/dist/core/plugins/copy-assets.js.map +1 -1
- package/dist/core/plugins/index.d.ts +1 -1
- package/dist/core/plugins/index.d.ts.map +1 -1
- package/dist/core/plugins/index.js +3 -3
- package/dist/core/plugins/index.js.map +1 -1
- package/dist/core/project.d.ts +14 -10
- package/dist/core/project.d.ts.map +1 -1
- package/dist/core/project.js +11 -7
- package/dist/core/project.js.map +1 -1
- package/dist/core/template.js +1 -1
- package/dist/core/template.js.map +1 -1
- package/dist/define.d.ts +1 -1
- package/dist/define.d.ts.map +1 -1
- package/package.json +5 -3
- package/templates/game/kurot.config.ts +3 -3
- package/templates/game/resource/ui/skins/ButtonSkin.kui.xml +24 -0
- package/templates/game/resource/ui/skins/CheckBoxSkin.kui.xml +45 -0
- package/templates/game/resource/ui/skins/ComboBoxSkin.kui.xml +32 -0
- package/templates/game/resource/ui/skins/GroupSkin.kui.xml +11 -0
- package/templates/game/resource/ui/skins/HScrollBarSkin.kui.xml +11 -0
- package/templates/game/resource/ui/skins/HSliderSkin.kui.xml +13 -0
- package/templates/game/resource/ui/skins/ImageSkin.kui.xml +11 -0
- package/templates/game/resource/ui/skins/ItemRendererSkin.kui.xml +22 -0
- package/templates/game/resource/ui/skins/LabelSkin.kui.xml +11 -0
- package/templates/game/resource/ui/skins/ListSkin.kui.xml +15 -0
- package/templates/game/resource/ui/skins/PanelSkin.kui.xml +18 -0
- package/templates/game/resource/ui/skins/ProgressBarSkin.kui.xml +14 -0
- package/templates/game/resource/ui/skins/RadioButtonSkin.kui.xml +45 -0
- package/templates/game/resource/ui/skins/ScrollerSkin.kui.xml +13 -0
- package/templates/game/resource/ui/skins/TabBarSkin.kui.xml +12 -0
- package/templates/game/resource/ui/skins/TextInputSkin.kui.xml +28 -0
- package/templates/game/resource/ui/skins/ToggleButtonSkin.kui.xml +34 -0
- package/templates/game/resource/ui/skins/ToggleSwitchSkin.kui.xml +29 -0
- package/templates/game/resource/ui/skins/VScrollBarSkin.kui.xml +11 -0
- package/templates/game/resource/ui/skins/VSliderSkin.kui.xml +13 -0
- package/templates/game/resource/ui/skins/ViewStackSkin.kui.xml +11 -0
- package/dist/core/exml/ast.d.ts.map +0 -1
- package/dist/core/exml/ast.js +0 -8
- package/dist/core/exml/codegen.d.ts.map +0 -1
- package/dist/core/exml/codegen.js.map +0 -1
- package/dist/core/exml/exml-diagnostics.d.ts.map +0 -1
- package/dist/core/exml/exml-diagnostics.js.map +0 -1
- package/dist/core/exml/exml-parser.d.ts +0 -27
- package/dist/core/exml/exml-parser.d.ts.map +0 -1
- package/dist/core/exml/exml-parser.js +0 -380
- package/dist/core/exml/exml-parser.js.map +0 -1
- package/dist/core/exml/index.d.ts +0 -54
- package/dist/core/exml/index.d.ts.map +0 -1
- package/dist/core/exml/index.js +0 -51
- package/dist/core/exml/index.js.map +0 -1
- package/dist/core/exml/registry.d.ts.map +0 -1
- package/dist/core/exml/registry.js.map +0 -1
- package/dist/core/exml/skin-module-builder.d.ts.map +0 -1
- package/dist/core/exml/skin-module-builder.js.map +0 -1
- package/dist/core/exml/skin-parts-declaration.d.ts.map +0 -1
- package/dist/core/exml/skin-parts-declaration.js +0 -82
- package/dist/core/exml/skin-parts-declaration.js.map +0 -1
- package/dist/core/exml/source-location.d.ts.map +0 -1
- package/dist/core/exml/source-location.js.map +0 -1
- package/dist/core/exml/xml-parser.d.ts +0 -86
- package/dist/core/exml/xml-parser.d.ts.map +0 -1
- package/dist/core/exml/xml-parser.js +0 -196
- package/dist/core/exml/xml-parser.js.map +0 -1
- package/dist/core/plugins/compile-exml.d.ts +0 -14
- package/dist/core/plugins/compile-exml.d.ts.map +0 -1
- package/dist/core/plugins/compile-exml.js +0 -256
- package/dist/core/plugins/compile-exml.js.map +0 -1
- package/templates/game/resource/default.thm.json +0 -19
- package/templates/game/resource/skins/eui/ButtonSkin.exml +0 -16
- package/templates/game/resource/skins/eui/CheckBoxSkin.exml +0 -18
- package/templates/game/resource/skins/eui/ComboBoxSkin.exml +0 -31
- package/templates/game/resource/skins/eui/GroupSkin.exml +0 -4
- package/templates/game/resource/skins/eui/HScrollBarSkin.exml +0 -6
- package/templates/game/resource/skins/eui/HSliderSkin.exml +0 -7
- package/templates/game/resource/skins/eui/ImageSkin.exml +0 -4
- package/templates/game/resource/skins/eui/ItemRendererSkin.exml +0 -15
- package/templates/game/resource/skins/eui/LabelSkin.exml +0 -7
- package/templates/game/resource/skins/eui/ListSkin.exml +0 -11
- package/templates/game/resource/skins/eui/PanelSkin.exml +0 -15
- package/templates/game/resource/skins/eui/ProgressBarSkin.exml +0 -11
- package/templates/game/resource/skins/eui/RadioButtonSkin.exml +0 -18
- package/templates/game/resource/skins/eui/ScrollerSkin.exml +0 -8
- package/templates/game/resource/skins/eui/TabBarSkin.exml +0 -6
- package/templates/game/resource/skins/eui/TextInputSkin.exml +0 -22
- package/templates/game/resource/skins/eui/ToggleButtonSkin.exml +0 -21
- package/templates/game/resource/skins/eui/ToggleSwitchSkin.exml +0 -15
- package/templates/game/resource/skins/eui/VScrollBarSkin.exml +0 -6
- package/templates/game/resource/skins/eui/VSliderSkin.exml +0 -7
- package/templates/game/resource/skins/eui/ViewStackSkin.exml +0 -4
- /package/dist/core/{exml → kui}/codegen.d.ts +0 -0
- /package/dist/core/{exml → kui}/source-location.d.ts +0 -0
- /package/dist/core/{exml → kui}/source-location.js +0 -0
package/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,53 @@ and this project follows [Semantic Versioning](https://semver.org/spec/v2.0.0.ht
|
|
|
7
7
|
|
|
8
8
|
## Unreleased
|
|
9
9
|
|
|
10
|
+
## 2.0.0 — 2026-09-21
|
|
11
|
+
|
|
12
|
+
This release is scoped to the Kurot Editor toolchain. Existing EXML game
|
|
13
|
+
projects remain supported by the 1.3.x line and are not expected to upgrade or
|
|
14
|
+
change their project configuration.
|
|
15
|
+
|
|
16
|
+
### Added
|
|
17
|
+
|
|
18
|
+
- Canonical KUI XML Skin compilation through `@kurot/ui-document`.
|
|
19
|
+
- Generated default theme mappings derived from Skin `target` and `default`
|
|
20
|
+
metadata, including duplicate-default diagnostics.
|
|
21
|
+
- KUI XML project templates for all 21 built-in UI skins.
|
|
22
|
+
|
|
23
|
+
### Changed
|
|
24
|
+
|
|
25
|
+
- Replaced the `exml` project configuration with `ui.sourceDir`,
|
|
26
|
+
`ui.namespaces`, and `ui.components`.
|
|
27
|
+
- Simplified SkinIR to the runtime operations produced by semantic KUI
|
|
28
|
+
documents and removed syntax-specific compatibility branches.
|
|
29
|
+
- The theme JSON is generated at the fixed `resource/default.thm.json` output
|
|
30
|
+
path rather than configured or supplied as an authored input.
|
|
31
|
+
|
|
32
|
+
### Removed
|
|
33
|
+
|
|
34
|
+
- EXML parsing, theme-input discovery, `.exml` templates, and compatibility
|
|
35
|
+
diagnostics.
|
|
36
|
+
|
|
37
|
+
## 1.3.0 — 2026-09-20
|
|
38
|
+
|
|
39
|
+
### Added
|
|
40
|
+
|
|
41
|
+
- Generated declarations now narrow each exported project class's public
|
|
42
|
+
`skinParts` accessor from an explicit string-literal `skinName`, a configured
|
|
43
|
+
reusable-component pair, or a unique `<ClassName>Skin` naming match.
|
|
44
|
+
- Added ambiguity protection: convention inference is omitted when multiple
|
|
45
|
+
compiled skins share the same short `<ClassName>Skin` name.
|
|
46
|
+
|
|
47
|
+
### Changed
|
|
48
|
+
|
|
49
|
+
- Project classes no longer need to repeat their skin as a base-class generic
|
|
50
|
+
when the CLI can establish an unambiguous host-to-skin relationship.
|
|
51
|
+
|
|
52
|
+
### Tests
|
|
53
|
+
|
|
54
|
+
- Added regression coverage for explicit assignment, reusable-component,
|
|
55
|
+
unique naming-convention, and ambiguous naming-convention host inference.
|
|
56
|
+
|
|
10
57
|
## 1.2.0 — 2026-09-20
|
|
11
58
|
|
|
12
59
|
### Added
|
package/README.md
CHANGED
|
@@ -1,371 +1,183 @@
|
|
|
1
1
|
# @kurot/cli
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Build tooling for the Kurot UI Editor workflow. It uses esbuild, emits ES2022
|
|
4
|
+
ESM, and compiles canonical KUI XML skins into runtime theme modules.
|
|
4
5
|
|
|
5
|
-
> **Current release:
|
|
6
|
+
> **Current release: 2.0.0.** Node.js 20 or later is required.
|
|
6
7
|
|
|
7
|
-
>
|
|
8
|
-
>
|
|
9
|
-
>
|
|
8
|
+
> **Release scope:** 2.0.0 is currently dedicated to Kurot Editor integration.
|
|
9
|
+
> Existing game projects that use EXML, including CrashMaster, should remain on
|
|
10
|
+
> `@kurot/cli@1.3.x`. Version 2.0.0 is not an in-place project upgrade and does
|
|
11
|
+
> not require those projects to change their configuration or UI assets.
|
|
10
12
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
`@kurot/cli` does **not** require a global install.
|
|
13
|
+
See [CHANGELOG.md](CHANGELOG.md) for release history.
|
|
14
14
|
|
|
15
|
-
|
|
15
|
+
## Usage
|
|
16
16
|
|
|
17
|
-
|
|
17
|
+
The CLI does not require a global install.
|
|
18
18
|
|
|
19
19
|
```bash
|
|
20
20
|
npx @kurot/cli create my-game
|
|
21
|
-
npx @kurot/cli create my-lib --template empty
|
|
22
|
-
```
|
|
23
|
-
|
|
24
|
-
### In-project commands
|
|
25
|
-
|
|
26
|
-
Scaffolded projects include `@kurot/cli` as a devDependency and expose commands via npm scripts:
|
|
27
|
-
|
|
28
|
-
```bash
|
|
29
21
|
cd my-game
|
|
30
22
|
pnpm install
|
|
31
|
-
pnpm
|
|
32
|
-
pnpm dev # dev server
|
|
33
|
-
pnpm clean # clean output
|
|
23
|
+
pnpm dev
|
|
34
24
|
```
|
|
35
25
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
```
|
|
26
|
+
Scaffolded projects expose `build`, `dev`, and `clean` scripts. For an
|
|
27
|
+
Editor-managed KUI XML project, install the package with
|
|
28
|
+
`pnpm add -D @kurot/cli@2`. Existing EXML projects should keep their current
|
|
29
|
+
1.3.x dependency.
|
|
41
30
|
|
|
42
31
|
## Commands
|
|
43
32
|
|
|
44
33
|
### `kurot create`
|
|
45
34
|
|
|
46
|
-
Scaffold a new project from a template.
|
|
47
|
-
|
|
48
35
|
```bash
|
|
49
|
-
kurot create <name> [
|
|
36
|
+
kurot create <name> [--template game|empty]
|
|
50
37
|
```
|
|
51
38
|
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
**Templates:**
|
|
57
|
-
|
|
58
|
-
| Template | Extends | Dependencies | Description |
|
|
59
|
-
| -------- | --------- | ------------------------------------------------- | -------------------------------------------------------------------------------- |
|
|
60
|
-
| `game` | `UILayer` | `@kurot/core` + `@kurot/game` + `@kurot/ui` | Full-featured project with resource loading, scene building, and Tween animation |
|
|
61
|
-
| `empty` | `Sprite` | `@kurot/core` | Minimal project — pure Canvas rendering, no extra dependencies |
|
|
62
|
-
|
|
63
|
-
**Lifecycle:**
|
|
64
|
-
|
|
65
|
-
| Template | Entry class | Lifecycle |
|
|
66
|
-
| -------- | ---------------------- | ------------------------------------------------------------------------------------------------- |
|
|
67
|
-
| `game` | `Main extends UILayer` | `createChildren` → `runGame` → `loadResource` → `loadTheme` → `createGameScene` → `startAnimation` |
|
|
68
|
-
| `empty` | `Main extends Sprite` | constructor → `ADDED_TO_STAGE` → `onAddToStage` |
|
|
39
|
+
The `game` template includes `@kurot/core`, `@kurot/game`, `@kurot/ui`, KUI
|
|
40
|
+
skins, resource loading, and an editable HTML template. The `empty` template
|
|
41
|
+
contains a minimal `Sprite` application.
|
|
69
42
|
|
|
70
43
|
### `kurot build`
|
|
71
44
|
|
|
72
|
-
Compile the project into ESM application, engine, namespace, and theme bundles.
|
|
73
|
-
|
|
74
|
-
```bash
|
|
75
|
-
kurot build [options]
|
|
76
|
-
```
|
|
77
|
-
|
|
78
|
-
| Option | Description | Default |
|
|
79
|
-
| ------------------------ | ------------------------------------------------------ | ------- |
|
|
80
|
-
| `-r, --release` | Minified, content-hashed release build (→ bin-release) | `false` |
|
|
81
|
-
| `--sourcemap` | Generate sourcemaps | `false` |
|
|
82
|
-
| `--watch` | Rebuild source on file changes | `false` |
|
|
83
|
-
| `--analyze` | Print bundle size analysis (esbuild metafile) | `false` |
|
|
84
|
-
| `--strict` | Promote supported warnings to build errors | `false` |
|
|
85
|
-
| `--diagnostics <format>` | Diagnostic output: `human` or `json` | `human` |
|
|
86
|
-
|
|
87
|
-
`--diagnostics json` writes exactly one JSON result to stdout. It includes
|
|
88
|
-
`success`, `mode`, `durationMs`, the output directory on success, and all
|
|
89
|
-
structured diagnostics. Release builds use strict diagnostic policy by default.
|
|
90
|
-
|
|
91
45
|
```bash
|
|
92
|
-
kurot build --
|
|
46
|
+
kurot build [--release] [--sourcemap] [--watch] [--analyze]
|
|
47
|
+
[--strict] [--diagnostics human|json]
|
|
93
48
|
```
|
|
94
49
|
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
| development | `bin-debug/` — per-file `.js` mirroring `src/` (`Main.js`, `com/.../X.js`) + engine chunks in `js/` |
|
|
100
|
-
| release (`-r`) | `bin-release/web/<timestamp>/` — `js/main.min_<hash>.js` + `js/kurot.*.min_<hash>.js` + `manifest.json` |
|
|
50
|
+
Development output is written to `bin-debug/`. Release output is written to
|
|
51
|
+
`bin-release/web/<timestamp>/` with minified, content-hashed files. Engine,
|
|
52
|
+
project namespace, theme, and application code are separate ESM chunks joined
|
|
53
|
+
by the generated HTML import map.
|
|
101
54
|
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
resolve bare specifiers (`import { Sprite } from '@kurot/core'`) in the browser
|
|
105
|
-
without duplicating engine code. `resource/` (including the compiled
|
|
106
|
-
`default.thm.json`) is copied with fixed names, since user code references those
|
|
107
|
-
paths directly. The entry script bootstraps via your own `createPlayer()` call.
|
|
55
|
+
`--diagnostics json` reserves stdout for one machine-readable build result.
|
|
56
|
+
Release builds apply strict diagnostic policy by default.
|
|
108
57
|
|
|
109
58
|
### `kurot dev`
|
|
110
59
|
|
|
111
|
-
Start a development server with auto-recompilation on file changes (manual browser refresh required).
|
|
112
|
-
|
|
113
|
-
```bash
|
|
114
|
-
kurot dev [options]
|
|
115
|
-
```
|
|
116
|
-
|
|
117
|
-
| Option | Description | Default |
|
|
118
|
-
| ------------------------ | ------------------------------------------ | ------- |
|
|
119
|
-
| `-p, --port <port>` | Port to listen | `3000` |
|
|
120
|
-
| `--sourcemap` | Generate sourcemaps | `false` |
|
|
121
|
-
| `--strict` | Promote supported warnings to build errors | `false` |
|
|
122
|
-
| `--diagnostics <format>` | Diagnostic output: `human` or `jsonl` | `human` |
|
|
123
|
-
|
|
124
|
-
Unlike build's single JSON result, `kurot dev --diagnostics jsonl` writes one
|
|
125
|
-
JSON event per line so an agent can follow initial builds, diagnostics,
|
|
126
|
-
rebuilds, and server readiness incrementally.
|
|
127
|
-
|
|
128
60
|
```bash
|
|
129
|
-
kurot dev --
|
|
61
|
+
kurot dev [--port 3000] [--sourcemap] [--strict]
|
|
62
|
+
[--diagnostics human|jsonl]
|
|
130
63
|
```
|
|
131
64
|
|
|
132
|
-
|
|
133
|
-
|
|
65
|
+
The development server rebuilds TypeScript, KUI XML, custom namespaces, and
|
|
66
|
+
the component catalog as their sources change. Browser refresh is currently
|
|
67
|
+
manual. JSONL mode reserves stdout for incremental build and server events.
|
|
134
68
|
|
|
135
69
|
### `kurot clean`
|
|
136
70
|
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
```bash
|
|
140
|
-
kurot clean
|
|
141
|
-
```
|
|
71
|
+
Removes `bin-debug` and `bin-release`.
|
|
142
72
|
|
|
143
73
|
## Configuration
|
|
144
74
|
|
|
145
|
-
Create
|
|
75
|
+
Create `kurot.config.ts` in the project root:
|
|
146
76
|
|
|
147
77
|
```ts
|
|
148
78
|
export default {
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
},
|
|
169
|
-
},
|
|
79
|
+
target: 'html5',
|
|
80
|
+
entry: 'src/Main.ts',
|
|
81
|
+
output: { dir: 'bin-debug' },
|
|
82
|
+
html: { template: 'template/web/index.html' },
|
|
83
|
+
stage: {
|
|
84
|
+
width: 640,
|
|
85
|
+
height: 1136,
|
|
86
|
+
scaleMode: 'showAll',
|
|
87
|
+
orientation: 'auto',
|
|
88
|
+
frameRate: 60,
|
|
89
|
+
},
|
|
90
|
+
ui: {
|
|
91
|
+
sourceDir: 'resource/ui',
|
|
92
|
+
components: {
|
|
93
|
+
namespace: 'game',
|
|
94
|
+
sourceDir: 'src/components',
|
|
95
|
+
skinDir: 'resource/ui/components',
|
|
96
|
+
},
|
|
97
|
+
},
|
|
170
98
|
};
|
|
171
99
|
```
|
|
172
100
|
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
| ------------------- | -------- | ------------------------------------------------------------------------------------------------------------------------ |
|
|
177
|
-
| `target` | `string` | Build target — currently only `'html5'` |
|
|
178
|
-
| `entry` | `string` | Entry file path, default `'src/Main.ts'` |
|
|
179
|
-
| `output.dir` | `string` | Output directory, default `'bin-debug'` |
|
|
180
|
-
| `html.template` | `string` | Optional project-owned HTML template; the CLI default page is used when omitted |
|
|
181
|
-
| `stage.width` | `number` | Stage width |
|
|
182
|
-
| `stage.height` | `number` | Stage height |
|
|
183
|
-
| `stage.scaleMode` | `string` | Scale mode: `showAll` / `noScale` / `exactFit` / `noBorder` / `fixedHeight` / `fixedWidth` / `fixedNarrow` / `fixedWide` |
|
|
184
|
-
| `stage.orientation` | `string` | Orientation: `auto` / `portrait` / `landscape` |
|
|
185
|
-
| `stage.frameRate` | `number` | Frame rate — must be a positive integer |
|
|
186
|
-
| `exml.themeFile` | `string` | Theme JSON file path |
|
|
187
|
-
| `exml.components` | `ComponentsConfig` | Optional reusable-component convention: namespace, TypeScript source directory, and Skin directory |
|
|
188
|
-
| `exml.namespaces` | `Record<string, string>` | Optional EXML prefix → source barrel-file mapping |
|
|
189
|
-
|
|
190
|
-
## HTML Template
|
|
191
|
-
|
|
192
|
-
New projects include an editable `template/web/index.html`. The build reads
|
|
193
|
-
this file and writes the rendered page to the active output directory. Existing
|
|
194
|
-
projects that do not configure `html.template` continue to use the CLI's
|
|
195
|
-
built-in default page.
|
|
196
|
-
|
|
197
|
-
The following placeholders are required in a configured project template:
|
|
198
|
-
|
|
199
|
-
| Placeholder | Generated value |
|
|
200
|
-
| --- | --- |
|
|
201
|
-
| `{{KUROT_IMPORT_MAP}}` | Engine and custom namespace import map |
|
|
202
|
-
| `{{KUROT_STAGE_WIDTH}}` | Configured stage width |
|
|
203
|
-
| `{{KUROT_STAGE_HEIGHT}}` | Configured stage height |
|
|
204
|
-
| `{{KUROT_SCALE_MODE}}` | Configured scale mode |
|
|
205
|
-
| `{{KUROT_ORIENTATION}}` | Configured orientation |
|
|
206
|
-
| `{{KUROT_FRAME_RATE}}` | Configured frame rate |
|
|
207
|
-
| `{{KUROT_ENTRY_SCRIPT}}` | Compiled application entry script |
|
|
208
|
-
|
|
209
|
-
The template may otherwise contain any project-specific HTML, styles, loading
|
|
210
|
-
screen, platform SDK, analytics, fonts, or additional containers. A build fails
|
|
211
|
-
with a clear error when a configured template is missing a required placeholder.
|
|
212
|
-
|
|
213
|
-
## EXML Skin Compiler
|
|
214
|
-
|
|
215
|
-
The CLI includes a complete EXML skin parsing and code generation pipeline (XML → SkinIR → ESM JavaScript). `.exml` files placed in the `resource/` directory are compiled automatically during `kurot build`.
|
|
216
|
-
|
|
217
|
-
### Features
|
|
218
|
-
|
|
219
|
-
- **XML Parsing** — lightweight parser with namespace, CDATA, and comment support
|
|
220
|
-
- **AST / IR Generation** — converts to an intermediate representation (SkinIR)
|
|
221
|
-
- **Code Generation** — outputs ESM factory functions
|
|
222
|
-
- **Component Registry** — built-in `eui:*` / `egret:*` namespace mapping to `@kurot/ui` / `@kurot/core`
|
|
223
|
-
- **Reusable Components** — pairs `src/components/<Name>.ts` with `resource/skins/components/<Name>Skin.exml`, then exposes `<game:Name>` without a hand-written barrel
|
|
224
|
-
- **Custom Namespaces** — retains `exml.namespaces` for advanced manually maintained source barrels
|
|
225
|
-
- **View States** — supports `<eui:states>`, shorthand `states="up,down"`, state properties, `includeIn`, and `excludeFrom`
|
|
226
|
-
- **Skin Properties** — preserves root properties such as `minWidth`, `minHeight`, and state-specific values
|
|
227
|
-
- **Percent Layout** — auto-detects `width="100%"` and converts to `percentWidth`
|
|
228
|
-
- **Data Binding** — parses `{expression}` binding syntax and generates `Binding.bindProperty` calls
|
|
229
|
-
- **Structured Diagnostics** — stable codes, source locations, suggestions, and strict warning promotion
|
|
230
|
-
|
|
231
|
-
Unknown tags remain warnings in normal development builds and are omitted from
|
|
232
|
-
the generated visual tree. Under `--strict` (and in release builds), those
|
|
233
|
-
warnings become errors. Syntax errors, invalid theme JSON, and other genuine
|
|
234
|
-
Skin compilation failures always stop the build; the compiler never substitutes
|
|
235
|
-
an empty Skin factory.
|
|
236
|
-
|
|
237
|
-
The standard declarations `xmlns:eui="http://ns.egret.com/eui"` and
|
|
238
|
-
`xmlns:egret="http://ns.egret.com/egret"` are namespace identifiers. The CLI
|
|
239
|
-
resolves their prefixes internally and does not access those URLs over the
|
|
240
|
-
network, so the original Egret namespace pages do not need to be hosted.
|
|
241
|
-
|
|
242
|
-
### Reusable components
|
|
243
|
-
|
|
244
|
-
The game template keeps reusable component logic and white-Egret-compatible
|
|
245
|
-
skins in parallel directories:
|
|
246
|
-
|
|
247
|
-
```text
|
|
248
|
-
src/components/<path>/<Name>.ts
|
|
249
|
-
resource/skins/components/<path>/<Name>Skin.exml
|
|
250
|
-
```
|
|
101
|
+
`ui.sourceDir` contains `.kui.xml` documents. The build always generates the
|
|
102
|
+
runtime theme manifest at `resource/default.thm.json`; it is not an authored
|
|
103
|
+
input. `ui.namespaces` can map additional XML prefixes to project barrel files.
|
|
251
104
|
|
|
252
|
-
The
|
|
253
|
-
must use a standard `eui:Skin` root with a `class` attribute. The CLI validates
|
|
254
|
-
the pair, generates the shared `#ns/game` entry, adds the default Theme mapping,
|
|
255
|
-
and accepts `<game:Name />` in other skins. Components are globally unique by
|
|
256
|
-
class name within the configured namespace.
|
|
105
|
+
The HTML template must contain these placeholders:
|
|
257
106
|
|
|
258
|
-
|
|
259
|
-
|
|
107
|
+
- `{{KUROT_IMPORT_MAP}}`
|
|
108
|
+
- `{{KUROT_STAGE_WIDTH}}`
|
|
109
|
+
- `{{KUROT_STAGE_HEIGHT}}`
|
|
110
|
+
- `{{KUROT_SCALE_MODE}}`
|
|
111
|
+
- `{{KUROT_ORIENTATION}}`
|
|
112
|
+
- `{{KUROT_FRAME_RATE}}`
|
|
113
|
+
- `{{KUROT_ENTRY_SCRIPT}}`
|
|
260
114
|
|
|
261
|
-
|
|
262
|
-
augments `@kurot/ui`'s `SkinPartsMap` with the exact named parts and runtime
|
|
263
|
-
types found in each compiled skin. The generated file is included by the
|
|
264
|
-
template `tsconfig.json`, ignored by git, and never enters browser or release
|
|
265
|
-
bundles.
|
|
115
|
+
## KUI XML compilation
|
|
266
116
|
|
|
267
|
-
|
|
268
|
-
|
|
117
|
+
KUI XML is the only authored UI format. A skin declares its runtime target and
|
|
118
|
+
whether it is the default skin directly on the document root:
|
|
269
119
|
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
this.skinParts.groupField.visible = true;
|
|
282
|
-
}
|
|
283
|
-
}
|
|
120
|
+
```xml
|
|
121
|
+
<?xml version="1.0" encoding="utf-8"?>
|
|
122
|
+
<Skin xmlns="https://kurot.dev/ui/1"
|
|
123
|
+
id="skins.ButtonSkin"
|
|
124
|
+
version="2"
|
|
125
|
+
target="kui.Button"
|
|
126
|
+
default="true">
|
|
127
|
+
<Group id="root" minWidth="100" minHeight="50">
|
|
128
|
+
<Label id="labelDisplay" horizontalCenter="0" verticalCenter="0" />
|
|
129
|
+
</Group>
|
|
130
|
+
</Skin>
|
|
284
131
|
```
|
|
285
132
|
|
|
286
|
-
The
|
|
133
|
+
The pipeline is:
|
|
287
134
|
|
|
288
|
-
```
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
this.once(UIEvent.CREATION_COMPLETE, this.onCreationComplete);
|
|
135
|
+
```text
|
|
136
|
+
.kui.xml → UIDocument → SkinIR → ESM skin factory → theme bundle
|
|
292
137
|
```
|
|
293
138
|
|
|
294
|
-
|
|
295
|
-
`
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
UI 2.0 no longer copies part names onto component instances and no longer
|
|
300
|
-
supports `setSkinPart()`, `partAdded()`, or `partRemoved()`. Read parts through
|
|
301
|
-
`this.skinParts` only while the skin-ready lifecycle is active.
|
|
139
|
+
Default skin mappings are derived from `target` and `default`; the build writes
|
|
140
|
+
`default.thm.json` with the mappings and the generated `skinsJs` module path.
|
|
141
|
+
Duplicate defaults are errors. Unknown tags are warnings in normal development
|
|
142
|
+
and errors under strict or release builds.
|
|
302
143
|
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
loaded theme bundle. A component covered by the theme's `skins` mapping normally
|
|
307
|
-
does not need to assign `skinName` itself. Hand-written `Skin` subclasses may be
|
|
308
|
-
imported and assigned directly instead of using a string.
|
|
144
|
+
Successful compilation also writes `.kurot/skin-parts.d.ts`. It augments the UI
|
|
145
|
+
runtime with the exact named parts and types declared by each skin. This file is
|
|
146
|
+
editor-only, ignored by git, and never enters browser bundles.
|
|
309
147
|
|
|
310
|
-
|
|
148
|
+
## Reusable components
|
|
311
149
|
|
|
312
|
-
|
|
313
|
-
or `js/default.thm.min_<hash>.js` (release) — that registers each skin factory.
|
|
314
|
-
`default.thm.json` keeps only the component→skin mapping plus a `skinsJs`
|
|
315
|
-
pointer to that module, which the runtime `Theme` imports. No `.exml` is shipped.
|
|
150
|
+
Convention-based reusable components pair:
|
|
316
151
|
|
|
317
|
-
```
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
XML Element Tree
|
|
321
|
-
↓ parseEXML()
|
|
322
|
-
SkinIR
|
|
323
|
-
↓ generateCode({ format: 'esm' })
|
|
324
|
-
per-skin ESM factories
|
|
325
|
-
↓ esbuild bundle (+ minify in release)
|
|
326
|
-
js/default.thm[.min_<hash>].js (skins register on globalThis)
|
|
152
|
+
```text
|
|
153
|
+
src/components/<path>/<Name>.ts
|
|
154
|
+
resource/ui/components/<path>/<Name>Skin.kui.xml
|
|
327
155
|
```
|
|
328
156
|
|
|
329
|
-
|
|
157
|
+
The TypeScript module must export `<Name>`. The paired skin must target
|
|
158
|
+
`<namespace>.<Name>`. The CLI exposes the component as `<namespace>:<Name>` in
|
|
159
|
+
KUI XML, refreshes the namespace bundle, and emits development catalog data at
|
|
160
|
+
`.kurot/component-catalog.json`.
|
|
330
161
|
|
|
331
|
-
|
|
162
|
+
Use `onSkinReady()` for logic that needs skin parts and `onSkinRemoved()` for
|
|
163
|
+
cleanup before a skin replacement. Access generated parts through
|
|
164
|
+
`this.skinParts`.
|
|
332
165
|
|
|
333
|
-
|
|
166
|
+
## Generated project shape
|
|
167
|
+
|
|
168
|
+
```text
|
|
334
169
|
my-game/
|
|
335
|
-
├── .kurot/
|
|
336
|
-
|
|
337
|
-
├── .gitignore # Excludes .kurot and build/dependency output
|
|
338
|
-
├── kurot.config.ts # Project config (includes exml options)
|
|
339
|
-
├── package.json # Dependencies & scripts
|
|
340
|
-
├── tsconfig.json # TypeScript config
|
|
341
|
-
├── template/
|
|
342
|
-
│ └── web/
|
|
343
|
-
│ └── index.html # Editable output page template
|
|
170
|
+
├── .kurot/skin-parts.d.ts
|
|
171
|
+
├── kurot.config.ts
|
|
344
172
|
├── resource/
|
|
345
|
-
│ ├── default.res.json
|
|
346
|
-
│ ├──
|
|
347
|
-
│ └──
|
|
348
|
-
│ ├── components/
|
|
349
|
-
│ └──
|
|
350
|
-
|
|
351
|
-
│
|
|
352
|
-
│
|
|
353
|
-
└──
|
|
354
|
-
|
|
355
|
-
├── Main.ts # Entry: class Main extends Sprite
|
|
356
|
-
└── LoadingUI.ts # Loading progress display
|
|
357
|
-
```
|
|
358
|
-
|
|
359
|
-
## Quick Start
|
|
360
|
-
|
|
361
|
-
```bash
|
|
362
|
-
# Full-featured game project (default)
|
|
363
|
-
npx @kurot/cli create my-game
|
|
364
|
-
cd my-game && pnpm install
|
|
365
|
-
pnpm dev
|
|
366
|
-
|
|
367
|
-
# Minimal project
|
|
368
|
-
npx @kurot/cli create my-lib --template empty
|
|
369
|
-
cd my-lib && pnpm install
|
|
370
|
-
pnpm dev
|
|
173
|
+
│ ├── default.res.json
|
|
174
|
+
│ ├── assets/
|
|
175
|
+
│ └── ui/
|
|
176
|
+
│ ├── components/
|
|
177
|
+
│ └── skins/*.kui.xml
|
|
178
|
+
├── src/
|
|
179
|
+
│ ├── components/
|
|
180
|
+
│ ├── LoadingUI.ts
|
|
181
|
+
│ └── Main.ts
|
|
182
|
+
└── template/web/index.html
|
|
371
183
|
```
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"discover-components.d.ts","sourceRoot":"","sources":["../../../src/core/components/discover-components.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,mBAAmB,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AAE3E;;;GAGG;AACH,wBAAsB,kBAAkB,CACvC,IAAI,EAAE,MAAM,EACZ,UAAU,EAAE,mBAAmB,GAAG,SAAS,GACzC,OAAO,CAAC,gBAAgB,EAAE,CAAC,
|
|
1
|
+
{"version":3,"file":"discover-components.d.ts","sourceRoot":"","sources":["../../../src/core/components/discover-components.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,mBAAmB,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AAE3E;;;GAGG;AACH,wBAAsB,kBAAkB,CACvC,IAAI,EAAE,MAAM,EACZ,UAAU,EAAE,mBAAmB,GAAG,SAAS,GACzC,OAAO,CAAC,gBAAgB,EAAE,CAAC,CAsF7B;AAED;;;GAGG;AACH,wBAAsB,wBAAwB,CAAC,OAAO,EAAE;IACvD,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,mBAAmB,CAAC,EAAE,mBAAmB,CAAC;IACnD,QAAQ,CAAC,UAAU,EAAE,gBAAgB,EAAE,CAAC;CACxC,GAAG,OAAO,CAAC,IAAI,CAAC,CAGhB"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import * as fs from 'node:fs/promises';
|
|
2
2
|
import * as path from 'node:path';
|
|
3
|
+
import { parseUIDocument } from '@kurot/ui-document';
|
|
3
4
|
import { ConfigError } from '../errors.js';
|
|
4
|
-
import { localName, parseXML } from '../exml/index.js';
|
|
5
5
|
/**
|
|
6
6
|
* Discovers reusable component source/skin pairs using the configured
|
|
7
7
|
* directory convention.
|
|
@@ -11,7 +11,7 @@ export async function discoverComponents(root, convention) {
|
|
|
11
11
|
return [];
|
|
12
12
|
const [sourceFiles, skinFiles] = await Promise.all([
|
|
13
13
|
collectFiles(convention.sourceDir, file => file.endsWith('.ts') && !file.endsWith('.d.ts')),
|
|
14
|
-
collectFiles(convention.skinDir, file => file.endsWith('Skin.
|
|
14
|
+
collectFiles(convention.skinDir, file => file.endsWith('Skin.kui.xml')),
|
|
15
15
|
]);
|
|
16
16
|
const sourceByPair = new Map(sourceFiles.map(file => [sourcePairKey(convention.sourceDir, file), file]));
|
|
17
17
|
const skinByPair = new Map(skinFiles.map(file => [skinPairKey(convention.skinDir, file), file]));
|
|
@@ -29,7 +29,7 @@ export async function discoverComponents(root, convention) {
|
|
|
29
29
|
continue;
|
|
30
30
|
}
|
|
31
31
|
if (!skin) {
|
|
32
|
-
errors.push(`Component source '${relative(root, source)}' has no matching skin '${pairKey}Skin.
|
|
32
|
+
errors.push(`Component source '${relative(root, source)}' has no matching skin '${pairKey}Skin.kui.xml'.`);
|
|
33
33
|
continue;
|
|
34
34
|
}
|
|
35
35
|
const name = path.basename(source, '.ts');
|
|
@@ -54,20 +54,21 @@ export async function discoverComponents(root, convention) {
|
|
|
54
54
|
}
|
|
55
55
|
let skinClass;
|
|
56
56
|
try {
|
|
57
|
-
const
|
|
58
|
-
if (
|
|
59
|
-
errors.push(`Component skin '${relative(root, skin)}' must
|
|
57
|
+
const skinDocument = parseUIDocument(await fs.readFile(skin, 'utf-8'));
|
|
58
|
+
if (skinDocument.assetKind !== 'appearance') {
|
|
59
|
+
errors.push(`Component skin '${relative(root, skin)}' must be a KUI Skin document.`);
|
|
60
60
|
continue;
|
|
61
61
|
}
|
|
62
|
-
|
|
63
|
-
if (
|
|
64
|
-
errors.push(`Component skin '${relative(root, skin)}' must
|
|
62
|
+
const targetType = `${convention.prefix}.${name}`;
|
|
63
|
+
if (skinDocument.contract.targetType !== targetType) {
|
|
64
|
+
errors.push(`Component skin '${relative(root, skin)}' must target '${targetType}'.`);
|
|
65
65
|
continue;
|
|
66
66
|
}
|
|
67
|
+
skinClass = skinDocument.id;
|
|
67
68
|
}
|
|
68
69
|
catch (error) {
|
|
69
70
|
const message = error instanceof Error ? error.message : String(error);
|
|
70
|
-
errors.push(`Component skin '${relative(root, skin)}' is invalid
|
|
71
|
+
errors.push(`Component skin '${relative(root, skin)}' is invalid KUI XML: ${message}`);
|
|
71
72
|
continue;
|
|
72
73
|
}
|
|
73
74
|
components.push({
|
|
@@ -124,7 +125,7 @@ function sourcePairKey(sourceDir, file) {
|
|
|
124
125
|
return toPosix(path.relative(sourceDir, file).slice(0, -'.ts'.length));
|
|
125
126
|
}
|
|
126
127
|
function skinPairKey(skinDir, file) {
|
|
127
|
-
return toPosix(path.relative(skinDir, file).slice(0, -'Skin.
|
|
128
|
+
return toPosix(path.relative(skinDir, file).slice(0, -'Skin.kui.xml'.length));
|
|
128
129
|
}
|
|
129
130
|
function hasNamedClassExport(source, name) {
|
|
130
131
|
source = stripComments(source);
|