diff --git a/src/index.ts b/src/index.ts index 1b34708..1b403df 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,7 +1,7 @@ -import TabManager from "./TabManager"; -import sections from "./sections"; +import TabManager from "./ui/TabManager"; +import sections from "./ui/sections"; import { nextAnimationFrame } from "./utils"; -import { searchBox } from "./search"; +import { searchBox } from "./scripts/search"; // @ts-expect-error: Parcel image import import unknown from "~/assets/images/tab-icons/unknown.svg"; @@ -51,7 +51,7 @@ async function load() { manager.setLoading(false); // Set first page as active - manager.setActive("Guide_to_chemistry"); + manager.setActive("Infections"); }); } if ("serviceWorker" in navigator) { diff --git a/src/darkmode.ts b/src/scripts/darkmode.ts similarity index 100% rename from src/darkmode.ts rename to src/scripts/darkmode.ts diff --git a/src/userscript.ts b/src/scripts/index.ts similarity index 74% rename from src/userscript.ts rename to src/scripts/index.ts index 9eb5214..45daf7b 100644 --- a/src/userscript.ts +++ b/src/scripts/index.ts @@ -1,11 +1,14 @@ import { darken, ColorFmt, lighten } from "./darkmode"; import { registerSearchEntries } from "./search"; import { findParent } from "./utils"; +import chemistryScript from "./pages/chemistry"; // This is used for cache busting when userscript changes significantly. // Only change it when you made changes to the processHTML part! export const CURRENT_VERSION = "bb7abd544a19369d4b6b7e3dde3eb3cc34c023d4"; +const MAX_WIDTH = 440; + function chemistryFixups(root: HTMLElement) { // Fix inconsistencies with

on random parts // Ideally I'd like a

