@intlayer/core 9.0.0-canary.0 → 9.0.0-canary.10
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/dictionaryManipulator/index.cjs +1 -0
- package/dist/cjs/dictionaryManipulator/mergeQualifiedDictionaries.cjs +1 -5
- package/dist/cjs/dictionaryManipulator/mergeQualifiedDictionaries.cjs.map +1 -1
- package/dist/cjs/dictionaryManipulator/qualifiedDictionary.cjs +48 -74
- package/dist/cjs/dictionaryManipulator/qualifiedDictionary.cjs.map +1 -1
- package/dist/cjs/index.cjs +4 -0
- package/dist/cjs/interpreter/getContent/plugins.cjs +8 -8
- package/dist/cjs/interpreter/getContent/plugins.cjs.map +1 -1
- package/dist/cjs/interpreter/getDictionary.cjs +5 -5
- package/dist/cjs/interpreter/getDictionary.cjs.map +1 -1
- package/dist/cjs/interpreter/getIntlayer.cjs +8 -3
- package/dist/cjs/interpreter/getIntlayer.cjs.map +1 -1
- package/dist/cjs/localization/comparePaths.cjs +75 -0
- package/dist/cjs/localization/comparePaths.cjs.map +1 -0
- package/dist/cjs/localization/getLocalizedUrl.cjs +4 -4
- package/dist/cjs/localization/getLocalizedUrl.cjs.map +1 -1
- package/dist/cjs/localization/getPathWithoutLocale.cjs +2 -2
- package/dist/cjs/localization/getPathWithoutLocale.cjs.map +1 -1
- package/dist/cjs/localization/getPrefix.cjs +2 -2
- package/dist/cjs/localization/getPrefix.cjs.map +1 -1
- package/dist/cjs/localization/index.cjs +3 -0
- package/dist/cjs/localization/rewriteUtils.cjs +1 -1
- package/dist/cjs/localization/rewriteUtils.cjs.map +1 -1
- package/dist/cjs/localization/validatePrefix.cjs +2 -2
- package/dist/cjs/localization/validatePrefix.cjs.map +1 -1
- package/dist/cjs/transpiler/markdown/validateMarkdown.cjs +6 -6
- package/dist/cjs/transpiler/markdown/validateMarkdown.cjs.map +1 -1
- package/dist/cjs/utils/localeStorage.cjs +4 -4
- package/dist/cjs/utils/localeStorage.cjs.map +1 -1
- package/dist/esm/dictionaryManipulator/index.mjs +2 -2
- package/dist/esm/dictionaryManipulator/mergeQualifiedDictionaries.mjs +1 -5
- package/dist/esm/dictionaryManipulator/mergeQualifiedDictionaries.mjs.map +1 -1
- package/dist/esm/dictionaryManipulator/qualifiedDictionary.mjs +48 -75
- package/dist/esm/dictionaryManipulator/qualifiedDictionary.mjs.map +1 -1
- package/dist/esm/index.mjs +3 -2
- package/dist/esm/interpreter/getContent/plugins.mjs +8 -8
- package/dist/esm/interpreter/getContent/plugins.mjs.map +1 -1
- package/dist/esm/interpreter/getDictionary.mjs +5 -5
- package/dist/esm/interpreter/getDictionary.mjs.map +1 -1
- package/dist/esm/interpreter/getIntlayer.mjs +8 -3
- package/dist/esm/interpreter/getIntlayer.mjs.map +1 -1
- package/dist/esm/localization/comparePaths.mjs +73 -0
- package/dist/esm/localization/comparePaths.mjs.map +1 -0
- package/dist/esm/localization/getLocalizedUrl.mjs +4 -4
- package/dist/esm/localization/getLocalizedUrl.mjs.map +1 -1
- package/dist/esm/localization/getPathWithoutLocale.mjs +2 -2
- package/dist/esm/localization/getPathWithoutLocale.mjs.map +1 -1
- package/dist/esm/localization/getPrefix.mjs +2 -2
- package/dist/esm/localization/getPrefix.mjs.map +1 -1
- package/dist/esm/localization/index.mjs +2 -1
- package/dist/esm/localization/rewriteUtils.mjs +1 -1
- package/dist/esm/localization/rewriteUtils.mjs.map +1 -1
- package/dist/esm/localization/validatePrefix.mjs +2 -2
- package/dist/esm/localization/validatePrefix.mjs.map +1 -1
- package/dist/esm/transpiler/markdown/validateMarkdown.mjs +6 -6
- package/dist/esm/transpiler/markdown/validateMarkdown.mjs.map +1 -1
- package/dist/esm/utils/localeStorage.mjs +4 -4
- package/dist/esm/utils/localeStorage.mjs.map +1 -1
- package/dist/types/deepTransformPlugins/getFilterMissingTranslationsContent.d.ts +1 -2
- package/dist/types/deepTransformPlugins/getFilterTranslationsOnlyContent.d.ts +1 -2
- package/dist/types/deepTransformPlugins/getFilteredLocalesContent.d.ts +1 -2
- package/dist/types/dictionaryManipulator/index.d.ts +2 -2
- package/dist/types/dictionaryManipulator/mergeQualifiedDictionaries.d.ts +1 -1
- package/dist/types/dictionaryManipulator/mergeQualifiedDictionaries.d.ts.map +1 -1
- package/dist/types/dictionaryManipulator/qualifiedDictionary.d.ts +33 -20
- package/dist/types/dictionaryManipulator/qualifiedDictionary.d.ts.map +1 -1
- package/dist/types/index.d.ts +3 -2
- package/dist/types/interpreter/getDictionary.d.ts +5 -5
- package/dist/types/interpreter/getIntlayer.d.ts +1 -1
- package/dist/types/interpreter/getPlural.d.ts +1 -1
- package/dist/types/localization/comparePaths.d.ts +66 -0
- package/dist/types/localization/comparePaths.d.ts.map +1 -0
- package/dist/types/localization/getPrefix.d.ts +4 -18
- package/dist/types/localization/getPrefix.d.ts.map +1 -1
- package/dist/types/localization/index.d.ts +2 -1
- package/dist/types/transpiler/markdown/validateMarkdown.d.ts.map +1 -1
- package/package.json +8 -8
- package/dist/cjs/interpreter/getCollection.cjs +0 -25
- package/dist/cjs/interpreter/getCollection.cjs.map +0 -1
- package/dist/cjs/interpreter/getVariant.cjs +0 -30
- package/dist/cjs/interpreter/getVariant.cjs.map +0 -1
- package/dist/cjs/transpiler/collection/collection.cjs +0 -32
- package/dist/cjs/transpiler/collection/collection.cjs.map +0 -1
- package/dist/cjs/transpiler/collection/index.cjs +0 -4
- package/dist/cjs/transpiler/variant/index.cjs +0 -4
- package/dist/cjs/transpiler/variant/variant.cjs +0 -35
- package/dist/cjs/transpiler/variant/variant.cjs.map +0 -1
- package/dist/esm/interpreter/getCollection.mjs +0 -23
- package/dist/esm/interpreter/getCollection.mjs.map +0 -1
- package/dist/esm/interpreter/getVariant.mjs +0 -28
- package/dist/esm/interpreter/getVariant.mjs.map +0 -1
- package/dist/esm/transpiler/collection/collection.mjs +0 -30
- package/dist/esm/transpiler/collection/collection.mjs.map +0 -1
- package/dist/esm/transpiler/collection/index.mjs +0 -3
- package/dist/esm/transpiler/variant/index.mjs +0 -3
- package/dist/esm/transpiler/variant/variant.mjs +0 -33
- package/dist/esm/transpiler/variant/variant.mjs.map +0 -1
- package/dist/types/@intlayer/core/dist/types/formatters/compact.d.ts +0 -1
- package/dist/types/@intlayer/core/dist/types/formatters/currency.d.ts +0 -1
- package/dist/types/@intlayer/core/dist/types/formatters/date.d.ts +0 -1
- package/dist/types/@intlayer/core/dist/types/formatters/index.d.ts +0 -1
- package/dist/types/@intlayer/core/dist/types/formatters/list.d.ts +0 -1
- package/dist/types/@intlayer/core/dist/types/formatters/number.d.ts +0 -1
- package/dist/types/@intlayer/core/dist/types/formatters/percentage.d.ts +0 -1
- package/dist/types/@intlayer/core/dist/types/formatters/relativeTime.d.ts +0 -1
- package/dist/types/@intlayer/core/dist/types/formatters/units.d.ts +0 -1
- package/dist/types/@intlayer/core/dist/types/interpreter/getCondition.d.ts +0 -1
- package/dist/types/@intlayer/core/dist/types/interpreter/getContent/deepTransform.d.ts +0 -1
- package/dist/types/@intlayer/core/dist/types/interpreter/getContent/getContent.d.ts +0 -2
- package/dist/types/@intlayer/core/dist/types/interpreter/getContent/plugins.d.ts +0 -4
- package/dist/types/@intlayer/core/dist/types/interpreter/getDictionary.d.ts +0 -2
- package/dist/types/@intlayer/core/dist/types/interpreter/getEnumeration.d.ts +0 -1
- package/dist/types/@intlayer/core/dist/types/interpreter/getIntlayer.d.ts +0 -2
- package/dist/types/@intlayer/core/dist/types/interpreter/getNesting.d.ts +0 -2
- package/dist/types/@intlayer/core/dist/types/interpreter/getPlural.d.ts +0 -1
- package/dist/types/@intlayer/core/dist/types/interpreter/getTranslation.d.ts +0 -1
- package/dist/types/@intlayer/core/dist/types/interpreter/getVariant.d.ts +0 -1
- package/dist/types/@intlayer/core/dist/types/interpreter/index.d.ts +0 -1
- package/dist/types/@intlayer/core/dist/types/intlayer/dist/types/index.d.ts +0 -1
- package/dist/types/@intlayer/core/dist/types/localization/generateSitemap.d.ts +0 -2
- package/dist/types/@intlayer/core/dist/types/localization/getBrowserLocale.d.ts +0 -1
- package/dist/types/@intlayer/core/dist/types/localization/getHTMLTextDir.d.ts +0 -1
- package/dist/types/@intlayer/core/dist/types/localization/getLocale.d.ts +0 -1
- package/dist/types/@intlayer/core/dist/types/localization/getLocaleFromPath.d.ts +0 -1
- package/dist/types/@intlayer/core/dist/types/localization/getLocaleLang.d.ts +0 -1
- package/dist/types/@intlayer/core/dist/types/localization/getLocaleName.d.ts +0 -1
- package/dist/types/@intlayer/core/dist/types/localization/getLocalizedUrl.d.ts +0 -1
- package/dist/types/@intlayer/core/dist/types/localization/getMultilingualUrls.d.ts +0 -1
- package/dist/types/@intlayer/core/dist/types/localization/getPathWithoutLocale.d.ts +0 -1
- package/dist/types/@intlayer/core/dist/types/localization/getPrefix.d.ts +0 -3
- package/dist/types/@intlayer/core/dist/types/localization/index.d.ts +0 -1
- package/dist/types/@intlayer/core/dist/types/localization/localeDetector.d.ts +0 -1
- package/dist/types/@intlayer/core/dist/types/localization/localeMapper.d.ts +0 -2
- package/dist/types/@intlayer/core/dist/types/localization/localeResolver.d.ts +0 -2
- package/dist/types/@intlayer/core/dist/types/localization/rewriteUtils.d.ts +0 -3
- package/dist/types/@intlayer/core/dist/types/localization/validatePrefix.d.ts +0 -1
- package/dist/types/@intlayer/core/dist/types/markdown/index.d.ts +0 -1
- package/dist/types/@intlayer/core/dist/types/transpiler/collection/collection.d.ts +0 -1
- package/dist/types/@intlayer/core/dist/types/transpiler/condition/condition.d.ts +0 -1
- package/dist/types/@intlayer/core/dist/types/transpiler/enumeration/enumeration.d.ts +0 -1
- package/dist/types/@intlayer/core/dist/types/transpiler/file/file.d.ts +0 -1
- package/dist/types/@intlayer/core/dist/types/transpiler/gender/gender.d.ts +0 -1
- package/dist/types/@intlayer/core/dist/types/transpiler/html/html.d.ts +0 -1
- package/dist/types/@intlayer/core/dist/types/transpiler/index.d.ts +0 -1
- package/dist/types/@intlayer/core/dist/types/transpiler/insertion/insertion.d.ts +0 -1
- package/dist/types/@intlayer/core/dist/types/transpiler/markdown/markdown.d.ts +0 -1
- package/dist/types/@intlayer/core/dist/types/transpiler/nesting/nesting.d.ts +0 -2
- package/dist/types/@intlayer/core/dist/types/transpiler/plural/plural.d.ts +0 -1
- package/dist/types/@intlayer/core/dist/types/transpiler/translation/translation.d.ts +0 -2
- package/dist/types/@intlayer/core/dist/types/transpiler/variant/variant.d.ts +0 -1
- package/dist/types/@intlayer/core/dist/types/utils/index.d.ts +0 -1
- package/dist/types/@intlayer/core/dist/types/utils/intl.d.ts +0 -1
- package/dist/types/@intlayer/core/dist/types/utils/isSameKeyPath.d.ts +0 -1
- package/dist/types/@intlayer/core/dist/types/utils/localeStorage.d.ts +0 -2
- package/dist/types/interpreter/getCollection.d.ts +0 -19
- package/dist/types/interpreter/getCollection.d.ts.map +0 -1
- package/dist/types/interpreter/getVariant.d.ts +0 -26
- package/dist/types/interpreter/getVariant.d.ts.map +0 -1
- package/dist/types/intlayer/dist/types/index.d.ts +0 -4
- package/dist/types/transpiler/collection/collection.d.ts +0 -34
- package/dist/types/transpiler/collection/collection.d.ts.map +0 -1
- package/dist/types/transpiler/collection/index.d.ts +0 -2
- package/dist/types/transpiler/variant/index.d.ts +0 -2
- package/dist/types/transpiler/variant/variant.d.ts +0 -43
- package/dist/types/transpiler/variant/variant.d.ts.map +0 -1
|
@@ -5,11 +5,11 @@ const require_localization_getPrefix = require('./getPrefix.cjs');
|
|
|
5
5
|
/**
|
|
6
6
|
* True when the build-time routing mode is known and is NOT 'no-prefix'.
|
|
7
7
|
*/
|
|
8
|
-
const TREE_SHAKE_NO_PREFIX = process.env
|
|
8
|
+
const TREE_SHAKE_NO_PREFIX = process.env.INTLAYER_ROUTING_MODE && process.env.INTLAYER_ROUTING_MODE !== "no-prefix";
|
|
9
9
|
/**
|
|
10
10
|
* True when the build-time routing mode is known and is NOT 'search-params'.
|
|
11
11
|
*/
|
|
12
|
-
const TREE_SHAKE_SEARCH_PARAMS = process.env
|
|
12
|
+
const TREE_SHAKE_SEARCH_PARAMS = process.env.INTLAYER_ROUTING_MODE && process.env.INTLAYER_ROUTING_MODE !== "search-params";
|
|
13
13
|
/**
|
|
14
14
|
* Checks whether a given locale is valid based on the configured locales.
|
|
15
15
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"validatePrefix.cjs","names":["resolveRoutingConfig","getPrefix"],"sources":["../../../src/localization/validatePrefix.ts"],"sourcesContent":["// ── Tree-shake constants ──────────────────────────────────────────────────────\n// When these env vars are injected at build time, bundlers eliminate the\n// branches guarded by these constants.\n\n/**\n * True when the build-time routing mode is known and is NOT 'no-prefix'.\n */\nconst TREE_SHAKE_NO_PREFIX =\n process.env
|
|
1
|
+
{"version":3,"file":"validatePrefix.cjs","names":["resolveRoutingConfig","getPrefix"],"sources":["../../../src/localization/validatePrefix.ts"],"sourcesContent":["// ── Tree-shake constants ──────────────────────────────────────────────────────\n// When these env vars are injected at build time, bundlers eliminate the\n// branches guarded by these constants.\n\n/**\n * True when the build-time routing mode is known and is NOT 'no-prefix'.\n */\nconst TREE_SHAKE_NO_PREFIX =\n process.env.INTLAYER_ROUTING_MODE &&\n process.env.INTLAYER_ROUTING_MODE !== 'no-prefix';\n\n/**\n * True when the build-time routing mode is known and is NOT 'search-params'.\n */\nconst TREE_SHAKE_SEARCH_PARAMS =\n process.env.INTLAYER_ROUTING_MODE &&\n process.env.INTLAYER_ROUTING_MODE !== 'search-params';\n\nimport type { LocalesValues } from '@intlayer/types/module_augmentation';\nimport {\n getPrefix,\n type RoutingOptions,\n resolveRoutingConfig,\n} from './getPrefix';\n\nexport type ValidatePrefixResult = {\n isValid: boolean;\n localePrefix: string | undefined;\n};\n\n/**\n * Checks whether a given locale is valid based on the configured locales.\n *\n * @param locale - The locale value to validate. Can be `undefined` or `null`.\n * @param options - Optional configuration to override default settings.\n * @param options.locales - Array of valid locales. Defaults to the configured internationalization locales.\n * @param options.defaultLocale - The default locale to use as fallback. Defaults to the configured default locale.\n * @param options.mode - The routing mode (`'prefix'`, `'prefix-all'`, or `'no-prefix'`). Defaults to the configured routing mode.\n * @returns An object containing the validation result and the locale prefix.\n *\n * @example\n * // Check if 'en' is a valid locale\n * const { isValid, localePrefix } = validatePrefix('en');\n *\n * @example\n * // Check with custom options\n * const { isValid, localePrefix } = validatePrefix('fr', {\n * locales: ['en', 'fr', 'es'],\n * defaultLocale: 'en',\n * mode: 'prefix-all',\n * });\n */\nexport const validatePrefix = (\n locale: LocalesValues | undefined | null,\n options?: RoutingOptions\n): ValidatePrefixResult => {\n const { defaultLocale, mode, locales } = resolveRoutingConfig(options);\n\n if (\n (!TREE_SHAKE_NO_PREFIX && mode === 'no-prefix') ||\n (!TREE_SHAKE_SEARCH_PARAMS && mode === 'search-params')\n ) {\n return { isValid: true, localePrefix: undefined };\n }\n\n const { localePrefix } = getPrefix(locale || defaultLocale, {\n mode,\n locales,\n defaultLocale,\n });\n\n if (localePrefix === locale && locale === undefined) {\n return { isValid: true, localePrefix: undefined };\n }\n\n // A segment that doesn't match a locale code pattern (e.g. 'concept', 'compiler')\n // is a content slug from a default-locale URL, not an invalid locale attempt.\n if (locale && !/^[a-z]{2,3}(-[a-zA-Z]{2,4})?$/.test(locale)) {\n return { isValid: true, localePrefix: undefined };\n }\n\n const isValid = locales.some((localeEl) => localeEl === locale);\n\n return { isValid, localePrefix };\n};\n"],"mappings":";;;;;;;AAOA,MAAM,uBACJ,QAAQ,IAAI,yBACZ,QAAQ,IAAI,0BAA0B;;;;AAKxC,MAAM,2BACJ,QAAQ,IAAI,yBACZ,QAAQ,IAAI,0BAA0B;;;;;;;;;;;;;;;;;;;;;;;AAoCxC,MAAa,kBACX,QACA,YACyB;CACzB,MAAM,EAAE,eAAe,MAAM,YAAYA,oDAAqB,QAAQ;AAEtE,KACG,CAAC,wBAAwB,SAAS,eAClC,CAAC,4BAA4B,SAAS,gBAEvC,QAAO;EAAE,SAAS;EAAM,cAAc;EAAW;CAGnD,MAAM,EAAE,iBAAiBC,yCAAU,UAAU,eAAe;EAC1D;EACA;EACA;EACD,CAAC;AAEF,KAAI,iBAAiB,UAAU,WAAW,OACxC,QAAO;EAAE,SAAS;EAAM,cAAc;EAAW;AAKnD,KAAI,UAAU,CAAC,gCAAgC,KAAK,OAAO,CACzD,QAAO;EAAE,SAAS;EAAM,cAAc;EAAW;AAKnD,QAAO;EAAE,SAFO,QAAQ,MAAM,aAAa,aAAa,OAExC;EAAE;EAAc"}
|
|
@@ -13,13 +13,13 @@ const stripCode = (content) => {
|
|
|
13
13
|
let openFence = null;
|
|
14
14
|
for (const line of lines) {
|
|
15
15
|
const fence = line.match(/^[\s>]*(`{3,}|~{3,})/);
|
|
16
|
-
if (!inCodeBlock) if (fence) {
|
|
16
|
+
if (!inCodeBlock) if (fence?.[1]) {
|
|
17
17
|
inCodeBlock = true;
|
|
18
18
|
openFence = fence[1];
|
|
19
19
|
result.push("");
|
|
20
|
-
} else result.push(line.replace(
|
|
20
|
+
} else result.push(line.replace(/(`+)(?:(?!\1).)+?\1/g, (m) => " ".repeat(m.length)));
|
|
21
21
|
else {
|
|
22
|
-
if (fence && fence[1][0] === openFence[0] && fence[1].length >= openFence.length) {
|
|
22
|
+
if (fence?.[1]?.[0] && fence[1][0] === openFence[0] && fence[1].length >= openFence.length) {
|
|
23
23
|
inCodeBlock = false;
|
|
24
24
|
openFence = null;
|
|
25
25
|
}
|
|
@@ -35,14 +35,14 @@ const validateCodeBlocks = (content) => {
|
|
|
35
35
|
let openFence = null;
|
|
36
36
|
let openLineNumber = -1;
|
|
37
37
|
for (let i = 0; i < lines.length; i++) {
|
|
38
|
-
const fence = lines[i]
|
|
38
|
+
const fence = lines[i]?.match(/^[\s>]*(`{3,}|~{3,})/);
|
|
39
39
|
if (!inCodeBlock) {
|
|
40
|
-
if (fence) {
|
|
40
|
+
if (fence?.[1]) {
|
|
41
41
|
inCodeBlock = true;
|
|
42
42
|
openFence = fence[1];
|
|
43
43
|
openLineNumber = i + 1;
|
|
44
44
|
}
|
|
45
|
-
} else if (fence && fence[1][0] === openFence[0] && fence[1].length >= openFence.length) {
|
|
45
|
+
} else if (fence?.[1] && fence[1][0] === openFence[0] && fence[1].length >= openFence.length) {
|
|
46
46
|
inCodeBlock = false;
|
|
47
47
|
openFence = null;
|
|
48
48
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"validateMarkdown.cjs","names":["validateHTML"],"sources":["../../../../src/transpiler/markdown/validateMarkdown.ts"],"sourcesContent":["import { type HTMLValidationIssue, validateHTML } from '../html/validateHTML';\n\nexport type { HTMLValidationIssue as MarkdownValidationIssue } from '../html/validateHTML';\n\nexport type MarkdownValidationResult = {\n valid: boolean;\n issues: HTMLValidationIssue[];\n};\n\n/**\n * Strips fenced code blocks and inline code from markdown content so that\n * HTML-like syntax inside code is not mistakenly validated.\n */\nconst stripCode = (content: string): string => {\n const lines = content.split('\\n');\n const result: string[] = [];\n let inCodeBlock = false;\n let openFence: string | null = null;\n\n for (const line of lines) {\n // Allow leading whitespace and blockquote markers before the fence characters\n const fence = line.match(/^[\\s>]*(`{3,}|~{3,})/);\n if (!inCodeBlock) {\n if (fence) {\n inCodeBlock = true;\n openFence = fence[1];\n result.push('');\n } else {\n // Also strip inline code spans on this line\n result.push(line.replace(
|
|
1
|
+
{"version":3,"file":"validateMarkdown.cjs","names":["validateHTML"],"sources":["../../../../src/transpiler/markdown/validateMarkdown.ts"],"sourcesContent":["import { type HTMLValidationIssue, validateHTML } from '../html/validateHTML';\n\nexport type { HTMLValidationIssue as MarkdownValidationIssue } from '../html/validateHTML';\n\nexport type MarkdownValidationResult = {\n valid: boolean;\n issues: HTMLValidationIssue[];\n};\n\n/**\n * Strips fenced code blocks and inline code from markdown content so that\n * HTML-like syntax inside code is not mistakenly validated.\n */\nconst stripCode = (content: string): string => {\n const lines = content.split('\\n');\n const result: string[] = [];\n let inCodeBlock = false;\n let openFence: string | null = null;\n\n for (const line of lines) {\n // Allow leading whitespace and blockquote markers before the fence characters\n const fence = line.match(/^[\\s>]*(`{3,}|~{3,})/);\n if (!inCodeBlock) {\n if (fence?.[1]) {\n inCodeBlock = true;\n openFence = fence[1];\n result.push('');\n } else {\n // Also strip inline code spans on this line. Code spans may be\n // delimited by a run of one or more backticks and end with a matching\n // run of the same length (CommonMark), allowing shorter backtick runs\n // inside (e.g. `` t`Hello ${name}` ``).\n result.push(\n line.replace(/(`+)(?:(?!\\1).)+?\\1/g, (m) => ' '.repeat(m.length))\n );\n }\n } else {\n if (\n fence?.[1]?.[0] &&\n fence[1][0] === openFence![0] &&\n fence[1].length >= openFence!.length\n ) {\n inCodeBlock = false;\n openFence = null;\n }\n result.push('');\n }\n }\n\n return result.join('\\n');\n};\n\nconst validateCodeBlocks = (content: string): HTMLValidationIssue[] => {\n const issues: HTMLValidationIssue[] = [];\n const lines = content.split('\\n');\n let inCodeBlock = false;\n let openFence: string | null = null;\n let openLineNumber = -1;\n\n for (let i = 0; i < lines.length; i++) {\n const line = lines[i];\n // Allow leading whitespace and blockquote markers before the fence characters\n const fence = line?.match(/^[\\s>]*(`{3,}|~{3,})/);\n\n if (!inCodeBlock) {\n if (fence?.[1]) {\n inCodeBlock = true;\n openFence = fence[1];\n openLineNumber = i + 1;\n }\n } else {\n if (\n fence?.[1] &&\n fence[1][0] === openFence![0] &&\n fence[1].length >= openFence!.length\n ) {\n inCodeBlock = false;\n openFence = null;\n }\n }\n }\n\n if (inCodeBlock) {\n issues.push({\n type: 'error',\n message: `Unclosed code block (opened at line ${openLineNumber})`,\n });\n }\n\n return issues;\n};\n\n/**\n * Validates markdown content for structural correctness:\n * - All fenced code blocks are properly closed\n * - HTML tags are properly nested and closed\n *\n * HTML inside code blocks is excluded from HTML validation.\n */\nexport const validateMarkdown = (content: string): MarkdownValidationResult => {\n const codeIssues = validateCodeBlocks(content);\n const htmlIssues = validateHTML(stripCode(content)).issues;\n const issues = [...codeIssues, ...htmlIssues];\n\n return {\n valid: issues.filter((i) => i.type === 'error').length === 0,\n issues,\n };\n};\n"],"mappings":";;;;;;;;AAaA,MAAM,aAAa,YAA4B;CAC7C,MAAM,QAAQ,QAAQ,MAAM,KAAK;CACjC,MAAM,SAAmB,EAAE;CAC3B,IAAI,cAAc;CAClB,IAAI,YAA2B;AAE/B,MAAK,MAAM,QAAQ,OAAO;EAExB,MAAM,QAAQ,KAAK,MAAM,uBAAuB;AAChD,MAAI,CAAC,YACH,KAAI,QAAQ,IAAI;AACd,iBAAc;AACd,eAAY,MAAM;AAClB,UAAO,KAAK,GAAG;QAMf,QAAO,KACL,KAAK,QAAQ,yBAAyB,MAAM,IAAI,OAAO,EAAE,OAAO,CAAC,CAClE;OAEE;AACL,OACE,QAAQ,KAAK,MACb,MAAM,GAAG,OAAO,UAAW,MAC3B,MAAM,GAAG,UAAU,UAAW,QAC9B;AACA,kBAAc;AACd,gBAAY;;AAEd,UAAO,KAAK,GAAG;;;AAInB,QAAO,OAAO,KAAK,KAAK;;AAG1B,MAAM,sBAAsB,YAA2C;CACrE,MAAM,SAAgC,EAAE;CACxC,MAAM,QAAQ,QAAQ,MAAM,KAAK;CACjC,IAAI,cAAc;CAClB,IAAI,YAA2B;CAC/B,IAAI,iBAAiB;AAErB,MAAK,IAAI,IAAI,GAAG,IAAI,MAAM,QAAQ,KAAK;EAGrC,MAAM,QAFO,MAAM,IAEC,MAAM,uBAAuB;AAEjD,MAAI,CAAC,aACH;OAAI,QAAQ,IAAI;AACd,kBAAc;AACd,gBAAY,MAAM;AAClB,qBAAiB,IAAI;;aAIrB,QAAQ,MACR,MAAM,GAAG,OAAO,UAAW,MAC3B,MAAM,GAAG,UAAU,UAAW,QAC9B;AACA,iBAAc;AACd,eAAY;;;AAKlB,KAAI,YACF,QAAO,KAAK;EACV,MAAM;EACN,SAAS,uCAAuC,eAAe;EAChE,CAAC;AAGJ,QAAO;;;;;;;;;AAUT,MAAa,oBAAoB,YAA8C;CAC7E,MAAM,aAAa,mBAAmB,QAAQ;CAC9C,MAAM,aAAaA,kDAAa,UAAU,QAAQ,CAAC,CAAC;CACpD,MAAM,SAAS,CAAC,GAAG,YAAY,GAAG,WAAW;AAE7C,QAAO;EACL,OAAO,OAAO,QAAQ,MAAM,EAAE,SAAS,QAAQ,CAAC,WAAW;EAC3D;EACD"}
|
|
@@ -8,19 +8,19 @@ let _intlayer_config_built = require("@intlayer/config/built");
|
|
|
8
8
|
/**
|
|
9
9
|
* True when cookie storage is explicitly disabled at build time.
|
|
10
10
|
*/
|
|
11
|
-
const TREE_SHAKE_STORAGE_COOKIES = process.env
|
|
11
|
+
const TREE_SHAKE_STORAGE_COOKIES = process.env.INTLAYER_ROUTING_STORAGE_COOKIES === "false";
|
|
12
12
|
/**
|
|
13
13
|
* True when localStorage is explicitly disabled at build time.
|
|
14
14
|
*/
|
|
15
|
-
const TREE_SHAKE_STORAGE_LOCAL_STORAGE = process.env
|
|
15
|
+
const TREE_SHAKE_STORAGE_LOCAL_STORAGE = process.env.INTLAYER_ROUTING_STORAGE_LOCALSTORAGE === "false";
|
|
16
16
|
/**
|
|
17
17
|
* True when sessionStorage is explicitly disabled at build time.
|
|
18
18
|
*/
|
|
19
|
-
const TREE_SHAKE_STORAGE_SESSION_STORAGE = process.env
|
|
19
|
+
const TREE_SHAKE_STORAGE_SESSION_STORAGE = process.env.INTLAYER_ROUTING_STORAGE_SESSIONSTORAGE === "false";
|
|
20
20
|
/**
|
|
21
21
|
* True when header storage is explicitly disabled at build time.
|
|
22
22
|
*/
|
|
23
|
-
const TREE_SHAKE_STORAGE_HEADERS = process.env
|
|
23
|
+
const TREE_SHAKE_STORAGE_HEADERS = process.env.INTLAYER_ROUTING_STORAGE_HEADERS === "false";
|
|
24
24
|
const localeStorageOptions = {
|
|
25
25
|
getCookie: (name) => document.cookie.split(";").find((c) => c.trim().startsWith(`${name}=`))?.split("=")[1],
|
|
26
26
|
getLocaleStorage: (name) => localStorage.getItem(name),
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"localeStorage.cjs","names":["internationalization","routing","resolveExpiresToTimestamp","buildCookieString","getCookie"],"sources":["../../../src/utils/localeStorage.ts"],"sourcesContent":["import { internationalization, routing } from '@intlayer/config/built';\nimport type { Locale } from '@intlayer/types/allLocales';\nimport type { LocalesValues } from '@intlayer/types/module_augmentation';\nimport { buildCookieString, resolveExpiresToTimestamp } from './cookieExpiry';\nimport { getCookie } from './getCookie';\n\n// ── Tree-shake constants ──────────────────────────────────────────────────────\n// When these env vars are injected at build time, bundlers eliminate the\n// branches guarded by these constants.\n\n/**\n * True when cookie storage is explicitly disabled at build time.\n */\nconst TREE_SHAKE_STORAGE_COOKIES =\n process.env['INTLAYER_ROUTING_STORAGE_COOKIES'] === 'false';\n\n/**\n * True when localStorage is explicitly disabled at build time.\n */\nconst TREE_SHAKE_STORAGE_LOCAL_STORAGE =\n process.env['INTLAYER_ROUTING_STORAGE_LOCALSTORAGE'] === 'false';\n\n/**\n * True when sessionStorage is explicitly disabled at build time.\n */\nconst TREE_SHAKE_STORAGE_SESSION_STORAGE =\n process.env['INTLAYER_ROUTING_STORAGE_SESSIONSTORAGE'] === 'false';\n\n/**\n * True when header storage is explicitly disabled at build time.\n */\nconst TREE_SHAKE_STORAGE_HEADERS =\n process.env['INTLAYER_ROUTING_STORAGE_HEADERS'] === 'false';\n\n// ============================================================================\n// Shared types\n// ============================================================================\n\nexport type CookieBuildAttributes = {\n domain?: string;\n path?: string;\n secure?: boolean;\n httpOnly?: boolean;\n sameSite?: 'strict' | 'lax' | 'none';\n /**\n * Absolute expiry as milliseconds since epoch, ready for `cookieStore.set()`.\n * Already resolved from the normalized `expires` by\n * `resolveExpiresToTimestamp`.\n */\n expires?: number | undefined;\n};\n\n// ============================================================================\n// Client-specific types and functions\n// (cookies via browser APIs, localStorage, sessionStorage — no headers)\n// ============================================================================\n\nexport type LocaleStorageClientOptions = {\n overwrite?: boolean;\n isCookieEnabled?: boolean;\n setCookieStore?: (\n name: string,\n value: string,\n cookie: CookieBuildAttributes\n ) => void;\n setCookieString?: (name: string, cookie: string) => void;\n getCookie?: (name: string) => string | undefined | null;\n setSessionStorage?: (name: string, value: string) => void;\n getSessionStorage?: (name: string) => string | undefined | null;\n setLocaleStorage?: (name: string, value: string) => void;\n getLocaleStorage?: (name: string) => string | undefined | null;\n};\n\n// cookieStore is part of the experimental Cookie Store API\ndeclare const cookieStore: any;\n\nexport const localeStorageOptions: LocaleStorageClientOptions = {\n getCookie: (name: string) =>\n document.cookie\n .split(';')\n .find((c) => c.trim().startsWith(`${name}=`))\n ?.split('=')[1],\n getLocaleStorage: (name: string) => localStorage.getItem(name),\n getSessionStorage: (name: string) => sessionStorage.getItem(name),\n isCookieEnabled: true,\n setCookieStore: (name, value, attributes) =>\n cookieStore.set({\n name,\n value,\n path: attributes.path,\n domain: attributes.domain,\n expires: attributes.expires,\n sameSite: attributes.sameSite,\n }),\n setCookieString: (_name, cookie) => {\n // biome-ignore lint/suspicious/noDocumentCookie: set cookie fallback\n document.cookie = cookie;\n },\n setSessionStorage: (name, value) => sessionStorage.setItem(name, value),\n setLocaleStorage: (name, value) => localStorage.setItem(name, value),\n};\n\n/**\n * Retrieves the locale from browser storage mechanisms\n * (cookies, localStorage, sessionStorage).\n * Does not read from headers — use `getLocaleFromStorageServer` for that.\n */\nexport const getLocaleFromStorageClient = (\n options: LocaleStorageClientOptions = localeStorageOptions\n): Locale | undefined => {\n const { locales } = internationalization;\n\n if (options?.isCookieEnabled === false) return undefined;\n\n const isValidLocale = (value: string | null | undefined): value is Locale =>\n !!value && locales.includes(value as Locale);\n\n if (!TREE_SHAKE_STORAGE_COOKIES) {\n for (let i = 0; i < (routing.storage.cookies ?? []).length; i++) {\n try {\n const value = options?.getCookie?.(routing.storage.cookies![i].name);\n if (isValidLocale(value)) return value;\n } catch {}\n }\n }\n\n if (!TREE_SHAKE_STORAGE_LOCAL_STORAGE) {\n for (let i = 0; i < (routing.storage.localStorage ?? []).length; i++) {\n try {\n const value = options?.getLocaleStorage?.(\n routing.storage.localStorage![i].name\n );\n if (isValidLocale(value)) return value;\n } catch {}\n }\n }\n\n if (!TREE_SHAKE_STORAGE_SESSION_STORAGE && routing.storage.sessionStorage) {\n for (let i = 0; i < routing.storage.sessionStorage.length; i++) {\n try {\n const value = options?.getSessionStorage?.(\n routing.storage.sessionStorage[i].name\n );\n if (isValidLocale(value)) return value;\n } catch {}\n }\n }\n};\n\n/**\n * Stores the locale in browser storage mechanisms\n * (cookies, localStorage, sessionStorage).\n * Does not write to headers — use `setLocaleInStorageServer` for that.\n */\nexport const setLocaleInStorageClient = (\n locale: LocalesValues,\n options?: LocaleStorageClientOptions\n): void => {\n if (options?.isCookieEnabled === false) return;\n\n if (!TREE_SHAKE_STORAGE_COOKIES && routing.storage.cookies) {\n for (let i = 0; i < routing.storage.cookies.length; i++) {\n const { name, attributes } = routing.storage.cookies[i];\n try {\n if (options?.setCookieStore) {\n options.setCookieStore(name, locale, {\n ...attributes,\n expires: resolveExpiresToTimestamp(attributes.expires),\n });\n }\n } catch {\n try {\n if (options?.setCookieString) {\n options.setCookieString(\n name,\n buildCookieString(name, locale, attributes)\n );\n }\n } catch {}\n }\n }\n }\n\n if (\n !TREE_SHAKE_STORAGE_LOCAL_STORAGE &&\n routing.storage.localStorage &&\n options?.setLocaleStorage\n ) {\n for (let i = 0; i < routing.storage.localStorage.length; i++) {\n const { name } = routing.storage.localStorage[i];\n try {\n if (!(options?.overwrite ?? true) && options?.getLocaleStorage) {\n if (options.getLocaleStorage(name)) continue;\n }\n options.setLocaleStorage(name, locale);\n } catch {}\n }\n }\n\n if (\n !TREE_SHAKE_STORAGE_SESSION_STORAGE &&\n routing.storage.sessionStorage &&\n options?.setSessionStorage\n ) {\n for (let i = 0; i < routing.storage.sessionStorage.length; i++) {\n const { name } = routing.storage.sessionStorage[i];\n try {\n if (!(options?.overwrite ?? true) && options?.getSessionStorage) {\n if (options.getSessionStorage(name)) continue;\n }\n options.setSessionStorage(name, locale);\n } catch {}\n }\n }\n};\n\n/**\n * Client-side locale storage utility.\n * Handles cookies (browser), localStorage and sessionStorage.\n * Does not access headers.\n *\n * @example\n * ```ts\n * const storage = LocaleStorageClient(localeStorageOptions);\n * const locale = storage.getLocale();\n * storage.setLocale('fr');\n * ```\n */\nexport const LocaleStorageClient = (options: LocaleStorageClientOptions) => ({\n getLocale: () => getLocaleFromStorageClient(options),\n setLocale: (locale: LocalesValues) =>\n setLocaleInStorageClient(locale, options),\n});\n\n// ============================================================================\n// Server-specific types and functions\n// (cookies via injected getter/setter, headers — no localStorage/sessionStorage)\n// ============================================================================\n\nexport type LocaleStorageServerOptions = {\n overwrite?: boolean;\n isCookieEnabled?: boolean;\n setCookieStore?: (\n name: string,\n value: string,\n cookie: CookieBuildAttributes\n ) => void;\n setCookieString?: (name: string, cookie: string) => void;\n getCookie?: (name: string) => string | undefined | null;\n getHeader?: (name: string) => string | undefined | null;\n setHeader?: (name: string, value: string) => void;\n};\n\n/**\n * Retrieves the locale from server-side storage mechanisms (cookies, headers).\n * Does not access localStorage or sessionStorage.\n * No browser cookie fallback — the caller must provide `getCookie`.\n */\nexport const getLocaleFromStorageServer = (\n options: LocaleStorageServerOptions\n): Locale | undefined => {\n const { locales } = internationalization;\n\n if (options?.isCookieEnabled === false) return undefined;\n\n const isValidLocale = (value: string | null | undefined): value is Locale =>\n !!value && locales.includes(value as Locale);\n\n if (!TREE_SHAKE_STORAGE_COOKIES && routing.storage.cookies) {\n for (let i = 0; i < routing.storage.cookies.length; i++) {\n try {\n const value = options?.getCookie?.(routing.storage.cookies[i].name);\n if (isValidLocale(value)) return value;\n } catch {}\n }\n }\n\n if (!TREE_SHAKE_STORAGE_HEADERS && routing.storage.headers) {\n for (let i = 0; i < routing.storage.headers.length; i++) {\n try {\n const value = options?.getHeader?.(routing.storage.headers[i].name);\n if (isValidLocale(value)) return value;\n } catch {}\n }\n }\n};\n\n/**\n * Stores the locale in server-side storage mechanisms (cookies, headers).\n * Does not write to localStorage or sessionStorage.\n */\nexport const setLocaleInStorageServer = (\n locale: LocalesValues,\n options?: LocaleStorageServerOptions\n): void => {\n if (options?.isCookieEnabled === false) return;\n\n if (!TREE_SHAKE_STORAGE_COOKIES && routing.storage.cookies) {\n for (let i = 0; i < routing.storage.cookies.length; i++) {\n const { name, attributes } = routing.storage.cookies[i];\n\n try {\n if (options?.setCookieStore) {\n options.setCookieStore(name, locale, {\n ...attributes,\n expires: resolveExpiresToTimestamp(attributes.expires),\n });\n }\n } catch {\n try {\n if (options?.setCookieString) {\n options.setCookieString(\n name,\n buildCookieString(name, locale, attributes)\n );\n }\n } catch {}\n }\n }\n }\n\n if (\n !TREE_SHAKE_STORAGE_HEADERS &&\n routing.storage.headers &&\n options?.setHeader\n ) {\n for (let i = 0; i < routing.storage.headers.length; i++) {\n try {\n options.setHeader(routing.storage.headers[i].name, locale);\n } catch {}\n }\n }\n};\n\n/**\n * Server-side locale storage utility.\n * Handles cookies (via injected getter/setter) and headers.\n * Does not access localStorage or sessionStorage.\n *\n * @example\n * ```ts\n * const storage = LocaleStorageServer({\n * getCookie: (name) => req.cookies[name],\n * setCookieStore: (name, value, attrs) => res.cookie(name, value, attrs),\n * getHeader: (name) => req.headers[name],\n * setHeader: (name, value) => res.setHeader(name, value),\n * });\n * const locale = storage.getLocale();\n * storage.setLocale('fr');\n * ```\n */\nexport const LocaleStorageServer = (options: LocaleStorageServerOptions) => ({\n getLocale: () => getLocaleFromStorageServer(options),\n setLocale: (locale: LocalesValues) =>\n setLocaleInStorageServer(locale, options),\n});\n\n// ============================================================================\n// Deprecated: combined LocaleStorage\n// Use LocaleStorageClient or LocaleStorageServer instead\n// ============================================================================\n\n/**\n * @deprecated Use {@link LocaleStorageClientOptions} or {@link LocaleStorageServerOptions} instead.\n */\nexport type LocaleStorageOptions = LocaleStorageClientOptions &\n LocaleStorageServerOptions;\n\n/**\n * Retrieves the locale from all storage mechanisms\n * (cookies, localStorage, sessionStorage, headers).\n *\n * @deprecated Use {@link getLocaleFromStorageClient} (browser) or\n * {@link getLocaleFromStorageServer} (server) instead.\n */\nexport const getLocaleFromStorage = (\n options: Pick<\n LocaleStorageOptions,\n | 'getCookie'\n | 'getSessionStorage'\n | 'getLocaleStorage'\n | 'getHeader'\n | 'isCookieEnabled'\n >\n): Locale | undefined => {\n const { locales } = internationalization;\n\n if (options?.isCookieEnabled === false) return undefined;\n\n const isValidLocale = (value: string | null | undefined): value is Locale =>\n !!value && locales.includes(value as Locale);\n\n const readCookie = (name: string): string | undefined => {\n try {\n const fromOption = options?.getCookie?.(name);\n if (fromOption !== null && fromOption !== undefined) return fromOption;\n } catch {}\n // Browser fallback kept for backward compatibility\n return getCookie(name);\n };\n\n if (!TREE_SHAKE_STORAGE_COOKIES && routing.storage.cookies) {\n for (let i = 0; i < routing.storage.cookies.length; i++) {\n const value = readCookie(routing.storage.cookies[i].name);\n if (isValidLocale(value)) return value;\n }\n }\n\n if (!TREE_SHAKE_STORAGE_LOCAL_STORAGE && routing.storage.localStorage) {\n for (let i = 0; i < routing.storage.localStorage.length; i++) {\n try {\n const value = options?.getLocaleStorage?.(\n routing.storage.localStorage[i].name\n );\n if (isValidLocale(value)) return value;\n } catch {}\n }\n }\n\n if (!TREE_SHAKE_STORAGE_SESSION_STORAGE && routing.storage.sessionStorage) {\n for (let i = 0; i < routing.storage.sessionStorage.length; i++) {\n try {\n const value = options?.getSessionStorage?.(\n routing.storage.sessionStorage[i].name\n );\n if (isValidLocale(value)) return value;\n } catch {}\n }\n }\n\n if (!TREE_SHAKE_STORAGE_HEADERS && routing.storage.headers) {\n for (let i = 0; i < routing.storage.headers.length; i++) {\n try {\n const value = options?.getHeader?.(routing.storage.headers[i].name);\n if (isValidLocale(value)) return value;\n } catch {}\n }\n }\n};\n\n/**\n * Stores the locale in all configured storage mechanisms\n * (cookies, localStorage, sessionStorage, headers).\n *\n * @deprecated Use {@link setLocaleInStorageClient} (browser) or\n * {@link setLocaleInStorageServer} (server) instead.\n */\nexport const setLocaleInStorage = (\n locale: LocalesValues,\n options?: LocaleStorageOptions\n): void => {\n if (options?.isCookieEnabled === false) return;\n\n if (!TREE_SHAKE_STORAGE_COOKIES && routing.storage.cookies) {\n for (let i = 0; i < routing.storage.cookies.length; i++) {\n const { name, attributes } = routing.storage.cookies[i];\n try {\n if (options?.setCookieStore) {\n options.setCookieStore(name, locale, {\n ...attributes,\n expires: resolveExpiresToTimestamp(attributes.expires),\n });\n }\n } catch {\n try {\n if (options?.setCookieString) {\n options.setCookieString(\n name,\n buildCookieString(name, locale, attributes)\n );\n }\n } catch {}\n }\n }\n }\n\n if (\n !TREE_SHAKE_STORAGE_LOCAL_STORAGE &&\n routing.storage.localStorage &&\n options?.setLocaleStorage\n ) {\n for (let i = 0; i < routing.storage.localStorage.length; i++) {\n const { name } = routing.storage.localStorage[i];\n try {\n if (!(options?.overwrite ?? true) && options?.getLocaleStorage) {\n if (options.getLocaleStorage(name)) continue;\n }\n options.setLocaleStorage(name, locale);\n } catch {}\n }\n }\n\n if (\n !TREE_SHAKE_STORAGE_SESSION_STORAGE &&\n routing.storage.sessionStorage &&\n options?.setSessionStorage\n ) {\n for (let i = 0; i < routing.storage.sessionStorage.length; i++) {\n const { name } = routing.storage.sessionStorage[i];\n try {\n if (!(options?.overwrite ?? true) && options?.getSessionStorage) {\n if (options.getSessionStorage(name)) continue;\n }\n options.setSessionStorage(name, locale);\n } catch {}\n }\n }\n\n if (\n !TREE_SHAKE_STORAGE_HEADERS &&\n routing.storage.headers &&\n options?.setHeader\n ) {\n for (let i = 0; i < routing.storage.headers.length; i++) {\n try {\n options.setHeader(routing.storage.headers[i].name, locale);\n } catch {}\n }\n }\n};\n\n/**\n * Utility object to get and set the locale in storage based on configuration.\n *\n * @deprecated Use {@link LocaleStorageClient} (browser) or\n * {@link LocaleStorageServer} (server) instead.\n */\nexport const LocaleStorage = (options: LocaleStorageOptions) => ({\n getLocale: () => getLocaleFromStorage(options),\n setLocale: (locale: LocalesValues) => setLocaleInStorage(locale, options),\n});\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"localeStorage.cjs","names":["internationalization","routing","resolveExpiresToTimestamp","buildCookieString","getCookie"],"sources":["../../../src/utils/localeStorage.ts"],"sourcesContent":["import { internationalization, routing } from '@intlayer/config/built';\nimport type { Locale } from '@intlayer/types/allLocales';\nimport type { LocalesValues } from '@intlayer/types/module_augmentation';\nimport { buildCookieString, resolveExpiresToTimestamp } from './cookieExpiry';\nimport { getCookie } from './getCookie';\n\n// ── Tree-shake constants ──────────────────────────────────────────────────────\n// When these env vars are injected at build time, bundlers eliminate the\n// branches guarded by these constants.\n\n/**\n * True when cookie storage is explicitly disabled at build time.\n */\nconst TREE_SHAKE_STORAGE_COOKIES =\n process.env.INTLAYER_ROUTING_STORAGE_COOKIES === 'false';\n\n/**\n * True when localStorage is explicitly disabled at build time.\n */\nconst TREE_SHAKE_STORAGE_LOCAL_STORAGE =\n process.env.INTLAYER_ROUTING_STORAGE_LOCALSTORAGE === 'false';\n\n/**\n * True when sessionStorage is explicitly disabled at build time.\n */\nconst TREE_SHAKE_STORAGE_SESSION_STORAGE =\n process.env.INTLAYER_ROUTING_STORAGE_SESSIONSTORAGE === 'false';\n\n/**\n * True when header storage is explicitly disabled at build time.\n */\nconst TREE_SHAKE_STORAGE_HEADERS =\n process.env.INTLAYER_ROUTING_STORAGE_HEADERS === 'false';\n\n// ============================================================================\n// Shared types\n// ============================================================================\n\nexport type CookieBuildAttributes = {\n domain?: string;\n path?: string;\n secure?: boolean;\n httpOnly?: boolean;\n sameSite?: 'strict' | 'lax' | 'none';\n /**\n * Absolute expiry as milliseconds since epoch, ready for `cookieStore.set()`.\n * Already resolved from the normalized `expires` by\n * `resolveExpiresToTimestamp`.\n */\n expires?: number | undefined;\n};\n\n// ============================================================================\n// Client-specific types and functions\n// (cookies via browser APIs, localStorage, sessionStorage — no headers)\n// ============================================================================\n\nexport type LocaleStorageClientOptions = {\n overwrite?: boolean;\n isCookieEnabled?: boolean;\n setCookieStore?: (\n name: string,\n value: string,\n cookie: CookieBuildAttributes\n ) => void;\n setCookieString?: (name: string, cookie: string) => void;\n getCookie?: (name: string) => string | undefined | null;\n setSessionStorage?: (name: string, value: string) => void;\n getSessionStorage?: (name: string) => string | undefined | null;\n setLocaleStorage?: (name: string, value: string) => void;\n getLocaleStorage?: (name: string) => string | undefined | null;\n};\n\n// cookieStore is part of the experimental Cookie Store API\ndeclare const cookieStore: any;\n\nexport const localeStorageOptions: LocaleStorageClientOptions = {\n getCookie: (name: string) =>\n document.cookie\n .split(';')\n .find((c) => c.trim().startsWith(`${name}=`))\n ?.split('=')[1],\n getLocaleStorage: (name: string) => localStorage.getItem(name),\n getSessionStorage: (name: string) => sessionStorage.getItem(name),\n isCookieEnabled: true,\n setCookieStore: (name, value, attributes) =>\n cookieStore.set({\n name,\n value,\n path: attributes.path,\n domain: attributes.domain,\n expires: attributes.expires,\n sameSite: attributes.sameSite,\n }),\n setCookieString: (_name, cookie) => {\n // biome-ignore lint/suspicious/noDocumentCookie: set cookie fallback\n document.cookie = cookie;\n },\n setSessionStorage: (name, value) => sessionStorage.setItem(name, value),\n setLocaleStorage: (name, value) => localStorage.setItem(name, value),\n};\n\n/**\n * Retrieves the locale from browser storage mechanisms\n * (cookies, localStorage, sessionStorage).\n * Does not read from headers — use `getLocaleFromStorageServer` for that.\n */\nexport const getLocaleFromStorageClient = (\n options: LocaleStorageClientOptions = localeStorageOptions\n): Locale | undefined => {\n const { locales } = internationalization;\n\n if (options?.isCookieEnabled === false) return undefined;\n\n const isValidLocale = (value: string | null | undefined): value is Locale =>\n !!value && locales.includes(value as Locale);\n\n if (!TREE_SHAKE_STORAGE_COOKIES) {\n for (let i = 0; i < (routing.storage.cookies ?? []).length; i++) {\n try {\n const value = options?.getCookie?.(routing.storage.cookies![i].name);\n if (isValidLocale(value)) return value;\n } catch {}\n }\n }\n\n if (!TREE_SHAKE_STORAGE_LOCAL_STORAGE) {\n for (let i = 0; i < (routing.storage.localStorage ?? []).length; i++) {\n try {\n const value = options?.getLocaleStorage?.(\n routing.storage.localStorage![i].name\n );\n if (isValidLocale(value)) return value;\n } catch {}\n }\n }\n\n if (!TREE_SHAKE_STORAGE_SESSION_STORAGE && routing.storage.sessionStorage) {\n for (let i = 0; i < routing.storage.sessionStorage.length; i++) {\n try {\n const value = options?.getSessionStorage?.(\n routing.storage.sessionStorage[i].name\n );\n if (isValidLocale(value)) return value;\n } catch {}\n }\n }\n};\n\n/**\n * Stores the locale in browser storage mechanisms\n * (cookies, localStorage, sessionStorage).\n * Does not write to headers — use `setLocaleInStorageServer` for that.\n */\nexport const setLocaleInStorageClient = (\n locale: LocalesValues,\n options?: LocaleStorageClientOptions\n): void => {\n if (options?.isCookieEnabled === false) return;\n\n if (!TREE_SHAKE_STORAGE_COOKIES && routing.storage.cookies) {\n for (let i = 0; i < routing.storage.cookies.length; i++) {\n const { name, attributes } = routing.storage.cookies[i];\n try {\n if (options?.setCookieStore) {\n options.setCookieStore(name, locale, {\n ...attributes,\n expires: resolveExpiresToTimestamp(attributes.expires),\n });\n }\n } catch {\n try {\n if (options?.setCookieString) {\n options.setCookieString(\n name,\n buildCookieString(name, locale, attributes)\n );\n }\n } catch {}\n }\n }\n }\n\n if (\n !TREE_SHAKE_STORAGE_LOCAL_STORAGE &&\n routing.storage.localStorage &&\n options?.setLocaleStorage\n ) {\n for (let i = 0; i < routing.storage.localStorage.length; i++) {\n const { name } = routing.storage.localStorage[i];\n try {\n if (!(options?.overwrite ?? true) && options?.getLocaleStorage) {\n if (options.getLocaleStorage(name)) continue;\n }\n options.setLocaleStorage(name, locale);\n } catch {}\n }\n }\n\n if (\n !TREE_SHAKE_STORAGE_SESSION_STORAGE &&\n routing.storage.sessionStorage &&\n options?.setSessionStorage\n ) {\n for (let i = 0; i < routing.storage.sessionStorage.length; i++) {\n const { name } = routing.storage.sessionStorage[i];\n try {\n if (!(options?.overwrite ?? true) && options?.getSessionStorage) {\n if (options.getSessionStorage(name)) continue;\n }\n options.setSessionStorage(name, locale);\n } catch {}\n }\n }\n};\n\n/**\n * Client-side locale storage utility.\n * Handles cookies (browser), localStorage and sessionStorage.\n * Does not access headers.\n *\n * @example\n * ```ts\n * const storage = LocaleStorageClient(localeStorageOptions);\n * const locale = storage.getLocale();\n * storage.setLocale('fr');\n * ```\n */\nexport const LocaleStorageClient = (options: LocaleStorageClientOptions) => ({\n getLocale: () => getLocaleFromStorageClient(options),\n setLocale: (locale: LocalesValues) =>\n setLocaleInStorageClient(locale, options),\n});\n\n// ============================================================================\n// Server-specific types and functions\n// (cookies via injected getter/setter, headers — no localStorage/sessionStorage)\n// ============================================================================\n\nexport type LocaleStorageServerOptions = {\n overwrite?: boolean;\n isCookieEnabled?: boolean;\n setCookieStore?: (\n name: string,\n value: string,\n cookie: CookieBuildAttributes\n ) => void;\n setCookieString?: (name: string, cookie: string) => void;\n getCookie?: (name: string) => string | undefined | null;\n getHeader?: (name: string) => string | undefined | null;\n setHeader?: (name: string, value: string) => void;\n};\n\n/**\n * Retrieves the locale from server-side storage mechanisms (cookies, headers).\n * Does not access localStorage or sessionStorage.\n * No browser cookie fallback — the caller must provide `getCookie`.\n */\nexport const getLocaleFromStorageServer = (\n options: LocaleStorageServerOptions\n): Locale | undefined => {\n const { locales } = internationalization;\n\n if (options?.isCookieEnabled === false) return undefined;\n\n const isValidLocale = (value: string | null | undefined): value is Locale =>\n !!value && locales.includes(value as Locale);\n\n if (!TREE_SHAKE_STORAGE_COOKIES && routing.storage.cookies) {\n for (let i = 0; i < routing.storage.cookies.length; i++) {\n try {\n const value = options?.getCookie?.(routing.storage.cookies[i].name);\n if (isValidLocale(value)) return value;\n } catch {}\n }\n }\n\n if (!TREE_SHAKE_STORAGE_HEADERS && routing.storage.headers) {\n for (let i = 0; i < routing.storage.headers.length; i++) {\n try {\n const value = options?.getHeader?.(routing.storage.headers[i].name);\n if (isValidLocale(value)) return value;\n } catch {}\n }\n }\n};\n\n/**\n * Stores the locale in server-side storage mechanisms (cookies, headers).\n * Does not write to localStorage or sessionStorage.\n */\nexport const setLocaleInStorageServer = (\n locale: LocalesValues,\n options?: LocaleStorageServerOptions\n): void => {\n if (options?.isCookieEnabled === false) return;\n\n if (!TREE_SHAKE_STORAGE_COOKIES && routing.storage.cookies) {\n for (let i = 0; i < routing.storage.cookies.length; i++) {\n const { name, attributes } = routing.storage.cookies[i];\n\n try {\n if (options?.setCookieStore) {\n options.setCookieStore(name, locale, {\n ...attributes,\n expires: resolveExpiresToTimestamp(attributes.expires),\n });\n }\n } catch {\n try {\n if (options?.setCookieString) {\n options.setCookieString(\n name,\n buildCookieString(name, locale, attributes)\n );\n }\n } catch {}\n }\n }\n }\n\n if (\n !TREE_SHAKE_STORAGE_HEADERS &&\n routing.storage.headers &&\n options?.setHeader\n ) {\n for (let i = 0; i < routing.storage.headers.length; i++) {\n try {\n options.setHeader(routing.storage.headers[i].name, locale);\n } catch {}\n }\n }\n};\n\n/**\n * Server-side locale storage utility.\n * Handles cookies (via injected getter/setter) and headers.\n * Does not access localStorage or sessionStorage.\n *\n * @example\n * ```ts\n * const storage = LocaleStorageServer({\n * getCookie: (name) => req.cookies[name],\n * setCookieStore: (name, value, attrs) => res.cookie(name, value, attrs),\n * getHeader: (name) => req.headers[name],\n * setHeader: (name, value) => res.setHeader(name, value),\n * });\n * const locale = storage.getLocale();\n * storage.setLocale('fr');\n * ```\n */\nexport const LocaleStorageServer = (options: LocaleStorageServerOptions) => ({\n getLocale: () => getLocaleFromStorageServer(options),\n setLocale: (locale: LocalesValues) =>\n setLocaleInStorageServer(locale, options),\n});\n\n// ============================================================================\n// Deprecated: combined LocaleStorage\n// Use LocaleStorageClient or LocaleStorageServer instead\n// ============================================================================\n\n/**\n * @deprecated Use {@link LocaleStorageClientOptions} or {@link LocaleStorageServerOptions} instead.\n */\nexport type LocaleStorageOptions = LocaleStorageClientOptions &\n LocaleStorageServerOptions;\n\n/**\n * Retrieves the locale from all storage mechanisms\n * (cookies, localStorage, sessionStorage, headers).\n *\n * @deprecated Use {@link getLocaleFromStorageClient} (browser) or\n * {@link getLocaleFromStorageServer} (server) instead.\n */\nexport const getLocaleFromStorage = (\n options: Pick<\n LocaleStorageOptions,\n | 'getCookie'\n | 'getSessionStorage'\n | 'getLocaleStorage'\n | 'getHeader'\n | 'isCookieEnabled'\n >\n): Locale | undefined => {\n const { locales } = internationalization;\n\n if (options?.isCookieEnabled === false) return undefined;\n\n const isValidLocale = (value: string | null | undefined): value is Locale =>\n !!value && locales.includes(value as Locale);\n\n const readCookie = (name: string): string | undefined => {\n try {\n const fromOption = options?.getCookie?.(name);\n if (fromOption !== null && fromOption !== undefined) return fromOption;\n } catch {}\n // Browser fallback kept for backward compatibility\n return getCookie(name);\n };\n\n if (!TREE_SHAKE_STORAGE_COOKIES && routing.storage.cookies) {\n for (let i = 0; i < routing.storage.cookies.length; i++) {\n const value = readCookie(routing.storage.cookies[i].name);\n if (isValidLocale(value)) return value;\n }\n }\n\n if (!TREE_SHAKE_STORAGE_LOCAL_STORAGE && routing.storage.localStorage) {\n for (let i = 0; i < routing.storage.localStorage.length; i++) {\n try {\n const value = options?.getLocaleStorage?.(\n routing.storage.localStorage[i].name\n );\n if (isValidLocale(value)) return value;\n } catch {}\n }\n }\n\n if (!TREE_SHAKE_STORAGE_SESSION_STORAGE && routing.storage.sessionStorage) {\n for (let i = 0; i < routing.storage.sessionStorage.length; i++) {\n try {\n const value = options?.getSessionStorage?.(\n routing.storage.sessionStorage[i].name\n );\n if (isValidLocale(value)) return value;\n } catch {}\n }\n }\n\n if (!TREE_SHAKE_STORAGE_HEADERS && routing.storage.headers) {\n for (let i = 0; i < routing.storage.headers.length; i++) {\n try {\n const value = options?.getHeader?.(routing.storage.headers[i].name);\n if (isValidLocale(value)) return value;\n } catch {}\n }\n }\n};\n\n/**\n * Stores the locale in all configured storage mechanisms\n * (cookies, localStorage, sessionStorage, headers).\n *\n * @deprecated Use {@link setLocaleInStorageClient} (browser) or\n * {@link setLocaleInStorageServer} (server) instead.\n */\nexport const setLocaleInStorage = (\n locale: LocalesValues,\n options?: LocaleStorageOptions\n): void => {\n if (options?.isCookieEnabled === false) return;\n\n if (!TREE_SHAKE_STORAGE_COOKIES && routing.storage.cookies) {\n for (let i = 0; i < routing.storage.cookies.length; i++) {\n const { name, attributes } = routing.storage.cookies[i];\n try {\n if (options?.setCookieStore) {\n options.setCookieStore(name, locale, {\n ...attributes,\n expires: resolveExpiresToTimestamp(attributes.expires),\n });\n }\n } catch {\n try {\n if (options?.setCookieString) {\n options.setCookieString(\n name,\n buildCookieString(name, locale, attributes)\n );\n }\n } catch {}\n }\n }\n }\n\n if (\n !TREE_SHAKE_STORAGE_LOCAL_STORAGE &&\n routing.storage.localStorage &&\n options?.setLocaleStorage\n ) {\n for (let i = 0; i < routing.storage.localStorage.length; i++) {\n const { name } = routing.storage.localStorage[i];\n try {\n if (!(options?.overwrite ?? true) && options?.getLocaleStorage) {\n if (options.getLocaleStorage(name)) continue;\n }\n options.setLocaleStorage(name, locale);\n } catch {}\n }\n }\n\n if (\n !TREE_SHAKE_STORAGE_SESSION_STORAGE &&\n routing.storage.sessionStorage &&\n options?.setSessionStorage\n ) {\n for (let i = 0; i < routing.storage.sessionStorage.length; i++) {\n const { name } = routing.storage.sessionStorage[i];\n try {\n if (!(options?.overwrite ?? true) && options?.getSessionStorage) {\n if (options.getSessionStorage(name)) continue;\n }\n options.setSessionStorage(name, locale);\n } catch {}\n }\n }\n\n if (\n !TREE_SHAKE_STORAGE_HEADERS &&\n routing.storage.headers &&\n options?.setHeader\n ) {\n for (let i = 0; i < routing.storage.headers.length; i++) {\n try {\n options.setHeader(routing.storage.headers[i].name, locale);\n } catch {}\n }\n }\n};\n\n/**\n * Utility object to get and set the locale in storage based on configuration.\n *\n * @deprecated Use {@link LocaleStorageClient} (browser) or\n * {@link LocaleStorageServer} (server) instead.\n */\nexport const LocaleStorage = (options: LocaleStorageOptions) => ({\n getLocale: () => getLocaleFromStorage(options),\n setLocale: (locale: LocalesValues) => setLocaleInStorage(locale, options),\n});\n"],"mappings":"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"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { COMPOSITE_ID_SEPARATOR, QUALIFIER_DYNAMIC_TYPES_KEY, QUALIFIER_ORDER, getDictionaryCompositeId, getDictionaryQualifierId, getDictionaryQualifierSegments, getDictionaryQualifierTypes, getDictionarySelectorCacheKey, isQualifiedDictionaryGroup, isQualifiedDynamicLoaderMap, parseDictionarySelector, reconstructQualifiedEntry, resolveQualifiedDictionary, resolveQualifiedDynamicContent, resolveQualifiedDynamicContentAsync } from "./qualifiedDictionary.mjs";
|
|
1
|
+
import { COMPOSITE_ID_SEPARATOR, QUALIFIER_DYNAMIC_TYPES_KEY, QUALIFIER_ORDER, getDictionaryCompositeId, getDictionaryQualifierId, getDictionaryQualifierSegments, getDictionaryQualifierTypes, getDictionarySelectorCacheKey, isQualifiedDictionaryGroup, isQualifiedDynamicLoaderMap, parseDictionarySelector, reconstructQualifiedEntry, resolveQualifiedDictionary, resolveQualifiedDynamicContent, resolveQualifiedDynamicContentAsync, serializeVariant } from "./qualifiedDictionary.mjs";
|
|
2
2
|
import { editDictionaryByKeyPath } from "./editDictionaryByKeyPath.mjs";
|
|
3
3
|
import { getContentNodeByKeyPath } from "./getContentNodeByKeyPath.mjs";
|
|
4
4
|
import { getDefaultNode } from "./getDefaultNode.mjs";
|
|
@@ -13,4 +13,4 @@ import { removeContentNodeByKeyPath } from "./removeContentNodeByKeyPath.mjs";
|
|
|
13
13
|
import { renameContentNodeByKeyPath } from "./renameContentNodeByKeyPath.mjs";
|
|
14
14
|
import { updateNodeChildren } from "./updateNodeChildren.mjs";
|
|
15
15
|
|
|
16
|
-
export { COMPOSITE_ID_SEPARATOR, QUALIFIER_DYNAMIC_TYPES_KEY, QUALIFIER_ORDER, editDictionaryByKeyPath, getContentNodeByKeyPath, getDefaultNode, getDictionaryCompositeId, getDictionaryQualifierId, getDictionaryQualifierSegments, getDictionaryQualifierTypes, getDictionarySelectorCacheKey, getEmptyNode, getNodeChildren, getNodeType, isQualifiedDictionaryGroup, isQualifiedDynamicLoaderMap, mergeDictionaries, mergeQualifiedDictionaries, normalizeDictionaries, normalizeDictionary, orderDictionaries, parseDictionarySelector, reconstructQualifiedEntry, removeContentNodeByKeyPath, renameContentNodeByKeyPath, resolveQualifiedDictionary, resolveQualifiedDynamicContent, resolveQualifiedDynamicContentAsync, updateNodeChildren };
|
|
16
|
+
export { COMPOSITE_ID_SEPARATOR, QUALIFIER_DYNAMIC_TYPES_KEY, QUALIFIER_ORDER, editDictionaryByKeyPath, getContentNodeByKeyPath, getDefaultNode, getDictionaryCompositeId, getDictionaryQualifierId, getDictionaryQualifierSegments, getDictionaryQualifierTypes, getDictionarySelectorCacheKey, getEmptyNode, getNodeChildren, getNodeType, isQualifiedDictionaryGroup, isQualifiedDynamicLoaderMap, mergeDictionaries, mergeQualifiedDictionaries, normalizeDictionaries, normalizeDictionary, orderDictionaries, parseDictionarySelector, reconstructQualifiedEntry, removeContentNodeByKeyPath, renameContentNodeByKeyPath, resolveQualifiedDictionary, resolveQualifiedDynamicContent, resolveQualifiedDynamicContentAsync, serializeVariant, updateNodeChildren };
|
|
@@ -11,7 +11,7 @@ import { colorizeKey, getAppLogger } from "@intlayer/config/logger";
|
|
|
11
11
|
* `mergeDictionaries` (single merged dictionary).
|
|
12
12
|
* - At least one dictionary declares a qualifier → the group's dimension set is
|
|
13
13
|
* the union of every declared dimension (in canonical order
|
|
14
|
-
* `variant →
|
|
14
|
+
* `variant → item`). Dictionaries are grouped by their composite id
|
|
15
15
|
* (one segment per dimension), merged within each group (locale completion /
|
|
16
16
|
* priority overrides preserved), and a `QualifiedDictionaryGroup` is returned.
|
|
17
17
|
* Unqualified siblings act as shared base content merged into every entry.
|
|
@@ -43,13 +43,10 @@ const mergeQualifiedDictionaries = (dictionaries) => {
|
|
|
43
43
|
entriesDictionaries.set(compositeId, existingEntries);
|
|
44
44
|
});
|
|
45
45
|
const content = {};
|
|
46
|
-
const metaByCompositeId = {};
|
|
47
|
-
const declaresMeta = groupQualifierTypes.includes("meta");
|
|
48
46
|
let importMode;
|
|
49
47
|
for (const [compositeId, qualifiedDictionaries] of entriesDictionaries) {
|
|
50
48
|
content[compositeId] = mergeDictionaries([...qualifiedDictionaries, ...baseDictionaries]).content;
|
|
51
49
|
const [firstQualified] = qualifiedDictionaries;
|
|
52
|
-
if (declaresMeta && firstQualified?.meta !== void 0) metaByCompositeId[compositeId] = firstQualified.meta;
|
|
53
50
|
importMode ??= firstQualified?.importMode;
|
|
54
51
|
}
|
|
55
52
|
const localIds = Array.from(new Set(dictionaries.filter((dictionary) => dictionary.localId).map((dictionary) => dictionary.localId)));
|
|
@@ -57,7 +54,6 @@ const mergeQualifiedDictionaries = (dictionaries) => {
|
|
|
57
54
|
key: dictionaries[0].key,
|
|
58
55
|
qualifierTypes: groupQualifierTypes,
|
|
59
56
|
content,
|
|
60
|
-
...declaresMeta && { meta: metaByCompositeId },
|
|
61
57
|
...importMode !== void 0 && { importMode },
|
|
62
58
|
localIds
|
|
63
59
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mergeQualifiedDictionaries.mjs","names":[],"sources":["../../../src/dictionaryManipulator/mergeQualifiedDictionaries.ts"],"sourcesContent":["import { log } from '@intlayer/config/built';\nimport { colorizeKey, getAppLogger } from '@intlayer/config/logger';\nimport type {\n Dictionary,\n
|
|
1
|
+
{"version":3,"file":"mergeQualifiedDictionaries.mjs","names":[],"sources":["../../../src/dictionaryManipulator/mergeQualifiedDictionaries.ts"],"sourcesContent":["import { log } from '@intlayer/config/built';\nimport { colorizeKey, getAppLogger } from '@intlayer/config/logger';\nimport type {\n Dictionary,\n DictionaryQualifierType,\n QualifiedDictionaryGroup,\n} from '@intlayer/types/dictionary';\nimport { mergeDictionaries } from './mergeDictionaries';\nimport {\n getDictionaryCompositeId,\n getDictionaryQualifierTypes,\n QUALIFIER_ORDER,\n} from './qualifiedDictionary';\n\n/**\n * Merges sibling dictionaries sharing the same key, honouring qualifiers.\n *\n * - No dictionary declares a qualifier → behaves exactly like\n * `mergeDictionaries` (single merged dictionary).\n * - At least one dictionary declares a qualifier → the group's dimension set is\n * the union of every declared dimension (in canonical order\n * `variant → item`). Dictionaries are grouped by their composite id\n * (one segment per dimension), merged within each group (locale completion /\n * priority overrides preserved), and a `QualifiedDictionaryGroup` is returned.\n * Unqualified siblings act as shared base content merged into every entry.\n *\n * Every qualified entry must declare ALL dimensions of the group; an entry that\n * declares only a subset is ambiguous and is rejected with an error log.\n */\nexport const mergeQualifiedDictionaries = (\n dictionaries: Dictionary[]\n): Dictionary | QualifiedDictionaryGroup => {\n const perDictionaryTypes = dictionaries.map(getDictionaryQualifierTypes);\n\n const declaredDimensions = new Set<DictionaryQualifierType>();\n for (const types of perDictionaryTypes) {\n for (const type of types) declaredDimensions.add(type);\n }\n\n // Canonical order, restricted to the dimensions actually declared.\n const groupQualifierTypes = QUALIFIER_ORDER.filter((qualifierType) =>\n declaredDimensions.has(qualifierType)\n );\n\n if (groupQualifierTypes.length === 0) {\n return mergeDictionaries(dictionaries);\n }\n\n const appLogger = getAppLogger({ log });\n\n const baseDictionaries: Dictionary[] = [];\n const entriesDictionaries = new Map<string, Dictionary[]>();\n\n dictionaries.forEach((dictionary, index) => {\n if (perDictionaryTypes[index].length === 0) {\n baseDictionaries.push(dictionary);\n return;\n }\n\n const compositeId = getDictionaryCompositeId(\n dictionary,\n groupQualifierTypes\n );\n\n if (compositeId === undefined) {\n appLogger(\n `Dictionary ${colorizeKey(dictionary.key)} declares (${perDictionaryTypes[index].join(', ')}) but the key's dimensions are (${groupQualifierTypes.join(', ')}); every entry must declare all of them. Entry ignored${dictionary.filePath ? ` - ${dictionary.filePath}` : ''}.`,\n { level: 'error' }\n );\n return;\n }\n\n const existingEntries = entriesDictionaries.get(compositeId) ?? [];\n existingEntries.push(dictionary);\n entriesDictionaries.set(compositeId, existingEntries);\n });\n\n // `content` maps each composite id to its resolved content node directly; the\n // qualifier coordinates live in the key, not in a per-entry wrapper. For an\n // object variant the variant segment is the canonical serialization of the\n // object, so it fully identifies the entry — no side-map is needed.\n const content: Record<string, unknown> = {};\n\n let importMode: Dictionary['importMode'];\n\n for (const [compositeId, qualifiedDictionaries] of entriesDictionaries) {\n // Unqualified siblings act as shared base content: appended last so the\n // qualified entries take precedence (mergeDictionaries prefers first).\n const mergedEntry = mergeDictionaries([\n ...qualifiedDictionaries,\n ...baseDictionaries,\n ]);\n\n content[compositeId] = mergedEntry.content;\n\n const [firstQualified] = qualifiedDictionaries;\n\n importMode ??= firstQualified?.importMode;\n }\n\n const localIds = Array.from(\n new Set(\n dictionaries\n .filter((dictionary) => dictionary.localId)\n .map((dictionary) => dictionary.localId!)\n )\n );\n\n return {\n key: dictionaries[0]!.key,\n qualifierTypes: groupQualifierTypes,\n content,\n ...(importMode !== undefined && { importMode }),\n localIds,\n };\n};\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;AA6BA,MAAa,8BACX,iBAC0C;CAC1C,MAAM,qBAAqB,aAAa,IAAI,4BAA4B;CAExE,MAAM,qCAAqB,IAAI,KAA8B;AAC7D,MAAK,MAAM,SAAS,mBAClB,MAAK,MAAM,QAAQ,MAAO,oBAAmB,IAAI,KAAK;CAIxD,MAAM,sBAAsB,gBAAgB,QAAQ,kBAClD,mBAAmB,IAAI,cAAc,CACtC;AAED,KAAI,oBAAoB,WAAW,EACjC,QAAO,kBAAkB,aAAa;CAGxC,MAAM,YAAY,aAAa,EAAE,KAAK,CAAC;CAEvC,MAAM,mBAAiC,EAAE;CACzC,MAAM,sCAAsB,IAAI,KAA2B;AAE3D,cAAa,SAAS,YAAY,UAAU;AAC1C,MAAI,mBAAmB,OAAO,WAAW,GAAG;AAC1C,oBAAiB,KAAK,WAAW;AACjC;;EAGF,MAAM,cAAc,yBAClB,YACA,oBACD;AAED,MAAI,gBAAgB,QAAW;AAC7B,aACE,cAAc,YAAY,WAAW,IAAI,CAAC,aAAa,mBAAmB,OAAO,KAAK,KAAK,CAAC,kCAAkC,oBAAoB,KAAK,KAAK,CAAC,wDAAwD,WAAW,WAAW,MAAM,WAAW,aAAa,GAAG,IAC5Q,EAAE,OAAO,SAAS,CACnB;AACD;;EAGF,MAAM,kBAAkB,oBAAoB,IAAI,YAAY,IAAI,EAAE;AAClE,kBAAgB,KAAK,WAAW;AAChC,sBAAoB,IAAI,aAAa,gBAAgB;GACrD;CAMF,MAAM,UAAmC,EAAE;CAE3C,IAAI;AAEJ,MAAK,MAAM,CAAC,aAAa,0BAA0B,qBAAqB;AAQtE,UAAQ,eALY,kBAAkB,CACpC,GAAG,uBACH,GAAG,iBACJ,CAEiC,CAAC;EAEnC,MAAM,CAAC,kBAAkB;AAEzB,iBAAe,gBAAgB;;CAGjC,MAAM,WAAW,MAAM,KACrB,IAAI,IACF,aACG,QAAQ,eAAe,WAAW,QAAQ,CAC1C,KAAK,eAAe,WAAW,QAAS,CAC5C,CACF;AAED,QAAO;EACL,KAAK,aAAa,GAAI;EACtB,gBAAgB;EAChB;EACA,GAAI,eAAe,UAAa,EAAE,YAAY;EAC9C;EACD"}
|
|
@@ -1,37 +1,40 @@
|
|
|
1
1
|
//#region src/dictionaryManipulator/qualifiedDictionary.ts
|
|
2
2
|
/**
|
|
3
|
-
*
|
|
4
|
-
*
|
|
3
|
+
* Canonical order of qualifier dimensions. A key that declares both dimensions
|
|
4
|
+
* always nests them in this order, with `item` innermost so it can act as the
|
|
5
|
+
* collection (array) axis.
|
|
5
6
|
*/
|
|
6
|
-
const
|
|
7
|
-
"locale",
|
|
8
|
-
"item",
|
|
9
|
-
"variant"
|
|
10
|
-
];
|
|
11
|
-
/**
|
|
12
|
-
* Canonical order of qualifier dimensions. A key that declares several
|
|
13
|
-
* dimensions always nests them in this order, with `item` innermost so it can
|
|
14
|
-
* act as the collection (array) axis.
|
|
15
|
-
*/
|
|
16
|
-
const QUALIFIER_ORDER = [
|
|
17
|
-
"variant",
|
|
18
|
-
"meta",
|
|
19
|
-
"item"
|
|
20
|
-
];
|
|
7
|
+
const QUALIFIER_ORDER = ["variant", "item"];
|
|
21
8
|
/**
|
|
22
9
|
* Separator joining per-dimension ids into a composite entry id. Also used as
|
|
23
10
|
* the chunk path separator in dynamic mode.
|
|
24
11
|
*/
|
|
25
12
|
const COMPOSITE_ID_SEPARATOR = "/";
|
|
26
13
|
/**
|
|
14
|
+
* Canonical serialization of a variant value into its identity string — the
|
|
15
|
+
* variant segment of a composite id and the runtime matching key.
|
|
16
|
+
*
|
|
17
|
+
* - `undefined` → `'default'` (the implicit fallback variant)
|
|
18
|
+
* - a string → the string itself (a named variant)
|
|
19
|
+
* - an object → its sorted `key=value` pairs joined by `&`
|
|
20
|
+
* (e.g. `{ userId: '123', id: 'abc' }` → `'id=abc&userId=123'`)
|
|
21
|
+
*
|
|
22
|
+
* Two variants resolve to the same entry iff their serializations are equal, so
|
|
23
|
+
* an object variant in a selector must equal the one declared on the dictionary.
|
|
24
|
+
*/
|
|
25
|
+
const serializeVariant = (variant) => {
|
|
26
|
+
if (variant === void 0) return "default";
|
|
27
|
+
if (typeof variant === "string") return variant;
|
|
28
|
+
return Object.keys(variant).sort().map((field) => `${field}=${variant[field]}`).join("&");
|
|
29
|
+
};
|
|
30
|
+
/**
|
|
27
31
|
* Returns the qualifier dimensions declared on a dictionary, in canonical
|
|
28
|
-
* order (`variant →
|
|
32
|
+
* order (`variant → item`). Empty when the dictionary is unqualified
|
|
29
33
|
* (plain dictionary or shared base content of a qualified group).
|
|
30
34
|
*/
|
|
31
35
|
const getDictionaryQualifierTypes = (dictionary) => {
|
|
32
36
|
const declaredQualifiers = [];
|
|
33
|
-
if (
|
|
34
|
-
if (dictionary.meta !== void 0) declaredQualifiers.push("meta");
|
|
37
|
+
if (dictionary.variant !== void 0) declaredQualifiers.push("variant");
|
|
35
38
|
if (typeof dictionary.item === "number") declaredQualifiers.push("item");
|
|
36
39
|
return declaredQualifiers;
|
|
37
40
|
};
|
|
@@ -39,16 +42,11 @@ const getDictionaryQualifierTypes = (dictionary) => {
|
|
|
39
42
|
* Returns the qualifier identifier of a dictionary for the given qualifier
|
|
40
43
|
* dimension — one segment of the composite entry id.
|
|
41
44
|
*
|
|
42
|
-
* - 'variant' → the variant
|
|
43
|
-
* - 'meta' → the `meta.id` discriminator
|
|
45
|
+
* - 'variant' → the serialized variant (named string or object identity)
|
|
44
46
|
* - 'item' → the item index as string
|
|
45
47
|
*/
|
|
46
48
|
const getDictionaryQualifierId = (dictionary, qualifierType) => {
|
|
47
|
-
if (qualifierType === "variant") return dictionary.variant;
|
|
48
|
-
if (qualifierType === "meta") {
|
|
49
|
-
const metaId = dictionary.meta?.id;
|
|
50
|
-
return metaId === void 0 ? void 0 : String(metaId);
|
|
51
|
-
}
|
|
49
|
+
if (qualifierType === "variant") return dictionary.variant === void 0 ? void 0 : serializeVariant(dictionary.variant);
|
|
52
50
|
return dictionary.item === void 0 ? void 0 : String(dictionary.item);
|
|
53
51
|
};
|
|
54
52
|
/**
|
|
@@ -71,27 +69,13 @@ const getDictionaryQualifierSegments = (dictionary, qualifierTypes) => {
|
|
|
71
69
|
*/
|
|
72
70
|
const getDictionaryCompositeId = (dictionary, qualifierTypes) => getDictionaryQualifierSegments(dictionary, qualifierTypes)?.join("/");
|
|
73
71
|
/**
|
|
74
|
-
* Checks that every declared meta field is provided and equal in the selector.
|
|
75
|
-
* Reserved keys (`locale`, `item`, `variant`) are skipped; `meta.id` is part of
|
|
76
|
-
* the equality check.
|
|
77
|
-
*/
|
|
78
|
-
const metaFieldsMatch = (meta, selector) => {
|
|
79
|
-
if (!meta) return false;
|
|
80
|
-
return Object.entries(meta).every(([metaField, declaredValue]) => {
|
|
81
|
-
if (RESERVED_SELECTOR_KEYS.includes(metaField)) return true;
|
|
82
|
-
const providedValue = selector?.[metaField];
|
|
83
|
-
return providedValue !== void 0 && String(providedValue) === String(declaredValue);
|
|
84
|
-
});
|
|
85
|
-
};
|
|
86
|
-
/**
|
|
87
72
|
* Tests whether a group entry matches a selector across every declared
|
|
88
73
|
* dimension. The `item` dimension matches any value when the selector does not
|
|
89
74
|
* provide one (open collection axis).
|
|
90
75
|
*/
|
|
91
76
|
const entryMatchesSelector = (entry, qualifierTypes, selector) => qualifierTypes.every((qualifierType) => {
|
|
92
|
-
if (qualifierType === "variant") return entry.variant === (selector?.variant
|
|
93
|
-
|
|
94
|
-
return metaFieldsMatch(entry.meta, selector);
|
|
77
|
+
if (qualifierType === "variant") return serializeVariant(entry.variant) === serializeVariant(selector?.variant);
|
|
78
|
+
return selector?.item === void 0 || String(entry.item) === String(selector.item);
|
|
95
79
|
});
|
|
96
80
|
/**
|
|
97
81
|
* Type guard discriminating a `QualifiedDictionaryGroup` (merge output of a
|
|
@@ -102,12 +86,13 @@ const isQualifiedDictionaryGroup = (value) => typeof value === "object" && value
|
|
|
102
86
|
/**
|
|
103
87
|
* Reconstructs a resolvable {@link Dictionary} from a single entry of a
|
|
104
88
|
* qualified group: the content node stored under its composite id, plus the
|
|
105
|
-
* qualifier coordinates decoded from that id (`variant`, `item`)
|
|
106
|
-
* preserved `meta` object for the meta dimension.
|
|
89
|
+
* qualifier coordinates decoded from that id (`variant`, `item`).
|
|
107
90
|
*
|
|
108
91
|
* This keeps the resolver's matching/transform code unchanged: it still sees a
|
|
109
|
-
* `{ key, content, variant?, item
|
|
110
|
-
*
|
|
92
|
+
* `{ key, content, variant?, item? }` shape, even though the stored format no
|
|
93
|
+
* longer duplicates those fields per entry. The `variant` coordinate stays in
|
|
94
|
+
* its serialized form (e.g. `'id=abc&userId=123'`), which round-trips through
|
|
95
|
+
* {@link serializeVariant} during matching.
|
|
111
96
|
*/
|
|
112
97
|
const reconstructQualifiedEntry = (group, compositeId) => {
|
|
113
98
|
const segments = compositeId.split("/");
|
|
@@ -119,10 +104,6 @@ const reconstructQualifiedEntry = (group, compositeId) => {
|
|
|
119
104
|
if (qualifierType === "variant") entry.variant = segments[index];
|
|
120
105
|
else if (qualifierType === "item") entry.item = Number(segments[index]);
|
|
121
106
|
});
|
|
122
|
-
if (group.qualifierTypes.includes("meta")) {
|
|
123
|
-
const metaIndex = group.qualifierTypes.indexOf("meta");
|
|
124
|
-
entry.meta = group.meta?.[compositeId] ?? { id: segments[metaIndex] };
|
|
125
|
-
}
|
|
126
107
|
return entry;
|
|
127
108
|
};
|
|
128
109
|
/**
|
|
@@ -132,8 +113,8 @@ const reconstructQualifiedEntry = (group, compositeId) => {
|
|
|
132
113
|
* - Plain dictionary → returned as-is (selector ignored)
|
|
133
114
|
* - `item` declared but not selected → every matching entry ordered by index
|
|
134
115
|
* - `item` selected → the matching entry or null
|
|
135
|
-
* - `variant` defaults to the `default` entry when not selected
|
|
136
|
-
*
|
|
116
|
+
* - `variant` defaults to the `default` entry when not selected; an object
|
|
117
|
+
* variant resolves only when the selector provides an equal object
|
|
137
118
|
*
|
|
138
119
|
* Dimensions compose: e.g. a variant × item key with `{ variant: 'promo' }`
|
|
139
120
|
* returns every promo item as an array; adding `{ item: 2 }` narrows to one.
|
|
@@ -141,7 +122,6 @@ const reconstructQualifiedEntry = (group, compositeId) => {
|
|
|
141
122
|
const resolveQualifiedDictionary = (dictionaryOrGroup, selector) => {
|
|
142
123
|
if (!isQualifiedDictionaryGroup(dictionaryOrGroup)) return dictionaryOrGroup;
|
|
143
124
|
const { qualifierTypes, content } = dictionaryOrGroup;
|
|
144
|
-
if (qualifierTypes.includes("meta") && selector?.id === void 0) return null;
|
|
145
125
|
const itemAxisOpen = qualifierTypes.includes("item") && selector?.item === void 0;
|
|
146
126
|
const matchedEntries = Object.keys(content).map((compositeId) => reconstructQualifiedEntry(dictionaryOrGroup, compositeId)).filter((entry) => entryMatchesSelector(entry, qualifierTypes, selector));
|
|
147
127
|
if (itemAxisOpen) return matchedEntries.sort((left, right) => (left.item ?? 0) - (right.item ?? 0));
|
|
@@ -164,7 +144,10 @@ const parseDictionarySelector = (localeOrSelector) => {
|
|
|
164
144
|
*/
|
|
165
145
|
const getDictionarySelectorCacheKey = (selector) => {
|
|
166
146
|
if (!selector) return "";
|
|
167
|
-
return Object.keys(selector).filter((selectorKey) => selectorKey !== "locale").sort().map((selectorKey) =>
|
|
147
|
+
return Object.keys(selector).filter((selectorKey) => selectorKey !== "locale").sort().map((selectorKey) => {
|
|
148
|
+
const value = selector[selectorKey];
|
|
149
|
+
return `${selectorKey}:${selectorKey === "variant" ? serializeVariant(value) : String(value)}`;
|
|
150
|
+
}).join("|");
|
|
168
151
|
};
|
|
169
152
|
/**
|
|
170
153
|
* Marker property carrying the ordered qualifier dimensions on a dynamic loader
|
|
@@ -175,7 +158,7 @@ const getDictionarySelectorCacheKey = (selector) => {
|
|
|
175
158
|
const QUALIFIER_DYNAMIC_TYPES_KEY = "__intlayerQualifierTypes";
|
|
176
159
|
/**
|
|
177
160
|
* Type guard discriminating a qualified dynamic loader map (collections /
|
|
178
|
-
* variants
|
|
161
|
+
* variants, possibly combined) from a plain dynamic loader map.
|
|
179
162
|
*/
|
|
180
163
|
const isQualifiedDynamicLoaderMap = (value) => typeof value === "object" && value !== null && "__intlayerQualifierTypes" in value;
|
|
181
164
|
/**
|
|
@@ -192,11 +175,6 @@ const collectQualifiedChunks = (loaderMap, key, locale, selector) => {
|
|
|
192
175
|
missed: true,
|
|
193
176
|
chunks: []
|
|
194
177
|
};
|
|
195
|
-
if (qualifierTypes.includes("meta") && selector?.id === void 0) return {
|
|
196
|
-
itemAxisOpen,
|
|
197
|
-
missed: true,
|
|
198
|
-
chunks: []
|
|
199
|
-
};
|
|
200
178
|
const chunks = [];
|
|
201
179
|
const walk = (node, dimensions, segments) => {
|
|
202
180
|
if (dimensions.length === 0) {
|
|
@@ -212,7 +190,7 @@ const collectQualifiedChunks = (loaderMap, key, locale, selector) => {
|
|
|
212
190
|
for (const segment of Object.keys(tree).sort((left, right) => Number(left) - Number(right))) walk(tree[segment], rest, [...segments, segment]);
|
|
213
191
|
return true;
|
|
214
192
|
}
|
|
215
|
-
const segment = dimension === "variant" ? selector?.variant
|
|
193
|
+
const segment = dimension === "variant" ? serializeVariant(selector?.variant) : String(selector?.item);
|
|
216
194
|
const child = tree[segment];
|
|
217
195
|
if (!child) return false;
|
|
218
196
|
return walk(child, rest, [...segments, segment]);
|
|
@@ -224,20 +202,15 @@ const collectQualifiedChunks = (loaderMap, key, locale, selector) => {
|
|
|
224
202
|
};
|
|
225
203
|
};
|
|
226
204
|
/**
|
|
227
|
-
* Whether a loaded chunk satisfies the selector's meta fields (no-op unless the
|
|
228
|
-
* key declares a `meta` dimension).
|
|
229
|
-
*/
|
|
230
|
-
const chunkMatchesMeta = (loaderMap, dictionary, selector) => !loaderMap["__intlayerQualifierTypes"].includes("meta") || metaFieldsMatch(dictionary.meta, selector);
|
|
231
|
-
/**
|
|
232
205
|
* Resolves the content of a qualified dynamic loader map against a selector,
|
|
233
206
|
* loading only the chunk(s) the selector actually targets.
|
|
234
207
|
*
|
|
235
208
|
* Walks the nested loader tree one dimension at a time (canonical order
|
|
236
|
-
* `variant →
|
|
237
|
-
*
|
|
238
|
-
* given — expands into every sibling chunk (the collection
|
|
239
|
-
*
|
|
240
|
-
*
|
|
209
|
+
* `variant → item`): `variant` defaults to `default` (or descends by the
|
|
210
|
+
* serialized object identity), and `item` either narrows to the selected index
|
|
211
|
+
* or — when no item is given — expands into every sibling chunk (the collection
|
|
212
|
+
* axis). Semantics mirror {@link resolveQualifiedDictionary} so dynamic and
|
|
213
|
+
* static modes behave alike.
|
|
241
214
|
*
|
|
242
215
|
* The Suspense mechanism is injected through `loadChunk` so the same logic
|
|
243
216
|
* serves both the client (suspender cache) and the server (`react.use`). Every
|
|
@@ -255,7 +228,7 @@ const resolveQualifiedDynamicContent = (params) => {
|
|
|
255
228
|
const { loaderMap, key, locale, selector, loadChunk, transform } = params;
|
|
256
229
|
const { itemAxisOpen, missed, chunks } = collectQualifiedChunks(loaderMap, key, locale, selector);
|
|
257
230
|
if (missed) return itemAxisOpen ? [] : null;
|
|
258
|
-
const dictionaries = chunks.map(({ cacheKey, loader }) => loadChunk(cacheKey, loader()))
|
|
231
|
+
const dictionaries = chunks.map(({ cacheKey, loader }) => loadChunk(cacheKey, loader()));
|
|
259
232
|
if (itemAxisOpen) return dictionaries.map(transform);
|
|
260
233
|
const [dictionary] = dictionaries;
|
|
261
234
|
return dictionary ? transform(dictionary) : null;
|
|
@@ -275,12 +248,12 @@ const resolveQualifiedDynamicContentAsync = async (params) => {
|
|
|
275
248
|
const { loaderMap, key, locale, selector, transform } = params;
|
|
276
249
|
const { itemAxisOpen, missed, chunks } = collectQualifiedChunks(loaderMap, key, locale, selector);
|
|
277
250
|
if (missed) return itemAxisOpen ? [] : null;
|
|
278
|
-
const dictionaries =
|
|
251
|
+
const dictionaries = await Promise.all(chunks.map(({ loader }) => loader()));
|
|
279
252
|
if (itemAxisOpen) return dictionaries.map(transform);
|
|
280
253
|
const [dictionary] = dictionaries;
|
|
281
254
|
return dictionary ? transform(dictionary) : null;
|
|
282
255
|
};
|
|
283
256
|
|
|
284
257
|
//#endregion
|
|
285
|
-
export { COMPOSITE_ID_SEPARATOR, QUALIFIER_DYNAMIC_TYPES_KEY, QUALIFIER_ORDER, getDictionaryCompositeId, getDictionaryQualifierId, getDictionaryQualifierSegments, getDictionaryQualifierTypes, getDictionarySelectorCacheKey, isQualifiedDictionaryGroup, isQualifiedDynamicLoaderMap, parseDictionarySelector, reconstructQualifiedEntry, resolveQualifiedDictionary, resolveQualifiedDynamicContent, resolveQualifiedDynamicContentAsync };
|
|
258
|
+
export { COMPOSITE_ID_SEPARATOR, QUALIFIER_DYNAMIC_TYPES_KEY, QUALIFIER_ORDER, getDictionaryCompositeId, getDictionaryQualifierId, getDictionaryQualifierSegments, getDictionaryQualifierTypes, getDictionarySelectorCacheKey, isQualifiedDictionaryGroup, isQualifiedDynamicLoaderMap, parseDictionarySelector, reconstructQualifiedEntry, resolveQualifiedDictionary, resolveQualifiedDynamicContent, resolveQualifiedDynamicContentAsync, serializeVariant };
|
|
286
259
|
//# sourceMappingURL=qualifiedDictionary.mjs.map
|