angular-intlayer 9.3.1 → 9.3.3

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.
Files changed (43) hide show
  1. package/dist/cjs/client/useDictionaryDynamic.cjs +1 -1
  2. package/dist/cjs/client/useDictionaryDynamic.cjs.map +1 -1
  3. package/dist/cjs/editor/useEditor.cjs +2 -2
  4. package/dist/cjs/editor/useEditor.cjs.map +1 -1
  5. package/dist/cjs/esbuild/plugin.cjs +28 -0
  6. package/dist/cjs/esbuild/plugin.cjs.map +1 -1
  7. package/dist/cjs/plugins.cjs +1 -1
  8. package/dist/cjs/plugins.cjs.map +1 -1
  9. package/dist/cjs/webpack/mergeConfig.cjs +1 -1
  10. package/dist/esm/client/useDictionaryDynamic.mjs +2 -2
  11. package/dist/esm/client/useDictionaryDynamic.mjs.map +1 -1
  12. package/dist/esm/editor/useEditor.mjs +2 -2
  13. package/dist/esm/editor/useEditor.mjs.map +1 -1
  14. package/dist/esm/esbuild/plugin.mjs +31 -2
  15. package/dist/esm/esbuild/plugin.mjs.map +1 -1
  16. package/dist/esm/plugins.mjs +1 -1
  17. package/dist/esm/plugins.mjs.map +1 -1
  18. package/dist/esm/webpack/mergeConfig.mjs +1 -1
  19. package/dist/types/client/useDictionaryDynamic.d.ts.map +1 -1
  20. package/dist/types/client/useLocaleStorage.d.ts +5 -4
  21. package/dist/types/client/useLocaleStorage.d.ts.map +1 -1
  22. package/dist/types/editor/useEditor.d.ts.map +1 -1
  23. package/dist/types/esbuild/plugin.d.ts +14 -0
  24. package/dist/types/esbuild/plugin.d.ts.map +1 -1
  25. package/dist/types/format/useCompact.d.ts +2 -1
  26. package/dist/types/format/useCompact.d.ts.map +1 -1
  27. package/dist/types/format/useCurrency.d.ts +2 -1
  28. package/dist/types/format/useCurrency.d.ts.map +1 -1
  29. package/dist/types/format/useDate.d.ts +2 -1
  30. package/dist/types/format/useDate.d.ts.map +1 -1
  31. package/dist/types/format/useList.d.ts +2 -1
  32. package/dist/types/format/useList.d.ts.map +1 -1
  33. package/dist/types/format/useNumber.d.ts +2 -1
  34. package/dist/types/format/useNumber.d.ts.map +1 -1
  35. package/dist/types/format/usePercentage.d.ts +2 -1
  36. package/dist/types/format/usePercentage.d.ts.map +1 -1
  37. package/dist/types/format/useRelativeTime.d.ts +2 -1
  38. package/dist/types/format/useRelativeTime.d.ts.map +1 -1
  39. package/dist/types/format/useUnit.d.ts +2 -1
  40. package/dist/types/format/useUnit.d.ts.map +1 -1
  41. package/dist/types/intlayer/dist/types/index.d.ts +14 -0
  42. package/dist/types/plugins.d.ts.map +1 -1
  43. package/package.json +10 -10
@@ -43,7 +43,7 @@ const useDictionaryDynamic = (dictionaryPromise, key, localeOrSelector) => {
43
43
  }
44
44
  const locale = typeof localeOrSelector === "string" ? localeOrSelector : void 0;
45
45
  const localeTarget = (0, _angular_core.computed)(() => locale ?? intlayer?.locale() ?? _intlayer_config_built.internationalization.defaultLocale);
46
- const dictionary = require_client_useLoadDynamic.useLoadDynamic(`${String(key)}.${localeTarget()}`, dictionaryPromise[localeTarget()]?.());
46
+ const dictionary = (0, _intlayer_core_dictionaryManipulator.getPreloadedDictionary)(dictionaryPromise, localeTarget()) ?? require_client_useLoadDynamic.useLoadDynamic(`${String(key)}.${localeTarget()}`, dictionaryPromise[localeTarget()]?.());
47
47
  return require_client_useDictionary.useDictionary(dictionary, localeTarget());
48
48
  };
49
49
 
@@ -1 +1 @@
1
- {"version":3,"file":"useDictionaryDynamic.cjs","names":["inject","INTLAYER_TOKEN","isQualifiedDynamicLoaderMap","parseDictionarySelector","resolveDictionaryArgument","internationalization","signal","getDictionary","computed","useLoadDynamic","useDictionary"],"sources":["../../../src/client/useDictionaryDynamic.ts"],"sourcesContent":["'use client';\n\nimport { computed, inject, signal } from '@angular/core';\nimport { internationalization } from '@intlayer/config/built';\nimport {\n isQualifiedDynamicLoaderMap,\n parseDictionarySelector,\n type QualifiedDynamicLoaderMap,\n resolveDictionaryArgument,\n resolveQualifiedDynamicContentAsync,\n} from '@intlayer/core/dictionaryManipulator';\nimport type { Dictionary } from '@intlayer/types/dictionary';\nimport type {\n DeclaredLocales,\n DictionaryKeys,\n DictionarySelectorForKey,\n LocalesValues,\n StrictModeLocaleMap,\n} from '@intlayer/types/module_augmentation';\nimport { getDictionary } from '../getDictionary';\nimport { INTLAYER_TOKEN, type IntlayerProvider } from './installIntlayer';\nimport { useDictionary } from './useDictionary';\nimport { useLoadDynamic } from './useLoadDynamic';\n\n/**\n * Lazily loads a dictionary (plain or qualified) and returns its reactive\n * content.\n *\n * For a qualified loader map (collection / variant, possibly\n * combined), only the chunk(s) the selector targets are loaded. For a plain\n * loader map, the locale chunk is loaded.\n *\n * If the locale is not provided (directly or through the selector), it will use\n * the locale from the client context.\n */\nexport const useDictionaryDynamic = <\n const T extends Dictionary,\n const K extends DictionaryKeys,\n const A extends LocalesValues | DictionarySelectorForKey<K> = DeclaredLocales,\n>(\n dictionaryPromise:\n | StrictModeLocaleMap<() => Promise<T>>\n | QualifiedDynamicLoaderMap,\n key: K,\n localeOrSelector?: A\n) => {\n const intlayer = inject<IntlayerProvider>(INTLAYER_TOKEN);\n\n if (\n process.env.INTLAYER_DICTIONARY_SELECTOR !== 'false' &&\n isQualifiedDynamicLoaderMap(dictionaryPromise)\n ) {\n // Layers the provider's ambient variant under the call-site argument\n // before the chunk walk, so only the targeted chunk is loaded.\n const { locale: selectorLocale, selector } =\n parseDictionarySelector<LocalesValues>(\n resolveDictionaryArgument({\n localeOrSelector,\n contextLocale: intlayer?.locale(),\n contextVariant: intlayer?.variant?.(),\n dictionaryKey: String(key),\n })\n );\n\n const localeTarget = selectorLocale ?? internationalization.defaultLocale;\n\n const container = signal<unknown>(undefined);\n\n resolveQualifiedDynamicContentAsync({\n loaderMap: dictionaryPromise,\n key: String(key),\n locale: localeTarget,\n selector,\n transform: (dictionary) => getDictionary(dictionary, localeTarget),\n }).then((resolved) => container.set(resolved));\n\n return computed(() => container() as any);\n }\n\n const locale =\n typeof localeOrSelector === 'string'\n ? (localeOrSelector as LocalesValues)\n : undefined;\n\n const localeTarget = computed(\n () => locale ?? intlayer?.locale() ?? internationalization.defaultLocale\n );\n\n const dictionary = useLoadDynamic<T>(\n `${String(key)}.${localeTarget()}`,\n (dictionaryPromise as any)[localeTarget()]?.()\n ) as T;\n\n return useDictionary(dictionary, localeTarget() as any);\n};\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;AAmCA,MAAa,wBAKX,mBAGA,KACA,qBACG;CACH,MAAM,eAAWA,sBAAyBC,2CAAc;CAExD,IACE,QAAQ,IAAI,iCAAiC,eAC7CC,kEAA4B,iBAAiB,GAC7C;EAGA,MAAM,EAAE,QAAQ,gBAAgB,iBAC9BC,kEACEC,gEAA0B;GACxB;GACA,eAAe,UAAU,OAAO;GAChC,gBAAgB,UAAU,UAAU;GACpC,eAAe,OAAO,GAAG;EAC3B,CAAC,CACH;EAEF,MAAM,eAAe,kBAAkBC,4CAAqB;EAE5D,MAAM,gBAAYC,sBAAgB,MAAS;EAE3C,8EAAoC;GAClC,WAAW;GACX,KAAK,OAAO,GAAG;GACf,QAAQ;GACR;GACA,YAAY,eAAeC,oCAAc,YAAY,YAAY;EACnE,CAAC,CAAC,CAAC,MAAM,aAAa,UAAU,IAAI,QAAQ,CAAC;EAE7C,WAAOC,8BAAe,UAAU,CAAQ;CAC1C;CAEA,MAAM,SACJ,OAAO,qBAAqB,WACvB,mBACD;CAEN,MAAM,mBAAeA,8BACb,UAAU,UAAU,OAAO,KAAKH,4CAAqB,aAC7D;CAEA,MAAM,aAAaI,6CACjB,GAAG,OAAO,GAAG,EAAE,GAAG,aAAa,KAC9B,kBAA0B,aAAa,EAAE,GAAG,CAC/C;CAEA,OAAOC,2CAAc,YAAY,aAAa,CAAQ;AACxD"}
1
+ {"version":3,"file":"useDictionaryDynamic.cjs","names":["inject","INTLAYER_TOKEN","isQualifiedDynamicLoaderMap","parseDictionarySelector","resolveDictionaryArgument","internationalization","signal","getDictionary","computed","getPreloadedDictionary","useLoadDynamic","useDictionary"],"sources":["../../../src/client/useDictionaryDynamic.ts"],"sourcesContent":["'use client';\n\nimport { computed, inject, signal } from '@angular/core';\nimport { internationalization } from '@intlayer/config/built';\nimport {\n getPreloadedDictionary,\n isQualifiedDynamicLoaderMap,\n parseDictionarySelector,\n type QualifiedDynamicLoaderMap,\n resolveDictionaryArgument,\n resolveQualifiedDynamicContentAsync,\n} from '@intlayer/core/dictionaryManipulator';\nimport type { Dictionary } from '@intlayer/types/dictionary';\nimport type {\n DeclaredLocales,\n DictionaryKeys,\n DictionarySelectorForKey,\n LocalesValues,\n StrictModeLocaleMap,\n} from '@intlayer/types/module_augmentation';\nimport { getDictionary } from '../getDictionary';\nimport { INTLAYER_TOKEN, type IntlayerProvider } from './installIntlayer';\nimport { useDictionary } from './useDictionary';\nimport { useLoadDynamic } from './useLoadDynamic';\n\n/**\n * Lazily loads a dictionary (plain or qualified) and returns its reactive\n * content.\n *\n * For a qualified loader map (collection / variant, possibly\n * combined), only the chunk(s) the selector targets are loaded. For a plain\n * loader map, the locale chunk is loaded.\n *\n * If the locale is not provided (directly or through the selector), it will use\n * the locale from the client context.\n */\nexport const useDictionaryDynamic = <\n const T extends Dictionary,\n const K extends DictionaryKeys,\n const A extends LocalesValues | DictionarySelectorForKey<K> = DeclaredLocales,\n>(\n dictionaryPromise:\n | StrictModeLocaleMap<() => Promise<T>>\n | QualifiedDynamicLoaderMap,\n key: K,\n localeOrSelector?: A\n) => {\n const intlayer = inject<IntlayerProvider>(INTLAYER_TOKEN);\n\n if (\n process.env.INTLAYER_DICTIONARY_SELECTOR !== 'false' &&\n isQualifiedDynamicLoaderMap(dictionaryPromise)\n ) {\n // Layers the provider's ambient variant under the call-site argument\n // before the chunk walk, so only the targeted chunk is loaded.\n const { locale: selectorLocale, selector } =\n parseDictionarySelector<LocalesValues>(\n resolveDictionaryArgument({\n localeOrSelector,\n contextLocale: intlayer?.locale(),\n contextVariant: intlayer?.variant?.(),\n dictionaryKey: String(key),\n })\n );\n\n const localeTarget = selectorLocale ?? internationalization.defaultLocale;\n\n const container = signal<unknown>(undefined);\n\n resolveQualifiedDynamicContentAsync({\n loaderMap: dictionaryPromise,\n key: String(key),\n locale: localeTarget,\n selector,\n transform: (dictionary) => getDictionary(dictionary, localeTarget),\n }).then((resolved) => container.set(resolved));\n\n return computed(() => container() as any);\n }\n\n const locale =\n typeof localeOrSelector === 'string'\n ? (localeOrSelector as LocalesValues)\n : undefined;\n\n const localeTarget = computed(\n () => locale ?? intlayer?.locale() ?? internationalization.defaultLocale\n );\n\n // A build-tool plugin may have started this locale's chunk while the entry\n // point evaluated, and it may already have landed. Using it directly skips `useLoadDynamic`, whose signal\n // starts empty and only fills in on the promise callback — one frame of blank\n // content per dictionary, even when nothing has to be fetched.\n const preloadedDictionary = getPreloadedDictionary(\n dictionaryPromise,\n localeTarget()\n );\n\n const dictionary =\n (preloadedDictionary as T | undefined) ??\n (useLoadDynamic<T>(\n `${String(key)}.${localeTarget()}`,\n (dictionaryPromise as any)[localeTarget()]?.()\n ) as T);\n\n return useDictionary(dictionary, localeTarget() as any);\n};\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;AAoCA,MAAa,wBAKX,mBAGA,KACA,qBACG;CACH,MAAM,eAAWA,sBAAyBC,2CAAc;CAExD,IACE,QAAQ,IAAI,iCAAiC,eAC7CC,kEAA4B,iBAAiB,GAC7C;EAGA,MAAM,EAAE,QAAQ,gBAAgB,iBAC9BC,kEACEC,gEAA0B;GACxB;GACA,eAAe,UAAU,OAAO;GAChC,gBAAgB,UAAU,UAAU;GACpC,eAAe,OAAO,GAAG;EAC3B,CAAC,CACH;EAEF,MAAM,eAAe,kBAAkBC,4CAAqB;EAE5D,MAAM,gBAAYC,sBAAgB,MAAS;EAE3C,8EAAoC;GAClC,WAAW;GACX,KAAK,OAAO,GAAG;GACf,QAAQ;GACR;GACA,YAAY,eAAeC,oCAAc,YAAY,YAAY;EACnE,CAAC,CAAC,CAAC,MAAM,aAAa,UAAU,IAAI,QAAQ,CAAC;EAE7C,WAAOC,8BAAe,UAAU,CAAQ;CAC1C;CAEA,MAAM,SACJ,OAAO,qBAAqB,WACvB,mBACD;CAEN,MAAM,mBAAeA,8BACb,UAAU,UAAU,OAAO,KAAKH,4CAAqB,aAC7D;CAWA,MAAM,iBALsBI,6DAC1B,mBACA,aAAa,CAIM,KAClBC,6CACC,GAAG,OAAO,GAAG,EAAE,GAAG,aAAa,KAC9B,kBAA0B,aAAa,EAAE,GAAG,CAC/C;CAEF,OAAOC,2CAAc,YAAY,aAAa,CAAQ;AACxD"}
@@ -26,7 +26,7 @@ const useEditor = (client) => {
26
26
  import("@intlayer/editor").then(({ initEditorClient }) => {
27
27
  if (stopped) return;
28
28
  manager.set(initEditorClient());
29
- });
29
+ }).catch(() => {});
30
30
  const effectRef = (0, _angular_core.runInInjectionContext)(injector, () => (0, _angular_core.effect)(() => {
31
31
  const m = manager();
32
32
  const locale = resolvedClient?.locale();
@@ -38,7 +38,7 @@ const useEditor = (client) => {
38
38
  manager.set(null);
39
39
  import("@intlayer/editor").then(({ stopEditorClient }) => {
40
40
  stopEditorClient();
41
- });
41
+ }).catch(() => {});
42
42
  });
43
43
  };
44
44
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"useEditor.cjs","names":["isEnabled","inject","DestroyRef","Injector","INTLAYER_TOKEN","signal","runInInjectionContext","effect","provideAppInitializer"],"sources":["../../../src/editor/useEditor.ts"],"sourcesContent":["import {\n DestroyRef,\n effect,\n Injector,\n inject,\n provideAppInitializer,\n runInInjectionContext,\n signal,\n} from '@angular/core';\nimport type { EditorStateManager } from '@intlayer/editor';\nimport { isEnabled } from '@intlayer/editor/isEnabled';\nimport type { Locale } from '@intlayer/types/allLocales';\n// Import from the standalone token file to avoid a circular dependency:\n// installIntlayer.ts → useEditor.ts → ../client → installIntlayer.ts\nimport { INTLAYER_TOKEN, type IntlayerProvider } from '../client/intlayerToken';\n\n/**\n * Initialises the Intlayer editor client singleton when the editor is enabled.\n * Syncs the current locale from the provided Intlayer client into the editor\n * manager so the editor always knows which locale the app is displaying.\n *\n * Must be called inside an Angular injection context (e.g. a component\n * constructor, `provideAppInitializer`, or `runInInjectionContext`).\n *\n * @param client - The IntlayerProvider instance to sync locale from.\n * When omitted the function injects `INTLAYER_TOKEN` from the DI tree,\n * so it still works when called directly from a component.\n */\nexport const useEditor = (client?: IntlayerProvider | null): void => {\n if (process.env.INTLAYER_EDITOR_ENABLED === 'false' || !isEnabled) return;\n\n const destroyRef = inject(DestroyRef, { optional: true });\n const injector = inject(Injector);\n\n // Resolve the client: use the passed-in reference or fall back to injection.\n const resolvedClient =\n client ??\n inject<IntlayerProvider>(INTLAYER_TOKEN, { optional: true } as any);\n\n // `manager` signal is set once the async import resolves.\n // Using a signal lets an `effect()` react to it becoming available.\n const manager = signal<EditorStateManager | null>(null);\n\n // Guard: prevents the async callback from acting after the view is destroyed.\n let stopped = false;\n\n // Initialise the editor client\n import('@intlayer/editor').then(({ initEditorClient }) => {\n if (stopped) return;\n manager.set(initEditorClient());\n });\n\n // Keep the editor locale in sync with the Angular locale signal\n const effectRef = runInInjectionContext(injector, () =>\n effect(() => {\n const m = manager();\n const locale = resolvedClient?.locale();\n if (m && locale) m.currentLocale.set(locale as Locale);\n })\n );\n\n // Tear down on destroy\n destroyRef?.onDestroy(() => {\n stopped = true;\n effectRef.destroy();\n manager.set(null);\n import('@intlayer/editor').then(({ stopEditorClient }) => {\n stopEditorClient();\n });\n });\n};\n\n/**\n * Angular provider that wires `useEditor` into the application initialisation\n * phase via `provideAppInitializer`.\n *\n * `provideIntlayer()` already calls this internally, so you only need this\n * function when you want to manage providers individually.\n *\n * @example\n * ```ts\n * // app.config.ts\n * import { provideIntlayer, provideIntlayerEditor } from 'angular-intlayer';\n *\n * export const appConfig: ApplicationConfig = {\n * providers: [provideIntlayer(), provideIntlayerEditor()],\n * };\n * ```\n */\nexport const provideIntlayerEditor = (client?: IntlayerProvider | null) =>\n provideAppInitializer(() => useEditor(client));\n"],"mappings":";;;;;;;;;;;;;;;;;;AA4BA,MAAa,aAAa,WAA2C;CACnE,IAAI,QAAQ,IAAI,4BAA4B,WAAW,CAACA,sCAAW;CAEnE,MAAM,iBAAaC,sBAAOC,0BAAY,EAAE,UAAU,KAAK,CAAC;CACxD,MAAM,eAAWD,sBAAOE,sBAAQ;CAGhC,MAAM,iBACJ,cACAF,sBAAyBG,6CAAgB,EAAE,UAAU,KAAK,CAAQ;CAIpE,MAAM,cAAUC,sBAAkC,IAAI;CAGtD,IAAI,UAAU;CAGd,OAAO,mBAAmB,CAAC,MAAM,EAAE,uBAAuB;EACxD,IAAI,SAAS;EACb,QAAQ,IAAI,iBAAiB,CAAC;CAChC,CAAC;CAGD,MAAM,gBAAYC,qCAAsB,oBACtCC,4BAAa;EACX,MAAM,IAAI,QAAQ;EAClB,MAAM,SAAS,gBAAgB,OAAO;EACtC,IAAI,KAAK,QAAQ,EAAE,cAAc,IAAI,MAAgB;CACvD,CAAC,CACH;CAGA,YAAY,gBAAgB;EAC1B,UAAU;EACV,UAAU,QAAQ;EAClB,QAAQ,IAAI,IAAI;EAChB,OAAO,mBAAmB,CAAC,MAAM,EAAE,uBAAuB;GACxD,iBAAiB;EACnB,CAAC;CACH,CAAC;AACH;;;;;;;;;;;;;;;;;;AAmBA,MAAa,yBAAyB,eACpCC,2CAA4B,UAAU,MAAM,CAAC"}
1
+ {"version":3,"file":"useEditor.cjs","names":["isEnabled","inject","DestroyRef","Injector","INTLAYER_TOKEN","signal","runInInjectionContext","effect","provideAppInitializer"],"sources":["../../../src/editor/useEditor.ts"],"sourcesContent":["import {\n DestroyRef,\n effect,\n Injector,\n inject,\n provideAppInitializer,\n runInInjectionContext,\n signal,\n} from '@angular/core';\nimport type { EditorStateManager } from '@intlayer/editor';\nimport { isEnabled } from '@intlayer/editor/isEnabled';\nimport type { Locale } from '@intlayer/types/allLocales';\n// Import from the standalone token file to avoid a circular dependency:\n// installIntlayer.ts → useEditor.ts → ../client → installIntlayer.ts\nimport { INTLAYER_TOKEN, type IntlayerProvider } from '../client/intlayerToken';\n\n/**\n * Initialises the Intlayer editor client singleton when the editor is enabled.\n * Syncs the current locale from the provided Intlayer client into the editor\n * manager so the editor always knows which locale the app is displaying.\n *\n * Must be called inside an Angular injection context (e.g. a component\n * constructor, `provideAppInitializer`, or `runInInjectionContext`).\n *\n * @param client - The IntlayerProvider instance to sync locale from.\n * When omitted the function injects `INTLAYER_TOKEN` from the DI tree,\n * so it still works when called directly from a component.\n */\nexport const useEditor = (client?: IntlayerProvider | null): void => {\n if (process.env.INTLAYER_EDITOR_ENABLED === 'false' || !isEnabled) return;\n\n const destroyRef = inject(DestroyRef, { optional: true });\n const injector = inject(Injector);\n\n // Resolve the client: use the passed-in reference or fall back to injection.\n const resolvedClient =\n client ??\n inject<IntlayerProvider>(INTLAYER_TOKEN, { optional: true } as any);\n\n // `manager` signal is set once the async import resolves.\n // Using a signal lets an `effect()` react to it becoming available.\n const manager = signal<EditorStateManager | null>(null);\n\n // Guard: prevents the async callback from acting after the view is destroyed.\n let stopped = false;\n\n // Initialise the editor client\n import('@intlayer/editor')\n .then(({ initEditorClient }) => {\n if (stopped) return;\n manager.set(initEditorClient());\n })\n .catch(() => {});\n\n // Keep the editor locale in sync with the Angular locale signal\n const effectRef = runInInjectionContext(injector, () =>\n effect(() => {\n const m = manager();\n const locale = resolvedClient?.locale();\n if (m && locale) m.currentLocale.set(locale as Locale);\n })\n );\n\n // Tear down on destroy\n destroyRef?.onDestroy(() => {\n stopped = true;\n effectRef.destroy();\n manager.set(null);\n import('@intlayer/editor')\n .then(({ stopEditorClient }) => {\n stopEditorClient();\n })\n .catch(() => {});\n });\n};\n\n/**\n * Angular provider that wires `useEditor` into the application initialisation\n * phase via `provideAppInitializer`.\n *\n * `provideIntlayer()` already calls this internally, so you only need this\n * function when you want to manage providers individually.\n *\n * @example\n * ```ts\n * // app.config.ts\n * import { provideIntlayer, provideIntlayerEditor } from 'angular-intlayer';\n *\n * export const appConfig: ApplicationConfig = {\n * providers: [provideIntlayer(), provideIntlayerEditor()],\n * };\n * ```\n */\nexport const provideIntlayerEditor = (client?: IntlayerProvider | null) =>\n provideAppInitializer(() => useEditor(client));\n"],"mappings":";;;;;;;;;;;;;;;;;;AA4BA,MAAa,aAAa,WAA2C;CACnE,IAAI,QAAQ,IAAI,4BAA4B,WAAW,CAACA,sCAAW;CAEnE,MAAM,iBAAaC,sBAAOC,0BAAY,EAAE,UAAU,KAAK,CAAC;CACxD,MAAM,eAAWD,sBAAOE,sBAAQ;CAGhC,MAAM,iBACJ,cACAF,sBAAyBG,6CAAgB,EAAE,UAAU,KAAK,CAAQ;CAIpE,MAAM,cAAUC,sBAAkC,IAAI;CAGtD,IAAI,UAAU;CAGd,OAAO,mBAAmB,CACvB,MAAM,EAAE,uBAAuB;EAC9B,IAAI,SAAS;EACb,QAAQ,IAAI,iBAAiB,CAAC;CAChC,CAAC,CAAC,CACD,YAAY,CAAC,CAAC;CAGjB,MAAM,gBAAYC,qCAAsB,oBACtCC,4BAAa;EACX,MAAM,IAAI,QAAQ;EAClB,MAAM,SAAS,gBAAgB,OAAO;EACtC,IAAI,KAAK,QAAQ,EAAE,cAAc,IAAI,MAAgB;CACvD,CAAC,CACH;CAGA,YAAY,gBAAgB;EAC1B,UAAU;EACV,UAAU,QAAQ;EAClB,QAAQ,IAAI,IAAI;EAChB,OAAO,mBAAmB,CACvB,MAAM,EAAE,uBAAuB;GAC9B,iBAAiB;EACnB,CAAC,CAAC,CACD,YAAY,CAAC,CAAC;CACnB,CAAC;AACH;;;;;;;;;;;;;;;;;;AAmBA,MAAa,yBAAyB,eACpCC,2CAA4B,UAAU,MAAM,CAAC"}
@@ -1,5 +1,8 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
2
+ let node_fs_promises = require("node:fs/promises");
3
+ let node_module = require("node:module");
2
4
  let node_path = require("node:path");
