postpostscript-readmemanager.web.val.run
Readme

@postpostscript/readmeManager: Edit Val Readmes With Persistent Drafts

edit this readme

image.png

image.png

Todo:

  • Upload images
  • Autosave/save without reloading page
  • Ctrl+S
  • Multiple draft versions
  • Switch to dark codemirror theme which has markdown styling
  • Allow for checking checkboxes in preview
    • View with just the preview
  • Ability to favorite vals on the Home page
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
/** @jsxImportSource https://esm.sh/hono/jsx */
import { fetchPaginatedData } from "https://esm.town/v/nbbaier/fetchPaginatedData?v=49";
import { api } from "https://esm.town/v/pomdtr/api?v=12";
import { extractValInfo } from "https://esm.town/v/pomdtr/extractValInfo?v=26";
import { authMiddlewareCookie, type HonoEnv } from "https://esm.town/v/postpostscript/authMiddleware";
import { html } from "https://esm.town/v/postpostscript/html";
import { updateValReadme } from "https://esm.town/v/postpostscript/updateValReadme";
import { API_URL } from "https://esm.town/v/std/API_URL?v=5";
import { blob } from "https://esm.town/v/std/blob?v=11";
import { type Context, Hono } from "npm:hono";
const app = new Hono<HonoEnv>();
app.use(
"*",
authMiddlewareCookie({
optional: true,
}),
);
export const DRAFT_PREFIX = "readmeManager:draft";
const styles = `
img {
max-width: 100%;
}
`;
app.all("/:author/:name", async (c) => {
const { pathname } = new URL(c.req.url);
const author = c.req.param("author");
const name = c.req.param("name");
let { id, readme } = await api(`/v1/alias/${author}/${name}`);
const blobID = `${DRAFT_PREFIX}:${id}`;
let draft;
if (c.get("auth")) {
if (c.req.method === "POST") {
const formData = await c.req.formData();
const submitType = formData.get("submit");
if (formData.get("readme")) {
if (submitType === "publish") {
await updateValReadme(id, formData.get("readme"));
return c.redirect(`/${author}/${name}`);
} else {
await blob.setJSON(blobID, formData.get("readme"));
return c.redirect(`/${author}/${name}?draft=1`);
}
}
} else {
draft = await blob.getJSON(blobID);
}
if (c.req.query("draft") && draft) {
readme = draft;
}
}
return c.html(
<html data-bs-theme="dark">
<head>
<link
href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css"
rel="stylesheet"
crossorigin="anonymous"
/>
<link
href="https://cdnjs.cloudflare.com/ajax/libs/github-markdown-css/5.4.0/github-markdown.min.css"
rel="stylesheet"
/>
<script
type="module"
src="https://cdn.jsdelivr.net/npm/code-mirror-web-component@0.0.16/dist/code-mirror.js"
>
</script>
<script src="https://cdn.jsdelivr.net/npm/marked/marked.min.js"></script>
<script
type="module"
dangerouslySetInnerHTML={{
__html: html`
import debounce from 'https://esm.sh/debounce';
async function render(text) {
window.result.innerHTML = await marked.parse(text);
document.getElementById('readme-input').value = text
}
document.addEventListener("DOMContentLoaded", () => {
const $editor = document.createElement('code-mirror')
$editor.setAttribute('id', 'editor')
$editor.setAttribute('theme', 'dracula')
$editor.setAttribute('language', 'markdown')
$editor.setAttribute('code', decodeURIComponent("${encodeURIComponent(readme ?? "")}"))
$editor.setAttribute('class', 'h-100')
$editor.addEventListener("code-change", (e) => {
render(e.detail.code)
})
render($editor.getAttribute('code'));
document.getElementById('editor-col').appendChild($editor)
})
Val Town is a social website to write and deploy JavaScript.
Build APIs and schedule functions from your browser.
Comments
Nobody has commented on this val yet: be the first!
v241
March 16, 2024