@rushstack/webpack5-localization-plugin 0.15.14 → 0.16.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (112) hide show
  1. package/CHANGELOG.json +52 -0
  2. package/CHANGELOG.md +15 -1
  3. package/dist/tsdoc-metadata.json +1 -1
  4. package/lib-esm/AssetProcessor.js +306 -0
  5. package/lib-esm/AssetProcessor.js.map +1 -0
  6. package/lib-esm/LocalizationPlugin.js +636 -0
  7. package/lib-esm/LocalizationPlugin.js.map +1 -0
  8. package/lib-esm/TrueHashPlugin.js +27 -0
  9. package/lib-esm/TrueHashPlugin.js.map +1 -0
  10. package/lib-esm/index.js +6 -0
  11. package/lib-esm/index.js.map +1 -0
  12. package/lib-esm/interfaces.js +4 -0
  13. package/lib-esm/interfaces.js.map +1 -0
  14. package/lib-esm/loaders/IResxLoaderOptions.js +4 -0
  15. package/lib-esm/loaders/IResxLoaderOptions.js.map +1 -0
  16. package/lib-esm/loaders/LoaderFactory.js +25 -0
  17. package/lib-esm/loaders/LoaderFactory.js.map +1 -0
  18. package/lib-esm/loaders/default-locale-loader.js +25 -0
  19. package/lib-esm/loaders/default-locale-loader.js.map +1 -0
  20. package/lib-esm/loaders/loc-loader.js +21 -0
  21. package/lib-esm/loaders/loc-loader.js.map +1 -0
  22. package/lib-esm/loaders/locjson-loader.js +13 -0
  23. package/lib-esm/loaders/locjson-loader.js.map +1 -0
  24. package/lib-esm/loaders/resjson-loader.js +13 -0
  25. package/lib-esm/loaders/resjson-loader.js.map +1 -0
  26. package/lib-esm/loaders/resx-loader.js +20 -0
  27. package/lib-esm/loaders/resx-loader.js.map +1 -0
  28. package/lib-esm/trueHashes.js +213 -0
  29. package/lib-esm/trueHashes.js.map +1 -0
  30. package/lib-esm/utilities/Constants.js +17 -0
  31. package/lib-esm/utilities/Constants.js.map +1 -0
  32. package/lib-esm/utilities/EntityMarker.js +16 -0
  33. package/lib-esm/utilities/EntityMarker.js.map +1 -0
  34. package/lib-esm/utilities/LoaderTerminalProvider.js +24 -0
  35. package/lib-esm/utilities/LoaderTerminalProvider.js.map +1 -0
  36. package/lib-esm/utilities/chunkUtilities.js +6 -0
  37. package/lib-esm/utilities/chunkUtilities.js.map +1 -0
  38. package/lib-esm/webpackInterfaces.js +4 -0
  39. package/lib-esm/webpackInterfaces.js.map +1 -0
  40. package/package.json +33 -9
  41. /package/{lib → lib-commonjs}/AssetProcessor.js +0 -0
  42. /package/{lib → lib-commonjs}/AssetProcessor.js.map +0 -0
  43. /package/{lib → lib-commonjs}/LocalizationPlugin.js +0 -0
  44. /package/{lib → lib-commonjs}/LocalizationPlugin.js.map +0 -0
  45. /package/{lib → lib-commonjs}/TrueHashPlugin.js +0 -0
  46. /package/{lib → lib-commonjs}/TrueHashPlugin.js.map +0 -0
  47. /package/{lib → lib-commonjs}/index.js +0 -0
  48. /package/{lib → lib-commonjs}/index.js.map +0 -0
  49. /package/{lib → lib-commonjs}/interfaces.js +0 -0
  50. /package/{lib → lib-commonjs}/interfaces.js.map +0 -0
  51. /package/{lib → lib-commonjs}/loaders/IResxLoaderOptions.js +0 -0
  52. /package/{lib → lib-commonjs}/loaders/IResxLoaderOptions.js.map +0 -0
  53. /package/{lib → lib-commonjs}/loaders/LoaderFactory.js +0 -0
  54. /package/{lib → lib-commonjs}/loaders/LoaderFactory.js.map +0 -0
  55. /package/{lib → lib-commonjs}/loaders/default-locale-loader.js +0 -0
  56. /package/{lib → lib-commonjs}/loaders/default-locale-loader.js.map +0 -0
  57. /package/{lib → lib-commonjs}/loaders/loc-loader.js +0 -0
  58. /package/{lib → lib-commonjs}/loaders/loc-loader.js.map +0 -0
  59. /package/{lib → lib-commonjs}/loaders/locjson-loader.js +0 -0
  60. /package/{lib → lib-commonjs}/loaders/locjson-loader.js.map +0 -0
  61. /package/{lib → lib-commonjs}/loaders/resjson-loader.js +0 -0
  62. /package/{lib → lib-commonjs}/loaders/resjson-loader.js.map +0 -0
  63. /package/{lib → lib-commonjs}/loaders/resx-loader.js +0 -0
  64. /package/{lib → lib-commonjs}/loaders/resx-loader.js.map +0 -0
  65. /package/{lib → lib-commonjs}/trueHashes.js +0 -0
  66. /package/{lib → lib-commonjs}/trueHashes.js.map +0 -0
  67. /package/{lib → lib-commonjs}/utilities/Constants.js +0 -0
  68. /package/{lib → lib-commonjs}/utilities/Constants.js.map +0 -0
  69. /package/{lib → lib-commonjs}/utilities/EntityMarker.js +0 -0
  70. /package/{lib → lib-commonjs}/utilities/EntityMarker.js.map +0 -0
  71. /package/{lib → lib-commonjs}/utilities/LoaderTerminalProvider.js +0 -0
  72. /package/{lib → lib-commonjs}/utilities/LoaderTerminalProvider.js.map +0 -0
  73. /package/{lib → lib-commonjs}/utilities/chunkUtilities.js +0 -0
  74. /package/{lib → lib-commonjs}/utilities/chunkUtilities.js.map +0 -0
  75. /package/{lib → lib-commonjs}/webpackInterfaces.js +0 -0
  76. /package/{lib → lib-commonjs}/webpackInterfaces.js.map +0 -0
  77. /package/{lib → lib-dts}/AssetProcessor.d.ts +0 -0
  78. /package/{lib → lib-dts}/AssetProcessor.d.ts.map +0 -0
  79. /package/{lib → lib-dts}/LocalizationPlugin.d.ts +0 -0
  80. /package/{lib → lib-dts}/LocalizationPlugin.d.ts.map +0 -0
  81. /package/{lib → lib-dts}/TrueHashPlugin.d.ts +0 -0
  82. /package/{lib → lib-dts}/TrueHashPlugin.d.ts.map +0 -0
  83. /package/{lib → lib-dts}/index.d.ts +0 -0
  84. /package/{lib → lib-dts}/index.d.ts.map +0 -0
  85. /package/{lib → lib-dts}/interfaces.d.ts +0 -0
  86. /package/{lib → lib-dts}/interfaces.d.ts.map +0 -0
  87. /package/{lib → lib-dts}/loaders/IResxLoaderOptions.d.ts +0 -0
  88. /package/{lib → lib-dts}/loaders/IResxLoaderOptions.d.ts.map +0 -0
  89. /package/{lib → lib-dts}/loaders/LoaderFactory.d.ts +0 -0
  90. /package/{lib → lib-dts}/loaders/LoaderFactory.d.ts.map +0 -0
  91. /package/{lib → lib-dts}/loaders/default-locale-loader.d.ts +0 -0
  92. /package/{lib → lib-dts}/loaders/default-locale-loader.d.ts.map +0 -0
  93. /package/{lib → lib-dts}/loaders/loc-loader.d.ts +0 -0
  94. /package/{lib → lib-dts}/loaders/loc-loader.d.ts.map +0 -0
  95. /package/{lib → lib-dts}/loaders/locjson-loader.d.ts +0 -0
  96. /package/{lib → lib-dts}/loaders/locjson-loader.d.ts.map +0 -0
  97. /package/{lib → lib-dts}/loaders/resjson-loader.d.ts +0 -0
  98. /package/{lib → lib-dts}/loaders/resjson-loader.d.ts.map +0 -0
  99. /package/{lib → lib-dts}/loaders/resx-loader.d.ts +0 -0
  100. /package/{lib → lib-dts}/loaders/resx-loader.d.ts.map +0 -0
  101. /package/{lib → lib-dts}/trueHashes.d.ts +0 -0
  102. /package/{lib → lib-dts}/trueHashes.d.ts.map +0 -0
  103. /package/{lib → lib-dts}/utilities/Constants.d.ts +0 -0
  104. /package/{lib → lib-dts}/utilities/Constants.d.ts.map +0 -0
  105. /package/{lib → lib-dts}/utilities/EntityMarker.d.ts +0 -0
  106. /package/{lib → lib-dts}/utilities/EntityMarker.d.ts.map +0 -0
  107. /package/{lib → lib-dts}/utilities/LoaderTerminalProvider.d.ts +0 -0
  108. /package/{lib → lib-dts}/utilities/LoaderTerminalProvider.d.ts.map +0 -0
  109. /package/{lib → lib-dts}/utilities/chunkUtilities.d.ts +0 -0
  110. /package/{lib → lib-dts}/utilities/chunkUtilities.d.ts.map +0 -0
  111. /package/{lib → lib-dts}/webpackInterfaces.d.ts +0 -0
  112. /package/{lib → lib-dts}/webpackInterfaces.d.ts.map +0 -0
