From fb3d578bc4910ab8b78dacadfb968fbc9b3a30f3 Mon Sep 17 00:00:00 2001 From: Hamcha Date: Wed, 17 Jun 2020 11:43:21 +0200 Subject: [PATCH] Frameworkless achieved! --- index.html | 7 ++- lib/App.tsx | 26 ---------- lib/TabManager.ts | 96 +++++++++++++++++++++++++++++++++++++ lib/components/TabList.tsx | 38 --------------- lib/components/WikiPage.tsx | 62 ------------------------ lib/index.ts | 14 ++++++ lib/index.tsx | 6 --- package.json | 8 +--- style/main.scss | 11 +++-- tsconfig.json | 3 +- yarn.lock | 80 +++---------------------------- 11 files changed, 132 insertions(+), 219 deletions(-) delete mode 100644 lib/App.tsx create mode 100644 lib/TabManager.ts delete mode 100644 lib/components/TabList.tsx delete mode 100644 lib/components/WikiPage.tsx create mode 100644 lib/index.ts delete mode 100644 lib/index.tsx diff --git a/index.html b/index.html index 6cdee54..5ad554f 100644 --- a/index.html +++ b/index.html @@ -12,7 +12,10 @@
-
- +
+ +
+
+ diff --git a/lib/App.tsx b/lib/App.tsx deleted file mode 100644 index 7a7963e..0000000 --- a/lib/App.tsx +++ /dev/null @@ -1,26 +0,0 @@ -import * as React from "react"; -import WikiPage from "./components/WikiPage"; -import TabList, { TabListItem } from "./components/TabList"; -import { useState } from "react"; - -export default function App() { - const [tabs, setTabs] = useState([ - { page: "Guide_to_chemistry" }, - { page: "Guide_to_medicine" }, - ]); - const [activeTab, setActiveTab] = useState(0); - return ( - - setActiveTab(i)} - /> -
- {tabs.map((tab, i) => ( - - ))} -
-
- ); -} diff --git a/lib/TabManager.ts b/lib/TabManager.ts new file mode 100644 index 0000000..b71f112 --- /dev/null +++ b/lib/TabManager.ts @@ -0,0 +1,96 @@ +import speen from "~/assets/images/speen.svg"; +import { getPageHTML } from "./wiki"; +import userscript from "./userscript"; + +function initWaiting(elem: HTMLElement) { + // Add spinner + const spinnerContainer = document.createElement("div"); + spinnerContainer.className = "speen"; + const spinnerImg = document.createElement("img"); + spinnerImg.src = speen; + spinnerContainer.appendChild(spinnerImg); + const spinnerText = document.createElement("p"); + spinnerText.appendChild( + document.createTextNode("You start skimming through the manual...") + ); + spinnerContainer.appendChild(spinnerText); + elem.appendChild(spinnerContainer); +} + +async function loadPage(page: string, elem: HTMLElement) { + console.log(page + ": fetching"); + let html = await getPageHTML(page); + // Convert relative links to absolute + html = html.replace(/"\/wiki/gi, '"//tgstation13.org/wiki'); + elem.innerHTML = html; + console.log(page + ": processing"); + userscript(elem, page); + console.log(page + ": userscript applied"); + elem.classList.remove("waiting"); +} + +type TabElements = { tabListItem: HTMLElement; tabContentItem: HTMLElement }; + +export default class TabManager { + tabListContainer: HTMLElement; + tabContentContainer: HTMLElement; + tabs: Record = {}; + + constructor(tablist: HTMLElement, tabcontent: HTMLElement) { + this.tabListContainer = tablist; + this.tabContentContainer = tabcontent; + } + + openTab(page: string, setActive: boolean) { + // Create tab list item + const tabListItem = document.createElement("div"); + tabListItem.className = "tab"; + tabListItem.dataset.tab = page; + tabListItem.addEventListener("click", () => { + if (tabListItem.classList.contains("active")) { + return; + } + this.setActive(page); + }); + tabListItem.appendChild(document.createTextNode(page.replace(/_/gi, " "))); + this.tabListContainer.appendChild(tabListItem); + + // Create tab content container + const tabContentItem = document.createElement("div"); + tabContentItem.className = "page waiting"; + tabContentItem.dataset.tab = page; + initWaiting(tabContentItem); + this.tabContentContainer.appendChild(tabContentItem); + + // Start loading page for new tab + loadPage(page, tabContentItem); + + // Create tab entry + this.tabs[page] = { tabListItem, tabContentItem }; + + // If asked for, set it to active + if (setActive) { + this.setActive(page); + } + } + + setActive(page: string) { + // Make sure tab exists (why wouldn't it?!) + if (!(page in this.tabs)) { + throw new Error("tab not found"); + } + + // Deactivate current active tab + this.tabListContainer + .querySelectorAll(".active") + .forEach((it) => it.classList.remove("active")); + this.tabContentContainer + .querySelectorAll(".active") + .forEach((it) => it.classList.remove("active")); + + // Activate new tab + const { tabListItem, tabContentItem } = this.tabs[page]; + tabListItem.classList.add("active"); + tabContentItem.classList.add("active"); + } +} diff --git a/lib/components/TabList.tsx b/lib/components/TabList.tsx deleted file mode 100644 index 3b077ed..0000000 --- a/lib/components/TabList.tsx +++ /dev/null @@ -1,38 +0,0 @@ -import * as React from "react"; - -export interface TabListItem { - page: string; -} - -export interface TabListProps { - tabs: TabListItem[]; - active: number; - tabClicked: (TabListItem, number) => void; -} - -function TabItem({ name, active, onClick }) { - const clickHandler = active ? null : onClick; - return ( -
- {name.replace(/_/gi, " ")} -
- ); -} - -export default function TabList({ tabs, active, tabClicked }: TabListProps) { - return ( - - ); -} diff --git a/lib/components/WikiPage.tsx b/lib/components/WikiPage.tsx deleted file mode 100644 index bdf479d..0000000 --- a/lib/components/WikiPage.tsx +++ /dev/null @@ -1,62 +0,0 @@ -import { getPageHTML } from "../wiki"; -import { darken, ColorFmt, lighten } from "../darkmode"; -import * as React from "react"; -import { useState, useEffect, useRef } from "react"; -import userscript from "../userscript"; -import speen from "~/assets/images/speen.svg"; - -export default function WikiPage({ page, visible }) { - const [data, setData] = useState({ - loaded: false, - processed: false, - html: "", - }); - const containerRef = useRef(null); - - // Fetch page - useEffect(() => { - console.log(page + ": fetching"); - (async () => { - let html = await getPageHTML(page); - // Convert relative links to absolute - html = html.replace(/"\/wiki/gi, '"//tgstation13.org/wiki'); - setData({ loaded: true, processed: false, html }); - })(); - }, []); - - // Process page - useEffect(() => { - console.log(page + ": processing"); - if (data.loaded == true && data.processed == false) { - userscript(containerRef.current, page); - console.log(page + ": userscript applied"); - } - }, [data]); - - if (!data.loaded) { - return ( -
-
- -

You start skimming through the manual...

-
-
- ); - } else { - return ( -
- ); - } -} diff --git a/lib/index.ts b/lib/index.ts new file mode 100644 index 0000000..1ed2daa --- /dev/null +++ b/lib/index.ts @@ -0,0 +1,14 @@ +import TabManager from "./TabManager"; + +const tabListContainer = document.getElementById("tab-list"); +const tabContentContainer = document.getElementById("tabs"); +const manager = new TabManager(tabListContainer, tabContentContainer); + +const defaultTabs = [ + { page: "Guide_to_chemistry", active: true }, + { page: "Guide_to_medicine", active: false }, +]; + +defaultTabs.forEach((tab) => { + manager.openTab(tab.page, tab.active); +}); diff --git a/lib/index.tsx b/lib/index.tsx deleted file mode 100644 index 498e8b6..0000000 --- a/lib/index.tsx +++ /dev/null @@ -1,6 +0,0 @@ -import * as React from "react"; -import * as ReactDOM from "react-dom"; -import App from "./App"; - -const main = document.getElementById("app"); -ReactDOM.render(, main); diff --git a/package.json b/package.json index 4feec92..88e75b0 100644 --- a/package.json +++ b/package.json @@ -7,17 +7,11 @@ "dev": "parcel index.html", "build": "parcel build index.html" }, - "devDependencies": { + "dependencies": { "parcel-bundler": "^1.12.4", "sass": "^1.26.8", "typescript": "^3.9.5" }, - "dependencies": { - "@types/react": "^16.9.36", - "@types/react-dom": "^16.9.8", - "react": "^16.13.1", - "react-dom": "^16.13.1" - }, "browserslist": [ "last 2 Chrome versions", "last 2 Firefox versions" diff --git a/style/main.scss b/style/main.scss index 99aa6e1..2a482cc 100644 --- a/style/main.scss +++ b/style/main.scss @@ -71,11 +71,16 @@ body { display: grid; overflow: hidden; .page { + visibility: hidden; padding-top: 10pt; overflow-y: scroll; grid-row: 1; grid-column: 1; + &.active { + visibility: visible; + } &.waiting { + user-select: none; position: fixed; top: 0; left: 0; @@ -130,8 +135,8 @@ body { $tab-active: lighten($nanotrasen, 10%); -.tab-list { - z-index: 1; +#tab-list { + z-index: 2; grid-row: 1; display: flex; border-bottom: 2px solid $tab-active; @@ -147,7 +152,7 @@ $tab-active: lighten($nanotrasen, 10%); &.active { background-color: $tab-active; } - &.clickable { + &:not(.active) { cursor: pointer; } } diff --git a/tsconfig.json b/tsconfig.json index 2dc8fcc..bd4d686 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,6 +1,5 @@ { "compilerOptions": { - "target": "ES2020", - "jsx": "react" + "target": "ES2020" } } diff --git a/yarn.lock b/yarn.lock index 01d77ca..8098a03 100644 --- a/yarn.lock +++ b/yarn.lock @@ -897,31 +897,11 @@ "@parcel/utils" "^1.11.0" physical-cpu-count "^2.0.0" -"@types/prop-types@*": - version "15.7.3" - resolved "https://registry.yarnpkg.com/@types/prop-types/-/prop-types-15.7.3.tgz#2ab0d5da2e5815f94b0b9d4b95d1e5f243ab2ca7" - integrity sha512-KfRL3PuHmqQLOG+2tGpRO26Ctg+Cq1E01D2DMriKEATHgWLfeNDmq9e29Q9WIky0dQ3NPkd1mzYH8Lm936Z9qw== - "@types/q@^1.5.1": version "1.5.4" resolved "https://registry.yarnpkg.com/@types/q/-/q-1.5.4.tgz#15925414e0ad2cd765bfef58842f7e26a7accb24" integrity sha512-1HcDas8SEj4z1Wc696tH56G8OlRaH/sqZOynNNB+HF0WOeXPaxTtbYzJY2oEfiUxjSKjhCKr+MvR7dCHcEelug== -"@types/react-dom@^16.9.8": - version "16.9.8" - resolved "https://registry.yarnpkg.com/@types/react-dom/-/react-dom-16.9.8.tgz#fe4c1e11dfc67155733dfa6aa65108b4971cb423" - integrity sha512-ykkPQ+5nFknnlU6lDd947WbQ6TE3NNzbQAkInC2EKY1qeYdTKp7onFusmYZb+ityzx2YviqT6BXSu+LyWWJwcA== - dependencies: - "@types/react" "*" - -"@types/react@*", "@types/react@^16.9.36": - version "16.9.36" - resolved "https://registry.yarnpkg.com/@types/react/-/react-16.9.36.tgz#ade589ff51e2a903e34ee4669e05dbfa0c1ce849" - integrity sha512-mGgUb/Rk/vGx4NCvquRuSH0GHBQKb1OqpGS9cT9lFxlTLHZgkksgI60TuIxubmn7JuCb+sENHhQciqa0npm0AQ== - dependencies: - "@types/prop-types" "*" - csstype "^2.2.0" - abab@^2.0.0: version "2.0.3" resolved "https://registry.yarnpkg.com/abab/-/abab-2.0.3.tgz#623e2075e02eb2d3f2475e49f99c91846467907a" @@ -1883,11 +1863,6 @@ cssstyle@^1.1.1: dependencies: cssom "0.3.x" -csstype@^2.2.0: - version "2.6.10" - resolved "https://registry.yarnpkg.com/csstype/-/csstype-2.6.10.tgz#e63af50e66d7c266edb6b32909cfd0aabe03928b" - integrity sha512-D34BqZU4cIlMCY93rZHbrq9pjTAQJ3U8S8rfBqjwHxkGPThWFjzZDQpgMJY0QViLxth6ZKYiwFBo14RdN44U/w== - dashdash@^1.12.0: version "1.14.1" resolved "https://registry.yarnpkg.com/dashdash/-/dashdash-1.14.1.tgz#853cfa0f7cbe2fed5de20326b8dd581035f6e2f0" @@ -2092,9 +2067,9 @@ ee-first@1.1.1: integrity sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0= electron-to-chromium@^1.3.413: - version "1.3.474" - resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.474.tgz#161af012e11f96795eade84bf03b8ddc039621b9" - integrity sha512-fPkSgT9IBKmVJz02XioNsIpg0WYmkPrvU1lUJblMMJALxyE7/32NGvbJQKKxpNokozPvqfqkuUqVClYsvetcLw== + version "1.3.475" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.475.tgz#67688cc82c342f39594a412286e975eda45d8412" + integrity sha512-vcTeLpPm4+ccoYFXnepvkFt0KujdyrBU19KNEO40Pnkhta6mUi2K0Dn7NmpRcNz7BvysnSqeuIYScP003HWuYg== elliptic@^6.0.0, elliptic@^6.5.2: version "6.5.2" @@ -3210,7 +3185,7 @@ log-symbols@^2.2.0: dependencies: chalk "^2.0.1" -loose-envify@^1.0.0, loose-envify@^1.1.0, loose-envify@^1.4.0: +loose-envify@^1.0.0: version "1.4.0" resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf" integrity sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q== @@ -4208,15 +4183,6 @@ process@^0.11.10: resolved "https://registry.yarnpkg.com/process/-/process-0.11.10.tgz#7332300e840161bda3e69a1d1d91a7d4bc16f182" integrity sha1-czIwDoQBYb2j5podHZGn1LwW8YI= -prop-types@^15.6.2: - version "15.7.2" - resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.7.2.tgz#52c41e75b8c87e72b9d9360e0206b99dcbffa6c5" - integrity sha512-8QQikdH7//R2vurIJSutZ1smHYTcLpRWEOlHnzcWHmBYrOGUysKwSsrC89BCiFj3CbrfJ/nXFdJepOVrY1GCHQ== - dependencies: - loose-envify "^1.4.0" - object-assign "^4.1.1" - react-is "^16.8.1" - psl@^1.1.28: version "1.8.0" resolved "https://registry.yarnpkg.com/psl/-/psl-1.8.0.tgz#9326f8bcfb013adcc005fdff056acce020e51c24" @@ -4308,30 +4274,6 @@ range-parser@~1.2.1: resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.1.tgz#3cf37023d199e1c24d1a55b84800c2f3e6468031" integrity sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg== -react-dom@^16.13.1: - version "16.13.1" - resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-16.13.1.tgz#c1bd37331a0486c078ee54c4740720993b2e0e7f" - integrity sha512-81PIMmVLnCNLO/fFOQxdQkvEq/+Hfpv24XNJfpyZhTRfO0QcmQIF/PgCa1zCOj2w1hrn12MFLyaJ/G0+Mxtfag== - dependencies: - loose-envify "^1.1.0" - object-assign "^4.1.1" - prop-types "^15.6.2" - scheduler "^0.19.1" - -react-is@^16.8.1: - version "16.13.1" - resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4" - integrity sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ== - -react@^16.13.1: - version "16.13.1" - resolved "https://registry.yarnpkg.com/react/-/react-16.13.1.tgz#2e818822f1a9743122c063d6410d85c1e3afe48e" - integrity sha512-YMZQQq32xHLX0bz5Mnibv1/LHb3Sqzngu7xstSM+vrkE5Kzr9xE0yMByK5kMoTK30YVJE61WfbxIFFvfeDKT1w== - dependencies: - loose-envify "^1.1.0" - object-assign "^4.1.1" - prop-types "^15.6.2" - readable-stream@^2.0.2, readable-stream@^2.2.2, readable-stream@^2.3.3, readable-stream@^2.3.6, readable-stream@~2.3.3, readable-stream@~2.3.6: version "2.3.7" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.7.tgz#1eca1cf711aef814c04f62252a36a62f6cb23b57" @@ -4595,14 +4537,6 @@ saxes@^3.1.9: dependencies: xmlchars "^2.1.1" -scheduler@^0.19.1: - version "0.19.1" - resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.19.1.tgz#4f3e2ed2c1a7d65681f4c854fa8c5a1ccb40f196" - integrity sha512-n/zwRWRYSUj0/3g/otKDRPMh6qv2SYMWNq85IEa8iZyAv8od9zDYpGSnpBEjNgcMNq6Scbu5KfIPxNF72R/2EA== - dependencies: - loose-envify "^1.1.0" - object-assign "^4.1.1" - semver@7.0.0: version "7.0.0" resolved "https://registry.yarnpkg.com/semver/-/semver-7.0.0.tgz#5f3ca35761e47e05b206c6daff2cf814f0316b8e" @@ -4998,9 +4932,9 @@ terser@^3.7.3: source-map-support "~0.5.10" terser@^4.3.9: - version "4.7.0" - resolved "https://registry.yarnpkg.com/terser/-/terser-4.7.0.tgz#15852cf1a08e3256a80428e865a2fa893ffba006" - integrity sha512-Lfb0RiZcjRDXCC3OSHJpEkxJ9Qeqs6mp2v4jf2MHfy8vGERmVDuvjXdd/EnP5Deme5F2yBRBymKmKHCBg2echw== + version "4.8.0" + resolved "https://registry.yarnpkg.com/terser/-/terser-4.8.0.tgz#63056343d7c70bb29f3af665865a46fe03a0df17" + integrity sha512-EAPipTNeWsb/3wLPeup1tVPaXfIaU68xMnVdPafIL1TV05OhASArYyIfFvnvJCNrR2NIOvDVNNTFRa+Re2MWyw== dependencies: commander "^2.20.0" source-map "~0.6.1"