move script from main to handlers
This commit is contained in:
15
cmd/main.go
15
cmd/main.go
@@ -19,9 +19,6 @@ import (
|
|||||||
//go:embed styles.css
|
//go:embed styles.css
|
||||||
var cssData embed.FS
|
var cssData embed.FS
|
||||||
|
|
||||||
//go:embed script.js
|
|
||||||
var scriptData embed.FS
|
|
||||||
|
|
||||||
//go:embed VERSION
|
//go:embed VERSION
|
||||||
var version string
|
var version string
|
||||||
|
|
||||||
@@ -169,17 +166,7 @@ func main() {
|
|||||||
return c.Send(cssData)
|
return c.Send(cssData)
|
||||||
})
|
})
|
||||||
|
|
||||||
// TODO: move to handlers/script.go
|
app.Get("/script.js", handlers.Script)
|
||||||
app.Get("/script.js", func(c *fiber.Ctx) error {
|
|
||||||
scriptData, err := scriptData.ReadFile("script.js")
|
|
||||||
if err != nil {
|
|
||||||
return c.Status(fiber.StatusInternalServerError).SendString("Internal Server Error")
|
|
||||||
}
|
|
||||||
|
|
||||||
c.Set("Content-Type", "text/javascript")
|
|
||||||
|
|
||||||
return c.Send(scriptData)
|
|
||||||
})
|
|
||||||
|
|
||||||
app.Get("ruleset", handlers.Ruleset)
|
app.Get("ruleset", handlers.Ruleset)
|
||||||
app.Get("raw/*", handlers.Raw)
|
app.Get("raw/*", handlers.Raw)
|
||||||
|
|||||||
23
handlers/script.go
Normal file
23
handlers/script.go
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
package handlers
|
||||||
|
|
||||||
|
import (
|
||||||
|
"embed"
|
||||||
|
|
||||||
|
"github.com/gofiber/fiber/v2"
|
||||||
|
)
|
||||||
|
|
||||||
|
//go:embed script.js
|
||||||
|
var scriptData embed.FS
|
||||||
|
|
||||||
|
func Script(c *fiber.Ctx) error {
|
||||||
|
|
||||||
|
scriptData, err := scriptData.ReadFile("script.js")
|
||||||
|
if err != nil {
|
||||||
|
return c.Status(fiber.StatusInternalServerError).SendString("Internal Server Error")
|
||||||
|
}
|
||||||
|
|
||||||
|
c.Set("Content-Type", "text/javascript")
|
||||||
|
|
||||||
|
return c.Send(scriptData)
|
||||||
|
|
||||||
|
}
|
||||||
296
handlers/script.js
Normal file
296
handlers/script.js
Normal file
@@ -0,0 +1,296 @@
|
|||||||
|
const labels = document.querySelectorAll("label");
|
||||||
|
const inputs = document.querySelectorAll('input[type="radio"]');
|
||||||
|
const mainElement = document.querySelector("main");
|
||||||
|
|
||||||
|
const handleDOMContentLoaded = () => {
|
||||||
|
handleFontChange();
|
||||||
|
handleFontSizeChange();
|
||||||
|
inputs.forEach((input) => {
|
||||||
|
const storedValue = localStorage.getItem(input.name);
|
||||||
|
if (storedValue === input.value) {
|
||||||
|
input.checked = true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
window.removeEventListener("DOMContentLoaded", handleDOMContentLoaded);
|
||||||
|
};
|
||||||
|
|
||||||
|
function focusable_children(node) {
|
||||||
|
const nodes = Array.from(
|
||||||
|
node.querySelectorAll(
|
||||||
|
'a[href], button, input, textarea, select, details, [tabindex]:not([tabindex="-1"])'
|
||||||
|
)
|
||||||
|
).filter((s) => s.offsetParent !== null);
|
||||||
|
const index = nodes.indexOf(document.activeElement);
|
||||||
|
const update = (d) => {
|
||||||
|
let i = index + d;
|
||||||
|
i += nodes.length;
|
||||||
|
i %= nodes.length;
|
||||||
|
nodes[i].focus();
|
||||||
|
};
|
||||||
|
return {
|
||||||
|
next: (selector) => {
|
||||||
|
const reordered = [
|
||||||
|
...nodes.slice(index + 1),
|
||||||
|
...nodes.slice(0, index + 1),
|
||||||
|
];
|
||||||
|
for (let i = 0; i < reordered.length; i += 1) {
|
||||||
|
if (!selector || reordered[i].matches(selector)) {
|
||||||
|
reordered[i].focus();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
prev: (selector) => {
|
||||||
|
const reordered = [
|
||||||
|
...nodes.slice(index + 1),
|
||||||
|
...nodes.slice(0, index + 1),
|
||||||
|
];
|
||||||
|
for (let i = reordered.length - 2; i >= 0; i -= 1) {
|
||||||
|
if (!selector || reordered[i].matches(selector)) {
|
||||||
|
reordered[i].focus();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
update,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function trap(node) {
|
||||||
|
const handle_keydown = (e) => {
|
||||||
|
if (e.key === "Tab") {
|
||||||
|
e.preventDefault();
|
||||||
|
const group = focusable_children(node);
|
||||||
|
if (e.shiftKey) {
|
||||||
|
group.prev();
|
||||||
|
} else {
|
||||||
|
group.next();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
node.addEventListener("keydown", handle_keydown);
|
||||||
|
return {
|
||||||
|
destroy: () => {
|
||||||
|
node.removeEventListener("keydown", handle_keydown);
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
const toggleDropdown = () => {
|
||||||
|
const dropdown = document.getElementById("dropdown");
|
||||||
|
const dropdown_panel = document.getElementById("dropdown_panel");
|
||||||
|
const focusTrap = trap(dropdown);
|
||||||
|
|
||||||
|
const closeDropdown = () => {
|
||||||
|
dropdown_panel.classList.add("hidden");
|
||||||
|
focusTrap.destroy();
|
||||||
|
dropdown.removeEventListener("keydown", handleEscapeKey);
|
||||||
|
document.removeEventListener("click", handleClickOutside);
|
||||||
|
inputs.forEach((input) => {
|
||||||
|
input.removeEventListener("change", handleInputChange);
|
||||||
|
});
|
||||||
|
labels.forEach((label) => {
|
||||||
|
label.removeEventListener("click", handleLabelSelection);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleClickOutside = (e) => {
|
||||||
|
if (!dropdown.contains(e.target)) {
|
||||||
|
closeDropdown();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleEscapeKey = (e) => {
|
||||||
|
if (e.key === "Escape") {
|
||||||
|
dropdown_panel.classList.add("hidden");
|
||||||
|
closeDropdown();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleInputChange = (e) => {
|
||||||
|
if (e.target.checked) {
|
||||||
|
localStorage.setItem(e.target.name, e.target.value);
|
||||||
|
switch (e.target.name) {
|
||||||
|
case "theme": {
|
||||||
|
handleThemeChange();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case "font": {
|
||||||
|
handleFontChange();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case "fontsize": {
|
||||||
|
handleFontSizeChange();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default: {
|
||||||
|
console.error("Unknown event");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleLabelSelection = (e) => {
|
||||||
|
if (e.key === "Enter" || e.key === " ") {
|
||||||
|
e.preventDefault();
|
||||||
|
const input = document.getElementById(e.target.getAttribute("for"));
|
||||||
|
input.checked = true;
|
||||||
|
input.dispatchEvent(new Event("change", { bubbles: true }));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if (dropdown_panel.classList.contains("hidden")) {
|
||||||
|
dropdown_panel.classList.remove("hidden");
|
||||||
|
dropdown.addEventListener("keydown", handleEscapeKey);
|
||||||
|
inputs.forEach((input) => {
|
||||||
|
input.addEventListener("change", handleInputChange);
|
||||||
|
});
|
||||||
|
labels.forEach((label) => {
|
||||||
|
label.addEventListener("keydown", handleLabelSelection);
|
||||||
|
});
|
||||||
|
document.addEventListener("click", handleClickOutside);
|
||||||
|
} else {
|
||||||
|
closeDropdown();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleFontChange = () => {
|
||||||
|
if (mainElement === null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let font = localStorage.getItem("font");
|
||||||
|
if (font === null) {
|
||||||
|
localStorage.setItem("font", "sans-serif");
|
||||||
|
font = "sans-serif";
|
||||||
|
}
|
||||||
|
if (font === "serif") {
|
||||||
|
mainElement.classList.add("font-serif");
|
||||||
|
mainElement.classList.remove("font-sans");
|
||||||
|
} else {
|
||||||
|
mainElement.classList.add("font-sans");
|
||||||
|
mainElement.classList.remove("font-serif");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const changeFontSize = (node, classes) => {
|
||||||
|
const sizes = [
|
||||||
|
"text-xs",
|
||||||
|
"text-sm",
|
||||||
|
"text-base",
|
||||||
|
"text-lg",
|
||||||
|
"text-xl",
|
||||||
|
"text-2xl",
|
||||||
|
"text-3xl",
|
||||||
|
"text-4xl",
|
||||||
|
"text-5xl",
|
||||||
|
"lg:text-4xl",
|
||||||
|
"lg:text-5xl",
|
||||||
|
"lg:text-6xl",
|
||||||
|
];
|
||||||
|
const currentClasses = sizes.filter((size) => node.classList.contains(size));
|
||||||
|
node.classList.remove(...currentClasses);
|
||||||
|
node.classList.add(...classes);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleFontSizeChange = () => {
|
||||||
|
if (mainElement === null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let fontSize = localStorage.getItem("fontsize");
|
||||||
|
if (fontSize === null) {
|
||||||
|
localStorage.setItem("fontsize", "text-base");
|
||||||
|
fontSize = "text-base";
|
||||||
|
}
|
||||||
|
if (fontSize === "text-sm") {
|
||||||
|
changeFontSize(document.querySelector("body"), ["text-sm"]);
|
||||||
|
} else if (fontSize === "text-lg") {
|
||||||
|
changeFontSize(document.querySelector("body"), ["text-lg"]);
|
||||||
|
} else {
|
||||||
|
changeFontSize(document.querySelector("body"), ["text-base"]);
|
||||||
|
}
|
||||||
|
|
||||||
|
const nodes = document.querySelectorAll(
|
||||||
|
"h1, h2, h3, h4, h5, h6, code, pre, kbd, table"
|
||||||
|
);
|
||||||
|
if (fontSize === "text-sm") {
|
||||||
|
changeFontSize(mainElement, ["text-sm"]);
|
||||||
|
} else if (fontSize === "text-lg") {
|
||||||
|
changeFontSize(mainElement, ["text-lg"]);
|
||||||
|
} else {
|
||||||
|
changeFontSize(mainElement, ["text-base"]);
|
||||||
|
}
|
||||||
|
nodes.forEach((node) => {
|
||||||
|
let classes = "";
|
||||||
|
switch (node.tagName) {
|
||||||
|
case "H1": {
|
||||||
|
if (fontSize === "text-sm") {
|
||||||
|
classes = ["text-3xl", "lg:text-4xl"];
|
||||||
|
} else if (fontSize === "text-lg") {
|
||||||
|
classes = ["text-5xl", "lg:text-6xl"];
|
||||||
|
} else {
|
||||||
|
classes = ["text-4xl", "lg:text-5xl"];
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case "H2": {
|
||||||
|
if (fontSize === "text-sm") {
|
||||||
|
classes = ["text-2xl"];
|
||||||
|
} else if (fontSize === "text-lg") {
|
||||||
|
classes = ["text-4xl"];
|
||||||
|
} else {
|
||||||
|
classes = ["text-3xl"];
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case "H3": {
|
||||||
|
if (fontSize === "text-sm") {
|
||||||
|
classes = ["text-xl"];
|
||||||
|
} else if (fontSize === "text-lg") {
|
||||||
|
classes = ["text-3xl"];
|
||||||
|
} else {
|
||||||
|
classes = ["text-2xl"];
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case "H4":
|
||||||
|
case "H5":
|
||||||
|
case "H6": {
|
||||||
|
if (fontSize === "text-sm") {
|
||||||
|
classes = ["text-lg"];
|
||||||
|
} else if (fontSize === "text-lg") {
|
||||||
|
classes = ["text-2xl"];
|
||||||
|
} else {
|
||||||
|
classes = ["text-xl"];
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case "CODE":
|
||||||
|
case "PRE":
|
||||||
|
case "KBD":
|
||||||
|
case "TABLE": {
|
||||||
|
if (fontSize === "text-sm") {
|
||||||
|
classes = ["text-xs"];
|
||||||
|
} else if (fontSize === "text-lg") {
|
||||||
|
classes = ["text-base"];
|
||||||
|
} else {
|
||||||
|
classes = ["text-sm"];
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default: {
|
||||||
|
if (fontSize === "text-sm") {
|
||||||
|
classes = ["text-sm"];
|
||||||
|
} else if (fontSize === "text-lg") {
|
||||||
|
classes = ["text-lg"];
|
||||||
|
} else {
|
||||||
|
classes = ["text-base"];
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
changeFontSize(node, classes);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
window.addEventListener("DOMContentLoaded", handleDOMContentLoaded);
|
||||||
Reference in New Issue
Block a user