@verbaly/compiler 0.22.0 → 0.23.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -312,5 +312,25 @@ interface RenderSiteResult {
312
312
  }
313
313
  declare function renderSite(cfg: ResolvedConfig, options?: RenderSiteOptions): Promise<RenderSiteResult>;
314
314
  //#endregion
315
- export { type Alternate, type Analysis, type AnalyzeOptions, type Catalog, type Catalogs, type CheckResult, type ClaudeProviderOptions, type DoctorEntry, type DoctorResult, type ExchangeFormat, type ExportFormat, type ExportOptions, type ExportResult, type ExportedFile, type ImportOptions, type ImportResult, type InitOptions, type InitResult, LOCALE_MODULE_PREFIX, MessageRegistry, type MissingEntry, type MobileFormat, PSEUDO_LOCALE, type ParamType, type PluginOptions, RESOLVED_VIRTUAL_ID, type RenderConfig, type RenderHtmlOptions, type RenderHtmlResult, type RenderSiteOptions, type RenderSiteResult, type ResolvedConfig, type RuntimeModuleOptions, SFC_FILE_RE, SOURCE_FILE_RE, type SyncResult, type TaggedMessage, type TaggedParam, type TransComponent, type TransformResult, type TranslateConfig, type TranslateOptions, type TranslateProvider, type TranslateRequest, type TranslateResult, type UnknownEntry, type UsedKey, VIRTUAL_ID, type VerbalyConfig, analyze, analyzeFile, analyzeSfc, catalogPath, check, claudeProvider, collectParams, detectBundler, doctor, exportCatalogs, extractProject, findConfigFile, formatCheckResult, generateDts, generateLocaleModule, generateRuntimeModule, importCatalogs, init, isMobileFormat, isTransformTarget, loadCatalogs, loadConfig, loadConfigFile, loadVirtualModule, parseExchangeFile, pruneCatalogs, pseudoCatalogs, pseudoLocalize, readCatalog, renderHtml, renderParamType, renderSite, resolveConfig, resolveVirtualId, runBuildGate, serializeCatalog, stableKey, structureMatches, syncCatalogs, targetLocales, transformCode, transformSource, translateCatalogs, writeCatalog, writeDts };
315
+ //#region src/status.d.ts
316
+ interface LocaleStatus {
317
+ locale: string;
318
+ translated: number;
319
+ total: number;
320
+ }
321
+ interface StatusResult {
322
+ messages: number;
323
+ source: string;
324
+ locales: LocaleStatus[];
325
+ }
326
+ declare function status(cfg: ResolvedConfig, catalogs: Catalogs, registry: MessageRegistry): StatusResult;
327
+ declare function formatStatusResult(result: StatusResult): string;
328
+ //#endregion
329
+ //#region src/watch.d.ts
330
+ interface WatchProjectOptions {
331
+ debounce?: number;
332
+ }
333
+ declare function watchProject(cfg: ResolvedConfig, run: () => Promise<void>, options?: WatchProjectOptions): () => void;
334
+ //#endregion
335
+ export { type Alternate, type Analysis, type AnalyzeOptions, type Catalog, type Catalogs, type CheckResult, type ClaudeProviderOptions, type DoctorEntry, type DoctorResult, type ExchangeFormat, type ExportFormat, type ExportOptions, type ExportResult, type ExportedFile, type ImportOptions, type ImportResult, type InitOptions, type InitResult, LOCALE_MODULE_PREFIX, type LocaleStatus, MessageRegistry, type MissingEntry, type MobileFormat, PSEUDO_LOCALE, type ParamType, type PluginOptions, RESOLVED_VIRTUAL_ID, type RenderConfig, type RenderHtmlOptions, type RenderHtmlResult, type RenderSiteOptions, type RenderSiteResult, type ResolvedConfig, type RuntimeModuleOptions, SFC_FILE_RE, SOURCE_FILE_RE, type StatusResult, type SyncResult, type TaggedMessage, type TaggedParam, type TransComponent, type TransformResult, type TranslateConfig, type TranslateOptions, type TranslateProvider, type TranslateRequest, type TranslateResult, type UnknownEntry, type UsedKey, VIRTUAL_ID, type VerbalyConfig, type WatchProjectOptions, analyze, analyzeFile, analyzeSfc, catalogPath, check, claudeProvider, collectParams, detectBundler, doctor, exportCatalogs, extractProject, findConfigFile, formatCheckResult, formatStatusResult, generateDts, generateLocaleModule, generateRuntimeModule, importCatalogs, init, isMobileFormat, isTransformTarget, loadCatalogs, loadConfig, loadConfigFile, loadVirtualModule, parseExchangeFile, pruneCatalogs, pseudoCatalogs, pseudoLocalize, readCatalog, renderHtml, renderParamType, renderSite, resolveConfig, resolveVirtualId, runBuildGate, serializeCatalog, stableKey, status, structureMatches, syncCatalogs, targetLocales, transformCode, transformSource, translateCatalogs, watchProject, writeCatalog, writeDts };
316
336
  //# sourceMappingURL=index.d.ts.map
