angular-intlayer 9.5.2 → 9.5.4-canary.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (56) hide show
  1. package/README.md +9 -9
  2. package/dist/cjs/analytics/useAnalytics.cjs +1 -1
  3. package/dist/cjs/client/intlayerToken.cjs +1 -1
  4. package/dist/cjs/client/useDictionary.cjs +1 -1
  5. package/dist/cjs/client/useDictionaryAsync.cjs +1 -1
  6. package/dist/cjs/client/useDictionaryDynamic.cjs +2 -2
  7. package/dist/cjs/client/useIntlayer.cjs +1 -1
  8. package/dist/cjs/client/useLocale.cjs +1 -1
  9. package/dist/cjs/editor/EditorProvider.component.cjs +1 -1
  10. package/dist/cjs/editor/index.cjs +1 -1
  11. package/dist/cjs/esbuild/hiddenDirectory.cjs +20 -0
  12. package/dist/cjs/esbuild/hiddenDirectory.cjs.map +1 -0
  13. package/dist/cjs/esbuild/plugin.cjs +69 -5
  14. package/dist/cjs/esbuild/plugin.cjs.map +1 -1
  15. package/dist/cjs/esbuild/resolvePackageExport.cjs +118 -0
  16. package/dist/cjs/esbuild/resolvePackageExport.cjs.map +1 -0
  17. package/dist/cjs/format/index.cjs +3 -3
  18. package/dist/cjs/index.cjs +3 -3
  19. package/dist/cjs/markdown/installIntlayerMarkdown.cjs +1 -1
  20. package/dist/cjs/plugins.cjs +36 -40
  21. package/dist/cjs/plugins.cjs.map +1 -1
  22. package/dist/cjs/webpack/mergeConfig.cjs +1 -1
  23. package/dist/cjs/webpack/mergeConfig.cjs.map +1 -1
  24. package/dist/esm/analytics/useAnalytics.mjs +1 -1
  25. package/dist/esm/client/intlayerToken.mjs +1 -1
  26. package/dist/esm/client/useDictionary.mjs +1 -1
  27. package/dist/esm/client/useDictionaryAsync.mjs +1 -1
  28. package/dist/esm/client/useDictionaryDynamic.mjs +2 -2
  29. package/dist/esm/client/useIntlayer.mjs +1 -1
  30. package/dist/esm/client/useLocale.mjs +1 -1
  31. package/dist/esm/editor/EditorProvider.component.mjs +1 -1
  32. package/dist/esm/editor/index.mjs +1 -1
  33. package/dist/esm/esbuild/hiddenDirectory.mjs +19 -0
  34. package/dist/esm/esbuild/hiddenDirectory.mjs.map +1 -0
  35. package/dist/esm/esbuild/plugin.mjs +70 -7
  36. package/dist/esm/esbuild/plugin.mjs.map +1 -1
  37. package/dist/esm/esbuild/resolvePackageExport.mjs +115 -0
  38. package/dist/esm/esbuild/resolvePackageExport.mjs.map +1 -0
  39. package/dist/esm/format/index.mjs +3 -3
  40. package/dist/esm/index.mjs +3 -3
  41. package/dist/esm/markdown/installIntlayerMarkdown.mjs +1 -1
  42. package/dist/esm/plugins.mjs +36 -40
  43. package/dist/esm/plugins.mjs.map +1 -1
  44. package/dist/esm/webpack/mergeConfig.mjs +1 -2
  45. package/dist/esm/webpack/mergeConfig.mjs.map +1 -1
  46. package/dist/types/esbuild/hiddenDirectory.d.ts +15 -0
  47. package/dist/types/esbuild/hiddenDirectory.d.ts.map +1 -0
  48. package/dist/types/esbuild/index.d.ts +2 -2
  49. package/dist/types/esbuild/plugin.d.ts +34 -18
  50. package/dist/types/esbuild/plugin.d.ts.map +1 -1
  51. package/dist/types/esbuild/resolvePackageExport.d.ts +37 -0
  52. package/dist/types/esbuild/resolvePackageExport.d.ts.map +1 -0
  53. package/dist/types/plugins.d.ts.map +1 -1
  54. package/dist/types/webpack/mergeConfig.d.ts.map +1 -1
  55. package/package.json +11 -10
  56. package/dist/esm/_virtual/_rolldown/runtime.mjs +0 -8
@@ -1,19 +1,29 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
2
2
  const require_runtime = require('./_virtual/_rolldown/runtime.cjs');
3
- const require_renderIntlayerNode = require('./renderIntlayerNode.cjs');
4
3
  const require_analytics_exposureSink = require('./analytics/exposureSink.cjs');
5
4
  const require_editor_ContentSelector_component = require('./editor/ContentSelector.component.cjs');
6
- let _intlayer_core_interpreter = require("@intlayer/core/interpreter");
5
+ const require_renderIntlayerNode = require('./renderIntlayerNode.cjs');
6
+ let _angular_core = require("@angular/core");
7
7
  let _intlayer_config_built = require("@intlayer/config/built");
8
+ let _intlayer_core_interpreter = require("@intlayer/core/interpreter");
8
9
  let _intlayer_core_markdown = require("@intlayer/core/markdown");
9
10
  let _intlayer_types_nodeType = require("@intlayer/types/nodeType");
10
11
  _intlayer_types_nodeType = require_runtime.__toESM(_intlayer_types_nodeType);
11
12
 
12
13
  //#region src/plugins.ts