or something on every part, wrapping it completely, but for now let's just kill 'em @@ -246,115 +249,35 @@ export function processHTML(root: HTMLElement, docname: string): void { } } -function chemistryScript(root: HTMLElement) { - // Add event to autofill child checkboxes - root - .querySelectorAll(".bgus_part_tooltip > .bgus_checkbox") - .forEach((box: HTMLInputElement) => { - const tooltip = box.parentElement.nextElementSibling; - box.addEventListener("click", () => { - tooltip - .querySelectorAll(".bgus_checkbox") - .forEach((el: HTMLInputElement) => { - el.checked = box.checked; - }); - }); - }); +function virologyScript(root: HTMLElement): void { + const symptoms = document.querySelector("#Symptoms_Table .wikitable"); + //parseTable(symptoms); +} - // Add event to collapse subsections - root.querySelectorAll(".bgus_nested_element").forEach((twistie) => { - twistie.addEventListener("click", () => { - twistie.classList.toggle("bgus_collapsed"); - }); - }); +// eslint-disable-next-line @typescript-eslint/no-unused-vars +export function postProcessHTML(root: HTMLElement, docname: string): void { + // This should be noop unless we're testing changes before committing them to processHTML + document.querySelectorAll("img[width]").forEach((img) => { + const width = img.getAttribute("width"); - const setPartSize = (labels, ml) => { - labels.forEach((el) => { - const part = el.parentElement.dataset.amount; - const total = el.parentElement.parentElement.dataset.parts; - const amt = Math.ceil(ml * (part / total)); - el.innerHTML = `${amt} ml`; - // Lookup tooltips - let next = el.parentElement.nextElementSibling; - while (next) { - if (next.classList.contains("tooltip")) { - const sublabels = []; - next.querySelector(".tooltiptext").childNodes.forEach((ch) => { - if (ch.classList && ch.classList.contains("bgus_part")) { - sublabels.push(ch.querySelector(".bgus_part_label")); - } - }); - setPartSize(sublabels, amt); - } - if (next.classList.contains("bgus_part")) { - // Done searching - break; - } - next = next.nextElementSibling; - } - }); - }; + // Don't care if they are not absolutely sized + if (width.includes("%")) { + return; + } - // Init fuzzy search with elements - const el = Array.from( - root.querySelectorAll( - "table.wikitable > tbody > tr:not(:first-child) > th" - ) - ); - registerSearchEntries( - el.map((element, id) => ({ - page: "Guide_to_chemistry", - name: element - .querySelector(".reagent-header") - .textContent.trim() - .replace("▮", ""), - element, - alignment: "center", - id, - })) - ); - - document.body.addEventListener("keydown", (ev) => { - if (ev.shiftKey) { - switch (ev.keyCode) { - // SHIFT+C = Toggle checkboxes - case 67: { - root.classList.toggle("bgus_cbox"); - root - .querySelectorAll(".bgus_checkbox:checked") - .forEach((sel: HTMLInputElement) => { - sel.checked = false; - }); - break; - } - - // SHIFT+B = Set whole size (beaker?) for parts/units - case 66: { - const size = parseInt( - prompt("Write target ml (0 to reset)", "90"), - 10 - ); - if (Number.isNaN(size) || size <= 0) { - // Reset to parts/unit - root - .querySelectorAll(".bgus_part_label") - .forEach((sel: HTMLElement) => { - sel.innerHTML = sel.dataset.src; - }); - return; - } - setPartSize( - root.querySelectorAll("td > .bgus_part > .bgus_part_label"), - +size - ); - break; - } - - default: - // Do nothing - } + const widthI = parseInt(width, 10); + if (widthI > MAX_WIDTH) { + img.setAttribute("width", "100%"); + img.removeAttribute("height"); // Remove any height so we don't have to deal with the crazy math } }); + + switch (docname) { + case "Infections": + virologyScript(root); + break; + default: + } } function genericScript(root: HTMLElement, docname: string) { @@ -387,6 +310,7 @@ export function bindFunctions(root: HTMLElement, docname: string): void { export default { CURRENT_VERSION, + postProcessHTML, processHTML, bindFunctions, }; diff --git a/src/scripts/pages/chemistry.ts b/src/scripts/pages/chemistry.ts new file mode 100644 index 0000000..d320c01 --- /dev/null +++ b/src/scripts/pages/chemistry.ts @@ -0,0 +1,112 @@ +import { registerSearchEntries } from "../search"; + +export default function chemistryScript(root: HTMLElement): void { + // Add event to autofill child checkboxes + root + .querySelectorAll(".bgus_part_tooltip > .bgus_checkbox") + .forEach((box: HTMLInputElement) => { + const tooltip = box.parentElement.nextElementSibling; + box.addEventListener("click", () => { + tooltip + .querySelectorAll(".bgus_checkbox") + .forEach((el: HTMLInputElement) => { + el.checked = box.checked; + }); + }); + }); + + // Add event to collapse subsections + root.querySelectorAll(".bgus_nested_element").forEach((twistie) => { + twistie.addEventListener("click", () => { + twistie.classList.toggle("bgus_collapsed"); + }); + }); + + const setPartSize = (labels, ml) => { + labels.forEach((el) => { + const part = el.parentElement.dataset.amount; + const total = el.parentElement.parentElement.dataset.parts; + const amt = Math.ceil(ml * (part / total)); + el.innerHTML = `${amt} ml`; + // Lookup tooltips + let next = el.parentElement.nextElementSibling; + while (next) { + if (next.classList.contains("tooltip")) { + const sublabels = []; + next.querySelector(".tooltiptext").childNodes.forEach((ch) => { + if (ch.classList && ch.classList.contains("bgus_part")) { + sublabels.push(ch.querySelector(".bgus_part_label")); + } + }); + setPartSize(sublabels, amt); + } + if (next.classList.contains("bgus_part")) { + // Done searching + break; + } + next = next.nextElementSibling; + } + }); + }; + + // Init fuzzy search with elements + const el = Array.from( + root.querySelectorAll( + "table.wikitable > tbody > tr:not(:first-child) > th" + ) + ); + registerSearchEntries( + el.map((element, id) => ({ + page: "Guide_to_chemistry", + name: element + .querySelector(".reagent-header") + .textContent.trim() + .replace("▮", ""), + element, + alignment: "center", + id, + })) + ); + + document.body.addEventListener("keydown", (ev) => { + if (ev.shiftKey) { + switch (ev.keyCode) { + // SHIFT+C = Toggle checkboxes + case 67: { + root.classList.toggle("bgus_cbox"); + root + .querySelectorAll(".bgus_checkbox:checked") + .forEach((sel: HTMLInputElement) => { + sel.checked = false; + }); + break; + } + + // SHIFT+B = Set whole size (beaker?) for parts/units + case 66: { + const size = parseInt( + prompt("Write target ml (0 to reset)", "90"), + 10 + ); + if (Number.isNaN(size) || size <= 0) { + // Reset to parts/unit + root + .querySelectorAll(".bgus_part_label") + .forEach((sel: HTMLElement) => { + sel.innerHTML = sel.dataset.src; + }); + return; + } + setPartSize( + root.querySelectorAll("td > .bgus_part > .bgus_part_label"), + +size + ); + break; + } + + default: + // Do nothing + } + } + }); +} diff --git a/src/scripts/pages/virology.ts b/src/scripts/pages/virology.ts new file mode 100644 index 0000000..e69de29 diff --git a/src/search.ts b/src/scripts/search.ts similarity index 98% rename from src/search.ts rename to src/scripts/search.ts index 08489b9..bfee9fb 100644 --- a/src/search.ts +++ b/src/scripts/search.ts @@ -1,5 +1,5 @@ -import { nextAnimationFrame } from "./utils"; -import TabManager from "./TabManager"; +import { nextAnimationFrame } from "../utils"; +import TabManager from "../ui/TabManager"; interface SearchEntry { page: string; diff --git a/src/scripts/utils.ts b/src/scripts/utils.ts new file mode 100644 index 0000000..c51c129 --- /dev/null +++ b/src/scripts/utils.ts @@ -0,0 +1,15 @@ +export function findParent( + base: HTMLElement, + matchFn: (candidate: HTMLElement) => boolean +): HTMLElement | null { + let parent = base.parentElement; + while (parent != null) { + if (matchFn(parent)) { + break; + } + parent = parent.parentElement; + } + return parent; +} + +export default { findParent }; diff --git a/src/TabManager.ts b/src/ui/TabManager.ts similarity index 96% rename from src/TabManager.ts rename to src/ui/TabManager.ts index 0d52e22..99a8b6e 100644 --- a/src/TabManager.ts +++ b/src/ui/TabManager.ts @@ -1,10 +1,14 @@ // @ts-expect-error: Asset imports are handled by parcel import speen from "~/assets/images/speen.svg"; -import { getPageHTML } from "./wiki"; -import { processHTML, bindFunctions, CURRENT_VERSION } from "./userscript"; -import cache from "./cache"; -import { nextAnimationFrame, delay } from "./utils"; -import { TabInfo } from "./sections"; +import { getPageHTML } from "../wiki"; +import { + processHTML, + bindFunctions, + CURRENT_VERSION, + postProcessHTML, +} from "../scripts/index"; +import cache from "../cache"; +import { nextAnimationFrame, delay } from "../utils"; // @ts-expect-error: Parcel image import import unknown from "~/assets/images/tab-icons/unknown.svg"; @@ -76,6 +80,8 @@ async function loadPage(page: string, elem: HTMLElement): Promise { } else { // Set cached content as HTML elem.innerHTML = html; + + postProcessHTML(elem, page); // noop in prod, used in dev for testing candidate DOM changes } bindFunctions(elem, page); diff --git a/src/sections.ts b/src/ui/sections.ts similarity index 100% rename from src/sections.ts rename to src/ui/sections.ts diff --git a/src/utils.ts b/src/utils.ts index 8ca2d74..2dc1240 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -1,17 +1,3 @@ -export function findParent( - base: HTMLElement, - matchFn: (candidate: HTMLElement) => boolean -): HTMLElement | null { - let parent = base.parentElement; - while (parent != null) { - if (matchFn(parent)) { - break; - } - parent = parent.parentElement; - } - return parent; -} - export function nextAnimationFrame(): Promise { return new Promise((resolve) => requestAnimationFrame(() => resolve())); } @@ -22,4 +8,4 @@ export function delay(ms: number): Promise { }); } -export default { findParent, nextAnimationFrame, delay }; +export default { nextAnimationFrame, delay };