obsidian-dev-utils 92.1.0 → 93.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (35) hide show
  1. package/CHANGELOG.md +7 -0
  2. package/dist/demo-vault-helper/main.js +30 -44
  3. package/dist/integration-test-plugin/main.js +10029 -9743
  4. package/dist/lib/cjs/__merged.cjs +9 -1
  5. package/dist/lib/cjs/__merged.d.cts +2 -2
  6. package/dist/lib/cjs/generated-during-build.cjs +1 -1
  7. package/dist/lib/cjs/obsidian/components/plugin-notice-component.cjs +118 -36
  8. package/dist/lib/cjs/obsidian/components/plugin-notice-component.d.cts +88 -19
  9. package/dist/lib/cjs/obsidian/demo-vault-helper-settings.cjs +120 -0
  10. package/dist/lib/cjs/obsidian/demo-vault-helper-settings.d.cts +29 -0
  11. package/dist/lib/cjs/obsidian/demo-vault-helper.cjs +31 -32
  12. package/dist/lib/cjs/obsidian/demo-vault-helper.d.cts +7 -3
  13. package/dist/lib/cjs/obsidian/desktop-demo-vault-opener.cjs +4 -2
  14. package/dist/lib/cjs/obsidian/index.cjs +4 -1
  15. package/dist/lib/cjs/obsidian/index.d.cts +1 -0
  16. package/dist/lib/cjs/obsidian/workspace.cjs +28 -3
  17. package/dist/lib/cjs/obsidian/workspace.d.cts +50 -0
  18. package/dist/lib/cjs/script-utils/demo-vault.cjs +8 -3
  19. package/dist/lib/esm/__merged.d.mts +2 -2
  20. package/dist/lib/esm/__merged.mjs +13 -3
  21. package/dist/lib/esm/generated-during-build.mjs +1 -1
  22. package/dist/lib/esm/obsidian/components/plugin-notice-component.d.mts +88 -19
  23. package/dist/lib/esm/obsidian/components/plugin-notice-component.mjs +116 -35
  24. package/dist/lib/esm/obsidian/demo-vault-helper-settings.d.mts +29 -0
  25. package/dist/lib/esm/obsidian/demo-vault-helper-settings.mjs +24 -0
  26. package/dist/lib/esm/obsidian/demo-vault-helper.d.mts +7 -3
  27. package/dist/lib/esm/obsidian/demo-vault-helper.mjs +32 -36
  28. package/dist/lib/esm/obsidian/desktop-demo-vault-opener.mjs +4 -2
  29. package/dist/lib/esm/obsidian/index.d.mts +1 -0
  30. package/dist/lib/esm/obsidian/index.mjs +3 -1
  31. package/dist/lib/esm/obsidian/workspace.d.mts +50 -0
  32. package/dist/lib/esm/obsidian/workspace.mjs +24 -2
  33. package/dist/lib/esm/script-utils/demo-vault.mjs +10 -4
  34. package/obsidian/demo-vault-helper-settings/package.json +6 -0
  35. package/package.json +1 -1
@@ -9,6 +9,35 @@ import type { Promisable } from 'type-fest' with { 'resolution-mode': 'import' }
9
9
  import { Notice } from 'obsidian';
10
10
  import type { ValueProvider } from '../../value-provider.cjs';
11
11
  import { ComponentEx } from './component-ex.cjs';
12
+ /**
13
+ * How a new notice relates to the plugin's current notice — the one occupying the single per-plugin
14
+ * slot this component keeps.
15
+ *
16
+ * Raw `new Notice(...)` calls always pile up, which is rarely what a plugin wants: usually only the
17
+ * latest message matters. So the slot exists, and this chooses what a new message does with it.
18
+ */
19
+ export declare enum PluginNoticeMode {
20
+ /**
21
+ * Adds the message to the current notice, so both messages stay visible in a single notice — for a
22
+ * running account of an operation. The countdown restarts, so an appended message is readable for a
23
+ * full duration rather than inheriting the remains of the current one.
24
+ *
25
+ * Falls back to {@link PluginNoticeMode.Replace} when there is no current notice on screen (it was
26
+ * never shown, or it has since been dismissed).
27
+ */
28
+ Append = "append",
29
+ /**
30
+ * Hides the current notice and shows this one in its place, so only the latest message is on screen.
31
+ * This is the default, and the reason the slot exists.
32
+ */
33
+ Replace = "replace",
34
+ /**
35
+ * Shows the message as its own notice, leaving the current one alone: both are on screen, piled up
36
+ * like plain `new Notice(...)` calls. A separate notice never replaces, and is never replaced by, a
37
+ * slot notice; any number of them coexist. They are still hidden together on unload.
38
+ */
39
+ Separate = "separate"
40
+ }
12
41
  /**
13
42
  * The event passed to {@link PluginNoticeComponentShowNoticeOptions.onCloseClick} when the notice's
14
43
  * close (X) button is clicked.
@@ -26,10 +55,14 @@ export interface PluginNoticeCloseClickEvent {
26
55
  */
