get poetry stuff workin

This commit is contained in:
Silas 2024-05-29 18:33:13 -04:00
parent 3d22344e7f
commit 251620863c
Failed to generate hash of commit
42 changed files with 632 additions and 299 deletions

7
.vscode/extensions.json vendored Normal file
View File

@ -0,0 +1,7 @@
{
"recommendations": [
"svelte.svelte-vscode",
"editorconfig.editorconfig",
"dbaeumer.vscode-eslint"
]
}

3
.vscode/settings.json vendored Normal file
View File

@ -0,0 +1,3 @@
{
"editor.formatOnSave": true
}

86
package-lock.json generated
View File

@ -20,6 +20,7 @@
"@sveltejs/adapter-auto": "^3.0.0", "@sveltejs/adapter-auto": "^3.0.0",
"@sveltejs/kit": "^2.0.0", "@sveltejs/kit": "^2.0.0",
"@sveltejs/vite-plugin-svelte": "^3.0.0", "@sveltejs/vite-plugin-svelte": "^3.0.0",
"@tailwindcss/typography": "^0.5.13",
"@theatre/core": "^0.7.1", "@theatre/core": "^0.7.1",
"@theatre/studio": "^0.7.1", "@theatre/studio": "^0.7.1",
"@threlte/theatre": "^2.1.7", "@threlte/theatre": "^2.1.7",
@ -28,6 +29,7 @@
"@typescript-eslint/eslint-plugin": "^7.0.0", "@typescript-eslint/eslint-plugin": "^7.0.0",
"@typescript-eslint/parser": "^7.0.0", "@typescript-eslint/parser": "^7.0.0",
"autoprefixer": "^10.4.19", "autoprefixer": "^10.4.19",
"daisyui": "^4.11.1",
"eslint": "^8.56.0", "eslint": "^8.56.0",
"eslint-config-prettier": "^9.1.0", "eslint-config-prettier": "^9.1.0",
"eslint-plugin-svelte": "^2.35.1", "eslint-plugin-svelte": "^2.35.1",
@ -1811,6 +1813,34 @@
"vite": "^5.0.0" "vite": "^5.0.0"
} }
}, },
"node_modules/@tailwindcss/typography": {
"version": "0.5.13",
"resolved": "https://registry.npmjs.org/@tailwindcss/typography/-/typography-0.5.13.tgz",
"integrity": "sha512-ADGcJ8dX21dVVHIwTRgzrcunY6YY9uSlAHHGVKvkA+vLc5qLwEszvKts40lx7z0qc4clpjclwLeK5rVCV2P/uw==",
"dev": true,
"dependencies": {
"lodash.castarray": "^4.4.0",
"lodash.isplainobject": "^4.0.6",
"lodash.merge": "^4.6.2",
"postcss-selector-parser": "6.0.10"
},
"peerDependencies": {
"tailwindcss": ">=3.0.0 || insiders"
}
},
"node_modules/@tailwindcss/typography/node_modules/postcss-selector-parser": {
"version": "6.0.10",
"resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.10.tgz",
"integrity": "sha512-IQ7TZdoaqbT+LCpShg46jnZVlhWD2w6iQYAcYXfHARZ7X1t/UGhhceQDs5X0cGqKvYlHNOuv7Oa1xmb0oQuA3w==",
"dev": true,
"dependencies": {
"cssesc": "^3.0.0",
"util-deprecate": "^1.0.2"
},
"engines": {
"node": ">=4"
}
},
"node_modules/@theatre/core": { "node_modules/@theatre/core": {
"version": "0.7.1", "version": "0.7.1",
"resolved": "https://registry.npmjs.org/@theatre/core/-/core-0.7.1.tgz", "resolved": "https://registry.npmjs.org/@theatre/core/-/core-0.7.1.tgz",
@ -2966,6 +2996,16 @@
"node": ">= 8" "node": ">= 8"
} }
}, },
"node_modules/css-selector-tokenizer": {
"version": "0.8.0",
"resolved": "https://registry.npmjs.org/css-selector-tokenizer/-/css-selector-tokenizer-0.8.0.tgz",
"integrity": "sha512-Jd6Ig3/pe62/qe5SBPTN8h8LeUg/pT4lLgtavPf7updwwHpvFzxvOQBHYj2LZDMjUnBzgvIUSjRcf6oT5HzHFg==",
"dev": true,
"dependencies": {
"cssesc": "^3.0.0",
"fastparse": "^1.1.2"
}
},
"node_modules/css-tree": { "node_modules/css-tree": {
"version": "2.3.1", "version": "2.3.1",
"resolved": "https://registry.npmjs.org/css-tree/-/css-tree-2.3.1.tgz", "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-2.3.1.tgz",
@ -3019,6 +3059,34 @@
"resolved": "https://registry.npmjs.org/csv-stringify/-/csv-stringify-5.6.5.tgz", "resolved": "https://registry.npmjs.org/csv-stringify/-/csv-stringify-5.6.5.tgz",
"integrity": "sha512-PjiQ659aQ+fUTQqSrd1XEDnOr52jh30RBurfzkscaE2tPaFsDH5wOAHJiw8XAHphRknCwMUE9KRayc4K/NbO8A==" "integrity": "sha512-PjiQ659aQ+fUTQqSrd1XEDnOr52jh30RBurfzkscaE2tPaFsDH5wOAHJiw8XAHphRknCwMUE9KRayc4K/NbO8A=="
}, },
"node_modules/culori": {
"version": "3.3.0",
"resolved": "https://registry.npmjs.org/culori/-/culori-3.3.0.tgz",
"integrity": "sha512-pHJg+jbuFsCjz9iclQBqyL3B2HLCBF71BwVNujUYEvCeQMvV97R59MNK3R2+jgJ3a1fcZgI9B3vYgz8lzr/BFQ==",
"dev": true,
"engines": {
"node": "^12.20.0 || ^14.13.1 || >=16.0.0"
}
},
"node_modules/daisyui": {
"version": "4.11.1",
"resolved": "https://registry.npmjs.org/daisyui/-/daisyui-4.11.1.tgz",
"integrity": "sha512-obT9CUbQdW6eoHwSeT5VwaRrWlwrM4OT5qlfdJ0oQlSIEYhwnEl2+L2fwu5PioLbitwuMdYC2X8I1cyy8Pf6LQ==",
"dev": true,
"dependencies": {
"css-selector-tokenizer": "^0.8",
"culori": "^3",
"picocolors": "^1",
"postcss-js": "^4"
},
"engines": {
"node": ">=16.9.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/daisyui"
}
},
"node_modules/data-view-buffer": { "node_modules/data-view-buffer": {
"version": "1.0.1", "version": "1.0.1",
"resolved": "https://registry.npmjs.org/data-view-buffer/-/data-view-buffer-1.0.1.tgz", "resolved": "https://registry.npmjs.org/data-view-buffer/-/data-view-buffer-1.0.1.tgz",
@ -3846,6 +3914,12 @@
"integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==",
"dev": true "dev": true
}, },
"node_modules/fastparse": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/fastparse/-/fastparse-1.1.2.tgz",
"integrity": "sha512-483XLLxTVIwWK3QTrMGRqUfUpoOs/0hbQrl2oz4J0pAcm3A3bu84wxTFqGqkJzewCLdME38xJLJAxBABfQT8sQ==",
"dev": true
},
"node_modules/fastq": { "node_modules/fastq": {
"version": "1.17.1", "version": "1.17.1",
"resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz", "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz",
@ -4970,6 +5044,18 @@
"integrity": "sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==", "integrity": "sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==",
"dev": true "dev": true
}, },
"node_modules/lodash.castarray": {
"version": "4.4.0",
"resolved": "https://registry.npmjs.org/lodash.castarray/-/lodash.castarray-4.4.0.tgz",
"integrity": "sha512-aVx8ztPv7/2ULbArGJ2Y42bG1mEQ5mGjpdvrbJcJFU3TbYybe+QlLS4pst9zV52ymy2in1KpFPiZnAOATxD4+Q==",
"dev": true
},
"node_modules/lodash.isplainobject": {
"version": "4.0.6",
"resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz",
"integrity": "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==",
"dev": true
},
"node_modules/lodash.merge": { "node_modules/lodash.merge": {
"version": "4.6.2", "version": "4.6.2",
"resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz",

View File

@ -17,6 +17,7 @@
"@sveltejs/adapter-auto": "^3.0.0", "@sveltejs/adapter-auto": "^3.0.0",
"@sveltejs/kit": "^2.0.0", "@sveltejs/kit": "^2.0.0",
"@sveltejs/vite-plugin-svelte": "^3.0.0", "@sveltejs/vite-plugin-svelte": "^3.0.0",
"@tailwindcss/typography": "^0.5.13",
"@theatre/core": "^0.7.1", "@theatre/core": "^0.7.1",
"@theatre/studio": "^0.7.1", "@theatre/studio": "^0.7.1",
"@threlte/theatre": "^2.1.7", "@threlte/theatre": "^2.1.7",
@ -25,6 +26,7 @@
"@typescript-eslint/eslint-plugin": "^7.0.0", "@typescript-eslint/eslint-plugin": "^7.0.0",
"@typescript-eslint/parser": "^7.0.0", "@typescript-eslint/parser": "^7.0.0",
"autoprefixer": "^10.4.19", "autoprefixer": "^10.4.19",
"daisyui": "^4.11.1",
"eslint": "^8.56.0", "eslint": "^8.56.0",
"eslint-config-prettier": "^9.1.0", "eslint-config-prettier": "^9.1.0",
"eslint-plugin-svelte": "^2.35.1", "eslint-plugin-svelte": "^2.35.1",

View File

@ -6,7 +6,7 @@
<meta name="viewport" content="width=device-width, initial-scale=1" /> <meta name="viewport" content="width=device-width, initial-scale=1" />
%sveltekit.head% %sveltekit.head%
</head> </head>
<body data-sveltekit-preload-data="hover"> <body data-sveltekit-preload-data="hover" data-theme="forest">
<div style="display: contents">%sveltekit.body%</div> <div style="display: contents">%sveltekit.body%</div>
</body> </body>
</html> </html>

View File

@ -0,0 +1,19 @@
<script context="module">
import { onMount } from 'svelte';
import Headline from './poetry/h1.svelte';
import p from './poetry/p.svelte';
export { Headline as h1, p };
</script>
<script lang="ts">
export let title;
export let date;
export let categories;
export let tags;
export let year;
export let layout;
</script>
<main>
<slot />
</main>

View File

@ -41,7 +41,7 @@ export const fetchMarkdownPosts = async (
section: SectionKey, section: SectionKey,
limit: number, limit: number,
offset: number offset: number
): Promise<Post[]> => { ): Promise<{posts: Post[], total: number}> => {
let posts: Record<string, () => Promise<unknown>>; let posts: Record<string, () => Promise<unknown>>;
switch (section) { switch (section) {
case 'poetry': case 'poetry':
@ -74,7 +74,9 @@ export const fetchMarkdownPosts = async (
}) })
); );
const paginatedPosts = allPosts.slice(offset, offset + limit); const sortedPosts = allPosts.sort((a, b) => new Date(a.meta.date).getTime() - new Date(b.meta.date).getTime() );
return paginatedPosts; const paginatedPosts = sortedPosts.slice(offset, offset + limit);
return {posts: paginatedPosts, total: allPosts.length};
}; };

