@angular/flex-layout
Version:
Angular Flex-Layout =======
140 lines • 17.7 kB
JavaScript
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
import { DOCUMENT } from '@angular/common';
import { BEFORE_APP_SERIALIZED } from '@angular/platform-server';
import { BREAKPOINTS, CLASS_NAME, SERVER_TOKEN, ɵMatchMedia as MatchMedia, StylesheetMap, sortAscendingPriority, MediaMarshaller, } from '@angular/flex-layout/core';
import { ServerMatchMedia } from './server-match-media';
/**
* Activate all the registered breakpoints in sequence, and then
* retrieve the associated stylings from the virtual stylesheet
* @param serverSheet the virtual stylesheet that stores styles for each
* element
* @param mediaController the MatchMedia service to activate/deactivate breakpoints
* @param breakpoints the registered breakpoints to activate/deactivate
* @param mediaMarshaller the MediaMarshaller service to disable fallback styles dynamically
*/
export function generateStaticFlexLayoutStyles(serverSheet, mediaController, breakpoints, mediaMarshaller) {
// Store the custom classes in the following map, that way only
// one class gets allocated per HTMLElement, and each class can
// be referenced in the static media queries
const classMap = new Map();
// Get the initial stylings for all the directives,
// and initialize the fallback block of stylings.
const defaultStyles = new Map(serverSheet.stylesheet);
// Reset the class counter, otherwise class numbers will
// increase with each server render.
nextId = 0;
let styleText = generateCss(defaultStyles, 'all', classMap);
mediaMarshaller.useFallbacks = false;
[...breakpoints].sort(sortAscendingPriority).forEach((bp) => {
serverSheet.clearStyles();
mediaController.activateBreakpoint(bp);
const stylesheet = new Map(serverSheet.stylesheet);
if (stylesheet.size > 0) {
styleText += generateCss(stylesheet, bp.mediaQuery, classMap);
}
mediaController.deactivateBreakpoint(bp);
});
return styleText;
}
/**
* Create a style tag populated with the dynamic stylings from Flex
* components and attach it to the head of the DOM
*/
export function FLEX_SSR_SERIALIZER_FACTORY(serverSheet, mediaController, _document, breakpoints, mediaMarshaller) {
return () => {
// This is the style tag that gets inserted into the head of the DOM,
// populated with the manual media queries
const styleTag = _document.createElement('style');
const styleText = generateStaticFlexLayoutStyles(serverSheet, mediaController, breakpoints, mediaMarshaller);
styleTag.classList.add(`${CLASS_NAME}ssr`);
styleTag.textContent = styleText;
_document.head.appendChild(styleTag);
};
}
/**
* Provider to set static styles on the server
*/
export const SERVER_PROVIDERS = [
{
provide: BEFORE_APP_SERIALIZED,
useFactory: FLEX_SSR_SERIALIZER_FACTORY,
deps: [
StylesheetMap,
MatchMedia,
DOCUMENT,
BREAKPOINTS,
MediaMarshaller,
],
multi: true,
},
{
provide: SERVER_TOKEN,
useValue: true
},
{
provide: MatchMedia,
useClass: ServerMatchMedia
}
];
let nextId = 0;
const IS_DEBUG_MODE = false;
/**
* create @media queries based on a virtual stylesheet
* * Adds a unique class to each element and stores it
* in a shared classMap for later reuse
* @param stylesheet the virtual stylesheet that stores styles for each
* element
* @param mediaQuery the given @media CSS selector for the current breakpoint
* @param classMap the map of HTML elements to class names to avoid duplications
*/
function generateCss(stylesheet, mediaQuery, classMap) {
let css = '';
stylesheet.forEach((styles, el) => {
let keyVals = '';
let className = getClassName(el, classMap);
styles.forEach((v, k) => {
keyVals += v ? format(`${k}:${v};`) : '';
});
if (keyVals) {
// Build list of CSS styles; each with a className
css += format(`.${className} {`, keyVals, '}');
}
});
// Group 1 or more styles (each with className) in a specific mediaQuery
return format(`@media ${mediaQuery} {`, css, '}');
}
/**
* For debugging purposes, prefix css segment with linefeed(s) for easy
* debugging purposes.
*/
function format(...list) {
let result = '';
list.forEach((css, i) => {
result += IS_DEBUG_MODE ? formatSegment(css, i !== 0) : css;
});
return result;
}
function formatSegment(css, asPrefix = true) {
return asPrefix ? `\n${css}` : `${css}\n`;
}
/**
* Get className associated with CSS styling
* If not found, generate global className and set
* association.
*/
function getClassName(element, classMap) {
let className = classMap.get(element);
if (!className) {
className = `${CLASS_NAME}${nextId++}`;
classMap.set(element, className);
}
element.classList.add(className);
return className;
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2VydmVyLXByb3ZpZGVyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vcHJvamVjdHMvbGlicy9mbGV4LWxheW91dC9zZXJ2ZXIvc2VydmVyLXByb3ZpZGVyLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOzs7Ozs7R0FNRztBQUNILE9BQU8sRUFBQyxRQUFRLEVBQUMsTUFBTSxpQkFBaUIsQ0FBQztBQUN6QyxPQUFPLEVBQUMscUJBQXFCLEVBQUMsTUFBTSwwQkFBMEIsQ0FBQztBQUMvRCxPQUFPLEVBQ0wsV0FBVyxFQUNYLFVBQVUsRUFDVixZQUFZLEVBRVosV0FBVyxJQUFJLFVBQVUsRUFDekIsYUFBYSxFQUNiLHFCQUFxQixFQUNyQixlQUFlLEdBQ2hCLE1BQU0sMkJBQTJCLENBQUM7QUFFbkMsT0FBTyxFQUFDLGdCQUFnQixFQUFDLE1BQU0sc0JBQXNCLENBQUM7QUFFdEQ7Ozs7Ozs7O0dBUUc7QUFDSCxNQUFNLFVBQVUsOEJBQThCLENBQUMsV0FBMEIsRUFDMUIsZUFBaUMsRUFDakMsV0FBeUIsRUFDekIsZUFBZ0M7SUFDN0UsK0RBQStEO0lBQy9ELCtEQUErRDtJQUMvRCw0Q0FBNEM7SUFDNUMsTUFBTSxRQUFRLEdBQUcsSUFBSSxHQUFHLEVBQXVCLENBQUM7SUFFaEQsbURBQW1EO0lBQ25ELGlEQUFpRDtJQUNqRCxNQUFNLGFBQWEsR0FBRyxJQUFJLEdBQUcsQ0FBQyxXQUFXLENBQUMsVUFBVSxDQUFDLENBQUM7SUFDdEQsd0RBQXdEO0lBQ3hELG9DQUFvQztJQUNwQyxNQUFNLEdBQUcsQ0FBQyxDQUFDO0lBQ1gsSUFBSSxTQUFTLEdBQUcsV0FBVyxDQUFDLGFBQWEsRUFBRSxLQUFLLEVBQUUsUUFBUSxDQUFDLENBQUM7SUFDNUQsZUFBZSxDQUFDLFlBQVksR0FBRyxLQUFLLENBQUM7SUFFckMsQ0FBQyxHQUFHLFdBQVcsQ0FBQyxDQUFDLElBQUksQ0FBQyxxQkFBcUIsQ0FBQyxDQUFDLE9BQU8sQ0FB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QyxDQUFDO0FBQ3BELENBQUM7QUFFRDs7O0dBR0c7QUFDSCxTQUFTLE1BQU0sQ0FBQyxHQUFHLElBQWM7SUFDL0IsSUFBSSxNQUFNLEdBQUcsRUFBRSxDQUFDO0lBQ2hCLElBQUksQ0FBQyxPQUFPLENBQUMsQ0FBQyxHQUFHLEVBQUUsQ0FBQyxFQUFFLEVBQUU7UUFDdEIsTUFBTSxJQUFJLGFBQWEsQ0FBQyxDQUFDLENBQUMsYUFBYSxDQUFDLEdBQUcsRUFBRSxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLEdBQUcsQ0FBQztJQUM5RCxDQUFDLENBQUMsQ0FBQztJQUNILE9BQU8sTUFBTSxDQUFDO0FBQ2hCLENBQUM7QUFFRCxTQUFTLGFBQWEsQ0FBQyxHQUFXLEVBQUUsV0FBb0IsSUFBSTtJQUMxRCxPQUFPLFFBQVEsQ0FBQyxDQUFDLENBQUMsS0FBSyxHQUFHLEVBQUUsQ0FBQyxDQUFDLENBQUMsR0FBRyxHQUFHLElBQUksQ0FBQztBQUM1QyxDQUFDO0FBRUQ7Ozs7R0FJRztBQUNILFNBQVMsWUFBWSxDQUFDLE9BQW9CLEVBQUUsUUFBa0M7SUFDNUUsSUFBSSxTQUFTLEdBQUcsUUFBUSxDQUFDLEdBQUcsQ0FBQyxPQUFPLENBQUMsQ0FBQztJQUN0QyxJQUFJLENBQUMsU0FBUyxFQUFFO1FBQ2QsU0FBUyxHQUFHLEdBQUcsVUFBVSxHQUFHLE1BQU0sRUFBRSxFQUFFLENBQUM7UUFDdkMsUUFBUSxDQUFDLEdBQUcsQ0FBQyxPQUFPLEVBQUUsU0FBUyxDQUFDLENBQUM7S0FDbEM7SUFDRCxPQUFPLENBQUMsU0FBUyxDQUFDLEdBQUcsQ0FBQyxTQUFTLENBQUMsQ0FBQztJQUVqQyxPQUFPLFNBQVMsQ0FBQztBQUNuQixDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBAbGljZW5zZVxuICogQ29weXJpZ2h0IEdvb2dsZSBMTEMgQWxsIFJpZ2h0cyBSZXNlcnZlZC5cbiAqXG4gKiBVc2Ugb2YgdGhpcyBzb3VyY2UgY29kZSBpcyBnb3Zlcm5lZCBieSBhbiBNSVQtc3R5bGUgbGljZW5zZSB0aGF0IGNhbiBiZVxuICogZm91bmQgaW4gdGhlIExJQ0VOU0UgZmlsZSBhdCBodHRwczovL2FuZ3VsYXIuaW8vbGljZW5zZVxuICovXG5pbXBvcnQge0RPQ1VNRU5UfSBmcm9tICdAYW5ndWxhci9jb21tb24nO1xuaW1wb3J0IHtCRUZPUkVfQVBQX1NFUklBTElaRUR9IGZyb20gJ0Bhbmd1bGFyL3BsYXRmb3JtLXNlcnZlcic7XG5pbXBvcnQge1xuICBCUkVBS1BPSU5UUyxcbiAgQ0xBU1NfTkFNRSxcbiAgU0VSVkVSX1RPS0VOLFxuICBCcmVha1BvaW50LFxuICDJtU1hdGNoTWVkaWEgYXMgTWF0Y2hNZWRpYSxcbiAgU3R5bGVzaGVldE1hcCxcbiAgc29ydEFzY2VuZGluZ1ByaW9yaXR5LFxuICBNZWRpYU1hcnNoYWxsZXIsXG59IGZyb20gJ0Bhbmd1bGFyL2ZsZXgtbGF5b3V0L2NvcmUnO1xuXG5pbXBvcnQge1NlcnZlck1hdGNoTWVkaWF9IGZyb20gJy4vc2VydmVyLW1hdGNoLW1lZGlhJztcblxuLyoqXG4gKiBBY3RpdmF0ZSBhbGwgdGhlIHJlZ2lzdGVyZWQgYnJlYWtwb2ludHMgaW4gc2VxdWVuY2UsIGFuZCB0aGVuXG4gKiByZXRyaWV2ZSB0aGUgYXNzb2NpYXRlZCBzdHlsaW5ncyBmcm9tIHRoZSB2aXJ0dWFsIHN0eWxlc2hlZXRcbiAqIEBwYXJhbSBzZXJ2ZXJTaGVldCB0aGUgdmlydHVhbCBzdHlsZXNoZWV0IHRoYXQgc3RvcmVzIHN0eWxlcyBmb3IgZWFjaFxuICogICAgICAgIGVsZW1lbnRcbiAqIEBwYXJhbSBtZWRpYUNvbnRyb2xsZXIgdGhlIE1hdGNoTWVkaWEgc2VydmljZSB0byBhY3RpdmF0ZS9kZWFjdGl2YXRlIGJyZWFrcG9pbnRzXG4gKiBAcGFyYW0gYnJlYWtwb2ludHMgdGhlIHJlZ2lzdGVyZWQgYnJlYWtwb2ludHMgdG8gYWN0aXZhdGUvZGVhY3RpdmF0ZVxuICogQHBhcmFtIG1lZGlhTWFyc2hhbGxlciB0aGUgTWVkaWFNYXJzaGFsbGVyIHNlcnZpY2UgdG8gZGlzYWJsZSBmYWxsYmFjayBzdHlsZXMgZHluYW1pY2FsbHlcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGdlbmVyYXRlU3RhdGljRmxleExheW91dFN0eWxlcyhzZXJ2ZXJTaGVldDogU3R5bGVzaGVldE1hcCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWVkaWFDb250cm9sbGVyOiBTZXJ2ZXJNYXRjaE1lZGlhLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVha3BvaW50czogQnJlYWtQb2ludFtdLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtZWRpYU1hcnNoYWxsZXI6IE1lZGlhTWFyc2hhbGxlcikge1xuICAvLyBTdG9yZSB0aGUgY3VzdG9tIGNsYXNzZXMgaW4gdGhlIGZvbGxvd2luZyBtYXAsIHRoYXQgd2F5IG9ubHlcbiAgLy8gb25lIGNsYXNzIGdldHMgYWxsb2NhdGVkIHBlciBIVE1MRWxlbWVudCwgYW5kIGVhY2ggY2xhc3MgY2FuXG4gIC8vIGJlIHJlZmVyZW5jZWQgaW4gdGhlIHN0YXRpYyBtZWRpYSBxdWVyaWVzXG4gIGNvbnN0IGNsYXNzTWFwID0gbmV3IE1hcDxIVE1MRWxlbWVudCwgc3RyaW5nPigpO1xuXG4gIC8vIEdldCB0aGUgaW5pdGlhbCBzdHlsaW5ncyBmb3IgYWxsIHRoZSBkaXJlY3RpdmVzLFxuICAvLyBhbmQgaW5pdGlhbGl6ZSB0aGUgZmFsbGJhY2sgYmxvY2sgb2Ygc3R5bGluZ3MuXG4gIGNvbnN0IGRlZmF1bHRTdHlsZXMgPSBuZXcgTWFwKHNlcnZlclNoZWV0LnN0eWxlc2hlZXQpO1xuICAvLyBSZXNldCB0aGUgY2xhc3MgY291bnRlciwgb3RoZXJ3aXNlIGNsYXNzIG51bWJlcnMgd2lsbFxuICAvLyBpbmNyZWFzZSB3aXRoIGVhY2ggc2VydmVyIHJlbmRlci5cbiAgbmV4dElkID0gMDtcbiAgbGV0IHN0eWxlVGV4dCA9IGdlbmVyYXRlQ3NzKGRlZmF1bHRTdHlsZXMsICdhbGwnLCBjbGFzc01hcCk7XG4gIG1lZGlhTWFyc2hhbGxlci51c2VGYWxsYmFja3MgPSBmYWxzZTtcblxuICBbLi4uYnJlYWtwb2ludHNdLnNvcnQoc29ydEFzY2VuZGluZ1ByaW9yaXR5KS5mb3JFYWNoKChicCkgPT4ge1xuICAgIHNlcnZlclNoZWV0LmNsZWFyU3R5bGVzKCk7XG4gICAgbWVkaWFDb250cm9sbGVyLmFjdGl2YXRlQnJlYWtwb2ludChicCk7XG4gICAgY29uc3Qgc3R5bGVzaGVldCA9IG5ldyBNYXAoc2VydmVyU2hlZXQuc3R5bGVzaGVldCk7XG4gICAgaWYgKHN0eWxlc2hlZXQuc2l6ZSA+IDApIHtcbiAgICAgIHN0eWxlVGV4dCArPSBnZW5lcmF0ZUNzcyhzdHlsZXNoZWV0LCBicC5tZWRpYVF1ZXJ5LCBjbGFzc01hcCk7XG4gICAgfVxuICAgIG1lZGlhQ29udHJvbGxlci5kZWFjdGl2YXRlQnJlYWtwb2ludChicCk7XG4gIH0pO1xuXG4gIHJldHVybiBzdHlsZVRleHQ7XG59XG5cbi8qKlxuICogQ3JlYXRlIGEgc3R5bGUgdGFnIHBvcHVsYXRlZCB3aXRoIHRoZSBkeW5hbWljIHN0eWxpbmdzIGZyb20gRmxleFxuICogY29tcG9uZW50cyBhbmQgYXR0YWNoIGl0IHRvIHRoZSBoZWFkIG9mIHRoZSBET01cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIEZMRVhfU1NSX1NFUklBTElaRVJfRkFDVE9SWShzZXJ2ZXJTaGVldDogU3R5bGVzaGVldE1hcCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWVkaWFDb250cm9sbGVyOiBTZXJ2ZXJNYXRjaE1lZGlhLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBfZG9jdW1lbnQ6IERvY3VtZW50LFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVha3BvaW50czogQnJlYWtQb2ludFtdLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtZWRpYU1hcnNoYWxsZXI6IE1lZGlhTWFyc2hhbGxlcikge1xuICByZXR1cm4gKCkgPT4ge1xuICAgIC8vIFRoaXMgaXMgdGhlIHN0eWxlIHRhZyB0aGF0IGdldHMgaW5zZXJ0ZWQgaW50byB0aGUgaGVhZCBvZiB0aGUgRE9NLFxuICAgIC8vIHBvcHVsYXRlZCB3aXRoIHRoZSBtYW51YWwgbWVkaWEgcXVlcmllc1xuICAgIGNvbnN0IHN0eWxlVGFnID0gX2RvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ3N0eWxlJyk7XG4gICAgY29uc3Qgc3R5bGVUZXh0ID0gZ2VuZXJhdGVTdGF0aWNGbGV4TGF5b3V0U3R5bGVzKFxuICAgICAgc2VydmVyU2hlZXQsIG1lZGlhQ29udHJvbGxlciwgYnJlYWtwb2ludHMsIG1lZGlhTWFyc2hhbGxlcik7XG4gICAgc3R5bGVUYWcuY2xhc3NMaXN0LmFkZChgJHtDTEFTU19OQU1FfXNzcmApO1xuICAgIHN0eWxlVGFnLnRleHRDb250ZW50ID0gc3R5bGVUZXh0O1xuICAgIF9kb2N1bWVudC5oZWFkIS5hcHBlbmRDaGlsZChzdHlsZVRhZyk7XG4gIH07XG59XG5cbi8qKlxuICogIFByb3ZpZGVyIHRvIHNldCBzdGF0aWMgc3R5bGVzIG9uIHRoZSBzZXJ2ZXJcbiAqL1xuZXhwb3J0IGNvbnN0IFNFUlZFUl9QUk9WSURFUlMgPSBbXG4gIHtcbiAgICBwcm92aWRlOiBCRUZPUkVfQVBQX1NFUklBTElaRUQsXG4gICAgdXNlRmFjdG9yeTogRkxFWF9TU1JfU0VSSUFMSVpFUl9GQUNUT1JZLFxuICAgIGRlcHM6IFtcbiAgICAgIFN0eWxlc2hlZXRNYXAsXG4gICAgICBNYXRjaE1lZGlhLFxuICAgICAgRE9DVU1FTlQsXG4gICAgICBCUkVBS1BPSU5UUyxcbiAgICAgIE1lZGlhTWFyc2hhbGxlcixcbiAgICBdLFxuICAgIG11bHRpOiB0cnVlLFxuICB9LFxuICB7XG4gICAgcHJvdmlkZTogU0VSVkVSX1RPS0VOLFxuICAgIHVzZVZhbHVlOiB0cnVlXG4gIH0sXG4gIHtcbiAgICBwcm92aWRlOiBNYXRjaE1lZGlhLFxuICAgIHVzZUNsYXNzOiBTZXJ2ZXJNYXRjaE1lZGlhXG4gIH1cbl07XG5cblxubGV0IG5leHRJZCA9IDA7XG5jb25zdCBJU19ERUJVR19NT0RFID0gZmFsc2U7XG5cbmV4cG9ydCB0eXBlIFN0eWxlU2hlZXQgPSBNYXA8SFRNTEVsZW1lbnQsIE1hcDxzdHJpbmcsIHN0cmluZ3xudW1iZXI+PjtcbmV4cG9ydCB0eXBlIENsYXNzTWFwID0gTWFwPEhUTUxFbGVtZW50LCBzdHJpbmc+O1xuXG4vKipcbiAqIGNyZWF0ZSBAbWVkaWEgcXVlcmllcyBiYXNlZCBvbiBhIHZpcnR1YWwgc3R5bGVzaGVldFxuICogKiBBZGRzIGEgdW5pcXVlIGNsYXNzIHRvIGVhY2ggZWxlbWVudCBhbmQgc3RvcmVzIGl0XG4gKiAgIGluIGEgc2hhcmVkIGNsYXNzTWFwIGZvciBsYXRlciByZXVzZVxuICogQHBhcmFtIHN0eWxlc2hlZXQgdGhlIHZpcnR1YWwgc3R5bGVzaGVldCB0aGF0IHN0b3JlcyBzdHlsZXMgZm9yIGVhY2hcbiAqICAgICAgICBlbGVtZW50XG4gKiBAcGFyYW0gbWVkaWFRdWVyeSB0aGUgZ2l2ZW4gQG1lZGlhIENTUyBzZWxlY3RvciBmb3IgdGhlIGN1cnJlbnQgYnJlYWtwb2ludFxuICogQHBhcmFtIGNsYXNzTWFwIHRoZSBtYXAgb2YgSFRNTCBlbGVtZW50cyB0byBjbGFzcyBuYW1lcyB0byBhdm9pZCBkdXBsaWNhdGlvbnNcbiAqL1xuZnVuY3Rpb24gZ2VuZXJhdGVDc3Moc3R5bGVzaGVldDogU3R5bGVTaGVldCwgbWVkaWFRdWVyeTogc3RyaW5nLCBjbGFzc01hcDogQ2xhc3NNYXApIHtcbiAgbGV0IGNzcyA9ICcnO1xuICBzdHlsZXNoZWV0LmZvckVhY2goKHN0eWxlcywgZWwpID0+IHtcbiAgICBsZXQga2V5VmFscyA9ICcnO1xuICAgIGxldCBjbGFzc05hbWUgPSBnZXRDbGFzc05hbWUoZWwsIGNsYXNzTWFwKTtcblxuICAgIHN0eWxlcy5mb3JFYWNoKCh2LCBrKSA9PiB7XG4gICAgICBrZXlWYWxzICs9IHYgPyBmb3JtYXQoYCR7a306JHt2fTtgKSA6ICcnO1xuICAgIH0pO1xuXG4gICAgaWYgKGtleVZhbHMpIHtcbiAgICAgIC8vIEJ1aWxkIGxpc3Qgb2YgQ1NTIHN0eWxlczsgZWFjaCB3aXRoIGEgY2xhc3NOYW1lXG4gICAgICBjc3MgKz0gZm9ybWF0KGAuJHtjbGFzc05hbWV9IHtgLCBrZXlWYWxzLCAnfScpO1xuICAgIH1cbiAgfSk7XG5cbiAgLy8gR3JvdXAgMSBvciBtb3JlIHN0eWxlcyAoZWFjaCB3aXRoIGNsYXNzTmFtZSkgaW4gYSBzcGVjaWZpYyBtZWRpYVF1ZXJ5XG4gIHJldHVybiBmb3JtYXQoYEBtZWRpYSAke21lZGlhUXVlcnl9IHtgLCBjc3MsICd9Jyk7XG59XG5cbi8qKlxuICogRm9yIGRlYnVnZ2luZyBwdXJwb3NlcywgcHJlZml4IGNzcyBzZWdtZW50IHdpdGggbGluZWZlZWQocykgZm9yIGVhc3lcbiAgKiBkZWJ1Z2dpbmcgcHVycG9zZXMuXG4gKi9cbmZ1bmN0aW9uIGZvcm1hdCguLi5saXN0OiBzdHJpbmdbXSk6IHN0cmluZyB7XG4gIGxldCByZXN1bHQgPSAnJztcbiAgbGlzdC5mb3JFYWNoKChjc3MsIGkpID0+IHtcbiAgICByZXN1bHQgKz0gSVNfREVCVUdfTU9ERSA/IGZvcm1hdFNlZ21lbnQoY3NzLCBpICE9PSAwKSA6IGNzcztcbiAgfSk7XG4gIHJldHVybiByZXN1bHQ7XG59XG5cbmZ1bmN0aW9uIGZvcm1hdFNlZ21lbnQoY3NzOiBzdHJpbmcsIGFzUHJlZml4OiBib29sZWFuID0gdHJ1ZSk6IHN0cmluZyB7XG4gIHJldHVybiBhc1ByZWZpeCA/IGBcXG4ke2Nzc31gIDogYCR7Y3NzfVxcbmA7XG59XG5cbi8qKlxuICogR2V0IGNsYXNzTmFtZSBhc3NvY2lhdGVkIHdpdGggQ1NTIHN0eWxpbmdcbiAqIElmIG5vdCBmb3VuZCwgZ2VuZXJhdGUgZ2xvYmFsIGNsYXNzTmFtZSBhbmQgc2V0XG4gKiBhc3NvY2lhdGlvbi5cbiAqL1xuZnVuY3Rpb24gZ2V0Q2xhc3NOYW1lKGVsZW1lbnQ6IEhUTUxFbGVtZW50LCBjbGFzc01hcDogTWFwPEhUTUxFbGVtZW50LCBzdHJpbmc+KSB7XG4gIGxldCBjbGFzc05hbWUgPSBjbGFzc01hcC5nZXQoZWxlbWVudCk7XG4gIGlmICghY2xhc3NOYW1lKSB7XG4gICAgY2xhc3NOYW1lID0gYCR7Q0xBU1NfTkFNRX0ke25leHRJZCsrfWA7XG4gICAgY2xhc3NNYXAuc2V0KGVsZW1lbnQsIGNsYXNzTmFtZSk7XG4gIH1cbiAgZWxlbWVudC5jbGFzc0xpc3QuYWRkKGNsYXNzTmFtZSk7XG5cbiAgcmV0dXJuIGNsYXNzTmFtZTtcbn1cbiJdfQ==