@enhanced-dom/webpack 0.4.0 → 0.5.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.
@@ -0,0 +1,236 @@
1
+ import HtmlWebpackPlugin from 'html-webpack-plugin';
2
+ import path from 'path';
3
+ // Ported from `escape-string-regexp` (inlined rather than taken as a dependency, since newer
4
+ // majors of these tiny sindresorhus utils are ESM-only).
5
+ // ATTRIBUTION: COPY | escape-string-regexp | Copyright (c) Sindre Sorhus <sindresorhus@gmail.com> (https://sindresorhus.com). MIT Licensed.
6
+ const escapeRegExp = (value) => value.replace(/[|\\{}()[\]^$+*?.]/g, '\\$&');
7
+ // Ported from `slash` (same reasoning as escapeRegExp above).
8
+ // ATTRIBUTION: COPY | slash | Copyright (c) Sindre Sorhus <sindresorhus@gmail.com> (https://sindresorhus.com). MIT Licensed.
9
+ // eslint-disable-next-line no-control-regex
10
+ const toPosixPath = (value) => (/[^\x00-\x80]+/.test(value) ? value : value.replace(/\\/g, '/'));
11
+ // Ported from `source-map-url` (same reasoning as escapeRegExp above); only the lookup this
12
+ // plugin actually uses (`getFrom`) is kept.
13
+ // ATTRIBUTION: COPY | source-map-url | Copyright 2014 Simon Lydell. X11 ("MIT") Licensed.
14
+ const sourceMappingUrlRegExp = (() => {
15
+ const inner = `[#@] sourceMappingURL=([^\\s'"]*)`;
16
+ return new RegExp(`(?:/\\*(?:\\s*\r?\n(?://)?)?(?:${inner})\\s*\\*/|//(?:${inner}))\\s*`);
17
+ })();
18
+ const getSourceMappingUrl = (code) => {
19
+ const match = code.match(sourceMappingUrlRegExp);
20
+ return match ? match[1] || match[2] || '' : null;
21
+ };
22
+ // Inserts immediately before the real closing tag - found by taking the LAST match of
23
+ // `</tagName>` in the document, not the first. An inlined <script>'s own source can legitimately
24
+ // contain that same substring as plain text (e.g. an embedded HTML template string inside a
25
+ // Worker's source, unrelated to actual document structure) well before the document's real
26
+ // closing tag; matching the first occurrence would splice the insertion into the middle of that
27
+ // script's text instead of after it, corrupting the script the browser was supposed to run.
28
+ const insertBeforeClosingTag = (html, tagName, insertion) => {
29
+ const closingTagRegExp = new RegExp(`</${tagName}\\s*>`, 'gi');
30
+ let lastMatch = null;
31
+ let match;
32
+ while ((match = closingTagRegExp.exec(html))) {
33
+ lastMatch = match;
34
+ }
35
+ return lastMatch ? `${html.slice(0, lastMatch.index)}${insertion}${html.slice(lastMatch.index)}` : `${html}${insertion}`;
36
+ };
37
+ const buildAdditionalAssetMarkup = (wrapper, assetName, encoded) => {
38
+ if (wrapper === 'comment') {
39
+ return `<!--data-asset-name="${assetName}" data-encoding="base64" ${encoded}-->`;
40
+ }
41
+ return `<script type="application/octet-stream" data-asset-name="${assetName}" data-encoding="base64">${encoded}</script>`;
42
+ };
43
+ class HtmlInlineSourcePlugin {
44
+ assetsRegExp;
45
+ faviconPath;
46
+ htmlAssetName;
47
+ inlinedChunks;
48
+ additionalAssets;
49
+ // Rewrites a `//# sourceMappingURL=...`/`/*# sourceMappingURL=... */` comment (if any) in an
50
+ // asset's source to be relative to the site root instead of the asset's own directory, since
51
+ // inlining moves the asset's content into the html document rather than serving it from
52
+ // alongside its sourcemap.
53
+ // Adapted from `html-webpack-inline-source-plugin`'s method of the same name.
54
+ // ATTRIBUTION: ADAPTATION | html-webpack-inline-source-plugin | Copyright (c) 2016 Jan Nicklas. MIT Licensed.
55
+ resolveSourceMaps(compilation, assetName, asset) {
56
+ const source = asset.source();
57
+ const out = compilation.outputOptions;
58
+ const assetPath = path.join(out.path, assetName);
59
+ const sourceText = typeof source === 'string' ? source : source.toString();
60
+ const mapUrlOriginal = getSourceMappingUrl(sourceText);
61
+ if (!mapUrlOriginal || mapUrlOriginal.indexOf('data:') === 0 || mapUrlOriginal.indexOf('/') === 0) {
62
+ return sourceText;
63
+ }
64
+ const assetDir = path.dirname(assetPath);
65
+ const mapPath = path.join(assetDir, mapUrlOriginal);
66
+ const mapPathRelative = path.relative(out.path, mapPath);
67
+ const publicPath = typeof out.publicPath === 'string' ? out.publicPath : '';
68
+ const mapUrlCorrected = toPosixPath(path.join(publicPath, mapPathRelative));
69
+ const regex = new RegExp(`${escapeRegExp(mapUrlOriginal)}(\\s*(?:\\*/)?\\s*$)`);
70
+ return sourceText.replace(regex, (_match, group) => `${mapUrlCorrected}${group}`);
71
+ }
72
+ // Adapted from `html-webpack-inline-source-plugin`'s method of the same name.
73
+ // ATTRIBUTION: ADAPTATION | html-webpack-inline-source-plugin | Copyright (c) 2016 Jan Nicklas. MIT Licensed.
74
+ processTag(compilation, regex, tag) {
75
+ let assetUrl;
76
+ let resultTag = tag;
77
+ if (tag.tagName === 'script' && regex.test(tag.attributes.src)) {
78
+ assetUrl = tag.attributes.src;
79
+ resultTag = { tagName: 'script', voidTag: false, meta: {}, attributes: { type: 'text/javascript' } };
80
+ }
81
+ else if (tag.tagName === 'link' && regex.test(tag.attributes.href)) {
82
+ assetUrl = tag.attributes.href;
83
+ resultTag = { tagName: 'style', voidTag: false, meta: {}, attributes: { type: 'text/css' } };
84
+ }
85
+ if (assetUrl) {
86
+ const publicUrlPrefix = typeof compilation.outputOptions.publicPath === 'string' ? compilation.outputOptions.publicPath : '';
87
+ const assetName = path.posix.relative(publicUrlPrefix, assetUrl);
88
+ const asset = compilation.assets[assetName];
89
+ if (!asset) {
90
+ return resultTag;
91
+ }
92
+ const updatedSource = this.resolveSourceMaps(compilation, assetName, asset);
93
+ resultTag.innerHTML = resultTag.tagName === 'script' ? updatedSource.replace(/(<)(\/script>)/g, '\\x3C$2') : updatedSource;
94
+ }
95
+ return resultTag;
96
+ }
97
+ // Adapted from `html-webpack-inline-source-plugin`'s method of the same name.
98
+ // ATTRIBUTION: ADAPTATION | html-webpack-inline-source-plugin | Copyright (c) 2016 Jan Nicklas. MIT Licensed.
99
+ processTags(compilation, pluginData) {
100
+ const assetsRegExp = this.assetsRegExp;
101
+ if (!assetsRegExp) {
102
+ return pluginData;
103
+ }
104
+ const headTags = [];
105
+ const bodyTags = [];
106
+ const { publicPath } = compilation.outputOptions;
107
+ const publicUrlPrefix = typeof publicPath === 'string' ? publicPath : '';
108
+ // Mirrors processTag's own match condition (same regex, same tag-type checks) to record
109
+ // exactly which asset this tag will cause to be inlined, if any - without this, the
110
+ // processAssets hook below has no way to know which assets were actually touched. We record
111
+ // the owning CHUNK rather than the asset name: a chunk's identity is stable even when its
112
+ // contenthash (and therefore filename) is recomputed later by minification, so resolving
113
+ // `chunk.files` when deleting - instead of replaying a filename captured now - survives that
114
+ // timing gap.
115
+ const trackInlinedAsset = (tag) => {
116
+ let assetUrl;
117
+ if (tag.tagName === 'script' && assetsRegExp.test(tag.attributes.src)) {
118
+ assetUrl = tag.attributes.src;
119
+ }
120
+ else if (tag.tagName === 'link' && assetsRegExp.test(tag.attributes.href)) {
121
+ assetUrl = tag.attributes.href;
122
+ }
123
+ if (!assetUrl) {
124
+ return;
125
+ }
126
+ const assetName = path.posix.relative(publicUrlPrefix, assetUrl);
127
+ const owningChunk = Array.from(compilation.chunks).find((chunk) => chunk.files.has(assetName));
128
+ this.inlinedChunks = this.inlinedChunks ?? new Set();
129
+ this.inlinedChunks.add(owningChunk ?? assetName);
130
+ };
131
+ pluginData.headTags.forEach((tag) => {
132
+ trackInlinedAsset(tag);
133
+ headTags.push(this.processTag(compilation, assetsRegExp, tag));
134
+ });
135
+ pluginData.bodyTags.forEach((tag) => {
136
+ trackInlinedAsset(tag);
137
+ bodyTags.push(this.processTag(compilation, assetsRegExp, tag));
138
+ });
139
+ return { ...pluginData, headTags, bodyTags };
140
+ }
141
+ // Assets that exist in the compilation but were never referenced by a <script>/<link> tag (e.g.
142
+ // a license-notices file written directly via compilation.emitAsset) have nothing for
143
+ // processTags to match against - embed them explicitly instead, keyed by asset name so consuming
144
+ // code can read them back out of the DOM at runtime. `wrapper` picks the markup (an opaque,
145
+ // non-executing <script>, or a plain HTML comment - base64 never contains `--`, so it can't
146
+ // prematurely close the comment); `container` picks where it lands.
147
+ //
148
+ // This runs against the already-emitted HTML asset (see the processAssets hook below), not
149
+ // against pluginData inside afterTemplateExecution - some plugins that emit matchable assets
150
+ // (e.g. webpack-license-plugin, which writes its notices file at PROCESS_ASSETS_STAGE_ANALYSE)
151
+ // do so well after html-webpack-plugin has already rendered and emitted its HTML, so scanning
152
+ // compilation.assets from inside afterTemplateExecution would silently miss them. Since there's
153
+ // no headTags/bodyTags array to push a HtmlTagObject into at this point, 'script'-wrapped markup
154
+ // is spliced into the html string the same way 'comment'-wrapped markup already was.
155
+ processAdditionalAssets(compilation, html) {
156
+ let result = html;
157
+ const additionalAssets = this.additionalAssets ?? [];
158
+ additionalAssets.forEach(({ pattern, wrapper, container }) => {
159
+ Object.keys(compilation.assets)
160
+ .filter((name) => name !== this.htmlAssetName && pattern.test(name))
161
+ .forEach((name) => {
162
+ const encoded = compilation.assets[name].buffer().toString('base64');
163
+ this.inlinedChunks = this.inlinedChunks ?? new Set();
164
+ this.inlinedChunks.add(name);
165
+ const markup = buildAdditionalAssetMarkup(wrapper, name, encoded);
166
+ result = container === 'head' || container === 'body' ? insertBeforeClosingTag(result, container, markup) : `${result}${markup}`;
167
+ });
168
+ });
169
+ return result;
170
+ }
171
+ apply(compiler) {
172
+ this.assetsRegExp = undefined;
173
+ this.faviconPath = undefined;
174
+ this.inlinedChunks = new Set();
175
+ compiler.hooks.compilation.tap('html-inline-source-plugin', (compilation) => {
176
+ HtmlWebpackPlugin.getHooks(compilation).afterTemplateExecution.tapAsync('html-inline-source-plugin', (htmlPluginData, callback) => {
177
+ this.assetsRegExp = new RegExp('.(js|css)$');
178
+ this.htmlAssetName = htmlPluginData.outputName;
179
+ const result = this.processTags(compilation, htmlPluginData);
180
+ const favicon = htmlPluginData.plugin.options?.favicon;
181
+ const inputFs = compiler.inputFileSystem;
182
+ if (!favicon || !inputFs.existsSync(favicon)) {
183
+ return callback(null, result);
184
+ }
185
+ const faviconTag = result.headTags.find((tag) => tag.tagName === 'link' && tag.attributes.rel === 'icon');
186
+ if (faviconTag) {
187
+ this.faviconPath = faviconTag.attributes.href;
188
+ faviconTag.attributes.href = `data:image/x-icon;base64, ${inputFs.readFileSync(favicon, 'base64')}`;
189
+ }
190
+ callback(null, result);
191
+ });
192
+ // Patches the already-emitted HTML asset directly (see processAdditionalAssets' own comment
193
+ // for why this can't happen inside afterTemplateExecution above) and must run strictly
194
+ // before the deletion pass below - same processAssets stage, but tapped first, so Tapable's
195
+ // stable same-stage ordering runs this one first.
196
+ compilation.hooks.processAssets.tap({ name: 'html-inline-source-plugin', stage: compiler.webpack.Compilation.PROCESS_ASSETS_STAGE_REPORT }, () => {
197
+ if (!this.htmlAssetName)
198
+ return;
199
+ const htmlAsset = compilation.assets[this.htmlAssetName];
200
+ if (!htmlAsset)
201
+ return;
202
+ const html = this.processAdditionalAssets(compilation, htmlAsset.source().toString());
203
+ compilation.updateAsset(this.htmlAssetName, new compiler.webpack.sources.RawSource(html));
204
+ });
205
+ // Only remove assets that were actually inlined into the HTML above. Blanket-matching by
206
+ // extension would also delete unrelated .js/.css assets that were never inlining candidates
207
+ // in the first place - e.g. a Worker chunk, which browsers load via the separate Worker API
208
+ // rather than a <script> tag, so html-webpack-plugin never generates a tag for it.
209
+ // PROCESS_ASSETS_STAGE_REPORT is the last processAssets stage - it still runs before
210
+ // sealing freezes compilation.assets, so chunk.files here already reflects any earlier
211
+ // stage's rename (e.g. Terser's contenthash recompute).
212
+ compilation.hooks.processAssets.tap(
213
+ // Read the stage constant off compiler.webpack rather than importing Compilation as a
214
+ // value from 'webpack' directly - the plugin then keeps working correctly even if the
215
+ // host project resolves a different webpack instance than the one in this package's own
216
+ // node_modules (the standard reason webpack plugins avoid a direct `require('webpack')`).
217
+ { name: 'html-inline-source-plugin', stage: compiler.webpack.Compilation.PROCESS_ASSETS_STAGE_REPORT }, () => {
218
+ this.inlinedChunks?.forEach((chunkOrName) => {
219
+ if (typeof chunkOrName === 'string') {
220
+ compilation.deleteAsset(chunkOrName);
221
+ return;
222
+ }
223
+ chunkOrName.files.forEach((file) => {
224
+ compilation.deleteAsset(file);
225
+ });
226
+ });
227
+ const faviconFile = this.faviconPath?.split(path.sep)?.pop();
228
+ if (faviconFile) {
229
+ compilation.deleteAsset(faviconFile);
230
+ }
231
+ });
232
+ });
233
+ }
234
+ }
235
+ export default HtmlInlineSourcePlugin;
236
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiSHRtbElubGluZVNvdXJjZVBsdWdpbi5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9wbHVnaW5zL0h0bWxJbmxpbmVTb3VyY2VQbHVnaW4udHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxpQkFBcUQsTUFBTSxxQkFBcUIsQ0FBQTtBQUd2RixPQUFPLElBQUksTUFBTSxNQUFNLENBQUE7QUFjdkIsNkZBQTZGO0FBQzdGLHlEQUF5RDtBQUN6RCw0SUFBNEk7QUFDNUksTUFBTSxZQUFZLEdBQUcsQ0FBQyxLQUFhLEVBQUUsRUFBRSxDQUFDLEtBQUssQ0FBQyxPQUFPLENBQUMscUJBQXFCLEVBQUUsTUFBTSxDQUFDLENBQUE7QUFFcEYsOERBQThEO0FBQzlELDZIQUE2SDtBQUM3SCw0Q0FBNEM7QUFDNUMsTUFBTSxXQUFXLEdBQUcsQ0FBQyxLQUFhLEVBQUUsRUFBRSxDQUFDLENBQUMsZUFBZSxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxLQUFLLENBQUMsT0FBTyxDQUFDLEtBQUssRUFBRSxHQUFHLENBQUMsQ0FBQyxDQUFBO0FBRXhHLDRGQUE0RjtBQUM1Riw0Q0FBNEM7QUFDNUMsMEZBQTBGO0FBQzFGLE1BQU0sc0JBQXNCLEdBQUcsQ0FBQyxHQUFHLEVBQUU7SUFDbkMsTUFBTSxLQUFLLEdBQUcsbUNBQW1DLENBQUE7SUFDakQsT0FBTyxJQUFJLE1BQU0sQ0FBQyxrQ0FBa0MsS0FBSyxrQkFBa0IsS0FBSyxRQUFRLENBQUMsQ0FBQTtBQUMzRixDQUFDLENBQUMsRUFBRSxDQUFBO0FBQ0osTUFBTSxtQkFBbUIsR0FBRyxDQUFDLElBQVksRUFBRSxFQUFFO0lBQzNDLE1BQU0sS0FBSyxHQUFHLElBQUksQ0FBQyxLQUFLLENBQUMsc0JBQXNCLENBQUMsQ0FBQTtJQUNoRCxPQUFPLEtBQUssQ0FBQyxDQUFDLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxJ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MEZBQTBGO1lBQzFGLEVBQUUsSUFBSSxFQUFFLDJCQUEyQixFQUFFLEtBQUssRUFBRSxRQUFRLENBQUMsT0FBTyxDQUFDLFdBQVcsQ0FBQywyQkFBMkIsRUFBRSxFQUN0RyxHQUFHLEVBQUU7Z0JBQ0gsSUFBSSxDQUFDLGFBQWEsRUFBRSxPQUFPLENBQUMsQ0FBQyxXQUFXLEVBQUUsRUFBRTtvQkFDMUMsSUFBSSxPQUFPLFdBQVcsS0FBSyxRQUFRLEVBQUUsQ0FBQzt3QkFDcEMsV0FBVyxDQUFDLFdBQVcsQ0FBQyxXQUFXLENBQUMsQ0FBQTt3QkFDcEMsT0FBTTtvQkFDUixDQUFDO29CQUNELFdBQVcsQ0FBQyxLQUFLLENBQUMsT0FBTyxDQUFDLENBQUMsSUFBSSxFQUFFLEVBQUU7d0JBQ2pDLFdBQVcsQ0FBQyxXQUFXLENBQUMsSUFBSSxDQUFDLENBQUE7b0JBQy9CLENBQUMsQ0FBQyxDQUFBO2dCQUNKLENBQUMsQ0FBQyxDQUFBO2dCQUNGLE1BQU0sV0FBVyxHQUFHLElBQUksQ0FBQyxXQUFXLEVBQUUsS0FBSyxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsRUFBRSxHQUFHLEVBQUUsQ0FBQTtnQkFDNUQsSUFBSSxXQUFXLEVBQUUsQ0FBQztvQkFDaEIsV0FBVyxDQUFDLFdBQVcsQ0FBQyxXQUFXLENBQUMsQ0FBQTtnQkFDdEMsQ0FBQztZQUNILENBQUMsQ0FDRixDQUFBO1FBQ0gsQ0FBQyxDQUFDLENBQUE7SUFDSixDQUFDO0NBQ0Y7QUFFRCxlQUFlLHNCQUFzQixDQUFBIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IEh0bWxXZWJwYWNrUGx1Z2luLCB7IHR5cGUgSG9va3MsIHR5cGUgSHRtbFRhZ09iamVjdCB9IGZyb20gJ2h0bWwtd2VicGFjay1wbHVnaW4nXG5pbXBvcnQgeyB0eXBlIEFzeW5jU2VyaWVzV2F0ZXJmYWxsSG9vayB9IGZyb20gJ3RhcGFibGUnXG5pbXBvcnQgeyB0eXBlIENodW5rLCB0eXBlIENvbXBpbGF0aW9uLCB0eXBlIENvbXBpbGVyLCB0eXBlIFdlYnBhY2tQbHVnaW5JbnN0YW5jZSB9IGZyb20gJ3dlYnBhY2snXG5pbXBvcnQgcGF0aCBmcm9tICdwYXRoJ1xuXG50eXBlIEFzeW5jU2VyaWVzV2F0ZXJmYWxsSG9va0RhdGFUeXBlPFQ+ID0gVCBleHRlbmRzIEFzeW5jU2VyaWVzV2F0ZXJmYWxsSG9vazxpbmZlciBSPiA/IFIgOiBuZXZlclxudHlwZSBUZW1wbGF0ZUV4ZWN1dGlvbkRhdGFUeXBlID0gQXN5bmNTZXJpZXNXYXRlcmZhbGxIb29rRGF0YVR5cGU8SG9va3NbJ2FmdGVyVGVtcGxhdGVFeGVjdXRpb24nXT5cblxuLy8gVGhlIGNvbXBpbGVyJ3MgaW5wdXRGaWxlU3lzdGVtIGlzIG9ubHkgb2ZmaWNpYWxseSB0eXBlZCB3aXRoIGFzeW5jIChjYWxsYmFjaykgbWV0aG9kcywgYnV0IGluXG4vLyBwcmFjdGljZSBpdCdzIGVpdGhlciBOb2RlJ3MgcmVhbCBgZnNgIG9yIGEgTWVtb3J5RlMgLSBib3RoIGFsc28gZXhwb3NlIHRoZXNlIFN5bmMgZXF1aXZhbGVudHMuXG4vLyBTYW1lIGNvbXByb21pc2UgV2ViY29tcG9uZW50U3R5bGVMb2FkZXIudHMgYW5kIEBlbmhhbmNlZC1kb20vaW50bCdzIHdlYnBhY2sucGx1Z2luLnRzIG1ha2UgZm9yXG4vLyB0aGUgc2FtZSByZWFzb24uXG5pbnRlcmZhY2UgSVN5bmNGaWxlU3lzdGVtIHtcbiAgZXhpc3RzU3luYzogKHBhdGhPZkl0ZW06IHN0cmluZykgPT4gYm9vbGVhblxuICByZWFkRmlsZVN5bmM6IChwYXRoT2ZJdGVtOiBzdHJpbmcsIGVuY29kaW5nOiBzdHJpbmcpID0+IHN0cmluZ1xufVxuXG4vLyBQb3J0ZWQgZnJvbSBgZXNjYXBlLXN0cmluZy1yZWdleHBgIChpbmxpbmVkIHJhdGhlciB0aGFuIHRha2VuIGFzIGEgZGVwZW5kZW5jeSwgc2luY2UgbmV3ZXJcbi8vIG1ham9ycyBvZiB0aGVzZSB0aW55IHNpbmRyZXNvcmh1cyB1dGlscyBhcmUgRVNNLW9ubHkpLlxuLy8gQVRUUklCVVRJT046IENPUFkgfCBlc2NhcGUtc3RyaW5nLXJlZ2V4cCB8IENvcHlyaWdodCAoYykgU2luZHJlIFNvcmh1cyA8c2luZHJlc29yaHVzQGdtYWlsLmNvbT4gKGh0dHBzOi8vc2luZHJlc29yaHVzLmNvbSkuIE1JVCBMaWNlbnNlZC5cbmNvbnN0IGVzY2FwZVJlZ0V4cCA9ICh2YWx1ZTogc3RyaW5nKSA9PiB2YWx1ZS5yZXBsYWNlKC9bfFxcXFx7fSgpW1xcXV4kKyo/Ll0vZywgJ1xcXFwkJicpXG5cbi8vIFBvcnRlZCBmcm9tIGBzbGFzaGAgKHNhbWUgcmVhc29uaW5nIGFzIGVzY2FwZVJlZ0V4cCBhYm92ZSkuXG4vLyBBVFRSSUJVVElPTjogQ09QWSB8IHNsYXNoIHwgQ29weXJpZ2h0IChjKSBTaW5kcmUgU29yaHVzIDxzaW5kcmVzb3JodXNAZ21haWwuY29tPiAoaHR0cHM6Ly9zaW5kcmVzb3JodXMuY29tKS4gTUlUIExpY2Vuc2VkLlxuLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIG5vLWNvbnRyb2wtcmVnZXhcbmNvbnN0IHRvUG9zaXhQYXRoID0gKHZhbHVlOiBzdHJpbmcpID0+ICgvW15cXHgwMC1cXHg4MF0rLy50ZXN0KHZhbHVlKSA/IHZhbHVlIDogdmFsdWUucmVwbGFjZSgvXFxcXC9nLCAnLycpKVxuXG4vLyBQb3J0ZWQgZnJvbSBgc291cmNlLW1hcC11cmxgIChzYW1lIHJlYXNvbmluZyBhcyBlc2NhcGVSZWdFeHAgYWJvdmUpOyBvbmx5IHRoZSBsb29rdXAgdGhpc1xuLy8gcGx1Z2luIGFjdHVhbGx5IHVzZXMgKGBnZXRGcm9tYCkgaXMga2VwdC5cbi8vIEFUVFJJQlVUSU9OOiBDT1BZIHwgc291cmNlLW1hcC11cmwgfCBDb3B5cmlnaHQgMjAxNCBTaW1vbiBMeWRlbGwuIFgxMSAoXCJNSVRcIikgTGljZW5zZWQuXG5jb25zdCBzb3VyY2VNYXBwaW5nVXJsUmVnRXhwID0gKCgpID0+IHtcbiAgY29uc3QgaW5uZXIgPSBgWyNAXSBzb3VyY2VNYXBwaW5nVVJMPShbXlxcXFxzJ1wiXSopYFxuICByZXR1cm4gbmV3IFJlZ0V4cChgKD86L1xcXFwqKD86XFxcXHMqXFxyP1xcbig/Oi8vKT8pPyg/OiR7aW5uZXJ9KVxcXFxzKlxcXFwqL3wvLyg/OiR7aW5uZXJ9KSlcXFxccypgKVxufSkoKVxuY29uc3QgZ2V0U291cmNlTWFwcGluZ1VybCA9IChjb2RlOiBzdHJpbmcpID0+IHtcbiAgY29uc3QgbWF0Y2ggPSBjb2RlLm1hdGNoKHNvdXJjZU1hcHBpbmdVcmxSZWdFeHApXG4gIHJldHVybiBtYXRjaCA/IG1hdGNoWzFdIHx8IG1hdGNoWzJdIHx8ICcnIDogbnVsbFxufVxuXG4vLyBJbnNlcnRzIGltbWVkaWF0ZWx5IGJlZm9yZSB0aGUgcmVhbCBjbG9zaW5nIHRhZyAtIGZvdW5kIGJ5IHRha2luZyB0aGUgTEFTVCBtYXRjaCBvZlxuLy8gYDwvdGFnTmFtZT5gIGluIHRoZSBkb2N1bWVudCwgbm90IHRoZSBmaXJzdC4gQW4gaW5saW5lZCA8c2NyaXB0PidzIG93biBzb3VyY2UgY2FuIGxlZ2l0aW1hdGVseVxuLy8gY29udGFpbiB0aGF0IHNhbWUgc3Vic3RyaW5nIGFzIHBsYWluIHRleHQgKGUuZy4gYW4gZW1iZWRkZWQgSFRNTCB0ZW1wbGF0ZSBzdHJpbmcgaW5zaWRlIGFcbi8vIFdvcmtlcidzIHNvdXJjZSwgdW5yZWxhdGVkIHRvIGFjdHVhbCBkb2N1bWVudCBzdHJ1Y3R1cmUpIHdlbGwgYmVmb3JlIHRoZSBkb2N1bWVudCdzIHJlYWxcbi8vIGNsb3NpbmcgdGFnOyBtYXRjaGluZyB0aGUgZmlyc3Qgb2NjdXJyZW5jZSB3b3VsZCBzcGxpY2UgdGhlIGluc2VydGlvbiBpbnRvIHRoZSBtaWRkbGUgb2YgdGhhdFxuLy8gc2NyaXB0J3MgdGV4dCBpbnN0ZWFkIG9mIGFmdGVyIGl0LCBjb3JydXB0aW5nIHRoZSBzY3JpcHQgdGhlIGJyb3dzZXIgd2FzIHN1cHBvc2VkIHRvIHJ1bi5cbmNvbnN0IGluc2VydEJlZm9yZUNsb3NpbmdUYWcgPSAoaHRtbDogc3RyaW5nLCB0YWdOYW1lOiAnaGVhZCcgfCAnYm9keScsIGluc2VydGlvbjogc3RyaW5nKSA9PiB7XG4gIGNvbnN0IGNsb3NpbmdUYWdSZWdFeHAgPSBuZXcgUmVnRXhwKGA8LyR7dGFnTmFtZX1cXFxccyo+YCwgJ2dpJylcbiAgbGV0IGxhc3RNYXRjaDogUmVnRXhwRXhlY0FycmF5IHwgbnVsbCA9IG51bGxcbiAgbGV0IG1hdGNoOiBSZWdFeHBFeGVjQXJyYXkgfCBudWxsXG4gIHdoaWxlICgobWF0Y2ggPSBjbG9zaW5nVGFnUmVnRXhwLmV4ZWMoaHRtbCkpKSB7XG4gICAgbGFzdE1hdGNoID0gbWF0Y2hcbiAgfVxuICByZXR1cm4gbGFzdE1hdGNoID8gYCR7aHRtbC5zbGljZSgwLCBsYXN0TWF0Y2guaW5kZXgpfSR7aW5zZXJ0aW9ufSR7aHRtbC5zbGljZShsYXN0TWF0Y2guaW5kZXgpfWAgOiBgJHtodG1sfSR7aW5zZXJ0aW9ufWBcbn1cblxuY29uc3QgYnVpbGRBZGRpdGlvbmFsQXNzZXRNYXJrdXAgPSAod3JhcHBlcjogJ2NvbW1lbnQnIHwgJ3NjcmlwdCcsIGFzc2V0TmFtZTogc3RyaW5nLCBlbmNvZGVkOiBzdHJpbmcpID0+IHtcbiAgaWYgKHdyYXBwZXIgPT09ICdjb21tZW50Jykge1xuICAgIHJldHVybiBgPCEtLWRhdGEtYXNzZXQtbmFtZT1cIiR7YXNzZXROYW1lfVwiIGRhdGEtZW5jb2Rpbmc9XCJiYXNlNjRcIiAke2VuY29kZWR9LS0+YFxuICB9XG4gIHJldHVybiBgPHNjcmlwdCB0eXBlPVwiYXBwbGljYXRpb24vb2N0ZXQtc3RyZWFtXCIgZGF0YS1hc3NldC1uYW1lPVwiJHthc3NldE5hbWV9XCIgZGF0YS1lbmNvZGluZz1cImJhc2U2NFwiPiR7ZW5jb2RlZH08L3NjcmlwdD5gXG59XG5cbmNsYXNzIEh0bWxJbmxpbmVTb3VyY2VQbHVnaW4gaW1wbGVtZW50cyBXZWJwYWNrUGx1Z2luSW5zdGFuY2Uge1xuICBhc3NldHNSZWdFeHA/OiBSZWdFeHBcbiAgZmF2aWNvblBhdGg/OiBzdHJpbmdcbiAgaHRtbEFzc2V0TmFtZT86IHN0cmluZ1xuICBpbmxpbmVkQ2h1bmtzPzogU2V0PENodW5rIHwgc3RyaW5nPlxuICBhZGRpdGlvbmFsQXNzZXRzPzogeyBwYXR0ZXJuOiBSZWdFeHA7IHdyYXBwZXI6ICdjb21tZW50JyB8ICdzY3JpcHQnOyBjb250YWluZXI6ICdoZWFkJyB8ICdib2R5JyB8ICdmb290ZXInIH1bXVxuXG4gIC8vIFJld3JpdGVzIGEgYC8vIyBzb3VyY2VNYXBwaW5nVVJMPS4uLmAvYC8qIyBzb3VyY2VNYXBwaW5nVVJMPS4uLiAqL2AgY29tbWVudCAoaWYgYW55KSBpbiBhblxuICAvLyBhc3NldCdzIHNvdXJjZSB0byBiZSByZWxhdGl2ZSB0byB0aGUgc2l0ZSByb290IGluc3RlYWQgb2YgdGhlIGFzc2V0J3Mgb3duIGRpcmVjdG9yeSwgc2luY2VcbiAgLy8gaW5saW5pbmcgbW92ZXMgdGhlIGFzc2V0J3MgY29udGVudCBpbnRvIHRoZSBodG1sIGRvY3VtZW50IHJhdGhlciB0aGFuIHNlcnZpbmcgaXQgZnJvbVxuICAvLyBhbG9uZ3NpZGUgaXRzIHNvdXJjZW1hcC5cbiAgLy8gQWRhcHRlZCBmcm9tIGBodG1sLXdlYnBhY2staW5saW5lLXNvdXJjZS1wbHVnaW5gJ3MgbWV0aG9kIG9mIHRoZSBzYW1lIG5hbWUuXG4gIC8vIEFUVFJJQlVUSU9OOiBBREFQVEFUSU9OIHwgaHRtbC13ZWJwYWNrLWlubGluZS1zb3VyY2UtcGx1Z2luIHwgQ29weXJpZ2h0IChjKSAyMDE2IEphbiBOaWNrbGFzLiBNSVQgTGljZW5zZWQuXG4gIHJlc29sdmVTb3VyY2VNYXBzKGNvbXBpbGF0aW9uOiBDb21waWxhdGlvbiwgYXNzZXROYW1lOiBzdHJpbmcsIGFzc2V0OiBDb21waWxhdGlvblsnYXNzZXRzJ11bc3RyaW5nXSk6IHN0cmluZyB7XG4gICAgY29uc3Qgc291cmNlID0gYXNzZXQuc291cmNlKClcbiAgICBjb25zdCBvdXQgPSBjb21waWxhdGlvbi5vdXRwdXRPcHRpb25zXG4gICAgY29uc3QgYXNzZXRQYXRoID0gcGF0aC5qb2luKG91dC5wYXRoLCBhc3NldE5hbWUpXG4gICAgY29uc3Qgc291cmNlVGV4dCA9IHR5cGVvZiBzb3VyY2UgPT09ICdzdHJpbmcnID8gc291cmNlIDogc291cmNlLnRvU3RyaW5nKClcbiAgICBjb25zdCBtYXBVcmxPcmlnaW5hbCA9IGdldFNvdXJjZU1hcHBpbmdVcmwoc291cmNlVGV4dClcbiAgICBpZiAoIW1hcFVybE9yaWdpbmFsIHx8IG1hcFVybE9yaWdpbmFsLmluZGV4T2YoJ2RhdGE6JykgPT09IDAgfHwgbWFwVXJsT3JpZ2luYWwuaW5kZXhPZignLycpID09PSAwKSB7XG4gICAgICByZXR1cm4gc291cmNlVGV4dFxuICAgIH1cbiAgICBjb25zdCBhc3NldERpciA9IHBhdGguZGlybmFtZShhc3NldFBhdGgpXG4gICAgY29uc3QgbWFwUGF0aCA9IHBhdGguam9pbihhc3NldERpciwgbWFwVXJsT3JpZ2luYWwpXG4gICAgY29uc3QgbWFwUGF0aFJlbGF0aXZlID0gcGF0aC5yZWxhdGl2ZShvdXQucGF0aCwgbWFwUGF0aClcbiAgICBjb25zdCBwdWJsaWNQYXRoID0gdHlwZW9mIG91dC5wdWJsaWNQYXRoID09PSAnc3RyaW5nJyA/IG91dC5wdWJsaWNQYXRoIDogJydcbiAgICBjb25zdCBtYXBVcmxDb3JyZWN0ZWQgPSB0b1Bvc2l4UGF0aChwYXRoLmpvaW4ocHVibGljUGF0aCwgbWFwUGF0aFJlbGF0aXZlKSlcbiAgICBjb25zdCByZWdleCA9IG5ldyBSZWdFeHAoYCR7ZXNjYXBlUmVnRXhwKG1hcFVybE9yaWdpbmFsKX0oXFxcXHMqKD86XFxcXCovKT9cXFxccyokKWApXG4gICAgcmV0dXJuIHNvdXJjZVRleHQucmVwbGFjZShyZWdleCwgKF9tYXRjaCwgZ3JvdXApID0+IGAke21hcFVybENvcnJlY3RlZH0ke2dyb3VwfWApXG4gIH1cblxuICAvLyBBZGFwdGVkIGZyb20gYGh0bWwtd2VicGFjay1pbmxpbmUtc291cmNlLXBsdWdpbmAncyBtZXRob2Qgb2YgdGhlIHNhbWUgbmFtZS5cbiAgLy8gQVRUUklCVVRJT046IEFEQVBUQVRJT04gfCBodG1sLXdlYnBhY2staW5saW5lLXNvdXJjZS1wbHVnaW4gfCBDb3B5cmlnaHQgKGMpIDIwMTYgSmFuIE5pY2tsYXMuIE1JVCBMaWNlbnNlZC5cbiAgcHJvY2Vzc1RhZyhjb21waWxhdGlvbjogQ29tcGlsYXRpb24sIHJlZ2V4OiBSZWdFeHAsIHRhZzogSHRtbFRhZ09iamVjdCk6IEh0bWxUYWdPYmplY3Qge1xuICAgIGxldCBhc3NldFVybDogc3RyaW5nIHwgdW5kZWZpbmVkXG4gICAgbGV0IHJlc3VsdFRhZyA9IHRhZ1xuXG4gICAgaWYgKHRhZy50YWdOYW1lID09PSAnc2NyaXB0JyAmJiByZWdleC50ZXN0KHRhZy5hdHRyaWJ1dGVzLnNyYyBhcyBzdHJpbmcpKSB7XG4gICAgICBhc3NldFVybCA9IHRhZy5hdHRyaWJ1dGVzLnNyYyBhcyBzdHJpbmdcbiAgICAgIHJlc3VsdFRhZyA9IHsgdGFnTmFtZTogJ3NjcmlwdCcsIHZvaWRUYWc6IGZhbHNlLCBtZXRhOiB7fSwgYXR0cmlidXRlczogeyB0eXBlOiAndGV4dC9qYXZhc2NyaXB0JyB9IH1cbiAgICB9IGVsc2UgaWYgKHRhZy50YWdOYW1lID09PSAnbGluaycgJiYgcmVnZXgudGVzdCh0YWcuYXR0cmlidXRlcy5ocmVmIGFzIHN0cmluZykpIHtcbiAgICAgIGFzc2V0VXJsID0gdGFnLmF0dHJpYnV0ZXMuaHJlZiBhcyBzdHJpbmdcbiAgICAgIHJlc3VsdFRhZyA9IHsgdGFnTmFtZTogJ3N0eWxlJywgdm9pZFRhZzogZmFsc2UsIG1ldGE6IHt9LCBhdHRyaWJ1dGVzOiB7IHR5cGU6ICd0ZXh0L2NzcycgfSB9XG4gICAgfVxuXG4gICAgaWYgKGFzc2V0VXJsKSB7XG4gICAgICBjb25zdCBwdWJsaWNVcmxQcmVmaXggPSB0eXBlb2YgY29tcGlsYXRpb24ub3V0cHV0T3B0aW9ucy5wdWJsaWNQYXRoID09PSAnc3RyaW5nJyA/IGNvbXBpbGF0aW9uLm91dHB1dE9wdGlvbnMucHVibGljUGF0aCA6ICcnXG4gICAgICBjb25zdCBhc3NldE5hbWUgPSBwYXRoLnBvc2l4LnJlbGF0aXZlKHB1YmxpY1VybFByZWZpeCwgYXNzZXRVcmwpXG4gICAgICBjb25zdCBhc3NldCA9IGNvbXBpbGF0aW9uLmFzc2V0c1thc3NldE5hbWVdXG4gICAgICBpZiAoIWFzc2V0KSB7XG4gICAgICAgIHJldHVybiByZXN1bHRUYWdcbiAgICAgIH1cbiAgICAgIGNvbnN0IHVwZGF0ZWRTb3VyY2UgPSB0aGlzLnJlc29sdmVTb3VyY2VNYXBzKGNvbXBpbGF0aW9uLCBhc3NldE5hbWUsIGFzc2V0KVxuICAgICAgcmVzdWx0VGFnLmlubmVySFRNTCA9IHJlc3VsdFRhZy50YWdOYW1lID09PSAnc2NyaXB0JyA/IHVwZGF0ZWRTb3VyY2UucmVwbGFjZSgvKDwpKFxcL3NjcmlwdD4pL2csICdcXFxceDNDJDInKSA6IHVwZGF0ZWRTb3VyY2VcbiAgICB9XG5cbiAgICByZXR1cm4gcmVzdWx0VGFnXG4gIH1cblxuICAvLyBBZGFwdGVkIGZyb20gYGh0bWwtd2VicGFjay1pbmxpbmUtc291cmNlLXBsdWdpbmAncyBtZXRob2Qgb2YgdGhlIHNhbWUgbmFtZS5cbiAgLy8gQVRUUklCVVRJT046IEFEQVBUQVRJT04gfCBodG1sLXdlYnBhY2staW5saW5lLXNvdXJjZS1wbHVnaW4gfCBDb3B5cmlnaHQgKGMpIDIwMTYgSmFuIE5pY2tsYXMuIE1JVCBMaWNlbnNlZC5cbiAgcHJvY2Vzc1RhZ3MoY29tcGlsYXRpb246IENvbXBpbGF0aW9uLCBwbHVnaW5EYXRhOiBUZW1wbGF0ZUV4ZWN1dGlvbkRhdGFUeXBlKTogVGVtcGxhdGVFeGVjdXRpb25EYXRhVHlwZSB7XG4gICAgY29uc3QgYXNzZXRzUmVnRXhwID0gdGhpcy5hc3NldHNSZWdFeHBcbiAgICBpZiAoIWFzc2V0c1JlZ0V4cCkge1xuICAgICAgcmV0dXJuIHBsdWdpbkRhdGFcbiAgICB9XG4gICAgY29uc3QgaGVhZFRhZ3M6IHR5cGVvZiBwbHVnaW5EYXRhLmhlYWRUYWdzID0gW11cbiAgICBjb25zdCBib2R5VGFnczogdHlwZW9mIHBsdWdpbkRhdGEuaGVhZFRhZ3MgPSBbXVxuXG4gICAgY29uc3QgeyBwdWJsaWNQYXRoIH0gPSBjb21waWxhdGlvbi5vdXRwdXRPcHRpb25zXG4gICAgY29uc3QgcHVibGljVXJsUHJlZml4ID0gdHlwZW9mIHB1YmxpY1BhdGggPT09ICdzdHJpbmcnID8gcHVibGljUGF0aCA6ICcnXG5cbiAgICAvLyBNaXJyb3JzIHByb2Nlc3NUYWcncyBvd24gbWF0Y2ggY29uZGl0aW9uIChzYW1lIHJlZ2V4LCBzYW1lIHRhZy10eXBlIGNoZWNrcykgdG8gcmVjb3JkXG4gICAgLy8gZXhhY3RseSB3aGljaCBhc3NldCB0aGlzIHRhZyB3aWxsIGNhdXNlIHRvIGJlIGlubGluZWQsIGlmIGFueSAtIHdpdGhvdXQgdGhpcywgdGhlXG4gICAgLy8gcHJvY2Vzc0Fzc2V0cyBob29rIGJlbG93IGhhcyBubyB3YXkgdG8ga25vdyB3aGljaCBhc3NldHMgd2VyZSBhY3R1YWxseSB0b3VjaGVkLiBXZSByZWNvcmRcbiAgICAvLyB0aGUgb3duaW5nIENIVU5LIHJhdGhlciB0aGFuIHRoZSBhc3NldCBuYW1lOiBhIGNodW5rJ3MgaWRlbnRpdHkgaXMgc3RhYmxlIGV2ZW4gd2hlbiBpdHNcbiAgICAvLyBjb250ZW50aGFzaCAoYW5kIHRoZXJlZm9yZSBmaWxlbmFtZSkgaXMgcmVjb21wdXRlZCBsYXRlciBieSBtaW5pZmljYXRpb24sIHNvIHJlc29sdmluZ1xuICAgIC8vIGBjaHVuay5maWxlc2Agd2hlbiBkZWxldGluZyAtIGluc3RlYWQgb2YgcmVwbGF5aW5nIGEgZmlsZW5hbWUgY2FwdHVyZWQgbm93IC0gc3Vydml2ZXMgdGhhdFxuICAgIC8vIHRpbWluZyBnYXAuXG4gICAgY29uc3QgdHJhY2tJbmxpbmVkQXNzZXQgPSAodGFnOiAodHlwZW9mIHBsdWdpbkRhdGEuaGVhZFRhZ3MpW251bWJlcl0pID0+IHtcbiAgICAgIGxldCBhc3NldFVybDogc3RyaW5nIHwgdW5kZWZpbmVkXG4gICAgICBpZiAodGFnLnRhZ05hbWUgPT09ICdzY3JpcHQnICYmIGFzc2V0c1JlZ0V4cC50ZXN0KHRhZy5hdHRyaWJ1dGVzLnNyYyBhcyBzdHJpbmcpKSB7XG4gICAgICAgIGFzc2V0VXJsID0gdGFnLmF0dHJpYnV0ZXMuc3JjIGFzIHN0cmluZ1xuICAgICAgfSBlbHNlIGlmICh0YWcudGFnTmFtZSA9PT0gJ2xpbmsnICYmIGFzc2V0c1JlZ0V4cC50ZXN0KHRhZy5hdHRyaWJ1dGVzLmhyZWYgYXMgc3RyaW5nKSkge1xuICAgICAgICBhc3NldFVybCA9IHRhZy5hdHRyaWJ1dGVzLmhyZWYgYXMgc3RyaW5nXG4gICAgICB9XG4gICAgICBpZiAoIWFzc2V0VXJsKSB7XG4gICAgICAgIHJldHVyblxuICAgICAgfVxuICAgICAgY29uc3QgYXNzZXROYW1lID0gcGF0aC5wb3NpeC5yZWxhdGl2ZShwdWJsaWNVcmxQcmVmaXgsIGFzc2V0VXJsKVxuICAgICAgY29uc3Qgb3duaW5nQ2h1bmsgPSBBcnJheS5mcm9tKGNvbXBpbGF0aW9uLmNodW5rcykuZmluZCgoY2h1bmspID0+IGNodW5rLmZpbGVzLmhhcyhhc3NldE5hbWUpKVxuICAgICAgdGhpcy5pbmxpbmVkQ2h1bmtzID0gdGhpcy5pbmxpbmVkQ2h1bmtzID8/IG5ldyBTZXQoKVxuICAgICAgdGhpcy5pbmxpbmVkQ2h1bmtzLmFkZChvd25pbmdDaHVuayA/PyBhc3NldE5hbWUpXG4gICAgfVxuXG4gICAgcGx1Z2luRGF0YS5oZWFkVGFncy5mb3JFYWNoKCh0YWcpID0+IHtcbiAgICAgIHRyYWNrSW5saW5lZEFzc2V0KHRhZylcbiAgICAgIGhlYWRUYWdzLnB1c2godGhpcy5wcm9jZXNzVGFnKGNvbXBpbGF0aW9uLCBhc3NldHNSZWdFeHAsIHRhZykpXG4gICAgfSlcblxuICAgIHBsdWdpbkRhdGEuYm9keVRhZ3MuZm9yRWFjaCgodGFnKSA9PiB7XG4gICAgICB0cmFja0lubGluZWRBc3NldCh0YWcpXG4gICAgICBib2R5VGFncy5wdXNoKHRoaXMucHJvY2Vzc1RhZyhjb21waWxhdGlvbiwgYXNzZXRzUmVnRXhwLCB0YWcpKVxuICAgIH0pXG5cbiAgICByZXR1cm4geyAuLi5wbHVnaW5EYXRhLCBoZWFkVGFncywgYm9keVRhZ3MgfVxuICB9XG5cbiAgLy8gQXNzZXRzIHRoYXQgZXhpc3QgaW4gdGhlIGNvbXBpbGF0aW9uIGJ1dCB3ZXJlIG5ldmVyIHJlZmVyZW5jZWQgYnkgYSA8c2NyaXB0Pi88bGluaz4gdGFnIChlLmcuXG4gIC8vIGEgbGljZW5zZS1ub3RpY2VzIGZpbGUgd3JpdHRlbiBkaXJlY3RseSB2aWEgY29tcGlsYXRpb24uZW1pdEFzc2V0KSBoYXZlIG5vdGhpbmcgZm9yXG4gIC8vIHByb2Nlc3NUYWdzIHRvIG1hdGNoIGFnYWluc3QgLSBlbWJlZCB0aGVtIGV4cGxpY2l0bHkgaW5zdGVhZCwga2V5ZWQgYnkgYXNzZXQgbmFtZSBzbyBjb25zdW1pbmdcbiAgLy8gY29kZSBjYW4gcmVhZCB0aGVtIGJhY2sgb3V0IG9mIHRoZSBET00gYXQgcnVudGltZS4gYHdyYXBwZXJgIHBpY2tzIHRoZSBtYXJrdXAgKGFuIG9wYXF1ZSxcbiAgLy8gbm9uLWV4ZWN1dGluZyA8c2NyaXB0Piwgb3IgYSBwbGFpbiBIVE1MIGNvbW1lbnQgLSBiYXNlNjQgbmV2ZXIgY29udGFpbnMgYC0tYCwgc28gaXQgY2FuJ3RcbiAgLy8gcHJlbWF0dXJlbHkgY2xvc2UgdGhlIGNvbW1lbnQpOyBgY29udGFpbmVyYCBwaWNrcyB3aGVyZSBpdCBsYW5kcy5cbiAgLy9cbiAgLy8gVGhpcyBydW5zIGFnYWluc3QgdGhlIGFscmVhZHktZW1pdHRlZCBIVE1MIGFzc2V0IChzZWUgdGhlIHByb2Nlc3NBc3NldHMgaG9vayBiZWxvdyksIG5vdFxuICAvLyBhZ2FpbnN0IHBsdWdpbkRhdGEgaW5zaWRlIGFmdGVyVGVtcGxhdGVFeGVjdXRpb24gLSBzb21lIHBsdWdpbnMgdGhhdCBlbWl0IG1hdGNoYWJsZSBhc3NldHNcbiAgLy8gKGUuZy4gd2VicGFjay1saWNlbnNlLXBsdWdpbiwgd2hpY2ggd3JpdGVzIGl0cyBub3RpY2VzIGZpbGUgYXQgUFJPQ0VTU19BU1NFVFNfU1RBR0VfQU5BTFlTRSlcbiAgLy8gZG8gc28gd2VsbCBhZnRlciBodG1sLXdlYnBhY2stcGx1Z2luIGhhcyBhbHJlYWR5IHJlbmRlcmVkIGFuZCBlbWl0dGVkIGl0cyBIVE1MLCBzbyBzY2FubmluZ1xuICAvLyBjb21waWxhdGlvbi5hc3NldHMgZnJvbSBpbnNpZGUgYWZ0ZXJUZW1wbGF0ZUV4ZWN1dGlvbiB3b3VsZCBzaWxlbnRseSBtaXNzIHRoZW0uIFNpbmNlIHRoZXJlJ3NcbiAgLy8gbm8gaGVhZFRhZ3MvYm9keVRhZ3MgYXJyYXkgdG8gcHVzaCBhIEh0bWxUYWdPYmplY3QgaW50byBhdCB0aGlzIHBvaW50LCAnc2NyaXB0Jy13cmFwcGVkIG1hcmt1cFxuICAvLyBpcyBzcGxpY2VkIGludG8gdGhlIGh0bWwgc3RyaW5nIHRoZSBzYW1lIHdheSAnY29tbWVudCctd3JhcHBlZCBtYXJrdXAgYWxyZWFkeSB3YXMuXG4gIHByb2Nlc3NBZGRpdGlvbmFsQXNzZXRzKGNvbXBpbGF0aW9uOiBDb21waWxhdGlvbiwgaHRtbDogc3RyaW5nKTogc3RyaW5nIHtcbiAgICBsZXQgcmVzdWx0ID0gaHRtbFxuXG4gICAgY29uc3QgYWRkaXRpb25hbEFzc2V0cyA9IHRoaXMuYWRkaXRpb25hbEFzc2V0cyA/PyBbXVxuICAgIGFkZGl0aW9uYWxBc3NldHMuZm9yRWFjaCgoeyBwYXR0ZXJuLCB3cmFwcGVyLCBjb250YWluZXIgfSkgPT4ge1xuICAgICAgT2JqZWN0LmtleXMoY29tcGlsYXRpb24uYXNzZXRzKVxuICAgICAgICAuZmlsdGVyKChuYW1lKSA9PiBuYW1lICE9PSB0aGlzLmh0bWxBc3NldE5hbWUgJiYgcGF0dGVybi50ZXN0KG5hbWUpKVxuICAgICAgICAuZm9yRWFjaCgobmFtZSkgPT4ge1xuICAgICAgICAgIGNvbnN0IGVuY29kZWQgPSBjb21waWxhdGlvbi5hc3NldHNbbmFtZV0hLmJ1ZmZlcigpLnRvU3RyaW5nKCdiYXNlNjQnKVxuICAgICAgICAgIHRoaXMuaW5saW5lZENodW5rcyA9IHRoaXMuaW5saW5lZENodW5rcyA/PyBuZXcgU2V0KClcbiAgICAgICAgICB0aGlzLmlubGluZWRDaHVua3MuYWRkKG5hbWUpXG5cbiAgICAgICAgICBjb25zdCBtYXJrdXAgPSBidWlsZEFkZGl0aW9uYWxBc3NldE1hcmt1cCh3cmFwcGVyLCBuYW1lLCBlbmNvZGVkKVxuICAgICAgICAgIHJlc3VsdCA9IGNvbnRhaW5lciA9PT0gJ2hlYWQnIHx8IGNvbnRhaW5lciA9PT0gJ2JvZHknID8gaW5zZXJ0QmVmb3JlQ2xvc2luZ1RhZyhyZXN1bHQsIGNvbnRhaW5lciwgbWFya3VwKSA6IGAke3Jlc3VsdH0ke21hcmt1cH1gXG4gICAgICAgIH0pXG4gICAgfSlcblxuICAgIHJldHVybiByZXN1bHRcbiAgfVxuXG4gIGFwcGx5KGNvbXBpbGVyOiBDb21waWxlcikge1xuICAgIHRoaXMuYXNzZXRzUmVnRXhwID0gdW5kZWZpbmVkXG4gICAgdGhpcy5mYXZpY29uUGF0aCA9IHVuZGVmaW5lZFxuICAgIHRoaXMuaW5saW5lZENodW5rcyA9IG5ldyBTZXQ8Q2h1bmsgfCBzdHJpbmc+KClcblxuICAgIGNvbXBpbGVyLmhvb2tzLmNvbXBpbGF0aW9uLnRhcCgnaHRtbC1pbmxpbmUtc291cmNlLXBsdWdpbicsIChjb21waWxhdGlvbikgPT4ge1xuICAgICAgSHRtbFdlYnBhY2tQbHVnaW4uZ2V0SG9va3MoY29tcGlsYXRpb24pLmFmdGVyVGVtcGxhdGVFeGVjdXRpb24udGFwQXN5bmMoJ2h0bWwtaW5saW5lLXNvdXJjZS1wbHVnaW4nLCAoaHRtbFBsdWdpbkRhdGEsIGNhbGxiYWNrKSA9PiB7XG4gICAgICAgIHRoaXMuYXNzZXRzUmVnRXhwID0gbmV3IFJlZ0V4cCgnLihqc3xjc3MpJCcpXG4gICAgICAgIHRoaXMuaHRtbEFzc2V0TmFtZSA9IGh0bWxQbHVnaW5EYXRhLm91dHB1dE5hbWVcbiAgICAgICAgY29uc3QgcmVzdWx0ID0gdGhpcy5wcm9jZXNzVGFncyhjb21waWxhdGlvbiwgaHRtbFBsdWdpbkRhdGEpXG5cbiAgICAgICAgY29uc3QgZmF2aWNvbiA9IGh0bWxQbHVnaW5EYXRhLnBsdWdpbi5vcHRpb25zPy5mYXZpY29uXG4gICAgICAgIGNvbnN0IGlucHV0RnMgPSBjb21waWxlci5pbnB1dEZpbGVTeXN0ZW0gYXMgdW5rbm93biBhcyBJU3luY0ZpbGVTeXN0ZW1cbiAgICAgICAgaWYgKCFmYXZpY29uIHx8ICFpbnB1dEZzLmV4aXN0c1N5bmMoZmF2aWNvbikpIHtcbiAgICAgICAgICByZXR1cm4gY2FsbGJhY2sobnVsbCwgcmVzdWx0KVxuICAgICAgICB9XG4gICAgICAgIGNvbnN0IGZhdmljb25UYWcgPSByZXN1bHQuaGVhZFRhZ3MuZmluZCgodGFnKSA9PiB0YWcudGFnTmFtZSA9PT0gJ2xpbmsnICYmIHRhZy5hdHRyaWJ1dGVzLnJlbCA9PT0gJ2ljb24nKVxuICAgICAgICBpZiAoZmF2aWNvblRhZykge1xuICAgICAgICAgIHRoaXMuZmF2aWNvblBhdGggPSBmYXZpY29uVGFnLmF0dHJpYnV0ZXMuaHJlZiBhcyBzdHJpbmdcbiAgICAgICAgICBmYXZpY29uVGFnLmF0dHJpYnV0ZXMuaHJlZiA9IGBkYXRhOmltYWdlL3gtaWNvbjtiYXNlNjQsICR7aW5wdXRGcy5yZWFkRmlsZVN5bmMoZmF2aWNvbiwgJ2Jhc2U2NCcpfWBcbiAgICAgICAgfVxuICAgICAgICBjYWxsYmFjayhudWxsLCByZXN1bHQpXG4gICAgICB9KVxuXG4gICAgICAvLyBQYXRjaGVzIHRoZSBhbHJlYWR5LWVtaXR0ZWQgSFRNTCBhc3NldCBkaXJlY3RseSAoc2VlIHByb2Nlc3NBZGRpdGlvbmFsQXNzZXRzJyBvd24gY29tbWVudFxuICAgICAgLy8gZm9yIHdoeSB0aGlzIGNhbid0IGhhcHBlbiBpbnNpZGUgYWZ0ZXJUZW1wbGF0ZUV4ZWN1dGlvbiBhYm92ZSkgYW5kIG11c3QgcnVuIHN0cmljdGx5XG4gICAgICAvLyBiZWZvcmUgdGhlIGRlbGV0aW9uIHBhc3MgYmVsb3cgLSBzYW1lIHByb2Nlc3NBc3NldHMgc3RhZ2UsIGJ1dCB0YXBwZWQgZmlyc3QsIHNvIFRhcGFibGUnc1xuICAgICAgLy8gc3RhYmxlIHNhbWUtc3RhZ2Ugb3JkZXJpbmcgcnVucyB0aGlzIG9uZSBmaXJzdC5cbiAgICAgIGNvbXBpbGF0aW9uLmhvb2tzLnByb2Nlc3NBc3NldHMudGFwKFxuICAgICAgICB7IG5hbWU6ICdodG1sLWlubGluZS1zb3VyY2UtcGx1Z2luJywgc3RhZ2U6IGNvbXBpbGVyLndlYnBhY2suQ29tcGlsYXRpb24uUFJPQ0VTU19BU1NFVFNfU1RBR0VfUkVQT1JUIH0sXG4gICAgICAgICgpID0+IHtcbiAgICAgICAgICBpZiAoIXRoaXMuaHRtbEFzc2V0TmFtZSkgcmV0dXJuXG4gICAgICAgICAgY29uc3QgaHRtbEFzc2V0ID0gY29tcGlsYXRpb24uYXNzZXRzW3RoaXMuaHRtbEFzc2V0TmFtZV1cbiAgICAgICAgICBpZiAoIWh0bWxBc3NldCkgcmV0dXJuXG4gICAgICAgICAgY29uc3QgaHRtbCA9IHRoaXMucHJvY2Vzc0FkZGl0aW9uYWxBc3NldHMoY29tcGlsYXRpb24sIGh0bWxBc3NldC5zb3VyY2UoKS50b1N0cmluZygpKVxuICAgICAgICAgIGNvbXBpbGF0aW9uLnVwZGF0ZUFzc2V0KHRoaXMuaHRtbEFzc2V0TmFtZSwgbmV3IGNvbXBpbGVyLndlYnBhY2suc291cmNlcy5SYXdTb3VyY2UoaHRtbCkpXG4gICAgICAgIH0sXG4gICAgICApXG5cbiAgICAgIC8vIE9ubHkgcmVtb3ZlIGFzc2V0cyB0aGF0IHdlcmUgYWN0dWFsbHkgaW5saW5lZCBpbnRvIHRoZSBIVE1MIGFib3ZlLiBCbGFua2V0LW1hdGNoaW5nIGJ5XG4gICAgICAvLyBleHRlbnNpb24gd291bGQgYWxzbyBkZWxldGUgdW5yZWxhdGVkIC5qcy8uY3NzIGFzc2V0cyB0aGF0IHdlcmUgbmV2ZXIgaW5saW5pbmcgY2FuZGlkYXRlc1xuICAgICAgLy8gaW4gdGhlIGZpcnN0IHBsYWNlIC0gZS5nLiBhIFdvcmtlciBjaHVuaywgd2hpY2ggYnJvd3NlcnMgbG9hZCB2aWEgdGhlIHNlcGFyYXRlIFdvcmtlciBBUElcbiAgICAgIC8vIHJhdGhlciB0aGFuIGEgPHNjcmlwdD4gdGFnLCBzbyBodG1sLXdlYnBhY2stcGx1Z2luIG5ldmVyIGdlbmVyYXRlcyBhIHRhZyBmb3IgaXQuXG4gICAgICAvLyBQUk9DRVNTX0FTU0VUU19TVEFHRV9SRVBPUlQgaXMgdGhlIGxhc3QgcHJvY2Vzc0Fzc2V0cyBzdGFnZSAtIGl0IHN0aWxsIHJ1bnMgYmVmb3JlXG4gICAgICAvLyBzZWFsaW5nIGZyZWV6ZXMgY29tcGlsYXRpb24uYXNzZXRzLCBzbyBjaHVuay5maWxlcyBoZXJlIGFscmVhZHkgcmVmbGVjdHMgYW55IGVhcmxpZXJcbiAgICAgIC8vIHN0YWdlJ3MgcmVuYW1lIChlLmcuIFRlcnNlcidzIGNvbnRlbnRoYXNoIHJlY29tcHV0ZSkuXG4gICAgICBjb21waWxhdGlvbi5ob29rcy5wcm9jZXNzQXNzZXRzLnRhcChcbiAgICAgICAgLy8gUmVhZCB0aGUgc3RhZ2UgY29uc3RhbnQgb2ZmIGNvbXBpbGVyLndlYnBhY2sgcmF0aGVyIHRoYW4gaW1wb3J0aW5nIENvbXBpbGF0aW9uIGFzIGFcbiAgICAgICAgLy8gdmFsdWUgZnJvbSAnd2VicGFjaycgZGlyZWN0bHkgLSB0aGUgcGx1Z2luIHRoZW4ga2VlcHMgd29ya2luZyBjb3JyZWN0bHkgZXZlbiBpZiB0aGVcbiAgICAgICAgLy8gaG9zdCBwcm9qZWN0IHJlc29sdmVzIGEgZGlmZmVyZW50IHdlYnBhY2sgaW5zdGFuY2UgdGhhbiB0aGUgb25lIGluIHRoaXMgcGFja2FnZSdzIG93blxuICAgICAgICAvLyBub2RlX21vZHVsZXMgKHRoZSBzdGFuZGFyZCByZWFzb24gd2VicGFjayBwbHVnaW5zIGF2b2lkIGEgZGlyZWN0IGByZXF1aXJlKCd3ZWJwYWNrJylgKS5cbiAgICAgICAgeyBuYW1lOiAnaHRtbC1pbmxpbmUtc291cmNlLXBsdWdpbicsIHN0YWdlOiBjb21waWxlci53ZWJwYWNrLkNvbXBpbGF0aW9uLlBST0NFU1NfQVNTRVRTX1NUQUdFX1JFUE9SVCB9LFxuICAgICAgICAoKSA9PiB7XG4gICAgICAgICAgdGhpcy5pbmxpbmVkQ2h1bmtzPy5mb3JFYWNoKChjaHVua09yTmFtZSkgPT4ge1xuICAgICAgICAgICAgaWYgKHR5cGVvZiBjaHVua09yTmFtZSA9PT0gJ3N0cmluZycpIHtcbiAgICAgICAgICAgICAgY29tcGlsYXRpb24uZGVsZXRlQXNzZXQoY2h1bmtPck5hbWUpXG4gICAgICAgICAgICAgIHJldHVyblxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY2h1bmtPck5hbWUuZmlsZXMuZm9yRWFjaCgoZmlsZSkgPT4ge1xuICAgICAgICAgICAgICBjb21waWxhdGlvbi5kZWxldGVBc3NldChmaWxlKVxuICAgICAgICAgICAgfSlcbiAgICAgICAgICB9KVxuICAgICAgICAgIGNvbnN0IGZhdmljb25GaWxlID0gdGhpcy5mYXZpY29uUGF0aD8uc3BsaXQocGF0aC5zZXApPy5wb3AoKVxuICAgICAgICAgIGlmIChmYXZpY29uRmlsZSkge1xuICAgICAgICAgICAgY29tcGlsYXRpb24uZGVsZXRlQXNzZXQoZmF2aWNvbkZpbGUpXG4gICAgICAgICAgfVxuICAgICAgICB9LFxuICAgICAgKVxuICAgIH0pXG4gIH1cbn1cblxuZXhwb3J0IGRlZmF1bHQgSHRtbElubGluZVNvdXJjZVBsdWdpblxuIl19
@@ -0,0 +1,10 @@
1
+ import { type Compiler, type WebpackPluginInstance } from 'webpack';
2
+ declare class SelfDecompressingHtmlPlugin implements WebpackPluginInstance {
3
+ htmlAssetName?: string;
4
+ loadingMarkup: string;
5
+ constructor({ loadingMarkup }?: {
6
+ loadingMarkup?: string;
7
+ });
8
+ apply(compiler: Compiler): void;
9
+ }
10
+ export default SelfDecompressingHtmlPlugin;
@@ -0,0 +1,119 @@
1
+ import HtmlWebpackPlugin from 'html-webpack-plugin';
2
+ import zlib from 'zlib';
3
+ const gzip = (text) => new Promise((resolve, reject) => zlib.gzip(text, (err, buf) => (err ? reject(err) : resolve(buf))));
4
+ const bodyRegExp = /<body([^>]*)>([\s\S]*)<\/body>/i;
5
+ // Shown in place of the real body while it decompresses - a body this size can take a visible
6
+ // moment to inflate, so leaving it blank would look broken. Overridable via the plugin's
7
+ // `loadingMarkup` option; this default covers both the transient styling and the spinner markup
8
+ // in one block, since neither has any meaning outside the other.
9
+ const defaultLoadingMarkup = `<style>
10
+ :root { color-scheme: light dark; }
11
+ html, body { height: 100%; margin: 0; }
12
+ body {
13
+ display: flex;
14
+ align-items: center;
15
+ justify-content: center;
16
+ background: #fff;
17
+ color: #111;
18
+ }
19
+ @media (prefers-color-scheme: dark) {
20
+ body { background: #111; color: #eee; }
21
+ }
22
+ .spinner {
23
+ width: 2.5rem;
24
+ height: 2.5rem;
25
+ border: 3px solid rgba(128, 128, 128, 0.3);
26
+ border-top-color: currentColor;
27
+ border-radius: 50%;
28
+ animation: spin 0.8s linear infinite;
29
+ }
30
+ @keyframes spin {
31
+ to { transform: rotate(360deg); }
32
+ }
33
+ </style>
34
+ <div class="spinner"></div>`;
35
+ // Inflates the gzipped, base64-encoded original body back into the page once it's ready, then
36
+ // swaps it in for the loading markup above. Rebuilds any <script> nodes via createElement/
37
+ // appendChild rather than assigning innerHTML/appendChild-ing template.content's parsed nodes
38
+ // directly - browsers deliberately don't execute a <script> that arrives either way, only one
39
+ // actually inserted via the DOM API, and the real body's inlined app bundle <script> has to run.
40
+ const bootstrapScript = (base64) => `<script>
41
+ (async () => {
42
+ try {
43
+ const bytes = Uint8Array.from(atob(${JSON.stringify(base64)}), (c) => c.charCodeAt(0))
44
+ const stream = new Blob([bytes]).stream().pipeThrough(new DecompressionStream('gzip'))
45
+ const bodyHtml = await new Response(stream).text()
46
+ const template = document.createElement('template')
47
+ template.innerHTML = bodyHtml
48
+ document.body.textContent = ''
49
+ Array.from(template.content.childNodes).forEach((node) => {
50
+ if (node.nodeName === 'SCRIPT') {
51
+ const script = document.createElement('script')
52
+ for (const attr of node.attributes) script.setAttribute(attr.name, attr.value)
53
+ script.textContent = node.textContent
54
+ document.body.appendChild(script)
55
+ } else {
56
+ document.body.appendChild(node)
57
+ }
58
+ })
59
+ } catch (err) {
60
+ document.body.textContent = 'Failed to decompress this page: ' + err.message
61
+ }
62
+ })()
63
+ </script>`;
64
+ // Gzips an HTML asset's <body> content and replaces it with a small loading placeholder plus a
65
+ // script that inflates and reinstates the original body client-side, via the browser's native
66
+ // DecompressionStream - <head> (title, meta tags, favicon, any inlined <style>/<link>) is left
67
+ // completely untouched, since html-webpack-plugin/htmlConfigFactory already built that correctly
68
+ // and there's no reason to reconstruct it. Unlike a build-time-only gzip step (e.g. a .gz sidecar
69
+ // file), this needs no server/Content-Encoding support to pay off - decompression happens
70
+ // entirely client-side in the loaded page - so it works for content served statically or opened
71
+ // directly from disk. Only replaces the body when the wrapped version actually comes out
72
+ // smaller, since gzip + base64's ~33% overhead can lose against a small/already-dense body.
73
+ class SelfDecompressingHtmlPlugin {
74
+ htmlAssetName;
75
+ loadingMarkup;
76
+ constructor({ loadingMarkup = defaultLoadingMarkup } = {}) {
77
+ this.loadingMarkup = loadingMarkup;
78
+ }
79
+ apply(compiler) {
80
+ compiler.hooks.compilation.tap('self-decompressing-html-plugin', (compilation) => {
81
+ // Capture the exact asset this plugin should act on - the one page the paired
82
+ // HtmlWebpackPlugin instance in this same htmlConfigFactory() call produced - the same way
83
+ // HtmlInlineSourcePlugin does. A pattern matched against all of compilation.assets (as an
84
+ // earlier version of this plugin did) would misfire in a multi-page build with several
85
+ // HtmlWebpackPlugin instances, touching pages this plugin instance has nothing to do with.
86
+ HtmlWebpackPlugin.getHooks(compilation).afterTemplateExecution.tap('self-decompressing-html-plugin', (htmlPluginData) => {
87
+ this.htmlAssetName = htmlPluginData.outputName;
88
+ return htmlPluginData;
89
+ });
90
+ // PROCESS_ASSETS_STAGE_REPORT is the last named processAssets stage - tapping a further
91
+ // 1000 past it, rather than at that same stage, guarantees this always runs after any
92
+ // other plugin's REPORT-stage work (e.g. an html-inlining plugin still rewriting the html
93
+ // asset at that same stage) regardless of plugin registration order, since this asset must
94
+ // be genuinely final before its body is gzipped.
95
+ compilation.hooks.processAssets.tapPromise({ name: 'self-decompressing-html-plugin', stage: compiler.webpack.Compilation.PROCESS_ASSETS_STAGE_REPORT + 1000 }, async () => {
96
+ if (!this.htmlAssetName)
97
+ return;
98
+ const htmlAsset = compilation.assets[this.htmlAssetName];
99
+ if (!htmlAsset)
100
+ return;
101
+ const html = htmlAsset.source().toString();
102
+ const match = html.match(bodyRegExp);
103
+ if (!match)
104
+ return;
105
+ const [fullMatch, bodyAttrs, bodyContent] = match;
106
+ if (bodyContent === undefined)
107
+ return;
108
+ const gzipped = await gzip(bodyContent);
109
+ const newBody = `<body${bodyAttrs}>${this.loadingMarkup}${bootstrapScript(gzipped.toString('base64'))}</body>`;
110
+ const wrapped = html.slice(0, match.index) + newBody + html.slice(match.index + fullMatch.length);
111
+ if (wrapped.length >= html.length)
112
+ return;
113
+ compilation.updateAsset(this.htmlAssetName, new compiler.webpack.sources.RawSource(wrapped));
114
+ });
115
+ });
116
+ }
117
+ }
118
+ export default SelfDecompressingHtmlPlugin;
119
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiU2VsZkRlY29tcHJlc3NpbmdIdG1sUGx1Z2luLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL3BsdWdpbnMvU2VsZkRlY29tcHJlc3NpbmdIdG1sUGx1Z2luLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8saUJBQWlCLE1BQU0scUJBQXFCLENBQUE7QUFFbkQsT0FBTyxJQUFJLE1BQU0sTUFBTSxDQUFBO0FBRXZCLE1BQU0sSUFBSSxHQUFHLENBQUMsSUFBWSxFQUFtQixFQUFFLENBQzdDLElBQUksT0FBTyxDQUFDLENBQUMsT0FBTyxFQUFFLE1BQU0sRUFBRSxFQUFFLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxJQUFJLEVBQUUsQ0FBQyxHQUFHLEVBQUUsR0FBRyxFQUFFLEVBQUUsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsTUFBTSxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxPQUFPLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUE7QUFFckcsTUFBTSxVQUFVLEdBQUcsaUNBQWlDLENBQUE7QUFFcEQsOEZBQThGO0FBQzlGLHlGQUF5RjtBQUN6RixnR0FBZ0c7QUFDaEcsaUVBQWlFO0FBQ2pFLE1BQU0sb0JBQW9CLEdBQUc7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7NEJBeUJELENBQUE7QUFFNUIsOEZBQThGO0FBQzlGLDJGQUEyRjtBQUMzRiw4RkFBOEY7QUFDOUYsOEZBQThGO0FBQzlGLGlHQUFpRztBQUNqRyxNQUFNLGVBQWUsR0FBRyxDQUFDLE1BQWMsRUFBRSxFQUFFLENBQUM7Ozt5Q0FHSCxJQUFJLENBQUMsU0FBUyxDQUFDLE1BQU0sQ0FBQzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7VUFvQnJELENBQUE7QUFFViwrRkFBK0Y7QUFDL0YsOEZBQThGO0FBQzlGLCtGQUErRjtBQUMvRixpR0FBaUc7QUFDakcsa0dBQWtHO0FBQ2xHLDBGQUEwRjtBQUMxRixnR0FBZ0c7QUFDaEcseUZBQXlGO0FBQ3pGLDRGQUE0RjtBQUM1RixNQUFNLDJCQUEyQjtJQUMvQixhQUFhLENBQVM7SUFDdEIsYUFBYSxDQUFRO0lBRXJCLFlBQVksRUFBRSxhQUFhLEdBQUcsb0JBQW9CLEtBQWlDLEVBQUU7UUFDbkYsSUFBSSxDQUFDLGFBQWEsR0FBRyxhQUFhLENBQUE7SUFDcEMsQ0FBQztJQUVELEtBQUssQ0FBQyxRQUFrQjtRQUN0QixRQUFRLENBQUMsS0FBSyxDQUFDLFdBQVcsQ0FBQyxHQUFHLENBQUMsZ0NBQWdDLEVBQUUsQ0FBQyxXQUF3QixFQUFFLEVBQUU7WUFDNUYsOEVBQThFO1lBQzlFLDJGQUEyRjtZQUMzRiwwRkFBMEY7WUFDMUYsdUZBQXVGO1lBQ3ZGLDJGQUEyRjtZQUMzRixpQkFBaUIsQ0FBQyxRQUFRLENBQUMsV0FBVyxDQUFDLENBQUMsc0JBQXNCLENBQUMsR0FBRyxDQUFDLGdDQUFnQyxFQUFFLENBQUMsY0FBYyxFQUFFLEVBQUU7Z0JBQ3RILElBQUksQ0FBQyxhQUFhLEdBQUcsY0FBYyxDQUFDLFVBQVUsQ0FBQTtnQkFDOUMsT0FBTyxjQUFjLENBQUE7WUFDdkIsQ0FBQyxDQUFDLENBQUE7WUFFRix3RkFBd0Y7WUFDeEYsc0ZBQXNGO1lBQ3RGLDBGQUEwRjtZQUMxRiwyRkFBMkY7WUFDM0YsaURBQWlEO1lBQ2pELFdBQVcsQ0FBQyxLQUFLLENBQUMsYUFBYSxDQUFDLFVBQVUsQ0FDeEMsRUFBRSxJQUFJLEVBQUUsZ0NBQWdDLEVBQUUsS0FBSyxFQUFFLFFBQVEsQ0FBQyxPQUFPLENBQUMsV0FBVyxDQUFDLDJCQUEyQixHQUFHLElBQUksRUFBRSxFQUNsSCxLQUFLLElBQUksRUFBRTtnQkFDVCxJQUFJLENBQUMsSUFBSSxDQUFDLGFBQWE7b0JBQUUsT0FBTTtnQkFDL0IsTUFBTSxTQUFTLEdBQUcsV0FBVyxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsYUFBYSxDQUFDLENBQUE7Z0JBQ3hELElBQUksQ0FBQyxTQUFTO29CQUFFLE9BQU07Z0JBRXRCLE1BQU0sSUFBSSxHQUFHLFNBQVMsQ0FBQyxNQUFNLEVBQUUsQ0FBQyxRQUFRLEVBQUUsQ0FBQTtnQkFDMUMsTUFBTSxLQUFLLEdBQUcsSUFBSSxDQUFDLEtBQUssQ0FBQyxVQUFVLENBQUMsQ0FBQTtnQkFDcEMsSUFBSSxDQUFDLEtBQUs7b0JBQUUsT0FBTTtnQkFFbEIsTUFBTSxDQUFDLFNBQVMsRUFBRSxTQUFTLEVBQUUsV0FBVyxDQUFDLEdBQUcsS0FBSyxDQUFBO2dCQUNqRCxJQUFJLFdBQVcsS0FBSyxTQUFTO29CQUFFLE9BQU07Z0JBQ3JDLE1BQU0sT0FBTyxHQUFHLE1BQU0sSUFBSSxDQUFDLFdBQVcsQ0FBQyxDQUFBO2dCQUN2QyxNQUFNLE9BQU8sR0FBRyxRQUFRLFNBQVMsSUFBSSxJQUFJLENBQUMsYUFBYSxHQUFHLGVBQWUsQ0FBQyxPQUFPLENBQUMsUUFBUSxDQUFDLFFBQVEsQ0FBQyxDQUFDLFNBQVMsQ0FBQTtnQkFDOUcsTUFBTSxPQUFPLEdBQUcsSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFDLEVBQUUsS0FBSyxDQUFDLEtBQUssQ0FBQyxHQUFHLE9BQU8sR0FBRyxJQUFJLENBQUMsS0FBSyxDQUFDLEtBQUssQ0FBQyxLQUFNLEdBQUcsU0FBUyxDQUFDLE1BQU0sQ0FBQyxDQUFBO2dCQUNsRyxJQUFJLE9BQU8sQ0FBQyxNQUFNLElBQUksSUFBSSxDQUFDLE1BQU07b0JBQUUsT0FBTTtnQkFFekMsV0FBVyxDQUFDLFdBQVcsQ0FBQyxJQUFJLENBQUMsYUFBYSxFQUFFLElBQUksUUFBUSxDQUFDLE9BQU8sQ0FBQyxPQUFPLENBQUMsU0FBUyxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUE7WUFDOUYsQ0FBQyxDQUNGLENBQUE7UUFDSCxDQUFDLENBQUMsQ0FBQTtJQUNKLENBQUM7Q0FDRjtBQUVELGVBQWUsMkJBQTJCLENBQUEiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgSHRtbFdlYnBhY2tQbHVnaW4gZnJvbSAnaHRtbC13ZWJwYWNrLXBsdWdpbidcbmltcG9ydCB7IHR5cGUgQ29tcGlsYXRpb24sIHR5cGUgQ29tcGlsZXIsIHR5cGUgV2VicGFja1BsdWdpbkluc3RhbmNlIH0gZnJvbSAnd2VicGFjaydcbmltcG9ydCB6bGliIGZyb20gJ3psaWInXG5cbmNvbnN0IGd6aXAgPSAodGV4dDogc3RyaW5nKTogUHJvbWlzZTxCdWZmZXI+ID0+XG4gIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHpsaWIuZ3ppcCh0ZXh0LCAoZXJyLCBidWYpID0+IChlcnIgPyByZWplY3QoZXJyKSA6IHJlc29sdmUoYnVmKSkpKVxuXG5jb25zdCBib2R5UmVnRXhwID0gLzxib2R5KFtePl0qKT4oW1xcc1xcU10qKTxcXC9ib2R5Pi9pXG5cbi8vIFNob3duIGluIHBsYWNlIG9mIHRoZSByZWFsIGJvZHkgd2hpbGUgaXQgZGVjb21wcmVzc2VzIC0gYSBib2R5IHRoaXMgc2l6ZSBjYW4gdGFrZSBhIHZpc2libGVcbi8vIG1vbWVudCB0byBpbmZsYXRlLCBzbyBsZWF2aW5nIGl0IGJsYW5rIHdvdWxkIGxvb2sgYnJva2VuLiBPdmVycmlkYWJsZSB2aWEgdGhlIHBsdWdpbidzXG4vLyBgbG9hZGluZ01hcmt1cGAgb3B0aW9uOyB0aGlzIGRlZmF1bHQgY292ZXJzIGJvdGggdGhlIHRyYW5zaWVudCBzdHlsaW5nIGFuZCB0aGUgc3Bpbm5lciBtYXJrdXBcbi8vIGluIG9uZSBibG9jaywgc2luY2UgbmVpdGhlciBoYXMgYW55IG1lYW5pbmcgb3V0c2lkZSB0aGUgb3RoZXIuXG5jb25zdCBkZWZhdWx0TG9hZGluZ01hcmt1cCA9IGA8c3R5bGU+XG4gIDpyb290IHsgY29sb3Itc2NoZW1lOiBsaWdodCBkYXJrOyB9XG4gIGh0bWwsIGJvZHkgeyBoZWlnaHQ6IDEwMCU7IG1hcmdpbjogMDsgfVxuICBib2R5IHtcbiAgICBkaXNwbGF5OiBmbGV4O1xuICAgIGFsaWduLWl0ZW1zOiBjZW50ZXI7XG4gICAganVzdGlmeS1jb250ZW50OiBjZW50ZXI7XG4gICAgYmFja2dyb3VuZDogI2ZmZjtcbiAgICBjb2xvcjogIzExMTtcbiAgfVxuICBAbWVkaWEgKHByZWZlcnMtY29sb3Itc2NoZW1lOiBkYXJrKSB7XG4gICAgYm9keSB7IGJhY2tncm91bmQ6ICMxMTE7IGNvbG9yOiAjZWVlOyB9XG4gIH1cbiAgLnNwaW5uZXIge1xuICAgIHdpZHRoOiAyLjVyZW07XG4gICAgaGVpZ2h0OiAyLjVyZW07XG4gICAgYm9yZGVyOiAzcHggc29saWQgcmdiYSgxMjgsIDEyOCwgMTI4LCAwLjMpO1xuICAgIGJvcmRlci10b3AtY29sb3I6IGN1cnJlbnRDb2xvcjtcbiAgICBib3JkZXItcmFkaXVzOiA1MCU7XG4gICAgYW5pbWF0aW9uOiBzcGluIDAuOHMgbGluZWFyIGluZmluaXRlO1xuICB9XG4gIEBrZXlmcmFtZXMgc3BpbiB7XG4gICAgdG8geyB0cmFuc2Zvcm06IHJvdGF0ZSgzNjBkZWcpOyB9XG4gIH1cbjwvc3R5bGU+XG48ZGl2IGNsYXNzPVwic3Bpbm5lclwiPjwvZGl2PmBcblxuLy8gSW5mbGF0ZXMgdGhlIGd6aXBwZWQsIGJhc2U2NC1lbmNvZGVkIG9yaWdpbmFsIGJvZHkgYmFjayBpbnRvIHRoZSBwYWdlIG9uY2UgaXQncyByZWFkeSwgdGhlblxuLy8gc3dhcHMgaXQgaW4gZm9yIHRoZSBsb2FkaW5nIG1hcmt1cCBhYm92ZS4gUmVidWlsZHMgYW55IDxzY3JpcHQ+IG5vZGVzIHZpYSBjcmVhdGVFbGVtZW50L1xuLy8gYXBwZW5kQ2hpbGQgcmF0aGVyIHRoYW4gYXNzaWduaW5nIGlubmVySFRNTC9hcHBlbmRDaGlsZC1pbmcgdGVtcGxhdGUuY29udGVudCdzIHBhcnNlZCBub2Rlc1xuLy8gZGlyZWN0bHkgLSBicm93c2VycyBkZWxpYmVyYXRlbHkgZG9uJ3QgZXhlY3V0ZSBhIDxzY3JpcHQ+IHRoYXQgYXJyaXZlcyBlaXRoZXIgd2F5LCBvbmx5IG9uZVxuLy8gYWN0dWFsbHkgaW5zZXJ0ZWQgdmlhIHRoZSBET00gQVBJLCBhbmQgdGhlIHJlYWwgYm9keSdzIGlubGluZWQgYXBwIGJ1bmRsZSA8c2NyaXB0PiBoYXMgdG8gcnVuLlxuY29uc3QgYm9vdHN0cmFwU2NyaXB0ID0gKGJhc2U2NDogc3RyaW5nKSA9PiBgPHNjcmlwdD5cbihhc3luYyAoKSA9PiB7XG4gIHRyeSB7XG4gICAgY29uc3QgYnl0ZXMgPSBVaW50OEFycmF5LmZyb20oYXRvYigke0pTT04uc3RyaW5naWZ5KGJhc2U2NCl9KSwgKGMpID0+IGMuY2hhckNvZGVBdCgwKSlcbiAgICBjb25zdCBzdHJlYW0gPSBuZXcgQmxvYihbYnl0ZXNdKS5zdHJlYW0oKS5waXBlVGhyb3VnaChuZXcgRGVjb21wcmVzc2lvblN0cmVhbSgnZ3ppcCcpKVxuICAgIGNvbnN0IGJvZHlIdG1sID0gYXdhaXQgbmV3IFJlc3BvbnNlKHN0cmVhbSkudGV4dCgpXG4gICAgY29uc3QgdGVtcGxhdGUgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCd0ZW1wbGF0ZScpXG4gICAgdGVtcGxhdGUuaW5uZXJIVE1MID0gYm9keUh0bWxcbiAgICBkb2N1bWVudC5ib2R5LnRleHRDb250ZW50ID0gJydcbiAgICBBcnJheS5mcm9tKHRlbXBsYXRlLmNvbnRlbnQuY2hpbGROb2RlcykuZm9yRWFjaCgobm9kZSkgPT4ge1xuICAgICAgaWYgKG5vZGUubm9kZU5hbWUgPT09ICdTQ1JJUFQnKSB7XG4gICAgICAgIGNvbnN0IHNjcmlwdCA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ3NjcmlwdCcpXG4gICAgICAgIGZvciAoY29uc3QgYXR0ciBvZiBub2RlLmF0dHJpYnV0ZXMpIHNjcmlwdC5zZXRBdHRyaWJ1dGUoYXR0ci5uYW1lLCBhdHRyLnZhbHVlKVxuICAgICAgICBzY3JpcHQudGV4dENvbnRlbnQgPSBub2RlLnRleHRDb250ZW50XG4gICAgICAgIGRvY3VtZW50LmJvZHkuYXBwZW5kQ2hpbGQoc2NyaXB0KVxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgZG9jdW1lbnQuYm9keS5hcHBlbmRDaGlsZChub2RlKVxuICAgICAgfVxuICAgIH0pXG4gIH0gY2F0Y2ggKGVycikge1xuICAgIGRvY3VtZW50LmJvZHkudGV4dENvbnRlbnQgPSAnRmFpbGVkIHRvIGRlY29tcHJlc3MgdGhpcyBwYWdlOiAnICsgZXJyLm1lc3NhZ2VcbiAgfVxufSkoKVxuPC9zY3JpcHQ+YFxuXG4vLyBHemlwcyBhbiBIVE1MIGFzc2V0J3MgPGJvZHk+IGNvbnRlbnQgYW5kIHJlcGxhY2VzIGl0IHdpdGggYSBzbWFsbCBsb2FkaW5nIHBsYWNlaG9sZGVyIHBsdXMgYVxuLy8gc2NyaXB0IHRoYXQgaW5mbGF0ZXMgYW5kIHJlaW5zdGF0ZXMgdGhlIG9yaWdpbmFsIGJvZHkgY2xpZW50LXNpZGUsIHZpYSB0aGUgYnJvd3NlcidzIG5hdGl2ZVxuLy8gRGVjb21wcmVzc2lvblN0cmVhbSAtIDxoZWFkPiAodGl0bGUsIG1ldGEgdGFncywgZmF2aWNvbiwgYW55IGlubGluZWQgPHN0eWxlPi88bGluaz4pIGlzIGxlZnRcbi8vIGNvbXBsZXRlbHkgdW50b3VjaGVkLCBzaW5jZSBodG1sLXdlYnBhY2stcGx1Z2luL2h0bWxDb25maWdGYWN0b3J5IGFscmVhZHkgYnVpbHQgdGhhdCBjb3JyZWN0bHlcbi8vIGFuZCB0aGVyZSdzIG5vIHJlYXNvbiB0byByZWNvbnN0cnVjdCBpdC4gVW5saWtlIGEgYnVpbGQtdGltZS1vbmx5IGd6aXAgc3RlcCAoZS5nLiBhIC5neiBzaWRlY2FyXG4vLyBmaWxlKSwgdGhpcyBuZWVkcyBubyBzZXJ2ZXIvQ29udGVudC1FbmNvZGluZyBzdXBwb3J0IHRvIHBheSBvZmYgLSBkZWNvbXByZXNzaW9uIGhhcHBlbnNcbi8vIGVudGlyZWx5IGNsaWVudC1zaWRlIGluIHRoZSBsb2FkZWQgcGFnZSAtIHNvIGl0IHdvcmtzIGZvciBjb250ZW50IHNlcnZlZCBzdGF0aWNhbGx5IG9yIG9wZW5lZFxuLy8gZGlyZWN0bHkgZnJvbSBkaXNrLiBPbmx5IHJlcGxhY2VzIHRoZSBib2R5IHdoZW4gdGhlIHdyYXBwZWQgdmVyc2lvbiBhY3R1YWxseSBjb21lcyBvdXRcbi8vIHNtYWxsZXIsIHNpbmNlIGd6aXAgKyBiYXNlNjQncyB+MzMlIG92ZXJoZWFkIGNhbiBsb3NlIGFnYWluc3QgYSBzbWFsbC9hbHJlYWR5LWRlbnNlIGJvZHkuXG5jbGFzcyBTZWxmRGVjb21wcmVzc2luZ0h0bWxQbHVnaW4gaW1wbGVtZW50cyBXZWJwYWNrUGx1Z2luSW5zdGFuY2Uge1xuICBodG1sQXNzZXROYW1lPzogc3RyaW5nXG4gIGxvYWRpbmdNYXJrdXA6IHN0cmluZ1xuXG4gIGNvbnN0cnVjdG9yKHsgbG9hZGluZ01hcmt1cCA9IGRlZmF1bHRMb2FkaW5nTWFya3VwIH06IHsgbG9hZGluZ01hcmt1cD86IHN0cmluZyB9ID0ge30pIHtcbiAgICB0aGlzLmxvYWRpbmdNYXJrdXAgPSBsb2FkaW5nTWFya3VwXG4gIH1cblxuICBhcHBseShjb21waWxlcjogQ29tcGlsZXIpIHtcbiAgICBjb21waWxlci5ob29rcy5jb21waWxhdGlvbi50YXAoJ3NlbGYtZGVjb21wcmVzc2luZy1odG1sLXBsdWdpbicsIChjb21waWxhdGlvbjogQ29tcGlsYXRpb24pID0+IHtcbiAgICAgIC8vIENhcHR1cmUgdGhlIGV4YWN0IGFzc2V0IHRoaXMgcGx1Z2luIHNob3VsZCBhY3Qgb24gLSB0aGUgb25lIHBhZ2UgdGhlIHBhaXJlZFxuICAgICAgLy8gSHRtbFdlYnBhY2tQbHVnaW4gaW5zdGFuY2UgaW4gdGhpcyBzYW1lIGh0bWxDb25maWdGYWN0b3J5KCkgY2FsbCBwcm9kdWNlZCAtIHRoZSBzYW1lIHdheVxuICAgICAgLy8gSHRtbElubGluZVNvdXJjZVBsdWdpbiBkb2VzLiBBIHBhdHRlcm4gbWF0Y2hlZCBhZ2FpbnN0IGFsbCBvZiBjb21waWxhdGlvbi5hc3NldHMgKGFzIGFuXG4gICAgICAvLyBlYXJsaWVyIHZlcnNpb24gb2YgdGhpcyBwbHVnaW4gZGlkKSB3b3VsZCBtaXNmaXJlIGluIGEgbXVsdGktcGFnZSBidWlsZCB3aXRoIHNldmVyYWxcbiAgICAgIC8vIEh0bWxXZWJwYWNrUGx1Z2luIGluc3RhbmNlcywgdG91Y2hpbmcgcGFnZXMgdGhpcyBwbHVnaW4gaW5zdGFuY2UgaGFzIG5vdGhpbmcgdG8gZG8gd2l0aC5cbiAgICAgIEh0bWxXZWJwYWNrUGx1Z2luLmdldEhvb2tzKGNvbXBpbGF0aW9uKS5hZnRlclRlbXBsYXRlRXhlY3V0aW9uLnRhcCgnc2VsZi1kZWNvbXByZXNzaW5nLWh0bWwtcGx1Z2luJywgKGh0bWxQbHVnaW5EYXRhKSA9PiB7XG4gICAgICAgIHRoaXMuaHRtbEFzc2V0TmFtZSA9IGh0bWxQbHVnaW5EYXRhLm91dHB1dE5hbWVcbiAgICAgICAgcmV0dXJuIGh0bWxQbHVnaW5EYXRhXG4gICAgICB9KVxuXG4gICAgICAvLyBQUk9DRVNTX0FTU0VUU19TVEFHRV9SRVBPUlQgaXMgdGhlIGxhc3QgbmFtZWQgcHJvY2Vzc0Fzc2V0cyBzdGFnZSAtIHRhcHBpbmcgYSBmdXJ0aGVyXG4gICAgICAvLyAxMDAwIHBhc3QgaXQsIHJhdGhlciB0aGFuIGF0IHRoYXQgc2FtZSBzdGFnZSwgZ3VhcmFudGVlcyB0aGlzIGFsd2F5cyBydW5zIGFmdGVyIGFueVxuICAgICAgLy8gb3RoZXIgcGx1Z2luJ3MgUkVQT1JULXN0YWdlIHdvcmsgKGUuZy4gYW4gaHRtbC1pbmxpbmluZyBwbHVnaW4gc3RpbGwgcmV3cml0aW5nIHRoZSBodG1sXG4gICAgICAvLyBhc3NldCBhdCB0aGF0IHNhbWUgc3RhZ2UpIHJlZ2FyZGxlc3Mgb2YgcGx1Z2luIHJlZ2lzdHJhdGlvbiBvcmRlciwgc2luY2UgdGhpcyBhc3NldCBtdXN0XG4gICAgICAvLyBiZSBnZW51aW5lbHkgZmluYWwgYmVmb3JlIGl0cyBib2R5IGlzIGd6aXBwZWQuXG4gICAgICBjb21waWxhdGlvbi5ob29rcy5wcm9jZXNzQXNzZXRzLnRhcFByb21pc2UoXG4gICAgICAgIHsgbmFtZTogJ3NlbGYtZGVjb21wcmVzc2luZy1odG1sLXBsdWdpbicsIHN0YWdlOiBjb21waWxlci53ZWJwYWNrLkNvbXBpbGF0aW9uLlBST0NFU1NfQVNTRVRTX1NUQUdFX1JFUE9SVCArIDEwMDAgfSxcbiAgICAgICAgYXN5bmMgKCkgPT4ge1xuICAgICAgICAgIGlmICghdGhpcy5odG1sQXNzZXROYW1lKSByZXR1cm5cbiAgICAgICAgICBjb25zdCBodG1sQXNzZXQgPSBjb21waWxhdGlvbi5hc3NldHNbdGhpcy5odG1sQXNzZXROYW1lXVxuICAgICAgICAgIGlmICghaHRtbEFzc2V0KSByZXR1cm5cblxuICAgICAgICAgIGNvbnN0IGh0bWwgPSBodG1sQXNzZXQuc291cmNlKCkudG9TdHJpbmcoKVxuICAgICAgICAgIGNvbnN0IG1hdGNoID0gaHRtbC5tYXRjaChib2R5UmVnRXhwKVxuICAgICAgICAgIGlmICghbWF0Y2gpIHJldHVyblxuXG4gICAgICAgICAgY29uc3QgW2Z1bGxNYXRjaCwgYm9keUF0dHJzLCBib2R5Q29udGVudF0gPSBtYXRjaFxuICAgICAgICAgIGlmIChib2R5Q29udGVudCA9PT0gdW5kZWZpbmVkKSByZXR1cm5cbiAgICAgICAgICBjb25zdCBnemlwcGVkID0gYXdhaXQgZ3ppcChib2R5Q29udGVudClcbiAgICAgICAgICBjb25zdCBuZXdCb2R5ID0gYDxib2R5JHtib2R5QXR0cnN9PiR7dGhpcy5sb2FkaW5nTWFya3VwfSR7Ym9vdHN0cmFwU2NyaXB0KGd6aXBwZWQudG9TdHJpbmcoJ2Jhc2U2NCcpKX08L2JvZHk+YFxuICAgICAgICAgIGNvbnN0IHdyYXBwZWQgPSBodG1sLnNsaWNlKDAsIG1hdGNoLmluZGV4KSArIG5ld0JvZHkgKyBodG1sLnNsaWNlKG1hdGNoLmluZGV4ISArIGZ1bGxNYXRjaC5sZW5ndGgpXG4gICAgICAgICAgaWYgKHdyYXBwZWQubGVuZ3RoID49IGh0bWwubGVuZ3RoKSByZXR1cm5cblxuICAgICAgICAgIGNvbXBpbGF0aW9uLnVwZGF0ZUFzc2V0KHRoaXMuaHRtbEFzc2V0TmFtZSwgbmV3IGNvbXBpbGVyLndlYnBhY2suc291cmNlcy5SYXdTb3VyY2Uod3JhcHBlZCkpXG4gICAgICAgIH0sXG4gICAgICApXG4gICAgfSlcbiAgfVxufVxuXG5leHBvcnQgZGVmYXVsdCBTZWxmRGVjb21wcmVzc2luZ0h0bWxQbHVnaW5cbiJdfQ==
@@ -0,0 +1,5 @@
1
+ import type LicensePlugin from 'webpack-license-plugin';
2
+ type AdditionalFilesConfigType = NonNullable<NonNullable<ConstructorParameters<typeof LicensePlugin>[0]>['additionalFiles']>;
3
+ type PackageLicenseMetaType = Parameters<AdditionalFilesConfigType[string]>[0][number];
4
+ declare const formatThirdPartyNotices: (packages: PackageLicenseMetaType[]) => string;
5
+ export default formatThirdPartyNotices;
@@ -0,0 +1,11 @@
1
+ const formatThirdPartyNotices = (packages) => packages
2
+ .slice()
3
+ .sort((a, b) => a.name.localeCompare(b.name))
4
+ .map(({ name, version, license, author, repository, licenseText }) => {
5
+ const header = `${name}@${version} — ${license}${author ? ` — ${author}` : ''}${repository ? ` — ${repository}` : ''}`;
6
+ const body = (licenseText || '(license text unavailable)').trim();
7
+ return `${header}\n${'='.repeat(header.length)}\n\n${body}`;
8
+ })
9
+ .join('\n\n\n');
10
+ export default formatThirdPartyNotices;
11
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZm9ybWF0VGhpcmRQYXJ0eU5vdGljZXMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvcGx1Z2lucy9mb3JtYXRUaGlyZFBhcnR5Tm90aWNlcy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFLQSxNQUFNLHVCQUF1QixHQUFHLENBQUMsUUFBa0MsRUFBRSxFQUFFLENBQ3JFLFFBQVE7S0FDTCxLQUFLLEVBQUU7S0FDUCxJQUFJLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLGFBQWEsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLENBQUM7S0FDNUMsR0FBRyxDQUFDLENBQUMsRUFBRSxJQUFJLEVBQUUsT0FBTyxFQUFFLE9BQU8sRUFBRSxNQUFNLEVBQUUsVUFBVSxFQUFFLFdBQVcsRUFBRSxFQUFFLEVBQUU7SUFDbkUsTUFBTSxNQUFNLEdBQUcsR0FBRyxJQUFJLElBQUksT0FBTyxNQUFNLE9BQU8sR0FBRyxNQUFNLENBQUMsQ0FBQyxDQUFDLE1BQU0sTUFBTSxFQUFFLENBQUMsQ0FBQyxDQUFDLEVBQUUsR0FBRyxVQUFVLENBQUMsQ0FBQyxDQUFDLE1BQU0sVUFBVSxFQUFFLENBQUMsQ0FBQyxDQUFDLEVBQUUsRUFBRSxDQUFBO0lBQ3RILE1BQU0sSUFBSSxHQUFHLENBQUMsV0FBVyxJQUFJLDRCQUE0QixDQUFDLENBQUMsSUFBSSxFQUFFLENBQUE7SUFDakUsT0FBTyxHQUFHLE1BQU0sS0FBSyxHQUFHLENBQUMsTUFBTSxDQUFDLE1BQU0sQ0FBQyxNQUFNLENBQUMsT0FBTyxJQUFJLEVBQUUsQ0FBQTtBQUM3RCxDQUFDLENBQUM7S0FDRCxJQUFJLENBQUMsUUFBUSxDQUFDLENBQUE7QUFFbkIsZUFBZSx1QkFBdUIsQ0FBQSIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB0eXBlIExpY2Vuc2VQbHVnaW4gZnJvbSAnd2VicGFjay1saWNlbnNlLXBsdWdpbidcblxudHlwZSBBZGRpdGlvbmFsRmlsZXNDb25maWdUeXBlID0gTm9uTnVsbGFibGU8Tm9uTnVsbGFibGU8Q29uc3RydWN0b3JQYXJhbWV0ZXJzPHR5cGVvZiBMaWNlbnNlUGx1Z2luPlswXT5bJ2FkZGl0aW9uYWxGaWxlcyddPlxudHlwZSBQYWNrYWdlTGljZW5zZU1ldGFUeXBlID0gUGFyYW1ldGVyczxBZGRpdGlvbmFsRmlsZXNDb25maWdUeXBlW3N0cmluZ10+WzBdW251bWJlcl1cblxuY29uc3QgZm9ybWF0VGhpcmRQYXJ0eU5vdGljZXMgPSAocGFja2FnZXM6IFBhY2thZ2VMaWNlbnNlTWV0YVR5cGVbXSkgPT5cbiAgcGFja2FnZXNcbiAgICAuc2xpY2UoKVxuICAgIC5zb3J0KChhLCBiKSA9PiBhLm5hbWUubG9jYWxlQ29tcGFyZShiLm5hbWUpKVxuICAgIC5tYXAoKHsgbmFtZSwgdmVyc2lvbiwgbGljZW5zZSwgYXV0aG9yLCByZXBvc2l0b3J5LCBsaWNlbnNlVGV4dCB9KSA9PiB7XG4gICAgICBjb25zdCBoZWFkZXIgPSBgJHtuYW1lfUAke3ZlcnNpb259IOKAlCAke2xpY2Vuc2V9JHthdXRob3IgPyBgIOKAlCAke2F1dGhvcn1gIDogJyd9JHtyZXBvc2l0b3J5ID8gYCDigJQgJHtyZXBvc2l0b3J5fWAgOiAnJ31gXG4gICAgICBjb25zdCBib2R5ID0gKGxpY2Vuc2VUZXh0IHx8ICcobGljZW5zZSB0ZXh0IHVuYXZhaWxhYmxlKScpLnRyaW0oKVxuICAgICAgcmV0dXJuIGAke2hlYWRlcn1cXG4keyc9Jy5yZXBlYXQoaGVhZGVyLmxlbmd0aCl9XFxuXFxuJHtib2R5fWBcbiAgICB9KVxuICAgIC5qb2luKCdcXG5cXG5cXG4nKVxuXG5leHBvcnQgZGVmYXVsdCBmb3JtYXRUaGlyZFBhcnR5Tm90aWNlc1xuIl19
@@ -1,23 +1,32 @@
1
1
  import { BundleAnalyzerPlugin } from 'webpack-bundle-analyzer';
