Back to packages list

Vals using micromark

Description from the NPM package:
small commonmark compliant markdown parser with positional info and concrete tokens

mdConvert

Inspired by markdown.rest. Converts markdown (plain text or base64 encoded) to HTML (plain text or base64 encoded)

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
import { html } from "https://esm.town/v/stevekrouse/html";
import { micromark } from "npm:micromark";
import { z } from "npm:zod";
const reqBodySchema = z.object({
isBase64: z.boolean().optional(),
returnBase64: z.boolean().optional(),
content: z.string(),
});
export default async function handler(request: Request) {
if (request.method !== "POST") {
return html(`
<pre>
curl https://stevekrouse-mdConvert.web.val.run \\
-X POST \\
-d '{"content":"# Hello","returnBase64":true}'
</pre>
`);
}
try {
const body = await request.json();
const { isBase64, returnBase64, content } = reqBodySchema.parse(body);
const md = isBase64 ? atob(content) : content;
const html = returnBase64 ? btoa(micromark(md)) : micromark(md);
return new Response(html, { headers: { "Content-Type": "text/plain" } });
} catch (e) {
return Response.json({ message: e.message }, {
status: 400,
});
}
}

mdConvert

Inspired by markdown.rest. Converts markdown (plain text or base64 encoded) to HTML (plain text or base64 encoded)

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
import { html } from "https://esm.town/v/stevekrouse/html";
import { micromark } from "npm:micromark";
import { z } from "npm:zod";
const reqBodySchema = z.object({
isBase64: z.boolean().optional(),
returnBase64: z.boolean().optional(),
content: z.string(),
});
export default async function handler(request: Request) {
if (request.method !== "POST") {
return html(`
<pre>
curl https://nbbaier-mdConvert.web.val.run \\
-X POST \\
-d '{"content":"# Hello","returnBase64":true}'
</pre>
`);
}
try {
const body = await request.json();
const { isBase64, returnBase64, content } = reqBodySchema.parse(body);
const md = isBase64 ? atob(content) : content;
const html = returnBase64 ? btoa(micromark(md)) : micromark(md);
return new Response(html, { headers: { "Content-Type": "text/plain" } });
} catch (e) {
return Response.json({ message: e.message }, {
status: 400,
});
}
}

Markdown to html (with github styling)

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
export async function html(markdown: string) {
const [
{ micromark },
{ frontmatter, frontmatterHtml },
{ gfm: gfmMarkdown, gfmHtml },
] = await Promise.all([
import("npm:micromark"),
import("npm:micromark-extension-frontmatter"),
import("npm:micromark-extension-gfm"),
]);
return micromark(markdown, {
extensions: [gfmMarkdown(), frontmatter()],
htmlExtensions: [gfmHtml(), frontmatterHtml()],
});
}
export async function gfm(
markdown: string,
options?: {
title?: string;
favicon?: string | URL;
render?: (markdown: string) => Promise<string>;
},
) {
const render = options?.render ?? html;
const body = await render(markdown);
const faviconURL = new URL(options?.favicon ?? "📝", "https://fav.farm");
return `
<!DOCTYPE html>
<html>
<head>
<title>${options?.title || "Article"}</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link href="${faviconURL.href}" rel="icon">
<link href="https://cdnjs.cloudflare.com/ajax/libs/github-markdown-css/5.4.0/github-markdown.min.css" rel="stylesheet">
<link href="https://cdn.jsdelivr.net/npm/prismjs@v1.29.0/themes/prism.css" rel="stylesheet">
<style>
.markdown-body {
box-sizing: border-box;
min-width: 200px;
max-width: 980px;
margin: 0 auto;
padding: 45px;
}
@media (max-width: 767px) {
.markdown-body {
padding: 15px;
}
}
</style>
</head>
<body class="markdown-body">
${body}
<script src="https://cdn.jsdelivr.net/npm/prismjs@v1.29.0/components/prism-core.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/prismjs@v1.29.0/plugins/autoloader/prism-autoloader.min.js"></script>
</body>
</html>`;
}

Markdown to html (with github styling)

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
import { micromark } from "npm:micromark";
import { frontmatter, frontmatterHtml } from "npm:micromark-extension-frontmatter";
import { gfm as gfmMarkdown, gfmHtml } from "npm:micromark-extension-gfm";
export function html(markdown: string) {
return micromark(markdown, {
extensions: [gfmMarkdown(), frontmatter()],
htmlExtensions: [gfmHtml(), frontmatterHtml()],
});
}
export async function gfm(markdown: string, options?: { title?: string; favicon?: string | URL }) {
const body = await html(markdown);
const faviconURL = new URL(options?.favicon ?? "📝", "https://fav.farm");
return `
<!DOCTYPE html>
<html>
<head>
<title>${options?.title || "Article"}</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link href="${faviconURL.href}" rel="icon">
<link href="https://cdnjs.cloudflare.com/ajax/libs/github-markdown-css/5.4.0/github-markdown.min.css" rel="stylesheet">
<link href="https://cdn.jsdelivr.net/npm/prismjs@v1.29.0/themes/prism.css" rel="stylesheet">
<style>
.markdown-body {
box-sizing: border-box;
min-width: 200px;
max-width: 980px;
margin: 0 auto;
padding: 45px;
}
@media (max-width: 767px) {
.markdown-body {
padding: 15px;
}
}
</style>
</head>
<body class="markdown-body">
${body}
<script src="https://cdn.jsdelivr.net/npm/prismjs@v1.29.0/components/prism-core.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/prismjs@v1.29.0/plugins/autoloader/prism-autoloader.min.js"></script>
</body>
</html>`;
}

