@inlang/paraglide-js 2.27.0 → 2.28.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +9 -0
- package/dist/bundler-plugins/per-locale-build/index.js +14 -7
- package/dist/bundler-plugins/per-locale-build/index.js.map +1 -1
- package/dist/bundler-plugins/per-locale-build/vite-environments.test.js +235 -2
- package/dist/bundler-plugins/per-locale-build/vite-environments.test.js.map +1 -1
- package/dist/bundler-plugins/unplugin.d.ts +1 -1
- package/dist/bundler-plugins/unplugin.js +79 -10
- package/dist/bundler-plugins/unplugin.js.map +1 -1
- package/dist/bundler-plugins/unplugin.test.js +334 -1
- package/dist/bundler-plugins/unplugin.test.js.map +1 -1
- package/dist/bundler-plugins/vite.js +2 -1
- package/dist/bundler-plugins/vite.js.map +1 -1
- package/dist/bundler-plugins/vite.test.js +1 -1
- package/dist/bundler-plugins/vite.test.js.map +1 -1
- package/dist/cli/commands/compile/command.js +13 -0
- package/dist/cli/commands/compile/command.js.map +1 -1
- package/dist/cli/commands/compile/command.test.js +87 -3
- package/dist/cli/commands/compile/command.test.js.map +1 -1
- package/dist/cli/commands/init/command.d.ts +5 -0
- package/dist/cli/commands/init/command.js +213 -59
- package/dist/cli/commands/init/command.js.map +1 -1
- package/dist/cli/commands/init/command.test.d.ts +1 -0
- package/dist/cli/commands/init/command.test.js +123 -0
- package/dist/cli/commands/init/command.test.js.map +1 -0
- package/dist/cli/init-options.d.ts +11 -0
- package/dist/cli/init-options.js +2 -0
- package/dist/cli/init-options.js.map +1 -0
- package/dist/cli/steps/add-inlang-check.js +2 -2
- package/dist/cli/steps/add-inlang-check.js.map +1 -1
- package/dist/cli/steps/add-message-lint.d.ts +34 -0
- package/dist/cli/steps/add-message-lint.js +105 -0
- package/dist/cli/steps/add-message-lint.js.map +1 -0
- package/dist/cli/steps/add-message-lint.test.d.ts +1 -0
- package/dist/cli/steps/add-message-lint.test.js +74 -0
- package/dist/cli/steps/add-message-lint.test.js.map +1 -0
- package/dist/cli/steps/add-vite-plugin.d.ts +18 -0
- package/dist/cli/steps/add-vite-plugin.js +34 -6
- package/dist/cli/steps/add-vite-plugin.js.map +1 -1
- package/dist/cli/steps/add-vite-plugin.test.js +25 -9
- package/dist/cli/steps/add-vite-plugin.test.js.map +1 -1
- package/dist/cli/steps/check-for-uncomitted-changes.d.ts +3 -0
- package/dist/cli/steps/check-for-uncomitted-changes.js +15 -3
- package/dist/cli/steps/check-for-uncomitted-changes.js.map +1 -1
- package/dist/cli/steps/detect-bundler.d.ts +1 -0
- package/dist/cli/steps/detect-bundler.js +7 -1
- package/dist/cli/steps/detect-bundler.js.map +1 -1
- package/dist/cli/steps/initialize-inlang-project.d.ts +4 -3
- package/dist/cli/steps/initialize-inlang-project.js +60 -157
- package/dist/cli/steps/initialize-inlang-project.js.map +1 -1
- package/dist/cli/steps/maybe-add-machine-translation.d.ts +4 -0
- package/dist/cli/steps/maybe-add-machine-translation.js +11 -6
- package/dist/cli/steps/maybe-add-machine-translation.js.map +1 -1
- package/dist/cli/steps/maybe-add-sherlock.d.ts +2 -0
- package/dist/cli/steps/maybe-add-sherlock.js +12 -6
- package/dist/cli/steps/maybe-add-sherlock.js.map +1 -1
- package/dist/cli/steps/maybe-add-sherlock.test.d.ts +1 -0
- package/dist/cli/steps/maybe-add-sherlock.test.js +44 -0
- package/dist/cli/steps/maybe-add-sherlock.test.js.map +1 -0
- package/dist/cli/steps/prompt-for-outdir.d.ts +2 -0
- package/dist/cli/steps/prompt-for-outdir.js +4 -0
- package/dist/cli/steps/prompt-for-outdir.js.map +1 -1
- package/dist/cli/steps/update-package-json.js +8 -13
- package/dist/cli/steps/update-package-json.js.map +1 -1
- package/dist/cli/steps/update-ts-config.d.ts +6 -0
- package/dist/cli/steps/update-ts-config.js +27 -4
- package/dist/cli/steps/update-ts-config.js.map +1 -1
- package/dist/cli/utils.d.ts +2 -0
- package/dist/cli/utils.js +6 -0
- package/dist/cli/utils.js.map +1 -1
- package/dist/cli/utils.test.d.ts +1 -0
- package/dist/cli/utils.test.js +16 -0
- package/dist/cli/utils.test.js.map +1 -0
- package/dist/compiler/compile-annotation.js +6 -1
- package/dist/compiler/compile-annotation.js.map +1 -1
- package/dist/compiler/compile-bundle.d.ts +4 -0
- package/dist/compiler/compile-bundle.js +67 -2
- package/dist/compiler/compile-bundle.js.map +1 -1
- package/dist/compiler/compile-bundle.test.js +214 -1
- package/dist/compiler/compile-bundle.test.js.map +1 -1
- package/dist/compiler/compile-lifecycle.test.d.ts +1 -0
- package/dist/compiler/compile-lifecycle.test.js +69 -0
- package/dist/compiler/compile-lifecycle.test.js.map +1 -0
- package/dist/compiler/compile-local-variable.test.js +14 -14
- package/dist/compiler/compile-local-variable.test.js.map +1 -1
- package/dist/compiler/compile-message.exact-number.test.js +1 -1
- package/dist/compiler/compile-message.exact-number.test.js.map +1 -1
- package/dist/compiler/compile-message.locals.test.js +1 -1
- package/dist/compiler/compile-message.locals.test.js.map +1 -1
- package/dist/compiler/compile-message.test.js +2 -2
- package/dist/compiler/compile-message.test.js.map +1 -1
- package/dist/compiler/compile-pattern.test.js +5 -5
- package/dist/compiler/compile-pattern.test.js.map +1 -1
- package/dist/compiler/compile-project.js +1 -0
- package/dist/compiler/compile-project.js.map +1 -1
- package/dist/compiler/compile-project.test.js +94 -1
- package/dist/compiler/compile-project.test.js.map +1 -1
- package/dist/compiler/compile.js +36 -17
- package/dist/compiler/compile.js.map +1 -1
- package/dist/compiler/compile.test.js +70 -0
- package/dist/compiler/compile.test.js.map +1 -1
- package/dist/compiler/compiler-options.d.ts +41 -0
- package/dist/compiler/compiler-options.js.map +1 -1
- package/dist/compiler/output-structure/message-modules.js +1 -1
- package/dist/compiler/output-structure/message-modules.js.map +1 -1
- package/dist/compiler/registry.js +71 -13
- package/dist/compiler/registry.js.map +1 -1
- package/dist/compiler/registry.test.d.ts +1 -0
- package/dist/compiler/registry.test.js +291 -0
- package/dist/compiler/registry.test.js.map +1 -0
- package/dist/compiler/runtime/create-runtime.d.ts +2 -0
- package/dist/compiler/runtime/create-runtime.js +9 -0
- package/dist/compiler/runtime/create-runtime.js.map +1 -1
- package/dist/compiler/runtime/extract-locale-from-cookie.js +8 -1
- package/dist/compiler/runtime/extract-locale-from-cookie.js.map +1 -1
- package/dist/compiler/runtime/extract-locale-from-cookie.test.js +26 -0
- package/dist/compiler/runtime/extract-locale-from-cookie.test.js.map +1 -1
- package/dist/compiler/runtime/extract-locale-from-header.js +47 -5
- package/dist/compiler/runtime/extract-locale-from-header.js.map +1 -1
- package/dist/compiler/runtime/extract-locale-from-header.test.js +58 -0
- package/dist/compiler/runtime/extract-locale-from-header.test.js.map +1 -1
- package/dist/compiler/runtime/get-locale.js +7 -1
- package/dist/compiler/runtime/get-locale.js.map +1 -1
- package/dist/compiler/runtime/get-locale.test.js +95 -0
- package/dist/compiler/runtime/get-locale.test.js.map +1 -1
- package/dist/compiler/runtime/localize-href.d.ts +8 -0
- package/dist/compiler/runtime/localize-href.js +60 -0
- package/dist/compiler/runtime/localize-href.js.map +1 -1
- package/dist/compiler/runtime/localize-href.test.js +227 -1
- package/dist/compiler/runtime/localize-href.test.js.map +1 -1
- package/dist/compiler/runtime/set-locale.js +24 -6
- package/dist/compiler/runtime/set-locale.js.map +1 -1
- package/dist/compiler/runtime/set-locale.test.js +182 -0
- package/dist/compiler/runtime/set-locale.test.js.map +1 -1
- package/dist/compiler/runtime/type.d.ts +2 -0
- package/dist/compiler/runtime/type.js.map +1 -1
- package/dist/compiler/runtime/type.test.js +34 -0
- package/dist/compiler/runtime/type.test.js.map +1 -1
- package/dist/compiler/runtime/variables.d.ts +2 -0
- package/dist/compiler/runtime/variables.js +7 -0
- package/dist/compiler/runtime/variables.js.map +1 -1
- package/dist/compiler/server/middleware.d.ts +8 -2
- package/dist/compiler/server/middleware.js +175 -7
- package/dist/compiler/server/middleware.js.map +1 -1
- package/dist/compiler/server/middleware.test.js +750 -3
- package/dist/compiler/server/middleware.test.js.map +1 -1
- package/dist/eslint/index.d.ts +4 -0
- package/dist/eslint/index.js +8 -0
- package/dist/eslint/index.js.map +1 -0
- package/dist/eslint/no-dynamic-message-access.d.ts +3 -0
- package/dist/eslint/no-dynamic-message-access.js +150 -0
- package/dist/eslint/no-dynamic-message-access.js.map +1 -0
- package/dist/eslint/no-dynamic-message-access.test.d.ts +1 -0
- package/dist/eslint/no-dynamic-message-access.test.js +126 -0
- package/dist/eslint/no-dynamic-message-access.test.js.map +1 -0
- package/dist/eslint/oxlint.test.d.ts +1 -0
- package/dist/eslint/oxlint.test.js +64 -0
- package/dist/eslint/oxlint.test.js.map +1 -0
- package/dist/services/config/config-schema.d.ts +2 -0
- package/dist/services/config/config-schema.js +2 -0
- package/dist/services/config/config-schema.js.map +1 -1
- package/dist/services/config/load-paraglide-config.test.js +12 -0
- package/dist/services/config/load-paraglide-config.test.js.map +1 -1
- package/dist/services/env-variables/index.js +1 -1
- package/dist/services/env-variables/index.js.map +1 -1
- package/dist/services/file-handling/write-output.bench.js +51 -11
- package/dist/services/file-handling/write-output.bench.js.map +1 -1
- package/dist/services/file-handling/write-output.js +60 -20
- package/dist/services/file-handling/write-output.js.map +1 -1
- package/dist/services/file-handling/write-output.test.js +175 -0
- package/dist/services/file-handling/write-output.test.js.map +1 -1
- package/package.json +14 -4
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { prompt } from "../utils.js";
|
|
2
2
|
import JSON5 from "json5";
|
|
3
|
+
import { parseTree, modify, applyEdits } from "jsonc-parser";
|
|
3
4
|
import { pathExists } from "../../services/file-handling/exists.js";
|
|
4
5
|
import nodePath from "node:path";
|
|
5
6
|
import { createRequire } from "node:module";
|
|
@@ -13,13 +14,20 @@ export const maybeUpdateTsConfig = async (ctx) => {
|
|
|
13
14
|
* Paraligde JS compiles to JS with JSDoc comments. TypeScript doesn't allow JS files by default.
|
|
14
15
|
*/
|
|
15
16
|
export const maybeUpdateTsConfigAllowJs = async (ctx) => {
|
|
16
|
-
|
|
17
|
+
const configPath = nodePath.resolve(ctx.root ?? process.cwd(), "tsconfig.json");
|
|
18
|
+
if ((await pathExists(configPath, ctx.fs)) === false) {
|
|
17
19
|
return ctx;
|
|
18
20
|
}
|
|
19
|
-
if (await hasAllowJsEnabled(
|
|
21
|
+
if (await hasAllowJsEnabled(configPath, ctx.fs)) {
|
|
20
22
|
// all clear, allowJs is already set to true
|
|
21
23
|
return ctx;
|
|
22
24
|
}
|
|
25
|
+
if (ctx.interactive === false) {
|
|
26
|
+
const text = await ctx.fs.readFile(configPath, "utf8");
|
|
27
|
+
await ctx.fs.writeFile(configPath, enableAllowJs(text));
|
|
28
|
+
ctx.logger.success("Enabled compilerOptions.allowJs in tsconfig.json.");
|
|
29
|
+
return ctx;
|
|
30
|
+
}
|
|
23
31
|
ctx.logger.info(`The option \`compilerOptions.allowJs\` needs to be set to \`true\` in the \`tsconfig.json\` file:
|
|
24
32
|
|
|
25
33
|
\`{
|
|
@@ -37,7 +45,7 @@ export const maybeUpdateTsConfigAllowJs = async (ctx) => {
|
|
|
37
45
|
ctx.logger.warn("Continuing without adjusting the tsconfig.json. This may lead to type errors.");
|
|
38
46
|
return ctx;
|
|
39
47
|
}
|
|
40
|
-
if (await hasAllowJsEnabled(
|
|
48
|
+
if (await hasAllowJsEnabled(configPath, ctx.fs)) {
|
|
41
49
|
isValid = true;
|
|
42
50
|
return ctx;
|
|
43
51
|
}
|
|
@@ -180,7 +188,7 @@ const resolveReferenceConfig = async (referenceSpecifier, baseDir, fs) => {
|
|
|
180
188
|
// * errors with Paraglide-JS.
|
|
181
189
|
// */
|
|
182
190
|
// const maybeUpdateTsConfigModuleResolution: CliStep<
|
|
183
|
-
// { fs: typeof import("node:fs/promises"); logger: Logger },
|
|
191
|
+
// { fs: typeof import("node:fs/promises"); logger: Logger; interactive?: boolean; root?: string },
|
|
184
192
|
// unknown
|
|
185
193
|
// > = async (ctx) => {
|
|
186
194
|
// if ((await pathExists("./tsconfig.json", ctx.fs)) === false) {
|
|
@@ -267,4 +275,19 @@ const resolveReferenceConfig = async (referenceSpecifier, baseDir, fs) => {
|
|
|
267
275
|
// }
|
|
268
276
|
// return ctx;
|
|
269
277
|
// };
|
|
278
|
+
/** Edit one property while retaining comments and unrelated configuration text. */
|
|
279
|
+
export function enableAllowJs(text) {
|
|
280
|
+
const errors = [];
|
|
281
|
+
const tree = parseTree(text, errors, { allowTrailingComma: true });
|
|
282
|
+
if (errors.length || tree?.type !== "object")
|
|
283
|
+
throw new Error("tsconfig.json must be a valid JSON-with-comments object.");
|
|
284
|
+
const indent = text.match(/\n([ \t]+)"/)?.[1] ?? " ";
|
|
285
|
+
return applyEdits(text, modify(text, ["compilerOptions", "allowJs"], true, {
|
|
286
|
+
formattingOptions: {
|
|
287
|
+
insertSpaces: !indent.includes("\t"),
|
|
288
|
+
tabSize: indent.length,
|
|
289
|
+
eol: text.includes("\r\n") ? "\r\n" : "\n",
|
|
290
|
+
},
|
|
291
|
+
}));
|
|
292
|
+
}
|
|
270
293
|
//# sourceMappingURL=update-ts-config.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"update-ts-config.js","sourceRoot":"","sources":["../../../src/cli/steps/update-ts-config.ts"],"names":[],"mappings":"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","sourcesContent":["import type { CliStep } from \"../utils.js\";\nimport type { Logger } from \"../../services/logger/index.js\";\nimport { prompt } from \"../utils.js\";\nimport JSON5 from \"json5\";\nimport { pathExists } from \"../../services/file-handling/exists.js\";\nimport nodePath from \"node:path\";\nimport { createRequire } from \"node:module\";\n\nconst require = createRequire(import.meta.url);\n\nexport const maybeUpdateTsConfig: CliStep<\n\t{ fs: typeof import(\"node:fs/promises\"); logger: Logger },\n\tunknown\n> = async (ctx) => {\n\tconst ctx1 = await maybeUpdateTsConfigAllowJs(ctx);\n\treturn ctx1;\n\t// return await maybeUpdateTsConfigModuleResolution(ctx1);\n};\n\n/**\n * Paraligde JS compiles to JS with JSDoc comments. TypeScript doesn't allow JS files by default.\n */\nexport const maybeUpdateTsConfigAllowJs: CliStep<\n\t{ fs: typeof import(\"node:fs/promises\"); logger: Logger },\n\tunknown\n> = async (ctx) => {\n\tif ((await pathExists(\"./tsconfig.json\", ctx.fs)) === false) {\n\t\treturn ctx;\n\t}\n\tif (await hasAllowJsEnabled(\"./tsconfig.json\", ctx.fs)) {\n\t\t// all clear, allowJs is already set to true\n\t\treturn ctx;\n\t}\n\n\tctx.logger.info(\n\t\t`The option \\`compilerOptions.allowJs\\` needs to be set to \\`true\\` in the \\`tsconfig.json\\` file:\n\n\\`{\n \"compilerOptions\": {\n \"allowJs\": true\n }\n}\\``\n\t);\n\tlet isValid = false;\n\twhile (isValid === false) {\n\t\tconst response = await prompt(\n\t\t\t`Is \\`compilerOptions.allowJs\\` set to \\`true\\`?`,\n\t\t\t{\n\t\t\t\ttype: \"confirm\",\n\t\t\t\tinitial: true,\n\t\t\t}\n\t\t);\n\t\tif (response === false) {\n\t\t\tctx.logger.warn(\n\t\t\t\t\"Continuing without adjusting the tsconfig.json. This may lead to type errors.\"\n\t\t\t);\n\t\t\treturn ctx;\n\t\t}\n\n\t\tif (await hasAllowJsEnabled(\"./tsconfig.json\", ctx.fs)) {\n\t\t\tisValid = true;\n\t\t\treturn ctx;\n\t\t} else {\n\t\t\tctx.logger.error(\n\t\t\t\t\"The compiler options has not been adjusted. Please sets `compilerOptions.allowJs` to `true`.\"\n\t\t\t);\n\t\t}\n\t}\n\treturn ctx;\n};\n\n/**\n * Recursively checks whether allowJs is enabled in the provided tsconfig or any\n * referenced configuration files.\n *\n * @param tsconfigPath The path to the tsconfig to inspect.\n * @param fs The file system used to read the configs.\n * @param visited A set of already inspected files to avoid circular lookups.\n * @example\n * ```ts\n * await hasAllowJsEnabled(\"./tsconfig.json\", fs);\n * ```\n */\nexport const hasAllowJsEnabled = async (\n\ttsconfigPath: string,\n\tfs: typeof import(\"node:fs/promises\"),\n\tvisited: Set<string> = new Set()\n): Promise<boolean> => {\n\tconst normalizedPath = normalizeConfigPath(tsconfigPath);\n\n\tif (visited.has(normalizedPath)) {\n\t\treturn false;\n\t}\n\n\tvisited.add(normalizedPath);\n\n\tconst file = await fs.readFile(normalizedPath, { encoding: \"utf-8\" });\n\tconst tsconfig = JSON5.parse(file);\n\n\tif (tsconfig?.compilerOptions?.allowJs === true) {\n\t\treturn true;\n\t}\n\n\tconst baseDir = nodePath.dirname(normalizedPath);\n\n\tconst extendCandidates = Array.isArray(tsconfig?.extends)\n\t\t? tsconfig.extends\n\t\t: tsconfig?.extends\n\t\t\t? [tsconfig.extends]\n\t\t\t: [];\n\n\tfor (const candidate of extendCandidates) {\n\t\tif (typeof candidate !== \"string\") continue;\n\t\tconst resolved = await resolveExtendedConfig(candidate, baseDir, fs);\n\t\tif (resolved && (await hasAllowJsEnabled(resolved, fs, visited))) {\n\t\t\treturn true;\n\t\t}\n\t}\n\n\tif (Array.isArray(tsconfig?.references)) {\n\t\tfor (const reference of tsconfig.references) {\n\t\t\tconst referencePath = reference?.path;\n\t\t\tif (typeof referencePath !== \"string\") continue;\n\t\t\tconst resolved = await resolveReferenceConfig(referencePath, baseDir, fs);\n\t\t\tif (resolved && (await hasAllowJsEnabled(resolved, fs, visited))) {\n\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\t}\n\n\treturn false;\n};\n\n/**\n * Normalizes a tsconfig path to an absolute path.\n */\nconst normalizeConfigPath = (configPath: string): string => {\n\treturn nodePath.isAbsolute(configPath)\n\t\t? configPath\n\t\t: nodePath.resolve(process.cwd(), configPath);\n};\n\n/**\n * Resolves the extended tsconfig path relative to the base config.\n */\nconst resolveExtendedConfig = async (\n\textendsSpecifier: string,\n\tbaseDir: string,\n\tfs: typeof import(\"node:fs/promises\")\n): Promise<string | undefined> => {\n\tconst candidates = new Set<string>();\n\tconst resolvedBase = nodePath.isAbsolute(extendsSpecifier)\n\t\t? extendsSpecifier\n\t\t: nodePath.resolve(baseDir, extendsSpecifier);\n\tcandidates.add(resolvedBase);\n\n\tif (nodePath.extname(resolvedBase) === \"\") {\n\t\tcandidates.add(`${resolvedBase}.json`);\n\t\tcandidates.add(nodePath.join(resolvedBase, \"tsconfig.json\"));\n\t}\n\n\tfor (const candidate of candidates) {\n\t\tif (await pathExists(candidate, fs)) {\n\t\t\treturn candidate;\n\t\t}\n\t}\n\n\ttry {\n\t\treturn require.resolve(extendsSpecifier, { paths: [baseDir] });\n\t} catch {\n\t\tif (extendsSpecifier.endsWith(\".json\") === false) {\n\t\t\ttry {\n\t\t\t\treturn require.resolve(`${extendsSpecifier}.json`, {\n\t\t\t\t\tpaths: [baseDir],\n\t\t\t\t});\n\t\t\t} catch {\n\t\t\t\treturn undefined;\n\t\t\t}\n\t\t}\n\t}\n\n\treturn undefined;\n};\n\n/**\n * Resolves the tsconfig referenced through the `references` property.\n */\nconst resolveReferenceConfig = async (\n\treferenceSpecifier: string,\n\tbaseDir: string,\n\tfs: typeof import(\"node:fs/promises\")\n): Promise<string | undefined> => {\n\tconst candidates = new Set<string>();\n\tconst resolvedBase = nodePath.isAbsolute(referenceSpecifier)\n\t\t? referenceSpecifier\n\t\t: nodePath.resolve(baseDir, referenceSpecifier);\n\tcandidates.add(resolvedBase);\n\n\tif (nodePath.extname(resolvedBase) === \"\") {\n\t\tcandidates.add(`${resolvedBase}.json`);\n\t\tcandidates.add(nodePath.join(resolvedBase, \"tsconfig.json\"));\n\t}\n\n\tfor (const candidate of candidates) {\n\t\tif (await pathExists(candidate, fs)) {\n\t\t\ttry {\n\t\t\t\tconst stats = await fs.stat(candidate);\n\t\t\t\tif (stats.isDirectory()) {\n\t\t\t\t\tconst directoryConfig = nodePath.join(candidate, \"tsconfig.json\");\n\t\t\t\t\tif (await pathExists(directoryConfig, fs)) {\n\t\t\t\t\t\treturn directoryConfig;\n\t\t\t\t\t}\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t} catch {\n\t\t\t\t// ignore, we'll continue checking other candidates\n\t\t\t}\n\t\t\treturn candidate;\n\t\t}\n\t}\n\n\treturn undefined;\n};\n\n// /**\n// * Ensures that the moduleResolution compiler option is set to \"bundler\" or similar in the tsconfig.json.\n// *\n// * Otherwise, types defined in `package.exports` are not resolved by TypeScript. Leading to type\n// * errors with Paraglide-JS.\n// */\n// const maybeUpdateTsConfigModuleResolution: CliStep<\n// \t{ fs: typeof import(\"node:fs/promises\"); logger: Logger },\n// \tunknown\n// > = async (ctx) => {\n// \tif ((await pathExists(\"./tsconfig.json\", ctx.fs)) === false) {\n// \t\treturn ctx;\n// \t}\n// \tconst file = await ctx.fs.readFile(\"./tsconfig.json\", {\n// \t\tencoding: \"utf-8\",\n// \t});\n// \t// tsconfig allows comments ... FML\n// \tlet tsconfig = JSON5.parse(file);\n\n// \tlet parentTsConfig: any | undefined;\n\n// \tif (tsconfig.extends) {\n// \t\ttry {\n// \t\t\tconst parentTsConfigPath = nodePath.resolve(\n// \t\t\t\tprocess.cwd(),\n// \t\t\t\ttsconfig.extends\n// \t\t\t);\n// \t\t\tconst parentTsConfigFile = await ctx.fs.readFile(parentTsConfigPath, {\n// \t\t\t\tencoding: \"utf-8\",\n// \t\t\t});\n// \t\t\tparentTsConfig = JSON5.parse(parentTsConfigFile);\n// \t\t} catch {\n// \t\t\tctx.logger.warn(\n// \t\t\t\t`The tsconfig.json is extended from a tsconfig that couldn't be read. Maybe the file doesn't exist yet or is a NPM package. Continuing without taking the extended from tsconfig into consideration.`\n// \t\t\t);\n// \t\t}\n// \t}\n\n// \t// options that don't support package.exports\n// \tconst invalidOptions = [\"classic\", \"node\", \"node10\"];\n// \tconst moduleResolution =\n// \t\ttsconfig.compilerOptions?.moduleResolution ??\n// \t\tparentTsConfig?.compilerOptions?.moduleResolution;\n\n// \tif (\n// \t\tmoduleResolution &&\n// \t\tinvalidOptions.includes(moduleResolution.toLowerCase()) === false\n// \t) {\n// \t\t// the moduleResolution is already set to bundler or similar\n// \t\treturn ctx;\n// \t}\n\n// \tctx.logger.info(\n// \t\t`The \\`compilerOptions.moduleResolution\\` options must be set to \"Bundler\" in the \\`tsconfig.json\\` file:\n\n// \\`{\n// \"compilerOptions\": {\n// \"moduleResolution\": \"Bundler\"\n// }\n// }\\``\n// \t);\n// \tlet isValid = false;\n// \twhile (isValid === false) {\n// \t\tconst response = await prompt(\n// \t\t\t`Is \\`compilerOptions.moduleResolution\\` set to \"Bundler\"?`,\n// \t\t\t{\n// \t\t\t\ttype: \"confirm\",\n// \t\t\t\tinitial: true,\n// \t\t\t}\n// \t\t);\n// \t\tif (response === false) {\n// \t\t\tctx.logger.warn(\n// \t\t\t\t\"Continuing without adjusting the tsconfig.json. This may lead to type errors.\"\n// \t\t\t);\n// \t\t\treturn ctx;\n// \t\t}\n\n// \t\t// don't re-ask the question if there is an `extends` present in the tsconfig\n// \t\t// just trust that it's correct.\n// \t\tif (tsconfig.extends) {\n// \t\t\tisValid = true;\n// \t\t\treturn ctx;\n// \t\t}\n\n// \t\tconst file = await ctx.fs.readFile(\"./tsconfig.json\", {\n// \t\t\tencoding: \"utf-8\",\n// \t\t});\n// \t\ttsconfig = JSON5.parse(file);\n// \t\tif (\n// \t\t\ttsconfig?.compilerOptions?.moduleResolution &&\n// \t\t\ttsconfig.compilerOptions.moduleResolution.toLowerCase() === \"bundler\"\n// \t\t) {\n// \t\t\tisValid = true;\n// \t\t\treturn ctx;\n// \t\t} else {\n// \t\t\tctx.logger.error(\n// \t\t\t\t\"The compiler options have not been adjusted. Please set the `compilerOptions.moduleResolution` to `Bundler`.\"\n// \t\t\t);\n// \t\t}\n// \t}\n\n// \treturn ctx;\n// };\n"]}
|
|
1
|
+
{"version":3,"file":"update-ts-config.js","sourceRoot":"","sources":["../../../src/cli/steps/update-ts-config.ts"],"names":[],"mappings":"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","sourcesContent":["import type { CliStep } from \"../utils.js\";\nimport type { Logger } from \"../../services/logger/index.js\";\nimport { prompt } from \"../utils.js\";\nimport JSON5 from \"json5\";\nimport { parseTree, modify, applyEdits, type ParseError } from \"jsonc-parser\";\nimport { pathExists } from \"../../services/file-handling/exists.js\";\nimport nodePath from \"node:path\";\nimport { createRequire } from \"node:module\";\n\nconst require = createRequire(import.meta.url);\n\nexport const maybeUpdateTsConfig: CliStep<\n\t{\n\t\tfs: typeof import(\"node:fs/promises\");\n\t\tlogger: Logger;\n\t\tinteractive?: boolean;\n\t\troot?: string;\n\t},\n\tunknown\n> = async (ctx) => {\n\tconst ctx1 = await maybeUpdateTsConfigAllowJs(ctx);\n\treturn ctx1;\n\t// return await maybeUpdateTsConfigModuleResolution(ctx1);\n};\n\n/**\n * Paraligde JS compiles to JS with JSDoc comments. TypeScript doesn't allow JS files by default.\n */\nexport const maybeUpdateTsConfigAllowJs: CliStep<\n\t{\n\t\tfs: typeof import(\"node:fs/promises\");\n\t\tlogger: Logger;\n\t\tinteractive?: boolean;\n\t\troot?: string;\n\t},\n\tunknown\n> = async (ctx) => {\n\tconst configPath = nodePath.resolve(\n\t\tctx.root ?? process.cwd(),\n\t\t\"tsconfig.json\"\n\t);\n\tif ((await pathExists(configPath, ctx.fs)) === false) {\n\t\treturn ctx;\n\t}\n\tif (await hasAllowJsEnabled(configPath, ctx.fs)) {\n\t\t// all clear, allowJs is already set to true\n\t\treturn ctx;\n\t}\n\n\tif (ctx.interactive === false) {\n\t\tconst text = await ctx.fs.readFile(configPath, \"utf8\");\n\t\tawait ctx.fs.writeFile(configPath, enableAllowJs(text));\n\t\tctx.logger.success(\"Enabled compilerOptions.allowJs in tsconfig.json.\");\n\t\treturn ctx;\n\t}\n\n\tctx.logger.info(\n\t\t`The option \\`compilerOptions.allowJs\\` needs to be set to \\`true\\` in the \\`tsconfig.json\\` file:\n\n\\`{\n \"compilerOptions\": {\n \"allowJs\": true\n }\n}\\``\n\t);\n\tlet isValid = false;\n\twhile (isValid === false) {\n\t\tconst response = await prompt(\n\t\t\t`Is \\`compilerOptions.allowJs\\` set to \\`true\\`?`,\n\t\t\t{\n\t\t\t\ttype: \"confirm\",\n\t\t\t\tinitial: true,\n\t\t\t}\n\t\t);\n\t\tif (response === false) {\n\t\t\tctx.logger.warn(\n\t\t\t\t\"Continuing without adjusting the tsconfig.json. This may lead to type errors.\"\n\t\t\t);\n\t\t\treturn ctx;\n\t\t}\n\n\t\tif (await hasAllowJsEnabled(configPath, ctx.fs)) {\n\t\t\tisValid = true;\n\t\t\treturn ctx;\n\t\t} else {\n\t\t\tctx.logger.error(\n\t\t\t\t\"The compiler options has not been adjusted. Please sets `compilerOptions.allowJs` to `true`.\"\n\t\t\t);\n\t\t}\n\t}\n\treturn ctx;\n};\n\n/**\n * Recursively checks whether allowJs is enabled in the provided tsconfig or any\n * referenced configuration files.\n *\n * @param tsconfigPath The path to the tsconfig to inspect.\n * @param fs The file system used to read the configs.\n * @param visited A set of already inspected files to avoid circular lookups.\n * @example\n * ```ts\n * await hasAllowJsEnabled(\"./tsconfig.json\", fs);\n * ```\n */\nexport const hasAllowJsEnabled = async (\n\ttsconfigPath: string,\n\tfs: typeof import(\"node:fs/promises\"),\n\tvisited: Set<string> = new Set()\n): Promise<boolean> => {\n\tconst normalizedPath = normalizeConfigPath(tsconfigPath);\n\n\tif (visited.has(normalizedPath)) {\n\t\treturn false;\n\t}\n\n\tvisited.add(normalizedPath);\n\n\tconst file = await fs.readFile(normalizedPath, { encoding: \"utf-8\" });\n\tconst tsconfig = JSON5.parse(file);\n\n\tif (tsconfig?.compilerOptions?.allowJs === true) {\n\t\treturn true;\n\t}\n\n\tconst baseDir = nodePath.dirname(normalizedPath);\n\n\tconst extendCandidates = Array.isArray(tsconfig?.extends)\n\t\t? tsconfig.extends\n\t\t: tsconfig?.extends\n\t\t\t? [tsconfig.extends]\n\t\t\t: [];\n\n\tfor (const candidate of extendCandidates) {\n\t\tif (typeof candidate !== \"string\") continue;\n\t\tconst resolved = await resolveExtendedConfig(candidate, baseDir, fs);\n\t\tif (resolved && (await hasAllowJsEnabled(resolved, fs, visited))) {\n\t\t\treturn true;\n\t\t}\n\t}\n\n\tif (Array.isArray(tsconfig?.references)) {\n\t\tfor (const reference of tsconfig.references) {\n\t\t\tconst referencePath = reference?.path;\n\t\t\tif (typeof referencePath !== \"string\") continue;\n\t\t\tconst resolved = await resolveReferenceConfig(referencePath, baseDir, fs);\n\t\t\tif (resolved && (await hasAllowJsEnabled(resolved, fs, visited))) {\n\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\t}\n\n\treturn false;\n};\n\n/**\n * Normalizes a tsconfig path to an absolute path.\n */\nconst normalizeConfigPath = (configPath: string): string => {\n\treturn nodePath.isAbsolute(configPath)\n\t\t? configPath\n\t\t: nodePath.resolve(process.cwd(), configPath);\n};\n\n/**\n * Resolves the extended tsconfig path relative to the base config.\n */\nconst resolveExtendedConfig = async (\n\textendsSpecifier: string,\n\tbaseDir: string,\n\tfs: typeof import(\"node:fs/promises\")\n): Promise<string | undefined> => {\n\tconst candidates = new Set<string>();\n\tconst resolvedBase = nodePath.isAbsolute(extendsSpecifier)\n\t\t? extendsSpecifier\n\t\t: nodePath.resolve(baseDir, extendsSpecifier);\n\tcandidates.add(resolvedBase);\n\n\tif (nodePath.extname(resolvedBase) === \"\") {\n\t\tcandidates.add(`${resolvedBase}.json`);\n\t\tcandidates.add(nodePath.join(resolvedBase, \"tsconfig.json\"));\n\t}\n\n\tfor (const candidate of candidates) {\n\t\tif (await pathExists(candidate, fs)) {\n\t\t\treturn candidate;\n\t\t}\n\t}\n\n\ttry {\n\t\treturn require.resolve(extendsSpecifier, { paths: [baseDir] });\n\t} catch {\n\t\tif (extendsSpecifier.endsWith(\".json\") === false) {\n\t\t\ttry {\n\t\t\t\treturn require.resolve(`${extendsSpecifier}.json`, {\n\t\t\t\t\tpaths: [baseDir],\n\t\t\t\t});\n\t\t\t} catch {\n\t\t\t\treturn undefined;\n\t\t\t}\n\t\t}\n\t}\n\n\treturn undefined;\n};\n\n/**\n * Resolves the tsconfig referenced through the `references` property.\n */\nconst resolveReferenceConfig = async (\n\treferenceSpecifier: string,\n\tbaseDir: string,\n\tfs: typeof import(\"node:fs/promises\")\n): Promise<string | undefined> => {\n\tconst candidates = new Set<string>();\n\tconst resolvedBase = nodePath.isAbsolute(referenceSpecifier)\n\t\t? referenceSpecifier\n\t\t: nodePath.resolve(baseDir, referenceSpecifier);\n\tcandidates.add(resolvedBase);\n\n\tif (nodePath.extname(resolvedBase) === \"\") {\n\t\tcandidates.add(`${resolvedBase}.json`);\n\t\tcandidates.add(nodePath.join(resolvedBase, \"tsconfig.json\"));\n\t}\n\n\tfor (const candidate of candidates) {\n\t\tif (await pathExists(candidate, fs)) {\n\t\t\ttry {\n\t\t\t\tconst stats = await fs.stat(candidate);\n\t\t\t\tif (stats.isDirectory()) {\n\t\t\t\t\tconst directoryConfig = nodePath.join(candidate, \"tsconfig.json\");\n\t\t\t\t\tif (await pathExists(directoryConfig, fs)) {\n\t\t\t\t\t\treturn directoryConfig;\n\t\t\t\t\t}\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t} catch {\n\t\t\t\t// ignore, we'll continue checking other candidates\n\t\t\t}\n\t\t\treturn candidate;\n\t\t}\n\t}\n\n\treturn undefined;\n};\n\n// /**\n// * Ensures that the moduleResolution compiler option is set to \"bundler\" or similar in the tsconfig.json.\n// *\n// * Otherwise, types defined in `package.exports` are not resolved by TypeScript. Leading to type\n// * errors with Paraglide-JS.\n// */\n// const maybeUpdateTsConfigModuleResolution: CliStep<\n// \t{ fs: typeof import(\"node:fs/promises\"); logger: Logger; interactive?: boolean; root?: string },\n// \tunknown\n// > = async (ctx) => {\n// \tif ((await pathExists(\"./tsconfig.json\", ctx.fs)) === false) {\n// \t\treturn ctx;\n// \t}\n// \tconst file = await ctx.fs.readFile(\"./tsconfig.json\", {\n// \t\tencoding: \"utf-8\",\n// \t});\n// \t// tsconfig allows comments ... FML\n// \tlet tsconfig = JSON5.parse(file);\n\n// \tlet parentTsConfig: any | undefined;\n\n// \tif (tsconfig.extends) {\n// \t\ttry {\n// \t\t\tconst parentTsConfigPath = nodePath.resolve(\n// \t\t\t\tprocess.cwd(),\n// \t\t\t\ttsconfig.extends\n// \t\t\t);\n// \t\t\tconst parentTsConfigFile = await ctx.fs.readFile(parentTsConfigPath, {\n// \t\t\t\tencoding: \"utf-8\",\n// \t\t\t});\n// \t\t\tparentTsConfig = JSON5.parse(parentTsConfigFile);\n// \t\t} catch {\n// \t\t\tctx.logger.warn(\n// \t\t\t\t`The tsconfig.json is extended from a tsconfig that couldn't be read. Maybe the file doesn't exist yet or is a NPM package. Continuing without taking the extended from tsconfig into consideration.`\n// \t\t\t);\n// \t\t}\n// \t}\n\n// \t// options that don't support package.exports\n// \tconst invalidOptions = [\"classic\", \"node\", \"node10\"];\n// \tconst moduleResolution =\n// \t\ttsconfig.compilerOptions?.moduleResolution ??\n// \t\tparentTsConfig?.compilerOptions?.moduleResolution;\n\n// \tif (\n// \t\tmoduleResolution &&\n// \t\tinvalidOptions.includes(moduleResolution.toLowerCase()) === false\n// \t) {\n// \t\t// the moduleResolution is already set to bundler or similar\n// \t\treturn ctx;\n// \t}\n\n// \tctx.logger.info(\n// \t\t`The \\`compilerOptions.moduleResolution\\` options must be set to \"Bundler\" in the \\`tsconfig.json\\` file:\n\n// \\`{\n// \"compilerOptions\": {\n// \"moduleResolution\": \"Bundler\"\n// }\n// }\\``\n// \t);\n// \tlet isValid = false;\n// \twhile (isValid === false) {\n// \t\tconst response = await prompt(\n// \t\t\t`Is \\`compilerOptions.moduleResolution\\` set to \"Bundler\"?`,\n// \t\t\t{\n// \t\t\t\ttype: \"confirm\",\n// \t\t\t\tinitial: true,\n// \t\t\t}\n// \t\t);\n// \t\tif (response === false) {\n// \t\t\tctx.logger.warn(\n// \t\t\t\t\"Continuing without adjusting the tsconfig.json. This may lead to type errors.\"\n// \t\t\t);\n// \t\t\treturn ctx;\n// \t\t}\n\n// \t\t// don't re-ask the question if there is an `extends` present in the tsconfig\n// \t\t// just trust that it's correct.\n// \t\tif (tsconfig.extends) {\n// \t\t\tisValid = true;\n// \t\t\treturn ctx;\n// \t\t}\n\n// \t\tconst file = await ctx.fs.readFile(\"./tsconfig.json\", {\n// \t\t\tencoding: \"utf-8\",\n// \t\t});\n// \t\ttsconfig = JSON5.parse(file);\n// \t\tif (\n// \t\t\ttsconfig?.compilerOptions?.moduleResolution &&\n// \t\t\ttsconfig.compilerOptions.moduleResolution.toLowerCase() === \"bundler\"\n// \t\t) {\n// \t\t\tisValid = true;\n// \t\t\treturn ctx;\n// \t\t} else {\n// \t\t\tctx.logger.error(\n// \t\t\t\t\"The compiler options have not been adjusted. Please set the `compilerOptions.moduleResolution` to `Bundler`.\"\n// \t\t\t);\n// \t\t}\n// \t}\n\n// \treturn ctx;\n// };\n\n/** Edit one property while retaining comments and unrelated configuration text. */\nexport function enableAllowJs(text: string): string {\n\tconst errors: ParseError[] = [];\n\tconst tree = parseTree(text, errors, { allowTrailingComma: true });\n\tif (errors.length || tree?.type !== \"object\")\n\t\tthrow new Error(\"tsconfig.json must be a valid JSON-with-comments object.\");\n\tconst indent = text.match(/\\n([ \\t]+)\"/)?.[1] ?? \" \";\n\treturn applyEdits(\n\t\ttext,\n\t\tmodify(text, [\"compilerOptions\", \"allowJs\"], true, {\n\t\t\tformattingOptions: {\n\t\t\t\tinsertSpaces: !indent.includes(\"\\t\"),\n\t\t\t\ttabSize: indent.length,\n\t\t\t\teol: text.includes(\"\\r\\n\") ? \"\\r\\n\" : \"\\n\",\n\t\t\t},\n\t\t})\n\t);\n}\n"]}
|
package/dist/cli/utils.d.ts
CHANGED
|
@@ -43,3 +43,5 @@ export declare const promptSelection: <T extends string>(message: string, option
|
|
|
43
43
|
* toRelativeDisplayPath("/app", "/app/src/paraglide") // "src/paraglide"
|
|
44
44
|
*/
|
|
45
45
|
export declare function toRelativeDisplayPath(root: string, path: string): string;
|
|
46
|
+
/** Quote package-script arguments containing shell metacharacters. */
|
|
47
|
+
export declare function shellArgument(value: string): string;
|
package/dist/cli/utils.js
CHANGED
|
@@ -32,4 +32,10 @@ export function toRelativeDisplayPath(root, path) {
|
|
|
32
32
|
.split(nodePath.sep)
|
|
33
33
|
.join("/");
|
|
34
34
|
}
|
|
35
|
+
/** Quote package-script arguments containing shell metacharacters. */
|
|
36
|
+
export function shellArgument(value) {
|
|
37
|
+
return /^[A-Za-z0-9_./-]+$/.test(value)
|
|
38
|
+
? value
|
|
39
|
+
: "'" + value.replaceAll("'", `'"'"'`) + "'";
|
|
40
|
+
}
|
|
35
41
|
//# sourceMappingURL=utils.js.map
|
package/dist/cli/utils.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"utils.js","sourceRoot":"","sources":["../../src/cli/utils.ts"],"names":[],"mappings":"AAAA,OAAO,OAAO,MAAM,SAAS,CAAC;AAC9B,OAAO,QAAQ,MAAM,WAAW,CAAC;AA6BjC;;GAEG;AACH,MAAM,CAAC,MAAM,MAAM,GAA0B,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,EAAE;IACvE,MAAM,QAAQ,GAAG,MAAM,OAAO,CAAC,MAAM,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;IACxD,IAAI,QAAQ,EAAE,QAAQ,EAAE,KAAK,sBAAsB,EAAE,CAAC;QACrD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IACjB,CAAC;IACD,OAAO,QAAQ,CAAC;AACjB,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,eAAe,GAAG,KAAK,EACnC,OAAe,EACf,OAAO,GAA4D;IAClE,OAAO,EAAE,EAAE;CACX,EACY,EAAE;IACf,OAAO,MAAM,CAAC,OAAO,EAAE;QACtB,IAAI,EAAE,QAAQ;QACd,GAAG,OAAO;KACV,CAA0B,CAAC;AAC7B,CAAC,CAAC;AAEF;;;;;;;GAOG;AACH,MAAM,UAAU,qBAAqB,CAAC,IAAY,EAAE,IAAY;IAC/D,OAAO,QAAQ;SACb,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAC,OAAO,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;SAC5C,KAAK,CAAC,QAAQ,CAAC,GAAG,CAAC;SACnB,IAAI,CAAC,GAAG,CAAC,CAAC;AACb,CAAC","sourcesContent":["import consola from \"consola\";\nimport nodePath from \"node:path\";\n\n/**\n * One step in a CLI chain.\n * Defines which types the context needs to extend and how it extends the context\n *\n * Cli Steps can be chained to slowly build up the context over time\n *\n * @example\n * ```ts\n * const step1: CliStep<unknown, { foo: string }> = async (ctx) => {\n * return {...ctx, foo: \"hello\" }\n * }\n *\n * const step2: CliStep<{ foo: string }, { bar: number }> = async (ctx) => {\n * return { ...ctx, bar: 42 }\n * }\n *\n * const initial = { baz: \"baz\" } as const;\n * const ctx1 = await step1(initial);\n * const ctx2 = await step2(ctx1);\n *\n * ctx2 // Has type { foo: string, bar: number, baz: \"baz\" }\n * ```\n */\nexport type CliStep<In extends object, Out> = <Ctx extends In>(\n\tctx: Ctx\n) => Promise<Ctx & Out>;\n\n/**\n * Wrapper to exit the process if the user presses CTRL+C.\n */\nexport const prompt: typeof consola.prompt = async (message, options) => {\n\tconst response = await consola.prompt(message, options);\n\tif (response?.toString() === \"Symbol(clack:cancel)\") {\n\t\tprocess.exit(0);\n\t}\n\treturn response;\n};\n\nexport const promptSelection = async <T extends string>(\n\tmessage: string,\n\toptions: { initial?: T; options: { label: string; value: T }[] } = {\n\t\toptions: [],\n\t}\n): Promise<T> => {\n\treturn prompt(message, {\n\t\ttype: \"select\",\n\t\t...options,\n\t}) as unknown as Promise<T>;\n};\n\n/**\n * A path relative to `root` with forward slashes and without a leading `./`,\n * for messages and package.json scripts.\n *\n * @example\n * toRelativeDisplayPath(\"/app\", \"./project.inlang\") // \"project.inlang\"\n * toRelativeDisplayPath(\"/app\", \"/app/src/paraglide\") // \"src/paraglide\"\n */\nexport function toRelativeDisplayPath(root: string, path: string): string {\n\treturn nodePath\n\t\t.relative(root, nodePath.resolve(root, path))\n\t\t.split(nodePath.sep)\n\t\t.join(\"/\");\n}\n"]}
|
|
1
|
+
{"version":3,"file":"utils.js","sourceRoot":"","sources":["../../src/cli/utils.ts"],"names":[],"mappings":"AAAA,OAAO,OAAO,MAAM,SAAS,CAAC;AAC9B,OAAO,QAAQ,MAAM,WAAW,CAAC;AA6BjC;;GAEG;AACH,MAAM,CAAC,MAAM,MAAM,GAA0B,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,EAAE;IACvE,MAAM,QAAQ,GAAG,MAAM,OAAO,CAAC,MAAM,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;IACxD,IAAI,QAAQ,EAAE,QAAQ,EAAE,KAAK,sBAAsB,EAAE,CAAC;QACrD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IACjB,CAAC;IACD,OAAO,QAAQ,CAAC;AACjB,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,eAAe,GAAG,KAAK,EACnC,OAAe,EACf,OAAO,GAA4D;IAClE,OAAO,EAAE,EAAE;CACX,EACY,EAAE;IACf,OAAO,MAAM,CAAC,OAAO,EAAE;QACtB,IAAI,EAAE,QAAQ;QACd,GAAG,OAAO;KACV,CAA0B,CAAC;AAC7B,CAAC,CAAC;AAEF;;;;;;;GAOG;AACH,MAAM,UAAU,qBAAqB,CAAC,IAAY,EAAE,IAAY;IAC/D,OAAO,QAAQ;SACb,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAC,OAAO,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;SAC5C,KAAK,CAAC,QAAQ,CAAC,GAAG,CAAC;SACnB,IAAI,CAAC,GAAG,CAAC,CAAC;AACb,CAAC;AAED,sEAAsE;AACtE,MAAM,UAAU,aAAa,CAAC,KAAa;IAC1C,OAAO,oBAAoB,CAAC,IAAI,CAAC,KAAK,CAAC;QACtC,CAAC,CAAC,KAAK;QACP,CAAC,CAAC,GAAG,GAAG,KAAK,CAAC,UAAU,CAAC,GAAG,EAAE,OAAO,CAAC,GAAG,GAAG,CAAC;AAC/C,CAAC","sourcesContent":["import consola from \"consola\";\nimport nodePath from \"node:path\";\n\n/**\n * One step in a CLI chain.\n * Defines which types the context needs to extend and how it extends the context\n *\n * Cli Steps can be chained to slowly build up the context over time\n *\n * @example\n * ```ts\n * const step1: CliStep<unknown, { foo: string }> = async (ctx) => {\n * return {...ctx, foo: \"hello\" }\n * }\n *\n * const step2: CliStep<{ foo: string }, { bar: number }> = async (ctx) => {\n * return { ...ctx, bar: 42 }\n * }\n *\n * const initial = { baz: \"baz\" } as const;\n * const ctx1 = await step1(initial);\n * const ctx2 = await step2(ctx1);\n *\n * ctx2 // Has type { foo: string, bar: number, baz: \"baz\" }\n * ```\n */\nexport type CliStep<In extends object, Out> = <Ctx extends In>(\n\tctx: Ctx\n) => Promise<Ctx & Out>;\n\n/**\n * Wrapper to exit the process if the user presses CTRL+C.\n */\nexport const prompt: typeof consola.prompt = async (message, options) => {\n\tconst response = await consola.prompt(message, options);\n\tif (response?.toString() === \"Symbol(clack:cancel)\") {\n\t\tprocess.exit(0);\n\t}\n\treturn response;\n};\n\nexport const promptSelection = async <T extends string>(\n\tmessage: string,\n\toptions: { initial?: T; options: { label: string; value: T }[] } = {\n\t\toptions: [],\n\t}\n): Promise<T> => {\n\treturn prompt(message, {\n\t\ttype: \"select\",\n\t\t...options,\n\t}) as unknown as Promise<T>;\n};\n\n/**\n * A path relative to `root` with forward slashes and without a leading `./`,\n * for messages and package.json scripts.\n *\n * @example\n * toRelativeDisplayPath(\"/app\", \"./project.inlang\") // \"project.inlang\"\n * toRelativeDisplayPath(\"/app\", \"/app/src/paraglide\") // \"src/paraglide\"\n */\nexport function toRelativeDisplayPath(root: string, path: string): string {\n\treturn nodePath\n\t\t.relative(root, nodePath.resolve(root, path))\n\t\t.split(nodePath.sep)\n\t\t.join(\"/\");\n}\n\n/** Quote package-script arguments containing shell metacharacters. */\nexport function shellArgument(value: string): string {\n\treturn /^[A-Za-z0-9_./-]+$/.test(value)\n\t\t? value\n\t\t: \"'\" + value.replaceAll(\"'\", `'\"'\"'`) + \"'\";\n}\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { test, expect } from "vitest";
|
|
2
|
+
import { execFile } from "node:child_process";
|
|
3
|
+
import { promisify } from "node:util";
|
|
4
|
+
import { shellArgument } from "./utils.js";
|
|
5
|
+
test.each([
|
|
6
|
+
"./src/paraglide",
|
|
7
|
+
"space directory",
|
|
8
|
+
"quote'path",
|
|
9
|
+
"literal$word",
|
|
10
|
+
"semi;colon",
|
|
11
|
+
"back`tick",
|
|
12
|
+
])("package scripts preserve literal path %s", async (value) => {
|
|
13
|
+
const { stdout } = await promisify(execFile)("/bin/sh", ["-c", "printf '%s' " + shellArgument(value)], { env: {} });
|
|
14
|
+
expect(stdout).toBe(value);
|
|
15
|
+
});
|
|
16
|
+
//# sourceMappingURL=utils.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utils.test.js","sourceRoot":"","sources":["../../src/cli/utils.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AACtC,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAC9C,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AACtC,OAAO,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAE3C,IAAI,CAAC,IAAI,CAAC;IACT,iBAAiB;IACjB,iBAAiB;IACjB,YAAY;IACZ,cAAc;IACd,YAAY;IACZ,WAAW;CACX,CAAC,CAAC,0CAA0C,EAAE,KAAK,EAAE,KAAK,EAAE,EAAE;IAC9D,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,SAAS,CAAC,QAAQ,CAAC,CAC3C,SAAS,EACT,CAAC,IAAI,EAAE,cAAc,GAAG,aAAa,CAAC,KAAK,CAAC,CAAC,EAC7C,EAAE,GAAG,EAAE,EAAE,EAAE,CACX,CAAC;IACF,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;AAC5B,CAAC,CAAC,CAAC","sourcesContent":["import { test, expect } from \"vitest\";\nimport { execFile } from \"node:child_process\";\nimport { promisify } from \"node:util\";\nimport { shellArgument } from \"./utils.js\";\n\ntest.each([\n\t\"./src/paraglide\",\n\t\"space directory\",\n\t\"quote'path\",\n\t\"literal$word\",\n\t\"semi;colon\",\n\t\"back`tick\",\n])(\"package scripts preserve literal path %s\", async (value) => {\n\tconst { stdout } = await promisify(execFile)(\n\t\t\"/bin/sh\",\n\t\t[\"-c\", \"printf '%s' \" + shellArgument(value)],\n\t\t{ env: {} }\n\t);\n\texpect(stdout).toBe(value);\n});\n"]}
|
|
@@ -74,7 +74,12 @@ export function compileAnnotation(str, locale, annotation, declarations, registr
|
|
|
74
74
|
const options = withDefaultDateTimeStyles(icuStyleAnnotation(annotation)).options;
|
|
75
75
|
// the options of `date` and `time` are those of `datetime`
|
|
76
76
|
const optionsOf = functionName === "datetime" ? "datetime" : annotation.name;
|
|
77
|
-
|
|
77
|
+
// compileOptions emits a plain data object, so the registry can safely cache it.
|
|
78
|
+
const cacheable = ["plural", "number", "datetime", "relativetime"].includes(functionName) &&
|
|
79
|
+
!options.some((option) => option.name === "__proto__")
|
|
80
|
+
? ", true"
|
|
81
|
+
: "";
|
|
82
|
+
return `registry.${functionName}("${locale}", ${str}, ${compileOptions(optionsOf, options, declarations)}${cacheable})`;
|
|
78
83
|
}
|
|
79
84
|
const icuDateTimeStyles = new Set(["short", "medium", "long", "full"]);
|
|
80
85
|
const intlNumberStyles = new Set(["decimal", "percent", "currency", "unit"]);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"compile-annotation.js","sourceRoot":"","sources":["../../src/compiler/compile-annotation.ts"],"names":[],"mappings":"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","sourcesContent":["import type {\n\tDeclaration,\n\tFunctionReference,\n\tLiteral,\n\tVariableReference,\n} from \"@inlang/sdk\";\nimport { compileVariableAccess } from \"./variable-access.js\";\nimport { escapeForDoubleQuoteString } from \"../services/codegen/escape.js\";\nimport { Logger } from \"../services/logger/index.js\";\n\n/**\n * The functions shipped in the generated registry.js file, by the annotation\n * name that calls them.\n *\n * @see createRegistry()\n */\nconst registryFunctionByAnnotation = new Map([\n\t[\"plural\", \"plural\"],\n\t[\"number\", \"number\"],\n\t[\"datetime\", \"datetime\"],\n\t[\"relativetime\", \"relativetime\"],\n\t// `#` in ICU MessageFormat 1 plurals, as imported by the ICU1 plugin\n\t[\"icu:pound\", \"icuPound\"],\n\t// `{d, date, short}` and `{d, time, short}` in ICU MessageFormat 1, as\n\t// imported by the ICU1 plugin, see icuStyleAnnotation()\n\t[\"date\", \"datetime\"],\n\t[\"time\", \"datetime\"],\n]);\n\n/**\n * The formatter names listed in warnings: the annotation names that call a\n * registry function.\n */\nconst displayedRegistryFunctions = Array.from(\n\tregistryFunctionByAnnotation.keys()\n);\n\nexport function isRegistryFunction(name: string): boolean {\n\treturn registryFunctionByAnnotation.has(name);\n}\n\nexport function registryFunctionNamesForDisplay(): string {\n\treturn displayedRegistryFunctions.join(\", \");\n}\n\nconst logger = new Logger();\n\n/**\n * Tracks annotation names that have already been warned about to avoid\n * spamming the console when the same unsupported formatter is used in\n * many messages (or across watch-mode recompiles).\n */\nconst warnedUnsupportedAnnotations = new Set<string>();\n\n/**\n * Returns the value unformatted, and warns once per formatter name.\n *\n * Unknown annotations, on pattern expressions and on local variables, fall\n * back to plain interpolation to avoid breaking compilation of messages\n * imported from other i18n libraries (e.g. i18next's `{{value, customFormat}}`).\n */\nexport function ignoreUnknownFormatter(name: string, value: string): string {\n\tif (!warnedUnsupportedAnnotations.has(name)) {\n\t\twarnedUnsupportedAnnotations.add(name);\n\t\tlogger.warn(\n\t\t\t`The formatter \"${name}\" is unknown and will be ignored. The value is interpolated without formatting. Supported formatters: ${registryFunctionNamesForDisplay()}.`\n\t\t);\n\t}\n\treturn value;\n}\n\n/**\n * The names of the registry functions a message calls, collected while it is\n * compiled. The output decides from it whether to import the registry.\n */\nexport type RegistryUsage = Set<string>;\n\n/**\n * Wraps a compiled expression value in a `registry.*` call if an\n * annotation is present.\n *\n * @example\n * compileAnnotation(\"i?.count\", \"en\", { type: \"function-reference\", name: \"number\", options: [] })\n * >> 'registry.number(\"en\", i?.count, {})'\n */\nexport function compileAnnotation(\n\tstr: string,\n\tlocale: string,\n\tannotation?: FunctionReference,\n\tdeclarations?: Declaration[],\n\tregistryUsage?: RegistryUsage\n): string {\n\tif (!annotation) {\n\t\treturn str;\n\t}\n\tif (annotation.name === \"relativetime\") {\n\t\tvalidateRelativeTimeOptions(annotation);\n\t}\n\tif (offsetAnnotations.has(annotation.name)) {\n\t\tvalidateOffsetOptions(annotation);\n\t}\n\tconst functionName =\n\t\tregistryFunctionByAnnotation.get(annotation.name) ?? annotation.name;\n\tregistryUsage?.add(functionName);\n\tconst options = withDefaultDateTimeStyles(\n\t\ticuStyleAnnotation(annotation)\n\t).options;\n\t// the options of `date` and `time` are those of `datetime`\n\tconst optionsOf = functionName === \"datetime\" ? \"datetime\" : annotation.name;\n\treturn `registry.${functionName}(\"${locale}\", ${str}, ${compileOptions(optionsOf, options, declarations)})`;\n}\n\nconst icuDateTimeStyles = new Set([\"short\", \"medium\", \"long\", \"full\"]);\n\nconst intlNumberStyles = new Set([\"decimal\", \"percent\", \"currency\", \"unit\"]);\n\n/**\n * Translates the ICU MessageFormat 1 `style` of an annotation to the options\n * of the registry function.\n *\n * The ICU1 plugin imports `{n, number, integer}` as `{$n :number style=integer}`\n * and `{d, date, short}` as `{$d :date style=short}`. Intl knows the number\n * styles \"decimal\", \"percent\", \"currency\" (with a `currency`) and \"unit\", and\n * throws for others. The date and time styles are Intl's `dateStyle` and\n * `timeStyle`. A style without an Intl equivalent, like an ICU skeleton\n * (`::currency/EUR`), is left out with a warning.\n *\n * @example\n * icuStyleAnnotation({ name: \"date\", options: [{ name: \"style\", value: \"short\" }] })\n * >> { name: \"date\", options: [{ name: \"dateStyle\", value: \"short\" }] }\n */\nexport function icuStyleAnnotation(\n\tannotation: FunctionReference\n): FunctionReference {\n\tconst style = annotation.options.find((option) => option.name === \"style\");\n\tconst others = annotation.options.filter((option) => option !== style);\n\tconst literal = (name: string, value: string) => ({\n\t\tname,\n\t\tvalue: { type: \"literal\" as const, value },\n\t});\n\n\tif (annotation.name === \"date\" || annotation.name === \"time\") {\n\t\tconst optionName = annotation.name === \"date\" ? \"dateStyle\" : \"timeStyle\";\n\t\tif (style?.value.type === \"literal\") {\n\t\t\tif (icuDateTimeStyles.has(style.value.value)) {\n\t\t\t\treturn {\n\t\t\t\t\t...annotation,\n\t\t\t\t\toptions: [literal(optionName, style.value.value), ...others],\n\t\t\t\t};\n\t\t\t}\n\t\t\tignoreUnknownStyle(annotation.name, style.value.value);\n\t\t} else if (style) {\n\t\t\treturn {\n\t\t\t\t...annotation,\n\t\t\t\toptions: [{ name: optionName, value: style.value }, ...others],\n\t\t\t};\n\t\t}\n\t\t// without a style, withDefaultDateTimeStyles() applies the default\n\t\treturn { ...annotation, options: others };\n\t}\n\n\tif (annotation.name === \"number\" && style?.value.type === \"literal\") {\n\t\tconst value = style.value.value;\n\t\tif (value === \"integer\") {\n\t\t\tconst hasFractionDigits = others.some(\n\t\t\t\t(option) => option.name === \"maximumFractionDigits\"\n\t\t\t);\n\t\t\treturn {\n\t\t\t\t...annotation,\n\t\t\t\toptions: hasFractionDigits\n\t\t\t\t\t? others\n\t\t\t\t\t: [literal(\"maximumFractionDigits\", \"0\"), ...others],\n\t\t\t};\n\t\t}\n\t\tconst hasCurrency = others.some((option) => option.name === \"currency\");\n\t\tif (\n\t\t\t!intlNumberStyles.has(value) ||\n\t\t\t(value === \"currency\" && !hasCurrency)\n\t\t) {\n\t\t\tignoreUnknownStyle(annotation.name, value);\n\t\t\treturn { ...annotation, options: others };\n\t\t}\n\t}\n\n\treturn annotation;\n}\n\n/**\n * The `Intl.DateTimeFormat` options that pick which parts of a date are shown.\n * Without any of them, Intl shows only the numeric date, e.g. \"10/9/2026\".\n * `dateStyle` and `timeStyle` cannot be combined with the others: Intl throws.\n */\nconst dateTimeFieldOptions = new Set([\n\t\"dateStyle\",\n\t\"timeStyle\",\n\t\"weekday\",\n\t\"era\",\n\t\"year\",\n\t\"month\",\n\t\"day\",\n\t\"dayPeriod\",\n\t\"hour\",\n\t\"minute\",\n\t\"second\",\n\t\"fractionalSecondDigits\",\n\t\"timeZoneName\",\n]);\n\n/**\n * The styles a date formatter uses when its options pick no fields.\n *\n * - `date`: MessageFormat 2 (LDML 47 `:date` `style=medium`) and ICU\n * MessageFormat 1 (`{d, date}`) both default to \"medium\", e.g. \"Oct 9, 2026\".\n * - `time`: ICU MessageFormat 1 `{d, time}` defaults to \"medium\", e.g.\n * \"4:30:00 PM\", while MessageFormat 2 (LDML 47 `:time`) defaults to \"short\".\n * `{$d :time}` is what the ICU1 plugin imports `{d, time}` as, so it keeps\n * ICU's default. Write `{$d :time style=short}` for MessageFormat 2's.\n * - `datetime`: MessageFormat 2 (LDML 47 `:datetime`) defaults to\n * `dateStyle=medium timeStyle=short`, e.g. \"Oct 9, 2026, 4:30 PM\".\n */\nconst defaultDateTimeStyles = new Map<string, Array<[string, string]>>([\n\t[\"date\", [[\"dateStyle\", \"medium\"]]],\n\t[\"time\", [[\"timeStyle\", \"medium\"]]],\n\t[\n\t\t\"datetime\",\n\t\t[\n\t\t\t[\"dateStyle\", \"medium\"],\n\t\t\t[\"timeStyle\", \"short\"],\n\t\t],\n\t],\n]);\n\n/**\n * Adds the default styles of `date`, `time` and `datetime` when the options\n * pick no fields. Options like `timeZone` or `hour12` are kept.\n *\n * @example\n * withDefaultDateTimeStyles({ name: \"datetime\", options: [] })\n * >> { name: \"datetime\", options: [{ name: \"dateStyle\", value: \"medium\" }, { name: \"timeStyle\", value: \"short\" }] }\n */\nexport function withDefaultDateTimeStyles(\n\tannotation: FunctionReference\n): FunctionReference {\n\tconst defaults = defaultDateTimeStyles.get(annotation.name);\n\tif (\n\t\t!defaults ||\n\t\tannotation.options.some((option) => dateTimeFieldOptions.has(option.name))\n\t) {\n\t\treturn annotation;\n\t}\n\treturn {\n\t\t...annotation,\n\t\toptions: [\n\t\t\t...defaults.map(([name, value]) => ({\n\t\t\t\tname,\n\t\t\t\tvalue: { type: \"literal\" as const, value },\n\t\t\t})),\n\t\t\t...annotation.options,\n\t\t],\n\t};\n}\n\nconst warnedUnknownStyles = new Set<string>();\n\nfunction ignoreUnknownStyle(name: string, style: string): void {\n\tconst key = `${name} ${style}`;\n\tif (warnedUnknownStyles.has(key)) return;\n\twarnedUnknownStyles.add(key);\n\tlogger.warn(\n\t\t`The style \"${style}\" of the formatter \"${name}\" is not supported and will be ignored.${\n\t\t\tname === \"number\" && style === \"currency\"\n\t\t\t\t? ' The \"currency\" style needs a \"currency\" option.'\n\t\t\t\t: \"\"\n\t\t}`\n\t);\n}\n\n/**\n * Returns the names of the variables the compiled options of an annotation\n * read.\n *\n * @example\n * // {$date :relativetime unit=$unit}\n * annotationVariableReferences(annotation) // [\"unit\"]\n */\nexport function annotationVariableReferences(\n\tannotation: FunctionReference\n): string[] {\n\tconst names: string[] = [];\n\tfor (const option of annotation.options) {\n\t\tif (option.value.type === \"variable-reference\") {\n\t\t\tnames.push(option.value.name);\n\t\t} else if (\n\t\t\tannotation.name === \"relativetime\" &&\n\t\t\toption.name === \"unit\" &&\n\t\t\tisDollarVariableReference(option.value.value)\n\t\t) {\n\t\t\tnames.push(option.value.value.slice(1));\n\t\t}\n\t}\n\treturn names;\n}\n\nfunction compileOptions(\n\tannotationName: string,\n\toptions: FunctionReference[\"options\"],\n\tdeclarations?: Declaration[]\n): string {\n\tif (options.length === 0) {\n\t\treturn \"{}\";\n\t}\n\tconst entries: string[] = options.map(\n\t\t(option) =>\n\t\t\t`${option.name}: ${compileOptionLiteralOrVarRef(\n\t\t\t\tannotationName,\n\t\t\t\toption.name,\n\t\t\t\toption.value,\n\t\t\t\tdeclarations\n\t\t\t)}`\n\t);\n\tconst code = \"{ \" + entries.join(\", \") + \" }\";\n\n\treturn code;\n}\n\nconst numericOptionNamesByAnnotation: Record<string, ReadonlySet<string>> = {\n\tnumber: new Set([\n\t\t\"minimumIntegerDigits\",\n\t\t\"minimumFractionDigits\",\n\t\t\"maximumFractionDigits\",\n\t\t\"minimumSignificantDigits\",\n\t\t\"maximumSignificantDigits\",\n\t\t\"roundingIncrement\",\n\t]),\n\tplural: new Set([\n\t\t\"minimumIntegerDigits\",\n\t\t\"minimumFractionDigits\",\n\t\t\"maximumFractionDigits\",\n\t\t\"minimumSignificantDigits\",\n\t\t\"maximumSignificantDigits\",\n\t]),\n\tdatetime: new Set([\"fractionalSecondDigits\"]),\n};\n\nconst booleanOptionNamesByAnnotation: Record<string, ReadonlySet<string>> = {\n\tnumber: new Set([\"useGrouping\"]),\n\tdatetime: new Set([\"hour12\"]),\n};\n\nconst jsNonNegativeIntegerPattern = /^(?:0|[1-9]\\d*)$/;\n\nfunction compileOptionLiteralOrVarRef(\n\tannotationName: string,\n\toptionName: string,\n\tvalue: Literal | VariableReference,\n\tdeclarations?: Declaration[]\n): string {\n\tif (value.type === \"variable-reference\") {\n\t\tif (annotationName === \"relativetime\" && optionName === \"unit\") {\n\t\t\treturn `/** @type {import(\"../registry.js\").RelativeTimeFormatUnit} */ (${compileVariableAccess(value.name, declarations)})`;\n\t\t}\n\t\treturn compileVariableAccess(value.name, declarations);\n\t}\n\n\tif (\n\t\tannotationName === \"relativetime\" &&\n\t\toptionName === \"unit\" &&\n\t\tisDollarVariableReference(value.value)\n\t) {\n\t\treturn `/** @type {import(\"../registry.js\").RelativeTimeFormatUnit} */ (${compileVariableAccess(value.value.slice(1), declarations)})`;\n\t}\n\n\tif (shouldEmitNumberLiteral(annotationName, optionName, value.value)) {\n\t\treturn value.value;\n\t}\n\n\tif (shouldEmitBooleanLiteral(annotationName, optionName, value.value)) {\n\t\treturn value.value;\n\t}\n\n\tif (offsetAnnotations.has(annotationName) && optionName === \"offset\") {\n\t\t// validated by validateOffsetOptions()\n\t\treturn String(Number(value.value));\n\t}\n\n\treturn `\"${escapeForDoubleQuoteString(value.value)}\"`;\n}\n\nfunction shouldEmitNumberLiteral(\n\tannotationName: string,\n\toptionName: string,\n\tliteral: string\n): boolean {\n\treturn (\n\t\tnumericOptionNamesByAnnotation[annotationName]?.has(optionName) === true &&\n\t\tjsNonNegativeIntegerPattern.test(literal)\n\t);\n}\n\nfunction shouldEmitBooleanLiteral(\n\tannotationName: string,\n\toptionName: string,\n\tliteral: string\n): boolean {\n\treturn (\n\t\tbooleanOptionNamesByAnnotation[annotationName]?.has(optionName) === true &&\n\t\t(literal === \"true\" || literal === \"false\")\n\t);\n}\n\nconst relativeTimeUnits = new Set([\n\t\"year\",\n\t\"years\",\n\t\"quarter\",\n\t\"quarters\",\n\t\"month\",\n\t\"months\",\n\t\"week\",\n\t\"weeks\",\n\t\"day\",\n\t\"days\",\n\t\"hour\",\n\t\"hours\",\n\t\"minute\",\n\t\"minutes\",\n\t\"second\",\n\t\"seconds\",\n]);\n\nfunction validateRelativeTimeOptions(annotation: FunctionReference): void {\n\tconst unitOptions = annotation.options.filter(\n\t\t(option) => option.name === \"unit\"\n\t);\n\n\tif (unitOptions.length === 0) {\n\t\tthrow new Error('The \"relativetime\" formatter requires a \"unit\" option.');\n\t}\n\n\tif (unitOptions.length > 1) {\n\t\tthrow new Error(\n\t\t\t'The \"relativetime\" formatter requires exactly one \"unit\" option.'\n\t\t);\n\t}\n\n\tconst [unitOption] = unitOptions;\n\tif (!unitOption || unitOption.value.type === \"variable-reference\") {\n\t\treturn;\n\t}\n\n\tif (isDollarVariableReference(unitOption.value.value)) {\n\t\treturn;\n\t}\n\n\tif (!relativeTimeUnits.has(unitOption.value.value)) {\n\t\tthrow new Error(\n\t\t\t`Invalid \"relativetime\" unit \"${unitOption.value.value}\". Expected one of: ${Array.from(\n\t\t\t\trelativeTimeUnits\n\t\t\t).join(\", \")}.`\n\t\t);\n\t}\n}\n\n/**\n * Annotations with an ICU MessageFormat 1 plural `offset` option.\n *\n * `{count, plural, offset:1 …}` imports as `{$count :plural offset=1}`, and\n * `#` inside it as `{$count :icu:pound offset=1}`. The registry subtracts the\n * offset from the input, so it has to be a number.\n */\nconst offsetAnnotations = new Set([\"plural\", \"icu:pound\"]);\n\nconst offsetPattern = /^-?(?:0|[1-9]\\d*)(?:\\.\\d+)?$/;\n\nfunction validateOffsetOptions(annotation: FunctionReference): void {\n\tfor (const option of annotation.options) {\n\t\tif (\n\t\t\toption.name === \"offset\" &&\n\t\t\toption.value.type === \"literal\" &&\n\t\t\t!offsetPattern.test(option.value.value)\n\t\t) {\n\t\t\tthrow new Error(\n\t\t\t\t`Invalid \"${annotation.name}\" offset \"${option.value.value}\". Expected a number.`\n\t\t\t);\n\t\t}\n\t}\n}\n\nfunction isDollarVariableReference(value: string): boolean {\n\treturn value.startsWith(\"$\") && value.length > 1;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"compile-annotation.js","sourceRoot":"","sources":["../../src/compiler/compile-annotation.ts"],"names":[],"mappings":"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","sourcesContent":["import type {\n\tDeclaration,\n\tFunctionReference,\n\tLiteral,\n\tVariableReference,\n} from \"@inlang/sdk\";\nimport { compileVariableAccess } from \"./variable-access.js\";\nimport { escapeForDoubleQuoteString } from \"../services/codegen/escape.js\";\nimport { Logger } from \"../services/logger/index.js\";\n\n/**\n * The functions shipped in the generated registry.js file, by the annotation\n * name that calls them.\n *\n * @see createRegistry()\n */\nconst registryFunctionByAnnotation = new Map([\n\t[\"plural\", \"plural\"],\n\t[\"number\", \"number\"],\n\t[\"datetime\", \"datetime\"],\n\t[\"relativetime\", \"relativetime\"],\n\t// `#` in ICU MessageFormat 1 plurals, as imported by the ICU1 plugin\n\t[\"icu:pound\", \"icuPound\"],\n\t// `{d, date, short}` and `{d, time, short}` in ICU MessageFormat 1, as\n\t// imported by the ICU1 plugin, see icuStyleAnnotation()\n\t[\"date\", \"datetime\"],\n\t[\"time\", \"datetime\"],\n]);\n\n/**\n * The formatter names listed in warnings: the annotation names that call a\n * registry function.\n */\nconst displayedRegistryFunctions = Array.from(\n\tregistryFunctionByAnnotation.keys()\n);\n\nexport function isRegistryFunction(name: string): boolean {\n\treturn registryFunctionByAnnotation.has(name);\n}\n\nexport function registryFunctionNamesForDisplay(): string {\n\treturn displayedRegistryFunctions.join(\", \");\n}\n\nconst logger = new Logger();\n\n/**\n * Tracks annotation names that have already been warned about to avoid\n * spamming the console when the same unsupported formatter is used in\n * many messages (or across watch-mode recompiles).\n */\nconst warnedUnsupportedAnnotations = new Set<string>();\n\n/**\n * Returns the value unformatted, and warns once per formatter name.\n *\n * Unknown annotations, on pattern expressions and on local variables, fall\n * back to plain interpolation to avoid breaking compilation of messages\n * imported from other i18n libraries (e.g. i18next's `{{value, customFormat}}`).\n */\nexport function ignoreUnknownFormatter(name: string, value: string): string {\n\tif (!warnedUnsupportedAnnotations.has(name)) {\n\t\twarnedUnsupportedAnnotations.add(name);\n\t\tlogger.warn(\n\t\t\t`The formatter \"${name}\" is unknown and will be ignored. The value is interpolated without formatting. Supported formatters: ${registryFunctionNamesForDisplay()}.`\n\t\t);\n\t}\n\treturn value;\n}\n\n/**\n * The names of the registry functions a message calls, collected while it is\n * compiled. The output decides from it whether to import the registry.\n */\nexport type RegistryUsage = Set<string>;\n\n/**\n * Wraps a compiled expression value in a `registry.*` call if an\n * annotation is present.\n *\n * @example\n * compileAnnotation(\"i?.count\", \"en\", { type: \"function-reference\", name: \"number\", options: [] })\n * >> 'registry.number(\"en\", i?.count, {})'\n */\nexport function compileAnnotation(\n\tstr: string,\n\tlocale: string,\n\tannotation?: FunctionReference,\n\tdeclarations?: Declaration[],\n\tregistryUsage?: RegistryUsage\n): string {\n\tif (!annotation) {\n\t\treturn str;\n\t}\n\tif (annotation.name === \"relativetime\") {\n\t\tvalidateRelativeTimeOptions(annotation);\n\t}\n\tif (offsetAnnotations.has(annotation.name)) {\n\t\tvalidateOffsetOptions(annotation);\n\t}\n\tconst functionName =\n\t\tregistryFunctionByAnnotation.get(annotation.name) ?? annotation.name;\n\tregistryUsage?.add(functionName);\n\tconst options = withDefaultDateTimeStyles(\n\t\ticuStyleAnnotation(annotation)\n\t).options;\n\t// the options of `date` and `time` are those of `datetime`\n\tconst optionsOf = functionName === \"datetime\" ? \"datetime\" : annotation.name;\n\t// compileOptions emits a plain data object, so the registry can safely cache it.\n\tconst cacheable =\n\t\t[\"plural\", \"number\", \"datetime\", \"relativetime\"].includes(functionName) &&\n\t\t!options.some((option) => option.name === \"__proto__\")\n\t\t\t? \", true\"\n\t\t\t: \"\";\n\treturn `registry.${functionName}(\"${locale}\", ${str}, ${compileOptions(optionsOf, options, declarations)}${cacheable})`;\n}\n\nconst icuDateTimeStyles = new Set([\"short\", \"medium\", \"long\", \"full\"]);\n\nconst intlNumberStyles = new Set([\"decimal\", \"percent\", \"currency\", \"unit\"]);\n\n/**\n * Translates the ICU MessageFormat 1 `style` of an annotation to the options\n * of the registry function.\n *\n * The ICU1 plugin imports `{n, number, integer}` as `{$n :number style=integer}`\n * and `{d, date, short}` as `{$d :date style=short}`. Intl knows the number\n * styles \"decimal\", \"percent\", \"currency\" (with a `currency`) and \"unit\", and\n * throws for others. The date and time styles are Intl's `dateStyle` and\n * `timeStyle`. A style without an Intl equivalent, like an ICU skeleton\n * (`::currency/EUR`), is left out with a warning.\n *\n * @example\n * icuStyleAnnotation({ name: \"date\", options: [{ name: \"style\", value: \"short\" }] })\n * >> { name: \"date\", options: [{ name: \"dateStyle\", value: \"short\" }] }\n */\nexport function icuStyleAnnotation(\n\tannotation: FunctionReference\n): FunctionReference {\n\tconst style = annotation.options.find((option) => option.name === \"style\");\n\tconst others = annotation.options.filter((option) => option !== style);\n\tconst literal = (name: string, value: string) => ({\n\t\tname,\n\t\tvalue: { type: \"literal\" as const, value },\n\t});\n\n\tif (annotation.name === \"date\" || annotation.name === \"time\") {\n\t\tconst optionName = annotation.name === \"date\" ? \"dateStyle\" : \"timeStyle\";\n\t\tif (style?.value.type === \"literal\") {\n\t\t\tif (icuDateTimeStyles.has(style.value.value)) {\n\t\t\t\treturn {\n\t\t\t\t\t...annotation,\n\t\t\t\t\toptions: [literal(optionName, style.value.value), ...others],\n\t\t\t\t};\n\t\t\t}\n\t\t\tignoreUnknownStyle(annotation.name, style.value.value);\n\t\t} else if (style) {\n\t\t\treturn {\n\t\t\t\t...annotation,\n\t\t\t\toptions: [{ name: optionName, value: style.value }, ...others],\n\t\t\t};\n\t\t}\n\t\t// without a style, withDefaultDateTimeStyles() applies the default\n\t\treturn { ...annotation, options: others };\n\t}\n\n\tif (annotation.name === \"number\" && style?.value.type === \"literal\") {\n\t\tconst value = style.value.value;\n\t\tif (value === \"integer\") {\n\t\t\tconst hasFractionDigits = others.some(\n\t\t\t\t(option) => option.name === \"maximumFractionDigits\"\n\t\t\t);\n\t\t\treturn {\n\t\t\t\t...annotation,\n\t\t\t\toptions: hasFractionDigits\n\t\t\t\t\t? others\n\t\t\t\t\t: [literal(\"maximumFractionDigits\", \"0\"), ...others],\n\t\t\t};\n\t\t}\n\t\tconst hasCurrency = others.some((option) => option.name === \"currency\");\n\t\tif (\n\t\t\t!intlNumberStyles.has(value) ||\n\t\t\t(value === \"currency\" && !hasCurrency)\n\t\t) {\n\t\t\tignoreUnknownStyle(annotation.name, value);\n\t\t\treturn { ...annotation, options: others };\n\t\t}\n\t}\n\n\treturn annotation;\n}\n\n/**\n * The `Intl.DateTimeFormat` options that pick which parts of a date are shown.\n * Without any of them, Intl shows only the numeric date, e.g. \"10/9/2026\".\n * `dateStyle` and `timeStyle` cannot be combined with the others: Intl throws.\n */\nconst dateTimeFieldOptions = new Set([\n\t\"dateStyle\",\n\t\"timeStyle\",\n\t\"weekday\",\n\t\"era\",\n\t\"year\",\n\t\"month\",\n\t\"day\",\n\t\"dayPeriod\",\n\t\"hour\",\n\t\"minute\",\n\t\"second\",\n\t\"fractionalSecondDigits\",\n\t\"timeZoneName\",\n]);\n\n/**\n * The styles a date formatter uses when its options pick no fields.\n *\n * - `date`: MessageFormat 2 (LDML 47 `:date` `style=medium`) and ICU\n * MessageFormat 1 (`{d, date}`) both default to \"medium\", e.g. \"Oct 9, 2026\".\n * - `time`: ICU MessageFormat 1 `{d, time}` defaults to \"medium\", e.g.\n * \"4:30:00 PM\", while MessageFormat 2 (LDML 47 `:time`) defaults to \"short\".\n * `{$d :time}` is what the ICU1 plugin imports `{d, time}` as, so it keeps\n * ICU's default. Write `{$d :time style=short}` for MessageFormat 2's.\n * - `datetime`: MessageFormat 2 (LDML 47 `:datetime`) defaults to\n * `dateStyle=medium timeStyle=short`, e.g. \"Oct 9, 2026, 4:30 PM\".\n */\nconst defaultDateTimeStyles = new Map<string, Array<[string, string]>>([\n\t[\"date\", [[\"dateStyle\", \"medium\"]]],\n\t[\"time\", [[\"timeStyle\", \"medium\"]]],\n\t[\n\t\t\"datetime\",\n\t\t[\n\t\t\t[\"dateStyle\", \"medium\"],\n\t\t\t[\"timeStyle\", \"short\"],\n\t\t],\n\t],\n]);\n\n/**\n * Adds the default styles of `date`, `time` and `datetime` when the options\n * pick no fields. Options like `timeZone` or `hour12` are kept.\n *\n * @example\n * withDefaultDateTimeStyles({ name: \"datetime\", options: [] })\n * >> { name: \"datetime\", options: [{ name: \"dateStyle\", value: \"medium\" }, { name: \"timeStyle\", value: \"short\" }] }\n */\nexport function withDefaultDateTimeStyles(\n\tannotation: FunctionReference\n): FunctionReference {\n\tconst defaults = defaultDateTimeStyles.get(annotation.name);\n\tif (\n\t\t!defaults ||\n\t\tannotation.options.some((option) => dateTimeFieldOptions.has(option.name))\n\t) {\n\t\treturn annotation;\n\t}\n\treturn {\n\t\t...annotation,\n\t\toptions: [\n\t\t\t...defaults.map(([name, value]) => ({\n\t\t\t\tname,\n\t\t\t\tvalue: { type: \"literal\" as const, value },\n\t\t\t})),\n\t\t\t...annotation.options,\n\t\t],\n\t};\n}\n\nconst warnedUnknownStyles = new Set<string>();\n\nfunction ignoreUnknownStyle(name: string, style: string): void {\n\tconst key = `${name} ${style}`;\n\tif (warnedUnknownStyles.has(key)) return;\n\twarnedUnknownStyles.add(key);\n\tlogger.warn(\n\t\t`The style \"${style}\" of the formatter \"${name}\" is not supported and will be ignored.${\n\t\t\tname === \"number\" && style === \"currency\"\n\t\t\t\t? ' The \"currency\" style needs a \"currency\" option.'\n\t\t\t\t: \"\"\n\t\t}`\n\t);\n}\n\n/**\n * Returns the names of the variables the compiled options of an annotation\n * read.\n *\n * @example\n * // {$date :relativetime unit=$unit}\n * annotationVariableReferences(annotation) // [\"unit\"]\n */\nexport function annotationVariableReferences(\n\tannotation: FunctionReference\n): string[] {\n\tconst names: string[] = [];\n\tfor (const option of annotation.options) {\n\t\tif (option.value.type === \"variable-reference\") {\n\t\t\tnames.push(option.value.name);\n\t\t} else if (\n\t\t\tannotation.name === \"relativetime\" &&\n\t\t\toption.name === \"unit\" &&\n\t\t\tisDollarVariableReference(option.value.value)\n\t\t) {\n\t\t\tnames.push(option.value.value.slice(1));\n\t\t}\n\t}\n\treturn names;\n}\n\nfunction compileOptions(\n\tannotationName: string,\n\toptions: FunctionReference[\"options\"],\n\tdeclarations?: Declaration[]\n): string {\n\tif (options.length === 0) {\n\t\treturn \"{}\";\n\t}\n\tconst entries: string[] = options.map(\n\t\t(option) =>\n\t\t\t`${option.name}: ${compileOptionLiteralOrVarRef(\n\t\t\t\tannotationName,\n\t\t\t\toption.name,\n\t\t\t\toption.value,\n\t\t\t\tdeclarations\n\t\t\t)}`\n\t);\n\tconst code = \"{ \" + entries.join(\", \") + \" }\";\n\n\treturn code;\n}\n\nconst numericOptionNamesByAnnotation: Record<string, ReadonlySet<string>> = {\n\tnumber: new Set([\n\t\t\"minimumIntegerDigits\",\n\t\t\"minimumFractionDigits\",\n\t\t\"maximumFractionDigits\",\n\t\t\"minimumSignificantDigits\",\n\t\t\"maximumSignificantDigits\",\n\t\t\"roundingIncrement\",\n\t]),\n\tplural: new Set([\n\t\t\"minimumIntegerDigits\",\n\t\t\"minimumFractionDigits\",\n\t\t\"maximumFractionDigits\",\n\t\t\"minimumSignificantDigits\",\n\t\t\"maximumSignificantDigits\",\n\t]),\n\tdatetime: new Set([\"fractionalSecondDigits\"]),\n};\n\nconst booleanOptionNamesByAnnotation: Record<string, ReadonlySet<string>> = {\n\tnumber: new Set([\"useGrouping\"]),\n\tdatetime: new Set([\"hour12\"]),\n};\n\nconst jsNonNegativeIntegerPattern = /^(?:0|[1-9]\\d*)$/;\n\nfunction compileOptionLiteralOrVarRef(\n\tannotationName: string,\n\toptionName: string,\n\tvalue: Literal | VariableReference,\n\tdeclarations?: Declaration[]\n): string {\n\tif (value.type === \"variable-reference\") {\n\t\tif (annotationName === \"relativetime\" && optionName === \"unit\") {\n\t\t\treturn `/** @type {import(\"../registry.js\").RelativeTimeFormatUnit} */ (${compileVariableAccess(value.name, declarations)})`;\n\t\t}\n\t\treturn compileVariableAccess(value.name, declarations);\n\t}\n\n\tif (\n\t\tannotationName === \"relativetime\" &&\n\t\toptionName === \"unit\" &&\n\t\tisDollarVariableReference(value.value)\n\t) {\n\t\treturn `/** @type {import(\"../registry.js\").RelativeTimeFormatUnit} */ (${compileVariableAccess(value.value.slice(1), declarations)})`;\n\t}\n\n\tif (shouldEmitNumberLiteral(annotationName, optionName, value.value)) {\n\t\treturn value.value;\n\t}\n\n\tif (shouldEmitBooleanLiteral(annotationName, optionName, value.value)) {\n\t\treturn value.value;\n\t}\n\n\tif (offsetAnnotations.has(annotationName) && optionName === \"offset\") {\n\t\t// validated by validateOffsetOptions()\n\t\treturn String(Number(value.value));\n\t}\n\n\treturn `\"${escapeForDoubleQuoteString(value.value)}\"`;\n}\n\nfunction shouldEmitNumberLiteral(\n\tannotationName: string,\n\toptionName: string,\n\tliteral: string\n): boolean {\n\treturn (\n\t\tnumericOptionNamesByAnnotation[annotationName]?.has(optionName) === true &&\n\t\tjsNonNegativeIntegerPattern.test(literal)\n\t);\n}\n\nfunction shouldEmitBooleanLiteral(\n\tannotationName: string,\n\toptionName: string,\n\tliteral: string\n): boolean {\n\treturn (\n\t\tbooleanOptionNamesByAnnotation[annotationName]?.has(optionName) === true &&\n\t\t(literal === \"true\" || literal === \"false\")\n\t);\n}\n\nconst relativeTimeUnits = new Set([\n\t\"year\",\n\t\"years\",\n\t\"quarter\",\n\t\"quarters\",\n\t\"month\",\n\t\"months\",\n\t\"week\",\n\t\"weeks\",\n\t\"day\",\n\t\"days\",\n\t\"hour\",\n\t\"hours\",\n\t\"minute\",\n\t\"minutes\",\n\t\"second\",\n\t\"seconds\",\n]);\n\nfunction validateRelativeTimeOptions(annotation: FunctionReference): void {\n\tconst unitOptions = annotation.options.filter(\n\t\t(option) => option.name === \"unit\"\n\t);\n\n\tif (unitOptions.length === 0) {\n\t\tthrow new Error('The \"relativetime\" formatter requires a \"unit\" option.');\n\t}\n\n\tif (unitOptions.length > 1) {\n\t\tthrow new Error(\n\t\t\t'The \"relativetime\" formatter requires exactly one \"unit\" option.'\n\t\t);\n\t}\n\n\tconst [unitOption] = unitOptions;\n\tif (!unitOption || unitOption.value.type === \"variable-reference\") {\n\t\treturn;\n\t}\n\n\tif (isDollarVariableReference(unitOption.value.value)) {\n\t\treturn;\n\t}\n\n\tif (!relativeTimeUnits.has(unitOption.value.value)) {\n\t\tthrow new Error(\n\t\t\t`Invalid \"relativetime\" unit \"${unitOption.value.value}\". Expected one of: ${Array.from(\n\t\t\t\trelativeTimeUnits\n\t\t\t).join(\", \")}.`\n\t\t);\n\t}\n}\n\n/**\n * Annotations with an ICU MessageFormat 1 plural `offset` option.\n *\n * `{count, plural, offset:1 …}` imports as `{$count :plural offset=1}`, and\n * `#` inside it as `{$count :icu:pound offset=1}`. The registry subtracts the\n * offset from the input, so it has to be a number.\n */\nconst offsetAnnotations = new Set([\"plural\", \"icu:pound\"]);\n\nconst offsetPattern = /^-?(?:0|[1-9]\\d*)(?:\\.\\d+)?$/;\n\nfunction validateOffsetOptions(annotation: FunctionReference): void {\n\tfor (const option of annotation.options) {\n\t\tif (\n\t\t\toption.name === \"offset\" &&\n\t\t\toption.value.type === \"literal\" &&\n\t\t\t!offsetPattern.test(option.value.value)\n\t\t) {\n\t\t\tthrow new Error(\n\t\t\t\t`Invalid \"${annotation.name}\" offset \"${option.value.value}\". Expected a number.`\n\t\t\t);\n\t\t}\n\t}\n}\n\nfunction isDollarVariableReference(value: string): boolean {\n\treturn value.startsWith(\"$\") && value.length > 1;\n}\n"]}
|
|
@@ -14,6 +14,8 @@ export type CompiledBundleWithMessages = {
|
|
|
14
14
|
matchTypes: InputMatchTypes;
|
|
15
15
|
/** Shared typedef name for bundle input types used across emitted JSDoc */
|
|
16
16
|
inputTypeAliasName?: string;
|
|
17
|
+
/** Compiled message helpers with no emitted reference in message-modules. */
|
|
18
|
+
unreferencedMessageLocales?: string[];
|
|
17
19
|
};
|
|
18
20
|
/**
|
|
19
21
|
* Compiles all the messages in the bundle and returns an index-function + each compiled message
|
|
@@ -23,6 +25,8 @@ export declare const compileBundle: (args: {
|
|
|
23
25
|
fallbackMap: Record<string, string | undefined>;
|
|
24
26
|
messageReferenceExpression: (locale: string, bundleId: string) => string;
|
|
25
27
|
settings?: ProjectSettings;
|
|
28
|
+
/** Internal layout control; locale modules keep text grouped by language. */
|
|
29
|
+
inlineMessages?: boolean;
|
|
26
30
|
experimentalMiddlewareLocaleSplitting?: boolean;
|
|
27
31
|
experimentalStaticLocale?: CompilerOptions["experimentalStaticLocale"];
|
|
28
32
|
}) => CompiledBundleWithMessages;
|
|
@@ -22,11 +22,22 @@ export const compileBundle = (args) => {
|
|
|
22
22
|
// set the pattern for the language tag
|
|
23
23
|
compiledMessages[message.locale] = compiledMessage;
|
|
24
24
|
}
|
|
25
|
+
const inlinePlainTextByLocale = args.inlineMessages !== true ||
|
|
26
|
+
args.experimentalStaticLocale === perLocaleBuildStaticLocaleExpression
|
|
27
|
+
? undefined
|
|
28
|
+
: findPlainTextMessages(args.bundle);
|
|
29
|
+
const unreferencedMessageLocales = findUnreferencedMessageLocales({
|
|
30
|
+
inlinePlainTextByLocale: inlinePlainTextByLocale ?? Object.create(null),
|
|
31
|
+
compiledMessages,
|
|
32
|
+
fallbackMap: args.fallbackMap,
|
|
33
|
+
hasMarkup,
|
|
34
|
+
});
|
|
25
35
|
return {
|
|
26
36
|
bundle: compileBundleFunction({
|
|
27
37
|
bundle: args.bundle,
|
|
28
38
|
availableLocales: Object.keys(args.fallbackMap),
|
|
29
39
|
messageReferenceExpression: args.messageReferenceExpression,
|
|
40
|
+
inlinePlainTextByLocale,
|
|
30
41
|
settings: args.settings,
|
|
31
42
|
matchTypes,
|
|
32
43
|
hasMarkup,
|
|
@@ -37,8 +48,54 @@ export const compileBundle = (args) => {
|
|
|
37
48
|
messages: compiledMessages,
|
|
38
49
|
matchTypes,
|
|
39
50
|
inputTypeAliasName,
|
|
51
|
+
unreferencedMessageLocales,
|
|
40
52
|
};
|
|
41
53
|
};
|
|
54
|
+
/**
|
|
55
|
+
* Finds one-variant messages whose pattern is entirely static text. Their
|
|
56
|
+
* dispatcher branch can return the string directly without retaining a
|
|
57
|
+
* locale message function in the client bundle.
|
|
58
|
+
*/
|
|
59
|
+
function findPlainTextMessages(bundle) {
|
|
60
|
+
const result = Object.create(null);
|
|
61
|
+
for (const message of bundle.messages) {
|
|
62
|
+
if (message.variants.length !== 1)
|
|
63
|
+
continue;
|
|
64
|
+
const variant = message.variants[0];
|
|
65
|
+
if (!variant || !variant.pattern.every((part) => part.type === "text")) {
|
|
66
|
+
continue;
|
|
67
|
+
}
|
|
68
|
+
// compilePattern emits static text inside a template literal, whose
|
|
69
|
+
// cooked value normalizes CR and CRLF line endings to LF.
|
|
70
|
+
result[message.locale] = variant.pattern
|
|
71
|
+
.map((part) => (part.type === "text" ? part.value : ""))
|
|
72
|
+
.join("")
|
|
73
|
+
.replace(/\r\n?/g, "\n");
|
|
74
|
+
}
|
|
75
|
+
return result;
|
|
76
|
+
}
|
|
77
|
+
function findUnreferencedMessageLocales(args) {
|
|
78
|
+
if (args.hasMarkup)
|
|
79
|
+
return [];
|
|
80
|
+
// Missing-locale aliases still call the first available compiled fallback
|
|
81
|
+
// function, even when the dispatcher's own branch uses an inline string.
|
|
82
|
+
const fallbackTargets = new Set();
|
|
83
|
+
for (const locale of Object.keys(args.fallbackMap)) {
|
|
84
|
+
if (Object.hasOwn(args.compiledMessages, locale))
|
|
85
|
+
continue;
|
|
86
|
+
let fallbackLocale = args.fallbackMap[locale];
|
|
87
|
+
const visited = new Set([locale]);
|
|
88
|
+
while (fallbackLocale && !visited.has(fallbackLocale)) {
|
|
89
|
+
visited.add(fallbackLocale);
|
|
90
|
+
if (Object.hasOwn(args.compiledMessages, fallbackLocale)) {
|
|
91
|
+
fallbackTargets.add(fallbackLocale);
|
|
92
|
+
break;
|
|
93
|
+
}
|
|
94
|
+
fallbackLocale = args.fallbackMap[fallbackLocale];
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
return Object.keys(args.inlinePlainTextByLocale).filter((locale) => !fallbackTargets.has(locale));
|
|
98
|
+
}
|
|
42
99
|
const compileBundleFunction = (args) => {
|
|
43
100
|
const inputs = args.bundle.declarations.filter((decl) => decl.type === "input-variable");
|
|
44
101
|
const hasInputs = inputs.length > 0;
|
|
@@ -52,6 +109,7 @@ const compileBundleFunction = (args) => {
|
|
|
52
109
|
baseLocale,
|
|
53
110
|
]
|
|
54
111
|
: args.availableLocales;
|
|
112
|
+
const allStringBranchesInline = dispatchLocales.every((locale) => args.inlinePlainTextByLocale?.[locale] !== undefined);
|
|
55
113
|
const inputType = args.inputTypeAliasName;
|
|
56
114
|
const localesUnion = args.availableLocales.length === 0
|
|
57
115
|
? "never"
|
|
@@ -70,6 +128,10 @@ const compileBundleFunction = (args) => {
|
|
|
70
128
|
const prefix = index > 0 ? continuationIndent : "";
|
|
71
129
|
const messageRef = args.messageReferenceExpression(locale, args.bundle.id);
|
|
72
130
|
if (mode === "string") {
|
|
131
|
+
const inlineText = args.inlinePlainTextByLocale?.[locale];
|
|
132
|
+
if (inlineText !== undefined) {
|
|
133
|
+
return `${prefix}${condition}return /** @type {LocalizedString} */ (${JSON.stringify(inlineText)})`;
|
|
134
|
+
}
|
|
73
135
|
return `${prefix}${condition}return ${messageRef}(inputs)`;
|
|
74
136
|
}
|
|
75
137
|
// A locale's message has .parts() only if its own variants have
|
|
@@ -125,10 +187,13 @@ ${englishMatchTableDoc}${jsDocBundleFunctionTypes({
|
|
|
125
187
|
}
|
|
126
188
|
return `${indent}const locale = ${localeExpression}${overrideWarning}${maybeTrackMessageCall(indent)}`;
|
|
127
189
|
};
|
|
190
|
+
const keepUnusedInputsParameter = (indent) => allStringBranchesInline && !args.experimentalMiddlewareLocaleSplitting
|
|
191
|
+
? `\n${indent}void inputs;`
|
|
192
|
+
: "";
|
|
128
193
|
let code = "";
|
|
129
194
|
if (!args.hasMarkup) {
|
|
130
195
|
code = `${commonJsDoc}
|
|
131
|
-
${isSafeBundleId ? "export " : ""}const ${safeBundleId} = /** @type {(${bundleFunctionType}) & ${messageMetadataType}} */ ((inputs${hasInputs ? "" : " = {}"}, options = {}) => {${clientMiddlewareGuard("\t")}
|
|
196
|
+
${isSafeBundleId ? "export " : ""}const ${safeBundleId} = /** @type {(${bundleFunctionType}) & ${messageMetadataType}} */ ((inputs${hasInputs ? "" : " = {}"}, options = {}) => {${clientMiddlewareGuard("\t")}${keepUnusedInputsParameter("\t")}
|
|
132
197
|
${localeResolutionStatement("\t")}
|
|
133
198
|
${compileLocaleReturnStatements("string", "\t")}${!isFullyTranslated
|
|
134
199
|
? `\n return /** @type {LocalizedString} */ ("${args.bundle.id}")`
|
|
@@ -139,7 +204,7 @@ ${localeResolutionStatement("\t")}
|
|
|
139
204
|
code = `${commonJsDoc}
|
|
140
205
|
${isSafeBundleId ? "export " : ""}const ${safeBundleId} = /** @type {(${bundleFunctionType}) & { parts: ${partsFunctionType} } & ${messageMetadataType}} */ (
|
|
141
206
|
/* @__PURE__ */ Object.assign(
|
|
142
|
-
/** @type {${bundleFunctionType}} */ ((inputs${hasInputs ? "" : " = {}"}, options = {}) => {${clientMiddlewareGuard("\t\t\t")}
|
|
207
|
+
/** @type {${bundleFunctionType}} */ ((inputs${hasInputs ? "" : " = {}"}, options = {}) => {${clientMiddlewareGuard("\t\t\t")}${keepUnusedInputsParameter("\t\t\t")}
|
|
143
208
|
${localeResolutionStatement("\t\t\t")}
|
|
144
209
|
${compileLocaleReturnStatements("string", "\t\t\t")}${!isFullyTranslated
|
|
145
210
|
? `\n return /** @type {LocalizedString} */ (${JSON.stringify(args.bundle.id)})`
|