2
+ import LicensePlugin from 'webpack-license-plugin';
2
3
  import CssMinimizerPlugin from 'css-minimizer-webpack-plugin';
3
4
  import MiniCssExtractPlugin from 'mini-css-extract-plugin';
4
5
  import TerserPlugin from 'terser-webpack-plugin';
5
6
  import { MinifyOptions } from 'terser';
6
7
  import HtmlWebpackPlugin from 'html-webpack-plugin';
7
8
  import { type WebpackPluginInstance } from 'webpack';
9
+ import DefineEnvPlugin from './DefineEnvPlugin.js';
10
+ import HtmlInlineSourcePlugin from './HtmlInlineSourcePlugin.js';
11
+ import SelfDecompressingHtmlPlugin from './SelfDecompressingHtmlPlugin.js';
8
12
  export declare const cssConfigFactory: ({ filename, cssnanoOptions, }?: {
9
13
  filename?: string;
10
14
  cssnanoOptions?: any;
11
15
  }) => (MiniCssExtractPlugin | CssMinimizerPlugin<CssMinimizerPlugin.CssNanoOptionsExtended>)[];
12
16
  export declare const bundleAnalyzerConfigFactory: (extraConfig?: BundleAnalyzerPlugin.Options) => BundleAnalyzerPlugin[];
