@gtkx/cli 1.0.0-rc.1 → 1.0.0-rc.3
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/dist/builder.d.ts +3 -2
- package/dist/builder.d.ts.map +1 -1
- package/dist/builder.js +2 -1
- package/dist/builder.js.map +1 -1
- package/dist/cli.d.ts +1 -1
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +21 -6
- package/dist/cli.js.map +1 -1
- package/dist/codegen/freshness.d.ts +5 -5
- package/dist/codegen/freshness.d.ts.map +1 -1
- package/dist/codegen/freshness.js +26 -23
- package/dist/codegen/freshness.js.map +1 -1
- package/dist/codegen/report.d.ts +2 -1
- package/dist/codegen/report.d.ts.map +1 -1
- package/dist/codegen/report.js +4 -2
- package/dist/codegen/report.js.map +1 -1
- package/dist/codegen/run-codegen.d.ts +10 -10
- package/dist/codegen/run-codegen.d.ts.map +1 -1
- package/dist/codegen/run-codegen.js +72 -47
- package/dist/codegen/run-codegen.js.map +1 -1
- package/dist/codegen/store-resolver.d.ts +9 -6
- package/dist/codegen/store-resolver.d.ts.map +1 -1
- package/dist/codegen/store-resolver.js +24 -7
- package/dist/codegen/store-resolver.js.map +1 -1
- package/dist/commands/build.d.ts +4 -3
- package/dist/commands/build.d.ts.map +1 -1
- package/dist/commands/build.js +2 -1
- package/dist/commands/build.js.map +1 -1
- package/dist/commands/codegen.d.ts +2 -1
- package/dist/commands/codegen.d.ts.map +1 -1
- package/dist/commands/codegen.js +6 -4
- package/dist/commands/codegen.js.map +1 -1
- package/dist/commands/dev.d.ts +2 -1
- package/dist/commands/dev.d.ts.map +1 -1
- package/dist/commands/dev.js +2 -1
- package/dist/commands/dev.js.map +1 -1
- package/dist/commands/docs.d.ts +2 -1
- package/dist/commands/docs.d.ts.map +1 -1
- package/dist/commands/docs.js +25 -7
- package/dist/commands/docs.js.map +1 -1
- package/dist/dev/icon-dir.d.ts +2 -1
- package/dist/dev/icon-dir.d.ts.map +1 -1
- package/dist/dev/icon-dir.js +6 -3
- package/dist/dev/icon-dir.js.map +1 -1
- package/dist/dev/refresh-tracker.d.ts +5 -4
- package/dist/dev/refresh-tracker.d.ts.map +1 -1
- package/dist/dev/refresh-tracker.js +6 -5
- package/dist/dev/refresh-tracker.js.map +1 -1
- package/dist/dev/runner-deps.d.ts +2 -1
- package/dist/dev/runner-deps.d.ts.map +1 -1
- package/dist/dev/runner-deps.js +20 -4
- package/dist/dev/runner-deps.js.map +1 -1
- package/dist/dev/runner-main.d.ts +2 -1
- package/dist/dev/runner-main.d.ts.map +1 -1
- package/dist/dev/runner-main.js +3 -2
- package/dist/dev/runner-main.js.map +1 -1
- package/dist/dev/runner.d.ts +6 -5
- package/dist/dev/runner.d.ts.map +1 -1
- package/dist/dev/runner.js +69 -38
- package/dist/dev/runner.js.map +1 -1
- package/dist/dev/schema-dir.d.ts +2 -1
- package/dist/dev/schema-dir.d.ts.map +1 -1
- package/dist/dev/schema-dir.js +4 -2
- package/dist/dev/schema-dir.js.map +1 -1
- package/dist/dev/supervisor.d.ts +7 -6
- package/dist/dev/supervisor.d.ts.map +1 -1
- package/dist/dev/supervisor.js +107 -67
- package/dist/dev/supervisor.js.map +1 -1
- package/dist/dev/vite-dev-server.d.ts +3 -3
- package/dist/dev/vite-dev-server.d.ts.map +1 -1
- package/dist/dev/vite-dev-server.js +2 -1
- package/dist/dev/vite-dev-server.js.map +1 -1
- package/dist/internal/banner.d.ts +2 -1
- package/dist/internal/banner.d.ts.map +1 -1
- package/dist/internal/banner.js +2 -1
- package/dist/internal/banner.js.map +1 -1
- package/dist/internal/data-dir.d.ts +3 -2
- package/dist/internal/data-dir.d.ts.map +1 -1
- package/dist/internal/data-dir.js +29 -14
- package/dist/internal/data-dir.js.map +1 -1
- package/dist/internal/entry-arg.d.ts +5 -4
- package/dist/internal/entry-arg.d.ts.map +1 -1
- package/dist/internal/entry-arg.js +10 -7
- package/dist/internal/entry-arg.js.map +1 -1
- package/dist/internal/errors.d.ts +3 -2
- package/dist/internal/errors.d.ts.map +1 -1
- package/dist/internal/errors.js +7 -5
- package/dist/internal/errors.js.map +1 -1
- package/dist/internal/list-files.d.ts +3 -2
- package/dist/internal/list-files.d.ts.map +1 -1
- package/dist/internal/list-files.js +5 -3
- package/dist/internal/list-files.js.map +1 -1
- package/dist/internal/resolve-cli-tool.d.ts +2 -1
- package/dist/internal/resolve-cli-tool.d.ts.map +1 -1
- package/dist/internal/resolve-cli-tool.js +17 -10
- package/dist/internal/resolve-cli-tool.js.map +1 -1
- package/dist/internal/staging-dir.d.ts +3 -2
- package/dist/internal/staging-dir.d.ts.map +1 -1
- package/dist/internal/staging-dir.js +3 -2
- package/dist/internal/staging-dir.js.map +1 -1
- package/dist/internal/xdg-data-dirs.d.ts +2 -1
- package/dist/internal/xdg-data-dirs.d.ts.map +1 -1
- package/dist/internal/xdg-data-dirs.js +4 -2
- package/dist/internal/xdg-data-dirs.js.map +1 -1
- package/dist/mcp/client.d.ts +9 -4
- package/dist/mcp/client.d.ts.map +1 -1
- package/dist/mcp/client.js +106 -81
- package/dist/mcp/client.js.map +1 -1
- package/dist/mcp/handlers.d.ts +3 -2
- package/dist/mcp/handlers.d.ts.map +1 -1
- package/dist/mcp/handlers.js +89 -61
- package/dist/mcp/handlers.js.map +1 -1
- package/dist/mcp/index.d.ts +2 -2
- package/dist/mcp/index.d.ts.map +1 -1
- package/dist/mcp/index.js +30 -13
- package/dist/mcp/index.js.map +1 -1
- package/dist/mcp/serialize-widget.d.ts +3 -3
- package/dist/mcp/serialize-widget.d.ts.map +1 -1
- package/dist/mcp/serialize-widget.js +9 -6
- package/dist/mcp/serialize-widget.js.map +1 -1
- package/dist/mcp/testing-loader.d.ts +3 -4
- package/dist/mcp/testing-loader.d.ts.map +1 -1
- package/dist/mcp/testing-loader.js +43 -21
- package/dist/mcp/testing-loader.js.map +1 -1
- package/dist/mcp/widget-registry.d.ts +3 -2
- package/dist/mcp/widget-registry.d.ts.map +1 -1
- package/dist/mcp/widget-registry.js +4 -3
- package/dist/mcp/widget-registry.js.map +1 -1
- package/dist/refresh-globals.d.ts +2 -0
- package/dist/refresh-globals.d.ts.map +1 -0
- package/dist/refresh-globals.js +8 -0
- package/dist/refresh-globals.js.map +1 -0
- package/dist/refresh-runtime.d.ts +5 -11
- package/dist/refresh-runtime.d.ts.map +1 -1
- package/dist/refresh-runtime.js +16 -14
- package/dist/refresh-runtime.js.map +1 -1
- package/dist/settings/compile.d.ts +2 -1
- package/dist/settings/compile.d.ts.map +1 -1
- package/dist/settings/compile.js +6 -4
- package/dist/settings/compile.js.map +1 -1
- package/dist/settings/parser.d.ts +6 -5
- package/dist/settings/parser.d.ts.map +1 -1
- package/dist/settings/parser.js +26 -22
- package/dist/settings/parser.js.map +1 -1
- package/dist/settings/render.d.ts +3 -2
- package/dist/settings/render.d.ts.map +1 -1
- package/dist/settings/render.js +38 -64
- package/dist/settings/render.js.map +1 -1
- package/dist/settings/schema.d.ts +8 -8
- package/dist/settings/schema.d.ts.map +1 -1
- package/dist/settings/schema.js +61 -43
- package/dist/settings/schema.js.map +1 -1
- package/dist/vite-plugins/asset-extensions.d.ts +4 -3
- package/dist/vite-plugins/asset-extensions.d.ts.map +1 -1
- package/dist/vite-plugins/asset-extensions.js +4 -3
- package/dist/vite-plugins/asset-extensions.js.map +1 -1
- package/dist/vite-plugins/built-url.d.ts +2 -1
- package/dist/vite-plugins/built-url.d.ts.map +1 -1
- package/dist/vite-plugins/built-url.js +19 -13
- package/dist/vite-plugins/built-url.js.map +1 -1
- package/dist/vite-plugins/css.d.ts +2 -1
- package/dist/vite-plugins/css.d.ts.map +1 -1
- package/dist/vite-plugins/css.js +23 -15
- package/dist/vite-plugins/css.js.map +1 -1
- package/dist/vite-plugins/fast-refresh/refresh-filter.d.ts +5 -4
- package/dist/vite-plugins/fast-refresh/refresh-filter.d.ts.map +1 -1
- package/dist/vite-plugins/fast-refresh/refresh-filter.js +11 -7
- package/dist/vite-plugins/fast-refresh/refresh-filter.js.map +1 -1
- package/dist/vite-plugins/fast-refresh/swc-refresh.d.ts +4 -3
- package/dist/vite-plugins/fast-refresh/swc-refresh.d.ts.map +1 -1
- package/dist/vite-plugins/fast-refresh/swc-refresh.js +45 -41
- package/dist/vite-plugins/fast-refresh/swc-refresh.js.map +1 -1
- package/dist/vite-plugins/icons.d.ts +2 -1
- package/dist/vite-plugins/icons.d.ts.map +1 -1
- package/dist/vite-plugins/icons.js +24 -20
- package/dist/vite-plugins/icons.js.map +1 -1
- package/dist/vite-plugins/index.d.ts +2 -1
- package/dist/vite-plugins/index.d.ts.map +1 -1
- package/dist/vite-plugins/index.js +4 -3
- package/dist/vite-plugins/index.js.map +1 -1
- package/dist/vite-plugins/native.d.ts +2 -1
- package/dist/vite-plugins/native.d.ts.map +1 -1
- package/dist/vite-plugins/native.js +6 -4
- package/dist/vite-plugins/native.js.map +1 -1
- package/dist/vite-plugins/react-compiler.d.ts +3 -2
- package/dist/vite-plugins/react-compiler.d.ts.map +1 -1
- package/dist/vite-plugins/react-compiler.js +26 -20
- package/dist/vite-plugins/react-compiler.js.map +1 -1
- package/dist/vite-plugins/react-dom-prebundle.d.ts +2 -1
- package/dist/vite-plugins/react-dom-prebundle.d.ts.map +1 -1
- package/dist/vite-plugins/react-dom-prebundle.js +2 -1
- package/dist/vite-plugins/react-dom-prebundle.js.map +1 -1
- package/dist/vite-plugins/resource-init-module.d.ts +2 -1
- package/dist/vite-plugins/resource-init-module.d.ts.map +1 -1
- package/dist/vite-plugins/resource-init-module.js +39 -38
- package/dist/vite-plugins/resource-init-module.js.map +1 -1
- package/dist/vite-plugins/resource-shared.d.ts +7 -5
- package/dist/vite-plugins/resource-shared.d.ts.map +1 -1
- package/dist/vite-plugins/resource-shared.js +17 -10
- package/dist/vite-plugins/resource-shared.js.map +1 -1
- package/dist/vite-plugins/resources.d.ts +3 -2
- package/dist/vite-plugins/resources.d.ts.map +1 -1
- package/dist/vite-plugins/resources.js +95 -55
- package/dist/vite-plugins/resources.js.map +1 -1
- package/dist/vite-plugins/settings-worker-env.d.ts +2 -1
- package/dist/vite-plugins/settings-worker-env.d.ts.map +1 -1
- package/dist/vite-plugins/settings-worker-env.js +4 -2
- package/dist/vite-plugins/settings-worker-env.js.map +1 -1
- package/dist/vite-plugins/settings.d.ts +2 -1
- package/dist/vite-plugins/settings.d.ts.map +1 -1
- package/dist/vite-plugins/settings.js +56 -32
- package/dist/vite-plugins/settings.js.map +1 -1
- package/dist/vite-plugins/strip-query.d.ts +3 -0
- package/dist/vite-plugins/strip-query.d.ts.map +1 -0
- package/dist/vite-plugins/strip-query.js +6 -0
- package/dist/vite-plugins/strip-query.js.map +1 -0
- package/dist/vite-plugins/undeclared-library.d.ts +3 -1
- package/dist/vite-plugins/undeclared-library.d.ts.map +1 -1
- package/dist/vite-plugins/undeclared-library.js +11 -8
- package/dist/vite-plugins/undeclared-library.js.map +1 -1
- package/dist/vite-plugins/virtual-module.d.ts +2 -2
- package/dist/vite-plugins/virtual-module.d.ts.map +1 -1
- package/dist/vite-plugins/virtual-module.js +5 -3
- package/dist/vite-plugins/virtual-module.js.map +1 -1
- package/dist/vitest-plugin.d.ts.map +1 -1
- package/dist/vitest-plugin.js.map +1 -1
- package/env.d.ts +21 -61
- package/package.json +12 -14
- package/src/babel-modules.d.ts +0 -2
- package/src/builder.ts +7 -6
- package/src/cli.ts +26 -6
- package/src/codegen/freshness.ts +39 -26
- package/src/codegen/report.ts +10 -2
- package/src/codegen/run-codegen.ts +131 -66
- package/src/codegen/store-resolver.ts +52 -15
- package/src/commands/build.ts +3 -2
- package/src/commands/codegen.ts +9 -4
- package/src/commands/dev.ts +3 -4
- package/src/commands/docs.ts +47 -7
- package/src/dev/icon-dir.ts +13 -3
- package/src/dev/refresh-tracker.ts +12 -8
- package/src/dev/runner-deps.ts +30 -7
- package/src/dev/runner-main.ts +4 -3
- package/src/dev/runner.ts +100 -41
- package/src/dev/schema-dir.ts +7 -2
- package/src/dev/supervisor.ts +169 -71
- package/src/dev/vite-dev-server.ts +4 -2
- package/src/internal/banner.ts +5 -1
- package/src/internal/data-dir.ts +47 -16
- package/src/internal/entry-arg.ts +16 -8
- package/src/internal/errors.ts +15 -7
- package/src/internal/list-files.ts +10 -4
- package/src/internal/resolve-cli-tool.ts +28 -12
- package/src/internal/staging-dir.ts +5 -2
- package/src/internal/xdg-data-dirs.ts +8 -2
- package/src/mcp/client.ts +143 -85
- package/src/mcp/handlers.ts +126 -69
- package/src/mcp/index.ts +38 -14
- package/src/mcp/serialize-widget.ts +15 -8
- package/src/mcp/testing-loader.ts +64 -23
- package/src/mcp/widget-registry.ts +11 -5
- package/src/refresh-globals.ts +10 -0
- package/src/refresh-runtime.ts +20 -16
- package/src/settings/compile.ts +7 -4
- package/src/settings/parser.ts +69 -30
- package/src/settings/render.ts +66 -66
- package/src/settings/schema.ts +100 -46
- package/src/vite-plugins/asset-extensions.ts +4 -3
- package/src/vite-plugins/built-url.ts +30 -15
- package/src/vite-plugins/css.ts +35 -20
- package/src/vite-plugins/fast-refresh/refresh-filter.ts +18 -10
- package/src/vite-plugins/fast-refresh/swc-refresh.ts +60 -47
- package/src/vite-plugins/icons.ts +40 -24
- package/src/vite-plugins/index.ts +7 -4
- package/src/vite-plugins/native.ts +14 -5
- package/src/vite-plugins/react-compiler.ts +44 -30
- package/src/vite-plugins/react-dom-prebundle.ts +4 -1
- package/src/vite-plugins/resource-init-module.ts +41 -38
- package/src/vite-plugins/resource-shared.ts +27 -14
- package/src/vite-plugins/resources.ts +154 -60
- package/src/vite-plugins/settings-worker-env.ts +7 -2
- package/src/vite-plugins/settings.ts +107 -42
- package/src/vite-plugins/strip-query.ts +7 -0
- package/src/vite-plugins/undeclared-library.ts +26 -16
- package/src/vite-plugins/virtual-module.ts +9 -2
- package/src/vitest-plugin.ts +1 -2
|
@@ -3,25 +3,30 @@ import type { SerializedWidget } from "@gtkx/mcp/internal";
|
|
|
3
3
|
|
|
4
4
|
type WidgetIdResolver = (widget: Gtk.Widget) => string;
|
|
5
5
|
|
|
6
|
-
|
|
6
|
+
type WidgetFormatting = {
|
|
7
7
|
formatRole(role: Gtk.AccessibleRole): string;
|
|
8
8
|
getWidgetNodeText(widget: Gtk.Widget): string | null;
|
|
9
9
|
};
|
|
10
10
|
|
|
11
|
-
|
|
11
|
+
const serializeWidget = (
|
|
12
12
|
widget: Gtk.Widget,
|
|
13
|
-
|
|
13
|
+
resolveId: WidgetIdResolver,
|
|
14
14
|
testing: WidgetFormatting,
|
|
15
|
+
maxDepth = Infinity,
|
|
15
16
|
): SerializedWidget => {
|
|
16
17
|
const children: SerializedWidget[] = [];
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
18
|
+
|
|
19
|
+
if (maxDepth > 0) {
|
|
20
|
+
let child = widget.getFirstChild();
|
|
21
|
+
|
|
22
|
+
while (child) {
|
|
23
|
+
children.push(serializeWidget(child, resolveId, testing, maxDepth - 1));
|
|
24
|
+
child = child.getNextSibling();
|
|
25
|
+
}
|
|
21
26
|
}
|
|
22
27
|
|
|
23
28
|
return {
|
|
24
|
-
id:
|
|
29
|
+
id: resolveId(widget),
|
|
25
30
|
type: widget.constructor.name,
|
|
26
31
|
role: testing.formatRole(widget.getAccessibleRole()),
|
|
27
32
|
name: widget.getName() || null,
|
|
@@ -32,3 +37,5 @@ export const serializeWidget = (
|
|
|
32
37
|
children,
|
|
33
38
|
};
|
|
34
39
|
};
|
|
40
|
+
|
|
41
|
+
export { serializeWidget, type WidgetFormatting };
|
|
@@ -1,32 +1,73 @@
|
|
|
1
1
|
type TestingModule = typeof import("@gtkx/testing");
|
|
2
|
+
type TestingModuleLoader = () => Promise<TestingModule>;
|
|
2
3
|
|
|
3
|
-
|
|
4
|
+
type TestingModuleCache = {
|
|
5
|
+
setLoader: (next: TestingModuleLoader | null) => void;
|
|
6
|
+
load: () => Promise<TestingModule>;
|
|
7
|
+
};
|
|
8
|
+
|
|
9
|
+
type TestingModuleState = {
|
|
10
|
+
loader: TestingModuleLoader;
|
|
11
|
+
testingModule: TestingModule | null;
|
|
12
|
+
testingLoadError: Error | null;
|
|
13
|
+
};
|
|
4
14
|
|
|
5
|
-
const
|
|
15
|
+
const { setLoader: setTestingModuleLoader, load: loadTestingModule } = createTestingModuleCache();
|
|
6
16
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
17
|
+
function defaultLoader(): Promise<TestingModule> {
|
|
18
|
+
return import("@gtkx/testing");
|
|
19
|
+
}
|
|
10
20
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
}
|
|
21
|
+
function missingTestingPackageError(cause: unknown): Error {
|
|
22
|
+
return new Error(
|
|
23
|
+
"@gtkx/testing is not installed, install it to enable MCP widget interactions: " +
|
|
24
|
+
`pnpm add -D @gtkx/testing (import failed: ${String(cause)})`,
|
|
25
|
+
{ cause },
|
|
26
|
+
);
|
|
27
|
+
}
|
|
16
28
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
29
|
+
function replaceLoader(state: TestingModuleState, next: TestingModuleLoader | null): void {
|
|
30
|
+
state.loader = next ?? defaultLoader;
|
|
31
|
+
state.testingModule = null;
|
|
32
|
+
state.testingLoadError = null;
|
|
33
|
+
}
|
|
20
34
|
|
|
35
|
+
async function importTestingModule(state: TestingModuleState): Promise<TestingModule> {
|
|
21
36
|
try {
|
|
22
|
-
testingModule = await loader();
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
{ cause },
|
|
29
|
-
);
|
|
30
|
-
throw testingLoadError;
|
|
37
|
+
state.testingModule = await state.loader();
|
|
38
|
+
|
|
39
|
+
return state.testingModule;
|
|
40
|
+
} catch (error) {
|
|
41
|
+
state.testingLoadError = missingTestingPackageError(error);
|
|
42
|
+
throw state.testingLoadError;
|
|
31
43
|
}
|
|
32
|
-
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
function loadCachedTestingModule(state: TestingModuleState): Promise<TestingModule> {
|
|
47
|
+
if (state.testingModule) {
|
|
48
|
+
return Promise.resolve(state.testingModule);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
if (state.testingLoadError) {
|
|
52
|
+
return Promise.reject(state.testingLoadError);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
return importTestingModule(state);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
function createTestingModuleCache(): TestingModuleCache {
|
|
59
|
+
const state: TestingModuleState = {
|
|
60
|
+
loader: defaultLoader,
|
|
61
|
+
testingModule: null,
|
|
62
|
+
testingLoadError: null,
|
|
63
|
+
};
|
|
64
|
+
|
|
65
|
+
return {
|
|
66
|
+
setLoader: (next: TestingModuleLoader | null): void => {
|
|
67
|
+
replaceLoader(state, next);
|
|
68
|
+
},
|
|
69
|
+
load: (): Promise<TestingModule> => loadCachedTestingModule(state),
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
export { setTestingModuleLoader, loadTestingModule, type TestingModule, type TestingModuleLoader };
|
|
@@ -1,14 +1,15 @@
|
|
|
1
1
|
import * as Gtk from "@gtkx/gi/gtk";
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
private idByWidget
|
|
3
|
+
class WidgetRegistry {
|
|
4
|
+
private idByWidget: WeakMap<Gtk.Widget, string> = new WeakMap();
|
|
5
5
|
private nextId = 0;
|
|
6
|
-
private widgetById
|
|
6
|
+
private widgetById: Map<string, Gtk.Widget> = new Map();
|
|
7
7
|
private toplevelWindows: Gtk.Window[] = [];
|
|
8
8
|
|
|
9
9
|
refresh(): void {
|
|
10
10
|
this.widgetById.clear();
|
|
11
11
|
this.toplevelWindows = Gtk.Window.listToplevels() as Gtk.Window[];
|
|
12
|
+
|
|
12
13
|
for (const window of this.toplevelWindows) {
|
|
13
14
|
this.register(window);
|
|
14
15
|
}
|
|
@@ -19,21 +20,24 @@ export class WidgetRegistry {
|
|
|
19
20
|
}
|
|
20
21
|
|
|
21
22
|
register(widget: Gtk.Widget): void {
|
|
22
|
-
const id = this.
|
|
23
|
+
const id = this.getOrCreateId(widget);
|
|
23
24
|
this.widgetById.set(id, widget);
|
|
24
25
|
let child = widget.getFirstChild();
|
|
26
|
+
|
|
25
27
|
while (child) {
|
|
26
28
|
this.register(child);
|
|
27
29
|
child = child.getNextSibling();
|
|
28
30
|
}
|
|
29
31
|
}
|
|
30
32
|
|
|
31
|
-
|
|
33
|
+
getOrCreateId(widget: Gtk.Widget): string {
|
|
32
34
|
let id = this.idByWidget.get(widget);
|
|
35
|
+
|
|
33
36
|
if (!id) {
|
|
34
37
|
id = String(this.nextId++);
|
|
35
38
|
this.idByWidget.set(widget, id);
|
|
36
39
|
}
|
|
40
|
+
|
|
37
41
|
return id;
|
|
38
42
|
}
|
|
39
43
|
|
|
@@ -41,3 +45,5 @@ export class WidgetRegistry {
|
|
|
41
45
|
return this.widgetById.get(id);
|
|
42
46
|
}
|
|
43
47
|
}
|
|
48
|
+
|
|
49
|
+
export { WidgetRegistry };
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import RefreshRuntime from "react-refresh/runtime";
|
|
2
|
+
|
|
3
|
+
const identity = (type: unknown): unknown => type;
|
|
4
|
+
|
|
5
|
+
RefreshRuntime.injectIntoGlobalHook(globalThis);
|
|
6
|
+
|
|
7
|
+
Object.assign(globalThis, {
|
|
8
|
+
$RefreshReg$: (): void => undefined,
|
|
9
|
+
$RefreshSig$: () => identity,
|
|
10
|
+
});
|
package/src/refresh-runtime.ts
CHANGED
|
@@ -1,11 +1,8 @@
|
|
|
1
1
|
import RefreshRuntime from "react-refresh/runtime";
|
|
2
|
+
import "./refresh-globals.js";
|
|
2
3
|
|
|
3
4
|
type ComponentType = (...args: unknown[]) => unknown;
|
|
4
5
|
|
|
5
|
-
RefreshRuntime.injectIntoGlobalHook(globalThis);
|
|
6
|
-
globalThis.$RefreshReg$ = () => {};
|
|
7
|
-
globalThis.$RefreshSig$ = () => (type: unknown) => type;
|
|
8
|
-
|
|
9
6
|
/**
|
|
10
7
|
* Builds the per-module `$RefreshReg$` and `$RefreshSig$` hooks that React Refresh
|
|
11
8
|
* transformed code expects, scoping every registered component to the given module.
|
|
@@ -13,7 +10,7 @@ globalThis.$RefreshSig$ = () => (type: unknown) => type;
|
|
|
13
10
|
* @param moduleId Identifier used to namespace registered component types so they are unique across modules.
|
|
14
11
|
* @returns An object with `$RefreshReg$` and `$RefreshSig$` to install as module-local globals.
|
|
15
12
|
*/
|
|
16
|
-
|
|
13
|
+
function createModuleRegistration(moduleId: string): {
|
|
17
14
|
$RefreshReg$: (type: ComponentType, id: string) => void;
|
|
18
15
|
$RefreshSig$: typeof RefreshRuntime.createSignatureFunctionForTransform;
|
|
19
16
|
} {
|
|
@@ -32,21 +29,26 @@ export function createModuleRegistration(moduleId: string): {
|
|
|
32
29
|
* @param moduleExports The module's export object to inspect.
|
|
33
30
|
* @returns `true` when the module qualifies as a refresh boundary, `false` otherwise.
|
|
34
31
|
*/
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
return true;
|
|
38
|
-
}
|
|
32
|
+
const isComponentExport = (key: string, value: unknown): boolean =>
|
|
33
|
+
key === "__esModule" || RefreshRuntime.isLikelyComponentType(value);
|
|
39
34
|
|
|
35
|
+
const areAllExportsComponents = (moduleExports: Record<string, unknown>): boolean => {
|
|
40
36
|
for (const key in moduleExports) {
|
|
41
|
-
if (key
|
|
42
|
-
|
|
37
|
+
if (!isComponentExport(key, moduleExports[key])) {
|
|
38
|
+
return false;
|
|
43
39
|
}
|
|
40
|
+
}
|
|
44
41
|
|
|
45
|
-
|
|
42
|
+
return true;
|
|
43
|
+
};
|
|
46
44
|
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
45
|
+
function isRefreshBoundary(moduleExports: Record<string, unknown>): boolean {
|
|
46
|
+
if (RefreshRuntime.isLikelyComponentType(moduleExports)) {
|
|
47
|
+
return true;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
if (!areAllExportsComponents(moduleExports)) {
|
|
51
|
+
return false;
|
|
50
52
|
}
|
|
51
53
|
|
|
52
54
|
return Object.keys(moduleExports).some((k) => k !== "__esModule");
|
|
@@ -55,6 +57,8 @@ export function isRefreshBoundary(moduleExports: Record<string, unknown>): boole
|
|
|
55
57
|
/**
|
|
56
58
|
* Applies all pending React Refresh updates, re-rendering components whose modules have changed.
|
|
57
59
|
*/
|
|
58
|
-
|
|
60
|
+
function performRefresh(): void {
|
|
59
61
|
RefreshRuntime.performReactRefresh();
|
|
60
62
|
}
|
|
63
|
+
|
|
64
|
+
export { createModuleRegistration, isRefreshBoundary, performRefresh };
|
package/src/settings/compile.ts
CHANGED
|
@@ -1,19 +1,22 @@
|
|
|
1
|
-
import { execFileSync } from "node:child_process";
|
|
2
1
|
import { formatChildProcessError } from "@gtkx/utils";
|
|
2
|
+
import { execFileSync } from "node:child_process";
|
|
3
3
|
import { resolveCliTool } from "../internal/resolve-cli-tool.js";
|
|
4
4
|
|
|
5
5
|
const SCHEMA_COMPILER = "glib-compile-schemas";
|
|
6
6
|
const SCHEMA_COMPILE_TIMEOUT_MS = 30_000;
|
|
7
7
|
|
|
8
|
-
|
|
8
|
+
const compileSchemas = (dir: string): void => {
|
|
9
9
|
try {
|
|
10
10
|
execFileSync(resolveCliTool(SCHEMA_COMPILER), ["--strict", dir], {
|
|
11
11
|
stdio: ["ignore", "pipe", "pipe"],
|
|
12
12
|
timeout: SCHEMA_COMPILE_TIMEOUT_MS,
|
|
13
|
-
encoding: "
|
|
13
|
+
encoding: "utf8",
|
|
14
14
|
});
|
|
15
15
|
} catch (error) {
|
|
16
16
|
const details = formatChildProcessError(error);
|
|
17
|
-
|
|
17
|
+
const suffix = details ? `:\n${details}` : "";
|
|
18
|
+
throw new Error(`glib-compile-schemas failed for ${dir}${suffix}`, { cause: error });
|
|
18
19
|
}
|
|
19
20
|
};
|
|
21
|
+
|
|
22
|
+
export { compileSchemas };
|
package/src/settings/parser.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { XMLParser } from "fast-xml-parser";
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
type ParsedKey = {
|
|
4
4
|
name: string;
|
|
5
5
|
variantType: string | null;
|
|
6
6
|
enumId: string | null;
|
|
@@ -9,23 +9,34 @@ export type ParsedKey = {
|
|
|
9
9
|
summary: string | null;
|
|
10
10
|
};
|
|
11
11
|
|
|
12
|
-
|
|
12
|
+
type ParsedSchema = {
|
|
13
13
|
id: string;
|
|
14
14
|
path: string | null;
|
|
15
15
|
keys: ParsedKey[];
|
|
16
16
|
};
|
|
17
17
|
|
|
18
|
-
|
|
18
|
+
type ParsedSchemaFile = {
|
|
19
19
|
fileName: string;
|
|
20
20
|
schemas: ParsedSchema[];
|
|
21
21
|
enums: Map<string, string[]>;
|
|
22
22
|
flags: Map<string, string[]>;
|
|
23
23
|
};
|
|
24
24
|
|
|
25
|
-
export class SchemaParseError extends Error {}
|
|
26
|
-
|
|
27
25
|
type RawNode = Record<string, unknown>;
|
|
28
26
|
|
|
27
|
+
type RawSchema = {
|
|
28
|
+
id: string;
|
|
29
|
+
path: string | null;
|
|
30
|
+
extendsId: string | null;
|
|
31
|
+
keys: ParsedKey[];
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
type MergeContext = {
|
|
35
|
+
byId: Map<string, RawSchema>;
|
|
36
|
+
merged: Map<string, ParsedKey>;
|
|
37
|
+
visited: Set<string>;
|
|
38
|
+
};
|
|
39
|
+
|
|
29
40
|
const MULTI_TAGS: Set<string> = new Set(["schema", "key", "enum", "flags", "value", "choice"]);
|
|
30
41
|
|
|
31
42
|
const PARSER = new XMLParser({
|
|
@@ -41,17 +52,23 @@ const isRawNode = (value: unknown): value is RawNode => typeof value === "object
|
|
|
41
52
|
|
|
42
53
|
const attr = (node: RawNode, name: string): string | null => {
|
|
43
54
|
const value = node[`@_${name}`];
|
|
55
|
+
|
|
44
56
|
return typeof value === "string" ? value : null;
|
|
45
57
|
};
|
|
46
58
|
|
|
47
59
|
const text = (node: RawNode, name: string): string | null => {
|
|
48
60
|
const value = node[name];
|
|
61
|
+
|
|
49
62
|
return typeof value === "string" && value.length > 0 ? value : null;
|
|
50
63
|
};
|
|
51
64
|
|
|
52
65
|
const children = (node: RawNode, name: string): RawNode[] => {
|
|
53
66
|
const value = node[name];
|
|
54
|
-
|
|
67
|
+
|
|
68
|
+
if (!Array.isArray(value)) {
|
|
69
|
+
return [];
|
|
70
|
+
}
|
|
71
|
+
|
|
55
72
|
return value.filter(isRawNode);
|
|
56
73
|
};
|
|
57
74
|
|
|
@@ -61,17 +78,26 @@ const parseNicks = (definition: RawNode): string[] =>
|
|
|
61
78
|
.filter((nick): nick is string => nick !== null);
|
|
62
79
|
|
|
63
80
|
const parseDefinitions = (schemalist: RawNode, tag: string): Map<string, string[]> => {
|
|
64
|
-
const definitions
|
|
81
|
+
const definitions: Map<string, string[]> = new Map();
|
|
82
|
+
|
|
65
83
|
for (const definition of children(schemalist, tag)) {
|
|
66
84
|
const id = attr(definition, "id");
|
|
67
|
-
|
|
85
|
+
|
|
86
|
+
if (id !== null) {
|
|
87
|
+
definitions.set(id, parseNicks(definition));
|
|
88
|
+
}
|
|
68
89
|
}
|
|
90
|
+
|
|
69
91
|
return definitions;
|
|
70
92
|
};
|
|
71
93
|
|
|
72
94
|
const parseChoices = (key: RawNode): string[] => {
|
|
73
95
|
const choices = key.choices;
|
|
74
|
-
|
|
96
|
+
|
|
97
|
+
if (!isRawNode(choices)) {
|
|
98
|
+
return [];
|
|
99
|
+
}
|
|
100
|
+
|
|
75
101
|
return children(choices, "choice")
|
|
76
102
|
.map((choice) => attr(choice, "value"))
|
|
77
103
|
.filter((value): value is string => value !== null);
|
|
@@ -79,9 +105,11 @@ const parseChoices = (key: RawNode): string[] => {
|
|
|
79
105
|
|
|
80
106
|
const parseKey = (key: RawNode, fileName: string): ParsedKey => {
|
|
81
107
|
const name = attr(key, "name");
|
|
108
|
+
|
|
82
109
|
if (name === null) {
|
|
83
110
|
throw new SchemaParseError(`A <key> in ${fileName} has no name attribute`);
|
|
84
111
|
}
|
|
112
|
+
|
|
85
113
|
return {
|
|
86
114
|
name,
|
|
87
115
|
variantType: attr(key, "type"),
|
|
@@ -92,18 +120,13 @@ const parseKey = (key: RawNode, fileName: string): ParsedKey => {
|
|
|
92
120
|
};
|
|
93
121
|
};
|
|
94
122
|
|
|
95
|
-
type RawSchema = {
|
|
96
|
-
id: string;
|
|
97
|
-
path: string | null;
|
|
98
|
-
extendsId: string | null;
|
|
99
|
-
keys: ParsedKey[];
|
|
100
|
-
};
|
|
101
|
-
|
|
102
123
|
const parseRawSchema = (schema: RawNode, fileName: string): RawSchema => {
|
|
103
124
|
const id = attr(schema, "id");
|
|
125
|
+
|
|
104
126
|
if (id === null) {
|
|
105
127
|
throw new SchemaParseError(`A <schema> in ${fileName} has no id attribute`);
|
|
106
128
|
}
|
|
129
|
+
|
|
107
130
|
return {
|
|
108
131
|
id,
|
|
109
132
|
path: attr(schema, "path"),
|
|
@@ -112,35 +135,47 @@ const parseRawSchema = (schema: RawNode, fileName: string): RawSchema => {
|
|
|
112
135
|
};
|
|
113
136
|
};
|
|
114
137
|
|
|
138
|
+
const collectInheritedKeys = (context: MergeContext, current: RawSchema): void => {
|
|
139
|
+
if (context.visited.has(current.id)) {
|
|
140
|
+
return;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
context.visited.add(current.id);
|
|
144
|
+
const parent = current.extendsId === null ? undefined : context.byId.get(current.extendsId);
|
|
145
|
+
|
|
146
|
+
if (parent !== undefined) {
|
|
147
|
+
collectInheritedKeys(context, parent);
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
for (const key of current.keys) {
|
|
151
|
+
context.merged.set(key.name, key);
|
|
152
|
+
}
|
|
153
|
+
};
|
|
154
|
+
|
|
115
155
|
const mergeInheritedKeys = (schema: RawSchema, byId: Map<string, RawSchema>): ParsedKey[] => {
|
|
116
|
-
const
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
visited.add(current.id);
|
|
121
|
-
if (current.extendsId !== null) {
|
|
122
|
-
const parent = byId.get(current.extendsId);
|
|
123
|
-
if (parent !== undefined) collect(parent);
|
|
124
|
-
}
|
|
125
|
-
for (const key of current.keys) merged.set(key.name, key);
|
|
126
|
-
};
|
|
127
|
-
collect(schema);
|
|
128
|
-
return [...merged.values()];
|
|
156
|
+
const context: MergeContext = { byId, merged: new Map(), visited: new Set() };
|
|
157
|
+
collectInheritedKeys(context, schema);
|
|
158
|
+
|
|
159
|
+
return context.merged.values().toArray();
|
|
129
160
|
};
|
|
130
161
|
|
|
131
|
-
|
|
162
|
+
const parseSchemaXml = (xml: string, fileName: string): ParsedSchemaFile => {
|
|
132
163
|
let document: unknown;
|
|
164
|
+
|
|
133
165
|
try {
|
|
134
166
|
document = PARSER.parse(xml);
|
|
135
167
|
} catch (error) {
|
|
136
168
|
throw new SchemaParseError(`Failed to parse ${fileName} as XML: ${String(error)}`, { cause: error });
|
|
137
169
|
}
|
|
170
|
+
|
|
138
171
|
if (!isRawNode(document) || !("schemalist" in document)) {
|
|
139
172
|
throw new SchemaParseError(`${fileName} has no <schemalist> root element`);
|
|
140
173
|
}
|
|
174
|
+
|
|
141
175
|
const schemalist = isRawNode(document.schemalist) ? document.schemalist : {};
|
|
142
176
|
const rawSchemas = children(schemalist, "schema").map((schema) => parseRawSchema(schema, fileName));
|
|
143
177
|
const byId = new Map(rawSchemas.map((schema) => [schema.id, schema]));
|
|
178
|
+
|
|
144
179
|
return {
|
|
145
180
|
fileName,
|
|
146
181
|
schemas: rawSchemas.map((schema) => ({
|
|
@@ -152,3 +187,7 @@ export const parseSchemaXml = (xml: string, fileName: string): ParsedSchemaFile
|
|
|
152
187
|
flags: parseDefinitions(schemalist, "flags"),
|
|
153
188
|
};
|
|
154
189
|
};
|
|
190
|
+
|
|
191
|
+
class SchemaParseError extends Error {}
|
|
192
|
+
|
|
193
|
+
export { parseSchemaXml, SchemaParseError, type ParsedKey, type ParsedSchema, type ParsedSchemaFile };
|