@mnaoumov/obsidian-dev-toolkit 0.0.0 → 1.0.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/LICENSE +21 -0
- package/README.md +7 -1
- package/bundlers/esbuild/package.json +6 -0
- package/bundlers/esbuild-impl/copy-to-obsidian-plugins-folder-plugin/package.json +6 -0
- package/bundlers/esbuild-impl/dependency/package.json +6 -0
- package/bundlers/esbuild-impl/fix-source-maps-plugin/package.json +6 -0
- package/bundlers/esbuild-impl/index/package.json +6 -0
- package/bundlers/esbuild-impl/obsidian-plugin-builder/package.json +6 -0
- package/bundlers/esbuild-impl/package.json +6 -0
- package/bundlers/esbuild-impl/preprocess-plugin/package.json +6 -0
- package/bundlers/esbuild-impl/rename-css-plugin/package.json +6 -0
- package/bundlers/index/package.json +6 -0
- package/bundlers/package.json +6 -0
- package/dist/demo-vault-helper/main.js +782 -0
- package/dist/demo-vault-helper/manifest.json +9 -0
- package/dist/integration-test-plugin/main.js +45388 -0
- package/dist/integration-test-plugin/manifest.json +8 -0
- package/dist/lib/cjs/bundlers/esbuild-impl/copy-to-obsidian-plugins-folder-plugin.cjs +335 -0
- package/dist/lib/cjs/bundlers/esbuild-impl/copy-to-obsidian-plugins-folder-plugin.d.cts +38 -0
- package/dist/lib/cjs/bundlers/esbuild-impl/dependency.cjs +253 -0
- package/dist/lib/cjs/bundlers/esbuild-impl/dependency.d.cts +20 -0
- package/dist/lib/cjs/bundlers/esbuild-impl/fix-source-maps-plugin.cjs +226 -0
- package/dist/lib/cjs/bundlers/esbuild-impl/fix-source-maps-plugin.d.cts +34 -0
- package/dist/lib/cjs/bundlers/esbuild-impl/index.cjs +192 -0
- package/dist/lib/cjs/bundlers/esbuild-impl/index.d.cts +7 -0
- package/dist/lib/cjs/bundlers/esbuild-impl/obsidian-plugin-builder.cjs +375 -0
- package/dist/lib/cjs/bundlers/esbuild-impl/obsidian-plugin-builder.d.cts +98 -0
- package/dist/lib/cjs/bundlers/esbuild-impl/preprocess-plugin.cjs +247 -0
- package/dist/lib/cjs/bundlers/esbuild-impl/preprocess-plugin.d.cts +30 -0
- package/dist/lib/cjs/bundlers/esbuild-impl/rename-css-plugin.cjs +184 -0
- package/dist/lib/cjs/bundlers/esbuild-impl/rename-css-plugin.d.cts +14 -0
- package/dist/lib/cjs/bundlers/esbuild.cjs +177 -0
- package/dist/lib/cjs/bundlers/esbuild.d.cts +11 -0
- package/dist/lib/cjs/bundlers/index.cjs +180 -0
- package/dist/lib/cjs/bundlers/index.d.cts +3 -0
- package/dist/lib/cjs/demo-vault-app-json.cjs +199 -0
- package/dist/lib/cjs/demo-vault-app-json.d.cts +93 -0
- package/dist/lib/cjs/demo-vault-buttons.cjs +580 -0
- package/dist/lib/cjs/demo-vault-buttons.d.cts +259 -0
- package/dist/lib/cjs/demo-vault-coverage.cjs +725 -0
- package/dist/lib/cjs/demo-vault-coverage.d.cts +533 -0
- package/dist/lib/cjs/demo-vault.cjs +309 -0
- package/dist/lib/cjs/demo-vault.d.cts +33 -0
- package/dist/lib/cjs/formatters/dprint.cjs +173 -0
- package/dist/lib/cjs/formatters/dprint.d.cts +15 -0
- package/dist/lib/cjs/formatters/index.cjs +177 -0
- package/dist/lib/cjs/formatters/index.d.cts +2 -0
- package/dist/lib/cjs/index.cjs +207 -0
- package/dist/lib/cjs/index.d.cts +16 -0
- package/dist/lib/cjs/integration-test-setup.cjs +142 -0
- package/dist/lib/cjs/integration-test-setup.d.cts +33 -0
- package/dist/lib/cjs/integration-test-vitest-global-setup.cjs +176 -0
- package/dist/lib/cjs/integration-test-vitest-global-setup.d.cts +39 -0
- package/dist/lib/cjs/jest-setup.cjs +147 -0
- package/dist/lib/cjs/jest-setup.d.cts +13 -0
- package/dist/lib/cjs/linters/eslint-config.cjs +365 -0
- package/dist/lib/cjs/linters/eslint-config.d.cts +25 -0
- package/dist/lib/cjs/linters/eslint-rules/index.cjs +201 -0
- package/dist/lib/cjs/linters/eslint-rules/index.d.cts +10 -0
- package/dist/lib/cjs/linters/eslint-rules/manifest-description.cjs +268 -0
- package/dist/lib/cjs/linters/eslint-rules/manifest-description.d.cts +54 -0
- package/dist/lib/cjs/linters/eslint-rules/manifest-helpers.cjs +231 -0
- package/dist/lib/cjs/linters/eslint-rules/manifest-helpers.d.cts +141 -0
- package/dist/lib/cjs/linters/eslint-rules/manifest-id.cjs +228 -0
- package/dist/lib/cjs/linters/eslint-rules/manifest-id.d.cts +32 -0
- package/dist/lib/cjs/linters/eslint-rules/manifest-name.cjs +229 -0
- package/dist/lib/cjs/linters/eslint-rules/manifest-name.d.cts +30 -0
- package/dist/lib/cjs/linters/eslint-rules/manifest-schema.cjs +329 -0
- package/dist/lib/cjs/linters/eslint-rules/manifest-schema.d.cts +45 -0
- package/dist/lib/cjs/linters/eslint-rules/no-over-cap-wait-in-eval-in-obsidian.cjs +670 -0
- package/dist/lib/cjs/linters/eslint-rules/no-over-cap-wait-in-eval-in-obsidian.d.cts +10 -0
- package/dist/lib/cjs/linters/eslint-rules/no-untrusted-input-events.cjs +260 -0
- package/dist/lib/cjs/linters/eslint-rules/no-untrusted-input-events.d.cts +10 -0
- package/dist/lib/cjs/linters/eslint-rules/obsidian-dev-utils-plugin.cjs +186 -0
- package/dist/lib/cjs/linters/eslint-rules/obsidian-dev-utils-plugin.d.cts +13 -0
- package/dist/lib/cjs/linters/eslint-rules/require-component-suffix.cjs +291 -0
- package/dist/lib/cjs/linters/eslint-rules/require-component-suffix.d.cts +18 -0
- package/dist/lib/cjs/linters/eslint.cjs +173 -0
- package/dist/lib/cjs/linters/eslint.d.cts +15 -0
- package/dist/lib/cjs/linters/index.cjs +189 -0
- package/dist/lib/cjs/linters/index.d.cts +6 -0
- package/dist/lib/cjs/linters/markdownlint.cjs +173 -0
- package/dist/lib/cjs/linters/markdownlint.d.cts +15 -0
- package/dist/lib/cjs/linters/obsidianmd-rule-custom-message.cjs +189 -0
- package/dist/lib/cjs/linters/obsidianmd-rule-custom-message.d.cts +40 -0
- package/dist/lib/cjs/obsidian-plugin-repo-paths.cjs +229 -0
- package/dist/lib/cjs/obsidian-plugin-repo-paths.d.cts +253 -0
- package/dist/lib/cjs/setup.cjs +176 -0
- package/dist/lib/cjs/setup.d.cts +21 -0
- package/dist/lib/cjs/templates.cjs +185 -0
- package/dist/lib/cjs/templates.d.cts +13 -0
- package/dist/lib/cjs/test-runners/index.cjs +183 -0
- package/dist/lib/cjs/test-runners/index.d.cts +4 -0
- package/dist/lib/cjs/test-runners/integration-test-plugin.cjs +224 -0
- package/dist/lib/cjs/test-runners/integration-test-plugin.d.cts +44 -0
- package/dist/lib/cjs/test-runners/performance-eval-cap.cjs +170 -0
- package/dist/lib/cjs/test-runners/performance-eval-cap.d.cts +27 -0
- package/dist/lib/cjs/test-runners/stale-build-global-setup.cjs +230 -0
- package/dist/lib/cjs/test-runners/stale-build-global-setup.d.cts +86 -0
- package/dist/lib/cjs/test-runners/vitest-config.cjs +497 -0
- package/dist/lib/cjs/test-runners/vitest-config.d.cts +200 -0
- package/dist/lib/cjs/version.cjs +275 -0
- package/dist/lib/cjs/version.d.cts +92 -0
- package/dist/lib/cjs/vitest-setup.cjs +147 -0
- package/dist/lib/cjs/vitest-setup.d.cts +11 -0
- package/dist/lib/esm/bundlers/esbuild-impl/copy-to-obsidian-plugins-folder-plugin.d.mts +38 -0
- package/dist/lib/esm/bundlers/esbuild-impl/copy-to-obsidian-plugins-folder-plugin.mjs +226 -0
- package/dist/lib/esm/bundlers/esbuild-impl/dependency.d.mts +20 -0
- package/dist/lib/esm/bundlers/esbuild-impl/dependency.mjs +138 -0
- package/dist/lib/esm/bundlers/esbuild-impl/fix-source-maps-plugin.d.mts +34 -0
- package/dist/lib/esm/bundlers/esbuild-impl/fix-source-maps-plugin.mjs +116 -0
- package/dist/lib/esm/bundlers/esbuild-impl/index.d.mts +7 -0
- package/dist/lib/esm/bundlers/esbuild-impl/index.mjs +64 -0
- package/dist/lib/esm/bundlers/esbuild-impl/obsidian-plugin-builder.d.mts +98 -0
- package/dist/lib/esm/bundlers/esbuild-impl/obsidian-plugin-builder.mjs +255 -0
- package/dist/lib/esm/bundlers/esbuild-impl/preprocess-plugin.d.mts +30 -0
- package/dist/lib/esm/bundlers/esbuild-impl/preprocess-plugin.mjs +134 -0
- package/dist/lib/esm/bundlers/esbuild-impl/rename-css-plugin.d.mts +14 -0
- package/dist/lib/esm/bundlers/esbuild-impl/rename-css-plugin.mjs +71 -0
- package/dist/lib/esm/bundlers/esbuild.d.mts +11 -0
- package/dist/lib/esm/bundlers/esbuild.mjs +66 -0
- package/dist/lib/esm/bundlers/index.d.mts +3 -0
- package/dist/lib/esm/bundlers/index.mjs +56 -0
- package/dist/lib/esm/demo-vault-app-json.d.mts +93 -0
- package/dist/lib/esm/demo-vault-app-json.mjs +83 -0
- package/dist/lib/esm/demo-vault-buttons.d.mts +259 -0
- package/dist/lib/esm/demo-vault-buttons.mjs +460 -0
- package/dist/lib/esm/demo-vault-coverage.d.mts +533 -0
- package/dist/lib/esm/demo-vault-coverage.mjs +626 -0
- package/dist/lib/esm/demo-vault.d.mts +33 -0
- package/dist/lib/esm/demo-vault.mjs +205 -0
- package/dist/lib/esm/formatters/dprint.d.mts +15 -0
- package/dist/lib/esm/formatters/dprint.mjs +60 -0
- package/dist/lib/esm/formatters/index.d.mts +2 -0
- package/dist/lib/esm/formatters/index.mjs +54 -0
- package/dist/lib/esm/index.d.mts +16 -0
- package/dist/lib/esm/index.mjs +74 -0
- package/dist/lib/esm/integration-test-setup.d.mts +33 -0
- package/dist/lib/esm/integration-test-setup.mjs +52 -0
- package/dist/lib/esm/integration-test-vitest-global-setup.d.mts +39 -0
- package/dist/lib/esm/integration-test-vitest-global-setup.mjs +65 -0
- package/dist/lib/esm/jest-setup.d.mts +13 -0
- package/dist/lib/esm/jest-setup.mjs +61 -0
- package/dist/lib/esm/linters/eslint-config.d.mts +25 -0
- package/dist/lib/esm/linters/eslint-config.mjs +247 -0
- package/dist/lib/esm/linters/eslint-rules/index.d.mts +10 -0
- package/dist/lib/esm/linters/eslint-rules/index.mjs +70 -0
- package/dist/lib/esm/linters/eslint-rules/manifest-description.d.mts +54 -0
- package/dist/lib/esm/linters/eslint-rules/manifest-description.mjs +154 -0
- package/dist/lib/esm/linters/eslint-rules/manifest-helpers.d.mts +141 -0
- package/dist/lib/esm/linters/eslint-rules/manifest-helpers.mjs +98 -0
- package/dist/lib/esm/linters/eslint-rules/manifest-id.d.mts +32 -0
- package/dist/lib/esm/linters/eslint-rules/manifest-id.mjs +117 -0
- package/dist/lib/esm/linters/eslint-rules/manifest-name.d.mts +30 -0
- package/dist/lib/esm/linters/eslint-rules/manifest-name.mjs +118 -0
- package/dist/lib/esm/linters/eslint-rules/manifest-schema.d.mts +45 -0
- package/dist/lib/esm/linters/eslint-rules/manifest-schema.mjs +220 -0
- package/dist/lib/esm/linters/eslint-rules/no-over-cap-wait-in-eval-in-obsidian.d.mts +10 -0
- package/dist/lib/esm/linters/eslint-rules/no-over-cap-wait-in-eval-in-obsidian.mjs +559 -0
- package/dist/lib/esm/linters/eslint-rules/no-untrusted-input-events.d.mts +10 -0
- package/dist/lib/esm/linters/eslint-rules/no-untrusted-input-events.mjs +146 -0
- package/dist/lib/esm/linters/eslint-rules/obsidian-dev-utils-plugin.d.mts +13 -0
- package/dist/lib/esm/linters/eslint-rules/obsidian-dev-utils-plugin.mjs +73 -0
- package/dist/lib/esm/linters/eslint-rules/require-component-suffix.d.mts +18 -0
- package/dist/lib/esm/linters/eslint-rules/require-component-suffix.mjs +175 -0
- package/dist/lib/esm/linters/eslint.d.mts +15 -0
- package/dist/lib/esm/linters/eslint.mjs +60 -0
- package/dist/lib/esm/linters/index.d.mts +6 -0
- package/dist/lib/esm/linters/index.mjs +62 -0
- package/dist/lib/esm/linters/markdownlint.d.mts +15 -0
- package/dist/lib/esm/linters/markdownlint.mjs +60 -0
- package/dist/lib/esm/linters/obsidianmd-rule-custom-message.d.mts +40 -0
- package/dist/lib/esm/linters/obsidianmd-rule-custom-message.mjs +75 -0
- package/dist/lib/esm/obsidian-plugin-repo-paths.d.mts +253 -0
- package/dist/lib/esm/obsidian-plugin-repo-paths.mjs +116 -0
- package/dist/lib/esm/setup.d.mts +21 -0
- package/dist/lib/esm/setup.mjs +63 -0
- package/dist/lib/esm/templates.d.mts +13 -0
- package/dist/lib/esm/templates.mjs +65 -0
- package/dist/lib/esm/test-runners/index.d.mts +4 -0
- package/dist/lib/esm/test-runners/index.mjs +58 -0
- package/dist/lib/esm/test-runners/integration-test-plugin.d.mts +44 -0
- package/dist/lib/esm/test-runners/integration-test-plugin.mjs +102 -0
- package/dist/lib/esm/test-runners/performance-eval-cap.d.mts +27 -0
- package/dist/lib/esm/test-runners/performance-eval-cap.mjs +56 -0
- package/dist/lib/esm/test-runners/stale-build-global-setup.d.mts +86 -0
- package/dist/lib/esm/test-runners/stale-build-global-setup.mjs +123 -0
- package/dist/lib/esm/test-runners/vitest-config.d.mts +200 -0
- package/dist/lib/esm/test-runners/vitest-config.mjs +377 -0
- package/dist/lib/esm/version.d.mts +92 -0
- package/dist/lib/esm/version.mjs +168 -0
- package/dist/lib/esm/vitest-setup.d.mts +11 -0
- package/dist/lib/esm/vitest-setup.mjs +61 -0
- package/dist/templates/.markdownlint-cli2.mjs +4 -0
- package/dist/templates/.nano-staged.mjs +4 -0
- package/dist/templates/commitlint.config.ts +3 -0
- package/dist/templates/dprint.json +26 -0
- package/dist/templates/eslint.config.mts +3 -0
- package/dist/templates/scripts/build/build-clean.ts +4 -0
- package/dist/templates/scripts/build/build-compile-svelte.ts +4 -0
- package/dist/templates/scripts/build/build-compile-typescript.ts +4 -0
- package/dist/templates/scripts/build/build-compile.ts +4 -0
- package/dist/templates/scripts/build/build-templates.ts +4 -0
- package/dist/templates/scripts/bundlers/esbuild/build.ts +4 -0
- package/dist/templates/scripts/bundlers/esbuild/dev.ts +4 -0
- package/dist/templates/scripts/commitlint-config.ts +3 -0
- package/dist/templates/scripts/eslint-config.ts +10 -0
- package/dist/templates/scripts/formatters/dprint/format-check.ts +8 -0
- package/dist/templates/scripts/formatters/dprint/format.ts +8 -0
- package/dist/templates/scripts/gate/gate.ts +10 -0
- package/dist/templates/scripts/linters/cspell/spellcheck.ts +8 -0
- package/dist/templates/scripts/linters/eslint/lint-fix.ts +8 -0
- package/dist/templates/scripts/linters/eslint/lint.ts +8 -0
- package/dist/templates/scripts/linters/markdownlint/lint-md-fix.ts +8 -0
- package/dist/templates/scripts/linters/markdownlint/lint-md.ts +8 -0
- package/dist/templates/scripts/linters/over-exposure/find-overexposed-fix.ts +25 -0
- package/dist/templates/scripts/linters/over-exposure/find-overexposed.ts +15 -0
- package/dist/templates/scripts/markdownlint-cli2-config.ts +3 -0
- package/dist/templates/scripts/nano-staged-config.ts +3 -0
- package/dist/templates/scripts/test-runners/vitest/test-coverage.ts +4 -0
- package/dist/templates/scripts/test-runners/vitest/test-watch.ts +4 -0
- package/dist/templates/scripts/test-runners/vitest/test.ts +4 -0
- package/dist/templates/scripts/version/version.ts +10 -0
- package/dist/templates/scripts/vitest-config.ts +3 -0
- package/dist/templates/vitest.config.ts +3 -0
- package/formatters/dprint/package.json +6 -0
- package/formatters/index/package.json +6 -0
- package/formatters/package.json +6 -0
- package/linters/eslint/package.json +6 -0
- package/linters/eslint-config/package.json +6 -0
- package/linters/eslint-rules/index/package.json +6 -0
- package/linters/eslint-rules/manifest-description/package.json +6 -0
- package/linters/eslint-rules/manifest-helpers/package.json +6 -0
- package/linters/eslint-rules/manifest-id/package.json +6 -0
- package/linters/eslint-rules/manifest-name/package.json +6 -0
- package/linters/eslint-rules/manifest-schema/package.json +6 -0
- package/linters/eslint-rules/no-over-cap-wait-in-eval-in-obsidian/package.json +6 -0
- package/linters/eslint-rules/no-untrusted-input-events/package.json +6 -0
- package/linters/eslint-rules/obsidian-dev-utils-plugin/package.json +6 -0
- package/linters/eslint-rules/package.json +6 -0
- package/linters/eslint-rules/require-component-suffix/package.json +6 -0
- package/linters/index/package.json +6 -0
- package/linters/markdownlint/package.json +6 -0
- package/linters/obsidianmd-rule-custom-message/package.json +6 -0
- package/linters/package.json +6 -0
- package/package.json +241 -13
- package/test-runners/index/package.json +6 -0
- package/test-runners/integration-test-plugin/package.json +6 -0
- package/test-runners/package.json +6 -0
- package/test-runners/performance-eval-cap/package.json +6 -0
- package/test-runners/stale-build-global-setup/package.json +6 -0
- package/test-runners/vitest-config/package.json +6 -0
|
@@ -0,0 +1,725 @@
|
|
|
1
|
+
/*
|
|
2
|
+
THIS IS A GENERATED/BUNDLED FILE BY ESBUILD
|
|
3
|
+
if you want to view the source, please visit the github repository of this plugin
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
(function () {
|
|
7
|
+
function ensureDisposeSymbols(symbolConstructor = Symbol) {
|
|
8
|
+
symbolConstructor.asyncDispose ??= symbolConstructor.for('Symbol.asyncDispose');
|
|
9
|
+
symbolConstructor.dispose ??= symbolConstructor.for('Symbol.dispose');
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
function ensureBrowserProcess() {
|
|
13
|
+
const browserProcess = {
|
|
14
|
+
browser: true,
|
|
15
|
+
cwd() {
|
|
16
|
+
return '/';
|
|
17
|
+
},
|
|
18
|
+
env: {},
|
|
19
|
+
platform: 'android'
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
// eslint-disable-next-line obsidianmd/no-global-this, unicorn/no-unnecessary-global-this -- Must stay `globalThis`-qualified: in the emitted banner a bare `process` is a free identifier, so reading it where the host has none throws a ReferenceError instead of yielding `undefined`. That is the very case this function exists to handle.
|
|
23
|
+
const existingProcess = globalThis.process;
|
|
24
|
+
|
|
25
|
+
if (!existingProcess) {
|
|
26
|
+
// eslint-disable-next-line obsidianmd/no-global-this -- Actively use globalThis.
|
|
27
|
+
globalThis.process = browserProcess;
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
if (existingProcess.versions?.node) {
|
|
32
|
+
return;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
const existingProcessRecord = existingProcess;
|
|
36
|
+
|
|
37
|
+
for (const [key, value] of Object.entries(browserProcess)) {
|
|
38
|
+
existingProcessRecord[key] ??= value;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
existingProcessRecord['browser'] = true;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
function keepName($unknown) {
|
|
45
|
+
return $unknown;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
(function initCjs() {
|
|
49
|
+
// eslint-disable-next-line obsidianmd/no-global-this -- Actively use globalThis.
|
|
50
|
+
const globalThisRecord = globalThis;
|
|
51
|
+
ensureDisposeSymbols();
|
|
52
|
+
globalThisRecord['__name'] ??= keepName;
|
|
53
|
+
globalThisRecord['__extractDefault'] ??= extractDefault;
|
|
54
|
+
|
|
55
|
+
ensureBrowserProcess();
|
|
56
|
+
|
|
57
|
+
// eslint-disable-next-line unicorn/consistent-function-scoping -- Serialized with initCjs into the banner; at module scope it would be left out of it.
|
|
58
|
+
function extractDefault(module) {
|
|
59
|
+
return module && module.__esModule && 'default' in module ? module.default : module;
|
|
60
|
+
}
|
|
61
|
+
})();
|
|
62
|
+
})();
|
|
63
|
+
(function patchObsidianRequire() {
|
|
64
|
+
const originalRequire = require;
|
|
65
|
+
if (!originalRequire || originalRequire.__isPatched) {
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
// eslint-disable-next-line no-global-assign, no-implicit-globals -- We need to patch the `require()` function.
|
|
70
|
+
require = Object.assign(
|
|
71
|
+
(id) => requirePatched(id),
|
|
72
|
+
originalRequire,
|
|
73
|
+
{
|
|
74
|
+
__isPatched: true
|
|
75
|
+
}
|
|
76
|
+
);
|
|
77
|
+
|
|
78
|
+
function extractDefault(module) {
|
|
79
|
+
return module && module.__esModule && 'default' in module ? module.default : module;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
const OBSIDIAN_BUILT_IN_MODULE_NAMES = new Set([
|
|
83
|
+
'@codemirror/autocomplete',
|
|
84
|
+
'@codemirror/collab',
|
|
85
|
+
'@codemirror/commands',
|
|
86
|
+
'@codemirror/language',
|
|
87
|
+
'@codemirror/lint',
|
|
88
|
+
'@codemirror/search',
|
|
89
|
+
'@codemirror/state',
|
|
90
|
+
'@codemirror/text',
|
|
91
|
+
'@codemirror/view',
|
|
92
|
+
'@lezer/common',
|
|
93
|
+
'@lezer/highlight',
|
|
94
|
+
'@lezer/lr',
|
|
95
|
+
'obsidian']
|
|
96
|
+
);
|
|
97
|
+
|
|
98
|
+
const DEPRECATED_OBSIDIAN_BUILT_IN_MODULE_NAMES = new Set([
|
|
99
|
+
'@codemirror/closebrackets',
|
|
100
|
+
'@codemirror/comment',
|
|
101
|
+
'@codemirror/fold',
|
|
102
|
+
'@codemirror/gutter',
|
|
103
|
+
'@codemirror/highlight',
|
|
104
|
+
'@codemirror/history',
|
|
105
|
+
'@codemirror/matchbrackets',
|
|
106
|
+
'@codemirror/panel',
|
|
107
|
+
'@codemirror/rangeset',
|
|
108
|
+
'@codemirror/rectangular-selection',
|
|
109
|
+
'@codemirror/stream-parser',
|
|
110
|
+
'@codemirror/tooltip']
|
|
111
|
+
);
|
|
112
|
+
|
|
113
|
+
function requirePatched(id) {
|
|
114
|
+
if (OBSIDIAN_BUILT_IN_MODULE_NAMES.has(id) || DEPRECATED_OBSIDIAN_BUILT_IN_MODULE_NAMES.has(id)) {
|
|
115
|
+
return originalRequire?.(id);
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
// eslint-disable-next-line @typescript-eslint/no-deprecated, obsidianmd/no-global-this -- Need access to app. Actively use globalThis.
|
|
119
|
+
if (globalThis.app.isMobile) {
|
|
120
|
+
if (id === 'process' || id === 'node:process') {
|
|
121
|
+
// eslint-disable-next-line no-console -- Valid usage.
|
|
122
|
+
console.debug(`The most likely you can safely ignore this error. Module not found: ${id}. Fake process object is returned instead.`);
|
|
123
|
+
|
|
124
|
+
return process;
|
|
125
|
+
}
|
|
126
|
+
} else {
|
|
127
|
+
const module = originalRequire?.(id);
|
|
128
|
+
if (module) {
|
|
129
|
+
return extractDefault(module);
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
// eslint-disable-next-line no-console -- Valid usage.
|
|
134
|
+
console.debug(`The most likely you can safely ignore this error. Module not found: ${id}. Empty object is returned instead.`);
|
|
135
|
+
return {};
|
|
136
|
+
}
|
|
137
|
+
})();
|
|
138
|
+
|
|
139
|
+
"use strict";
|
|
140
|
+
var __defProp = Object.defineProperty;
|
|
141
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
142
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
143
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
144
|
+
var __export = (target, all) => {
|
|
145
|
+
for (var name in all)
|
|
146
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
147
|
+
};
|
|
148
|
+
var __copyProps = (to, from, except, desc) => {
|
|
149
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
150
|
+
for (let key of __getOwnPropNames(from))
|
|
151
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
152
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
153
|
+
}
|
|
154
|
+
return to;
|
|
155
|
+
};
|
|
156
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
157
|
+
var demo_vault_coverage_exports = {};
|
|
158
|
+
__export(demo_vault_coverage_exports, {
|
|
159
|
+
DemoVaultCoverageChecker: () => DemoVaultCoverageChecker,
|
|
160
|
+
registerDemoVaultCoverageSuite: () => registerDemoVaultCoverageSuite
|
|
161
|
+
});
|
|
162
|
+
module.exports = __toCommonJS(demo_vault_coverage_exports);
|
|
163
|
+
var import_object_utils = require('@mnaoumov/typescript-lib/object-utils');
|
|
164
|
+
var import_path = require('@mnaoumov/typescript-lib/path');
|
|
165
|
+
var import_reg_exp = require('@mnaoumov/typescript-lib/reg-exp');
|
|
166
|
+
var import_type_guards = require('@mnaoumov/typescript-lib/type-guards');
|
|
167
|
+
var import_node_fs = require('node:fs');
|
|
168
|
+
var import_vitest = require('vitest');
|
|
169
|
+
var import_demo_vault_app_json = require('./demo-vault-app-json.cjs');
|
|
170
|
+
var import_obsidian_plugin_repo_paths = require('./obsidian-plugin-repo-paths.cjs');
|
|
171
|
+
class DemoVaultCoverageChecker {
|
|
172
|
+
cachedCorpus = null;
|
|
173
|
+
cachedNotes = null;
|
|
174
|
+
demoVaultFolder;
|
|
175
|
+
excludedNotes;
|
|
176
|
+
rootFolder;
|
|
177
|
+
/**
|
|
178
|
+
* Creates a checker rooted at a plugin repo.
|
|
179
|
+
*
|
|
180
|
+
* @param params - The parameters for the constructor.
|
|
181
|
+
*/
|
|
182
|
+
constructor(params) {
|
|
183
|
+
this.rootFolder = params.rootFolder;
|
|
184
|
+
this.demoVaultFolder = (0, import_path.join)(this.rootFolder, import_obsidian_plugin_repo_paths.ObsidianPluginRepoPaths.DemoVault);
|
|
185
|
+
this.excludedNotes = new Set(params.excludedNotes ?? DEFAULT_EXCLUDED_NOTES);
|
|
186
|
+
}
|
|
187
|
+
/**
|
|
188
|
+
* Collects the demo notes as paths relative to the demo vault folder (for a non-trivial-surface guard).
|
|
189
|
+
*
|
|
190
|
+
* @returns The relative paths of every `*.md` note in the demo vault.
|
|
191
|
+
*/
|
|
192
|
+
collectDemoNoteRelativePaths() {
|
|
193
|
+
return this.collectNotes().map((note) => note.relativePath);
|
|
194
|
+
}
|
|
195
|
+
/**
|
|
196
|
+
* Reads and caches every demo note individually — the per-note view the authoring checks work on, as
|
|
197
|
+
* opposed to the concatenated {@link DemoVaultCoverageChecker.readCorpus}.
|
|
198
|
+
*
|
|
199
|
+
* @returns Every `*.md` note in the demo vault, excluded ones included.
|
|
200
|
+
*/
|
|
201
|
+
collectNotes() {
|
|
202
|
+
this.cachedNotes ??= this.collectMarkdownFiles(this.demoVaultFolder).map((file) => ({
|
|
203
|
+
content: (0, import_node_fs.readFileSync)(file, "utf-8"),
|
|
204
|
+
relativePath: (0, import_path.relative)(this.demoVaultFolder, file)
|
|
205
|
+
}));
|
|
206
|
+
return this.cachedNotes;
|
|
207
|
+
}
|
|
208
|
+
/**
|
|
209
|
+
* Finds the `.obsidian/app.json` settings the vault commits that `obsidian-dev-utils` owns and writes
|
|
210
|
+
* into the archived vault itself. A committed one is a second copy of a setting nothing reconciles, and
|
|
211
|
+
* it is the copy that goes stale — so the convention is that the vault commits none of them.
|
|
212
|
+
*
|
|
213
|
+
* @returns The names of the owned settings the committed `app.json` sets. A vault that commits no
|
|
214
|
+
* `app.json` at all is fine, and yields none.
|
|
215
|
+
*/
|
|
216
|
+
findCommittedAppJsonSettings() {
|
|
217
|
+
const appJsonPath = (0, import_path.join)(this.demoVaultFolder, import_obsidian_plugin_repo_paths.ObsidianPluginRepoPaths.DotObsidian, import_obsidian_plugin_repo_paths.ObsidianPluginRepoPaths.AppJson);
|
|
218
|
+
const content = (0, import_node_fs.existsSync)(appJsonPath) ? (0, import_node_fs.readFileSync)(appJsonPath, "utf-8") : null;
|
|
219
|
+
return (0, import_demo_vault_app_json.findOwnedDemoVaultAppJsonSettings)({ appJson: (0, import_demo_vault_app_json.parseDemoVaultAppJson)({ content, path: appJsonPath }) });
|
|
220
|
+
}
|
|
221
|
+
/**
|
|
222
|
+
* Finds notes carrying a `[Docs](…)` link line. The note IS the documentation, so a line pointing
|
|
223
|
+
* elsewhere for the real explanation is the shape this convention exists to remove.
|
|
224
|
+
*
|
|
225
|
+
* @returns The relative paths of the offending notes.
|
|
226
|
+
*/
|
|
227
|
+
findNotesWithDocsLinks() {
|
|
228
|
+
return this.collectCheckableNotes().filter((note) => getLinesOutsideFences(note.content).some((line) => DOCS_LINK_REG_EXP.test(line))).map((note) => note.relativePath);
|
|
229
|
+
}
|
|
230
|
+
/**
|
|
231
|
+
* Finds notes that do not open with an `# H1` (frontmatter aside).
|
|
232
|
+
*
|
|
233
|
+
* @returns The relative paths of the offending notes.
|
|
234
|
+
*/
|
|
235
|
+
findNotesWithoutH1() {
|
|
236
|
+
return this.collectCheckableNotes().filter((note) => !hasH1(note.content)).map((note) => note.relativePath);
|
|
237
|
+
}
|
|
238
|
+
/**
|
|
239
|
+
* Finds notes with no prose paragraph before their first code fence — the 1-3 sentences saying what the
|
|
240
|
+
* feature does and why a reader would want it, without which the note is a button with no lesson.
|
|
241
|
+
*
|
|
242
|
+
* @returns The relative paths of the offending notes.
|
|
243
|
+
*/
|
|
244
|
+
findNotesWithoutIntroProse() {
|
|
245
|
+
return this.collectCheckableNotes().filter((note) => !hasIntroProse(note.content)).map((note) => note.relativePath);
|
|
246
|
+
}
|
|
247
|
+
/**
|
|
248
|
+
* Finds notes whose wikilink allowance is not doing any work — declared without a reason, or on a note
|
|
249
|
+
* that carries no wikilink at all. Both are drift: an exemption nobody can justify, and one nothing needs
|
|
250
|
+
* any more, which would go on hiding the next wikilink somebody adds by accident.
|
|
251
|
+
*
|
|
252
|
+
* @returns The relative paths of the offending notes.
|
|
253
|
+
*/
|
|
254
|
+
findNotesWithUnjustifiedWikilinkAllowance() {
|
|
255
|
+
return this.collectCheckableNotes().flatMap((note) => {
|
|
256
|
+
const scan = scanWikilinkDirectives(note.content);
|
|
257
|
+
const problems = [...scan.problems];
|
|
258
|
+
const reason = readWikilinkAllowanceReason(note.content);
|
|
259
|
+
if (reason !== null) {
|
|
260
|
+
if (reason.trim() === "") {
|
|
261
|
+
problems.push("a note-level allowance with no reason");
|
|
262
|
+
} else if (!hasWikilink(note.content)) {
|
|
263
|
+
problems.push("a note-level allowance covering no wikilink");
|
|
264
|
+
} else if (scan.allowedLineIndexes.size > 0) {
|
|
265
|
+
problems.push("inline directives the note-level allowance already covers");
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
return problems.map((problem) => `${note.relativePath}: ${problem}`);
|
|
269
|
+
});
|
|
270
|
+
}
|
|
271
|
+
/**
|
|
272
|
+
* Finds notes using an Obsidian `[[wikilink]]` outside a code fence. The demo vault is also read on
|
|
273
|
+
* GitHub, where a wikilink renders as literal brackets and leads nowhere. A wikilink shown INSIDE a
|
|
274
|
+
* fence is sample text, not navigation, so fenced blocks are skipped, as is a note that declares in its
|
|
275
|
+
* frontmatter why its wikilinks are the point — see the file overview.
|
|
276
|
+
*
|
|
277
|
+
* @returns The relative paths of the offending notes.
|
|
278
|
+
*/
|
|
279
|
+
findNotesWithWikilinks() {
|
|
280
|
+
return this.collectCheckableNotes().filter((note) => {
|
|
281
|
+
if (readWikilinkAllowanceReason(note.content) !== null) {
|
|
282
|
+
return false;
|
|
283
|
+
}
|
|
284
|
+
const { allowedLineIndexes } = scanWikilinkDirectives(note.content);
|
|
285
|
+
return findWikilinkLineIndexes(note.content).some((lineIndex) => !allowedLineIndexes.has(lineIndex));
|
|
286
|
+
}).map((note) => note.relativePath);
|
|
287
|
+
}
|
|
288
|
+
/**
|
|
289
|
+
* Finds members that the demo notes reference on a receiver but that no longer exist on it (rename drift).
|
|
290
|
+
*
|
|
291
|
+
* @param params - The parameters for the lookup.
|
|
292
|
+
* @returns The distinct stale member names referenced in the demo corpus.
|
|
293
|
+
*/
|
|
294
|
+
findStaleReferences(params) {
|
|
295
|
+
const validMembers = new Set(params.validMembers);
|
|
296
|
+
const referenced = [...this.readCorpus().matchAll(new RegExp(String.raw`${params.receiver}\.(?<member>\w+)`, "g"))].map((match) => (0, import_reg_exp.getMandatoryNamedGroup)(match, "member"));
|
|
297
|
+
return [...new Set(referenced)].filter((member) => !validMembers.has(member));
|
|
298
|
+
}
|
|
299
|
+
/**
|
|
300
|
+
* Finds members that are not demonstrated anywhere in the demo corpus.
|
|
301
|
+
*
|
|
302
|
+
* @param params - The parameters for the lookup.
|
|
303
|
+
* @returns The member names with no demonstration.
|
|
304
|
+
*/
|
|
305
|
+
findUndemonstratedMembers(params) {
|
|
306
|
+
const corpus = this.readCorpus();
|
|
307
|
+
return params.members.filter((member) => {
|
|
308
|
+
const needle = params.receiver === void 0 ? member : `${params.receiver}.${member}`;
|
|
309
|
+
return !corpus.includes(needle);
|
|
310
|
+
});
|
|
311
|
+
}
|
|
312
|
+
/**
|
|
313
|
+
* Finds feature docs that no demo note links to.
|
|
314
|
+
*
|
|
315
|
+
* @param params - The parameters for the lookup.
|
|
316
|
+
* @returns The feature-doc basenames (without `.md`) not linked from any demo note.
|
|
317
|
+
*/
|
|
318
|
+
findUnlinkedFeatureDocs(params) {
|
|
319
|
+
const nonFeatureDocs = new Set(params.nonFeatureDocs);
|
|
320
|
+
const featureDocs = (0, import_node_fs.readdirSync)((0, import_path.join)(this.rootFolder, params.docsFolder)).filter((file) => file.endsWith(".md")).map((file) => file.replace(/\.md$/, "")).filter((name) => !nonFeatureDocs.has(name));
|
|
321
|
+
const linkedDocs = new Set(
|
|
322
|
+
[...this.readCorpus().matchAll(/docs\/(?<doc>[\w-]+)\.md/g)].map((match) => (0, import_reg_exp.getMandatoryNamedGroup)(match, "doc"))
|
|
323
|
+
);
|
|
324
|
+
return featureDocs.filter((doc) => !linkedDocs.has(doc));
|
|
325
|
+
}
|
|
326
|
+
/**
|
|
327
|
+
* Finds notes that cannot be reached from the start note by following Markdown links between notes.
|
|
328
|
+
*
|
|
329
|
+
* The walk starts at {@link DemoVaultCoverageCheckerFindUnreachableNotesParams.startNote} and follows
|
|
330
|
+
* every `[Text](<./NN Name.md>)` link outside a code fence, transitively. A note nothing links to is
|
|
331
|
+
* one a reader can only find by browsing the file list — which is exactly what the grouped index in the
|
|
332
|
+
* start note is meant to replace. When the start note itself is missing, EVERY note is unreachable,
|
|
333
|
+
* because there is nowhere to start from.
|
|
334
|
+
*
|
|
335
|
+
* @param params - The parameters for the walk.
|
|
336
|
+
* @returns The relative paths of the unreachable notes.
|
|
337
|
+
*/
|
|
338
|
+
findUnreachableNotes(params) {
|
|
339
|
+
const notesByRelativePath = new Map(this.collectNotes().map((note) => [note.relativePath, note]));
|
|
340
|
+
const reachedNotes = /* @__PURE__ */ new Set();
|
|
341
|
+
const pendingNotes = [params.startNote];
|
|
342
|
+
while (pendingNotes.length > 0) {
|
|
343
|
+
const notePath = (0, import_type_guards.ensureNonNullable)(pendingNotes.pop());
|
|
344
|
+
const note = notesByRelativePath.get(notePath);
|
|
345
|
+
if (!note || reachedNotes.has(notePath)) {
|
|
346
|
+
continue;
|
|
347
|
+
}
|
|
348
|
+
reachedNotes.add(notePath);
|
|
349
|
+
pendingNotes.push(...collectNoteLinkTargets(note));
|
|
350
|
+
}
|
|
351
|
+
return this.collectCheckableNotes().map((note) => note.relativePath).filter((notePath) => !reachedNotes.has(notePath));
|
|
352
|
+
}
|
|
353
|
+
/**
|
|
354
|
+
* Parses the names of the `export function`s (including `async` and generator declarations) in a source file.
|
|
355
|
+
*
|
|
356
|
+
* @param params - The parameters for the lookup.
|
|
357
|
+
* @returns The exported function names in source order.
|
|
358
|
+
*/
|
|
359
|
+
getExportedFunctionNames(params) {
|
|
360
|
+
const source = (0, import_node_fs.readFileSync)((0, import_path.join)(this.rootFolder, params.sourcePath), "utf-8");
|
|
361
|
+
return [...source.matchAll(/^export (?:async )?function\*? (?<name>\w+)/gm)].map((match) => (0, import_reg_exp.getMandatoryNamedGroup)(match, "name"));
|
|
362
|
+
}
|
|
363
|
+
/**
|
|
364
|
+
* Parses the members of an `export interface`, `export class`, or `export enum` declared in a source file.
|
|
365
|
+
*
|
|
366
|
+
* @param params - The parameters for the lookup.
|
|
367
|
+
* @returns The parsed {@link InterfaceMembers}.
|
|
368
|
+
* @throws When the interface, class, or enum cannot be found in the source file.
|
|
369
|
+
*/
|
|
370
|
+
getInterfaceMembers(params) {
|
|
371
|
+
const source = (0, import_node_fs.readFileSync)((0, import_path.join)(this.rootFolder, params.sourcePath), "utf-8");
|
|
372
|
+
const match = new RegExp(String.raw`export (?<keyword>interface|class|enum) ${params.interfaceName}\b[^{]*\{(?<body>[\s\S]*?)\n\}`).exec(source);
|
|
373
|
+
if (!match) {
|
|
374
|
+
throw new Error(`Could not find interface ${params.interfaceName}`);
|
|
375
|
+
}
|
|
376
|
+
return parseMembers((0, import_reg_exp.getMandatoryNamedGroup)(match, "keyword"), (0, import_reg_exp.getMandatoryNamedGroup)(match, "body"));
|
|
377
|
+
}
|
|
378
|
+
/**
|
|
379
|
+
* Reads and caches the demo corpus — every `*.md` note in the demo vault joined into one string.
|
|
380
|
+
*
|
|
381
|
+
* @returns The concatenated demo-note contents.
|
|
382
|
+
*/
|
|
383
|
+
readCorpus() {
|
|
384
|
+
this.cachedCorpus ??= this.collectNotes().map((note) => note.content).join("\n");
|
|
385
|
+
return this.cachedCorpus;
|
|
386
|
+
}
|
|
387
|
+
// The notes the authoring checks apply to: every note except the ones declared outside the learning
|
|
388
|
+
// path (the vault's own `README.md` by default).
|
|
389
|
+
collectCheckableNotes() {
|
|
390
|
+
return this.collectNotes().filter((note) => !this.excludedNotes.has(note.relativePath));
|
|
391
|
+
}
|
|
392
|
+
collectMarkdownFiles(folder) {
|
|
393
|
+
const result = [];
|
|
394
|
+
for (const entry of (0, import_node_fs.readdirSync)(folder, { withFileTypes: true })) {
|
|
395
|
+
if (entry.isDirectory()) {
|
|
396
|
+
if (entry.name === import_obsidian_plugin_repo_paths.ObsidianPluginRepoPaths.NodeModules) {
|
|
397
|
+
continue;
|
|
398
|
+
}
|
|
399
|
+
result.push(...this.collectMarkdownFiles((0, import_path.join)(folder, entry.name)));
|
|
400
|
+
} else if (entry.name.endsWith(".md")) {
|
|
401
|
+
result.push((0, import_path.join)(folder, entry.name));
|
|
402
|
+
}
|
|
403
|
+
}
|
|
404
|
+
return result;
|
|
405
|
+
}
|
|
406
|
+
}
|
|
407
|
+
function registerDemoVaultCoverageSuite(params) {
|
|
408
|
+
const checker = new DemoVaultCoverageChecker((0, import_object_utils.normalizeOptionalProperties)({
|
|
409
|
+
excludedNotes: params.authoring?.excludedNotes,
|
|
410
|
+
rootFolder: params.rootFolder
|
|
411
|
+
}));
|
|
412
|
+
const startNote = params.authoring?.startNote ?? DEFAULT_START_NOTE;
|
|
413
|
+
(0, import_vitest.describe)("demo-vault coverage", () => {
|
|
414
|
+
for (const spec of params.interfaces ?? []) {
|
|
415
|
+
(0, import_vitest.it)(`demonstrates every ${spec.interfaceName} ${spec.kind}`, () => {
|
|
416
|
+
const members = checker.getInterfaceMembers(spec);
|
|
417
|
+
const demonstrated = members[spec.kind];
|
|
418
|
+
(0, import_vitest.expect)(demonstrated.length).toBeGreaterThan(0);
|
|
419
|
+
(0, import_vitest.expect)(checker.findUndemonstratedMembers({ members: demonstrated, receiver: spec.receiver })).toEqual([]);
|
|
420
|
+
});
|
|
421
|
+
(0, import_vitest.it)(`references no ${spec.interfaceName} member that no longer exists`, () => {
|
|
422
|
+
const members = checker.getInterfaceMembers(spec);
|
|
423
|
+
(0, import_vitest.expect)(checker.findStaleReferences({ receiver: spec.receiver, validMembers: members.all })).toEqual([]);
|
|
424
|
+
});
|
|
425
|
+
}
|
|
426
|
+
for (const spec of params.configInterfaces ?? []) {
|
|
427
|
+
(0, import_vitest.it)(`demonstrates every ${spec.interfaceName} option`, () => {
|
|
428
|
+
const members = checker.getInterfaceMembers(spec);
|
|
429
|
+
(0, import_vitest.expect)(members.properties.length).toBeGreaterThan(0);
|
|
430
|
+
(0, import_vitest.expect)(checker.findUndemonstratedMembers({ members: members.properties })).toEqual([]);
|
|
431
|
+
});
|
|
432
|
+
}
|
|
433
|
+
for (const spec of params.functionModules ?? []) {
|
|
434
|
+
(0, import_vitest.it)(`demonstrates every exported function in ${spec.sourcePath}`, () => {
|
|
435
|
+
const functionNames = checker.getExportedFunctionNames(spec);
|
|
436
|
+
(0, import_vitest.expect)(functionNames.length).toBeGreaterThan(0);
|
|
437
|
+
(0, import_vitest.expect)(checker.findUndemonstratedMembers({ members: functionNames })).toEqual([]);
|
|
438
|
+
});
|
|
439
|
+
}
|
|
440
|
+
const docs = params.docs;
|
|
441
|
+
if (docs) {
|
|
442
|
+
(0, import_vitest.it)("links a demo note for every feature doc", () => {
|
|
443
|
+
(0, import_vitest.expect)(checker.findUnlinkedFeatureDocs({ docsFolder: docs.folder, nonFeatureDocs: docs.nonFeatureDocs })).toEqual([]);
|
|
444
|
+
});
|
|
445
|
+
}
|
|
446
|
+
(0, import_vitest.it)("opens every note with an H1", () => {
|
|
447
|
+
(0, import_vitest.expect)(checker.findNotesWithoutH1()).toEqual([]);
|
|
448
|
+
});
|
|
449
|
+
(0, import_vitest.it)("opens every note with a prose paragraph before its first code block", () => {
|
|
450
|
+
(0, import_vitest.expect)(checker.findNotesWithoutIntroProse()).toEqual([]);
|
|
451
|
+
});
|
|
452
|
+
(0, import_vitest.it)(`reaches every note from ${startNote}`, () => {
|
|
453
|
+
(0, import_vitest.expect)(checker.findUnreachableNotes({ startNote })).toEqual([]);
|
|
454
|
+
});
|
|
455
|
+
(0, import_vitest.it)("uses no wikilinks, which do not render on GitHub", () => {
|
|
456
|
+
(0, import_vitest.expect)(checker.findNotesWithWikilinks()).toEqual([]);
|
|
457
|
+
});
|
|
458
|
+
(0, import_vitest.it)("justifies every wikilink allowance, and declares none it no longer needs", () => {
|
|
459
|
+
(0, import_vitest.expect)(checker.findNotesWithUnjustifiedWikilinkAllowance()).toEqual([]);
|
|
460
|
+
});
|
|
461
|
+
(0, import_vitest.it)("carries no Docs link line, because the note is the docs", () => {
|
|
462
|
+
(0, import_vitest.expect)(checker.findNotesWithDocsLinks()).toEqual([]);
|
|
463
|
+
});
|
|
464
|
+
(0, import_vitest.it)("commits none of the app.json settings obsidian-dev-utils injects at release time", () => {
|
|
465
|
+
(0, import_vitest.expect)(checker.findCommittedAppJsonSettings()).toEqual([]);
|
|
466
|
+
});
|
|
467
|
+
(0, import_vitest.it)("reads a non-empty demo vault", () => {
|
|
468
|
+
(0, import_vitest.expect)(checker.collectDemoNoteRelativePaths().length).toBeGreaterThan(0);
|
|
469
|
+
});
|
|
470
|
+
const guard = params.nonTrivialGuard;
|
|
471
|
+
if (guard) {
|
|
472
|
+
(0, import_vitest.it)("keeps the reflected surface non-trivial", () => {
|
|
473
|
+
const members = checker.getInterfaceMembers(guard);
|
|
474
|
+
(0, import_vitest.expect)(members.all).toContain(guard.expectMember);
|
|
475
|
+
(0, import_vitest.expect)(checker.collectDemoNoteRelativePaths()).toContain(guard.expectDemoNote);
|
|
476
|
+
});
|
|
477
|
+
}
|
|
478
|
+
});
|
|
479
|
+
}
|
|
480
|
+
const CLASS_MEMBER_MODIFIERS = String.raw`(?:(?:public|private|protected|readonly|static|abstract|override)\s+)*`;
|
|
481
|
+
const ABSOLUTE_URL_REG_EXP = /^[a-z][\w+.-]*:/i;
|
|
482
|
+
const ARROW_REG_EXP = /^\s*=>/;
|
|
483
|
+
const FUNCTION_TYPE_PARAMETERS_REG_EXP = /^<[^>]*>\s*/;
|
|
484
|
+
const ANGLE_BRACKETS_REG_EXP = /^<|>$/g;
|
|
485
|
+
const CODE_FENCE_REG_EXP = /^\s*(?:```|~~~)/;
|
|
486
|
+
const DEFAULT_EXCLUDED_NOTES = ["README.md"];
|
|
487
|
+
const DEFAULT_START_NOTE = "00 Start.md";
|
|
488
|
+
const DOCS_LINK_REG_EXP = /^\s*\[Docs]\(/;
|
|
489
|
+
const FRONTMATTER_REG_EXP = /^---\r?\n[\s\S]*?\r?\n---[^\S\n]*\r?\n?/;
|
|
490
|
+
const H1_REG_EXP = /^# \S/;
|
|
491
|
+
const HEADING_REG_EXP = /^#{1,6} /;
|
|
492
|
+
const INLINE_CODE_REG_EXP = /`[^`\n]*`/g;
|
|
493
|
+
const MARKDOWN_LINK_REG_EXP = /\[[^\]]*]\((?<target>[^)]+)\)/g;
|
|
494
|
+
const DIRECTIVE_REG_EXP = /^\s*<!--\s*obsidian-dev-utils-(?<action>disable-next-line|disable|enable)\s+(?<rule>[\w-]+\/[\w-]+)(?:\s+--\s+(?<reason>.*?))?\s*-->\s*$/;
|
|
495
|
+
const DIRECTIVE_PROBE_REG_EXP = /<!--\s*obsidian-dev-utils-/;
|
|
496
|
+
const WIKILINK_RULE = "demo-vault-validation/no-wikilinks";
|
|
497
|
+
const WIKILINK_ALLOWANCE_REG_EXP = /^obsidian-dev-utils:[^\S\n]*\n(?:[^\S\n]+.*\n)*?[^\S\n]+demo-vault-validation:[^\S\n]*\n(?:[^\S\n]+.*\n)*?[^\S\n]+allow-wikilinks:(?<reason>.*)$/m;
|
|
498
|
+
const WIKILINK_REG_EXP = /\[\[[^\]]+]]/;
|
|
499
|
+
function applyWikilinkDirective(state, lineIndex, match) {
|
|
500
|
+
const action = (0, import_reg_exp.getMandatoryNamedGroup)(match, "action");
|
|
501
|
+
const rule = (0, import_reg_exp.getMandatoryNamedGroup)(match, "rule");
|
|
502
|
+
const reason = match.groups?.["reason"]?.trim() ?? "";
|
|
503
|
+
if (rule !== WIKILINK_RULE) {
|
|
504
|
+
state.problems.push(`an unknown rule "${rule}" on ${formatLineNumber(lineIndex)}`);
|
|
505
|
+
return;
|
|
506
|
+
}
|
|
507
|
+
if (action !== "enable" && reason === "") {
|
|
508
|
+
state.problems.push(`a directive with no reason on ${formatLineNumber(lineIndex)}`);
|
|
509
|
+
return;
|
|
510
|
+
}
|
|
511
|
+
if (action === "disable-next-line") {
|
|
512
|
+
state.pendingNextLineIndex = lineIndex;
|
|
513
|
+
return;
|
|
514
|
+
}
|
|
515
|
+
if (action === "disable") {
|
|
516
|
+
if (state.openRegion) {
|
|
517
|
+
state.problems.push(`a disable on ${formatLineNumber(lineIndex)} inside the region opened on ${formatLineNumber(state.openRegion.lineIndex)}`);
|
|
518
|
+
return;
|
|
519
|
+
}
|
|
520
|
+
state.openRegion = { isUsed: false, lineIndex };
|
|
521
|
+
return;
|
|
522
|
+
}
|
|
523
|
+
if (!state.openRegion) {
|
|
524
|
+
state.problems.push(`an enable on ${formatLineNumber(lineIndex)} with no region open`);
|
|
525
|
+
return;
|
|
526
|
+
}
|
|
527
|
+
if (!state.openRegion.isUsed) {
|
|
528
|
+
state.problems.push(`a region opened on ${formatLineNumber(state.openRegion.lineIndex)} covering no wikilink`);
|
|
529
|
+
}
|
|
530
|
+
state.openRegion = null;
|
|
531
|
+
}
|
|
532
|
+
function applyWikilinkScanLine(state, lineIndex, line) {
|
|
533
|
+
if (state.openRegion) {
|
|
534
|
+
state.allowedLineIndexes.add(lineIndex);
|
|
535
|
+
state.openRegion.isUsed ||= state.wikilinkLineIndexes.has(lineIndex);
|
|
536
|
+
return;
|
|
537
|
+
}
|
|
538
|
+
if (state.pendingNextLineIndex === null || line.trim() === "") {
|
|
539
|
+
return;
|
|
540
|
+
}
|
|
541
|
+
state.allowedLineIndexes.add(lineIndex);
|
|
542
|
+
if (!state.wikilinkLineIndexes.has(lineIndex)) {
|
|
543
|
+
state.problems.push(`a disable-next-line on ${formatLineNumber(state.pendingNextLineIndex)} covering no wikilink`);
|
|
544
|
+
}
|
|
545
|
+
state.pendingNextLineIndex = null;
|
|
546
|
+
}
|
|
547
|
+
function buildMembers(methods, properties) {
|
|
548
|
+
return {
|
|
549
|
+
all: [...methods, ...properties],
|
|
550
|
+
methods,
|
|
551
|
+
properties
|
|
552
|
+
};
|
|
553
|
+
}
|
|
554
|
+
function collectLinesOutsideFences(content) {
|
|
555
|
+
const noteLines = [];
|
|
556
|
+
let isInsideFence = false;
|
|
557
|
+
for (const [index, line] of content.split("\n").entries()) {
|
|
558
|
+
if (CODE_FENCE_REG_EXP.test(line)) {
|
|
559
|
+
isInsideFence = !isInsideFence;
|
|
560
|
+
continue;
|
|
561
|
+
}
|
|
562
|
+
if (!isInsideFence) {
|
|
563
|
+
noteLines.push({ index, line });
|
|
564
|
+
}
|
|
565
|
+
}
|
|
566
|
+
return noteLines;
|
|
567
|
+
}
|
|
568
|
+
function collectNoteLinkTargets(note) {
|
|
569
|
+
const targets = [];
|
|
570
|
+
for (const line of getLinesOutsideFences(note.content)) {
|
|
571
|
+
for (const match of stripInlineCode(line).matchAll(MARKDOWN_LINK_REG_EXP)) {
|
|
572
|
+
const target = (0, import_reg_exp.getMandatoryNamedGroup)(match, "target").replaceAll(ANGLE_BRACKETS_REG_EXP, "");
|
|
573
|
+
const [notePath = ""] = target.split("#", 1);
|
|
574
|
+
if (ABSOLUTE_URL_REG_EXP.test(notePath) || !notePath.toLowerCase().endsWith(".md")) {
|
|
575
|
+
continue;
|
|
576
|
+
}
|
|
577
|
+
targets.push((0, import_path.join)((0, import_path.dirname)(note.relativePath), tryDecodeUriComponent(notePath)));
|
|
578
|
+
}
|
|
579
|
+
}
|
|
580
|
+
return targets;
|
|
581
|
+
}
|
|
582
|
+
function extractClassMethodNames(classBody) {
|
|
583
|
+
return [...classBody.matchAll(new RegExp(String.raw`^ {2}(?<modifiers>${CLASS_MEMBER_MODIFIERS})(?<name>\w+)(?:<[^>]*>)?\(`, "gm"))].filter((match) => !isNonPublicMember((0, import_reg_exp.getMandatoryNamedGroup)(match, "modifiers"))).map((match) => (0, import_reg_exp.getMandatoryNamedGroup)(match, "name"));
|
|
584
|
+
}
|
|
585
|
+
function extractClassPropertyNames(classBody) {
|
|
586
|
+
return [...classBody.matchAll(new RegExp(String.raw`^ {2}(?<modifiers>${CLASS_MEMBER_MODIFIERS})(?<name>\w+)\s*\??\s*[:=]`, "gm"))].filter((match) => !isNonPublicMember((0, import_reg_exp.getMandatoryNamedGroup)(match, "modifiers"))).map((match) => (0, import_reg_exp.getMandatoryNamedGroup)(match, "name"));
|
|
587
|
+
}
|
|
588
|
+
function extractEnumMemberNames(enumBody) {
|
|
589
|
+
return [...enumBody.matchAll(/^ {2}(?<name>\w+)/gm)].map((match) => (0, import_reg_exp.getMandatoryNamedGroup)(match, "name"));
|
|
590
|
+
}
|
|
591
|
+
function extractMethodNames(interfaceBody) {
|
|
592
|
+
const methodSignatureNames = [...interfaceBody.matchAll(/^ {2}(?<name>\w+)(?:<[^>]*>)?\(/gm)].map((match) => (0, import_reg_exp.getMandatoryNamedGroup)(match, "name"));
|
|
593
|
+
const functionPropertyNames = matchPropertySignatures(interfaceBody).filter((match) => isFunctionType(interfaceBody, match)).map((match) => (0, import_reg_exp.getMandatoryNamedGroup)(match, "name"));
|
|
594
|
+
return [...methodSignatureNames, ...functionPropertyNames];
|
|
595
|
+
}
|
|
596
|
+
function extractPropertyNames(interfaceBody) {
|
|
597
|
+
return matchPropertySignatures(interfaceBody).filter((match) => !isFunctionType(interfaceBody, match)).map((match) => (0, import_reg_exp.getMandatoryNamedGroup)(match, "name"));
|
|
598
|
+
}
|
|
599
|
+
function findWikilinkLineIndexes(content) {
|
|
600
|
+
return collectLinesOutsideFences(content).filter((noteLine) => WIKILINK_REG_EXP.test(stripInlineCode(noteLine.line))).map((noteLine) => noteLine.index);
|
|
601
|
+
}
|
|
602
|
+
function formatLineNumber(lineIndex) {
|
|
603
|
+
return `line ${String(lineIndex + 1)}`;
|
|
604
|
+
}
|
|
605
|
+
function getLinesOutsideFences(content) {
|
|
606
|
+
return collectLinesOutsideFences(content).map((noteLine) => noteLine.line);
|
|
607
|
+
}
|
|
608
|
+
function hasH1(content) {
|
|
609
|
+
for (const line of stripFrontmatter(content).split("\n")) {
|
|
610
|
+
const trimmedLine = line.trim();
|
|
611
|
+
if (trimmedLine === "") {
|
|
612
|
+
continue;
|
|
613
|
+
}
|
|
614
|
+
return H1_REG_EXP.test(trimmedLine);
|
|
615
|
+
}
|
|
616
|
+
return false;
|
|
617
|
+
}
|
|
618
|
+
function hasIntroProse(content) {
|
|
619
|
+
for (const line of stripFrontmatter(content).split("\n")) {
|
|
620
|
+
if (CODE_FENCE_REG_EXP.test(line)) {
|
|
621
|
+
return false;
|
|
622
|
+
}
|
|
623
|
+
const trimmedLine = line.trim();
|
|
624
|
+
if (trimmedLine === "" || HEADING_REG_EXP.test(trimmedLine)) {
|
|
625
|
+
continue;
|
|
626
|
+
}
|
|
627
|
+
return true;
|
|
628
|
+
}
|
|
629
|
+
return false;
|
|
630
|
+
}
|
|
631
|
+
function hasWikilink(content) {
|
|
632
|
+
return findWikilinkLineIndexes(content).length > 0;
|
|
633
|
+
}
|
|
634
|
+
function isFunctionType(interfaceBody, match) {
|
|
635
|
+
let index = match.index + match[0].length;
|
|
636
|
+
index += FUNCTION_TYPE_PARAMETERS_REG_EXP.exec(interfaceBody.slice(index))?.[0].length ?? 0;
|
|
637
|
+
if (interfaceBody[index] !== "(") {
|
|
638
|
+
return false;
|
|
639
|
+
}
|
|
640
|
+
let depth = 0;
|
|
641
|
+
for (; index < interfaceBody.length; index++) {
|
|
642
|
+
const character = interfaceBody[index];
|
|
643
|
+
if (character === "(") {
|
|
644
|
+
depth++;
|
|
645
|
+
} else if (character === ")") {
|
|
646
|
+
depth--;
|
|
647
|
+
if (depth === 0) {
|
|
648
|
+
return ARROW_REG_EXP.test(interfaceBody.slice(index + 1));
|
|
649
|
+
}
|
|
650
|
+
}
|
|
651
|
+
}
|
|
652
|
+
return false;
|
|
653
|
+
}
|
|
654
|
+
function isNonPublicMember(modifiers) {
|
|
655
|
+
return /\b(?:private|protected)\b/.test(modifiers);
|
|
656
|
+
}
|
|
657
|
+
function matchPropertySignatures(interfaceBody) {
|
|
658
|
+
return [...interfaceBody.matchAll(/^ {2}(?:readonly\s+)?(?<name>\w+)\??:\s*/gm)];
|
|
659
|
+
}
|
|
660
|
+
function parseMembers(keyword, body) {
|
|
661
|
+
switch (keyword) {
|
|
662
|
+
case "class": {
|
|
663
|
+
return buildMembers(extractClassMethodNames(body), extractClassPropertyNames(body));
|
|
664
|
+
}
|
|
665
|
+
case "enum": {
|
|
666
|
+
return buildMembers([], extractEnumMemberNames(body));
|
|
667
|
+
}
|
|
668
|
+
default: {
|
|
669
|
+
return buildMembers(extractMethodNames(body), extractPropertyNames(body));
|
|
670
|
+
}
|
|
671
|
+
}
|
|
672
|
+
}
|
|
673
|
+
function readWikilinkAllowanceReason(content) {
|
|
674
|
+
const frontmatter = FRONTMATTER_REG_EXP.exec(content)?.[0];
|
|
675
|
+
if (frontmatter === void 0) {
|
|
676
|
+
return null;
|
|
677
|
+
}
|
|
678
|
+
const reason = WIKILINK_ALLOWANCE_REG_EXP.exec(frontmatter)?.groups?.["reason"];
|
|
679
|
+
return reason === void 0 ? null : reason.trim().replace(/^(?<quote>["'])(?<value>[\s\S]*)\k<quote>$/, "$<value>");
|
|
680
|
+
}
|
|
681
|
+
function scanWikilinkDirectives(content) {
|
|
682
|
+
const state = {
|
|
683
|
+
allowedLineIndexes: /* @__PURE__ */ new Set(),
|
|
684
|
+
openRegion: null,
|
|
685
|
+
pendingNextLineIndex: null,
|
|
686
|
+
problems: [],
|
|
687
|
+
wikilinkLineIndexes: new Set(findWikilinkLineIndexes(content))
|
|
688
|
+
};
|
|
689
|
+
for (const { index, line } of collectLinesOutsideFences(content)) {
|
|
690
|
+
const match = DIRECTIVE_REG_EXP.exec(line);
|
|
691
|
+
if (match) {
|
|
692
|
+
applyWikilinkDirective(state, index, match);
|
|
693
|
+
} else if (DIRECTIVE_PROBE_REG_EXP.test(line)) {
|
|
694
|
+
state.problems.push(`a malformed directive on ${formatLineNumber(index)}`);
|
|
695
|
+
} else {
|
|
696
|
+
applyWikilinkScanLine(state, index, line);
|
|
697
|
+
}
|
|
698
|
+
}
|
|
699
|
+
if (state.openRegion) {
|
|
700
|
+
state.problems.push(`a region opened on ${formatLineNumber(state.openRegion.lineIndex)} that is never enabled again`);
|
|
701
|
+
}
|
|
702
|
+
if (state.pendingNextLineIndex !== null) {
|
|
703
|
+
state.problems.push(`a disable-next-line on ${formatLineNumber(state.pendingNextLineIndex)} covering no wikilink`);
|
|
704
|
+
}
|
|
705
|
+
return { allowedLineIndexes: state.allowedLineIndexes, problems: state.problems };
|
|
706
|
+
}
|
|
707
|
+
function stripFrontmatter(content) {
|
|
708
|
+
return content.replace(FRONTMATTER_REG_EXP, "");
|
|
709
|
+
}
|
|
710
|
+
function stripInlineCode(line) {
|
|
711
|
+
return line.replaceAll(INLINE_CODE_REG_EXP, "");
|
|
712
|
+
}
|
|
713
|
+
function tryDecodeUriComponent(value) {
|
|
714
|
+
try {
|
|
715
|
+
return decodeURIComponent(value);
|
|
716
|
+
} catch {
|
|
717
|
+
return value;
|
|
718
|
+
}
|
|
719
|
+
}
|
|
720
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
721
|
+
0 && (module.exports = {
|
|
722
|
+
DemoVaultCoverageChecker,
|
|
723
|
+
registerDemoVaultCoverageSuite
|
|
724
|
+
});
|
|
725
|
+
//# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsiLi4vLi4vLi4vc3JjL2RlbW8tdmF1bHQtY292ZXJhZ2UudHMiXSwKICAic291cmNlc0NvbnRlbnQiOiBbIi8qKlxuICogQGZpbGVcbiAqXG4gKiBTdGF0aWMgY292ZXJhZ2UvZnJlc2huZXNzIGNoZWNrcyB0aGF0IGtlZXAgYSBwbHVnaW4ncyBpbi1yZXBvIGBkZW1vLXZhdWx0L2AgaW4gc3luYyB3aXRoIGl0cyBwdWJsaWMgc3VyZmFjZS5cbiAqXG4gKiBBIHBsdWdpbiBjYW4gc2hpcCBhIGN1cmF0ZWQgZGVtbyB2YXVsdCBhdCBgZGVtby12YXVsdC9gIGluIGl0cyByZXBvIHJvb3QuIFRoZXNlIGhlbHBlcnMgcmVmbGVjdCB0aGUgcmVhbFxuICogcHVibGljIEFQSS9jb25maWcvZG9jcyBzdHJhaWdodCBmcm9tIHNvdXJjZSBhbmQgYXNzZXJ0IFx1MjAxNCBXSVRIT1VUIGxhdW5jaGluZyBPYnNpZGlhbiBcdTIwMTQgdGhhdCBldmVyeSBmZWF0dXJlIGlzXG4gKiBkZW1vbnN0cmF0ZWQgaW4gdGhlIG5vdGVzIGFuZCB0aGF0IHRoZSBub3RlcyByZWZlcmVuY2Ugbm8gQVBJIG1lbWJlciB0aGF0IG5vIGxvbmdlciBleGlzdHMgKHJlbmFtZSBkcmlmdCkuXG4gKiBUaGUgcnVudGltZSBiZWhhdmlvciBvZiB0aGUgcGx1Z2luIGlzIGNvdmVyZWQgYnkgaXRzIG90aGVyIGludGVncmF0aW9uIHRlc3RzLCBub3QgYnkgdGhlIGRlbW8gdmF1bHQ7IHRoZVxuICogdmF1bHQgaXMgYSBsZWFybmluZyByZXNvdXJjZSwgYW5kIHRoZXNlIGNoZWNrcyBvbmx5IGd1YXJkIHRoYXQgaXQgc3RheXMgdHJ1dGhmdWwuXG4gKlxuICogVGhleSBhbHNvIGd1YXJkIHRoZSB2YXVsdCdzIG93biBgLm9ic2lkaWFuL2FwcC5qc29uYDogdGhlIHNldHRpbmdzIGxpc3RlZCBpblxuICoge0BsaW5rIERFTU9fVkFVTFRfQVBQX0pTT05fU0VUVElOR1N9IGJlbG9uZyB0byBgb2JzaWRpYW4tZGV2LXV0aWxzYCwgd2hpY2ggd3JpdGVzIHRoZW0gaW50byB0aGUgYXJjaGl2ZWRcbiAqIHZhdWx0IGF0IHJlbGVhc2UgdGltZSwgc28gYSB2YXVsdCB0aGF0IGNvbW1pdHMgYW55IG9mIHRoZW0gaXMga2VlcGluZyBhIHNlY29uZCBjb3B5IG5vdGhpbmcgcmVjb25jaWxlcy5cbiAqXG4gKiBUaGV5IGFsc28gZW5mb3JjZSB0aGUgZGVtby12YXVsdCBBVVRIT1JJTkcgY29udmVudGlvbiBcdTIwMTQgZXZlcnkgbm90ZSBvcGVucyB3aXRoIGFuIGAjIEgxYCBhbmQgYSBwbGFpblxuICogcHJvc2UgcGFyYWdyYXBoLCBldmVyeSBub3RlIGlzIHJlYWNoYWJsZSBmcm9tIHRoZSBzdGFydCBub3RlLCBhbmQgbm8gbm90ZSB1c2VzIGEgYFtbd2lraWxpbmtdXWAgb3IgYVxuICogYFtEb2NzXShcdTIwMjYpYCBsaW5lLiBUaGVzZSBjaGVja3MgYXJlIHVuY29uZGl0aW9uYWw6IHRoZSBkZW1vIHZhdWx0IGlzIHRoZSBwdWJsaXNoZWQgZG9jdW1lbnRhdGlvbiwgcmVhZFxuICogaW4gT2JzaWRpYW4gQU5EIG9uIEdpdEh1YiAod2hlcmUgYSB3aWtpbGluayBkb2VzIG5vdCByZW5kZXIpLCBzbyBhIG5vdGUgdGhhdCBicmVha3MgdGhlIGNvbnZlbnRpb24gaXNcbiAqIGJyb2tlbiBmb3IgcmVhbCByZWFkZXJzLiBgYXV0aG9yaW5nYCBvbmx5IHR1bmVzIHRoZW0gKHdoaWNoIG5vdGUgaXMgdGhlIHN0YXJ0LCB3aGljaCBub3RlcyBzaXQgb3V0c2lkZVxuICogdGhlIGxlYXJuaW5nIHBhdGgpOyBpdCBjYW5ub3Qgc3dpdGNoIHRoZW0gb2ZmLlxuICpcbiAqIE9ubHkgYHJvb3RGb2xkZXJgIGlzIHJlcXVpcmVkLCBzbyBhIHBsdWdpbiB3aXRoIG5vIHNldHRpbmdzIGFuZCBubyBwdWJsaWMgQVBJIHRvIHJlZmxlY3QgcmVnaXN0ZXJzIHRoZVxuICogc3VpdGUgd2l0aCB0aGF0IGFsb25lIGFuZCBzdGlsbCBnZXRzIGV2ZXJ5IGF1dGhvcmluZyBjaGVjayBcdTIwMTQgdGhlIGNoZWNrcyBoYXZlIG5vdGhpbmcgdG8gZG8gd2l0aCB3aGF0IHRoZVxuICogcGx1Z2luIGV4cG9zZXMuIEVhY2ggcmVmbGVjdGlvbiBzcGVjIChgY29uZmlnSW50ZXJmYWNlc2AsIGBpbnRlcmZhY2VzYCwgYG5vblRyaXZpYWxHdWFyZGApIGFkZHMgdGhlIGNoZWNrc1xuICogaXQgZGVzY3JpYmVzIHdoZW4gc3VwcGxpZWQuIFRoZSB2YXVsdCBpcyBndWFyZGVkIGFnYWluc3QgYmVpbmcgZW1wdHkgZWl0aGVyIHdheTogd2l0aCBubyBub3RlcyB0byByZWFkLFxuICogZXZlcnkgYXV0aG9yaW5nIGNoZWNrIHdvdWxkIHBhc3MgYnkgaGF2aW5nIG5vdGhpbmcgdG8gbG9vayBhdC5cbiAqXG4gKiBUaGUgb25lIGV4Y2VwdGlvbiBpcyBhIG5vdGUgd2hvc2UgU1VCSkVDVCBpcyB0aGUgd2lraWxpbmsgXHUyMDE0IGFuIGVtYmVkIHNwZWxsaW5nIHRoZSByZWFkZXIgaXMgYmVpbmcgdGF1Z2h0XG4gKiB0byB0eXBlLCBhIGZyb250bWF0dGVyIHByb3BlcnR5IHZhbHVlIHRoYXQgZXhpc3RzIHRvIGNvbnRyYXN0IHdpdGggYSBNYXJrZG93biBsaW5rLCBhIGZpeHR1cmUgdGhhdCBtdXN0XG4gKiBrZWVwIHRoZSB3aWtpbGluayBhIGNvbW1hbmQgaXMgc3VwcG9zZWQgdG8gbGVhdmUgYWxvbmUsIGEgbGluayB0aGUgcmVhZGVyIGNsaWNrcyB3aGlsZSBpdCBzdGlsbCByZXNvbHZlc1xuICogdG8gbm90aGluZy4gU3VjaCBhIG5vdGUgc2F5cyBzbyBpdHNlbGYsIHN0YXRpbmcgd2h5LCBpbiBvbmUgb2YgdHdvIGZvcm1zIG1vZGVsbGVkIG9uIEVTTGludCdzLlxuICpcbiAqIFBlciBsaW5lIG9yIHBlciByZWdpb24sIHdyaXR0ZW4gYXMgYW4gSFRNTCBjb21tZW50IHNvIGl0IGlzIGludmlzaWJsZSBpbiBPYnNpZGlhbiBBTkQgb24gR2l0SHViIFx1MjAxNCB0aGVcbiAqIHNwZWxsaW5nIHRoZXNlIHZhdWx0cyBhbHJlYWR5IHVzZSBmb3IgYG1hcmtkb3dubGludC1kaXNhYmxlLW5leHQtbGluZWA6XG4gKlxuICogYGBgbWFya2Rvd25cbiAqIDwhLS0gb2JzaWRpYW4tZGV2LXV0aWxzLWRpc2FibGUtbmV4dC1saW5lIGRlbW8tdmF1bHQtdmFsaWRhdGlvbi9uby13aWtpbGlua3MgLS0gQ2xpY2tpbmcgYSBsaW5rIHRvIGEgbm90ZSB0aGF0IGRvZXMgbm90IGV4aXN0IHlldCBJUyB0aGUgZmVhdHVyZS4gLS0+XG4gKiAyLiBDbGljayB0aGlzIGxpbms6IFtbUHJvamVjdHMvRnJlc2ggaWRlYV1dLlxuICpcbiAqIDwhLS0gb2JzaWRpYW4tZGV2LXV0aWxzLWRpc2FibGUgZGVtby12YXVsdC12YWxpZGF0aW9uL25vLXdpa2lsaW5rcyAtLSBUaGUgd2lraWxpbmsgZW1iZWQgaXMgdGhlIHN5bnRheCB0aGlzIG5vdGUgdGVhY2hlcy4gLS0+XG4gKiAhW1tiYXNpYy5odG1sfDQwMF1dXG4gKiA8IS0tIG9ic2lkaWFuLWRldi11dGlscy1lbmFibGUgZGVtby12YXVsdC12YWxpZGF0aW9uL25vLXdpa2lsaW5rcyAtLT5cbiAqIGBgYFxuICpcbiAqIFBlciBub3RlLCBpbiB0aGUgbm90ZSdzIG93biBmcm9udG1hdHRlciBcdTIwMTQgdGhlIG9ubHkgZm9ybSB0aGF0IGNhbiByZWFjaCBhIHdpa2lsaW5rIElOU0lERSBmcm9udG1hdHRlcixcbiAqIHdoZXJlIGEgY29tbWVudCBjYW5ub3QgZ286XG4gKlxuICogYGBgeWFtbFxuICogLS0tXG4gKiBvYnNpZGlhbi1kZXYtdXRpbHM6XG4gKiAgIGRlbW8tdmF1bHQtdmFsaWRhdGlvbjpcbiAqICAgICBhbGxvdy13aWtpbGlua3M6IFRoZSBgd2lraWxpbmtgIHByb3BlcnR5IHZhbHVlIGlzIHRoZSBjb250cmFzdCB0aGlzIG5vdGUgaXMgYnVpbHQgYXJvdW5kLlxuICogLS0tXG4gKiBgYGBcbiAqXG4gKiBFaXRoZXIgd2F5IHRoZSBkZWNsYXJhdGlvbiB0cmF2ZWxzIHdpdGggdGhlIG5vdGUgcmF0aGVyIHRoYW4gc2l0dGluZyBpbiBhIGxpc3Qgc29tZXdoZXJlIGVsc2UsIGl0IGNhcnJpZXNcbiAqIGl0cyBqdXN0aWZpY2F0aW9uLCBhbmQgaXQgZXhlbXB0cyBvbmx5IHRoZSBXSUtJTElOSyBjaGVjayBcdTIwMTQgdGhlIEgxLCBwcm9zZSwgcmVhY2hhYmlsaXR5IGFuZCBgW0RvY3NdYFxuICogY2hlY2tzIHN0aWxsIGFwcGx5LiBBIGRlY2xhcmF0aW9uIHdpdGggbm8gcmVhc29uLCBvbmUgY292ZXJpbmcgbm8gd2lraWxpbmssIGEgcmVnaW9uIG5ldmVyIGVuYWJsZWQgYWdhaW4sXG4gKiBvciBhIG1pc3NwZWxsZWQgZGlyZWN0aXZlIGFsbCBmYWlsOiBhbiBleGVtcHRpb24gbm9ib2R5IGNhbiBqdXN0aWZ5LCB0aGF0IG5vdGhpbmcgbmVlZHMgYW55IG1vcmUsIG9yIHRoYXRcbiAqIHNpbGVudGx5IGRvZXMgbm90aGluZyBpcyB3b3JzZSB0aGFuIG5vIGV4ZW1wdGlvbiBhdCBhbGwuXG4gKlxuICogVHdvIGxheWVycyBhcmUgZXhwb3NlZDpcbiAqIC0ge0BsaW5rIERlbW9WYXVsdENvdmVyYWdlQ2hlY2tlcn0gXHUyMDE0IGEgZnJhbWV3b3JrLWFnbm9zdGljIGNvcmUgdGhhdCByZWFkcyB0aGUgY29ycHVzLCBwYXJzZXMgaW50ZXJmYWNlIC9cbiAqICAgY2xhc3MgLyBlbnVtIG1lbWJlcnMgYW5kIGV4cG9ydGVkIGZ1bmN0aW9ucywgYW5kIHJldHVybnMgZGlhZ25vc3RpYyBhcnJheXMgKHdoYXQgaXMgdW5kZW1vbnN0cmF0ZWQgLyBzdGFsZVxuICogICAvIHVubGlua2VkIC8gb2ZmLWNvbnZlbnRpb24pLlxuICogLSB7QGxpbmsgcmVnaXN0ZXJEZW1vVmF1bHRDb3ZlcmFnZVN1aXRlfSBcdTIwMTQgYSB0aGluIHdyYXBwZXIgdGhhdCByZWdpc3RlcnMgYSBgdml0ZXN0YCBzdWl0ZSBvdmVyIHRoZSBjb3JlLCBzb1xuICogICBhIHBsdWdpbidzIGBkZW1vLXZhdWx0Lm5vLWFwcC5pbnRlZ3JhdGlvbi50ZXN0LnRzYCBpcyBhIHNpbmdsZSBkZWNsYXJhdGl2ZSBjYWxsLlxuICovXG5cbmltcG9ydCB7IG5vcm1hbGl6ZU9wdGlvbmFsUHJvcGVydGllcyB9IGZyb20gJ0BtbmFvdW1vdi90eXBlc2NyaXB0LWxpYi9vYmplY3QtdXRpbHMnO1xuaW1wb3J0IHtcbiAgZGlybmFtZSxcbiAgam9pbixcbiAgcmVsYXRpdmVcbn0gZnJvbSAnQG1uYW91bW92L3R5cGVzY3JpcHQtbGliL3BhdGgnO1xuaW1wb3J0IHsgZ2V0TWFuZGF0b3J5TmFtZWRHcm91cCB9IGZyb20gJ0BtbmFvdW1vdi90eXBlc2NyaXB0LWxpYi9yZWctZXhwJztcbmltcG9ydCB7IGVuc3VyZU5vbk51bGxhYmxlIH0gZnJvbSAnQG1uYW91bW92L3R5cGVzY3JpcHQtbGliL3R5cGUtZ3VhcmRzJztcbmltcG9ydCB7XG4gIGV4aXN0c1N5bmMsXG4gIHJlYWRkaXJTeW5jLFxuICByZWFkRmlsZVN5bmNcbn0gZnJvbSAnbm9kZTpmcyc7XG5pbXBvcnQge1xuICBkZXNjcmliZSxcbiAgZXhwZWN0LFxuICBpdFxufSBmcm9tICd2aXRlc3QnO1xuXG5pbXBvcnQge1xuICBmaW5kT3duZWREZW1vVmF1bHRBcHBKc29uU2V0dGluZ3MsXG4gIHBhcnNlRGVtb1ZhdWx0QXBwSnNvblxufSBmcm9tICcuL2RlbW8tdmF1bHQtYXBwLWpzb24udHMnO1xuaW1wb3J0IHsgT2JzaWRpYW5QbHVnaW5SZXBvUGF0aHMgfSBmcm9tICcuL29ic2lkaWFuLXBsdWdpbi1yZXBvLXBhdGhzLnRzJztcblxuLyoqXG4gKiBUdW5lcyB0aGUgYWx3YXlzLW9uIGF1dGhvcmluZyBjaGVja3MuIEl0IGNhbm5vdCBkaXNhYmxlIHRoZW0gXHUyMDE0IHNlZSB0aGUgZmlsZSBvdmVydmlldy5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBEZW1vVmF1bHRBdXRob3JpbmdTcGVjIHtcbiAgLyoqXG4gICAqIFRoZSBub3RlcyAocGF0aHMgcmVsYXRpdmUgdG8gdGhlIGRlbW8gdmF1bHQpIHRoYXQgc2l0IG91dHNpZGUgdGhlIGxlYXJuaW5nIHBhdGggYW5kIGFyZSB0aGVyZWZvcmVcbiAgICogZXhlbXB0IGZyb20gZXZlcnkgYXV0aG9yaW5nIGNoZWNrLiBEZWZhdWx0cyB0byB0aGUgdmF1bHQncyBvd24gYFJFQURNRS5tZGAsIHdoaWNoIGFkZHJlc3NlcyBzb21lb25lXG4gICAqIGJyb3dzaW5nIHRoZSByZXBvIG9uIEdpdEh1YiByYXRoZXIgdGhhbiBhIHJlYWRlciB3b3JraW5nIHRocm91Z2ggdGhlIHZhdWx0LlxuICAgKi9cbiAgcmVhZG9ubHkgZXhjbHVkZWROb3Rlcz86IHN0cmluZ1tdO1xuXG4gIC8qKlxuICAgKiBUaGUgbm90ZSAocGF0aCByZWxhdGl2ZSB0byB0aGUgZGVtbyB2YXVsdCkgZXZlcnkgb3RoZXIgbm90ZSBtdXN0IGJlIHJlYWNoYWJsZSBmcm9tLiBEZWZhdWx0cyB0b1xuICAgKiBgMDAgU3RhcnQubWRgLlxuICAgKi9cbiAgcmVhZG9ubHkgc3RhcnROb3RlPzogc3RyaW5nO1xufVxuXG4vKipcbiAqIFJlZmxlY3RzIGEgY29uZmlnIGludGVyZmFjZSB3aG9zZSBvcHRpb25zIGFyZSBkZW1vbnN0cmF0ZWQgYnkgdGhlaXIgYmFyZSBuYW1lLlxuICovXG5leHBvcnQgaW50ZXJmYWNlIERlbW9WYXVsdENvbmZpZ0ludGVyZmFjZUNvdmVyYWdlU3BlYyB7XG4gIC8qKlxuICAgKiBUaGUgbmFtZSBvZiB0aGUgYGV4cG9ydCBpbnRlcmZhY2VgLCBgZXhwb3J0IGNsYXNzYCwgb3IgYGV4cG9ydCBlbnVtYCB3aG9zZSBwcm9wZXJ0aWVzIGFyZSB0aGUgY29uZmlnXG4gICAqIG9wdGlvbnMuXG4gICAqL1xuICByZWFkb25seSBpbnRlcmZhY2VOYW1lOiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIFRoZSBzb3VyY2UgZmlsZSBwYXRoIChyZWxhdGl2ZSB0byB0aGUgcmVwbyByb290KSB0aGF0IGRlY2xhcmVzIHRoZSBpbnRlcmZhY2UsIGNsYXNzLCBvciBlbnVtLlxuICAgKi9cbiAgcmVhZG9ubHkgc291cmNlUGF0aDogc3RyaW5nO1xufVxuXG4vKipcbiAqIFRoZSBwYXJhbWV0ZXJzIGZvciB0aGUge0BsaW5rIERlbW9WYXVsdENvdmVyYWdlQ2hlY2tlcn0gY29uc3RydWN0b3IuXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgRGVtb1ZhdWx0Q292ZXJhZ2VDaGVja2VyQ29uc3RydWN0b3JQYXJhbXMge1xuICAvKipcbiAgICogVGhlIG5vdGVzIChwYXRocyByZWxhdGl2ZSB0byB0aGUgZGVtbyB2YXVsdCkgZXhlbXB0IGZyb20gdGhlIGF1dGhvcmluZyBjaGVja3MuIERlZmF1bHRzIHRvIHRoZVxuICAgKiB2YXVsdCdzIG93biBgUkVBRE1FLm1kYC5cbiAgICovXG4gIHJlYWRvbmx5IGV4Y2x1ZGVkTm90ZXM/OiBzdHJpbmdbXTtcblxuICAvKipcbiAgICogVGhlIGFic29sdXRlIHBhdGggb2YgdGhlIHBsdWdpbiByZXBvIHJvb3QgXHUyMDE0IHRoZSBmb2xkZXIgY29udGFpbmluZyBgZGVtby12YXVsdC9gIGFuZCB0aGUgc291cmNlIGJlaW5nXG4gICAqIHJlZmxlY3RlZC4gQ2FsbGVycyB0eXBpY2FsbHkgcGFzcyBgZ2V0Um9vdEZvbGRlcigpID8/IHByb2Nlc3MuY3dkKClgLlxuICAgKi9cbiAgcmVhZG9ubHkgcm9vdEZvbGRlcjogc3RyaW5nO1xufVxuXG4vKipcbiAqIFRoZSBwYXJhbWV0ZXJzIGZvciB7QGxpbmsgRGVtb1ZhdWx0Q292ZXJhZ2VDaGVja2VyLmZpbmRTdGFsZVJlZmVyZW5jZXN9LlxuICovXG5leHBvcnQgaW50ZXJmYWNlIERlbW9WYXVsdENvdmVyYWdlQ2hlY2tlckZpbmRTdGFsZVJlZmVyZW5jZXNQYXJhbXMge1xuICAvKipcbiAgICogVGhlIHJlY2VpdmVyIHdob3NlIGBgIGAke3JlY2VpdmVyfS48bWVtYmVyPmAgYGAgcmVmZXJlbmNlcyBhcmUgc2Nhbm5lZCBmb3IgaW4gdGhlIGRlbW8gY29ycHVzLlxuICAgKi9cbiAgcmVhZG9ubHkgcmVjZWl2ZXI6IHN0cmluZztcblxuICAvKipcbiAgICogVGhlIG1lbWJlcnMgdGhhdCBjdXJyZW50bHkgZXhpc3Qgb24gdGhlIHJlY2VpdmVyOyBhbnkgcmVmZXJlbmNlZCBtZW1iZXIgbm90IGluIHRoaXMgc2V0IGlzIHN0YWxlLlxuICAgKi9cbiAgcmVhZG9ubHkgdmFsaWRNZW1iZXJzOiBzdHJpbmdbXTtcbn1cblxuLyoqXG4gKiBUaGUgcGFyYW1ldGVycyBmb3Ige0BsaW5rIERlbW9WYXVsdENvdmVyYWdlQ2hlY2tlci5maW5kVW5kZW1vbnN0cmF0ZWRNZW1iZXJzfS5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBEZW1vVmF1bHRDb3ZlcmFnZUNoZWNrZXJGaW5kVW5kZW1vbnN0cmF0ZWRNZW1iZXJzUGFyYW1zIHtcbiAgLyoqXG4gICAqIFRoZSBtZW1iZXIgbmFtZXMgdGhhdCBtdXN0IGVhY2ggYXBwZWFyIGluIHRoZSBkZW1vIGNvcnB1cy5cbiAgICovXG4gIHJlYWRvbmx5IG1lbWJlcnM6IHN0cmluZ1tdO1xuXG4gIC8qKlxuICAgKiBXaGVuIHNldCwgYSBtZW1iZXIgaXMgZGVtb25zdHJhdGVkIG9ubHkgaWYgYGAgYCR7cmVjZWl2ZXJ9LiR7bWVtYmVyfWAgYGAgYXBwZWFycyAoZS5nLiBhIGNvbnRleHQgb2JqZWN0J3NcbiAgICogbWV0aG9kcyk7IHdoZW4gYWJzZW50LCB0aGUgYmFyZSBtZW1iZXIgbmFtZSBpcyBsb29rZWQgdXAgKGUuZy4gYSBjb25maWcgb3B0aW9uKS5cbiAgICovXG4gIHJlYWRvbmx5IHJlY2VpdmVyPzogc3RyaW5nO1xufVxuXG4vKipcbiAqIFRoZSBwYXJhbWV0ZXJzIGZvciB7QGxpbmsgRGVtb1ZhdWx0Q292ZXJhZ2VDaGVja2VyLmZpbmRVbmxpbmtlZEZlYXR1cmVEb2NzfS5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBEZW1vVmF1bHRDb3ZlcmFnZUNoZWNrZXJGaW5kVW5saW5rZWRGZWF0dXJlRG9jc1BhcmFtcyB7XG4gIC8qKlxuICAgKiBUaGUgZG9jcyBmb2xkZXIgKHJlbGF0aXZlIHRvIHRoZSByZXBvIHJvb3QpIHdob3NlIHRvcC1sZXZlbCBgKi5tZGAgZmlsZXMgYXJlIHRoZSBmZWF0dXJlIGRvY3MuXG4gICAqL1xuICByZWFkb25seSBkb2NzRm9sZGVyOiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIFRoZSBkb2MgYmFzZW5hbWVzICh3aXRob3V0IGAubWRgKSB0aGF0IGFyZSBOT1QgcGVyLWZlYXR1cmUgcGFnZXMgYW5kIHNvIG5lZWQgbm8gbGlua2luZyBkZW1vIG5vdGUuXG4gICAqL1xuICByZWFkb25seSBub25GZWF0dXJlRG9jczogc3RyaW5nW107XG59XG5cbi8qKlxuICogVGhlIHBhcmFtZXRlcnMgZm9yIHtAbGluayBEZW1vVmF1bHRDb3ZlcmFnZUNoZWNrZXIuZmluZFVucmVhY2hhYmxlTm90ZXN9LlxuICovXG5leHBvcnQgaW50ZXJmYWNlIERlbW9WYXVsdENvdmVyYWdlQ2hlY2tlckZpbmRVbnJlYWNoYWJsZU5vdGVzUGFyYW1zIHtcbiAgLyoqXG4gICAqIFRoZSBub3RlIChwYXRoIHJlbGF0aXZlIHRvIHRoZSBkZW1vIHZhdWx0KSB0aGUgd2FsayBzdGFydHMgZnJvbSwgZS5nLiBgMDAgU3RhcnQubWRgLlxuICAgKi9cbiAgcmVhZG9ubHkgc3RhcnROb3RlOiBzdHJpbmc7XG59XG5cbi8qKlxuICogVGhlIHBhcmFtZXRlcnMgZm9yIHtAbGluayBEZW1vVmF1bHRDb3ZlcmFnZUNoZWNrZXIuZ2V0RXhwb3J0ZWRGdW5jdGlvbk5hbWVzfS5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBEZW1vVmF1bHRDb3ZlcmFnZUNoZWNrZXJHZXRFeHBvcnRlZEZ1bmN0aW9uTmFtZXNQYXJhbXMge1xuICAvKipcbiAgICogVGhlIHNvdXJjZSBmaWxlIHBhdGggKHJlbGF0aXZlIHRvIHRoZSByZXBvIHJvb3QpIHdob3NlIGBleHBvcnQgZnVuY3Rpb25gcyBhcmUgcGFyc2VkLlxuICAgKi9cbiAgcmVhZG9ubHkgc291cmNlUGF0aDogc3RyaW5nO1xufVxuXG4vKipcbiAqIFRoZSBwYXJhbWV0ZXJzIGZvciB7QGxpbmsgRGVtb1ZhdWx0Q292ZXJhZ2VDaGVja2VyLmdldEludGVyZmFjZU1lbWJlcnN9LlxuICovXG5leHBvcnQgaW50ZXJmYWNlIERlbW9WYXVsdENvdmVyYWdlQ2hlY2tlckdldEludGVyZmFjZU1lbWJlcnNQYXJhbXMge1xuICAvKipcbiAgICogVGhlIG5hbWUgb2YgdGhlIGBleHBvcnQgaW50ZXJmYWNlYCwgYGV4cG9ydCBjbGFzc2AsIG9yIGBleHBvcnQgZW51bWAgdG8gcGFyc2UuXG4gICAqL1xuICByZWFkb25seSBpbnRlcmZhY2VOYW1lOiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIFRoZSBzb3VyY2UgZmlsZSBwYXRoIChyZWxhdGl2ZSB0byB0aGUgcmVwbyByb290KSB0aGF0IGRlY2xhcmVzIHRoZSBpbnRlcmZhY2UsIGNsYXNzLCBvciBlbnVtLlxuICAgKi9cbiAgcmVhZG9ubHkgc291cmNlUGF0aDogc3RyaW5nO1xufVxuXG4vKipcbiAqIENvbmZpZ3VyZXMgdGhlIGZlYXR1cmUtZG9jIGxpbmtpbmcgY2hlY2suXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgRGVtb1ZhdWx0RG9jc0NvdmVyYWdlU3BlYyB7XG4gIC8qKlxuICAgKiBUaGUgZG9jcyBmb2xkZXIgKHJlbGF0aXZlIHRvIHRoZSByZXBvIHJvb3QpIHdob3NlIHRvcC1sZXZlbCBgKi5tZGAgZmlsZXMgYXJlIHRoZSBmZWF0dXJlIGRvY3MuXG4gICAqL1xuICByZWFkb25seSBmb2xkZXI6IHN0cmluZztcblxuICAvKipcbiAgICogVGhlIGRvYyBiYXNlbmFtZXMgKHdpdGhvdXQgYC5tZGApIHRoYXQgYXJlIE5PVCBwZXItZmVhdHVyZSBwYWdlcyBhbmQgc28gbmVlZCBubyBsaW5raW5nIGRlbW8gbm90ZS5cbiAgICovXG4gIHJlYWRvbmx5IG5vbkZlYXR1cmVEb2NzOiBzdHJpbmdbXTtcbn1cblxuLyoqXG4gKiBSZWZsZWN0cyBhIG1vZHVsZSdzIGV4cG9ydGVkIGZ1bmN0aW9ucywgZWFjaCBkZW1vbnN0cmF0ZWQgYnkgaXRzIGJhcmUgbmFtZSBpbiB0aGUgZGVtbyBjb3JwdXMuXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgRGVtb1ZhdWx0RnVuY3Rpb25zQ292ZXJhZ2VTcGVjIHtcbiAgLyoqXG4gICAqIFRoZSBzb3VyY2UgZmlsZSBwYXRoIChyZWxhdGl2ZSB0byB0aGUgcmVwbyByb290KSB3aG9zZSBgZXhwb3J0IGZ1bmN0aW9uYHMgbXVzdCBlYWNoIGJlIGRlbW9uc3RyYXRlZC5cbiAgICovXG4gIHJlYWRvbmx5IHNvdXJjZVBhdGg6IHN0cmluZztcbn1cblxuLyoqXG4gKiBSZWZsZWN0cyBhIHNpbmdsZSBpbnRlcmZhY2UncyBtZW1iZXJzIGFuZCBkZW1vbnN0cmF0ZXMgdGhlbSB2aWEgYGAgYCR7cmVjZWl2ZXJ9LjxtZW1iZXI+YCBgYCByZWZlcmVuY2VzLlxuICovXG5leHBvcnQgaW50ZXJmYWNlIERlbW9WYXVsdEludGVyZmFjZUNvdmVyYWdlU3BlYyB7XG4gIC8qKlxuICAgKiBUaGUgbmFtZSBvZiB0aGUgYGV4cG9ydCBpbnRlcmZhY2VgLCBgZXhwb3J0IGNsYXNzYCwgb3IgYGV4cG9ydCBlbnVtYCB0byByZWZsZWN0LlxuICAgKi9cbiAgcmVhZG9ubHkgaW50ZXJmYWNlTmFtZTogc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBXaGV0aGVyIHRoZSBkZW1vbnN0cmF0ZWQgbWVtYmVycyBhcmUgdGhlIHJlZmxlY3RlZCB0eXBlJ3MgbWV0aG9kcyBvciBpdHMgcHJvcGVydGllcyAoZW51bSBtZW1iZXJzIGNvdW50IGFzXG4gICAqIHByb3BlcnRpZXMpLlxuICAgKi9cbiAgcmVhZG9ubHkga2luZDogRGVtb1ZhdWx0SW50ZXJmYWNlTWVtYmVyS2luZDtcblxuICAvKipcbiAgICogVGhlIGlkZW50aWZpZXIgdGhlIG5vdGVzIGNhbGwgdGhlIG1lbWJlcnMgb24gKGUuZy4gYGNvZGVCdXR0b25Db250ZXh0YCkuXG4gICAqL1xuICByZWFkb25seSByZWNlaXZlcjogc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBUaGUgc291cmNlIGZpbGUgcGF0aCAocmVsYXRpdmUgdG8gdGhlIHJlcG8gcm9vdCkgdGhhdCBkZWNsYXJlcyB0aGUgaW50ZXJmYWNlLCBjbGFzcywgb3IgZW51bS5cbiAgICovXG4gIHJlYWRvbmx5IHNvdXJjZVBhdGg6IHN0cmluZztcbn1cblxuLyoqXG4gKiBXaGV0aGVyIGFuIGludGVyZmFjZSdzIGRlbW9uc3RyYXRlZCBtZW1iZXJzIGFyZSBpdHMgbWV0aG9kcyBvciBpdHMgcHJvcGVydGllcy5cbiAqL1xuZXhwb3J0IHR5cGUgRGVtb1ZhdWx0SW50ZXJmYWNlTWVtYmVyS2luZCA9ICdtZXRob2RzJyB8ICdwcm9wZXJ0aWVzJztcblxuLyoqXG4gKiBDb25maWd1cmVzIHRoZSBndWFyZCB0aGF0IHRoZSByZWZsZWN0ZWQgc3VyZmFjZSBpcyBub24tdHJpdmlhbCAocHJvdGVjdHMgYWdhaW5zdCBhIHBhcnNpbmcgcmVncmVzc2lvblxuICogc2lsZW50bHkgZW1wdHlpbmcgZXZlcnkgb3RoZXIgY2hlY2spLlxuICovXG5leHBvcnQgaW50ZXJmYWNlIERlbW9WYXVsdE5vblRyaXZpYWxHdWFyZFNwZWMge1xuICAvKipcbiAgICogQSBkZW1vIG5vdGUgKHBhdGggcmVsYXRpdmUgdG8gdGhlIGRlbW8gdmF1bHQpIHRoYXQgbXVzdCBiZSBwcmVzZW50LlxuICAgKi9cbiAgcmVhZG9ubHkgZXhwZWN0RGVtb05vdGU6IHN0cmluZztcblxuICAvKipcbiAgICogQSBtZW1iZXIgdGhhdCBtdXN0IGJlIHJlZmxlY3RlZCBmcm9tIHtAbGluayBEZW1vVmF1bHROb25Ucml2aWFsR3VhcmRTcGVjLmludGVyZmFjZU5hbWV9LlxuICAgKi9cbiAgcmVhZG9ubHkgZXhwZWN0TWVtYmVyOiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIFRoZSBuYW1lIG9mIHRoZSBgZXhwb3J0IGludGVyZmFjZWAsIGBleHBvcnQgY2xhc3NgLCBvciBgZXhwb3J0IGVudW1gIHdob3NlIG1lbWJlcnMgYXJlIHJlLXBhcnNlZCBmb3IgdGhlXG4gICAqIGd1YXJkLlxuICAgKi9cbiAgcmVhZG9ubHkgaW50ZXJmYWNlTmFtZTogc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBUaGUgc291cmNlIGZpbGUgcGF0aCAocmVsYXRpdmUgdG8gdGhlIHJlcG8gcm9vdCkgdGhhdCBkZWNsYXJlcyB0aGUgaW50ZXJmYWNlLCBjbGFzcywgb3IgZW51bS5cbiAgICovXG4gIHJlYWRvbmx5IHNvdXJjZVBhdGg6IHN0cmluZztcbn1cblxuLyoqXG4gKiBBIHNpbmdsZSBkZW1vIG5vdGUsIGFzIHJlYWQgZnJvbSB0aGUgZGVtbyB2YXVsdC5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBEZW1vVmF1bHROb3RlIHtcbiAgLyoqXG4gICAqIFRoZSBub3RlJ3MgcmF3IE1hcmtkb3duIGNvbnRlbnQuXG4gICAqL1xuICByZWFkb25seSBjb250ZW50OiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIFRoZSBub3RlJ3MgcGF0aCByZWxhdGl2ZSB0byB0aGUgZGVtbyB2YXVsdCBmb2xkZXIsIGUuZy4gYDAwIFN0YXJ0Lm1kYC5cbiAgICovXG4gIHJlYWRvbmx5IHJlbGF0aXZlUGF0aDogc3RyaW5nO1xufVxuXG4vKipcbiAqIFRoZSBwYXJzZWQgbWVtYmVycyBvZiBhIHNvdXJjZSBpbnRlcmZhY2UsIGNsYXNzLCBvciBlbnVtLlxuICovXG5leHBvcnQgaW50ZXJmYWNlIEludGVyZmFjZU1lbWJlcnMge1xuICAvKipcbiAgICogRXZlcnkgbWVtYmVyIFx1MjAxNCB7QGxpbmsgSW50ZXJmYWNlTWVtYmVycy5tZXRob2RzfSBmb2xsb3dlZCBieSB7QGxpbmsgSW50ZXJmYWNlTWVtYmVycy5wcm9wZXJ0aWVzfS5cbiAgICovXG4gIHJlYWRvbmx5IGFsbDogc3RyaW5nW107XG5cbiAgLyoqXG4gICAqIFRoZSBtZXRob2QgbWVtYmVycyAoZGVjbGFyZWQgYXMgYG5hbWUoLi4uKWApLlxuICAgKi9cbiAgcmVhZG9ubHkgbWV0aG9kczogc3RyaW5nW107XG5cbiAgLyoqXG4gICAqIFRoZSBwcm9wZXJ0eSBtZW1iZXJzIChkZWNsYXJlZCBhcyBgbmFtZT86IC4uLmApLlxuICAgKi9cbiAgcmVhZG9ubHkgcHJvcGVydGllczogc3RyaW5nW107XG59XG5cbi8qKlxuICogQSBub3RlIGxpbmUgcGFpcmVkIHdpdGggdGhlIGxpbmUgbnVtYmVyIGl0IGNhbWUgZnJvbSwgc28gYSBjaGVjayB0aGF0IHNraXBzIGZlbmNlZCBibG9ja3MgY2FuIHN0aWxsXG4gKiByZXBvcnQgXHUyMDE0IGFuZCBhbiBpbmxpbmUgZGlyZWN0aXZlIGNhbiBzdGlsbCBuYW1lIFx1MjAxNCB0aGUgbGluZSBhcyB0aGUgcmVhZGVyIHNlZXMgaXQuXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgTm90ZUxpbmUge1xuICAvKipcbiAgICogVGhlIHplcm8tYmFzZWQgbGluZSBudW1iZXIgd2l0aGluIHRoZSBub3RlLlxuICAgKi9cbiAgcmVhZG9ubHkgaW5kZXg6IG51bWJlcjtcblxuICAvKipcbiAgICogVGhlIGxpbmUncyByYXcgdGV4dC5cbiAgICovXG4gIHJlYWRvbmx5IGxpbmU6IHN0cmluZztcbn1cblxuLyoqXG4gKiBBIGBkaXNhYmxlYCByZWdpb24gdGhhdCBoYXMgYmVlbiBvcGVuZWQgYW5kIG5vdCB5ZXQgZW5hYmxlZCBhZ2Fpbi5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBPcGVuV2lraWxpbmtEaXJlY3RpdmVSZWdpb24ge1xuICAvKipcbiAgICogV2hldGhlciB0aGUgcmVnaW9uIGhhcyBjb3ZlcmVkIGEgd2lraWxpbmssIHdoaWNoIGlzIHdoYXQgc3RvcHMgaXQgYmVpbmcgcmVwb3J0ZWQgYXMgcG9pbnRsZXNzLlxuICAgKi9cbiAgaXNVc2VkOiBib29sZWFuO1xuXG4gIC8qKlxuICAgKiBUaGUgbGluZSB0aGUgcmVnaW9uIHdhcyBvcGVuZWQgb24uXG4gICAqL1xuICByZWFkb25seSBsaW5lSW5kZXg6IG51bWJlcjtcbn1cblxuLyoqXG4gKiBUaGUgcGFyYW1ldGVycyBmb3Ige0BsaW5rIHJlZ2lzdGVyRGVtb1ZhdWx0Q292ZXJhZ2VTdWl0ZX0uXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgUmVnaXN0ZXJEZW1vVmF1bHRDb3ZlcmFnZVN1aXRlUGFyYW1zIHtcbiAgLyoqXG4gICAqIFR1bmVzIHRoZSBhbHdheXMtb24gYXV0aG9yaW5nIGNoZWNrcywgb3IgYHVuZGVmaW5lZGAgdG8gdGFrZSB0aGVpciBkZWZhdWx0cy4gSXQgY2Fubm90IGRpc2FibGUgdGhlbS5cbiAgICovXG4gIHJlYWRvbmx5IGF1dGhvcmluZz86IERlbW9WYXVsdEF1dGhvcmluZ1NwZWM7XG5cbiAgLyoqXG4gICAqIFRoZSBjb25maWcgaW50ZXJmYWNlcyB3aG9zZSBvcHRpb25zIG11c3QgZWFjaCBiZSBkZW1vbnN0cmF0ZWQgYnkgdGhlaXIgYmFyZSBuYW1lLCBvciBgdW5kZWZpbmVkYCB3aGVuIHRoZVxuICAgKiBwbHVnaW4gaGFzIG5vIHNldHRpbmdzLlxuICAgKi9cbiAgcmVhZG9ubHkgY29uZmlnSW50ZXJmYWNlcz86IERlbW9WYXVsdENvbmZpZ0ludGVyZmFjZUNvdmVyYWdlU3BlY1tdO1xuXG4gIC8qKlxuICAgKiBUaGUgZmVhdHVyZS1kb2MgbGlua2luZyBjaGVjaywgb3IgYHVuZGVmaW5lZGAgd2hlbiB0aGUgcGx1Z2luIHNoaXBzIG5vIGBkb2NzL2AgZm9sZGVyLlxuICAgKi9cbiAgcmVhZG9ubHkgZG9jcz86IERlbW9WYXVsdERvY3NDb3ZlcmFnZVNwZWM7XG5cbiAgLyoqXG4gICAqIFRoZSBtb2R1bGVzIHdob3NlIGBleHBvcnQgZnVuY3Rpb25gcyBtdXN0IGVhY2ggYmUgZGVtb25zdHJhdGVkIGJ5IHRoZWlyIGJhcmUgbmFtZSwgb3IgYHVuZGVmaW5lZGAgd2hlbiB0aGVcbiAgICogcGx1Z2luIGV4cG9zZXMgbm8gc3VjaCBtb2R1bGUgdG8gY2hlY2suXG4gICAqL1xuICByZWFkb25seSBmdW5jdGlvbk1vZHVsZXM/OiBEZW1vVmF1bHRGdW5jdGlvbnNDb3ZlcmFnZVNwZWNbXTtcblxuICAvKipcbiAgICogVGhlIGludGVyZmFjZXMgd2hvc2UgbWVtYmVycyBtdXN0IGVhY2ggYmUgZGVtb25zdHJhdGVkIChhbmQgcmVmZXJlbmNlZCB3aXRob3V0IGRyaWZ0KSwgb3IgYHVuZGVmaW5lZGAgd2hlblxuICAgKiB0aGUgcGx1Z2luIGV4cG9zZXMgbm8gcHVibGljIEFQSSBzdXJmYWNlIHRvIHJlZmxlY3QuXG4gICAqL1xuICByZWFkb25seSBpbnRlcmZhY2VzPzogRGVtb1ZhdWx0SW50ZXJmYWNlQ292ZXJhZ2VTcGVjW107XG5cbiAgLyoqXG4gICAqIFRoZSBndWFyZCB0aGF0IGtlZXBzIHRoZSByZWZsZWN0ZWQgc3VyZmFjZSBub24tdHJpdmlhbCwgb3IgYHVuZGVmaW5lZGAgd2hlbiB0aGVyZSBpcyBubyByZWZsZWN0ZWQgc3VyZmFjZVxuICAgKiB0byBndWFyZC4gVGhlIHZhdWx0IGlzIGNoZWNrZWQgZm9yIGJlaW5nIG5vbi1lbXB0eSBlaXRoZXIgd2F5LlxuICAgKi9cbiAgcmVhZG9ubHkgbm9uVHJpdmlhbEd1YXJkPzogRGVtb1ZhdWx0Tm9uVHJpdmlhbEd1YXJkU3BlYztcblxuICAvKipcbiAgICogVGhlIGFic29sdXRlIHBhdGggb2YgdGhlIHBsdWdpbiByZXBvIHJvb3QuIENhbGxlcnMgdHlwaWNhbGx5IHBhc3MgYGdldFJvb3RGb2xkZXIoKSA/PyBwcm9jZXNzLmN3ZCgpYC5cbiAgICovXG4gIHJlYWRvbmx5IHJvb3RGb2xkZXI6IHN0cmluZztcbn1cblxuLyoqXG4gKiBXaGF0IGEgbm90ZSdzIGlubGluZSBgb2JzaWRpYW4tZGV2LXV0aWxzLWRpc2FibGVcdTIwMjZgIGRpcmVjdGl2ZXMgYWxsb3csIGFuZCB3aGF0IGlzIHdyb25nIHdpdGggdGhlbS5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBXaWtpbGlua0RpcmVjdGl2ZVNjYW4ge1xuICAvKipcbiAgICogVGhlIHplcm8tYmFzZWQgbGluZSBudW1iZXJzIGEgZGlyZWN0aXZlIGFsbG93cyBhIHdpa2lsaW5rIG9uLlxuICAgKi9cbiAgcmVhZG9ubHkgYWxsb3dlZExpbmVJbmRleGVzOiBSZWFkb25seVNldDxudW1iZXI+O1xuXG4gIC8qKlxuICAgKiBUaGUgZGlyZWN0aXZlIG1pc3Rha2VzIGZvdW5kLCBlYWNoIHBocmFzZWQgZm9yIGEgZmFpbGluZyBhc3NlcnRpb24uXG4gICAqL1xuICByZWFkb25seSBwcm9ibGVtczogc3RyaW5nW107XG59XG5cbi8qKlxuICogVGhlIHJ1bm5pbmcgc3RhdGUgb2YgYSBkaXJlY3RpdmUgc2NhbiwgdGhyZWFkZWQgdGhyb3VnaCB0aGUgcGVyLWxpbmUgaGVscGVycy5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBXaWtpbGlua0RpcmVjdGl2ZVNjYW5TdGF0ZSB7XG4gIC8qKlxuICAgKiBUaGUgbGluZXMgYSBkaXJlY3RpdmUgaGFzIGFsbG93ZWQgYSB3aWtpbGluayBvbiBzbyBmYXIuXG4gICAqL1xuICByZWFkb25seSBhbGxvd2VkTGluZUluZGV4ZXM6IFNldDxudW1iZXI+O1xuXG4gIC8qKlxuICAgKiBUaGUgcmVnaW9uIGN1cnJlbnRseSBvcGVuLCBhbmQgd2hldGhlciBpdCBoYXMgY292ZXJlZCBhIHdpa2lsaW5rIHlldC5cbiAgICovXG4gIG9wZW5SZWdpb246IG51bGwgfCBPcGVuV2lraWxpbmtEaXJlY3RpdmVSZWdpb247XG5cbiAgLyoqXG4gICAqIFRoZSBsaW5lIGEgYGRpc2FibGUtbmV4dC1saW5lYCB3YXMgcmVhZCBvbiwgd2hpbGUgaXQgc3RpbGwgd2FpdHMgZm9yIHRoZSBsaW5lIGl0IGNvdmVycy5cbiAgICovXG4gIHBlbmRpbmdOZXh0TGluZUluZGV4OiBudWxsIHwgbnVtYmVyO1xuXG4gIC8qKlxuICAgKiBUaGUgZGlyZWN0aXZlIG1pc3Rha2VzIGZvdW5kIHNvIGZhci5cbiAgICovXG4gIHJlYWRvbmx5IHByb2JsZW1zOiBzdHJpbmdbXTtcblxuICAvKipcbiAgICogVGhlIGxpbmVzIG9mIHRoZSBub3RlIHRoYXQgY2FycnkgYSB3aWtpbGluay5cbiAgICovXG4gIHJlYWRvbmx5IHdpa2lsaW5rTGluZUluZGV4ZXM6IFJlYWRvbmx5U2V0PG51bWJlcj47XG59XG5cbi8qKlxuICogUmVmbGVjdHMgYSBwbHVnaW4ncyBwdWJsaWMgc3VyZmFjZSBmcm9tIHNvdXJjZSBhbmQgY2hlY2tzIGl0cyBpbi1yZXBvIGBkZW1vLXZhdWx0L2Agc3RheXMgaW4gc3luYyB3aXRoIGl0LlxuICpcbiAqIEV2ZXJ5IG1ldGhvZCBpcyBhIHB1cmUgcXVlcnkgb3ZlciBmaWxlcyB1bmRlciB0aGUgcmVwbyByb290ICh0aGUgZGVtbyBjb3JwdXMgaXMgcmVhZCBvbmNlIGFuZCBjYWNoZWQpLCBzb1xuICogdGhlIGNoZWNrZXIgaXMgdHJpdmlhbGx5IHVuaXQtdGVzdGFibGUgYWdhaW5zdCBhIGZpeHR1cmUgcmVwbyBhbmQgY2FycmllcyBubyB0ZXN0LWZyYW1ld29yayBkZXBlbmRlbmN5LlxuICovXG5leHBvcnQgY2xhc3MgRGVtb1ZhdWx0Q292ZXJhZ2VDaGVja2VyIHtcbiAgcHJpdmF0ZSBjYWNoZWRDb3JwdXM6IG51bGwgfCBzdHJpbmcgPSBudWxsO1xuICBwcml2YXRlIGNhY2hlZE5vdGVzOiBEZW1vVmF1bHROb3RlW10gfCBudWxsID0gbnVsbDtcbiAgcHJpdmF0ZSByZWFkb25seSBkZW1vVmF1bHRGb2xkZXI6IHN0cmluZztcbiAgcHJpdmF0ZSByZWFkb25seSBleGNsdWRlZE5vdGVzOiBTZXQ8c3RyaW5nPjtcbiAgcHJpdmF0ZSByZWFkb25seSByb290Rm9sZGVyOiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIENyZWF0ZXMgYSBjaGVja2VyIHJvb3RlZCBhdCBhIHBsdWdpbiByZXBvLlxuICAgKlxuICAgKiBAcGFyYW0gcGFyYW1zIC0gVGhlIHBhcmFtZXRlcnMgZm9yIHRoZSBjb25zdHJ1Y3Rvci5cbiAgICovXG4gIHB1YmxpYyBjb25zdHJ1Y3RvcihwYXJhbXM6IERlbW9WYXVsdENvdmVyYWdlQ2hlY2tlckNvbnN0cnVjdG9yUGFyYW1zKSB7XG4gICAgdGhpcy5yb290Rm9sZGVyID0gcGFyYW1zLnJvb3RGb2xkZXI7XG4gICAgdGhpcy5kZW1vVmF1bHRGb2xkZXIgPSBqb2luKHRoaXMucm9vdEZvbGRlciwgT2JzaWRpYW5QbHVnaW5SZXBvUGF0aHMuRGVtb1ZhdWx0KTtcbiAgICB0aGlzLmV4Y2x1ZGVkTm90ZXMgPSBuZXcgU2V0KHBhcmFtcy5leGNsdWRlZE5vdGVzID8/IERFRkFVTFRfRVhDTFVERURfTk9URVMpO1xuICB9XG5cbiAgLyoqXG4gICAqIENvbGxlY3RzIHRoZSBkZW1vIG5vdGVzIGFzIHBhdGhzIHJlbGF0aXZlIHRvIHRoZSBkZW1vIHZhdWx0IGZvbGRlciAoZm9yIGEgbm9uLXRyaXZpYWwtc3VyZmFjZSBndWFyZCkuXG4gICAqXG4gICAqIEByZXR1cm5zIFRoZSByZWxhdGl2ZSBwYXRocyBvZiBldmVyeSBgKi5tZGAgbm90ZSBpbiB0aGUgZGVtbyB2YXVsdC5cbiAgICovXG4gIHB1YmxpYyBjb2xsZWN0RGVtb05vdGVSZWxhdGl2ZVBhdGhzKCk6IHN0cmluZ1tdIHtcbiAgICByZXR1cm4gdGhpcy5jb2xsZWN0Tm90ZXMoKS5tYXAoKG5vdGUpID0+IG5vdGUucmVsYXRpdmVQYXRoKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZWFkcyBhbmQgY2FjaGVzIGV2ZXJ5IGRlbW8gbm90ZSBpbmRpdmlkdWFsbHkgXHUyMDE0IHRoZSBwZXItbm90ZSB2aWV3IHRoZSBhdXRob3JpbmcgY2hlY2tzIHdvcmsgb24sIGFzXG4gICAqIG9wcG9zZWQgdG8gdGhlIGNvbmNhdGVuYXRlZCB7QGxpbmsgRGVtb1ZhdWx0Q292ZXJhZ2VDaGVja2VyLnJlYWRDb3JwdXN9LlxuICAgKlxuICAgKiBAcmV0dXJucyBFdmVyeSBgKi5tZGAgbm90ZSBpbiB0aGUgZGVtbyB2YXVsdCwgZXhjbHVkZWQgb25lcyBpbmNsdWRlZC5cbiAgICovXG4gIHB1YmxpYyBjb2xsZWN0Tm90ZXMoKTogRGVtb1ZhdWx0Tm90ZVtdIHtcbiAgICB0aGlzLmNhY2hlZE5vdGVzID8/PSB0aGlzLmNvbGxlY3RNYXJrZG93bkZpbGVzKHRoaXMuZGVtb1ZhdWx0Rm9sZGVyKS5tYXAoKGZpbGUpID0+ICh7XG4gICAgICBjb250ZW50OiByZWFkRmlsZVN5bmMoZmlsZSwgJ3V0Zi04JyksXG4gICAgICByZWxhdGl2ZVBhdGg6IHJlbGF0aXZlKHRoaXMuZGVtb1ZhdWx0Rm9sZGVyLCBmaWxlKVxuICAgIH0pKTtcbiAgICByZXR1cm4gdGhpcy5jYWNoZWROb3RlcztcbiAgfVxuXG4gIC8qKlxuICAgKiBGaW5kcyB0aGUgYC5vYnNpZGlhbi9hcHAuanNvbmAgc2V0dGluZ3MgdGhlIHZhdWx0IGNvbW1pdHMgdGhhdCBgb2JzaWRpYW4tZGV2LXV0aWxzYCBvd25zIGFuZCB3cml0ZXNcbiAgICogaW50byB0aGUgYXJjaGl2ZWQgdmF1bHQgaXRzZWxmLiBBIGNvbW1pdHRlZCBvbmUgaXMgYSBzZWNvbmQgY29weSBvZiBhIHNldHRpbmcgbm90aGluZyByZWNvbmNpbGVzLCBhbmRcbiAgICogaXQgaXMgdGhlIGNvcHkgdGhhdCBnb2VzIHN0YWxlIFx1MjAxNCBzbyB0aGUgY29udmVudGlvbiBpcyB0aGF0IHRoZSB2YXVsdCBjb21taXRzIG5vbmUgb2YgdGhlbS5cbiAgICpcbiAgICogQHJldHVybnMgVGhlIG5hbWVzIG9mIHRoZSBvd25lZCBzZXR0aW5ncyB0aGUgY29tbWl0dGVkIGBhcHAuanNvbmAgc2V0cy4gQSB2YXVsdCB0aGF0IGNvbW1pdHMgbm9cbiAgICogYGFwcC5qc29uYCBhdCBhbGwgaXMgZmluZSwgYW5kIHlpZWxkcyBub25lLlxuICAgKi9cbiAgcHVibGljIGZpbmRDb21taXR0ZWRBcHBKc29uU2V0dGluZ3MoKTogc3RyaW5nW10ge1xuICAgIGNvbnN0IGFwcEpzb25QYXRoID0gam9pbih0aGlzLmRlbW9WYXVsdEZvbGRlciwgT2JzaWRpYW5QbHVnaW5SZXBvUGF0aHMuRG90T2JzaWRpYW4sIE9ic2lkaWFuUGx1Z2luUmVwb1BhdGhzLkFwcEpzb24pO1xuICAgIGNvbnN0IGNvbnRlbnQgPSBleGlzdHNTeW5jKGFwcEpzb25QYXRoKSA/IHJlYWRGaWxlU3luYyhhcHBKc29uUGF0aCwgJ3V0Zi04JykgOiBudWxsO1xuICAgIHJldHVybiBmaW5kT3duZWREZW1vVmF1bHRBcHBKc29uU2V0dGluZ3MoeyBhcHBKc29uOiBwYXJzZURlbW9WYXVsdEFwcEpzb24oeyBjb250ZW50LCBwYXRoOiBhcHBKc29uUGF0aCB9KSB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBGaW5kcyBub3RlcyBjYXJyeWluZyBhIGBbRG9jc10oXHUyMDI2KWAgbGluayBsaW5lLiBUaGUgbm90ZSBJUyB0aGUgZG9jdW1lbnRhdGlvbiwgc28gYSBsaW5lIHBvaW50aW5nXG4gICAqIGVsc2V3aGVyZSBmb3IgdGhlIHJlYWwgZXhwbGFuYXRpb24gaXMgdGhlIHNoYXBlIHRoaXMgY29udmVudGlvbiBleGlzdHMgdG8gcmVtb3ZlLlxuICAgKlxuICAgKiBAcmV0dXJucyBUaGUgcmVsYXRpdmUgcGF0aHMgb2YgdGhlIG9mZmVuZGluZyBub3Rlcy5cbiAgICovXG4gIHB1YmxpYyBmaW5kTm90ZXNXaXRoRG9jc0xpbmtzKCk6IHN0cmluZ1tdIHtcbiAgICByZXR1cm4gdGhpcy5jb2xsZWN0Q2hlY2thYmxlTm90ZXMoKVxuICAgICAgLmZpbHRlcigobm90ZSkgPT4gZ2V0TGluZXNPdXRzaWRlRmVuY2VzKG5vdGUuY29udGVudCkuc29tZSgobGluZSkgPT4gRE9DU19MSU5LX1JFR19FWFAudGVzdChsaW5lKSkpXG4gICAgICAubWFwKChub3RlKSA9PiBub3RlLnJlbGF0aXZlUGF0aCk7XG4gIH1cblxuICAvKipcbiAgICogRmluZHMgbm90ZXMgdGhhdCBkbyBub3Qgb3BlbiB3aXRoIGFuIGAjIEgxYCAoZnJvbnRtYXR0ZXIgYXNpZGUpLlxuICAgKlxuICAgKiBAcmV0dXJucyBUaGUgcmVsYXRpdmUgcGF0aHMgb2YgdGhlIG9mZmVuZGluZyBub3Rlcy5cbiAgICovXG4gIHB1YmxpYyBmaW5kTm90ZXNXaXRob3V0SDEoKTogc3RyaW5nW10ge1xuICAgIHJldHVybiB0aGlzLmNvbGxlY3RDaGVja2FibGVOb3RlcygpXG4gICAgICAuZmlsdGVyKChub3RlKSA9PiAhaGFzSDEobm90ZS5jb250ZW50KSlcbiAgICAgIC5tYXAoKG5vdGUpID0+IG5vdGUucmVsYXRpdmVQYXRoKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBGaW5kcyBub3RlcyB3aXRoIG5vIHByb3NlIHBhcmFncmFwaCBiZWZvcmUgdGhlaXIgZmlyc3QgY29kZSBmZW5jZSBcdTIwMTQgdGhlIDEtMyBzZW50ZW5jZXMgc2F5aW5nIHdoYXQgdGhlXG4gICAqIGZlYXR1cmUgZG9lcyBhbmQgd2h5IGEgcmVhZGVyIHdvdWxkIHdhbnQgaXQsIHdpdGhvdXQgd2hpY2ggdGhlIG5vdGUgaXMgYSBidXR0b24gd2l0aCBubyBsZXNzb24uXG4gICAqXG4gICAqIEByZXR1cm5zIFRoZSByZWxhdGl2ZSBwYXRocyBvZiB0aGUgb2ZmZW5kaW5nIG5vdGVzLlxuICAgKi9cbiAgcHVibGljIGZpbmROb3Rlc1dpdGhvdXRJbnRyb1Byb3NlKCk6IHN0cmluZ1tdIHtcbiAgICByZXR1cm4gdGhpcy5jb2xsZWN0Q2hlY2thYmxlTm90ZXMoKVxuICAgICAgLmZpbHRlcigobm90ZSkgPT4gIWhhc0ludHJvUHJvc2Uobm90ZS5jb250ZW50KSlcbiAgICAgIC5tYXAoKG5vdGUpID0+IG5vdGUucmVsYXRpdmVQYXRoKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBGaW5kcyBub3RlcyB3aG9zZSB3aWtpbGluayBhbGxvd2FuY2UgaXMgbm90IGRvaW5nIGFueSB3b3JrIFx1MjAxNCBkZWNsYXJlZCB3aXRob3V0IGEgcmVhc29uLCBvciBvbiBhIG5vdGVcbiAgICogdGhhdCBjYXJyaWVzIG5vIHdpa2lsaW5rIGF0IGFsbC4gQm90aCBhcmUgZHJpZnQ6IGFuIGV4ZW1wdGlvbiBub2JvZHkgY2FuIGp1c3RpZnksIGFuZCBvbmUgbm90aGluZyBuZWVkc1xuICAgKiBhbnkgbW9yZSwgd2hpY2ggd291bGQgZ28gb24gaGlkaW5nIHRoZSBuZXh0IHdpa2lsaW5rIHNvbWVib2R5IGFkZHMgYnkgYWNjaWRlbnQuXG4gICAqXG4gICAqIEByZXR1cm5zIFRoZSByZWxhdGl2ZSBwYXRocyBvZiB0aGUgb2ZmZW5kaW5nIG5vdGVzLlxuICAgKi9cbiAgcHVibGljIGZpbmROb3Rlc1dpdGhVbmp1c3RpZmllZFdpa2lsaW5rQWxsb3dhbmNlKCk6IHN0cmluZ1tdIHtcbiAgICByZXR1cm4gdGhpcy5jb2xsZWN0Q2hlY2thYmxlTm90ZXMoKS5mbGF0TWFwKChub3RlKSA9PiB7XG4gICAgICBjb25zdCBzY2FuID0gc2Nhbldpa2lsaW5rRGlyZWN0aXZlcyhub3RlLmNvbnRlbnQpO1xuICAgICAgY29uc3QgcHJvYmxlbXMgPSBbLi4uc2Nhbi5wcm9ibGVtc107XG4gICAgICBjb25zdCByZWFzb24gPSByZWFkV2lraWxpbmtBbGxvd2FuY2VSZWFzb24obm90ZS5jb250ZW50KTtcbiAgICAgIGlmIChyZWFzb24gIT09IG51bGwpIHtcbiAgICAgICAgaWYgKHJlYXNvbi50cmltKCkgPT09ICcnKSB7XG4gICAgICAgICAgcHJvYmxlbXMucHVzaCgnYSBub3RlLWxldmVsIGFsbG93YW5jZSB3aXRoIG5vIHJlYXNvbicpO1xuICAgICAgICB9IGVsc2UgaWYgKCFoYXNXaWtpbGluayhub3RlLmNvbnRlbnQpKSB7XG4gICAgICAgICAgcHJvYmxlbXMucHVzaCgnYSBub3RlLWxldmVsIGFsbG93YW5jZSBjb3ZlcmluZyBubyB3aWtpbGluaycpO1xuICAgICAgICB9IGVsc2UgaWYgKHNjYW4uYWxsb3dlZExpbmVJbmRleGVzLnNpemUgPiAwKSB7XG4gICAgICAgICAgcHJvYmxlbXMucHVzaCgnaW5saW5lIGRpcmVjdGl2ZXMgdGhlIG5vdGUtbGV2ZWwgYWxsb3dhbmNlIGFscmVhZHkgY292ZXJzJyk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIHJldHVybiBwcm9ibGVtcy5tYXAoKHByb2JsZW0pID0+IGAke25vdGUucmVsYXRpdmVQYXRofTogJHtwcm9ibGVtfWApO1xuICAgIH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIEZpbmRzIG5vdGVzIHVzaW5nIGFuIE9ic2lkaWFuIGBbW3dpa2lsaW5rXV1gIG91dHNpZGUgYSBjb2RlIGZlbmNlLiBUaGUgZGVtbyB2YXVsdCBpcyBhbHNvIHJlYWQgb25cbiAgICogR2l0SHViLCB3aGVyZSBhIHdpa2lsaW5rIHJlbmRlcnMgYXMgbGl0ZXJhbCBicmFja2V0cyBhbmQgbGVhZHMgbm93aGVyZS4gQSB3aWtpbGluayBzaG93biBJTlNJREUgYVxuICAgKiBmZW5jZSBpcyBzYW1wbGUgdGV4dCwgbm90IG5hdmlnYXRpb24sIHNvIGZlbmNlZCBibG9ja3MgYXJlIHNraXBwZWQsIGFzIGlzIGEgbm90ZSB0aGF0IGRlY2xhcmVzIGluIGl0c1xuICAgKiBmcm9udG1hdHRlciB3aHkgaXRzIHdpa2lsaW5rcyBhcmUgdGhlIHBvaW50IFx1MjAxNCBzZWUgdGhlIGZpbGUgb3ZlcnZpZXcuXG4gICAqXG4gICAqIEByZXR1cm5zIFRoZSByZWxhdGl2ZSBwYXRocyBvZiB0aGUgb2ZmZW5kaW5nIG5vdGVzLlxuICAgKi9cbiAgcHVibGljIGZpbmROb3Rlc1dpdGhXaWtpbGlua3MoKTogc3RyaW5nW10ge1xuICAgIHJldHVybiB0aGlzLmNvbGxlY3RDaGVja2FibGVOb3RlcygpXG4gICAgICAuZmlsdGVyKChub3RlKSA9PiB7XG4gICAgICAgIGlmIChyZWFkV2lraWxpbmtBbGxvd2FuY2VSZWFzb24obm90ZS5jb250ZW50KSAhPT0gbnVsbCkge1xuICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgfVxuICAgICAgICBjb25zdCB7IGFsbG93ZWRMaW5lSW5kZXhlcyB9ID0gc2Nhbldpa2lsaW5rRGlyZWN0aXZlcyhub3RlLmNvbnRlbnQpO1xuICAgICAgICByZXR1cm4gZmluZFdpa2lsaW5rTGluZUluZGV4ZXMobm90ZS5jb250ZW50KS5zb21lKChsaW5lSW5kZXgpID0+ICFhbGxvd2VkTGluZUluZGV4ZXMuaGFzKGxpbmVJbmRleCkpO1xuICAgICAgfSlcbiAgICAgIC5tYXAoKG5vdGUpID0+IG5vdGUucmVsYXRpdmVQYXRoKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBGaW5kcyBtZW1iZXJzIHRoYXQgdGhlIGRlbW8gbm90ZXMgcmVmZXJlbmNlIG9uIGEgcmVjZWl2ZXIgYnV0IHRoYXQgbm8gbG9uZ2VyIGV4aXN0IG9uIGl0IChyZW5hbWUgZHJpZnQpLlxuICAgKlxuICAgKiBAcGFyYW0gcGFyYW1zIC0gVGhlIHBhcmFtZXRlcnMgZm9yIHRoZSBsb29rdXAuXG4gICAqIEByZXR1cm5zIFRoZSBkaXN0aW5jdCBzdGFsZSBtZW1iZXIgbmFtZXMgcmVmZXJlbmNlZCBpbiB0aGUgZGVtbyBjb3JwdXMuXG4gICAqL1xuICBwdWJsaWMgZmluZFN0YWxlUmVmZXJlbmNlcyhwYXJhbXM6IERlbW9WYXVsdENvdmVyYWdlQ2hlY2tlckZpbmRTdGFsZVJlZmVyZW5jZXNQYXJhbXMpOiBzdHJpbmdbXSB7XG4gICAgY29uc3QgdmFsaWRNZW1iZXJzID0gbmV3IFNldChwYXJhbXMudmFsaWRNZW1iZXJzKTtcbiAgICBjb25zdCByZWZlcmVuY2VkID0gWy4uLnRoaXMucmVhZENvcnB1cygpLm1hdGNoQWxsKG5ldyBSZWdFeHAoU3RyaW5nLnJhd2Ake3BhcmFtcy5yZWNlaXZlcn1cXC4oPzxtZW1iZXI+XFx3KylgLCAnZycpKV1cbiAgICAgIC5tYXAoKG1hdGNoKSA9PiBnZXRNYW5kYXRvcnlOYW1lZEdyb3VwKG1hdGNoLCAnbWVtYmVyJykpO1xuICAgIHJldHVybiBbLi4ubmV3IFNldChyZWZlcmVuY2VkKV0uZmlsdGVyKChtZW1iZXIpID0+ICF2YWxpZE1lbWJlcnMuaGFzKG1lbWJlcikpO1xuICB9XG5cbiAgLyoqXG4gICAqIEZpbmRzIG1lbWJlcnMgdGhhdCBhcmUgbm90IGRlbW9uc3RyYXRlZCBhbnl3aGVyZSBpbiB0aGUgZGVtbyBjb3JwdXMuXG4gICAqXG4gICAqIEBwYXJhbSBwYXJhbXMgLSBUaGUgcGFyYW1ldGVycyBmb3IgdGhlIGxvb2t1cC5cbiAgICogQHJldHVybnMgVGhlIG1lbWJlciBuYW1lcyB3aXRoIG5vIGRlbW9uc3RyYXRpb24uXG4gICAqL1xuICBwdWJsaWMgZmluZFVuZGVtb25zdHJhdGVkTWVtYmVycyhwYXJhbXM6IERlbW9WYXVsdENvdmVyYWdlQ2hlY2tlckZpbmRVbmRlbW9uc3RyYXRlZE1lbWJlcnNQYXJhbXMpOiBzdHJpbmdbXSB7XG4gICAgY29uc3QgY29ycHVzID0gdGhpcy5yZWFkQ29ycHVzKCk7XG4gICAgcmV0dXJuIHBhcmFtcy5tZW1iZXJzLmZpbHRlcigobWVtYmVyKSA9PiB7XG4gICAgICBjb25zdCBuZWVkbGUgPSBwYXJhbXMucmVjZWl2ZXIgPT09IHVuZGVmaW5lZCA/IG1lbWJlciA6IGAke3BhcmFtcy5yZWNlaXZlcn0uJHttZW1iZXJ9YDtcbiAgICAgIHJldHVybiAhY29ycHVzLmluY2x1ZGVzKG5lZWRsZSk7XG4gICAgfSk7XG4gIH1cblxuICAvKipcbiAgICogRmluZHMgZmVhdHVyZSBkb2NzIHRoYXQgbm8gZGVtbyBub3RlIGxpbmtzIHRvLlxuICAgKlxuICAgKiBAcGFyYW0gcGFyYW1zIC0gVGhlIHBhcmFtZXRlcnMgZm9yIHRoZSBsb29rdXAuXG4gICAqIEByZXR1cm5zIFRoZSBmZWF0dXJlLWRvYyBiYXNlbmFtZXMgKHdpdGhvdXQgYC5tZGApIG5vdCBsaW5rZWQgZnJvbSBhbnkgZGVtbyBub3RlLlxuICAgKi9cbiAgcHVibGljIGZpbmRVbmxpbmtlZEZlYXR1cmVEb2NzKHBhcmFtczogRGVtb1ZhdWx0Q292ZXJhZ2VDaGVja2VyRmluZFVubGlua2VkRmVhdHVyZURvY3NQYXJhbXMpOiBzdHJpbmdbXSB7XG4gICAgY29uc3Qgbm9uRmVhdHVyZURvY3MgPSBuZXcgU2V0KHBhcmFtcy5ub25GZWF0dXJlRG9jcyk7XG4gICAgY29uc3QgZmVhdHVyZURvY3MgPSByZWFkZGlyU3luYyhqb2luKHRoaXMucm9vdEZvbGRlciwgcGFyYW1zLmRvY3NGb2xkZXIpKVxuICAgICAgLmZpbHRlcigoZmlsZSkgPT4gZmlsZS5lbmRzV2l0aCgnLm1kJykpXG4gICAgICAubWFwKChmaWxlKSA9PiBmaWxlLnJlcGxhY2UoL1xcLm1kJC8sICcnKSlcbiAgICAgIC5maWx0ZXIoKG5hbWUpID0+ICFub25GZWF0dXJlRG9jcy5oYXMobmFtZSkpO1xuICAgIGNvbnN0IGxpbmtlZERvY3MgPSBuZXcgU2V0KFxuICAgICAgWy4uLnRoaXMucmVhZENvcnB1cygpLm1hdGNoQWxsKC9kb2NzXFwvKD88ZG9jPltcXHctXSspXFwubWQvZyldLm1hcCgobWF0Y2gpID0+IGdldE1hbmRhdG9yeU5hbWVkR3JvdXAobWF0Y2gsICdkb2MnKSlcbiAgICApO1xuICAgIHJldHVybiBmZWF0dXJlRG9jcy5maWx0ZXIoKGRvYykgPT4gIWxpbmtlZERvY3MuaGFzKGRvYykpO1xuICB9XG5cbiAgLyoqXG4gICAqIEZpbmRzIG5vdGVzIHRoYXQgY2Fubm90IGJlIHJlYWNoZWQgZnJvbSB0aGUgc3RhcnQgbm90ZSBieSBmb2xsb3dpbmcgTWFya2Rvd24gbGlua3MgYmV0d2VlbiBub3Rlcy5cbiAgICpcbiAgICogVGhlIHdhbGsgc3RhcnRzIGF0IHtAbGluayBEZW1vVmF1bHRDb3ZlcmFnZUNoZWNrZXJGaW5kVW5yZWFjaGFibGVOb3Rlc1BhcmFtcy5zdGFydE5vdGV9IGFuZCBmb2xsb3dzXG4gICAqIGV2ZXJ5IGBbVGV4dF0oPC4vTk4gTmFtZS5tZD4pYCBsaW5rIG91dHNpZGUgYSBjb2RlIGZlbmNlLCB0cmFuc2l0aXZlbHkuIEEgbm90ZSBub3RoaW5nIGxpbmtzIHRvIGlzXG4gICAqIG9uZSBhIHJlYWRlciBjYW4gb25seSBmaW5kIGJ5IGJyb3dzaW5nIHRoZSBmaWxlIGxpc3QgXHUyMDE0IHdoaWNoIGlzIGV4YWN0bHkgd2hhdCB0aGUgZ3JvdXBlZCBpbmRleCBpbiB0aGVcbiAgICogc3RhcnQgbm90ZSBpcyBtZWFudCB0byByZXBsYWNlLiBXaGVuIHRoZSBzdGFydCBub3RlIGl0c2VsZiBpcyBtaXNzaW5nLCBFVkVSWSBub3RlIGlzIHVucmVhY2hhYmxlLFxuICAgKiBiZWNhdXNlIHRoZXJlIGlzIG5vd2hlcmUgdG8gc3RhcnQgZnJvbS5cbiAgICpcbiAgICogQHBhcmFtIHBhcmFtcyAtIFRoZSBwYXJhbWV0ZXJzIGZvciB0aGUgd2Fsay5cbiAgICogQHJldHVybnMgVGhlIHJlbGF0aXZlIHBhdGhzIG9mIHRoZSB1bnJlYWNoYWJsZSBub3Rlcy5cbiAgICovXG4gIHB1YmxpYyBmaW5kVW5yZWFjaGFibGVOb3RlcyhwYXJhbXM6IERlbW9WYXVsdENvdmVyYWdlQ2hlY2tlckZpbmRVbnJlYWNoYWJsZU5vdGVzUGFyYW1zKTogc3RyaW5nW10ge1xuICAgIGNvbnN0IG5vdGVzQnlSZWxhdGl2ZVBhdGggPSBuZXcgTWFwKHRoaXMuY29sbGVjdE5vdGVzKCkubWFwKChub3RlKSA9PiBbbm90ZS5yZWxhdGl2ZVBhdGgsIG5vdGVdKSk7XG4gICAgY29uc3QgcmVhY2hlZE5vdGVzID0gbmV3IFNldDxzdHJpbmc+KCk7XG4gICAgY29uc3QgcGVuZGluZ05vdGVzID0gW3BhcmFtcy5zdGFydE5vdGVdO1xuXG4gICAgd2hpbGUgKHBlbmRpbmdOb3Rlcy5sZW5ndGggPiAwKSB7XG4gICAgICBjb25zdCBub3RlUGF0aCA9IGVuc3VyZU5vbk51bGxhYmxlKHBlbmRpbmdOb3Rlcy5wb3AoKSk7XG4gICAgICBjb25zdCBub3RlID0gbm90ZXNCeVJlbGF0aXZlUGF0aC5nZXQobm90ZVBhdGgpO1xuICAgICAgaWYgKCFub3RlIHx8IHJlYWNoZWROb3Rlcy5oYXMobm90ZVBhdGgpKSB7XG4gICAgICAgIGNvbnRpbnVlO1xuICAgICAgfVxuICAgICAgcmVhY2hlZE5vdGVzLmFkZChub3RlUGF0aCk7XG4gICAgICBwZW5kaW5nTm90ZXMucHVzaCguLi5jb2xsZWN0Tm90ZUxpbmtUYXJnZXRzKG5vdGUpKTtcbiAgICB9XG5cbiAgICByZXR1cm4gdGhpcy5jb2xsZWN0Q2hlY2thYmxlTm90ZXMoKVxuICAgICAgLm1hcCgobm90ZSkgPT4gbm90ZS5yZWxhdGl2ZVBhdGgpXG4gICAgICAuZmlsdGVyKChub3RlUGF0aCkgPT4gIXJlYWNoZWROb3Rlcy5oYXMobm90ZVBhdGgpKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBQYXJzZXMgdGhlIG5hbWVzIG9mIHRoZSBgZXhwb3J0IGZ1bmN0aW9uYHMgKGluY2x1ZGluZyBgYXN5bmNgIGFuZCBnZW5lcmF0b3IgZGVjbGFyYXRpb25zKSBpbiBhIHNvdXJjZSBmaWxlLlxuICAgKlxuICAgKiBAcGFyYW0gcGFyYW1zIC0gVGhlIHBhcmFtZXRlcnMgZm9yIHRoZSBsb29rdXAuXG4gICAqIEByZXR1cm5zIFRoZSBleHBvcnRlZCBmdW5jdGlvbiBuYW1lcyBpbiBzb3VyY2Ugb3JkZXIuXG4gICAqL1xuICBwdWJsaWMgZ2V0RXhwb3J0ZWRGdW5jdGlvbk5hbWVzKHBhcmFtczogRGVtb1ZhdWx0Q292ZXJhZ2VDaGVja2VyR2V0RXhwb3J0ZWRGdW5jdGlvbk5hbWVzUGFyYW1zKTogc3RyaW5nW10ge1xuICAgIGNvbnN0IHNvdXJjZSA9IHJlYWRGaWxlU3luYyhqb2luKHRoaXMucm9vdEZvbGRlciwgcGFyYW1zLnNvdXJjZVBhdGgpLCAndXRmLTgnKTtcbiAgICByZXR1cm4gWy4uLnNvdXJjZS5tYXRjaEFsbCgvXmV4cG9ydCAoPzphc3luYyApP2Z1bmN0aW9uXFwqPyAoPzxuYW1lPlxcdyspL2dtKV1cbiAgICAgIC5tYXAoKG1hdGNoKSA9PiBnZXRNYW5kYXRvcnlOYW1lZEdyb3VwKG1hdGNoLCAnbmFtZScpKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBQYXJzZXMgdGhlIG1lbWJlcnMgb2YgYW4gYGV4cG9ydCBpbnRlcmZhY2VgLCBgZXhwb3J0IGNsYXNzYCwgb3IgYGV4cG9ydCBlbnVtYCBkZWNsYXJlZCBpbiBhIHNvdXJjZSBmaWxlLlxuICAgKlxuICAgKiBAcGFyYW0gcGFyYW1zIC0gVGhlIHBhcmFtZXRlcnMgZm9yIHRoZSBsb29rdXAuXG4gICAqIEByZXR1cm5zIFRoZSBwYXJzZWQge0BsaW5rIEludGVyZmFjZU1lbWJlcnN9LlxuICAgKiBAdGhyb3dzIFdoZW4gdGhlIGludGVyZmFjZSwgY2xhc3MsIG9yIGVudW0gY2Fubm90IGJlIGZvdW5kIGluIHRoZSBzb3VyY2UgZmlsZS5cbiAgICovXG4gIHB1YmxpYyBnZXRJbnRlcmZhY2VNZW1iZXJzKHBhcmFtczogRGVtb1ZhdWx0Q292ZXJhZ2VDaGVja2VyR2V0SW50ZXJmYWNlTWVtYmVyc1BhcmFtcyk6IEludGVyZmFjZU1lbWJlcnMge1xuICAgIGNvbnN0IHNvdXJjZSA9IHJlYWRGaWxlU3luYyhqb2luKHRoaXMucm9vdEZvbGRlciwgcGFyYW1zLnNvdXJjZVBhdGgpLCAndXRmLTgnKTtcbiAgICBjb25zdCBtYXRjaCA9IG5ldyBSZWdFeHAoU3RyaW5nLnJhd2BleHBvcnQgKD88a2V5d29yZD5pbnRlcmZhY2V8Y2xhc3N8ZW51bSkgJHtwYXJhbXMuaW50ZXJmYWNlTmFtZX1cXGJbXntdKlxceyg/PGJvZHk+W1xcc1xcU10qPylcXG5cXH1gKS5leGVjKHNvdXJjZSk7XG4gICAgaWYgKCFtYXRjaCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGBDb3VsZCBub3QgZmluZCBpbnRlcmZhY2UgJHtwYXJhbXMuaW50ZXJmYWNlTmFtZX1gKTtcbiAgICB9XG4gICAgcmV0dXJuIHBhcnNlTWVtYmVycyhnZXRNYW5kYXRvcnlOYW1lZEdyb3VwKG1hdGNoLCAna2V5d29yZCcpLCBnZXRNYW5kYXRvcnlOYW1lZEdyb3VwKG1hdGNoLCAnYm9keScpKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZWFkcyBhbmQgY2FjaGVzIHRoZSBkZW1vIGNvcnB1cyBcdTIwMTQgZXZlcnkgYCoubWRgIG5vdGUgaW4gdGhlIGRlbW8gdmF1bHQgam9pbmVkIGludG8gb25lIHN0cmluZy5cbiAgICpcbiAgICogQHJldHVybnMgVGhlIGNvbmNhdGVuYXRlZCBkZW1vLW5vdGUgY29udGVudHMuXG4gICAqL1xuICBwdWJsaWMgcmVhZENvcnB1cygpOiBzdHJpbmcge1xuICAgIHRoaXMuY2FjaGVkQ29ycHVzID8/PSB0aGlzLmNvbGxlY3ROb3RlcygpXG4gICAgICAubWFwKChub3RlKSA9PiBub3RlLmNvbnRlbnQpXG4gICAgICAuam9pbignXFxuJyk7XG4gICAgcmV0dXJuIHRoaXMuY2FjaGVkQ29ycHVzO1xuICB9XG5cbiAgLy8gVGhlIG5vdGVzIHRoZSBhdXRob3JpbmcgY2hlY2tzIGFwcGx5IHRvOiBldmVyeSBub3RlIGV4Y2VwdCB0aGUgb25lcyBkZWNsYXJlZCBvdXRzaWRlIHRoZSBsZWFybmluZ1xuICAvLyBwYXRoICh0aGUgdmF1bHQncyBvd24gYFJFQURNRS5tZGAgYnkgZGVmYXVsdCkuXG4gIHByaXZhdGUgY29sbGVjdENoZWNrYWJsZU5vdGVzKCk6IERlbW9WYXVsdE5vdGVbXSB7XG4gICAgcmV0dXJuIHRoaXMuY29sbGVjdE5vdGVzKCkuZmlsdGVyKChub3RlKSA9PiAhdGhpcy5leGNsdWRlZE5vdGVzLmhhcyhub3RlLnJlbGF0aXZlUGF0aCkpO1xuICB9XG5cbiAgcHJpdmF0ZSBjb2xsZWN0TWFya2Rvd25GaWxlcyhmb2xkZXI6IHN0cmluZyk6IHN0cmluZ1tdIHtcbiAgICBjb25zdCByZXN1bHQ6IHN0cmluZ1tdID0gW107XG4gICAgZm9yIChjb25zdCBlbnRyeSBvZiByZWFkZGlyU3luYyhmb2xkZXIsIHsgd2l0aEZpbGVUeXBlczogdHJ1ZSB9KSkge1xuICAgICAgaWYgKGVudHJ5LmlzRGlyZWN0b3J5KCkpIHtcbiAgICAgICAgaWYgKGVudHJ5Lm5hbWUgPT09IE9ic2lkaWFuUGx1Z2luUmVwb1BhdGhzLk5vZGVNb2R1bGVzIGFzIHN0cmluZykge1xuICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICB9XG4gICAgICAgIHJlc3VsdC5wdXNoKC4uLnRoaXMuY29sbGVjdE1hcmtkb3duRmlsZXMoam9pbihmb2xkZXIsIGVudHJ5Lm5hbWUpKSk7XG4gICAgICB9IGVsc2UgaWYgKGVudHJ5Lm5hbWUuZW5kc1dpdGgoJy5tZCcpKSB7XG4gICAgICAgIHJlc3VsdC5wdXNoKGpvaW4oZm9sZGVyLCBlbnRyeS5uYW1lKSk7XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiByZXN1bHQ7XG4gIH1cbn1cblxuLyoqXG4gKiBSZWdpc3RlcnMgYSBgdml0ZXN0YCBzdWl0ZSB0aGF0IGtlZXBzIGEgcGx1Z2luJ3MgaW4tcmVwbyBgZGVtby12YXVsdC9gIGluIHN5bmMgd2l0aCBpdHMgcHVibGljIHN1cmZhY2UuXG4gKlxuICogQ2FsbCBpdCBvbmNlIGZyb20gYSBwbHVnaW4ncyBgZGVtby12YXVsdC5uby1hcHAuaW50ZWdyYXRpb24udGVzdC50c2A7IGl0IHJlZ2lzdGVycyBvbmUgdGVzdCBwZXIgY2hlY2ssXG4gKiBkZWxlZ2F0aW5nIHRvIHtAbGluayBEZW1vVmF1bHRDb3ZlcmFnZUNoZWNrZXJ9LlxuICpcbiAqIEBwYXJhbSBwYXJhbXMgLSBUaGUgZGVjbGFyYXRpdmUgY292ZXJhZ2Ugc3BlY2lmaWNhdGlvbi5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHJlZ2lzdGVyRGVtb1ZhdWx0Q292ZXJhZ2VTdWl0ZShwYXJhbXM6IFJlZ2lzdGVyRGVtb1ZhdWx0Q292ZXJhZ2VTdWl0ZVBhcmFtcyk6IHZvaWQge1xuICBjb25zdCBjaGVja2VyID0gbmV3IERlbW9WYXVsdENvdmVyYWdlQ2hlY2tlcihub3JtYWxpemVPcHRpb25hbFByb3BlcnRpZXM8RGVtb1ZhdWx0Q292ZXJhZ2VDaGVja2VyQ29uc3RydWN0b3JQYXJhbXM+KHtcbiAgICBleGNsdWRlZE5vdGVzOiBwYXJhbXMuYXV0aG9yaW5nPy5leGNsdWRlZE5vdGVzLFxuICAgIHJvb3RGb2xkZXI6IHBhcmFtcy5yb290Rm9sZGVyXG4gIH0pKTtcbiAgY29uc3Qgc3RhcnROb3RlID0gcGFyYW1zLmF1dGhvcmluZz8uc3RhcnROb3RlID8/IERFRkFVTFRfU1RBUlRfTk9URTtcblxuICBkZXNjcmliZSgnZGVtby12YXVsdCBjb3ZlcmFnZScsICgpID0+IHtcbiAgICBmb3IgKGNvbnN0IHNwZWMgb2YgcGFyYW1zLmludGVyZmFjZXMgPz8gW10pIHtcbiAgICAgIGl0KGBkZW1vbnN0cmF0ZXMgZXZlcnkgJHtzcGVjLmludGVyZmFjZU5hbWV9ICR7c3BlYy5raW5kfWAsICgpID0+IHtcbiAgICAgICAgY29uc3QgbWVtYmVycyA9IGNoZWNrZXIuZ2V0SW50ZXJmYWNlTWVtYmVycyhzcGVjKTtcbiAgICAgICAgY29uc3QgZGVtb25zdHJhdGVkID0gbWVtYmVyc1tzcGVjLmtpbmRdO1xuICAgICAgICBleHBlY3QoZGVtb25zdHJhdGVkLmxlbmd0aCkudG9CZUdyZWF0ZXJUaGFuKDApO1xuICAgICAgICBleHBlY3QoY2hlY2tlci5maW5kVW5kZW1vbnN0cmF0ZWRNZW1iZXJzKHsgbWVtYmVyczogZGVtb25zdHJhdGVkLCByZWNlaXZlcjogc3BlYy5yZWNlaXZlciB9KSkudG9FcXVhbChbXSk7XG4gICAgICB9KTtcblxuICAgICAgaXQoYHJlZmVyZW5jZXMgbm8gJHtzcGVjLmludGVyZmFjZU5hbWV9IG1lbWJlciB0aGF0IG5vIGxvbmdlciBleGlzdHNgLCAoKSA9PiB7XG4gICAgICAgIGNvbnN0IG1lbWJlcnMgPSBjaGVja2VyLmdldEludGVyZmFjZU1lbWJlcnMoc3BlYyk7XG4gICAgICAgIGV4cGVjdChjaGVja2VyLmZpbmRTdGFsZVJlZmVyZW5jZXMoeyByZWNlaXZlcjogc3BlYy5yZWNlaXZlciwgdmFsaWRNZW1iZXJzOiBtZW1iZXJzLmFsbCB9KSkudG9FcXVhbChbXSk7XG4gICAgICB9KTtcbiAgICB9XG5cbiAgICBmb3IgKGNvbnN0IHNwZWMgb2YgcGFyYW1zLmNvbmZpZ0ludGVyZmFjZXMgPz8gW10pIHtcbiAgICAgIGl0KGBkZW1vbnN0cmF0ZXMgZXZlcnkgJHtzcGVjLmludGVyZmFjZU5hbWV9IG9wdGlvbmAsICgpID0+IHtcbiAgICAgICAgY29uc3QgbWVtYmVycyA9IGNoZWNrZXIuZ2V0SW50ZXJmYWNlTWVtYmVycyhzcGVjKTtcbiAgICAgICAgZXhwZWN0KG1lbWJlcnMucHJvcGVydGllcy5sZW5ndGgpLnRvQmVHcmVhdGVyVGhhbigwKTtcbiAgICAgICAgZXhwZWN0KGNoZWNrZXIuZmluZFVuZGVtb25zdHJhdGVkTWVtYmVycyh7IG1lbWJlcnM6IG1lbWJlcnMucHJvcGVydGllcyB9KSkudG9FcXVhbChbXSk7XG4gICAgICB9KTtcbiAgICB9XG5cbiAgICBmb3IgKGNvbnN0IHNwZWMgb2YgcGFyYW1zLmZ1bmN0aW9uTW9kdWxlcyA/PyBbXSkge1xuICAgICAgaXQoYGRlbW9uc3RyYXRlcyBldmVyeSBleHBvcnRlZCBmdW5jdGlvbiBpbiAke3NwZWMuc291cmNlUGF0aH1gLCAoKSA9PiB7XG4gICAgICAgIGNvbnN0IGZ1bmN0aW9uTmFtZXMgPSBjaGVja2VyLmdldEV4cG9ydGVkRnVuY3Rpb25OYW1lcyhzcGVjKTtcbiAgICAgICAgZXhwZWN0KGZ1bmN0aW9uTmFtZXMubGVuZ3RoKS50b0JlR3JlYXRlclRoYW4oMCk7XG4gICAgICAgIGV4cGVjdChjaGVja2VyLmZpbmRVbmRlbW9uc3RyYXRlZE1lbWJlcnMoeyBtZW1iZXJzOiBmdW5jdGlvbk5hbWVzIH0pKS50b0VxdWFsKFtdKTtcbiAgICAgIH0pO1xuICAgIH1cblxuICAgIGNvbnN0IGRvY3MgPSBwYXJhbXMuZG9jcztcbiAgICBpZiAoZG9jcykge1xuICAgICAgaXQoJ2xpbmtzIGEgZGVtbyBub3RlIGZvciBldmVyeSBmZWF0dXJlIGRvYycsICgpID0+IHtcbiAgICAgICAgZXhwZWN0KGNoZWNrZXIuZmluZFVubGlua2VkRmVhdHVyZURvY3MoeyBkb2NzRm9sZGVyOiBkb2NzLmZvbGRlciwgbm9uRmVhdHVyZURvY3M6IGRvY3Mubm9uRmVhdHVyZURvY3MgfSkpXG4gICAgICAgICAgLnRvRXF1YWwoW10pO1xuICAgICAgfSk7XG4gICAgfVxuXG4gICAgaXQoJ29wZW5zIGV2ZXJ5IG5vdGUgd2l0aCBhbiBIMScsICgpID0+IHtcbiAgICAgIGV4cGVjdChjaGVja2VyLmZpbmROb3Rlc1dpdGhvdXRIMSgpKS50b0VxdWFsKFtdKTtcbiAgICB9KTtcblxuICAgIGl0KCdvcGVucyBldmVyeSBub3RlIHdpdGggYSBwcm9zZSBwYXJhZ3JhcGggYmVmb3JlIGl0cyBmaXJzdCBjb2RlIGJsb2NrJywgKCkgPT4ge1xuICAgICAgZXhwZWN0KGNoZWNrZXIuZmluZE5vdGVzV2l0aG91dEludHJvUHJvc2UoKSkudG9FcXVhbChbXSk7XG4gICAgfSk7XG5cbiAgICBpdChgcmVhY2hlcyBldmVyeSBub3RlIGZyb20gJHtzdGFydE5vdGV9YCwgKCkgPT4ge1xuICAgICAgZXhwZWN0KGNoZWNrZXIuZmluZFVucmVhY2hhYmxlTm90ZXMoeyBzdGFydE5vdGUgfSkpLnRvRXF1YWwoW10pO1xuICAgIH0pO1xuXG4gICAgaXQoJ3VzZXMgbm8gd2lraWxpbmtzLCB3aGljaCBkbyBub3QgcmVuZGVyIG9uIEdpdEh1YicsICgpID0+IHtcbiAgICAgIGV4cGVjdChjaGVja2VyLmZpbmROb3Rlc1dpdGhXaWtpbGlua3MoKSkudG9FcXVhbChbXSk7XG4gICAgfSk7XG5cbiAgICBpdCgnanVzdGlmaWVzIGV2ZXJ5IHdpa2lsaW5rIGFsbG93YW5jZSwgYW5kIGRlY2xhcmVzIG5vbmUgaXQgbm8gbG9uZ2VyIG5lZWRzJywgKCkgPT4ge1xuICAgICAgZXhwZWN0KGNoZWNrZXIuZmluZE5vdGVzV2l0aFVuanVzdGlmaWVkV2lraWxpbmtBbGxvd2FuY2UoKSkudG9FcXVhbChbXSk7XG4gICAgfSk7XG5cbiAgICBpdCgnY2FycmllcyBubyBEb2NzIGxpbmsgbGluZSwgYmVjYXVzZSB0aGUgbm90ZSBpcyB0aGUgZG9jcycsICgpID0+IHtcbiAgICAgIGV4cGVjdChjaGVja2VyLmZpbmROb3Rlc1dpdGhEb2NzTGlua3MoKSkudG9FcXVhbChbXSk7XG4gICAgfSk7XG5cbiAgICBpdCgnY29tbWl0cyBub25lIG9mIHRoZSBhcHAuanNvbiBzZXR0aW5ncyBvYnNpZGlhbi1kZXYtdXRpbHMgaW5qZWN0cyBhdCByZWxlYXNlIHRpbWUnLCAoKSA9PiB7XG4gICAgICBleHBlY3QoY2hlY2tlci5maW5kQ29tbWl0dGVkQXBwSnNvblNldHRpbmdzKCkpLnRvRXF1YWwoW10pO1xuICAgIH0pO1xuXG4gICAgLy8gV2l0aCBubyBub3RlcyB0byByZWFkLCBldmVyeSBhdXRob3JpbmcgY2hlY2sgYWJvdmUgcGFzc2VzIGJ5IGhhdmluZyBub3RoaW5nIHRvIGxvb2sgYXQsIHNvIGEgdmF1bHRcbiAgICAvLyB0aGF0IHN0b3BwZWQgYmVpbmcgZm91bmQgd291bGQgZ28gb24gcmVwb3J0aW5nIGl0c2VsZiBjbGVhbi4gVGhpcyBpcyB0aGUgaGFsZiBvZiB0aGUgbm9uLXRyaXZpYWxcbiAgICAvLyBndWFyZCB0aGF0IHN0aWxsIGFwcGxpZXMgd2hlbiB0aGUgcGx1Z2luIGV4cG9zZXMgbm90aGluZyB0byByZWZsZWN0LlxuICAgIGl0KCdyZWFkcyBhIG5vbi1lbXB0eSBkZW1vIHZhdWx0JywgKCkgPT4ge1xuICAgICAgZXhwZWN0KGNoZWNrZXIuY29sbGVjdERlbW9Ob3RlUmVsYXRpdmVQYXRocygpLmxlbmd0aCkudG9CZUdyZWF0ZXJUaGFuKDApO1xuICAgIH0pO1xuXG4gICAgY29uc3QgZ3VhcmQgPSBwYXJhbXMubm9uVHJpdmlhbEd1YXJkO1xuICAgIGlmIChndWFyZCkge1xuICAgICAgaXQoJ2tlZXBzIHRoZSByZWZsZWN0ZWQgc3VyZmFjZSBub24tdHJpdmlhbCcsICgpID0+IHtcbiAgICAgICAgY29uc3QgbWVtYmVycyA9IGNoZWNrZXIuZ2V0SW50ZXJmYWNlTWVtYmVycyhndWFyZCk7XG4gICAgICAgIGV4cGVjdChtZW1iZXJzLmFsbCkudG9Db250YWluKGd1YXJkLmV4cGVjdE1lbWJlcik7XG4gICAgICAgIGV4cGVjdChjaGVja2VyLmNvbGxlY3REZW1vTm90ZVJlbGF0aXZlUGF0aHMoKSkudG9Db250YWluKGd1YXJkLmV4cGVjdERlbW9Ob3RlKTtcbiAgICAgIH0pO1xuICAgIH1cbiAgfSk7XG59XG5cbmNvbnN0IENMQVNTX01FTUJFUl9NT0RJRklFUlMgPSBTdHJpbmcucmF3YCg/Oig/OnB1YmxpY3xwcml2YXRlfHByb3RlY3RlZHxyZWFkb25seXxzdGF0aWN8YWJzdHJhY3R8b3ZlcnJpZGUpXFxzKykqYDtcbmNvbnN0IEFCU09MVVRFX1VSTF9SRUdfRVhQID0gL15bYS16XVtcXHcrLi1dKjovaTtcbmNvbnN0IEFSUk9XX1JFR19FWFAgPSAvXlxccyo9Pi87XG5jb25zdCBGVU5DVElPTl9UWVBFX1BBUkFNRVRFUlNfUkVHX0VYUCA9IC9ePFtePl0qPlxccyovO1xuY29uc3QgQU5HTEVfQlJBQ0tFVFNfUkVHX0VYUCA9IC9ePHw+JC9nO1xuY29uc3QgQ09ERV9GRU5DRV9SRUdfRVhQID0gL15cXHMqKD86YGBgfH5+fikvO1xuY29uc3QgREVGQVVMVF9FWENMVURFRF9OT1RFUyA9IFsnUkVBRE1FLm1kJ107XG5jb25zdCBERUZBVUxUX1NUQVJUX05PVEUgPSAnMDAgU3RhcnQubWQnO1xuY29uc3QgRE9DU19MSU5LX1JFR19FWFAgPSAvXlxccypcXFtEb2NzXVxcKC87XG5jb25zdCBGUk9OVE1BVFRFUl9SRUdfRVhQID0gL14tLS1cXHI/XFxuW1xcc1xcU10qP1xccj9cXG4tLS1bXlxcU1xcbl0qXFxyP1xcbj8vO1xuY29uc3QgSDFfUkVHX0VYUCA9IC9eIyBcXFMvO1xuY29uc3QgSEVBRElOR19SRUdfRVhQID0gL14jezEsNn0gLztcbmNvbnN0IElOTElORV9DT0RFX1JFR19FWFAgPSAvYFteYFxcbl0qYC9nO1xuY29uc3QgTUFSS0RPV05fTElOS19SRUdfRVhQID0gL1xcW1teXFxdXSpdXFwoKD88dGFyZ2V0PlteKV0rKVxcKS9nO1xuLy8gQW4gaW5saW5lIGRpcmVjdGl2ZSwgc2hhcGVkIGFmdGVyIEVTTGludCdzIGFuZCB3cml0dGVuIGFzIGFuIEhUTUwgY29tbWVudCBzbyBpdCBpcyBpbnZpc2libGUgQk9USCBpblxuLy8gT2JzaWRpYW4gYW5kIG9uIEdpdEh1YiBcdTIwMTQgdGhlIHNhbWUgc3BlbGxpbmcgdGhlIHZhdWx0cyBhbHJlYWR5IHVzZSBmb3IgYG1hcmtkb3dubGludC1kaXNhYmxlLW5leHQtbGluZWAuXG4vLyBBbiBPYnNpZGlhbiBgJSUgXHUyMDI2ICUlYCBjb21tZW50IHdvdWxkIHNob3cgdXAgYXMgbGl0ZXJhbCB0ZXh0IG9uIEdpdEh1Yiwgd2hpY2ggaXMgaGFsZiB0aGUgcmVhZGVyc2hpcC5cbmNvbnN0IERJUkVDVElWRV9SRUdfRVhQID0gL15cXHMqPCEtLVxccypvYnNpZGlhbi1kZXYtdXRpbHMtKD88YWN0aW9uPmRpc2FibGUtbmV4dC1saW5lfGRpc2FibGV8ZW5hYmxlKVxccysoPzxydWxlPltcXHctXStcXC9bXFx3LV0rKSg/OlxccystLVxccysoPzxyZWFzb24+Lio/KSk/XFxzKi0tPlxccyokLztcbi8vIENhdGNoZXMgYSBkaXJlY3RpdmUgdGhhdCB3YXMgTUVBTlQgdG8gYmUgb25lIGJ1dCBpcyBtaXNzcGVsbGVkOiBpdCB3b3VsZCBvdGhlcndpc2UgcmVhZCBhcyBhbiBvcmRpbmFyeVxuLy8gY29tbWVudCBhbmQgc2lsZW50bHkgZG8gbm90aGluZywgd2hpY2ggaXMgdGhlIGZhaWx1cmUgbW9kZSBhIHN1cHByZXNzaW9uIHN5bnRheCBtdXN0IG5ldmVyIGhhdmUuXG5jb25zdCBESVJFQ1RJVkVfUFJPQkVfUkVHX0VYUCA9IC88IS0tXFxzKm9ic2lkaWFuLWRldi11dGlscy0vO1xuY29uc3QgV0lLSUxJTktfUlVMRSA9ICdkZW1vLXZhdWx0LXZhbGlkYXRpb24vbm8td2lraWxpbmtzJztcbi8vIFRoZSBgb2JzaWRpYW4tZGV2LXV0aWxzID4gZGVtby12YXVsdC12YWxpZGF0aW9uID4gYWxsb3ctd2lraWxpbmtzYCBmcm9udG1hdHRlciBwYXRoLCBhdCBhbnkgaW5kZW50YXRpb246XG4vLyBUaGUga2V5cyBtdXN0IG5lc3QgaW4gdGhhdCBvcmRlciwgYW5kIGFueSBsaW5lIGJldHdlZW4gdGhlbSBoYXMgdG8gc3RheSBpbmRlbnRlZCwgc28gYSBkZWRlbnQgdG8gdGhlXG4vLyBkb2N1bWVudCdzIG93biB0b3AgbGV2ZWwgZW5kcyB0aGUgbWF0Y2ggcmF0aGVyIHRoYW4gcmVhY2hpbmcgYSBzYW1lLW5hbWVkIGtleSB1bmRlciBhbm90aGVyIHBhcmVudC5cbmNvbnN0IFdJS0lMSU5LX0FMTE9XQU5DRV9SRUdfRVhQID0gL15vYnNpZGlhbi1kZXYtdXRpbHM6W15cXFNcXG5dKlxcbig/OlteXFxTXFxuXSsuKlxcbikqP1teXFxTXFxuXStkZW1vLXZhdWx0LXZhbGlkYXRpb246W15cXFNcXG5dKlxcbig/OlteXFxTXFxuXSsuKlxcbikqP1teXFxTXFxuXSthbGxvdy13aWtpbGlua3M6KD88cmVhc29uPi4qKSQvbTtcbmNvbnN0IFdJS0lMSU5LX1JFR19FWFAgPSAvXFxbXFxbW15cXF1dK11dLztcblxuLy8gQXBwbGllcyBvbmUgcGFyc2VkIGRpcmVjdGl2ZSB0byB0aGUgc2Nhbi5cbmZ1bmN0aW9uIGFwcGx5V2lraWxpbmtEaXJlY3RpdmUoc3RhdGU6IFdpa2lsaW5rRGlyZWN0aXZlU2NhblN0YXRlLCBsaW5lSW5kZXg6IG51bWJlciwgbWF0Y2g6IFJlZ0V4cEV4ZWNBcnJheSk6IHZvaWQge1xuICBjb25zdCBhY3Rpb24gPSBnZXRNYW5kYXRvcnlOYW1lZEdyb3VwKG1hdGNoLCAnYWN0aW9uJyk7XG4gIGNvbnN0IHJ1bGUgPSBnZXRNYW5kYXRvcnlOYW1lZEdyb3VwKG1hdGNoLCAncnVsZScpO1xuICBjb25zdCByZWFzb24gPSBtYXRjaC5ncm91cHM/LlsncmVhc29uJ10/LnRyaW0oKSA/PyAnJztcbiAgaWYgKHJ1bGUgIT09IFdJS0lMSU5LX1JVTEUpIHtcbiAgICBzdGF0ZS5wcm9ibGVtcy5wdXNoKGBhbiB1bmtub3duIHJ1bGUgXCIke3J1bGV9XCIgb24gJHtmb3JtYXRMaW5lTnVtYmVyKGxpbmVJbmRleCl9YCk7XG4gICAgcmV0dXJuO1xuICB9XG4gIGlmIChhY3Rpb24gIT09ICdlbmFibGUnICYmIHJlYXNvbiA9PT0gJycpIHtcbiAgICBzdGF0ZS5wcm9ibGVtcy5wdXNoKGBhIGRpcmVjdGl2ZSB3aXRoIG5vIHJlYXNvbiBvbiAke2Zvcm1hdExpbmVOdW1iZXIobGluZUluZGV4KX1gKTtcbiAgICByZXR1cm47XG4gIH1cblxuICBpZiAoYWN0aW9uID09PSAnZGlzYWJsZS1uZXh0LWxpbmUnKSB7XG4gICAgc3RhdGUucGVuZGluZ05leHRMaW5lSW5kZXggPSBsaW5lSW5kZXg7XG4gICAgcmV0dXJuO1xuICB9XG5cbiAgaWYgKGFjdGlvbiA9PT0gJ2Rpc2FibGUnKSB7XG4gICAgaWYgKHN0YXRlLm9wZW5SZWdpb24pIHtcbiAgICAgIHN0YXRlLnByb2JsZW1zLnB1c2goYGEgZGlzYWJsZSBvbiAke2Zvcm1hdExpbmVOdW1iZXIobGluZUluZGV4KX0gaW5zaWRlIHRoZSByZWdpb24gb3BlbmVkIG9uICR7Zm9ybWF0TGluZU51bWJlcihzdGF0ZS5vcGVuUmVnaW9uLmxpbmVJbmRleCl9YCk7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIHN0YXRlLm9wZW5SZWdpb24gPSB7IGlzVXNlZDogZmFsc2UsIGxpbmVJbmRleCB9O1xuICAgIHJldHVybjtcbiAgfVxuXG4gIGlmICghc3RhdGUub3BlblJlZ2lvbikge1xuICAgIHN0YXRlLnByb2JsZW1zLnB1c2goYGFuIGVuYWJsZSBvbiAke2Zvcm1hdExpbmVOdW1iZXIobGluZUluZGV4KX0gd2l0aCBubyByZWdpb24gb3BlbmApO1xuICAgIHJldHVybjtcbiAgfVxuICBpZiAoIXN0YXRlLm9wZW5SZWdpb24uaXNVc2VkKSB7XG4gICAgc3RhdGUucHJvYmxlbXMucHVzaChgYSByZWdpb24gb3BlbmVkIG9uICR7Zm9ybWF0TGluZU51bWJlcihzdGF0ZS5vcGVuUmVnaW9uLmxpbmVJbmRleCl9IGNvdmVyaW5nIG5vIHdpa2lsaW5rYCk7XG4gIH1cbiAgc3RhdGUub3BlblJlZ2lvbiA9IG51bGw7XG59XG5cbi8vIEFwcGxpZXMgb25lIG9yZGluYXJ5IGxpbmUgdG8gdGhlIHNjYW46IGFuIG9wZW4gcmVnaW9uIGNvdmVycyBpdCwgYW5kIGEgcGVuZGluZyBgZGlzYWJsZS1uZXh0LWxpbmVgXG4vLyBjbGFpbXMgdGhlIGZpcnN0IGxpbmUgd2l0aCBjb250ZW50IG9uIGl0IFx1MjAxNCB0aGUgZGlyZWN0aXZlIGFuZCBpdHMgdGFyZ2V0IGFyZSB1c3VhbGx5IGEgYmxhbmsgbGluZSBhcGFydC5cbmZ1bmN0aW9uIGFwcGx5V2lraWxpbmtTY2FuTGluZShzdGF0ZTogV2lraWxpbmtEaXJlY3RpdmVTY2FuU3RhdGUsIGxpbmVJbmRleDogbnVtYmVyLCBsaW5lOiBzdHJpbmcpOiB2b2lkIHtcbiAgaWYgKHN0YXRlLm9wZW5SZWdpb24pIHtcbiAgICBzdGF0ZS5hbGxvd2VkTGluZUluZGV4ZXMuYWRkKGxpbmVJbmRleCk7XG4gICAgc3RhdGUub3BlblJlZ2lvbi5pc1VzZWQgfHw9IHN0YXRlLndpa2lsaW5rTGluZUluZGV4ZXMuaGFzKGxpbmVJbmRleCk7XG4gICAgcmV0dXJuO1xuICB9XG4gIGlmIChzdGF0ZS5wZW5kaW5nTmV4dExpbmVJbmRleCA9PT0gbnVsbCB8fCBsaW5lLnRyaW0oKSA9PT0gJycpIHtcbiAgICByZXR1cm47XG4gIH1cbiAgc3RhdGUuYWxsb3dlZExpbmVJbmRleGVzLmFkZChsaW5lSW5kZXgpO1xuICBpZiAoIXN0YXRlLndpa2lsaW5rTGluZUluZGV4ZXMuaGFzKGxpbmVJbmRleCkpIHtcbiAgICBzdGF0ZS5wcm9ibGVtcy5wdXNoKGBhIGRpc2FibGUtbmV4dC1saW5lIG9uICR7Zm9ybWF0TGluZU51bWJlcihzdGF0ZS5wZW5kaW5nTmV4dExpbmVJbmRleCl9IGNvdmVyaW5nIG5vIHdpa2lsaW5rYCk7XG4gIH1cbiAgc3RhdGUucGVuZGluZ05leHRMaW5lSW5kZXggPSBudWxsO1xufVxuXG5mdW5jdGlvbiBidWlsZE1lbWJlcnMobWV0aG9kczogc3RyaW5nW10sIHByb3BlcnRpZXM6IHN0cmluZ1tdKTogSW50ZXJmYWNlTWVtYmVycyB7XG4gIHJldHVybiB7XG4gICAgYWxsOiBbLi4ubWV0aG9kcywgLi4ucHJvcGVydGllc10sXG4gICAgbWV0aG9kcyxcbiAgICBwcm9wZXJ0aWVzXG4gIH07XG59XG5cbi8vIFJlc29sdmVzIHRoZSBub3RlcyBhIG5vdGUgbGlua3MgdG86IGV2ZXJ5IE1hcmtkb3duIGxpbmsgb3V0c2lkZSBhIGNvZGUgZmVuY2Ugd2hvc2UgdGFyZ2V0IGlzIGEgYC5tZGBcbi8vIGZpbGUsIG1hZGUgcmVsYXRpdmUgdG8gdGhlIGRlbW8gdmF1bHQgc28gaXQgY2FuIGJlIGxvb2tlZCB1cCBpbiB0aGUgbm90ZSBtYXAuIEV4dGVybmFsIFVSTHMgYW5kXG4vLyBub24tbm90ZSB0YXJnZXRzIChpbWFnZXMsIHNjcmlwdHMpIGFyZSBub3QgcGFydCBvZiB0aGUgbGVhcm5pbmcgcGF0aCBhbmQgYXJlIHNraXBwZWQ7IGEgYCNhbmNob3JgIGlzXG4vLyBkcm9wcGVkLCBzaW5jZSBpdCBhZGRyZXNzZXMgYSBwbGFjZSBpbnNpZGUgYW4gYWxyZWFkeS1yZXNvbHZlZCBub3RlLlxuLy8gUmV0dXJucyB0aGUgbm90ZSdzIGxpbmVzIHdpdGggZmVuY2VkIGNvZGUgYmxvY2tzIHJlbW92ZWQgKHRoZSBmZW5jZSBsaW5lcyBpbmNsdWRlZCksIHBhaXJlZCB3aXRoIHRoZVxuLy8gbGluZSBudW1iZXIgZWFjaCBjYW1lIGZyb20sIHNvIGEgY2hlY2sgbmV2ZXIgbWlzdGFrZXMgc2FtcGxlIGNvZGUgZm9yIHByb3NlIFx1MjAxNCBhIGBbW3dpa2lsaW5rXV1gXG4vLyBkZW1vbnN0cmF0ZWQgaW5zaWRlIGEgZmVuY2UgaXMgdGV4dCwgbm90IG5hdmlnYXRpb24gXHUyMDE0IGFuZCBhbiBpbmxpbmUgZGlyZWN0aXZlIGNhbiBzdGlsbCBuYW1lIGEgbGluZS5cbmZ1bmN0aW9uIGNvbGxlY3RMaW5lc091dHNpZGVGZW5jZXMoY29udGVudDogc3RyaW5nKTogTm90ZUxpbmVbXSB7XG4gIGNvbnN0IG5vdGVMaW5lczogTm90ZUxpbmVbXSA9IFtdO1xuICBsZXQgaXNJbnNpZGVGZW5jZSA9IGZhbHNlO1xuICBmb3IgKGNvbnN0IFtpbmRleCwgbGluZV0gb2YgY29udGVudC5zcGxpdCgnXFxuJykuZW50cmllcygpKSB7XG4gICAgaWYgKENPREVfRkVOQ0VfUkVHX0VYUC50ZXN0KGxpbmUpKSB7XG4gICAgICBpc0luc2lkZUZlbmNlID0gIWlzSW5zaWRlRmVuY2U7XG4gICAgICBjb250aW51ZTtcbiAgICB9XG4gICAgaWYgKCFpc0luc2lkZUZlbmNlKSB7XG4gICAgICBub3RlTGluZXMucHVzaCh7IGluZGV4LCBsaW5lIH0pO1xuICAgIH1cbiAgfVxuICByZXR1cm4gbm90ZUxpbmVzO1xufVxuXG5mdW5jdGlvbiBjb2xsZWN0Tm90ZUxpbmtUYXJnZXRzKG5vdGU6IERlbW9WYXVsdE5vdGUpOiBzdHJpbmdbXSB7XG4gIGNvbnN0IHRhcmdldHM6IHN0cmluZ1tdID0gW107XG4gIGZvciAoY29uc3QgbGluZSBvZiBnZXRMaW5lc091dHNpZGVGZW5jZXMobm90ZS5jb250ZW50KSkge1xuICAgIGZvciAoY29uc3QgbWF0Y2ggb2Ygc3RyaXBJbmxpbmVDb2RlKGxpbmUpLm1hdGNoQWxsKE1BUktET1dOX0xJTktfUkVHX0VYUCkpIHtcbiAgICAgIGNvbnN0IHRhcmdldCA9IGdldE1hbmRhdG9yeU5hbWVkR3JvdXAobWF0Y2gsICd0YXJnZXQnKS5yZXBsYWNlQWxsKEFOR0xFX0JSQUNLRVRTX1JFR19FWFAsICcnKTtcbiAgICAgIGNvbnN0IFtub3RlUGF0aCA9ICcnXSA9IHRhcmdldC5zcGxpdCgnIycsIDEpO1xuICAgICAgaWYgKEFCU09MVVRFX1VSTF9SRUdfRVhQLnRlc3Qobm90ZVBhdGgpIHx8ICFub3RlUGF0aC50b0xvd2VyQ2FzZSgpLmVuZHNXaXRoKCcubWQnKSkge1xuICAgICAgICBjb250aW51ZTtcbiAgICAgIH1cbiAgICAgIHRhcmdldHMucHVzaChqb2luKGRpcm5hbWUobm90ZS5yZWxhdGl2ZVBhdGgpLCB0cnlEZWNvZGVVcmlDb21wb25lbnQobm90ZVBhdGgpKSk7XG4gICAgfVxuICB9XG4gIHJldHVybiB0YXJnZXRzO1xufVxuXG5mdW5jdGlvbiBleHRyYWN0Q2xhc3NNZXRob2ROYW1lcyhjbGFzc0JvZHk6IHN0cmluZyk6IHN0cmluZ1tdIHtcbiAgcmV0dXJuIFsuLi5jbGFzc0JvZHkubWF0Y2hBbGwobmV3IFJlZ0V4cChTdHJpbmcucmF3YF4gezJ9KD88bW9kaWZpZXJzPiR7Q0xBU1NfTUVNQkVSX01PRElGSUVSU30pKD88bmFtZT5cXHcrKSg/OjxbXj5dKj4pP1xcKGAsICdnbScpKV1cbiAgICAuZmlsdGVyKChtYXRjaCkgPT4gIWlzTm9uUHVibGljTWVtYmVyKGdldE1hbmRhdG9yeU5hbWVkR3JvdXAobWF0Y2gsICdtb2RpZmllcnMnKSkpXG4gICAgLm1hcCgobWF0Y2gpID0+IGdldE1hbmRhdG9yeU5hbWVkR3JvdXAobWF0Y2gsICduYW1lJykpO1xufVxuXG5mdW5jdGlvbiBleHRyYWN0Q2xhc3NQcm9wZXJ0eU5hbWVzKGNsYXNzQm9keTogc3RyaW5nKTogc3RyaW5nW10ge1xuICByZXR1cm4gWy4uLmNsYXNzQm9keS5tYXRjaEFsbChuZXcgUmVnRXhwKFN0cmluZy5yYXdgXiB7Mn0oPzxtb2RpZmllcnM+JHtDTEFTU19NRU1CRVJfTU9ESUZJRVJTfSkoPzxuYW1lPlxcdyspXFxzKlxcPz9cXHMqWzo9XWAsICdnbScpKV1cbiAgICAuZmlsdGVyKChtYXRjaCkgPT4gIWlzTm9uUHVibGljTWVtYmVyKGdldE1hbmRhdG9yeU5hbWVkR3JvdXAobWF0Y2gsICdtb2RpZmllcnMnKSkpXG4gICAgLm1hcCgobWF0Y2gpID0+IGdldE1hbmRhdG9yeU5hbWVkR3JvdXAobWF0Y2gsICduYW1lJykpO1xufVxuXG5mdW5jdGlvbiBleHRyYWN0RW51bU1lbWJlck5hbWVzKGVudW1Cb2R5OiBzdHJpbmcpOiBzdHJpbmdbXSB7XG4gIHJldHVybiBbLi4uZW51bUJvZHkubWF0Y2hBbGwoL14gezJ9KD88bmFtZT5cXHcrKS9nbSldLm1hcCgobWF0Y2gpID0+IGdldE1hbmRhdG9yeU5hbWVkR3JvdXAobWF0Y2gsICduYW1lJykpO1xufVxuXG4vLyBBIG1ldGhvZCBpcyBjYWxsYWJsZSBzdXJmYWNlIGhvd2V2ZXIgaXQgaXMgd3JpdHRlbjogYSBtZXRob2Qgc2lnbmF0dXJlIChgZm9vKGJhcjogc3RyaW5nKTogdm9pZDtgKSBvciBhXG4vLyBwcm9wZXJ0eSBzaWduYXR1cmUgd2hvc2UgdHlwZSBpcyBhIGZ1bmN0aW9uIHR5cGUgKGBmb286IChiYXI6IHN0cmluZykgPT4gdm9pZDtgKS4gVGhlIHNoYXJlZCBFU0xpbnQgY29uZmlnXG4vLyBydW5zIGBAdHlwZXNjcmlwdC1lc2xpbnQvbWV0aG9kLXNpZ25hdHVyZS1zdHlsZWAgYXQgaXRzIGBwcm9wZXJ0eWAgZGVmYXVsdCwgc28gYGxpbnQ6Zml4YCByZXdyaXRlcyB0aGVcbi8vIGZpcnN0IHNoYXBlIGludG8gdGhlIHNlY29uZCBcdTIwMTQgcmVhZGluZyBvbmx5IHRoZSBmaXJzdCByZXBvcnRlZCB6ZXJvIG1ldGhvZHMgZm9yIGV2ZXJ5IHN1Y2ggaW50ZXJmYWNlLlxuZnVuY3Rpb24gZXh0cmFjdE1ldGhvZE5hbWVzKGludGVyZmFjZUJvZHk6IHN0cmluZyk6IHN0cmluZ1tdIHtcbiAgY29uc3QgbWV0aG9kU2lnbmF0dXJlTmFtZXMgPSBbLi4uaW50ZXJmYWNlQm9keS5tYXRjaEFsbCgvXiB7Mn0oPzxuYW1lPlxcdyspKD86PFtePl0qPik/XFwoL2dtKV0ubWFwKChtYXRjaCkgPT4gZ2V0TWFuZGF0b3J5TmFtZWRHcm91cChtYXRjaCwgJ25hbWUnKSk7XG4gIGNvbnN0IGZ1bmN0aW9uUHJvcGVydHlOYW1lcyA9IG1hdGNoUHJvcGVydHlTaWduYXR1cmVzKGludGVyZmFjZUJvZHkpXG4gICAgLmZpbHRlcigobWF0Y2gpID0+IGlzRnVuY3Rpb25UeXBlKGludGVyZmFjZUJvZHksIG1hdGNoKSlcbiAgICAubWFwKChtYXRjaCkgPT4gZ2V0TWFuZGF0b3J5TmFtZWRHcm91cChtYXRjaCwgJ25hbWUnKSk7XG4gIHJldHVybiBbLi4ubWV0aG9kU2lnbmF0dXJlTmFtZXMsIC4uLmZ1bmN0aW9uUHJvcGVydHlOYW1lc107XG59XG5cbi8vIEV2ZXJ5IHByb3BlcnR5IHNpZ25hdHVyZSB3aG9zZSB0eXBlIGlzIG5vdCBhIGZ1bmN0aW9uIHR5cGUsIHNvIG1ldGhvZHMgYW5kIHByb3BlcnRpZXMgc3RheSBhIHBhcnRpdGlvbi5cbmZ1bmN0aW9uIGV4dHJhY3RQcm9wZXJ0eU5hbWVzKGludGVyZmFjZUJvZHk6IHN0cmluZyk6IHN0cmluZ1tdIHtcbiAgcmV0dXJuIG1hdGNoUHJvcGVydHlTaWduYXR1cmVzKGludGVyZmFjZUJvZHkpXG4gICAgLmZpbHRlcigobWF0Y2gpID0+ICFpc0Z1bmN0aW9uVHlwZShpbnRlcmZhY2VCb2R5LCBtYXRjaCkpXG4gICAgLm1hcCgobWF0Y2gpID0+IGdldE1hbmRhdG9yeU5hbWVkR3JvdXAobWF0Y2gsICduYW1lJykpO1xufVxuXG4vLyBUaGUgbGluZSBudW1iZXJzIGNhcnJ5aW5nIGEgd2lraWxpbmsgdGhhdCBpcyBuYXZpZ2F0aW9uIHJhdGhlciB0aGFuIHNhbXBsZSB0ZXh0LlxuZnVuY3Rpb24gZmluZFdpa2lsaW5rTGluZUluZGV4ZXMoY29udGVudDogc3RyaW5nKTogbnVtYmVyW10ge1xuICByZXR1cm4gY29sbGVjdExpbmVzT3V0c2lkZUZlbmNlcyhjb250ZW50KVxuICAgIC5maWx0ZXIoKG5vdGVMaW5lKSA9PiBXSUtJTElOS19SRUdfRVhQLnRlc3Qoc3RyaXBJbmxpbmVDb2RlKG5vdGVMaW5lLmxpbmUpKSlcbiAgICAubWFwKChub3RlTGluZSkgPT4gbm90ZUxpbmUuaW5kZXgpO1xufVxuXG5mdW5jdGlvbiBmb3JtYXRMaW5lTnVtYmVyKGxpbmVJbmRleDogbnVtYmVyKTogc3RyaW5nIHtcbiAgcmV0dXJuIGBsaW5lICR7U3RyaW5nKGxpbmVJbmRleCArIDEpfWA7XG59XG5cbmZ1bmN0aW9uIGdldExpbmVzT3V0c2lkZUZlbmNlcyhjb250ZW50OiBzdHJpbmcpOiBzdHJpbmdbXSB7XG4gIHJldHVybiBjb2xsZWN0TGluZXNPdXRzaWRlRmVuY2VzKGNvbnRlbnQpLm1hcCgobm90ZUxpbmUpID0+IG5vdGVMaW5lLmxpbmUpO1xufVxuXG4vLyBXaGV0aGVyIHRoZSBub3RlJ3MgZmlyc3QgY29udGVudCBsaW5lIChmcm9udG1hdHRlciBhbmQgYmxhbmsgbGluZXMgYXNpZGUpIGlzIGFuIGAjIEgxYC5cbmZ1bmN0aW9uIGhhc0gxKGNvbnRlbnQ6IHN0cmluZyk6IGJvb2xlYW4ge1xuICBmb3IgKGNvbnN0IGxpbmUgb2Ygc3RyaXBGcm9udG1hdHRlcihjb250ZW50KS5zcGxpdCgnXFxuJykpIHtcbiAgICBjb25zdCB0cmltbWVkTGluZSA9IGxpbmUudHJpbSgpO1xuICAgIGlmICh0cmltbWVkTGluZSA9PT0gJycpIHtcbiAgICAgIGNvbnRpbnVlO1xuICAgIH1cbiAgICByZXR1cm4gSDFfUkVHX0VYUC50ZXN0KHRyaW1tZWRMaW5lKTtcbiAgfVxuICByZXR1cm4gZmFsc2U7XG59XG5cbi8vIFdoZXRoZXIgYSBwbGFpbiBwcm9zZSBsaW5lIGFwcGVhcnMgYmVmb3JlIHRoZSBub3RlJ3MgZmlyc3QgY29kZSBmZW5jZS4gSGVhZGluZ3MgYXJlIG5vdCBwcm9zZSBcdTIwMTQgYSBub3RlXG4vLyB0aGF0IGdvZXMgc3RyYWlnaHQgZnJvbSBpdHMgdGl0bGUgdG8gYSBidXR0b24gaXMgZXhhY3RseSB0aGUgc2hhcGUgdGhpcyBjaGVjayByZWplY3RzLlxuZnVuY3Rpb24gaGFzSW50cm9Qcm9zZShjb250ZW50OiBzdHJpbmcpOiBib29sZWFuIHtcbiAgZm9yIChjb25zdCBsaW5lIG9mIHN0cmlwRnJvbnRtYXR0ZXIoY29udGVudCkuc3BsaXQoJ1xcbicpKSB7XG4gICAgaWYgKENPREVfRkVOQ0VfUkVHX0VYUC50ZXN0KGxpbmUpKSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuICAgIGNvbnN0IHRyaW1tZWRMaW5lID0gbGluZS50cmltKCk7XG4gICAgaWYgKHRyaW1tZWRMaW5lID09PSAnJyB8fCBIRUFESU5HX1JFR19FWFAudGVzdCh0cmltbWVkTGluZSkpIHtcbiAgICAgIGNvbnRpbnVlO1xuICAgIH1cbiAgICByZXR1cm4gdHJ1ZTtcbiAgfVxuICByZXR1cm4gZmFsc2U7XG59XG5cbi8vIFdoZXRoZXIgdGhlIG5vdGUgbmF2aWdhdGVzIHdpdGggYW4gT2JzaWRpYW4gYFtbd2lraWxpbmtdXWAuIEZlbmNlZCBibG9ja3MgYW5kIGlubGluZSBjb2RlIGFyZSBzYW1wbGVcbi8vIHRleHQgcmF0aGVyIHRoYW4gbmF2aWdhdGlvbiwgc28gdGhleSBhcmUgcmVtb3ZlZCBiZWZvcmUgbG9va2luZy5cbmZ1bmN0aW9uIGhhc1dpa2lsaW5rKGNvbnRlbnQ6IHN0cmluZyk6IGJvb2xlYW4ge1xuICByZXR1cm4gZmluZFdpa2lsaW5rTGluZUluZGV4ZXMoY29udGVudCkubGVuZ3RoID4gMDtcbn1cblxuLy8gV2hldGhlciB0aGUgcHJvcGVydHkgc2lnbmF0dXJlJ3MgdHlwZSwgc3RhcnRpbmcgcmlnaHQgYWZ0ZXIgaXRzIGA6YCwgaXMgYSBmdW5jdGlvbiB0eXBlOiBhbiBvcHRpb25hbCB0eXBlXG4vLyBwYXJhbWV0ZXIgbGlzdCwgYSBwYXJhbWV0ZXIgbGlzdCwgdGhlbiBgPT5gLiBUaGUgcGFyYW1ldGVyIGxpc3QgaXMgd2Fsa2VkIGJ5IGJyYWNrZXQgZGVwdGggcmF0aGVyIHRoYW4gYnkgYVxuLy8gcmVndWxhciBleHByZXNzaW9uLCBzbyBhIHBhcmVudGhlc2l6ZWQgbm9uLWZ1bmN0aW9uIHR5cGUgKGAoc3RyaW5nIHwgbnVtYmVyKVtdYCkgYW5kIGEgcGFyYW1ldGVyIHdob3NlIG93blxuLy8gdHlwZSBob2xkcyBwYXJlbnRoZXNlcyAoYChjYWxsYmFjazogKCkgPT4gdm9pZCkgPT4gdm9pZGApIGFyZSBib3RoIHJlYWQgY29ycmVjdGx5LCBhY3Jvc3MgbGluZXMgdG9vLlxuZnVuY3Rpb24gaXNGdW5jdGlvblR5cGUoaW50ZXJmYWNlQm9keTogc3RyaW5nLCBtYXRjaDogUmVnRXhwRXhlY0FycmF5KTogYm9vbGVhbiB7XG4gIGxldCBpbmRleCA9IG1hdGNoLmluZGV4ICsgbWF0Y2hbMF0ubGVuZ3RoO1xuICBpbmRleCArPSBGVU5DVElPTl9UWVBFX1BBUkFNRVRFUlNfUkVHX0VYUC5leGVjKGludGVyZmFjZUJvZHkuc2xpY2UoaW5kZXgpKT8uWzBdLmxlbmd0aCA/PyAwO1xuICBpZiAoaW50ZXJmYWNlQm9keVtpbmRleF0gIT09ICcoJykge1xuICAgIHJldHVybiBmYWxzZTtcbiAgfVxuICBsZXQgZGVwdGggPSAwO1xuICBmb3IgKDsgaW5kZXggPCBpbnRlcmZhY2VCb2R5Lmxlbmd0aDsgaW5kZXgrKykge1xuICAgIGNvbnN0IGNoYXJhY3RlciA9IGludGVyZmFjZUJvZHlbaW5kZXhdO1xuICAgIGlmIChjaGFyYWN0ZXIgPT09ICcoJykge1xuICAgICAgZGVwdGgrKztcbiAgICB9IGVsc2UgaWYgKGNoYXJhY3RlciA9PT0gJyknKSB7XG4gICAgICBkZXB0aC0tO1xuICAgICAgaWYgKGRlcHRoID09PSAwKSB7XG4gICAgICAgIHJldHVybiBBUlJPV19SRUdfRVhQLnRlc3QoaW50ZXJmYWNlQm9keS5zbGljZShpbmRleCArIDEpKTtcbiAgICAgIH1cbiAgICB9XG4gIH1cbiAgcmV0dXJuIGZhbHNlO1xufVxuXG5mdW5jdGlvbiBpc05vblB1YmxpY01lbWJlcihtb2RpZmllcnM6IHN0cmluZyk6IGJvb2xlYW4ge1xuICByZXR1cm4gL1xcYig/OnByaXZhdGV8cHJvdGVjdGVkKVxcYi8udGVzdChtb2RpZmllcnMpO1xufVxuXG4vLyBgcmVhZG9ubHlgIGlzIHRoZSBvbmx5IG1vZGlmaWVyIGEgcHJvcGVydHkgc2lnbmF0dXJlIHRha2VzLCBhbmQgYSBtZXRob2Qgc2lnbmF0dXJlIHRha2VzIG5vbmUgXHUyMDE0IFR5cGVTY3JpcHRcbi8vIHJlamVjdHMgYHJlYWRvbmx5IGZvbygpOiB2b2lkO2AgXHUyMDE0IHNvIHRoZSBtZXRob2Qtc2lnbmF0dXJlIHJlZ2V4IG5lZWRzIG5vIGNvdW50ZXJwYXJ0LlxuZnVuY3Rpb24gbWF0Y2hQcm9wZXJ0eVNpZ25hdHVyZXMoaW50ZXJmYWNlQm9keTogc3RyaW5nKTogUmVnRXhwRXhlY0FycmF5W10ge1xuICByZXR1cm4gWy4uLmludGVyZmFjZUJvZHkubWF0Y2hBbGwoL14gezJ9KD86cmVhZG9ubHlcXHMrKT8oPzxuYW1lPlxcdyspXFw/PzpcXHMqL2dtKV07XG59XG5cbmZ1bmN0aW9uIHBhcnNlTWVtYmVycyhrZXl3b3JkOiBzdHJpbmcsIGJvZHk6IHN0cmluZyk6IEludGVyZmFjZU1lbWJlcnMge1xuICBzd2l0Y2ggKGtleXdvcmQpIHtcbiAgICBjYXNlICdjbGFzcyc6IHtcbiAgICAgIHJldHVybiBidWlsZE1lbWJlcnMoZXh0cmFjdENsYXNzTWV0aG9kTmFtZXMoYm9keSksIGV4dHJhY3RDbGFzc1Byb3BlcnR5TmFtZXMoYm9keSkpO1xuICAgIH1cbiAgICBjYXNlICdlbnVtJzoge1xuICAgICAgcmV0dXJuIGJ1aWxkTWVtYmVycyhbXSwgZXh0cmFjdEVudW1NZW1iZXJOYW1lcyhib2R5KSk7XG4gICAgfVxuICAgIGRlZmF1bHQ6IHtcbiAgICAgIHJldHVybiBidWlsZE1lbWJlcnMoZXh0cmFjdE1ldGhvZE5hbWVzKGJvZHkpLCBleHRyYWN0UHJvcGVydHlOYW1lcyhib2R5KSk7XG4gICAgfVxuICB9XG59XG5cbi8vIFJlYWRzIHRoZSBub3RlJ3MgYG9ic2lkaWFuLWRldi11dGlscyA+IGRlbW8tdmF1bHQtdmFsaWRhdGlvbiA+IGFsbG93LXdpa2lsaW5rc2AgZGVjbGFyYXRpb246IHRoZSBzdGF0ZWRcbi8vIHJlYXNvbiwgYCcnYCB3aGVuIHRoZSBrZXkgaXMgcHJlc2VudCB3aXRoIG5vdGhpbmcgYWZ0ZXIgaXQsIG9yIGBudWxsYCB3aGVuIHRoZSBub3RlIGRlY2xhcmVzIG5vdGhpbmcuXG4vLyBSZWFkIHdpdGggYSByZWd1bGFyIGV4cHJlc3Npb24gcmF0aGVyIHRoYW4gYSBZQU1MIHBhcnNlcjogaXQgaXMgb25lIGtub3duIGtleSBwYXRoLCBhbmQgZXZlcnkgcGx1Z2luIHRoYXRcbi8vIGluc3RhbGxzIHRoaXMgcGFja2FnZSB3b3VsZCBvdGhlcndpc2UgY2FycnkgYSBZQU1MIGRlcGVuZGVuY3kgZm9yIGl0LlxuZnVuY3Rpb24gcmVhZFdpa2lsaW5rQWxsb3dhbmNlUmVhc29uKGNvbnRlbnQ6IHN0cmluZyk6IG51bGwgfCBzdHJpbmcge1xuICBjb25zdCBmcm9udG1hdHRlciA9IEZST05UTUFUVEVSX1JFR19FWFAuZXhlYyhjb250ZW50KT8uWzBdO1xuICBpZiAoZnJvbnRtYXR0ZXIgPT09IHVuZGVmaW5lZCkge1xuICAgIHJldHVybiBudWxsO1xuICB9XG4gIGNvbnN0IHJlYXNvbiA9IFdJS0lMSU5LX0FMTE9XQU5DRV9SRUdfRVhQLmV4ZWMoZnJvbnRtYXR0ZXIpPy5ncm91cHM/LlsncmVhc29uJ107XG4gIHJldHVybiByZWFzb24gPT09IHVuZGVmaW5lZCA/IG51bGwgOiByZWFzb24udHJpbSgpLnJlcGxhY2UoL14oPzxxdW90ZT5bXCInXSkoPzx2YWx1ZT5bXFxzXFxTXSopXFxrPHF1b3RlPiQvLCAnJDx2YWx1ZT4nKTtcbn1cblxuLy8gUmVhZHMgdGhlIG5vdGUncyBpbmxpbmUgYG9ic2lkaWFuLWRldi11dGlscy1kaXNhYmxlXHUyMDI2YCBkaXJlY3RpdmVzLCByZXR1cm5pbmcgd2hpY2ggbGluZXMgdGhleSBhbGxvdyBhXG4vLyB3aWtpbGluayBvbiBhbmQgZXZlcnl0aGluZyB3cm9uZyB3aXRoIHRoZW0uIEEgc3VwcHJlc3Npb24gdGhhdCBxdWlldGx5IGRvZXMgbm90aGluZyBpcyB3b3JzZSB0aGFuIG5vbmUsXG4vLyBzbyBhIG1pc3NwZWxsZWQgZGlyZWN0aXZlLCBvbmUgd2l0aCBubyByZWFzb24sIGFuIHVuY2xvc2VkIHJlZ2lvbiBhbmQgb25lIGNvdmVyaW5nIG5vIHdpa2lsaW5rIGF0IGFsbFxuLy8gYXJlIGVhY2ggcmVwb3J0ZWQgcmF0aGVyIHRoYW4gaWdub3JlZC5cbmZ1bmN0aW9uIHNjYW5XaWtpbGlua0RpcmVjdGl2ZXMoY29udGVudDogc3RyaW5nKTogV2lraWxpbmtEaXJlY3RpdmVTY2FuIHtcbiAgY29uc3Qgc3RhdGU6IFdpa2lsaW5rRGlyZWN0aXZlU2NhblN0YXRlID0ge1xuICAgIGFsbG93ZWRMaW5lSW5kZXhlczogbmV3IFNldDxudW1iZXI+KCksXG4gICAgb3BlblJlZ2lvbjogbnVsbCxcbiAgICBwZW5kaW5nTmV4dExpbmVJbmRleDogbnVsbCxcbiAgICBwcm9ibGVtczogW10sXG4gICAgd2lraWxpbmtMaW5lSW5kZXhlczogbmV3IFNldChmaW5kV2lraWxpbmtMaW5lSW5kZXhlcyhjb250ZW50KSlcbiAgfTtcblxuICBmb3IgKGNvbnN0IHsgaW5kZXgsIGxpbmUgfSBvZiBjb2xsZWN0TGluZXNPdXRzaWRlRmVuY2VzKGNvbnRlbnQpKSB7XG4gICAgY29uc3QgbWF0Y2ggPSBESVJFQ1RJVkVfUkVHX0VYUC5leGVjKGxpbmUpO1xuICAgIGlmIChtYXRjaCkge1xuICAgICAgYXBwbHlXaWtpbGlua0RpcmVjdGl2ZShzdGF0ZSwgaW5kZXgsIG1hdGNoKTtcbiAgICB9IGVsc2UgaWYgKERJUkVDVElWRV9QUk9CRV9SRUdfRVhQLnRlc3QobGluZSkpIHtcbiAgICAgIHN0YXRlLnByb2JsZW1zLnB1c2goYGEgbWFsZm9ybWVkIGRpcmVjdGl2ZSBvbiAke2Zvcm1hdExpbmVOdW1iZXIoaW5kZXgpfWApO1xuICAgIH0gZWxzZSB7XG4gICAgICBhcHBseVdpa2lsaW5rU2NhbkxpbmUoc3RhdGUsIGluZGV4LCBsaW5lKTtcbiAgICB9XG4gIH1cblxuICBpZiAoc3RhdGUub3BlblJlZ2lvbikge1xuICAgIHN0YXRlLnByb2JsZW1zLnB1c2goYGEgcmVnaW9uIG9wZW5lZCBvbiAke2Zvcm1hdExpbmVOdW1iZXIoc3RhdGUub3BlblJlZ2lvbi5saW5lSW5kZXgpfSB0aGF0IGlzIG5ldmVyIGVuYWJsZWQgYWdhaW5gKTtcbiAgfVxuICBpZiAoc3RhdGUucGVuZGluZ05leHRMaW5lSW5kZXggIT09IG51bGwpIHtcbiAgICBzdGF0ZS5wcm9ibGVtcy5wdXNoKGBhIGRpc2FibGUtbmV4dC1saW5lIG9uICR7Zm9ybWF0TGluZU51bWJlcihzdGF0ZS5wZW5kaW5nTmV4dExpbmVJbmRleCl9IGNvdmVyaW5nIG5vIHdpa2lsaW5rYCk7XG4gIH1cbiAgcmV0dXJuIHsgYWxsb3dlZExpbmVJbmRleGVzOiBzdGF0ZS5hbGxvd2VkTGluZUluZGV4ZXMsIHByb2JsZW1zOiBzdGF0ZS5wcm9ibGVtcyB9O1xufVxuXG5mdW5jdGlvbiBzdHJpcEZyb250bWF0dGVyKGNvbnRlbnQ6IHN0cmluZyk6IHN0cmluZyB7XG4gIHJldHVybiBjb250ZW50LnJlcGxhY2UoRlJPTlRNQVRURVJfUkVHX0VYUCwgJycpO1xufVxuXG5mdW5jdGlvbiBzdHJpcElubGluZUNvZGUobGluZTogc3RyaW5nKTogc3RyaW5nIHtcbiAgcmV0dXJuIGxpbmUucmVwbGFjZUFsbChJTkxJTkVfQ09ERV9SRUdfRVhQLCAnJyk7XG59XG5cbi8vIEEgaGFuZC13cml0dGVuIGxpbmsgbWF5IGNvbnRhaW4gYSBiYXJlIGAlYCAob3IgYW55IG90aGVyIGludmFsaWQgcGVyY2VudC1lc2NhcGUpLCB3aGljaCBtYWtlc1xuLy8gYGRlY29kZVVSSUNvbXBvbmVudGAgdGhyb3cuIFN1Y2ggYSB0YXJnZXQgaXMgbWVhbnQgbGl0ZXJhbGx5LCBzbyBpdCBpcyB1c2VkIGFzIHdyaXR0ZW4uXG5mdW5jdGlvbiB0cnlEZWNvZGVVcmlDb21wb25lbnQodmFsdWU6IHN0cmluZyk6IHN0cmluZyB7XG4gIHRyeSB7XG4gICAgcmV0dXJuIGRlY29kZVVSSUNvbXBvbmVudCh2YWx1ZSk7XG4gIH0gY2F0Y2gge1xuICAgIHJldHVybiB2YWx1ZTtcbiAgfVxufVxuIl0sCiAgIm1hcHBpbmdzIjogIjs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBc0VBLDBCQUE0QztBQUM1QyxrQkFJTztBQUNQLHFCQUF1QztBQUN2Qyx5QkFBa0M7QUFDbEMscUJBSU87QUFDUCxvQkFJTztBQUVQLGlDQUdPO0FB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
|