@jax-data-science/sci-image-visualizer 0.9.0 → 0.11.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/esm2022/index.mjs +10 -1
- package/esm2022/lib/contracts/image.contract.mjs +1 -1
- package/esm2022/lib/contracts/ports/region-io.port.mjs +1 -1
- package/esm2022/lib/contracts/region-editor-api.contract.mjs +1 -1
- package/esm2022/lib/contracts/region-store.contract.mjs +1 -1
- package/esm2022/lib/contracts/section-view.contract.mjs +2 -0
- package/esm2022/lib/contracts/visualizer.contract.mjs +1 -1
- package/esm2022/lib/contracts/viz-config.mjs +1 -1
- package/esm2022/lib/geometry/loft.mjs +128 -0
- package/esm2022/lib/geometry/polylabel.mjs +156 -0
- package/esm2022/lib/geometry/reconstruct.mjs +315 -0
- package/esm2022/lib/geometry/reslice-image.mjs +57 -0
- package/esm2022/lib/geometry/section.mjs +215 -0
- package/esm2022/lib/implementations/napari-js/napari-loading-badge.mjs +11 -7
- package/esm2022/lib/implementations/napari-js/napari-loading-state.mjs +20 -3
- package/esm2022/lib/implementations/napari-js/napari-region-mesh-pointer.mjs +100 -0
- package/esm2022/lib/implementations/napari-js/napari-region-overlay.mjs +28 -5
- package/esm2022/lib/implementations/napari-js/napari-scene.mjs +1 -1
- package/esm2022/lib/implementations/napari-js/napari-spatial-hover.mjs +9 -2
- package/esm2022/lib/implementations/napari-js/napari-tool-bridge.mjs +5 -2
- package/esm2022/lib/implementations/napari-js/napari-visualizer.service.mjs +81 -1
- package/esm2022/lib/implementations/napari-js/napari-volume-region-meshes.mjs +129 -0
- package/esm2022/lib/implementations/napari-js/napari-volume-scene.mjs +115 -4
- package/esm2022/lib/implementations/napari-js/napari-volume-slice-planes.mjs +103 -0
- package/esm2022/lib/implementations/napari-js/region-overlay/region-svg-renderer.mjs +15 -3
- package/esm2022/lib/implementations/osd/openseadragon-viewer-options.mjs +18 -2
- package/esm2022/lib/implementations/osd/openseadragon-visualizer.service.mjs +9 -1
- package/esm2022/lib/implementations/osd/osd-region-overlay-draw.mjs +18 -7
- package/esm2022/lib/implementations/osd/osd-region-overlay.mjs +38 -8
- package/esm2022/lib/implementations/osd/osd-tile-loading.mjs +71 -0
- package/esm2022/lib/implementations/osd/osd-viewer-like.mjs +1 -1
- package/esm2022/lib/implementations/osd/slice-cache.mjs +35 -6
- package/esm2022/lib/implementations/tile-server/tile-protocol.mjs +1 -1
- package/esm2022/lib/models/class-preset.mjs +1 -1
- package/esm2022/lib/models/polygon-factory.mjs +17 -1
- package/esm2022/lib/models/region-geojson.mjs +44 -6
- package/esm2022/lib/models/region.mjs +1 -1
- package/esm2022/lib/region-editor/class-tree/class-tree.component.mjs +156 -0
- package/esm2022/lib/region-editor/class-tree/class-tree.mjs +108 -0
- package/esm2022/lib/region-editor/classes-panel/classes-panel.component.mjs +77 -13
- package/esm2022/lib/region-editor/region-editor.component.mjs +670 -42
- package/esm2022/lib/region-editor/region-metrics.mjs +20 -2
- package/esm2022/lib/region-editor/region-persistence.service.mjs +44 -10
- package/esm2022/lib/region-editor/region-table/region-table.component.mjs +24 -8
- package/esm2022/lib/region-import/label-classes.mjs +149 -0
- package/esm2022/lib/region-import/label-volume.mjs +194 -0
- package/esm2022/lib/region-import/region-import.mjs +71 -0
- package/esm2022/lib/region-overlay/region-geometry.mjs +3 -3
- package/esm2022/lib/region-overlay/region-source-layer.mjs +378 -0
- package/esm2022/lib/region-overlay/region-style.mjs +97 -0
- package/esm2022/lib/region-source/http-region-source.mjs +104 -0
- package/esm2022/lib/region-source/region-source-ops.mjs +53 -0
- package/esm2022/lib/region-source/region-source-worker.mjs +10 -0
- package/esm2022/lib/region-source/region-source.mjs +67 -0
- package/esm2022/lib/region-source/region-tiles.mjs +708 -0
- package/esm2022/lib/region-source/worker-region-source.mjs +229 -0
- package/esm2022/lib/routing-visualizer.service.mjs +510 -22
- package/esm2022/lib/section-pane/section-pane.component.mjs +299 -0
- package/esm2022/lib/store/class-color.util.mjs +10 -5
- package/esm2022/lib/store/class-signatures.mjs +63 -0
- package/esm2022/lib/store/region-scope-cache.mjs +5 -1
- package/esm2022/lib/store/region-source-scope.mjs +186 -0
- package/esm2022/lib/store/region-store.service.mjs +774 -12
- package/esm2022/lib/store/visualizer-store.service.mjs +33 -6
- package/esm2022/lib/toolbar/region-tools/region-tools.component.mjs +8 -2
- package/esm2022/lib/toolbar/stack-controls/stack-controls.component.mjs +55 -15
- package/esm2022/lib/toolbar/toolbar.component.mjs +19 -5
- package/esm2022/lib/visualizer/region-load.mjs +67 -4
- package/esm2022/lib/visualizer/volume-sections.mjs +175 -0
- package/esm2022/lib/visualizer.component.mjs +155 -7
- package/fesm2022/{jax-data-science-sci-image-visualizer-jax-data-science-sci-image-visualizer-Csxlnq7I.mjs → jax-data-science-sci-image-visualizer-jax-data-science-sci-image-visualizer-BELcx0jv.mjs} +9851 -2904
- package/fesm2022/jax-data-science-sci-image-visualizer-jax-data-science-sci-image-visualizer-BELcx0jv.mjs.map +1 -0
- package/fesm2022/{jax-data-science-sci-image-visualizer-onnx-sam-session-Bkujqg7m.mjs → jax-data-science-sci-image-visualizer-onnx-sam-session-DEDSm_NL.mjs} +4 -4
- package/fesm2022/{jax-data-science-sci-image-visualizer-onnx-sam-session-Bkujqg7m.mjs.map → jax-data-science-sci-image-visualizer-onnx-sam-session-DEDSm_NL.mjs.map} +1 -1
- package/fesm2022/jax-data-science-sci-image-visualizer-region-source-worker-CAqBjM5L.mjs +12 -0
- package/fesm2022/jax-data-science-sci-image-visualizer-region-source-worker-CAqBjM5L.mjs.map +1 -0
- package/fesm2022/jax-data-science-sci-image-visualizer.mjs +3 -3
- package/fesm2022/region-source.worker.js +1067 -0
- package/index.d.ts +12 -0
- package/lib/contracts/image.contract.d.ts +4 -0
- package/lib/contracts/ports/region-io.port.d.ts +24 -0
- package/lib/contracts/region-editor-api.contract.d.ts +102 -0
- package/lib/contracts/region-store.contract.d.ts +22 -0
- package/lib/contracts/section-view.contract.d.ts +44 -0
- package/lib/contracts/visualizer.contract.d.ts +10 -0
- package/lib/contracts/viz-config.d.ts +8 -0
- package/lib/geometry/loft.d.ts +22 -0
- package/lib/geometry/polylabel.d.ts +23 -0
- package/lib/geometry/reconstruct.d.ts +54 -0
- package/lib/geometry/reslice-image.d.ts +33 -0
- package/lib/geometry/section.d.ts +52 -0
- package/lib/implementations/napari-js/napari-loading-badge.d.ts +4 -2
- package/lib/implementations/napari-js/napari-loading-state.d.ts +8 -1
- package/lib/implementations/napari-js/napari-region-mesh-pointer.d.ts +32 -0
- package/lib/implementations/napari-js/napari-region-overlay.d.ts +6 -1
- package/lib/implementations/napari-js/napari-scene.d.ts +33 -0
- package/lib/implementations/napari-js/napari-spatial-hover.d.ts +3 -1
- package/lib/implementations/napari-js/napari-visualizer.service.d.ts +48 -0
- package/lib/implementations/napari-js/napari-volume-region-meshes.d.ts +66 -0
- package/lib/implementations/napari-js/napari-volume-scene.d.ts +45 -1
- package/lib/implementations/napari-js/napari-volume-slice-planes.d.ts +43 -0
- package/lib/implementations/osd/openseadragon-viewer-options.d.ts +2 -0
- package/lib/implementations/osd/openseadragon-visualizer.service.d.ts +2 -0
- package/lib/implementations/osd/osd-region-overlay-draw.d.ts +4 -3
- package/lib/implementations/osd/osd-region-overlay.d.ts +10 -3
- package/lib/implementations/osd/osd-tile-loading.d.ts +43 -0
- package/lib/implementations/osd/osd-viewer-like.d.ts +14 -0
- package/lib/implementations/osd/slice-cache.d.ts +13 -3
- package/lib/implementations/tile-server/tile-protocol.d.ts +3 -0
- package/lib/models/class-preset.d.ts +7 -0
- package/lib/models/polygon-factory.d.ts +5 -0
- package/lib/models/region-geojson.d.ts +40 -0
- package/lib/models/region.d.ts +19 -0
- package/lib/region-editor/class-tree/class-tree.component.d.ts +78 -0
- package/lib/region-editor/class-tree/class-tree.d.ts +31 -0
- package/lib/region-editor/classes-panel/classes-panel.component.d.ts +36 -6
- package/lib/region-editor/region-editor.component.d.ts +159 -17
- package/lib/region-editor/region-metrics.d.ts +8 -0
- package/lib/region-editor/region-persistence.service.d.ts +17 -5
- package/lib/region-editor/region-table/region-table.component.d.ts +10 -4
- package/lib/region-import/label-classes.d.ts +39 -0
- package/lib/region-import/label-volume.d.ts +31 -0
- package/lib/region-import/region-import.d.ts +46 -0
- package/lib/region-overlay/region-geometry.d.ts +4 -3
- package/lib/region-overlay/region-source-layer.d.ts +96 -0
- package/lib/region-overlay/region-style.d.ts +52 -0
- package/lib/region-source/http-region-source.d.ts +45 -0
- package/lib/region-source/region-source-ops.d.ts +89 -0
- package/lib/region-source/region-source-worker.d.ts +7 -0
- package/lib/region-source/region-source.d.ts +82 -0
- package/lib/region-source/region-tiles.d.ts +289 -0
- package/lib/region-source/worker-region-source.d.ts +65 -0
- package/lib/routing-visualizer.service.d.ts +168 -1
- package/lib/section-pane/section-pane.component.d.ts +47 -0
- package/lib/store/class-color.util.d.ts +6 -3
- package/lib/store/class-signatures.d.ts +11 -0
- package/lib/store/region-scope-cache.d.ts +2 -0
- package/lib/store/region-source-scope.d.ts +74 -0
- package/lib/store/region-store.service.d.ts +216 -2
- package/lib/store/visualizer-store.service.d.ts +10 -0
- package/lib/toolbar/region-tools/region-tools.component.d.ts +3 -1
- package/lib/toolbar/stack-controls/stack-controls.component.d.ts +20 -9
- package/lib/toolbar/toolbar.component.d.ts +9 -2
- package/lib/visualizer/region-load.d.ts +23 -4
- package/lib/visualizer/volume-sections.d.ts +64 -0
- package/lib/visualizer.component.d.ts +40 -0
- package/package.json +2 -2
- package/src/lib/assets/slice.svg +23 -0
- package/fesm2022/jax-data-science-sci-image-visualizer-jax-data-science-sci-image-visualizer-Csxlnq7I.mjs.map +0 -1
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
import { ChangeDetectionStrategy, Component, ElementRef, EventEmitter, Input, Output, } from '@angular/core';
|
|
2
|
+
import { CommonModule } from '@angular/common';
|
|
3
|
+
import { FormsModule } from '@angular/forms';
|
|
4
|
+
import { InputTextModule } from 'primeng/inputtext';
|
|
5
|
+
import { TooltipModule } from 'primeng/tooltip';
|
|
6
|
+
import { HexColorPickerComponent } from '../../hex-color-picker/hex-color-picker.component';
|
|
7
|
+
import { ancestors, buildClassTree, subtree, visibleRows } from './class-tree';
|
|
8
|
+
import * as i0 from "@angular/core";
|
|
9
|
+
import * as i1 from "@angular/common";
|
|
10
|
+
import * as i2 from "@angular/forms";
|
|
11
|
+
import * as i3 from "primeng/inputtext";
|
|
12
|
+
import * as i4 from "primeng/tooltip";
|
|
13
|
+
/**
|
|
14
|
+
* The Region Editor's classes as a hierarchy (a brain atlas's ontology), as the Allen atlas viewer
|
|
15
|
+
* shows it: collapsible, each class with its colour, name and long name, and the regions it and
|
|
16
|
+
* its subclasses have on this slice; a class with none is greyed. Picking a class selects all its
|
|
17
|
+
* regions and its subclasses' (the editor does the selecting). Search by name or long name. A
|
|
18
|
+
* class's swatch recolours it, as the class list's does; its eye hides it and its subclasses.
|
|
19
|
+
*/
|
|
20
|
+
export class ClassTreeComponent {
|
|
21
|
+
constructor(el) {
|
|
22
|
+
this.el = el;
|
|
23
|
+
/** The hierarchy. */
|
|
24
|
+
this.nodes = [];
|
|
25
|
+
/** Regions per class on this slice (the regions and the region source's). */
|
|
26
|
+
this.counts = new Map();
|
|
27
|
+
/** A class's colour (a new function when the colours change, so the rows repaint). */
|
|
28
|
+
this.colorOf = () => '#999999';
|
|
29
|
+
/** The class picked last (highlighted, its path expanded, scrolled into view). */
|
|
30
|
+
this.picked = null;
|
|
31
|
+
/** Classes with a selected region (marked). */
|
|
32
|
+
this.marked = new Set();
|
|
33
|
+
/** Whether a volume view is on screen: each class can then be shown in 3D. */
|
|
34
|
+
this.volume = false;
|
|
35
|
+
/** The classes shown in 3D. */
|
|
36
|
+
this.shown3d = new Set();
|
|
37
|
+
/** The classes hidden from view. */
|
|
38
|
+
this.hidden = new Set();
|
|
39
|
+
this.pick = new EventEmitter();
|
|
40
|
+
/** A class's swatch picked a new colour. */
|
|
41
|
+
this.recolor = new EventEmitter();
|
|
42
|
+
/** A class's 3D toggle: it with every class under it. */
|
|
43
|
+
this.toggle3d = new EventEmitter();
|
|
44
|
+
/** A class's eye: hide (or show) it with every class under it. */
|
|
45
|
+
this.toggleHidden = new EventEmitter();
|
|
46
|
+
this.tree = buildClassTree([], new Map());
|
|
47
|
+
this.rows = [];
|
|
48
|
+
/** Each row's visibility (a row absent: shown). */
|
|
49
|
+
this.visibility = new Map();
|
|
50
|
+
this.query = '';
|
|
51
|
+
this.expanded = new Set();
|
|
52
|
+
this.trackRow = (_, r) => r.name;
|
|
53
|
+
}
|
|
54
|
+
ngOnChanges(changes) {
|
|
55
|
+
const fresh = !!changes['nodes'];
|
|
56
|
+
if (fresh || changes['counts'])
|
|
57
|
+
this.tree = buildClassTree(this.nodes, this.counts);
|
|
58
|
+
// A new hierarchy opens with its roots expanded, as the atlas viewer does.
|
|
59
|
+
if (fresh)
|
|
60
|
+
this.expanded = new Set(this.tree.roots);
|
|
61
|
+
if (changes['picked'] && this.picked)
|
|
62
|
+
for (const a of ancestors(this.tree, this.picked))
|
|
63
|
+
this.expanded.add(a);
|
|
64
|
+
this.refresh();
|
|
65
|
+
// A pick from elsewhere (a surface clicked in 3D) may be off screen: bring its row into view.
|
|
66
|
+
if (changes['picked'] && this.picked)
|
|
67
|
+
setTimeout(() => scrollToPicked(this.el.nativeElement, '.tree-row.picked'));
|
|
68
|
+
}
|
|
69
|
+
node(name) {
|
|
70
|
+
return this.tree.node.get(name);
|
|
71
|
+
}
|
|
72
|
+
total(name) {
|
|
73
|
+
return this.tree.total.get(name) ?? 0;
|
|
74
|
+
}
|
|
75
|
+
toggle(row, event) {
|
|
76
|
+
event.stopPropagation();
|
|
77
|
+
if (this.expanded.has(row.name))
|
|
78
|
+
this.expanded.delete(row.name);
|
|
79
|
+
else
|
|
80
|
+
this.expanded.add(row.name);
|
|
81
|
+
this.refresh();
|
|
82
|
+
}
|
|
83
|
+
choose(name, event) {
|
|
84
|
+
const e = event;
|
|
85
|
+
this.pick.emit({ name, classes: subtree(this.tree, name), additive: e.shiftKey || e.metaKey || e.ctrlKey });
|
|
86
|
+
}
|
|
87
|
+
/** The eye: a class hidden (wholly) is shown again with its subclasses; otherwise they are hidden. */
|
|
88
|
+
flipHidden(name, event) {
|
|
89
|
+
event.stopPropagation();
|
|
90
|
+
const hidden = this.visibility.get(name) !== 'hidden';
|
|
91
|
+
this.toggleHidden.emit({ classes: subtree(this.tree, name), hidden });
|
|
92
|
+
}
|
|
93
|
+
flip3d(name, event) {
|
|
94
|
+
event.stopPropagation();
|
|
95
|
+
this.toggle3d.emit({ name, classes: subtree(this.tree, name) });
|
|
96
|
+
}
|
|
97
|
+
onQuery(value) {
|
|
98
|
+
this.query = value;
|
|
99
|
+
this.refresh();
|
|
100
|
+
}
|
|
101
|
+
/** Enter in the search box picks the first match. */
|
|
102
|
+
pickFirstMatch(event) {
|
|
103
|
+
const q = this.query.trim().toLowerCase();
|
|
104
|
+
const hit = this.rows.find((r) => r.name.toLowerCase().includes(q) || (this.node(r.name)?.title ?? '').toLowerCase().includes(q));
|
|
105
|
+
if (hit)
|
|
106
|
+
this.choose(hit.name, event);
|
|
107
|
+
}
|
|
108
|
+
refresh() {
|
|
109
|
+
this.rows = visibleRows(this.tree, this.expanded, this.query);
|
|
110
|
+
this.visibility = new Map();
|
|
111
|
+
if (!this.hidden.size)
|
|
112
|
+
return;
|
|
113
|
+
for (const row of this.rows) {
|
|
114
|
+
const classes = subtree(this.tree, row.name);
|
|
115
|
+
const off = classes.filter((c) => this.hidden.has(c)).length;
|
|
116
|
+
if (off)
|
|
117
|
+
this.visibility.set(row.name, off === classes.length ? 'hidden' : 'partial');
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.9", ngImport: i0, type: ClassTreeComponent, deps: [{ token: i0.ElementRef }], target: i0.ɵɵFactoryTarget.Component }); }
|
|
121
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.3.9", type: ClassTreeComponent, isStandalone: true, selector: "region-class-tree", inputs: { nodes: "nodes", counts: "counts", colorOf: "colorOf", picked: "picked", marked: "marked", volume: "volume", shown3d: "shown3d", hidden: "hidden" }, outputs: { pick: "pick", recolor: "recolor", toggle3d: "toggle3d", toggleHidden: "toggleHidden" }, usesOnChanges: true, ngImport: i0, template: "<div class=\"class-tree\">\n <div class=\"tree-header\" *ngIf=\"picked as p\">\n <span class=\"tree-picked\">\n <b>{{ p }}</b\n ><span *ngIf=\"node(p)?.title as t\"> \u00B7 {{ t }}</span>\n </span>\n </div>\n <input\n type=\"text\"\n pInputText\n class=\"p-inputtext-sm tree-search\"\n placeholder=\"Search by name\"\n aria-label=\"Search the classes\"\n [ngModel]=\"query\"\n (ngModelChange)=\"onQuery($event)\"\n (keydown.enter)=\"pickFirstMatch($event)\"\n />\n <div class=\"tree-body\" role=\"tree\">\n <div\n *ngFor=\"let row of rows; trackBy: trackRow\"\n class=\"tree-row\"\n role=\"treeitem\"\n tabindex=\"0\"\n [attr.aria-expanded]=\"row.hasChildren ? row.expanded : null\"\n [class.absent]=\"total(row.name) === 0\"\n [class.picked]=\"row.name === picked\"\n [class.marked]=\"marked.has(row.name)\"\n [class.hidden-class]=\"visibility.get(row.name) === 'hidden'\"\n [style.padding-left.rem]=\"0.35 + row.depth * 0.9\"\n [pTooltip]=\"node(row.name)?.title || row.name\"\n tooltipPosition=\"left\"\n [showDelay]=\"600\"\n (click)=\"choose(row.name, $event)\"\n (keydown.enter)=\"choose(row.name, $event)\"\n >\n <i\n class=\"pi tree-toggle\"\n [class.pi-minus-circle]=\"row.hasChildren && row.expanded\"\n [class.pi-plus-circle]=\"row.hasChildren && !row.expanded\"\n [attr.aria-label]=\"row.expanded ? 'Collapse' : 'Expand'\"\n (click)=\"row.hasChildren && toggle(row, $event)\"\n ></i>\n <i\n class=\"pi tree-eye\"\n [ngClass]=\"visibility.get(row.name) === 'hidden' ? 'pi-eye-slash' : 'pi-eye'\"\n [class.partial]=\"visibility.get(row.name) === 'partial'\"\n role=\"button\"\n [attr.aria-pressed]=\"visibility.get(row.name) !== 'hidden'\"\n [attr.aria-label]=\"(visibility.get(row.name) === 'hidden' ? 'Show ' : 'Hide ') + row.name\"\n [pTooltip]=\"\n (visibility.get(row.name) === 'hidden' ? 'Show' : 'Hide') +\n (row.hasChildren ? ' it and its subclasses' : '') +\n (visibility.get(row.name) === 'partial' ? ' (some are hidden)' : '')\n \"\n tooltipPosition=\"left\"\n (click)=\"flipHidden(row.name, $event)\"\n (keydown.enter)=\"flipHidden(row.name, $event)\"\n ></i>\n <span class=\"tree-swatch\" (click)=\"$event.stopPropagation()\" (keydown.enter)=\"$event.stopPropagation()\">\n <hex-color-picker\n [color]=\"colorOf(row.name)\"\n (colorChange)=\"recolor.emit({ name: row.name, color: $event })\"\n >\n </hex-color-picker>\n </span>\n <span class=\"tree-name\">{{ row.name }}</span>\n <span class=\"tree-long\">{{ node(row.name)?.title }}</span>\n <span class=\"tree-count\" *ngIf=\"total(row.name) > 0\">{{ total(row.name) }}</span>\n <i\n *ngIf=\"volume\"\n class=\"pi pi-box tree-3d\"\n [class.on]=\"shown3d.has(row.name)\"\n role=\"button\"\n [attr.aria-pressed]=\"shown3d.has(row.name)\"\n [attr.aria-label]=\"'Show ' + row.name + ' in 3D'\"\n pTooltip=\"Show in the volume, in 3D\"\n tooltipPosition=\"left\"\n (click)=\"flip3d(row.name, $event)\"\n ></i>\n </div>\n <div *ngIf=\"!rows.length\" class=\"tree-empty\">No class matches.</div>\n </div>\n</div>\n", styles: [":host{display:block;flex:0 0 auto}.class-tree{display:flex;flex-direction:column;padding-top:.25rem}.tree-header{display:flex;align-items:baseline;gap:.5rem;padding:0 .5rem .25rem}.tree-picked{font-size:.8rem;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.tree-search{margin:0 .5rem .25rem}.tree-body{height:14rem;min-height:3rem;max-height:70vh;overflow:auto;resize:vertical;padding-bottom:.25rem}.tree-row{display:flex;align-items:center;gap:.35rem;padding-top:.05rem;padding-bottom:.05rem;padding-right:.5rem;cursor:pointer;font-size:.8rem;white-space:nowrap}.tree-row:hover,.tree-row:focus-visible{background:var(--surface-hover, rgba(0, 0, 0, .04))}.tree-row.picked{background:var(--highlight-bg, rgba(51, 153, 255, .15))}.tree-row.marked{box-shadow:inset 3px 0 0 var(--primary-color)}.tree-row.absent{color:var(--text-color-secondary, #8a8a8a);font-style:italic;opacity:.7}.tree-toggle{flex:0 0 .9rem;font-size:.75rem;color:var(--text-color-secondary)}.tree-swatch{flex:0 0 auto;display:inline-flex}::ng-deep region-class-tree .tree-swatch .hex-picker-swatch{width:.8rem;height:.8rem;border-width:1px;border-radius:0}.tree-name{font-weight:700}.absent .tree-name{font-weight:400}.tree-long{min-width:0;overflow:hidden;text-overflow:ellipsis;flex:1 1 auto}.tree-count{flex:0 0 auto;font-size:.7rem;color:var(--text-color-secondary)}.tree-empty{padding:.5rem;font-size:.8rem;color:var(--text-color-secondary)}.tree-3d{flex:0 0 auto;font-size:.8rem;opacity:.35;cursor:pointer}.tree-3d:hover{opacity:.8}.tree-3d.on{opacity:1;color:var(--primary-color)}.tree-eye{flex:0 0 auto;font-size:.8rem;opacity:.4;cursor:pointer}.tree-eye:hover{opacity:.9}.tree-eye.partial{opacity:.7;color:var(--primary-color)}.tree-row.hidden-class .tree-eye{opacity:1}.tree-row.hidden-class .tree-swatch,.tree-row.hidden-class .tree-name,.tree-row.hidden-class .tree-long,.tree-row.hidden-class .tree-count{opacity:.45}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i2.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: InputTextModule }, { kind: "directive", type: i3.InputText, selector: "[pInputText]", inputs: ["variant"] }, { kind: "ngmodule", type: TooltipModule }, { kind: "directive", type: i4.Tooltip, selector: "[pTooltip]", inputs: ["tooltipPosition", "tooltipEvent", "appendTo", "positionStyle", "tooltipStyleClass", "tooltipZIndex", "escape", "showDelay", "hideDelay", "life", "positionTop", "positionLeft", "autoHide", "fitContent", "hideOnEscape", "pTooltip", "tooltipDisabled", "tooltipOptions"] }, { kind: "component", type: HexColorPickerComponent, selector: "hex-color-picker", inputs: ["color"], outputs: ["colorChange", "colorInput"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
122
|
+
}
|
|
123
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.9", ngImport: i0, type: ClassTreeComponent, decorators: [{
|
|
124
|
+
type: Component,
|
|
125
|
+
args: [{ selector: 'region-class-tree', standalone: true, imports: [CommonModule, FormsModule, InputTextModule, TooltipModule, HexColorPickerComponent], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"class-tree\">\n <div class=\"tree-header\" *ngIf=\"picked as p\">\n <span class=\"tree-picked\">\n <b>{{ p }}</b\n ><span *ngIf=\"node(p)?.title as t\"> \u00B7 {{ t }}</span>\n </span>\n </div>\n <input\n type=\"text\"\n pInputText\n class=\"p-inputtext-sm tree-search\"\n placeholder=\"Search by name\"\n aria-label=\"Search the classes\"\n [ngModel]=\"query\"\n (ngModelChange)=\"onQuery($event)\"\n (keydown.enter)=\"pickFirstMatch($event)\"\n />\n <div class=\"tree-body\" role=\"tree\">\n <div\n *ngFor=\"let row of rows; trackBy: trackRow\"\n class=\"tree-row\"\n role=\"treeitem\"\n tabindex=\"0\"\n [attr.aria-expanded]=\"row.hasChildren ? row.expanded : null\"\n [class.absent]=\"total(row.name) === 0\"\n [class.picked]=\"row.name === picked\"\n [class.marked]=\"marked.has(row.name)\"\n [class.hidden-class]=\"visibility.get(row.name) === 'hidden'\"\n [style.padding-left.rem]=\"0.35 + row.depth * 0.9\"\n [pTooltip]=\"node(row.name)?.title || row.name\"\n tooltipPosition=\"left\"\n [showDelay]=\"600\"\n (click)=\"choose(row.name, $event)\"\n (keydown.enter)=\"choose(row.name, $event)\"\n >\n <i\n class=\"pi tree-toggle\"\n [class.pi-minus-circle]=\"row.hasChildren && row.expanded\"\n [class.pi-plus-circle]=\"row.hasChildren && !row.expanded\"\n [attr.aria-label]=\"row.expanded ? 'Collapse' : 'Expand'\"\n (click)=\"row.hasChildren && toggle(row, $event)\"\n ></i>\n <i\n class=\"pi tree-eye\"\n [ngClass]=\"visibility.get(row.name) === 'hidden' ? 'pi-eye-slash' : 'pi-eye'\"\n [class.partial]=\"visibility.get(row.name) === 'partial'\"\n role=\"button\"\n [attr.aria-pressed]=\"visibility.get(row.name) !== 'hidden'\"\n [attr.aria-label]=\"(visibility.get(row.name) === 'hidden' ? 'Show ' : 'Hide ') + row.name\"\n [pTooltip]=\"\n (visibility.get(row.name) === 'hidden' ? 'Show' : 'Hide') +\n (row.hasChildren ? ' it and its subclasses' : '') +\n (visibility.get(row.name) === 'partial' ? ' (some are hidden)' : '')\n \"\n tooltipPosition=\"left\"\n (click)=\"flipHidden(row.name, $event)\"\n (keydown.enter)=\"flipHidden(row.name, $event)\"\n ></i>\n <span class=\"tree-swatch\" (click)=\"$event.stopPropagation()\" (keydown.enter)=\"$event.stopPropagation()\">\n <hex-color-picker\n [color]=\"colorOf(row.name)\"\n (colorChange)=\"recolor.emit({ name: row.name, color: $event })\"\n >\n </hex-color-picker>\n </span>\n <span class=\"tree-name\">{{ row.name }}</span>\n <span class=\"tree-long\">{{ node(row.name)?.title }}</span>\n <span class=\"tree-count\" *ngIf=\"total(row.name) > 0\">{{ total(row.name) }}</span>\n <i\n *ngIf=\"volume\"\n class=\"pi pi-box tree-3d\"\n [class.on]=\"shown3d.has(row.name)\"\n role=\"button\"\n [attr.aria-pressed]=\"shown3d.has(row.name)\"\n [attr.aria-label]=\"'Show ' + row.name + ' in 3D'\"\n pTooltip=\"Show in the volume, in 3D\"\n tooltipPosition=\"left\"\n (click)=\"flip3d(row.name, $event)\"\n ></i>\n </div>\n <div *ngIf=\"!rows.length\" class=\"tree-empty\">No class matches.</div>\n </div>\n</div>\n", styles: [":host{display:block;flex:0 0 auto}.class-tree{display:flex;flex-direction:column;padding-top:.25rem}.tree-header{display:flex;align-items:baseline;gap:.5rem;padding:0 .5rem .25rem}.tree-picked{font-size:.8rem;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.tree-search{margin:0 .5rem .25rem}.tree-body{height:14rem;min-height:3rem;max-height:70vh;overflow:auto;resize:vertical;padding-bottom:.25rem}.tree-row{display:flex;align-items:center;gap:.35rem;padding-top:.05rem;padding-bottom:.05rem;padding-right:.5rem;cursor:pointer;font-size:.8rem;white-space:nowrap}.tree-row:hover,.tree-row:focus-visible{background:var(--surface-hover, rgba(0, 0, 0, .04))}.tree-row.picked{background:var(--highlight-bg, rgba(51, 153, 255, .15))}.tree-row.marked{box-shadow:inset 3px 0 0 var(--primary-color)}.tree-row.absent{color:var(--text-color-secondary, #8a8a8a);font-style:italic;opacity:.7}.tree-toggle{flex:0 0 .9rem;font-size:.75rem;color:var(--text-color-secondary)}.tree-swatch{flex:0 0 auto;display:inline-flex}::ng-deep region-class-tree .tree-swatch .hex-picker-swatch{width:.8rem;height:.8rem;border-width:1px;border-radius:0}.tree-name{font-weight:700}.absent .tree-name{font-weight:400}.tree-long{min-width:0;overflow:hidden;text-overflow:ellipsis;flex:1 1 auto}.tree-count{flex:0 0 auto;font-size:.7rem;color:var(--text-color-secondary)}.tree-empty{padding:.5rem;font-size:.8rem;color:var(--text-color-secondary)}.tree-3d{flex:0 0 auto;font-size:.8rem;opacity:.35;cursor:pointer}.tree-3d:hover{opacity:.8}.tree-3d.on{opacity:1;color:var(--primary-color)}.tree-eye{flex:0 0 auto;font-size:.8rem;opacity:.4;cursor:pointer}.tree-eye:hover{opacity:.9}.tree-eye.partial{opacity:.7;color:var(--primary-color)}.tree-row.hidden-class .tree-eye{opacity:1}.tree-row.hidden-class .tree-swatch,.tree-row.hidden-class .tree-name,.tree-row.hidden-class .tree-long,.tree-row.hidden-class .tree-count{opacity:.45}\n"] }]
|
|
126
|
+
}], ctorParameters: () => [{ type: i0.ElementRef }], propDecorators: { nodes: [{
|
|
127
|
+
type: Input
|
|
128
|
+
}], counts: [{
|
|
129
|
+
type: Input
|
|
130
|
+
}], colorOf: [{
|
|
131
|
+
type: Input
|
|
132
|
+
}], picked: [{
|
|
133
|
+
type: Input
|
|
134
|
+
}], marked: [{
|
|
135
|
+
type: Input
|
|
136
|
+
}], volume: [{
|
|
137
|
+
type: Input
|
|
138
|
+
}], shown3d: [{
|
|
139
|
+
type: Input
|
|
140
|
+
}], hidden: [{
|
|
141
|
+
type: Input
|
|
142
|
+
}], pick: [{
|
|
143
|
+
type: Output
|
|
144
|
+
}], recolor: [{
|
|
145
|
+
type: Output
|
|
146
|
+
}], toggle3d: [{
|
|
147
|
+
type: Output
|
|
148
|
+
}], toggleHidden: [{
|
|
149
|
+
type: Output
|
|
150
|
+
}] } });
|
|
151
|
+
/** Scroll the row matching `selector` inside `host` into view, if it is out of it. */
|
|
152
|
+
export function scrollToPicked(host, selector) {
|
|
153
|
+
const row = host.querySelector(selector);
|
|
154
|
+
row?.scrollIntoView?.({ block: 'nearest' });
|
|
155
|
+
}
|
|
156
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2xhc3MtdHJlZS5jb21wb25lbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi9zcmMvbGliL3JlZ2lvbi1lZGl0b3IvY2xhc3MtdHJlZS9jbGFzcy10cmVlLmNvbXBvbmVudC50cyIsIi4uLy4uLy4uLy4uLy4uL3NyYy9saWIvcmVnaW9uLWVkaXRvci9jbGFzcy10cmVlL2NsYXNzLXRyZWUuY29tcG9uZW50Lmh0bWwiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUNMLHVCQUF1QixFQUN2QixTQUFTLEVBQ1QsVUFBVSxFQUNWLFlBQVksRUFDWixLQUFLLEVBRUwsTUFBTSxHQUVQLE1BQU0sZUFBZSxDQUFDO0FBQ3ZCLE9BQU8sRUFBRSxZQUFZLEVBQUUsTUFBTSxpQkFBaUIsQ0FBQztBQUMvQyxPQUFPLEVBQUUsV0FBVyxFQUFFLE1BQU0sZ0JBQWdCLENBQUM7QUFDN0MsT0FBTyxFQUFFLGVBQWUsRUFBRSxNQUFNLG1CQUFtQixDQUFDO0FBQ3BELE9BQU8sRUFBRSxhQUFhLEVBQUUsTUFBTSxpQkFBaUIsQ0FBQztBQUdoRCxPQUFPLEVBQUUsdUJBQXVCLEVBQUUsTUFBTSxtREFBbUQsQ0FBQztBQUM1RixPQUFPLEVBQTJCLFNBQVMsRUFBRSxjQUFjLEVBQUUsT0FBTyxFQUFFLFdBQVcsRUFBRSxNQUFNLGNBQWMsQ0FBQzs7Ozs7O0FBWXhHOzs7Ozs7R0FNRztBQVNILE1BQU0sT0FBTyxrQkFBa0I7SUFpQzdCLFlBQTZCLEVBQTJCO1FBQTNCLE9BQUUsR0FBRixFQUFFLENBQXlCO1FBaEN4RCxxQkFBcUI7UUFDWixVQUFLLEdBQStCLEVBQUUsQ0FBQztRQUNoRCw2RUFBNkU7UUFDcEUsV0FBTSxHQUFnQyxJQUFJLEdBQUcsRUFBRSxDQUFDO1FBQ3pELHNGQUFzRjtRQUM3RSxZQUFPLEdBQTZCLEdBQUcsRUFBRSxDQUFDLFNBQVMsQ0FBQztRQUM3RCxrRkFBa0Y7UUFDekUsV0FBTSxHQUFrQixJQUFJLENBQUM7UUFDdEMsK0NBQStDO1FBQ3RDLFdBQU0sR0FBd0IsSUFBSSxHQUFHLEVBQUUsQ0FBQztRQUNqRCw4RUFBOEU7UUFDckUsV0FBTSxHQUFHLEtBQUssQ0FBQztRQUN4QiwrQkFBK0I7UUFDdEIsWUFBTyxHQUF3QixJQUFJLEdBQUcsRUFBRSxDQUFDO1FBQ2xELG9DQUFvQztRQUMzQixXQUFNLEdBQXdCLElBQUksR0FBRyxFQUFFLENBQUM7UUFFdkMsU0FBSSxHQUFHLElBQUksWUFBWSxFQUFpQixDQUFDO1FBQ25ELDRDQUE0QztRQUNsQyxZQUFPLEdBQUcsSUFBSSxZQUFZLEVBQW1DLENBQUM7UUFDeEUseURBQXlEO1FBQy9DLGFBQVEsR0FBRyxJQUFJLFlBQVksRUFBdUMsQ0FBQztRQUM3RSxrRUFBa0U7UUFDeEQsaUJBQVksR0FBRyxJQUFJLFlBQVksRUFBMEMsQ0FBQztRQUUxRSxTQUFJLEdBQWMsY0FBYyxDQUFDLEVBQUUsRUFBRSxJQUFJLEdBQUcsRUFBRSxDQUFDLENBQUM7UUFDaEQsU0FBSSxHQUFtQixFQUFFLENBQUM7UUFDcEMsbURBQW1EO1FBQ3pDLGVBQVUsR0FBRyxJQUFJLEdBQUcsRUFBMkIsQ0FBQztRQUNoRCxVQUFLLEdBQUcsRUFBRSxDQUFDO1FBQ2IsYUFBUSxHQUFHLElBQUksR0FBRyxFQUFVLENBQUM7UUE4RGxCLGFBQVEsR0FBRyxDQUFDLENBQVMsRUFBRSxDQUFlLEVBQUUsRUFBRSxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUM7SUE1RFYsQ0FBQztJQUU1RCxXQUFXLENBQUMsT0FBc0I7UUFDaEMsTUFBTSxLQUFLLEdBQUcsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxPQUFPLENBQUMsQ0FBQztRQUNqQyxJQUFJLEtBQUssSUFBSSxPQUFPLENBQUMsUUFBUSxDQUFDO1lBQUUsSUFBSSxDQUFDLElBQUksR0FBRyxjQUFjLENBQUMsSUFBSSxDQUFDLEtBQUssRUFBRSxJQUFJLENBQUMsTUFBTSxDQUFDLENBQUM7UUFDcEYsMkVBQTJFO1FBQzNFLElBQUksS0FBSztZQUFFLElBQUksQ0FBQyxRQUFRLEdBQUcsSUFBSSxHQUFHLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsQ0FBQztRQUNwRCxJQUFJLE9BQU8sQ0FBQyxRQUFRLENBQUMsSUFBSSxJQUFJLENBQUMsTUFBTTtZQUFFLEtBQUssTUFBTSxDQUFDLElBQUksU0FBUyxDQUFDLElBQUksQ0FBQyxJQUFJLEVBQUUsSUFBSSxDQUFDLE1BQU0sQ0FBQztnQkFBRSxJQUFJLENBQUMsUUFBUSxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUM5RyxJQUFJLENBQUMsT0FBTyxFQUFFLENBQUM7UUFDZiw4RkFBOEY7UUFDOUYsSUFBSSxPQUFPLENBQUMsUUFBUSxDQUFDLElBQUksSUFBSSxDQUFDLE1BQU07WUFDbEMsVUFBVSxDQUFDLEdBQUcsRUFBRSxDQUFDLGNBQWMsQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDLGFBQWEsRUFBRSxrQkFBa0IsQ0FBQyxDQUFDLENBQUM7SUFDaEYsQ0FBQztJQUVTLElBQUksQ0FBQyxJQUFZO1FBQ3pCLE9BQU8sSUFBSSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDLElBQUksQ0FBQyxDQUFDO0lBQ2xDLENBQUM7SUFFUyxLQUFLLENBQUMsSUFBWTtRQUMxQixPQUFPLElBQUksQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUM7SUFDeEMsQ0FBQztJQUVTLE1BQU0sQ0FBQyxHQUFpQixFQUFFLEtBQVk7UUFDOUMsS0FBSyxDQUFDLGVBQWUsRUFBRSxDQUFDO1FBQ3hCLElBQUksSUFBSSxDQUFDLFFBQVEsQ0FBQyxHQUFHLENBQUMsR0FBRyxDQUFDLElBQUksQ0FBQztZQUFFLElBQUksQ0FBQyxRQUFRLENBQUMsTUFBTSxDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUMsQ0FBQzs7WUFDM0QsSUFBSSxDQUFDLFFBQVEsQ0FBQyxHQUFHLENBQUMsR0FBRyxDQUFDLElBQUksQ0FBQyxDQUFDO1FBQ2pDLElBQUksQ0FBQyxPQUFPLEVBQUUsQ0FBQztJQUNqQixDQUFDO0lBRVMsTUFBTSxDQUFDLElBQVksRUFBRSxLQUFZO1FBQ3pDLE1BQU0sQ0FBQyxHQUFHLEtBQW1DLENBQUM7UUFDOUMsSUFBSSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsRUFBRSxJQUFJLEVBQUUsT0FBTyxFQUFFLE9BQU8sQ0FBQyxJQUFJLENBQUMsSUFBSSxFQUFFLElBQUksQ0FBQyxFQUFFLFFBQVEsRUFBRSxDQUFDLENBQUMsUUFBUSxJQUFJLENBQUMsQ0FBQyxPQUFPLElBQUksQ0FBQyxDQUFDLE9BQU8sRUFBRSxDQUFDLENBQUM7SUFDOUcsQ0FBQztJQUVELHNHQUFzRztJQUM1RixVQUFVLENBQUMsSUFBWSxFQUFFLEtBQVk7UUFDN0MsS0FBSyxDQUFDLGVBQWUsRUFBRSxDQUFDO1FBQ3hCLE1BQU0sTUFBTSxHQUFHLElBQUksQ0FBQyxVQUFVLENBQUMsR0FBRyxDQUFDLElBQUksQ0FBQyxLQUFLLFFBQVEsQ0FBQztRQUN0RCxJQUFJLENBQUMsWUFBWSxDQUFDLElBQUksQ0FBQyxFQUFFLE9BQU8sRUFBRSxPQUFPLENBQUMsSUFBSSxDQUFDLElBQUksRUFBRSxJQUFJLENBQUMsRUFBRSxNQUFNLEVBQUUsQ0FBQyxDQUFDO0lBQ3hFLENBQUM7SUFFUyxNQUFNLENBQUMsSUFBWSxFQUFFLEtBQVk7UUFDekMsS0FBSyxDQUFDLGVBQWUsRUFBRSxDQUFDO1FBQ3hCLElBQUksQ0FBQyxRQUFRLENBQUMsSUFBSSxDQUFDLEVBQUUsSUFBSSxFQUFFLE9BQU8sRUFBRSxPQUFPLENBQUMsSUFBSSxDQUFDLElBQUksRUFBRSxJQUFJLENBQUMsRUFBRSxDQUFDLENBQUM7SUFDbEUsQ0FBQztJQUVTLE9BQU8sQ0FBQyxLQUFhO1FBQzdCLElBQUksQ0FBQyxLQUFLLEdBQUcsS0FBSyxDQUFDO1FBQ25CLElBQUksQ0FBQyxPQUFPLEVBQUUsQ0FBQztJQUNqQixDQUFDO0lBRUQscURBQXFEO0lBQzNDLGNBQWMsQ0FBQyxLQUFZO1FBQ25DLE1BQU0sQ0FBQyxHQUFHLElBQUksQ0FBQyxLQUFLLENBQUMsSUFBSSxFQUFFLENBQUMsV0FBVyxFQUFFLENBQUM7UUFDMUMsTUFBTSxHQUFHLEdBQUcsSUFBSSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQ3hCLENBQUMsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLFdBQVcsRUFBRSxDQUFDLFFBQVEsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxFQUFFLEtBQUssSUFBSSxFQUFFLENBQUMsQ0FBQyxXQUFXLEVBQUUsQ0FBQyxRQUFRLENBQUMsQ0FBQyxDQUFDLENBQ3RHLENBQUM7UUFDRixJQUFJLEdBQUc7WUFBRSxJQUFJLENBQUMsTUFBTSxDQUFDLEdBQUcsQ0FBQyxJQUFJLEVBQUUsS0FBSyxDQUFDLENBQUM7SUFDeEMsQ0FBQztJQUlPLE9BQU87UUFDYixJQUFJLENBQUMsSUFBSSxHQUFHLFdBQVcsQ0FBQyxJQUFJLENBQUMsSUFBSSxFQUFFLElBQUksQ0FBQyxRQUFRLEVBQUUsSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFDO1FBQzlELElBQUksQ0FBQyxVQUFVLEdBQUcsSUFBSSxHQUFHLEVBQUUsQ0FBQztRQUM1QixJQUFJLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxJQUFJO1lBQUUsT0FBTztRQUM5QixLQUFLLE1BQU0sR0FBRyxJQUFJLElBQUksQ0FBQyxJQUFJLEVBQUUsQ0FBQztZQUM1QixNQUFNLE9BQU8sR0FBRyxPQUFPLENBQUMsSUFBSSxDQUFDLElBQUksRUFBRSxHQUFHLENBQUMsSUFBSSxDQUFDLENBQUM7WUFDN0MsTUFBTSxHQUFHLEdBQUcsT0FBTyxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsRUFBRSxFQUFFLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxNQUFNLENBQUM7WUFDN0QsSUFBSSxHQUFHO2dCQUFFLElBQUksQ0FBQyxVQUFVLENBQUMsR0FBRyxDQUFDLEdBQUcsQ0FBQyxJQUFJLEVBQUUsR0FBRyxLQUFLLE9BQU8sQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxDQUFDLENBQUMsU0FBUyxDQUFDLENBQUM7UUFDeEYsQ0FBQztJQUNILENBQUM7OEdBeEdVLGtCQUFrQjtrR0FBbEIsa0JBQWtCLG1XQzVDL0IscTFHQW1GQSw0N0RENUNZLFlBQVksNlZBQUUsV0FBVyw4bUJBQUUsZUFBZSx3SEFBRSxhQUFhLHNYQUFFLHVCQUF1Qjs7MkZBS2pGLGtCQUFrQjtrQkFSOUIsU0FBUzsrQkFDRSxtQkFBbUIsY0FDakIsSUFBSSxXQUNQLENBQUMsWUFBWSxFQUFFLFdBQVcsRUFBRSxlQUFlLEVBQUUsYUFBYSxFQUFFLHVCQUF1QixDQUFDLG1CQUc1RSx1QkFBdUIsQ0FBQyxNQUFNOytFQUl0QyxLQUFLO3NCQUFiLEtBQUs7Z0JBRUcsTUFBTTtzQkFBZCxLQUFLO2dCQUVHLE9BQU87c0JBQWYsS0FBSztnQkFFRyxNQUFNO3NCQUFkLEtBQUs7Z0JBRUcsTUFBTTtzQkFBZCxLQUFLO2dCQUVHLE1BQU07c0JBQWQsS0FBSztnQkFFRyxPQUFPO3NCQUFmLEtBQUs7Z0JBRUcsTUFBTTtzQkFBZCxLQUFLO2dCQUVJLElBQUk7c0JBQWIsTUFBTTtnQkFFRyxPQUFPO3NCQUFoQixNQUFNO2dCQUVHLFFBQVE7c0JBQWpCLE1BQU07Z0JBRUcsWUFBWTtzQkFBckIsTUFBTTs7QUFtRlQsc0ZBQXNGO0FBQ3RGLE1BQU0sVUFBVSxjQUFjLENBQUMsSUFBaUIsRUFBRSxRQUFnQjtJQUNoRSxNQUFNLEdBQUcsR0FBRyxJQUFJLENBQUMsYUFBYSxDQUFDLFFBQVEsQ0FBdUIsQ0FBQztJQUMvRCxHQUFHLEVBQUUsY0FBYyxFQUFFLENBQUMsRUFBRSxLQUFLLEVBQUUsU0FBUyxFQUFFLENBQUMsQ0FBQztBQUM5QyxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHtcbiAgQ2hhbmdlRGV0ZWN0aW9uU3RyYXRlZ3ksXG4gIENvbXBvbmVudCxcbiAgRWxlbWVudFJlZixcbiAgRXZlbnRFbWl0dGVyLFxuICBJbnB1dCxcbiAgT25DaGFuZ2VzLFxuICBPdXRwdXQsXG4gIFNpbXBsZUNoYW5nZXMsXG59IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgQ29tbW9uTW9kdWxlIH0gZnJvbSAnQGFuZ3VsYXIvY29tbW9uJztcbmltcG9ydCB7IEZvcm1zTW9kdWxlIH0gZnJvbSAnQGFuZ3VsYXIvZm9ybXMnO1xuaW1wb3J0IHsgSW5wdXRUZXh0TW9kdWxlIH0gZnJvbSAncHJpbWVuZy9pbnB1dHRleHQnO1xuaW1wb3J0IHsgVG9vbHRpcE1vZHVsZSB9IGZyb20gJ3ByaW1lbmcvdG9vbHRpcCc7XG5cbmltcG9ydCB0eXBlIHsgUmVnaW9uQ2xhc3NOb2RlIH0gZnJvbSAnLi4vLi4vcmVnaW9uLXNvdXJjZS9yZWdpb24tdGlsZXMnO1xuaW1wb3J0IHsgSGV4Q29sb3JQaWNrZXJDb21wb25lbnQgfSBmcm9tICcuLi8uLi9oZXgtY29sb3ItcGlja2VyL2hleC1jb2xvci1waWNrZXIuY29tcG9uZW50JztcbmltcG9ydCB7IENsYXNzVHJlZSwgQ2xhc3NUcmVlUm93LCBhbmNlc3RvcnMsIGJ1aWxkQ2xhc3NUcmVlLCBzdWJ0cmVlLCB2aXNpYmxlUm93cyB9IGZyb20gJy4vY2xhc3MtdHJlZSc7XG5cbi8qKiBBIHBpY2sgaW4gdGhlIHRyZWU6IHRoZSBjbGFzcywgYW5kIGl0IHdpdGggZXZlcnkgY2xhc3MgdW5kZXIgaXQuICovXG5leHBvcnQgaW50ZXJmYWNlIENsYXNzVHJlZVBpY2sge1xuICBuYW1lOiBzdHJpbmc7XG4gIGNsYXNzZXM6IHN0cmluZ1tdO1xuICBhZGRpdGl2ZTogYm9vbGVhbjtcbn1cblxuLyoqIFdoZXRoZXIgYSBjbGFzcyBpcyBzaG93bjogaXQgYW5kIGl0cyBzdWJjbGFzc2VzIGFsbCwgbm9uZSAoJ2hpZGRlbicpLCBvciBvbmx5IHNvbWUgKCdwYXJ0aWFsJykuICovXG5leHBvcnQgdHlwZSBDbGFzc1Zpc2liaWxpdHkgPSAnc2hvd24nIHwgJ2hpZGRlbicgfCAncGFydGlhbCc7XG5cbi8qKlxuICogVGhlIFJlZ2lvbiBFZGl0b3IncyBjbGFzc2VzIGFzIGEgaGllcmFyY2h5IChhIGJyYWluIGF0bGFzJ3Mgb250b2xvZ3kpLCBhcyB0aGUgQWxsZW4gYXRsYXMgdmlld2VyXG4gKiBzaG93cyBpdDogY29sbGFwc2libGUsIGVhY2ggY2xhc3Mgd2l0aCBpdHMgY29sb3VyLCBuYW1lIGFuZCBsb25nIG5hbWUsIGFuZCB0aGUgcmVnaW9ucyBpdCBhbmRcbiAqIGl0cyBzdWJjbGFzc2VzIGhhdmUgb24gdGhpcyBzbGljZTsgYSBjbGFzcyB3aXRoIG5vbmUgaXMgZ3JleWVkLiBQaWNraW5nIGEgY2xhc3Mgc2VsZWN0cyBhbGwgaXRzXG4gKiByZWdpb25zIGFuZCBpdHMgc3ViY2xhc3NlcycgKHRoZSBlZGl0b3IgZG9lcyB0aGUgc2VsZWN0aW5nKS4gU2VhcmNoIGJ5IG5hbWUgb3IgbG9uZyBuYW1lLiBBXG4gKiBjbGFzcydzIHN3YXRjaCByZWNvbG91cnMgaXQsIGFzIHRoZSBjbGFzcyBsaXN0J3MgZG9lczsgaXRzIGV5ZSBoaWRlcyBpdCBhbmQgaXRzIHN1YmNsYXNzZXMuXG4gKi9cbkBDb21wb25lbnQoe1xuICBzZWxlY3RvcjogJ3JlZ2lvbi1jbGFzcy10cmVlJyxcbiAgc3RhbmRhbG9uZTogdHJ1ZSxcbiAgaW1wb3J0czogW0NvbW1vbk1vZHVsZSwgRm9ybXNNb2R1bGUsIElucHV0VGV4dE1vZHVsZSwgVG9vbHRpcE1vZHVsZSwgSGV4Q29sb3JQaWNrZXJDb21wb25lbnRdLFxuICB0ZW1wbGF0ZVVybDogJy4vY2xhc3MtdHJlZS5jb21wb25lbnQuaHRtbCcsXG4gIHN0eWxlVXJsczogWycuL2NsYXNzLXRyZWUuY29tcG9uZW50LnNjc3MnXSxcbiAgY2hhbmdlRGV0ZWN0aW9uOiBDaGFuZ2VEZXRlY3Rpb25TdHJhdGVneS5PblB1c2gsXG59KVxuZXhwb3J0IGNsYXNzIENsYXNzVHJlZUNvbXBvbmVudCBpbXBsZW1lbnRzIE9uQ2hhbmdlcyB7XG4gIC8qKiBUaGUgaGllcmFyY2h5LiAqL1xuICBASW5wdXQoKSBub2RlczogcmVhZG9ubHkgUmVnaW9uQ2xhc3NOb2RlW10gPSBbXTtcbiAgLyoqIFJlZ2lvbnMgcGVyIGNsYXNzIG9uIHRoaXMgc2xpY2UgKHRoZSByZWdpb25zIGFuZCB0aGUgcmVnaW9uIHNvdXJjZSdzKS4gKi9cbiAgQElucHV0KCkgY291bnRzOiBSZWFkb25seU1hcDxzdHJpbmcsIG51bWJlcj4gPSBuZXcgTWFwKCk7XG4gIC8qKiBBIGNsYXNzJ3MgY29sb3VyIChhIG5ldyBmdW5jdGlvbiB3aGVuIHRoZSBjb2xvdXJzIGNoYW5nZSwgc28gdGhlIHJvd3MgcmVwYWludCkuICovXG4gIEBJbnB1dCgpIGNvbG9yT2Y6IChuYW1lOiBzdHJpbmcpID0+IHN0cmluZyA9ICgpID0+ICcjOTk5OTk5JztcbiAgLyoqIFRoZSBjbGFzcyBwaWNrZWQgbGFzdCAoaGlnaGxpZ2h0ZWQsIGl0cyBwYXRoIGV4cGFuZGVkLCBzY3JvbGxlZCBpbnRvIHZpZXcpLiAqL1xuICBASW5wdXQoKSBwaWNrZWQ6IHN0cmluZyB8IG51bGwgPSBudWxsO1xuICAvKiogQ2xhc3NlcyB3aXRoIGEgc2VsZWN0ZWQgcmVnaW9uIChtYXJrZWQpLiAqL1xuICBASW5wdXQoKSBtYXJrZWQ6IFJlYWRvbmx5U2V0PHN0cmluZz4gPSBuZXcgU2V0KCk7XG4gIC8qKiBXaGV0aGVyIGEgdm9sdW1lIHZpZXcgaXMgb24gc2NyZWVuOiBlYWNoIGNsYXNzIGNhbiB0aGVuIGJlIHNob3duIGluIDNELiAqL1xuICBASW5wdXQoKSB2b2x1bWUgPSBmYWxzZTtcbiAgLyoqIFRoZSBjbGFzc2VzIHNob3duIGluIDNELiAqL1xuICBASW5wdXQoKSBzaG93bjNkOiBSZWFkb25seVNldDxzdHJpbmc+ID0gbmV3IFNldCgpO1xuICAvKiogVGhlIGNsYXNzZXMgaGlkZGVuIGZyb20gdmlldy4gKi9cbiAgQElucHV0KCkgaGlkZGVuOiBSZWFkb25seVNldDxzdHJpbmc+ID0gbmV3IFNldCgpO1xuXG4gIEBPdXRwdXQoKSBwaWNrID0gbmV3IEV2ZW50RW1pdHRlcjxDbGFzc1RyZWVQaWNrPigpO1xuICAvKiogQSBjbGFzcydzIHN3YXRjaCBwaWNrZWQgYSBuZXcgY29sb3VyLiAqL1xuICBAT3V0cHV0KCkgcmVjb2xvciA9IG5ldyBFdmVudEVtaXR0ZXI8eyBuYW1lOiBzdHJpbmc7IGNvbG9yOiBzdHJpbmcgfT4oKTtcbiAgLyoqIEEgY2xhc3MncyAzRCB0b2dnbGU6IGl0IHdpdGggZXZlcnkgY2xhc3MgdW5kZXIgaXQuICovXG4gIEBPdXRwdXQoKSB0b2dnbGUzZCA9IG5ldyBFdmVudEVtaXR0ZXI8eyBuYW1lOiBzdHJpbmc7IGNsYXNzZXM6IHN0cmluZ1tdIH0+KCk7XG4gIC8qKiBBIGNsYXNzJ3MgZXllOiBoaWRlIChvciBzaG93KSBpdCB3aXRoIGV2ZXJ5IGNsYXNzIHVuZGVyIGl0LiAqL1xuICBAT3V0cHV0KCkgdG9nZ2xlSGlkZGVuID0gbmV3IEV2ZW50RW1pdHRlcjx7IGNsYXNzZXM6IHN0cmluZ1tdOyBoaWRkZW46IGJvb2xlYW4gfT4oKTtcblxuICBwcm90ZWN0ZWQgdHJlZTogQ2xhc3NUcmVlID0gYnVpbGRDbGFzc1RyZWUoW10sIG5ldyBNYXAoKSk7XG4gIHByb3RlY3RlZCByb3dzOiBDbGFzc1RyZWVSb3dbXSA9IFtdO1xuICAvKiogRWFjaCByb3cncyB2aXNpYmlsaXR5IChhIHJvdyBhYnNlbnQ6IHNob3duKS4gKi9cbiAgcHJvdGVjdGVkIHZpc2liaWxpdHkgPSBuZXcgTWFwPHN0cmluZywgQ2xhc3NWaXNpYmlsaXR5PigpO1xuICBwcm90ZWN0ZWQgcXVlcnkgPSAnJztcbiAgcHJpdmF0ZSBleHBhbmRlZCA9IG5ldyBTZXQ8c3RyaW5nPigpO1xuXG4gIGNvbnN0cnVjdG9yKHByaXZhdGUgcmVhZG9ubHkgZWw6IEVsZW1lbnRSZWY8SFRNTEVsZW1lbnQ+KSB7fVxuXG4gIG5nT25DaGFuZ2VzKGNoYW5nZXM6IFNpbXBsZUNoYW5nZXMpOiB2b2lkIHtcbiAgICBjb25zdCBmcmVzaCA9ICEhY2hhbmdlc1snbm9kZXMnXTtcbiAgICBpZiAoZnJlc2ggfHwgY2hhbmdlc1snY291bnRzJ10pIHRoaXMudHJlZSA9IGJ1aWxkQ2xhc3NUcmVlKHRoaXMubm9kZXMsIHRoaXMuY291bnRzKTtcbiAgICAvLyBBIG5ldyBoaWVyYXJjaHkgb3BlbnMgd2l0aCBpdHMgcm9vdHMgZXhwYW5kZWQsIGFzIHRoZSBhdGxhcyB2aWV3ZXIgZG9lcy5cbiAgICBpZiAoZnJlc2gpIHRoaXMuZXhwYW5kZWQgPSBuZXcgU2V0KHRoaXMudHJlZS5yb290cyk7XG4gICAgaWYgKGNoYW5nZXNbJ3BpY2tlZCddICYmIHRoaXMucGlja2VkKSBmb3IgKGNvbnN0IGEgb2YgYW5jZXN0b3JzKHRoaXMudHJlZSwgdGhpcy5waWNrZWQpKSB0aGlzLmV4cGFuZGVkLmFkZChhKTtcbiAgICB0aGlzLnJlZnJlc2goKTtcbiAgICAvLyBBIHBpY2sgZnJvbSBlbHNld2hlcmUgKGEgc3VyZmFjZSBjbGlja2VkIGluIDNEKSBtYXkgYmUgb2ZmIHNjcmVlbjogYnJpbmcgaXRzIHJvdyBpbnRvIHZpZXcuXG4gICAgaWYgKGNoYW5nZXNbJ3BpY2tlZCddICYmIHRoaXMucGlja2VkKVxuICAgICAgc2V0VGltZW91dCgoKSA9PiBzY3JvbGxUb1BpY2tlZCh0aGlzLmVsLm5hdGl2ZUVsZW1lbnQsICcudHJlZS1yb3cucGlja2VkJykpO1xuICB9XG5cbiAgcHJvdGVjdGVkIG5vZGUobmFtZTogc3RyaW5nKTogUmVnaW9uQ2xhc3NOb2RlIHwgdW5kZWZpbmVkIHtcbiAgICByZXR1cm4gdGhpcy50cmVlLm5vZGUuZ2V0KG5hbWUpO1xuICB9XG5cbiAgcHJvdGVjdGVkIHRvdGFsKG5hbWU6IHN0cmluZyk6IG51bWJlciB7XG4gICAgcmV0dXJuIHRoaXMudHJlZS50b3RhbC5nZXQobmFtZSkgPz8gMDtcbiAgfVxuXG4gIHByb3RlY3RlZCB0b2dnbGUocm93OiBDbGFzc1RyZWVSb3csIGV2ZW50OiBFdmVudCk6IHZvaWQge1xuICAgIGV2ZW50LnN0b3BQcm9wYWdhdGlvbigpO1xuICAgIGlmICh0aGlzLmV4cGFuZGVkLmhhcyhyb3cubmFtZSkpIHRoaXMuZXhwYW5kZWQuZGVsZXRlKHJvdy5uYW1lKTtcbiAgICBlbHNlIHRoaXMuZXhwYW5kZWQuYWRkKHJvdy5uYW1lKTtcbiAgICB0aGlzLnJlZnJlc2goKTtcbiAgfVxuXG4gIHByb3RlY3RlZCBjaG9vc2UobmFtZTogc3RyaW5nLCBldmVudDogRXZlbnQpOiB2b2lkIHtcbiAgICBjb25zdCBlID0gZXZlbnQgYXMgTW91c2VFdmVudCB8IEtleWJvYXJkRXZlbnQ7XG4gICAgdGhpcy5waWNrLmVtaXQoeyBuYW1lLCBjbGFzc2VzOiBzdWJ0cmVlKHRoaXMudHJlZSwgbmFtZSksIGFkZGl0aXZlOiBlLnNoaWZ0S2V5IHx8IGUubWV0YUtleSB8fCBlLmN0cmxLZXkgfSk7XG4gIH1cblxuICAvKiogVGhlIGV5ZTogYSBjbGFzcyBoaWRkZW4gKHdob2xseSkgaXMgc2hvd24gYWdhaW4gd2l0aCBpdHMgc3ViY2xhc3Nlczsgb3RoZXJ3aXNlIHRoZXkgYXJlIGhpZGRlbi4gKi9cbiAgcHJvdGVjdGVkIGZsaXBIaWRkZW4obmFtZTogc3RyaW5nLCBldmVudDogRXZlbnQpOiB2b2lkIHtcbiAgICBldmVudC5zdG9wUHJvcGFnYXRpb24oKTtcbiAgICBjb25zdCBoaWRkZW4gPSB0aGlzLnZpc2liaWxpdHkuZ2V0KG5hbWUpICE9PSAnaGlkZGVuJztcbiAgICB0aGlzLnRvZ2dsZUhpZGRlbi5lbWl0KHsgY2xhc3Nlczogc3VidHJlZSh0aGlzLnRyZWUsIG5hbWUpLCBoaWRkZW4gfSk7XG4gIH1cblxuICBwcm90ZWN0ZWQgZmxpcDNkKG5hbWU6IHN0cmluZywgZXZlbnQ6IEV2ZW50KTogdm9pZCB7XG4gICAgZXZlbnQuc3RvcFByb3BhZ2F0aW9uKCk7XG4gICAgdGhpcy50b2dnbGUzZC5lbWl0KHsgbmFtZSwgY2xhc3Nlczogc3VidHJlZSh0aGlzLnRyZWUsIG5hbWUpIH0pO1xuICB9XG5cbiAgcHJvdGVjdGVkIG9uUXVlcnkodmFsdWU6IHN0cmluZyk6IHZvaWQge1xuICAgIHRoaXMucXVlcnkgPSB2YWx1ZTtcbiAgICB0aGlzLnJlZnJlc2goKTtcbiAgfVxuXG4gIC8qKiBFbnRlciBpbiB0aGUgc2VhcmNoIGJveCBwaWNrcyB0aGUgZmlyc3QgbWF0Y2guICovXG4gIHByb3RlY3RlZCBwaWNrRmlyc3RNYXRjaChldmVudDogRXZlbnQpOiB2b2lkIHtcbiAgICBjb25zdCBxID0gdGhpcy5xdWVyeS50cmltKCkudG9Mb3dlckNhc2UoKTtcbiAgICBjb25zdCBoaXQgPSB0aGlzLnJvd3MuZmluZChcbiAgICAgIChyKSA9PiByLm5hbWUudG9Mb3dlckNhc2UoKS5pbmNsdWRlcyhxKSB8fCAodGhpcy5ub2RlKHIubmFtZSk/LnRpdGxlID8/ICcnKS50b0xvd2VyQ2FzZSgpLmluY2x1ZGVzKHEpLFxuICAgICk7XG4gICAgaWYgKGhpdCkgdGhpcy5jaG9vc2UoaGl0Lm5hbWUsIGV2ZW50KTtcbiAgfVxuXG4gIHByb3RlY3RlZCByZWFkb25seSB0cmFja1JvdyA9IChfOiBudW1iZXIsIHI6IENsYXNzVHJlZVJvdykgPT4gci5uYW1lO1xuXG4gIHByaXZhdGUgcmVmcmVzaCgpOiB2b2lkIHtcbiAgICB0aGlzLnJvd3MgPSB2aXNpYmxlUm93cyh0aGlzLnRyZWUsIHRoaXMuZXhwYW5kZWQsIHRoaXMucXVlcnkpO1xuICAgIHRoaXMudmlzaWJpbGl0eSA9IG5ldyBNYXAoKTtcbiAgICBpZiAoIXRoaXMuaGlkZGVuLnNpemUpIHJldHVybjtcbiAgICBmb3IgKGNvbnN0IHJvdyBvZiB0aGlzLnJvd3MpIHtcbiAgICAgIGNvbnN0IGNsYXNzZXMgPSBzdWJ0cmVlKHRoaXMudHJlZSwgcm93Lm5hbWUpO1xuICAgICAgY29uc3Qgb2ZmID0gY2xhc3Nlcy5maWx0ZXIoKGMpID0+IHRoaXMuaGlkZGVuLmhhcyhjKSkubGVuZ3RoO1xuICAgICAgaWYgKG9mZikgdGhpcy52aXNpYmlsaXR5LnNldChyb3cubmFtZSwgb2ZmID09PSBjbGFzc2VzLmxlbmd0aCA/ICdoaWRkZW4nIDogJ3BhcnRpYWwnKTtcbiAgICB9XG4gIH1cbn1cblxuLyoqIFNjcm9sbCB0aGUgcm93IG1hdGNoaW5nIGBzZWxlY3RvcmAgaW5zaWRlIGBob3N0YCBpbnRvIHZpZXcsIGlmIGl0IGlzIG91dCBvZiBpdC4gKi9cbmV4cG9ydCBmdW5jdGlvbiBzY3JvbGxUb1BpY2tlZChob3N0OiBIVE1MRWxlbWVudCwgc2VsZWN0b3I6IHN0cmluZyk6IHZvaWQge1xuICBjb25zdCByb3cgPSBob3N0LnF1ZXJ5U2VsZWN0b3Ioc2VsZWN0b3IpIGFzIEhUTUxFbGVtZW50IHwgbnVsbDtcbiAgcm93Py5zY3JvbGxJbnRvVmlldz8uKHsgYmxvY2s6ICduZWFyZXN0JyB9KTtcbn1cbiIsIjxkaXYgY2xhc3M9XCJjbGFzcy10cmVlXCI+XG4gIDxkaXYgY2xhc3M9XCJ0cmVlLWhlYWRlclwiICpuZ0lmPVwicGlja2VkIGFzIHBcIj5cbiAgICA8c3BhbiBjbGFzcz1cInRyZWUtcGlja2VkXCI+XG4gICAgICA8Yj57eyBwIH19PC9iXG4gICAgICA+PHNwYW4gKm5nSWY9XCJub2RlKHApPy50aXRsZSBhcyB0XCI+IMK3IHt7IHQgfX08L3NwYW4+XG4gICAgPC9zcGFuPlxuICA8L2Rpdj5cbiAgPGlucHV0XG4gICAgdHlwZT1cInRleHRcIlxuICAgIHBJbnB1dFRleHRcbiAgICBjbGFzcz1cInAtaW5wdXR0ZXh0LXNtIHRyZWUtc2VhcmNoXCJcbiAgICBwbGFjZWhvbGRlcj1cIlNlYXJjaCBieSBuYW1lXCJcbiAgICBhcmlhLWxhYmVsPVwiU2VhcmNoIHRoZSBjbGFzc2VzXCJcbiAgICBbbmdNb2RlbF09XCJxdWVyeVwiXG4gICAgKG5nTW9kZWxDaGFuZ2UpPVwib25RdWVyeSgkZXZlbnQpXCJcbiAgICAoa2V5ZG93bi5lbnRlcik9XCJwaWNrRmlyc3RNYXRjaCgkZXZlbnQpXCJcbiAgLz5cbiAgPGRpdiBjbGFzcz1cInRyZWUtYm9keVwiIHJvbGU9XCJ0cmVlXCI+XG4gICAgPGRpdlxuICAgICAgKm5nRm9yPVwibGV0IHJvdyBvZiByb3dzOyB0cmFja0J5OiB0cmFja1Jvd1wiXG4gICAgICBjbGFzcz1cInRyZWUtcm93XCJcbiAgICAgIHJvbGU9XCJ0cmVlaXRlbVwiXG4gICAgICB0YWJpbmRleD1cIjBcIlxuICAgICAgW2F0dHIuYXJpYS1leHBhbmRlZF09XCJyb3cuaGFzQ2hpbGRyZW4gPyByb3cuZXhwYW5kZWQgOiBudWxsXCJcbiAgICAgIFtjbGFzcy5hYnNlbnRdPVwidG90YWwocm93Lm5hbWUpID09PSAwXCJcbiAgICAgIFtjbGFzcy5waWNrZWRdPVwicm93Lm5hbWUgPT09IHBpY2tlZFwiXG4gICAgICBbY2xhc3MubWFya2VkXT1cIm1hcmtlZC5oYXMocm93Lm5hbWUpXCJcbiAgICAgIFtjbGFzcy5oaWRkZW4tY2xhc3NdPVwidmlzaWJpbGl0eS5nZXQocm93Lm5hbWUpID09PSAnaGlkZGVuJ1wiXG4gICAgICBbc3R5bGUucGFkZGluZy1sZWZ0LnJlbV09XCIwLjM1ICsgcm93LmRlcHRoICogMC45XCJcbiAgICAgIFtwVG9vbHRpcF09XCJub2RlKHJvdy5uYW1lKT8udGl0bGUgfHwgcm93Lm5hbWVcIlxuICAgICAgdG9vbHRpcFBvc2l0aW9uPVwibGVmdFwiXG4gICAgICBbc2hvd0RlbGF5XT1cIjYwMFwiXG4gICAgICAoY2xpY2spPVwiY2hvb3NlKHJvdy5uYW1lLCAkZXZlbnQpXCJcbiAgICAgIChrZXlkb3duLmVudGVyKT1cImNob29zZShyb3cubmFtZSwgJGV2ZW50KVwiXG4gICAgPlxuICAgICAgPGlcbiAgICAgICAgY2xhc3M9XCJwaSB0cmVlLXRvZ2dsZVwiXG4gICAgICAgIFtjbGFzcy5waS1taW51cy1jaXJjbGVdPVwicm93Lmhhc0NoaWxkcmVuICYmIHJvdy5leHBhbmRlZFwiXG4gICAgICAgIFtjbGFzcy5waS1wbHVzLWNpcmNsZV09XCJyb3cuaGFzQ2hpbGRyZW4gJiYgIXJvdy5leHBhbmRlZFwiXG4gICAgICAgIFthdHRyLmFyaWEtbGFiZWxdPVwicm93LmV4cGFuZGVkID8gJ0NvbGxhcHNlJyA6ICdFeHBhbmQnXCJcbiAgICAgICAgKGNsaWNrKT1cInJvdy5oYXNDaGlsZHJlbiAmJiB0b2dnbGUocm93LCAkZXZlbnQpXCJcbiAgICAgID48L2k+XG4gICAgICA8aVxuICAgICAgICBjbGFzcz1cInBpIHRyZWUtZXllXCJcbiAgICAgICAgW25nQ2xhc3NdPVwidmlzaWJpbGl0eS5nZXQocm93Lm5hbWUpID09PSAnaGlkZGVuJyA/ICdwaS1leWUtc2xhc2gnIDogJ3BpLWV5ZSdcIlxuICAgICAgICBbY2xhc3MucGFydGlhbF09XCJ2aXNpYmlsaXR5LmdldChyb3cubmFtZSkgPT09ICdwYXJ0aWFsJ1wiXG4gICAgICAgIHJvbGU9XCJidXR0b25cIlxuICAgICAgICBbYXR0ci5hcmlhLXByZXNzZWRdPVwidmlzaWJpbGl0eS5nZXQocm93Lm5hbWUpICE9PSAnaGlkZGVuJ1wiXG4gICAgICAgIFthdHRyLmFyaWEtbGFiZWxdPVwiKHZpc2liaWxpdHkuZ2V0KHJvdy5uYW1lKSA9PT0gJ2hpZGRlbicgPyAnU2hvdyAnIDogJ0hpZGUgJykgKyByb3cubmFtZVwiXG4gICAgICAgIFtwVG9vbHRpcF09XCJcbiAgICAgICAgICAodmlzaWJpbGl0eS5nZXQocm93Lm5hbWUpID09PSAnaGlkZGVuJyA/ICdTaG93JyA6ICdIaWRlJykgK1xuICAgICAgICAgIChyb3cuaGFzQ2hpbGRyZW4gPyAnIGl0IGFuZCBpdHMgc3ViY2xhc3NlcycgOiAnJykgK1xuICAgICAgICAgICh2aXNpYmlsaXR5LmdldChyb3cubmFtZSkgPT09ICdwYXJ0aWFsJyA/ICcgKHNvbWUgYXJlIGhpZGRlbiknIDogJycpXG4gICAgICAgIFwiXG4gICAgICAgIHRvb2x0aXBQb3NpdGlvbj1cImxlZnRcIlxuICAgICAgICAoY2xpY2spPVwiZmxpcEhpZGRlbihyb3cubmFtZSwgJGV2ZW50KVwiXG4gICAgICAgIChrZXlkb3duLmVudGVyKT1cImZsaXBIaWRkZW4ocm93Lm5hbWUsICRldmVudClcIlxuICAgICAgPjwvaT5cbiAgICAgIDxzcGFuIGNsYXNzPVwidHJlZS1zd2F0Y2hcIiAoY2xpY2spPVwiJGV2ZW50LnN0b3BQcm9wYWdhdGlvbigpXCIgKGtleWRvd24uZW50ZXIpPVwiJGV2ZW50LnN0b3BQcm9wYWdhdGlvbigpXCI+XG4gICAgICAgIDxoZXgtY29sb3ItcGlja2VyXG4gICAgICAgICAgW2NvbG9yXT1cImNvbG9yT2Yocm93Lm5hbWUpXCJcbiAgICAgICAgICAoY29sb3JDaGFuZ2UpPVwicmVjb2xvci5lbWl0KHsgbmFtZTogcm93Lm5hbWUsIGNvbG9yOiAkZXZlbnQgfSlcIlxuICAgICAgICA+XG4gICAgICAgIDwvaGV4LWNvbG9yLXBpY2tlcj5cbiAgICAgIDwvc3Bhbj5cbiAgICAgIDxzcGFuIGNsYXNzPVwidHJlZS1uYW1lXCI+e3sgcm93Lm5hbWUgfX08L3NwYW4+XG4gICAgICA8c3BhbiBjbGFzcz1cInRyZWUtbG9uZ1wiPnt7IG5vZGUocm93Lm5hbWUpPy50aXRsZSB9fTwvc3Bhbj5cbiAgICAgIDxzcGFuIGNsYXNzPVwidHJlZS1jb3VudFwiICpuZ0lmPVwidG90YWwocm93Lm5hbWUpID4gMFwiPnt7IHRvdGFsKHJvdy5uYW1lKSB9fTwvc3Bhbj5cbiAgICAgIDxpXG4gICAgICAgICpuZ0lmPVwidm9sdW1lXCJcbiAgICAgICAgY2xhc3M9XCJwaSBwaS1ib3ggdHJlZS0zZFwiXG4gICAgICAgIFtjbGFzcy5vbl09XCJzaG93bjNkLmhhcyhyb3cubmFtZSlcIlxuICAgICAgICByb2xlPVwiYnV0dG9uXCJcbiAgICAgICAgW2F0dHIuYXJpYS1wcmVzc2VkXT1cInNob3duM2QuaGFzKHJvdy5uYW1lKVwiXG4gICAgICAgIFthdHRyLmFyaWEtbGFiZWxdPVwiJ1Nob3cgJyArIHJvdy5uYW1lICsgJyBpbiAzRCdcIlxuICAgICAgICBwVG9vbHRpcD1cIlNob3cgaW4gdGhlIHZvbHVtZSwgaW4gM0RcIlxuICAgICAgICB0b29sdGlwUG9zaXRpb249XCJsZWZ0XCJcbiAgICAgICAgKGNsaWNrKT1cImZsaXAzZChyb3cubmFtZSwgJGV2ZW50KVwiXG4gICAgICA+PC9pPlxuICAgIDwvZGl2PlxuICAgIDxkaXYgKm5nSWY9XCIhcm93cy5sZW5ndGhcIiBjbGFzcz1cInRyZWUtZW1wdHlcIj5ObyBjbGFzcyBtYXRjaGVzLjwvZGl2PlxuICA8L2Rpdj5cbjwvZGl2PlxuIl19
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Build the tree of `nodes`, counting `counts` (regions per class) up through it. A node whose
|
|
3
|
+
* parent is not in the hierarchy is a root; siblings sort by `order`, then as listed.
|
|
4
|
+
*/
|
|
5
|
+
export function buildClassTree(nodes, counts) {
|
|
6
|
+
const node = new Map();
|
|
7
|
+
for (const n of nodes)
|
|
8
|
+
if (!node.has(n.name))
|
|
9
|
+
node.set(n.name, n);
|
|
10
|
+
const children = new Map();
|
|
11
|
+
const parent = new Map();
|
|
12
|
+
const roots = [];
|
|
13
|
+
const position = new Map(nodes.map((n, i) => [n.name, i]));
|
|
14
|
+
for (const n of node.values()) {
|
|
15
|
+
const p = n.parent && node.has(n.parent) && n.parent !== n.name ? n.parent : null;
|
|
16
|
+
parent.set(n.name, p);
|
|
17
|
+
if (p) {
|
|
18
|
+
const list = children.get(p);
|
|
19
|
+
if (list)
|
|
20
|
+
list.push(n.name);
|
|
21
|
+
else
|
|
22
|
+
children.set(p, [n.name]);
|
|
23
|
+
}
|
|
24
|
+
else
|
|
25
|
+
roots.push(n.name);
|
|
26
|
+
}
|
|
27
|
+
const byOrder = (a, b) => (node.get(a)?.order ?? Infinity) - (node.get(b)?.order ?? Infinity) ||
|
|
28
|
+
(position.get(a) ?? 0) - (position.get(b) ?? 0);
|
|
29
|
+
roots.sort(byOrder);
|
|
30
|
+
for (const list of children.values())
|
|
31
|
+
list.sort(byOrder);
|
|
32
|
+
const total = new Map();
|
|
33
|
+
const visit = (name, seen) => {
|
|
34
|
+
const known = total.get(name);
|
|
35
|
+
if (known !== undefined)
|
|
36
|
+
return known;
|
|
37
|
+
if (seen.has(name))
|
|
38
|
+
return 0; // a cycle in a malformed file
|
|
39
|
+
seen.add(name);
|
|
40
|
+
let sum = counts.get(name) ?? 0;
|
|
41
|
+
for (const c of children.get(name) ?? [])
|
|
42
|
+
sum += visit(c, seen);
|
|
43
|
+
total.set(name, sum);
|
|
44
|
+
return sum;
|
|
45
|
+
};
|
|
46
|
+
for (const name of node.keys())
|
|
47
|
+
visit(name, new Set());
|
|
48
|
+
return { roots, node, children, parent, total };
|
|
49
|
+
}
|
|
50
|
+
/** `name` and every class under it. */
|
|
51
|
+
export function subtree(tree, name) {
|
|
52
|
+
const out = [];
|
|
53
|
+
const stack = [name];
|
|
54
|
+
const seen = new Set();
|
|
55
|
+
while (stack.length) {
|
|
56
|
+
const n = stack.pop();
|
|
57
|
+
if (seen.has(n))
|
|
58
|
+
continue;
|
|
59
|
+
seen.add(n);
|
|
60
|
+
out.push(n);
|
|
61
|
+
for (const c of tree.children.get(n) ?? [])
|
|
62
|
+
stack.push(c);
|
|
63
|
+
}
|
|
64
|
+
return out;
|
|
65
|
+
}
|
|
66
|
+
/** The classes from the root down to `name`'s parent. */
|
|
67
|
+
export function ancestors(tree, name) {
|
|
68
|
+
const out = [];
|
|
69
|
+
let p = tree.parent.get(name) ?? null;
|
|
70
|
+
while (p && !out.includes(p)) {
|
|
71
|
+
out.unshift(p);
|
|
72
|
+
p = tree.parent.get(p) ?? null;
|
|
73
|
+
}
|
|
74
|
+
return out;
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* The rows to draw: depth-first through the expanded nodes. With a `query`, only the nodes whose
|
|
78
|
+
* name or title contains it and their ancestors, all expanded.
|
|
79
|
+
*/
|
|
80
|
+
export function visibleRows(tree, expanded, query = '') {
|
|
81
|
+
const q = query.trim().toLowerCase();
|
|
82
|
+
let keep = null;
|
|
83
|
+
if (q) {
|
|
84
|
+
keep = new Set();
|
|
85
|
+
for (const [name, n] of tree.node) {
|
|
86
|
+
if (name.toLowerCase().includes(q) || (n.title ?? '').toLowerCase().includes(q)) {
|
|
87
|
+
keep.add(name);
|
|
88
|
+
for (const a of ancestors(tree, name))
|
|
89
|
+
keep.add(a);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
const rows = [];
|
|
94
|
+
const walk = (name, depth) => {
|
|
95
|
+
if (keep && !keep.has(name))
|
|
96
|
+
return;
|
|
97
|
+
const kids = tree.children.get(name) ?? [];
|
|
98
|
+
const open = keep ? true : expanded.has(name);
|
|
99
|
+
rows.push({ name, depth, hasChildren: kids.length > 0, expanded: open && kids.length > 0 });
|
|
100
|
+
if (open)
|
|
101
|
+
for (const c of kids)
|
|
102
|
+
walk(c, depth + 1);
|
|
103
|
+
};
|
|
104
|
+
for (const r of tree.roots)
|
|
105
|
+
walk(r, 0);
|
|
106
|
+
return rows;
|
|
107
|
+
}
|
|
108
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2xhc3MtdHJlZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uL3NyYy9saWIvcmVnaW9uLWVkaXRvci9jbGFzcy10cmVlL2NsYXNzLXRyZWUudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBWUE7OztHQUdHO0FBQ0gsTUFBTSxVQUFVLGNBQWMsQ0FBQyxLQUFpQyxFQUFFLE1BQW1DO0lBQ25HLE1BQU0sSUFBSSxHQUFHLElBQUksR0FBRyxFQUEyQixDQUFDO0lBQ2hELEtBQUssTUFBTSxDQUFDLElBQUksS0FBSztRQUFFLElBQUksQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUM7WUFBRSxJQUFJLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxJQUFJLEVBQUUsQ0FBQyxDQUFDLENBQUM7SUFDbEUsTUFBTSxRQUFRLEdBQUcsSUFBSSxHQUFHLEVBQW9CLENBQUM7SUFDN0MsTUFBTSxNQUFNLEdBQUcsSUFBSSxHQUFHLEVBQXlCLENBQUM7SUFDaEQsTUFBTSxLQUFLLEdBQWEsRUFBRSxDQUFDO0lBQzNCLE1BQU0sUUFBUSxHQUFHLElBQUksR0FBRyxDQUFDLEtBQUssQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxJQUFJLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQzNELEtBQUssTUFBTSxDQUFDLElBQUksSUFBSSxDQUFDLE1BQU0sRUFBRSxFQUFFLENBQUM7UUFDOUIsTUFBTSxDQUFDLEdBQUcsQ0FBQyxDQUFDLE1BQU0sSUFBSSxJQUFJLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLENBQUMsTUFBTSxLQUFLLENBQUMsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQztRQUNsRixNQUFNLENBQUMsR0FB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LENBQUMsQ0FBQztJQUNyRCxDQUFDLENBQUM7SUFDRixLQUFLLE1BQU0sQ0FBQyxJQUFJLElBQUksQ0FBQyxLQUFLO1FBQUUsSUFBSSxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQztJQUN2QyxPQUFPLElBQUksQ0FBQztBQUNkLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgdHlwZSB7IFJlZ2lvbkNsYXNzTm9kZSB9IGZyb20gJy4uLy4uL3JlZ2lvbi1zb3VyY2UvcmVnaW9uLXRpbGVzJztcblxuLyoqIEEgY2xhc3MgaGllcmFyY2h5IGFzIGEgdHJlZTogY2hpbGRyZW4gaW4gb3JkZXIsIHN1YnRyZWUgY291bnRzLCBkZXB0aHMuIFB1cmUuICovXG5leHBvcnQgaW50ZXJmYWNlIENsYXNzVHJlZSB7XG4gIHJvb3RzOiBzdHJpbmdbXTtcbiAgbm9kZTogTWFwPHN0cmluZywgUmVnaW9uQ2xhc3NOb2RlPjtcbiAgY2hpbGRyZW46IE1hcDxzdHJpbmcsIHN0cmluZ1tdPjtcbiAgcGFyZW50OiBNYXA8c3RyaW5nLCBzdHJpbmcgfCBudWxsPjtcbiAgLyoqIFJlZ2lvbnMgb2YgdGhlIGNsYXNzIGFuZCBldmVyeSBjbGFzcyB1bmRlciBpdC4gKi9cbiAgdG90YWw6IE1hcDxzdHJpbmcsIG51bWJlcj47XG59XG5cbi8qKlxuICogQnVpbGQgdGhlIHRyZWUgb2YgYG5vZGVzYCwgY291bnRpbmcgYGNvdW50c2AgKHJlZ2lvbnMgcGVyIGNsYXNzKSB1cCB0aHJvdWdoIGl0LiBBIG5vZGUgd2hvc2VcbiAqIHBhcmVudCBpcyBub3QgaW4gdGhlIGhpZXJhcmNoeSBpcyBhIHJvb3Q7IHNpYmxpbmdzIHNvcnQgYnkgYG9yZGVyYCwgdGhlbiBhcyBsaXN0ZWQuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBidWlsZENsYXNzVHJlZShub2RlczogcmVhZG9ubHkgUmVnaW9uQ2xhc3NOb2RlW10sIGNvdW50czogUmVhZG9ubHlNYXA8c3RyaW5nLCBudW1iZXI+KTogQ2xhc3NUcmVlIHtcbiAgY29uc3Qgbm9kZSA9IG5ldyBNYXA8c3RyaW5nLCBSZWdpb25DbGFzc05vZGU+KCk7XG4gIGZvciAoY29uc3QgbiBvZiBub2RlcykgaWYgKCFub2RlLmhhcyhuLm5hbWUpKSBub2RlLnNldChuLm5hbWUsIG4pO1xuICBjb25zdCBjaGlsZHJlbiA9IG5ldyBNYXA8c3RyaW5nLCBzdHJpbmdbXT4oKTtcbiAgY29uc3QgcGFyZW50ID0gbmV3IE1hcDxzdHJpbmcsIHN0cmluZyB8IG51bGw+KCk7XG4gIGNvbnN0IHJvb3RzOiBzdHJpbmdbXSA9IFtdO1xuICBjb25zdCBwb3NpdGlvbiA9IG5ldyBNYXAobm9kZXMubWFwKChuLCBpKSA9PiBbbi5uYW1lLCBpXSkpO1xuICBmb3IgKGNvbnN0IG4gb2Ygbm9kZS52YWx1ZXMoKSkge1xuICAgIGNvbnN0IHAgPSBuLnBhcmVudCAmJiBub2RlLmhhcyhuLnBhcmVudCkgJiYgbi5wYXJlbnQgIT09IG4ubmFtZSA/IG4ucGFyZW50IDogbnVsbDtcbiAgICBwYXJlbnQuc2V0KG4ubmFtZSwgcCk7XG4gICAgaWYgKHApIHtcbiAgICAgIGNvbnN0IGxpc3QgPSBjaGlsZHJlbi5nZXQocCk7XG4gICAgICBpZiAobGlzdCkgbGlzdC5wdXNoKG4ubmFtZSk7XG4gICAgICBlbHNlIGNoaWxkcmVuLnNldChwLCBbbi5uYW1lXSk7XG4gICAgfSBlbHNlIHJvb3RzLnB1c2gobi5uYW1lKTtcbiAgfVxuICBjb25zdCBieU9yZGVyID0gKGE6IHN0cmluZywgYjogc3RyaW5nKSA9PlxuICAgIChub2RlLmdldChhKT8ub3JkZXIgPz8gSW5maW5pdHkpIC0gKG5vZGUuZ2V0KGIpPy5vcmRlciA/PyBJbmZpbml0eSkgfHxcbiAgICAocG9zaXRpb24uZ2V0KGEpID8/IDApIC0gKHBvc2l0aW9uLmdldChiKSA/PyAwKTtcbiAgcm9vdHMuc29ydChieU9yZGVyKTtcbiAgZm9yIChjb25zdCBsaXN0IG9mIGNoaWxkcmVuLnZhbHVlcygpKSBsaXN0LnNvcnQoYnlPcmRlcik7XG5cbiAgY29uc3QgdG90YWwgPSBuZXcgTWFwPHN0cmluZywgbnVtYmVyPigpO1xuICBjb25zdCB2aXNpdCA9IChuYW1lOiBzdHJpbmcsIHNlZW46IFNldDxzdHJpbmc+KTogbnVtYmVyID0+IHtcbiAgICBjb25zdCBrbm93biA9IHRvdGFsLmdldChuYW1lKTtcbiAgICBpZiAoa25vd24gIT09IHVuZGVmaW5lZCkgcmV0dXJuIGtub3duO1xuICAgIGlmIChzZWVuLmhhcyhuYW1lKSkgcmV0dXJuIDA7IC8vIGEgY3ljbGUgaW4gYSBtYWxmb3JtZWQgZmlsZVxuICAgIHNlZW4uYWRkKG5hbWUpO1xuICAgIGxldCBzdW0gPSBjb3VudHMuZ2V0KG5hbWUpID8/IDA7XG4gICAgZm9yIChjb25zdCBjIG9mIGNoaWxkcmVuLmdldChuYW1lKSA/PyBbXSkgc3VtICs9IHZpc2l0KGMsIHNlZW4pO1xuICAgIHRvdGFsLnNldChuYW1lLCBzdW0pO1xuICAgIHJldHVybiBzdW07XG4gIH07XG4gIGZvciAoY29uc3QgbmFtZSBvZiBub2RlLmtleXMoKSkgdmlzaXQobmFtZSwgbmV3IFNldCgpKTtcbiAgcmV0dXJuIHsgcm9vdHMsIG5vZGUsIGNoaWxkcmVuLCBwYXJlbnQsIHRvdGFsIH07XG59XG5cbi8qKiBgbmFtZWAgYW5kIGV2ZXJ5IGNsYXNzIHVuZGVyIGl0LiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHN1YnRyZWUodHJlZTogQ2xhc3NUcmVlLCBuYW1lOiBzdHJpbmcpOiBzdHJpbmdbXSB7XG4gIGNvbnN0IG91dDogc3RyaW5nW10gPSBbXTtcbiAgY29uc3Qgc3RhY2sgPSBbbmFtZV07XG4gIGNvbnN0IHNlZW4gPSBuZXcgU2V0PHN0cmluZz4oKTtcbiAgd2hpbGUgKHN0YWNrLmxlbmd0aCkge1xuICAgIGNvbnN0IG4gPSBzdGFjay5wb3AoKSBhcyBzdHJpbmc7XG4gICAgaWYgKHNlZW4uaGFzKG4pKSBjb250aW51ZTtcbiAgICBzZWVuLmFkZChuKTtcbiAgICBvdXQucHVzaChuKTtcbiAgICBmb3IgKGNvbnN0IGMgb2YgdHJlZS5jaGlsZHJlbi5nZXQobikgPz8gW10pIHN0YWNrLnB1c2goYyk7XG4gIH1cbiAgcmV0dXJuIG91dDtcbn1cblxuLyoqIFRoZSBjbGFzc2VzIGZyb20gdGhlIHJvb3QgZG93biB0byBgbmFtZWAncyBwYXJlbnQuICovXG5leHBvcnQgZnVuY3Rpb24gYW5jZXN0b3JzKHRyZWU6IENsYXNzVHJlZSwgbmFtZTogc3RyaW5nKTogc3RyaW5nW10ge1xuICBjb25zdCBvdXQ6IHN0cmluZ1tdID0gW107XG4gIGxldCBwID0gdHJlZS5wYXJlbnQuZ2V0KG5hbWUpID8/IG51bGw7XG4gIHdoaWxlIChwICYmICFvdXQuaW5jbHVkZXMocCkpIHtcbiAgICBvdXQudW5zaGlmdChwKTtcbiAgICBwID0gdHJlZS5wYXJlbnQuZ2V0KHApID8/IG51bGw7XG4gIH1cbiAgcmV0dXJuIG91dDtcbn1cblxuLyoqIE9uZSB2aXNpYmxlIHJvdyBvZiB0aGUgdHJlZS4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgQ2xhc3NUcmVlUm93IHtcbiAgbmFtZTogc3RyaW5nO1xuICBkZXB0aDogbnVtYmVyO1xuICBoYXNDaGlsZHJlbjogYm9vbGVhbjtcbiAgZXhwYW5kZWQ6IGJvb2xlYW47XG59XG5cbi8qKlxuICogVGhlIHJvd3MgdG8gZHJhdzogZGVwdGgtZmlyc3QgdGhyb3VnaCB0aGUgZXhwYW5kZWQgbm9kZXMuIFdpdGggYSBgcXVlcnlgLCBvbmx5IHRoZSBub2RlcyB3aG9zZVxuICogbmFtZSBvciB0aXRsZSBjb250YWlucyBpdCBhbmQgdGhlaXIgYW5jZXN0b3JzLCBhbGwgZXhwYW5kZWQuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiB2aXNpYmxlUm93cyh0cmVlOiBDbGFzc1RyZWUsIGV4cGFuZGVkOiBSZWFkb25seVNldDxzdHJpbmc+LCBxdWVyeSA9ICcnKTogQ2xhc3NUcmVlUm93W10ge1xuICBjb25zdCBxID0gcXVlcnkudHJpbSgpLnRvTG93ZXJDYXNlKCk7XG4gIGxldCBrZWVwOiBTZXQ8c3RyaW5nPiB8IG51bGwgPSBudWxsO1xuICBpZiAocSkge1xuICAgIGtlZXAgPSBuZXcgU2V0KCk7XG4gICAgZm9yIChjb25zdCBbbmFtZSwgbl0gb2YgdHJlZS5ub2RlKSB7XG4gICAgICBpZiAobmFtZS50b0xvd2VyQ2FzZSgpLmluY2x1ZGVzKHEpIHx8IChuLnRpdGxlID8/ICcnKS50b0xvd2VyQ2FzZSgpLmluY2x1ZGVzKHEpKSB7XG4gICAgICAgIGtlZXAuYWRkKG5hbWUpO1xuICAgICAgICBmb3IgKGNvbnN0IGEgb2YgYW5jZXN0b3JzKHRyZWUsIG5hbWUpKSBrZWVwLmFkZChhKTtcbiAgICAgIH1cbiAgICB9XG4gIH1cbiAgY29uc3Qgcm93czogQ2xhc3NUcmVlUm93W10gPSBbXTtcbiAgY29uc3Qgd2FsayA9IChuYW1lOiBzdHJpbmcsIGRlcHRoOiBudW1iZXIpID0+IHtcbiAgICBpZiAoa2VlcCAmJiAha2VlcC5oYXMobmFtZSkpIHJldHVybjtcbiAgICBjb25zdCBraWRzID0gdHJlZS5jaGlsZHJlbi5nZXQobmFtZSkgPz8gW107XG4gICAgY29uc3Qgb3BlbiA9IGtlZXAgPyB0cnVlIDogZXhwYW5kZWQuaGFzKG5hbWUpO1xuICAgIHJvd3MucHVzaCh7IG5hbWUsIGRlcHRoLCBoYXNDaGlsZHJlbjoga2lkcy5sZW5ndGggPiAwLCBleHBhbmRlZDogb3BlbiAmJiBraWRzLmxlbmd0aCA+IDAgfSk7XG4gICAgaWYgKG9wZW4pIGZvciAoY29uc3QgYyBvZiBraWRzKSB3YWxrKGMsIGRlcHRoICsgMSk7XG4gIH07XG4gIGZvciAoY29uc3QgciBvZiB0cmVlLnJvb3RzKSB3YWxrKHIsIDApO1xuICByZXR1cm4gcm93cztcbn1cbiJdfQ==
|