xng-breadcrumb
Version:
A declarative and reactive breadcrumb approach for Angular 6 and beyond https://www.npmjs.com/package/xng-breadcrumb
1 lines • 87.3 kB
Source Map (JSON)
{"version":3,"file":"xng-breadcrumb.mjs","sources":["../tmp-esm2022/lib/breadcrumb-item.directive.js","../tmp-esm2022/lib/breadcrumb.service.js","../tmp-esm2022/lib/breadcrumb.component.js","../tmp-esm2022/xng-breadcrumb.js"],"sourcesContent":["import { Directive } from '@angular/core';\nimport * as i0 from \"@angular/core\";\n/**\n * This directive is used to customize the breadcrumb label behavior\n * *xngBreadcrumbItem directive can be used in the child element of xng-breadcrumb\n * Usage: refer to the demo - app.component.html\n */\nexport class BreadcrumbItemDirective {\n static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: \"12.0.0\", version: \"20.0.7\", ngImport: i0, type: BreadcrumbItemDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }\n static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: \"14.0.0\", version: \"20.0.7\", type: BreadcrumbItemDirective, isStandalone: true, selector: \"[xngBreadcrumbItem]\", ngImport: i0 }); }\n}\ni0.ɵɵngDeclareClassMetadata({ minVersion: \"12.0.0\", version: \"20.0.7\", ngImport: i0, type: BreadcrumbItemDirective, decorators: [{\n type: Directive,\n args: [{\n selector: '[xngBreadcrumbItem]',\n standalone: true,\n }]\n }] });\n//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYnJlYWRjcnVtYi1pdGVtLmRpcmVjdGl2ZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3huZy1icmVhZGNydW1iL3NyYy9saWIvYnJlYWRjcnVtYi1pdGVtLmRpcmVjdGl2ZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsU0FBUyxFQUFFLE1BQU0sZUFBZSxDQUFDOztBQUUxQzs7OztHQUlHO0FBS0gsTUFBTSxPQUFPLHVCQUF1Qjs4R0FBdkIsdUJBQXVCO2tHQUF2Qix1QkFBdUI7OzJGQUF2Qix1QkFBdUI7a0JBSm5DLFNBQVM7bUJBQUM7b0JBQ1QsUUFBUSxFQUFFLHFCQUFxQjtvQkFDL0IsVUFBVSxFQUFFLElBQUk7aUJBQ2pCIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgRGlyZWN0aXZlIH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5cbi8qKlxuICogVGhpcyBkaXJlY3RpdmUgaXMgdXNlZCB0byBjdXN0b21pemUgdGhlIGJyZWFkY3J1bWIgbGFiZWwgYmVoYXZpb3JcbiAqICp4bmdCcmVhZGNydW1iSXRlbSBkaXJlY3RpdmUgY2FuIGJlIHVzZWQgaW4gdGhlIGNoaWxkIGVsZW1lbnQgb2YgeG5nLWJyZWFkY3J1bWJcbiAqIFVzYWdlOiByZWZlciB0byB0aGUgZGVtbyAtIGFwcC5jb21wb25lbnQuaHRtbFxuICovXG5ARGlyZWN0aXZlKHtcbiAgc2VsZWN0b3I6ICdbeG5nQnJlYWRjcnVtYkl0ZW1dJyxcbiAgc3RhbmRhbG9uZTogdHJ1ZSxcbn0pXG5leHBvcnQgY2xhc3MgQnJlYWRjcnVtYkl0ZW1EaXJlY3RpdmUge31cbiJdfQ==","import { inject, Injectable } from '@angular/core';\nimport { ActivatedRoute, GuardsCheckEnd, Router } from '@angular/router';\nimport { BehaviorSubject } from 'rxjs';\nimport { filter } from 'rxjs/operators';\nimport * as i0 from \"@angular/core\";\nconst PATH_PARAM = {\n PREFIX: ':',\n REGEX_IDENTIFIER: '/:[^/]+',\n REGEX_REPLACER: '/[^/]+',\n};\nconst ALIAS_PREFIX = '@';\nconst isNonEmpty = (obj) => {\n return !!obj && Object.keys(obj).length > 0;\n};\nexport class BreadcrumbService {\n constructor() {\n this.baseHref = '/';\n /**\n * dynamicBreadcrumbStore holds information about dynamically updated breadcrumbs.\n * Breadcrumbs can be set from anywhere (component, service) in the app.\n * On every breadcrumb update check this store and use the info if available.\n */\n this.dynamicBreadcrumbStore = [];\n /**\n * breadcrumbList for the current route\n * When breadcrumb info is changed dynamically, check if the currentBreadcrumbs is effected\n * If effected, update the change and emit a new stream\n */\n this.currentBreadcrumbs = [];\n this.previousBreadcrumbs = [];\n /**\n * Breadcrumbs observable to be subscribed by BreadcrumbComponent\n * Emits on every route change OR dynamic update of breadcrumb\n */\n this.breadcrumbs = new BehaviorSubject([]);\n this.breadcrumbs$ = this.breadcrumbs.asObservable();\n this.activatedRoute = inject(ActivatedRoute);\n this.router = inject(Router);\n this.detectRouteChanges();\n }\n /**\n * Whenever route changes build breadcrumb list again\n */\n detectRouteChanges() {\n // Special case where breadcrumb service & component instantiates after a route is navigated.\n // Ex: put breadcrumbs within *ngIf and this.router.events would be empty\n // This check is also required where { initialNavigation: 'enabledBlocking' } is applied to routes\n this.setupBreadcrumbs(this.activatedRoute.snapshot);\n this.router.events.pipe(filter((event) => event instanceof GuardsCheckEnd)).subscribe((event) => {\n // activatedRoute doesn't carry data when shouldReuseRoute returns false\n // use the event data with GuardsCheckEnd as workaround\n // Check for shouldActivate in case where the authGuard returns false the breadcrumbs shouldn't be changed\n if (event.shouldActivate) {\n this.setupBreadcrumbs(event.state.root);\n }\n });\n }\n setupBreadcrumbs(activatedRouteSnapshot) {\n this.previousBreadcrumbs = this.currentBreadcrumbs;\n // breadcrumb label for base OR root path. Usually, this can be set as 'Home'\n const rootBreadcrumb = this.getRootBreadcrumb();\n this.currentBreadcrumbs = rootBreadcrumb ? [rootBreadcrumb] : [];\n this.prepareBreadcrumbList(activatedRouteSnapshot, this.baseHref);\n }\n getRootBreadcrumb() {\n const rootConfig = this.router.config.find((config) => config.path === '');\n const rootBreadcrumb = this.extractObject(rootConfig?.data?.['breadcrumb']);\n const storeItem = this.getFromStore(rootBreadcrumb.alias, '/');\n if (isNonEmpty(rootBreadcrumb) || isNonEmpty(storeItem)) {\n return {\n ...storeItem,\n ...rootBreadcrumb,\n routeLink: this.baseHref,\n ...this.getQueryParamsFromPreviousList('/'),\n };\n }\n }\n prepareBreadcrumbItem(activatedRouteSnapshot, routeLinkPrefix) {\n const { path, breadcrumb } = this.parseRouteData(activatedRouteSnapshot.routeConfig);\n const resolvedSegment = this.resolvePathSegment(path, activatedRouteSnapshot);\n const routeLink = `${routeLinkPrefix}${resolvedSegment}`;\n const storeItem = this.getFromStore(breadcrumb.alias, routeLink);\n const label = this.extractLabel(storeItem?.label || breadcrumb?.label, resolvedSegment);\n let isAutoGeneratedLabel = false;\n let autoGeneratedLabel = '';\n if (!label) {\n isAutoGeneratedLabel = true;\n autoGeneratedLabel = resolvedSegment;\n }\n return {\n ...storeItem,\n ...breadcrumb,\n label: isAutoGeneratedLabel ? autoGeneratedLabel : label,\n routeLink,\n isAutoGeneratedLabel,\n ...this.getQueryParamsFromPreviousList(routeLink),\n };\n }\n prepareBreadcrumbList(activatedRouteSnapshot, routeLinkPrefix) {\n if (activatedRouteSnapshot.routeConfig?.path) {\n const breadcrumbItem = this.prepareBreadcrumbItem(activatedRouteSnapshot, routeLinkPrefix);\n this.currentBreadcrumbs.push(breadcrumbItem);\n if (activatedRouteSnapshot.firstChild) {\n return this.prepareBreadcrumbList(activatedRouteSnapshot.firstChild, breadcrumbItem.routeLink + '/');\n }\n }\n else if (activatedRouteSnapshot.firstChild) {\n return this.prepareBreadcrumbList(activatedRouteSnapshot.firstChild, routeLinkPrefix);\n }\n const lastCrumb = this.currentBreadcrumbs[this.currentBreadcrumbs.length - 1];\n this.setQueryParamsForActiveBreadcrumb(lastCrumb, activatedRouteSnapshot);\n // remove breadcrumb items that needs to be hidden\n const breadcrumbsToShow = this.currentBreadcrumbs.filter((item) => !item.skip);\n this.breadcrumbs.next(breadcrumbsToShow);\n }\n getFromStore(alias, routeLink) {\n return this.dynamicBreadcrumbStore.find((item) => {\n return (alias && alias === item.alias) || (routeLink && routeLink === item.routeLink) || this.matchRegex(routeLink, item.routeRegex);\n });\n }\n /**\n * use exact match instead of regexp.test\n * for /mentor/[^/]+ we should match '/mentor/12' but not '/mentor/12/abc'\n */\n matchRegex(routeLink, routeRegex) {\n const match = routeLink.match(new RegExp(routeRegex));\n return match?.[0] === routeLink;\n }\n /**\n * if the path segment has route params, read the param value from url\n * for each segment of route this gets called\n *\n * for mentor/:id/view - it gets called with mentor, :id, view 3 times\n */\n resolvePathSegment(segment, activatedRouteSnapshot) {\n //quirk -segment can be defined as view/:id in route config in which case you need to make it view/<resolved-param>\n if (segment.includes(PATH_PARAM.PREFIX)) {\n Object.entries(activatedRouteSnapshot.params).forEach(([key, value]) => {\n segment = segment.replace(`:${key}`, `${value}`);\n });\n }\n return segment;\n }\n /**\n * queryParams & fragments for previous breadcrumb path are copied over to new list\n */\n getQueryParamsFromPreviousList(routeLink) {\n const { queryParams, fragment } = this.previousBreadcrumbs.find((item) => item.routeLink === routeLink) || {};\n return { queryParams, fragment };\n }\n /**\n * set current activated route query params to the last breadcrumb item\n */\n setQueryParamsForActiveBreadcrumb(lastItem, activatedRouteSnapshot) {\n if (lastItem) {\n const { queryParams, fragment } = activatedRouteSnapshot;\n lastItem.queryParams = queryParams ? { ...queryParams } : undefined;\n lastItem.fragment = fragment;\n }\n }\n /**\n * For a specific route, breadcrumb can be defined either on parent OR it's child(which has empty path)\n * When both are defined, child takes precedence\n *\n * Ex: Below we are setting breadcrumb on both parent and child.\n * So, child takes precedence and \"Defined On Child\" is displayed for the route 'home'\n * { path: 'home', loadChildren: () => import('./home/home.module').then((m) => m.HomeModule) , data: {breadcrumb: \"Defined On Module\"}}\n * AND\n * children: [\n * { path: '', component: ShowUserComponent, data: {breadcrumb: \"Defined On Child\" }\n * ]\n */\n parseRouteData(routeConfig) {\n const { path, data } = routeConfig;\n const breadcrumb = this.mergeWithBaseChildData(routeConfig, data?.breadcrumb);\n return { path, breadcrumb };\n }\n /**\n * get empty children of a module or Component. Empty child is the one with path: ''\n * When parent and it's children (that has empty route path) define data merge them both with child taking precedence\n */\n mergeWithBaseChildData(routeConfig, // TODO: add proper type\n config) {\n if (!routeConfig) {\n return this.extractObject(config);\n }\n let baseChild;\n if (routeConfig.loadChildren) {\n // To handle a module with empty child route\n baseChild = routeConfig._loadedRoutes.find((route) => route.path === '');\n }\n else if (routeConfig.children) {\n // To handle a component with empty child route\n baseChild = routeConfig.children.find((route) => route.path === '');\n }\n const childConfig = baseChild?.data?.breadcrumb;\n return childConfig\n ? this.mergeWithBaseChildData(baseChild, {\n ...this.extractObject(config),\n ...this.extractObject(childConfig),\n })\n : this.extractObject(config);\n }\n /**\n * Update breadcrumb dynamically\n *\n * key can be a path | alias\n *\n * 1) Using complete route path. route can be passed the same way you define angular routes\n * - path can be passed as 'exact path(routeLink)' or 'path with params(routeRegex)'\n * - update label Ex: set('/mentor', 'Mentor'), set('/mentor/:id', 'Mentor Details')\n * - change visibility Ex: set('/mentor/:id/edit', { skip: true })\n * ------------------------------------------ OR ------------------------------------------\n * 2) Using route alias (prefixed with '@'). alias should be unique for a route\n * - update label Ex: set('@mentor', 'Enabler')\n * - change visibility Ex: set('@mentorEdit', { skip: true })\n *\n *\n * value can be string | BreadcrumbObject | BreadcrumbFunction\n */\n set(key, breadcrumb) {\n const breadcrumbObject = this.extractObject(breadcrumb);\n let updateArgs;\n if (key.startsWith(ALIAS_PREFIX)) {\n updateArgs = ['alias', { ...breadcrumbObject, alias: key.slice(1) }];\n }\n else if (key.includes(PATH_PARAM.PREFIX)) {\n updateArgs = ['routeRegex', { ...breadcrumbObject, routeRegex: this.buildRegex(key) }];\n }\n else {\n updateArgs = ['routeLink', { ...breadcrumbObject, routeLink: this.ensureLeadingSlash(key) }];\n }\n // For this route if previously a breadcrumb is not defined that sets isAutoGeneratedLabel: true\n // change it to false since this is user supplied value\n updateArgs[1].isAutoGeneratedLabel = false;\n this.updateStore(...updateArgs);\n this.updateCurrentBreadcrumbs(...updateArgs);\n }\n /**\n * Update the store to reuse for dynamic declarations\n * If the store already has this route definition update it, else add\n */\n updateStore(key, breadcrumb) {\n const storeItemIndex = this.dynamicBreadcrumbStore.findIndex((item) => {\n return breadcrumb[key] === item[key];\n });\n if (storeItemIndex > -1) {\n this.dynamicBreadcrumbStore[storeItemIndex] = {\n ...this.dynamicBreadcrumbStore[storeItemIndex],\n ...breadcrumb,\n };\n }\n else {\n this.dynamicBreadcrumbStore.push({ ...breadcrumb });\n }\n }\n /**\n * If breadcrumb is present in current breadcrumbs update it and emit new stream\n */\n updateCurrentBreadcrumbs(key, breadcrumb) {\n const itemIndex = this.currentBreadcrumbs.findIndex((item) => {\n return key === 'routeRegex' ? this.matchRegex(item.routeLink, breadcrumb[key]) : breadcrumb[key] === item[key];\n });\n if (itemIndex > -1) {\n this.currentBreadcrumbs[itemIndex] = {\n ...this.currentBreadcrumbs[itemIndex],\n ...breadcrumb,\n };\n const breadcrumbsToShow = this.currentBreadcrumbs.filter((item) => !item.skip);\n this.breadcrumbs.next([...breadcrumbsToShow]);\n }\n }\n /**\n * For a route with path param, we create regex dynamically from angular route syntax\n * '/mentor/:id' becomes '/mentor/[^/]',\n * breadcrumbService.set('/mentor/:id', 'Uday') should update 'Uday' as label for '/mentor/2' OR 'mentor/ada'\n */\n buildRegex(path) {\n return this.ensureLeadingSlash(path).replace(new RegExp(PATH_PARAM.REGEX_IDENTIFIER, 'g'), PATH_PARAM.REGEX_REPLACER);\n }\n ensureLeadingSlash(path) {\n return path.startsWith('/') ? path : `/${path}`;\n }\n /**\n * In App's RouteConfig, breadcrumb can be defined as a string OR a function OR an object\n *\n * string: simple static breadcrumb label for a path\n * function: callback that gets invoked with resolved path param\n * object: additional data defined along with breadcrumb label that gets passed to *xngBreadcrumbItem directive\n */\n extractLabel(config, resolvedParam) {\n const label = typeof config === 'object' ? config.label : config;\n if (typeof label === 'function') {\n return label(resolvedParam);\n }\n return label;\n }\n extractObject(config) {\n // don't include {label} if config is undefined. This is important since we merge the configs\n if (config && (typeof config === 'string' || typeof config === 'function')) {\n return { label: config };\n }\n return config || {};\n }\n static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: \"12.0.0\", version: \"20.0.7\", ngImport: i0, type: BreadcrumbService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }\n static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: \"12.0.0\", version: \"20.0.7\", ngImport: i0, type: BreadcrumbService, providedIn: 'root' }); }\n}\ni0.ɵɵngDeclareClassMetadata({ minVersion: \"12.0.0\", version: \"20.0.7\", ngImport: i0, type: BreadcrumbService, decorators: [{\n type: Injectable,\n args: [{\n providedIn: 'root',\n }]\n }], ctorParameters: () => [] });\n//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYnJlYWRjcnVtYi5zZXJ2aWNlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4veG5nLWJyZWFkY3J1bWIvc3JjL2xpYi9icmVhZGNydW1iLnNlcnZpY2UudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLE1BQU0sRUFBRSxVQUFVLEVBQUUsTUFBTSxlQUFlLENBQUM7QUFDbkQsT0FBTyxFQUFFLGNBQWMsRUFBMEIsY0FBYyxFQUFFLE1BQU0sRUFBRSxNQUFNLGlCQUFpQixDQUFDO0FBQ2pHLE9BQU8sRUFBRSxlQUFlLEVBQUUsTUFBTSxNQUFNLENBQUM7QUFDdkMsT0FBTyxFQUFFLE1BQU0sRUFBRSxNQUFNLGdCQUFnQixDQUFDOztBQUt4QyxNQUFNLFVBQVUsR0FBRztJQUNqQixNQUFNLEVBQUUsR0FBRztJQUNYLGdCQUFnQixFQUFFLFNBQVM7SUFDM0IsY0FBYyxFQUFFLFFBQVE7Q0FDekIsQ0FBQztBQUNGLE1BQU0sWUFBWSxHQUFHLEdBQUcsQ0FBQztBQUN6QixNQUFNLFVBQVUsR0FBRyxDQUFDLEdBQVksRUFBVyxFQUFFO0lBQzNDLE9BQU8sQ0FBQyxDQUFDLEdBQUcsSUFBSSxNQUFNLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxDQUFDLE1BQU0sR0FBRyxDQUFDLENBQUM7QUFDOUMsQ0FBQyxDQUFDO0FBS0YsTUFBTSxPQUFPLGlCQUFpQjtJQTRCNUI7UUEzQlEsYUFBUSxHQUFHLEdBQUcsQ0FBQztRQUV2Qjs7OztXQUlHO1FBQ0ssMkJBQXNCLEdBQTJCLEVBQUUsQ0FBQztRQUU1RDs7OztXQUlHO1FBQ0ssdUJBQWtCLEdBQTJCLEVBQUUsQ0FBQztRQUNoRCx3QkFBbUIsR0FBMkIsRUFBRSxDQUFDO1FBRXpEOzs7V0FHRztRQUNLLGdCQUFXLEdBQUcsSUFBSSxlQUFlLENBQXlCLEVBQUUsQ0FBQyxDQUFDO1FBQy9ELGlCQUFZLEdBQUcsSUFBSSxDQUFDLFdBQVcsQ0FBQyxZQUFZLEVBQUUsQ0FB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cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgaW5qZWN0LCBJbmplY3RhYmxlIH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgeyBBY3RpdmF0ZWRSb3V0ZSwgQWN0aXZhdGVkUm91dGVTbmFwc2hvdCwgR3VhcmRzQ2hlY2tFbmQsIFJvdXRlciB9IGZyb20gJ0Bhbmd1bGFyL3JvdXRlcic7XG5pbXBvcnQgeyBCZWhhdmlvclN1YmplY3QgfSBmcm9tICdyeGpzJztcbmltcG9ydCB7IGZpbHRlciB9IGZyb20gJ3J4anMvb3BlcmF0b3JzJztcbmltcG9ydCB7IEJyZWFkY3J1bWJEZWZpbml0aW9uLCBCcmVhZGNydW1iLCBCcmVhZGNydW1iQ29uZmlnLCBCcmVhZGNydW1iT2JqZWN0IH0gZnJvbSAnLi90eXBlcyc7XG5cbnR5cGUgU3RvcmVNYXRjaGVyS2V5ID0gJ3JvdXRlTGluaycgfCAncm91dGVSZWdleCcgfCAnYWxpYXMnO1xuXG5jb25zdCBQQVRIX1BBUkFNID0ge1xuICBQUkVGSVg6ICc6JyxcbiAgUkVHRVhfSURFTlRJRklFUjogJy86W14vXSsnLFxuICBSRUdFWF9SRVBMQUNFUjogJy9bXi9dKycsXG59O1xuY29uc3QgQUxJQVNfUFJFRklYID0gJ0AnO1xuY29uc3QgaXNOb25FbXB0eSA9IChvYmo6IHVua25vd24pOiBib29sZWFuID0+IHtcbiAgcmV0dXJuICEhb2JqICYmIE9iamVjdC5rZXlzKG9iaikubGVuZ3RoID4gMDtcbn07XG5cbkBJbmplY3RhYmxlKHtcbiAgcHJvdmlkZWRJbjogJ3Jvb3QnLFxufSlcbmV4cG9ydCBjbGFzcyBCcmVhZGNydW1iU2VydmljZSB7XG4gIHByaXZhdGUgYmFzZUhyZWYgPSAnLyc7XG5cbiAgLyoqXG4gICAqIGR5bmFtaWNCcmVhZGNydW1iU3RvcmUgaG9sZHMgaW5mb3JtYXRpb24gYWJvdXQgZHluYW1pY2FsbHkgdXBkYXRlZCBicmVhZGNydW1icy5cbiAgICogQnJlYWRjcnVtYnMgY2FuIGJlIHNldCBmcm9tIGFueXdoZXJlIChjb21wb25lbnQsIHNlcnZpY2UpIGluIHRoZSBhcHAuXG4gICAqIE9uIGV2ZXJ5IGJyZWFkY3J1bWIgdXBkYXRlIGNoZWNrIHRoaXMgc3RvcmUgYW5kIHVzZSB0aGUgaW5mbyBpZiBhdmFpbGFibGUuXG4gICAqL1xuICBwcml2YXRlIGR5bmFtaWNCcmVhZGNydW1iU3RvcmU6IEJyZWFkY3J1bWJEZWZpbml0aW9uW10gPSBbXTtcblxuICAvKipcbiAgICogYnJlYWRjcnVtYkxpc3QgZm9yIHRoZSBjdXJyZW50IHJvdXRlXG4gICAqIFdoZW4gYnJlYWRjcnVtYiBpbmZvIGlzIGNoYW5nZWQgZHluYW1pY2FsbHksIGNoZWNrIGlmIHRoZSBjdXJyZW50QnJlYWRjcnVtYnMgaXMgZWZmZWN0ZWRcbiAgICogSWYgZWZmZWN0ZWQsIHVwZGF0ZSB0aGUgY2hhbmdlIGFuZCBlbWl0IGEgbmV3IHN0cmVhbVxuICAgKi9cbiAgcHJpdmF0ZSBjdXJyZW50QnJlYWRjcnVtYnM6IEJyZWFkY3J1bWJEZWZpbml0aW9uW10gPSBbXTtcbiAgcHJpdmF0ZSBwcmV2aW91c0JyZWFkY3J1bWJzOiBCcmVhZGNydW1iRGVmaW5pdGlvbltdID0gW107XG5cbiAgLyoqXG4gICAqIEJyZWFkY3J1bWJzIG9ic2VydmFibGUgdG8gYmUgc3Vic2NyaWJlZCBieSBCcmVhZGNydW1iQ29tcG9uZW50XG4gICAqIEVtaXRzIG9uIGV2ZXJ5IHJvdXRlIGNoYW5nZSBPUiBkeW5hbWljIHVwZGF0ZSBvZiBicmVhZGNydW1iXG4gICAqL1xuICBwcml2YXRlIGJyZWFkY3J1bWJzID0gbmV3IEJlaGF2aW9yU3ViamVjdDxCcmVhZGNydW1iRGVmaW5pdGlvbltdPihbXSk7XG4gIHB1YmxpYyBicmVhZGNydW1icyQgPSB0aGlzLmJyZWFkY3J1bWJzLmFzT2JzZXJ2YWJsZSgpO1xuXG4gIHByaXZhdGUgcmVhZG9ubHkgYWN0aXZhdGVkUm91dGUgPSBpbmplY3QoQWN0aXZhdGVkUm91dGUpO1xuICBwcml2YXRlIHJlYWRvbmx5IHJvdXRlciA9IGluamVjdChSb3V0ZXIpO1xuXG4gIGNvbnN0cnVjdG9yKCkge1xuICAgIHRoaXMuZGV0ZWN0Um91dGVDaGFuZ2VzKCk7XG4gIH1cblxuICAvKipcbiAgICogV2hlbmV2ZXIgcm91dGUgY2hhbmdlcyBidWlsZCBicmVhZGNydW1iIGxpc3QgYWdhaW5cbiAgICovXG4gIHByaXZhdGUgZGV0ZWN0Um91dGVDaGFuZ2VzKCkge1xuICAgIC8vIFNwZWNpYWwgY2FzZSB3aGVyZSBicmVhZGNydW1iIHNlcnZpY2UgJiBjb21wb25lbnQgaW5zdGFudGlhdGVzIGFmdGVyIGEgcm91dGUgaXMgbmF2aWdhdGVkLlxuICAgIC8vIEV4OiBwdXQgYnJlYWRjcnVtYnMgd2l0aGluICpuZ0lmIGFuZCB0aGlzLnJvdXRlci5ldmVudHMgd291bGQgYmUgZW1wdHlcbiAgICAvLyBUaGlzIGNoZWNrIGlzIGFsc28gcmVxdWlyZWQgd2hlcmUgIHsgaW5pdGlhbE5hdmlnYXRpb246ICdlbmFibGVkQmxvY2tpbmcnIH0gaXMgYXBwbGllZCB0byByb3V0ZXNcbiAgICB0aGlzLnNldHVwQnJlYWRjcnVtYnModGhpcy5hY3RpdmF0ZWRSb3V0ZS5zbmFwc2hvdCk7XG5cbiAgICB0aGlzLnJvdXRlci5ldmVudHMucGlwZShmaWx0ZXIoKGV2ZW50KTogZXZlbnQgaXMgR3VhcmRzQ2hlY2tFbmQgPT4gZXZlbnQgaW5zdGFuY2VvZiBHdWFyZHNDaGVja0VuZCkpLnN1YnNjcmliZSgoZXZlbnQpID0+IHtcbiAgICAgIC8vIGFjdGl2YXRlZFJvdXRlIGRvZXNuJ3QgY2FycnkgZGF0YSB3aGVuIHNob3VsZFJldXNlUm91dGUgcmV0dXJucyBmYWxzZVxuICAgICAgLy8gdXNlIHRoZSBldmVudCBkYXRhIHdpdGggR3VhcmRzQ2hlY2tFbmQgYXMgd29ya2Fyb3VuZFxuICAgICAgLy8gQ2hlY2sgZm9yIHNob3VsZEFjdGl2YXRlIGluIGNhc2Ugd2hlcmUgdGhlIGF1dGhHdWFyZCByZXR1cm5zIGZhbHNlIHRoZSBicmVhZGNydW1icyBzaG91bGRuJ3QgYmUgY2hhbmdlZFxuICAgICAgaWYgKGV2ZW50LnNob3VsZEFjdGl2YXRlKSB7XG4gICAgICAgIHRoaXMuc2V0dXBCcmVhZGNydW1icyhldmVudC5zdGF0ZS5yb290KTtcbiAgICAgIH1cbiAgICB9KTtcbiAgfVxuXG4gIHByaXZhdGUgc2V0dXBCcmVhZGNydW1icyhhY3RpdmF0ZWRSb3V0ZVNuYXBzaG90OiBBY3RpdmF0ZWRSb3V0ZVNuYXBzaG90KSB7XG4gICAgdGhpcy5wcmV2aW91c0JyZWFkY3J1bWJzID0gdGhpcy5jdXJyZW50QnJlYWRjcnVtYnM7XG4gICAgLy8gYnJlYWRjcnVtYiBsYWJlbCBmb3IgYmFzZSBPUiByb290IHBhdGguIFVzdWFsbHksIHRoaXMgY2FuIGJlIHNldCBhcyAnSG9tZSdcbiAgICBjb25zdCByb290QnJlYWRjcnVtYiA9IHRoaXMuZ2V0Um9vdEJyZWFkY3J1bWIoKTtcbiAgICB0aGlzLmN1cnJlbnRCcmVhZGNydW1icyA9IHJvb3RCcmVhZGNydW1iID8gW3Jvb3RCcmVhZGNydW1iXSA6IFtdO1xuICAgIHRoaXMucHJlcGFyZUJyZWFkY3J1bWJMaXN0KGFjdGl2YXRlZFJvdXRlU25hcHNob3QsIHRoaXMuYmFzZUhyZWYpO1xuICB9XG5cbiAgcHJpdmF0ZSBnZXRSb290QnJlYWRjcnVtYigpOiBCcmVhZGNydW1iIHwgdm9pZCB7XG4gICAgY29uc3Qgcm9vdENvbmZpZyA9IHRoaXMucm91dGVyLmNvbmZpZy5maW5kKChjb25maWcpID0+IGNvbmZpZy5wYXRoID09PSAnJyk7XG4gICAgY29uc3Qgcm9vdEJyZWFkY3J1bWIgPSB0aGlzLmV4dHJhY3RPYmplY3Qocm9vdENvbmZpZz8uZGF0YT8uWydicmVhZGNydW1iJ10pO1xuICAgIGNvbnN0IHN0b3JlSXRlbSA9IHRoaXMuZ2V0RnJvbVN0b3JlKHJvb3RCcmVhZGNydW1iLmFsaWFzLCAnLycpO1xuXG4gICAgaWYgKGlzTm9uRW1wdHkocm9vdEJyZWFkY3J1bWIpIHx8IGlzTm9uRW1wdHkoc3RvcmVJdGVtKSkge1xuICAgICAgcmV0dXJuIHtcbiAgICAgICAgLi4uc3RvcmVJdGVtLFxuICAgICAgICAuLi5yb290QnJlYWRjcnVtYixcbiAgICAgICAgcm91dGVMaW5rOiB0aGlzLmJhc2VIcmVmLFxuICAgICAgICAuLi50aGlzLmdldFF1ZXJ5UGFyYW1zRnJvbVByZXZpb3VzTGlzdCgnLycpLFxuICAgICAgfTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIHByZXBhcmVCcmVhZGNydW1iSXRlbShhY3RpdmF0ZWRSb3V0ZVNuYXBzaG90OiBBY3RpdmF0ZWRSb3V0ZVNuYXBzaG90LCByb3V0ZUxpbmtQcmVmaXg6IHN0cmluZyk6IEJyZWFkY3J1bWJEZWZpbml0aW9uIHtcbiAgICBjb25zdCB7IHBhdGgsIGJyZWFkY3J1bWIgfSA9IHRoaXMucGFyc2VSb3V0ZURhdGEoYWN0aXZhdGVkUm91dGVTbmFwc2hvdC5yb3V0ZUNvbmZpZyk7XG4gICAgY29uc3QgcmVzb2x2ZWRTZWdtZW50ID0gdGhpcy5yZXNvbHZlUGF0aFNlZ21lbnQocGF0aCwgYWN0aXZhdGVkUm91dGVTbmFwc2hvdCk7XG4gICAgY29uc3Qgcm91dGVMaW5rID0gYCR7cm91dGVMaW5rUHJlZml4fSR7cmVzb2x2ZWRTZWdtZW50fWA7XG4gICAgY29uc3Qgc3RvcmVJdGVtID0gdGhpcy5nZXRGcm9tU3RvcmUoYnJlYWRjcnVtYi5hbGlhcywgcm91dGVMaW5rKTtcblxuICAgIGNvbnN0IGxhYmVsID0gdGhpcy5leHRyYWN0TGFiZWwoc3RvcmVJdGVtPy5sYWJlbCB8fCBicmVhZGNydW1iPy5sYWJlbCwgcmVzb2x2ZWRTZWdtZW50KTtcbiAgICBsZXQgaXNBdXRvR2VuZXJhdGVkTGFiZWwgPSBmYWxzZTtcbiAgICBsZXQgYXV0b0dlbmVyYXRlZExhYmVsID0gJyc7XG4gICAgaWYgKCFsYWJlbCkge1xuICAgICAgaXNBdXRvR2VuZXJhdGVkTGFiZWwgPSB0cnVlO1xuICAgICAgYXV0b0dlbmVyYXRlZExhYmVsID0gcmVzb2x2ZWRTZWdtZW50O1xuICAgIH1cblxuICAgIHJldHVybiB7XG4gICAgICAuLi5zdG9yZUl0ZW0sXG4gICAgICAuLi5icmVhZGNydW1iLFxuICAgICAgbGFiZWw6IGlzQXV0b0dlbmVyYXRlZExhYmVsID8gYXV0b0dlbmVyYXRlZExhYmVsIDogbGFiZWwsXG4gICAgICByb3V0ZUxpbmssXG4gICAgICBpc0F1dG9HZW5lcmF0ZWRMYWJlbCxcbiAgICAgIC4uLnRoaXMuZ2V0UXVlcnlQYXJhbXNGcm9tUHJldmlvdXNMaXN0KHJvdXRlTGluayksXG4gICAgfTtcbiAgfVxuXG4gIHByaXZhdGUgcHJlcGFyZUJyZWFkY3J1bWJMaXN0KGFjdGl2YXRlZFJvdXRlU25hcHNob3Q6IEFjdGl2YXRlZFJvdXRlU25hcHNob3QsIHJvdXRlTGlua1ByZWZpeDogc3RyaW5nKTogQnJlYWRjcnVtYltdIHwgdm9pZCB7XG4gICAgaWYgKGFjdGl2YXRlZFJvdXRlU25hcHNob3Qucm91dGVDb25maWc/LnBhdGgpIHtcbiAgICAgIGNvbnN0IGJyZWFkY3J1bWJJdGVtID0gdGhpcy5wcmVwYXJlQnJlYWRjcnVtYkl0ZW0oYWN0aXZhdGVkUm91dGVTbmFwc2hvdCwgcm91dGVMaW5rUHJlZml4KTtcbiAgICAgIHRoaXMuY3VycmVudEJyZWFkY3J1bWJzLnB1c2goYnJlYWRjcnVtYkl0ZW0pO1xuXG4gICAgICBpZiAoYWN0aXZhdGVkUm91dGVTbmFwc2hvdC5maXJzdENoaWxkKSB7XG4gICAgICAgIHJldHVybiB0aGlzLnByZXBhcmVCcmVhZGNydW1iTGlzdChhY3RpdmF0ZWRSb3V0ZVNuYXBzaG90LmZpcnN0Q2hpbGQsIGJyZWFkY3J1bWJJdGVtLnJvdXRlTGluayArICcvJyk7XG4gICAgICB9XG4gICAgfSBlbHNlIGlmIChhY3RpdmF0ZWRSb3V0ZVNuYXBzaG90LmZpcnN0Q2hpbGQpIHtcbiAgICAgIHJldHVybiB0aGlzLnByZXBhcmVCcmVhZGNydW1iTGlzdChhY3RpdmF0ZWRSb3V0ZVNuYXBzaG90LmZpcnN0Q2hpbGQsIHJvdXRlTGlua1ByZWZpeCk7XG4gICAgfVxuICAgIGNvbnN0IGxhc3RDcnVtYiA9IHRoaXMuY3VycmVudEJyZWFkY3J1bWJzW3RoaXMuY3VycmVudEJyZWFkY3J1bWJzLmxlbmd0aCAtIDFdO1xuICAgIHRoaXMuc2V0UXVlcnlQYXJhbXNGb3JBY3RpdmVCcmVhZGNydW1iKGxhc3RDcnVtYiwgYWN0aXZhdGVkUm91dGVTbmFwc2hvdCk7XG5cbiAgICAvLyByZW1vdmUgYnJlYWRjcnVtYiBpdGVtcyB0aGF0IG5lZWRzIHRvIGJlIGhpZGRlblxuICAgIGNvbnN0IGJyZWFkY3J1bWJzVG9TaG93ID0gdGhpcy5jdXJyZW50QnJlYWRjcnVtYnMuZmlsdGVyKChpdGVtKSA9PiAhaXRlbS5za2lwKTtcblxuICAgIHRoaXMuYnJlYWRjcnVtYnMubmV4dChicmVhZGNydW1ic1RvU2hvdyk7XG4gIH1cblxuICBwcml2YXRlIGdldEZyb21TdG9yZShhbGlhczogc3RyaW5nLCByb3V0ZUxpbms6IHN0cmluZyk6IEJyZWFkY3J1bWJEZWZpbml0aW9uIHtcbiAgICByZXR1cm4gdGhpcy5keW5hbWljQnJlYWRjcnVtYlN0b3JlLmZpbmQoKGl0ZW0pID0+IHtcbiAgICAgIHJldHVybiAoYWxpYXMgJiYgYWxpYXMgPT09IGl0ZW0uYWxpYXMpIHx8IChyb3V0ZUxpbmsgJiYgcm91dGVMaW5rID09PSBpdGVtLnJvdXRlTGluaykgfHwgdGhpcy5tYXRjaFJlZ2V4KHJvdXRlTGluaywgaXRlbS5yb3V0ZVJlZ2V4KTtcbiAgICB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiB1c2UgZXhhY3QgbWF0Y2ggaW5zdGVhZCBvZiByZWdleHAudGVzdFxuICAgKiBmb3IgL21lbnRvci9bXi9dKyB3ZSBzaG91bGQgbWF0Y2ggJy9tZW50b3IvMTInIGJ1dCBub3QgJy9tZW50b3IvMTIvYWJjJ1xuICAgKi9cbiAgcHJpdmF0ZSBtYXRjaFJlZ2V4KHJvdXRlTGluazogc3RyaW5nLCByb3V0ZVJlZ2V4OiBzdHJpbmcpIHtcbiAgICBjb25zdCBtYXRjaCA9IHJvdXRlTGluay5tYXRjaChuZXcgUmVnRXhwKHJvdXRlUmVnZXgpKTtcbiAgICByZXR1cm4gbWF0Y2g/LlswXSA9PT0gcm91dGVMaW5rO1xuICB9XG5cbiAgLyoqXG4gICAqIGlmIHRoZSBwYXRoIHNlZ21lbnQgaGFzIHJvdXRlIHBhcmFtcywgcmVhZCB0aGUgcGFyYW0gdmFsdWUgZnJvbSB1cmxcbiAgICogZm9yIGVhY2ggc2VnbWVudCBvZiByb3V0ZSB0aGlzIGdldHMgY2FsbGVkXG4gICAqXG4gICAqIGZvciBtZW50b3IvOmlkL3ZpZXcgLSBpdCBnZXRzIGNhbGxlZCB3aXRoIG1lbnRvciwgOmlkLCB2aWV3IDMgdGltZXNcbiAgICovXG4gIHByaXZhdGUgcmVzb2x2ZVBhdGhTZWdtZW50KHNlZ21lbnQ6IHN0cmluZywgYWN0aXZhdGVkUm91dGVTbmFwc2hvdDogQWN0aXZhdGVkUm91dGVTbmFwc2hvdCkge1xuICAgIC8vcXVpcmsgLXNlZ21lbnQgY2FuIGJlIGRlZmluZWQgYXMgdmlldy86aWQgaW4gcm91dGUgY29uZmlnIGluIHdoaWNoIGNhc2UgeW91IG5lZWQgdG8gbWFrZSBpdCB2aWV3LzxyZXNvbHZlZC1wYXJhbT5cbiAgICBpZiAoc2VnbWVudC5pbmNsdWRlcyhQQVRIX1BBUkFNLlBSRUZJWCkpIHtcbiAgICAgIE9iamVjdC5lbnRyaWVzKGFjdGl2YXRlZFJvdXRlU25hcHNob3QucGFyYW1zKS5mb3JFYWNoKChba2V5LCB2YWx1ZV0pID0+IHtcbiAgICAgICAgc2VnbWVudCA9IHNlZ21lbnQucmVwbGFjZShgOiR7a2V5fWAsIGAke3ZhbHVlfWApO1xuICAgICAgfSk7XG4gICAgfVxuICAgIHJldHVybiBzZWdtZW50O1xuICB9XG5cbiAgLyoqXG4gICAqIHF1ZXJ5UGFyYW1zICYgZnJhZ21lbnRzIGZvciBwcmV2aW91cyBicmVhZGNydW1iIHBhdGggYXJlIGNvcGllZCBvdmVyIHRvIG5ldyBsaXN0XG4gICAqL1xuICBwcml2YXRlIGdldFF1ZXJ5UGFyYW1zRnJvbVByZXZpb3VzTGlzdChyb3V0ZUxpbms6IHN0cmluZyk6IEJyZWFkY3J1bWIge1xuICAgIGNvbnN0IHsgcXVlcnlQYXJhbXMsIGZyYWdtZW50IH0gPSB0aGlzLnByZXZpb3VzQnJlYWRjcnVtYnMuZmluZCgoaXRlbSkgPT4gaXRlbS5yb3V0ZUxpbmsgPT09IHJvdXRlTGluaykgfHwge307XG4gICAgcmV0dXJuIHsgcXVlcnlQYXJhbXMsIGZyYWdtZW50IH07XG4gIH1cblxuICAvKipcbiAgICogc2V0IGN1cnJlbnQgYWN0aXZhdGVkIHJvdXRlIHF1ZXJ5IHBhcmFtcyB0byB0aGUgbGFzdCBicmVhZGNydW1iIGl0ZW1cbiAgICovXG4gIHByaXZhdGUgc2V0UXVlcnlQYXJhbXNGb3JBY3RpdmVCcmVhZGNydW1iKGxhc3RJdGVtOiBCcmVhZGNydW1iLCBhY3RpdmF0ZWRSb3V0ZVNuYXBzaG90OiBBY3RpdmF0ZWRSb3V0ZVNuYXBzaG90KSB7XG4gICAgaWYgKGxhc3RJdGVtKSB7XG4gICAgICBjb25zdCB7IHF1ZXJ5UGFyYW1zLCBmcmFnbWVudCB9ID0gYWN0aXZhdGVkUm91dGVTbmFwc2hvdDtcbiAgICAgIGxhc3RJdGVtLnF1ZXJ5UGFyYW1zID0gcXVlcnlQYXJhbXMgPyB7IC4uLnF1ZXJ5UGFyYW1zIH0gOiB1bmRlZmluZWQ7XG4gICAgICBsYXN0SXRlbS5mcmFnbWVudCA9IGZyYWdtZW50O1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBGb3IgYSBzcGVjaWZpYyByb3V0ZSwgYnJlYWRjcnVtYiBjYW4gYmUgZGVmaW5lZCBlaXRoZXIgb24gcGFyZW50IE9SIGl0J3MgY2hpbGQod2hpY2ggaGFzIGVtcHR5IHBhdGgpXG4gICAqIFdoZW4gYm90aCBhcmUgZGVmaW5lZCwgY2hpbGQgdGFrZXMgcHJlY2VkZW5jZVxuICAgKlxuICAgKiBFeDogQmVsb3cgd2UgYXJlIHNldHRpbmcgYnJlYWRjcnVtYiBvbiBib3RoIHBhcmVudCBhbmQgY2hpbGQuXG4gICAqIFNvLCBjaGlsZCB0YWtlcyBwcmVjZWRlbmNlIGFuZCBcIkRlZmluZWQgT24gQ2hpbGRcIiBpcyBkaXNwbGF5ZWQgZm9yIHRoZSByb3V0ZSAnaG9tZSdcbiAgICogeyBwYXRoOiAnaG9tZScsIGxvYWRDaGlsZHJlbjogKCkgPT4gaW1wb3J0KCcuL2hvbWUvaG9tZS5tb2R1bGUnKS50aGVuKChtKSA9PiBtLkhvbWVNb2R1bGUpICwgZGF0YToge2JyZWFkY3J1bWI6IFwiRGVmaW5lZCBPbiBNb2R1bGVcIn19XG4gICAqICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgQU5EXG4gICAqIGNoaWxkcmVuOiBbXG4gICAqICAgeyBwYXRoOiAnJywgY29tcG9uZW50OiBTaG93VXNlckNvbXBvbmVudCwgZGF0YToge2JyZWFkY3J1bWI6IFwiRGVmaW5lZCBPbiBDaGlsZFwiIH1cbiAgICogXVxuICAgKi9cbiAgcHJpdmF0ZSBwYXJzZVJvdXRlRGF0YShyb3V0ZUNvbmZpZykge1xuICAgIGNvbnN0IHsgcGF0aCwgZGF0YSB9ID0gcm91dGVDb25maWc7XG4gICAgY29uc3QgYnJlYWRjcnVtYiA9IHRoaXMubWVyZ2VXaXRoQmFzZUNoaWxkRGF0YShyb3V0ZUNvbmZpZywgZGF0YT8uYnJlYWRjcnVtYik7XG5cbiAgICByZXR1cm4geyBwYXRoLCBicmVhZGNydW1iIH07XG4gIH1cblxuICAvKipcbiAgICogZ2V0IGVtcHR5IGNoaWxkcmVuIG9mIGEgbW9kdWxlIG9yIENvbXBvbmVudC4gRW1wdHkgY2hpbGQgaXMgdGhlIG9uZSB3aXRoIHBhdGg6ICcnXG4gICAqIFdoZW4gcGFyZW50IGFuZCBpdCdzIGNoaWxkcmVuICh0aGF0IGhhcyBlbXB0eSByb3V0ZSBwYXRoKSBkZWZpbmUgZGF0YSBtZXJnZSB0aGVtIGJvdGggd2l0aCBjaGlsZCB0YWtpbmcgcHJlY2VkZW5jZVxuICAgKi9cbiAgcHJpdmF0ZSBtZXJnZVdpdGhCYXNlQ2hpbGREYXRhKFxuICAgIHJvdXRlQ29uZmlnOiBhbnksIC8vIFRPRE86IGFkZCBwcm9wZXIgdHlwZVxuICAgIGNvbmZpZzogQnJlYWRjcnVtYkNvbmZpZ1xuICApOiBCcmVhZGNydW1iT2JqZWN0IHtcbiAgICBpZiAoIXJvdXRlQ29uZmlnKSB7XG4gICAgICByZXR1cm4gdGhpcy5leHRyYWN0T2JqZWN0KGNvbmZpZyk7XG4gICAgfVxuXG4gICAgbGV0IGJhc2VDaGlsZDtcbiAgICBpZiAocm91dGVDb25maWcubG9hZENoaWxkcmVuKSB7XG4gICAgICAvLyBUbyBoYW5kbGUgYSBtb2R1bGUgd2l0aCBlbXB0eSBjaGlsZCByb3V0ZVxuICAgICAgYmFzZUNoaWxkID0gcm91dGVDb25maWcuX2xvYWRlZFJvdXRlcy5maW5kKChyb3V0ZSkgPT4gcm91dGUucGF0aCA9PT0gJycpO1xuICAgIH0gZWxzZSBpZiAocm91dGVDb25maWcuY2hpbGRyZW4pIHtcbiAgICAgIC8vIFRvIGhhbmRsZSBhIGNvbXBvbmVudCB3aXRoIGVtcHR5IGNoaWxkIHJvdXRlXG4gICAgICBiYXNlQ2hpbGQgPSByb3V0ZUNvbmZpZy5jaGlsZHJlbi5maW5kKChyb3V0ZSkgPT4gcm91dGUucGF0aCA9PT0gJycpO1xuICAgIH1cblxuICAgIGNvbnN0IGNoaWxkQ29uZmlnID0gYmFzZUNoaWxkPy5kYXRhPy5icmVhZGNydW1iO1xuICAgIHJldHVybiBjaGlsZENvbmZpZ1xuICAgICAgPyB0aGlzLm1lcmdlV2l0aEJhc2VDaGlsZERhdGEoYmFzZUNoaWxkLCB7XG4gICAgICAgICAgLi4udGhpcy5leHRyYWN0T2JqZWN0KGNvbmZpZyksXG4gICAgICAgICAgLi4udGhpcy5leHRyYWN0T2JqZWN0KGNoaWxkQ29uZmlnKSxcbiAgICAgICAgfSlcbiAgICAgIDogdGhpcy5leHRyYWN0T2JqZWN0KGNvbmZpZyk7XG4gIH1cblxuICAvKipcbiAgICogVXBkYXRlIGJyZWFkY3J1bWIgZHluYW1pY2FsbHlcbiAgICpcbiAgICoga2V5IGNhbiBiZSBhIHBhdGggfCBhbGlhc1xuICAgKlxuICAgKiAxKSBVc2luZyBjb21wbGV0ZSByb3V0ZSBwYXRoLiByb3V0ZSBjYW4gYmUgcGFzc2VkIHRoZSBzYW1lIHdheSB5b3UgZGVmaW5lIGFuZ3VsYXIgcm91dGVzXG4gICAqIC0gcGF0aCBjYW4gYmUgcGFzc2VkIGFzICdleGFjdCBwYXRoKHJvdXRlTGluayknIG9yICdwYXRoIHdpdGggcGFyYW1zKHJvdXRlUmVnZXgpJ1xuICAgKiAtIHVwZGF0ZSBsYWJlbCBFeDogc2V0KCcvbWVudG9yJywgJ01lbnRvcicpLCBzZXQoJy9tZW50b3IvOmlkJywgJ01lbnRvciBEZXRhaWxzJylcbiAgICogLSBjaGFuZ2UgdmlzaWJpbGl0eSBFeDogc2V0KCcvbWVudG9yLzppZC9lZGl0JywgeyBza2lwOiB0cnVlIH0pXG4gICAqIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSBPUiAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgICogMikgVXNpbmcgcm91dGUgYWxpYXMgKHByZWZpeGVkIHdpdGggJ0AnKS4gYWxpYXMgc2hvdWxkIGJlIHVuaXF1ZSBmb3IgYSByb3V0ZVxuICAgKiAtIHVwZGF0ZSBsYWJlbCBFeDogc2V0KCdAbWVudG9yJywgJ0VuYWJsZXInKVxuICAgKiAtIGNoYW5nZSB2aXNpYmlsaXR5IEV4OiBzZXQoJ0BtZW50b3JFZGl0JywgeyBza2lwOiB0cnVlIH0pXG4gICAqXG4gICAqXG4gICAqIHZhbHVlIGNhbiBiZSBzdHJpbmcgfCBCcmVhZGNydW1iT2JqZWN0IHwgQnJlYWRjcnVtYkZ1bmN0aW9uXG4gICAqL1xuICBzZXQoa2V5OiBzdHJpbmcsIGJyZWFkY3J1bWI6IHN0cmluZyB8IEJyZWFkY3J1bWJPYmplY3QpIHtcbiAgICBjb25zdCBicmVhZGNydW1iT2JqZWN0ID0gdGhpcy5leHRyYWN0T2JqZWN0KGJyZWFkY3J1bWIpO1xuICAgIGxldCB1cGRhdGVBcmdzOiBbU3RvcmVNYXRjaGVyS2V5LCBCcmVhZGNydW1iRGVmaW5pdGlvbl07XG5cbiAgICBpZiAoa2V5LnN0YXJ0c1dpdGgoQUxJQVNfUFJFRklYKSkge1xuICAgICAgdXBkYXRlQXJncyA9IFsnYWxpYXMnLCB7IC4uLmJyZWFkY3J1bWJPYmplY3QsIGFsaWFzOiBrZXkuc2xpY2UoMSkgfV07XG4gICAgfSBlbHNlIGlmIChrZXkuaW5jbHVkZXMoUEFUSF9QQVJBTS5QUkVGSVgpKSB7XG4gICAgICB1cGRhdGVBcmdzID0gWydyb3V0ZVJlZ2V4JywgeyAuLi5icmVhZGNydW1iT2JqZWN0LCByb3V0ZVJlZ2V4OiB0aGlzLmJ1aWxkUmVnZXgoa2V5KSB9XTtcbiAgICB9IGVsc2Uge1xuICAgICAgdXBkYXRlQXJncyA9IFsncm91dGVMaW5rJywgeyAuLi5icmVhZGNydW1iT2JqZWN0LCByb3V0ZUxpbms6IHRoaXMuZW5zdXJlTGVhZGluZ1NsYXNoKGtleSkgfV07XG4gICAgfVxuXG4gICAgLy8gRm9yIHRoaXMgcm91dGUgaWYgcHJldmlvdXNseSBhIGJyZWFkY3J1bWIgaXMgbm90IGRlZmluZWQgdGhhdCBzZXRzIGlzQXV0b0dlbmVyYXRlZExhYmVsOiB0cnVlXG4gICAgLy8gY2hhbmdlIGl0IHRvIGZhbHNlIHNpbmNlIHRoaXMgaXMgdXNlciBzdXBwbGllZCB2YWx1ZVxuICAgIHVwZGF0ZUFyZ3NbMV0uaXNBdXRvR2VuZXJhdGVkTGFiZWwgPSBmYWxzZTtcblxuICAgIHRoaXMudXBkYXRlU3RvcmUoLi4udXBkYXRlQXJncyk7XG4gICAgdGhpcy51cGRhdGVDdXJyZW50QnJlYWRjcnVtYnMoLi4udXBkYXRlQXJncyk7XG4gIH1cblxuICAvKipcbiAgICogVXBkYXRlIHRoZSBzdG9yZSB0byByZXVzZSBmb3IgZHluYW1pYyBkZWNsYXJhdGlvbnNcbiAgICogSWYgdGhlIHN0b3JlIGFscmVhZHkgaGFzIHRoaXMgcm91dGUgZGVmaW5pdGlvbiB1cGRhdGUgaXQsIGVsc2UgYWRkXG4gICAqL1xuICBwcml2YXRlIHVwZGF0ZVN0b3JlKGtleTogc3RyaW5nLCBicmVhZGNydW1iOiBCcmVhZGNydW1iRGVmaW5pdGlvbikge1xuICAgIGNvbnN0IHN0b3JlSXRlbUluZGV4ID0gdGhpcy5keW5hbWljQnJlYWRjcnVtYlN0b3JlLmZpbmRJbmRleCgoaXRlbSkgPT4ge1xuICAgICAgcmV0dXJuIGJyZWFkY3J1bWJba2V5XSA9PT0gaXRlbVtrZXldO1xuICAgIH0pO1xuICAgIGlmIChzdG9yZUl0ZW1JbmRleCA+IC0xKSB7XG4gICAgICB0aGlzLmR5bmFtaWNCcmVhZGNydW1iU3RvcmVbc3RvcmVJdGVtSW5kZXhdID0ge1xuICAgICAgICAuLi50aGlzLmR5bmFtaWNCcmVhZGNydW1iU3RvcmVbc3RvcmVJdGVtSW5kZXhdLFxuICAgICAgICAuLi5icmVhZGNydW1iLFxuICAgICAgfTtcbiAgICB9IGVsc2Uge1xuICAgICAgdGhpcy5keW5hbWljQnJlYWRjcnVtYlN0b3JlLnB1c2goeyAuLi5icmVhZGNydW1iIH0pO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBJZiBicmVhZGNydW1iIGlzIHByZXNlbnQgaW4gY3VycmVudCBicmVhZGNydW1icyB1cGRhdGUgaXQgYW5kIGVtaXQgbmV3IHN0cmVhbVxuICAgKi9cbiAgcHJpdmF0ZSB1cGRhdGVDdXJyZW50QnJlYWRjcnVtYnMoa2V5OiBzdHJpbmcsIGJyZWFkY3J1bWI6IEJyZWFkY3J1bWJEZWZpbml0aW9uKSB7XG4gICAgY29uc3QgaXRlbUluZGV4ID0gdGhpcy5jdXJyZW50QnJlYWRjcnVtYnMuZmluZEluZGV4KChpdGVtKSA9PiB7XG4gICAgICByZXR1cm4ga2V5ID09PSAncm91dGVSZWdleCcgPyB0aGlzLm1hdGNoUmVnZXgoaXRlbS5yb3V0ZUxpbmssIGJyZWFkY3J1bWJba2V5XSkgOiBicmVhZGNydW1iW2tleV0gPT09IGl0ZW1ba2V5XTtcbiAgICB9KTtcbiAgICBpZiAoaXRlbUluZGV4ID4gLTEpIHtcbiAgICAgIHRoaXMuY3VycmVudEJyZWFkY3J1bWJzW2l0ZW1JbmRleF0gPSB7XG4gICAgICAgIC4uLnRoaXMuY3VycmVudEJyZWFkY3J1bWJzW2l0ZW1JbmRleF0sXG4gICAgICAgIC4uLmJyZWFkY3J1bWIsXG4gICAgICB9O1xuICAgICAgY29uc3QgYnJlYWRjcnVtYnNUb1Nob3cgPSB0aGlzLmN1cnJlbnRCcmVhZGNydW1icy5maWx0ZXIoKGl0ZW0pID0+ICFpdGVtLnNraXApO1xuICAgICAgdGhpcy5icmVhZGNydW1icy5uZXh0KFsuLi5icmVhZGNydW1ic1RvU2hvd10pO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBGb3IgYSByb3V0ZSB3aXRoIHBhdGggcGFyYW0sIHdlIGNyZWF0ZSByZWdleCBkeW5hbWljYWxseSBmcm9tIGFuZ3VsYXIgcm91dGUgc3ludGF4XG4gICAqICcvbWVudG9yLzppZCcgYmVjb21lcyAnL21lbnRvci9bXi9dJyxcbiAgICogYnJlYWRjcnVtYlNlcnZpY2Uuc2V0KCcvbWVudG9yLzppZCcsICdVZGF5Jykgc2hvdWxkIHVwZGF0ZSAnVWRheScgYXMgbGFiZWwgZm9yICcvbWVudG9yLzInIE9SICdtZW50b3IvYWRhJ1xuICAgKi9cbiAgcHJpdmF0ZSBidWlsZFJlZ2V4KHBhdGg6IHN0cmluZykge1xuICAgIHJldHVybiB0aGlzLmVuc3VyZUxlYWRpbmdTbGFzaChwYXRoKS5yZXBsYWNlKG5ldyBSZWdFeHAoUEFUSF9QQVJBTS5SRUdFWF9JREVOVElGSUVSLCAnZycpLCBQQVRIX1BBUkFNLlJFR0VYX1JFUExBQ0VSKTtcbiAgfVxuXG4gIHByaXZhdGUgZW5zdXJlTGVhZGluZ1NsYXNoKHBhdGg6IHN0cmluZykge1xuICAgIHJldHVybiBwYXRoLnN0YXJ0c1dpdGgoJy8nKSA/IHBhdGggOiBgLyR7cGF0aH1gO1xuICB9XG5cbiAgLyoqXG4gICAqIEluIEFwcCdzIFJvdXRlQ29uZmlnLCBicmVhZGNydW1iIGNhbiBiZSBkZWZpbmVkIGFzIGEgc3RyaW5nIE9SIGEgZnVuY3Rpb24gT1IgYW4gb2JqZWN0XG4gICAqXG4gICAqIHN0cmluZzogc2ltcGxlIHN0YXRpYyBicmVhZGNydW1iIGxhYmVsIGZvciBhIHBhdGhcbiAgICogZnVuY3Rpb246IGNhbGxiYWNrIHRoYXQgZ2V0cyBpbnZva2VkIHdpdGggcmVzb2x2ZWQgcGF0aCBwYXJhbVxuICAgKiBvYmplY3Q6IGFkZGl0aW9uYWwgZGF0YSBkZWZpbmVkIGFsb25nIHdpdGggYnJlYWRjcnVtYiBsYWJlbCB0aGF0IGdldHMgcGFzc2VkIHRvICp4bmdCcmVhZGNydW1iSXRlbSBkaXJlY3RpdmVcbiAgICovXG4gIHByaXZhdGUgZXh0cmFjdExhYmVsKGNvbmZpZzogQnJlYWRjcnVtYkNvbmZpZywgcmVzb2x2ZWRQYXJhbT86IHN0cmluZykge1xuICAgIGNvbnN0IGxhYmVsID0gdHlwZW9mIGNvbmZpZyA9PT0gJ29iamVjdCcgPyBjb25maWcubGFiZWwgOiBjb25maWc7XG4gICAgaWYgKHR5cGVvZiBsYWJlbCA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgcmV0dXJuIGxhYmVsKHJlc29sdmVkUGFyYW0pO1xuICAgIH1cbiAgICByZXR1cm4gbGFiZWw7XG4gIH1cblxuICBwcml2YXRlIGV4dHJhY3RPYmplY3QoY29uZmlnOiBCcmVhZGNydW1iQ29uZmlnKTogQnJlYWRjcnVtYk9iamVjdCB7XG4gICAgLy8gZG9uJ3QgaW5jbHVkZSB7bGFiZWx9IGlmIGNvbmZpZyBpcyB1bmRlZmluZWQuIFRoaXMgaXMgaW1wb3J0YW50IHNpbmNlIHdlIG1lcmdlIHRoZSBjb25maWdzXG4gICAgaWYgKGNvbmZpZyAmJiAodHlwZW9mIGNvbmZpZyA9PT0gJ3N0cmluZycgfHwgdHlwZW9mIGNvbmZpZyA9PT0gJ2Z1bmN0aW9uJykpIHtcbiAgICAgIHJldHVybiB7IGxhYmVsOiBjb25maWcgfTtcbiAgICB9XG4gICAgcmV0dXJuIChjb25maWcgYXMgQnJlYWRjcnVtYk9iamVjdCkgfHwge307XG4gIH1cbn1cbiJdfQ==","import { Component, ContentChild, inject, Input, TemplateRef, ViewEncapsulation } from '@angular/core';\nimport { CommonModule } from '@angular/common';\nimport { ActivatedRoute, RouterModule } from '@angular/router';\nimport { map } from 'rxjs';\nimport { BreadcrumbItemDirective } from './breadcrumb-item.directive';\nimport { BreadcrumbService } from './breadcrumb.service';\nimport * as i0 from \"@angular/core\";\nimport * as i1 from \"@angular/common\";\nimport * as i2 from \"@angular/router\";\nexport class BreadcrumbComponent {\n /**\n * separator between breadcrumbs, defaults to '/'.\n * User can customize separator either by passing a String or Template\n *\n * String --> Ex: <xng-breadcrumb separator=\"-\"> </xng-breadcrumb>\n *\n * Template --> Ex: <xng-breadcrumb [separator]=\"separatorTemplate\"> </xng-breadcrumb>\n * <ng-template #separatorTemplate><mat-icon>arrow_right</mat-icon></ng-template>\n */\n set separator(value) {\n if (value instanceof TemplateRef) {\n this.separatorTemplate = value;\n this._separator = undefined;\n }\n else {\n this.separatorTemplate = undefined;\n this._separator = value || '/';\n }\n }\n get separator() {\n return this._separator;\n }\n constructor() {\n this._separator = '/';\n /**\n * If true, breadcrumb is auto generated even without any mapping label\n * Default label is same as route segment\n */\n this.autoGenerate = true;\n /**\n * By default query params will be preserved with breadcrumbs\n */\n this.preserveQueryParams = true;\n /**\n * By default query fragments will be preserved with breadcrumbs\n */\n this.preserveFragment = true;\n /*