package/dist/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import { parse } from "@babel/parser";
2
2
  import { createHash } from "node:crypto";
3
- import { existsSync, mkdirSync, readFileSync, readdirSync, rmSync, writeFileSync } from "node:fs";
3
+ import { existsSync, mkdirSync, readFileSync, readdirSync, rmSync, watch, writeFileSync } from "node:fs";
4
4
  import { basename, dirname, join, relative, resolve } from "node:path";
5
5
  import { RICH_TAGS, createVerbaly, parse as parse$1, parseTags, safeHref } from "verbaly";
6
6
  import { pathToFileURL } from "node:url";
@@ -409,8 +409,13 @@ function serializeCatalog(catalog) {
409
409
  }
410
410
  function writeCatalog(cfg, locale, catalog) {
411
411
  const serialized = serializeCatalog(catalog);
412
- mkdirSync(cfg.dir, { recursive: true });
413
- writeFileSync(catalogPath(cfg, locale), serialized);
412
+ const path = catalogPath(cfg, locale);
413
+ try {
414
+ if (readFileSync(path, "utf8") === serialized) return serialized;
415
+ } catch {
416
+ mkdirSync(cfg.dir, { recursive: true });
417
+ }
418
+ writeFileSync(path, serialized);
414
419
  return serialized;
415
420
  }
416
421
  //#endregion
