@gtkx/cli 1.5.0 → 2.0.0-beta.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (211) hide show
  1. package/README.md +5 -5
  2. package/dist/cli.js +4 -0
  3. package/dist/cli.js.map +1 -1
  4. package/dist/codegen/freshness.d.ts.map +1 -1
  5. package/dist/codegen/freshness.js +45 -15
  6. package/dist/codegen/freshness.js.map +1 -1
  7. package/dist/codegen/reference.d.ts +17 -0
  8. package/dist/codegen/reference.d.ts.map +1 -0
  9. package/dist/codegen/reference.js +31 -0
  10. package/dist/codegen/reference.js.map +1 -0
  11. package/dist/codegen/report.d.ts.map +1 -1
  12. package/dist/codegen/report.js +18 -15
  13. package/dist/codegen/report.js.map +1 -1
  14. package/dist/codegen/run-codegen.d.ts +5 -5
  15. package/dist/codegen/run-codegen.d.ts.map +1 -1
  16. package/dist/codegen/run-codegen.js +24 -59
  17. package/dist/codegen/run-codegen.js.map +1 -1
  18. package/dist/codegen/store-resolver.d.ts +0 -1
  19. package/dist/codegen/store-resolver.d.ts.map +1 -1
  20. package/dist/codegen/store-resolver.js +8 -17
  21. package/dist/codegen/store-resolver.js.map +1 -1
  22. package/dist/commands/docs.d.ts.map +1 -1
  23. package/dist/commands/docs.js +6 -22
  24. package/dist/commands/docs.js.map +1 -1
  25. package/dist/commands/mcp.d.ts +13 -0
  26. package/dist/commands/mcp.d.ts.map +1 -0
  27. package/dist/commands/mcp.js +68 -0
  28. package/dist/commands/mcp.js.map +1 -0
  29. package/dist/deploy/freedesktop/copyright.d.ts.map +1 -1
  30. package/dist/deploy/freedesktop/copyright.js +2 -13
  31. package/dist/deploy/freedesktop/copyright.js.map +1 -1
  32. package/dist/deploy/freedesktop/xml.d.ts.map +1 -1
  33. package/dist/deploy/freedesktop/xml.js +21 -25
  34. package/dist/deploy/freedesktop/xml.js.map +1 -1
  35. package/dist/deploy/node-runtime/license.d.ts.map +1 -1
  36. package/dist/deploy/node-runtime/license.js +2 -9
  37. package/dist/deploy/node-runtime/license.js.map +1 -1
  38. package/dist/deploy/notices/gtkx.js +1 -1
  39. package/dist/deploy/notices/gtkx.js.map +1 -1
  40. package/dist/deploy/notices/libraries.d.ts.map +1 -1
  41. package/dist/deploy/notices/libraries.js +2 -1
  42. package/dist/deploy/notices/libraries.js.map +1 -1
  43. package/dist/deploy/notices/packages.d.ts.map +1 -1
  44. package/dist/deploy/notices/packages.js +3 -10
  45. package/dist/deploy/notices/packages.js.map +1 -1
  46. package/dist/deploy/payload/copy-tree.d.ts.map +1 -1
  47. package/dist/deploy/payload/copy-tree.js +3 -3
  48. package/dist/deploy/payload/copy-tree.js.map +1 -1
  49. package/dist/deploy/payload/stage.d.ts.map +1 -1
  50. package/dist/deploy/payload/stage.js +1 -3
  51. package/dist/deploy/payload/stage.js.map +1 -1
  52. package/dist/deploy/settings/build-manifest.d.ts.map +1 -1
  53. package/dist/deploy/settings/build-manifest.js +4 -15
  54. package/dist/deploy/settings/build-manifest.js.map +1 -1
  55. package/dist/deploy/settings/libraries.d.ts.map +1 -1
  56. package/dist/deploy/settings/libraries.js +2 -21
  57. package/dist/deploy/settings/libraries.js.map +1 -1
  58. package/dist/deploy/settings/paths.d.ts +1 -2
  59. package/dist/deploy/settings/paths.d.ts.map +1 -1
  60. package/dist/deploy/settings/paths.js +5 -15
  61. package/dist/deploy/settings/paths.js.map +1 -1
  62. package/dist/deploy/settings/screenshots.d.ts.map +1 -1
  63. package/dist/deploy/settings/screenshots.js +6 -31
  64. package/dist/deploy/settings/screenshots.js.map +1 -1
  65. package/dist/deploy/targets/flatpak-pnpm.js +4 -4
  66. package/dist/deploy/targets/flatpak-pnpm.js.map +1 -1
  67. package/dist/deploy/targets/flatpak-source.d.ts.map +1 -1
  68. package/dist/deploy/targets/flatpak-source.js +4 -4
  69. package/dist/deploy/targets/flatpak-source.js.map +1 -1
  70. package/dist/deploy/targets/flatpak-sources.js +1 -1
  71. package/dist/deploy/targets/flatpak-sources.js.map +1 -1
  72. package/dist/deploy/tools.d.ts.map +1 -1
  73. package/dist/deploy/tools.js +1 -3
  74. package/dist/deploy/tools.js.map +1 -1
  75. package/dist/dev/runner-main.js +1 -1
  76. package/dist/dev/runner-main.js.map +1 -1
  77. package/dist/dev/schema-dir.d.ts +1 -1
  78. package/dist/dev/schema-dir.d.ts.map +1 -1
  79. package/dist/dev/schema-dir.js +2 -4
  80. package/dist/dev/schema-dir.js.map +1 -1
  81. package/dist/i18n/catalogs.d.ts.map +1 -1
  82. package/dist/i18n/catalogs.js +2 -1
  83. package/dist/i18n/catalogs.js.map +1 -1
  84. package/dist/i18n/metadata-templates.d.ts.map +1 -1
  85. package/dist/i18n/metadata-templates.js +2 -1
  86. package/dist/i18n/metadata-templates.js.map +1 -1
  87. package/dist/i18n/source-messages.d.ts +3 -21
  88. package/dist/i18n/source-messages.d.ts.map +1 -1
  89. package/dist/i18n/source-messages.js +66 -85
  90. package/dist/i18n/source-messages.js.map +1 -1
  91. package/dist/i18n/types.d.ts +6 -7
  92. package/dist/i18n/types.d.ts.map +1 -1
  93. package/dist/i18n/types.js +83 -96
  94. package/dist/i18n/types.js.map +1 -1
  95. package/dist/internal/agent-rules.d.ts +7 -0
  96. package/dist/internal/agent-rules.d.ts.map +1 -0
  97. package/dist/internal/agent-rules.js +106 -0
  98. package/dist/internal/agent-rules.js.map +1 -0
  99. package/dist/internal/docs-elements.d.ts +8 -0
  100. package/dist/internal/docs-elements.d.ts.map +1 -0
  101. package/dist/internal/docs-elements.js +12 -0
  102. package/dist/internal/docs-elements.js.map +1 -0
  103. package/dist/internal/icon-path.d.ts.map +1 -1
  104. package/dist/internal/icon-path.js +5 -16
  105. package/dist/internal/icon-path.js.map +1 -1
  106. package/dist/internal/source-imports.d.ts.map +1 -1
  107. package/dist/internal/source-imports.js +10 -42
  108. package/dist/internal/source-imports.js.map +1 -1
  109. package/dist/mcp/client-config.d.ts +22 -0
  110. package/dist/mcp/client-config.d.ts.map +1 -0
  111. package/dist/mcp/client-config.js +94 -0
  112. package/dist/mcp/client-config.js.map +1 -0
  113. package/dist/settings/render.d.ts +0 -1
  114. package/dist/settings/render.d.ts.map +1 -1
  115. package/dist/settings/render.js +1 -11
  116. package/dist/settings/render.js.map +1 -1
  117. package/dist/settings/schema.d.ts +2 -2
  118. package/dist/settings/schema.d.ts.map +1 -1
  119. package/dist/settings/schema.js +21 -62
  120. package/dist/settings/schema.js.map +1 -1
  121. package/dist/vite-plugins/asset-imports.d.ts +1 -2
  122. package/dist/vite-plugins/asset-imports.d.ts.map +1 -1
  123. package/dist/vite-plugins/asset-imports.js +19 -32
  124. package/dist/vite-plugins/asset-imports.js.map +1 -1
  125. package/dist/vite-plugins/asset-specifier.d.ts +1 -3
  126. package/dist/vite-plugins/asset-specifier.d.ts.map +1 -1
  127. package/dist/vite-plugins/asset-specifier.js +1 -4
  128. package/dist/vite-plugins/asset-specifier.js.map +1 -1
  129. package/dist/vite-plugins/i18n.d.ts.map +1 -1
  130. package/dist/vite-plugins/i18n.js +2 -1
  131. package/dist/vite-plugins/i18n.js.map +1 -1
  132. package/dist/vite-plugins/index.js +2 -2
  133. package/dist/vite-plugins/index.js.map +1 -1
  134. package/dist/vite-plugins/resources.d.ts.map +1 -1
  135. package/dist/vite-plugins/resources.js +31 -96
  136. package/dist/vite-plugins/resources.js.map +1 -1
  137. package/dist/vite-plugins/settings-worker-env.d.ts.map +1 -1
  138. package/dist/vite-plugins/settings-worker-env.js +1 -3
  139. package/dist/vite-plugins/settings-worker-env.js.map +1 -1
  140. package/dist/vite-plugins/settings.d.ts +1 -2
  141. package/dist/vite-plugins/settings.d.ts.map +1 -1
  142. package/dist/vite-plugins/settings.js +8 -13
  143. package/dist/vite-plugins/settings.js.map +1 -1
  144. package/dist/vite-plugins/undeclared-library.d.ts.map +1 -1
  145. package/dist/vite-plugins/undeclared-library.js +10 -13
  146. package/dist/vite-plugins/undeclared-library.js.map +1 -1
  147. package/dist/vite-plugins/worker.d.ts.map +1 -1
  148. package/dist/vite-plugins/worker.js +0 -1
  149. package/dist/vite-plugins/worker.js.map +1 -1
  150. package/package.json +21 -14
  151. package/src/cli.ts +5 -0
  152. package/src/codegen/freshness.ts +66 -16
  153. package/src/codegen/reference.ts +52 -0
  154. package/src/codegen/report.ts +16 -17
  155. package/src/codegen/run-codegen.ts +31 -91
  156. package/src/codegen/store-resolver.ts +8 -24
  157. package/src/commands/docs.ts +6 -36
  158. package/src/commands/mcp.ts +81 -0
  159. package/src/deploy/freedesktop/copyright.ts +2 -14
  160. package/src/deploy/freedesktop/xml.ts +24 -32
  161. package/src/deploy/node-runtime/license.ts +2 -8
  162. package/src/deploy/notices/gtkx.ts +1 -1
  163. package/src/deploy/notices/libraries.ts +2 -1
  164. package/src/deploy/notices/packages.ts +3 -11
  165. package/src/deploy/payload/copy-tree.ts +3 -4
  166. package/src/deploy/payload/stage.ts +2 -6
  167. package/src/deploy/settings/build-manifest.ts +4 -16
  168. package/src/deploy/settings/libraries.ts +1 -25
  169. package/src/deploy/settings/paths.ts +6 -16
  170. package/src/deploy/settings/screenshots.ts +8 -46
  171. package/src/deploy/targets/flatpak-pnpm.ts +4 -4
  172. package/src/deploy/targets/flatpak-source.ts +4 -4
  173. package/src/deploy/targets/flatpak-sources.ts +1 -1
  174. package/src/deploy/tools.ts +1 -3
  175. package/src/dev/runner-main.ts +1 -1
  176. package/src/dev/schema-dir.ts +2 -4
  177. package/src/i18n/catalogs.ts +2 -1
  178. package/src/i18n/metadata-templates.ts +2 -1
  179. package/src/i18n/source-messages.ts +77 -115
  180. package/src/i18n/types.ts +97 -131
  181. package/src/internal/agent-rules.ts +135 -0
  182. package/src/internal/docs-elements.ts +21 -0
  183. package/src/internal/icon-path.ts +6 -19
  184. package/src/internal/source-imports.ts +14 -50
  185. package/src/mcp/client-config.ts +130 -0
  186. package/src/settings/render.ts +1 -13
  187. package/src/settings/schema.ts +19 -81
  188. package/src/vite-plugins/asset-imports.ts +20 -44
  189. package/src/vite-plugins/asset-specifier.ts +0 -5
  190. package/src/vite-plugins/i18n.ts +2 -1
  191. package/src/vite-plugins/index.ts +2 -2
  192. package/src/vite-plugins/resources.ts +36 -139
  193. package/src/vite-plugins/settings-worker-env.ts +1 -3
  194. package/src/vite-plugins/settings.ts +11 -19
  195. package/src/vite-plugins/undeclared-library.ts +14 -20
  196. package/src/vite-plugins/worker.ts +0 -1
  197. package/dist/i18n/binding-extractor.d.ts +0 -30
  198. package/dist/i18n/binding-extractor.d.ts.map +0 -1
  199. package/dist/i18n/binding-extractor.js +0 -1324
  200. package/dist/i18n/binding-extractor.js.map +0 -1
  201. package/dist/i18n/extractor-plugin.d.ts +0 -8
  202. package/dist/i18n/extractor-plugin.d.ts.map +0 -1
  203. package/dist/i18n/extractor-plugin.js +0 -247
  204. package/dist/i18n/extractor-plugin.js.map +0 -1
  205. package/dist/internal/data-dir.d.ts +0 -4
  206. package/dist/internal/data-dir.d.ts.map +0 -1
  207. package/dist/internal/data-dir.js +0 -52
  208. package/dist/internal/data-dir.js.map +0 -1
  209. package/src/i18n/binding-extractor.ts +0 -1969
  210. package/src/i18n/extractor-plugin.ts +0 -413
  211. package/src/internal/data-dir.ts +0 -70
