mirror of
https://github.com/youwen5/site.git
synced 2024-11-28 10:53:50 -08:00
feat: schema validation + article format improvements
This commit is contained in:
parent
4a11f11e54
commit
f26765dda5
15 changed files with 277 additions and 16 deletions
|
@ -1,3 +1,5 @@
|
||||||
|
#:schema ../../../post.schema.json
|
||||||
|
|
||||||
title = "A Brief Introduction to Taylor Series"
|
title = "A Brief Introduction to Taylor Series"
|
||||||
|
|
||||||
[manifest]
|
[manifest]
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
#:schema ../../../post.schema.json
|
||||||
title = "My Awesome Blog Post"
|
title = "My Awesome Blog Post"
|
||||||
|
|
||||||
[manifest]
|
[manifest]
|
||||||
|
@ -12,6 +13,6 @@ primary = ["Rust", "WebAssembly"]
|
||||||
secondary = ["Web Development", "Frontend"]
|
secondary = ["Web Development", "Frontend"]
|
||||||
|
|
||||||
[cover]
|
[cover]
|
||||||
src = "cover.jpg"
|
src = "https://machinelearningmastery.com/wp-content/uploads/2021/07/tayloreq6.png"
|
||||||
alt = "A Rust and WebAssembly logo"
|
alt = "A Rust and WebAssembly logo"
|
||||||
caption = "Rust and WebAssembly"
|
caption = "Rust and WebAssembly"
|
||||||
|
|
|
@ -51,6 +51,7 @@
|
||||||
"@types/node": "^20.12.5",
|
"@types/node": "^20.12.5",
|
||||||
"bits-ui": "^0.21.2",
|
"bits-ui": "^0.21.2",
|
||||||
"clsx": "^2.1.0",
|
"clsx": "^2.1.0",
|
||||||
|
"coredump": "link:",
|
||||||
"dayjs": "^1.11.10",
|
"dayjs": "^1.11.10",
|
||||||
"mode-watcher": "^0.3.0",
|
"mode-watcher": "^0.3.0",
|
||||||
"rehype-katex": "^7.0.0",
|
"rehype-katex": "^7.0.0",
|
||||||
|
|
|
@ -32,6 +32,9 @@ dependencies:
|
||||||
clsx:
|
clsx:
|
||||||
specifier: ^2.1.0
|
specifier: ^2.1.0
|
||||||
version: 2.1.0
|
version: 2.1.0
|
||||||
|
coredump:
|
||||||
|
specifier: 'link:'
|
||||||
|
version: 'link:'
|
||||||
dayjs:
|
dayjs:
|
||||||
specifier: ^1.11.10
|
specifier: ^1.11.10
|
||||||
version: 1.11.10
|
version: 1.11.10
|
||||||
|
|
69
post.schema.json
Normal file
69
post.schema.json
Normal file
|
@ -0,0 +1,69 @@
|
||||||
|
{
|
||||||
|
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"title": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"manifest": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"date": {
|
||||||
|
"type": "string",
|
||||||
|
"format": "date-time"
|
||||||
|
},
|
||||||
|
"blurb": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"description": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"type": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"authors": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"tags": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"primary": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"secondary": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": ["primary", "secondary"]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": ["date", "blurb", "description", "type", "authors", "tags"]
|
||||||
|
},
|
||||||
|
"cover": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"src": {
|
||||||
|
"type": "string",
|
||||||
|
"format": "uri"
|
||||||
|
},
|
||||||
|
"alt": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"caption": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": ["src", "alt", "caption"]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": ["title", "manifest", "cover"]
|
||||||
|
}
|
|
@ -1,5 +1,5 @@
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { ChevronRight } from 'svelte-radix';
|
import * as Breadcrumb from '../ui/breadcrumb';
|
||||||
|
|
||||||
export let slug: string;
|
export let slug: string;
|
||||||
export let title: string;
|
export let title: string;
|
||||||
|
@ -7,14 +7,18 @@
|
||||||
$: trail = slug.split('/').slice(0, slug.split('/').length - 1);
|
$: trail = slug.split('/').slice(0, slug.split('/').length - 1);
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="mb-4 flex items-center space-x-1 text-sm text-muted-foreground">
|
<Breadcrumb.Root class="mb-4">
|
||||||
<a class="overflow-hidden text-ellipsis whitespace-nowrap hover:underline" href="/blog"
|
<Breadcrumb.List>
|
||||||
>The Coredump</a
|
<Breadcrumb.Item><Breadcrumb.Link href="/blog">The Coredump</Breadcrumb.Link></Breadcrumb.Item>
|
||||||
>
|
<Breadcrumb.Separator />
|
||||||
<ChevronRight class="h-4 w-4" />
|
|
||||||
{#each trail as crumb, i}
|
{#each trail as crumb, i}
|
||||||
<div class="text-muted-foreground">{crumb}</div>
|
<Breadcrumb.Item>{crumb}</Breadcrumb.Item>
|
||||||
<ChevronRight class="h-4 w-4" />
|
<Breadcrumb.Separator />
|
||||||
{/each}
|
{/each}
|
||||||
<div class="font-medium text-foreground">{title}</div>
|
<Breadcrumb.Item>
|
||||||
</div>
|
<Breadcrumb.Page>
|
||||||
|
{title}
|
||||||
|
</Breadcrumb.Page>
|
||||||
|
</Breadcrumb.Item>
|
||||||
|
</Breadcrumb.List>
|
||||||
|
</Breadcrumb.Root>
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import * as Card from '$lib/components/ui/card';
|
import * as Card from '$lib/components/ui/card';
|
||||||
import Placeholder from '$lib/assets/img/galaxy.jpg';
|
|
||||||
import Button from '../ui/button/button.svelte';
|
import Button from '../ui/button/button.svelte';
|
||||||
import PostMetadata from './PostMetadata.svelte';
|
import PostMetadata from './PostMetadata.svelte';
|
||||||
|
|
||||||
|
@ -26,8 +25,8 @@
|
||||||
</Card.Header>
|
</Card.Header>
|
||||||
<Card.Content class="grid grid-cols-3 gap-6">
|
<Card.Content class="grid grid-cols-3 gap-6">
|
||||||
<img
|
<img
|
||||||
src={Placeholder}
|
src={doc.metadata.cover.src}
|
||||||
alt="Placeholder"
|
alt={doc.metadata.cover.alt}
|
||||||
class="col-span-3 md:col-span-1 rounded-2xl shadow-md"
|
class="col-span-3 md:col-span-1 rounded-2xl shadow-md"
|
||||||
/>
|
/>
|
||||||
<div class="flex flex-col justify-around col-span-3 md:col-span-2 gap-4">
|
<div class="flex flex-col justify-around col-span-3 md:col-span-2 gap-4">
|
||||||
|
|
24
src/lib/components/ui/breadcrumb/breadcrumb-ellipsis.svelte
Normal file
24
src/lib/components/ui/breadcrumb/breadcrumb-ellipsis.svelte
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
<script lang="ts">
|
||||||
|
import type { HTMLAttributes } from "svelte/elements";
|
||||||
|
import DotsHorizontal from "svelte-radix/DotsHorizontal.svelte";
|
||||||
|
import { cn } from "$lib/utils.js";
|
||||||
|
|
||||||
|
type $$Props = HTMLAttributes<HTMLSpanElement> & {
|
||||||
|
el?: HTMLSpanElement;
|
||||||
|
};
|
||||||
|
|
||||||
|
export let el: $$Props["el"] = undefined;
|
||||||
|
let className: $$Props["class"] = undefined;
|
||||||
|
export { className as class };
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<span
|
||||||
|
bind:this={el}
|
||||||
|
role="presentation"
|
||||||
|
aria-hidden="true"
|
||||||
|
class={cn("flex h-9 w-9 items-center justify-center", className)}
|
||||||
|
{...$$restProps}
|
||||||
|
>
|
||||||
|
<DotsHorizontal class="h-4 w-4 outline-none" tabindex="-1" />
|
||||||
|
<span class="sr-only">More</span>
|
||||||
|
</span>
|
16
src/lib/components/ui/breadcrumb/breadcrumb-item.svelte
Normal file
16
src/lib/components/ui/breadcrumb/breadcrumb-item.svelte
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
<script lang="ts">
|
||||||
|
import type { HTMLLiAttributes } from "svelte/elements";
|
||||||
|
import { cn } from "$lib/utils.js";
|
||||||
|
|
||||||
|
type $$Props = HTMLLiAttributes & {
|
||||||
|
el?: HTMLLIElement;
|
||||||
|
};
|
||||||
|
|
||||||
|
export let el: $$Props["el"] = undefined;
|
||||||
|
let className: $$Props["class"] = undefined;
|
||||||
|
export { className as class };
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<li bind:this={el} class={cn("inline-flex items-center gap-1.5", className)}>
|
||||||
|
<slot />
|
||||||
|
</li>
|
31
src/lib/components/ui/breadcrumb/breadcrumb-link.svelte
Normal file
31
src/lib/components/ui/breadcrumb/breadcrumb-link.svelte
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
<script lang="ts">
|
||||||
|
import type { HTMLAnchorAttributes } from "svelte/elements";
|
||||||
|
import { cn } from "$lib/utils.js";
|
||||||
|
|
||||||
|
type $$Props = HTMLAnchorAttributes & {
|
||||||
|
el?: HTMLAnchorElement;
|
||||||
|
asChild?: boolean;
|
||||||
|
};
|
||||||
|
|
||||||
|
export let href: $$Props["href"] = undefined;
|
||||||
|
export let el: $$Props["el"] = undefined;
|
||||||
|
export let asChild: $$Props["asChild"] = false;
|
||||||
|
let className: $$Props["class"] = undefined;
|
||||||
|
export { className as class };
|
||||||
|
|
||||||
|
let attrs: Record<string, unknown>;
|
||||||
|
|
||||||
|
$: attrs = {
|
||||||
|
class: cn("transition-colors hover:text-foreground", className),
|
||||||
|
href,
|
||||||
|
...$$restProps,
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
{#if asChild}
|
||||||
|
<slot {attrs} />
|
||||||
|
{:else}
|
||||||
|
<a bind:this={el} {...attrs} {href}>
|
||||||
|
<slot {attrs} />
|
||||||
|
</a>
|
||||||
|
{/if}
|
23
src/lib/components/ui/breadcrumb/breadcrumb-list.svelte
Normal file
23
src/lib/components/ui/breadcrumb/breadcrumb-list.svelte
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
<script lang="ts">
|
||||||
|
import type { HTMLOlAttributes } from "svelte/elements";
|
||||||
|
import { cn } from "$lib/utils.js";
|
||||||
|
|
||||||
|
type $$Props = HTMLOlAttributes & {
|
||||||
|
el?: HTMLOListElement;
|
||||||
|
};
|
||||||
|
|
||||||
|
export let el: $$Props["el"] = undefined;
|
||||||
|
let className: $$Props["class"] = undefined;
|
||||||
|
export { className as class };
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<ol
|
||||||
|
bind:this={el}
|
||||||
|
class={cn(
|
||||||
|
"flex flex-wrap items-center gap-1.5 break-words text-sm text-muted-foreground sm:gap-2.5",
|
||||||
|
className
|
||||||
|
)}
|
||||||
|
{...$$restProps}
|
||||||
|
>
|
||||||
|
<slot />
|
||||||
|
</ol>
|
23
src/lib/components/ui/breadcrumb/breadcrumb-page.svelte
Normal file
23
src/lib/components/ui/breadcrumb/breadcrumb-page.svelte
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
<script lang="ts">
|
||||||
|
import type { HTMLAttributes } from "svelte/elements";
|
||||||
|
import { cn } from "$lib/utils.js";
|
||||||
|
|
||||||
|
type $$Props = HTMLAttributes<HTMLSpanElement> & {
|
||||||
|
el?: HTMLSpanElement;
|
||||||
|
};
|
||||||
|
|
||||||
|
export let el: $$Props["el"] = undefined;
|
||||||
|
export let className: $$Props["class"] = undefined;
|
||||||
|
export { className as class };
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<span
|
||||||
|
bind:this={el}
|
||||||
|
role="link"
|
||||||
|
aria-disabled="true"
|
||||||
|
aria-current="page"
|
||||||
|
class={cn("font-normal text-foreground", className)}
|
||||||
|
{...$$restProps}
|
||||||
|
>
|
||||||
|
<slot />
|
||||||
|
</span>
|
25
src/lib/components/ui/breadcrumb/breadcrumb-separator.svelte
Normal file
25
src/lib/components/ui/breadcrumb/breadcrumb-separator.svelte
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
<script lang="ts">
|
||||||
|
import type { HTMLLiAttributes } from "svelte/elements";
|
||||||
|
import ChevronRight from "svelte-radix/ChevronRight.svelte";
|
||||||
|
import { cn } from "$lib/utils.js";
|
||||||
|
|
||||||
|
type $$Props = HTMLLiAttributes & {
|
||||||
|
el?: HTMLLIElement;
|
||||||
|
};
|
||||||
|
|
||||||
|
export let el: $$Props["el"] = undefined;
|
||||||
|
let className: $$Props["class"] = undefined;
|
||||||
|
export { className as class };
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<li
|
||||||
|
role="presentation"
|
||||||
|
aria-hidden="true"
|
||||||
|
class={cn("[&>svg]:size-3.5", className)}
|
||||||
|
bind:this={el}
|
||||||
|
{...$$restProps}
|
||||||
|
>
|
||||||
|
<slot>
|
||||||
|
<ChevronRight tabindex="-1" />
|
||||||
|
</slot>
|
||||||
|
</li>
|
15
src/lib/components/ui/breadcrumb/breadcrumb.svelte
Normal file
15
src/lib/components/ui/breadcrumb/breadcrumb.svelte
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
<script lang="ts">
|
||||||
|
import type { HTMLAttributes } from "svelte/elements";
|
||||||
|
|
||||||
|
type $$Props = HTMLAttributes<HTMLElement> & {
|
||||||
|
el?: HTMLElement;
|
||||||
|
};
|
||||||
|
|
||||||
|
export let el: $$Props["el"] = undefined;
|
||||||
|
let className: $$Props["class"] = undefined;
|
||||||
|
export { className as class };
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<nav class={className} bind:this={el} aria-label="breadcrumb" {...$$restProps}>
|
||||||
|
<slot />
|
||||||
|
</nav>
|
25
src/lib/components/ui/breadcrumb/index.ts
Normal file
25
src/lib/components/ui/breadcrumb/index.ts
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
import Root from "./breadcrumb.svelte";
|
||||||
|
import Ellipsis from "./breadcrumb-ellipsis.svelte";
|
||||||
|
import Item from "./breadcrumb-item.svelte";
|
||||||
|
import Separator from "./breadcrumb-separator.svelte";
|
||||||
|
import Link from "./breadcrumb-link.svelte";
|
||||||
|
import List from "./breadcrumb-list.svelte";
|
||||||
|
import Page from "./breadcrumb-page.svelte";
|
||||||
|
|
||||||
|
export {
|
||||||
|
Root,
|
||||||
|
Ellipsis,
|
||||||
|
Item,
|
||||||
|
Separator,
|
||||||
|
Link,
|
||||||
|
List,
|
||||||
|
Page,
|
||||||
|
//
|
||||||
|
Root as Breadcrumb,
|
||||||
|
Ellipsis as BreadcrumbEllipsis,
|
||||||
|
Item as BreadcrumbItem,
|
||||||
|
Separator as BreadcrumbSeparator,
|
||||||
|
Link as BreadcrumbLink,
|
||||||
|
List as BreadcrumbList,
|
||||||
|
Page as BreadcrumbPage,
|
||||||
|
};
|
Loading…
Reference in a new issue