View File

@ -0,0 +1,3 @@
<h1 class="poetry-headline">
<slot></slot>
</h1>

View File

@ -0,0 +1,3 @@
<p class="whitespace-pre">
<slot></slot>
</p>

View File

@ -1,13 +1,13 @@
--- ---
categories: categories:
- Poetry - Poetry
date: 2013-01-10 00:00:00 +0000 date: 2013-01-10 00:00:00 +0000
tags: tags:
- Humor - Humor
- Muffins - Muffins
title: Breakfast Blues title: Breakfast Blues
--- ---
Lost my reason to wake in the morning Lost my reason to wake in the morning
Ever since you left me without warning. Ever since you left me without warning.
We've always seemed to have gotten along We've always seemed to have gotten along

View File

@ -6,6 +6,7 @@ tags:
- Christian - Christian
title: Djinn title: Djinn
year: 2019 year: 2019
layout: poetry
--- ---
"Jesus dropped by." "Jesus dropped by."

View File

@ -1,14 +1,14 @@
--- ---
categories: categories:
- Poetry - Poetry
date: 2018-04-28 12:00:00 +0000 date: 2018-04-28 12:00:00 +0000
tags: tags:
- Wisdom - Wisdom
- Lessons - Lessons
title: I've Seen title: I've Seen
year: 2018 year: 2018
--- ---
I've seen tears fall I've seen tears fall
From the face of a giant, From the face of a giant,
A hint of desperation A hint of desperation

