@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.
Files changed (252) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +7 -1
  3. package/bundlers/esbuild/package.json +6 -0
  4. package/bundlers/esbuild-impl/copy-to-obsidian-plugins-folder-plugin/package.json +6 -0
  5. package/bundlers/esbuild-impl/dependency/package.json +6 -0
  6. package/bundlers/esbuild-impl/fix-source-maps-plugin/package.json +6 -0
  7. package/bundlers/esbuild-impl/index/package.json +6 -0
  8. package/bundlers/esbuild-impl/obsidian-plugin-builder/package.json +6 -0
  9. package/bundlers/esbuild-impl/package.json +6 -0
  10. package/bundlers/esbuild-impl/preprocess-plugin/package.json +6 -0
  11. package/bundlers/esbuild-impl/rename-css-plugin/package.json +6 -0
  12. package/bundlers/index/package.json +6 -0
  13. package/bundlers/package.json +6 -0
  14. package/dist/demo-vault-helper/main.js +782 -0
  15. package/dist/demo-vault-helper/manifest.json +9 -0
  16. package/dist/integration-test-plugin/main.js +45388 -0
  17. package/dist/integration-test-plugin/manifest.json +8 -0
  18. package/dist/lib/cjs/bundlers/esbuild-impl/copy-to-obsidian-plugins-folder-plugin.cjs +335 -0
  19. package/dist/lib/cjs/bundlers/esbuild-impl/copy-to-obsidian-plugins-folder-plugin.d.cts +38 -0
  20. package/dist/lib/cjs/bundlers/esbuild-impl/dependency.cjs +253 -0
  21. package/dist/lib/cjs/bundlers/esbuild-impl/dependency.d.cts +20 -0
  22. package/dist/lib/cjs/bundlers/esbuild-impl/fix-source-maps-plugin.cjs +226 -0
  23. package/dist/lib/cjs/bundlers/esbuild-impl/fix-source-maps-plugin.d.cts +34 -0
  24. package/dist/lib/cjs/bundlers/esbuild-impl/index.cjs +192 -0
  25. package/dist/lib/cjs/bundlers/esbuild-impl/index.d.cts +7 -0
  26. package/dist/lib/cjs/bundlers/esbuild-impl/obsidian-plugin-builder.cjs +375 -0
  27. package/dist/lib/cjs/bundlers/esbuild-impl/obsidian-plugin-builder.d.cts +98 -0
  28. package/dist/lib/cjs/bundlers/esbuild-impl/preprocess-plugin.cjs +247 -0
  29. package/dist/lib/cjs/bundlers/esbuild-impl/preprocess-plugin.d.cts +30 -0
  30. package/dist/lib/cjs/bundlers/esbuild-impl/rename-css-plugin.cjs +184 -0
  31. package/dist/lib/cjs/bundlers/esbuild-impl/rename-css-plugin.d.cts +14 -0
  32. package/dist/lib/cjs/bundlers/esbuild.cjs +177 -0
  33. package/dist/lib/cjs/bundlers/esbuild.d.cts +11 -0
  34. package/dist/lib/cjs/bundlers/index.cjs +180 -0
  35. package/dist/lib/cjs/bundlers/index.d.cts +3 -0
  36. package/dist/lib/cjs/demo-vault-app-json.cjs +199 -0
  37. package/dist/lib/cjs/demo-vault-app-json.d.cts +93 -0
  38. package/dist/lib/cjs/demo-vault-buttons.cjs +580 -0
  39. package/dist/lib/cjs/demo-vault-buttons.d.cts +259 -0
  40. package/dist/lib/cjs/demo-vault-coverage.cjs +725 -0
  41. package/dist/lib/cjs/demo-vault-coverage.d.cts +533 -0
  42. package/dist/lib/cjs/demo-vault.cjs +309 -0
  43. package/dist/lib/cjs/demo-vault.d.cts +33 -0
  44. package/dist/lib/cjs/formatters/dprint.cjs +173 -0
  45. package/dist/lib/cjs/formatters/dprint.d.cts +15 -0
  46. package/dist/lib/cjs/formatters/index.cjs +177 -0
  47. package/dist/lib/cjs/formatters/index.d.cts +2 -0
  48. package/dist/lib/cjs/index.cjs +207 -0
  49. package/dist/lib/cjs/index.d.cts +16 -0
  50. package/dist/lib/cjs/integration-test-setup.cjs +142 -0
  51. package/dist/lib/cjs/integration-test-setup.d.cts +33 -0
  52. package/dist/lib/cjs/integration-test-vitest-global-setup.cjs +176 -0
  53. package/dist/lib/cjs/integration-test-vitest-global-setup.d.cts +39 -0
  54. package/dist/lib/cjs/jest-setup.cjs +147 -0
  55. package/dist/lib/cjs/jest-setup.d.cts +13 -0
  56. package/dist/lib/cjs/linters/eslint-config.cjs +365 -0
  57. package/dist/lib/cjs/linters/eslint-config.d.cts +25 -0
  58. package/dist/lib/cjs/linters/eslint-rules/index.cjs +201 -0
  59. package/dist/lib/cjs/linters/eslint-rules/index.d.cts +10 -0
  60. package/dist/lib/cjs/linters/eslint-rules/manifest-description.cjs +268 -0
  61. package/dist/lib/cjs/linters/eslint-rules/manifest-description.d.cts +54 -0
  62. package/dist/lib/cjs/linters/eslint-rules/manifest-helpers.cjs +231 -0
  63. package/dist/lib/cjs/linters/eslint-rules/manifest-helpers.d.cts +141 -0
  64. package/dist/lib/cjs/linters/eslint-rules/manifest-id.cjs +228 -0
  65. package/dist/lib/cjs/linters/eslint-rules/manifest-id.d.cts +32 -0
  66. package/dist/lib/cjs/linters/eslint-rules/manifest-name.cjs +229 -0
  67. package/dist/lib/cjs/linters/eslint-rules/manifest-name.d.cts +30 -0
  68. package/dist/lib/cjs/linters/eslint-rules/manifest-schema.cjs +329 -0
  69. package/dist/lib/cjs/linters/eslint-rules/manifest-schema.d.cts +45 -0
  70. package/dist/lib/cjs/linters/eslint-rules/no-over-cap-wait-in-eval-in-obsidian.cjs +670 -0
  71. package/dist/lib/cjs/linters/eslint-rules/no-over-cap-wait-in-eval-in-obsidian.d.cts +10 -0
  72. package/dist/lib/cjs/linters/eslint-rules/no-untrusted-input-events.cjs +260 -0
  73. package/dist/lib/cjs/linters/eslint-rules/no-untrusted-input-events.d.cts +10 -0
  74. package/dist/lib/cjs/linters/eslint-rules/obsidian-dev-utils-plugin.cjs +186 -0
  75. package/dist/lib/cjs/linters/eslint-rules/obsidian-dev-utils-plugin.d.cts +13 -0
  76. package/dist/lib/cjs/linters/eslint-rules/require-component-suffix.cjs +291 -0
  77. package/dist/lib/cjs/linters/eslint-rules/require-component-suffix.d.cts +18 -0
  78. package/dist/lib/cjs/linters/eslint.cjs +173 -0
  79. package/dist/lib/cjs/linters/eslint.d.cts +15 -0
  80. package/dist/lib/cjs/linters/index.cjs +189 -0
  81. package/dist/lib/cjs/linters/index.d.cts +6 -0
  82. package/dist/lib/cjs/linters/markdownlint.cjs +173 -0
  83. package/dist/lib/cjs/linters/markdownlint.d.cts +15 -0
  84. package/dist/lib/cjs/linters/obsidianmd-rule-custom-message.cjs +189 -0
  85. package/dist/lib/cjs/linters/obsidianmd-rule-custom-message.d.cts +40 -0
  86. package/dist/lib/cjs/obsidian-plugin-repo-paths.cjs +229 -0
  87. package/dist/lib/cjs/obsidian-plugin-repo-paths.d.cts +253 -0
  88. package/dist/lib/cjs/setup.cjs +176 -0
  89. package/dist/lib/cjs/setup.d.cts +21 -0
  90. package/dist/lib/cjs/templates.cjs +185 -0
  91. package/dist/lib/cjs/templates.d.cts +13 -0
  92. package/dist/lib/cjs/test-runners/index.cjs +183 -0
  93. package/dist/lib/cjs/test-runners/index.d.cts +4 -0
  94. package/dist/lib/cjs/test-runners/integration-test-plugin.cjs +224 -0
  95. package/dist/lib/cjs/test-runners/integration-test-plugin.d.cts +44 -0
  96. package/dist/lib/cjs/test-runners/performance-eval-cap.cjs +170 -0
  97. package/dist/lib/cjs/test-runners/performance-eval-cap.d.cts +27 -0
  98. package/dist/lib/cjs/test-runners/stale-build-global-setup.cjs +230 -0
  99. package/dist/lib/cjs/test-runners/stale-build-global-setup.d.cts +86 -0
  100. package/dist/lib/cjs/test-runners/vitest-config.cjs +497 -0
  101. package/dist/lib/cjs/test-runners/vitest-config.d.cts +200 -0
  102. package/dist/lib/cjs/version.cjs +275 -0
  103. package/dist/lib/cjs/version.d.cts +92 -0
  104. package/dist/lib/cjs/vitest-setup.cjs +147 -0
  105. package/dist/lib/cjs/vitest-setup.d.cts +11 -0
  106. package/dist/lib/esm/bundlers/esbuild-impl/copy-to-obsidian-plugins-folder-plugin.d.mts +38 -0
  107. package/dist/lib/esm/bundlers/esbuild-impl/copy-to-obsidian-plugins-folder-plugin.mjs +226 -0
  108. package/dist/lib/esm/bundlers/esbuild-impl/dependency.d.mts +20 -0
  109. package/dist/lib/esm/bundlers/esbuild-impl/dependency.mjs +138 -0
  110. package/dist/lib/esm/bundlers/esbuild-impl/fix-source-maps-plugin.d.mts +34 -0
  111. package/dist/lib/esm/bundlers/esbuild-impl/fix-source-maps-plugin.mjs +116 -0
  112. package/dist/lib/esm/bundlers/esbuild-impl/index.d.mts +7 -0
  113. package/dist/lib/esm/bundlers/esbuild-impl/index.mjs +64 -0
  114. package/dist/lib/esm/bundlers/esbuild-impl/obsidian-plugin-builder.d.mts +98 -0
  115. package/dist/lib/esm/bundlers/esbuild-impl/obsidian-plugin-builder.mjs +255 -0
  116. package/dist/lib/esm/bundlers/esbuild-impl/preprocess-plugin.d.mts +30 -0
  117. package/dist/lib/esm/bundlers/esbuild-impl/preprocess-plugin.mjs +134 -0
  118. package/dist/lib/esm/bundlers/esbuild-impl/rename-css-plugin.d.mts +14 -0
  119. package/dist/lib/esm/bundlers/esbuild-impl/rename-css-plugin.mjs +71 -0
  120. package/dist/lib/esm/bundlers/esbuild.d.mts +11 -0
  121. package/dist/lib/esm/bundlers/esbuild.mjs +66 -0
  122. package/dist/lib/esm/bundlers/index.d.mts +3 -0
  123. package/dist/lib/esm/bundlers/index.mjs +56 -0
  124. package/dist/lib/esm/demo-vault-app-json.d.mts +93 -0
  125. package/dist/lib/esm/demo-vault-app-json.mjs +83 -0
  126. package/dist/lib/esm/demo-vault-buttons.d.mts +259 -0
  127. package/dist/lib/esm/demo-vault-buttons.mjs +460 -0
  128. package/dist/lib/esm/demo-vault-coverage.d.mts +533 -0
  129. package/dist/lib/esm/demo-vault-coverage.mjs +626 -0
  130. package/dist/lib/esm/demo-vault.d.mts +33 -0
  131. package/dist/lib/esm/demo-vault.mjs +205 -0
  132. package/dist/lib/esm/formatters/dprint.d.mts +15 -0
  133. package/dist/lib/esm/formatters/dprint.mjs +60 -0
  134. package/dist/lib/esm/formatters/index.d.mts +2 -0
  135. package/dist/lib/esm/formatters/index.mjs +54 -0
  136. package/dist/lib/esm/index.d.mts +16 -0
  137. package/dist/lib/esm/index.mjs +74 -0
  138. package/dist/lib/esm/integration-test-setup.d.mts +33 -0
  139. package/dist/lib/esm/integration-test-setup.mjs +52 -0
  140. package/dist/lib/esm/integration-test-vitest-global-setup.d.mts +39 -0
  141. package/dist/lib/esm/integration-test-vitest-global-setup.mjs +65 -0
  142. package/dist/lib/esm/jest-setup.d.mts +13 -0
  143. package/dist/lib/esm/jest-setup.mjs +61 -0
  144. package/dist/lib/esm/linters/eslint-config.d.mts +25 -0
  145. package/dist/lib/esm/linters/eslint-config.mjs +247 -0
  146. package/dist/lib/esm/linters/eslint-rules/index.d.mts +10 -0
  147. package/dist/lib/esm/linters/eslint-rules/index.mjs +70 -0
  148. package/dist/lib/esm/linters/eslint-rules/manifest-description.d.mts +54 -0
  149. package/dist/lib/esm/linters/eslint-rules/manifest-description.mjs +154 -0
  150. package/dist/lib/esm/linters/eslint-rules/manifest-helpers.d.mts +141 -0
  151. package/dist/lib/esm/linters/eslint-rules/manifest-helpers.mjs +98 -0
  152. package/dist/lib/esm/linters/eslint-rules/manifest-id.d.mts +32 -0
  153. package/dist/lib/esm/linters/eslint-rules/manifest-id.mjs +117 -0
  154. package/dist/lib/esm/linters/eslint-rules/manifest-name.d.mts +30 -0
  155. package/dist/lib/esm/linters/eslint-rules/manifest-name.mjs +118 -0
  156. package/dist/lib/esm/linters/eslint-rules/manifest-schema.d.mts +45 -0
  157. package/dist/lib/esm/linters/eslint-rules/manifest-schema.mjs +220 -0
  158. package/dist/lib/esm/linters/eslint-rules/no-over-cap-wait-in-eval-in-obsidian.d.mts +10 -0
  159. package/dist/lib/esm/linters/eslint-rules/no-over-cap-wait-in-eval-in-obsidian.mjs +559 -0
  160. package/dist/lib/esm/linters/eslint-rules/no-untrusted-input-events.d.mts +10 -0
  161. package/dist/lib/esm/linters/eslint-rules/no-untrusted-input-events.mjs +146 -0
  162. package/dist/lib/esm/linters/eslint-rules/obsidian-dev-utils-plugin.d.mts +13 -0
  163. package/dist/lib/esm/linters/eslint-rules/obsidian-dev-utils-plugin.mjs +73 -0
  164. package/dist/lib/esm/linters/eslint-rules/require-component-suffix.d.mts +18 -0
  165. package/dist/lib/esm/linters/eslint-rules/require-component-suffix.mjs +175 -0
  166. package/dist/lib/esm/linters/eslint.d.mts +15 -0
  167. package/dist/lib/esm/linters/eslint.mjs +60 -0
  168. package/dist/lib/esm/linters/index.d.mts +6 -0
  169. package/dist/lib/esm/linters/index.mjs +62 -0
  170. package/dist/lib/esm/linters/markdownlint.d.mts +15 -0
  171. package/dist/lib/esm/linters/markdownlint.mjs +60 -0
  172. package/dist/lib/esm/linters/obsidianmd-rule-custom-message.d.mts +40 -0
  173. package/dist/lib/esm/linters/obsidianmd-rule-custom-message.mjs +75 -0
  174. package/dist/lib/esm/obsidian-plugin-repo-paths.d.mts +253 -0
  175. package/dist/lib/esm/obsidian-plugin-repo-paths.mjs +116 -0
  176. package/dist/lib/esm/setup.d.mts +21 -0
  177. package/dist/lib/esm/setup.mjs +63 -0
  178. package/dist/lib/esm/templates.d.mts +13 -0
  179. package/dist/lib/esm/templates.mjs +65 -0
  180. package/dist/lib/esm/test-runners/index.d.mts +4 -0
  181. package/dist/lib/esm/test-runners/index.mjs +58 -0
  182. package/dist/lib/esm/test-runners/integration-test-plugin.d.mts +44 -0
  183. package/dist/lib/esm/test-runners/integration-test-plugin.mjs +102 -0
  184. package/dist/lib/esm/test-runners/performance-eval-cap.d.mts +27 -0
  185. package/dist/lib/esm/test-runners/performance-eval-cap.mjs +56 -0
  186. package/dist/lib/esm/test-runners/stale-build-global-setup.d.mts +86 -0
  187. package/dist/lib/esm/test-runners/stale-build-global-setup.mjs +123 -0
  188. package/dist/lib/esm/test-runners/vitest-config.d.mts +200 -0
  189. package/dist/lib/esm/test-runners/vitest-config.mjs +377 -0
  190. package/dist/lib/esm/version.d.mts +92 -0
  191. package/dist/lib/esm/version.mjs +168 -0
  192. package/dist/lib/esm/vitest-setup.d.mts +11 -0
  193. package/dist/lib/esm/vitest-setup.mjs +61 -0
  194. package/dist/templates/.markdownlint-cli2.mjs +4 -0
  195. package/dist/templates/.nano-staged.mjs +4 -0
  196. package/dist/templates/commitlint.config.ts +3 -0
  197. package/dist/templates/dprint.json +26 -0
  198. package/dist/templates/eslint.config.mts +3 -0
  199. package/dist/templates/scripts/build/build-clean.ts +4 -0
  200. package/dist/templates/scripts/build/build-compile-svelte.ts +4 -0
  201. package/dist/templates/scripts/build/build-compile-typescript.ts +4 -0
  202. package/dist/templates/scripts/build/build-compile.ts +4 -0
  203. package/dist/templates/scripts/build/build-templates.ts +4 -0
  204. package/dist/templates/scripts/bundlers/esbuild/build.ts +4 -0
  205. package/dist/templates/scripts/bundlers/esbuild/dev.ts +4 -0
  206. package/dist/templates/scripts/commitlint-config.ts +3 -0
  207. package/dist/templates/scripts/eslint-config.ts +10 -0
  208. package/dist/templates/scripts/formatters/dprint/format-check.ts +8 -0
  209. package/dist/templates/scripts/formatters/dprint/format.ts +8 -0
  210. package/dist/templates/scripts/gate/gate.ts +10 -0
  211. package/dist/templates/scripts/linters/cspell/spellcheck.ts +8 -0
  212. package/dist/templates/scripts/linters/eslint/lint-fix.ts +8 -0
  213. package/dist/templates/scripts/linters/eslint/lint.ts +8 -0
  214. package/dist/templates/scripts/linters/markdownlint/lint-md-fix.ts +8 -0
  215. package/dist/templates/scripts/linters/markdownlint/lint-md.ts +8 -0
  216. package/dist/templates/scripts/linters/over-exposure/find-overexposed-fix.ts +25 -0
  217. package/dist/templates/scripts/linters/over-exposure/find-overexposed.ts +15 -0
  218. package/dist/templates/scripts/markdownlint-cli2-config.ts +3 -0
  219. package/dist/templates/scripts/nano-staged-config.ts +3 -0
  220. package/dist/templates/scripts/test-runners/vitest/test-coverage.ts +4 -0
  221. package/dist/templates/scripts/test-runners/vitest/test-watch.ts +4 -0
  222. package/dist/templates/scripts/test-runners/vitest/test.ts +4 -0
  223. package/dist/templates/scripts/version/version.ts +10 -0
  224. package/dist/templates/scripts/vitest-config.ts +3 -0
  225. package/dist/templates/vitest.config.ts +3 -0
  226. package/formatters/dprint/package.json +6 -0
  227. package/formatters/index/package.json +6 -0
  228. package/formatters/package.json +6 -0
  229. package/linters/eslint/package.json +6 -0
  230. package/linters/eslint-config/package.json +6 -0
  231. package/linters/eslint-rules/index/package.json +6 -0
  232. package/linters/eslint-rules/manifest-description/package.json +6 -0
  233. package/linters/eslint-rules/manifest-helpers/package.json +6 -0
  234. package/linters/eslint-rules/manifest-id/package.json +6 -0
  235. package/linters/eslint-rules/manifest-name/package.json +6 -0
  236. package/linters/eslint-rules/manifest-schema/package.json +6 -0
  237. package/linters/eslint-rules/no-over-cap-wait-in-eval-in-obsidian/package.json +6 -0
  238. package/linters/eslint-rules/no-untrusted-input-events/package.json +6 -0
  239. package/linters/eslint-rules/obsidian-dev-utils-plugin/package.json +6 -0
  240. package/linters/eslint-rules/package.json +6 -0
  241. package/linters/eslint-rules/require-component-suffix/package.json +6 -0
  242. package/linters/index/package.json +6 -0
  243. package/linters/markdownlint/package.json +6 -0
  244. package/linters/obsidianmd-rule-custom-message/package.json +6 -0
  245. package/linters/package.json +6 -0
  246. package/package.json +241 -13
  247. package/test-runners/index/package.json +6 -0
  248. package/test-runners/integration-test-plugin/package.json +6 -0
  249. package/test-runners/package.json +6 -0
  250. package/test-runners/performance-eval-cap/package.json +6 -0
  251. package/test-runners/stale-build-global-setup/package.json +6 -0
  252. package/test-runners/vitest-config/package.json +6 -0
