summaryrefslogtreecommitdiff
path: root/internal/mdedit/res
diff options
context:
space:
mode:
authorStefan Majewsky <majewsky@gmx.net>2025-09-30 13:34:10 +0200
committerStefan Majewsky <majewsky@gmx.net>2025-09-30 13:37:25 +0200
commite75d9e371269a4e46bffa6b3dd1fc7d040e82750 (patch)
treec1f2a9aa8022a2710af5e5a577578855584540df /internal/mdedit/res
parent0bb27576a37de4bf76dab35c73fa8790fcfa706a (diff)
downloadgofu-e75d9e371269a4e46bffa6b3dd1fc7d040e82750.tar.gz
add mdeditv2025.1
Diffstat (limited to 'internal/mdedit/res')
-rw-r--r--internal/mdedit/res/app.js67
-rw-r--r--internal/mdedit/res/index.html18
-rw-r--r--internal/mdedit/res/style.css48
3 files changed, 133 insertions, 0 deletions
diff --git a/internal/mdedit/res/app.js b/internal/mdedit/res/app.js
new file mode 100644
index 0000000..c934697
--- /dev/null
+++ b/internal/mdedit/res/app.js
@@ -0,0 +1,67 @@
+(() => {
+ const $ = selector => document.querySelector(selector);
+
+ const handleResponse = (promise, action) => {
+ const error = promise.then(response => {
+ if (!response.ok) {
+ throw new Error(`HTTP error, status = ${response.status} from ${response.url}`);
+ }
+ const title = response.headers.get("X-Mdedit-Path");
+ if (title !== null && title !== "") {
+ window.document.title = "mdedit: " + title;
+ $("span#title").innerText = title;
+ }
+ return response.text();
+ }).then(body => {
+ action(body);
+ return null;
+ }).catch((error) => {
+ return error;
+ }).then((error) => {
+ if (error != null) {
+ console.log(error);
+ $("span#status").innerText = `Error: ${error.message}`;
+ }
+ });
+ };
+
+ // handler for receiving a rendered HTML from the server
+ const receiveHTML = body => {
+ $("div#preview").innerHTML = body;
+ $("span#status").innerText = "Saved";
+ };
+
+ // whenever the <textedit> changes, wait 3 seconds and then save all changes
+ let timeoutID = null;
+ const onTextChange = event => {
+ if (timeoutID !== null) {
+ window.clearTimeout(timeoutID);
+ }
+ timeoutID = window.setTimeout(uploadMarkdown, 1000);
+ $("span#status").innerText = "Changed";
+ };
+ const uploadMarkdown = () => {
+ window.clearTimeout(timeoutID);
+ timeoutID = null;
+ $("span#status").innerText = "Saving...";
+
+ const opts = {
+ method: "PUT",
+ body: $("textarea#editor").value,
+ };
+ handleResponse(fetch("/data.md", opts), receiveHTML);
+ };
+
+ // load Markdown and rendered HTML on startup
+ handleResponse(fetch("/data.md"), body => {
+ const editor = $("textarea#editor");
+ $("textarea#editor").value = body;
+ handleResponse(fetch("/data.html"), receiveHTML);
+
+ // avoid a useless upload on startup by attaching this only after the initial load is done
+ for (const eventType of ["change", "input", "textInput"]) {
+ editor.addEventListener(eventType, onTextChange);
+ }
+ });
+
+})();
diff --git a/internal/mdedit/res/index.html b/internal/mdedit/res/index.html
new file mode 100644
index 0000000..20aea13
--- /dev/null
+++ b/internal/mdedit/res/index.html
@@ -0,0 +1,18 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset="utf-8">
+ <meta http-equiv="X-UA-Compatible" content="IE=edge" />
+ <meta name="viewport" content="width=device-width, initial-scale=1">
+ <title>mdedit</title>
+ <link rel="stylesheet" type="text/css" href="/res.css" />
+</head>
+<body>
+ <nav>
+ <span id="title">mdedit</span>: <span id="status">Loading...</span>
+ </nav>
+ <textarea id="editor"></textarea>
+ <div id="preview"></div>
+</body>
+<script src="/res.js"></script>
+</html>
diff --git a/internal/mdedit/res/style.css b/internal/mdedit/res/style.css
new file mode 100644
index 0000000..01cd0c2
--- /dev/null
+++ b/internal/mdedit/res/style.css
@@ -0,0 +1,48 @@
+:root {
+ height: 100vh;
+ overflow: none;
+}
+
+body {
+ display: grid;
+ margin: 0;
+ padding: 0;
+ grid-template-rows: 2rem 1fr;
+ grid-template-columns: 1fr 1fr;
+ grid-template-areas: "nav nav" "editor preview";
+ overflow: hidden;
+ height: 100vh;
+ font-family: system-ui, sans-serif;
+
+ & > nav { grid-area: nav; }
+ & > textarea#editor { grid-area: editor; }
+ & > div#preview { grid-area: preview; }
+}
+
+nav {
+ height: 2rem;
+ line-height: 2rem;
+ padding: 0 1rem;
+ background: #111;
+ color: white;
+
+ & > span#title { font-weight: bold; }
+}
+
+textarea#editor {
+ margin: 0;
+ border: none;
+ background: #333;
+ color: white;
+
+ resize: none;
+ overflow-y: scroll;
+ height: 100%;
+}
+
+div#preview {
+ padding: 0 1rem;
+
+ overflow: scroll;
+ height: 100%;
+}