View File

@ -1,12 +1,12 @@
--- ---
categories: categories:
- Poetry - Poetry
date: 2019-02-02 12:00:00 +0000 date: 2019-02-02 12:00:00 +0000
tags: tags:
- Love - Love
- Lovers - Lovers
- Relationships - Relationships
- Introspective - Introspective
title: Infrared Homing title: Infrared Homing
--- ---
@ -40,4 +40,3 @@ A candle
Can't replace it, Can't replace it,
But any fire But any fire
Is better than none. Is better than none.

View File

@ -1,12 +1,11 @@
--- ---
categories: categories:
- Poetry - Poetry
date: 2020-10-01 20:00:00 +0000 date: 2020-10-01 20:00:00 +0000
tags: tags:
- Neuroscience - Neuroscience
- Wisdom - Wisdom
title: Judge Judy title: Judge Judy
--- ---
With each passing moment, With each passing moment,
@ -28,4 +27,3 @@ The neurons are dismissed
Then return to jury duty Then return to jury duty
For another microcosm case For another microcosm case
In their show of Judge Judy. In their show of Judge Judy.

View File

@ -1,10 +1,10 @@
--- ---
categories: categories:
- Poetry - Poetry
date: 2018-06-25 20:00:00 +0000 date: 2018-06-25 20:00:00 +0000
tags: tags:
- Chess - Chess
- Lessons - Lessons
title: King's Pin title: King's Pin
year: 2018 year: 2018
--- ---
@ -24,4 +24,3 @@ Synonymous to beginner.
A satisfying poach A satisfying poach
Awarded to the winner. Awarded to the winner.

