commit cfb3379ef05cfa8ad595d350210beef6ed54acce Author: haetae Date: Sun Jan 19 23:21:07 2025 -0500 fix git diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..016b59e --- /dev/null +++ b/.gitignore @@ -0,0 +1,24 @@ +# build output +dist/ + +# generated types +.astro/ + +# dependencies +node_modules/ + +# logs +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* + +# environment variables +.env +.env.production + +# macOS-specific files +.DS_Store + +# jetbrains setting folder +.idea/ diff --git a/.vscode/extensions.json b/.vscode/extensions.json new file mode 100644 index 0000000..22a1505 --- /dev/null +++ b/.vscode/extensions.json @@ -0,0 +1,4 @@ +{ + "recommendations": ["astro-build.astro-vscode"], + "unwantedRecommendations": [] +} diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 0000000..d642209 --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,11 @@ +{ + "version": "0.2.0", + "configurations": [ + { + "command": "./node_modules/.bin/astro dev", + "name": "Development server", + "request": "launch", + "type": "node-terminal" + } + ] +} diff --git a/README.md b/README.md new file mode 100644 index 0000000..ff19a3e --- /dev/null +++ b/README.md @@ -0,0 +1,48 @@ +# Astro Starter Kit: Basics + +```sh +npm create astro@latest -- --template basics +``` + +[![Open in StackBlitz](https://developer.stackblitz.com/img/open_in_stackblitz.svg)](https://stackblitz.com/github/withastro/astro/tree/latest/examples/basics) +[![Open with CodeSandbox](https://assets.codesandbox.io/github/button-edit-lime.svg)](https://codesandbox.io/p/sandbox/github/withastro/astro/tree/latest/examples/basics) +[![Open in GitHub Codespaces](https://github.com/codespaces/badge.svg)](https://codespaces.new/withastro/astro?devcontainer_path=.devcontainer/basics/devcontainer.json) + +> πŸ§‘β€πŸš€ **Seasoned astronaut?** Delete this file. Have fun! + +![just-the-basics](https://github.com/withastro/astro/assets/2244813/a0a5533c-a856-4198-8470-2d67b1d7c554) + +## πŸš€ Project Structure + +Inside of your Astro project, you'll see the following folders and files: + +```text +/ +β”œβ”€β”€ public/ +β”‚ └── favicon.svg +β”œβ”€β”€ src/ +β”‚ β”œβ”€β”€ layouts/ +β”‚ β”‚ └── Layout.astro +β”‚ └── pages/ +β”‚ └── index.astro +└── package.json +``` + +To learn more about the folder structure of an Astro project, refer to [our guide on project structure](https://docs.astro.build/en/basics/project-structure/). + +## 🧞 Commands + +All commands are run from the root of the project, from a terminal: + +| Command | Action | +| :------------------------ | :----------------------------------------------- | +| `npm install` | Installs dependencies | +| `npm run dev` | Starts local dev server at `localhost:4321` | +| `npm run build` | Build your production site to `./dist/` | +| `npm run preview` | Preview your build locally, before deploying | +| `npm run astro ...` | Run CLI commands like `astro add`, `astro check` | +| `npm run astro -- --help` | Get help using the Astro CLI | + +## πŸ‘€ Want to learn more? + +Feel free to check [our documentation](https://docs.astro.build) or jump into our [Discord server](https://astro.build/chat). diff --git a/astro.config.mjs b/astro.config.mjs new file mode 100644 index 0000000..9a971f3 --- /dev/null +++ b/astro.config.mjs @@ -0,0 +1,13 @@ +// @ts-check +import { defineConfig } from 'astro/config'; +import db from '@astrojs/db'; +import node from '@astrojs/node'; + +// https://astro.build/config +export default defineConfig({ + site: "https://haetae.gay", + integrations: [db()], + adapter: node({ + mode: 'standalone' + }) +}); \ No newline at end of file diff --git a/bun.lockb b/bun.lockb new file mode 100755 index 0000000..8d642d3 Binary files /dev/null and b/bun.lockb differ diff --git a/db/config.ts b/db/config.ts new file mode 100644 index 0000000..9b6c945 --- /dev/null +++ b/db/config.ts @@ -0,0 +1,14 @@ +import { column, defineDb, defineTable, NOW } from 'astro:db'; + +const Guestbook = defineTable({ + columns: { + username: column.text(), + website: column.text({ optional: true }), + body: column.text(), + date: column.date({ default: NOW }), + }, +}); + +export default defineDb({ + tables: { Guestbook }, +}); diff --git a/db/seed.ts b/db/seed.ts new file mode 100644 index 0000000..ac6fe65 --- /dev/null +++ b/db/seed.ts @@ -0,0 +1,9 @@ +import { db, Guestbook } from 'astro:db'; + +// https://astro.build/db/seed +export default async function seed() { + await db.insert(Guestbook).values([ + { username: "tester", website: "", body: "hey there!" }, + { username: "ayo", website: "https://google.com", body: "this is googlebot" }, + ]); +} diff --git a/package.json b/package.json new file mode 100644 index 0000000..5a77c2a --- /dev/null +++ b/package.json @@ -0,0 +1,25 @@ +{ + "name": "astro", + "type": "module", + "version": "0.0.1", + "scripts": { + "dev": "astro dev", + "build": "astro build", + "preview": "astro preview", + "astro": "astro" + }, + "dependencies": { + "@astrojs/db": "^0.14.5", + "@astrojs/node": "^9.0.1", + "@astrojs/rss": "^4.0.11", + "astro": "^5.1.7", + "astro-breadcrumbs": "^3.3.1", + "markdown-it": "^14.1.0", + "sanitize-html": "^2.14.0" + }, + "devDependencies": { + "@types/markdown-it": "^14.1.2", + "@types/node": "^22.10.7", + "@types/sanitize-html": "^2.13.0" + } +} \ No newline at end of file diff --git a/public/favicon.svg b/public/favicon.svg new file mode 100644 index 0000000..f157bd1 --- /dev/null +++ b/public/favicon.svg @@ -0,0 +1,9 @@ + + + + diff --git a/public/fonts/DepartureMono-Regular.woff2 b/public/fonts/DepartureMono-Regular.woff2 new file mode 100644 index 0000000..20353c7 Binary files /dev/null and b/public/fonts/DepartureMono-Regular.woff2 differ diff --git a/public/fonts/KiwiSoda.woff2 b/public/fonts/KiwiSoda.woff2 new file mode 100644 index 0000000..21ccc2f Binary files /dev/null and b/public/fonts/KiwiSoda.woff2 differ diff --git a/public/fonts/Redaction_35-Bold.woff2 b/public/fonts/Redaction_35-Bold.woff2 new file mode 100644 index 0000000..737e8be Binary files /dev/null and b/public/fonts/Redaction_35-Bold.woff2 differ diff --git a/public/fonts/Redaction_35-Italic.woff2 b/public/fonts/Redaction_35-Italic.woff2 new file mode 100644 index 0000000..18e54ff Binary files /dev/null and b/public/fonts/Redaction_35-Italic.woff2 differ diff --git a/public/fonts/Redaction_35-Regular.woff2 b/public/fonts/Redaction_35-Regular.woff2 new file mode 100644 index 0000000..52a9ff6 Binary files /dev/null and b/public/fonts/Redaction_35-Regular.woff2 differ diff --git a/public/fonts/wondermail.woff2 b/public/fonts/wondermail.woff2 new file mode 100644 index 0000000..e390cdf Binary files /dev/null and b/public/fonts/wondermail.woff2 differ diff --git a/public/pretty-feed-v3.xsl b/public/pretty-feed-v3.xsl new file mode 100644 index 0000000..b8f0063 --- /dev/null +++ b/public/pretty-feed-v3.xsl @@ -0,0 +1,82 @@ + + + + + + + + <xsl:value-of select="/rss/channel/title"/> Web Feed + + + + + + +
+
+