5
+ let _intlayer_config_dictionaryPreload = require("@intlayer/config/dictionaryPreload");
3
6
  let _intlayer_config_envVars = require("@intlayer/config/envVars");
4
7
  let _intlayer_config_logger = require("@intlayer/config/logger");
5
8
  let _intlayer_config_node = require("@intlayer/config/node");
@@ -11,6 +14,18 @@ let _intlayer_engine_watcher = require("@intlayer/engine/watcher");
11
14
 
12
15
  //#region src/esbuild/plugin.ts
13
16
  /**
17
+ * Absolute id of the locale resolver the injected preamble imports.
18
+ *
19
+ * Resolved from this package, which declares `@intlayer/core` as a dependency,
20
+ * rather than left bare in the emitted source: the importer is a generated
21
+ * entry point under the application's `.intlayer` directory, and an application
22
+ * only depends on `intlayer` and its framework binding, so the bare specifier
23
+ * would resolve from a tree that need not contain the package at all.
24
+ *
25
+ * This package ships both module formats, hence the `require` fallback.
26
+ */
27
+ const preloadModuleId = (0, _intlayer_config_utils.normalizePath)((0, _intlayer_config_dictionaryPreload.resolvePreloadModuleId)(typeof require !== "undefined" ? require : (0, node_module.createRequire)(require("url").pathToFileURL(__filename).href)));
28
+ /**
14
29
  * esbuild plugin that integrates Intlayer into the Angular (or any esbuild-based) build process.
15
30
  *
16
31
  * Handles:
@@ -86,6 +101,19 @@ const intlayerEsbuildPlugin = (options) => {
86
101
  const escapedFrom = from.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
87
102
  build.onResolve({ filter: new RegExp(`^${escapedFrom}$`) }, () => ({ path: to }));
88
103
  }
104
+ if (config.build.dictionariesPreload) {
105
+ const dynamicDictionariesDir = (0, _intlayer_config_utils.normalizePath)(config.system.dynamicDictionariesDir);
106
+ build.onLoad({ filter: (0, _intlayer_config_dictionaryPreload.createDynamicEntryFilter)(dynamicDictionariesDir) }, async ({ path }) => {
107
+ if (!(0, _intlayer_config_utils.normalizePath)(path).startsWith(`${dynamicDictionariesDir}/`)) return null;
108
+ const code = await (0, node_fs_promises.readFile)(path, "utf-8");
109
+ const result = (0, _intlayer_config_dictionaryPreload.addDynamicEntryPreload)(code, preloadModuleId);
110
+ if (result.skipped) return null;
111
+ return {
112
+ contents: result.code,
113
+ loader: "js"
114
+ };
115
+ });
116
+ }
89
117
  if (!preparePromise) preparePromise = (0, _intlayer_engine_build.prepareIntlayer)(config, {
90
118
  clean: isProduction,
91
119
  cacheTimeoutMs: isProduction ? 3e4 : 36e5,
@@ -1 +1 @@
1
- {"version":3,"file":"plugin.cjs","names":["getConfiguration","getAlias","join","getAppLogger","getConfigEnvVars","getDictionaries","getUnusedNodeTypesAsync","formatNodeTypeToEnvVar","formatDictionarySelectorEnvVar","getHasDictionarySelector","prepareIntlayer","watch"],"sources":["../../../src/esbuild/plugin.ts"],"sourcesContent":["import { join } from 'node:path';\nimport {\n formatDictionarySelectorEnvVar,\n formatNodeTypeToEnvVar,\n getConfigEnvVars,\n} from '@intlayer/config/envVars';\nimport { getAppLogger } from '@intlayer/config/logger';\nimport {\n type GetConfigurationOptions,\n getConfiguration,\n} from '@intlayer/config/node';\nimport {\n getAlias,\n getHasDictionarySelector,\n getUnusedNodeTypesAsync,\n} from '@intlayer/config/utils';\nimport { getDictionaries } from '@intlayer/dictionaries-entry';\nimport { prepareIntlayer } from '@intlayer/engine/build';\nimport { logConfigDetails } from '@intlayer/engine/cli';\nimport { watch } from '@intlayer/engine/watcher';\n\n// Minimal subset of the esbuild Plugin interface to avoid a hard dependency on\n// the `esbuild` package for type resolution. The shape is compatible with\n// esbuild >=0.17, `@angular-builders/custom-esbuild`, and NX esbuild builders.\nexport interface EsbuildPluginBuild {\n initialOptions: {\n alias?: Record<string, string>;\n define?: Record<string, string>;\n minify?: boolean;\n watch?: unknown;\n /** Absolute working directory of the esbuild context (set by Angular's builder). */\n absWorkingDir?: string;\n };\n onStart(callback: () => void | Promise<void>): void;\n /** Intercept module resolution — works even for imports inside node_modules. */\n onResolve(\n options: { filter: RegExp; namespace?: string },\n callback: (args: {\n path: string;\n importer: string;\n namespace: string;\n resolveDir: string;\n }) => { path: string; namespace?: string } | null | undefined\n ): void;\n}\n\nexport interface EsbuildPlugin {\n name: string;\n setup(build: EsbuildPluginBuild): void | Promise<void>;\n}\n\nexport type IntlayerEsbuildPluginOptions = {\n configOptions?: GetConfigurationOptions;\n /**\n * Whether to start the Intlayer file watcher for dictionary regeneration.\n * - `true`: always start the watcher (useful for `ng serve`)\n * - `false`: never start the watcher (useful for `ng build`)\n * - `undefined` (default): auto-detect based on the build context\n * (skips the watcher when a production build is detected)\n */\n watch?: boolean;\n};\n\n/**\n * esbuild plugin that integrates Intlayer into the Angular (or any esbuild-based) build process.\n *\n * Handles:\n * 1. Injecting `alias` entries so `@intlayer/dictionaries-entry` etc. resolve to\n * the generated files under `.intlayer/`.\n * 2. Defining `process.env.*` tree-shaking constants for production builds.\n * 3. Running `prepareIntlayer` (dictionary generation) before the first build.\n * 4. Starting the chokidar file-watcher in dev / serve mode.\n *\n * Compatible with:\n * - `@angular-builders/custom-esbuild` (`application` or `browser-esbuild` builder)\n * - NX `@nx/angular:browser-esbuild`\n * - Any raw esbuild setup that accepts the standard `Plugin` interface\n *\n * @example\n * ```ts\n * // esbuild.plugins.ts (referenced from angular.json \"plugins\" option)\n * import { intlayerEsbuildPlugin } from 'angular-intlayer/esbuild';\n * export default [intlayerEsbuildPlugin()];\n * ```\n */\nexport const intlayerEsbuildPlugin = (\n options?: IntlayerEsbuildPluginOptions\n): EsbuildPlugin => {\n // All Node.js-heavy initialization (getConfiguration, getAlias, …) is deferred\n // into setup() so it runs in esbuild's Node.js context, not at module-evaluation\n // time. @angular/build loads the plugin file through Vite's SSR module runner\n // (ESM) where CommonJS globals like __filename are undefined. Calling\n // getConfiguration() here would trigger: buildSync → worker threads →\n // __filename → ReferenceError, crashing the plugin before setup() ever runs.\n let config: ReturnType<typeof getConfiguration> | null = null;\n let alias: Record<string, string> | null = null;\n\n // Shared across parallel setup() calls (Angular spawns one per bundle context).\n let preparePromise: Promise<void> | null = null;\n let watcherStarted = false;\n // Once any esbuild context (browser or server) detects a production build,\n // suppress the watcher for all contexts so `ng build` can exit cleanly.\n let isBuildMode = false;\n\n return {\n name: 'intlayer',\n\n async setup(build) {\n if (!config) {\n const baseDir =\n build.initialOptions.absWorkingDir ??\n options?.configOptions?.baseDir ??\n process.cwd();\n\n config = getConfiguration({ baseDir, ...options?.configOptions });\n logConfigDetails({ baseDir, ...options?.configOptions });\n\n alias = getAlias({\n configuration: config,\n formatter: (value: string) => join(config!.system.baseDir, value),\n });\n }\n\n const appLogger = getAppLogger(config);\n const nodeEnvDefine =\n build.initialOptions.define?.['process.env.NODE_ENV'];\n\n // Angular's esbuild builder doesn't set `minify` or `process.env.NODE_ENV`\n // on initialOptions — it handles optimisation through its own pipeline.\n // Instead, Angular defines `ngDevMode` as `\"false\"` in production builds.\n const isProduction =\n nodeEnvDefine === '\"production\"' ||\n nodeEnvDefine === \"'production'\" ||\n build.initialOptions.minify === true ||\n build.initialOptions.define?.['ngDevMode'] === 'false';\n\n if (isProduction) {\n isBuildMode = true;\n }\n\n const wrapKey = (key: string) => `process.env.${key}`;\n const wrapValue = (value: string) => `\"${value}\"`;\n\n const envVars: Record<string, string> = {\n // Catch-all so that any `process.env.*` read NOT covered by a specific\n // key below resolves to `undefined` instead of dereferencing a bare\n // `process`, which is not defined in browser bundles and throws\n // `process is not defined`. esbuild resolves the most specific define\n // first, so the keys below keep their tree-shaking effect.\n 'process.env': '{}',\n [wrapKey('INTLAYER')]: wrapValue('true'),\n [wrapKey('NODE_ENV')]: wrapValue(\n isProduction ? 'production' : 'development'\n ),\n // Tree shaking flags derived from the config (routing / storage /\n // editor). Emitted in every mode so behaviour is consistent in dev.\n ...getConfigEnvVars(config, wrapKey, wrapValue),\n };\n\n if (isProduction) {\n const dictionaries = getDictionaries(config);\n if (Object.keys(dictionaries).length === 0) {\n appLogger('No dictionaries found. Please check your configuration.', {\n isVerbose: true,\n });\n }\n\n const unusedNodeTypes = await getUnusedNodeTypesAsync(dictionaries);\n Object.assign(\n envVars,\n // Tree shaking based on unused node types\n formatNodeTypeToEnvVar(unusedNodeTypes, wrapKey, wrapValue),\n // Tree shaking the dictionary selector logic\n // (collections / variants)\n formatDictionarySelectorEnvVar(\n getHasDictionarySelector(dictionaries),\n wrapKey,\n wrapValue\n )\n );\n }\n\n // Existing defines (Angular's own, or the user's angular.json `define`\n // block) take precedence over the Intlayer ones.\n build.initialOptions.define = {\n ...envVars,\n ...(build.initialOptions.define ?? {}),\n };\n\n build.initialOptions.alias = {\n ...alias,\n ...(build.initialOptions.alias ?? {}),\n };\n\n for (const [from, to] of Object.entries(alias!)) {\n const escapedFrom = from.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n\n build.onResolve({ filter: new RegExp(`^${escapedFrom}$`) }, () => ({\n path: to,\n }));\n }\n\n if (!preparePromise) {\n preparePromise = prepareIntlayer(config, {\n clean: isProduction,\n cacheTimeoutMs: isProduction ? 1000 * 30 : 1000 * 60 * 60,\n env: isProduction ? 'prod' : 'dev',\n });\n }\n\n await preparePromise;\n\n build.onStart(async () => {\n // Determine whether the watcher should run:\n // 1. Explicit option from the caller takes precedence\n // 2. If any esbuild context detected a production build, skip\n // 3. esbuild's own watch mode is a positive signal\n const shouldWatch = options?.watch ?? !isBuildMode;\n\n if (shouldWatch && !watcherStarted) {\n watcherStarted = true;\n\n await watch({ configuration: config! });\n }\n });\n },\n };\n};\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAqFA,MAAa,yBACX,YACkB;CAOlB,IAAI,SAAqD;CACzD,IAAI,QAAuC;CAG3C,IAAI,iBAAuC;CAC3C,IAAI,iBAAiB;CAGrB,IAAI,cAAc;CAElB,OAAO;EACL,MAAM;EAEN,MAAM,MAAM,OAAO;GACjB,IAAI,CAAC,QAAQ;IACX,MAAM,UACJ,MAAM,eAAe,iBACrB,SAAS,eAAe,WACxB,QAAQ,IAAI;IAEd,aAASA,wCAAiB;KAAE;KAAS,GAAG,SAAS;IAAc,CAAC;IAChE,2CAAiB;KAAE;KAAS,GAAG,SAAS;IAAc,CAAC;IAEvD,YAAQC,iCAAS;KACf,eAAe;KACf,YAAY,cAAkBC,gBAAK,OAAQ,OAAO,SAAS,KAAK;IAClE,CAAC;GACH;GAEA,MAAM,gBAAYC,sCAAa,MAAM;GACrC,MAAM,gBACJ,MAAM,eAAe,SAAS;GAKhC,MAAM,eACJ,kBAAkB,oBAClB,kBAAkB,kBAClB,MAAM,eAAe,WAAW,QAChC,MAAM,eAAe,SAAS,iBAAiB;GAEjD,IAAI,cACF,cAAc;GAGhB,MAAM,WAAW,QAAgB,eAAe;GAChD,MAAM,aAAa,UAAkB,IAAI,MAAM;GAE/C,MAAM,UAAkC;IAMtC,eAAe;KACd,QAAQ,UAAU,IAAI,UAAU,MAAM;KACtC,QAAQ,UAAU,IAAI,UACrB,eAAe,eAAe,aAChC;IAGA,OAAGC,2CAAiB,QAAQ,SAAS,SAAS;GAChD;GAEA,IAAI,cAAc;IAChB,MAAM,mBAAeC,8CAAgB,MAAM;IAC3C,IAAI,OAAO,KAAK,YAAY,CAAC,CAAC,WAAW,GACvC,UAAU,2DAA2D,EACnE,WAAW,KACb,CAAC;IAGH,MAAM,kBAAkB,UAAMC,gDAAwB,YAAY;IAClE,OAAO,OACL,aAEAC,iDAAuB,iBAAiB,SAAS,SAAS,OAG1DC,6DACEC,iDAAyB,YAAY,GACrC,SACA,SACF,CACF;GACF;GAIA,MAAM,eAAe,SAAS;IAC5B,GAAG;IACH,GAAI,MAAM,eAAe,UAAU,CAAC;GACtC;GAEA,MAAM,eAAe,QAAQ;IAC3B,GAAG;IACH,GAAI,MAAM,eAAe,SAAS,CAAC;GACrC;GAEA,KAAK,MAAM,CAAC,MAAM,OAAO,OAAO,QAAQ,KAAM,GAAG;IAC/C,MAAM,cAAc,KAAK,QAAQ,uBAAuB,MAAM;IAE9D,MAAM,UAAU,EAAE,QAAQ,IAAI,OAAO,IAAI,YAAY,EAAE,EAAE,UAAU,EACjE,MAAM,GACR,EAAE;GACJ;GAEA,IAAI,CAAC,gBACH,qBAAiBC,wCAAgB,QAAQ;IACvC,OAAO;IACP,gBAAgB,eAAe,MAAY;IAC3C,KAAK,eAAe,SAAS;GAC/B,CAAC;GAGH,MAAM;GAEN,MAAM,QAAQ,YAAY;IAOxB,KAFoB,SAAS,SAAS,CAAC,gBAEpB,CAAC,gBAAgB;KAClC,iBAAiB;KAEjB,UAAMC,gCAAM,EAAE,eAAe,OAAQ,CAAC;IACxC;GACF,CAAC;EACH;CACF;AACF"}
1
+ {"version":3,"file":"plugin.cjs","names":["normalizePath","resolvePreloadModuleId","createRequire","getConfiguration","getAlias","join","getAppLogger","getConfigEnvVars","getDictionaries","getUnusedNodeTypesAsync","formatNodeTypeToEnvVar","formatDictionarySelectorEnvVar","getHasDictionarySelector","createDynamicEntryFilter","readFile","addDynamicEntryPreload","prepareIntlayer","watch"],"sources":["../../../src/esbuild/plugin.ts"],"sourcesContent":["import { readFile } from 'node:fs/promises';\nimport { createRequire } from 'node:module';\nimport { join } from 'node:path';\nimport {\n addDynamicEntryPreload,\n createDynamicEntryFilter,\n resolvePreloadModuleId,\n} from '@intlayer/config/dictionaryPreload';\nimport {\n formatDictionarySelectorEnvVar,\n formatNodeTypeToEnvVar,\n getConfigEnvVars,\n} from '@intlayer/config/envVars';\nimport { getAppLogger } from '@intlayer/config/logger';\nimport {\n type GetConfigurationOptions,\n getConfiguration,\n} from '@intlayer/config/node';\nimport {\n getAlias,\n getHasDictionarySelector,\n getUnusedNodeTypesAsync,\n normalizePath,\n} from '@intlayer/config/utils';\nimport { getDictionaries } from '@intlayer/dictionaries-entry';\nimport { prepareIntlayer } from '@intlayer/engine/build';\nimport { logConfigDetails } from '@intlayer/engine/cli';\nimport { watch } from '@intlayer/engine/watcher';\n\n/**\n * Absolute id of the locale resolver the injected preamble imports.\n *\n * Resolved from this package, which declares `@intlayer/core` as a dependency,\n * rather than left bare in the emitted source: the importer is a generated\n * entry point under the application's `.intlayer` directory, and an application\n * only depends on `intlayer` and its framework binding, so the bare specifier\n * would resolve from a tree that need not contain the package at all.\n *\n * This package ships both module formats, hence the `require` fallback.\n */\nconst preloadModuleId = normalizePath(\n resolvePreloadModuleId(\n typeof require !== 'undefined' ? require : createRequire(import.meta.url)\n )\n);\n\n// Minimal subset of the esbuild Plugin interface to avoid a hard dependency on\n// the `esbuild` package for type resolution. The shape is compatible with\n// esbuild >=0.17, `@angular-builders/custom-esbuild`, and NX esbuild builders.\nexport interface EsbuildPluginBuild {\n initialOptions: {\n alias?: Record<string, string>;\n define?: Record<string, string>;\n minify?: boolean;\n watch?: unknown;\n /** Absolute working directory of the esbuild context (set by Angular's builder). */\n absWorkingDir?: string;\n };\n onStart(callback: () => void | Promise<void>): void;\n /** Intercept module resolution — works even for imports inside node_modules. */\n onResolve(\n options: { filter: RegExp; namespace?: string },\n callback: (args: {\n path: string;\n importer: string;\n namespace: string;\n resolveDir: string;\n }) => { path: string; namespace?: string } | null | undefined\n ): void;\n /** Intercept module contents, so a resolved file can be rewritten. */\n onLoad(\n options: { filter: RegExp; namespace?: string },\n callback: (args: {\n path: string;\n namespace: string;\n }) =>\n | { contents: string; loader?: string }\n | null\n | undefined\n | Promise<{ contents: string; loader?: string } | null | undefined>\n ): void;\n}\n\nexport interface EsbuildPlugin {\n name: string;\n setup(build: EsbuildPluginBuild): void | Promise<void>;\n}\n\nexport type IntlayerEsbuildPluginOptions = {\n configOptions?: GetConfigurationOptions;\n /**\n * Whether to start the Intlayer file watcher for dictionary regeneration.\n * - `true`: always start the watcher (useful for `ng serve`)\n * - `false`: never start the watcher (useful for `ng build`)\n * - `undefined` (default): auto-detect based on the build context\n * (skips the watcher when a production build is detected)\n */\n watch?: boolean;\n};\n\n/**\n * esbuild plugin that integrates Intlayer into the Angular (or any esbuild-based) build process.\n *\n * Handles:\n * 1. Injecting `alias` entries so `@intlayer/dictionaries-entry` etc. resolve to\n * the generated files under `.intlayer/`.\n * 2. Defining `process.env.*` tree-shaking constants for production builds.\n * 3. Running `prepareIntlayer` (dictionary generation) before the first build.\n * 4. Starting the chokidar file-watcher in dev / serve mode.\n *\n * Compatible with:\n * - `@angular-builders/custom-esbuild` (`application` or `browser-esbuild` builder)\n * - NX `@nx/angular:browser-esbuild`\n * - Any raw esbuild setup that accepts the standard `Plugin` interface\n *\n * @example\n * ```ts\n * // esbuild.plugins.ts (referenced from angular.json \"plugins\" option)\n * import { intlayerEsbuildPlugin } from 'angular-intlayer/esbuild';\n * export default [intlayerEsbuildPlugin()];\n * ```\n */\nexport const intlayerEsbuildPlugin = (\n options?: IntlayerEsbuildPluginOptions\n): EsbuildPlugin => {\n // All Node.js-heavy initialization (getConfiguration, getAlias, …) is deferred\n // into setup() so it runs in esbuild's Node.js context, not at module-evaluation\n // time. @angular/build loads the plugin file through Vite's SSR module runner\n // (ESM) where CommonJS globals like __filename are undefined. Calling\n // getConfiguration() here would trigger: buildSync → worker threads →\n // __filename → ReferenceError, crashing the plugin before setup() ever runs.\n let config: ReturnType<typeof getConfiguration> | null = null;\n let alias: Record<string, string> | null = null;\n\n // Shared across parallel setup() calls (Angular spawns one per bundle context).\n let preparePromise: Promise<void> | null = null;\n let watcherStarted = false;\n // Once any esbuild context (browser or server) detects a production build,\n // suppress the watcher for all contexts so `ng build` can exit cleanly.\n let isBuildMode = false;\n\n return {\n name: 'intlayer',\n\n async setup(build) {\n if (!config) {\n const baseDir =\n build.initialOptions.absWorkingDir ??\n options?.configOptions?.baseDir ??\n process.cwd();\n\n config = getConfiguration({ baseDir, ...options?.configOptions });\n logConfigDetails({ baseDir, ...options?.configOptions });\n\n alias = getAlias({\n configuration: config,\n formatter: (value: string) => join(config!.system.baseDir, value),\n });\n }\n\n const appLogger = getAppLogger(config);\n const nodeEnvDefine =\n build.initialOptions.define?.['process.env.NODE_ENV'];\n\n // Angular's esbuild builder doesn't set `minify` or `process.env.NODE_ENV`\n // on initialOptions — it handles optimisation through its own pipeline.\n // Instead, Angular defines `ngDevMode` as `\"false\"` in production builds.\n const isProduction =\n nodeEnvDefine === '\"production\"' ||\n nodeEnvDefine === \"'production'\" ||\n build.initialOptions.minify === true ||\n build.initialOptions.define?.['ngDevMode'] === 'false';\n\n if (isProduction) {\n isBuildMode = true;\n }\n\n const wrapKey = (key: string) => `process.env.${key}`;\n const wrapValue = (value: string) => `\"${value}\"`;\n\n const envVars: Record<string, string> = {\n // Catch-all so that any `process.env.*` read NOT covered by a specific\n // key below resolves to `undefined` instead of dereferencing a bare\n // `process`, which is not defined in browser bundles and throws\n // `process is not defined`. esbuild resolves the most specific define\n // first, so the keys below keep their tree-shaking effect.\n 'process.env': '{}',\n [wrapKey('INTLAYER')]: wrapValue('true'),\n [wrapKey('NODE_ENV')]: wrapValue(\n isProduction ? 'production' : 'development'\n ),\n // Tree shaking flags derived from the config (routing / storage /\n // editor). Emitted in every mode so behaviour is consistent in dev.\n ...getConfigEnvVars(config, wrapKey, wrapValue),\n };\n\n if (isProduction) {\n const dictionaries = getDictionaries(config);\n if (Object.keys(dictionaries).length === 0) {\n appLogger('No dictionaries found. Please check your configuration.', {\n isVerbose: true,\n });\n }\n\n const unusedNodeTypes = await getUnusedNodeTypesAsync(dictionaries);\n Object.assign(\n envVars,\n // Tree shaking based on unused node types\n formatNodeTypeToEnvVar(unusedNodeTypes, wrapKey, wrapValue),\n // Tree shaking the dictionary selector logic\n // (collections / variants)\n formatDictionarySelectorEnvVar(\n getHasDictionarySelector(dictionaries),\n wrapKey,\n wrapValue\n )\n );\n }\n\n // Existing defines (Angular's own, or the user's angular.json `define`\n // block) take precedence over the Intlayer ones.\n build.initialOptions.define = {\n ...envVars,\n ...(build.initialOptions.define ?? {}),\n };\n\n build.initialOptions.alias = {\n ...alias,\n ...(build.initialOptions.alias ?? {}),\n };\n\n for (const [from, to] of Object.entries(alias!)) {\n const escapedFrom = from.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n\n build.onResolve({ filter: new RegExp(`^${escapedFrom}$`) }, () => ({\n path: to,\n }));\n }\n\n // Dictionaries load with the chunk that needs them rather than being\n // fetched once that chunk renders: the entry point starts the browsing\n // locale's load as it evaluates, so a lazily loaded route requests its\n // content on `import()` instead of on first render. Without it every\n // dictionary read renders an empty placeholder first and fills in a tick\n // later.\n //\n // Not gated on the configured `importMode`: a `.content` file can set\n // `importMode: 'dynamic'` on a single dictionary under a `static` or\n // `fetch` global mode, and that dictionary needs the preload just the\n // same. Only entry points the optimizer imported are ever loaded, so the\n // path check below is the accurate gate.\n if (config.build.dictionariesPreload) {\n const dynamicDictionariesDir = normalizePath(\n config.system.dynamicDictionariesDir\n );\n\n build.onLoad(\n { filter: createDynamicEntryFilter(dynamicDictionariesDir) },\n async ({ path }) => {\n const posixPath = normalizePath(path);\n if (!posixPath.startsWith(`${dynamicDictionariesDir}/`))\n return null;\n\n const code = await readFile(path, 'utf-8');\n const result = addDynamicEntryPreload(code, preloadModuleId);\n\n if (result.skipped) return null;\n\n return { contents: result.code, loader: 'js' };\n }\n );\n }\n\n if (!preparePromise) {\n preparePromise = prepareIntlayer(config, {\n clean: isProduction,\n cacheTimeoutMs: isProduction ? 1000 * 30 : 1000 * 60 * 60,\n env: isProduction ? 'prod' : 'dev',\n });\n }\n\n await preparePromise;\n\n build.onStart(async () => {\n // Determine whether the watcher should run:\n // 1. Explicit option from the caller takes precedence\n // 2. If any esbuild context detected a production build, skip\n // 3. esbuild's own watch mode is a positive signal\n const shouldWatch = options?.watch ?? !isBuildMode;\n\n if (shouldWatch && !watcherStarted) {\n watcherStarted = true;\n\n await watch({ configuration: config! });\n }\n });\n },\n };\n};\n"],"mappings":"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"}
@@ -13,7 +13,7 @@ _intlayer_types_nodeType = require_runtime.__toESM(_intlayer_types_nodeType);
13
13
  let _markdownInstall = null;
14
14
  if (process.env.INTLAYER_NODE_TYPE_MARKDOWN !== "false" || process.env.INTLAYER_NODE_TYPE_HTML !== "false") Promise.resolve().then(() => require("./markdown/installIntlayerMarkdown.cjs")).then((m) => {
15
15
  _markdownInstall = m;
16
- });
16
+ }).catch(() => {});
17
17
  /** ---------------------------------------------
18
18
  * UTILS
19
19
  * --------------------------------------------- */