View File

@ -1,12 +1,12 @@
--- ---
categories: categories:
- Poetry - Poetry
date: 2014-10-27 00:00:00 +0000 date: 2014-10-27 00:00:00 +0000
tags: tags:
- Humor - Humor
title: Klepto Couches title: Klepto Couches
--- ---
My home houses countless couches. My home houses countless couches.
Klepto-couches with pickpocket pouches Klepto-couches with pickpocket pouches
That swiftly swipe your cellular phone That swiftly swipe your cellular phone

View File

@ -1,13 +1,13 @@
--- ---
categories: categories:
- Poetry - Poetry
date: 2012-02-25 00:00:00 +0000 date: 2012-02-25 00:00:00 +0000
tags: tags:
- Grounds - Grounds
- Covenant - Covenant
title: Leafblower title: Leafblower
--- ---
You're the girl sitting on the park bench. You're the girl sitting on the park bench.
I'm the guy with a leaf blower. I'm the guy with a leaf blower.
I've gotta do my job, I've gotta do my job,

View File

@ -1,9 +1,9 @@
--- ---
categories: categories:
- Poetry - Poetry
date: 2019-10-26 12:00:00 +0000 date: 2019-10-26 12:00:00 +0000
tags: tags:
- Wisdom - Wisdom
title: Of Molecules And Men title: Of Molecules And Men
--- ---
@ -49,4 +49,3 @@ To cease to be
Is to become Is to become
Every friend Every friend
And alleged foe. And alleged foe.

View File

@ -1,13 +1,13 @@
--- ---
categories: categories:
- Poetry - Poetry
date: 2012-03-01 00:00:00 +0000 date: 2012-03-01 00:00:00 +0000
tags: tags:
- Grounds - Grounds
- Covenant - Covenant
title: Monday Morning Shift title: Monday Morning Shift
--- ---
These plants look beautiful, but not at this location. These plants look beautiful, but not at this location.
They must be eradicated according to administration. They must be eradicated according to administration.
I brought out my tools; Some gloves and a spade, I brought out my tools; Some gloves and a spade,

View File

@ -1,13 +1,12 @@
--- ---
categories: categories:
- Poetry - Poetry
date: 2016-05-10 00:00:00 +0000 date: 2016-05-10 00:00:00 +0000
tags: tags:
- Work - Work
- Worry - Worry
- Self-conscious - Self-conscious
title: Morning Commute title: Morning Commute
--- ---
A few minutes into my morning commute A few minutes into my morning commute
@ -24,4 +23,3 @@ So I ditched the car and snuck into work,
Though I knew my hopes and dreams would be seen Though I knew my hopes and dreams would be seen
Swirled amidst my self-doubt and worries Swirled amidst my self-doubt and worries
Like creamer mixed in bitter cups of caffeine. Like creamer mixed in bitter cups of caffeine.

View File

@ -1,14 +1,13 @@
--- ---
categories: categories:
- Poetry - Poetry
date: 2015-07-15 00:00:00 +0000 date: 2015-07-15 00:00:00 +0000
tags: tags:
- Relationships - Relationships
- Love - Love
- Drinking - Drinking
- Humor - Humor
title: Perfect Situation title: Perfect Situation
--- ---
When I'm hammered, When I'm hammered,
@ -32,5 +31,3 @@ And I speculate the odds
Given a perfect situation Given a perfect situation
In a parallel universe In a parallel universe
If I'd rise to the occasion. If I'd rise to the occasion.

View File

