forked from
danabra.mov/overreacted
my blog https://overreacted.io
1import { readFile, readdir } from "fs/promises";
2import matter from "gray-matter";
3import {
4 GreetingFrontend,
5 GreetingFrontend_2,
6 SortableList,
7 SortableList_2,
8 SortableList_3,
9 SortableList_4,
10 ExpandingSection_2,
11} from "./client";
12
13export async function GreetingBackend({
14 colorFile = "./public/impossible-components/color.txt",
15}) {
16 const myColor = await readFile(colorFile, "utf8");
17 return <GreetingFrontend color={myColor} />;
18}
19
20export function Welcome() {
21 return (
22 <>
23 <GreetingBackend colorFile="./public/impossible-components/color1.txt" />
24 <GreetingBackend colorFile="./public/impossible-components/color2.txt" />
25 <GreetingBackend colorFile="./public/impossible-components/color3.txt" />
26 </>
27 );
28}
29
30export async function GreetingBackend_2({
31 colorFile = "./public/impossible-components/color.txt",
32}) {
33 const myColor = await readFile(colorFile, "utf8");
34 return <GreetingFrontend_2 color={myColor} />;
35}
36
37export function Welcome_2() {
38 return (
39 <>
40 <GreetingBackend_2 colorFile="./public/impossible-components/color1.txt" />
41 <GreetingBackend_2 colorFile="./public/impossible-components/color2.txt" />
42 <GreetingBackend_2 colorFile="./public/impossible-components/color3.txt" />
43 </>
44 );
45}
46
47export async function SortableFileList({ directory }) {
48 const files = await readdir(directory);
49 return <SortableList items={files} />;
50}
51
52export async function SortableFileList_2({ directory }) {
53 const files = await readdir(directory);
54 return <SortableList_2 items={files} />;
55}
56
57export async function PostPreview({ slug }) {
58 const fileContent = await readFile("./public/" + slug + "/index.md", "utf8");
59 const { data, content } = matter(fileContent);
60 const wordCount = content.split(" ").filter(Boolean).length;
61
62 return (
63 <section className="rounded-md bg-black/5 p-2">
64 <h5 className="font-bold">
65 <a
66 href={"/" + slug}
67 target="_blank"
68 className="underline decoration-[--link] decoration-1 underline-offset-4 text-[--link]"
69 >
70 {data.title}
71 </a>
72 </h5>
73 <i>{wordCount.toLocaleString()} words</i>
74 </section>
75 );
76}
77
78export async function PostPreview_2({ slug }) {
79 const fileContent = await readFile("./public/" + slug + "/index.md", "utf8");
80 const { data, content } = matter(fileContent);
81 const wordCount = content.split(" ").filter(Boolean).length;
82 const firstSentence = content.split(/\.|\n\n/)[0];
83
84 return (
85 <section className="rounded-md bg-black/5 p-2">
86 <h5 className="font-bold">
87 <a
88 href={"/" + slug}
89 target="_blank"
90 className="underline decoration-[--link] decoration-1 underline-offset-4 text-[--link]"
91 >
92 {data.title}
93 </a>
94 </h5>
95 <i>{wordCount.toLocaleString()} words</i>
96 <p style={{ marginTop: 20, padding: 0 }}>{firstSentence} [...]</p>
97 </section>
98 );
99}
100
101export async function PostPreview_3({ slug }) {
102 const fileContent = await readFile("./public/" + slug + "/index.md", "utf8");
103 const { data, content } = matter(fileContent);
104 const wordCount = content.split(" ").filter(Boolean).length;
105 const firstSentence = content.split(/\.\s|\n\n/)[0];
106
107 return (
108 <ExpandingSection_2
109 extraContent={
110 <p style={{ marginTop: 20, padding: 0 }}>{firstSentence} [...]</p>
111 }
112 >
113 <h5 className="font-bold">
114 <a
115 href={"/" + slug}
116 target="_blank"
117 className="underline decoration-[--link] decoration-1 underline-offset-4 text-[--link]"
118 >
119 {data.title}
120 </a>
121 </h5>
122 <i>{wordCount.toLocaleString()} words</i>
123 </ExpandingSection_2>
124 );
125}
126
127export async function PostList() {
128 const entries = await readdir("./public/", { withFileTypes: true });
129 const dirs = entries.filter((entry) => entry.isDirectory());
130 return (
131 <div className="mb-8 flex h-72 flex-col gap-2 overflow-scroll font-sans">
132 {dirs.map((dir) => (
133 <PostPreview_3 key={dir.name} slug={dir.name} />
134 ))}
135 </div>
136 );
137}
138
139export async function SortableFileList_3({ directory }) {
140 const files = await readdir(directory);
141 const items = files.map((file) => ({
142 id: file,
143 content: file,
144 searchText: file,
145 }));
146 return <SortableList_3 items={items} />;
147}
148
149export async function SortablePostList() {
150 const entries = await readdir("./public/", { withFileTypes: true });
151 const dirs = entries.filter((entry) => entry.isDirectory());
152 return (
153 <div className="mb-8 flex h-72 flex-col gap-2 overflow-scroll font-sans">
154 <SortableList_4
155 items={dirs.map((dir) => ({
156 id: dir.name,
157 searchText: dir.name.replaceAll("-", " "),
158 content: <PostPreview_3 slug={dir.name} />,
159 }))}
160 />
161 </div>
162 );
163}