fix: fix minor bug 404 every page lmao)

This commit is contained in:
2026-08-24 13:33:52 +09:30
parent 6688a53acc
commit a411d646ae
4 changed files with 47 additions and 25 deletions
+6 -10
View File
@@ -141,11 +141,6 @@ async function init() {
} }
} }
function shouldBootKitten404(): boolean {
if (IsSEQTAPage || document.getElementById("container")) return false;
return /404|not found/i.test(document.title);
}
/** Hide the rebranded 404 before the kitten card mounts (removed after boot). */ /** Hide the rebranded 404 before the kitten card mounts (removed after boot). */
function inject404FlashHide(): void { function inject404FlashHide(): void {
if (document.getElementById("bsplus-404-flash-hide")) return; if (document.getElementById("bsplus-404-flash-hide")) return;
@@ -159,13 +154,17 @@ function inject404FlashHide(): void {
async function bootErrorPage() { async function bootErrorPage() {
if (IsSEQTAPage) return; if (IsSEQTAPage) return;
const { isSeqta404Page, mountErrorPageKitten } = await import(
"@/plugins/built-in/errorPageKitten"
);
const storagePromise = browser.storage.local.get([ const storagePromise = browser.storage.local.get([
"onoff", "onoff",
"plugin.error-page-kitten.settings", "plugin.error-page-kitten.settings",
]); ]);
const watchTitle = () => { const watchTitle = () => {
if (shouldBootKitten404()) inject404FlashHide(); if (isSeqta404Page()) inject404FlashHide();
}; };
watchTitle(); watchTitle();
if (document.readyState === "loading") { if (document.readyState === "loading") {
@@ -179,7 +178,7 @@ async function bootErrorPage() {
} }
document.removeEventListener("readystatechange", watchTitle); document.removeEventListener("readystatechange", watchTitle);
if (!shouldBootKitten404()) return; if (!isSeqta404Page()) return;
const stored = await storagePromise; const stored = await storagePromise;
if ((stored.onoff ?? true) === false) return; if ((stored.onoff ?? true) === false) return;
@@ -189,9 +188,6 @@ async function bootErrorPage() {
if (kittenSettings?.enabled === false) return; if (kittenSettings?.enabled === false) return;
try { try {
const { mountErrorPageKitten } = await import(
"@/plugins/built-in/errorPageKitten"
);
mountErrorPageKitten(); mountErrorPageKitten();
document.getElementById("bsplus-404-flash-hide")?.remove(); document.getElementById("bsplus-404-flash-hide")?.remove();
} catch (error) { } catch (error) {
@@ -2,8 +2,6 @@
* @jest-environment jsdom * @jest-environment jsdom
*/ */
/// <reference types="jest" /> /// <reference types="jest" />
import type { PluginAPI } from "@/plugins/core/types";
jest.mock("@/lib/extensionAssetUrl", () => ({ jest.mock("@/lib/extensionAssetUrl", () => ({
resolveExtensionAssetUrl: (url: string) => resolveExtensionAssetUrl: (url: string) =>
`chrome-extension://test/${String(url).replace(/^\/+/, "")}`, `chrome-extension://test/${String(url).replace(/^\/+/, "")}`,
@@ -17,7 +15,10 @@ jest.mock("./styles.css?inline", () => ({
default: "/* test */", default: "/* test */",
})); }));
import { mountErrorPageKitten } from "./index"; import errorPageKittenPlugin, {
isSeqta404Page,
mountErrorPageKitten,
} from "./index";
const REBRANDED_404_BODY = ` const REBRANDED_404_BODY = `
<div class="message"> <div class="message">
@@ -43,18 +44,33 @@ describe("errorPageKitten", () => {
const cleanup = mountErrorPageKitten(); const cleanup = mountErrorPageKitten();
const card = getCard(); expect(getCard()).not.toBeNull();
expect(card).not.toBeNull();
expect(document.documentElement.classList).toContain("bsplus-kitten-404"); expect(document.documentElement.classList).toContain("bsplus-kitten-404");
expect(card?.querySelector("h1")?.textContent).toBe("404 Not Found");
expect(document.title).toBe("404 Not Found");
expect(card?.querySelector(".kitten img")?.getAttribute("src")).toContain("kitten");
expect(
document.querySelector(".message")?.classList.contains("bsplus-kitten-404-hidden"),
).toBe(true);
cleanup(); cleanup();
expect(getCard()).toBeNull(); expect(getCard()).toBeNull();
expect(document.title).toBe("Page not found"); });
it("detects standalone 404 pages by .message and title", () => {
document.title = "Page not found";
document.body.innerHTML = REBRANDED_404_BODY;
expect(isSeqta404Page()).toBe(true);
});
it("does not detect the SPA", () => {
document.title = "SEQTA Learn";
document.body.innerHTML = '<div id="container"></div>';
expect(isSeqta404Page()).toBe(false);
});
it("plugin run is a no-op outside a 404 page", async () => {
document.title = "SEQTA Learn";
document.body.innerHTML = '<div id="container"></div>';
const cleanup = await errorPageKittenPlugin.run();
expect(getCard()).toBeNull();
expect(cleanup).toBeDefined();
cleanup?.();
}); });
}); });
@@ -16,7 +16,14 @@ const CARD_HTML = `<h1>404 Not Found</h1>
</div> </div>
<a href="http://www.seqta.com.au">SEQTA</a>`; <a href="http://www.seqta.com.au">SEQTA</a>`;
/** Boot path in SEQTA.ts gates when this runs; keep render-only here. */ /** Standalone SEQTA 404 document — not the SPA (#container). */
export function isSeqta404Page(): boolean {
if (document.getElementById("container")) return false;
const heading = document.querySelector(".message > h1");
const text = heading?.textContent ?? document.title;
return /not found/i.test(text) || /404/.test(document.title);
}
export function mountErrorPageKitten(): () => void { export function mountErrorPageKitten(): () => void {
const styleEl = document.createElement("style"); const styleEl = document.createElement("style");
styleEl.textContent = styles; styleEl.textContent = styles;
@@ -52,7 +59,7 @@ const errorPageKittenPlugin: Plugin = {
disableToggle: true, disableToggle: true,
defaultEnabled: true, defaultEnabled: true,
styles, styles,
run: async () => mountErrorPageKitten(), run: async () => (isSeqta404Page() ? mountErrorPageKitten() : () => {}),
}; };
export default errorPageKittenPlugin; export default errorPageKittenPlugin;
+4 -1
View File
@@ -43,6 +43,9 @@ const PLUGIN_START_PHASES: readonly string[][] = [
["global-search"], ["global-search"],
]; ];
/** Booted only from SEQTA.ts on standalone 404 documents — never auto-start in the SPA. */
const PLUGIN_BOOT_ONLY_IDS = new Set(["error-page-kitten"]);
/** /**
* Singleton class responsible for the entire lifecycle of plugins. * Singleton class responsible for the entire lifecycle of plugins.
* This includes registration, starting, stopping, event dispatching, * This includes registration, starting, stopping, event dispatching,
@@ -263,7 +266,7 @@ export class PluginManager {
const phasedIds = new Set(PLUGIN_START_PHASES.flat()); const phasedIds = new Set(PLUGIN_START_PHASES.flat());
const remainingIds = Array.from(this.plugins.keys()).filter( const remainingIds = Array.from(this.plugins.keys()).filter(
(id) => !phasedIds.has(id), (id) => !phasedIds.has(id) && !PLUGIN_BOOT_ONLY_IDS.has(id),
); );
if (remainingIds.length > 0) { if (remainingIds.length > 0) {
await this.startPluginPhase(remainingIds); await this.startPluginPhase(remainingIds);