Skip to content

Commit ea32666

Browse files
committed
Upgrade to Svelte 5
1 parent 3c61611 commit ea32666

File tree

15 files changed

+423
-486
lines changed

15 files changed

+423
-486
lines changed

package-lock.json

Lines changed: 222 additions & 390 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -12,30 +12,30 @@
1212
},
1313
"devDependencies": {
1414
"@sveltejs/adapter-static": "^3.0.0",
15-
"@sveltejs/kit": "^2.0.0",
16-
"@sveltejs/vite-plugin-svelte": "^3.0.0",
15+
"@sveltejs/kit": "^2.5.27",
16+
"@sveltejs/vite-plugin-svelte": "^4.0.0",
1717
"@tailwindcss/typography": "^0.5.7",
1818
"@vcarl/remark-headings": "^0.0.1",
1919
"autoprefixer": "^10.4.7",
2020
"cssnano": "^5.0.15",
2121
"eslint": "^7.32.0",
2222
"eslint-config-prettier": "^8.3.0",
23-
"eslint-plugin-svelte": "^2.33.1",
23+
"eslint-plugin-svelte": "^2.45.1",
2424
"mdsvex": "^0.11.0",
2525
"mdsvex-relative-images": "^1.0.3",
2626
"postcss": "^8.4.14",
2727
"postcss-load-config": "^4.0.1",
28-
"prettier": "^2.8.1",
29-
"prettier-plugin-svelte": "^2.10.1",
28+
"prettier": "^3.1.0",
29+
"prettier-plugin-svelte": "^3.2.6",
3030
"rehype-autolink-headings": "^5.1.0",
3131
"rehype-slug": "^4.0.1",
3232
"remark-reading-time": "^1.0.1",
33-
"svelte": "^4.0.0",
34-
"svelte-preprocess": "^5.0.3",
33+
"svelte": "^5.0.0",
34+
"svelte-preprocess": "^6.0.0",
3535
"tailwindcss": "^3.1.5",
36-
"typescript": "^5.0.0",
36+
"typescript": "^5.5.0",
3737
"unist-util-visit": "^3.1.0",
38-
"vite": "^5.0.0"
38+
"vite": "^5.4.4"
3939
},
4040
"type": "module",
4141
"dependencies": {

src/lib/components/ArrowLeftIcon.svelte

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,9 @@
1-
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor" {...$$props}>
1+
<script>
2+
/** @type {{ [key: string]: any }} */
3+
let { ...props } = $props();
4+
</script>
5+
6+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor" {...props}>
27
<path
38
fill-rule="evenodd"
49
d="M9.707 14.707a1 1 0 01-1.414 0l-4-4a1 1 0 010-1.414l4-4a1 1 0 011.414 1.414L7.414 9H15a1 1 0 110 2H7.414l2.293 2.293a1 1 0 010 1.414z"

src/lib/components/ArrowRightIcon.svelte

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,9 @@
1-
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor" {...$$props}>
1+
<script>
2+
/** @type {{ [key: string]: any }} */
3+
let { ...props } = $props();
4+
</script>
5+
6+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor" {...props}>
27
<path
38
fill-rule="evenodd"
49
d="M10.293 5.293a1 1 0 011.414 0l4 4a1 1 0 010 1.414l-4 4a1 1 0 01-1.414-1.414L12.586 11H5a1 1 0 110-2h7.586l-2.293-2.293a1 1 0 010-1.414z"

src/lib/components/Card.svelte

Lines changed: 33 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,44 +1,62 @@
11
<script>
2-
export let as = 'div'
3-
export let href = undefined
42
5-
let _class = undefined
6-
export { _class as class }
3+
/**
4+
* @typedef {Object} Props
5+
* @property {string} [as]
6+
* @property {any} [href]
7+
* @property {any} [class]
8+
* @property {import('svelte').Snippet} [eyebrow]
9+
* @property {import('svelte').Snippet} [title]
10+
* @property {import('svelte').Snippet} [description]
11+
* @property {import('svelte').Snippet} [actions]
12+
*/
13+
14+
/** @type {Props} */
15+
let {
16+
as = 'div',
17+
href = undefined,
18+
class: _class = undefined,
19+
eyebrow,
20+
title,
21+
description,
22+
actions
23+
} = $props();
24+
725
</script>
826

927
<svelte:element this={as} class={['relative flex flex-col items-start group', _class].join(' ')}>
10-
<slot name="eyebrow" />
28+
{@render eyebrow?.()}
1129

12-
{#if $$slots.title}
30+
{#if title}
1331
<div class="text-base font-semibold tracking-tight text-zinc-800 dark:text-zinc-100">
1432
{#if href}
1533
<div
1634
class="absolute z-0 transition scale-95 opacity-0 -inset-y-6 -inset-x-4 bg-zinc-50 group-hover:scale-100 group-hover:opacity-100 dark:bg-zinc-800/50 sm:-inset-x-6 sm:rounded-2xl"
17-
/>
35+
></div>
1836
<a {href} data-sveltekit-prefetch>
19-
<span class="absolute z-20 -inset-y-6 -inset-x-4 sm:-inset-x-6 sm:rounded-2xl" />
37+
<span class="absolute z-20 -inset-y-6 -inset-x-4 sm:-inset-x-6 sm:rounded-2xl"></span>
2038
<span class="relative z-10">
21-
<slot name="title" />
39+
{@render title?.()}
2240
</span>
2341
</a>
2442
{:else}
25-
<slot name="title" />
43+
{@render title?.()}
2644
{/if}
2745
</div>
2846
{/if}
2947

30-
{#if $$slots.description}
48+
{#if description}
3149
<div
3250
class="relative z-10 flex-1 text-sm text-zinc-600 dark:text-zinc-400"
33-
class:mt-2={!!$$slots.title}
51+
class:mt-2={!!title}
3452
>
35-
<slot name="description" />
53+
{@render description?.()}
3654
</div>
3755
{/if}
3856

39-
{#if $$slots.actions}
57+
{#if actions}
4058
<div aria-hidden="true" class="relative z-10 flex items-center mt-4">
41-
<slot name="actions" />
59+
{@render actions?.()}
4260
</div>
4361
{/if}
4462
</svelte:element>

src/lib/components/PostDate.svelte

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,23 @@
11
<script>
22
import { format, parseISO } from 'date-fns'
33
4-
export let decorate
5-
export let post
6-
export let collapsed = false
74
8-
let _class
9-
export { _class as class }
5+
/**
6+
* @typedef {Object} Props
7+
* @property {any} decorate
8+
* @property {any} post
9+
* @property {boolean} [collapsed]
10+
* @property {any} class
11+
*/
12+
13+
/** @type {Props} */
14+
let {
15+
decorate,
16+
post,
17+
collapsed = false,
18+
class: _class
19+
} = $props();
20+
1021
</script>
1122

1223
<div
@@ -15,7 +26,7 @@
1526
>
1627
{#if decorate}
1728
<span class="absolute inset-y-0 left-0 flex items-center py-1" aria-hidden="true">
18-
<span class="h-full w-0.5 rounded-full bg-zinc-200 dark:bg-zinc-500" />
29+
<span class="h-full w-0.5 rounded-full bg-zinc-200 dark:bg-zinc-500"></span>
1930
</span>
2031
{/if}
2132
<div class="flex" class:flex-col={!collapsed}>

src/lib/components/PostPreview.svelte

Lines changed: 37 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -2,24 +2,47 @@
22
import Card from "./Card.svelte";
33
import ArrowRightIcon from "./ArrowRightIcon.svelte";
44
5-
export let post;
6-
export let showPreview = true;
5+
/**
6+
* @typedef {Object} Props
7+
* @property {any} post
8+
* @property {boolean} [showPreview]
9+
* @property {import('svelte').Snippet} [eyebrow]
10+
* @property {import('svelte').Snippet} [children]
11+
*/
12+
13+
/** @type {Props} */
14+
let {
15+
post,
16+
showPreview = true,
17+
eyebrow,
18+
children
19+
} = $props();
20+
21+
const eyebrow_render = $derived(eyebrow);
722
</script>
823

924
<Card href={post.path} data-sveltekit-prefetch>
10-
<slot slot="eyebrow" name="eyebrow" />
11-
<slot slot="title">{post.title}</slot>
12-
<div slot="description" class="prose dark:prose-invert">
13-
{#if showPreview}
14-
{@html post.preview.html}
15-
{/if}
16-
</div>
17-
<div slot="actions">
18-
<div class="flex items-center text-teal-500">
19-
<span class="text-sm font-medium">Read</span>
20-
<ArrowRightIcon class="w-4 h-4 ml-1" />
25+
{#snippet eyebrow()}
26+
{@render eyebrow_render?.()}
27+
{/snippet}
28+
{#snippet title()}
29+
{#if children}{@render children()}{:else}{post.title}{/if}
30+
{/snippet}
31+
{#snippet description()}
32+
<div class="prose dark:prose-invert">
33+
{#if showPreview}
34+
{@html post.preview.html}
35+
{/if}
36+
</div>
37+
{/snippet}
38+
{#snippet actions()}
39+
<div >
40+
<div class="flex items-center text-teal-500">
41+
<span class="text-sm font-medium">Read</span>
42+
<ArrowRightIcon class="w-4 h-4 ml-1" />
43+
</div>
2144
</div>
22-
</div>
45+
{/snippet}
2346
</Card>
2447

2548
<style>

src/lib/components/PostsList.svelte

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,15 @@
22
import PostPreview from "$lib/components/PostPreview.svelte";
33
import PostDate from "$lib/components/PostDate.svelte";
44
5-
export let posts;
6-
export let showPreview = true;
5+
/**
6+
* @typedef {Object} Props
7+
* @property {any} posts
8+
* @property {boolean} [showPreview]
9+
* @property {import('svelte').Snippet} [children]
10+
*/
11+
12+
/** @type {Props} */
13+
let { posts, showPreview = true, children } = $props();
714
</script>
815

916
<div
@@ -15,9 +22,11 @@
1522

1623
<div class="col-span-4 md:col-span-3">
1724
<PostPreview {post} {showPreview}>
18-
<slot slot="eyebrow">
19-
<PostDate class="md:hidden" {post} collapsed decorate />
20-
</slot>
25+
{#snippet eyebrow()}
26+
{#if children}{@render children()}{:else}
27+
<PostDate class="md:hidden" {post} collapsed decorate />
28+
{/if}
29+
{/snippet}
2130
</PostPreview>
2231
</div>
2332
</article>

src/lib/components/ToC.svelte

Lines changed: 22 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -3,17 +3,17 @@
33
import { onMount } from 'svelte'
44
import Card from './Card.svelte'
55
6-
export let post
6+
let { post, children } = $props();
77
88
let elements = []
9-
let headings = post.headings
9+
let headings = $state(post.headings)
1010
1111
onMount(() => {
1212
updateHeadings()
1313
setActiveHeading()
1414
})
1515
16-
let activeHeading = headings[0]
16+
let activeHeading = $state(headings[0])
1717
let scrollY
1818
1919
function updateHeadings() {
@@ -46,25 +46,27 @@
4646
}
4747
</script>
4848

49-
<svelte:window on:scroll={setActiveHeading} />
49+
<svelte:window onscroll={setActiveHeading} />
5050

5151
<Card>
52-
<slot slot="description">
53-
<ul class="flex flex-col gap-2">
54-
{#each headings as heading}
55-
<li
56-
class="pl-2 transition-colors border-teal-500 heading text-zinc-500 dark:text-zinc-600 hover:text-zinc-900 dark:hover:text-zinc-100"
57-
class:active={activeHeading === heading}
58-
style={`--depth: ${
59-
// consider h1 and h2 at the same depth, as h1 will only be used for page title
60-
Math.max(0, heading.depth - 1)
61-
}`}
62-
>
63-
<a href={`#${heading.id}`}>{heading.value}</a>
64-
</li>
65-
{/each}
66-
</ul>
67-
</slot>
52+
{#snippet description()}
53+
{#if children}{@render children()}{:else}
54+
<ul class="flex flex-col gap-2">
55+
{#each headings as heading}
56+
<li
57+
class="pl-2 transition-colors border-teal-500 heading text-zinc-500 dark:text-zinc-600 hover:text-zinc-900 dark:hover:text-zinc-100"
58+
class:active={activeHeading === heading}
59+
style={`--depth: ${
60+
// consider h1 and h2 at the same depth, as h1 will only be used for page title
61+
Math.max(0, heading.depth - 1)
62+
}`}
63+
>
64+
<a href={`#${heading.id}`}>{heading.value}</a>
65+
</li>
66+
{/each}
67+
</ul>
68+
{/if}
69+
{/snippet}
6870
</Card>
6971

7072
<style lang="postcss">

src/lib/data/posts.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import { browser } from '$app/environment'
22
import { format } from 'date-fns'
33
import { parse } from 'node-html-parser'
44
import readingTime from 'reading-time/lib/reading-time.js'
5+
import { render } from 'svelte/server'
56
import { website } from "$lib/info.js";
67

78
// we require some server-side APIs to parse all metadata
@@ -48,7 +49,7 @@ export function metaAnnotator({ withPreview = false, urlPrefix = "/" }) {
4849
return meta
4950
}
5051

51-
const html = parse(entry.default.render().html)
52+
const html = parse(render(entry.default).html)
5253
const preview = entry.metadata.preview ? parse(entry.metadata.preview) : html.querySelector('p')
5354

5455
meta.readingTime = readingTime(html.structuredText).text

0 commit comments

Comments
 (0)