UNPKG

17.7 kBJavaScriptView Raw
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 */
8import { DOCUMENT } from '@angular/common';
9import { BEFORE_APP_SERIALIZED } from '@angular/platform-server';
10import { BREAKPOINTS, CLASS_NAME, SERVER_TOKEN, ɵMatchMedia as MatchMedia, StylesheetMap, sortAscendingPriority, MediaMarshaller, } from '@angular/flex-layout/core';
11import { ServerMatchMedia } from './server-match-media';
12/**
13 * Activate all the registered breakpoints in sequence, and then
14 * retrieve the associated stylings from the virtual stylesheet
15 * @param serverSheet the virtual stylesheet that stores styles for each
16 * element
17 * @param mediaController the MatchMedia service to activate/deactivate breakpoints
18 * @param breakpoints the registered breakpoints to activate/deactivate
19 * @param mediaMarshaller the MediaMarshaller service to disable fallback styles dynamically
20 */
21export function generateStaticFlexLayoutStyles(serverSheet, mediaController, breakpoints, mediaMarshaller) {
22 // Store the custom classes in the following map, that way only
23 // one class gets allocated per HTMLElement, and each class can
24 // be referenced in the static media queries
25 const classMap = new Map();
26 // Get the initial stylings for all the directives,
27 // and initialize the fallback block of stylings.
28 const defaultStyles = new Map(serverSheet.stylesheet);
29 // Reset the class counter, otherwise class numbers will
30 // increase with each server render.
31 nextId = 0;
32 let styleText = generateCss(defaultStyles, 'all', classMap);
33 mediaMarshaller.useFallbacks = false;
34 [...breakpoints].sort(sortAscendingPriority).forEach((bp) => {
35 serverSheet.clearStyles();
36 mediaController.activateBreakpoint(bp);
37 const stylesheet = new Map(serverSheet.stylesheet);
38 if (stylesheet.size > 0) {
39 styleText += generateCss(stylesheet, bp.mediaQuery, classMap);
40 }
41 mediaController.deactivateBreakpoint(bp);
42 });
43 return styleText;
44}
45/**
46 * Create a style tag populated with the dynamic stylings from Flex
47 * components and attach it to the head of the DOM
48 */
49export function FLEX_SSR_SERIALIZER_FACTORY(serverSheet, mediaController, _document, breakpoints, mediaMarshaller) {
50 return () => {
51 // This is the style tag that gets inserted into the head of the DOM,
52 // populated with the manual media queries
53 const styleTag = _document.createElement('style');
54 const styleText = generateStaticFlexLayoutStyles(serverSheet, mediaController, breakpoints, mediaMarshaller);
55 styleTag.classList.add(`${CLASS_NAME}ssr`);
56 styleTag.textContent = styleText;
57 _document.head.appendChild(styleTag);
58 };
59}
60/**
61 * Provider to set static styles on the server
62 */
63export const SERVER_PROVIDERS = [
64 {
65 provide: BEFORE_APP_SERIALIZED,
66 useFactory: FLEX_SSR_SERIALIZER_FACTORY,
67 deps: [
68 StylesheetMap,
69 MatchMedia,
70 DOCUMENT,
71 BREAKPOINTS,
72 MediaMarshaller,
73 ],
74 multi: true,
75 },
76 {
77 provide: SERVER_TOKEN,
78 useValue: true
79 },
80 {
81 provide: MatchMedia,
82 useClass: ServerMatchMedia
83 }
84];
85let nextId = 0;
86const IS_DEBUG_MODE = false;
87/**
88 * create @media queries based on a virtual stylesheet
89 * * Adds a unique class to each element and stores it
90 * in a shared classMap for later reuse
91 * @param stylesheet the virtual stylesheet that stores styles for each
92 * element
93 * @param mediaQuery the given @media CSS selector for the current breakpoint
94 * @param classMap the map of HTML elements to class names to avoid duplications
95 */
96function generateCss(stylesheet, mediaQuery, classMap) {
97 let css = '';
98 stylesheet.forEach((styles, el) => {
99 let keyVals = '';
100 let className = getClassName(el, classMap);
101 styles.forEach((v, k) => {
102 keyVals += v ? format(`${k}:${v};`) : '';
103 });
104 if (keyVals) {
105 // Build list of CSS styles; each with a className
106 css += format(`.${className} {`, keyVals, '}');
107 }
108 });
109 // Group 1 or more styles (each with className) in a specific mediaQuery
110 return format(`@media ${mediaQuery} {`, css, '}');
111}
112/**
113 * For debugging purposes, prefix css segment with linefeed(s) for easy
114 * debugging purposes.
115 */
116function format(...list) {
117 let result = '';
118 list.forEach((css, i) => {
119 result += IS_DEBUG_MODE ? formatSegment(css, i !== 0) : css;
120 });
121 return result;
122}
123function formatSegment(css, asPrefix = true) {
124 return asPrefix ? `\n${css}` : `${css}\n`;
125}
126/**
127 * Get className associated with CSS styling
128 * If not found, generate global className and set
129 * association.
130 */
131function getClassName(element, classMap) {
132 let className = classMap.get(element);
133 if (!className) {
134 className = `${CLASS_NAME}${nextId++}`;
135 classMap.set(element, className);
136 }
137 element.classList.add(className);
138 return className;
139}
140//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2VydmVyLXByb3ZpZGVyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vcHJvamVjdHMvbGlicy9mbGV4LWxheW91dC9zZXJ2ZXIvc2VydmVyLXByb3ZpZGVyLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOzs7Ozs7R0FNRztBQUNILE9BQU8sRUFBQyxRQUFRLEVBQUMsTUFBTSxpQkFBaUIsQ0FBQztBQUN6QyxPQUFPLEVBQUMscUJBQXFCLEVBQUMsTUFBTSwwQkFBMEIsQ0FBQztBQUMvRCxPQUFPLEVBQ0wsV0FBVyxFQUNYLFVBQVUsRUFDVixZQUFZLEVBRVosV0FBVyxJQUFJLFVBQVUsRUFDekIsYUFBYSxFQUNiLHFCQUFxQixFQUNyQixlQUFlLEdBQ2hCLE1BQU0sMkJBQTJCLENBQUM7QUFFbkMsT0FBTyxFQUFDLGdCQUFnQixFQUFDLE1BQU0sc0JBQXNCLENBQUM7QUFFdEQ7Ozs7Ozs7O0dBUUc7QUFDSCxNQUFNLFVBQVUsOEJBQThCLENBQUMsV0FBMEIsRUFDMUIsZUFBaUMsRUFDakMsV0FBeUIsRUFDekIsZUFBZ0M7SUFDN0UsK0RBQStEO0lBQy9ELCtEQUErRDtJQUMvRCw0Q0FBNEM7SUFDNUMsTUFBTSxRQUFRLEdBQUcsSUFBSSxHQUFHLEVBQXVCLENBQUM7SUFFaEQsbURBQW1EO0lBQ25ELGlEQUFpRDtJQUNqRCxNQUFNLGFBQWEsR0FBRyxJQUFJLEdBQUcsQ0FBQyxXQUFXLENBQUMsVUFBVSxDQUFDLENBQUM7SUFDdEQsd0RBQXdEO0lBQ3hELG9DQUFvQztJQUNwQyxNQUFNLEdBQUcsQ0FBQyxDQUFDO0lBQ1gsSUFBSSxTQUFTLEdBQUcsV0FBVyxDQUFDLGFBQWEsRUFBRSxLQUFLLEVBQUUsUUFBUSxDQUFDLENBQUM7SUFDNUQsZUFBZSxDQUFDLFlBQVksR0FBRyxLQUFLLENBQUM7SUFFckMsQ0FBQyxHQUFHLFdBQVcsQ0FBQyxDQUFDLElBQUksQ0FBQyxxQkFBcUIsQ0FBQyxDQUFDLE9BQU8sQ0FB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QyxDQUFDO0FBQ3BELENBQUM7QUFFRDs7O0dBR0c7QUFDSCxTQUFTLE1BQU0sQ0FBQyxHQUFHLElBQWM7SUFDL0IsSUFBSSxNQUFNLEdBQUcsRUFBRSxDQUFDO0lBQ2hCLElBQUksQ0FBQyxPQUFPLENBQUMsQ0FBQyxHQUFHLEVBQUUsQ0FBQyxFQUFFLEVBQUU7UUFDdEIsTUFBTSxJQUFJLGFBQWEsQ0FBQyxDQUFDLENBQUMsYUFBYSxDQUFDLEdBQUcsRUFBRSxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLEdBQUcsQ0FBQztJQUM5RCxDQUFDLENBQUMsQ0FBQztJQUNILE9BQU8sTUFBTSxDQUFDO0FBQ2hCLENBQUM7QUFFRCxTQUFTLGFBQWEsQ0FBQyxHQUFXLEVBQUUsV0FBb0IsSUFBSTtJQUMxRCxPQUFPLFFBQVEsQ0FBQyxDQUFDLENBQUMsS0FBSyxHQUFHLEVBQUUsQ0FBQyxDQUFDLENBQUMsR0FBRyxHQUFHLElBQUksQ0FBQztBQUM1QyxDQUFDO0FBRUQ7Ozs7R0FJRztBQUNILFNBQVMsWUFBWSxDQUFDLE9BQW9CLEVBQUUsUUFBa0M7SUFDNUUsSUFBSSxTQUFTLEdBQUcsUUFBUSxDQUFDLEdBQUcsQ0FBQyxPQUFPLENBQUMsQ0FBQztJQUN0QyxJQUFJLENBQUMsU0FBUyxFQUFFO1FBQ2QsU0FBUyxHQUFHLEdBQUcsVUFBVSxHQUFHLE1BQU0sRUFBRSxFQUFFLENBQUM7UUFDdkMsUUFBUSxDQUFDLEdBQUcsQ0FBQyxPQUFPLEVBQUUsU0FBUyxDQUFDLENBQUM7S0FDbEM7SUFDRCxPQUFPLENBQUMsU0FBUyxDQUFDLEdBQUcsQ0FBQyxTQUFTLENBQUMsQ0FBQztJQUVqQyxPQUFPLFNBQVMsQ0FBQztBQUNuQixDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBAbGljZW5zZVxuICogQ29weXJpZ2h0IEdvb2dsZSBMTEMgQWxsIFJpZ2h0cyBSZXNlcnZlZC5cbiAqXG4gKiBVc2Ugb2YgdGhpcyBzb3VyY2UgY29kZSBpcyBnb3Zlcm5lZCBieSBhbiBNSVQtc3R5bGUgbGljZW5zZSB0aGF0IGNhbiBiZVxuICogZm91bmQgaW4gdGhlIExJQ0VOU0UgZmlsZSBhdCBodHRwczovL2FuZ3VsYXIuaW8vbGljZW5zZVxuICovXG5pbXBvcnQge0RPQ1VNRU5UfSBmcm9tICdAYW5ndWxhci9jb21tb24nO1xuaW1wb3J0IHtCRUZPUkVfQVBQX1NFUklBTElaRUR9IGZyb20gJ0Bhbmd1bGFyL3BsYXRmb3JtLXNlcnZlcic7XG5pbXBvcnQge1xuICBCUkVBS1BPSU5UUyxcbiAgQ0xBU1NfTkFNRSxcbiAgU0VSVkVSX1RPS0VOLFxuICBCcmVha1BvaW50LFxuICDJtU1hdGNoTWVkaWEgYXMgTWF0Y2hNZWRpYSxcbiAgU3R5bGVzaGVldE1hcCxcbiAgc29ydEFzY2VuZGluZ1ByaW9yaXR5LFxuICBNZWRpYU1hcnNoYWxsZXIsXG59IGZyb20gJ0Bhbmd1bGFyL2ZsZXgtbGF5b3V0L2NvcmUnO1xuXG5pbXBvcnQge1NlcnZlck1hdGNoTWVkaWF9IGZyb20gJy4vc2VydmVyLW1hdGNoLW1lZGlhJztcblxuLyoqXG4gKiBBY3RpdmF0ZSBhbGwgdGhlIHJlZ2lzdGVyZWQgYnJlYWtwb2ludHMgaW4gc2VxdWVuY2UsIGFuZCB0aGVuXG4gKiByZXRyaWV2ZSB0aGUgYXNzb2NpYXRlZCBzdHlsaW5ncyBmcm9tIHRoZSB2aXJ0dWFsIHN0eWxlc2hlZXRcbiAqIEBwYXJhbSBzZXJ2ZXJTaGVldCB0aGUgdmlydHVhbCBzdHlsZXNoZWV0IHRoYXQgc3RvcmVzIHN0eWxlcyBmb3IgZWFjaFxuICogICAgICAgIGVsZW1lbnRcbiAqIEBwYXJhbSBtZWRpYUNvbnRyb2xsZXIgdGhlIE1hdGNoTWVkaWEgc2VydmljZSB0byBhY3RpdmF0ZS9kZWFjdGl2YXRlIGJyZWFrcG9pbnRzXG4gKiBAcGFyYW0gYnJlYWtwb2ludHMgdGhlIHJlZ2lzdGVyZWQgYnJlYWtwb2ludHMgdG8gYWN0aXZhdGUvZGVhY3RpdmF0ZVxuICogQHBhcmFtIG1lZGlhTWFyc2hhbGxlciB0aGUgTWVkaWFNYXJzaGFsbGVyIHNlcnZpY2UgdG8gZGlzYWJsZSBmYWxsYmFjayBzdHlsZXMgZHluYW1pY2FsbHlcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGdlbmVyYXRlU3RhdGljRmxleExheW91dFN0eWxlcyhzZXJ2ZXJTaGVldDogU3R5bGVzaGVldE1hcCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWVkaWFDb250cm9sbGVyOiBTZXJ2ZXJNYXRjaE1lZGlhLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVha3BvaW50czogQnJlYWtQb2ludFtdLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtZWRpYU1hcnNoYWxsZXI6IE1lZGlhTWFyc2hhbGxlcikge1xuICAvLyBTdG9yZSB0aGUgY3VzdG9tIGNsYXNzZXMgaW4gdGhlIGZvbGxvd2luZyBtYXAsIHRoYXQgd2F5IG9ubHlcbiAgLy8gb25lIGNsYXNzIGdldHMgYWxsb2NhdGVkIHBlciBIVE1MRWxlbWVudCwgYW5kIGVhY2ggY2xhc3MgY2FuXG4gIC8vIGJlIHJlZmVyZW5jZWQgaW4gdGhlIHN0YXRpYyBtZWRpYSBxdWVyaWVzXG4gIGNvbnN0IGNsYXNzTWFwID0gbmV3IE1hcDxIVE1MRWxlbWVudCwgc3RyaW5nPigpO1xuXG4gIC8vIEdldCB0aGUgaW5pdGlhbCBzdHlsaW5ncyBmb3IgYWxsIHRoZSBkaXJlY3RpdmVzLFxuICAvLyBhbmQgaW5pdGlhbGl6ZSB0aGUgZmFsbGJhY2sgYmxvY2sgb2Ygc3R5bGluZ3MuXG4gIGNvbnN0IGRlZmF1bHRTdHlsZXMgPSBuZXcgTWFwKHNlcnZlclNoZWV0LnN0eWxlc2hlZXQpO1xuICAvLyBSZXNldCB0aGUgY2xhc3MgY291bnRlciwgb3RoZXJ3aXNlIGNsYXNzIG51bWJlcnMgd2lsbFxuICAvLyBpbmNyZWFzZSB3aXRoIGVhY2ggc2VydmVyIHJlbmRlci5cbiAgbmV4dElkID0gMDtcbiAgbGV0IHN0eWxlVGV4dCA9IGdlbmVyYXRlQ3NzKGRlZmF1bHRTdHlsZXMsICdhbGwnLCBjbGFzc01hcCk7XG4gIG1lZGlhTWFyc2hhbGxlci51c2VGYWxsYmFja3MgPSBmYWxzZTtcblxuICBbLi4uYnJlYWtwb2ludHNdLnNvcnQoc29ydEFzY2VuZGluZ1ByaW9yaXR5KS5mb3JFYWNoKChicCkgPT4ge1xuICAgIHNlcnZlclNoZWV0LmNsZWFyU3R5bGVzKCk7XG4gICAgbWVkaWFDb250cm9sbGVyLmFjdGl2YXRlQnJlYWtwb2ludChicCk7XG4gICAgY29uc3Qgc3R5bGVzaGVldCA9IG5ldyBNYXAoc2VydmVyU2hlZXQuc3R5bGVzaGVldCk7XG4gICAgaWYgKHN0eWxlc2hlZXQuc2l6ZSA+IDApIHtcbiAgICAgIHN0eWxlVGV4dCArPSBnZW5lcmF0ZUNzcyhzdHlsZXNoZWV0LCBicC5tZWRpYVF1ZXJ5LCBjbGFzc01hcCk7XG4gICAgfVxuICAgIG1lZGlhQ29udHJvbGxlci5kZWFjdGl2YXRlQnJlYWtwb2ludChicCk7XG4gIH0pO1xuXG4gIHJldHVybiBzdHlsZVRleHQ7XG59XG5cbi8qKlxuICogQ3JlYXRlIGEgc3R5bGUgdGFnIHBvcHVsYXRlZCB3aXRoIHRoZSBkeW5hbWljIHN0eWxpbmdzIGZyb20gRmxleFxuICogY29tcG9uZW50cyBhbmQgYXR0YWNoIGl0IHRvIHRoZSBoZWFkIG9mIHRoZSBET01cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIEZMRVhfU1NSX1NFUklBTElaRVJfRkFDVE9SWShzZXJ2ZXJTaGVldDogU3R5bGVzaGVldE1hcCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWVkaWFDb250cm9sbGVyOiBTZXJ2ZXJNYXRjaE1lZGlhLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBfZG9jdW1lbnQ6IERvY3VtZW50LFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVha3BvaW50czogQnJlYWtQb2ludFtdLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtZWRpYU1hcnNoYWxsZXI6IE1lZGlhTWFyc2hhbGxlcikge1xuICByZXR1cm4gKCkgPT4ge1xuICAgIC8vIFRoaXMgaXMgdGhlIHN0eWxlIHRhZyB0aGF0IGdldHMgaW5zZXJ0ZWQgaW50byB0aGUgaGVhZCBvZiB0aGUgRE9NLFxuICAgIC8vIHBvcHVsYXRlZCB3aXRoIHRoZSBtYW51YWwgbWVkaWEgcXVlcmllc1xuICAgIGNvbnN0IHN0eWxlVGFnID0gX2RvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ3N0eWxlJyk7XG4gICAgY29uc3Qgc3R5bGVUZXh0ID0gZ2VuZXJhdGVTdGF0aWNGbGV4TGF5b3V0U3R5bGVzKFxuICAgICAgc2VydmVyU2hlZXQsIG1lZGlhQ29udHJvbGxlciwgYnJlYWtwb2ludHMsIG1lZGlhTWFyc2hhbGxlcik7XG4gICAgc3R5bGVUYWcuY2xhc3NMaXN0LmFkZChgJHtDTEFTU19OQU1FfXNzcmApO1xuICAgIHN0eWxlVGFnLnRleHRDb250ZW50ID0gc3R5bGVUZXh0O1xuICAgIF9kb2N1bWVudC5oZWFkIS5hcHBlbmRDaGlsZChzdHlsZVRhZyk7XG4gIH07XG59XG5cbi8qKlxuICogIFByb3ZpZGVyIHRvIHNldCBzdGF0aWMgc3R5bGVzIG9uIHRoZSBzZXJ2ZXJcbiAqL1xuZXhwb3J0IGNvbnN0IFNFUlZFUl9QUk9WSURFUlMgPSBbXG4gIHtcbiAgICBwcm92aWRlOiBCRUZPUkVfQVBQX1NFUklBTElaRUQsXG4gICAgdXNlRmFjdG9yeTogRkxFWF9TU1JfU0VSSUFMSVpFUl9GQUNUT1JZLFxuICAgIGRlcHM6IFtcbiAgICAgIFN0eWxlc2hlZXRNYXAsXG4gICAgICBNYXRjaE1lZGlhLFxuICAgICAgRE9DVU1FTlQsXG4gICAgICBCUkVBS1BPSU5UUyxcbiAgICAgIE1lZGlhTWFyc2hhbGxlcixcbiAgICBdLFxuICAgIG11bHRpOiB0cnVlLFxuICB9LFxuICB7XG4gICAgcHJvdmlkZTogU0VSVkVSX1RPS0VOLFxuICAgIHVzZVZhbHVlOiB0cnVlXG4gIH0sXG4gIHtcbiAgICBwcm92aWRlOiBNYXRjaE1lZGlhLFxuICAgIHVzZUNsYXNzOiBTZXJ2ZXJNYXRjaE1lZGlhXG4gIH1cbl07XG5cblxubGV0IG5leHRJZCA9IDA7XG5jb25zdCBJU19ERUJVR19NT0RFID0gZmFsc2U7XG5cbmV4cG9ydCB0eXBlIFN0eWxlU2hlZXQgPSBNYXA8SFRNTEVsZW1lbnQsIE1hcDxzdHJpbmcsIHN0cmluZ3xudW1iZXI+PjtcbmV4cG9ydCB0eXBlIENsYXNzTWFwID0gTWFwPEhUTUxFbGVtZW50LCBzdHJpbmc+O1xuXG4vKipcbiAqIGNyZWF0ZSBAbWVkaWEgcXVlcmllcyBiYXNlZCBvbiBhIHZpcnR1YWwgc3R5bGVzaGVldFxuICogKiBBZGRzIGEgdW5pcXVlIGNsYXNzIHRvIGVhY2ggZWxlbWVudCBhbmQgc3RvcmVzIGl0XG4gKiAgIGluIGEgc2hhcmVkIGNsYXNzTWFwIGZvciBsYXRlciByZXVzZVxuICogQHBhcmFtIHN0eWxlc2hlZXQgdGhlIHZpcnR1YWwgc3R5bGVzaGVldCB0aGF0IHN0b3JlcyBzdHlsZXMgZm9yIGVhY2hcbiAqICAgICAgICBlbGVtZW50XG4gKiBAcGFyYW0gbWVkaWFRdWVyeSB0aGUgZ2l2ZW4gQG1lZGlhIENTUyBzZWxlY3RvciBmb3IgdGhlIGN1cnJlbnQgYnJlYWtwb2ludFxuICogQHBhcmFtIGNsYXNzTWFwIHRoZSBtYXAgb2YgSFRNTCBlbGVtZW50cyB0byBjbGFzcyBuYW1lcyB0byBhdm9pZCBkdXBsaWNhdGlvbnNcbiAqL1xuZnVuY3Rpb24gZ2VuZXJhdGVDc3Moc3R5bGVzaGVldDogU3R5bGVTaGVldCwgbWVkaWFRdWVyeTogc3RyaW5nLCBjbGFzc01hcDogQ2xhc3NNYXApIHtcbiAgbGV0IGNzcyA9ICcnO1xuICBzdHlsZXNoZWV0LmZvckVhY2goKHN0eWxlcywgZWwpID0+IHtcbiAgICBsZXQga2V5VmFscyA9ICcnO1xuICAgIGxldCBjbGFzc05hbWUgPSBnZXRDbGFzc05hbWUoZWwsIGNsYXNzTWFwKTtcblxuICAgIHN0eWxlcy5mb3JFYWNoKCh2LCBrKSA9PiB7XG4gICAgICBrZXlWYWxzICs9IHYgPyBmb3JtYXQoYCR7a306JHt2fTtgKSA6ICcnO1xuICAgIH0pO1xuXG4gICAgaWYgKGtleVZhbHMpIHtcbiAgICAgIC8vIEJ1aWxkIGxpc3Qgb2YgQ1NTIHN0eWxlczsgZWFjaCB3aXRoIGEgY2xhc3NOYW1lXG4gICAgICBjc3MgKz0gZm9ybWF0KGAuJHtjbGFzc05hbWV9IHtgLCBrZXlWYWxzLCAnfScpO1xuICAgIH1cbiAgfSk7XG5cbiAgLy8gR3JvdXAgMSBvciBtb3JlIHN0eWxlcyAoZWFjaCB3aXRoIGNsYXNzTmFtZSkgaW4gYSBzcGVjaWZpYyBtZWRpYVF1ZXJ5XG4gIHJldHVybiBmb3JtYXQoYEBtZWRpYSAke21lZGlhUXVlcnl9IHtgLCBjc3MsICd9Jyk7XG59XG5cbi8qKlxuICogRm9yIGRlYnVnZ2luZyBwdXJwb3NlcywgcHJlZml4IGNzcyBzZWdtZW50IHdpdGggbGluZWZlZWQocykgZm9yIGVhc3lcbiAgKiBkZWJ1Z2dpbmcgcHVycG9zZXMuXG4gKi9cbmZ1bmN0aW9uIGZvcm1hdCguLi5saXN0OiBzdHJpbmdbXSk6IHN0cmluZyB7XG4gIGxldCByZXN1bHQgPSAnJztcbiAgbGlzdC5mb3JFYWNoKChjc3MsIGkpID0+IHtcbiAgICByZXN1bHQgKz0gSVNfREVCVUdfTU9ERSA/IGZvcm1hdFNlZ21lbnQoY3NzLCBpICE9PSAwKSA6IGNzcztcbiAgfSk7XG4gIHJldHVybiByZXN1bHQ7XG59XG5cbmZ1bmN0aW9uIGZvcm1hdFNlZ21lbnQoY3NzOiBzdHJpbmcsIGFzUHJlZml4OiBib29sZWFuID0gdHJ1ZSk6IHN0cmluZyB7XG4gIHJldHVybiBhc1ByZWZpeCA/IGBcXG4ke2Nzc31gIDogYCR7Y3NzfVxcbmA7XG59XG5cbi8qKlxuICogR2V0IGNsYXNzTmFtZSBhc3NvY2lhdGVkIHdpdGggQ1NTIHN0eWxpbmdcbiAqIElmIG5vdCBmb3VuZCwgZ2VuZXJhdGUgZ2xvYmFsIGNsYXNzTmFtZSBhbmQgc2V0XG4gKiBhc3NvY2lhdGlvbi5cbiAqL1xuZnVuY3Rpb24gZ2V0Q2xhc3NOYW1lKGVsZW1lbnQ6IEhUTUxFbGVtZW50LCBjbGFzc01hcDogTWFwPEhUTUxFbGVtZW50LCBzdHJpbmc+KSB7XG4gIGxldCBjbGFzc05hbWUgPSBjbGFzc01hcC5nZXQoZWxlbWVudCk7XG4gIGlmICghY2xhc3NOYW1lKSB7XG4gICAgY2xhc3NOYW1lID0gYCR7Q0xBU1NfTkFNRX0ke25leHRJZCsrfWA7XG4gICAgY2xhc3NNYXAuc2V0KGVsZW1lbnQsIGNsYXNzTmFtZSk7XG4gIH1cbiAgZWxlbWVudC5jbGFzc0xpc3QuYWRkKGNsYXNzTmFtZSk7XG5cbiAgcmV0dXJuIGNsYXNzTmFtZTtcbn1cbiJdfQ==
\No newline at end of file