+ + + + + + + + + + + + + + + + + + + Web Feed Preview +

+

+

+ + + + + Visit Website → + +
+

Recent Items

+ +
+

+ + + + + + +

+ + Published: + +
+
+
+ + +
+
diff --git a/src/actions/index.ts b/src/actions/index.ts new file mode 100644 index 0000000..d0f7f66 --- /dev/null +++ b/src/actions/index.ts @@ -0,0 +1,52 @@ +import { defineAction, ActionError } from "astro:actions"; +import { db, Guestbook } from "astro:db"; +import { z } from "astro:schema"; +import { checkProfanity } from "./utils"; + +export const server = { + guestbook: defineAction({ + accept: "form", + input: z.object({ + username: z.string(), + website: z.string().url().optional(), + body: z.string(), + honeypot: z.string().max(0).nullish(), + }), + handler: async (input) => { + if (input.username === "") { + throw new ActionError({ + code: "BAD_REQUEST", + message: "You should put in a name for yourself!" + }); + } + + if (input.body === "") { + throw new ActionError({ + code: "BAD_REQUEST", + message: "There should be a message here." + }); + } + + if (input.honeypot !== undefined) { + throw new ActionError({ + code: "UNPROCESSABLE_CONTENT", + message: "Oh dear, something went wrong!", + }); + } + + const filter = await checkProfanity(input.body); + if (filter) { + return await db.insert(Guestbook).values({ + username: input.username, + website: input.website, + body: input.body, + }).returning(); + } else { + throw new ActionError({ + code: "BAD_REQUEST", + message: "You can't curse!", + }); + } + }, + }), +} \ No newline at end of file diff --git a/src/actions/utils.ts b/src/actions/utils.ts new file mode 100644 index 0000000..320bdd1 --- /dev/null +++ b/src/actions/utils.ts @@ -0,0 +1,29 @@ +export async function checkProfanity(message: string) { + try { + const response = await fetch("https://vector.profanity.dev", { + method: "POST", + headers: { "Content-Type": "application/json" }, + body: JSON.stringify({ message }), + }); + + if (!response.ok) { + throw new Error(`There was an error checking your message: ${response.status}`); + } + + const json = await response.json(); + + if (json.isProfanity) { + throw new Error("Please don't cuss!"); + } + + return true; + } catch (e) { + console.error(e); + return false; + } +} + +async function checkSpam(form: FormData) { + const token = form.append("procaptcha-response", import.meta.env.SPAM_SITE_KEY); + +} \ No newline at end of file diff --git a/src/assets/astro.svg b/src/assets/astro.svg new file mode 100644 index 0000000..8cf8fb0 --- /dev/null +++ b/src/assets/astro.svg @@ -0,0 +1 @@ + diff --git a/src/assets/background.svg b/src/assets/background.svg new file mode 100644 index 0000000..4b2be0a --- /dev/null +++ b/src/assets/background.svg @@ -0,0 +1 @@ + diff --git a/src/assets/frame.png b/src/assets/frame.png new file mode 100644 index 0000000..4b00911 Binary files /dev/null and b/src/assets/frame.png differ diff --git a/src/assets/styles/base.css b/src/assets/styles/base.css new file mode 100644 index 0000000..453e6b9 --- /dev/null +++ b/src/assets/styles/base.css @@ -0,0 +1,40 @@ +@import url("./reset.css"); +@import url("./fonts.css"); + +:root { + --body-font: "Wonder Mail", system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif; + --title-font: "Kiwi Soda", Impact, Haettenschweiler, 'Arial Narrow Bold', sans-serif; + --mono-font: "Departure Mono", ui-monospace, 'Cascadia Code', 'Source Code Pro', Menlo, Consolas, 'DejaVu Sans Mono', monospace; + --serif-font: "Redaction 35", 'Iowan Old Style', 'Palatino Linotype', 'URW Palladio L', P052, serif; +} + +body { + font-family: var(--body-font); + font-size: 2rem; +} + +h1, h2, h3, h4, h5, h6 { + font-family: var(--title-font); + font-weight: normal; + line-height: 1; +} + +h1 { font-size: 4rem; } +h2 { font-size: 3rem; } +h3 { font-size: 2rem; } +h4, h5, h6 { font-size: 1rem; } + +@media screen and (max-width: 48em) { + h1, h2, h3 { + font-size: 3rem; + } +} + +input, button, textarea, select { + font-family: var(--mono-font); + font-size: 1.375rem; + + /* @media screen and (max-width: 48em) { + font-size: 11px; + } */ +} \ No newline at end of file diff --git a/src/assets/styles/fonts.css b/src/assets/styles/fonts.css new file mode 100644 index 0000000..a7493e5 --- /dev/null +++ b/src/assets/styles/fonts.css @@ -0,0 +1,38 @@ +@font-face { + font-family: "Departure Mono"; + src: url("/fonts/DepartureMono-Regular.woff2") format("woff2"); + font-weight: normal; +} + +@font-face { + font-family: "Kiwi Soda"; + src: url("/fonts/KiwiSoda.woff2") format("woff2"); + font-weight: normal; +} + +@font-face { + font-family: "Redaction 35"; + src: url("/fonts/Redaction_35-Regular.woff2") format("woff2"); + font-weight: normal; + font-style: normal; +} + +@font-face { + font-family: "Redaction 35"; + src: url("/fonts/Redaction_35-Italic.woff2") format("woff2"); + font-weight: normal; + font-style: italic; +} + +@font-face { + font-family: "Redaction 35"; + src: url("/fonts/Redaction_35-Bold.woff2") format("woff2"); + font-weight: bold; + font-style: normal; +} + +@font-face { + font-family: "Wonder Mail"; + src: url("/fonts/wondermail.woff2") format("woff2"); + font-weight: normal; +} \ No newline at end of file diff --git a/src/assets/styles/reset.css b/src/assets/styles/reset.css new file mode 100644 index 0000000..97c2e3e --- /dev/null +++ b/src/assets/styles/reset.css @@ -0,0 +1,37 @@ +*, *::before, *::after { + box-sizing: border-box; +} + +* { + margin: 0; +} + +html, body { + height: 100vh; + width: 100vw; +} + +body { + line-height: calc(1em + 0.5rem); +} + +img, picture, video, canvas, svg { + display: block; + max-width: 100%; +} + +input, button, textarea, select { + font: inherit; +} + +p, h1, h2, h3, h4, h5, h6 { + overflow-wrap: break-word; +} + +p { + text-wrap: pretty; +} + +h1, h2, h3, h4, h5, h6 { + text-wrap: balance; +} \ No newline at end of file diff --git a/src/components/Figure.astro b/src/components/Figure.astro new file mode 100644 index 0000000..ca5cba1 --- /dev/null +++ b/src/components/Figure.astro @@ -0,0 +1,17 @@ +--- +import { Image } from 'astro:assets'; + +interface Props { + imagePath: string; + alt: string; + caption?: string; +} + +const { imagePath, alt, caption }: Props = Astro.props; +const images = import.meta.glob<{ default: ImageMetadata }>("/src/assets/**/*.{jpeg,jpg,png,webp,gif}"); +if (!images[imagePath]) throw new Error(`"${imagePath}" does not exist in glob: "src/assets/**/*.{jpeg,jpg,png,webp,gif}"`); +--- +
+ +
{caption ?? alt}
+
\ No newline at end of file diff --git a/src/components/Navbar.astro b/src/components/Navbar.astro new file mode 100644 index 0000000..efc242a --- /dev/null +++ b/src/components/Navbar.astro @@ -0,0 +1,32 @@ +--- +const links = [ + "about", + "blog", + "fics", + "gallery", + "guestbook", +]; +--- + + + \ No newline at end of file diff --git a/src/components/Top.astro b/src/components/Top.astro new file mode 100644 index 0000000..0d924da --- /dev/null +++ b/src/components/Top.astro @@ -0,0 +1,12 @@ + + back to top + + + + \ No newline at end of file diff --git a/src/content/blog/hello-world.md b/src/content/blog/hello-world.md new file mode 100644 index 0000000..9e2c722 --- /dev/null +++ b/src/content/blog/hello-world.md @@ -0,0 +1,14 @@ +--- +title: hey girl hey +pubDate: 2024-02-03 +--- + +Lorem ipsum dolor sit amet, consectetur adipiscing elit. Proin pretium augue elit, eget interdum massa lobortis ut. Praesent facilisis ornare aliquam. Donec sit amet volutpat ipsum, id ultricies urna. Donec vestibulum sagittis felis, tempor fermentum urna posuere at. Vestibulum cursus mauris eget bibendum blandit. Aenean at augue porttitor, bibendum massa ut, laoreet lacus. Phasellus fermentum tincidunt lectus vel volutpat. Proin sagittis vel sem sit amet consequat. Vestibulum ac laoreet quam. Mauris eu purus sit amet odio maximus dictum. Mauris quam tellus, tempus eu faucibus in, mollis quis velit. Phasellus nisl mauris, congue vel magna a, rutrum aliquet ante. Proin in ante pharetra, vestibulum nisi vel, fringilla tortor. Etiam mattis, mauris et mattis sagittis, orci eros ornare risus, vitae consequat ligula nulla eget quam. + +Fusce malesuada sed risus eget elementum. Quisque porttitor finibus libero, et semper magna pretium ac. Donec gravida erat iaculis ante cursus, in laoreet ligula dapibus. Vestibulum gravida lorem eleifend mollis hendrerit. Nulla et velit dapibus, aliquet lectus at, mattis nulla. Pellentesque lacus eros, sagittis quis dignissim a, malesuada ut eros. Aliquam fringilla a leo sed commodo. Sed eu ligula malesuada, ultrices orci eget, suscipit ipsum. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Cras interdum libero sed leo eleifend tempor. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. + +Vivamus scelerisque ac quam sed interdum. Mauris pulvinar aliquet est in luctus. Donec convallis dui aliquam urna pellentesque, eget maximus tellus scelerisque. Integer posuere commodo justo in finibus. Vivamus at molestie nisl, sit amet ultrices ex. Ut elementum dignissim dui a lacinia. Etiam nec purus ac felis congue tristique ut eget leo. Aenean id augue molestie, auctor quam ac, aliquam magna. Maecenas condimentum sem mauris, in sodales nunc suscipit non. Sed iaculis ut magna vel sollicitudin. Etiam commodo lacinia lorem, quis tincidunt sem laoreet et. Sed interdum elit ac erat blandit cursus. Pellentesque imperdiet placerat lacus id sagittis. In vitae efficitur ante, sit amet feugiat nunc. Praesent erat mi, hendrerit molestie maximus sed, tempus eu massa. + +Fusce convallis ultricies orci, vulputate laoreet magna. Proin in aliquet diam. Etiam placerat ante eget lacus ultrices fermentum. Phasellus interdum facilisis ex mattis blandit. Quisque vitae convallis velit. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla sodales tincidunt lorem. Ut bibendum posuere elementum. Phasellus arcu lacus, porta sit amet convallis a, finibus et nisi. Sed id justo dapibus, faucibus elit eu, tincidunt ante. + +Donec vehicula ultrices egestas. Maecenas non magna tortor. Curabitur metus sapien, ultricies porta urna vitae, pulvinar blandit tellus. In aliquet risus sed libero vulputate, in volutpat ligula malesuada. Phasellus viverra pretium turpis, quis congue dolor fringilla vitae. Morbi orci lacus, mollis non dolor nec, euismod aliquet risus. Ut massa nibh, maximus sit amet turpis et, dapibus ullamcorper turpis. Aenean ut tellus ac nisi mollis tempus. Duis at libero quis felis ornare viverra ac sit amet justo. Sed gravida magna ut nibh tincidunt, consectetur lobortis est consequat. Phasellus ex velit, tincidunt sit amet consectetur id, vulputate eget tellus. Donec ligula elit, vestibulum non tincidunt eu, ullamcorper eget massa. Nulla venenatis maximus metus, sed pulvinar dolor ullamcorper at. Vestibulum volutpat tortor ante, a ornare justo porttitor tempus. Aliquam sit amet sem porta, hendrerit dolor sed, tristique neque. \ No newline at end of file diff --git a/src/content/blog/hi-world.md b/src/content/blog/hi-world.md new file mode 100644 index 0000000..dbb700f --- /dev/null +++ b/src/content/blog/hi-world.md @@ -0,0 +1,6 @@ +--- +title: hmhmhm! +pubDate: 2024-02-04 +--- + +hey there this is a test \ No newline at end of file diff --git a/src/content/config.ts b/src/content/config.ts new file mode 100644 index 0000000..e0ceeab --- /dev/null +++ b/src/content/config.ts @@ -0,0 +1,39 @@ +import { defineCollection, z } from "astro:content"; +import { glob } from "astro/loaders"; +import { rssSchema } from "@astrojs/rss"; + +const blog = defineCollection({ + loader: glob({ pattern: "*.md", base: "./src/content/blog" }), + schema: rssSchema, +}); + +function generateFicSlug({ entry, data }: { entry: string, data: any }): string { + if (data.slug) { + return data.slug as string; + } + return entry.split("/")[0]; +} + +const source = "./src/content/fics"; +const chapters = defineCollection({ + loader: glob({ pattern: "**/*.{md,mdx,mdoc}", base: source }), + schema: z.object({ + title: z.string(), + publishedAt: z.coerce.date(), + notes: z.ostring(), + lastModified: z.coerce.date().optional(), + sortOrder: z.number(), + }), +}); + +const fics = defineCollection({ + loader: glob({ pattern: "**/*.{yml,yaml}", base: source, generateId: generateFicSlug }), + schema: z.object({ + title: z.string(), + series: z.array(z.string()), + publishedAt: z.coerce.date(), + summary: z.string(), + }), +}); + +export const collections = { blog, fics, chapters }; \ No newline at end of file diff --git a/src/content/fics/hello-world/_index.yaml b/src/content/fics/hello-world/_index.yaml new file mode 100644 index 0000000..8e1df28 --- /dev/null +++ b/src/content/fics/hello-world/_index.yaml @@ -0,0 +1,9 @@ +title: hello world +series: + - soccer + - some what +publishedAt: 2024-01-20 +summary: + sometime after the war, x finds love in the middle of a soccer field... + + what wil lyou do now diff --git a/src/content/fics/hello-world/chapter-1.md b/src/content/fics/hello-world/chapter-1.md new file mode 100644 index 0000000..4b7b6b0 --- /dev/null +++ b/src/content/fics/hello-world/chapter-1.md @@ -0,0 +1,12 @@ +--- +title: not a sin +publishedAt: 2024-02-01 +sortOrder: 1 +notes: + hello is this is a test, this is going to be a really long text! this is where all the author's notes will go. + + fhi +--- +Lorem ipsum dolor sit amet *consectetur* adipisicing elit. Reiciendis reprehenderit provident ullam sint explicabo quas esse velit, voluptatum eveniet, tempora illum expedita, eum voluptate! Odio excepturi similique ex quos **tenetur**. + +"here lies by her's" \ No newline at end of file diff --git a/src/content/fics/hello-world/chapter-2.md b/src/content/fics/hello-world/chapter-2.md new file mode 100644 index 0000000..f996ef6 --- /dev/null +++ b/src/content/fics/hello-world/chapter-2.md @@ -0,0 +1,13 @@ +--- +title: this IS a sin +publishedAt: 2024-03-02 +sortOrder: 2 +notes: +

