Compare commits
4 commits
85211e22d6
...
8bfbdd9f26
Author | SHA1 | Date | |
---|---|---|---|
8bfbdd9f26 | |||
4b5d36292b | |||
4198faa4b7 | |||
32c69ee4ca |
12 changed files with 349 additions and 59 deletions
22
.drone.yml
22
.drone.yml
|
@ -53,18 +53,16 @@ steps:
|
||||||
depends_on:
|
depends_on:
|
||||||
- dependencies
|
- dependencies
|
||||||
|
|
||||||
- name: build_master
|
- name: build_branch
|
||||||
image: node
|
image: node
|
||||||
commands:
|
commands:
|
||||||
- yarn build
|
- yarn build
|
||||||
environment:
|
environment:
|
||||||
SUBPATH: /tghandbook/latest
|
SUBPATH: /tghandbook/${DRONE_COMMIT_BRANCH/\//_}
|
||||||
OUTDIR: ./dist-master
|
OUTDIR: ./dist-branch
|
||||||
when:
|
when:
|
||||||
event:
|
event:
|
||||||
- push
|
- push
|
||||||
branch:
|
|
||||||
- master
|
|
||||||
depends_on:
|
depends_on:
|
||||||
- dependencies
|
- dependencies
|
||||||
|
|
||||||
|
@ -106,7 +104,7 @@ steps:
|
||||||
depends_on:
|
depends_on:
|
||||||
- build_pr
|
- build_pr
|
||||||
|
|
||||||
- name: upload_build_master
|
- name: upload_build_branch
|
||||||
image: plugins/s3
|
image: plugins/s3
|
||||||
settings:
|
settings:
|
||||||
bucket: tghandbook
|
bucket: tghandbook
|
||||||
|
@ -114,18 +112,16 @@ steps:
|
||||||
from_secret: minio_access
|
from_secret: minio_access
|
||||||
secret_key:
|
secret_key:
|
||||||
from_secret: minio_secret
|
from_secret: minio_secret
|
||||||
source: dist-master/**/*
|
source: dist-branch/**/*
|
||||||
target: /latest/
|
target: /${DRONE_COMMIT_BRANCH/\//_}/
|
||||||
strip_prefix: dist-master/
|
strip_prefix: dist-branch/
|
||||||
path_style: true
|
path_style: true
|
||||||
endpoint: https://artifacts.fromouter.space
|
endpoint: https://artifacts.fromouter.space
|
||||||
when:
|
when:
|
||||||
event:
|
event:
|
||||||
- push
|
- push
|
||||||
branch:
|
|
||||||
- master
|
|
||||||
depends_on:
|
depends_on:
|
||||||
- build_master
|
- build_branch
|
||||||
|
|
||||||
- name: rebuild-cache
|
- name: rebuild-cache
|
||||||
image: drillster/drone-volume-cache
|
image: drillster/drone-volume-cache
|
||||||
|
@ -146,4 +142,4 @@ volumes:
|
||||||
path: /opt/gitea/drone-cache/hamcha/tghandbook
|
path: /opt/gitea/drone-cache/hamcha/tghandbook
|
||||||
---
|
---
|
||||||
kind: signature
|
kind: signature
|
||||||
hmac: 9f4b08596bdaa078a6c60fc63d932084bab117c340a310903bbe96f31c0122bb
|
hmac: de6248685716ee52a8de5686a13b1ce209a84046fb278e20115738516ee7335c
|
||||||
|
|
5
assets/images/tab-icons/chemistry.svg
Normal file
5
assets/images/tab-icons/chemistry.svg
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||||
|
<svg width="100%" height="100%" viewBox="0 0 32 32" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2;">
|
||||||
|
<path d="M12.011,14.392L12.011,3.941C12.011,3.55 12.166,3.174 12.443,2.897C12.72,2.62 13.095,2.465 13.487,2.465L18.654,2.465C19.045,2.465 19.421,2.62 19.698,2.897C19.974,3.174 20.13,3.55 20.13,3.941L20.13,14.392L25.938,24.999C26.458,25.948 26.439,27.101 25.887,28.033C25.335,28.964 24.333,29.535 23.251,29.535L8.89,29.535C7.808,29.535 6.805,28.964 6.254,28.033C5.702,27.101 5.682,25.948 6.202,24.999L12.011,14.392ZM18.13,4.465L14.011,4.465L14.011,14.648C14.011,14.816 13.968,14.981 13.888,15.128C13.888,15.128 10.195,21.871 7.956,25.959C7.776,26.289 7.783,26.69 7.974,27.013C8.166,27.337 8.514,27.535 8.89,27.535L23.251,27.535C23.627,27.535 23.975,27.337 24.166,27.013C24.358,26.69 24.365,26.289 24.184,25.959C21.945,21.871 18.253,15.128 18.253,15.128C18.172,14.981 18.13,14.816 18.13,14.648L18.13,4.465ZM15.452,18.07L19.028,18.07C19.028,18.07 21.911,23.671 23.014,25.813C23.103,25.987 23.096,26.195 22.994,26.363C22.892,26.53 22.71,26.632 22.514,26.632L9.627,26.632C9.431,26.632 9.249,26.53 9.147,26.363C9.045,26.195 9.037,25.987 9.127,25.813C10.229,23.671 13.113,18.07 13.113,18.07L14.328,18.07L11.138,24.285C11.012,24.53 11.109,24.832 11.354,24.958C11.6,25.084 11.901,24.987 12.027,24.741L15.452,18.07Z" style="fill:white;"/>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 1.6 KiB |
13
assets/images/tab-icons/unknown.svg
Normal file
13
assets/images/tab-icons/unknown.svg
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||||
|
<svg width="100%" height="100%" viewBox="0 0 32 32" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:1.5;">
|
||||||
|
<g transform="matrix(1,0,0,1,-32,0)">
|
||||||
|
<path d="M59.485,9.925C59.485,6.912 57.039,4.465 54.025,4.465L43.105,4.465C40.091,4.465 37.644,6.912 37.644,9.925L37.644,22.075C37.644,25.088 40.091,27.535 43.105,27.535L54.025,27.535C57.039,27.535 59.485,25.088 59.485,22.075L59.485,9.925Z" style="fill:none;stroke:white;stroke-width:3px;"/>
|
||||||
|
<g transform="matrix(0.865715,0.145428,-0.145428,0.865715,8.58626,-7.33972)">
|
||||||
|
<path d="M44.849,14.354C44.849,12.303 46.514,10.638 48.565,10.638C50.616,10.638 52.281,12.303 52.281,14.354C52.281,16.405 50.616,18.07 48.565,18.07C47.395,18.07 49.01,21.846 49.01,21.846" style="fill:none;stroke:white;stroke-width:3.42px;"/>
|
||||||
|
</g>
|
||||||
|
<g transform="matrix(1.2157,-0.0104971,0.0104971,1.2157,-11.9419,-4.29553)">
|
||||||
|
<path d="M49.627,22.899L49.53,22.351" style="fill:none;stroke:white;stroke-width:2.47px;"/>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 1.3 KiB |
BIN
assets/projectfiles/icons.afdesign
Normal file
BIN
assets/projectfiles/icons.afdesign
Normal file
Binary file not shown.
BIN
assets/projectfiles/logo.afdesign
Normal file
BIN
assets/projectfiles/logo.afdesign
Normal file
Binary file not shown.
|
@ -43,12 +43,7 @@
|
||||||
<link rel="preload" href="style/main.scss" as="style" />
|
<link rel="preload" href="style/main.scss" as="style" />
|
||||||
<link rel="preload" href="style/bgus.scss" as="style" />
|
<link rel="preload" href="style/bgus.scss" as="style" />
|
||||||
<link rel="preload" href="src/index.ts" as="script" />
|
<link rel="preload" href="src/index.ts" as="script" />
|
||||||
<link
|
<link rel="stylesheet" href="assets/fonts/iosevka/iosevka-aile.css" />
|
||||||
rel="stylesheet"
|
|
||||||
href="assets/fonts/iosevka/iosevka-aile.css"
|
|
||||||
media="async"
|
|
||||||
onload="this.media='all'"
|
|
||||||
/>
|
|
||||||
<link rel="stylesheet" href="style/main.scss" />
|
<link rel="stylesheet" href="style/main.scss" />
|
||||||
<link rel="stylesheet" href="style/bgus.scss" />
|
<link rel="stylesheet" href="style/bgus.scss" />
|
||||||
<title>/tg/station Handbook</title>
|
<title>/tg/station Handbook</title>
|
||||||
|
@ -58,6 +53,7 @@
|
||||||
<img src="./assets/images/bg-nanotrasen.svg" />
|
<img src="./assets/images/bg-nanotrasen.svg" />
|
||||||
</div>
|
</div>
|
||||||
<main id="app">
|
<main id="app">
|
||||||
|
<nav id="section-list"></nav>
|
||||||
<nav id="tab-list"></nav>
|
<nav id="tab-list"></nav>
|
||||||
<section id="tabs"></section>
|
<section id="tabs"></section>
|
||||||
</main>
|
</main>
|
||||||
|
|
|
@ -3,6 +3,9 @@ import speen from "~/assets/images/speen.svg";
|
||||||
import { getPageHTML } from "./wiki";
|
import { getPageHTML } from "./wiki";
|
||||||
import userscript from "./userscript";
|
import userscript from "./userscript";
|
||||||
|
|
||||||
|
// @ts-expect-error: Parcel image import
|
||||||
|
import unknown from "~/assets/images/tab-icons/unknown.svg";
|
||||||
|
|
||||||
function initWaiting(elem: HTMLElement) {
|
function initWaiting(elem: HTMLElement) {
|
||||||
// Add spinner
|
// Add spinner
|
||||||
const spinnerContainer = document.createElement("div");
|
const spinnerContainer = document.createElement("div");
|
||||||
|
@ -36,32 +39,117 @@ async function loadPage(page: string, elem: HTMLElement) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
type TabElements = { tabListItem: HTMLElement; tabContentItem: HTMLElement };
|
type TabElements = {
|
||||||
|
tabListItem: HTMLElement;
|
||||||
|
tabContentItem: HTMLElement;
|
||||||
|
};
|
||||||
|
|
||||||
|
interface Section {
|
||||||
|
name: string;
|
||||||
|
element: HTMLElement;
|
||||||
|
tabs: Record<string, TabElements>;
|
||||||
|
}
|
||||||
|
|
||||||
export default class TabManager {
|
export default class TabManager {
|
||||||
|
sectionListContainer: HTMLElement;
|
||||||
|
|
||||||
tabListContainer: HTMLElement;
|
tabListContainer: HTMLElement;
|
||||||
|
|
||||||
tabContentContainer: HTMLElement;
|
tabContentContainer: HTMLElement;
|
||||||
|
|
||||||
tabs: Record<string, TabElements> = {};
|
sections: Record<string, Section> = {};
|
||||||
|
|
||||||
constructor(tablist: HTMLElement, tabcontent: HTMLElement) {
|
constructor(
|
||||||
|
sectionlist: HTMLElement,
|
||||||
|
tablist: HTMLElement,
|
||||||
|
tabcontent: HTMLElement
|
||||||
|
) {
|
||||||
|
this.sectionListContainer = sectionlist;
|
||||||
this.tabListContainer = tablist;
|
this.tabListContainer = tablist;
|
||||||
this.tabContentContainer = tabcontent;
|
this.tabContentContainer = tabcontent;
|
||||||
}
|
}
|
||||||
|
|
||||||
openTab(page: string, setActive: boolean): void {
|
/**
|
||||||
|
* Create section and add it to the section list
|
||||||
|
* @param name Section name
|
||||||
|
*/
|
||||||
|
createSection(name: string): void {
|
||||||
|
// Create section element
|
||||||
|
const sectionItem = document.createElement("div");
|
||||||
|
sectionItem.className = "section";
|
||||||
|
sectionItem.dataset.section = name;
|
||||||
|
sectionItem.appendChild(document.createTextNode(name));
|
||||||
|
sectionItem.addEventListener("click", () => {
|
||||||
|
if (sectionItem.classList.contains("active")) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.showSection(name);
|
||||||
|
});
|
||||||
|
this.sectionListContainer.appendChild(sectionItem);
|
||||||
|
|
||||||
|
this.sections[name] = { name, element: sectionItem, tabs: {} };
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Show tabs of a specific section
|
||||||
|
* @param name Section name
|
||||||
|
*/
|
||||||
|
showSection(name: string): void {
|
||||||
|
const active = this.sectionListContainer.querySelector<HTMLElement>(
|
||||||
|
".active"
|
||||||
|
);
|
||||||
|
if (active) {
|
||||||
|
// De-activate current section
|
||||||
|
active.classList.remove("active");
|
||||||
|
|
||||||
|
// Hide all tabs
|
||||||
|
this.tabListContainer
|
||||||
|
.querySelectorAll(`div[data-section=${active.dataset.section}]`)
|
||||||
|
.forEach((tab) => tab.classList.add("hidden"));
|
||||||
|
}
|
||||||
|
// Set section as active
|
||||||
|
this.sections[name].element.classList.add("active");
|
||||||
|
|
||||||
|
// Show all tabs of that section
|
||||||
|
this.tabListContainer
|
||||||
|
.querySelectorAll(`div[data-section=${name}]`)
|
||||||
|
.forEach((tab) => tab.classList.remove("hidden"));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Open tab page and add it to the tab list
|
||||||
|
* @param section Section to add the tab button to
|
||||||
|
* @param page Page name
|
||||||
|
* @param icon Icon to show
|
||||||
|
* @param setActive Also set the tab as active
|
||||||
|
*/
|
||||||
|
openTab(
|
||||||
|
section: string,
|
||||||
|
page: string,
|
||||||
|
options: {
|
||||||
|
icon?: string;
|
||||||
|
active?: boolean;
|
||||||
|
text?: string;
|
||||||
|
}
|
||||||
|
): void {
|
||||||
// Create tab list item
|
// Create tab list item
|
||||||
const tabListItem = document.createElement("div");
|
const tabListItem = document.createElement("div");
|
||||||
tabListItem.className = "tab";
|
tabListItem.className = "tab";
|
||||||
|
tabListItem.dataset.section = section;
|
||||||
tabListItem.dataset.tab = page;
|
tabListItem.dataset.tab = page;
|
||||||
tabListItem.addEventListener("click", () => {
|
tabListItem.addEventListener("click", () => {
|
||||||
if (tabListItem.classList.contains("active")) {
|
if (tabListItem.classList.contains("active")) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this.setActive(page);
|
this.setActive(section, page);
|
||||||
});
|
});
|
||||||
tabListItem.appendChild(document.createTextNode(page.replace(/_/gi, " ")));
|
const iconElement = document.createElement("img");
|
||||||
|
iconElement.src = options.icon || unknown;
|
||||||
|
tabListItem.title = page.replace(/_/gi, " ");
|
||||||
|
tabListItem.appendChild(iconElement);
|
||||||
|
const shortTitle =
|
||||||
|
options.text || page.substr(page.lastIndexOf("_") + 1, 4);
|
||||||
|
tabListItem.appendChild(document.createTextNode(shortTitle));
|
||||||
this.tabListContainer.appendChild(tabListItem);
|
this.tabListContainer.appendChild(tabListItem);
|
||||||
|
|
||||||
// Create tab content container
|
// Create tab content container
|
||||||
|
@ -69,27 +157,45 @@ export default class TabManager {
|
||||||
tabContentItem.className = "page waiting";
|
tabContentItem.className = "page waiting";
|
||||||
tabContentItem.dataset.tab = page;
|
tabContentItem.dataset.tab = page;
|
||||||
initWaiting(tabContentItem);
|
initWaiting(tabContentItem);
|
||||||
this.tabContentContainer.appendChild(tabContentItem);
|
|
||||||
|
|
||||||
// Start loading page for new tab
|
// Start loading page for new tab
|
||||||
loadPage(page, tabContentItem);
|
loadPage(page, tabContentItem);
|
||||||
|
|
||||||
|
this.tabContentContainer.appendChild(tabContentItem);
|
||||||
|
|
||||||
// Create tab entry
|
// Create tab entry
|
||||||
this.tabs[page] = { tabListItem, tabContentItem };
|
this.sections[section].tabs[page] = { tabListItem, tabContentItem };
|
||||||
|
|
||||||
|
// Hide tab if section is hidden
|
||||||
|
if (!this.sections[section].element.classList.contains("active")) {
|
||||||
|
tabListItem.classList.add("hidden");
|
||||||
|
}
|
||||||
|
|
||||||
// If asked for, set it to active
|
// If asked for, set it to active
|
||||||
if (setActive) {
|
if (options.active) {
|
||||||
this.setActive(page);
|
this.setActive(section, page);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
setActive(page: string): void {
|
/**
|
||||||
|
* Set a specific page to be the active/visible one
|
||||||
|
* @param section Section name
|
||||||
|
* @param page Page name
|
||||||
|
*/
|
||||||
|
setActive(section: string, page: string): void {
|
||||||
// Make sure tab exists (why wouldn't it?!)
|
// Make sure tab exists (why wouldn't it?!)
|
||||||
if (!(page in this.tabs)) {
|
if (!(section in this.sections)) {
|
||||||
|
throw new Error("section not found");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(page in this.sections[section].tabs)) {
|
||||||
throw new Error("tab not found");
|
throw new Error("tab not found");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Deactivate current active tab
|
// Deactivate current active tab
|
||||||
|
this.sectionListContainer
|
||||||
|
.querySelectorAll(".active")
|
||||||
|
.forEach((it) => it.classList.remove("active"));
|
||||||
this.tabListContainer
|
this.tabListContainer
|
||||||
.querySelectorAll(".active")
|
.querySelectorAll(".active")
|
||||||
.forEach((it) => it.classList.remove("active"));
|
.forEach((it) => it.classList.remove("active"));
|
||||||
|
@ -97,8 +203,14 @@ export default class TabManager {
|
||||||
.querySelectorAll(".active")
|
.querySelectorAll(".active")
|
||||||
.forEach((it) => it.classList.remove("active"));
|
.forEach((it) => it.classList.remove("active"));
|
||||||
|
|
||||||
|
// If section is not shown, show it!
|
||||||
|
if (!this.sections[section].element.classList.contains("active")) {
|
||||||
|
this.showSection(section);
|
||||||
|
}
|
||||||
|
|
||||||
// Activate new tab
|
// Activate new tab
|
||||||
const { tabListItem, tabContentItem } = this.tabs[page];
|
const { tabListItem, tabContentItem } = this.sections[section].tabs[page];
|
||||||
|
this.sections[section].element.classList.add("active");
|
||||||
tabListItem.classList.add("active");
|
tabListItem.classList.add("active");
|
||||||
tabContentItem.classList.add("active");
|
tabContentItem.classList.add("active");
|
||||||
}
|
}
|
||||||
|
|
23
src/index.ts
23
src/index.ts
|
@ -1,18 +1,25 @@
|
||||||
import TabManager from "./TabManager";
|
import TabManager from "./TabManager";
|
||||||
|
import sections from "./sections";
|
||||||
|
|
||||||
|
const sectionListContainer = document.getElementById("section-list");
|
||||||
const tabListContainer = document.getElementById("tab-list");
|
const tabListContainer = document.getElementById("tab-list");
|
||||||
const tabContentContainer = document.getElementById("tabs");
|
const tabContentContainer = document.getElementById("tabs");
|
||||||
const manager = new TabManager(tabListContainer, tabContentContainer);
|
const manager = new TabManager(
|
||||||
|
sectionListContainer,
|
||||||
|
tabListContainer,
|
||||||
|
tabContentContainer
|
||||||
|
);
|
||||||
|
|
||||||
const defaultTabs = [
|
sections.forEach((section) => {
|
||||||
{ page: "Guide_to_chemistry", active: true },
|
manager.createSection(section.name);
|
||||||
{ page: "Guide_to_medicine", active: false },
|
section.tabs.forEach((tab) => {
|
||||||
];
|
manager.openTab(section.name, tab.page, { icon: tab.icon, text: tab.text });
|
||||||
|
});
|
||||||
defaultTabs.forEach((tab) => {
|
|
||||||
manager.openTab(tab.page, tab.active);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Set first page as active
|
||||||
|
manager.setActive("Medical", "Guide_to_chemistry");
|
||||||
|
|
||||||
if ("serviceWorker" in navigator) {
|
if ("serviceWorker" in navigator) {
|
||||||
const x = process.env.SUBPATH ? `${process.env.SUBPATH}/sw.js` : "sw.js";
|
const x = process.env.SUBPATH ? `${process.env.SUBPATH}/sw.js` : "sw.js";
|
||||||
navigator.serviceWorker
|
navigator.serviceWorker
|
||||||
|
|
99
src/sections.ts
Normal file
99
src/sections.ts
Normal file
|
@ -0,0 +1,99 @@
|
||||||
|
// @ts-expect-error: Parcel image import
|
||||||
|
import chemistry from "~/assets/images/tab-icons/chemistry.svg";
|
||||||
|
|
||||||
|
const sections = [
|
||||||
|
{
|
||||||
|
name: "Medical",
|
||||||
|
tabs: [
|
||||||
|
{ page: "Guide_to_medicine", icon: null },
|
||||||
|
{ page: "Guide_to_chemistry", icon: chemistry },
|
||||||
|
{ page: "Guide_to_plumbing", icon: null },
|
||||||
|
{ page: "Grenade", text: "nade", icon: null },
|
||||||
|
{ page: "Guide_to_genetics", icon: null },
|
||||||
|
{ page: "Infections", text: "virus", icon: null },
|
||||||
|
{ page: "Surgery", icon: null },
|
||||||
|
{ page: "Guide_to_Traumas", text: "trauma", icon: null },
|
||||||
|
{ page: "Guide_to_Wounds", text: "wound", icon: null },
|
||||||
|
{ page: "Guide_to_Ghetto_Chemistry", text: "ghetto", icon: null },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Engineering",
|
||||||
|
tabs: [
|
||||||
|
{ page: "Guide_to_construction", icon: null },
|
||||||
|
{ page: "Machines", icon: null },
|
||||||
|
{ page: "Guide_to_power", text: "power", icon: null },
|
||||||
|
{ page: "Solars", text: "solar", icon: null },
|
||||||
|
{ page: "Guide_to_the_Supermatter", text: "smatt", icon: null },
|
||||||
|
{ page: "Singularity_and_Tesla_engines", text: "sing/tesl", icon: null },
|
||||||
|
{ page: "Gas_turbine", text: "GAS", icon: null },
|
||||||
|
{ page: "Guide_to_Atmospherics", text: "atmos", icon: null },
|
||||||
|
{ page: "Guide_to_Telecommunications", icon: null, text: "tcomm" },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Science",
|
||||||
|
tabs: [
|
||||||
|
{ page: "Guide_to_Research_and_Development", text: "R&D", icon: null },
|
||||||
|
{ page: "Guide_to_robotics", icon: null },
|
||||||
|
{ page: "Guide_to_toxins", text: "toxin", icon: null },
|
||||||
|
{ page: "Guide_to_xenobiology", icon: null },
|
||||||
|
{ page: "Guide_to_genetics", icon: null },
|
||||||
|
{ page: "Guide_to_telescience", icon: null },
|
||||||
|
{ page: "Guide_to_Nanites", text: "nanite", icon: null },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Security",
|
||||||
|
tabs: [
|
||||||
|
{ page: "Guide_to_security", text: "security", icon: null },
|
||||||
|
{ page: "Space_Law", text: "space law", icon: null },
|
||||||
|
{ page: "Standard_Operating_Procedure", text: "S.O.P.", icon: null },
|
||||||
|
{ page: "Guide_to_trials", text: "trials", icon: null },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Antagonists",
|
||||||
|
tabs: [
|
||||||
|
{ page: "Traitor", icon: null },
|
||||||
|
{ page: "Makeshift_weapons", icon: null },
|
||||||
|
{ page: "Hacking", icon: null },
|
||||||
|
{ page: "Guide_to_Combat", icon: null },
|
||||||
|
{ page: "Syndicate_Items", text: "synd", icon: null },
|
||||||
|
{ page: "Illicit_Access", icon: null },
|
||||||
|
{ page: "Revolutionary", icon: null },
|
||||||
|
{ page: "Blood_Cult", text: "cult", icon: null },
|
||||||
|
{ page: "Nuclear_Operative", text: "nuke", icon: null },
|
||||||
|
{ page: "Guide_to_malfunction", icon: null },
|
||||||
|
{ page: "Xenos", text: "xmor", icon: null },
|
||||||
|
{ page: "Abductor", icon: null },
|
||||||
|
{ page: "Families", icon: null },
|
||||||
|
{ page: "Heretic", icon: null },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Other",
|
||||||
|
tabs: [
|
||||||
|
{ page: "Ai_Modules", text: "aimo", icon: null },
|
||||||
|
{ page: "Silicon_Policy", text: "sipo", icon: null },
|
||||||
|
{
|
||||||
|
page: "Guide_to_Awesome_Miscellaneous_Stuff",
|
||||||
|
text: "misc",
|
||||||
|
icon: null,
|
||||||
|
},
|
||||||
|
{ page: "Creatures", icon: null },
|
||||||
|
{ page: "Critters", icon: null },
|
||||||
|
{ page: "Guide_to_races", icon: null },
|
||||||
|
{ page: "Guide_to_food_and_drinks", text: "food", icon: null },
|
||||||
|
{ page: "Guide_to_hydroponics", icon: null },
|
||||||
|
{ page: "Guide_to_plants", icon: null },
|
||||||
|
{ page: "Songs", icon: null },
|
||||||
|
{ page: "Supply_crates", icon: null },
|
||||||
|
{ page: "Auxiliary_Base_Construction", text: "aux", icon: null },
|
||||||
|
{ page: "Guide_to_wire_art", text: "wire", icon: null },
|
||||||
|
{ page: "Guide_to_Space_Exploration", icon: null },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
export default sections;
|
|
@ -3,6 +3,13 @@ import searchBox from "./search";
|
||||||
import { findParent } from "./utils";
|
import { findParent } from "./utils";
|
||||||
|
|
||||||
export default function userscript(root: HTMLElement, docname: string): void {
|
export default function userscript(root: HTMLElement, docname: string): void {
|
||||||
|
// Add header
|
||||||
|
const header = document.createElement("h1");
|
||||||
|
header.className = "pageheader";
|
||||||
|
header.appendChild(document.createTextNode(docname.replace(/_/g, " ")));
|
||||||
|
root.insertBefore(header, root.firstChild);
|
||||||
|
|
||||||
|
// Remove edit links
|
||||||
root.querySelectorAll(".mw-editsection").forEach((editLink) => {
|
root.querySelectorAll(".mw-editsection").forEach((editLink) => {
|
||||||
editLink.parentElement.removeChild(editLink);
|
editLink.parentElement.removeChild(editLink);
|
||||||
});
|
});
|
||||||
|
@ -55,8 +62,16 @@ export default function userscript(root: HTMLElement, docname: string): void {
|
||||||
row.appendChild(td);
|
row.appendChild(td);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Fuck #toctitle
|
||||||
|
const toc = root.querySelector("#toc");
|
||||||
|
if (toc) {
|
||||||
|
const tocHeader = toc.querySelector("h2");
|
||||||
|
toc.parentNode.insertBefore(tocHeader, toc);
|
||||||
|
toc.removeChild(toc.querySelector("#toctitle"));
|
||||||
|
}
|
||||||
|
|
||||||
// Group headers and content so stickies don't overlap
|
// Group headers and content so stickies don't overlap
|
||||||
root.querySelectorAll("h3,h2").forEach((h3) => {
|
root.querySelectorAll("h1,h2,h3").forEach((h3) => {
|
||||||
const parent = h3.parentNode;
|
const parent = h3.parentNode;
|
||||||
const div = document.createElement("div");
|
const div = document.createElement("div");
|
||||||
parent.insertBefore(div, h3);
|
parent.insertBefore(div, h3);
|
||||||
|
@ -79,7 +94,7 @@ export default function userscript(root: HTMLElement, docname: string): void {
|
||||||
if (container) {
|
if (container) {
|
||||||
container.id = span.id;
|
container.id = span.id;
|
||||||
span.id += "-span";
|
span.id += "-span";
|
||||||
container.dataset.name = span.innerText;
|
container.dataset.name = span.textContent;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -117,7 +132,7 @@ export default function userscript(root: HTMLElement, docname: string): void {
|
||||||
|
|
||||||
// Enrich "x part" with checkboxes and parts
|
// Enrich "x part" with checkboxes and parts
|
||||||
Array.from(document.querySelectorAll("td"))
|
Array.from(document.querySelectorAll("td"))
|
||||||
.filter((el) => el.innerText.indexOf(" part") >= 0)
|
.filter((el) => el.textContent.indexOf(" part") >= 0)
|
||||||
.forEach((el) => {
|
.forEach((el) => {
|
||||||
el.innerHTML = el.innerHTML.replace(
|
el.innerHTML = el.innerHTML.replace(
|
||||||
/((\d+)\s+(?:parts?|units?))(.*?(?:<\/a>|\n|$))/gi,
|
/((\d+)\s+(?:parts?|units?))(.*?(?:<\/a>|\n|$))/gi,
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
}
|
}
|
||||||
#bgus_fz_searchbox {
|
#bgus_fz_searchbox {
|
||||||
position: fixed;
|
position: fixed;
|
||||||
top: 50px;
|
top: 80px;
|
||||||
left: 20%;
|
left: 20%;
|
||||||
right: 20%;
|
right: 20%;
|
||||||
background: rgba(10, 10, 10, 0.8);
|
background: rgba(10, 10, 10, 0.8);
|
||||||
|
|
|
@ -36,7 +36,6 @@ body {
|
||||||
#app {
|
#app {
|
||||||
height: 100%;
|
height: 100%;
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-rows: 40px 1fr;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
::-webkit-scrollbar {
|
::-webkit-scrollbar {
|
||||||
|
@ -60,13 +59,12 @@ body {
|
||||||
}
|
}
|
||||||
|
|
||||||
#tabs {
|
#tabs {
|
||||||
grid-row: 2;
|
grid-row: 3;
|
||||||
z-index: 1;
|
z-index: 1;
|
||||||
display: grid;
|
display: grid;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
.page {
|
.page {
|
||||||
visibility: hidden;
|
visibility: hidden;
|
||||||
padding-top: 10pt;
|
|
||||||
overflow-y: scroll;
|
overflow-y: scroll;
|
||||||
grid-row: 1;
|
grid-row: 1;
|
||||||
grid-column: 1;
|
grid-column: 1;
|
||||||
|
@ -97,6 +95,11 @@ body {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
h1.pageheader {
|
||||||
|
margin-top: 0;
|
||||||
|
padding: 15pt 10pt;
|
||||||
|
}
|
||||||
|
|
||||||
p,
|
p,
|
||||||
h2,
|
h2,
|
||||||
h3,
|
h3,
|
||||||
|
@ -107,19 +110,15 @@ body {
|
||||||
a[href] {
|
a[href] {
|
||||||
color: white;
|
color: white;
|
||||||
}
|
}
|
||||||
#toctitle,
|
|
||||||
h1,
|
h1,
|
||||||
h2,
|
h2,
|
||||||
h3 {
|
h3 {
|
||||||
position: sticky;
|
position: sticky;
|
||||||
top: -10pt;
|
top: 0;
|
||||||
background: $nanotrasen;
|
background: $nanotrasen;
|
||||||
padding: 10px;
|
padding: 10pt;
|
||||||
z-index: 999;
|
z-index: 999;
|
||||||
}
|
}
|
||||||
#toctitle h2 {
|
|
||||||
margin: 0;
|
|
||||||
}
|
|
||||||
.mw-headline {
|
.mw-headline {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
@ -127,27 +126,75 @@ body {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$section-active: darken($nanotrasen, 5%);
|
||||||
$tab-active: lighten($nanotrasen, 10%);
|
$tab-active: lighten($nanotrasen, 10%);
|
||||||
|
|
||||||
#tab-list {
|
#section-list {
|
||||||
z-index: 2;
|
z-index: 2;
|
||||||
grid-row: 1;
|
grid-row: 1;
|
||||||
|
border-bottom: 2px solid $section-active;
|
||||||
display: flex;
|
display: flex;
|
||||||
border-bottom: 2px solid $tab-active;
|
.section {
|
||||||
|
|
||||||
.tab {
|
|
||||||
max-width: 200px;
|
|
||||||
flex: 1;
|
|
||||||
display: flex;
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
user-select: none;
|
user-select: none;
|
||||||
|
font-size: 9pt;
|
||||||
|
padding: 3pt 7pt;
|
||||||
|
text-transform: uppercase;
|
||||||
|
color: lighten($nanotrasen, 60%);
|
||||||
|
flex: 1;
|
||||||
|
&.active {
|
||||||
|
background-color: $section-active;
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
&:not(.active) {
|
||||||
|
cursor: pointer;
|
||||||
|
&:hover {
|
||||||
|
background-color: darken($section-active, 10%);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#tab-list {
|
||||||
|
z-index: 2;
|
||||||
|
grid-row: 2;
|
||||||
|
display: flex;
|
||||||
|
background-color: $section-active;
|
||||||
|
border-bottom: 4px solid $tab-active;
|
||||||
|
|
||||||
|
.tab {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
user-select: none;
|
||||||
|
font-size: 7pt;
|
||||||
|
padding: 2px 4px;
|
||||||
|
padding-bottom: 0;
|
||||||
|
text-transform: uppercase;
|
||||||
|
flex: 1;
|
||||||
|
max-width: 100px;
|
||||||
|
|
||||||
|
img {
|
||||||
|
height: 80%;
|
||||||
|
max-height: 24px;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
&.active {
|
&.active {
|
||||||
background-color: $tab-active;
|
background-color: $tab-active;
|
||||||
}
|
}
|
||||||
&:not(.active) {
|
&:not(.active) {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
|
&:hover {
|
||||||
|
background-color: darken($tab-active, 8%);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&.hidden {
|
||||||
|
display: none;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Reference in a new issue