@@ -1 +1 @@
1
- {"version":3,"file":"plugins.cjs","names":["renderIntlayerNode","editor","ContentSelectorWrapperComponent","fallbackPlugin","getMarkdownMetadata","compile","NodeTypes","isInterpolableWrapperNode","transformInterpolableNode","internationalization","translationPlugin","enumerationPlugin","pluralPlugin","conditionPlugin","nestedPlugin","filePlugin","genderPlugin","selectPlugin"],"sources":["../../src/plugins.ts"],"sourcesContent":["import { editor, internationalization } from '@intlayer/config/built';\nimport {\n conditionPlugin,\n type DeepTransformContent as DeepTransformContentCore,\n enumerationPlugin,\n fallbackPlugin,\n filePlugin,\n genderPlugin,\n type IInterpreterPluginState as IInterpreterPluginStateCore,\n isInterpolableWrapperNode,\n nestedPlugin,\n type Plugins,\n pluralPlugin,\n selectPlugin,\n transformInterpolableNode,\n translationPlugin,\n} from '@intlayer/core/interpreter';\nimport type { MarkdownContent } from '@intlayer/core/markdown';\nimport { compile, getMarkdownMetadata } from '@intlayer/core/markdown';\nimport type { HTMLContent, InsertionContent } from '@intlayer/core/transpiler';\nimport type { KeyPath } from '@intlayer/types/keyPath';\nimport type {\n DeclaredLocales,\n LocalesValues,\n} from '@intlayer/types/module_augmentation';\nimport type { NodeType } from '@intlayer/types/nodeType';\nimport * as NodeTypes from '@intlayer/types/nodeType';\nimport { reportExposure } from './analytics/exposureSink';\nimport { ContentSelectorWrapperComponent } from './editor/ContentSelector.component';\nimport { renderIntlayerNode } from './renderIntlayerNode';\n\nlet _markdownInstall: {\n htmlRuntime: any;\n useMarkdown: () => { renderMarkdown: (s: string, components?: any) => any };\n} | null = null;\nif (\n process.env.INTLAYER_NODE_TYPE_MARKDOWN !== 'false' ||\n process.env.INTLAYER_NODE_TYPE_HTML !== 'false'\n) {\n void import('./markdown/installIntlayerMarkdown').then((m) => {\n _markdownInstall = m as any;\n });\n}\n\n/** ---------------------------------------------\n * UTILS\n * --------------------------------------------- */\n\nconst createRuntimeWithOverides = (baseRuntime: any, overrides: any) => ({\n ...baseRuntime,\n createElement: (tag: string, props: any, ...children: any[]) => {\n const override = overrides?.[tag];\n\n if (override) {\n const newProps = { ...props, ...override };\n\n // Merge class attributes intelligently\n const originalClass = props?.class || props?.className;\n const overrideClass = override.class || override.className;\n\n if (originalClass && overrideClass) {\n newProps.class = `${originalClass} ${overrideClass}`;\n newProps.className = undefined;\n }\n\n return baseRuntime.createElement(tag, newProps, ...children);\n }\n\n return baseRuntime.createElement(tag, props, ...children);\n },\n});\n\n/** ---------------------------------------------\n * INTLAYER NODE PLUGIN\n * --------------------------------------------- */\n\nexport type IntlayerNodeCond<T> = T extends number | string\n ? IntlayerNode<T>\n : never;\n\nexport interface IntlayerNode<T, P = {}> {\n value: T;\n children?: any;\n additionalProps?: P;\n}\n\n/** Translation plugin. Replaces node with a locale string if nodeType = Translation. */\nexport const intlayerNodePlugins: Plugins = {\n id: 'intlayer-node-plugin',\n canHandle: (node) =>\n typeof node === 'bigint' ||\n typeof node === 'string' ||\n typeof node === 'number',\n transform: (_node, { children, ...rest }) => {\n // Node-level analytics: record which content is resolved for display.\n // No-op (and dead-code-eliminated) when analytics is disabled.\n if (process.env.INTLAYER_ANALYTICS_ENABLED !== 'false') {\n reportExposure({\n dictionaryKey: rest.dictionaryKey,\n keyPath: rest.keyPath,\n locale: rest.locale,\n nodeType: 'text',\n });\n }\n\n return renderIntlayerNode({\n ...rest,\n value: children,\n children: () => ({\n component:\n process.env.INTLAYER_EDITOR_ENABLED === 'false' || !editor.enabled\n ? children\n : ContentSelectorWrapperComponent,\n props: {\n dictionaryKey: rest.dictionaryKey,\n keyPath: rest.keyPath,\n },\n children: children,\n }),\n });\n },\n};\n\n/**\n * MARKDOWN PLUGIN\n */\n\nexport type MarkdownStringCond<T> = T extends string\n ? IntlayerNode<string, { metadata: DeepTransformContent<string> }>\n : never;\n\n/** Markdown string plugin. Replaces string node with a component that render the markdown. */\nexport const markdownStringPlugin: Plugins =\n process.env.INTLAYER_NODE_TYPE_MARKDOWN === 'false'\n ? fallbackPlugin\n : {\n id: 'markdown-string-plugin',\n canHandle: (node) => typeof node === 'string',\n transform: (node: string, props, deepTransformNode) => {\n const {\n plugins, // Removed to avoid next error - Functions cannot be passed directly to Client Components\n ...rest\n } = props;\n\n const metadata = getMarkdownMetadata(node) ?? {};\n\n const metadataPlugins: Plugins = {\n id: 'markdown-metadata-plugin',\n canHandle: (metadataNode) =>\n typeof metadataNode === 'string' ||\n typeof metadataNode === 'number' ||\n typeof metadataNode === 'boolean' ||\n !metadataNode,\n transform: (metadataNode, props) =>\n renderIntlayerNode({\n ...props,\n value: metadataNode,\n children: node,\n }),\n };\n\n // Transform metadata while keeping the same structure\n const metadataNodes = deepTransformNode(metadata, {\n plugins: [metadataPlugins],\n dictionaryKey: rest.dictionaryKey,\n keyPath: [],\n });\n\n const render = (components?: any) =>\n renderIntlayerNode({\n ...rest,\n value: node,\n children:\n process.env.INTLAYER_EDITOR_ENABLED === 'false' ||\n !editor.enabled\n ? () => {\n const { renderMarkdown } =\n _markdownInstall?.useMarkdown() ?? {\n renderMarkdown: () => node,\n };\n return renderMarkdown(node, components);\n }\n : () => ({\n component: ContentSelectorWrapperComponent,\n props: {\n dictionaryKey: rest.dictionaryKey,\n keyPath: rest.keyPath,\n ...components,\n },\n children: () => {\n const { renderMarkdown } =\n _markdownInstall?.useMarkdown() ?? {\n renderMarkdown: () => node,\n };\n return renderMarkdown(node, components);\n },\n }),\n additionalProps: {\n metadata: metadataNodes,\n },\n });\n\n const createProxy = (element: any, components?: any) =>\n new Proxy(element, {\n get(target, prop, receiver) {\n if (prop === 'value') {\n return node;\n }\n if (prop === 'metadata') {\n return metadataNodes;\n }\n\n if (prop === 'toString') {\n return () => {\n const htmlRuntime = _markdownInstall?.htmlRuntime;\n if (!htmlRuntime || !compile) return node;\n const runtime = components\n ? createRuntimeWithOverides(htmlRuntime, components)\n : htmlRuntime;\n return compile(node, { runtime }) as string;\n };\n }\n\n if (prop === Symbol.toPrimitive) {\n return () => {\n const htmlRuntime = _markdownInstall?.htmlRuntime;\n if (!htmlRuntime || !compile) return node;\n const runtime = components\n ? createRuntimeWithOverides(htmlRuntime, components)\n : htmlRuntime;\n return compile(node, { runtime }) as string;\n };\n }\n\n if (prop === 'use') {\n return (newComponents?: any) => {\n const mergedComponents = {\n ...components,\n ...newComponents,\n };\n return createProxy(\n render(mergedComponents),\n mergedComponents\n );\n };\n }\n\n return Reflect.get(target, prop, receiver);\n },\n }) as any;\n\n return createProxy(render() as any);\n },\n };\n\nexport type MarkdownCond<T, _S, _L extends LocalesValues> = T extends {\n nodeType: NodeType | string;\n [NodeTypes.MARKDOWN]: infer M;\n tags?: infer U;\n metadata?: infer V;\n}\n ? IntlayerNode<\n M,\n {\n use: (components?: Record<keyof U, any>) => any;\n metadata: DeepTransformContent<V>;\n }\n >\n : never;\n\nexport const markdownPlugin: Plugins =\n process.env.INTLAYER_NODE_TYPE_MARKDOWN === 'false'\n ? fallbackPlugin\n : {\n id: 'markdown-plugin',\n canHandle: (node) =>\n typeof node === 'object' && node?.nodeType === NodeTypes.MARKDOWN,\n transform: (node: MarkdownContent, props, deepTransformNode) => {\n const newKeyPath: KeyPath[] = [\n ...props.keyPath,\n {\n type: NodeTypes.MARKDOWN,\n },\n ];\n\n const children = node[NodeTypes.MARKDOWN];\n\n return deepTransformNode(children, {\n ...props,\n children,\n keyPath: newKeyPath,\n plugins: [markdownStringPlugin, ...(props.plugins ?? [])],\n });\n },\n };\n\n/** ---------------------------------------------\n * HTML PLUGIN\n * --------------------------------------------- */\n\n/**\n * HTML conditional type.\n *\n * This ensures type safety:\n * - `html('<div>Hello <CustomComponent /></div>').use({ CustomComponent: ... })` - optional but typed\n */\nexport type HTMLPluginCond<T, _S, _L> = T extends {\n nodeType: NodeType | string;\n [NodeTypes.HTML]: infer I;\n tags?: infer U;\n}\n ? IntlayerNode<\n I,\n {\n use: (components?: Record<keyof U, any>) => any;\n }\n >\n : never;\n\n/** HTML plugin. Replaces node with a function that takes components => IntlayerNode. */\nexport const htmlPlugin: Plugins =\n process.env.INTLAYER_NODE_TYPE_HTML === 'false'\n ? fallbackPlugin\n : {\n id: 'html-plugin',\n canHandle: (node) =>\n typeof node === 'object' && node?.nodeType === NodeTypes.HTML,\n\n transform: (node: HTMLContent<string>, props) => {\n const html = node[NodeTypes.HTML];\n const { plugins, ...rest } = props;\n\n // Type-safe render function that accepts properly typed components\n const render = (userComponents?: any) =>\n renderIntlayerNode({\n ...rest,\n value: html,\n children:\n process.env.INTLAYER_EDITOR_ENABLED === 'false' ||\n !editor.enabled\n ? html\n : () => ({\n component: ContentSelectorWrapperComponent,\n props: {\n dictionaryKey: rest.dictionaryKey,\n keyPath: rest.keyPath,\n ...userComponents,\n },\n children: html,\n }),\n });\n\n const createProxy = (element: any, components?: any) =>\n new Proxy(element, {\n get(target, prop, receiver) {\n if (prop === 'value') {\n return html;\n }\n\n if (prop === 'toString') {\n return () => {\n if (\n !components ||\n (typeof components === 'object' &&\n Object.keys(components).length === 0)\n ) {\n return String(html);\n }\n const htmlRuntime = _markdownInstall?.htmlRuntime;\n if (!htmlRuntime || !compile) return String(html);\n const runtime = createRuntimeWithOverides(\n htmlRuntime,\n components\n );\n return compile(html, { runtime }) as string;\n };\n }\n\n if (prop === Symbol.toPrimitive) {\n return () => {\n if (\n !components ||\n (typeof components === 'object' &&\n Object.keys(components).length === 0)\n ) {\n return String(html);\n }\n const htmlRuntime = _markdownInstall?.htmlRuntime;\n if (!htmlRuntime || !compile) return String(html);\n const runtime = createRuntimeWithOverides(\n htmlRuntime,\n components\n );\n return compile(html, { runtime }) as string;\n };\n }\n\n if (prop === 'use') {\n // Return a properly typed function based on custom components\n return (userComponents?: any) => {\n const mergedComponents = {\n ...components,\n ...userComponents,\n };\n return createProxy(\n render(mergedComponents),\n mergedComponents\n );\n };\n }\n\n return Reflect.get(target, prop, receiver);\n },\n }) as any;\n\n return createProxy(render() as any);\n },\n };\n\n/** ---------------------------------------------\n * INSERTION PLUGIN\n * --------------------------------------------- */\n\n/**\n * Insertion conditional type.\n */\nexport type InsertionPluginCond<T> = T extends {\n nodeType: NodeType | string;\n [NodeTypes.INSERTION]: infer _I;\n}\n ? (args: Record<string, string | number>) => string\n : never;\n\nexport const insertionPlugin: Plugins =\n process.env.INTLAYER_NODE_TYPE_INSERTION === 'false'\n ? fallbackPlugin\n : {\n id: 'insertion-plugin',\n canHandle: (node) =>\n typeof node === 'object' && node?.nodeType === NodeTypes.INSERTION,\n transform: (node: InsertionContent, props, deepTransformNode) => {\n const { plugins, ...rest } = props;\n const content = node[NodeTypes.INSERTION];\n\n // `html()`/`markdown()` nodes carry their `{{ … }}` placeholders\n // inside a raw string. Interpolate into that string, then re-run the\n // transform so the html/markdown renderer applies afterwards.\n if (isInterpolableWrapperNode(content)) {\n return (args: Record<string, string | number> = {}) =>\n transformInterpolableNode(\n content,\n args,\n props,\n props.plugins,\n deepTransformNode\n );\n }\n\n // Return a function that performs the interpolation\n const render = (args: Record<string, string | number> = {}) => {\n let text = content as string;\n if (args) {\n Object.entries(args).forEach(([key, value]) => {\n text = text.replace(\n new RegExp(`{{\\\\s*${key}\\\\s*}}`, 'g'),\n String(value)\n );\n });\n }\n return text;\n };\n\n return renderIntlayerNode({\n ...rest,\n value: render as any,\n children: render,\n });\n },\n };\n\nexport interface IInterpreterPluginAngular<T, S, L extends LocalesValues> {\n angularIntlayerNode: IntlayerNodeCond<T>;\n angularMarkdown: MarkdownCond<T, S, L>;\n angularHtml: HTMLPluginCond<T, S, L>;\n angularInsertion: InsertionPluginCond<T>;\n}\n\n/**\n * Insert this type as param of `DeepTransformContent` to avoid `intlayer` package pollution.\n *\n * Otherwise the the `angular-intlayer` plugins will override the types of `intlayer` functions.\n */\nexport type IInterpreterPluginState = Omit<\n IInterpreterPluginStateCore,\n 'insertion' // Remove insertion type from core package\n> & {\n angularIntlayerNode: true;\n angularMarkdown: true;\n angularHtml: true;\n angularInsertion: true;\n};\n\nexport type DeepTransformContent<\n T,\n L extends LocalesValues = DeclaredLocales,\n> = DeepTransformContentCore<T, IInterpreterPluginState, L>;\n\nconst pluginsCache = new Map<string, Plugins[]>();\n\n/**\n * Get the plugins array for Angular content transformation.\n * This function is used by both getIntlayer and getDictionary to ensure consistent plugin configuration.\n */\nexport const getPlugins = (\n locale?: LocalesValues,\n fallback: boolean = true\n): Plugins[] => {\n const currentLocale = locale ?? internationalization.defaultLocale;\n const cacheKey = `${currentLocale}_${fallback}`;\n\n if (pluginsCache.has(cacheKey)) {\n return pluginsCache.get(cacheKey)!;\n }\n\n const plugins = [\n translationPlugin(\n locale ?? internationalization.defaultLocale,\n fallback ? internationalization.defaultLocale : undefined\n ),\n enumerationPlugin,\n pluralPlugin(locale ?? internationalization.defaultLocale),\n conditionPlugin,\n nestedPlugin(locale ?? internationalization.defaultLocale),\n filePlugin,\n genderPlugin,\n selectPlugin,\n intlayerNodePlugins,\n markdownPlugin,\n htmlPlugin,\n insertionPlugin,\n ] as Plugins[];\n\n pluginsCache.set(cacheKey, plugins);\n\n return plugins;\n};\n"],"mappings":"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"}
1
+ {"version":3,"file":"plugins.cjs","names":["renderIntlayerNode","editor","ContentSelectorWrapperComponent","fallbackPlugin","getMarkdownMetadata","compile","NodeTypes","isInterpolableWrapperNode","transformInterpolableNode","internationalization","translationPlugin","enumerationPlugin","pluralPlugin","conditionPlugin","nestedPlugin","filePlugin","genderPlugin","selectPlugin"],"sources":["../../src/plugins.ts"],"sourcesContent":["import { editor, internationalization } from '@intlayer/config/built';\nimport {\n conditionPlugin,\n type DeepTransformContent as DeepTransformContentCore,\n enumerationPlugin,\n fallbackPlugin,\n filePlugin,\n genderPlugin,\n type IInterpreterPluginState as IInterpreterPluginStateCore,\n isInterpolableWrapperNode,\n nestedPlugin,\n type Plugins,\n pluralPlugin,\n selectPlugin,\n transformInterpolableNode,\n translationPlugin,\n} from '@intlayer/core/interpreter';\nimport type { MarkdownContent } from '@intlayer/core/markdown';\nimport { compile, getMarkdownMetadata } from '@intlayer/core/markdown';\nimport type { HTMLContent, InsertionContent } from '@intlayer/core/transpiler';\nimport type { KeyPath } from '@intlayer/types/keyPath';\nimport type {\n DeclaredLocales,\n LocalesValues,\n} from '@intlayer/types/module_augmentation';\nimport type { NodeType } from '@intlayer/types/nodeType';\nimport * as NodeTypes from '@intlayer/types/nodeType';\nimport { reportExposure } from './analytics/exposureSink';\nimport { ContentSelectorWrapperComponent } from './editor/ContentSelector.component';\nimport { renderIntlayerNode } from './renderIntlayerNode';\n\nlet _markdownInstall: {\n htmlRuntime: any;\n useMarkdown: () => { renderMarkdown: (s: string, components?: any) => any };\n} | null = null;\nif (\n process.env.INTLAYER_NODE_TYPE_MARKDOWN !== 'false' ||\n process.env.INTLAYER_NODE_TYPE_HTML !== 'false'\n) {\n void import('./markdown/installIntlayerMarkdown')\n .then((m) => {\n _markdownInstall = m as any;\n })\n .catch(() => {});\n}\n\n/** ---------------------------------------------\n * UTILS\n * --------------------------------------------- */\n\nconst createRuntimeWithOverides = (baseRuntime: any, overrides: any) => ({\n ...baseRuntime,\n createElement: (tag: string, props: any, ...children: any[]) => {\n const override = overrides?.[tag];\n\n if (override) {\n const newProps = { ...props, ...override };\n\n // Merge class attributes intelligently\n const originalClass = props?.class || props?.className;\n const overrideClass = override.class || override.className;\n\n if (originalClass && overrideClass) {\n newProps.class = `${originalClass} ${overrideClass}`;\n newProps.className = undefined;\n }\n\n return baseRuntime.createElement(tag, newProps, ...children);\n }\n\n return baseRuntime.createElement(tag, props, ...children);\n },\n});\n\n/** ---------------------------------------------\n * INTLAYER NODE PLUGIN\n * --------------------------------------------- */\n\nexport type IntlayerNodeCond<T> = T extends number | string\n ? IntlayerNode<T>\n : never;\n\nexport interface IntlayerNode<T, P = {}> {\n value: T;\n children?: any;\n additionalProps?: P;\n}\n\n/** Translation plugin. Replaces node with a locale string if nodeType = Translation. */\nexport const intlayerNodePlugins: Plugins = {\n id: 'intlayer-node-plugin',\n canHandle: (node) =>\n typeof node === 'bigint' ||\n typeof node === 'string' ||\n typeof node === 'number',\n transform: (_node, { children, ...rest }) => {\n // Node-level analytics: record which content is resolved for display.\n // No-op (and dead-code-eliminated) when analytics is disabled.\n if (process.env.INTLAYER_ANALYTICS_ENABLED !== 'false') {\n reportExposure({\n dictionaryKey: rest.dictionaryKey,\n keyPath: rest.keyPath,\n locale: rest.locale,\n nodeType: 'text',\n });\n }\n\n return renderIntlayerNode({\n ...rest,\n value: children,\n children: () => ({\n component:\n process.env.INTLAYER_EDITOR_ENABLED === 'false' || !editor.enabled\n ? children\n : ContentSelectorWrapperComponent,\n props: {\n dictionaryKey: rest.dictionaryKey,\n keyPath: rest.keyPath,\n },\n children: children,\n }),\n });\n },\n};\n\n/**\n * MARKDOWN PLUGIN\n */\n\nexport type MarkdownStringCond<T> = T extends string\n ? IntlayerNode<string, { metadata: DeepTransformContent<string> }>\n : never;\n\n/** Markdown string plugin. Replaces string node with a component that render the markdown. */\nexport const markdownStringPlugin: Plugins =\n process.env.INTLAYER_NODE_TYPE_MARKDOWN === 'false'\n ? fallbackPlugin\n : {\n id: 'markdown-string-plugin',\n canHandle: (node) => typeof node === 'string',\n transform: (node: string, props, deepTransformNode) => {\n const {\n plugins, // Removed to avoid next error - Functions cannot be passed directly to Client Components\n ...rest\n } = props;\n\n const metadata = getMarkdownMetadata(node) ?? {};\n\n const metadataPlugins: Plugins = {\n id: 'markdown-metadata-plugin',\n canHandle: (metadataNode) =>\n typeof metadataNode === 'string' ||\n typeof metadataNode === 'number' ||\n typeof metadataNode === 'boolean' ||\n !metadataNode,\n transform: (metadataNode, props) =>\n renderIntlayerNode({\n ...props,\n value: metadataNode,\n children: node,\n }),\n };\n\n // Transform metadata while keeping the same structure\n const metadataNodes = deepTransformNode(metadata, {\n plugins: [metadataPlugins],\n dictionaryKey: rest.dictionaryKey,\n keyPath: [],\n });\n\n const render = (components?: any) =>\n renderIntlayerNode({\n ...rest,\n value: node,\n children:\n process.env.INTLAYER_EDITOR_ENABLED === 'false' ||\n !editor.enabled\n ? () => {\n const { renderMarkdown } =\n _markdownInstall?.useMarkdown() ?? {\n renderMarkdown: () => node,\n };\n return renderMarkdown(node, components);\n }\n : () => ({\n component: ContentSelectorWrapperComponent,\n props: {\n dictionaryKey: rest.dictionaryKey,\n keyPath: rest.keyPath,\n ...components,\n },\n children: () => {\n const { renderMarkdown } =\n _markdownInstall?.useMarkdown() ?? {\n renderMarkdown: () => node,\n };\n return renderMarkdown(node, components);\n },\n }),\n additionalProps: {\n metadata: metadataNodes,\n },\n });\n\n const createProxy = (element: any, components?: any) =>\n new Proxy(element, {\n get(target, prop, receiver) {\n if (prop === 'value') {\n return node;\n }\n if (prop === 'metadata') {\n return metadataNodes;\n }\n\n if (prop === 'toString') {\n return () => {\n const htmlRuntime = _markdownInstall?.htmlRuntime;\n if (!htmlRuntime || !compile) return node;\n const runtime = components\n ? createRuntimeWithOverides(htmlRuntime, components)\n : htmlRuntime;\n return compile(node, { runtime }) as string;\n };\n }\n\n if (prop === Symbol.toPrimitive) {\n return () => {\n const htmlRuntime = _markdownInstall?.htmlRuntime;\n if (!htmlRuntime || !compile) return node;\n const runtime = components\n ? createRuntimeWithOverides(htmlRuntime, components)\n : htmlRuntime;\n return compile(node, { runtime }) as string;\n };\n }\n\n if (prop === 'use') {\n return (newComponents?: any) => {\n const mergedComponents = {\n ...components,\n ...newComponents,\n };\n return createProxy(\n render(mergedComponents),\n mergedComponents\n );\n };\n }\n\n return Reflect.get(target, prop, receiver);\n },\n }) as any;\n\n return createProxy(render() as any);\n },\n };\n\nexport type MarkdownCond<T, _S, _L extends LocalesValues> = T extends {\n nodeType: NodeType | string;\n [NodeTypes.MARKDOWN]: infer M;\n tags?: infer U;\n metadata?: infer V;\n}\n ? IntlayerNode<\n M,\n {\n use: (components?: Record<keyof U, any>) => any;\n metadata: DeepTransformContent<V>;\n }\n >\n : never;\n\nexport const markdownPlugin: Plugins =\n process.env.INTLAYER_NODE_TYPE_MARKDOWN === 'false'\n ? fallbackPlugin\n : {\n id: 'markdown-plugin',\n canHandle: (node) =>\n typeof node === 'object' && node?.nodeType === NodeTypes.MARKDOWN,\n transform: (node: MarkdownContent, props, deepTransformNode) => {\n const newKeyPath: KeyPath[] = [\n ...props.keyPath,\n {\n type: NodeTypes.MARKDOWN,\n },\n ];\n\n const children = node[NodeTypes.MARKDOWN];\n\n return deepTransformNode(children, {\n ...props,\n children,\n keyPath: newKeyPath,\n plugins: [markdownStringPlugin, ...(props.plugins ?? [])],\n });\n },\n };\n\n/** ---------------------------------------------\n * HTML PLUGIN\n * --------------------------------------------- */\n\n/**\n * HTML conditional type.\n *\n * This ensures type safety:\n * - `html('<div>Hello <CustomComponent /></div>').use({ CustomComponent: ... })` - optional but typed\n */\nexport type HTMLPluginCond<T, _S, _L> = T extends {\n nodeType: NodeType | string;\n [NodeTypes.HTML]: infer I;\n tags?: infer U;\n}\n ? IntlayerNode<\n I,\n {\n use: (components?: Record<keyof U, any>) => any;\n }\n >\n : never;\n\n/** HTML plugin. Replaces node with a function that takes components => IntlayerNode. */\nexport const htmlPlugin: Plugins =\n process.env.INTLAYER_NODE_TYPE_HTML === 'false'\n ? fallbackPlugin\n : {\n id: 'html-plugin',\n canHandle: (node) =>\n typeof node === 'object' && node?.nodeType === NodeTypes.HTML,\n\n transform: (node: HTMLContent<string>, props) => {\n const html = node[NodeTypes.HTML];\n const { plugins, ...rest } = props;\n\n // Type-safe render function that accepts properly typed components\n const render = (userComponents?: any) =>\n renderIntlayerNode({\n ...rest,\n value: html,\n children:\n process.env.INTLAYER_EDITOR_ENABLED === 'false' ||\n !editor.enabled\n ? html\n : () => ({\n component: ContentSelectorWrapperComponent,\n props: {\n dictionaryKey: rest.dictionaryKey,\n keyPath: rest.keyPath,\n ...userComponents,\n },\n children: html,\n }),\n });\n\n const createProxy = (element: any, components?: any) =>\n new Proxy(element, {\n get(target, prop, receiver) {\n if (prop === 'value') {\n return html;\n }\n\n if (prop === 'toString') {\n return () => {\n if (\n !components ||\n (typeof components === 'object' &&\n Object.keys(components).length === 0)\n ) {\n return String(html);\n }\n const htmlRuntime = _markdownInstall?.htmlRuntime;\n if (!htmlRuntime || !compile) return String(html);\n const runtime = createRuntimeWithOverides(\n htmlRuntime,\n components\n );\n return compile(html, { runtime }) as string;\n };\n }\n\n if (prop === Symbol.toPrimitive) {\n return () => {\n if (\n !components ||\n (typeof components === 'object' &&\n Object.keys(components).length === 0)\n ) {\n return String(html);\n }\n const htmlRuntime = _markdownInstall?.htmlRuntime;\n if (!htmlRuntime || !compile) return String(html);\n const runtime = createRuntimeWithOverides(\n htmlRuntime,\n components\n );\n return compile(html, { runtime }) as string;\n };\n }\n\n if (prop === 'use') {\n // Return a properly typed function based on custom components\n return (userComponents?: any) => {\n const mergedComponents = {\n ...components,\n ...userComponents,\n };\n return createProxy(\n render(mergedComponents),\n mergedComponents\n );\n };\n }\n\n return Reflect.get(target, prop, receiver);\n },\n }) as any;\n\n return createProxy(render() as any);\n },\n };\n\n/** ---------------------------------------------\n * INSERTION PLUGIN\n * --------------------------------------------- */\n\n/**\n * Insertion conditional type.\n */\nexport type InsertionPluginCond<T> = T extends {\n nodeType: NodeType | string;\n [NodeTypes.INSERTION]: infer _I;\n}\n ? (args: Record<string, string | number>) => string\n : never;\n\nexport const insertionPlugin: Plugins =\n process.env.INTLAYER_NODE_TYPE_INSERTION === 'false'\n ? fallbackPlugin\n : {\n id: 'insertion-plugin',\n canHandle: (node) =>\n typeof node === 'object' && node?.nodeType === NodeTypes.INSERTION,\n transform: (node: InsertionContent, props, deepTransformNode) => {\n const { plugins, ...rest } = props;\n const content = node[NodeTypes.INSERTION];\n\n // `html()`/`markdown()` nodes carry their `{{ … }}` placeholders\n // inside a raw string. Interpolate into that string, then re-run the\n // transform so the html/markdown renderer applies afterwards.\n if (isInterpolableWrapperNode(content)) {\n return (args: Record<string, string | number> = {}) =>\n transformInterpolableNode(\n content,\n args,\n props,\n props.plugins,\n deepTransformNode\n );\n }\n\n // Return a function that performs the interpolation\n const render = (args: Record<string, string | number> = {}) => {\n let text = content as string;\n if (args) {\n Object.entries(args).forEach(([key, value]) => {\n text = text.replace(\n new RegExp(`{{\\\\s*${key}\\\\s*}}`, 'g'),\n String(value)\n );\n });\n }\n return text;\n };\n\n return renderIntlayerNode({\n ...rest,\n value: render as any,\n children: render,\n });\n },\n };\n\nexport interface IInterpreterPluginAngular<T, S, L extends LocalesValues> {\n angularIntlayerNode: IntlayerNodeCond<T>;\n angularMarkdown: MarkdownCond<T, S, L>;\n angularHtml: HTMLPluginCond<T, S, L>;\n angularInsertion: InsertionPluginCond<T>;\n}\n\n/**\n * Insert this type as param of `DeepTransformContent` to avoid `intlayer` package pollution.\n *\n * Otherwise the the `angular-intlayer` plugins will override the types of `intlayer` functions.\n */\nexport type IInterpreterPluginState = Omit<\n IInterpreterPluginStateCore,\n 'insertion' // Remove insertion type from core package\n> & {\n angularIntlayerNode: true;\n angularMarkdown: true;\n angularHtml: true;\n angularInsertion: true;\n};\n\nexport type DeepTransformContent<\n T,\n L extends LocalesValues = DeclaredLocales,\n> = DeepTransformContentCore<T, IInterpreterPluginState, L>;\n\nconst pluginsCache = new Map<string, Plugins[]>();\n\n/**\n * Get the plugins array for Angular content transformation.\n * This function is used by both getIntlayer and getDictionary to ensure consistent plugin configuration.\n */\nexport const getPlugins = (\n locale?: LocalesValues,\n fallback: boolean = true\n): Plugins[] => {\n const currentLocale = locale ?? internationalization.defaultLocale;\n const cacheKey = `${currentLocale}_${fallback}`;\n\n if (pluginsCache.has(cacheKey)) {\n return pluginsCache.get(cacheKey)!;\n }\n\n const plugins = [\n translationPlugin(\n locale ?? internationalization.defaultLocale,\n fallback ? internationalization.defaultLocale : undefined\n ),\n enumerationPlugin,\n pluralPlugin(locale ?? internationalization.defaultLocale),\n conditionPlugin,\n nestedPlugin(locale ?? internationalization.defaultLocale),\n filePlugin,\n genderPlugin,\n selectPlugin,\n intlayerNodePlugins,\n markdownPlugin,\n htmlPlugin,\n insertionPlugin,\n ] as Plugins[];\n\n pluginsCache.set(cacheKey, plugins);\n\n return plugins;\n};\n"],"mappings":"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"}
@@ -1,8 +1,8 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
2
+ let node_module = require("node:module");
2
3
  let node_path = require("node:path");