@@ -1,108 +1,95 @@
1
- import { mkdirSync, readFileSync, writeFileSync } from "node:fs";
1
+ import { runTypesGenerator } from "i18next-cli";
2
+ import { existsSync, mkdirSync, readFileSync, rmSync, writeFileSync } from "node:fs";
2
3
  import { dirname, join } from "node:path";
4
+ const CONTEXT_SEPARATOR = "\u{4}";
5
+ const DEFAULT_NAMESPACE = "translation";
3
6
  const I18N_TYPES_FILENAME = "i18n.d.ts";
4
- const INTERPOLATION_PATTERN = /\{\{[^{}]+\}\}/u;
5
- const stringType = (values) => [...new Set(values)].map((value) => JSON.stringify(value)).join(" | ");
6
- const contextField = (context) => context === null ? "" : ` context: ${JSON.stringify(context)};`;
7
- const hasInterpolation = (values) => values.some((value) => INTERPOLATION_PATTERN.test(value));
8
- const pointVariant = (message) => {
9
- const isRequired = message.context !== null || hasInterpolation([message.msgid]);
10
- const isInterpolated = hasInterpolation([message.msgid]);
11
- return (`{${contextField(message.context)} interpolated: ${String(isInterpolated)}; kind: "point"; ` +
12
- `required: ${String(isRequired)}; value: ${JSON.stringify(message.msgid)} }`);
7
+ const I18N_RESOURCES_FILENAME = "i18n-resources.d.ts";
8
+ const generatedDir = (root) => join(root, "node_modules", ".gtkx");
9
+ const i18nResourceDir = (root) => join(generatedDir(root), "i18n");
10
+ const i18nTypesPath = (root) => join(generatedDir(root), I18N_TYPES_FILENAME);
11
+ const i18nResourcesPath = (root) => join(generatedDir(root), I18N_RESOURCES_FILENAME);
12
+ const clearI18nResources = (root) => {
13
+ rmSync(i18nResourceDir(root), { force: true, recursive: true });
13
14
  };
14
- const defaultVariant = (message) => {
15
- const values = [message.singular];
16
- const isInterpolated = hasInterpolation(values);
17
- const isRequired = message.context !== null || isInterpolated;
18
- return (`{${contextField(message.context)} defaultValue: ${JSON.stringify(message.singular)}; ` +
19
- `interpolated: ${String(isInterpolated)}; kind: "default"; required: ${String(isRequired)}; ` +
20
- `value: ${stringType(values)} }`);
21
- };
22
- const requirePlural = (message) => {
23
- if (message.plural === null) {
24
- throw new Error("Plural translation metadata requires a plural source string");
25
- }
26
- return message.plural;
27
- };
28
- const pluralVariant = (message) => {
29
- const plural = requirePlural(message);
30
- const values = [message.singular, plural];
31
- const isInterpolated = hasInterpolation(values);
32
- return (`{${contextField(message.context)} defaultValue: ${JSON.stringify(plural)}; ` +
33
- `interpolated: ${String(isInterpolated)}; kind: "plural"; required: true; ` +
34
- `value: ${stringType(values)} }`);
35
- };
36
- const pluralDefaultsVariant = (message) => {
37
- const plural = requirePlural(message);
38
- const values = [message.singular, plural];
39
- const isInterpolated = hasInterpolation(values);
40
- return (`{${contextField(message.context)} defaultValueOne: ${JSON.stringify(message.singular)}; ` +
41
- `defaultValueOther: ${JSON.stringify(plural)}; interpolated: ${String(isInterpolated)}; ` +
42
- `kind: "pluralDefaults"; required: true; value: ${stringType(values)} }`);
43
- };
44
- const variantsFor = (message) => {
45
- if (message.kind === "plural") {
46
- return [pluralVariant(message)];
47
- }
48
- if (message.kind === "pluralDefaults") {
49
- return [pluralDefaultsVariant(message)];
50
- }
51
- return message.kind === "default" ? [defaultVariant(message)] : [pointVariant(message)];
52
- };
53
- const renderRegistry = (messages) => {
54
- const entries = new Map();
55
- for (const message of messages) {
56
- const variants = entries.get(message.msgid) ?? new Set();
57
- for (const variant of variantsFor(message)) {
58
- variants.add(variant);
59
- }
60
- entries.set(message.msgid, variants);
61
- }
62
- return [...entries]
63
- .toSorted(([left], [right]) => left.localeCompare(right))
64
- .map(([msgid, variants]) => ` ${JSON.stringify(msgid)}: ${[...variants].join(" | ")};`);
65
- };
66
- const generatedHeader = () => [
67
- "/**",
68
- " * Translation declarations generated by GTKX. Regenerated by",
69
- " * `gtkx codegen`, `gtkx dev`, and `gtkx build`; do not edit.",
70
- " */",
71
- ];
72
- const renderI18nTypes = (messages, isEnabled = true) => {
73
- if (!isEnabled) {
74
- return [...generatedHeader(), "export {};", ""].join("\n");
75
- }
76
- return [
77
- ...generatedHeader(),
78
- 'import "@gtkx/i18n";',
79
- "",
80
- 'declare module "@gtkx/i18n" {',
81
- " interface TranslationRegistry {",
82
- ...renderRegistry(messages),
83
- " }",
84
- "}",
85
- "",
86
- ].join("\n");
87
- };
88
- const i18nTypesPath = (root) => join(root, "node_modules", ".gtkx", I18N_TYPES_FILENAME);
89
- const readFileOrNull = (path) => {
15
+ const i18nToolkitConfig = (root, sourceFiles, plugins = []) => ({
16
+ locales: ["en"],
17
+ plugins,
18
+ extract: {
19
+ contextSeparator: CONTEXT_SEPARATOR,
20
+ defaultNS: DEFAULT_NAMESPACE,
21
+ disablePlurals: false,
22
+ extractFromComments: false,
23
+ functions: ["t"],
24
+ generateBasePluralForms: false,
25
+ input: sourceFiles,
26
+ keySeparator: ".",
27
+ nsSeparator: false,
28
+ output: join(i18nResourceDir(root), "{{language}}", "{{namespace}}.json"),
29
+ pluralSeparator: "_",
30
+ primaryLanguage: "en",
31
+ removeUnusedKeys: true,
32
+ transComponents: ["Trans", "TransWithoutContext"],
33
+ useTranslationNames: ["useTranslation"],
34
+ warnOnConflicts: "error",
35
+ },
36
+ types: {
37
+ input: join(i18nResourceDir(root), "en", "*.json"),
38
+ output: i18nTypesPath(root),
39
+ resourcesFile: i18nResourcesPath(root),
40
+ },
41
+ });
42
+ const declarations = () => `import type Resources from "./i18n-resources.js";
43
+
44
+ declare module "@gtkx/i18n" {
45
+ interface I18nResources extends Resources {}
46
+ }
47
+ `;
48
+ const writeChanged = (path, content) => {
49
+ let current;
90
50
  try {
91
- return readFileSync(path, "utf8");
51
+ current = readFileSync(path, "utf8");
92
52
  }
93
53
  catch {
94
- return null;
54
+ current = null;
95
55
  }
96
- };
97
- const emitI18nTypes = (root, messages, isEnabled = true) => {
98
- const path = i18nTypesPath(root);
99
- const content = renderI18nTypes(messages, isEnabled);
100
- if (readFileOrNull(path) === content) {
101
- return { isWritten: false, path };
56
+ if (current === content) {
57
+ return;
102
58
  }
103
59
  mkdirSync(dirname(path), { recursive: true });
104
60
  writeFileSync(path, content);
105
- return { isWritten: true, path };
106
61
  };
107
- export { I18N_TYPES_FILENAME, emitI18nTypes, i18nTypesPath };
62
+ const typegenLogger = () => {
63
+ const errors = [];
64
+ return {
65
+ errors,
66
+ logger: {
67
+ error(value) {
68
+ errors.push(String(value));
69
+ },
70
+ info() {
71
+ return;
72
+ },
73
+ warn() {
74
+ return;
75
+ },
76
+ },
77
+ };
78
+ };
79
+ const emitI18nTypes = async (root) => {
80
+ const typesPath = i18nTypesPath(root);
81
+ const resourcesPath = i18nResourcesPath(root);
82
+ writeChanged(typesPath, declarations());
83
+ const { errors, logger } = typegenLogger();
84
+ await runTypesGenerator(i18nToolkitConfig(root, []), { logger, quiet: true });
85
+ if (errors.length > 0 || !existsSync(typesPath) || !existsSync(resourcesPath)) {
86
+ throw new Error(errors.join("\n") || "i18next type generation did not produce its outputs");
87
+ }
88
+ };
89
+ const clearI18nTypes = (root) => {
90
+ rmSync(i18nTypesPath(root), { force: true });
91
+ rmSync(i18nResourcesPath(root), { force: true });
92
+ clearI18nResources(root);
93
+ };
94
+ export { I18N_TYPES_FILENAME, clearI18nResources, clearI18nTypes, emitI18nTypes, i18nToolkitConfig, i18nTypesPath, };
108
95
  //# sourceMappingURL=types.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/i18n/types.ts"],"names":[],"mappings":"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","sourcesContent":["import { mkdirSync, readFileSync, writeFileSync } from \"node:fs\";\nimport { dirname, join } from \"node:path\";\nimport type { SourceMessage } from \"./source-messages.js\";\n\ntype I18nTypesResult = {\n isWritten: boolean;\n path: string;\n};\n\nconst I18N_TYPES_FILENAME = \"i18n.d.ts\";\nconst INTERPOLATION_PATTERN = /\\{\\{[^{}]+\\}\\}/u;\n\nconst stringType = (values: string[]): string =>\n [...new Set(values)].map((value) => JSON.stringify(value)).join(\" | \");\n\nconst contextField = (context: string | null): string =>\n context === null ? \"\" : ` context: ${JSON.stringify(context)};`;\n\nconst hasInterpolation = (values: string[]): boolean => values.some((value) => INTERPOLATION_PATTERN.test(value));\n\nconst pointVariant = (message: SourceMessage): string => {\n const isRequired = message.context !== null || hasInterpolation([message.msgid]);\n const isInterpolated = hasInterpolation([message.msgid]);\n\n return (\n `{${contextField(message.context)} interpolated: ${String(isInterpolated)}; kind: \"point\"; ` +\n `required: ${String(isRequired)}; value: ${JSON.stringify(message.msgid)} }`\n );\n};\n\nconst defaultVariant = (message: SourceMessage): string => {\n const values = [message.singular];\n const isInterpolated = hasInterpolation(values);\n const isRequired = message.context !== null || isInterpolated;\n\n return (\n `{${contextField(message.context)} defaultValue: ${JSON.stringify(message.singular)}; ` +\n `interpolated: ${String(isInterpolated)}; kind: \"default\"; required: ${String(isRequired)}; ` +\n `value: ${stringType(values)} }`\n );\n};\n\nconst requirePlural = (message: SourceMessage): string => {\n if (message.plural === null) {\n throw new Error(\"Plural translation metadata requires a plural source string\");\n }\n\n return message.plural;\n};\n\nconst pluralVariant = (message: SourceMessage): string => {\n const plural = requirePlural(message);\n const values = [message.singular, plural];\n const isInterpolated = hasInterpolation(values);\n\n return (\n `{${contextField(message.context)} defaultValue: ${JSON.stringify(plural)}; ` +\n `interpolated: ${String(isInterpolated)}; kind: \"plural\"; required: true; ` +\n `value: ${stringType(values)} }`\n );\n};\n\nconst pluralDefaultsVariant = (message: SourceMessage): string => {\n const plural = requirePlural(message);\n const values = [message.singular, plural];\n const isInterpolated = hasInterpolation(values);\n\n return (\n `{${contextField(message.context)} defaultValueOne: ${JSON.stringify(message.singular)}; ` +\n `defaultValueOther: ${JSON.stringify(plural)}; interpolated: ${String(isInterpolated)}; ` +\n `kind: \"pluralDefaults\"; required: true; value: ${stringType(values)} }`\n );\n};\n\nconst variantsFor = (message: SourceMessage): string[] => {\n if (message.kind === \"plural\") {\n return [pluralVariant(message)];\n }\n\n if (message.kind === \"pluralDefaults\") {\n return [pluralDefaultsVariant(message)];\n }\n\n return message.kind === \"default\" ? [defaultVariant(message)] : [pointVariant(message)];\n};\n\nconst renderRegistry = (messages: SourceMessage[]): string[] => {\n const entries: Map<string, Set<string>> = new Map();\n\n for (const message of messages) {\n const variants = entries.get(message.msgid) ?? new Set<string>();\n\n for (const variant of variantsFor(message)) {\n variants.add(variant);\n }\n\n entries.set(message.msgid, variants);\n }\n\n return [...entries]\n .toSorted(([left], [right]) => left.localeCompare(right))\n .map(([msgid, variants]) => ` ${JSON.stringify(msgid)}: ${[...variants].join(\" | \")};`);\n};\n\nconst generatedHeader = (): string[] => [\n \"/**\",\n \" * Translation declarations generated by GTKX. Regenerated by\",\n \" * `gtkx codegen`, `gtkx dev`, and `gtkx build`; do not edit.\",\n \" */\",\n];\n\nconst renderI18nTypes = (messages: SourceMessage[], isEnabled = true): string => {\n if (!isEnabled) {\n return [...generatedHeader(), \"export {};\", \"\"].join(\"\\n\");\n }\n\n return [\n ...generatedHeader(),\n 'import \"@gtkx/i18n\";',\n \"\",\n 'declare module \"@gtkx/i18n\" {',\n \" interface TranslationRegistry {\",\n ...renderRegistry(messages),\n \" }\",\n \"}\",\n \"\",\n ].join(\"\\n\");\n};\n\nconst i18nTypesPath = (root: string): string => join(root, \"node_modules\", \".gtkx\", I18N_TYPES_FILENAME);\n\nconst readFileOrNull = (path: string): string | null => {\n try {\n return readFileSync(path, \"utf8\");\n } catch {\n return null;\n }\n};\n\nconst emitI18nTypes = (root: string, messages: SourceMessage[], isEnabled = true): I18nTypesResult => {\n const path = i18nTypesPath(root);\n const content = renderI18nTypes(messages, isEnabled);\n\n if (readFileOrNull(path) === content) {\n return { isWritten: false, path };\n }\n\n mkdirSync(dirname(path), { recursive: true });\n writeFileSync(path, content);\n\n return { isWritten: true, path };\n};\n\nexport { I18N_TYPES_FILENAME, emitI18nTypes, i18nTypesPath };\n"]}
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/i18n/types.ts"],"names":[],"mappings":"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","sourcesContent":["import type { I18nextToolkitConfig, Logger, Plugin } from \"i18next-cli\";\nimport { runTypesGenerator } from \"i18next-cli\";\nimport { existsSync, mkdirSync, readFileSync, rmSync, writeFileSync } from \"node:fs\";\nimport { dirname, join } from \"node:path\";\n\nconst CONTEXT_SEPARATOR = \"\\u{4}\";\nconst DEFAULT_NAMESPACE = \"translation\";\nconst I18N_TYPES_FILENAME = \"i18n.d.ts\";\nconst I18N_RESOURCES_FILENAME = \"i18n-resources.d.ts\";\n\nconst generatedDir = (root: string): string => join(root, \"node_modules\", \".gtkx\");\nconst i18nResourceDir = (root: string): string => join(generatedDir(root), \"i18n\");\nconst i18nTypesPath = (root: string): string => join(generatedDir(root), I18N_TYPES_FILENAME);\nconst i18nResourcesPath = (root: string): string => join(generatedDir(root), I18N_RESOURCES_FILENAME);\n\nconst clearI18nResources = (root: string): void => {\n rmSync(i18nResourceDir(root), { force: true, recursive: true });\n};\n\nconst i18nToolkitConfig = (\n root: string,\n sourceFiles: string[],\n plugins: Plugin[] = [],\n): I18nextToolkitConfig => ({\n locales: [\"en\"],\n plugins,\n extract: {\n contextSeparator: CONTEXT_SEPARATOR,\n defaultNS: DEFAULT_NAMESPACE,\n disablePlurals: false,\n extractFromComments: false,\n functions: [\"t\"],\n generateBasePluralForms: false,\n input: sourceFiles,\n keySeparator: \".\",\n nsSeparator: false,\n output: join(i18nResourceDir(root), \"{{language}}\", \"{{namespace}}.json\"),\n pluralSeparator: \"_\",\n primaryLanguage: \"en\",\n removeUnusedKeys: true,\n transComponents: [\"Trans\", \"TransWithoutContext\"],\n useTranslationNames: [\"useTranslation\"],\n warnOnConflicts: \"error\",\n },\n types: {\n input: join(i18nResourceDir(root), \"en\", \"*.json\"),\n output: i18nTypesPath(root),\n resourcesFile: i18nResourcesPath(root),\n },\n});\n\nconst declarations = (): string => `import type Resources from \"./i18n-resources.js\";\n\ndeclare module \"@gtkx/i18n\" {\n interface I18nResources extends Resources {}\n}\n`;\n\nconst writeChanged = (path: string, content: string): void => {\n let current: string | null;\n\n try {\n current = readFileSync(path, \"utf8\");\n } catch {\n current = null;\n }\n\n if (current === content) {\n return;\n }\n\n mkdirSync(dirname(path), { recursive: true });\n writeFileSync(path, content);\n};\n\nconst typegenLogger = (): { errors: string[]; logger: Logger } => {\n const errors: string[] = [];\n\n return {\n errors,\n logger: {\n error(value) {\n errors.push(String(value));\n },\n info() {\n return;\n },\n warn() {\n return;\n },\n },\n };\n};\n\nconst emitI18nTypes = async (root: string): Promise<void> => {\n const typesPath = i18nTypesPath(root);\n const resourcesPath = i18nResourcesPath(root);\n writeChanged(typesPath, declarations());\n const { errors, logger } = typegenLogger();\n await runTypesGenerator(i18nToolkitConfig(root, []), { logger, quiet: true });\n\n if (errors.length > 0 || !existsSync(typesPath) || !existsSync(resourcesPath)) {\n throw new Error(errors.join(\"\\n\") || \"i18next type generation did not produce its outputs\");\n }\n};\n\nconst clearI18nTypes = (root: string): void => {\n rmSync(i18nTypesPath(root), { force: true });\n rmSync(i18nResourcesPath(root), { force: true });\n clearI18nResources(root);\n};\n\nexport {\n I18N_TYPES_FILENAME,\n clearI18nResources,\n clearI18nTypes,\n emitI18nTypes,\n i18nToolkitConfig,\n i18nTypesPath,\n};\n"]}
@@ -0,0 +1,7 @@
1
+ type AgentRulesResult = {
2
+ isWritten: boolean;
3
+ files: string[];
4
+ };
5
+ declare const upsertAgentRules: (root: string) => AgentRulesResult;
6
+ export { upsertAgentRules };
7
+ //# sourceMappingURL=agent-rules.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"agent-rules.d.ts","sourceRoot":"","sources":["../../src/internal/agent-rules.ts"],"names":[],"mappings":"AAIA,KAAK,gBAAgB,GAAG;IACpB,SAAS,EAAE,OAAO,CAAC;IACnB,KAAK,EAAE,MAAM,EAAE,CAAC;CACnB,CAAC;AA+GF,QAAA,MAAM,gBAAgB,GAAI,MAAM,MAAM,KAAG,gBAcxC,CAAC;AAEF,OAAO,EAAE,gBAAgB,EAAE,CAAC"}
@@ -0,0 +1,106 @@
1
+ import { readFileSync, writeFileSync } from "node:fs";
2
+ import { join } from "node:path";
3
+ import { REFERENCE_PATH } from "../codegen/reference.js";
4
+ const AGENTS_FILENAME = "AGENTS.md";
5
+ const CLAUDE_FILENAME = "CLAUDE.md";
6
+ const CLAUDE_CONTENTS = `@${AGENTS_FILENAME}\n`;
7
+ const BEGIN_MARKER = "<!-- BEGIN:gtkx-agent-rules -->";
8
+ const END_MARKER = "<!-- END:gtkx-agent-rules -->";
9
+ const BLOCK_PATTERN = /<!-- BEGIN:gtkx-agent-rules -->[\s\S]*?<!-- END:gtkx-agent-rules -->/;
10
+ const TOP_LEVEL_HEADING = /^# /m;
11
+ const rulesBody = (heading) => [
12
+ `${heading} GTKX`,
13
+ "",
14
+ "This is not the GTK you have seen before. Most GTK code in your training data is C, PyGObject, Vala or " +
15
+ "GJS, and almost none of it is valid here. Check the rules below against what you are about to write.",
16
+ "",
17
+ "- Children are JSX, never `.append()`, `pack_start()`, `set_child()` or `add()`.",
18
+ '- Signals are props: `onClicked`, not `widget.connect("clicked", ...)`.',
19
+ "- Props are camelCase: `marginTop`, not `margin-top` or `margin_top`.",
20
+ "- There is no `Gtk.Template`, no `.ui` XML, and no `GtkBuilder`. The JSX tree is the definition.",
21
+ "- Elements come from `@gtkx/jsx/<namespace>` and classes, enums and functions from " +
22
+ "`@gtkx/gi/<namespace>`. Both are generated for this project by `gtkx codegen`, not installed from npm, " +
23
+ "so they match the GIR libraries this project declares.",
24
+ "",
25
+ `Read \`${REFERENCE_PATH}/index.md\` before writing widget code. It is generated from this project's own ` +
26
+ "GIR libraries and is the authority on which props, signals and methods exist. Do not infer a prop from " +
27
+ "another toolkit, from a C function name, or from a similar element.",
28
+ "",
29
+ "| Command | What it does |",
30
+ "| --- | --- |",
31
+ "| `gtkx dev` | Run the app with fast refresh |",
32
+ "| `gtkx codegen` | Regenerate bindings and this reference |",
33
+ "| `tsc --noEmit` | Typecheck |",
34
+ "| `vitest run` | Run the tests |",
35
+ "",
36
+ "Never call UI work done without looking at the running app. With `gtkx dev` up, the gtkx MCP server " +
37
+ "exposes the live widget tree, queries, clicks and screenshots; use them to confirm the change landed.",
38
+ "",
39
+ "This block is written by `gtkx codegen`. Anything outside the markers is yours and is left alone, and " +
40
+ "committing the block with your work keeps the tree clean.",
41
+ ];
42
+ const renderBlock = (heading) => [BEGIN_MARKER, "", ...rulesBody(heading), "", END_MARKER].join("\n");
43
+ const headingFor = (contents) => (TOP_LEVEL_HEADING.test(contents) ? "##" : "#");
44
+ const withTrailingNewline = (contents) => (contents.endsWith("\n") ? contents : `${contents}\n`);
45
+ const appendBlock = (contents, block) => {
46
+ if (contents.trim() === "") {
47
+ return `${block}\n`;
48
+ }
49
+ return `${withTrailingNewline(contents)}\n${block}\n`;
50
+ };
51
+ const replaceBlock = (contents, block) => {
52
+ const match = BLOCK_PATTERN.exec(contents);
53
+ if (match === null) {
54
+ return appendBlock(contents, block);
55
+ }
56
+ return contents.slice(0, match.index) + block + contents.slice(match.index + match[0].length);
57
+ };
58
+ const nextContents = (contents) => {
59
+ const heading = headingFor(contents.replace(BLOCK_PATTERN, ""));
60
+ return replaceBlock(contents, renderBlock(heading));
61
+ };
62
+ const errorCode = (error) => error instanceof Error ? error.code : undefined;
63
+ const readOrUndefined = (path) => {
64
+ try {
65
+ return readFileSync(path, "utf8");
66
+ }
67
+ catch (error) {
68
+ if (errorCode(error) === "ENOENT") {
69
+ return undefined;
70
+ }
71
+ throw error;
72
+ }
73
+ };
74
+ const hasWritten = (path, contents) => {
75
+ if (readOrUndefined(path) === contents) {
76
+ return false;
77
+ }
78
+ writeFileSync(path, contents);
79
+ return true;
80
+ };
81
+ const hasWrittenClaudeImport = (root) => {
82
+ try {
83
+ writeFileSync(join(root, CLAUDE_FILENAME), CLAUDE_CONTENTS, { flag: "wx" });
84
+ return true;
85
+ }
86
+ catch (error) {
87
+ if (errorCode(error) === "EEXIST") {
88
+ return false;
89
+ }
90
+ throw error;
91
+ }
92
+ };
93
+ const upsertAgentRules = (root) => {
94
+ const agentsPath = join(root, AGENTS_FILENAME);
95
+ const existing = readOrUndefined(agentsPath) ?? "";
96
+ const files = [];
97
+ if (hasWritten(agentsPath, nextContents(existing))) {
98
+ files.push(AGENTS_FILENAME);
99
+ }
100
+ if (hasWrittenClaudeImport(root)) {
101
+ files.push(CLAUDE_FILENAME);
102
+ }
103
+ return { isWritten: files.length > 0, files };
104
+ };
105
+ export { upsertAgentRules };
106
+ //# sourceMappingURL=agent-rules.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"agent-rules.js","sourceRoot":"","sources":["../../src/internal/agent-rules.ts"],"names":[],"mappings":"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","sourcesContent":["import { readFileSync, writeFileSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport { REFERENCE_PATH } from \"../codegen/reference.js\";\n\ntype AgentRulesResult = {\n isWritten: boolean;\n files: string[];\n};\n\nconst AGENTS_FILENAME = \"AGENTS.md\";\nconst CLAUDE_FILENAME = \"CLAUDE.md\";\nconst CLAUDE_CONTENTS = `@${AGENTS_FILENAME}\\n`;\nconst BEGIN_MARKER = \"<!-- BEGIN:gtkx-agent-rules -->\";\nconst END_MARKER = \"<!-- END:gtkx-agent-rules -->\";\nconst BLOCK_PATTERN = /<!-- BEGIN:gtkx-agent-rules -->[\\s\\S]*?<!-- END:gtkx-agent-rules -->/;\nconst TOP_LEVEL_HEADING = /^# /m;\n\nconst rulesBody = (heading: string): string[] => [\n `${heading} GTKX`,\n \"\",\n \"This is not the GTK you have seen before. Most GTK code in your training data is C, PyGObject, Vala or \" +\n \"GJS, and almost none of it is valid here. Check the rules below against what you are about to write.\",\n \"\",\n \"- Children are JSX, never `.append()`, `pack_start()`, `set_child()` or `add()`.\",\n '- Signals are props: `onClicked`, not `widget.connect(\"clicked\", ...)`.',\n \"- Props are camelCase: `marginTop`, not `margin-top` or `margin_top`.\",\n \"- There is no `Gtk.Template`, no `.ui` XML, and no `GtkBuilder`. The JSX tree is the definition.\",\n \"- Elements come from `@gtkx/jsx/<namespace>` and classes, enums and functions from \" +\n \"`@gtkx/gi/<namespace>`. Both are generated for this project by `gtkx codegen`, not installed from npm, \" +\n \"so they match the GIR libraries this project declares.\",\n \"\",\n `Read \\`${REFERENCE_PATH}/index.md\\` before writing widget code. It is generated from this project's own ` +\n \"GIR libraries and is the authority on which props, signals and methods exist. Do not infer a prop from \" +\n \"another toolkit, from a C function name, or from a similar element.\",\n \"\",\n \"| Command | What it does |\",\n \"| --- | --- |\",\n \"| `gtkx dev` | Run the app with fast refresh |\",\n \"| `gtkx codegen` | Regenerate bindings and this reference |\",\n \"| `tsc --noEmit` | Typecheck |\",\n \"| `vitest run` | Run the tests |\",\n \"\",\n \"Never call UI work done without looking at the running app. With `gtkx dev` up, the gtkx MCP server \" +\n \"exposes the live widget tree, queries, clicks and screenshots; use them to confirm the change landed.\",\n \"\",\n \"This block is written by `gtkx codegen`. Anything outside the markers is yours and is left alone, and \" +\n \"committing the block with your work keeps the tree clean.\",\n];\n\nconst renderBlock = (heading: string): string =>\n [BEGIN_MARKER, \"\", ...rulesBody(heading), \"\", END_MARKER].join(\"\\n\");\n\nconst headingFor = (contents: string): string => (TOP_LEVEL_HEADING.test(contents) ? \"##\" : \"#\");\nconst withTrailingNewline = (contents: string): string => (contents.endsWith(\"\\n\") ? contents : `${contents}\\n`);\n\nconst appendBlock = (contents: string, block: string): string => {\n if (contents.trim() === \"\") {\n return `${block}\\n`;\n }\n\n return `${withTrailingNewline(contents)}\\n${block}\\n`;\n};\n\nconst replaceBlock = (contents: string, block: string): string => {\n const match = BLOCK_PATTERN.exec(contents);\n\n if (match === null) {\n return appendBlock(contents, block);\n }\n\n return contents.slice(0, match.index) + block + contents.slice(match.index + match[0].length);\n};\n\nconst nextContents = (contents: string): string => {\n const heading = headingFor(contents.replace(BLOCK_PATTERN, \"\"));\n\n return replaceBlock(contents, renderBlock(heading));\n};\n\nconst errorCode = (error: unknown): string | undefined =>\n error instanceof Error ? (error as NodeJS.ErrnoException).code : undefined;\n\nconst readOrUndefined = (path: string): string | undefined => {\n try {\n return readFileSync(path, \"utf8\");\n } catch (error) {\n if (errorCode(error) === \"ENOENT\") {\n return undefined;\n }\n\n throw error;\n }\n};\n\nconst hasWritten = (path: string, contents: string): boolean => {\n if (readOrUndefined(path) === contents) {\n return false;\n }\n\n writeFileSync(path, contents);\n\n return true;\n};\n\nconst hasWrittenClaudeImport = (root: string): boolean => {\n try {\n writeFileSync(join(root, CLAUDE_FILENAME), CLAUDE_CONTENTS, { flag: \"wx\" });\n\n return true;\n } catch (error) {\n if (errorCode(error) === \"EEXIST\") {\n return false;\n }\n\n throw error;\n }\n};\n\nconst upsertAgentRules = (root: string): AgentRulesResult => {\n const agentsPath = join(root, AGENTS_FILENAME);\n const existing = readOrUndefined(agentsPath) ?? \"\";\n const files: string[] = [];\n\n if (hasWritten(agentsPath, nextContents(existing))) {\n files.push(AGENTS_FILENAME);\n }\n\n if (hasWrittenClaudeImport(root)) {\n files.push(CLAUDE_FILENAME);\n }\n\n return { isWritten: files.length > 0, files };\n};\n\nexport { upsertAgentRules };\n"]}
@@ -0,0 +1,8 @@
1
+ import { type ElementProps, type OmittedProps } from "@gtkx/codegen";
2
+ type DocsElements = {
3
+ props: ElementProps;
4
+ omittedProps: OmittedProps;
5
+ };
6
+ declare const resolveDocsElements: (cwd: string) => Promise<DocsElements>;
7
+ export { resolveDocsElements };
8
+ //# sourceMappingURL=docs-elements.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"docs-elements.d.ts","sourceRoot":"","sources":["../../src/internal/docs-elements.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,YAAY,EAAE,KAAK,YAAY,EAAqC,MAAM,eAAe,CAAC;AAGxG,KAAK,YAAY,GAAG;IAChB,KAAK,EAAE,YAAY,CAAC;IACpB,YAAY,EAAE,YAAY,CAAC;CAC9B,CAAC;AAEF,QAAA,MAAM,mBAAmB,GAAU,KAAK,MAAM,KAAG,OAAO,CAAC,YAAY,CAUpE,CAAC;AAEF,OAAO,EAAE,mBAAmB,EAAE,CAAC"}
@@ -0,0 +1,12 @@
1
+ import { readBuiltinElements, resolveStore } from "@gtkx/codegen";
2
+ import { existsSync } from "node:fs";
3
+ const resolveDocsElements = async (cwd) => {
4
+ const { gi } = resolveStore(cwd);
5
+ if (!existsSync(gi.storeDir)) {
6
+ return { props: {}, omittedProps: {} };
7
+ }
8
+ const { props, omittedProps } = await readBuiltinElements();
9
+ return { props, omittedProps };
10
+ };
11
+ export { resolveDocsElements };
12
+ //# sourceMappingURL=docs-elements.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"docs-elements.js","sourceRoot":"","sources":["../../src/internal/docs-elements.ts"],"names":[],"mappings":"AAAA,OAAO,EAAwC,mBAAmB,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AACxG,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAOrC,MAAM,mBAAmB,GAAG,KAAK,EAAE,GAAW,EAAyB,EAAE;IACrE,MAAM,EAAE,EAAE,EAAE,GAAG,YAAY,CAAC,GAAG,CAAC,CAAC;IAEjC,IAAI,CAAC,UAAU,CAAC,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAC;QAC3B,OAAO,EAAE,KAAK,EAAE,EAAE,EAAE,YAAY,EAAE,EAAE,EAAE,CAAC;IAC3C,CAAC;IAED,MAAM,EAAE,KAAK,EAAE,YAAY,EAAE,GAAG,MAAM,mBAAmB,EAAE,CAAC;IAE5D,OAAO,EAAE,KAAK,EAAE,YAAY,EAAE,CAAC;AACnC,CAAC,CAAC;AAEF,OAAO,EAAE,mBAAmB,EAAE,CAAC","sourcesContent":["import { type ElementProps, type OmittedProps, readBuiltinElements, resolveStore } from \"@gtkx/codegen\";\nimport { existsSync } from \"node:fs\";\n\ntype DocsElements = {\n props: ElementProps;\n omittedProps: OmittedProps;\n};\n\nconst resolveDocsElements = async (cwd: string): Promise<DocsElements> => {\n const { gi } = resolveStore(cwd);\n\n if (!existsSync(gi.storeDir)) {\n return { props: {}, omittedProps: {} };\n }\n\n const { props, omittedProps } = await readBuiltinElements();\n\n return { props, omittedProps };\n};\n\nexport { resolveDocsElements };\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"icon-path.d.ts","sourceRoot":"","sources":["../../src/internal/icon-path.ts"],"names":[],"mappings":"AAGA,KAAK,uBAAuB,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GACzD;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,GAChB;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC;AA0DpC,QAAA,MAAM,sBAAsB,GACxB,MAAM,MAAM,EACZ,eAAe,MAAM,EACrB,YAAY,MAAM,GAAG,SAAS,KAC/B,uBA4BF,CAAC;AAyBF,QAAA,MAAM,gBAAgB,GAAI,eAAe,MAAM,EAAE,MAAM,MAAM,KAAG,MAI/D,CAAC;AAEF,OAAO,EAAE,gBAAgB,EAAE,sBAAsB,EAAE,KAAK,uBAAuB,EAAE,CAAC"}
1
+ {"version":3,"file":"icon-path.d.ts","sourceRoot":"","sources":["../../src/internal/icon-path.ts"],"names":[],"mappings":"AAIA,KAAK,uBAAuB,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GACzD;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,GAChB;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC;AA4CpC,QAAA,MAAM,sBAAsB,GACxB,MAAM,MAAM,EACZ,eAAe,MAAM,EACrB,YAAY,MAAM,GAAG,SAAS,KAC/B,uBA4BF,CAAC;AAyBF,QAAA,MAAM,gBAAgB,GAAI,eAAe,MAAM,EAAE,MAAM,MAAM,KAAG,MAI/D,CAAC;AAEF,OAAO,EAAE,gBAAgB,EAAE,sBAAsB,EAAE,KAAK,uBAAuB,EAAE,CAAC"}
@@ -1,21 +1,10 @@
1
+ import { isPathInside } from "@gtkx/utils";
1
2
  import { statSync } from "node:fs";
2
- import { basename, extname, isAbsolute, join, relative, resolve } from "node:path";
3
+ import { basename, extname, isAbsolute, join, resolve } from "node:path";
3
4
  const ICON_EXTENSIONS = new Set([".svg", ".png", ".xpm"]);
4
5
  const SCALABLE_DIR = "hicolor/scalable/apps";
5
6
  const SIZE_PATTERN = /^(?<width>[1-9]\d{0,3})x(?<height>[1-9]\d{0,3})$/;
6
7
  const SIZE_SEPARATORS = /[-_.]/;
7
- const isInside = (parent, candidate) => {
8
- const rel = relative(parent, candidate);
9
- return rel.length > 0 && !rel.startsWith("..") && !isAbsolute(rel);
10
- };
11
- const getStats = (path) => {
12
- try {
13
- return statSync(path, { throwIfNoEntry: false });
14
- }
15
- catch {
16
- return undefined;
17
- }
18
- };
19
8
  const iconExtension = (file) => {
20
9
  const extension = extname(file).toLowerCase();
21
10
  if (!ICON_EXTENSIONS.has(extension)) {
@@ -25,7 +14,7 @@ const iconExtension = (file) => {
25
14
  };
26
15
  const defaultIconFiles = (root, applicationId) => [...ICON_EXTENSIONS]
27
16
  .map((extension) => join(root, `${applicationId}${extension}`))
28
- .filter((path) => getStats(path)?.isFile() === true);
17
+ .filter((path) => statSync(path, { throwIfNoEntry: false })?.isFile() === true);
29
18
  const resolveDefaultApplicationIcon = (root, applicationId) => {
30
19
  const files = defaultIconFiles(root, applicationId);
31
20
  if (files.length === 0) {
@@ -48,10 +37,10 @@ const resolveApplicationIcon = (root, applicationId, configured) => {
48
37
  throw new Error(`Cannot use "${configured}" as the application icon: expected a project-relative path`);
49
38
  }
50
39
  const path = resolve(root, configured);
51
- if (!isInside(root, path)) {
40
+ if (!isPathInside(root, path)) {
52
41
  throw new Error(`Cannot use "${configured}" as the application icon: it is outside ${root}`);
53
42
  }
54
- const stats = getStats(path);
43
+ const stats = statSync(path, { throwIfNoEntry: false });
55
44
  if (stats?.isDirectory() === true) {
56
45
  return { kind: "theme", path };
57
46
  }
@@ -1 +1 @@
1
- {"version":3,"file":"icon-path.js","sourceRoot":"","sources":["../../src/internal/icon-path.ts"],"names":[],"mappings":"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","sourcesContent":["import { type Stats, statSync } from \"node:fs\";\nimport { basename, extname, isAbsolute, join, relative, resolve } from \"node:path\";\n\ntype ResolvedApplicationIcon = { kind: \"file\"; path: string } |\n { kind: \"none\" } |\n { kind: \"theme\"; path: string };\n\nconst ICON_EXTENSIONS: Set<string> = new Set([\".svg\", \".png\", \".xpm\"]);\nconst SCALABLE_DIR = \"hicolor/scalable/apps\";\nconst SIZE_PATTERN = /^(?<width>[1-9]\\d{0,3})x(?<height>[1-9]\\d{0,3})$/;\nconst SIZE_SEPARATORS = /[-_.]/;\n\nconst isInside = (parent: string, candidate: string): boolean => {\n const rel = relative(parent, candidate);\n\n return rel.length > 0 && !rel.startsWith(\"..\") && !isAbsolute(rel);\n};\n\nconst getStats = (path: string): Stats | undefined => {\n try {\n return statSync(path, { throwIfNoEntry: false });\n } catch {\n return undefined;\n }\n};\n\nconst iconExtension = (file: string): string => {\n const extension = extname(file).toLowerCase();\n\n if (!ICON_EXTENSIONS.has(extension)) {\n throw new Error(`Cannot use ${file} as an application icon: expected an SVG, PNG, or XPM file`);\n }\n\n return extension;\n};\n\nconst defaultIconFiles = (root: string, applicationId: string): string[] =>\n [...ICON_EXTENSIONS]\n .map((extension) => join(root, `${applicationId}${extension}`))\n .filter((path) => getStats(path)?.isFile() === true);\n\nconst resolveDefaultApplicationIcon = (root: string, applicationId: string): ResolvedApplicationIcon => {\n const files = defaultIconFiles(root, applicationId);\n\n if (files.length === 0) {\n return { kind: \"none\" };\n }\n\n if (files.length > 1) {\n throw new Error(\n `Found multiple default application icons for ${applicationId}; set \\`applicationIcon\\` to choose one`,\n );\n }\n\n const path = files[0];\n\n if (path === undefined) {\n return { kind: \"none\" };\n }\n\n return { kind: \"file\", path };\n};\n\nconst resolveApplicationIcon = (\n root: string,\n applicationId: string,\n configured: string | undefined,\n): ResolvedApplicationIcon => {\n if (configured === undefined) {\n return resolveDefaultApplicationIcon(root, applicationId);\n }\n\n if (isAbsolute(configured)) {\n throw new Error(`Cannot use \"${configured}\" as the application icon: expected a project-relative path`);\n }\n\n const path = resolve(root, configured);\n\n if (!isInside(root, path)) {\n throw new Error(`Cannot use \"${configured}\" as the application icon: it is outside ${root}`);\n }\n\n const stats = getStats(path);\n\n if (stats?.isDirectory() === true) {\n return { kind: \"theme\", path };\n }\n\n if (stats?.isFile() !== true) {\n throw new Error(`Cannot read the application icon \"${configured}\": no such file or directory under ${root}`);\n }\n\n iconExtension(path);\n\n return { kind: \"file\", path };\n};\n\nconst squareSize = (token: string): number | null => {\n const groups = SIZE_PATTERN.exec(token)?.groups;\n\n if (groups === undefined || groups.width !== groups.height) {\n return null;\n }\n\n return Number(groups.width);\n};\n\nconst iconThemeDir = (file: string, extension: string): string => {\n if (extension === \".svg\") {\n return SCALABLE_DIR;\n }\n\n const size = basename(file)\n .split(SIZE_SEPARATORS)\n .map((token) => squareSize(token))\n .find((value) => value !== null);\n\n return size === undefined ? SCALABLE_DIR : `hicolor/${String(size)}x${String(size)}/apps`;\n};\n\nconst relativeIconPath = (applicationId: string, file: string): string => {\n const extension = iconExtension(file);\n\n return `${iconThemeDir(file, extension)}/${applicationId}${extension}`;\n};\n\nexport { relativeIconPath, resolveApplicationIcon, type ResolvedApplicationIcon };\n"]}
1
+ {"version":3,"file":"icon-path.js","sourceRoot":"","sources":["../../src/internal/icon-path.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AACnC,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,UAAU,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAMzE,MAAM,eAAe,GAAgB,IAAI,GAAG,CAAC,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;AACvE,MAAM,YAAY,GAAG,uBAAuB,CAAC;AAC7C,MAAM,YAAY,GAAG,kDAAkD,CAAC;AACxE,MAAM,eAAe,GAAG,OAAO,CAAC;AAEhC,MAAM,aAAa,GAAG,CAAC,IAAY,EAAU,EAAE;IAC3C,MAAM,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,WAAW,EAAE,CAAC;IAE9C,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,SAAS,CAAC,EAAE,CAAC;QAClC,MAAM,IAAI,KAAK,CAAC,cAAc,IAAI,4DAA4D,CAAC,CAAC;IACpG,CAAC;IAED,OAAO,SAAS,CAAC;AACrB,CAAC,CAAC;AAEF,MAAM,gBAAgB,GAAG,CAAC,IAAY,EAAE,aAAqB,EAAY,EAAE,CACvE,CAAC,GAAG,eAAe,CAAC;KACf,GAAG,CAAC,CAAC,SAAS,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,EAAE,GAAG,aAAa,GAAG,SAAS,EAAE,CAAC,CAAC;KAC9D,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,QAAQ,CAAC,IAAI,EAAE,EAAE,cAAc,EAAE,KAAK,EAAE,CAAC,EAAE,MAAM,EAAE,KAAK,IAAI,CAAC,CAAC;AAExF,MAAM,6BAA6B,GAAG,CAAC,IAAY,EAAE,aAAqB,EAA2B,EAAE;IACnG,MAAM,KAAK,GAAG,gBAAgB,CAAC,IAAI,EAAE,aAAa,CAAC,CAAC;IAEpD,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACrB,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;IAC5B,CAAC;IAED,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACnB,MAAM,IAAI,KAAK,CACX,gDAAgD,aAAa,yCAAyC,CACzG,CAAC;IACN,CAAC;IAED,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;IAEtB,IAAI,IAAI,KAAK,SAAS,EAAE,CAAC;QACrB,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;IAC5B,CAAC;IAED,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC;AAClC,CAAC,CAAC;AAEF,MAAM,sBAAsB,GAAG,CAC3B,IAAY,EACZ,aAAqB,EACrB,UAA8B,EACP,EAAE;IACzB,IAAI,UAAU,KAAK,SAAS,EAAE,CAAC;QAC3B,OAAO,6BAA6B,CAAC,IAAI,EAAE,aAAa,CAAC,CAAC;IAC9D,CAAC;IAED,IAAI,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;QACzB,MAAM,IAAI,KAAK,CAAC,eAAe,UAAU,6DAA6D,CAAC,CAAC;IAC5G,CAAC;IAED,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,EAAE,UAAU,CAAC,CAAC;IAEvC,IAAI,CAAC,YAAY,CAAC,IAAI,EAAE,IAAI,CAAC,EAAE,CAAC;QAC5B,MAAM,IAAI,KAAK,CAAC,eAAe,UAAU,4CAA4C,IAAI,EAAE,CAAC,CAAC;IACjG,CAAC;IAED,MAAM,KAAK,GAAG,QAAQ,CAAC,IAAI,EAAE,EAAE,cAAc,EAAE,KAAK,EAAE,CAAC,CAAC;IAExD,IAAI,KAAK,EAAE,WAAW,EAAE,KAAK,IAAI,EAAE,CAAC;QAChC,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;IACnC,CAAC;IAED,IAAI,KAAK,EAAE,MAAM,EAAE,KAAK,IAAI,EAAE,CAAC;QAC3B,MAAM,IAAI,KAAK,CAAC,qCAAqC,UAAU,sCAAsC,IAAI,EAAE,CAAC,CAAC;IACjH,CAAC;IAED,aAAa,CAAC,IAAI,CAAC,CAAC;IAEpB,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC;AAClC,CAAC,CAAC;AAEF,MAAM,UAAU,GAAG,CAAC,KAAa,EAAiB,EAAE;IAChD,MAAM,MAAM,GAAG,YAAY,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IAEhD,IAAI,MAAM,KAAK,SAAS,IAAI,MAAM,CAAC,KAAK,KAAK,MAAM,CAAC,MAAM,EAAE,CAAC;QACzD,OAAO,IAAI,CAAC;IAChB,CAAC;IAED,OAAO,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;AAChC,CAAC,CAAC;AAEF,MAAM,YAAY,GAAG,CAAC,IAAY,EAAE,SAAiB,EAAU,EAAE;IAC7D,IAAI,SAAS,KAAK,MAAM,EAAE,CAAC;QACvB,OAAO,YAAY,CAAC;IACxB,CAAC;IAED,MAAM,IAAI,GAAG,QAAQ,CAAC,IAAI,CAAC;SACtB,KAAK,CAAC,eAAe,CAAC;SACtB,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC;SACjC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,KAAK,IAAI,CAAC,CAAC;IAErC,OAAO,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,WAAW,MAAM,CAAC,IAAI,CAAC,IAAI,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC;AAC9F,CAAC,CAAC;AAEF,MAAM,gBAAgB,GAAG,CAAC,aAAqB,EAAE,IAAY,EAAU,EAAE;IACrE,MAAM,SAAS,GAAG,aAAa,CAAC,IAAI,CAAC,CAAC;IAEtC,OAAO,GAAG,YAAY,CAAC,IAAI,EAAE,SAAS,CAAC,IAAI,aAAa,GAAG,SAAS,EAAE,CAAC;AAC3E,CAAC,CAAC;AAEF,OAAO,EAAE,gBAAgB,EAAE,sBAAsB,EAAgC,CAAC","sourcesContent":["import { isPathInside } from \"@gtkx/utils\";\nimport { statSync } from \"node:fs\";\nimport { basename, extname, isAbsolute, join, resolve } from \"node:path\";\n\ntype ResolvedApplicationIcon = { kind: \"file\"; path: string } |\n { kind: \"none\" } |\n { kind: \"theme\"; path: string };\n\nconst ICON_EXTENSIONS: Set<string> = new Set([\".svg\", \".png\", \".xpm\"]);\nconst SCALABLE_DIR = \"hicolor/scalable/apps\";\nconst SIZE_PATTERN = /^(?<width>[1-9]\\d{0,3})x(?<height>[1-9]\\d{0,3})$/;\nconst SIZE_SEPARATORS = /[-_.]/;\n\nconst iconExtension = (file: string): string => {\n const extension = extname(file).toLowerCase();\n\n if (!ICON_EXTENSIONS.has(extension)) {\n throw new Error(`Cannot use ${file} as an application icon: expected an SVG, PNG, or XPM file`);\n }\n\n return extension;\n};\n\nconst defaultIconFiles = (root: string, applicationId: string): string[] =>\n [...ICON_EXTENSIONS]\n .map((extension) => join(root, `${applicationId}${extension}`))\n .filter((path) => statSync(path, { throwIfNoEntry: false })?.isFile() === true);\n\nconst resolveDefaultApplicationIcon = (root: string, applicationId: string): ResolvedApplicationIcon => {\n const files = defaultIconFiles(root, applicationId);\n\n if (files.length === 0) {\n return { kind: \"none\" };\n }\n\n if (files.length > 1) {\n throw new Error(\n `Found multiple default application icons for ${applicationId}; set \\`applicationIcon\\` to choose one`,\n );\n }\n\n const path = files[0];\n\n if (path === undefined) {\n return { kind: \"none\" };\n }\n\n return { kind: \"file\", path };\n};\n\nconst resolveApplicationIcon = (\n root: string,\n applicationId: string,\n configured: string | undefined,\n): ResolvedApplicationIcon => {\n if (configured === undefined) {\n return resolveDefaultApplicationIcon(root, applicationId);\n }\n\n if (isAbsolute(configured)) {\n throw new Error(`Cannot use \"${configured}\" as the application icon: expected a project-relative path`);\n }\n\n const path = resolve(root, configured);\n\n if (!isPathInside(root, path)) {\n throw new Error(`Cannot use \"${configured}\" as the application icon: it is outside ${root}`);\n }\n\n const stats = statSync(path, { throwIfNoEntry: false });\n\n if (stats?.isDirectory() === true) {\n return { kind: \"theme\", path };\n }\n\n if (stats?.isFile() !== true) {\n throw new Error(`Cannot read the application icon \"${configured}\": no such file or directory under ${root}`);\n }\n\n iconExtension(path);\n\n return { kind: \"file\", path };\n};\n\nconst squareSize = (token: string): number | null => {\n const groups = SIZE_PATTERN.exec(token)?.groups;\n\n if (groups === undefined || groups.width !== groups.height) {\n return null;\n }\n\n return Number(groups.width);\n};\n\nconst iconThemeDir = (file: string, extension: string): string => {\n if (extension === \".svg\") {\n return SCALABLE_DIR;\n }\n\n const size = basename(file)\n .split(SIZE_SEPARATORS)\n .map((token) => squareSize(token))\n .find((value) => value !== null);\n\n return size === undefined ? SCALABLE_DIR : `hicolor/${String(size)}x${String(size)}/apps`;\n};\n\nconst relativeIconPath = (applicationId: string, file: string): string => {\n const extension = iconExtension(file);\n\n return `${iconThemeDir(file, extension)}/${applicationId}${extension}`;\n};\n\nexport { relativeIconPath, resolveApplicationIcon, type ResolvedApplicationIcon };\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"source-imports.d.ts","sourceRoot":"","sources":["../../src/internal/source-imports.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAuB,aAAa,EAAE,MAAM,MAAM,CAAC;AAM/D,KAAK,YAAY,GAAG;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;CAClB,CAAC;AAEF,KAAK,cAAc,GAAG,WAAW,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC,CAAC;AAwBzD,QAAA,MAAM,cAAc,GAAI,MAAM,MAAM,KAAG,cAAc,GAAG,SAMvD,CAAC;AAgCF,QAAA,MAAM,mBAAmB,GAAI,KAAK,MAAM,KAAG,MAAM,EAKhD,CAAC;AA+EF,QAAA,MAAM,qBAAqB,GAAI,MAAM,MAAM,KAAG,YAAY,EAAE,GAAG,IACP,CAAC;AAKzD,QAAA,MAAM,qBAAqB,GAAI,KAAK,MAAM,KAAG,YAAY,EAKxD,CAAC;AAEF,OAAO,EAAE,mBAAmB,EAAE,qBAAqB,EAAE,qBAAqB,EAAE,KAAK,YAAY,EAAE,cAAc,EAAE,CAAC"}
1
+ {"version":3,"file":"source-imports.d.ts","sourceRoot":"","sources":["../../src/internal/source-imports.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAuB,aAAa,EAAE,MAAM,MAAM,CAAC;AAM/D,KAAK,YAAY,GAAG;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;CAClB,CAAC;AAEF,KAAK,cAAc,GAAG,WAAW,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC,CAAC;AAYzD,QAAA,MAAM,cAAc,GAAI,MAAM,MAAM,KAAG,cAAc,GAAG,SAMvD,CAAC;AAEF,QAAA,MAAM,mBAAmB,GAAI,KAAK,MAAM,KAAG,MAAM,EAW5C,CAAC;AA+EN,QAAA,MAAM,qBAAqB,GAAI,MAAM,MAAM,KAAG,YAAY,EAAE,GAAG,IACP,CAAC;AAKzD,QAAA,MAAM,qBAAqB,GAAI,KAAK,MAAM,KAAG,YAAY,EAKxD,CAAC;AAEF,OAAO,EAAE,mBAAmB,EAAE,qBAAqB,EAAE,qBAAqB,EAAE,KAAK,YAAY,EAAE,cAAc,EAAE,CAAC"}
@@ -1,10 +1,8 @@
1
1
  import { sortStringsBy } from "@gtkx/utils";
2
- import { readdirSync, readFileSync } from "node:fs";
2
+ import { globSync, readFileSync } from "node:fs";
3
3
  import { extname, join } from "node:path";
4
4
  import { parseSync, Visitor } from "vite";
5
5
  const SOURCE_LANGUAGES = new Map([
6
- [".cjs", "jsx"],
7
- [".cts", "ts"],
8
6
  [".js", "jsx"],
9
7
  [".jsx", "jsx"],
10
8
  [".mjs", "jsx"],
@@ -12,50 +10,20 @@ const SOURCE_LANGUAGES = new Map([
12
10
  [".ts", "ts"],
13
11
  [".tsx", "tsx"],
14
12
  ]);
15
- const EXCLUDED_DIRECTORIES = new Set([
16
- ".git",
17
- ".gtkx",
18
- "build",
19
- "coverage",
20
- "dist",
21
- "node_modules",
22
- "out-tsc",
23
- ]);
24
13
  const sourceLanguage = (path) => {
25
- if (path.endsWith(".d.ts") || path.endsWith(".d.cts") || path.endsWith(".d.mts")) {
14
+ if (path.endsWith(".d.ts") || path.endsWith(".d.mts")) {
26
15
  return undefined;
27
16
  }
28
17
  return SOURCE_LANGUAGES.get(extname(path).toLowerCase());
29
18
  };
30
- const collectSourceEntry = (dir, entry, found) => {
31
- const path = join(dir, entry.name);
32
- if (entry.isDirectory()) {
33
- if (!EXCLUDED_DIRECTORIES.has(entry.name)) {
34
- sourceFilesIn(path, found);
35
- }
36
- return;
37
- }
38
- if (entry.isFile() && sourceLanguage(path) !== undefined) {
39
- found.push(path);
40
- }
41
- };
42
- const sourceFilesIn = (dir, found) => {
43
- let entries;
44
- try {
45
- entries = readdirSync(dir, { withFileTypes: true });
46
- }
47
- catch {
48
- return;
49
- }
50
- for (const entry of entries) {
51
- collectSourceEntry(dir, entry, found);
52
- }
53
- };
54
- const discoverSourceFiles = (dir) => {
55
- const files = [];
56
- sourceFilesIn(dir, files);
57
- return sortStringsBy(files, (path) => path);
58
- };
19
+ const discoverSourceFiles = (dir) => sortStringsBy(globSync("**/{*,.*}", {
20
+ cwd: dir,
21
+ exclude: ["**/{build,coverage,dist,node_modules,out-tsc}/**"],
22
+ withFileTypes: true,
23
+ })
24
+ .filter((entry) => entry.isFile())
25
+ .map((entry) => join(entry.parentPath, entry.name))
26
+ .filter((path) => sourceLanguage(path) !== undefined), (path) => path);
59
27
  const staticImportSources = (module) => [
60
28
  ...module.staticImports.map((statement) => statement.moduleRequest.value),
61
29
  ...module.staticExports.flatMap((statement) => statement.entries
@@ -1 +1 @@
1
- {"version":3,"file":"source-imports.js","sourceRoot":"","sources":["../../src/internal/source-imports.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,EAAe,WAAW,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACjE,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,MAAM,CAAC;AAU1C,MAAM,gBAAgB,GAAgC,IAAI,GAAG,CAAC;IAC1D,CAAC,MAAM,EAAE,KAAK,CAAC;IACf,CAAC,MAAM,EAAE,IAAI,CAAC;IACd,CAAC,KAAK,EAAE,KAAK,CAAC;IACd,CAAC,MAAM,EAAE,KAAK,CAAC;IACf,CAAC,MAAM,EAAE,KAAK,CAAC;IACf,CAAC,MAAM,EAAE,IAAI,CAAC;IACd,CAAC,KAAK,EAAE,IAAI,CAAC;IACb,CAAC,MAAM,EAAE,KAAK,CAAC;CAClB,CAAC,CAAC;AAEH,MAAM,oBAAoB,GAAgB,IAAI,GAAG,CAAC;IAC9C,MAAM;IACN,OAAO;IACP,OAAO;IACP,UAAU;IACV,MAAM;IACN,cAAc;IACd,SAAS;CACZ,CAAC,CAAC;AAEH,MAAM,cAAc,GAAG,CAAC,IAAY,EAA8B,EAAE;IAChE,IAAI,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC;QAC/E,OAAO,SAAS,CAAC;IACrB,CAAC;IAED,OAAO,gBAAgB,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC;AAC7D,CAAC,CAAC;AAEF,MAAM,kBAAkB,GAAG,CAAC,GAAW,EAAE,KAAa,EAAE,KAAe,EAAQ,EAAE;IAC7E,MAAM,IAAI,GAAG,IAAI,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC;IAEnC,IAAI,KAAK,CAAC,WAAW,EAAE,EAAE,CAAC;QACtB,IAAI,CAAC,oBAAoB,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC;YACxC,aAAa,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;QAC/B,CAAC;QAED,OAAO;IACX,CAAC;IAED,IAAI,KAAK,CAAC,MAAM,EAAE,IAAI,cAAc,CAAC,IAAI,CAAC,KAAK,SAAS,EAAE,CAAC;QACvD,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACrB,CAAC;AACL,CAAC,CAAC;AAEF,MAAM,aAAa,GAAG,CAAC,GAAW,EAAE,KAAe,EAAQ,EAAE;IACzD,IAAI,OAAiB,CAAC;IAEtB,IAAI,CAAC;QACD,OAAO,GAAG,WAAW,CAAC,GAAG,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,CAAC;IACxD,CAAC;IAAC,MAAM,CAAC;QACL,OAAO;IACX,CAAC;IAED,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;QAC1B,kBAAkB,CAAC,GAAG,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC;IAC1C,CAAC;AACL,CAAC,CAAC;AAEF,MAAM,mBAAmB,GAAG,CAAC,GAAW,EAAY,EAAE;IAClD,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,aAAa,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;IAE1B,OAAO,aAAa,CAAC,KAAK,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,CAAC;AAChD,CAAC,CAAC;AAEF,MAAM,mBAAmB,GAAG,CAAC,MAAoB,EAAY,EAAE,CAAC;IAC5D,GAAG,MAAM,CAAC,aAAa,CAAC,GAAG,CAAC,CAAC,SAAS,EAAE,EAAE,CAAC,SAAS,CAAC,aAAa,CAAC,KAAK,CAAC;IACzE,GAAG,MAAM,CAAC,aAAa,CAAC,OAAO,CAAC,CAAC,SAAS,EAAE,EAAE,CAC1C,SAAS,CAAC,OAAO;SACZ,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,aAAa,EAAE,KAAK,CAAC;SAC1C,MAAM,CAAC,CAAC,MAAM,EAAoB,EAAE,CAAC,MAAM,KAAK,SAAS,CAAC,CAClE;CACJ,CAAC;AAEF,MAAM,0BAA0B,GAAG,CAAC,MAAoB,EAAY,EAAE,CAAC;IACnE,GAAG,MAAM,CAAC,aAAa;SAClB,MAAM,CAAC,CAAC,SAAS,EAAE,EAAE,CAAC,SAAS,CAAC,OAAO,CAAC,MAAM,KAAK,CAAC,IAAI,SAAS,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;SACzG,GAAG,CAAC,CAAC,SAAS,EAAE,EAAE,CAAC,SAAS,CAAC,aAAa,CAAC,KAAK,CAAC;IACtD,GAAG,MAAM,CAAC,aAAa,CAAC,OAAO,CAAC,CAAC,SAAS,EAAE,EAAE,CAC1C,SAAS,CAAC,OAAO;SACZ,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC;SAChC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,aAAa,EAAE,KAAK,CAAC;SAC1C,MAAM,CAAC,CAAC,MAAM,EAAoB,EAAE,CAAC,MAAM,KAAK,SAAS,CAAC,CAClE;CACJ,CAAC;AAEF,MAAM,oBAAoB,GAAG,CAAC,IAA4B,EAAiB,EAAE;IACzE,MAAM,CAAC,KAAK,CAAC,GAAG,IAAI,CAAC,MAAM,CAAC;IAE5B,OAAO,KAAK,KAAK,SAAS,IAAI,IAAI,CAAC,WAAW,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC;AAC1F,CAAC,CAAC;AAEF,MAAM,mBAAmB,GAAG,CAAC,IAAuB,EAAiB,EAAE;IACnE,IAAI,IAAI,CAAC,IAAI,KAAK,iBAAiB,EAAE,CAAC;QAClC,OAAO,oBAAoB,CAAC,IAAI,CAAC,CAAC;IACtC,CAAC;IAED,OAAO,IAAI,CAAC,IAAI,KAAK,SAAS,IAAI,OAAO,IAAI,CAAC,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC;AACzF,CAAC,CAAC;AAEF,MAAM,2BAA2B,GAAG,CAAC,OAAuB,EAAE,KAAe,EAAQ,EAAE;IACnF,IAAI,OAAO,CAAC;QACR,gBAAgB,EAAE,CAAC,IAAI,EAAE,EAAE;YACvB,MAAM,MAAM,GAAG,mBAAmB,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;YAEhD,IAAI,MAAM,KAAK,IAAI,EAAE,CAAC;gBAClB,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;YACvB,CAAC;QACL,CAAC;KACJ,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;AACtB,CAAC,CAAC;AAEF,MAAM,kBAAkB,GAAG,CACvB,IAAY,EACZ,aAAiD,EAC5B,EAAE;IACvB,MAAM,IAAI,GAAG,cAAc,CAAC,IAAI,CAAC,CAAC;IAElC,IAAI,IAAI,KAAK,SAAS,EAAE,CAAC;QACrB,OAAO,EAAE,CAAC;IACd,CAAC;IAED,IAAI,MAAmB,CAAC;IAExB,IAAI,CAAC;QACD,MAAM,GAAG,SAAS,CAAC,IAAI,EAAE,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC;IACnE,CAAC;IAAC,MAAM,CAAC;QACL,OAAO,IAAI,CAAC;IAChB,CAAC;IAED,IAAI,MAAM,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC3B,OAAO,IAAI,CAAC;IAChB,CAAC;IAED,MAAM,OAAO,GAAG,aAAa,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;IAC7C,2BAA2B,CAAC,MAAM,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;IAErD,OAAO,CAAC,GAAG,IAAI,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC;AAC/E,CAAC,CAAC;AAEF,MAAM,cAAc,GAAG,CAAC,IAAY,EAAyB,EAAE,CAAC,kBAAkB,CAAC,IAAI,EAAE,mBAAmB,CAAC,CAAC;AAE9G,MAAM,qBAAqB,GAAG,CAAC,IAAY,EAAyB,EAAE,CAClE,kBAAkB,CAAC,IAAI,EAAE,0BAA0B,CAAC,CAAC;AAEzD,MAAM,SAAS,GAAG,CAAC,IAAY,EAAkB,EAAE,CAAC,cAAc,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;AAC/E,MAAM,SAAS,GAAG,CAAC,KAAmB,EAAU,EAAE,CAAC,GAAG,KAAK,CAAC,QAAQ,KAAK,KAAK,CAAC,MAAM,EAAE,CAAC;AAExF,MAAM,qBAAqB,GAAG,CAAC,GAAW,EAAkB,EAAE;IAC1D,MAAM,KAAK,GAAG,mBAAmB,CAAC,GAAG,CAAC,CAAC;IACvC,MAAM,OAAO,GAAG,KAAK,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC;IAEzD,OAAO,aAAa,CAAC,OAAO,EAAE,SAAS,CAAC,CAAC;AAC7C,CAAC,CAAC;AAEF,OAAO,EAAE,mBAAmB,EAAE,qBAAqB,EAAE,qBAAqB,EAAqB,cAAc,EAAE,CAAC","sourcesContent":["import type { ESTree, ParseResult, ParserOptions } from \"vite\";\nimport { sortStringsBy } from \"@gtkx/utils\";\nimport { type Dirent, readdirSync, readFileSync } from \"node:fs\";\nimport { extname, join } from \"node:path\";\nimport { parseSync, Visitor } from \"vite\";\n\ntype SourceImport = {\n importer: string;\n source: string;\n};\n\ntype SourceLanguage = NonNullable<ParserOptions[\"lang\"]>;\ntype ParsedModule = ParseResult[\"module\"];\n\nconst SOURCE_LANGUAGES: Map<string, SourceLanguage> = new Map([\n [\".cjs\", \"jsx\"],\n [\".cts\", \"ts\"],\n [\".js\", \"jsx\"],\n [\".jsx\", \"jsx\"],\n [\".mjs\", \"jsx\"],\n [\".mts\", \"ts\"],\n [\".ts\", \"ts\"],\n [\".tsx\", \"tsx\"],\n]);\n\nconst EXCLUDED_DIRECTORIES: Set<string> = new Set([\n \".git\",\n \".gtkx\",\n \"build\",\n \"coverage\",\n \"dist\",\n \"node_modules\",\n \"out-tsc\",\n]);\n\nconst sourceLanguage = (path: string): SourceLanguage | undefined => {\n if (path.endsWith(\".d.ts\") || path.endsWith(\".d.cts\") || path.endsWith(\".d.mts\")) {\n return undefined;\n }\n\n return SOURCE_LANGUAGES.get(extname(path).toLowerCase());\n};\n\nconst collectSourceEntry = (dir: string, entry: Dirent, found: string[]): void => {\n const path = join(dir, entry.name);\n\n if (entry.isDirectory()) {\n if (!EXCLUDED_DIRECTORIES.has(entry.name)) {\n sourceFilesIn(path, found);\n }\n\n return;\n }\n\n if (entry.isFile() && sourceLanguage(path) !== undefined) {\n found.push(path);\n }\n};\n\nconst sourceFilesIn = (dir: string, found: string[]): void => {\n let entries: Dirent[];\n\n try {\n entries = readdirSync(dir, { withFileTypes: true });\n } catch {\n return;\n }\n\n for (const entry of entries) {\n collectSourceEntry(dir, entry, found);\n }\n};\n\nconst discoverSourceFiles = (dir: string): string[] => {\n const files: string[] = [];\n sourceFilesIn(dir, files);\n\n return sortStringsBy(files, (path) => path);\n};\n\nconst staticImportSources = (module: ParsedModule): string[] => [\n ...module.staticImports.map((statement) => statement.moduleRequest.value),\n ...module.staticExports.flatMap((statement) =>\n statement.entries\n .map((entry) => entry.moduleRequest?.value)\n .filter((source): source is string => source !== undefined),\n ),\n];\n\nconst staticRuntimeImportSources = (module: ParsedModule): string[] => [\n ...module.staticImports\n .filter((statement) => statement.entries.length === 0 || statement.entries.some((entry) => !entry.isType))\n .map((statement) => statement.moduleRequest.value),\n ...module.staticExports.flatMap((statement) =>\n statement.entries\n .filter((entry) => !entry.isType)\n .map((entry) => entry.moduleRequest?.value)\n .filter((source): source is string => source !== undefined),\n ),\n];\n\nconst templateImportSource = (node: ESTree.TemplateLiteral): string | null => {\n const [quasi] = node.quasis;\n\n return quasi === undefined || node.expressions.length > 0 ? null : quasi.value.cooked;\n};\n\nconst literalImportSource = (node: ESTree.Expression): string | null => {\n if (node.type === \"TemplateLiteral\") {\n return templateImportSource(node);\n }\n\n return node.type === \"Literal\" && typeof node.value === \"string\" ? node.value : null;\n};\n\nconst collectDynamicImportSources = (program: ESTree.Program, found: string[]): void => {\n new Visitor({\n ImportExpression: (node) => {\n const source = literalImportSource(node.source);\n\n if (source !== null) {\n found.push(source);\n }\n },\n }).visit(program);\n};\n\nconst parseImportsInWith = (\n path: string,\n staticSources: (module: ParsedModule) => string[],\n): SourceImport[] | null => {\n const lang = sourceLanguage(path);\n\n if (lang === undefined) {\n return [];\n }\n\n let parsed: ParseResult;\n\n try {\n parsed = parseSync(path, readFileSync(path, \"utf8\"), { lang });\n } catch {\n return null;\n }\n\n if (parsed.errors.length > 0) {\n return null;\n }\n\n const sources = staticSources(parsed.module);\n collectDynamicImportSources(parsed.program, sources);\n\n return [...new Set(sources)].map((source) => ({ importer: path, source }));\n};\n\nconst parseImportsIn = (path: string): SourceImport[] | null => parseImportsInWith(path, staticImportSources);\n\nconst parseRuntimeImportsIn = (path: string): SourceImport[] | null =>\n parseImportsInWith(path, staticRuntimeImportSources);\n\nconst importsIn = (path: string): SourceImport[] => parseImportsIn(path) ?? [];\nconst importKey = (entry: SourceImport): string => `${entry.importer}\\0${entry.source}`;\n\nconst discoverSourceImports = (dir: string): SourceImport[] => {\n const files = discoverSourceFiles(dir);\n const imports = files.flatMap((path) => importsIn(path));\n\n return sortStringsBy(imports, importKey);\n};\n\nexport { discoverSourceFiles, discoverSourceImports, parseRuntimeImportsIn, type SourceImport, sourceLanguage };\n"]}
1
+ {"version":3,"file":"source-imports.js","sourceRoot":"","sources":["../../src/internal/source-imports.ts"],"names":[],"mappings":"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","sourcesContent":["import type { ESTree, ParseResult, ParserOptions } from \"vite\";\nimport { sortStringsBy } from \"@gtkx/utils\";\nimport { globSync, readFileSync } from \"node:fs\";\nimport { extname, join } from \"node:path\";\nimport { parseSync, Visitor } from \"vite\";\n\ntype SourceImport = {\n importer: string;\n source: string;\n};\n\ntype SourceLanguage = NonNullable<ParserOptions[\"lang\"]>;\ntype ParsedModule = ParseResult[\"module\"];\n\nconst SOURCE_LANGUAGES: Map<string, SourceLanguage> = new Map([\n [\".js\", \"jsx\"],\n [\".jsx\", \"jsx\"],\n [\".mjs\", \"jsx\"],\n [\".mts\", \"ts\"],\n [\".ts\", \"ts\"],\n [\".tsx\", \"tsx\"],\n]);\n\nconst sourceLanguage = (path: string): SourceLanguage | undefined => {\n if (path.endsWith(\".d.ts\") || path.endsWith(\".d.mts\")) {\n return undefined;\n }\n\n return SOURCE_LANGUAGES.get(extname(path).toLowerCase());\n};\n\nconst discoverSourceFiles = (dir: string): string[] =>\n sortStringsBy(\n globSync(\"**/{*,.*}\", {\n cwd: dir,\n exclude: [\"**/{build,coverage,dist,node_modules,out-tsc}/**\"],\n withFileTypes: true,\n })\n .filter((entry) => entry.isFile())\n .map((entry) => join(entry.parentPath, entry.name))\n .filter((path) => sourceLanguage(path) !== undefined),\n (path) => path,\n );\n\nconst staticImportSources = (module: ParsedModule): string[] => [\n ...module.staticImports.map((statement) => statement.moduleRequest.value),\n ...module.staticExports.flatMap((statement) =>\n statement.entries\n .map((entry) => entry.moduleRequest?.value)\n .filter((source): source is string => source !== undefined),\n ),\n];\n\nconst staticRuntimeImportSources = (module: ParsedModule): string[] => [\n ...module.staticImports\n .filter((statement) => statement.entries.length === 0 || statement.entries.some((entry) => !entry.isType))\n .map((statement) => statement.moduleRequest.value),\n ...module.staticExports.flatMap((statement) =>\n statement.entries\n .filter((entry) => !entry.isType)\n .map((entry) => entry.moduleRequest?.value)\n .filter((source): source is string => source !== undefined),\n ),\n];\n\nconst templateImportSource = (node: ESTree.TemplateLiteral): string | null => {\n const [quasi] = node.quasis;\n\n return quasi === undefined || node.expressions.length > 0 ? null : quasi.value.cooked;\n};\n\nconst literalImportSource = (node: ESTree.Expression): string | null => {\n if (node.type === \"TemplateLiteral\") {\n return templateImportSource(node);\n }\n\n return node.type === \"Literal\" && typeof node.value === \"string\" ? node.value : null;\n};\n\nconst collectDynamicImportSources = (program: ESTree.Program, found: string[]): void => {\n new Visitor({\n ImportExpression: (node) => {\n const source = literalImportSource(node.source);\n\n if (source !== null) {\n found.push(source);\n }\n },\n }).visit(program);\n};\n\nconst parseImportsInWith = (\n path: string,\n staticSources: (module: ParsedModule) => string[],\n): SourceImport[] | null => {\n const lang = sourceLanguage(path);\n\n if (lang === undefined) {\n return [];\n }\n\n let parsed: ParseResult;\n\n try {\n parsed = parseSync(path, readFileSync(path, \"utf8\"), { lang });\n } catch {\n return null;\n }\n\n if (parsed.errors.length > 0) {\n return null;\n }\n\n const sources = staticSources(parsed.module);\n collectDynamicImportSources(parsed.program, sources);\n\n return [...new Set(sources)].map((source) => ({ importer: path, source }));\n};\n\nconst parseImportsIn = (path: string): SourceImport[] | null => parseImportsInWith(path, staticImportSources);\n\nconst parseRuntimeImportsIn = (path: string): SourceImport[] | null =>\n parseImportsInWith(path, staticRuntimeImportSources);\n\nconst importsIn = (path: string): SourceImport[] => parseImportsIn(path) ?? [];\nconst importKey = (entry: SourceImport): string => `${entry.importer}\\0${entry.source}`;\n\nconst discoverSourceImports = (dir: string): SourceImport[] => {\n const files = discoverSourceFiles(dir);\n const imports = files.flatMap((path) => importsIn(path));\n\n return sortStringsBy(imports, importKey);\n};\n\nexport { discoverSourceFiles, discoverSourceImports, parseRuntimeImportsIn, type SourceImport, sourceLanguage };\n"]}