@wuchale/jsx 0.8.2 → 0.9.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.d.ts CHANGED
@@ -1,8 +1,14 @@
1
- import type { HeuristicFunc, Adapter, AdapterArgs } from 'wuchale';
1
+ import type { HeuristicFunc, Adapter, AdapterArgs, LoaderChoice, CreateHeuristicOpts } from 'wuchale';
2
2
  import { type JSXLib } from "./transformer.js";
3
+ export declare function createJsxHeuristic(opts: CreateHeuristicOpts): HeuristicFunc;
3
4
  export declare const jsxDefaultHeuristic: HeuristicFunc;
4
- type JSXArgs = AdapterArgs & {
5
+ type LoadersAvailable = 'default' | 'react' | 'solidjs';
6
+ type JSXArgs = AdapterArgs<LoadersAvailable> & {
5
7
  variant?: JSXLib;
6
8
  };
9
+ export declare function getDefaultLoaderPath(loader: LoaderChoice<LoadersAvailable>, bundle: boolean): string | {
10
+ client: string;
11
+ server: string;
12
+ };
7
13
  export declare const adapter: (args?: JSXArgs) => Adapter;
8
14
  export {};
package/dist/index.js CHANGED
@@ -1,19 +1,24 @@
1
- import { defaultGenerateLoadID, defaultHeuristic, deepMergeObjects } from 'wuchale';
2
- import { pluralPattern, adapter as vanillaAdapter } from 'wuchale/adapter-vanilla';
1
+ import { defaultGenerateLoadID, deepMergeObjects, createHeuristic, defaultHeuristicOpts } from 'wuchale';
2
+ import { pluralPattern, getDefaultLoaderPath as getDefaultLoaderPathVanilla } from 'wuchale/adapter-vanilla';
3
3
  import { JSXTransformer } from "./transformer.js";
4
- import { getDependencies, loaderPathResolver } from 'wuchale/adapter-utils';
5
- export const jsxDefaultHeuristic = msg => {
6
- if (!defaultHeuristic(msg)) {
7
- return false;
8
- }
9
- if (msg.details.scope !== 'script') {
10
- return true;
11
- }
12
- if (msg.details.declaring === 'variable') {
13
- return false;
14
- }
15
- return true;
16
- };
4
+ import { loaderPathResolver } from 'wuchale/adapter-utils';
5
+ export function createJsxHeuristic(opts) {
6
+ const defaultHeuristic = createHeuristic(opts);
7
+ return msg => {
8
+ const defRes = defaultHeuristic(msg);
9
+ if (!defRes) {
10
+ return false;
11
+ }
12
+ if (msg.details.scope !== 'script') {
13
+ return defRes;
14
+ }
15
+ if (msg.details.declaring === 'variable') {
16
+ return false;
17
+ }
18
+ return defRes;
19
+ };
20
+ }
21
+ export const jsxDefaultHeuristic = createJsxHeuristic(defaultHeuristicOpts);
17
22
  const defaultRuntime = {
18
23
  useReactive: ({ funcName, nested }) => {
19
24
  const inTopLevel = funcName == null;
@@ -24,12 +29,10 @@ const defaultRuntime = {
24
29
  };
25
30
  },
26
31
  reactive: {
27
- importName: 'default',
28
32
  wrapInit: expr => expr,
29
33
  wrapUse: expr => expr,
30
34
  },
31
35
  plain: {
32
- importName: 'get',
33
36
  wrapInit: expr => expr,
34
37
  wrapUse: expr => expr,
35
38
  },
@@ -44,56 +47,44 @@ const defaultRuntimeSolid = {
44
47
  };
45
48
  },
46
49
  reactive: {
47
- importName: 'default',
48
50
  wrapInit: expr => `() => ${expr}`,
49
51
  wrapUse: expr => `${expr}()`
50
52
  }
51
53
  };
52
54
  const defaultArgs = {
53
55
  files: { include: 'src/**/*.{js,ts,jsx,tsx}', ignore: '**/*.d.ts' },
54
- catalog: './src/locales/{locale}',
56
+ localesDir: './src/locales',
55
57
  patterns: [pluralPattern],
56
58
  heuristic: jsxDefaultHeuristic,
57
59
  granularLoad: false,
58
60
  bundleLoad: false,
61
+ loader: 'default',
59
62
  generateLoadID: defaultGenerateLoadID,
60
- writeFiles: {},
61
63
  runtime: defaultRuntime,
62
64
  variant: 'default',
63
65
  };
64
66
  const resolveLoaderPath = loaderPathResolver(import.meta.url, '../src/loaders', 'js');