hey there this is just a test

+

him!!! lol!!!

+--- +Lorem ipsum dolor sit amet consectetur adipisicing elit. Reiciendis **reprehenderit** provident ullam sint *explicabo* quas esse velit, voluptatum eveniet, tempora illum expedita, eum voluptate! Odio excepturi similique ex quos tenetur. + +"here lies by her's" + +hmmm there it is!! "hiii!!!" \ No newline at end of file diff --git a/src/content/fics/test-1/_index.yaml b/src/content/fics/test-1/_index.yaml new file mode 100644 index 0000000..6c4fe43 --- /dev/null +++ b/src/content/fics/test-1/_index.yaml @@ -0,0 +1,6 @@ +title: testing +series: + - another fandom +publishedAt: 2024-01-20 +summary: + in another planet, we all face the end of a world \ No newline at end of file diff --git a/src/content/fics/test-1/test.md b/src/content/fics/test-1/test.md new file mode 100644 index 0000000..a54f009 --- /dev/null +++ b/src/content/fics/test-1/test.md @@ -0,0 +1,7 @@ +--- +title: chapter 1 +publishedAt: 2024-02-01 +sortOrder: 1 +--- + +# this is another test!! \ No newline at end of file diff --git a/src/layouts/About.astro b/src/layouts/About.astro new file mode 100644 index 0000000..b20b5b2 --- /dev/null +++ b/src/layouts/About.astro @@ -0,0 +1,11 @@ +--- +import Navbar from "@/components/Navbar.astro"; +import Layout from "./Layout.astro"; +--- + + + +
+ +
+
\ No newline at end of file diff --git a/src/layouts/Blog.astro b/src/layouts/Blog.astro new file mode 100644 index 0000000..d594dfc --- /dev/null +++ b/src/layouts/Blog.astro @@ -0,0 +1,153 @@ +--- +import { getCollection } from "astro:content"; +import Layout from "./Layout.astro"; +import Navbar from "@/components/Navbar.astro"; + +interface Props { + title: string; + date: Date; +} + +const blog = await getCollection("blog"); +blog.length = Math.min(blog.length, 5); +blog.sort((a, b) => a.data.pubDate!.valueOf() - b.data.pubDate!.valueOf()); +const { title, date } = Astro.props; +--- + + + +
+ + +
+
+
+

