icon.service.mjs 37 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281
  1. import { DOCUMENT } from '@angular/common';
  2. import { HttpClient } from '@angular/common/http';
  3. import { Inject, Injectable, InjectionToken, Optional, SecurityContext } from '@angular/core';
  4. import { of, Observable, Subject } from 'rxjs';
  5. import { catchError, filter, finalize, map, share, take, tap } from 'rxjs/operators';
  6. import { cloneSVG, getIconDefinitionFromAbbr, getNameAndNamespace, getSecondaryColor, hasNamespace, isIconDefinition, replaceFillColor, warn, withSuffix, withSuffixAndColor } from '../utils';
  7. import { DynamicLoadingTimeoutError, HttpModuleNotImport, IconNotFoundError, NameSpaceIsNotSpecifyError, SVGTagNotFoundError, UrlNotSafeError } from './icon.error';
  8. import * as i0 from "@angular/core";
  9. import * as i1 from "@angular/common/http";
  10. import * as i2 from "@angular/platform-browser";
  11. const JSONP_HANDLER_NAME = '__ant_icon_load';
  12. export const ANT_ICONS = new InjectionToken('ant_icons');
  13. class IconService {
  14. set twoToneColor({ primaryColor, secondaryColor }) {
  15. this._twoToneColorPalette.primaryColor = primaryColor;
  16. this._twoToneColorPalette.secondaryColor =
  17. secondaryColor || getSecondaryColor(primaryColor);
  18. }
  19. get twoToneColor() {
  20. // Make a copy to avoid unexpected changes.
  21. return { ...this._twoToneColorPalette };
  22. }
  23. /**
  24. * Disable dynamic loading (support static loading only).
  25. */
  26. get _disableDynamicLoading() {
  27. return false;
  28. }
  29. constructor(_rendererFactory, _handler, _document, sanitizer, _antIcons) {
  30. this._rendererFactory = _rendererFactory;
  31. this._handler = _handler;
  32. this._document = _document;
  33. this.sanitizer = sanitizer;
  34. this._antIcons = _antIcons;
  35. this.defaultTheme = 'outline';
  36. /**
  37. * All icon definitions would be registered here.
  38. */
  39. this._svgDefinitions = new Map();
  40. /**
  41. * Cache all rendered icons. Icons are identified by name, theme,
  42. * and for twotone icons, primary color and secondary color.
  43. */
  44. this._svgRenderedDefinitions = new Map();
  45. this._inProgressFetches = new Map();
  46. /**
  47. * Url prefix for fetching inline SVG by dynamic importing.
  48. */
  49. this._assetsUrlRoot = '';
  50. this._twoToneColorPalette = {
  51. primaryColor: '#333333',
  52. secondaryColor: '#E6E6E6'
  53. };
  54. /** A flag indicates whether jsonp loading is enabled. */
  55. this._enableJsonpLoading = false;
  56. this._jsonpIconLoad$ = new Subject();
  57. this._renderer = this._rendererFactory.createRenderer(null, null);
  58. if (this._handler) {
  59. this._http = new HttpClient(this._handler);
  60. }
  61. if (this._antIcons) {
  62. this.addIcon(...this._antIcons);
  63. }
  64. }
  65. /**
  66. * Call this method to switch to jsonp like loading.
  67. */
  68. useJsonpLoading() {
  69. if (!this._enableJsonpLoading) {
  70. this._enableJsonpLoading = true;
  71. window[JSONP_HANDLER_NAME] = (icon) => {
  72. this._jsonpIconLoad$.next(icon);
  73. };
  74. }
  75. else {
  76. warn('You are already using jsonp loading.');
  77. }
  78. }
  79. /**
  80. * Change the prefix of the inline svg resources, so they could be deployed elsewhere, like CDN.
  81. * @param prefix
  82. */
  83. changeAssetsSource(prefix) {
  84. this._assetsUrlRoot = prefix.endsWith('/') ? prefix : prefix + '/';
  85. }
  86. /**
  87. * Add icons provided by ant design.
  88. * @param icons
  89. */
  90. addIcon(...icons) {
  91. icons.forEach(icon => {
  92. this._svgDefinitions.set(withSuffix(icon.name, icon.theme), icon);
  93. });
  94. }
  95. /**
  96. * Register an icon. Namespace is required.
  97. * @param type
  98. * @param literal
  99. */
  100. addIconLiteral(type, literal) {
  101. const [_, namespace] = getNameAndNamespace(type);
  102. if (!namespace) {
  103. throw NameSpaceIsNotSpecifyError();
  104. }
  105. this.addIcon({ name: type, icon: literal });
  106. }
  107. /**
  108. * Remove all cache.
  109. */
  110. clear() {
  111. this._svgDefinitions.clear();
  112. this._svgRenderedDefinitions.clear();
  113. }
  114. /**
  115. * Get a rendered `SVGElement`.
  116. * @param icon
  117. * @param twoToneColor
  118. */
  119. getRenderedContent(icon, twoToneColor) {
  120. // If `icon` is a `IconDefinition`, go to the next step. If not, try to fetch it from cache.
  121. const definition = isIconDefinition(icon)
  122. ? icon
  123. : this._svgDefinitions.get(icon) || null;
  124. if (!definition && this._disableDynamicLoading) {
  125. throw IconNotFoundError(icon);
  126. }
  127. // If `icon` is a `IconDefinition` of successfully fetch, wrap it in an `Observable`.
  128. // Otherwise try to fetch it from remote.
  129. const $iconDefinition = definition
  130. ? of(definition)
  131. : this._loadIconDynamically(icon);
  132. // If finally get an `IconDefinition`, render and return it. Otherwise throw an error.
  133. return $iconDefinition.pipe(map(i => {
  134. if (!i) {
  135. throw IconNotFoundError(icon);
  136. }
  137. return this._loadSVGFromCacheOrCreateNew(i, twoToneColor);
  138. }));
  139. }
  140. getCachedIcons() {
  141. return this._svgDefinitions;
  142. }
  143. /**
  144. * Get raw svg and assemble a `IconDefinition` object.
  145. * @param type
  146. */
  147. _loadIconDynamically(type) {
  148. // If developer doesn't provide HTTP module nor enable jsonp loading, just throw an error.
  149. if (!this._http && !this._enableJsonpLoading) {
  150. return of(HttpModuleNotImport());
  151. }
  152. // If multi directive ask for the same icon at the same time,
  153. // request should only be fired once.
  154. let inProgress = this._inProgressFetches.get(type);
  155. if (!inProgress) {
  156. const [name, namespace] = getNameAndNamespace(type);
  157. // If the string has a namespace within, create a simple `IconDefinition`.
  158. const icon = namespace
  159. ? { name: type, icon: '' }
  160. : getIconDefinitionFromAbbr(name);
  161. const suffix = this._enableJsonpLoading ? '.js' : '.svg';
  162. const url = (namespace
  163. ? `${this._assetsUrlRoot}assets/${namespace}/${name}`
  164. : `${this._assetsUrlRoot}assets/${icon.theme}/${icon.name}`) + suffix;
  165. const safeUrl = this.sanitizer.sanitize(SecurityContext.URL, url);
  166. if (!safeUrl) {
  167. throw UrlNotSafeError(url);
  168. }
  169. const source = !this._enableJsonpLoading
  170. ? this._http
  171. .get(safeUrl, { responseType: 'text' })
  172. .pipe(map(literal => ({ ...icon, icon: literal })))
  173. : this._loadIconDynamicallyWithJsonp(icon, safeUrl);
  174. inProgress = source.pipe(tap(definition => this.addIcon(definition)), finalize(() => this._inProgressFetches.delete(type)), catchError(() => of(null)), share());
  175. this._inProgressFetches.set(type, inProgress);
  176. }
  177. return inProgress;
  178. }
  179. _loadIconDynamicallyWithJsonp(icon, url) {
  180. return new Observable(subscriber => {
  181. const loader = this._document.createElement('script');
  182. const timer = setTimeout(() => {
  183. clean();
  184. subscriber.error(DynamicLoadingTimeoutError());
  185. }, 6000);
  186. loader.src = url;
  187. function clean() {
  188. loader.parentNode.removeChild(loader);
  189. clearTimeout(timer);
  190. }
  191. this._document.body.appendChild(loader);
  192. this._jsonpIconLoad$
  193. .pipe(filter(i => i.name === icon.name && i.theme === icon.theme), take(1))
  194. .subscribe(i => {
  195. subscriber.next(i);
  196. clean();
  197. });
  198. });
  199. }
  200. /**
  201. * Render a new `SVGElement` for a given `IconDefinition`, or make a copy from cache.
  202. * @param icon
  203. * @param twoToneColor
  204. */
  205. _loadSVGFromCacheOrCreateNew(icon, twoToneColor) {
  206. let svg;
  207. const pri = twoToneColor || this._twoToneColorPalette.primaryColor;
  208. const sec = getSecondaryColor(pri) || this._twoToneColorPalette.secondaryColor;
  209. const key = icon.theme === 'twotone'
  210. ? withSuffixAndColor(icon.name, icon.theme, pri, sec)
  211. : icon.theme === undefined
  212. ? icon.name
  213. : withSuffix(icon.name, icon.theme);
  214. // Try to make a copy from cache.
  215. const cached = this._svgRenderedDefinitions.get(key);
  216. if (cached) {
  217. svg = cached.icon;
  218. }
  219. else {
  220. svg = this._setSVGAttribute(this._colorizeSVGIcon(
  221. // Icons provided by ant design should be refined to remove preset colors.
  222. this._createSVGElementFromString(hasNamespace(icon.name) ? icon.icon : replaceFillColor(icon.icon)), icon.theme === 'twotone', pri, sec));
  223. // Cache it.
  224. this._svgRenderedDefinitions.set(key, {
  225. ...icon,
  226. icon: svg
  227. });
  228. }
  229. return cloneSVG(svg);
  230. }
  231. _createSVGElementFromString(str) {
  232. const div = this._document.createElement('div');
  233. div.innerHTML = str;
  234. const svg = div.querySelector('svg');
  235. if (!svg) {
  236. throw SVGTagNotFoundError;
  237. }
  238. return svg;
  239. }
  240. _setSVGAttribute(svg) {
  241. this._renderer.setAttribute(svg, 'width', '1em');
  242. this._renderer.setAttribute(svg, 'height', '1em');
  243. return svg;
  244. }
  245. _colorizeSVGIcon(svg, twotone, pri, sec) {
  246. if (twotone) {
  247. const children = svg.childNodes;
  248. const length = children.length;
  249. for (let i = 0; i < length; i++) {
  250. const child = children[i];
  251. if (child.getAttribute('fill') === 'secondaryColor') {
  252. this._renderer.setAttribute(child, 'fill', sec);
  253. }
  254. else {
  255. this._renderer.setAttribute(child, 'fill', pri);
  256. }
  257. }
  258. }
  259. this._renderer.setAttribute(svg, 'fill', 'currentColor');
  260. return svg;
  261. }
  262. static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.0.2", ngImport: i0, type: IconService, deps: [{ token: i0.RendererFactory2 }, { token: i1.HttpBackend, optional: true }, { token: DOCUMENT, optional: true }, { token: i2.DomSanitizer }, { token: ANT_ICONS, optional: true }], target: i0.ɵɵFactoryTarget.Injectable }); }
  263. static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "16.0.2", ngImport: i0, type: IconService }); }
  264. }
  265. export { IconService };
  266. i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.0.2", ngImport: i0, type: IconService, decorators: [{
  267. type: Injectable
  268. }], ctorParameters: function () { return [{ type: i0.RendererFactory2 }, { type: i1.HttpBackend, decorators: [{
  269. type: Optional
  270. }] }, { type: undefined, decorators: [{
  271. type: Optional
  272. }, {
  273. type: Inject,
  274. args: [DOCUMENT]
  275. }] }, { type: i2.DomSanitizer }, { type: undefined, decorators: [{
  276. type: Optional
  277. }, {
  278. type: Inject,
  279. args: [ANT_ICONS]
  280. }] }]; } });
  281. //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaWNvbi5zZXJ2aWNlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vc3JjL2NvbXBvbmVudC9pY29uLnNlcnZpY2UudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLFFBQVEsRUFBRSxNQUFNLGlCQUFpQixDQUFDO0FBQzNDLE9BQU8sRUFBZSxVQUFVLEVBQUUsTUFBTSxzQkFBc0IsQ0FBQztBQUMvRCxPQUFPLEVBQUUsTUFBTSxFQUFFLFVBQVUsRUFBRSxjQUFjLEVBQUUsUUFBUSxFQUErQixlQUFlLEVBQUUsTUFBTSxlQUFlLENBQUM7QUFFM0gsT0FBTyxFQUFFLEVBQUUsRUFBRSxVQUFVLEVBQUUsT0FBTyxFQUFFLE1BQU0sTUFBTSxDQUFDO0FBQy9DLE9BQU8sRUFDTCxVQUFVLEVBQ1YsTUFBTSxFQUNOLFFBQVEsRUFDUixHQUFHLEVBQ0gsS0FBSyxFQUNMLElBQUksRUFDSixHQUFHLEVBQ0osTUFBTSxnQkFBZ0IsQ0FBQztBQVF4QixPQUFPLEVBQ0wsUUFBUSxFQUNSLHlCQUF5QixFQUN6QixtQkFBbUIsRUFDbkIsaUJBQWlCLEVBQ2pCLFlBQVksRUFDWixnQkFBZ0IsRUFDaEIsZ0JBQWdCLEVBQ2hCLElBQUksRUFDSixVQUFVLEVBQ1Ysa0JBQWtCLEVBQ25CLE1BQU0sVUFBVSxDQUFDO0FBQ2xCLE9BQU8sRUFDTCwwQkFBMEIsRUFDMUIsbUJBQW1CLEVBQ25CLGlCQUFpQixFQUNqQiwwQkFBMEIsRUFDMUIsbUJBQW1CLEVBQ25CLGVBQWUsRUFDaEIsTUFBTSxjQUFjLENBQUM7Ozs7QUFFdEIsTUFBTSxrQkFBa0IsR0FBRyxpQkFBaUIsQ0FBQztBQUU3QyxNQUFNLENBQUMsTUFBTSxTQUFTLEdBQUcsSUFBSSxjQUFjLENBQW1CLFdBQVcsQ0FBQyxDQUFDO0FBRTNFLE1BQ2EsV0FBVztJQUd0QixJQUFJLFlBQVksQ0FBQyxFQUNmLFlBQVksRUFDWixjQUFjLEVBQ1k7UUFDMUIsSUFBSSxDQUFDLG9C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SUFBSSxDQUFDLFNBQVMsQ0FBQyxZQUFZLENBQUMsS0FBSyxFQUFFLE1BQU0sRUFBRSxHQUFHLENBQUMsQ0FBQztpQkFDakQ7YUFDRjtTQUNGO1FBQ0QsSUFBSSxDQUFDLFNBQVMsQ0FBQyxZQUFZLENBQUMsR0FBRyxFQUFFLE1BQU0sRUFBRSxjQUFjLENBQUMsQ0FBQztRQUN6RCxPQUFPLEdBQUcsQ0FBQztJQUNiLENBQUM7OEdBaFZVLFdBQVcsNkZBNERBLFFBQVEseURBR1IsU0FBUztrSEEvRHBCLFdBQVc7O1NBQVgsV0FBVzsyRkFBWCxXQUFXO2tCQUR2QixVQUFVOzswQkE0RE4sUUFBUTs7MEJBQ1IsUUFBUTs7MEJBQUksTUFBTTsyQkFBQyxRQUFROzswQkFHM0IsUUFBUTs7MEJBQUksTUFBTTsyQkFBQyxTQUFTIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgRE9DVU1FTlQgfSBmcm9tICdAYW5ndWxhci9jb21tb24nO1xuaW1wb3J0IHsgSHR0cEJhY2tlbmQsIEh0dHBDbGllbnQgfSBmcm9tICdAYW5ndWxhci9jb21tb24vaHR0cCc7XG5pbXBvcnQgeyBJbmplY3QsIEluamVjdGFibGUsIEluamVjdGlvblRva2VuLCBPcHRpb25hbCwgUmVuZGVyZXIyLCBSZW5kZXJlckZhY3RvcnkyLCBTZWN1cml0eUNvbnRleHQgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IERvbVNhbml0aXplciB9IGZyb20gJ0Bhbmd1bGFyL3BsYXRmb3JtLWJyb3dzZXInO1xuaW1wb3J0IHsgb2YsIE9ic2VydmFibGUsIFN1YmplY3QgfSBmcm9tICdyeGpzJztcbmltcG9ydCB7XG4gIGNhdGNoRXJyb3IsXG4gIGZpbHRlcixcbiAgZmluYWxpemUsXG4gIG1hcCxcbiAgc2hhcmUsXG4gIHRha2UsXG4gIHRhcFxufSBmcm9tICdyeGpzL29wZXJhdG9ycyc7XG5pbXBvcnQge1xuICBDYWNoZWRJY29uRGVmaW5pdGlvbixcbiAgSWNvbkRlZmluaXRpb24sXG4gIFRoZW1lVHlwZSxcbiAgVHdvVG9uZUNvbG9yUGFsZXR0ZSxcbiAgVHdvVG9uZUNvbG9yUGFsZXR0ZVNldHRlclxufSBmcm9tICcuLi90eXBlcyc7XG5pbXBvcnQge1xuICBjbG9uZVNWRyxcbiAgZ2V0SWNvbkRlZmluaXRpb25Gcm9tQWJicixcbiAgZ2V0TmFtZUFuZE5hbWVzcGFjZSxcbiAgZ2V0U2Vjb25kYXJ5Q29sb3IsXG4gIGhhc05hbWVzcGFjZSxcbiAgaXNJY29uRGVmaW5pdGlvbixcbiAgcmVwbGFjZUZpbGxDb2xvcixcbiAgd2FybixcbiAgd2l0aFN1ZmZpeCxcbiAgd2l0aFN1ZmZpeEFuZENvbG9yXG59IGZyb20gJy4uL3V0aWxzJztcbmltcG9ydCB7XG4gIER5bmFtaWNMb2FkaW5nVGltZW91dEVycm9yLFxuICBIdHRwTW9kdWxlTm90SW1wb3J0LFxuICBJY29uTm90Rm91bmRFcnJvcixcbiAgTmFtZVNwYWNlSXNOb3RTcGVjaWZ5RXJyb3IsXG4gIFNWR1RhZ05vdEZvdW5kRXJyb3IsXG4gIFVybE5vdFNhZmVFcnJvclxufSBmcm9tICcuL2ljb24uZXJyb3InO1xuXG5jb25zdCBKU09OUF9IQU5ETEVSX05BTUUgPSAnX19hbnRfaWNvbl9sb2FkJztcblxuZXhwb3J0IGNvbnN0IEFOVF9JQ09OUyA9IG5ldyBJbmplY3Rpb25Ub2tlbjxJY29uRGVmaW5pdGlvbltdPignYW50X2ljb25zJyk7XG5cbkBJbmplY3RhYmxlKClcbmV4cG9ydCBjbGFzcyBJY29uU2VydmljZSB7XG4gIGRlZmF1bHRUaGVtZTogVGhlbWVUeXBlID0gJ291dGxpbmUnO1xuXG4gIHNldCB0d29Ub25lQ29sb3Ioe1xuICAgIHByaW1hcnlDb2xvcixcbiAgICBzZWNvbmRhcnlDb2xvclxuICB9OiBUd29Ub25lQ29sb3JQYWxldHRlU2V0dGVyKSB7XG4gICAgdGhpcy5fdHdvVG9uZUNvbG9yUGFsZXR0ZS5wcmltYXJ5Q29sb3IgPSBwcmltYXJ5Q29sb3I7XG4gICAgdGhpcy5fdHdvVG9uZUNvbG9yUGFsZXR0ZS5zZWNvbmRhcnlDb2xvciA9XG4gICAgICBzZWNvbmRhcnlDb2xvciB8fCBnZXRTZWNvbmRhcnlDb2xvcihwcmltYXJ5Q29sb3IpO1xuICB9XG5cbiAgZ2V0IHR3b1RvbmVDb2xvcigpOiBUd29Ub25lQ29sb3JQYWxldHRlU2V0dGVyIHtcbiAgICAvLyBNYWtlIGEgY29weSB0byBhdm9pZCB1bmV4cGVjdGVkIGNoYW5nZXMuXG4gICAgcmV0dXJuIHsgLi4udGhpcy5fdHdvVG9uZUNvbG9yUGFsZXR0ZSB9IGFzIFR3b1RvbmVDb2xvclBhbGV0dGU7XG4gIH1cblxuICBwcm90ZWN0ZWQgX3JlbmRlcmVyOiBSZW5kZXJlcjI7XG4gIHByb3RlY3RlZCBfaHR0cDogSHR0cENsaWVudDtcblxuICAvKipcbiAgICogRGlzYWJsZSBkeW5hbWljIGxvYWRpbmcgKHN1cHBvcnQgc3RhdGljIGxvYWRpbmcgb25seSkuXG4gICAqL1xuICBwcm90ZWN0ZWQgZ2V0IF9kaXNhYmxlRHluYW1pY0xvYWRpbmcoKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG5cbiAgLyoqXG4gICAqIEFsbCBpY29uIGRlZmluaXRpb25zIHdvdWxkIGJlIHJlZ2lzdGVyZWQgaGVyZS5cbiAgICovXG4gIHByb3RlY3RlZCByZWFkb25seSBfc3ZnRGVmaW5pdGlvbnMgPSBuZXcgTWFwPHN0cmluZywgSWNvbkRlZmluaXRpb24+KCk7XG5cbiAgLyoqXG4gICAqIENhY2hlIGFsbCByZW5kZXJlZCBpY29ucy4gSWNvbnMgYXJlIGlkZW50aWZpZWQgYnkgbmFtZSwgdGhlbWUsXG4gICAqIGFuZCBmb3IgdHdvdG9uZSBpY29ucywgcHJpbWFyeSBjb2xvciBhbmQgc2Vjb25kYXJ5IGNvbG9yLlxuICAgKi9cbiAgcHJvdGVjdGVkIHJlYWRvbmx5IF9zdmdSZW5kZXJlZERlZmluaXRpb25zID0gbmV3IE1hcDxzdHJpbmcsIENhY2hlZEljb25EZWZpbml0aW9uPigpO1xuXG4gIHByb3RlY3RlZCBfaW5Qcm9ncmVzc0ZldGNoZXMgPSBuZXcgTWFwPFxuICAgIHN0cmluZyxcbiAgICBPYnNlcnZhYmxlPEljb25EZWZpbml0aW9uIHwgbnVsbD5cbiAgPigpO1xuXG4gIC8qKlxuICAgKiBVcmwgcHJlZml4IGZvciBmZXRjaGluZyBpbmxpbmUgU1ZHIGJ5IGR5bmFtaWMgaW1wb3J0aW5nLlxuICAgKi9cbiAgcHJvdGVjdGVkIF9hc3NldHNVcmxSb290ID0gJyc7XG5cbiAgcHJvdGVjdGVkIF90d29Ub25lQ29sb3JQYWxldHRlOiBUd29Ub25lQ29sb3JQYWxldHRlID0ge1xuICAgIHByaW1hcnlDb2xvcjogJyMzMzMzMzMnLFxuICAgIHNlY29uZGFyeUNvbG9yOiAnI0U2RTZFNidcbiAgfTtcblxuICAvKiogQSBmbGFnIGluZGljYXRlcyB3aGV0aGVyIGpzb25wIGxvYWRpbmcgaXMgZW5hYmxlZC4gKi9cbiAgcHJpdmF0ZSBfZW5hYmxlSnNvbnBMb2FkaW5nID0gZmFsc2U7XG4gIHByaXZhdGUgcmVhZG9ubHkgX2pzb25wSWNvbkxvYWQkID0gbmV3IFN1YmplY3Q8SWNvbkRlZmluaXRpb24+KCk7XG5cbiAgY29uc3RydWN0b3IoXG4gICAgcHJvdGVjdGVkIF9yZW5kZXJlckZhY3Rvcnk6IFJlbmRlcmVyRmFjdG9yeTIsXG4gICAgQE9wdGlvbmFsKCkgcHJvdGVjdGVkIF9oYW5kbGVyOiBIdHRwQmFja2VuZCxcbiAgICBAT3B0aW9uYWwoKSBASW5qZWN0KERPQ1VNRU5UKSBwcm90ZWN0ZWQgX2RvY3VtZW50OiBhbnksXG4gICAgcHJvdGVjdGVkIHNhbml0aXplcjogRG9tU2FuaXRpemVyLFxuXG4gICAgQE9wdGlvbmFsKCkgQEluamVjdChBTlRfSUNPTlMpIHByb3RlY3RlZCBfYW50SWNvbnM6IEljb25EZWZpbml0aW9uW11cbiAgKSB7XG4gICAgdGhpcy5fcmVuZGVyZXIgPSB0aGlzLl9yZW5kZXJlckZhY3RvcnkuY3JlYXRlUmVuZGVyZXIobnVsbCwgbnVsbCk7XG5cbiAgICBpZiAodGhpcy5faGFuZGxlcikge1xuICAgICAgdGhpcy5faHR0cCA9IG5ldyBIdHRwQ2xpZW50KHRoaXMuX2hhbmRsZXIpO1xuICAgIH1cblxuICAgIGlmICh0aGlzLl9hbnRJY29ucykge1xuICAgICAgdGhpcy5hZGRJY29uKC4uLnRoaXMuX2FudEljb25zKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogQ2FsbCB0aGlzIG1ldGhvZCB0byBzd2l0Y2ggdG8ganNvbnAgbGlrZSBsb2FkaW5nLlxuICAgKi9cbiAgdXNlSnNvbnBMb2FkaW5nKCk6IHZvaWQge1xuICAgIGlmICghdGhpcy5fZW5hYmxlSnNvbnBMb2FkaW5nKSB7XG4gICAgICB0aGlzLl9lbmFibGVKc29ucExvYWRpbmcgPSB0cnVlO1xuXG4gICAgICB3aW5kb3dbSlNPTlBfSEFORExFUl9OQU1FXSA9IChpY29uOiBJY29uRGVmaW5pdGlvbikgPT4ge1xuICAgICAgICB0aGlzLl9qc29ucEljb25Mb2FkJC5uZXh0KGljb24pO1xuICAgICAgfTtcbiAgICB9IGVsc2Uge1xuICAgICAgd2FybignWW91IGFyZSBhbHJlYWR5IHVzaW5nIGpzb25wIGxvYWRpbmcuJyk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIENoYW5nZSB0aGUgcHJlZml4IG9mIHRoZSBpbmxpbmUgc3ZnIHJlc291cmNlcywgc28gdGhleSBjb3VsZCBiZSBkZXBsb3llZCBlbHNld2hlcmUsIGxpa2UgQ0ROLlxuICAgKiBAcGFyYW0gcHJlZml4XG4gICAqL1xuICBjaGFuZ2VBc3NldHNTb3VyY2UocHJlZml4OiBzdHJpbmcpOiB2b2lkIHtcbiAgICB0aGlzLl9hc3NldHNVcmxSb290ID0gcHJlZml4LmVuZHNXaXRoKCcvJykgPyBwcmVmaXggOiBwcmVmaXggKyAnLyc7XG4gIH1cblxuICAvKipcbiAgICogQWRkIGljb25zIHByb3ZpZGVkIGJ5IGFudCBkZXNpZ24uXG4gICAqIEBwYXJhbSBpY29uc1xuICAgKi9cbiAgYWRkSWNvbiguLi5pY29uczogSWNvbkRlZmluaXRpb25bXSk6IHZvaWQge1xuICAgIGljb25zLmZvckVhY2goaWNvbiA9PiB7XG4gICAgICB0aGlzLl9zdmdEZWZpbml0aW9ucy5zZXQod2l0aFN1ZmZpeChpY29uLm5hbWUsIGljb24udGhlbWUpLCBpY29uKTtcbiAgICB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZWdpc3RlciBhbiBpY29uLiBOYW1lc3BhY2UgaXMgcmVxdWlyZWQuXG4gICAqIEBwYXJhbSB0eXBlXG4gICAqIEBwYXJhbSBsaXRlcmFsXG4gICAqL1xuICBhZGRJY29uTGl0ZXJhbCh0eXBlOiBzdHJpbmcsIGxpdGVyYWw6IHN0cmluZyk6IHZvaWQge1xuICAgIGNvbnN0IFtfLCBuYW1lc3BhY2VdID0gZ2V0TmFtZUFuZE5hbWVzcGFjZSh0eXBlKTtcbiAgICBpZiAoIW5hbWVzcGFjZSkge1xuICAgICAgdGhyb3cgTmFtZVNwYWNlSXNOb3RTcGVjaWZ5RXJyb3IoKTtcbiAgICB9XG4gICAgdGhpcy5hZGRJY29uKHsgbmFtZTogdHlwZSwgaWNvbjogbGl0ZXJhbCB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZW1vdmUgYWxsIGNhY2hlLlxuICAgKi9cbiAgY2xlYXIoKTogdm9pZCB7XG4gICAgdGhpcy5fc3ZnRGVmaW5pdGlvbnMuY2xlYXIoKTtcbiAgICB0aGlzLl9zdmdSZW5kZXJlZERlZmluaXRpb25zLmNsZWFyKCk7XG4gIH1cblxuICAvKipcbiAgICogR2V0IGEgcmVuZGVyZWQgYFNWR0VsZW1lbnRgLlxuICAgKiBAcGFyYW0gaWNvblxuICAgKiBAcGFyYW0gdHdvVG9uZUNvbG9yXG4gICAqL1xuICBnZXRSZW5kZXJlZENvbnRlbnQoXG4gICAgaWNvbjogSWNvbkRlZmluaXRpb24gfCBzdHJpbmcsXG4gICAgdHdvVG9uZUNvbG9yPzogc3RyaW5nXG4gICk6IE9ic2VydmFibGU8U1ZHRWxlbWVudD4ge1xuICAgIC8vIElmIGBpY29uYCBpcyBhIGBJY29uRGVmaW5pdGlvbmAsIGdvIHRvIHRoZSBuZXh0IHN0ZXAuIElmIG5vdCwgdHJ5IHRvIGZldGNoIGl0IGZyb20gY2FjaGUuXG4gICAgY29uc3QgZGVmaW5pdGlvbjogSWNvbkRlZmluaXRpb24gfCBudWxsID0gaXNJY29uRGVmaW5pdGlvbihpY29uKVxuICAgICAgPyAoaWNvbiBhcyBJY29uRGVmaW5pdGlvbilcbiAgICAgIDogdGhpcy5fc3ZnRGVmaW5pdGlvbnMuZ2V0KGljb24pIHx8IG51bGw7XG4gICAgXG4gICAgaWYgKCFkZWZpbml0aW9uICYmIHRoaXMuX2Rpc2FibGVEeW5hbWljTG9hZGluZykge1xuICAgICAgdGhyb3cgSWNvbk5vdEZvdW5kRXJyb3IoaWNvbiBhcyBzdHJpbmcpO1xuICAgIH1cblxuICAgIC8vIElmIGBpY29uYCBpcyBhIGBJY29uRGVmaW5pdGlvbmAgb2Ygc3VjY2Vzc2Z1bGx5IGZldGNoLCB3cmFwIGl0IGluIGFuIGBPYnNlcnZhYmxlYC5cbiAgICAvLyBPdGhlcndpc2UgdHJ5IHRvIGZldGNoIGl0IGZyb20gcmVtb3RlLlxuICAgIGNvbnN0ICRpY29uRGVmaW5pdGlvbiA9IGRlZmluaXRpb25cbiAgICAgID8gb2YoZGVmaW5pdGlvbilcbiAgICAgIDogdGhpcy5fbG9hZEljb25EeW5hbWljYWxseShpY29uIGFzIHN0cmluZyk7XG5cbiAgICAvLyBJZiBmaW5hbGx5IGdldCBhbiBgSWNvbkRlZmluaXRpb25gLCByZW5kZXIgYW5kIHJldHVybiBpdC4gT3RoZXJ3aXNlIHRocm93IGFuIGVycm9yLlxuICAgIHJldHVybiAkaWNvbkRlZmluaXRpb24ucGlwZShcbiAgICAgIG1hcChpID0+IHtcbiAgICAgICAgaWYgKCFpKSB7XG4gICAgICAgICAgdGhyb3cgSWNvbk5vdEZvdW5kRXJyb3IoaWNvbiBhcyBzdHJpbmcpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0aGlzLl9sb2FkU1ZHRnJvbUNhY2hlT3JDcmVhdGVOZXcoaSwgdHdvVG9uZUNvbG9yKTtcbiAgICAgIH0pXG4gICAgKTtcbiAgfVxuXG4gIGdldENhY2hlZEljb25zKCk6IE1hcDxzdHJpbmcsIEljb25EZWZpbml0aW9uPiB7XG4gICAgcmV0dXJuIHRoaXMuX3N2Z0RlZmluaXRpb25zO1xuICB9XG5cbiAgLyoqXG4gICAqIEdldCByYXcgc3ZnIGFuZCBhc3NlbWJsZSBhIGBJY29uRGVmaW5pdGlvbmAgb2JqZWN0LlxuICAgKiBAcGFyYW0gdHlwZVxuICAgKi9cbiAgcHJvdGVjdGVkIF9sb2FkSWNvbkR5bmFtaWNhbGx5KFxuICAgIHR5cGU6IHN0cmluZ1xuICApOiBPYnNlcnZhYmxlPEljb25EZWZpbml0aW9uIHwgbnVsbD4ge1xuICAgIC8vIElmIGRldmVsb3BlciBkb2Vzbid0IHByb3ZpZGUgSFRUUCBtb2R1bGUgbm9yIGVuYWJsZSBqc29ucCBsb2FkaW5nLCBqdXN0IHRocm93IGFuIGVycm9yLlxuICAgIGlmICghdGhpcy5faHR0cCAmJiAhdGhpcy5fZW5hYmxlSnNvbnBMb2FkaW5nKSB7XG4gICAgICByZXR1cm4gb2YoSHR0cE1vZHVsZU5vdEltcG9ydCgpKTtcbiAgICB9XG5cbiAgICAvLyBJZiBtdWx0aSBkaXJlY3RpdmUgYXNrIGZvciB0aGUgc2FtZSBpY29uIGF0IHRoZSBzYW1lIHRpbWUsXG4gICAgLy8gcmVxdWVzdCBzaG91bGQgb25seSBiZSBmaXJlZCBvbmNlLlxuICAgIGxldCBpblByb2dyZXNzID0gdGhpcy5faW5Qcm9ncmVzc0ZldGNoZXMuZ2V0KHR5cGUpO1xuXG4gICAgaWYgKCFpblByb2dyZXNzKSB7XG4gICAgICBjb25zdCBbbmFtZSwgbmFtZXNwYWNlXSA9IGdldE5hbWVBbmROYW1lc3BhY2UodHlwZSk7XG5cbiAgICAgIC8vIElmIHRoZSBzdHJpbmcgaGFzIGEgbmFtZXNwYWNlIHdpdGhpbiwgY3JlYXRlIGEgc2ltcGxlIGBJY29uRGVmaW5pdGlvbmAuXG4gICAgICBjb25zdCBpY29uOiBJY29uRGVmaW5pdGlvbiA9IG5hbWVzcGFjZVxuICAgICAgICA/IHsgbmFtZTogdHlwZSwgaWNvbjogJycgfVxuICAgICAgICA6IGdldEljb25EZWZpbml0aW9uRnJvbUFiYnIobmFtZSk7XG5cbiAgICAgIGNvbnN0IHN1ZmZpeCA9IHRoaXMuX2VuYWJsZUpzb25wTG9hZGluZyA/ICcuanMnIDogJy5zdmcnO1xuICAgICAgY29uc3QgdXJsID1cbiAgICAgICAgKG5hbWVzcGFjZVxuICAgICAgICAgID8gYCR7dGhpcy5fYXNzZXRzVXJsUm9vdH1hc3NldHMvJHtuYW1lc3BhY2V9LyR7bmFtZX1gXG4gICAgICAgICAgOiBgJHt0aGlzLl9hc3NldHNVcmxSb290fWFzc2V0cy8ke2ljb24udGhlbWV9LyR7aWNvbi5uYW1lfWApICsgc3VmZml4O1xuXG4gICAgICBjb25zdCBzYWZlVXJsID0gdGhpcy5zYW5pdGl6ZXIuc2FuaXRpemUoU2VjdXJpdHlDb250ZXh0LlVSTCwgdXJsKTtcblxuICAgICAgaWYgKCFzYWZlVXJsKSB7XG4gICAgICAgIHRocm93IFVybE5vdFNhZmVFcnJvcih1cmwpO1xuICAgICAgfVxuXG4gICAgICBjb25zdCBzb3VyY2UgPSAhdGhpcy5fZW5hYmxlSnNvbnBMb2FkaW5nXG4gICAgICAgID8gdGhpcy5faHR0cFxuICAgICAgICAgICAgLmdldChzYWZlVXJsLCB7IHJlc3BvbnNlVHlwZTogJ3RleHQnIH0pXG4gICAgICAgICAgICAucGlwZShtYXAobGl0ZXJhbCA9PiAoeyAuLi5pY29uLCBpY29uOiBsaXRlcmFsIH0pKSlcbiAgICAgICAgOiB0aGlzLl9sb2FkSWNvbkR5bmFtaWNhbGx5V2l0aEpzb25wKGljb24sIHNhZmVVcmwpO1xuXG4gICAgICBpblByb2dyZXNzID0gc291cmNlLnBpcGUoXG4gICAgICAgIHRhcChkZWZpbml0aW9uID0+IHRoaXMuYWRkSWNvbihkZWZpbml0aW9uKSksXG4gICAgICAgIGZpbmFsaXplKCgpID0+IHRoaXMuX2luUHJvZ3Jlc3NGZXRjaGVzLmRlbGV0ZSh0eXBlKSksXG4gICAgICAgIGNhdGNoRXJyb3IoKCkgPT4gb2YobnVsbCkpLFxuICAgICAgICBzaGFyZSgpXG4gICAgICApO1xuXG4gICAgICB0aGlzLl9pblByb2dyZXNzRmV0Y2hlcy5zZXQodHlwZSwgaW5Qcm9ncmVzcyk7XG4gICAgfVxuXG4gICAgcmV0dXJuIGluUHJvZ3Jlc3M7XG4gIH1cblxuICBwcm90ZWN0ZWQgX2xvYWRJY29uRHluYW1pY2FsbHlXaXRoSnNvbnAoaWNvbjogSWNvbkRlZmluaXRpb24sIHVybDogc3RyaW5nKTogT2JzZXJ2YWJsZTxJY29uRGVmaW5pdGlvbj4ge1xuICAgIHJldHVybiBuZXcgT2JzZXJ2YWJsZTxJY29uRGVmaW5pdGlvbj4oc3Vic2NyaWJlciA9PiB7XG4gICAgICBjb25zdCBsb2FkZXIgPSB0aGlzLl9kb2N1bWVudC5jcmVhdGVFbGVtZW50KCdzY3JpcHQnKTtcbiAgICAgIGNvbnN0IHRpbWVyID0gc2V0VGltZW91dCgoKSA9PiB7XG4gICAgICAgIGNsZWFuKCk7XG4gICAgICAgIHN1YnNjcmliZXIuZXJyb3IoRHluYW1pY0xvYWRpbmdUaW1lb3V0RXJyb3IoKSk7XG4gICAgICB9LCA2MDAwKTtcblxuICAgICAgbG9hZGVyLnNyYyA9IHVybDtcblxuICAgICAgZnVuY3Rpb24gY2xlYW4oKTogdm9pZCB7XG4gICAgICAgIGxvYWRlci5wYXJlbnROb2RlLnJlbW92ZUNoaWxkKGxvYWRlcik7XG4gICAgICAgIGNsZWFyVGltZW91dCh0aW1lcik7XG4gICAgICB9XG5cbiAgICAgIHRoaXMuX2RvY3VtZW50LmJvZHkuYXBwZW5kQ2hpbGQobG9hZGVyKTtcbiAgICAgIHRoaXMuX2pzb25wSWNvbkxvYWQkXG4gICAgICAgICAgLnBpcGUoXG4gICAgICAgICAgICAgIGZpbHRlcihpID0+IGkubmFtZSA9PT0gaWNvbi5uYW1lICYmIGkudGhlbWUgPT09IGljb24udGhlbWUpLFxuICAgICAgICAgICAgICB0YWtlKDEpXG4gICAgICAgICAgKVxuICAgICAgICAgIC5zdWJzY3JpYmUoaSA9PiB7XG4gICAgICAgICAgICBzdWJzY3JpYmVyLm5leHQoaSk7XG4gICAgICAgICAgICBjbGVhbigpO1xuICAgICAgICAgIH0pO1xuICAgIH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIFJlbmRlciBhIG5ldyBgU1ZHRWxlbWVudGAgZm9yIGEgZ2l2ZW4gYEljb25EZWZpbml0aW9uYCwgb3IgbWFrZSBhIGNvcHkgZnJvbSBjYWNoZS5cbiAgICogQHBhcmFtIGljb25cbiAgICogQHBhcmFtIHR3b1RvbmVDb2xvclxuICAgKi9cbiAgcHJvdGVjdGVkIF9sb2FkU1ZHRnJvbUNhY2hlT3JDcmVhdGVOZXcoXG4gICAgaWNvbjogSWNvbkRlZmluaXRpb24sXG4gICAgdHdvVG9uZUNvbG9yPzogc3RyaW5nXG4gICk6IFNWR0VsZW1lbnQge1xuICAgIGxldCBzdmc6IFNWR0VsZW1lbnQ7XG5cbiAgICBjb25zdCBwcmkgPSB0d29Ub25lQ29sb3IgfHwgdGhpcy5fdHdvVG9uZUNvbG9yUGFsZXR0ZS5wcmltYXJ5Q29sb3I7XG4gICAgY29uc3Qgc2VjID1cbiAgICAgIGdldFNlY29uZGFyeUNvbG9yKHByaSkgfHwgdGhpcy5fdHdvVG9uZUNvbG9yUGFsZXR0ZS5zZWNvbmRhcnlDb2xvcjtcbiAgICBjb25zdCBrZXkgPVxuICAgICAgaWNvbi50aGVtZSA9PT0gJ3R3b3RvbmUnXG4gICAgICAgID8gd2l0aFN1ZmZpeEFuZENvbG9yKGljb24ubmFtZSwgaWNvbi50aGVtZSwgcHJpLCBzZWMpXG4gICAgICAgIDogaWNvbi50aGVtZSA9PT0gdW5kZWZpbmVkXG4gICAgICAgID8gaWNvbi5uYW1lXG4gICAgICAgIDogd2l0aFN1ZmZpeChpY29uLm5hbWUsIGljb24udGhlbWUpO1xuXG4gICAgLy8gVHJ5IHRvIG1ha2UgYSBjb3B5IGZyb20gY2FjaGUuXG4gICAgY29uc3QgY2FjaGVkID0gdGhpcy5fc3ZnUmVuZGVyZWREZWZpbml0aW9ucy5nZXQoa2V5KTtcblxuICAgIGlmIChjYWNoZWQpIHtcbiAgICAgIHN2ZyA9IGNhY2hlZC5pY29uO1xuICAgIH0gZWxzZSB7XG4gICAgICBzdmcgPSB0aGlzLl9zZXRTVkdBdHRyaWJ1dGUoXG4gICAgICAgIHRoaXMuX2NvbG9yaXplU1ZHSWNvbihcbiAgICAgICAgICAvLyBJY29ucyBwcm92aWRlZCBieSBhbnQgZGVzaWduIHNob3VsZCBiZSByZWZpbmVkIHRvIHJlbW92ZSBwcmVzZXQgY29sb3JzLlxuICAgICAgICAgIHRoaXMuX2NyZWF0ZVNWR0VsZW1lbnRGcm9tU3RyaW5nKFxuICAgICAgICAgICAgaGFzTmFtZXNwYWNlKGljb24ubmFtZSkgPyBpY29uLmljb24gOiByZXBsYWNlRmlsbENvbG9yKGljb24uaWNvbilcbiAgICAgICAgICApLFxuICAgICAgICAgIGljb24udGhlbWUgPT09ICd0d290b25lJyxcbiAgICAgICAgICBwcmksXG4gICAgICAgICAgc2VjXG4gICAgICAgIClcbiAgICAgICk7XG4gICAgICAvLyBDYWNoZSBpdC5cbiAgICAgIHRoaXMuX3N2Z1JlbmRlcmVkRGVmaW5pdGlvbnMuc2V0KGtleSwge1xuICAgICAgICAuLi5pY29uLFxuICAgICAgICBpY29uOiBzdmdcbiAgICAgIH0gYXMgQ2FjaGVkSWNvbkRlZmluaXRpb24pO1xuICAgIH1cblxuICAgIHJldHVybiBjbG9uZVNWRyhzdmcpO1xuICB9XG5cbiAgcHJvdGVjdGVkIF9jcmVhdGVTVkdFbGVtZW50RnJvbVN0cmluZyhzdHI6IHN0cmluZyk6IFNWR0VsZW1lbnQge1xuICAgIGNvbnN0IGRpdiA9IHRoaXMuX2RvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2RpdicpO1xuICAgIGRpdi5pbm5lckhUTUwgPSBzdHI7XG4gICAgY29uc3Qgc3ZnOiBTVkdFbGVtZW50ID0gZGl2LnF1ZXJ5U2VsZWN0b3IoJ3N2ZycpO1xuICAgIGlmICghc3ZnKSB7XG4gICAgICB0aHJvdyBTVkdUYWdOb3RGb3VuZEVycm9yO1xuICAgIH1cbiAgICByZXR1cm4gc3ZnO1xuICB9XG5cbiAgcHJvdGVjdGVkIF9zZXRTVkdBdHRyaWJ1dGUoc3ZnOiBTVkdFbGVtZW50KTogU1ZHRWxlbWVudCB7XG4gICAgdGhpcy5fcmVuZGVyZXIuc2V0QXR0cmlidXRlKHN2ZywgJ3dpZHRoJywgJzFlbScpO1xuICAgIHRoaXMuX3JlbmRlcmVyLnNldEF0dHJpYnV0ZShzdmcsICdoZWlnaHQnLCAnMWVtJyk7XG4gICAgcmV0dXJuIHN2ZztcbiAgfVxuXG4gIHByb3RlY3RlZCBfY29sb3JpemVTVkdJY29uKFxuICAgIHN2ZzogU1ZHRWxlbWVudCxcbiAgICB0d290b25lOiBib29sZWFuLFxuICAgIHByaTogc3RyaW5nLFxuICAgIHNlYzogc3RyaW5nXG4gICk6IFNWR0VsZW1lbnQge1xuICAgIGlmICh0d290b25lKSB7XG4gICAgICBjb25zdCBjaGlsZHJlbiA9IHN2Zy5jaGlsZE5vZGVzO1xuICAgICAgY29uc3QgbGVuZ3RoID0gY2hpbGRyZW4ubGVuZ3RoO1xuICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBsZW5ndGg7IGkrKykge1xuICAgICAgICBjb25zdCBjaGlsZDogSFRNTEVsZW1lbnQgPSBjaGlsZHJlbltpXSBhcyBIVE1MRWxlbWVudDtcbiAgICAgICAgaWYgKGNoaWxkLmdldEF0dHJpYnV0ZSgnZmlsbCcpID09PSAnc2Vjb25kYXJ5Q29sb3InKSB7XG4gICAgICAgICAgdGhpcy5fcmVuZGVyZXIuc2V0QXR0cmlidXRlKGNoaWxkLCAnZmlsbCcsIHNlYyk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgdGhpcy5fcmVuZGVyZXIuc2V0QXR0cmlidXRlKGNoaWxkLCAnZmlsbCcsIHByaSk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG4gICAgdGhpcy5fcmVuZGVyZXIuc2V0QXR0cmlidXRlKHN2ZywgJ2ZpbGwnLCAnY3VycmVudENvbG9yJyk7XG4gICAgcmV0dXJuIHN2ZztcbiAgfVxufVxuIl19