67
+ export function getDefaultLoaderPath(loader, bundle) {
68
+ if (loader === 'default') {
69
+ return getDefaultLoaderPathVanilla('bundle', bundle);
70
+ }
71
+ if (bundle) {
72
+ loader += '.bundle';
73
+ }
74
+ return resolveLoaderPath(loader);
75
+ }
65
76
  export const adapter = (args = defaultArgs) => {
66
- let { heuristic, patterns, variant, runtime, ...rest } = deepMergeObjects(args, defaultArgs);
77
+ let { heuristic, patterns, variant, runtime, loader, ...rest } = deepMergeObjects(args, defaultArgs);
67
78
  if (variant === 'solidjs' && args.runtime == null) {
68
79
  runtime = defaultRuntimeSolid;
69
80
  }
70
81
  return {
71
- transform: ({ content, filename, index, expr }) => {
72
- return new JSXTransformer(content, filename, index, heuristic, patterns, expr, runtime).transformJx(variant);
82
+ transform: ({ content, filename, index, expr, matchUrl }) => {
83
+ return new JSXTransformer(content, filename, index, heuristic, patterns, expr, runtime, matchUrl).transformJx(variant);
73
84
  },
74
85
  loaderExts: ['.js', '.ts'],
75
- defaultLoaders: async () => {
76
- const deps = await getDependencies();
77
- const loaders = ['default'];
78
- if (deps.has('react') || deps.has('preact')) {
79
- loaders.unshift('react');
80
- }
81
- if (deps.has('solid-js')) {
82
- loaders.unshift('solidjs');
83
- }
84
- return loaders;
85
- },
86
- defaultLoaderPath: (loader) => {
87
- if (loader === 'default') {
88
- return vanillaAdapter({ bundleLoad: rest.bundleLoad }).defaultLoaderPath('vite');
89
- }
90
- if (rest.bundleLoad) {
91
- loader += '.bundle';
92
- }
93
- return resolveLoaderPath(loader);
94
- },
86
+ defaultLoaderPath: getDefaultLoaderPath(loader, rest.bundleLoad),
95
87
  runtime,
96
88
  ...rest,
97
- docsUrl: 'https://wuchale.dev/adapters/jsx'
98
89
  };
99
90
  };
@@ -2,7 +2,7 @@ import { Message } from 'wuchale';
2
2
  import type * as JX from 'estree-jsx';
3
3
  import type * as Estree from 'acorn';
4
4
  import { Transformer } from 'wuchale/adapter-vanilla';
5
- import type { IndexTracker, HeuristicFunc, TransformOutput, RuntimeConf, CatalogExpr, CodePattern } from 'wuchale';
5
+ import type { IndexTracker, HeuristicFunc, TransformOutput, RuntimeConf, CatalogExpr, CodePattern, UrlMatcher } from 'wuchale';
6
6
  import { MixedVisitor, type CommentDirectives } from "wuchale/adapter-utils";
7
7
  export declare function parseScriptJSX(content: string): [Estree.Program, Estree.Comment[][]];
8
8
  type MixedNodesTypes = JX.JSXElement | JX.JSXFragment | JX.JSXText | JX.JSXExpressionContainer | JX.JSXSpreadChild;
@@ -14,7 +14,7 @@ export declare class JSXTransformer extends Transformer {
14
14
  lastVisitIsComment: boolean;
15
15
  currentJsxKey?: number;
16
16
  mixedVisitor: MixedVisitor<MixedNodesTypes>;
17
- constructor(content: string, filename: string, index: IndexTracker, heuristic: HeuristicFunc, patterns: CodePattern[], catalogExpr: CatalogExpr, rtConf: RuntimeConf);
17
+ constructor(content: string, filename: string, index: IndexTracker, heuristic: HeuristicFunc, patterns: CodePattern[], catalogExpr: CatalogExpr, rtConf: RuntimeConf, matchUrl: UrlMatcher);
18
18
  initMixedVisitor: () => MixedVisitor<MixedNodesTypes>;
19
19
  visitChildrenJ: (node: JX.JSXElement | JX.JSXFragment) => Message[];
20
20
  visitNameJSXNamespacedName: (node: JX.JSXNamespacedName) => string;
@@ -19,8 +19,8 @@ export class JSXTransformer extends Transformer {
19
19
  lastVisitIsComment = false;
20
20
  currentJsxKey;
21
21
  mixedVisitor;
22
- constructor(content, filename, index, heuristic, patterns, catalogExpr, rtConf) {
23
- super(content, filename, index, heuristic, patterns, catalogExpr, rtConf);
22
+ constructor(content, filename, index, heuristic, patterns, catalogExpr, rtConf, matchUrl) {
23
+ super(content, filename, index, heuristic, patterns, catalogExpr, rtConf, matchUrl);
24
24
  }
25
25
  initMixedVisitor = () => new MixedVisitor({
26
26
  mstr: this.mstr,
@@ -50,7 +50,7 @@ export class JSXTransformer extends Transformer {
50
50
  },
51
51
  visitExpressionTag: this.visitJSXExpressionContainer,
52
52
  fullHeuristicDetails: this.fullHeuristicDetails,
53
- checkHeuristic: this.checkHeuristicBool,
53
+ checkHeuristic: this.getHeuristicMessageType,
54
54
  index: this.index,
55
55
  wrapNested: (msgInfo, hasExprs, nestedRanges, lastChildEnd) => {
56
56
  let begin = `<${rtComponent}`;
@@ -152,13 +152,6 @@ export class JSXTransformer extends Transformer {
152
152
  if (node.value == null) {
153
153
  return [];
154
154
  }
155
- if (node.value.type !== 'Literal') {
156
- return this.visitJx(node.value);
157
- }
158
- if (typeof node.value.value !== 'string') {
159
- return [];
160
- }
161
- const value = node.value;
162
155
  let name;
163
156
  if (node.name.type === 'JSXIdentifier') {
164
157
  name = node.name.name;
@@ -166,11 +159,29 @@ export class JSXTransformer extends Transformer {
166
159
  else {
167
160
  name = node.name.name.name;
168
161
  }
169
- const [pass, msgInfo] = this.checkHeuristic(node.value.value, {
170
- scope: 'attribute',
162
+ const heurBase = {
163
+ scope: 'script',
171
164
  element: this.currentElement,
172
165
  attribute: name,
173
- });
166
+ };
167
+ if (node.value.type !== 'Literal') {
168
+ if (node.value.type === 'JSXExpressionContainer') {
169
+ if (node.value.expression.type === 'Literal' && typeof node.value.expression.value === 'string') {
170
+ const expr = node.value.expression;
171
+ return this.visitWithCommentDirectives(expr, () => this.visitLiteral(expr, heurBase));
172
+ }
173
+ if (node.value.expression.type === 'TemplateLiteral') {
174
+ const expr = node.value.expression;
175
+ return this.visitWithCommentDirectives(expr, () => this.visitTemplateLiteral(expr, heurBase));
176
+ }
177
+ }
178
+ return this.visitJx(node.value);
179
+ }
180
+ if (typeof node.value.value !== 'string') {
181
+ return [];
182
+ }
183
+ const value = node.value;
184
+ const [pass, msgInfo] = this.checkHeuristic(node.value.value, heurBase);
174
185
  if (!pass) {
175
186
  return [];
176
187
  }
@@ -213,7 +224,7 @@ export class JSXTransformer extends Transformer {
213
224
  if (this.commentDirectives.ignoreFile) {
214
225
  return [];
215
226
  }
216
- if (this.commentDirectives.forceInclude !== false) {
227
+ if (this.commentDirectives.forceType !== false) {
217
228
  msgs = this.visit(node);
218
229
  }
219
230
  this.commentDirectives = commentDirectivesPrev;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wuchale/jsx",
3
- "version": "0.8.2",
3
+ "version": "0.9.0",
4
4
  "description": "Protobuf-like i18n from plain code: JSX adapter",
5
5
  "scripts": {
6
6
  "dev": "tsc --watch",
@@ -71,7 +71,7 @@
71
71
  "dependencies": {
72
72
  "@sveltejs/acorn-typescript": "^1.0.6",
73
73
  "acorn": "^8.15.0",
74
- "wuchale": "^0.17.4"
74
+ "wuchale": "^0.18.0"
75
75
  },
76
76
  "devDependencies": {
77
77
  "@types/estree-jsx": "^1.0.5",
@@ -1,9 +1,8 @@
1
1
  // This is just the default loader.
2
2
  // You can customize it however you want, it will not be overwritten once it exists and is not empty.
3
3
 
4
- /// <reference types="wuchale/virtual" />
5
-
6
- import { useState, useEffect } from 'react'
4
+ import { useState, useEffect, useMemo } from 'react'
5
+ import toRuntime from 'wuchale/runtime'
7
6
 
8
7
  let locale = 'en'
9
8
 
@@ -18,15 +17,15 @@ export function setLocale(locale) {
18
17
  }
19
18
  }
20
19
 
21
- export default (/** @type {{[locale: string]: import('wuchale/runtime').CatalogModule }} */ catalogs) => {
20
+ export const getRuntimeRx = (/** @type {{[locale: string]: import('wuchale/runtime').CatalogModule }} */ catalogs) => {
22
21
  const [locale, setLocale] = useState('en')
23
22
  useEffect(() => {
24
23
  const cb = (/** @type {string} */ locale) => setLocale(locale)
25
24
  callbacks.add(cb)
26
25
  return () => callbacks.delete(cb)
27
- })
28
- return catalogs[locale]
26
+ }, [catalogs])
27
+ return useMemo(() => toRuntime(catalogs[locale], locale), [locale, catalogs])
29
28
  }
30
29
 
31
30
  // non-reactive
32
- export const get = (/** @type {{[locale: string]: import('wuchale/runtime').CatalogModule }} */ catalogs) => catalogs[locale]
31
+ export const getRuntime = (/** @type {{[locale: string]: import('wuchale/runtime').CatalogModule }} */ catalogs) => toRuntime(catalogs[locale], locale)
@@ -1,33 +1,32 @@
1
1
  // This is just the default loader.
2
2
  // You can customize it however you want, it will not be overwritten once it exists and is not empty.
3
3
 
4
- /// <reference types="wuchale/virtual" />
5
-
6
- import { loadCatalog, loadIDs, key } from 'virtual:wuchale/proxy' // or proxy/sync
4
+ import { loadCatalog, loadIDs } from '${PROXY}'
7
5
  import { registerLoaders } from 'wuchale/load-utils'
8
6
  import { useState, useEffect } from 'react'
9
7
 
8
+ export const key = '${KEY}'
10
9
  const callbacks = {}
11
10
  const store = {}
12
11
 
13
12
  // non-reactive
14
- export const get = (/** @type {string} */ loadID) => store[loadID]
13
+ export const getRuntime = (/** @type {string} */ loadID) => store[loadID]
15
14
 
16
15
  const collection = {
17
- get,
18
- set: (/** @type {string} */ loadID, /** @type {import('wuchale/runtime').CatalogModule} */ catalog) => {
19
- store[loadID] = catalog // for when useEffect hasn't run yet
20
- callbacks[loadID]?.(catalog)
16
+ get: getRuntime,
17
+ set: (/** @type {string} */ loadID, /** @type {import('wuchale/runtime').Runtime} */ runtime) => {
18
+ store[loadID] = runtime // for when useEffect hasn't run yet
19
+ callbacks[loadID]?.(runtime)
21
20
  }
22
21
  }
23
22
 
24
23
  registerLoaders(key, loadCatalog, loadIDs, collection)
25
24
 
26
- export default (/** @type {string} */ loadID) => {
27
- const [catalog, setCatalog] = useState(collection.get(loadID))
25
+ export const getRuntimeRx = (/** @type {string} */ loadID) => {
26
+ const [runtime, setRuntime] = useState(collection.get(loadID))
28
27
  useEffect(() => {
29
- callbacks[loadID] = (/** @type {import('wuchale/runtime').CatalogModule} */ catalog) => setCatalog(catalog)
28
+ callbacks[loadID] = (/** @type {import('wuchale/runtime').Runtime} */ runtime) => setRuntime(runtime)
30
29
  return () => delete callbacks[loadID]
31
- })
32
- return catalog
30
+ }, [loadID])
31
+ return runtime
33
32
  }
@@ -3,6 +3,7 @@
3
3
  // The content is this way because you have enabled bundleLoad in the config.
4
4
 
5
5
  import { createSignal } from "solid-js"
6
+ import toRuntime from "wuchale/runtime"
6
7
 
7
8
  const [locale, setLocale] = createSignal('en')
8
9
 
@@ -11,6 +12,6 @@ export { setLocale }
11
12
  /**
12
13
  * @param {{ [locale: string]: import('wuchale/runtime').CatalogModule }} catalogs
13
14
  */
14
- export const get = catalogs => catalogs[locale()]
15
+ export const getRuntimeRx = catalogs => toRuntime(catalogs[locale()], locale())
15
16
  // same function, because solid-js can use them anywhere
16
- export default get
17
+ export const getRuntime = getRuntimeRx
@@ -1,17 +1,17 @@
1
1
  // This is just the default loader.
2
2
  // You can customize it however you want, it will not be overwritten once it exists and is not empty.
3
3
 
4
- /// <reference types="wuchale/virtual" />
5
-
6
- import { loadCatalog, loadIDs, key } from 'virtual:wuchale/proxy' // or proxy/sync
4
+ import { loadCatalog, loadIDs } from '${PROXY}'
7
5
  import { registerLoaders } from 'wuchale/load-utils'
8
6
  import { createStore } from 'solid-js/store'
9
7
 
8
+ const key = '${KEY}'
9
+
10
10
  const [store, setStore] = createStore({})
11
11
 
12
12
  // two exports. can be the same because solid-js can use them anywhere unlike react
13
- export const get = registerLoaders(key, loadCatalog, loadIDs, {
13
+ export const getRuntimeRx = registerLoaders(key, loadCatalog, loadIDs, {
14
14
  get: loadID => store[loadID],
15
15
  set: setStore,
16
16
  })
17
- export default get
17
+ export const getRuntime = getRuntimeRx