13
- let _markdownInstall = null;
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
- _markdownInstall = m;
16
- }).catch(() => {});
14
+ /**
15
+ * Code-split markdown renderer, held in a signal.
16
+ *
17
+ * The chunk loads asynchronously, so the first dictionary evaluation may run
18
+ * before it lands. `getPlugins` reads this signal inside the `computed` of
19
+ * `useIntlayer`/`useDictionary`, which makes that computed depend on it: nodes
20
+ * stringify to their raw source until the module resolves, then the signal
21
+ * flip re-evaluates the dictionary and every binding re-renders with compiled
22
+ * HTML. This is the Angular counterpart of the `Suspense` boundary the React
23
+ * and Solid packages wrap their markdown renderer in.
24
+ */
25
+ const markdownRendererModule = (0, _angular_core.signal)(null);
26
+ if (process.env.INTLAYER_NODE_TYPE_MARKDOWN !== "false" || process.env.INTLAYER_NODE_TYPE_HTML !== "false") Promise.resolve().then(() => require("./markdown/installIntlayerMarkdown.cjs")).then((module) => markdownRendererModule.set(module)).catch(() => {});
17
27
  /** ---------------------------------------------
18
28
  * UTILS
19
29
  * --------------------------------------------- */
@@ -37,6 +47,18 @@ const createRuntimeWithOverides = (baseRuntime, overrides) => ({
37
47
  return baseRuntime.createElement(tag, props, ...children);
38
48
  }
39
49
  });
50
+ /**
51
+ * Compiles a markdown/HTML source to an HTML string with the code-split
52
+ * runtime, or returns the raw source while the renderer chunk is still
53
+ * loading. Runs at stringify time, so a node kept outside any reactive
54
+ * context still picks the renderer up once it has landed.
55
+ */
56
+ const compileToHtml = (source, components) => {
57
+ const rendererModule = (0, _angular_core.untracked)(markdownRendererModule);
58
+ if (!rendererModule) return source;
59
+ const runtime = components ? createRuntimeWithOverides(rendererModule.htmlRuntime, components) : rendererModule.htmlRuntime;
60
+ return (0, _intlayer_core_markdown.compile)(source, { runtime });
61
+ };
40
62
  /** Translation plugin. Replaces node with a locale string if nodeType = Translation. */
41
63
  const intlayerNodePlugins = {
42
64
  id: "intlayer-node-plugin",
@@ -81,41 +103,25 @@ const markdownStringPlugin = process.env.INTLAYER_NODE_TYPE_MARKDOWN === "false"
81
103
  dictionaryKey: rest.dictionaryKey,
82
104
  keyPath: []
83
105
  });
