Compare commits
43 Commits
post/heade
...
main
Author | SHA1 | Date |
---|---|---|
|
cc44b37a35 | |
|
1a3b0a2e05 | |
|
795e10938e | |
|
50555eb10c | |
|
ed2f417999 | |
|
afc3e2d2fb | |
|
24c7b137df | |
|
f014ebd1cd | |
|
6024a151b2 | |
|
3f71107a0a | |
|
f5843184d5 | |
|
2d1e5d20fb | |
|
8d0fb521d4 | |
|
33ebd62026 | |
|
23f715e6ac | |
|
83666fc504 | |
|
045311168d | |
|
2b11a969fc | |
|
4b9a131d35 | |
|
c04e04667c | |
|
7cf3e31b22 | |
|
c2362e26ef | |
|
442e589874 | |
|
f8bdcb811a | |
|
1d7be8373f | |
|
7daa6eb70d | |
|
662a298b28 | |
|
e7984f9c33 | |
|
7d9fe36140 | |
|
56e6efc795 | |
|
6f5933d902 | |
|
46ca660a13 | |
|
5dbb8e7a8c | |
|
7b900c2993 | |
|
0d87cea96f | |
|
d18c3f62c7 | |
|
e8e52588e4 | |
|
482f7e59a7 | |
|
78a414c747 | |
|
0cea3461dc | |
|
60fc46af4a | |
|
d756598342 | |
|
6e7ccd73fc |
|
@ -11,7 +11,7 @@ repos:
|
||||||
hooks:
|
hooks:
|
||||||
- id: conventional-pre-commit
|
- id: conventional-pre-commit
|
||||||
stages: [commit-msg]
|
stages: [commit-msg]
|
||||||
args: [feat, fix, chore, test, build, merge, refactor]
|
args: [feat, fix, chore, test, build, merge, refactor, doc]
|
||||||
- repo: local
|
- repo: local
|
||||||
hooks:
|
hooks:
|
||||||
- id: eslint
|
- id: eslint
|
||||||
|
|
25
README.md
25
README.md
|
@ -7,10 +7,10 @@ A blog framework
|
||||||
To create the production version,
|
To create the production version,
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
npm run build
|
pnpm run build
|
||||||
```
|
```
|
||||||
|
|
||||||
You can preview the production build with `npm run preview`.
|
You can preview the production build with `pnpm run dev --open`.
|
||||||
|
|
||||||
### Content
|
### Content
|
||||||
|
|
||||||
|
@ -19,28 +19,39 @@ To insert custom content, create a directory with a similar structure to
|
||||||
directory. The website will be built statically in `build/`. Note that changing
|
directory. The website will be built statically in `build/`. Note that changing
|
||||||
`favicon.svg` will require modifying the `static/` folder.
|
`favicon.svg` will require modifying the `static/` folder.
|
||||||
|
|
||||||
|
Set `metadata.json` based on the example to have a custom avatar and background
|
||||||
|
image.
|
||||||
|
- `name`: Displayed name on the home page
|
||||||
|
- `blogName`: Displayed name of the blog
|
||||||
|
- `url`: The site url
|
||||||
|
- `frontDescription`: The text above the main navbar
|
||||||
|
- `frontCover`: Path to the cover image
|
||||||
|
- `picture`: Avatar
|
||||||
|
- `links`: A map of brands to links
|
||||||
|
- `extra`: Extra pages showing on the navbar
|
||||||
|
- `markdown`: `{ "highlighterLangs": [ ... ], "katex": [ ... ] }`
|
||||||
|
|
||||||
## Developing
|
## Developing
|
||||||
|
|
||||||
Install [pre-commit](https://pre-commit.com/).
|
Install [pre-commit](https://pre-commit.com/).
|
||||||
|
|
||||||
Install dependencies with `npm install` (or `pnpm install` or `yarn`). Then
|
Install dependencies with `pnpm install`. Then start the dev server with
|
||||||
start the dev server with
|
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
npm run dev [-- --open]
|
pnpm run dev [-- --open]
|
||||||
```
|
```
|
||||||
|
|
||||||
### Formatting
|
### Formatting
|
||||||
|
|
||||||
``` bash
|
``` bash
|
||||||
npx eslint
|
pnpx eslint
|
||||||
```
|
```
|
||||||
|
|
||||||
### Testing
|
### Testing
|
||||||
|
|
||||||
To run tests
|
To run tests
|
||||||
``` bash
|
``` bash
|
||||||
npx playwright test
|
pnpx playwright test
|
||||||
```
|
```
|
||||||
|
|
||||||
All tests must have the suffix `.spec.[jt]s`. Be cautious while updating
|
All tests must have the suffix `.spec.[jt]s`. Be cautious while updating
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
58
package.json
58
package.json
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "chrysoblog",
|
"name": "chrysoblog",
|
||||||
"version": "0.0.2",
|
"version": "0.0.4",
|
||||||
"private": true,
|
"private": true,
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "vite dev",
|
"dev": "vite dev",
|
||||||
|
@ -16,47 +16,47 @@
|
||||||
"prepare": "svelte-kit sync"
|
"prepare": "svelte-kit sync"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@eslint/js": "^9.11.1",
|
"@eslint/js": "^9.29.0",
|
||||||
"@playwright/test": "^1.40.0",
|
"@playwright/test": "^1.53.1",
|
||||||
"@sveltejs/adapter-auto": "^3.0.0",
|
"@sveltejs/adapter-auto": "^3.3.1",
|
||||||
"@sveltejs/adapter-static": "^3.0.5",
|
"@sveltejs/adapter-static": "^3.0.8",
|
||||||
"@sveltejs/kit": "^2.0.0",
|
"@sveltejs/kit": "^2.22.0",
|
||||||
"@sveltejs/vite-plugin-svelte": "^3.0.0",
|
"@sveltejs/vite-plugin-svelte": "^5.1.0",
|
||||||
"@tailwindcss/typography": "^0.5.15",
|
"@tailwindcss/typography": "^0.5.16",
|
||||||
"@types/eslint": "^9.6.0",
|
"@types/eslint": "^9.6.1",
|
||||||
"autoprefixer": "^10.4.20",
|
"autoprefixer": "^10.4.21",
|
||||||
"eslint": "^9.11.1",
|
"eslint": "^9.29.0",
|
||||||
"eslint-config-prettier": "^9.1.0",
|
"eslint-config-prettier": "^9.1.0",
|
||||||
"eslint-plugin-svelte": "^2.36.0",
|
"eslint-plugin-svelte": "^2.46.1",
|
||||||
"globals": "^15.9.0",
|
"globals": "^15.15.0",
|
||||||
"mdsvex": "^0.12.3",
|
"mdsvex": "^0.12.6",
|
||||||
"mdsvex-relative-images": "^1.0.3",
|
"mdsvex-relative-images": "^1.0.3",
|
||||||
"prettier": "^3.1.1",
|
"prettier": "^3.5.3",
|
||||||
"prettier-plugin-svelte": "^3.1.2",
|
"prettier-plugin-svelte": "^3.4.0",
|
||||||
"prettier-plugin-tailwindcss": "^0.6.5",
|
"prettier-plugin-tailwindcss": "^0.6.13",
|
||||||
"rehype-katex-svelte": "^1.2.0",
|
"rehype-katex-svelte": "^1.2.0",
|
||||||
"remark-math": "^3.0.0",
|
"remark-math": "^3.0.1",
|
||||||
"svelte": "^4.2.7",
|
"svelte": "^5.34.7",
|
||||||
"svelte-check": "^4.0.0",
|
"svelte-check": "^4.0.0",
|
||||||
"tailwindcss": "^3.4.9",
|
"tailwindcss": "^3.4.17",
|
||||||
"typescript": "5.5",
|
"typescript": "~5.5.4",
|
||||||
"typescript-eslint": "^8.7.0",
|
"typescript-eslint": "^8.34.1",
|
||||||
"unist-util-visit": "^5.0.0",
|
"unist-util-visit": "^5.0.0",
|
||||||
"vite": "^5.0.3",
|
"vite": "^6.0.0",
|
||||||
"vitest": "^2.0.0"
|
"vitest": "^2.1.9"
|
||||||
},
|
},
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@fortawesome/fontawesome-free": "^6.6.0",
|
"@fortawesome/fontawesome-free": "^6.7.2",
|
||||||
"bits-ui": "^0.21.13",
|
"bits-ui": "^2.8.0",
|
||||||
"clsx": "^2.1.1",
|
"clsx": "^2.1.1",
|
||||||
"lucide-svelte": "^0.451.0",
|
"lucide-svelte": "^0.451.0",
|
||||||
"rehype-slug": "^6.0.0",
|
"rehype-slug": "^6.0.0",
|
||||||
"remark-github-blockquote-alert": "^1.2.1",
|
"remark-github-blockquote-alert": "^1.3.1",
|
||||||
"remark-toc": "^9.0.0",
|
"remark-toc": "^9.0.0",
|
||||||
"shiki": "^1.22.0",
|
"shiki": "^1.29.2",
|
||||||
"svelte-radix": "^1.1.1",
|
"svelte-radix": "^1.1.1",
|
||||||
"tailwind-merge": "^2.5.2",
|
"tailwind-merge": "^2.6.0",
|
||||||
"tailwind-variants": "^0.2.1"
|
"tailwind-variants": "^0.2.1"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -115,16 +115,18 @@ a, button {
|
||||||
text-shadow: 0 0 5px;
|
text-shadow: 0 0 5px;
|
||||||
}
|
}
|
||||||
.nav-link, .nav-link * {
|
.nav-link, .nav-link * {
|
||||||
color: var(--navlink);
|
|
||||||
@apply text-lg;
|
@apply text-lg;
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
font-family: serif;
|
font-family: serif;
|
||||||
}
|
}
|
||||||
|
.nav-link:not(.disabled-link):not(.current-link) {
|
||||||
|
color: var(--navlink);
|
||||||
|
}
|
||||||
a.disabled-link {
|
a.disabled-link {
|
||||||
color: rgb(128,128,128);
|
color: rgb(128,128,128);
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
}
|
}
|
||||||
a:not(.icon) {
|
main a:not(.icon) {
|
||||||
position: relative;
|
position: relative;
|
||||||
text-decoration: inherit;
|
text-decoration: inherit;
|
||||||
|
|
||||||
|
|
|
@ -6,6 +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%
|
||||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/katex@0.12.0/dist/katex.min.css" integrity="sha384-AfEj0r4/OFrOo5t7NnNe46zW/tFgW6x/bCJG8FqQCEo3+Aro6EYUG4+cU+KJWu/X" crossorigin="anonymous">
|
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/katex@0.12.0/dist/katex.min.css" integrity="sha384-AfEj0r4/OFrOo5t7NnNe46zW/tFgW6x/bCJG8FqQCEo3+Aro6EYUG4+cU+KJWu/X" crossorigin="anonymous">
|
||||||
|
<meta name="theme-color" content="#028760" />
|
||||||
</head>
|
</head>
|
||||||
<body data-sveltekit-preload-data="hover" class="font-serif">
|
<body data-sveltekit-preload-data="hover" class="font-serif">
|
||||||
<div style="display: contents">%sveltekit.body%</div>
|
<div style="display: contents">%sveltekit.body%</div>
|
||||||
|
|
|
@ -0,0 +1,6 @@
|
||||||
|
---
|
||||||
|
title: Research
|
||||||
|
---
|
||||||
|
# Research
|
||||||
|
|
||||||
|
I teach Lean!
|
|
@ -12,5 +12,12 @@
|
||||||
},
|
},
|
||||||
"extra": [
|
"extra": [
|
||||||
{ "route": "/archives", "name": "Archives" }
|
{ "route": "/archives", "name": "Archives" }
|
||||||
|
],
|
||||||
|
"markdown": {
|
||||||
|
"highlighterLangs": [
|
||||||
|
"python",
|
||||||
|
"lean",
|
||||||
|
"tex"
|
||||||
]
|
]
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,3 +26,7 @@ $$
|
||||||
$$
|
$$
|
||||||
\vec z^{(l+1)} = \mat M\vec z^{(l)} + \vec b
|
\vec z^{(l+1)} = \mat M\vec z^{(l)} + \vec b
|
||||||
$$
|
$$
|
||||||
|
|
||||||
|
```tex
|
||||||
|
\\newcommand{\\cirno}{9}
|
||||||
|
```
|
||||||
|
|
File diff suppressed because one or more lines are too long
After Width: | Height: | Size: 149 KiB |
|
@ -37,9 +37,7 @@
|
||||||
<p class="text-gray-200 flex justify-center">
|
<p class="text-gray-200 flex justify-center">
|
||||||
{#each (post?.tags ?? []) as tag, i}
|
{#each (post?.tags ?? []) as tag, i}
|
||||||
{#if i > 0}
|
{#if i > 0}
|
||||||
<div class="separator text-sm">
|
|
||||||
<DividerVertical />
|
<DividerVertical />
|
||||||
</div>
|
|
||||||
{/if}
|
{/if}
|
||||||
<a href="/tag/{tag}">{tag}</a>
|
<a href="/tag/{tag}">{tag}</a>
|
||||||
{/each}
|
{/each}
|
||||||
|
|
|
@ -20,7 +20,10 @@
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<button class="nav-link" on:click={toggleTheme} aria-label="Toggle Theme">
|
<button
|
||||||
|
id="theme-switch"
|
||||||
|
class="nav-link"
|
||||||
|
on:click={toggleTheme} aria-label="Toggle Theme">
|
||||||
{#if $theme === "tokiwa"}
|
{#if $theme === "tokiwa"}
|
||||||
<Sun />
|
<Sun />
|
||||||
{:else}
|
{:else}
|
||||||
|
@ -30,6 +33,7 @@
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
button {
|
button {
|
||||||
|
flex-shrink: 0;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
font-weight: inherit;
|
font-weight: inherit;
|
||||||
background: none;
|
background: none;
|
||||||
|
|
File diff suppressed because one or more lines are too long
After Width: | Height: | Size: 340 KiB |
|
@ -15,7 +15,8 @@ export function transformPostMeta(metadata: PostMetadata, slug: string) : Post {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function getPosts(tag: string | null = null) : Promise<Post[]> {
|
// Generates a list of all posts filtering by tags and series, reverse chronologically ordered.
|
||||||
|
export async function getPosts(filter: { tag?: string, series?: string }) : Promise<Post[]> {
|
||||||
const allPostFiles = import.meta.glob('$content/post/*.md');
|
const allPostFiles = import.meta.glob('$content/post/*.md');
|
||||||
const iterablePostFiles = Object.entries(allPostFiles);
|
const iterablePostFiles = Object.entries(allPostFiles);
|
||||||
|
|
||||||
|
@ -27,8 +28,10 @@ export async function getPosts(tag: string | null = null) : Promise<Post[]> {
|
||||||
return transformPostMeta(metadata, slug);
|
return transformPostMeta(metadata, slug);
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
if (tag)
|
if (filter?.tag)
|
||||||
posts = posts.filter(post => post.tags.includes(tag))
|
posts = posts.filter(post => post.tags.includes(filter.tag!))
|
||||||
|
if (filter?.series)
|
||||||
|
posts = posts.filter(post => post.series?.includes(filter.series!) ?? false)
|
||||||
|
|
||||||
posts.sort((post1, post2) => {
|
posts.sort((post1, post2) => {
|
||||||
const date1: Date = post1.date;
|
const date1: Date = post1.date;
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
import siteMetadata from '$content/metadata.json';
|
|
||||||
|
|
||||||
export const routes: { route: string, name: string, disabled?: boolean }[] = [
|
export const routes: { route: string, name: string, disabled?: boolean }[] = [
|
||||||
{ route: "/", name: "Home" },
|
{ route: "/", name: "Home" },
|
||||||
{ route: "/post", name: "Blog" },
|
{ route: "/post", name: "Blog" },
|
||||||
{ route: "/tag", name: "Tags" },
|
{ route: "/tag", name: "Tags" },
|
||||||
{ route: "/gallery", name: "Gallery", disabled: true },
|
{ route: "/gallery", name: "Gallery", disabled: true },
|
||||||
].concat(siteMetadata?.extra || []);
|
{ route: "/research", name: "Research" },
|
||||||
|
{ route: "/archives", name: "Archives" },
|
||||||
|
]
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { writable } from 'svelte/store'
|
import { writable, get } from 'svelte/store'
|
||||||
import { browser } from "$app/environment"
|
import { browser } from "$app/environment"
|
||||||
|
|
||||||
type Theme = 'tokiwa' | 'star'
|
type Theme = 'tokiwa' | 'star'
|
||||||
|
@ -11,3 +11,11 @@ export const theme = writable(userTheme ?? 'tokiwa')
|
||||||
export function setTheme(newTheme: Theme) {
|
export function setTheme(newTheme: Theme) {
|
||||||
theme.set(newTheme)
|
theme.set(newTheme)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function getThemeObject(key: string, obj: { [key in Theme]: string } | string) {
|
||||||
|
if (typeof obj === 'object') {
|
||||||
|
return obj[key];
|
||||||
|
} else {
|
||||||
|
return obj;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import '../app.css';
|
import '../app.css';
|
||||||
import { page } from '$app/stores';
|
import { page } from '$app/stores';
|
||||||
|
import { name } from '$content/metadata.json';
|
||||||
import Footer from "./Footer.svelte";
|
import Footer from "./Footer.svelte";
|
||||||
import Navbar from "./Navbar.svelte";
|
import Navbar from "./Navbar.svelte";
|
||||||
import PageTransition from "./PageTransition.svelte";
|
import PageTransition from "./PageTransition.svelte";
|
||||||
|
@ -11,7 +12,8 @@
|
||||||
<!-- Homepage has its own navbar with animations -->
|
<!-- Homepage has its own navbar with animations -->
|
||||||
{#if $page.url.pathname != "/"}
|
{#if $page.url.pathname != "/"}
|
||||||
<div id="layout">
|
<div id="layout">
|
||||||
<div id="navbar">
|
<div id="nav">
|
||||||
|
<p id="bio-name">{name}</p>
|
||||||
<Navbar />
|
<Navbar />
|
||||||
<slot name="header" />
|
<slot name="header" />
|
||||||
</div>
|
</div>
|
||||||
|
@ -31,6 +33,12 @@
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
|
#bio-name {
|
||||||
|
font-family: serif;
|
||||||
|
font-size: 3rem;
|
||||||
|
font-weight: normal;
|
||||||
|
color: var(--name);
|
||||||
|
}
|
||||||
#layout {
|
#layout {
|
||||||
max-width: max(80vw, 100vh);
|
max-width: max(80vw, 100vh);
|
||||||
margin-left: auto;
|
margin-left: auto;
|
||||||
|
@ -58,7 +66,7 @@
|
||||||
width: min(100vw, max(50vw, 100vh));
|
width: min(100vw, max(50vw, 100vh));
|
||||||
grid-area: content;
|
grid-area: content;
|
||||||
}
|
}
|
||||||
#navbar {
|
#nav {
|
||||||
align-self: right;
|
align-self: right;
|
||||||
padding-left: 10px;
|
padding-left: 10px;
|
||||||
grid-area: nav;
|
grid-area: nav;
|
||||||
|
|
|
@ -1,12 +1,39 @@
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
|
import { onMount } from 'svelte';
|
||||||
|
import { derived } from 'svelte/store'
|
||||||
import { routes } from "$lib/sitemap.ts"
|
import { routes } from "$lib/sitemap.ts"
|
||||||
import { Separator } from "$lib/components/ui/separator/index.js";
|
import { Separator } from "$lib/components/ui/separator/index.js";
|
||||||
|
import { theme, setTheme, getThemeObject } from '$lib/theme'
|
||||||
import { Rss } from "lucide-svelte";
|
import { Rss } from "lucide-svelte";
|
||||||
import ThemeSwitch from "$lib/components/ThemeSwitch.svelte"
|
import ThemeSwitch from "$lib/components/ThemeSwitch.svelte"
|
||||||
|
import Cover from "$lib/Cover.svelte"
|
||||||
let scrollPosition: number = .5;
|
let scrollPosition: number = .5;
|
||||||
let scrollHeight: number = 1;
|
let scrollHeight: number = 1;
|
||||||
let progress: number = 0;
|
let progress: number
|
||||||
|
= 0.0;
|
||||||
|
|
||||||
|
let button_blog;
|
||||||
|
|
||||||
|
function toggleTheme() {
|
||||||
|
theme.update((currentTheme) => {
|
||||||
|
const newTheme = currentTheme === 'tokiwa' ? 'star' : 'tokiwa'
|
||||||
|
|
||||||
|
document.documentElement.setAttribute('color-scheme', newTheme)
|
||||||
|
localStorage.setItem('color-scheme', newTheme)
|
||||||
|
|
||||||
|
if (newTheme === "tokiwa") {
|
||||||
|
document.documentElement.classList.remove('dark');
|
||||||
|
} else {
|
||||||
|
document.documentElement.classList.add('dark');
|
||||||
|
}
|
||||||
|
setTheme(newTheme);
|
||||||
|
return newTheme
|
||||||
|
})
|
||||||
|
}
|
||||||
|
onMount(() => {
|
||||||
|
let entity_switch = document.getElementById("switch");
|
||||||
|
entity_switch.addEventListener("click", toggleTheme);
|
||||||
|
});
|
||||||
function onScroll() {
|
function onScroll() {
|
||||||
if (scrollHeight > 1) {
|
if (scrollHeight > 1) {
|
||||||
progress = Math.max(0, Math.min(1, scrollPosition / scrollHeight));
|
progress = Math.max(0, Math.min(1, scrollPosition / scrollHeight));
|
||||||
|
@ -19,15 +46,22 @@
|
||||||
|
|
||||||
import metadata from '$content/metadata.json';
|
import metadata from '$content/metadata.json';
|
||||||
const iconMap: Map<string, string> = {
|
const iconMap: Map<string, string> = {
|
||||||
"bitbucket": "fa-brands fa-bitbucket",
|
"orcid": "fa-brands fa-orcid",
|
||||||
|
"google-scholar": "fa-brands fa-google-scholar",
|
||||||
|
|
||||||
"discord": "fa-brands fa-discord",
|
"discord": "fa-brands fa-discord",
|
||||||
"email": "fa-solid fa-envelope",
|
"email": "fa-solid fa-envelope",
|
||||||
|
|
||||||
|
"bitbucket": "fa-brands fa-bitbucket",
|
||||||
"github": "fa-brands fa-github",
|
"github": "fa-brands fa-github",
|
||||||
"gitlab": "fa-brands fa-gitlab",
|
"gitlab": "fa-brands fa-gitlab",
|
||||||
"google-scholar": "fa-brands fa-google-scholar",
|
|
||||||
"instagram": "fa-brands fa-instagram",
|
|
||||||
"open-source": "fa-brands fa-osi",
|
"open-source": "fa-brands fa-osi",
|
||||||
"orcid": "fa-brands fa-orcid",
|
|
||||||
|
"bluesky": "fa-brands fa-bluesky",
|
||||||
|
"youtube": "fa-brands fa-youtube",
|
||||||
|
"instagram": "fa-brands fa-instagram",
|
||||||
|
"bandcamp": "fa-brands fa-bandcamp",
|
||||||
|
"pixiv": "fa-brands fa-pixiv",
|
||||||
};
|
};
|
||||||
const iconLinks: [string, string][] = Object.entries(metadata.links).map(
|
const iconLinks: [string, string][] = Object.entries(metadata.links).map(
|
||||||
([key, link]) => [iconMap[key], link]);
|
([key, link]) => [iconMap[key], link]);
|
||||||
|
@ -38,36 +72,31 @@
|
||||||
</svelte:head>
|
</svelte:head>
|
||||||
|
|
||||||
<div
|
<div
|
||||||
id="background"
|
id="cover"
|
||||||
style="opacity: {1 - progress}; background-image: url('{metadata.frontCover}')"
|
style="opacity: {1 - progress}; --grid-line: #999; --grid-line-dark: #333; --grid-cell: #707078"
|
||||||
>
|
>
|
||||||
</div>
|
<div id="cover-image">
|
||||||
|
<Cover />
|
||||||
|
</div>
|
||||||
|
|
||||||
<div id="front">
|
<div id="navbar">
|
||||||
<div id="floater">
|
<div>
|
||||||
<p class="text-2xl floater-elem" style="color: #888">{metadata.frontDescription}</p>
|
<p class="text-2xl" style="color: #888; z-index: 2">{metadata.frontDescription}</p>
|
||||||
<div
|
</div>
|
||||||
class="floater-elem"
|
<div id="link-container" class="h-5 items-center">
|
||||||
style="padding-bottom: {(1 - progress) * 50}vh"
|
|
||||||
>
|
|
||||||
<div id="navbar" class="h-5 items-center space-x-4 text-sm">
|
|
||||||
<a class="nav-link" href="#bio">Bio</a>
|
<a class="nav-link" href="#bio">Bio</a>
|
||||||
<Separator class="bg-gray-500 dark:bg-gray-100" orientation="vertical" />
|
|
||||||
{#each routes as item}
|
{#each routes as item}
|
||||||
{#if item.route !== "/"}
|
{#if item.route !== "/"}
|
||||||
<a
|
<a
|
||||||
href={item.route}
|
href={item.route}
|
||||||
class="nav-link"
|
class="nav-link"
|
||||||
class:disabled-link={item.disabled}>{item.name}</a>
|
class:disabled-link={item.disabled}>{item.name}</a>
|
||||||
<Separator class="bg-gray-500 dark:bg-gray-100" orientation="vertical" />
|
|
||||||
{/if}
|
{/if}
|
||||||
{/each}
|
{/each}
|
||||||
<a class="icon nav-link" href="/rss.xml"><Rss /></a>
|
<a class="icon nav-link" href="/rss.xml"><Rss /></a>
|
||||||
<Separator class="bg-gray-500 dark:bg-gray-100" orientation="vertical" />
|
|
||||||
<ThemeSwitch />
|
<ThemeSwitch />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<main>
|
<main>
|
||||||
|
@ -78,7 +107,7 @@
|
||||||
<p id="bio-name">{name}</p>
|
<p id="bio-name">{name}</p>
|
||||||
<div class="w-100">
|
<div class="w-100">
|
||||||
{#each iconLinks as [cl, link]}
|
{#each iconLinks as [cl, link]}
|
||||||
<a class="icon m-1" href={link}><i class="fa-xl {cl}"></i></a>
|
<a class="icon m-1" href={link} aria-label={cl}><i class="fa-xl {cl}"></i></a>
|
||||||
{/each}
|
{/each}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -100,40 +129,130 @@
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
#background {
|
#cover {
|
||||||
background-attachment: fixed;
|
background:
|
||||||
background-size: cover;
|
repeating-linear-gradient(128.6deg, transparent, var(--grid-line) 1px, var(--grid-line) 2px, transparent 1px, transparent 55px),
|
||||||
background-repeat: no-repeat;
|
repeating-linear-gradient(11deg, transparent, var(--grid-line) 1px, var(--grid-line) 2px, transparent 1px, transparent 40px),
|
||||||
background-position: center center;
|
var(--grid-cell)
|
||||||
z-index: -10;
|
;
|
||||||
position: fixed;
|
/*
|
||||||
min-width: 100%;
|
position: absolute;
|
||||||
min-height: 100%;
|
background-size: contain;
|
||||||
|
background-position: center center; */
|
||||||
overscroll-behaviour: none;
|
overscroll-behaviour: none;
|
||||||
}
|
|
||||||
#front {
|
|
||||||
height: 100vh;
|
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
|
||||||
overscroll-behavior: none;
|
|
||||||
}
|
|
||||||
#floater {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
margin-top: auto;
|
flex-direction: column;
|
||||||
margin-left: auto;
|
visibility: visible;
|
||||||
margin-right: auto;
|
}
|
||||||
|
:global(.dark #cover) {
|
||||||
|
background:
|
||||||
|
repeating-linear-gradient(128.6deg, transparent, var(--grid-line-dark) 1px, var(--grid-line-dark) 2px, transparent 1px, transparent 55px),
|
||||||
|
repeating-linear-gradient(11deg, transparent, var(--grid-line-dark) 1px, var(--grid-line-dark) 2px, transparent 1px, transparent 40px),
|
||||||
|
black
|
||||||
|
;
|
||||||
|
}
|
||||||
|
:global(#cover-image > svg) {
|
||||||
|
max-width: 100svw;
|
||||||
|
max-height: 100svh;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
:global(svg a) {
|
||||||
|
pointer-events: all;
|
||||||
|
:global(path) {
|
||||||
|
filter: contrast(50%);
|
||||||
|
}
|
||||||
|
:global(.effect) {
|
||||||
|
visibility: hidden;
|
||||||
|
}
|
||||||
|
&:hover,
|
||||||
|
&:focus {
|
||||||
|
:global(.effect) {
|
||||||
|
visibility: visible;
|
||||||
|
}
|
||||||
|
:global(path) {
|
||||||
|
filter: contrast(100%);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
:global(.dark .shadow) {
|
||||||
|
visibility: hidden;
|
||||||
|
}
|
||||||
|
:global(svg .shadow) {
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
:global(#switch-right) {
|
||||||
|
visibility: hidden;
|
||||||
|
}
|
||||||
|
:global(#switch-left) {
|
||||||
|
visibility: visible;
|
||||||
|
}
|
||||||
|
:global(.dark #switch-right) {
|
||||||
|
visibility: visible;
|
||||||
|
}
|
||||||
|
:global(.dark #switch-left) {
|
||||||
|
visibility: hidden;
|
||||||
|
}
|
||||||
|
:global(.effect > .glow) {
|
||||||
|
filter: blur(.3rem);
|
||||||
|
}
|
||||||
|
.nav-link {
|
||||||
|
display: inline-block;
|
||||||
}
|
}
|
||||||
#navbar {
|
#navbar {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-wrap: wrap;
|
flex-wrap: wrap;
|
||||||
justify-content: center;
|
padding-top: 30%;
|
||||||
|
flex-direction: column;
|
||||||
|
div {
|
||||||
|
padding-left: 5%;
|
||||||
}
|
}
|
||||||
.floater-elem {
|
|
||||||
margin-left: auto;
|
|
||||||
margin-right: auto;
|
|
||||||
}
|
}
|
||||||
|
#link-container {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: flex-start;
|
||||||
|
}
|
||||||
|
/* mobile */
|
||||||
|
@media (max-width: 700px) {
|
||||||
|
#navbar {
|
||||||
|
visibility: visible;
|
||||||
|
height: 100svh;
|
||||||
|
}
|
||||||
|
#cover {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: flex-end;
|
||||||
|
}
|
||||||
|
#cover-image {
|
||||||
|
position: absolute;
|
||||||
|
max-height: 100svh;
|
||||||
|
max-width: 100svw;
|
||||||
|
pointer-events: none;
|
||||||
|
|
||||||
|
:global(.effect) {
|
||||||
|
visibility: visible;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
:global(#cover-image a) {
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
:global(svg .entity-label) {
|
||||||
|
visibility: hidden;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* desktop */
|
||||||
|
@media (min-width: 701px) {
|
||||||
|
#navbar {
|
||||||
|
padding-top: 0;
|
||||||
|
visibility: hidden;
|
||||||
|
height: 0;
|
||||||
|
width: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* main */
|
||||||
main {
|
main {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
@apply bg-background;
|
@apply bg-background;
|
||||||
|
|
|
@ -1,43 +1,95 @@
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { page } from '$app/stores';
|
import { page } from '$app/stores';
|
||||||
import { routes } from "$lib/sitemap.ts"
|
import { routes } from "$lib/sitemap.ts"
|
||||||
import { name } from '$content/metadata.json';
|
|
||||||
import ThemeSwitch from "$lib/components/ThemeSwitch.svelte"
|
import ThemeSwitch from "$lib/components/ThemeSwitch.svelte"
|
||||||
import { Rss } from "lucide-svelte";
|
import { Rss, Menu } from "lucide-svelte";
|
||||||
|
|
||||||
function isCurrentLink(pathname, route) {
|
function isCurrentLink(pathname, route) {
|
||||||
return route != "/" && pathname.startsWith(route)
|
return route != "/" && pathname.startsWith(route)
|
||||||
|| route == "/post" && pathname.startsWith("/page");
|
|| route == "/post" && pathname.startsWith("/page");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
import { onMount } from 'svelte';
|
||||||
|
|
||||||
|
let showDropdown = false;
|
||||||
|
|
||||||
|
function onDropdownToggle(event) {
|
||||||
|
showDropdown = !showDropdown;
|
||||||
|
}
|
||||||
|
function onKeyDown(event) {
|
||||||
|
if (event.key == "Escape") {
|
||||||
|
showDropdown = !showDropdown;
|
||||||
|
}
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div id="navbar" class="h-5 space-x-4">
|
<nav
|
||||||
<p id="bio-name">{name}</p>
|
id="navbar"
|
||||||
|
class="h-5 space-x-4"
|
||||||
|
class:dropdown-opened={showDropdown}>
|
||||||
|
<div
|
||||||
|
class="link-container"
|
||||||
|
role="button"
|
||||||
|
tabindex={0}
|
||||||
|
on:keydown={onKeyDown}
|
||||||
|
on:click={() => { showDropdown = false; }}
|
||||||
|
>
|
||||||
{#each routes as item}
|
{#each routes as item}
|
||||||
<a
|
<a
|
||||||
class="nav-link"
|
class="nav-link"
|
||||||
class:current-link={isCurrentLink($page.url.pathname, item.route)}
|
|
||||||
class:disabled-link={item.disabled}
|
class:disabled-link={item.disabled}
|
||||||
href={item.route}>{item.name}</a>
|
class:current-link={isCurrentLink($page.url.pathname, item.route)}
|
||||||
|
on:click={() => { showDropdown = false; }}
|
||||||
|
href={item.route}>
|
||||||
|
{item.name}
|
||||||
|
</a>
|
||||||
{/each}
|
{/each}
|
||||||
<a class="nav-link icon" href="/rss.xml"><Rss /></a>
|
<a class="nav-link icon" href="/rss.xml"><Rss /></a>
|
||||||
<div><ThemeSwitch /></div>
|
<div><ThemeSwitch /></div>
|
||||||
</div>
|
</div>
|
||||||
|
<button
|
||||||
|
id="dropdown-toggle"
|
||||||
|
aria-hidden="true"
|
||||||
|
on:click={onDropdownToggle}>
|
||||||
|
<Menu />
|
||||||
|
</button>
|
||||||
|
</nav>
|
||||||
|
|
||||||
|
<svelte:window on:keydown={onKeyDown} />
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
#bio-name {
|
.link-container {
|
||||||
font-family: serif;
|
|
||||||
font-size: 3rem;
|
|
||||||
font-weight: normal;
|
|
||||||
color: var(--name);
|
|
||||||
}
|
|
||||||
#navbar {
|
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
align-items: flex-end;
|
align-items: flex-end;
|
||||||
justify-content: between;
|
position: sticky;
|
||||||
|
top: 0;
|
||||||
|
}
|
||||||
|
#dropdown-toggle {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* mobile mode */
|
||||||
|
@media (max-width: 768px) {
|
||||||
|
.link-container {
|
||||||
|
position: fixed;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
height: 100vh;
|
||||||
|
justify-content: center;
|
||||||
|
|
||||||
|
margin: 0;
|
||||||
|
padding-left: 5vw;
|
||||||
|
padding-right: 5vw;
|
||||||
|
|
||||||
|
background: hsl(var(--background) / .8);
|
||||||
|
|
||||||
|
/* Initial hidden state */
|
||||||
|
opacity: 0;
|
||||||
|
transform: translateY(-100%);
|
||||||
|
transition: transform 0.2s, opacity 0.2s;
|
||||||
}
|
}
|
||||||
@media (max-width: 700px) {
|
|
||||||
#navbar {
|
#navbar {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
white-space: pre-wrap;
|
white-space: pre-wrap;
|
||||||
|
@ -45,5 +97,14 @@
|
||||||
#navbar .nav-link {
|
#navbar .nav-link {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
}
|
}
|
||||||
|
#dropdown-toggle {
|
||||||
|
display: initial;
|
||||||
|
z-index: 5;
|
||||||
|
}
|
||||||
|
.dropdown-opened > .link-container {
|
||||||
|
opacity: 1;
|
||||||
|
z-index: 1;
|
||||||
|
transform: translateY(0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -1,12 +0,0 @@
|
||||||
import type { PageLoad } from './$types';
|
|
||||||
|
|
||||||
export const load: PageLoad = async ({ params }) => {
|
|
||||||
const post = await import(`$content/extra/${params.slug}.md`);
|
|
||||||
const Content = post.default;
|
|
||||||
|
|
||||||
return {
|
|
||||||
slug: params.slug,
|
|
||||||
metadata: post.metadata,
|
|
||||||
Content,
|
|
||||||
};
|
|
||||||
}
|
|
|
@ -1,10 +1,10 @@
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import type { PageData } from './$types';
|
import type { PageData } from './$types';
|
||||||
export let data: PageData;
|
export let data: PageData;
|
||||||
const { slug, metadata, Content } = data;
|
const { metadata, Content } = data;
|
||||||
import siteMetadata from '$content/metadata.json';
|
import siteMetadata from '$content/metadata.json';
|
||||||
|
|
||||||
const title = metadata?.title || (slug[0].toUpperCase() + slug.slice(1));
|
const title = metadata?.title
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<svelte:head>
|
<svelte:head>
|
|
@ -0,0 +1,14 @@
|
||||||
|
import { error } from '@sveltejs/kit';
|
||||||
|
import type { PageLoad } from './$types';
|
||||||
|
|
||||||
|
export const load: PageLoad = async (_) => {
|
||||||
|
const post = await import(`$content/extra/archives.md`);
|
||||||
|
if (!post) throw error(404);
|
||||||
|
const { name } = post.metadata;
|
||||||
|
const Content = post.default;
|
||||||
|
|
||||||
|
return {
|
||||||
|
name,
|
||||||
|
Content,
|
||||||
|
};
|
||||||
|
}
|
|
@ -12,4 +12,4 @@
|
||||||
</svelte:head>
|
</svelte:head>
|
||||||
|
|
||||||
<hr class="separator" />
|
<hr class="separator" />
|
||||||
<PostList {posts} pageN=1 {maxPageN}/>
|
<PostList {posts} pageN={1} {maxPageN}/>
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
|
import { TrackPrevious, TrackNext } from 'svelte-radix';
|
||||||
import type { PageData } from './$types';
|
import type { PageData } from './$types';
|
||||||
export let data: PageData;
|
export let data: PageData;
|
||||||
const { post, Content } = data;
|
const { post, Content, seriesNeighbours } = data;
|
||||||
import siteMetadata from '$content/metadata.json';
|
import siteMetadata from '$content/metadata.json';
|
||||||
import PostHeader from '$lib/components/PostHeader.svelte';
|
import PostHeader from '$lib/components/PostHeader.svelte';
|
||||||
</script>
|
</script>
|
||||||
|
@ -17,3 +18,39 @@
|
||||||
<Content />
|
<Content />
|
||||||
</article>
|
</article>
|
||||||
<hr />
|
<hr />
|
||||||
|
<ul id="series">
|
||||||
|
{#each seriesNeighbours as { name, prevSlug, prevTitle, nextSlug, nextTitle }}
|
||||||
|
<li class="series-neighbour">
|
||||||
|
{#if prevTitle}
|
||||||
|
<a href="/post/{prevSlug}">{prevTitle}</a>
|
||||||
|
<p class="dummy"><TrackPrevious /></p>
|
||||||
|
{/if}
|
||||||
|
<p class="series-tag">{name}</p>
|
||||||
|
{#if nextTitle}
|
||||||
|
<p class="dummy"><TrackNext /></p>
|
||||||
|
<a href="/post/{nextSlug}">{nextTitle}</a>
|
||||||
|
{/if}
|
||||||
|
</li>
|
||||||
|
{/each}
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
#series {
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
.series-tag {
|
||||||
|
color: var(--series);
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
.dummy {
|
||||||
|
display: inline-block;
|
||||||
|
color: rgba(128,128,128, .6);
|
||||||
|
vertical-align: middle;
|
||||||
|
padding-left: 1em;
|
||||||
|
padding-right: 1em;
|
||||||
|
}
|
||||||
|
.series-neighbour {
|
||||||
|
padding-left: 2em;
|
||||||
|
padding-right: 2em;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
|
@ -1,16 +1,54 @@
|
||||||
import { error } from '@sveltejs/kit';
|
import { error } from '@sveltejs/kit';
|
||||||
import type { PageLoad } from './$types';
|
import type { PageLoad } from './$types';
|
||||||
import { transformPostMeta } from '$lib/posts';
|
import type { Post } from '$lib/types'
|
||||||
|
import { getPosts, transformPostMeta } from '$lib/posts';
|
||||||
|
|
||||||
export const load: PageLoad = async ({ params }) => {
|
export const load: PageLoad = async ({ params }) => {
|
||||||
try {
|
try {
|
||||||
const post = await import(`$content/post/${params.slug}.md`);
|
const post = await import(`$content/post/${params.slug}.md`);
|
||||||
if (!post) throw error(404);
|
if (!post) throw error(404);
|
||||||
|
const metadata: Post = transformPostMeta(post.metadata, params.slug);
|
||||||
const Content = post.default;
|
const Content = post.default;
|
||||||
|
|
||||||
|
const seriesNeighbours : {
|
||||||
|
name: string,
|
||||||
|
prevSlug?: string,
|
||||||
|
prevTitle?: string,
|
||||||
|
nextSlug?: string,
|
||||||
|
nextTitle?: string,
|
||||||
|
}[] = await Promise.all((metadata.series || []).map(async (series: string) => {
|
||||||
|
const postInSeries: Post[] = await getPosts({ series });
|
||||||
|
|
||||||
|
let prevSlug = undefined;
|
||||||
|
let prevTitle = undefined;
|
||||||
|
let nextSlug = undefined;
|
||||||
|
let nextTitle = undefined;
|
||||||
|
|
||||||
|
for (const p of postInSeries) {
|
||||||
|
if (p.date > metadata.date) {
|
||||||
|
nextSlug = p.slug;
|
||||||
|
nextTitle = p.title;
|
||||||
|
}
|
||||||
|
if (p.date < metadata.date) {
|
||||||
|
prevSlug = p.slug;
|
||||||
|
prevTitle = p.title;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
post: transformPostMeta(post.metadata, params.slug),
|
name: series,
|
||||||
|
prevSlug,
|
||||||
|
prevTitle,
|
||||||
|
nextSlug,
|
||||||
|
nextTitle,
|
||||||
|
};
|
||||||
|
}));
|
||||||
|
|
||||||
|
return {
|
||||||
|
post: metadata,
|
||||||
Content,
|
Content,
|
||||||
|
seriesNeighbours,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
catch {
|
catch {
|
||||||
|
|
|
@ -0,0 +1,18 @@
|
||||||
|
<script lang="ts">
|
||||||
|
import type { PageData } from './$types';
|
||||||
|
export let data: PageData;
|
||||||
|
const { metadata, Content } = data;
|
||||||
|
import siteMetadata from '$content/metadata.json';
|
||||||
|
|
||||||
|
const title = metadata?.title
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<svelte:head>
|
||||||
|
<title>{title} | {siteMetadata.blogName}</title>
|
||||||
|
</svelte:head>
|
||||||
|
|
||||||
|
<hr />
|
||||||
|
<article class="prose lg:prose-xl dark:prose-dark p-4">
|
||||||
|
<Content />
|
||||||
|
</article>
|
||||||
|
<hr />
|
|
@ -0,0 +1,14 @@
|
||||||
|
import { error } from '@sveltejs/kit';
|
||||||
|
import type { PageLoad } from './$types';
|
||||||
|
|
||||||
|
export const load: PageLoad = async (_) => {
|
||||||
|
const post = await import(`$content/extra/research.md`);
|
||||||
|
if (!post) throw error(404);
|
||||||
|
const { name } = post.metadata;
|
||||||
|
const Content = post.default;
|
||||||
|
|
||||||
|
return {
|
||||||
|
name,
|
||||||
|
Content,
|
||||||
|
};
|
||||||
|
}
|
|
@ -2,7 +2,7 @@ import type { PageLoad } from './$types';
|
||||||
import { getPosts } from '$lib/posts';
|
import { getPosts } from '$lib/posts';
|
||||||
|
|
||||||
export const load: PageLoad = async ({ params }) => {
|
export const load: PageLoad = async ({ params }) => {
|
||||||
const posts = await getPosts(params.slug);
|
const posts = await getPosts({ tag: params.slug });
|
||||||
return {
|
return {
|
||||||
name: params.slug,
|
name: params.slug,
|
||||||
posts,
|
posts,
|
||||||
|
|
|
@ -0,0 +1,34 @@
|
||||||
|
User-agent: GPTBot
|
||||||
|
Disallow: /
|
||||||
|
User-agent: ChatGPT-User
|
||||||
|
Disallow: /
|
||||||
|
User-agent: Google-Extended
|
||||||
|
Disallow: /
|
||||||
|
User-agent: PerplexityBot
|
||||||
|
Disallow: /
|
||||||
|
User-agent: Amazonbot
|
||||||
|
Disallow: /
|
||||||
|
User-agent: ClaudeBot
|
||||||
|
Disallow: /
|
||||||
|
User-agent: Omgilibot
|
||||||
|
Disallow: /
|
||||||
|
User-Agent: FacebookBot
|
||||||
|
Disallow: /
|
||||||
|
User-Agent: Applebot
|
||||||
|
Disallow: /
|
||||||
|
User-agent: anthropic-ai
|
||||||
|
Disallow: /
|
||||||
|
User-agent: Bytespider
|
||||||
|
Disallow: /
|
||||||
|
User-agent: Claude-Web
|
||||||
|
Disallow: /
|
||||||
|
User-agent: Diffbot
|
||||||
|
Disallow: /
|
||||||
|
User-agent: ImagesiftBot
|
||||||
|
Disallow: /
|
||||||
|
User-agent: Omgilibot
|
||||||
|
Disallow: /
|
||||||
|
User-agent: Omgili
|
||||||
|
Disallow: /
|
||||||
|
User-agent: YouBot
|
||||||
|
Disallow: /
|
|
@ -1,5 +1,6 @@
|
||||||
import { vitePreprocess } from '@sveltejs/vite-plugin-svelte';
|
import { vitePreprocess } from '@sveltejs/vite-plugin-svelte';
|
||||||
import adapter from '@sveltejs/adapter-static';
|
import adapter from '@sveltejs/adapter-static';
|
||||||
|
import fs from 'fs';
|
||||||
|
|
||||||
import { mdsvex, escapeSvelte } from 'mdsvex';
|
import { mdsvex, escapeSvelte } from 'mdsvex';
|
||||||
import remarkAlert from './src/lib/markdown.js'
|
import remarkAlert from './src/lib/markdown.js'
|
||||||
|
@ -12,7 +13,9 @@ import remarkMath from 'remark-math'
|
||||||
|
|
||||||
const contentDir = process.env?.CHRYSOBLOG_CONTENT ?? "src/content";
|
const contentDir = process.env?.CHRYSOBLOG_CONTENT ?? "src/content";
|
||||||
|
|
||||||
const langs = [
|
const metadata = await fs.promises.readFile(contentDir + "/metadata.json")
|
||||||
|
.then((file) => JSON.parse(file.toString()));
|
||||||
|
const langs = metadata?.markdown.highlighterLangs ?? [
|
||||||
"javascript",
|
"javascript",
|
||||||
"lean",
|
"lean",
|
||||||
"lisp",
|
"lisp",
|
||||||
|
@ -26,11 +29,7 @@ const langs = [
|
||||||
"c++",
|
"c++",
|
||||||
"sh",
|
"sh",
|
||||||
];
|
];
|
||||||
const highlightingThemes = {
|
const katexOptions = metadata?.markdown.katex ?? {
|
||||||
light: 'vitesse-light',
|
|
||||||
dark: 'vitesse-dark',
|
|
||||||
};
|
|
||||||
const katexOptions = {
|
|
||||||
macros: {
|
macros: {
|
||||||
"\\Nat": "\\mathbb N",
|
"\\Nat": "\\mathbb N",
|
||||||
"\\Complex": "\\mathbb C",
|
"\\Complex": "\\mathbb C",
|
||||||
|
@ -39,6 +38,10 @@ const katexOptions = {
|
||||||
"\\rv": "\\mathrm",
|
"\\rv": "\\mathrm",
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
const highlightingThemes = {
|
||||||
|
light: 'vitesse-light',
|
||||||
|
dark: 'vitesse-dark',
|
||||||
|
};
|
||||||
|
|
||||||
const themes = Object.keys(highlightingThemes).map(function(k){ return highlightingThemes[k] });
|
const themes = Object.keys(highlightingThemes).map(function(k){ return highlightingThemes[k] });
|
||||||
const highlighter = await getHighlighter({
|
const highlighter = await getHighlighter({
|
||||||
|
|
|
@ -0,0 +1,9 @@
|
||||||
|
import { expect, test } from '@playwright/test';
|
||||||
|
|
||||||
|
test('Navigate in series', async ({ page }) => {
|
||||||
|
await page.goto('/post');
|
||||||
|
await page.getByText('Placeholder 2').click();
|
||||||
|
await expect(page).toHaveURL("/post/placeholder2/");
|
||||||
|
await page.getByText('Placeholder 1').click();
|
||||||
|
await expect(page).toHaveURL("/post/placeholder1/");
|
||||||
|
});
|
Loading…
Reference in New Issue