@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.
- package/NOTICE.md +11 -0
- package/compiler.helpers.d.ts +3 -3
- package/compiler.helpers.js +10 -19
- package/configs/index.d.ts +38 -2
- package/configs/index.js +9 -16
- package/index.d.ts +5 -5
- package/index.js +6 -40
- package/loaders/WebcomponentStyleLoader.d.ts +12 -5
- package/loaders/WebcomponentStyleLoader.js +77 -41
- package/loaders/index.d.ts +51 -10
- package/loaders/index.js +34 -35
- package/loaders/resolveWebcomponentStyleLoaderPath.cjs +9 -0
- package/loaders/resolveWebcomponentStyleLoaderPath.d.cts +2 -0
- package/package.json +31 -30
- package/plugins/DefineEnvPlugin.d.ts +7 -0
- package/plugins/DefineEnvPlugin.js +17 -0
- package/plugins/HtmlInlineSourcePlugin.d.ts +22 -0
- package/plugins/HtmlInlineSourcePlugin.js +236 -0
- package/plugins/SelfDecompressingHtmlPlugin.d.ts +10 -0
- package/plugins/SelfDecompressingHtmlPlugin.js +119 -0
- package/plugins/formatThirdPartyNotices.d.ts +5 -0
- package/plugins/formatThirdPartyNotices.js +11 -0
- package/plugins/index.d.ts +17 -5
- package/plugins/index.js +63 -34
- package/compiler.helpers.js.map +0 -1
- package/configs/index.js.map +0 -1
- package/index.js.map +0 -1
- package/loaders/WebcomponentStyleLoader.js.map +0 -1
- package/loaders/index.js.map +0 -1
- package/plugins/HtmlWebpackInlineSourcePlugin.d.ts +0 -2
- package/plugins/HtmlWebpackInlineSourcePlugin.js +0 -55
- package/plugins/HtmlWebpackInlineSourcePlugin.js.map +0 -1
- package/plugins/index.js.map +0 -1
|
@@ -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
|
package/plugins/index.d.ts
CHANGED
|
@@ -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
|
-
|
|
14
|
-
|
|
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 {};
|