Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
b374185
fix(fontless): support preload
hi-ogawa Sep 26, 2025
f72d68a
wip
hi-ogawa Sep 26, 2025
9e3788e
wip
hi-ogawa Sep 26, 2025
1e9e3cc
Revert "wip"
hi-ogawa Sep 26, 2025
0009ac6
chore: cleanup
hi-ogawa Sep 26, 2025
cd08fe3
cleanup
hi-ogawa Sep 26, 2025
c698aff
Merge branch 'main' into 09-26-fix_fontless_support_preload
hi-ogawa Sep 26, 2025
80f6c99
chore: tweak
hi-ogawa Sep 26, 2025
aa58ce4
test: add e2e
hi-ogawa Sep 26, 2025
45d834b
Merge branch 'main' into 09-26-fix_fontless_support_preload
hi-ogawa Sep 26, 2025
7853b5c
feat(fontless): expose preload fonts via `fontless/runtime`
hi-ogawa Sep 27, 2025
47f4cc0
chore: update examples
hi-ogawa Sep 27, 2025
21ad534
Merge branch 'main' into 09-27-feat_fontless_expose_preload_fonts_via…
hi-ogawa Sep 28, 2025
7d61080
Merge branch 'main' into 09-27-feat_fontless_expose_preload_fonts_via…
hi-ogawa Sep 28, 2025
bd022dd
refactor: minor
hi-ogawa Sep 28, 2025
f81ab22
Merge branch 'main' into 09-27-feat_fontless_expose_preload_fonts_via…
hi-ogawa Sep 29, 2025
e564a65
chore: comment
hi-ogawa Sep 29, 2025
1ab307b
docs: wip
hi-ogawa Sep 29, 2025
8230cae
fix: noExternal fontless/runtime
hi-ogawa Sep 29, 2025
633494d
fix: invalidate runtime during dev
hi-ogawa Sep 29, 2025
84f2976
fix: invalidate virtual module on all environments
hi-ogawa Sep 29, 2025
d9f84e1
chore: add preload to qwik example
hi-ogawa Sep 29, 2025
20891c8
refactor: return attributs from preload
hi-ogawa Sep 29, 2025
3707328
test: add e2e
hi-ogawa Sep 29, 2025
31ccb7c
Merge branch 'main' into 09-27-feat_fontless_expose_preload_fonts_via…
hi-ogawa Sep 30, 2025
51b5cda
chore: fix types
hi-ogawa Sep 30, 2025
f192c2d
docs
hi-ogawa Sep 30, 2025
6ef95e3
docs
hi-ogawa Sep 30, 2025
a918a4a
chore: cleanup
hi-ogawa Sep 30, 2025
b4a67b5
fix: tweak type
hi-ogawa Sep 30, 2025
4a884c4
test: add sveltekit example
hi-ogawa Sep 30, 2025
71071b3
chore: remove svelte-app in favor of sveltekit-app
hi-ogawa Sep 30, 2025
b4f591e
chore: cleanup
hi-ogawa Sep 30, 2025
d72f8e6
chore: knip
hi-ogawa Sep 30, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
test: add sveltekit example
  • Loading branch information
hi-ogawa committed Sep 30, 2025
commit 4a884c4188d7757e977abaed57cd106288ac4879
5 changes: 3 additions & 2 deletions packages/fontless/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -189,16 +189,17 @@ function Layout() {
}
```

- [SvelteKit](https://github.com/sveltejs/kit/)
- [SvelteKit]./examples/sveltekit-app)

```svelte
<script lang="ts">
import { preloads } from "fontless/runtime";
</script>

