obsidian-dev-utils 101.5.0 → 101.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +12 -0
- package/dist/integration-test-plugin/main.js +2612 -1815
- package/dist/lib/cjs/__merged.cjs +29 -1
- package/dist/lib/cjs/__merged.d.cts +5 -1
- package/dist/lib/cjs/generated-during-build.cjs +1 -1
- package/dist/lib/cjs/obsidian/components/component-ex.cjs +14 -1
- package/dist/lib/cjs/obsidian/components/component-ex.d.cts +11 -0
- package/dist/lib/cjs/obsidian/components/index.cjs +7 -1
- package/dist/lib/cjs/obsidian/components/index.d.cts +2 -0
- package/dist/lib/cjs/obsidian/components/monkey-around-component.cjs +1 -1
- package/dist/lib/cjs/obsidian/components/plugin-gate-component.cjs +520 -0
- package/dist/lib/cjs/obsidian/components/plugin-gate-component.d.cts +299 -0
- package/dist/lib/cjs/obsidian/components/plugin-suggestion-component.cjs +17 -38
- package/dist/lib/cjs/obsidian/components/plugin-suggestion-component.d.cts +25 -18
- package/dist/lib/cjs/obsidian/components/rename-delete-handler-component.cjs +7 -2
- package/dist/lib/cjs/obsidian/components/settings-migration-component.cjs +232 -0
- package/dist/lib/cjs/obsidian/components/settings-migration-component.d.cts +120 -0
- package/dist/lib/cjs/obsidian/css-class.cjs +3 -1
- package/dist/lib/cjs/obsidian/css-class.d.cts +9 -0
- package/dist/lib/cjs/obsidian/html-element.cjs +27 -3
- package/dist/lib/cjs/obsidian/html-element.d.cts +36 -0
- package/dist/lib/cjs/obsidian/i18n/locales/en.cjs +15 -1
- package/dist/lib/cjs/obsidian/i18n/locales/en.d.cts +14 -0
- package/dist/lib/cjs/obsidian/i18n/locales/translations-map.d.cts +14 -0
- package/dist/lib/cjs/obsidian/mobile-trusted-input.cjs +1 -1
- package/dist/lib/cjs/obsidian/mobile-trusted-input.d.cts +5 -3
- package/dist/lib/cjs/obsidian/plugin/index.cjs +12 -3
- package/dist/lib/cjs/obsidian/plugin/index.d.cts +3 -0
- package/dist/lib/cjs/obsidian/plugin/plugin-api.cjs +2 -2
- package/dist/lib/cjs/obsidian/plugin/plugin-api.d.cts +34 -15
- package/dist/lib/cjs/obsidian/plugin/plugin-install-state.cjs +208 -0
- package/dist/lib/cjs/obsidian/plugin/plugin-install-state.d.cts +113 -0
- package/dist/lib/cjs/obsidian/plugin/plugin-lifecycle-events.cjs +161 -0
- package/dist/lib/cjs/obsidian/plugin/plugin-lifecycle-events.d.cts +119 -0
- package/dist/lib/cjs/obsidian/plugin/plugin.cjs +241 -21
- package/dist/lib/cjs/obsidian/plugin/plugin.d.cts +133 -4
- package/dist/lib/cjs/obsidian/plugin/settings-migration-api.cjs +141 -0
- package/dist/lib/cjs/obsidian/plugin/settings-migration-api.d.cts +91 -0
- package/dist/lib/esm/__merged.d.mts +5 -1
- package/dist/lib/esm/__merged.mjs +32 -2
- package/dist/lib/esm/generated-during-build.mjs +1 -1
- package/dist/lib/esm/obsidian/components/component-ex.d.mts +11 -0
- package/dist/lib/esm/obsidian/components/component-ex.mjs +14 -1
- package/dist/lib/esm/obsidian/components/index.d.mts +2 -0
- package/dist/lib/esm/obsidian/components/index.mjs +5 -1
- package/dist/lib/esm/obsidian/components/monkey-around-component.mjs +1 -1
- package/dist/lib/esm/obsidian/components/plugin-gate-component.d.mts +299 -0
- package/dist/lib/esm/obsidian/components/plugin-gate-component.mjs +428 -0
- package/dist/lib/esm/obsidian/components/plugin-suggestion-component.d.mts +25 -18
- package/dist/lib/esm/obsidian/components/plugin-suggestion-component.mjs +21 -41
- package/dist/lib/esm/obsidian/components/rename-delete-handler-component.mjs +7 -2
- package/dist/lib/esm/obsidian/components/settings-migration-component.d.mts +120 -0
- package/dist/lib/esm/obsidian/components/settings-migration-component.mjs +127 -0
- package/dist/lib/esm/obsidian/css-class.d.mts +9 -0
- package/dist/lib/esm/obsidian/css-class.mjs +3 -1
- package/dist/lib/esm/obsidian/html-element.d.mts +36 -0
- package/dist/lib/esm/obsidian/html-element.mjs +24 -2
- package/dist/lib/esm/obsidian/i18n/locales/en.d.mts +14 -0
- package/dist/lib/esm/obsidian/i18n/locales/en.mjs +15 -1
- package/dist/lib/esm/obsidian/i18n/locales/translations-map.d.mts +14 -0
- package/dist/lib/esm/obsidian/mobile-trusted-input.d.mts +5 -3
- package/dist/lib/esm/obsidian/mobile-trusted-input.mjs +1 -1
- package/dist/lib/esm/obsidian/plugin/index.d.mts +3 -0
- package/dist/lib/esm/obsidian/plugin/index.mjs +8 -2
- package/dist/lib/esm/obsidian/plugin/plugin-api.d.mts +34 -15
- package/dist/lib/esm/obsidian/plugin/plugin-api.mjs +2 -2
- package/dist/lib/esm/obsidian/plugin/plugin-install-state.d.mts +113 -0
- package/dist/lib/esm/obsidian/plugin/plugin-install-state.mjs +106 -0
- package/dist/lib/esm/obsidian/plugin/plugin-lifecycle-events.d.mts +119 -0
- package/dist/lib/esm/obsidian/plugin/plugin-lifecycle-events.mjs +54 -0
- package/dist/lib/esm/obsidian/plugin/plugin.d.mts +133 -4
- package/dist/lib/esm/obsidian/plugin/plugin.mjs +245 -21
- package/dist/lib/esm/obsidian/plugin/settings-migration-api.d.mts +91 -0
- package/dist/lib/esm/obsidian/plugin/settings-migration-api.mjs +44 -0
- package/obsidian/components/plugin-gate-component/package.json +6 -0
- package/obsidian/components/settings-migration-component/package.json +6 -0
- package/obsidian/plugin/plugin-install-state/package.json +6 -0
- package/obsidian/plugin/plugin-lifecycle-events/package.json +6 -0
- package/obsidian/plugin/settings-migration-api/package.json +6 -0
- package/package.json +15 -15
|
@@ -0,0 +1,106 @@
|
|
|
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 ensureBrowserProcess() {
|
|
8
|
+
const browserProcess = {
|
|
9
|
+
browser: true,
|
|
10
|
+
cwd() {
|
|
11
|
+
return '/';
|
|
12
|
+
},
|
|
13
|
+
env: {},
|
|
14
|
+
platform: 'android'
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
// eslint-disable-next-line obsidianmd/no-global-this, unicorn/no-unnecessary-global-this -- Must stay `globalThis`-qualified: in the emitted banner a bare `process` is a free identifier, so reading it where the host has none throws a ReferenceError instead of yielding `undefined`. That is the very case this function exists to handle.
|
|
18
|
+
const existingProcess = globalThis.process;
|
|
19
|
+
|
|
20
|
+
if (!existingProcess) {
|
|
21
|
+
// eslint-disable-next-line obsidianmd/no-global-this -- Actively use globalThis.
|
|
22
|
+
globalThis.process = browserProcess;
|
|
23
|
+
return;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
if (existingProcess.versions?.node) {
|
|
27
|
+
return;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
const existingProcessRecord = existingProcess;
|
|
31
|
+
|
|
32
|
+
for (const [key, value] of Object.entries(browserProcess)) {
|
|
33
|
+
existingProcessRecord[key] ??= value;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
existingProcessRecord['browser'] = true;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
(function initEsm() {
|
|
40
|
+
ensureBrowserProcess();
|
|
41
|
+
})();
|
|
42
|
+
})();
|
|
43
|
+
|
|
44
|
+
import {
|
|
45
|
+
enableCommunityPlugin,
|
|
46
|
+
installConfigureEnableCommunityPlugin
|
|
47
|
+
} from "../community-plugins.mjs";
|
|
48
|
+
import {
|
|
49
|
+
asCodeBlock,
|
|
50
|
+
createFragmentWithCodeBlocks
|
|
51
|
+
} from "../html-element.mjs";
|
|
52
|
+
import { t } from "../i18n/i18n.mjs";
|
|
53
|
+
var InstalledPluginState = /* @__PURE__ */ ((InstalledPluginState2) => {
|
|
54
|
+
InstalledPluginState2["Enabled"] = "enabled";
|
|
55
|
+
InstalledPluginState2["InstalledButDisabled"] = "installedButDisabled";
|
|
56
|
+
InstalledPluginState2["NotInstalled"] = "notInstalled";
|
|
57
|
+
return InstalledPluginState2;
|
|
58
|
+
})(InstalledPluginState || {});
|
|
59
|
+
function getInstalledPluginState(params) {
|
|
60
|
+
const { app, pluginId } = params;
|
|
61
|
+
if (app.plugins.enabledPlugins.has(pluginId)) {
|
|
62
|
+
return "enabled" /* Enabled */;
|
|
63
|
+
}
|
|
64
|
+
return Object.hasOwn(app.plugins.manifests, pluginId) ? "installedButDisabled" /* InstalledButDisabled */ : "notInstalled" /* NotInstalled */;
|
|
65
|
+
}
|
|
66
|
+
function getInstalledPluginVersion(params) {
|
|
67
|
+
const { app, pluginId } = params;
|
|
68
|
+
if (!app.plugins.enabledPlugins.has(pluginId)) {
|
|
69
|
+
return null;
|
|
70
|
+
}
|
|
71
|
+
return app.plugins.manifests[pluginId]?.version ?? "";
|
|
72
|
+
}
|
|
73
|
+
async function installAndEnablePlugin(params) {
|
|
74
|
+
const {
|
|
75
|
+
app,
|
|
76
|
+
pluginId,
|
|
77
|
+
pluginName,
|
|
78
|
+
pluginNoticeComponent
|
|
79
|
+
} = params;
|
|
80
|
+
const state = getInstalledPluginState({ app, pluginId });
|
|
81
|
+
if (state === "enabled" /* Enabled */) {
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
84
|
+
try {
|
|
85
|
+
if (state === "installedButDisabled" /* InstalledButDisabled */) {
|
|
86
|
+
await enableCommunityPlugin({ app, pluginId });
|
|
87
|
+
} else {
|
|
88
|
+
await installConfigureEnableCommunityPlugin({ app, pluginId });
|
|
89
|
+
}
|
|
90
|
+
} catch (error) {
|
|
91
|
+
pluginNoticeComponent.showNotice(createFragmentWithCodeBlocks(
|
|
92
|
+
t(($) => $.obsidianDevUtils.pluginSuggestion.installFailed, { pluginName: asCodeBlock(pluginName) })
|
|
93
|
+
));
|
|
94
|
+
throw error;
|
|
95
|
+
}
|
|
96
|
+
pluginNoticeComponent.showNotice(createFragmentWithCodeBlocks(
|
|
97
|
+
t(($) => $.obsidianDevUtils.pluginSuggestion.installed, { pluginName: asCodeBlock(pluginName) })
|
|
98
|
+
));
|
|
99
|
+
}
|
|
100
|
+
export {
|
|
101
|
+
InstalledPluginState,
|
|
102
|
+
getInstalledPluginState,
|
|
103
|
+
getInstalledPluginVersion,
|
|
104
|
+
installAndEnablePlugin
|
|
105
|
+
};
|
|
106
|
+
//# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsiLi4vLi4vLi4vLi4vLi4vc3JjL29ic2lkaWFuL3BsdWdpbi9wbHVnaW4taW5zdGFsbC1zdGF0ZS50cyJdLAogICJzb3VyY2VzQ29udGVudCI6IFsiLyoqXG4gKiBAZmlsZVxuICpcbiAqIEhvdyBhbm90aGVyIHBsdWdpbiBpcyBwcmVzZW50IGluIHRoaXMgdmF1bHQsIGFuZCB0aGUgb25lLWNsaWNrIHBhdGggdG8gbWFraW5nIGl0IHByZXNlbnQuXG4gKlxuICogU2hhcmVkIGJ5IHRoZSB0d28gY29tcG9uZW50cyB0aGF0IGFzayBhIHVzZXIgdG8gYnJpbmcgYW5vdGhlciBwbHVnaW4gaW46IGBQbHVnaW5TdWdnZXN0aW9uQ29tcG9uZW50YCxcbiAqIHdoaWNoIE9GRkVSUyBvbmUgYW5kIGtlZXBzIHdvcmtpbmcgd2l0aG91dCBpdCwgYW5kIGBQbHVnaW5HYXRlQ29tcG9uZW50YCwgd2hpY2ggUkVRVUlSRVMgb25lIGFuZFxuICogZG9lcyBub3RoaW5nIHVudGlsIGl0IGlzIHRoZXJlLiBUaGUgb2ZmZXIgYW5kIHRoZSByZXF1aXJlbWVudCBkaWZmZXIgaW4gd2hhdCB0aGV5IGRvIGFib3V0IHRoZSBhbnN3ZXIsXG4gKiBub3QgaW4gaG93IHRoZXkgcmVhZCB0aGUgc3RhdGUgb3IgaG93IHRoZXkgaW5zdGFsbCBcdTIwMTQgc28gdGhhdCBwYXJ0IGxpdmVzIGhlcmUgcmF0aGVyIHRoYW4gaW4gYm90aC5cbiAqL1xuXG5pbXBvcnQgdHlwZSB7IEFwcCB9IGZyb20gJ29ic2lkaWFuJztcblxuaW1wb3J0IHR5cGUgeyBQbHVnaW5Ob3RpY2VDb21wb25lbnQgfSBmcm9tICcuLi9jb21wb25lbnRzL3BsdWdpbi1ub3RpY2UtY29tcG9uZW50LnRzJztcblxuaW1wb3J0IHtcbiAgZW5hYmxlQ29tbXVuaXR5UGx1Z2luLFxuICBpbnN0YWxsQ29uZmlndXJlRW5hYmxlQ29tbXVuaXR5UGx1Z2luXG59IGZyb20gJy4uL2NvbW11bml0eS1wbHVnaW5zLnRzJztcbmltcG9ydCB7XG4gIGFzQ29kZUJsb2NrLFxuICBjcmVhdGVGcmFnbWVudFdpdGhDb2RlQmxvY2tzXG59IGZyb20gJy4uL2h0bWwtZWxlbWVudC50cyc7XG5pbXBvcnQgeyB0IH0gZnJvbSAnLi4vaTE4bi9pMThuLnRzJztcblxuLyoqXG4gKiBIb3cgYW5vdGhlciBwbHVnaW4gaXMgY3VycmVudGx5IHByZXNlbnQgaW4gdGhlIHZhdWx0LlxuICovXG5leHBvcnQgZW51bSBJbnN0YWxsZWRQbHVnaW5TdGF0ZSB7XG4gIC8qKlxuICAgKiBJbnN0YWxsZWQgYW5kIGVuYWJsZWQgXHUyMDE0IHRoZXJlIGlzIG5vdGhpbmcgdG8gZG8uXG4gICAqL1xuICBFbmFibGVkID0gJ2VuYWJsZWQnLFxuXG4gIC8qKlxuICAgKiBJbnN0YWxsZWQgYnV0IGRpc2FibGVkLiBPbmx5IGFuIGVuYWJsZSBpcyBuZWVkZWQsIHNvIG5vIGRvd25sb2FkIGhhcHBlbnMuXG4gICAqL1xuICBJbnN0YWxsZWRCdXREaXNhYmxlZCA9ICdpbnN0YWxsZWRCdXREaXNhYmxlZCcsXG5cbiAgLyoqXG4gICAqIE5vdCBpbnN0YWxsZWQgYXQgYWxsLlxuICAgKi9cbiAgTm90SW5zdGFsbGVkID0gJ25vdEluc3RhbGxlZCdcbn1cblxuLyoqXG4gKiBQYXJhbWV0ZXJzIGZvciB7QGxpbmsgZ2V0SW5zdGFsbGVkUGx1Z2luU3RhdGV9LlxuICovXG5leHBvcnQgaW50ZXJmYWNlIEdldEluc3RhbGxlZFBsdWdpblN0YXRlUGFyYW1zIHtcbiAgLyoqXG4gICAqIFRoZSBPYnNpZGlhbiBhcHAgaW5zdGFuY2UuXG4gICAqL1xuICByZWFkb25seSBhcHA6IEFwcDtcblxuICAvKipcbiAgICogVGhlIGBtYW5pZmVzdC5pZGAgb2YgdGhlIHBsdWdpbiB0byBsb29rIGZvci5cbiAgICovXG4gIHJlYWRvbmx5IHBsdWdpbklkOiBzdHJpbmc7XG59XG5cbi8qKlxuICogUGFyYW1ldGVycyBmb3Ige0BsaW5rIGdldEluc3RhbGxlZFBsdWdpblZlcnNpb259LlxuICovXG5leHBvcnQgaW50ZXJmYWNlIEdldEluc3RhbGxlZFBsdWdpblZlcnNpb25QYXJhbXMge1xuICAvKipcbiAgICogVGhlIE9ic2lkaWFuIGFwcCBpbnN0YW5jZS5cbiAgICovXG4gIHJlYWRvbmx5IGFwcDogQXBwO1xuXG4gIC8qKlxuICAgKiBUaGUgYG1hbmlmZXN0LmlkYCBvZiB0aGUgcGx1Z2luIHRvIGxvb2sgZm9yLlxuICAgKi9cbiAgcmVhZG9ubHkgcGx1Z2luSWQ6IHN0cmluZztcbn1cblxuLyoqXG4gKiBQYXJhbWV0ZXJzIGZvciB7QGxpbmsgaW5zdGFsbEFuZEVuYWJsZVBsdWdpbn0uXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgSW5zdGFsbEFuZEVuYWJsZVBsdWdpblBhcmFtcyB7XG4gIC8qKlxuICAgKiBUaGUgT2JzaWRpYW4gYXBwIGluc3RhbmNlLlxuICAgKi9cbiAgcmVhZG9ubHkgYXBwOiBBcHA7XG5cbiAgLyoqXG4gICAqIFRoZSBgbWFuaWZlc3QuaWRgIG9mIHRoZSBwbHVnaW4gdG8gaW5zdGFsbCBhbmQgZW5hYmxlLlxuICAgKi9cbiAgcmVhZG9ubHkgcGx1Z2luSWQ6IHN0cmluZztcblxuICAvKipcbiAgICogVGhlIGRpc3BsYXkgbmFtZSBvZiB0aGUgcGx1Z2luLCBzaG93biB0byB0aGUgdXNlci5cbiAgICovXG4gIHJlYWRvbmx5IHBsdWdpbk5hbWU6IHN0cmluZztcblxuICAvKipcbiAgICogVGhlIG5vdGljZSBjb21wb25lbnQgb2YgdGhlIHBsdWdpbiBkb2luZyB0aGUgYXNraW5nLCB1c2VkIHRvIHJlcG9ydCB0aGUgb3V0Y29tZS5cbiAgICovXG4gIHJlYWRvbmx5IHBsdWdpbk5vdGljZUNvbXBvbmVudDogUGx1Z2luTm90aWNlQ29tcG9uZW50O1xufVxuXG4vKipcbiAqIFJlc29sdmVzIGhvdyBhbm90aGVyIHBsdWdpbiBpcyBjdXJyZW50bHkgcHJlc2VudCBpbiB0aGUgdmF1bHQuXG4gKlxuICogQHBhcmFtIHBhcmFtcyAtIFRoZSB7QGxpbmsgR2V0SW5zdGFsbGVkUGx1Z2luU3RhdGVQYXJhbXN9LlxuICogQHJldHVybnMgVGhlIHtAbGluayBJbnN0YWxsZWRQbHVnaW5TdGF0ZX0uXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBnZXRJbnN0YWxsZWRQbHVnaW5TdGF0ZShwYXJhbXM6IEdldEluc3RhbGxlZFBsdWdpblN0YXRlUGFyYW1zKTogSW5zdGFsbGVkUGx1Z2luU3RhdGUge1xuICBjb25zdCB7IGFwcCwgcGx1Z2luSWQgfSA9IHBhcmFtcztcblxuICBpZiAoYXBwLnBsdWdpbnMuZW5hYmxlZFBsdWdpbnMuaGFzKHBsdWdpbklkKSkge1xuICAgIHJldHVybiBJbnN0YWxsZWRQbHVnaW5TdGF0ZS5FbmFibGVkO1xuICB9XG5cbiAgcmV0dXJuIE9iamVjdC5oYXNPd24oYXBwLnBsdWdpbnMubWFuaWZlc3RzLCBwbHVnaW5JZClcbiAgICA/IEluc3RhbGxlZFBsdWdpblN0YXRlLkluc3RhbGxlZEJ1dERpc2FibGVkXG4gICAgOiBJbnN0YWxsZWRQbHVnaW5TdGF0ZS5Ob3RJbnN0YWxsZWQ7XG59XG5cbi8qKlxuICogUmVhZHMgdGhlIHZlcnNpb24gb2YgYW5vdGhlciBwbHVnaW4gYXMgdGhpcyB2YXVsdCBoYXMgaXQgaW5zdGFsbGVkLCBvciBgbnVsbGAgd2hlbiBpdCBpcyBub3QgcnVubmluZy5cbiAqXG4gKiBUaGUgdmVyc2lvbiBjb21lcyBvdXQgb2YgYGFwcC5wbHVnaW5zLm1hbmlmZXN0c2AsIHdoaWNoIGlzIHBvcHVsYXRlZCBmb3IgZXZlcnkgaW5zdGFsbGVkIHBsdWdpbiBhdFxuICogc3RhcnR1cCBcdTIwMTQgc28sIHVubGlrZSBhbnl0aGluZyBhIHBsdWdpbiBSRUdJU1RFUlMsIGl0IGFuc3dlcnMgdGhlIHNhbWUgd2F5IG5vIG1hdHRlciB3aGljaCBwbHVnaW4gbG9hZGVkXG4gKiBmaXJzdC4gVGhhdCBsb2FkLW9yZGVyIGluZGVwZW5kZW5jZSBpcyB0aGUgd2hvbGUgcmVhc29uIGEgY29uZmxpY3QgaXMgZGV0ZWN0ZWQgYnkgdmVyc2lvbiByYXRoZXIgdGhhbiBieVxuICogYXNraW5nIGEgcmVnaXN0cnkuXG4gKlxuICogYG51bGxgIGZvciBhIHBsdWdpbiB0aGF0IGlzIG5vdCBpbnN0YWxsZWQgT1IgaXMgaW5zdGFsbGVkIGJ1dCBkaXNhYmxlZDogYSBkaXNhYmxlZCBwbHVnaW4gcmVnaXN0ZXJzXG4gKiBub3RoaW5nLCBzbyBmb3IgZXZlcnkgcXVlc3Rpb24gdGhpcyBhbnN3ZXJzIHRoZSB0d28gY2FzZXMgYXJlIHRoZSBzYW1lLiBBbiBpbnN0YWxsZWQsIGVuYWJsZWQgcGx1Z2luXG4gKiB3aG9zZSBtYW5pZmVzdCBzb21laG93IGNhcnJpZXMgbm8gdmVyc2lvbiByZWFkcyBhcyBhbiBlbXB0eSBzdHJpbmcgcmF0aGVyIHRoYW4gYG51bGxgLCB3aGljaCBrZWVwc1xuICogXCJydW5uaW5nLCB2ZXJzaW9uIHVua25vd25cIiBkaXN0aW5ndWlzaGFibGUgZnJvbSBcIm5vdCBydW5uaW5nXCIgXHUyMDE0IGEgY2FsbGVyIGNvbXBhcmluZyB2ZXJzaW9ucyBzaG91bGQgZmFpbFxuICogY2xvc2VkIG9uIGl0IHJhdGhlciB0aGFuIHRyZWF0IGl0IGFzIGFic2VudC5cbiAqXG4gKiBAcGFyYW0gcGFyYW1zIC0gVGhlIHtAbGluayBHZXRJbnN0YWxsZWRQbHVnaW5WZXJzaW9uUGFyYW1zfS5cbiAqIEByZXR1cm5zIFRoZSBpbnN0YWxsZWQgdmVyc2lvbiwgb3IgYG51bGxgIHdoZW4gdGhlIHBsdWdpbiBpcyBub3QgZW5hYmxlZC5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGdldEluc3RhbGxlZFBsdWdpblZlcnNpb24ocGFyYW1zOiBHZXRJbnN0YWxsZWRQbHVnaW5WZXJzaW9uUGFyYW1zKTogbnVsbCB8IHN0cmluZyB7XG4gIGNvbnN0IHsgYXBwLCBwbHVnaW5JZCB9ID0gcGFyYW1zO1xuXG4gIGlmICghYXBwLnBsdWdpbnMuZW5hYmxlZFBsdWdpbnMuaGFzKHBsdWdpbklkKSkge1xuICAgIHJldHVybiBudWxsO1xuICB9XG5cbiAgcmV0dXJuIGFwcC5wbHVnaW5zLm1hbmlmZXN0c1twbHVnaW5JZF0/LnZlcnNpb24gPz8gJyc7XG59XG5cbi8qKlxuICogSW5zdGFsbHMgKHdoZW4gbmVlZGVkKSBhbmQgZW5hYmxlcyBhbm90aGVyIHBsdWdpbiwgcmVwb3J0aW5nIHRoZSBvdXRjb21lIGFzIGEgbm90aWNlLlxuICpcbiAqIEEgbm8tb3Agd2hlbiB0aGUgcGx1Z2luIGlzIGFscmVhZHkgZW5hYmxlZCwgc28gYSBjYWxsZXIgcmVhY3RpbmcgdG8gYSBjbGljayBuZWVkIG5vdCBjaGVjayBmaXJzdC5cbiAqXG4gKiBAcGFyYW0gcGFyYW1zIC0gVGhlIHtAbGluayBJbnN0YWxsQW5kRW5hYmxlUGx1Z2luUGFyYW1zfS5cbiAqIEByZXR1cm5zIEEge0BsaW5rIFByb21pc2V9IHRoYXQgcmVzb2x2ZXMgb25jZSB0aGUgcGx1Z2luIGlzIGVuYWJsZWQuXG4gKiBAdGhyb3dzIFdoYXRldmVyIHRoZSBpbnN0YWxsIG9yIGVuYWJsZSB0aHJldywgYWZ0ZXIgcmVwb3J0aW5nIGl0IGFzIGEgbm90aWNlIFx1MjAxNCB0aGUgY2FsbGVyIGRlY2lkZXNcbiAqIHdoZXRoZXIgYSBmYWlsdXJlIGlzIHdvcnRoIG1vcmUgdGhhbiB0aGUgbm90aWNlIHRoZSB1c2VyIGhhcyBhbHJlYWR5IHNlZW4uXG4gKi9cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBpbnN0YWxsQW5kRW5hYmxlUGx1Z2luKHBhcmFtczogSW5zdGFsbEFuZEVuYWJsZVBsdWdpblBhcmFtcyk6IFByb21pc2U8dm9pZD4ge1xuICBjb25zdCB7XG4gICAgYXBwLFxuICAgIHBsdWdpbklkLFxuICAgIHBsdWdpbk5hbWUsXG4gICAgcGx1Z2luTm90aWNlQ29tcG9uZW50XG4gIH0gPSBwYXJhbXM7XG4gIGNvbnN0IHN0YXRlID0gZ2V0SW5zdGFsbGVkUGx1Z2luU3RhdGUoeyBhcHAsIHBsdWdpbklkIH0pO1xuXG4gIGlmIChzdGF0ZSA9PT0gSW5zdGFsbGVkUGx1Z2luU3RhdGUuRW5hYmxlZCkge1xuICAgIHJldHVybjtcbiAgfVxuXG4gIHRyeSB7XG4gICAgaWYgKHN0YXRlID09PSBJbnN0YWxsZWRQbHVnaW5TdGF0ZS5JbnN0YWxsZWRCdXREaXNhYmxlZCkge1xuICAgICAgYXdhaXQgZW5hYmxlQ29tbXVuaXR5UGx1Z2luKHsgYXBwLCBwbHVnaW5JZCB9KTtcbiAgICB9IGVsc2Uge1xuICAgICAgYXdhaXQgaW5zdGFsbENvbmZpZ3VyZUVuYWJsZUNvbW11bml0eVBsdWdpbih7IGFwcCwgcGx1Z2luSWQgfSk7XG4gICAgfVxuICB9IGNhdGNoIChlcnJvcikge1xuICAgIHBsdWdpbk5vdGljZUNvbXBvbmVudC5zaG93Tm90aWNlKGNyZWF0ZUZyYWdtZW50V2l0aENvZGVCbG9ja3MoXG4gICAgICB0KCgkKSA9PiAkLm9ic2lkaWFuRGV2VXRpbHMucGx1Z2luU3VnZ2VzdGlvbi5pbnN0YWxsRmFpbGVkLCB7IHBsdWdpbk5hbWU6IGFzQ29kZUJsb2NrKHBsdWdpbk5hbWUpIH0pXG4gICAgKSk7XG4gICAgdGhyb3cgZXJyb3I7XG4gIH1cblxuICBwbHVnaW5Ob3RpY2VDb21wb25lbnQuc2hvd05vdGljZShjcmVhdGVGcmFnbWVudFdpdGhDb2RlQmxvY2tzKFxuICAgIHQoKCQpID0+ICQub2JzaWRpYW5EZXZVdGlscy5wbHVnaW5TdWdnZXN0aW9uLmluc3RhbGxlZCwgeyBwbHVnaW5OYW1lOiBhc0NvZGVCbG9jayhwbHVnaW5OYW1lKSB9KVxuICApKTtcbn1cbiJdLAogICJtYXBwaW5ncyI6ICI7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7QUFlQTtBQUFBLEVBQ0U7QUFBQSxFQUNBO0FBQUEsT0FDSztBQUNQO0FBQUEsRUFDRTtBQUFBLEVBQ0E7QUFBQSxPQUNLO0FBQ1AsU0FBUyxTQUFTO0FBS1gsSUFBSyx1QkFBTCxrQkFBS0EsMEJBQUw7QUFJTCxFQUFBQSxzQkFBQSxhQUFVO0FBS1YsRUFBQUEsc0JBQUEsMEJBQXVCO0FBS3ZCLEVBQUFBLHNCQUFBLGtCQUFlO0FBZEwsU0FBQUE7QUFBQSxHQUFBO0FBOEVMLFNBQVMsd0JBQXdCLFFBQTZEO0FBQ25HLFFBQU0sRUFBRSxLQUFLLFNBQVMsSUFBSTtBQUUxQixNQUFJLElBQUksUUFBUSxlQUFlLElBQUksUUFBUSxHQUFHO0FBQzVDLFdBQU87QUFBQSxFQUNUO0FBRUEsU0FBTyxPQUFPLE9BQU8sSUFBSSxRQUFRLFdBQVcsUUFBUSxJQUNoRCxvREFDQTtBQUNOO0FBbUJPLFNBQVMsMEJBQTBCLFFBQXdEO0FBQ2hHLFFBQU0sRUFBRSxLQUFLLFNBQVMsSUFBSTtBQUUxQixNQUFJLENBQUMsSUFBSSxRQUFRLGVBQWUsSUFBSSxRQUFRLEdBQUc7QUFDN0MsV0FBTztBQUFBLEVBQ1Q7QUFFQSxTQUFPLElBQUksUUFBUSxVQUFVLFFBQVEsR0FBRyxXQUFXO0FBQ3JEO0FBWUEsZUFBc0IsdUJBQXVCLFFBQXFEO0FBQ2hHLFFBQU07QUFBQSxJQUNKO0FBQUEsSUFDQTtBQUFBLElBQ0E7QUFBQSxJQUNBO0FBQUEsRUFDRixJQUFJO0FBQ0osUUFBTSxRQUFRLHdCQUF3QixFQUFFLEtBQUssU0FBUyxDQUFDO0FBRXZELE1BQUksVUFBVSx5QkFBOEI7QUFDMUM7QUFBQSxFQUNGO0FBRUEsTUFBSTtBQUNGLFFBQUksVUFBVSxtREFBMkM7QUFDdkQsWUFBTSxzQkFBc0IsRUFBRSxLQUFLLFNBQVMsQ0FBQztBQUFBLElBQy9DLE9BQU87QUFDTCxZQUFNLHNDQUFzQyxFQUFFLEtBQUssU0FBUyxDQUFDO0FBQUEsSUFDL0Q7QUFBQSxFQUNGLFNBQVMsT0FBTztBQUNkLDBCQUFzQixXQUFXO0FBQUEsTUFDL0IsRUFBRSxDQUFDLE1BQU0sRUFBRSxpQkFBaUIsaUJBQWlCLGVBQWUsRUFBRSxZQUFZLFlBQVksVUFBVSxFQUFFLENBQUM7QUFBQSxJQUNyRyxDQUFDO0FBQ0QsVUFBTTtBQUFBLEVBQ1I7QUFFQSx3QkFBc0IsV0FBVztBQUFBLElBQy9CLEVBQUUsQ0FBQyxNQUFNLEVBQUUsaUJBQWlCLGlCQUFpQixXQUFXLEVBQUUsWUFBWSxZQUFZLFVBQVUsRUFBRSxDQUFDO0FBQUEsRUFDakcsQ0FBQztBQUNIOyIsCiAgIm5hbWVzIjogWyJJbnN0YWxsZWRQbHVnaW5TdGF0ZSJdCn0K
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
/// <reference path="../../library.d.mts" />
|
|
2
|
+
/**
|
|
3
|
+
* @file
|
|
4
|
+
*
|
|
5
|
+
* The lifecycle broadcast every {@link PluginBase} makes: `obsidian-dev-utils:plugin-loaded` when it has
|
|
6
|
+
* finished loading and `obsidian-dev-utils:plugin-unloaded` when it goes away.
|
|
7
|
+
*
|
|
8
|
+
* Obsidian gives a plugin no way to learn that ANOTHER plugin was enabled or disabled — there is no such
|
|
9
|
+
* event on `app.plugins`, and a plugin's own `Events` source cannot help a listener that does not yet hold
|
|
10
|
+
* the instance. So the broadcast goes through `app.workspace`, which is one object every plugin in the
|
|
11
|
+
* vault can reach. Deliberately NOT the `globalThis.__obsidianDevUtils` bag the rest of the library shares
|
|
12
|
+
* its state through: a listener there needs its own copy of this library, and these events are meant to be
|
|
13
|
+
* consumable by any plugin at all.
|
|
14
|
+
*
|
|
15
|
+
* The names are past tense because a broadcast states something that has already happened. `loaded` in
|
|
16
|
+
* particular carries a guarantee: it is triggered only after every API the plugin declares has been
|
|
17
|
+
* published, so a listener may call them immediately.
|
|
18
|
+
*
|
|
19
|
+
* Both the event names and {@link PluginLifecycleEventPayload} are a CROSS-VERSION CONTRACT. Copies of
|
|
20
|
+
* this library at different versions publish and consume them side by side in one vault, so neither may
|
|
21
|
+
* change incompatibly: plain data only, and new payload fields only ever added.
|
|
22
|
+
*/
|
|
23
|
+
import type { App } from 'obsidian';
|
|
24
|
+
/**
|
|
25
|
+
* The name of either lifecycle event.
|
|
26
|
+
*/
|
|
27
|
+
export type PluginLifecycleEventName = typeof PLUGIN_LOADED_EVENT_NAME | typeof PLUGIN_UNLOADED_EVENT_NAME;
|
|
28
|
+
/**
|
|
29
|
+
* The payload of {@link PLUGIN_LOADED_EVENT_NAME} and {@link PLUGIN_UNLOADED_EVENT_NAME}.
|
|
30
|
+
*
|
|
31
|
+
* Plain data by design — no class instances and no types owned by this library — because it crosses
|
|
32
|
+
* between independently bundled copies of it, and between plugins that do not use it at all.
|
|
33
|
+
*/
|
|
34
|
+
export interface PluginLifecycleEventPayload {
|
|
35
|
+
/**
|
|
36
|
+
* The contract versions the plugin published, empty when it publishes no API.
|
|
37
|
+
*
|
|
38
|
+
* An array rather than a single version because a provider may publish several contract versions side by
|
|
39
|
+
* side, so consumers pinned to an older range keep working across a breaking change.
|
|
40
|
+
*
|
|
41
|
+
* The API objects themselves are deliberately NOT here. A handle delivered by a one-shot event is a
|
|
42
|
+
* probe: it answers "now" and never says when "now" changed, and one that outlives the provider is
|
|
43
|
+
* exactly the stale handle the plugin-api registry's revocable handles exist to prevent. Reach the API
|
|
44
|
+
* through `watchPluginApi` instead, whose reference stays correct across unload and re-enable.
|
|
45
|
+
*/
|
|
46
|
+
readonly apiVersions: readonly string[];
|
|
47
|
+
/**
|
|
48
|
+
* The ids of the plugins this one declares as mandatory dependencies, empty when it declares none.
|
|
49
|
+
*
|
|
50
|
+
* Present so the relationship can be read from the OTHER end: a provider has no way to ask who depends
|
|
51
|
+
* on it — the registry only answers consumer-to-provider — and "which installed plugins need this one"
|
|
52
|
+
* is what lets a provider's settings tab tell the user why it is in their vault at all.
|
|
53
|
+
*/
|
|
54
|
+
readonly dependencyPluginIds: readonly string[];
|
|
55
|
+
/**
|
|
56
|
+
* The plugin's `manifest.id`.
|
|
57
|
+
*/
|
|
58
|
+
readonly pluginId: string;
|
|
59
|
+
/**
|
|
60
|
+
* The plugin's `manifest.name`, for display.
|
|
61
|
+
*/
|
|
62
|
+
readonly pluginName: string;
|
|
63
|
+
/**
|
|
64
|
+
* The plugin's `manifest.version`.
|
|
65
|
+
*/
|
|
66
|
+
readonly pluginVersion: string;
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Parameters for {@link triggerPluginLifecycleEvent}.
|
|
70
|
+
*/
|
|
71
|
+
export interface TriggerPluginLifecycleEventParams {
|
|
72
|
+
/**
|
|
73
|
+
* The Obsidian app instance whose workspace carries the broadcast.
|
|
74
|
+
*/
|
|
75
|
+
readonly app: App;
|
|
76
|
+
/**
|
|
77
|
+
* The event to trigger.
|
|
78
|
+
*/
|
|
79
|
+
readonly name: PluginLifecycleEventName;
|
|
80
|
+
/**
|
|
81
|
+
* The payload describing the plugin.
|
|
82
|
+
*/
|
|
83
|
+
readonly payload: PluginLifecycleEventPayload;
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Triggered once a plugin has finished loading AND published every API it declares, so a listener may call
|
|
87
|
+
* those APIs immediately.
|
|
88
|
+
*
|
|
89
|
+
* Namespaced by the package name rather than by an abbreviation of it: the event is global to the vault
|
|
90
|
+
* and aimed at plugin authors who have never heard of this library, so the prefix has to identify itself.
|
|
91
|
+
*/
|
|
92
|
+
export declare const PLUGIN_LOADED_EVENT_NAME = "obsidian-dev-utils:plugin-loaded";
|
|
93
|
+
/**
|
|
94
|
+
* Triggered as a plugin unloads — whether the user disabled it, uninstalled it, or Obsidian is shutting
|
|
95
|
+
* down. Its APIs are revoked by the time a listener runs.
|
|
96
|
+
*/
|
|
97
|
+
export declare const PLUGIN_UNLOADED_EVENT_NAME = "obsidian-dev-utils:plugin-unloaded";
|
|
98
|
+
declare module 'obsidian' {
|
|
99
|
+
interface Workspace {
|
|
100
|
+
/**
|
|
101
|
+
* Subscribes to a plugin finishing its load, or to one unloading.
|
|
102
|
+
*
|
|
103
|
+
* @param name - Should be {@link PLUGIN_LOADED_EVENT_NAME} or {@link PLUGIN_UNLOADED_EVENT_NAME}.
|
|
104
|
+
* @param callback - The callback receiving the plugin's payload.
|
|
105
|
+
* @param context - The context passed as `this` to the `callback` function.
|
|
106
|
+
* @returns The event reference.
|
|
107
|
+
*/
|
|
108
|
+
on(name: PluginLifecycleEventName, callback: (payload: PluginLifecycleEventPayload) => unknown, context?: unknown): EventRef;
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* Triggers one of the two lifecycle events on the app's workspace.
|
|
113
|
+
*
|
|
114
|
+
* A thin typed wrapper over `Workspace.trigger`, which accepts any event name and any arguments, so that
|
|
115
|
+
* the one place a payload is constructed is checked against {@link PluginLifecycleEventPayload}.
|
|
116
|
+
*
|
|
117
|
+
* @param params - The {@link TriggerPluginLifecycleEventParams}.
|
|
118
|
+
*/
|
|
119
|
+
export declare function triggerPluginLifecycleEvent(params: TriggerPluginLifecycleEventParams): void;
|
|
@@ -0,0 +1,54 @@
|
|
|
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 ensureBrowserProcess() {
|
|
8
|
+
const browserProcess = {
|
|
9
|
+
browser: true,
|
|
10
|
+
cwd() {
|
|
11
|
+
return '/';
|
|
12
|
+
},
|
|
13
|
+
env: {},
|
|
14
|
+
platform: 'android'
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
// eslint-disable-next-line obsidianmd/no-global-this, unicorn/no-unnecessary-global-this -- Must stay `globalThis`-qualified: in the emitted banner a bare `process` is a free identifier, so reading it where the host has none throws a ReferenceError instead of yielding `undefined`. That is the very case this function exists to handle.
|
|
18
|
+
const existingProcess = globalThis.process;
|
|
19
|
+
|
|
20
|
+
if (!existingProcess) {
|
|
21
|
+
// eslint-disable-next-line obsidianmd/no-global-this -- Actively use globalThis.
|
|
22
|
+
globalThis.process = browserProcess;
|
|
23
|
+
return;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
if (existingProcess.versions?.node) {
|
|
27
|
+
return;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
const existingProcessRecord = existingProcess;
|
|
31
|
+
|
|
32
|
+
for (const [key, value] of Object.entries(browserProcess)) {
|
|
33
|
+
existingProcessRecord[key] ??= value;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
existingProcessRecord['browser'] = true;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
(function initEsm() {
|
|
40
|
+
ensureBrowserProcess();
|
|
41
|
+
})();
|
|
42
|
+
})();
|
|
43
|
+
|
|
44
|
+
const PLUGIN_LOADED_EVENT_NAME = "obsidian-dev-utils:plugin-loaded";
|
|
45
|
+
const PLUGIN_UNLOADED_EVENT_NAME = "obsidian-dev-utils:plugin-unloaded";
|
|
46
|
+
function triggerPluginLifecycleEvent(params) {
|
|
47
|
+
params.app.workspace.trigger(params.name, params.payload);
|
|
48
|
+
}
|
|
49
|
+
export {
|
|
50
|
+
PLUGIN_LOADED_EVENT_NAME,
|
|
51
|
+
PLUGIN_UNLOADED_EVENT_NAME,
|
|
52
|
+
triggerPluginLifecycleEvent
|
|
53
|
+
};
|
|
54
|
+
//# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsiLi4vLi4vLi4vLi4vLi4vc3JjL29ic2lkaWFuL3BsdWdpbi9wbHVnaW4tbGlmZWN5Y2xlLWV2ZW50cy50cyJdLAogICJzb3VyY2VzQ29udGVudCI6IFsiLyoqXG4gKiBAZmlsZVxuICpcbiAqIFRoZSBsaWZlY3ljbGUgYnJvYWRjYXN0IGV2ZXJ5IHtAbGluayBQbHVnaW5CYXNlfSBtYWtlczogYG9ic2lkaWFuLWRldi11dGlsczpwbHVnaW4tbG9hZGVkYCB3aGVuIGl0IGhhc1xuICogZmluaXNoZWQgbG9hZGluZyBhbmQgYG9ic2lkaWFuLWRldi11dGlsczpwbHVnaW4tdW5sb2FkZWRgIHdoZW4gaXQgZ29lcyBhd2F5LlxuICpcbiAqIE9ic2lkaWFuIGdpdmVzIGEgcGx1Z2luIG5vIHdheSB0byBsZWFybiB0aGF0IEFOT1RIRVIgcGx1Z2luIHdhcyBlbmFibGVkIG9yIGRpc2FibGVkIFx1MjAxNCB0aGVyZSBpcyBubyBzdWNoXG4gKiBldmVudCBvbiBgYXBwLnBsdWdpbnNgLCBhbmQgYSBwbHVnaW4ncyBvd24gYEV2ZW50c2Agc291cmNlIGNhbm5vdCBoZWxwIGEgbGlzdGVuZXIgdGhhdCBkb2VzIG5vdCB5ZXQgaG9sZFxuICogdGhlIGluc3RhbmNlLiBTbyB0aGUgYnJvYWRjYXN0IGdvZXMgdGhyb3VnaCBgYXBwLndvcmtzcGFjZWAsIHdoaWNoIGlzIG9uZSBvYmplY3QgZXZlcnkgcGx1Z2luIGluIHRoZVxuICogdmF1bHQgY2FuIHJlYWNoLiBEZWxpYmVyYXRlbHkgTk9UIHRoZSBgZ2xvYmFsVGhpcy5fX29ic2lkaWFuRGV2VXRpbHNgIGJhZyB0aGUgcmVzdCBvZiB0aGUgbGlicmFyeSBzaGFyZXNcbiAqIGl0cyBzdGF0ZSB0aHJvdWdoOiBhIGxpc3RlbmVyIHRoZXJlIG5lZWRzIGl0cyBvd24gY29weSBvZiB0aGlzIGxpYnJhcnksIGFuZCB0aGVzZSBldmVudHMgYXJlIG1lYW50IHRvIGJlXG4gKiBjb25zdW1hYmxlIGJ5IGFueSBwbHVnaW4gYXQgYWxsLlxuICpcbiAqIFRoZSBuYW1lcyBhcmUgcGFzdCB0ZW5zZSBiZWNhdXNlIGEgYnJvYWRjYXN0IHN0YXRlcyBzb21ldGhpbmcgdGhhdCBoYXMgYWxyZWFkeSBoYXBwZW5lZC4gYGxvYWRlZGAgaW5cbiAqIHBhcnRpY3VsYXIgY2FycmllcyBhIGd1YXJhbnRlZTogaXQgaXMgdHJpZ2dlcmVkIG9ubHkgYWZ0ZXIgZXZlcnkgQVBJIHRoZSBwbHVnaW4gZGVjbGFyZXMgaGFzIGJlZW5cbiAqIHB1Ymxpc2hlZCwgc28gYSBsaXN0ZW5lciBtYXkgY2FsbCB0aGVtIGltbWVkaWF0ZWx5LlxuICpcbiAqIEJvdGggdGhlIGV2ZW50IG5hbWVzIGFuZCB7QGxpbmsgUGx1Z2luTGlmZWN5Y2xlRXZlbnRQYXlsb2FkfSBhcmUgYSBDUk9TUy1WRVJTSU9OIENPTlRSQUNULiBDb3BpZXMgb2ZcbiAqIHRoaXMgbGlicmFyeSBhdCBkaWZmZXJlbnQgdmVyc2lvbnMgcHVibGlzaCBhbmQgY29uc3VtZSB0aGVtIHNpZGUgYnkgc2lkZSBpbiBvbmUgdmF1bHQsIHNvIG5laXRoZXIgbWF5XG4gKiBjaGFuZ2UgaW5jb21wYXRpYmx5OiBwbGFpbiBkYXRhIG9ubHksIGFuZCBuZXcgcGF5bG9hZCBmaWVsZHMgb25seSBldmVyIGFkZGVkLlxuICovXG5cbmltcG9ydCB0eXBlIHsgQXBwIH0gZnJvbSAnb2JzaWRpYW4nO1xuXG4vKipcbiAqIFRoZSBuYW1lIG9mIGVpdGhlciBsaWZlY3ljbGUgZXZlbnQuXG4gKi9cbmV4cG9ydCB0eXBlIFBsdWdpbkxpZmVjeWNsZUV2ZW50TmFtZSA9IHR5cGVvZiBQTFVHSU5fTE9BREVEX0VWRU5UX05BTUUgfCB0eXBlb2YgUExVR0lOX1VOTE9BREVEX0VWRU5UX05BTUU7XG5cbi8qKlxuICogVGhlIHBheWxvYWQgb2Yge0BsaW5rIFBMVUdJTl9MT0FERURfRVZFTlRfTkFNRX0gYW5kIHtAbGluayBQTFVHSU5fVU5MT0FERURfRVZFTlRfTkFNRX0uXG4gKlxuICogUGxhaW4gZGF0YSBieSBkZXNpZ24gXHUyMDE0IG5vIGNsYXNzIGluc3RhbmNlcyBhbmQgbm8gdHlwZXMgb3duZWQgYnkgdGhpcyBsaWJyYXJ5IFx1MjAxNCBiZWNhdXNlIGl0IGNyb3NzZXNcbiAqIGJldHdlZW4gaW5kZXBlbmRlbnRseSBidW5kbGVkIGNvcGllcyBvZiBpdCwgYW5kIGJldHdlZW4gcGx1Z2lucyB0aGF0IGRvIG5vdCB1c2UgaXQgYXQgYWxsLlxuICovXG5leHBvcnQgaW50ZXJmYWNlIFBsdWdpbkxpZmVjeWNsZUV2ZW50UGF5bG9hZCB7XG4gIC8qKlxuICAgKiBUaGUgY29udHJhY3QgdmVyc2lvbnMgdGhlIHBsdWdpbiBwdWJsaXNoZWQsIGVtcHR5IHdoZW4gaXQgcHVibGlzaGVzIG5vIEFQSS5cbiAgICpcbiAgICogQW4gYXJyYXkgcmF0aGVyIHRoYW4gYSBzaW5nbGUgdmVyc2lvbiBiZWNhdXNlIGEgcHJvdmlkZXIgbWF5IHB1Ymxpc2ggc2V2ZXJhbCBjb250cmFjdCB2ZXJzaW9ucyBzaWRlIGJ5XG4gICAqIHNpZGUsIHNvIGNvbnN1bWVycyBwaW5uZWQgdG8gYW4gb2xkZXIgcmFuZ2Uga2VlcCB3b3JraW5nIGFjcm9zcyBhIGJyZWFraW5nIGNoYW5nZS5cbiAgICpcbiAgICogVGhlIEFQSSBvYmplY3RzIHRoZW1zZWx2ZXMgYXJlIGRlbGliZXJhdGVseSBOT1QgaGVyZS4gQSBoYW5kbGUgZGVsaXZlcmVkIGJ5IGEgb25lLXNob3QgZXZlbnQgaXMgYVxuICAgKiBwcm9iZTogaXQgYW5zd2VycyBcIm5vd1wiIGFuZCBuZXZlciBzYXlzIHdoZW4gXCJub3dcIiBjaGFuZ2VkLCBhbmQgb25lIHRoYXQgb3V0bGl2ZXMgdGhlIHByb3ZpZGVyIGlzXG4gICAqIGV4YWN0bHkgdGhlIHN0YWxlIGhhbmRsZSB0aGUgcGx1Z2luLWFwaSByZWdpc3RyeSdzIHJldm9jYWJsZSBoYW5kbGVzIGV4aXN0IHRvIHByZXZlbnQuIFJlYWNoIHRoZSBBUElcbiAgICogdGhyb3VnaCBgd2F0Y2hQbHVnaW5BcGlgIGluc3RlYWQsIHdob3NlIHJlZmVyZW5jZSBzdGF5cyBjb3JyZWN0IGFjcm9zcyB1bmxvYWQgYW5kIHJlLWVuYWJsZS5cbiAgICovXG4gIHJlYWRvbmx5IGFwaVZlcnNpb25zOiByZWFkb25seSBzdHJpbmdbXTtcblxuICAvKipcbiAgICogVGhlIGlkcyBvZiB0aGUgcGx1Z2lucyB0aGlzIG9uZSBkZWNsYXJlcyBhcyBtYW5kYXRvcnkgZGVwZW5kZW5jaWVzLCBlbXB0eSB3aGVuIGl0IGRlY2xhcmVzIG5vbmUuXG4gICAqXG4gICAqIFByZXNlbnQgc28gdGhlIHJlbGF0aW9uc2hpcCBjYW4gYmUgcmVhZCBmcm9tIHRoZSBPVEhFUiBlbmQ6IGEgcHJvdmlkZXIgaGFzIG5vIHdheSB0byBhc2sgd2hvIGRlcGVuZHNcbiAgICogb24gaXQgXHUyMDE0IHRoZSByZWdpc3RyeSBvbmx5IGFuc3dlcnMgY29uc3VtZXItdG8tcHJvdmlkZXIgXHUyMDE0IGFuZCBcIndoaWNoIGluc3RhbGxlZCBwbHVnaW5zIG5lZWQgdGhpcyBvbmVcIlxuICAgKiBpcyB3aGF0IGxldHMgYSBwcm92aWRlcidzIHNldHRpbmdzIHRhYiB0ZWxsIHRoZSB1c2VyIHdoeSBpdCBpcyBpbiB0aGVpciB2YXVsdCBhdCBhbGwuXG4gICAqL1xuICByZWFkb25seSBkZXBlbmRlbmN5UGx1Z2luSWRzOiByZWFkb25seSBzdHJpbmdbXTtcblxuICAvKipcbiAgICogVGhlIHBsdWdpbidzIGBtYW5pZmVzdC5pZGAuXG4gICAqL1xuICByZWFkb25seSBwbHVnaW5JZDogc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBUaGUgcGx1Z2luJ3MgYG1hbmlmZXN0Lm5hbWVgLCBmb3IgZGlzcGxheS5cbiAgICovXG4gIHJlYWRvbmx5IHBsdWdpbk5hbWU6IHN0cmluZztcblxuICAvKipcbiAgICogVGhlIHBsdWdpbidzIGBtYW5pZmVzdC52ZXJzaW9uYC5cbiAgICovXG4gIHJlYWRvbmx5IHBsdWdpblZlcnNpb246IHN0cmluZztcbn1cblxuLyoqXG4gKiBQYXJhbWV0ZXJzIGZvciB7QGxpbmsgdHJpZ2dlclBsdWdpbkxpZmVjeWNsZUV2ZW50fS5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBUcmlnZ2VyUGx1Z2luTGlmZWN5Y2xlRXZlbnRQYXJhbXMge1xuICAvKipcbiAgICogVGhlIE9ic2lkaWFuIGFwcCBpbnN0YW5jZSB3aG9zZSB3b3Jrc3BhY2UgY2FycmllcyB0aGUgYnJvYWRjYXN0LlxuICAgKi9cbiAgcmVhZG9ubHkgYXBwOiBBcHA7XG5cbiAgLyoqXG4gICAqIFRoZSBldmVudCB0byB0cmlnZ2VyLlxuICAgKi9cbiAgcmVhZG9ubHkgbmFtZTogUGx1Z2luTGlmZWN5Y2xlRXZlbnROYW1lO1xuXG4gIC8qKlxuICAgKiBUaGUgcGF5bG9hZCBkZXNjcmliaW5nIHRoZSBwbHVnaW4uXG4gICAqL1xuICByZWFkb25seSBwYXlsb2FkOiBQbHVnaW5MaWZlY3ljbGVFdmVudFBheWxvYWQ7XG59XG5cbi8qKlxuICogVHJpZ2dlcmVkIG9uY2UgYSBwbHVnaW4gaGFzIGZpbmlzaGVkIGxvYWRpbmcgQU5EIHB1Ymxpc2hlZCBldmVyeSBBUEkgaXQgZGVjbGFyZXMsIHNvIGEgbGlzdGVuZXIgbWF5IGNhbGxcbiAqIHRob3NlIEFQSXMgaW1tZWRpYXRlbHkuXG4gKlxuICogTmFtZXNwYWNlZCBieSB0aGUgcGFja2FnZSBuYW1lIHJhdGhlciB0aGFuIGJ5IGFuIGFiYnJldmlhdGlvbiBvZiBpdDogdGhlIGV2ZW50IGlzIGdsb2JhbCB0byB0aGUgdmF1bHRcbiAqIGFuZCBhaW1lZCBhdCBwbHVnaW4gYXV0aG9ycyB3aG8gaGF2ZSBuZXZlciBoZWFyZCBvZiB0aGlzIGxpYnJhcnksIHNvIHRoZSBwcmVmaXggaGFzIHRvIGlkZW50aWZ5IGl0c2VsZi5cbiAqL1xuZXhwb3J0IGNvbnN0IFBMVUdJTl9MT0FERURfRVZFTlRfTkFNRSA9ICdvYnNpZGlhbi1kZXYtdXRpbHM6cGx1Z2luLWxvYWRlZCc7XG5cbi8qKlxuICogVHJpZ2dlcmVkIGFzIGEgcGx1Z2luIHVubG9hZHMgXHUyMDE0IHdoZXRoZXIgdGhlIHVzZXIgZGlzYWJsZWQgaXQsIHVuaW5zdGFsbGVkIGl0LCBvciBPYnNpZGlhbiBpcyBzaHV0dGluZ1xuICogZG93bi4gSXRzIEFQSXMgYXJlIHJldm9rZWQgYnkgdGhlIHRpbWUgYSBsaXN0ZW5lciBydW5zLlxuICovXG5leHBvcnQgY29uc3QgUExVR0lOX1VOTE9BREVEX0VWRU5UX05BTUUgPSAnb2JzaWRpYW4tZGV2LXV0aWxzOnBsdWdpbi11bmxvYWRlZCc7XG5cbmRlY2xhcmUgbW9kdWxlICdvYnNpZGlhbicge1xuICBpbnRlcmZhY2UgV29ya3NwYWNlIHtcbiAgICAvKipcbiAgICAgKiBTdWJzY3JpYmVzIHRvIGEgcGx1Z2luIGZpbmlzaGluZyBpdHMgbG9hZCwgb3IgdG8gb25lIHVubG9hZGluZy5cbiAgICAgKlxuICAgICAqIEBwYXJhbSBuYW1lIC0gU2hvdWxkIGJlIHtAbGluayBQTFVHSU5fTE9BREVEX0VWRU5UX05BTUV9IG9yIHtAbGluayBQTFVHSU5fVU5MT0FERURfRVZFTlRfTkFNRX0uXG4gICAgICogQHBhcmFtIGNhbGxiYWNrIC0gVGhlIGNhbGxiYWNrIHJlY2VpdmluZyB0aGUgcGx1Z2luJ3MgcGF5bG9hZC5cbiAgICAgKiBAcGFyYW0gY29udGV4dCAtIFRoZSBjb250ZXh0IHBhc3NlZCBhcyBgdGhpc2AgdG8gdGhlIGBjYWxsYmFja2AgZnVuY3Rpb24uXG4gICAgICogQHJldHVybnMgVGhlIGV2ZW50IHJlZmVyZW5jZS5cbiAgICAgKi9cbiAgICBvbihuYW1lOiBQbHVnaW5MaWZlY3ljbGVFdmVudE5hbWUsIGNhbGxiYWNrOiAocGF5bG9hZDogUGx1Z2luTGlmZWN5Y2xlRXZlbnRQYXlsb2FkKSA9PiB1bmtub3duLCBjb250ZXh0PzogdW5rbm93bik6IEV2ZW50UmVmO1xuICB9XG59XG5cbi8qKlxuICogVHJpZ2dlcnMgb25lIG9mIHRoZSB0d28gbGlmZWN5Y2xlIGV2ZW50cyBvbiB0aGUgYXBwJ3Mgd29ya3NwYWNlLlxuICpcbiAqIEEgdGhpbiB0eXBlZCB3cmFwcGVyIG92ZXIgYFdvcmtzcGFjZS50cmlnZ2VyYCwgd2hpY2ggYWNjZXB0cyBhbnkgZXZlbnQgbmFtZSBhbmQgYW55IGFyZ3VtZW50cywgc28gdGhhdFxuICogdGhlIG9uZSBwbGFjZSBhIHBheWxvYWQgaXMgY29uc3RydWN0ZWQgaXMgY2hlY2tlZCBhZ2FpbnN0IHtAbGluayBQbHVnaW5MaWZlY3ljbGVFdmVudFBheWxvYWR9LlxuICpcbiAqIEBwYXJhbSBwYXJhbXMgLSBUaGUge0BsaW5rIFRyaWdnZXJQbHVnaW5MaWZlY3ljbGVFdmVudFBhcmFtc30uXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiB0cmlnZ2VyUGx1Z2luTGlmZWN5Y2xlRXZlbnQocGFyYW1zOiBUcmlnZ2VyUGx1Z2luTGlmZWN5Y2xlRXZlbnRQYXJhbXMpOiB2b2lkIHtcbiAgcGFyYW1zLmFwcC53b3Jrc3BhY2UudHJpZ2dlcihwYXJhbXMubmFtZSwgcGFyYW1zLnBheWxvYWQpO1xufVxuIl0sCiAgIm1hcHBpbmdzIjogIjs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQXFHTyxNQUFNLDJCQUEyQjtBQU1qQyxNQUFNLDZCQUE2QjtBQXdCbkMsU0FBUyw0QkFBNEIsUUFBaUQ7QUFDM0YsU0FBTyxJQUFJLFVBQVUsUUFBUSxPQUFPLE1BQU0sT0FBTyxPQUFPO0FBQzFEOyIsCiAgIm5hbWVzIjogW10KfQo=
|
|
@@ -9,13 +9,16 @@
|
|
|
9
9
|
import type { Component, IconName } from 'obsidian';
|
|
10
10
|
import type { Promisable } from 'type-fest';
|
|
11
11
|
import { Plugin } from 'obsidian';
|
|
12
|
+
import type { PluginConflict, PluginDependency } from '../components/plugin-gate-component.mjs';
|
|
12
13
|
import type { TranslationsMap } from '../i18n/i18n.mjs';
|
|
14
|
+
import type { PluginApiDeclaration } from './plugin-api.mjs';
|
|
13
15
|
import type { PluginEventMap, PluginEventSource } from './plugin-event-source.mjs';
|
|
14
16
|
import { CommandHandlerComponent } from '../command-handlers/command-handler-component.mjs';
|
|
15
17
|
import { AbortSignalComponent } from '../components/abort-signal-component.mjs';
|
|
16
18
|
import { AsyncErrorHandlerComponent } from '../components/async-error-handler-component.mjs';
|
|
17
19
|
import { ConsoleDebugComponent } from '../components/console-debug-component.mjs';
|
|
18
20
|
import { PluginContextComponent } from '../components/plugin-context-component.mjs';
|
|
21
|
+
import { PluginGateComponent } from '../components/plugin-gate-component.mjs';
|
|
19
22
|
import { PluginNoticeComponent } from '../components/plugin-notice-component.mjs';
|
|
20
23
|
import { PluginSettingsComponentBase } from '../components/plugin-settings-component.mjs';
|
|
21
24
|
import { ResourceLockComponent } from '../resource-lock.mjs';
|
|
@@ -90,6 +93,22 @@ export declare abstract class PluginBase extends PluginBase_base implements Plug
|
|
|
90
93
|
* @param value - Plugin context component.
|
|
91
94
|
*/
|
|
92
95
|
protected set pluginContextComponent(value: PluginContextComponent);
|
|
96
|
+
/**
|
|
97
|
+
* Gets the gate holding the plugin's feature surface up or down.
|
|
98
|
+
*
|
|
99
|
+
* Reach for it from a settings tab to render the overlap banner for a
|
|
100
|
+
* {@link obsidian/components/plugin-gate-component!PluginConflictSeverity.Warn} conflict — the one
|
|
101
|
+
* banner the library cannot place itself, because a running plugin builds its own settings tab.
|
|
102
|
+
*
|
|
103
|
+
* @returns The plugin gate component.
|
|
104
|
+
*/
|
|
105
|
+
protected get pluginGateComponent(): PluginGateComponent;
|
|
106
|
+
/**
|
|
107
|
+
* Sets the plugin gate component.
|
|
108
|
+
*
|
|
109
|
+
* @param value - The plugin gate component.
|
|
110
|
+
*/
|
|
111
|
+
protected set pluginGateComponent(value: PluginGateComponent);
|
|
93
112
|
/**
|
|
94
113
|
* Gets plugin notice component.
|
|
95
114
|
*
|
|
@@ -128,13 +147,22 @@ export declare abstract class PluginBase extends PluginBase_base implements Plug
|
|
|
128
147
|
*/
|
|
129
148
|
protected set resourceLockComponent(value: ResourceLockComponent);
|
|
130
149
|
private readonly components;
|
|
131
|
-
private
|
|
150
|
+
private gatedWrapperComponent;
|
|
151
|
+
private lifecycleEventPayload;
|
|
152
|
+
private readonly universalWrapperComponent;
|
|
132
153
|
/**
|
|
133
154
|
* Adds a child component.
|
|
134
155
|
*
|
|
135
|
-
* The child is added to
|
|
136
|
-
* before
|
|
137
|
-
* children-first, and is usable by the time this method returns.
|
|
156
|
+
* The child is added to the internal wrapper holding the subclass's own surface, which {@link onload}
|
|
157
|
+
* creates and loads before calling {@link onloadImpl}. So a child added during {@link onloadImpl} is
|
|
158
|
+
* loaded immediately, children-first, and is usable by the time this method returns.
|
|
159
|
+
*
|
|
160
|
+
* That wrapper is torn down and rebuilt whenever the gate closes and opens again — a dependency declared
|
|
161
|
+
* by {@link getPluginDependencies} going away and coming back, or a conflict declared by
|
|
162
|
+
* {@link getPluginConflicts} appearing and being resolved — so a child added here lives exactly as long
|
|
163
|
+
* as the plugin's feature surface does. Adding one while the surface is down is still legitimate — it is
|
|
164
|
+
* queued and loaded when the surface next comes up, the way {@link ComponentEx.addChild} already queues
|
|
165
|
+
* a child added to a not-yet-loaded component.
|
|
138
166
|
*
|
|
139
167
|
* @typeParam TComponent - The type of component to add.
|
|
140
168
|
* @param component - The component instance to add.
|
|
@@ -157,6 +185,15 @@ export declare abstract class PluginBase extends PluginBase_base implements Plug
|
|
|
157
185
|
* Do NOT override this method. Override {@link onloadImpl} instead.
|
|
158
186
|
*/
|
|
159
187
|
onload(): Promise<void>;
|
|
188
|
+
/**
|
|
189
|
+
* Called when the plugin is unloaded.
|
|
190
|
+
*
|
|
191
|
+
* Announces the departure on `app.workspace` so anything depending on this plugin learns of it at the
|
|
192
|
+
* moment it happens, rather than discovering it later through behavior that quietly stopped.
|
|
193
|
+
*
|
|
194
|
+
* Do NOT override this method; put teardown on a component instead, which unloads with the plugin.
|
|
195
|
+
*/
|
|
196
|
+
onunload(): void;
|
|
160
197
|
/**
|
|
161
198
|
* Removes a child component.
|
|
162
199
|
*
|
|
@@ -184,6 +221,62 @@ export declare abstract class PluginBase extends PluginBase_base implements Plug
|
|
|
184
221
|
* @returns The icon, or `''` for no icon.
|
|
185
222
|
*/
|
|
186
223
|
protected getNotebookNavigatorMenuSubmenuIcon(): IconName;
|
|
224
|
+
/**
|
|
225
|
+
* Provides the APIs this plugin exposes to other plugins.
|
|
226
|
+
*
|
|
227
|
+
* Override in subclass to publish one. The default publishes none. Called after {@link onloadImpl}, so a
|
|
228
|
+
* declaration may reference anything it created; the returned declarations are published through
|
|
229
|
+
* `publishPluginApi` and revoked when the plugin's feature surface unloads.
|
|
230
|
+
*
|
|
231
|
+
* Returning a LIST rather than a single API is deliberate: the registry supports several contract
|
|
232
|
+
* versions published side by side, which is how a provider ships a breaking `2.0.0` without stranding
|
|
233
|
+
* consumers still pinned to `^1`.
|
|
234
|
+
*
|
|
235
|
+
* Every declaration here is published BEFORE the `obsidian-dev-utils:plugin-loaded` broadcast, which is
|
|
236
|
+
* what lets a listener call these APIs the moment it hears that event.
|
|
237
|
+
*
|
|
238
|
+
* @returns The API declarations.
|
|
239
|
+
*/
|
|
240
|
+
protected getPluginApis(): PluginApiDeclaration[];
|
|
241
|
+
/**
|
|
242
|
+
* Provides the plugins this one refuses, or warns about, running beside.
|
|
243
|
+
*
|
|
244
|
+
* Override in subclass to declare an overlap. The default declares none.
|
|
245
|
+
*
|
|
246
|
+
* A `Block` conflict is the mirror image of a dependency: while a conflicting plugin is enabled at a
|
|
247
|
+
* conflicting version, {@link onloadImpl} does not run at all and the plugin registers nothing. Declare
|
|
248
|
+
* it when both plugins acting on the same operation damages the vault — there is no reliable way to win
|
|
249
|
+
* that race, because whichever plugin loaded first keeps a hand on the wheel, so refusing deterministically
|
|
250
|
+
* beats competing unpredictably. A `Warn` conflict declares an overlap that is merely annoying, such as a
|
|
251
|
+
* duplicated command: both plugins keep running and the user is told.
|
|
252
|
+
*
|
|
253
|
+
* Unlike a dependency, a conflicting plugin need not publish anything — it is detected by reading its
|
|
254
|
+
* installed version, which is the only thing about another plugin that reads the same regardless of load
|
|
255
|
+
* order.
|
|
256
|
+
*
|
|
257
|
+
* @returns The declared conflicts.
|
|
258
|
+
*/
|
|
259
|
+
protected getPluginConflicts(): PluginConflict[];
|
|
260
|
+
/**
|
|
261
|
+
* Provides the plugins this one cannot work without.
|
|
262
|
+
*
|
|
263
|
+
* Override in subclass to declare a mandatory dependency. The default declares none, and such a plugin
|
|
264
|
+
* loads exactly as it always has.
|
|
265
|
+
*
|
|
266
|
+
* A declared dependency is MANDATORY, unlike the offer `PluginSuggestionComponent` makes: while one is
|
|
267
|
+
* missing, disabled, or too old, {@link onloadImpl} does not run at all and the plugin registers nothing
|
|
268
|
+
* — no commands, no handlers, no patches. It stays enabled in Obsidian's list rather than disabling
|
|
269
|
+
* itself, because the enabled set is the user's to change, and it explains itself through a notice and a
|
|
270
|
+
* settings banner that installs the missing plugin in one click. The load completes the moment the
|
|
271
|
+
* dependency arrives, with no restart.
|
|
272
|
+
*
|
|
273
|
+
* A dependency must publish an API through `publishPluginApi`, which is what makes its presence,
|
|
274
|
+
* absence, version and departure all observable through one mechanism. A plugin with nothing to expose
|
|
275
|
+
* can publish an empty API purely so it can be depended upon.
|
|
276
|
+
*
|
|
277
|
+
* @returns The declared dependencies.
|
|
278
|
+
*/
|
|
279
|
+
protected getPluginDependencies(): PluginDependency[];
|
|
187
280
|
/**
|
|
188
281
|
* Called during {@link onload} to wire plugin-specific child components.
|
|
189
282
|
*
|
|
@@ -204,7 +297,43 @@ export declare abstract class PluginBase extends PluginBase_base implements Plug
|
|
|
204
297
|
* @param key - The key of the component to store.
|
|
205
298
|
* @param value - The component to store.
|
|
206
299
|
*/
|
|
300
|
+
/**
|
|
301
|
+
* Adds a component to the universal tier, which outlives any dependency.
|
|
302
|
+
*
|
|
303
|
+
* Private on purpose: only this class decides what is universal. A subclass adding one of its own goes
|
|
304
|
+
* through {@link addChild} and lands in the gated tier, where it belongs.
|
|
305
|
+
*
|
|
306
|
+
* @typeParam TComponent - The type of component to add.
|
|
307
|
+
* @param component - The component instance to add.
|
|
308
|
+
* @returns The added component.
|
|
309
|
+
*/
|
|
310
|
+
private addUniversalChild;
|
|
311
|
+
/**
|
|
312
|
+
* Announces on `app.workspace` that this plugin is loaded and its APIs are callable.
|
|
313
|
+
*/
|
|
314
|
+
private broadcastLoaded;
|
|
315
|
+
/**
|
|
316
|
+
* Announces on `app.workspace` that this plugin's surface has gone away.
|
|
317
|
+
*
|
|
318
|
+
* Silent unless a loaded broadcast is outstanding, so the two events stay paired: a plugin that never
|
|
319
|
+
* got past its dependency gate never announced itself, and must not announce a departure either.
|
|
320
|
+
*/
|
|
321
|
+
private broadcastUnloaded;
|
|
322
|
+
/**
|
|
323
|
+
* Builds and loads the subclass's feature surface, then publishes its APIs and announces itself.
|
|
324
|
+
*
|
|
325
|
+
* NOT idempotent, deliberately. `PluginGateComponent` owns the up/down state machine and calls
|
|
326
|
+
* this only on a real transition; a second guard here would be a second copy of that state, which is the
|
|
327
|
+
* kind of duplicate that drifts.
|
|
328
|
+
*
|
|
329
|
+
* @returns A {@link Promise} that resolves once the surface is loaded and the broadcast has been made.
|
|
330
|
+
*/
|
|
331
|
+
private loadFeatureSurface;
|
|
207
332
|
private setComponent;
|
|
333
|
+
/**
|
|
334
|
+
* Tears the subclass's feature surface down, leaving the universal components running.
|
|
335
|
+
*/
|
|
336
|
+
private unloadFeatureSurface;
|
|
208
337
|
}
|
|
209
338
|
/**
|
|
210
339
|
* Reloads the specified plugin by disabling and then re-enabling it.
|