angular-intlayer 9.0.0-canary.9 → 9.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/UI/IntlayerNode.component.cjs +4 -5
- package/dist/cjs/UI/IntlayerNode.component.cjs.map +1 -1
- package/dist/cjs/_virtual/{_@oxc-project_runtime@0.127.0/helpers → _@oxc-project_runtime@0.140.0/helpers/esm}/decorate.cjs +2 -2
- package/dist/{esm/_virtual/_@oxc-project_runtime@0.127.0/helpers/decorateMetadata.mjs → cjs/_virtual/_@oxc-project_runtime@0.140.0/helpers/esm/decorateMetadata.cjs} +3 -2
- package/dist/cjs/analytics/exposureSink.cjs +27 -0
- package/dist/cjs/analytics/exposureSink.cjs.map +1 -0
- package/dist/cjs/analytics/index.cjs +9 -0
- package/dist/cjs/analytics/useAnalytics.cjs +84 -0
- package/dist/cjs/analytics/useAnalytics.cjs.map +1 -0
- package/dist/cjs/analytics/useConversion.cjs +36 -0
- package/dist/cjs/analytics/useConversion.cjs.map +1 -0
- package/dist/cjs/analytics/useExperiment.cjs +69 -0
- package/dist/cjs/analytics/useExperiment.cjs.map +1 -0
- package/dist/cjs/client/installIntlayer.cjs +9 -4
- package/dist/cjs/client/installIntlayer.cjs.map +1 -1
- package/dist/cjs/client/intlayerToken.cjs +0 -1
- package/dist/cjs/client/intlayerToken.cjs.map +1 -1
- package/dist/cjs/client/useDictionary.cjs +0 -1
- package/dist/cjs/client/useDictionary.cjs.map +1 -1
- package/dist/cjs/client/useDictionaryAsync.cjs +0 -1
- package/dist/cjs/client/useDictionaryAsync.cjs.map +1 -1
- package/dist/cjs/client/useDictionaryDynamic.cjs +0 -1
- package/dist/cjs/client/useDictionaryDynamic.cjs.map +1 -1
- package/dist/cjs/client/useIntlayer.cjs +0 -1
- package/dist/cjs/client/useIntlayer.cjs.map +1 -1
- package/dist/cjs/client/useLoadDynamic.cjs +0 -1
- package/dist/cjs/client/useLoadDynamic.cjs.map +1 -1
- package/dist/cjs/client/useLocale.cjs +0 -1
- package/dist/cjs/client/useLocale.cjs.map +1 -1
- package/dist/cjs/client/useLocaleStorage.cjs +0 -1
- package/dist/cjs/client/useLocaleStorage.cjs.map +1 -1
- package/dist/cjs/client/usePathname.cjs +0 -1
- package/dist/cjs/client/usePathname.cjs.map +1 -1
- package/dist/cjs/editor/ContentSelector.component.cjs +5 -6
- package/dist/cjs/editor/ContentSelector.component.cjs.map +1 -1
- package/dist/cjs/editor/EditorProvider.component.cjs +4 -5
- package/dist/cjs/editor/EditorProvider.component.cjs.map +1 -1
- package/dist/cjs/editor/useEditor.cjs +0 -1
- package/dist/cjs/editor/useEditor.cjs.map +1 -1
- package/dist/cjs/esbuild/plugin.cjs +19 -12
- package/dist/cjs/esbuild/plugin.cjs.map +1 -1
- package/dist/cjs/format/useCompact.cjs +0 -1
- package/dist/cjs/format/useCompact.cjs.map +1 -1
- package/dist/cjs/format/useCurrency.cjs +0 -1
- package/dist/cjs/format/useCurrency.cjs.map +1 -1
- package/dist/cjs/format/useDate.cjs +0 -1
- package/dist/cjs/format/useDate.cjs.map +1 -1
- package/dist/cjs/format/useIntl.cjs +0 -1
- package/dist/cjs/format/useIntl.cjs.map +1 -1
- package/dist/cjs/format/useList.cjs +0 -1
- package/dist/cjs/format/useList.cjs.map +1 -1
- package/dist/cjs/format/useNumber.cjs +0 -1
- package/dist/cjs/format/useNumber.cjs.map +1 -1
- package/dist/cjs/format/usePercentage.cjs +0 -1
- package/dist/cjs/format/usePercentage.cjs.map +1 -1
- package/dist/cjs/format/useRelativeTime.cjs +0 -1
- package/dist/cjs/format/useRelativeTime.cjs.map +1 -1
- package/dist/cjs/format/useUnit.cjs +0 -1
- package/dist/cjs/format/useUnit.cjs.map +1 -1
- package/dist/cjs/getDictionary.cjs +0 -1
- package/dist/cjs/getDictionary.cjs.map +1 -1
- package/dist/cjs/getIntlayer.cjs +0 -1
- package/dist/cjs/getIntlayer.cjs.map +1 -1
- package/dist/cjs/html/installIntlayerHTML.cjs +2 -3
- package/dist/cjs/html/installIntlayerHTML.cjs.map +1 -1
- package/dist/cjs/index.cjs +7 -0
- package/dist/cjs/markdown/installIntlayerMarkdown.cjs +2 -3
- package/dist/cjs/markdown/installIntlayerMarkdown.cjs.map +1 -1
- package/dist/cjs/plugins.cjs +29 -16
- package/dist/cjs/plugins.cjs.map +1 -1
- package/dist/cjs/renderIntlayerNode.cjs.map +1 -1
- package/dist/cjs/webpack/mergeConfig.cjs +1 -2
- package/dist/cjs/webpack/mergeConfig.cjs.map +1 -1
- package/dist/esm/UI/IntlayerNode.component.mjs +2 -2
- package/dist/esm/UI/IntlayerNode.component.mjs.map +1 -1
- package/dist/esm/_virtual/{_@oxc-project_runtime@0.127.0/helpers → _@oxc-project_runtime@0.140.0/helpers/esm}/decorate.mjs +2 -2
- package/dist/{cjs/_virtual/_@oxc-project_runtime@0.127.0/helpers/decorateMetadata.cjs → esm/_virtual/_@oxc-project_runtime@0.140.0/helpers/esm/decorateMetadata.mjs} +2 -3
- package/dist/esm/analytics/exposureSink.mjs +24 -0
- package/dist/esm/analytics/exposureSink.mjs.map +1 -0
- package/dist/esm/analytics/index.mjs +5 -0
- package/dist/esm/analytics/useAnalytics.mjs +82 -0
- package/dist/esm/analytics/useAnalytics.mjs.map +1 -0
- package/dist/esm/analytics/useConversion.mjs +35 -0
- package/dist/esm/analytics/useConversion.mjs.map +1 -0
- package/dist/esm/analytics/useExperiment.mjs +68 -0
- package/dist/esm/analytics/useExperiment.mjs.map +1 -0
- package/dist/esm/client/installIntlayer.mjs +9 -4
- package/dist/esm/client/installIntlayer.mjs.map +1 -1
- package/dist/esm/client/intlayerToken.mjs.map +1 -1
- package/dist/esm/client/useDictionary.mjs.map +1 -1
- package/dist/esm/client/useDictionaryAsync.mjs.map +1 -1
- package/dist/esm/client/useDictionaryDynamic.mjs.map +1 -1
- package/dist/esm/client/useIntlayer.mjs.map +1 -1
- package/dist/esm/client/useLoadDynamic.mjs.map +1 -1
- package/dist/esm/client/useLocale.mjs.map +1 -1
- package/dist/esm/client/useLocaleStorage.mjs.map +1 -1
- package/dist/esm/client/usePathname.mjs.map +1 -1
- package/dist/esm/editor/ContentSelector.component.mjs +2 -2
- package/dist/esm/editor/ContentSelector.component.mjs.map +1 -1
- package/dist/esm/editor/EditorProvider.component.mjs +2 -2
- package/dist/esm/editor/EditorProvider.component.mjs.map +1 -1
- package/dist/esm/editor/useEditor.mjs.map +1 -1
- package/dist/esm/esbuild/plugin.mjs +16 -8
- package/dist/esm/esbuild/plugin.mjs.map +1 -1
- package/dist/esm/format/useCompact.mjs.map +1 -1
- package/dist/esm/format/useCurrency.mjs.map +1 -1
- package/dist/esm/format/useDate.mjs.map +1 -1
- package/dist/esm/format/useIntl.mjs.map +1 -1
- package/dist/esm/format/useList.mjs.map +1 -1
- package/dist/esm/format/useNumber.mjs.map +1 -1
- package/dist/esm/format/usePercentage.mjs.map +1 -1
- package/dist/esm/format/useRelativeTime.mjs.map +1 -1
- package/dist/esm/format/useUnit.mjs.map +1 -1
- package/dist/esm/getDictionary.mjs.map +1 -1
- package/dist/esm/getIntlayer.mjs.map +1 -1
- package/dist/esm/html/installIntlayerHTML.mjs +1 -1
- package/dist/esm/html/installIntlayerHTML.mjs.map +1 -1
- package/dist/esm/index.mjs +4 -1
- package/dist/esm/markdown/installIntlayerMarkdown.mjs +1 -1
- package/dist/esm/markdown/installIntlayerMarkdown.mjs.map +1 -1
- package/dist/esm/plugins.mjs +30 -17
- package/dist/esm/plugins.mjs.map +1 -1
- package/dist/esm/renderIntlayerNode.mjs.map +1 -1
- package/dist/esm/webpack/mergeConfig.mjs.map +1 -1
- package/dist/types/UI/IntlayerNode.component.d.ts +0 -1
- package/dist/types/UI/IntlayerNode.component.d.ts.map +1 -1
- package/dist/types/analytics/exposureSink.d.ts +32 -0
- package/dist/types/analytics/exposureSink.d.ts.map +1 -0
- package/dist/types/analytics/index.d.ts +4 -0
- package/dist/types/analytics/useAnalytics.d.ts +36 -0
- package/dist/types/analytics/useAnalytics.d.ts.map +1 -0
- package/dist/types/analytics/useConversion.d.ts +38 -0
- package/dist/types/analytics/useConversion.d.ts.map +1 -0
- package/dist/types/analytics/useExperiment.d.ts +47 -0
- package/dist/types/analytics/useExperiment.d.ts.map +1 -0
- package/dist/types/client/installIntlayer.d.ts +2 -4
- package/dist/types/client/installIntlayer.d.ts.map +1 -1
- package/dist/types/client/intlayerToken.d.ts +1 -3
- package/dist/types/client/intlayerToken.d.ts.map +1 -1
- package/dist/types/client/useDictionary.d.ts +0 -1
- package/dist/types/client/useDictionary.d.ts.map +1 -1
- package/dist/types/client/useDictionaryAsync.d.ts +1 -3
- package/dist/types/client/useDictionaryAsync.d.ts.map +1 -1
- package/dist/types/client/useDictionaryDynamic.d.ts +1 -3
- package/dist/types/client/useDictionaryDynamic.d.ts.map +1 -1
- package/dist/types/client/useIntlayer.d.ts +0 -1
- package/dist/types/client/useIntlayer.d.ts.map +1 -1
- package/dist/types/client/useLoadDynamic.d.ts.map +1 -1
- package/dist/types/client/useLocale.d.ts +1 -5
- package/dist/types/client/useLocale.d.ts.map +1 -1
- package/dist/types/client/useLocaleStorage.d.ts +5 -7
- package/dist/types/client/useLocaleStorage.d.ts.map +1 -1
- package/dist/types/client/usePathname.d.ts +0 -1
- package/dist/types/client/usePathname.d.ts.map +1 -1
- package/dist/types/editor/ContentSelector.component.d.ts.map +1 -1
- package/dist/types/editor/EditorProvider.component.d.ts.map +1 -1
- package/dist/types/editor/useEditor.d.ts +1 -3
- package/dist/types/editor/useEditor.d.ts.map +1 -1
- package/dist/types/esbuild/plugin.d.ts +2 -2
- package/dist/types/esbuild/plugin.d.ts.map +1 -1
- package/dist/types/format/useCompact.d.ts +2 -5
- package/dist/types/format/useCompact.d.ts.map +1 -1
- package/dist/types/format/useCurrency.d.ts +2 -5
- package/dist/types/format/useCurrency.d.ts.map +1 -1
- package/dist/types/format/useDate.d.ts +3 -7
- package/dist/types/format/useDate.d.ts.map +1 -1
- package/dist/types/format/useIntl.d.ts +1 -3
- package/dist/types/format/useIntl.d.ts.map +1 -1
- package/dist/types/format/useList.d.ts +5 -8
- package/dist/types/format/useList.d.ts.map +1 -1
- package/dist/types/format/useNumber.d.ts +2 -5
- package/dist/types/format/useNumber.d.ts.map +1 -1
- package/dist/types/format/usePercentage.d.ts +2 -5
- package/dist/types/format/usePercentage.d.ts.map +1 -1
- package/dist/types/format/useRelativeTime.d.ts +2 -5
- package/dist/types/format/useRelativeTime.d.ts.map +1 -1
- package/dist/types/format/useUnit.d.ts +2 -5
- package/dist/types/format/useUnit.d.ts.map +1 -1
- package/dist/types/getDictionary.d.ts +0 -1
- package/dist/types/getDictionary.d.ts.map +1 -1
- package/dist/types/getIntlayer.d.ts +0 -1
- package/dist/types/getIntlayer.d.ts.map +1 -1
- package/dist/types/html/installIntlayerHTML.d.ts +0 -1
- package/dist/types/html/installIntlayerHTML.d.ts.map +1 -1
- package/dist/types/index.d.ts +7 -2
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/markdown/installIntlayerMarkdown.d.ts +0 -1
- package/dist/types/markdown/installIntlayerMarkdown.d.ts.map +1 -1
- package/dist/types/plugins.d.ts +0 -1
- package/dist/types/plugins.d.ts.map +1 -1
- package/dist/types/renderIntlayerNode.d.ts +1 -6
- package/dist/types/renderIntlayerNode.d.ts.map +1 -1
- package/dist/types/webpack/mergeConfig.d.ts +1 -1
- package/dist/types/webpack/mergeConfig.d.ts.map +1 -1
- package/package.json +15 -12
package/dist/cjs/plugins.cjs
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
2
2
|
const require_runtime = require('./_virtual/_rolldown/runtime.cjs');
|
|
3
3
|
const require_renderIntlayerNode = require('./renderIntlayerNode.cjs');
|
|
4
|
+
const require_analytics_exposureSink = require('./analytics/exposureSink.cjs');
|
|
4
5
|
const require_editor_ContentSelector_component = require('./editor/ContentSelector.component.cjs');
|
|
5
6
|
let _intlayer_core_interpreter = require("@intlayer/core/interpreter");
|
|
6
7
|
let _intlayer_config_built = require("@intlayer/config/built");
|
|
@@ -40,18 +41,26 @@ const createRuntimeWithOverides = (baseRuntime, overrides) => ({
|
|
|
40
41
|
const intlayerNodePlugins = {
|
|
41
42
|
id: "intlayer-node-plugin",
|
|
42
43
|
canHandle: (node) => typeof node === "bigint" || typeof node === "string" || typeof node === "number",
|
|
43
|
-
transform: (_node, { children, ...rest }) =>
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
children
|
|
53
|
-
|
|
54
|
-
|
|
44
|
+
transform: (_node, { children, ...rest }) => {
|
|
45
|
+
if (process.env.INTLAYER_ANALYTICS_ENABLED !== "false") require_analytics_exposureSink.reportExposure({
|
|
46
|
+
dictionaryKey: rest.dictionaryKey,
|
|
47
|
+
keyPath: rest.keyPath,
|
|
48
|
+
locale: rest.locale,
|
|
49
|
+
nodeType: "text"
|
|
50
|
+
});
|
|
51
|
+
return require_renderIntlayerNode.renderIntlayerNode({
|
|
52
|
+
...rest,
|
|
53
|
+
value: children,
|
|
54
|
+
children: () => ({
|
|
55
|
+
component: process.env.INTLAYER_EDITOR_ENABLED === "false" || !_intlayer_config_built.editor.enabled ? children : require_editor_ContentSelector_component.ContentSelectorWrapperComponent,
|
|
56
|
+
props: {
|
|
57
|
+
dictionaryKey: rest.dictionaryKey,
|
|
58
|
+
keyPath: rest.keyPath
|
|
59
|
+
},
|
|
60
|
+
children
|
|
61
|
+
})
|
|
62
|
+
});
|
|
63
|
+
}
|
|
55
64
|
};
|
|
56
65
|
/** Markdown string plugin. Replaces string node with a component that render the markdown. */
|
|
57
66
|
const markdownStringPlugin = process.env.INTLAYER_NODE_TYPE_MARKDOWN === "false" ? _intlayer_core_interpreter.fallbackPlugin : {
|
|
@@ -157,13 +166,15 @@ const htmlPlugin = process.env.INTLAYER_NODE_TYPE_HTML === "false" ? _intlayer_c
|
|
|
157
166
|
if (!components || typeof components === "object" && Object.keys(components).length === 0) return String(html);
|
|
158
167
|
const htmlRuntime = _markdownInstall?.htmlRuntime;
|
|
159
168
|
if (!htmlRuntime || !_intlayer_core_markdown.compile) return String(html);
|
|
160
|
-
|
|
169
|
+
const runtime = createRuntimeWithOverides(htmlRuntime, components);
|
|
170
|
+
return (0, _intlayer_core_markdown.compile)(html, { runtime });
|
|
161
171
|
};
|
|
162
172
|
if (prop === Symbol.toPrimitive) return () => {
|
|
163
173
|
if (!components || typeof components === "object" && Object.keys(components).length === 0) return String(html);
|
|
164
174
|
const htmlRuntime = _markdownInstall?.htmlRuntime;
|
|
165
175
|
if (!htmlRuntime || !_intlayer_core_markdown.compile) return String(html);
|
|
166
|
-
|
|
176
|
+
const runtime = createRuntimeWithOverides(htmlRuntime, components);
|
|
177
|
+
return (0, _intlayer_core_markdown.compile)(html, { runtime });
|
|
167
178
|
};
|
|
168
179
|
if (prop === "use") return (userComponents) => {
|
|
169
180
|
const mergedComponents = {
|
|
@@ -180,10 +191,12 @@ const htmlPlugin = process.env.INTLAYER_NODE_TYPE_HTML === "false" ? _intlayer_c
|
|
|
180
191
|
const insertionPlugin = process.env.INTLAYER_NODE_TYPE_INSERTION === "false" ? _intlayer_core_interpreter.fallbackPlugin : {
|
|
181
192
|
id: "insertion-plugin",
|
|
182
193
|
canHandle: (node) => typeof node === "object" && node?.nodeType === _intlayer_types_nodeType.INSERTION,
|
|
183
|
-
transform: (node, props) => {
|
|
194
|
+
transform: (node, props, deepTransformNode) => {
|
|
184
195
|
const { plugins, ...rest } = props;
|
|
196
|
+
const content = node[_intlayer_types_nodeType.INSERTION];
|
|
197
|
+
if ((0, _intlayer_core_interpreter.isInterpolableWrapperNode)(content)) return (args = {}) => (0, _intlayer_core_interpreter.transformInterpolableNode)(content, args, props, props.plugins, deepTransformNode);
|
|
185
198
|
const render = (args = {}) => {
|
|
186
|
-
let text =
|
|
199
|
+
let text = content;
|
|
187
200
|
if (args) Object.entries(args).forEach(([key, value]) => {
|
|
188
201
|
text = text.replace(new RegExp(`{{\\s*${key}\\s*}}`, "g"), String(value));
|
|
189
202
|
});
|
package/dist/cjs/plugins.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"plugins.cjs","names":["renderIntlayerNode","editor","ContentSelectorWrapperComponent","fallbackPlugin","compile","NodeTypes","internationalization","enumerationPlugin","conditionPlugin","filePlugin","genderPlugin"],"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 nestedPlugin,\n type Plugins,\n pluralPlugin,\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 { 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 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 * 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) => {\n const { plugins, ...rest } = props;\n\n // Return a function that performs the interpolation\n const render = (args: Record<string, string | number> = {}) => {\n let text = node[NodeTypes.INSERTION] 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 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","compile","NodeTypes","internationalization","enumerationPlugin","conditionPlugin","filePlugin","genderPlugin"],"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 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 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 +1 @@
|
|
|
1
|
-
{"version":3,"file":"renderIntlayerNode.cjs","names":[],"sources":["../../src/renderIntlayerNode.ts"],"sourcesContent":["import type { ResolvedEditor } from '@intlayer/types/module_augmentation';\n\nexport type IntlayerNode<T = string, AdditionalProps = {}> = ResolvedEditor<\n T,\n any\n> & {\n value: T;\n} & AdditionalProps &\n T;\n\ntype RenderIntlayerNodeProps<T> = {\n value: T;\n children: any;\n additionalProps?: { [key: string]: any };\n};\n\nexport const renderIntlayerNode = <\n T, // Broadened to support arrays, numbers, objects, etc.\n>({\n children,\n value,\n additionalProps = {},\n}: RenderIntlayerNodeProps<T>): IntlayerNode<T> => {\n // If children is null or undefined, return a simple object with the value\n if (children == null) {\n return new Proxy({} as any, {\n get(target, prop, receiver) {\n if (prop === 'value') return value;\n if (prop === Symbol.toPrimitive) return () => value ?? '';\n if (prop === 'toString') return () => String(value ?? '');\n if (prop === 'valueOf') return () => value;\n\n // Additional Props take precedence\n if (additionalProps && prop in additionalProps) {\n return additionalProps[prop as keyof typeof additionalProps];\n }\n\n // Delegate native methods/properties to the underlying value\n if (\n value !== null &&\n value !== undefined &&\n typeof prop === 'string' &&\n prop !== 'constructor' &&\n !(prop in target)\n ) {\n const valObj = Object(value); // Safely boxes primitives (e.g., 50 -> Number object)\n if (prop in valObj) {\n const valProp = valObj[prop];\n return typeof valProp === 'function'\n ? valProp.bind(value)\n : valProp;\n }\n }\n\n return Reflect.get(target, prop, receiver);\n },\n }) as IntlayerNode<T>;\n }\n\n // Proxy target must be an object or function; wrap primitives\n const target =\n typeof children === 'object' || typeof children === 'function'\n ? children\n : ({} as any);\n\n // Return a Proxy that pretends to be the original content\n // but also has a .value getter and additional props.\n return new Proxy(target, {\n apply(target, thisArg, argumentsList) {\n if (typeof value === 'function') {\n return Reflect.apply(value as Function, thisArg, argumentsList);\n }\n return Reflect.apply(target as Function, thisArg, argumentsList);\n },\n get(target, prop, receiver) {\n if (prop === 'value') return value;\n if (prop === Symbol.toPrimitive) return () => value ?? '';\n if (prop === 'toString') return () => String(value ?? '');\n if (prop === 'valueOf') return () => value;\n\n // Additional Props take precedence\n if (additionalProps && prop in additionalProps) {\n return additionalProps[prop as keyof typeof additionalProps];\n }\n\n // Delegate native methods/properties to the underlying value\n if (\n value !== null &&\n value !== undefined &&\n typeof prop === 'string' &&\n prop !== 'constructor' &&\n !(prop in target)\n ) {\n const valObj = Object(value); // Safely boxes primitives (e.g., 50 -> Number object)\n if (prop in valObj) {\n const valProp = valObj[prop];\n return typeof valProp === 'function' ? valProp.bind(value) : valProp;\n }\n }\n\n return Reflect.get(target, prop, receiver);\n },\n }) as IntlayerNode<T>;\n};\n"],"mappings":";;;AAgBA,MAAa,sBAEX,EACA,UACA,OACA,kBAAkB,
|
|
1
|
+
{"version":3,"file":"renderIntlayerNode.cjs","names":[],"sources":["../../src/renderIntlayerNode.ts"],"sourcesContent":["import type { ResolvedEditor } from '@intlayer/types/module_augmentation';\n\nexport type IntlayerNode<T = string, AdditionalProps = {}> = ResolvedEditor<\n T,\n any\n> & {\n value: T;\n} & AdditionalProps &\n T;\n\ntype RenderIntlayerNodeProps<T> = {\n value: T;\n children: any;\n additionalProps?: { [key: string]: any };\n};\n\nexport const renderIntlayerNode = <\n T, // Broadened to support arrays, numbers, objects, etc.\n>({\n children,\n value,\n additionalProps = {},\n}: RenderIntlayerNodeProps<T>): IntlayerNode<T> => {\n // If children is null or undefined, return a simple object with the value\n if (children == null) {\n return new Proxy({} as any, {\n get(target, prop, receiver) {\n if (prop === 'value') return value;\n if (prop === Symbol.toPrimitive) return () => value ?? '';\n if (prop === 'toString') return () => String(value ?? '');\n if (prop === 'valueOf') return () => value;\n\n // Additional Props take precedence\n if (additionalProps && prop in additionalProps) {\n return additionalProps[prop as keyof typeof additionalProps];\n }\n\n // Delegate native methods/properties to the underlying value\n if (\n value !== null &&\n value !== undefined &&\n typeof prop === 'string' &&\n prop !== 'constructor' &&\n !(prop in target)\n ) {\n const valObj = Object(value); // Safely boxes primitives (e.g., 50 -> Number object)\n if (prop in valObj) {\n const valProp = valObj[prop];\n return typeof valProp === 'function'\n ? valProp.bind(value)\n : valProp;\n }\n }\n\n return Reflect.get(target, prop, receiver);\n },\n }) as IntlayerNode<T>;\n }\n\n // Proxy target must be an object or function; wrap primitives\n const target =\n typeof children === 'object' || typeof children === 'function'\n ? children\n : ({} as any);\n\n // Return a Proxy that pretends to be the original content\n // but also has a .value getter and additional props.\n return new Proxy(target, {\n apply(target, thisArg, argumentsList) {\n if (typeof value === 'function') {\n return Reflect.apply(value as Function, thisArg, argumentsList);\n }\n return Reflect.apply(target as Function, thisArg, argumentsList);\n },\n get(target, prop, receiver) {\n if (prop === 'value') return value;\n if (prop === Symbol.toPrimitive) return () => value ?? '';\n if (prop === 'toString') return () => String(value ?? '');\n if (prop === 'valueOf') return () => value;\n\n // Additional Props take precedence\n if (additionalProps && prop in additionalProps) {\n return additionalProps[prop as keyof typeof additionalProps];\n }\n\n // Delegate native methods/properties to the underlying value\n if (\n value !== null &&\n value !== undefined &&\n typeof prop === 'string' &&\n prop !== 'constructor' &&\n !(prop in target)\n ) {\n const valObj = Object(value); // Safely boxes primitives (e.g., 50 -> Number object)\n if (prop in valObj) {\n const valProp = valObj[prop];\n return typeof valProp === 'function' ? valProp.bind(value) : valProp;\n }\n }\n\n return Reflect.get(target, prop, receiver);\n },\n }) as IntlayerNode<T>;\n};\n"],"mappings":";;;AAgBA,MAAa,sBAEX,EACA,UACA,OACA,kBAAkB,CAAC,QAC8B;CAEjD,IAAI,YAAY,MACd,OAAO,IAAI,MAAM,CAAC,GAAU,EAC1B,IAAI,QAAQ,MAAM,UAAU;EAC1B,IAAI,SAAS,SAAS,OAAO;EAC7B,IAAI,SAAS,OAAO,aAAa,aAAa,SAAS;EACvD,IAAI,SAAS,YAAY,aAAa,OAAO,SAAS,EAAE;EACxD,IAAI,SAAS,WAAW,aAAa;EAGrC,IAAI,mBAAmB,QAAQ,iBAC7B,OAAO,gBAAgB;EAIzB,IACE,UAAU,QACV,UAAU,UACV,OAAO,SAAS,YAChB,SAAS,iBACT,EAAE,QAAQ,SACV;GACA,MAAM,SAAS,OAAO,KAAK;GAC3B,IAAI,QAAQ,QAAQ;IAClB,MAAM,UAAU,OAAO;IACvB,OAAO,OAAO,YAAY,aACtB,QAAQ,KAAK,KAAK,IAClB;GACN;EACF;EAEA,OAAO,QAAQ,IAAI,QAAQ,MAAM,QAAQ;CAC3C,EACF,CAAC;CAWH,OAAO,IAAI,MANT,OAAO,aAAa,YAAY,OAAO,aAAa,aAChD,WACC,CAAC,GAIiB;EACvB,MAAM,QAAQ,SAAS,eAAe;GACpC,IAAI,OAAO,UAAU,YACnB,OAAO,QAAQ,MAAM,OAAmB,SAAS,aAAa;GAEhE,OAAO,QAAQ,MAAM,QAAoB,SAAS,aAAa;EACjE;EACA,IAAI,QAAQ,MAAM,UAAU;GAC1B,IAAI,SAAS,SAAS,OAAO;GAC7B,IAAI,SAAS,OAAO,aAAa,aAAa,SAAS;GACvD,IAAI,SAAS,YAAY,aAAa,OAAO,SAAS,EAAE;GACxD,IAAI,SAAS,WAAW,aAAa;GAGrC,IAAI,mBAAmB,QAAQ,iBAC7B,OAAO,gBAAgB;GAIzB,IACE,UAAU,QACV,UAAU,UACV,OAAO,SAAS,YAChB,SAAS,iBACT,EAAE,QAAQ,SACV;IACA,MAAM,SAAS,OAAO,KAAK;IAC3B,IAAI,QAAQ,QAAQ;KAClB,MAAM,UAAU,OAAO;KACvB,OAAO,OAAO,YAAY,aAAa,QAAQ,KAAK,KAAK,IAAI;IAC/D;GACF;GAEA,OAAO,QAAQ,IAAI,QAAQ,MAAM,QAAQ;EAC3C;CACF,CAAC;AACH"}
|
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
2
|
-
const require_runtime = require('../_virtual/_rolldown/runtime.cjs');
|
|
3
|
-
let node_module = require("node:module");
|
|
4
2
|
let node_path = require("node:path");
|
|
5
3
|
let _intlayer_config_node = require("@intlayer/config/node");
|
|
6
4
|
let _intlayer_config_utils = require("@intlayer/config/utils");
|
|
5
|
+
let node_module = require("node:module");
|
|
7
6
|
let _intlayer_webpack = require("@intlayer/webpack");
|
|
8
7
|
let defu = require("defu");
|
|
9
8
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mergeConfig.cjs","names":["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":"
|
|
1
|
+
{"version":3,"file":"mergeConfig.cjs","names":["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,sFAAuC;AAC1E,MAAa,eACX,eACoC;CACpC,MAAM,6DAAkC;CAoDxC,sBAAY;EAjDV,SAAS,EACP,4CAAgB;GACd,eAAe;GACf,YAAY,iCAA0B,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,IAAIA,iCAAe,cAAc,CAAC;CAG7B,GAAG,UAAU;AAChC"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import
|
|
2
|
-
import
|
|
1
|
+
import __decorateMetadata from "../_virtual/_@oxc-project_runtime@0.140.0/helpers/esm/decorateMetadata.mjs";
|
|
2
|
+
import __decorate from "../_virtual/_@oxc-project_runtime@0.140.0/helpers/esm/decorate.mjs";
|
|
3
3
|
import { ChangeDetectorRef, Component, ElementRef, Input, ViewContainerRef, inject } from "@angular/core";
|
|
4
4
|
|
|
5
5
|
//#region src/UI/IntlayerNode.component.ts
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"IntlayerNode.component.mjs","names":[],"sources":["../../../src/UI/IntlayerNode.component.ts"],"sourcesContent":["import {\n ChangeDetectorRef,\n Component,\n ElementRef,\n Input,\n inject,\n type OnChanges,\n type SimpleChanges,\n type Type,\n ViewContainerRef,\n} from '@angular/core';\n\n/**\n * A transparent host element that renders Intlayer content nodes.\n *\n * `display: contents` makes the `<intlayer-node>` element invisible in the\n * layout — its children appear as if they were direct children of the parent,\n * so placing this component inside `<h1>`, `<p>`, etc. does not break the\n * document structure.\n *\n * ### Usage\n * ```html\n * <h1><intlayer-node [node]=\"content().title\"></intlayer-node></h1>\n * ```\n */\n@Component({\n selector: 'intlayer-node',\n standalone: true,\n // The ng-content slot is the anchor point for ViewContainerRef.\n // Wrapping text renders directly inside this host thanks to display:contents.\n template: `<ng-container #anchor></ng-container>`,\n // display:contents collapses the host box so it is layout-transparent.\n styles: [`:host { display: contents; }`],\n})\nexport class IntlayerNodeComponent implements OnChanges {\n @Input() node: any;\n\n private vcr = inject(ViewContainerRef);\n private elRef = inject<ElementRef<HTMLElement>>(ElementRef);\n private cdr = inject(ChangeDetectorRef);\n\n ngOnChanges(changes: SimpleChanges): void {\n if (changes['node']) {\n this.render();\n }\n }\n\n private render() {\n // Clear previously created views / text nodes\n this.vcr.clear();\n const host = this.elRef.nativeElement;\n // Remove any raw text nodes we injected directly on previous renders\n host.childNodes.forEach((n) => {\n if (n.nodeType === Node.TEXT_NODE) n.parentNode?.removeChild(n);\n });\n\n if (!this.node) return;\n\n // The node returned by the Angular plugin is a Proxy whose `.children`\n // property is a function returning component info (editor on) or the raw\n // value (editor off).\n const nodeInfo =\n typeof this.node?.children === 'function'\n ? this.node.children()\n : this.node;\n\n if (nodeInfo?.component && typeof nodeInfo.component !== 'string') {\n // ── Editor enabled path: create the ContentSelectorWrapper component ──\n const componentRef = this.vcr.createComponent(\n nodeInfo.component as Type<any>\n );\n\n if (nodeInfo.props) {\n for (const [key, value] of Object.entries(nodeInfo.props)) {\n (componentRef.instance as any)[key] = value;\n }\n }\n\n if (nodeInfo.children) {\n const content = nodeInfo.children;\n if (typeof content === 'string' || typeof content === 'number') {\n componentRef.location.nativeElement.appendChild(\n document.createTextNode(String(content))\n );\n }\n }\n\n this.cdr.markForCheck();\n } else {\n // ── Editor disabled path: render plain text inside the host ──────────\n const text =\n this.node?.value ?? this.node?.toString?.() ?? String(this.node);\n // Append a text node directly inside the host element.\n // Because the host has `display: contents`, this text is layout-wise a\n // direct child of the surrounding element (e.g. <h1>).\n host.appendChild(document.createTextNode(text));\n }\n }\n}\n"],"mappings":";;;;;AAkCO,
|
|
1
|
+
{"version":3,"file":"IntlayerNode.component.mjs","names":[],"sources":["../../../src/UI/IntlayerNode.component.ts"],"sourcesContent":["import {\n ChangeDetectorRef,\n Component,\n ElementRef,\n Input,\n inject,\n type OnChanges,\n type SimpleChanges,\n type Type,\n ViewContainerRef,\n} from '@angular/core';\n\n/**\n * A transparent host element that renders Intlayer content nodes.\n *\n * `display: contents` makes the `<intlayer-node>` element invisible in the\n * layout — its children appear as if they were direct children of the parent,\n * so placing this component inside `<h1>`, `<p>`, etc. does not break the\n * document structure.\n *\n * ### Usage\n * ```html\n * <h1><intlayer-node [node]=\"content().title\"></intlayer-node></h1>\n * ```\n */\n@Component({\n selector: 'intlayer-node',\n standalone: true,\n // The ng-content slot is the anchor point for ViewContainerRef.\n // Wrapping text renders directly inside this host thanks to display:contents.\n template: `<ng-container #anchor></ng-container>`,\n // display:contents collapses the host box so it is layout-transparent.\n styles: [`:host { display: contents; }`],\n})\nexport class IntlayerNodeComponent implements OnChanges {\n @Input() node: any;\n\n private vcr = inject(ViewContainerRef);\n private elRef = inject<ElementRef<HTMLElement>>(ElementRef);\n private cdr = inject(ChangeDetectorRef);\n\n ngOnChanges(changes: SimpleChanges): void {\n if (changes['node']) {\n this.render();\n }\n }\n\n private render() {\n // Clear previously created views / text nodes\n this.vcr.clear();\n const host = this.elRef.nativeElement;\n // Remove any raw text nodes we injected directly on previous renders\n host.childNodes.forEach((n) => {\n if (n.nodeType === Node.TEXT_NODE) n.parentNode?.removeChild(n);\n });\n\n if (!this.node) return;\n\n // The node returned by the Angular plugin is a Proxy whose `.children`\n // property is a function returning component info (editor on) or the raw\n // value (editor off).\n const nodeInfo =\n typeof this.node?.children === 'function'\n ? this.node.children()\n : this.node;\n\n if (nodeInfo?.component && typeof nodeInfo.component !== 'string') {\n // ── Editor enabled path: create the ContentSelectorWrapper component ──\n const componentRef = this.vcr.createComponent(\n nodeInfo.component as Type<any>\n );\n\n if (nodeInfo.props) {\n for (const [key, value] of Object.entries(nodeInfo.props)) {\n (componentRef.instance as any)[key] = value;\n }\n }\n\n if (nodeInfo.children) {\n const content = nodeInfo.children;\n if (typeof content === 'string' || typeof content === 'number') {\n componentRef.location.nativeElement.appendChild(\n document.createTextNode(String(content))\n );\n }\n }\n\n this.cdr.markForCheck();\n } else {\n // ── Editor disabled path: render plain text inside the host ──────────\n const text =\n this.node?.value ?? this.node?.toString?.() ?? String(this.node);\n // Append a text node directly inside the host element.\n // Because the host has `display: contents`, this text is layout-wise a\n // direct child of the surrounding element (e.g. <h1>).\n host.appendChild(document.createTextNode(text));\n }\n }\n}\n"],"mappings":";;;;;AAkCO,IAAM,wBAAN,MAAM,sBAA2C;CACtD,AAAS;CAET,AAAQ,MAAM,OAAO,gBAAgB;CACrC,AAAQ,QAAQ,OAAgC,UAAU;CAC1D,AAAQ,MAAM,OAAO,iBAAiB;CAEtC,YAAY,SAA8B;EACxC,IAAI,QAAQ,SACV,KAAK,OAAO;CAEhB;CAEA,AAAQ,SAAS;EAEf,KAAK,IAAI,MAAM;EACf,MAAM,OAAO,KAAK,MAAM;EAExB,KAAK,WAAW,SAAS,MAAM;GAC7B,IAAI,EAAE,aAAa,KAAK,WAAW,EAAE,YAAY,YAAY,CAAC;EAChE,CAAC;EAED,IAAI,CAAC,KAAK,MAAM;EAKhB,MAAM,WACJ,OAAO,KAAK,MAAM,aAAa,aAC3B,KAAK,KAAK,SAAS,IACnB,KAAK;EAEX,IAAI,UAAU,aAAa,OAAO,SAAS,cAAc,UAAU;GAEjE,MAAM,eAAe,KAAK,IAAI,gBAC5B,SAAS,SACX;GAEA,IAAI,SAAS,OACX,KAAK,MAAM,CAAC,KAAK,UAAU,OAAO,QAAQ,SAAS,KAAK,GACtD,AAAC,aAAa,SAAiB,OAAO;GAI1C,IAAI,SAAS,UAAU;IACrB,MAAM,UAAU,SAAS;IACzB,IAAI,OAAO,YAAY,YAAY,OAAO,YAAY,UACpD,aAAa,SAAS,cAAc,YAClC,SAAS,eAAe,OAAO,OAAO,CAAC,CACzC;GAEJ;GAEA,KAAK,IAAI,aAAa;EACxB,OAAO;GAEL,MAAM,OACJ,KAAK,MAAM,SAAS,KAAK,MAAM,WAAW,KAAK,OAAO,KAAK,IAAI;GAIjE,KAAK,YAAY,SAAS,eAAe,IAAI,CAAC;EAChD;CACF;AACF;YA/DG,MAAM;oCAVR,UAAU;CACT,UAAU;CACV,YAAY;CAGZ,UAAU;CAEV,QAAQ,CAAC,8BAA8B;AACzC,CAAC"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
//#region \0@oxc-project+runtime@0.
|
|
1
|
+
//#region \0@oxc-project+runtime@0.140.0/helpers/esm/decorate.js
|
|
2
2
|
function __decorate(decorators, target, key, desc) {
|
|
3
3
|
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
4
4
|
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
@@ -7,4 +7,4 @@ function __decorate(decorators, target, key, desc) {
|
|
|
7
7
|
}
|
|
8
8
|
|
|
9
9
|
//#endregion
|
|
10
|
-
export { __decorate };
|
|
10
|
+
export { __decorate as default };
|
|
@@ -1,8 +1,7 @@
|
|
|
1
|
-
|
|
2
|
-
//#region \0@oxc-project+runtime@0.127.0/helpers/decorateMetadata.js
|
|
1
|
+
//#region \0@oxc-project+runtime@0.140.0/helpers/esm/decorateMetadata.js
|
|
3
2
|
function __decorateMetadata(k, v) {
|
|
4
3
|
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
5
4
|
}
|
|
6
5
|
|
|
7
6
|
//#endregion
|
|
8
|
-
|
|
7
|
+
export { __decorateMetadata as default };
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
//#region src/analytics/exposureSink.ts
|
|
2
|
+
let sink = null;
|
|
3
|
+
/**
|
|
4
|
+
* Installs (or clears) the exposure sink. `useAnalytics` sets this once the
|
|
5
|
+
* analytics client has loaded, and clears it on unmount.
|
|
6
|
+
*
|
|
7
|
+
* @param next - The sink to install, or `null` to clear.
|
|
8
|
+
*/
|
|
9
|
+
const setExposureSink = (next) => {
|
|
10
|
+
sink = next;
|
|
11
|
+
};
|
|
12
|
+
/**
|
|
13
|
+
* Forwards a content exposure to the installed sink. A cheap null-check when
|
|
14
|
+
* analytics is not running, so it is safe to call from every node resolution.
|
|
15
|
+
*
|
|
16
|
+
* @param input - The node metadata to report.
|
|
17
|
+
*/
|
|
18
|
+
const reportExposure = (input) => {
|
|
19
|
+
sink?.(input);
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
//#endregion
|
|
23
|
+
export { reportExposure, setExposureSink };
|
|
24
|
+
//# sourceMappingURL=exposureSink.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"exposureSink.mjs","names":[],"sources":["../../../src/analytics/exposureSink.ts"],"sourcesContent":["import type { KeyPath } from '@intlayer/types/keyPath';\n\n/**\n * Node metadata reported for a content exposure. Kept dependency-free (types\n * only) so the interpreter hot path in `plugins.ts` never statically imports\n * `@intlayer/analytics` — the package stays optional and tree-shakeable.\n */\nexport type ExposureInput = {\n dictionaryKey: string;\n keyPath: KeyPath[];\n locale?: string;\n nodeType?: string;\n};\n\n/** Consumer of exposure reports, installed by `useAnalytics` after init. */\nexport type ExposureSink = (input: ExposureInput) => void;\n\nlet sink: ExposureSink | null = null;\n\n/**\n * Installs (or clears) the exposure sink. `useAnalytics` sets this once the\n * analytics client has loaded, and clears it on unmount.\n *\n * @param next - The sink to install, or `null` to clear.\n */\nexport const setExposureSink = (next: ExposureSink | null): void => {\n sink = next;\n};\n\n/**\n * Forwards a content exposure to the installed sink. A cheap null-check when\n * analytics is not running, so it is safe to call from every node resolution.\n *\n * @param input - The node metadata to report.\n */\nexport const reportExposure = (input: ExposureInput): void => {\n sink?.(input);\n};\n"],"mappings":";AAiBA,IAAI,OAA4B;;;;;;;AAQhC,MAAa,mBAAmB,SAAoC;CAClE,OAAO;AACT;;;;;;;AAQA,MAAa,kBAAkB,UAA+B;CAC5D,OAAO,KAAK;AACd"}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import { setExposureSink } from "./exposureSink.mjs";
|
|
2
|
+
import { INTLAYER_TOKEN } from "../client/intlayerToken.mjs";
|
|
3
|
+
import { DestroyRef, Injector, effect, inject, provideAppInitializer, runInInjectionContext, signal } from "@angular/core";
|
|
4
|
+
import { isEnabled } from "@intlayer/analytics/isEnabled";
|
|
5
|
+
|
|
6
|
+
//#region src/analytics/useAnalytics.ts
|
|
7
|
+
/**
|
|
8
|
+
* Initializes the Intlayer analytics client singleton when analytics is
|
|
9
|
+
* enabled (mirrors {@link useEditor}). Records an initial page view, keeps the
|
|
10
|
+
* client aware of the current locale, and wires node-level content exposures.
|
|
11
|
+
*
|
|
12
|
+
* Must be called inside an Angular injection context (e.g. a component
|
|
13
|
+
* constructor, `provideAppInitializer`, or `runInInjectionContext`).
|
|
14
|
+
*
|
|
15
|
+
* @param client - The IntlayerProvider instance to sync locale from.
|
|
16
|
+
* When omitted the function injects `INTLAYER_TOKEN` from the DI tree,
|
|
17
|
+
* so it still works when called directly from a component.
|
|
18
|
+
*/
|
|
19
|
+
const useAnalytics = (client) => {
|
|
20
|
+
if (process.env.INTLAYER_ANALYTICS_ENABLED === "false" || !isEnabled) return;
|
|
21
|
+
const destroyRef = inject(DestroyRef, { optional: true });
|
|
22
|
+
const injector = inject(Injector);
|
|
23
|
+
const resolvedClient = client ?? inject(INTLAYER_TOKEN, { optional: true });
|
|
24
|
+
const analyticsClient = signal(null);
|
|
25
|
+
let stopped = false;
|
|
26
|
+
let initialized = false;
|
|
27
|
+
import("@intlayer/analytics").then(({ initAnalyticsClient, buildContentExposure }) => {
|
|
28
|
+
if (stopped) return;
|
|
29
|
+
const clientInstance = initAnalyticsClient();
|
|
30
|
+
initialized = true;
|
|
31
|
+
const currentLocale = resolvedClient?.locale();
|
|
32
|
+
if (currentLocale) clientInstance.setLocale(currentLocale);
|
|
33
|
+
clientInstance.trackPageView({ reason: "initial" });
|
|
34
|
+
setExposureSink((input) => clientInstance.trackContentExposure(buildContentExposure(input)));
|
|
35
|
+
analyticsClient.set(clientInstance);
|
|
36
|
+
}).catch(() => {});
|
|
37
|
+
let previousLocale;
|
|
38
|
+
const effectRef = runInInjectionContext(injector, () => effect(() => {
|
|
39
|
+
const clientInstance = analyticsClient();
|
|
40
|
+
const locale = resolvedClient?.locale();
|
|
41
|
+
if (!clientInstance || !locale) return;
|
|
42
|
+
if (previousLocale === void 0) {
|
|
43
|
+
previousLocale = locale;
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
46
|
+
if (previousLocale === locale) return;
|
|
47
|
+
previousLocale = locale;
|
|
48
|
+
clientInstance.setLocale(locale);
|
|
49
|
+
clientInstance.trackPageView({ reason: "locale_change" });
|
|
50
|
+
}));
|
|
51
|
+
destroyRef?.onDestroy(() => {
|
|
52
|
+
stopped = true;
|
|
53
|
+
effectRef.destroy();
|
|
54
|
+
analyticsClient.set(null);
|
|
55
|
+
setExposureSink(null);
|
|
56
|
+
import("@intlayer/analytics").then(({ stopAnalyticsClient }) => {
|
|
57
|
+
if (initialized) stopAnalyticsClient();
|
|
58
|
+
}).catch(() => {});
|
|
59
|
+
});
|
|
60
|
+
};
|
|
61
|
+
/**
|
|
62
|
+
* Angular provider that wires `useAnalytics` into the application
|
|
63
|
+
* initialisation phase via `provideAppInitializer`.
|
|
64
|
+
*
|
|
65
|
+
* `provideIntlayer()` already calls this internally, so you only need this
|
|
66
|
+
* function when you want to manage providers individually.
|
|
67
|
+
*
|
|
68
|
+
* @example
|
|
69
|
+
* ```ts
|
|
70
|
+
* // app.config.ts
|
|
71
|
+
* import { provideIntlayer, provideIntlayerAnalytics } from 'angular-intlayer';
|
|
72
|
+
*
|
|
73
|
+
* export const appConfig: ApplicationConfig = {
|
|
74
|
+
* providers: [provideIntlayer(), provideIntlayerAnalytics()],
|
|
75
|
+
* };
|
|
76
|
+
* ```
|
|
77
|
+
*/
|
|
78
|
+
const provideIntlayerAnalytics = (client) => provideAppInitializer(() => useAnalytics(client));
|
|
79
|
+
|
|
80
|
+
//#endregion
|
|
81
|
+
export { provideIntlayerAnalytics, useAnalytics };
|
|
82
|
+
//# sourceMappingURL=useAnalytics.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useAnalytics.mjs","names":[],"sources":["../../../src/analytics/useAnalytics.ts"],"sourcesContent":["import {\n DestroyRef,\n effect,\n Injector,\n inject,\n provideAppInitializer,\n runInInjectionContext,\n signal,\n} from '@angular/core';\nimport type { AnalyticsClient } from '@intlayer/analytics';\nimport { isEnabled } from '@intlayer/analytics/isEnabled';\n// Import from the standalone token file to avoid a circular dependency:\n// installIntlayer.ts → useAnalytics.ts → ../client → installIntlayer.ts\nimport { INTLAYER_TOKEN, type IntlayerProvider } from '../client/intlayerToken';\nimport { setExposureSink } from './exposureSink';\n\n/**\n * Initializes the Intlayer analytics client singleton when analytics is\n * enabled (mirrors {@link useEditor}). Records an initial page view, keeps the\n * client aware of the current locale, and wires node-level content exposures.\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 useAnalytics = (client?: IntlayerProvider | null): void => {\n if (process.env.INTLAYER_ANALYTICS_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 // `analyticsClient` signal is set once the async import resolves.\n // Using a signal lets an `effect()` react to it becoming available.\n const analyticsClient = signal<AnalyticsClient | null>(null);\n\n // Guard: prevents the async callback from acting after the view is destroyed.\n let stopped = false;\n // Tracks whether initAnalyticsClient actually ran, so teardown never calls\n // stopAnalyticsClient for an init that was cancelled — that would decrement\n // the shared reference count once too many.\n let initialized = false;\n\n import('@intlayer/analytics')\n .then(({ initAnalyticsClient, buildContentExposure }) => {\n if (stopped) return;\n\n const clientInstance = initAnalyticsClient();\n initialized = true;\n\n const currentLocale = resolvedClient?.locale();\n if (currentLocale) clientInstance.setLocale(currentLocale);\n clientInstance.trackPageView({ reason: 'initial' });\n\n // Route node-level exposures (from the interpreter plugins) into the\n // client. Serialization happens here, off the hot render path.\n setExposureSink((input) =>\n clientInstance.trackContentExposure(buildContentExposure(input))\n );\n\n analyticsClient.set(clientInstance);\n })\n .catch(() => {\n /* chunk failed to load — analytics stays a no-op */\n });\n\n // Locale switches are a real signal — record them as page views.\n let previousLocale: string | undefined;\n const effectRef = runInInjectionContext(injector, () =>\n effect(() => {\n const clientInstance = analyticsClient();\n const locale = resolvedClient?.locale();\n\n if (!clientInstance || !locale) return;\n\n if (previousLocale === undefined) {\n // First run after init — the initial page view already covered it.\n previousLocale = locale;\n return;\n }\n if (previousLocale === locale) return;\n\n previousLocale = locale;\n clientInstance.setLocale(locale);\n clientInstance.trackPageView({ reason: 'locale_change' });\n })\n );\n\n // Tear down on destroy\n destroyRef?.onDestroy(() => {\n stopped = true;\n effectRef.destroy();\n analyticsClient.set(null);\n setExposureSink(null);\n import('@intlayer/analytics')\n .then(({ stopAnalyticsClient }) => {\n if (initialized) stopAnalyticsClient();\n })\n .catch(() => {});\n });\n};\n\n/**\n * Angular provider that wires `useAnalytics` into the application\n * initialisation 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, provideIntlayerAnalytics } from 'angular-intlayer';\n *\n * export const appConfig: ApplicationConfig = {\n * providers: [provideIntlayer(), provideIntlayerAnalytics()],\n * };\n * ```\n */\nexport const provideIntlayerAnalytics = (client?: IntlayerProvider | null) =>\n provideAppInitializer(() => useAnalytics(client));\n"],"mappings":";;;;;;;;;;;;;;;;;;AA4BA,MAAa,gBAAgB,WAA2C;CACtE,IAAI,QAAQ,IAAI,+BAA+B,WAAW,CAAC,WAAW;CAEtE,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,kBAAkB,OAA+B,IAAI;CAG3D,IAAI,UAAU;CAId,IAAI,cAAc;CAElB,OAAO,sBAAsB,CAC1B,MAAM,EAAE,qBAAqB,2BAA2B;EACvD,IAAI,SAAS;EAEb,MAAM,iBAAiB,oBAAoB;EAC3C,cAAc;EAEd,MAAM,gBAAgB,gBAAgB,OAAO;EAC7C,IAAI,eAAe,eAAe,UAAU,aAAa;EACzD,eAAe,cAAc,EAAE,QAAQ,UAAU,CAAC;EAIlD,iBAAiB,UACf,eAAe,qBAAqB,qBAAqB,KAAK,CAAC,CACjE;EAEA,gBAAgB,IAAI,cAAc;CACpC,CAAC,CAAC,CACD,YAAY,CAEb,CAAC;CAGH,IAAI;CACJ,MAAM,YAAY,sBAAsB,gBACtC,aAAa;EACX,MAAM,iBAAiB,gBAAgB;EACvC,MAAM,SAAS,gBAAgB,OAAO;EAEtC,IAAI,CAAC,kBAAkB,CAAC,QAAQ;EAEhC,IAAI,mBAAmB,QAAW;GAEhC,iBAAiB;GACjB;EACF;EACA,IAAI,mBAAmB,QAAQ;EAE/B,iBAAiB;EACjB,eAAe,UAAU,MAAM;EAC/B,eAAe,cAAc,EAAE,QAAQ,gBAAgB,CAAC;CAC1D,CAAC,CACH;CAGA,YAAY,gBAAgB;EAC1B,UAAU;EACV,UAAU,QAAQ;EAClB,gBAAgB,IAAI,IAAI;EACxB,gBAAgB,IAAI;EACpB,OAAO,sBAAsB,CAC1B,MAAM,EAAE,0BAA0B;GACjC,IAAI,aAAa,oBAAoB;EACvC,CAAC,CAAC,CACD,YAAY,CAAC,CAAC;CACnB,CAAC;AACH;;;;;;;;;;;;;;;;;;AAmBA,MAAa,4BAA4B,WACvC,4BAA4B,aAAa,MAAM,CAAC"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { isEnabled } from "@intlayer/analytics/isEnabled";
|
|
2
|
+
|
|
3
|
+
//#region src/analytics/useConversion.ts
|
|
4
|
+
/**
|
|
5
|
+
* Returns a `trackConversion` callback for content A/B testing. Safe to call
|
|
6
|
+
* from any component: it resolves to a no-op when analytics is disabled or the
|
|
7
|
+
* client has not been initialized yet.
|
|
8
|
+
*
|
|
9
|
+
* @example
|
|
10
|
+
* ```ts
|
|
11
|
+
* export class CtaComponent {
|
|
12
|
+
* trackConversion = useConversion();
|
|
13
|
+
*
|
|
14
|
+
* onClick() {
|
|
15
|
+
* this.trackConversion({
|
|
16
|
+
* experimentKey: 'homepage-hero',
|
|
17
|
+
* variant: 'b',
|
|
18
|
+
* goal: 'cta_click',
|
|
19
|
+
* });
|
|
20
|
+
* }
|
|
21
|
+
* }
|
|
22
|
+
* ```
|
|
23
|
+
*/
|
|
24
|
+
const useConversion = () => {
|
|
25
|
+
return (params) => {
|
|
26
|
+
if (process.env.INTLAYER_ANALYTICS_ENABLED === "false" || !isEnabled) return;
|
|
27
|
+
import("@intlayer/analytics").then(({ getGlobalAnalyticsClient }) => {
|
|
28
|
+
getGlobalAnalyticsClient()?.trackConversion(params);
|
|
29
|
+
}).catch(() => {});
|
|
30
|
+
};
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
//#endregion
|
|
34
|
+
export { useConversion };
|
|
35
|
+
//# sourceMappingURL=useConversion.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useConversion.mjs","names":[],"sources":["../../../src/analytics/useConversion.ts"],"sourcesContent":["import { isEnabled } from '@intlayer/analytics/isEnabled';\n\n/**\n * Parameters describing a conversion to record.\n */\nexport type ConversionParams = {\n /** The experiment this conversion is attributed to. */\n experimentKey: string;\n /** The variant the session was assigned. */\n variant: string;\n /** The goal reached (e.g. `\"signup\"`, `\"cta_click\"`). */\n goal: string;\n /** Optional numeric value (e.g. revenue). */\n value?: number;\n};\n\n/**\n * Returns a `trackConversion` callback for content A/B testing. Safe to call\n * from any component: it resolves to a no-op when analytics is disabled or the\n * client has not been initialized yet.\n *\n * @example\n * ```ts\n * export class CtaComponent {\n * trackConversion = useConversion();\n *\n * onClick() {\n * this.trackConversion({\n * experimentKey: 'homepage-hero',\n * variant: 'b',\n * goal: 'cta_click',\n * });\n * }\n * }\n * ```\n */\nexport const useConversion = () => {\n return (params: ConversionParams): void => {\n if (process.env.INTLAYER_ANALYTICS_ENABLED === 'false' || !isEnabled) {\n return;\n }\n\n import('@intlayer/analytics')\n .then(({ getGlobalAnalyticsClient }) => {\n getGlobalAnalyticsClient()?.trackConversion(params);\n })\n .catch(() => {});\n };\n};\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;AAoCA,MAAa,sBAAsB;CACjC,QAAQ,WAAmC;EACzC,IAAI,QAAQ,IAAI,+BAA+B,WAAW,CAAC,WACzD;EAGF,OAAO,sBAAsB,CAC1B,MAAM,EAAE,+BAA+B;GACtC,yBAAyB,CAAC,EAAE,gBAAgB,MAAM;EACpD,CAAC,CAAC,CACD,YAAY,CAAC,CAAC;CACnB;AACF"}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import { DestroyRef, inject, signal } from "@angular/core";
|
|
2
|
+
import { isEnabled } from "@intlayer/analytics/isEnabled";
|
|
3
|
+
|
|
4
|
+
//#region src/analytics/useExperiment.ts
|
|
5
|
+
/**
|
|
6
|
+
* Assigns this session to a variant of an A/B experiment and records the
|
|
7
|
+
* exposure, scoped to `experimentKey`, so the backend can compute per-variant
|
|
8
|
+
* conversion rates against `useConversion` events.
|
|
9
|
+
*
|
|
10
|
+
* Assignment is deterministic per session (no server round-trip, stable across
|
|
11
|
+
* re-mounts). The exposure is recorded once per call.
|
|
12
|
+
*
|
|
13
|
+
* Must be called inside an Angular injection context (e.g. a component
|
|
14
|
+
* constructor or field initializer).
|
|
15
|
+
*
|
|
16
|
+
* @param experimentKey - Unique key identifying the experiment.
|
|
17
|
+
* @param variants - The candidate variant names; the first one is the control.
|
|
18
|
+
* @param weights - Optional relative weights, one per variant (e.g. `[9, 1]`).
|
|
19
|
+
* @returns The {@link ExperimentState} for this session.
|
|
20
|
+
*
|
|
21
|
+
* @example
|
|
22
|
+
* ```ts
|
|
23
|
+
* export class HeroComponent {
|
|
24
|
+
* experiment = useExperiment('homepage-hero', ['a', 'b']);
|
|
25
|
+
* content = useIntlayer('hero');
|
|
26
|
+
* }
|
|
27
|
+
* ```
|
|
28
|
+
*/
|
|
29
|
+
const useExperiment = (experimentKey, variants, weights) => {
|
|
30
|
+
const variant = signal(variants[0] ?? "");
|
|
31
|
+
const isAssigned = signal(false);
|
|
32
|
+
if (process.env.INTLAYER_ANALYTICS_ENABLED === "false" || !isEnabled) return {
|
|
33
|
+
variant: variant.asReadonly(),
|
|
34
|
+
isAssigned: isAssigned.asReadonly()
|
|
35
|
+
};
|
|
36
|
+
const destroyRef = inject(DestroyRef, { optional: true });
|
|
37
|
+
let cancelled = false;
|
|
38
|
+
let initialized = false;
|
|
39
|
+
import("@intlayer/analytics").then(({ initAnalyticsClient }) => {
|
|
40
|
+
if (cancelled) return;
|
|
41
|
+
const client = initAnalyticsClient();
|
|
42
|
+
initialized = true;
|
|
43
|
+
const assigned = client.getVariant(experimentKey, variants, weights);
|
|
44
|
+
variant.set(assigned);
|
|
45
|
+
isAssigned.set(true);
|
|
46
|
+
client.trackContentExposure({
|
|
47
|
+
dictionaryKey: experimentKey,
|
|
48
|
+
keyPath: "",
|
|
49
|
+
nodeType: "experiment",
|
|
50
|
+
experimentKey,
|
|
51
|
+
variant: assigned
|
|
52
|
+
});
|
|
53
|
+
}).catch(() => {});
|
|
54
|
+
destroyRef?.onDestroy(() => {
|
|
55
|
+
cancelled = true;
|
|
56
|
+
import("@intlayer/analytics").then(({ stopAnalyticsClient }) => {
|
|
57
|
+
if (initialized) stopAnalyticsClient();
|
|
58
|
+
}).catch(() => {});
|
|
59
|
+
});
|
|
60
|
+
return {
|
|
61
|
+
variant: variant.asReadonly(),
|
|
62
|
+
isAssigned: isAssigned.asReadonly()
|
|
63
|
+
};
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
//#endregion
|
|
67
|
+
export { useExperiment };
|
|
68
|
+
//# sourceMappingURL=useExperiment.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useExperiment.mjs","names":[],"sources":["../../../src/analytics/useExperiment.ts"],"sourcesContent":["import { DestroyRef, inject, type Signal, signal } from '@angular/core';\nimport { isEnabled } from '@intlayer/analytics/isEnabled';\n\n/**\n * The state of an A/B experiment for the current session.\n */\nexport type ExperimentState = {\n /**\n * The variant assigned to this session. Until assignment resolves (and on\n * the server, or when analytics is disabled), this is the first variant —\n * treat the first variant as the control.\n */\n variant: Signal<string>;\n /**\n * `true` once the variant has been deterministically assigned and its\n * exposure recorded. Useful to defer rendering when a flash of the control\n * variant is not acceptable.\n */\n isAssigned: Signal<boolean>;\n};\n\n/**\n * Assigns this session to a variant of an A/B experiment and records the\n * exposure, scoped to `experimentKey`, so the backend can compute per-variant\n * conversion rates against `useConversion` events.\n *\n * Assignment is deterministic per session (no server round-trip, stable across\n * re-mounts). The exposure is recorded once per call.\n *\n * Must be called inside an Angular injection context (e.g. a component\n * constructor or field initializer).\n *\n * @param experimentKey - Unique key identifying the experiment.\n * @param variants - The candidate variant names; the first one is the control.\n * @param weights - Optional relative weights, one per variant (e.g. `[9, 1]`).\n * @returns The {@link ExperimentState} for this session.\n *\n * @example\n * ```ts\n * export class HeroComponent {\n * experiment = useExperiment('homepage-hero', ['a', 'b']);\n * content = useIntlayer('hero');\n * }\n * ```\n */\nexport const useExperiment = (\n experimentKey: string,\n variants: string[],\n weights?: number[]\n): ExperimentState => {\n const variant = signal(variants[0] ?? '');\n const isAssigned = signal(false);\n\n if (process.env.INTLAYER_ANALYTICS_ENABLED === 'false' || !isEnabled) {\n return {\n variant: variant.asReadonly(),\n isAssigned: isAssigned.asReadonly(),\n };\n }\n\n const destroyRef = inject(DestroyRef, { optional: true });\n\n let cancelled = false;\n let initialized = false;\n\n import('@intlayer/analytics')\n .then(({ initAnalyticsClient }) => {\n if (cancelled) return;\n\n // Ref-counted: guarantees a live client even when this call's import\n // resolves before the provider's. Balanced by stop on destroy.\n const client = initAnalyticsClient();\n initialized = true;\n\n const assigned = client.getVariant(experimentKey, variants, weights);\n variant.set(assigned);\n isAssigned.set(true);\n\n // Experiment-level exposure — the denominator of the conversion rate.\n client.trackContentExposure({\n dictionaryKey: experimentKey,\n keyPath: '',\n nodeType: 'experiment',\n experimentKey,\n variant: assigned,\n });\n })\n .catch(() => {\n /* chunk failed to load — control variant stays in place */\n });\n\n destroyRef?.onDestroy(() => {\n cancelled = true;\n import('@intlayer/analytics')\n .then(({ stopAnalyticsClient }) => {\n if (initialized) stopAnalyticsClient();\n })\n .catch(() => {});\n });\n\n return { variant: variant.asReadonly(), isAssigned: isAssigned.asReadonly() };\n};\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;AA6CA,MAAa,iBACX,eACA,UACA,YACoB;CACpB,MAAM,UAAU,OAAO,SAAS,MAAM,EAAE;CACxC,MAAM,aAAa,OAAO,KAAK;CAE/B,IAAI,QAAQ,IAAI,+BAA+B,WAAW,CAAC,WACzD,OAAO;EACL,SAAS,QAAQ,WAAW;EAC5B,YAAY,WAAW,WAAW;CACpC;CAGF,MAAM,aAAa,OAAO,YAAY,EAAE,UAAU,KAAK,CAAC;CAExD,IAAI,YAAY;CAChB,IAAI,cAAc;CAElB,OAAO,sBAAsB,CAC1B,MAAM,EAAE,0BAA0B;EACjC,IAAI,WAAW;EAIf,MAAM,SAAS,oBAAoB;EACnC,cAAc;EAEd,MAAM,WAAW,OAAO,WAAW,eAAe,UAAU,OAAO;EACnE,QAAQ,IAAI,QAAQ;EACpB,WAAW,IAAI,IAAI;EAGnB,OAAO,qBAAqB;GAC1B,eAAe;GACf,SAAS;GACT,UAAU;GACV;GACA,SAAS;EACX,CAAC;CACH,CAAC,CAAC,CACD,YAAY,CAEb,CAAC;CAEH,YAAY,gBAAgB;EAC1B,YAAY;EACZ,OAAO,sBAAsB,CAC1B,MAAM,EAAE,0BAA0B;GACjC,IAAI,aAAa,oBAAoB;EACvC,CAAC,CAAC,CACD,YAAY,CAAC,CAAC;CACnB,CAAC;CAED,OAAO;EAAE,SAAS,QAAQ,WAAW;EAAG,YAAY,WAAW,WAAW;CAAE;AAC9E"}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { INTLAYER_TOKEN, IntlayerProvider, createIntlayerClient } from "./intlayerToken.mjs";
|
|
2
|
+
import { provideIntlayerAnalytics } from "../analytics/useAnalytics.mjs";
|
|
2
3
|
import { provideIntlayerEditor } from "../editor/useEditor.mjs";
|
|
3
4
|
|
|
4
5
|
//#region src/client/installIntlayer.ts
|
|
@@ -27,10 +28,14 @@ import { provideIntlayerEditor } from "../editor/useEditor.mjs";
|
|
|
27
28
|
*/
|
|
28
29
|
const provideIntlayer = (locale, isCookieEnabled = true) => {
|
|
29
30
|
const client = installIntlayer(locale, isCookieEnabled);
|
|
30
|
-
return [
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
31
|
+
return [
|
|
32
|
+
{
|
|
33
|
+
provide: INTLAYER_TOKEN,
|
|
34
|
+
useValue: client
|
|
35
|
+
},
|
|
36
|
+
provideIntlayerEditor(client),
|
|
37
|
+
provideIntlayerAnalytics(client)
|
|
38
|
+
];
|
|
34
39
|
};
|
|
35
40
|
/**
|
|
36
41
|
* Helper to install the Intlayer provider.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"installIntlayer.mjs","names":[],"sources":["../../../src/client/installIntlayer.ts"],"sourcesContent":["import type { LocalesValues } from '@intlayer/types/module_augmentation';\nimport { provideIntlayerEditor } from '../editor/useEditor';\nimport {\n createIntlayerClient,\n INTLAYER_TOKEN,\n IntlayerProvider,\n} from './intlayerToken';\n\nexport { createIntlayerClient, INTLAYER_TOKEN, IntlayerProvider };\n\n/**\n * Provides Intlayer to your Angular application.\n *\n * Registers the Intlayer locale token **and** automatically starts the Intlayer\n * editor client (when the editor is enabled) via `provideAppInitializer`.\n *\n * This is the recommended way to set up Intlayer in `app.config.ts`.\n *\n * @param locale - Initial locale to use.\n * @param isCookieEnabled - Whether to store the locale in cookies.\n * @returns An array of Angular providers for Intlayer.\n *\n * @example\n * ```ts\n * // app.config.ts\n * import { ApplicationConfig } from '@angular/core';\n * import { provideIntlayer } from 'angular-intlayer';\n *\n * export const appConfig: ApplicationConfig = {\n * providers: [provideIntlayer()],\n * };\n * ```\n */\nexport const provideIntlayer = (\n locale?: LocalesValues,\n isCookieEnabled = true\n) => {\n const client = installIntlayer(locale, isCookieEnabled);\n\n return [\n { provide: INTLAYER_TOKEN, useValue: client },\n provideIntlayerEditor(client),\n ];\n};\n\n/**\n * Helper to install the Intlayer provider.\n */\nexport const installIntlayer = (\n locale?: LocalesValues,\n isCookieEnabled = true\n) => {\n return createIntlayerClient(locale, isCookieEnabled);\n};\n"],"mappings":"
|
|
1
|
+
{"version":3,"file":"installIntlayer.mjs","names":[],"sources":["../../../src/client/installIntlayer.ts"],"sourcesContent":["import type { LocalesValues } from '@intlayer/types/module_augmentation';\nimport { provideIntlayerAnalytics } from '../analytics/useAnalytics';\nimport { provideIntlayerEditor } from '../editor/useEditor';\nimport {\n createIntlayerClient,\n INTLAYER_TOKEN,\n IntlayerProvider,\n} from './intlayerToken';\n\nexport { createIntlayerClient, INTLAYER_TOKEN, IntlayerProvider };\n\n/**\n * Provides Intlayer to your Angular application.\n *\n * Registers the Intlayer locale token **and** automatically starts the Intlayer\n * editor client (when the editor is enabled) via `provideAppInitializer`.\n *\n * This is the recommended way to set up Intlayer in `app.config.ts`.\n *\n * @param locale - Initial locale to use.\n * @param isCookieEnabled - Whether to store the locale in cookies.\n * @returns An array of Angular providers for Intlayer.\n *\n * @example\n * ```ts\n * // app.config.ts\n * import { ApplicationConfig } from '@angular/core';\n * import { provideIntlayer } from 'angular-intlayer';\n *\n * export const appConfig: ApplicationConfig = {\n * providers: [provideIntlayer()],\n * };\n * ```\n */\nexport const provideIntlayer = (\n locale?: LocalesValues,\n isCookieEnabled = true\n) => {\n const client = installIntlayer(locale, isCookieEnabled);\n\n return [\n { provide: INTLAYER_TOKEN, useValue: client },\n provideIntlayerEditor(client),\n provideIntlayerAnalytics(client),\n ];\n};\n\n/**\n * Helper to install the Intlayer provider.\n */\nexport const installIntlayer = (\n locale?: LocalesValues,\n isCookieEnabled = true\n) => {\n return createIntlayerClient(locale, isCookieEnabled);\n};\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAkCA,MAAa,mBACX,QACA,kBAAkB,SACf;CACH,MAAM,SAAS,gBAAgB,QAAQ,eAAe;CAEtD,OAAO;EACL;GAAE,SAAS;GAAgB,UAAU;EAAO;EAC5C,sBAAsB,MAAM;EAC5B,yBAAyB,MAAM;CACjC;AACF;;;;AAKA,MAAa,mBACX,QACA,kBAAkB,SACf;CACH,OAAO,qBAAqB,QAAQ,eAAe;AACrD"}
|