@x18n/node 0.0.12 → 0.0.14
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.mjs +108 -9
- package/package.json +3 -3
package/dist/index.mjs
CHANGED
|
@@ -3,11 +3,12 @@ import { existsSync, readFileSync } from "node:fs";
|
|
|
3
3
|
import { mkdir, readFile, readdir, rm, writeFile } from "node:fs/promises";
|
|
4
4
|
import { dirname, isAbsolute, join, relative, resolve, sep } from "node:path";
|
|
5
5
|
import { fileURLToPath, pathToFileURL } from "node:url";
|
|
6
|
-
import { compileYamlPlugin } from "@x18n/builtins/yaml-plugin";
|
|
7
6
|
import { PluginFileSchema, createProject, errors, hashText, isX18nError, resolveConfig, validate } from "@x18n/core";
|
|
8
7
|
import { createJiti } from "jiti";
|
|
9
8
|
import { glob } from "tinyglobby";
|
|
10
9
|
import { parse, stringify } from "yaml";
|
|
10
|
+
import { placeholderFromShape } from "@x18n/builtins/placeholders";
|
|
11
|
+
import regexScopes from "@x18n/builtins/scanners/regex-scopes";
|
|
11
12
|
import process from "node:process";
|
|
12
13
|
import { watch } from "chokidar";
|
|
13
14
|
import ignore from "ignore";
|
|
@@ -15,6 +16,76 @@ import { createBuiltins } from "@x18n/builtins";
|
|
|
15
16
|
import { Buffer } from "node:buffer";
|
|
16
17
|
import { execFile, spawn } from "node:child_process";
|
|
17
18
|
import { applyEdits, modify, parse as parse$1 } from "jsonc-parser";
|
|
19
|
+
//#region src/yaml-plugin.ts
|
|
20
|
+
/**
|
|
21
|
+
* Compiles a validated YAML plugin into plugin objects. Each section maps to the
|
|
22
|
+
* options of a built-in factory, so moving to a TS plugin is a small change.
|
|
23
|
+
*/
|
|
24
|
+
function compileYamlPlugin(data) {
|
|
25
|
+
const replacements = (data.normalizeKey ?? []).map((rule) => ({
|
|
26
|
+
from: new RegExp(rule.replace.pattern, "g"),
|
|
27
|
+
to: rule.replace.with
|
|
28
|
+
}));
|
|
29
|
+
const localeInfo = data.localeInfo;
|
|
30
|
+
const plugin = {
|
|
31
|
+
name: data.name,
|
|
32
|
+
config(draft) {
|
|
33
|
+
const defaults = data.config;
|
|
34
|
+
if (defaults?.sourceLocale) draft.sourceLocale = defaults.sourceLocale;
|
|
35
|
+
if (defaults?.locales) draft.locales = defaults.locales;
|
|
36
|
+
if (defaults?.resources && draft.resources.length === 0) draft.resources = defaults.resources;
|
|
37
|
+
if (defaults?.keyStyle) draft.keyStyle = defaults.keyStyle;
|
|
38
|
+
if (defaults?.namespace) draft.namespace = {
|
|
39
|
+
separator: defaults.namespace.separator ?? draft.namespace.separator,
|
|
40
|
+
default: defaults.namespace.default ?? draft.namespace.default,
|
|
41
|
+
fallback: defaults.namespace.fallback ?? draft.namespace.fallback,
|
|
42
|
+
byFile: {
|
|
43
|
+
...draft.namespace.byFile,
|
|
44
|
+
...defaults.namespace.byFile
|
|
45
|
+
},
|
|
46
|
+
fromPath: defaults.namespace.fromPath ?? draft.namespace.fromPath
|
|
47
|
+
};
|
|
48
|
+
draft.usage = {
|
|
49
|
+
...draft.usage,
|
|
50
|
+
calls: [...draft.usage.calls, ...data.scanners?.calls ?? []],
|
|
51
|
+
regex: [...draft.usage.regex, ...data.scanners?.regex ?? []]
|
|
52
|
+
};
|
|
53
|
+
if (data.extract?.templates) draft.extract = {
|
|
54
|
+
...draft.extract,
|
|
55
|
+
templates: [...draft.extract.templates ?? [], ...data.extract.templates]
|
|
56
|
+
};
|
|
57
|
+
},
|
|
58
|
+
derivedKeys: data.derivedKeys,
|
|
59
|
+
placeholders: data.placeholders?.map(placeholderFromShape),
|
|
60
|
+
normalizeKey: replacements.length > 0 ? (raw) => replacements.reduce((text, rule) => text.replace(rule.from, rule.to), raw) : void 0,
|
|
61
|
+
localeInfo: localeInfo ? (code) => {
|
|
62
|
+
const info = localeInfo[code];
|
|
63
|
+
return info ? {
|
|
64
|
+
...info.flag ? { flag: info.flag } : {},
|
|
65
|
+
...info.displayName ? { displayName: info.displayName } : {}
|
|
66
|
+
} : void 0;
|
|
67
|
+
} : void 0
|
|
68
|
+
};
|
|
69
|
+
const plugins = [plugin, ...data.scopes ? [regexScopes(data.scopes.regex, `${data.name}-scopes`)] : []];
|
|
70
|
+
const detect = data.detect;
|
|
71
|
+
if (!detect) return plugins.length === 1 ? plugin : {
|
|
72
|
+
name: data.name,
|
|
73
|
+
plugins
|
|
74
|
+
};
|
|
75
|
+
return {
|
|
76
|
+
name: data.name,
|
|
77
|
+
exclusive: data.exclusive,
|
|
78
|
+
plugins,
|
|
79
|
+
async detect(ctx) {
|
|
80
|
+
const deps = detect.dependencies;
|
|
81
|
+
if (deps?.any && !ctx.hasAnyDependency(deps.any)) return false;
|
|
82
|
+
if (deps?.all && !deps.all.every(ctx.hasDependency)) return false;
|
|
83
|
+
for (const pattern of detect.files ?? []) if (!await ctx.fileExists(pattern)) return false;
|
|
84
|
+
return true;
|
|
85
|
+
}
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
//#endregion
|
|
18
89
|
//#region src/config.ts
|
|
19
90
|
const configFileNames = [
|
|
20
91
|
"x18n.config.ts",
|
|
@@ -43,6 +114,15 @@ function findConfigUpward(cwd) {
|
|
|
43
114
|
dir = parent;
|
|
44
115
|
}
|
|
45
116
|
}
|
|
117
|
+
/** One config file per directory below `dir`, shallowest first. */
|
|
118
|
+
async function findConfigsBelow(dir) {
|
|
119
|
+
const files = await glob(configFileNames.map((name) => `**/${name}`), {
|
|
120
|
+
cwd: dir,
|
|
121
|
+
absolute: true,
|
|
122
|
+
ignore: ["**/node_modules/**"]
|
|
123
|
+
});
|
|
124
|
+
return [...new Set(files.map((file) => dirname(file)))].sort((a, b) => a.split("/").length - b.split("/").length || a.localeCompare(b)).flatMap((found) => findConfigFile(found) ?? []);
|
|
125
|
+
}
|
|
46
126
|
function resolveOwn(specifier) {
|
|
47
127
|
try {
|
|
48
128
|
return fileURLToPath(import.meta.resolve(specifier));
|
|
@@ -153,7 +233,9 @@ async function manifestRootsOf(root, gitRoot) {
|
|
|
153
233
|
}
|
|
154
234
|
//#endregion
|
|
155
235
|
//#region src/host.ts
|
|
156
|
-
|
|
236
|
+
function toPosix(path) {
|
|
237
|
+
return sep === "\\" ? path.replace(/\\/g, "/") : path;
|
|
238
|
+
}
|
|
157
239
|
function isNotFound(error) {
|
|
158
240
|
return error instanceof Error && "code" in error && (error.code === "ENOENT" || error.code === "EISDIR");
|
|
159
241
|
}
|
|
@@ -719,10 +801,17 @@ const keygenStyles = {
|
|
|
719
801
|
"kebab-case": "kebab"
|
|
720
802
|
};
|
|
721
803
|
const editorSettings = {
|
|
722
|
-
annotations: "x18n.annotations",
|
|
723
|
-
annotationInPlace: "x18n.
|
|
724
|
-
|
|
725
|
-
|
|
804
|
+
"annotations": "x18n.annotations",
|
|
805
|
+
"annotationInPlace": "x18n.annotationInPlace",
|
|
806
|
+
"annotationInPlaceFullMatch": "x18n.annotationInPlaceFullMatch",
|
|
807
|
+
"annotationMaxLength": "x18n.annotationMaxLength",
|
|
808
|
+
"displayLanguage": "x18n.displayLocale",
|
|
809
|
+
"showFlags": "x18n.showFlags",
|
|
810
|
+
"theme.annotation": "x18n.theme.annotation",
|
|
811
|
+
"theme.annotationMissing": "x18n.theme.annotationMissing",
|
|
812
|
+
"theme.annotationBorder": "x18n.theme.annotationBorder",
|
|
813
|
+
"theme.annotationMissingBorder": "x18n.theme.annotationMissingBorder",
|
|
814
|
+
"theme.annotationInPlaceFullMatch": "x18n.theme.annotationInPlaceFullMatch"
|
|
726
815
|
};
|
|
727
816
|
const handledByDefaults = [
|
|
728
817
|
"readonly",
|
|
@@ -731,7 +820,6 @@ const handledByDefaults = [
|
|
|
731
820
|
"includeSubfolders",
|
|
732
821
|
"ignoreFiles",
|
|
733
822
|
"editor.preferEditor",
|
|
734
|
-
"showFlags",
|
|
735
823
|
"annotationDelimiter",
|
|
736
824
|
"languageTagSystem",
|
|
737
825
|
"targetPickingStrategy",
|
|
@@ -753,7 +841,9 @@ async function readFirst(root, paths) {
|
|
|
753
841
|
function isRecord(value) {
|
|
754
842
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
755
843
|
}
|
|
756
|
-
|
|
844
|
+
function asStrings(value) {
|
|
845
|
+
return (Array.isArray(value) ? value : value === void 0 ? [] : [value]).filter((v) => typeof v === "string");
|
|
846
|
+
}
|
|
757
847
|
/** Setting prefixes by priority: the i18n-ally-next fork renames `i18n-ally.*` keys, so its value is the newest. */
|
|
758
848
|
const settingPrefixes = [
|
|
759
849
|
"i18n-ally-next",
|
|
@@ -1121,6 +1211,15 @@ function applyDefaults(draft, config) {
|
|
|
1121
1211
|
}
|
|
1122
1212
|
async function projectSpecs(rootConfigFile, cwd, upward) {
|
|
1123
1213
|
if (!rootConfigFile) {
|
|
1214
|
+
const nested = await findConfigsBelow(cwd);
|
|
1215
|
+
if (nested.length) {
|
|
1216
|
+
const specs = [];
|
|
1217
|
+
for (const file of nested) if (!specs.some((spec) => spec.configFile === file)) specs.push(...(await projectSpecs(file, cwd, false)).specs);
|
|
1218
|
+
return {
|
|
1219
|
+
root: resolve(cwd),
|
|
1220
|
+
specs
|
|
1221
|
+
};
|
|
1222
|
+
}
|
|
1124
1223
|
const settingsRoot = findI18nAllyRoot(cwd, upward);
|
|
1125
1224
|
const fallback = settingsRoot && await i18nAllyFallback(settingsRoot);
|
|
1126
1225
|
if (settingsRoot && fallback) return {
|
|
@@ -1173,7 +1272,7 @@ async function loadWorkspace(options) {
|
|
|
1173
1272
|
const configFile = options.configFile ? resolve(options.cwd, options.configFile) : options.upward === false ? findConfigFile(resolve(options.cwd)) : findConfigUpward(options.cwd);
|
|
1174
1273
|
const { root, specs } = await projectSpecs(configFile, options.cwd, options.upward !== false);
|
|
1175
1274
|
const gitRoot = findGitRoot(root);
|
|
1176
|
-
const defaults = options.builtins ?? createBuiltins();
|
|
1275
|
+
const defaults = options.builtins ?? await createBuiltins();
|
|
1177
1276
|
const builtins = gitRoot ? {
|
|
1178
1277
|
...defaults,
|
|
1179
1278
|
plugins: [...defaults.plugins, gitHistory()]
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@x18n/node",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.0.
|
|
4
|
+
"version": "0.0.14",
|
|
5
5
|
"description": "Node.js host for x18n: file system access, config and plugin loading",
|
|
6
6
|
"author": "Anthony Fu <anthonyfu117@hotmail.com>",
|
|
7
7
|
"license": "MIT",
|
|
@@ -25,8 +25,8 @@
|
|
|
25
25
|
"node": ">=22"
|
|
26
26
|
},
|
|
27
27
|
"dependencies": {
|
|
28
|
-
"@x18n/builtins": "0.0.
|
|
29
|
-
"@x18n/core": "0.0.
|
|
28
|
+
"@x18n/builtins": "0.0.14",
|
|
29
|
+
"@x18n/core": "0.0.14",
|
|
30
30
|
"chokidar": "^6.0.0",
|
|
31
31
|
"ignore": "^7.0.13",
|
|
32
32
|
"jiti": "^2.7.0",
|