@dialexjs/cli 0.7.0 → 0.7.1

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/api.d.mts CHANGED
@@ -122,6 +122,34 @@ interface AnalysisConfig {
122
122
  include?: string | string[];
123
123
  exclude?: string[];
124
124
  }
125
+ /**
126
+ * Remembers parsed dictionaries and scanned source files between `analyzeProject` calls, keyed by
127
+ * modification time and size, so a long-lived caller (the editor extension) only re-reads what
128
+ * changed. Create one with {@link createAnalysisCache}; one-shot callers do not need it.
129
+ */
130
+ interface AnalysisCache {
131
+ dictionaries: Map<string, {
132
+ stamp: string;
133
+ loaded: Loaded;
134
+ }>;
135
+ sources: Map<string, {
136
+ stamp: string;
137
+ scan: SourceScan;
138
+ }>;
139
+ /** The `.gitignore` filter, reused until {@link clearGitignore} is called. */
140
+ gitignore: Map<string, (absolutePath: string) => boolean>;
141
+ }
142
+ export declare function createAnalysisCache(): AnalysisCache;
143
+ /** Forget the cached `.gitignore` rules, for example after a `.gitignore` file changed. */
144
+ export declare function clearGitignore(cache: AnalysisCache): void;
145
+ interface SourceScan {
146
+ /** Distinct word-like tokens, for the unused-key heuristic. */
147
+ tokens: string[];
148
+ refs: {
149
+ ref: Reference;
150
+ range: SourceRange;
151
+ }[];
152
+ }
125
153
  interface AnalysisOptions {
126
154
  root: string;
127
155
  config: AnalysisConfig;
@@ -135,6 +163,8 @@ interface AnalysisOptions {
135
163
  unused?: boolean;
136
164
  /** Report translations whose source text changed since `dialex.lock.json` recorded them. @default true */
137
165
  lock?: boolean;
166
+ /** Reuse work between calls. Ignored when `runtime` is set, because that evaluates code. */
167
+ cache?: AnalysisCache;
138
168
  }
139
169
  interface LeafInfo {
140
170
  kind: "string" | "function" | "other";
@@ -171,6 +201,21 @@ interface Reference {
171
201
  }
172
202
  /** Finds `getDictionary("x")`-style and `t("x.y.z")` references in source text. */
173
203
  export declare function scanReferences(text: string): Reference[];
204
+ interface DictionaryData {
205
+ name: string;
206
+ locales: string[];
207
+ leaves: Map<string, Map<string, LeafInfo>>;
208
+ df?: DictionaryFile;
209
+ }
210
+ type Loaded = {
211
+ ok: true;
212
+ data: DictionaryData;
213
+ } | {
214
+ ok: false;
215
+ level: IssueLevel;
216
+ code: IssueCode;
217
+ message: string;
218
+ };
174
219
  export declare function analyzeProject(options: AnalysisOptions): Promise<AnalysisResult>;
175
220
  /** Project root-relative path with forward slashes, for display. */
176
221
  export declare function relativeFile(root: string, file: string): string;
@@ -195,6 +240,8 @@ interface ScanOptions {
195
240
  ignore?: string[];
196
241
  /** Skip what `.gitignore` files ignore. @default true */
197
242
  gitignore?: boolean;
243
+ /** A filter from {@link createGitignoreFilter} to reuse instead of reading `.gitignore` again. */
244
+ gitignoreFilter?: (absolutePath: string) => boolean;
198
245
  }
199
246
  /** Finds files under `root`, skipping build output, configured excludes and Git-ignored paths. */
200
247
  export declare function scanFiles(root: string, patterns: string | string[], options?: ScanOptions): string[];
@@ -333,6 +380,14 @@ export declare function generateDictionaries(root: string, options?: GenerateOpt
333
380
  configFile?: string;
334
381
  notes: string[];
335
382
  };
383
+ /**
384
+ * Regenerates when a dictionary or config file is added, edited or removed. chokidar 4+ no longer
385
+ * understands globs, so this watches the project directory and decides for itself which events
386
+ * matter, using the same `include` glob as `generate`.
387
+ */
388
+ export declare function startGenerateWatcher(root: string, options: GenerateOptions, regenerate: () => void, delay?: number,
389
+ /** Where to report what triggered a regeneration. Defaults to the CLI logger (stdout). */
390
+ log?: (message: string) => void): import("chokidar").FSWatcher;
336
391
  //#endregion
337
- export type { AnalysisConfig, AnalysisIssue, AnalysisOptions, AnalysisResult, AnalyzedDictionary, DictionaryFile, GenerateOptions, IssueCode, IssueLevel, Leaf, LeafInfo, LeafKind, Lockfile, Project, ProjectDictionary, Reference, RenderedGenerate, ScanOptions, SourceRange, StaticConfig, StaticConfigResult };
392
+ export type { AnalysisCache, AnalysisConfig, AnalysisIssue, AnalysisOptions, AnalysisResult, AnalyzedDictionary, DictionaryFile, GenerateOptions, IssueCode, IssueLevel, Leaf, LeafInfo, LeafKind, Lockfile, Project, ProjectDictionary, Reference, RenderedGenerate, ScanOptions, SourceRange, StaticConfig, StaticConfigResult };
338
393
  //# sourceMappingURL=api.d.mts.map
@@ -1 +1 @@
1
- {"version":3,"file":"api.d.mts","names":[],"sources":["../src/utils/dictionary-edit.ts","../src/analysis.ts","../src/utils/files.ts","../src/utils/lockfile.ts","../src/utils/static-config.ts","../src/utils/project.ts","../src/commands/generate.ts"],"mappings":";;;;;;;;;;;;;;;KAiBK;EAAS;GAAe;;qBAEhB;UAII;EACf;;EAEA;EACA,KAAK,QAAQ,kBAAkB;;EAE/B,YAAY;;EAEZ;;;;;;EAMA;;;UAIe;EACf;IAAS;IAAc;;EACvB;IAAO;IAAc;;;KAGX;UAEK;EACf;EACA,MAAM;;EAEN;;;;;;wBAgIc,oBAAoB,cAAc,eAAe;;wBAoB3C,mBAAmB,eAAe,QAAQ;;wBAKhD,qBAAqB,IAAI;wBAKnB,mBAAmB,IAAI,iBAAiB;wBAQ9C,YAAY,IAAI;;wBAahB,WAAW,IAAI,gBAAgB,iBAAiB;wBAoChD,QAAQ,IAAI,gBAAgB,gBAAgB;wBAI5C,UAAU,IAAI,gBAAgB,gBAAgB;KA+BlD;;;;;wBAMI,UACd,IAAI,gBACJ,gBACA,gBACA,gBACC;;;;;;wBAsBa,SACd,IAAI,gBACJ,oBACA,kBACA,gBACA,aAAa;;;;;wBAwCC,WACd,IAAI,gBACJ,gBACA,kBACC;;wBAMa,mBAAmB,IAAI,iBAAiB;;wBAKxC,cACd,IAAI,gBACJ,gBACA;;;;;;;;;;;KClXU;KAEA;UAgBK;;EAEf;EACA,OAAO;EACP,MAAM;EACN;;EAEA,QAAQ;;EAER;EACA;;EAEA;;EAEA;;UAGe;EACf;EACA;EACA;EACA;;UAGe;EACf;EACA,QAAQ;;EAER;;EAEA;;EAEA;;EAEA;;EAEA;;UAGe;EACf;EACA;;UAGe;EACf;;EAEA;;EAEA;;EAEA,QAAQ,YAAY,YAAY;;EAEhC;;EAEA,KAAK;;UAGU;EACf,QAAQ;EACR,cAAc;;EAEd;EACA;;qBAGW;UAQI;;EAEf;EACA;;EAEA;EACA;;;wBAIc,eAAe,eAAe;wBA4IxB,eAAe,SAAS,kBAAkB,QAAQ;;wBAkPxD,aAAa,cAAc;;;;qBCzf9B;;qBAQA;;;;;;wBA2CG,sBAAsB,gBAAgB;UAoCrC;;EAEf;;EAEA;;EAEA;;EAEA;;;wBAIc,UACd,cACA,6BACA,UAAS;;;qBCzGE;;;;;;;;;;;;UAaI;EACf;EACA;EACA,SAAS,eAAe;;;wBAYV,WAAW;;wBAKX,SAAS,eAAe;;wBAiBxB,UAAU,cAAc,MAAM;;;;;wBA2B9B,QAAQ,MAAM,UAAU,gBAAgB,aAAa;;;;;;;;UC/DpD;EACf;EACA;EACA;EACA;EACA,WAAW;EACX;EACA;;UAGe;EACf,QAAQ;;EAER;;EAEA;;qBAMW,uBAAuB;;wBAmFpB,kBAAkB,cAAc,gBAA4B;;wBA+C5D,iBAAiB,cAAc,sBAAsB;;;UChKpD;;EAEf;EACA;EACA,IAAI;;UAGW;EACf;EACA,QAAQ;EACR,cAAc;;EAEd;;EAEA;;;;;;wBA4BoB,YAAY,cAAc,sBAAsB,QAAQ;;;;;wBASxD,kBAAkB,cAAc,sBAAsB,QAAQ;;qBAMvE,QAAK,oBAAsB;;;UCnDvB;EACf;EACA;EACA;EACA;EACA;;;;;EAKA;;UAGe;;EAEf;;EAEA;EACA;;EAEA;EACA;;EAEA;;EAEA;IAAc;IAAc;;;EAE5B;;;;;;;;;wBAcc,gBAAgB,cAAc,UAAS,kBAAuB;wBA8J9D,qBACd,cACA,UAAS;EAET;EACA;EACA;EACA;EACA"}
1
+ {"version":3,"file":"api.d.mts","names":[],"sources":["../src/utils/dictionary-edit.ts","../src/analysis.ts","../src/utils/files.ts","../src/utils/lockfile.ts","../src/utils/static-config.ts","../src/utils/project.ts","../src/commands/generate.ts"],"mappings":"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"}
package/dist/api.mjs CHANGED
@@ -1,2 +1,2 @@
1
- import { A as dictionaryLocation, B as saveDictionaryFile, C as writeLock, D as scanFiles, E as createGitignoreFilter, F as listLocales, I as loadDictionaryFile, L as locationOf, M as getString, N as hasPath, O as TODO_PREFIX, P as listLeaves, R as parseDictionaryText, T as SOURCE_BUILTIN_IGNORE, V as setString, _ as hashSource, a as renderGenerated, c as parseStaticConfig, f as DEFAULT_SOURCE_GLOB, g as LOCK_FILE, h as scanReferences, i as generateDictionaries, j as getLeafSource, k as copyLeaf, l as readStaticConfig, m as relativeFile, n as loadStaticProject, p as analyzeProject, r as toKey, s as DEFAULT_STATIC_CONFIG, t as loadProject, v as isStale, w as BUILTIN_IGNORE, x as readLock, z as renderDictionaryFile } from "./project-DBVeKLa3.mjs";
2
- export { BUILTIN_IGNORE, DEFAULT_SOURCE_GLOB, DEFAULT_STATIC_CONFIG, LOCK_FILE, SOURCE_BUILTIN_IGNORE, TODO_PREFIX, analyzeProject, copyLeaf, createGitignoreFilter, dictionaryLocation, generateDictionaries, getLeafSource, getString, hasPath, hashSource, isStale, listLeaves, listLocales, loadDictionaryFile, loadProject, loadStaticProject, locationOf, parseDictionaryText, parseStaticConfig, readLock, readStaticConfig, relativeFile, renderDictionaryFile, renderGenerated, saveDictionaryFile, scanFiles, scanReferences, setString, toKey, writeLock };
1
+ import { A as scanFiles, B as locationOf, D as BUILTIN_IGNORE, E as writeLock, F as getString, H as renderDictionaryFile, I as hasPath, L as listLeaves, M as copyLeaf, N as dictionaryLocation, O as SOURCE_BUILTIN_IGNORE, P as getLeafSource, R as listLocales, U as saveDictionaryFile, V as parseDictionaryText, W as setString, _ as relativeFile, a as renderGenerated, b as hashSource, c as DEFAULT_STATIC_CONFIG, g as createAnalysisCache, h as clearGitignore, i as generateDictionaries, j as TODO_PREFIX, k as createGitignoreFilter, l as parseStaticConfig, m as analyzeProject, n as loadStaticProject, p as DEFAULT_SOURCE_GLOB, r as toKey, s as startGenerateWatcher, t as loadProject, u as readStaticConfig, v as scanReferences, w as readLock, x as isStale, y as LOCK_FILE, z as loadDictionaryFile } from "./project-Dz0FbydQ.mjs";
2
+ export { BUILTIN_IGNORE, DEFAULT_SOURCE_GLOB, DEFAULT_STATIC_CONFIG, LOCK_FILE, SOURCE_BUILTIN_IGNORE, TODO_PREFIX, analyzeProject, clearGitignore, copyLeaf, createAnalysisCache, createGitignoreFilter, dictionaryLocation, generateDictionaries, getLeafSource, getString, hasPath, hashSource, isStale, listLeaves, listLocales, loadDictionaryFile, loadProject, loadStaticProject, locationOf, parseDictionaryText, parseStaticConfig, readLock, readStaticConfig, relativeFile, renderDictionaryFile, renderGenerated, saveDictionaryFile, scanFiles, scanReferences, setString, startGenerateWatcher, toKey, writeLock };
package/dist/index.mjs CHANGED
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- import { B as saveDictionaryFile, C as writeLock, D as scanFiles, F as listLocales, I as loadDictionaryFile, M as getString, N as hasPath, O as TODO_PREFIX, P as listLeaves, S as record, V as setString, a as renderGenerated, b as lockPath, d as logger, g as LOCK_FILE, i as generateDictionaries, k as copyLeaf, o as runGenerate, p as analyzeProject, r as toKey, t as loadProject, u as resolveDialexConfig, v as isStale, x as readLock, y as lockFor } from "./project-DBVeKLa3.mjs";
2
+ import { A as scanFiles, C as lockPath, E as writeLock, F as getString, I as hasPath, L as listLeaves, M as copyLeaf, R as listLocales, S as lockFor, T as record, U as saveDictionaryFile, W as setString, a as renderGenerated, d as resolveDialexConfig, f as logger, i as generateDictionaries, j as TODO_PREFIX, m as analyzeProject, o as runGenerate, r as toKey, t as loadProject, w as readLock, x as isStale, y as LOCK_FILE, z as loadDictionaryFile } from "./project-Dz0FbydQ.mjs";
3
3
  import { Command } from "commander";
4
4
  import fs from "node:fs";
5
5
  import path from "node:path";
@@ -10,7 +10,7 @@ import { argumentSignature, getArguments, isIcuStructured, parseMessage } from "
10
10
  import * as p from "@clack/prompts";
11
11
  import { addNuxtModule } from "magicast/helpers";
12
12
  //#region package.json
13
- var version = "0.7.0";
13
+ var version = "0.7.1";
14
14
  //#endregion
15
15
  //#region src/commands/check.ts
16
16
  function addIssue(diag, issue) {
@@ -363,7 +363,7 @@ function scanFiles(root, patterns, options = {}) {
363
363
  ]
364
364
  });
365
365
  if (options.gitignore === false) return files;
366
- const ignored = createGitignoreFilter(root);
366
+ const ignored = options.gitignoreFilter ?? createGitignoreFilter(root);
367
367
  return files.filter((file) => !ignored(file));
368
368
  }
369
369
  //#endregion
@@ -518,6 +518,17 @@ function lockFor(root, sourceLocale) {
518
518
  }
519
519
  //#endregion
520
520
  //#region src/analysis.ts
521
+ function createAnalysisCache() {
522
+ return {
523
+ dictionaries: /* @__PURE__ */ new Map(),
524
+ sources: /* @__PURE__ */ new Map(),
525
+ gitignore: /* @__PURE__ */ new Map()
526
+ };
527
+ }
528
+ /** Forget the cached `.gitignore` rules, for example after a `.gitignore` file changed. */
529
+ function clearGitignore(cache) {
530
+ cache.gitignore.clear();
531
+ }
521
532
  const DEFAULT_SOURCE_GLOB = "**/*.{ts,tsx,js,jsx,mjs,cjs,vue,svelte,astro,mdx}";
522
533
  /** `getDictionary("x")`, `useDictionary("x")`, `@DialexDictionary("x")` */