{title}

+ +
+ +
+ +
+
+ + +
+
+
+ + \ No newline at end of file diff --git a/src/layouts/Chapter.astro b/src/layouts/Chapter.astro new file mode 100644 index 0000000..84f2a78 --- /dev/null +++ b/src/layouts/Chapter.astro @@ -0,0 +1,67 @@ +--- +import Layout from "./Layout.astro"; + +interface Props { + title: string; + date: Date; + notes?: string; + lastModified?: string; +} + +const { title, date, notes, lastModified }: Props = Astro.props; +--- + + + +
+
+

{title}

+ + {lastModified && ( + + )} + {notes && ( +
")} />
+ )} +
+ +
+ +
+ + +
+
+ + \ No newline at end of file diff --git a/src/layouts/Layout.astro b/src/layouts/Layout.astro new file mode 100644 index 0000000..b792275 --- /dev/null +++ b/src/layouts/Layout.astro @@ -0,0 +1,24 @@ +--- +import "@/assets/styles/base.css"; + +interface Props { + title?: string; +} + +const { title = "haetae" }: Props = Astro.props; +--- + + + + + + + + + + {title} + + + + + \ No newline at end of file diff --git a/src/pages/about.md b/src/pages/about.md new file mode 100644 index 0000000..042ff21 --- /dev/null +++ b/src/pages/about.md @@ -0,0 +1,10 @@ +--- +title: about me +layout: ../layouts/About.astro +--- +# hello! + +it's me, the weirdo. here's a bunch of my images: + +## badges... + diff --git a/src/pages/blog/[...id].astro b/src/pages/blog/[...id].astro new file mode 100644 index 0000000..ef727dd --- /dev/null +++ b/src/pages/blog/[...id].astro @@ -0,0 +1,54 @@ +--- +import Blog from '@/layouts/Blog.astro'; +import type { GetStaticPaths } from 'astro'; +import { getCollection, render } from 'astro:content'; + +export const getStaticPaths = (async () => { + const blog = await getCollection("blog"); + return blog.map(entry => ({ + params: { id: entry.id }, + props: { entry }, + })); +}) satisfies GetStaticPaths; + +const { entry } = Astro.props; +const { Content } = await render(entry); + +const blog = await getCollection("blog"); +blog.sort((a, b) => b.data.pubDate!.valueOf() - a.data.pubDate!.valueOf()); +const current = blog.findIndex(entry => entry.id === Astro.params.id); +const previous = current + 1 === blog.length ? undefined : blog[current + 1]; +const next = current === 0 ? undefined : blog[current - 1]; +--- + + + + {(previous || next) && ( +
+ {previous && ( + + )} + + {next && ( + + )} +
+ )} +
+ + \ No newline at end of file diff --git a/src/pages/blog/index.astro b/src/pages/blog/index.astro new file mode 100644 index 0000000..fb6e1d6 --- /dev/null +++ b/src/pages/blog/index.astro @@ -0,0 +1,34 @@ +--- +import Layout from "@/layouts/Layout.astro"; +import { getCollection } from "astro:content"; + +const blog = await getCollection("blog"); +const sorted = Object.groupBy(blog, ({ data }) => data.pubDate!.getMonth()); + +const getMonth = (id: number) => { + let date = new Date(); + date.setDate(1); + date.setMonth(id); + return date.toLocaleString(undefined, { month: "long" }); +} +--- + +