3
4
  let _intlayer_config_node = require("@intlayer/config/node");
4
5
  let _intlayer_config_utils = require("@intlayer/config/utils");
5
- let node_module = require("node:module");
6
6
  let _intlayer_webpack = require("@intlayer/webpack");
7
7
  let defu = require("defu");
8
8
 
@@ -6,7 +6,7 @@ import { useDictionary } from "./useDictionary.mjs";
6
6
  import { useLoadDynamic } from "./useLoadDynamic.mjs";
7
7
  import { internationalization } from "@intlayer/config/built";
8
8
  import { computed, inject, signal } from "@angular/core";
9
- import { isQualifiedDynamicLoaderMap, parseDictionarySelector, resolveDictionaryArgument, resolveQualifiedDynamicContentAsync } from "@intlayer/core/dictionaryManipulator";
9
+ import { getPreloadedDictionary, isQualifiedDynamicLoaderMap, parseDictionarySelector, resolveDictionaryArgument, resolveQualifiedDynamicContentAsync } from "@intlayer/core/dictionaryManipulator";
10
10
 
11
11
  //#region src/client/useDictionaryDynamic.ts
12
12
  /**
@@ -42,7 +42,7 @@ const useDictionaryDynamic = (dictionaryPromise, key, localeOrSelector) => {
42
42
  }
43
43
  const locale = typeof localeOrSelector === "string" ? localeOrSelector : void 0;
44
44
  const localeTarget = computed(() => locale ?? intlayer?.locale() ?? internationalization.defaultLocale);
45
- const dictionary = useLoadDynamic(`${String(key)}.${localeTarget()}`, dictionaryPromise[localeTarget()]?.());
45
+ const dictionary = getPreloadedDictionary(dictionaryPromise, localeTarget()) ?? useLoadDynamic(`${String(key)}.${localeTarget()}`, dictionaryPromise[localeTarget()]?.());
46
46
  return useDictionary(dictionary, localeTarget());
47
47
  };
48
48
 
@@ -1 +1 @@
1
- {"version":3,"file":"useDictionaryDynamic.mjs","names":[],"sources":["../../../src/client/useDictionaryDynamic.ts"],"sourcesContent":["'use client';\n\nimport { computed, inject, signal } from '@angular/core';\nimport { internationalization } from '@intlayer/config/built';\nimport {\n isQualifiedDynamicLoaderMap,\n parseDictionarySelector,\n type QualifiedDynamicLoaderMap,\n resolveDictionaryArgument,\n resolveQualifiedDynamicContentAsync,\n} from '@intlayer/core/dictionaryManipulator';\nimport type { Dictionary } from '@intlayer/types/dictionary';\nimport type {\n DeclaredLocales,\n DictionaryKeys,\n DictionarySelectorForKey,\n LocalesValues,\n StrictModeLocaleMap,\n} from '@intlayer/types/module_augmentation';\nimport { getDictionary } from '../getDictionary';\nimport { INTLAYER_TOKEN, type IntlayerProvider } from './installIntlayer';\nimport { useDictionary } from './useDictionary';\nimport { useLoadDynamic } from './useLoadDynamic';\n\n/**\n * Lazily loads a dictionary (plain or qualified) and returns its reactive\n * content.\n *\n * For a qualified loader map (collection / variant, possibly\n * combined), only the chunk(s) the selector targets are loaded. For a plain\n * loader map, the locale chunk is loaded.\n *\n * If the locale is not provided (directly or through the selector), it will use\n * the locale from the client context.\n */\nexport const useDictionaryDynamic = <\n const T extends Dictionary,\n const K extends DictionaryKeys,\n const A extends LocalesValues | DictionarySelectorForKey<K> = DeclaredLocales,\n>(\n dictionaryPromise:\n | StrictModeLocaleMap<() => Promise<T>>\n | QualifiedDynamicLoaderMap,\n key: K,\n localeOrSelector?: A\n) => {\n const intlayer = inject<IntlayerProvider>(INTLAYER_TOKEN);\n\n if (\n process.env.INTLAYER_DICTIONARY_SELECTOR !== 'false' &&\n isQualifiedDynamicLoaderMap(dictionaryPromise)\n ) {\n // Layers the provider's ambient variant under the call-site argument\n // before the chunk walk, so only the targeted chunk is loaded.\n const { locale: selectorLocale, selector } =\n parseDictionarySelector<LocalesValues>(\n resolveDictionaryArgument({\n localeOrSelector,\n contextLocale: intlayer?.locale(),\n contextVariant: intlayer?.variant?.(),\n dictionaryKey: String(key),\n })\n );\n\n const localeTarget = selectorLocale ?? internationalization.defaultLocale;\n\n const container = signal<unknown>(undefined);\n\n resolveQualifiedDynamicContentAsync({\n loaderMap: dictionaryPromise,\n key: String(key),\n locale: localeTarget,\n selector,\n transform: (dictionary) => getDictionary(dictionary, localeTarget),\n }).then((resolved) => container.set(resolved));\n\n return computed(() => container() as any);\n }\n\n const locale =\n typeof localeOrSelector === 'string'\n ? (localeOrSelector as LocalesValues)\n : undefined;\n\n const localeTarget = computed(\n () => locale ?? intlayer?.locale() ?? internationalization.defaultLocale\n );\n\n const dictionary = useLoadDynamic<T>(\n `${String(key)}.${localeTarget()}`,\n (dictionaryPromise as any)[localeTarget()]?.()\n ) as T;\n\n return useDictionary(dictionary, localeTarget() as any);\n};\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;AAmCA,MAAa,wBAKX,mBAGA,KACA,qBACG;CACH,MAAM,WAAW,OAAyB,cAAc;CAExD,IACE,QAAQ,IAAI,iCAAiC,WAC7C,4BAA4B,iBAAiB,GAC7C;EAGA,MAAM,EAAE,QAAQ,gBAAgB,aAC9B,wBACE,0BAA0B;GACxB;GACA,eAAe,UAAU,OAAO;GAChC,gBAAgB,UAAU,UAAU;GACpC,eAAe,OAAO,GAAG;EAC3B,CAAC,CACH;EAEF,MAAM,eAAe,kBAAkB,qBAAqB;EAE5D,MAAM,YAAY,OAAgB,MAAS;EAE3C,oCAAoC;GAClC,WAAW;GACX,KAAK,OAAO,GAAG;GACf,QAAQ;GACR;GACA,YAAY,eAAe,cAAc,YAAY,YAAY;EACnE,CAAC,CAAC,CAAC,MAAM,aAAa,UAAU,IAAI,QAAQ,CAAC;EAE7C,OAAO,eAAe,UAAU,CAAQ;CAC1C;CAEA,MAAM,SACJ,OAAO,qBAAqB,WACvB,mBACD;CAEN,MAAM,eAAe,eACb,UAAU,UAAU,OAAO,KAAK,qBAAqB,aAC7D;CAEA,MAAM,aAAa,eACjB,GAAG,OAAO,GAAG,EAAE,GAAG,aAAa,KAC9B,kBAA0B,aAAa,EAAE,GAAG,CAC/C;CAEA,OAAO,cAAc,YAAY,aAAa,CAAQ;AACxD"}
1
+ {"version":3,"file":"useDictionaryDynamic.mjs","names":[],"sources":["../../../src/client/useDictionaryDynamic.ts"],"sourcesContent":["'use client';\n\nimport { computed, inject, signal } from '@angular/core';\nimport { internationalization } from '@intlayer/config/built';\nimport {\n getPreloadedDictionary,\n isQualifiedDynamicLoaderMap,\n parseDictionarySelector,\n type QualifiedDynamicLoaderMap,\n resolveDictionaryArgument,\n resolveQualifiedDynamicContentAsync,\n} from '@intlayer/core/dictionaryManipulator';\nimport type { Dictionary } from '@intlayer/types/dictionary';\nimport type {\n DeclaredLocales,\n DictionaryKeys,\n DictionarySelectorForKey,\n LocalesValues,\n StrictModeLocaleMap,\n} from '@intlayer/types/module_augmentation';\nimport { getDictionary } from '../getDictionary';\nimport { INTLAYER_TOKEN, type IntlayerProvider } from './installIntlayer';\nimport { useDictionary } from './useDictionary';\nimport { useLoadDynamic } from './useLoadDynamic';\n\n/**\n * Lazily loads a dictionary (plain or qualified) and returns its reactive\n * content.\n *\n * For a qualified loader map (collection / variant, possibly\n * combined), only the chunk(s) the selector targets are loaded. For a plain\n * loader map, the locale chunk is loaded.\n *\n * If the locale is not provided (directly or through the selector), it will use\n * the locale from the client context.\n */\nexport const useDictionaryDynamic = <\n const T extends Dictionary,\n const K extends DictionaryKeys,\n const A extends LocalesValues | DictionarySelectorForKey<K> = DeclaredLocales,\n>(\n dictionaryPromise:\n | StrictModeLocaleMap<() => Promise<T>>\n | QualifiedDynamicLoaderMap,\n key: K,\n localeOrSelector?: A\n) => {\n const intlayer = inject<IntlayerProvider>(INTLAYER_TOKEN);\n\n if (\n process.env.INTLAYER_DICTIONARY_SELECTOR !== 'false' &&\n isQualifiedDynamicLoaderMap(dictionaryPromise)\n ) {\n // Layers the provider's ambient variant under the call-site argument\n // before the chunk walk, so only the targeted chunk is loaded.\n const { locale: selectorLocale, selector } =\n parseDictionarySelector<LocalesValues>(\n resolveDictionaryArgument({\n localeOrSelector,\n contextLocale: intlayer?.locale(),\n contextVariant: intlayer?.variant?.(),\n dictionaryKey: String(key),\n })\n );\n\n const localeTarget = selectorLocale ?? internationalization.defaultLocale;\n\n const container = signal<unknown>(undefined);\n\n resolveQualifiedDynamicContentAsync({\n loaderMap: dictionaryPromise,\n key: String(key),\n locale: localeTarget,\n selector,\n transform: (dictionary) => getDictionary(dictionary, localeTarget),\n }).then((resolved) => container.set(resolved));\n\n return computed(() => container() as any);\n }\n\n const locale =\n typeof localeOrSelector === 'string'\n ? (localeOrSelector as LocalesValues)\n : undefined;\n\n const localeTarget = computed(\n () => locale ?? intlayer?.locale() ?? internationalization.defaultLocale\n );\n\n // A build-tool plugin may have started this locale's chunk while the entry\n // point evaluated, and it may already have landed. Using it directly skips `useLoadDynamic`, whose signal\n // starts empty and only fills in on the promise callback — one frame of blank\n // content per dictionary, even when nothing has to be fetched.\n const preloadedDictionary = getPreloadedDictionary(\n dictionaryPromise,\n localeTarget()\n );\n\n const dictionary =\n (preloadedDictionary as T | undefined) ??\n (useLoadDynamic<T>(\n `${String(key)}.${localeTarget()}`,\n (dictionaryPromise as any)[localeTarget()]?.()\n ) as T);\n\n return useDictionary(dictionary, localeTarget() as any);\n};\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;AAoCA,MAAa,wBAKX,mBAGA,KACA,qBACG;CACH,MAAM,WAAW,OAAyB,cAAc;CAExD,IACE,QAAQ,IAAI,iCAAiC,WAC7C,4BAA4B,iBAAiB,GAC7C;EAGA,MAAM,EAAE,QAAQ,gBAAgB,aAC9B,wBACE,0BAA0B;GACxB;GACA,eAAe,UAAU,OAAO;GAChC,gBAAgB,UAAU,UAAU;GACpC,eAAe,OAAO,GAAG;EAC3B,CAAC,CACH;EAEF,MAAM,eAAe,kBAAkB,qBAAqB;EAE5D,MAAM,YAAY,OAAgB,MAAS;EAE3C,oCAAoC;GAClC,WAAW;GACX,KAAK,OAAO,GAAG;GACf,QAAQ;GACR;GACA,YAAY,eAAe,cAAc,YAAY,YAAY;EACnE,CAAC,CAAC,CAAC,MAAM,aAAa,UAAU,IAAI,QAAQ,CAAC;EAE7C,OAAO,eAAe,UAAU,CAAQ;CAC1C;CAEA,MAAM,SACJ,OAAO,qBAAqB,WACvB,mBACD;CAEN,MAAM,eAAe,eACb,UAAU,UAAU,OAAO,KAAK,qBAAqB,aAC7D;CAWA,MAAM,aALsB,uBAC1B,mBACA,aAAa,CAIM,KAClB,eACC,GAAG,OAAO,GAAG,EAAE,GAAG,aAAa,KAC9B,kBAA0B,aAAa,EAAE,GAAG,CAC/C;CAEF,OAAO,cAAc,YAAY,aAAa,CAAQ;AACxD"}
@@ -25,7 +25,7 @@ const useEditor = (client) => {
25
25
  import("@intlayer/editor").then(({ initEditorClient }) => {
26
26
  if (stopped) return;
27
27
  manager.set(initEditorClient());
28
- });
28
+ }).catch(() => {});
29
29
  const effectRef = runInInjectionContext(injector, () => effect(() => {
30
30
  const m = manager();
31
31
  const locale = resolvedClient?.locale();
@@ -37,7 +37,7 @@ const useEditor = (client) => {
37
37
  manager.set(null);
38
38
  import("@intlayer/editor").then(({ stopEditorClient }) => {
39
39
  stopEditorClient();
40
- });
40
+ }).catch(() => {});
41
41
  });
42
42
  };
43
43
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"useEditor.mjs","names":[],"sources":["../../../src/editor/useEditor.ts"],"sourcesContent":["import {\n DestroyRef,\n effect,\n Injector,\n inject,\n provideAppInitializer,\n runInInjectionContext,\n signal,\n} from '@angular/core';\nimport type { EditorStateManager } from '@intlayer/editor';\nimport { isEnabled } from '@intlayer/editor/isEnabled';\nimport type { Locale } from '@intlayer/types/allLocales';\n// Import from the standalone token file to avoid a circular dependency:\n// installIntlayer.ts → useEditor.ts → ../client → installIntlayer.ts\nimport { INTLAYER_TOKEN, type IntlayerProvider } from '../client/intlayerToken';\n\n/**\n * Initialises the Intlayer editor client singleton when the editor is enabled.\n * Syncs the current locale from the provided Intlayer client into the editor\n * manager so the editor always knows which locale the app is displaying.\n *\n * Must be called inside an Angular injection context (e.g. a component\n * constructor, `provideAppInitializer`, or `runInInjectionContext`).\n *\n * @param client - The IntlayerProvider instance to sync locale from.\n * When omitted the function injects `INTLAYER_TOKEN` from the DI tree,\n * so it still works when called directly from a component.\n */\nexport const useEditor = (client?: IntlayerProvider | null): void => {\n if (process.env.INTLAYER_EDITOR_ENABLED === 'false' || !isEnabled) return;\n\n const destroyRef = inject(DestroyRef, { optional: true });\n const injector = inject(Injector);\n\n // Resolve the client: use the passed-in reference or fall back to injection.\n const resolvedClient =\n client ??\n inject<IntlayerProvider>(INTLAYER_TOKEN, { optional: true } as any);\n\n // `manager` signal is set once the async import resolves.\n // Using a signal lets an `effect()` react to it becoming available.\n const manager = signal<EditorStateManager | null>(null);\n\n // Guard: prevents the async callback from acting after the view is destroyed.\n let stopped = false;\n\n // Initialise the editor client\n import('@intlayer/editor').then(({ initEditorClient }) => {\n if (stopped) return;\n manager.set(initEditorClient());\n });\n\n // Keep the editor locale in sync with the Angular locale signal\n const effectRef = runInInjectionContext(injector, () =>\n effect(() => {\n const m = manager();\n const locale = resolvedClient?.locale();\n if (m && locale) m.currentLocale.set(locale as Locale);\n })\n );\n\n // Tear down on destroy\n destroyRef?.onDestroy(() => {\n stopped = true;\n effectRef.destroy();\n manager.set(null);\n import('@intlayer/editor').then(({ stopEditorClient }) => {\n stopEditorClient();\n });\n });\n};\n\n/**\n * Angular provider that wires `useEditor` into the application initialisation\n * phase via `provideAppInitializer`.\n *\n * `provideIntlayer()` already calls this internally, so you only need this\n * function when you want to manage providers individually.\n *\n * @example\n * ```ts\n * // app.config.ts\n * import { provideIntlayer, provideIntlayerEditor } from 'angular-intlayer';\n *\n * export const appConfig: ApplicationConfig = {\n * providers: [provideIntlayer(), provideIntlayerEditor()],\n * };\n * ```\n */\nexport const provideIntlayerEditor = (client?: IntlayerProvider | null) =>\n provideAppInitializer(() => useEditor(client));\n"],"mappings":";;;;;;;;;;;;;;;;;AA4BA,MAAa,aAAa,WAA2C;CACnE,IAAI,QAAQ,IAAI,4BAA4B,WAAW,CAAC,WAAW;CAEnE,MAAM,aAAa,OAAO,YAAY,EAAE,UAAU,KAAK,CAAC;CACxD,MAAM,WAAW,OAAO,QAAQ;CAGhC,MAAM,iBACJ,UACA,OAAyB,gBAAgB,EAAE,UAAU,KAAK,CAAQ;CAIpE,MAAM,UAAU,OAAkC,IAAI;CAGtD,IAAI,UAAU;CAGd,OAAO,mBAAmB,CAAC,MAAM,EAAE,uBAAuB;EACxD,IAAI,SAAS;EACb,QAAQ,IAAI,iBAAiB,CAAC;CAChC,CAAC;CAGD,MAAM,YAAY,sBAAsB,gBACtC,aAAa;EACX,MAAM,IAAI,QAAQ;EAClB,MAAM,SAAS,gBAAgB,OAAO;EACtC,IAAI,KAAK,QAAQ,EAAE,cAAc,IAAI,MAAgB;CACvD,CAAC,CACH;CAGA,YAAY,gBAAgB;EAC1B,UAAU;EACV,UAAU,QAAQ;EAClB,QAAQ,IAAI,IAAI;EAChB,OAAO,mBAAmB,CAAC,MAAM,EAAE,uBAAuB;GACxD,iBAAiB;EACnB,CAAC;CACH,CAAC;AACH;;;;;;;;;;;;;;;;;;AAmBA,MAAa,yBAAyB,WACpC,4BAA4B,UAAU,MAAM,CAAC"}
1
+ {"version":3,"file":"useEditor.mjs","names":[],"sources":["../../../src/editor/useEditor.ts"],"sourcesContent":["import {\n DestroyRef,\n effect,\n Injector,\n inject,\n provideAppInitializer,\n runInInjectionContext,\n signal,\n} from '@angular/core';\nimport type { EditorStateManager } from '@intlayer/editor';\nimport { isEnabled } from '@intlayer/editor/isEnabled';\nimport type { Locale } from '@intlayer/types/allLocales';\n// Import from the standalone token file to avoid a circular dependency:\n// installIntlayer.ts → useEditor.ts → ../client → installIntlayer.ts\nimport { INTLAYER_TOKEN, type IntlayerProvider } from '../client/intlayerToken';\n\n/**\n * Initialises the Intlayer editor client singleton when the editor is enabled.\n * Syncs the current locale from the provided Intlayer client into the editor\n * manager so the editor always knows which locale the app is displaying.\n *\n * Must be called inside an Angular injection context (e.g. a component\n * constructor, `provideAppInitializer`, or `runInInjectionContext`).\n *\n * @param client - The IntlayerProvider instance to sync locale from.\n * When omitted the function injects `INTLAYER_TOKEN` from the DI tree,\n * so it still works when called directly from a component.\n */\nexport const useEditor = (client?: IntlayerProvider | null): void => {\n if (process.env.INTLAYER_EDITOR_ENABLED === 'false' || !isEnabled) return;\n\n const destroyRef = inject(DestroyRef, { optional: true });\n const injector = inject(Injector);\n\n // Resolve the client: use the passed-in reference or fall back to injection.\n const resolvedClient =\n client ??\n inject<IntlayerProvider>(INTLAYER_TOKEN, { optional: true } as any);\n\n // `manager` signal is set once the async import resolves.\n // Using a signal lets an `effect()` react to it becoming available.\n const manager = signal<EditorStateManager | null>(null);\n\n // Guard: prevents the async callback from acting after the view is destroyed.\n let stopped = false;\n\n // Initialise the editor client\n import('@intlayer/editor')\n .then(({ initEditorClient }) => {\n if (stopped) return;\n manager.set(initEditorClient());\n })\n .catch(() => {});\n\n // Keep the editor locale in sync with the Angular locale signal\n const effectRef = runInInjectionContext(injector, () =>\n effect(() => {\n const m = manager();\n const locale = resolvedClient?.locale();\n if (m && locale) m.currentLocale.set(locale as Locale);\n })\n );\n\n // Tear down on destroy\n destroyRef?.onDestroy(() => {\n stopped = true;\n effectRef.destroy();\n manager.set(null);\n import('@intlayer/editor')\n .then(({ stopEditorClient }) => {\n stopEditorClient();\n })\n .catch(() => {});\n });\n};\n\n/**\n * Angular provider that wires `useEditor` into the application initialisation\n * phase via `provideAppInitializer`.\n *\n * `provideIntlayer()` already calls this internally, so you only need this\n * function when you want to manage providers individually.\n *\n * @example\n * ```ts\n * // app.config.ts\n * import { provideIntlayer, provideIntlayerEditor } from 'angular-intlayer';\n *\n * export const appConfig: ApplicationConfig = {\n * providers: [provideIntlayer(), provideIntlayerEditor()],\n * };\n * ```\n */\nexport const provideIntlayerEditor = (client?: IntlayerProvider | null) =>\n provideAppInitializer(() => useEditor(client));\n"],"mappings":";;;;;;;;;;;;;;;;;AA4BA,MAAa,aAAa,WAA2C;CACnE,IAAI,QAAQ,IAAI,4BAA4B,WAAW,CAAC,WAAW;CAEnE,MAAM,aAAa,OAAO,YAAY,EAAE,UAAU,KAAK,CAAC;CACxD,MAAM,WAAW,OAAO,QAAQ;CAGhC,MAAM,iBACJ,UACA,OAAyB,gBAAgB,EAAE,UAAU,KAAK,CAAQ;CAIpE,MAAM,UAAU,OAAkC,IAAI;CAGtD,IAAI,UAAU;CAGd,OAAO,mBAAmB,CACvB,MAAM,EAAE,uBAAuB;EAC9B,IAAI,SAAS;EACb,QAAQ,IAAI,iBAAiB,CAAC;CAChC,CAAC,CAAC,CACD,YAAY,CAAC,CAAC;CAGjB,MAAM,YAAY,sBAAsB,gBACtC,aAAa;EACX,MAAM,IAAI,QAAQ;EAClB,MAAM,SAAS,gBAAgB,OAAO;EACtC,IAAI,KAAK,QAAQ,EAAE,cAAc,IAAI,MAAgB;CACvD,CAAC,CACH;CAGA,YAAY,gBAAgB;EAC1B,UAAU;EACV,UAAU,QAAQ;EAClB,QAAQ,IAAI,IAAI;EAChB,OAAO,mBAAmB,CACvB,MAAM,EAAE,uBAAuB;GAC9B,iBAAiB;EACnB,CAAC,CAAC,CACD,YAAY,CAAC,CAAC;CACnB,CAAC;AACH;;;;;;;;;;;;;;;;;;AAmBA,MAAa,yBAAyB,WACpC,4BAA4B,UAAU,MAAM,CAAC"}
@@ -1,8 +1,12 @@
1
+ import { __require } from "../_virtual/_rolldown/runtime.mjs";
2
+ import { createRequire } from "node:module";
1
3
  import { join } from "node:path";
