Back to packages list

Vals using preact

Description from the NPM package:
Fast 3kb React-compatible Virtual DOM library.

Val Town email subscriptions: generate newsletter template

Cousin Val to @petermillspaugh/emailSubscription — see docs there.

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
/** @jsxImportSource https://esm.sh/preact */
import { JSX } from "npm:preact";
interface NewsletterJsxParams {
webUrl: string;
newsletterContent: JSX.Element;
emailAddress: string;
}
export function generateNewsletterJsx({ webUrl, newsletterContent, emailAddress }) {
return (
<main>
<header>
<p>
<em>
You can also read the <a href={webUrl}>Web version</a> of this clipping.
</em>
</p>
</header>
{newsletterContent}
<footer>
<hr />
<p>
<em>
This clipping was sent via my{" "}
<a href="https://petemillspaugh.com/cultivating-emails">custom email newsletter logic</a> built with{" "}
<a href="https://val.town">Val Town</a>.
</em>
</p>
<p>
<a href={`https://petermillspaugh-unsubscribeFromNewsletter.web.val.run?email=${emailAddress}`}>
Unsubscribe
</a>
</p>
</footer>
</main>
);
}
1
2
3
4
5
6
7
8
9
10
/** @jsxImportSource npm:preact */
import type { VNode } from "npm:preact";
import { render } from "npm:preact-render-to-string";
export const html = (html: VNode) =>
render(
<div id="root">
{html}
</div>,
);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
import { html } from "https://esm.town/v/neverstew/html";
import type { VNode } from "npm:preact";
export const htmlResponse = (htmlNode: VNode, options?: ResponseInit) =>
new Response(
html(htmlNode),
{
...options,
headers: {
"Content-Type": "text/html",
...options?.headers,
},
},
);

@easrng.preactWebApp

Example Make a web app on val.town with server-side rendered Preact components

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
export const preactWebApp = (function () {
type propType =
& {
setHeaders: (headers: {
[key: string]: string | string[];
}) => void;
setStatus: (status: number) => void;
req: express.Request;
html: (
strings: TemplateStringsArray,
...values: any[]
) =>
| import("npm:preact@10.17.0").VNode<
import("npm:preact@10.17.0").Attributes
>
| import("npm:preact@10.17.0").VNode<
import("npm:preact@10.17.0").Attributes
>[];
}
& typeof import("npm:preact@10.17.0")
& typeof import("npm:preact@10.17.0/hooks");
const preactWebApp =
(App: (_: propType) => import("npm:preact@10.17.0").VNode) =>
async (req: express.Request, res: express.Response) => {
const preact = await import("npm:preact@10.17.0");
const hooks = await import("npm:preact@10.17.0/hooks");
const _renderToString = await import("npm:preact-render-to-string@6.2.1");
const { renderToString } = _renderToString;
const { default: htm } = await import("npm:htm@3.1.1");
const html = htm.bind(preact.h);
try {
let status = 200;
let headers: {
[key: string]: string | string[];
} = {};
const props: propType = {
html,
req,
setStatus: (s: number) => {
status = s;
},
setHeaders: (h: typeof headers) => {
headers = h;
},
...preact,
...hooks,
};
const renderedHtml = "<!DOCTYPE html>" +
renderToString(await App(props));
for (const [k, v] of Object.entries(headers))
res.set(k, v);
res.status(status);
res.send(renderedHtml);
}
catch (e) {
const etext = e.stack || JSON.stringify(e);
console.error(etext);
res.status(500);
res.send(renderToString(preact.h(
"html",
null,
html`
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<style>html{font-family:sans-serif;color-scheme:dark light;padding:1rem}h1{font-size:2.5rem;font-weight:300;margin:1rem 0}pre{overflow-x:auto;color:GrayText;white-space:pre-wrap;word-wrap:break-word}</style>
<h1>error running val</h1>
<pre>${etext}</pre>
`,
)));
}
};
preactWebApp.props = {} as propType;
return preactWebApp;
}).call(this);
1
Next