@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.
- package/CHANGELOG.json +52 -0
- package/CHANGELOG.md +15 -1
- package/dist/tsdoc-metadata.json +1 -1
- package/lib-esm/AssetProcessor.js +306 -0
- package/lib-esm/AssetProcessor.js.map +1 -0
- package/lib-esm/LocalizationPlugin.js +636 -0
- package/lib-esm/LocalizationPlugin.js.map +1 -0
- package/lib-esm/TrueHashPlugin.js +27 -0
- package/lib-esm/TrueHashPlugin.js.map +1 -0
- package/lib-esm/index.js +6 -0
- package/lib-esm/index.js.map +1 -0
- package/lib-esm/interfaces.js +4 -0
- package/lib-esm/interfaces.js.map +1 -0
- package/lib-esm/loaders/IResxLoaderOptions.js +4 -0
- package/lib-esm/loaders/IResxLoaderOptions.js.map +1 -0
- package/lib-esm/loaders/LoaderFactory.js +25 -0
- package/lib-esm/loaders/LoaderFactory.js.map +1 -0
- package/lib-esm/loaders/default-locale-loader.js +25 -0
- package/lib-esm/loaders/default-locale-loader.js.map +1 -0
- package/lib-esm/loaders/loc-loader.js +21 -0
- package/lib-esm/loaders/loc-loader.js.map +1 -0
- package/lib-esm/loaders/locjson-loader.js +13 -0
- package/lib-esm/loaders/locjson-loader.js.map +1 -0
- package/lib-esm/loaders/resjson-loader.js +13 -0
- package/lib-esm/loaders/resjson-loader.js.map +1 -0
- package/lib-esm/loaders/resx-loader.js +20 -0
- package/lib-esm/loaders/resx-loader.js.map +1 -0
- package/lib-esm/trueHashes.js +213 -0
- package/lib-esm/trueHashes.js.map +1 -0
- package/lib-esm/utilities/Constants.js +17 -0
- package/lib-esm/utilities/Constants.js.map +1 -0
- package/lib-esm/utilities/EntityMarker.js +16 -0
- package/lib-esm/utilities/EntityMarker.js.map +1 -0
- package/lib-esm/utilities/LoaderTerminalProvider.js +24 -0
- package/lib-esm/utilities/LoaderTerminalProvider.js.map +1 -0
- package/lib-esm/utilities/chunkUtilities.js +6 -0
- package/lib-esm/utilities/chunkUtilities.js.map +1 -0
- package/lib-esm/webpackInterfaces.js +4 -0
- package/lib-esm/webpackInterfaces.js.map +1 -0
- package/package.json +33 -9
- /package/{lib → lib-commonjs}/AssetProcessor.js +0 -0
- /package/{lib → lib-commonjs}/AssetProcessor.js.map +0 -0
- /package/{lib → lib-commonjs}/LocalizationPlugin.js +0 -0
- /package/{lib → lib-commonjs}/LocalizationPlugin.js.map +0 -0
- /package/{lib → lib-commonjs}/TrueHashPlugin.js +0 -0
- /package/{lib → lib-commonjs}/TrueHashPlugin.js.map +0 -0
- /package/{lib → lib-commonjs}/index.js +0 -0
- /package/{lib → lib-commonjs}/index.js.map +0 -0
- /package/{lib → lib-commonjs}/interfaces.js +0 -0
- /package/{lib → lib-commonjs}/interfaces.js.map +0 -0
- /package/{lib → lib-commonjs}/loaders/IResxLoaderOptions.js +0 -0
- /package/{lib → lib-commonjs}/loaders/IResxLoaderOptions.js.map +0 -0
- /package/{lib → lib-commonjs}/loaders/LoaderFactory.js +0 -0
- /package/{lib → lib-commonjs}/loaders/LoaderFactory.js.map +0 -0
- /package/{lib → lib-commonjs}/loaders/default-locale-loader.js +0 -0
- /package/{lib → lib-commonjs}/loaders/default-locale-loader.js.map +0 -0
- /package/{lib → lib-commonjs}/loaders/loc-loader.js +0 -0
- /package/{lib → lib-commonjs}/loaders/loc-loader.js.map +0 -0
- /package/{lib → lib-commonjs}/loaders/locjson-loader.js +0 -0
- /package/{lib → lib-commonjs}/loaders/locjson-loader.js.map +0 -0
- /package/{lib → lib-commonjs}/loaders/resjson-loader.js +0 -0
- /package/{lib → lib-commonjs}/loaders/resjson-loader.js.map +0 -0
- /package/{lib → lib-commonjs}/loaders/resx-loader.js +0 -0
- /package/{lib → lib-commonjs}/loaders/resx-loader.js.map +0 -0
- /package/{lib → lib-commonjs}/trueHashes.js +0 -0
- /package/{lib → lib-commonjs}/trueHashes.js.map +0 -0
- /package/{lib → lib-commonjs}/utilities/Constants.js +0 -0
- /package/{lib → lib-commonjs}/utilities/Constants.js.map +0 -0
- /package/{lib → lib-commonjs}/utilities/EntityMarker.js +0 -0
- /package/{lib → lib-commonjs}/utilities/EntityMarker.js.map +0 -0
- /package/{lib → lib-commonjs}/utilities/LoaderTerminalProvider.js +0 -0
- /package/{lib → lib-commonjs}/utilities/LoaderTerminalProvider.js.map +0 -0
- /package/{lib → lib-commonjs}/utilities/chunkUtilities.js +0 -0
- /package/{lib → lib-commonjs}/utilities/chunkUtilities.js.map +0 -0
- /package/{lib → lib-commonjs}/webpackInterfaces.js +0 -0
- /package/{lib → lib-commonjs}/webpackInterfaces.js.map +0 -0
- /package/{lib → lib-dts}/AssetProcessor.d.ts +0 -0
- /package/{lib → lib-dts}/AssetProcessor.d.ts.map +0 -0
- /package/{lib → lib-dts}/LocalizationPlugin.d.ts +0 -0
- /package/{lib → lib-dts}/LocalizationPlugin.d.ts.map +0 -0
- /package/{lib → lib-dts}/TrueHashPlugin.d.ts +0 -0
- /package/{lib → lib-dts}/TrueHashPlugin.d.ts.map +0 -0
- /package/{lib → lib-dts}/index.d.ts +0 -0
- /package/{lib → lib-dts}/index.d.ts.map +0 -0
- /package/{lib → lib-dts}/interfaces.d.ts +0 -0
- /package/{lib → lib-dts}/interfaces.d.ts.map +0 -0
- /package/{lib → lib-dts}/loaders/IResxLoaderOptions.d.ts +0 -0
- /package/{lib → lib-dts}/loaders/IResxLoaderOptions.d.ts.map +0 -0
- /package/{lib → lib-dts}/loaders/LoaderFactory.d.ts +0 -0
- /package/{lib → lib-dts}/loaders/LoaderFactory.d.ts.map +0 -0
- /package/{lib → lib-dts}/loaders/default-locale-loader.d.ts +0 -0
- /package/{lib → lib-dts}/loaders/default-locale-loader.d.ts.map +0 -0
- /package/{lib → lib-dts}/loaders/loc-loader.d.ts +0 -0
- /package/{lib → lib-dts}/loaders/loc-loader.d.ts.map +0 -0
- /package/{lib → lib-dts}/loaders/locjson-loader.d.ts +0 -0
- /package/{lib → lib-dts}/loaders/locjson-loader.d.ts.map +0 -0
- /package/{lib → lib-dts}/loaders/resjson-loader.d.ts +0 -0
- /package/{lib → lib-dts}/loaders/resjson-loader.d.ts.map +0 -0
- /package/{lib → lib-dts}/loaders/resx-loader.d.ts +0 -0
- /package/{lib → lib-dts}/loaders/resx-loader.d.ts.map +0 -0
- /package/{lib → lib-dts}/trueHashes.d.ts +0 -0
- /package/{lib → lib-dts}/trueHashes.d.ts.map +0 -0
- /package/{lib → lib-dts}/utilities/Constants.d.ts +0 -0
- /package/{lib → lib-dts}/utilities/Constants.d.ts.map +0 -0
- /package/{lib → lib-dts}/utilities/EntityMarker.d.ts +0 -0
- /package/{lib → lib-dts}/utilities/EntityMarker.d.ts.map +0 -0
- /package/{lib → lib-dts}/utilities/LoaderTerminalProvider.d.ts +0 -0
- /package/{lib → lib-dts}/utilities/LoaderTerminalProvider.d.ts.map +0 -0
- /package/{lib → lib-dts}/utilities/chunkUtilities.d.ts +0 -0
- /package/{lib → lib-dts}/utilities/chunkUtilities.d.ts.map +0 -0
- /package/{lib → lib-dts}/webpackInterfaces.d.ts +0 -0
- /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
|
|
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
|
package/dist/tsdoc-metadata.json
CHANGED
|
@@ -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"]}
|