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 { coerceBooleanProperty } from '@angular/cdk/coercion';
|
---|
9 | import { DOCUMENT } from '@angular/common';
|
---|
10 | import { Attribute, ChangeDetectionStrategy, Component, ElementRef, ErrorHandler, inject, Inject, InjectionToken, Input, ViewEncapsulation, } from '@angular/core';
|
---|
11 | import { mixinColor } from '@angular/material/core';
|
---|
12 | import { Subscription } from 'rxjs';
|
---|
13 | import { take } from 'rxjs/operators';
|
---|
14 | import { MatIconRegistry } from './icon-registry';
|
---|
15 | // Boilerplate for applying mixins to MatIcon.
|
---|
16 | /** @docs-private */
|
---|
17 | const _MatIconBase = mixinColor(class {
|
---|
18 | constructor(_elementRef) {
|
---|
19 | this._elementRef = _elementRef;
|
---|
20 | }
|
---|
21 | });
|
---|
22 | /**
|
---|
23 | * Injection token used to provide the current location to `MatIcon`.
|
---|
24 | * Used to handle server-side rendering and to stub out during unit tests.
|
---|
25 | * @docs-private
|
---|
26 | */
|
---|
27 | export const MAT_ICON_LOCATION = new InjectionToken('mat-icon-location', {
|
---|
28 | providedIn: 'root',
|
---|
29 | factory: MAT_ICON_LOCATION_FACTORY
|
---|
30 | });
|
---|
31 | /** @docs-private */
|
---|
32 | export function MAT_ICON_LOCATION_FACTORY() {
|
---|
33 | const _document = inject(DOCUMENT);
|
---|
34 | const _location = _document ? _document.location : null;
|
---|
35 | return {
|
---|
36 | // Note that this needs to be a function, rather than a property, because Angular
|
---|
37 | // will only resolve it once, but we want the current path on each call.
|
---|
38 | getPathname: () => _location ? (_location.pathname + _location.search) : ''
|
---|
39 | };
|
---|
40 | }
|
---|
41 | /** SVG attributes that accept a FuncIRI (e.g. `url(<something>)`). */
|
---|
42 | const funcIriAttributes = [
|
---|
43 | 'clip-path',
|
---|
44 | 'color-profile',
|
---|
45 | 'src',
|
---|
46 | 'cursor',
|
---|
47 | 'fill',
|
---|
48 | 'filter',
|
---|
49 | 'marker',
|
---|
50 | 'marker-start',
|
---|
51 | 'marker-mid',
|
---|
52 | 'marker-end',
|
---|
53 | 'mask',
|
---|
54 | 'stroke'
|
---|
55 | ];
|
---|
56 | const ɵ0 = attr => `[${attr}]`;
|
---|
57 | /** Selector that can be used to find all elements that are using a `FuncIRI`. */
|
---|
58 | const funcIriAttributeSelector = funcIriAttributes.map(ɵ0).join(', ');
|
---|
59 | /** Regex that can be used to extract the id out of a FuncIRI. */
|
---|
60 | const funcIriPattern = /^url\(['"]?#(.*?)['"]?\)$/;
|
---|
61 | /**
|
---|
62 | * Component to display an icon. It can be used in the following ways:
|
---|
63 | *
|
---|
64 | * - Specify the svgIcon input to load an SVG icon from a URL previously registered with the
|
---|
65 | * addSvgIcon, addSvgIconInNamespace, addSvgIconSet, or addSvgIconSetInNamespace methods of
|
---|
66 | * MatIconRegistry. If the svgIcon value contains a colon it is assumed to be in the format
|
---|
67 | * "[namespace]:[name]", if not the value will be the name of an icon in the default namespace.
|
---|
68 | * Examples:
|
---|
69 | * `<mat-icon svgIcon="left-arrow"></mat-icon>
|
---|
70 | * <mat-icon svgIcon="animals:cat"></mat-icon>`
|
---|
71 | *
|
---|
72 | * - Use a font ligature as an icon by putting the ligature text in the content of the `<mat-icon>`
|
---|
73 | * component. By default the Material icons font is used as described at
|
---|
74 | * http://google.github.io/material-design-icons/#icon-font-for-the-web. You can specify an
|
---|
75 | * alternate font by setting the fontSet input to either the CSS class to apply to use the
|
---|
76 | * desired font, or to an alias previously registered with MatIconRegistry.registerFontClassAlias.
|
---|
77 | * Examples:
|
---|
78 | * `<mat-icon>home</mat-icon>
|
---|
79 | * <mat-icon fontSet="myfont">sun</mat-icon>`
|
---|
80 | *
|
---|
81 | * - Specify a font glyph to be included via CSS rules by setting the fontSet input to specify the
|
---|
82 | * font, and the fontIcon input to specify the icon. Typically the fontIcon will specify a
|
---|
83 | * CSS class which causes the glyph to be displayed via a :before selector, as in
|
---|
84 | * https://fortawesome.github.io/Font-Awesome/examples/
|
---|
85 | * Example:
|
---|
86 | * `<mat-icon fontSet="fa" fontIcon="alarm"></mat-icon>`
|
---|
87 | */
|
---|
88 | export class MatIcon extends _MatIconBase {
|
---|
89 | constructor(elementRef, _iconRegistry, ariaHidden, _location, _errorHandler) {
|
---|
90 | super(elementRef);
|
---|
91 | this._iconRegistry = _iconRegistry;
|
---|
92 | this._location = _location;
|
---|
93 | this._errorHandler = _errorHandler;
|
---|
94 | this._inline = false;
|
---|
95 | /** Subscription to the current in-progress SVG icon request. */
|
---|
96 | this._currentIconFetch = Subscription.EMPTY;
|
---|
97 | // If the user has not explicitly set aria-hidden, mark the icon as hidden, as this is
|
---|
98 | // the right thing to do for the majority of icon use-cases.
|
---|
99 | if (!ariaHidden) {
|
---|
100 | elementRef.nativeElement.setAttribute('aria-hidden', 'true');
|
---|
101 | }
|
---|
102 | }
|
---|
103 | /**
|
---|
104 | * Whether the icon should be inlined, automatically sizing the icon to match the font size of
|
---|
105 | * the element the icon is contained in.
|
---|
106 | */
|
---|
107 | get inline() {
|
---|
108 | return this._inline;
|
---|
109 | }
|
---|
110 | set inline(inline) {
|
---|
111 | this._inline = coerceBooleanProperty(inline);
|
---|
112 | }
|
---|
113 | /** Name of the icon in the SVG icon set. */
|
---|
114 | get svgIcon() { return this._svgIcon; }
|
---|
115 | set svgIcon(value) {
|
---|
116 | if (value !== this._svgIcon) {
|
---|
117 | if (value) {
|
---|
118 | this._updateSvgIcon(value);
|
---|
119 | }
|
---|
120 | else if (this._svgIcon) {
|
---|
121 | this._clearSvgElement();
|
---|
122 | }
|
---|
123 | this._svgIcon = value;
|
---|
124 | }
|
---|
125 | }
|
---|
126 | /** Font set that the icon is a part of. */
|
---|
127 | get fontSet() { return this._fontSet; }
|
---|
128 | set fontSet(value) {
|
---|
129 | const newValue = this._cleanupFontValue(value);
|
---|
130 | if (newValue !== this._fontSet) {
|
---|
131 | this._fontSet = newValue;
|
---|
132 | this._updateFontIconClasses();
|
---|
133 | }
|
---|
134 | }
|
---|
135 | /** Name of an icon within a font set. */
|
---|
136 | get fontIcon() { return this._fontIcon; }
|
---|
137 | set fontIcon(value) {
|
---|
138 | const newValue = this._cleanupFontValue(value);
|
---|
139 | if (newValue !== this._fontIcon) {
|
---|
140 | this._fontIcon = newValue;
|
---|
141 | this._updateFontIconClasses();
|
---|
142 | }
|
---|
143 | }
|
---|
144 | /**
|
---|
145 | * Splits an svgIcon binding value into its icon set and icon name components.
|
---|
146 | * Returns a 2-element array of [(icon set), (icon name)].
|
---|
147 | * The separator for the two fields is ':'. If there is no separator, an empty
|
---|
148 | * string is returned for the icon set and the entire value is returned for
|
---|
149 | * the icon name. If the argument is falsy, returns an array of two empty strings.
|
---|
150 | * Throws an error if the name contains two or more ':' separators.
|
---|
151 | * Examples:
|
---|
152 | * `'social:cake' -> ['social', 'cake']
|
---|
153 | * 'penguin' -> ['', 'penguin']
|
---|
154 | * null -> ['', '']
|
---|
155 | * 'a:b:c' -> (throws Error)`
|
---|
156 | */
|
---|
157 | _splitIconName(iconName) {
|
---|
158 | if (!iconName) {
|
---|
159 | return ['', ''];
|
---|
160 | }
|
---|
161 | const parts = iconName.split(':');
|
---|
162 | switch (parts.length) {
|
---|
163 | case 1: return ['', parts[0]]; // Use default namespace.
|
---|
164 | case 2: return parts;
|
---|
165 | default: throw Error(`Invalid icon name: "${iconName}"`); // TODO: add an ngDevMode check
|
---|
166 | }
|
---|
167 | }
|
---|
168 | ngOnInit() {
|
---|
169 | // Update font classes because ngOnChanges won't be called if none of the inputs are present,
|
---|
170 | // e.g. <mat-icon>arrow</mat-icon> In this case we need to add a CSS class for the default font.
|
---|
171 | this._updateFontIconClasses();
|
---|
172 | }
|
---|
173 | ngAfterViewChecked() {
|
---|
174 | const cachedElements = this._elementsWithExternalReferences;
|
---|
175 | if (cachedElements && cachedElements.size) {
|
---|
176 | const newPath = this._location.getPathname();
|
---|
177 | // We need to check whether the URL has changed on each change detection since
|
---|
178 | // the browser doesn't have an API that will let us react on link clicks and
|
---|
179 | // we can't depend on the Angular router. The references need to be updated,
|
---|
180 | // because while most browsers don't care whether the URL is correct after
|
---|
181 | // the first render, Safari will break if the user navigates to a different
|
---|
182 | // page and the SVG isn't re-rendered.
|
---|
183 | if (newPath !== this._previousPath) {
|
---|
184 | this._previousPath = newPath;
|
---|
185 | this._prependPathToReferences(newPath);
|
---|
186 | }
|
---|
187 | }
|
---|
188 | }
|
---|
189 | ngOnDestroy() {
|
---|
190 | this._currentIconFetch.unsubscribe();
|
---|
191 | if (this._elementsWithExternalReferences) {
|
---|
192 | this._elementsWithExternalReferences.clear();
|
---|
193 | }
|
---|
194 | }
|
---|
195 | _usingFontIcon() {
|
---|
196 | return !this.svgIcon;
|
---|
197 | }
|
---|
198 | _setSvgElement(svg) {
|
---|
199 | this._clearSvgElement();
|
---|
200 | // Workaround for IE11 and Edge ignoring `style` tags inside dynamically-created SVGs.
|
---|
201 | // See: https://developer.microsoft.com/en-us/microsoft-edge/platform/issues/10898469/
|
---|
202 | // Do this before inserting the element into the DOM, in order to avoid a style recalculation.
|
---|
203 | const styleTags = svg.querySelectorAll('style');
|
---|
204 | for (let i = 0; i < styleTags.length; i++) {
|
---|
205 | styleTags[i].textContent += ' ';
|
---|
206 | }
|
---|
207 | // Note: we do this fix here, rather than the icon registry, because the
|
---|
208 | // references have to point to the URL at the time that the icon was created.
|
---|
209 | const path = this._location.getPathname();
|
---|
210 | this._previousPath = path;
|
---|
211 | this._cacheChildrenWithExternalReferences(svg);
|
---|
212 | this._prependPathToReferences(path);
|
---|
213 | this._elementRef.nativeElement.appendChild(svg);
|
---|
214 | }
|
---|
215 | _clearSvgElement() {
|
---|
216 | const layoutElement = this._elementRef.nativeElement;
|
---|
217 | let childCount = layoutElement.childNodes.length;
|
---|
218 | if (this._elementsWithExternalReferences) {
|
---|
219 | this._elementsWithExternalReferences.clear();
|
---|
220 | }
|
---|
221 | // Remove existing non-element child nodes and SVGs, and add the new SVG element. Note that
|
---|
222 | // we can't use innerHTML, because IE will throw if the element has a data binding.
|
---|
223 | while (childCount--) {
|
---|
224 | const child = layoutElement.childNodes[childCount];
|
---|
225 | // 1 corresponds to Node.ELEMENT_NODE. We remove all non-element nodes in order to get rid
|
---|
226 | // of any loose text nodes, as well as any SVG elements in order to remove any old icons.
|
---|
227 | if (child.nodeType !== 1 || child.nodeName.toLowerCase() === 'svg') {
|
---|
228 | layoutElement.removeChild(child);
|
---|
229 | }
|
---|
230 | }
|
---|
231 | }
|
---|
232 | _updateFontIconClasses() {
|
---|
233 | if (!this._usingFontIcon()) {
|
---|
234 | return;
|
---|
235 | }
|
---|
236 | const elem = this._elementRef.nativeElement;
|
---|
237 | const fontSetClass = this.fontSet ?
|
---|
238 | this._iconRegistry.classNameForFontAlias(this.fontSet) :
|
---|
239 | this._iconRegistry.getDefaultFontSetClass();
|
---|
240 | if (fontSetClass != this._previousFontSetClass) {
|
---|
241 | if (this._previousFontSetClass) {
|
---|
242 | elem.classList.remove(this._previousFontSetClass);
|
---|
243 | }
|
---|
244 | if (fontSetClass) {
|
---|
245 | elem.classList.add(fontSetClass);
|
---|
246 | }
|
---|
247 | this._previousFontSetClass = fontSetClass;
|
---|
248 | }
|
---|
249 | if (this.fontIcon != this._previousFontIconClass) {
|
---|
250 | if (this._previousFontIconClass) {
|
---|
251 | elem.classList.remove(this._previousFontIconClass);
|
---|
252 | }
|
---|
253 | if (this.fontIcon) {
|
---|
254 | elem.classList.add(this.fontIcon);
|
---|
255 | }
|
---|
256 | this._previousFontIconClass = this.fontIcon;
|
---|
257 | }
|
---|
258 | }
|
---|
259 | /**
|
---|
260 | * Cleans up a value to be used as a fontIcon or fontSet.
|
---|
261 | * Since the value ends up being assigned as a CSS class, we
|
---|
262 | * have to trim the value and omit space-separated values.
|
---|
263 | */
|
---|
264 | _cleanupFontValue(value) {
|
---|
265 | return typeof value === 'string' ? value.trim().split(' ')[0] : value;
|
---|
266 | }
|
---|
267 | /**
|
---|
268 | * Prepends the current path to all elements that have an attribute pointing to a `FuncIRI`
|
---|
269 | * reference. This is required because WebKit browsers require references to be prefixed with
|
---|
270 | * the current path, if the page has a `base` tag.
|
---|
271 | */
|
---|
272 | _prependPathToReferences(path) {
|
---|
273 | const elements = this._elementsWithExternalReferences;
|
---|
274 | if (elements) {
|
---|
275 | elements.forEach((attrs, element) => {
|
---|
276 | attrs.forEach(attr => {
|
---|
277 | element.setAttribute(attr.name, `url('${path}#${attr.value}')`);
|
---|
278 | });
|
---|
279 | });
|
---|
280 | }
|
---|
281 | }
|
---|
282 | /**
|
---|
283 | * Caches the children of an SVG element that have `url()`
|
---|
284 | * references that we need to prefix with the current path.
|
---|
285 | */
|
---|
286 | _cacheChildrenWithExternalReferences(element) {
|
---|
287 | const elementsWithFuncIri = element.querySelectorAll(funcIriAttributeSelector);
|
---|
288 | const elements = this._elementsWithExternalReferences =
|
---|
289 | this._elementsWithExternalReferences || new Map();
|
---|
290 | for (let i = 0; i < elementsWithFuncIri.length; i++) {
|
---|
291 | funcIriAttributes.forEach(attr => {
|
---|
292 | const elementWithReference = elementsWithFuncIri[i];
|
---|
293 | const value = elementWithReference.getAttribute(attr);
|
---|
294 | const match = value ? value.match(funcIriPattern) : null;
|
---|
295 | if (match) {
|
---|
296 | let attributes = elements.get(elementWithReference);
|
---|
297 | if (!attributes) {
|
---|
298 | attributes = [];
|
---|
299 | elements.set(elementWithReference, attributes);
|
---|
300 | }
|
---|
301 | attributes.push({ name: attr, value: match[1] });
|
---|
302 | }
|
---|
303 | });
|
---|
304 | }
|
---|
305 | }
|
---|
306 | /** Sets a new SVG icon with a particular name. */
|
---|
307 | _updateSvgIcon(rawName) {
|
---|
308 | this._svgNamespace = null;
|
---|
309 | this._svgName = null;
|
---|
310 | this._currentIconFetch.unsubscribe();
|
---|
311 | if (rawName) {
|
---|
312 | const [namespace, iconName] = this._splitIconName(rawName);
|
---|
313 | if (namespace) {
|
---|
314 | this._svgNamespace = namespace;
|
---|
315 | }
|
---|
316 | if (iconName) {
|
---|
317 | this._svgName = iconName;
|
---|
318 | }
|
---|
319 | this._currentIconFetch = this._iconRegistry.getNamedSvgIcon(iconName, namespace)
|
---|
320 | .pipe(take(1))
|
---|
321 | .subscribe(svg => this._setSvgElement(svg), (err) => {
|
---|
322 | const errorMessage = `Error retrieving icon ${namespace}:${iconName}! ${err.message}`;
|
---|
323 | this._errorHandler.handleError(new Error(errorMessage));
|
---|
324 | });
|
---|
325 | }
|
---|
326 | }
|
---|
327 | }
|
---|
328 | MatIcon.decorators = [
|
---|
329 | { type: Component, args: [{
|
---|
330 | template: '<ng-content></ng-content>',
|
---|
331 | selector: 'mat-icon',
|
---|
332 | exportAs: 'matIcon',
|
---|
333 | inputs: ['color'],
|
---|
334 | host: {
|
---|
335 | 'role': 'img',
|
---|
336 | 'class': 'mat-icon notranslate',
|
---|
337 | '[attr.data-mat-icon-type]': '_usingFontIcon() ? "font" : "svg"',
|
---|
338 | '[attr.data-mat-icon-name]': '_svgName || fontIcon',
|
---|
339 | '[attr.data-mat-icon-namespace]': '_svgNamespace || fontSet',
|
---|
340 | '[class.mat-icon-inline]': 'inline',
|
---|
341 | '[class.mat-icon-no-color]': 'color !== "primary" && color !== "accent" && color !== "warn"',
|
---|
342 | },
|
---|
343 | encapsulation: ViewEncapsulation.None,
|
---|
344 | changeDetection: ChangeDetectionStrategy.OnPush,
|
---|
345 | styles: [".mat-icon{background-repeat:no-repeat;display:inline-block;fill:currentColor;height:24px;width:24px}.mat-icon.mat-icon-inline{font-size:inherit;height:inherit;line-height:inherit;width:inherit}[dir=rtl] .mat-icon-rtl-mirror{transform:scale(-1, 1)}.mat-form-field:not(.mat-form-field-appearance-legacy) .mat-form-field-prefix .mat-icon,.mat-form-field:not(.mat-form-field-appearance-legacy) .mat-form-field-suffix .mat-icon{display:block}.mat-form-field:not(.mat-form-field-appearance-legacy) .mat-form-field-prefix .mat-icon-button .mat-icon,.mat-form-field:not(.mat-form-field-appearance-legacy) .mat-form-field-suffix .mat-icon-button .mat-icon{margin:auto}\n"]
|
---|
346 | },] }
|
---|
347 | ];
|
---|
348 | MatIcon.ctorParameters = () => [
|
---|
349 | { type: ElementRef },
|
---|
350 | { type: MatIconRegistry },
|
---|
351 | { type: String, decorators: [{ type: Attribute, args: ['aria-hidden',] }] },
|
---|
352 | { type: undefined, decorators: [{ type: Inject, args: [MAT_ICON_LOCATION,] }] },
|
---|
353 | { type: ErrorHandler }
|
---|
354 | ];
|
---|
355 | MatIcon.propDecorators = {
|
---|
356 | inline: [{ type: Input }],
|
---|
357 | svgIcon: [{ type: Input }],
|
---|
358 | fontSet: [{ type: Input }],
|
---|
359 | fontIcon: [{ type: Input }]
|
---|
360 | };
|
---|
361 | export { ɵ0 };
|
---|
362 | //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaWNvbi5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uLy4uL3NyYy9tYXRlcmlhbC9pY29uL2ljb24udHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7Ozs7OztHQU1HO0FBRUgsT0FBTyxFQUFlLHFCQUFxQixFQUFDLE1BQU0sdUJBQXVCLENBQUM7QUFDMUUsT0FBTyxFQUFDLFFBQVEsRUFBQyxNQUFNLGlCQUFpQixDQUFDO0FBQ3pDLE9BQU8sRUFFTCxTQUFTLEVBQ1QsdUJBQXVCLEVBQ3ZCLFNBQVMsRUFDVCxVQUFVLEVBQ1YsWUFBWSxFQUNaLE1BQU0sRUFDTixNQUFNLEVBQ04sY0FBYyxFQUNkLEtBQUssRUFHTCxpQkFBaUIsR0FDbEIsTUFBTSxlQUFlLENBQUM7QUFDdkIsT0FBTyxFQUFXLFVBQVUsRUFBQyxNQUFNLHdCQUF3QixDQUFDO0FBQzVELE9BQU8sRUFBQyxZQUFZLEVBQUMsTUFBTSxNQUFNLENBQUM7QUFDbEMsT0FBTyxFQUFDLElBQUksRUFBQyxNQUFNLGdCQUFnQixDQUFDO0FBRXBDLE9BQU8sRUFBQyxlQUFlLEVBQUMsTUFBTSxpQkFBaUIsQ0FBQztBQUdoRCw4Q0FBOEM7QUFDOUMsb0JBQW9CO0FBQ3BCLE1BQU0sWUFBWSxHQUFHLFVBQVUsQ0FBQztJQUM5QixZQUFtQixXQUF1QjtRQUF2QixnQkFBVyxHQUFYLFdBQVcsQ0FBWTtJQUFHLENBQUM7Q0FDL0MsQ0FBQyxDQUFDO0FBRUg7Ozs7R0FJRztBQUNILE1BQU0sQ0FBQyxNQUFNLGlCQUFpQixHQUFHLElBQUksY0FBYyxDQUFrQixtQkFBbUIsRUFBRTtJQUN4RixVQUFVLEVBQUUsTUFBTTtJQUNsQixPQUFPLEVBQUUseUJBQXlCO0NBQ25DLENBQUMsQ0FBQztBQVVILG9CQUFvQjtBQUNwQixNQUFNLFVBQVUseUJBQXlCO0lBQ3ZDLE1BQU0sU0FBUyxHQUFHLE1BQU0sQ0FBQyxRQUFRLENBQUMsQ0FBQztJQUNuQyxNQUFNLFNBQVMsR0FBRyxTQUFTLENBQUMsQ0FBQyxDQUFDLFNBQVMsQ0FBQyxRQUFRLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQztJQUV4RCxPQUFPO1FBQ0wsaUZBQWlGO1FBQ2pGLHdFQUF3RTtRQUN4RSxXQUFXLEVBQUUsR0FBRyxFQUFFLENBQUMsU0FBUyxDQUFDLENBQUMsQ0FBQyxDQUFDLFNBQVMsQ0FBQyxRQUFRLEdBQUcsU0FBUyxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFO0tBQzVFLENBQUM7QUFDSixDQUFDO0FBR0Qsc0VBQXNFO0FBQ3RFLE1BQU0saUJBQWlCLEdBQUc7SUFDeEIsV0FBVztJQUNYLGVBQWU7SUFDZixLQUFLO0lBQ0wsUUFBUTtJQUNSLE1BQU07SUFDTixRQUFRO0lBQ1IsUUFBUTtJQUNSLGNBQWM7SUFDZCxZQUFZO0lBQ1osWUFBWTtJQUNaLE1BQU07SUFDTixRQUFRO0NBQ1QsQ0FBQztXQUdxRCxJQUFJLENBQUMsRUFBRSxDQUFDLElBQUksSUFBSSxHQUFHO0FBRDFFLGlGQUFpRjtBQUNqRixNQUFNLHdCQUF3QixHQUFHLGlCQUFpQixDQUFDLEdBQUcsSUFBcUIsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUM7QUFFdkYsaUVBQWlFO0FBQ2pFLE1BQU0sY0FBYyxHQUFHLDJCQUEyQixDQUFDO0FBRW5EOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztHQTBCRztBQW1CSCxNQUFNLE9BQU8sT0FBUSxTQUFRLFlBQVk7SUFzRXZDLFlBQ0ksVUFBbUMsRUFBVSxhQUE4QixFQUNqRCxVQUFrQixFQUNULFNBQTBCLEVBQzVDLGFBQTJCO1FBQzlDLEtBQUssQ0FBQyxVQUFVLENBQUMsQ0FBQztRQUo2QixrQkFBYSxHQUFiLGFBQWEsQ0FBaUI7UUFFeEMsY0FBUyxHQUFULFNBQVMsQ0FBaUI7UUFDNUMsa0JBQWEsR0FBYixhQUFhLENBQWM7UUE5RHhDLFlBQU8sR0FBWSxLQUFLLENBQUM7UUF1RGpDLGdFQUFnRTtRQUN4RCxzQkFBaUIsR0FBRyxZQUFZLENBQUMsS0FBSyxDQUFDO1FBUzdDLHNGQUFzRjtRQUN0Riw0REFBNEQ7UUFDNUQsSUFBSSxDQUFDLFVBQVUsRUFBRTtZQUNmLFVBQVUsQ0FBQyxhQUFhLENBQUMsWUFBWSxDQUFDLGFBQWEsRUFBRSxNQUFNLENBQUMsQ0FBQztTQUM5RDtJQUNILENBQUM7SUFqRkQ7OztPQUdHO0lBQ0gsSUFDSSxNQUFNO1FBQ1IsT0FBTyxJQUFJLENBQUMsT0FBTyxDQUFDO0lBQ3RCLENBQUM7SUFDRCxJQUFJLE1BQU0sQ0FBQyxNQUFlO1FBQ3hCLElBQUksQ0FBQyxPQUFPLEdBQUcscUJBQXFCLENBQUMsTUFBTSxDQUFDLENBQUM7SUFDL0MsQ0FBQztJQUdELDRDQUE0QztJQUM1QyxJQUNJLE9BQU8sS0FBYSxPQUFPLElBQUksQ0FBQyxRQUFRLENBQUMsQ0FBQyxDQUFDO0lBQy9DLElBQUksT0FBTyxDQUFDLEtBQWE7UUFDdkIsSUFBSSxLQUFLLEtBQUssSUFBSSxDQUFDLFFBQVEsRUFBRTtZQUMzQixJQUFJLEtBQUssRUFBRTtnQkFDVCxJQUFJLENBQUMsY0FBYyxDQUFDLEtBQUssQ0FBQyxDQUFDO2FBQzVCO2lCQUFNLElBQUksSUFBSSxDQUFDLFFBQVEsRUFBRTtnQkFDeEIsSUFBSSxDQUFDLGdCQUFnQixFQUFFLENBQUM7YUFDekI7WUFDRCxJQUFJLENBQUMsUUFBUSxHQUFHLEtBQUssQ0FBQztTQUN2QjtJQUNILENBQUM7SUFHRCwyQ0FBMkM7SUFDM0MsSUFDSSxPQUFPLEtBQWEsT0FBTyxJQUFJLENBQUMsUUFBUSxDQUFDLENBQUMsQ0FBQztJQUMvQyxJQUFJLE9BQU8sQ0FBQyxLQUFhO1FBQ3ZCLE1BQU0sUUFBUSxHQUFHLElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxLQUFLLENBQUMsQ0FBQztRQUUvQyxJQUFJLFFBQVEsS0FBSyxJQUFJLENBQUMsUUFBUSxFQUFFO1lBQzlCLElBQUksQ0FBQyxRQUFRLEdBQUcsUUFBUSxDQUFDO1lBQ3pCLElBQUksQ0FBQyxzQkFBc0IsRUFBRSxDQUFDO1NBQy9CO0lBQ0gsQ0FBQztJQUdELHlDQUF5QztJQUN6QyxJQUNJLFFBQVEsS0FBYSxPQUFPLElBQUksQ0FBQyxTQUFTLENBQUMsQ0FBQyxDQUFDO0lBQ2pELElBQUksUUFBUSxDQUFDLEtBQWE7UUFDeEIsTUFBTSxRQUFRLEdBQUcsSUFBSSxDQUFDLGlCQUFpQixDQUFDLEtBQUssQ0FBQyxDQUFDO1FBRS9DLElBQUksUUFBUSxLQUFLLElBQUksQ0FBQyxTQUFTLEVBQUU7WUFDL0IsSUFBSSxDQUFDLFNBQVMsR0FBRyxRQUFRLENBQUM7WUFDMUIsSUFBSSxDQUFDLHNCQUFzQixFQUFFLENBQUM7U0FDL0I7SUFDSCxDQUFDO0lBZ0NEOzs7Ozs7Ozs7Ozs7T0FZRztJQUNLLGNBQWMsQ0FBQyxRQUFnQjtRQUNyQyxJQUFJLENBQUMsUUFBUSxFQUFFO1lBQ2IsT0FBTyxDQUFDLEVBQUUsRUFBRSxFQUFFLENBQUMsQ0FBQztTQUNqQjtRQUNELE1BQU0sS0FBSyxHQUFHLFFBQVEsQ0FBQyxLQUFLLENBQUMsR0FBRyxDQUFDLENBQUM7UUFDbEMsUUFBUSxLQUFLLENBQUMsTUFBTSxFQUFFO1lBQ3BCLEtBQUssQ0FBQyxDQUFDLENBQUMsT0FBTyxDQUFDLEVBQUUsRUFBRSxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLHlCQUF5QjtZQUN4RCxLQUFLLENBQUMsQ0FBQyxDQUFDLE9BQXlCLEtBQUssQ0FBQztZQUN2QyxPQUFPLENBQUMsQ0FBQyxNQUFNLEtBQUssQ0FBQyx1QkFBdUIsUUFBUSxHQUFHLENBQUMsQ0FBQyxDQUFDLCtCQUErQjtTQUMxRjtJQUNILENBQUM7SUFFRCxRQUFRO1FBQ04sNkZBQTZGO1FBQzdGLGdHQUFnRztRQUNoRyxJQUFJLENBQUMsc0JBQXNCLEVBQUUsQ0FBQztJQUNoQyxDQUFDO0lBRUQsa0JBQWtCO1FBQ2hCLE1BQU0sY0FBYyxHQUFHLElBQUksQ0FBQywrQkFBK0IsQ0FBQztRQUU1RCxJQUFJLGNBQWMsSUFBSSxjQUFjLENBQUMsSUFBSSxFQUFFO1lBQ3pDLE1BQU0sT0FBTyxHQUFHLElBQUksQ0FBQyxTQUFTLENBQUMsV0FBVyxFQUFFLENBQUM7WUFFN0MsOEVBQThFO1lBQzlFLDRFQUE0RTtZQUM1RSw0RUFBNEU7WUFDNUUsMEVBQTBFO1lBQzFFLDJFQUEyRTtZQUMzRSxzQ0FBc0M7WUFDdEMsSUFBSSxPQUFPLEtBQUssSUFBSSxDQUFDLGFBQWEsRUFBRTtnQkFDbEMsSUFBSSxDQUFDLGFBQWEsR0FBRyxPQUFPLENBQUM7Z0JBQzdCLElBQUksQ0FBQyx3QkFBd0IsQ0FBQyxPQUFPLENBQUMsQ0FBQzthQUN4QztTQUNGO0lBQ0gsQ0FBQztJQUVELFdBQVc7UUFDVCxJQUFJLENBQUMsaUJBQWlCLENBQUMsV0FBVyxFQUFFLENBQUM7UUFFckMsSUFBSSxJQUFJLENBQUMsK0JBQStCLEVBQUU7WUFDeEMsSUFBSSxDQUFDLCtCQUErQixDQUFDLEtBQUssRUFBRSxDQUFDO1NBQzlDO0lBQ0gsQ0FBQztJQUVELGNBQWM7UUFDWixPQUFPLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQztJQUN2QixDQUFDO0lBRU8sY0FBYyxDQUFDLEdBQWU7UUFDcEMsSUFBSSxDQUFDLGdCQUFnQixFQUFFLENBQUM7UUFFeEIsc0ZBQXNGO1FBQ3RGLHNGQUFzRjtRQUN0Riw4RkFBOEY7UUFDOUYsTUFBTSxTQUFTLEdBQUcsR0FBRyxDQUFDLGdCQUFnQixDQUFDLE9BQU8sQ0FBaUMsQ0FBQztRQUVoRixLQUFLLElBQUksQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLEdBQUcsU0FBUyxDQUFDLE1BQU0sRUFBRSxDQUFDLEVBQUUsRUFBRTtZQUN6QyxTQUFTLENBQUMsQ0FBQyxDQUFDLENBQUMsV0FBVyxJQUFJLEdBQUcsQ0FBQztTQUNqQztRQUVELHdFQUF3RTtRQUN4RSw2RUFBNkU7UUFDN0UsTUFBTSxJQUFJLEdBQUcsSUFBSSxDQUFDLFNBQVMsQ0FBQyxXQUFXLEVBQUUsQ0FBQztRQUMxQyxJQUFJLENBQUMsYUFBYSxHQUFHLElBQUksQ0FBQztRQUMxQixJQUFJLENBQUMsb0NBQW9DLENBQUMsR0FBRyxDQUFDLENBQUM7UUFDL0MsSUFBSSxDQUFDLHdCQUF3QixDQUFDLElBQUksQ0FBQyxDQUFDO1FBQ3BDLElBQUksQ0FBQyxXQUFXLENBQUMsYUFBYSxDQUFDLFdBQVcsQ0FBQyxHQUFHLENBQUMsQ0FBQztJQUNsRCxDQUFDO0lBRU8sZ0JBQWdCO1FBQ3RCLE1BQU0sYUFBYSxHQUFnQixJQUFJLENBQUMsV0FBVyxDQUFDLGFBQWEsQ0FBQztRQUNsRSxJQUFJLFVBQVUsR0FBRyxhQUFhLENBQUMsVUFBVSxDQUFDLE1BQU0sQ0FBQztRQUVqRCxJQUFJLElBQUksQ0FBQywrQkFBK0IsRUFBRTtZQUN4QyxJQUFJLENBQUMsK0JBQStCLENBQUMsS0FBSyxFQUFFLENBQUM7U0FDOUM7UUFFRCwyRkFBMkY7UUFDM0YsbUZBQW1GO1FBQ25GLE9BQU8sVUFBVSxFQUFFLEVBQUU7WUFDbkIsTUFBTSxLQUFLLEdBQUcsYUFBYSxDQUFDLFVBQVUsQ0FBQyxVQUFVLENBQUMsQ0FBQztZQUVuRCwwRkFBMEY7WUFDMUYseUZBQXlGO1lBQ3pGLElBQUksS0FBSyxDQUFDLFFBQVEsS0FBSyxDQUFDLElBQUksS0FBSyxDQUFDLFFBQVEsQ0FBQyxXQUFXLEVBQUUsS0FBSyxLQUFLLEVBQUU7Z0JBQ2xFLGFBQWEsQ0FBQyxXQUFXLENBQUMsS0FBSyxDQUFDLENBQUM7YUFDbEM7U0FDRjtJQUNILENBQUM7SUFFTyxzQkFBc0I7UUFDNUIsSUFBSSxDQUFDLElBQUksQ0FBQyxjQUFjLEVBQUUsRUFBRTtZQUMxQixPQUFPO1NBQ1I7UUFFRCxNQUFNLElBQUksR0FBZ0IsSUFBSSxDQUFDLFdBQVcsQ0FBQyxhQUFhLENBQUM7UUFDekQsTUFBTSxZQUFZLEdBQUcsSUFBSSxDQUFDLE9BQU8sQ0FBQyxDQUFDO1lBQy9CLElBQUksQ0FBQyxhQUFhLENBQUMscUJBQXFCLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUM7WUFDeEQsSUFBSSxDQUFDLGFBQWEsQ0FBQyxzQkFBc0IsRUFBRSxDQUFDO1FBRWhELElBQUksWUFBWSxJQUFJLElBQUksQ0FBQyxxQkFBcUIsRUFBRTtZQUM5QyxJQUFJLElBQUksQ0FBQyxxQkFBcUIsRUFBRTtnQkFDOUIsSUFBSSxDQUFDLFNBQVMsQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLHFCQUFxQixDQUFDLENBQUM7YUFDbkQ7WUFDRCxJQUFJLFlBQVksRUFBRTtnQkFDaEIsSUFBSSxDQUFDLFNBQVMsQ0FBQyxHQUFHLENBQUMsWUFBWSxDQUFDLENBQUM7YUFDbEM7WUFDRCxJQUFJLENBQUMscUJBQXFCLEdBQUcsWUFBWSxDQUFDO1NBQzNDO1FBRUQsSUFBSSxJQUFJLENBQUMsUUFBUSxJQUFJLElBQUksQ0FBQyxzQkFBc0IsRUFBRTtZQUNoRCxJQUFJLElBQUksQ0FBQyxzQkFBc0IsRUFBRTtnQkFDL0IsSUFBSSxDQUFDLFNBQVMsQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLHNCQUFzQixDQUFDLENBQUM7YUFDcEQ7WUFDRCxJQUFJLElBQUksQ0FBQyxRQUFRLEVBQUU7Z0JBQ2pCLElBQUksQ0FBQyxTQUFTLENBQUMsR0FBRyxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsQ0FBQzthQUNuQztZQUNELElBQUksQ0FBQyxzQkFBc0IsR0FBRyxJQUFJLENBQUMsUUFBUSxDQUFDO1NBQzdDO0lBQ0gsQ0FBQztJQUVEOzs7O09BSUc7SUFDSyxpQkFBaUIsQ0FBQyxLQUFhO1FBQ3JDLE9BQU8sT0FBTyxLQUFLLEtBQUssUUFBUSxDQUFDLENBQUMsQ0FBQyxLQUFLLENBQUMsSUFBSSxFQUFFLENBQUMsS0FBSyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxLQUFLLENBQUM7SUFDeEUsQ0FBQztJQUVEOzs7O09BSUc7SUFDSyx3QkFBd0IsQ0FBQyxJQUFZO1FBQzNDLE1BQU0sUUFBUSxHQUFHLElBQUksQ0FBQywrQkFBK0IsQ0FBQztRQUV0RCxJQUFJLFFBQVEsRUFBRTtZQUNaLFFBQVEsQ0FBQyxPQUFPLENBQUMsQ0FBQyxLQUFLLEVBQUUsT0FBTyxFQUFFLEVBQUU7Z0JBQ2xDLEtBQUssQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDLEVBQUU7b0JBQ25CLE9BQU8sQ0FBQyxZQUFZLENBQUMsSUFBSSxDQUFDLElBQUksRUFBRSxRQUFRLElBQUksSUFBSSxJQUFJLENBQUMsS0FBSyxJQUFJLENBQUMsQ0FBQztnQkFDbEUsQ0FBQyxDQUFDLENBQUM7WUFDTCxDQUFDLENBQUMsQ0FBQztTQUNKO0lBQ0gsQ0FBQztJQUVEOzs7T0FHRztJQUNLLG9DQUFvQyxDQUFDLE9BQW1CO1FBQzlELE1BQU0sbUJBQW1CLEdBQUcsT0FBTyxDQUFDLGdCQUFnQixDQUFDLHdCQUF3QixDQUFDLENBQUM7UUFDL0UsTUFBTSxRQUFRLEdBQUcsSUFBSSxDQUFDLCtCQUErQjtZQUNqRCxJQUFJLENBQUMsK0JBQStCLElBQUksSUFBSSxHQUFHLEVBQUUsQ0FBQztRQUV0RCxLQUFLLElBQUksQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLEdBQUcsbUJBQW1CLENBQUMsTUFBTSxFQUFFLENBQUMsRUFBRSxFQUFFO1lBQ25ELGlCQUFpQixDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsRUFBRTtnQkFDL0IsTUFBTSxvQkFBb0IsR0FBRyxtQkFBbUIsQ0FBQyxDQUFDLENBQUMsQ0FBQztnQkFDcEQsTUFBTSxLQUFLLEdBQUcsb0JBQW9CLENBQUMsWUFBWSxDQUFDLElBQUksQ0FBQyxDQUFDO2dCQUN0RCxNQUFNLEtBQUssR0FBRyxLQUFLLENBQUMsQ0FBQyxDQUFDLEtBQUssQ0FBQyxLQUFLLENBQUMsY0FBYyxDQUFDLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQztnQkFFekQsSUFBSSxLQUFLLEVBQUU7b0JBQ1QsSUFBSSxVQUFVLEdBQUcsUUFBUSxDQUFDLEdBQUcsQ0FBQyxvQkFBb0IsQ0FBQyxDQUFDO29CQUVwRCxJQUFJLENBQUMsVUFBVSxFQUFFO3dCQUNmLFVBQVUsR0FBRyxFQUFFLENBQUM7d0JBQ2hCLFFBQVEsQ0FBQyxHQUFHLENBQUMsb0JBQW9CLEVBQUUsVUFBVSxDQUFDLENBQUM7cUJBQ2hEO29CQUVELFVBQVcsQ0FBQyxJQUFJLENBQUMsRUFBQyxJQUFJLEVBQUUsSUFBSSxFQUFFLEtBQUssRUFBRSxLQUFLLENBQUMsQ0FBQyxDQUFDLEVBQUMsQ0FBQyxDQUFDO2lCQUNqRDtZQUNILENBQUMsQ0FBQyxDQUFDO1NBQ0o7SUFDSCxDQUFDO0lBRUQsa0RBQWtEO0lBQzFDLGNBQWMsQ0FBQyxPQUF5QjtRQUM5QyxJQUFJLENBQUMsYUFBYSxHQUFHLElBQUksQ0FBQztRQUMxQixJQUFJLENBQUMsUUFBUSxHQUFHLElBQUksQ0FBQztRQUNyQixJQUFJLENBQUMsaUJBQWlCLENBQUMsV0FBVyxFQUFFLENBQUM7UUFFckMsSUFBSSxPQUFPLEVBQUU7WUFDWCxNQUFNLENBQUMsU0FBUyxFQUFFLFFBQVEsQ0FBQyxHQUFHLElBQUksQ0FBQyxjQUFjLENBQUMsT0FBTyxDQUFDLENBQUM7WUFFM0QsSUFBSSxTQUFTLEVBQUU7Z0JBQ2IsSUFBSSxDQUFDLGFBQWEsR0FBRyxTQUFTLENBQUM7YUFDaEM7WUFFRCxJQUFJLFFBQVEsRUFBRTtnQkFDWixJQUFJLENBQUMsUUFBUSxHQUFHLFFBQVEsQ0FBQzthQUMxQjtZQUVELElBQUksQ0FBQyxpQkFBaUIsR0FBRyxJQUFJLENBQUMsYUFBYSxDQUFDLGVBQWUsQ0FBQyxRQUFRLEVBQUUsU0FBUyxDQUFDO2lCQUMzRSxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDO2lCQUNiLFNBQVMsQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLElBQUksQ0FBQyxjQUFjLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxHQUFVLEVBQUUsRUFBRTtnQkFDekQsTUFBTSxZQUFZLEdBQUcseUJBQXlCLFNBQVMsSUFBSSxRQUFRLEtBQUssR0FBRyxDQUFDLE9BQU8sRUFBRSxDQUFDO2dCQUN0RixJQUFJLENBQUMsYUFBYSxDQUFDLFdBQVcsQ0FBQyxJQUFJLEtBQUssQ0FBQyxZQUFZLENBQUMsQ0FBQyxDQUFDO1lBQzFELENBQUMsQ0FBQyxDQUFDO1NBQ1I7SUFDSCxDQUFDOzs7WUE1VEYsU0FBUyxTQUFDO2dCQUNULFFBQVEsRUFBRSwyQkFBMkI7Z0JBQ3JDLFFBQVEsRUFBRSxVQUFVO2dCQUNwQixRQUFRLEVBQUUsU0FBUztnQkFFbkIsTUFBTSxFQUFFLENBQUMsT0FBTyxDQUFDO2dCQUNqQixJQUFJLEVBQUU7b0JBQ0osTUFBTSxFQUFFLEtBQUs7b0JBQ2IsT0FBTyxFQUFFLHNCQUFzQjtvQkFDL0IsMkJBQTJCLEVBQUUsbUNBQW1DO29CQUNoRSwyQkFBMkIsRUFBRSxzQkFBc0I7b0JBQ25ELGdDQUFnQyxFQUFFLDBCQUEwQjtvQkFDNUQseUJBQXlCLEVBQUUsUUFBUTtvQkFDbkMsMkJBQTJCLEVBQUUsK0RBQStEO2lCQUM3RjtnQkFDRCxhQUFhLEVBQUUsaUJBQWlCLENBQUMsSUFBSTtnQkFDckMsZUFBZSxFQUFFLHVCQUF1QixDQUFDLE1BQU07O2FBQ2hEOzs7WUF4SEMsVUFBVTtZQWNKLGVBQWU7eUNBbUxoQixTQUFTLFNBQUMsYUFBYTs0Q0FDdkIsTUFBTSxTQUFDLGlCQUFpQjtZQWpNN0IsWUFBWTs7O3FCQTZIWCxLQUFLO3NCQVVMLEtBQUs7c0JBZUwsS0FBSzt1QkFhTCxLQUFLIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBAbGljZW5zZVxuICogQ29weXJpZ2h0IEdvb2dsZSBMTEMgQWxsIFJpZ2h0cyBSZXNlcnZlZC5cbiAqXG4gKiBVc2Ugb2YgdGhpcyBzb3VyY2UgY29kZSBpcyBnb3Zlcm5lZCBieSBhbiBNSVQtc3R5bGUgbGljZW5zZSB0aGF0IGNhbiBiZVxuICogZm91bmQgaW4gdGhlIExJQ0VOU0UgZmlsZSBhdCBodHRwczovL2FuZ3VsYXIuaW8vbGljZW5zZVxuICovXG5cbmltcG9ydCB7Qm9vbGVhbklucHV0LCBjb2VyY2VCb29sZWFuUHJvcGVydHl9IGZyb20gJ0Bhbmd1bGFyL2Nkay9jb2VyY2lvbic7XG5pbXBvcnQge0RPQ1VNRU5UfSBmcm9tICdAYW5ndWxhci9jb21tb24nO1xuaW1wb3J0IHtcbiAgQWZ0ZXJWaWV3Q2hlY2tlZCxcbiAgQXR0cmlidXRlLFxuICBDaGFuZ2VEZXRlY3Rpb25TdHJhdGVneSxcbiAgQ29tcG9uZW50LFxuICBFbGVtZW50UmVmLFxuICBFcnJvckhhbmRsZXIsXG4gIGluamVjdCxcbiAgSW5qZWN0LFxuICBJbmplY3Rpb25Ub2tlbixcbiAgSW5wdXQsXG4gIE9uRGVzdHJveSxcbiAgT25Jbml0LFxuICBWaWV3RW5jYXBzdWxhdGlvbixcbn0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQge0NhbkNvbG9yLCBtaXhpbkNvbG9yfSBmcm9tICdAYW5ndWxhci9tYXRlcmlhbC9jb3JlJztcbmltcG9ydCB7U3Vic2NyaXB0aW9ufSBmcm9tICdyeGpzJztcbmltcG9ydCB7dGFrZX0gZnJvbSAncnhqcy9vcGVyYXRvcnMnO1xuXG5pbXBvcnQge01hdEljb25SZWdpc3RyeX0gZnJvbSAnLi9pY29uLXJlZ2lzdHJ5JztcblxuXG4vLyBCb2lsZXJwbGF0ZSBmb3IgYXBwbHlpbmcgbWl4aW5zIHRvIE1hdEljb24uXG4vKiogQGRvY3MtcHJpdmF0ZSAqL1xuY29uc3QgX01hdEljb25CYXNlID0gbWl4aW5Db2xvcihjbGFzcyB7XG4gIGNvbnN0cnVjdG9yKHB1YmxpYyBfZWxlbWVudFJlZjogRWxlbWVudFJlZikge31cbn0pO1xuXG4vKipcbiAqIEluamVjdGlvbiB0b2tlbiB1c2VkIHRvIHByb3ZpZGUgdGhlIGN1cnJlbnQgbG9jYXRpb24gdG8gYE1hdEljb25gLlxuICogVXNlZCB0byBoYW5kbGUgc2VydmVyLXNpZGUgcmVuZGVyaW5nIGFuZCB0byBzdHViIG91dCBkdXJpbmcgdW5pdCB0ZXN0cy5cbiAqIEBkb2NzLXByaXZhdGVcbiAqL1xuZXhwb3J0IGNvbnN0IE1BVF9JQ09OX0xPQ0FUSU9OID0gbmV3IEluamVjdGlvblRva2VuPE1hdEljb25Mb2NhdGlvbj4oJ21hdC1pY29uLWxvY2F0aW9uJywge1xuICBwcm92aWRlZEluOiAncm9vdCcsXG4gIGZhY3Rvcnk6IE1BVF9JQ09OX0xPQ0FUSU9OX0ZBQ1RPUllcbn0pO1xuXG4vKipcbiAqIFN0dWJiZWQgb3V0IGxvY2F0aW9uIGZvciBgTWF0SWNvbmAuXG4gKiBAZG9jcy1wcml2YXRlXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgTWF0SWNvbkxvY2F0aW9uIHtcbiAgZ2V0UGF0aG5hbWU6ICgpID0+IHN0cmluZztcbn1cblxuLyoqIEBkb2NzLXByaXZhdGUgKi9cbmV4cG9ydCBmdW5jdGlvbiBNQVRfSUNPTl9MT0NBVElPTl9GQUNUT1JZKCk6IE1hdEljb25Mb2NhdGlvbiB7XG4gIGNvbnN0IF9kb2N1bWVudCA9IGluamVjdChET0NVTUVOVCk7XG4gIGNvbnN0IF9sb2NhdGlvbiA9IF9kb2N1bWVudCA/IF9kb2N1bWVudC5sb2NhdGlvbiA6IG51bGw7XG5cbiAgcmV0dXJuIHtcbiAgICAvLyBOb3RlIHRoYXQgdGhpcyBuZWVkcyB0byBiZSBhIGZ1bmN0aW9uLCByYXRoZXIgdGhhbiBhIHByb3BlcnR5LCBiZWNhdXNlIEFuZ3VsYXJcbiAgICAvLyB3aWxsIG9ubHkgcmVzb2x2ZSBpdCBvbmNlLCBidXQgd2Ugd2FudCB0aGUgY3VycmVudCBwYXRoIG9uIGVhY2ggY2FsbC5cbiAgICBnZXRQYXRobmFtZTogKCkgPT4gX2xvY2F0aW9uID8gKF9sb2NhdGlvbi5wYXRobmFtZSArIF9sb2NhdGlvbi5zZWFyY2gpIDogJydcbiAgfTtcbn1cblxuXG4vKiogU1ZHIGF0dHJpYnV0ZXMgdGhhdCBhY2NlcHQgYSBGdW5jSVJJIChlLmcuIGB1cmwoPHNvbWV0aGluZz4pYCkuICovXG5jb25zdCBmdW5jSXJpQXR0cmlidXRlcyA9IFtcbiAgJ2NsaXAtcGF0aCcsXG4gICdjb2xvci1wcm9maWxlJyxcbiAgJ3NyYycsXG4gICdjdXJzb3InLFxuICAnZmlsbCcsXG4gICdmaWx0ZXInLFxuICAnbWFya2VyJyxcbiAgJ21hcmtlci1zdGFydCcsXG4gICdtYXJrZXItbWlkJyxcbiAgJ21hcmtlci1lbmQnLFxuICAnbWFzaycsXG4gICdzdHJva2UnXG5dO1xuXG4vKiogU2VsZWN0b3IgdGhhdCBjYW4gYmUgdXNlZCB0byBmaW5kIGFsbCBlbGVtZW50cyB0aGF0IGFyZSB1c2luZyBhIGBGdW5jSVJJYC4gKi9cbmNvbnN0IGZ1bmNJcmlBdHRyaWJ1dGVTZWxlY3RvciA9IGZ1bmNJcmlBdHRyaWJ1dGVzLm1hcChhdHRyID0+IGBbJHthdHRyfV1gKS5qb2luKCcsICcpO1xuXG4vKiogUmVnZXggdGhhdCBjYW4gYmUgdXNlZCB0byBleHRyYWN0IHRoZSBpZCBvdXQgb2YgYSBGdW5jSVJJLiAqL1xuY29uc3QgZnVuY0lyaVBhdHRlcm4gPSAvXnVybFxcKFsnXCJdPyMoLio/KVsnXCJdP1xcKSQvO1xuXG4vKipcbiAqIENvbXBvbmVudCB0byBkaXNwbGF5IGFuIGljb24uIEl0IGNhbiBiZSB1c2VkIGluIHRoZSBmb2xsb3dpbmcgd2F5czpcbiAqXG4gKiAtIFNwZWNpZnkgdGhlIHN2Z0ljb24gaW5wdXQgdG8gbG9hZCBhbiBTVkcgaWNvbiBmcm9tIGEgVVJMIHByZXZpb3VzbHkgcmVnaXN0ZXJlZCB3aXRoIHRoZVxuICogICBhZGRTdmdJY29uLCBhZGRTdmdJY29uSW5OYW1lc3BhY2UsIGFkZFN2Z0ljb25TZXQsIG9yIGFkZFN2Z0ljb25TZXRJbk5hbWVzcGFjZSBtZXRob2RzIG9mXG4gKiAgIE1hdEljb25SZWdpc3RyeS4gSWYgdGhlIHN2Z0ljb24gdmFsdWUgY29udGFpbnMgYSBjb2xvbiBpdCBpcyBhc3N1bWVkIHRvIGJlIGluIHRoZSBmb3JtYXRcbiAqICAgXCJbbmFtZXNwYWNlXTpbbmFtZV1cIiwgaWYgbm90IHRoZSB2YWx1ZSB3aWxsIGJlIHRoZSBuYW1lIG9mIGFuIGljb24gaW4gdGhlIGRlZmF1bHQgbmFtZXNwYWNlLlxuICogICBFeGFtcGxlczpcbiAqICAgICBgPG1hdC1pY29uIHN2Z0ljb249XCJsZWZ0LWFycm93XCI+PC9tYXQtaWNvbj5cbiAqICAgICA8bWF0LWljb24gc3ZnSWNvbj1cImFuaW1hbHM6Y2F0XCI+PC9tYXQtaWNvbj5gXG4gKlxuICogLSBVc2UgYSBmb250IGxpZ2F0dXJlIGFzIGFuIGljb24gYnkgcHV0dGluZyB0aGUgbGlnYXR1cmUgdGV4dCBpbiB0aGUgY29udGVudCBvZiB0aGUgYDxtYXQtaWNvbj5gXG4gKiAgIGNvbXBvbmVudC4gQnkgZGVmYXVsdCB0aGUgTWF0ZXJpYWwgaWNvbnMgZm9udCBpcyB1c2VkIGFzIGRlc2NyaWJlZCBhdFxuICogICBodHRwOi8vZ29vZ2xlLmdpdGh1Yi5pby9tYXRlcmlhbC1kZXNpZ24taWNvbnMvI2ljb24tZm9udC1mb3ItdGhlLXdlYi4gWW91IGNhbiBzcGVjaWZ5IGFuXG4gKiAgIGFsdGVybmF0ZSBmb250IGJ5IHNldHRpbmcgdGhlIGZvbnRTZXQgaW5wdXQgdG8gZWl0aGVyIHRoZSBDU1MgY2xhc3MgdG8gYXBwbHkgdG8gdXNlIHRoZVxuICogICBkZXNpcmVkIGZvbnQsIG9yIHRvIGFuIGFsaWFzIHByZXZpb3VzbHkgcmVnaXN0ZXJlZCB3aXRoIE1hdEljb25SZWdpc3RyeS5yZWdpc3RlckZvbnRDbGFzc0FsaWFzLlxuICogICBFeGFtcGxlczpcbiAqICAgICBgPG1hdC1pY29uPmhvbWU8L21hdC1pY29uPlxuICogICAgIDxtYXQtaWNvbiBmb250U2V0PVwibXlmb250XCI+c3VuPC9tYXQtaWNvbj5gXG4gKlxuICogLSBTcGVjaWZ5IGEgZm9udCBnbHlwaCB0byBiZSBpbmNsdWRlZCB2aWEgQ1NTIHJ1bGVzIGJ5IHNldHRpbmcgdGhlIGZvbnRTZXQgaW5wdXQgdG8gc3BlY2lmeSB0aGVcbiAqICAgZm9udCwgYW5kIHRoZSBmb250SWNvbiBpbnB1dCB0byBzcGVjaWZ5IHRoZSBpY29uLiBUeXBpY2FsbHkgdGhlIGZvbnRJY29uIHdpbGwgc3BlY2lmeSBhXG4gKiAgIENTUyBjbGFzcyB3aGljaCBjYXVzZXMgdGhlIGdseXBoIHRvIGJlIGRpc3BsYXllZCB2aWEgYSA6YmVmb3JlIHNlbGVjdG9yLCBhcyBpblxuICogICBodHRwczovL2ZvcnRhd2Vzb21lLmdpdGh1Yi5pby9Gb250LUF3ZXNvbWUvZXhhbXBsZXMvXG4gKiAgIEV4YW1wbGU6XG4gKiAgICAgYDxtYXQtaWNvbiBmb250U2V0PVwiZmFcIiBmb250SWNvbj1cImFsYXJtXCI+PC9tYXQtaWNvbj5gXG4gKi9cbkBDb21wb25lbnQoe1xuICB0ZW1wbGF0ZTogJzxuZy1jb250ZW50PjwvbmctY29udGVudD4nLFxuICBzZWxlY3RvcjogJ21hdC1pY29uJyxcbiAgZXhwb3J0QXM6ICdtYXRJY29uJyxcbiAgc3R5bGVVcmxzOiBbJ2ljb24uY3NzJ10sXG4gIGlucHV0czogWydjb2xvciddLFxuICBob3N0OiB7XG4gICAgJ3JvbGUnOiAnaW1nJyxcbiAgICAnY2xhc3MnOiAnbWF0LWljb24gbm90cmFuc2xhdGUnLFxuICAgICdbYXR0ci5kYXRhLW1hdC1pY29uLXR5cGVdJzogJ191c2luZ0ZvbnRJY29uKCkgPyBcImZvbnRcIiA6IFwic3ZnXCInLFxuICAgICdbYXR0ci5kYXRhLW1hdC1pY29uLW5hbWVdJzogJ19zdmdOYW1lIHx8IGZvbnRJY29uJyxcbiAgICAnW2F0dHIuZGF0YS1tYXQtaWNvbi1uYW1lc3BhY2VdJzogJ19zdmdOYW1lc3BhY2UgfHwgZm9udFNldCcsXG4gICAgJ1tjbGFzcy5tYXQtaWNvbi1pbmxpbmVdJzogJ2lubGluZScsXG4gICAgJ1tjbGFzcy5tYXQtaWNvbi1uby1jb2xvcl0nOiAnY29sb3IgIT09IFwicHJpbWFyeVwiICYmIGNvbG9yICE9PSBcImFjY2VudFwiICYmIGNvbG9yICE9PSBcIndhcm5cIicsXG4gIH0sXG4gIGVuY2Fwc3VsYXRpb246IFZpZXdFbmNhcHN1bGF0aW9uLk5vbmUsXG4gIGNoYW5nZURldGVjdGlvbjogQ2hhbmdlRGV0ZWN0aW9uU3RyYXRlZ3kuT25QdXNoLFxufSlcbmV4cG9ydCBjbGFzcyBNYXRJY29uIGV4dGVuZHMgX01hdEljb25CYXNlIGltcGxlbWVudHMgT25Jbml0LCBBZnRlclZpZXdDaGVja2VkLCBDYW5Db2xvciwgT25EZXN0cm95IHtcbiAgLyoqXG4gICAqIFdoZXRoZXIgdGhlIGljb24gc2hvdWxkIGJlIGlubGluZWQsIGF1dG9tYXRpY2FsbHkgc2l6aW5nIHRoZSBpY29uIHRvIG1hdGNoIHRoZSBmb250IHNpemUgb2ZcbiAgICogdGhlIGVsZW1lbnQgdGhlIGljb24gaXMgY29udGFpbmVkIGluLlxuICAgKi9cbiAgQElucHV0KClcbiAgZ2V0IGlubGluZSgpOiBib29sZWFuIHtcbiAgICByZXR1cm4gdGhpcy5faW5saW5lO1xuICB9XG4gIHNldCBpbmxpbmUoaW5saW5lOiBib29sZWFuKSB7XG4gICAgdGhpcy5faW5saW5lID0gY29lcmNlQm9vbGVhblByb3BlcnR5KGlubGluZSk7XG4gIH1cbiAgcHJpdmF0ZSBfaW5saW5lOiBib29sZWFuID0gZmFsc2U7XG5cbiAgLyoqIE5hbWUgb2YgdGhlIGljb24gaW4gdGhlIFNWRyBpY29uIHNldC4gKi9cbiAgQElucHV0KClcbiAgZ2V0IHN2Z0ljb24oKTogc3RyaW5nIHsgcmV0dXJuIHRoaXMuX3N2Z0ljb247IH1cbiAgc2V0IHN2Z0ljb24odmFsdWU6IHN0cmluZykge1xuICAgIGlmICh2YWx1ZSAhPT0gdGhpcy5fc3ZnSWNvbikge1xuICAgICAgaWYgKHZhbHVlKSB7XG4gICAgICAgIHRoaXMuX3VwZGF0ZVN2Z0ljb24odmFsdWUpO1xuICAgICAgfSBlbHNlIGlmICh0aGlzLl9zdmdJY29uKSB7XG4gICAgICAgIHRoaXMuX2NsZWFyU3ZnRWxlbWVudCgpO1xuICAgICAgfVxuICAgICAgdGhpcy5fc3ZnSWNvbiA9IHZhbHVlO1xuICAgIH1cbiAgfVxuICBwcml2YXRlIF9zdmdJY29uOiBzdHJpbmc7XG5cbiAgLyoqIEZvbnQgc2V0IHRoYXQgdGhlIGljb24gaXMgYSBwYXJ0IG9mLiAqL1xuICBASW5wdXQoKVxuICBnZXQgZm9udFNldCgpOiBzdHJpbmcgeyByZXR1cm4gdGhpcy5fZm9udFNldDsgfVxuICBzZXQgZm9udFNldCh2YWx1ZTogc3RyaW5nKSB7XG4gICAgY29uc3QgbmV3VmFsdWUgPSB0aGlzLl9jbGVhbnVwRm9udFZhbHVlKHZhbHVlKTtcblxuICAgIGlmIChuZXdWYWx1ZSAhPT0gdGhpcy5fZm9udFNldCkge1xuICAgICAgdGhpcy5fZm9udFNldCA9IG5ld1ZhbHVlO1xuICAgICAgdGhpcy5fdXBkYXRlRm9udEljb25DbGFzc2VzKCk7XG4gICAgfVxuICB9XG4gIHByaXZhdGUgX2ZvbnRTZXQ6IHN0cmluZztcblxuICAvKiogTmFtZSBvZiBhbiBpY29uIHdpdGhpbiBhIGZvbnQgc2V0LiAqL1xuICBASW5wdXQoKVxuICBnZXQgZm9udEljb24oKTogc3RyaW5nIHsgcmV0dXJuIHRoaXMuX2ZvbnRJY29uOyB9XG4gIHNldCBmb250SWNvbih2YWx1ZTogc3RyaW5nKSB7XG4gICAgY29uc3QgbmV3VmFsdWUgPSB0aGlzLl9jbGVhbnVwRm9udFZhbHVlKHZhbHVlKTtcblxuICAgIGlmIChuZXdWYWx1ZSAhPT0gdGhpcy5fZm9udEljb24pIHtcbiAgICAgIHRoaXMuX2ZvbnRJY29uID0gbmV3VmFsdWU7XG4gICAgICB0aGlzLl91cGRhdGVGb250SWNvbkNsYXNzZXMoKTtcbiAgICB9XG4gIH1cbiAgcHJpdmF0ZSBfZm9udEljb246IHN0cmluZztcblxuICBwcml2YXRlIF9wcmV2aW91c0ZvbnRTZXRDbGFzczogc3RyaW5nO1xuICBwcml2YXRlIF9wcmV2aW91c0ZvbnRJY29uQ2xhc3M6IHN0cmluZztcblxuICBfc3ZnTmFtZTogc3RyaW5nIHwgbnVsbDtcbiAgX3N2Z05hbWVzcGFjZTogc3RyaW5nIHwgbnVsbDtcblxuICAvKiogS2VlcHMgdHJhY2sgb2YgdGhlIGN1cnJlbnQgcGFnZSBwYXRoLiAqL1xuICBwcml2YXRlIF9wcmV2aW91c1BhdGg/OiBzdHJpbmc7XG5cbiAgLyoqIEtlZXBzIHRyYWNrIG9mIHRoZSBlbGVtZW50cyBhbmQgYXR0cmlidXRlcyB0aGF0IHdlJ3ZlIHByZWZpeGVkIHdpdGggdGhlIGN1cnJlbnQgcGF0aC4gKi9cbiAgcHJpdmF0ZSBfZWxlbWVudHNXaXRoRXh0ZXJuYWxSZWZlcmVuY2VzPzogTWFwPEVsZW1lbnQsIHtuYW1lOiBzdHJpbmcsIHZhbHVlOiBzdHJpbmd9W10+O1xuXG4gIC8qKiBTdWJzY3JpcHRpb24gdG8gdGhlIGN1cnJlbnQgaW4tcHJvZ3Jlc3MgU1ZHIGljb24gcmVxdWVzdC4gKi9cbiAgcHJpdmF0ZSBfY3VycmVudEljb25GZXRjaCA9IFN1YnNjcmlwdGlvbi5FTVBUWTtcblxuICBjb25zdHJ1Y3RvcihcbiAgICAgIGVsZW1lbnRSZWY6IEVsZW1lbnRSZWY8SFRNTEVsZW1lbnQ+LCBwcml2YXRlIF9pY29uUmVnaXN0cnk6IE1hdEljb25SZWdpc3RyeSxcbiAgICAgIEBBdHRyaWJ1dGUoJ2FyaWEtaGlkZGVuJykgYXJpYUhpZGRlbjogc3RyaW5nLFxuICAgICAgQEluamVjdChNQVRfSUNPTl9MT0NBVElPTikgcHJpdmF0ZSBfbG9jYXRpb246IE1hdEljb25Mb2NhdGlvbixcbiAgICAgIHByaXZhdGUgcmVhZG9ubHkgX2Vycm9ySGFuZGxlcjogRXJyb3JIYW5kbGVyKSB7XG4gICAgc3VwZXIoZWxlbWVudFJlZik7XG5cbiAgICAvLyBJZiB0aGUgdXNlciBoYXMgbm90IGV4cGxpY2l0bHkgc2V0IGFyaWEtaGlkZGVuLCBtYXJrIHRoZSBpY29uIGFzIGhpZGRlbiwgYXMgdGhpcyBpc1xuICAgIC8vIHRoZSByaWdodCB0aGluZyB0byBkbyBmb3IgdGhlIG1ham9yaXR5IG9mIGljb24gdXNlLWNhc2VzLlxuICAgIGlmICghYXJpYUhpZGRlbikge1xuICAgICAgZWxlbWVudFJlZi5uYXRpdmVFbGVtZW50LnNldEF0dHJpYnV0ZSgnYXJpYS1oaWRkZW4nLCAndHJ1ZScpO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBTcGxpdHMgYW4gc3ZnSWNvbiBiaW5kaW5nIHZhbHVlIGludG8gaXRzIGljb24gc2V0IGFuZCBpY29uIG5hbWUgY29tcG9uZW50cy5cbiAgICogUmV0dXJucyBhIDItZWxlbWVudCBhcnJheSBvZiBbKGljb24gc2V0KSwgKGljb24gbmFtZSldLlxuICAgKiBUaGUgc2VwYXJhdG9yIGZvciB0aGUgdHdvIGZpZWxkcyBpcyAnOicuIElmIHRoZXJlIGlzIG5vIHNlcGFyYXRvciwgYW4gZW1wdHlcbiAgICogc3RyaW5nIGlzIHJldHVybmVkIGZvciB0aGUgaWNvbiBzZXQgYW5kIHRoZSBlbnRpcmUgdmFsdWUgaXMgcmV0dXJuZWQgZm9yXG4gICAqIHRoZSBpY29uIG5hbWUuIElmIHRoZSBhcmd1bWVudCBpcyBmYWxzeSwgcmV0dXJucyBhbiBhcnJheSBvZiB0d28gZW1wdHkgc3RyaW5ncy5cbiAgICogVGhyb3dzIGFuIGVycm9yIGlmIHRoZSBuYW1lIGNvbnRhaW5zIHR3byBvciBtb3JlICc6JyBzZXBhcmF0b3JzLlxuICAgKiBFeGFtcGxlczpcbiAgICogICBgJ3NvY2lhbDpjYWtlJyAtPiBbJ3NvY2lhbCcsICdjYWtlJ11cbiAgICogICAncGVuZ3VpbicgLT4gWycnLCAncGVuZ3VpbiddXG4gICAqICAgbnVsbCAtPiBbJycsICcnXVxuICAgKiAgICdhOmI6YycgLT4gKHRocm93cyBFcnJvcilgXG4gICAqL1xuICBwcml2YXRlIF9zcGxpdEljb25OYW1lKGljb25OYW1lOiBzdHJpbmcpOiBbc3RyaW5nLCBzdHJpbmddIHtcbiAgICBpZiAoIWljb25OYW1lKSB7XG4gICAgICByZXR1cm4gWycnLCAnJ107XG4gICAgfVxuICAgIGNvbnN0IHBhcnRzID0gaWNvbk5hbWUuc3BsaXQoJzonKTtcbiAgICBzd2l0Y2ggKHBhcnRzLmxlbmd0aCkge1xuICAgICAgY2FzZSAxOiByZXR1cm4gWycnLCBwYXJ0c1swXV07IC8vIFVzZSBkZWZhdWx0IG5hbWVzcGFjZS5cbiAgICAgIGNhc2UgMjogcmV0dXJuIDxbc3RyaW5nLCBzdHJpbmddPnBhcnRzO1xuICAgICAgZGVmYXVsdDogdGhyb3cgRXJyb3IoYEludmFsaWQgaWNvbiBuYW1lOiBcIiR7aWNvbk5hbWV9XCJgKTsgLy8gVE9ETzogYWRkIGFuIG5nRGV2TW9kZSBjaGVja1xuICAgIH1cbiAgfVxuXG4gIG5nT25Jbml0KCkge1xuICAgIC8vIFVwZGF0ZSBmb250IGNsYXNzZXMgYmVjYXVzZSBuZ09uQ2hhbmdlcyB3b24ndCBiZSBjYWxsZWQgaWYgbm9uZSBvZiB0aGUgaW5wdXRzIGFyZSBwcmVzZW50LFxuICAgIC8vIGUuZy4gPG1hdC1pY29uPmFycm93PC9tYXQtaWNvbj4gSW4gdGhpcyBjYXNlIHdlIG5lZWQgdG8gYWRkIGEgQ1NTIGNsYXNzIGZvciB0aGUgZGVmYXVsdCBmb250LlxuICAgIHRoaXMuX3VwZGF0ZUZvbnRJY29uQ2xhc3NlcygpO1xuICB9XG5cbiAgbmdBZnRlclZpZXdDaGVja2VkKCkge1xuICAgIGNvbnN0IGNhY2hlZEVsZW1lbnRzID0gdGhpcy5fZWxlbWVudHNXaXRoRXh0ZXJuYWxSZWZlcmVuY2VzO1xuXG4gICAgaWYgKGNhY2hlZEVsZW1lbnRzICYmIGNhY2hlZEVsZW1lbnRzLnNpemUpIHtcbiAgICAgIGNvbnN0IG5ld1BhdGggPSB0aGlzLl9sb2NhdGlvbi5nZXRQYXRobmFtZSgpO1xuXG4gICAgICAvLyBXZSBuZWVkIHRvIGNoZWNrIHdoZXRoZXIgdGhlIFVSTCBoYXMgY2hhbmdlZCBvbiBlYWNoIGNoYW5nZSBkZXRlY3Rpb24gc2luY2VcbiAgICAgIC8vIHRoZSBicm93c2VyIGRvZXNuJ3QgaGF2ZSBhbiBBUEkgdGhhdCB3aWxsIGxldCB1cyByZWFjdCBvbiBsaW5rIGNsaWNrcyBhbmRcbiAgICAgIC8vIHdlIGNhbid0IGRlcGVuZCBvbiB0aGUgQW5ndWxhciByb3V0ZXIuIFRoZSByZWZlcmVuY2VzIG5lZWQgdG8gYmUgdXBkYXRlZCxcbiAgICAgIC8vIGJlY2F1c2Ugd2hpbGUgbW9zdCBicm93c2VycyBkb24ndCBjYXJlIHdoZXRoZXIgdGhlIFVSTCBpcyBjb3JyZWN0IGFmdGVyXG4gICAgICAvLyB0aGUgZmlyc3QgcmVuZGVyLCBTYWZhcmkgd2lsbCBicmVhayBpZiB0aGUgdXNlciBuYXZpZ2F0ZXMgdG8gYSBkaWZmZXJlbnRcbiAgICAgIC8vIHBhZ2UgYW5kIHRoZSBTVkcgaXNuJ3QgcmUtcmVuZGVyZWQuXG4gICAgICBpZiAobmV3UGF0aCAhPT0gdGhpcy5fcHJldmlvdXNQYXRoKSB7XG4gICAgICAgIHRoaXMuX3ByZXZpb3VzUGF0aCA9IG5ld1BhdGg7XG4gICAgICAgIHRoaXMuX3ByZXBlbmRQYXRoVG9SZWZlcmVuY2VzKG5ld1BhdGgpO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIG5nT25EZXN0cm95KCkge1xuICAgIHRoaXMuX2N1cnJlbnRJY29uRmV0Y2gudW5zdWJzY3JpYmUoKTtcblxuICAgIGlmICh0aGlzLl9lbGVtZW50c1dpdGhFeHRlcm5hbFJlZmVyZW5jZXMpIHtcbiAgICAgIHRoaXMuX2VsZW1lbnRzV2l0aEV4dGVybmFsUmVmZXJlbmNlcy5jbGVhcigpO1xuICAgIH1cbiAgfVxuXG4gIF91c2luZ0ZvbnRJY29uKCk6IGJvb2xlYW4ge1xuICAgIHJldHVybiAhdGhpcy5zdmdJY29uO1xuICB9XG5cbiAgcHJpdmF0ZSBfc2V0U3ZnRWxlbWVudChzdmc6IFNWR0VsZW1lbnQpIHtcbiAgICB0aGlzLl9jbGVhclN2Z0VsZW1lbnQoKTtcblxuICAgIC8vIFdvcmthcm91bmQgZm9yIElFMTEgYW5kIEVkZ2UgaWdub3JpbmcgYHN0eWxlYCB0YWdzIGluc2lkZSBkeW5hbWljYWxseS1jcmVhdGVkIFNWR3MuXG4gICAgLy8gU2VlOiBodHRwczovL2RldmVsb3Blci5taWNyb3NvZnQuY29tL2VuLXVzL21pY3Jvc29mdC1lZGdlL3BsYXRmb3JtL2lzc3Vlcy8xMDg5ODQ2OS9cbiAgICAvLyBEbyB0aGlzIGJlZm9yZSBpbnNlcnRpbmcgdGhlIGVsZW1lbnQgaW50byB0aGUgRE9NLCBpbiBvcmRlciB0byBhdm9pZCBhIHN0eWxlIHJlY2FsY3VsYXRpb24uXG4gICAgY29uc3Qgc3R5bGVUYWdzID0gc3ZnLnF1ZXJ5U2VsZWN0b3JBbGwoJ3N0eWxlJykgYXMgTm9kZUxpc3RPZjxIVE1MU3R5bGVFbGVtZW50PjtcblxuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgc3R5bGVUYWdzLmxlbmd0aDsgaSsrKSB7XG4gICAgICBzdHlsZVRhZ3NbaV0udGV4dENvbnRlbnQgKz0gJyAnO1xuICAgIH1cblxuICAgIC8vIE5vdGU6IHdlIGRvIHRoaXMgZml4IGhlcmUsIHJhdGhlciB0aGFuIHRoZSBpY29uIHJlZ2lzdHJ5LCBiZWNhdXNlIHRoZVxuICAgIC8vIHJlZmVyZW5jZXMgaGF2ZSB0byBwb2ludCB0byB0aGUgVVJMIGF0IHRoZSB0aW1lIHRoYXQgdGhlIGljb24gd2FzIGNyZWF0ZWQuXG4gICAgY29uc3QgcGF0aCA9IHRoaXMuX2xvY2F0aW9uLmdldFBhdGhuYW1lKCk7XG4gICAgdGhpcy5fcHJldmlvdXNQYXRoID0gcGF0aDtcbiAgICB0aGlzLl9jYWNoZUNoaWxkcmVuV2l0aEV4dGVybmFsUmVmZXJlbmNlcyhzdmcpO1xuICAgIHRoaXMuX3ByZXBlbmRQYXRoVG9SZWZlcmVuY2VzKHBhdGgpO1xuICAgIHRoaXMuX2VsZW1lbnRSZWYubmF0aXZlRWxlbWVudC5hcHBlbmRDaGlsZChzdmcpO1xuICB9XG5cbiAgcHJpdmF0ZSBfY2xlYXJTdmdFbGVtZW50KCkge1xuICAgIGNvbnN0IGxheW91dEVsZW1lbnQ6IEhUTUxFbGVtZW50ID0gdGhpcy5fZWxlbWVudFJlZi5uYXRpdmVFbGVtZW50O1xuICAgIGxldCBjaGlsZENvdW50ID0gbGF5b3V0RWxlbWVudC5jaGlsZE5vZGVzLmxlbmd0aDtcblxuICAgIGlmICh0aGlzLl9lbGVtZW50c1dpdGhFeHRlcm5hbFJlZmVyZW5jZXMpIHtcbiAgICAgIHRoaXMuX2VsZW1lbnRzV2l0aEV4dGVybmFsUmVmZXJlbmNlcy5jbGVhcigpO1xuICAgIH1cblxuICAgIC8vIFJlbW92ZSBleGlzdGluZyBub24tZWxlbWVudCBjaGlsZCBub2RlcyBhbmQgU1ZHcywgYW5kIGFkZCB0aGUgbmV3IFNWRyBlbGVtZW50LiBOb3RlIHRoYXRcbiAgICAvLyB3ZSBjYW4ndCB1c2UgaW5uZXJIVE1MLCBiZWNhdXNlIElFIHdpbGwgdGhyb3cgaWYgdGhlIGVsZW1lbnQgaGFzIGEgZGF0YSBiaW5kaW5nLlxuICAgIHdoaWxlIChjaGlsZENvdW50LS0pIHtcbiAgICAgIGNvbnN0IGNoaWxkID0gbGF5b3V0RWxlbWVudC5jaGlsZE5vZGVzW2NoaWxkQ291bnRdO1xuXG4gICAgICAvLyAxIGNvcnJlc3BvbmRzIHRvIE5vZGUuRUxFTUVOVF9OT0RFLiBXZSByZW1vdmUgYWxsIG5vbi1lbGVtZW50IG5vZGVzIGluIG9yZGVyIHRvIGdldCByaWRcbiAgICAgIC8vIG9mIGFueSBsb29zZSB0ZXh0IG5vZGVzLCBhcyB3ZWxsIGFzIGFueSBTVkcgZWxlbWVudHMgaW4gb3JkZXIgdG8gcmVtb3ZlIGFueSBvbGQgaWNvbnMuXG4gICAgICBpZiAoY2hpbGQubm9kZVR5cGUgIT09IDEgfHwgY2hpbGQubm9kZU5hbWUudG9Mb3dlckNhc2UoKSA9PT0gJ3N2ZycpIHtcbiAgICAgICAgbGF5b3V0RWxlbWVudC5yZW1vdmVDaGlsZChjaGlsZCk7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBfdXBkYXRlRm9udEljb25DbGFzc2VzKCkge1xuICAgIGlmICghdGhpcy5fdXNpbmdGb250SWNvbigpKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgY29uc3QgZWxlbTogSFRNTEVsZW1lbnQgPSB0aGlzLl9lbGVtZW50UmVmLm5hdGl2ZUVsZW1lbnQ7XG4gICAgY29uc3QgZm9udFNldENsYXNzID0gdGhpcy5mb250U2V0ID9cbiAgICAgICAgdGhpcy5faWNvblJlZ2lzdHJ5LmNsYXNzTmFtZUZvckZvbnRBbGlhcyh0aGlzLmZvbnRTZXQpIDpcbiAgICAgICAgdGhpcy5faWNvblJlZ2lzdHJ5LmdldERlZmF1bHRGb250U2V0Q2xhc3MoKTtcblxuICAgIGlmIChmb250U2V0Q2xhc3MgIT0gdGhpcy5fcHJldmlvdXNGb250U2V0Q2xhc3MpIHtcbiAgICAgIGlmICh0aGlzLl9wcmV2aW91c0ZvbnRTZXRDbGFzcykge1xuICAgICAgICBlbGVtLmNsYXNzTGlzdC5yZW1vdmUodGhpcy5fcHJldmlvdXNGb250U2V0Q2xhc3MpO1xuICAgICAgfVxuICAgICAgaWYgKGZvbnRTZXRDbGFzcykge1xuICAgICAgICBlbGVtLmNsYXNzTGlzdC5hZGQoZm9udFNldENsYXNzKTtcbiAgICAgIH1cbiAgICAgIHRoaXMuX3ByZXZpb3VzRm9udFNldENsYXNzID0gZm9udFNldENsYXNzO1xuICAgIH1cblxuICAgIGlmICh0aGlzLmZvbnRJY29uICE9IHRoaXMuX3ByZXZpb3VzRm9udEljb25DbGFzcykge1xuICAgICAgaWYgKHRoaXMuX3ByZXZpb3VzRm9udEljb25DbGFzcykge1xuICAgICAgICBlbGVtLmNsYXNzTGlzdC5yZW1vdmUodGhpcy5fcHJldmlvdXNGb250SWNvbkNsYXNzKTtcbiAgICAgIH1cbiAgICAgIGlmICh0aGlzLmZvbnRJY29uKSB7XG4gICAgICAgIGVsZW0uY2xhc3NMaXN0LmFkZCh0aGlzLmZvbnRJY29uKTtcbiAgICAgIH1cbiAgICAgIHRoaXMuX3ByZXZpb3VzRm9udEljb25DbGFzcyA9IHRoaXMuZm9udEljb247XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIENsZWFucyB1cCBhIHZhbHVlIHRvIGJlIHVzZWQgYXMgYSBmb250SWNvbiBvciBmb250U2V0LlxuICAgKiBTaW5jZSB0aGUgdmFsdWUgZW5kcyB1cCBiZWluZyBhc3NpZ25lZCBhcyBhIENTUyBjbGFzcywgd2VcbiAgICogaGF2ZSB0byB0cmltIHRoZSB2YWx1ZSBhbmQgb21pdCBzcGFjZS1zZXBhcmF0ZWQgdmFsdWVzLlxuICAgKi9cbiAgcHJpdmF0ZSBfY2xlYW51cEZvbnRWYWx1ZSh2YWx1ZTogc3RyaW5nKSB7XG4gICAgcmV0dXJuIHR5cGVvZiB2YWx1ZSA9PT0gJ3N0cmluZycgPyB2YWx1ZS50cmltKCkuc3BsaXQoJyAnKVswXSA6IHZhbHVlO1xuICB9XG5cbiAgLyoqXG4gICAqIFByZXBlbmRzIHRoZSBjdXJyZW50IHBhdGggdG8gYWxsIGVsZW1lbnRzIHRoYXQgaGF2ZSBhbiBhdHRyaWJ1dGUgcG9pbnRpbmcgdG8gYSBgRnVuY0lSSWBcbiAgICogcmVmZXJlbmNlLiBUaGlzIGlzIHJlcXVpcmVkIGJlY2F1c2UgV2ViS2l0IGJyb3dzZXJzIHJlcXVpcmUgcmVmZXJlbmNlcyB0byBiZSBwcmVmaXhlZCB3aXRoXG4gICAqIHRoZSBjdXJyZW50IHBhdGgsIGlmIHRoZSBwYWdlIGhhcyBhIGBiYXNlYCB0YWcuXG4gICAqL1xuICBwcml2YXRlIF9wcmVwZW5kUGF0aFRvUmVmZXJlbmNlcyhwYXRoOiBzdHJpbmcpIHtcbiAgICBjb25zdCBlbGVtZW50cyA9IHRoaXMuX2VsZW1lbnRzV2l0aEV4dGVybmFsUmVmZXJlbmNlcztcblxuICAgIGlmIChlbGVtZW50cykge1xuICAgICAgZWxlbWVudHMuZm9yRWFjaCgoYXR0cnMsIGVsZW1lbnQpID0+IHtcbiAgICAgICAgYXR0cnMuZm9yRWFjaChhdHRyID0+IHtcbiAgICAgICAgICBlbGVtZW50LnNldEF0dHJpYnV0ZShhdHRyLm5hbWUsIGB1cmwoJyR7cGF0aH0jJHthdHRyLnZhbHVlfScpYCk7XG4gICAgICAgIH0pO1xuICAgICAgfSk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIENhY2hlcyB0aGUgY2hpbGRyZW4gb2YgYW4gU1ZHIGVsZW1lbnQgdGhhdCBoYXZlIGB1cmwoKWBcbiAgICogcmVmZXJlbmNlcyB0aGF0IHdlIG5lZWQgdG8gcHJlZml4IHdpdGggdGhlIGN1cnJlbnQgcGF0aC5cbiAgICovXG4gIHByaXZhdGUgX2NhY2hlQ2hpbGRyZW5XaXRoRXh0ZXJuYWxSZWZlcmVuY2VzKGVsZW1lbnQ6IFNWR0VsZW1lbnQpIHtcbiAgICBjb25zdCBlbGVtZW50c1dpdGhGdW5jSXJpID0gZWxlbWVudC5xdWVyeVNlbGVjdG9yQWxsKGZ1bmNJcmlBdHRyaWJ1dGVTZWxlY3Rvcik7XG4gICAgY29uc3QgZWxlbWVudHMgPSB0aGlzLl9lbGVtZW50c1dpdGhFeHRlcm5hbFJlZmVyZW5jZXMgPVxuICAgICAgICB0aGlzLl9lbGVtZW50c1dpdGhFeHRlcm5hbFJlZmVyZW5jZXMgfHwgbmV3IE1hcCgpO1xuXG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCBlbGVtZW50c1dpdGhGdW5jSXJpLmxlbmd0aDsgaSsrKSB7XG4gICAgICBmdW5jSXJpQXR0cmlidXRlcy5mb3JFYWNoKGF0dHIgPT4ge1xuICAgICAgICBjb25zdCBlbGVtZW50V2l0aFJlZmVyZW5jZSA9IGVsZW1lbnRzV2l0aEZ1bmNJcmlbaV07XG4gICAgICAgIGNvbnN0IHZhbHVlID0gZWxlbWVudFdpdGhSZWZlcmVuY2UuZ2V0QXR0cmlidXRlKGF0dHIpO1xuICAgICAgICBjb25zdCBtYXRjaCA9IHZhbHVlID8gdmFsdWUubWF0Y2goZnVuY0lyaVBhdHRlcm4pIDogbnVsbDtcblxuICAgICAgICBpZiAobWF0Y2gpIHtcbiAgICAgICAgICBsZXQgYXR0cmlidXRlcyA9IGVsZW1lbnRzLmdldChlbGVtZW50V2l0aFJlZmVyZW5jZSk7XG5cbiAgICAgICAgICBpZiAoIWF0dHJpYnV0ZXMpIHtcbiAgICAgICAgICAgIGF0dHJpYnV0ZXMgPSBbXTtcbiAgICAgICAgICAgIGVsZW1lbnRzLnNldChlbGVtZW50V2l0aFJlZmVyZW5jZSwgYXR0cmlidXRlcyk7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgYXR0cmlidXRlcyEucHVzaCh7bmFtZTogYXR0ciwgdmFsdWU6IG1hdGNoWzFdfSk7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuICAgIH1cbiAgfVxuXG4gIC8qKiBTZXRzIGEgbmV3IFNWRyBpY29uIHdpdGggYSBwYXJ0aWN1bGFyIG5hbWUuICovXG4gIHByaXZhdGUgX3VwZGF0ZVN2Z0ljb24ocmF3TmFtZTogc3RyaW5nfHVuZGVmaW5lZCkge1xuICAgIHRoaXMuX3N2Z05hbWVzcGFjZSA9IG51bGw7XG4gICAgdGhpcy5fc3ZnTmFtZSA9IG51bGw7XG4gICAgdGhpcy5fY3VycmVudEljb25GZXRjaC51bnN1YnNjcmliZSgpO1xuXG4gICAgaWYgKHJhd05hbWUpIHtcbiAgICAgIGNvbnN0IFtuYW1lc3BhY2UsIGljb25OYW1lXSA9IHRoaXMuX3NwbGl0SWNvbk5hbWUocmF3TmFtZSk7XG5cbiAgICAgIGlmIChuYW1lc3BhY2UpIHtcbiAgICAgICAgdGhpcy5fc3ZnTmFtZXNwYWNlID0gbmFtZXNwYWNlO1xuICAgICAgfVxuXG4gICAgICBpZiAoaWNvbk5hbWUpIHtcbiAgICAgICAgdGhpcy5fc3ZnTmFtZSA9IGljb25OYW1lO1xuICAgICAgfVxuXG4gICAgICB0aGlzLl9jdXJyZW50SWNvbkZldGNoID0gdGhpcy5faWNvblJlZ2lzdHJ5LmdldE5hbWVkU3ZnSWNvbihpY29uTmFtZSwgbmFtZXNwYWNlKVxuICAgICAgICAgIC5waXBlKHRha2UoMSkpXG4gICAgICAgICAgLnN1YnNjcmliZShzdmcgPT4gdGhpcy5fc2V0U3ZnRWxlbWVudChzdmcpLCAoZXJyOiBFcnJvcikgPT4ge1xuICAgICAgICAgICAgY29uc3QgZXJyb3JNZXNzYWdlID0gYEVycm9yIHJldHJpZXZpbmcgaWNvbiAke25hbWVzcGFjZX06JHtpY29uTmFtZX0hICR7ZXJyLm1lc3NhZ2V9YDtcbiAgICAgICAgICAgIHRoaXMuX2Vycm9ySGFuZGxlci5oYW5kbGVFcnJvcihuZXcgRXJyb3IoZXJyb3JNZXNzYWdlKSk7XG4gICAgICAgICAgfSk7XG4gICAgfVxuICB9XG5cbiAgc3RhdGljIG5nQWNjZXB0SW5wdXRUeXBlX2lubGluZTogQm9vbGVhbklucHV0O1xufVxuIl19 |
---|