blog

+
    + {Object.entries(sorted).map(entry => ( +
  • +

    {getMonth(Number(entry[0]))}

    +
      + {entry[1]?.sort((a, b) => a.data.pubDate!.valueOf() - b.data.pubDate!.valueOf()).map(post => ( +
    • + + {post.data.title} +
    • + ))} +
    +
  • + ))} +
+
\ No newline at end of file diff --git a/src/pages/blog/rss.xml.ts b/src/pages/blog/rss.xml.ts new file mode 100644 index 0000000..d615448 --- /dev/null +++ b/src/pages/blog/rss.xml.ts @@ -0,0 +1,23 @@ +import type { APIRoute } from "astro"; +import { getCollection } from "astro:content"; +import rss from "@astrojs/rss"; +import MarkdownIt from "markdown-it"; +import sanitize from "sanitize-html"; +const parser = new MarkdownIt(); + +export const GET: APIRoute = async (context) => { + const blog = await getCollection("blog"); + return rss({ + title: "haetae's blog", + description: "a blog about a weirdo who likes coding", + site: context.site!, + items: blog.map(entry => ({ + link: `/blog/${entry.id}`, + content: sanitize(parser.render(entry.body!), { + allowedTags: sanitize.defaults.allowedTags.concat(["img"]), + }), + ...entry.data, + })), + stylesheet: "/pretty-feed-v3.xsl", + }); +} \ No newline at end of file diff --git a/src/pages/fics/[ficId]/[...chapterId].astro b/src/pages/fics/[ficId]/[...chapterId].astro new file mode 100644 index 0000000..16a3123 --- /dev/null +++ b/src/pages/fics/[ficId]/[...chapterId].astro @@ -0,0 +1,121 @@ +--- +import Chapter from "@/layouts/Chapter.astro"; +import type { GetStaticPaths } from "astro"; +import { getCollection, render } from "astro:content"; +import { Breadcrumbs } from "astro-breadcrumbs"; + +export const getStaticPaths = (async () => { + const chapters = await getCollection("chapters"); + return chapters.map(chapter => ({ + params: { + ficId: chapter.id.split("/")[0], + chapterId: chapter.id.split("/")[1], + }, + props: { chapter }, + })); +}) satisfies GetStaticPaths; + +const { ficId, chapterId } = Astro.params; +const { chapter } = Astro.props; +const { Content } = await render(chapter); + +const chapters = await getCollection("chapters", ({ id }) => { + return id.split("/")[0] === ficId; +}); +const fic = await getCollection("fics", ({ id }) => { + return id === ficId; +}); +chapters.sort((a, b) => a.data.sortOrder - b.data.sortOrder); +const current = chapters.findIndex(chapter => chapter.id === `${ficId}/${chapterId}`); +const next = current + 1 === chapters.length ? undefined : chapters[current + 1]; +const previous = current === 0 ? undefined : chapters[current - 1]; +// lastmodified + +const links = [ + { index: "last", text: chapter.data.title }, + { index: 2, text: fic[0].data.title }, +]; +--- + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/pages/fics/[ficId]/index.astro b/src/pages/fics/[ficId]/index.astro new file mode 100644 index 0000000..f3302e8 --- /dev/null +++ b/src/pages/fics/[ficId]/index.astro @@ -0,0 +1,42 @@ +--- +import type { GetStaticPaths } from "astro"; +import { getCollection } from "astro:content"; +import Layout from "@/layouts/Layout.astro"; + +export const getStaticPaths = (async () => { + const fics = await getCollection("fics"); + return fics.map(fic => ({ + params: { ficId: fic.id }, + props: { fic }, + })); +}) satisfies GetStaticPaths; + +const { fic } = Astro.props; +const chapters = await getCollection("chapters", ({ id }) => { + return id.startsWith(fic.id); +}); +chapters.length = Math.min(chapters.length, 5); +chapters.sort((a, b) => a.data.sortOrder - b.data.sortOrder); +--- + +
+

