wuchale 0.18.4 → 0.18.6

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.
@@ -2,13 +2,14 @@ import type MagicString from "magic-string";
2
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
+ type BasicNode = {
6
+ start: number;
7
+ end: number;
8
+ };
5
9
  type InitProps<NodeT> = {
6
10
  vars: () => RuntimeVars;
7
11
  mstr: MagicString;
8
- getRange: (node: NodeT) => {
9
- start: number;
10
- end: number;
11
- };
12
+ getRange: (node: NodeT) => BasicNode;
12
13
  isText: (node: NodeT) => boolean;
13
14
  isExpression: (node: NodeT) => boolean;
14
15
  isComment: (node: NodeT) => boolean;
@@ -33,7 +34,7 @@ type VisitProps<NodeT> = {
33
34
  attribute?: string;
34
35
  useComponent?: boolean;
35
36
  };
36
- export interface MixedVisitor<NodeT> extends InitProps<NodeT> {
37
+ export interface MixedVisitor<NodeT extends BasicNode> extends InitProps<NodeT> {
37
38
  }
38
39
  export declare class MixedVisitor<NodeT> {
39
40
  constructor(props: InitProps<NodeT>);
@@ -169,6 +169,11 @@ export class MixedVisitor {
169
169
  begin += ', [';
170
170
  end = ']' + end;
171
171
  }
172
+ if (props.scope === 'attribute' && `'"`.includes(this.mstr.original[lastChildEnd])) {
173
+ const firstChild = props.children[0];
174
+ this.mstr.remove(firstChild.start - 1, firstChild.start);
175
+ this.mstr.remove(lastChildEnd, lastChildEnd + 1);
176
+ }
172
177
  this.mstr.appendLeft(lastChildEnd, begin);
173
178
  this.mstr.appendRight(lastChildEnd, end);
174
179
  }
@@ -4,8 +4,9 @@ export { Transformer };
4
4
  export { parseScript, scriptParseOptions, scriptParseOptionsWithComments } from './transformer.js';
5
5
  export declare const pluralPattern: CodePattern;
6
6
  type LoadersAvailable = 'server' | 'vite';
7
+ export type VanillaArgs = AdapterArgs<LoadersAvailable>;
7
8
  export declare function getDefaultLoaderPath(loader: LoaderChoice<LoadersAvailable>, bundle: boolean): string | {
8
9
  client: string;
9
10
  server: string;
10
11
  };
11
- export declare const adapter: (args?: AdapterArgs<LoadersAvailable>) => Adapter;
12
+ export declare const adapter: (args?: VanillaArgs) => Adapter;
@@ -79,6 +79,14 @@ export declare class Transformer {
79
79
  visitTemplateLiteralQuasis: (node: Estree.TemplateLiteral, msgTyp: MessageType) => [number, Message[]];
80
80
  visitTemplateLiteral: (node: Estree.TemplateLiteral, heurDetails?: HeuristicDetailsBase | boolean) => Message[];
81
81
  visitTaggedTemplateExpression: (node: Estree.TaggedTemplateExpression) => Message[];
82
+ visitSwitchStatement: (node: Estree.SwitchStatement) => Message[];
83
+ visitTryStatement: (node: Estree.TryStatement) => Message[];
84
+ visitTSAsExpression: (node: {
85
+ expression: Estree.AnyNode;
86
+ }) => Message[];
87
+ visitTSTypeAssertion: (node: {
88
+ expression: Estree.AnyNode;
89
+ }) => Message[];
82
90
  visitProgram: (node: Estree.Program) => Message[];
83
91
  visitWithCommentDirectives: (node: Estree.AnyNode, func: Function) => any;
84
92
  visit: (node: Estree.AnyNode) => Message[];
@@ -322,12 +322,19 @@ export class Transformer {
322
322
  ...this.visit(node.right),
323
323
  ...this.visit(node.body),
324
324
  ];
325
- visitForStatement = (node) => [
326
- ...this.visit(node.init),
327
- ...this.visit(node.test),
328
- ...this.visit(node.update),
329
- ...this.visit(node.body),
330
- ];
325
+ visitForStatement = (node) => {
326
+ const msgs = this.visit(node.body);
327
+ if (node.init) {
328
+ msgs.push(...this.visit(node.init));
329
+ }
330
+ if (node.test) {
331
+ msgs.push(...this.visit(node.test));
332
+ }
333
+ if (node.update) {
334
+ msgs.push(...this.visit(node.update));
335
+ }
336
+ return msgs;
337
+ };
331
338
  getMemberChainName = (node) => {
332
339
  let name = '';
333
340
  if (node.object.type === 'Identifier') {
@@ -485,7 +492,9 @@ export class Transformer {
485
492
  if (body.type === 'MethodDefinition') {
486
493
  msgs.push(...this.visit(body.key));
487
494
  const methodName = this.content.slice(body.key.start, body.key.end);
488
- msgs.push(...this.visitFunctionBody(body.value.body, `${node.id.name}.${methodName}`));
495
+ if (body.value.type === 'FunctionExpression') { // and not e.g. TSDeclareMethod
496
+ msgs.push(...this.visitFunctionBody(body.value.body, `${node.id.name}.${methodName}`));
497
+ }
489
498
  }
490
499
  else if (body.type === 'StaticBlock') {
491
500
  const currentFuncDef = this.currentFuncDef;
@@ -580,6 +589,19 @@ export class Transformer {
580
589
  this.currentCall = prevCall;
581
590
  return msgs;
582
591
  };
592
+ visitSwitchStatement = (node) => node.cases.map(c => c.consequent.map(this.visit)).flat().flat();
593
+ visitTryStatement = (node) => {
594
+ const msgs = this.visit(node.block);
595
+ if (node.handler) {
596
+ msgs.push(...this.visit(node.handler.body));
597
+ }
598
+ if (node.finalizer) {
599
+ msgs.push(...this.visit(node.finalizer));
600
+ }
601
+ return msgs;
602
+ };
603
+ visitTSAsExpression = (node) => this.visit(node.expression);
604
+ visitTSTypeAssertion = (node) => this.visit(node.expression);
583
605
  visitProgram = (node) => {
584
606
  this.insideProgram = true;
585
607
  const msgs = this.visitStatementsNSaveRealBodyStart(node.body);
@@ -123,6 +123,8 @@ export type Adapter = AdapterPassThruOpts & {
123
123
  loaderExts: string[];
124
124
  /** default loaders to copy, `null` means custom */
125
125
  defaultLoaderPath: LoaderPath | string | null;
126
+ /** names to import from loaders, should avoid collision with code variables */
127
+ getRuntimeVars?: Partial<CatalogExpr>;
126
128
  };
127
129
  export type CodePattern = {
128
130
  name: string;
package/dist/compile.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- export type Mixed = (number | string)[];
2
- export type CompositePayload = CompiledElement | number;
1
+ export type CompositePayload = number | string | Composite;
3
2
  export type Composite = [number, ...CompositePayload[]];
4
- export type CompiledElement = string | Mixed | Composite;
3
+ export type Mixed = (string | number)[];
4
+ export type CompiledElement = string | Mixed | CompositePayload[];
5
5
  export declare function compileTranslation(msgStr: string, fallback: CompiledElement): CompiledElement;
package/dist/handler.js CHANGED
@@ -23,13 +23,9 @@ export const urlPatternFlag = 'url-pattern';
23
23
  const urlExtractedFlag = 'url-extracted';
24
24
  const loaderImportGetRuntime = 'getRuntime';
25
25
  const loaderImportGetRuntimeRx = 'getRuntimeRx';
26
- const getFuncPlain = '_w_load_';
27
- const getFuncReactive = getFuncPlain + 'rx_';
26
+ const getFuncPlainDefault = '_w_load_';
27
+ const getFuncReactiveDefault = getFuncPlainDefault + 'rx_';
28
28
  const bundleCatalogsVarName = '_w_catalogs_';
29
- const bundledCatalogExpr = {
30
- plain: `${getFuncPlain}(${bundleCatalogsVarName})`,
31
- reactive: `${getFuncReactive}(${bundleCatalogsVarName})`,
32
- };
33
29
  const objKeyLocale = (locale) => locale.includes('-') ? `'${locale}'` : locale;
34
30
  export async function loadPOFile(filename) {
35
31
  return new Promise((res, rej) => {
@@ -473,7 +469,7 @@ export class AdapterHandler {
473
469
  }
474
470
  const compiledItems = JSON.stringify(compiledData.items);
475
471
  const plural = `n => ${this.sharedState.poFilesByLoc[locale].pluralRule.plural}`;
476
- let module = `export let ${catalogVarName} = ${compiledItems}`;
472
+ let module = `/** @type import('wuchale').CompiledElement[] */\nexport let ${catalogVarName} = ${compiledItems}`;
477
473
  if (compiledData.hasPlurals) {
478
474
  module = `${module}\nexport let p = ${plural}`;
479
475
  }
@@ -698,15 +694,20 @@ export class AdapterHandler {
698
694
  }
699
695
  `;
700
696
  };
697
+ #getRuntimeVars = () => ({
698
+ plain: this.#adapter.getRuntimeVars?.plain ?? getFuncPlainDefault,
699
+ reactive: this.#adapter.getRuntimeVars?.reactive ?? getFuncReactiveDefault,
700
+ });
701
701
  #prepareHeader = (filename, loadID, hmrData, forServer) => {
702
702
  let head = [];
703
- let getFuncImportPlain = getFuncPlain;
704
- let getFuncImportReactive = getFuncReactive;
703
+ const getRuntimeVars = this.#getRuntimeVars();
704
+ let getRuntimePlain = getRuntimeVars.plain;
705
+ let getRuntimeReactive = getRuntimeVars.reactive;
705
706
  if (hmrData != null) {
706
707
  head.push(`const ${varNames.hmrUpdate} = ${JSON.stringify(hmrData)}`);
707
- getFuncImportPlain += 'hmr_';
708
- getFuncImportReactive += 'hmr_';
709
- head.push(this.#hmrUpdateFunc(getFuncPlain, getFuncImportPlain), this.#hmrUpdateFunc(getFuncReactive, getFuncImportReactive));
708
+ getRuntimePlain += 'hmr_';
709
+ getRuntimeReactive += 'hmr_';
710
+ head.push(this.#hmrUpdateFunc(getRuntimeVars.plain, getRuntimePlain), this.#hmrUpdateFunc(getRuntimeVars.reactive, getRuntimeReactive));
710
711
  }
711
712
  let loaderRelTo = filename;
712
713
  if (this.#adapter.outDir) {
@@ -714,8 +715,8 @@ export class AdapterHandler {
714
715
  }
715
716
  const loaderPath = this.#getImportPath(forServer ? this.loaderPath.server : this.loaderPath.client, loaderRelTo);
716
717
  const importsFuncs = [
717
- `${loaderImportGetRuntime} as ${getFuncImportPlain}`,
718
- `${loaderImportGetRuntimeRx} as ${getFuncImportReactive}`,
718
+ `${loaderImportGetRuntime} as ${getRuntimePlain}`,
719
+ `${loaderImportGetRuntimeRx} as ${getRuntimeReactive}`,
719
720
  ];
720
721
  head = [
721
722
  `import {${importsFuncs.join(', ')}} from "${loaderPath}"`,
@@ -739,12 +740,16 @@ export class AdapterHandler {
739
740
  ].join('\n');
740
741
  };
741
742
  #prepareRuntimeExpr = (loadID) => {
743
+ const importLoaderVars = this.#getRuntimeVars();
742
744
  if (this.#adapter.bundleLoad) {
743
- return bundledCatalogExpr;
745
+ return {
746
+ plain: `${importLoaderVars.plain}(${bundleCatalogsVarName})`,
747
+ reactive: `${importLoaderVars.reactive}(${bundleCatalogsVarName})`,
748
+ };
744
749
  }
745
750
  return {
746
- plain: `${getFuncPlain}('${loadID}')`,
747
- reactive: `${getFuncReactive}('${loadID}')`,
751
+ plain: `${importLoaderVars.plain}('${loadID}')`,
752
+ reactive: `${importLoaderVars.reactive}('${loadID}')`,
748
753
  };
749
754
  };
750
755
  handleMessages = async (loc, msgs, filename) => {
package/dist/runtime.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import type { Mixed, CompiledElement, Composite } from "./compile.js";
1
+ import type { Mixed, CompiledElement, CompositePayload } from "./compile.js";
2
2
  export declare const catalogVarName: "c";
3
3
  export type CatalogModule = {
4
4
  [catalogVarName]: CompiledElement[];
@@ -10,7 +10,7 @@ export declare function onInvalid(newOnInvalid: typeof onInvalidFunc): void;
10
10
  export type Runtime = {
11
11
  _: CatalogModule;
12
12
  l: string;
13
- cx: (id: number) => Mixed | Composite;
13
+ cx: (id: number) => Mixed | CompositePayload[];
14
14
  tx: (ctx: Mixed, args?: any[], start?: number) => string;
15
15
  tt: (tag: CallableFunction, id: number, args?: any[]) => any;
16
16
  tp: (id: number) => any;
package/package.json CHANGED
@@ -1,11 +1,11 @@
1
1
  {
2
2
  "name": "wuchale",
3
- "version": "0.18.4",
3
+ "version": "0.18.6",
4
4
  "description": "Protobuf-like i18n from plain code",
5
5
  "scripts": {
6
6
  "dev": "tsc --watch",
7
7
  "build": "tsc",
8
- "test": "node tests"
8
+ "test": "node tests/index.ts"
9
9
  },
10
10
  "keywords": [
11
11
  "i18n",
@@ -77,7 +77,7 @@
77
77
  "author": "K1DV5",
78
78
  "license": "MIT",
79
79
  "dependencies": {
80
- "@sveltejs/acorn-typescript": "^1.0.6",
80
+ "@sveltejs/acorn-typescript": "^1.0.7",
81
81
  "acorn": "^8.15.0",
82
82
  "chokidar": "^4.0.3",
83
83
  "magic-string": "^0.30.21",
@@ -87,7 +87,7 @@
87
87
  "tinyglobby": "^0.2.15"
88
88
  },
89
89
  "devDependencies": {
90
- "@types/node": "^24.10.0",
90
+ "@types/node": "^24.10.1",
91
91
  "@types/picomatch": "^4.0.1",
92
92
  "typescript": "^5.9.3"
93
93
  },