13
- export declare const htmlConfigFactory: ({ html, embed }?: {
14
- embed?: boolean;
17
+ type HtmlInlineSourceAdditionalAssetsType = NonNullable<InstanceType<typeof HtmlInlineSourcePlugin>['additionalAssets']>;
18
+ type SelfDecompressingHtmlOptionsType = ConstructorParameters<typeof SelfDecompressingHtmlPlugin>[0];
19
+ export declare const htmlConfigFactory: ({ html, embed, compress, }?: {
20
+ embed?: boolean | {
21
+ additionalAssets?: HtmlInlineSourceAdditionalAssetsType;
22
+ };
23
+ compress?: boolean | SelfDecompressingHtmlOptionsType;
15
24
  html?: Partial<HtmlWebpackPlugin.Options>;
16
25
  }) => WebpackPluginInstance[];
17
26
  export declare const terserConfigFactory: ({ enableSourcemaps, terserOptions, embed }?: {
18
- enableSourcemaps?: boolean;
19
- terserOptions?: MinifyOptions;
20
- embed?: boolean;
27
+ enableSourcemaps?: boolean | undefined;
28
+ terserOptions?: MinifyOptions | undefined;
29
+ embed?: boolean | undefined;
21
30
  }) => TerserPlugin<{
22
31
  compress: boolean | import("terser").CompressOptions;
23
32
  ecma?: import("terser").ECMA;
@@ -35,3 +44,6 @@ export declare const terserConfigFactory: ({ enableSourcemaps, terserOptions, em
35
44
  sourceMap: boolean | import("terser").SourceMapOptions;
36
45
  toplevel?: boolean;
37
46
  }>[];
47
+ export declare const defineEnvConfigFactory: (envVarNames: string[]) => DefineEnvPlugin[];
48
+ export declare const licenseConfigFactory: ({ outputFilename, includeNoticeText, additionalFiles, ...extraConfig }?: Partial<ConstructorParameters<typeof LicensePlugin>[0]>) => LicensePlugin[];
49
+ export {};