Add html tagged template literal
This commit is contained in:
parent
f2fee64925
commit
2724333412
121
index.ts
121
index.ts
|
@ -8,6 +8,7 @@ import { JSDOM } from "jsdom";
|
||||||
import { promises as fs } from "fs";
|
import { promises as fs } from "fs";
|
||||||
import writeFileAtomic from "write-file-atomic";
|
import writeFileAtomic from "write-file-atomic";
|
||||||
import cryptoRandomString from "crypto-random-string";
|
import cryptoRandomString from "crypto-random-string";
|
||||||
|
import html from "tagged-template-noop";
|
||||||
|
|
||||||
export const WEB_PORT = process.env.WEB_PORT ?? 8000;
|
export const WEB_PORT = process.env.WEB_PORT ?? 8000;
|
||||||
export const EMAIL_PORT = process.env.EMAIL_PORT ?? 2525;
|
export const EMAIL_PORT = process.env.EMAIL_PORT ?? 2525;
|
||||||
|
@ -36,7 +37,7 @@ export const webServer = express()
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
res.send(
|
res.send(
|
||||||
layout(`
|
layout(html`
|
||||||
<p><strong>“${H(name)}” Inbox Created</strong></p>
|
<p><strong>“${H(name)}” Inbox Created</strong></p>
|
||||||
${renderedCreated}
|
${renderedCreated}
|
||||||
`)
|
`)
|
||||||
|
@ -121,42 +122,76 @@ async function addEntryToFeed(
|
||||||
}
|
}
|
||||||
await writeFileAtomic(
|
await writeFileAtomic(
|
||||||
path,
|
path,
|
||||||
`<?xml version="1.0" encoding="utf-8"?>${feed.serialize()}`
|
html`<?xml version="1.0" encoding="utf-8"?>${feed.serialize()}`.trim()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function layout(content: string): string {
|
function layout(content: string): string {
|
||||||
return `<!DOCTYPE html>
|
return html`
|
||||||
|
<!DOCTYPE html>
|
||||||
<html lang="en">
|
<html lang="en">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8" />
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
<title>Kill the Newsletter!</title>
|
<title>Kill the Newsletter!</title>
|
||||||
<meta name="author" content="Leandro Facchinetti">
|
<meta name="author" content="Leandro Facchinetti" />
|
||||||
<meta name="description" content="Convert email newsletters into Atom feeds.">
|
<meta
|
||||||
<link rel="icon" type="image/png" sizes="32x32" href="/favicon-32x32.png">
|
name="description"
|
||||||
<link rel="icon" type="image/png" sizes="16x16" href="/favicon-16x16.png">
|
content="Convert email newsletters into Atom feeds."
|
||||||
<link rel="icon" type="image/x-icon" href="/favicon.ico">
|
/>
|
||||||
<link rel="stylesheet" type="text/css" href="/styles.css">
|
<link
|
||||||
|
rel="icon"
|
||||||
|
type="image/png"
|
||||||
|
sizes="32x32"
|
||||||
|
href="/favicon-32x32.png"
|
||||||
|
/>
|
||||||
|
<link
|
||||||
|
rel="icon"
|
||||||
|
type="image/png"
|
||||||
|
sizes="16x16"
|
||||||
|
href="/favicon-16x16.png"
|
||||||
|
/>
|
||||||
|
<link rel="icon" type="image/x-icon" href="/favicon.ico" />
|
||||||
|
<link rel="stylesheet" type="text/css" href="/styles.css" />
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<header>
|
<header>
|
||||||
<h1><a href="/">Kill the Newsletter!</a></h1>
|
<h1><a href="/">Kill the Newsletter!</a></h1>
|
||||||
<p>Convert email newsletters into Atom feeds</p>
|
<p>Convert email newsletters into Atom feeds</p>
|
||||||
<p><img src="/logo.svg" alt="Convert email newsletters into Atom feeds"></p>
|
<p>
|
||||||
|
<img
|
||||||
|
src="/logo.svg"
|
||||||
|
alt="Convert email newsletters into Atom feeds"
|
||||||
|
/>
|
||||||
|
</p>
|
||||||
</header>
|
</header>
|
||||||
<main>${content}</main>
|
<main>${content}</main>
|
||||||
<footer><p>By <a href="https://leafac.com">Leandro Facchinetti</a> · <a href="https://github.com/leafac/kill-the-newsletter.com">Source</a> · <a href="${ISSUE_REPORT}">Report an Issue</a></p></footer>
|
<footer>
|
||||||
|
<p>
|
||||||
|
By <a href="https://leafac.com">Leandro Facchinetti</a> ·
|
||||||
|
<a href="https://github.com/leafac/kill-the-newsletter.com"
|
||||||
|
>Source</a
|
||||||
|
>
|
||||||
|
· <a href="${ISSUE_REPORT}">Report an Issue</a>
|
||||||
|
</p>
|
||||||
|
</footer>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
`;
|
`.trim();
|
||||||
}
|
}
|
||||||
|
|
||||||
function newInbox(): string {
|
function newInbox(): string {
|
||||||
return `
|
return html`
|
||||||
<form method="POST" action="/">
|
<form method="POST" action="/">
|
||||||
<p>
|
<p>
|
||||||
<input type="text" name="name" placeholder="Newsletter Name…" maxlength="500" size="30" required>
|
<input
|
||||||
|
type="text"
|
||||||
|
name="name"
|
||||||
|
placeholder="Newsletter Name…"
|
||||||
|
maxlength="500"
|
||||||
|
size="30"
|
||||||
|
required
|
||||||
|
/>
|
||||||
<button>Create Inbox</button>
|
<button>Create Inbox</button>
|
||||||
</p>
|
</p>
|
||||||
</form>
|
</form>
|
||||||
|
@ -164,33 +199,45 @@ function newInbox(): string {
|
||||||
}
|
}
|
||||||
|
|
||||||
function created(identifier: string): string {
|
function created(identifier: string): string {
|
||||||
return `
|
return html`
|
||||||
<p>Sign up for the newsletter with<br><code>${feedEmail(
|
<p>
|
||||||
identifier
|
Sign up for the newsletter with<br /><code>${feedEmail(identifier)}</code>
|
||||||
)}</code></p>
|
</p>
|
||||||
<p>Subscribe to the Atom feed at<br><code>${feedURL(identifier)}</code></p>
|
<p>
|
||||||
<p>Don’t share these addresses.<br>They contain an identifier that other people could use<br>to send you spam and to control your newsletter subscriptions.</p>
|
Subscribe to the Atom feed at<br /><code>${feedURL(identifier)}</code>
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
Don’t share these addresses.<br />They contain an identifier that other
|
||||||
|
people could use<br />to send you spam and to control your newsletter
|
||||||
|
subscriptions.
|
||||||
|
</p>
|
||||||
<p>Enjoy your readings!</p>
|
<p>Enjoy your readings!</p>
|
||||||
<p><a href="${BASE_URL}"><strong>Create Another Inbox</strong></a></p>
|
<p>
|
||||||
|
<a href="${BASE_URL}"><strong>Create Another Inbox</strong></a>
|
||||||
|
</p>
|
||||||
`.trim();
|
`.trim();
|
||||||
}
|
}
|
||||||
|
|
||||||
function feed(identifier: string, name: string): string {
|
function feed(identifier: string, name: string): string {
|
||||||
return `<?xml version="1.0" encoding="utf-8"?>
|
return html`
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<feed xmlns="http://www.w3.org/2005/Atom">
|
<feed xmlns="http://www.w3.org/2005/Atom">
|
||||||
<link rel="self" type="application/atom+xml" href="${feedURL(
|
<link
|
||||||
identifier
|
rel="self"
|
||||||
)}"/>
|
type="application/atom+xml"
|
||||||
<link rel="alternate" type="text/html" href="${BASE_URL}"/>
|
href="${feedURL(identifier)}"
|
||||||
|
/>
|
||||||
|
<link rel="alternate" type="text/html" href="${BASE_URL}" />
|
||||||
<id>${urn(identifier)}</id>
|
<id>${urn(identifier)}</id>
|
||||||
<title>${name}</title>
|
<title>${name}</title>
|
||||||
<subtitle>Kill the Newsletter! Inbox: ${feedEmail(
|
<subtitle
|
||||||
identifier
|
>Kill the Newsletter! Inbox: ${feedEmail(identifier)} →
|
||||||
)} → ${feedURL(identifier)}</subtitle>
|
${feedURL(identifier)}</subtitle
|
||||||
|
>
|
||||||
<updated>${now()}</updated>
|
<updated>${now()}</updated>
|
||||||
<author><name>Kill the Newsletter!</name></author>
|
<author><name>Kill the Newsletter!</name></author>
|
||||||
</feed>
|
</feed>
|
||||||
`;
|
`.trim();
|
||||||
}
|
}
|
||||||
|
|
||||||
function entry(
|
function entry(
|
||||||
|
@ -199,15 +246,17 @@ function entry(
|
||||||
author: string,
|
author: string,
|
||||||
content: string
|
content: string
|
||||||
): string {
|
): string {
|
||||||
return `
|
return html`
|
||||||
<entry>
|
<entry>
|
||||||
<id>${urn(identifier)}</id>
|
<id>${urn(identifier)}</id>
|
||||||
<title>${title}</title>
|
<title>${title}</title>
|
||||||
<author><name>${author}</name></author>
|
<author><name>${author}</name></author>
|
||||||
<updated>${now()}</updated>
|
<updated>${now()}</updated>
|
||||||
<link rel="alternate" type="text/html" href="${alternateURL(
|
<link
|
||||||
identifier
|
rel="alternate"
|
||||||
)}"/>
|
type="text/html"
|
||||||
|
href="${alternateURL(identifier)}"
|
||||||
|
/>
|
||||||
<content type="html">${content}</content>
|
<content type="html">${content}</content>
|
||||||
</entry>
|
</entry>
|
||||||
`.trim();
|
`.trim();
|
||||||
|
|
|
@ -7744,6 +7744,11 @@
|
||||||
"integrity": "sha512-gtqfvz5jUIMqWn0kkdkV4G8uiLmJckQ+z6aKy1uyE0OPU/6tStubahtZDiF0ajSRVJht+Vd4pX5DDwQLhAapww==",
|
"integrity": "sha512-gtqfvz5jUIMqWn0kkdkV4G8uiLmJckQ+z6aKy1uyE0OPU/6tStubahtZDiF0ajSRVJht+Vd4pX5DDwQLhAapww==",
|
||||||
"optional": true
|
"optional": true
|
||||||
},
|
},
|
||||||
|
"tagged-template-noop": {
|
||||||
|
"version": "2.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/tagged-template-noop/-/tagged-template-noop-2.1.1.tgz",
|
||||||
|
"integrity": "sha512-diZ004cBHKVueqSr5p+/EPZhofCBRW7w7zZL71FcK8x+209BbMw77ICrP9AWXpVjPyyyIqRYYFAM4Wjk2HNWQg=="
|
||||||
|
},
|
||||||
"tar": {
|
"tar": {
|
||||||
"version": "2.2.2",
|
"version": "2.2.2",
|
||||||
"resolved": "https://registry.npmjs.org/tar/-/tar-2.2.2.tgz",
|
"resolved": "https://registry.npmjs.org/tar/-/tar-2.2.2.tgz",
|
||||||
|
|
|
@ -23,6 +23,7 @@
|
||||||
"pm2": "^4.2.3",
|
"pm2": "^4.2.3",
|
||||||
"sanitize-xml-string": "^1.1.0",
|
"sanitize-xml-string": "^1.1.0",
|
||||||
"smtp-server": "^3.6.0",
|
"smtp-server": "^3.6.0",
|
||||||
|
"tagged-template-noop": "^2.1.1",
|
||||||
"ts-node": "^8.10.1",
|
"ts-node": "^8.10.1",
|
||||||
"typescript": "^3.8.3",
|
"typescript": "^3.8.3",
|
||||||
"write-file-atomic": "^3.0.3"
|
"write-file-atomic": "^3.0.3"
|
||||||
|
|
Loading…
Reference in New Issue