27
56
  export interface PluginNoticeComponentDelayedNotice extends Disposable {
28
57
  /**
29
- * Replaces the notice content, re-applying the plugin-name prefix, the interactive-click guard, and
58
+ * Replaces this handle's message, re-applying the plugin-name prefix, the interactive-click guard, and
30
59
  * the Cancel button. Useful for reporting progress. If the delay has not elapsed yet, the new content
31
60
  * becomes what is shown once it does.
32
61
  *
62
+ * Only this handle's own message is rewritten: when the notice was joined rather than opened (see
63
+ * {@link PluginNoticeComponentShowNoticeAfterDelayParams.mode}), the messages already in it are left
64
+ * alone.
65
+ *
33
66
  * @param content - The new notice content.
34
67
  */
35
68
  setContent(content: DocumentFragment | string): void;
@@ -60,6 +93,20 @@ export interface PluginNoticeComponentShowNoticeAfterDelayParams {
60
93
  * @default `500`
61
94
  */
62
95
  readonly delayInMilliseconds?: number;
96
+ /**
97
+ * How this notice relates to the plugin's current notice — see {@link PluginNoticeMode}.
98
+ *
99
+ * {@link PluginNoticeMode.Separate} is worth considering for a long operation: on the default
100
+ * {@link PluginNoticeMode.Replace} the progress notice takes the shared slot, so any ordinary notice
101
+ * raised while the operation runs hides it, and the progress the user was watching does not come back.
102
+ *
103
+ * Whichever mode is used, the returned handle owns only ITS message: updating the content rewrites
104
+ * that message alone, and disposing takes away only that message when the notice was already on
105
+ * screen (a notice this handle opened is hidden as a whole).
106
+ *
107
+ * @default {@link PluginNoticeMode.Replace}
108
+ */
109
+ readonly mode?: PluginNoticeMode;
63
110
  }
64
111
  /**
65
112
  * Options for {@link PluginNoticeComponent.showNotice}.
@@ -77,18 +124,17 @@ export interface PluginNoticeComponentShowNoticeOptions {
77
124
  */
78
125
  readonly isPermanent?: boolean;
79
126
  /**
80
- * Whether the notice occupies the single per-plugin reusable slot.
81
- *
82
- * A reusable notice takes the shared slot: the next reusable notice hides it, and it is hidden on unload.
83
- * A non-reusable (standalone) notice is not placed in the slot — it never hides, and is never hidden by, a
84
- * reusable notice; multiple standalone notices coexist. Standalone notices are still hidden together on unload.
127
+ * How this notice relates to the plugin's current notice — see {@link PluginNoticeMode}.
85
128
  *
86
- * A permanent notice must be reusable ({@link PluginNoticeComponentShowNoticeOptions.isPermanent} implies
87
- * `isReusable`); passing `isReusable: false` together with `isPermanent: true` throws.
129
+ * A permanent notice cannot be {@link PluginNoticeMode.Separate} (it needs the shared slot it is
130
+ * tracked in), and a notice that does not hide on click must be
131
+ * {@link PluginNoticeMode.Separate} (so a later notice never silently replaces it); either
132
+ * contradiction throws.
88
133
  *
89
- * @default `true`
134
+ * @default {@link PluginNoticeMode.Replace}, or {@link PluginNoticeMode.Separate} when
135
+ * {@link PluginNoticeComponentShowNoticeOptions.shouldHideOnClick} is `false`
90
136
  */
91
- readonly isReusable?: boolean;
137
+ readonly mode?: PluginNoticeMode;
92
138
  /**
93
139
  * A callback invoked when the user clicks the close (X) button, before the notice is hidden. Call
94
140
  * {@link PluginNoticeCloseClickEvent.cancel} on the event to cancel the close and keep the notice
@@ -113,9 +159,10 @@ export interface PluginNoticeComponentShowNoticeOptions {
113
159
  * {@link PluginNoticeComponentShowNoticeOptions.shouldShowCloseButton} and
114
160
  * {@link PluginNoticeComponentShowNoticeOptions.onCloseClick}).
115
161
  *
116
- * A `shouldHideOnClick: false` notice is shown with an infinite duration and is standalone (implies
117
- * {@link PluginNoticeComponentShowNoticeOptions.isReusable} `= false`), so a later notice never
118
- * silently replaces it; passing `isReusable: true` together with `shouldHideOnClick: false` throws.
162
+ * A `shouldHideOnClick: false` notice is shown with an infinite duration and stands on its own
163
+ * (implies {@link PluginNoticeMode.Separate}), so a later notice never silently replaces it; passing
164
+ * any other {@link PluginNoticeComponentShowNoticeOptions.mode} together with `shouldHideOnClick: false`
165
+ * throws.
119
166
  *
120
167
  * @default `true`
121
168
  */
@@ -151,7 +198,9 @@ interface PluginNoticeComponentConstructorParams {
151
198
  readonly pluginName: string;
152
199
  }
153
200
  /**
154
- * Manages showing plugin notices. Automatically hides the previous notice when a new one is shown.
201
+ * Manages showing plugin notices. By default a new notice hides the previous one, so only the latest
202
+ * message is on screen; {@link PluginNoticeComponentShowNoticeOptions.mode} chooses otherwise — see
203
+ * {@link PluginNoticeMode}.
155
204
  */
156
205
  export declare class PluginNoticeComponent extends ComponentEx {
157
206
  /**
@@ -221,6 +270,24 @@ export declare class PluginNoticeComponent extends ComponentEx {
221
270
  * @param params - The parameters.
222
271
  */
223
272
  private appendCloseButton;
273
+ /**
274
+ * Adds a message to the notice currently in the per-plugin slot, so both messages stay on screen in a
275
+ * single notice.
276
+ *
277
+ * The appended message carries no plugin-name prefix — the notice already opens with one, and
278
+ * repeating it on every line reads as noise. It is wrapped like any other notice content, so a link or
279
+ * button inside it still keeps the notice open when clicked.
280
+ *
281
+ * Appending restarts the notice's countdown ({@link Notice.setAutoHide}), so the new message gets a
282
+ * full duration instead of inheriting what was left of the current one — a line appended a moment
283
+ * before the notice expires would otherwise flash and vanish.
284
+ *
285
+ * @param params - The parameters.
286
+ * @returns The {@link PluginNoticeComponentShownNotice} describing the joined notice, or `null` when
287
+ * there is nothing on screen to append to — the slot is empty, or its notice has since been dismissed
288
+ * — and the caller should show a new notice instead.
289
+ */
290
+ private appendToCurrentNotice;
224
291
  /**
225
292
  * Builds the message for a delayed notice: the resolved content, optionally followed by a Cancel
226
293
  * button that aborts the provided controller when clicked.
@@ -236,7 +303,7 @@ export declare class PluginNoticeComponent extends ComponentEx {
236
303
  * input, etc.) and stops them there, so the element's own handler still runs but the notice stays.
237
304
  *
238
305
  * @param params - The parameters.
239
- * @returns A {@link DocumentFragment} holding the wrapped, prefixed notice content.
306
+ * @returns The {@link PluginNoticeComponentNoticeContent} holding the wrapped notice content.
240
307
  */
241
308
  private buildNoticeContent;
242
309
  /**
@@ -272,12 +339,14 @@ export declare class PluginNoticeComponent extends ComponentEx {
272
339
  private installUserClickTracking;
273
340
  private setPermanentNotice;
274
341
  /**
275
- * Shows a notice with the given duration. A reusable notice replaces the current reusable notice (and
276
- * is optionally registered as this plugin's permanent notice); a standalone notice is tracked
277
- * separately, leaving the reusable slot untouched.
342
+ * Shows a notice with the given duration, placing it according to its {@link PluginNoticeMode}: a
343
+ * {@link PluginNoticeMode.Replace} notice takes the per-plugin slot (hiding whatever was in it, and
344
+ * optionally registering as this plugin's permanent notice), an {@link PluginNoticeMode.Append} one
345
+ * joins the notice already in the slot, and a {@link PluginNoticeMode.Separate} one is tracked on its
346
+ * own, leaving the slot untouched.
278
347
  *
279
348
  * @param params - The parameters.
280
- * @returns The created notice.
349
+ * @returns The {@link PluginNoticeComponentShownNotice} describing where the message ended up.
281
350
  */
282
351
  private showNoticeWithDuration;
283
352
  /**
@@ -0,0 +1,120 @@
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 initCjs() {
7
+ // eslint-disable-next-line obsidianmd/no-global-this -- Actively use globalThis.
8
+ const globalThisRecord = globalThis;
9
+ globalThisRecord['__name'] ??= name;
10
+ const originalRequire = require;
11
+ if (originalRequire && !originalRequire.__isPatched) {
12
+ // eslint-disable-next-line no-global-assign, no-implicit-globals -- We need to patch the `require()` function.
13
+ require = Object.assign(
14
+ (id) => requirePatched(id),
15
+ originalRequire,
16
+ {
17
+ __isPatched: true
18
+ }
19
+ );
20
+ }
21
+
22
+ const newFuncs = {
23
+ __extractDefault() {
24
+ return extractDefault;
25
+ },
26
+ process() {
27
+ const browserProcess = {
28
+ browser: true,
29
+ cwd() {
30
+ return '/';
31
+ },
32
+ env: {},
33
+ platform: 'android'
34
+ };
35
+ return browserProcess;
36
+ }
37
+ };
38
+
39
+ for (const key of Object.keys(newFuncs)) {
40
+ globalThisRecord[key] ??= newFuncs[key]?.();
41
+ }
42
+
43
+ function extractDefault(module) {
44
+ return module && module.__esModule && 'default' in module ? module.default : module;
45
+ }
46
+
47
+ const OBSIDIAN_BUILT_IN_MODULE_NAMES = new Set([
48
+ '@codemirror/autocomplete',
49
+ '@codemirror/collab',
50
+ '@codemirror/commands',
51
+ '@codemirror/language',
52
+ '@codemirror/lint',
53
+ '@codemirror/search',
54
+ '@codemirror/state',
55
+ '@codemirror/text',
56
+ '@codemirror/view',
57
+ '@lezer/common',
58
+ '@lezer/highlight',
59
+ '@lezer/lr',
60
+ 'obsidian']
61
+ );
62
+
63
+ const DEPRECATED_OBSIDIAN_BUILT_IN_MODULE_NAMES = new Set([
64
+ '@codemirror/closebrackets',
65
+ '@codemirror/comment',
66
+ '@codemirror/fold',
67
+ '@codemirror/gutter',
68
+ '@codemirror/highlight',
69
+ '@codemirror/history',
70
+ '@codemirror/matchbrackets',
71
+ '@codemirror/panel',
72
+ '@codemirror/rangeset',
73
+ '@codemirror/rectangular-selection',
74
+ '@codemirror/stream-parser',
75
+ '@codemirror/tooltip']
76
+ );
77
+
78
+ function requirePatched(id) {
79
+ if (OBSIDIAN_BUILT_IN_MODULE_NAMES.has(id) || DEPRECATED_OBSIDIAN_BUILT_IN_MODULE_NAMES.has(id)) {
80
+ return originalRequire?.(id);
81
+ }
82
+
83
+ // eslint-disable-next-line @typescript-eslint/no-deprecated, obsidianmd/no-global-this -- Need access to app. Actively use globalThis.
84
+ if (globalThis.app.isMobile) {
85
+ if (id === 'process' || id === 'node:process') {
86
+ // eslint-disable-next-line no-console -- Valid usage.
87
+ console.debug(`The most likely you can safely ignore this error. Module not found: ${id}. Fake process object is returned instead.`);
88
+
89
+ return process;
90
+ }
91
+ } else {
92
+ const module = originalRequire?.(id);
93
+ if (module) {
94
+ return extractDefault(module);
95
+ }
96
+ }
97
+
98
+ // eslint-disable-next-line no-console -- Valid usage.
99
+ console.debug(`The most likely you can safely ignore this error. Module not found: ${id}. Empty object is returned instead.`);
100
+ return {};
101
+ }
102
+ })();
103
+
104
+ "use strict";
105
+ var __defProp = Object.defineProperty;
106
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
107
+ var __getOwnPropNames = Object.getOwnPropertyNames;
108
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
109
+ var __copyProps = (to, from, except, desc) => {
110
+ if (from && typeof from === "object" || typeof from === "function") {
111
+ for (let key of __getOwnPropNames(from))
112
+ if (!__hasOwnProp.call(to, key) && key !== except)
113
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
114
+ }
115
+ return to;
116
+ };
117
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
118
+ var demo_vault_helper_settings_exports = {};
119
+ module.exports = __toCommonJS(demo_vault_helper_settings_exports);
120
+ //# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsiLi4vLi4vLi4vLi4vc3JjL29ic2lkaWFuL2RlbW8tdmF1bHQtaGVscGVyLXNldHRpbmdzLnRzIl0sCiAgInNvdXJjZXNDb250ZW50IjogWyIvKipcbiAqIEBmaWxlXG4gKlxuICogVGhlIGBkZW1vLXZhdWx0LWhlbHBlcmAgcGx1Z2luJ3Mgb3duIHNldHRpbmdzIFx1MjAxNCB0aGUgY29udHJhY3QgYmV0d2VlbiB0aGUgZGVtby12YXVsdCBwYWNrYWdpbmcgc3RlcFxuICogYW5kIHRoZSBib290c3RyYXAgdGhhdCBydW5zIGluc2lkZSB0aGUgb3BlbmVkIHZhdWx0LlxuICpcbiAqIFRoZSBoZWxwZXIgaGFzIHRvIG5hbWUgdGhlIHBsdWdpbiB0aGUgdmF1bHQgZGVtb25zdHJhdGVzLCBhbmQgbm90aGluZyBpbnNpZGUgdGhlIHZhdWx0IHJlbGlhYmx5IHNheXNcbiAqIHdoaWNoIG9uZSB0aGF0IGlzOiB0aGUgcGx1Z2luIGZvbGRlcnMgYWxzbyBob2xkIHRoZSBoZWxwZXIgaXRzZWxmLCBDb2RlU2NyaXB0IFRvb2xraXQgb25jZSB0aGVcbiAqIGJvb3RzdHJhcCBoYXMgaW5zdGFsbGVkIGl0LCBhbmQgYW55dGhpbmcgYSBkZW1vIG5vdGUncyBwcmVyZXF1aXNpdGVzIGluc3RhbGxlZCwgc28gY291bnRpbmcgdGhlbVxuICogZ3Vlc3NlcyAoYW5kIGd1ZXNzZXMgZGlmZmVyZW50bHkgb24gYSByZS1vcGVuKS4gVGhlIHBhY2thZ2luZyBzdGVwLCBvbiB0aGUgb3RoZXIgaGFuZCwgS05PV1MgXHUyMDE0IGl0XG4gKiByZWFkcyB0aGUgcGx1Z2luJ3MgYG1hbmlmZXN0Lmpzb25gIHRvIG5hbWUgdGhlIGFyY2hpdmUgXHUyMDE0IHNvIGl0IHdyaXRlcyB0aGUgaWQgZG93biBoZXJlIGFuZCB0aGVcbiAqIGJvb3RzdHJhcCBzaW1wbHkgcmVhZHMgaXQuXG4gKlxuICogVGhlIG1hcmtlciBhbmQgdGhlIGhlbHBlciBiaW5hcnkgYXJlIHdyaXR0ZW4gdG9nZXRoZXIsIGJ5IHRoZSBzYW1lIGBvYnNpZGlhbi1kZXYtdXRpbHNgIHZlcnNpb24sIGludG9cbiAqIHRoZSBzYW1lIGFyY2hpdmUsIHNvIHRoZSB0d28gY2FuIG5ldmVyIGRpc2FncmVlLlxuICpcbiAqIEtlcHQgZnJlZSBvZiBgb2JzaWRpYW5gIGltcG9ydHMgb24gcHVycG9zZTogdGhlIHBhY2thZ2luZyBzdGVwICh7QGxpbmsgYXJjaGl2ZVBsdWdpbkRlbW9WYXVsdH0pIHJ1bnNcbiAqIHVuZGVyIE5vZGUsIHdoZXJlIHRoZSBgb2JzaWRpYW5gIG1vZHVsZSBkb2VzIG5vdCBleGlzdC5cbiAqL1xuXG4vKipcbiAqIFRoZSBgZGVtby12YXVsdC1oZWxwZXJgIHBsdWdpbidzIGBkYXRhLmpzb25gLCB3cml0dGVuIGludG8gdGhlIGRlbW8gdmF1bHQgYXQgcGFja2FnaW5nIHRpbWUuXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgRGVtb1ZhdWx0SGVscGVyU2V0dGluZ3Mge1xuICAvKipcbiAgICogVGhlIGlkIG9mIHRoZSBwbHVnaW4gdGhlIHZhdWx0IGRlbW9uc3RyYXRlcywgdGFrZW4gZnJvbSB0aGF0IHBsdWdpbidzIGBtYW5pZmVzdC5qc29uYC5cbiAgICovXG4gIHJlYWRvbmx5IGRlbW9lZFBsdWdpbklkOiBzdHJpbmc7XG59XG4iXSwKICAibWFwcGluZ3MiOiAiOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7QUFBQTtBQUFBOyIsCiAgIm5hbWVzIjogW10KfQo=
@@ -0,0 +1,29 @@
1
+ /// <reference path="../library.d.cts" />
2
+ /**
3
+ * @file
4
+ *
5
+ * The `demo-vault-helper` plugin's own settings — the contract between the demo-vault packaging step
6
+ * and the bootstrap that runs inside the opened vault.
7
+ *
8
+ * The helper has to name the plugin the vault demonstrates, and nothing inside the vault reliably says
9
+ * which one that is: the plugin folders also hold the helper itself, CodeScript Toolkit once the
10
+ * bootstrap has installed it, and anything a demo note's prerequisites installed, so counting them
11
+ * guesses (and guesses differently on a re-open). The packaging step, on the other hand, KNOWS — it
12
+ * reads the plugin's `manifest.json` to name the archive — so it writes the id down here and the
13
+ * bootstrap simply reads it.
14
+ *
15
+ * The marker and the helper binary are written together, by the same `obsidian-dev-utils` version, into
16
+ * the same archive, so the two can never disagree.
17
+ *
18
+ * Kept free of `obsidian` imports on purpose: the packaging step ({@link archivePluginDemoVault}) runs
19
+ * under Node, where the `obsidian` module does not exist.
20
+ */
21
+ /**
22
+ * The `demo-vault-helper` plugin's `data.json`, written into the demo vault at packaging time.
23
+ */
24
+ export interface DemoVaultHelperSettings {
25
+ /**
26
+ * The id of the plugin the vault demonstrates, taken from that plugin's `manifest.json`.
27
+ */
28
+ readonly demoedPluginId: string;
29
+ }
@@ -126,7 +126,7 @@ __export(demo_vault_helper_exports, {
126
126
  module.exports = __toCommonJS(demo_vault_helper_exports);
127
127
  var import_obsidian = require('obsidian');
128
128
  var import_path = require('../path.cjs');
129
- var import_type_guards = require('../type-guards.cjs');
129
+ var import_string = require('../string.cjs');
130
130
  var import_community_plugins = require('./community-plugins.cjs');
131
131
  const CODE_SCRIPT_TOOLKIT_PLUGIN_ID = "fix-require-modules";
132
132
  const CODE_SCRIPT_TOOLKIT_MODULES_ROOT = "_assets/CodeScriptToolkit";
@@ -139,6 +139,8 @@ const CODE_SCRIPT_TOOLKIT_SETTINGS = {
139
139
  };
140
140
  const DEMO_VAULT_HELPER_PLUGIN_ID = "demo-vault-helper";
141
141
  const PLUGINS_FOLDER_NAME = "plugins";
142
+ const DATA_JSON_FILE_NAME = "data.json";
143
+ const INVALID_DEMO_VAULT_ERROR_MESSAGE = "Invalid demo vault";
142
144
  const OPEN_DEMO_VAULT_COMMAND_NAME = "Open demo vault";
143
145
  const SANDBOX_NOTICE_DURATION_IN_MILLISECONDS = 0;
144
146
  async function bootstrapDemoVault(params) {
@@ -159,23 +161,17 @@ async function bootstrapDemoVault(params) {
159
161
  }
160
162
  showSandboxNotice(app, demoedPluginId);
161
163
  }
162
- function buildSandboxNoticeFragment(pluginName, basePath) {
164
+ function buildSandboxNoticeFragment(pluginName) {
163
165
  return createFragment((fragment) => {
164
- if (pluginName === null) {
165
- fragment.appendText("This is a demo vault.");
166
- } else {
167
- fragment.appendText("This is a demo vault for ");
168
- fragment.createEl("b", { text: pluginName });
169
- fragment.appendText(".");
170
- }
171
- fragment.appendText(" It is a temporary sandbox");
172
- if (basePath !== null) {
173
- fragment.appendText(" at ");
174
- fragment.createEl("code", { text: basePath });
175
- }
176
- fragment.appendText(", cleaned up automatically about a day after you last use it \u2014 copy anything you want to keep into your own vault. Running ");
177
- fragment.createEl("b", { text: pluginName === null ? OPEN_DEMO_VAULT_COMMAND_NAME : `${pluginName}: ${OPEN_DEMO_VAULT_COMMAND_NAME}` });
178
- fragment.appendText(" again creates a new copy with the latest plugin version, so your notes will not appear in it.");
166
+ fragment.appendText("This is a demo vault for ");
167
+ fragment.createEl("b", { text: pluginName });
168
+ fragment.appendText(".");
169
+ fragment.createEl("br");
170
+ fragment.appendText("It is a temporary sandbox, cleaned up automatically about a day after you last use it.");
171
+ fragment.createEl("br");
172
+ fragment.appendText("Executing ");
173
+ fragment.createEl("b", { text: `${pluginName}: ${OPEN_DEMO_VAULT_COMMAND_NAME}` });
174
+ fragment.appendText(" command again creates a new copy with the latest plugin version, so your notes will not appear in it.");
179
175
  });
180
176
  }
181
177
  async function ensureInvocableScriptsFolder(app) {
@@ -185,27 +181,30 @@ async function ensureInvocableScriptsFolder(app) {
185
181
  }
186
182
  }
187
183
  async function getDemoedPluginId(app) {
188
- const pluginsFolderPath = (0, import_path.join)(app.vault.configDir, PLUGINS_FOLDER_NAME);
189
- if (!await app.vault.adapter.exists(pluginsFolderPath)) {
190
- return null;
184
+ const settingsPath = (0, import_path.join)(app.vault.configDir, PLUGINS_FOLDER_NAME, DEMO_VAULT_HELPER_PLUGIN_ID, DATA_JSON_FILE_NAME);
185
+ if (!await app.vault.adapter.exists(settingsPath)) {
186
+ throw new Error(INVALID_DEMO_VAULT_ERROR_MESSAGE);
191
187
  }
192
- const listedFiles = await app.vault.adapter.list(pluginsFolderPath);
193
- const demoedPluginIds = listedFiles.folders.map((folderPath) => (0, import_path.basename)(folderPath)).filter((pluginId) => pluginId !== DEMO_VAULT_HELPER_PLUGIN_ID);
194
- return demoedPluginIds.length === 1 ? (0, import_type_guards.ensureNonNullable)(demoedPluginIds[0]) : null;
195
- }
196
- function getVaultBasePath(app) {
197
- return isBasePathAdapter(app.vault.adapter) ? app.vault.adapter.getBasePath() : null;
198
- }
199
- function isBasePathAdapter(adapter) {
200
- return typeof Reflect.get(adapter, "getBasePath") === "function";
188
+ let parsed;
189
+ try {
190
+ parsed = JSON.parse(await app.vault.adapter.read(settingsPath));
191
+ } catch (error) {
192
+ throw new Error(INVALID_DEMO_VAULT_ERROR_MESSAGE, { cause: error });
193
+ }
194
+ const demoedPluginId = parsed?.demoedPluginId;
195
+ if (typeof demoedPluginId !== "string" || demoedPluginId === import_string.EMPTY) {
196
+ throw new Error(INVALID_DEMO_VAULT_ERROR_MESSAGE);
197
+ }
198
+ return demoedPluginId;
201
199
  }
202
200
  function showSandboxNotice(app, demoedPluginId) {
203
- const pluginName = demoedPluginId === null ? null : app.plugins.manifests[demoedPluginId]?.name ?? demoedPluginId;
204
- const fragment = buildSandboxNoticeFragment(pluginName, getVaultBasePath(app));
201
+ const pluginName = app.plugins.manifests[demoedPluginId]?.name ?? demoedPluginId;
202
+ const fragment = buildSandboxNoticeFragment(pluginName);
203
+ app.setting.close();
205
204
  new import_obsidian.Notice(fragment, SANDBOX_NOTICE_DURATION_IN_MILLISECONDS);
206
205
  }
207
206
  // Annotate the CommonJS export names for ESM import in node:
208
207
  0 && (module.exports = {
209
208
  bootstrapDemoVault
210
209
  });
211
- //# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsiLi4vLi4vLi4vLi4vc3JjL29ic2lkaWFuL2RlbW8tdmF1bHQtaGVscGVyLnRzIl0sCiAgInNvdXJjZXNDb250ZW50IjogWyIvKipcbiAqIEBmaWxlXG4gKlxuICogQm9vdHN0cmFwcyBhIGRlbW8gdmF1bHQgYnkgaW5zdGFsbGluZywgY29uZmlndXJpbmcsIGFuZCBlbmFibGluZyBDb2RlU2NyaXB0IFRvb2xraXQuXG4gKlxuICogQSBwbHVnaW4ncyBkZW1vIHZhdWx0IHNob3djYXNlcyB0aGUgcGx1Z2luIHRocm91Z2ggbm90ZXMgd2hvc2UgYGNvZGUtYnV0dG9uYHMgcnVuIFR5cGVTY3JpcHQgdmlhXG4gKiBDb2RlU2NyaXB0IFRvb2xraXQuIEEgZGVtbyB2YXVsdCB0aGF0IGRvZXMgbm90IGl0c2VsZiBzaGlwIENvZGVTY3JpcHQgVG9vbGtpdCB0aGVyZWZvcmUgbmVlZHMgaXRcbiAqIGluc3RhbGxlZCwgY29uZmlndXJlZCwgYW5kIGVuYWJsZWQgYmVmb3JlIHRob3NlIGJ1dHRvbnMgd29yay4ge0BsaW5rIGJvb3RzdHJhcERlbW9WYXVsdH0gZG9lcyBleGFjdGx5XG4gKiB0aGF0IHdpdGggbm8gY29tbWl0dGVkIENvZGVTY3JpcHQgVG9vbGtpdCBjb25maWcgYW5kIG5vIG1hbnVhbCBzZXR1cCwgc28gaXQgY2FuIGJlIGRyaXZlbiBmcm9tIGEgdGlueVxuICogY29tbWl0dGVkIGJvb3RzdHJhcCBwbHVnaW4gKGBkZW1vLXZhdWx0LWhlbHBlcmApIHRoYXQgaXMgaW5qZWN0ZWQgaW50byBldmVyeSBkZW1vIHZhdWx0IGF0IHJlbGVhc2VcbiAqIHRpbWUuXG4gKlxuICogSXQgd3JpdGVzIENvZGVTY3JpcHQgVG9vbGtpdCdzIHNldHRpbmdzIEJFRk9SRSBlbmFibGluZyBpdCwgc28gdGhlIHBsdWdpbiBsb2FkcyBhbHJlYWR5IGNvbmZpZ3VyZWQgXHUyMDE0XG4gKiBubyByZWxvYWQuIENvZGVTY3JpcHQgVG9vbGtpdCB0aGVuIHJ1bnMgdGhlIHZhdWx0J3MgYHN0YXJ0dXAudHNgICh2aWEgaXRzIGBzdGFydHVwU2NyaXB0UGF0aGBcbiAqIHNldHRpbmcpLCB3aGljaCBpcyB3aGVyZSBlYWNoIHZhdWx0IG9wZW5zIGl0cyBzdGFydCBub3RlIGFuZCBkb2VzIGFueSBwbHVnaW4tc3BlY2lmaWMgc2V0dXAuXG4gKlxuICogSXQgYWxzbyBjcmVhdGVzIENvZGVTY3JpcHQgVG9vbGtpdCdzIGludm9jYWJsZS1zY3JpcHRzIGZvbGRlciBpZiBpdCBpcyBtaXNzaW5nLCBzbyBldmVyeSBkZW1vIHZhdWx0XG4gKiBoYXMgdGhlIHNhbWUgbGF5b3V0IGV2ZW4gd2hlbiB0aGUgdmF1bHQgc2hpcHMgbm8gaW52b2NhYmxlIHNjcmlwdHMgXHUyMDE0IHRoZSB2YXVsdHMgdGhlbXNlbHZlcyBjb21taXQgbm9cbiAqIGVtcHR5IGZvbGRlciBmb3IgaXQuXG4gKlxuICogRmluYWxseSBpdCByYWlzZXMgdGhlIHNhbmRib3ggbm90aWNlIGV4cGxhaW5pbmcgdGhhdCB0aGUgb3BlbmVkIHZhdWx0IGlzIGEgdGhyb3dhd2F5IGNvcHksIHNvIGEgdXNlclxuICogd2hvIHdyaXRlcyB0aGVpciBvd24gbm90ZXMgaW4gaXQgaXMgbmV2ZXIgc3VycHJpc2VkIGJ5IHRoZW0gYmVpbmcgYWJzZW50IGZyb20gdGhlIG5leHQgY29weS5cbiAqL1xuXG5pbXBvcnQgdHlwZSB7XG4gIEFwcCxcbiAgRGF0YUFkYXB0ZXJcbn0gZnJvbSAnb2JzaWRpYW4nO1xuXG5pbXBvcnQgeyBOb3RpY2UgfSBmcm9tICdvYnNpZGlhbic7XG5cbmltcG9ydCB7XG4gIGJhc2VuYW1lLFxuICBqb2luXG59IGZyb20gJy4uL3BhdGgudHMnO1xuaW1wb3J0IHsgZW5zdXJlTm9uTnVsbGFibGUgfSBmcm9tICcuLi90eXBlLWd1YXJkcy50cyc7XG5pbXBvcnQge1xuICBjb25maWd1cmVDb21tdW5pdHlQbHVnaW4sXG4gIENvbmZpZ3VyZUNvbW11bml0eVBsdWdpblJlc3VsdCxcbiAgZGlzYWJsZUNvbW11bml0eVBsdWdpbixcbiAgZW5hYmxlQ29tbXVuaXR5UGx1Z2luLFxuICBpbnN0YWxsQ29tbXVuaXR5UGx1Z2luXG59IGZyb20gJy4vY29tbXVuaXR5LXBsdWdpbnMudHMnO1xuXG4vKipcbiAqIFBhcmFtZXRlcnMgZm9yIHtAbGluayBib290c3RyYXBEZW1vVmF1bHR9LlxuICovXG5leHBvcnQgaW50ZXJmYWNlIEJvb3RzdHJhcERlbW9WYXVsdFBhcmFtcyB7XG4gIC8qKlxuICAgKiBUaGUgT2JzaWRpYW4gYXBwIGluc3RhbmNlLlxuICAgKi9cbiAgcmVhZG9ubHkgYXBwOiBBcHA7XG59XG5cbi8qKlxuICogVGhlIHNsaWNlIG9mIHRoZSBkZXNrdG9wIHZhdWx0IGFkYXB0ZXIgdGhhdCBrbm93cyB0aGUgdmF1bHQncyBhYnNvbHV0ZSBwYXRoLlxuICovXG5pbnRlcmZhY2UgQmFzZVBhdGhBZGFwdGVyIHtcbiAgLyoqXG4gICAqIFJldHVybnMgdGhlIGFic29sdXRlIHBhdGggb2YgdGhlIHZhdWx0IGZvbGRlci5cbiAgICovXG4gIGdldEJhc2VQYXRoKCk6IHN0cmluZztcbn1cblxuLyoqXG4gKiBDb2RlU2NyaXB0IFRvb2xraXQncyBzZXR0aW5ncywgd3JpdHRlbiBpbnRvIGl0cyBgZGF0YS5qc29uYCBiZWZvcmUgaXQgaXMgZW5hYmxlZC5cbiAqL1xuaW50ZXJmYWNlIENvZGVTY3JpcHRUb29sa2l0U2V0dGluZ3Mge1xuICAvKipcbiAgICogVGhlIFlBTUwgZnJvbnRtYXR0ZXIgbWVyZ2VkIGludG8gZXZlcnkgYGNvZGUtYnV0dG9uYCBibG9jaydzIG93biBjb25maWcsIHVzZWQgaGVyZSB0byB0dXJuIHRoZVxuICAgKiBzb3VyY2Ugdmlld2VyIG9uIGZvciBldmVyeSBidXR0b24gaW4gZXZlcnkgZGVtbyB2YXVsdCB3aXRob3V0IGVkaXRpbmcgYSBzaW5nbGUgbm90ZS5cbiAgICovXG4gIHJlYWRvbmx5IGRlZmF1bHRDb2RlQnV0dG9uQ29uZmlnOiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIFRoZSBmb2xkZXIgKHVuZGVyIHtAbGluayBDb2RlU2NyaXB0VG9vbGtpdFNldHRpbmdzLm1vZHVsZXNSb290fSkgaG9sZGluZyBpbnZvY2FibGUgc2NyaXB0cy5cbiAgICovXG4gIHJlYWRvbmx5IGludm9jYWJsZVNjcmlwdHNGb2xkZXI6IHN0cmluZztcblxuICAvKipcbiAgICogVGhlIHZhdWx0LXJlbGF0aXZlIGZvbGRlciB0aGF0IGByZXF1aXJlKCcvXHUyMDI2JylgIHJlc29sdmVzIG1vZHVsZSBwYXRocyBhZ2FpbnN0LlxuICAgKi9cbiAgcmVhZG9ubHkgbW9kdWxlc1Jvb3Q6IHN0cmluZztcblxuICAvKipcbiAgICogV2hldGhlciBDb2RlU2NyaXB0IFRvb2xraXQgaGFuZGxlcyBgb2JzaWRpYW46Ly9gIHByb3RvY29sIFVSTHMuXG4gICAqL1xuICByZWFkb25seSBzaG91bGRIYW5kbGVQcm90b2NvbFVybHM6IGJvb2xlYW47XG5cbiAgLyoqXG4gICAqIFRoZSBwYXRoICh1bmRlciB7QGxpbmsgQ29kZVNjcmlwdFRvb2xraXRTZXR0aW5ncy5tb2R1bGVzUm9vdH0pIG9mIHRoZSBzY3JpcHQgcnVuIG9uIGxvYWQuXG4gICAqL1xuICByZWFkb25seSBzdGFydHVwU2NyaXB0UGF0aDogc3RyaW5nO1xufVxuXG5jb25zdCBDT0RFX1NDUklQVF9UT09MS0lUX1BMVUdJTl9JRCA9ICdmaXgtcmVxdWlyZS1tb2R1bGVzJztcbmNvbnN0IENPREVfU0NSSVBUX1RPT0xLSVRfTU9EVUxFU19ST09UID0gJ19hc3NldHMvQ29kZVNjcmlwdFRvb2xraXQnO1xuY29uc3QgQ09ERV9TQ1JJUFRfVE9PTEtJVF9TRVRUSU5HUzogQ29kZVNjcmlwdFRvb2xraXRTZXR0aW5ncyA9IHtcbiAgZGVmYXVsdENvZGVCdXR0b25Db25maWc6ICctLS1cXG5zb3VyY2VWaXNpYmlsaXR5OiBjb2xsYXBzZWRcXG4tLS0nLFxuICBpbnZvY2FibGVTY3JpcHRzRm9sZGVyOiAnSW52b2NhYmxlcycsXG4gIG1vZHVsZXNSb290OiBDT0RFX1NDUklQVF9UT09MS0lUX01PRFVMRVNfUk9PVCxcbiAgc2hvdWxkSGFuZGxlUHJvdG9jb2xVcmxzOiB0cnVlLFxuICBzdGFydHVwU2NyaXB0UGF0aDogJ3N0YXJ0dXAudHMnXG59O1xuXG5jb25zdCBERU1PX1ZBVUxUX0hFTFBFUl9QTFVHSU5fSUQgPSAnZGVtby12YXVsdC1oZWxwZXInO1xuY29uc3QgUExVR0lOU19GT0xERVJfTkFNRSA9ICdwbHVnaW5zJztcbmNvbnN0IE9QRU5fREVNT19WQVVMVF9DT01NQU5EX05BTUUgPSAnT3BlbiBkZW1vIHZhdWx0Jztcbi8vIGAwYCBhc2tzIE9ic2lkaWFuIHRvIGtlZXAgdGhlIG5vdGljZSB1cCB1bnRpbCB0aGUgdXNlciBjbGlja3MgaXQgXHUyMDE0IHRoZSBzYW1lIHRyZWF0bWVudCBPYnNpZGlhbiBnaXZlc1xuLy8gSXRzIG93biBzYW5kYm94LXZhdWx0IG5vdGljZSwgYW5kIHdoYXQgdGhlIGRlbW8tdmF1bHQgbm90aWNlIGlzIG1vZGVsbGVkIG9uLlxuY29uc3QgU0FOREJPWF9OT1RJQ0VfRFVSQVRJT05fSU5fTUlMTElTRUNPTkRTID0gMDtcblxuLyoqXG4gKiBCb290c3RyYXBzIGEgZGVtbyB2YXVsdCBzbyBpdHMgbm90ZXMnIGBjb2RlLWJ1dHRvbmBzIHdvcmsgd2l0aCBubyBtYW51YWwgc2V0dXA6IGluc3RhbGxzIENvZGVTY3JpcHRcbiAqIFRvb2xraXQgZnJvbSB0aGUgY29tbXVuaXR5IHN0b3JlIChpZiBpdCBpcyBub3QgYWxyZWFkeSBpbnN0YWxsZWQpLCB3cml0ZXMgaXRzIHNldHRpbmdzLCB0aGVuIGVuYWJsZXNcbiAqIGl0IFx1MjAxNCB3cml0aW5nIHRoZSBzZXR0aW5ncyBCRUZPUkUgZW5hYmxpbmcgc28gYSBmcmVzaCBlbmFibGUgbG9hZHMgaXQgYWxyZWFkeSBjb25maWd1cmVkLCB3aXRoIG5vXG4gKiByZWxvYWQuIElmIENvZGVTY3JpcHQgVG9vbGtpdCBpcyBhbHJlYWR5IGVuYWJsZWQgYnV0IHRoZSBzZXR0aW5ncyBqdXN0IGNoYW5nZWQsIGl0IGlzIHJlbG9hZGVkXG4gKiAoZGlzYWJsZWQgdGhlbiBlbmFibGVkKSBzbyBpdCByZS1yZWFkcyBgZGF0YS5qc29uYDsgd2hlbiB0aGUgc2V0dGluZ3Mgd2VyZSBhbHJlYWR5IGluIHBsYWNlLCBub3RoaW5nIGlzXG4gKiByZWxvYWRlZCAoc28gYSByb3V0aW5lIHZhdWx0IHJlLW9wZW4gZG9lcyBub3QgcmUtcnVuIENvZGVTY3JpcHQgVG9vbGtpdCdzIHN0YXJ0dXApLiBDb2RlU2NyaXB0IFRvb2xraXRcbiAqIHRoZW4gcnVucyB0aGUgdmF1bHQncyBgc3RhcnR1cC50c2AuIEZpbmFsbHkgaXQgcmFpc2VzIHRoZSBzYW5kYm94IG5vdGljZSBkZXNjcmliaW5nIHRoZSBvcGVuZWQgdmF1bHRcbiAqIGFzIGEgdGhyb3dhd2F5IGNvcHkuXG4gKlxuICogQHBhcmFtIHBhcmFtcyAtIFRoZSB7QGxpbmsgQm9vdHN0cmFwRGVtb1ZhdWx0UGFyYW1zfS5cbiAqIEByZXR1cm5zIEEge0BsaW5rIFByb21pc2V9IHRoYXQgcmVzb2x2ZXMgb25jZSBDb2RlU2NyaXB0IFRvb2xraXQgaXMgaW5zdGFsbGVkLCBjb25maWd1cmVkLCBhbmQgZW5hYmxlZFxuICogYW5kIHRoZSBzYW5kYm94IG5vdGljZSBoYXMgYmVlbiBzaG93bi5cbiAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGJvb3RzdHJhcERlbW9WYXVsdChwYXJhbXM6IEJvb3RzdHJhcERlbW9WYXVsdFBhcmFtcyk6IFByb21pc2U8dm9pZD4ge1xuICBjb25zdCB7IGFwcCB9ID0gcGFyYW1zO1xuICAvLyBSZXNvbHZlZCBCRUZPUkUgQ29kZVNjcmlwdCBUb29sa2l0IGlzIGluc3RhbGxlZC4gQXQgcmVsZWFzZSB0aW1lIHRoZSB2YXVsdCBjYXJyaWVzIGV4YWN0bHkgdHdvXG4gIC8vIFBsdWdpbiBmb2xkZXJzIFx1MjAxNCB0aGlzIGhlbHBlciBhbmQgdGhlIHBsdWdpbiBiZWluZyBkZW1vbnN0cmF0ZWQgXHUyMDE0IHNvIGRyb3BwaW5nIHRoZSBoZWxwZXIgbGVhdmVzIHRoZVxuICAvLyBEZW1vbnN0cmF0ZWQgb25lLiBSZWFkaW5nIHRoZSBmb2xkZXIgbGF0ZXIgd291bGQgYWxzbyBzZWUgQ29kZVNjcmlwdCBUb29sa2l0IGFuZCBhbnl0aGluZyBhIGRlbW9cbiAgLy8gTm90ZSdzIHByZXJlcXVpc2l0ZXMgaW5zdGFsbGVkLCBsZWF2aW5nIG5vIHdheSB0byB0ZWxsIHdoaWNoIHBsdWdpbiB0aGUgdmF1bHQgaXMgZm9yLlxuICBjb25zdCBkZW1vZWRQbHVnaW5JZCA9IGF3YWl0IGdldERlbW9lZFBsdWdpbklkKGFwcCk7XG4gIGF3YWl0IGluc3RhbGxDb21tdW5pdHlQbHVnaW4oeyBhcHAsIHBsdWdpbklkOiBDT0RFX1NDUklQVF9UT09MS0lUX1BMVUdJTl9JRCB9KTtcbiAgY29uc3QgcmVzdWx0ID0gYXdhaXQgY29uZmlndXJlQ29tbXVuaXR5UGx1Z2luKHtcbiAgICBhcHAsXG4gICAgcGx1Z2luSWQ6IENPREVfU0NSSVBUX1RPT0xLSVRfUExVR0lOX0lELFxuICAgIHNldHRpbmdzOiBDT0RFX1NDUklQVF9UT09MS0lUX1NFVFRJTkdTXG4gIH0pO1xuICBhd2FpdCBlbnN1cmVJbnZvY2FibGVTY3JpcHRzRm9sZGVyKGFwcCk7XG5cbiAgaWYgKCFhcHAucGx1Z2lucy5lbmFibGVkUGx1Z2lucy5oYXMoQ09ERV9TQ1JJUFRfVE9PTEtJVF9QTFVHSU5fSUQpKSB7XG4gICAgYXdhaXQgZW5hYmxlQ29tbXVuaXR5UGx1Z2luKHsgYXBwLCBwbHVnaW5JZDogQ09ERV9TQ1JJUFRfVE9PTEtJVF9QTFVHSU5fSUQgfSk7XG4gIH0gZWxzZSBpZiAocmVzdWx0ID09PSBDb25maWd1cmVDb21tdW5pdHlQbHVnaW5SZXN1bHQuU3VjY2Vzcykge1xuICAgIC8vIEFscmVhZHkgZW5hYmxlZCB3aXRoIHN0YWxlIHNldHRpbmdzIFx1MjAxNCByZWxvYWQgc28gQ29kZVNjcmlwdCBUb29sa2l0IHJlLXJlYWRzIHRoZSBmcmVzaGx5IHdyaXR0ZW4gZGF0YS5qc29uLlxuICAgIGF3YWl0IGRpc2FibGVDb21tdW5pdHlQbHVnaW4oeyBhcHAsIHBsdWdpbklkOiBDT0RFX1NDUklQVF9UT09MS0lUX1BMVUdJTl9JRCB9KTtcbiAgICBhd2FpdCBlbmFibGVDb21tdW5pdHlQbHVnaW4oeyBhcHAsIHBsdWdpbklkOiBDT0RFX1NDUklQVF9UT09MS0lUX1BMVUdJTl9JRCB9KTtcbiAgfVxuXG4gIHNob3dTYW5kYm94Tm90aWNlKGFwcCwgZGVtb2VkUGx1Z2luSWQpO1xufVxuXG4vLyBCdWlsZHMgdGhlIHNhbmRib3ggbm90aWNlIGNvbnRlbnQ6IHdoYXQgdGhpcyB2YXVsdCBpcywgd2hlcmUgaXQgbGl2ZXMsIGhvdyBsb25nIGl0IGxpdmVzLCBhbmQgd2h5XG4vLyBSZS1ydW5uaW5nIHRoZSBjb21tYW5kIHByb2R1Y2VzIGEgdmF1bHQgd2l0aG91dCB0aGUgbm90ZXMganVzdCB3cml0dGVuIGhlcmUuXG4vL1xuLy8gRXZlcnkgY2xhaW0gaGFzIHRvIHN0YXkgdHJ1ZSBvZiB0aGUgb3BlbmVyIChgZGVza3RvcC1kZW1vLXZhdWx0LW9wZW5lci50c2ApOiBpdCBleHRyYWN0cyBhIEZSRVNIIGNvcHlcbi8vIEludG8gaXRzIG93biBmb2xkZXIgb24gZXZlcnkgb3BlbiwgYW5kIGRlbGV0ZXMgZXh0cmFjdGVkIGZvbGRlcnMgb2xkZXIgdGhhbiBhIGRheSBvbiBlYWNoIGxhdGVyIG9wZW4uXG4vLyBTbyB0aGUgdmF1bHQgaXMgYSB0ZW1wb3Jhcnkgc2FuZGJveCBcdTIwMTQgaXQgbXVzdCBuZXZlciBiZSBkZXNjcmliZWQgYXMgYSBwbGFjZSB3b3JrIGNhbiBiZSBsZWZ0LlxuZnVuY3Rpb24gYnVpbGRTYW5kYm94Tm90aWNlRnJhZ21lbnQocGx1Z2luTmFtZTogbnVsbCB8IHN0cmluZywgYmFzZVBhdGg6IG51bGwgfCBzdHJpbmcpOiBEb2N1bWVudEZyYWdtZW50IHtcbiAgcmV0dXJuIGNyZWF0ZUZyYWdtZW50KChmcmFnbWVudCkgPT4ge1xuICAgIGlmIChwbHVnaW5OYW1lID09PSBudWxsKSB7XG4gICAgICBmcmFnbWVudC5hcHBlbmRUZXh0KCdUaGlzIGlzIGEgZGVtbyB2YXVsdC4nKTtcbiAgICB9IGVsc2Uge1xuICAgICAgZnJhZ21lbnQuYXBwZW5kVGV4dCgnVGhpcyBpcyBhIGRlbW8gdmF1bHQgZm9yICcpO1xuICAgICAgZnJhZ21lbnQuY3JlYXRlRWwoJ2InLCB7IHRleHQ6IHBsdWdpbk5hbWUgfSk7XG4gICAgICBmcmFnbWVudC5hcHBlbmRUZXh0KCcuJyk7XG4gICAgfVxuXG4gICAgZnJhZ21lbnQuYXBwZW5kVGV4dCgnIEl0IGlzIGEgdGVtcG9yYXJ5IHNhbmRib3gnKTtcbiAgICBpZiAoYmFzZVBhdGggIT09IG51bGwpIHtcbiAgICAgIGZyYWdtZW50LmFwcGVuZFRleHQoJyBhdCAnKTtcbiAgICAgIGZyYWdtZW50LmNyZWF0ZUVsKCdjb2RlJywgeyB0ZXh0OiBiYXNlUGF0aCB9KTtcbiAgICB9XG4gICAgZnJhZ21lbnQuYXBwZW5kVGV4dCgnLCBjbGVhbmVkIHVwIGF1dG9tYXRpY2FsbHkgYWJvdXQgYSBkYXkgYWZ0ZXIgeW91IGxhc3QgdXNlIGl0IFx1MjAxNCBjb3B5IGFueXRoaW5nIHlvdSB3YW50IHRvIGtlZXAgaW50byB5b3VyIG93biB2YXVsdC4gUnVubmluZyAnKTtcbiAgICBmcmFnbWVudC5jcmVhdGVFbCgnYicsIHsgdGV4dDogcGx1Z2luTmFtZSA9PT0gbnVsbCA/IE9QRU5fREVNT19WQVVMVF9DT01NQU5EX05BTUUgOiBgJHtwbHVnaW5OYW1lfTogJHtPUEVOX0RFTU9fVkFVTFRfQ09NTUFORF9OQU1FfWAgfSk7XG4gICAgZnJhZ21lbnQuYXBwZW5kVGV4dCgnIGFnYWluIGNyZWF0ZXMgYSBuZXcgY29weSB3aXRoIHRoZSBsYXRlc3QgcGx1Z2luIHZlcnNpb24sIHNvIHlvdXIgbm90ZXMgd2lsbCBub3QgYXBwZWFyIGluIGl0LicpO1xuICB9KTtcbn1cblxuLy8gQ3JlYXRlcyBDb2RlU2NyaXB0IFRvb2xraXQncyBpbnZvY2FibGUtc2NyaXB0cyBmb2xkZXIgKHVuZGVyIGBtb2R1bGVzUm9vdGApIGlmIGl0IGlzIG1pc3NpbmcuXG4vLyBFdmVyeSBkZW1vIHZhdWx0IHRoZW4gaGFzIHRoZSBzYW1lIENvZGVTY3JpcHQgVG9vbGtpdCBsYXlvdXQgZXZlbiB3aGVuIGl0IHNoaXBzIG5vIGludm9jYWJsZSBzY3JpcHRzLlxuLy8gVGhlIGNvbW1pdHRlZCB2YXVsdCB0aGVyZWZvcmUgY2FycmllcyBubyBvdGhlcndpc2UtZW1wdHkgcGxhY2Vob2xkZXIgZm9sZGVyLlxuYXN5bmMgZnVuY3Rpb24gZW5zdXJlSW52b2NhYmxlU2NyaXB0c0ZvbGRlcihhcHA6IEFwcCk6IFByb21pc2U8dm9pZD4ge1xuICBjb25zdCBpbnZvY2FibGVTY3JpcHRzRm9sZGVyUGF0aCA9IGpvaW4oQ09ERV9TQ1JJUFRfVE9PTEtJVF9NT0RVTEVTX1JPT1QsIENPREVfU0NSSVBUX1RPT0xLSVRfU0VUVElOR1MuaW52b2NhYmxlU2NyaXB0c0ZvbGRlcik7XG4gIGlmICghYXdhaXQgYXBwLnZhdWx0LmFkYXB0ZXIuZXhpc3RzKGludm9jYWJsZVNjcmlwdHNGb2xkZXJQYXRoKSkge1xuICAgIGF3YWl0IGFwcC52YXVsdC5hZGFwdGVyLm1rZGlyKGludm9jYWJsZVNjcmlwdHNGb2xkZXJQYXRoKTtcbiAgfVxufVxuXG4vLyBJZGVudGlmaWVzIHRoZSBwbHVnaW4gdGhlIHZhdWx0IGRlbW9uc3RyYXRlcyBhcyB0aGUgb25seSBpbnN0YWxsZWQgcGx1Z2luIHRoYXQgaXMgbm90IHRoaXMgaGVscGVyLlxuLy8gQ2FsbCBpdCBCRUZPUkUgYW55dGhpbmcgZWxzZSBpcyBpbnN0YWxsZWQgKHNlZSBgYm9vdHN0cmFwRGVtb1ZhdWx0YCkuIEFueSBvdGhlciBjb3VudCBcdTIwMTQgYSB2YXVsdFxuLy8gT3BlbmVkIGFmdGVyIHRoZSBwbHVnaW4gZm9sZGVyIHdhcyBoYW5kLWVkaXRlZCwgb3Igb25lIHRoYXQgc2hpcHMgbm90aGluZyBidXQgdGhlIGhlbHBlciBcdTIwMTQgaXNcbi8vIEFtYmlndW91cywgYW5kIGFuIGFtYmlndW91cyBhbnN3ZXIgYmVjb21lcyBnZW5lcmljIG5vdGljZSB3b3JkaW5nIHJhdGhlciB0aGFuIGEgd3JvbmcgcGx1Z2luIG5hbWUuXG5hc3luYyBmdW5jdGlvbiBnZXREZW1vZWRQbHVnaW5JZChhcHA6IEFwcCk6IFByb21pc2U8bnVsbCB8IHN0cmluZz4ge1xuICBjb25zdCBwbHVnaW5zRm9sZGVyUGF0aCA9IGpvaW4oYXBwLnZhdWx0LmNvbmZpZ0RpciwgUExVR0lOU19GT0xERVJfTkFNRSk7XG4gIGlmICghYXdhaXQgYXBwLnZhdWx0LmFkYXB0ZXIuZXhpc3RzKHBsdWdpbnNGb2xkZXJQYXRoKSkge1xuICAgIHJldHVybiBudWxsO1xuICB9XG5cbiAgY29uc3QgbGlzdGVkRmlsZXMgPSBhd2FpdCBhcHAudmF1bHQuYWRhcHRlci5saXN0KHBsdWdpbnNGb2xkZXJQYXRoKTtcbiAgY29uc3QgZGVtb2VkUGx1Z2luSWRzID0gbGlzdGVkRmlsZXMuZm9sZGVyc1xuICAgIC5tYXAoKGZvbGRlclBhdGgpID0+IGJhc2VuYW1lKGZvbGRlclBhdGgpKVxuICAgIC5maWx0ZXIoKHBsdWdpbklkKSA9PiBwbHVnaW5JZCAhPT0gREVNT19WQVVMVF9IRUxQRVJfUExVR0lOX0lEKTtcbiAgcmV0dXJuIGRlbW9lZFBsdWdpbklkcy5sZW5ndGggPT09IDEgPyBlbnN1cmVOb25OdWxsYWJsZShkZW1vZWRQbHVnaW5JZHNbMF0pIDogbnVsbDtcbn1cblxuLy8gUmVzb2x2ZXMgdGhlIHZhdWx0J3MgYWJzb2x1dGUgcGF0aCBmb3IgdGhlIG5vdGljZS4gT25seSB0aGUgZGVza3RvcCBhZGFwdGVyIGtub3dzIGl0OiBgRGF0YUFkYXB0ZXJgXG4vLyBEb2VzIG5vdCBkZWNsYXJlIGBnZXRCYXNlUGF0aGAsIGFuZCBgRmlsZVN5c3RlbUFkYXB0ZXJgIGlzIGEgZGVza3RvcC1vbmx5IGNsYXNzIHRoYXQgaXMgbm90IGd1YXJhbnRlZWRcbi8vIFRvIGV4aXN0IGVsc2V3aGVyZSBcdTIwMTQgc28gYGluc3RhbmNlb2ZgIHdvdWxkIHRocm93IHJhdGhlciB0aGFuIGFuc3dlci4gSXQgaXMgcmVhY2hlZCBpbnN0ZWFkIHRocm91Z2ggYVxuLy8gTmFycm93IGhhbmQtZGVjbGFyZWQgc2hhcGUgcGx1cyBhIHJ1bnRpbWUgY2hlY2sgKHNlZSBMOSkuIEFuIGFkYXB0ZXIgd2l0aG91dCBpdCB5aWVsZHMgbm8gcGF0aCwgYW5kXG4vLyBUaGUgbm90aWNlIHRoZW4gb21pdHMgdGhlIHNlbnRlbmNlIG5hbWluZyBpdCByYXRoZXIgdGhhbiByZW5kZXJpbmcgYHVuZGVmaW5lZGAuXG5mdW5jdGlvbiBnZXRWYXVsdEJhc2VQYXRoKGFwcDogQXBwKTogbnVsbCB8IHN0cmluZyB7XG4gIHJldHVybiBpc0Jhc2VQYXRoQWRhcHRlcihhcHAudmF1bHQuYWRhcHRlcikgPyBhcHAudmF1bHQuYWRhcHRlci5nZXRCYXNlUGF0aCgpIDogbnVsbDtcbn1cblxuZnVuY3Rpb24gaXNCYXNlUGF0aEFkYXB0ZXIoYWRhcHRlcjogRGF0YUFkYXB0ZXIpOiBhZGFwdGVyIGlzIEJhc2VQYXRoQWRhcHRlciAmIERhdGFBZGFwdGVyIHtcbiAgcmV0dXJuIHR5cGVvZiBSZWZsZWN0LmdldChhZGFwdGVyLCAnZ2V0QmFzZVBhdGgnKSA9PT0gJ2Z1bmN0aW9uJztcbn1cblxuLy8gVGVsbHMgdGhlIHVzZXIgdGhpcyB2YXVsdCBpcyBhIHNhbmRib3gsIHVzaW5nIE9ic2lkaWFuJ3Mgb3duIHNhbmRib3gtdmF1bHQgdHJlYXRtZW50OiBhbiBpbmZpbml0ZVxuLy8gRHVyYXRpb24sIGRpc21pc3NlZCBieSBjbGlja2luZyBpdC4gUmFpc2VkIGxhc3QsIHNvIGl0IGlzIHRoZSBuZXdlc3Qgbm90aWNlIG9uIHNjcmVlbiBvbmNlXG4vLyBDb2RlU2NyaXB0IFRvb2xraXQncyBzdGFydHVwIHNjcmlwdCBoYXMgZG9uZSBpdHMgb3duIHdvcmsuXG5mdW5jdGlvbiBzaG93U2FuZGJveE5vdGljZShhcHA6IEFwcCwgZGVtb2VkUGx1Z2luSWQ6IG51bGwgfCBzdHJpbmcpOiB2b2lkIHtcbiAgY29uc3QgcGx1Z2luTmFtZSA9IGRlbW9lZFBsdWdpbklkID09PSBudWxsID8gbnVsbCA6IGFwcC5wbHVnaW5zLm1hbmlmZXN0c1tkZW1vZWRQbHVnaW5JZF0/Lm5hbWUgPz8gZGVtb2VkUGx1Z2luSWQ7XG4gIGNvbnN0IGZyYWdtZW50ID0gYnVpbGRTYW5kYm94Tm90aWNlRnJhZ21lbnQocGx1Z2luTmFtZSwgZ2V0VmF1bHRCYXNlUGF0aChhcHApKTtcbiAgbmV3IE5vdGljZShmcmFnbWVudCwgU0FOREJPWF9OT1RJQ0VfRFVSQVRJT05fSU5fTUlMTElTRUNPTkRTKTtcbn1cbiJdLAogICJtYXBwaW5ncyI6ICI7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBNkJBLHNCQUF1QjtBQUV2QixrQkFHTztBQUNQLHlCQUFrQztBQUNsQywrQkFNTztBQXFEUCxNQUFNLGdDQUFnQztBQUN0QyxNQUFNLG1DQUFtQztBQUN6QyxNQUFNLCtCQUEwRDtBQUFBLEVBQzlELHlCQUF5QjtBQUFBLEVBQ3pCLHdCQUF3QjtBQUFBLEVBQ3hCLGFBQWE7QUFBQSxFQUNiLDBCQUEwQjtBQUFBLEVBQzFCLG1CQUFtQjtBQUNyQjtBQUVBLE1BQU0sOEJBQThCO0FBQ3BDLE1BQU0sc0JBQXNCO0FBQzVCLE1BQU0sK0JBQStCO0FBR3JDLE1BQU0sMENBQTBDO0FBZ0JoRCxlQUFzQixtQkFBbUIsUUFBaUQ7QUFDeEYsUUFBTSxFQUFFLElBQUksSUFBSTtBQUtoQixRQUFNLGlCQUFpQixNQUFNLGtCQUFrQixHQUFHO0FBQ2xELFlBQU0saURBQXVCLEVBQUUsS0FBSyxVQUFVLDhCQUE4QixDQUFDO0FBQzdFLFFBQU0sU0FBUyxVQUFNLG1EQUF5QjtBQUFBLElBQzVDO0FBQUEsSUFDQSxVQUFVO0FBQUEsSUFDVixVQUFVO0FBQUEsRUFDWixDQUFDO0FBQ0QsUUFBTSw2QkFBNkIsR0FBRztBQUV0QyxNQUFJLENBQUMsSUFBSSxRQUFRLGVBQWUsSUFBSSw2QkFBNkIsR0FBRztBQUNsRSxjQUFNLGdEQUFzQixFQUFFLEtBQUssVUFBVSw4QkFBOEIsQ0FBQztBQUFBLEVBQzlFLFdBQVcsV0FBVyx3REFBK0IsU0FBUztBQUU1RCxjQUFNLGlEQUF1QixFQUFFLEtBQUssVUFBVSw4QkFBOEIsQ0FBQztBQUM3RSxjQUFNLGdEQUFzQixFQUFFLEtBQUssVUFBVSw4QkFBOEIsQ0FBQztBQUFBLEVBQzlFO0FBRUEsb0JBQWtCLEtBQUssY0FBYztBQUN2QztBQVFBLFNBQVMsMkJBQTJCLFlBQTJCLFVBQTJDO0FBQ3hHLFNBQU8sZUFBZSxDQUFDLGFBQWE7QUFDbEMsUUFBSSxlQUFlLE1BQU07QUFDdkIsZUFBUyxXQUFXLHVCQUF1QjtBQUFBLElBQzdDLE9BQU87QUFDTCxlQUFTLFdBQVcsMkJBQTJCO0FBQy9DLGVBQVMsU0FBUyxLQUFLLEVBQUUsTUFBTSxXQUFXLENBQUM7QUFDM0MsZUFBUyxXQUFXLEdBQUc7QUFBQSxJQUN6QjtBQUVBLGFBQVMsV0FBVyw0QkFBNEI7QUFDaEQsUUFBSSxhQUFhLE1BQU07QUFDckIsZUFBUyxXQUFXLE1BQU07QUFDMUIsZUFBUyxTQUFTLFFBQVEsRUFBRSxNQUFNLFNBQVMsQ0FBQztBQUFBLElBQzlDO0FBQ0EsYUFBUyxXQUFXLGtJQUE2SDtBQUNqSixhQUFTLFNBQVMsS0FBSyxFQUFFLE1BQU0sZUFBZSxPQUFPLCtCQUErQixHQUFHLFVBQVUsS0FBSyw0QkFBNEIsR0FBRyxDQUFDO0FBQ3RJLGFBQVMsV0FBVyxnR0FBZ0c7QUFBQSxFQUN0SCxDQUFDO0FBQ0g7QUFLQSxlQUFlLDZCQUE2QixLQUF5QjtBQUNuRSxRQUFNLGlDQUE2QixrQkFBSyxrQ0FBa0MsNkJBQTZCLHNCQUFzQjtBQUM3SCxNQUFJLENBQUMsTUFBTSxJQUFJLE1BQU0sUUFBUSxPQUFPLDBCQUEwQixHQUFHO0FBQy9ELFVBQU0sSUFBSSxNQUFNLFFBQVEsTUFBTSwwQkFBMEI7QUFBQSxFQUMxRDtBQUNGO0FBTUEsZUFBZSxrQkFBa0IsS0FBa0M7QUFDakUsUUFBTSx3QkFBb0Isa0JBQUssSUFBSSxNQUFNLFdBQVcsbUJBQW1CO0FBQ3ZFLE1BQUksQ0FBQyxNQUFNLElBQUksTUFBTSxRQUFRLE9BQU8saUJBQWlCLEdBQUc7QUFDdEQsV0FBTztBQUFBLEVBQ1Q7QUFFQSxRQUFNLGNBQWMsTUFBTSxJQUFJLE1BQU0sUUFBUSxLQUFLLGlCQUFpQjtBQUNsRSxRQUFNLGtCQUFrQixZQUFZLFFBQ2pDLElBQUksQ0FBQyxtQkFBZSxzQkFBUyxVQUFVLENBQUMsRUFDeEMsT0FBTyxDQUFDLGFBQWEsYUFBYSwyQkFBMkI7QUFDaEUsU0FBTyxnQkFBZ0IsV0FBVyxRQUFJLHNDQUFrQixnQkFBZ0IsQ0FBQyxDQUFDLElBQUk7QUFDaEY7QUFPQSxTQUFTLGlCQUFpQixLQUF5QjtBQUNqRCxTQUFPLGtCQUFrQixJQUFJLE1BQU0sT0FBTyxJQUFJLElBQUksTUFBTSxRQUFRLFlBQVksSUFBSTtBQUNsRjtBQUVBLFNBQVMsa0JBQWtCLFNBQWdFO0FBQ3pGLFNBQU8sT0FBTyxRQUFRLElBQUksU0FBUyxhQUFhLE1BQU07QUFDeEQ7QUFLQSxTQUFTLGtCQUFrQixLQUFVLGdCQUFxQztBQUN4RSxRQUFNLGFBQWEsbUJBQW1CLE9BQU8sT0FBTyxJQUFJLFFBQVEsVUFBVSxjQUFjLEdBQUcsUUFBUTtBQUNuRyxRQUFNLFdBQVcsMkJBQTJCLFlBQVksaUJBQWlCLEdBQUcsQ0FBQztBQUM3RSxNQUFJLHVCQUFPLFVBQVUsdUNBQXVDO0FBQzlEOyIsCiAgIm5hbWVzIjogW10KfQo=
210
+ //# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsiLi4vLi4vLi4vLi4vc3JjL29ic2lkaWFuL2RlbW8tdmF1bHQtaGVscGVyLnRzIl0sCiAgInNvdXJjZXNDb250ZW50IjogWyIvKipcbiAqIEBmaWxlXG4gKlxuICogQm9vdHN0cmFwcyBhIGRlbW8gdmF1bHQgYnkgaW5zdGFsbGluZywgY29uZmlndXJpbmcsIGFuZCBlbmFibGluZyBDb2RlU2NyaXB0IFRvb2xraXQuXG4gKlxuICogQSBwbHVnaW4ncyBkZW1vIHZhdWx0IHNob3djYXNlcyB0aGUgcGx1Z2luIHRocm91Z2ggbm90ZXMgd2hvc2UgYGNvZGUtYnV0dG9uYHMgcnVuIFR5cGVTY3JpcHQgdmlhXG4gKiBDb2RlU2NyaXB0IFRvb2xraXQuIEEgZGVtbyB2YXVsdCB0aGF0IGRvZXMgbm90IGl0c2VsZiBzaGlwIENvZGVTY3JpcHQgVG9vbGtpdCB0aGVyZWZvcmUgbmVlZHMgaXRcbiAqIGluc3RhbGxlZCwgY29uZmlndXJlZCwgYW5kIGVuYWJsZWQgYmVmb3JlIHRob3NlIGJ1dHRvbnMgd29yay4ge0BsaW5rIGJvb3RzdHJhcERlbW9WYXVsdH0gZG9lcyBleGFjdGx5XG4gKiB0aGF0IHdpdGggbm8gY29tbWl0dGVkIENvZGVTY3JpcHQgVG9vbGtpdCBjb25maWcgYW5kIG5vIG1hbnVhbCBzZXR1cCwgc28gaXQgY2FuIGJlIGRyaXZlbiBmcm9tIGEgdGlueVxuICogY29tbWl0dGVkIGJvb3RzdHJhcCBwbHVnaW4gKGBkZW1vLXZhdWx0LWhlbHBlcmApIHRoYXQgaXMgaW5qZWN0ZWQgaW50byBldmVyeSBkZW1vIHZhdWx0IGF0IHJlbGVhc2VcbiAqIHRpbWUuXG4gKlxuICogVGhlIHBsdWdpbiB0aGUgdmF1bHQgZGVtb25zdHJhdGVzIGlzIHJlYWQgZnJvbSB0aGUgaGVscGVyJ3Mgb3duIGBkYXRhLmpzb25gLCB3cml0dGVuIGJ5IHRoZSBwYWNrYWdpbmdcbiAqIHN0ZXAgKHtAbGluayBEZW1vVmF1bHRIZWxwZXJTZXR0aW5nc30pOyBhIHZhdWx0IHdpdGhvdXQgdGhhdCBtYXJrZXIgaXMgcmVmdXNlZCBhcyBub3QgYSBkZW1vIHZhdWx0LlxuICpcbiAqIEl0IHdyaXRlcyBDb2RlU2NyaXB0IFRvb2xraXQncyBzZXR0aW5ncyBCRUZPUkUgZW5hYmxpbmcgaXQsIHNvIHRoZSBwbHVnaW4gbG9hZHMgYWxyZWFkeSBjb25maWd1cmVkIFx1MjAxNFxuICogbm8gcmVsb2FkLiBDb2RlU2NyaXB0IFRvb2xraXQgdGhlbiBydW5zIHRoZSB2YXVsdCdzIGBzdGFydHVwLnRzYCAodmlhIGl0cyBgc3RhcnR1cFNjcmlwdFBhdGhgXG4gKiBzZXR0aW5nKSwgd2hpY2ggaXMgd2hlcmUgZWFjaCB2YXVsdCBvcGVucyBpdHMgc3RhcnQgbm90ZSBhbmQgZG9lcyBhbnkgcGx1Z2luLXNwZWNpZmljIHNldHVwLlxuICpcbiAqIEl0IGFsc28gY3JlYXRlcyBDb2RlU2NyaXB0IFRvb2xraXQncyBpbnZvY2FibGUtc2NyaXB0cyBmb2xkZXIgaWYgaXQgaXMgbWlzc2luZywgc28gZXZlcnkgZGVtbyB2YXVsdFxuICogaGFzIHRoZSBzYW1lIGxheW91dCBldmVuIHdoZW4gdGhlIHZhdWx0IHNoaXBzIG5vIGludm9jYWJsZSBzY3JpcHRzIFx1MjAxNCB0aGUgdmF1bHRzIHRoZW1zZWx2ZXMgY29tbWl0IG5vXG4gKiBlbXB0eSBmb2xkZXIgZm9yIGl0LlxuICpcbiAqIEZpbmFsbHkgaXQgcmFpc2VzIHRoZSBzYW5kYm94IG5vdGljZSBleHBsYWluaW5nIHRoYXQgdGhlIG9wZW5lZCB2YXVsdCBpcyBhIHRocm93YXdheSBjb3B5LCBzbyBhIHVzZXJcbiAqIHdobyB3cml0ZXMgdGhlaXIgb3duIG5vdGVzIGluIGl0IGlzIG5ldmVyIHN1cnByaXNlZCBieSB0aGVtIGJlaW5nIGFic2VudCBmcm9tIHRoZSBuZXh0IGNvcHkuIFNldHRpbmdzXG4gKiBpcyBjbG9zZWQgZmlyc3QsIHNvIHRoZSBub3RpY2UgbGFuZHMgaW4gdGhlIHZhdWx0J3MgbWFpbiB3aW5kb3cgcmF0aGVyIHRoYW4gaW4gdGhlIHNldHRpbmdzIHBvcG91dC5cbiAqL1xuXG5pbXBvcnQgdHlwZSB7IEFwcCB9IGZyb20gJ29ic2lkaWFuJztcblxuaW1wb3J0IHsgTm90aWNlIH0gZnJvbSAnb2JzaWRpYW4nO1xuXG5pbXBvcnQgdHlwZSB7IERlbW9WYXVsdEhlbHBlclNldHRpbmdzIH0gZnJvbSAnLi9kZW1vLXZhdWx0LWhlbHBlci1zZXR0aW5ncy50cyc7XG5cbmltcG9ydCB7IGpvaW4gfSBmcm9tICcuLi9wYXRoLnRzJztcbmltcG9ydCB7IEVNUFRZIH0gZnJvbSAnLi4vc3RyaW5nLnRzJztcbmltcG9ydCB7XG4gIGNvbmZpZ3VyZUNvbW11bml0eVBsdWdpbixcbiAgQ29uZmlndXJlQ29tbXVuaXR5UGx1Z2luUmVzdWx0LFxuICBkaXNhYmxlQ29tbXVuaXR5UGx1Z2luLFxuICBlbmFibGVDb21tdW5pdHlQbHVnaW4sXG4gIGluc3RhbGxDb21tdW5pdHlQbHVnaW5cbn0gZnJvbSAnLi9jb21tdW5pdHktcGx1Z2lucy50cyc7XG5cbi8qKlxuICogUGFyYW1ldGVycyBmb3Ige0BsaW5rIGJvb3RzdHJhcERlbW9WYXVsdH0uXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgQm9vdHN0cmFwRGVtb1ZhdWx0UGFyYW1zIHtcbiAgLyoqXG4gICAqIFRoZSBPYnNpZGlhbiBhcHAgaW5zdGFuY2UuXG4gICAqL1xuICByZWFkb25seSBhcHA6IEFwcDtcbn1cblxuLyoqXG4gKiBDb2RlU2NyaXB0IFRvb2xraXQncyBzZXR0aW5ncywgd3JpdHRlbiBpbnRvIGl0cyBgZGF0YS5qc29uYCBiZWZvcmUgaXQgaXMgZW5hYmxlZC5cbiAqL1xuaW50ZXJmYWNlIENvZGVTY3JpcHRUb29sa2l0U2V0dGluZ3Mge1xuICAvKipcbiAgICogVGhlIFlBTUwgZnJvbnRtYXR0ZXIgbWVyZ2VkIGludG8gZXZlcnkgYGNvZGUtYnV0dG9uYCBibG9jaydzIG93biBjb25maWcsIHVzZWQgaGVyZSB0byB0dXJuIHRoZVxuICAgKiBzb3VyY2Ugdmlld2VyIG9uIGZvciBldmVyeSBidXR0b24gaW4gZXZlcnkgZGVtbyB2YXVsdCB3aXRob3V0IGVkaXRpbmcgYSBzaW5nbGUgbm90ZS5cbiAgICovXG4gIHJlYWRvbmx5IGRlZmF1bHRDb2RlQnV0dG9uQ29uZmlnOiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIFRoZSBmb2xkZXIgKHVuZGVyIHtAbGluayBDb2RlU2NyaXB0VG9vbGtpdFNldHRpbmdzLm1vZHVsZXNSb290fSkgaG9sZGluZyBpbnZvY2FibGUgc2NyaXB0cy5cbiAgICovXG4gIHJlYWRvbmx5IGludm9jYWJsZVNjcmlwdHNGb2xkZXI6IHN0cmluZztcblxuICAvKipcbiAgICogVGhlIHZhdWx0LXJlbGF0aXZlIGZvbGRlciB0aGF0IGByZXF1aXJlKCcvXHUyMDI2JylgIHJlc29sdmVzIG1vZHVsZSBwYXRocyBhZ2FpbnN0LlxuICAgKi9cbiAgcmVhZG9ubHkgbW9kdWxlc1Jvb3Q6IHN0cmluZztcblxuICAvKipcbiAgICogV2hldGhlciBDb2RlU2NyaXB0IFRvb2xraXQgaGFuZGxlcyBgb2JzaWRpYW46Ly9gIHByb3RvY29sIFVSTHMuXG4gICAqL1xuICByZWFkb25seSBzaG91bGRIYW5kbGVQcm90b2NvbFVybHM6IGJvb2xlYW47XG5cbiAgLyoqXG4gICAqIFRoZSBwYXRoICh1bmRlciB7QGxpbmsgQ29kZVNjcmlwdFRvb2xraXRTZXR0aW5ncy5tb2R1bGVzUm9vdH0pIG9mIHRoZSBzY3JpcHQgcnVuIG9uIGxvYWQuXG4gICAqL1xuICByZWFkb25seSBzdGFydHVwU2NyaXB0UGF0aDogc3RyaW5nO1xufVxuXG5jb25zdCBDT0RFX1NDUklQVF9UT09MS0lUX1BMVUdJTl9JRCA9ICdmaXgtcmVxdWlyZS1tb2R1bGVzJztcbmNvbnN0IENPREVfU0NSSVBUX1RPT0xLSVRfTU9EVUxFU19ST09UID0gJ19hc3NldHMvQ29kZVNjcmlwdFRvb2xraXQnO1xuY29uc3QgQ09ERV9TQ1JJUFRfVE9PTEtJVF9TRVRUSU5HUzogQ29kZVNjcmlwdFRvb2xraXRTZXR0aW5ncyA9IHtcbiAgZGVmYXVsdENvZGVCdXR0b25Db25maWc6ICctLS1cXG5zb3VyY2VWaXNpYmlsaXR5OiBjb2xsYXBzZWRcXG4tLS0nLFxuICBpbnZvY2FibGVTY3JpcHRzRm9sZGVyOiAnSW52b2NhYmxlcycsXG4gIG1vZHVsZXNSb290OiBDT0RFX1NDUklQVF9UT09MS0lUX01PRFVMRVNfUk9PVCxcbiAgc2hvdWxkSGFuZGxlUHJvdG9jb2xVcmxzOiB0cnVlLFxuICBzdGFydHVwU2NyaXB0UGF0aDogJ3N0YXJ0dXAudHMnXG59O1xuXG5jb25zdCBERU1PX1ZBVUxUX0hFTFBFUl9QTFVHSU5fSUQgPSAnZGVtby12YXVsdC1oZWxwZXInO1xuY29uc3QgUExVR0lOU19GT0xERVJfTkFNRSA9ICdwbHVnaW5zJztcbmNvbnN0IERBVEFfSlNPTl9GSUxFX05BTUUgPSAnZGF0YS5qc29uJztcbmNvbnN0IElOVkFMSURfREVNT19WQVVMVF9FUlJPUl9NRVNTQUdFID0gJ0ludmFsaWQgZGVtbyB2YXVsdCc7XG5jb25zdCBPUEVOX0RFTU9fVkFVTFRfQ09NTUFORF9OQU1FID0gJ09wZW4gZGVtbyB2YXVsdCc7XG4vLyBgMGAgYXNrcyBPYnNpZGlhbiB0byBrZWVwIHRoZSBub3RpY2UgdXAgdW50aWwgdGhlIHVzZXIgY2xpY2tzIGl0IFx1MjAxNCB0aGUgc2FtZSB0cmVhdG1lbnQgT2JzaWRpYW4gZ2l2ZXNcbi8vIEl0cyBvd24gc2FuZGJveC12YXVsdCBub3RpY2UsIGFuZCB3aGF0IHRoZSBkZW1vLXZhdWx0IG5vdGljZSBpcyBtb2RlbGxlZCBvbi5cbmNvbnN0IFNBTkRCT1hfTk9USUNFX0RVUkFUSU9OX0lOX01JTExJU0VDT05EUyA9IDA7XG5cbi8qKlxuICogQm9vdHN0cmFwcyBhIGRlbW8gdmF1bHQgc28gaXRzIG5vdGVzJyBgY29kZS1idXR0b25gcyB3b3JrIHdpdGggbm8gbWFudWFsIHNldHVwOiBpbnN0YWxscyBDb2RlU2NyaXB0XG4gKiBUb29sa2l0IGZyb20gdGhlIGNvbW11bml0eSBzdG9yZSAoaWYgaXQgaXMgbm90IGFscmVhZHkgaW5zdGFsbGVkKSwgd3JpdGVzIGl0cyBzZXR0aW5ncywgdGhlbiBlbmFibGVzXG4gKiBpdCBcdTIwMTQgd3JpdGluZyB0aGUgc2V0dGluZ3MgQkVGT1JFIGVuYWJsaW5nIHNvIGEgZnJlc2ggZW5hYmxlIGxvYWRzIGl0IGFscmVhZHkgY29uZmlndXJlZCwgd2l0aCBub1xuICogcmVsb2FkLiBJZiBDb2RlU2NyaXB0IFRvb2xraXQgaXMgYWxyZWFkeSBlbmFibGVkIGJ1dCB0aGUgc2V0dGluZ3MganVzdCBjaGFuZ2VkLCBpdCBpcyByZWxvYWRlZFxuICogKGRpc2FibGVkIHRoZW4gZW5hYmxlZCkgc28gaXQgcmUtcmVhZHMgYGRhdGEuanNvbmA7IHdoZW4gdGhlIHNldHRpbmdzIHdlcmUgYWxyZWFkeSBpbiBwbGFjZSwgbm90aGluZyBpc1xuICogcmVsb2FkZWQgKHNvIGEgcm91dGluZSB2YXVsdCByZS1vcGVuIGRvZXMgbm90IHJlLXJ1biBDb2RlU2NyaXB0IFRvb2xraXQncyBzdGFydHVwKS4gQ29kZVNjcmlwdCBUb29sa2l0XG4gKiB0aGVuIHJ1bnMgdGhlIHZhdWx0J3MgYHN0YXJ0dXAudHNgLiBGaW5hbGx5IGl0IGNsb3NlcyBTZXR0aW5ncyAoc28gdGhlIG5vdGljZSBjYW5ub3QgYmUgcmFpc2VkIGluc2lkZVxuICogdGhlIHNldHRpbmdzIHBvcG91dCkgYW5kIHJhaXNlcyB0aGUgc2FuZGJveCBub3RpY2UgZGVzY3JpYmluZyB0aGUgb3BlbmVkIHZhdWx0IGFzIGEgdGhyb3dhd2F5IGNvcHkuXG4gKlxuICogQHBhcmFtIHBhcmFtcyAtIFRoZSB7QGxpbmsgQm9vdHN0cmFwRGVtb1ZhdWx0UGFyYW1zfS5cbiAqIEByZXR1cm5zIEEge0BsaW5rIFByb21pc2V9IHRoYXQgcmVzb2x2ZXMgb25jZSBDb2RlU2NyaXB0IFRvb2xraXQgaXMgaW5zdGFsbGVkLCBjb25maWd1cmVkLCBhbmQgZW5hYmxlZFxuICogYW5kIHRoZSBzYW5kYm94IG5vdGljZSBoYXMgYmVlbiBzaG93bi5cbiAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGJvb3RzdHJhcERlbW9WYXVsdChwYXJhbXM6IEJvb3RzdHJhcERlbW9WYXVsdFBhcmFtcyk6IFByb21pc2U8dm9pZD4ge1xuICBjb25zdCB7IGFwcCB9ID0gcGFyYW1zO1xuICAvLyBSZXNvbHZlZCBmaXJzdCwgc28gYSB2YXVsdCB0aGF0IGlzIG5vdCBhIGRlbW8gdmF1bHQgaXMgcmVmdXNlZCBiZWZvcmUgYW55dGhpbmcgaXMgaW5zdGFsbGVkIGludG8gaXQuXG4gIGNvbnN0IGRlbW9lZFBsdWdpbklkID0gYXdhaXQgZ2V0RGVtb2VkUGx1Z2luSWQoYXBwKTtcbiAgYXdhaXQgaW5zdGFsbENvbW11bml0eVBsdWdpbih7IGFwcCwgcGx1Z2luSWQ6IENPREVfU0NSSVBUX1RPT0xLSVRfUExVR0lOX0lEIH0pO1xuICBjb25zdCByZXN1bHQgPSBhd2FpdCBjb25maWd1cmVDb21tdW5pdHlQbHVnaW4oe1xuICAgIGFwcCxcbiAgICBwbHVnaW5JZDogQ09ERV9TQ1JJUFRfVE9PTEtJVF9QTFVHSU5fSUQsXG4gICAgc2V0dGluZ3M6IENPREVfU0NSSVBUX1RPT0xLSVRfU0VUVElOR1NcbiAgfSk7XG4gIGF3YWl0IGVuc3VyZUludm9jYWJsZVNjcmlwdHNGb2xkZXIoYXBwKTtcblxuICBpZiAoIWFwcC5wbHVnaW5zLmVuYWJsZWRQbHVnaW5zLmhhcyhDT0RFX1NDUklQVF9UT09MS0lUX1BMVUdJTl9JRCkpIHtcbiAgICBhd2FpdCBlbmFibGVDb21tdW5pdHlQbHVnaW4oeyBhcHAsIHBsdWdpbklkOiBDT0RFX1NDUklQVF9UT09MS0lUX1BMVUdJTl9JRCB9KTtcbiAgfSBlbHNlIGlmIChyZXN1bHQgPT09IENvbmZpZ3VyZUNvbW11bml0eVBsdWdpblJlc3VsdC5TdWNjZXNzKSB7XG4gICAgLy8gQWxyZWFkeSBlbmFibGVkIHdpdGggc3RhbGUgc2V0dGluZ3MgXHUyMDE0IHJlbG9hZCBzbyBDb2RlU2NyaXB0IFRvb2xraXQgcmUtcmVhZHMgdGhlIGZyZXNobHkgd3JpdHRlbiBkYXRhLmpzb24uXG4gICAgYXdhaXQgZGlzYWJsZUNvbW11bml0eVBsdWdpbih7IGFwcCwgcGx1Z2luSWQ6IENPREVfU0NSSVBUX1RPT0xLSVRfUExVR0lOX0lEIH0pO1xuICAgIGF3YWl0IGVuYWJsZUNvbW11bml0eVBsdWdpbih7IGFwcCwgcGx1Z2luSWQ6IENPREVfU0NSSVBUX1RPT0xLSVRfUExVR0lOX0lEIH0pO1xuICB9XG5cbiAgc2hvd1NhbmRib3hOb3RpY2UoYXBwLCBkZW1vZWRQbHVnaW5JZCk7XG59XG5cbi8vIEJ1aWxkcyB0aGUgc2FuZGJveCBub3RpY2UgY29udGVudDogd2hhdCB0aGlzIHZhdWx0IGlzLCB3aGVyZSBpdCBsaXZlcywgaG93IGxvbmcgaXQgbGl2ZXMsIGFuZCB3aHlcbi8vIFJlLXJ1bm5pbmcgdGhlIGNvbW1hbmQgcHJvZHVjZXMgYSB2YXVsdCB3aXRob3V0IHRoZSBub3RlcyBqdXN0IHdyaXR0ZW4gaGVyZS5cbi8vXG4vLyBFdmVyeSBjbGFpbSBoYXMgdG8gc3RheSB0cnVlIG9mIHRoZSBvcGVuZXIgKGBkZXNrdG9wLWRlbW8tdmF1bHQtb3BlbmVyLnRzYCk6IGl0IGV4dHJhY3RzIGEgRlJFU0ggY29weVxuLy8gSW50byBpdHMgb3duIGZvbGRlciBvbiBldmVyeSBvcGVuLCBhbmQgZGVsZXRlcyBleHRyYWN0ZWQgZm9sZGVycyBvbGRlciB0aGFuIGEgZGF5IG9uIGVhY2ggbGF0ZXIgb3Blbi5cbi8vIFNvIHRoZSB2YXVsdCBpcyBhIHRlbXBvcmFyeSBzYW5kYm94IFx1MjAxNCBpdCBtdXN0IG5ldmVyIGJlIGRlc2NyaWJlZCBhcyBhIHBsYWNlIHdvcmsgY2FuIGJlIGxlZnQuXG5mdW5jdGlvbiBidWlsZFNhbmRib3hOb3RpY2VGcmFnbWVudChwbHVnaW5OYW1lOiBzdHJpbmcpOiBEb2N1bWVudEZyYWdtZW50IHtcbiAgcmV0dXJuIGNyZWF0ZUZyYWdtZW50KChmcmFnbWVudCkgPT4ge1xuICAgIGZyYWdtZW50LmFwcGVuZFRleHQoJ1RoaXMgaXMgYSBkZW1vIHZhdWx0IGZvciAnKTtcbiAgICBmcmFnbWVudC5jcmVhdGVFbCgnYicsIHsgdGV4dDogcGx1Z2luTmFtZSB9KTtcbiAgICBmcmFnbWVudC5hcHBlbmRUZXh0KCcuJyk7XG5cbiAgICBmcmFnbWVudC5jcmVhdGVFbCgnYnInKTtcbiAgICBmcmFnbWVudC5hcHBlbmRUZXh0KCdJdCBpcyBhIHRlbXBvcmFyeSBzYW5kYm94LCBjbGVhbmVkIHVwIGF1dG9tYXRpY2FsbHkgYWJvdXQgYSBkYXkgYWZ0ZXIgeW91IGxhc3QgdXNlIGl0LicpO1xuXG4gICAgZnJhZ21lbnQuY3JlYXRlRWwoJ2JyJyk7XG4gICAgZnJhZ21lbnQuYXBwZW5kVGV4dCgnRXhlY3V0aW5nICcpO1xuICAgIGZyYWdtZW50LmNyZWF0ZUVsKCdiJywgeyB0ZXh0OiBgJHtwbHVnaW5OYW1lfTogJHtPUEVOX0RFTU9fVkFVTFRfQ09NTUFORF9OQU1FfWAgfSk7XG4gICAgZnJhZ21lbnQuYXBwZW5kVGV4dCgnIGNvbW1hbmQgYWdhaW4gY3JlYXRlcyBhIG5ldyBjb3B5IHdpdGggdGhlIGxhdGVzdCBwbHVnaW4gdmVyc2lvbiwgc28geW91ciBub3RlcyB3aWxsIG5vdCBhcHBlYXIgaW4gaXQuJyk7XG4gIH0pO1xufVxuXG4vLyBDcmVhdGVzIENvZGVTY3JpcHQgVG9vbGtpdCdzIGludm9jYWJsZS1zY3JpcHRzIGZvbGRlciAodW5kZXIgYG1vZHVsZXNSb290YCkgaWYgaXQgaXMgbWlzc2luZy5cbi8vIEV2ZXJ5IGRlbW8gdmF1bHQgdGhlbiBoYXMgdGhlIHNhbWUgQ29kZVNjcmlwdCBUb29sa2l0IGxheW91dCBldmVuIHdoZW4gaXQgc2hpcHMgbm8gaW52b2NhYmxlIHNjcmlwdHMuXG4vLyBUaGUgY29tbWl0dGVkIHZhdWx0IHRoZXJlZm9yZSBjYXJyaWVzIG5vIG90aGVyd2lzZS1lbXB0eSBwbGFjZWhvbGRlciBmb2xkZXIuXG5hc3luYyBmdW5jdGlvbiBlbnN1cmVJbnZvY2FibGVTY3JpcHRzRm9sZGVyKGFwcDogQXBwKTogUHJvbWlzZTx2b2lkPiB7XG4gIGNvbnN0IGludm9jYWJsZVNjcmlwdHNGb2xkZXJQYXRoID0gam9pbihDT0RFX1NDUklQVF9UT09MS0lUX01PRFVMRVNfUk9PVCwgQ09ERV9TQ1JJUFRfVE9PTEtJVF9TRVRUSU5HUy5pbnZvY2FibGVTY3JpcHRzRm9sZGVyKTtcbiAgaWYgKCFhd2FpdCBhcHAudmF1bHQuYWRhcHRlci5leGlzdHMoaW52b2NhYmxlU2NyaXB0c0ZvbGRlclBhdGgpKSB7XG4gICAgYXdhaXQgYXBwLnZhdWx0LmFkYXB0ZXIubWtkaXIoaW52b2NhYmxlU2NyaXB0c0ZvbGRlclBhdGgpO1xuICB9XG59XG5cbi8vIFJlYWRzIHRoZSBwbHVnaW4gdGhlIHZhdWx0IGRlbW9uc3RyYXRlcyBvdXQgb2YgdGhpcyBoZWxwZXIncyBvd24gYGRhdGEuanNvbmAsIHdyaXR0ZW4gYnkgdGhlXG4vLyBQYWNrYWdpbmcgc3RlcCAoc2VlIGBEZW1vVmF1bHRIZWxwZXJTZXR0aW5nc2ApLiBBIHZhdWx0IHdpdGhvdXQgYSByZWFkYWJsZSBtYXJrZXIgd2FzIG5vdCBwcm9kdWNlZCBieVxuLy8gVGhhdCBzdGVwIFx1MjAxNCBoYW5kLWFzc2VtYmxlZCwgb3IgdW5wYWNrZWQgZnJvbSBzb21ldGhpbmcgdGhhdCBpcyBub3QgYSBkZW1vIHZhdWx0IFx1MjAxNCBzbyBpdCBpcyByZWZ1c2VkXG4vLyBSYXRoZXIgdGhhbiBib290c3RyYXBwZWQgYWdhaW5zdCBhIGd1ZXNzLlxuYXN5bmMgZnVuY3Rpb24gZ2V0RGVtb2VkUGx1Z2luSWQoYXBwOiBBcHApOiBQcm9taXNlPHN0cmluZz4ge1xuICBjb25zdCBzZXR0aW5nc1BhdGggPSBqb2luKGFwcC52YXVsdC5jb25maWdEaXIsIFBMVUdJTlNfRk9MREVSX05BTUUsIERFTU9fVkFVTFRfSEVMUEVSX1BMVUdJTl9JRCwgREFUQV9KU09OX0ZJTEVfTkFNRSk7XG4gIGlmICghYXdhaXQgYXBwLnZhdWx0LmFkYXB0ZXIuZXhpc3RzKHNldHRpbmdzUGF0aCkpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoSU5WQUxJRF9ERU1PX1ZBVUxUX0VSUk9SX01FU1NBR0UpO1xuICB9XG5cbiAgbGV0IHBhcnNlZDogdW5rbm93bjtcbiAgdHJ5IHtcbiAgICBwYXJzZWQgPSBKU09OLnBhcnNlKGF3YWl0IGFwcC52YXVsdC5hZGFwdGVyLnJlYWQoc2V0dGluZ3NQYXRoKSk7XG4gIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKElOVkFMSURfREVNT19WQVVMVF9FUlJPUl9NRVNTQUdFLCB7IGNhdXNlOiBlcnJvciB9KTtcbiAgfVxuXG4gIGNvbnN0IGRlbW9lZFBsdWdpbklkID0gKHBhcnNlZCBhcyBudWxsIHwgUGFydGlhbDxEZW1vVmF1bHRIZWxwZXJTZXR0aW5ncz4pPy5kZW1vZWRQbHVnaW5JZDtcbiAgaWYgKHR5cGVvZiBkZW1vZWRQbHVnaW5JZCAhPT0gJ3N0cmluZycgfHwgZGVtb2VkUGx1Z2luSWQgPT09IEVNUFRZKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKElOVkFMSURfREVNT19WQVVMVF9FUlJPUl9NRVNTQUdFKTtcbiAgfVxuICByZXR1cm4gZGVtb2VkUGx1Z2luSWQ7XG59XG5cbi8vIFRlbGxzIHRoZSB1c2VyIHRoaXMgdmF1bHQgaXMgYSBzYW5kYm94LCB1c2luZyBPYnNpZGlhbidzIG93biBzYW5kYm94LXZhdWx0IHRyZWF0bWVudDogYW4gaW5maW5pdGVcbi8vIER1cmF0aW9uLCBkaXNtaXNzZWQgYnkgY2xpY2tpbmcgaXQuIFJhaXNlZCBsYXN0LCBzbyBpdCBpcyB0aGUgbmV3ZXN0IG5vdGljZSBvbiBzY3JlZW4gb25jZVxuLy8gQ29kZVNjcmlwdCBUb29sa2l0J3Mgc3RhcnR1cCBzY3JpcHQgaGFzIGRvbmUgaXRzIG93biB3b3JrLlxuLy9cbi8vIEEgYE5vdGljZWAgaXMgYnVpbHQgaW5zaWRlIHdoYXRldmVyIHdpbmRvdyBpcyBhY3RpdmUgYXQgdGhhdCBtb21lbnQsIGFuZCBTZXR0aW5ncyBpcyBhIFBPUE9VVCBXSU5ET1dcbi8vICh2ZXJpZmllZCBvbiAxLjEzLjYpIHRoYXQgYmVjb21lcyB0aGUgYWN0aXZlIG9uZSB3aGlsZSBpdCBpcyBvcGVuIFx1MjAxNCBzbyBhIG5vdGljZSByYWlzZWQgdGhlbiB3b3VsZCBiZVxuLy8gQ3JlYXRlZCBpbiB0aGUgc2V0dGluZ3Mgd2luZG93IGFuZCB2YW5pc2ggd2l0aCBpdC4gU2V0dGluZ3MgaXMgdGhlcmVmb3JlIGNsb3NlZCBmaXJzdDogT2JzaWRpYW4gaGFuZHNcbi8vIFRoZSBtYWluIHdpbmRvdyBiYWNrIGFzIHRoZSBwb3BvdXQgZ29lcyBhd2F5IChzeW5jaHJvbm91c2x5LCBiZWZvcmUgdGhlIG5vdGljZSBpcyBidWlsdCksIGFuZCBhIHVzZXJcbi8vIFdobyBoYXMganVzdCBvcGVuZWQgYSBkZW1vIHZhdWx0IHdhbnRzIHRvIHNlZSB0aGUgdmF1bHQgcmF0aGVyIHRoYW4gYSBzZXR0aW5ncyB3aW5kb3cgYW55d2F5LiBDbG9zaW5nXG4vLyBBbiBhbHJlYWR5LWNsb3NlZCBTZXR0aW5ncyBpcyBhIG5vLW9wLCBzbyBubyBvcGVuLXN0YXRlIHByb2JlIGlzIG5lZWRlZC5cbmZ1bmN0aW9uIHNob3dTYW5kYm94Tm90aWNlKGFwcDogQXBwLCBkZW1vZWRQbHVnaW5JZDogc3RyaW5nKTogdm9pZCB7XG4gIGNvbnN0IHBsdWdpbk5hbWUgPSBhcHAucGx1Z2lucy5tYW5pZmVzdHNbZGVtb2VkUGx1Z2luSWRdPy5uYW1lID8/IGRlbW9lZFBsdWdpbklkO1xuICBjb25zdCBmcmFnbWVudCA9IGJ1aWxkU2FuZGJveE5vdGljZUZyYWdtZW50KHBsdWdpbk5hbWUpO1xuICBhcHAuc2V0dGluZy5jbG9zZSgpO1xuICBuZXcgTm90aWNlKGZyYWdtZW50LCBTQU5EQk9YX05PVElDRV9EVVJBVElPTl9JTl9NSUxMSVNFQ09ORFMpO1xufVxuIl0sCiAgIm1hcHBpbmdzIjogIjs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUE4QkEsc0JBQXVCO0FBSXZCLGtCQUFxQjtBQUNyQixvQkFBc0I7QUFDdEIsK0JBTU87QUEyQ1AsTUFBTSxnQ0FBZ0M7QUFDdEMsTUFBTSxtQ0FBbUM7QUFDekMsTUFBTSwrQkFBMEQ7QUFBQSxFQUM5RCx5QkFBeUI7QUFBQSxFQUN6Qix3QkFBd0I7QUFBQSxFQUN4QixhQUFhO0FBQUEsRUFDYiwwQkFBMEI7QUFBQSxFQUMxQixtQkFBbUI7QUFDckI7QUFFQSxNQUFNLDhCQUE4QjtBQUNwQyxNQUFNLHNCQUFzQjtBQUM1QixNQUFNLHNCQUFzQjtBQUM1QixNQUFNLG1DQUFtQztBQUN6QyxNQUFNLCtCQUErQjtBQUdyQyxNQUFNLDBDQUEwQztBQWdCaEQsZUFBc0IsbUJBQW1CLFFBQWlEO0FBQ3hGLFFBQU0sRUFBRSxJQUFJLElBQUk7QUFFaEIsUUFBTSxpQkFBaUIsTUFBTSxrQkFBa0IsR0FBRztBQUNsRCxZQUFNLGlEQUF1QixFQUFFLEtBQUssVUFBVSw4QkFBOEIsQ0FBQztBQUM3RSxRQUFNLFNBQVMsVUFBTSxtREFBeUI7QUFBQSxJQUM1QztBQUFBLElBQ0EsVUFBVTtBQUFBLElBQ1YsVUFBVTtBQUFBLEVBQ1osQ0FBQztBQUNELFFBQU0sNkJBQTZCLEdBQUc7QUFFdEMsTUFBSSxDQUFDLElBQUksUUFBUSxlQUFlLElBQUksNkJBQTZCLEdBQUc7QUFDbEUsY0FBTSxnREFBc0IsRUFBRSxLQUFLLFVBQVUsOEJBQThCLENBQUM7QUFBQSxFQUM5RSxXQUFXLFdBQVcsd0RBQStCLFNBQVM7QUFFNUQsY0FBTSxpREFBdUIsRUFBRSxLQUFLLFVBQVUsOEJBQThCLENBQUM7QUFDN0UsY0FBTSxnREFBc0IsRUFBRSxLQUFLLFVBQVUsOEJBQThCLENBQUM7QUFBQSxFQUM5RTtBQUVBLG9CQUFrQixLQUFLLGNBQWM7QUFDdkM7QUFRQSxTQUFTLDJCQUEyQixZQUFzQztBQUN4RSxTQUFPLGVBQWUsQ0FBQyxhQUFhO0FBQ2xDLGFBQVMsV0FBVywyQkFBMkI7QUFDL0MsYUFBUyxTQUFTLEtBQUssRUFBRSxNQUFNLFdBQVcsQ0FBQztBQUMzQyxhQUFTLFdBQVcsR0FBRztBQUV2QixhQUFTLFNBQVMsSUFBSTtBQUN0QixhQUFTLFdBQVcsd0ZBQXdGO0FBRTVHLGFBQVMsU0FBUyxJQUFJO0FBQ3RCLGFBQVMsV0FBVyxZQUFZO0FBQ2hDLGFBQVMsU0FBUyxLQUFLLEVBQUUsTUFBTSxHQUFHLFVBQVUsS0FBSyw0QkFBNEIsR0FBRyxDQUFDO0FBQ2pGLGFBQVMsV0FBVyx3R0FBd0c7QUFBQSxFQUM5SCxDQUFDO0FBQ0g7QUFLQSxlQUFlLDZCQUE2QixLQUF5QjtBQUNuRSxRQUFNLGlDQUE2QixrQkFBSyxrQ0FBa0MsNkJBQTZCLHNCQUFzQjtBQUM3SCxNQUFJLENBQUMsTUFBTSxJQUFJLE1BQU0sUUFBUSxPQUFPLDBCQUEwQixHQUFHO0FBQy9ELFVBQU0sSUFBSSxNQUFNLFFBQVEsTUFBTSwwQkFBMEI7QUFBQSxFQUMxRDtBQUNGO0FBTUEsZUFBZSxrQkFBa0IsS0FBMkI7QUFDMUQsUUFBTSxtQkFBZSxrQkFBSyxJQUFJLE1BQU0sV0FBVyxxQkFBcUIsNkJBQTZCLG1CQUFtQjtBQUNwSCxNQUFJLENBQUMsTUFBTSxJQUFJLE1BQU0sUUFBUSxPQUFPLFlBQVksR0FBRztBQUNqRCxVQUFNLElBQUksTUFBTSxnQ0FBZ0M7QUFBQSxFQUNsRDtBQUVBLE1BQUk7QUFDSixNQUFJO0FBQ0YsYUFBUyxLQUFLLE1BQU0sTUFBTSxJQUFJLE1BQU0sUUFBUSxLQUFLLFlBQVksQ0FBQztBQUFBLEVBQ2hFLFNBQVMsT0FBTztBQUNkLFVBQU0sSUFBSSxNQUFNLGtDQUFrQyxFQUFFLE9BQU8sTUFBTSxDQUFDO0FBQUEsRUFDcEU7QUFFQSxRQUFNLGlCQUFrQixRQUFvRDtBQUM1RSxNQUFJLE9BQU8sbUJBQW1CLFlBQVksbUJBQW1CLHFCQUFPO0FBQ2xFLFVBQU0sSUFBSSxNQUFNLGdDQUFnQztBQUFBLEVBQ2xEO0FBQ0EsU0FBTztBQUNUO0FBWUEsU0FBUyxrQkFBa0IsS0FBVSxnQkFBOEI7QUFDakUsUUFBTSxhQUFhLElBQUksUUFBUSxVQUFVLGNBQWMsR0FBRyxRQUFRO0FBQ2xFLFFBQU0sV0FBVywyQkFBMkIsVUFBVTtBQUN0RCxNQUFJLFFBQVEsTUFBTTtBQUNsQixNQUFJLHVCQUFPLFVBQVUsdUNBQXVDO0FBQzlEOyIsCiAgIm5hbWVzIjogW10KfQo=
@@ -11,6 +11,9 @@
11
11
  * committed bootstrap plugin (`demo-vault-helper`) that is injected into every demo vault at release
12
12
  * time.
13
13
  *
14
+ * The plugin the vault demonstrates is read from the helper's own `data.json`, written by the packaging
15
+ * step ({@link DemoVaultHelperSettings}); a vault without that marker is refused as not a demo vault.
16
+ *
14
17
  * It writes CodeScript Toolkit's settings BEFORE enabling it, so the plugin loads already configured —
15
18
  * no reload. CodeScript Toolkit then runs the vault's `startup.ts` (via its `startupScriptPath`
16
19
  * setting), which is where each vault opens its start note and does any plugin-specific setup.
@@ -20,7 +23,8 @@
20
23
  * empty folder for it.
21
24
  *
22
25
  * Finally it raises the sandbox notice explaining that the opened vault is a throwaway copy, so a user
23
- * who writes their own notes in it is never surprised by them being absent from the next copy.
26
+ * who writes their own notes in it is never surprised by them being absent from the next copy. Settings
27
+ * is closed first, so the notice lands in the vault's main window rather than in the settings popout.
24
28
  */
25
29
  import type { App } from 'obsidian' with { 'resolution-mode': 'import' };
26
30
  /**
@@ -39,8 +43,8 @@ export interface BootstrapDemoVaultParams {
39
43
  * reload. If CodeScript Toolkit is already enabled but the settings just changed, it is reloaded
40
44
  * (disabled then enabled) so it re-reads `data.json`; when the settings were already in place, nothing is
41
45
  * reloaded (so a routine vault re-open does not re-run CodeScript Toolkit's startup). CodeScript Toolkit
42
- * then runs the vault's `startup.ts`. Finally it raises the sandbox notice describing the opened vault
43
- * as a throwaway copy.
46
+ * then runs the vault's `startup.ts`. Finally it closes Settings (so the notice cannot be raised inside
47
+ * the settings popout) and raises the sandbox notice describing the opened vault as a throwaway copy.
44
48
  *
45
49
  * @param params - The {@link BootstrapDemoVaultParams}.
46
50
  * @returns A {@link Promise} that resolves once CodeScript Toolkit is installed, configured, and enabled