{fic.data.title}

+
+

fandom: {fic.data.series.join(", ")}

+ +
+ ")} /> +
+ start reading + rss feed +
+

chapters

+ +
+
\ No newline at end of file diff --git a/src/pages/fics/[ficId]/rss.xml.ts b/src/pages/fics/[ficId]/rss.xml.ts new file mode 100644 index 0000000..48cbaab --- /dev/null +++ b/src/pages/fics/[ficId]/rss.xml.ts @@ -0,0 +1,36 @@ +import type { APIRoute } from "astro"; +import { getCollection } from "astro:content"; +import rss from "@astrojs/rss"; +import MarkdownIt from "markdown-it"; +import sanitize from "sanitize-html"; +const parser = new MarkdownIt(); + +const fics = await getCollection("fics"); + +export const GET: APIRoute = async (context) => { + const chapters = await getCollection("chapters", ({ id }) => { + return id.split("/")[0] === context.params.ficId; + }); + const fic = fics.find(({ id }) => id === context.params.ficId); + return rss({ + title: `${fic?.data.title}`, + description: `${fic?.data.summary}`, + site: context.site!, + items: chapters.map(chapter => ({ + link: `/fics/${chapter.id}`, + title: chapter.data.title, + pubDate: chapter.data.publishedAt, + content: sanitize(parser.render(chapter.body!), { + allowedTags: sanitize.defaults.allowedTags.concat(["img"]), + }), + categories: fic?.data.series, + })), + stylesheet: "/pretty-feed-v3.xsl", + }); +}; + +export function getStaticPaths() { + return fics.map(fic => ({ + params: { ficId: fic.id }, + })); +} \ No newline at end of file diff --git a/src/pages/fics/index.astro b/src/pages/fics/index.astro new file mode 100644 index 0000000..ccc76f2 --- /dev/null +++ b/src/pages/fics/index.astro @@ -0,0 +1,32 @@ +--- +import Layout from "@/layouts/Layout.astro"; +import { getCollection } from "astro:content"; + +const fics = await getCollection("fics"); +const chapters = await getCollection("chapters"); +chapters.length = Math.min(chapters.length, 5); +chapters.sort((a, b) => a.data.publishedAt.valueOf() - b.data.publishedAt.valueOf()); +--- + +