4
+ import { getConfiguration } from "@intlayer/config/node";
5
+ import { getAlias, getHasDictionarySelector, getUnusedNodeTypesAsync, normalizePath } from "@intlayer/config/utils";
6
+ import { readFile } from "node:fs/promises";
7
+ import { addDynamicEntryPreload, createDynamicEntryFilter, resolvePreloadModuleId } from "@intlayer/config/dictionaryPreload";
2
8
  import { formatDictionarySelectorEnvVar, formatNodeTypeToEnvVar, getConfigEnvVars } from "@intlayer/config/envVars";
3
9
  import { getAppLogger } from "@intlayer/config/logger";
4
- import { getConfiguration } from "@intlayer/config/node";
5
- import { getAlias, getHasDictionarySelector, getUnusedNodeTypesAsync } from "@intlayer/config/utils";
6
10
  import { getDictionaries } from "@intlayer/dictionaries-entry";
7
11
  import { prepareIntlayer } from "@intlayer/engine/build";
8
12
  import { logConfigDetails } from "@intlayer/engine/cli";
@@ -10,6 +14,18 @@ import { watch } from "@intlayer/engine/watcher";
10
14
 
11
15
  //#region src/esbuild/plugin.ts
12
16
  /**
17
+ * Absolute id of the locale resolver the injected preamble imports.
18
+ *
19
+ * Resolved from this package, which declares `@intlayer/core` as a dependency,
20
+ * rather than left bare in the emitted source: the importer is a generated
21
+ * entry point under the application's `.intlayer` directory, and an application
22
+ * only depends on `intlayer` and its framework binding, so the bare specifier
23
+ * would resolve from a tree that need not contain the package at all.
24
+ *
25
+ * This package ships both module formats, hence the `require` fallback.
26
+ */
27
+ const preloadModuleId = normalizePath(resolvePreloadModuleId(typeof __require !== "undefined" ? __require : createRequire(import.meta.url)));
28
+ /**
13
29
  * esbuild plugin that integrates Intlayer into the Angular (or any esbuild-based) build process.
14
30
  *
15
31
  * Handles:
@@ -85,6 +101,19 @@ const intlayerEsbuildPlugin = (options) => {
85
101
  const escapedFrom = from.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
86
102
  build.onResolve({ filter: new RegExp(`^${escapedFrom}$`) }, () => ({ path: to }));
87
103
  }
104
+ if (config.build.dictionariesPreload) {
105
+ const dynamicDictionariesDir = normalizePath(config.system.dynamicDictionariesDir);
106
+ build.onLoad({ filter: createDynamicEntryFilter(dynamicDictionariesDir) }, async ({ path }) => {
107
+ if (!normalizePath(path).startsWith(`${dynamicDictionariesDir}/`)) return null;
108
+ const code = await readFile(path, "utf-8");
109
+ const result = addDynamicEntryPreload(code, preloadModuleId);
110
+ if (result.skipped) return null;
111
+ return {
112
+ contents: result.code,
113
+ loader: "js"
114
+ };
115
+ });
116
+ }
88
117
  if (!preparePromise) preparePromise = prepareIntlayer(config, {
89
118
  clean: isProduction,
90
119
  cacheTimeoutMs: isProduction ? 3e4 : 36e5,
@@ -1 +1 @@
1
- {"version":3,"file":"plugin.mjs","names":[],"sources":["../../../src/esbuild/plugin.ts"],"sourcesContent":["import { join } from 'node:path';\nimport {\n formatDictionarySelectorEnvVar,\n formatNodeTypeToEnvVar,\n getConfigEnvVars,\n} from '@intlayer/config/envVars';\nimport { getAppLogger } from '@intlayer/config/logger';\nimport {\n type GetConfigurationOptions,\n getConfiguration,\n} from '@intlayer/config/node';\nimport {\n getAlias,\n getHasDictionarySelector,\n getUnusedNodeTypesAsync,\n} from '@intlayer/config/utils';\nimport { getDictionaries } from '@intlayer/dictionaries-entry';\nimport { prepareIntlayer } from '@intlayer/engine/build';\nimport { logConfigDetails } from '@intlayer/engine/cli';\nimport { watch } from '@intlayer/engine/watcher';\n\n// Minimal subset of the esbuild Plugin interface to avoid a hard dependency on\n// the `esbuild` package for type resolution. The shape is compatible with\n// esbuild >=0.17, `@angular-builders/custom-esbuild`, and NX esbuild builders.\nexport interface EsbuildPluginBuild {\n initialOptions: {\n alias?: Record<string, string>;\n define?: Record<string, string>;\n minify?: boolean;\n watch?: unknown;\n /** Absolute working directory of the esbuild context (set by Angular's builder). */\n absWorkingDir?: string;\n };\n onStart(callback: () => void | Promise<void>): void;\n /** Intercept module resolution — works even for imports inside node_modules. */\n onResolve(\n options: { filter: RegExp; namespace?: string },\n callback: (args: {\n path: string;\n importer: string;\n namespace: string;\n resolveDir: string;\n }) => { path: string; namespace?: string } | null | undefined\n ): void;\n}\n\nexport interface EsbuildPlugin {\n name: string;\n setup(build: EsbuildPluginBuild): void | Promise<void>;\n}\n\nexport type IntlayerEsbuildPluginOptions = {\n configOptions?: GetConfigurationOptions;\n /**\n * Whether to start the Intlayer file watcher for dictionary regeneration.\n * - `true`: always start the watcher (useful for `ng serve`)\n * - `false`: never start the watcher (useful for `ng build`)\n * - `undefined` (default): auto-detect based on the build context\n * (skips the watcher when a production build is detected)\n */\n watch?: boolean;\n};\n\n/**\n * esbuild plugin that integrates Intlayer into the Angular (or any esbuild-based) build process.\n *\n * Handles:\n * 1. Injecting `alias` entries so `@intlayer/dictionaries-entry` etc. resolve to\n * the generated files under `.intlayer/`.\n * 2. Defining `process.env.*` tree-shaking constants for production builds.\n * 3. Running `prepareIntlayer` (dictionary generation) before the first build.\n * 4. Starting the chokidar file-watcher in dev / serve mode.\n *\n * Compatible with:\n * - `@angular-builders/custom-esbuild` (`application` or `browser-esbuild` builder)\n * - NX `@nx/angular:browser-esbuild`\n * - Any raw esbuild setup that accepts the standard `Plugin` interface\n *\n * @example\n * ```ts\n * // esbuild.plugins.ts (referenced from angular.json \"plugins\" option)\n * import { intlayerEsbuildPlugin } from 'angular-intlayer/esbuild';\n * export default [intlayerEsbuildPlugin()];\n * ```\n */\nexport const intlayerEsbuildPlugin = (\n options?: IntlayerEsbuildPluginOptions\n): EsbuildPlugin => {\n // All Node.js-heavy initialization (getConfiguration, getAlias, …) is deferred\n // into setup() so it runs in esbuild's Node.js context, not at module-evaluation\n // time. @angular/build loads the plugin file through Vite's SSR module runner\n // (ESM) where CommonJS globals like __filename are undefined. Calling\n // getConfiguration() here would trigger: buildSync → worker threads →\n // __filename → ReferenceError, crashing the plugin before setup() ever runs.\n let config: ReturnType<typeof getConfiguration> | null = null;\n let alias: Record<string, string> | null = null;\n\n // Shared across parallel setup() calls (Angular spawns one per bundle context).\n let preparePromise: Promise<void> | null = null;\n let watcherStarted = false;\n // Once any esbuild context (browser or server) detects a production build,\n // suppress the watcher for all contexts so `ng build` can exit cleanly.\n let isBuildMode = false;\n\n return {\n name: 'intlayer',\n\n async setup(build) {\n if (!config) {\n const baseDir =\n build.initialOptions.absWorkingDir ??\n options?.configOptions?.baseDir ??\n process.cwd();\n\n config = getConfiguration({ baseDir, ...options?.configOptions });\n logConfigDetails({ baseDir, ...options?.configOptions });\n\n alias = getAlias({\n configuration: config,\n formatter: (value: string) => join(config!.system.baseDir, value),\n });\n }\n\n const appLogger = getAppLogger(config);\n const nodeEnvDefine =\n build.initialOptions.define?.['process.env.NODE_ENV'];\n\n // Angular's esbuild builder doesn't set `minify` or `process.env.NODE_ENV`\n // on initialOptions — it handles optimisation through its own pipeline.\n // Instead, Angular defines `ngDevMode` as `\"false\"` in production builds.\n const isProduction =\n nodeEnvDefine === '\"production\"' ||\n nodeEnvDefine === \"'production'\" ||\n build.initialOptions.minify === true ||\n build.initialOptions.define?.['ngDevMode'] === 'false';\n\n if (isProduction) {\n isBuildMode = true;\n }\n\n const wrapKey = (key: string) => `process.env.${key}`;\n const wrapValue = (value: string) => `\"${value}\"`;\n\n const envVars: Record<string, string> = {\n // Catch-all so that any `process.env.*` read NOT covered by a specific\n // key below resolves to `undefined` instead of dereferencing a bare\n // `process`, which is not defined in browser bundles and throws\n // `process is not defined`. esbuild resolves the most specific define\n // first, so the keys below keep their tree-shaking effect.\n 'process.env': '{}',\n [wrapKey('INTLAYER')]: wrapValue('true'),\n [wrapKey('NODE_ENV')]: wrapValue(\n isProduction ? 'production' : 'development'\n ),\n // Tree shaking flags derived from the config (routing / storage /\n // editor). Emitted in every mode so behaviour is consistent in dev.\n ...getConfigEnvVars(config, wrapKey, wrapValue),\n };\n\n if (isProduction) {\n const dictionaries = getDictionaries(config);\n if (Object.keys(dictionaries).length === 0) {\n appLogger('No dictionaries found. Please check your configuration.', {\n isVerbose: true,\n });\n }\n\n const unusedNodeTypes = await getUnusedNodeTypesAsync(dictionaries);\n Object.assign(\n envVars,\n // Tree shaking based on unused node types\n formatNodeTypeToEnvVar(unusedNodeTypes, wrapKey, wrapValue),\n // Tree shaking the dictionary selector logic\n // (collections / variants)\n formatDictionarySelectorEnvVar(\n getHasDictionarySelector(dictionaries),\n wrapKey,\n wrapValue\n )\n );\n }\n\n // Existing defines (Angular's own, or the user's angular.json `define`\n // block) take precedence over the Intlayer ones.\n build.initialOptions.define = {\n ...envVars,\n ...(build.initialOptions.define ?? {}),\n };\n\n build.initialOptions.alias = {\n ...alias,\n ...(build.initialOptions.alias ?? {}),\n };\n\n for (const [from, to] of Object.entries(alias!)) {\n const escapedFrom = from.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n\n build.onResolve({ filter: new RegExp(`^${escapedFrom}$`) }, () => ({\n path: to,\n }));\n }\n\n if (!preparePromise) {\n preparePromise = prepareIntlayer(config, {\n clean: isProduction,\n cacheTimeoutMs: isProduction ? 1000 * 30 : 1000 * 60 * 60,\n env: isProduction ? 'prod' : 'dev',\n });\n }\n\n await preparePromise;\n\n build.onStart(async () => {\n // Determine whether the watcher should run:\n // 1. Explicit option from the caller takes precedence\n // 2. If any esbuild context detected a production build, skip\n // 3. esbuild's own watch mode is a positive signal\n const shouldWatch = options?.watch ?? !isBuildMode;\n\n if (shouldWatch && !watcherStarted) {\n watcherStarted = true;\n\n await watch({ configuration: config! });\n }\n });\n },\n };\n};\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAqFA,MAAa,yBACX,YACkB;CAOlB,IAAI,SAAqD;CACzD,IAAI,QAAuC;CAG3C,IAAI,iBAAuC;CAC3C,IAAI,iBAAiB;CAGrB,IAAI,cAAc;CAElB,OAAO;EACL,MAAM;EAEN,MAAM,MAAM,OAAO;GACjB,IAAI,CAAC,QAAQ;IACX,MAAM,UACJ,MAAM,eAAe,iBACrB,SAAS,eAAe,WACxB,QAAQ,IAAI;IAEd,SAAS,iBAAiB;KAAE;KAAS,GAAG,SAAS;IAAc,CAAC;IAChE,iBAAiB;KAAE;KAAS,GAAG,SAAS;IAAc,CAAC;IAEvD,QAAQ,SAAS;KACf,eAAe;KACf,YAAY,UAAkB,KAAK,OAAQ,OAAO,SAAS,KAAK;IAClE,CAAC;GACH;GAEA,MAAM,YAAY,aAAa,MAAM;GACrC,MAAM,gBACJ,MAAM,eAAe,SAAS;GAKhC,MAAM,eACJ,kBAAkB,oBAClB,kBAAkB,kBAClB,MAAM,eAAe,WAAW,QAChC,MAAM,eAAe,SAAS,iBAAiB;GAEjD,IAAI,cACF,cAAc;GAGhB,MAAM,WAAW,QAAgB,eAAe;GAChD,MAAM,aAAa,UAAkB,IAAI,MAAM;GAE/C,MAAM,UAAkC;IAMtC,eAAe;KACd,QAAQ,UAAU,IAAI,UAAU,MAAM;KACtC,QAAQ,UAAU,IAAI,UACrB,eAAe,eAAe,aAChC;IAGA,GAAG,iBAAiB,QAAQ,SAAS,SAAS;GAChD;GAEA,IAAI,cAAc;IAChB,MAAM,eAAe,gBAAgB,MAAM;IAC3C,IAAI,OAAO,KAAK,YAAY,CAAC,CAAC,WAAW,GACvC,UAAU,2DAA2D,EACnE,WAAW,KACb,CAAC;IAGH,MAAM,kBAAkB,MAAM,wBAAwB,YAAY;IAClE,OAAO,OACL,SAEA,uBAAuB,iBAAiB,SAAS,SAAS,GAG1D,+BACE,yBAAyB,YAAY,GACrC,SACA,SACF,CACF;GACF;GAIA,MAAM,eAAe,SAAS;IAC5B,GAAG;IACH,GAAI,MAAM,eAAe,UAAU,CAAC;GACtC;GAEA,MAAM,eAAe,QAAQ;IAC3B,GAAG;IACH,GAAI,MAAM,eAAe,SAAS,CAAC;GACrC;GAEA,KAAK,MAAM,CAAC,MAAM,OAAO,OAAO,QAAQ,KAAM,GAAG;IAC/C,MAAM,cAAc,KAAK,QAAQ,uBAAuB,MAAM;IAE9D,MAAM,UAAU,EAAE,QAAQ,IAAI,OAAO,IAAI,YAAY,EAAE,EAAE,UAAU,EACjE,MAAM,GACR,EAAE;GACJ;GAEA,IAAI,CAAC,gBACH,iBAAiB,gBAAgB,QAAQ;IACvC,OAAO;IACP,gBAAgB,eAAe,MAAY;IAC3C,KAAK,eAAe,SAAS;GAC/B,CAAC;GAGH,MAAM;GAEN,MAAM,QAAQ,YAAY;IAOxB,KAFoB,SAAS,SAAS,CAAC,gBAEpB,CAAC,gBAAgB;KAClC,iBAAiB;KAEjB,MAAM,MAAM,EAAE,eAAe,OAAQ,CAAC;IACxC;GACF,CAAC;EACH;CACF;AACF"}
1
+ {"version":3,"file":"plugin.mjs","names":[],"sources":["../../../src/esbuild/plugin.ts"],"sourcesContent":["import { readFile } from 'node:fs/promises';\nimport { createRequire } from 'node:module';\nimport { join } from 'node:path';\nimport {\n addDynamicEntryPreload,\n createDynamicEntryFilter,\n resolvePreloadModuleId,\n} from '@intlayer/config/dictionaryPreload';\nimport {\n formatDictionarySelectorEnvVar,\n formatNodeTypeToEnvVar,\n getConfigEnvVars,\n} from '@intlayer/config/envVars';\nimport { getAppLogger } from '@intlayer/config/logger';\nimport {\n type GetConfigurationOptions,\n getConfiguration,\n} from '@intlayer/config/node';\nimport {\n getAlias,\n getHasDictionarySelector,\n getUnusedNodeTypesAsync,\n normalizePath,\n} from '@intlayer/config/utils';\nimport { getDictionaries } from '@intlayer/dictionaries-entry';\nimport { prepareIntlayer } from '@intlayer/engine/build';\nimport { logConfigDetails } from '@intlayer/engine/cli';\nimport { watch } from '@intlayer/engine/watcher';\n\n/**\n * Absolute id of the locale resolver the injected preamble imports.\n *\n * Resolved from this package, which declares `@intlayer/core` as a dependency,\n * rather than left bare in the emitted source: the importer is a generated\n * entry point under the application's `.intlayer` directory, and an application\n * only depends on `intlayer` and its framework binding, so the bare specifier\n * would resolve from a tree that need not contain the package at all.\n *\n * This package ships both module formats, hence the `require` fallback.\n */\nconst preloadModuleId = normalizePath(\n resolvePreloadModuleId(\n typeof require !== 'undefined' ? require : createRequire(import.meta.url)\n )\n);\n\n// Minimal subset of the esbuild Plugin interface to avoid a hard dependency on\n// the `esbuild` package for type resolution. The shape is compatible with\n// esbuild >=0.17, `@angular-builders/custom-esbuild`, and NX esbuild builders.\nexport interface EsbuildPluginBuild {\n initialOptions: {\n alias?: Record<string, string>;\n define?: Record<string, string>;\n minify?: boolean;\n watch?: unknown;\n /** Absolute working directory of the esbuild context (set by Angular's builder). */\n absWorkingDir?: string;\n };\n onStart(callback: () => void | Promise<void>): void;\n /** Intercept module resolution — works even for imports inside node_modules. */\n onResolve(\n options: { filter: RegExp; namespace?: string },\n callback: (args: {\n path: string;\n importer: string;\n namespace: string;\n resolveDir: string;\n }) => { path: string; namespace?: string } | null | undefined\n ): void;\n /** Intercept module contents, so a resolved file can be rewritten. */\n onLoad(\n options: { filter: RegExp; namespace?: string },\n callback: (args: {\n path: string;\n namespace: string;\n }) =>\n | { contents: string; loader?: string }\n | null\n | undefined\n | Promise<{ contents: string; loader?: string } | null | undefined>\n ): void;\n}\n\nexport interface EsbuildPlugin {\n name: string;\n setup(build: EsbuildPluginBuild): void | Promise<void>;\n}\n\nexport type IntlayerEsbuildPluginOptions = {\n configOptions?: GetConfigurationOptions;\n /**\n * Whether to start the Intlayer file watcher for dictionary regeneration.\n * - `true`: always start the watcher (useful for `ng serve`)\n * - `false`: never start the watcher (useful for `ng build`)\n * - `undefined` (default): auto-detect based on the build context\n * (skips the watcher when a production build is detected)\n */\n watch?: boolean;\n};\n\n/**\n * esbuild plugin that integrates Intlayer into the Angular (or any esbuild-based) build process.\n *\n * Handles:\n * 1. Injecting `alias` entries so `@intlayer/dictionaries-entry` etc. resolve to\n * the generated files under `.intlayer/`.\n * 2. Defining `process.env.*` tree-shaking constants for production builds.\n * 3. Running `prepareIntlayer` (dictionary generation) before the first build.\n * 4. Starting the chokidar file-watcher in dev / serve mode.\n *\n * Compatible with:\n * - `@angular-builders/custom-esbuild` (`application` or `browser-esbuild` builder)\n * - NX `@nx/angular:browser-esbuild`\n * - Any raw esbuild setup that accepts the standard `Plugin` interface\n *\n * @example\n * ```ts\n * // esbuild.plugins.ts (referenced from angular.json \"plugins\" option)\n * import { intlayerEsbuildPlugin } from 'angular-intlayer/esbuild';\n * export default [intlayerEsbuildPlugin()];\n * ```\n */\nexport const intlayerEsbuildPlugin = (\n options?: IntlayerEsbuildPluginOptions\n): EsbuildPlugin => {\n // All Node.js-heavy initialization (getConfiguration, getAlias, …) is deferred\n // into setup() so it runs in esbuild's Node.js context, not at module-evaluation\n // time. @angular/build loads the plugin file through Vite's SSR module runner\n // (ESM) where CommonJS globals like __filename are undefined. Calling\n // getConfiguration() here would trigger: buildSync → worker threads →\n // __filename → ReferenceError, crashing the plugin before setup() ever runs.\n let config: ReturnType<typeof getConfiguration> | null = null;\n let alias: Record<string, string> | null = null;\n\n // Shared across parallel setup() calls (Angular spawns one per bundle context).\n let preparePromise: Promise<void> | null = null;\n let watcherStarted = false;\n // Once any esbuild context (browser or server) detects a production build,\n // suppress the watcher for all contexts so `ng build` can exit cleanly.\n let isBuildMode = false;\n\n return {\n name: 'intlayer',\n\n async setup(build) {\n if (!config) {\n const baseDir =\n build.initialOptions.absWorkingDir ??\n options?.configOptions?.baseDir ??\n process.cwd();\n\n config = getConfiguration({ baseDir, ...options?.configOptions });\n logConfigDetails({ baseDir, ...options?.configOptions });\n\n alias = getAlias({\n configuration: config,\n formatter: (value: string) => join(config!.system.baseDir, value),\n });\n }\n\n const appLogger = getAppLogger(config);\n const nodeEnvDefine =\n build.initialOptions.define?.['process.env.NODE_ENV'];\n\n // Angular's esbuild builder doesn't set `minify` or `process.env.NODE_ENV`\n // on initialOptions — it handles optimisation through its own pipeline.\n // Instead, Angular defines `ngDevMode` as `\"false\"` in production builds.\n const isProduction =\n nodeEnvDefine === '\"production\"' ||\n nodeEnvDefine === \"'production'\" ||\n build.initialOptions.minify === true ||\n build.initialOptions.define?.['ngDevMode'] === 'false';\n\n if (isProduction) {\n isBuildMode = true;\n }\n\n const wrapKey = (key: string) => `process.env.${key}`;\n const wrapValue = (value: string) => `\"${value}\"`;\n\n const envVars: Record<string, string> = {\n // Catch-all so that any `process.env.*` read NOT covered by a specific\n // key below resolves to `undefined` instead of dereferencing a bare\n // `process`, which is not defined in browser bundles and throws\n // `process is not defined`. esbuild resolves the most specific define\n // first, so the keys below keep their tree-shaking effect.\n 'process.env': '{}',\n [wrapKey('INTLAYER')]: wrapValue('true'),\n [wrapKey('NODE_ENV')]: wrapValue(\n isProduction ? 'production' : 'development'\n ),\n // Tree shaking flags derived from the config (routing / storage /\n // editor). Emitted in every mode so behaviour is consistent in dev.\n ...getConfigEnvVars(config, wrapKey, wrapValue),\n };\n\n if (isProduction) {\n const dictionaries = getDictionaries(config);\n if (Object.keys(dictionaries).length === 0) {\n appLogger('No dictionaries found. Please check your configuration.', {\n isVerbose: true,\n });\n }\n\n const unusedNodeTypes = await getUnusedNodeTypesAsync(dictionaries);\n Object.assign(\n envVars,\n // Tree shaking based on unused node types\n formatNodeTypeToEnvVar(unusedNodeTypes, wrapKey, wrapValue),\n // Tree shaking the dictionary selector logic\n // (collections / variants)\n formatDictionarySelectorEnvVar(\n getHasDictionarySelector(dictionaries),\n wrapKey,\n wrapValue\n )\n );\n }\n\n // Existing defines (Angular's own, or the user's angular.json `define`\n // block) take precedence over the Intlayer ones.\n build.initialOptions.define = {\n ...envVars,\n ...(build.initialOptions.define ?? {}),\n };\n\n build.initialOptions.alias = {\n ...alias,\n ...(build.initialOptions.alias ?? {}),\n };\n\n for (const [from, to] of Object.entries(alias!)) {\n const escapedFrom = from.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n\n build.onResolve({ filter: new RegExp(`^${escapedFrom}$`) }, () => ({\n path: to,\n }));\n }\n\n // Dictionaries load with the chunk that needs them rather than being\n // fetched once that chunk renders: the entry point starts the browsing\n // locale's load as it evaluates, so a lazily loaded route requests its\n // content on `import()` instead of on first render. Without it every\n // dictionary read renders an empty placeholder first and fills in a tick\n // later.\n //\n // Not gated on the configured `importMode`: a `.content` file can set\n // `importMode: 'dynamic'` on a single dictionary under a `static` or\n // `fetch` global mode, and that dictionary needs the preload just the\n // same. Only entry points the optimizer imported are ever loaded, so the\n // path check below is the accurate gate.\n if (config.build.dictionariesPreload) {\n const dynamicDictionariesDir = normalizePath(\n config.system.dynamicDictionariesDir\n );\n\n build.onLoad(\n { filter: createDynamicEntryFilter(dynamicDictionariesDir) },\n async ({ path }) => {\n const posixPath = normalizePath(path);\n if (!posixPath.startsWith(`${dynamicDictionariesDir}/`))\n return null;\n\n const code = await readFile(path, 'utf-8');\n const result = addDynamicEntryPreload(code, preloadModuleId);\n\n if (result.skipped) return null;\n\n return { contents: result.code, loader: 'js' };\n }\n );\n }\n\n if (!preparePromise) {\n preparePromise = prepareIntlayer(config, {\n clean: isProduction,\n cacheTimeoutMs: isProduction ? 1000 * 30 : 1000 * 60 * 60,\n env: isProduction ? 'prod' : 'dev',\n });\n }\n\n await preparePromise;\n\n build.onStart(async () => {\n // Determine whether the watcher should run:\n // 1. Explicit option from the caller takes precedence\n // 2. If any esbuild context detected a production build, skip\n // 3. esbuild's own watch mode is a positive signal\n const shouldWatch = options?.watch ?? !isBuildMode;\n\n if (shouldWatch && !watcherStarted) {\n watcherStarted = true;\n\n await watch({ configuration: config! });\n }\n });\n },\n };\n};\n"],"mappings":"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"}
@@ -10,7 +10,7 @@ import * as NodeTypes from "@intlayer/types/nodeType";
10
10
  let _markdownInstall = null;
11
11
  if (process.env.INTLAYER_NODE_TYPE_MARKDOWN !== "false" || process.env.INTLAYER_NODE_TYPE_HTML !== "false") import("./markdown/installIntlayerMarkdown.mjs").then((m) => {
12
12
  _markdownInstall = m;
13
- });
13
+ }).catch(() => {});
14
14
  /** ---------------------------------------------
15
15
  * UTILS
16
16
  * --------------------------------------------- */
