diff --git a/src/components.tsx b/src/components.tsx deleted file mode 100644 index 514186f..0000000 --- a/src/components.tsx +++ /dev/null @@ -1,209 +0,0 @@ -import React from "react"; -import ReactDOMServer from "react-dom/server"; -import { Builder } from "xml2js"; -import cryptoRandomString from "crypto-random-string"; - -export type Inbox = { - name: string; - token: string; -}; - -export function Layout({ children }: { children: React.ReactNode }) { - return ( - - - - - - - - - - - Kill the Newsletter! - - -
-

- Kill the Newsletter! -

-

Convert email newsletters into Atom feeds

-

- Convert email newsletters into Atom feeds -

-
-
{children}
- - - - ); -} - -export function Form() { - return ( -
-

- - -

-
- ); -} - -export function Created({ inbox: { name, token } }: { inbox: Inbox }) { - return ( - <> -

“{name}” Inbox Created

-

- Sign up for the newsletter with -
- {feedEmail(token)} -

-

- Subscribe to the Atom feed at -
- {feedUrl(token)} -

-

- Don’t share these addresses. -
- They contain a security token that other people could use -
- to send you spam and to control your newsletter subscriptions. -

-

Enjoy your readings!

-

- - Create Another Inbox - -

- - ); -} - -// https://validator.w3.org/feed/docs/atom.html -// https://validator.w3.org/feed/#validate_by_input - -export function Feed(inbox: Inbox) { - const { name, token } = inbox; - return { - feed: { - $: { xmlns: "http://www.w3.org/2005/Atom" }, - link: [ - { - $: { - rel: "self", - type: "application/atom+xml", - href: feedUrl(token) - } - }, - { - $: { - rel: "alternate", - type: "text/html", - href: "https://www.kill-the-newsletter.com/" - } - } - ], - id: id(token), - title: name, - subtitle: `Kill the Newsletter! Inbox “${feedEmail(token)}”`, - updated: now(), - ...Entry({ - title: `“${name}” Inbox Created`, - author: "Kill the Newsletter!", - content: ReactDOMServer.renderToStaticMarkup( - - ) - }) - } - }; -} - -export function Entry({ - title, - author, - content -}: { - title: string; - author: string; - content: string; -}) { - return { - entry: { - id: id(newToken()), - title, - author: { name: author }, - updated: now(), - content: { $: { type: "html" }, _: content } - } - }; -} - -export function newToken() { - return cryptoRandomString({ - length: 20, - characters: "1234567890qwertyuiopasdfghjklzxcvbnm" - }); -} - -export function now() { - return new Date().toISOString(); -} - -export function feedPath(token: string) { - return `static/feeds/${token}.xml`; -} - -export function feedUrl(token: string) { - return `https://www.kill-the-newsletter.com/feeds/${token}.xml`; -} - -export function feedEmail(token: string) { - return `${token}@kill-the-newsletter.com`; -} - -export function id(token: string) { - return `urn:kill-the-newsletter:${token}`; -} - -export function renderHtml(component: React.ReactElement): string { - return `\n${ReactDOMServer.renderToStaticMarkup(component)}`; -} - -export function renderXml(xml: object): string { - return new Builder().buildObject(xml); -} diff --git a/src/server.tsx b/src/server.tsx index 4c514e6..4777ef9 100644 --- a/src/server.tsx +++ b/src/server.tsx @@ -1,17 +1,9 @@ import express from "express"; import React from "react"; -import { - Inbox, - Layout, - Form, - Created, - Feed, - newToken, - feedPath, - renderHtml, - renderXml -} from "./components"; import fs from "fs"; +import ReactDOMServer from "react-dom/server"; +import { Builder } from "xml2js"; +import cryptoRandomString from "crypto-random-string"; export const webServer = express() .use(express.static("static")) @@ -37,3 +29,208 @@ export const webServer = express() ); }) .listen(8443); + +type Inbox = { + name: string; + token: string; +}; + +function Layout({ children }: { children: React.ReactNode }) { + return ( + + + + + + + + + + + Kill the Newsletter! + + +
+

+ Kill the Newsletter! +

+

Convert email newsletters into Atom feeds

+

+ Convert email newsletters into Atom feeds +

+
+
{children}
+ + + + ); +} + +function Form() { + return ( +
+

+ + +

+
+ ); +} + +function Created({ inbox: { name, token } }: { inbox: Inbox }) { + return ( + <> +

“{name}” Inbox Created

+

+ Sign up for the newsletter with +
+ {feedEmail(token)} +

+

+ Subscribe to the Atom feed at +
+ {feedUrl(token)} +

+

+ Don’t share these addresses. +
+ They contain a security token that other people could use +
+ to send you spam and to control your newsletter subscriptions. +

+

Enjoy your readings!

+

+ + Create Another Inbox + +

+ + ); +} + +// https://validator.w3.org/feed/docs/atom.html +// https://validator.w3.org/feed/#validate_by_input + +function Feed(inbox: Inbox) { + const { name, token } = inbox; + return { + feed: { + $: { xmlns: "http://www.w3.org/2005/Atom" }, + link: [ + { + $: { + rel: "self", + type: "application/atom+xml", + href: feedUrl(token) + } + }, + { + $: { + rel: "alternate", + type: "text/html", + href: "https://www.kill-the-newsletter.com/" + } + } + ], + id: id(token), + title: name, + subtitle: `Kill the Newsletter! Inbox “${feedEmail(token)}”`, + updated: now(), + ...Entry({ + title: `“${name}” Inbox Created`, + author: "Kill the Newsletter!", + content: ReactDOMServer.renderToStaticMarkup( + + ) + }) + } + }; +} + +function Entry({ + title, + author, + content +}: { + title: string; + author: string; + content: string; +}) { + return { + entry: { + id: id(newToken()), + title, + author: { name: author }, + updated: now(), + content: { $: { type: "html" }, _: content } + } + }; +} + +function newToken() { + return cryptoRandomString({ + length: 20, + characters: "1234567890qwertyuiopasdfghjklzxcvbnm" + }); +} + +function now() { + return new Date().toISOString(); +} + +export function feedPath(token: string) { + return `static/feeds/${token}.xml`; +} + +function feedUrl(token: string) { + return `https://www.kill-the-newsletter.com/feeds/${token}.xml`; +} + +function feedEmail(token: string) { + return `${token}@kill-the-newsletter.com`; +} + +function id(token: string) { + return `urn:kill-the-newsletter:${token}`; +} + +function renderHtml(component: React.ReactElement): string { + return `\n${ReactDOMServer.renderToStaticMarkup(component)}`; +} + +function renderXml(xml: object): string { + return new Builder().buildObject(xml); +} diff --git a/src/test.ts b/src/test.ts index aa7c7ce..07557de 100644 --- a/src/test.ts +++ b/src/test.ts @@ -1,5 +1,4 @@ -import { webServer } from "./server"; -import { feedPath } from "./components"; +import { webServer, feedPath } from "./server"; import fetch from "node-fetch"; import fs from "fs";