diff --git a/svelte-app/src/components/about/timeline.svelte b/svelte-app/src/components/about/timeline.svelte index eb3efc19e..151322264 100644 --- a/svelte-app/src/components/about/timeline.svelte +++ b/svelte-app/src/components/about/timeline.svelte @@ -10,7 +10,6 @@ import Hoverable from '$components/hoverable.svelte'; import Icon from '$components/icon.svelte'; import PortableText from '$components/portable-text/portable-text.svelte'; - // import Tags from '$components/tags.svelte'; import Tooltip from '$components/tooltip.svelte'; import type { AuthorTimelineItem } from '$types'; @@ -111,9 +110,6 @@ easing: circInOut }} > -
diff --git a/svelte-app/src/components/document/content/common/header.svelte b/svelte-app/src/components/document/content/common/header.svelte index fd73b1126..08df43332 100644 --- a/svelte-app/src/components/document/content/common/header.svelte +++ b/svelte-app/src/components/document/content/common/header.svelte @@ -1,12 +1,16 @@ -
- (expanded = !expanded)} /> - {#if expanded} - (expanded = !expanded)} /> - {/if} +
+ {#each headings as heading} + + •  {heading.text} + + {#if heading.children?.length} + + {/if} + {/each}
- - diff --git a/svelte-app/src/components/document/content/common/summary/item.svelte b/svelte-app/src/components/document/content/common/summary/item.svelte deleted file mode 100644 index dc39d5928..000000000 --- a/svelte-app/src/components/document/content/common/summary/item.svelte +++ /dev/null @@ -1,19 +0,0 @@ - - -
- {#each headings as heading} - - •  {heading.text} - - {#if heading.children?.length} - - {/if} - {/each} -
diff --git a/svelte-app/src/components/document/content/common/summary/items.svelte b/svelte-app/src/components/document/content/common/summary/items.svelte deleted file mode 100644 index e28f9cd0c..000000000 --- a/svelte-app/src/components/document/content/common/summary/items.svelte +++ /dev/null @@ -1,20 +0,0 @@ - - -
- -
diff --git a/svelte-app/src/components/document/content/content.svelte b/svelte-app/src/components/document/content/content.svelte index 40730bc1b..c636c39a0 100644 --- a/svelte-app/src/components/document/content/content.svelte +++ b/svelte-app/src/components/document/content/content.svelte @@ -14,12 +14,11 @@ export let data: PostDocument | ProjectDocument, model = data._type, headings: DocumentHeadings[] | undefined, - routeFetch: RouteFetch | undefined = undefined, - container: HTMLDivElement | undefined = undefined; + routeFetch: RouteFetch | undefined = undefined;
-
+
{#if data.body} {:else} diff --git a/svelte-app/src/components/document/route.svelte b/svelte-app/src/components/document/route.svelte index 93819df8e..3c2e3d34d 100644 --- a/svelte-app/src/components/document/route.svelte +++ b/svelte-app/src/components/document/route.svelte @@ -17,28 +17,26 @@ export let data: ProjectDocument | PostDocument, model = data._type, - headings: DocumentHeadings[] | never[], + headings: DocumentHeadings[] | undefined, routeFetch: RouteFetch | undefined = undefined; - const allTags = - (((tags: NonNullable['tags'] | undefined) => { - if (!tags) { - return undefined; - } - return tags.reduce((acc, tag) => { - tag.title && acc.push(tag.title.toLowerCase()); - return acc; - }, [] as string[]); - })(data?.tags)?.join(', ') as string) + ', ' || ''; - onMount(() => { scrollTo($page?.url); }); + $: allTags = + (data?.tags || []) + .reduce( + (acc, tag) => (tag.title && acc.push(tag.title.toLowerCase()), acc), + [] as string[] + ) + ?.join(', ') + ', ' || ''; $: $page?.url && scrollTo($page.url); $: pageTitle = `kio.dev${data?.title ? ` | ${data.title}` : ''}`; $: pageDescription = data?.desc - ? data.desc + ? data.desc.length > 160 + ? `${data.desc.slice(0, 160 - 3)}...` + : data.desc : $t(`A ${model === 'post' ? 'post' : 'project'} on kio.dev`); @@ -52,7 +50,7 @@ @@ -68,8 +66,6 @@ - - diff --git a/svelte-app/src/components/link-non-pt.svelte b/svelte-app/src/components/link-non-pt.svelte deleted file mode 100644 index 3089340b2..000000000 --- a/svelte-app/src/components/link-non-pt.svelte +++ /dev/null @@ -1,46 +0,0 @@ - - - - - - - - - - - diff --git a/svelte-app/src/components/link.svelte b/svelte-app/src/components/link.svelte new file mode 100644 index 000000000..8d0cc6523 --- /dev/null +++ b/svelte-app/src/components/link.svelte @@ -0,0 +1,42 @@ + + + + dispatch('click')} + on:keydown={(e) => { + if (e.key === 'Enter') { + dispatch('click'); + } + }} + role={type === 'a' ? 'link' : 'button'} + aria-label={$$props['aria-label']} + {...$$restProps} + > + + + diff --git a/svelte-app/src/components/portable-text/serializers/custom-link.svelte b/svelte-app/src/components/portable-text/serializers/custom-link.svelte index 59658cb0d..31b956199 100644 --- a/svelte-app/src/components/portable-text/serializers/custom-link.svelte +++ b/svelte-app/src/components/portable-text/serializers/custom-link.svelte @@ -1,29 +1,11 @@ - - - {plainTextContent} - - +{plainTextContent} diff --git a/svelte-app/src/components/tags.svelte b/svelte-app/src/components/tags.svelte deleted file mode 100644 index 2611ef4de..000000000 --- a/svelte-app/src/components/tags.svelte +++ /dev/null @@ -1,38 +0,0 @@ - - -
- {#each data as tag} - - {tag.title} - - {/each} -
diff --git a/svelte-app/src/lib/assets/last_fm-512.png b/svelte-app/src/lib/assets/last_fm-512.png deleted file mode 100644 index 7014707ca..000000000 Binary files a/svelte-app/src/lib/assets/last_fm-512.png and /dev/null differ diff --git a/svelte-app/src/lib/assets/logo-text.png b/svelte-app/src/lib/assets/logo-text.png deleted file mode 100644 index 94da7af34..000000000 Binary files a/svelte-app/src/lib/assets/logo-text.png and /dev/null differ diff --git a/svelte-app/src/lib/consts.ts b/svelte-app/src/lib/consts.ts index a3f6f4a5f..384e03e25 100644 --- a/svelte-app/src/lib/consts.ts +++ b/svelte-app/src/lib/consts.ts @@ -4,7 +4,7 @@ export const DARK_THEME = 'dark'; export const APP_LANGS = ['en', 'fr'] as const; export const DEFAULT_APP_LANG = 'en'; -export const VALID_DOC_TYPES = ['post', 'project', 'tag', 'about', 'config'] as const; +export const VALID_DOC_TYPES = ['post', 'project', 'about', 'config'] as const; export const LOCAL_SETTINGS_KEY = 'kio-dev-settings'; @@ -24,25 +24,13 @@ export const APP_ROUTES = [ { name: 'Blog', path: '/blog', - children: [ - { name: 'Post', path: '/blog/:slug' }, - { name: 'All Posts', path: '/blog/:int' }, - { name: 'Tag', path: '/blog/+/:tag' } - ], + children: [{ name: 'Post', path: '/blog/:slug' }], hidden: false }, { name: 'Work', path: '/work', - children: [ - { name: 'Project', path: '/work/:slug' }, - { name: 'All Projects', path: '/work/:int' }, - { - name: 'Tags', - path: '/work/+', - children: [{ name: 'Tag', path: '/work/+/:tag' }] - } - ], + children: [{ name: 'Project', path: '/work/:slug' }], hidden: false }, { @@ -58,21 +46,7 @@ export const TOP_LEVEL_ROUTES = APP_ROUTES.map((r) => { return rest; }) as Omit[]; -export const ROUTE_ORDER = [ - 'index', - 'about', - 'blog', - 'blog/*', - 'blog/*/*', - 'blog/+/*', - 'art', - 'art/*', - 'work', - 'work/*', - 'work/*/*', - 'work/+/*', - 'etc' -]; +export const ROUTE_ORDER = ['index', 'blog', 'blog/*', 'work', 'work/*', 'etc']; export const NAV_LINKS = TOP_LEVEL_ROUTES.filter((route) => !route.hidden)?.map( (route) => ({ diff --git a/svelte-app/src/lib/data.server.ts b/svelte-app/src/lib/data.server.ts index b0eb7ea7d..bbf81eaa0 100644 --- a/svelte-app/src/lib/data.server.ts +++ b/svelte-app/src/lib/data.server.ts @@ -1,4 +1,3 @@ -import { ENV } from '$lib/env'; import { REMOTE_API_TOKEN } from '$lib/env.server'; import Logger from '$lib/logger'; @@ -77,27 +76,16 @@ const normalize = (data: ResponseOrError) => { (normalized.meta as ResData['meta'] & { [key: string]: unknown })[key] = resData[key]; } - !['development', 'backed', 'test'].includes(ENV) && - normalized.meta?.query && - (normalized.meta.query = undefined); - return normalized; }; -const fetchRemote = async ({ - endpoint, - options -}: { - endpoint: string | URL; - options?: RequestInit; -}): Promise => { +const fetchRemote = async (endpoint: string | URL): Promise => { try { const response = await fetch(endpoint, { method: 'GET', headers: { authorization: `Bearer ${REMOTE_API_TOKEN}` - }, - ...options + } }); const jsonResponse = (await response.json()) as ResponseOrError; diff --git a/svelte-app/src/lib/data/normalize.ts b/svelte-app/src/lib/data/normalize.ts deleted file mode 100644 index dccdbc8a0..000000000 --- a/svelte-app/src/lib/data/normalize.ts +++ /dev/null @@ -1,69 +0,0 @@ -import { ENV } from '$lib/env'; - -/** - * Util to serialize recieved API data to common types - */ - -interface Response extends Record { - code: number; - message?: string; - data?: ResData; -} - -interface ResData extends Record { - result: Record; - ms?: number; - query?: string; - meta?: { - total?: number; - count?: number; - id?: string; - type?: string; - }; -} - -interface Normalized extends Record { - code?: number; - error?: string; - data?: ResData['result']; - meta?: ResData['meta'] & { [key: string]: unknown }; -} - -const normalize = (data: Response | Record) => { - if (!data?.code || (!data?.message && !data?.data)) { - return { - code: 500, - error: 'Endpoint error: Failed to normalize data. Remote API returned invalid data.' - }; - } - - const normalized = {} as Normalized; - - if (data.message) { - normalized.code = (data as Response).code; - normalized.error = (data as Response).message; - return normalized; - } - - const { data: resData } = data as Response; - - normalized.data = resData?.result; - normalized.meta = {} as Normalized['meta']; - resData?.meta && (normalized.meta = { ...resData.meta }); - - Object.keys(resData as ResData).forEach((key) => { - if (!['result', 'meta'].includes(key)) { - (normalized.meta as ResData['meta'] & { [key: string]: unknown })[key] = ( - resData as ResData - )[key]; - } - }); - - !['development', 'backed', 'test'].includes(ENV) && - normalized.meta?.query && - (normalized.meta.query = undefined); - - return normalized; -}; - -export default normalize; diff --git a/svelte-app/src/lib/env.ts b/svelte-app/src/lib/env.ts index ce6b7d781..0095745c3 100644 --- a/svelte-app/src/lib/env.ts +++ b/svelte-app/src/lib/env.ts @@ -1,4 +1,8 @@ -export const ENV: string = import.meta.env.MODE || import.meta.env.CONTEXT; +export const ENV = (import.meta.env.MODE || import.meta.env.CONTEXT) as + | 'backed' + | 'testing' + | 'development' + | 'production'; export const BASE_URL = '/'; export const API_URL = `${BASE_URL}api/`; diff --git a/svelte-app/src/lib/store.ts b/svelte-app/src/lib/store.ts index 75a87a2ce..02fb68406 100644 --- a/svelte-app/src/lib/store.ts +++ b/svelte-app/src/lib/store.ts @@ -1,4 +1,3 @@ -/* eslint-disable @typescript-eslint/no-non-null-assertion */ import { API_URL } from '$lib/env'; import Logger from '$lib/logger'; import tryFetch from '$lib/try-fetch'; @@ -37,111 +36,96 @@ type QueryResponse = } | undefined; -const EXP_TIME = 1000 * 60 * 30; - -const documentCache = new Proxy( - {} as Record< - string, - | { - exp: number; - data: - | DocumentRegistry[keyof DocumentRegistry][] - | DocumentRegistry[keyof DocumentRegistry]; - } - | undefined - >, +const EXP_TIME = 1000 * 60 * 30; // 30 minutes + +const documentCache: Record< + string, { - get: (target, prop) => { - switch (prop) { - case 'get': - return (key: string) => { - if (!(key in target) || target[key] === undefined) { - return undefined; - } - - if (target[key]!.exp <= Date.now()) { - target[key] = undefined; - return undefined; - } - - return target[key]!.data; - }; - case 'set': - return ( - key: string, - value: T - ) => - (target[key] = { - exp: Date.now() + EXP_TIME, - data: value - }); - default: - return undefined; - } - } + exp: number; + data: + | DocumentRegistry[keyof DocumentRegistry] + | DocumentRegistry[keyof DocumentRegistry][]; + } +> = {}; + +const cacheGet = (key: string) => { + const item = documentCache[key]; + if (!item || isExpired(item.exp)) { + delete documentCache[key]; + return undefined; } -) as unknown as { - get: ( - key: string - ) => + return item.data; +}; + +const cacheSet = ( + key: string, + value: | DocumentRegistry[keyof DocumentRegistry] | DocumentRegistry[keyof DocumentRegistry][] - | undefined; - set: ( - key: string, - value: - | DocumentRegistry[keyof DocumentRegistry] - | DocumentRegistry[keyof DocumentRegistry][] - ) => boolean; +) => { + documentCache[key] = { + exp: Date.now() + EXP_TIME, + data: value + }; }; +const isExpired = (timestamp: number): boolean => timestamp <= Date.now(); + const constructUrl = ( model: keyof DocumentRegistry, params: PossibleParams, many = false ) => { - const url = new URL(`http://fake${API_URL}get/${model}${many ? '/many' : ''}`); - Object.entries(params).forEach(([key, value]) => { - if (Array.isArray(value)) { - return value.length ? url.searchParams.append(key, value.join(',')) : undefined; + const basePath = `${API_URL}get/${model}${many ? '/many' : ''}`, + queryParams = []; + + for (const [key, value] of Object.entries(params)) { + if (Array.isArray(value) && value.length) { + queryParams.push(`${key}=${value.join(',')}`); + } else if (value !== null && value !== undefined && value.toString() !== '') { + queryParams.push(`${key}=${value}`); } - return typeof value === 'boolean' - ? url.searchParams.set(key, value.toString()) - : value.toString() !== '' && url.searchParams.set(key, value.toString()); - }); - return url.toString().replace('http://fake', ''); -}; - -const find = async ( - fetch: RouteFetch, - model: T, - params: PossibleParams = {} -) => { - const cacheKey = JSON.stringify({ model, params, many: true }); - if (documentCache.get(cacheKey)) { - return documentCache.get(cacheKey) as DocumentRegistry[T][]; } - const url = constructUrl(model, params, true); - let response: DocumentRegistry[T][] | undefined; + return `${basePath}${queryParams.length ? `?${queryParams.join('&')}` : ''}`; +}; +const fetchData = async ( + fetch: RouteFetch, + url: string, + model: keyof DocumentRegistry +): Promise => { try { - const fetchResponse = (await tryFetch(fetch(url)).then( - async (r) => await r.json() - )) as QueryResponse; + const response = await tryFetch(fetch(url)); + const fetchResponse = (await response.json()) as QueryResponse; if (!fetchResponse?.meta || fetchResponse?.error) { Logger.error(`Failed to query ${model}`, fetchResponse?.error); return undefined; } - response = fetchResponse?.data; + return fetchResponse?.data; } catch (e) { Logger.error(`Failed to query ${model}`, e); return undefined; } +}; +const find = async ( + fetch: RouteFetch, + model: T, + params: PossibleParams = {} +): Promise => { + const cacheKey = JSON.stringify({ model, params, many: true }); + const cachedData = cacheGet(cacheKey); + if (cachedData) { + return cachedData as DocumentRegistry[T][]; + } + + const url = constructUrl(model, params, true); + const response = await fetchData(fetch, url, model); if (response) { - documentCache.set(cacheKey, response); + cacheSet(cacheKey, response); } + return response; }; @@ -149,32 +133,21 @@ const findOne = async ( fetch: RouteFetch, model: T, params: PossibleParams = {} -) => { +): Promise => { const cacheKey = JSON.stringify({ model, params, many: false }); - if (!(params.preview === 'true') && documentCache.get(cacheKey)) { - return documentCache.get(cacheKey) as DocumentRegistry[T]; + if (params.preview !== 'true') { + const cachedData = cacheGet(cacheKey); + if (cachedData) { + return cachedData as DocumentRegistry[T]; + } } const url = constructUrl(model, params); - let response: DocumentRegistry[T] | undefined; - - try { - const fetchResponse = (await tryFetch(fetch(url)).then( - async (r) => await r.json() - )) as QueryResponse; - if (!fetchResponse?.meta || fetchResponse?.error) { - Logger.error(`Failed to query ${model}`, fetchResponse?.error); - return undefined; - } - response = fetchResponse?.data; - } catch (e) { - Logger.error(`Failed to query ${model}`, e); - return undefined; + const response = await fetchData(fetch, url, model); + if (params.preview !== 'true' && response) { + cacheSet(cacheKey, response); } - if (!(params.preview === 'true') && response) { - documentCache.set(cacheKey, response); - } return response; }; diff --git a/svelte-app/src/lib/try-fetch.ts b/svelte-app/src/lib/try-fetch.ts index eb6cd303c..23518ea9b 100644 --- a/svelte-app/src/lib/try-fetch.ts +++ b/svelte-app/src/lib/try-fetch.ts @@ -4,10 +4,6 @@ import { browser } from '$app/environment'; * Since Netlify has a timeout of 10s for any SSR function, we need to wrap * all SSR'd fetches in our own timeout block to abort and have the browser * handle fetching instead - * - * @param promise Promise to wrap - * @param ms Timeout in milliseconds - * @returns Initial promise's result */ export default (promise: Promise, ms = 6000): Promise => { if (browser) { diff --git a/svelte-app/src/params/int.ts b/svelte-app/src/params/int.ts index 61283eec3..c67a6a070 100644 --- a/svelte-app/src/params/int.ts +++ b/svelte-app/src/params/int.ts @@ -1,5 +1,3 @@ import type { ParamMatcher } from '@sveltejs/kit'; -export const match: ParamMatcher = (param: string) => { - return /^\d+$/.test(param); -}; +export const match: ParamMatcher = (param: string) => /^\d+$/.test(param); diff --git a/svelte-app/src/params/lang.ts b/svelte-app/src/params/lang.ts index 43e80dbdb..6158ac063 100644 --- a/svelte-app/src/params/lang.ts +++ b/svelte-app/src/params/lang.ts @@ -2,8 +2,5 @@ import { APP_LANGS } from '$lib/consts'; import type { ParamMatcher } from '@sveltejs/kit'; -export const match: ParamMatcher = (param: string) => { - // eslint-disable-next-line @typescript-eslint/ban-ts-comment - // @ts-ignore - param is string - return param.length === 2 && APP_LANGS.includes(param); -}; +export const match: ParamMatcher = (param: string) => + APP_LANGS.includes(param as (typeof APP_LANGS)[number]); diff --git a/svelte-app/src/params/plus.ts b/svelte-app/src/params/plus.ts deleted file mode 100644 index 38656b226..000000000 --- a/svelte-app/src/params/plus.ts +++ /dev/null @@ -1,5 +0,0 @@ -import type { ParamMatcher } from '@sveltejs/kit'; - -export const match: ParamMatcher = (param: string) => { - return param === '+' || param === '%2B'; -}; diff --git a/svelte-app/src/params/txt.ts b/svelte-app/src/params/txt.ts index 8e528fa89..a1d765613 100644 --- a/svelte-app/src/params/txt.ts +++ b/svelte-app/src/params/txt.ts @@ -1,5 +1,3 @@ import type { ParamMatcher } from '@sveltejs/kit'; -export const match: ParamMatcher = (param: string) => { - return /\.txt$/.test(param); -}; +export const match: ParamMatcher = (param: string) => /\.txt$/.test(param); diff --git a/svelte-app/src/params/well_known.ts b/svelte-app/src/params/well_known.ts index 9e46a2b7e..9566e648b 100644 --- a/svelte-app/src/params/well_known.ts +++ b/svelte-app/src/params/well_known.ts @@ -1,5 +1,3 @@ import type { ParamMatcher } from '@sveltejs/kit'; -export const match: ParamMatcher = (param: string) => { - return /^\.?well-known$/.test(param); -}; +export const match: ParamMatcher = (param: string) => /^\.?well-known$/.test(param); diff --git a/svelte-app/src/routes/+error.svelte b/svelte-app/src/routes/+error.svelte index 70d2e523d..fdf380775 100644 --- a/svelte-app/src/routes/+error.svelte +++ b/svelte-app/src/routes/+error.svelte @@ -1,15 +1,21 @@ - kio.dev | {$page.status} + kio.dev | {status} -
+
-

- {$t(title)} +

+ {status}: {$t(title)}

- - {#if $page.error?.stack} +

+ {$t($page.error?.message && $page.status !== 404 ? $page.error.message : message)} + {$t('Click here to')} + { + window.history.back(); + }} + on:keydown={() => { + window.history.back(); + }}>{$t('go back')}. +

+ {#if stack} -
-

Stack Trace

-
-            {$page.error.stack}
-          
-
+ (showStack = !showStack)}> + {showStack ? $t('Hide stack trace') : $t('Show stack trace')} + + + {#if showStack} +
+
+              {stack}
+            
+
+ {/if} {/if}
diff --git a/svelte-app/src/routes/+layout.svelte b/svelte-app/src/routes/+layout.svelte index 4a6830795..058efdffd 100644 --- a/svelte-app/src/routes/+layout.svelte +++ b/svelte-app/src/routes/+layout.svelte @@ -9,8 +9,9 @@ import { navigating, page } from '$app/stores'; import { isDesktop } from '$helpers/responsive'; - import { check as checkTranslations, currentLang, isLocalized } from '$i18n'; + import { check as checkTranslations, currentLang, isLocalized, t } from '$i18n'; import { APP_LANGS, DEFAULT_APP_LANG } from '$lib/consts'; + import { ENV } from '$lib/env'; import { setState as setMenuState, state as menuState } from '$lib/helpers/menu'; import Settings, { loading } from '$stores/settings'; @@ -66,7 +67,7 @@ ].forEach(([k, v]) => setContext(k, v)); onMount(() => { - checkTranslations(); + ENV !== 'production' && checkTranslations(); setTimeout(() => { loading.set(false); @@ -112,11 +113,11 @@ Skip to content{$t('Skip to content')}
{ const lang = params.lang || DEFAULT_APP_LANG, diff --git a/svelte-app/src/routes/[[lang=lang]]/+page.ts b/svelte-app/src/routes/[[lang=lang]]/+page.ts index 7c9c4ab20..da57b029d 100644 --- a/svelte-app/src/routes/[[lang=lang]]/+page.ts +++ b/svelte-app/src/routes/[[lang=lang]]/+page.ts @@ -6,7 +6,7 @@ import { error } from '@sveltejs/kit'; import type { PageLoad } from './$types'; import type { PostDocument, ProjectDocument } from '$types'; -export const load: PageLoad = async ({ parent, fetch, params }) => { +export const load = (async ({ parent, fetch, params }) => { const parentData = await parent(), about = parentData.about, lang = params.lang || DEFAULT_APP_LANG, @@ -28,4 +28,4 @@ export const load: PageLoad = async ({ parent, fetch, params }) => { ]; return { posts, projects: [project], about }; -}; +}) satisfies PageLoad; diff --git a/svelte-app/src/routes/[[lang=lang]]/.well-known/[path]/+server.ts b/svelte-app/src/routes/[[lang=lang]]/.well-known/[path]/+server.ts index e901cf1d8..b8f24081b 100644 --- a/svelte-app/src/routes/[[lang=lang]]/.well-known/[path]/+server.ts +++ b/svelte-app/src/routes/[[lang=lang]]/.well-known/[path]/+server.ts @@ -3,7 +3,7 @@ import { security } from '$lib/fixtures/well-known'; import type { RequestHandler } from './$types'; -export const GET: RequestHandler = async ({ url }): Promise => { +export const GET = (async ({ url }) => { const filename = url.pathname.split('/').pop(); switch (filename) { @@ -35,4 +35,4 @@ export const GET: RequestHandler = async ({ url }): Promise => { } ); } -}; +}) satisfies RequestHandler; diff --git a/svelte-app/src/routes/[[lang=lang]]/[file=txt]/+server.ts b/svelte-app/src/routes/[[lang=lang]]/[file=txt]/+server.ts index 2d6f4fe7f..3c7a22ffb 100644 --- a/svelte-app/src/routes/[[lang=lang]]/[file=txt]/+server.ts +++ b/svelte-app/src/routes/[[lang=lang]]/[file=txt]/+server.ts @@ -2,7 +2,7 @@ import Robots from '$lib/fixtures/robots'; import type { RequestHandler } from './$types'; -export const GET: RequestHandler = async ({ url, fetch }): Promise => { +export const GET = (async ({ url, fetch }) => { const filename = url.pathname.split('/').pop(); switch (filename) { @@ -41,4 +41,4 @@ export const GET: RequestHandler = async ({ url, fetch }): Promise => } ); } -}; +}) satisfies RequestHandler; diff --git a/svelte-app/src/routes/[[lang=lang]]/blog/+layout.svelte b/svelte-app/src/routes/[[lang=lang]]/blog/+layout.svelte deleted file mode 100644 index b927cdac1..000000000 --- a/svelte-app/src/routes/[[lang=lang]]/blog/+layout.svelte +++ /dev/null @@ -1,5 +0,0 @@ - - - diff --git a/svelte-app/src/routes/[[lang=lang]]/blog/+page.svelte b/svelte-app/src/routes/[[lang=lang]]/blog/+page.svelte index 1a9db5ed7..0bb83cf05 100644 --- a/svelte-app/src/routes/[[lang=lang]]/blog/+page.svelte +++ b/svelte-app/src/routes/[[lang=lang]]/blog/+page.svelte @@ -4,6 +4,7 @@ import { t } from '$lib/helpers/i18n'; import EmptyContent from '$components/empty-content.svelte'; + import ContentWrapper from '$components/layouts/content-wrapper.svelte'; import ListItem from '$components/lists/list-item.svelte'; export let data; @@ -31,28 +32,30 @@ -

{$t('Recent posts')}

-{#if posts?.length} -
- {#each sortedPosts as yearObj} -
-

{yearObj.year}

- {#if yearObj.items.length} -
- {#each yearObj.items as item} - - {/each} -
- {:else} -

{$t('No content')}

- {/if} -
- {/each} -
-{:else} -
- -
-{/if} + +

{$t('Recent posts')}

+ {#if posts?.length} +
+ {#each sortedPosts as yearObj} +
+

{yearObj.year}

+ {#if yearObj.items.length} +
+ {#each yearObj.items as item} + + {/each} +
+ {:else} +

{$t('No content')}

+ {/if} +
+ {/each} +
+ {:else} +
+ +
+ {/if} +
diff --git a/svelte-app/src/routes/[[lang=lang]]/blog/+page.ts b/svelte-app/src/routes/[[lang=lang]]/blog/+page.ts index 5b8092ff1..67f12e9b6 100644 --- a/svelte-app/src/routes/[[lang=lang]]/blog/+page.ts +++ b/svelte-app/src/routes/[[lang=lang]]/blog/+page.ts @@ -3,12 +3,11 @@ import { find } from '$lib/store'; import type { PageLoad } from './$types'; -export const load: PageLoad = async ({ parent, fetch, params }) => { - const _parentData = await parent(), - posts = await find(fetch, 'post', { - limit: RECENT_POSTS_COUNT, - lang: params.lang ?? 'en' - }); +export const load = (async ({ fetch, params }) => { + const posts = await find(fetch, 'post', { + limit: RECENT_POSTS_COUNT, + lang: params.lang ?? 'en' + }); return { posts }; -}; +}) satisfies PageLoad; diff --git a/svelte-app/src/routes/[[lang=lang]]/blog/[plus=plus]/+page.ts b/svelte-app/src/routes/[[lang=lang]]/blog/[plus=plus]/+page.ts deleted file mode 100644 index 1cc3407b9..000000000 --- a/svelte-app/src/routes/[[lang=lang]]/blog/[plus=plus]/+page.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { redirect } from '@sveltejs/kit'; - -import type { PageLoad } from './$types'; - -export const prerender = false; - -export const load: PageLoad = ({ params }) => { - throw redirect(301, params.lang === 'fr' ? '/fr/blog' : '/blog'); -}; diff --git a/svelte-app/src/routes/[[lang=lang]]/blog/[plus=plus]/[slug]/+page.svelte b/svelte-app/src/routes/[[lang=lang]]/blog/[plus=plus]/[slug]/+page.svelte deleted file mode 100644 index 66b7b65a5..000000000 --- a/svelte-app/src/routes/[[lang=lang]]/blog/[plus=plus]/[slug]/+page.svelte +++ /dev/null @@ -1,32 +0,0 @@ - - - - - kio.dev | {$t('Blog').toLowerCase()} | {pageTitle} - - - -

- {$t("Recent '{tag}' posts", { tag: pageTitle })} -

-{#if data.posts?.length} -
- {#each data.posts as post} - - {/each} -
-{:else} -
- -
-{/if} diff --git a/svelte-app/src/routes/[[lang=lang]]/blog/[plus=plus]/[slug]/+page.ts b/svelte-app/src/routes/[[lang=lang]]/blog/[plus=plus]/[slug]/+page.ts deleted file mode 100644 index b74dd673e..000000000 --- a/svelte-app/src/routes/[[lang=lang]]/blog/[plus=plus]/[slug]/+page.ts +++ /dev/null @@ -1,45 +0,0 @@ -import { PAGINATION_POSTS_PER_PAGE } from '$lib/consts'; -import Logger from '$lib/logger'; -import { find } from '$lib/store'; - -import { error, redirect } from '@sveltejs/kit'; - -import type { PageLoad } from './$types'; - -export const prerender = false; - -export const load: PageLoad = async ({ parent, fetch, params }) => { - if (params.slug === '') { - throw redirect(301, params.lang === 'fr' ? '/fr/blog/' : '/blog/'); - } - - const _parentData = await parent(), - allTags = await find(fetch, 'tag', { - type: 'post', - limit: 0 - }); - - if ( - !allTags?.some( - (tag) => - tag.slug.current?.toLowerCase() === params.slug?.toLowerCase() || - tag.title?.toLowerCase() === params.slug?.toLowerCase() - ) - ) { - Logger.info('Tag not found', params.slug); - if (!allTags) { - Logger.warn('Failed to fetch tags'); - } - // TODO: Find i18n alternative since linkTo can't work outside client component ctx - throw error(404, { - message: "Sorry, that tag couldn't be found or doesn't exist" - }); - } - - const posts = await find(fetch, 'post', { - limit: PAGINATION_POSTS_PER_PAGE, - tags: [params.slug] - }); - - return { posts }; -}; diff --git a/svelte-app/src/routes/[[lang=lang]]/work/[slug]/+page@.svelte b/svelte-app/src/routes/[[lang=lang]]/blog/[slug]/+page.svelte similarity index 53% rename from svelte-app/src/routes/[[lang=lang]]/work/[slug]/+page@.svelte rename to svelte-app/src/routes/[[lang=lang]]/blog/[slug]/+page.svelte index 7332cdaba..9f7377c60 100644 --- a/svelte-app/src/routes/[[lang=lang]]/work/[slug]/+page@.svelte +++ b/svelte-app/src/routes/[[lang=lang]]/blog/[slug]/+page.svelte @@ -2,8 +2,10 @@ import DocumentRoute from '$components/document/route.svelte'; export let data; - - $: ({ project } = data); - + diff --git a/svelte-app/src/routes/[[lang=lang]]/blog/[slug]/+page.ts b/svelte-app/src/routes/[[lang=lang]]/blog/[slug]/+page.ts index 60e356c0f..0140e6309 100644 --- a/svelte-app/src/routes/[[lang=lang]]/blog/[slug]/+page.ts +++ b/svelte-app/src/routes/[[lang=lang]]/blog/[slug]/+page.ts @@ -5,9 +5,8 @@ import { error } from '@sveltejs/kit'; import type { PageLoad } from './$types'; -export const load: PageLoad = async ({ parent, fetch, params, url }) => { - const _parentData = await parent(), - lang = params.lang || DEFAULT_APP_LANG, +export const load = (async ({ fetch, params, url }) => { + const lang = params.lang || DEFAULT_APP_LANG, preview = url.searchParams.get('preview') === 'true' || false, post = await findOne(fetch, 'post', { idb: btoa(params.slug), lang, preview }).catch( (e: Error) => { @@ -25,4 +24,4 @@ export const load: PageLoad = async ({ parent, fetch, params, url }) => { } return { post, routeFetch: fetch }; -}; +}) satisfies PageLoad; diff --git a/svelte-app/src/routes/[[lang=lang]]/etc/+page.svelte b/svelte-app/src/routes/[[lang=lang]]/etc/+page.svelte index 756399617..f04697199 100644 --- a/svelte-app/src/routes/[[lang=lang]]/etc/+page.svelte +++ b/svelte-app/src/routes/[[lang=lang]]/etc/+page.svelte @@ -8,7 +8,7 @@ import EmptyContent from '$components/empty-content.svelte'; import HeadedBlock from '$components/headings/headed-block.svelte'; import ContentWrapper from '$components/layouts/content-wrapper.svelte'; - import LinkNonPt from '$components/link-non-pt.svelte'; + import Link from '$components/link.svelte'; import PortableText from '$components/portable-text/portable-text.svelte'; export let data; @@ -45,8 +45,8 @@

{$t("Want to send a secure message my way? Here's my main PGP key:")} - D1FD DE24 BB72 BFEF E045 ECE0 8A2C 67E2 2184 F162D1FD DE24 BB72 BFEF E045 ECE0 8A2C 67E2 2184 F162

diff --git a/svelte-app/src/routes/[[lang=lang]]/etc/+page.ts b/svelte-app/src/routes/[[lang=lang]]/etc/+page.ts index 0f27c6e74..1a0a99f34 100644 --- a/svelte-app/src/routes/[[lang=lang]]/etc/+page.ts +++ b/svelte-app/src/routes/[[lang=lang]]/etc/+page.ts @@ -2,7 +2,7 @@ import { error } from '@sveltejs/kit'; import type { PageLoad } from './$types'; -export const load: PageLoad = async ({ parent }) => { +export const load = (async ({ parent }) => { const parentData = await parent(); if (!parentData.about) { @@ -13,4 +13,4 @@ export const load: PageLoad = async ({ parent }) => { } return { about: parentData.about }; -}; +}) satisfies PageLoad; diff --git a/svelte-app/src/routes/[[lang=lang]]/work/+layout.svelte b/svelte-app/src/routes/[[lang=lang]]/work/+layout.svelte deleted file mode 100644 index b927cdac1..000000000 --- a/svelte-app/src/routes/[[lang=lang]]/work/+layout.svelte +++ /dev/null @@ -1,5 +0,0 @@ - - - diff --git a/svelte-app/src/routes/[[lang=lang]]/work/+page.svelte b/svelte-app/src/routes/[[lang=lang]]/work/+page.svelte index da24322d3..d9c744705 100644 --- a/svelte-app/src/routes/[[lang=lang]]/work/+page.svelte +++ b/svelte-app/src/routes/[[lang=lang]]/work/+page.svelte @@ -5,6 +5,7 @@ import NewTimeline from '$components/about/timeline.svelte'; import EmptyContent from '$components/empty-content.svelte'; + import ContentWrapper from '$components/layouts/content-wrapper.svelte'; import ListItem from '$components/lists/list-item.svelte'; export let data; @@ -34,35 +35,37 @@ -

{$t("Where I've worked")}

-{#if about?.timeline?.length} - -{:else} -
- -
-{/if} + +

{$t("Where I've worked")}

+ {#if about?.timeline?.length} + + {:else} +
+ +
+ {/if} -

{$t('Projects & Talks')}

-{#if projects?.length} -
- {#each sortedProjects as yearObj} -
-

{yearObj.year}

- {#if yearObj.items.length} -
- {#each yearObj.items as item} - - {/each} -
- {:else} -

{$t('No content')}

- {/if} -
- {/each} -
-{:else} -
- -
-{/if} +

{$t('Projects & Talks')}

+ {#if projects?.length} +
+ {#each sortedProjects as yearObj} +
+

{yearObj.year}

+ {#if yearObj.items.length} +
+ {#each yearObj.items as item} + + {/each} +
+ {:else} +

{$t('No content')}

+ {/if} +
+ {/each} +
+ {:else} +
+ +
+ {/if} +
diff --git a/svelte-app/src/routes/[[lang=lang]]/work/+page.ts b/svelte-app/src/routes/[[lang=lang]]/work/+page.ts index f37a1bee2..e3faab903 100644 --- a/svelte-app/src/routes/[[lang=lang]]/work/+page.ts +++ b/svelte-app/src/routes/[[lang=lang]]/work/+page.ts @@ -9,7 +9,7 @@ import { error } from '@sveltejs/kit'; import type { PageLoad } from './$types'; -export const load: PageLoad = async ({ parent, fetch, params }) => { +export const load = (async ({ parent, fetch, params }) => { const parentData = await parent(), lang = params.lang || DEFAULT_APP_LANG, projects = await find(fetch, 'project', { @@ -26,4 +26,4 @@ export const load: PageLoad = async ({ parent, fetch, params }) => { } return { about: parentData.about, projects }; -}; +}) satisfies PageLoad; diff --git a/svelte-app/src/routes/[[lang=lang]]/work/[plus=plus]/+page.ts b/svelte-app/src/routes/[[lang=lang]]/work/[plus=plus]/+page.ts deleted file mode 100644 index cdb01756d..000000000 --- a/svelte-app/src/routes/[[lang=lang]]/work/[plus=plus]/+page.ts +++ /dev/null @@ -1,7 +0,0 @@ -import { redirect } from '@sveltejs/kit'; - -import type { PageLoad } from './$types'; - -export const load = (({ params }) => { - throw redirect(301, params.lang === 'fr' ? '/fr/work' : '/work'); -}) satisfies PageLoad; diff --git a/svelte-app/src/routes/[[lang=lang]]/work/[plus=plus]/[slug]/+page.svelte b/svelte-app/src/routes/[[lang=lang]]/work/[plus=plus]/[slug]/+page.svelte deleted file mode 100644 index f42011cd1..000000000 --- a/svelte-app/src/routes/[[lang=lang]]/work/[plus=plus]/[slug]/+page.svelte +++ /dev/null @@ -1,28 +0,0 @@ - - - - - kio.dev | work | {pageTitle} - - - -

- {$t("Recent '{tag}' projects", { tag: pageTitle })} -

-{#if $page.data.projects?.length} -
- {#each $page.data.projects as project} - - {/each} -
-{:else} - -{/if} diff --git a/svelte-app/src/routes/[[lang=lang]]/work/[plus=plus]/[slug]/+page.ts b/svelte-app/src/routes/[[lang=lang]]/work/[plus=plus]/[slug]/+page.ts deleted file mode 100644 index 79707b8da..000000000 --- a/svelte-app/src/routes/[[lang=lang]]/work/[plus=plus]/[slug]/+page.ts +++ /dev/null @@ -1,51 +0,0 @@ -import { DEFAULT_PROJECT_QUERY_PARAMS, PAGINATION_PROJECTS_PER_PAGE } from '$lib/consts'; -import Logger from '$lib/logger'; -import { find } from '$lib/store'; - -import { error, redirect } from '@sveltejs/kit'; - -import type { PageLoad } from './$types'; - -export const prerender = false; - -export const load = (async ({ parent, fetch, params }) => { - if (params.slug === '') { - throw redirect(301, params.lang === 'fr' ? '/fr/work/' : '/work/'); - } - - const _parentData = await parent(), - allTags = await find(fetch, 'tag', { - type: 'project', - limit: 0 - }).catch((err: unknown) => { - Logger.error('', err); - return undefined; - }); - - if ( - !allTags?.some( - (tag) => - tag.slug.current?.toLowerCase() === params.slug?.toLowerCase() || - tag.title?.toLowerCase() === params.slug?.toLowerCase() - ) - ) { - Logger.info('Tag not found', {}, params.slug); - if (!allTags) { - console.warn('Failed to fetch tags'); - } - throw error(404, { - message: "Sorry, that tag couldn't be found or doesn't exist" - }); - } - - const projects = await find(fetch, 'project', { - ...DEFAULT_PROJECT_QUERY_PARAMS, - limit: PAGINATION_PROJECTS_PER_PAGE, - tags: [params.slug] - }).catch((err: unknown) => { - Logger.error(err as string, {}, `routes/work/+/${params.slug}`); - return undefined; - }); - - return { projects }; -}) satisfies PageLoad; diff --git a/svelte-app/src/routes/[[lang=lang]]/blog/[slug]/+page@.svelte b/svelte-app/src/routes/[[lang=lang]]/work/[slug]/+page.svelte similarity index 50% rename from svelte-app/src/routes/[[lang=lang]]/blog/[slug]/+page@.svelte rename to svelte-app/src/routes/[[lang=lang]]/work/[slug]/+page.svelte index 959040145..6231059da 100644 --- a/svelte-app/src/routes/[[lang=lang]]/blog/[slug]/+page@.svelte +++ b/svelte-app/src/routes/[[lang=lang]]/work/[slug]/+page.svelte @@ -2,8 +2,10 @@ import DocumentRoute from '$components/document/route.svelte'; export let data; - - $: ({ post, routeFetch } = data); - + diff --git a/svelte-app/src/routes/[[lang=lang]]/work/[slug]/+page.ts b/svelte-app/src/routes/[[lang=lang]]/work/[slug]/+page.ts index a93f862d3..83a22b660 100644 --- a/svelte-app/src/routes/[[lang=lang]]/work/[slug]/+page.ts +++ b/svelte-app/src/routes/[[lang=lang]]/work/[slug]/+page.ts @@ -5,9 +5,8 @@ import { error } from '@sveltejs/kit'; import type { PageLoad } from './$types'; -export const load: PageLoad = async ({ parent, fetch, params, url }) => { - const _parentData = await parent(), - lang = params.lang || DEFAULT_APP_LANG, +export const load = (async ({ fetch, params, url }) => { + const lang = params.lang || DEFAULT_APP_LANG, preview = url.searchParams.get('preview') === 'true' || false, project = await findOne(fetch, 'project', { id: params.slug, lang, preview }).catch( (e: Error) => { @@ -24,5 +23,5 @@ export const load: PageLoad = async ({ parent, fetch, params, url }) => { }); } - return { project }; -}; + return { project, routeFetch: fetch }; +}) satisfies PageLoad; diff --git a/svelte-app/src/routes/api/[[version]]/get/[[type]]/[[many]]/+server.ts b/svelte-app/src/routes/api/[[version]]/get/[[type]]/[[many]]/+server.ts index 84601fb4f..83c674eff 100644 --- a/svelte-app/src/routes/api/[[version]]/get/[[type]]/[[many]]/+server.ts +++ b/svelte-app/src/routes/api/[[version]]/get/[[type]]/[[many]]/+server.ts @@ -2,12 +2,9 @@ import { VALID_DOC_TYPES } from '$lib/consts'; import { fetchRemote } from '$lib/data.server'; import { REMOTE_API_URL } from '$lib/env'; -import type { RequestEvent, RequestHandler } from './$types'; +import type { RequestHandler } from './$types'; -export const GET: RequestHandler = async ({ - url, - params -}: RequestEvent): Promise => { +export const GET = (async ({ url, params }) => { const docType = params.type as (typeof VALID_DOC_TYPES)[number], many = !!params.many ?? false; @@ -26,20 +23,7 @@ export const GET: RequestHandler = async ({ } if ( - docType === 'tag' && - !['post', 'project'].includes(url.searchParams.get('type') || '') - ) { - return endpointResponse( - { - status: 400, - error: 'Endpoint error: Missing or invalid query parameter: type' - }, - 400 - ); - } - - if ( - ['post', 'project'].includes(docType) && + (docType === 'post' || docType === 'project') && !many && !(url.searchParams.get('id') || url.searchParams.get('idb')) ) { @@ -54,9 +38,8 @@ export const GET: RequestHandler = async ({ url.searchParams.delete('many'); - const endpoint = getEndpoint(docType, many, url.searchParams); - - const remoteRes = await fetchRemote({ endpoint }); + const endpoint = getEndpoint(docType, many, url.searchParams), + remoteRes = await fetchRemote(endpoint); if (remoteRes.error) { return endpointResponse( @@ -69,7 +52,7 @@ export const GET: RequestHandler = async ({ } return endpointResponse(remoteRes); -}; +}) satisfies RequestHandler; const getEndpoint = ( type: (typeof VALID_DOC_TYPES)[number], @@ -87,8 +70,6 @@ const getEndpoint = ( }?lang=${params.get('lang') || 'en'}${ params.get('preview') === 'true' ? '&preview=true' : '' }`; - case 'tag': - return `${REMOTE_API_URL}/query/tags?${params}`; case 'config': return `${REMOTE_API_URL}/config`; case 'about':