Skip to content

Commit ad07a06

Browse files
authored
Migrate to Svelte 5 (#135)
* migrate to Svelte 5 * npm-test.yml add install-e2e: npx playwright install chromium nodejs-gh-pages.yml drop custom install-cmd * fix build * fix playwright tests * 2 new in site/tests/site.test.ts - Add test for 404 page handling - Add test for page metadata (title, description, OG tags)
1 parent 403f83f commit ad07a06

17 files changed

+231
-155
lines changed

.github/workflows/gh-pages.yml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,4 +12,3 @@ jobs:
1212
uses: janosh/workflows/.github/workflows/nodejs-gh-pages.yml@main
1313
with:
1414
working-directory: site
15-
install-cmd: npm install -f

.github/workflows/test.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,3 +12,4 @@ jobs:
1212
uses: janosh/workflows/.github/workflows/npm-test.yml@main
1313
with:
1414
working-directory: site
15+
install-e2e: npx playwright install chromium

.pre-commit-config.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ repos:
5454
stages: [pre-commit, commit-msg]
5555

5656
- repo: https://github.com/pre-commit/mirrors-eslint
57-
rev: v9.19.0
57+
rev: v9.20.1
5858
hooks:
5959
- id: eslint
6060
types: [file]

site/package.json

Lines changed: 22 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -17,31 +17,31 @@
1717
"test": "playwright test tests/*.test.ts"
1818
},
1919
"devDependencies": {
20-
"@iconify/svelte": "^4.0.2",
21-
"@playwright/test": "^1.47.1",
20+
"@iconify/svelte": "^4.2.0",
21+
"@playwright/test": "^1.50.1",
2222
"@rollup/plugin-yaml": "^4.1.2",
23-
"@stylistic/eslint-plugin": "^3.0.1",
24-
"@sveltejs/adapter-static": "^3.0.5",
25-
"@sveltejs/kit": "^2.5.28",
26-
"@sveltejs/vite-plugin-svelte": "^3.1.2",
27-
"dotenv": "^16.4.5",
28-
"eslint": "^9.10.0",
29-
"eslint-plugin-svelte": "^2.44.0",
23+
"@stylistic/eslint-plugin": "^4.0.1",
24+
"@sveltejs/adapter-static": "^3.0.8",
25+
"@sveltejs/kit": "^2.17.2",
26+
"@sveltejs/vite-plugin-svelte": "^5.0.3",
27+
"dotenv": "^16.4.7",
28+
"eslint": "^9.20.1",
29+
"eslint-plugin-svelte": "^2.46.1",
3030
"js-yaml": "^4.1.0",
31-
"marked": "^14.1.2",
32-
"prettier": "^3.3.3",
33-
"prettier-plugin-svelte": "^3.2.6",
34-
"puppeteer": "^23.3.1",
31+
"marked": "^15.0.7",
32+
"prettier": "^3.5.1",
33+
"prettier-plugin-svelte": "^3.3.3",
34+
"puppeteer": "^24.2.1",
3535
"sharp": "^0.33.5",
36-
"svelte": "4.2.19",
37-
"svelte-check": "^4.0.2",
38-
"svelte-multiselect": "^10.3.0",
39-
"svelte-preprocess": "^6.0.2",
40-
"svelte-zoo": "^0.4.11",
41-
"svelte2tsx": "^0.7.19",
42-
"typescript": "5.6.2",
43-
"typescript-eslint": "^8.6.0",
44-
"vite": "^5.4.6"
36+
"svelte": "^5.20.2",
37+
"svelte-check": "^4.1.4",
38+
"svelte-multiselect": "11.0.0-rc.1",
39+
"svelte-preprocess": "^6.0.3",
40+
"svelte-zoo": "^0.4.17",
41+
"svelte2tsx": "^0.7.34",
42+
"typescript": "5.7.3",
43+
"typescript-eslint": "^8.24.1",
44+
"vite": "^6.1.1"
4545
},
4646
"keywords": [
4747
"sveltekit",

site/src/lib/ContributorList.svelte

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,11 @@
11
<script lang="ts">
22
import type { RepoContributor } from '$lib'
33
4-
export let contributors: RepoContributor[]
4+
interface Props {
5+
contributors: RepoContributor[]
6+
}
7+
8+
let { contributors }: Props = $props()
59
</script>
610

711
<ul class="contributors">

site/src/lib/Filters.svelte

Lines changed: 19 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,13 @@
1010
tag_filter_mode,
1111
} from './stores'
1212
13-
export let tags: [string, number][]
14-
export let contributors: [string, number][]
15-
export let sort_order: `asc` | `desc` = `desc`
13+
interface Props {
14+
tags: [string, number][]
15+
contributors: [string, number][]
16+
sort_order?: `asc` | `desc`
17+
}
18+
19+
let { tags, contributors, sort_order = $bindable(`desc`) }: Props = $props()
1620
</script>
1721

