my blog https://overreacted.io
at fix/a-socialfilesystem-typos 163 lines 4.8 kB view raw
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}