wuchale 0.23.3 → 0.24.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/dist/adapter-utils/mixed-visitor.d.ts +21 -14
- package/dist/adapter-utils/mixed-visitor.js +110 -101
- package/dist/adapter-vanilla/index.js +8 -6
- package/dist/adapter-vanilla/inertvisitors.d.ts +31 -0
- package/dist/adapter-vanilla/inertvisitors.js +86 -0
- package/dist/adapter-vanilla/transformer.d.ts +67 -95
- package/dist/adapter-vanilla/transformer.js +292 -240
- package/dist/adapters.d.ts +18 -12
- package/dist/adapters.js +33 -13
- package/dist/ai/gemini.js +1 -1
- package/dist/ai/index.js +3 -1
- package/dist/bundlers/vite.d.ts +1 -1
- package/dist/bundlers/vite.js +3 -3
- package/dist/cli/check.js +1 -1
- package/dist/cli/index.js +12 -5
- package/dist/cli/status.js +1 -1
- package/dist/config.d.ts +2 -1
- package/dist/config.js +2 -2
- package/dist/handler/files.d.ts +11 -13
- package/dist/handler/files.js +37 -44
- package/dist/handler/index.d.ts +7 -4
- package/dist/handler/index.js +85 -62
- package/dist/handler/state.d.ts +10 -11
- package/dist/handler/state.js +40 -28
- package/dist/handler/url.d.ts +10 -13
- package/dist/handler/url.js +51 -80
- package/dist/hub.d.ts +1 -1
- package/dist/hub.js +16 -14
- package/dist/index.d.ts +3 -3
- package/dist/index.js +2 -2
- package/dist/load-utils/index.d.ts +6 -8
- package/dist/load-utils/index.js +11 -11
- package/dist/load-utils/pure.d.ts +2 -2
- package/dist/load-utils/server.d.ts +3 -3
- package/dist/load-utils/server.js +4 -7
- package/dist/pofile.d.ts +5 -5
- package/dist/pofile.js +23 -35
- package/dist/storage.d.ts +6 -3
- package/dist/storage.js +98 -0
- package/dist/url.d.ts +12 -10
- package/dist/url.js +206 -31
- package/package.json +4 -5
- package/src/adapter-vanilla/loaders/bundle.js +1 -1
- package/src/adapter-vanilla/loaders/server.js +3 -3
- package/src/adapter-vanilla/loaders/vite.js +2 -2
- package/src/adapter-vanilla/loaders/vite.ssr.js +3 -3
package/dist/adapters.d.ts
CHANGED
|
@@ -22,13 +22,16 @@ export type HeuristicDetails = HeuristicDetailsBase & {
|
|
|
22
22
|
topLevelCall?: string | undefined;
|
|
23
23
|
/** the name of the nearest call (for arguments) */
|
|
24
24
|
call?: string | undefined;
|
|
25
|
+
/** inside an export const ... etc */
|
|
26
|
+
exported?: boolean | undefined;
|
|
27
|
+
/** object property path */
|
|
28
|
+
property?: string | undefined;
|
|
25
29
|
};
|
|
26
30
|
export type MessageType = 'message' | 'url';
|
|
27
31
|
export type Message = {
|
|
28
32
|
msgStr: string[];
|
|
29
|
-
plural: boolean;
|
|
30
33
|
context?: string | undefined;
|
|
31
|
-
placeholders: [
|
|
34
|
+
placeholders: [string, string][];
|
|
32
35
|
details: HeuristicDetails;
|
|
33
36
|
type: MessageType;
|
|
34
37
|
};
|
|
@@ -43,6 +46,7 @@ export declare const defaultHeuristicOpts: {
|
|
|
43
46
|
ignoreCalls: string[];
|
|
44
47
|
urlAttribs: string[][];
|
|
45
48
|
urlCalls: string[];
|
|
49
|
+
urlProps: string[];
|
|
46
50
|
};
|
|
47
51
|
export type CreateHeuristicOpts = typeof defaultHeuristicOpts;
|
|
48
52
|
export declare function createHeuristic(opts: CreateHeuristicOpts): HeuristicFunc;
|
|
@@ -50,11 +54,12 @@ export declare function createHeuristic(opts: CreateHeuristicOpts): HeuristicFun
|
|
|
50
54
|
export declare const defaultHeuristic: HeuristicFunc;
|
|
51
55
|
/** Default heuristic which ignores messages outside functions in the `script` scope */
|
|
52
56
|
export declare const defaultHeuristicFuncOnly: HeuristicFunc;
|
|
53
|
-
export declare const defaultGenerateLoadID: (filename: string) => string;
|
|
54
57
|
export declare class IndexTracker {
|
|
55
|
-
|
|
56
|
-
|
|
58
|
+
#private;
|
|
59
|
+
constructor(bypassHas: boolean);
|
|
57
60
|
get: (msgStr: string) => number;
|
|
61
|
+
has: (msgStr: string) => boolean;
|
|
62
|
+
getAll: () => MapIterator<[string, number]>;
|
|
58
63
|
}
|
|
59
64
|
export type GlobConf = string | string[] | {
|
|
60
65
|
include: string | string[];
|
|
@@ -64,8 +69,8 @@ export type RuntimeExpr = {
|
|
|
64
69
|
plain: string;
|
|
65
70
|
reactive: string;
|
|
66
71
|
};
|
|
67
|
-
export type UrlMatcher = (url: string) => string | null
|
|
68
|
-
type TransformCtx = {
|
|
72
|
+
export type UrlMatcher = (url: string) => readonly [number, string[]] | null;
|
|
73
|
+
export type TransformCtx = {
|
|
69
74
|
content: string;
|
|
70
75
|
filename: string;
|
|
71
76
|
index: IndexTracker;
|
|
@@ -109,16 +114,17 @@ export type URLConf = {
|
|
|
109
114
|
patterns?: string[];
|
|
110
115
|
localize?: boolean | string;
|
|
111
116
|
};
|
|
117
|
+
export type LoadGroupPatt = string | string[];
|
|
112
118
|
export type AdapterPassThruOpts = {
|
|
113
119
|
sourceLocale?: string;
|
|
114
120
|
files: GlobConf;
|
|
115
121
|
storage: StorageFactory;
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
122
|
+
loading: {
|
|
123
|
+
direct: boolean;
|
|
124
|
+
granular: boolean;
|
|
125
|
+
group: LoadGroupPatt[];
|
|
126
|
+
};
|
|
120
127
|
url?: URLConf;
|
|
121
|
-
generateLoadID: (filename: string) => string;
|
|
122
128
|
runtime: RuntimeConf;
|
|
123
129
|
};
|
|
124
130
|
export type Adapter = AdapterPassThruOpts & {
|
package/dist/adapters.js
CHANGED
|
@@ -5,7 +5,6 @@ export function newMessage(init) {
|
|
|
5
5
|
}
|
|
6
6
|
return {
|
|
7
7
|
msgStr: init.msgStr,
|
|
8
|
-
plural: init.plural ?? false,
|
|
9
8
|
placeholders: init.placeholders ?? [],
|
|
10
9
|
type: init.type ?? 'message',
|
|
11
10
|
context: init.context,
|
|
@@ -23,6 +22,7 @@ export const defaultHeuristicOpts = {
|
|
|
23
22
|
ignoreCalls: ['fetch'],
|
|
24
23
|
urlAttribs: [['a', 'href']],
|
|
25
24
|
urlCalls: [],
|
|
25
|
+
urlProps: ['href', 'link', 'url'],
|
|
26
26
|
};
|
|
27
27
|
export function createHeuristic(opts) {
|
|
28
28
|
return msg => {
|
|
@@ -46,6 +46,13 @@ export function createHeuristic(opts) {
|
|
|
46
46
|
}
|
|
47
47
|
}
|
|
48
48
|
}
|
|
49
|
+
if (msg.details.property) {
|
|
50
|
+
for (const prop of opts.urlProps) {
|
|
51
|
+
if (msg.details.property === prop || msg.details.property?.endsWith(`.${prop}`)) {
|
|
52
|
+
return 'url';
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
}
|
|
49
56
|
if (msg.details.attribute) {
|
|
50
57
|
for (const [element, attrib] of opts.urlAttribs) {
|
|
51
58
|
if (msg.details.element === element && msg.details.attribute === attrib) {
|
|
@@ -61,11 +68,19 @@ export function createHeuristic(opts) {
|
|
|
61
68
|
return 'message';
|
|
62
69
|
}
|
|
63
70
|
// script and attribute
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
if (
|
|
71
|
+
if (/^([A-Z]|\P{L})+$/u.test(msgStr)) {
|
|
72
|
+
// only upper-case English and non-letters
|
|
73
|
+
return false;
|
|
74
|
+
}
|
|
75
|
+
if (/^\{\d+\}/.test(msgStr)) {
|
|
76
|
+
// template literals that begin with a placeholder expression
|
|
77
|
+
if (!/\s\p{L}/u.test(msgStr)) {
|
|
78
|
+
// should contain spaces and letters
|
|
79
|
+
return false;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
else if (/[a-z]|\P{L}/u.test(msgStr[0])) {
|
|
83
|
+
// ignore non-letter and lower-case English beginnings
|
|
69
84
|
return false;
|
|
70
85
|
}
|
|
71
86
|
if (msg.details.scope === 'attribute') {
|
|
@@ -90,18 +105,23 @@ export const defaultHeuristicFuncOnly = msg => {
|
|
|
90
105
|
}
|
|
91
106
|
return false;
|
|
92
107
|
};
|
|
93
|
-
export const defaultGenerateLoadID = (filename) => filename.replace(/[^a-zA-Z0-9_]+/g, '_');
|
|
94
108
|
export class IndexTracker {
|
|
95
|
-
indices = new Map();
|
|
96
|
-
nextIndex = 0;
|
|
109
|
+
#indices = new Map();
|
|
110
|
+
#nextIndex = 0;
|
|
111
|
+
#bypassHas;
|
|
112
|
+
constructor(bypassHas) {
|
|
113
|
+
this.#bypassHas = bypassHas;
|
|
114
|
+
}
|
|
97
115
|
get = (msgStr) => {
|
|
98
|
-
let index = this
|
|
116
|
+
let index = this.#indices.get(msgStr);
|
|
99
117
|
if (index != null) {
|
|
100
118
|
return index;
|
|
101
119
|
}
|
|
102
|
-
index = this
|
|
103
|
-
this
|
|
104
|
-
this
|
|
120
|
+
index = this.#nextIndex;
|
|
121
|
+
this.#indices.set(msgStr, index);
|
|
122
|
+
this.#nextIndex++;
|
|
105
123
|
return index;
|
|
106
124
|
};
|
|
125
|
+
has = (msgStr) => this.#bypassHas || this.#indices.has(msgStr);
|
|
126
|
+
getAll = () => this.#indices.entries();
|
|
107
127
|
}
|
package/dist/ai/gemini.js
CHANGED
|
@@ -15,7 +15,7 @@ function prepareData(content, instruction, think) {
|
|
|
15
15
|
},
|
|
16
16
|
};
|
|
17
17
|
}
|
|
18
|
-
export function gemini({ apiKey = 'env', model = 'gemini-
|
|
18
|
+
export function gemini({ apiKey = 'env', model = 'gemini-3.5-flash', group = {}, batchSize = 50, think = false, parallel = 4, } = {}) {
|
|
19
19
|
if (apiKey === 'env') {
|
|
20
20
|
apiKey = process.env['GEMINI_API_KEY'] ?? '';
|
|
21
21
|
}
|
package/dist/ai/index.js
CHANGED
|
@@ -43,7 +43,9 @@ Respond with a JSON array matching the order of the input items. Each element is
|
|
|
43
43
|
Output schema:
|
|
44
44
|
${JSON.stringify(outputSchema)}
|
|
45
45
|
|
|
46
|
-
|
|
46
|
+
CRITICAL!:
|
|
47
|
+
- ALWAYS Respond with a raw compact JSON array even if there is only one item.
|
|
48
|
+
- NEVER wrap it in markdown code fences or any other surrounding text.
|
|
47
49
|
`.trim();
|
|
48
50
|
// implements a queue for a sequential translation useful for vite's transform during dev
|
|
49
51
|
// as vite can do async transform
|
package/dist/bundlers/vite.d.ts
CHANGED
|
@@ -31,7 +31,7 @@ export declare const wuchale: ({ configPath, hmrDelayThreshold, trimQueryParams
|
|
|
31
31
|
order: "pre";
|
|
32
32
|
handler(code: string, id: string, options?: {
|
|
33
33
|
ssr?: boolean | undefined;
|
|
34
|
-
}): Promise<import("
|
|
34
|
+
}): Promise<import("../adapters.js").TransformOutputCode>;
|
|
35
35
|
};
|
|
36
36
|
};
|
|
37
37
|
export {};
|
package/dist/bundlers/vite.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { dirname } from 'node:path';
|
|
2
|
-
import { getConfig } from '
|
|
2
|
+
import { getConfig } from '../config.js';
|
|
3
3
|
import { Hub, pluginName } from '../hub.js';
|
|
4
4
|
export function toViteError(err, adapterKey, filename) {
|
|
5
5
|
const prefix = `${adapterKey}: transform failed for ${filename}`;
|
|
@@ -49,11 +49,11 @@ export function trimViteQueries(id, trimParams) {
|
|
|
49
49
|
}
|
|
50
50
|
export const wuchale = ({ configPath, hmrDelayThreshold = 1000, trimQueryParams } = {}) => {
|
|
51
51
|
let hub;
|
|
52
|
-
const trimParams = new Set([...(trimQueryParams ?? []), 'v', 't', 'sentry-auto-wrap']);
|
|
52
|
+
const trimParams = new Set([...(trimQueryParams ?? []), 'v', 't', 'sentry-auto-wrap', 'tsr-split']);
|
|
53
53
|
return {
|
|
54
54
|
name: pluginName,
|
|
55
55
|
async configResolved(config) {
|
|
56
|
-
hub = await Hub.create(config.env.DEV ? 'dev' : 'build', () => getConfig(configPath), dirname(configPath ?? '.'), hmrDelayThreshold, undefined, toViteError);
|
|
56
|
+
hub = await Hub.create(config.env.DEV ? 'dev' : 'build', () => getConfig(configPath), dirname(configPath ?? '.'), [], hmrDelayThreshold, undefined, toViteError);
|
|
57
57
|
},
|
|
58
58
|
async handleHotUpdate(ctx) {
|
|
59
59
|
const changeInfo = await hub.onFileChange(ctx.file, ctx.read);
|
package/dist/cli/check.js
CHANGED
|
@@ -15,7 +15,7 @@ const checkErrMsgs = {
|
|
|
15
15
|
};
|
|
16
16
|
export async function check(config, root, full) {
|
|
17
17
|
// disable ai as this is a check, not persisted
|
|
18
|
-
const hub = await Hub.create('cli', () => ({ ...config, ai: null }), root, 0, readOnlyFS);
|
|
18
|
+
const hub = await Hub.create('cli', () => ({ ...config, ai: null }), root, [], 0, readOnlyFS);
|
|
19
19
|
const { checked, errors, syncs } = await hub.check(full);
|
|
20
20
|
// console.log because if the user invokes this command, they want full info regardless of config
|
|
21
21
|
for (const err of errors) {
|
package/dist/cli/index.js
CHANGED
|
@@ -38,6 +38,9 @@ const { positionals, values } = parseArgs({
|
|
|
38
38
|
short: 'l',
|
|
39
39
|
default: 'info',
|
|
40
40
|
},
|
|
41
|
+
modify: {
|
|
42
|
+
type: 'string',
|
|
43
|
+
},
|
|
41
44
|
help: {
|
|
42
45
|
type: 'boolean',
|
|
43
46
|
short: 'h',
|
|
@@ -57,10 +60,11 @@ Commands:
|
|
|
57
60
|
${color.cyan('check')} Check for errors
|
|
58
61
|
|
|
59
62
|
Options:
|
|
60
|
-
${color.cyan('--config')}
|
|
61
|
-
${color.cyan('--clean')}, ${color.cyan('-c')}
|
|
62
|
-
${color.cyan('--watch')}, ${color.cyan('-w')}
|
|
63
|
-
${color.cyan('--sync')}
|
|
63
|
+
${color.cyan('--config')} Use another config file instead of ${defaultConfigNames.map(color.cyan).join('|')}
|
|
64
|
+
${color.cyan('--clean')}, ${color.cyan('-c')} Remove unused messages from catalogs
|
|
65
|
+
${color.cyan('--watch')}, ${color.cyan('-w')} Continuously watch for file changes
|
|
66
|
+
${color.cyan('--sync')} Extract sequentially instead of in parallel
|
|
67
|
+
${color.cyan('--modify a1,a2')} Modify files in place for adapters ${color.cyan('a1')}, ${color.cyan('a2')}, etc.
|
|
64
68
|
${color.cyan('--log-level')}, ${color.cyan('-l')} {${Object.keys(logLevels).map(color.cyan)}} (only when no commands) set log level
|
|
65
69
|
${color.cyan('--help')}, ${color.cyan('-h')} Show this help
|
|
66
70
|
|
|
@@ -96,7 +100,10 @@ else if (values.help) {
|
|
|
96
100
|
}
|
|
97
101
|
else if (cmd == null) {
|
|
98
102
|
const [config, root] = await configRootLocales();
|
|
99
|
-
const hub = await Hub.create('cli', () => config, root
|
|
103
|
+
const hub = await Hub.create('cli', () => config, root, values.modify
|
|
104
|
+
?.split(',')
|
|
105
|
+
?.map(a => a.trim())
|
|
106
|
+
?.filter(a => a) ?? []);
|
|
100
107
|
await hub.directVisit(values.clean, values.watch, values.sync);
|
|
101
108
|
}
|
|
102
109
|
else {
|
package/dist/cli/status.js
CHANGED
|
@@ -13,7 +13,7 @@ Options:
|
|
|
13
13
|
`;
|
|
14
14
|
export async function status(config, root, json) {
|
|
15
15
|
// console.log because if the user invokes this command, they want full info regardless of config
|
|
16
|
-
const hub = await Hub.create('cli', () => config, root, 0, readOnlyFS);
|
|
16
|
+
const hub = await Hub.create('cli', () => config, root, [], 0, readOnlyFS);
|
|
17
17
|
if (json) {
|
|
18
18
|
console.log(JSON.stringify(await hub.status(), null, process.stdout.isTTY ? ' ' : undefined));
|
|
19
19
|
return;
|
package/dist/config.d.ts
CHANGED
|
@@ -8,9 +8,10 @@ export type ConfigPartial = {
|
|
|
8
8
|
ai: AI | null;
|
|
9
9
|
logLevel: LogLevel;
|
|
10
10
|
};
|
|
11
|
+
export type DevMode = false | 'read' | 'add' | 'refs' | 'clean';
|
|
11
12
|
export type Config = ConfigPartial & {
|
|
12
13
|
adapters: Record<string, Adapter>;
|
|
13
|
-
|
|
14
|
+
dev: DevMode;
|
|
14
15
|
};
|
|
15
16
|
export type DeepPartial<T> = {
|
|
16
17
|
[K in keyof T]?: T[K] extends (infer A)[] ? DeepPartial<A>[] : T[K] extends (...args: any[]) => any ? T[K] : T[K] extends object ? DeepPartial<T[K]> : T[K];
|
package/dist/config.js
CHANGED
|
@@ -5,14 +5,14 @@ export const defaultConfig = {
|
|
|
5
5
|
fallback: {},
|
|
6
6
|
localesDir: 'src/locales',
|
|
7
7
|
adapters: {},
|
|
8
|
-
|
|
8
|
+
dev: 'refs',
|
|
9
9
|
ai: defaultGemini,
|
|
10
10
|
logLevel: 'info',
|
|
11
11
|
};
|
|
12
12
|
function deepFill(target, defaults) {
|
|
13
13
|
for (const [key, def] of Object.entries(defaults)) {
|
|
14
14
|
const value = target[key];
|
|
15
|
-
if (Array.isArray(value)) {
|
|
15
|
+
if (value !== undefined && (typeof value !== 'object' || Array.isArray(value))) {
|
|
16
16
|
continue;
|
|
17
17
|
}
|
|
18
18
|
if (!def || Array.isArray(def) || typeof def !== 'object') {
|
package/dist/handler/files.d.ts
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
|
-
import type { Adapter, GlobConf, LoaderPath } from '../adapters.js';
|
|
1
|
+
import type { Adapter, GlobConf, LoaderPath, LoadGroupPatt } from '../adapters.js';
|
|
2
2
|
import type { CompiledElement } from '../compile.js';
|
|
3
3
|
import type { FS } from '../fs.js';
|
|
4
4
|
import type { URLManifest } from '../url.js';
|
|
5
5
|
export declare const dataFileName = "data.js";
|
|
6
6
|
export declare const generatedDir = ".wuchale";
|
|
7
|
+
export declare const defaultLoadID = 0;
|
|
7
8
|
export type ManifestEntryObj = {
|
|
8
9
|
text: string | string[];
|
|
9
10
|
context?: string | undefined;
|
|
@@ -22,25 +23,22 @@ export type FilesOptsCreate = FilesOptsCreatePass & {
|
|
|
22
23
|
};
|
|
23
24
|
export declare const objKeyLocale: (locale: string) => string;
|
|
24
25
|
export declare function normalizeSep(path: string): string;
|
|
25
|
-
export declare function globConfToArgs(conf: GlobConf,
|
|
26
|
-
ignore: string[];
|
|
27
|
-
}];
|
|
26
|
+
export declare function globConfToArgs(conf: GlobConf, localesDir: string): [string[], string[]];
|
|
28
27
|
export declare function getLoaderPath(adapter: Adapter, key: string, localesDirAbs: string, root: string, fs: FS): Promise<LoaderPath>;
|
|
29
28
|
export declare class Files {
|
|
30
29
|
#private;
|
|
31
30
|
readonly loaderPath: LoaderPath;
|
|
32
31
|
private constructor();
|
|
33
|
-
getCompiledFilePath(loc: string, id:
|
|
32
|
+
getCompiledFilePath(loc: string, id: number | null): string;
|
|
34
33
|
getImportPath(filename: string, importer?: string): string;
|
|
35
|
-
genProxyContent(catalogs: string[],
|
|
36
|
-
genProxy(locales: string[],
|
|
37
|
-
genProxySync(locales: string[],
|
|
38
|
-
writeProxies: (locales: string[],
|
|
34
|
+
genProxyContent(catalogs: string[], patterns: LoadGroupPatt[], locales: string[], syncImports?: string[]): string;
|
|
35
|
+
genProxy(locales: string[], patterns: LoadGroupPatt[]): string;
|
|
36
|
+
genProxySync(locales: string[], patterns: LoadGroupPatt[]): string;
|
|
37
|
+
writeProxies: (locales: string[], groupPatterns: LoadGroupPatt[]) => Promise<void>;
|
|
39
38
|
static create: (opts: FilesOptsCreate) => Promise<Files>;
|
|
40
39
|
writeUrlFiles: (manifest: URLManifest, fallbackLocale: string) => Promise<void>;
|
|
41
|
-
getManifestFilePath(id:
|
|
42
|
-
writeManifest: (keys: ManifestEntry[], id:
|
|
43
|
-
writeCatalogModule: (compiledData: CompiledElement[], pluralRule: string | null, locale: string, hmrVersion: number | null, loadID:
|
|
44
|
-
writeTransformed: (filename: string, content: string) => Promise<void>;
|
|
40
|
+
getManifestFilePath(id: number | null): string;
|
|
41
|
+
writeManifest: (keys: ManifestEntry[], id: number | null) => Promise<void>;
|
|
42
|
+
writeCatalogModule: (compiledData: CompiledElement[], pluralRule: string | null, locale: string, hmrVersion: number | null, loadID: number | null) => Promise<void>;
|
|
45
43
|
getImportLoaderPath(forServer: boolean, relativeTo: string): string;
|
|
46
44
|
}
|
package/dist/handler/files.js
CHANGED
|
@@ -2,6 +2,7 @@ import { dirname, relative, resolve } from 'node:path';
|
|
|
2
2
|
import { platform } from 'node:process';
|
|
3
3
|
export const dataFileName = 'data.js';
|
|
4
4
|
export const generatedDir = '.wuchale';
|
|
5
|
+
export const defaultLoadID = 0;
|
|
5
6
|
export const objKeyLocale = (locale) => (locale.includes('-') ? `'${locale}'` : locale);
|
|
6
7
|
export function normalizeSep(path) {
|
|
7
8
|
if (platform !== 'win32') {
|
|
@@ -9,13 +10,10 @@ export function normalizeSep(path) {
|
|
|
9
10
|
}
|
|
10
11
|
return path.replaceAll('\\', '/');
|
|
11
12
|
}
|
|
12
|
-
export function globConfToArgs(conf,
|
|
13
|
+
export function globConfToArgs(conf, localesDir) {
|
|
13
14
|
let patterns = [];
|
|
14
15
|
// ignore generated files
|
|
15
|
-
const
|
|
16
|
-
if (outDir) {
|
|
17
|
-
options.ignore.push(outDir);
|
|
18
|
-
}
|
|
16
|
+
const ignore = [`${localesDir}/**/*`];
|
|
19
17
|
if (typeof conf === 'string') {
|
|
20
18
|
patterns = [conf];
|
|
21
19
|
}
|
|
@@ -30,13 +28,13 @@ export function globConfToArgs(conf, root, localesDir, outDir) {
|
|
|
30
28
|
patterns = conf.include;
|
|
31
29
|
}
|
|
32
30
|
if (typeof conf.ignore === 'string') {
|
|
33
|
-
|
|
31
|
+
ignore.push(conf.ignore);
|
|
34
32
|
}
|
|
35
33
|
else {
|
|
36
|
-
|
|
34
|
+
ignore.push(...conf.ignore);
|
|
37
35
|
}
|
|
38
36
|
}
|
|
39
|
-
return [patterns.map(normalizeSep),
|
|
37
|
+
return [patterns.map(normalizeSep), ignore];
|
|
40
38
|
}
|
|
41
39
|
export async function getLoaderPath(adapter, key, localesDirAbs, root, fs) {
|
|
42
40
|
const loaderPathHead = resolve(localesDirAbs, `${key}.loader`);
|
|
@@ -107,7 +105,7 @@ export class Files {
|
|
|
107
105
|
}
|
|
108
106
|
getCompiledFilePath(loc, id) {
|
|
109
107
|
const ownerKey = this.#opts.ownerKey;
|
|
110
|
-
return resolve(this.#opts.localesDirAbs, generatedDir, `${ownerKey}.${id ??
|
|
108
|
+
return resolve(this.#opts.localesDirAbs, generatedDir, `${ownerKey}.${id ?? defaultLoadID}.${loc}.compiled.js`);
|
|
111
109
|
}
|
|
112
110
|
getImportPath(filename, importer) {
|
|
113
111
|
const relTo = importer ? resolve(this.#opts.root, importer) : filename;
|
|
@@ -118,48 +116,51 @@ export class Files {
|
|
|
118
116
|
return filename;
|
|
119
117
|
}
|
|
120
118
|
// typed to work regardless of user's noUncheckedIndexedAccess setting in tsconfig
|
|
121
|
-
genProxyContent(catalogs,
|
|
119
|
+
genProxyContent(catalogs, patterns, locales, syncImports) {
|
|
122
120
|
const baseType = 'import("wuchale/runtime").CatalogModule';
|
|
121
|
+
const byLocale = catalogs.map((locCats, i) => `${objKeyLocale(locales[i])}: ${locCats}`).join(',');
|
|
123
122
|
return `
|
|
124
123
|
${syncImports?.join('\n') ?? ''}
|
|
125
124
|
/** @typedef {${syncImports ? baseType : `() => Promise<${baseType}>`}} CatalogMod */
|
|
126
|
-
/** @
|
|
127
|
-
|
|
128
|
-
const
|
|
129
|
-
|
|
130
|
-
return /** @type {CatalogMod} */ (/** @type {KeyCatalogs} */ (catalogs[loadID])[locale])${syncImports ? '' : '()'}
|
|
125
|
+
/** @type {{[locale: string]: CatalogMod[]}} */
|
|
126
|
+
const catalogs = {${byLocale}}
|
|
127
|
+
export const loadCatalog = (/** @type {number} */ loadID, /** @type {string} */ locale) => {
|
|
128
|
+
return /** @type {CatalogMod} */ (/** @type {CatalogMod[]} */ (catalogs[locale])[loadID])${syncImports ? '' : '()'}
|
|
131
129
|
}
|
|
132
|
-
export const
|
|
130
|
+
export const loadCount = ${patterns.length}
|
|
131
|
+
// not essential. in case it is needed and for debugging
|
|
132
|
+
export const patterns = ${JSON.stringify(patterns)}
|
|
133
133
|
`;
|
|
134
134
|
}
|
|
135
|
-
genProxy(locales,
|
|
135
|
+
genProxy(locales, patterns) {
|
|
136
136
|
const imports = [];
|
|
137
|
-
for (const
|
|
138
|
-
const
|
|
139
|
-
for (const
|
|
140
|
-
|
|
137
|
+
for (const loc of locales) {
|
|
138
|
+
const importsForLocale = [];
|
|
139
|
+
for (const [loadID] of patterns.entries()) {
|
|
140
|
+
importsForLocale.push(`() => import('${this.getImportPath(this.getCompiledFilePath(loc, loadID))}')`);
|
|
141
141
|
}
|
|
142
|
-
imports.push(
|
|
142
|
+
imports.push(`[${importsForLocale.join(',')}]`);
|
|
143
143
|
}
|
|
144
|
-
return this.genProxyContent(imports,
|
|
144
|
+
return this.genProxyContent(imports, patterns, locales);
|
|
145
145
|
}
|
|
146
|
-
genProxySync(locales,
|
|
146
|
+
genProxySync(locales, patterns) {
|
|
147
147
|
const imports = [];
|
|
148
148
|
const object = [];
|
|
149
|
-
for (const [
|
|
150
|
-
const
|
|
151
|
-
for (const [
|
|
152
|
-
const locKey = `_w_c_${
|
|
153
|
-
imports.push(`import * as ${locKey} from '${this.getImportPath(this.getCompiledFilePath(loc,
|
|
154
|
-
|
|
149
|
+
for (const [i, loc] of locales.entries()) {
|
|
150
|
+
const importedForLocale = [];
|
|
151
|
+
for (const [loadID] of patterns.entries()) {
|
|
152
|
+
const locKey = `_w_c_${loadID}_${i}_`;
|
|
153
|
+
imports.push(`import * as ${locKey} from '${this.getImportPath(this.getCompiledFilePath(loc, loadID))}'`);
|
|
154
|
+
importedForLocale.push(locKey);
|
|
155
155
|
}
|
|
156
|
-
object.push(
|
|
156
|
+
object.push(`[${importedForLocale.join(',')}]`);
|
|
157
157
|
}
|
|
158
|
-
return this.genProxyContent(object,
|
|
158
|
+
return this.genProxyContent(object, patterns, locales, imports);
|
|
159
159
|
}
|
|
160
|
-
writeProxies = async (locales,
|
|
161
|
-
|
|
162
|
-
await this.#opts.fs.write(this.#
|
|
160
|
+
writeProxies = async (locales, groupPatterns) => {
|
|
161
|
+
const allPatterns = [this.#opts.key, ...groupPatterns];
|
|
162
|
+
await this.#opts.fs.write(this.#proxyPath, this.genProxy(locales, allPatterns));
|
|
163
|
+
await this.#opts.fs.write(this.#proxySyncPath, this.genProxySync(locales, allPatterns));
|
|
163
164
|
};
|
|
164
165
|
static create = async (opts) => {
|
|
165
166
|
const { adapter, key, localesDirAbs, root, fs } = opts;
|
|
@@ -211,7 +212,7 @@ export class Files {
|
|
|
211
212
|
};
|
|
212
213
|
getManifestFilePath(id) {
|
|
213
214
|
const ownerKey = this.#opts.ownerKey;
|
|
214
|
-
return resolve(this.#opts.localesDirAbs, generatedDir, `${ownerKey}.${id ??
|
|
215
|
+
return resolve(this.#opts.localesDirAbs, generatedDir, `${ownerKey}.${id ?? defaultLoadID}.manifest.js`);
|
|
215
216
|
}
|
|
216
217
|
writeManifest = async (keys, id) => {
|
|
217
218
|
const content = `/** @type {(string | string[] | {text: string | string[], context?: string, isUrl?: boolean})[]} */\n` +
|
|
@@ -243,14 +244,6 @@ export class Files {
|
|
|
243
244
|
}
|
|
244
245
|
await this.#opts.fs.write(this.getCompiledFilePath(locale, loadID), module);
|
|
245
246
|
};
|
|
246
|
-
writeTransformed = async (filename, content) => {
|
|
247
|
-
if (!this.#opts.adapter.outDir) {
|
|
248
|
-
return;
|
|
249
|
-
}
|
|
250
|
-
const fname = resolve(`${this.#opts.adapter.outDir}/${filename}`);
|
|
251
|
-
await this.#opts.fs.mkdir(dirname(fname));
|
|
252
|
-
await this.#opts.fs.write(fname, content);
|
|
253
|
-
};
|
|
254
247
|
getImportLoaderPath(forServer, relativeTo) {
|
|
255
248
|
return this.getImportPath(forServer ? this.#opts.loaderPath.server : this.#opts.loaderPath.client, relativeTo);
|
|
256
249
|
}
|
package/dist/handler/index.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { type Matcher } from 'picomatch';
|
|
2
2
|
import type { Adapter, Message, TransformOutputCode } from '../adapters.js';
|
|
3
3
|
import AIQueue from '../ai/index.js';
|
|
4
|
-
import type { ConfigPartial } from '../config.js';
|
|
4
|
+
import type { ConfigPartial, DevMode } from '../config.js';
|
|
5
5
|
import type { Logger } from '../log.js';
|
|
6
6
|
import { type FileRef, type Item } from '../storage.js';
|
|
7
7
|
import { Files, type FilesOptsCreatePass } from './files.js';
|
|
@@ -12,14 +12,17 @@ type TrackedRefs = Map<string, {
|
|
|
12
12
|
ref: FileRef;
|
|
13
13
|
used: number;
|
|
14
14
|
}>;
|
|
15
|
-
|
|
16
|
-
export declare
|
|
15
|
+
export declare function getLoadIDs(adapter: Adapter, granularStates: Iterable<GranularState>, sourceLocale: string): number[];
|
|
16
|
+
export declare const newItemsAllowed: (mode: Mode, devMode: DevMode) => boolean;
|
|
17
|
+
export declare function getFallbackChains(fallbackConf: Record<string, string>, locales: string[], sourceLocale: string): Map<string, string[]>;
|
|
17
18
|
type HandlerOptsCreate = FilesOptsCreatePass & {
|
|
18
19
|
config: ConfigPartial;
|
|
19
20
|
mode: Mode;
|
|
20
21
|
log: Logger;
|
|
21
22
|
sourceLocale: string;
|
|
22
23
|
sharedState: SharedState;
|
|
24
|
+
devMode: DevMode;
|
|
25
|
+
modifyInplace: boolean;
|
|
23
26
|
};
|
|
24
27
|
export declare class AdapterHandler {
|
|
25
28
|
#private;
|
|
@@ -40,7 +43,7 @@ export declare class AdapterHandler {
|
|
|
40
43
|
compile: (hmrVersion?: number) => Promise<void>;
|
|
41
44
|
saveStorageCompile: () => Promise<void>;
|
|
42
45
|
writeCompiled: (loc: string, hmrVersion?: number) => Promise<void>;
|
|
43
|
-
getCompiledFallback(index: number,
|
|
46
|
+
getCompiledFallback(index: number, locale: string): string | import("../compile.js").CompositePayload[];
|
|
44
47
|
popTrackedRefs: (filename: string) => TrackedRefs;
|
|
45
48
|
updateRef: (item: Item, key: string, filename: string, msgInfo: Message, trackedRefrences: TrackedRefs) => boolean;
|
|
46
49
|
cleanTrackedRefs: (trackedRefs: TrackedRefs) => {
|