@@ -1 +1 @@
1
- {"version":3,"file":"plugins.mjs","names":[],"sources":["../../src/plugins.ts"],"sourcesContent":["import { editor, internationalization } from '@intlayer/config/built';\nimport {\n conditionPlugin,\n type DeepTransformContent as DeepTransformContentCore,\n enumerationPlugin,\n fallbackPlugin,\n filePlugin,\n genderPlugin,\n type IInterpreterPluginState as IInterpreterPluginStateCore,\n isInterpolableWrapperNode,\n nestedPlugin,\n type Plugins,\n pluralPlugin,\n selectPlugin,\n transformInterpolableNode,\n translationPlugin,\n} from '@intlayer/core/interpreter';\nimport type { MarkdownContent } from '@intlayer/core/markdown';\nimport { compile, getMarkdownMetadata } from '@intlayer/core/markdown';\nimport type { HTMLContent, InsertionContent } from '@intlayer/core/transpiler';\nimport type { KeyPath } from '@intlayer/types/keyPath';\nimport type {\n DeclaredLocales,\n LocalesValues,\n} from '@intlayer/types/module_augmentation';\nimport type { NodeType } from '@intlayer/types/nodeType';\nimport * as NodeTypes from '@intlayer/types/nodeType';\nimport { reportExposure } from './analytics/exposureSink';\nimport { ContentSelectorWrapperComponent } from './editor/ContentSelector.component';\nimport { renderIntlayerNode } from './renderIntlayerNode';\n\nlet _markdownInstall: {\n htmlRuntime: any;\n useMarkdown: () => { renderMarkdown: (s: string, components?: any) => any };\n} | null = null;\nif (\n process.env.INTLAYER_NODE_TYPE_MARKDOWN !== 'false' ||\n process.env.INTLAYER_NODE_TYPE_HTML !== 'false'\n) {\n void import('./markdown/installIntlayerMarkdown').then((m) => {\n _markdownInstall = m as any;\n });\n}\n\n/** ---------------------------------------------\n * UTILS\n * --------------------------------------------- */\n\nconst createRuntimeWithOverides = (baseRuntime: any, overrides: any) => ({\n ...baseRuntime,\n createElement: (tag: string, props: any, ...children: any[]) => {\n const override = overrides?.[tag];\n\n if (override) {\n const newProps = { ...props, ...override };\n\n // Merge class attributes intelligently\n const originalClass = props?.class || props?.className;\n const overrideClass = override.class || override.className;\n\n if (originalClass && overrideClass) {\n newProps.class = `${originalClass} ${overrideClass}`;\n newProps.className = undefined;\n }\n\n return baseRuntime.createElement(tag, newProps, ...children);\n }\n\n return baseRuntime.createElement(tag, props, ...children);\n },\n});\n\n/** ---------------------------------------------\n * INTLAYER NODE PLUGIN\n * --------------------------------------------- */\n\nexport type IntlayerNodeCond<T> = T extends number | string\n ? IntlayerNode<T>\n : never;\n\nexport interface IntlayerNode<T, P = {}> {\n value: T;\n children?: any;\n additionalProps?: P;\n}\n\n/** Translation plugin. Replaces node with a locale string if nodeType = Translation. */\nexport const intlayerNodePlugins: Plugins = {\n id: 'intlayer-node-plugin',\n canHandle: (node) =>\n typeof node === 'bigint' ||\n typeof node === 'string' ||\n typeof node === 'number',\n transform: (_node, { children, ...rest }) => {\n // Node-level analytics: record which content is resolved for display.\n // No-op (and dead-code-eliminated) when analytics is disabled.\n if (process.env.INTLAYER_ANALYTICS_ENABLED !== 'false') {\n reportExposure({\n dictionaryKey: rest.dictionaryKey,\n keyPath: rest.keyPath,\n locale: rest.locale,\n nodeType: 'text',\n });\n }\n\n return renderIntlayerNode({\n ...rest,\n value: children,\n children: () => ({\n component:\n process.env.INTLAYER_EDITOR_ENABLED === 'false' || !editor.enabled\n ? children\n : ContentSelectorWrapperComponent,\n props: {\n dictionaryKey: rest.dictionaryKey,\n keyPath: rest.keyPath,\n },\n children: children,\n }),\n });\n },\n};\n\n/**\n * MARKDOWN PLUGIN\n */\n\nexport type MarkdownStringCond<T> = T extends string\n ? IntlayerNode<string, { metadata: DeepTransformContent<string> }>\n : never;\n\n/** Markdown string plugin. Replaces string node with a component that render the markdown. */\nexport const markdownStringPlugin: Plugins =\n process.env.INTLAYER_NODE_TYPE_MARKDOWN === 'false'\n ? fallbackPlugin\n : {\n id: 'markdown-string-plugin',\n canHandle: (node) => typeof node === 'string',\n transform: (node: string, props, deepTransformNode) => {\n const {\n plugins, // Removed to avoid next error - Functions cannot be passed directly to Client Components\n ...rest\n } = props;\n\n const metadata = getMarkdownMetadata(node) ?? {};\n\n const metadataPlugins: Plugins = {\n id: 'markdown-metadata-plugin',\n canHandle: (metadataNode) =>\n typeof metadataNode === 'string' ||\n typeof metadataNode === 'number' ||\n typeof metadataNode === 'boolean' ||\n !metadataNode,\n transform: (metadataNode, props) =>\n renderIntlayerNode({\n ...props,\n value: metadataNode,\n children: node,\n }),\n };\n\n // Transform metadata while keeping the same structure\n const metadataNodes = deepTransformNode(metadata, {\n plugins: [metadataPlugins],\n dictionaryKey: rest.dictionaryKey,\n keyPath: [],\n });\n\n const render = (components?: any) =>\n renderIntlayerNode({\n ...rest,\n value: node,\n children:\n process.env.INTLAYER_EDITOR_ENABLED === 'false' ||\n !editor.enabled\n ? () => {\n const { renderMarkdown } =\n _markdownInstall?.useMarkdown() ?? {\n renderMarkdown: () => node,\n };\n return renderMarkdown(node, components);\n }\n : () => ({\n component: ContentSelectorWrapperComponent,\n props: {\n dictionaryKey: rest.dictionaryKey,\n keyPath: rest.keyPath,\n ...components,\n },\n children: () => {\n const { renderMarkdown } =\n _markdownInstall?.useMarkdown() ?? {\n renderMarkdown: () => node,\n };\n return renderMarkdown(node, components);\n },\n }),\n additionalProps: {\n metadata: metadataNodes,\n },\n });\n\n const createProxy = (element: any, components?: any) =>\n new Proxy(element, {\n get(target, prop, receiver) {\n if (prop === 'value') {\n return node;\n }\n if (prop === 'metadata') {\n return metadataNodes;\n }\n\n if (prop === 'toString') {\n return () => {\n const htmlRuntime = _markdownInstall?.htmlRuntime;\n if (!htmlRuntime || !compile) return node;\n const runtime = components\n ? createRuntimeWithOverides(htmlRuntime, components)\n : htmlRuntime;\n return compile(node, { runtime }) as string;\n };\n }\n\n if (prop === Symbol.toPrimitive) {\n return () => {\n const htmlRuntime = _markdownInstall?.htmlRuntime;\n if (!htmlRuntime || !compile) return node;\n const runtime = components\n ? createRuntimeWithOverides(htmlRuntime, components)\n : htmlRuntime;\n return compile(node, { runtime }) as string;\n };\n }\n\n if (prop === 'use') {\n return (newComponents?: any) => {\n const mergedComponents = {\n ...components,\n ...newComponents,\n };\n return createProxy(\n render(mergedComponents),\n mergedComponents\n );\n };\n }\n\n return Reflect.get(target, prop, receiver);\n },\n }) as any;\n\n return createProxy(render() as any);\n },\n };\n\nexport type MarkdownCond<T, _S, _L extends LocalesValues> = T extends {\n nodeType: NodeType | string;\n [NodeTypes.MARKDOWN]: infer M;\n tags?: infer U;\n metadata?: infer V;\n}\n ? IntlayerNode<\n M,\n {\n use: (components?: Record<keyof U, any>) => any;\n metadata: DeepTransformContent<V>;\n }\n >\n : never;\n\nexport const markdownPlugin: Plugins =\n process.env.INTLAYER_NODE_TYPE_MARKDOWN === 'false'\n ? fallbackPlugin\n : {\n id: 'markdown-plugin',\n canHandle: (node) =>\n typeof node === 'object' && node?.nodeType === NodeTypes.MARKDOWN,\n transform: (node: MarkdownContent, props, deepTransformNode) => {\n const newKeyPath: KeyPath[] = [\n ...props.keyPath,\n {\n type: NodeTypes.MARKDOWN,\n },\n ];\n\n const children = node[NodeTypes.MARKDOWN];\n\n return deepTransformNode(children, {\n ...props,\n children,\n keyPath: newKeyPath,\n plugins: [markdownStringPlugin, ...(props.plugins ?? [])],\n });\n },\n };\n\n/** ---------------------------------------------\n * HTML PLUGIN\n * --------------------------------------------- */\n\n/**\n * HTML conditional type.\n *\n * This ensures type safety:\n * - `html('<div>Hello <CustomComponent /></div>').use({ CustomComponent: ... })` - optional but typed\n */\nexport type HTMLPluginCond<T, _S, _L> = T extends {\n nodeType: NodeType | string;\n [NodeTypes.HTML]: infer I;\n tags?: infer U;\n}\n ? IntlayerNode<\n I,\n {\n use: (components?: Record<keyof U, any>) => any;\n }\n >\n : never;\n\n/** HTML plugin. Replaces node with a function that takes components => IntlayerNode. */\nexport const htmlPlugin: Plugins =\n process.env.INTLAYER_NODE_TYPE_HTML === 'false'\n ? fallbackPlugin\n : {\n id: 'html-plugin',\n canHandle: (node) =>\n typeof node === 'object' && node?.nodeType === NodeTypes.HTML,\n\n transform: (node: HTMLContent<string>, props) => {\n const html = node[NodeTypes.HTML];\n const { plugins, ...rest } = props;\n\n // Type-safe render function that accepts properly typed components\n const render = (userComponents?: any) =>\n renderIntlayerNode({\n ...rest,\n value: html,\n children:\n process.env.INTLAYER_EDITOR_ENABLED === 'false' ||\n !editor.enabled\n ? html\n : () => ({\n component: ContentSelectorWrapperComponent,\n props: {\n dictionaryKey: rest.dictionaryKey,\n keyPath: rest.keyPath,\n ...userComponents,\n },\n children: html,\n }),\n });\n\n const createProxy = (element: any, components?: any) =>\n new Proxy(element, {\n get(target, prop, receiver) {\n if (prop === 'value') {\n return html;\n }\n\n if (prop === 'toString') {\n return () => {\n if (\n !components ||\n (typeof components === 'object' &&\n Object.keys(components).length === 0)\n ) {\n return String(html);\n }\n const htmlRuntime = _markdownInstall?.htmlRuntime;\n if (!htmlRuntime || !compile) return String(html);\n const runtime = createRuntimeWithOverides(\n htmlRuntime,\n components\n );\n return compile(html, { runtime }) as string;\n };\n }\n\n if (prop === Symbol.toPrimitive) {\n return () => {\n if (\n !components ||\n (typeof components === 'object' &&\n Object.keys(components).length === 0)\n ) {\n return String(html);\n }\n const htmlRuntime = _markdownInstall?.htmlRuntime;\n if (!htmlRuntime || !compile) return String(html);\n const runtime = createRuntimeWithOverides(\n htmlRuntime,\n components\n );\n return compile(html, { runtime }) as string;\n };\n }\n\n if (prop === 'use') {\n // Return a properly typed function based on custom components\n return (userComponents?: any) => {\n const mergedComponents = {\n ...components,\n ...userComponents,\n };\n return createProxy(\n render(mergedComponents),\n mergedComponents\n );\n };\n }\n\n return Reflect.get(target, prop, receiver);\n },\n }) as any;\n\n return createProxy(render() as any);\n },\n };\n\n/** ---------------------------------------------\n * INSERTION PLUGIN\n * --------------------------------------------- */\n\n/**\n * Insertion conditional type.\n */\nexport type InsertionPluginCond<T> = T extends {\n nodeType: NodeType | string;\n [NodeTypes.INSERTION]: infer _I;\n}\n ? (args: Record<string, string | number>) => string\n : never;\n\nexport const insertionPlugin: Plugins =\n process.env.INTLAYER_NODE_TYPE_INSERTION === 'false'\n ? fallbackPlugin\n : {\n id: 'insertion-plugin',\n canHandle: (node) =>\n typeof node === 'object' && node?.nodeType === NodeTypes.INSERTION,\n transform: (node: InsertionContent, props, deepTransformNode) => {\n const { plugins, ...rest } = props;\n const content = node[NodeTypes.INSERTION];\n\n // `html()`/`markdown()` nodes carry their `{{ … }}` placeholders\n // inside a raw string. Interpolate into that string, then re-run the\n // transform so the html/markdown renderer applies afterwards.\n if (isInterpolableWrapperNode(content)) {\n return (args: Record<string, string | number> = {}) =>\n transformInterpolableNode(\n content,\n args,\n props,\n props.plugins,\n deepTransformNode\n );\n }\n\n // Return a function that performs the interpolation\n const render = (args: Record<string, string | number> = {}) => {\n let text = content as string;\n if (args) {\n Object.entries(args).forEach(([key, value]) => {\n text = text.replace(\n new RegExp(`{{\\\\s*${key}\\\\s*}}`, 'g'),\n String(value)\n );\n });\n }\n return text;\n };\n\n return renderIntlayerNode({\n ...rest,\n value: render as any,\n children: render,\n });\n },\n };\n\nexport interface IInterpreterPluginAngular<T, S, L extends LocalesValues> {\n angularIntlayerNode: IntlayerNodeCond<T>;\n angularMarkdown: MarkdownCond<T, S, L>;\n angularHtml: HTMLPluginCond<T, S, L>;\n angularInsertion: InsertionPluginCond<T>;\n}\n\n/**\n * Insert this type as param of `DeepTransformContent` to avoid `intlayer` package pollution.\n *\n * Otherwise the the `angular-intlayer` plugins will override the types of `intlayer` functions.\n */\nexport type IInterpreterPluginState = Omit<\n IInterpreterPluginStateCore,\n 'insertion' // Remove insertion type from core package\n> & {\n angularIntlayerNode: true;\n angularMarkdown: true;\n angularHtml: true;\n angularInsertion: true;\n};\n\nexport type DeepTransformContent<\n T,\n L extends LocalesValues = DeclaredLocales,\n> = DeepTransformContentCore<T, IInterpreterPluginState, L>;\n\nconst pluginsCache = new Map<string, Plugins[]>();\n\n/**\n * Get the plugins array for Angular content transformation.\n * This function is used by both getIntlayer and getDictionary to ensure consistent plugin configuration.\n */\nexport const getPlugins = (\n locale?: LocalesValues,\n fallback: boolean = true\n): Plugins[] => {\n const currentLocale = locale ?? internationalization.defaultLocale;\n const cacheKey = `${currentLocale}_${fallback}`;\n\n if (pluginsCache.has(cacheKey)) {\n return pluginsCache.get(cacheKey)!;\n }\n\n const plugins = [\n translationPlugin(\n locale ?? internationalization.defaultLocale,\n fallback ? internationalization.defaultLocale : undefined\n ),\n enumerationPlugin,\n pluralPlugin(locale ?? internationalization.defaultLocale),\n conditionPlugin,\n nestedPlugin(locale ?? internationalization.defaultLocale),\n filePlugin,\n genderPlugin,\n selectPlugin,\n intlayerNodePlugins,\n markdownPlugin,\n htmlPlugin,\n insertionPlugin,\n ] as Plugins[];\n\n pluginsCache.set(cacheKey, plugins);\n\n return plugins;\n};\n"],"mappings":"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"}
1
+ {"version":3,"file":"plugins.mjs","names":[],"sources":["../../src/plugins.ts"],"sourcesContent":["import { editor, internationalization } from '@intlayer/config/built';\nimport {\n conditionPlugin,\n type DeepTransformContent as DeepTransformContentCore,\n enumerationPlugin,\n fallbackPlugin,\n filePlugin,\n genderPlugin,\n type IInterpreterPluginState as IInterpreterPluginStateCore,\n isInterpolableWrapperNode,\n nestedPlugin,\n type Plugins,\n pluralPlugin,\n selectPlugin,\n transformInterpolableNode,\n translationPlugin,\n} from '@intlayer/core/interpreter';\nimport type { MarkdownContent } from '@intlayer/core/markdown';\nimport { compile, getMarkdownMetadata } from '@intlayer/core/markdown';\nimport type { HTMLContent, InsertionContent } from '@intlayer/core/transpiler';\nimport type { KeyPath } from '@intlayer/types/keyPath';\nimport type {\n DeclaredLocales,\n LocalesValues,\n} from '@intlayer/types/module_augmentation';\nimport type { NodeType } from '@intlayer/types/nodeType';\nimport * as NodeTypes from '@intlayer/types/nodeType';\nimport { reportExposure } from './analytics/exposureSink';\nimport { ContentSelectorWrapperComponent } from './editor/ContentSelector.component';\nimport { renderIntlayerNode } from './renderIntlayerNode';\n\nlet _markdownInstall: {\n htmlRuntime: any;\n useMarkdown: () => { renderMarkdown: (s: string, components?: any) => any };\n} | null = null;\nif (\n process.env.INTLAYER_NODE_TYPE_MARKDOWN !== 'false' ||\n process.env.INTLAYER_NODE_TYPE_HTML !== 'false'\n) {\n void import('./markdown/installIntlayerMarkdown')\n .then((m) => {\n _markdownInstall = m as any;\n })\n .catch(() => {});\n}\n\n/** ---------------------------------------------\n * UTILS\n * --------------------------------------------- */\n\nconst createRuntimeWithOverides = (baseRuntime: any, overrides: any) => ({\n ...baseRuntime,\n createElement: (tag: string, props: any, ...children: any[]) => {\n const override = overrides?.[tag];\n\n if (override) {\n const newProps = { ...props, ...override };\n\n // Merge class attributes intelligently\n const originalClass = props?.class || props?.className;\n const overrideClass = override.class || override.className;\n\n if (originalClass && overrideClass) {\n newProps.class = `${originalClass} ${overrideClass}`;\n newProps.className = undefined;\n }\n\n return baseRuntime.createElement(tag, newProps, ...children);\n }\n\n return baseRuntime.createElement(tag, props, ...children);\n },\n});\n\n/** ---------------------------------------------\n * INTLAYER NODE PLUGIN\n * --------------------------------------------- */\n\nexport type IntlayerNodeCond<T> = T extends number | string\n ? IntlayerNode<T>\n : never;\n\nexport interface IntlayerNode<T, P = {}> {\n value: T;\n children?: any;\n additionalProps?: P;\n}\n\n/** Translation plugin. Replaces node with a locale string if nodeType = Translation. */\nexport const intlayerNodePlugins: Plugins = {\n id: 'intlayer-node-plugin',\n canHandle: (node) =>\n typeof node === 'bigint' ||\n typeof node === 'string' ||\n typeof node === 'number',\n transform: (_node, { children, ...rest }) => {\n // Node-level analytics: record which content is resolved for display.\n // No-op (and dead-code-eliminated) when analytics is disabled.\n if (process.env.INTLAYER_ANALYTICS_ENABLED !== 'false') {\n reportExposure({\n dictionaryKey: rest.dictionaryKey,\n keyPath: rest.keyPath,\n locale: rest.locale,\n nodeType: 'text',\n });\n }\n\n return renderIntlayerNode({\n ...rest,\n value: children,\n children: () => ({\n component:\n process.env.INTLAYER_EDITOR_ENABLED === 'false' || !editor.enabled\n ? children\n : ContentSelectorWrapperComponent,\n props: {\n dictionaryKey: rest.dictionaryKey,\n keyPath: rest.keyPath,\n },\n children: children,\n }),\n });\n },\n};\n\n/**\n * MARKDOWN PLUGIN\n */\n\nexport type MarkdownStringCond<T> = T extends string\n ? IntlayerNode<string, { metadata: DeepTransformContent<string> }>\n : never;\n\n/** Markdown string plugin. Replaces string node with a component that render the markdown. */\nexport const markdownStringPlugin: Plugins =\n process.env.INTLAYER_NODE_TYPE_MARKDOWN === 'false'\n ? fallbackPlugin\n : {\n id: 'markdown-string-plugin',\n canHandle: (node) => typeof node === 'string',\n transform: (node: string, props, deepTransformNode) => {\n const {\n plugins, // Removed to avoid next error - Functions cannot be passed directly to Client Components\n ...rest\n } = props;\n\n const metadata = getMarkdownMetadata(node) ?? {};\n\n const metadataPlugins: Plugins = {\n id: 'markdown-metadata-plugin',\n canHandle: (metadataNode) =>\n typeof metadataNode === 'string' ||\n typeof metadataNode === 'number' ||\n typeof metadataNode === 'boolean' ||\n !metadataNode,\n transform: (metadataNode, props) =>\n renderIntlayerNode({\n ...props,\n value: metadataNode,\n children: node,\n }),\n };\n\n // Transform metadata while keeping the same structure\n const metadataNodes = deepTransformNode(metadata, {\n plugins: [metadataPlugins],\n dictionaryKey: rest.dictionaryKey,\n keyPath: [],\n });\n\n const render = (components?: any) =>\n renderIntlayerNode({\n ...rest,\n value: node,\n children:\n process.env.INTLAYER_EDITOR_ENABLED === 'false' ||\n !editor.enabled\n ? () => {\n const { renderMarkdown } =\n _markdownInstall?.useMarkdown() ?? {\n renderMarkdown: () => node,\n };\n return renderMarkdown(node, components);\n }\n : () => ({\n component: ContentSelectorWrapperComponent,\n props: {\n dictionaryKey: rest.dictionaryKey,\n keyPath: rest.keyPath,\n ...components,\n },\n children: () => {\n const { renderMarkdown } =\n _markdownInstall?.useMarkdown() ?? {\n renderMarkdown: () => node,\n };\n return renderMarkdown(node, components);\n },\n }),\n additionalProps: {\n metadata: metadataNodes,\n },\n });\n\n const createProxy = (element: any, components?: any) =>\n new Proxy(element, {\n get(target, prop, receiver) {\n if (prop === 'value') {\n return node;\n }\n if (prop === 'metadata') {\n return metadataNodes;\n }\n\n if (prop === 'toString') {\n return () => {\n const htmlRuntime = _markdownInstall?.htmlRuntime;\n if (!htmlRuntime || !compile) return node;\n const runtime = components\n ? createRuntimeWithOverides(htmlRuntime, components)\n : htmlRuntime;\n return compile(node, { runtime }) as string;\n };\n }\n\n if (prop === Symbol.toPrimitive) {\n return () => {\n const htmlRuntime = _markdownInstall?.htmlRuntime;\n if (!htmlRuntime || !compile) return node;\n const runtime = components\n ? createRuntimeWithOverides(htmlRuntime, components)\n : htmlRuntime;\n return compile(node, { runtime }) as string;\n };\n }\n\n if (prop === 'use') {\n return (newComponents?: any) => {\n const mergedComponents = {\n ...components,\n ...newComponents,\n };\n return createProxy(\n render(mergedComponents),\n mergedComponents\n );\n };\n }\n\n return Reflect.get(target, prop, receiver);\n },\n }) as any;\n\n return createProxy(render() as any);\n },\n };\n\nexport type MarkdownCond<T, _S, _L extends LocalesValues> = T extends {\n nodeType: NodeType | string;\n [NodeTypes.MARKDOWN]: infer M;\n tags?: infer U;\n metadata?: infer V;\n}\n ? IntlayerNode<\n M,\n {\n use: (components?: Record<keyof U, any>) => any;\n metadata: DeepTransformContent<V>;\n }\n >\n : never;\n\nexport const markdownPlugin: Plugins =\n process.env.INTLAYER_NODE_TYPE_MARKDOWN === 'false'\n ? fallbackPlugin\n : {\n id: 'markdown-plugin',\n canHandle: (node) =>\n typeof node === 'object' && node?.nodeType === NodeTypes.MARKDOWN,\n transform: (node: MarkdownContent, props, deepTransformNode) => {\n const newKeyPath: KeyPath[] = [\n ...props.keyPath,\n {\n type: NodeTypes.MARKDOWN,\n },\n ];\n\n const children = node[NodeTypes.MARKDOWN];\n\n return deepTransformNode(children, {\n ...props,\n children,\n keyPath: newKeyPath,\n plugins: [markdownStringPlugin, ...(props.plugins ?? [])],\n });\n },\n };\n\n/** ---------------------------------------------\n * HTML PLUGIN\n * --------------------------------------------- */\n\n/**\n * HTML conditional type.\n *\n * This ensures type safety:\n * - `html('<div>Hello <CustomComponent /></div>').use({ CustomComponent: ... })` - optional but typed\n */\nexport type HTMLPluginCond<T, _S, _L> = T extends {\n nodeType: NodeType | string;\n [NodeTypes.HTML]: infer I;\n tags?: infer U;\n}\n ? IntlayerNode<\n I,\n {\n use: (components?: Record<keyof U, any>) => any;\n }\n >\n : never;\n\n/** HTML plugin. Replaces node with a function that takes components => IntlayerNode. */\nexport const htmlPlugin: Plugins =\n process.env.INTLAYER_NODE_TYPE_HTML === 'false'\n ? fallbackPlugin\n : {\n id: 'html-plugin',\n canHandle: (node) =>\n typeof node === 'object' && node?.nodeType === NodeTypes.HTML,\n\n transform: (node: HTMLContent<string>, props) => {\n const html = node[NodeTypes.HTML];\n const { plugins, ...rest } = props;\n\n // Type-safe render function that accepts properly typed components\n const render = (userComponents?: any) =>\n renderIntlayerNode({\n ...rest,\n value: html,\n children:\n process.env.INTLAYER_EDITOR_ENABLED === 'false' ||\n !editor.enabled\n ? html\n : () => ({\n component: ContentSelectorWrapperComponent,\n props: {\n dictionaryKey: rest.dictionaryKey,\n keyPath: rest.keyPath,\n ...userComponents,\n },\n children: html,\n }),\n });\n\n const createProxy = (element: any, components?: any) =>\n new Proxy(element, {\n get(target, prop, receiver) {\n if (prop === 'value') {\n return html;\n }\n\n if (prop === 'toString') {\n return () => {\n if (\n !components ||\n (typeof components === 'object' &&\n Object.keys(components).length === 0)\n ) {\n return String(html);\n }\n const htmlRuntime = _markdownInstall?.htmlRuntime;\n if (!htmlRuntime || !compile) return String(html);\n const runtime = createRuntimeWithOverides(\n htmlRuntime,\n components\n );\n return compile(html, { runtime }) as string;\n };\n }\n\n if (prop === Symbol.toPrimitive) {\n return () => {\n if (\n !components ||\n (typeof components === 'object' &&\n Object.keys(components).length === 0)\n ) {\n return String(html);\n }\n const htmlRuntime = _markdownInstall?.htmlRuntime;\n if (!htmlRuntime || !compile) return String(html);\n const runtime = createRuntimeWithOverides(\n htmlRuntime,\n components\n );\n return compile(html, { runtime }) as string;\n };\n }\n\n if (prop === 'use') {\n // Return a properly typed function based on custom components\n return (userComponents?: any) => {\n const mergedComponents = {\n ...components,\n ...userComponents,\n };\n return createProxy(\n render(mergedComponents),\n mergedComponents\n );\n };\n }\n\n return Reflect.get(target, prop, receiver);\n },\n }) as any;\n\n return createProxy(render() as any);\n },\n };\n\n/** ---------------------------------------------\n * INSERTION PLUGIN\n * --------------------------------------------- */\n\n/**\n * Insertion conditional type.\n */\nexport type InsertionPluginCond<T> = T extends {\n nodeType: NodeType | string;\n [NodeTypes.INSERTION]: infer _I;\n}\n ? (args: Record<string, string | number>) => string\n : never;\n\nexport const insertionPlugin: Plugins =\n process.env.INTLAYER_NODE_TYPE_INSERTION === 'false'\n ? fallbackPlugin\n : {\n id: 'insertion-plugin',\n canHandle: (node) =>\n typeof node === 'object' && node?.nodeType === NodeTypes.INSERTION,\n transform: (node: InsertionContent, props, deepTransformNode) => {\n const { plugins, ...rest } = props;\n const content = node[NodeTypes.INSERTION];\n\n // `html()`/`markdown()` nodes carry their `{{ … }}` placeholders\n // inside a raw string. Interpolate into that string, then re-run the\n // transform so the html/markdown renderer applies afterwards.\n if (isInterpolableWrapperNode(content)) {\n return (args: Record<string, string | number> = {}) =>\n transformInterpolableNode(\n content,\n args,\n props,\n props.plugins,\n deepTransformNode\n );\n }\n\n // Return a function that performs the interpolation\n const render = (args: Record<string, string | number> = {}) => {\n let text = content as string;\n if (args) {\n Object.entries(args).forEach(([key, value]) => {\n text = text.replace(\n new RegExp(`{{\\\\s*${key}\\\\s*}}`, 'g'),\n String(value)\n );\n });\n }\n return text;\n };\n\n return renderIntlayerNode({\n ...rest,\n value: render as any,\n children: render,\n });\n },\n };\n\nexport interface IInterpreterPluginAngular<T, S, L extends LocalesValues> {\n angularIntlayerNode: IntlayerNodeCond<T>;\n angularMarkdown: MarkdownCond<T, S, L>;\n angularHtml: HTMLPluginCond<T, S, L>;\n angularInsertion: InsertionPluginCond<T>;\n}\n\n/**\n * Insert this type as param of `DeepTransformContent` to avoid `intlayer` package pollution.\n *\n * Otherwise the the `angular-intlayer` plugins will override the types of `intlayer` functions.\n */\nexport type IInterpreterPluginState = Omit<\n IInterpreterPluginStateCore,\n 'insertion' // Remove insertion type from core package\n> & {\n angularIntlayerNode: true;\n angularMarkdown: true;\n angularHtml: true;\n angularInsertion: true;\n};\n\nexport type DeepTransformContent<\n T,\n L extends LocalesValues = DeclaredLocales,\n> = DeepTransformContentCore<T, IInterpreterPluginState, L>;\n\nconst pluginsCache = new Map<string, Plugins[]>();\n\n/**\n * Get the plugins array for Angular content transformation.\n * This function is used by both getIntlayer and getDictionary to ensure consistent plugin configuration.\n */\nexport const getPlugins = (\n locale?: LocalesValues,\n fallback: boolean = true\n): Plugins[] => {\n const currentLocale = locale ?? internationalization.defaultLocale;\n const cacheKey = `${currentLocale}_${fallback}`;\n\n if (pluginsCache.has(cacheKey)) {\n return pluginsCache.get(cacheKey)!;\n }\n\n const plugins = [\n translationPlugin(\n locale ?? internationalization.defaultLocale,\n fallback ? internationalization.defaultLocale : undefined\n ),\n enumerationPlugin,\n pluralPlugin(locale ?? internationalization.defaultLocale),\n conditionPlugin,\n nestedPlugin(locale ?? internationalization.defaultLocale),\n filePlugin,\n genderPlugin,\n selectPlugin,\n intlayerNodePlugins,\n markdownPlugin,\n htmlPlugin,\n insertionPlugin,\n ] as Plugins[];\n\n pluginsCache.set(cacheKey, plugins);\n\n return plugins;\n};\n"],"mappings":"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"}
@@ -1,8 +1,8 @@
1
1
  import { __require } from "../_virtual/_rolldown/runtime.mjs";