@@ -1757,6 +1762,82 @@ function decodeEntities(text) {
1757
1762
  return text.replace(/&quot;/g, "\"").replace(/&#39;/g, "'").replace(/&lt;/g, "<").replace(/&gt;/g, ">").replace(/&amp;/g, "&");
1758
1763
  }
1759
1764
  //#endregion
1760
- export { LOCALE_MODULE_PREFIX, MessageRegistry, PSEUDO_LOCALE, RESOLVED_VIRTUAL_ID, SFC_FILE_RE, SOURCE_FILE_RE, VIRTUAL_ID, analyze, analyzeFile, analyzeSfc, catalogPath, check, claudeProvider, collectParams, detectBundler, doctor, exportCatalogs, extractProject, findConfigFile, formatCheckResult, generateDts, generateLocaleModule, generateRuntimeModule, importCatalogs, init, isMobileFormat, isTransformTarget, loadCatalogs, loadConfig, loadConfigFile, loadVirtualModule, parseExchangeFile, pruneCatalogs, pseudoCatalogs, pseudoLocalize, readCatalog, renderHtml, renderParamType, renderSite, resolveConfig, resolveVirtualId, runBuildGate, serializeCatalog, stableKey, structureMatches, syncCatalogs, targetLocales, transformCode, transformSource, translateCatalogs, writeCatalog, writeDts };
1765
+ //#region src/status.ts
1766
+ function status(cfg, catalogs, registry) {
1767
+ const source = catalogs[cfg.sourceLocale] ?? {};
1768
+ const needed = /* @__PURE__ */ new Set([...registry.messages().keys(), ...Object.keys(source)]);
1769
+ const locales = [];
1770
+ for (const locale of cfg.locales) {
1771
+ if (locale === cfg.sourceLocale) continue;
1772
+ let translated = 0;
1773
+ for (const key of needed) if (catalogs[locale]?.[key]) translated += 1;
1774
+ locales.push({
1775
+ locale,
1776
+ translated,
1777
+ total: needed.size
1778
+ });
1779
+ }
1780
+ return {
1781
+ messages: needed.size,
1782
+ source: cfg.sourceLocale,
1783
+ locales
1784
+ };
1785
+ }
1786
+ function formatStatusResult(result) {
1787
+ const lines = [`[verbaly] ${result.messages} messages · source: ${result.source}`];
1788
+ if (result.locales.length === 0) {
1789
+ lines.push(" no target locales (add locales to your config)");
1790
+ return lines.join("\n");
1791
+ }
1792
+ for (const { locale, translated, total } of result.locales) {
1793
+ const pct = total === 0 ? 100 : Math.floor(translated / total * 100);
1794
+ const mark = translated === total ? " ✓" : "";
1795
+ lines.push(` ${locale}: ${translated}/${total} translated (${pct}%)${mark}`);
1796
+ }
1797
+ return lines.join("\n");
1798
+ }
1799
+ //#endregion
1800
+ //#region src/watch.ts
1801
+ function watchProject(cfg, run, options = {}) {
1802
+ const catalogDir = relative(cfg.root, cfg.dir).replaceAll("\\", "/");
1803
+ let timer;
1804
+ let running = false;
1805
+ let queued = false;
1806
+ async function refresh() {
1807
+ if (running) {
1808
+ queued = true;
1809
+ return;
1810
+ }
1811
+ running = true;
1812
+ try {
1813
+ await run();
1814
+ } catch (error) {
1815
+ console.warn("[verbaly] watch run failed:", error);
1816
+ } finally {
1817
+ running = false;
1818
+ if (queued) {
1819
+ queued = false;
1820
+ schedule();
1821
+ }
1822
+ }
1823
+ }
1824
+ function schedule() {
1825
+ clearTimeout(timer);
1826
+ timer = setTimeout(() => void refresh(), options.debounce ?? 150);
1827
+ }
1828
+ const watcher = watch(cfg.root, { recursive: true }, (_event, filename) => {
1829
+ if (!filename) return;
1830
+ const file = filename.replaceAll("\\", "/");
1831
+ if (file.includes("node_modules/") || file.endsWith(".d.ts")) return;
1832
+ if (catalogDir && file.startsWith(`${catalogDir}/`)) return;
1833
+ if (SOURCE_FILE_RE.test(file)) schedule();
1834
+ });
1835
+ return () => {
1836
+ clearTimeout(timer);
1837
+ watcher.close();
1838
+ };
1839
+ }
1840
+ //#endregion
1841
+ export { LOCALE_MODULE_PREFIX, MessageRegistry, PSEUDO_LOCALE, RESOLVED_VIRTUAL_ID, SFC_FILE_RE, SOURCE_FILE_RE, VIRTUAL_ID, analyze, analyzeFile, analyzeSfc, catalogPath, check, claudeProvider, collectParams, detectBundler, doctor, exportCatalogs, extractProject, findConfigFile, formatCheckResult, formatStatusResult, generateDts, generateLocaleModule, generateRuntimeModule, importCatalogs, init, isMobileFormat, isTransformTarget, loadCatalogs, loadConfig, loadConfigFile, loadVirtualModule, parseExchangeFile, pruneCatalogs, pseudoCatalogs, pseudoLocalize, readCatalog, renderHtml, renderParamType, renderSite, resolveConfig, resolveVirtualId, runBuildGate, serializeCatalog, stableKey, status, structureMatches, syncCatalogs, targetLocales, transformCode, transformSource, translateCatalogs, watchProject, writeCatalog, writeDts };
1761
1842
 
1762
1843
  //# sourceMappingURL=index.js.map