<svelte:head>
<link rel="icon" href={favicon} />
{#each preloads as attrs}
<link rel={attrs.rel} as={attrs.as} href={attrs.href} crossorigin={attrs.crossorigin} />
<link {...attrs} />
{/each}
</svelte:head>
```
Expand Down
56 changes: 55 additions & 1 deletion packages/fontless/e2e/basic.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,20 @@ test.describe('build react-rotuer', () => {
await cli.done
})

test.describe(() => {
test('basic', async ({ page }) => {
await page.goto(baseURL)
const fonts = await page.evaluate(async () => {
const fonts = await (globalThis as any).document.fonts.ready
return [...fonts].map((f: any) => ({ family: f.family, status: f.status }))
})
expect(fonts).toEqual(
expect.arrayContaining([
{ family: 'Poppins', status: 'loaded' },
]),
)
})

test.describe('no js', () => {
test.use({ javaScriptEnabled: false })

test('ssr preload links', async ({ page }) => {
Expand All @@ -67,3 +80,44 @@ test.describe('build react-rotuer', () => {
})
})
})

test.describe('build sveltekit', () => {
let cli: ReturnType<typeof runCli>
let baseURL: string

test.beforeAll(async () => {
const build = runCli({ command: 'pnpm build', cwd: 'examples/sveltekit-app' })
await build.done
cli = runCli({ command: 'pnpm preview', cwd: 'examples/sveltekit-app' })
const port = await cli.findPort()
baseURL = `http://localhost:${port}`
})

test.afterAll(async () => {
if (!cli)
return
cli.kill()
await cli.done
})

test('basic', async ({ page }) => {
await page.goto(baseURL)
const fonts = await page.evaluate(async () => {
const fonts = await (globalThis as any).document.fonts.ready
return [...fonts].map((f: any) => ({ family: f.family, status: f.status }))
})
expect(fonts).toEqual(
expect.arrayContaining([
{ family: 'Fira Sans', status: 'loaded' },
]),
)
})

test.describe('no js', () => {
test.use({ javaScriptEnabled: false })
test('ssr preload links', async ({ page }) => {
await page.goto(baseURL)
await expect(page.locator('head > link[rel="preload"][as="font"]').first()).toBeAttached()
})
})
})
23 changes: 23 additions & 0 deletions packages/fontless/examples/sveltekit-app/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
node_modules

# Output
.output
.vercel
.netlify
.wrangler
/.svelte-kit
/build

# OS
.DS_Store
Thumbs.db

# Env
.env
.env.*
!.env.example
!.env.test

# Vite
vite.config.js.timestamp-*
vite.config.ts.timestamp-*
1 change: 1 addition & 0 deletions packages/fontless/examples/sveltekit-app/.npmrc
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
engine-strict=true
38 changes: 38 additions & 0 deletions packages/fontless/examples/sveltekit-app/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
# sv

