@rushstack/webpack5-localization-plugin 0.11.1 → 0.11.2

Sign up to get free protection for your applications and to get access to all the features.
package/CHANGELOG.json CHANGED
@@ -1,6 +1,18 @@
1
1
  {
2
2
  "name": "@rushstack/webpack5-localization-plugin",
3
3
  "entries": [
4
+ {
5
+ "version": "0.11.2",
6
+ "tag": "@rushstack/webpack5-localization-plugin_v0.11.2",
7
+ "date": "Wed, 07 Aug 2024 00:11:51 GMT",
8
+ "comments": {
9
+ "patch": [
10
+ {
11
+ "comment": "Improve performance of localized asset reconstruction."
12
+ }
13
+ ]
14
+ }
15
+ },
4
16
  {
5
17
  "version": "0.11.1",
6
18
  "tag": "@rushstack/webpack5-localization-plugin_v0.11.1",
package/CHANGELOG.md CHANGED
@@ -1,6 +1,13 @@
1
1
  # Change Log - @rushstack/webpack5-localization-plugin
2
2
 
3
- This log was last generated on Fri, 02 Aug 2024 17:26:42 GMT and should not be manually modified.
3
+ This log was last generated on Wed, 07 Aug 2024 00:11:51 GMT and should not be manually modified.
4
+
5
+ ## 0.11.2
6
+ Wed, 07 Aug 2024 00:11:51 GMT
7
+
8
+ ### Patches
9
+
10
+ - Improve performance of localized asset reconstruction.
4
11
 
5
12
  ## 0.11.1
6
13
  Fri, 02 Aug 2024 17:26:42 GMT
@@ -5,7 +5,7 @@
5
5
  "toolPackages": [
6
6
  {
7
7
  "packageName": "@microsoft/api-extractor",
8
- "packageVersion": "7.47.4"
8
+ "packageVersion": "7.47.5"
9
9
  }
10
10
  ]
11
11
  }
@@ -127,14 +127,21 @@ function _reconstructLocalized(result, reconstructionSeries, locale, fallbackLoc
127
127
  }
128
128
  }
129
129
  const escapedBackslash = element.escapedBackslash || '\\';
130
- // Replace backslashes with the properly escaped backslash
131
- BACKSLASH_REGEX.lastIndex = -1;
132
- newValue = newValue.replace(BACKSLASH_REGEX, escapedBackslash);
133
- // @todo: look into using JSON.parse(...) to get the escaping characters
134
- const escapingCharacterSequence = escapedBackslash.slice(escapedBackslash.length / 2);
130
+ if (newValue.includes('\\')) {
131
+ // The vast majority of localized strings do not contain `\\`, so this check avoids an allocation.
132
+ // Replace backslashes with the properly escaped backslash
133
+ BACKSLASH_REGEX.lastIndex = -1;
134
+ newValue = newValue.replace(BACKSLASH_REGEX, escapedBackslash);
135
+ }
135
136
  // Ensure the the quotemark, apostrophe, tab, and newline characters are properly escaped
136
137
  ESCAPE_REGEX.lastIndex = -1;
137
- newValue = newValue.replace(ESCAPE_REGEX, (match) => `${escapingCharacterSequence}${ESCAPE_MAP.get(match)}`);
138
+ if (ESCAPE_REGEX.test(newValue)) {
139
+ // The majority of localized strings do not contain the characters that need to be escaped,
140
+ // so this check avoids an allocation.
141
+ // @todo: look into using JSON.parse(...) to get the escaping characters
142
+ const escapingCharacterSequence = escapedBackslash.slice(escapedBackslash.length / 2);
143
+ newValue = newValue.replace(ESCAPE_REGEX, (match) => `${escapingCharacterSequence}${ESCAPE_MAP.get(match)}`);
144
+ }
138
145
  result.replace(element.start, element.end - 1, newValue);
139
146
  break;
140
147
  }
