@wuchale/jsx 0.5.2 → 0.6.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/index.js +43 -3
- package/dist/transformer.d.ts +5 -5
- package/dist/transformer.js +15 -14
- package/package.json +2 -2
- package/src/loaders/react.bundle.js +9 -2
- package/src/loaders/react.js +6 -5
package/dist/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { defaultGenerateLoadID, defaultHeuristic, deepMergeObjects } from 'wuchale';
|
|
2
|
-
import { adapter as vanillaAdapter
|
|
2
|
+
import { adapter as vanillaAdapter } from 'wuchale/adapter-vanilla';
|
|
3
3
|
import { JSXTransformer } from "./transformer.js";
|
|
4
4
|
import { getDependencies } from 'wuchale/adapter-utils';
|
|
5
5
|
const ignoreElements = ['style', 'path'];
|
|
@@ -18,6 +18,41 @@ const jsxHeuristic = (msgStr, details) => {
|
|
|
18
18
|
}
|
|
19
19
|
return true;
|
|
20
20
|
};
|
|
21
|
+
const defaultRuntime = {
|
|
22
|
+
useReactive: ({ funcName, nested }) => {
|
|
23
|
+
const inTopLevel = funcName == null;
|
|
24
|
+
const insideReactive = !inTopLevel && !nested && ((funcName.startsWith('use') && funcName.length > 3) || /[A-Z]/.test(funcName[0]));
|
|
25
|
+
return {
|
|
26
|
+
init: inTopLevel ? null : insideReactive,
|
|
27
|
+
use: insideReactive
|
|
28
|
+
};
|
|
29
|
+
},
|
|
30
|
+
reactive: {
|
|
31
|
+
importName: 'default',
|
|
32
|
+
wrapInit: expr => expr,
|
|
33
|
+
wrapUse: expr => expr,
|
|
34
|
+
},
|
|
35
|
+
plain: {
|
|
36
|
+
importName: 'get',
|
|
37
|
+
wrapInit: expr => expr,
|
|
38
|
+
wrapUse: expr => expr,
|
|
39
|
+
},
|
|
40
|
+
};
|
|
41
|
+
const defaultRuntimeSolid = {
|
|
42
|
+
...defaultRuntime,
|
|
43
|
+
useReactive: ({ funcName }) => {
|
|
44
|
+
const inTopLevel = funcName == null;
|
|
45
|
+
return {
|
|
46
|
+
init: inTopLevel ? true : null, // init only in top level
|
|
47
|
+
use: true, // always use reactive
|
|
48
|
+
};
|
|
49
|
+
},
|
|
50
|
+
reactive: {
|
|
51
|
+
importName: 'default',
|
|
52
|
+
wrapInit: expr => `() => ${expr}`,
|
|
53
|
+
wrapUse: expr => `${expr}()`
|
|
54
|
+
}
|
|
55
|
+
};
|
|
21
56
|
const defaultArgs = {
|
|
22
57
|
files: { include: 'src/**/*.{js,ts,jsx,tsx}', ignore: '**/*.d.ts' },
|
|
23
58
|
catalog: './src/locales/{locale}',
|
|
@@ -27,13 +62,17 @@ const defaultArgs = {
|
|
|
27
62
|
bundleLoad: false,
|
|
28
63
|
generateLoadID: defaultGenerateLoadID,
|
|
29
64
|
writeFiles: {},
|
|
65
|
+
runtime: defaultRuntime,
|
|
30
66
|
variant: 'default',
|
|
31
67
|
};
|
|
32
68
|
export const adapter = (args = defaultArgs) => {
|
|
33
|
-
|
|
69
|
+
let { heuristic, pluralsFunc, variant, runtime, ...rest } = deepMergeObjects(args, defaultArgs);
|
|
70
|
+
if (variant === 'solidjs' && args.runtime == null) {
|
|
71
|
+
runtime = defaultRuntimeSolid;
|
|
72
|
+
}
|
|
34
73
|
return {
|
|
35
74
|
transform: ({ content, filename, index, header }) => {
|
|
36
|
-
return new JSXTransformer(content, filename, index, heuristic, pluralsFunc,
|
|
75
|
+
return new JSXTransformer(content, filename, index, heuristic, pluralsFunc, header.expr, runtime).transformJx(header.head, variant);
|
|
37
76
|
},
|
|
38
77
|
loaderExts: ['.js', '.ts'],
|
|
39
78
|
defaultLoaders: async () => {
|
|
@@ -56,6 +95,7 @@ export const adapter = (args = defaultArgs) => {
|
|
|
56
95
|
}
|
|
57
96
|
return new URL(`../src/loaders/${loader}.js`, import.meta.url).pathname;
|
|
58
97
|
},
|
|
98
|
+
runtime,
|
|
59
99
|
...rest,
|
|
60
100
|
docsUrl: 'https://wuchale.dev/adapters/jsx'
|
|
61
101
|
};
|
package/dist/transformer.d.ts
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import { type Program } from "acorn";
|
|
2
1
|
import { Message } from 'wuchale';
|
|
3
2
|
import type * as JX from 'estree-jsx';
|
|
3
|
+
import type * as Estree from 'acorn';
|
|
4
4
|
import { Transformer } from 'wuchale/adapter-vanilla';
|
|
5
|
-
import type { IndexTracker, HeuristicFunc, TransformOutput, CommentDirectives } from 'wuchale';
|
|
5
|
+
import type { IndexTracker, HeuristicFunc, TransformOutput, CommentDirectives, RuntimeConf, CatalogExpr } from 'wuchale';
|
|
6
6
|
import { MixedVisitor } from "wuchale/adapter-utils";
|
|
7
|
-
export declare function parseScript(content: string): [Program,
|
|
7
|
+
export declare function parseScript(content: string): [Estree.Program, Estree.Comment[][]];
|
|
8
8
|
type MixedNodesTypes = JX.JSXElement | JX.JSXFragment | JX.JSXText | JX.JSXExpressionContainer | JX.JSXSpreadChild;
|
|
9
9
|
export type JSXLib = 'default' | 'solidjs';
|
|
10
10
|
export declare class JSXTransformer extends Transformer {
|
|
@@ -14,7 +14,7 @@ export declare class JSXTransformer extends Transformer {
|
|
|
14
14
|
lastVisitIsComment: boolean;
|
|
15
15
|
currentElementI: number;
|
|
16
16
|
mixedVisitor: MixedVisitor<MixedNodesTypes>;
|
|
17
|
-
constructor(content: string, filename: string, index: IndexTracker, heuristic: HeuristicFunc, pluralsFunc: string,
|
|
17
|
+
constructor(content: string, filename: string, index: IndexTracker, heuristic: HeuristicFunc, pluralsFunc: string, catalogExpr: CatalogExpr, rtConf: RuntimeConf);
|
|
18
18
|
initMixedVisitor: () => MixedVisitor<MixedNodesTypes>;
|
|
19
19
|
visitChildrenJ: (node: JX.JSXElement | JX.JSXFragment) => Message[];
|
|
20
20
|
visitNameJSXNamespacedName: (node: JX.JSXNamespacedName) => string;
|
|
@@ -29,7 +29,7 @@ export declare class JSXTransformer extends Transformer {
|
|
|
29
29
|
visitJSXAttribute: (node: JX.JSXAttribute) => Message[];
|
|
30
30
|
visitJSXSpreadAttribute: (node: JX.JSXSpreadAttribute) => Message[];
|
|
31
31
|
visitJSXEmptyExpression: (node: JX.JSXEmptyExpression) => Message[];
|
|
32
|
-
visitJx: (node: JX.Node | JX.JSXSpreadChild | Program) => Message[];
|
|
32
|
+
visitJx: (node: JX.Node | JX.JSXSpreadChild | Estree.Program) => Message[];
|
|
33
33
|
transformJx: (headerHead: string, lib: JSXLib) => TransformOutput;
|
|
34
34
|
}
|
|
35
35
|
export {};
|
package/dist/transformer.js
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import MagicString from
|
|
2
|
-
import { Parser } from
|
|
1
|
+
import MagicString from 'magic-string';
|
|
2
|
+
import { Parser } from 'acorn';
|
|
3
3
|
import { Message } from 'wuchale';
|
|
4
4
|
import { tsPlugin } from '@sveltejs/acorn-typescript';
|
|
5
5
|
import jsx from 'acorn-jsx';
|
|
6
6
|
import { Transformer, scriptParseOptionsWithComments } from 'wuchale/adapter-vanilla';
|
|
7
|
-
import { nonWhitespaceText, MixedVisitor
|
|
7
|
+
import { nonWhitespaceText, MixedVisitor } from "wuchale/adapter-utils";
|
|
8
8
|
const JsxParser = Parser.extend(tsPlugin(), jsx());
|
|
9
9
|
export function parseScript(content) {
|
|
10
10
|
const [opts, comments] = scriptParseOptionsWithComments();
|
|
@@ -20,11 +20,12 @@ export class JSXTransformer extends Transformer {
|
|
|
20
20
|
lastVisitIsComment = false;
|
|
21
21
|
currentElementI = 0;
|
|
22
22
|
mixedVisitor;
|
|
23
|
-
constructor(content, filename, index, heuristic, pluralsFunc,
|
|
24
|
-
super(content, filename, index, heuristic, pluralsFunc,
|
|
23
|
+
constructor(content, filename, index, heuristic, pluralsFunc, catalogExpr, rtConf) {
|
|
24
|
+
super(content, filename, index, heuristic, pluralsFunc, catalogExpr, rtConf);
|
|
25
25
|
}
|
|
26
26
|
initMixedVisitor = () => new MixedVisitor({
|
|
27
27
|
mstr: this.mstr,
|
|
28
|
+
vars: this.vars,
|
|
28
29
|
getRange: node => ({
|
|
29
30
|
// @ts-expect-error
|
|
30
31
|
start: node.start,
|
|
@@ -59,15 +60,15 @@ export class JSXTransformer extends Transformer {
|
|
|
59
60
|
else {
|
|
60
61
|
toAppend = ', ';
|
|
61
62
|
}
|
|
62
|
-
this.mstr.appendRight(childStart, `${toAppend}${haveCtx ?
|
|
63
|
+
this.mstr.appendRight(childStart, `${toAppend}${haveCtx ? this.vars().nestCtx : '()'} => `);
|
|
63
64
|
}
|
|
64
65
|
let begin = `]} ctx=`;
|
|
65
66
|
if (this.inCompoundText) {
|
|
66
|
-
begin += `{${
|
|
67
|
+
begin += `{${this.vars().nestCtx}} nest`;
|
|
67
68
|
}
|
|
68
69
|
else {
|
|
69
70
|
const index = this.index.get(msgInfo.toKey());
|
|
70
|
-
begin += `{${
|
|
71
|
+
begin += `{${this.vars().rtCtx}(${index})}`;
|
|
71
72
|
}
|
|
72
73
|
let end = ' />';
|
|
73
74
|
if (hasExprs) {
|
|
@@ -123,7 +124,7 @@ export class JSXTransformer extends Transformer {
|
|
|
123
124
|
// @ts-expect-error
|
|
124
125
|
node.start + startWh,
|
|
125
126
|
// @ts-expect-error
|
|
126
|
-
node.end - endWh, `{${
|
|
127
|
+
node.end - endWh, `{${this.vars().rtTrans}(${this.index.get(msgInfo.toKey())})}`);
|
|
127
128
|
return [msgInfo];
|
|
128
129
|
};
|
|
129
130
|
visitJSXFragment = (node) => this.visitChildrenJ(node);
|
|
@@ -168,7 +169,7 @@ export class JSXTransformer extends Transformer {
|
|
|
168
169
|
// @ts-expect-error
|
|
169
170
|
value.start,
|
|
170
171
|
// @ts-expect-error
|
|
171
|
-
value.end, `{${
|
|
172
|
+
value.end, `{${this.vars().rtTrans}(${this.index.get(msgInfo.toKey())})}`);
|
|
172
173
|
return [msgInfo];
|
|
173
174
|
};
|
|
174
175
|
visitJSXSpreadAttribute = (node) => this.visit(node.argument);
|
|
@@ -215,13 +216,13 @@ export class JSXTransformer extends Transformer {
|
|
|
215
216
|
if (!msgs.length) {
|
|
216
217
|
return this.finalize(msgs, 0);
|
|
217
218
|
}
|
|
218
|
-
let devInit = '';
|
|
219
219
|
const headerFin = [
|
|
220
220
|
`import ${rtComponent} from "@wuchale/jsx/runtime${lib === 'solidjs' ? '.solid' : ''}.jsx"`,
|
|
221
221
|
headerHead,
|
|
222
|
-
|
|
222
|
+
this.initRuntime(this.filename, null, null, {}),
|
|
223
223
|
].join('\n');
|
|
224
|
-
this.
|
|
225
|
-
|
|
224
|
+
const bodyStart = this.getRealBodyStart(ast.body);
|
|
225
|
+
this.mstr.appendRight(bodyStart, headerFin + '\n');
|
|
226
|
+
return this.finalize(msgs, bodyStart);
|
|
226
227
|
};
|
|
227
228
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@wuchale/jsx",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.6.0",
|
|
4
4
|
"description": "Protobuf-like i18n from plain code: JSX adapter",
|
|
5
5
|
"scripts": {
|
|
6
6
|
"dev": "tsc --watch",
|
|
@@ -72,7 +72,7 @@
|
|
|
72
72
|
"@sveltejs/acorn-typescript": "^1.0.5",
|
|
73
73
|
"acorn": "^8.15.0",
|
|
74
74
|
"acorn-jsx": "^5.3.2",
|
|
75
|
-
"wuchale": "^0.
|
|
75
|
+
"wuchale": "^0.15.0"
|
|
76
76
|
},
|
|
77
77
|
"devDependencies": {
|
|
78
78
|
"@types/estree-jsx": "^1.0.5",
|
|
@@ -5,7 +5,9 @@
|
|
|
5
5
|
|
|
6
6
|
import { useState, useEffect } from 'react'
|
|
7
7
|
|
|
8
|
-
|
|
8
|
+
let locale = 'en'
|
|
9
|
+
|
|
10
|
+
const callbacks = new Set([(/** @type {string} */ loc) => {locale = loc}])
|
|
9
11
|
|
|
10
12
|
/**
|
|
11
13
|
* @param {string} locale
|
|
@@ -19,7 +21,12 @@ export function setLocale(locale) {
|
|
|
19
21
|
export default (/** @type {{[locale: string]: import('wuchale/runtime').CatalogModule }} */ catalogs) => {
|
|
20
22
|
const [locale, setLocale] = useState('en')
|
|
21
23
|
useEffect(() => {
|
|
22
|
-
|
|
24
|
+
const cb = (/** @type {string} */ locale) => setLocale(locale)
|
|
25
|
+
callbacks.add(cb)
|
|
26
|
+
return () => callbacks.delete(cb)
|
|
23
27
|
})
|
|
24
28
|
return catalogs[locale]
|
|
25
29
|
}
|
|
30
|
+
|
|
31
|
+
// non-reactive
|
|
32
|
+
export const get = (/** @type {{[locale: string]: import('wuchale/runtime').CatalogModule }} */ catalogs) => catalogs[locale]
|
package/src/loaders/react.js
CHANGED
|
@@ -10,8 +10,11 @@ import { useState, useEffect } from 'react'
|
|
|
10
10
|
const callbacks = {}
|
|
11
11
|
const store = {}
|
|
12
12
|
|
|
13
|
+
// non-reactive
|
|
14
|
+
export const get = (/** @type {string} */ loadID) => store[loadID]
|
|
15
|
+
|
|
13
16
|
const collection = {
|
|
14
|
-
get
|
|
17
|
+
get,
|
|
15
18
|
set: (/** @type {string} */ loadID, /** @type {import('wuchale/runtime').CatalogModule} */ catalog) => {
|
|
16
19
|
store[loadID] = catalog // for when useEffect hasn't run yet
|
|
17
20
|
callbacks[loadID]?.(catalog)
|
|
@@ -20,13 +23,11 @@ const collection = {
|
|
|
20
23
|
|
|
21
24
|
registerLoaders(key, loadCatalog, loadIDs, collection)
|
|
22
25
|
|
|
23
|
-
/**
|
|
24
|
-
* @param { string } loadID
|
|
25
|
-
*/
|
|
26
|
-
export default loadID => {
|
|
26
|
+
export default (/** @type {string} */ loadID) => {
|
|
27
27
|
const [catalog, setCatalog] = useState(collection.get(loadID))
|
|
28
28
|
useEffect(() => {
|
|
29
29
|
callbacks[loadID] = (/** @type {import('wuchale/runtime').CatalogModule} */ catalog) => setCatalog(catalog)
|
|
30
|
+
return () => delete callbacks[loadID]
|
|
30
31
|
})
|
|
31
32
|
return catalog
|
|
32
33
|
}
|