Everything you need to build a Svelte project, powered by [`sv`](https://github.com/sveltejs/cli).

## Creating a project

If you're seeing this, you've probably already done this step. Congrats!

```sh
# create a new project in the current directory
npx sv create

# create a new project in my-app
npx sv create my-app
```

## Developing

Once you've created a project and installed dependencies with `npm install` (or `pnpm install` or `yarn`), start a development server:

```sh
npm run dev

# or start the server and open the app in a new browser tab
npm run dev -- --open
```

## Building

To create a production version of your app:

```sh
npm run build
```

You can preview the production build with `npm run preview`.

> To deploy your app, you may need to install an [adapter](https://svelte.dev/docs/kit/adapters) for your target environment.
24 changes: 24 additions & 0 deletions packages/fontless/examples/sveltekit-app/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
{
"name": "sveltekit-app",
"private": true,
"version": "0.0.1",
"type": "module",
"scripts": {
"dev": "vite dev",
"build": "vite build",
"preview": "vite preview",
"prepare": "svelte-kit sync || echo ''",
"check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json",
"check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch"
},
"devDependencies": {
"@sveltejs/adapter-auto": "^6.0.0",
"@sveltejs/kit": "^2.22.0",
"@sveltejs/vite-plugin-svelte": "^6.0.0",
"fontless": "latest",
"svelte": "^5.0.0",
"svelte-check": "^4.0.0",
"typescript": "^5.0.0",
"vite": "^7.0.4"
}
}
3 changes: 3 additions & 0 deletions packages/fontless/examples/sveltekit-app/src/app.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
:root {
font-family: "Fira Sans", sans-serif;
}
13 changes: 13 additions & 0 deletions packages/fontless/examples/sveltekit-app/src/app.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
// See https://svelte.dev/docs/kit/types#app.d.ts
// for information about these interfaces
declare global {
namespace App {
// interface Error {}
// interface Locals {}
// interface PageData {}
// interface PageState {}
// interface Platform {}
}
}

export {};
11 changes: 11 additions & 0 deletions packages/fontless/examples/sveltekit-app/src/app.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
%sveltekit.head%
</head>
<body data-sveltekit-preload-data="hover">
<div style="display: contents">%sveltekit.body%</div>
</body>
</html>
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions packages/fontless/examples/sveltekit-app/src/lib/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
// place files you want to import through the `$lib` alias in this folder.
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<script lang="ts">
import "../app.css"
import favicon from '$lib/assets/favicon.svg';
import { preloads } from "fontless/runtime";

let { children } = $props();
</script>

<svelte:head>
<link rel="icon" href={favicon} />
{#each preloads as attrs}
<link {...attrs} />
{/each}
</svelte:head>

{@render children?.()}
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
<h1>Welcome to SvelteKit</h1>
<p>Visit <a href="https://svelte.dev/docs/kit">svelte.dev/docs/kit</a> to read the documentation</p>
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export const prerender = true
3 changes: 3 additions & 0 deletions packages/fontless/examples/sveltekit-app/static/robots.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# allow crawling everything by default
User-agent: *
Disallow:
18 changes: 18 additions & 0 deletions packages/fontless/examples/sveltekit-app/svelte.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import adapter from '@sveltejs/adapter-auto';
import { vitePreprocess } from '@sveltejs/vite-plugin-svelte';

/** @type {import('@sveltejs/kit').Config} */
const config = {
// Consult https://svelte.dev/docs/kit/integrations
// for more information about preprocessors
preprocess: vitePreprocess(),

kit: {
// adapter-auto only supports some environments, see https://svelte.dev/docs/kit/adapter-auto for a list.
// If your environment is not supported, or you settled on a specific environment, switch out the adapter.
// See https://svelte.dev/docs/kit/adapters for more information about adapters.
adapter: adapter()
}
};

export default config;
19 changes: 19 additions & 0 deletions packages/fontless/examples/sveltekit-app/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
{
"extends": "./.svelte-kit/tsconfig.json",
"compilerOptions": {
"allowJs": true,
"checkJs": true,
"esModuleInterop": true,
"forceConsistentCasingInFileNames": true,
"resolveJsonModule": true,
"skipLibCheck": true,
"sourceMap": true,
"strict": true,
"moduleResolution": "bundler"
}
// Path aliases are handled by https://svelte.dev/docs/kit/configuration#alias
// except $lib which is handled by https://svelte.dev/docs/kit/configuration#files
//
// To make changes to top-level options such as include and exclude, we recommend extending
// the generated config; see https://svelte.dev/docs/kit/configuration#typescript
}
15 changes: 15 additions & 0 deletions packages/fontless/examples/sveltekit-app/vite.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { sveltekit } from '@sveltejs/kit/vite';
import { defineConfig } from 'vite';
import { fontless } from "fontless"

export default defineConfig({
plugins: [
sveltekit(),
fontless({
provider: 'google',
defaults: {
preload: true,
}
})
]
});
5 changes: 4 additions & 1 deletion packages/fontless/test/e2e.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,13 @@ import { join, resolve } from 'pathe'
import { build } from 'vite'
import { describe, expect, it } from 'vitest'

const fixtures = await Array.fromAsync(fsp.glob('*', {
let fixtures = await Array.fromAsync(fsp.glob('*', {
cwd: fileURLToPath(new URL('../examples', import.meta.url)),
}))

// tested via playwright
fixtures = fixtures.filter(i => !['react-router-app', 'sveltekit-app'].includes(i))

describe.each(fixtures)('e2e %s', (fixture) => {
it('should compile', { timeout: 20_000 }, async () => {
const root = fileURLToPath(new URL(`../examples/${fixture}`, import.meta.url))
Expand Down
Loading