@@ -177,9 +184,7 @@ function _parseStringToReconstructionSequence(plugin, source, formatLocaleForFil
177
184
  const issues = [];
178
185
  const reconstructionSeries = [];
179
186
  const jsonStringifyFormatLocaleForFilenameFn = (locale) => JSON.stringify(formatLocaleForFilenameFn(locale));
180
- let regexResult;
181
- exports.PLACEHOLDER_REGEX.lastIndex = -1;
182
- while ((regexResult = exports.PLACEHOLDER_REGEX.exec(source))) {
187
+ for (const regexResult of source.matchAll(exports.PLACEHOLDER_REGEX)) {
183
188
  const [placeholder, escapedBackslash, elementLabel, placeholderSerialNumber] = regexResult;
184
189
  const start = regexResult.index;
185
190
  const end = start + placeholder.length;
@@ -1 +1 @@
1
- {"version":3,"file":"AssetProcessor.js","sourceRoot":"","sources":["../src/AssetProcessor.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.\n// See LICENSE in the project root for license information.\n\nimport type { Asset, AssetInfo, Chunk, Compilation, sources } from 'webpack';\n\nimport * as Constants from './utilities/Constants';\nimport type { LocalizationPlugin, IStringPlaceholder } from './LocalizationPlugin';\nimport type { ILocalizedWebpackChunk, IAssetPathOptions } from './webpackInterfaces';\n\ninterface ILocalizedReconstructionElement {\n kind: 'localized';\n start: number;\n end: number;\n escapedBackslash: string;\n data: IStringPlaceholder;\n}\n\ninterface IDynamicReconstructionElement {\n kind: 'dynamic';\n start: number;\n end: number;\n escapedBackslash: string;\n valueFn: (locale: string) => string;\n}\n\ntype IReconstructionElement = ILocalizedReconstructionElement | IDynamicReconstructionElement;\ntype FormatLocaleForFilenameFn = (locale: string) => string;\n\ninterface IParseResult {\n issues: string[];\n reconstructionSeries: IReconstructionElement[];\n}\n\ninterface ILocalizedReconstructionResult {\n result: sources.ReplaceSource;\n issues: string[];\n}\n\ninterface INonLocalizedReconstructionResult {\n result: sources.ReplaceSource;\n issues: string[];\n}\n\nexport interface IProcessAssetOptionsBase {\n plugin: LocalizationPlugin;\n compilation: Compilation;\n chunk: Chunk;\n asset: Asset;\n}\n\nexport interface IProcessNonLocalizedAssetOptions extends IProcessAssetOptionsBase {\n fileName: string;\n noStringsLocaleName: string;\n formatLocaleForFilenameFn: FormatLocaleForFilenameFn;\n}\n\nexport interface IProcessLocalizedAssetOptions extends IProcessAssetOptionsBase {\n locales: Set<string>;\n fillMissingTranslationStrings: boolean;\n defaultLocale: string;\n filenameTemplate: Parameters<typeof Compilation.prototype.getAssetPath>[0];\n formatLocaleForFilenameFn: FormatLocaleForFilenameFn;\n}\n\nexport interface IProcessAssetResult {\n filename: string;\n asset: sources.Source;\n}\n\nexport const PLACEHOLDER_REGEX: RegExp = new RegExp(\n `${Constants.STRING_PLACEHOLDER_PREFIX}_(\\\\\\\\*)_([A-C])_([0-9a-f]+)`,\n 'g'\n);\n\nexport function processLocalizedAsset(options: IProcessLocalizedAssetOptions): Record<string, string> {\n const { compilation, asset, chunk, filenameTemplate, locales, formatLocaleForFilenameFn } = options;\n\n const { sources, WebpackError } = compilation.compiler.webpack;\n\n const rawSource: sources.CachedSource = new sources.CachedSource(asset.source);\n const assetSource: string = rawSource.source().toString();\n\n const parsedAsset: IParseResult = _parseStringToReconstructionSequence(\n options.plugin,\n assetSource,\n formatLocaleForFilenameFn\n );\n\n const { issues } = parsedAsset;\n\n const localizedFiles: Record<string, string> = {};\n (chunk as ILocalizedWebpackChunk).localizedFiles = localizedFiles;\n\n const { info: originInfo, name: originName } = asset;\n if (!originInfo.related) {\n originInfo.related = {};\n }\n\n for (const locale of locales) {\n const { issues: localeIssues, result: localeResult } = _reconstructLocalized(\n new sources.ReplaceSource(rawSource, locale),\n parsedAsset.reconstructionSeries,\n locale,\n options.fillMissingTranslationStrings ? options.defaultLocale : undefined\n );\n\n for (const issue of localeIssues) {\n issues.push(issue);\n }\n\n const data: IAssetPathOptions = {\n chunk,\n contentHashType: 'javascript',\n // The locale property will get processed by the extension to the getAssetPath hook\n locale\n };\n\n const fileName: string = compilation.getAssetPath(filenameTemplate, data);\n\n originInfo.related[locale] = fileName;\n\n const info: AssetInfo = {\n ...originInfo,\n locale\n };\n\n const wrapped: sources.CachedSource = new sources.CachedSource(localeResult);\n localizedFiles[locale] = fileName;\n\n // If file already exists\n if (originName === fileName) {\n // This helper throws if the asset doesn't already exist\n compilation.updateAsset(fileName, wrapped, info);\n } else {\n // This helper throws if the asset already exists\n compilation.emitAsset(fileName, wrapped, info);\n }\n }\n\n if (issues.length > 0) {\n compilation.errors.push(\n new WebpackError(`localization:\\n${issues.map((issue) => ` ${issue}`).join('\\n')}`)\n );\n }\n\n return localizedFiles;\n}\n\nexport function processNonLocalizedAsset(options: IProcessNonLocalizedAssetOptions): void {\n const { asset, fileName, compilation, formatLocaleForFilenameFn } = options;\n\n const { sources, WebpackError } = compilation.compiler.webpack;\n\n const rawSource: sources.CachedSource = new sources.CachedSource(asset.source);\n const assetSource: string = rawSource.source().toString();\n\n const parsedAsset: IParseResult = _parseStringToReconstructionSequence(\n options.plugin,\n assetSource,\n formatLocaleForFilenameFn\n );\n\n const { info: originInfo } = asset;\n const { issues } = parsedAsset;\n\n const locale: string = options.noStringsLocaleName;\n const { issues: localeIssues, result } = _reconstructNonLocalized(\n new sources.ReplaceSource(rawSource, locale),\n parsedAsset.reconstructionSeries,\n locale\n );\n\n for (const issue of localeIssues) {\n issues.push(issue);\n }\n\n const info: AssetInfo = {\n ...originInfo,\n locale\n };\n\n const wrapped: sources.CachedSource = new sources.CachedSource(result);\n compilation.updateAsset(fileName, wrapped, info);\n\n if (issues.length > 0) {\n options.compilation.errors.push(\n new WebpackError(`localization:\\n${issues.map((issue) => ` ${issue}`).join('\\n')}`)\n );\n }\n}\n\nconst ESCAPE_MAP: Map<string, string> = new Map([\n ['\\r', 'r'],\n ['\\n', 'n'],\n ['\\t', 't'],\n ['\"', 'u0022'],\n [\"'\", 'u0027']\n]);\n\nconst BACKSLASH_REGEX: RegExp = /\\\\/g;\nconst ESCAPE_REGEX: RegExp = /[\\r\\n\\t\"']/g;\n\nfunction _reconstructLocalized(\n result: sources.ReplaceSource,\n reconstructionSeries: IReconstructionElement[],\n locale: string,\n fallbackLocale: string | undefined\n): ILocalizedReconstructionResult {\n const issues: string[] = [];\n\n for (const element of reconstructionSeries) {\n switch (element.kind) {\n case 'localized': {\n const { data } = element;\n let newValue: string | undefined = data.valuesByLocale.get(locale);\n if (newValue === undefined) {\n if (fallbackLocale) {\n newValue = data.valuesByLocale.get(fallbackLocale)!;\n } else {\n issues.push(\n `The string \"${data.stringName}\" in \"${data.locFilePath}\" is missing in ` +\n `the locale ${locale}`\n );\n\n newValue = '-- MISSING STRING --';\n }\n }\n\n const escapedBackslash: string = element.escapedBackslash || '\\\\';\n\n // Replace backslashes with the properly escaped backslash\n BACKSLASH_REGEX.lastIndex = -1;\n newValue = newValue.replace(BACKSLASH_REGEX, escapedBackslash);\n\n // @todo: look into using JSON.parse(...) to get the escaping characters\n const escapingCharacterSequence: string = escapedBackslash.slice(escapedBackslash.length / 2);\n\n // Ensure the the quotemark, apostrophe, tab, and newline characters are properly escaped\n ESCAPE_REGEX.lastIndex = -1;\n newValue = newValue.replace(\n ESCAPE_REGEX,\n (match) => `${escapingCharacterSequence}${ESCAPE_MAP.get(match)}`\n );\n\n result.replace(element.start, element.end - 1, newValue);\n break;\n }\n\n case 'dynamic': {\n const newValue: string = element.valueFn(locale);\n result.replace(element.start, element.end - 1, newValue);\n break;\n }\n }\n }\n\n return {\n issues,\n result\n };\n}\n\nfunction _reconstructNonLocalized(\n result: sources.ReplaceSource,\n reconstructionSeries: IReconstructionElement[],\n noStringsLocaleName: string\n): INonLocalizedReconstructionResult {\n const issues: string[] = [];\n\n for (const element of reconstructionSeries) {\n switch (element.kind) {\n case 'localized': {\n issues.push(\n `The string \"${element.data.stringName}\" in \"${element.data.locFilePath}\" appeared in an asset ` +\n 'that is not expected to contain localized resources.'\n );\n\n const newValue: string = '-- NOT EXPECTED TO BE LOCALIZED --';\n result.replace(element.start, element.end - 1, newValue);\n break;\n }\n\n case 'dynamic': {\n const newValue: string = element.valueFn(noStringsLocaleName);\n result.replace(element.start, element.end - 1, newValue);\n break;\n }\n }\n }\n\n return {\n issues,\n result\n };\n}\n\nfunction _parseStringToReconstructionSequence(\n plugin: LocalizationPlugin,\n source: string,\n formatLocaleForFilenameFn: FormatLocaleForFilenameFn\n): IParseResult {\n const issues: string[] = [];\n const reconstructionSeries: IReconstructionElement[] = [];\n\n const jsonStringifyFormatLocaleForFilenameFn: FormatLocaleForFilenameFn = (locale: string) =>\n JSON.stringify(formatLocaleForFilenameFn(locale));\n\n let regexResult: RegExpExecArray | null;\n PLACEHOLDER_REGEX.lastIndex = -1;\n while ((regexResult = PLACEHOLDER_REGEX.exec(source))) {\n const [placeholder, escapedBackslash, elementLabel, placeholderSerialNumber] = regexResult;\n const start: number = regexResult.index;\n const end: number = start + placeholder.length;\n\n let localizedReconstructionElement: IReconstructionElement;\n switch (elementLabel) {\n case Constants.STRING_PLACEHOLDER_LABEL: {\n const stringData: IStringPlaceholder | undefined =\n plugin.getDataForSerialNumber(placeholderSerialNumber);\n if (!stringData) {\n issues.push(`Missing placeholder ${placeholder}`);\n continue;\n } else {\n const localizedElement: ILocalizedReconstructionElement = {\n kind: 'localized',\n start,\n end,\n escapedBackslash,\n data: stringData\n };\n localizedReconstructionElement = localizedElement;\n }\n break;\n }\n\n case Constants.LOCALE_NAME_PLACEHOLDER_LABEL: {\n const dynamicElement: IDynamicReconstructionElement = {\n kind: 'dynamic',\n start,\n end,\n escapedBackslash,\n valueFn: formatLocaleForFilenameFn\n };\n localizedReconstructionElement = dynamicElement;\n break;\n }\n\n case Constants.JSONP_PLACEHOLDER_LABEL: {\n const dynamicElement: IDynamicReconstructionElement = {\n kind: 'dynamic',\n start,\n end,\n escapedBackslash,\n valueFn: jsonStringifyFormatLocaleForFilenameFn\n };\n localizedReconstructionElement = dynamicElement;\n break;\n }\n\n default: {\n throw new Error(`Unexpected label ${elementLabel}`);\n }\n }\n\n reconstructionSeries.push(localizedReconstructionElement);\n }\n\n return {\n issues,\n reconstructionSeries\n };\n}\n"]}
1
+ {"version":3,"file":"AssetProcessor.js","sourceRoot":"","sources":["../src/AssetProcessor.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.\n// See LICENSE in the project root for license information.\n\nimport type { Asset, AssetInfo, Chunk, Compilation, sources } from 'webpack';\n\nimport * as Constants from './utilities/Constants';\nimport type { LocalizationPlugin, IStringPlaceholder } from './LocalizationPlugin';\nimport type { ILocalizedWebpackChunk, IAssetPathOptions } from './webpackInterfaces';\n\ninterface ILocalizedReconstructionElement {\n kind: 'localized';\n start: number;\n end: number;\n escapedBackslash: string;\n data: IStringPlaceholder;\n}\n\ninterface IDynamicReconstructionElement {\n kind: 'dynamic';\n start: number;\n end: number;\n escapedBackslash: string;\n valueFn: (locale: string) => string;\n}\n\ntype IReconstructionElement = ILocalizedReconstructionElement | IDynamicReconstructionElement;\ntype FormatLocaleForFilenameFn = (locale: string) => string;\n\ninterface IParseResult {\n issues: string[];\n reconstructionSeries: IReconstructionElement[];\n}\n\ninterface ILocalizedReconstructionResult {\n result: sources.ReplaceSource;\n issues: string[];\n}\n\ninterface INonLocalizedReconstructionResult {\n result: sources.ReplaceSource;\n issues: string[];\n}\n\nexport interface IProcessAssetOptionsBase {\n plugin: LocalizationPlugin;\n compilation: Compilation;\n chunk: Chunk;\n asset: Asset;\n}\n\nexport interface IProcessNonLocalizedAssetOptions extends IProcessAssetOptionsBase {\n fileName: string;\n noStringsLocaleName: string;\n formatLocaleForFilenameFn: FormatLocaleForFilenameFn;\n}\n\nexport interface IProcessLocalizedAssetOptions extends IProcessAssetOptionsBase {\n locales: Set<string>;\n fillMissingTranslationStrings: boolean;\n defaultLocale: string;\n filenameTemplate: Parameters<typeof Compilation.prototype.getAssetPath>[0];\n formatLocaleForFilenameFn: FormatLocaleForFilenameFn;\n}\n\nexport interface IProcessAssetResult {\n filename: string;\n asset: sources.Source;\n}\n\nexport const PLACEHOLDER_REGEX: RegExp = new RegExp(\n `${Constants.STRING_PLACEHOLDER_PREFIX}_(\\\\\\\\*)_([A-C])_([0-9a-f]+)`,\n 'g'\n);\n\nexport function processLocalizedAsset(options: IProcessLocalizedAssetOptions): Record<string, string> {\n const { compilation, asset, chunk, filenameTemplate, locales, formatLocaleForFilenameFn } = options;\n\n const { sources, WebpackError } = compilation.compiler.webpack;\n\n const rawSource: sources.CachedSource = new sources.CachedSource(asset.source);\n const assetSource: string = rawSource.source().toString();\n\n const parsedAsset: IParseResult = _parseStringToReconstructionSequence(\n options.plugin,\n assetSource,\n formatLocaleForFilenameFn\n );\n\n const { issues } = parsedAsset;\n\n const localizedFiles: Record<string, string> = {};\n (chunk as ILocalizedWebpackChunk).localizedFiles = localizedFiles;\n\n const { info: originInfo, name: originName } = asset;\n if (!originInfo.related) {\n originInfo.related = {};\n }\n\n for (const locale of locales) {\n const { issues: localeIssues, result: localeResult } = _reconstructLocalized(\n new sources.ReplaceSource(rawSource, locale),\n parsedAsset.reconstructionSeries,\n locale,\n options.fillMissingTranslationStrings ? options.defaultLocale : undefined\n );\n\n for (const issue of localeIssues) {\n issues.push(issue);\n }\n\n const data: IAssetPathOptions = {\n chunk,\n contentHashType: 'javascript',\n // The locale property will get processed by the extension to the getAssetPath hook\n locale\n };\n\n const fileName: string = compilation.getAssetPath(filenameTemplate, data);\n\n originInfo.related[locale] = fileName;\n\n const info: AssetInfo = {\n ...originInfo,\n locale\n };\n\n const wrapped: sources.CachedSource = new sources.CachedSource(localeResult);\n localizedFiles[locale] = fileName;\n\n // If file already exists\n if (originName === fileName) {\n // This helper throws if the asset doesn't already exist\n compilation.updateAsset(fileName, wrapped, info);\n } else {\n // This helper throws if the asset already exists\n compilation.emitAsset(fileName, wrapped, info);\n }\n }\n\n if (issues.length > 0) {\n compilation.errors.push(\n new WebpackError(`localization:\\n${issues.map((issue) => ` ${issue}`).join('\\n')}`)\n );\n }\n\n return localizedFiles;\n}\n\nexport function processNonLocalizedAsset(options: IProcessNonLocalizedAssetOptions): void {\n const { asset, fileName, compilation, formatLocaleForFilenameFn } = options;\n\n const { sources, WebpackError } = compilation.compiler.webpack;\n\n const rawSource: sources.CachedSource = new sources.CachedSource(asset.source);\n const assetSource: string = rawSource.source().toString();\n\n const parsedAsset: IParseResult = _parseStringToReconstructionSequence(\n options.plugin,\n assetSource,\n formatLocaleForFilenameFn\n );\n\n const { info: originInfo } = asset;\n const { issues } = parsedAsset;\n\n const locale: string = options.noStringsLocaleName;\n const { issues: localeIssues, result } = _reconstructNonLocalized(\n new sources.ReplaceSource(rawSource, locale),\n parsedAsset.reconstructionSeries,\n locale\n );\n\n for (const issue of localeIssues) {\n issues.push(issue);\n }\n\n const info: AssetInfo = {\n ...originInfo,\n locale\n };\n\n const wrapped: sources.CachedSource = new sources.CachedSource(result);\n compilation.updateAsset(fileName, wrapped, info);\n\n if (issues.length > 0) {\n options.compilation.errors.push(\n new WebpackError(`localization:\\n${issues.map((issue) => ` ${issue}`).join('\\n')}`)\n );\n }\n}\n\nconst ESCAPE_MAP: Map<string, string> = new Map([\n ['\\r', 'r'],\n ['\\n', 'n'],\n ['\\t', 't'],\n ['\"', 'u0022'],\n [\"'\", 'u0027']\n]);\n\nconst BACKSLASH_REGEX: RegExp = /\\\\/g;\nconst ESCAPE_REGEX: RegExp = /[\\r\\n\\t\"']/g;\n\nfunction _reconstructLocalized(\n result: sources.ReplaceSource,\n reconstructionSeries: IReconstructionElement[],\n locale: string,\n fallbackLocale: string | undefined\n): ILocalizedReconstructionResult {\n const issues: string[] = [];\n\n for (const element of reconstructionSeries) {\n switch (element.kind) {\n case 'localized': {\n const { data } = element;\n let newValue: string | undefined = data.valuesByLocale.get(locale);\n if (newValue === undefined) {\n if (fallbackLocale) {\n newValue = data.valuesByLocale.get(fallbackLocale)!;\n } else {\n issues.push(\n `The string \"${data.stringName}\" in \"${data.locFilePath}\" is missing in ` +\n `the locale ${locale}`\n );\n\n newValue = '-- MISSING STRING --';\n }\n }\n\n const escapedBackslash: string = element.escapedBackslash || '\\\\';\n\n if (newValue.includes('\\\\')) {\n // The vast majority of localized strings do not contain `\\\\`, so this check avoids an allocation.\n // Replace backslashes with the properly escaped backslash\n BACKSLASH_REGEX.lastIndex = -1;\n newValue = newValue.replace(BACKSLASH_REGEX, escapedBackslash);\n }\n\n // Ensure the the quotemark, apostrophe, tab, and newline characters are properly escaped\n ESCAPE_REGEX.lastIndex = -1;\n if (ESCAPE_REGEX.test(newValue)) {\n // The majority of localized strings do not contain the characters that need to be escaped,\n // so this check avoids an allocation.\n // @todo: look into using JSON.parse(...) to get the escaping characters\n const escapingCharacterSequence: string = escapedBackslash.slice(escapedBackslash.length / 2);\n newValue = newValue.replace(\n ESCAPE_REGEX,\n (match) => `${escapingCharacterSequence}${ESCAPE_MAP.get(match)}`\n );\n }\n\n result.replace(element.start, element.end - 1, newValue);\n break;\n }\n\n case 'dynamic': {\n const newValue: string = element.valueFn(locale);\n result.replace(element.start, element.end - 1, newValue);\n break;\n }\n }\n }\n\n return {\n issues,\n result\n };\n}\n\nfunction _reconstructNonLocalized(\n result: sources.ReplaceSource,\n reconstructionSeries: IReconstructionElement[],\n noStringsLocaleName: string\n): INonLocalizedReconstructionResult {\n const issues: string[] = [];\n\n for (const element of reconstructionSeries) {\n switch (element.kind) {\n case 'localized': {\n issues.push(\n `The string \"${element.data.stringName}\" in \"${element.data.locFilePath}\" appeared in an asset ` +\n 'that is not expected to contain localized resources.'\n );\n\n const newValue: string = '-- NOT EXPECTED TO BE LOCALIZED --';\n result.replace(element.start, element.end - 1, newValue);\n break;\n }\n\n case 'dynamic': {\n const newValue: string = element.valueFn(noStringsLocaleName);\n result.replace(element.start, element.end - 1, newValue);\n break;\n }\n }\n }\n\n return {\n issues,\n result\n };\n}\n\nfunction _parseStringToReconstructionSequence(\n plugin: LocalizationPlugin,\n source: string,\n formatLocaleForFilenameFn: FormatLocaleForFilenameFn\n): IParseResult {\n const issues: string[] = [];\n const reconstructionSeries: IReconstructionElement[] = [];\n\n const jsonStringifyFormatLocaleForFilenameFn: FormatLocaleForFilenameFn = (locale: string) =>\n JSON.stringify(formatLocaleForFilenameFn(locale));\n\n for (const regexResult of source.matchAll(PLACEHOLDER_REGEX)) {\n const [placeholder, escapedBackslash, elementLabel, placeholderSerialNumber] = regexResult;\n const start: number = regexResult.index;\n const end: number = start + placeholder.length;\n\n let localizedReconstructionElement: IReconstructionElement;\n switch (elementLabel) {\n case Constants.STRING_PLACEHOLDER_LABEL: {\n const stringData: IStringPlaceholder | undefined =\n plugin.getDataForSerialNumber(placeholderSerialNumber);\n if (!stringData) {\n issues.push(`Missing placeholder ${placeholder}`);\n continue;\n } else {\n const localizedElement: ILocalizedReconstructionElement = {\n kind: 'localized',\n start,\n end,\n escapedBackslash,\n data: stringData\n };\n localizedReconstructionElement = localizedElement;\n }\n break;\n }\n\n case Constants.LOCALE_NAME_PLACEHOLDER_LABEL: {\n const dynamicElement: IDynamicReconstructionElement = {\n kind: 'dynamic',\n start,\n end,\n escapedBackslash,\n valueFn: formatLocaleForFilenameFn\n };\n localizedReconstructionElement = dynamicElement;\n break;\n }\n\n case Constants.JSONP_PLACEHOLDER_LABEL: {\n const dynamicElement: IDynamicReconstructionElement = {\n kind: 'dynamic',\n start,\n end,\n escapedBackslash,\n valueFn: jsonStringifyFormatLocaleForFilenameFn\n };\n localizedReconstructionElement = dynamicElement;\n break;\n }\n\n default: {\n throw new Error(`Unexpected label ${elementLabel}`);\n }\n }\n\n reconstructionSeries.push(localizedReconstructionElement);\n }\n\n return {\n issues,\n reconstructionSeries\n };\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rushstack/webpack5-localization-plugin",
3
- "version": "0.11.1",
3
+ "version": "0.11.2",
4
4
  "description": "This plugin facilitates localization with Webpack.",
5
5
  "main": "lib/index.js",
6
6
  "typings": "dist/webpack5-localization-plugin.d.ts",
@@ -15,15 +15,15 @@
15
15
  "@types/node": "*"
16
16
  },
17
17
  "dependencies": {
18
- "@rushstack/node-core-library": "5.5.1",
19
18
  "@rushstack/localization-utilities": "0.9.62",
19
+ "@rushstack/node-core-library": "5.5.1",
20
20
  "@rushstack/terminal": "0.13.3"
21
21
  },
22
22
  "devDependencies": {
23
23
  "memfs": "3.4.3",
24
24
  "webpack": "~5.82.1",
25
- "local-node-rig": "1.0.0",
26
- "@rushstack/heft": "0.66.25"
25
+ "@rushstack/heft": "0.66.25",
26
+ "local-node-rig": "1.0.0"
27
27
  },
28
28
  "peerDependenciesMeta": {
29
29
  "@types/node": {