@ -1,12 +1,11 @@
--- ---
categories: categories:
- Poetry - Poetry
date: 2016-12-20 00:00:00 +0000 date: 2016-12-20 00:00:00 +0000
tags: tags:
- Introspective - Introspective
- Silence - Silence
title: Silent Silas title: Silent Silas
--- ---
The windows to my soul The windows to my soul
@ -24,4 +23,3 @@ But if it's any consolation,
I am striving to get better I am striving to get better
At voicing my own thoughts At voicing my own thoughts
Without resorting to writing letters. Without resorting to writing letters.

View File

@ -1,18 +1,15 @@
--- ---
categories: categories:
- Poetry - Poetry
date: 2014-07-20 00:00:00 +0000 date: 2014-07-20 00:00:00 +0000
tags: tags:
- Love - Love
- Relationships - Relationships
- Realtalk - Realtalk
title: Thought Experiment title: Thought Experiment
--- ---
Love is a free fall Love is a free fall
And I'm afraid of the ground. And I'm afraid of the ground.
If I jump and no one's there, If I jump and no one's there,
Will my body make a sound? Will my body make a sound?

View File

@ -1,13 +1,12 @@
--- ---
categories: categories:
- Poetry - Poetry
date: 2017-10-10 00:00:00 +0000 date: 2017-10-10 00:00:00 +0000
tags: tags:
- Wisdom - Wisdom
- Speech - Speech
- Verbal Abuse - Verbal Abuse
title: Unintentional Internalization title: Unintentional Internalization
--- ---
Our skin's as thick Our skin's as thick
@ -29,4 +28,3 @@ For each one we've endured,
We've dealt so many more We've dealt so many more
For the most innocuous remark For the most innocuous remark
Still can pierce like a sword. Still can pierce like a sword.

View File

@ -1,12 +1,12 @@
--- ---
categories: categories:
- Poetry - Poetry
date: 2013-05-10 00:00:00 +0000 date: 2013-05-10 00:00:00 +0000
tags: tags:
- Realtalk - Realtalk
title: Who Am I? title: Who Am I?
--- ---
Am I the clothes on my back Am I the clothes on my back
And the hair on my head? And the hair on my head?
Am I the people I'm with Am I the people I'm with

View File

@ -1,7 +1,52 @@
<script lang="ts"> <script>
import App from '$lib/components/scenes/app/App.svelte'; import '../../app.css';
</script> </script>
<App> <div class="flex flex-col h-screen">
<slot /> <div class="navbar bg-base-300 sticky top-0 z-50">
</App> <div class="navbar-start">
<div class="dropdown">
<div tabindex="-1" class="btn btn-ghost lg:hidden">
<svg
xmlns="http://www.w3.org/2000/svg"
class="h-5 w-5"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M4 6h16M4 12h8m-8 6h16"
/>
</svg>
</div>
<ul
tabindex="-1"
class="menu menu-sm dropdown-content mt-3 z-10 p-2 shadow bg-base-300 rounded-box w-52"
>
<li><a href="/thoughts">Thoughts</a></li>
<li><a href="/poetry">Poetry</a></li>
<li><a href="/projects">Projects</a></li>
<li><a href="/experiments">Experiments</a></li>
<li><a href="/services">Services</a></li>
</ul>
</div>
<a class="btn btn-outline btn-primary text-xl" href="/">silentsilas</a>
</div>
<div class="navbar-end hidden lg:flex">
<ul class="menu menu-horizontal px-1">
<li><a href="/thoughts">Thoughts</a></li>
<li><a href="/poetry">Poetry</a></li>
<li><a href="/projects">Projects</a></li>
<li><a href="/experiments">Experiments</a></li>
<li><a href="/services">Services</a></li>
</ul>
</div>
</div>
<div class="flex flex-col items-center flex-1 overflow-auto">
<slot />
</div>
</div>

View File

