@rushstack/webpack5-localization-plugin 0.11.0 → 0.11.2

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/CHANGELOG.json CHANGED
@@ -1,6 +1,33 @@
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
+ },
16
+ {
17
+ "version": "0.11.1",
18
+ "tag": "@rushstack/webpack5-localization-plugin_v0.11.1",
19
+ "date": "Fri, 02 Aug 2024 17:26:42 GMT",
20
+ "comments": {
21
+ "dependency": [
22
+ {
23
+ "comment": "Updating dependency \"@rushstack/localization-utilities\" to `0.9.62`"
24
+ },
25
+ {
26
+ "comment": "Updating dependency \"@rushstack/heft\" to `0.66.25`"
27
+ }
28
+ ]
29
+ }
30
+ },
4
31
  {
5
32
  "version": "0.11.0",
6
33
  "tag": "@rushstack/webpack5-localization-plugin_v0.11.0",
package/CHANGELOG.md CHANGED
@@ -1,6 +1,18 @@
1
1
  # Change Log - @rushstack/webpack5-localization-plugin
2
2
 
3
- This log was last generated on Wed, 31 Jul 2024 00:10:53 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.
11
+
12
+ ## 0.11.1
13
+ Fri, 02 Aug 2024 17:26:42 GMT
14
+
15
+ _Version update only_
4
16
 
5
17
  ## 0.11.0
6
18
  Wed, 31 Jul 2024 00:10:53 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.0",
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/localization-utilities": "0.9.61",
19
- "@rushstack/terminal": "0.13.3",
20
- "@rushstack/node-core-library": "5.5.1"
18
+ "@rushstack/localization-utilities": "0.9.62",
19
+ "@rushstack/node-core-library": "5.5.1",
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.24"
25
+ "@rushstack/heft": "0.66.25",
26
+ "local-node-rig": "1.0.0"
27
27
  },
28
28
  "peerDependenciesMeta": {
29
29
  "@types/node": {