mirror of
https://github.com/danbulant/design
synced 2026-05-23 06:09:04 +00:00
update sveltekit
This commit is contained in:
parent
14de7c0332
commit
6503b9978b
24 changed files with 552 additions and 422 deletions
|
|
@ -2,14 +2,14 @@
|
||||||
"name": "design",
|
"name": "design",
|
||||||
"version": "0.0.1",
|
"version": "0.0.1",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "svelte-kit dev",
|
"dev": "vite dev",
|
||||||
"build": "svelte-kit build",
|
"build": "svelte-kit build",
|
||||||
"package": "svelte-kit package",
|
"package": "svelte-kit package",
|
||||||
"preview": "svelte-kit preview"
|
"preview": "svelte-kit preview"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@sveltejs/adapter-static": "1.0.0-next.28",
|
"@sveltejs/adapter-static": "1.0.0-next.28",
|
||||||
"@sveltejs/kit": "1.0.0-next.291",
|
"@sveltejs/kit": "1.0.0-next.431",
|
||||||
"mdsvex": "0.10.5",
|
"mdsvex": "0.10.5",
|
||||||
"svelte": "3.46.4",
|
"svelte": "3.46.4",
|
||||||
"vite-plugin-windicss": "^1.8.6"
|
"vite-plugin-windicss": "^1.8.6"
|
||||||
|
|
@ -28,6 +28,7 @@
|
||||||
"remark-parse": "10.0.1",
|
"remark-parse": "10.0.1",
|
||||||
"remark-twemoji": "0.1.1",
|
"remark-twemoji": "0.1.1",
|
||||||
"twemoji": "13.1.0",
|
"twemoji": "13.1.0",
|
||||||
|
"vite": "^3.0.9",
|
||||||
"xterm": "4.18.0"
|
"xterm": "4.18.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
769
pnpm-lock.yaml
769
pnpm-lock.yaml
File diff suppressed because it is too large
Load diff
10
src/app.html
10
src/app.html
|
|
@ -3,13 +3,13 @@
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8" />
|
<meta charset="utf-8" />
|
||||||
<script data-goatcounter="https://danbulant.goatcounter.com/count" async src="//gc.zgo.at/count.js"></script>
|
<script data-goatcounter="https://danbulant.goatcounter.com/count" async src="//gc.zgo.at/count.js"></script>
|
||||||
<link rel="icon" href="%svelte.assets%/favicon.png" />
|
<link rel="icon" href="%sveltekit.assets%/favicon.png" />
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||||
<link rel="stylesheet" href="%svelte.assets%/prism/dark.css" />
|
<link rel="stylesheet" href="%sveltekit.assets%/prism/dark.css" />
|
||||||
<link rel="stylesheet" href="%svelte.assets%/global.css" />
|
<link rel="stylesheet" href="%sveltekit.assets%/global.css" />
|
||||||
%svelte.head%
|
%sveltekit.head%
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div id="svelte">%svelte.body%</div>
|
<div id="svelte">%sveltekit.body%</div>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,8 @@
|
||||||
import { DateTime } from "luxon";
|
import { DateTime } from "luxon";
|
||||||
|
|
||||||
export var value;
|
export var value;
|
||||||
|
var dt = DateTime.fromISO(value);
|
||||||
|
$: dt = DateTime.fromISO(value);
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<code title={DateTime.fromISO(value).toRelative()}>{value}</code>
|
<time datetime={dt.toISOWeekDate()} title={dt.toRelative()}>{dt.toLocaleString()}</time>
|
||||||
15
src/lib/components/posts/callout.svelte
Normal file
15
src/lib/components/posts/callout.svelte
Normal file
|
|
@ -0,0 +1,15 @@
|
||||||
|
<script>
|
||||||
|
export var color;
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<!-- A simple callout with header and slot body. Header background colored according to color, and the whole callout has a left border colored as well. -->
|
||||||
|
<div class="w-full rounded border-l border-l-4 my-2" style="border-left-color: {color}">
|
||||||
|
<div class="rounded-tr-lg p-4" style="background-color: {color}40">
|
||||||
|
<h1 class="text-big text-white p-0 m-0">
|
||||||
|
<slot name="title"/>
|
||||||
|
</h1>
|
||||||
|
</div>
|
||||||
|
<div class="rounded-br-lg p-4 bg-gray-500/10">
|
||||||
|
<slot />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
@ -1,38 +1,28 @@
|
||||||
<script context="module">
|
|
||||||
/** @type {import('@sveltejs/kit').Load} */
|
|
||||||
export async function load({ error, status }) {
|
|
||||||
let response;
|
|
||||||
try {
|
|
||||||
response = await fetch("/api/posts.json");
|
|
||||||
} catch(e) {}
|
|
||||||
return {
|
|
||||||
props: {
|
|
||||||
status,
|
|
||||||
error,
|
|
||||||
posts: response && response.ok && (await response.json())
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
import { page } from '$app/stores';
|
||||||
|
import { dev } from '$app/env';
|
||||||
import Button from "$lib/components/button.svelte";
|
import Button from "$lib/components/button.svelte";
|
||||||
import HeroPost from "$lib/components/heroPost.svelte";
|
import HeroPost from "$lib/components/heroPost.svelte";
|
||||||
import Post from "$lib/components/post.svelte";
|
import Post from "$lib/components/post.svelte";
|
||||||
|
|
||||||
export let status;
|
|
||||||
export let error;
|
|
||||||
export let posts;
|
|
||||||
let currentHover;
|
let currentHover;
|
||||||
|
|
||||||
console.error(error);
|
console.error($page.error);
|
||||||
|
|
||||||
|
function loadPosts() {
|
||||||
|
let posts = fetch("/api/posts.json").then(t => t.json()).catch(t => []);
|
||||||
|
return posts;
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<h1 class="text-center">
|
<h1 class="text-center">
|
||||||
{#if status == 404}
|
{#if $page.status == 404}
|
||||||
404 - Page Not Found
|
404 - Page Not Found
|
||||||
{:else}
|
{:else}
|
||||||
{status} - {error.message}
|
{$page.status} - {$page.error.message}
|
||||||
|
{#if dev}
|
||||||
|
<pre><code>{$page.error.stack}</code></pre>
|
||||||
|
{/if}
|
||||||
{/if}
|
{/if}
|
||||||
</h1>
|
</h1>
|
||||||
|
|
||||||
|
|
@ -43,6 +33,8 @@
|
||||||
<Button href="/">Go to my home page</Button>
|
<Button href="/">Go to my home page</Button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
{#await loadPosts()}
|
||||||
|
{:then posts}
|
||||||
{#if posts && posts.length > 0}
|
{#if posts && posts.length > 0}
|
||||||
<div class="my-4 separator text-big">OR</div>
|
<div class="my-4 separator text-big">OR</div>
|
||||||
|
|
||||||
|
|
@ -59,6 +51,9 @@
|
||||||
{/each}
|
{/each}
|
||||||
</main>
|
</main>
|
||||||
{/if}
|
{/if}
|
||||||
|
{:catch error}
|
||||||
|
<!-- Couldn't load -->
|
||||||
|
{/await}
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
.flex {
|
.flex {
|
||||||
7
src/routes/+layout.js
Normal file
7
src/routes/+layout.js
Normal file
|
|
@ -0,0 +1,7 @@
|
||||||
|
|
||||||
|
/** @type {import('./$types').PageLoad} */
|
||||||
|
export const load = async ({ url }) => {
|
||||||
|
return {
|
||||||
|
url: url.pathname
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
@ -1,20 +1,16 @@
|
||||||
<script context="module">
|
|
||||||
export const load = async ({ url }) => ({ props: { url } });
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import Navbar from "$lib/components/navbar.svelte";
|
import Navbar from "$lib/components/navbar.svelte";
|
||||||
import PageTransition from "$lib/components/pageTransition.svelte";
|
import PageTransition from "$lib/components/pageTransition.svelte";
|
||||||
import "virtual:windi.css";
|
import "virtual:windi.css";
|
||||||
import { browser } from "$app/env";
|
import { browser } from "$app/env";
|
||||||
if (browser) import("virtual:windi-devtools");
|
if (browser) import("virtual:windi-devtools");
|
||||||
export let url;
|
export let data;
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<Navbar />
|
<Navbar />
|
||||||
|
|
||||||
<div class="overflow-x-hidden w-100vw">
|
<div class="overflow-x-hidden w-100vw">
|
||||||
<PageTransition {url}>
|
<PageTransition url={data.url}>
|
||||||
<slot />
|
<slot />
|
||||||
</PageTransition>
|
</PageTransition>
|
||||||
</div>
|
</div>
|
||||||
7
src/routes/+page.js
Normal file
7
src/routes/+page.js
Normal file
|
|
@ -0,0 +1,7 @@
|
||||||
|
|
||||||
|
/** @type {import('./$types').PageLoad} */
|
||||||
|
export async function load({ fetch }) {
|
||||||
|
return {
|
||||||
|
posts: await fetch("/api/posts.json").then(t => t.json())
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
@ -1,16 +1,3 @@
|
||||||
<script context="module">
|
|
||||||
/** @type {import('./index').Load} */
|
|
||||||
export async function load({ params, fetch, session, stuff }) {
|
|
||||||
const response = await fetch("/api/posts.json");
|
|
||||||
|
|
||||||
return {
|
|
||||||
props: {
|
|
||||||
posts: response.ok && (await response.json())
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import Bottombar from "$lib/components/bottombar.svelte";
|
import Bottombar from "$lib/components/bottombar.svelte";
|
||||||
import Button from "$lib/components/button.svelte";
|
import Button from "$lib/components/button.svelte";
|
||||||
|
|
@ -26,7 +13,9 @@
|
||||||
/** @type {null | "websites" | "applications" | "bots"} */
|
/** @type {null | "websites" | "applications" | "bots"} */
|
||||||
var appTypeHover = null;
|
var appTypeHover = null;
|
||||||
|
|
||||||
export var posts;
|
export var data;
|
||||||
|
var posts = data.posts;
|
||||||
|
$: posts = data.posts;
|
||||||
$: if(typeof window !== "undefined") console.log(posts);
|
$: if(typeof window !== "undefined") console.log(posts);
|
||||||
|
|
||||||
var selectedPost = posts && posts.find(t => !t.categories.includes("experiment"));
|
var selectedPost = posts && posts.find(t => !t.categories.includes("experiment"));
|
||||||
|
|
@ -1,14 +1,14 @@
|
||||||
/**
|
/**
|
||||||
* @type {import("@sveltejs/kit").RequestHandler}
|
* @type {import("@sveltejs/kit").RequestHandler}
|
||||||
*/
|
*/
|
||||||
export async function get(req) {
|
export async function GET(req) {
|
||||||
const allPostFiles = import.meta.glob('../posts/**/*.md');
|
const allPostFiles = import.meta.glob('../../posts/**/*.md');
|
||||||
|
|
||||||
const allPosts = await Promise.all(
|
const allPosts = await Promise.all(
|
||||||
Object.entries(allPostFiles).map(async ([path, resolver]) => {
|
Object.entries(allPostFiles).map(async ([path, resolver]) => {
|
||||||
const { metadata } = await resolver();
|
const { metadata } = await resolver();
|
||||||
let postPath = path.slice(2, -3);
|
let postPath = path.slice(2, -3);
|
||||||
if(postPath.endsWith('/index')) postPath = postPath.slice(0, -6);
|
if(postPath.endsWith('/+page')) postPath = postPath.slice(0, -6);
|
||||||
return {
|
return {
|
||||||
...metadata,
|
...metadata,
|
||||||
path: postPath,
|
path: postPath,
|
||||||
|
|
@ -20,7 +20,9 @@ export async function get(req) {
|
||||||
return new Date(b.date) - new Date(a.date)
|
return new Date(b.date) - new Date(a.date)
|
||||||
});
|
});
|
||||||
|
|
||||||
return {
|
return new Response(JSON.stringify(allPosts.filter(t => new Date(t.date) < Date.now())), {
|
||||||
body: allPosts.filter(t => new Date(t.date) < Date.now())
|
headers: {
|
||||||
};
|
'Content-Type': 'application/json'
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
9
src/routes/posts/+page.js
Normal file
9
src/routes/posts/+page.js
Normal file
|
|
@ -0,0 +1,9 @@
|
||||||
|
|
||||||
|
/** @type {import('./$types').PageLoad} */
|
||||||
|
export async function load({ fetch }) {
|
||||||
|
const response = await fetch("/api/posts.json");
|
||||||
|
|
||||||
|
return {
|
||||||
|
posts: response.ok && (await response.json())
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
@ -1,16 +1,3 @@
|
||||||
<script context="module">
|
|
||||||
/** @type {import('./index').Load} */
|
|
||||||
export async function load({ params, fetch, session, stuff }) {
|
|
||||||
const response = await fetch("/api/posts.json");
|
|
||||||
|
|
||||||
return {
|
|
||||||
props: {
|
|
||||||
posts: response.ok && (await response.json())
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import HeroPost from "$lib/components/heroPost.svelte";
|
import HeroPost from "$lib/components/heroPost.svelte";
|
||||||
import Post from "$lib/components/post.svelte";
|
import Post from "$lib/components/post.svelte";
|
||||||
|
|
@ -18,7 +5,9 @@
|
||||||
import { flip } from 'svelte/animate';
|
import { flip } from 'svelte/animate';
|
||||||
|
|
||||||
var currentHover = null;
|
var currentHover = null;
|
||||||
export var posts;
|
export var data;
|
||||||
|
var posts = data.posts;
|
||||||
|
$: posts = data.posts;
|
||||||
|
|
||||||
var tags = posts && posts.map(t => t.categories).flat().filter((t, i, a) => a.indexOf(t) == i).sort();
|
var tags = posts && posts.map(t => t.categories).flat().filter((t, i, a) => a.indexOf(t) == i).sort();
|
||||||
|
|
||||||
|
|
@ -15,8 +15,15 @@ description: So I added blog to my personal home page.
|
||||||
import ExampleWrapper from "$lib/components/posts/exampleWrapper.svelte";
|
import ExampleWrapper from "$lib/components/posts/exampleWrapper.svelte";
|
||||||
import SimpleExample from "./_comp/simpleExample.svelte";
|
import SimpleExample from "./_comp/simpleExample.svelte";
|
||||||
import BidiExample from "./_comp/bidiExample.svelte";
|
import BidiExample from "./_comp/bidiExample.svelte";
|
||||||
|
import Callout from "$lib/components/posts/callout.svelte";
|
||||||
|
import Date from "$lib/components/Date.svelte";
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
<Callout color="#139ab4">
|
||||||
|
<span slot="title">Update <Date value="2022-08-24" /></span>
|
||||||
|
Sveltekit's routing was changed, the article was updated to accomodate that.
|
||||||
|
</Callout>
|
||||||
|
|
||||||
I'm mainly a web developer, yet for quite a while, my personal site looked like this:
|
I'm mainly a web developer, yet for quite a while, my personal site looked like this:
|
||||||
|
|
||||||
<Image src="/posts/writing-personal-home-page/2020-website.png">
|
<Image src="/posts/writing-personal-home-page/2020-website.png">
|
||||||
|
|
@ -119,14 +126,15 @@ Essentially:
|
||||||
|
|
||||||
*For full description, see [Svelte Kit's documentation](https://kit.svelte.dev/docs/routing)*
|
*For full description, see [Svelte Kit's documentation](https://kit.svelte.dev/docs/routing)*
|
||||||
|
|
||||||
Essentially, **each file in `src/routes` creates a new route**.
|
Essentially, **each folder in `src/routes` creates a new route**.
|
||||||
|
All special files in sveltekit start with a `+` - `+page.svelte` is the page visible to user
|
||||||
|
|
||||||
`/index.svelte` is the root page
|
`/+page.svelte` is the root page
|
||||||
`/something.svelte` will be accessible as `/something`
|
`/something/+page.svelte` will be accessible as `/something`
|
||||||
|
|
||||||
`js` files are used to create API endpoints, which are run server side. Those can do some action (like user login/registration), or retrieve some data (like a list of blog posts, as I'll demonstrate later).
|
`js` files are used to create API endpoints, which are run server side. Those can do some action (like user login/registration), or retrieve some data (like a list of blog posts, as I'll demonstrate later).
|
||||||
|
|
||||||
`md` files are compiled/transpiled into `svelte` files internally, and behave nearly identical.
|
`md` files are compiled/transpiled into `svelte` files internally, and behave nearly identical. Note this only works when you set up mdsvex with sveltekit (sveltekit doesn't do it on it's own).
|
||||||
|
|
||||||
## Writing blog posts
|
## Writing blog posts
|
||||||
|
|
||||||
|
|
@ -208,17 +216,17 @@ Hello there, **markdown**
|
||||||
You can then write YAML metadata (YAML is basically simplified JSON. If you're unsure, any JSON is valid YAML, so you can write it in JSON as well). For example, this page stores it's title, description and thumbnail links there.
|
You can then write YAML metadata (YAML is basically simplified JSON. If you're unsure, any JSON is valid YAML, so you can write it in JSON as well). For example, this page stores it's title, description and thumbnail links there.
|
||||||
|
|
||||||
When you import the file elsewhere, you can use that metadata to for example show a preview of the post (as is the case here).
|
When you import the file elsewhere, you can use that metadata to for example show a preview of the post (as is the case here).
|
||||||
A simple API route can be used to get a list of posts along with their metadata, for example if all the posts are in `/posts` route, you can use this as `/api/posts.json.js`:
|
A simple API route can be used to get a list of posts along with their metadata, for example if all the posts are in `/posts` route, you can use this as `/api/posts.json/+server.js`:
|
||||||
|
|
||||||
```js
|
```js
|
||||||
export async function get() {
|
export async function GET() {
|
||||||
const allPostFiles = import.meta.glob('../posts/**/*.md');
|
const allPostFiles = import.meta.glob('../../posts/**/*.md');
|
||||||
|
|
||||||
const allPosts = await Promise.all(
|
const allPosts = await Promise.all(
|
||||||
Object.entries(allPostFiles).map(async ([path, resolver]) => {
|
Object.entries(allPostFiles).map(async ([path, resolver]) => {
|
||||||
const { metadata } = await resolver();
|
const { metadata } = await resolver();
|
||||||
let postPath = path.slice(2, -3);
|
let postPath = path.slice(2, -3);
|
||||||
if(postPath.endsWith('/index')) postPath = postPath.slice(0, -6);
|
if(postPath.endsWith('/+page')) postPath = postPath.slice(0, -6);
|
||||||
return {
|
return {
|
||||||
...metadata,
|
...metadata,
|
||||||
path: postPath,
|
path: postPath,
|
||||||
|
|
@ -244,7 +252,7 @@ this will get all the metadata about posts and return it as a JSON response, ord
|
||||||
[{
|
[{
|
||||||
"title": "An example blog post",
|
"title": "An example blog post",
|
||||||
"date": "2020-03-05",
|
"date": "2020-03-05",
|
||||||
"path": "/posts/example.md"
|
"path": "/posts/example"
|
||||||
}]
|
}]
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
@ -2,6 +2,6 @@
|
||||||
var name = "world";
|
var name = "world";
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<input type=text bind:value={name}>
|
<input type=text bind:value={name} class="text-black">
|
||||||
|
|
||||||
<input type=text bind:value={name}>
|
<input type=text bind:value={name} class="text-black">
|
||||||
|
|
@ -6,7 +6,7 @@
|
||||||
|
|
||||||
<h1>Hello {funny[name] || name}</h1>
|
<h1>Hello {funny[name] || name}</h1>
|
||||||
|
|
||||||
<input type=text bind:value={name}>
|
<input type=text class="text-black" bind:value={name}>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
h1 {
|
h1 {
|
||||||
|
|
|
||||||
|
|
@ -7,20 +7,13 @@ import remarkTwemoji from 'remark-twemoji';
|
||||||
import remarkGfm from 'remark-gfm';
|
import remarkGfm from 'remark-gfm';
|
||||||
import remarkExtendedTable from 'remark-extended-table';
|
import remarkExtendedTable from 'remark-extended-table';
|
||||||
import rehypeKatexSvelte from "rehype-katex-svelte";
|
import rehypeKatexSvelte from "rehype-katex-svelte";
|
||||||
import WindiCSS from 'vite-plugin-windicss';
|
|
||||||
|
|
||||||
/** @type {import('@sveltejs/kit').Config} */
|
/** @type {import('@sveltejs/kit').Config} */
|
||||||
const config = {
|
const config = {
|
||||||
kit: {
|
kit: {
|
||||||
adapter: adapter({
|
adapter: adapter({
|
||||||
precompress: true
|
precompress: true
|
||||||
}),
|
})
|
||||||
vite: {
|
|
||||||
clearScreen: false,
|
|
||||||
plugins: [
|
|
||||||
WindiCSS()
|
|
||||||
]
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
extensions: ['.svelte', '.md'],
|
extensions: ['.svelte', '.md'],
|
||||||
|
|
||||||
|
|
|
||||||
10
vite.config.js
Normal file
10
vite.config.js
Normal file
|
|
@ -0,0 +1,10 @@
|
||||||
|
import { sveltekit } from '@sveltejs/kit/vite';
|
||||||
|
import WindiCSS from 'vite-plugin-windicss';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
clearScreen: false,
|
||||||
|
plugins: [
|
||||||
|
WindiCSS(),
|
||||||
|
sveltekit()
|
||||||
|
]
|
||||||
|
}
|
||||||
Loading…
Reference in a new issue