single snapshot test
This commit is contained in:
98
dist/bootstrap.js
vendored
Normal file
98
dist/bootstrap.js
vendored
Normal file
@@ -0,0 +1,98 @@
|
||||
export function runtimeBootstrapScript(basePath = "") {
|
||||
return `(() => {
|
||||
const runtime = {
|
||||
basePath: ${JSON.stringify(basePath)},
|
||||
hooks: {},
|
||||
mounts: {},
|
||||
registerMount(pluginId, hookName, mountId, mountFn) {
|
||||
const key = pluginId + ':' + hookName + ':' + mountId;
|
||||
this.mounts[key] = mountFn;
|
||||
},
|
||||
async loadScript(url) {
|
||||
if (document.querySelector('script[data-runtime-src="' + url + '"]')) return;
|
||||
await new Promise((resolve, reject) => {
|
||||
const script = document.createElement('script');
|
||||
script.src = url;
|
||||
script.async = true;
|
||||
script.dataset.runtimeSrc = url;
|
||||
script.onload = () => resolve();
|
||||
script.onerror = reject;
|
||||
document.head.appendChild(script);
|
||||
});
|
||||
},
|
||||
ensureCss(url) {
|
||||
if (!url || document.querySelector('link[data-runtime-css="' + url + '"]')) return;
|
||||
const link = document.createElement('link');
|
||||
link.rel = 'stylesheet';
|
||||
link.href = url;
|
||||
link.dataset.runtimeCss = url;
|
||||
document.head.appendChild(link);
|
||||
},
|
||||
async fetchHooks() {
|
||||
const res = await fetch(this.basePath + '/api/runtime/hooks', { credentials: 'include' });
|
||||
if (!res.ok) throw new Error('hook fetch failed: ' + res.status);
|
||||
const data = await res.json();
|
||||
this.hooks = data.hooks || {};
|
||||
return data;
|
||||
},
|
||||
toolbarAnchor() {
|
||||
return document.querySelector('[data-mailcow-plugin-hook="mail.compose.toolbar"]')
|
||||
|| document.querySelector('.compose-toolbar')
|
||||
|| document.querySelector('[role="toolbar"]')
|
||||
|| document.body;
|
||||
},
|
||||
attachmentsAnchor() {
|
||||
return document.querySelector('[data-mailcow-plugin-hook="mail.compose.attachments"]')
|
||||
|| document.querySelector('.compose-attachments')
|
||||
|| document.querySelector('[data-attachments]')
|
||||
|| document.body;
|
||||
},
|
||||
async mountContribution(contribution) {
|
||||
if (contribution.cssUrl) this.ensureCss(contribution.cssUrl);
|
||||
if (contribution.mountUrl) await this.loadScript(contribution.mountUrl);
|
||||
const key = contribution.pluginId + ':' + contribution.hook + ':' + contribution.id;
|
||||
const mountFn = this.mounts[key];
|
||||
if (!mountFn) return;
|
||||
const parent = contribution.hook === 'mail.compose.attachments' ? this.attachmentsAnchor() : this.toolbarAnchor();
|
||||
let target = parent.querySelector('[data-plugin-target="' + key + '"]');
|
||||
if (!target) {
|
||||
target = document.createElement('div');
|
||||
target.dataset.pluginTarget = key;
|
||||
target.className = 'mailcow-plugin-target';
|
||||
parent.appendChild(target);
|
||||
}
|
||||
const context = {
|
||||
basePath: this.basePath,
|
||||
contribution,
|
||||
hooks: this.hooks,
|
||||
apiBase: contribution.apiBase,
|
||||
uiBase: contribution.uiBase,
|
||||
user: window.MAILCOW_USER || null,
|
||||
};
|
||||
await mountFn(target, context);
|
||||
},
|
||||
async renderHook(hookName) {
|
||||
const list = this.hooks[hookName] || [];
|
||||
for (const contribution of list) {
|
||||
try {
|
||||
await this.mountContribution(contribution);
|
||||
} catch (error) {
|
||||
console.error('Failed to mount contribution', contribution, error);
|
||||
}
|
||||
}
|
||||
},
|
||||
async init() {
|
||||
window.MAILCOW_PLUGIN_RUNTIME = this;
|
||||
await this.fetchHooks();
|
||||
await this.renderHook('mail.compose.toolbar');
|
||||
await this.renderHook('mail.compose.attachments');
|
||||
}
|
||||
};
|
||||
const start = () => runtime.init().catch((err) => console.error('Mailcow plugin runtime bootstrap failed', err));
|
||||
if (document.readyState === 'loading') {
|
||||
document.addEventListener('DOMContentLoaded', start, { once: true });
|
||||
} else {
|
||||
start();
|
||||
}
|
||||
})();`;
|
||||
}
|
||||
Reference in New Issue
Block a user