1822
<div class="filters">
@@ -23,10 +27,12 @@
2327
placeholder="Filter by tag..."
2428
bind:selected={$filter_tags}
2529
>
26-
<span slot="option" let:option style="display: flex;">
27-
{option.label} <span style="flex: 1;"></span>
28-
{option.count}
29-
</span>
30+
{#snippet option({ option })}
31+
<span style="display: flex;">
32+
{option.label} <span style="flex: 1;"></span>
33+
{option.count}
34+
</span>
35+
{/snippet}
3036
</MultiSelect>
3137
{#if $filter_tags.length > 1}
3238
<RadioButtons bind:selected={$tag_filter_mode} options={[`all`, `any`]} />
@@ -38,10 +44,12 @@
3844
placeholder="Filter by contributor..."
3945
bind:selected={$filter_contributors}
4046
>
41-
<span slot="option" let:option style="display: flex;">
42-
{option.label} <span style="flex: 1;"></span>
43-
{option.count}
44-
</span>
47+
{#snippet option({ option })}
48+
<span style="display: flex;">
49+
{option.label} <span style="flex: 1;"></span>
50+
{option.count}
51+
</span>
52+
{/snippet}
4553
</MultiSelect>
4654
{#if $filter_contributors.length > 1}
4755
<RadioButtons bind:selected={$contributor_filter_mode} options={[`all`, `any`]} />

site/src/lib/Person.svelte

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,13 @@
22
import Icon from '@iconify/svelte'
33
import type { Contributor } from '.'
44
5-
export let person: Contributor
5+
interface Props {
6+
person: Contributor
7+
}
8+
9+
let { person }: Props = $props()
610
7-
$: ({ name, twitter, github, url, avatar } = person)
11+
let { name, twitter, github, url, avatar } = $derived(person)
812
</script>
913

1014
<span>

site/src/lib/Screenshot.svelte

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,21 @@
11
<script lang="ts">
22
import { dev } from '$app/environment'
33
4-
export let title: string
5-
// width/height used only for aspect ratio to avoid content shift on img load
6-
export let width = 800
7-
export let height = 600
8-
export let style = ``
9-
export let resolution: `.small` | `` = ``
4+
interface Props {
5+
title: string
6+
// width/height used only for aspect ratio to avoid content shift on img load
7+
width?: number
8+
height?: number
9+
style?: string
10+
resolution?: `.small` | ``
11+
}
12+
13+
let { title, width = 800, height = 600, style = ``, resolution = `` }: Props = $props()
1014
11-
const titleToSlug = (title: string) => title.toLowerCase().replaceAll(` `, `-`)
15+
const slugify = (title: string) => title.toLowerCase().replaceAll(` `, `-`)
1216
1317
const base = `https://raw.githubusercontent.com/janosh/awesome-sveltekit/main/site/static`
14-
$: src = `${dev ? `` : base}/screenshots/${titleToSlug(title)}${resolution}.avif`
18+
let src = $derived(`${dev ? `` : base}/screenshots/${slugify(title)}${resolution}.avif`)
1519
</script>
1620

1721
<img {src} alt="Screenshot of {title}" {width} {height} {style} />

site/src/lib/SiteDetails.svelte

Lines changed: 23 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -4,24 +4,30 @@
44
import { Tooltip } from 'svelte-zoo'
55
import { Person, Screenshot, type Site } from '.'
66
7-
export let site: Site
7+
interface Props {
8+
site: Site
9+
}
10+
11+
let { site }: Props = $props()
812
9-
$: ({ title, url, tags, uses, contributors, date_created, repo_stars } = site)
13+
let { title, url, tags, uses, contributors, date_created, repo_stars } = $derived(site)
1014
11-
$: days_since_created = Math.floor(
12-
(Date.now() - date_created.getTime()) / (1000 * 60 * 60 * 24)
15+
let days_since_created = $derived(
16+
Math.floor((Date.now() - date_created.getTime()) / (1000 * 60 * 60 * 24)),
1317
)
1418
15-
$: tools = uses.map((tool) => {
16-
const href = uses_links[tool.toLowerCase()]
17-
if (!href) {
18-
console.error(`Unknown tool: ${tool}`)
19-
} else if (!href.startsWith(`https`)) {
20-
// all tools should have an https URL
21-
throw `All tool URLs should use HTTPS: ${tool} has href: ${href}`
22-
}
23-
return [tool, href]
24-
})
19+
let tools = $derived(
20+
uses.map((tool) => {
21+
const href = uses_links[tool.toLowerCase()]
22+
if (!href) {
23+
console.error(`Unknown tool: ${tool}`)
24+
} else if (!href.startsWith(`https`)) {
25+
// all tools should have an https URL
26+
throw `All tool URLs should use HTTPS: ${tool} has href: ${href}`
27+
}
28+
return [tool, href]
29+
}),
30+
)
2531
</script>
2632

2733
<section>
@@ -48,7 +54,7 @@
4854
<hr />
4955
<p class="flex">
5056
<Icon icon="octicon:star" />&emsp;Stars
51-
<span style="flex: 1" />
57+
<span style="flex: 1"></span>
5258
<a href="{site.repo}/stargazers">{repo_stars.toLocaleString()}</a>
5359
</p>
5460
{/if}
@@ -72,7 +78,7 @@
7278
{/each}
7379
</ol>
7480
{:else}
75-
<span style="flex: 1" />
81+
<span style="flex: 1"></span>
7682
<Person person={contributors[0]} />
7783
{/if}
7884
</div>
@@ -81,7 +87,7 @@
8187
<hr />
8288
<p class="flex">
8389
<Icon icon="octicon:project" />&emsp;Project started on
84-
<span style="flex: 1" />
90+
<span style="flex: 1"></span>
8591
<Tooltip
8692
text="{days_since_created} days ago"
8793
min_width="max-content"

site/src/lib/SiteList.svelte

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,13 @@
77
import type { Site } from '.'
88
import { SitePreview } from '.'
99
10-
export let sites: Site[]
10+
interface Props {
11+
sites: Site[]
12+
}
13+
14+
let { sites }: Props = $props()
1115
12-
let active_idx = -1
16+
let active_idx = $state(-1)
1317
1418
function handle_keyup(event: KeyboardEvent) {
1519
if (event.key === `Enter` && active_idx >= 0) {
@@ -29,7 +33,7 @@
2933
}
3034
</script>
3135

32-
<svelte:window on:keyup={handle_keyup} />
36+
<svelte:window onkeyup={handle_keyup} />
3337

3438
<ol use:highlight_matches={{ query: $search, css_class: `highlight-match` }}>
3539
{#each sites as site, idx (site.url)}
@@ -56,7 +60,7 @@
5660
border-radius: 1ex;
5761
padding: 10pt;
5862
}
59-
ol > :is(li:hover, li.active) {
63+
ol > :is(:global(li:hover, li.active)) {
6064
transform: scale(1.01);
6165
background-color: rgba(255, 255, 255, 0.05);
6266
}

site/src/lib/SitePreview.svelte

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,13 @@
44
import { Screenshot } from '.'
55
import { filter_tags } from './stores'
66
7-
export let site: Site
8-
export let idx: number = 0
9-
export let tags: boolean = false
10-
export let style: string | null = null
7+
interface Props {
8+
site: Site
9+
idx?: number
10+
tags?: boolean
11+
style?: string | null
12+
}
13+
let { site, idx = 0, tags = false, style = null }: Props = $props()
1114
</script>
1215

1316
<a href={site.slug} {style}>

site/src/routes/+error.svelte

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
import { homepage, name } from '$site/package.json'
44
import Icon from '@iconify/svelte'
55
6-
let online: boolean
6+
let online: boolean = $state(true)
77
</script>
88

99
<svelte:head>

site/src/routes/+layout.svelte

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,12 @@
55
import { GitHubCorner } from 'svelte-zoo'
66
import '../app.css'
77
import sites from '../sites.yml'
8+
interface Props {
9+
children?: import('svelte').Snippet
10+
}
811
9-
let innerWidth: number
12+
let { children }: Props = $props()
13+
let innerWidth: number = $state(0)
1014
1115
const actions = sites.map(({ title, slug }) => {
1216
return { label: title, action: () => goto(slug) }
@@ -23,4 +27,4 @@
2327
<base target="_{innerWidth > 600 ? `blank` : `self`}" />
2428
</svelte:head>
2529

26-
<slot />
30+
{@render children?.()}

0 commit comments

Comments
 (0)