UNPKG

35.3 kBJavaScriptView Raw
1var UIRouterUpgradeModule_1;
2import * as tslib_1 from "tslib";
3import { Component, ElementRef, Inject, Injector, Input, ModuleWithProviders, NgModule } from '@angular/core';
4import { downgradeComponent, UpgradeModule, getAngularJSGlobal, getAngularLib } from '@angular/upgrade/static';
5import { StateObject, forEach, PathNode, Resolvable, StateRegistry, UIRouter, ViewConfig, ViewService, } from '@uirouter/core';
6import { applyModuleConfig, NATIVE_INJECTOR_TOKEN, ng2LazyLoadBuilder, Ng2ViewConfig, UIView, _UIROUTER_SERVICE_PROVIDERS, UIROUTER_MODULE_TOKEN, UIROUTER_ROOT_MODULE, UIRouterModule, makeChildProviders, } from '@uirouter/angular';
7import { Ng1ViewConfig } from '@uirouter/angularjs';
8import { UIRouterRx } from '@uirouter/rx';
9const getAngularJS = getAngularJSGlobal || getAngularLib;
10const angular = getAngularJS();
11if (!angular) {
12 throw new Error('AngularJS not found on window. https://github.com/ui-router/angular-hybrid/wiki/AngularJS-not-found-on-window');
13}
14/**
15 * Create a ng1 module for the ng1 half of the hybrid application to depend on.
16 *
17 * Example:
18 * const myApp = angular.module('myApp', ['ui.router.upgrade']);
19 */
20export const upgradeModule = angular.module('ui.router.upgrade', ['ui.router']);
21export function objectFactory() {
22 return {};
23}
24/**
25 * UIViewNgUpgrade is a component bridge from ng1 ui-view to ng2 ui-view
26 *
27 * When a ui-router for ng1 is registering a state it checks if a view's
28 * `component:` is an ng2 Component class. If so, it creates a special ng1 template
29 * which references this component, i.e., <ui-view-ng-upgrade></ui-view-ng-upgrade>
30 *
31 * See that code by searching ng1-to-ng2 source for: "$stateProvider.decorator"
32 *
33 * ---
34 *
35 * ng1-to-ng2 component bridge process:
36 *
37 * 1)
38 * When an ng1 template creates a ui-view which is targeted by a ng2 Component,
39 *
40 * ```
41 * <a ui-sref="foo">Go to foo</a>
42 * <div ui-view> <!-- ui-view created in ng1 template -->
43 * </div> <!-- targeted with { component: Ng2RoutedComponent } -->
44 * ```
45 *
46 * the state decorator spits out a custom template. That template loads this
47 * ng2 Component adapter as a downgraded-to-ng1 directive.
48 *
49 * ```
50 * <a ui-sref="foo">Go to foo</a>
51 * <div ui-view> <!-- decorated template references the downgraded component -->
52 * <ui-view-ng-upgrade> <!-- downgraded adapter component -->
53 * </ui-view-ng-upgrade>
54 * </div>
55 * ```
56 *
57 * This downgraded ng2 Component then creates a child UIView (ng2 component)
58 *
59 * ```
60 * <a ui-sref="foo">Go to foo</a>
61 * <div ui-view> <!-- custom template references the downgraded component -->
62 * <ui-view-ng-upgrade> <!-- ng2 component adapter downgraded to ng1-->
63 * <ui-view> <!-- pure ng2 ui-view -->
64 * </ui-view>
65 * </ui-view-ng-upgrade>
66 * </div>
67 * ```
68 *
69 * which in turn is filled with the routed ng2 component.
70 *
71 * ```
72 * <a ui-sref="foo">Go to foo</a>
73 * <div ui-view> <!-- ng1 ui-view -->
74 * <ui-view-ng-upgrade> <!-- ng2 component adapter (downgraded to ng1)-->
75 * <ui-view> <!-- pure ng2 ui-view -->
76 * <ng2-routed-component> <!-- ng2 component hosted in ng2 ui-view -->
77 * <h1>ng2 routed component contents</h1>
78 * </ng2-routed-component>
79 * </ui-view>
80 * </ui-view-ng-upgrade>
81 * </div>
82 * ```
83 *
84 * This adapter exposes exposes the parent view context (ParentUIViewInject)
85 * as an ng2 DI Provider, which the nested ng2 UIView requires.
86 *
87 * It gets the ParentUIViewContext information (from the parent ng1 ui-view) by walking
88 * up the DOM and grabbing the .data('$uiView') which the ng1 ui-view directive exposes.
89 */
90let UIViewNgUpgrade = class UIViewNgUpgrade {
91 constructor(ref, parent, registry // access the root state
92 ) {
93 // From the ui-view-ng-upgrade component's element ref, walk up the DOM two elements...
94 // There will first be an ng1 ui-view which hosts this element, and then that ui-view's parent element.
95 // That (parent) element has access to the proper "parent viewcontext"
96 // The ng2 ui-view component is inside this ui-view-ng-upgrade directive, which is inside the ng1 "host" ui-view.
97 // Both ui-views share the same "view context" information (the view's fqn and created-by-state context information)
98 const ng1elem = angular
99 .element(ref.nativeElement)
100 .parent()
101 .parent();
102 // Expose getters on PARENT_INJECT for context (creation state) and fqn (view address)
103 // These will be used by further nested UIView
104 Object.defineProperty(parent, 'context', {
105 get: function () {
106 const data = ng1elem['inheritedData']('$uiView');
107 return data && data.$cfg ? data.$cfg.viewDecl.$context : registry.root();
108 },
109 enumerable: true,
110 });
111 Object.defineProperty(parent, 'fqn', {
112 get: function () {
113 const data = ng1elem['inheritedData']('$uiView');
114 return data && data.$uiView ? data.$uiView.fqn : null;
115 },
116 enumerable: true,
117 });
118 }
119};
120UIViewNgUpgrade.ctorParameters = () => [
121 { type: ElementRef },
122 { type: undefined, decorators: [{ type: Inject, args: [UIView.PARENT_INJECT,] }] },
123 { type: StateRegistry // access the root state
124 }
125];
126tslib_1.__decorate([
127 Input()
128], UIViewNgUpgrade.prototype, "name", void 0);
129UIViewNgUpgrade = tslib_1.__decorate([
130 Component({
131 selector: 'ui-view-ng-upgrade',
132 template: `
133 <ui-view [name]="name"></ui-view>
134 `,
135 // provide a blank object as PARENT_INJECT.
136 // The component will add property getters when it is constructed.
137 viewProviders: [{ provide: UIView.PARENT_INJECT, useFactory: objectFactory }]
138 }),
139 tslib_1.__param(1, Inject(UIView.PARENT_INJECT))
140], UIViewNgUpgrade);
141export { UIViewNgUpgrade };
142/**********************************
143 * Ng2 @NgModule and bootstrap code
144 **********************************/
145// Register the ng1 DI '$uiRouter' object as an ng2 Provider.
146export function uiRouterUpgradeFactory(router, injector) {
147 const modules = injector.get(UIROUTER_MODULE_TOKEN, []);
148 modules.forEach(module => applyModuleConfig(router, injector, module));
149 return router;
150}
151export function getUIRouter($injector) {
152 return $injector.get('$uiRouter');
153}
154export function getParentUIViewInject(r) {
155 return { fqn: null, context: r.root() };
156}
157const ɵ0 = {};
158/**
159 * This NgModule should be added to the root module of the hybrid app.
160 */
161let UIRouterUpgradeModule = UIRouterUpgradeModule_1 = class UIRouterUpgradeModule {
162 static forRoot(module = {}) {
163 return {
164 ngModule: UIRouterUpgradeModule_1,
165 providers: makeChildProviders(module),
166 };
167 }
168 static forChild(module = {}) {
169 return {
170 ngModule: UIRouterModule,
171 providers: makeChildProviders(module),
172 };
173 }
174};
175UIRouterUpgradeModule = UIRouterUpgradeModule_1 = tslib_1.__decorate([
176 NgModule({
177 imports: [UIRouterModule, UpgradeModule],
178 declarations: [UIViewNgUpgrade],
179 providers: [
180 // @uirouter/angular code will use the ng1 $uiRouter instance instead of creating its own.
181 { provide: '$uiRouter', useFactory: getUIRouter, deps: ['$injector'] },
182 { provide: UIRouter, useFactory: uiRouterUpgradeFactory, deps: ['$uiRouter', Injector] },
183 { provide: UIROUTER_ROOT_MODULE, useValue: ɵ0, multi: true },
184 { provide: UIView.PARENT_INJECT, useFactory: getParentUIViewInject, deps: [StateRegistry] },
185 ..._UIROUTER_SERVICE_PROVIDERS,
186 ],
187 entryComponents: [UIViewNgUpgrade],
188 exports: [UIViewNgUpgrade, UIRouterModule],
189 })
190], UIRouterUpgradeModule);
191export { UIRouterUpgradeModule };
192// Downgrade the UIViewNgUpgrade ng2 Component to an ng1 directive.
193// The directive is used in a (generated) view template by the (host) ng1 ui-router,
194// whenever it finds a view configured with a `component: <Ng2ComponentClass>`
195upgradeModule.directive('uiViewNgUpgrade', downgradeComponent({
196 component: UIViewNgUpgrade,
197 inputs: ['name'],
198}));
199upgradeModule.run([
200 '$injector',
201 (ng1Injector) => {
202 const $uiRouter = ng1Injector.get('$uiRouter');
203 /** Add support for observable state and param changes */
204 $uiRouter.plugin(UIRouterRx);
205 // Expose a merged ng1/ng2 injector as a Resolvable (on the root state).
206 // This mimics how ui-router-ng2 exposes the root ng2 Injector, but
207 // it retrieves from ng1 injector first, then ng2 injector if the token isn't found.
208 const mergedInjector = {
209 get: function (token, ng2NotFoundValue) {
210 const ng2Injector = ng1Injector.get('$$angularInjector');
211 if (ng1Injector.has(token)) {
212 return ng1Injector.get(token);
213 }
214 return ng2Injector.get(token, ng2NotFoundValue);
215 },
216 };
217 const ng2InjectorResolvable = Resolvable.fromData(NATIVE_INJECTOR_TOKEN, mergedInjector);
218 $uiRouter.stateRegistry.root().resolvables.push(ng2InjectorResolvable);
219 },
220]);
221/** Adds support for `loadChildren`: Angular NgModule lazy loading via @gntools/webpack */
222upgradeModule.config([
223 '$stateRegistryProvider',
224 ($stateRegistry) => {
225 $stateRegistry.decorator('lazyLoad', ng2LazyLoadBuilder);
226 },
227]);
228/**
229 * Define a stateProvider `views` builder decorator.
230 * The decorator first applies the standard views builder function.
231 * Then it finds any view components which are **actually** a Ng2 Component Class.
232 * It overwrites that view's config with a ng1-to-ng2 hybrid config.
233 *
234 * In place of the template provider, it simply puts a <ui-view-ng-upgrade/> component
235 * which that provides a ng1 -> ng2 boundary in the component tree.
236 */
237upgradeModule.config([
238 '$stateRegistryProvider',
239 ($stateRegistry) => {
240 $stateRegistry.decorator('views', function (state, parentFn) {
241 const views = parentFn(state);
242 forEach(views, (viewDecl, viewName) => {
243 if (viewDecl.$type === 'ng1-to-ng2' || typeof viewDecl.component === 'function') {
244 // Update the view config.
245 // Override default ng1 `component:` behavior (of defining a templateProvider)
246 // with a <ui-view-ng-upgrade> adapter directive template
247 viewDecl.$type = 'ng1-to-ng2';
248 viewDecl.templateProvider = null;
249 viewDecl.template = `<ui-view-ng-upgrade name='${viewDecl.$uiViewName}'></ui-view-ng-upgrade>`;
250 }
251 });
252 return views;
253 });
254 },
255]);
256// UI-Router ViewConfig factories take a view declaration object from a state.views: { foo: <ViewDeclaration> }
257// and return a runtime config object (a ViewConfig)
258upgradeModule.run([
259 '$view',
260 '$templateFactory',
261 ($view, $templateFactory) => {
262 // Register a ViewConfig factory for views of type `ng2`
263 $view._pluginapi._viewConfigFactory('ng2', (path, config) => new Ng2ViewConfig(path, config));
264 // Register a ViewConfig factory for views of type `ng1-to-ng2`.
265 // Returns both an ng1 config and an ng2 config allowing either ng1 or ng2 ui-view components to be targeted.
266 $view._pluginapi._viewConfigFactory('ng1-to-ng2', (path, config) => {
267 const ng1ViewConfig = (new Ng1ViewConfig(path, Object.assign({}, config, { $type: 'ng1' }), $templateFactory));
268 const ng2ViewConfig = (new Ng2ViewConfig(path, Object.assign({}, config, { $type: 'ng2' })));
269 return [ng2ViewConfig, ng1ViewConfig];
270 });
271 },
272]);
273export { ɵ0 };
274//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYW5ndWxhci1oeWJyaWQuanMiLCJzb3VyY2VSb290Ijoibmc6Ly9AdWlyb3V0ZXIvYW5ndWxhci1oeWJyaWQvIiwic291cmNlcyI6WyJhbmd1bGFyLWh5YnJpZC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOztBQUFBLE9BQU8sRUFBRSxTQUFTLEVBQUUsVUFBVSxFQUFFLE1BQU0sRUFBRSxRQUFRLEVBQUUsS0FBSyxFQUFFLG1CQUFtQixFQUFFLFFBQVEsRUFBRSxNQUFNLGVBQWUsQ0FBQztBQUM5RyxPQUFPLEVBQUUsa0JBQWtCLEVBQUUsYUFBYSxFQUFFLGtCQUFrQixFQUFFLGFBQWEsRUFBRSxNQUFNLHlCQUF5QixDQUFDO0FBRS9HLE9BQU8sRUFDTCxXQUFXLEVBQ1gsT0FBTyxFQUNQLFFBQVEsRUFDUixVQUFVLEVBQ1YsYUFBYSxFQUNiLFFBQVEsRUFDUixVQUFVLEVBQ1YsV0FBVyxHQUNaLE1BQU0sZ0JBQWdCLENBQUM7QUFFeEIsT0FBTyxFQUNMLGlCQUFpQixFQUNqQixxQkFBcUIsRUFDckIsa0JBQWtCLEVBQ2xCLGFBQWEsRUFDYixNQUFNLEVBQ04sMkJBQTJCLEVBSTNCLHFCQUFxQixFQUNyQixvQkFBb0IsRUFDcEIsY0FBYyxFQUNkLGtCQUFrQixHQUNuQixNQUFNLG1CQUFtQixDQUFDO0FBRTNCLE9BQU8sRUFBaUIsYUFBYSxFQUFFLE1BQU0scUJBQXFCLENBQUM7QUFFbkUsT0FBTyxFQUFFLFVBQVUsRUFBRSxNQUFNLGNBQWMsQ0FBQztBQUcxQyxNQUFNLFlBQVksR0FBRyxrQkFBa0IsSUFBSSxhQUFhLENBQUM7QUFDekQsTUFBTSxPQUFPLEdBQUcsWUFBWSxFQUFFLENBQUM7QUFFL0IsSUFBSSxDQUFDLE9BQU8sRUFBRTtJQUNaLE1BQU0sSUFBSSxLQUFLLENBQ2IsZ0hBQWdILENBQ2pILENBQUM7Q0FDSDtBQUVEOzs7OztHQUtHO0FBQ0gsTUFBTSxDQUFDLE1BQU0sYUFBYSxHQUFHLE9BQU8sQ0FBQyxNQUFNLENBQUMsbUJBQW1CLEVB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RCxLQUFLLENBQUMsVUFBVSxDQUFDLGtCQUFrQixDQUNqQyxLQUFLLEVBQ0wsQ0FBQyxJQUFnQixFQUFFLE1BQTBCLEVBQUUsRUFBRSxDQUFDLElBQUksYUFBYSxDQUFDLElBQUksRUFBRSxNQUFNLENBQUMsQ0FDbEYsQ0FBQztRQUVGLGdFQUFnRTtRQUNoRSw2R0FBNkc7UUFDN0csS0FBSyxDQUFDLFVBQVUsQ0FBQyxrQkFBa0IsQ0FBQyxZQUFZLEVBQUUsQ0FBQyxJQUFnQixFQUFFLE1BQTBCLEVBQUUsRUFBRTtZQUNqRyxNQUFNLGFBQWEsR0FBb0IsQ0FDckMsSUFBSSxhQUFhLENBQU0sSUFBSSxFQUFPLE1BQU0sQ0FBQyxNQUFNLENBQUMsRUFBRSxFQUFFLE1BQU0sRUFBRSxFQUFFLEtBQUssRUFBRSxLQUFLLEVBQUUsQ0FBQyxFQUFFLGdCQUFnQixDQUFDLENBQ2pHLENBQUM7WUFDRixNQUFNLGFBQWEsR0FBb0IsQ0FDckMsSUFBSSxhQUFhLENBQU0sSUFBSSxFQUFPLE1BQU0sQ0FBQyxNQUFNLENBQUMsRUFBRSxFQUFFLE1BQU0sRUFBRSxFQUFFLEtBQUssRUFBRSxLQUFLLEVBQUUsQ0FBQyxDQUFDLENBQy9FLENBQUM7WUFFRixPQUFPLENBQUMsYUFBYSxFQUFFLGFBQWEsQ0FBQyxDQUFDO1FBQ3hDLENBQUMsQ0FBQyxDQUFDO0lBQ0wsQ0FBQztDQUNGLENBQUMsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IENvbXBvbmVudCwgRWxlbWVudFJlZiwgSW5qZWN0LCBJbmplY3RvciwgSW5wdXQsIE1vZHVsZVdpdGhQcm92aWRlcnMsIE5nTW9kdWxlIH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgeyBkb3duZ3JhZGVDb21wb25lbnQsIFVwZ3JhZGVNb2R1bGUsIGdldEFuZ3VsYXJKU0dsb2JhbCwgZ2V0QW5ndWxhckxpYiB9IGZyb20gJ0Bhbmd1bGFyL3VwZ3JhZGUvc3RhdGljJztcblxuaW1wb3J0IHtcbiAgU3RhdGVPYmplY3QsXG4gIGZvckVhY2gsXG4gIFBhdGhOb2RlLFxuICBSZXNvbHZhYmxlLFxuICBTdGF0ZVJlZ2lzdHJ5LFxuICBVSVJvdXRlcixcbiAgVmlld0NvbmZpZyxcbiAgVmlld1NlcnZpY2UsXG59IGZyb20gJ0B1aXJvdXRlci9jb3JlJztcblxuaW1wb3J0IHtcbiAgYXBwbHlNb2R1bGVDb25maWcsXG4gIE5BVElWRV9JTkpFQ1RPUl9UT0tFTixcbiAgbmcyTGF6eUxvYWRCdWlsZGVyLFxuICBOZzJWaWV3Q29uZmlnLFxuICBVSVZpZXcsXG4gIF9VSVJPVVRFUl9TRVJWSUNFX1BST1ZJREVSUyxcbiAgTmcyVmlld0RlY2xhcmF0aW9uLFxuICBQYXJlbnRVSVZpZXdJbmplY3QsXG4gIFN0YXRlc01vZHVsZSxcbiAgVUlST1VURVJfTU9EVUxFX1RPS0VOLFxuICBVSVJPVVRFUl9ST09UX01PRFVMRSxcbiAgVUlSb3V0ZXJNb2R1bGUsXG4gIG1ha2VDaGlsZFByb3ZpZGVycyxcbn0gZnJvbSAnQHVpcm91dGVyL2FuZ3VsYXInO1xuXG5pbXBvcnQgeyAkSW5qZWN0b3JMaWtlLCBOZzFWaWV3Q29uZmlnIH0gZnJvbSAnQHVpcm91dGVyL2FuZ3VsYXJqcyc7XG5cbmltcG9ydCB7IFVJUm91dGVyUnggfSBmcm9tICdAdWlyb3V0ZXIvcngnO1xuaW1wb3J0IHsgTmdIeWJyaWRTdGF0ZXNNb2R1bGUgfSBmcm9tICcuL2ludGVyZmFjZXMnO1xuXG5jb25zdCBnZXRBbmd1bGFySlMgPSBnZXRBbmd1bGFySlNHbG9iYWwgfHwgZ2V0QW5ndWxhckxpYjtcbmNvbnN0IGFuZ3VsYXIgPSBnZXRBbmd1bGFySlMoKTtcblxuaWYgKCFhbmd1bGFyKSB7XG4gIHRocm93IG5ldyBFcnJvcihcbiAgICAnQW5ndWxhckpTIG5vdCBmb3VuZCBvbiB3aW5kb3cuICBodHRwczovL2dpdGh1Yi5jb20vdWktcm91dGVyL2FuZ3VsYXItaHlicmlkL3dpa2kvQW5ndWxhckpTLW5vdC1mb3VuZC1vbi13aW5kb3cnXG4gICk7XG59XG5cbi8qKlxuICogQ3JlYXRlIGEgbmcxIG1vZHVsZSBmb3IgdGhlIG5nMSBoYWxmIG9mIHRoZSBoeWJyaWQgYXBwbGljYXRpb24gdG8gZGVwZW5kIG9uLlxuICpcbiAqIEV4YW1wbGU6XG4gKiBjb25zdCBteUFwcCA9IGFuZ3VsYXIubW9kdWxlKCdteUFwcCcsIFsndWkucm91dGVyLnVwZ3JhZGUnXSk7XG4gKi9cbmV4cG9ydCBjb25zdCB1cGdyYWRlTW9kdWxlID0gYW5ndWxhci5tb2R1bGUoJ3VpLnJvdXRlci51cGdyYWRlJywgWyd1aS5yb3V0ZXInXSk7XG5cbmV4cG9ydCBmdW5jdGlvbiBvYmplY3RGYWN0b3J5KCkge1xuICByZXR1cm4ge307XG59XG5cbi8qKlxuICogVUlWaWV3TmdVcGdyYWRlIGlzIGEgY29tcG9uZW50IGJyaWRnZSBmcm9tIG5nMSB1aS12aWV3IHRvIG5nMiB1aS12aWV3XG4gKlxuICogV2hlbiBhIHVpLXJvdXRlciBmb3IgbmcxIGlzIHJlZ2lzdGVyaW5nIGEgc3RhdGUgaXQgY2hlY2tzIGlmIGEgdmlldydzXG4gKiBgY29tcG9uZW50OmAgaXMgYW4gbmcyIENvbXBvbmVudCBjbGFzcy4gSWYgc28sIGl0IGNyZWF0ZXMgYSBzcGVjaWFsIG5nMSB0ZW1wbGF0ZVxuICogd2hpY2ggcmVmZXJlbmNlcyB0aGlzIGNvbXBvbmVudCwgaS5lLiwgPHVpLXZpZXctbmctdXBncmFkZT48L3VpLXZpZXctbmctdXBncmFkZT5cbiAqXG4gKiBTZWUgdGhhdCBjb2RlIGJ5IHNlYXJjaGluZyBuZzEtdG8tbmcyIHNvdXJjZSBmb3I6IFwiJHN0YXRlUHJvdmlkZXIuZGVjb3JhdG9yXCJcbiAqXG4gKiAtLS1cbiAqXG4gKiBuZzEtdG8tbmcyIGNvbXBvbmVudCBicmlkZ2UgcHJvY2VzczpcbiAqXG4gKiAxKVxuICogV2hlbiBhbiBuZzEgdGVtcGxhdGUgY3JlYXRlcyBhIHVpLXZpZXcgd2hpY2ggaXMgdGFyZ2V0ZWQgYnkgYSBuZzIgQ29tcG9uZW50LFxuICpcbiAqIGBgYFxuICogPGEgdWktc3JlZj1cImZvb1wiPkdvIHRvIGZvbzwvYT5cbiAqIDxkaXYgdWktdmlldz4gPCEtLSB1aS12aWV3IGNyZWF0ZWQgaW4gbmcxIHRlbXBsYXRlIC0tPlxuICogPC9kaXY+IDwhLS0gdGFyZ2V0ZWQgd2l0aCB7IGNvbXBvbmVudDogTmcyUm91dGVkQ29tcG9uZW50IH0gLS0+XG4gKiBgYGBcbiAqXG4gKiB0aGUgc3RhdGUgZGVjb3JhdG9yIHNwaXRzIG91dCBhIGN1c3RvbSB0ZW1wbGF0ZS4gIFRoYXQgdGVtcGxhdGUgbG9hZHMgdGhpc1xuICogbmcyIENvbXBvbmVudCBhZGFwdGVyIGFzIGEgZG93bmdyYWRlZC10by1uZzEgZGlyZWN0aXZlLlxuICpcbiAqIGBgYFxuICogPGEgdWktc3JlZj1cImZvb1wiPkdvIHRvIGZvbzwvYT5cbiAqIDxkaXYgdWktdmlldz4gPCEtLSBkZWNvcmF0ZWQgdGVtcGxhdGUgcmVmZXJlbmNlcyB0aGUgZG93bmdyYWRlZCBjb21wb25lbnQgLS0+XG4gKiAgIDx1aS12aWV3LW5nLXVwZ3JhZGU+IDwhLS0gZG93bmdyYWRlZCBhZGFwdGVyIGNvbXBvbmVudCAtLT5cbiAqICAgPC91aS12aWV3LW5nLXVwZ3JhZGU+XG4gKiA8L2Rpdj5cbiAqIGBgYFxuICpcbiAqIFRoaXMgZG93bmdyYWRlZCBuZzIgQ29tcG9uZW50IHRoZW4gY3JlYXRlcyBhIGNoaWxkIFVJVmlldyAobmcyIGNvbXBvbmVudClcbiAqXG4gKiBgYGBcbiAqIDxhIHVpLXNyZWY9XCJmb29cIj5HbyB0byBmb288L2E+XG4gKiA8ZGl2IHVpLXZpZXc+IDwhLS0gY3VzdG9tIHRlbXBsYXRlIHJlZmVyZW5jZXMgdGhlIGRvd25ncmFkZWQgY29tcG9uZW50IC0tPlxuICogICA8dWktdmlldy1uZy11cGdyYWRlPiA8IS0tIG5nMiBjb21wb25lbnQgYWRhcHRlciBkb3duZ3JhZGVkIHRvIG5nMS0tPlxuICogICAgIDx1aS12aWV3PiA8IS0tIHB1cmUgbmcyIHVpLXZpZXcgLS0+XG4gKiAgICAgIDwvdWktdmlldz5cbiAqICAgPC91aS12aWV3LW5nLXVwZ3JhZGU+XG4gKiA8L2Rpdj5cbiAqIGBgYFxuICpcbiAqIHdoaWNoIGluIHR1cm4gaXMgZmlsbGVkIHdpdGggdGhlIHJvdXRlZCBuZzIgY29tcG9uZW50LlxuICpcbiAqIGBgYFxuICogPGEgdWktc3JlZj1cImZvb1wiPkdvIHRvIGZvbzwvYT5cbiAqIDxkaXYgdWktdmlldz4gPCEtLSBuZzEgdWktdmlldyAtLT5cbiAqICAgPHVpLXZpZXctbmctdXBncmFkZT4gPCEtLSBuZzIgY29tcG9uZW50IGFkYXB0ZXIgKGRvd25ncmFkZWQgdG8gbmcxKS0tPlxuICogICAgIDx1aS12aWV3PiA8IS0tIHB1cmUgbmcyIHVpLXZpZXcgLS0+XG4gKiAgICAgICA8bmcyLXJvdXRlZC1jb21wb25lbnQ+IDwhLS0gbmcyIGNvbXBvbmVudCBob3N0ZWQgaW4gbmcyIHVpLXZpZXcgLS0+XG4gKiAgICAgICAgIDxoMT5uZzIgcm91dGVkIGNvbXBvbmVudCBjb250ZW50czwvaDE+XG4gKiAgICAgICA8L25nMi1yb3V0ZWQtY29tcG9uZW50PlxuICogICAgIDwvdWktdmlldz5cbiAqICAgPC91aS12aWV3LW5nLXVwZ3JhZGU+XG4gKiA8L2Rpdj5cbiAqIGBgYFxuICpcbiAqIFRoaXMgYWRhcHRlciBleHBvc2VzIGV4cG9zZXMgdGhlIHBhcmVudCB2aWV3IGNvbnRleHQgKFBhcmVudFVJVmlld0luamVjdClcbiAqIGFzIGFuIG5nMiBESSBQcm92aWRlciwgd2hpY2ggdGhlIG5lc3RlZCBuZzIgVUlWaWV3IHJlcXVpcmVzLlxuICpcbiAqIEl0IGdldHMgdGhlIFBhcmVudFVJVmlld0NvbnRleHQgaW5mb3JtYXRpb24gKGZyb20gdGhlIHBhcmVudCBuZzEgdWktdmlldykgYnkgd2Fsa2luZ1xuICogdXAgdGhlIERPTSBhbmQgZ3JhYmJpbmcgdGhlIC5kYXRhKCckdWlWaWV3Jykgd2hpY2ggdGhlIG5nMSB1aS12aWV3IGRpcmVjdGl2ZSBleHBvc2VzLlxuICovXG5AQ29tcG9uZW50KHtcbiAgc2VsZWN0b3I6ICd1aS12aWV3LW5nLXVwZ3JhZGUnLFxuICB0ZW1wbGF0ZTogYFxuICAgIDx1aS12aWV3IFtuYW1lXT1cIm5hbWVcIj48L3VpLXZpZXc+XG4gIGAsXG4gIC8vIHByb3ZpZGUgYSBibGFuayBvYmplY3QgYXMgUEFSRU5UX0lOSkVDVC5cbiAgLy8gVGhlIGNvbXBvbmVudCB3aWxsIGFkZCBwcm9wZXJ0eSBnZXR0ZXJzIHdoZW4gaXQgaXMgY29uc3RydWN0ZWQuXG4gIHZpZXdQcm92aWRlcnM6IFt7IHByb3ZpZGU6IFVJVmlldy5QQVJFTlRfSU5KRUNULCB1c2VGYWN0b3J5OiBvYmplY3RGYWN0b3J5IH1dLFxufSlcbmV4cG9ydCBjbGFzcyBVSVZpZXdOZ1VwZ3JhZGUge1xuICAvLyBUaGUgdWktdmlldydzIG5hbWUgKG9yICckZGVmYXVsdCcpXG4gIEBJbnB1dCgpXG4gIG5hbWU6IHN0cmluZztcblxuICBjb25zdHJ1Y3RvcihcbiAgICByZWY6IEVsZW1lbnRSZWYsXG4gICAgQEluamVjdChVSVZpZXcuUEFSRU5UX0lOSkVDVCkgcGFyZW50OiBQYXJlbnRVSVZpZXdJbmplY3QsXG4gICAgcmVnaXN0cnk6IFN0YXRlUmVnaXN0cnkgLy8gYWNjZXNzIHRoZSByb290IHN0YXRlXG4gICkge1xuICAgIC8vIEZyb20gdGhlIHVpLXZpZXctbmctdXBncmFkZSBjb21wb25lbnQncyBlbGVtZW50IHJlZiwgd2FsayB1cCB0aGUgRE9NIHR3byBlbGVtZW50cy4uLlxuICAgIC8vIFRoZXJlIHdpbGwgZmlyc3QgYmUgYW4gbmcxIHVpLXZpZXcgd2hpY2ggaG9zdHMgdGhpcyBlbGVtZW50LCBhbmQgdGhlbiB0aGF0IHVpLXZpZXcncyBwYXJlbnQgZWxlbWVudC5cbiAgICAvLyBUaGF0IChwYXJlbnQpIGVsZW1lbnQgaGFzIGFjY2VzcyB0byB0aGUgcHJvcGVyIFwicGFyZW50IHZpZXdjb250ZXh0XCJcblxuICAgIC8vIFRoZSBuZzIgdWktdmlldyBjb21wb25lbnQgaXMgaW5zaWRlIHRoaXMgdWktdmlldy1uZy11cGdyYWRlIGRpcmVjdGl2ZSwgd2hpY2ggaXMgaW5zaWRlIHRoZSBuZzEgXCJob3N0XCIgdWktdmlldy5cbiAgICAvLyBCb3RoIHVpLXZpZXdzIHNoYXJlIHRoZSBzYW1lIFwidmlldyBjb250ZXh0XCIgaW5mb3JtYXRpb24gKHRoZSB2aWV3J3MgZnFuIGFuZCBjcmVhdGVkLWJ5LXN0YXRlIGNvbnRleHQgaW5mb3JtYXRpb24pXG4gICAgY29uc3QgbmcxZWxlbSA9IGFuZ3VsYXJcbiAgICAgIC5lbGVtZW50KHJlZi5uYXRpdmVFbGVtZW50KVxuICAgICAgLnBhcmVudCgpXG4gICAgICAucGFyZW50KCk7XG5cbiAgICAvLyBFeHBvc2UgZ2V0dGVycyBvbiBQQVJFTlRfSU5KRUNUIGZvciBjb250ZXh0IChjcmVhdGlvbiBzdGF0ZSkgYW5kIGZxbiAodmlldyBhZGRyZXNzKVxuICAgIC8vIFRoZXNlIHdpbGwgYmUgdXNlZCBieSBmdXJ0aGVyIG5lc3RlZCBVSVZpZXdcbiAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkocGFyZW50LCAnY29udGV4dCcsIHtcbiAgICAgIGdldDogZnVuY3Rpb24oKSB7XG4gICAgICAgIGNvbnN0IGRhdGEgPSBuZzFlbGVtWydpbmhlcml0ZWREYXRhJ10oJyR1aVZpZXcnKTtcbiAgICAgICAgcmV0dXJuIGRhdGEgJiYgZGF0YS4kY2ZnID8gZGF0YS4kY2ZnLnZpZXdEZWNsLiRjb250ZXh0IDogcmVnaXN0cnkucm9vdCgpO1xuICAgICAgfSxcbiAgICAgIGVudW1lcmFibGU6IHRydWUsXG4gICAgfSk7XG5cbiAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkocGFyZW50LCAnZnFuJywge1xuICAgICAgZ2V0OiBmdW5jdGlvbigpIHtcbiAgICAgICAgY29uc3QgZGF0YSA9IG5nMWVsZW1bJ2luaGVyaXRlZERhdGEnXSgnJHVpVmlldycpO1xuICAgICAgICByZXR1cm4gZGF0YSAmJiBkYXRhLiR1aVZpZXcgPyBkYXRhLiR1aVZpZXcuZnFuIDogbnVsbDtcbiAgICAgIH0sXG4gICAgICBlbnVtZXJhYmxlOiB0cnVlLFxuICAgIH0pO1xuICB9XG59XG5cbi8qKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqXG4gKiBOZzIgQE5nTW9kdWxlIGFuZCBib290c3RyYXAgY29kZVxuICoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKiovXG5cbi8vIFJlZ2lzdGVyIHRoZSBuZzEgREkgJyR1aVJvdXRlcicgb2JqZWN0IGFzIGFuIG5nMiBQcm92aWRlci5cbmV4cG9ydCBmdW5jdGlvbiB1aVJvdXRlclVwZ3JhZGVGYWN0b3J5KHJvdXRlcjogVUlSb3V0ZXIsIGluamVjdG9yOiBJbmplY3Rvcikge1xuICBjb25zdCBtb2R1bGVzOiBTdGF0ZXNNb2R1bGVbXSA9IGluamVjdG9yLmdldDxTdGF0ZXNNb2R1bGVbXT4oVUlST1VURVJfTU9EVUxFX1RPS0VOLCBbXSk7XG4gIG1vZHVsZXMuZm9yRWFjaChtb2R1bGUgPT4gYXBwbHlNb2R1bGVDb25maWcocm91dGVyLCBpbmplY3RvciwgbW9kdWxlKSk7XG4gIHJldHVybiByb3V0ZXI7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBnZXRVSVJvdXRlcigkaW5qZWN0b3I6IGFueSkge1xuICByZXR1cm4gJGluamVjdG9yLmdldCgnJHVpUm91dGVyJyk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBnZXRQYXJlbnRVSVZpZXdJbmplY3QocjogU3RhdGVSZWdpc3RyeSk6IFBhcmVudFVJVmlld0luamVjdCB7XG4gIHJldHVybiB7IGZxbjogbnVsbCwgY29udGV4dDogci5yb290KCkgfTtcbn1cblxuLyoqXG4gKiBUaGlzIE5nTW9kdWxlIHNob3VsZCBiZSBhZGRlZCB0byB0aGUgcm9vdCBtb2R1bGUgb2YgdGhlIGh5YnJpZCBhcHAuXG4gKi9cbkBOZ01vZHVsZSh7XG4gIGltcG9ydHM6IFtVSVJvdXRlck1vZHVsZSwgVXBncmFkZU1vZHVsZV0sXG4gIGRlY2xhcmF0aW9uczogW1VJVmlld05nVXBncmFkZV0sXG4gIHByb3ZpZGVyczogW1xuICAgIC8vIEB1aXJvdXRlci9hbmd1bGFyIGNvZGUgd2lsbCB1c2UgdGhlIG5nMSAkdWlSb3V0ZXIgaW5zdGFuY2UgaW5zdGVhZCBvZiBjcmVhdGluZyBpdHMgb3duLlxuICAgIHsgcHJvdmlkZTogJyR1aVJvdXRlcicsIHVzZUZhY3Rvcnk6IGdldFVJUm91dGVyLCBkZXBzOiBbJyRpbmplY3RvciddIH0sXG5cbiAgICB7IHByb3ZpZGU6IFVJUm91dGVyLCB1c2VGYWN0b3J5OiB1aVJvdXRlclVwZ3JhZGVGYWN0b3J5LCBkZXBzOiBbJyR1aVJvdXRlcicsIEluamVjdG9yXSB9LFxuXG4gICAgeyBwcm92aWRlOiBVSVJPVVRFUl9ST09UX01PRFVMRSwgdXNlVmFsdWU6IHt9LCBtdWx0aTogdHJ1ZSB9LFxuXG4gICAgeyBwcm92aWRlOiBVSVZpZXcuUEFSRU5UX0lOSkVDVCwgdXNlRmFjdG9yeTogZ2V0UGFyZW50VUlWaWV3SW5qZWN0LCBkZXBzOiBbU3RhdGVSZWdpc3RyeV0gfSxcblxuICAgIC4uLl9VSVJPVVRFUl9TRVJWSUNFX1BST1ZJREVSUyxcbiAgXSxcbiAgZW50cnlDb21wb25lbnRzOiBbVUlWaWV3TmdVcGdyYWRlXSxcbiAgZXhwb3J0czogW1VJVmlld05nVXBncmFkZSwgVUlSb3V0ZXJNb2R1bGVdLFxufSlcbmV4cG9ydCBjbGFzcyBVSVJvdXRlclVwZ3JhZGVNb2R1bGUge1xuICBzdGF0aWMgZm9yUm9vdChtb2R1bGU6IE5nSHlicmlkU3RhdGVzTW9kdWxlID0ge30pOiBNb2R1bGVXaXRoUHJvdmlkZXJzIHtcbiAgICByZXR1cm4ge1xuICAgICAgbmdNb2R1bGU6IFVJUm91dGVyVXBncmFkZU1vZHVsZSxcbiAgICAgIHByb3ZpZGVyczogbWFrZUNoaWxkUHJvdmlkZXJzKG1vZHVsZSBhcyBTdGF0ZXNNb2R1bGUpLFxuICAgIH07XG4gIH1cblxuICBzdGF0aWMgZm9yQ2hpbGQobW9kdWxlOiBOZ0h5YnJpZFN0YXRlc01vZHVsZSA9IHt9KTogTW9kdWxlV2l0aFByb3ZpZGVycyB7XG4gICAgcmV0dXJuIHtcbiAgICAgIG5nTW9kdWxlOiBVSVJvdXRlck1vZHVsZSxcbiAgICAgIHByb3ZpZGVyczogbWFrZUNoaWxkUHJvdmlkZXJzKG1vZHVsZSBhcyBTdGF0ZXNNb2R1bGUpLFxuICAgIH07XG4gIH1cbn1cblxuLy8gRG93bmdyYWRlIHRoZSBVSVZpZXdOZ1VwZ3JhZGUgbmcyIENvbXBvbmVudCB0byBhbiBuZzEgZGlyZWN0aXZlLlxuLy8gVGhlIGRpcmVjdGl2ZSBpcyB1c2VkIGluIGEgKGdlbmVyYXRlZCkgdmlldyB0ZW1wbGF0ZSBieSB0aGUgKGhvc3QpIG5nMSB1aS1yb3V0ZXIsXG4vLyB3aGVuZXZlciBpdCBmaW5kcyBhIHZpZXcgY29uZmlndXJlZCB3aXRoIGEgYGNvbXBvbmVudDogPE5nMkNvbXBvbmVudENsYXNzPmBcbnVwZ3JhZGVNb2R1bGUuZGlyZWN0aXZlKCd1aVZpZXdOZ1VwZ3JhZGUnLCA8YW55PmRvd25ncmFkZUNvbXBvbmVudCh7XG4gIGNvbXBvbmVudDogVUlWaWV3TmdVcGdyYWRlLFxuICBpbnB1dHM6IFsnbmFtZSddLFxufSkpO1xuXG51cGdyYWRlTW9kdWxlLnJ1bihbXG4gICckaW5qZWN0b3InLFxuICAobmcxSW5qZWN0b3I6ICRJbmplY3Rvckxpa2UpID0+IHtcbiAgICBjb25zdCAkdWlSb3V0ZXI6IFVJUm91dGVyID0gbmcxSW5qZWN0b3IuZ2V0KCckdWlSb3V0ZXInKTtcblxuICAgIC8qKiBBZGQgc3VwcG9ydCBmb3Igb2JzZXJ2YWJsZSBzdGF0ZSBhbmQgcGFyYW0gY2hhbmdlcyAqL1xuICAgICR1aVJvdXRlci5wbHVnaW4oVUlSb3V0ZXJSeCk7XG5cbiAgICAvLyBFeHBvc2UgYSBtZXJnZWQgbmcxL25nMiBpbmplY3RvciBhcyBhIFJlc29sdmFibGUgKG9uIHRoZSByb290IHN0YXRlKS5cbiAgICAvLyBUaGlzIG1pbWljcyBob3cgdWktcm91dGVyLW5nMiBleHBvc2VzIHRoZSByb290IG5nMiBJbmplY3RvciwgYnV0XG4gICAgLy8gaXQgcmV0cmlldmVzIGZyb20gbmcxIGluamVjdG9yIGZpcnN0LCB0aGVuIG5nMiBpbmplY3RvciBpZiB0aGUgdG9rZW4gaXNuJ3QgZm91bmQuXG4gICAgY29uc3QgbWVyZ2VkSW5qZWN0b3IgPSB7XG4gICAgICBnZXQ6IGZ1bmN0aW9uKHRva2VuOiBhbnksIG5nMk5vdEZvdW5kVmFsdWU/OiBhbnkpIHtcbiAgICAgICAgY29uc3QgbmcySW5qZWN0b3IgPSBuZzFJbmplY3Rvci5nZXQoJyQkYW5ndWxhckluamVjdG9yJyk7XG4gICAgICAgIGlmIChuZzFJbmplY3Rvci5oYXModG9rZW4pKSB7XG4gICAgICAgICAgcmV0dXJuIG5nMUluamVjdG9yLmdldCh0b2tlbik7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIG5nMkluamVjdG9yLmdldCh0b2tlbiwgbmcyTm90Rm91bmRWYWx1ZSk7XG4gICAgICB9LFxuICAgIH07XG5cbiAgICBjb25zdCBuZzJJbmplY3RvclJlc29sdmFibGUgPSBSZXNvbHZhYmxlLmZyb21EYXRhKE5BVElWRV9JTkpFQ1RPUl9UT0tFTiwgbWVyZ2VkSW5qZWN0b3IpO1xuICAgICR1aVJvdXRlci5zdGF0ZVJlZ2lzdHJ5LnJvb3QoKS5yZXNvbHZhYmxlcy5wdXNoKG5nMkluamVjdG9yUmVzb2x2YWJsZSk7XG4gIH0sXG5dKTtcblxuLyoqIEFkZHMgc3VwcG9ydCBmb3IgYGxvYWRDaGlsZHJlbmA6IEFuZ3VsYXIgTmdNb2R1bGUgbGF6eSBsb2FkaW5nIHZpYSBAZ250b29scy93ZWJwYWNrICovXG51cGdyYWRlTW9kdWxlLmNvbmZpZyhbXG4gICckc3RhdGVSZWdpc3RyeVByb3ZpZGVyJyxcbiAgKCRzdGF0ZVJlZ2lzdHJ5OiBTdGF0ZVJlZ2lzdHJ5KSA9PiB7XG4gICAgJHN0YXRlUmVnaXN0cnkuZGVjb3JhdG9yKCdsYXp5TG9hZCcsIG5nMkxhenlMb2FkQnVpbGRlcik7XG4gIH0sXG5dKTtcblxuLyoqXG4gKiBEZWZpbmUgYSBzdGF0ZVByb3ZpZGVyIGB2aWV3c2AgYnVpbGRlciBkZWNvcmF0b3IuXG4gKiBUaGUgZGVjb3JhdG9yIGZpcnN0IGFwcGxpZXMgdGhlIHN0YW5kYXJkIHZpZXdzIGJ1aWxkZXIgZnVuY3Rpb24uXG4gKiBUaGVuIGl0IGZpbmRzIGFueSB2aWV3IGNvbXBvbmVudHMgd2hpY2ggYXJlICoqYWN0dWFsbHkqKiBhIE5nMiBDb21wb25lbnQgQ2xhc3MuXG4gKiBJdCBvdmVyd3JpdGVzIHRoYXQgdmlldydzIGNvbmZpZyB3aXRoIGEgbmcxLXRvLW5nMiBoeWJyaWQgY29uZmlnLlxuICpcbiAqIEluIHBsYWNlIG9mIHRoZSB0ZW1wbGF0ZSBwcm92aWRlciwgaXQgc2ltcGx5IHB1dHMgYSA8dWktdmlldy1uZy11cGdyYWRlLz4gY29tcG9uZW50XG4gKiB3aGljaCB0aGF0IHByb3ZpZGVzIGEgbmcxIC0+IG5nMiBib3VuZGFyeSBpbiB0aGUgY29tcG9uZW50IHRyZWUuXG4gKi9cbnVwZ3JhZGVNb2R1bGUuY29uZmlnKFtcbiAgJyRzdGF0ZVJlZ2lzdHJ5UHJvdmlkZXInLFxuICAoJHN0YXRlUmVnaXN0cnk6IFN0YXRlUmVnaXN0cnkpID0+IHtcbiAgICAkc3RhdGVSZWdpc3RyeS5kZWNvcmF0b3IoJ3ZpZXdzJywgZnVuY3Rpb24oc3RhdGU6IFN0YXRlT2JqZWN0LCBwYXJlbnRGbjogRnVuY3Rpb24pIHtcbiAgICAgIGNvbnN0IHZpZXdzID0gcGFyZW50Rm4oc3RhdGUpO1xuXG4gICAgICBmb3JFYWNoKHZpZXdzLCAodmlld0RlY2w6IGFueSwgdmlld05hbWU6IHN0cmluZykgPT4ge1xuICAgICAgICBpZiAodmlld0RlY2wuJHR5cGUgPT09ICduZzEtdG8tbmcyJyB8fCB0eXBlb2Ygdmlld0RlY2wuY29tcG9uZW50ID09PSAnZnVuY3Rpb24nKSB7XG4gICAgICAgICAgLy8gVXBkYXRlIHRoZSB2aWV3IGNvbmZpZy5cbiAgICAgICAgICAvLyBPdmVycmlkZSBkZWZhdWx0IG5nMSBgY29tcG9uZW50OmAgYmVoYXZpb3IgKG9mIGRlZmluaW5nIGEgdGVtcGxhdGVQcm92aWRlcilcbiAgICAgICAgICAvLyB3aXRoIGEgPHVpLXZpZXctbmctdXBncmFkZT4gYWRhcHRlciBkaXJlY3RpdmUgdGVtcGxhdGVcbiAgICAgICAgICB2aWV3RGVjbC4kdHlwZSA9ICduZzEtdG8tbmcyJztcbiAgICAgICAgICB2aWV3RGVjbC50ZW1wbGF0ZVByb3ZpZGVyID0gbnVsbDtcbiAgICAgICAgICB2aWV3RGVjbC50ZW1wbGF0ZSA9IGA8dWktdmlldy1uZy11cGdyYWRlIG5hbWU9JyR7dmlld0RlY2wuJHVpVmlld05hbWV9Jz48L3VpLXZpZXctbmctdXBncmFkZT5gO1xuICAgICAgICB9XG4gICAgICB9KTtcbiAgICAgIHJldHVybiB2aWV3cztcbiAgICB9KTtcbiAgfSxcbl0pO1xuXG4vLyBVSS1Sb3V0ZXIgVmlld0NvbmZpZyBmYWN0b3JpZXMgdGFrZSBhIHZpZXcgZGVjbGFyYXRpb24gb2JqZWN0IGZyb20gYSBzdGF0ZS52aWV3czogeyBmb286IDxWaWV3RGVjbGFyYXRpb24+IH1cbi8vIGFuZCByZXR1cm4gYSBydW50aW1lIGNvbmZpZyBvYmplY3QgKGEgVmlld0NvbmZpZylcbnVwZ3JhZGVNb2R1bGUucnVuKFtcbiAgJyR2aWV3JyxcbiAgJyR0ZW1wbGF0ZUZhY3RvcnknLFxuICAoJHZpZXc6IFZpZXdTZXJ2aWNlLCAkdGVtcGxhdGVGYWN0b3J5OiBhbnkpID0+IHtcbiAgICAvLyBSZWdpc3RlciBhIFZpZXdDb25maWcgZmFjdG9yeSBmb3Igdmlld3Mgb2YgdHlwZSBgbmcyYFxuICAgICR2aWV3Ll9wbHVnaW5hcGkuX3ZpZXdDb25maWdGYWN0b3J5KFxuICAgICAgJ25nMicsXG4gICAgICAocGF0aDogUGF0aE5vZGVbXSwgY29uZmlnOiBOZzJWaWV3RGVjbGFyYXRpb24pID0+IG5ldyBOZzJWaWV3Q29uZmlnKHBhdGgsIGNvbmZpZylcbiAgICApO1xuXG4gICAgLy8gUmVnaXN0ZXIgYSBWaWV3Q29uZmlnIGZhY3RvcnkgZm9yIHZpZXdzIG9mIHR5cGUgYG5nMS10by1uZzJgLlxuICAgIC8vIFJldHVybnMgYm90aCBhbiBuZzEgY29uZmlnIGFuZCBhbiBuZzIgY29uZmlnIGFsbG93aW5nIGVpdGhlciBuZzEgb3IgbmcyIHVpLXZpZXcgY29tcG9uZW50cyB0byBiZSB0YXJnZXRlZC5cbiAgICAkdmlldy5fcGx1Z2luYXBpLl92aWV3Q29uZmlnRmFjdG9yeSgnbmcxLXRvLW5nMicsIChwYXRoOiBQYXRoTm9kZVtdLCBjb25maWc6IE5nMlZpZXdEZWNsYXJhdGlvbikgPT4ge1xuICAgICAgY29uc3QgbmcxVmlld0NvbmZpZzogVmlld0NvbmZpZyA9IDxhbnk+KFxuICAgICAgICBuZXcgTmcxVmlld0NvbmZpZyg8YW55PnBhdGgsIDxhbnk+T2JqZWN0LmFzc2lnbih7fSwgY29uZmlnLCB7ICR0eXBlOiAnbmcxJyB9KSwgJHRlbXBsYXRlRmFjdG9yeSlcbiAgICAgICk7XG4gICAgICBjb25zdCBuZzJWaWV3Q29uZmlnOiBWaWV3Q29uZmlnID0gPGFueT4oXG4gICAgICAgIG5ldyBOZzJWaWV3Q29uZmlnKDxhbnk+cGF0aCwgPGFueT5PYmplY3QuYXNzaWduKHt9LCBjb25maWcsIHsgJHR5cGU6ICduZzInIH0pKVxuICAgICAgKTtcblxuICAgICAgcmV0dXJuIFtuZzJWaWV3Q29uZmlnLCBuZzFWaWV3Q29uZmlnXTtcbiAgICB9KTtcbiAgfSxcbl0pO1xuIl19
\No newline at end of file