@angular/ssr 0.0.0-PLACEHOLDER → 17.0.0-next.0
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/esm2022/index.mjs +9 -0
- package/esm2022/public_api.mjs +9 -0
- package/esm2022/src/common-engine.mjs +131 -0
- package/esm2022/src/inline-css-processor.mjs +170 -0
- package/fesm2022/ssr.mjs +289 -0
- package/fesm2022/ssr.mjs.map +1 -0
- package/index.d.ts +44 -0
- package/package.json +26 -3
- package/schematics/collection.json +9 -0
- package/schematics/ng-add/files/server.ts.template +67 -0
- package/schematics/ng-add/index.d.ts +10 -0
- package/schematics/ng-add/index.js +278 -0
- package/schematics/ng-add/index.mjs +252 -0
- package/schematics/ng-add/schema.d.ts +22 -0
- package/schematics/ng-add/schema.js +5 -0
- package/schematics/ng-add/schema.json +39 -0
- package/schematics/ng-add/schema.mjs +4 -0
- package/schematics/package.json +3 -0
- package/schematics/schematics.externs.js +0 -0
- package/schematics/utility/latest-versions/index.d.ts +8 -0
- package/schematics/utility/latest-versions/index.js +16 -0
- package/schematics/utility/latest-versions/index.mjs +13 -0
- package/schematics/utility/latest-versions/package.json +9 -0
- package/schematics/utility/utils.d.ts +22 -0
- package/schematics/utility/utils.js +127 -0
- package/schematics/utility/utils.mjs +95 -0
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright Google LLC All Rights Reserved.
|
|
4
|
+
*
|
|
5
|
+
* Use of this source code is governed by an MIT-style license that can be
|
|
6
|
+
* found in the LICENSE file at https://angular.io/license
|
|
7
|
+
*/
|
|
8
|
+
export * from './public_api';
|
|
9
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi9wYWNrYWdlcy9hbmd1bGFyL3Nzci9pbmRleC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7Ozs7O0dBTUc7QUFFSCxjQUFjLGNBQWMsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogQGxpY2Vuc2VcbiAqIENvcHlyaWdodCBHb29nbGUgTExDIEFsbCBSaWdodHMgUmVzZXJ2ZWQuXG4gKlxuICogVXNlIG9mIHRoaXMgc291cmNlIGNvZGUgaXMgZ292ZXJuZWQgYnkgYW4gTUlULXN0eWxlIGxpY2Vuc2UgdGhhdCBjYW4gYmVcbiAqIGZvdW5kIGluIHRoZSBMSUNFTlNFIGZpbGUgYXQgaHR0cHM6Ly9hbmd1bGFyLmlvL2xpY2Vuc2VcbiAqL1xuXG5leHBvcnQgKiBmcm9tICcuL3B1YmxpY19hcGknO1xuIl19
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright Google LLC All Rights Reserved.
|
|
4
|
+
*
|
|
5
|
+
* Use of this source code is governed by an MIT-style license that can be
|
|
6
|
+
* found in the LICENSE file at https://angular.io/license
|
|
7
|
+
*/
|
|
8
|
+
export { CommonEngine } from './src/common-engine';
|
|
9
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicHVibGljX2FwaS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uLy4uL3BhY2thZ2VzL2FuZ3VsYXIvc3NyL3B1YmxpY19hcGkudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7Ozs7OztHQU1HO0FBRUgsT0FBTyxFQUFFLFlBQVksRUFBNkIsTUFBTSxxQkFBcUIsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogQGxpY2Vuc2VcbiAqIENvcHlyaWdodCBHb29nbGUgTExDIEFsbCBSaWdodHMgUmVzZXJ2ZWQuXG4gKlxuICogVXNlIG9mIHRoaXMgc291cmNlIGNvZGUgaXMgZ292ZXJuZWQgYnkgYW4gTUlULXN0eWxlIGxpY2Vuc2UgdGhhdCBjYW4gYmVcbiAqIGZvdW5kIGluIHRoZSBMSUNFTlNFIGZpbGUgYXQgaHR0cHM6Ly9hbmd1bGFyLmlvL2xpY2Vuc2VcbiAqL1xuXG5leHBvcnQgeyBDb21tb25FbmdpbmUsIENvbW1vbkVuZ2luZVJlbmRlck9wdGlvbnMgfSBmcm9tICcuL3NyYy9jb21tb24tZW5naW5lJztcbiJdfQ==
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright Google LLC All Rights Reserved.
|
|
4
|
+
*
|
|
5
|
+
* Use of this source code is governed by an MIT-style license that can be
|
|
6
|
+
* found in the LICENSE file at https://angular.io/license
|
|
7
|
+
*/
|
|
8
|
+
import { INITIAL_CONFIG, renderApplication, renderModule, ɵSERVER_CONTEXT, } from '@angular/platform-server';
|
|
9
|
+
import * as fs from 'node:fs';
|
|
10
|
+
import { dirname, resolve } from 'node:path';
|
|
11
|
+
import { URL } from 'node:url';
|
|
12
|
+
import { InlineCriticalCssProcessor } from './inline-css-processor';
|
|
13
|
+
const SSG_MARKER_REGEXP = /ng-server-context=["']\w*\|?ssg\|?\w*["']/;
|
|
14
|
+
/**
|
|
15
|
+
* A common rendering engine utility. This abstracts the logic
|
|
16
|
+
* for handling the platformServer compiler, the module cache, and
|
|
17
|
+
* the document loader
|
|
18
|
+
*/
|
|
19
|
+
export class CommonEngine {
|
|
20
|
+
constructor(bootstrap, providers = []) {
|
|
21
|
+
this.bootstrap = bootstrap;
|
|
22
|
+
this.providers = providers;
|
|
23
|
+
this.templateCache = new Map();
|
|
24
|
+
this.pageIsSSG = new Map();
|
|
25
|
+
this.inlineCriticalCssProcessor = new InlineCriticalCssProcessor({
|
|
26
|
+
minify: false,
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Render an HTML document for a specific URL with specified
|
|
31
|
+
* render options
|
|
32
|
+
*/
|
|
33
|
+
async render(opts) {
|
|
34
|
+
const { inlineCriticalCss = true, url } = opts;
|
|
35
|
+
if (opts.publicPath && opts.documentFilePath && url !== undefined) {
|
|
36
|
+
const pathname = canParseUrl(url) ? new URL(url).pathname : url;
|
|
37
|
+
// Remove leading forward slash.
|
|
38
|
+
const pagePath = resolve(opts.publicPath, pathname.substring(1), 'index.html');
|
|
39
|
+
if (pagePath !== resolve(opts.documentFilePath)) {
|
|
40
|
+
// View path doesn't match with prerender path.
|
|
41
|
+
const pageIsSSG = this.pageIsSSG.get(pagePath);
|
|
42
|
+
if (pageIsSSG === undefined) {
|
|
43
|
+
if (await exists(pagePath)) {
|
|
44
|
+
const content = await fs.promises.readFile(pagePath, 'utf-8');
|
|
45
|
+
const isSSG = SSG_MARKER_REGEXP.test(content);
|
|
46
|
+
this.pageIsSSG.set(pagePath, isSSG);
|
|
47
|
+
if (isSSG) {
|
|
48
|
+
return content;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
else {
|
|
52
|
+
this.pageIsSSG.set(pagePath, false);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
else if (pageIsSSG) {
|
|
56
|
+
// Serve pre-rendered page.
|
|
57
|
+
return fs.promises.readFile(pagePath, 'utf-8');
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
// if opts.document dosen't exist then opts.documentFilePath must
|
|
62
|
+
const extraProviders = [
|
|
63
|
+
{ provide: ɵSERVER_CONTEXT, useValue: 'ssr' },
|
|
64
|
+
...(opts.providers ?? []),
|
|
65
|
+
...this.providers,
|
|
66
|
+
];
|
|
67
|
+
let document = opts.document;
|
|
68
|
+
if (!document && opts.documentFilePath) {
|
|
69
|
+
document = await this.getDocument(opts.documentFilePath);
|
|
70
|
+
}
|
|
71
|
+
if (document) {
|
|
72
|
+
extraProviders.push({
|
|
73
|
+
provide: INITIAL_CONFIG,
|
|
74
|
+
useValue: {
|
|
75
|
+
document,
|
|
76
|
+
url: opts.url,
|
|
77
|
+
},
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
const moduleOrFactory = this.bootstrap || opts.bootstrap;
|
|
81
|
+
if (!moduleOrFactory) {
|
|
82
|
+
throw new Error('A module or bootstrap option must be provided.');
|
|
83
|
+
}
|
|
84
|
+
const html = await (isBootstrapFn(moduleOrFactory)
|
|
85
|
+
? renderApplication(moduleOrFactory, { platformProviders: extraProviders })
|
|
86
|
+
: renderModule(moduleOrFactory, { extraProviders }));
|
|
87
|
+
if (!inlineCriticalCss) {
|
|
88
|
+
return html;
|
|
89
|
+
}
|
|
90
|
+
const { content, errors, warnings } = await this.inlineCriticalCssProcessor.process(html, {
|
|
91
|
+
outputPath: opts.publicPath ?? (opts.documentFilePath ? dirname(opts.documentFilePath) : ''),
|
|
92
|
+
});
|
|
93
|
+
// eslint-disable-next-line no-console
|
|
94
|
+
warnings?.forEach((m) => console.warn(m));
|
|
95
|
+
// eslint-disable-next-line no-console
|
|
96
|
+
errors?.forEach((m) => console.error(m));
|
|
97
|
+
return content;
|
|
98
|
+
}
|
|
99
|
+
/** Retrieve the document from the cache or the filesystem */
|
|
100
|
+
async getDocument(filePath) {
|
|
101
|
+
let doc = this.templateCache.get(filePath);
|
|
102
|
+
if (!doc) {
|
|
103
|
+
doc = await fs.promises.readFile(filePath, 'utf-8');
|
|
104
|
+
this.templateCache.set(filePath, doc);
|
|
105
|
+
}
|
|
106
|
+
return doc;
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
async function exists(path) {
|
|
110
|
+
try {
|
|
111
|
+
await fs.promises.access(path, fs.constants.F_OK);
|
|
112
|
+
return true;
|
|
113
|
+
}
|
|
114
|
+
catch {
|
|
115
|
+
return false;
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
function isBootstrapFn(value) {
|
|
119
|
+
// We can differentiate between a module and a bootstrap function by reading `cmp`:
|
|
120
|
+
return typeof value === 'function' && !('ɵmod' in value);
|
|
121
|
+
}
|
|
122
|
+
// The below can be removed in favor of URL.canParse() when Node.js 18 is dropped
|
|
123
|
+
function canParseUrl(url) {
|
|
124
|
+
try {
|
|
125
|
+
return !!new URL(url);
|
|
126
|
+
}
|
|
127
|
+
catch {
|
|
128
|
+
return false;
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29tbW9uLWVuZ2luZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uLy4uLy4uL3BhY2thZ2VzL2FuZ3VsYXIvc3NyL3NyYy9jb21tb24tZW5naW5lLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOzs7Ozs7R0FNRztBQUdILE9BQU8sRUFDTCxjQUFjLEVBQ2QsaUJBQWlCLEVBQ2pCLFlBQVksRUFDWixlQUFlLEdBQ2hCLE1BQU0sMEJBQTBCLENBQUM7QUFDbEMsT0FBTyxLQUFLLEVBQUUsTUFBTSxTQUFTLENBQUM7QUFDOUIsT0FBTyxFQUFFLE9BQU8sRUFBRSxPQUFPLEVBQUUsTUFBTSxXQUFXLENBQUM7QUFDN0MsT0FBTyxFQUFFLEdBQUcsRUFBRSxNQUFNLFVBQVUsQ0FBQztBQUMvQixPQUFPLEVBQUUsMEJBQTBCLEVBQUUsTUFBTSx3QkFBd0IsQ0FBQztBQUVwRSxNQUFNLGlCQUFpQixHQUFHLDJDQUEyQyxDQUFDO0FBb0J0RTs7OztHQUlHO0FBQ0gsTUFBTSxPQUFPLFlBQVk7SUFLdkIsWUFDVSxTQUFzRCxFQUN0RCxZQUE4QixFQUFFO1FBRGhDLGNBQVMsR0FBVCxTQUFTLENBQTZDO1FBQ3RELGNBQVMsR0FBVCxTQUFTLENBQXVCO1FBTnpCLGtCQUFhLEdBQUcsSUFBSSxHQUFHLEVBQWtCLENBQUM7UUFFMUMsY0FBUyxHQUFHLElBQUksR0FBRyxFQUFtQixDQUFDO1FBTXRELElBQUksQ0FBQywwQkFBMEIsR0FBRyxJQUFJLDBCQUEwQixDQUFDO1lBQy9ELE1BQU0sRUFBRSxLQUFLO1NBQ2QsQ0FBQyxDQUFDO0lBQ0wsQ0FBQztJQUVEOzs7T0FHRztJQUNILEtBQUssQ0FBQyxNQUFNLENBQUMsSUFBK0I7UUFDMUMsTUFBTSxFQUFFLGlCQUFpQixHQUFHLElBQUksRUFBRSxHQUFHLEVBQUUsR0FBRyxJQUFJLENBQUM7UUFFL0MsSUFBSSxJQUFJLENBQUMsVUFBVSxJQUFJLElBQUksQ0FBQyxnQkFBZ0IsSUFB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QztRQUVsRCxPQUFPLElBQUksQ0FBQztLQUNiO0lBQUMsTUFBTTtRQUNOLE9BQU8sS0FBSyxDQUFDO0tBQ2Q7QUFDSCxDQUFDO0FBRUQsU0FBUyxhQUFhLENBQUMsS0FBYztJQUNuQyxtRkFBbUY7SUFDbkYsT0FBTyxPQUFPLEtBQUssS0FBSyxVQUFVLElBQUksQ0FBQyxDQUFDLE1BQU0sSUFBSSxLQUFLLENBQUMsQ0FBQztBQUMzRCxDQUFDO0FBRUQsaUZBQWlGO0FBQ2pGLFNBQVMsV0FBVyxDQUFDLEdBQVc7SUFDOUIsSUFBSTtRQUNGLE9BQU8sQ0FBQyxDQUFDLElBQUksR0FBRyxDQUFDLEdBQUcsQ0FBQyxDQUFDO0tBQ3ZCO0lBQUMsTUFBTTtRQUNOLE9BQU8sS0FBSyxDQUFDO0tBQ2Q7QUFDSCxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBAbGljZW5zZVxuICogQ29weXJpZ2h0IEdvb2dsZSBMTEMgQWxsIFJpZ2h0cyBSZXNlcnZlZC5cbiAqXG4gKiBVc2Ugb2YgdGhpcyBzb3VyY2UgY29kZSBpcyBnb3Zlcm5lZCBieSBhbiBNSVQtc3R5bGUgbGljZW5zZSB0aGF0IGNhbiBiZVxuICogZm91bmQgaW4gdGhlIExJQ0VOU0UgZmlsZSBhdCBodHRwczovL2FuZ3VsYXIuaW8vbGljZW5zZVxuICovXG5cbmltcG9ydCB7IEFwcGxpY2F0aW9uUmVmLCBTdGF0aWNQcm92aWRlciwgVHlwZSB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHtcbiAgSU5JVElBTF9DT05GSUcsXG4gIHJlbmRlckFwcGxpY2F0aW9uLFxuICByZW5kZXJNb2R1bGUsXG4gIMm1U0VSVkVSX0NPTlRFWFQsXG59IGZyb20gJ0Bhbmd1bGFyL3BsYXRmb3JtLXNlcnZlcic7XG5pbXBvcnQgKiBhcyBmcyBmcm9tICdub2RlOmZzJztcbmltcG9ydCB7IGRpcm5hbWUsIHJlc29sdmUgfSBmcm9tICdub2RlOnBhdGgnO1xuaW1wb3J0IHsgVVJMIH0gZnJvbSAnbm9kZTp1cmwnO1xuaW1wb3J0IHsgSW5saW5lQ3JpdGljYWxDc3NQcm9jZXNzb3IgfSBmcm9tICcuL2lubGluZS1jc3MtcHJvY2Vzc29yJztcblxuY29uc3QgU1NHX01BUktFUl9SRUdFWFAgPSAvbmctc2VydmVyLWNvbnRleHQ9W1wiJ11cXHcqXFx8P3NzZ1xcfD9cXHcqW1wiJ10vO1xuXG5leHBvcnQgaW50ZXJmYWNlIENvbW1vbkVuZ2luZVJlbmRlck9wdGlvbnMge1xuICBib290c3RyYXA/OiBUeXBlPHt9PiB8ICgoKSA9PiBQcm9taXNlPEFwcGxpY2F0aW9uUmVmPik7XG4gIHByb3ZpZGVycz86IFN0YXRpY1Byb3ZpZGVyW107XG4gIHVybD86IHN0cmluZztcbiAgZG9jdW1lbnQ/OiBzdHJpbmc7XG4gIGRvY3VtZW50RmlsZVBhdGg/OiBzdHJpbmc7XG4gIC8qKlxuICAgKiBSZWR1Y2UgcmVuZGVyIGJsb2NraW5nIHJlcXVlc3RzIGJ5IGlubGluaW5nIGNyaXRpY2FsIENTUy5cbiAgICogRGVmYXVsdHMgdG8gdHJ1ZS5cbiAgICovXG4gIGlubGluZUNyaXRpY2FsQ3NzPzogYm9vbGVhbjtcbiAgLyoqXG4gICAqIEJhc2UgcGF0aCBsb2NhdGlvbiBvZiBpbmRleCBmaWxlLlxuICAgKiBEZWZhdWx0cyB0byB0aGUgJ2RvY3VtZW50RmlsZVBhdGgnIGRpcm5hbWUgd2hlbiBub3QgcHJvdmlkZWQuXG4gICAqL1xuICBwdWJsaWNQYXRoPzogc3RyaW5nO1xufVxuXG4vKipcbiAqIEEgY29tbW9uIHJlbmRlcmluZyBlbmdpbmUgdXRpbGl0eS4gVGhpcyBhYnN0cmFjdHMgdGhlIGxvZ2ljXG4gKiBmb3IgaGFuZGxpbmcgdGhlIHBsYXRmb3JtU2VydmVyIGNvbXBpbGVyLCB0aGUgbW9kdWxlIGNhY2hlLCBhbmRcbiAqIHRoZSBkb2N1bWVudCBsb2FkZXJcbiAqL1xuZXhwb3J0IGNsYXNzIENvbW1vbkVuZ2luZSB7XG4gIHByaXZhdGUgcmVhZG9ubHkgdGVtcGxhdGVDYWNoZSA9IG5ldyBNYXA8c3RyaW5nLCBzdHJpbmc+KCk7XG4gIHByaXZhdGUgcmVhZG9ubHkgaW5saW5lQ3JpdGljYWxDc3NQcm9jZXNzb3I6IElubGluZUNyaXRpY2FsQ3NzUHJvY2Vzc29yO1xuICBwcml2YXRlIHJlYWRvbmx5IHBhZ2VJc1NTRyA9IG5ldyBNYXA8c3RyaW5nLCBib29sZWFuPigpO1xuXG4gIGNvbnN0cnVjdG9yKFxuICAgIHByaXZhdGUgYm9vdHN0cmFwPzogVHlwZTx7fT4gfCAoKCkgPT4gUHJvbWlzZTxBcHBsaWNhdGlvblJlZj4pLFxuICAgIHByaXZhdGUgcHJvdmlkZXJzOiBTdGF0aWNQcm92aWRlcltdID0gW10sXG4gICkge1xuICAgIHRoaXMuaW5saW5lQ3JpdGljYWxDc3NQcm9jZXNzb3IgPSBuZXcgSW5saW5lQ3JpdGljYWxDc3NQcm9jZXNzb3Ioe1xuICAgICAgbWluaWZ5OiBmYWxzZSxcbiAgICB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZW5kZXIgYW4gSFRNTCBkb2N1bWVudCBmb3IgYSBzcGVjaWZpYyBVUkwgd2l0aCBzcGVjaWZpZWRcbiAgICogcmVuZGVyIG9wdGlvbnNcbiAgICovXG4gIGFzeW5jIHJlbmRlcihvcHRzOiBDb21tb25FbmdpbmVSZW5kZXJPcHRpb25zKTogUHJvbWlzZTxzdHJpbmc+IHtcbiAgICBjb25zdCB7IGlubGluZUNyaXRpY2FsQ3NzID0gdHJ1ZSwgdXJsIH0gPSBvcHRzO1xuXG4gICAgaWYgKG9wdHMucHVibGljUGF0aCAmJiBvcHRzLmRvY3VtZW50RmlsZVBhdGggJiYgdXJsICE9PSB1bmRlZmluZWQpIHtcbiAgICAgIGNvbnN0IHBhdGhuYW1lID0gY2FuUGFyc2VVcmwodXJsKSA/IG5ldyBVUkwodXJsKS5wYXRobmFtZSA6IHVybDtcbiAgICAgIC8vIFJlbW92ZSBsZWFkaW5nIGZvcndhcmQgc2xhc2guXG4gICAgICBjb25zdCBwYWdlUGF0aCA9IHJlc29sdmUob3B0cy5wdWJsaWNQYXRoLCBwYXRobmFtZS5zdWJzdHJpbmcoMSksICdpbmRleC5odG1sJyk7XG5cbiAgICAgIGlmIChwYWdlUGF0aCAhPT0gcmVzb2x2ZShvcHRzLmRvY3VtZW50RmlsZVBhdGgpKSB7XG4gICAgICAgIC8vIFZpZXcgcGF0aCBkb2Vzbid0IG1hdGNoIHdpdGggcHJlcmVuZGVyIHBhdGguXG4gICAgICAgIGNvbnN0IHBhZ2VJc1NTRyA9IHRoaXMucGFnZUlzU1NHLmdldChwYWdlUGF0aCk7XG4gICAgICAgIGlmIChwYWdlSXNTU0cgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgIGlmIChhd2FpdCBleGlzdHMocGFnZVBhdGgpKSB7XG4gICAgICAgICAgICBjb25zdCBjb250ZW50ID0gYXdhaXQgZnMucHJvbWlzZXMucmVhZEZpbGUocGFnZVBhdGgsICd1dGYtOCcpO1xuICAgICAgICAgICAgY29uc3QgaXNTU0cgPSBTU0dfTUFSS0VSX1JFR0VYUC50ZXN0KGNvbnRlbnQpO1xuICAgICAgICAgICAgdGhpcy5wYWdlSXNTU0cuc2V0KHBhZ2VQYXRoLCBpc1NTRyk7XG5cbiAgICAgICAgICAgIGlmIChpc1NTRykge1xuICAgICAgICAgICAgICByZXR1cm4gY29udGVudDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgdGhpcy5wYWdlSXNTU0cuc2V0KHBhZ2VQYXRoLCBmYWxzZSk7XG4gICAgICAgICAgfVxuICAgICAgICB9IGVsc2UgaWYgKHBhZ2VJc1NTRykge1xuICAgICAgICAgIC8vIFNlcnZlIHByZS1yZW5kZXJlZCBwYWdlLlxuICAgICAgICAgIHJldHVybiBmcy5wcm9taXNlcy5yZWFkRmlsZShwYWdlUGF0aCwgJ3V0Zi04Jyk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG5cbiAgICAvLyBpZiBvcHRzLmRvY3VtZW50IGRvc2VuJ3QgZXhpc3QgdGhlbiBvcHRzLmRvY3VtZW50RmlsZVBhdGggbXVzdFxuICAgIGNvbnN0IGV4dHJhUHJvdmlkZXJzOiBTdGF0aWNQcm92aWRlcltdID0gW1xuICAgICAgeyBwcm92aWRlOiDJtVNFUlZFUl9DT05URVhULCB1c2VWYWx1ZTogJ3NzcicgfSxcbiAgICAgIC4uLihvcHRzLnByb3ZpZGVycyA/PyBbXSksXG4gICAgICAuLi50aGlzLnByb3ZpZGVycyxcbiAgICBdO1xuXG4gICAgbGV0IGRvY3VtZW50ID0gb3B0cy5kb2N1bWVudDtcbiAgICBpZiAoIWRvY3VtZW50ICYmIG9wdHMuZG9jdW1lbnRGaWxlUGF0aCkge1xuICAgICAgZG9jdW1lbnQgPSBhd2FpdCB0aGlzLmdldERvY3VtZW50KG9wdHMuZG9jdW1lbnRGaWxlUGF0aCk7XG4gICAgfVxuXG4gICAgaWYgKGRvY3VtZW50KSB7XG4gICAgICBleHRyYVByb3ZpZGVycy5wdXNoKHtcbiAgICAgICAgcHJvdmlkZTogSU5JVElBTF9DT05GSUcsXG4gICAgICAgIHVzZVZhbHVlOiB7XG4gICAgICAgICAgZG9jdW1lbnQsXG4gICAgICAgICAgdXJsOiBvcHRzLnVybCxcbiAgICAgICAgfSxcbiAgICAgIH0pO1xuICAgIH1cblxuICAgIGNvbnN0IG1vZHVsZU9yRmFjdG9yeSA9IHRoaXMuYm9vdHN0cmFwIHx8IG9wdHMuYm9vdHN0cmFwO1xuICAgIGlmICghbW9kdWxlT3JGYWN0b3J5KSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ0EgbW9kdWxlIG9yIGJvb3RzdHJhcCBvcHRpb24gbXVzdCBiZSBwcm92aWRlZC4nKTtcbiAgICB9XG5cbiAgICBjb25zdCBodG1sID0gYXdhaXQgKGlzQm9vdHN0cmFwRm4obW9kdWxlT3JGYWN0b3J5KVxuICAgICAgPyByZW5kZXJBcHBsaWNhdGlvbihtb2R1bGVPckZhY3RvcnksIHsgcGxhdGZvcm1Qcm92aWRlcnM6IGV4dHJhUHJvdmlkZXJzIH0pXG4gICAgICA6IHJlbmRlck1vZHVsZShtb2R1bGVPckZhY3RvcnksIHsgZXh0cmFQcm92aWRlcnMgfSkpO1xuXG4gICAgaWYgKCFpbmxpbmVDcml0aWNhbENzcykge1xuICAgICAgcmV0dXJuIGh0bWw7XG4gICAgfVxuXG4gICAgY29uc3QgeyBjb250ZW50LCBlcnJvcnMsIHdhcm5pbmdzIH0gPSBhd2FpdCB0aGlzLmlubGluZUNyaXRpY2FsQ3NzUHJvY2Vzc29yLnByb2Nlc3MoaHRtbCwge1xuICAgICAgb3V0cHV0UGF0aDogb3B0cy5wdWJsaWNQYXRoID8/IChvcHRzLmRvY3VtZW50RmlsZVBhdGggPyBkaXJuYW1lKG9wdHMuZG9jdW1lbnRGaWxlUGF0aCkgOiAnJyksXG4gICAgfSk7XG5cbiAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgbm8tY29uc29sZVxuICAgIHdhcm5pbmdzPy5mb3JFYWNoKChtKSA9PiBjb25zb2xlLndhcm4obSkpO1xuICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBuby1jb25zb2xlXG4gICAgZXJyb3JzPy5mb3JFYWNoKChtKSA9PiBjb25zb2xlLmVycm9yKG0pKTtcblxuICAgIHJldHVybiBjb250ZW50O1xuICB9XG5cbiAgLyoqIFJldHJpZXZlIHRoZSBkb2N1bWVudCBmcm9tIHRoZSBjYWNoZSBvciB0aGUgZmlsZXN5c3RlbSAqL1xuICBwcml2YXRlIGFzeW5jIGdldERvY3VtZW50KGZpbGVQYXRoOiBzdHJpbmcpOiBQcm9taXNlPHN0cmluZz4ge1xuICAgIGxldCBkb2MgPSB0aGlzLnRlbXBsYXRlQ2FjaGUuZ2V0KGZpbGVQYXRoKTtcblxuICAgIGlmICghZG9jKSB7XG4gICAgICBkb2MgPSBhd2FpdCBmcy5wcm9taXNlcy5yZWFkRmlsZShmaWxlUGF0aCwgJ3V0Zi04Jyk7XG4gICAgICB0aGlzLnRlbXBsYXRlQ2FjaGUuc2V0KGZpbGVQYXRoLCBkb2MpO1xuICAgIH1cblxuICAgIHJldHVybiBkb2M7XG4gIH1cbn1cblxuYXN5bmMgZnVuY3Rpb24gZXhpc3RzKHBhdGg6IGZzLlBhdGhMaWtlKTogUHJvbWlzZTxib29sZWFuPiB7XG4gIHRyeSB7XG4gICAgYXdhaXQgZnMucHJvbWlzZXMuYWNjZXNzKHBhdGgsIGZzLmNvbnN0YW50cy5GX09LKTtcblxuICAgIHJldHVybiB0cnVlO1xuICB9IGNhdGNoIHtcbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cbn1cblxuZnVuY3Rpb24gaXNCb290c3RyYXBGbih2YWx1ZTogdW5rbm93bik6IHZhbHVlIGlzICgpID0+IFByb21pc2U8QXBwbGljYXRpb25SZWY+IHtcbiAgLy8gV2UgY2FuIGRpZmZlcmVudGlhdGUgYmV0d2VlbiBhIG1vZHVsZSBhbmQgYSBib290c3RyYXAgZnVuY3Rpb24gYnkgcmVhZGluZyBgY21wYDpcbiAgcmV0dXJuIHR5cGVvZiB2YWx1ZSA9PT0gJ2Z1bmN0aW9uJyAmJiAhKCfJtW1vZCcgaW4gdmFsdWUpO1xufVxuXG4vLyBUaGUgYmVsb3cgY2FuIGJlIHJlbW92ZWQgaW4gZmF2b3Igb2YgVVJMLmNhblBhcnNlKCkgd2hlbiBOb2RlLmpzIDE4IGlzIGRyb3BwZWRcbmZ1bmN0aW9uIGNhblBhcnNlVXJsKHVybDogc3RyaW5nKTogYm9vbGVhbiB7XG4gIHRyeSB7XG4gICAgcmV0dXJuICEhbmV3IFVSTCh1cmwpO1xuICB9IGNhdGNoIHtcbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cbn1cbiJdfQ==
|
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright Google LLC All Rights Reserved.
|
|
4
|
+
*
|
|
5
|
+
* Use of this source code is governed by an MIT-style license that can be
|
|
6
|
+
* found in the LICENSE file at https://angular.io/license
|
|
7
|
+
*/
|
|
8
|
+
import Critters from 'critters';
|
|
9
|
+
import { readFile } from 'node:fs/promises';
|
|
10
|
+
/**
|
|
11
|
+
* Pattern used to extract the media query set by Critters in an `onload` handler.
|
|
12
|
+
*/
|
|
13
|
+
const MEDIA_SET_HANDLER_PATTERN = /^this\.media=["'](.*)["'];?$/;
|
|
14
|
+
/**
|
|
15
|
+
* Name of the attribute used to save the Critters media query so it can be re-assigned on load.
|
|
16
|
+
*/
|
|
17
|
+
const CSP_MEDIA_ATTR = 'ngCspMedia';
|
|
18
|
+
/**
|
|
19
|
+
* Script text used to change the media value of the link tags.
|
|
20
|
+
*/
|
|
21
|
+
const LINK_LOAD_SCRIPT_CONTENT = [
|
|
22
|
+
`(() => {`,
|
|
23
|
+
// Save the `children` in a variable since they're a live DOM node collection.
|
|
24
|
+
// We iterate over the direct descendants, instead of going through a `querySelectorAll`,
|
|
25
|
+
// because we know that the tags will be directly inside the `head`.
|
|
26
|
+
` const children = document.head.children;`,
|
|
27
|
+
// Declare `onLoad` outside the loop to avoid leaking memory.
|
|
28
|
+
// Can't be an arrow function, because we need `this` to refer to the DOM node.
|
|
29
|
+
` function onLoad() {this.media = this.getAttribute('${CSP_MEDIA_ATTR}');}`,
|
|
30
|
+
// Has to use a plain for loop, because some browsers don't support
|
|
31
|
+
// `forEach` on `children` which is a `HTMLCollection`.
|
|
32
|
+
` for (let i = 0; i < children.length; i++) {`,
|
|
33
|
+
` const child = children[i];`,
|
|
34
|
+
` child.hasAttribute('${CSP_MEDIA_ATTR}') && child.addEventListener('load', onLoad);`,
|
|
35
|
+
` }`,
|
|
36
|
+
`})();`,
|
|
37
|
+
].join('\n');
|
|
38
|
+
class CrittersExtended extends Critters {
|
|
39
|
+
constructor(optionsExtended, resourceCache) {
|
|
40
|
+
super({
|
|
41
|
+
logger: {
|
|
42
|
+
warn: (s) => this.warnings.push(s),
|
|
43
|
+
error: (s) => this.errors.push(s),
|
|
44
|
+
info: () => { },
|
|
45
|
+
},
|
|
46
|
+
logLevel: 'warn',
|
|
47
|
+
path: optionsExtended.outputPath,
|
|
48
|
+
publicPath: optionsExtended.deployUrl,
|
|
49
|
+
compress: !!optionsExtended.minify,
|
|
50
|
+
pruneSource: false,
|
|
51
|
+
reduceInlineStyles: false,
|
|
52
|
+
mergeStylesheets: false,
|
|
53
|
+
// Note: if `preload` changes to anything other than `media`, the logic in
|
|
54
|
+
// `embedLinkedStylesheetOverride` will have to be updated.
|
|
55
|
+
preload: 'media',
|
|
56
|
+
noscriptFallback: true,
|
|
57
|
+
inlineFonts: true,
|
|
58
|
+
});
|
|
59
|
+
this.optionsExtended = optionsExtended;
|
|
60
|
+
this.resourceCache = resourceCache;
|
|
61
|
+
this.warnings = [];
|
|
62
|
+
this.errors = [];
|
|
63
|
+
this.addedCspScriptsDocuments = new WeakSet();
|
|
64
|
+
this.documentNonces = new WeakMap();
|
|
65
|
+
/**
|
|
66
|
+
* Override of the Critters `embedLinkedStylesheet` method
|
|
67
|
+
* that makes it work with Angular's CSP APIs.
|
|
68
|
+
*/
|
|
69
|
+
this.embedLinkedStylesheetOverride = async (link, document) => {
|
|
70
|
+
if (link.getAttribute('media') === 'print' && link.next?.name === 'noscript') {
|
|
71
|
+
// Workaround for https://github.com/GoogleChromeLabs/critters/issues/64
|
|
72
|
+
// NB: this is only needed for the webpack based builders.
|
|
73
|
+
const media = link.getAttribute('onload')?.match(MEDIA_SET_HANDLER_PATTERN);
|
|
74
|
+
if (media) {
|
|
75
|
+
link.removeAttribute('onload');
|
|
76
|
+
link.setAttribute('media', media[1]);
|
|
77
|
+
link?.next?.remove();
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
const returnValue = await this.initialEmbedLinkedStylesheet(link, document);
|
|
81
|
+
const cspNonce = this.findCspNonce(document);
|
|
82
|
+
if (cspNonce) {
|
|
83
|
+
const crittersMedia = link.getAttribute('onload')?.match(MEDIA_SET_HANDLER_PATTERN);
|
|
84
|
+
if (crittersMedia) {
|
|
85
|
+
// If there's a Critters-generated `onload` handler and the file has an Angular CSP nonce,
|
|
86
|
+
// we have to remove the handler, because it's incompatible with CSP. We save the value
|
|
87
|
+
// in a different attribute and we generate a script tag with the nonce that uses
|
|
88
|
+
// `addEventListener` to apply the media query instead.
|
|
89
|
+
link.removeAttribute('onload');
|
|
90
|
+
link.setAttribute(CSP_MEDIA_ATTR, crittersMedia[1]);
|
|
91
|
+
this.conditionallyInsertCspLoadingScript(document, cspNonce);
|
|
92
|
+
}
|
|
93
|
+
// Ideally we would hook in at the time Critters inserts the `style` tags, but there isn't
|
|
94
|
+
// a way of doing that at the moment so we fall back to doing it any time a `link` tag is
|
|
95
|
+
// inserted. We mitigate it by only iterating the direct children of the `<head>` which
|
|
96
|
+
// should be pretty shallow.
|
|
97
|
+
document.head.children.forEach((child) => {
|
|
98
|
+
if (child.tagName === 'style' && !child.hasAttribute('nonce')) {
|
|
99
|
+
child.setAttribute('nonce', cspNonce);
|
|
100
|
+
}
|
|
101
|
+
});
|
|
102
|
+
}
|
|
103
|
+
return returnValue;
|
|
104
|
+
};
|
|
105
|
+
// We can't use inheritance to override `embedLinkedStylesheet`, because it's not declared in
|
|
106
|
+
// the `Critters` .d.ts which means that we can't call the `super` implementation. TS doesn't
|
|
107
|
+
// allow for `super` to be cast to a different type.
|
|
108
|
+
this.initialEmbedLinkedStylesheet = this.embedLinkedStylesheet;
|
|
109
|
+
this.embedLinkedStylesheet = this.embedLinkedStylesheetOverride;
|
|
110
|
+
}
|
|
111
|
+
async readFile(path) {
|
|
112
|
+
let resourceContent = this.resourceCache.get(path);
|
|
113
|
+
if (resourceContent === undefined) {
|
|
114
|
+
resourceContent = await readFile(path, 'utf-8');
|
|
115
|
+
this.resourceCache.set(path, resourceContent);
|
|
116
|
+
}
|
|
117
|
+
return resourceContent;
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* Finds the CSP nonce for a specific document.
|
|
121
|
+
*/
|
|
122
|
+
findCspNonce(document) {
|
|
123
|
+
if (this.documentNonces.has(document)) {
|
|
124
|
+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
125
|
+
return this.documentNonces.get(document);
|
|
126
|
+
}
|
|
127
|
+
// HTML attribute are case-insensitive, but the parser used by Critters is case-sensitive.
|
|
128
|
+
const nonceElement = document.querySelector('[ngCspNonce], [ngcspnonce]');
|
|
129
|
+
const cspNonce = nonceElement?.getAttribute('ngCspNonce') || nonceElement?.getAttribute('ngcspnonce') || null;
|
|
130
|
+
this.documentNonces.set(document, cspNonce);
|
|
131
|
+
return cspNonce;
|
|
132
|
+
}
|
|
133
|
+
/**
|
|
134
|
+
* Inserts the `script` tag that swaps the critical CSS at runtime,
|
|
135
|
+
* if one hasn't been inserted into the document already.
|
|
136
|
+
*/
|
|
137
|
+
conditionallyInsertCspLoadingScript(document, nonce) {
|
|
138
|
+
if (this.addedCspScriptsDocuments.has(document)) {
|
|
139
|
+
return;
|
|
140
|
+
}
|
|
141
|
+
if (document.head.textContent.includes(LINK_LOAD_SCRIPT_CONTENT)) {
|
|
142
|
+
// Script was already added during the build.
|
|
143
|
+
this.addedCspScriptsDocuments.add(document);
|
|
144
|
+
return;
|
|
145
|
+
}
|
|
146
|
+
const script = document.createElement('script');
|
|
147
|
+
script.setAttribute('nonce', nonce);
|
|
148
|
+
script.textContent = LINK_LOAD_SCRIPT_CONTENT;
|
|
149
|
+
// Append the script to the head since it needs to
|
|
150
|
+
// run as early as possible, after the `link` tags.
|
|
151
|
+
document.head.appendChild(script);
|
|
152
|
+
this.addedCspScriptsDocuments.add(document);
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
export class InlineCriticalCssProcessor {
|
|
156
|
+
constructor(options) {
|
|
157
|
+
this.options = options;
|
|
158
|
+
this.resourceCache = new Map();
|
|
159
|
+
}
|
|
160
|
+
async process(html, options) {
|
|
161
|
+
const critters = new CrittersExtended({ ...this.options, ...options }, this.resourceCache);
|
|
162
|
+
const content = await critters.process(html);
|
|
163
|
+
return {
|
|
164
|
+
content,
|
|
165
|
+
errors: critters.errors.length ? critters.errors : undefined,
|
|
166
|
+
warnings: critters.warnings.length ? critters.warnings : undefined,
|
|
167
|
+
};
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5saW5lLWNzcy1wcm9jZXNzb3IuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi8uLi9wYWNrYWdlcy9hbmd1bGFyL3Nzci9zcmMvaW5saW5lLWNzcy1wcm9jZXNzb3IudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7Ozs7OztHQU1HO0FBRUgsT0FBTyxRQUFRLE1BQU0sVUFBVSxDQUFDO0FBQ2hDLE9BQU8sRUFBRSxRQUFRLEVBQUUsTUFBTSxrQkFBa0IsQ0FBQztBQUU1Qzs7R0FFRztBQUNILE1BQU0seUJBQXlCLEdBQUcsOEJBQThCLENBQUM7QUFFakU7O0dBRUc7QUFDSCxNQUFNLGNBQWMsR0FBRyxZQUFZLENBQUM7QUFFcEM7O0dBRUc7QUFDSCxNQUFNLHdCQUF3QixHQUFHO0lBQy9CLFVBQVU7SUFDViw4RUFBOEU7SUFDOUUseUZBQXlGO0lBQ3pGLG9FQUFvRTtJQUNwRSw0Q0FBNEM7SUFDNUMsNkRBQTZEO0lBQzdELCtFQUErRTtJQUMvRSx3REFBd0QsY0FBYyxNQUFNO0lBQzVFLG1FQUFtRTtJQUNuRSx1REFBdUQ7SUFDdkQsK0NBQStDO0lBQy9DLGdDQUFnQztJQUNoQywyQkFBMkIsY0FBYywrQ0FBK0M7SUFDeEYsS0FBSztJQUNMLE9BQU87Q0FDUixDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQztBQThDYixNQUFNLGdCQUFpQixTQUFRLFFBQVE7SUFVckMsWUFDVyxlQUFvRixFQUM1RSxhQUFrQztRQUVuRCxLQUFLLENBQUM7WUFDSixNQUFNLEVBQUU7Z0JBQ04sSUFBSSxFQUFFLENBQUMsQ0FBUyxFQUFFLEVBQUUsQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUM7Z0JBQzFDLEtBQUssRUFBRSxDQUFDLENBQVMsRUFBRSxFQUFFLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDO2dCQUN6QyxJQUFJLEVBQUUsR0FBRyxFQUFF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TSxDQUFDLENBQUMsQ0FBQyxTQUFTO1lBQzVELFFBQVEsRUFBRSxRQUFRLENBQUMsUUFBUSxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsUUFBUSxDQUFDLFFBQVEsQ0FBQyxDQUFDLENBQUMsU0FBUztTQUNuRSxDQUFDO0lBQ0osQ0FBQztDQUNGIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBAbGljZW5zZVxuICogQ29weXJpZ2h0IEdvb2dsZSBMTEMgQWxsIFJpZ2h0cyBSZXNlcnZlZC5cbiAqXG4gKiBVc2Ugb2YgdGhpcyBzb3VyY2UgY29kZSBpcyBnb3Zlcm5lZCBieSBhbiBNSVQtc3R5bGUgbGljZW5zZSB0aGF0IGNhbiBiZVxuICogZm91bmQgaW4gdGhlIExJQ0VOU0UgZmlsZSBhdCBodHRwczovL2FuZ3VsYXIuaW8vbGljZW5zZVxuICovXG5cbmltcG9ydCBDcml0dGVycyBmcm9tICdjcml0dGVycyc7XG5pbXBvcnQgeyByZWFkRmlsZSB9IGZyb20gJ25vZGU6ZnMvcHJvbWlzZXMnO1xuXG4vKipcbiAqIFBhdHRlcm4gdXNlZCB0byBleHRyYWN0IHRoZSBtZWRpYSBxdWVyeSBzZXQgYnkgQ3JpdHRlcnMgaW4gYW4gYG9ubG9hZGAgaGFuZGxlci5cbiAqL1xuY29uc3QgTUVESUFfU0VUX0hBTkRMRVJfUEFUVEVSTiA9IC9edGhpc1xcLm1lZGlhPVtcIiddKC4qKVtcIiddOz8kLztcblxuLyoqXG4gKiBOYW1lIG9mIHRoZSBhdHRyaWJ1dGUgdXNlZCB0byBzYXZlIHRoZSBDcml0dGVycyBtZWRpYSBxdWVyeSBzbyBpdCBjYW4gYmUgcmUtYXNzaWduZWQgb24gbG9hZC5cbiAqL1xuY29uc3QgQ1NQX01FRElBX0FUVFIgPSAnbmdDc3BNZWRpYSc7XG5cbi8qKlxuICogU2NyaXB0IHRleHQgdXNlZCB0byBjaGFuZ2UgdGhlIG1lZGlhIHZhbHVlIG9mIHRoZSBsaW5rIHRhZ3MuXG4gKi9cbmNvbnN0IExJTktfTE9BRF9TQ1JJUFRfQ09OVEVOVCA9IFtcbiAgYCgoKSA9PiB7YCxcbiAgLy8gU2F2ZSB0aGUgYGNoaWxkcmVuYCBpbiBhIHZhcmlhYmxlIHNpbmNlIHRoZXkncmUgYSBsaXZlIERPTSBub2RlIGNvbGxlY3Rpb24uXG4gIC8vIFdlIGl0ZXJhdGUgb3ZlciB0aGUgZGlyZWN0IGRlc2NlbmRhbnRzLCBpbnN0ZWFkIG9mIGdvaW5nIHRocm91Z2ggYSBgcXVlcnlTZWxlY3RvckFsbGAsXG4gIC8vIGJlY2F1c2Ugd2Uga25vdyB0aGF0IHRoZSB0YWdzIHdpbGwgYmUgZGlyZWN0bHkgaW5zaWRlIHRoZSBgaGVhZGAuXG4gIGAgIGNvbnN0IGNoaWxkcmVuID0gZG9jdW1lbnQuaGVhZC5jaGlsZHJlbjtgLFxuICAvLyBEZWNsYXJlIGBvbkxvYWRgIG91dHNpZGUgdGhlIGxvb3AgdG8gYXZvaWQgbGVha2luZyBtZW1vcnkuXG4gIC8vIENhbid0IGJlIGFuIGFycm93IGZ1bmN0aW9uLCBiZWNhdXNlIHdlIG5lZWQgYHRoaXNgIHRvIHJlZmVyIHRvIHRoZSBET00gbm9kZS5cbiAgYCAgZnVuY3Rpb24gb25Mb2FkKCkge3RoaXMubWVkaWEgPSB0aGlzLmdldEF0dHJpYnV0ZSgnJHtDU1BfTUVESUFfQVRUUn0nKTt9YCxcbiAgLy8gSGFzIHRvIHVzZSBhIHBsYWluIGZvciBsb29wLCBiZWNhdXNlIHNvbWUgYnJvd3NlcnMgZG9uJ3Qgc3VwcG9ydFxuICAvLyBgZm9yRWFjaGAgb24gYGNoaWxkcmVuYCB3aGljaCBpcyBhIGBIVE1MQ29sbGVjdGlvbmAuXG4gIGAgIGZvciAobGV0IGkgPSAwOyBpIDwgY2hpbGRyZW4ubGVuZ3RoOyBpKyspIHtgLFxuICBgICAgIGNvbnN0IGNoaWxkID0gY2hpbGRyZW5baV07YCxcbiAgYCAgICBjaGlsZC5oYXNBdHRyaWJ1dGUoJyR7Q1NQX01FRElBX0FUVFJ9JykgJiYgY2hpbGQuYWRkRXZlbnRMaXN0ZW5lcignbG9hZCcsIG9uTG9hZCk7YCxcbiAgYCAgfWAsXG4gIGB9KSgpO2AsXG5dLmpvaW4oJ1xcbicpO1xuXG5leHBvcnQgaW50ZXJmYWNlIElubGluZUNyaXRpY2FsQ3NzUHJvY2Vzc09wdGlvbnMge1xuICBvdXRwdXRQYXRoPzogc3RyaW5nO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIElubGluZUNyaXRpY2FsQ3NzUHJvY2Vzc29yT3B0aW9ucyB7XG4gIG1pbmlmeT86IGJvb2xlYW47XG4gIGRlcGxveVVybD86IHN0cmluZztcbn1cblxuZXhwb3J0IGludGVyZmFjZSBJbmxpbmVDcml0aWNhbENzc1Jlc3VsdCB7XG4gIGNvbnRlbnQ6IHN0cmluZztcbiAgd2FybmluZ3M/OiBzdHJpbmdbXTtcbiAgZXJyb3JzPzogc3RyaW5nW107XG59XG5cbi8qKiBQYXJ0aWFsIHJlcHJlc2VudGF0aW9uIG9mIGFuIGBIVE1MRWxlbWVudGAuICovXG5pbnRlcmZhY2UgUGFydGlhbEhUTUxFbGVtZW50IHtcbiAgZ2V0QXR0cmlidXRlKG5hbWU6IHN0cmluZyk6IHN0cmluZyB8IG51bGw7XG4gIHNldEF0dHJpYnV0ZShuYW1lOiBzdHJpbmcsIHZhbHVlOiBzdHJpbmcpOiB2b2lkO1xuICBoYXNBdHRyaWJ1dGUobmFtZTogc3RyaW5nKTogYm9vbGVhbjtcbiAgcmVtb3ZlQXR0cmlidXRlKG5hbWU6IHN0cmluZyk6IHZvaWQ7XG4gIGFwcGVuZENoaWxkKGNoaWxkOiBQYXJ0aWFsSFRNTEVsZW1lbnQpOiB2b2lkO1xuICByZW1vdmUoKTogdm9pZDtcbiAgbmFtZTogc3RyaW5nO1xuICB0ZXh0Q29udGVudDogc3RyaW5nO1xuICB0YWdOYW1lOiBzdHJpbmcgfCBudWxsO1xuICBjaGlsZHJlbjogUGFydGlhbEhUTUxFbGVtZW50W107XG4gIG5leHQ6IFBhcnRpYWxIVE1MRWxlbWVudCB8IG51bGw7XG4gIHByZXY6IFBhcnRpYWxIVE1MRWxlbWVudCB8IG51bGw7XG59XG5cbi8qKiBQYXJ0aWFsIHJlcHJlc2VudGF0aW9uIG9mIGFuIEhUTUwgYERvY3VtZW50YC4gKi9cbmludGVyZmFjZSBQYXJ0aWFsRG9jdW1lbnQge1xuICBoZWFkOiBQYXJ0aWFsSFRNTEVsZW1lbnQ7XG4gIGNyZWF0ZUVsZW1lbnQodGFnTmFtZTogc3RyaW5nKTogUGFydGlhbEhUTUxFbGVtZW50O1xuICBxdWVyeVNlbGVjdG9yKHNlbGVjdG9yOiBzdHJpbmcpOiBQYXJ0aWFsSFRNTEVsZW1lbnQgfCBudWxsO1xufVxuXG4vKiogU2lnbmF0dXJlIG9mIHRoZSBgQ3JpdHRlcnMuZW1iZWRMaW5rZWRTdHlsZXNoZWV0YCBtZXRob2QuICovXG50eXBlIEVtYmVkTGlua2VkU3R5bGVzaGVldEZuID0gKFxuICBsaW5rOiBQYXJ0aWFsSFRNTEVsZW1lbnQsXG4gIGRvY3VtZW50OiBQYXJ0aWFsRG9jdW1lbnQsXG4pID0+IFByb21pc2U8dW5rbm93bj47XG5cbmNsYXNzIENyaXR0ZXJzRXh0ZW5kZWQgZXh0ZW5kcyBDcml0dGVycyB7XG4gIHJlYWRvbmx5IHdhcm5pbmdzOiBzdHJpbmdbXSA9IFtdO1xuICByZWFkb25seSBlcnJvcnM6IHN0cmluZ1tdID0gW107XG4gIHByaXZhdGUgaW5pdGlhbEVtYmVkTGlua2VkU3R5bGVzaGVldDogRW1iZWRMaW5rZWRTdHlsZXNoZWV0Rm47XG4gIHByaXZhdGUgYWRkZWRDc3BTY3JpcHRzRG9jdW1lbnRzID0gbmV3IFdlYWtTZXQ8UGFydGlhbERvY3VtZW50PigpO1xuICBwcml2YXRlIGRvY3VtZW50Tm9uY2VzID0gbmV3IFdlYWtNYXA8UGFydGlhbERvY3VtZW50LCBzdHJpbmcgfCBudWxsPigpO1xuXG4gIC8vIEluaGVyaXRlZCBmcm9tIGBDcml0dGVyc2AsIGJ1dCBub3QgZXhwb3NlZCBpbiB0aGUgdHlwaW5ncy5cbiAgcHJvdGVjdGVkIGVtYmVkTGlua2VkU3R5bGVzaGVldCE6IEVtYmVkTGlua2VkU3R5bGVzaGVldEZuO1xuXG4gIGNvbnN0cnVjdG9yKFxuICAgIHJlYWRvbmx5IG9wdGlvbnNFeHRlbmRlZDogSW5saW5lQ3JpdGljYWxDc3NQcm9jZXNzb3JPcHRpb25zICYgSW5saW5lQ3JpdGljYWxDc3NQcm9jZXNzT3B0aW9ucyxcbiAgICBwcml2YXRlIHJlYWRvbmx5IHJlc291cmNlQ2FjaGU6IE1hcDxzdHJpbmcsIHN0cmluZz4sXG4gICkge1xuICAgIHN1cGVyKHtcbiAgICAgIGxvZ2dlcjoge1xuICAgICAgICB3YXJuOiAoczogc3RyaW5nKSA9PiB0aGlzLndhcm5pbmdzLnB1c2gocyksXG4gICAgICAgIGVycm9yOiAoczogc3RyaW5nKSA9PiB0aGlzLmVycm9ycy5wdXNoKHMpLFxuICAgICAgICBpbmZvOiAoKSA9PiB7fSxcbiAgICAgIH0sXG4gICAgICBsb2dMZXZlbDogJ3dhcm4nLFxuICAgICAgcGF0aDogb3B0aW9uc0V4dGVuZGVkLm91dHB1dFBhdGgsXG4gICAgICBwdWJsaWNQYXRoOiBvcHRpb25zRXh0ZW5kZWQuZGVwbG95VXJsLFxuICAgICAgY29tcHJlc3M6ICEhb3B0aW9uc0V4dGVuZGVkLm1pbmlmeSxcbiAgICAgIHBydW5lU291cmNlOiBmYWxzZSxcbiAgICAgIHJlZHVjZUlubGluZVN0eWxlczogZmFsc2UsXG4gICAgICBtZXJnZVN0eWxlc2hlZXRzOiBmYWxzZSxcbiAgICAgIC8vIE5vdGU6IGlmIGBwcmVsb2FkYCBjaGFuZ2VzIHRvIGFueXRoaW5nIG90aGVyIHRoYW4gYG1lZGlhYCwgdGhlIGxvZ2ljIGluXG4gICAgICAvLyBgZW1iZWRMaW5rZWRTdHlsZXNoZWV0T3ZlcnJpZGVgIHdpbGwgaGF2ZSB0byBiZSB1cGRhdGVkLlxuICAgICAgcHJlbG9hZDogJ21lZGlhJyxcbiAgICAgIG5vc2NyaXB0RmFsbGJhY2s6IHRydWUsXG4gICAgICBpbmxpbmVGb250czogdHJ1ZSxcbiAgICB9KTtcblxuICAgIC8vIFdlIGNhbid0IHVzZSBpbmhlcml0YW5jZSB0byBvdmVycmlkZSBgZW1iZWRMaW5rZWRTdHlsZXNoZWV0YCwgYmVjYXVzZSBpdCdzIG5vdCBkZWNsYXJlZCBpblxuICAgIC8vIHRoZSBgQ3JpdHRlcnNgIC5kLnRzIHdoaWNoIG1lYW5zIHRoYXQgd2UgY2FuJ3QgY2FsbCB0aGUgYHN1cGVyYCBpbXBsZW1lbnRhdGlvbi4gVFMgZG9lc24ndFxuICAgIC8vIGFsbG93IGZvciBgc3VwZXJgIHRvIGJlIGNhc3QgdG8gYSBkaWZmZXJlbnQgdHlwZS5cbiAgICB0aGlzLmluaXRpYWxFbWJlZExpbmtlZFN0eWxlc2hlZXQgPSB0aGlzLmVtYmVkTGlua2VkU3R5bGVzaGVldDtcbiAgICB0aGlzLmVtYmVkTGlua2VkU3R5bGVzaGVldCA9IHRoaXMuZW1iZWRMaW5rZWRTdHlsZXNoZWV0T3ZlcnJpZGU7XG4gIH1cblxuICBwdWJsaWMgb3ZlcnJpZGUgYXN5bmMgcmVhZEZpbGUocGF0aDogc3RyaW5nKTogUHJvbWlzZTxzdHJpbmc+IHtcbiAgICBsZXQgcmVzb3VyY2VDb250ZW50ID0gdGhpcy5yZXNvdXJjZUNhY2hlLmdldChwYXRoKTtcbiAgICBpZiAocmVzb3VyY2VDb250ZW50ID09PSB1bmRlZmluZWQpIHtcbiAgICAgIHJlc291cmNlQ29udGVudCA9IGF3YWl0IHJlYWRGaWxlKHBhdGgsICd1dGYtOCcpO1xuICAgICAgdGhpcy5yZXNvdXJjZUNhY2hlLnNldChwYXRoLCByZXNvdXJjZUNvbnRlbnQpO1xuICAgIH1cblxuICAgIHJldHVybiByZXNvdXJjZUNvbnRlbnQ7XG4gIH1cblxuICAvKipcbiAgICogT3ZlcnJpZGUgb2YgdGhlIENyaXR0ZXJzIGBlbWJlZExpbmtlZFN0eWxlc2hlZXRgIG1ldGhvZFxuICAgKiB0aGF0IG1ha2VzIGl0IHdvcmsgd2l0aCBBbmd1bGFyJ3MgQ1NQIEFQSXMuXG4gICAqL1xuICBwcml2YXRlIGVtYmVkTGlua2VkU3R5bGVzaGVldE92ZXJyaWRlOiBFbWJlZExpbmtlZFN0eWxlc2hlZXRGbiA9IGFzeW5jIChsaW5rLCBkb2N1bWVudCkgPT4ge1xuICAgIGlmIChsaW5rLmdldEF0dHJpYnV0ZSgnbWVkaWEnKSA9PT0gJ3ByaW50JyAmJiBsaW5rLm5leHQ/Lm5hbWUgPT09ICdub3NjcmlwdCcpIHtcbiAgICAgIC8vIFdvcmthcm91bmQgZm9yIGh0dHBzOi8vZ2l0aHViLmNvbS9Hb29nbGVDaHJvbWVMYWJzL2NyaXR0ZXJzL2lzc3Vlcy82NFxuICAgICAgLy8gTkI6IHRoaXMgaXMgb25seSBuZWVkZWQgZm9yIHRoZSB3ZWJwYWNrIGJhc2VkIGJ1aWxkZXJzLlxuICAgICAgY29uc3QgbWVkaWEgPSBsaW5rLmdldEF0dHJpYnV0ZSgnb25sb2FkJyk/Lm1hdGNoKE1FRElBX1NFVF9IQU5ETEVSX1BBVFRFUk4pO1xuICAgICAgaWYgKG1lZGlhKSB7XG4gICAgICAgIGxpbmsucmVtb3ZlQXR0cmlidXRlKCdvbmxvYWQnKTtcbiAgICAgICAgbGluay5zZXRBdHRyaWJ1dGUoJ21lZGlhJywgbWVkaWFbMV0pO1xuICAgICAgICBsaW5rPy5uZXh0Py5yZW1vdmUoKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBjb25zdCByZXR1cm5WYWx1ZSA9IGF3YWl0IHRoaXMuaW5pdGlhbEVtYmVkTGlua2VkU3R5bGVzaGVldChsaW5rLCBkb2N1bWVudCk7XG4gICAgY29uc3QgY3NwTm9uY2UgPSB0aGlzLmZpbmRDc3BOb25jZShkb2N1bWVudCk7XG5cbiAgICBpZiAoY3NwTm9uY2UpIHtcbiAgICAgIGNvbnN0IGNyaXR0ZXJzTWVkaWEgPSBsaW5rLmdldEF0dHJpYnV0ZSgnb25sb2FkJyk/Lm1hdGNoKE1FRElBX1NFVF9IQU5ETEVSX1BBVFRFUk4pO1xuXG4gICAgICBpZiAoY3JpdHRlcnNNZWRpYSkge1xuICAgICAgICAvLyBJZiB0aGVyZSdzIGEgQ3JpdHRlcnMtZ2VuZXJhdGVkIGBvbmxvYWRgIGhhbmRsZXIgYW5kIHRoZSBmaWxlIGhhcyBhbiBBbmd1bGFyIENTUCBub25jZSxcbiAgICAgICAgLy8gd2UgaGF2ZSB0byByZW1vdmUgdGhlIGhhbmRsZXIsIGJlY2F1c2UgaXQncyBpbmNvbXBhdGlibGUgd2l0aCBDU1AuIFdlIHNhdmUgdGhlIHZhbHVlXG4gICAgICAgIC8vIGluIGEgZGlmZmVyZW50IGF0dHJpYnV0ZSBhbmQgd2UgZ2VuZXJhdGUgYSBzY3JpcHQgdGFnIHdpdGggdGhlIG5vbmNlIHRoYXQgdXNlc1xuICAgICAgICAvLyBgYWRkRXZlbnRMaXN0ZW5lcmAgdG8gYXBwbHkgdGhlIG1lZGlhIHF1ZXJ5IGluc3RlYWQuXG4gICAgICAgIGxpbmsucmVtb3ZlQXR0cmlidXRlKCdvbmxvYWQnKTtcbiAgICAgICAgbGluay5zZXRBdHRyaWJ1dGUoQ1NQX01FRElBX0FUVFIsIGNyaXR0ZXJzTWVkaWFbMV0pO1xuICAgICAgICB0aGlzLmNvbmRpdGlvbmFsbHlJbnNlcnRDc3BMb2FkaW5nU2NyaXB0KGRvY3VtZW50LCBjc3BOb25jZSk7XG4gICAgICB9XG5cbiAgICAgIC8vIElkZWFsbHkgd2Ugd291bGQgaG9vayBpbiBhdCB0aGUgdGltZSBDcml0dGVycyBpbnNlcnRzIHRoZSBgc3R5bGVgIHRhZ3MsIGJ1dCB0aGVyZSBpc24ndFxuICAgICAgLy8gYSB3YXkgb2YgZG9pbmcgdGhhdCBhdCB0aGUgbW9tZW50IHNvIHdlIGZhbGwgYmFjayB0byBkb2luZyBpdCBhbnkgdGltZSBhIGBsaW5rYCB0YWcgaXNcbiAgICAgIC8vIGluc2VydGVkLiBXZSBtaXRpZ2F0ZSBpdCBieSBvbmx5IGl0ZXJhdGluZyB0aGUgZGlyZWN0IGNoaWxkcmVuIG9mIHRoZSBgPGhlYWQ+YCB3aGljaFxuICAgICAgLy8gc2hvdWxkIGJlIHByZXR0eSBzaGFsbG93LlxuICAgICAgZG9jdW1lbnQuaGVhZC5jaGlsZHJlbi5mb3JFYWNoKChjaGlsZCkgPT4ge1xuICAgICAgICBpZiAoY2hpbGQudGFnTmFtZSA9PT0gJ3N0eWxlJyAmJiAhY2hpbGQuaGFzQXR0cmlidXRlKCdub25jZScpKSB7XG4gICAgICAgICAgY2hpbGQuc2V0QXR0cmlidXRlKCdub25jZScsIGNzcE5vbmNlKTtcbiAgICAgICAgfVxuICAgICAgfSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHJldHVyblZhbHVlO1xuICB9O1xuXG4gIC8qKlxuICAgKiBGaW5kcyB0aGUgQ1NQIG5vbmNlIGZvciBhIHNwZWNpZmljIGRvY3VtZW50LlxuICAgKi9cbiAgcHJpdmF0ZSBmaW5kQ3NwTm9uY2UoZG9jdW1lbnQ6IFBhcnRpYWxEb2N1bWVudCk6IHN0cmluZyB8IG51bGwge1xuICAgIGlmICh0aGlzLmRvY3VtZW50Tm9uY2VzLmhhcyhkb2N1bWVudCkpIHtcbiAgICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tbm9uLW51bGwtYXNzZXJ0aW9uXG4gICAgICByZXR1cm4gdGhpcy5kb2N1bWVudE5vbmNlcy5nZXQoZG9jdW1lbnQpITtcbiAgICB9XG5cbiAgICAvLyBIVE1MIGF0dHJpYnV0ZSBhcmUgY2FzZS1pbnNlbnNpdGl2ZSwgYnV0IHRoZSBwYXJzZXIgdXNlZCBieSBDcml0dGVycyBpcyBjYXNlLXNlbnNpdGl2ZS5cbiAgICBjb25zdCBub25jZUVsZW1lbnQgPSBkb2N1bWVudC5xdWVyeVNlbGVjdG9yKCdbbmdDc3BOb25jZV0sIFtuZ2NzcG5vbmNlXScpO1xuICAgIGNvbnN0IGNzcE5vbmNlID1cbiAgICAgIG5vbmNlRWxlbWVudD8uZ2V0QXR0cmlidXRlKCduZ0NzcE5vbmNlJykgfHwgbm9uY2VFbGVtZW50Py5nZXRBdHRyaWJ1dGUoJ25nY3Nwbm9uY2UnKSB8fCBudWxsO1xuXG4gICAgdGhpcy5kb2N1bWVudE5vbmNlcy5zZXQoZG9jdW1lbnQsIGNzcE5vbmNlKTtcblxuICAgIHJldHVybiBjc3BOb25jZTtcbiAgfVxuXG4gIC8qKlxuICAgKiBJbnNlcnRzIHRoZSBgc2NyaXB0YCB0YWcgdGhhdCBzd2FwcyB0aGUgY3JpdGljYWwgQ1NTIGF0IHJ1bnRpbWUsXG4gICAqIGlmIG9uZSBoYXNuJ3QgYmVlbiBpbnNlcnRlZCBpbnRvIHRoZSBkb2N1bWVudCBhbHJlYWR5LlxuICAgKi9cbiAgcHJpdmF0ZSBjb25kaXRpb25hbGx5SW5zZXJ0Q3NwTG9hZGluZ1NjcmlwdChkb2N1bWVudDogUGFydGlhbERvY3VtZW50LCBub25jZTogc3RyaW5nKTogdm9pZCB7XG4gICAgaWYgKHRoaXMuYWRkZWRDc3BTY3JpcHRzRG9jdW1lbnRzLmhhcyhkb2N1bWVudCkpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBpZiAoZG9jdW1lbnQuaGVhZC50ZXh0Q29udGVudC5pbmNsdWRlcyhMSU5LX0xPQURfU0NSSVBUX0NPTlRFTlQpKSB7XG4gICAgICAvLyBTY3JpcHQgd2FzIGFscmVhZHkgYWRkZWQgZHVyaW5nIHRoZSBidWlsZC5cbiAgICAgIHRoaXMuYWRkZWRDc3BTY3JpcHRzRG9jdW1lbnRzLmFkZChkb2N1bWVudCk7XG5cbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBjb25zdCBzY3JpcHQgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdzY3JpcHQnKTtcbiAgICBzY3JpcHQuc2V0QXR0cmlidXRlKCdub25jZScsIG5vbmNlKTtcbiAgICBzY3JpcHQudGV4dENvbnRlbnQgPSBMSU5LX0xPQURfU0NSSVBUX0NPTlRFTlQ7XG4gICAgLy8gQXBwZW5kIHRoZSBzY3JpcHQgdG8gdGhlIGhlYWQgc2luY2UgaXQgbmVlZHMgdG9cbiAgICAvLyBydW4gYXMgZWFybHkgYXMgcG9zc2libGUsIGFmdGVyIHRoZSBgbGlua2AgdGFncy5cbiAgICBkb2N1bWVudC5oZWFkLmFwcGVuZENoaWxkKHNjcmlwdCk7XG4gICAgdGhpcy5hZGRlZENzcFNjcmlwdHNEb2N1bWVudHMuYWRkKGRvY3VtZW50KTtcbiAgfVxufVxuXG5leHBvcnQgY2xhc3MgSW5saW5lQ3JpdGljYWxDc3NQcm9jZXNzb3Ige1xuICBwcml2YXRlIHJlYWRvbmx5IHJlc291cmNlQ2FjaGUgPSBuZXcgTWFwPHN0cmluZywgc3RyaW5nPigpO1xuXG4gIGNvbnN0cnVjdG9yKHByb3RlY3RlZCByZWFkb25seSBvcHRpb25zOiBJbmxpbmVDcml0aWNhbENzc1Byb2Nlc3Nvck9wdGlvbnMpIHt9XG5cbiAgYXN5bmMgcHJvY2VzcyhcbiAgICBodG1sOiBzdHJpbmcsXG4gICAgb3B0aW9uczogSW5saW5lQ3JpdGljYWxDc3NQcm9jZXNzT3B0aW9ucyxcbiAgKTogUHJvbWlzZTxJbmxpbmVDcml0aWNhbENzc1Jlc3VsdD4ge1xuICAgIGNvbnN0IGNyaXR0ZXJzID0gbmV3IENyaXR0ZXJzRXh0ZW5kZWQoeyAuLi50aGlzLm9wdGlvbnMsIC4uLm9wdGlvbnMgfSwgdGhpcy5yZXNvdXJjZUNhY2hlKTtcbiAgICBjb25zdCBjb250ZW50ID0gYXdhaXQgY3JpdHRlcnMucHJvY2VzcyhodG1sKTtcblxuICAgIHJldHVybiB7XG4gICAgICBjb250ZW50LFxuICAgICAgZXJyb3JzOiBjcml0dGVycy5lcnJvcnMubGVuZ3RoID8gY3JpdHRlcnMuZXJyb3JzIDogdW5kZWZpbmVkLFxuICAgICAgd2FybmluZ3M6IGNyaXR0ZXJzLndhcm5pbmdzLmxlbmd0aCA/IGNyaXR0ZXJzLndhcm5pbmdzIDogdW5kZWZpbmVkLFxuICAgIH07XG4gIH1cbn1cbiJdfQ==
|