SharedDocsLib/docslib/templates/loader.js

89 lines
3 KiB
JavaScript

(() => {
"use strict";
const embedded = JSON.parse(document.getElementById("docslib-manifest").textContent);
const config = JSON.parse(document.getElementById("docslib-config").textContent);
const loading = document.getElementById("docslib-loading");
const loaderStyle = document.getElementById("docslib-loader-style");
function isManifest(value) {
return Boolean(
value &&
value.schema_version >= 2 &&
Array.isArray(value.pages) &&
value.client &&
value.client.css &&
typeof value.client.css.system === "string" &&
value.client.js &&
typeof value.client.js.system === "string"
);
}
const dbPromise = new Promise((resolve, reject) => {
if (!window.indexedDB) return reject(new Error("IndexedDB"));
const request = indexedDB.open("docslib-cache", 1);
request.onupgradeneeded = () => {
if (!request.result.objectStoreNames.contains("manifests")) {
request.result.createObjectStore("manifests");
}
};
request.onsuccess = () => resolve(request.result);
request.onerror = () => reject(request.error);
});
async function cacheGet() {
const db = await dbPromise;
return new Promise((resolve, reject) => {
const request = db.transaction("manifests", "readonly").objectStore("manifests").get(config.cacheKey);
request.onsuccess = () => resolve(request.result);
request.onerror = () => reject(request.error);
});
}
async function cachePut(value) {
const db = await dbPromise;
return new Promise((resolve, reject) => {
const transaction = db.transaction("manifests", "readwrite");
transaction.objectStore("manifests").put(value, config.cacheKey);
transaction.oncomplete = resolve;
transaction.onerror = () => reject(transaction.error);
});
}
async function selectManifest() {
try {
const cached = await cacheGet();
if (isManifest(cached) && cached.schema_version === embedded.schema_version) {
return cached;
}
await cachePut(embedded);
} catch (_) { /* IndexedDB is unavailable; use the embedded manifest */ }
return embedded;
}
function applyRuntime(manifest) {
const style = document.createElement("style");
style.id = "docslib-runtime-style";
style.textContent = [manifest.client.css.system, manifest.client.css.custom || ""].join("\n");
document.head.append(style);
window.__DOCSLIB_MANIFEST__ = manifest;
window.__DOCSLIB_CONFIG__ = config;
const script = document.createElement("script");
script.id = "docslib-runtime-script";
script.textContent = `${manifest.client.js.system}\n//# sourceURL=docslib-client.js`;
document.body.append(script);
}
document.addEventListener("docslib:rendered", () => {
loading?.remove();
loaderStyle?.remove();
}, { once: true });
selectManifest()
.then((manifest) => {
if (!isManifest(manifest)) throw new Error("manifest");
applyRuntime(manifest);
})
.catch((error) => console.error("SharedDocsLib", error));
})();