106
+ const renderMarkdown = (components) => (0, _angular_core.untracked)(markdownRendererModule)?.useMarkdown().renderMarkdown(node, components) ?? node;
84
107
  const render = (components) => require_renderIntlayerNode.renderIntlayerNode({
85
108
  ...rest,
86
109
  value: node,
87
- children: process.env.INTLAYER_EDITOR_ENABLED === "false" || !_intlayer_config_built.editor.enabled ? () => {
88
- const { renderMarkdown } = _markdownInstall?.useMarkdown() ?? { renderMarkdown: () => node };
89
- return renderMarkdown(node, components);
90
- } : () => ({
110
+ children: process.env.INTLAYER_EDITOR_ENABLED === "false" || !_intlayer_config_built.editor.enabled ? () => renderMarkdown(components) : () => ({
91
111
  component: require_editor_ContentSelector_component.ContentSelectorWrapperComponent,
92
112
  props: {
93
113
  dictionaryKey: rest.dictionaryKey,
94
114
  keyPath: rest.keyPath,
95
115
  ...components
96
116
  },
97
- children: () => {
98
- const { renderMarkdown } = _markdownInstall?.useMarkdown() ?? { renderMarkdown: () => node };
99
- return renderMarkdown(node, components);
100
- }
117
+ children: () => renderMarkdown(components)
101
118
  }),
102
119
  additionalProps: { metadata: metadataNodes }
103
120
  });
104
121
  const createProxy = (element, components) => new Proxy(element, { get(target, prop, receiver) {
105
122
  if (prop === "value") return node;
106
123
  if (prop === "metadata") return metadataNodes;
107
- if (prop === "toString") return () => {
108
- const htmlRuntime = _markdownInstall?.htmlRuntime;
109
- if (!htmlRuntime || !_intlayer_core_markdown.compile) return node;
110
- const runtime = components ? createRuntimeWithOverides(htmlRuntime, components) : htmlRuntime;
111
- return (0, _intlayer_core_markdown.compile)(node, { runtime });
112
- };
113
- if (prop === Symbol.toPrimitive) return () => {
114
- const htmlRuntime = _markdownInstall?.htmlRuntime;
115
- if (!htmlRuntime || !_intlayer_core_markdown.compile) return node;
116
- const runtime = components ? createRuntimeWithOverides(htmlRuntime, components) : htmlRuntime;
117
- return (0, _intlayer_core_markdown.compile)(node, { runtime });
118
- };
124
+ if (prop === "toString" || prop === Symbol.toPrimitive) return () => compileToHtml(node, components);
119
125
  if (prop === "use") return (newComponents) => {
120
126
  const mergedComponents = {
121
127
  ...components,
@@ -164,19 +170,9 @@ const htmlPlugin = process.env.INTLAYER_NODE_TYPE_HTML === "false" ? _intlayer_c
164
170
  });
165
171
  const createProxy = (element, components) => new Proxy(element, { get(target, prop, receiver) {
166
172
  if (prop === "value") return html;
167
- if (prop === "toString") return () => {
168
- if (!components || typeof components === "object" && Object.keys(components).length === 0) return String(html);
169
- const htmlRuntime = _markdownInstall?.htmlRuntime;
170
- if (!htmlRuntime || !_intlayer_core_markdown.compile) return String(html);
171
- const runtime = createRuntimeWithOverides(htmlRuntime, components);
172
- return (0, _intlayer_core_markdown.compile)(html, { runtime });
173
- };
174
- if (prop === Symbol.toPrimitive) return () => {
175
- if (!components || typeof components === "object" && Object.keys(components).length === 0) return String(html);
176
- const htmlRuntime = _markdownInstall?.htmlRuntime;
177
- if (!htmlRuntime || !_intlayer_core_markdown.compile) return String(html);
178
- const runtime = createRuntimeWithOverides(htmlRuntime, components);
179
- return (0, _intlayer_core_markdown.compile)(html, { runtime });
173
+ if (prop === "toString" || prop === Symbol.toPrimitive) return () => {
174
+ if (!components || Object.keys(components).length === 0) return String(html);
175
+ return compileToHtml(String(html), components);
180
176
  };
181
177
  if (prop === "use") return (userComponents) => {
182
178
  const mergedComponents = {
@@ -217,7 +213,7 @@ const pluginsCache = /* @__PURE__ */ new Map();
217
213
  * This function is used by both getIntlayer and getDictionary to ensure consistent plugin configuration.
218
214
  */
219
215
  const getPlugins = (locale, fallback = true) => {
220
- const cacheKey = `${locale ?? _intlayer_config_built.internationalization.defaultLocale}_${fallback}`;
216
+ const cacheKey = `${locale ?? _intlayer_config_built.internationalization.defaultLocale}_${fallback}_${markdownRendererModule() !== null}`;
221
217
  if (pluginsCache.has(cacheKey)) return pluginsCache.get(cacheKey);
222
218
  const plugins = [
223
219
  (0, _intlayer_core_interpreter.translationPlugin)(locale ?? _intlayer_config_built.internationalization.defaultLocale, fallback ? _intlayer_config_built.internationalization.defaultLocale : void 0),
@@ -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')\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
+ {"version":3,"file":"plugins.cjs","names":["signal","untracked","compile","renderIntlayerNode","editor","ContentSelectorWrapperComponent","fallbackPlugin","getMarkdownMetadata","NodeTypes","isInterpolableWrapperNode","transformInterpolableNode","internationalization","translationPlugin","enumerationPlugin","pluralPlugin","conditionPlugin","nestedPlugin","filePlugin","genderPlugin","selectPlugin"],"sources":["../../src/plugins.ts"],"sourcesContent":["import { signal, untracked } from '@angular/core';\nimport { 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\ntype MarkdownRendererModule = Pick<\n typeof import('./markdown/installIntlayerMarkdown'),\n 'htmlRuntime' | 'useMarkdown'\n>;\n\n/**\n * Code-split markdown renderer, held in a signal.\n *\n * The chunk loads asynchronously, so the first dictionary evaluation may run\n * before it lands. `getPlugins` reads this signal inside the `computed` of\n * `useIntlayer`/`useDictionary`, which makes that computed depend on it: nodes\n * stringify to their raw source until the module resolves, then the signal\n * flip re-evaluates the dictionary and every binding re-renders with compiled\n * HTML. This is the Angular counterpart of the `Suspense` boundary the React\n * and Solid packages wrap their markdown renderer in.\n */\nconst markdownRendererModule = signal<MarkdownRendererModule | null>(null);\n\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((module) => markdownRendererModule.set(module))\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 * Compiles a markdown/HTML source to an HTML string with the code-split\n * runtime, or returns the raw source while the renderer chunk is still\n * loading. Runs at stringify time, so a node kept outside any reactive\n * context still picks the renderer up once it has landed.\n */\nconst compileToHtml = (\n source: string,\n components?: Record<string, unknown>\n): string => {\n const rendererModule = untracked(markdownRendererModule);\n\n if (!rendererModule) return source;\n\n const runtime = components\n ? createRuntimeWithOverides(rendererModule.htmlRuntime, components)\n : rendererModule.htmlRuntime;\n\n return compile(source, { runtime }) as string;\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 renderMarkdown = (components?: any) =>\n untracked(markdownRendererModule)\n ?.useMarkdown()\n .renderMarkdown(node, components) ?? node;\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 ? () => renderMarkdown(components)\n : () => ({\n component: ContentSelectorWrapperComponent,\n props: {\n dictionaryKey: rest.dictionaryKey,\n keyPath: rest.keyPath,\n ...components,\n },\n children: () => renderMarkdown(components),\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' || prop === Symbol.toPrimitive) {\n return () => compileToHtml(node, components);\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' || prop === Symbol.toPrimitive) {\n return () => {\n // Without component overrides the source is already HTML.\n if (!components || Object.keys(components).length === 0) {\n return String(html);\n }\n\n return compileToHtml(String(html), components);\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 // Tracked read: called inside the dictionary `computed` of the hooks, so the\n // computed re-evaluates once the renderer chunk lands. The core interpreter\n // memoizes transformed content per plugin-array identity, and the transform\n // itself is lazy (property getters resolved from the template), so handing\n // out a fresh array is what discards the proxies built while pending and\n // gives every binding a new value to re-render.\n const isRendererLoaded = markdownRendererModule() !== null;\n const cacheKey = `${currentLocale}_${fallback}_${isRendererLoaded}`;\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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"}
@@ -7,7 +7,7 @@ let _intlayer_webpack = require("@intlayer/webpack");
7
7
  let defu = require("defu");
8
8
 
9
9
  //#region src/webpack/mergeConfig.ts
10
- const _require = typeof require !== "undefined" ? require : (0, node_module.createRequire)(require("url").pathToFileURL(__filename).href);
10
+ const _require = (0, node_module.createRequire)(require("url").pathToFileURL(__filename).href);
11
11
  const mergeConfig = (baseConfig) => {
12
12
  const intlayerConfig = (0, _intlayer_config_node.getConfiguration)();
13
13
  const config = {
@@ -1 +1 @@
1
- {"version":3,"file":"mergeConfig.cjs","names":["createRequire","getConfiguration","getAlias","resolve","IntlayerPlugin"],"sources":["../../../src/webpack/mergeConfig.ts"],"sourcesContent":["import { createRequire } from 'node:module';\nimport { resolve } from 'node:path';\nimport { getConfiguration } from '@intlayer/config/node';\nimport { getAlias } from '@intlayer/config/utils';\nimport { IntlayerPlugin } from '@intlayer/webpack'; // adjust path if needed\nimport { defu } from 'defu';\n\nconst _require =\n typeof require !== 'undefined' ? require : createRequire(import.meta.url);\nexport const mergeConfig = (\n baseConfig: import('webpack').Configuration\n): import('webpack').Configuration => {\n const intlayerConfig = getConfiguration();\n\n const config = {\n resolve: {\n alias: getAlias({\n configuration: intlayerConfig,\n formatter: (value: string) => resolve(value), // get absolute path\n }),\n },\n externals: {\n esbuild: 'esbuild',\n module: 'module',\n fs: 'fs',\n chokidar: 'chokidar',\n fsevents: 'fsevents',\n },\n module: {\n rules: [\n {\n test: /\\.node$/,\n loader: 'node-loader',\n },\n\n // Fix `import _48DQ2FD8DPGT8SPgqAmt from '../dictionary/app.json' with { type: 'json' };` syntax\n {\n test: /\\.mjs$/,\n include: [/[\\\\/]\\.intlayer[\\\\/]/],\n type: 'javascript/auto',\n enforce: 'pre',\n use: {\n loader: _require.resolve('babel-loader'),\n options: {\n presets: [\n [\n _require.resolve('@babel/preset-env'),\n { modules: 'commonjs' },\n ],\n ],\n plugins: [\n [\n _require.resolve('@babel/plugin-syntax-import-attributes'),\n { deprecatedAssert: true },\n ],\n ],\n },\n },\n },\n ],\n },\n plugins: [new IntlayerPlugin(intlayerConfig)],\n };\n\n return defu(config, baseConfig) as import('webpack').Configuration;\n};\n"],"mappings":";;;;;;;;;AAOA,MAAM,WACJ,OAAO,YAAY,cAAc,cAAUA,wEAA6B;AAC1E,MAAa,eACX,eACoC;CACpC,MAAM,qBAAiBC,wCAAiB;CAExC,MAAM,SAAS;EACb,SAAS,EACP,WAAOC,iCAAS;GACd,eAAe;GACf,YAAY,cAAkBC,mBAAQ,KAAK;EAC7C,CAAC,EACH;EACA,WAAW;GACT,SAAS;GACT,QAAQ;GACR,IAAI;GACJ,UAAU;GACV,UAAU;EACZ;EACA,QAAQ,EACN,OAAO,CACL;GACE,MAAM;GACN,QAAQ;EACV,GAGA;GACE,MAAM;GACN,SAAS,CAAC,sBAAsB;GAChC,MAAM;GACN,SAAS;GACT,KAAK;IACH,QAAQ,SAAS,QAAQ,cAAc;IACvC,SAAS;KACP,SAAS,CACP,CACE,SAAS,QAAQ,mBAAmB,GACpC,EAAE,SAAS,WAAW,CACxB,CACF;KACA,SAAS,CACP,CACE,SAAS,QAAQ,wCAAwC,GACzD,EAAE,kBAAkB,KAAK,CAC3B,CACF;IACF;GACF;EACF,CACF,EACF;EACA,SAAS,CAAC,IAAIC,iCAAe,cAAc,CAAC;CAC9C;CAEA,WAAO,WAAK,QAAQ,UAAU;AAChC"}
1
+ {"version":3,"file":"mergeConfig.cjs","names":["createRequire","getConfiguration","getAlias","resolve","IntlayerPlugin"],"sources":["../../../src/webpack/mergeConfig.ts"],"sourcesContent":["import { createRequire } from 'node:module';\nimport { resolve } from 'node:path';\nimport { getConfiguration } from '@intlayer/config/node';\nimport { getAlias } from '@intlayer/config/utils';\nimport { IntlayerPlugin } from '@intlayer/webpack'; // adjust path if needed\nimport { defu } from 'defu';\n\n// `import.meta.url` is shimmed to `__filename` in the CommonJS build, while a\n// `typeof require` guard would pick up the ESM build's `require` proxy.\nconst _require = createRequire(import.meta.url);\n\nexport const mergeConfig = (\n baseConfig: import('webpack').Configuration\n): import('webpack').Configuration => {\n const intlayerConfig = getConfiguration();\n\n const config = {\n resolve: {\n alias: getAlias({\n configuration: intlayerConfig,\n formatter: (value: string) => resolve(value), // get absolute path\n }),\n },\n externals: {\n esbuild: 'esbuild',\n module: 'module',\n fs: 'fs',\n chokidar: 'chokidar',\n fsevents: 'fsevents',\n },\n module: {\n rules: [\n {\n test: /\\.node$/,\n loader: 'node-loader',\n },\n\n // Fix `import _48DQ2FD8DPGT8SPgqAmt from '../dictionary/app.json' with { type: 'json' };` syntax\n {\n test: /\\.mjs$/,\n include: [/[\\\\/]\\.intlayer[\\\\/]/],\n type: 'javascript/auto',\n enforce: 'pre',\n use: {\n loader: _require.resolve('babel-loader'),\n options: {\n presets: [\n [\n _require.resolve('@babel/preset-env'),\n { modules: 'commonjs' },\n ],\n ],\n plugins: [\n [\n _require.resolve('@babel/plugin-syntax-import-attributes'),\n { deprecatedAssert: true },\n ],\n ],\n },\n },\n },\n ],\n },\n plugins: [new IntlayerPlugin(intlayerConfig)],\n };\n\n return defu(config, baseConfig) as import('webpack').Configuration;\n};\n"],"mappings":";;;;;;;;;AASA,MAAM,eAAWA,wEAA6B;AAE9C,MAAa,eACX,eACoC;CACpC,MAAM,qBAAiBC,wCAAiB;CAExC,MAAM,SAAS;EACb,SAAS,EACP,WAAOC,iCAAS;GACd,eAAe;GACf,YAAY,cAAkBC,mBAAQ,KAAK;EAC7C,CAAC,EACH;EACA,WAAW;GACT,SAAS;GACT,QAAQ;GACR,IAAI;GACJ,UAAU;GACV,UAAU;EACZ;EACA,QAAQ,EACN,OAAO,CACL;GACE,MAAM;GACN,QAAQ;EACV,GAGA;GACE,MAAM;GACN,SAAS,CAAC,sBAAsB;GAChC,MAAM;GACN,SAAS;GACT,KAAK;IACH,QAAQ,SAAS,QAAQ,cAAc;IACvC,SAAS;KACP,SAAS,CACP,CACE,SAAS,QAAQ,mBAAmB,GACpC,EAAE,SAAS,WAAW,CACxB,CACF;KACA,SAAS,CACP,CACE,SAAS,QAAQ,wCAAwC,GACzD,EAAE,kBAAkB,KAAK,CAC3B,CACF;IACF;GACF;EACF,CACF,EACF;EACA,SAAS,CAAC,IAAIC,iCAAe,cAAc,CAAC;CAC9C;CAEA,WAAO,WAAK,QAAQ,UAAU;AAChC"}
@@ -1,5 +1,5 @@
1
- import { setExposureSink } from "./exposureSink.mjs";
2
1
  import { INTLAYER_TOKEN } from "../client/intlayerToken.mjs";
2
+ import { setExposureSink } from "./exposureSink.mjs";
3
3
  import { DestroyRef, Injector, effect, inject, provideAppInitializer, runInInjectionContext, signal } from "@angular/core";
4
4
  import { isEnabled } from "@intlayer/analytics/isEnabled";
5
5
 
@@ -1,5 +1,5 @@
1
- import { internationalization } from "@intlayer/config/built";
2
1
  import { InjectionToken, signal } from "@angular/core";
2
+ import { internationalization } from "@intlayer/config/built";
3
3
  import { setIntlayerIdentifier } from "@intlayer/config/client";
4
4
 
5
5
  //#region src/client/intlayerToken.ts
@@ -1,5 +1,5 @@
1
- import { getDictionary } from "../getDictionary.mjs";
2
1
  import { INTLAYER_TOKEN } from "./intlayerToken.mjs";
2
+ import { getDictionary } from "../getDictionary.mjs";
3
3
  import { computed, inject } from "@angular/core";
4
4
  import { resolveDictionaryArgument } from "@intlayer/core/dictionaryManipulator";
5
5
 
@@ -2,8 +2,8 @@
2
2
 
3
3
  import { INTLAYER_TOKEN } from "./intlayerToken.mjs";
4
4
  import { useDictionary } from "./useDictionary.mjs";
5
- import { internationalization } from "@intlayer/config/built";
6
5
  import { computed, inject } from "@angular/core";
6
+ import { internationalization } from "@intlayer/config/built";
7
7
 
8
8
  //#region src/client/useDictionaryAsync.ts
9
9
  /**
@@ -1,11 +1,11 @@
1
1
  'use client';
2
2
 
3
- import { getDictionary } from "../getDictionary.mjs";
4
3
  import { INTLAYER_TOKEN } from "./intlayerToken.mjs";
4
+ import { getDictionary } from "../getDictionary.mjs";
5
5
  import { useDictionary } from "./useDictionary.mjs";
6
6
  import { useLoadDynamic } from "./useLoadDynamic.mjs";
7
- import { internationalization } from "@intlayer/config/built";
8
7
  import { computed, inject, signal } from "@angular/core";
8
+ import { internationalization } from "@intlayer/config/built";
9
9
  import { getPreloadedDictionary, isQualifiedDynamicLoaderMap, parseDictionarySelector, resolveDictionaryArgument, resolveQualifiedDynamicContentAsync } from "@intlayer/core/dictionaryManipulator";
10
10
 
11
11
  //#region src/client/useDictionaryDynamic.ts
@@ -1,5 +1,5 @@
1
- import { getIntlayer } from "../getIntlayer.mjs";
2
1
  import { INTLAYER_TOKEN } from "./intlayerToken.mjs";
2
+ import { getIntlayer } from "../getIntlayer.mjs";
3
3
  import { computed, inject } from "@angular/core";
4
4
  import { resolveDictionaryArgument } from "@intlayer/core/dictionaryManipulator";
5
5
 
@@ -1,7 +1,7 @@
1
1
  import { INTLAYER_TOKEN } from "./intlayerToken.mjs";
2
2
  import { setLocaleInStorage } from "./useLocaleStorage.mjs";
3
- import { internationalization } from "@intlayer/config/built";
4
3
  import { computed, inject } from "@angular/core";
4
+ import { internationalization } from "@intlayer/config/built";
5
5
 
6
6
  //#region src/client/useLocale.ts
7
7
  const { defaultLocale, locales: availableLocales } = internationalization ?? {};
@@ -1,6 +1,6 @@
1
+ import { useEditor } from "./useEditor.mjs";
1
2
  import __decorateMetadata from "../_virtual/_@oxc-project_runtime@0.148.0/helpers/esm/decorateMetadata.mjs";
2
3
  import __decorate from "../_virtual/_@oxc-project_runtime@0.148.0/helpers/esm/decorate.mjs";
3
- import { useEditor } from "./useEditor.mjs";
4
4
  import { Component } from "@angular/core";
5
5
 
6
6
  //#region src/editor/EditorProvider.component.ts
@@ -1,5 +1,5 @@
1
- import { ContentSelectorWrapperComponent } from "./ContentSelector.component.mjs";
2
1
  import { provideIntlayerEditor, useEditor } from "./useEditor.mjs";
2
+ import { ContentSelectorWrapperComponent } from "./ContentSelector.component.mjs";
3
3
  import { EditorProviderComponent } from "./EditorProvider.component.mjs";
4
4
 
5
5
  export { ContentSelectorWrapperComponent, EditorProviderComponent, provideIntlayerEditor, useEditor };
@@ -0,0 +1,19 @@
1
+ import { relative, sep } from "node:path";
2
+
3
+ //#region src/esbuild/hiddenDirectory.ts
4
+ /**
5
+ * Whether `directory` sits under a dot-directory (`.intlayer/…`) of `baseDir`.
6
+ *
7
+ * Angular's esbuild dev server ignores `<workspace>/**\/.*\/**` in its file
8
+ * watcher, so generated files living there never invalidate its TypeScript
9
+ * source cache: a key added to a dictionary regenerates the types, but the
10
+ * template type-checker keeps the stale declaration until `ng serve` restarts.
11
+ *
12
+ * @param baseDir - Angular workspace root (the Intlayer `system.baseDir`).
13
+ * @param directory - Absolute directory to test.
14
+ */
15
+ const isInHiddenDirectory = (baseDir, directory) => relative(baseDir, directory).split(sep).some((segment) => segment.startsWith(".") && segment !== "..");
16
+
17
+ //#endregion
18
+ export { isInHiddenDirectory };
19
+ //# sourceMappingURL=hiddenDirectory.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hiddenDirectory.mjs","names":[],"sources":["../../../src/esbuild/hiddenDirectory.ts"],"sourcesContent":["import { relative, sep } from 'node:path';\n\n/**\n * Whether `directory` sits under a dot-directory (`.intlayer/…`) of `baseDir`.\n *\n * Angular's esbuild dev server ignores `<workspace>/**\\/.*\\/**` in its file\n * watcher, so generated files living there never invalidate its TypeScript\n * source cache: a key added to a dictionary regenerates the types, but the\n * template type-checker keeps the stale declaration until `ng serve` restarts.\n *\n * @param baseDir - Angular workspace root (the Intlayer `system.baseDir`).\n * @param directory - Absolute directory to test.\n */\nexport const isInHiddenDirectory = (\n baseDir: string,\n directory: string\n): boolean =>\n relative(baseDir, directory)\n .split(sep)\n .some((segment) => segment.startsWith('.') && segment !== '..');\n"],"mappings":";;;;;;;;;;;;;;AAaA,MAAa,uBACX,SACA,cAEA,SAAS,SAAS,SAAS,CAAC,CACzB,MAAM,GAAG,CAAC,CACV,MAAM,YAAY,QAAQ,WAAW,GAAG,KAAK,YAAY,IAAI"}
@@ -1,12 +1,13 @@
1
- import { __require } from "../_virtual/_rolldown/runtime.mjs";
2
- import { createRequire } from "node:module";
3
- import { join } from "node:path";
4
- import { getConfiguration } from "@intlayer/config/node";
5
- import { getAlias, getHasDictionarySelector, getUnusedNodeTypesAsync, normalizePath } from "@intlayer/config/utils";
1
+ import { isInHiddenDirectory } from "./hiddenDirectory.mjs";
2
+ import { resolvePackageExport } from "./resolvePackageExport.mjs";
6
3
  import { readFile } from "node:fs/promises";
4
+ import { createRequire } from "node:module";
5
+ import { basename, dirname, join, relative } from "node:path";
7
6
  import { addDynamicEntryPreload, createDynamicEntryFilter, resolvePreloadModuleId } from "@intlayer/config/dictionaryPreload";
8
7
  import { formatDictionarySelectorEnvVar, formatNodeTypeToEnvVar, getConfigEnvVars } from "@intlayer/config/envVars";
9
8
  import { getAppLogger } from "@intlayer/config/logger";
9
+ import { getConfiguration } from "@intlayer/config/node";
10
+ import { getAlias, getHasDictionarySelector, getUnusedNodeTypesAsync, normalizePath } from "@intlayer/config/utils";
10
11
  import { getDictionaries } from "@intlayer/dictionaries-entry";
11
12
  import { prepareIntlayer } from "@intlayer/engine/build";
12
13
  import { logConfigDetails } from "@intlayer/engine/cli";
@@ -22,9 +23,34 @@ import { watch } from "@intlayer/engine/watcher";
22
23
  * only depends on `intlayer` and its framework binding, so the bare specifier
23
24
  * would resolve from a tree that need not contain the package at all.
24
25
  *
25
- * This package ships both module formats, hence the `require` fallback.
26
+ * Always built from `import.meta.url`: the bundler shims it to `__filename` in
27
+ * the CommonJS output, whereas a `typeof require` guard is unreliable here —
28
+ * the ESM output rewrites `require` into an always-defined proxy that has no
29
+ * `resolve` method.
26
30
  */
27
- const preloadModuleId = normalizePath(resolvePreloadModuleId(typeof __require !== "undefined" ? __require : createRequire(import.meta.url)));
31
+ const preloadModuleId = normalizePath(resolvePreloadModuleId(createRequire(import.meta.url)));
32
+ /** Bare specifiers of the packages this plugin keeps inside its own build. */
33
+ const INTLAYER_PACKAGE_FILTER = /^(?:intlayer|angular-intlayer|@intlayer\/[^/]+)(?:\/|$)/;
34
+ /** Namespace of the re-export shims standing in for externalised packages. */
35
+ const INTLAYER_PACKAGE_NAMESPACE = "intlayer-package";
36
+ /** Matches a module that has a default export, on unminified sources. */
37
+ const DEFAULT_EXPORT_PATTERN = /\bexport\s+default\b|\bas\s+default\b|\{\s*default\s*[,}]/;
38
+ /**
39
+ * The dev server's file watcher skips dot-directories, so type declarations
40
+ * generated there are never re-read: a key added to a dictionary stays unknown
41
+ * to template type-checking until `ng serve` restarts. Nothing in the plugin
42
+ * can reach that cache, so the fix is to generate the types elsewhere.
43
+ */
44
+ const warnAboutHiddenTypesDirectory = (configuration, appLogger) => {
45
+ const { baseDir, typesDir, moduleAugmentationDir } = configuration.system;
46
+ const hiddenDirectories = [.../* @__PURE__ */ new Set([typesDir, moduleAugmentationDir])].filter((directory) => isInHiddenDirectory(baseDir, directory));
47
+ if (hiddenDirectories.length === 0) return;
48
+ appLogger([
49
+ `Type declarations are generated under ${hiddenDirectories.map((directory) => relative(baseDir, directory)).join(", ")}.`,
50
+ "The Angular dev server does not watch dot-directories, so keys added to a dictionary stay unknown to template type-checking until 'ng serve' restarts.",
51
+ "Set 'system.typesDir' and 'system.moduleAugmentationDir' to a directory outside any dot-directory (e.g. 'intlayer-types') and point the tsconfig 'include' at it."
52
+ ].join(" "), { level: "warn" });
53
+ };
28
54
  /**
29
55
  * esbuild plugin that integrates Intlayer into the Angular (or any esbuild-based) build process.
30
56
  *
@@ -101,6 +127,36 @@ const intlayerEsbuildPlugin = (options) => {
101
127
  const escapedFrom = from.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
102
128
  build.onResolve({ filter: new RegExp(`^${escapedFrom}$`) }, () => ({ path: to }));
103
129
  }
130
+ let externalizesPackages;
131
+ build.onResolve({ filter: INTLAYER_PACKAGE_FILTER }, (args) => {
132
+ if (!externalizesPackages || !args.resolveDir) return null;
133
+ const importCondition = args.kind.startsWith("require") ? "require" : "import";
134
+ const resolved = resolvePackageExport(args.path, args.resolveDir, [
135
+ "browser",
136
+ "module",
137
+ importCondition
138
+ ]);
139
+ if (!resolved) return null;
140
+ return {
141
+ path: `${encodeURIComponent(dirname(resolved.path))}/${args.path}`,
142
+ namespace: INTLAYER_PACKAGE_NAMESPACE,
143
+ pluginData: { realPath: resolved.path },
144
+ sideEffects: resolved.sideEffects
145
+ };
146
+ });
147
+ build.onLoad({
148
+ filter: /.*/,
149
+ namespace: INTLAYER_PACKAGE_NAMESPACE
150
+ }, async (args) => {
151
+ const { realPath } = args.pluginData;
152
+ const source = await readFile(realPath, "utf-8");
153
+ const specifier = JSON.stringify(`./${basename(realPath)}`);
154
+ return {
155
+ contents: [`export * from ${specifier};`, DEFAULT_EXPORT_PATTERN.test(source) && `export { default } from ${specifier};`].filter(Boolean).join("\n"),
156
+ loader: "js",
157
+ resolveDir: dirname(realPath)
158
+ };
159
+ });
104
160
  if (config.build.dictionariesPreload) {
105
161
  const dynamicDictionariesDir = normalizePath(config.system.dynamicDictionariesDir);
106
162
  build.onLoad({ filter: createDynamicEntryFilter(dynamicDictionariesDir) }, async ({ path }) => {
@@ -121,6 +177,13 @@ const intlayerEsbuildPlugin = (options) => {
121
177
  });
122
178
  await preparePromise;
123
179
  build.onStart(async () => {
180
+ if (externalizesPackages === void 0) {
181
+ externalizesPackages = (await build.resolve("@angular/core", {
182
+ kind: "import-statement",
183
+ resolveDir: config.system.baseDir
184
+ })).external;
185
+ if (externalizesPackages) warnAboutHiddenTypesDirectory(config, appLogger);
186
+ }
124
187
  if ((options?.watch ?? !isBuildMode) && !watcherStarted) {
125
188
  watcherStarted = true;
126
189
  await watch({ configuration: config });
@@ -1 +1 @@
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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"}
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 { basename, dirname, join, relative } 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';\nimport type { IntlayerConfig } from '@intlayer/types/config';\nimport { isInHiddenDirectory } from './hiddenDirectory';\nimport { resolvePackageExport } from './resolvePackageExport';\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 * Always built from `import.meta.url`: the bundler shims it to `__filename` in\n * the CommonJS output, whereas a `typeof require` guard is unreliable here —\n * the ESM output rewrites `require` into an always-defined proxy that has no\n * `resolve` method.\n */\nconst preloadModuleId = normalizePath(\n resolvePreloadModuleId(createRequire(import.meta.url))\n);\n\n/** Bare specifiers of the packages this plugin keeps inside its own build. */\nconst INTLAYER_PACKAGE_FILTER =\n /^(?:intlayer|angular-intlayer|@intlayer\\/[^/]+)(?:\\/|$)/;\n\n/** Namespace of the re-export shims standing in for externalised packages. */\nconst INTLAYER_PACKAGE_NAMESPACE = 'intlayer-package';\n\n/** Matches a module that has a default export, on unminified sources. */\nconst DEFAULT_EXPORT_PATTERN =\n /\\bexport\\s+default\\b|\\bas\\s+default\\b|\\{\\s*default\\s*[,}]/;\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 type EsbuildResolveArgs = {\n path: string;\n importer: string;\n namespace: string;\n resolveDir: string;\n kind: string;\n pluginData?: unknown;\n};\n\nexport type EsbuildResolveResult = {\n path?: string;\n namespace?: string;\n external?: boolean;\n sideEffects?: boolean;\n pluginData?: unknown;\n errors?: unknown[];\n warnings?: unknown[];\n};\n\nexport type EsbuildLoadArgs = {\n path: string;\n namespace: string;\n pluginData?: unknown;\n};\n\nexport type EsbuildLoadResult = {\n contents: string;\n loader?: string;\n /** Directory relative imports of `contents` resolve from. */\n resolveDir?: string;\n};\n\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: (\n args: EsbuildResolveArgs\n ) =>\n | EsbuildResolveResult\n | null\n | undefined\n | Promise<EsbuildResolveResult | null | undefined>\n ): void;\n /** Run the remaining resolution pipeline (other plugins, then esbuild). */\n resolve(\n path: string,\n options: Partial<Omit<EsbuildResolveArgs, 'path'>>\n ): Promise<EsbuildResolveResult & { path: string; external: boolean }>;\n /** Intercept module contents, so a resolved file can be rewritten. */\n onLoad(\n options: { filter: RegExp; namespace?: string },\n callback: (\n args: EsbuildLoadArgs\n ) =>\n | EsbuildLoadResult\n | null\n | undefined\n | Promise<EsbuildLoadResult | 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 * The dev server's file watcher skips dot-directories, so type declarations\n * generated there are never re-read: a key added to a dictionary stays unknown\n * to template type-checking until `ng serve` restarts. Nothing in the plugin\n * can reach that cache, so the fix is to generate the types elsewhere.\n */\nconst warnAboutHiddenTypesDirectory = (\n configuration: IntlayerConfig,\n appLogger: ReturnType<typeof getAppLogger>\n) => {\n const { baseDir, typesDir, moduleAugmentationDir } = configuration.system;\n\n const hiddenDirectories = [\n ...new Set([typesDir, moduleAugmentationDir]),\n ].filter((directory) => isInHiddenDirectory(baseDir, directory));\n\n if (hiddenDirectories.length === 0) return;\n\n appLogger(\n [\n `Type declarations are generated under ${hiddenDirectories.map((directory) => relative(baseDir, directory)).join(', ')}.`,\n \"The Angular dev server does not watch dot-directories, so keys added to a dictionary stay unknown to template type-checking until 'ng serve' restarts.\",\n \"Set 'system.typesDir' and 'system.moduleAugmentationDir' to a directory outside any dot-directory (e.g. 'intlayer-types') and point the tsconfig 'include' at it.\",\n ].join(' '),\n { level: 'warn' }\n );\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 // Angular's dev server marks every import that resolves under\n // `node_modules` as external so Vite can pre-bundle it. Vite's\n // pre-bundler runs without this plugin, so the aliases above never apply\n // there and the real `@intlayer/config/built` — a Node config loader —\n // ends up in the browser. Angular's externalising plugin is registered\n // ahead of this one and only lets a resolution through when the path it\n // gets back is outside `node_modules`; so in that mode an Intlayer\n // package resolves to a re-export shim in its own namespace, whose\n // relative import of the real file the pipeline then bundles as usual.\n // Whether the pipeline externalises packages is probed once, at the\n // first build, so production builds keep the bundler's own resolution.\n let externalizesPackages: boolean | undefined;\n\n build.onResolve({ filter: INTLAYER_PACKAGE_FILTER }, (args) => {\n if (!externalizesPackages || !args.resolveDir) return null;\n\n const importCondition = args.kind.startsWith('require')\n ? 'require'\n : 'import';\n const resolved = resolvePackageExport(args.path, args.resolveDir, [\n 'browser',\n 'module',\n importCondition,\n ]);\n\n if (!resolved) return null;\n\n return {\n // Neither a `node_modules` segment nor a script extension, which the\n // externalising plugin and Angular's own JS loader key on. Ends with\n // the specifier so a lazy chunk is named after it, and starts with\n // the encoded directory so two copies of a package stay distinct.\n path: `${encodeURIComponent(dirname(resolved.path))}/${args.path}`,\n namespace: INTLAYER_PACKAGE_NAMESPACE,\n pluginData: { realPath: resolved.path },\n sideEffects: resolved.sideEffects,\n };\n });\n\n build.onLoad(\n { filter: /.*/, namespace: INTLAYER_PACKAGE_NAMESPACE },\n async (args) => {\n const { realPath } = args.pluginData as { realPath: string };\n const source = await readFile(realPath, 'utf-8');\n const specifier = JSON.stringify(`./${basename(realPath)}`);\n\n const contents = [\n `export * from ${specifier};`,\n DEFAULT_EXPORT_PATTERN.test(source) &&\n `export { default } from ${specifier};`,\n ]\n .filter(Boolean)\n .join('\\n');\n\n return { contents, loader: 'js', resolveDir: dirname(realPath) };\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 // `@angular/core` is always installed and never worth excluding from\n // pre-bundling, so its fate tells whether packages get externalised.\n if (externalizesPackages === undefined) {\n externalizesPackages = (\n await build.resolve('@angular/core', {\n kind: 'import-statement',\n resolveDir: config!.system.baseDir,\n })\n ).external;\n\n if (externalizesPackages) {\n warnAboutHiddenTypesDirectory(config!, appLogger);\n }\n }\n\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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"}