Add linting and fix lint errors
Some checks failed
continuous-integration/drone/push Build is failing
Some checks failed
continuous-integration/drone/push Build is failing
This commit is contained in:
parent
4978851016
commit
42ed7591b6
11 changed files with 1214 additions and 150 deletions
142
.drone.yml
Normal file
142
.drone.yml
Normal file
|
@ -0,0 +1,142 @@
|
|||
kind: pipeline
|
||||
name: default
|
||||
|
||||
steps:
|
||||
- name: restore-cache
|
||||
image: drillster/drone-volume-cache
|
||||
volumes:
|
||||
- name: cache
|
||||
path: /cache
|
||||
settings:
|
||||
restore: true
|
||||
mount:
|
||||
- ./node_modules
|
||||
|
||||
- name: dependencies
|
||||
image: node
|
||||
failure: ignore
|
||||
commands:
|
||||
- yarn
|
||||
depends_on:
|
||||
- restore-cache
|
||||
|
||||
- name: lint
|
||||
image: node
|
||||
commands:
|
||||
- yarn lint
|
||||
depends_on:
|
||||
- dependencies
|
||||
|
||||
- name: build_versioned
|
||||
image: node
|
||||
commands:
|
||||
- yarn build
|
||||
when:
|
||||
event:
|
||||
- push
|
||||
branch:
|
||||
exclude:
|
||||
- master
|
||||
depends_on:
|
||||
- dependencies
|
||||
|
||||
- name: build_pr
|
||||
image: node
|
||||
commands:
|
||||
- yarn build
|
||||
when:
|
||||
event:
|
||||
- pull_request
|
||||
depends_on:
|
||||
- dependencies
|
||||
|
||||
- name: build_master
|
||||
image: node
|
||||
commands:
|
||||
- yarn build
|
||||
environment:
|
||||
SUBPATH: /latest
|
||||
when:
|
||||
event:
|
||||
- push
|
||||
branch:
|
||||
- master
|
||||
depends_on:
|
||||
- dependencies
|
||||
|
||||
- name: upload_build_versioned
|
||||
image: plugins/s3
|
||||
settings:
|
||||
bucket: tghandbook
|
||||
access_key:
|
||||
from_secret: minio_access
|
||||
secret_key:
|
||||
from_secret: minio_secret
|
||||
source: dist/**/*
|
||||
target: /${DRONE_COMMIT_SHA:0:8}/
|
||||
path_style: true
|
||||
endpoint: https://artifacts.fromouter.space
|
||||
when:
|
||||
event:
|
||||
- push
|
||||
branch:
|
||||
exclude:
|
||||
- master
|
||||
depends_on:
|
||||
- build_versioned
|
||||
|
||||
- name: upload_build_pr
|
||||
image: plugins/s3
|
||||
settings:
|
||||
bucket: tghandbook
|
||||
access_key:
|
||||
from_secret: minio_access
|
||||
secret_key:
|
||||
from_secret: minio_secret
|
||||
source: dist/**/*
|
||||
target: /pr-${DRONE_PULL_REQUEST}/
|
||||
path_style: true
|
||||
endpoint: https://artifacts.fromouter.space
|
||||
when:
|
||||
event:
|
||||
- pull_request
|
||||
depends_on:
|
||||
- build_pr
|
||||
|
||||
- name: upload_build_master
|
||||
image: plugins/s3
|
||||
settings:
|
||||
bucket: tghandbook
|
||||
access_key:
|
||||
from_secret: minio_access
|
||||
secret_key:
|
||||
from_secret: minio_secret
|
||||
source: dist/**/*
|
||||
target: /latest/
|
||||
path_style: true
|
||||
endpoint: https://artifacts.fromouter.space
|
||||
when:
|
||||
event:
|
||||
- push
|
||||
branch:
|
||||
- master
|
||||
depends_on:
|
||||
- build_master
|
||||
|
||||
- name: rebuild-cache
|
||||
image: drillster/drone-volume-cache
|
||||
failure: ignore
|
||||
volumes:
|
||||
- name: cache
|
||||
path: /cache
|
||||
settings:
|
||||
rebuild: true
|
||||
mount:
|
||||
- ./node_modules
|
||||
depends_on:
|
||||
- dependencies
|
||||
|
||||
volumes:
|
||||
- name: cache
|
||||
host:
|
||||
path: /opt/gitea/drone-cache/hamcha/tghandbook
|
29
.eslintrc.js
Normal file
29
.eslintrc.js
Normal file
|
@ -0,0 +1,29 @@
|
|||
module.exports = {
|
||||
env: {
|
||||
browser: true,
|
||||
es2020: true,
|
||||
},
|
||||
extends: [
|
||||
"airbnb-base",
|
||||
"plugin:@typescript-eslint/recommended",
|
||||
"plugin:prettier/recommended",
|
||||
],
|
||||
parser: "@typescript-eslint/parser",
|
||||
plugins: ["@typescript-eslint", "prettier"],
|
||||
rules: {
|
||||
"prettier/prettier": "error",
|
||||
"one-var": "off", // WHO CARES?????
|
||||
"no-use-before-define": "off", // YOU ARE WRONG
|
||||
"import/extensions": "off",
|
||||
"import/no-unresolved": "off",
|
||||
"no-param-reassign": "off",
|
||||
"no-alert": "off",
|
||||
"no-console": "off",
|
||||
"@typescript-eslint/ban-ts-comment": [
|
||||
"error",
|
||||
{
|
||||
"ts-expect-error": "allow-with-description",
|
||||
},
|
||||
],
|
||||
},
|
||||
};
|
4
.prettierrc
Normal file
4
.prettierrc
Normal file
|
@ -0,0 +1,4 @@
|
|||
{
|
||||
"singleQuote": false,
|
||||
"endOfLine": "auto"
|
||||
}
|
|
@ -1,5 +1,7 @@
|
|||
# /tg/ handbook
|
||||
|
||||
[![Build Status](https://drone.zyg.ovh/api/badges/Hamcha/tghandbook/status.svg)](https://drone.zyg.ovh/Hamcha/tghandbook)
|
||||
|
||||
## Building
|
||||
|
||||
`yarn build`
|
||||
|
|
22
index.html
22
index.html
|
@ -3,7 +3,25 @@
|
|||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<link rel="stylesheet" href="assets/fonts/iosevka/iosevka-aile.css" />
|
||||
<link
|
||||
rel="preload"
|
||||
href="assets/fonts/iosevka/iosevka-aile.css"
|
||||
as="style"
|
||||
/>
|
||||
<link
|
||||
rel="preload"
|
||||
href="assets/fonts/iosevka/woff2/iosevka-aile-regular.woff2"
|
||||
as="font"
|
||||
/>
|
||||
<link rel="preload" href="style/main.scss" as="style" />
|
||||
<link rel="preload" href="style/bgus.scss" as="style" />
|
||||
<link rel="preload" href="lib/index.ts" as="script" />
|
||||
<link
|
||||
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/bgus.scss" />
|
||||
<title>/tg/ Handbook</title>
|
||||
|
@ -16,6 +34,6 @@
|
|||
<nav id="tab-list"></nav>
|
||||
<section id="tabs"></section>
|
||||
</main>
|
||||
<script src="lib/index.ts"></script>
|
||||
<script src="lib/index.ts" async></script>
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
// @ts-expect-error: Asset imports are handled by parcel
|
||||
import speen from "~/assets/images/speen.svg";
|
||||
import { getPageHTML } from "./wiki";
|
||||
import userscript from "./userscript";
|
||||
|
@ -19,7 +20,7 @@ function initWaiting(elem: HTMLElement) {
|
|||
|
||||
async function loadPage(page: string, elem: HTMLElement) {
|
||||
// Fetch page content
|
||||
console.log(page + ": fetching");
|
||||
console.log(`${page}: fetching`);
|
||||
let html = await getPageHTML(page);
|
||||
|
||||
// Convert relative links to absolute
|
||||
|
@ -28,9 +29,9 @@ async function loadPage(page: string, elem: HTMLElement) {
|
|||
// Set as HTML content and run HTML manipulations on it
|
||||
requestAnimationFrame(() => {
|
||||
elem.innerHTML = html;
|
||||
console.log(page + ": processing");
|
||||
console.log(`${page}: processing`);
|
||||
userscript(elem, page);
|
||||
console.log(page + ": userscript applied");
|
||||
console.log(`${page}: userscript applied`);
|
||||
elem.classList.remove("waiting");
|
||||
});
|
||||
}
|
||||
|
@ -39,7 +40,9 @@ type TabElements = { tabListItem: HTMLElement; tabContentItem: HTMLElement };
|
|||
|
||||
export default class TabManager {
|
||||
tabListContainer: HTMLElement;
|
||||
|
||||
tabContentContainer: HTMLElement;
|
||||
|
||||
tabs: Record<string, TabElements> = {};
|
||||
|
||||
constructor(tablist: HTMLElement, tabcontent: HTMLElement) {
|
||||
|
@ -47,7 +50,7 @@ export default class TabManager {
|
|||
this.tabContentContainer = tabcontent;
|
||||
}
|
||||
|
||||
openTab(page: string, setActive: boolean) {
|
||||
openTab(page: string, setActive: boolean): void {
|
||||
// Create tab list item
|
||||
const tabListItem = document.createElement("div");
|
||||
tabListItem.className = "tab";
|
||||
|
@ -80,7 +83,7 @@ export default class TabManager {
|
|||
}
|
||||
}
|
||||
|
||||
setActive(page: string) {
|
||||
setActive(page: string): void {
|
||||
// Make sure tab exists (why wouldn't it?!)
|
||||
if (!(page in this.tabs)) {
|
||||
throw new Error("tab not found");
|
||||
|
|
|
@ -16,48 +16,61 @@ export enum ColorFmt {
|
|||
}
|
||||
|
||||
function hsvToRgb({ h, s, v }: ColorHSV): ColorRGB {
|
||||
var r, g, b;
|
||||
let r, g, b;
|
||||
|
||||
var i = Math.floor(h * 6);
|
||||
var f = h * 6 - i;
|
||||
var p = v * (1 - s);
|
||||
var q = v * (1 - f * s);
|
||||
var t = v * (1 - (1 - f) * s);
|
||||
const i = Math.floor(h * 6);
|
||||
const f = h * 6 - i;
|
||||
const p = v * (1 - s);
|
||||
const q = v * (1 - f * s);
|
||||
const t = v * (1 - (1 - f) * s);
|
||||
|
||||
switch (i % 6) {
|
||||
case 0:
|
||||
(r = v), (g = t), (b = p);
|
||||
r = v;
|
||||
g = t;
|
||||
b = p;
|
||||
break;
|
||||
case 1:
|
||||
(r = q), (g = v), (b = p);
|
||||
r = q;
|
||||
g = v;
|
||||
b = p;
|
||||
break;
|
||||
case 2:
|
||||
(r = p), (g = v), (b = t);
|
||||
r = p;
|
||||
g = v;
|
||||
b = t;
|
||||
break;
|
||||
case 3:
|
||||
(r = p), (g = q), (b = v);
|
||||
r = p;
|
||||
g = q;
|
||||
b = v;
|
||||
break;
|
||||
case 4:
|
||||
(r = t), (g = p), (b = v);
|
||||
r = t;
|
||||
g = p;
|
||||
b = v;
|
||||
break;
|
||||
case 5:
|
||||
(r = v), (g = p), (b = q);
|
||||
r = v;
|
||||
g = p;
|
||||
b = q;
|
||||
break;
|
||||
default:
|
||||
throw new Error("unreacheable");
|
||||
}
|
||||
return { r, g, b };
|
||||
}
|
||||
|
||||
function rgbToHsv({ r, g, b }: ColorRGB): ColorHSV {
|
||||
var max = Math.max(r, g, b),
|
||||
min = Math.min(r, g, b);
|
||||
var h,
|
||||
s,
|
||||
v = max;
|
||||
const max = Math.max(r, g, b);
|
||||
const min = Math.min(r, g, b);
|
||||
const v = max;
|
||||
|
||||
var d = max - min;
|
||||
s = max == 0 ? 0 : d / max;
|
||||
const d = max - min;
|
||||
const s = max === 0 ? 0 : d / max;
|
||||
|
||||
if (max == min) {
|
||||
let h;
|
||||
if (max === min) {
|
||||
h = 0; // achromatic
|
||||
} else {
|
||||
switch (max) {
|
||||
|
@ -70,6 +83,8 @@ function rgbToHsv({ r, g, b }: ColorRGB): ColorHSV {
|
|||
case b:
|
||||
h = (r - g) / d + 4;
|
||||
break;
|
||||
default:
|
||||
throw new Error("unreacheable");
|
||||
}
|
||||
h /= 6;
|
||||
}
|
||||
|
@ -80,13 +95,13 @@ function rgbToHsv({ r, g, b }: ColorRGB): ColorHSV {
|
|||
// Hacky way to get RGB values FOR SURE!
|
||||
function nameToRGB(name: string): ColorRGB {
|
||||
// Create fake div
|
||||
let fakeDiv = document.createElement("div");
|
||||
const fakeDiv = document.createElement("div");
|
||||
fakeDiv.style.color = name;
|
||||
document.body.appendChild(fakeDiv);
|
||||
|
||||
// Get color of div
|
||||
let cs = window.getComputedStyle(fakeDiv),
|
||||
pv = cs.getPropertyValue("color");
|
||||
const cs = window.getComputedStyle(fakeDiv);
|
||||
const pv = cs.getPropertyValue("color");
|
||||
|
||||
// Remove div after obtaining desired color value
|
||||
document.body.removeChild(fakeDiv);
|
||||
|
@ -98,9 +113,9 @@ function nameToRGB(name: string): ColorRGB {
|
|||
// https://stackoverflow.com/questions/11068240/what-is-the-most-efficient-way-to-parse-a-css-color-in-javascript
|
||||
function parseColor(input: string): ColorRGB {
|
||||
// Hex format
|
||||
if (input.substr(0, 1) == "#") {
|
||||
var collen = (input.length - 1) / 3;
|
||||
var fact = [17, 1, 0.062272][collen - 1];
|
||||
if (input.substr(0, 1) === "#") {
|
||||
const collen = (input.length - 1) / 3;
|
||||
const fact = [17, 1, 0.062272][collen - 1];
|
||||
return {
|
||||
r: Math.round(parseInt(input.substr(1, collen), 16) * fact) / 256,
|
||||
g:
|
||||
|
@ -132,11 +147,13 @@ function serializeColor(col: ColorRGB, format: ColorFmt): string {
|
|||
case ColorFmt.RGB:
|
||||
return `rgb(${r}, ${g}, ${b})`;
|
||||
case ColorFmt.HEX: {
|
||||
const rhex = ("00" + r.toString(16)).slice(-2);
|
||||
const ghex = ("00" + g.toString(16)).slice(-2);
|
||||
const bhex = ("00" + b.toString(16)).slice(-2);
|
||||
return "#" + rhex + ghex + bhex;
|
||||
const rhex = `00${r.toString(16)}`.slice(-2);
|
||||
const ghex = `00${g.toString(16)}`.slice(-2);
|
||||
const bhex = `00${b.toString(16)}`.slice(-2);
|
||||
return `#${rhex}${ghex}${bhex}`;
|
||||
}
|
||||
default:
|
||||
return "#000";
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -147,12 +164,10 @@ export function darken(color: string, format: ColorFmt): string {
|
|||
hsl.h = 0.6;
|
||||
hsl.s = 0.5;
|
||||
hsl.v = Math.max(0.2, 1 - hsl.v);
|
||||
} else {
|
||||
if (hsl.v > 0.5) {
|
||||
hsl.v = 0.4;
|
||||
if (hsl.s > 0.2) {
|
||||
hsl.s = Math.min(1, hsl.s + 0.2);
|
||||
}
|
||||
} else if (hsl.v > 0.5) {
|
||||
hsl.v = 0.4;
|
||||
if (hsl.s > 0.2) {
|
||||
hsl.s = Math.min(1, hsl.s + 0.2);
|
||||
}
|
||||
}
|
||||
const out = hsvToRgb(hsl);
|
||||
|
|
|
@ -4,7 +4,7 @@ const DEFAULT_OPTS = {
|
|||
alignment: "center",
|
||||
};
|
||||
|
||||
export default function (root: HTMLElement, docname: string) {
|
||||
export default function userscript(root: HTMLElement, docname: string): void {
|
||||
root.querySelectorAll(".mw-editsection").forEach((editLink) => {
|
||||
editLink.parentElement.removeChild(editLink);
|
||||
});
|
||||
|
@ -15,16 +15,16 @@ export default function (root: HTMLElement, docname: string) {
|
|||
// Shitty way to detect if it's hex or not
|
||||
// Basically, none of the css colors long 6 letters only use hex letters
|
||||
// THANK FUCKING GOD
|
||||
if (bgcolor.length === 6 && parseInt(bgcolor, 16) !== NaN) {
|
||||
bgcolor = "#" + bgcolor;
|
||||
if (bgcolor.length === 6 && Number.isNaN(parseInt(bgcolor, 16))) {
|
||||
bgcolor = `#${bgcolor}`;
|
||||
}
|
||||
td.setAttribute("bgcolor", darken(bgcolor, ColorFmt.HEX).slice(1));
|
||||
});
|
||||
root.querySelectorAll("*[style]").forEach((td: HTMLElement) => {
|
||||
if (td.style.backgroundColor != "") {
|
||||
if (td.style.backgroundColor !== "") {
|
||||
td.style.backgroundColor = darken(td.style.backgroundColor, ColorFmt.RGB);
|
||||
}
|
||||
if (td.style.background != "") {
|
||||
if (td.style.background !== "") {
|
||||
td.style.backgroundColor = darken(td.style.background, ColorFmt.RGB);
|
||||
}
|
||||
});
|
||||
|
@ -32,8 +32,8 @@ export default function (root: HTMLElement, docname: string) {
|
|||
// Lighten fgcolors
|
||||
root.querySelectorAll("*[color]").forEach((td) => {
|
||||
let color = td.getAttribute("color");
|
||||
if (color.length === 6 && !isNaN(parseInt(color, 16))) {
|
||||
color = "#" + color;
|
||||
if (color.length === 6 && !Number.isNaN(parseInt(color, 16))) {
|
||||
color = `#${color}`;
|
||||
}
|
||||
td.setAttribute("color", lighten(color, ColorFmt.HEX).slice(1));
|
||||
});
|
||||
|
@ -43,7 +43,7 @@ export default function (root: HTMLElement, docname: string) {
|
|||
td.setAttribute("width", "100%");
|
||||
});
|
||||
root.querySelectorAll("table[style]").forEach((td: HTMLTableElement) => {
|
||||
if (td.style.width != "") {
|
||||
if (td.style.width !== "") {
|
||||
td.style.width = "100%";
|
||||
}
|
||||
});
|
||||
|
@ -88,14 +88,14 @@ export default function (root: HTMLElement, docname: string) {
|
|||
postbody.insertBefore(statusMessage, postbody.firstChild);
|
||||
|
||||
// TODO Refactor this mess
|
||||
function searchBox(el, search_candidate, options = DEFAULT_OPTS) {
|
||||
function searchBox(el, searchCandidate, options = DEFAULT_OPTS) {
|
||||
// Fuzzy search box
|
||||
const resultList = document.createElement("ul");
|
||||
const searchBox = document.createElement("div");
|
||||
let selected_result = null;
|
||||
const searchBoxElem = document.createElement("div");
|
||||
let selectedResult = null;
|
||||
let results = [];
|
||||
|
||||
const jumpTo = function (id) {
|
||||
const jumpTo = (id) => {
|
||||
el[id].scrollIntoView({
|
||||
block: options.alignment,
|
||||
inline: "nearest",
|
||||
|
@ -103,15 +103,15 @@ export default function (root: HTMLElement, docname: string) {
|
|||
});
|
||||
document
|
||||
.querySelectorAll("table.wikitable .bgus_fz_selected")
|
||||
.forEach((el) => el.classList.remove("bgus_fz_selected"));
|
||||
.forEach((sel) => sel.classList.remove("bgus_fz_selected"));
|
||||
el[id].parentElement.classList.add("bgus_fz_selected");
|
||||
};
|
||||
|
||||
const setSelectedResult = function (i) {
|
||||
selected_result = i;
|
||||
const setSelectedResult = (i) => {
|
||||
selectedResult = i;
|
||||
resultList
|
||||
.querySelectorAll(".selected")
|
||||
.forEach((el) => el.classList.remove("selected"));
|
||||
.forEach((sel) => sel.classList.remove("selected"));
|
||||
resultList.children[i].classList.add("selected");
|
||||
jumpTo(results[i].id);
|
||||
};
|
||||
|
@ -121,15 +121,13 @@ export default function (root: HTMLElement, docname: string) {
|
|||
return;
|
||||
}
|
||||
const regex = new RegExp(
|
||||
"^(.*?)([" +
|
||||
str
|
||||
.split("")
|
||||
.map((c) => (c.includes(["\\", "]", "^"]) ? "\\" + c : c))
|
||||
.join("])(.*?)([") +
|
||||
"])(.*?)$",
|
||||
`^(.*?)([${str
|
||||
.split("")
|
||||
.map((c) => (c.includes(["\\", "]", "^"]) ? `\\${c}` : c))
|
||||
.join("])(.*?)([")}])(.*?)$`,
|
||||
"i"
|
||||
);
|
||||
const arr = search_candidate
|
||||
const arr = searchCandidate
|
||||
.map((o) => {
|
||||
o.matches = (o.str.match(regex) || [])
|
||||
.slice(1)
|
||||
|
@ -148,7 +146,7 @@ export default function (root: HTMLElement, docname: string) {
|
|||
}
|
||||
return list;
|
||||
}, [])
|
||||
.map((str) => str.join(""));
|
||||
.map((cstr) => cstr.join(""));
|
||||
return o;
|
||||
})
|
||||
// Strike non-matching rows
|
||||
|
@ -164,7 +162,7 @@ export default function (root: HTMLElement, docname: string) {
|
|||
if (a.length !== 1 && b.length === 1) return 1;
|
||||
|
||||
// Most complete groups (alphanumeric)
|
||||
const clean = (el) => !/[^a-zA-Z0-9]*$/.test(el);
|
||||
const clean = (cel) => !/[^a-zA-Z0-9]*$/.test(cel);
|
||||
const cLen = a.filter(clean).length - b.filter(clean).length;
|
||||
if (cLen !== 0) return cLen;
|
||||
|
||||
|
@ -187,11 +185,11 @@ export default function (root: HTMLElement, docname: string) {
|
|||
arr.forEach(({ matches, id }) => {
|
||||
const li = document.createElement("li");
|
||||
li.innerHTML = matches
|
||||
.map((c, i) => (i % 2 ? "<strong>" + c + "</strong>" : c))
|
||||
.map((c, i) => (i % 2 ? `<strong>${c}</strong>` : c))
|
||||
.join("");
|
||||
li.addEventListener("click", () => {
|
||||
jumpTo(id);
|
||||
searchBox.classList.add("bgus_hidden");
|
||||
searchBoxElem.classList.add("bgus_hidden");
|
||||
});
|
||||
resultList.appendChild(li);
|
||||
});
|
||||
|
@ -203,58 +201,60 @@ export default function (root: HTMLElement, docname: string) {
|
|||
|
||||
// Create fuzzy search box
|
||||
const sel = document.createElement("input");
|
||||
searchBox.id = "bgus_fz_searchbox";
|
||||
searchBox.classList.add("bgus_hidden");
|
||||
searchBox.appendChild(sel);
|
||||
searchBox.appendChild(resultList);
|
||||
root.appendChild(searchBox);
|
||||
searchBoxElem.id = "bgus_fz_searchbox";
|
||||
searchBoxElem.classList.add("bgus_hidden");
|
||||
searchBoxElem.appendChild(sel);
|
||||
searchBoxElem.appendChild(resultList);
|
||||
root.appendChild(searchBoxElem);
|
||||
|
||||
// Bind events
|
||||
let oldValue = "";
|
||||
sel.addEventListener("keyup", function (event) {
|
||||
sel.addEventListener("keyup", (event) => {
|
||||
switch (event.keyCode) {
|
||||
case 27: // Escape - Hide bar
|
||||
searchBox.classList.add("bgus_hidden");
|
||||
searchBoxElem.classList.add("bgus_hidden");
|
||||
return;
|
||||
case 13: // Enter - Jump to first result and hide bar
|
||||
if (results.length > 0) {
|
||||
jumpTo(results[selected_result].id);
|
||||
jumpTo(results[selectedResult].id);
|
||||
}
|
||||
searchBox.classList.add("bgus_hidden");
|
||||
searchBoxElem.classList.add("bgus_hidden");
|
||||
return;
|
||||
case 40: // Down arrow - Select next result
|
||||
if (selected_result < results.length - 1) {
|
||||
setSelectedResult(selected_result + 1);
|
||||
if (selectedResult < results.length - 1) {
|
||||
setSelectedResult(selectedResult + 1);
|
||||
}
|
||||
return;
|
||||
case 38: // Up arrow - Select previous result
|
||||
if (selected_result > 0) {
|
||||
setSelectedResult(selected_result - 1);
|
||||
if (selectedResult > 0) {
|
||||
setSelectedResult(selectedResult - 1);
|
||||
}
|
||||
return;
|
||||
default:
|
||||
if (this.value != oldValue) {
|
||||
search(this.value);
|
||||
oldValue = this.value;
|
||||
if (sel.value !== oldValue) {
|
||||
search(sel.value);
|
||||
oldValue = sel.value;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
document.body.addEventListener("keyup", function (ev) {
|
||||
document.body.addEventListener("keyup", (ev) => {
|
||||
if (ev.keyCode === 83) {
|
||||
sel.focus();
|
||||
}
|
||||
});
|
||||
|
||||
document.body.addEventListener("keydown", function (ev) {
|
||||
document.body.addEventListener("keydown", (ev) => {
|
||||
if (ev.shiftKey) {
|
||||
switch (ev.keyCode) {
|
||||
// SHIFT+S = Fuzzy search
|
||||
case 83: {
|
||||
searchBox.classList.remove("bgus_hidden");
|
||||
searchBoxElem.classList.remove("bgus_hidden");
|
||||
sel.value = "";
|
||||
return;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
// Do nothing
|
||||
}
|
||||
}
|
||||
});
|
||||
|
@ -268,14 +268,16 @@ export default function (root: HTMLElement, docname: string) {
|
|||
"table.wikitable > tbody > tr:not(:first-child) > td:nth-child(2), .tooltiptext"
|
||||
)
|
||||
.forEach((td) => {
|
||||
const tmp = td.cloneNode();
|
||||
const tmp = td.cloneNode() as HTMLElement;
|
||||
// The cast to Array is necessary because, while childNodes's NodeList technically has a forEach method, it's a live list and operations mess with its lenght in the middle of the loop.
|
||||
// Nodes can only have one parent so append removes them from the original NodeList and shifts the following one back into the wrong index.
|
||||
Array.from(td.childNodes).forEach((el) => {
|
||||
if (el.tagName === "P") {
|
||||
tmp.append(...el.childNodes);
|
||||
} else {
|
||||
tmp.append(el);
|
||||
if (el instanceof HTMLElement) {
|
||||
if (el.tagName === "P") {
|
||||
tmp.append(...el.childNodes);
|
||||
} else {
|
||||
tmp.append(el);
|
||||
}
|
||||
}
|
||||
});
|
||||
td.parentNode.replaceChild(tmp, td);
|
||||
|
@ -303,18 +305,20 @@ export default function (root: HTMLElement, docname: string) {
|
|||
// Add event to autofill child checkboxes
|
||||
root
|
||||
.querySelectorAll(".bgus_part_tooltip > .bgus_checkbox")
|
||||
.forEach((box) => {
|
||||
.forEach((box: HTMLInputElement) => {
|
||||
const tooltip = box.parentElement.nextElementSibling;
|
||||
box.addEventListener("click", function () {
|
||||
box.addEventListener("click", () => {
|
||||
tooltip
|
||||
.querySelectorAll(".bgus_checkbox")
|
||||
.forEach((el) => (el.checked = this.checked));
|
||||
.forEach((el: HTMLInputElement) => {
|
||||
el.checked = box.checked;
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
// Add event to collapse subsections
|
||||
root.querySelectorAll(".bgus_nested_element").forEach((twistie) => {
|
||||
twistie.addEventListener("click", function (evt) {
|
||||
twistie.addEventListener("click", () => {
|
||||
twistie.classList.toggle("bgus_collapsed");
|
||||
});
|
||||
});
|
||||
|
@ -322,15 +326,16 @@ export default function (root: HTMLElement, docname: string) {
|
|||
// Wrap every recipe with extra metadata
|
||||
root.querySelectorAll(".bgus_part").forEach((el: HTMLElement) => {
|
||||
if ("parts" in el.parentElement.dataset) {
|
||||
el.parentElement.dataset.parts =
|
||||
parseInt(el.parentElement.dataset.parts) +
|
||||
parseInt(el.dataset.amount);
|
||||
el.parentElement.dataset.parts = (
|
||||
parseInt(el.parentElement.dataset.parts, 10) +
|
||||
parseInt(el.dataset.amount, 10)
|
||||
).toString();
|
||||
} else {
|
||||
el.parentElement.dataset.parts = el.dataset.amount;
|
||||
}
|
||||
});
|
||||
|
||||
const setPartSize = function (labels, ml) {
|
||||
const setPartSize = (labels, ml) => {
|
||||
labels.forEach((el) => {
|
||||
const part = el.parentElement.dataset.amount;
|
||||
const total = el.parentElement.parentElement.dataset.parts;
|
||||
|
@ -340,7 +345,7 @@ export default function (root: HTMLElement, docname: string) {
|
|||
let next = el.parentElement.nextElementSibling;
|
||||
while (next) {
|
||||
if (next.classList.contains("tooltip")) {
|
||||
let sublabels = [];
|
||||
const sublabels = [];
|
||||
next.querySelector(".tooltiptext").childNodes.forEach((ch) => {
|
||||
if (ch.classList && ch.classList.contains("bgus_part")) {
|
||||
sublabels.push(ch.querySelector(".bgus_part_label"));
|
||||
|
@ -365,13 +370,13 @@ export default function (root: HTMLElement, docname: string) {
|
|||
)
|
||||
);
|
||||
const name = el.map((elem) => {
|
||||
let name = "";
|
||||
let partial = "";
|
||||
elem.childNodes.forEach((t) => {
|
||||
if (t instanceof Text) {
|
||||
name += t.textContent;
|
||||
partial += t.textContent;
|
||||
}
|
||||
});
|
||||
return name.trim();
|
||||
return partial.trim();
|
||||
});
|
||||
searchBox(
|
||||
el,
|
||||
|
@ -379,23 +384,23 @@ export default function (root: HTMLElement, docname: string) {
|
|||
);
|
||||
|
||||
// Remove "Removed medicines" section
|
||||
let remTable = root.querySelector(
|
||||
const remTable = root.querySelector(
|
||||
"#Non-craftable_Medicines + h4 + p + table"
|
||||
);
|
||||
remTable.parentElement.removeChild(remTable);
|
||||
|
||||
root
|
||||
.querySelectorAll("div[data-name] .wikitable.sortable tr")
|
||||
.forEach((el: HTMLElement) => {
|
||||
let sectionEl = el.parentElement;
|
||||
.forEach((row: HTMLElement) => {
|
||||
let sectionEl = row.parentElement;
|
||||
while (!sectionEl.dataset.name) {
|
||||
sectionEl = sectionEl.parentElement;
|
||||
}
|
||||
const section = sectionEl.dataset.name;
|
||||
if (el.querySelector("td") === null) {
|
||||
if (row.querySelector("td") === null) {
|
||||
// Remove unused rows if found
|
||||
const row = el.querySelectorAll("th");
|
||||
row.forEach((th, i) => {
|
||||
const headers = row.querySelectorAll("th");
|
||||
headers.forEach((th, i) => {
|
||||
if (i < 2) {
|
||||
th.classList.add("table-head");
|
||||
return;
|
||||
|
@ -404,7 +409,7 @@ export default function (root: HTMLElement, docname: string) {
|
|||
});
|
||||
return;
|
||||
}
|
||||
let rows = Array.from(el.querySelectorAll("td")).slice(1);
|
||||
const rows = Array.from(row.querySelectorAll("td")).slice(1);
|
||||
let treatment = null;
|
||||
let desc = null;
|
||||
let metabolism = null;
|
||||
|
@ -428,7 +433,7 @@ export default function (root: HTMLElement, docname: string) {
|
|||
// All fields
|
||||
[treatment, desc, metabolism, overdose, addiction] = rows;
|
||||
}
|
||||
const title = el.querySelector("th");
|
||||
const title = row.querySelector("th");
|
||||
let content = `<div class="reagent-header">${title.innerHTML}</div>`;
|
||||
if (treatment) {
|
||||
content += `<p class="treatment">${treatment.innerHTML}</p>`;
|
||||
|
@ -436,10 +441,10 @@ export default function (root: HTMLElement, docname: string) {
|
|||
if (metabolism) {
|
||||
content += `<p class="metabolism">${metabolism.innerHTML}</p>`;
|
||||
}
|
||||
if (addiction && addiction.innerHTML.trim() != "N/A") {
|
||||
if (addiction && addiction.innerHTML.trim() !== "N/A") {
|
||||
content += `<p class="addiction">${addiction.innerHTML}</p>`;
|
||||
}
|
||||
if (overdose && overdose.innerHTML.trim() != "N/A") {
|
||||
if (overdose && overdose.innerHTML.trim() !== "N/A") {
|
||||
content += `<p class="overdose">${overdose.innerHTML}</p>`;
|
||||
}
|
||||
if (desc) {
|
||||
|
@ -454,7 +459,7 @@ export default function (root: HTMLElement, docname: string) {
|
|||
if (addiction) addiction.parentElement.removeChild(addiction);
|
||||
});
|
||||
|
||||
document.body.addEventListener("keydown", function (ev) {
|
||||
document.body.addEventListener("keydown", (ev) => {
|
||||
if (ev.shiftKey) {
|
||||
switch (ev.keyCode) {
|
||||
// SHIFT+C = Toggle checkboxes
|
||||
|
@ -462,28 +467,36 @@ export default function (root: HTMLElement, docname: string) {
|
|||
root.classList.toggle("bgus_cbox");
|
||||
root
|
||||
.querySelectorAll(".bgus_checkbox:checked")
|
||||
.forEach((el: HTMLInputElement) => {
|
||||
el.checked = false;
|
||||
.forEach((sel: HTMLInputElement) => {
|
||||
sel.checked = false;
|
||||
});
|
||||
return;
|
||||
break;
|
||||
}
|
||||
|
||||
// SHIFT+B = Set whole size (beaker?) for parts/units
|
||||
case 66: {
|
||||
let size = parseInt(prompt("Write target ml (0 to reset)", "90"));
|
||||
if (isNaN(size) || size <= 0) {
|
||||
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((el: HTMLElement) => (el.innerHTML = el.dataset.src));
|
||||
.forEach((sel: HTMLElement) => {
|
||||
sel.innerHTML = sel.dataset.src;
|
||||
});
|
||||
return;
|
||||
}
|
||||
setPartSize(
|
||||
root.querySelectorAll("td > .bgus_part > .bgus_part_label"),
|
||||
+size
|
||||
);
|
||||
return;
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
// Do nothing
|
||||
}
|
||||
}
|
||||
});
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
const WIKI_BASE = "https://cors-anywhere.herokuapp.com/tgstation13.org/wiki";
|
||||
const WIKI_BASE = "https://tgproxy.ovo.ovh/wiki";
|
||||
|
||||
/**
|
||||
* Get HTML content of a page using Mediawiki Parse APIs
|
||||
|
@ -9,3 +9,5 @@ export async function getPageHTML(name: string): Promise<string> {
|
|||
const apiURL = `/api.php?action=parse&page=${urlname}&prop=text&format=json`;
|
||||
return (await (await fetch(WIKI_BASE + apiURL)).json()).parse.text["*"];
|
||||
}
|
||||
|
||||
export default { getPageHTML };
|
||||
|
|
|
@ -5,10 +5,19 @@
|
|||
"license": "MIT",
|
||||
"scripts": {
|
||||
"dev": "parcel index.html",
|
||||
"lint": "eslint lib",
|
||||
"build": "parcel build index.html"
|
||||
},
|
||||
"dependencies": {
|
||||
"@typescript-eslint/eslint-plugin": "^3.3.0",
|
||||
"@typescript-eslint/parser": "^3.3.0",
|
||||
"eslint": "7.2.0",
|
||||
"eslint-config-airbnb-base": "^14.2.0",
|
||||
"eslint-config-prettier": "^6.11.0",
|
||||
"eslint-plugin-import": "2.21.2",
|
||||
"eslint-plugin-prettier": "^3.1.4",
|
||||
"parcel-bundler": "^1.12.4",
|
||||
"prettier": "^2.0.5",
|
||||
"sass": "^1.26.8",
|
||||
"typescript": "^3.9.5"
|
||||
},
|
||||
|
|
Reference in a new issue