@x18n/builtins 0.0.0 → 0.0.2

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.
@@ -1,188 +0,0 @@
1
- //#region src/finders/pattern.ts
2
- const localeLike = /^[a-z]{2,3}(?:[-_][a-z\d]{2,8})*$/i;
3
- function isLocaleCode(text) {
4
- if (!localeLike.test(text)) return false;
5
- try {
6
- return Intl.getCanonicalLocales(text.replace(/_/g, "-")).length === 1;
7
- } catch {
8
- return false;
9
- }
10
- }
11
- function escapeRegExp(text) {
12
- return text.replace(/[.+^$()|[\]\\]/g, "\\$&");
13
- }
14
- /**
15
- * Compiles a resource pattern. Tokens: `{locale}`, `{locale?}`, `{namespace}`,
16
- * `{namespaces}` (several segments, joined with `.`), `{ext}`; plus `*` and `**`.
17
- */
18
- function compilePattern(pattern, extensions) {
19
- const normalized = pattern.replace(/^\.\//, "");
20
- const ext = `(?<ext>${extensions.map(escapeRegExp).join("|")})`;
21
- let source = "";
22
- let glob = "";
23
- const tokens = /\{[^}]*\}|\*\*\/|\*\*|\*|\?/g;
24
- let last = 0;
25
- for (const match of normalized.matchAll(tokens)) {
26
- const literal = normalized.slice(last, match.index);
27
- source += escapeRegExp(literal);
28
- glob += literal;
29
- last = match.index + match[0].length;
30
- switch (match[0]) {
31
- case "{locale}":
32
- source += "(?<locale>[\\w-]+)";
33
- glob += "*";
34
- break;
35
- case "{locale?}":
36
- source += "(?<locale>[\\w-]+)?";
37
- glob += "*";
38
- break;
39
- case "{namespace}":
40
- source += "(?<namespace>[^/]+)";
41
- glob += "*";
42
- break;
43
- case "{namespaces}":
44
- source += "(?<namespace>.+)";
45
- glob += "**";
46
- break;
47
- case "{ext}":
48
- source += ext;
49
- glob += extensions.length === 1 ? extensions[0] : `{${extensions.join(",")}}`;
50
- break;
51
- case "**/":
52
- source += "(?:.*/)?";
53
- glob += "**/";
54
- break;
55
- case "**":
56
- source += ".*";
57
- glob += "**";
58
- break;
59
- case "*":
60
- source += "[^/]*";
61
- glob += "*";
62
- break;
63
- case "?":
64
- source += "[^/]";
65
- glob += "?";
66
- break;
67
- default: {
68
- const options = match[0].slice(1, -1).split(",");
69
- source += `(?:${options.map(escapeRegExp).join("|")})`;
70
- glob += match[0];
71
- }
72
- }
73
- }
74
- source += escapeRegExp(normalized.slice(last));
75
- glob += normalized.slice(last);
76
- const regex = new RegExp(`^${source}$`);
77
- return {
78
- glob,
79
- match(path) {
80
- const found = regex.exec(path);
81
- if (!found) return void 0;
82
- const groups = found.groups ?? {};
83
- const extension = groups.ext ?? path.slice(path.lastIndexOf(".") + 1);
84
- return {
85
- locale: groups.locale,
86
- namespace: groups.namespace?.replace(/\//g, "."),
87
- ext: extension
88
- };
89
- }
90
- };
91
- }
92
- const localeDirNames = [
93
- "locales",
94
- "locale",
95
- "i18n",
96
- "lang",
97
- "langs",
98
- "language",
99
- "languages",
100
- "translations",
101
- "messages",
102
- "_locales",
103
- "l10n"
104
- ];
105
- /** Guesses resource patterns from directories named like `locales`, as i18n-ally did without `localesPaths`. */
106
- async function guessResources(ctx) {
107
- const exts = ctx.extensions.length === 1 ? ctx.extensions[0] : `{${ctx.extensions.join(",")}}`;
108
- const files = await ctx.host.glob([`**/{${localeDirNames.join(",")}}/**/*.${exts}`], {
109
- ignore: [
110
- "**/node_modules/**",
111
- "**/dist/**",
112
- "**/.git/**",
113
- "**/.nuxt/**",
114
- "**/.output/**",
115
- "**/build/**"
116
- ],
117
- gitignore: true
118
- });
119
- const dirs = /* @__PURE__ */ new Map();
120
- for (const file of files) {
121
- const segments = file.split("/");
122
- const index = segments.findLastIndex((segment) => localeDirNames.includes(segment));
123
- const dir = segments.slice(0, index + 1).join("/");
124
- const list = dirs.get(dir) ?? [];
125
- dirs.set(dir, list);
126
- list.push(segments.slice(index + 1).join("/"));
127
- }
128
- const specs = [];
129
- for (const [dir, rest] of dirs) {
130
- const stem = (file) => file.slice(0, file.lastIndexOf("."));
131
- const fileLayout = rest.filter((file) => !file.includes("/") && isLocaleCode(stem(file))).length;
132
- const dirLayout = rest.filter((file) => file.includes("/") && isLocaleCode(file.split("/")[0])).length;
133
- if (fileLayout === 0 && dirLayout === 0) continue;
134
- specs.push({ pattern: fileLayout >= dirLayout ? `${dir}/{locale}.{ext}` : `${dir}/{locale}/{namespaces}.{ext}` });
135
- }
136
- return specs;
137
- }
138
- async function findBySpecs(ctx, specs, guessed) {
139
- const out = [];
140
- for (const spec of specs) {
141
- const compiled = compilePattern(spec.pattern, ctx.extensions);
142
- const fixed = spec.locale ?? (spec.pattern.includes("{locale") ? void 0 : ctx.config.sourceLocale);
143
- const paths = await ctx.host.glob([compiled.glob], {
144
- ignore: ["**/node_modules/**"],
145
- gitignore: false
146
- });
147
- for (const path of paths) {
148
- const matched = compiled.match(path);
149
- if (!matched) continue;
150
- const locale = fixed ?? matched.locale ?? (spec.pattern.includes("{locale?}") ? ctx.config.sourceLocale : void 0);
151
- if (!locale || guessed && !isLocaleCode(locale)) continue;
152
- out.push({
153
- path,
154
- locale,
155
- namespace: spec.namespace ?? matched.namespace,
156
- format: spec.format,
157
- readonly: spec.execute === true
158
- });
159
- }
160
- }
161
- return out;
162
- }
163
- const patternFinder = {
164
- id: "pattern",
165
- resolveNew(target, ctx) {
166
- for (const spec of ctx.config.resources) {
167
- if (/\{namespaces?\}/.test(spec.pattern) !== (target.namespace !== void 0) || spec.execute || !spec.pattern.includes("{locale")) continue;
168
- const path = spec.pattern.replace(/^\.\//, "").replace(/\{locale\??\}/g, target.locale).replace("{namespaces}", (target.namespace ?? "").replace(/\./g, "/")).replace("{namespace}", target.namespace ?? "").replace("{ext}", spec.format === "yaml" ? "yml" : spec.format ?? "json");
169
- if (!/[*?{}[\]]/.test(path)) return path;
170
- }
171
- },
172
- async find(ctx) {
173
- const configured = ctx.config.resources;
174
- const found = configured.length > 0 ? await findBySpecs(ctx, configured, false) : [];
175
- const fromUser = ctx.config.origins.resources === "user" || ctx.config.origins.resources === "parent";
176
- if (found.length > 0 || fromUser) return found;
177
- return findBySpecs(ctx, await guessResources(ctx), true);
178
- }
179
- };
180
- /** The `pattern` locale finder: files that match `resources[].pattern`, or guessed locale directories. */
181
- function pattern() {
182
- return {
183
- name: "x18n:finder-pattern",
184
- localeFinders: [patternFinder]
185
- };
186
- }
187
- //#endregion
188
- export { patternFinder as i, guessResources as n, pattern as r, compilePattern as t };
@@ -1,29 +0,0 @@
1
- import { FinderContext, LocaleFinder, Plugin, ResourceSpec } from "@x18n/core";
2
- //#region src/finders/pattern.d.ts
3
- interface CompiledPattern {
4
- /** Glob for the host. */
5
- readonly glob: string;
6
- readonly match: (path: string) => {
7
- locale: string | undefined;
8
- namespace: string | undefined;
9
- ext: string;
10
- } | undefined;
11
- }
12
- /**
13
- * Compiles a resource pattern. Tokens: `{locale}`, `{locale?}`, `{namespace}`,
14
- * `{namespaces}` (several segments, joined with `.`), `{ext}`; plus `*` and `**`.
15
- */
16
- export declare function compilePattern(pattern: string, extensions: readonly string[]): CompiledPattern;
17
- /** Guesses resource patterns from directories named like `locales`, as i18n-ally did without `localesPaths`. */
18
- export declare function guessResources(ctx: FinderContext): Promise<ResourceSpec[]>;
19
- export declare const patternFinder: LocaleFinder;
20
- /** The `pattern` locale finder: files that match `resources[].pattern`, or guessed locale directories. */
21
- export declare function pattern(): Plugin;
22
- //#endregion
23
- //#region src/finders/sfc-blocks.d.ts
24
- /** Vue `<i18n>` blocks: one resource per block and locale (`locale="en"`, or every top-level locale key). */
25
- export declare function sfcBlocks(): Plugin;
26
- /** fluent-vue `<fluent locale="en">` blocks in Vue SFCs, read with the `ftl` format. */
27
- export declare function sfcFluentBlocks(): Plugin;
28
- //#endregion
29
- export type { CompiledPattern };
package/dist/finders.mjs DELETED
@@ -1,3 +0,0 @@
1
- import { i as patternFinder, n as guessResources, r as pattern, t as compilePattern } from "./finders-Cf-IEaDm.mjs";
2
- import { n as sfcFluentBlocks, t as sfcBlocks } from "./sfc-blocks-CQhgEeT6.mjs";
3
- export { compilePattern, guessResources, pattern, patternFinder, sfcBlocks, sfcFluentBlocks };