micromark

micromark is a fantastic choice for formatting Markdown: it's tiny, safe, works great with Val Town.

1
2
3
4
export let micromarkExample = (async () => {
const { micromark } = await import("npm:micromark");
return micromark("**Bold text**");
})();

Unfancy blocks

Screenshot

In the old days, there was a website called bl.ocks.org which re-hosted content on GitHub Gists and displayed visualizations made in those gists. It wasn't shiny but it was well-crafted and for the little community that used it, it was very nice.

This is a much worse, but very small, version of the same kind of program. This also shows you stuff from blocks. It displays readmes, with Titus's lovely micromark. It uses Ian's collected search index of bl.ocks.org to show you examples and thumbnails. It uses Alpine to pull together a little interface. And, of course, Val Town to make it all work.

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
import { fetch } from "https://esm.town/v/std/fetch";
export let blocks = async (req, res) => {
const { micromark } = await import("npm:micromark");
const [_, user, id, ...file] = req.path.split("/");
if (!user) {
return res.send(`
<html>
<script src="https://cdn.tailwindcss.com?plugins=typography"></script>
<script defer src="https://cdn.jsdelivr.net/npm/alpinejs@3.x.x/dist/cdn.min.js"></script>
<body class='p-20 bg-stone-100'>
<div
x-data="{ page: 0, blocks: [],
get filteredBlocks() {
return this.blocks.filter(block => block.thumbnail)
.reverse()
.map(block => {
return {
...block,
href: '/' + block.userId + '/' + block.id
}
}).slice(this.page * 100, (this.page + 1) * 100)
}
}"
x-init="blocks = await (await fetch('https://storage.googleapis.com/bb-search-data/parsed/blocks-min.json')).json()"
>
<div class='grid gap-4 grid-cols-4 lg:grid-cols-8'>
<template x-for="block in filteredBlocks">
<a class="aspect-square p-4 block" x-bind:href="block.href">
<div>
<span x-text="block.description"></span>
by <span x-text="block.userId"></span>
</div>
<template x-if="block.thumbnail">
<img x-bind:src="block.thumbnail" class='w-full' />
</template>
</a>
</template>
</div>
<div class='flex items-center justify-center gap-x-2 pt-20'>
Page <div x-text="page"></div>
<template x-if="page > 0">
<button @click="page--">Previous page</button>
</template>
<button @click="page++">Next page</button>
</div>
</div>
</body>
</body>
</html>`);
}
const gistRes = await fetch(`https://api.github.com/gists/${id}`);
if (!gistRes.ok) {
return res.send("GitHub replied with a non-200 status.");
}
const gist = await gistRes.json();
const readme = gist.files["README.md"];
const blocks = gist.files[".block"];
let height = 700;
if (blocks) {
const { parse } = await import("npm:yaml");
try {
const v = parse(blocks.content);
if (v.height) {
height = +v.height;
}
}
catch (e) {
}
}
res.set("Cache-Control", "public,max-age=64800");
return res.send(`
<html>
<script src="https://cdn.tailwindcss.com?plugins=typography"></script>
<body class='bg-stone-100'>
<div class='max-w-5xl mx-auto py-10'>
<div class='prose'>
<a href='https://tmcw-blocks.express.val.run/'>unfancy blocks</a> /
<a href='https://gist.github.com/${user}/${id}'>gist: ${user}/${id}</a>
<hr />
${readme ? micromark(readme.content) : ""}
${
blocks?.content
? `<h4>.blocks</h4><pre><code>${blocks?.content.trim()}</code></pre>`
: ""
}
</div>
<iframe style='height:${height}px;' class='mt-10 w-full border border-black' src='https://tmcw-blocks_inner.express.val.run/${user}/${id}/'>
</iframe>
</div>
</body>
</html>`);
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import { buildLayout } from "https://esm.town/v/nbbaier/buildLayout";
export const micromarkTest = async (
req: express.Request,
res: express.Response
) => {
const { micromark } = await import("npm:micromark");
const md = "*emphasis* and **strong**";
res.send(
buildLayout({
body: micromark(md),
})
);
// res.send(micromark(md));
};
1
Next