package/CHANGELOG.json CHANGED
@@ -1,6 +1,58 @@
1
1
  {
2
2
  "name": "@rushstack/webpack5-localization-plugin",
3
3
  "entries": [
4
+ {
5
+ "version": "0.16.1",
6
+ "tag": "@rushstack/webpack5-localization-plugin_v0.16.1",
7
+ "date": "Fri, 20 Feb 2026 00:15:04 GMT",
8
+ "comments": {
9
+ "patch": [
10
+ {
11
+ "comment": "Add `\"node\"` condition before `\"import\"` in the `\"exports\"` map so that Node.js uses the CJS output (which handles extensionless imports), while bundlers still use ESM via `\"import\"`. Fixes https://github.com/microsoft/rushstack/issues/5644."
12
+ }
13
+ ],
14
+ "dependency": [
15
+ {
16
+ "comment": "Updating dependency \"@rushstack/localization-utilities\" to `0.15.1`"
17
+ },
18
+ {
19
+ "comment": "Updating dependency \"@rushstack/node-core-library\" to `5.20.1`"
20
+ },
21
+ {
22
+ "comment": "Updating dependency \"@rushstack/terminal\" to `0.22.1`"
23
+ },
24
+ {
25
+ "comment": "Updating dependency \"@rushstack/heft\" to `1.2.1`"
26
+ }
27
+ ]
28
+ }
29
+ },
30
+ {
31
+ "version": "0.16.0",
32
+ "tag": "@rushstack/webpack5-localization-plugin_v0.16.0",
33
+ "date": "Thu, 19 Feb 2026 00:04:53 GMT",
34
+ "comments": {
35
+ "minor": [
36
+ {
37
+ "comment": "Normalize package layout. CommonJS is now under `lib-commonjs`, DTS is now under `lib-dts`, and ESM is now under `lib-esm`. Imports to `lib` still work as before, handled by the `\"exports\"` field in `package.json`."
38
+ }
39
+ ],
40
+ "dependency": [
41
+ {
42
+ "comment": "Updating dependency \"@rushstack/localization-utilities\" to `0.15.0`"
43
+ },
44
+ {
45
+ "comment": "Updating dependency \"@rushstack/node-core-library\" to `5.20.0`"
46
+ },
47
+ {
48
+ "comment": "Updating dependency \"@rushstack/terminal\" to `0.22.0`"
49
+ },
50
+ {
51
+ "comment": "Updating dependency \"@rushstack/heft\" to `1.2.0`"
52
+ }
53
+ ]
54
+ }
55
+ },
4
56
  {
5
57
  "version": "0.15.14",
6
58
  "tag": "@rushstack/webpack5-localization-plugin_v0.15.14",
package/CHANGELOG.md CHANGED
@@ -1,6 +1,20 @@
1
1
  # Change Log - @rushstack/webpack5-localization-plugin
2
2
 
3
- This log was last generated on Sat, 07 Feb 2026 01:13:26 GMT and should not be manually modified.
3
+ This log was last generated on Fri, 20 Feb 2026 00:15:04 GMT and should not be manually modified.
4
+
5
+ ## 0.16.1
6
+ Fri, 20 Feb 2026 00:15:04 GMT
7
+
8
+ ### Patches
9
+
10
+ - Add `"node"` condition before `"import"` in the `"exports"` map so that Node.js uses the CJS output (which handles extensionless imports), while bundlers still use ESM via `"import"`. Fixes https://github.com/microsoft/rushstack/issues/5644.
11
+
12
+ ## 0.16.0
13
+ Thu, 19 Feb 2026 00:04:53 GMT
14
+
15
+ ### Minor changes
16
+
17
+ - Normalize package layout. CommonJS is now under `lib-commonjs`, DTS is now under `lib-dts`, and ESM is now under `lib-esm`. Imports to `lib` still work as before, handled by the `"exports"` field in `package.json`.
4
18
 
5
19
  ## 0.15.14
6
20
  Sat, 07 Feb 2026 01:13:26 GMT
@@ -5,7 +5,7 @@
5
5
  "toolPackages": [
6
6
  {
7
7
  "packageName": "@microsoft/api-extractor",
8
- "packageVersion": "7.56.2"
8
+ "packageVersion": "7.57.0"
9
9
  }
10
10
  ]
11
11
  }
@@ -0,0 +1,306 @@
1
+ // Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.
2
+ // See LICENSE in the project root for license information.
3
+ import * as Constants from './utilities/Constants';
4
+ const LOCALIZED_RECONSTRUCTION_ELEMENT_KIND = 1;
5
+ const DYNAMIC_RECONSTRUCTION_ELEMENT_KIND = 2;
6
+ export async function processLocalizedAssetCachedAsync(options) {
7
+ const { compilation, asset, cache, chunk } = options;
8
+ const { source: originalSource } = asset;
9
+ const eTag = cache.getLazyHashedEtag(originalSource);
10
+ const { name: originName } = asset;
11
+ const cacheItem = cache.getItemCache(originName, eTag);
12
+ let output = await cacheItem.getPromise();
13
+ if (!output) {
14
+ output = processLocalizedAsset(options);
15
+ await cacheItem.storePromise(output);
16
+ }
17
+ const { localizedFiles, processedAssets } = output;
18
+ chunk.localizedFiles = localizedFiles;
19
+ for (const { filename, source, info } of processedAssets) {
20
+ if (originName === filename) {
21
+ // This helper throws if the asset doesn't already exist
22
+ // Use the function form so that the object identity of `related` is preserved.
23
+ // Since we already read the original info, we don't need fancy merge logic.
24
+ compilation.updateAsset(filename, source, () => info);
25
+ }
26
+ else {
27
+ // This helper throws if the asset already exists
28
+ compilation.emitAsset(filename, source, info);
29
+ }
30
+ }
31
+ return localizedFiles;
32
+ }
33
+ export function processLocalizedAsset(options) {
34
+ const { compilation, asset, chunk, filenameTemplate, locales, formatLocaleForFilenameFn, plugin, fillMissingTranslationStrings, defaultLocale, passthroughLocaleName } = options;
35
+ const { sources, WebpackError } = compilation.compiler.webpack;
36
+ const { source: originalSource } = asset;
37
+ const fallbackLocale = fillMissingTranslationStrings ? defaultLocale : undefined;
38
+ const rawSource = originalSource instanceof sources.CachedSource
39
+ ? originalSource
40
+ : new sources.CachedSource(originalSource);
41
+ const assetSource = rawSource.source().toString();
42
+ const parsedAsset = _parseStringToReconstructionSequence(plugin, assetSource, formatLocaleForFilenameFn);
43
+ const { issues } = parsedAsset;
44
+ const localizedFiles = {};
45
+ const processedAssets = [];
46
+ const { info: originInfo, name: originName } = asset;
47
+ if (!originInfo.related) {
48
+ originInfo.related = {};
49
+ }
50
+ for (const locale of locales) {
51
+ const { issues: localeIssues, result: localeResult } = _reconstructLocalized(new sources.ReplaceSource(rawSource, locale), parsedAsset.reconstructionSeries, locale, fallbackLocale, passthroughLocaleName, chunk);
52
+ for (const issue of localeIssues) {
53
+ issues.push(issue);
54
+ }
55
+ const data = {
56
+ chunk,
57
+ contentHashType: 'javascript',
58
+ // The locale property will get processed by the extension to the getAssetPath hook
59
+ locale
60
+ };
61
+ const fileName = compilation.getAssetPath(filenameTemplate, data);
62
+ const info = {
63
+ ...originInfo,
64
+ locale
65
+ };
66
+ const wrapped = new sources.CachedSource(localeResult);
67
+ localizedFiles[locale] = fileName;
68
+ processedAssets.push({
69
+ filename: fileName,
70
+ source: wrapped,
71
+ info
72
+ });
73
+ // If file already exists
74
+ if (originName !== fileName) {
75
+ // If A.related points to B, B.related can't point to A or the stats emitter explodes
76
+ // So just strip the related object for the localized assets
77
+ info.related = undefined;
78
+ // We omit the `related` property that does a self-reference.
79
+ originInfo.related[locale] = fileName;
80
+ }
81
+ }
82
+ if (issues.length > 0) {
83
+ compilation.errors.push(new WebpackError(`localization:\n${issues.map((issue) => ` ${issue}`).join('\n')}`));
84
+ }
85
+ return {
86
+ localizedFiles,
87
+ processedAssets
88
+ };
89
+ }
90
+ export async function processNonLocalizedAssetCachedAsync(options) {
91
+ const { compilation, asset, cache } = options;
92
+ const { source: originalSource } = asset;
93
+ const eTag = cache.getLazyHashedEtag(originalSource);
94
+ const { name: originName } = asset;
95
+ const cacheItem = cache.getItemCache(originName, eTag);
96
+ let output = await cacheItem.getPromise();
97
+ if (!output) {
98
+ output = processNonLocalizedAsset(options);
99
+ await cacheItem.storePromise(output);
100
+ }
101
+ const { filename, source, info } = output;
102
+ compilation.updateAsset(originName, source, info);
103
+ if (originName !== filename) {
104
+ compilation.renameAsset(originName, filename);
105
+ }
106
+ }
107
+ export function processNonLocalizedAsset(options) {
108
+ const { asset, fileName, compilation, formatLocaleForFilenameFn, hasUrlGenerator, chunk } = options;
109
+ const { sources, WebpackError } = compilation.compiler.webpack;
110
+ const rawSource = asset.source;
111
+ let cachedSource = rawSource instanceof sources.CachedSource ? rawSource : new sources.CachedSource(rawSource);
112
+ const { info: originInfo } = asset;
113
+ const locale = options.noStringsLocaleName;
114
+ if (hasUrlGenerator) {
115
+ const assetSource = cachedSource.source().toString();
116
+ const parsedAsset = _parseStringToReconstructionSequence(options.plugin, assetSource, formatLocaleForFilenameFn);
117
+ const { issues } = parsedAsset;
118
+ const { issues: localeIssues, result } = _reconstructNonLocalized(new sources.ReplaceSource(cachedSource, locale), parsedAsset.reconstructionSeries, locale, chunk);
119
+ for (const issue of localeIssues) {
120
+ issues.push(issue);
121
+ }
122
+ if (issues.length > 0) {
123
+ options.compilation.errors.push(new WebpackError(`localization:\n${issues.map((issue) => ` ${issue}`).join('\n')}`));
124
+ }
125
+ cachedSource = new sources.CachedSource(result);
126
+ }
127
+ else {
128
+ // Force the CachedSource to cache the concatenated *string*, so that the subsequent ask for the buffer is fast
129
+ cachedSource.source();
130
+ }
131
+ const info = {
132
+ ...originInfo,
133
+ locale
134
+ };
135
+ return {
136
+ filename: fileName,
137
+ source: cachedSource,
138
+ info
139
+ };
140
+ }
141
+ const ESCAPE_MAP = new Map([
142
+ ['\r', 'r'],
143
+ ['\n', 'n'],
144
+ ['\t', 't'],
145
+ ['"', 'u0022'],
146
+ ["'", 'u0027']
147
+ ]);
148
+ const BACKSLASH_REGEX = /\\/g;
149
+ const ESCAPE_REGEX = /[\r\n\t"']/g;
150
+ function _reconstructLocalized(result, reconstructionSeries, locale, fallbackLocale, passthroughLocale, chunk) {
151
+ var _a, _b;
152
+ const issues = [];
153
+ for (const element of reconstructionSeries) {
154
+ const { kind, start, end } = element;
155
+ switch (kind) {
156
+ case LOCALIZED_RECONSTRUCTION_ELEMENT_KIND: {
157
+ const { data, escapedBackslash } = element;
158
+ const { stringName, translations } = data;
159
+ let newValue = locale === passthroughLocale ? stringName : (_a = translations.get(locale)) === null || _a === void 0 ? void 0 : _a.get(stringName);
160
+ if (fallbackLocale && newValue === undefined) {
161
+ newValue = (_b = translations.get(fallbackLocale)) === null || _b === void 0 ? void 0 : _b.get(stringName);
162
+ }
163
+ if (newValue === undefined) {
164
+ issues.push(`The string "${stringName}" in "${data.locFilePath}" is missing in the locale ${locale}`);
165
+ newValue = '-- MISSING STRING --';
166
+ }
167
+ if (newValue.includes('\\')) {
168
+ // The vast majority of localized strings do not contain `\\`, so this check avoids an allocation.
169
+ // Replace backslashes with the properly escaped backslash
170
+ BACKSLASH_REGEX.lastIndex = -1;
171
+ newValue = newValue.replace(BACKSLASH_REGEX, escapedBackslash);
172
+ }
173
+ // Ensure the the quotemark, apostrophe, tab, and newline characters are properly escaped
174
+ ESCAPE_REGEX.lastIndex = -1;
175
+ if (ESCAPE_REGEX.test(newValue)) {
176
+ // The majority of localized strings do not contain the characters that need to be escaped,
177
+ // so this check avoids an allocation.
178
+ // @todo: look into using JSON.parse(...) to get the escaping characters
179
+ const escapingCharacterSequence = escapedBackslash.slice(escapedBackslash.length / 2);
180
+ newValue = newValue.replace(ESCAPE_REGEX, (match) => `${escapingCharacterSequence}${ESCAPE_MAP.get(match)}`);
181
+ }
182
+ result.replace(start, end - 1, newValue);
183
+ break;
184
+ }
185
+ case DYNAMIC_RECONSTRUCTION_ELEMENT_KIND: {
186
+ const newValue = element.valueFn(locale, chunk);
187
+ result.replace(start, end - 1, newValue);
188
+ break;
189
+ }
190
+ }
191
+ }
192
+ return {
193
+ issues,
194
+ result
195
+ };
196
+ }
197
+ function _reconstructNonLocalized(result, reconstructionSeries, noStringsLocaleName, chunk) {
198
+ const issues = [];
199
+ for (const element of reconstructionSeries) {
200
+ switch (element.kind) {
201
+ case LOCALIZED_RECONSTRUCTION_ELEMENT_KIND: {
202
+ issues.push(`The string "${element.data.stringName}" in "${element.data.locFilePath}" appeared in an asset ` +
203
+ 'that is not expected to contain localized resources.');
204
+ const newValue = '-- NOT EXPECTED TO BE LOCALIZED --';
205
+ result.replace(element.start, element.end - 1, newValue);
206
+ break;
207
+ }
208
+ case DYNAMIC_RECONSTRUCTION_ELEMENT_KIND: {
209
+ const newValue = element.valueFn(noStringsLocaleName, chunk);
210
+ result.replace(element.start, element.end - 1, newValue);
211
+ break;
212
+ }
213
+ }
214
+ }
215
+ return {
216
+ issues,
217
+ result
218
+ };
219
+ }
220
+ function _parseStringToReconstructionSequence(plugin, source, formatLocaleForFilenameFn) {
221
+ const issues = [];
222
+ const reconstructionSeries = [];
223
+ let jsonStringifyFormatLocaleForFilenameFn;
224
+ let index = source.indexOf(Constants.STRING_PLACEHOLDER_PREFIX);
225
+ const increment = Constants.STRING_PLACEHOLDER_PREFIX.length + 1;
226
+ while (index >= 0) {
227
+ const start = index;
228
+ const elementStart = index + increment;
229
+ const elementLabel = source.charAt(elementStart);
230
+ let end = elementStart + 2;
231
+ switch (elementLabel) {
232
+ case Constants.STRING_PLACEHOLDER_LABEL: {
233
+ const backslashEnd = source.indexOf('_', end);
234
+ const escapedBackslash = source.slice(end, backslashEnd) || '\\';
235
+ end = backslashEnd + 1;
236
+ const suffixEnd = source.indexOf('_', end);
237
+ const suffix = source.slice(end, suffixEnd);
238
+ end = suffixEnd + 1;
239
+ const stringData = plugin._getStringDataForSerialNumber(suffix);
240
+ if (!stringData) {
241
+ issues.push(`Missing placeholder ${suffix}`);
242
+ }
243
+ else {
244
+ const localizedElement = {
245
+ kind: LOCALIZED_RECONSTRUCTION_ELEMENT_KIND,
246
+ start,
247
+ end,
248
+ escapedBackslash,
249
+ data: stringData
250
+ };
251
+ reconstructionSeries.push(localizedElement);
252
+ }
253
+ break;
254
+ }
255
+ case Constants.LOCALE_NAME_PLACEHOLDER_LABEL: {
256
+ const dynamicElement = {
257
+ kind: DYNAMIC_RECONSTRUCTION_ELEMENT_KIND,
258
+ start,
259
+ end,
260
+ valueFn: formatLocaleForFilenameFn
261
+ };
262
+ reconstructionSeries.push(dynamicElement);
263
+ break;
264
+ }
265
+ case Constants.JSONP_PLACEHOLDER_LABEL: {
266
+ jsonStringifyFormatLocaleForFilenameFn || (jsonStringifyFormatLocaleForFilenameFn = (locale, chunk) => JSON.stringify(formatLocaleForFilenameFn(locale, chunk)));
267
+ const dynamicElement = {
268
+ kind: DYNAMIC_RECONSTRUCTION_ELEMENT_KIND,
269
+ start,
270
+ end,
271
+ valueFn: jsonStringifyFormatLocaleForFilenameFn
272
+ };
273
+ reconstructionSeries.push(dynamicElement);
274
+ break;
275
+ }
276
+ case Constants.CUSTOM_PLACEHOLDER_LABEL: {
277
+ const serialEnd = source.indexOf('_', end);
278
+ const serial = source.slice(end, serialEnd);
279
+ end = serialEnd + 1;
280
+ const customData = plugin._getCustomDataForSerialNumber(serial);
281
+ if (!customData) {
282
+ issues.push(`Missing custom placeholder ${serial}`);
283
+ }
284
+ else {
285
+ const dynamicElement = {
286
+ kind: DYNAMIC_RECONSTRUCTION_ELEMENT_KIND,
287
+ start,
288
+ end,
289
+ valueFn: customData.valueForLocaleFn
290
+ };
291
+ reconstructionSeries.push(dynamicElement);
292
+ }
293
+ break;
294
+ }
295
+ default: {
296
+ throw new Error(`Unexpected label ${elementLabel} in pattern ${source.slice(start, end)}`);
297
+ }
298
+ }
299
+ index = source.indexOf(Constants.STRING_PLACEHOLDER_PREFIX, end);
300
+ }
301
+ return {
302
+ issues,
303
+ reconstructionSeries
304
+ };
305
+ }
306
+ //# sourceMappingURL=AssetProcessor.js.map
@@ -0,0 +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 {\n LocalizationPlugin,\n IStringPlaceholder,\n ValueForLocaleFn,\n ICustomDataPlaceholder\n} from './LocalizationPlugin';\nimport type { ILocalizedWebpackChunk, IAssetPathOptions } from './webpackInterfaces';\n\nconst LOCALIZED_RECONSTRUCTION_ELEMENT_KIND: 1 = 1;\nconst DYNAMIC_RECONSTRUCTION_ELEMENT_KIND: 2 = 2;\n\ninterface ILocalizedReconstructionElement {\n kind: typeof LOCALIZED_RECONSTRUCTION_ELEMENT_KIND;\n start: number;\n end: number;\n escapedBackslash: string;\n data: IStringPlaceholder;\n}\n\ninterface IDynamicReconstructionElement {\n kind: typeof DYNAMIC_RECONSTRUCTION_ELEMENT_KIND;\n start: number;\n end: number;\n valueFn: ValueForLocaleFn;\n}\n\ntype IReconstructionElement = ILocalizedReconstructionElement | IDynamicReconstructionElement;\n/**\n * @remarks\n * Include the `chunk` parameter so that the functions arity is the same as the\n * `ValueForLocaleFn` type.\n */\ntype FormatLocaleForFilenameFn = (locale: string, chunk: unknown) => 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 cache: ReturnType<Compilation['getCache']>;\n chunk: Chunk;\n asset: Asset;\n}\n\nexport interface IProcessNonLocalizedAssetOptions extends IProcessAssetOptionsBase {\n fileName: string;\n hasUrlGenerator: boolean;\n noStringsLocaleName: string;\n formatLocaleForFilenameFn: FormatLocaleForFilenameFn;\n}\n\nexport interface IProcessLocalizedAssetOptions extends IProcessAssetOptionsBase {\n locales: Set<string>;\n fillMissingTranslationStrings: boolean;\n defaultLocale: string;\n passthroughLocaleName: string | undefined;\n filenameTemplate: Parameters<typeof Compilation.prototype.getAssetPath>[0];\n formatLocaleForFilenameFn: FormatLocaleForFilenameFn;\n}\n\ninterface IProcessedAsset {\n filename: string;\n source: sources.CachedSource;\n info: AssetInfo;\n}\n\ninterface IProcessLocalizedAssetResult {\n localizedFiles: Record<string, string>;\n processedAssets: IProcessedAsset[];\n}\n\ntype ItemCacheFacade = ReturnType<ReturnType<Compilation['getCache']>['getItemCache']>;\n\nexport async function processLocalizedAssetCachedAsync(\n options: IProcessLocalizedAssetOptions\n): Promise<Record<string, string>> {\n const { compilation, asset, cache, chunk } = options;\n const { source: originalSource } = asset;\n\n type ETag = NonNullable<ReturnType<typeof cache.getLazyHashedEtag>>;\n const eTag: ETag | null = cache.getLazyHashedEtag(originalSource);\n const { name: originName } = asset;\n const cacheItem: ItemCacheFacade = cache.getItemCache(originName, eTag);\n let output: IProcessLocalizedAssetResult | undefined = await cacheItem.getPromise();\n\n if (!output) {\n output = processLocalizedAsset(options);\n await cacheItem.storePromise(output);\n }\n\n const { localizedFiles, processedAssets } = output;\n\n (chunk as ILocalizedWebpackChunk).localizedFiles = localizedFiles;\n\n for (const { filename, source, info } of processedAssets) {\n if (originName === filename) {\n // This helper throws if the asset doesn't already exist\n // Use the function form so that the object identity of `related` is preserved.\n // Since we already read the original info, we don't need fancy merge logic.\n compilation.updateAsset(filename, source, () => info);\n } else {\n // This helper throws if the asset already exists\n compilation.emitAsset(filename, source, info);\n }\n }\n\n return localizedFiles;\n}\n\nexport function processLocalizedAsset(options: IProcessLocalizedAssetOptions): IProcessLocalizedAssetResult {\n const {\n compilation,\n asset,\n chunk,\n filenameTemplate,\n locales,\n formatLocaleForFilenameFn,\n plugin,\n fillMissingTranslationStrings,\n defaultLocale,\n passthroughLocaleName\n } = options;\n const { sources, WebpackError } = compilation.compiler.webpack;\n const { source: originalSource } = asset;\n\n const fallbackLocale: string | undefined = fillMissingTranslationStrings ? defaultLocale : undefined;\n const rawSource: sources.CachedSource =\n originalSource instanceof sources.CachedSource\n ? originalSource\n : new sources.CachedSource(originalSource);\n const assetSource: string = rawSource.source().toString();\n\n const parsedAsset: IParseResult = _parseStringToReconstructionSequence(\n plugin,\n assetSource,\n formatLocaleForFilenameFn\n );\n\n const { issues } = parsedAsset;\n\n const localizedFiles: Record<string, string> = {};\n\n const processedAssets: IProcessedAsset[] = [];\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 fallbackLocale,\n passthroughLocaleName,\n chunk\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 const info: AssetInfo & { locale: string } = {\n ...originInfo,\n locale\n };\n\n const wrapped: sources.CachedSource = new sources.CachedSource(localeResult);\n localizedFiles[locale] = fileName;\n\n processedAssets.push({\n filename: fileName,\n source: wrapped,\n info\n });\n\n // If file already exists\n if (originName !== fileName) {\n // If A.related points to B, B.related can't point to A or the stats emitter explodes\n // So just strip the related object for the localized assets\n info.related = undefined;\n // We omit the `related` property that does a self-reference.\n originInfo.related[locale] = fileName;\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 {\n localizedFiles,\n processedAssets\n };\n}\n\nexport async function processNonLocalizedAssetCachedAsync(\n options: IProcessNonLocalizedAssetOptions\n): Promise<void> {\n const { compilation, asset, cache } = options;\n const { source: originalSource } = asset;\n\n type ETag = NonNullable<ReturnType<typeof cache.getLazyHashedEtag>>;\n const eTag: ETag | null = cache.getLazyHashedEtag(originalSource);\n const { name: originName } = asset;\n const cacheItem: ItemCacheFacade = cache.getItemCache(originName, eTag);\n let output: IProcessedAsset | undefined = await cacheItem.getPromise();\n\n if (!output) {\n output = processNonLocalizedAsset(options);\n await cacheItem.storePromise(output);\n }\n\n const { filename, source, info } = output;\n compilation.updateAsset(originName, source, info);\n if (originName !== filename) {\n compilation.renameAsset(originName, filename);\n }\n}\n\nexport function processNonLocalizedAsset(options: IProcessNonLocalizedAssetOptions): IProcessedAsset {\n const { asset, fileName, compilation, formatLocaleForFilenameFn, hasUrlGenerator, chunk } = options;\n\n const { sources, WebpackError } = compilation.compiler.webpack;\n\n const rawSource: sources.Source = asset.source;\n let cachedSource: sources.CachedSource =\n rawSource instanceof sources.CachedSource ? rawSource : new sources.CachedSource(rawSource);\n\n const { info: originInfo } = asset;\n const locale: string = options.noStringsLocaleName;\n\n if (hasUrlGenerator) {\n const assetSource: string = cachedSource.source().toString();\n const parsedAsset: IParseResult = _parseStringToReconstructionSequence(\n options.plugin,\n assetSource,\n formatLocaleForFilenameFn\n );\n\n const { issues } = parsedAsset;\n\n const { issues: localeIssues, result } = _reconstructNonLocalized(\n new sources.ReplaceSource(cachedSource, locale),\n parsedAsset.reconstructionSeries,\n locale,\n chunk\n );\n\n for (const issue of localeIssues) {\n issues.push(issue);\n }\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 cachedSource = new sources.CachedSource(result);\n } else {\n // Force the CachedSource to cache the concatenated *string*, so that the subsequent ask for the buffer is fast\n cachedSource.source();\n }\n\n const info: AssetInfo = {\n ...originInfo,\n locale\n };\n\n return {\n filename: fileName,\n source: cachedSource,\n info\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 passthroughLocale: string | undefined,\n chunk: Chunk\n): ILocalizedReconstructionResult {\n const issues: string[] = [];\n\n for (const element of reconstructionSeries) {\n const { kind, start, end } = element;\n switch (kind) {\n case LOCALIZED_RECONSTRUCTION_ELEMENT_KIND: {\n const { data, escapedBackslash } = element;\n const { stringName, translations } = data;\n let newValue: string | undefined =\n locale === passthroughLocale ? stringName : translations.get(locale)?.get(stringName);\n if (fallbackLocale && newValue === undefined) {\n newValue = translations.get(fallbackLocale)?.get(stringName);\n }\n\n if (newValue === undefined) {\n issues.push(\n `The string \"${stringName}\" in \"${data.locFilePath}\" is missing in the locale ${locale}`\n );\n\n newValue = '-- MISSING STRING --';\n }\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(start, end - 1, newValue);\n break;\n }\n\n case DYNAMIC_RECONSTRUCTION_ELEMENT_KIND: {\n const newValue: string = element.valueFn(locale, chunk);\n result.replace(start, 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 chunk: Chunk\n): INonLocalizedReconstructionResult {\n const issues: string[] = [];\n\n for (const element of reconstructionSeries) {\n switch (element.kind) {\n case LOCALIZED_RECONSTRUCTION_ELEMENT_KIND: {\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_RECONSTRUCTION_ELEMENT_KIND: {\n const newValue: string = element.valueFn(noStringsLocaleName, chunk);\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 let jsonStringifyFormatLocaleForFilenameFn: FormatLocaleForFilenameFn | undefined;\n\n let index: number = source.indexOf(Constants.STRING_PLACEHOLDER_PREFIX);\n const increment: number = Constants.STRING_PLACEHOLDER_PREFIX.length + 1;\n while (index >= 0) {\n const start: number = index;\n const elementStart: number = index + increment;\n const elementLabel: string = source.charAt(elementStart);\n let end: number = elementStart + 2;\n\n switch (elementLabel) {\n case Constants.STRING_PLACEHOLDER_LABEL: {\n const backslashEnd: number = source.indexOf('_', end);\n const escapedBackslash: string = source.slice(end, backslashEnd) || '\\\\';\n end = backslashEnd + 1;\n const suffixEnd: number = source.indexOf('_', end);\n const suffix: string = source.slice(end, suffixEnd);\n end = suffixEnd + 1;\n\n const stringData: IStringPlaceholder | undefined = plugin._getStringDataForSerialNumber(suffix);\n if (!stringData) {\n issues.push(`Missing placeholder ${suffix}`);\n } else {\n const localizedElement: ILocalizedReconstructionElement = {\n kind: LOCALIZED_RECONSTRUCTION_ELEMENT_KIND,\n start,\n end,\n escapedBackslash,\n data: stringData\n };\n reconstructionSeries.push(localizedElement);\n }\n break;\n }\n\n case Constants.LOCALE_NAME_PLACEHOLDER_LABEL: {\n const dynamicElement: IDynamicReconstructionElement = {\n kind: DYNAMIC_RECONSTRUCTION_ELEMENT_KIND,\n start,\n end,\n valueFn: formatLocaleForFilenameFn\n };\n reconstructionSeries.push(dynamicElement);\n break;\n }\n\n case Constants.JSONP_PLACEHOLDER_LABEL: {\n jsonStringifyFormatLocaleForFilenameFn ||= (locale: string, chunk: unknown) =>\n JSON.stringify(formatLocaleForFilenameFn(locale, chunk));\n const dynamicElement: IDynamicReconstructionElement = {\n kind: DYNAMIC_RECONSTRUCTION_ELEMENT_KIND,\n start,\n end,\n valueFn: jsonStringifyFormatLocaleForFilenameFn\n };\n reconstructionSeries.push(dynamicElement);\n break;\n }\n\n case Constants.CUSTOM_PLACEHOLDER_LABEL: {\n const serialEnd: number = source.indexOf('_', end);\n const serial: string = source.slice(end, serialEnd);\n end = serialEnd + 1;\n const customData: ICustomDataPlaceholder | undefined = plugin._getCustomDataForSerialNumber(serial);\n if (!customData) {\n issues.push(`Missing custom placeholder ${serial}`);\n } else {\n const dynamicElement: IDynamicReconstructionElement = {\n kind: DYNAMIC_RECONSTRUCTION_ELEMENT_KIND,\n start,\n end,\n valueFn: customData.valueForLocaleFn\n };\n reconstructionSeries.push(dynamicElement);\n }\n break;\n }\n\n default: {\n throw new Error(`Unexpected label ${elementLabel} in pattern ${source.slice(start, end)}`);\n }\n }\n\n index = source.indexOf(Constants.STRING_PLACEHOLDER_PREFIX, end);\n }\n\n return {\n issues,\n reconstructionSeries\n };\n}\n"]}