2
+ import { createRequire } from "node:module";
2
3
  import { resolve } from "node:path";
3
4
  import { getConfiguration } from "@intlayer/config/node";
4
5
  import { getAlias } from "@intlayer/config/utils";
5
- import { createRequire } from "node:module";
6
6
  import { IntlayerPlugin } from "@intlayer/webpack";
7
7
  import { defu } from "defu";
8
8
 
@@ -1 +1 @@
1
- {"version":3,"file":"useDictionaryDynamic.d.ts","names":[],"sources":["../../../src/client/useDictionaryDynamic.ts"],"mappings":";;;;;;;;;;;;;;;cAmCa,6BACL,UAAU,kBACV,UAAU,sBACV,UAAU,gBAAgB,yBAAyB,KAAK,iBAAe,mBAGzE,0BAA0B,QAAQ,MAClC,2BAAyB,KACxB,GAAC,mBACa,8BAAC"}
1
+ {"version":3,"file":"useDictionaryDynamic.d.ts","names":[],"sources":["../../../src/client/useDictionaryDynamic.ts"],"mappings":";;;;;;;;;;;;;;;cAoCa,6BACL,UAAU,kBACV,UAAU,sBACV,UAAU,gBAAgB,yBAAyB,KAAK,iBAAe,mBAGzE,0BAA0B,QAAQ,MAClC,2BAAyB,KACxB,GAAC,mBACa,8BAAC"}
@@ -1,3 +1,4 @@
1
+ import { Locale } from "../intlayer/dist/types/index.js";
1
2
  import { LocalesValues } from "@intlayer/types/module_augmentation";
