Files
BetterSEQTA-Plus/src/seqta/utils/patchThemeImagesPageContext.ts
T
AdenMGB 4fda63dedd refactor: trim PR debloat and fix transformers build
Extract shared helpers for home notices, timetable subtitles, and theme images; dedupe global search, Select, and build scripts while preserving behaviour.

Add @huggingface/transformers as a direct dependency and resolve ORT WASM paths via require.resolve so pnpm postinstall and Vite can bundle vector search.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-28 10:30:25 +09:30

85 lines
2.8 KiB
TypeScript

/**
* Bridge theme CSS and decorative images into PAGE JavaScript context.
*/
import patchScript from "@/seqta/utils/themeImagePagePatch.js?url";
import { resolveExtensionAssetUrl } from "@/lib/extensionAssetUrl";
import { blobToBase64Data } from "@/plugins/built-in/themes/themeImageUrl";
const PAGE_PATCH_LOADER_ID = "bsplus-theme-image-page-patch-loader";
const BRIDGE_ID = "bsplus-theme-image-bridge";
const PAYLOAD_ID = "bsplus-theme-image-payload";
export type ThemePageSyncInput = {
images?: Array<{ variableName: string; blob: Blob }>;
customCss?: string;
previewCss?: string;
clear?: boolean;
clearPreview?: boolean;
};
export function installThemeImagePagePatch(): void {
if (document.getElementById(PAGE_PATCH_LOADER_ID)) return;
const script = document.createElement("script");
script.id = PAGE_PATCH_LOADER_ID;
script.src = resolveExtensionAssetUrl(patchScript);
script.addEventListener("load", () => script.remove());
(document.documentElement || document.head).appendChild(script);
}
function ensureBridgeElements(): void {
if (!document.getElementById(PAYLOAD_ID)) {
const payload = document.createElement("textarea");
payload.id = PAYLOAD_ID;
payload.hidden = true;
payload.setAttribute("aria-hidden", "true");
payload.tabIndex = -1;
document.documentElement.appendChild(payload);
}
if (!document.getElementById(BRIDGE_ID)) {
const bridge = document.createElement("div");
bridge.id = BRIDGE_ID;
bridge.hidden = true;
bridge.setAttribute("aria-hidden", "true");
document.documentElement.appendChild(bridge);
}
}
function sendPayload(payload: Record<string, unknown>): void {
installThemeImagePagePatch();
ensureBridgeElements();
const payloadEl = document.getElementById(PAYLOAD_ID) as HTMLTextAreaElement;
payloadEl.value = JSON.stringify(payload);
const bridge = document.getElementById(BRIDGE_ID)!;
bridge.setAttribute("data-rev", String(Number(bridge.getAttribute("data-rev") || "0") + 1));
}
export async function syncThemeToPage(input: ThemePageSyncInput): Promise<void> {
if (input.clear) {
sendPayload({ clear: true });
return;
}
const payload: Record<string, unknown> = {};
if (input.clearPreview) payload.clearPreview = true;
if (input.customCss !== undefined) payload.customCss = input.customCss;
if (input.previewCss !== undefined) payload.previewCss = input.previewCss;
if (input.images !== undefined) {
payload.images = await Promise.all(
input.images.map(async (image) => ({
variableName: image.variableName,
data: await blobToBase64Data(image.blob),
mime: image.blob.type || "image/png",
})),
);
}
if (Object.keys(payload).length === 0) return;
sendPayload(payload);
}
export function clearThemeInPage(): void {
sendPayload({ clear: true });
}