This commit is contained in:
cupcakearmy 2021-08-21 11:12:25 +02:00
parent 0f8c58d182
commit 170d61dd96
No known key found for this signature in database
GPG Key ID: D28129AE5654D9D9
12 changed files with 172 additions and 44 deletions

View File

@ -36,7 +36,7 @@ export type Page = {
status: string status: string
} }
export const BaseAttributes = gql` export const BaseAttributes = `
id id
slug slug
status status
@ -44,6 +44,27 @@ export const BaseAttributes = gql`
content content
` `
export interface Post extends Page {
date: string
modified: string
post: {
featured: MediaItem
}
}
export const PostFragment = gql`
fragment PostFragment on Post {
${BaseAttributes}
date
modified
post {
featured {
...MediaItemFragment
}
}
}
`
export interface Work extends Page { export interface Work extends Page {
work: { work: {
date: string date: string

View File

@ -1,11 +1,12 @@
<script> <script lang="ts">
import dj from 'dayjs' import dj from 'dayjs'
import { readingTimeInMinutes } from '../lib/readingTime' import type { Post } from '$lib/api'
import { readingTimeInMinutes } from '$lib/utils'
export let post export let post: Post
export let full = false export let full = false
function format(date) { function format(date: string) {
return dj(date).format('MMM D, YYYY') return dj(date).format('MMM D, YYYY')
} }
@ -13,6 +14,16 @@
$: modified = format(post.modified) $: modified = format(post.modified)
</script> </script>
<div class="attributes">
<div>
{created}
{#if full && created !== modified}<br /> <small>Last update: {modified}</small>{/if}
</div>
{#if post.content}
<div>~ {readingTimeInMinutes(post.content)} min</div>
{/if}
</div>
<style> <style>
.attributes { .attributes {
display: flex; display: flex;
@ -21,11 +32,3 @@
margin-top: -0.125em; margin-top: -0.125em;
} }
</style> </style>
<div class="attributes">
<div>
{created}
{#if full && created !== modified}<br /> <small>Last update: {modified}</small>{/if}
</div>
<div>~ {readingTimeInMinutes(post.content)} min</div>
</div>

View File

@ -1,10 +1,22 @@
<script> <script lang="ts">
import type { Post } from '$lib/api'
import ImageFrame from '../components/ImageFrame.svelte' import ImageFrame from '../components/ImageFrame.svelte'
import PostAttributes from '../components/PostAttributes.svelte' import PostAttributes from '../components/PostAttributes.svelte'
export let post export let post: Post
</script> </script>
<a href={`blog/${post.slug}`} class:without={!post.post.featured}>
{#if post.post.featured}
<ImageFrame src={post.post.featured.sourceUrl} alt={post.post.featured.altText} />
{/if}
<PostAttributes {post} />
<h2>
{@html post.title}
</h2>
</a>
<style> <style>
a { a {
display: block; display: block;
@ -41,13 +53,3 @@
transform: translateX(-5%); transform: translateX(-5%);
} }
</style> </style>
<a href={`blog/${post.slug}`} class:without={!post.featured}>
{#if post.featured}
<ImageFrame src={post.featured.url} alt={post.featured.description} />
{/if}
<PostAttributes {post} />
<h2>
{@html post.title}
</h2>
</a>

5
src/lib/utils.ts Normal file
View File

@ -0,0 +1,5 @@
export function readingTimeInMinutes(text: string, options: { wpm?: number } = {}): number {
const cleaned = text.replace(/(<.*?>)|(\\n)|(&#\d*?;)/g, '')
const words = cleaned.split(' ').length
return Math.round(words / (options.wpm ?? 200))
}

View File

@ -7,6 +7,8 @@ import {
MediaItem, MediaItem,
MediaItemFragment, MediaItemFragment,
Page, Page,
Post,
PostFragment,
Project, Project,
ProjectFragment, ProjectFragment,
WorkFragment, WorkFragment,
@ -22,7 +24,7 @@ export const get: RequestHandler = async (args) => {
if (all) { if (all) {
const data = await Call<{ pages: { nodes: Page[] } }>(gql` const data = await Call<{ pages: { nodes: Page[] } }>(gql`
query { query {
pages { pages(where: {status: PUBLISH}) {
nodes { nodes {
${BaseAttributes} ${BaseAttributes}
} }
@ -50,7 +52,7 @@ export const get: RequestHandler = async (args) => {
${MediaItemFragment} ${MediaItemFragment}
${WorkFragment} ${WorkFragment}
query { query {
works { works(where: { status: PUBLISH }) {
nodes { nodes {
...WorkFragment ...WorkFragment
} }
@ -81,7 +83,7 @@ export const get: RequestHandler = async (args) => {
gql` gql`
${ProjectFragment} ${ProjectFragment}
query { query {
projects { projects(where: { status: PUBLISH }) {
nodes { nodes {
...ProjectFragment ...ProjectFragment
} }
@ -120,6 +122,38 @@ export const get: RequestHandler = async (args) => {
) )
return { body: data.mediaItem } return { body: data.mediaItem }
} }
case 'posts': {
if (all) {
const data = await Call<{ posts: { nodes: Post[] } }>(gql`
${PostFragment}
${MediaItemFragment}
{
posts(where: { status: PUBLISH }, first: 1000000000) {
nodes {
...PostFragment
}
}
}
`)
return { body: data.posts.nodes }
} else {
const data = await Call<{ post: Post }>(
gql`
${PostFragment}
${MediaItemFragment}
query ($slug: ID!) {
post(id: $slug, idType: SLUG) {
...PostFragment
}
}
`,
{ slug }
)
return { body: data.post }
}
}
default: default:
return { status: 404 } return { status: 404 }
} }

View File

@ -0,0 +1,32 @@
<script lang="ts" context="module">
import type { Load } from '@sveltejs/kit'
export const prerender = true
export const load: Load = async ({ fetch, page }) => {
return {
props: {
data: await fetch(`/api/posts/${page.params.slug}.json`).then((r) => r.json()),
},
}
}
</script>
<script lang="ts">
import type { Post } from '$lib/api'
import SimplePage from '$lib/components/SimplePage.svelte'
import PostAttributes from '$lib/components/PostAttributes.svelte'
import WpAdapter from '$lib/components/WPAdapter.svelte'
export let data: Post
</script>
<svelte:head>
<title>Works</title>
</svelte:head>
<SimplePage title={data.title}>
<PostAttributes post={data} full />
{#if data.content}
<WpAdapter content={data.content} />
{/if}
</SimplePage>

View File

@ -0,0 +1,30 @@
<script lang="ts" context="module">
import type { Load } from '@sveltejs/kit'
export const prerender = true
export const load: Load = async ({ fetch }) => {
return {
props: {
data: await fetch('/api/posts/*.json').then((r) => r.json()),
},
}
}
</script>
<script lang="ts">
import type { Post } from '$lib/api'
import SimplePage from '$lib/components/SimplePage.svelte'
import PostPreview from '$lib/components/PostPreview.svelte'
export let data: Post[]
</script>
<svelte:head>
<title>Blog</title>
</svelte:head>
<SimplePage title="Works">
{#each data as post}
<PostPreview {post} />
{/each}
</SimplePage>

View File

@ -1,3 +1,7 @@
<script lang="ts" context="module">
export const prerender = true
</script>
<script lang="ts"> <script lang="ts">
import IconList from '$lib/components/IconList.svelte' import IconList from '$lib/components/IconList.svelte'
import SimplePage from '$lib/components/SimplePage.svelte' import SimplePage from '$lib/components/SimplePage.svelte'

View File

@ -1,22 +1,13 @@
<script lang="ts" context="module"> <script lang="ts" context="module">
import { Call, gql } from '$lib/api' import type { MediaItem } from '$lib/api'
export const prerender = true export const prerender = true
type Data = Record<'signature' | 'home', { srcSet: string }> type Data = Record<'signature' | 'home', MediaItem>
export const load: Load = async () => { export const load: Load = async ({ fetch }) => {
const data = await Call<Data>(gql` const signature: MediaItem = await fetch('/api/media/signature.json').then((r) => r.json())
query { const home: MediaItem = await fetch('/api/media/home.json').then((r) => r.json())
signature: mediaItem(id: "signature", idType: SLUG) { return { props: { data: { signature, home } } }
srcSet
}
home: mediaItem(id: "home", idType: SLUG) {
srcSet
}
}
`)
return { props: { data } }
} }
</script> </script>
@ -28,7 +19,7 @@
</script> </script>
<svelte:head> <svelte:head>
<title>Niccolo Borgioli</title> <title>Niccolò Borgioli</title>
</svelte:head> </svelte:head>
<div class="wrapper"> <div class="wrapper">

View File

@ -1,6 +1,7 @@
<script lang="ts" context="module"> <script lang="ts" context="module">
import type { Load } from '@sveltejs/kit' import type { Load } from '@sveltejs/kit'
export const prerender = true
export const load: Load = async ({ fetch }) => { export const load: Load = async ({ fetch }) => {
return { return {
props: { props: {

1
src/routes/search.svelte Normal file
View File

@ -0,0 +1 @@
Hello

View File

@ -1,3 +1,7 @@
<script lang="ts" context="module">
export const prerender = true
</script>
<script lang="ts"> <script lang="ts">
import IconList from '$lib/components/IconList.svelte' import IconList from '$lib/components/IconList.svelte'
import SimplePage from '$lib/components/SimplePage.svelte' import SimplePage from '$lib/components/SimplePage.svelte'