Public
HTTP (deprecated)
Val Town is a social website to write and deploy JavaScript.
Build APIs and schedule functions from your browser.
Readme

Bookmarklet Manager

Write your bookmarklets in val.town.

Usage

You val should just contain your bookmarklet code.

alert("Hi mom!");

Make sure that your val is either unlisted or public, and not named bookmarklets. Then navigate to https://pomdtr-bookmarklets.web.val.run/v/:author/:name to generate the bookmarklet link.

Sharing a bookmarklet

Make sure that your val is public, and add a #bookmarklet tag anywhere in the code.

alert("Hi mom!"); // #bookmarklet

It should automatically appears on https://pomdtr-bookmarklets.web.val.run.

⚠️ If you are using the Arc Browser, you can use the Powerlet extension to install bookmarklets.

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
/** @jsxImportSource https://esm.sh/hono@3.9.2/jsx **/
import { api } from "https://esm.town/v/pomdtr/api";
import { extractValInfo } from "https://esm.town/v/pomdtr/extractValInfo";
import { fetchText } from "https://esm.town/v/stevekrouse/fetchText?v=6";
import { Hono } from "npm:hono";
import { jsxRenderer } from "npm:hono/jsx-renderer";
import { minify } from "npm:terser";
const app = new Hono();
async function bookmarkletUrl(author: string, name: string) {
const resp = await fetch(`https://esm.town/v/${author}/${name}`);
const { code } = await minify(await resp.text());
return `javascript:(() => {${encodeURIComponent(code)}})()`;
}
app.get(
"/*",
jsxRenderer(({ children }) => {
return (
<html>
<head>
<title>Bookmarklets</title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@picocss/pico@1/css/pico.min.css" />
<link rel="icon" href="https://fav.farm/🔖" />
</head>
<body>
<main class="container">
{children}
</main>
</body>
</html>
);
}),
);
app.get("/", async c => {
const { data: vals } = await api(`/v1/search/vals?query=${encodeURIComponent("#bookmarklet")}`);
const bookmarklets = await Promise.all(
vals.filter(
val => val.name != "bookmarklets",
).map(async val => {
try {
const url = await bookmarkletUrl(val.author.username, val.name);
return { val, url };
} catch (error) {
return { val, error };
}
}),
);
return c.render(
<>
<h1>Bookmarklets</h1>
<table>
<thead>
<th scope="col">Bookmarklet</th>
<th scope="col">Val</th>
</thead>
<tbody>
{bookmarklets.map(({ val, url: bookmarkletUrl }) => {
const bookmarkletVal = {
label: `@${val.author.username}/${val.name}`,
url: new URL(`https://val.town/v/${val.author.username}/${val.name}`).href,
};
return (
<tr>
<td>
<a href={bookmarkletUrl}>{bookmarkletVal.label}</a>
</td>
<td>
<a href={bookmarkletVal.url}>View Val</a>
</td>
</tr>
);
})}
</tbody>
</table>
<a href="https://www.val.town/v/pomdtr/bookmarklets">Add your bookmarklet to this list</a>
</>,
);
});
app.get("/v/:author/:name", async c => {
const { author, name } = c.req.param();
const { privacy } = await api(`/v1/alias/${author}/${name}`);
if (privacy === "private") {
return c.notFound();
}
const label = `@${author}/${name}`;
const url = await bookmarkletUrl(author, name);
return c.render(
<a href={url}>{label}</a>,
);
});
export default app.fetch;
pomdtr-bookmarklets.web.val.run
May 11, 2024