fanfics

+ +

recent updates

+ + +

works

+ +
\ No newline at end of file diff --git a/src/pages/gallery.astro b/src/pages/gallery.astro new file mode 100644 index 0000000..15976ae --- /dev/null +++ b/src/pages/gallery.astro @@ -0,0 +1,9 @@ +--- +import Layout from "@/layouts/Layout.astro"; +--- + +
+

gallery

+ import images here +
+
\ No newline at end of file diff --git a/src/pages/guestbook.astro b/src/pages/guestbook.astro new file mode 100644 index 0000000..9808884 --- /dev/null +++ b/src/pages/guestbook.astro @@ -0,0 +1,59 @@ +--- +import { actions, isInputError } from "astro:actions"; +import { db, Guestbook as table } from "astro:db"; +import Layout from "@/layouts/Layout.astro"; + +export const prerender = false; + +const result = Astro.getActionResult(actions.guestbook); +const errors = isInputError(result?.error) ? result.error.fields : {}; +const entries = await db.select().from(table); +entries.sort((a, b) => b.date.valueOf() - a.date.valueOf()); +--- + + +
+

Guestbook

+ +
+ + + {errors.username &&

{errors.username.join(",")}

} + + + + {errors.website &&

{errors.website.join(",")}

} + + + + {errors.body &&

{errors.body.join(",")}

} + + + + + {errors.honeypot &&

{errors.honeypot.join(",")}

} +
+ + {entries.map(({ username, website, body, date }) => ( +
+

{username}

+ {website &&

website

} + +
+ {body} +
+
+ ))} +
+
+ + \ No newline at end of file diff --git a/src/pages/index.astro b/src/pages/index.astro new file mode 100644 index 0000000..85a355d --- /dev/null +++ b/src/pages/index.astro @@ -0,0 +1,19 @@ +--- +import Navbar from '~/Navbar.astro'; +import Layout from '@/layouts/Layout.astro'; +--- + + + +
+

hi

+

this is a test chummy but cool <===

+
+
+ + \ No newline at end of file diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..3146848 --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,12 @@ +{ + "extends": "astro/tsconfigs/strict", + "include": [".astro/types.d.ts", "**/*"], + "exclude": ["dist"], + "compilerOptions": { + "baseUrl": ".", + "paths": { + "@/*": ["src/*"], + "~/*": ["src/components/*"], + } + } +}