@ -1,23 +1,106 @@
<script lang="ts"> <script lang="ts">
import MenuItem from '$lib/components/scenes/app/MenuItem.svelte'; import { onMount } from 'svelte';
import { fade } from 'svelte/transition';
type Greeting = {
greeting: string;
language: string;
romanisation?: string;
};
const GREETINGS: Greeting[] = [
{ greeting: '你好', language: 'Mandarin', romanisation: 'Nǐ hǎo' },
{ greeting: 'नमस्ते', language: 'Hindi', romanisation: 'Namaste' },
{ greeting: 'Hola', language: 'Spanish' },
{ greeting: 'হ্যালো', language: 'Bengali', romanisation: 'Hyālō' },
{ greeting: 'ہیلو', language: 'Urdu', romanisation: 'Hello' },
{ greeting: 'Oi', language: 'Portuguese' },
{ greeting: 'Здравствуйте', language: 'Russian', romanisation: 'Zdravstvuyte' },
{ greeting: 'こんにちは', language: 'Japanese', romanisation: "Kon'nichiwa" },
{ greeting: 'Merhaba', language: 'Turkish' },
{ greeting: '안녕하세요', language: 'Korean', romanisation: 'Annyeonghaseyo' },
{ greeting: 'Hallo', language: 'German' },
{ greeting: 'สวัสดี', language: 'Thai', romanisation: 'S̄wạs̄dī' },
{ greeting: 'مرحبا', language: 'Arabic', romanisation: 'Marhaba' },
{ greeting: 'היי', language: 'Hebrew', romanisation: 'Hi' },
{ greeting: 'Helo', language: 'Welsh' },
{ greeting: 'Pozdrav', language: 'Croatian' },
{ greeting: 'Hej', language: 'Swedish' },
{ greeting: 'Hyālō', language: 'Bengali' },
{ greeting: 'Salut', language: 'French' },
{ greeting: 'Ciao', language: 'Italian' }
];
let greetings = [...GREETINGS];
let currentGreeting: Greeting = { greeting: 'Hello', language: 'English' };
let visible = false;
onMount(() => {
visible = true;
const interval = setInterval(getRandomGreeting, 3000);
return () => clearInterval(interval);
});
async function getRandomGreeting() {
visible = false;
await new Promise((r) => setTimeout(r, 1000));
if (greetings.length === 0) {
greetings = [...GREETINGS];
}
const greetingIndex = Math.floor(Math.random() * greetings.length);
const greeting = greetings[greetingIndex];
greetings = greetings.filter((_, index) => index !== greetingIndex);
currentGreeting = greeting;
visible = true;
return greeting;
}
</script> </script>
<MenuItem position={[-2.5, 7.5, 0]} htmlContent="Poetry" href="/poetry" /> <div class="container mx-auto flex flex-col justify-center items-center flex-1">
<div class="justify-center items-center text-center m-10">
<MenuItem {#if visible && currentGreeting}
position={[2.5, 2.5, -2.5]} <div
htmlContent="Projects" transition:fade={{ duration: 1200 }}
clickHandler={() => console.log('clicked!')} >
/> <span class="font-bold">{currentGreeting.greeting}</span>
{#if currentGreeting.romanisation}
<MenuItem <span class="text-gray-500">( {currentGreeting.romanisation} )</span>
position={[-2.5, -2.5, -2.5]} {/if}
htmlContent="Thoughts" </div>
clickHandler={() => console.log('clicked!')} <p class="mt-2 text-gray-700" transition:fade={{ delay: 400, duration: 400 }}>
/> That's {currentGreeting.language} for hello!
</p>
<MenuItem {/if}
position={[2.5, -7.5, 2.5]} </div>
htmlContent="About" <div class="text-center prose px-4">
clickHandler={() => console.log('clicked!')} <p>
/> The name's Silas. I write code for a living, and sometimes for fun. I use <a
href="https://elixir-lang.org/"
target="_blank">Elixir</a
>
at my day job, and recently have been messing around with
<a href="https://elixir-lang.org/" target="_blank">Rust</a>,
<a href="https://kit.svelte.dev/" target="_blank">Svelte</a>, and
<a href="https://threejs.org/" target="_blank">three.js</a>
</p>
<p>
Here you can browse my shower <a href="/thoughts" class="link">thoughts</a> and bad
<a href="/poetry" class="link">poetry</a>. Opinions are personally mine and not endorsed by my
employer.
</p>
<p>
I tend to start a lot of <a href="/projects" class="link">projects</a>, but I'm trying to
finish more. I also like to toy with weird web technologies and will host the
<a href="/experiments" class="link">experiments</a> here.
</p>
<p>
I self-host a lot of <a href="/services" class="link">services</a> I find useful. None of them
run any analytics or log your activity, but the software/servers may be outdated, so use at your
own risk.
</p>
<p>Shalom.</p>
</div>
</div>

View File

@ -0,0 +1,15 @@
export const load = async ({ fetch, url }) => {
const limit = 8;
const page = Number(url.searchParams.get('page')) || 1;
const response = await fetch(`/api/poetry?limit=${limit}&page=${page}`);
const { posts, total } = await response.json();
return {
posts,
total,
page,
limit
};
};

View File

@ -1,39 +1,70 @@
<script lang="ts"> <script lang="ts">
import MenuItem from '$lib/components/scenes/app/MenuItem.svelte'; import { goto } from '$app/navigation';
import type { PageData } from './$types'; import { page } from '$app/stores';
import type { PageData } from '../poetry/$types';
export let data: PageData; export let data: PageData;
const xMin = -2.5, const formatDate = (date: string) => {
xMax = 2.5; return new Date(date).toLocaleDateString(undefined, {
const yMin = -7.5, year: 'numeric',
yMax = 7.5; month: 'long',
const zMin = -2.5, day: 'numeric'
zMax = 2.5; });
// Calculate positions
const calculatePositions = (numPosts: number): Array<[number, number, number]> => {
const positions: Array<[number, number, number]> = [];
const numRows = Math.ceil(Math.sqrt(numPosts));
const numCols = Math.ceil(numPosts / numRows);
for (let i = 0; i < numPosts; i++) {
const row = Math.floor(i / numCols);
const col = i % numCols;
const x = xMin + (xMax - xMin) * (col / (numCols - 1));
const y = yMin + (yMax - yMin) * (row / (numRows - 1));
const z = zMin;
positions.push([x, y, z]);
}
return positions;
}; };
// Generate positions based on the number of posts let { posts, total } = data;
const positions = calculatePositions(data.posts.length); const limit = 8;
let currentPage = Number($page.url.searchParams.get('page')) || 1;
let totalPages = Math.ceil(total / limit);
$: $page.url.searchParams.get('page'),
(currentPage = Number($page.url.searchParams.get('page')) || 1);
async function fetchData(page: number) {
const response = await fetch(`/api/poetry?limit=${limit}&page=${page}`);
const newData = await response.json();
currentPage = page;
posts = newData.posts;
total = newData.total;
totalPages = Math.ceil(total / limit);
}
function navigate(page: number) {
fetchData(page);
goto(`/poetry/?page=${page}`, { replaceState: true });
}
</script> </script>
{#each data.posts as post, i} <div class="container mx-auto flex flex-col items-center py-10">
<MenuItem position={positions[i]} htmlContent={post.meta.title} href={post.path} /> <div class="prose">
{/each} <h1 class="py-6">Poetry</h1>
</div>
<ul>
{#each posts as post}
<li class="py-4">
<h3 class="pb-1">
<a class="link" href={post.path}>
{post.meta.title}
</a>
</h3>
<p class="text-sm">{formatDate(post.meta.date)}</p>
</li>
{/each}
</ul>
</div>
{#if total > 1}
<nav class="join justify-end">
<button
class="join-item btn-primary btn btn-outline"
on:click={() => navigate(currentPage - 1)}
disabled={currentPage === 1}>Prev</button
>
<button class="join-item btn btn-outline">{currentPage} of {totalPages}</button>
<button
class="join-item btn btn-primary btn-outline"
on:click={() => navigate(currentPage + 1)}
disabled={currentPage === totalPages}>Next</button
>
</nav>
{/if}

View File

@ -1,19 +1,16 @@
<script lang="ts"> <script lang="ts">
import MenuItem from '$lib/components/scenes/app/MenuItem.svelte';
import type { PageData } from './$types'; import type { PageData } from './$types';
import DomPortal from '$lib/utils/DomPortal.svelte';
export let data: PageData; export let data: PageData;
const { title, date: _date, Content, categories: _ } = data; const { title, date: _date, Content, categories: _ } = data;
</script> </script>
<MenuItem position={[-2.5, 10, 0]} htmlContent="Back" href="/poetry" /> <div class="container mx-auto flex flex-col items-center py-10">
<div class="prose">
<DomPortal target="#overlay"> <h1 class="py-6">{title}</h1>
<div class="py-4">
<h1 class="text-xl font-medium text-black pb-2">{title}</h1>
<div>
<Content />
</div>
</div> </div>
</DomPortal> <div class="prose">
<Content />
</div>
<a href="/poetry" class="link mt-10">Back to Poetry</a>
</div>

View File

@ -13,6 +13,7 @@ export async function load({ params }) {
Content, Content,
title, title,
date: validDate, date: validDate,
categories categories,
post
}; };
} }

View File

@ -1,38 +1 @@
<script lang="ts"> <slot />
import CanvasContainer from '$lib/components/scenes/app/CanvasContainer.svelte';
import '../app.css';
</script>
<CanvasContainer>
<slot />
</CanvasContainer>
<div class="overlay container" id="overlay"></div>
<style>
:global(body) {
margin: 0;
}
.canvas {
width: 100%;
height: 100%;
background: rgb(0, 36, 6);
background: linear-gradient(180deg, rgba(0, 36, 6, 1) 0%, rgba(0, 0, 0, 1) 100%);
position: absolute;
justify-content: center;
align-items: center;
}
.overlay {
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
background: rgba(16, 56, 30, 0.9);
}
</style>

View File

@ -1,2 +1,2 @@
export const prerender = true export const prerender = true
export const ssr = false export const ssr = true

View File

@ -2,13 +2,14 @@ import { fetchMarkdownPosts } from '$lib/utils';
import { json } from '@sveltejs/kit'; import { json } from '@sveltejs/kit';
export const GET = async ({ url }) => { export const GET = async ({ url }) => {
const limit = Number(url.searchParams.get('limit')) || 6; const page = Number(url.searchParams.get('page')) || 1;
const offset = Number(url.searchParams.get('offset')) || 0; const limit = Number(url.searchParams.get('limit')) || 8;
const allPosts = await fetchMarkdownPosts('poetry', limit, offset); const offset = (page - 1) * limit;
const {posts: allPosts, total: total} = await fetchMarkdownPosts('poetry', limit, offset);
const sortedPosts = allPosts.sort((a, b) => { const sortedPosts = allPosts.sort((a, b) => {
return new Date(b.meta.date).getTime() - new Date(a.meta.date).getTime(); return new Date(b.meta.date).getTime() - new Date(a.meta.date).getTime();
}); });
return json(sortedPosts); return json({posts: sortedPosts, total: total, page: page});
}; };

View File

@ -0,0 +1,42 @@
<script lang="ts">
import App from '$lib/components/scenes/app/App.svelte';
import CanvasContainer from '$lib/components/scenes/app/CanvasContainer.svelte';
import '../../app.css'
</script>
<CanvasContainer>
<App>
<slot />
</App>
</CanvasContainer>
<div class="overlay container" id="overlay"></div>
<style>
:global(body) {
margin: 0;
}
.canvas {
width: 100%;
height: 100%;
background: rgb(0, 36, 6);
background: linear-gradient(180deg, rgba(0, 36, 6, 1) 0%, rgba(0, 0, 0, 1) 100%);
position: absolute;
justify-content: center;
align-items: center;
}
.overlay {
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
background: rgba(16, 56, 30, 0.9);
}
</style>

View File

@ -0,0 +1,2 @@
export const prerender = true
export const ssr = false

View File

@ -0,0 +1,37 @@
<script lang="ts">
import MenuItem from '$lib/components/scenes/app/MenuItem.svelte';
import type { PageData } from './$types';
export let data: PageData;
const xMin = -2.5,
xMax = 2.5;
const yMin = -7.5,
yMax = 7.5;
const zMin = -2.5,
zMax = 2.5;
const calculatePositions = (numPosts: number): Array<[number, number, number]> => {
const positions: Array<[number, number, number]> = [];
const numRows = Math.ceil(Math.sqrt(numPosts));
const numCols = Math.ceil(numPosts / numRows);
for (let i = 0; i < numPosts; i++) {
const row = Math.floor(i / numCols);
const col = i % numCols;
const x = xMin + (xMax - xMin) * (col / (numCols - 1));
const y = yMin + (yMax - yMin) * (row / (numRows - 1));
const z = zMin;
positions.push([x, y, z]);
}
return positions;
};
const positions = calculatePositions(data.posts.length);
</script>
{#each data.posts as post, i}
<MenuItem position={positions[i]} htmlContent={post.meta.title} href={post.path} />
{/each}

View File

@ -6,7 +6,10 @@ import { mdsvex } from 'mdsvex';
const config = { const config = {
// Consult https://kit.svelte.dev/docs/integrations#preprocessors // Consult https://kit.svelte.dev/docs/integrations#preprocessors
// for more information about preprocessors // for more information about preprocessors
preprocess: [vitePreprocess(), mdsvex({ extensions: ['.md'] })], preprocess: [vitePreprocess(), mdsvex({ extensions: ['.md'], layout: {
poetry: './src/lib/utils/PoetryLayout.svelte'
}})],
kit: { kit: {
// adapter-auto only supports some environments, see https://kit.svelte.dev/docs/adapter-auto for a list. // adapter-auto only supports some environments, see https://kit.svelte.dev/docs/adapter-auto for a list.

View File

@ -4,6 +4,10 @@ export default {
theme: { theme: {
extend: {}, extend: {},
}, },
plugins: [], plugins: [require("@tailwindcss/typography"), require('daisyui')],
daisyui: {
themes: ["light", "forest"],
darkMode: "forest"
},
} }