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