wuchale 0.17.5 → 0.18.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/index.d.ts +2 -3
- package/dist/adapter-utils/index.js +7 -18
- package/dist/adapter-utils/mixed-visitor.d.ts +2 -2
- package/dist/adapter-utils/mixed-visitor.js +11 -9
- package/dist/adapter-vanilla/index.d.ts +7 -2
- package/dist/adapter-vanilla/index.js +18 -27
- package/dist/adapter-vanilla/transformer.d.ts +13 -11
- package/dist/adapter-vanilla/transformer.js +119 -46
- package/dist/adapters.d.ts +31 -17
- package/dist/adapters.js +66 -31
- package/dist/cli/extract.d.ts +1 -4
- package/dist/cli/extract.js +4 -53
- package/dist/cli/index.js +1 -6
- package/dist/cli/status.js +3 -3
- package/dist/config.js +3 -0
- package/dist/handler.d.ts +26 -19
- package/dist/handler.js +546 -271
- package/dist/index.d.ts +2 -2
- package/dist/index.js +1 -1
- package/dist/load-utils/index.d.ts +7 -7
- package/dist/load-utils/index.js +7 -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 +14 -12
- package/dist/runtime.d.ts +12 -18
- package/dist/runtime.js +38 -36
- package/dist/url.d.ts +19 -0
- package/dist/url.js +57 -0
- package/package.json +9 -5
- package/src/adapter-vanilla/loaders/bundle.js +4 -2
- package/src/adapter-vanilla/loaders/server.js +6 -3
- package/src/adapter-vanilla/loaders/vite.js +5 -5
- package/src/adapter-vanilla/loaders/vite.ssr.js +6 -7
- package/dist/cli/init.d.ts +0 -2
- package/dist/cli/init.js +0 -62
- package/dist/cli/input.d.ts +0 -2
- package/dist/cli/input.js +0 -56
- package/src/virtual.d.ts +0 -20
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
export { MixedVisitor } from './mixed-visitor.js';
|
|
2
|
+
import type { HeuristicResultChecked } from '../adapters.js';
|
|
2
3
|
export declare const varNames: {
|
|
3
4
|
rt: string;
|
|
4
5
|
hmrUpdate: string;
|
|
5
|
-
rtWrap: string;
|
|
6
6
|
};
|
|
7
7
|
export declare function runtimeVars(wrapFunc: (expr: string) => string, base?: string): {
|
|
8
8
|
rtTrans: string;
|
|
@@ -17,12 +17,11 @@ export declare function runtimeVars(wrapFunc: (expr: string) => string, base?: s
|
|
|
17
17
|
};
|
|
18
18
|
export type RuntimeVars = ReturnType<typeof runtimeVars>;
|
|
19
19
|
export declare function nonWhitespaceText(msgStr: string): [number, string, number];
|
|
20
|
-
export declare function getDependencies(): Promise<Set<string>>;
|
|
21
20
|
export declare function loaderPathResolver(importMetaUrl: string, baseDir: string, ext: string): (name: string) => string;
|
|
22
21
|
export declare const commentPrefix = "@wc-";
|
|
23
22
|
export type CommentDirectives = {
|
|
24
23
|
ignoreFile?: boolean;
|
|
25
|
-
|
|
24
|
+
forceType?: HeuristicResultChecked;
|
|
26
25
|
context?: string;
|
|
27
26
|
};
|
|
28
27
|
export declare function processCommentDirectives(data: string, current: CommentDirectives): CommentDirectives;
|
|
@@ -1,18 +1,16 @@
|
|
|
1
|
-
import { readFile } from "node:fs/promises";
|
|
2
1
|
export { MixedVisitor } from './mixed-visitor.js';
|
|
3
2
|
import { dirname, resolve } from 'node:path';
|
|
4
3
|
import { fileURLToPath } from 'node:url';
|
|
5
4
|
export const varNames = {
|
|
6
5
|
rt: '_w_runtime_',
|
|
7
6
|
hmrUpdate: '_w_hmrUpdate_',
|
|
8
|
-
rtWrap: '_w_to_rt_',
|
|
9
7
|
};
|
|
10
8
|
export function runtimeVars(wrapFunc, base = varNames.rt) {
|
|
11
9
|
return {
|
|
12
10
|
rtTrans: `${wrapFunc(base)}.t`,
|
|
13
11
|
rtTPlural: `${wrapFunc(base)}.tp`,
|
|
14
12
|
rtPlural: `${wrapFunc(base)}._.p`,
|
|
15
|
-
rtLocale: `${wrapFunc(base)}.
|
|
13
|
+
rtLocale: `${wrapFunc(base)}.l`,
|
|
16
14
|
rtCtx: `${wrapFunc(base)}.cx`,
|
|
17
15
|
rtTransCtx: `${wrapFunc(base)}.tx`,
|
|
18
16
|
rtTransTag: `${wrapFunc(base)}.tt`,
|
|
@@ -27,19 +25,6 @@ export function nonWhitespaceText(msgStr) {
|
|
|
27
25
|
const endWh = trimmedS.length - trimmed.length;
|
|
28
26
|
return [startWh, trimmed, endWh];
|
|
29
27
|
}
|
|
30
|
-
export async function getDependencies() {
|
|
31
|
-
let json = { devDependencies: {}, dependencies: {} };
|
|
32
|
-
try {
|
|
33
|
-
const pkgJson = await readFile('package.json');
|
|
34
|
-
json = JSON.parse(pkgJson.toString());
|
|
35
|
-
}
|
|
36
|
-
catch (err) {
|
|
37
|
-
if (err.code !== 'ENOENT') {
|
|
38
|
-
throw err;
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
|
-
return new Set(Object.keys({ ...json.devDependencies, ...json.dependencies }));
|
|
42
|
-
}
|
|
43
28
|
export function loaderPathResolver(importMetaUrl, baseDir, ext) {
|
|
44
29
|
const dir = dirname(fileURLToPath(importMetaUrl));
|
|
45
30
|
return (name) => resolve(dir, `${baseDir}/${name}.${ext}`);
|
|
@@ -49,15 +34,19 @@ const commentDirectives = {
|
|
|
49
34
|
ignore: `${commentPrefix}ignore`,
|
|
50
35
|
ignoreFile: `${commentPrefix}ignore-file`,
|
|
51
36
|
include: `${commentPrefix}include`,
|
|
37
|
+
url: `${commentPrefix}url`,
|
|
52
38
|
context: `${commentPrefix}context:`,
|
|
53
39
|
};
|
|
54
40
|
export function processCommentDirectives(data, current) {
|
|
55
41
|
const directives = { ...current };
|
|
56
42
|
if (data === commentDirectives.ignore) {
|
|
57
|
-
directives.
|
|
43
|
+
directives.forceType = false;
|
|
58
44
|
}
|
|
59
45
|
if (data === commentDirectives.include) {
|
|
60
|
-
directives.
|
|
46
|
+
directives.forceType = 'message';
|
|
47
|
+
}
|
|
48
|
+
if (data === commentDirectives.url) {
|
|
49
|
+
directives.forceType = 'url';
|
|
61
50
|
}
|
|
62
51
|
if (data === commentDirectives.ignoreFile) {
|
|
63
52
|
directives.ignoreFile = true;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type MagicString from "magic-string";
|
|
2
|
-
import { IndexTracker, Message, type HeuristicDetails, type HeuristicDetailsBase, type HeuristicFunc } from "../adapters.js";
|
|
2
|
+
import { IndexTracker, Message, type HeuristicDetails, type HeuristicDetailsBase, type HeuristicFunc, type MessageType } from "../adapters.js";
|
|
3
3
|
import { type RuntimeVars, type CommentDirectives } from "./index.js";
|
|
4
4
|
type NestedRanges = [number, number, boolean][];
|
|
5
5
|
type InitProps<NodeT> = {
|
|
@@ -37,7 +37,7 @@ export interface MixedVisitor<NodeT> extends InitProps<NodeT> {
|
|
|
37
37
|
}
|
|
38
38
|
export declare class MixedVisitor<NodeT> {
|
|
39
39
|
constructor(props: InitProps<NodeT>);
|
|
40
|
-
separatelyVisitChildren: (props: VisitProps<NodeT>) => [boolean, boolean, boolean, Message[]];
|
|
40
|
+
separatelyVisitChildren: (props: VisitProps<NodeT>) => [boolean, boolean, boolean, MessageType, Message[]];
|
|
41
41
|
visit: (props: VisitProps<NodeT>) => Message[];
|
|
42
42
|
}
|
|
43
43
|
export {};
|
|
@@ -17,7 +17,7 @@ export class MixedVisitor {
|
|
|
17
17
|
continue;
|
|
18
18
|
}
|
|
19
19
|
hasTextChild = true;
|
|
20
|
-
heurStr += strContent
|
|
20
|
+
heurStr += strContent;
|
|
21
21
|
}
|
|
22
22
|
else if (this.isComment(child)) {
|
|
23
23
|
if (this.getCommentData(child).trim().startsWith(commentPrefix)) {
|
|
@@ -26,7 +26,7 @@ export class MixedVisitor {
|
|
|
26
26
|
}
|
|
27
27
|
else if (!this.leaveInPlace(child)) {
|
|
28
28
|
hasNonTextChild = true;
|
|
29
|
-
heurStr +=
|
|
29
|
+
heurStr += `#`;
|
|
30
30
|
}
|
|
31
31
|
}
|
|
32
32
|
heurStr = heurStr.trimEnd();
|
|
@@ -35,11 +35,12 @@ export class MixedVisitor {
|
|
|
35
35
|
element: props.element,
|
|
36
36
|
attribute: props.attribute,
|
|
37
37
|
}), null);
|
|
38
|
-
const
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
38
|
+
const heurMsgType = this.checkHeuristic(msg);
|
|
39
|
+
if (heurMsgType) {
|
|
40
|
+
let hasCompoundText = hasTextChild && hasNonTextChild;
|
|
41
|
+
if (props.inCompoundText || hasCompoundText && !hasCommentDirectives) {
|
|
42
|
+
return [false, hasTextChild, hasCompoundText, heurMsgType, []];
|
|
43
|
+
}
|
|
43
44
|
}
|
|
44
45
|
// can't be extracted as one; visit each separately if markup
|
|
45
46
|
const msgs = [];
|
|
@@ -48,13 +49,13 @@ export class MixedVisitor {
|
|
|
48
49
|
msgs.push(...this.visitFunc(child, props.inCompoundText));
|
|
49
50
|
}
|
|
50
51
|
}
|
|
51
|
-
return [true, false, false, msgs];
|
|
52
|
+
return [true, false, false, heurMsgType || 'message', msgs];
|
|
52
53
|
};
|
|
53
54
|
visit = (props) => {
|
|
54
55
|
if (props.children.length === 0) {
|
|
55
56
|
return [];
|
|
56
57
|
}
|
|
57
|
-
const [visitedSeparately, hasTextChild, hasCompoundText, separateTxts] = this.separatelyVisitChildren(props);
|
|
58
|
+
const [visitedSeparately, hasTextChild, hasCompoundText, heurMsgType, separateTxts] = this.separatelyVisitChildren(props);
|
|
58
59
|
if (visitedSeparately) {
|
|
59
60
|
return separateTxts;
|
|
60
61
|
}
|
|
@@ -143,6 +144,7 @@ export class MixedVisitor {
|
|
|
143
144
|
return msgs;
|
|
144
145
|
}
|
|
145
146
|
const msgInfo = new Message(msgStr, this.fullHeuristicDetails({ scope: props.scope }), props.commentDirectives.context);
|
|
147
|
+
msgInfo.type = heurMsgType;
|
|
146
148
|
msgInfo.comments = comments;
|
|
147
149
|
if (hasTextChild || hasTextDescendants) {
|
|
148
150
|
msgs.push(msgInfo);
|
|
@@ -1,6 +1,11 @@
|
|
|
1
|
-
import type { AdapterArgs, Adapter, CodePattern } from "../adapters.js";
|
|
1
|
+
import type { AdapterArgs, Adapter, CodePattern, LoaderChoice } from "../adapters.js";
|
|
2
2
|
import { Transformer } from "./transformer.js";
|
|
3
3
|
export { Transformer };
|
|
4
4
|
export { parseScript, scriptParseOptions, scriptParseOptionsWithComments } from './transformer.js';
|
|
5
5
|
export declare const pluralPattern: CodePattern;
|
|
6
|
-
|
|
6
|
+
type LoadersAvailable = 'bundle' | 'server' | 'vite';
|
|
7
|
+
export declare function getDefaultLoaderPath(loader: LoaderChoice<LoadersAvailable>, bundle: boolean): string | {
|
|
8
|
+
client: string;
|
|
9
|
+
server: string;
|
|
10
|
+
};
|
|
11
|
+
export declare const adapter: (args?: AdapterArgs<LoadersAvailable>) => Adapter;
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import { defaultGenerateLoadID, defaultHeuristicFuncOnly } from '../adapters.js';
|
|
3
3
|
import { deepMergeObjects } from "../config.js";
|
|
4
4
|
import { Transformer } from "./transformer.js";
|
|
5
|
-
import {
|
|
5
|
+
import { loaderPathResolver } from '../adapter-utils/index.js';
|
|
6
6
|
export { Transformer };
|
|
7
7
|
export { parseScript, scriptParseOptions, scriptParseOptionsWithComments } from './transformer.js';
|
|
8
8
|
export const pluralPattern = {
|
|
@@ -11,53 +11,44 @@ export const pluralPattern = {
|
|
|
11
11
|
};
|
|
12
12
|
const defaultArgs = {
|
|
13
13
|
files: { include: 'src/**/*.{js,ts}', ignore: '**/*.d.ts' },
|
|
14
|
-
|
|
14
|
+
localesDir: './src/locales',
|
|
15
15
|
patterns: [pluralPattern],
|
|
16
16
|
heuristic: defaultHeuristicFuncOnly,
|
|
17
17
|
granularLoad: false,
|
|
18
18
|
bundleLoad: false,
|
|
19
19
|
generateLoadID: defaultGenerateLoadID,
|
|
20
|
-
|
|
20
|
+
loader: 'vite',
|
|
21
21
|
runtime: {
|
|
22
22
|
useReactive: ({ nested }) => ({
|
|
23
23
|
init: nested ? null : false,
|
|
24
24
|
use: nested ? null : false,
|
|
25
25
|
}),
|
|
26
26
|
plain: {
|
|
27
|
-
importName: 'default',
|
|
28
27
|
wrapInit: expr => expr,
|
|
29
28
|
wrapUse: expr => expr,
|
|
30
29
|
}
|
|
31
30
|
}
|
|
32
31
|
};
|
|
33
32
|
const resolveLoaderPath = loaderPathResolver(import.meta.url, '../../src/adapter-vanilla/loaders', 'js');
|
|
33
|
+
export function getDefaultLoaderPath(loader, bundle) {
|
|
34
|
+
if (bundle) {
|
|
35
|
+
return resolveLoaderPath('bundle');
|
|
36
|
+
}
|
|
37
|
+
if (loader === 'vite') {
|
|
38
|
+
return {
|
|
39
|
+
client: resolveLoaderPath('vite'),
|
|
40
|
+
server: resolveLoaderPath('vite.ssr'),
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
return resolveLoaderPath(loader);
|
|
44
|
+
}
|
|
34
45
|
export const adapter = (args = defaultArgs) => {
|
|
35
|
-
const { heuristic, patterns, runtime, ...rest } = deepMergeObjects(args, defaultArgs);
|
|
46
|
+
const { heuristic, patterns, runtime, loader, ...rest } = deepMergeObjects(args, defaultArgs);
|
|
36
47
|
return {
|
|
37
|
-
transform: ({ content, filename, index, expr }) => new Transformer(content, filename, index, heuristic, patterns, expr, runtime).transform(),
|
|
48
|
+
transform: ({ content, filename, index, expr, matchUrl }) => new Transformer(content, filename, index, heuristic, patterns, expr, runtime, matchUrl).transform(),
|
|
38
49
|
loaderExts: ['.js', '.ts'],
|
|
39
|
-
|
|
40
|
-
if (rest.bundleLoad) {
|
|
41
|
-
return ['bundle'];
|
|
42
|
-
}
|
|
43
|
-
const deps = await getDependencies();
|
|
44
|
-
const available = ['server'];
|
|
45
|
-
if (deps.has('vite')) {
|
|
46
|
-
available.unshift('vite');
|
|
47
|
-
}
|
|
48
|
-
return available;
|
|
49
|
-
},
|
|
50
|
-
defaultLoaderPath: (loader) => {
|
|
51
|
-
if (loader === 'vite') {
|
|
52
|
-
return {
|
|
53
|
-
client: resolveLoaderPath('vite'),
|
|
54
|
-
server: resolveLoaderPath('vite.ssr'),
|
|
55
|
-
};
|
|
56
|
-
}
|
|
57
|
-
return resolveLoaderPath(loader);
|
|
58
|
-
},
|
|
50
|
+
defaultLoaderPath: getDefaultLoaderPath(loader, rest.bundleLoad),
|
|
59
51
|
runtime,
|
|
60
52
|
...rest,
|
|
61
|
-
docsUrl: 'https://wuchale.dev/adapters/vanilla'
|
|
62
53
|
};
|
|
63
54
|
};
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import MagicString from "magic-string";
|
|
2
2
|
import type * as Estree from "acorn";
|
|
3
3
|
import { Message } from '../adapters.js';
|
|
4
|
-
import type { HeuristicDetailsBase, HeuristicFunc, IndexTracker, ScriptDeclType, TransformOutput, HeuristicDetails, RuntimeConf, CatalogExpr, CodePattern } from "../adapters.js";
|
|
4
|
+
import type { HeuristicDetailsBase, HeuristicFunc, IndexTracker, ScriptDeclType, TransformOutput, HeuristicDetails, RuntimeConf, CatalogExpr, CodePattern, UrlMatcher, HeuristicResultChecked, MessageType } from "../adapters.js";
|
|
5
5
|
import { type RuntimeVars, type CommentDirectives } from "../adapter-utils/index.js";
|
|
6
6
|
export declare const scriptParseOptions: Estree.Options;
|
|
7
7
|
export declare function scriptParseOptionsWithComments(): [Estree.Options, Estree.Comment[][]];
|
|
@@ -15,6 +15,7 @@ export declare class Transformer {
|
|
|
15
15
|
filename: string;
|
|
16
16
|
mstr: MagicString;
|
|
17
17
|
patterns: CodePattern[];
|
|
18
|
+
matchUrl: UrlMatcher;
|
|
18
19
|
initRuntime: InitRuntimeFunc;
|
|
19
20
|
currentRtVar: string;
|
|
20
21
|
vars: () => RuntimeVars;
|
|
@@ -25,16 +26,15 @@ export declare class Transformer {
|
|
|
25
26
|
currentFuncDef: string | null;
|
|
26
27
|
currentCall: string;
|
|
27
28
|
currentTopLevelCall: string;
|
|
29
|
+
/** .start of the first statements in their respective parents, to put the runtime init before */
|
|
30
|
+
realBodyStarts: Set<number>;
|
|
28
31
|
/** for subclasses. right now for svelte, if in <script module> */
|
|
29
32
|
additionalState: object;
|
|
30
|
-
constructor(content: string, filename: string, index: IndexTracker, heuristic: HeuristicFunc, patterns: CodePattern[], catalogExpr: CatalogExpr, rtConf: RuntimeConf, rtBaseVars?: string[]);
|
|
33
|
+
constructor(content: string, filename: string, index: IndexTracker, heuristic: HeuristicFunc, patterns: CodePattern[], catalogExpr: CatalogExpr, rtConf: RuntimeConf, matchUrl: (url: string) => string, rtBaseVars?: string[]);
|
|
31
34
|
fullHeuristicDetails: (detailsBase: HeuristicDetailsBase) => HeuristicDetails;
|
|
32
|
-
|
|
33
|
-
checkHeuristic: (msgStr: string, detailsBase: HeuristicDetailsBase) => [
|
|
34
|
-
visitLiteral: (node: Estree.Literal
|
|
35
|
-
start: number;
|
|
36
|
-
end: number;
|
|
37
|
-
}) => Message[];
|
|
35
|
+
getHeuristicMessageType: (msg: Message) => HeuristicResultChecked;
|
|
36
|
+
checkHeuristic: (msgStr: string, detailsBase: HeuristicDetailsBase) => [HeuristicResultChecked, Message];
|
|
37
|
+
visitLiteral: (node: Estree.Literal, heuristicDetailsBase?: HeuristicDetailsBase) => Message[];
|
|
38
38
|
visitArrayExpression: (node: Estree.ArrayExpression) => Message[];
|
|
39
39
|
visitSequenceExpression: (node: Estree.SequenceExpression) => Message[];
|
|
40
40
|
visitObjectExpression: (node: Estree.ObjectExpression) => Message[];
|
|
@@ -65,6 +65,7 @@ export declare class Transformer {
|
|
|
65
65
|
visitVariableDeclaration: (node: Estree.VariableDeclaration) => Message[];
|
|
66
66
|
visitExportNamedDeclaration: (node: Estree.ExportNamedDeclaration) => Message[];
|
|
67
67
|
visitExportDefaultDeclaration: (node: Estree.ExportNamedDeclaration) => Message[];
|
|
68
|
+
visitStatementsNSaveRealBodyStart: (nodes: (Estree.Statement | Estree.ModuleDeclaration)[]) => Message[];
|
|
68
69
|
getRealBodyStart: (nodes: (Estree.Statement | Estree.ModuleDeclaration)[]) => number | undefined;
|
|
69
70
|
visitFunctionBody: (node: Estree.BlockStatement | Estree.Expression, name: string | null, end?: number) => Message[];
|
|
70
71
|
visitFunctionDeclaration: (node: Estree.FunctionDeclaration) => Message[];
|
|
@@ -74,11 +75,12 @@ export declare class Transformer {
|
|
|
74
75
|
visitReturnStatement: (node: Estree.ReturnStatement) => Message[];
|
|
75
76
|
visitIfStatement: (node: Estree.IfStatement) => Message[];
|
|
76
77
|
visitClassDeclaration: (node: Estree.ClassDeclaration) => Message[];
|
|
77
|
-
checkHeuristicTemplateLiteral: (node: Estree.TemplateLiteral) =>
|
|
78
|
-
visitTemplateLiteralQuasis: (node: Estree.TemplateLiteral) => [number, Message[]];
|
|
79
|
-
visitTemplateLiteral: (node: Estree.TemplateLiteral,
|
|
78
|
+
checkHeuristicTemplateLiteral: (node: Estree.TemplateLiteral, heurDetails?: HeuristicDetailsBase) => HeuristicResultChecked;
|
|
79
|
+
visitTemplateLiteralQuasis: (node: Estree.TemplateLiteral, msgTyp: MessageType) => [number, Message[]];
|
|
80
|
+
visitTemplateLiteral: (node: Estree.TemplateLiteral, heurDetails?: HeuristicDetailsBase | boolean) => Message[];
|
|
80
81
|
visitTaggedTemplateExpression: (node: Estree.TaggedTemplateExpression) => Message[];
|
|
81
82
|
visitProgram: (node: Estree.Program) => Message[];
|
|
83
|
+
visitWithCommentDirectives: (node: Estree.AnyNode, func: Function) => any;
|
|
82
84
|
visit: (node: Estree.AnyNode) => Message[];
|
|
83
85
|
finalize: (msgs: Message[], hmrHeaderIndex: number, additionalHeader?: string) => TransformOutput;
|
|
84
86
|
transform: () => TransformOutput;
|
|
@@ -48,6 +48,7 @@ export class Transformer {
|
|
|
48
48
|
filename;
|
|
49
49
|
mstr;
|
|
50
50
|
patterns;
|
|
51
|
+
matchUrl;
|
|
51
52
|
initRuntime;
|
|
52
53
|
currentRtVar;
|
|
53
54
|
vars;
|
|
@@ -59,14 +60,17 @@ export class Transformer {
|
|
|
59
60
|
currentFuncDef = null;
|
|
60
61
|
currentCall;
|
|
61
62
|
currentTopLevelCall;
|
|
63
|
+
/** .start of the first statements in their respective parents, to put the runtime init before */
|
|
64
|
+
realBodyStarts = new Set();
|
|
62
65
|
/** for subclasses. right now for svelte, if in <script module> */
|
|
63
66
|
additionalState = {};
|
|
64
|
-
constructor(content, filename, index, heuristic, patterns, catalogExpr, rtConf, rtBaseVars = [varNames.rt]) {
|
|
67
|
+
constructor(content, filename, index, heuristic, patterns, catalogExpr, rtConf, matchUrl, rtBaseVars = [varNames.rt]) {
|
|
65
68
|
this.index = index;
|
|
66
69
|
this.heuristic = heuristic;
|
|
67
70
|
this.patterns = patterns;
|
|
68
71
|
this.content = content;
|
|
69
72
|
this.filename = filename;
|
|
73
|
+
this.matchUrl = matchUrl;
|
|
70
74
|
const topLevelUseReactive = rtConf.useReactive({
|
|
71
75
|
funcName: null,
|
|
72
76
|
nested: false,
|
|
@@ -99,8 +103,7 @@ export class Transformer {
|
|
|
99
103
|
}
|
|
100
104
|
const wrapInit = useReactive.init ? rtConf.reactive.wrapInit : rtConf.plain.wrapInit;
|
|
101
105
|
const expr = useReactive.init ? catalogExpr.reactive : catalogExpr.plain;
|
|
102
|
-
|
|
103
|
-
return `\nconst ${this.currentRtVar} = ${wrapInit(runtimeExpr)}\n`;
|
|
106
|
+
return `\nconst ${this.currentRtVar} = ${wrapInit(expr)}\n`;
|
|
104
107
|
};
|
|
105
108
|
}
|
|
106
109
|
fullHeuristicDetails = (detailsBase) => {
|
|
@@ -117,17 +120,20 @@ export class Transformer {
|
|
|
117
120
|
}
|
|
118
121
|
return details;
|
|
119
122
|
};
|
|
120
|
-
|
|
123
|
+
getHeuristicMessageType = (msg) => {
|
|
121
124
|
const msgStr = msg.msgStr.join('\n');
|
|
122
125
|
if (!msgStr) {
|
|
123
126
|
// nothing to ask
|
|
124
127
|
return false;
|
|
125
128
|
}
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
+
if (this.commentDirectives.forceType === false) {
|
|
130
|
+
return false;
|
|
131
|
+
}
|
|
132
|
+
const heuRes = this.heuristic(msg) ?? defaultHeuristicFuncOnly(msg) ?? 'message';
|
|
133
|
+
if (this.commentDirectives.forceType == null && heuRes === 'url' && this.matchUrl(msgStr) == null) {
|
|
134
|
+
return false;
|
|
129
135
|
}
|
|
130
|
-
return
|
|
136
|
+
return this.commentDirectives.forceType || heuRes;
|
|
131
137
|
};
|
|
132
138
|
checkHeuristic = (msgStr, detailsBase) => {
|
|
133
139
|
if (!msgStr) {
|
|
@@ -135,14 +141,18 @@ export class Transformer {
|
|
|
135
141
|
return [false, null];
|
|
136
142
|
}
|
|
137
143
|
const msg = new Message(msgStr, this.fullHeuristicDetails(detailsBase), this.commentDirectives.context);
|
|
138
|
-
|
|
144
|
+
const heuRes = this.getHeuristicMessageType(msg);
|
|
145
|
+
if (heuRes) {
|
|
146
|
+
msg.type = heuRes;
|
|
147
|
+
}
|
|
148
|
+
return [heuRes, msg];
|
|
139
149
|
};
|
|
140
|
-
visitLiteral = (node) => {
|
|
150
|
+
visitLiteral = (node, heuristicDetailsBase) => {
|
|
141
151
|
if (typeof node.value !== 'string') {
|
|
142
152
|
return [];
|
|
143
153
|
}
|
|
144
154
|
const { start, end } = node;
|
|
145
|
-
const [pass, msgInfo] = this.checkHeuristic(node.value, { scope: 'script' });
|
|
155
|
+
const [pass, msgInfo] = this.checkHeuristic(node.value, heuristicDetailsBase ?? { scope: 'script' });
|
|
146
156
|
if (!pass) {
|
|
147
157
|
return [];
|
|
148
158
|
}
|
|
@@ -189,29 +199,53 @@ export class Transformer {
|
|
|
189
199
|
if (!pattern) {
|
|
190
200
|
return this.defaultVisitCallExpression(node);
|
|
191
201
|
}
|
|
202
|
+
let iLastNonOther = pattern.args.length - 1; // after this no change will be made
|
|
203
|
+
for (; iLastNonOther >= 0; iLastNonOther--) {
|
|
204
|
+
if (pattern.args[iLastNonOther] !== 'other') {
|
|
205
|
+
break;
|
|
206
|
+
}
|
|
207
|
+
}
|
|
192
208
|
const msgs = [];
|
|
209
|
+
const updates = [];
|
|
210
|
+
const appends = [];
|
|
193
211
|
let lastArgEnd;
|
|
194
212
|
for (const [i, arg] of pattern.args.entries()) {
|
|
195
213
|
const argVal = node.arguments[i];
|
|
196
214
|
let argInsertIndex;
|
|
197
215
|
if (argVal == null) {
|
|
216
|
+
argInsertIndex = lastArgEnd ?? node.callee.end + 1;
|
|
198
217
|
if (lastArgEnd == null) {
|
|
199
|
-
|
|
218
|
+
lastArgEnd = argInsertIndex;
|
|
200
219
|
}
|
|
201
|
-
argInsertIndex = lastArgEnd;
|
|
202
220
|
}
|
|
203
221
|
else {
|
|
204
222
|
lastArgEnd = argVal.end;
|
|
205
223
|
}
|
|
224
|
+
const comma = i > 0 ? ', ' : '';
|
|
206
225
|
if (arg === 'other') {
|
|
226
|
+
if (argVal == null && i < iLastNonOther) {
|
|
227
|
+
appends.push([argInsertIndex, `${comma}undefined`]);
|
|
228
|
+
}
|
|
229
|
+
continue;
|
|
230
|
+
}
|
|
231
|
+
if (arg === 'locale') {
|
|
232
|
+
if (argVal) {
|
|
233
|
+
if (argVal.type !== 'Literal' || typeof argVal.value !== 'string') {
|
|
234
|
+
continue;
|
|
235
|
+
}
|
|
236
|
+
updates.push([argVal.start, argVal.end, this.vars().rtLocale]);
|
|
237
|
+
}
|
|
238
|
+
else {
|
|
239
|
+
appends.push([argInsertIndex, `${comma}${this.vars().rtLocale}`]);
|
|
240
|
+
}
|
|
207
241
|
continue;
|
|
208
242
|
}
|
|
209
243
|
if (arg === 'pluralFunc') {
|
|
210
244
|
if (argVal) {
|
|
211
|
-
|
|
245
|
+
updates.push([argVal.start, argVal.end, this.vars().rtPlural]);
|
|
212
246
|
}
|
|
213
247
|
else {
|
|
214
|
-
|
|
248
|
+
appends.push([argInsertIndex, `${comma}${this.vars().rtPlural}`]);
|
|
215
249
|
}
|
|
216
250
|
continue;
|
|
217
251
|
}
|
|
@@ -224,7 +258,7 @@ export class Transformer {
|
|
|
224
258
|
return this.defaultVisitCallExpression(node);
|
|
225
259
|
}
|
|
226
260
|
const msgInfo = new Message(argVal.value, this.fullHeuristicDetails({ scope: 'script' }), this.commentDirectives.context);
|
|
227
|
-
|
|
261
|
+
updates.push([argVal.start, argVal.end, `${this.vars().rtTrans}(${this.index.get(msgInfo.toKey())})`]);
|
|
228
262
|
msgs.push(msgInfo);
|
|
229
263
|
continue;
|
|
230
264
|
}
|
|
@@ -247,7 +281,13 @@ export class Transformer {
|
|
|
247
281
|
msgInfo.plural = true;
|
|
248
282
|
const index = this.index.get(msgInfo.toKey());
|
|
249
283
|
msgs.push(msgInfo);
|
|
250
|
-
|
|
284
|
+
updates.push([argVal.start, argVal.end, `${this.vars().rtTPlural}(${index})`]);
|
|
285
|
+
}
|
|
286
|
+
for (const [start, end, by] of updates) {
|
|
287
|
+
this.mstr.update(start, end, by);
|
|
288
|
+
}
|
|
289
|
+
for (const [index, insert] of appends) {
|
|
290
|
+
this.mstr.appendRight(index, insert);
|
|
251
291
|
}
|
|
252
292
|
return msgs;
|
|
253
293
|
};
|
|
@@ -348,14 +388,40 @@ export class Transformer {
|
|
|
348
388
|
visitVariableDeclaration = (node) => node.declarations.map(this.visitVariableDeclarator).flat();
|
|
349
389
|
visitExportNamedDeclaration = (node) => node.declaration ? this.visit(node.declaration) : [];
|
|
350
390
|
visitExportDefaultDeclaration = this.visitExportNamedDeclaration;
|
|
391
|
+
visitStatementsNSaveRealBodyStart = (nodes) => {
|
|
392
|
+
const msgs = [];
|
|
393
|
+
let bodyStart = null;
|
|
394
|
+
for (const bod of nodes) {
|
|
395
|
+
let currentContent;
|
|
396
|
+
if (bodyStart == null) {
|
|
397
|
+
currentContent = this.mstr.toString();
|
|
398
|
+
}
|
|
399
|
+
const msgsBod = this.visit(bod);
|
|
400
|
+
if (bodyStart == null && this.mstr.toString() !== currentContent) {
|
|
401
|
+
bodyStart = bod.start;
|
|
402
|
+
}
|
|
403
|
+
if (msgsBod.length) {
|
|
404
|
+
msgs.push(...msgsBod);
|
|
405
|
+
}
|
|
406
|
+
}
|
|
407
|
+
if (bodyStart) {
|
|
408
|
+
this.realBodyStarts.add(bodyStart);
|
|
409
|
+
}
|
|
410
|
+
return msgs;
|
|
411
|
+
};
|
|
351
412
|
getRealBodyStart = (nodes) => {
|
|
413
|
+
let nonLiteralStart = null;
|
|
352
414
|
for (const node of nodes) {
|
|
353
|
-
if (
|
|
354
|
-
|
|
415
|
+
if (this.realBodyStarts.has(node.start)) {
|
|
416
|
+
return node.start;
|
|
417
|
+
}
|
|
418
|
+
if (nonLiteralStart == null
|
|
419
|
+
&& node.type !== 'ImportDeclaration'
|
|
420
|
+
&& (node.type !== 'ExpressionStatement' || node.expression.type !== 'Literal')) {
|
|
421
|
+
nonLiteralStart = node.start;
|
|
355
422
|
}
|
|
356
|
-
return node.start;
|
|
357
423
|
}
|
|
358
|
-
return nodes[0]?.start;
|
|
424
|
+
return nonLiteralStart ?? nodes[0]?.start;
|
|
359
425
|
};
|
|
360
426
|
visitFunctionBody = (node, name, end) => {
|
|
361
427
|
const prevFuncDef = this.currentFuncDef;
|
|
@@ -400,7 +466,7 @@ export class Transformer {
|
|
|
400
466
|
};
|
|
401
467
|
visitArrowFunctionExpression = (node) => this.visitFunctionBody(node.body, '', node.end);
|
|
402
468
|
visitFunctionExpression = (node) => this.visitFunctionBody(node.body, '');
|
|
403
|
-
visitBlockStatement = (node) => node.body
|
|
469
|
+
visitBlockStatement = (node) => this.visitStatementsNSaveRealBodyStart(node.body);
|
|
404
470
|
visitReturnStatement = (node) => node.argument ? this.visit(node.argument) : [];
|
|
405
471
|
visitIfStatement = (node) => {
|
|
406
472
|
const msgs = this.visit(node.test);
|
|
@@ -430,7 +496,7 @@ export class Transformer {
|
|
|
430
496
|
this.declaring = prevDecl; // restore
|
|
431
497
|
return msgs;
|
|
432
498
|
};
|
|
433
|
-
checkHeuristicTemplateLiteral = (node) => {
|
|
499
|
+
checkHeuristicTemplateLiteral = (node, heurDetails) => {
|
|
434
500
|
let heurTxt = '';
|
|
435
501
|
for (const quasi of node.quasis) {
|
|
436
502
|
heurTxt += quasi.value.cooked ?? '';
|
|
@@ -439,10 +505,10 @@ export class Transformer {
|
|
|
439
505
|
}
|
|
440
506
|
}
|
|
441
507
|
heurTxt = heurTxt.trim();
|
|
442
|
-
const [pass] = this.checkHeuristic(heurTxt, { scope: 'script' });
|
|
508
|
+
const [pass] = this.checkHeuristic(heurTxt, heurDetails ?? { scope: 'script' });
|
|
443
509
|
return pass;
|
|
444
510
|
};
|
|
445
|
-
visitTemplateLiteralQuasis = (node) => {
|
|
511
|
+
visitTemplateLiteralQuasis = (node, msgTyp) => {
|
|
446
512
|
const msgs = [];
|
|
447
513
|
let msgStr = node.quasis[0].value?.cooked ?? '';
|
|
448
514
|
const comments = [];
|
|
@@ -460,18 +526,22 @@ export class Transformer {
|
|
|
460
526
|
this.mstr.update(end, end + 2, ', ');
|
|
461
527
|
}
|
|
462
528
|
const msgInfo = new Message(msgStr, this.fullHeuristicDetails({ scope: 'script' }), this.commentDirectives.context);
|
|
529
|
+
msgInfo.type = msgTyp;
|
|
463
530
|
msgInfo.comments = comments;
|
|
464
531
|
const index = this.index.get(msgInfo.toKey());
|
|
465
532
|
msgs.push(msgInfo);
|
|
466
533
|
return [index, msgs];
|
|
467
534
|
};
|
|
468
|
-
visitTemplateLiteral = (node,
|
|
469
|
-
|
|
470
|
-
|
|
535
|
+
visitTemplateLiteral = (node, heurDetails = false) => {
|
|
536
|
+
let msgTyp = 'message';
|
|
537
|
+
if (heurDetails !== true) {
|
|
538
|
+
const heuRes = this.checkHeuristicTemplateLiteral(node, typeof heurDetails === 'boolean' ? undefined : heurDetails);
|
|
539
|
+
if (!heuRes) {
|
|
471
540
|
return node.expressions.map(this.visit).flat();
|
|
472
541
|
}
|
|
542
|
+
msgTyp = heuRes;
|
|
473
543
|
}
|
|
474
|
-
const [index, msgs] = this.visitTemplateLiteralQuasis(node);
|
|
544
|
+
const [index, msgs] = this.visitTemplateLiteralQuasis(node, msgTyp);
|
|
475
545
|
const { start: start0, end: end0 } = node.quasis[0];
|
|
476
546
|
let begin = `${this.vars().rtTrans}(${index}`;
|
|
477
547
|
let end = ')';
|
|
@@ -491,8 +561,9 @@ export class Transformer {
|
|
|
491
561
|
const prevCall = this.currentCall;
|
|
492
562
|
this.currentCall = this.getCalleeName(node.tag);
|
|
493
563
|
let msgs = [];
|
|
494
|
-
|
|
495
|
-
|
|
564
|
+
const heuRes = this.checkHeuristicTemplateLiteral(node.quasi);
|
|
565
|
+
if (heuRes) {
|
|
566
|
+
const [index, msgsNew] = this.visitTemplateLiteralQuasis(node.quasi, heuRes);
|
|
496
567
|
msgs = msgsNew;
|
|
497
568
|
this.mstr.appendRight(node.tag.start, `${this.vars().rtTransTag}(`);
|
|
498
569
|
const { start, end, expressions } = node.quasi;
|
|
@@ -509,17 +580,14 @@ export class Transformer {
|
|
|
509
580
|
return msgs;
|
|
510
581
|
};
|
|
511
582
|
visitProgram = (node) => {
|
|
512
|
-
const msgs = [];
|
|
513
583
|
this.insideProgram = true;
|
|
514
|
-
|
|
515
|
-
msgs.push(...this.visit(child));
|
|
516
|
-
}
|
|
584
|
+
const msgs = this.visitStatementsNSaveRealBodyStart(node.body);
|
|
517
585
|
this.insideProgram = false;
|
|
518
586
|
return msgs;
|
|
519
587
|
};
|
|
520
|
-
|
|
521
|
-
// for estree
|
|
588
|
+
visitWithCommentDirectives = (node, func) => {
|
|
522
589
|
const commentDirectives = { ...this.commentDirectives };
|
|
590
|
+
// for estree
|
|
523
591
|
const comments = this.comments[node.start];
|
|
524
592
|
// @ts-expect-error
|
|
525
593
|
for (const comment of node.leadingComments ?? comments ?? []) {
|
|
@@ -528,18 +596,23 @@ export class Transformer {
|
|
|
528
596
|
if (this.commentDirectives.ignoreFile) {
|
|
529
597
|
return [];
|
|
530
598
|
}
|
|
599
|
+
const res = func();
|
|
600
|
+
this.commentDirectives = commentDirectives; // restore
|
|
601
|
+
return res;
|
|
602
|
+
};
|
|
603
|
+
visit = (node) => this.visitWithCommentDirectives(node, () => {
|
|
604
|
+
if (this.commentDirectives.forceType === false) {
|
|
605
|
+
return [];
|
|
606
|
+
}
|
|
531
607
|
let msgs = [];
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
// console.log(node)
|
|
538
|
-
}
|
|
608
|
+
const methodName = `visit${node.type}`;
|
|
609
|
+
if (methodName in this) {
|
|
610
|
+
msgs = this[methodName](node);
|
|
611
|
+
// } else {
|
|
612
|
+
// console.log(node)
|
|
539
613
|
}
|
|
540
|
-
this.commentDirectives = commentDirectives; // restore
|
|
541
614
|
return msgs;
|
|
542
|
-
};
|
|
615
|
+
});
|
|
543
616
|
finalize = (msgs, hmrHeaderIndex, additionalHeader = '') => ({
|
|
544
617
|
msgs,
|
|
545
618
|
output: header => {
|