@@ -0,0 +1,580 @@
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 __create = Object.create;
141
+ var __defProp = Object.defineProperty;
142
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
143
+ var __getOwnPropNames = Object.getOwnPropertyNames;
144
+ var __getProtoOf = Object.getPrototypeOf;
145
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
146
+ var __export = (target, all) => {
147
+ for (var name in all)
148
+ __defProp(target, name, { get: all[name], enumerable: true });
149
+ };
150
+ var __copyProps = (to, from, except, desc) => {
151
+ if (from && typeof from === "object" || typeof from === "function") {
152
+ for (let key of __getOwnPropNames(from))
153
+ if (!__hasOwnProp.call(to, key) && key !== except)
154
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
155
+ }
156
+ return to;
157
+ };
158
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
159
+ // If the importer is in node compatibility mode or this is not an ESM
160
+ // file that has been converted to a CommonJS file using a Babel-
161
+ // compatible transform (i.e. "__esModule" has not been set), then set
162
+ // "default" to the CommonJS "module.exports" for node compatibility.
163
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
164
+ mod
165
+ ));
166
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
167
+ var demo_vault_buttons_exports = {};
168
+ __export(demo_vault_buttons_exports, {
169
+ CODE_SCRIPT_TOOLKIT_PLUGIN_ID: () => CODE_SCRIPT_TOOLKIT_PLUGIN_ID,
170
+ assertClickBudgetsFitTransportCap: () => assertClickBudgetsFitTransportCap,
171
+ countRenderedButtons: () => countRenderedButtons,
172
+ findDuplicateCaptions: () => findDuplicateCaptions,
173
+ formatFailures: () => formatFailures,
174
+ listNotesWithButtons: () => listNotesWithButtons,
175
+ listRenderedButtonCaptions: () => listRenderedButtonCaptions,
176
+ registerDemoVaultButtonSuite: () => registerDemoVaultButtonSuite,
177
+ selectUnexpectedFailures: () => selectUnexpectedFailures
178
+ });
179
+ module.exports = __toCommonJS(demo_vault_buttons_exports);
180
+ var import_root = require('@mnaoumov/typescript-dev-toolkit/root');
181
+ var import_node_fs = require('node:fs');
182
+ var import_node_path = require('node:path');
183
+ var import_node_process = __toESM(__extractDefault(require('node:process')), 1);
184
+ var import_obsidian_integration_testing = require('obsidian-integration-testing');
185
+ var import_vitest_global_setup_plugin = require('obsidian-integration-testing/vitest-global-setup-plugin');
186
+ var import_vitest = require('vitest');
187
+ const CODE_SCRIPT_TOOLKIT_PLUGIN_ID = "fix-require-modules";
188
+ const DEFAULT_BUTTON_RESULT_TIMEOUT_IN_MILLISECONDS = 1e4;
189
+ const DEFAULT_SETTLE_TIMEOUT_IN_MILLISECONDS = 12e3;
190
+ const POLL_INTERVAL_IN_MILLISECONDS = 100;
191
+ const OUTPUT_EXCERPT_LENGTH = 400;
192
+ const DEFAULT_EXCLUDED_NOTES = ["README.md"];
193
+ const FENCE_REG_EXP = /^(?<indent>\s*)(?<marker>`{3,}|~{3,})(?<info>.*)$/;
194
+ const CODE_BUTTON_FENCE_INFO = "code-button";
195
+ const FRONT_MATTER_DELIMITER = "---";
196
+ const RAW_MODE_CONFIG_REG_EXP = /^isRaw:\s*true\s*$/m;
197
+ const CAPTION_CONFIG_REG_EXP = /^caption:(?<value>.*)$/m;
198
+ const PLAIN_SCALAR_COMMENT_REG_EXP = /\s+#.*$/;
199
+ const SINGLE_QUOTED_SCALAR_REG_EXP = /^'(?<content>.*)'$/;
200
+ const DOUBLE_QUOTED_SCALAR_REG_EXP = /^"(?<content>.*)"$/;
201
+ const DEFAULT_CODE_BUTTON_CAPTION = "(no caption)";
202
+ function assertClickBudgetsFitTransportCap(timeouts) {
203
+ const totalInMilliseconds = timeouts.settleTimeoutInMilliseconds + timeouts.buttonResultTimeoutInMilliseconds;
204
+ if (totalInMilliseconds < import_obsidian_integration_testing.DEFAULT_EVAL_CAP_IN_MILLISECONDS) {
205
+ return;
206
+ }
207
+ throw new Error(
208
+ `One demo-vault button click spends settleTimeoutInMilliseconds (${String(timeouts.settleTimeoutInMilliseconds)} ms) and buttonResultTimeoutInMilliseconds (${String(timeouts.buttonResultTimeoutInMilliseconds)} ms) inside a single transport call, so their sum of ${String(totalInMilliseconds)} ms is at or over the transport's ${String(import_obsidian_integration_testing.DEFAULT_EVAL_CAP_IN_MILLISECONDS)} ms script timeout and can never be honoured. Lower either budget in RegisterDemoVaultButtonSuiteOptions.`
209
+ );
210
+ }
211
+ function countRenderedButtons(source) {
212
+ return listRenderedButtonCaptions(source).length;
213
+ }
214
+ function findDuplicateCaptions(captions) {
215
+ const seenCaptions = /* @__PURE__ */ new Set();
216
+ const duplicateCaptions = /* @__PURE__ */ new Set();
217
+ for (const caption of captions) {
218
+ if (seenCaptions.has(caption)) {
219
+ duplicateCaptions.add(caption);
220
+ }
221
+ seenCaptions.add(caption);
222
+ }
223
+ return [...duplicateCaptions];
224
+ }
225
+ function formatFailures(noteName, failures) {
226
+ if (failures.length === 0) {
227
+ return "";
228
+ }
229
+ const details = failures.map((failure) => ` - "${failure.caption}" [${failure.status}]: ${failure.output.replaceAll(/\s+/g, " ").trim()}`).join("\n");
230
+ return `${String(failures.length)} button(s) in ${noteName} did not run cleanly:
231
+ ${details}`;
232
+ }
233
+ function listRenderedButtonCaptions(source) {
234
+ const captions = [];
235
+ let openMarker = "";
236
+ let isCodeButtonFence = false;
237
+ let fenceBody = [];
238
+ let fenceIndentLength = 0;
239
+ function closeFence() {
240
+ if (isCodeButtonFence && !isRawFence(fenceBody)) {
241
+ captions.push(readCaption(fenceBody));
242
+ }
243
+ openMarker = "";
244
+ }
245
+ for (const line of source.split(/\r?\n/)) {
246
+ const match = FENCE_REG_EXP.exec(line);
247
+ const indent = match?.groups?.["indent"] ?? "";
248
+ const marker = match?.groups?.["marker"] ?? "";
249
+ const info = (match?.groups?.["info"] ?? "").trim();
250
+ if (openMarker === "") {
251
+ if (match) {
252
+ openMarker = marker;
253
+ isCodeButtonFence = info === CODE_BUTTON_FENCE_INFO;
254
+ fenceBody = [];
255
+ fenceIndentLength = indent.length;
256
+ }
257
+ continue;
258
+ }
259
+ if (marker.startsWith(openMarker.charAt(0)) && marker.length >= openMarker.length && info === "") {
260
+ closeFence();
261
+ continue;
262
+ }
263
+ fenceBody.push(line.slice(Math.min(fenceIndentLength, line.length - line.trimStart().length)));
264
+ }
265
+ if (openMarker !== "") {
266
+ closeFence();
267
+ }
268
+ return captions;
269
+ }
270
+ function selectUnexpectedFailures(noteName, results, expectedNonOkButtons) {
271
+ return results.filter(
272
+ (result) => result.status !== "ok" && expectedNonOkButtons.every(
273
+ (expected) => !(expected.note === noteName && expected.status === result.status && result.caption.includes(expected.captionIncludes))
274
+ )
275
+ );
276
+ }
277
+ function isRawFence(fenceBody) {
278
+ const config = readConfigBlock(fenceBody);
279
+ return config !== null && RAW_MODE_CONFIG_REG_EXP.test(config);
280
+ }
281
+ function readCaption(fenceBody) {
282
+ const config = readConfigBlock(fenceBody);
283
+ const rawValue = config === null ? void 0 : CAPTION_CONFIG_REG_EXP.exec(config)?.groups?.["value"];
284
+ if (rawValue === void 0) {
285
+ return DEFAULT_CODE_BUTTON_CAPTION;
286
+ }
287
+ const value = rawValue.trim();
288
+ const singleQuotedContent = SINGLE_QUOTED_SCALAR_REG_EXP.exec(value)?.groups?.["content"];
289
+ if (singleQuotedContent !== void 0) {
290
+ return singleQuotedContent.replaceAll("''", "'");
291
+ }
292
+ const doubleQuotedContent = DOUBLE_QUOTED_SCALAR_REG_EXP.exec(value)?.groups?.["content"];
293
+ if (doubleQuotedContent !== void 0) {
294
+ try {
295
+ return JSON.parse(value);
296
+ } catch {
297
+ return doubleQuotedContent;
298
+ }
299
+ }
300
+ return value.replace(PLAIN_SCALAR_COMMENT_REG_EXP, "");
301
+ }
302
+ function readConfigBlock(fenceBody) {
303
+ if (fenceBody[0]?.trim() !== FRONT_MATTER_DELIMITER) {
304
+ return null;
305
+ }
306
+ const endIndex = fenceBody.findIndex((line, index) => index > 0 && line.trim() === FRONT_MATTER_DELIMITER);
307
+ return endIndex === -1 ? null : fenceBody.slice(1, endIndex).join("\n");
308
+ }
309
+ const NON_WALKTHROUGH_FOLDERS = /* @__PURE__ */ new Set(["Materials"]);
310
+ function listNotesWithButtons(demoVaultPath, excludedNotes, excludedFolders = /* @__PURE__ */ new Set()) {
311
+ const notes = [];
312
+ function walk(folder, relativeFolder) {
313
+ for (const entry of (0, import_node_fs.readdirSync)(folder, { withFileTypes: true })) {
314
+ const relativePath = relativeFolder === "" ? entry.name : `${relativeFolder}/${entry.name}`;
315
+ if (entry.isDirectory()) {
316
+ if (!entry.name.startsWith(".") && !entry.name.startsWith("_") && !NON_WALKTHROUGH_FOLDERS.has(entry.name) && !excludedFolders.has(entry.name) && !excludedFolders.has(relativePath)) {
317
+ walk((0, import_node_path.join)(folder, entry.name), relativePath);
318
+ }
319
+ continue;
320
+ }
321
+ if (!entry.name.endsWith(".md") || excludedNotes.has(entry.name) || excludedNotes.has(relativePath)) {
322
+ continue;
323
+ }
324
+ const captions = listRenderedButtonCaptions((0, import_node_fs.readFileSync)((0, import_node_path.join)(folder, entry.name), "utf-8"));
325
+ if (captions.length > 0) {
326
+ notes.push({ buttonCount: captions.length, captions, name: relativePath });
327
+ }
328
+ }
329
+ }
330
+ walk(demoVaultPath, "");
331
+ return notes.sort((a, b) => a.name.localeCompare(b.name, "en"));
332
+ }
333
+ function registerDemoVaultButtonSuite(options = {}) {
334
+ const rootFolder = options.rootFolder ?? (0, import_root.getRootFolder)() ?? import_node_process.default.cwd();
335
+ const demoVaultPath = (0, import_node_path.join)(rootFolder, "demo-vault");
336
+ const excludedNotes = new Set(options.excludedNotes ?? DEFAULT_EXCLUDED_NOTES);
337
+ const excludedFolders = new Set(options.excludedFolders);
338
+ const expectedNonOkButtons = options.expectedNonOkButtons ?? [];
339
+ const shouldDismissModals = options.shouldDismissModals ?? false;
340
+ const settleTimeoutInMilliseconds = options.settleTimeoutInMilliseconds ?? DEFAULT_SETTLE_TIMEOUT_IN_MILLISECONDS;
341
+ const buttonResultTimeoutInMilliseconds = options.buttonResultTimeoutInMilliseconds ?? DEFAULT_BUTTON_RESULT_TIMEOUT_IN_MILLISECONDS;
342
+ const clickButtonTimeouts = {
343
+ buttonResultTimeoutInMilliseconds,
344
+ settleTimeoutInMilliseconds
345
+ };
346
+ assertClickBudgetsFitTransportCap(clickButtonTimeouts);
347
+ const notes = listNotesWithButtons(demoVaultPath, excludedNotes, excludedFolders);
348
+ (0, import_vitest.describe)("demo-vault buttons", () => {
349
+ (0, import_vitest.beforeAll)(async () => {
350
+ const isCodeScriptToolkitLoaded = await checkCodeScriptToolkitLoaded(settleTimeoutInMilliseconds);
351
+ (0, import_vitest.expect)(isCodeScriptToolkitLoaded, "CodeScript Toolkit did not load, so no button could render").toBe(true);
352
+ });
353
+ (0, import_vitest.it)("has at least one note with a code button", () => {
354
+ (0, import_vitest.expect)(notes.length).toBeGreaterThan(0);
355
+ });
356
+ for (const note of notes) {
357
+ (0, import_vitest.it)(`runs every code button in ${note.name}`, async () => {
358
+ const duplicateCaptions = findDuplicateCaptions(note.captions);
359
+ (0, import_vitest.expect)(
360
+ duplicateCaptions,
361
+ `${note.name} declares more than one button captioned ${duplicateCaptions.map((caption) => `"${caption}"`).join(", ")}. This suite addresses a button by its caption, so only the first of them could ever be clicked. Give each button a distinct caption.`
362
+ ).toEqual([]);
363
+ const captions = await openNoteAndListButtonCaptions(note, settleTimeoutInMilliseconds);
364
+ const missingCaptions = note.captions.filter((caption) => !captions.includes(caption));
365
+ (0, import_vitest.expect)(
366
+ captions.length,
367
+ `${note.name} declares ${String(note.buttonCount)} button(s) but only ${String(captions.length)} rendered; never seen: ${missingCaptions.map((caption) => `"${caption}"`).join(", ")}`
368
+ ).toBeGreaterThanOrEqual(note.buttonCount);
369
+ const results = [];
370
+ for (const caption of captions) {
371
+ results.push(await clickButton({ buttonCaption: caption, notePath: note.name, shouldDismissModals, timeouts: clickButtonTimeouts }));
372
+ }
373
+ const failures = selectUnexpectedFailures(note.name, results, expectedNonOkButtons);
374
+ (0, import_vitest.expect)(failures, formatFailures(note.name, failures)).toEqual([]);
375
+ });
376
+ }
377
+ });
378
+ }
379
+ async function checkCodeScriptToolkitLoaded(timeoutInMilliseconds) {
380
+ return (0, import_obsidian_integration_testing.evalInObsidian)({
381
+ async callback({ app, codeScriptToolkitPluginId, intervalInMilliseconds, lib: { waitUntil }, timeoutInMilliseconds: timeout }) {
382
+ if (typeof app.plugins.isEnabled === "function" && !app.plugins.isEnabled()) {
383
+ await app.plugins.setEnable(true);
384
+ }
385
+ if (!app.plugins.getPlugin(codeScriptToolkitPluginId)) {
386
+ await app.plugins.enablePlugin(codeScriptToolkitPluginId);
387
+ }
388
+ try {
389
+ await waitUntil({
390
+ intervalInMilliseconds,
391
+ message: "CodeScript Toolkit never loaded",
392
+ predicate: () => app.plugins.getPlugin(codeScriptToolkitPluginId) !== null,
393
+ timeoutInMilliseconds: timeout
394
+ });
395
+ } catch {
396
+ return false;
397
+ }
398
+ return true;
399
+ },
400
+ input: {
401
+ codeScriptToolkitPluginId: CODE_SCRIPT_TOOLKIT_PLUGIN_ID,
402
+ intervalInMilliseconds: POLL_INTERVAL_IN_MILLISECONDS,
403
+ timeoutInMilliseconds
404
+ },
405
+ vaultPath: (0, import_vitest_global_setup_plugin.getTemporaryVault)().path
406
+ });
407
+ }
408
+ async function clickButton(params) {
409
+ return (0, import_obsidian_integration_testing.evalInObsidian)({
410
+ async callback({
411
+ app,
412
+ buttonResultTimeoutInMilliseconds,
413
+ caption,
414
+ intervalInMilliseconds,
415
+ lib: { pressKey, waitUntil },
416
+ notePath: notePathToOpen,
417
+ obsidianModule,
418
+ outputExcerptLength,
419
+ settleTimeoutInMilliseconds,
420
+ shouldDismissModals: shouldDismiss
421
+ }) {
422
+ function view() {
423
+ return app.workspace.getActiveViewOfType(obsidianModule.MarkdownView);
424
+ }
425
+ function previewEl() {
426
+ return view()?.containerEl.querySelector(":scope .markdown-preview-view") ?? null;
427
+ }
428
+ function buttons() {
429
+ return [...view()?.containerEl.querySelectorAll(":scope .block-language-code-button button.mod-cta") ?? []];
430
+ }
431
+ function findButton() {
432
+ return buttons().find((candidate) => candidate.textContent === caption);
433
+ }
434
+ const SCROLL_BOTTOM_TOLERANCE_IN_PIXELS = 4;
435
+ const SCROLL_STEP_RATIO = 0.8;
436
+ function advanceScroll() {
437
+ const scroller = previewEl();
438
+ if (!scroller) {
439
+ return;
440
+ }
441
+ const isAtBottom = scroller.scrollTop + scroller.clientHeight >= scroller.scrollHeight - SCROLL_BOTTOM_TOLERANCE_IN_PIXELS;
442
+ scroller.scrollTop = isAtBottom ? 0 : scroller.scrollTop + Math.floor(scroller.clientHeight * SCROLL_STEP_RATIO);
443
+ }
444
+ async function dismissModals() {
445
+ if (!shouldDismiss) {
446
+ return;
447
+ }
448
+ for (const closeButton of activeDocument.body.querySelectorAll(":scope .modal-container :is(.modal-close-button, .modal-header-button)")) {
449
+ closeButton.click();
450
+ }
451
+ if (activeDocument.querySelector(".modal-container, .prompt")) {
452
+ await pressKey({ key: "Escape" });
453
+ }
454
+ }
455
+ await app.workspace.openLinkText(notePathToOpen.replace(/\.md$/, ""), "", false);
456
+ await app.workspace.getLeaf(false).setViewState({ state: { file: notePathToOpen, mode: "preview" }, type: "markdown" });
457
+ let button;
458
+ try {
459
+ await waitUntil({
460
+ intervalInMilliseconds,
461
+ message: `code button "${caption}" never rendered`,
462
+ predicate: () => {
463
+ advanceScroll();
464
+ button = findButton();
465
+ return button !== void 0;
466
+ },
467
+ timeoutInMilliseconds: settleTimeoutInMilliseconds
468
+ });
469
+ } catch {
470
+ return { caption, output: "", status: "timeout" };
471
+ }
472
+ if (!button) {
473
+ return { caption, output: "", status: "timeout" };
474
+ }
475
+ const block = button.closest(".block-language-code-button") ?? button.parentElement;
476
+ button.scrollIntoView();
477
+ button.click();
478
+ let status;
479
+ try {
480
+ await waitUntil({
481
+ intervalInMilliseconds,
482
+ message: `button "${caption}" never reported a result`,
483
+ predicate: async () => {
484
+ await dismissModals();
485
+ return /Executed (?:successfully|with error)/.test(block?.textContent ?? "");
486
+ },
487
+ timeoutInMilliseconds: buttonResultTimeoutInMilliseconds
488
+ });
489
+ const text = block?.textContent ?? "";
490
+ if (text.includes("Executed with error")) {
491
+ status = "error";
492
+ } else if (text.includes("Executed successfully")) {
493
+ status = "ok";
494
+ } else {
495
+ status = "unknown";
496
+ }
497
+ } catch {
498
+ status = "timeout";
499
+ }
500
+ await dismissModals();
501
+ return { caption, output: (block?.textContent ?? "").slice(0, outputExcerptLength), status };
502
+ },
503
+ input: {
504
+ buttonResultTimeoutInMilliseconds: params.timeouts.buttonResultTimeoutInMilliseconds,
505
+ caption: params.buttonCaption,
506
+ intervalInMilliseconds: POLL_INTERVAL_IN_MILLISECONDS,
507
+ notePath: params.notePath,
508
+ outputExcerptLength: OUTPUT_EXCERPT_LENGTH,
509
+ settleTimeoutInMilliseconds: params.timeouts.settleTimeoutInMilliseconds,
510
+ shouldDismissModals: params.shouldDismissModals
511
+ },
512
+ vaultPath: (0, import_vitest_global_setup_plugin.getTemporaryVault)().path
513
+ });
514
+ }
515
+ async function openNoteAndListButtonCaptions(note, settleTimeoutInMilliseconds) {
516
+ return (0, import_obsidian_integration_testing.evalInObsidian)({
517
+ async callback({ app, expectedButtonCount, intervalInMilliseconds, lib: { waitUntil }, notePath, obsidianModule, timeoutInMilliseconds }) {
518
+ function view() {
519
+ return app.workspace.getActiveViewOfType(obsidianModule.MarkdownView);
520
+ }
521
+ function previewEl() {
522
+ return view()?.containerEl.querySelector(":scope .markdown-preview-view") ?? null;
523
+ }
524
+ const seenCaptions = /* @__PURE__ */ new Set();
525
+ function captions() {
526
+ for (const button of view()?.containerEl.querySelectorAll(":scope .block-language-code-button button.mod-cta") ?? []) {
527
+ if (button.textContent !== "") {
528
+ seenCaptions.add(button.textContent);
529
+ }
530
+ }
531
+ return [...seenCaptions];
532
+ }
533
+ const SCROLL_BOTTOM_TOLERANCE_IN_PIXELS = 4;
534
+ const SCROLL_STEP_RATIO = 0.8;
535
+ function advanceScroll() {
536
+ const scroller = previewEl();
537
+ if (!scroller) {
538
+ return;
539
+ }
540
+ const isAtBottom = scroller.scrollTop + scroller.clientHeight >= scroller.scrollHeight - SCROLL_BOTTOM_TOLERANCE_IN_PIXELS;
541
+ scroller.scrollTop = isAtBottom ? 0 : scroller.scrollTop + Math.floor(scroller.clientHeight * SCROLL_STEP_RATIO);
542
+ }
543
+ await app.workspace.openLinkText(notePath.replace(/\.md$/, ""), "", false);
544
+ await app.workspace.getLeaf(false).setViewState({ state: { file: notePath, mode: "preview" }, type: "markdown" });
545
+ try {
546
+ await waitUntil({
547
+ intervalInMilliseconds,
548
+ message: `"${notePath}" never mounted all ${String(expectedButtonCount)} of its buttons`,
549
+ predicate: () => {
550
+ advanceScroll();
551
+ return captions().length >= expectedButtonCount;
552
+ },
553
+ timeoutInMilliseconds
554
+ });
555
+ } catch {
556
+ }
557
+ return captions();
558
+ },
559
+ input: {
560
+ expectedButtonCount: note.buttonCount,
561
+ intervalInMilliseconds: POLL_INTERVAL_IN_MILLISECONDS,
562
+ notePath: note.name,
563
+ timeoutInMilliseconds: settleTimeoutInMilliseconds
564
+ },
565
+ vaultPath: (0, import_vitest_global_setup_plugin.getTemporaryVault)().path
566
+ });
567
+ }
568
+ // Annotate the CommonJS export names for ESM import in node:
569
+ 0 && (module.exports = {
570
+ CODE_SCRIPT_TOOLKIT_PLUGIN_ID,
571
+ assertClickBudgetsFitTransportCap,
572
+ countRenderedButtons,
573
+ findDuplicateCaptions,
574
+ formatFailures,
575
+ listNotesWithButtons,
576
+ listRenderedButtonCaptions,
577
+ registerDemoVaultButtonSuite,
578
+ selectUnexpectedFailures
579
+ });
580
+ //# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsiLi4vLi4vLi4vc3JjL2RlbW8tdmF1bHQtYnV0dG9ucy50cyJdLAogICJzb3VyY2VzQ29udGVudCI6IFsiLyoqXG4gKiBAZmlsZVxuICpcbiAqIEEgdml0ZXN0IHN1aXRlIHRoYXQgb3BlbnMgZXZlcnkgbm90ZSBvZiBhIHBsdWdpbidzIGluLXJlcG8gYGRlbW8tdmF1bHQvYCwgY2xpY2tzIGVhY2ggYGNvZGUtYnV0dG9uYFxuICogaW4gaXQgYWdhaW5zdCBhIHJlYWwgT2JzaWRpYW4sIGFuZCBmYWlscyBvbiBhbnkgYnV0dG9uIHRoYXQgZXJyb3JzIG9yIG5ldmVyIHJlcG9ydHMgYSByZXN1bHQuXG4gKlxuICogQSBkZW1vIHZhdWx0J3MgYnV0dG9ucyBhcmUgdGhlIG9uZSBwYXJ0IG9mIGl0IG5vIG90aGVyIGdhdGUgY2FuIGNoZWNrLiBgbGludDptZGAgcmVhZHMgdGhlIG1hcmtkb3duLFxuICogdGhlIGNvdmVyYWdlIHN1aXRlICh7QGxpbmsgLi9kZW1vLXZhdWx0LWNvdmVyYWdlLnRzIHwgYHJlZ2lzdGVyRGVtb1ZhdWx0Q292ZXJhZ2VTdWl0ZWB9KSBjaGVja3MgdGhlXG4gKiBhdXRob3JpbmcgY29udmVudGlvbnMsIGFuZCBuZWl0aGVyIGV4ZWN1dGVzIGFueXRoaW5nIFx1MjAxNCBhIGJ1dHRvbiB3aG9zZSBgcmVxdWlyZSgnL2RlbW9TZXR1cC50cycpYCBwYXRoXG4gKiBpcyB3cm9uZywgb3IgdGhhdCBjYWxscyBhbiBBUEkgdGhhdCBoYXMgc2luY2UgY2hhbmdlZCBzaGFwZSwgZmFpbHMgYXQgY2xpY2sgdGltZSBhbmQgbm93aGVyZSBlbHNlLlxuICpcbiAqIFRoZSBjb21wYW5pb24gaGFsZiBcdTIwMTQgc2VlZGluZyB0aGUgdGVtcCB2YXVsdCB3aXRoIHRoZSBkZW1vLXZhdWx0IHRyZWUsIGl0cyBgLm9ic2lkaWFuYCBjb25maWcsIGFuZCB0aGVcbiAqIENvZGVTY3JpcHQgVG9vbGtpdCBiaW5hcnkgdGhhdCB0dXJucyBgYGBgIGBgYGNvZGUtYnV0dG9uIGBgYGAgZmVuY2VzIGludG8gYnV0dG9ucyBcdTIwMTQgaXNcbiAqIGBidWlsZERlbW9WYXVsdFBvcHVsYXRlYCBpbiBgb2JzaWRpYW4taW50ZWdyYXRpb24tdGVzdGluZ2A7IGhhbmQgaXRzIHJlc3VsdCB0byB0aGUgcHJvamVjdCdzXG4gKiBgZ2xvYmFsU2V0dXBgIGFuZCBuYW1lIENvZGVTY3JpcHQgVG9vbGtpdCBpbiBgZW5hYmxlQ29tbXVuaXR5UGx1Z2luc2AuXG4gKi9cblxuaW1wb3J0IHsgZ2V0Um9vdEZvbGRlciB9IGZyb20gJ0BtbmFvdW1vdi90eXBlc2NyaXB0LWRldi10b29sa2l0L3Jvb3QnO1xuaW1wb3J0IHtcbiAgcmVhZGRpclN5bmMsXG4gIHJlYWRGaWxlU3luY1xufSBmcm9tICdub2RlOmZzJztcbmltcG9ydCB7IGpvaW4gfSBmcm9tICdub2RlOnBhdGgnO1xuaW1wb3J0IHByb2Nlc3MgZnJvbSAnbm9kZTpwcm9jZXNzJztcbmltcG9ydCB7XG4gIERFRkFVTFRfRVZBTF9DQVBfSU5fTUlMTElTRUNPTkRTLFxuICBldmFsSW5PYnNpZGlhblxufSBmcm9tICdvYnNpZGlhbi1pbnRlZ3JhdGlvbi10ZXN0aW5nJztcbmltcG9ydCB7IGdldFRlbXBvcmFyeVZhdWx0IH0gZnJvbSAnb2JzaWRpYW4taW50ZWdyYXRpb24tdGVzdGluZy92aXRlc3QtZ2xvYmFsLXNldHVwLXBsdWdpbic7XG5pbXBvcnQge1xuICBiZWZvcmVBbGwsXG4gIGRlc2NyaWJlLFxuICBleHBlY3QsXG4gIGl0XG59IGZyb20gJ3ZpdGVzdCc7XG5cbi8qKlxuICogQ29kZVNjcmlwdCBUb29sa2l0J3MgbWFuaWZlc3QgaWQuIEl0IGlzIHN0aWxsIHRoZSBwbHVnaW4ncyBvcmlnaW5hbCBgZml4LXJlcXVpcmUtbW9kdWxlc2AgaWQsIHdoaWNoXG4gKiBubyBsb25nZXIgbWF0Y2hlcyBpdHMgbmFtZSBcdTIwMTQgdGhlIGlkIGlzIHB1Ymxpc2hlZCwgc28gaXQgY2Fubm90IGJlIGNoYW5nZWQuXG4gKi9cbmV4cG9ydCBjb25zdCBDT0RFX1NDUklQVF9UT09MS0lUX1BMVUdJTl9JRCA9ICdmaXgtcmVxdWlyZS1tb2R1bGVzJztcblxuLyoqXG4gKiBUaGUgd2FpdGluZyBidWRnZXRzIGEgc2luZ2xlIGJ1dHRvbiBjbGljayBpcyBhbGxvd2VkLlxuICpcbiAqIEJvdGggYXJlIHNwZW50IGluc2lkZSBPTkUgdHJhbnNwb3J0IGNhbGwsIHNvIGl0IGlzIHRoZWlyIFNVTSB0aGF0XG4gKiB7QGxpbmsgYXNzZXJ0Q2xpY2tCdWRnZXRzRml0VHJhbnNwb3J0Q2FwfSBib3VuZHMuXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgQ2xpY2tCdXR0b25UaW1lb3V0cyB7XG4gIC8qKlxuICAgKiBIb3cgbG9uZyB0byB3YWl0IGZvciB0aGUgY2xpY2tlZCBidXR0b24gdG8gcmVwb3J0IGEgcmVzdWx0LlxuICAgKi9cbiAgcmVhZG9ubHkgYnV0dG9uUmVzdWx0VGltZW91dEluTWlsbGlzZWNvbmRzOiBudW1iZXI7XG5cbiAgLyoqXG4gICAqIEhvdyBsb25nIHRvIHdhaXQgZm9yIHRoZSBidXR0b24gaXRzZWxmIHRvIG1vdW50LlxuICAgKi9cbiAgcmVhZG9ubHkgc2V0dGxlVGltZW91dEluTWlsbGlzZWNvbmRzOiBudW1iZXI7XG59XG5cbi8qKlxuICogVGhlIG91dGNvbWUgb2YgY2xpY2tpbmcgb25lIGJ1dHRvbi5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBEZW1vVmF1bHRCdXR0b25SZXN1bHQge1xuICAvKipcbiAgICogVGhlIGJ1dHRvbidzIGNhcHRpb24sIGFzIHJlbmRlcmVkLlxuICAgKi9cbiAgcmVhZG9ubHkgY2FwdGlvbjogc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBUaGUgcmVzdWx0IGxpbmUgQ29kZVNjcmlwdCBUb29sa2l0IHByaW50ZWQgdW5kZXIgdGhlIGJ1dHRvbiwgdHJ1bmNhdGVkLlxuICAgKi9cbiAgcmVhZG9ubHkgb3V0cHV0OiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIFdoZXRoZXIgdGhlIGJ1dHRvbiByZXBvcnRlZCBzdWNjZXNzLCByZXBvcnRlZCBhbiBlcnJvciwgb3IgbmV2ZXIgcmVwb3J0ZWQgYXQgYWxsLlxuICAgKi9cbiAgcmVhZG9ubHkgc3RhdHVzOiAnZXJyb3InIHwgJ29rJyB8ICd0aW1lb3V0JyB8ICd1bmtub3duJztcbn1cblxuLyoqXG4gKiBPbmUgZGVtby12YXVsdCBub3RlIGFuZCBob3cgbWFueSBidXR0b25zIGl0cyBzb3VyY2UgZGVjbGFyZXMuXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgRGVtb1ZhdWx0Tm90ZSB7XG4gIC8qKlxuICAgKiBIb3cgbWFueSBidXR0b25zIHRoZSBub3RlJ3Mgc291cmNlIHJlbmRlcnMsIGFzIGNvdW50ZWQgYnkge0BsaW5rIGNvdW50UmVuZGVyZWRCdXR0b25zfS5cbiAgICovXG4gIHJlYWRvbmx5IGJ1dHRvbkNvdW50OiBudW1iZXI7XG5cbiAgLyoqXG4gICAqIFRoZSBjYXB0aW9ucyBvZiB0aG9zZSBidXR0b25zLCBpbiBzb3VyY2Ugb3JkZXIsIGFzIHJlYWQgYnkge0BsaW5rIGxpc3RSZW5kZXJlZEJ1dHRvbkNhcHRpb25zfS5cbiAgICovXG4gIHJlYWRvbmx5IGNhcHRpb25zOiByZWFkb25seSBzdHJpbmdbXTtcblxuICAvKipcbiAgICogVGhlIG5vdGUncyBmaWxlIG5hbWUsIHJlbGF0aXZlIHRvIHRoZSBkZW1vIHZhdWx0IHJvb3QuXG4gICAqL1xuICByZWFkb25seSBuYW1lOiBzdHJpbmc7XG59XG5cbi8qKlxuICogQSBidXR0b24gdGhhdCBpcyBFWFBFQ1RFRCBub3QgdG8gcmVwb3J0IHN1Y2Nlc3MsIHNvIHRoZSBzdWl0ZSBkb2VzIG5vdCBmYWlsIG9uIGl0LlxuICovXG5leHBvcnQgaW50ZXJmYWNlIEV4cGVjdGVkTm9uT2tCdXR0b24ge1xuICAvKipcbiAgICogQSBzdWJzdHJpbmcgb2YgdGhlIGJ1dHRvbidzIHJlbmRlcmVkIGNhcHRpb24uXG4gICAqL1xuICByZWFkb25seSBjYXB0aW9uSW5jbHVkZXM6IHN0cmluZztcblxuICAvKipcbiAgICogVGhlIG5vdGUgaG9sZGluZyB0aGUgYnV0dG9uLCByZWxhdGl2ZSB0byB0aGUgZGVtbyB2YXVsdCByb290LlxuICAgKi9cbiAgcmVhZG9ubHkgbm90ZTogc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBUaGUgc3RhdHVzIHRoZSBidXR0b24gaXMgZXhwZWN0ZWQgdG8gZW5kIGluLiBBbnkgb3RoZXIgc3RhdHVzIHN0aWxsIGZhaWxzLCBzbyBhbiBlcnJvciBkZW1vIHRoYXRcbiAgICogc3RhcnRzIHRpbWluZyBvdXQgaW5zdGVhZCBpcyByZXBvcnRlZCByYXRoZXIgdGhhbiB3YXZlZCB0aHJvdWdoLlxuICAgKi9cbiAgcmVhZG9ubHkgc3RhdHVzOiBFeGNsdWRlPERlbW9WYXVsdEJ1dHRvblJlc3VsdFsnc3RhdHVzJ10sICdvayc+O1xufVxuXG4vKipcbiAqIFRoZSBvcHRpb25zIGZvciB7QGxpbmsgcmVnaXN0ZXJEZW1vVmF1bHRCdXR0b25TdWl0ZX0uXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgUmVnaXN0ZXJEZW1vVmF1bHRCdXR0b25TdWl0ZU9wdGlvbnMge1xuICAvKipcbiAgICogSG93IGxvbmcsIGluIG1pbGxpc2Vjb25kcywgdG8gd2FpdCBmb3IgYSBjbGlja2VkIGJ1dHRvbiB0byByZXBvcnQgYSByZXN1bHQuXG4gICAqXG4gICAqIEJvdW5kZWQgYnkgdGhlIHNhbWUgc3VtIGFzIHtAbGluayBSZWdpc3RlckRlbW9WYXVsdEJ1dHRvblN1aXRlT3B0aW9ucy5zZXR0bGVUaW1lb3V0SW5NaWxsaXNlY29uZHN9LFxuICAgKiBhbmQgcmVmdXNlZCBieSB0aGUgc2FtZSB0aHJvdyBhdCByZWdpc3RyYXRpb24uXG4gICAqXG4gICAqIEBkZWZhdWx0IGAxMDAwMGBcbiAgICovXG4gIHJlYWRvbmx5IGJ1dHRvblJlc3VsdFRpbWVvdXRJbk1pbGxpc2Vjb25kcz86IG51bWJlcjtcblxuICAvKipcbiAgICogRm9sZGVycyB0byBza2lwIHdob2xlLCBtYXRjaGVkIGFnYWluc3QgYm90aCB0aGUgZm9sZGVyIG5hbWUgYW5kIGl0cyBwYXRoIHJlbGF0aXZlIHRvIHRoZSBkZW1vIHZhdWx0XG4gICAqIHJvb3QgXHUyMDE0IGZvciBhIGdyb3VwIHdob3NlIG5vdGVzIGNhbm5vdCBydW4gdW5hdHRlbmRlZCwgc3VjaCBhcyBvbmVzIHRoYXQgZmlyc3QgaW5zdGFsbCBhIHRoaXJkLXBhcnR5XG4gICAqIHBsdWdpbiBmcm9tIHRoZSBjb21tdW5pdHkgc3RvcmUuXG4gICAqXG4gICAqIEBkZWZhdWx0IGBbXWBcbiAgICovXG4gIHJlYWRvbmx5IGV4Y2x1ZGVkRm9sZGVycz86IHJlYWRvbmx5IHN0cmluZ1tdO1xuXG4gIC8qKlxuICAgKiBOb3RlIGZpbGUgbmFtZXMgKHJlbGF0aXZlIHRvIHRoZSBkZW1vIHZhdWx0IHJvb3QpIHRvIHNraXAuXG4gICAqXG4gICAqIEBkZWZhdWx0IGBbJ1JFQURNRS5tZCddYFxuICAgKi9cbiAgcmVhZG9ubHkgZXhjbHVkZWROb3Rlcz86IHJlYWRvbmx5IHN0cmluZ1tdO1xuXG4gIC8qKlxuICAgKiBCdXR0b25zIHRoYXQgbGVnaXRpbWF0ZWx5IGRvIG5vdCByZXBvcnQgc3VjY2VzczogYW4gZXJyb3IgZGVtbywgb3IgYSBidXR0b24gdGhhdCB0dXJucyBzeXN0ZW1cbiAgICogbWVzc2FnZXMgb2ZmIGFuZCBzbyBuZXZlciBwcmludHMgdGhlIHJlc3VsdCBsaW5lIHRoZSBzdWl0ZSBjbGFzc2lmaWVzLlxuICAgKlxuICAgKiBAZGVmYXVsdCBgW11gXG4gICAqL1xuICByZWFkb25seSBleHBlY3RlZE5vbk9rQnV0dG9ucz86IHJlYWRvbmx5IEV4cGVjdGVkTm9uT2tCdXR0b25bXTtcblxuICAvKipcbiAgICogVGhlIHJlcG9zaXRvcnkgcm9vdCBob2xkaW5nIGBkZW1vLXZhdWx0L2AuXG4gICAqXG4gICAqIEBkZWZhdWx0IHRoZSByZXNvbHZlZCByZXBvIHJvb3QsIGZhbGxpbmcgYmFjayB0byBgcHJvY2Vzcy5jd2QoKWAuXG4gICAqL1xuICByZWFkb25seSByb290Rm9sZGVyPzogc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBIb3cgbG9uZywgaW4gbWlsbGlzZWNvbmRzLCB0byB3YWl0IGZvciBhIG5vdGUncyBwcmV2aWV3IGFuZCBpdHMgYnV0dG9ucyB0byBtb3VudC5cbiAgICpcbiAgICogVG9nZXRoZXIgd2l0aCBgYnV0dG9uUmVzdWx0VGltZW91dEluTWlsbGlzZWNvbmRzYCB0aGlzIG11c3Qgc3RheSB1bmRlciB0aGUgdHJhbnNwb3J0J3MgfjMwIHMgc2NyaXB0XG4gICAqIHRpbWVvdXQ6IG9uZSBidXR0b24gY2xpY2sgc3BlbmRzIGJvdGggaW5zaWRlIGEgU0lOR0xFIGV2YWx1YXRpb24sIHNvIGEgc3VtIGF0IG9yIG92ZXIgdGhlIGNhcCBjYW5ub3RcbiAgICogYmUgaG9ub3VyZWQgYW5kIHR1cm5zIGEgcmVhbCB0aW1lb3V0IGludG8gYSBiYXJlIGBzY3JpcHQgdGltZW91dGAgbmFtaW5nIG9ubHkgdGhlIHRyYW5zcG9ydC5cbiAgICoge0BsaW5rIHJlZ2lzdGVyRGVtb1ZhdWx0QnV0dG9uU3VpdGV9IHRocm93cyBvbiBzdWNoIGEgcGFpciByYXRoZXIgdGhhbiByZWdpc3RlcmluZyBpdC5cbiAgICpcbiAgICogQGRlZmF1bHQgYDEyMDAwYFxuICAgKi9cbiAgcmVhZG9ubHkgc2V0dGxlVGltZW91dEluTWlsbGlzZWNvbmRzPzogbnVtYmVyO1xuXG4gIC8qKlxuICAgKiBXaGV0aGVyIHRvIGRpc21pc3MgYW55IG9wZW4gbW9kYWwgd2hpbGUgd2FpdGluZyBmb3IgYSBjbGlja2VkIGJ1dHRvbidzIHJlc3VsdCwgYW5kIGFnYWluIG9uY2UgaXQgaXNcbiAgICogY2xhc3NpZmllZC5cbiAgICpcbiAgICogQSBidXR0b24gdGhhdCBgYXdhaXRgcyBhbiBgYWxlcnRgIC8gYGNvbmZpcm1gIC8gYHByb21wdGAgY2Fubm90IHJlcG9ydCBhIHJlc3VsdCB1bnRpbCBzb21lYm9keSBjbG9zZXNcbiAgICogdGhlIGRpYWxvZywgc28gd2l0aG91dCB0aGlzIGl0IGVuZHMgYXMgYHRpbWVvdXRgIFx1MjAxNCBhbmQgdGhlIGRpYWxvZyBpdCBsZWZ0IG9wZW4gdGhlbiBzaXRzIG92ZXIgZXZlcnlcbiAgICogbGF0ZXIgYnV0dG9uIGluIHRoZSBydW4uIE9mZiBieSBkZWZhdWx0LCBzbyBubyBzdWl0ZSBjaGFuZ2VzIGJlaGF2aW9yIHVuYXNrZWQuXG4gICAqXG4gICAqIEBkZWZhdWx0IGBmYWxzZWBcbiAgICovXG4gIHJlYWRvbmx5IHNob3VsZERpc21pc3NNb2RhbHM/OiBib29sZWFuO1xufVxuXG4vKlxuICogVGhlc2UgdHdvIGFyZSBzcGVudCBJTlNJREUgT05FIGBldmFsSW5PYnNpZGlhbmAgY2xvc3VyZSBieSBgY2xpY2tCdXR0b25gLCB3aGljaCB3YWl0cyBmb3IgdGhlIGJ1dHRvbiB0b1xuICogbW91bnQgYW5kIHRoZW4gZm9yIGl0cyByZXN1bHQsIHNvIGl0IGlzIHRoZWlyIFNVTSB0aGF0IGhhcyB0byBzdGF5IHVuZGVyIHRoZSB0cmFuc3BvcnQncyB+MzAgcyBzY3JpcHRcbiAqIHRpbWVvdXQgXHUyMDE0IG5vdCBlaXRoZXIgb25lIGFsb25lLiBUaGUgZm9ybWVyIDIwIDAwMCArIDE1IDAwMCBhc2tlZCBmb3IgMzUgcywgd2hpY2ggdGhlIHRyYW5zcG9ydCBjYW4gbmV2ZXJcbiAqIGdyYW50OiBhIHNsb3cgYnV0dG9uIGRpZCBub3QgcmVwb3J0IFwibmV2ZXIgcmVwb3J0ZWQgYSByZXN1bHRcIiwgaXQgZGllZCBhcyBhIGJhcmUgYHNjcmlwdCB0aW1lb3V0YCBuYW1pbmdcbiAqIG9ubHkgdGhlIHRyYW5zcG9ydC4gYG5vLW92ZXItY2FwLXdhaXQtaW4tZXZhbC1pbi1vYnNpZGlhbmAgY2Fubm90IGNhdGNoIHRoaXMgb25lLCBiZWNhdXNlIHRoZSBidWRnZXRzXG4gKiByZWFjaCB0aGUgY2xvc3VyZSBmcm9tIGEgY2FsbGVyIHR3byBsZXZlbHMgdXAgcmF0aGVyIHRoYW4gYmVpbmcgd3JpdHRlbiBhdCB0aGUgd2FpdCBcdTIwMTQgd2hpY2ggaXMgd2h5XG4gKiBgYXNzZXJ0Q2xpY2tCdWRnZXRzRml0VHJhbnNwb3J0Q2FwYCBiZWxvdyBlbmZvcmNlcyBhdCBydW50aW1lIHdoYXQgdGhlIHJ1bGUgY2Fubm90IHNlZS4gT3ZlcnJpZGluZ1xuICogZWl0aGVyIGRlZmF1bHQgdmlhIGBSZWdpc3RlckRlbW9WYXVsdEJ1dHRvblN1aXRlT3B0aW9uc2AgaXMgc3ViamVjdCB0byB0aGUgc2FtZSBzdW0uXG4gKi9cbmNvbnN0IERFRkFVTFRfQlVUVE9OX1JFU1VMVF9USU1FT1VUX0lOX01JTExJU0VDT05EUyA9IDEwXzAwMDtcbmNvbnN0IERFRkFVTFRfU0VUVExFX1RJTUVPVVRfSU5fTUlMTElTRUNPTkRTID0gMTJfMDAwO1xuXG5pbnRlcmZhY2UgQ2xpY2tCdXR0b25QYXJhbXMge1xuICAvKipcbiAgICogVGhlIGJ1dHRvbidzIHJlbmRlcmVkIGNhcHRpb24sIHdoaWNoIGlzIGhvdyBpdCBpcyBhZGRyZXNzZWQuXG4gICAqL1xuICByZWFkb25seSBidXR0b25DYXB0aW9uOiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIFRoZSBub3RlIGhvbGRpbmcgdGhlIGJ1dHRvbi5cbiAgICovXG4gIHJlYWRvbmx5IG5vdGVQYXRoOiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIFdoZXRoZXIgdG8gZGlzbWlzcyB0aGUgbW9kYWxzIHRoZSBidXR0b24gb3BlbnMuXG4gICAqL1xuICByZWFkb25seSBzaG91bGREaXNtaXNzTW9kYWxzOiBib29sZWFuO1xuXG4gIC8qKlxuICAgKiBUaGUgcmVuZGVyIGFuZCByZXN1bHQgYnVkZ2V0cy5cbiAgICovXG4gIHJlYWRvbmx5IHRpbWVvdXRzOiBDbGlja0J1dHRvblRpbWVvdXRzO1xufVxuXG5jb25zdCBQT0xMX0lOVEVSVkFMX0lOX01JTExJU0VDT05EUyA9IDEwMDtcbmNvbnN0IE9VVFBVVF9FWENFUlBUX0xFTkdUSCA9IDQwMDtcblxuLy8gYFJFQURNRS5tZGAgaXMgdGhlIHJlcG8tZmFjaW5nIHBhZ2UgR2l0SHViIHJlbmRlcnMsIG5vdCBhIHdhbGt0aHJvdWdoLiBgMDAgU3RhcnQubWRgIGlzIGRlbGliZXJhdGVseVxuLy8gTk9UIGV4Y2x1ZGVkOiB0aGUgbGFuZGluZyBub3RlcyBjYXJyeSBidXR0b25zIG9mIHRoZWlyIG93bi5cbmNvbnN0IERFRkFVTFRfRVhDTFVERURfTk9URVMgPSBbJ1JFQURNRS5tZCddO1xuXG4vLyBBIGZlbmNlIGxpbmU6IGl0cyBtYXJrZXIgcnVuICh0aHJlZSBvciBtb3JlIGJhY2t0aWNrcyBvciB0aWxkZXMpIGFuZCB3aGF0ZXZlciBmb2xsb3dzIGl0LlxuY29uc3QgRkVOQ0VfUkVHX0VYUCA9IC9eKD88aW5kZW50PlxccyopKD88bWFya2VyPmB7Myx9fH57Myx9KSg/PGluZm8+LiopJC87XG5jb25zdCBDT0RFX0JVVFRPTl9GRU5DRV9JTkZPID0gJ2NvZGUtYnV0dG9uJztcbmNvbnN0IEZST05UX01BVFRFUl9ERUxJTUlURVIgPSAnLS0tJztcbmNvbnN0IFJBV19NT0RFX0NPTkZJR19SRUdfRVhQID0gL15pc1JhdzpcXHMqdHJ1ZVxccyokL207XG5jb25zdCBDQVBUSU9OX0NPTkZJR19SRUdfRVhQID0gL15jYXB0aW9uOig/PHZhbHVlPi4qKSQvbTtcbmNvbnN0IFBMQUlOX1NDQUxBUl9DT01NRU5UX1JFR19FWFAgPSAvXFxzKyMuKiQvO1xuY29uc3QgU0lOR0xFX1FVT1RFRF9TQ0FMQVJfUkVHX0VYUCA9IC9eJyg/PGNvbnRlbnQ+LiopJyQvO1xuY29uc3QgRE9VQkxFX1FVT1RFRF9TQ0FMQVJfUkVHX0VYUCA9IC9eXCIoPzxjb250ZW50Pi4qKVwiJC87XG4vLyBDb2RlU2NyaXB0IFRvb2xraXQncyBvd24gZGVmYXVsdCwgd2hpY2ggYSBmZW5jZSBuYW1pbmcgbm8gY2FwdGlvbiByZW5kZXJzLlxuY29uc3QgREVGQVVMVF9DT0RFX0JVVFRPTl9DQVBUSU9OID0gJyhubyBjYXB0aW9uKSc7XG5cbi8vIFRoZSByZW5kZXJlZC1idXR0b24gc2VsZWN0b3IgaXMgYDpzY29wZSAuYmxvY2stbGFuZ3VhZ2UtY29kZS1idXR0b24gYnV0dG9uLm1vZC1jdGFgLiBJdCBpcyB3cml0dGVuXG4vLyBvdXQgYXQgZWFjaCB1c2Ugc2l0ZSByYXRoZXIgdGhhbiBoZWxkIGluIGEgY29uc3RhbnQgaGVyZTogZXZlcnkgY2xvc3VyZSBiZWxvdyBpcyBzZXJpYWxpemVkIHdpdGhcbi8vIGB0b1N0cmluZygpYCBhbmQgZXZhbHVhdGVkIGluc2lkZSBPYnNpZGlhbiwgd2hlcmUgbm90aGluZyBmcm9tIHRoaXMgbW9kdWxlJ3Mgc2NvcGUgZXhpc3RzLlxuXG4vKipcbiAqIFJlZnVzZXMgYSBzZXR0bGUvcmVzdWx0IGJ1ZGdldCBwYWlyIHRoYXQgYSBzaW5nbGUgdHJhbnNwb3J0IGNhbGwgY291bGQgbmV2ZXIgaG9ub3VyLlxuICpcbiAqIGBjbGlja0J1dHRvbmAgd2FpdHMgZm9yIHRoZSBidXR0b24gdG8gbW91bnQgYW5kIHRoZW4gZm9yIGl0cyByZXN1bHQgSU5TSURFIE9ORSBgZXZhbEluT2JzaWRpYW5gXG4gKiBjbG9zdXJlLCBzbyB0aGUgdHJhbnNwb3J0J3Mgc2NyaXB0IHRpbWVvdXQgYm91bmRzIHRoZWlyIHN1bSByYXRoZXIgdGhhbiBlaXRoZXIgb25lIGFsb25lIFx1MjAxNCBhbmRcbiAqIGBSZWdpc3RlckRlbW9WYXVsdEJ1dHRvblN1aXRlT3B0aW9uc2AgbGV0cyBhIGNvbnN1bWVyIHJhaXNlIGVhY2ggaW5kZXBlbmRlbnRseSwgd2l0aCBub3RoaW5nIHN1bW1pbmdcbiAqIHRoZW0uIFJhaXNpbmcgYHNldHRsZVRpbWVvdXRJbk1pbGxpc2Vjb25kc2AgdG8gMjAgMDAwIGZvciBvbmUgc2xvdyBub3RlIGlzIGFuIG9yZGluYXJ5IHRoaW5nIHRvIGRvIGFuZFxuICogc2lsZW50bHkgcHV0cyB0aGUgcGFpciBhdCB0aGUgY2FwLlxuICpcbiAqIFRocm93aW5nIGhlcmUsIGF0IHN1aXRlIHJlZ2lzdHJhdGlvbiwgaXMgdGhlIHdob2xlIHZhbHVlOiB0aGUgZmFpbHVyZSBpdCByZXBsYWNlcyBpcyBhXG4gKiBgV2ViRHJpdmVyRXJyb3I6IHNjcmlwdCB0aW1lb3V0YCByYWlzZWQgbWlkLXJ1biBhZ2FpbnN0IHdoaWNoZXZlciBidXR0b24gaGFwcGVuZWQgdG8gYmUgc2xvd2VzdCxcbiAqIG5hbWluZyB0aGUgdHJhbnNwb3J0IGFuZCBuZWl0aGVyIGJ1ZGdldC5cbiAqXG4gKiBAcGFyYW0gdGltZW91dHMgLSBUaGUge0BsaW5rIENsaWNrQnV0dG9uVGltZW91dHN9IHRvIGJvdW5kLlxuICovXG5leHBvcnQgZnVuY3Rpb24gYXNzZXJ0Q2xpY2tCdWRnZXRzRml0VHJhbnNwb3J0Q2FwKHRpbWVvdXRzOiBDbGlja0J1dHRvblRpbWVvdXRzKTogdm9pZCB7XG4gIGNvbnN0IHRvdGFsSW5NaWxsaXNlY29uZHMgPSB0aW1lb3V0cy5zZXR0bGVUaW1lb3V0SW5NaWxsaXNlY29uZHMgKyB0aW1lb3V0cy5idXR0b25SZXN1bHRUaW1lb3V0SW5NaWxsaXNlY29uZHM7XG5cbiAgLypcbiAgICogVGhlIGNvbXBhcmlzb24gaXMgYDxgIHJhdGhlciB0aGFuIGA8PWAgYmVjYXVzZSBhIHN1bSB0aGF0IG1lcmVseSBSRUFDSEVTIHRoZSBjYXAgY2FuIGFscmVhZHkgbmV2ZXJcbiAgICogYmUgaG9ub3VyZWQ6IGBuby1vdmVyLWNhcC13YWl0LWluLWV2YWwtaW4tb2JzaWRpYW5gIHJlcG9ydHMgYXQgdGhlIGNhcCBhcyB3ZWxsIGFzIG92ZXIgaXQsIGFuZCBhXG4gICAqIGNsb3N1cmUgaGFuZGVkIGV4YWN0bHkgdGhlIHRyYW5zcG9ydCdzIGJ1ZGdldCBoYXMgbm90aGluZyBsZWZ0IGZvciB0aGUgZGlzcGF0Y2ggaXRzZWxmLlxuICAgKi9cbiAgaWYgKHRvdGFsSW5NaWxsaXNlY29uZHMgPCBERUZBVUxUX0VWQUxfQ0FQX0lOX01JTExJU0VDT05EUykge1xuICAgIHJldHVybjtcbiAgfVxuXG4gIHRocm93IG5ldyBFcnJvcihcbiAgICBgT25lIGRlbW8tdmF1bHQgYnV0dG9uIGNsaWNrIHNwZW5kcyBzZXR0bGVUaW1lb3V0SW5NaWxsaXNlY29uZHMgKCR7U3RyaW5nKHRpbWVvdXRzLnNldHRsZVRpbWVvdXRJbk1pbGxpc2Vjb25kcyl9IG1zKSBhbmQgYFxuICAgICAgKyBgYnV0dG9uUmVzdWx0VGltZW91dEluTWlsbGlzZWNvbmRzICgke1N0cmluZyh0aW1lb3V0cy5idXR0b25SZXN1bHRUaW1lb3V0SW5NaWxsaXNlY29uZHMpfSBtcykgaW5zaWRlIGEgc2luZ2xlIHRyYW5zcG9ydCBjYWxsLCBgXG4gICAgICArIGBzbyB0aGVpciBzdW0gb2YgJHtTdHJpbmcodG90YWxJbk1pbGxpc2Vjb25kcyl9IG1zIGlzIGF0IG9yIG92ZXIgdGhlIHRyYW5zcG9ydCdzIGBcbiAgICAgICsgYCR7U3RyaW5nKERFRkFVTFRfRVZBTF9DQVBfSU5fTUlMTElTRUNPTkRTKX0gbXMgc2NyaXB0IHRpbWVvdXQgYW5kIGNhbiBuZXZlciBiZSBob25vdXJlZC4gYFxuICAgICAgKyAnTG93ZXIgZWl0aGVyIGJ1ZGdldCBpbiBSZWdpc3RlckRlbW9WYXVsdEJ1dHRvblN1aXRlT3B0aW9ucy4nXG4gICk7XG59XG5cbi8qKlxuICogQ291bnRzIHRoZSBidXR0b25zIGEgbm90ZSdzIHNvdXJjZSB3aWxsIGFjdHVhbGx5IHJlbmRlci5cbiAqXG4gKiBUaHJlZSBraW5kcyBvZiBgIGBgYGNvZGUtYnV0dG9uIGAgZmVuY2UgcmVuZGVyIG5vIGNsaWNrYWJsZSBidXR0b24sIGFuZCBhIHZhdWx0IHRoYXQgRE9DVU1FTlRTIGNvZGVcbiAqIGJ1dHRvbnMgaXMgZnVsbCBvZiB0aGUgZmlyc3QgdHdvOlxuICpcbiAqIC0gQSBmZW5jZSBuZXN0ZWQgaW5zaWRlIGEgbG9uZ2VyIG9yIGRpZmZlcmVudCBmZW5jZSAoYSBgYGBgIGBgYGBtYXJrZG93biBgYGBgIG9yIGB+fn5gIGJsb2NrKSBpcyBhXG4gKiAgIG1hcmtkb3duIFNBTVBMRSBzaG93biB0byB0aGUgcmVhZGVyOyB0aGUgcmVuZGVyZXIgbmV2ZXIgc2VlcyBpdCBhcyBhIGJsb2NrLlxuICogLSBBbiBgaXNSYXc6IHRydWVgIGZlbmNlIHJlbmRlcnMgaXRzIG91dHB1dCBkaXJlY3RseSBhbmQgbm8gYnV0dG9uIGVsZW1lbnQgYXQgYWxsLlxuICogLSBBIGZlbmNlIHdob3NlIGluZm8gc3RyaW5nIGNhcnJpZXMgYW55dGhpbmcgYWZ0ZXIgYGNvZGUtYnV0dG9uYCB1c2VzIHRoZSBsZWdhY3kgYXJndW1lbnQgc3ludGF4LCB3aGljaFxuICogICByZW5kZXJzIGFuIGVycm9yIGJhbm5lciBhc2tpbmcgdG8gdXBkYXRlIHRoZSBjb25maWcgcmF0aGVyIHRoYW4gdGhlIGJ1dHRvbi5cbiAqXG4gKiBDb3VudGluZyBhbnkgb2YgdGhlbSBtYWtlcyB0aGUgc3VpdGUncyBzaG9ydGZhbGwgYXNzZXJ0aW9uIHVuc2F0aXNmaWFibGUgXHUyMDE0IGl0IGRlbWFuZHMgbW9yZSBidXR0b25zXG4gKiB0aGFuIHRoZSBub3RlIGNhbiBldmVyIHJlbmRlciBcdTIwMTQgYW5kIGFuIGFzc2VydGlvbiB0aGF0IGNhbm5vdCBwYXNzIGdhdGVzIG5vdGhpbmcuXG4gKlxuICogVGhlIHNjYW4gZm9sbG93cyBDb21tb25NYXJrJ3MgZmVuY2UgcnVsZXM6IGEgZmVuY2UgY2xvc2VzIG9ubHkgb24gYSBydW4gb2YgdGhlIFNBTUUgY2hhcmFjdGVyIGF0IGxlYXN0XG4gKiBhcyBsb25nIGFzIHRoZSBvcGVuZXIsIHdpdGggbm8gaW5mbyBzdHJpbmcsIGFuZCBvbmUgbGVmdCBvcGVuIHJ1bnMgdG8gdGhlIGVuZCBvZiB0aGUgZG9jdW1lbnQsIHdoZXJlIGl0XG4gKiBzdGlsbCByZW5kZXJzLlxuICpcbiAqIEBwYXJhbSBzb3VyY2UgLSBUaGUgbm90ZSdzIG1hcmtkb3duLlxuICogQHJldHVybnMgSG93IG1hbnkgYnV0dG9ucyBpdCByZW5kZXJzLlxuICovXG5leHBvcnQgZnVuY3Rpb24gY291bnRSZW5kZXJlZEJ1dHRvbnMoc291cmNlOiBzdHJpbmcpOiBudW1iZXIge1xuICByZXR1cm4gbGlzdFJlbmRlcmVkQnV0dG9uQ2FwdGlvbnMoc291cmNlKS5sZW5ndGg7XG59XG5cbi8qKlxuICogRmluZHMgdGhlIGNhcHRpb25zIGRlY2xhcmVkIGJ5IG1vcmUgdGhhbiBvbmUgYnV0dG9uLlxuICpcbiAqIFRoZSBzdWl0ZSBhZGRyZXNzZXMgYSBidXR0b24gYnkgaXRzIGNhcHRpb24gXHUyMDE0IGl0IGNvbGxlY3RzIHRoZSBjYXB0aW9ucyB0aGF0IG1vdW50ZWQgYW5kIGNsaWNrcyB0aGVcbiAqIGJ1dHRvbiBjYXJyeWluZyBlYWNoIG9uZSBcdTIwMTQgc28gdHdvIGJ1dHRvbnMgc2hhcmluZyBhIGNhcHRpb24gY29sbGFwc2UgaW50byBvbmU6IHRoZSBzZWNvbmQgaXMgbmV2ZXJcbiAqIGNsaWNrZWQsIGFuZCB0aGUgbm90ZSByZWFkcyBhcyBkZWNsYXJpbmcgYSBidXR0b24gdGhhdCBuZXZlciByZW5kZXJlZC5cbiAqXG4gKiBAcGFyYW0gY2FwdGlvbnMgLSBBIG5vdGUncyBidXR0b24gY2FwdGlvbnMuXG4gKiBAcmV0dXJucyBFYWNoIGNhcHRpb24gb2NjdXJyaW5nIG1vcmUgdGhhbiBvbmNlLCBsaXN0ZWQgb25jZSwgaW4gb3JkZXIgb2YgZmlyc3QgcmVwZWF0LlxuICovXG5leHBvcnQgZnVuY3Rpb24gZmluZER1cGxpY2F0ZUNhcHRpb25zKGNhcHRpb25zOiByZWFkb25seSBzdHJpbmdbXSk6IHN0cmluZ1tdIHtcbiAgY29uc3Qgc2VlbkNhcHRpb25zID0gbmV3IFNldDxzdHJpbmc+KCk7XG4gIGNvbnN0IGR1cGxpY2F0ZUNhcHRpb25zID0gbmV3IFNldDxzdHJpbmc+KCk7XG4gIGZvciAoY29uc3QgY2FwdGlvbiBvZiBjYXB0aW9ucykge1xuICAgIGlmIChzZWVuQ2FwdGlvbnMuaGFzKGNhcHRpb24pKSB7XG4gICAgICBkdXBsaWNhdGVDYXB0aW9ucy5hZGQoY2FwdGlvbik7XG4gICAgfVxuICAgIHNlZW5DYXB0aW9ucy5hZGQoY2FwdGlvbik7XG4gIH1cbiAgcmV0dXJuIFsuLi5kdXBsaWNhdGVDYXB0aW9uc107XG59XG5cbi8qKlxuICogQnVpbGRzIHRoZSBhc3NlcnRpb24gbWVzc2FnZSBmb3IgYSBub3RlJ3MgZmFpbGluZyBidXR0b25zLlxuICpcbiAqIFRoZSBjYXB0dXJlZCBvdXRwdXQgaXMgaW5jbHVkZWQgYmVjYXVzZSBhIGJ1dHRvbidzIGZhaWx1cmUgaXMgYSBydW50aW1lIG9uZSBcdTIwMTQgdGhlIHN0YWNrIENvZGVTY3JpcHRcbiAqIFRvb2xraXQgcHJpbnRzIHVuZGVyIGl0IGlzIHRoZSBvbmx5IGRpYWdub3NpcyB0aGVyZSBpcy5cbiAqXG4gKiBAcGFyYW0gbm90ZU5hbWUgLSBUaGUgbm90ZSB0aGUgYnV0dG9ucyBiZWxvbmcgdG8uXG4gKiBAcGFyYW0gZmFpbHVyZXMgLSBUaGUgZmFpbGluZyBidXR0b25zLlxuICogQHJldHVybnMgVGhlIG1lc3NhZ2UuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBmb3JtYXRGYWlsdXJlcyhub3RlTmFtZTogc3RyaW5nLCBmYWlsdXJlczogcmVhZG9ubHkgRGVtb1ZhdWx0QnV0dG9uUmVzdWx0W10pOiBzdHJpbmcge1xuICBpZiAoZmFpbHVyZXMubGVuZ3RoID09PSAwKSB7XG4gICAgcmV0dXJuICcnO1xuICB9XG5cbiAgY29uc3QgZGV0YWlscyA9IGZhaWx1cmVzXG4gICAgLm1hcCgoZmFpbHVyZSkgPT4gYCAgLSBcIiR7ZmFpbHVyZS5jYXB0aW9ufVwiIFske2ZhaWx1cmUuc3RhdHVzfV06ICR7ZmFpbHVyZS5vdXRwdXQucmVwbGFjZUFsbCgvXFxzKy9nLCAnICcpLnRyaW0oKX1gKVxuICAgIC5qb2luKCdcXG4nKTtcbiAgcmV0dXJuIGAke1N0cmluZyhmYWlsdXJlcy5sZW5ndGgpfSBidXR0b24ocykgaW4gJHtub3RlTmFtZX0gZGlkIG5vdCBydW4gY2xlYW5seTpcXG4ke2RldGFpbHN9YDtcbn1cblxuLyoqXG4gKiBMaXN0cyB0aGUgY2FwdGlvbnMgb2YgdGhlIGJ1dHRvbnMgYSBub3RlJ3Mgc291cmNlIHdpbGwgYWN0dWFsbHkgcmVuZGVyLCBpbiBzb3VyY2Ugb3JkZXIuXG4gKlxuICogV2hpY2ggZmVuY2VzIHJlbmRlciBhIGJ1dHRvbiBpcyBkZWNpZGVkIGV4YWN0bHkgYXMge0BsaW5rIGNvdW50UmVuZGVyZWRCdXR0b25zfSBkZXNjcmliZXMuIEEgY2FwdGlvbiBpc1xuICogcmVhZCBmcm9tIHRoZSBmZW5jZSdzIG93biBjb25maWcgYmxvY2s7IGEgZmVuY2UgbmFtaW5nIG5vbmUgdGFrZXMgQ29kZVNjcmlwdCBUb29sa2l0J3MgZGVmYXVsdCxcbiAqIGAobm8gY2FwdGlvbilgLCB3aGljaCBpcyB3aGF0IGl0cyBidXR0b24gdGhlbiBzaG93cy5cbiAqXG4gKiBAcGFyYW0gc291cmNlIC0gVGhlIG5vdGUncyBtYXJrZG93bi5cbiAqIEByZXR1cm5zIFRoZSBjYXB0aW9ucywgb25lIHBlciByZW5kZXJlZCBidXR0b24uXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBsaXN0UmVuZGVyZWRCdXR0b25DYXB0aW9ucyhzb3VyY2U6IHN0cmluZyk6IHN0cmluZ1tdIHtcbiAgY29uc3QgY2FwdGlvbnM6IHN0cmluZ1tdID0gW107XG4gIGxldCBvcGVuTWFya2VyID0gJyc7XG4gIGxldCBpc0NvZGVCdXR0b25GZW5jZSA9IGZhbHNlO1xuICBsZXQgZmVuY2VCb2R5OiBzdHJpbmdbXSA9IFtdO1xuICBsZXQgZmVuY2VJbmRlbnRMZW5ndGggPSAwO1xuXG4gIGZ1bmN0aW9uIGNsb3NlRmVuY2UoKTogdm9pZCB7XG4gICAgaWYgKGlzQ29kZUJ1dHRvbkZlbmNlICYmICFpc1Jhd0ZlbmNlKGZlbmNlQm9keSkpIHtcbiAgICAgIGNhcHRpb25zLnB1c2gocmVhZENhcHRpb24oZmVuY2VCb2R5KSk7XG4gICAgfVxuICAgIG9wZW5NYXJrZXIgPSAnJztcbiAgfVxuXG4gIGZvciAoY29uc3QgbGluZSBvZiBzb3VyY2Uuc3BsaXQoL1xccj9cXG4vKSkge1xuICAgIGNvbnN0IG1hdGNoID0gRkVOQ0VfUkVHX0VYUC5leGVjKGxpbmUpO1xuICAgIGNvbnN0IGluZGVudCA9IG1hdGNoPy5ncm91cHM/LlsnaW5kZW50J10gPz8gJyc7XG4gICAgY29uc3QgbWFya2VyID0gbWF0Y2g/Lmdyb3Vwcz8uWydtYXJrZXInXSA/PyAnJztcbiAgICBjb25zdCBpbmZvID0gKG1hdGNoPy5ncm91cHM/LlsnaW5mbyddID8/ICcnKS50cmltKCk7XG5cbiAgICBpZiAob3Blbk1hcmtlciA9PT0gJycpIHtcbiAgICAgIGlmIChtYXRjaCkge1xuICAgICAgICBvcGVuTWFya2VyID0gbWFya2VyO1xuICAgICAgICBpc0NvZGVCdXR0b25GZW5jZSA9IGluZm8gPT09IENPREVfQlVUVE9OX0ZFTkNFX0lORk87XG4gICAgICAgIGZlbmNlQm9keSA9IFtdO1xuICAgICAgICBmZW5jZUluZGVudExlbmd0aCA9IGluZGVudC5sZW5ndGg7XG4gICAgICB9XG4gICAgICBjb250aW51ZTtcbiAgICB9XG5cbiAgICAvLyBBbnl0aGluZyBlbHNlIHdoaWxlIGEgZmVuY2UgaXMgb3BlbiBpcyBpdHMgY29udGVudCBcdTIwMTQgd2hpY2ggaXMgZXhhY3RseSBob3cgYSBgYGBgbWFya2Rvd24gc2FtcGxlXG4gICAgLy8gaG9sZHMgYSBgYGBjb2RlLWJ1dHRvbi5cbiAgICBpZiAobWFya2VyLnN0YXJ0c1dpdGgob3Blbk1hcmtlci5jaGFyQXQoMCkpICYmIG1hcmtlci5sZW5ndGggPj0gb3Blbk1hcmtlci5sZW5ndGggJiYgaW5mbyA9PT0gJycpIHtcbiAgICAgIGNsb3NlRmVuY2UoKTtcbiAgICAgIGNvbnRpbnVlO1xuICAgIH1cblxuICAgIC8vIENvbW1vbk1hcmsgc3RyaXBzIHVwIHRvIHRoZSBvcGVuaW5nIGZlbmNlJ3MgaW5kZW50YXRpb24gZnJvbSBlYWNoIGNvbnRlbnQgbGluZSwgc28gYSBmZW5jZSBuZXN0ZWQgaW5cbiAgICAvLyBhIGxpc3QgaXRlbSBjYXJyaWVzIGl0cyBgY2FwdGlvbjpgIC8gYGlzUmF3OmAga2V5cyBhdCBjb2x1bW4gMCBsaWtlIGFueSBvdGhlci5cbiAgICBmZW5jZUJvZHkucHVzaChsaW5lLnNsaWNlKE1hdGgubWluKGZlbmNlSW5kZW50TGVuZ3RoLCBsaW5lLmxlbmd0aCAtIGxpbmUudHJpbVN0YXJ0KCkubGVuZ3RoKSkpO1xuICB9XG5cbiAgaWYgKG9wZW5NYXJrZXIgIT09ICcnKSB7XG4gICAgY2xvc2VGZW5jZSgpO1xuICB9XG5cbiAgcmV0dXJuIGNhcHRpb25zO1xufVxuXG4vKipcbiAqIFBpY2tzIHRoZSBidXR0b25zIHRoYXQgZmFpbGVkIGFuZCB3ZXJlIG5vdCBleHBlY3RlZCB0by5cbiAqXG4gKiBAcGFyYW0gbm90ZU5hbWUgLSBUaGUgbm90ZSB0aGUgcmVzdWx0cyBiZWxvbmcgdG8sIHJlbGF0aXZlIHRvIHRoZSBkZW1vIHZhdWx0IHJvb3QuXG4gKiBAcGFyYW0gcmVzdWx0cyAtIEV2ZXJ5IGJ1dHRvbidzIHJlc3VsdCBpbiB0aGF0IG5vdGUuXG4gKiBAcGFyYW0gZXhwZWN0ZWROb25Pa0J1dHRvbnMgLSBUaGUgYnV0dG9ucyBhbGxvd2VkIHRvIGVuZCBpbiBhIGdpdmVuIG5vbi1gb2tgIHN0YXR1cy5cbiAqIEByZXR1cm5zIFRoZSByZXN1bHRzIHRoYXQgYXJlIG5vdCBgb2tgIGFuZCBtYXRjaCBubyB7QGxpbmsgRXhwZWN0ZWROb25Pa0J1dHRvbn0uXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBzZWxlY3RVbmV4cGVjdGVkRmFpbHVyZXMoXG4gIG5vdGVOYW1lOiBzdHJpbmcsXG4gIHJlc3VsdHM6IHJlYWRvbmx5IERlbW9WYXVsdEJ1dHRvblJlc3VsdFtdLFxuICBleHBlY3RlZE5vbk9rQnV0dG9uczogcmVhZG9ubHkgRXhwZWN0ZWROb25Pa0J1dHRvbltdXG4pOiBEZW1vVmF1bHRCdXR0b25SZXN1bHRbXSB7XG4gIHJldHVybiByZXN1bHRzLmZpbHRlcigocmVzdWx0KSA9PlxuICAgIHJlc3VsdC5zdGF0dXMgIT09ICdvaydcbiAgICAmJiBleHBlY3RlZE5vbk9rQnV0dG9ucy5ldmVyeSgoZXhwZWN0ZWQpID0+XG4gICAgICAhKGV4cGVjdGVkLm5vdGUgPT09IG5vdGVOYW1lXG4gICAgICAgICYmIGV4cGVjdGVkLnN0YXR1cyA9PT0gcmVzdWx0LnN0YXR1c1xuICAgICAgICAmJiByZXN1bHQuY2FwdGlvbi5pbmNsdWRlcyhleHBlY3RlZC5jYXB0aW9uSW5jbHVkZXMpKVxuICAgIClcbiAgKTtcbn1cblxuLyoqXG4gKiBXaGV0aGVyIGEgYGNvZGUtYnV0dG9uYCBmZW5jZSdzIG93biBZQU1MIGNvbmZpZyBhc2tzIGZvciByYXcgbW9kZS5cbiAqXG4gKiBSZWFkIGZyb20gdGhlIGxlYWRpbmcgYC0tLWAgYmxvY2sgcmF0aGVyIHRoYW4gZnJvbSB0aGUgd2hvbGUgYm9keSwgc28gYW4gYGlzUmF3OiB0cnVlYCB3cml0dGVuIGluc2lkZVxuICogYSBidXR0b24ncyBDT0RFIFx1MjAxNCBhIGJ1dHRvbiB0aGF0IGRlbW9uc3RyYXRlcyB0aGUga2V5IFx1MjAxNCBpcyBub3QgbWlzdGFrZW4gZm9yIHRoZSBidXR0b24ncyBvd24gY29uZmlnLlxuICpcbiAqIEBwYXJhbSBmZW5jZUJvZHkgLSBUaGUgZmVuY2UncyBsaW5lcywgd2l0aG91dCB0aGUgZmVuY2UgbWFya2Vycy5cbiAqIEByZXR1cm5zIFdoZXRoZXIgdGhlIGZlbmNlIHJlbmRlcnMgbm8gYnV0dG9uLlxuICovXG5mdW5jdGlvbiBpc1Jhd0ZlbmNlKGZlbmNlQm9keTogcmVhZG9ubHkgc3RyaW5nW10pOiBib29sZWFuIHtcbiAgY29uc3QgY29uZmlnID0gcmVhZENvbmZpZ0Jsb2NrKGZlbmNlQm9keSk7XG4gIHJldHVybiBjb25maWcgIT09IG51bGwgJiYgUkFXX01PREVfQ09ORklHX1JFR19FWFAudGVzdChjb25maWcpO1xufVxuXG4vKipcbiAqIFJlYWRzIHRoZSBjYXB0aW9uIGEgYGNvZGUtYnV0dG9uYCBmZW5jZSdzIG93biBjb25maWcgYmxvY2sgZ2l2ZXMgaXRzIGJ1dHRvbi5cbiAqXG4gKiBBIGRlbGliZXJhdGVseSBzbWFsbCByZWFkaW5nIG9mIFlBTUwgXHUyMDE0IGEgcGxhaW4sIHNpbmdsZS1xdW90ZWQgb3IgZG91YmxlLXF1b3RlZCBzY2FsYXIgb24gdGhlIGBjYXB0aW9uOmBcbiAqIGxpbmUgXHUyMDE0IHNpbmNlIHRoZSB2YWx1ZSBvbmx5IGV2ZXIgbmFtZXMgYSBidXR0b24uIEEgdmFsdWUgaXQgY2Fubm90IHJlYWQgZXhhY3RseSwgc3VjaCBhcyBhIGJsb2NrXG4gKiBzY2FsYXIsIGlzIHJldHVybmVkIGFzIHdyaXR0ZW46IHRoYXQgY2FuIG1ha2Ugb25lIGNhcHRpb24gcmVhZCB3cm9uZywgYnV0IGl0IGNhbm5vdCBtYWtlIHR3b1xuICogZGlmZmVyZW50IG9uZXMgY29tcGFyZSBlcXVhbC5cbiAqXG4gKiBAcGFyYW0gZmVuY2VCb2R5IC0gVGhlIGZlbmNlJ3MgbGluZXMsIHdpdGhvdXQgdGhlIGZlbmNlIG1hcmtlcnMuXG4gKiBAcmV0dXJucyBUaGUgY2FwdGlvbi5cbiAqL1xuZnVuY3Rpb24gcmVhZENhcHRpb24oZmVuY2VCb2R5OiByZWFkb25seSBzdHJpbmdbXSk6IHN0cmluZyB7XG4gIGNvbnN0IGNvbmZpZyA9IHJlYWRDb25maWdCbG9jayhmZW5jZUJvZHkpO1xuICBjb25zdCByYXdWYWx1ZSA9IGNvbmZpZyA9PT0gbnVsbCA/IHVuZGVmaW5lZCA6IENBUFRJT05fQ09ORklHX1JFR19FWFAuZXhlYyhjb25maWcpPy5ncm91cHM/LlsndmFsdWUnXTtcbiAgaWYgKHJhd1ZhbHVlID09PSB1bmRlZmluZWQpIHtcbiAgICByZXR1cm4gREVGQVVMVF9DT0RFX0JVVFRPTl9DQVBUSU9OO1xuICB9XG5cbiAgY29uc3QgdmFsdWUgPSByYXdWYWx1ZS50cmltKCk7XG4gIGNvbnN0IHNpbmdsZVF1b3RlZENvbnRlbnQgPSBTSU5HTEVfUVVPVEVEX1NDQUxBUl9SRUdfRVhQLmV4ZWModmFsdWUpPy5ncm91cHM/LlsnY29udGVudCddO1xuICBpZiAoc2luZ2xlUXVvdGVkQ29udGVudCAhPT0gdW5kZWZpbmVkKSB7XG4gICAgcmV0dXJuIHNpbmdsZVF1b3RlZENvbnRlbnQucmVwbGFjZUFsbCgnXFwnXFwnJywgJ1xcJycpO1xuICB9XG4gIGNvbnN0IGRvdWJsZVF1b3RlZENvbnRlbnQgPSBET1VCTEVfUVVPVEVEX1NDQUxBUl9SRUdfRVhQLmV4ZWModmFsdWUpPy5ncm91cHM/LlsnY29udGVudCddO1xuICBpZiAoZG91YmxlUXVvdGVkQ29udGVudCAhPT0gdW5kZWZpbmVkKSB7XG4gICAgdHJ5IHtcbiAgICAgIHJldHVybiBKU09OLnBhcnNlKHZhbHVlKSBhcyBzdHJpbmc7XG4gICAgfSBjYXRjaCB7XG4gICAgICByZXR1cm4gZG91YmxlUXVvdGVkQ29udGVudDtcbiAgICB9XG4gIH1cbiAgcmV0dXJuIHZhbHVlLnJlcGxhY2UoUExBSU5fU0NBTEFSX0NPTU1FTlRfUkVHX0VYUCwgJycpO1xufVxuXG4vKipcbiAqIFJlYWRzIGEgYGNvZGUtYnV0dG9uYCBmZW5jZSdzIGxlYWRpbmcgYC0tLWAgY29uZmlnIGJsb2NrLlxuICpcbiAqIE9ubHkgdGhlIGxlYWRpbmcgYmxvY2sgY291bnRzLCBzbyBhIGAtLS1gIGJsb2NrIHdyaXR0ZW4gaW5zaWRlIGEgYnV0dG9uJ3MgQ09ERSBpcyBub3QgbWlzdGFrZW4gZm9yIHRoZVxuICogYnV0dG9uJ3Mgb3duIGNvbmZpZy5cbiAqXG4gKiBAcGFyYW0gZmVuY2VCb2R5IC0gVGhlIGZlbmNlJ3MgbGluZXMsIHdpdGhvdXQgdGhlIGZlbmNlIG1hcmtlcnMuXG4gKiBAcmV0dXJucyBUaGUgYmxvY2sncyBjb250ZW50LCBvciBgbnVsbGAgd2hlbiB0aGUgZmVuY2Ugb3BlbnMgd2l0aCBubyB0ZXJtaW5hdGVkIGJsb2NrLlxuICovXG5mdW5jdGlvbiByZWFkQ29uZmlnQmxvY2soZmVuY2VCb2R5OiByZWFkb25seSBzdHJpbmdbXSk6IG51bGwgfCBzdHJpbmcge1xuICBpZiAoZmVuY2VCb2R5WzBdPy50cmltKCkgIT09IEZST05UX01BVFRFUl9ERUxJTUlURVIpIHtcbiAgICByZXR1cm4gbnVsbDtcbiAgfVxuXG4gIGNvbnN0IGVuZEluZGV4ID0gZmVuY2VCb2R5LmZpbmRJbmRleCgobGluZSwgaW5kZXgpID0+IGluZGV4ID4gMCAmJiBsaW5lLnRyaW0oKSA9PT0gRlJPTlRfTUFUVEVSX0RFTElNSVRFUik7XG4gIHJldHVybiBlbmRJbmRleCA9PT0gLTEgPyBudWxsIDogZmVuY2VCb2R5LnNsaWNlKDEsIGVuZEluZGV4KS5qb2luKCdcXG4nKTtcbn1cblxuLyoqXG4gKiBGb2xkZXJzIHRoYXQgbmV2ZXIgaG9sZCBhIHdhbGt0aHJvdWdoLiBgTWF0ZXJpYWxzL2AgaG9sZHMgdGhlIGZpeHR1cmVzIHRoZSB3YWxrdGhyb3VnaHMgYWN0IG9uO1xuICogYF9hc3NldHMvYCBob2xkcyB0aGUgZGVtbyBzY3JpcHRzOyBgLm9ic2lkaWFuL2AgaXMgdmF1bHQgY29uZmlnLiBBIGZvbGRlciBzdGFydGluZyB3aXRoIGAuYCBvciBgX2BcbiAqIGlzIHNraXBwZWQgb24gdGhlIHNhbWUgcmVhc29uaW5nLCB3aXRob3V0IGhhdmluZyB0byBiZSBsaXN0ZWQuXG4gKi9cbmNvbnN0IE5PTl9XQUxLVEhST1VHSF9GT0xERVJTID0gbmV3IFNldChbJ01hdGVyaWFscyddKTtcblxuLyoqXG4gKiBMaXN0cyB0aGUgZGVtbyB2YXVsdCdzIG5vdGVzIHRoYXQgZGVjbGFyZSBhdCBsZWFzdCBvbmUgYGNvZGUtYnV0dG9uYCwgd2Fsa2luZyBncm91cCBmb2xkZXJzIHRvby5cbiAqXG4gKiBBIHZhdWx0IGJpZyBlbm91Z2ggdG8gbmVlZCBncm91cGluZyBwdXRzIGl0cyB3YWxrdGhyb3VnaHMgaW4gbnVtYmVyZWQgZm9sZGVycyBcdTIwMTQgYW5kIGEgcm9vdC1vbmx5IHdhbGtcbiAqIGZpbmRzIE5PTkUgb2YgdGhlbSwgd2hpY2ggaXMgd29yc2UgdGhhbiBpdCBzb3VuZHM6IGEgdmF1bHQgd2hvc2Ugbm90ZXMgYXJlIGFsbCBncm91cGVkIHJlcG9ydHMgemVyb1xuICogbm90ZXMsIGFuZCBvbmUgdGhhdCBpcyBwYXJ0bHkgZ3JvdXBlZCBzaWxlbnRseSBnYXRlcyBvbmx5IHRoZSB1bmdyb3VwZWQgcGFydC4gRml4dHVyZSBhbmQgYXNzZXRcbiAqIGZvbGRlcnMgYXJlIHN0aWxsIHNraXBwZWQsIHNvIHdoYXQgaXMgd2Fsa2VkIGlzIHdhbGt0aHJvdWdocyBhbmQgbm90aGluZyBlbHNlLlxuICpcbiAqIEBwYXJhbSBkZW1vVmF1bHRQYXRoIC0gVGhlIGRlbW8gdmF1bHQgcm9vdC5cbiAqIEBwYXJhbSBleGNsdWRlZE5vdGVzIC0gTm90ZSBuYW1lcyB0byBza2lwLCBtYXRjaGVkIGFnYWluc3QgYm90aCB0aGUgZmlsZSBuYW1lIGFuZCB0aGUgcGF0aCByZWxhdGl2ZVxuICogdG8gdGhlIHZhdWx0IHJvb3QuXG4gKiBAcGFyYW0gZXhjbHVkZWRGb2xkZXJzIC0gRm9sZGVycyB0byBza2lwIHdob2xlLCBtYXRjaGVkIHRoZSBzYW1lIHdheS5cbiAqIEByZXR1cm5zIFRoZSBub3Rlcywgc29ydGVkIGJ5IHBhdGguXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBsaXN0Tm90ZXNXaXRoQnV0dG9ucyhcbiAgZGVtb1ZhdWx0UGF0aDogc3RyaW5nLFxuICBleGNsdWRlZE5vdGVzOiBSZWFkb25seVNldDxzdHJpbmc+LFxuICBleGNsdWRlZEZvbGRlcnM6IFJlYWRvbmx5U2V0PHN0cmluZz4gPSBuZXcgU2V0KClcbik6IERlbW9WYXVsdE5vdGVbXSB7XG4gIGNvbnN0IG5vdGVzOiBEZW1vVmF1bHROb3RlW10gPSBbXTtcblxuICBmdW5jdGlvbiB3YWxrKGZvbGRlcjogc3RyaW5nLCByZWxhdGl2ZUZvbGRlcjogc3RyaW5nKTogdm9pZCB7XG4gICAgZm9yIChjb25zdCBlbnRyeSBvZiByZWFkZGlyU3luYyhmb2xkZXIsIHsgd2l0aEZpbGVUeXBlczogdHJ1ZSB9KSkge1xuICAgICAgY29uc3QgcmVsYXRpdmVQYXRoID0gcmVsYXRpdmVGb2xkZXIgPT09ICcnID8gZW50cnkubmFtZSA6IGAke3JlbGF0aXZlRm9sZGVyfS8ke2VudHJ5Lm5hbWV9YDtcblxuICAgICAgaWYgKGVudHJ5LmlzRGlyZWN0b3J5KCkpIHtcbiAgICAgICAgaWYgKFxuICAgICAgICAgICFlbnRyeS5uYW1lLnN0YXJ0c1dpdGgoJy4nKSAmJiAhZW50cnkubmFtZS5zdGFydHNXaXRoKCdfJykgJiYgIU5PTl9XQUxLVEhST1VHSF9GT0xERVJTLmhhcyhlbnRyeS5uYW1lKVxuICAgICAgICAgICYmICFleGNsdWRlZEZvbGRlcnMuaGFzKGVudHJ5Lm5hbWUpICYmICFleGNsdWRlZEZvbGRlcnMuaGFzKHJlbGF0aXZlUGF0aClcbiAgICAgICAgKSB7XG4gICAgICAgICAgd2Fsayhqb2luKGZvbGRlciwgZW50cnkubmFtZSksIHJlbGF0aXZlUGF0aCk7XG4gICAgICAgIH1cbiAgICAgICAgY29udGludWU7XG4gICAgICB9XG5cbiAgICAgIGlmICghZW50cnkubmFtZS5lbmRzV2l0aCgnLm1kJykgfHwgZXhjbHVkZWROb3Rlcy5oYXMoZW50cnkubmFtZSkgfHwgZXhjbHVkZWROb3Rlcy5oYXMocmVsYXRpdmVQYXRoKSkge1xuICAgICAgICBjb250aW51ZTtcbiAgICAgIH1cblxuICAgICAgY29uc3QgY2FwdGlvbnMgPSBsaXN0UmVuZGVyZWRCdXR0b25DYXB0aW9ucyhyZWFkRmlsZVN5bmMoam9pbihmb2xkZXIsIGVudHJ5Lm5hbWUpLCAndXRmLTgnKSk7XG4gICAgICBpZiAoY2FwdGlvbnMubGVuZ3RoID4gMCkge1xuICAgICAgICBub3Rlcy5wdXNoKHsgYnV0dG9uQ291bnQ6IGNhcHRpb25zLmxlbmd0aCwgY2FwdGlvbnMsIG5hbWU6IHJlbGF0aXZlUGF0aCB9KTtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICB3YWxrKGRlbW9WYXVsdFBhdGgsICcnKTtcbiAgcmV0dXJuIG5vdGVzLnNvcnQoKGEsIGIpID0+IGEubmFtZS5sb2NhbGVDb21wYXJlKGIubmFtZSwgJ2VuJykpO1xufVxuXG4vKiB2OCBpZ25vcmUgc3RhcnQgLS0gRXZlcnkgYXNzZXJ0aW9uIGJlbG93IHJ1bnMgYWdhaW5zdCBhIHJlYWwgT2JzaWRpYW4gb3ZlciBDRFAsIGRyaXZlbiBieSBjbG9zdXJlcyB0aGlzIHByb2Nlc3Mgc2VyaWFsaXplcyBhbmQgYW5vdGhlciBleGVjdXRlcy4gVGhlIHRlc3RhYmxlIHBhcnRzIGFyZSBsaXN0Tm90ZXNXaXRoQnV0dG9ucyBhbmQgZm9ybWF0RmFpbHVyZXMsIHdoaWNoIGhhdmUgdGhlaXIgb3duIHVuaXQgdGVzdHMuICovXG4vKipcbiAqIFJlZ2lzdGVycyBhIHZpdGVzdCBzdWl0ZSB0aGF0IGNsaWNrcyBldmVyeSBgY29kZS1idXR0b25gIGluIHRoZSByZXBvJ3MgZGVtbyB2YXVsdC5cbiAqXG4gKiBPbmUgYGl0YCBwZXIgbm90ZSwgYW5kIG9uZSBgZXZhbEluT2JzaWRpYW5gIHBlciBidXR0b246IGEgc2luZ2xlIGNsb3N1cmUgcnVucyBhcyBvbmUgQ0RQXG4gKiBgUnVudGltZS5ldmFsdWF0ZWAsIHdoaWNoIHRoZSBoYXJuZXNzIGNhcHMgYXQgMzAgcywgc28gYSBub3RlIHdpdGggYSBkb3plbiBidXR0b25zIHdvdWxkIG90aGVyd2lzZVxuICogdGltZSBvdXQgYXMgYSB3aG9sZSByYXRoZXIgdGhhbiByZXBvcnRpbmcgd2hpY2ggYnV0dG9uIGZhaWxlZC5cbiAqXG4gKiBAcGFyYW0gb3B0aW9ucyAtIFRoZSB7QGxpbmsgUmVnaXN0ZXJEZW1vVmF1bHRCdXR0b25TdWl0ZU9wdGlvbnN9LlxuICovXG5leHBvcnQgZnVuY3Rpb24gcmVnaXN0ZXJEZW1vVmF1bHRCdXR0b25TdWl0ZShvcHRpb25zOiBSZWdpc3RlckRlbW9WYXVsdEJ1dHRvblN1aXRlT3B0aW9ucyA9IHt9KTogdm9pZCB7XG4gIGNvbnN0IHJvb3RGb2xkZXIgPSBvcHRpb25zLnJvb3RGb2xkZXIgPz8gZ2V0Um9vdEZvbGRlcigpID8/IHByb2Nlc3MuY3dkKCk7XG4gIGNvbnN0IGRlbW9WYXVsdFBhdGggPSBqb2luKHJvb3RGb2xkZXIsICdkZW1vLXZhdWx0Jyk7XG4gIGNvbnN0IGV4Y2x1ZGVkTm90ZXMgPSBuZXcgU2V0KG9wdGlvbnMuZXhjbHVkZWROb3RlcyA/PyBERUZBVUxUX0VYQ0xVREVEX05PVEVTKTtcbiAgY29uc3QgZXhjbHVkZWRGb2xkZXJzID0gbmV3IFNldChvcHRpb25zLmV4Y2x1ZGVkRm9sZGVycyk7XG4gIGNvbnN0IGV4cGVjdGVkTm9uT2tCdXR0b25zID0gb3B0aW9ucy5leHBlY3RlZE5vbk9rQnV0dG9ucyA/PyBbXTtcbiAgY29uc3Qgc2hvdWxkRGlzbWlzc01vZGFscyA9IG9wdGlvbnMuc2hvdWxkRGlzbWlzc01vZGFscyA/PyBmYWxzZTtcbiAgY29uc3Qgc2V0dGxlVGltZW91dEluTWlsbGlzZWNvbmRzID0gb3B0aW9ucy5zZXR0bGVUaW1lb3V0SW5NaWxsaXNlY29uZHMgPz8gREVGQVVMVF9TRVRUTEVfVElNRU9VVF9JTl9NSUxMSVNFQ09ORFM7XG4gIGNvbnN0IGJ1dHRvblJlc3VsdFRpbWVvdXRJbk1pbGxpc2Vjb25kcyA9IG9wdGlvbnMuYnV0dG9uUmVzdWx0VGltZW91dEluTWlsbGlzZWNvbmRzID8/IERFRkFVTFRfQlVUVE9OX1JFU1VMVF9USU1FT1VUX0lOX01JTExJU0VDT05EUztcblxuICAvLyBSZXNvbHZlZCBPTkNFIGFuZCBoYW5kZWQgdG8gYm90aCB0aGUgYm91bmQgYW5kIHRoZSBjbGljaywgc28gdGhlIHBhaXIgdGhhdCBpcyBhc3NlcnRlZCBhbmQgdGhlIHBhaXJcbiAgLy8gdGhhdCBpcyBzcGVudCBjYW5ub3QgZHJpZnQgYXBhcnQuXG4gIGNvbnN0IGNsaWNrQnV0dG9uVGltZW91dHM6IENsaWNrQnV0dG9uVGltZW91dHMgPSB7XG4gICAgYnV0dG9uUmVzdWx0VGltZW91dEluTWlsbGlzZWNvbmRzLFxuICAgIHNldHRsZVRpbWVvdXRJbk1pbGxpc2Vjb25kc1xuICB9O1xuICBhc3NlcnRDbGlja0J1ZGdldHNGaXRUcmFuc3BvcnRDYXAoY2xpY2tCdXR0b25UaW1lb3V0cyk7XG5cbiAgY29uc3Qgbm90ZXMgPSBsaXN0Tm90ZXNXaXRoQnV0dG9ucyhkZW1vVmF1bHRQYXRoLCBleGNsdWRlZE5vdGVzLCBleGNsdWRlZEZvbGRlcnMpO1xuXG4gIGRlc2NyaWJlKCdkZW1vLXZhdWx0IGJ1dHRvbnMnLCAoKSA9PiB7XG4gICAgYmVmb3JlQWxsKGFzeW5jICgpID0+IHtcbiAgICAgIGNvbnN0IGlzQ29kZVNjcmlwdFRvb2xraXRMb2FkZWQgPSBhd2FpdCBjaGVja0NvZGVTY3JpcHRUb29sa2l0TG9hZGVkKHNldHRsZVRpbWVvdXRJbk1pbGxpc2Vjb25kcyk7XG4gICAgICAvLyBXaXRob3V0IGl0IGV2ZXJ5IGBjb2RlLWJ1dHRvbmAgZmVuY2Ugc3RheXMgYSBwbGFpbiBjb2RlIGJsb2NrLCBzbyBldmVyeSBub3RlIGJlbG93IHdvdWxkIHJlcG9ydFxuICAgICAgLy8gemVybyBidXR0b25zIGFuZCBwYXNzIHZhY3VvdXNseS4gRmFpbCBoZXJlIGluc3RlYWQsIG9uY2UsIHdpdGggdGhlIHJlYXNvbi5cbiAgICAgIGV4cGVjdChpc0NvZGVTY3JpcHRUb29sa2l0TG9hZGVkLCAnQ29kZVNjcmlwdCBUb29sa2l0IGRpZCBub3QgbG9hZCwgc28gbm8gYnV0dG9uIGNvdWxkIHJlbmRlcicpLnRvQmUodHJ1ZSk7XG4gICAgfSk7XG5cbiAgICAvLyBBIGRlbW8gdmF1bHQgaGFzIHRvIGRlbW9uc3RyYXRlIGV2ZXJ5IGhlYWRsaW5lIGZlYXR1cmUsIHNvIGEgdmF1bHQgd2hvc2Ugbm90ZXMgZGVjbGFyZSBubyBidXR0b25zXG4gICAgLy8gaXMgYSByZWFsIGZhaWx1cmUgb2YgaXRzIGludGVyYWN0aXZlIGhhbGYsIG5vdCBhIHJlYXNvbiB0byByZWdpc3RlciBub3RoaW5nIGFuZCByZXBvcnQgZ3JlZW4uXG4gICAgaXQoJ2hhcyBhdCBsZWFzdCBvbmUgbm90ZSB3aXRoIGEgY29kZSBidXR0b24nLCAoKSA9PiB7XG4gICAgICBleHBlY3Qobm90ZXMubGVuZ3RoKS50b0JlR3JlYXRlclRoYW4oMCk7XG4gICAgfSk7XG5cbiAgICBmb3IgKGNvbnN0IG5vdGUgb2Ygbm90ZXMpIHtcbiAgICAgIGl0KGBydW5zIGV2ZXJ5IGNvZGUgYnV0dG9uIGluICR7bm90ZS5uYW1lfWAsIGFzeW5jICgpID0+IHtcbiAgICAgICAgLy8gQ2hlY2tlZCBmcm9tIHRoZSBzb3VyY2UsIGJlZm9yZSBhbnl0aGluZyBpcyBvcGVuZWQ6IGJ1dHRvbnMgYXJlIGFkZHJlc3NlZCBieSBjYXB0aW9uLCBzbyBhXG4gICAgICAgIC8vIHNoYXJlZCBvbmUgd291bGQgb3RoZXJ3aXNlIHN1cmZhY2UgYmVsb3cgYXMgYSBidXR0b24gdGhhdCBcIm5ldmVyIHJlbmRlcmVkXCIuXG4gICAgICAgIGNvbnN0IGR1cGxpY2F0ZUNhcHRpb25zID0gZmluZER1cGxpY2F0ZUNhcHRpb25zKG5vdGUuY2FwdGlvbnMpO1xuICAgICAgICBleHBlY3QoXG4gICAgICAgICAgZHVwbGljYXRlQ2FwdGlvbnMsXG4gICAgICAgICAgYCR7bm90ZS5uYW1lfSBkZWNsYXJlcyBtb3JlIHRoYW4gb25lIGJ1dHRvbiBjYXB0aW9uZWQgJHtkdXBsaWNhdGVDYXB0aW9ucy5tYXAoKGNhcHRpb24pID0+IGBcIiR7Y2FwdGlvbn1cImApLmpvaW4oJywgJyl9LiBgXG4gICAgICAgICAgICArICdUaGlzIHN1aXRlIGFkZHJlc3NlcyBhIGJ1dHRvbiBieSBpdHMgY2FwdGlvbiwgc28gb25seSB0aGUgZmlyc3Qgb2YgdGhlbSBjb3VsZCBldmVyIGJlIGNsaWNrZWQuIEdpdmUgZWFjaCBidXR0b24gYSBkaXN0aW5jdCBjYXB0aW9uLidcbiAgICAgICAgKS50b0VxdWFsKFtdKTtcblxuICAgICAgICBjb25zdCBjYXB0aW9ucyA9IGF3YWl0IG9wZW5Ob3RlQW5kTGlzdEJ1dHRvbkNhcHRpb25zKG5vdGUsIHNldHRsZVRpbWVvdXRJbk1pbGxpc2Vjb25kcyk7XG4gICAgICAgIC8vIFJlYWRpbmcgdmlldyBtb3VudHMgYSBub3RlJ3MgbGVhZGluZyBzZWN0aW9ucyBtb3JlIHRoYW4gb25jZSB3aGlsZSBpdCBzZXR0bGVzLCBzbyB0aGUgRE9NIGNhblxuICAgICAgICAvLyBob2xkIHNldmVyYWwgZWxlbWVudHMgcGVyIGZlbmNlLiBUaGUgY2FwdGlvbnMgYXJlIGRlZHVwbGljYXRlZCwgYW5kIHRoZSBhc3NlcnRpb24gaXMgdGhhdCBhdFxuICAgICAgICAvLyBsZWFzdCBhcyBtYW55IERJU1RJTkNUIGJ1dHRvbnMgcmVuZGVyZWQgYXMgdGhlIHNvdXJjZSBkZWNsYXJlcyBcdTIwMTQgYSBmZW5jZSB0aGF0IHNpbGVudGx5IHN0YXllZFxuICAgICAgICAvLyBBIHBsYWluIGNvZGUgYmxvY2sgaXMgdGhlIGZhaWx1cmUgdGhpcyBjYXRjaGVzLlxuICAgICAgICBjb25zdCBtaXNzaW5nQ2FwdGlvbnMgPSBub3RlLmNhcHRpb25zLmZpbHRlcigoY2FwdGlvbikgPT4gIWNhcHRpb25zLmluY2x1ZGVzKGNhcHRpb24pKTtcbiAgICAgICAgZXhwZWN0KFxuICAgICAgICAgIGNhcHRpb25zLmxlbmd0aCxcbiAgICAgICAgICBgJHtub3RlLm5hbWV9IGRlY2xhcmVzICR7U3RyaW5nKG5vdGUuYnV0dG9uQ291bnQpfSBidXR0b24ocykgYnV0IG9ubHkgJHtTdHJpbmcoY2FwdGlvbnMubGVuZ3RoKX0gcmVuZGVyZWQ7IGBcbiAgICAgICAgICAgICsgYG5ldmVyIHNlZW46ICR7bWlzc2luZ0NhcHRpb25zLm1hcCgoY2FwdGlvbikgPT4gYFwiJHtjYXB0aW9ufVwiYCkuam9pbignLCAnKX1gXG4gICAgICAgIClcbiAgICAgICAgICAudG9CZUdyZWF0ZXJUaGFuT3JFcXVhbChub3RlLmJ1dHRvbkNvdW50KTtcblxuICAgICAgICBjb25zdCByZXN1bHRzOiBEZW1vVmF1bHRCdXR0b25SZXN1bHRbXSA9IFtdO1xuICAgICAgICBmb3IgKGNvbnN0IGNhcHRpb24gb2YgY2FwdGlvbnMpIHtcbiAgICAgICAgICByZXN1bHRzLnB1c2goYXdhaXQgY2xpY2tCdXR0b24oeyBidXR0b25DYXB0aW9uOiBjYXB0aW9uLCBub3RlUGF0aDogbm90ZS5uYW1lLCBzaG91bGREaXNtaXNzTW9kYWxzLCB0aW1lb3V0czogY2xpY2tCdXR0b25UaW1lb3V0cyB9KSk7XG4gICAgICAgIH1cblxuICAgICAgICBjb25zdCBmYWlsdXJlcyA9IHNlbGVjdFVuZXhwZWN0ZWRGYWlsdXJlcyhub3RlLm5hbWUsIHJlc3VsdHMsIGV4cGVjdGVkTm9uT2tCdXR0b25zKTtcblxuICAgICAgICBleHBlY3QoZmFpbHVyZXMsIGZvcm1hdEZhaWx1cmVzKG5vdGUubmFtZSwgZmFpbHVyZXMpKS50b0VxdWFsKFtdKTtcbiAgICAgIH0pO1xuICAgIH1cbiAgfSk7XG59XG5cbi8qIHY4IGlnbm9yZSBzdG9wICovXG5cbi8qIHY4IGlnbm9yZSBzdGFydCAtLSBEcml2ZXMgYSByZWFsIE9ic2lkaWFuIG92ZXIgQ0RQOiB0aGUgY2xvc3VyZSBpcyBzZXJpYWxpemVkIGhlcmUgYW5kIGV4ZWN1dGVkIGluIGFub3RoZXIgcHJvY2Vzcywgc28gaXQgY2Fubm90IGJlIGV4ZXJjaXNlZCBieSBhIHVuaXQgdGVzdC4gKi9cbi8qKlxuICogVHVybnMgcmVzdHJpY3RlZCBtb2RlIG9mZiBhbmQgZW5hYmxlcyBDb2RlU2NyaXB0IFRvb2xraXQsIHdob3NlIGJpbmFyeSB0aGUgZ2xvYmFsIHNldHVwIHNlZWRlZC5cbiAqXG4gKiBAcGFyYW0gdGltZW91dEluTWlsbGlzZWNvbmRzIC0gSG93IGxvbmcgdG8gd2FpdCBmb3IgaXQgdG8gbG9hZC5cbiAqIEByZXR1cm5zIFdoZXRoZXIgQ29kZVNjcmlwdCBUb29sa2l0IGlzIGxvYWRlZC5cbiAqL1xuYXN5bmMgZnVuY3Rpb24gY2hlY2tDb2RlU2NyaXB0VG9vbGtpdExvYWRlZCh0aW1lb3V0SW5NaWxsaXNlY29uZHM6IG51bWJlcik6IFByb21pc2U8Ym9vbGVhbj4ge1xuICByZXR1cm4gZXZhbEluT2JzaWRpYW4oe1xuICAgIGFzeW5jIGNhbGxiYWNrKHsgYXBwLCBjb2RlU2NyaXB0VG9vbGtpdFBsdWdpbklkLCBpbnRlcnZhbEluTWlsbGlzZWNvbmRzLCBsaWI6IHsgd2FpdFVudGlsIH0sIHRpbWVvdXRJbk1pbGxpc2Vjb25kczogdGltZW91dCB9KTogUHJvbWlzZTxib29sZWFuPiB7XG4gICAgICBpZiAodHlwZW9mIGFwcC5wbHVnaW5zLmlzRW5hYmxlZCA9PT0gJ2Z1bmN0aW9uJyAmJiAhYXBwLnBsdWdpbnMuaXNFbmFibGVkKCkpIHtcbiAgICAgICAgYXdhaXQgYXBwLnBsdWdpbnMuc2V0RW5hYmxlKHRydWUpO1xuICAgICAgfVxuICAgICAgaWYgKCFhcHAucGx1Z2lucy5nZXRQbHVnaW4oY29kZVNjcmlwdFRvb2xraXRQbHVnaW5JZCkpIHtcbiAgICAgICAgYXdhaXQgYXBwLnBsdWdpbnMuZW5hYmxlUGx1Z2luKGNvZGVTY3JpcHRUb29sa2l0UGx1Z2luSWQpO1xuICAgICAgfVxuICAgICAgdHJ5IHtcbiAgICAgICAgYXdhaXQgd2FpdFVudGlsKHtcbiAgICAgICAgICBpbnRlcnZhbEluTWlsbGlzZWNvbmRzLFxuICAgICAgICAgIG1lc3NhZ2U6ICdDb2RlU2NyaXB0IFRvb2xraXQgbmV2ZXIgbG9hZGVkJyxcbiAgICAgICAgICBwcmVkaWNhdGU6ICgpOiBib29sZWFuID0+IGFwcC5wbHVnaW5zLmdldFBsdWdpbihjb2RlU2NyaXB0VG9vbGtpdFBsdWdpbklkKSAhPT0gbnVsbCxcbiAgICAgICAgICB0aW1lb3V0SW5NaWxsaXNlY29uZHM6IHRpbWVvdXRcbiAgICAgICAgfSk7XG4gICAgICB9IGNhdGNoIHtcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgfVxuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfSxcbiAgICBpbnB1dDoge1xuICAgICAgY29kZVNjcmlwdFRvb2xraXRQbHVnaW5JZDogQ09ERV9TQ1JJUFRfVE9PTEtJVF9QTFVHSU5fSUQsXG4gICAgICBpbnRlcnZhbEluTWlsbGlzZWNvbmRzOiBQT0xMX0lOVEVSVkFMX0lOX01JTExJU0VDT05EUyxcbiAgICAgIHRpbWVvdXRJbk1pbGxpc2Vjb25kc1xuICAgIH0sXG4gICAgdmF1bHRQYXRoOiBnZXRUZW1wb3JhcnlWYXVsdCgpLnBhdGhcbiAgfSk7XG59XG5cbi8qIHY4IGlnbm9yZSBzdG9wICovXG5cbi8qIHY4IGlnbm9yZSBzdGFydCAtLSBEcml2ZXMgYSByZWFsIE9ic2lkaWFuIG92ZXIgQ0RQOiB0aGUgY2xvc3VyZSBpcyBzZXJpYWxpemVkIGhlcmUgYW5kIGV4ZWN1dGVkIGluIGFub3RoZXIgcHJvY2Vzcywgc28gaXQgY2Fubm90IGJlIGV4ZXJjaXNlZCBieSBhIHVuaXQgdGVzdC4gKi9cbi8qKlxuICogQ2xpY2tzIG9uZSBidXR0b24gYW5kIHJlYWRzIHRoZSByZXN1bHQgbGluZSBDb2RlU2NyaXB0IFRvb2xraXQgd3JpdGVzIHVuZGVyIGl0LlxuICpcbiAqIEEgYnV0dG9uIHRoYXQgcmUtcmVuZGVycyBpdHMgb3duIG5vdGUgKGEgc2V0dGluZ3MgY2hhbmdlLCBhIHJlbG9hZCkgZGV0YWNoZXMgdGhlIGJsb2NrIGl0IGxpdmVzIGluLFxuICogc28gdGhlIGJsb2NrIGVsZW1lbnQgaXMgY2FwdHVyZWQgQkVGT1JFIHRoZSBjbGljayBhbmQgcmVhZCBhZnRlcndhcmRzIFx1MjAxNCBDb2RlU2NyaXB0IFRvb2xraXQgd3JpdGVzIHRoZVxuICogcmVzdWx0IGludG8gdGhhdCBzYW1lIGVsZW1lbnQgZXZlbiBvbmNlIGl0IGlzIGRldGFjaGVkLlxuICpcbiAqIEBwYXJhbSBwYXJhbXMgLSBUaGUge0BsaW5rIENsaWNrQnV0dG9uUGFyYW1zfS5cbiAqIEByZXR1cm5zIFRoZSB7QGxpbmsgRGVtb1ZhdWx0QnV0dG9uUmVzdWx0fS5cbiAqL1xuYXN5bmMgZnVuY3Rpb24gY2xpY2tCdXR0b24ocGFyYW1zOiBDbGlja0J1dHRvblBhcmFtcyk6IFByb21pc2U8RGVtb1ZhdWx0QnV0dG9uUmVzdWx0PiB7XG4gIHJldHVybiBldmFsSW5PYnNpZGlhbih7XG4gICAgYXN5bmMgY2FsbGJhY2soe1xuICAgICAgYXBwLFxuICAgICAgYnV0dG9uUmVzdWx0VGltZW91dEluTWlsbGlzZWNvbmRzLFxuICAgICAgY2FwdGlvbixcbiAgICAgIGludGVydmFsSW5NaWxsaXNlY29uZHMsXG4gICAgICBsaWI6IHsgcHJlc3NLZXksIHdhaXRVbnRpbCB9LFxuICAgICAgbm90ZVBhdGg6IG5vdGVQYXRoVG9PcGVuLFxuICAgICAgb2JzaWRpYW5Nb2R1bGUsXG4gICAgICBvdXRwdXRFeGNlcnB0TGVuZ3RoLFxuICAgICAgc2V0dGxlVGltZW91dEluTWlsbGlzZWNvbmRzLFxuICAgICAgc2hvdWxkRGlzbWlzc01vZGFsczogc2hvdWxkRGlzbWlzc1xuICAgIH0pOiBQcm9taXNlPERlbW9WYXVsdEJ1dHRvblJlc3VsdD4ge1xuICAgICAgZnVuY3Rpb24gdmlldygpOiBJbnN0YW5jZVR5cGU8dHlwZW9mIG9ic2lkaWFuTW9kdWxlLk1hcmtkb3duVmlldz4gfCBudWxsIHtcbiAgICAgICAgcmV0dXJuIGFwcC53b3Jrc3BhY2UuZ2V0QWN0aXZlVmlld09mVHlwZShvYnNpZGlhbk1vZHVsZS5NYXJrZG93blZpZXcpO1xuICAgICAgfVxuICAgICAgZnVuY3Rpb24gcHJldmlld0VsKCk6IEhUTUxFbGVtZW50IHwgbnVsbCB7XG4gICAgICAgIHJldHVybiB2aWV3KCk/LmNvbnRhaW5lckVsLnF1ZXJ5U2VsZWN0b3I8SFRNTEVsZW1lbnQ+KCc6c2NvcGUgLm1hcmtkb3duLXByZXZpZXctdmlldycpID8/IG51bGw7XG4gICAgICB9XG4gICAgICBmdW5jdGlvbiBidXR0b25zKCk6IEhUTUxCdXR0b25FbGVtZW50W10ge1xuICAgICAgICByZXR1cm4gWy4uLnZpZXcoKT8uY29udGFpbmVyRWwucXVlcnlTZWxlY3RvckFsbDxIVE1MQnV0dG9uRWxlbWVudD4oJzpzY29wZSAuYmxvY2stbGFuZ3VhZ2UtY29kZS1idXR0b24gYnV0dG9uLm1vZC1jdGEnKSA/PyBbXV07XG4gICAgICB9XG5cbiAgICAgIGZ1bmN0aW9uIGZpbmRCdXR0b24oKTogSFRNTEJ1dHRvbkVsZW1lbnQgfCB1bmRlZmluZWQge1xuICAgICAgICByZXR1cm4gYnV0dG9ucygpLmZpbmQoKGNhbmRpZGF0ZSkgPT4gY2FuZGlkYXRlLnRleHRDb250ZW50ID09PSBjYXB0aW9uKTtcbiAgICAgIH1cblxuICAgICAgLy8gUmVhZGluZyB2aWV3IG1vdW50cyBsYXppbHkgYW5kIHVubW91bnRzIHNlY3Rpb25zIGZhciBvZmYtc2NyZWVuLCBzbyBOTyBzaW5nbGUgc2Nyb2xsIHBvc2l0aW9uXG4gICAgICAvLyBob2xkcyBhIHdob2xlIG5vdGUncyBidXR0b25zLiBBZHZhbmNlIGEgdmlld3BvcnQgYXQgYSB0aW1lIGFuZCB3cmFwIGJhY2sgdG8gdGhlIHRvcCwgcmVtb3VudGluZ1xuICAgICAgLy8gZXZlcnkgc2VjdGlvbiBpbiB0dXJuIHVudGlsIHRoZSBvbmUgYmVpbmcgbG9va2VkIGZvciBhcHBlYXJzLiBQaW5uaW5nIHRvIHRoZSBCT1RUT00gaW5zdGVhZCBcdTIwMTRcbiAgICAgIC8vIHdoYXQgdGhpcyBkaWQgdW50aWwgOTQuNC4xIFx1MjAxNCBvbmx5IGV2ZXIgbW91bnRzIHRoZSBub3RlJ3MgdGFpbCwgc28gYSBidXR0b24gYW55d2hlcmUgYnV0IGF0IHRoZVxuICAgICAgLy8gZW5kIG9mIGl0cyBub3RlIHdhcyByZXBvcnRlZCBhcyBuZXZlciByZW5kZXJlZCAoYHN0YXR1czogJ3RpbWVvdXQnYCwgZW1wdHkgb3V0cHV0KSBob3dldmVyXG4gICAgICAvLyBoZWFsdGh5IGl0IHdhcy5cbiAgICAgIGNvbnN0IFNDUk9MTF9CT1RUT01fVE9MRVJBTkNFX0lOX1BJWEVMUyA9IDQ7XG4gICAgICBjb25zdCBTQ1JPTExfU1RFUF9SQVRJTyA9IDAuODtcbiAgICAgIGZ1bmN0aW9uIGFkdmFuY2VTY3JvbGwoKTogdm9pZCB7XG4gICAgICAgIGNvbnN0IHNjcm9sbGVyID0gcHJldmlld0VsKCk7XG4gICAgICAgIGlmICghc2Nyb2xsZXIpIHtcbiAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgY29uc3QgaXNBdEJvdHRvbSA9IHNjcm9sbGVyLnNjcm9sbFRvcCArIHNjcm9sbGVyLmNsaWVudEhlaWdodCA+PSBzY3JvbGxlci5zY3JvbGxIZWlnaHQgLSBTQ1JPTExfQk9UVE9NX1RPTEVSQU5DRV9JTl9QSVhFTFM7XG4gICAgICAgIHNjcm9sbGVyLnNjcm9sbFRvcCA9IGlzQXRCb3R0b20gPyAwIDogc2Nyb2xsZXIuc2Nyb2xsVG9wICsgTWF0aC5mbG9vcihzY3JvbGxlci5jbGllbnRIZWlnaHQgKiBTQ1JPTExfU1RFUF9SQVRJTyk7XG4gICAgICB9XG5cbiAgICAgIC8vIEJvdGggdGhlIHByZS0xLjEzIGFuZCB0aGUgMS4xMyBuYW1lIG9mIGEgbW9kYWwncyBYOiB0aGUgb2xkIG9uZSBhbG9uZSBtYXRjaGVzIG5vdGhpbmcgb24gYSBjdXJyZW50XG4gICAgICAvLyBPYnNpZGlhbiwgYW5kIGNsaWNraW5nIG5vdGhpbmcgaXMgYSBzaWxlbnQgbm8tb3AgcmF0aGVyIHRoYW4gYW4gZXJyb3IuXG4gICAgICBhc3luYyBmdW5jdGlvbiBkaXNtaXNzTW9kYWxzKCk6IFByb21pc2U8dm9pZD4ge1xuICAgICAgICBpZiAoIXNob3VsZERpc21pc3MpIHtcbiAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgZm9yIChjb25zdCBjbG9zZUJ1dHRvbiBvZiBhY3RpdmVEb2N1bWVudC5ib2R5LnF1ZXJ5U2VsZWN0b3JBbGw8SFRNTEVsZW1lbnQ+KCc6c2NvcGUgLm1vZGFsLWNvbnRhaW5lciA6aXMoLm1vZGFsLWNsb3NlLWJ1dHRvbiwgLm1vZGFsLWhlYWRlci1idXR0b24pJykpIHtcbiAgICAgICAgICBjbG9zZUJ1dHRvbi5jbGljaygpO1xuICAgICAgICB9XG4gICAgICAgIC8vIEEgdHJ1c3RlZCBFc2NhcGUgXHUyMDE0IHdoYXQgYSB1c2VyIHByZXNzZXMgXHUyMDE0IGJ1dCBvbmx5IHdoaWxlIHNvbWV0aGluZyBpcyBzdGlsbCBvcGVuOiB0aGlzIHJ1bnMgb25cbiAgICAgICAgLy8gZXZlcnkgcG9sbCwgYW5kIGFuIHVuY29uZGl0aW9uYWwga2V5IHByZXNzIHdvdWxkIGxhbmQgaW4gd2hhdGV2ZXIgdGhlIG5leHQgYnV0dG9uIGlzIGRvaW5nLlxuICAgICAgICBpZiAoYWN0aXZlRG9jdW1lbnQucXVlcnlTZWxlY3RvcignLm1vZGFsLWNvbnRhaW5lciwgLnByb21wdCcpKSB7XG4gICAgICAgICAgYXdhaXQgcHJlc3NLZXkoeyBrZXk6ICdFc2NhcGUnIH0pO1xuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIC8vIFJlLW9wZW4gdGhlIG5vdGUgYmVmb3JlIGV2ZXJ5IGNsaWNrIGluc3RlYWQgb2YgYXNzdW1pbmcgdGhlIHByZXZpb3VzIGJ1dHRvbiBsZWZ0IHRoZSB3b3Jrc3BhY2VcbiAgICAgIC8vIHdoZXJlIGl0IHdhcyBmb3VuZC4gRXZlcnkgaGVscGVyIGFib3ZlIHJlYWRzIHRoZSBBQ1RJVkUgdmlldywgYW5kIG9wZW5pbmcgYSBub3RlIGlzIG9uZSBvZiB0aGVcbiAgICAgIC8vIG1vc3Qgb3JkaW5hcnkgdGhpbmdzIGEgZGVtbyBidXR0b24gZG9lcyBcdTIwMTQgc28gdGhlIGZpcnN0IHN1Y2ggYnV0dG9uIHdvdWxkIG90aGVyd2lzZSBzZW5kIGVhY2hcbiAgICAgIC8vIGxhdGVyIGJ1dHRvbiBpbiBpdHMgbm90ZSB0byBgc3RhdHVzOiAndGltZW91dCdgIHdpdGggYW4gZW1wdHkgb3V0cHV0LCB3aGljaCBpcyB0aGUgc2hhcGUgb2YgYVxuICAgICAgLy8gYnV0dG9uIHRoYXQgbmV2ZXIgcmVuZGVyZWQgcmF0aGVyIHRoYW4gb25lIHRoYXQgd2FzIGxvb2tlZCBmb3IgaW4gdGhlIHdyb25nIHZpZXcuXG4gICAgICBhd2FpdCBhcHAud29ya3NwYWNlLm9wZW5MaW5rVGV4dChub3RlUGF0aFRvT3Blbi5yZXBsYWNlKC9cXC5tZCQvLCAnJyksICcnLCBmYWxzZSk7XG4gICAgICBhd2FpdCBhcHAud29ya3NwYWNlLmdldExlYWYoZmFsc2UpLnNldFZpZXdTdGF0ZSh7IHN0YXRlOiB7IGZpbGU6IG5vdGVQYXRoVG9PcGVuLCBtb2RlOiAncHJldmlldycgfSwgdHlwZTogJ21hcmtkb3duJyB9KTtcblxuICAgICAgLy8gSGVsZCBmcm9tIHRoZSBwcmVkaWNhdGUgcmF0aGVyIHRoYW4gcmUtcXVlcmllZCBhZnRlciBpdDogdGhlIHdhbGsgYWJvdmUga2VlcHMgbW92aW5nIHRoZVxuICAgICAgLy8gdmlld3BvcnQsIHNvIGEgYnV0dG9uIGZvdW5kIG9uIG9uZSBwb2xsIGNhbiBiZSB1bm1vdW50ZWQgYWdhaW4gYnkgdGhlIG5leHQuXG4gICAgICBsZXQgYnV0dG9uOiBIVE1MQnV0dG9uRWxlbWVudCB8IHVuZGVmaW5lZDtcbiAgICAgIHRyeSB7XG4gICAgICAgIGF3YWl0IHdhaXRVbnRpbCh7XG4gICAgICAgICAgaW50ZXJ2YWxJbk1pbGxpc2Vjb25kcyxcbiAgICAgICAgICBtZXNzYWdlOiBgY29kZSBidXR0b24gXCIke2NhcHRpb259XCIgbmV2ZXIgcmVuZGVyZWRgLFxuICAgICAgICAgIHByZWRpY2F0ZTogKCk6IGJvb2xlYW4gPT4ge1xuICAgICAgICAgICAgYWR2YW5jZVNjcm9sbCgpO1xuICAgICAgICAgICAgYnV0dG9uID0gZmluZEJ1dHRvbigpO1xuICAgICAgICAgICAgcmV0dXJuIGJ1dHRvbiAhPT0gdW5kZWZpbmVkO1xuICAgICAgICAgIH0sXG4gICAgICAgICAgdGltZW91dEluTWlsbGlzZWNvbmRzOiBzZXR0bGVUaW1lb3V0SW5NaWxsaXNlY29uZHNcbiAgICAgICAgfSk7XG4gICAgICB9IGNhdGNoIHtcbiAgICAgICAgcmV0dXJuIHsgY2FwdGlvbiwgb3V0cHV0OiAnJywgc3RhdHVzOiAndGltZW91dCcgfTtcbiAgICAgIH1cblxuICAgICAgaWYgKCFidXR0b24pIHtcbiAgICAgICAgcmV0dXJuIHsgY2FwdGlvbiwgb3V0cHV0OiAnJywgc3RhdHVzOiAndGltZW91dCcgfTtcbiAgICAgIH1cblxuICAgICAgY29uc3QgYmxvY2sgPSBidXR0b24uY2xvc2VzdDxIVE1MRWxlbWVudD4oJy5ibG9jay1sYW5ndWFnZS1jb2RlLWJ1dHRvbicpID8/IGJ1dHRvbi5wYXJlbnRFbGVtZW50O1xuICAgICAgYnV0dG9uLnNjcm9sbEludG9WaWV3KCk7XG4gICAgICBidXR0b24uY2xpY2soKTtcblxuICAgICAgbGV0IHN0YXR1czogRGVtb1ZhdWx0QnV0dG9uUmVzdWx0WydzdGF0dXMnXTtcbiAgICAgIHRyeSB7XG4gICAgICAgIGF3YWl0IHdhaXRVbnRpbCh7XG4gICAgICAgICAgaW50ZXJ2YWxJbk1pbGxpc2Vjb25kcyxcbiAgICAgICAgICBtZXNzYWdlOiBgYnV0dG9uIFwiJHtjYXB0aW9ufVwiIG5ldmVyIHJlcG9ydGVkIGEgcmVzdWx0YCxcbiAgICAgICAgICBwcmVkaWNhdGU6IGFzeW5jICgpOiBQcm9taXNlPGJvb2xlYW4+ID0+IHtcbiAgICAgICAgICAgIC8vIEEgYnV0dG9uIHRoYXQgYXdhaXRzIGFuIGFsZXJ0IC8gY29uZmlybSAvIHByb21wdCByZXBvcnRzIG5vdGhpbmcgdW50aWwgdGhlIGRpYWxvZyBjbG9zZXMuXG4gICAgICAgICAgICBhd2FpdCBkaXNtaXNzTW9kYWxzKCk7XG4gICAgICAgICAgICByZXR1cm4gL0V4ZWN1dGVkICg/OnN1Y2Nlc3NmdWxseXx3aXRoIGVycm9yKS8udGVzdChibG9jaz8udGV4dENvbnRlbnQgPz8gJycpO1xuICAgICAgICAgIH0sXG4gICAgICAgICAgdGltZW91dEluTWlsbGlzZWNvbmRzOiBidXR0b25SZXN1bHRUaW1lb3V0SW5NaWxsaXNlY29uZHNcbiAgICAgICAgfSk7XG4gICAgICAgIGNvbnN0IHRleHQgPSBibG9jaz8udGV4dENvbnRlbnQgPz8gJyc7XG4gICAgICAgIGlmICh0ZXh0LmluY2x1ZGVzKCdFeGVjdXRlZCB3aXRoIGVycm9yJykpIHtcbiAgICAgICAgICBzdGF0dXMgPSAnZXJyb3InO1xuICAgICAgICB9IGVsc2UgaWYgKHRleHQuaW5jbHVkZXMoJ0V4ZWN1dGVkIHN1Y2Nlc3NmdWxseScpKSB7XG4gICAgICAgICAgc3RhdHVzID0gJ29rJztcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBzdGF0dXMgPSAndW5rbm93bic7XG4gICAgICAgIH1cbiAgICAgIH0gY2F0Y2gge1xuICAgICAgICBzdGF0dXMgPSAndGltZW91dCc7XG4gICAgICB9XG5cbiAgICAgIC8vIFdoYXRldmVyIHRoaXMgYnV0dG9uIGxlZnQgb3BlbiB3b3VsZCBvdGhlcndpc2Ugc2l0IG92ZXIgdGhlIG5leHQgb25lLlxuICAgICAgYXdhaXQgZGlzbWlzc01vZGFscygpO1xuXG4gICAgICByZXR1cm4geyBjYXB0aW9uLCBvdXRwdXQ6IChibG9jaz8udGV4dENvbnRlbnQgPz8gJycpLnNsaWNlKDAsIG91dHB1dEV4Y2VycHRMZW5ndGgpLCBzdGF0dXMgfTtcbiAgICB9LFxuICAgIGlucHV0OiB7XG4gICAgICBidXR0b25SZXN1bHRUaW1lb3V0SW5NaWxsaXNlY29uZHM6IHBhcmFtcy50aW1lb3V0cy5idXR0b25SZXN1bHRUaW1lb3V0SW5NaWxsaXNlY29uZHMsXG4gICAgICBjYXB0aW9uOiBwYXJhbXMuYnV0dG9uQ2FwdGlvbixcbiAgICAgIGludGVydmFsSW5NaWxsaXNlY29uZHM6IFBPTExfSU5URVJWQUxfSU5fTUlMTElTRUNPTkRTLFxuICAgICAgbm90ZVBhdGg6IHBhcmFtcy5ub3RlUGF0aCxcbiAgICAgIG91dHB1dEV4Y2VycHRMZW5ndGg6IE9VVFBVVF9FWENFUlBUX0xFTkdUSCxcbiAgICAgIHNldHRsZVRpbWVvdXRJbk1pbGxpc2Vjb25kczogcGFyYW1zLnRpbWVvdXRzLnNldHRsZVRpbWVvdXRJbk1pbGxpc2Vjb25kcyxcbiAgICAgIHNob3VsZERpc21pc3NNb2RhbHM6IHBhcmFtcy5zaG91bGREaXNtaXNzTW9kYWxzXG4gICAgfSxcbiAgICB2YXVsdFBhdGg6IGdldFRlbXBvcmFyeVZhdWx0KCkucGF0aFxuICB9KTtcbn1cblxuLyoqXG4gKiBPcGVucyBhIG5vdGUgaW4gcmVhZGluZyB2aWV3IGFuZCBsaXN0cyB0aGUgY2FwdGlvbnMgb2YgdGhlIGJ1dHRvbnMgdGhhdCBtb3VudGVkLCBkZWR1cGxpY2F0ZWQgYW5kIGluXG4gKiBkb2N1bWVudCBvcmRlci5cbiAqXG4gKiBUd28gcXVpcmtzIG9mIHJlYWRpbmcgdmlldyBzaGFwZSB0aGlzLiBJdCByZW5kZXJzIGxhemlseSBhbmQgdW5tb3VudHMgc2VjdGlvbnMgZmFyIG9mZi1zY3JlZW4sIHNvIG5vXG4gKiBzaW5nbGUgc2Nyb2xsIHBvc2l0aW9uIGhvbGRzIGEgd2hvbGUgbm90ZSdzIGJ1dHRvbnMgXHUyMDE0IHRoZSBwcmV2aWV3IGlzIHdhbGtlZCB0b3AgdG8gYm90dG9tIGFuZCBiYWNrXG4gKiB3aGlsZSB3YWl0aW5nLCBhbmQgdGhlIGNhcHRpb25zIHNlZW4gYWxvbmcgdGhlIHdheSBhcmUgQUNDVU1VTEFURUQgcmF0aGVyIHRoYW4gcmVhZCBvbmNlIGF0IHRoZSBlbmQuXG4gKiBBbmQgd2hpbGUgaXQgc2V0dGxlcyBpdCBjYW4gaG9sZCBTRVZFUkFMIGVsZW1lbnRzIHBlciBmZW5jZSBcdTIwMTQgdGhlIHNhbWUgYnV0dG9uIHdhcyBvYnNlcnZlZCByZW5kZXJlZFxuICogdHdpY2UgXHUyMDE0IHNvIHRoZSBjYXB0aW9ucyBhcmUgZGVkdXBsaWNhdGVkOyBjbGlja2luZyBieSBjYXB0aW9uIHRoZW4gYWRkcmVzc2VzIGVhY2ggYnV0dG9uIG9uY2UgaG93ZXZlclxuICogbWFueSBjb3BpZXMgb2YgaXQgdGhlIERPTSBpcyBob2xkaW5nLlxuICpcbiAqIEBwYXJhbSBub3RlIC0gVGhlIG5vdGUgdG8gb3Blbi5cbiAqIEBwYXJhbSBzZXR0bGVUaW1lb3V0SW5NaWxsaXNlY29uZHMgLSBIb3cgbG9uZyB0byB3YWl0IGZvciB0aGUgYnV0dG9ucyB0byBtb3VudC5cbiAqIEByZXR1cm5zIFRoZSBkaXN0aW5jdCBidXR0b24gY2FwdGlvbnMuXG4gKi9cbmFzeW5jIGZ1bmN0aW9uIG9wZW5Ob3RlQW5kTGlzdEJ1dHRvbkNhcHRpb25zKG5vdGU6IERlbW9WYXVsdE5vdGUsIHNldHRsZVRpbWVvdXRJbk1pbGxpc2Vjb25kczogbnVtYmVyKTogUHJvbWlzZTxzdHJpbmdbXT4ge1xuICByZXR1cm4gZXZhbEluT2JzaWRpYW4oe1xuICAgIGFzeW5jIGNhbGxiYWNrKHsgYXBwLCBleHBlY3RlZEJ1dHRvbkNvdW50LCBpbnRlcnZhbEluTWlsbGlzZWNvbmRzLCBsaWI6IHsgd2FpdFVudGlsIH0sIG5vdGVQYXRoLCBvYnNpZGlhbk1vZHVsZSwgdGltZW91dEluTWlsbGlzZWNvbmRzIH0pOiBQcm9taXNlPHN0cmluZ1tdPiB7XG4gICAgICBmdW5jdGlvbiB2aWV3KCk6IEluc3RhbmNlVHlwZTx0eXBlb2Ygb2JzaWRpYW5Nb2R1bGUuTWFya2Rvd25WaWV3PiB8IG51bGwge1xuICAgICAgICByZXR1cm4gYXBwLndvcmtzcGFjZS5nZXRBY3RpdmVWaWV3T2ZUeXBlKG9ic2lkaWFuTW9kdWxlLk1hcmtkb3duVmlldyk7XG4gICAgICB9XG4gICAgICBmdW5jdGlvbiBwcmV2aWV3RWwoKTogSFRNTEVsZW1lbnQgfCBudWxsIHtcbiAgICAgICAgcmV0dXJuIHZpZXcoKT8uY29udGFpbmVyRWwucXVlcnlTZWxlY3RvcjxIVE1MRWxlbWVudD4oJzpzY29wZSAubWFya2Rvd24tcHJldmlldy12aWV3JykgPz8gbnVsbDtcbiAgICAgIH1cbiAgICAgIC8vIEFjY3VtdWxhdGVkIGFjcm9zcyB0aGUgd2FsayBiZWxvdywgbmV2ZXIgcmVhZCBmcm9tIG9uZSBzbmFwc2hvdDogd2l0aCB0aGUgdmlld3BvcnQgbW92aW5nLCBhbnlcbiAgICAgIC8vIHNpbmdsZSByZWFkaW5nIGhvbGRzIG9ubHkgdGhlIHNlY3Rpb25zIGN1cnJlbnRseSBtb3VudGVkLlxuICAgICAgY29uc3Qgc2VlbkNhcHRpb25zID0gbmV3IFNldDxzdHJpbmc+KCk7XG4gICAgICBmdW5jdGlvbiBjYXB0aW9ucygpOiBzdHJpbmdbXSB7XG4gICAgICAgIGZvciAoY29uc3QgYnV0dG9uIG9mIHZpZXcoKT8uY29udGFpbmVyRWwucXVlcnlTZWxlY3RvckFsbDxIVE1MQnV0dG9uRWxlbWVudD4oJzpzY29wZSAuYmxvY2stbGFuZ3VhZ2UtY29kZS1idXR0b24gYnV0dG9uLm1vZC1jdGEnKSA/PyBbXSkge1xuICAgICAgICAgIGlmIChidXR0b24udGV4dENvbnRlbnQgIT09ICcnKSB7XG4gICAgICAgICAgICBzZWVuQ2FwdGlvbnMuYWRkKGJ1dHRvbi50ZXh0Q29udGVudCk7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiBbLi4uc2VlbkNhcHRpb25zXTtcbiAgICAgIH1cblxuICAgICAgLy8gU2FtZSB3YWxrIGFzIGBjbGlja0J1dHRvbmAsIGFuZCBmb3IgdGhlIHNhbWUgcmVhc29uOiBhIG5vdGUgd2hvc2UgYnV0dG9ucyBhcmUgaW4gdGhlIE1JRERMRVxuICAgICAgLy8gbmV2ZXIgbW91bnRzIHRoZW0gaWYgdGhlIHByZXZpZXcgaXMgcGlubmVkIHRvIHRoZSBib3R0b20uXG4gICAgICBjb25zdCBTQ1JPTExfQk9UVE9NX1RPTEVSQU5DRV9JTl9QSVhFTFMgPSA0O1xuICAgICAgY29uc3QgU0NST0xMX1NURVBfUkFUSU8gPSAwLjg7XG4gICAgICBmdW5jdGlvbiBhZHZhbmNlU2Nyb2xsKCk6IHZvaWQge1xuICAgICAgICBjb25zdCBzY3JvbGxlciA9IHByZXZpZXdFbCgpO1xuICAgICAgICBpZiAoIXNjcm9sbGVyKSB7XG4gICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIGNvbnN0IGlzQXRCb3R0b20gPSBzY3JvbGxlci5zY3JvbGxUb3AgKyBzY3JvbGxlci5jbGllbnRIZWlnaHQgPj0gc2Nyb2xsZXIuc2Nyb2xsSGVpZ2h0IC0gU0NST0xMX0JPVFRPTV9UT0xFUkFOQ0VfSU5fUElYRUxTO1xuICAgICAgICBzY3JvbGxlci5zY3JvbGxUb3AgPSBpc0F0Qm90dG9tID8gMCA6IHNjcm9sbGVyLnNjcm9sbFRvcCArIE1hdGguZmxvb3Ioc2Nyb2xsZXIuY2xpZW50SGVpZ2h0ICogU0NST0xMX1NURVBfUkFUSU8pO1xuICAgICAgfVxuXG4gICAgICBhd2FpdCBhcHAud29ya3NwYWNlLm9wZW5MaW5rVGV4dChub3RlUGF0aC5yZXBsYWNlKC9cXC5tZCQvLCAnJyksICcnLCBmYWxzZSk7XG4gICAgICBhd2FpdCBhcHAud29ya3NwYWNlLmdldExlYWYoZmFsc2UpLnNldFZpZXdTdGF0ZSh7IHN0YXRlOiB7IGZpbGU6IG5vdGVQYXRoLCBtb2RlOiAncHJldmlldycgfSwgdHlwZTogJ21hcmtkb3duJyB9KTtcblxuICAgICAgdHJ5IHtcbiAgICAgICAgYXdhaXQgd2FpdFVudGlsKHtcbiAgICAgICAgICBpbnRlcnZhbEluTWlsbGlzZWNvbmRzLFxuICAgICAgICAgIG1lc3NhZ2U6IGBcIiR7bm90ZVBhdGh9XCIgbmV2ZXIgbW91bnRlZCBhbGwgJHtTdHJpbmcoZXhwZWN0ZWRCdXR0b25Db3VudCl9IG9mIGl0cyBidXR0b25zYCxcbiAgICAgICAgICBwcmVkaWNhdGU6ICgpOiBib29sZWFuID0+IHtcbiAgICAgICAgICAgIGFkdmFuY2VTY3JvbGwoKTtcbiAgICAgICAgICAgIHJldHVybiBjYXB0aW9ucygpLmxlbmd0aCA+PSBleHBlY3RlZEJ1dHRvbkNvdW50O1xuICAgICAgICAgIH0sXG4gICAgICAgICAgdGltZW91dEluTWlsbGlzZWNvbmRzXG4gICAgICAgIH0pO1xuICAgICAgfSBjYXRjaCB7XG4gICAgICAgIC8vIFRoZSBjYXB0aW9ucyBhcmUgcmV0dXJuZWQgZWl0aGVyIHdheTsgdGhlIGNhbGxlciBhc3NlcnRzIG9uIHRoZW0gYW5kIHJlcG9ydHMgdGhlIHNob3J0ZmFsbC5cbiAgICAgIH1cblxuICAgICAgcmV0dXJuIGNhcHRpb25zKCk7XG4gICAgfSxcbiAgICBpbnB1dDoge1xuICAgICAgZXhwZWN0ZWRCdXR0b25Db3VudDogbm90ZS5idXR0b25Db3VudCxcbiAgICAgIGludGVydmFsSW5NaWxsaXNlY29uZHM6IFBPTExfSU5URVJWQUxfSU5fTUlMTElTRUNPTkRTLFxuICAgICAgbm90ZVBhdGg6IG5vdGUubmFtZSxcbiAgICAgIHRpbWVvdXRJbk1pbGxpc2Vjb25kczogc2V0dGxlVGltZW91dEluTWlsbGlzZWNvbmRzXG4gICAgfSxcbiAgICB2YXVsdFBhdGg6IGdldFRlbXBvcmFyeVZhdWx0KCkucGF0aFxuICB9KTtcbn1cblxuLyogdjggaWdub3JlIHN0b3AgKi9cbiJdLAogICJt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