2
3
  //#region src/client/useLocaleStorage.d.ts
3
4
  /**
@@ -6,13 +7,13 @@ import { LocalesValues } from "@intlayer/types/module_augmentation";
6
7
  /**
7
8
  * Get the locale cookie
8
9
  */
9
- declare const localeInStorage: import("@intlayer/types").Locale;
10
+ declare const localeInStorage: Locale;
10
11
  /**
11
12
  * @deprecated Use localeInStorage instead
12
13
  *
13
14
  * Get the locale cookie
14
15
  */
15
- declare const localeCookie: import("@intlayer/types").Locale;
16
+ declare const localeCookie: Locale;
16
17
  /**
17
18
  * Set the locale cookie
18
19
  */
@@ -27,7 +28,7 @@ declare const setLocaleCookie: typeof setLocaleInStorage;
27
28
  * Hook that provides the locale storage and a function to set it
28
29
  */
29
30
  declare const useLocaleStorage: (isCookieEnabled?: boolean) => {
30
- getLocale: () => import("@intlayer/types").Locale;
31
+ getLocale: () => Locale;
31
32
  setLocale: (locale: LocalesValues) => void;
32
33
  };
33
34
  /**
@@ -38,7 +39,7 @@ declare const useLocaleStorage: (isCookieEnabled?: boolean) => {
38
39
  * Hook that provides the locale cookie and a function to set it
39
40
  */
40
41
  declare const useLocaleCookie: (isCookieEnabled?: boolean) => {
41
- localeCookie: import("@intlayer/types").Locale;
42
+ localeCookie: Locale;
42
43
  setLocaleCookie: (locale: LocalesValues) => void;
43
44
  };
44
45
  //#endregion
@@ -1 +1 @@
1
- {"version":3,"file":"useLocaleStorage.d.ts","names":[],"sources":["../../../src/client/useLocaleStorage.ts"],"mappings":";;;;;;;;cAca,2CAAe;;;;;;cAMf,wCAAY;;;;cAKZ,qBAAkB,QACrB,eAAa;;;;;;cAaV,wBAAe;;;;cAKf,mBAAgB;;sBAAhB;;;;;;;;;cAaA,kBAAe;EAIxB,wCAAY;EACZ,kBAAe,QAAA"}
1
+ {"version":3,"file":"useLocaleStorage.d.ts","names":[],"sources":["../../../src/client/useLocaleStorage.ts"],"mappings":";;;;;;;;;cAca,iBAAA;;;;;;cAMA,cAAA;;;;cAKA,qBAAkB,QACrB,eAAa;;;;;;cAaV,wBAAe;;;;cAKf,mBAAgB;mBAAhB;sBAAA;;;;;;;;;cAaA,kBAAe;EAIxB,cAJS;EAKT,kBAAe,QAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"useEditor.d.ts","names":[],"sources":["../../../src/editor/useEditor.ts"],"mappings":";;;;;;;;;;;;;;cA4Ba,YAAS,SAAa;;;;;;;;;;;;;;;;;;cA6DtB,wBAAqB,SAAa,oDAAuB"}
1
+ {"version":3,"file":"useEditor.d.ts","names":[],"sources":["../../../src/editor/useEditor.ts"],"mappings":";;;;;;;;;;;;;;cA4Ba,YAAS,SAAa;;;;;;;;;;;;;;;;;;cAiEtB,wBAAqB,SAAa,oDAAuB"}
@@ -23,6 +23,20 @@ interface EsbuildPluginBuild {
23
23
  path: string;
24
24
  namespace?: string;
25
25
  } | null | undefined): void;
26
+ /** Intercept module contents, so a resolved file can be rewritten. */
27
+ onLoad(options: {
28
+ filter: RegExp;
29
+ namespace?: string;
30
+ }, callback: (args: {
31
+ path: string;
32
+ namespace: string;
33
+ }) => {
34
+ contents: string;
35
+ loader?: string;
36
+ } | null | undefined | Promise<{
37
+ contents: string;
38
+ loader?: string;
39
+ } | null | undefined>): void;
26
40
  }
27
41
  interface EsbuildPlugin {
28
42
  name: string;
@@ -1 +1 @@
1
- {"version":3,"file":"plugin.d.ts","names":[],"sources":["../../../src/esbuild/plugin.ts"],"mappings":";;UAwBiB;EACf;IACE,QAAQ;IACR,SAAS;IACT;IACA;;IAEA;;EAEF,QAAQ,uBAAuB;;EAE/B,UACE;IAAW,QAAQ;IAAQ;KAC3B,WAAW;IACT;IACA;IACA;IACA;;IACM;IAAc;;;UAIT;EACf;EACA,MAAM,OAAO,4BAA4B;;KAG/B;EACV,gBAAgB;;;;;;;;EAQhB;;;;;;;;;;;;;;;;;;;;;;;;cAyBW,wBAAqB,UACtB,iCACT"}
1
+ {"version":3,"file":"plugin.d.ts","names":[],"sources":["../../../src/esbuild/plugin.ts"],"mappings":";;UAiDiB;EACf;IACE,QAAQ;IACR,SAAS;IACT;IACA;;IAEA;;EAEF,QAAQ,uBAAuB;;EAE/B,UACE;IAAW,QAAQ;IAAQ;KAC3B,WAAW;IACT;IACA;IACA;IACA;;IACM;IAAc;;;EAGxB,OACE;IAAW,QAAQ;IAAQ;KAC3B,WAAW;IACT;IACA;;IAEI;IAAkB;yBAGpB;IAAU;IAAkB;;;UAInB;EACf;EACA,MAAM,OAAO,4BAA4B;;KAG/B;EACV,gBAAgB;;;;;;;;EAQhB;;;;;;;;;;;;;;;;;;;;;;;;cAyBW,wBAAqB,UACtB,iCACT"}
@@ -1,6 +1,7 @@
1
+ import { LocalesValues } from "../intlayer/dist/types/index.js";
1
2
  //#region src/format/useCompact.d.ts
2
3
  declare const useCompact: () => import("@angular/core").Signal<(value: string | number, options?: Intl.NumberFormatOptions & {
3
- locale?: import("@intlayer/types").LocalesValues;
4
+ locale?: LocalesValues;
4
5
  }) => string>;
5
6
  //#endregion
6
7
  export { useCompact };
@@ -1 +1 @@
1
- {"version":3,"file":"useCompact.d.ts","names":[],"sources":["../../../src/format/useCompact.ts"],"mappings":";cAIa,0CAAU,QAAA,wBAAA,UAAA,KAAA"}
1
+ {"version":3,"file":"useCompact.d.ts","names":[],"sources":["../../../src/format/useCompact.ts"],"mappings":";;cAIa,0CAAU,QAAA,wBAAA,UAAA,KAAA;WAAA"}
@@ -1,6 +1,7 @@
1
+ import { LocalesValues } from "../intlayer/dist/types/index.js";
1
2
  //#region src/format/useCurrency.d.ts
2
3
  declare const useCurrency: () => import("@angular/core").Signal<(value: string | number, options?: Intl.NumberFormatOptions & {
3
- locale?: import("@intlayer/types").LocalesValues;
4
+ locale?: LocalesValues;
4
5
  }) => string>;
5
6
  //#endregion
6
7
  export { useCurrency };
@@ -1 +1 @@
1
- {"version":3,"file":"useCurrency.d.ts","names":[],"sources":["../../../src/format/useCurrency.ts"],"mappings":";cAIa,2CAAW,QAAA,wBAAA,UAAA,KAAA"}
1
+ {"version":3,"file":"useCurrency.d.ts","names":[],"sources":["../../../src/format/useCurrency.ts"],"mappings":";;cAIa,2CAAW,QAAA,wBAAA,UAAA,KAAA;WAAA"}
@@ -1,9 +1,10 @@
1
+ import { LocalesValues } from "../intlayer/dist/types/index.js";
1
2
  //#region src/format/useDate.d.ts
2
3
  /**
3
4
  * Angular client hook that provides a localized date/time formatter.
4
5
  */
5
6
  declare const useDate: () => import("@angular/core").Signal<(date: string | number | Date, options?: import("@intlayer/core/formatters").DateTimePreset | (Intl.DateTimeFormatOptions & {
6
- locale?: import("@intlayer/types").LocalesValues;
7
+ locale?: LocalesValues;
7
8
  })) => string>;
8
9
  //#endregion
9
10
  export { useDate };
@@ -1 +1 @@
1
- {"version":3,"file":"useDate.d.ts","names":[],"sources":["../../../src/format/useDate.ts"],"mappings":";;;;cAOa,uCAAO,QAAA,wBAAA,MAAA,8CAAA,kBAAA,KAAA"}
1
+ {"version":3,"file":"useDate.d.ts","names":[],"sources":["../../../src/format/useDate.ts"],"mappings":";;;;;cAOa,uCAAO,QAAA,wBAAA,MAAA,8CAAA,kBAAA,KAAA;WAAA"}
@@ -1,10 +1,11 @@
1
+ import { LocalesValues } from "../intlayer/dist/types/index.js";
1
2
  //#region src/format/useList.d.ts
2
3
  declare const useList: () => import("@angular/core").Signal<(values: (string | number)[], options?: {
3
4
  localeMatcher?: 'lookup' | 'best fit';
4
5
  type?: 'conjunction' | 'disjunction' | 'unit';
5
6
  style?: 'long' | 'short' | 'narrow';
6
7
  } & {
7
- locale?: import("@intlayer/types").LocalesValues;
8
+ locale?: LocalesValues;
8
9
  }) => string>;
9
10
  //#endregion
10
11
  export { useList };
@@ -1 +1 @@
1
- {"version":3,"file":"useList.d.ts","names":[],"sources":["../../../src/format/useList.ts"],"mappings":";cAIa,uCAAO,QAAA,6BAAA"}
1
+ {"version":3,"file":"useList.d.ts","names":[],"sources":["../../../src/format/useList.ts"],"mappings":";;cAIa,uCAAO,QAAA,6BAAA;;;;;WAAP"}
@@ -1,9 +1,10 @@
1
+ import { LocalesValues } from "../intlayer/dist/types/index.js";
1
2
  //#region src/format/useNumber.d.ts
2
3
  /**
3
4
  * Angular client hook that provides a localized number formatter.
4
5
  */
5
6
  declare const useNumber: () => import("@angular/core").Signal<(value: string | number, args_1?: Intl.NumberFormatOptions & {
6
- locale?: import("@intlayer/types").LocalesValues;
7
+ locale?: LocalesValues;
7
8
  }) => string>;
8
9
  //#endregion
9
10
  export { useNumber };
@@ -1 +1 @@
1
- {"version":3,"file":"useNumber.d.ts","names":[],"sources":["../../../src/format/useNumber.ts"],"mappings":";;;;cAOa,yCAAS,QAAA,wBAAA,SAAA,KAAA"}
1
+ {"version":3,"file":"useNumber.d.ts","names":[],"sources":["../../../src/format/useNumber.ts"],"mappings":";;;;;cAOa,yCAAS,QAAA,wBAAA,SAAA,KAAA;WAAA"}
@@ -1,6 +1,7 @@
1
+ import { LocalesValues } from "../intlayer/dist/types/index.js";
1
2
  //#region src/format/usePercentage.d.ts
2
3
  declare const usePercentage: () => import("@angular/core").Signal<(value: string | number, args_1?: Intl.NumberFormatOptions & {
3
- locale?: import("@intlayer/types").LocalesValues;
4
+ locale?: LocalesValues;
4
5
  }) => string>;
5
6
  //#endregion
6
7
  export { usePercentage };
@@ -1 +1 @@
1
- {"version":3,"file":"usePercentage.d.ts","names":[],"sources":["../../../src/format/usePercentage.ts"],"mappings":";cAIa,6CAAa,QAAA,wBAAA,SAAA,KAAA"}
1
+ {"version":3,"file":"usePercentage.d.ts","names":[],"sources":["../../../src/format/usePercentage.ts"],"mappings":";;cAIa,6CAAa,QAAA,wBAAA,SAAA,KAAA;WAAA"}
@@ -1,6 +1,7 @@
1
+ import { LocalesValues } from "../intlayer/dist/types/index.js";
1
2
  //#region src/format/useRelativeTime.d.ts
2
3
  declare const useRelativeTime: () => import("@angular/core").Signal<(from: string | number | Date, to?: string | number | Date, options?: Intl.RelativeTimeFormatOptions & {
3
- locale?: import("@intlayer/types").LocalesValues;
4
+ locale?: LocalesValues;
4
5
  unit?: Intl.RelativeTimeFormatUnit;
5
6
  }) => string>;
6
7
  //#endregion
@@ -1 +1 @@
1
- {"version":3,"file":"useRelativeTime.d.ts","names":[],"sources":["../../../src/format/useRelativeTime.ts"],"mappings":";cAIa,+CAAe,QAAA,wBAAA,MAAA,uBAAA,MAAA,UAAA,KAAA"}
1
+ {"version":3,"file":"useRelativeTime.d.ts","names":[],"sources":["../../../src/format/useRelativeTime.ts"],"mappings":";;cAIa,+CAAe,QAAA,wBAAA,MAAA,uBAAA,MAAA,UAAA,KAAA;WAAA"}
@@ -1,6 +1,7 @@
1
+ import { LocalesValues } from "../intlayer/dist/types/index.js";
1
2
  //#region src/format/useUnit.d.ts
2
3
  declare const useUnit: () => import("@angular/core").Signal<(value: string | number, options?: Intl.NumberFormatOptions & {
3
- locale?: import("@intlayer/types").LocalesValues;
4
+ locale?: LocalesValues;
4
5
  }) => string>;
5
6
  //#endregion
6
7
  export { useUnit };
@@ -1 +1 @@
1
- {"version":3,"file":"useUnit.d.ts","names":[],"sources":["../../../src/format/useUnit.ts"],"mappings":";cAIa,uCAAO,QAAA,wBAAA,UAAA,KAAA"}
1
+ {"version":3,"file":"useUnit.d.ts","names":[],"sources":["../../../src/format/useUnit.ts"],"mappings":";;cAIa,uCAAO,QAAA,wBAAA,UAAA,KAAA;WAAA"}
@@ -0,0 +1,14 @@
1
+ import { LocalesValues as LocalesValues$1 } from "@intlayer/types/module_augmentation";
2
+ import { Dictionary } from "@intlayer/types/dictionary";
3
+ import "@intlayer/core/interpreter";
4
+ import "@intlayer/types/config";
5
+ import { Locale } from "@intlayer/types/allLocales";
6
+ import "@intlayer/types/locales";
7
+ import "@intlayer/config/built";
8
+ import "@intlayer/core/file";
9
+ import "@intlayer/core/formatters";
10
+ import "@intlayer/core/localization";
11
+ import "@intlayer/core/markdown";
12
+ import "@intlayer/core/transpiler";
13
+ import "@intlayer/core/utils";
14
+ export type { Locale, LocalesValues$1 as LocalesValues };
@@ -1 +1 @@
1
- {"version":3,"file":"plugins.d.ts","names":[],"sources":["../../src/plugins.ts"],"mappings":";;;;;;;;KA4EY,iBAAiB,KAAK,4BAC9B,aAAa;UAGA,aAAa,GAAG;EAC/B,OAAO;EACP;EACA,kBAAkB;;;cAIP,qBAAqB;;;;KAwCtB,mBAAmB,KAAK,mBAChC;EAAuB,UAAU;;;cAIxB,sBAAsB;KA2HvB,aAAa,GAAG,IAAI,WAAW,iBAAiB;EAC1D,UAAU;GACT,UAAU,iBAAiB;EAC5B,aAAa;EACb,iBAAiB;IAEf,aACE;EAEE,MAAM,aAAa,aAAa;EAChC,UAAU,qBAAqB;;cAK1B,gBAAgB;;;;;;;;;;KAoCjB,eAAe,GAAG,IAAI,MAAM;EACtC,UAAU;GACT,UAAU,aAAa;EACxB,aAAa;IAEX,aACE;EAEE,MAAM,aAAa,aAAa;;;cAM3B,YAAY;;;;;;;KA0Gb,oBAAoB,KAAK;EACnC,UAAU;GACT,UAAU,kBAAkB;KAE1B,MAAM;cAGE,iBAAiB;UA+Cb,0BAA0B,GAAG,GAAG,UAAU;EACzD,qBAAqB,iBAAiB;EACtC,iBAAiB,aAAa,GAAG,GAAG;EACpC,aAAa,eAAe,GAAG,GAAG;EAClC,kBAAkB,oBAAoB;;;;;;;KAQ5B,0BAA0B,KACpC;EAGA;EACA;EACA;EACA;;KAGU,qBACV,GACA,UAAU,gBAAgB,mBACxB,uBAAyB,GAAG,yBAAyB;;;;;cAQ5C,aAAU,SACZ,eAAa,uBAErB"}
1
+ {"version":3,"file":"plugins.d.ts","names":[],"sources":["../../src/plugins.ts"],"mappings":";;;;;;;;KA8EY,iBAAiB,KAAK,4BAC9B,aAAa;UAGA,aAAa,GAAG;EAC/B,OAAO;EACP;EACA,kBAAkB;;;cAIP,qBAAqB;;;;KAwCtB,mBAAmB,KAAK,mBAChC;EAAuB,UAAU;;;cAIxB,sBAAsB;KA2HvB,aAAa,GAAG,IAAI,WAAW,iBAAiB;EAC1D,UAAU;GACT,UAAU,iBAAiB;EAC5B,aAAa;EACb,iBAAiB;IAEf,aACE;EAEE,MAAM,aAAa,aAAa;EAChC,UAAU,qBAAqB;;cAK1B,gBAAgB;;;;;;;;;;KAoCjB,eAAe,GAAG,IAAI,MAAM;EACtC,UAAU;GACT,UAAU,aAAa;EACxB,aAAa;IAEX,aACE;EAEE,MAAM,aAAa,aAAa;;;cAM3B,YAAY;;;;;;;KA0Gb,oBAAoB,KAAK;EACnC,UAAU;GACT,UAAU,kBAAkB;KAE1B,MAAM;cAGE,iBAAiB;UA+Cb,0BAA0B,GAAG,GAAG,UAAU;EACzD,qBAAqB,iBAAiB;EACtC,iBAAiB,aAAa,GAAG,GAAG;EACpC,aAAa,eAAe,GAAG,GAAG;EAClC,kBAAkB,oBAAoB;;;;;;;KAQ5B,0BAA0B,KACpC;EAGA;EACA;EACA;EACA;;KAGU,qBACV,GACA,UAAU,gBAAgB,mBACxB,uBAAyB,GAAG,yBAAyB;;;;;cAQ5C,aAAU,SACZ,eAAa,uBAErB"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "angular-intlayer",
3
- "version": "9.3.1",
3
+ "version": "9.3.3",
4
4
  "private": false,
5
5
  "description": "Easily internationalize i18n your Angular applications with type-safe multilingual content management.",
6
6
  "keywords": [
@@ -119,13 +119,13 @@
119
119
  "@babel/core": "^7.26.9",
120
120
  "@babel/plugin-syntax-import-attributes": "7.28.6",
121
121
  "@babel/preset-env": "7.29.2",
122
- "@intlayer/config": "9.3.1",
123
- "@intlayer/core": "9.3.1",
124
- "@intlayer/dictionaries-entry": "9.3.1",
125
- "@intlayer/editor": "9.3.1",
126
- "@intlayer/engine": "9.3.1",
127
- "@intlayer/types": "9.3.1",
128
- "@intlayer/webpack": "9.3.1",
122
+ "@intlayer/config": "9.3.3",
123
+ "@intlayer/core": "9.3.3",
124
+ "@intlayer/dictionaries-entry": "9.3.3",
125
+ "@intlayer/editor": "9.3.3",
126
+ "@intlayer/engine": "9.3.2",
127
+ "@intlayer/types": "9.3.3",
128
+ "@intlayer/webpack": "9.3.2",
129
129
  "babel-loader": "10.1.1",
130
130
  "defu": "6.1.7"
131
131
  },
@@ -141,7 +141,7 @@
141
141
  "rimraf": "6.1.3",
142
142
  "tsdown": "0.22.14",
143
143
  "typescript": "7.0.2",
144
- "vitest": "4.1.10"
144
+ "vitest": "4.1.11"
145
145
  },
146
146
  "peerDependencies": {
147
147
  "@angular/common": ">=15",
@@ -155,7 +155,7 @@
155
155
  }
156
156
  },
157
157
  "optionalDependencies": {
158
- "@intlayer/analytics": "9.3.1"
158
+ "@intlayer/analytics": "9.3.3"
159
159
  },
160
160
  "engines": {
161
161
  "node": ">=14.18"