523
534
  const DICTIONARY_CALL = /\b(?:getDictionary|useDictionary|DialexDictionary)\(\s*(["'`])([^"'`$\n]+)\1/dg;
@@ -653,21 +664,61 @@ async function loadDictionaryData(file, runtime) {
653
664
  message: "This dictionary uses spreads, computed keys, imported values, or a computed name, so it cannot be analyzed statically."
654
665
  };
655
666
  }
667
+ function stampOf(file) {
668
+ try {
669
+ const stat = fs.statSync(file);
670
+ return `${stat.mtimeMs}:${stat.size}`;
671
+ } catch {
672
+ return;
673
+ }
674
+ }
675
+ async function cachedDictionary(file, runtime, cache) {
676
+ const stamp = cache ? stampOf(file) : void 0;
677
+ const hit = stamp ? cache.dictionaries.get(file) : void 0;
678
+ if (hit && hit.stamp === stamp) return hit.loaded;
679
+ const loaded = await loadDictionaryData(file, runtime);
680
+ if (cache && stamp) cache.dictionaries.set(file, {
681
+ stamp,
682
+ loaded
683
+ });
684
+ return loaded;
685
+ }
686
+ function scanSource(text) {
687
+ const starts = lineStarts(text);
688
+ const rangeOf = (start, end) => ({
689
+ start: positionAt(starts, start),
690
+ end: positionAt(starts, end)
691
+ });
692
+ return {
693
+ tokens: [...new Set(text.match(/[\w$-]+/g) ?? [])],
694
+ refs: scanReferences(text).map((ref) => ({
695
+ ref,
696
+ range: rangeOf(ref.start, ref.end)
697
+ }))
698
+ };
699
+ }
656
700
  async function analyzeProject(options) {
657
701
  const { root, config } = options;
658
702
  const include = config.include || "**/*.content.ts";
659
703
  const configuredLocales = config.locales || [];
660
704
  const defaultLocale = config.defaultLocale || "en";
661
705
  const extraIgnore = options.ignore ?? [];
706
+ const cache = options.runtime ? void 0 : options.cache;
707
+ let gitignore = cache?.gitignore.get(root);
708
+ if (cache && !gitignore) {
709
+ gitignore = createGitignoreFilter(root);
710
+ cache.gitignore.set(root, gitignore);
711
+ }
662
712
  const files = scanFiles(root, include, {
663
713
  exclude: config.exclude,
664
- ignore: extraIgnore
714
+ ignore: extraIgnore,
715
+ gitignoreFilter: gitignore
665
716
  });
666
717
  const issues = [];
667
718
  const dictionaries = [];
668
719
  const lock = options.lock === false ? void 0 : readLock(root);
669
720
  for (const file of files) {
670
- const loaded = await loadDictionaryData(file, options.runtime === true);
721
+ const loaded = await cachedDictionary(file, options.runtime === true, cache);
671
722
  if (!loaded.ok) {
672
723
  for (const message of loaded.message.split("\n")) issues.push({
673
724
  file,
@@ -777,31 +828,36 @@ async function analyzeProject(options) {
777
828
  const sourceFiles = sourceGlobs.length === 0 ? [] : scanFiles(root, sourceGlobs, {
778
829
  kind: "source",
779
830
  exclude: config.exclude,
780
- ignore: extraIgnore
831
+ ignore: extraIgnore,
832
+ gitignoreFilter: gitignore
781
833
  }).filter((f) => !dictionaryFiles.has(f));
782
834
  if (sourceFiles.length > 0) {
783
835
  const tokens = /* @__PURE__ */ new Set();
784
836
  for (const file of sourceFiles) {
785
- let text;
786
- try {
787
- text = fs.readFileSync(file, "utf-8");
788
- } catch {
789
- continue;
837
+ const stamp = cache ? stampOf(file) : void 0;
838
+ let scan = stamp ? cache.sources.get(file) : void 0;
839
+ if (!scan || scan.stamp !== stamp) {
840
+ let text;
841
+ try {
842
+ text = fs.readFileSync(file, "utf-8");
843
+ } catch {
844
+ continue;
845
+ }
846
+ scan = {
847
+ stamp: stamp ?? "",
848
+ scan: scanSource(text)
849
+ };
850
+ if (cache && stamp) cache.sources.set(file, scan);
790
851
  }
791
- for (const token of text.match(/[\w$-]+/g) ?? []) tokens.add(token);
792
- const starts = lineStarts(text);
793
- const rangeOf = (start, end) => ({
794
- start: positionAt(starts, start),
795
- end: positionAt(starts, end)
796
- });
797
- for (const ref of scanReferences(text)) {
852
+ for (const token of scan.scan.tokens) tokens.add(token);
853
+ for (const { ref, range } of scan.scan.refs) {
798
854
  if (ref.kind === "dictionary") {
799
855
  if (!known.has(ref.value)) issues.push({
800
856
  file,
801
857
  level: "error",
802
858
  code: "unknown-dictionary",
803
859
  message: `Unknown dictionary "${ref.value}"`,
804
- range: rangeOf(ref.start, ref.end),
860
+ range,
805
861
  dictionary: ref.value
806
862
  });
807
863
  continue;
@@ -815,7 +871,7 @@ async function analyzeProject(options) {
815
871
  level: "error",
816
872
  code: "unknown-path",
817
873
  message: `Unknown translation path "${ref.value}"`,
818
- range: rangeOf(ref.start, ref.end),
874
+ range,
819
875
  dictionary: name,
820
876
  path: rest
821
877
  });
@@ -849,6 +905,10 @@ async function analyzeProject(options) {
849
905
  }
850
906
  }
851
907
  }
908
+ if (cache) {
909
+ const live = /* @__PURE__ */ new Set([...files, ...sourceFiles]);
910
+ for (const map of [cache.dictionaries, cache.sources]) for (const key of map.keys()) if (key.startsWith(root) && !live.has(key)) map.delete(key);
911
+ }
852
912
  return {
853
913
  issues,
854
914
  dictionaries,
@@ -1574,7 +1634,7 @@ const CONFIG_FILE = /(^|[\\/])(dialex|i18n)\.config\.[cm]?[jt]s(on)?$/;
1574
1634
  * understands globs, so this watches the project directory and decides for itself which events
1575
1635
  * matter, using the same `include` glob as `generate`.
1576
1636
  */
1577
- function startGenerateWatcher(root, options, regenerate, delay = 100) {
1637
+ function startGenerateWatcher(root, options, regenerate, delay = 100, log = (message) => logger.info(message)) {
1578
1638
  const dictionaryFiles = () => new Set(renderGenerated(root, options).files);
1579
1639
  let known = dictionaryFiles();
1580
1640
  let outputs = /* @__PURE__ */ new Set();
@@ -1610,7 +1670,7 @@ function startGenerateWatcher(root, options, regenerate, delay = 100) {
1610
1670
  }
1611
1671
  if (!(now.size !== known.size || [...now].some((f) => !known.has(f))) && !isConfig) return;
1612
1672
  } else return;
1613
- logger.info(`[${event}] ${path.relative(root, file)} changed, regenerating...`);
1673
+ log(`[${event}] ${path.relative(root, file)} changed, regenerating...`);
1614
1674
  trigger();
1615
1675
  });
1616
1676
  return watcher;
@@ -1669,6 +1729,6 @@ async function loadStaticProject(root, configFile) {
1669
1729
  /** `home` + `["nav", "about"]` -> `home.nav.about` */
1670
1730
  const toKey = (dictionary, keyPath) => [dictionary, ...keyPath].join(".");
1671
1731
  //#endregion
1672
- export { dictionaryLocation as A, saveDictionaryFile as B, writeLock as C, scanFiles as D, createGitignoreFilter as E, listLocales as F, loadDictionaryFile as I, locationOf as L, getString as M, hasPath as N, TODO_PREFIX as O, listLeaves as P, parseDictionaryText as R, record as S, SOURCE_BUILTIN_IGNORE as T, setString as V, hashSource as _, renderGenerated as a, lockPath as b, parseStaticConfig as c, logger as d, DEFAULT_SOURCE_GLOB as f, LOCK_FILE as g, scanReferences as h, generateDictionaries as i, getLeafSource as j, copyLeaf as k, readStaticConfig as l, relativeFile as m, loadStaticProject as n, runGenerate as o, analyzeProject as p, toKey as r, DEFAULT_STATIC_CONFIG as s, loadProject as t, resolveDialexConfig as u, isStale as v, BUILTIN_IGNORE as w, readLock as x, lockFor as y, renderDictionaryFile as z };
1732
+ export { scanFiles as A, locationOf as B, lockPath as C, BUILTIN_IGNORE as D, writeLock as E, getString as F, renderDictionaryFile as H, hasPath as I, listLeaves as L, copyLeaf as M, dictionaryLocation as N, SOURCE_BUILTIN_IGNORE as O, getLeafSource as P, listLocales as R, lockFor as S, record as T, saveDictionaryFile as U, parseDictionaryText as V, setString as W, relativeFile as _, renderGenerated as a, hashSource as b, DEFAULT_STATIC_CONFIG as c, resolveDialexConfig as d, logger as f, createAnalysisCache as g, clearGitignore as h, generateDictionaries as i, TODO_PREFIX as j, createGitignoreFilter as k, parseStaticConfig as l, analyzeProject as m, loadStaticProject as n, runGenerate as o, DEFAULT_SOURCE_GLOB as p, toKey as r, startGenerateWatcher as s, loadProject as t, readStaticConfig as u, scanReferences as v, readLock as w, isStale as x, LOCK_FILE as y, loadDictionaryFile as z };
1673
1733
 
1674
- //# sourceMappingURL=project-DBVeKLa3.mjs.map
1734
+ //# sourceMappingURL=project-Dz0FbydQ.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"project-Dz0FbydQ.mjs","names":["IDENTIFIER","propertyKeyName","unwrapNode","isObjectNode","unwrapNode","propertyKeyName","isObjectNode","findProperty"],"sources":["../src/utils/dictionary-edit.ts","../src/utils/files.ts","../src/utils/icu-check.ts","../src/utils/lockfile.ts","../src/analysis.ts","../src/utils/logger.ts","../src/utils/scanner.ts","../src/utils/message-arguments.ts","../src/utils/split-locales.ts","../src/utils/static-config.ts","../src/utils/tsconfig.ts","../src/commands/generate.ts","../src/utils/project.ts"],"sourcesContent":["import fs from \"node:fs\";\n\nimport { loadFile, writeFile, generateCode, parseExpression, parseModule } from \"magicast\";\n\n/**\n * AST-level helpers for reading and editing `.content.ts` dictionary files.\n *\n * Magicast's proxy layer cannot represent every value (for example template-literal\n * functions), so these helpers work on the underlying AST nodes and use Magicast only\n * to parse and print, which preserves the rest of the file's formatting.\n *\n * Supported shapes:\n * - `export default defineDictionary(\"name\", { en: {...}, tr: {...} })`\n * - `export default defineDictionary({ name: \"name\", dictionary: { ... } })`\n * - `export default { name: \"name\", dictionary: { ... } }`\n */\n\ntype Node = { type: string; [key: string]: any };\n\nexport const TODO_PREFIX = \"[TODO] \";\n\nconst IDENTIFIER = /^[A-Za-z_$][\\w$]*$/;\n\nexport interface DictionaryFile {\n file: string;\n /** Dictionary name from `defineDictionary(\"name\", ...)` or the `name` property, if literal. */\n name?: string;\n mod: Awaited<ReturnType<typeof loadFile>>;\n /** The object whose keys are locales. */\n localesObj: Node;\n /** Whether the file ended with a newline when loaded; restored on save. */\n endsWithNewline: boolean;\n /**\n * `false` when part of the dictionary cannot be read statically (spreads, computed keys, or a\n * locale whose content is not an object literal). Leaf lists and parity checks are unreliable\n * for such files.\n */\n complete: boolean;\n}\n\n/** A zero-based line/column range, as used by editors. */\nexport interface SourceRange {\n start: { line: number; column: number };\n end: { line: number; column: number };\n}\n\nexport type LeafKind = \"string\" | \"function\" | \"other\";\n\nexport interface Leaf {\n path: string[];\n kind: LeafKind;\n /** Present when `kind` is `\"string\"`. */\n value?: string;\n}\n\nfunction unwrap(node: Node): Node {\n while (\n node &&\n (node.type === \"TSAsExpression\" ||\n node.type === \"TSSatisfiesExpression\" ||\n node.type === \"ParenthesizedExpression\")\n ) {\n node = node.expression;\n }\n return node;\n}\n\nconst isObject = (node: Node) => node?.type === \"ObjectExpression\";\n\nfunction keyName(prop: Node): string | undefined {\n const key = prop?.key;\n if (!key || prop.computed) return undefined;\n if (key.type === \"Identifier\") return key.name;\n if (key.type === \"StringLiteral\" || (key.type === \"Literal\" && typeof key.value === \"string\")) {\n return key.value;\n }\n if (key.type === \"NumericLiteral\") return String(key.value);\n return undefined;\n}\n\nconst isPropLike = (p: Node) =>\n p?.type === \"ObjectProperty\" || p?.type === \"Property\" || p?.type === \"ObjectMethod\";\n\nfunction findProp(obj: Node, key: string): Node | undefined {\n return obj.properties.find((p: Node) => isPropLike(p) && keyName(p) === key);\n}\n\nfunction stringValue(node: Node): string | undefined {\n node = unwrap(node);\n if (node?.type === \"StringLiteral\") return node.value;\n if (node?.type === \"Literal\" && typeof node.value === \"string\") return node.value;\n if (node?.type === \"TemplateLiteral\" && node.expressions.length === 0) {\n return node.quasis[0]?.value?.cooked ?? undefined;\n }\n return undefined;\n}\n\nfunction leafKind(node: Node): LeafKind {\n node = unwrap(node);\n if (stringValue(node) !== undefined) return \"string\";\n if (\n node?.type === \"ArrowFunctionExpression\" ||\n node?.type === \"FunctionExpression\" ||\n node?.type === \"ObjectMethod\"\n ) {\n return \"function\";\n }\n return \"other\";\n}\n\nfunction dictionaryProp(obj: Node): Node | undefined {\n const prop = findProp(obj, \"dictionary\");\n const value = unwrap(prop?.value);\n return isObject(value) ? value : undefined;\n}\n\nfunction locateName(declaration: Node): string | undefined {\n const decl = unwrap(declaration);\n if (decl?.type === \"CallExpression\") {\n const first = unwrap(decl.arguments[0]);\n if (isObject(first)) return stringValue(findProp(first, \"name\")?.value);\n return stringValue(first);\n }\n if (isObject(decl)) return stringValue(findProp(decl, \"name\")?.value);\n return undefined;\n}\n\nfunction locateLocalesObject(declaration: Node): Node | undefined {\n const decl = unwrap(declaration);\n if (decl?.type === \"CallExpression\") {\n const first = unwrap(decl.arguments[0]);\n const second = unwrap(decl.arguments[1]);\n if (isObject(second)) return second;\n if (isObject(first)) return dictionaryProp(first);\n return undefined;\n }\n if (isObject(decl)) return dictionaryProp(decl);\n return undefined;\n}\n\n/** Quotes a property key only when it is not a valid identifier. */\nfunction keyCode(key: string): string {\n return IDENTIFIER.test(key) ? key : JSON.stringify(key);\n}\n\n/** Builds a detached `key: <value>` property node from source text. */\nfunction makeProp(key: string, valueCode: string): Node {\n const expr: Node = parseExpression(`({ ${keyCode(key)}: ${valueCode} })`);\n return expr.$ast.properties[0];\n}\n\nfunction makeStringNode(value: string): Node {\n return makeProp(\"_\", JSON.stringify(value)).value;\n}\n\n/**\n * A dictionary is statically readable when every locale is an object literal and no object on the\n * way down uses spreads or computed keys.\n */\nfunction isStaticallyComplete(localesObj: Node): boolean {\n const walk = (obj: Node): boolean =>\n obj.properties.every((prop: Node) => {\n if (!isPropLike(prop) || keyName(prop) === undefined) return false;\n if (prop.type === \"ObjectMethod\") return true;\n const value = unwrap(prop.value);\n return isObject(value) ? walk(value) : true;\n });\n\n return localesObj.properties.every((prop: Node) => {\n if (!isPropLike(prop) || keyName(prop) === undefined || prop.type === \"ObjectMethod\")\n return false;\n const value = unwrap(prop.value);\n return isObject(value) && walk(value);\n });\n}\n\n/**\n * Parses dictionary source text (for example an unsaved editor buffer). Returns `undefined` when\n * the file does not have an editable shape; throws on syntax errors.\n */\nexport function parseDictionaryText(file: string, text: string): DictionaryFile | undefined {\n const mod = parseModule(text);\n const exported: Node = (mod.exports as any).default;\n const ast: Node = exported?.$ast;\n if (!ast) return undefined;\n const declaration = ast.declaration ?? ast;\n const localesObj = locateLocalesObject(declaration);\n return localesObj\n ? {\n file,\n mod,\n localesObj,\n name: locateName(declaration),\n endsWithNewline: text.endsWith(\"\\n\"),\n complete: isStaticallyComplete(localesObj),\n }\n : undefined;\n}\n\n/** Loads a dictionary file; returns `undefined` when its shape is not editable. */\nexport async function loadDictionaryFile(file: string): Promise<DictionaryFile | undefined> {\n return parseDictionaryText(file, fs.readFileSync(file, \"utf-8\"));\n}\n\n/** The source text with all edits applied, without writing anything. */\nexport function renderDictionaryFile(df: DictionaryFile): string {\n const code = generateCode(df.mod as any).code;\n return df.endsWithNewline && !code.endsWith(\"\\n\") ? `${code}\\n` : code;\n}\n\nexport async function saveDictionaryFile(df: DictionaryFile): Promise<void> {\n await writeFile(df.mod, df.file);\n if (df.endsWithNewline) {\n const text = fs.readFileSync(df.file, \"utf-8\");\n if (!text.endsWith(\"\\n\")) fs.writeFileSync(df.file, text + \"\\n\", \"utf-8\");\n }\n}\n\nexport function listLocales(df: DictionaryFile): string[] {\n return df.localesObj.properties\n .filter(isPropLike)\n .map(keyName)\n .filter((k: string | undefined): k is string => k !== undefined);\n}\n\nfunction localeObject(df: DictionaryFile, locale: string): Node | undefined {\n const value = unwrap(findProp(df.localesObj, locale)?.value);\n return isObject(value) ? value : undefined;\n}\n\n/** Lists every leaf (string, function, or other value) of a locale, in source order. */\nexport function listLeaves(df: DictionaryFile, locale: string): Leaf[] {\n const root = localeObject(df, locale);\n if (!root) return [];\n\n const leaves: Leaf[] = [];\n const walk = (obj: Node, prefix: string[]) => {\n for (const prop of obj.properties) {\n if (!isPropLike(prop)) continue;\n const name = keyName(prop);\n if (name === undefined) continue;\n const path = [...prefix, name];\n const value = prop.type === \"ObjectMethod\" ? prop : unwrap(prop.value);\n if (isObject(value)) {\n walk(value, path);\n } else {\n const kind = leafKind(value);\n leaves.push({ path, kind, ...(kind === \"string\" ? { value: stringValue(value) } : {}) });\n }\n }\n };\n walk(root, []);\n return leaves;\n}\n\nfunction getProp(df: DictionaryFile, locale: string, path: string[]): Node | undefined {\n let obj = localeObject(df, locale);\n for (let i = 0; obj && i < path.length; i++) {\n const prop = findProp(obj, path[i]);\n if (!prop) return undefined;\n if (i === path.length - 1) return prop;\n const next = unwrap(prop.value);\n obj = isObject(next) ? next : undefined;\n }\n return undefined;\n}\n\nexport function hasPath(df: DictionaryFile, locale: string, path: string[]): boolean {\n return getProp(df, locale, path) !== undefined;\n}\n\nexport function getString(df: DictionaryFile, locale: string, path: string[]): string | undefined {\n const prop = getProp(df, locale, path);\n return prop && prop.type !== \"ObjectMethod\" ? stringValue(prop.value) : undefined;\n}\n\nfunction ensureLocale(df: DictionaryFile, locale: string): Node {\n let obj = localeObject(df, locale);\n if (!obj) {\n const prop = makeProp(locale, \"{}\");\n df.localesObj.properties.push(prop);\n obj = prop.value as Node;\n }\n return obj;\n}\n\n/** Returns the object that should contain the last path segment, creating objects as needed. */\nfunction ensureParent(df: DictionaryFile, locale: string, path: string[]): Node | undefined {\n let obj = ensureLocale(df, locale);\n for (const segment of path.slice(0, -1)) {\n let prop = findProp(obj, segment);\n if (!prop) {\n prop = makeProp(segment, \"{}\");\n obj.properties.push(prop);\n }\n const next = unwrap(prop.value);\n if (!isObject(next)) return undefined;\n obj = next;\n }\n return obj;\n}\n\nexport type SetResult = \"created\" | \"updated\" | \"skipped\";\n\n/**\n * Sets a string value at `path`. Existing function or non-string values are left alone\n * (`\"skipped\"`) because they cannot be translated as plain text.\n */\nexport function setString(\n df: DictionaryFile,\n locale: string,\n path: string[],\n value: string,\n): SetResult {\n const parent = ensureParent(df, locale, path);\n if (!parent) return \"skipped\";\n\n const last = path[path.length - 1];\n const existing = findProp(parent, last);\n if (existing) {\n if (existing.type === \"ObjectMethod\" || leafKind(existing.value) !== \"string\") {\n return \"skipped\";\n }\n existing.value = makeStringNode(value);\n return \"updated\";\n }\n parent.properties.push(makeProp(last, JSON.stringify(value)));\n return \"created\";\n}\n\n/**\n * Copies the leaf at `path` from one locale to another. String values can be rewritten with\n * `mapString` (for example to add a `[TODO]` marker); other values are copied verbatim.\n * Returns `false` when the source has no such leaf or the target already has one.\n */\nexport function copyLeaf(\n df: DictionaryFile,\n fromLocale: string,\n toLocale: string,\n path: string[],\n mapString?: (value: string) => string,\n): boolean {\n const source = getProp(df, fromLocale, path);\n if (!source || hasPath(df, toLocale, path)) return false;\n\n const parent = ensureParent(df, toLocale, path);\n if (!parent) return false;\n\n const last = path[path.length - 1];\n const text = source.type === \"ObjectMethod\" ? undefined : stringValue(source.value);\n if (text !== undefined && mapString) {\n parent.properties.push(makeProp(last, JSON.stringify(mapString(text))));\n } else {\n const code = generateCode(source as any).code;\n const expr: Node = parseExpression(`({ ${code} })`);\n parent.properties.push(expr.$ast.properties[0]);\n }\n return true;\n}\n\n/** Leaf paths of a runtime dictionary value (plain objects recurse; everything else is a leaf). */\nexport function flattenPaths(value: unknown, prefix: string[] = []): string[][] {\n if (value && typeof value === \"object\" && !Array.isArray(value)) {\n return Object.entries(value).flatMap(([k, v]) => flattenPaths(v, [...prefix, k]));\n }\n return prefix.length > 0 ? [prefix] : [];\n}\n\nconst toRange = (loc: Node | undefined): SourceRange | undefined =>\n loc\n ? {\n start: { line: loc.start.line - 1, column: loc.start.column },\n end: { line: loc.end.line - 1, column: loc.end.column },\n }\n : undefined;\n\n/**\n * Where a locale (no `path`) or a key within it is written. The range covers the property key, so\n * it is a good place to attach a diagnostic or jump to.\n */\nexport function locationOf(\n df: DictionaryFile,\n locale: string,\n path: string[] = [],\n): SourceRange | undefined {\n const prop = path.length === 0 ? findProp(df.localesObj, locale) : getProp(df, locale, path);\n return toRange((prop?.key ?? prop)?.loc);\n}\n\n/** The source text of the dictionary object itself (the object whose keys are locales). */\nexport function dictionaryLocation(df: DictionaryFile): SourceRange | undefined {\n return toRange(df.localesObj.loc);\n}\n\n/** The source code of a leaf's value (a function's source, or a string with its quotes). */\nexport function getLeafSource(\n df: DictionaryFile,\n locale: string,\n path: string[],\n): string | undefined {\n const prop = getProp(df, locale, path);\n if (!prop) return undefined;\n return generateCode((prop.type === \"ObjectMethod\" ? prop : prop.value) as any).code;\n}\n\n// AST helpers shared with the static config reader.\nexport {\n unwrap as unwrapNode,\n isObject as isObjectNode,\n keyName as propertyKeyName,\n findProp as findProperty,\n};\nexport type { Node as AstNode };\n","import fs from \"node:fs\";\nimport path from \"node:path\";\n\nimport fg from \"fast-glob\";\nimport ignore, { type Ignore } from \"ignore\";\n\n/** Folders that never hold project dictionaries or sources, in every scanner. */\nexport const BUILTIN_IGNORE = [\n \"**/node_modules/**\",\n \"**/dist/**\",\n \"**/.next/**\",\n \"**/dialex.locales/**\",\n];\n\n/** What the source scan skips on top: other tools' output, declarations, generated and config files. */\nexport const SOURCE_BUILTIN_IGNORE = [\n ...BUILTIN_IGNORE,\n \"**/.nuxt/**\",\n \"**/.output/**\",\n \"**/.svelte-kit/**\",\n \"**/.astro/**\",\n \"**/.turbo/**\",\n \"**/coverage/**\",\n \"**/graphify-out/**\",\n \"**/*.d.ts\",\n \"**/dialex.generated.*\",\n \"**/dialex.config.*\",\n \"**/i18n.config.*\",\n];\n\ninterface GitignoreScope {\n /** Absolute directory the file's patterns are relative to. */\n dir: string;\n matcher: Ignore;\n}\n\n/** The nearest directory at or above `root` that contains `.git`, or `root` itself. */\nfunction repositoryRoot(root: string): string {\n for (let dir = root; ; dir = path.dirname(dir)) {\n if (fs.existsSync(path.join(dir, \".git\"))) return dir;\n if (path.dirname(dir) === dir) return root;\n }\n}\n\nfunction readScope(dir: string): GitignoreScope | undefined {\n try {\n const text = fs.readFileSync(path.join(dir, \".gitignore\"), \"utf-8\");\n return { dir, matcher: ignore().add(text) };\n } catch {\n return undefined;\n }\n}\n\n/**\n * A function that says whether an absolute path is ignored by Git. It reads the `.gitignore`\n * files of the project folder, of every folder above it up to the repository root (monorepo\n * packages inherit the root's rules), and of nested folders.\n */\nexport function createGitignoreFilter(root: string): (absolutePath: string) => boolean {\n const base = path.resolve(root);\n const top = repositoryRoot(base);\n\n const scopes: GitignoreScope[] = [];\n for (let dir = base; ; dir = path.dirname(dir)) {\n const scope = readScope(dir);\n if (scope) scopes.push(scope);\n if (dir === top || path.dirname(dir) === dir) break;\n }\n\n const nested = fg.sync(\"**/.gitignore\", {\n cwd: base,\n absolute: true,\n dot: true,\n ignore: [\"**/node_modules/**\", \"**/.git/**\"],\n });\n for (const file of nested) {\n const dir = path.dirname(file);\n if (dir === base) continue; // already read above\n const scope = readScope(dir);\n if (scope) scopes.push(scope);\n }\n\n if (scopes.length === 0) return () => false;\n\n return (absolutePath) => {\n for (const { dir, matcher } of scopes) {\n const relative = path.relative(dir, absolutePath);\n if (!relative || relative.startsWith(\"..\") || path.isAbsolute(relative)) continue;\n if (matcher.ignores(relative.split(path.sep).join(\"/\"))) return true;\n }\n return false;\n };\n}\n\nexport interface ScanOptions {\n /** Which built-in ignore list applies. @default \"dictionary\" */\n kind?: \"dictionary\" | \"source\";\n /** `exclude` from the config: extra globs, relative to `root`. */\n exclude?: string[];\n /** More ignore globs, relative to `root` (nested projects, for example). */\n ignore?: string[];\n /** Skip what `.gitignore` files ignore. @default true */\n gitignore?: boolean;\n /** A filter from {@link createGitignoreFilter} to reuse instead of reading `.gitignore` again. */\n gitignoreFilter?: (absolutePath: string) => boolean;\n}\n\n/** Finds files under `root`, skipping build output, configured excludes and Git-ignored paths. */\nexport function scanFiles(\n root: string,\n patterns: string | string[],\n options: ScanOptions = {},\n): string[] {\n const builtin = options.kind === \"source\" ? SOURCE_BUILTIN_IGNORE : BUILTIN_IGNORE;\n const files = fg.sync(patterns, {\n cwd: root,\n absolute: true,\n ignore: [...builtin, ...(options.exclude ?? []), ...(options.ignore ?? [])],\n });\n if (options.gitignore === false) return files;\n const ignored = options.gitignoreFilter ?? createGitignoreFilter(root);\n return files.filter((file) => !ignored(file));\n}\n","import {\n argumentSignature,\n findPlurals,\n getArguments,\n isIcuStructured,\n parseMessage,\n type IcuNode,\n} from \"dialexjs/icu\";\n\nexport interface IcuFinding {\n level: \"error\" | \"warning\";\n code: \"invalid-icu\" | \"icu-args-mismatch\" | \"icu-plural-categories\";\n locale: string;\n /** Dotted key including the dictionary name, e.g. `cart.items`. */\n key: string;\n message: string;\n}\n\n/** `locale -> dotted path within the dictionary -> string value` */\nexport type LocaleStrings = Map<string, Map<string, string>>;\n\n/** CLDR order. `resolvedOptions().pluralCategories` order differs between Node versions. */\nconst CATEGORY_ORDER = [\"zero\", \"one\", \"two\", \"few\", \"many\"];\n\nfunction requiredCategories(locale: string, ordinal: boolean): string[] {\n try {\n return new Intl.PluralRules(locale, { type: ordinal ? \"ordinal\" : \"cardinal\" })\n .resolvedOptions()\n .pluralCategories.filter((c) => c !== \"other\")\n .sort((a, b) => CATEGORY_ORDER.indexOf(a) - CATEGORY_ORDER.indexOf(b));\n } catch {\n return []; // not a valid BCP 47 tag; nothing to compare against\n }\n}\n\n/**\n * Validates ICU messages across the locales of one dictionary:\n *\n * - invalid syntax: an error for messages that clearly use ICU (plural/select/number/date/time),\n * a warning for plain `{placeholders}` that do not parse (they may not be meant as ICU);\n * - every locale must use the same arguments as the reference locale;\n * - plural options should cover the categories the locale's plural rules need.\n */\nexport function checkIcu(\n dictionary: string,\n strings: LocaleStrings,\n defaultLocale: string,\n): IcuFinding[] {\n const findings: IcuFinding[] = [];\n const parsed = new Map<string, Map<string, IcuNode[]>>();\n\n for (const [locale, entries] of strings) {\n const ok = new Map<string, IcuNode[]>();\n for (const [path, value] of entries) {\n if (!value.includes(\"{\")) continue;\n const key = `${dictionary}.${path}`;\n try {\n ok.set(path, parseMessage(value));\n } catch (error) {\n const structured = isIcuStructured(value);\n findings.push({\n level: structured ? \"error\" : \"warning\",\n code: \"invalid-icu\",\n locale,\n key,\n message: structured\n ? `Invalid ICU message \"${key}\" (${locale}): ${(error as Error).message}`\n : `\"${key}\" (${locale}) contains braces but is not valid ICU, so t() values cannot be applied: ${(error as Error).message}`,\n });\n }\n }\n parsed.set(locale, ok);\n }\n\n // Compare every locale against the reference (default locale first)\n const order = [defaultLocale, ...[...parsed.keys()].filter((l) => l !== defaultLocale)];\n const paths = new Set([...parsed.values()].flatMap((m) => [...m.keys()]));\n\n for (const path of paths) {\n const key = `${dictionary}.${path}`;\n const reference = order.find((l) => parsed.get(l)?.has(path));\n if (!reference) continue;\n const expected = argumentSignature(parsed.get(reference)!.get(path)!);\n\n for (const locale of order) {\n const nodes = parsed.get(locale)?.get(path);\n if (nodes && locale !== reference) {\n const found = argumentSignature(nodes);\n if (found !== expected) {\n findings.push({\n level: \"error\",\n code: \"icu-args-mismatch\",\n locale,\n key,\n message: `Locale \"${locale}\" uses different arguments than \"${reference}\" for \"${key}\" (expected ${expected || \"none\"}, found ${found || \"none\"})`,\n });\n }\n }\n if (!nodes) continue;\n\n for (const plural of findPlurals(nodes)) {\n const missing = requiredCategories(locale, plural.ordinal).filter(\n (c) => !(c in plural.options),\n );\n if (missing.length > 0) {\n findings.push({\n level: \"warning\",\n code: \"icu-plural-categories\",\n locale,\n key,\n message: `Locale \"${locale}\" plural \"${plural.name}\" in \"${key}\" has no ${missing.map((c) => `\"${c}\"`).join(\", \")} option (used by this language; \"other\" will be shown instead)`,\n });\n }\n }\n }\n }\n\n return findings;\n}\n\n/** Arguments of a message, or `undefined` when it does not parse. */\nexport function tryGetArguments(message: string) {\n try {\n return getArguments(parseMessage(message));\n } catch {\n return undefined;\n }\n}\n","import { createHash } from \"node:crypto\";\nimport fs from \"node:fs\";\nimport path from \"node:path\";\n\nexport const LOCK_FILE = \"dialex.lock.json\";\n\n/**\n * Records which version of the source text each translation was made from, so a later edit of the\n * source can be noticed. A translation whose source changed afterwards is *stale*.\n *\n * ```json\n * { \"version\": 1, \"sourceLocale\": \"en\", \"locales\": { \"tr\": { \"home.title\": \"a1b2c3d4\" } } }\n * ```\n *\n * The value is a short hash of the source locale's text at the time. Translations without a\n * record are untracked (for example hand-written ones) and are never reported as stale.\n */\nexport interface Lockfile {\n version: 1;\n sourceLocale?: string;\n locales: Record<string, Record<string, string>>;\n}\n\nexport const emptyLock = (sourceLocale?: string): Lockfile => ({\n version: 1,\n ...(sourceLocale ? { sourceLocale } : {}),\n locales: {},\n});\n\nexport const lockPath = (root: string) => path.join(root, LOCK_FILE);\n\n/** A short, stable fingerprint of a source string. */\nexport function hashSource(text: string): string {\n return createHash(\"sha1\").update(text).digest(\"hex\").slice(0, 8);\n}\n\n/** The lock file, or `undefined` when there is none (or it cannot be read). */\nexport function readLock(root: string): Lockfile | undefined {\n try {\n const data = JSON.parse(fs.readFileSync(lockPath(root), \"utf-8\"));\n if (data?.version !== 1 || typeof data.locales !== \"object\" || data.locales === null) {\n return undefined;\n }\n return {\n version: 1,\n ...(typeof data.sourceLocale === \"string\" ? { sourceLocale: data.sourceLocale } : {}),\n locales: data.locales,\n };\n } catch {\n return undefined;\n }\n}\n\n/** Writes the lock with sorted keys, so it produces small, stable diffs. */\nexport function writeLock(root: string, lock: Lockfile): void {\n const sorted: Lockfile = {\n version: 1,\n ...(lock.sourceLocale ? { sourceLocale: lock.sourceLocale } : {}),\n locales: Object.fromEntries(\n Object.keys(lock.locales)\n .sort()\n .map((locale) => [\n locale,\n Object.fromEntries(\n Object.entries(lock.locales[locale]).sort(([a], [b]) => a.localeCompare(b)),\n ),\n ]),\n ),\n };\n fs.writeFileSync(lockPath(root), JSON.stringify(sorted, null, 2) + \"\\n\", \"utf-8\");\n}\n\n/** Notes that `key` in `locale` was written from this source text. */\nexport function record(lock: Lockfile, locale: string, key: string, sourceText: string): void {\n (lock.locales[locale] ??= {})[key] = hashSource(sourceText);\n}\n\n/**\n * True when `key` was recorded for `locale` from different source text than `sourceText`. A key\n * with no record is not stale.\n */\nexport function isStale(lock: Lockfile, locale: string, key: string, sourceText: string): boolean {\n const recorded = lock.locales[locale]?.[key];\n return recorded !== undefined && recorded !== hashSource(sourceText);\n}\n\n/**\n * The lock to use for a run translating from `sourceLocale`. A lock written from another source\n * locale says nothing about this one, so it is replaced by a fresh one.\n */\nexport function lockFor(root: string, sourceLocale: string): { lock: Lockfile; replaced: boolean } {\n const existing = readLock(root);\n if (!existing) return { lock: emptyLock(sourceLocale), replaced: false };\n if (existing.sourceLocale && existing.sourceLocale !== sourceLocale) {\n return { lock: emptyLock(sourceLocale), replaced: true };\n }\n existing.sourceLocale = sourceLocale;\n return { lock: existing, replaced: false };\n}\n","import fs from \"node:fs\";\nimport path from \"node:path\";\nimport { pathToFileURL } from \"node:url\";\n\nimport {\n TODO_PREFIX,\n dictionaryLocation,\n flattenPaths,\n listLeaves,\n listLocales,\n loadDictionaryFile,\n locationOf,\n type DictionaryFile,\n type SourceRange,\n} from \"./utils/dictionary-edit.js\";\nimport { createGitignoreFilter, scanFiles } from \"./utils/files.js\";\nimport { checkIcu, type LocaleStrings } from \"./utils/icu-check.js\";\nimport { isStale, readLock } from \"./utils/lockfile.js\";\n\n/**\n * Project analysis shared by `dialex check` and the editor extension.\n *\n * It reads dictionaries from the syntax tree, so it never runs project code. Dictionaries that\n * cannot be read that way (spreads, computed keys, imported values) are skipped with an `info`\n * issue, unless `runtime: true` is passed, in which case they are imported and read from the\n * evaluated module (the CLI does this; editors must not).\n */\n\nexport type IssueLevel = \"error\" | \"warning\" | \"info\";\n\nexport type IssueCode =\n | \"invalid-dictionary\"\n | \"unanalyzable\"\n | \"missing-locale\"\n | \"missing-key\"\n | \"invalid-locale\"\n | \"todo-placeholder\"\n | \"stale-translation\"\n | \"invalid-icu\"\n | \"icu-args-mismatch\"\n | \"icu-plural-categories\"\n | \"unknown-dictionary\"\n | \"unknown-path\"\n | \"unused-key\"\n | \"unused-dictionary\";\n\nexport interface AnalysisIssue {\n /** Absolute path of the file the issue is in. */\n file: string;\n level: IssueLevel;\n code: IssueCode;\n message: string;\n /** Where to point, when known. Lines and columns are zero-based. */\n range?: SourceRange;\n /** The dictionary the issue is about, when it is about one. */\n dictionary?: string;\n locale?: string;\n /** Key path within the dictionary. */\n path?: string[];\n /** For `missing-key`: a locale that has the key, to copy it from. */\n sourceLocale?: string;\n}\n\nexport interface AnalysisConfig {\n defaultLocale?: string;\n locales?: string[];\n include?: string | string[];\n exclude?: string[];\n}\n\n/**\n * Remembers parsed dictionaries and scanned source files between `analyzeProject` calls, keyed by\n * modification time and size, so a long-lived caller (the editor extension) only re-reads what\n * changed. Create one with {@link createAnalysisCache}; one-shot callers do not need it.\n */\nexport interface AnalysisCache {\n dictionaries: Map<string, { stamp: string; loaded: Loaded }>;\n sources: Map<string, { stamp: string; scan: SourceScan }>;\n /** The `.gitignore` filter, reused until {@link clearGitignore} is called. */\n gitignore: Map<string, (absolutePath: string) => boolean>;\n}\n\nexport function createAnalysisCache(): AnalysisCache {\n return { dictionaries: new Map(), sources: new Map(), gitignore: new Map() };\n}\n\n/** Forget the cached `.gitignore` rules, for example after a `.gitignore` file changed. */\nexport function clearGitignore(cache: AnalysisCache): void {\n cache.gitignore.clear();\n}\n\ninterface SourceScan {\n /** Distinct word-like tokens, for the unused-key heuristic. */\n tokens: string[];\n refs: { ref: Reference; range: SourceRange }[];\n}\n\nexport interface AnalysisOptions {\n root: string;\n config: AnalysisConfig;\n /** Source globs to scan for dictionary references. Pass `[]` to skip scanning. */\n src?: string[];\n /** Import dictionaries the syntax tree cannot fully describe. Runs project code. */\n runtime?: boolean;\n /** Extra ignore globs, relative to `root`. */\n ignore?: string[];\n /** Report possibly unused keys and dictionaries. @default true */\n unused?: boolean;\n /** Report translations whose source text changed since `dialex.lock.json` recorded them. @default true */\n lock?: boolean;\n /** Reuse work between calls. Ignored when `runtime` is set, because that evaluates code. */\n cache?: AnalysisCache;\n}\n\nexport interface LeafInfo {\n kind: \"string\" | \"function\" | \"other\";\n value?: string;\n}\n\nexport interface AnalyzedDictionary {\n name: string;\n /** Absolute path. */\n file: string;\n /** Locales in source order. */\n locales: string[];\n /** `locale -> dotted path -> leaf` */\n leaves: Map<string, Map<string, LeafInfo>>;\n /** Union of dotted leaf paths across locales, in order of first appearance. */\n paths: string[];\n /** The parsed file, present when it was read statically. */\n df?: DictionaryFile;\n}\n\nexport interface AnalysisResult {\n issues: AnalysisIssue[];\n dictionaries: AnalyzedDictionary[];\n /** Absolute paths of every dictionary file that matched. */\n files: string[];\n sourceFilesScanned: number;\n}\n\nexport const DEFAULT_SOURCE_GLOB = \"**/*.{ts,tsx,js,jsx,mjs,cjs,vue,svelte,astro,mdx}\";\n\n/** `getDictionary(\"x\")`, `useDictionary(\"x\")`, `@DialexDictionary(\"x\")` */\nconst DICTIONARY_CALL =\n /\\b(?:getDictionary|useDictionary|DialexDictionary)\\(\\s*([\"'`])([^\"'`$\\n]+)\\1/dg;\n/** `t(\"dictionary.path.to.key\")` */\nconst T_CALL = /(?<![\\w$.])t\\(\\s*([\"'`])([\\w-]+(?:\\.[\\w-]+)+)\\1/dg;\n\nexport interface Reference {\n /** A dictionary name, or a full `dictionary.key.path`. */\n kind: \"dictionary\" | \"path\";\n value: string;\n /** Offsets of the string's contents (without the quotes) in the scanned text. */\n start: number;\n end: number;\n}\n\n/** Finds `getDictionary(\"x\")`-style and `t(\"x.y.z\")` references in source text. */\nexport function scanReferences(text: string): Reference[] {\n const references: Reference[] = [];\n const collect = (pattern: RegExp, kind: Reference[\"kind\"]) => {\n for (const match of text.matchAll(pattern)) {\n const [start, end] = match.indices![2] as [number, number];\n references.push({ kind, value: match[2], start, end });\n }\n };\n collect(DICTIONARY_CALL, \"dictionary\");\n collect(T_CALL, \"path\");\n return references.sort((a, b) => a.start - b.start);\n}\n\nfunction lineStarts(text: string): number[] {\n const starts = [0];\n for (let i = 0; i < text.length; i++) if (text.charCodeAt(i) === 10) starts.push(i + 1);\n return starts;\n}\n\nfunction positionAt(starts: number[], offset: number) {\n let low = 0;\n let high = starts.length - 1;\n while (low < high) {\n const mid = Math.ceil((low + high) / 2);\n if (starts[mid] <= offset) low = mid;\n else high = mid - 1;\n }\n return { line: low, column: offset - starts[low] };\n}\n\ninterface DictionaryData {\n name: string;\n locales: string[];\n leaves: Map<string, Map<string, LeafInfo>>;\n df?: DictionaryFile;\n}\n\ntype Loaded =\n | { ok: true; data: DictionaryData }\n | { ok: false; level: IssueLevel; code: IssueCode; message: string };\n\nfunction fromSyntaxTree(df: DictionaryFile): DictionaryData {\n const locales = listLocales(df);\n const leaves = new Map<string, Map<string, LeafInfo>>();\n for (const locale of locales) {\n const entries = new Map<string, LeafInfo>();\n for (const leaf of listLeaves(df, locale)) {\n entries.set(leaf.path.join(\".\"), { kind: leaf.kind, value: leaf.value });\n }\n leaves.set(locale, entries);\n }\n return { name: df.name!, locales, leaves, df };\n}\n\nasync function fromRuntime(file: string): Promise<Loaded> {\n try {\n const mod = await import(`${pathToFileURL(file).href}?t=${Date.now()}_${Math.random()}`);\n const definition = mod.default || mod;\n if (!definition || typeof definition !== \"object\" || !definition.dictionary) {\n return {\n ok: false,\n level: \"error\",\n code: \"invalid-dictionary\",\n message: \"Default export does not appear to be a valid defineDictionary output.\",\n };\n }\n\n const dictionary = definition.dictionary as Record<string, Record<string, any>>;\n const leaves = new Map<string, Map<string, LeafInfo>>();\n const invalid: string[] = [];\n\n for (const [locale, content] of Object.entries(dictionary)) {\n if (!content || typeof content !== \"object\") {\n invalid.push(locale);\n continue;\n }\n const entries = new Map<string, LeafInfo>();\n for (const leafPath of flattenPaths(content)) {\n let value: any = content;\n for (const segment of leafPath) value = value?.[segment];\n entries.set(\n leafPath.join(\".\"),\n typeof value === \"string\"\n ? { kind: \"string\", value }\n : { kind: typeof value === \"function\" ? \"function\" : \"other\" },\n );\n }\n leaves.set(locale, entries);\n }\n\n if (invalid.length > 0) {\n return {\n ok: false,\n level: \"error\",\n code: \"invalid-locale\",\n message: invalid.map((l) => `Locale \"${l}\" content is empty or invalid.`).join(\"\\n\"),\n };\n }\n\n return {\n ok: true,\n data: { name: String(definition.name ?? \"\"), locales: [...leaves.keys()], leaves },\n };\n } catch (error: any) {\n return {\n ok: false,\n level: \"error\",\n code: \"invalid-dictionary\",\n message: `Failed to import dictionary: ${error.message || String(error)}`,\n };\n }\n}\n\nasync function loadDictionaryData(file: string, runtime: boolean): Promise<Loaded> {\n let astError: Error | undefined;\n try {\n const df = await loadDictionaryFile(file);\n if (df?.complete && df.name) return { ok: true, data: fromSyntaxTree(df) };\n } catch (error) {\n astError = error as Error;\n }\n\n if (runtime) return fromRuntime(file);\n\n return astError\n ? {\n ok: false,\n level: \"error\",\n code: \"invalid-dictionary\",\n message: `Failed to parse dictionary: ${astError.message}`,\n }\n : {\n ok: false,\n level: \"info\",\n code: \"unanalyzable\",\n message:\n \"This dictionary uses spreads, computed keys, imported values, or a computed name, so it cannot be analyzed statically.\",\n };\n}\n\nfunction stampOf(file: string): string | undefined {\n try {\n const stat = fs.statSync(file);\n return `${stat.mtimeMs}:${stat.size}`;\n } catch {\n return undefined;\n }\n}\n\nasync function cachedDictionary(\n file: string,\n runtime: boolean,\n cache: AnalysisCache | undefined,\n): Promise<Loaded> {\n const stamp = cache ? stampOf(file) : undefined;\n const hit = stamp ? cache!.dictionaries.get(file) : undefined;\n if (hit && hit.stamp === stamp) return hit.loaded;\n\n const loaded = await loadDictionaryData(file, runtime);\n if (cache && stamp) cache.dictionaries.set(file, { stamp, loaded });\n return loaded;\n}\n\nfunction scanSource(text: string): SourceScan {\n const starts = lineStarts(text);\n const rangeOf = (start: number, end: number): SourceRange => ({\n start: positionAt(starts, start),\n end: positionAt(starts, end),\n });\n return {\n tokens: [...new Set(text.match(/[\\w$-]+/g) ?? [])],\n refs: scanReferences(text).map((ref) => ({ ref, range: rangeOf(ref.start, ref.end) })),\n };\n}\n\nexport async function analyzeProject(options: AnalysisOptions): Promise<AnalysisResult> {\n const { root, config } = options;\n const include = config.include || \"**/*.content.ts\";\n const configuredLocales = config.locales || [];\n const defaultLocale = config.defaultLocale || \"en\";\n const extraIgnore = options.ignore ?? [];\n\n const cache = options.runtime ? undefined : options.cache;\n let gitignore = cache?.gitignore.get(root);\n if (cache && !gitignore) {\n gitignore = createGitignoreFilter(root);\n cache.gitignore.set(root, gitignore);\n }\n\n const files = scanFiles(root, include, {\n exclude: config.exclude,\n ignore: extraIgnore,\n gitignoreFilter: gitignore,\n });\n\n const issues: AnalysisIssue[] = [];\n const dictionaries: AnalyzedDictionary[] = [];\n const lock = options.lock === false ? undefined : readLock(root);\n\n // 1. Dictionaries: parity, placeholders, ICU\n for (const file of files) {\n const loaded = await cachedDictionary(file, options.runtime === true, cache);\n if (!loaded.ok) {\n for (const message of loaded.message.split(\"\\n\")) {\n issues.push({ file, level: loaded.level, code: loaded.code, message });\n }\n continue;\n }\n\n const { data } = loaded;\n const { df } = data;\n const at = (locale?: string, keyPath?: string[]) =>\n df && locale ? locationOf(df, locale, keyPath) : undefined;\n const add = (issue: Omit<AnalysisIssue, \"file\" | \"dictionary\">) =>\n issues.push({ ...issue, file, dictionary: data.name });\n\n for (const required of configuredLocales) {\n if (!data.locales.includes(required)) {\n add({\n level: \"error\",\n code: \"missing-locale\",\n message: `Missing configured locale \"${required}\"`,\n range: df ? dictionaryLocation(df) : undefined,\n locale: required,\n });\n }\n }\n\n const paths: string[] = [];\n const seen = new Set<string>();\n for (const locale of data.locales) {\n for (const leafPath of data.leaves.get(locale)!.keys()) {\n if (!seen.has(leafPath)) {\n seen.add(leafPath);\n paths.push(leafPath);\n }\n }\n }\n\n for (const locale of data.locales) {\n const present = data.leaves.get(locale)!;\n for (const leafPath of paths) {\n if (present.has(leafPath)) continue;\n const sourceLocale = [defaultLocale, ...data.locales].find(\n (l) => l !== locale && data.leaves.get(l)?.has(leafPath),\n );\n add({\n level: \"error\",\n code: \"missing-key\",\n message: `Locale \"${locale}\" is missing key \"${leafPath}\"`,\n range: at(locale),\n locale,\n path: leafPath.split(\".\"),\n sourceLocale,\n });\n }\n }\n\n const strings: LocaleStrings = new Map();\n for (const locale of data.locales) {\n const entries = new Map<string, string>();\n strings.set(locale, entries);\n for (const [leafPath, leaf] of data.leaves.get(locale)!) {\n if (leaf.kind !== \"string\" || leaf.value === undefined) continue;\n entries.set(leafPath, leaf.value);\n if (leaf.value.startsWith(TODO_PREFIX)) {\n add({\n level: \"warning\",\n code: \"todo-placeholder\",\n message: `Locale \"${locale}\" key \"${leafPath}\" still has a ${TODO_PREFIX.trim()} placeholder`,\n range: at(locale, leafPath.split(\".\")),\n locale,\n path: leafPath.split(\".\"),\n });\n }\n }\n }\n\n // Translations made from source text that has changed since (see dialex.lock.json)\n const sourceLeaves = lock?.sourceLocale ? data.leaves.get(lock.sourceLocale) : undefined;\n if (lock && sourceLeaves) {\n for (const locale of data.locales) {\n if (locale === lock.sourceLocale) continue;\n for (const [leafPath, leaf] of data.leaves.get(locale)!) {\n if (leaf.kind !== \"string\" || leaf.value === undefined) continue;\n if (leaf.value.startsWith(TODO_PREFIX)) continue;\n const source = sourceLeaves.get(leafPath);\n if (source?.kind !== \"string\" || source.value === undefined) continue;\n if (!isStale(lock, locale, `${data.name}.${leafPath}`, source.value)) continue;\n add({\n level: \"warning\",\n code: \"stale-translation\",\n message: `Locale \"${locale}\" key \"${leafPath}\" is out of date: the \"${lock.sourceLocale}\" text changed after it was translated`,\n range: at(locale, leafPath.split(\".\")),\n locale,\n path: leafPath.split(\".\"),\n sourceLocale: lock.sourceLocale,\n });\n }\n }\n }\n\n for (const finding of checkIcu(data.name, strings, defaultLocale)) {\n const keyPath = finding.key.slice(data.name.length + 1).split(\".\");\n add({\n level: finding.level,\n code: finding.code,\n message: finding.message,\n range: at(finding.locale, keyPath),\n locale: finding.locale,\n path: keyPath,\n });\n }\n\n dictionaries.push({\n name: data.name,\n file,\n locales: data.locales,\n leaves: data.leaves,\n paths,\n df,\n });\n }\n\n // 2. Source code: references to dictionaries and keys\n const known = new Map(dictionaries.map((d) => [d.name, d]));\n const dictionaryFiles = new Set(files);\n const sourceGlobs = options.src ?? [DEFAULT_SOURCE_GLOB];\n const sourceFiles =\n sourceGlobs.length === 0\n ? []\n : scanFiles(root, sourceGlobs, {\n kind: \"source\",\n exclude: config.exclude,\n ignore: extraIgnore,\n gitignoreFilter: gitignore,\n }).filter((f) => !dictionaryFiles.has(f));\n\n if (sourceFiles.length > 0) {\n const tokens = new Set<string>();\n\n for (const file of sourceFiles) {\n const stamp = cache ? stampOf(file) : undefined;\n let scan = stamp ? cache!.sources.get(file) : undefined;\n if (!scan || scan.stamp !== stamp) {\n let text: string;\n try {\n text = fs.readFileSync(file, \"utf-8\");\n } catch {\n continue;\n }\n scan = { stamp: stamp ?? \"\", scan: scanSource(text) };\n if (cache && stamp) cache.sources.set(file, scan);\n }\n for (const token of scan.scan.tokens) tokens.add(token);\n\n for (const { ref, range } of scan.scan.refs) {\n if (ref.kind === \"dictionary\") {\n if (!known.has(ref.value)) {\n issues.push({\n file,\n level: \"error\",\n code: \"unknown-dictionary\",\n message: `Unknown dictionary \"${ref.value}\"`,\n range,\n dictionary: ref.value,\n });\n }\n continue;\n }\n\n const [name, ...rest] = ref.value.split(\".\");\n const dictionary = known.get(name);\n if (!dictionary) continue; // `t(...)` may belong to another library\n const keyPath = rest.join(\".\");\n const exists = dictionary.paths.some((p) => p === keyPath || p.startsWith(`${keyPath}.`));\n if (!exists) {\n issues.push({\n file,\n level: \"error\",\n code: \"unknown-path\",\n message: `Unknown translation path \"${ref.value}\"`,\n range,\n dictionary: name,\n path: rest,\n });\n }\n }\n }\n\n // 3. Possibly unused dictionaries and keys (heuristic: warnings only)\n if (options.unused !== false) {\n for (const dictionary of dictionaries) {\n if (!tokens.has(dictionary.name)) {\n issues.push({\n file: dictionary.file,\n level: \"warning\",\n code: \"unused-dictionary\",\n message: `Dictionary \"${dictionary.name}\" is never referenced`,\n range: dictionary.df ? dictionaryLocation(dictionary.df) : undefined,\n dictionary: dictionary.name,\n });\n continue;\n }\n for (const keyPath of dictionary.paths) {\n const last = keyPath.split(\".\").pop()!;\n if (tokens.has(last)) continue;\n const holder = dictionary.locales.find((l) => dictionary.leaves.get(l)?.has(keyPath));\n issues.push({\n file: dictionary.file,\n level: \"warning\",\n code: \"unused-key\",\n message: `Key \"${keyPath}\" is possibly unused`,\n range:\n dictionary.df && holder\n ? locationOf(dictionary.df, holder, keyPath.split(\".\"))\n : undefined,\n dictionary: dictionary.name,\n path: keyPath.split(\".\"),\n });\n }\n }\n }\n }\n\n if (cache) {\n const live = new Set([...files, ...sourceFiles]);\n for (const map of [cache.dictionaries, cache.sources] as Map<string, unknown>[]) {\n for (const key of map.keys()) if (key.startsWith(root) && !live.has(key)) map.delete(key);\n }\n }\n\n return { issues, dictionaries, files, sourceFilesScanned: sourceFiles.length };\n}\n\n/** Project root-relative path with forward slashes, for display. */\nexport function relativeFile(root: string, file: string): string {\n return path.relative(root, file);\n}\n","import pc from \"picocolors\";\n\nexport const logger = {\n info: (msg: string) => console.log(pc.blue(\"ℹ \") + msg),\n success: (msg: string) => console.log(pc.green(\"✔ \") + pc.bold(msg)),\n warn: (msg: string) => console.warn(pc.yellow(\"⚠ \") + msg),\n error: (msg: string) => console.error(pc.red(\"✖ \") + pc.bold(msg)),\n log: (msg: string) => console.log(msg),\n};\n","import fs from \"node:fs\";\nimport path from \"node:path\";\n\nimport { DEFAULT_CONFIG, type DialexConfig } from \"dialexjs\";\nimport { loadConfigSync } from \"unconfig\";\n\nexport function resolveDialexConfig(root: string, inlineConfig: DialexConfig = {}): DialexConfig {\n let loadedConfig: DialexConfig = {};\n try {\n const sources: any[] = [];\n if (inlineConfig.configFile) {\n sources.push({ files: inlineConfig.configFile });\n }\n sources.push(\n {\n files: \"dialex.config\",\n extensions: [\"ts\", \"mts\", \"cts\", \"js\", \"mjs\", \"cjs\", \"json\", \"\"],\n },\n {\n files: \"i18n.config\",\n extensions: [\"ts\", \"mts\", \"cts\", \"js\", \"mjs\", \"cjs\", \"json\", \"\"],\n },\n );\n\n const result = loadConfigSync<DialexConfig>({\n sources,\n merge: false,\n defaults: {},\n cwd: root,\n });\n if (result && result.config) {\n loadedConfig = result.config;\n }\n } catch {\n // Config fallback\n }\n\n return {\n ...DEFAULT_CONFIG,\n ...loadedConfig,\n ...inlineConfig,\n };\n}\n\n/** Every adapter entry point that has its own `DictionaryRegistry` to augment. */\nexport const REGISTRY_ADAPTERS = [\n \"react\",\n \"server\",\n \"hono\",\n \"express\",\n \"fastify\",\n \"koa\",\n \"nestjs\",\n \"elysia\",\n \"sveltekit\",\n \"astro\",\n \"vue\",\n \"web\",\n \"h3\",\n \"angular\",\n] as const;\n\n/** Dependencies that tell which `dialexjs/*` entry points a project can import. */\nconst ADAPTER_DEPENDENCIES: Record<string, string[]> = {\n react: [\"react\"],\n \"react-dom\": [\"react\"],\n next: [\"react\", \"server\"],\n hono: [\"hono\"],\n express: [\"express\"],\n fastify: [\"fastify\"],\n koa: [\"koa\"],\n \"@nestjs/core\": [\"nestjs\"],\n \"@nestjs/common\": [\"nestjs\"],\n elysia: [\"elysia\"],\n \"@sveltejs/kit\": [\"sveltekit\"],\n astro: [\"astro\"],\n vue: [\"vue\"],\n nuxt: [\"vue\", \"h3\"],\n h3: [\"h3\"],\n nitropack: [\"h3\"],\n \"@angular/core\": [\"angular\"],\n // Frameworks that hand you a standard `Request`, served by `dialexjs/web`.\n \"react-router\": [\"web\"],\n \"react-router-dom\": [\"web\"],\n \"@remix-run/react\": [\"web\"],\n \"@remix-run/node\": [\"web\"],\n \"@tanstack/react-start\": [\"web\"],\n \"@solidjs/start\": [\"web\"],\n wrangler: [\"web\"],\n};\n\n/**\n * The adapter entry points to augment for a project, read from its `package.json`. Falls back to\n * all of them when nothing is recognised, so types never silently go missing.\n */\nexport function detectAdapters(root: string): string[] {\n try {\n const pkg = JSON.parse(fs.readFileSync(path.join(root, \"package.json\"), \"utf-8\"));\n const deps = { ...pkg.dependencies, ...pkg.devDependencies, ...pkg.peerDependencies };\n const found = new Set<string>();\n for (const name of Object.keys(deps)) {\n for (const adapter of ADAPTER_DEPENDENCIES[name] ?? []) found.add(adapter);\n }\n if (found.size > 0) return REGISTRY_ADAPTERS.filter((adapter) => found.has(adapter));\n } catch {\n // no readable package.json\n }\n return [...REGISTRY_ADAPTERS];\n}\n\n/**\n * The `dialex-env.d.ts` a project should have: its path and contents, or `undefined` when there\n * are no dictionary files. Nothing is written.\n */\nexport function renderDts(\n root: string,\n files: string[],\n locales?: string[],\n messageArguments: Record<string, string> = {},\n): { path: string; content: string } | undefined {\n if (files.length === 0) return undefined;\n\n const dtsDir = fs.existsSync(path.join(root, \"src\")) ? path.join(root, \"src\") : root;\n const imports: string[] = [];\n const records: string[] = [];\n\n files.forEach((file, index) => {\n let relPath = path.relative(dtsDir, file).replace(/\\\\/g, \"/\");\n relPath = relPath.replace(/\\.ts$/, \"\");\n if (!relPath.startsWith(\".\")) {\n relPath = \"./\" + relPath;\n }\n\n imports.push(`import dict${index} from '${relPath}';`);\n records.push(\n `Record<typeof dict${index}['name'], typeof dict${index}['dictionary'][keyof typeof dict${index}['dictionary']]>`,\n );\n });\n\n const localesType =\n locales && locales.length > 0 ? locales.map((l) => `\"${l}\"`).join(\" | \") : \"string\";\n\n const registry = records.join(\",\\n \");\n const messageEntries = Object.entries(messageArguments)\n .sort(([a], [b]) => a.localeCompare(b))\n .map(([key, type]) => ` ${JSON.stringify(key)}: ${type};`)\n .join(\"\\n\");\n const adapterBlocks = detectAdapters(root)\n .map(\n (adapter) => `\ndeclare module 'dialexjs/${adapter}' {\n export interface DictionaryRegistry extends ${registry} {}\n}\n`,\n )\n .join(\"\");\n\n const dtsContent = `/* eslint-disable */\n// @ts-nocheck\n// Generated by dialex\n${imports.join(\"\\n\")}\n\ndeclare module 'dialexjs' {\n export interface Register {\n locales: ${localesType};\n }\n export interface DictionaryRegistry extends ${records.join(\",\\n \")} {}\n export interface MessageArguments {${messageEntries ? `\\n${messageEntries}\\n ` : \"\"}}\n}\n${adapterBlocks}\n`;\n\n return { path: path.join(dtsDir, \"dialex-env.d.ts\"), content: dtsContent };\n}\n\nexport function generateDts(root: string, files: string[], locales?: string[]) {\n const dts = renderDts(root, files, locales);\n if (!dts) return;\n const existing = fs.existsSync(dts.path) ? fs.readFileSync(dts.path, \"utf-8\") : \"\";\n if (existing !== dts.content) {\n fs.mkdirSync(path.dirname(dts.path), { recursive: true });\n fs.writeFileSync(dts.path, dts.content, \"utf-8\");\n }\n}\n","import { getArguments, parseMessage, type IcuArgument } from \"dialexjs/icu\";\n\nimport { listLeaves, listLocales, type DictionaryFile } from \"./dictionary-edit.js\";\n\nconst IDENTIFIER = /^[A-Za-z_$][\\w$]*$/;\n\n/**\n * The TypeScript type of one ICU argument. A name can appear more than once (in a `plural` and as\n * a plain `{name}`, say); the narrowest use wins, because that is the value the message needs.\n */\nfunction typeOfArgument(uses: IcuArgument[]): string {\n if (uses.some((u) => u.type === \"plural\" || u.type === \"selectordinal\" || u.type === \"number\")) {\n return \"number\";\n }\n if (uses.some((u) => u.type === \"date\" || u.type === \"time\")) return \"Date | number\";\n const select = uses.find((u) => u.type === \"select\");\n if (select) {\n const options = (select.selectors ?? []).filter((s) => s !== \"other\");\n return options.length > 0\n ? `${options.map((o) => JSON.stringify(o)).join(\" | \")} | (string & {})`\n : \"string\";\n }\n return \"string | number | boolean | Date\";\n}\n\n/** `{ count: number; name: string | number | boolean | Date }` for the arguments of one message. */\nexport function messageType(message: string): string | undefined {\n if (!message.includes(\"{\")) return undefined;\n let args: IcuArgument[];\n try {\n args = getArguments(parseMessage(message));\n } catch {\n return undefined; // not valid ICU; `dx check` reports it\n }\n if (args.length === 0) return undefined;\n\n const byName = new Map<string, IcuArgument[]>();\n for (const arg of args) byName.set(arg.name, [...(byName.get(arg.name) ?? []), arg]);\n const members = [...byName].map(\n ([name, uses]) =>\n `${IDENTIFIER.test(name) ? name : JSON.stringify(name)}: ${typeOfArgument(uses)}`,\n );\n return `{ ${members.join(\"; \")} }`;\n}\n\n/**\n * `dictionary.key.path` to the type of its ICU values, read from each dictionary's reference\n * locale (the default locale when the dictionary has it, otherwise its first). Other locales must\n * use the same arguments, which `dx check` verifies.\n */\nexport function messageArguments(\n dictionaries: (DictionaryFile | undefined)[],\n defaultLocale: string,\n): Record<string, string> {\n const result: Record<string, string> = {};\n for (const df of dictionaries) {\n if (!df?.name) continue;\n const locales = listLocales(df);\n const reference = locales.includes(defaultLocale) ? defaultLocale : locales[0];\n if (!reference) continue;\n for (const leaf of listLeaves(df, reference)) {\n if (leaf.kind !== \"string\" || leaf.value === undefined) continue;\n const type = messageType(leaf.value);\n if (type) result[`${df.name}.${leaf.path.join(\".\")}`] = type;\n }\n }\n return result;\n}\n","import { generateCode } from \"magicast\";\n\nimport {\n isObjectNode,\n propertyKeyName,\n unwrapNode,\n type AstNode,\n type DictionaryFile,\n} from \"./dictionary-edit.js\";\n\nexport interface LocaleSlice {\n locale: string;\n /** Source of the locale's object, ready for `export default <code>`. */\n code: string;\n}\n\nexport type SplitResult = { ok: true; slices: LocaleSlice[] } | { ok: false; reason: string };\n\nconst SKIPPED_KEYS = new Set([\n \"loc\",\n \"start\",\n \"end\",\n \"extra\",\n \"range\",\n \"comments\",\n \"leadingComments\",\n \"trailingComments\",\n \"innerComments\",\n \"tokens\",\n]);\n\n/** Every identifier name used in a node, except property names that are not variable references. */\nfunction usedNames(node: unknown, found = new Set<string>()): Set<string> {\n if (!node || typeof node !== \"object\") return found;\n if (Array.isArray(node)) {\n node.forEach((child) => usedNames(child, found));\n return found;\n }\n const ast = node as AstNode;\n if (ast.type === \"Identifier\") found.add(ast.name);\n\n for (const key of Object.keys(ast)) {\n if (SKIPPED_KEYS.has(key)) continue;\n const isPropertyName =\n key === \"key\" &&\n !ast.computed &&\n [\"ObjectProperty\", \"ObjectMethod\", \"TSPropertySignature\", \"TSMethodSignature\"].includes(\n ast.type,\n );\n const isMemberName =\n key === \"property\" &&\n !ast.computed &&\n (ast.type === \"MemberExpression\" || ast.type === \"OptionalMemberExpression\");\n if (isPropertyName || isMemberName) continue;\n usedNames(ast[key], found);\n }\n return found;\n}\n\n/** Names bound anywhere in a pattern (`const { a, b: [c] } = ...`). */\nfunction patternNames(pattern: AstNode | undefined, found: Set<string>) {\n if (!pattern) return;\n switch (pattern.type) {\n case \"Identifier\":\n found.add(pattern.name);\n break;\n case \"ObjectPattern\":\n for (const prop of pattern.properties) patternNames(prop.value ?? prop.argument, found);\n break;\n case \"ArrayPattern\":\n for (const element of pattern.elements) patternNames(element ?? undefined, found);\n break;\n case \"AssignmentPattern\":\n patternNames(pattern.left, found);\n break;\n case \"RestElement\":\n patternNames(pattern.argument, found);\n break;\n }\n}\n\n/** What the file declares or imports at the top level: a locale that uses any of it cannot move. */\nfunction topLevelNames(df: DictionaryFile): Set<string> {\n const names = new Set<string>();\n const program: AstNode = (df.mod as any).$ast;\n const statements: AstNode[] = program?.body ?? program?.program?.body ?? [];\n for (const raw of statements) {\n const statement =\n raw.type === \"ExportNamedDeclaration\" && raw.declaration ? raw.declaration : raw;\n switch (statement.type) {\n case \"ImportDeclaration\":\n for (const specifier of statement.specifiers) names.add(specifier.local.name);\n break;\n case \"VariableDeclaration\":\n for (const declarator of statement.declarations) patternNames(declarator.id, names);\n break;\n case \"FunctionDeclaration\":\n case \"ClassDeclaration\":\n case \"TSInterfaceDeclaration\":\n case \"TSTypeAliasDeclaration\":\n case \"TSEnumDeclaration\":\n if (statement.id?.name) names.add(statement.id.name);\n break;\n }\n }\n return names;\n}\n\n/**\n * Cuts a dictionary into one self-contained piece per locale, for `lazy: \"locale\"`.\n *\n * A piece moves to its own file, so it must not depend on anything else in the original file.\n * That is checked conservatively: if a locale uses any name the file imports or declares (even one\n * that is only shadowed), the whole file is left alone. A missed split costs bytes; a wrong split\n * would break the app.\n */\nexport function splitLocales(df: DictionaryFile): SplitResult {\n if (!df.complete) {\n return { ok: false, reason: \"it uses spreads, computed keys or non-literal locale values\" };\n }\n\n const bound = topLevelNames(df);\n const slices: LocaleSlice[] = [];\n\n for (const prop of df.localesObj.properties as AstNode[]) {\n const locale = propertyKeyName(prop);\n const value = unwrapNode(prop.value);\n if (locale === undefined || !isObjectNode(value)) {\n return { ok: false, reason: \"a locale is not an object literal\" };\n }\n const clash = [...usedNames(value)].find((name) => bound.has(name));\n if (clash) {\n return {\n ok: false,\n reason: `\"${locale}\" uses \"${clash}\", which is defined elsewhere in the file`,\n };\n }\n slices.push({ locale, code: generateCode(value as any).code });\n }\n\n if (slices.length === 0) return { ok: false, reason: \"it defines no locales\" };\n return { ok: true, slices };\n}\n","import fs from \"node:fs\";\nimport path from \"node:path\";\n\nimport { parseModule } from \"magicast\";\n\nimport {\n findProperty,\n isObjectNode,\n propertyKeyName,\n unwrapNode,\n type AstNode,\n} from \"./dictionary-edit.js\";\n\n/**\n * The parts of `dialex.config` that tooling needs, read **without running the file**. Editors must\n * not execute workspace code (it may be untrusted), so values are read from the syntax tree and\n * only literals are understood.\n */\nexport interface StaticConfig {\n defaultLocale: string;\n locales: string[];\n include: string | string[];\n exclude: string[];\n fallbacks: Record<string, string[]>;\n prefixDefault: boolean;\n lazy: boolean | \"locale\";\n}\n\nexport interface StaticConfigResult {\n config: StaticConfig;\n /** The file the values came from, if any. */\n file?: string;\n /** Things that could not be read statically, for example `locales: getLocales()`. */\n notes: string[];\n}\n\nconst CONFIG_NAMES = [\"dialex.config\", \"i18n.config\"];\nconst EXTENSIONS = [\"ts\", \"mts\", \"cts\", \"js\", \"mjs\", \"cjs\", \"json\"];\n\nexport const DEFAULT_STATIC_CONFIG: StaticConfig = {\n defaultLocale: \"en\",\n locales: [],\n include: \"**/*.content.ts\",\n exclude: [],\n fallbacks: {},\n prefixDefault: true,\n lazy: false,\n};\n\nconst NOT_LITERAL = Symbol(\"not literal\");\n\nfunction literal(node: AstNode | undefined): unknown {\n node = unwrapNode(node as AstNode);\n switch (node?.type) {\n case \"StringLiteral\":\n case \"NumericLiteral\":\n case \"BooleanLiteral\":\n return node.value;\n case \"Literal\":\n return node.value;\n case \"TemplateLiteral\":\n return node.expressions.length === 0 ? (node.quasis[0]?.value?.cooked ?? \"\") : NOT_LITERAL;\n case \"ArrayExpression\": {\n const items = node.elements.map((e: AstNode) => literal(e));\n return items.includes(NOT_LITERAL) ? NOT_LITERAL : items;\n }\n case \"ObjectExpression\": {\n const result: Record<string, unknown> = {};\n for (const prop of node.properties) {\n const key = propertyKeyName(prop);\n const value = key === undefined ? NOT_LITERAL : literal(prop.value);\n if (value === NOT_LITERAL) return NOT_LITERAL;\n result[key as string] = value;\n }\n return result;\n }\n default:\n return NOT_LITERAL;\n }\n}\n\n/** The object literal passed to `defineConfig({...})`, or exported directly. */\nfunction findConfigObject(declaration: AstNode): AstNode | undefined {\n const node = unwrapNode(declaration);\n if (node?.type === \"CallExpression\") return findConfigObject(node.arguments[0]);\n return isObjectNode(node) ? node : undefined;\n}\n\nconst isStringArray = (value: unknown): value is string[] =>\n Array.isArray(value) && value.every((v) => typeof v === \"string\");\n\nfunction apply(object: Record<string, unknown>, config: StaticConfig, notes: string[]) {\n const accept = <K extends keyof StaticConfig>(\n key: K,\n valid: (value: unknown) => boolean,\n expected: string,\n ) => {\n if (!(key in object)) return;\n const value = object[key];\n if (valid(value)) (config as any)[key] = value;\n else notes.push(`\"${key}\" could not be read statically (expected ${expected}).`);\n };\n\n accept(\"defaultLocale\", (v) => typeof v === \"string\" && v !== \"\", \"a string literal\");\n accept(\"locales\", isStringArray, \"an array of string literals\");\n accept(\n \"include\",\n (v) => typeof v === \"string\" || isStringArray(v),\n \"a string or array of strings\",\n );\n accept(\"exclude\", isStringArray, \"an array of string literals\");\n accept(\n \"fallbacks\",\n (v) =>\n typeof v === \"object\" && v !== null && Object.values(v).every((list) => isStringArray(list)),\n \"an object of string arrays\",\n );\n accept(\"prefixDefault\", (v) => typeof v === \"boolean\", \"true or false\");\n accept(\"lazy\", (v) => typeof v === \"boolean\" || v === \"locale\", 'true, false or \"locale\"');\n}\n\n/** Reads a config file's source text. Exposed for tests and for unsaved buffers. */\nexport function parseStaticConfig(text: string, file = \"dialex.config.ts\"): StaticConfigResult {\n const notes: string[] = [];\n const config: StaticConfig = { ...DEFAULT_STATIC_CONFIG };\n\n if (file.endsWith(\".json\")) {\n try {\n const data = JSON.parse(text);\n if (data && typeof data === \"object\") apply(data, config, notes);\n } catch (error) {\n notes.push(`Could not parse ${path.basename(file)}: ${(error as Error).message}`);\n }\n return { config, file, notes };\n }\n\n try {\n const exported = (parseModule(text).exports as any).default;\n const object = findConfigObject(exported?.$ast?.declaration ?? exported?.$ast);\n if (!object) {\n notes.push(`${path.basename(file)} does not export a config object literal.`);\n } else {\n const values: Record<string, unknown> = {};\n for (const key of [\n \"defaultLocale\",\n \"locales\",\n \"include\",\n \"exclude\",\n \"fallbacks\",\n \"prefixDefault\",\n \"lazy\",\n ]) {\n const prop = findProperty(object, key);\n if (!prop) continue;\n const value = literal(prop.value);\n if (value === NOT_LITERAL)\n notes.push(`\"${key}\" could not be read statically (not a literal).`);\n else values[key] = value;\n }\n apply(values, config, notes);\n }\n } catch (error) {\n notes.push(`Could not parse ${path.basename(file)}: ${(error as Error).message}`);\n }\n\n return { config, file, notes };\n}\n\n/** Reads `dialex.config.*` (or `i18n.config.*`) from `root`, or from `configFile` if given. */\nexport function readStaticConfig(root: string, configFile?: string): StaticConfigResult {\n const candidates = configFile\n ? [path.resolve(root, configFile)]\n : CONFIG_NAMES.flatMap((name) => EXTENSIONS.map((ext) => path.join(root, `${name}.${ext}`)));\n\n for (const file of candidates) {\n if (fs.existsSync(file)) return parseStaticConfig(fs.readFileSync(file, \"utf-8\"), file);\n }\n return { config: { ...DEFAULT_STATIC_CONFIG }, notes: [] };\n}\n","import fs from \"node:fs\";\nimport path from \"node:path\";\n\n/** Parses tsconfig-style JSON: comments and trailing commas are allowed. */\nexport function parseJsonc(text: string): any {\n let out = \"\";\n let inString = false;\n for (let i = 0; i < text.length; i++) {\n const c = text[i];\n if (inString) {\n out += c;\n if (c === \"\\\\\") out += text[++i] ?? \"\";\n else if (c === '\"') inString = false;\n } else if (c === '\"') {\n inString = true;\n out += c;\n } else if (c === \"/\" && text[i + 1] === \"/\") {\n while (i < text.length && text[i] !== \"\\n\") i++;\n out += \"\\n\";\n } else if (c === \"/\" && text[i + 1] === \"*\") {\n i += 2;\n while (i < text.length && !(text[i] === \"*\" && text[i + 1] === \"/\")) i++;\n i++;\n } else {\n out += c;\n }\n }\n return JSON.parse(out.replace(/,(\\s*[}\\]])/g, \"$1\"));\n}\n\ninterface Resolved {\n moduleResolution?: string;\n include?: string[];\n references: string[];\n}\n\nfunction configFile(from: string): string | undefined {\n if (fs.existsSync(from) && fs.statSync(from).isFile()) return from;\n for (const candidate of [`${from}.json`, path.join(from, \"tsconfig.json\")]) {\n if (fs.existsSync(candidate) && fs.statSync(candidate).isFile()) return candidate;\n }\n return undefined;\n}\n\n/** `moduleResolution` and `include` of a tsconfig, following relative `extends`. */\nfunction read(file: string, depth = 0): Resolved {\n const result: Resolved = { references: [] };\n let json: any;\n try {\n json = parseJsonc(fs.readFileSync(file, \"utf-8\"));\n } catch {\n return result;\n }\n const dir = path.dirname(file);\n\n const parent =\n typeof json.extends === \"string\" && json.extends.startsWith(\".\") && depth < 5\n ? configFile(path.resolve(dir, json.extends))\n : undefined;\n if (parent) Object.assign(result, read(parent, depth + 1));\n\n const options = json.compilerOptions ?? {};\n const module = typeof options.module === \"string\" ? options.module.toLowerCase() : undefined;\n const resolution =\n typeof options.moduleResolution === \"string\"\n ? options.moduleResolution.toLowerCase()\n : module === \"node16\" || module === \"nodenext\"\n ? module\n : undefined;\n if (resolution) result.moduleResolution = resolution;\n if (Array.isArray(json.include)) result.include = json.include;\n result.references = (json.references ?? [])\n .map((ref: any) =>\n typeof ref?.path === \"string\" ? configFile(path.resolve(dir, ref.path)) : undefined,\n )\n .filter(Boolean) as string[];\n return result;\n}\n\n/**\n * The extension for relative imports in generated files. TypeScript's `node16`/`nodenext` need\n * `./x.js`; bundlers (webpack, Vite) resolve extensionless imports, and webpack cannot map `.js`\n * to a `.ts` file. Without any tsconfig it is plain Node ESM, which needs the extension.\n */\nexport function relativeImportExtension(root: string): \".js\" | \"\" {\n const file = configFile(path.join(root, \"tsconfig.json\"));\n if (!file) return \".js\";\n\n let resolved = read(file);\n if (!resolved.moduleResolution && resolved.references.length > 0) {\n // A \"solution\" tsconfig: use the referenced project that covers src/.\n const projects = resolved.references.map((ref) => read(ref));\n resolved =\n projects.find((p) => p.include?.some((entry) => /^(\\.\\/)?src(\\/|$)/.test(entry))) ??\n projects[0] ??\n resolved;\n }\n const resolution = resolved.moduleResolution;\n return resolution === \"node16\" || resolution === \"nodenext\" ? \".js\" : \"\";\n}\n","import fs from \"node:fs\";\nimport path from \"node:path\";\n\nimport chokidar from \"chokidar\";\nimport { DEFAULT_CONFIG } from \"dialexjs\";\n\nimport { listLocales, parseDictionaryText } from \"../utils/dictionary-edit.js\";\nimport { createGitignoreFilter, scanFiles } from \"../utils/files.js\";\nimport { logger } from \"../utils/logger.js\";\nimport { messageArguments } from \"../utils/message-arguments.js\";\nimport { resolveDialexConfig, renderDts } from \"../utils/scanner.js\";\nimport { splitLocales } from \"../utils/split-locales.js\";\nimport { readStaticConfig } from \"../utils/static-config.js\";\nimport { relativeImportExtension } from \"../utils/tsconfig.js\";\n\nexport interface GenerateOptions {\n cwd?: string;\n watch?: boolean;\n output?: string;\n config?: string;\n json?: boolean;\n /**\n * Read `dialex.config.*` from its syntax tree instead of running it, so no project code\n * executes (used by the editor extension). Settings that are not literals fall back to defaults.\n */\n static?: boolean;\n}\n\nexport interface RenderedGenerate {\n /** Absolute paths of the dictionary files, sorted. */\n files: string[];\n /** Where `dialex.generated.ts` goes, and what it should contain. */\n outputPath: string;\n content: string;\n /** Where `dialex-env.d.ts` goes, and what it should contain (absent without dictionaries). */\n dtsPath: string;\n dtsContent?: string;\n /** The config file that was read, if there is one. Without it every default applies. */\n configFile?: string;\n /** Per-locale modules for `lazy: \"locale\"`, written next to the generated file. */\n extraFiles: { path: string; content: string }[];\n /** Things worth telling the user, such as a dictionary that could not be split by locale. */\n notes: string[];\n}\n\n/** The folder, next to `dialex.generated.ts`, that holds the per-locale modules. */\nexport const LOCALES_DIR = \"dialex.locales\";\nconst safeName = (text: string) => text.replace(/[^A-Za-z0-9._-]/g, \"_\");\n\n/**\n * Works out `dialex.generated.ts` and `dialex-env.d.ts` for a project without writing anything,\n * so `check` can tell whether they are up to date.\n *\n * Settings come from `dialex.config.*` and fall back to {@link DEFAULT_CONFIG}; `locales` falls\n * back to the locales the dictionaries define.\n */\nexport function renderGenerated(root: string, options: GenerateOptions = {}): RenderedGenerate {\n const inlineConfig = options.config ? { configFile: options.config } : {};\n const staticRead = readStaticConfig(root, options.config);\n const config = options.static ? staticRead.config : resolveDialexConfig(root, inlineConfig);\n const include = config.include || DEFAULT_CONFIG.include;\n\n const found = scanFiles(root, include, { exclude: config.exclude }).sort();\n\n const srcDir = fs.existsSync(path.join(root, \"src\")) ? path.join(root, \"src\") : root;\n const outputPath = options.output\n ? path.resolve(root, options.output)\n : path.join(srcDir, \"dialex.generated.ts\");\n const outputDir = path.dirname(outputPath);\n // A broad `include` (like `src/**/*.ts`) would otherwise match the files generated here\n const files = found.filter(\n (file) =>\n file !== outputPath &&\n !file.endsWith(\".d.ts\") &&\n path.basename(file) !== \"dialex.generated.ts\",\n );\n\n // Read each dictionary's name and locales from its syntax tree; project code is never run.\n const parsed = files.map((file) => parseDictionaryText(file, fs.readFileSync(file, \"utf-8\")));\n const inferred: string[] = [];\n for (const df of parsed) {\n if (df)\n for (const locale of listLocales(df)) if (!inferred.includes(locale)) inferred.push(locale);\n }\n const locales = config.locales?.length ? config.locales : inferred;\n\n const clientConfig = {\n defaultLocale: config.defaultLocale || DEFAULT_CONFIG.defaultLocale,\n locales,\n fallbacks: config.fallbacks ?? DEFAULT_CONFIG.fallbacks,\n prefixDefault: config.prefixDefault ?? DEFAULT_CONFIG.prefixDefault,\n lazy: config.lazy ?? DEFAULT_CONFIG.lazy,\n };\n\n const extension = relativeImportExtension(root);\n const importPath = (file: string) => {\n let rel = path.relative(outputDir, file).replace(/\\\\/g, \"/\").replace(/\\.ts$/, extension);\n if (!rel.startsWith(\".\")) rel = \"./\" + rel;\n return rel;\n };\n\n const header = `// Auto-generated by dialex CLI. Do not edit directly.\n/* eslint-disable */\n// @ts-nocheck`;\n // \"locale\" must stay a literal type, or `<DialexProvider {...dialex}>` would not type-check\n const configJson = JSON.stringify(clientConfig, null, 2).replace(\n '\"lazy\": \"locale\"',\n '\"lazy\": \"locale\" as const',\n );\n const configExport = `export const config = ${configJson};\n\n${\n locales.length > 0\n ? `export const locales = ${JSON.stringify(locales)} as const;\\nexport type Locale = (typeof locales)[number];`\n : \"export const locales: readonly string[] = [];\\nexport type Locale = string;\"\n}`;\n\n const extraFiles: { path: string; content: string }[] = [];\n const notes: string[] = [];\n const takenNames = new Set<string>();\n\n let content: string;\n if (clientConfig.lazy) {\n // Only dynamic imports, so bundlers can split each dictionary (or, with \"locale\", each\n // locale of it) into its own chunk.\n const loaders = files.map((file, i) => {\n const df = parsed[i];\n const name = df?.name;\n if (!name || !df) {\n throw new Error(\n `Cannot determine the dictionary name of ${path.relative(root, file)} for lazy loading. ` +\n 'Use defineDictionary(\"name\", ...) or a literal `name` property.',\n );\n }\n const whole = ` ${JSON.stringify(name)}: () => import(\"${importPath(file)}\"),`;\n if (clientConfig.lazy !== \"locale\") return whole;\n\n const split = splitLocales(df);\n if (!split.ok) {\n notes.push(\n `${path.relative(root, file)} is loaded whole, not per locale: ${split.reason}.`,\n );\n return whole;\n }\n let base = safeName(name);\n for (let n = 2; takenNames.has(base); n++) base = `${safeName(name)}-${n}`;\n takenNames.add(base);\n\n const entries = split.slices.map((slice) => {\n const target = path.join(outputDir, LOCALES_DIR, `${base}.${safeName(slice.locale)}.ts`);\n extraFiles.push({\n path: target,\n content: `${header}\\nexport default ${slice.code};\\n`,\n });\n return ` ${JSON.stringify(slice.locale)}: () => import(\"${importPath(target)}\"),`;\n });\n return ` ${JSON.stringify(name)}: {\\n${entries.join(\"\\n\")}\\n },`;\n });\n content = `${header}\n\nexport const dictionaries = [];\n\nexport const dictionaryMap = {};\n\nexport const loaders = {\n${loaders.join(\"\\n\")}\n};\n\n${configExport}\n\nexport const dialex = { dictionaries, config, loaders };\n\nexport default dictionaries;\n`;\n } else {\n const ids = files.map((_, i) => `dict_${i}`);\n const dictList = ids.length <= 1 ? `[${ids.join(\", \")}]` : `[\\n ${ids.join(\",\\n \")}\\n]`;\n content = `${header}\n${files.map((file, i) => `import ${ids[i]} from \"${importPath(file)}\";`).join(\"\\n\")}\n\nexport const dictionaries = ${dictList};\n\nexport const dictionaryMap = {\n${ids.map((id) => ` [${id}.name]: ${id}.dictionary,`).join(\"\\n\")}\n};\n\n${configExport}\n\nexport const dialex = { dictionaries, config };\n\nexport default dictionaries;\n`;\n }\n\n const dts = renderDts(root, files, locales, messageArguments(parsed, clientConfig.defaultLocale));\n return {\n files,\n outputPath,\n content,\n dtsPath: dts?.path ?? path.join(srcDir, \"dialex-env.d.ts\"),\n dtsContent: dts?.content,\n configFile: staticRead.file,\n extraFiles,\n notes,\n };\n}\n\nfunction writeIfChanged(file: string, content: string) {\n const existing = fs.existsSync(file) ? fs.readFileSync(file, \"utf-8\") : \"\";\n if (existing === content) return;\n fs.mkdirSync(path.dirname(file), { recursive: true });\n fs.writeFileSync(file, content, \"utf-8\");\n}\n\nexport function generateDictionaries(\n root: string,\n options: GenerateOptions = {},\n): {\n files: string[];\n outputPath: string;\n dtsPath: string;\n configFile?: string;\n notes: string[];\n} {\n const rendered = renderGenerated(root, options);\n if (rendered.dtsContent !== undefined) writeIfChanged(rendered.dtsPath, rendered.dtsContent);\n writeIfChanged(rendered.outputPath, rendered.content);\n\n // Per-locale modules, and no leftovers from dictionaries or locales that are gone\n const dir = path.join(path.dirname(rendered.outputPath), LOCALES_DIR);\n const wanted = new Set(rendered.extraFiles.map((f) => f.path));\n for (const file of rendered.extraFiles) writeIfChanged(file.path, file.content);\n if (fs.existsSync(dir)) {\n for (const entry of fs.readdirSync(dir)) {\n const full = path.join(dir, entry);\n if (entry.endsWith(\".ts\") && !wanted.has(full)) fs.rmSync(full);\n }\n if (fs.readdirSync(dir).length === 0) fs.rmdirSync(dir);\n }\n\n return {\n files: rendered.files,\n outputPath: rendered.outputPath,\n dtsPath: rendered.dtsPath,\n configFile: rendered.configFile,\n notes: rendered.notes,\n };\n}\n\nexport async function runGenerate(options: GenerateOptions = {}) {\n const root = options.cwd || process.cwd();\n const quiet = options.json === true;\n\n const doGenerate = () => {\n try {\n const { files, outputPath, dtsPath, configFile, notes } = generateDictionaries(root, options);\n if (quiet) {\n console.log(\n JSON.stringify(\n {\n success: true,\n files: files.map((f) => path.relative(root, f)),\n outputPath: path.relative(root, outputPath),\n dtsPath: path.relative(root, dtsPath),\n notes,\n },\n null,\n 2,\n ),\n );\n } else {\n if (!configFile) {\n logger.info(\"No dialex.config.* found, using defaults (run `dialex init` to add one).\");\n }\n logger.success(\n `Generated dictionaries for ${files.length} file${files.length === 1 ? \"\" : \"s\"}:`,\n );\n logger.info(`→ ${path.relative(root, outputPath)}`);\n logger.info(`→ ${path.relative(root, dtsPath)}`);\n for (const note of notes) logger.info(note);\n }\n return true;\n } catch (err: any) {\n if (quiet) {\n console.log(\n JSON.stringify(\n {\n success: false,\n error: err.message || String(err),\n },\n null,\n 2,\n ),\n );\n } else {\n logger.error(`Generation failed: ${err.message || String(err)}`);\n }\n return false;\n }\n };\n\n const ok = doGenerate();\n if (!ok && !options.watch) {\n process.exit(1);\n }\n\n if (options.watch) {\n logger.info(\"Watching for dictionary changes (-w, --watch)...\");\n startGenerateWatcher(root, options, doGenerate);\n }\n}\n\nconst WATCH_IGNORED =\n /(^|[\\\\/])(node_modules|dist|\\.next|\\.nuxt|\\.output|\\.turbo|\\.git|dialex\\.locales)([\\\\/]|$)/;\nconst CONFIG_FILE = /(^|[\\\\/])(dialex|i18n)\\.config\\.[cm]?[jt]s(on)?$/;\n\n/**\n * Regenerates when a dictionary or config file is added, edited or removed. chokidar 4+ no longer\n * understands globs, so this watches the project directory and decides for itself which events\n * matter, using the same `include` glob as `generate`.\n */\nexport function startGenerateWatcher(\n root: string,\n options: GenerateOptions,\n regenerate: () => void,\n delay = 100,\n /** Where to report what triggered a regeneration. Defaults to the CLI logger (stdout). */\n log: (message: string) => void = (message) => logger.info(message),\n) {\n const dictionaryFiles = () => new Set(renderGenerated(root, options).files);\n let known = dictionaryFiles();\n let outputs = new Set<string>();\n let timer: ReturnType<typeof setTimeout> | undefined;\n\n const trigger = () => {\n if (timer) clearTimeout(timer);\n timer = setTimeout(() => {\n regenerate();\n try {\n known = dictionaryFiles();\n const rendered = renderGenerated(root, options);\n outputs = new Set([rendered.outputPath, rendered.dtsPath]);\n } catch {\n // keep the previous list; the next event tries again\n }\n }, delay);\n };\n\n const gitIgnored = createGitignoreFilter(root);\n const watcher = chokidar.watch(root, {\n ignoreInitial: true,\n ignored: (file: string) => WATCH_IGNORED.test(file) || gitIgnored(path.resolve(root, file)),\n });\n\n watcher.on(\"all\", (event, filePath) => {\n const file = path.resolve(root, filePath);\n if (outputs.has(file)) return; // our own output\n const isConfig = CONFIG_FILE.test(file);\n\n if (event === \"change\") {\n if (!known.has(file) && !isConfig) return;\n } else if (event === \"add\" || event === \"unlink\") {\n let now: Set<string>;\n try {\n now = dictionaryFiles();\n } catch {\n return;\n }\n const changed = now.size !== known.size || [...now].some((f) => !known.has(f));\n if (!changed && !isConfig) return;\n } else {\n return;\n }\n\n log(`[${event}] ${path.relative(root, file)} changed, regenerating...`);\n trigger();\n });\n\n return watcher;\n}\n","import path from \"node:path\";\n\nimport type { DialexConfig } from \"dialexjs\";\n\nimport { loadDictionaryFile, type DictionaryFile } from \"./dictionary-edit.js\";\nimport { scanFiles } from \"./files.js\";\nimport { resolveDialexConfig } from \"./scanner.js\";\nimport { readStaticConfig } from \"./static-config.js\";\n\nexport interface ProjectDictionary {\n /** Path relative to the project root. */\n rel: string;\n name: string;\n df: DictionaryFile;\n}\n\nexport interface Project {\n root: string;\n config: DialexConfig;\n dictionaries: ProjectDictionary[];\n /** Dictionary files that could not be parsed into an editable shape. */\n unsupported: string[];\n /** Config values that could not be read statically (static loading only). */\n notes: string[];\n}\n\nasync function loadDictionaries(root: string, config: DialexConfig) {\n const include = config.include || \"**/*.content.ts\";\n const files = scanFiles(root, include, { exclude: config.exclude });\n\n const dictionaries: ProjectDictionary[] = [];\n const unsupported: string[] = [];\n\n for (const file of files) {\n const rel = path.relative(root, file);\n try {\n const df = await loadDictionaryFile(file);\n if (!df || !df.name) unsupported.push(rel);\n else dictionaries.push({ rel, name: df.name, df });\n } catch {\n unsupported.push(rel); // syntax error: reported by the analysis, nothing to edit here\n }\n }\n\n return { dictionaries, unsupported };\n}\n\n/**\n * Resolves the config (running `dialex.config.*` through the loader, which executes it) and loads\n * every dictionary file for AST-level reading and editing.\n */\nexport async function loadProject(root: string, configFile?: string): Promise<Project> {\n const config = resolveDialexConfig(root, configFile ? { configFile } : {});\n return { root, config, notes: [], ...(await loadDictionaries(root, config)) };\n}\n\n/**\n * Like `loadProject`, but reads the config from the syntax tree without executing it. Use this in\n * editors and anywhere project code must not run.\n */\nexport async function loadStaticProject(root: string, configFile?: string): Promise<Project> {\n const { config, notes } = readStaticConfig(root, configFile);\n return { root, config, notes, ...(await loadDictionaries(root, config)) };\n}\n\n/** `home` + `[\"nav\", \"about\"]` -> `home.nav.about` */\nexport const toKey = (dictionary: string, keyPath: string[]) => [dictionary, ...keyPath].join(\".\");\n"],"mappings":";;;;;;;;;;;;;AAmBA,MAAa,cAAc;AAE3B,MAAMA,eAAa;AAkCnB,SAAS,OAAO,MAAkB;CAChC,OACE,SACC,KAAK,SAAS,oBACb,KAAK,SAAS,2BACd,KAAK,SAAS,4BAEhB,OAAO,KAAK;CAEd,OAAO;AACT;AAEA,MAAM,YAAY,SAAe,MAAM,SAAS;AAEhD,SAAS,QAAQ,MAAgC;CAC/C,MAAM,MAAM,MAAM;CAClB,IAAI,CAAC,OAAO,KAAK,UAAU,OAAO,KAAA;CAClC,IAAI,IAAI,SAAS,cAAc,OAAO,IAAI;CAC1C,IAAI,IAAI,SAAS,mBAAoB,IAAI,SAAS,aAAa,OAAO,IAAI,UAAU,UAClF,OAAO,IAAI;CAEb,IAAI,IAAI,SAAS,kBAAkB,OAAO,OAAO,IAAI,KAAK;AAE5D;AAEA,MAAM,cAAc,MAClB,GAAG,SAAS,oBAAoB,GAAG,SAAS,cAAc,GAAG,SAAS;AAExE,SAAS,SAAS,KAAW,KAA+B;CAC1D,OAAO,IAAI,WAAW,MAAM,MAAY,WAAW,CAAC,KAAK,QAAQ,CAAC,MAAM,GAAG;AAC7E;AAEA,SAAS,YAAY,MAAgC;CACnD,OAAO,OAAO,IAAI;CAClB,IAAI,MAAM,SAAS,iBAAiB,OAAO,KAAK;CAChD,IAAI,MAAM,SAAS,aAAa,OAAO,KAAK,UAAU,UAAU,OAAO,KAAK;CAC5E,IAAI,MAAM,SAAS,qBAAqB,KAAK,YAAY,WAAW,GAClE,OAAO,KAAK,OAAO,EAAE,EAAE,OAAO,UAAU,KAAA;AAG5C;AAEA,SAAS,SAAS,MAAsB;CACtC,OAAO,OAAO,IAAI;CAClB,IAAI,YAAY,IAAI,MAAM,KAAA,GAAW,OAAO;CAC5C,IACE,MAAM,SAAS,6BACf,MAAM,SAAS,wBACf,MAAM,SAAS,gBAEf,OAAO;CAET,OAAO;AACT;AAEA,SAAS,eAAe,KAA6B;CAEnD,MAAM,QAAQ,OADD,SAAS,KAAK,YACH,CAAC,EAAE,KAAK;CAChC,OAAO,SAAS,KAAK,IAAI,QAAQ,KAAA;AACnC;AAEA,SAAS,WAAW,aAAuC;CACzD,MAAM,OAAO,OAAO,WAAW;CAC/B,IAAI,MAAM,SAAS,kBAAkB;EACnC,MAAM,QAAQ,OAAO,KAAK,UAAU,EAAE;EACtC,IAAI,SAAS,KAAK,GAAG,OAAO,YAAY,SAAS,OAAO,MAAM,CAAC,EAAE,KAAK;EACtE,OAAO,YAAY,KAAK;CAC1B;CACA,IAAI,SAAS,IAAI,GAAG,OAAO,YAAY,SAAS,MAAM,MAAM,CAAC,EAAE,KAAK;AAEtE;AAEA,SAAS,oBAAoB,aAAqC;CAChE,MAAM,OAAO,OAAO,WAAW;CAC/B,IAAI,MAAM,SAAS,kBAAkB;EACnC,MAAM,QAAQ,OAAO,KAAK,UAAU,EAAE;EACtC,MAAM,SAAS,OAAO,KAAK,UAAU,EAAE;EACvC,IAAI,SAAS,MAAM,GAAG,OAAO;EAC7B,IAAI,SAAS,KAAK,GAAG,OAAO,eAAe,KAAK;EAChD;CACF;CACA,IAAI,SAAS,IAAI,GAAG,OAAO,eAAe,IAAI;AAEhD;;AAGA,SAAS,QAAQ,KAAqB;CACpC,OAAOA,aAAW,KAAK,GAAG,IAAI,MAAM,KAAK,UAAU,GAAG;AACxD;;AAGA,SAAS,SAAS,KAAa,WAAyB;CAEtD,OADmB,gBAAgB,MAAM,QAAQ,GAAG,EAAE,IAAI,UAAU,IAC1D,CAAC,CAAC,KAAK,WAAW;AAC9B;AAEA,SAAS,eAAe,OAAqB;CAC3C,OAAO,SAAS,KAAK,KAAK,UAAU,KAAK,CAAC,CAAC,CAAC;AAC9C;;;;;AAMA,SAAS,qBAAqB,YAA2B;CACvD,MAAM,QAAQ,QACZ,IAAI,WAAW,OAAO,SAAe;EACnC,IAAI,CAAC,WAAW,IAAI,KAAK,QAAQ,IAAI,MAAM,KAAA,GAAW,OAAO;EAC7D,IAAI,KAAK,SAAS,gBAAgB,OAAO;EACzC,MAAM,QAAQ,OAAO,KAAK,KAAK;EAC/B,OAAO,SAAS,KAAK,IAAI,KAAK,KAAK,IAAI;CACzC,CAAC;CAEH,OAAO,WAAW,WAAW,OAAO,SAAe;EACjD,IAAI,CAAC,WAAW,IAAI,KAAK,QAAQ,IAAI,MAAM,KAAA,KAAa,KAAK,SAAS,gBACpE,OAAO;EACT,MAAM,QAAQ,OAAO,KAAK,KAAK;EAC/B,OAAO,SAAS,KAAK,KAAK,KAAK,KAAK;CACtC,CAAC;AACH;;;;;AAMA,SAAgB,oBAAoB,MAAc,MAA0C;CAC1F,MAAM,MAAM,YAAY,IAAI;CAE5B,MAAM,MADkB,IAAI,QAAgB,SAChB;CAC5B,IAAI,CAAC,KAAK,OAAO,KAAA;CACjB,MAAM,cAAc,IAAI,eAAe;CACvC,MAAM,aAAa,oBAAoB,WAAW;CAClD,OAAO,aACH;EACE;EACA;EACA;EACA,MAAM,WAAW,WAAW;EAC5B,iBAAiB,KAAK,SAAS,IAAI;EACnC,UAAU,qBAAqB,UAAU;CAC3C,IACA,KAAA;AACN;;AAGA,eAAsB,mBAAmB,MAAmD;CAC1F,OAAO,oBAAoB,MAAM,GAAG,aAAa,MAAM,OAAO,CAAC;AACjE;;AAGA,SAAgB,qBAAqB,IAA4B;CAC/D,MAAM,OAAO,aAAa,GAAG,GAAU,CAAC,CAAC;CACzC,OAAO,GAAG,mBAAmB,CAAC,KAAK,SAAS,IAAI,IAAI,GAAG,KAAK,MAAM;AACpE;AAEA,eAAsB,mBAAmB,IAAmC;CAC1E,MAAM,UAAU,GAAG,KAAK,GAAG,IAAI;CAC/B,IAAI,GAAG,iBAAiB;EACtB,MAAM,OAAO,GAAG,aAAa,GAAG,MAAM,OAAO;EAC7C,IAAI,CAAC,KAAK,SAAS,IAAI,GAAG,GAAG,cAAc,GAAG,MAAM,OAAO,MAAM,OAAO;CAC1E;AACF;AAEA,SAAgB,YAAY,IAA8B;CACxD,OAAO,GAAG,WAAW,WAClB,OAAO,UAAU,CAAC,CAClB,IAAI,OAAO,CAAC,CACZ,QAAQ,MAAuC,MAAM,KAAA,CAAS;AACnE;AAEA,SAAS,aAAa,IAAoB,QAAkC;CAC1E,MAAM,QAAQ,OAAO,SAAS,GAAG,YAAY,MAAM,CAAC,EAAE,KAAK;CAC3D,OAAO,SAAS,KAAK,IAAI,QAAQ,KAAA;AACnC;;AAGA,SAAgB,WAAW,IAAoB,QAAwB;CACrE,MAAM,OAAO,aAAa,IAAI,MAAM;CACpC,IAAI,CAAC,MAAM,OAAO,CAAC;CAEnB,MAAM,SAAiB,CAAC;CACxB,MAAM,QAAQ,KAAW,WAAqB;EAC5C,KAAK,MAAM,QAAQ,IAAI,YAAY;GACjC,IAAI,CAAC,WAAW,IAAI,GAAG;GACvB,MAAM,OAAO,QAAQ,IAAI;GACzB,IAAI,SAAS,KAAA,GAAW;GACxB,MAAM,OAAO,CAAC,GAAG,QAAQ,IAAI;GAC7B,MAAM,QAAQ,KAAK,SAAS,iBAAiB,OAAO,OAAO,KAAK,KAAK;GACrE,IAAI,SAAS,KAAK,GAChB,KAAK,OAAO,IAAI;QACX;IACL,MAAM,OAAO,SAAS,KAAK;IAC3B,OAAO,KAAK;KAAE;KAAM;KAAM,GAAI,SAAS,WAAW,EAAE,OAAO,YAAY,KAAK,EAAE,IAAI,CAAC;IAAG,CAAC;GACzF;EACF;CACF;CACA,KAAK,MAAM,CAAC,CAAC;CACb,OAAO;AACT;AAEA,SAAS,QAAQ,IAAoB,QAAgB,MAAkC;CACrF,IAAI,MAAM,aAAa,IAAI,MAAM;CACjC,KAAK,IAAI,IAAI,GAAG,OAAO,IAAI,KAAK,QAAQ,KAAK;EAC3C,MAAM,OAAO,SAAS,KAAK,KAAK,EAAE;EAClC,IAAI,CAAC,MAAM,OAAO,KAAA;EAClB,IAAI,MAAM,KAAK,SAAS,GAAG,OAAO;EAClC,MAAM,OAAO,OAAO,KAAK,KAAK;EAC9B,MAAM,SAAS,IAAI,IAAI,OAAO,KAAA;CAChC;AAEF;AAEA,SAAgB,QAAQ,IAAoB,QAAgB,MAAyB;CACnF,OAAO,QAAQ,IAAI,QAAQ,IAAI,MAAM,KAAA;AACvC;AAEA,SAAgB,UAAU,IAAoB,QAAgB,MAAoC;CAChG,MAAM,OAAO,QAAQ,IAAI,QAAQ,IAAI;CACrC,OAAO,QAAQ,KAAK,SAAS,iBAAiB,YAAY,KAAK,KAAK,IAAI,KAAA;AAC1E;AAEA,SAAS,aAAa,IAAoB,QAAsB;CAC9D,IAAI,MAAM,aAAa,IAAI,MAAM;CACjC,IAAI,CAAC,KAAK;EACR,MAAM,OAAO,SAAS,QAAQ,IAAI;EAClC,GAAG,WAAW,WAAW,KAAK,IAAI;EAClC,MAAM,KAAK;CACb;CACA,OAAO;AACT;;AAGA,SAAS,aAAa,IAAoB,QAAgB,MAAkC;CAC1F,IAAI,MAAM,aAAa,IAAI,MAAM;CACjC,KAAK,MAAM,WAAW,KAAK,MAAM,GAAG,EAAE,GAAG;EACvC,IAAI,OAAO,SAAS,KAAK,OAAO;EAChC,IAAI,CAAC,MAAM;GACT,OAAO,SAAS,SAAS,IAAI;GAC7B,IAAI,WAAW,KAAK,IAAI;EAC1B;EACA,MAAM,OAAO,OAAO,KAAK,KAAK;EAC9B,IAAI,CAAC,SAAS,IAAI,GAAG,OAAO,KAAA;EAC5B,MAAM;CACR;CACA,OAAO;AACT;;;;;AAQA,SAAgB,UACd,IACA,QACA,MACA,OACW;CACX,MAAM,SAAS,aAAa,IAAI,QAAQ,IAAI;CAC5C,IAAI,CAAC,QAAQ,OAAO;CAEpB,MAAM,OAAO,KAAK,KAAK,SAAS;CAChC,MAAM,WAAW,SAAS,QAAQ,IAAI;CACtC,IAAI,UAAU;EACZ,IAAI,SAAS,SAAS,kBAAkB,SAAS,SAAS,KAAK,MAAM,UACnE,OAAO;EAET,SAAS,QAAQ,eAAe,KAAK;EACrC,OAAO;CACT;CACA,OAAO,WAAW,KAAK,SAAS,MAAM,KAAK,UAAU,KAAK,CAAC,CAAC;CAC5D,OAAO;AACT;;;;;;AAOA,SAAgB,SACd,IACA,YACA,UACA,MACA,WACS;CACT,MAAM,SAAS,QAAQ,IAAI,YAAY,IAAI;CAC3C,IAAI,CAAC,UAAU,QAAQ,IAAI,UAAU,IAAI,GAAG,OAAO;CAEnD,MAAM,SAAS,aAAa,IAAI,UAAU,IAAI;CAC9C,IAAI,CAAC,QAAQ,OAAO;CAEpB,MAAM,OAAO,KAAK,KAAK,SAAS;CAChC,MAAM,OAAO,OAAO,SAAS,iBAAiB,KAAA,IAAY,YAAY,OAAO,KAAK;CAClF,IAAI,SAAS,KAAA,KAAa,WACxB,OAAO,WAAW,KAAK,SAAS,MAAM,KAAK,UAAU,UAAU,IAAI,CAAC,CAAC,CAAC;MACjE;EACL,MAAM,OAAO,aAAa,MAAa,CAAC,CAAC;EACzC,MAAM,OAAa,gBAAgB,MAAM,KAAK,IAAI;EAClD,OAAO,WAAW,KAAK,KAAK,KAAK,WAAW,EAAE;CAChD;CACA,OAAO;AACT;;AAGA,SAAgB,aAAa,OAAgB,SAAmB,CAAC,GAAe;CAC9E,IAAI,SAAS,OAAO,UAAU,YAAY,CAAC,MAAM,QAAQ,KAAK,GAC5D,OAAO,OAAO,QAAQ,KAAK,CAAC,CAAC,SAAS,CAAC,GAAG,OAAO,aAAa,GAAG,CAAC,GAAG,QAAQ,CAAC,CAAC,CAAC;CAElF,OAAO,OAAO,SAAS,IAAI,CAAC,MAAM,IAAI,CAAC;AACzC;AAEA,MAAM,WAAW,QACf,MACI;CACE,OAAO;EAAE,MAAM,IAAI,MAAM,OAAO;EAAG,QAAQ,IAAI,MAAM;CAAO;CAC5D,KAAK;EAAE,MAAM,IAAI,IAAI,OAAO;EAAG,QAAQ,IAAI,IAAI;CAAO;AACxD,IACA,KAAA;;;;;AAMN,SAAgB,WACd,IACA,QACA,OAAiB,CAAC,GACO;CACzB,MAAM,OAAO,KAAK,WAAW,IAAI,SAAS,GAAG,YAAY,MAAM,IAAI,QAAQ,IAAI,QAAQ,IAAI;CAC3F,OAAO,SAAS,MAAM,OAAO,KAAA,EAAO,GAAG;AACzC;;AAGA,SAAgB,mBAAmB,IAA6C;CAC9E,OAAO,QAAQ,GAAG,WAAW,GAAG;AAClC;;AAGA,SAAgB,cACd,IACA,QACA,MACoB;CACpB,MAAM,OAAO,QAAQ,IAAI,QAAQ,IAAI;CACrC,IAAI,CAAC,MAAM,OAAO,KAAA;CAClB,OAAO,aAAc,KAAK,SAAS,iBAAiB,OAAO,KAAK,KAAa,CAAC,CAAC;AACjF;;;;AC5YA,MAAa,iBAAiB;CAC5B;CACA;CACA;CACA;AACF;;AAGA,MAAa,wBAAwB;CACnC,GAAG;CACH;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;AACF;;AASA,SAAS,eAAe,MAAsB;CAC5C,KAAK,IAAI,MAAM,OAAQ,MAAM,KAAK,QAAQ,GAAG,GAAG;EAC9C,IAAI,GAAG,WAAW,KAAK,KAAK,KAAK,MAAM,CAAC,GAAG,OAAO;EAClD,IAAI,KAAK,QAAQ,GAAG,MAAM,KAAK,OAAO;CACxC;AACF;AAEA,SAAS,UAAU,KAAyC;CAC1D,IAAI;EACF,MAAM,OAAO,GAAG,aAAa,KAAK,KAAK,KAAK,YAAY,GAAG,OAAO;EAClE,OAAO;GAAE;GAAK,SAAS,OAAO,CAAC,CAAC,IAAI,IAAI;EAAE;CAC5C,QAAQ;EACN;CACF;AACF;;;;;;AAOA,SAAgB,sBAAsB,MAAiD;CACrF,MAAM,OAAO,KAAK,QAAQ,IAAI;CAC9B,MAAM,MAAM,eAAe,IAAI;CAE/B,MAAM,SAA2B,CAAC;CAClC,KAAK,IAAI,MAAM,OAAQ,MAAM,KAAK,QAAQ,GAAG,GAAG;EAC9C,MAAM,QAAQ,UAAU,GAAG;EAC3B,IAAI,OAAO,OAAO,KAAK,KAAK;EAC5B,IAAI,QAAQ,OAAO,KAAK,QAAQ,GAAG,MAAM,KAAK;CAChD;CAEA,MAAM,SAAS,GAAG,KAAK,iBAAiB;EACtC,KAAK;EACL,UAAU;EACV,KAAK;EACL,QAAQ,CAAC,sBAAsB,YAAY;CAC7C,CAAC;CACD,KAAK,MAAM,QAAQ,QAAQ;EACzB,MAAM,MAAM,KAAK,QAAQ,IAAI;EAC7B,IAAI,QAAQ,MAAM;EAClB,MAAM,QAAQ,UAAU,GAAG;EAC3B,IAAI,OAAO,OAAO,KAAK,KAAK;CAC9B;CAEA,IAAI,OAAO,WAAW,GAAG,aAAa;CAEtC,QAAQ,iBAAiB;EACvB,KAAK,MAAM,EAAE,KAAK,aAAa,QAAQ;GACrC,MAAM,WAAW,KAAK,SAAS,KAAK,YAAY;GAChD,IAAI,CAAC,YAAY,SAAS,WAAW,IAAI,KAAK,KAAK,WAAW,QAAQ,GAAG;GACzE,IAAI,QAAQ,QAAQ,SAAS,MAAM,KAAK,GAAG,CAAC,CAAC,KAAK,GAAG,CAAC,GAAG,OAAO;EAClE;EACA,OAAO;CACT;AACF;;AAgBA,SAAgB,UACd,MACA,UACA,UAAuB,CAAC,GACd;CACV,MAAM,UAAU,QAAQ,SAAS,WAAW,wBAAwB;CACpE,MAAM,QAAQ,GAAG,KAAK,UAAU;EAC9B,KAAK;EACL,UAAU;EACV,QAAQ;GAAC,GAAG;GAAS,GAAI,QAAQ,WAAW,CAAC;GAAI,GAAI,QAAQ,UAAU,CAAC;EAAE;CAC5E,CAAC;CACD,IAAI,QAAQ,cAAc,OAAO,OAAO;CACxC,MAAM,UAAU,QAAQ,mBAAmB,sBAAsB,IAAI;CACrE,OAAO,MAAM,QAAQ,SAAS,CAAC,QAAQ,IAAI,CAAC;AAC9C;;;;ACpGA,MAAM,iBAAiB;CAAC;CAAQ;CAAO;CAAO;CAAO;AAAM;AAE3D,SAAS,mBAAmB,QAAgB,SAA4B;CACtE,IAAI;EACF,OAAO,IAAI,KAAK,YAAY,QAAQ,EAAE,MAAM,UAAU,YAAY,WAAW,CAAC,CAAC,CAC5E,gBAAgB,CAAC,CACjB,iBAAiB,QAAQ,MAAM,MAAM,OAAO,CAAC,CAC7C,MAAM,GAAG,MAAM,eAAe,QAAQ,CAAC,IAAI,eAAe,QAAQ,CAAC,CAAC;CACzE,QAAQ;EACN,OAAO,CAAC;CACV;AACF;;;;;;;;;AAUA,SAAgB,SACd,YACA,SACA,eACc;CACd,MAAM,WAAyB,CAAC;CAChC,MAAM,yBAAS,IAAI,IAAoC;CAEvD,KAAK,MAAM,CAAC,QAAQ,YAAY,SAAS;EACvC,MAAM,qBAAK,IAAI,IAAuB;EACtC,KAAK,MAAM,CAAC,MAAM,UAAU,SAAS;GACnC,IAAI,CAAC,MAAM,SAAS,GAAG,GAAG;GAC1B,MAAM,MAAM,GAAG,WAAW,GAAG;GAC7B,IAAI;IACF,GAAG,IAAI,MAAM,aAAa,KAAK,CAAC;GAClC,SAAS,OAAO;IACd,MAAM,aAAa,gBAAgB,KAAK;IACxC,SAAS,KAAK;KACZ,OAAO,aAAa,UAAU;KAC9B,MAAM;KACN;KACA;KACA,SAAS,aACL,wBAAwB,IAAI,KAAK,OAAO,KAAM,MAAgB,YAC9D,IAAI,IAAI,KAAK,OAAO,2EAA4E,MAAgB;IACtH,CAAC;GACH;EACF;EACA,OAAO,IAAI,QAAQ,EAAE;CACvB;CAGA,MAAM,QAAQ,CAAC,eAAe,GAAG,CAAC,GAAG,OAAO,KAAK,CAAC,CAAC,CAAC,QAAQ,MAAM,MAAM,aAAa,CAAC;CACtF,MAAM,QAAQ,IAAI,IAAI,CAAC,GAAG,OAAO,OAAO,CAAC,CAAC,CAAC,SAAS,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC,CAAC;CAExE,KAAK,MAAM,QAAQ,OAAO;EACxB,MAAM,MAAM,GAAG,WAAW,GAAG;EAC7B,MAAM,YAAY,MAAM,MAAM,MAAM,OAAO,IAAI,CAAC,CAAC,EAAE,IAAI,IAAI,CAAC;EAC5D,IAAI,CAAC,WAAW;EAChB,MAAM,WAAW,kBAAkB,OAAO,IAAI,SAAS,CAAC,CAAE,IAAI,IAAI,CAAE;EAEpE,KAAK,MAAM,UAAU,OAAO;GAC1B,MAAM,QAAQ,OAAO,IAAI,MAAM,CAAC,EAAE,IAAI,IAAI;GAC1C,IAAI,SAAS,WAAW,WAAW;IACjC,MAAM,QAAQ,kBAAkB,KAAK;IACrC,IAAI,UAAU,UACZ,SAAS,KAAK;KACZ,OAAO;KACP,MAAM;KACN;KACA;KACA,SAAS,WAAW,OAAO,mCAAmC,UAAU,SAAS,IAAI,cAAc,YAAY,OAAO,UAAU,SAAS,OAAO;IAClJ,CAAC;GAEL;GACA,IAAI,CAAC,OAAO;GAEZ,KAAK,MAAM,UAAU,YAAY,KAAK,GAAG;IACvC,MAAM,UAAU,mBAAmB,QAAQ,OAAO,OAAO,CAAC,CAAC,QACxD,MAAM,EAAE,KAAK,OAAO,QACvB;IACA,IAAI,QAAQ,SAAS,GACnB,SAAS,KAAK;KACZ,OAAO;KACP,MAAM;KACN;KACA;KACA,SAAS,WAAW,OAAO,YAAY,OAAO,KAAK,QAAQ,IAAI,WAAW,QAAQ,KAAK,MAAM,IAAI,EAAE,EAAE,CAAC,CAAC,KAAK,IAAI,EAAE;IACpH,CAAC;GAEL;EACF;CACF;CAEA,OAAO;AACT;;;AClHA,MAAa,YAAY;AAmBzB,MAAa,aAAa,kBAAqC;CAC7D,SAAS;CACT,GAAI,eAAe,EAAE,aAAa,IAAI,CAAC;CACvC,SAAS,CAAC;AACZ;AAEA,MAAa,YAAY,SAAiB,KAAK,KAAK,MAAM,SAAS;;AAGnE,SAAgB,WAAW,MAAsB;CAC/C,OAAO,WAAW,MAAM,CAAC,CAAC,OAAO,IAAI,CAAC,CAAC,OAAO,KAAK,CAAC,CAAC,MAAM,GAAG,CAAC;AACjE;;AAGA,SAAgB,SAAS,MAAoC;CAC3D,IAAI;EACF,MAAM,OAAO,KAAK,MAAM,GAAG,aAAa,SAAS,IAAI,GAAG,OAAO,CAAC;EAChE,IAAI,MAAM,YAAY,KAAK,OAAO,KAAK,YAAY,YAAY,KAAK,YAAY,MAC9E;EAEF,OAAO;GACL,SAAS;GACT,GAAI,OAAO,KAAK,iBAAiB,WAAW,EAAE,cAAc,KAAK,aAAa,IAAI,CAAC;GACnF,SAAS,KAAK;EAChB;CACF,QAAQ;EACN;CACF;AACF;;AAGA,SAAgB,UAAU,MAAc,MAAsB;CAC5D,MAAM,SAAmB;EACvB,SAAS;EACT,GAAI,KAAK,eAAe,EAAE,cAAc,KAAK,aAAa,IAAI,CAAC;EAC/D,SAAS,OAAO,YACd,OAAO,KAAK,KAAK,OAAO,CAAC,CACtB,KAAK,CAAC,CACN,KAAK,WAAW,CACf,QACA,OAAO,YACL,OAAO,QAAQ,KAAK,QAAQ,OAAO,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,cAAc,CAAC,CAAC,CAC5E,CACF,CAAC,CACL;CACF;CACA,GAAG,cAAc,SAAS,IAAI,GAAG,KAAK,UAAU,QAAQ,MAAM,CAAC,IAAI,MAAM,OAAO;AAClF;;AAGA,SAAgB,OAAO,MAAgB,QAAgB,KAAa,YAA0B;CAC5F,CAAC,KAAK,QAAQ,YAAY,CAAC,EAAA,CAAG,OAAO,WAAW,UAAU;AAC5D;;;;;AAMA,SAAgB,QAAQ,MAAgB,QAAgB,KAAa,YAA6B;CAChG,MAAM,WAAW,KAAK,QAAQ,OAAO,GAAG;CACxC,OAAO,aAAa,KAAA,KAAa,aAAa,WAAW,UAAU;AACrE;;;;;AAMA,SAAgB,QAAQ,MAAc,cAA6D;CACjG,MAAM,WAAW,SAAS,IAAI;CAC9B,IAAI,CAAC,UAAU,OAAO;EAAE,MAAM,UAAU,YAAY;EAAG,UAAU;CAAM;CACvE,IAAI,SAAS,gBAAgB,SAAS,iBAAiB,cACrD,OAAO;EAAE,MAAM,UAAU,YAAY;EAAG,UAAU;CAAK;CAEzD,SAAS,eAAe;CACxB,OAAO;EAAE,MAAM;EAAU,UAAU;CAAM;AAC3C;;;AChBA,SAAgB,sBAAqC;CACnD,OAAO;EAAE,8BAAc,IAAI,IAAI;EAAG,yBAAS,IAAI,IAAI;EAAG,2BAAW,IAAI,IAAI;CAAE;AAC7E;;AAGA,SAAgB,eAAe,OAA4B;CACzD,MAAM,UAAU,MAAM;AACxB;AAoDA,MAAa,sBAAsB;;AAGnC,MAAM,kBACJ;;AAEF,MAAM,SAAS;;AAYf,SAAgB,eAAe,MAA2B;CACxD,MAAM,aAA0B,CAAC;CACjC,MAAM,WAAW,SAAiB,SAA4B;EAC5D,KAAK,MAAM,SAAS,KAAK,SAAS,OAAO,GAAG;GAC1C,MAAM,CAAC,OAAO,OAAO,MAAM,QAAS;GACpC,WAAW,KAAK;IAAE;IAAM,OAAO,MAAM;IAAI;IAAO;GAAI,CAAC;EACvD;CACF;CACA,QAAQ,iBAAiB,YAAY;CACrC,QAAQ,QAAQ,MAAM;CACtB,OAAO,WAAW,MAAM,GAAG,MAAM,EAAE,QAAQ,EAAE,KAAK;AACpD;AAEA,SAAS,WAAW,MAAwB;CAC1C,MAAM,SAAS,CAAC,CAAC;CACjB,KAAK,IAAI,IAAI,GAAG,IAAI,KAAK,QAAQ,KAAK,IAAI,KAAK,WAAW,CAAC,MAAM,IAAI,OAAO,KAAK,IAAI,CAAC;CACtF,OAAO;AACT;AAEA,SAAS,WAAW,QAAkB,QAAgB;CACpD,IAAI,MAAM;CACV,IAAI,OAAO,OAAO,SAAS;CAC3B,OAAO,MAAM,MAAM;EACjB,MAAM,MAAM,KAAK,MAAM,MAAM,QAAQ,CAAC;EACtC,IAAI,OAAO,QAAQ,QAAQ,MAAM;OAC5B,OAAO,MAAM;CACpB;CACA,OAAO;EAAE,MAAM;EAAK,QAAQ,SAAS,OAAO;CAAK;AACnD;AAaA,SAAS,eAAe,IAAoC;CAC1D,MAAM,UAAU,YAAY,EAAE;CAC9B,MAAM,yBAAS,IAAI,IAAmC;CACtD,KAAK,MAAM,UAAU,SAAS;EAC5B,MAAM,0BAAU,IAAI,IAAsB;EAC1C,KAAK,MAAM,QAAQ,WAAW,IAAI,MAAM,GACtC,QAAQ,IAAI,KAAK,KAAK,KAAK,GAAG,GAAG;GAAE,MAAM,KAAK;GAAM,OAAO,KAAK;EAAM,CAAC;EAEzE,OAAO,IAAI,QAAQ,OAAO;CAC5B;CACA,OAAO;EAAE,MAAM,GAAG;EAAO;EAAS;EAAQ;CAAG;AAC/C;AAEA,eAAe,YAAY,MAA+B;CACxD,IAAI;EACF,MAAM,MAAM,MAAM,OAAO,GAAG,cAAc,IAAI,CAAC,CAAC,KAAK,KAAK,KAAK,IAAI,EAAE,GAAG,KAAK,OAAO;EACpF,MAAM,aAAa,IAAI,WAAW;EAClC,IAAI,CAAC,cAAc,OAAO,eAAe,YAAY,CAAC,WAAW,YAC/D,OAAO;GACL,IAAI;GACJ,OAAO;GACP,MAAM;GACN,SAAS;EACX;EAGF,MAAM,aAAa,WAAW;EAC9B,MAAM,yBAAS,IAAI,IAAmC;EACtD,MAAM,UAAoB,CAAC;EAE3B,KAAK,MAAM,CAAC,QAAQ,YAAY,OAAO,QAAQ,UAAU,GAAG;GAC1D,IAAI,CAAC,WAAW,OAAO,YAAY,UAAU;IAC3C,QAAQ,KAAK,MAAM;IACnB;GACF;GACA,MAAM,0BAAU,IAAI,IAAsB;GAC1C,KAAK,MAAM,YAAY,aAAa,OAAO,GAAG;IAC5C,IAAI,QAAa;IACjB,KAAK,MAAM,WAAW,UAAU,QAAQ,QAAQ;IAChD,QAAQ,IACN,SAAS,KAAK,GAAG,GACjB,OAAO,UAAU,WACb;KAAE,MAAM;KAAU;IAAM,IACxB,EAAE,MAAM,OAAO,UAAU,aAAa,aAAa,QAAQ,CACjE;GACF;GACA,OAAO,IAAI,QAAQ,OAAO;EAC5B;EAEA,IAAI,QAAQ,SAAS,GACnB,OAAO;GACL,IAAI;GACJ,OAAO;GACP,MAAM;GACN,SAAS,QAAQ,KAAK,MAAM,WAAW,EAAE,+BAA+B,CAAC,CAAC,KAAK,IAAI;EACrF;EAGF,OAAO;GACL,IAAI;GACJ,MAAM;IAAE,MAAM,OAAO,WAAW,QAAQ,EAAE;IAAG,SAAS,CAAC,GAAG,OAAO,KAAK,CAAC;IAAG;GAAO;EACnF;CACF,SAAS,OAAY;EACnB,OAAO;GACL,IAAI;GACJ,OAAO;GACP,MAAM;GACN,SAAS,gCAAgC,MAAM,WAAW,OAAO,KAAK;EACxE;CACF;AACF;AAEA,eAAe,mBAAmB,MAAc,SAAmC;CACjF,IAAI;CACJ,IAAI;EACF,MAAM,KAAK,MAAM,mBAAmB,IAAI;EACxC,IAAI,IAAI,YAAY,GAAG,MAAM,OAAO;GAAE,IAAI;GAAM,MAAM,eAAe,EAAE;EAAE;CAC3E,SAAS,OAAO;EACd,WAAW;CACb;CAEA,IAAI,SAAS,OAAO,YAAY,IAAI;CAEpC,OAAO,WACH;EACE,IAAI;EACJ,OAAO;EACP,MAAM;EACN,SAAS,+BAA+B,SAAS;CACnD,IACA;EACE,IAAI;EACJ,OAAO;EACP,MAAM;EACN,SACE;CACJ;AACN;AAEA,SAAS,QAAQ,MAAkC;CACjD,IAAI;EACF,MAAM,OAAO,GAAG,SAAS,IAAI;EAC7B,OAAO,GAAG,KAAK,QAAQ,GAAG,KAAK;CACjC,QAAQ;EACN;CACF;AACF;AAEA,eAAe,iBACb,MACA,SACA,OACiB;CACjB,MAAM,QAAQ,QAAQ,QAAQ,IAAI,IAAI,KAAA;CACtC,MAAM,MAAM,QAAQ,MAAO,aAAa,IAAI,IAAI,IAAI,KAAA;CACpD,IAAI,OAAO,IAAI,UAAU,OAAO,OAAO,IAAI;CAE3C,MAAM,SAAS,MAAM,mBAAmB,MAAM,OAAO;CACrD,IAAI,SAAS,OAAO,MAAM,aAAa,IAAI,MAAM;EAAE;EAAO;CAAO,CAAC;CAClE,OAAO;AACT;AAEA,SAAS,WAAW,MAA0B;CAC5C,MAAM,SAAS,WAAW,IAAI;CAC9B,MAAM,WAAW,OAAe,SAA8B;EAC5D,OAAO,WAAW,QAAQ,KAAK;EAC/B,KAAK,WAAW,QAAQ,GAAG;CAC7B;CACA,OAAO;EACL,QAAQ,CAAC,GAAG,IAAI,IAAI,KAAK,MAAM,UAAU,KAAK,CAAC,CAAC,CAAC;EACjD,MAAM,eAAe,IAAI,CAAC,CAAC,KAAK,SAAS;GAAE;GAAK,OAAO,QAAQ,IAAI,OAAO,IAAI,GAAG;EAAE,EAAE;CACvF;AACF;AAEA,eAAsB,eAAe,SAAmD;CACtF,MAAM,EAAE,MAAM,WAAW;CACzB,MAAM,UAAU,OAAO,WAAW;CAClC,MAAM,oBAAoB,OAAO,WAAW,CAAC;CAC7C,MAAM,gBAAgB,OAAO,iBAAiB;CAC9C,MAAM,cAAc,QAAQ,UAAU,CAAC;CAEvC,MAAM,QAAQ,QAAQ,UAAU,KAAA,IAAY,QAAQ;CACpD,IAAI,YAAY,OAAO,UAAU,IAAI,IAAI;CACzC,IAAI,SAAS,CAAC,WAAW;EACvB,YAAY,sBAAsB,IAAI;EACtC,MAAM,UAAU,IAAI,MAAM,SAAS;CACrC;CAEA,MAAM,QAAQ,UAAU,MAAM,SAAS;EACrC,SAAS,OAAO;EAChB,QAAQ;EACR,iBAAiB;CACnB,CAAC;CAED,MAAM,SAA0B,CAAC;CACjC,MAAM,eAAqC,CAAC;CAC5C,MAAM,OAAO,QAAQ,SAAS,QAAQ,KAAA,IAAY,SAAS,IAAI;CAG/D,KAAK,MAAM,QAAQ,OAAO;EACxB,MAAM,SAAS,MAAM,iBAAiB,MAAM,QAAQ,YAAY,MAAM,KAAK;EAC3E,IAAI,CAAC,OAAO,IAAI;GACd,KAAK,MAAM,WAAW,OAAO,QAAQ,MAAM,IAAI,GAC7C,OAAO,KAAK;IAAE;IAAM,OAAO,OAAO;IAAO,MAAM,OAAO;IAAM;GAAQ,CAAC;GAEvE;EACF;EAEA,MAAM,EAAE,SAAS;EACjB,MAAM,EAAE,OAAO;EACf,MAAM,MAAM,QAAiB,YAC3B,MAAM,SAAS,WAAW,IAAI,QAAQ,OAAO,IAAI,KAAA;EACnD,MAAM,OAAO,UACX,OAAO,KAAK;GAAE,GAAG;GAAO;GAAM,YAAY,KAAK;EAAK,CAAC;EAEvD,KAAK,MAAM,YAAY,mBACrB,IAAI,CAAC,KAAK,QAAQ,SAAS,QAAQ,GACjC,IAAI;GACF,OAAO;GACP,MAAM;GACN,SAAS,8BAA8B,SAAS;GAChD,OAAO,KAAK,mBAAmB,EAAE,IAAI,KAAA;GACrC,QAAQ;EACV,CAAC;EAIL,MAAM,QAAkB,CAAC;EACzB,MAAM,uBAAO,IAAI,IAAY;EAC7B,KAAK,MAAM,UAAU,KAAK,SACxB,KAAK,MAAM,YAAY,KAAK,OAAO,IAAI,MAAM,CAAC,CAAE,KAAK,GACnD,IAAI,CAAC,KAAK,IAAI,QAAQ,GAAG;GACvB,KAAK,IAAI,QAAQ;GACjB,MAAM,KAAK,QAAQ;EACrB;EAIJ,KAAK,MAAM,UAAU,KAAK,SAAS;GACjC,MAAM,UAAU,KAAK,OAAO,IAAI,MAAM;GACtC,KAAK,MAAM,YAAY,OAAO;IAC5B,IAAI,QAAQ,IAAI,QAAQ,GAAG;IAC3B,MAAM,eAAe,CAAC,eAAe,GAAG,KAAK,OAAO,CAAC,CAAC,MACnD,MAAM,MAAM,UAAU,KAAK,OAAO,IAAI,CAAC,CAAC,EAAE,IAAI,QAAQ,CACzD;IACA,IAAI;KACF,OAAO;KACP,MAAM;KACN,SAAS,WAAW,OAAO,oBAAoB,SAAS;KACxD,OAAO,GAAG,MAAM;KAChB;KACA,MAAM,SAAS,MAAM,GAAG;KACxB;IACF,CAAC;GACH;EACF;EAEA,MAAM,0BAAyB,IAAI,IAAI;EACvC,KAAK,MAAM,UAAU,KAAK,SAAS;GACjC,MAAM,0BAAU,IAAI,IAAoB;GACxC,QAAQ,IAAI,QAAQ,OAAO;GAC3B,KAAK,MAAM,CAAC,UAAU,SAAS,KAAK,OAAO,IAAI,MAAM,GAAI;IACvD,IAAI,KAAK,SAAS,YAAY,KAAK,UAAU,KAAA,GAAW;IACxD,QAAQ,IAAI,UAAU,KAAK,KAAK;IAChC,IAAI,KAAK,MAAM,WAAA,SAAsB,GACnC,IAAI;KACF,OAAO;KACP,MAAM;KACN,SAAS,WAAW,OAAO,SAAS,SAAS,gBAAgB,YAAY,KAAK,EAAE;KAChF,OAAO,GAAG,QAAQ,SAAS,MAAM,GAAG,CAAC;KACrC;KACA,MAAM,SAAS,MAAM,GAAG;IAC1B,CAAC;GAEL;EACF;EAGA,MAAM,eAAe,MAAM,eAAe,KAAK,OAAO,IAAI,KAAK,YAAY,IAAI,KAAA;EAC/E,IAAI,QAAQ,cACV,KAAK,MAAM,UAAU,KAAK,SAAS;GACjC,IAAI,WAAW,KAAK,cAAc;GAClC,KAAK,MAAM,CAAC,UAAU,SAAS,KAAK,OAAO,IAAI,MAAM,GAAI;IACvD,IAAI,KAAK,SAAS,YAAY,KAAK,UAAU,KAAA,GAAW;IACxD,IAAI,KAAK,MAAM,WAAA,SAAsB,GAAG;IACxC,MAAM,SAAS,aAAa,IAAI,QAAQ;IACxC,IAAI,QAAQ,SAAS,YAAY,OAAO,UAAU,KAAA,GAAW;IAC7D,IAAI,CAAC,QAAQ,MAAM,QAAQ,GAAG,KAAK,KAAK,GAAG,YAAY,OAAO,KAAK,GAAG;IACtE,IAAI;KACF,OAAO;KACP,MAAM;KACN,SAAS,WAAW,OAAO,SAAS,SAAS,yBAAyB,KAAK,aAAa;KACxF,OAAO,GAAG,QAAQ,SAAS,MAAM,GAAG,CAAC;KACrC;KACA,MAAM,SAAS,MAAM,GAAG;KACxB,cAAc,KAAK;IACrB,CAAC;GACH;EACF;EAGF,KAAK,MAAM,WAAW,SAAS,KAAK,MAAM,SAAS,aAAa,GAAG;GACjE,MAAM,UAAU,QAAQ,IAAI,MAAM,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,MAAM,GAAG;GACjE,IAAI;IACF,OAAO,QAAQ;IACf,MAAM,QAAQ;IACd,SAAS,QAAQ;IACjB,OAAO,GAAG,QAAQ,QAAQ,OAAO;IACjC,QAAQ,QAAQ;IAChB,MAAM;GACR,CAAC;EACH;EAEA,aAAa,KAAK;GAChB,MAAM,KAAK;GACX;GACA,SAAS,KAAK;GACd,QAAQ,KAAK;GACb;GACA;EACF,CAAC;CACH;CAGA,MAAM,QAAQ,IAAI,IAAI,aAAa,KAAK,MAAM,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC;CAC1D,MAAM,kBAAkB,IAAI,IAAI,KAAK;CACrC,MAAM,cAAc,QAAQ,OAAO,CAAA,mDAAoB;CACvD,MAAM,cACJ,YAAY,WAAW,IACnB,CAAC,IACD,UAAU,MAAM,aAAa;EAC3B,MAAM;EACN,SAAS,OAAO;EAChB,QAAQ;EACR,iBAAiB;CACnB,CAAC,CAAC,CAAC,QAAQ,MAAM,CAAC,gBAAgB,IAAI,CAAC,CAAC;CAE9C,IAAI,YAAY,SAAS,GAAG;EAC1B,MAAM,yBAAS,IAAI,IAAY;EAE/B,KAAK,MAAM,QAAQ,aAAa;GAC9B,MAAM,QAAQ,QAAQ,QAAQ,IAAI,IAAI,KAAA;GACtC,IAAI,OAAO,QAAQ,MAAO,QAAQ,IAAI,IAAI,IAAI,KAAA;GAC9C,IAAI,CAAC,QAAQ,KAAK,UAAU,OAAO;IACjC,IAAI;IACJ,IAAI;KACF,OAAO,GAAG,aAAa,MAAM,OAAO;IACtC,QAAQ;KACN;IACF;IACA,OAAO;KAAE,OAAO,SAAS;KAAI,MAAM,WAAW,IAAI;IAAE;IACpD,IAAI,SAAS,OAAO,MAAM,QAAQ,IAAI,MAAM,IAAI;GAClD;GACA,KAAK,MAAM,SAAS,KAAK,KAAK,QAAQ,OAAO,IAAI,KAAK;GAEtD,KAAK,MAAM,EAAE,KAAK,WAAW,KAAK,KAAK,MAAM;IAC3C,IAAI,IAAI,SAAS,cAAc;KAC7B,IAAI,CAAC,MAAM,IAAI,IAAI,KAAK,GACtB,OAAO,KAAK;MACV;MACA,OAAO;MACP,MAAM;MACN,SAAS,uBAAuB,IAAI,MAAM;MAC1C;MACA,YAAY,IAAI;KAClB,CAAC;KAEH;IACF;IAEA,MAAM,CAAC,MAAM,GAAG,QAAQ,IAAI,MAAM,MAAM,GAAG;IAC3C,MAAM,aAAa,MAAM,IAAI,IAAI;IACjC,IAAI,CAAC,YAAY;IACjB,MAAM,UAAU,KAAK,KAAK,GAAG;IAE7B,IAAI,CADW,WAAW,MAAM,MAAM,MAAM,MAAM,WAAW,EAAE,WAAW,GAAG,QAAQ,EAAE,CAC7E,GACR,OAAO,KAAK;KACV;KACA,OAAO;KACP,MAAM;KACN,SAAS,6BAA6B,IAAI,MAAM;KAChD;KACA,YAAY;KACZ,MAAM;IACR,CAAC;GAEL;EACF;EAGA,IAAI,QAAQ,WAAW,OACrB,KAAK,MAAM,cAAc,cAAc;GACrC,IAAI,CAAC,OAAO,IAAI,WAAW,IAAI,GAAG;IAChC,OAAO,KAAK;KACV,MAAM,WAAW;KACjB,OAAO;KACP,MAAM;KACN,SAAS,eAAe,WAAW,KAAK;KACxC,OAAO,WAAW,KAAK,mBAAmB,WAAW,EAAE,IAAI,KAAA;KAC3D,YAAY,WAAW;IACzB,CAAC;IACD;GACF;GACA,KAAK,MAAM,WAAW,WAAW,OAAO;IACtC,MAAM,OAAO,QAAQ,MAAM,GAAG,CAAC,CAAC,IAAI;IACpC,IAAI,OAAO,IAAI,IAAI,GAAG;IACtB,MAAM,SAAS,WAAW,QAAQ,MAAM,MAAM,WAAW,OAAO,IAAI,CAAC,CAAC,EAAE,IAAI,OAAO,CAAC;IACpF,OAAO,KAAK;KACV,MAAM,WAAW;KACjB,OAAO;KACP,MAAM;KACN,SAAS,QAAQ,QAAQ;KACzB,OACE,WAAW,MAAM,SACb,WAAW,WAAW,IAAI,QAAQ,QAAQ,MAAM,GAAG,CAAC,IACpD,KAAA;KACN,YAAY,WAAW;KACvB,MAAM,QAAQ,MAAM,GAAG;IACzB,CAAC;GACH;EACF;CAEJ;CAEA,IAAI,OAAO;EACT,MAAM,uBAAO,IAAI,IAAI,CAAC,GAAG,OAAO,GAAG,WAAW,CAAC;EAC/C,KAAK,MAAM,OAAO,CAAC,MAAM,cAAc,MAAM,OAAO,GAClD,KAAK,MAAM,OAAO,IAAI,KAAK,GAAG,IAAI,IAAI,WAAW,IAAI,KAAK,CAAC,KAAK,IAAI,GAAG,GAAG,IAAI,OAAO,GAAG;CAE5F;CAEA,OAAO;EAAE;EAAQ;EAAc;EAAO,oBAAoB,YAAY;CAAO;AAC/E;;AAGA,SAAgB,aAAa,MAAc,MAAsB;CAC/D,OAAO,KAAK,SAAS,MAAM,IAAI;AACjC;;;ACnlBA,MAAa,SAAS;CACpB,OAAO,QAAgB,QAAQ,IAAI,GAAG,KAAK,IAAI,IAAI,GAAG;CACtD,UAAU,QAAgB,QAAQ,IAAI,GAAG,MAAM,IAAI,IAAI,GAAG,KAAK,GAAG,CAAC;CACnE,OAAO,QAAgB,QAAQ,KAAK,GAAG,OAAO,IAAI,IAAI,GAAG;CACzD,QAAQ,QAAgB,QAAQ,MAAM,GAAG,IAAI,IAAI,IAAI,GAAG,KAAK,GAAG,CAAC;CACjE,MAAM,QAAgB,QAAQ,IAAI,GAAG;AACvC;;;ACFA,SAAgB,oBAAoB,MAAc,eAA6B,CAAC,GAAiB;CAC/F,IAAI,eAA6B,CAAC;CAClC,IAAI;EACF,MAAM,UAAiB,CAAC;EACxB,IAAI,aAAa,YACf,QAAQ,KAAK,EAAE,OAAO,aAAa,WAAW,CAAC;EAEjD,QAAQ,KACN;GACE,OAAO;GACP,YAAY;IAAC;IAAM;IAAO;IAAO;IAAM;IAAO;IAAO;IAAQ;GAAE;EACjE,GACA;GACE,OAAO;GACP,YAAY;IAAC;IAAM;IAAO;IAAO;IAAM;IAAO;IAAO;IAAQ;GAAE;EACjE,CACF;EAEA,MAAM,SAAS,eAA6B;GAC1C;GACA,OAAO;GACP,UAAU,CAAC;GACX,KAAK;EACP,CAAC;EACD,IAAI,UAAU,OAAO,QACnB,eAAe,OAAO;CAE1B,QAAQ,CAER;CAEA,OAAO;EACL,GAAG;EACH,GAAG;EACH,GAAG;CACL;AACF;;AAGA,MAAa,oBAAoB;CAC/B;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;AACF;;AAGA,MAAM,uBAAiD;CACrD,OAAO,CAAC,OAAO;CACf,aAAa,CAAC,OAAO;CACrB,MAAM,CAAC,SAAS,QAAQ;CACxB,MAAM,CAAC,MAAM;CACb,SAAS,CAAC,SAAS;CACnB,SAAS,CAAC,SAAS;CACnB,KAAK,CAAC,KAAK;CACX,gBAAgB,CAAC,QAAQ;CACzB,kBAAkB,CAAC,QAAQ;CAC3B,QAAQ,CAAC,QAAQ;CACjB,iBAAiB,CAAC,WAAW;CAC7B,OAAO,CAAC,OAAO;CACf,KAAK,CAAC,KAAK;CACX,MAAM,CAAC,OAAO,IAAI;CAClB,IAAI,CAAC,IAAI;CACT,WAAW,CAAC,IAAI;CAChB,iBAAiB,CAAC,SAAS;CAE3B,gBAAgB,CAAC,KAAK;CACtB,oBAAoB,CAAC,KAAK;CAC1B,oBAAoB,CAAC,KAAK;CAC1B,mBAAmB,CAAC,KAAK;CACzB,yBAAyB,CAAC,KAAK;CAC/B,kBAAkB,CAAC,KAAK;CACxB,UAAU,CAAC,KAAK;AAClB;;;;;AAMA,SAAgB,eAAe,MAAwB;CACrD,IAAI;EACF,MAAM,MAAM,KAAK,MAAM,GAAG,aAAa,KAAK,KAAK,MAAM,cAAc,GAAG,OAAO,CAAC;EAChF,MAAM,OAAO;GAAE,GAAG,IAAI;GAAc,GAAG,IAAI;GAAiB,GAAG,IAAI;EAAiB;EACpF,MAAM,wBAAQ,IAAI,IAAY;EAC9B,KAAK,MAAM,QAAQ,OAAO,KAAK,IAAI,GACjC,KAAK,MAAM,WAAW,qBAAqB,SAAS,CAAC,GAAG,MAAM,IAAI,OAAO;EAE3E,IAAI,MAAM,OAAO,GAAG,OAAO,kBAAkB,QAAQ,YAAY,MAAM,IAAI,OAAO,CAAC;CACrF,QAAQ,CAER;CACA,OAAO,CAAC,GAAG,iBAAiB;AAC9B;;;;;AAMA,SAAgB,UACd,MACA,OACA,SACA,mBAA2C,CAAC,GACG;CAC/C,IAAI,MAAM,WAAW,GAAG,OAAO,KAAA;CAE/B,MAAM,SAAS,GAAG,WAAW,KAAK,KAAK,MAAM,KAAK,CAAC,IAAI,KAAK,KAAK,MAAM,KAAK,IAAI;CAChF,MAAM,UAAoB,CAAC;CAC3B,MAAM,UAAoB,CAAC;CAE3B,MAAM,SAAS,MAAM,UAAU;EAC7B,IAAI,UAAU,KAAK,SAAS,QAAQ,IAAI,CAAC,CAAC,QAAQ,OAAO,GAAG;EAC5D,UAAU,QAAQ,QAAQ,SAAS,EAAE;EACrC,IAAI,CAAC,QAAQ,WAAW,GAAG,GACzB,UAAU,OAAO;EAGnB,QAAQ,KAAK,cAAc,MAAM,SAAS,QAAQ,GAAG;EACrD,QAAQ,KACN,qBAAqB,MAAM,uBAAuB,MAAM,kCAAkC,MAAM,iBAClG;CACF,CAAC;CAED,MAAM,cACJ,WAAW,QAAQ,SAAS,IAAI,QAAQ,KAAK,MAAM,IAAI,EAAE,EAAE,CAAC,CAAC,KAAK,KAAK,IAAI;CAE7E,MAAM,WAAW,QAAQ,KAAK,SAAS;CACvC,MAAM,iBAAiB,OAAO,QAAQ,gBAAgB,CAAC,CACpD,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,cAAc,CAAC,CAAC,CAAC,CACtC,KAAK,CAAC,KAAK,UAAU,OAAO,KAAK,UAAU,GAAG,EAAE,IAAI,KAAK,EAAE,CAAC,CAC5D,KAAK,IAAI;CACZ,MAAM,gBAAgB,eAAe,IAAI,CAAC,CACvC,KACE,YAAY;2BACQ,QAAQ;gDACa,SAAS;;CAGrD,CAAC,CACA,KAAK,EAAE;CAEV,MAAM,aAAa;;;EAGnB,QAAQ,KAAK,IAAI,EAAE;;;;eAIN,YAAY;;gDAEqB,QAAQ,KAAK,SAAS,EAAE;uCACjC,iBAAiB,KAAK,eAAe,QAAQ,GAAG;;EAErF,cAAc;;CAGd,OAAO;EAAE,MAAM,KAAK,KAAK,QAAQ,iBAAiB;EAAG,SAAS;CAAW;AAC3E;;;ACzKA,MAAM,aAAa;;;;;AAMnB,SAAS,eAAe,MAA6B;CACnD,IAAI,KAAK,MAAM,MAAM,EAAE,SAAS,YAAY,EAAE,SAAS,mBAAmB,EAAE,SAAS,QAAQ,GAC3F,OAAO;CAET,IAAI,KAAK,MAAM,MAAM,EAAE,SAAS,UAAU,EAAE,SAAS,MAAM,GAAG,OAAO;CACrE,MAAM,SAAS,KAAK,MAAM,MAAM,EAAE,SAAS,QAAQ;CACnD,IAAI,QAAQ;EACV,MAAM,WAAW,OAAO,aAAa,CAAC,EAAA,CAAG,QAAQ,MAAM,MAAM,OAAO;EACpE,OAAO,QAAQ,SAAS,IACpB,GAAG,QAAQ,KAAK,MAAM,KAAK,UAAU,CAAC,CAAC,CAAC,CAAC,KAAK,KAAK,EAAE,oBACrD;CACN;CACA,OAAO;AACT;;AAGA,SAAgB,YAAY,SAAqC;CAC/D,IAAI,CAAC,QAAQ,SAAS,GAAG,GAAG,OAAO,KAAA;CACnC,IAAI;CACJ,IAAI;EACF,OAAO,aAAa,aAAa,OAAO,CAAC;CAC3C,QAAQ;EACN;CACF;CACA,IAAI,KAAK,WAAW,GAAG,OAAO,KAAA;CAE9B,MAAM,yBAAS,IAAI,IAA2B;CAC9C,KAAK,MAAM,OAAO,MAAM,OAAO,IAAI,IAAI,MAAM,CAAC,GAAI,OAAO,IAAI,IAAI,IAAI,KAAK,CAAC,GAAI,GAAG,CAAC;CAKnF,OAAO,KAJS,CAAC,GAAG,MAAM,CAAC,CAAC,KACzB,CAAC,MAAM,UACN,GAAG,WAAW,KAAK,IAAI,IAAI,OAAO,KAAK,UAAU,IAAI,EAAE,IAAI,eAAe,IAAI,GAEhE,CAAC,CAAC,KAAK,IAAI,EAAE;AACjC;;;;;;AAOA,SAAgB,iBACd,cACA,eACwB;CACxB,MAAM,SAAiC,CAAC;CACxC,KAAK,MAAM,MAAM,cAAc;EAC7B,IAAI,CAAC,IAAI,MAAM;EACf,MAAM,UAAU,YAAY,EAAE;EAC9B,MAAM,YAAY,QAAQ,SAAS,aAAa,IAAI,gBAAgB,QAAQ;EAC5E,IAAI,CAAC,WAAW;EAChB,KAAK,MAAM,QAAQ,WAAW,IAAI,SAAS,GAAG;GAC5C,IAAI,KAAK,SAAS,YAAY,KAAK,UAAU,KAAA,GAAW;GACxD,MAAM,OAAO,YAAY,KAAK,KAAK;GACnC,IAAI,MAAM,OAAO,GAAG,GAAG,KAAK,GAAG,KAAK,KAAK,KAAK,GAAG,OAAO;EAC1D;CACF;CACA,OAAO;AACT;;;ACjDA,MAAM,+BAAe,IAAI,IAAI;CAC3B;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;AACF,CAAC;;AAGD,SAAS,UAAU,MAAe,wBAAQ,IAAI,IAAY,GAAgB;CACxE,IAAI,CAAC,QAAQ,OAAO,SAAS,UAAU,OAAO;CAC9C,IAAI,MAAM,QAAQ,IAAI,GAAG;EACvB,KAAK,SAAS,UAAU,UAAU,OAAO,KAAK,CAAC;EAC/C,OAAO;CACT;CACA,MAAM,MAAM;CACZ,IAAI,IAAI,SAAS,cAAc,MAAM,IAAI,IAAI,IAAI;CAEjD,KAAK,MAAM,OAAO,OAAO,KAAK,GAAG,GAAG;EAClC,IAAI,aAAa,IAAI,GAAG,GAAG;EAC3B,MAAM,iBACJ,QAAQ,SACR,CAAC,IAAI,YACL;GAAC;GAAkB;GAAgB;GAAuB;EAAmB,CAAC,CAAC,SAC7E,IAAI,IACN;EACF,MAAM,eACJ,QAAQ,cACR,CAAC,IAAI,aACJ,IAAI,SAAS,sBAAsB,IAAI,SAAS;EACnD,IAAI,kBAAkB,cAAc;EACpC,UAAU,IAAI,MAAM,KAAK;CAC3B;CACA,OAAO;AACT;;AAGA,SAAS,aAAa,SAA8B,OAAoB;CACtE,IAAI,CAAC,SAAS;CACd,QAAQ,QAAQ,MAAhB;EACE,KAAK;GACH,MAAM,IAAI,QAAQ,IAAI;GACtB;EACF,KAAK;GACH,KAAK,MAAM,QAAQ,QAAQ,YAAY,aAAa,KAAK,SAAS,KAAK,UAAU,KAAK;GACtF;EACF,KAAK;GACH,KAAK,MAAM,WAAW,QAAQ,UAAU,aAAa,WAAW,KAAA,GAAW,KAAK;GAChF;EACF,KAAK;GACH,aAAa,QAAQ,MAAM,KAAK;GAChC;EACF,KAAK,eACH,aAAa,QAAQ,UAAU,KAAK;CAExC;AACF;;AAGA,SAAS,cAAc,IAAiC;CACtD,MAAM,wBAAQ,IAAI,IAAY;CAC9B,MAAM,UAAoB,GAAG,IAAY;CACzC,MAAM,aAAwB,SAAS,QAAQ,SAAS,SAAS,QAAQ,CAAC;CAC1E,KAAK,MAAM,OAAO,YAAY;EAC5B,MAAM,YACJ,IAAI,SAAS,4BAA4B,IAAI,cAAc,IAAI,cAAc;EAC/E,QAAQ,UAAU,MAAlB;GACE,KAAK;IACH,KAAK,MAAM,aAAa,UAAU,YAAY,MAAM,IAAI,UAAU,MAAM,IAAI;IAC5E;GACF,KAAK;IACH,KAAK,MAAM,cAAc,UAAU,cAAc,aAAa,WAAW,IAAI,KAAK;IAClF;GACF,KAAK;GACL,KAAK;GACL,KAAK;GACL,KAAK;GACL,KAAK,qBACH,IAAI,UAAU,IAAI,MAAM,MAAM,IAAI,UAAU,GAAG,IAAI;EAEvD;CACF;CACA,OAAO;AACT;;;;;;;;;AAUA,SAAgB,aAAa,IAAiC;CAC5D,IAAI,CAAC,GAAG,UACN,OAAO;EAAE,IAAI;EAAO,QAAQ;CAA8D;CAG5F,MAAM,QAAQ,cAAc,EAAE;CAC9B,MAAM,SAAwB,CAAC;CAE/B,KAAK,MAAM,QAAQ,GAAG,WAAW,YAAyB;EACxD,MAAM,SAASC,QAAgB,IAAI;EACnC,MAAM,QAAQC,OAAW,KAAK,KAAK;EACnC,IAAI,WAAW,KAAA,KAAa,CAACC,SAAa,KAAK,GAC7C,OAAO;GAAE,IAAI;GAAO,QAAQ;EAAoC;EAElE,MAAM,QAAQ,CAAC,GAAG,UAAU,KAAK,CAAC,CAAC,CAAC,MAAM,SAAS,MAAM,IAAI,IAAI,CAAC;EAClE,IAAI,OACF,OAAO;GACL,IAAI;GACJ,QAAQ,IAAI,OAAO,UAAU,MAAM;EACrC;EAEF,OAAO,KAAK;GAAE;GAAQ,MAAM,aAAa,KAAY,CAAC,CAAC;EAAK,CAAC;CAC/D;CAEA,IAAI,OAAO,WAAW,GAAG,OAAO;EAAE,IAAI;EAAO,QAAQ;CAAwB;CAC7E,OAAO;EAAE,IAAI;EAAM;CAAO;AAC5B;;;AC1GA,MAAM,eAAe,CAAC,iBAAiB,aAAa;AACpD,MAAM,aAAa;CAAC;CAAM;CAAO;CAAO;CAAM;CAAO;CAAO;AAAM;AAElE,MAAa,wBAAsC;CACjD,eAAe;CACf,SAAS,CAAC;CACV,SAAS;CACT,SAAS,CAAC;CACV,WAAW,CAAC;CACZ,eAAe;CACf,MAAM;AACR;AAEA,MAAM,cAAc,OAAO,aAAa;AAExC,SAAS,QAAQ,MAAoC;CACnD,OAAOC,OAAW,IAAe;CACjC,QAAQ,MAAM,MAAd;EACE,KAAK;EACL,KAAK;EACL,KAAK,kBACH,OAAO,KAAK;EACd,KAAK,WACH,OAAO,KAAK;EACd,KAAK,mBACH,OAAO,KAAK,YAAY,WAAW,IAAK,KAAK,OAAO,EAAE,EAAE,OAAO,UAAU,KAAM;EACjF,KAAK,mBAAmB;GACtB,MAAM,QAAQ,KAAK,SAAS,KAAK,MAAe,QAAQ,CAAC,CAAC;GAC1D,OAAO,MAAM,SAAS,WAAW,IAAI,cAAc;EACrD;EACA,KAAK,oBAAoB;GACvB,MAAM,SAAkC,CAAC;GACzC,KAAK,MAAM,QAAQ,KAAK,YAAY;IAClC,MAAM,MAAMC,QAAgB,IAAI;IAChC,MAAM,QAAQ,QAAQ,KAAA,IAAY,cAAc,QAAQ,KAAK,KAAK;IAClE,IAAI,UAAU,aAAa,OAAO;IAClC,OAAO,OAAiB;GAC1B;GACA,OAAO;EACT;EACA,SACE,OAAO;CACX;AACF;;AAGA,SAAS,iBAAiB,aAA2C;CACnE,MAAM,OAAOD,OAAW,WAAW;CACnC,IAAI,MAAM,SAAS,kBAAkB,OAAO,iBAAiB,KAAK,UAAU,EAAE;CAC9E,OAAOE,SAAa,IAAI,IAAI,OAAO,KAAA;AACrC;AAEA,MAAM,iBAAiB,UACrB,MAAM,QAAQ,KAAK,KAAK,MAAM,OAAO,MAAM,OAAO,MAAM,QAAQ;AAElE,SAAS,MAAM,QAAiC,QAAsB,OAAiB;CACrF,MAAM,UACJ,KACA,OACA,aACG;EACH,IAAI,EAAE,OAAO,SAAS;EACtB,MAAM,QAAQ,OAAO;EACrB,IAAI,MAAM,KAAK,GAAG,OAAgB,OAAO;OACpC,MAAM,KAAK,IAAI,IAAI,2CAA2C,SAAS,GAAG;CACjF;CAEA,OAAO,kBAAkB,MAAM,OAAO,MAAM,YAAY,MAAM,IAAI,kBAAkB;CACpF,OAAO,WAAW,eAAe,6BAA6B;CAC9D,OACE,YACC,MAAM,OAAO,MAAM,YAAY,cAAc,CAAC,GAC/C,8BACF;CACA,OAAO,WAAW,eAAe,6BAA6B;CAC9D,OACE,cACC,MACC,OAAO,MAAM,YAAY,MAAM,QAAQ,OAAO,OAAO,CAAC,CAAC,CAAC,OAAO,SAAS,cAAc,IAAI,CAAC,GAC7F,4BACF;CACA,OAAO,kBAAkB,MAAM,OAAO,MAAM,WAAW,eAAe;CACtE,OAAO,SAAS,MAAM,OAAO,MAAM,aAAa,MAAM,UAAU,2BAAyB;AAC3F;;AAGA,SAAgB,kBAAkB,MAAc,OAAO,oBAAwC;CAC7F,MAAM,QAAkB,CAAC;CACzB,MAAM,SAAuB,EAAE,GAAG,sBAAsB;CAExD,IAAI,KAAK,SAAS,OAAO,GAAG;EAC1B,IAAI;GACF,MAAM,OAAO,KAAK,MAAM,IAAI;GAC5B,IAAI,QAAQ,OAAO,SAAS,UAAU,MAAM,MAAM,QAAQ,KAAK;EACjE,SAAS,OAAO;GACd,MAAM,KAAK,mBAAmB,KAAK,SAAS,IAAI,EAAE,IAAK,MAAgB,SAAS;EAClF;EACA,OAAO;GAAE;GAAQ;GAAM;EAAM;CAC/B;CAEA,IAAI;EACF,MAAM,WAAY,YAAY,IAAI,CAAC,CAAC,QAAgB;EACpD,MAAM,SAAS,iBAAiB,UAAU,MAAM,eAAe,UAAU,IAAI;EAC7E,IAAI,CAAC,QACH,MAAM,KAAK,GAAG,KAAK,SAAS,IAAI,EAAE,0CAA0C;OACvE;GACL,MAAM,SAAkC,CAAC;GACzC,KAAK,MAAM,OAAO;IAChB;IACA;IACA;IACA;IACA;IACA;IACA;GACF,GAAG;IACD,MAAM,OAAOC,SAAa,QAAQ,GAAG;IACrC,IAAI,CAAC,MAAM;IACX,MAAM,QAAQ,QAAQ,KAAK,KAAK;IAChC,IAAI,UAAU,aACZ,MAAM,KAAK,IAAI,IAAI,gDAAgD;SAChE,OAAO,OAAO;GACrB;GACA,MAAM,QAAQ,QAAQ,KAAK;EAC7B;CACF,SAAS,OAAO;EACd,MAAM,KAAK,mBAAmB,KAAK,SAAS,IAAI,EAAE,IAAK,MAAgB,SAAS;CAClF;CAEA,OAAO;EAAE;EAAQ;EAAM;CAAM;AAC/B;;AAGA,SAAgB,iBAAiB,MAAc,YAAyC;CACtF,MAAM,aAAa,aACf,CAAC,KAAK,QAAQ,MAAM,UAAU,CAAC,IAC/B,aAAa,SAAS,SAAS,WAAW,KAAK,QAAQ,KAAK,KAAK,MAAM,GAAG,KAAK,GAAG,KAAK,CAAC,CAAC;CAE7F,KAAK,MAAM,QAAQ,YACjB,IAAI,GAAG,WAAW,IAAI,GAAG,OAAO,kBAAkB,GAAG,aAAa,MAAM,OAAO,GAAG,IAAI;CAExF,OAAO;EAAE,QAAQ,EAAE,GAAG,sBAAsB;EAAG,OAAO,CAAC;CAAE;AAC3D;;;;AC9KA,SAAgB,WAAW,MAAmB;CAC5C,IAAI,MAAM;CACV,IAAI,WAAW;CACf,KAAK,IAAI,IAAI,GAAG,IAAI,KAAK,QAAQ,KAAK;EACpC,MAAM,IAAI,KAAK;EACf,IAAI,UAAU;GACZ,OAAO;GACP,IAAI,MAAM,MAAM,OAAO,KAAK,EAAE,MAAM;QAC/B,IAAI,MAAM,MAAK,WAAW;EACjC,OAAO,IAAI,MAAM,MAAK;GACpB,WAAW;GACX,OAAO;EACT,OAAO,IAAI,MAAM,OAAO,KAAK,IAAI,OAAO,KAAK;GAC3C,OAAO,IAAI,KAAK,UAAU,KAAK,OAAO,MAAM;GAC5C,OAAO;EACT,OAAO,IAAI,MAAM,OAAO,KAAK,IAAI,OAAO,KAAK;GAC3C,KAAK;GACL,OAAO,IAAI,KAAK,UAAU,EAAE,KAAK,OAAO,OAAO,KAAK,IAAI,OAAO,MAAM;GACrE;EACF,OACE,OAAO;CAEX;CACA,OAAO,KAAK,MAAM,IAAI,QAAQ,gBAAgB,IAAI,CAAC;AACrD;AAQA,SAAS,WAAW,MAAkC;CACpD,IAAI,GAAG,WAAW,IAAI,KAAK,GAAG,SAAS,IAAI,CAAC,CAAC,OAAO,GAAG,OAAO;CAC9D,KAAK,MAAM,aAAa,CAAC,GAAG,KAAK,QAAQ,KAAK,KAAK,MAAM,eAAe,CAAC,GACvE,IAAI,GAAG,WAAW,SAAS,KAAK,GAAG,SAAS,SAAS,CAAC,CAAC,OAAO,GAAG,OAAO;AAG5E;;AAGA,SAAS,KAAK,MAAc,QAAQ,GAAa;CAC/C,MAAM,SAAmB,EAAE,YAAY,CAAC,EAAE;CAC1C,IAAI;CACJ,IAAI;EACF,OAAO,WAAW,GAAG,aAAa,MAAM,OAAO,CAAC;CAClD,QAAQ;EACN,OAAO;CACT;CACA,MAAM,MAAM,KAAK,QAAQ,IAAI;CAE7B,MAAM,SACJ,OAAO,KAAK,YAAY,YAAY,KAAK,QAAQ,WAAW,GAAG,KAAK,QAAQ,IACxE,WAAW,KAAK,QAAQ,KAAK,KAAK,OAAO,CAAC,IAC1C,KAAA;CACN,IAAI,QAAQ,OAAO,OAAO,QAAQ,KAAK,QAAQ,QAAQ,CAAC,CAAC;CAEzD,MAAM,UAAU,KAAK,mBAAmB,CAAC;CACzC,MAAM,SAAS,OAAO,QAAQ,WAAW,WAAW,QAAQ,OAAO,YAAY,IAAI,KAAA;CACnF,MAAM,aACJ,OAAO,QAAQ,qBAAqB,WAChC,QAAQ,iBAAiB,YAAY,IACrC,WAAW,YAAY,WAAW,aAChC,SACA,KAAA;CACR,IAAI,YAAY,OAAO,mBAAmB;CAC1C,IAAI,MAAM,QAAQ,KAAK,OAAO,GAAG,OAAO,UAAU,KAAK;CACvD,OAAO,cAAc,KAAK,cAAc,CAAC,EAAA,CACtC,KAAK,QACJ,OAAO,KAAK,SAAS,WAAW,WAAW,KAAK,QAAQ,KAAK,IAAI,IAAI,CAAC,IAAI,KAAA,CAC5E,CAAC,CACA,OAAO,OAAO;CACjB,OAAO;AACT;;;;;;AAOA,SAAgB,wBAAwB,MAA0B;CAChE,MAAM,OAAO,WAAW,KAAK,KAAK,MAAM,eAAe,CAAC;CACxD,IAAI,CAAC,MAAM,OAAO;CAElB,IAAI,WAAW,KAAK,IAAI;CACxB,IAAI,CAAC,SAAS,oBAAoB,SAAS,WAAW,SAAS,GAAG;EAEhE,MAAM,WAAW,SAAS,WAAW,KAAK,QAAQ,KAAK,GAAG,CAAC;EAC3D,WACE,SAAS,MAAM,MAAM,EAAE,SAAS,MAAM,UAAU,oBAAoB,KAAK,KAAK,CAAC,CAAC,KAChF,SAAS,MACT;CACJ;CACA,MAAM,aAAa,SAAS;CAC5B,OAAO,eAAe,YAAY,eAAe,aAAa,QAAQ;AACxE;;;;ACrDA,MAAa,cAAc;AAC3B,MAAM,YAAY,SAAiB,KAAK,QAAQ,oBAAoB,GAAG;;;;;;;;AASvE,SAAgB,gBAAgB,MAAc,UAA2B,CAAC,GAAqB;CAC7F,MAAM,eAAe,QAAQ,SAAS,EAAE,YAAY,QAAQ,OAAO,IAAI,CAAC;CACxE,MAAM,aAAa,iBAAiB,MAAM,QAAQ,MAAM;CACxD,MAAM,SAAS,QAAQ,SAAS,WAAW,SAAS,oBAAoB,MAAM,YAAY;CAG1F,MAAM,QAAQ,UAAU,MAFR,OAAO,WAAW,eAAe,SAEV,EAAE,SAAS,OAAO,QAAQ,CAAC,CAAC,CAAC,KAAK;CAEzE,MAAM,SAAS,GAAG,WAAW,KAAK,KAAK,MAAM,KAAK,CAAC,IAAI,KAAK,KAAK,MAAM,KAAK,IAAI;CAChF,MAAM,aAAa,QAAQ,SACvB,KAAK,QAAQ,MAAM,QAAQ,MAAM,IACjC,KAAK,KAAK,QAAQ,qBAAqB;CAC3C,MAAM,YAAY,KAAK,QAAQ,UAAU;CAEzC,MAAM,QAAQ,MAAM,QACjB,SACC,SAAS,cACT,CAAC,KAAK,SAAS,OAAO,KACtB,KAAK,SAAS,IAAI,MAAM,qBAC5B;CAGA,MAAM,SAAS,MAAM,KAAK,SAAS,oBAAoB,MAAM,GAAG,aAAa,MAAM,OAAO,CAAC,CAAC;CAC5F,MAAM,WAAqB,CAAC;CAC5B,KAAK,MAAM,MAAM,QACf,IAAI,IACG;OAAA,MAAM,UAAU,YAAY,EAAE,GAAG,IAAI,CAAC,SAAS,SAAS,MAAM,GAAG,SAAS,KAAK,MAAM;CAAA;CAE9F,MAAM,UAAU,OAAO,SAAS,SAAS,OAAO,UAAU;CAE1D,MAAM,eAAe;EACnB,eAAe,OAAO,iBAAiB,eAAe;EACtD;EACA,WAAW,OAAO,aAAa,eAAe;EAC9C,eAAe,OAAO,iBAAiB,eAAe;EACtD,MAAM,OAAO,QAAQ,eAAe;CACtC;CAEA,MAAM,YAAY,wBAAwB,IAAI;CAC9C,MAAM,cAAc,SAAiB;EACnC,IAAI,MAAM,KAAK,SAAS,WAAW,IAAI,CAAC,CAAC,QAAQ,OAAO,GAAG,CAAC,CAAC,QAAQ,SAAS,SAAS;EACvF,IAAI,CAAC,IAAI,WAAW,GAAG,GAAG,MAAM,OAAO;EACvC,OAAO;CACT;CAEA,MAAM,SAAS;;;CAQf,MAAM,eAAe,yBAJF,KAAK,UAAU,cAAc,MAAM,CAAC,CAAC,CAAC,QACvD,wBACA,+BAEqD,EAAE;;EAGzD,QAAQ,SAAS,IACb,0BAA0B,KAAK,UAAU,OAAO,EAAE,8DAClD;CAGJ,MAAM,aAAkD,CAAC;CACzD,MAAM,QAAkB,CAAC;CACzB,MAAM,6BAAa,IAAI,IAAY;CAEnC,IAAI;CACJ,IAAI,aAAa,MAoCf,UAAU,GAAG,OAAO;;;;;;;EAjCJ,MAAM,KAAK,MAAM,MAAM;EACrC,MAAM,KAAK,OAAO;EAClB,MAAM,OAAO,IAAI;EACjB,IAAI,CAAC,QAAQ,CAAC,IACZ,MAAM,IAAI,MACR,2CAA2C,KAAK,SAAS,MAAM,IAAI,EAAE,qFAEvE;EAEF,MAAM,QAAQ,KAAK,KAAK,UAAU,IAAI,EAAE,kBAAkB,WAAW,IAAI,EAAE;EAC3E,IAAI,aAAa,SAAS,UAAU,OAAO;EAE3C,MAAM,QAAQ,aAAa,EAAE;EAC7B,IAAI,CAAC,MAAM,IAAI;GACb,MAAM,KACJ,GAAG,KAAK,SAAS,MAAM,IAAI,EAAE,oCAAoC,MAAM,OAAO,EAChF;GACA,OAAO;EACT;EACA,IAAI,OAAO,SAAS,IAAI;EACxB,KAAK,IAAI,IAAI,GAAG,WAAW,IAAI,IAAI,GAAG,KAAK,OAAO,GAAG,SAAS,IAAI,EAAE,GAAG;EACvE,WAAW,IAAI,IAAI;EAEnB,MAAM,UAAU,MAAM,OAAO,KAAK,UAAU;GAC1C,MAAM,SAAS,KAAK,KAAK,WAAW,aAAa,GAAG,KAAK,GAAG,SAAS,MAAM,MAAM,EAAE,IAAI;GACvF,WAAW,KAAK;IACd,MAAM;IACN,SAAS,GAAG,OAAO,mBAAmB,MAAM,KAAK;GACnD,CAAC;GACD,OAAO,OAAO,KAAK,UAAU,MAAM,MAAM,EAAE,kBAAkB,WAAW,MAAM,EAAE;EAClF,CAAC;EACD,OAAO,KAAK,KAAK,UAAU,IAAI,EAAE,OAAO,QAAQ,KAAK,IAAI,EAAE;CAC7D,CAQI,CAAC,CAAC,KAAK,IAAI,EAAE;;;EAGnB,aAAa;;;;;;MAMN;EACL,MAAM,MAAM,MAAM,KAAK,GAAG,MAAM,QAAQ,GAAG;EAC3C,MAAM,WAAW,IAAI,UAAU,IAAI,IAAI,IAAI,KAAK,IAAI,EAAE,KAAK,QAAQ,IAAI,KAAK,OAAO,EAAE;EACrF,UAAU,GAAG,OAAO;EACtB,MAAM,KAAK,MAAM,MAAM,UAAU,IAAI,GAAG,SAAS,WAAW,IAAI,EAAE,GAAG,CAAC,CAAC,KAAK,IAAI,EAAE;;8BAEtD,SAAS;;;EAGrC,IAAI,KAAK,OAAO,MAAM,GAAG,UAAU,GAAG,aAAa,CAAC,CAAC,KAAK,IAAI,EAAE;;;EAGhE,aAAa;;;;;;CAMb;CAEA,MAAM,MAAM,UAAU,MAAM,OAAO,SAAS,iBAAiB,QAAQ,aAAa,aAAa,CAAC;CAChG,OAAO;EACL;EACA;EACA;EACA,SAAS,KAAK,QAAQ,KAAK,KAAK,QAAQ,iBAAiB;EACzD,YAAY,KAAK;EACjB,YAAY,WAAW;EACvB;EACA;CACF;AACF;AAEA,SAAS,eAAe,MAAc,SAAiB;CAErD,KADiB,GAAG,WAAW,IAAI,IAAI,GAAG,aAAa,MAAM,OAAO,IAAI,QACvD,SAAS;CAC1B,GAAG,UAAU,KAAK,QAAQ,IAAI,GAAG,EAAE,WAAW,KAAK,CAAC;CACpD,GAAG,cAAc,MAAM,SAAS,OAAO;AACzC;AAEA,SAAgB,qBACd,MACA,UAA2B,CAAC,GAO5B;CACA,MAAM,WAAW,gBAAgB,MAAM,OAAO;CAC9C,IAAI,SAAS,eAAe,KAAA,GAAW,eAAe,SAAS,SAAS,SAAS,UAAU;CAC3F,eAAe,SAAS,YAAY,SAAS,OAAO;CAGpD,MAAM,MAAM,KAAK,KAAK,KAAK,QAAQ,SAAS,UAAU,GAAG,WAAW;CACpE,MAAM,SAAS,IAAI,IAAI,SAAS,WAAW,KAAK,MAAM,EAAE,IAAI,CAAC;CAC7D,KAAK,MAAM,QAAQ,SAAS,YAAY,eAAe,KAAK,MAAM,KAAK,OAAO;CAC9E,IAAI,GAAG,WAAW,GAAG,GAAG;EACtB,KAAK,MAAM,SAAS,GAAG,YAAY,GAAG,GAAG;GACvC,MAAM,OAAO,KAAK,KAAK,KAAK,KAAK;GACjC,IAAI,MAAM,SAAS,KAAK,KAAK,CAAC,OAAO,IAAI,IAAI,GAAG,GAAG,OAAO,IAAI;EAChE;EACA,IAAI,GAAG,YAAY,GAAG,CAAC,CAAC,WAAW,GAAG,GAAG,UAAU,GAAG;CACxD;CAEA,OAAO;EACL,OAAO,SAAS;EAChB,YAAY,SAAS;EACrB,SAAS,SAAS;EAClB,YAAY,SAAS;EACrB,OAAO,SAAS;CAClB;AACF;AAEA,eAAsB,YAAY,UAA2B,CAAC,GAAG;CAC/D,MAAM,OAAO,QAAQ,OAAO,QAAQ,IAAI;CACxC,MAAM,QAAQ,QAAQ,SAAS;CAE/B,MAAM,mBAAmB;EACvB,IAAI;GACF,MAAM,EAAE,OAAO,YAAY,SAAS,YAAY,UAAU,qBAAqB,MAAM,OAAO;GAC5F,IAAI,OACF,QAAQ,IACN,KAAK,UACH;IACE,SAAS;IACT,OAAO,MAAM,KAAK,MAAM,KAAK,SAAS,MAAM,CAAC,CAAC;IAC9C,YAAY,KAAK,SAAS,MAAM,UAAU;IAC1C,SAAS,KAAK,SAAS,MAAM,OAAO;IACpC;GACF,GACA,MACA,CACF,CACF;QACK;IACL,IAAI,CAAC,YACH,OAAO,KAAK,0EAA0E;IAExF,OAAO,QACL,8BAA8B,MAAM,OAAO,OAAO,MAAM,WAAW,IAAI,KAAK,IAAI,EAClF;IACA,OAAO,KAAK,KAAK,KAAK,SAAS,MAAM,UAAU,GAAG;IAClD,OAAO,KAAK,KAAK,KAAK,SAAS,MAAM,OAAO,GAAG;IAC/C,KAAK,MAAM,QAAQ,OAAO,OAAO,KAAK,IAAI;GAC5C;GACA,OAAO;EACT,SAAS,KAAU;GACjB,IAAI,OACF,QAAQ,IACN,KAAK,UACH;IACE,SAAS;IACT,OAAO,IAAI,WAAW,OAAO,GAAG;GAClC,GACA,MACA,CACF,CACF;QAEA,OAAO,MAAM,sBAAsB,IAAI,WAAW,OAAO,GAAG,GAAG;GAEjE,OAAO;EACT;CACF;CAGA,IAAI,CADO,WACL,KAAK,CAAC,QAAQ,OAClB,QAAQ,KAAK,CAAC;CAGhB,IAAI,QAAQ,OAAO;EACjB,OAAO,KAAK,kDAAkD;EAC9D,qBAAqB,MAAM,SAAS,UAAU;CAChD;AACF;AAEA,MAAM,gBACJ;AACF,MAAM,cAAc;;;;;;AAOpB,SAAgB,qBACd,MACA,SACA,YACA,QAAQ,KAER,OAAkC,YAAY,OAAO,KAAK,OAAO,GACjE;CACA,MAAM,wBAAwB,IAAI,IAAI,gBAAgB,MAAM,OAAO,CAAC,CAAC,KAAK;CAC1E,IAAI,QAAQ,gBAAgB;CAC5B,IAAI,0BAAU,IAAI,IAAY;CAC9B,IAAI;CAEJ,MAAM,gBAAgB;EACpB,IAAI,OAAO,aAAa,KAAK;EAC7B,QAAQ,iBAAiB;GACvB,WAAW;GACX,IAAI;IACF,QAAQ,gBAAgB;IACxB,MAAM,WAAW,gBAAgB,MAAM,OAAO;IAC9C,0BAAU,IAAI,IAAI,CAAC,SAAS,YAAY,SAAS,OAAO,CAAC;GAC3D,QAAQ,CAER;EACF,GAAG,KAAK;CACV;CAEA,MAAM,aAAa,sBAAsB,IAAI;CAC7C,MAAM,UAAU,SAAS,MAAM,MAAM;EACnC,eAAe;EACf,UAAU,SAAiB,cAAc,KAAK,IAAI,KAAK,WAAW,KAAK,QAAQ,MAAM,IAAI,CAAC;CAC5F,CAAC;CAED,QAAQ,GAAG,QAAQ,OAAO,aAAa;EACrC,MAAM,OAAO,KAAK,QAAQ,MAAM,QAAQ;EACxC,IAAI,QAAQ,IAAI,IAAI,GAAG;EACvB,MAAM,WAAW,YAAY,KAAK,IAAI;EAEtC,IAAI,UAAU,UACR;OAAA,CAAC,MAAM,IAAI,IAAI,KAAK,CAAC,UAAU;EAAA,OAC9B,IAAI,UAAU,SAAS,UAAU,UAAU;GAChD,IAAI;GACJ,IAAI;IACF,MAAM,gBAAgB;GACxB,QAAQ;IACN;GACF;GAEA,IAAI,EADY,IAAI,SAAS,MAAM,QAAQ,CAAC,GAAG,GAAG,CAAC,CAAC,MAAM,MAAM,CAAC,MAAM,IAAI,CAAC,CAAC,MAC7D,CAAC,UAAU;EAC7B,OACE;EAGF,IAAI,IAAI,MAAM,IAAI,KAAK,SAAS,MAAM,IAAI,EAAE,0BAA0B;EACtE,QAAQ;CACV,CAAC;CAED,OAAO;AACT;;;ACjWA,eAAe,iBAAiB,MAAc,QAAsB;CAElE,MAAM,QAAQ,UAAU,MADR,OAAO,WAAW,mBACK,EAAE,SAAS,OAAO,QAAQ,CAAC;CAElE,MAAM,eAAoC,CAAC;CAC3C,MAAM,cAAwB,CAAC;CAE/B,KAAK,MAAM,QAAQ,OAAO;EACxB,MAAM,MAAM,KAAK,SAAS,MAAM,IAAI;EACpC,IAAI;GACF,MAAM,KAAK,MAAM,mBAAmB,IAAI;GACxC,IAAI,CAAC,MAAM,CAAC,GAAG,MAAM,YAAY,KAAK,GAAG;QACpC,aAAa,KAAK;IAAE;IAAK,MAAM,GAAG;IAAM;GAAG,CAAC;EACnD,QAAQ;GACN,YAAY,KAAK,GAAG;EACtB;CACF;CAEA,OAAO;EAAE;EAAc;CAAY;AACrC;;;;;AAMA,eAAsB,YAAY,MAAc,YAAuC;CACrF,MAAM,SAAS,oBAAoB,MAAM,aAAa,EAAE,WAAW,IAAI,CAAC,CAAC;CACzE,OAAO;EAAE;EAAM;EAAQ,OAAO,CAAC;EAAG,GAAI,MAAM,iBAAiB,MAAM,MAAM;CAAG;AAC9E;;;;;AAMA,eAAsB,kBAAkB,MAAc,YAAuC;CAC3F,MAAM,EAAE,QAAQ,UAAU,iBAAiB,MAAM,UAAU;CAC3D,OAAO;EAAE;EAAM;EAAQ;EAAO,GAAI,MAAM,iBAAiB,MAAM,MAAM;CAAG;AAC1E;;AAGA,MAAa,SAAS,YAAoB,YAAsB,CAAC,YAAY,GAAG,OAAO,CAAC,CAAC,KAAK,GAAG"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dialexjs/cli",
3
- "version": "0.7.0",
3
+ "version": "0.7.1",
4
4
  "description": "High-performance CLI tool for Dialex internationalization (codegen, scaffolding, CI parity checking)",
5
5
  "homepage": "https://github.com/awaiden/dialex#readme",
6
6
  "bugs": {
@@ -39,7 +39,7 @@
39
39
  "@clack/prompts": "^1.8.1",
40
40
  "chokidar": "^5.0.0",
41
41
  "commander": "^15.0.0",
42
- "dialexjs": "0.7.0",
42
+ "dialexjs": "0.7.1",
43
43
  "fast-glob": "^3.3.3",
44
44
  "ignore": "^7.0.12",
45
45
  "magicast": "^0.5.5",
@@ -1 +0,0 @@
1
- {"version":3,"file":"project-DBVeKLa3.mjs","names":["IDENTIFIER","propertyKeyName","unwrapNode","isObjectNode","unwrapNode","propertyKeyName","isObjectNode","findProperty"],"sources":["../src/utils/dictionary-edit.ts","../src/utils/files.ts","../src/utils/icu-check.ts","../src/utils/lockfile.ts","../src/analysis.ts","../src/utils/logger.ts","../src/utils/scanner.ts","../src/utils/message-arguments.ts","../src/utils/split-locales.ts","../src/utils/static-config.ts","../src/utils/tsconfig.ts","../src/commands/generate.ts","../src/utils/project.ts"],"sourcesContent":["import fs from \"node:fs\";\n\nimport { loadFile, writeFile, generateCode, parseExpression, parseModule } from \"magicast\";\n\n/**\n * AST-level helpers for reading and editing `.content.ts` dictionary files.\n *\n * Magicast's proxy layer cannot represent every value (for example template-literal\n * functions), so these helpers work on the underlying AST nodes and use Magicast only\n * to parse and print, which preserves the rest of the file's formatting.\n *\n * Supported shapes:\n * - `export default defineDictionary(\"name\", { en: {...}, tr: {...} })`\n * - `export default defineDictionary({ name: \"name\", dictionary: { ... } })`\n * - `export default { name: \"name\", dictionary: { ... } }`\n */\n\ntype Node = { type: string; [key: string]: any };\n\nexport const TODO_PREFIX = \"[TODO] \";\n\nconst IDENTIFIER = /^[A-Za-z_$][\\w$]*$/;\n\nexport interface DictionaryFile {\n file: string;\n /** Dictionary name from `defineDictionary(\"name\", ...)` or the `name` property, if literal. */\n name?: string;\n mod: Awaited<ReturnType<typeof loadFile>>;\n /** The object whose keys are locales. */\n localesObj: Node;\n /** Whether the file ended with a newline when loaded; restored on save. */\n endsWithNewline: boolean;\n /**\n * `false` when part of the dictionary cannot be read statically (spreads, computed keys, or a\n * locale whose content is not an object literal). Leaf lists and parity checks are unreliable\n * for such files.\n */\n complete: boolean;\n}\n\n/** A zero-based line/column range, as used by editors. */\nexport interface SourceRange {\n start: { line: number; column: number };\n end: { line: number; column: number };\n}\n\nexport type LeafKind = \"string\" | \"function\" | \"other\";\n\nexport interface Leaf {\n path: string[];\n kind: LeafKind;\n /** Present when `kind` is `\"string\"`. */\n value?: string;\n}\n\nfunction unwrap(node: Node): Node {\n while (\n node &&\n (node.type === \"TSAsExpression\" ||\n node.type === \"TSSatisfiesExpression\" ||\n node.type === \"ParenthesizedExpression\")\n ) {\n node = node.expression;\n }\n return node;\n}\n\nconst isObject = (node: Node) => node?.type === \"ObjectExpression\";\n\nfunction keyName(prop: Node): string | undefined {\n const key = prop?.key;\n if (!key || prop.computed) return undefined;\n if (key.type === \"Identifier\") return key.name;\n if (key.type === \"StringLiteral\" || (key.type === \"Literal\" && typeof key.value === \"string\")) {\n return key.value;\n }\n if (key.type === \"NumericLiteral\") return String(key.value);\n return undefined;\n}\n\nconst isPropLike = (p: Node) =>\n p?.type === \"ObjectProperty\" || p?.type === \"Property\" || p?.type === \"ObjectMethod\";\n\nfunction findProp(obj: Node, key: string): Node | undefined {\n return obj.properties.find((p: Node) => isPropLike(p) && keyName(p) === key);\n}\n\nfunction stringValue(node: Node): string | undefined {\n node = unwrap(node);\n if (node?.type === \"StringLiteral\") return node.value;\n if (node?.type === \"Literal\" && typeof node.value === \"string\") return node.value;\n if (node?.type === \"TemplateLiteral\" && node.expressions.length === 0) {\n return node.quasis[0]?.value?.cooked ?? undefined;\n }\n return undefined;\n}\n\nfunction leafKind(node: Node): LeafKind {\n node = unwrap(node);\n if (stringValue(node) !== undefined) return \"string\";\n if (\n node?.type === \"ArrowFunctionExpression\" ||\n node?.type === \"FunctionExpression\" ||\n node?.type === \"ObjectMethod\"\n ) {\n return \"function\";\n }\n return \"other\";\n}\n\nfunction dictionaryProp(obj: Node): Node | undefined {\n const prop = findProp(obj, \"dictionary\");\n const value = unwrap(prop?.value);\n return isObject(value) ? value : undefined;\n}\n\nfunction locateName(declaration: Node): string | undefined {\n const decl = unwrap(declaration);\n if (decl?.type === \"CallExpression\") {\n const first = unwrap(decl.arguments[0]);\n if (isObject(first)) return stringValue(findProp(first, \"name\")?.value);\n return stringValue(first);\n }\n if (isObject(decl)) return stringValue(findProp(decl, \"name\")?.value);\n return undefined;\n}\n\nfunction locateLocalesObject(declaration: Node): Node | undefined {\n const decl = unwrap(declaration);\n if (decl?.type === \"CallExpression\") {\n const first = unwrap(decl.arguments[0]);\n const second = unwrap(decl.arguments[1]);\n if (isObject(second)) return second;\n if (isObject(first)) return dictionaryProp(first);\n return undefined;\n }\n if (isObject(decl)) return dictionaryProp(decl);\n return undefined;\n}\n\n/** Quotes a property key only when it is not a valid identifier. */\nfunction keyCode(key: string): string {\n return IDENTIFIER.test(key) ? key : JSON.stringify(key);\n}\n\n/** Builds a detached `key: <value>` property node from source text. */\nfunction makeProp(key: string, valueCode: string): Node {\n const expr: Node = parseExpression(`({ ${keyCode(key)}: ${valueCode} })`);\n return expr.$ast.properties[0];\n}\n\nfunction makeStringNode(value: string): Node {\n return makeProp(\"_\", JSON.stringify(value)).value;\n}\n\n/**\n * A dictionary is statically readable when every locale is an object literal and no object on the\n * way down uses spreads or computed keys.\n */\nfunction isStaticallyComplete(localesObj: Node): boolean {\n const walk = (obj: Node): boolean =>\n obj.properties.every((prop: Node) => {\n if (!isPropLike(prop) || keyName(prop) === undefined) return false;\n if (prop.type === \"ObjectMethod\") return true;\n const value = unwrap(prop.value);\n return isObject(value) ? walk(value) : true;\n });\n\n return localesObj.properties.every((prop: Node) => {\n if (!isPropLike(prop) || keyName(prop) === undefined || prop.type === \"ObjectMethod\")\n return false;\n const value = unwrap(prop.value);\n return isObject(value) && walk(value);\n });\n}\n\n/**\n * Parses dictionary source text (for example an unsaved editor buffer). Returns `undefined` when\n * the file does not have an editable shape; throws on syntax errors.\n */\nexport function parseDictionaryText(file: string, text: string): DictionaryFile | undefined {\n const mod = parseModule(text);\n const exported: Node = (mod.exports as any).default;\n const ast: Node = exported?.$ast;\n if (!ast) return undefined;\n const declaration = ast.declaration ?? ast;\n const localesObj = locateLocalesObject(declaration);\n return localesObj\n ? {\n file,\n mod,\n localesObj,\n name: locateName(declaration),\n endsWithNewline: text.endsWith(\"\\n\"),\n complete: isStaticallyComplete(localesObj),\n }\n : undefined;\n}\n\n/** Loads a dictionary file; returns `undefined` when its shape is not editable. */\nexport async function loadDictionaryFile(file: string): Promise<DictionaryFile | undefined> {\n return parseDictionaryText(file, fs.readFileSync(file, \"utf-8\"));\n}\n\n/** The source text with all edits applied, without writing anything. */\nexport function renderDictionaryFile(df: DictionaryFile): string {\n const code = generateCode(df.mod as any).code;\n return df.endsWithNewline && !code.endsWith(\"\\n\") ? `${code}\\n` : code;\n}\n\nexport async function saveDictionaryFile(df: DictionaryFile): Promise<void> {\n await writeFile(df.mod, df.file);\n if (df.endsWithNewline) {\n const text = fs.readFileSync(df.file, \"utf-8\");\n if (!text.endsWith(\"\\n\")) fs.writeFileSync(df.file, text + \"\\n\", \"utf-8\");\n }\n}\n\nexport function listLocales(df: DictionaryFile): string[] {\n return df.localesObj.properties\n .filter(isPropLike)\n .map(keyName)\n .filter((k: string | undefined): k is string => k !== undefined);\n}\n\nfunction localeObject(df: DictionaryFile, locale: string): Node | undefined {\n const value = unwrap(findProp(df.localesObj, locale)?.value);\n return isObject(value) ? value : undefined;\n}\n\n/** Lists every leaf (string, function, or other value) of a locale, in source order. */\nexport function listLeaves(df: DictionaryFile, locale: string): Leaf[] {\n const root = localeObject(df, locale);\n if (!root) return [];\n\n const leaves: Leaf[] = [];\n const walk = (obj: Node, prefix: string[]) => {\n for (const prop of obj.properties) {\n if (!isPropLike(prop)) continue;\n const name = keyName(prop);\n if (name === undefined) continue;\n const path = [...prefix, name];\n const value = prop.type === \"ObjectMethod\" ? prop : unwrap(prop.value);\n if (isObject(value)) {\n walk(value, path);\n } else {\n const kind = leafKind(value);\n leaves.push({ path, kind, ...(kind === \"string\" ? { value: stringValue(value) } : {}) });\n }\n }\n };\n walk(root, []);\n return leaves;\n}\n\nfunction getProp(df: DictionaryFile, locale: string, path: string[]): Node | undefined {\n let obj = localeObject(df, locale);\n for (let i = 0; obj && i < path.length; i++) {\n const prop = findProp(obj, path[i]);\n if (!prop) return undefined;\n if (i === path.length - 1) return prop;\n const next = unwrap(prop.value);\n obj = isObject(next) ? next : undefined;\n }\n return undefined;\n}\n\nexport function hasPath(df: DictionaryFile, locale: string, path: string[]): boolean {\n return getProp(df, locale, path) !== undefined;\n}\n\nexport function getString(df: DictionaryFile, locale: string, path: string[]): string | undefined {\n const prop = getProp(df, locale, path);\n return prop && prop.type !== \"ObjectMethod\" ? stringValue(prop.value) : undefined;\n}\n\nfunction ensureLocale(df: DictionaryFile, locale: string): Node {\n let obj = localeObject(df, locale);\n if (!obj) {\n const prop = makeProp(locale, \"{}\");\n df.localesObj.properties.push(prop);\n obj = prop.value as Node;\n }\n return obj;\n}\n\n/** Returns the object that should contain the last path segment, creating objects as needed. */\nfunction ensureParent(df: DictionaryFile, locale: string, path: string[]): Node | undefined {\n let obj = ensureLocale(df, locale);\n for (const segment of path.slice(0, -1)) {\n let prop = findProp(obj, segment);\n if (!prop) {\n prop = makeProp(segment, \"{}\");\n obj.properties.push(prop);\n }\n const next = unwrap(prop.value);\n if (!isObject(next)) return undefined;\n obj = next;\n }\n return obj;\n}\n\nexport type SetResult = \"created\" | \"updated\" | \"skipped\";\n\n/**\n * Sets a string value at `path`. Existing function or non-string values are left alone\n * (`\"skipped\"`) because they cannot be translated as plain text.\n */\nexport function setString(\n df: DictionaryFile,\n locale: string,\n path: string[],\n value: string,\n): SetResult {\n const parent = ensureParent(df, locale, path);\n if (!parent) return \"skipped\";\n\n const last = path[path.length - 1];\n const existing = findProp(parent, last);\n if (existing) {\n if (existing.type === \"ObjectMethod\" || leafKind(existing.value) !== \"string\") {\n return \"skipped\";\n }\n existing.value = makeStringNode(value);\n return \"updated\";\n }\n parent.properties.push(makeProp(last, JSON.stringify(value)));\n return \"created\";\n}\n\n/**\n * Copies the leaf at `path` from one locale to another. String values can be rewritten with\n * `mapString` (for example to add a `[TODO]` marker); other values are copied verbatim.\n * Returns `false` when the source has no such leaf or the target already has one.\n */\nexport function copyLeaf(\n df: DictionaryFile,\n fromLocale: string,\n toLocale: string,\n path: string[],\n mapString?: (value: string) => string,\n): boolean {\n const source = getProp(df, fromLocale, path);\n if (!source || hasPath(df, toLocale, path)) return false;\n\n const parent = ensureParent(df, toLocale, path);\n if (!parent) return false;\n\n const last = path[path.length - 1];\n const text = source.type === \"ObjectMethod\" ? undefined : stringValue(source.value);\n if (text !== undefined && mapString) {\n parent.properties.push(makeProp(last, JSON.stringify(mapString(text))));\n } else {\n const code = generateCode(source as any).code;\n const expr: Node = parseExpression(`({ ${code} })`);\n parent.properties.push(expr.$ast.properties[0]);\n }\n return true;\n}\n\n/** Leaf paths of a runtime dictionary value (plain objects recurse; everything else is a leaf). */\nexport function flattenPaths(value: unknown, prefix: string[] = []): string[][] {\n if (value && typeof value === \"object\" && !Array.isArray(value)) {\n return Object.entries(value).flatMap(([k, v]) => flattenPaths(v, [...prefix, k]));\n }\n return prefix.length > 0 ? [prefix] : [];\n}\n\nconst toRange = (loc: Node | undefined): SourceRange | undefined =>\n loc\n ? {\n start: { line: loc.start.line - 1, column: loc.start.column },\n end: { line: loc.end.line - 1, column: loc.end.column },\n }\n : undefined;\n\n/**\n * Where a locale (no `path`) or a key within it is written. The range covers the property key, so\n * it is a good place to attach a diagnostic or jump to.\n */\nexport function locationOf(\n df: DictionaryFile,\n locale: string,\n path: string[] = [],\n): SourceRange | undefined {\n const prop = path.length === 0 ? findProp(df.localesObj, locale) : getProp(df, locale, path);\n return toRange((prop?.key ?? prop)?.loc);\n}\n\n/** The source text of the dictionary object itself (the object whose keys are locales). */\nexport function dictionaryLocation(df: DictionaryFile): SourceRange | undefined {\n return toRange(df.localesObj.loc);\n}\n\n/** The source code of a leaf's value (a function's source, or a string with its quotes). */\nexport function getLeafSource(\n df: DictionaryFile,\n locale: string,\n path: string[],\n): string | undefined {\n const prop = getProp(df, locale, path);\n if (!prop) return undefined;\n return generateCode((prop.type === \"ObjectMethod\" ? prop : prop.value) as any).code;\n}\n\n// AST helpers shared with the static config reader.\nexport {\n unwrap as unwrapNode,\n isObject as isObjectNode,\n keyName as propertyKeyName,\n findProp as findProperty,\n};\nexport type { Node as AstNode };\n","import fs from \"node:fs\";\nimport path from \"node:path\";\n\nimport fg from \"fast-glob\";\nimport ignore, { type Ignore } from \"ignore\";\n\n/** Folders that never hold project dictionaries or sources, in every scanner. */\nexport const BUILTIN_IGNORE = [\n \"**/node_modules/**\",\n \"**/dist/**\",\n \"**/.next/**\",\n \"**/dialex.locales/**\",\n];\n\n/** What the source scan skips on top: other tools' output, declarations, generated and config files. */\nexport const SOURCE_BUILTIN_IGNORE = [\n ...BUILTIN_IGNORE,\n \"**/.nuxt/**\",\n \"**/.output/**\",\n \"**/.svelte-kit/**\",\n \"**/.astro/**\",\n \"**/.turbo/**\",\n \"**/coverage/**\",\n \"**/graphify-out/**\",\n \"**/*.d.ts\",\n \"**/dialex.generated.*\",\n \"**/dialex.config.*\",\n \"**/i18n.config.*\",\n];\n\ninterface GitignoreScope {\n /** Absolute directory the file's patterns are relative to. */\n dir: string;\n matcher: Ignore;\n}\n\n/** The nearest directory at or above `root` that contains `.git`, or `root` itself. */\nfunction repositoryRoot(root: string): string {\n for (let dir = root; ; dir = path.dirname(dir)) {\n if (fs.existsSync(path.join(dir, \".git\"))) return dir;\n if (path.dirname(dir) === dir) return root;\n }\n}\n\nfunction readScope(dir: string): GitignoreScope | undefined {\n try {\n const text = fs.readFileSync(path.join(dir, \".gitignore\"), \"utf-8\");\n return { dir, matcher: ignore().add(text) };\n } catch {\n return undefined;\n }\n}\n\n/**\n * A function that says whether an absolute path is ignored by Git. It reads the `.gitignore`\n * files of the project folder, of every folder above it up to the repository root (monorepo\n * packages inherit the root's rules), and of nested folders.\n */\nexport function createGitignoreFilter(root: string): (absolutePath: string) => boolean {\n const base = path.resolve(root);\n const top = repositoryRoot(base);\n\n const scopes: GitignoreScope[] = [];\n for (let dir = base; ; dir = path.dirname(dir)) {\n const scope = readScope(dir);\n if (scope) scopes.push(scope);\n if (dir === top || path.dirname(dir) === dir) break;\n }\n\n const nested = fg.sync(\"**/.gitignore\", {\n cwd: base,\n absolute: true,\n dot: true,\n ignore: [\"**/node_modules/**\", \"**/.git/**\"],\n });\n for (const file of nested) {\n const dir = path.dirname(file);\n if (dir === base) continue; // already read above\n const scope = readScope(dir);\n if (scope) scopes.push(scope);\n }\n\n if (scopes.length === 0) return () => false;\n\n return (absolutePath) => {\n for (const { dir, matcher } of scopes) {\n const relative = path.relative(dir, absolutePath);\n if (!relative || relative.startsWith(\"..\") || path.isAbsolute(relative)) continue;\n if (matcher.ignores(relative.split(path.sep).join(\"/\"))) return true;\n }\n return false;\n };\n}\n\nexport interface ScanOptions {\n /** Which built-in ignore list applies. @default \"dictionary\" */\n kind?: \"dictionary\" | \"source\";\n /** `exclude` from the config: extra globs, relative to `root`. */\n exclude?: string[];\n /** More ignore globs, relative to `root` (nested projects, for example). */\n ignore?: string[];\n /** Skip what `.gitignore` files ignore. @default true */\n gitignore?: boolean;\n}\n\n/** Finds files under `root`, skipping build output, configured excludes and Git-ignored paths. */\nexport function scanFiles(\n root: string,\n patterns: string | string[],\n options: ScanOptions = {},\n): string[] {\n const builtin = options.kind === \"source\" ? SOURCE_BUILTIN_IGNORE : BUILTIN_IGNORE;\n const files = fg.sync(patterns, {\n cwd: root,\n absolute: true,\n ignore: [...builtin, ...(options.exclude ?? []), ...(options.ignore ?? [])],\n });\n if (options.gitignore === false) return files;\n const ignored = createGitignoreFilter(root);\n return files.filter((file) => !ignored(file));\n}\n","import {\n argumentSignature,\n findPlurals,\n getArguments,\n isIcuStructured,\n parseMessage,\n type IcuNode,\n} from \"dialexjs/icu\";\n\nexport interface IcuFinding {\n level: \"error\" | \"warning\";\n code: \"invalid-icu\" | \"icu-args-mismatch\" | \"icu-plural-categories\";\n locale: string;\n /** Dotted key including the dictionary name, e.g. `cart.items`. */\n key: string;\n message: string;\n}\n\n/** `locale -> dotted path within the dictionary -> string value` */\nexport type LocaleStrings = Map<string, Map<string, string>>;\n\n/** CLDR order. `resolvedOptions().pluralCategories` order differs between Node versions. */\nconst CATEGORY_ORDER = [\"zero\", \"one\", \"two\", \"few\", \"many\"];\n\nfunction requiredCategories(locale: string, ordinal: boolean): string[] {\n try {\n return new Intl.PluralRules(locale, { type: ordinal ? \"ordinal\" : \"cardinal\" })\n .resolvedOptions()\n .pluralCategories.filter((c) => c !== \"other\")\n .sort((a, b) => CATEGORY_ORDER.indexOf(a) - CATEGORY_ORDER.indexOf(b));\n } catch {\n return []; // not a valid BCP 47 tag; nothing to compare against\n }\n}\n\n/**\n * Validates ICU messages across the locales of one dictionary:\n *\n * - invalid syntax: an error for messages that clearly use ICU (plural/select/number/date/time),\n * a warning for plain `{placeholders}` that do not parse (they may not be meant as ICU);\n * - every locale must use the same arguments as the reference locale;\n * - plural options should cover the categories the locale's plural rules need.\n */\nexport function checkIcu(\n dictionary: string,\n strings: LocaleStrings,\n defaultLocale: string,\n): IcuFinding[] {\n const findings: IcuFinding[] = [];\n const parsed = new Map<string, Map<string, IcuNode[]>>();\n\n for (const [locale, entries] of strings) {\n const ok = new Map<string, IcuNode[]>();\n for (const [path, value] of entries) {\n if (!value.includes(\"{\")) continue;\n const key = `${dictionary}.${path}`;\n try {\n ok.set(path, parseMessage(value));\n } catch (error) {\n const structured = isIcuStructured(value);\n findings.push({\n level: structured ? \"error\" : \"warning\",\n code: \"invalid-icu\",\n locale,\n key,\n message: structured\n ? `Invalid ICU message \"${key}\" (${locale}): ${(error as Error).message}`\n : `\"${key}\" (${locale}) contains braces but is not valid ICU, so t() values cannot be applied: ${(error as Error).message}`,\n });\n }\n }\n parsed.set(locale, ok);\n }\n\n // Compare every locale against the reference (default locale first)\n const order = [defaultLocale, ...[...parsed.keys()].filter((l) => l !== defaultLocale)];\n const paths = new Set([...parsed.values()].flatMap((m) => [...m.keys()]));\n\n for (const path of paths) {\n const key = `${dictionary}.${path}`;\n const reference = order.find((l) => parsed.get(l)?.has(path));\n if (!reference) continue;\n const expected = argumentSignature(parsed.get(reference)!.get(path)!);\n\n for (const locale of order) {\n const nodes = parsed.get(locale)?.get(path);\n if (nodes && locale !== reference) {\n const found = argumentSignature(nodes);\n if (found !== expected) {\n findings.push({\n level: \"error\",\n code: \"icu-args-mismatch\",\n locale,\n key,\n message: `Locale \"${locale}\" uses different arguments than \"${reference}\" for \"${key}\" (expected ${expected || \"none\"}, found ${found || \"none\"})`,\n });\n }\n }\n if (!nodes) continue;\n\n for (const plural of findPlurals(nodes)) {\n const missing = requiredCategories(locale, plural.ordinal).filter(\n (c) => !(c in plural.options),\n );\n if (missing.length > 0) {\n findings.push({\n level: \"warning\",\n code: \"icu-plural-categories\",\n locale,\n key,\n message: `Locale \"${locale}\" plural \"${plural.name}\" in \"${key}\" has no ${missing.map((c) => `\"${c}\"`).join(\", \")} option (used by this language; \"other\" will be shown instead)`,\n });\n }\n }\n }\n }\n\n return findings;\n}\n\n/** Arguments of a message, or `undefined` when it does not parse. */\nexport function tryGetArguments(message: string) {\n try {\n return getArguments(parseMessage(message));\n } catch {\n return undefined;\n }\n}\n","import { createHash } from \"node:crypto\";\nimport fs from \"node:fs\";\nimport path from \"node:path\";\n\nexport const LOCK_FILE = \"dialex.lock.json\";\n\n/**\n * Records which version of the source text each translation was made from, so a later edit of the\n * source can be noticed. A translation whose source changed afterwards is *stale*.\n *\n * ```json\n * { \"version\": 1, \"sourceLocale\": \"en\", \"locales\": { \"tr\": { \"home.title\": \"a1b2c3d4\" } } }\n * ```\n *\n * The value is a short hash of the source locale's text at the time. Translations without a\n * record are untracked (for example hand-written ones) and are never reported as stale.\n */\nexport interface Lockfile {\n version: 1;\n sourceLocale?: string;\n locales: Record<string, Record<string, string>>;\n}\n\nexport const emptyLock = (sourceLocale?: string): Lockfile => ({\n version: 1,\n ...(sourceLocale ? { sourceLocale } : {}),\n locales: {},\n});\n\nexport const lockPath = (root: string) => path.join(root, LOCK_FILE);\n\n/** A short, stable fingerprint of a source string. */\nexport function hashSource(text: string): string {\n return createHash(\"sha1\").update(text).digest(\"hex\").slice(0, 8);\n}\n\n/** The lock file, or `undefined` when there is none (or it cannot be read). */\nexport function readLock(root: string): Lockfile | undefined {\n try {\n const data = JSON.parse(fs.readFileSync(lockPath(root), \"utf-8\"));\n if (data?.version !== 1 || typeof data.locales !== \"object\" || data.locales === null) {\n return undefined;\n }\n return {\n version: 1,\n ...(typeof data.sourceLocale === \"string\" ? { sourceLocale: data.sourceLocale } : {}),\n locales: data.locales,\n };\n } catch {\n return undefined;\n }\n}\n\n/** Writes the lock with sorted keys, so it produces small, stable diffs. */\nexport function writeLock(root: string, lock: Lockfile): void {\n const sorted: Lockfile = {\n version: 1,\n ...(lock.sourceLocale ? { sourceLocale: lock.sourceLocale } : {}),\n locales: Object.fromEntries(\n Object.keys(lock.locales)\n .sort()\n .map((locale) => [\n locale,\n Object.fromEntries(\n Object.entries(lock.locales[locale]).sort(([a], [b]) => a.localeCompare(b)),\n ),\n ]),\n ),\n };\n fs.writeFileSync(lockPath(root), JSON.stringify(sorted, null, 2) + \"\\n\", \"utf-8\");\n}\n\n/** Notes that `key` in `locale` was written from this source text. */\nexport function record(lock: Lockfile, locale: string, key: string, sourceText: string): void {\n (lock.locales[locale] ??= {})[key] = hashSource(sourceText);\n}\n\n/**\n * True when `key` was recorded for `locale` from different source text than `sourceText`. A key\n * with no record is not stale.\n */\nexport function isStale(lock: Lockfile, locale: string, key: string, sourceText: string): boolean {\n const recorded = lock.locales[locale]?.[key];\n return recorded !== undefined && recorded !== hashSource(sourceText);\n}\n\n/**\n * The lock to use for a run translating from `sourceLocale`. A lock written from another source\n * locale says nothing about this one, so it is replaced by a fresh one.\n */\nexport function lockFor(root: string, sourceLocale: string): { lock: Lockfile; replaced: boolean } {\n const existing = readLock(root);\n if (!existing) return { lock: emptyLock(sourceLocale), replaced: false };\n if (existing.sourceLocale && existing.sourceLocale !== sourceLocale) {\n return { lock: emptyLock(sourceLocale), replaced: true };\n }\n existing.sourceLocale = sourceLocale;\n return { lock: existing, replaced: false };\n}\n","import fs from \"node:fs\";\nimport path from \"node:path\";\nimport { pathToFileURL } from \"node:url\";\n\nimport {\n TODO_PREFIX,\n dictionaryLocation,\n flattenPaths,\n listLeaves,\n listLocales,\n loadDictionaryFile,\n locationOf,\n type DictionaryFile,\n type SourceRange,\n} from \"./utils/dictionary-edit.js\";\nimport { scanFiles } from \"./utils/files.js\";\nimport { checkIcu, type LocaleStrings } from \"./utils/icu-check.js\";\nimport { isStale, readLock } from \"./utils/lockfile.js\";\n\n/**\n * Project analysis shared by `dialex check` and the editor extension.\n *\n * It reads dictionaries from the syntax tree, so it never runs project code. Dictionaries that\n * cannot be read that way (spreads, computed keys, imported values) are skipped with an `info`\n * issue, unless `runtime: true` is passed, in which case they are imported and read from the\n * evaluated module (the CLI does this; editors must not).\n */\n\nexport type IssueLevel = \"error\" | \"warning\" | \"info\";\n\nexport type IssueCode =\n | \"invalid-dictionary\"\n | \"unanalyzable\"\n | \"missing-locale\"\n | \"missing-key\"\n | \"invalid-locale\"\n | \"todo-placeholder\"\n | \"stale-translation\"\n | \"invalid-icu\"\n | \"icu-args-mismatch\"\n | \"icu-plural-categories\"\n | \"unknown-dictionary\"\n | \"unknown-path\"\n | \"unused-key\"\n | \"unused-dictionary\";\n\nexport interface AnalysisIssue {\n /** Absolute path of the file the issue is in. */\n file: string;\n level: IssueLevel;\n code: IssueCode;\n message: string;\n /** Where to point, when known. Lines and columns are zero-based. */\n range?: SourceRange;\n /** The dictionary the issue is about, when it is about one. */\n dictionary?: string;\n locale?: string;\n /** Key path within the dictionary. */\n path?: string[];\n /** For `missing-key`: a locale that has the key, to copy it from. */\n sourceLocale?: string;\n}\n\nexport interface AnalysisConfig {\n defaultLocale?: string;\n locales?: string[];\n include?: string | string[];\n exclude?: string[];\n}\n\nexport interface AnalysisOptions {\n root: string;\n config: AnalysisConfig;\n /** Source globs to scan for dictionary references. Pass `[]` to skip scanning. */\n src?: string[];\n /** Import dictionaries the syntax tree cannot fully describe. Runs project code. */\n runtime?: boolean;\n /** Extra ignore globs, relative to `root`. */\n ignore?: string[];\n /** Report possibly unused keys and dictionaries. @default true */\n unused?: boolean;\n /** Report translations whose source text changed since `dialex.lock.json` recorded them. @default true */\n lock?: boolean;\n}\n\nexport interface LeafInfo {\n kind: \"string\" | \"function\" | \"other\";\n value?: string;\n}\n\nexport interface AnalyzedDictionary {\n name: string;\n /** Absolute path. */\n file: string;\n /** Locales in source order. */\n locales: string[];\n /** `locale -> dotted path -> leaf` */\n leaves: Map<string, Map<string, LeafInfo>>;\n /** Union of dotted leaf paths across locales, in order of first appearance. */\n paths: string[];\n /** The parsed file, present when it was read statically. */\n df?: DictionaryFile;\n}\n\nexport interface AnalysisResult {\n issues: AnalysisIssue[];\n dictionaries: AnalyzedDictionary[];\n /** Absolute paths of every dictionary file that matched. */\n files: string[];\n sourceFilesScanned: number;\n}\n\nexport const DEFAULT_SOURCE_GLOB = \"**/*.{ts,tsx,js,jsx,mjs,cjs,vue,svelte,astro,mdx}\";\n\n/** `getDictionary(\"x\")`, `useDictionary(\"x\")`, `@DialexDictionary(\"x\")` */\nconst DICTIONARY_CALL =\n /\\b(?:getDictionary|useDictionary|DialexDictionary)\\(\\s*([\"'`])([^\"'`$\\n]+)\\1/dg;\n/** `t(\"dictionary.path.to.key\")` */\nconst T_CALL = /(?<![\\w$.])t\\(\\s*([\"'`])([\\w-]+(?:\\.[\\w-]+)+)\\1/dg;\n\nexport interface Reference {\n /** A dictionary name, or a full `dictionary.key.path`. */\n kind: \"dictionary\" | \"path\";\n value: string;\n /** Offsets of the string's contents (without the quotes) in the scanned text. */\n start: number;\n end: number;\n}\n\n/** Finds `getDictionary(\"x\")`-style and `t(\"x.y.z\")` references in source text. */\nexport function scanReferences(text: string): Reference[] {\n const references: Reference[] = [];\n const collect = (pattern: RegExp, kind: Reference[\"kind\"]) => {\n for (const match of text.matchAll(pattern)) {\n const [start, end] = match.indices![2] as [number, number];\n references.push({ kind, value: match[2], start, end });\n }\n };\n collect(DICTIONARY_CALL, \"dictionary\");\n collect(T_CALL, \"path\");\n return references.sort((a, b) => a.start - b.start);\n}\n\nfunction lineStarts(text: string): number[] {\n const starts = [0];\n for (let i = 0; i < text.length; i++) if (text.charCodeAt(i) === 10) starts.push(i + 1);\n return starts;\n}\n\nfunction positionAt(starts: number[], offset: number) {\n let low = 0;\n let high = starts.length - 1;\n while (low < high) {\n const mid = Math.ceil((low + high) / 2);\n if (starts[mid] <= offset) low = mid;\n else high = mid - 1;\n }\n return { line: low, column: offset - starts[low] };\n}\n\ninterface DictionaryData {\n name: string;\n locales: string[];\n leaves: Map<string, Map<string, LeafInfo>>;\n df?: DictionaryFile;\n}\n\ntype Loaded =\n | { ok: true; data: DictionaryData }\n | { ok: false; level: IssueLevel; code: IssueCode; message: string };\n\nfunction fromSyntaxTree(df: DictionaryFile): DictionaryData {\n const locales = listLocales(df);\n const leaves = new Map<string, Map<string, LeafInfo>>();\n for (const locale of locales) {\n const entries = new Map<string, LeafInfo>();\n for (const leaf of listLeaves(df, locale)) {\n entries.set(leaf.path.join(\".\"), { kind: leaf.kind, value: leaf.value });\n }\n leaves.set(locale, entries);\n }\n return { name: df.name!, locales, leaves, df };\n}\n\nasync function fromRuntime(file: string): Promise<Loaded> {\n try {\n const mod = await import(`${pathToFileURL(file).href}?t=${Date.now()}_${Math.random()}`);\n const definition = mod.default || mod;\n if (!definition || typeof definition !== \"object\" || !definition.dictionary) {\n return {\n ok: false,\n level: \"error\",\n code: \"invalid-dictionary\",\n message: \"Default export does not appear to be a valid defineDictionary output.\",\n };\n }\n\n const dictionary = definition.dictionary as Record<string, Record<string, any>>;\n const leaves = new Map<string, Map<string, LeafInfo>>();\n const invalid: string[] = [];\n\n for (const [locale, content] of Object.entries(dictionary)) {\n if (!content || typeof content !== \"object\") {\n invalid.push(locale);\n continue;\n }\n const entries = new Map<string, LeafInfo>();\n for (const leafPath of flattenPaths(content)) {\n let value: any = content;\n for (const segment of leafPath) value = value?.[segment];\n entries.set(\n leafPath.join(\".\"),\n typeof value === \"string\"\n ? { kind: \"string\", value }\n : { kind: typeof value === \"function\" ? \"function\" : \"other\" },\n );\n }\n leaves.set(locale, entries);\n }\n\n if (invalid.length > 0) {\n return {\n ok: false,\n level: \"error\",\n code: \"invalid-locale\",\n message: invalid.map((l) => `Locale \"${l}\" content is empty or invalid.`).join(\"\\n\"),\n };\n }\n\n return {\n ok: true,\n data: { name: String(definition.name ?? \"\"), locales: [...leaves.keys()], leaves },\n };\n } catch (error: any) {\n return {\n ok: false,\n level: \"error\",\n code: \"invalid-dictionary\",\n message: `Failed to import dictionary: ${error.message || String(error)}`,\n };\n }\n}\n\nasync function loadDictionaryData(file: string, runtime: boolean): Promise<Loaded> {\n let astError: Error | undefined;\n try {\n const df = await loadDictionaryFile(file);\n if (df?.complete && df.name) return { ok: true, data: fromSyntaxTree(df) };\n } catch (error) {\n astError = error as Error;\n }\n\n if (runtime) return fromRuntime(file);\n\n return astError\n ? {\n ok: false,\n level: \"error\",\n code: \"invalid-dictionary\",\n message: `Failed to parse dictionary: ${astError.message}`,\n }\n : {\n ok: false,\n level: \"info\",\n code: \"unanalyzable\",\n message:\n \"This dictionary uses spreads, computed keys, imported values, or a computed name, so it cannot be analyzed statically.\",\n };\n}\n\nexport async function analyzeProject(options: AnalysisOptions): Promise<AnalysisResult> {\n const { root, config } = options;\n const include = config.include || \"**/*.content.ts\";\n const configuredLocales = config.locales || [];\n const defaultLocale = config.defaultLocale || \"en\";\n const extraIgnore = options.ignore ?? [];\n\n const files = scanFiles(root, include, { exclude: config.exclude, ignore: extraIgnore });\n\n const issues: AnalysisIssue[] = [];\n const dictionaries: AnalyzedDictionary[] = [];\n const lock = options.lock === false ? undefined : readLock(root);\n\n // 1. Dictionaries: parity, placeholders, ICU\n for (const file of files) {\n const loaded = await loadDictionaryData(file, options.runtime === true);\n if (!loaded.ok) {\n for (const message of loaded.message.split(\"\\n\")) {\n issues.push({ file, level: loaded.level, code: loaded.code, message });\n }\n continue;\n }\n\n const { data } = loaded;\n const { df } = data;\n const at = (locale?: string, keyPath?: string[]) =>\n df && locale ? locationOf(df, locale, keyPath) : undefined;\n const add = (issue: Omit<AnalysisIssue, \"file\" | \"dictionary\">) =>\n issues.push({ ...issue, file, dictionary: data.name });\n\n for (const required of configuredLocales) {\n if (!data.locales.includes(required)) {\n add({\n level: \"error\",\n code: \"missing-locale\",\n message: `Missing configured locale \"${required}\"`,\n range: df ? dictionaryLocation(df) : undefined,\n locale: required,\n });\n }\n }\n\n const paths: string[] = [];\n const seen = new Set<string>();\n for (const locale of data.locales) {\n for (const leafPath of data.leaves.get(locale)!.keys()) {\n if (!seen.has(leafPath)) {\n seen.add(leafPath);\n paths.push(leafPath);\n }\n }\n }\n\n for (const locale of data.locales) {\n const present = data.leaves.get(locale)!;\n for (const leafPath of paths) {\n if (present.has(leafPath)) continue;\n const sourceLocale = [defaultLocale, ...data.locales].find(\n (l) => l !== locale && data.leaves.get(l)?.has(leafPath),\n );\n add({\n level: \"error\",\n code: \"missing-key\",\n message: `Locale \"${locale}\" is missing key \"${leafPath}\"`,\n range: at(locale),\n locale,\n path: leafPath.split(\".\"),\n sourceLocale,\n });\n }\n }\n\n const strings: LocaleStrings = new Map();\n for (const locale of data.locales) {\n const entries = new Map<string, string>();\n strings.set(locale, entries);\n for (const [leafPath, leaf] of data.leaves.get(locale)!) {\n if (leaf.kind !== \"string\" || leaf.value === undefined) continue;\n entries.set(leafPath, leaf.value);\n if (leaf.value.startsWith(TODO_PREFIX)) {\n add({\n level: \"warning\",\n code: \"todo-placeholder\",\n message: `Locale \"${locale}\" key \"${leafPath}\" still has a ${TODO_PREFIX.trim()} placeholder`,\n range: at(locale, leafPath.split(\".\")),\n locale,\n path: leafPath.split(\".\"),\n });\n }\n }\n }\n\n // Translations made from source text that has changed since (see dialex.lock.json)\n const sourceLeaves = lock?.sourceLocale ? data.leaves.get(lock.sourceLocale) : undefined;\n if (lock && sourceLeaves) {\n for (const locale of data.locales) {\n if (locale === lock.sourceLocale) continue;\n for (const [leafPath, leaf] of data.leaves.get(locale)!) {\n if (leaf.kind !== \"string\" || leaf.value === undefined) continue;\n if (leaf.value.startsWith(TODO_PREFIX)) continue;\n const source = sourceLeaves.get(leafPath);\n if (source?.kind !== \"string\" || source.value === undefined) continue;\n if (!isStale(lock, locale, `${data.name}.${leafPath}`, source.value)) continue;\n add({\n level: \"warning\",\n code: \"stale-translation\",\n message: `Locale \"${locale}\" key \"${leafPath}\" is out of date: the \"${lock.sourceLocale}\" text changed after it was translated`,\n range: at(locale, leafPath.split(\".\")),\n locale,\n path: leafPath.split(\".\"),\n sourceLocale: lock.sourceLocale,\n });\n }\n }\n }\n\n for (const finding of checkIcu(data.name, strings, defaultLocale)) {\n const keyPath = finding.key.slice(data.name.length + 1).split(\".\");\n add({\n level: finding.level,\n code: finding.code,\n message: finding.message,\n range: at(finding.locale, keyPath),\n locale: finding.locale,\n path: keyPath,\n });\n }\n\n dictionaries.push({\n name: data.name,\n file,\n locales: data.locales,\n leaves: data.leaves,\n paths,\n df,\n });\n }\n\n // 2. Source code: references to dictionaries and keys\n const known = new Map(dictionaries.map((d) => [d.name, d]));\n const dictionaryFiles = new Set(files);\n const sourceGlobs = options.src ?? [DEFAULT_SOURCE_GLOB];\n const sourceFiles =\n sourceGlobs.length === 0\n ? []\n : scanFiles(root, sourceGlobs, {\n kind: \"source\",\n exclude: config.exclude,\n ignore: extraIgnore,\n }).filter((f) => !dictionaryFiles.has(f));\n\n if (sourceFiles.length > 0) {\n const tokens = new Set<string>();\n\n for (const file of sourceFiles) {\n let text: string;\n try {\n text = fs.readFileSync(file, \"utf-8\");\n } catch {\n continue;\n }\n for (const token of text.match(/[\\w$-]+/g) ?? []) tokens.add(token);\n\n const starts = lineStarts(text);\n const rangeOf = (start: number, end: number): SourceRange => ({\n start: positionAt(starts, start),\n end: positionAt(starts, end),\n });\n\n for (const ref of scanReferences(text)) {\n if (ref.kind === \"dictionary\") {\n if (!known.has(ref.value)) {\n issues.push({\n file,\n level: \"error\",\n code: \"unknown-dictionary\",\n message: `Unknown dictionary \"${ref.value}\"`,\n range: rangeOf(ref.start, ref.end),\n dictionary: ref.value,\n });\n }\n continue;\n }\n\n const [name, ...rest] = ref.value.split(\".\");\n const dictionary = known.get(name);\n if (!dictionary) continue; // `t(...)` may belong to another library\n const keyPath = rest.join(\".\");\n const exists = dictionary.paths.some((p) => p === keyPath || p.startsWith(`${keyPath}.`));\n if (!exists) {\n issues.push({\n file,\n level: \"error\",\n code: \"unknown-path\",\n message: `Unknown translation path \"${ref.value}\"`,\n range: rangeOf(ref.start, ref.end),\n dictionary: name,\n path: rest,\n });\n }\n }\n }\n\n // 3. Possibly unused dictionaries and keys (heuristic: warnings only)\n if (options.unused !== false) {\n for (const dictionary of dictionaries) {\n if (!tokens.has(dictionary.name)) {\n issues.push({\n file: dictionary.file,\n level: \"warning\",\n code: \"unused-dictionary\",\n message: `Dictionary \"${dictionary.name}\" is never referenced`,\n range: dictionary.df ? dictionaryLocation(dictionary.df) : undefined,\n dictionary: dictionary.name,\n });\n continue;\n }\n for (const keyPath of dictionary.paths) {\n const last = keyPath.split(\".\").pop()!;\n if (tokens.has(last)) continue;\n const holder = dictionary.locales.find((l) => dictionary.leaves.get(l)?.has(keyPath));\n issues.push({\n file: dictionary.file,\n level: \"warning\",\n code: \"unused-key\",\n message: `Key \"${keyPath}\" is possibly unused`,\n range:\n dictionary.df && holder\n ? locationOf(dictionary.df, holder, keyPath.split(\".\"))\n : undefined,\n dictionary: dictionary.name,\n path: keyPath.split(\".\"),\n });\n }\n }\n }\n }\n\n return { issues, dictionaries, files, sourceFilesScanned: sourceFiles.length };\n}\n\n/** Project root-relative path with forward slashes, for display. */\nexport function relativeFile(root: string, file: string): string {\n return path.relative(root, file);\n}\n","import pc from \"picocolors\";\n\nexport const logger = {\n info: (msg: string) => console.log(pc.blue(\"ℹ \") + msg),\n success: (msg: string) => console.log(pc.green(\"✔ \") + pc.bold(msg)),\n warn: (msg: string) => console.warn(pc.yellow(\"⚠ \") + msg),\n error: (msg: string) => console.error(pc.red(\"✖ \") + pc.bold(msg)),\n log: (msg: string) => console.log(msg),\n};\n","import fs from \"node:fs\";\nimport path from \"node:path\";\n\nimport { DEFAULT_CONFIG, type DialexConfig } from \"dialexjs\";\nimport { loadConfigSync } from \"unconfig\";\n\nexport function resolveDialexConfig(root: string, inlineConfig: DialexConfig = {}): DialexConfig {\n let loadedConfig: DialexConfig = {};\n try {\n const sources: any[] = [];\n if (inlineConfig.configFile) {\n sources.push({ files: inlineConfig.configFile });\n }\n sources.push(\n {\n files: \"dialex.config\",\n extensions: [\"ts\", \"mts\", \"cts\", \"js\", \"mjs\", \"cjs\", \"json\", \"\"],\n },\n {\n files: \"i18n.config\",\n extensions: [\"ts\", \"mts\", \"cts\", \"js\", \"mjs\", \"cjs\", \"json\", \"\"],\n },\n );\n\n const result = loadConfigSync<DialexConfig>({\n sources,\n merge: false,\n defaults: {},\n cwd: root,\n });\n if (result && result.config) {\n loadedConfig = result.config;\n }\n } catch {\n // Config fallback\n }\n\n return {\n ...DEFAULT_CONFIG,\n ...loadedConfig,\n ...inlineConfig,\n };\n}\n\n/** Every adapter entry point that has its own `DictionaryRegistry` to augment. */\nexport const REGISTRY_ADAPTERS = [\n \"react\",\n \"server\",\n \"hono\",\n \"express\",\n \"fastify\",\n \"koa\",\n \"nestjs\",\n \"elysia\",\n \"sveltekit\",\n \"astro\",\n \"vue\",\n \"web\",\n \"h3\",\n \"angular\",\n] as const;\n\n/** Dependencies that tell which `dialexjs/*` entry points a project can import. */\nconst ADAPTER_DEPENDENCIES: Record<string, string[]> = {\n react: [\"react\"],\n \"react-dom\": [\"react\"],\n next: [\"react\", \"server\"],\n hono: [\"hono\"],\n express: [\"express\"],\n fastify: [\"fastify\"],\n koa: [\"koa\"],\n \"@nestjs/core\": [\"nestjs\"],\n \"@nestjs/common\": [\"nestjs\"],\n elysia: [\"elysia\"],\n \"@sveltejs/kit\": [\"sveltekit\"],\n astro: [\"astro\"],\n vue: [\"vue\"],\n nuxt: [\"vue\", \"h3\"],\n h3: [\"h3\"],\n nitropack: [\"h3\"],\n \"@angular/core\": [\"angular\"],\n // Frameworks that hand you a standard `Request`, served by `dialexjs/web`.\n \"react-router\": [\"web\"],\n \"react-router-dom\": [\"web\"],\n \"@remix-run/react\": [\"web\"],\n \"@remix-run/node\": [\"web\"],\n \"@tanstack/react-start\": [\"web\"],\n \"@solidjs/start\": [\"web\"],\n wrangler: [\"web\"],\n};\n\n/**\n * The adapter entry points to augment for a project, read from its `package.json`. Falls back to\n * all of them when nothing is recognised, so types never silently go missing.\n */\nexport function detectAdapters(root: string): string[] {\n try {\n const pkg = JSON.parse(fs.readFileSync(path.join(root, \"package.json\"), \"utf-8\"));\n const deps = { ...pkg.dependencies, ...pkg.devDependencies, ...pkg.peerDependencies };\n const found = new Set<string>();\n for (const name of Object.keys(deps)) {\n for (const adapter of ADAPTER_DEPENDENCIES[name] ?? []) found.add(adapter);\n }\n if (found.size > 0) return REGISTRY_ADAPTERS.filter((adapter) => found.has(adapter));\n } catch {\n // no readable package.json\n }\n return [...REGISTRY_ADAPTERS];\n}\n\n/**\n * The `dialex-env.d.ts` a project should have: its path and contents, or `undefined` when there\n * are no dictionary files. Nothing is written.\n */\nexport function renderDts(\n root: string,\n files: string[],\n locales?: string[],\n messageArguments: Record<string, string> = {},\n): { path: string; content: string } | undefined {\n if (files.length === 0) return undefined;\n\n const dtsDir = fs.existsSync(path.join(root, \"src\")) ? path.join(root, \"src\") : root;\n const imports: string[] = [];\n const records: string[] = [];\n\n files.forEach((file, index) => {\n let relPath = path.relative(dtsDir, file).replace(/\\\\/g, \"/\");\n relPath = relPath.replace(/\\.ts$/, \"\");\n if (!relPath.startsWith(\".\")) {\n relPath = \"./\" + relPath;\n }\n\n imports.push(`import dict${index} from '${relPath}';`);\n records.push(\n `Record<typeof dict${index}['name'], typeof dict${index}['dictionary'][keyof typeof dict${index}['dictionary']]>`,\n );\n });\n\n const localesType =\n locales && locales.length > 0 ? locales.map((l) => `\"${l}\"`).join(\" | \") : \"string\";\n\n const registry = records.join(\",\\n \");\n const messageEntries = Object.entries(messageArguments)\n .sort(([a], [b]) => a.localeCompare(b))\n .map(([key, type]) => ` ${JSON.stringify(key)}: ${type};`)\n .join(\"\\n\");\n const adapterBlocks = detectAdapters(root)\n .map(\n (adapter) => `\ndeclare module 'dialexjs/${adapter}' {\n export interface DictionaryRegistry extends ${registry} {}\n}\n`,\n )\n .join(\"\");\n\n const dtsContent = `/* eslint-disable */\n// @ts-nocheck\n// Generated by dialex\n${imports.join(\"\\n\")}\n\ndeclare module 'dialexjs' {\n export interface Register {\n locales: ${localesType};\n }\n export interface DictionaryRegistry extends ${records.join(\",\\n \")} {}\n export interface MessageArguments {${messageEntries ? `\\n${messageEntries}\\n ` : \"\"}}\n}\n${adapterBlocks}\n`;\n\n return { path: path.join(dtsDir, \"dialex-env.d.ts\"), content: dtsContent };\n}\n\nexport function generateDts(root: string, files: string[], locales?: string[]) {\n const dts = renderDts(root, files, locales);\n if (!dts) return;\n const existing = fs.existsSync(dts.path) ? fs.readFileSync(dts.path, \"utf-8\") : \"\";\n if (existing !== dts.content) {\n fs.mkdirSync(path.dirname(dts.path), { recursive: true });\n fs.writeFileSync(dts.path, dts.content, \"utf-8\");\n }\n}\n","import { getArguments, parseMessage, type IcuArgument } from \"dialexjs/icu\";\n\nimport { listLeaves, listLocales, type DictionaryFile } from \"./dictionary-edit.js\";\n\nconst IDENTIFIER = /^[A-Za-z_$][\\w$]*$/;\n\n/**\n * The TypeScript type of one ICU argument. A name can appear more than once (in a `plural` and as\n * a plain `{name}`, say); the narrowest use wins, because that is the value the message needs.\n */\nfunction typeOfArgument(uses: IcuArgument[]): string {\n if (uses.some((u) => u.type === \"plural\" || u.type === \"selectordinal\" || u.type === \"number\")) {\n return \"number\";\n }\n if (uses.some((u) => u.type === \"date\" || u.type === \"time\")) return \"Date | number\";\n const select = uses.find((u) => u.type === \"select\");\n if (select) {\n const options = (select.selectors ?? []).filter((s) => s !== \"other\");\n return options.length > 0\n ? `${options.map((o) => JSON.stringify(o)).join(\" | \")} | (string & {})`\n : \"string\";\n }\n return \"string | number | boolean | Date\";\n}\n\n/** `{ count: number; name: string | number | boolean | Date }` for the arguments of one message. */\nexport function messageType(message: string): string | undefined {\n if (!message.includes(\"{\")) return undefined;\n let args: IcuArgument[];\n try {\n args = getArguments(parseMessage(message));\n } catch {\n return undefined; // not valid ICU; `dx check` reports it\n }\n if (args.length === 0) return undefined;\n\n const byName = new Map<string, IcuArgument[]>();\n for (const arg of args) byName.set(arg.name, [...(byName.get(arg.name) ?? []), arg]);\n const members = [...byName].map(\n ([name, uses]) =>\n `${IDENTIFIER.test(name) ? name : JSON.stringify(name)}: ${typeOfArgument(uses)}`,\n );\n return `{ ${members.join(\"; \")} }`;\n}\n\n/**\n * `dictionary.key.path` to the type of its ICU values, read from each dictionary's reference\n * locale (the default locale when the dictionary has it, otherwise its first). Other locales must\n * use the same arguments, which `dx check` verifies.\n */\nexport function messageArguments(\n dictionaries: (DictionaryFile | undefined)[],\n defaultLocale: string,\n): Record<string, string> {\n const result: Record<string, string> = {};\n for (const df of dictionaries) {\n if (!df?.name) continue;\n const locales = listLocales(df);\n const reference = locales.includes(defaultLocale) ? defaultLocale : locales[0];\n if (!reference) continue;\n for (const leaf of listLeaves(df, reference)) {\n if (leaf.kind !== \"string\" || leaf.value === undefined) continue;\n const type = messageType(leaf.value);\n if (type) result[`${df.name}.${leaf.path.join(\".\")}`] = type;\n }\n }\n return result;\n}\n","import { generateCode } from \"magicast\";\n\nimport {\n isObjectNode,\n propertyKeyName,\n unwrapNode,\n type AstNode,\n type DictionaryFile,\n} from \"./dictionary-edit.js\";\n\nexport interface LocaleSlice {\n locale: string;\n /** Source of the locale's object, ready for `export default <code>`. */\n code: string;\n}\n\nexport type SplitResult = { ok: true; slices: LocaleSlice[] } | { ok: false; reason: string };\n\nconst SKIPPED_KEYS = new Set([\n \"loc\",\n \"start\",\n \"end\",\n \"extra\",\n \"range\",\n \"comments\",\n \"leadingComments\",\n \"trailingComments\",\n \"innerComments\",\n \"tokens\",\n]);\n\n/** Every identifier name used in a node, except property names that are not variable references. */\nfunction usedNames(node: unknown, found = new Set<string>()): Set<string> {\n if (!node || typeof node !== \"object\") return found;\n if (Array.isArray(node)) {\n node.forEach((child) => usedNames(child, found));\n return found;\n }\n const ast = node as AstNode;\n if (ast.type === \"Identifier\") found.add(ast.name);\n\n for (const key of Object.keys(ast)) {\n if (SKIPPED_KEYS.has(key)) continue;\n const isPropertyName =\n key === \"key\" &&\n !ast.computed &&\n [\"ObjectProperty\", \"ObjectMethod\", \"TSPropertySignature\", \"TSMethodSignature\"].includes(\n ast.type,\n );\n const isMemberName =\n key === \"property\" &&\n !ast.computed &&\n (ast.type === \"MemberExpression\" || ast.type === \"OptionalMemberExpression\");\n if (isPropertyName || isMemberName) continue;\n usedNames(ast[key], found);\n }\n return found;\n}\n\n/** Names bound anywhere in a pattern (`const { a, b: [c] } = ...`). */\nfunction patternNames(pattern: AstNode | undefined, found: Set<string>) {\n if (!pattern) return;\n switch (pattern.type) {\n case \"Identifier\":\n found.add(pattern.name);\n break;\n case \"ObjectPattern\":\n for (const prop of pattern.properties) patternNames(prop.value ?? prop.argument, found);\n break;\n case \"ArrayPattern\":\n for (const element of pattern.elements) patternNames(element ?? undefined, found);\n break;\n case \"AssignmentPattern\":\n patternNames(pattern.left, found);\n break;\n case \"RestElement\":\n patternNames(pattern.argument, found);\n break;\n }\n}\n\n/** What the file declares or imports at the top level: a locale that uses any of it cannot move. */\nfunction topLevelNames(df: DictionaryFile): Set<string> {\n const names = new Set<string>();\n const program: AstNode = (df.mod as any).$ast;\n const statements: AstNode[] = program?.body ?? program?.program?.body ?? [];\n for (const raw of statements) {\n const statement =\n raw.type === \"ExportNamedDeclaration\" && raw.declaration ? raw.declaration : raw;\n switch (statement.type) {\n case \"ImportDeclaration\":\n for (const specifier of statement.specifiers) names.add(specifier.local.name);\n break;\n case \"VariableDeclaration\":\n for (const declarator of statement.declarations) patternNames(declarator.id, names);\n break;\n case \"FunctionDeclaration\":\n case \"ClassDeclaration\":\n case \"TSInterfaceDeclaration\":\n case \"TSTypeAliasDeclaration\":\n case \"TSEnumDeclaration\":\n if (statement.id?.name) names.add(statement.id.name);\n break;\n }\n }\n return names;\n}\n\n/**\n * Cuts a dictionary into one self-contained piece per locale, for `lazy: \"locale\"`.\n *\n * A piece moves to its own file, so it must not depend on anything else in the original file.\n * That is checked conservatively: if a locale uses any name the file imports or declares (even one\n * that is only shadowed), the whole file is left alone. A missed split costs bytes; a wrong split\n * would break the app.\n */\nexport function splitLocales(df: DictionaryFile): SplitResult {\n if (!df.complete) {\n return { ok: false, reason: \"it uses spreads, computed keys or non-literal locale values\" };\n }\n\n const bound = topLevelNames(df);\n const slices: LocaleSlice[] = [];\n\n for (const prop of df.localesObj.properties as AstNode[]) {\n const locale = propertyKeyName(prop);\n const value = unwrapNode(prop.value);\n if (locale === undefined || !isObjectNode(value)) {\n return { ok: false, reason: \"a locale is not an object literal\" };\n }\n const clash = [...usedNames(value)].find((name) => bound.has(name));\n if (clash) {\n return {\n ok: false,\n reason: `\"${locale}\" uses \"${clash}\", which is defined elsewhere in the file`,\n };\n }\n slices.push({ locale, code: generateCode(value as any).code });\n }\n\n if (slices.length === 0) return { ok: false, reason: \"it defines no locales\" };\n return { ok: true, slices };\n}\n","import fs from \"node:fs\";\nimport path from \"node:path\";\n\nimport { parseModule } from \"magicast\";\n\nimport {\n findProperty,\n isObjectNode,\n propertyKeyName,\n unwrapNode,\n type AstNode,\n} from \"./dictionary-edit.js\";\n\n/**\n * The parts of `dialex.config` that tooling needs, read **without running the file**. Editors must\n * not execute workspace code (it may be untrusted), so values are read from the syntax tree and\n * only literals are understood.\n */\nexport interface StaticConfig {\n defaultLocale: string;\n locales: string[];\n include: string | string[];\n exclude: string[];\n fallbacks: Record<string, string[]>;\n prefixDefault: boolean;\n lazy: boolean | \"locale\";\n}\n\nexport interface StaticConfigResult {\n config: StaticConfig;\n /** The file the values came from, if any. */\n file?: string;\n /** Things that could not be read statically, for example `locales: getLocales()`. */\n notes: string[];\n}\n\nconst CONFIG_NAMES = [\"dialex.config\", \"i18n.config\"];\nconst EXTENSIONS = [\"ts\", \"mts\", \"cts\", \"js\", \"mjs\", \"cjs\", \"json\"];\n\nexport const DEFAULT_STATIC_CONFIG: StaticConfig = {\n defaultLocale: \"en\",\n locales: [],\n include: \"**/*.content.ts\",\n exclude: [],\n fallbacks: {},\n prefixDefault: true,\n lazy: false,\n};\n\nconst NOT_LITERAL = Symbol(\"not literal\");\n\nfunction literal(node: AstNode | undefined): unknown {\n node = unwrapNode(node as AstNode);\n switch (node?.type) {\n case \"StringLiteral\":\n case \"NumericLiteral\":\n case \"BooleanLiteral\":\n return node.value;\n case \"Literal\":\n return node.value;\n case \"TemplateLiteral\":\n return node.expressions.length === 0 ? (node.quasis[0]?.value?.cooked ?? \"\") : NOT_LITERAL;\n case \"ArrayExpression\": {\n const items = node.elements.map((e: AstNode) => literal(e));\n return items.includes(NOT_LITERAL) ? NOT_LITERAL : items;\n }\n case \"ObjectExpression\": {\n const result: Record<string, unknown> = {};\n for (const prop of node.properties) {\n const key = propertyKeyName(prop);\n const value = key === undefined ? NOT_LITERAL : literal(prop.value);\n if (value === NOT_LITERAL) return NOT_LITERAL;\n result[key as string] = value;\n }\n return result;\n }\n default:\n return NOT_LITERAL;\n }\n}\n\n/** The object literal passed to `defineConfig({...})`, or exported directly. */\nfunction findConfigObject(declaration: AstNode): AstNode | undefined {\n const node = unwrapNode(declaration);\n if (node?.type === \"CallExpression\") return findConfigObject(node.arguments[0]);\n return isObjectNode(node) ? node : undefined;\n}\n\nconst isStringArray = (value: unknown): value is string[] =>\n Array.isArray(value) && value.every((v) => typeof v === \"string\");\n\nfunction apply(object: Record<string, unknown>, config: StaticConfig, notes: string[]) {\n const accept = <K extends keyof StaticConfig>(\n key: K,\n valid: (value: unknown) => boolean,\n expected: string,\n ) => {\n if (!(key in object)) return;\n const value = object[key];\n if (valid(value)) (config as any)[key] = value;\n else notes.push(`\"${key}\" could not be read statically (expected ${expected}).`);\n };\n\n accept(\"defaultLocale\", (v) => typeof v === \"string\" && v !== \"\", \"a string literal\");\n accept(\"locales\", isStringArray, \"an array of string literals\");\n accept(\n \"include\",\n (v) => typeof v === \"string\" || isStringArray(v),\n \"a string or array of strings\",\n );\n accept(\"exclude\", isStringArray, \"an array of string literals\");\n accept(\n \"fallbacks\",\n (v) =>\n typeof v === \"object\" && v !== null && Object.values(v).every((list) => isStringArray(list)),\n \"an object of string arrays\",\n );\n accept(\"prefixDefault\", (v) => typeof v === \"boolean\", \"true or false\");\n accept(\"lazy\", (v) => typeof v === \"boolean\" || v === \"locale\", 'true, false or \"locale\"');\n}\n\n/** Reads a config file's source text. Exposed for tests and for unsaved buffers. */\nexport function parseStaticConfig(text: string, file = \"dialex.config.ts\"): StaticConfigResult {\n const notes: string[] = [];\n const config: StaticConfig = { ...DEFAULT_STATIC_CONFIG };\n\n if (file.endsWith(\".json\")) {\n try {\n const data = JSON.parse(text);\n if (data && typeof data === \"object\") apply(data, config, notes);\n } catch (error) {\n notes.push(`Could not parse ${path.basename(file)}: ${(error as Error).message}`);\n }\n return { config, file, notes };\n }\n\n try {\n const exported = (parseModule(text).exports as any).default;\n const object = findConfigObject(exported?.$ast?.declaration ?? exported?.$ast);\n if (!object) {\n notes.push(`${path.basename(file)} does not export a config object literal.`);\n } else {\n const values: Record<string, unknown> = {};\n for (const key of [\n \"defaultLocale\",\n \"locales\",\n \"include\",\n \"exclude\",\n \"fallbacks\",\n \"prefixDefault\",\n \"lazy\",\n ]) {\n const prop = findProperty(object, key);\n if (!prop) continue;\n const value = literal(prop.value);\n if (value === NOT_LITERAL)\n notes.push(`\"${key}\" could not be read statically (not a literal).`);\n else values[key] = value;\n }\n apply(values, config, notes);\n }\n } catch (error) {\n notes.push(`Could not parse ${path.basename(file)}: ${(error as Error).message}`);\n }\n\n return { config, file, notes };\n}\n\n/** Reads `dialex.config.*` (or `i18n.config.*`) from `root`, or from `configFile` if given. */\nexport function readStaticConfig(root: string, configFile?: string): StaticConfigResult {\n const candidates = configFile\n ? [path.resolve(root, configFile)]\n : CONFIG_NAMES.flatMap((name) => EXTENSIONS.map((ext) => path.join(root, `${name}.${ext}`)));\n\n for (const file of candidates) {\n if (fs.existsSync(file)) return parseStaticConfig(fs.readFileSync(file, \"utf-8\"), file);\n }\n return { config: { ...DEFAULT_STATIC_CONFIG }, notes: [] };\n}\n","import fs from \"node:fs\";\nimport path from \"node:path\";\n\n/** Parses tsconfig-style JSON: comments and trailing commas are allowed. */\nexport function parseJsonc(text: string): any {\n let out = \"\";\n let inString = false;\n for (let i = 0; i < text.length; i++) {\n const c = text[i];\n if (inString) {\n out += c;\n if (c === \"\\\\\") out += text[++i] ?? \"\";\n else if (c === '\"') inString = false;\n } else if (c === '\"') {\n inString = true;\n out += c;\n } else if (c === \"/\" && text[i + 1] === \"/\") {\n while (i < text.length && text[i] !== \"\\n\") i++;\n out += \"\\n\";\n } else if (c === \"/\" && text[i + 1] === \"*\") {\n i += 2;\n while (i < text.length && !(text[i] === \"*\" && text[i + 1] === \"/\")) i++;\n i++;\n } else {\n out += c;\n }\n }\n return JSON.parse(out.replace(/,(\\s*[}\\]])/g, \"$1\"));\n}\n\ninterface Resolved {\n moduleResolution?: string;\n include?: string[];\n references: string[];\n}\n\nfunction configFile(from: string): string | undefined {\n if (fs.existsSync(from) && fs.statSync(from).isFile()) return from;\n for (const candidate of [`${from}.json`, path.join(from, \"tsconfig.json\")]) {\n if (fs.existsSync(candidate) && fs.statSync(candidate).isFile()) return candidate;\n }\n return undefined;\n}\n\n/** `moduleResolution` and `include` of a tsconfig, following relative `extends`. */\nfunction read(file: string, depth = 0): Resolved {\n const result: Resolved = { references: [] };\n let json: any;\n try {\n json = parseJsonc(fs.readFileSync(file, \"utf-8\"));\n } catch {\n return result;\n }\n const dir = path.dirname(file);\n\n const parent =\n typeof json.extends === \"string\" && json.extends.startsWith(\".\") && depth < 5\n ? configFile(path.resolve(dir, json.extends))\n : undefined;\n if (parent) Object.assign(result, read(parent, depth + 1));\n\n const options = json.compilerOptions ?? {};\n const module = typeof options.module === \"string\" ? options.module.toLowerCase() : undefined;\n const resolution =\n typeof options.moduleResolution === \"string\"\n ? options.moduleResolution.toLowerCase()\n : module === \"node16\" || module === \"nodenext\"\n ? module\n : undefined;\n if (resolution) result.moduleResolution = resolution;\n if (Array.isArray(json.include)) result.include = json.include;\n result.references = (json.references ?? [])\n .map((ref: any) =>\n typeof ref?.path === \"string\" ? configFile(path.resolve(dir, ref.path)) : undefined,\n )\n .filter(Boolean) as string[];\n return result;\n}\n\n/**\n * The extension for relative imports in generated files. TypeScript's `node16`/`nodenext` need\n * `./x.js`; bundlers (webpack, Vite) resolve extensionless imports, and webpack cannot map `.js`\n * to a `.ts` file. Without any tsconfig it is plain Node ESM, which needs the extension.\n */\nexport function relativeImportExtension(root: string): \".js\" | \"\" {\n const file = configFile(path.join(root, \"tsconfig.json\"));\n if (!file) return \".js\";\n\n let resolved = read(file);\n if (!resolved.moduleResolution && resolved.references.length > 0) {\n // A \"solution\" tsconfig: use the referenced project that covers src/.\n const projects = resolved.references.map((ref) => read(ref));\n resolved =\n projects.find((p) => p.include?.some((entry) => /^(\\.\\/)?src(\\/|$)/.test(entry))) ??\n projects[0] ??\n resolved;\n }\n const resolution = resolved.moduleResolution;\n return resolution === \"node16\" || resolution === \"nodenext\" ? \".js\" : \"\";\n}\n","import fs from \"node:fs\";\nimport path from \"node:path\";\n\nimport chokidar from \"chokidar\";\nimport { DEFAULT_CONFIG } from \"dialexjs\";\n\nimport { listLocales, parseDictionaryText } from \"../utils/dictionary-edit.js\";\nimport { createGitignoreFilter, scanFiles } from \"../utils/files.js\";\nimport { logger } from \"../utils/logger.js\";\nimport { messageArguments } from \"../utils/message-arguments.js\";\nimport { resolveDialexConfig, renderDts } from \"../utils/scanner.js\";\nimport { splitLocales } from \"../utils/split-locales.js\";\nimport { readStaticConfig } from \"../utils/static-config.js\";\nimport { relativeImportExtension } from \"../utils/tsconfig.js\";\n\nexport interface GenerateOptions {\n cwd?: string;\n watch?: boolean;\n output?: string;\n config?: string;\n json?: boolean;\n /**\n * Read `dialex.config.*` from its syntax tree instead of running it, so no project code\n * executes (used by the editor extension). Settings that are not literals fall back to defaults.\n */\n static?: boolean;\n}\n\nexport interface RenderedGenerate {\n /** Absolute paths of the dictionary files, sorted. */\n files: string[];\n /** Where `dialex.generated.ts` goes, and what it should contain. */\n outputPath: string;\n content: string;\n /** Where `dialex-env.d.ts` goes, and what it should contain (absent without dictionaries). */\n dtsPath: string;\n dtsContent?: string;\n /** The config file that was read, if there is one. Without it every default applies. */\n configFile?: string;\n /** Per-locale modules for `lazy: \"locale\"`, written next to the generated file. */\n extraFiles: { path: string; content: string }[];\n /** Things worth telling the user, such as a dictionary that could not be split by locale. */\n notes: string[];\n}\n\n/** The folder, next to `dialex.generated.ts`, that holds the per-locale modules. */\nexport const LOCALES_DIR = \"dialex.locales\";\nconst safeName = (text: string) => text.replace(/[^A-Za-z0-9._-]/g, \"_\");\n\n/**\n * Works out `dialex.generated.ts` and `dialex-env.d.ts` for a project without writing anything,\n * so `check` can tell whether they are up to date.\n *\n * Settings come from `dialex.config.*` and fall back to {@link DEFAULT_CONFIG}; `locales` falls\n * back to the locales the dictionaries define.\n */\nexport function renderGenerated(root: string, options: GenerateOptions = {}): RenderedGenerate {\n const inlineConfig = options.config ? { configFile: options.config } : {};\n const staticRead = readStaticConfig(root, options.config);\n const config = options.static ? staticRead.config : resolveDialexConfig(root, inlineConfig);\n const include = config.include || DEFAULT_CONFIG.include;\n\n const found = scanFiles(root, include, { exclude: config.exclude }).sort();\n\n const srcDir = fs.existsSync(path.join(root, \"src\")) ? path.join(root, \"src\") : root;\n const outputPath = options.output\n ? path.resolve(root, options.output)\n : path.join(srcDir, \"dialex.generated.ts\");\n const outputDir = path.dirname(outputPath);\n // A broad `include` (like `src/**/*.ts`) would otherwise match the files generated here\n const files = found.filter(\n (file) =>\n file !== outputPath &&\n !file.endsWith(\".d.ts\") &&\n path.basename(file) !== \"dialex.generated.ts\",\n );\n\n // Read each dictionary's name and locales from its syntax tree; project code is never run.\n const parsed = files.map((file) => parseDictionaryText(file, fs.readFileSync(file, \"utf-8\")));\n const inferred: string[] = [];\n for (const df of parsed) {\n if (df)\n for (const locale of listLocales(df)) if (!inferred.includes(locale)) inferred.push(locale);\n }\n const locales = config.locales?.length ? config.locales : inferred;\n\n const clientConfig = {\n defaultLocale: config.defaultLocale || DEFAULT_CONFIG.defaultLocale,\n locales,\n fallbacks: config.fallbacks ?? DEFAULT_CONFIG.fallbacks,\n prefixDefault: config.prefixDefault ?? DEFAULT_CONFIG.prefixDefault,\n lazy: config.lazy ?? DEFAULT_CONFIG.lazy,\n };\n\n const extension = relativeImportExtension(root);\n const importPath = (file: string) => {\n let rel = path.relative(outputDir, file).replace(/\\\\/g, \"/\").replace(/\\.ts$/, extension);\n if (!rel.startsWith(\".\")) rel = \"./\" + rel;\n return rel;\n };\n\n const header = `// Auto-generated by dialex CLI. Do not edit directly.\n/* eslint-disable */\n// @ts-nocheck`;\n // \"locale\" must stay a literal type, or `<DialexProvider {...dialex}>` would not type-check\n const configJson = JSON.stringify(clientConfig, null, 2).replace(\n '\"lazy\": \"locale\"',\n '\"lazy\": \"locale\" as const',\n );\n const configExport = `export const config = ${configJson};\n\n${\n locales.length > 0\n ? `export const locales = ${JSON.stringify(locales)} as const;\\nexport type Locale = (typeof locales)[number];`\n : \"export const locales: readonly string[] = [];\\nexport type Locale = string;\"\n}`;\n\n const extraFiles: { path: string; content: string }[] = [];\n const notes: string[] = [];\n const takenNames = new Set<string>();\n\n let content: string;\n if (clientConfig.lazy) {\n // Only dynamic imports, so bundlers can split each dictionary (or, with \"locale\", each\n // locale of it) into its own chunk.\n const loaders = files.map((file, i) => {\n const df = parsed[i];\n const name = df?.name;\n if (!name || !df) {\n throw new Error(\n `Cannot determine the dictionary name of ${path.relative(root, file)} for lazy loading. ` +\n 'Use defineDictionary(\"name\", ...) or a literal `name` property.',\n );\n }\n const whole = ` ${JSON.stringify(name)}: () => import(\"${importPath(file)}\"),`;\n if (clientConfig.lazy !== \"locale\") return whole;\n\n const split = splitLocales(df);\n if (!split.ok) {\n notes.push(\n `${path.relative(root, file)} is loaded whole, not per locale: ${split.reason}.`,\n );\n return whole;\n }\n let base = safeName(name);\n for (let n = 2; takenNames.has(base); n++) base = `${safeName(name)}-${n}`;\n takenNames.add(base);\n\n const entries = split.slices.map((slice) => {\n const target = path.join(outputDir, LOCALES_DIR, `${base}.${safeName(slice.locale)}.ts`);\n extraFiles.push({\n path: target,\n content: `${header}\\nexport default ${slice.code};\\n`,\n });\n return ` ${JSON.stringify(slice.locale)}: () => import(\"${importPath(target)}\"),`;\n });\n return ` ${JSON.stringify(name)}: {\\n${entries.join(\"\\n\")}\\n },`;\n });\n content = `${header}\n\nexport const dictionaries = [];\n\nexport const dictionaryMap = {};\n\nexport const loaders = {\n${loaders.join(\"\\n\")}\n};\n\n${configExport}\n\nexport const dialex = { dictionaries, config, loaders };\n\nexport default dictionaries;\n`;\n } else {\n const ids = files.map((_, i) => `dict_${i}`);\n const dictList = ids.length <= 1 ? `[${ids.join(\", \")}]` : `[\\n ${ids.join(\",\\n \")}\\n]`;\n content = `${header}\n${files.map((file, i) => `import ${ids[i]} from \"${importPath(file)}\";`).join(\"\\n\")}\n\nexport const dictionaries = ${dictList};\n\nexport const dictionaryMap = {\n${ids.map((id) => ` [${id}.name]: ${id}.dictionary,`).join(\"\\n\")}\n};\n\n${configExport}\n\nexport const dialex = { dictionaries, config };\n\nexport default dictionaries;\n`;\n }\n\n const dts = renderDts(root, files, locales, messageArguments(parsed, clientConfig.defaultLocale));\n return {\n files,\n outputPath,\n content,\n dtsPath: dts?.path ?? path.join(srcDir, \"dialex-env.d.ts\"),\n dtsContent: dts?.content,\n configFile: staticRead.file,\n extraFiles,\n notes,\n };\n}\n\nfunction writeIfChanged(file: string, content: string) {\n const existing = fs.existsSync(file) ? fs.readFileSync(file, \"utf-8\") : \"\";\n if (existing === content) return;\n fs.mkdirSync(path.dirname(file), { recursive: true });\n fs.writeFileSync(file, content, \"utf-8\");\n}\n\nexport function generateDictionaries(\n root: string,\n options: GenerateOptions = {},\n): {\n files: string[];\n outputPath: string;\n dtsPath: string;\n configFile?: string;\n notes: string[];\n} {\n const rendered = renderGenerated(root, options);\n if (rendered.dtsContent !== undefined) writeIfChanged(rendered.dtsPath, rendered.dtsContent);\n writeIfChanged(rendered.outputPath, rendered.content);\n\n // Per-locale modules, and no leftovers from dictionaries or locales that are gone\n const dir = path.join(path.dirname(rendered.outputPath), LOCALES_DIR);\n const wanted = new Set(rendered.extraFiles.map((f) => f.path));\n for (const file of rendered.extraFiles) writeIfChanged(file.path, file.content);\n if (fs.existsSync(dir)) {\n for (const entry of fs.readdirSync(dir)) {\n const full = path.join(dir, entry);\n if (entry.endsWith(\".ts\") && !wanted.has(full)) fs.rmSync(full);\n }\n if (fs.readdirSync(dir).length === 0) fs.rmdirSync(dir);\n }\n\n return {\n files: rendered.files,\n outputPath: rendered.outputPath,\n dtsPath: rendered.dtsPath,\n configFile: rendered.configFile,\n notes: rendered.notes,\n };\n}\n\nexport async function runGenerate(options: GenerateOptions = {}) {\n const root = options.cwd || process.cwd();\n const quiet = options.json === true;\n\n const doGenerate = () => {\n try {\n const { files, outputPath, dtsPath, configFile, notes } = generateDictionaries(root, options);\n if (quiet) {\n console.log(\n JSON.stringify(\n {\n success: true,\n files: files.map((f) => path.relative(root, f)),\n outputPath: path.relative(root, outputPath),\n dtsPath: path.relative(root, dtsPath),\n notes,\n },\n null,\n 2,\n ),\n );\n } else {\n if (!configFile) {\n logger.info(\"No dialex.config.* found, using defaults (run `dialex init` to add one).\");\n }\n logger.success(\n `Generated dictionaries for ${files.length} file${files.length === 1 ? \"\" : \"s\"}:`,\n );\n logger.info(`→ ${path.relative(root, outputPath)}`);\n logger.info(`→ ${path.relative(root, dtsPath)}`);\n for (const note of notes) logger.info(note);\n }\n return true;\n } catch (err: any) {\n if (quiet) {\n console.log(\n JSON.stringify(\n {\n success: false,\n error: err.message || String(err),\n },\n null,\n 2,\n ),\n );\n } else {\n logger.error(`Generation failed: ${err.message || String(err)}`);\n }\n return false;\n }\n };\n\n const ok = doGenerate();\n if (!ok && !options.watch) {\n process.exit(1);\n }\n\n if (options.watch) {\n logger.info(\"Watching for dictionary changes (-w, --watch)...\");\n startGenerateWatcher(root, options, doGenerate);\n }\n}\n\nconst WATCH_IGNORED =\n /(^|[\\\\/])(node_modules|dist|\\.next|\\.nuxt|\\.output|\\.turbo|\\.git|dialex\\.locales)([\\\\/]|$)/;\nconst CONFIG_FILE = /(^|[\\\\/])(dialex|i18n)\\.config\\.[cm]?[jt]s(on)?$/;\n\n/**\n * Regenerates when a dictionary or config file is added, edited or removed. chokidar 4+ no longer\n * understands globs, so this watches the project directory and decides for itself which events\n * matter, using the same `include` glob as `generate`.\n */\nexport function startGenerateWatcher(\n root: string,\n options: GenerateOptions,\n regenerate: () => void,\n delay = 100,\n) {\n const dictionaryFiles = () => new Set(renderGenerated(root, options).files);\n let known = dictionaryFiles();\n let outputs = new Set<string>();\n let timer: ReturnType<typeof setTimeout> | undefined;\n\n const trigger = () => {\n if (timer) clearTimeout(timer);\n timer = setTimeout(() => {\n regenerate();\n try {\n known = dictionaryFiles();\n const rendered = renderGenerated(root, options);\n outputs = new Set([rendered.outputPath, rendered.dtsPath]);\n } catch {\n // keep the previous list; the next event tries again\n }\n }, delay);\n };\n\n const gitIgnored = createGitignoreFilter(root);\n const watcher = chokidar.watch(root, {\n ignoreInitial: true,\n ignored: (file: string) => WATCH_IGNORED.test(file) || gitIgnored(path.resolve(root, file)),\n });\n\n watcher.on(\"all\", (event, filePath) => {\n const file = path.resolve(root, filePath);\n if (outputs.has(file)) return; // our own output\n const isConfig = CONFIG_FILE.test(file);\n\n if (event === \"change\") {\n if (!known.has(file) && !isConfig) return;\n } else if (event === \"add\" || event === \"unlink\") {\n let now: Set<string>;\n try {\n now = dictionaryFiles();\n } catch {\n return;\n }\n const changed = now.size !== known.size || [...now].some((f) => !known.has(f));\n if (!changed && !isConfig) return;\n } else {\n return;\n }\n\n logger.info(`[${event}] ${path.relative(root, file)} changed, regenerating...`);\n trigger();\n });\n\n return watcher;\n}\n","import path from \"node:path\";\n\nimport type { DialexConfig } from \"dialexjs\";\n\nimport { loadDictionaryFile, type DictionaryFile } from \"./dictionary-edit.js\";\nimport { scanFiles } from \"./files.js\";\nimport { resolveDialexConfig } from \"./scanner.js\";\nimport { readStaticConfig } from \"./static-config.js\";\n\nexport interface ProjectDictionary {\n /** Path relative to the project root. */\n rel: string;\n name: string;\n df: DictionaryFile;\n}\n\nexport interface Project {\n root: string;\n config: DialexConfig;\n dictionaries: ProjectDictionary[];\n /** Dictionary files that could not be parsed into an editable shape. */\n unsupported: string[];\n /** Config values that could not be read statically (static loading only). */\n notes: string[];\n}\n\nasync function loadDictionaries(root: string, config: DialexConfig) {\n const include = config.include || \"**/*.content.ts\";\n const files = scanFiles(root, include, { exclude: config.exclude });\n\n const dictionaries: ProjectDictionary[] = [];\n const unsupported: string[] = [];\n\n for (const file of files) {\n const rel = path.relative(root, file);\n try {\n const df = await loadDictionaryFile(file);\n if (!df || !df.name) unsupported.push(rel);\n else dictionaries.push({ rel, name: df.name, df });\n } catch {\n unsupported.push(rel); // syntax error: reported by the analysis, nothing to edit here\n }\n }\n\n return { dictionaries, unsupported };\n}\n\n/**\n * Resolves the config (running `dialex.config.*` through the loader, which executes it) and loads\n * every dictionary file for AST-level reading and editing.\n */\nexport async function loadProject(root: string, configFile?: string): Promise<Project> {\n const config = resolveDialexConfig(root, configFile ? { configFile } : {});\n return { root, config, notes: [], ...(await loadDictionaries(root, config)) };\n}\n\n/**\n * Like `loadProject`, but reads the config from the syntax tree without executing it. Use this in\n * editors and anywhere project code must not run.\n */\nexport async function loadStaticProject(root: string, configFile?: string): Promise<Project> {\n const { config, notes } = readStaticConfig(root, configFile);\n return { root, config, notes, ...(await loadDictionaries(root, config)) };\n}\n\n/** `home` + `[\"nav\", \"about\"]` -> `home.nav.about` */\nexport const toKey = (dictionary: string, keyPath: string[]) => [dictionary, ...keyPath].join(\".\");\n"],"mappings":"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"}