(mouseDown = 'r')}
- on:mouseenter={() => (handleHovered = 'r')}
- on:mouseleave={() => (handleHovered = false)}
- role="presentation"
- />
-
-
-
diff --git a/svelte-app/src/components/link.svelte b/svelte-app/src/components/link.svelte
index fbc15ba1a..cdcbc4f94 100644
--- a/svelte-app/src/components/link.svelte
+++ b/svelte-app/src/components/link.svelte
@@ -3,48 +3,70 @@
import { linkTo, t } from '$lib/i18n';
- import Hoverable from '$components/hoverable.svelte';
import Tooltip from '$components/tooltips/tooltip.svelte';
- const dispatch = createEventDispatcher(),
- type = $$props.href ? 'a' : 'button';
+ import type { Placement } from '@floating-ui/dom';
- export let tooltipPosition: 'top' | 'bottom' = 'bottom',
+ export let tooltipPlacement: Placement = 'bottom',
tooltipText: string | undefined = undefined,
newtab = false;
- $: link = $$props.href
- ? $$props.href.startsWith('/')
- ? $linkTo($$props.href)
- : $$props.href
- : undefined;
+ const isMailLink: boolean = $$props.href?.startsWith?.('mailto:'),
+ mailAddress: string = isMailLink ? $$props.href.slice('mailto:'.length) : '',
+ dispatch = createEventDispatcher(),
+ type = !$$props.href?.length || isMailLink ? 'button' : 'a';
+
+ $: link = (() => {
+ if (isMailLink) {
+ return undefined;
+ }
+
+ if ($$props.href?.startsWith('/')) {
+ return $linkTo($$props.href);
+ }
+
+ return $$props.href;
+ })();
-
+
+
diff --git a/svelte-app/src/components/lists/document-list.svelte b/svelte-app/src/components/lists/document-list.svelte
index 88034bf58..9b246efad 100644
--- a/svelte-app/src/components/lists/document-list.svelte
+++ b/svelte-app/src/components/lists/document-list.svelte
@@ -6,17 +6,8 @@
export let documents: (ProjectDocument | PostDocument)[];
-
- {#each documents as document, idx}
-
- {#if idx < documents.length - 1}
-
- {/if}
+
+ {#each documents as document}
+
{/each}
diff --git a/svelte-app/src/components/lists/list-item.svelte b/svelte-app/src/components/lists/list-item.svelte
index 6b68850a4..d6cc63dd7 100644
--- a/svelte-app/src/components/lists/list-item.svelte
+++ b/svelte-app/src/components/lists/list-item.svelte
@@ -1,10 +1,8 @@
-
-
+
-
-
- {$formatDate(document.date || document._createdAt, 'med')}
-
- {#if document.tags?.length}
-
{document.tags[0].title.toLowerCase()}
- {:else}
-
- {/if}
-
{$t('{views} views', { views: $parseViews(document.views ?? 0) })}
-
-
-
- {document.title}
-
-
- {#if document.desc?.length}
-
- {document.desc}
-
- {/if}
+
+ {$formatDate(document.date || document._createdAt, 'med')}
+
+
+
+
+ {document.tags?.[0]?.title || $t('Uncategorized')}
+
+
+
+
+ {document.title}
+
- →
-
-
-
-
+ {document.desc}
+
+ {/if}
+
diff --git a/svelte-app/src/components/nav/base-link.svelte b/svelte-app/src/components/nav/base-link.svelte
deleted file mode 100644
index 5548e03bb..000000000
--- a/svelte-app/src/components/nav/base-link.svelte
+++ /dev/null
@@ -1,45 +0,0 @@
-
-
-
- dispatch('click', e)}
- on:keyup={(e) => e.code === 'Enter' && dispatch('click', e)}
- >
- {#if $$slots.default}
-
- {:else}
- {text.toLowerCase()}
- {/if}
-
-
diff --git a/svelte-app/src/components/nav/confetti-piece.svelte b/svelte-app/src/components/nav/confetti-piece.svelte
deleted file mode 100644
index 59345a0b1..000000000
--- a/svelte-app/src/components/nav/confetti-piece.svelte
+++ /dev/null
@@ -1,39 +0,0 @@
-
-
-
-
-
diff --git a/svelte-app/src/components/nav/confetti.svelte b/svelte-app/src/components/nav/confetti.svelte
deleted file mode 100644
index 448ddd8db..000000000
--- a/svelte-app/src/components/nav/confetti.svelte
+++ /dev/null
@@ -1,18 +0,0 @@
-
-
-
- {#each Array.from({ length: 30 }) as _, index (index)}
-
- {/each}
-
diff --git a/svelte-app/src/components/nav/header-link.svelte b/svelte-app/src/components/nav/header-link.svelte
deleted file mode 100644
index 2b0689072..000000000
--- a/svelte-app/src/components/nav/header-link.svelte
+++ /dev/null
@@ -1,45 +0,0 @@
-
-
-
diff --git a/svelte-app/src/components/nav/header-logo.svelte b/svelte-app/src/components/nav/header-logo.svelte
deleted file mode 100644
index a1db37d95..000000000
--- a/svelte-app/src/components/nav/header-logo.svelte
+++ /dev/null
@@ -1,35 +0,0 @@
-
-
-
-
-
-
-
- {#if showConfetti}
- (showConfetti = false)}>
- {/if}
-
diff --git a/svelte-app/src/components/portable-text/footnote.svelte b/svelte-app/src/components/portable-text/footnote.svelte
index 87fc6c3f4..717118f47 100644
--- a/svelte-app/src/components/portable-text/footnote.svelte
+++ b/svelte-app/src/components/portable-text/footnote.svelte
@@ -38,7 +38,7 @@
-
+
1}
-
-
+
+
{/if}
diff --git a/svelte-app/src/components/portable-text/image-carousel/scroll-button.svelte b/svelte-app/src/components/portable-text/image-carousel/scroll-button.svelte
index 9dd28c093..8a430acd8 100644
--- a/svelte-app/src/components/portable-text/image-carousel/scroll-button.svelte
+++ b/svelte-app/src/components/portable-text/image-carousel/scroll-button.svelte
@@ -1,35 +1,44 @@
-
-
+ {#if dir === 'left'}
+
+
+
+
+
+
+ {:else}
+
+
+
+
+
+
+ {/if}
+
+
diff --git a/svelte-app/src/components/portable-text/portable-text.svelte b/svelte-app/src/components/portable-text/portable-text.svelte
index 3f4dd67ab..b373a8d4f 100644
--- a/svelte-app/src/components/portable-text/portable-text.svelte
+++ b/svelte-app/src/components/portable-text/portable-text.svelte
@@ -2,6 +2,8 @@
import { t } from '$lib/i18n';
import Logger from '$lib/logger';
+ import ChevronDoubleUpSmall from '$components/icons/chevron-double-up-small.svelte';
+ import ChevronUpSmall from '$components/icons/chevron-up-small.svelte';
import Footnote from '$components/portable-text/footnote.svelte';
import CodeBlock from '$components/portable-text/serializers/code-block.svelte';
import CustomCode from '$components/portable-text/serializers/custom-code.svelte';
@@ -16,6 +18,7 @@
import NullMark from '$components/portable-text/serializers/null-mark.svelte';
import OlWrapper from '$components/portable-text/serializers/ol-wrapper.svelte';
import UlWrapper from '$components/portable-text/serializers/ul-wrapper.svelte';
+ import Tooltip from '$components/tooltips/tooltip.svelte';
import { PortableText } from '@portabletext/svelte';
@@ -144,18 +147,27 @@
- customScrollTo(e, `src-${note._key}`)}
- on:keydown={(e) => {
- if (e.code === 'Space' || e.code === 'Enter') {
- customScrollTo(e, `src-${note._key}`);
- }
- }}>↑
+
+ customScrollTo(e, `src-${note._key}`)}
+ on:keydown={(e) => {
+ if (e.code === 'Space' || e.code === 'Enter') {
+ customScrollTo(e, `src-${note._key}`);
+ }
+ }}
+ >
+
+
+
+
+
+
+
+
{/each}
diff --git a/svelte-app/src/components/portable-text/serializers/custom-heading.svelte b/svelte-app/src/components/portable-text/serializers/custom-heading.svelte
index ea96027e6..34c9f39cf 100644
--- a/svelte-app/src/components/portable-text/serializers/custom-heading.svelte
+++ b/svelte-app/src/components/portable-text/serializers/custom-heading.svelte
@@ -1,29 +1,47 @@
diff --git a/svelte-app/src/components/portable-text/serializers/image.svelte b/svelte-app/src/components/portable-text/serializers/image.svelte
index 0eb3da22f..6c4f24e26 100644
--- a/svelte-app/src/components/portable-text/serializers/image.svelte
+++ b/svelte-app/src/components/portable-text/serializers/image.svelte
@@ -13,5 +13,5 @@
-
+
diff --git a/svelte-app/src/components/sidebar.svelte b/svelte-app/src/components/sidebar.svelte
new file mode 100644
index 000000000..9a7b9993c
--- /dev/null
+++ b/svelte-app/src/components/sidebar.svelte
@@ -0,0 +1,152 @@
+
+
+
+
+
+ {#if config.image}
+
+ {/if}
+
+
+ {name}
+
+ {#if config.handle}
+
+ {config.handle}
+
+ {/if}
+
+
+
+ {#if config.bio && socials}
+
+ {#if config.bio}
+
+ {config.bio}
+
+ {/if}
+ {#if socials}
+
+ {#each socials as social}
+ -
+ {#if social.url.includes('mailto')}
+
+
+ {:else}
+
+
+ {/if}
+
+ {social.name}
+
+
+ {/each}
+
+ {/if}
+
+ {/if}
+
+
+
+
+
+
+
+
+
+
+
+ {#if config.enableToru}
+
+ {/if}
+
+ {#if APP_VERSION?.length}
+
+ {/if}
+
diff --git a/svelte-app/src/components/sidebar/profile-image.svelte b/svelte-app/src/components/sidebar/profile-image.svelte
new file mode 100644
index 000000000..0ba4bfc87
--- /dev/null
+++ b/svelte-app/src/components/sidebar/profile-image.svelte
@@ -0,0 +1,25 @@
+
+
+
diff --git a/svelte-app/src/components/sidebar/sidebar-block.svelte b/svelte-app/src/components/sidebar/sidebar-block.svelte
new file mode 100644
index 000000000..da302b1b1
--- /dev/null
+++ b/svelte-app/src/components/sidebar/sidebar-block.svelte
@@ -0,0 +1,135 @@
+
+
+{#if $isDesktop && $sidebarBlock}
+
+
+
+ {$t('Reading')} — {estRemainingTime} {$t(
+ estRemainingTime === 1 ? 'min left' : 'mins left'
+ )}
+
+
+
+ {title}
+
+
+ {#if tags?.length}
+
+ {/if}
+
+ {#if desc}
+
+ {desc}
+
+ {/if}
+
+ {#if $sidebarHeadings}
+
+ {$t('Summary')}
+
+
+
+
+ {/if}
+
+
+{/if}
diff --git a/svelte-app/src/components/sidebar/sidebar-headings.svelte b/svelte-app/src/components/sidebar/sidebar-headings.svelte
new file mode 100644
index 000000000..844ac9082
--- /dev/null
+++ b/svelte-app/src/components/sidebar/sidebar-headings.svelte
@@ -0,0 +1,35 @@
+
+
+{#each headings as heading}
+
+{/each}
diff --git a/svelte-app/src/components/sidebar/sidebar-link.svelte b/svelte-app/src/components/sidebar/sidebar-link.svelte
new file mode 100644
index 000000000..38a438c2c
--- /dev/null
+++ b/svelte-app/src/components/sidebar/sidebar-link.svelte
@@ -0,0 +1,91 @@
+
+
+
+
e.key === 'Enter' && handleAction(e)}
+>
+ {$t(link.name)}
+
+
+
+
+
diff --git a/svelte-app/src/components/sidebar/sidebar-tooltip.svelte b/svelte-app/src/components/sidebar/sidebar-tooltip.svelte
new file mode 100644
index 000000000..76c221a82
--- /dev/null
+++ b/svelte-app/src/components/sidebar/sidebar-tooltip.svelte
@@ -0,0 +1,42 @@
+
+
+
+
+ {title}
+
+
{description}
+
diff --git a/svelte-app/src/components/sidebar/tooltips.ts b/svelte-app/src/components/sidebar/tooltips.ts
new file mode 100644
index 000000000..b1d64b03a
--- /dev/null
+++ b/svelte-app/src/components/sidebar/tooltips.ts
@@ -0,0 +1,3 @@
+import { writable } from 'svelte/store';
+
+export const tooltipContent = writable({});
diff --git a/svelte-app/src/components/sidebar/toru.svelte b/svelte-app/src/components/sidebar/toru.svelte
new file mode 100644
index 000000000..bf91e6fd3
--- /dev/null
+++ b/svelte-app/src/components/sidebar/toru.svelte
@@ -0,0 +1,149 @@
+
+
+{#if $data && $isDesktop}
+
+
+
+ {#if playing}
+
+
+
+ {#each Array(4) as _}
+
+ {/each}
+
+
+ {/if}
+
+
+
+
+ {$t(playing ? 'toru.status.playing' : 'toru.status.paused')}
+
+
+
+ {title ?? 'Unknown title'}
+
+
+
+ {artist ?? ''}
+ {artist && album ? '—' : ''}
+ {album ?? ''}
+
+
+
+
+
+
+{/if}
+
+
diff --git a/svelte-app/src/components/experiments/toru.ts b/svelte-app/src/components/sidebar/toru.ts
similarity index 65%
rename from svelte-app/src/components/experiments/toru.ts
rename to svelte-app/src/components/sidebar/toru.ts
index c573aaa21..7ee95039b 100644
--- a/svelte-app/src/components/experiments/toru.ts
+++ b/svelte-app/src/components/sidebar/toru.ts
@@ -1,3 +1,5 @@
+import { writable } from 'svelte/store';
+
import { browser } from '$app/environment';
import Logger from '$lib/logger';
@@ -20,6 +22,8 @@ let socketInstance: WebSocket | undefined,
const interval = 36_000;
+export const data = writable
(undefined);
+
const onOpen = () => {
Logger.info('[ToruSync] Connected');
retries = 0;
@@ -27,33 +31,32 @@ const onOpen = () => {
const onClose = () => {
Logger.info('[ToruSync] Disconnected');
- stop();
+ // stop();
};
const onError = (e: Event) => {
Logger.error('[ToruSync] Error', e);
};
-const onMessage =
- (onUpdate: (data: ToruData) => void) => (e: MessageEvent) => {
- if (!e.data || e.data === 'pong') {
- return;
- }
+const onMessage = (e: MessageEvent) => {
+ if (!e.data || e.data === 'pong') {
+ return;
+ }
- try {
- const res = JSON.parse(e.data as string) as ToruData;
+ try {
+ const res = JSON.parse(e.data as string) as ToruData;
- Logger.info('[ToruSync] Received frame');
+ Logger.info('[ToruSync] Received frame');
- if (res.title || res.album || res.artist) {
- onUpdate(res);
- }
- } catch (e) {
- Logger.error('[ToruSync] Error parsing', e);
+ if (res.title || res.album || res.artist) {
+ data.set(res);
}
- };
+ } catch (e) {
+ Logger.error('[ToruSync] Error parsing', e);
+ }
+};
-export const initSync = (onUpdate: (data: ToruData) => void) => {
+export const initSync = () => {
if (!browser || (socketInstance && socketInstance.readyState === WebSocket.OPEN)) {
return;
}
@@ -63,7 +66,7 @@ export const initSync = (onUpdate: (data: ToruData) => void) => {
socketInstance = new WebSocket('wss://toru.kio.dev/api/v1/ws/kiosion?cover_size=large');
socketInstance.addEventListener('open', onOpen);
- socketInstance.addEventListener('message', onMessage(onUpdate));
+ socketInstance.addEventListener('message', onMessage);
socketInstance.addEventListener('error', onError);
socketInstance.addEventListener('close', onClose);
@@ -74,19 +77,22 @@ export const initSync = (onUpdate: (data: ToruData) => void) => {
}, interval);
};
-export const stopSync = (onUpdate: (data: ToruData) => void) => {
+export const stopSync = () => {
if (!browser || !socketInstance) {
return;
}
clearInterval(repeat);
- if (socketInstance.readyState !== WebSocket.CLOSED) {
+ if (
+ socketInstance.readyState === WebSocket.OPEN ||
+ socketInstance.readyState === WebSocket.CONNECTING
+ ) {
socketInstance.close();
}
socketInstance.removeEventListener('open', onOpen);
- socketInstance.removeEventListener('message', onMessage(onUpdate));
+ socketInstance.removeEventListener('message', onMessage);
socketInstance.removeEventListener('error', onError);
socketInstance.removeEventListener('close', onClose);
diff --git a/svelte-app/src/components/tooltips/inner.svelte b/svelte-app/src/components/tooltips/inner.svelte
index 2b9189b54..ce31f3261 100644
--- a/svelte-app/src/components/tooltips/inner.svelte
+++ b/svelte-app/src/components/tooltips/inner.svelte
@@ -1,144 +1,121 @@
-
- {content.trim().length >= MAX_LENGTH
- ? `${content.trim().slice(0, MAX_LENGTH - 3)}...`
- : content.trim()}
+
+
+ {#if showArrow}
+
+ {/if}
diff --git a/svelte-app/src/components/tooltips/manager.svelte b/svelte-app/src/components/tooltips/manager.svelte
deleted file mode 100644
index 390f45760..000000000
--- a/svelte-app/src/components/tooltips/manager.svelte
+++ /dev/null
@@ -1,11 +0,0 @@
-
-
-{#each $tooltips as tooltip (tooltip.id)}
-
-{/each}
diff --git a/svelte-app/src/components/tooltips/tooltip.svelte b/svelte-app/src/components/tooltips/tooltip.svelte
index 2dbf1b0fd..c9b3ff783 100644
--- a/svelte-app/src/components/tooltips/tooltip.svelte
+++ b/svelte-app/src/components/tooltips/tooltip.svelte
@@ -1,51 +1,47 @@
+
+{#if active && target}
+ fade(node, { ...(args ?? {}), easing: cubicInOut })
+ : (node, args) => fly(node, { ...(args ?? {}), easing: cubicInOut, x: 4 })}
+ {duration}
+ {placement}
+ {offset}
+ {target}
+ {showArrow}
+ {followCursor}
+ className={content &&
+ 'bg-neutral-600 font-mono text-xs text-light dark:bg-neutral-100 dark:text-dark whitespace-nowrap rounded-md'}
+ >
+ {#if content}
+ {content}
+ {:else}
+
+ {/if}
+
+{/if}
diff --git a/svelte-app/src/languages/en.json b/svelte-app/src/languages/en.json
index 052b8c353..1cf315c3e 100644
--- a/svelte-app/src/languages/en.json
+++ b/svelte-app/src/languages/en.json
@@ -11,9 +11,12 @@
"Click here to": "Click here to",
"Code block": "Code block",
"Code content": "Code content",
+ "Contents": "Contents",
"Copied": "Copied",
"Copy": "Copy",
"Copy to clipboard": "Copy to clipboard",
+ "Copy {value}": "Copy {value}",
+ "Dark": "Dark",
"Date posted": "Date posted",
"Duration": "Duration",
"English": "English",
@@ -22,44 +25,48 @@
"Experiments": "Experiments",
"Footnotes": "Footnotes",
"French": "French",
+ "Go back": "Go back",
"Go to footnote": "Go to footnote",
"Go to footnote source": "Go to footnote source",
- "Hide stack trace": "Hide stack trace",
"Home": "Home",
"Internal Error": "Internal Error",
"Invalid date": "Invalid date",
"Language": "Language",
- "Lights off": "Lights off",
- "Lights on": "Lights on",
+ "Light": "Light",
"Links": "Links",
"Meta": "Meta",
"More": "More",
"No content": "No content",
"PGP": "PGP",
"Page content": "Page content",
+ "Pages": "Pages",
"Please": "Please",
"Post": "Post",
"Posts": "Posts",
"Project": "Project",
"Projects": "Projects",
"Read more": "Read more",
+ "Reading": "Reading",
"Recent projects": "Recent projects",
"Recent thoughts": "Recent thoughts",
+ "Reload page": "Reload page",
"Say hello": "Say hello",
"See more": "See more",
- "Show stack trace": "Show stack trace",
"Show {amount}": "Show {amount}",
"Skip to content": "Skip to content",
"Social": "Social",
"Social links": "Social links",
"Sorry, something went wrong. Please try again.": "Sorry, something went wrong. Please try again.",
+ "Summary": "Summary",
"Switch to English": "Switch to English",
"Switch to French": "Switch to French",
+ "Switch to {opt}": "Switch to {opt}",
"Tags": "Tags",
"Theme": "Theme",
"Thoughts": "Thoughts",
"Topic": "Topic",
"Topics": "Topics",
+ "Uncategorized": "Uncategorized",
"Unknown date": "Unknown date",
"Use dark mode": "Use dark mode",
"Use light mode": "Use light mode",
@@ -98,8 +105,9 @@
"message": "No content."
}
},
- "go back": "go back",
"less": "less",
+ "min left": "min left",
+ "mins left": "mins left",
"more": "more",
"now": "now",
"pages": {
@@ -130,8 +138,15 @@
},
"present": "present",
"refresh the page": "refresh the page",
+ "toru": {
+ "status": {
+ "playing": "Listening to",
+ "paused": "Last listened to"
+ }
+ },
"{document} details": "{document} details",
"{length} min read": "{length} min read",
+ "{length} words": "{length} words",
"{months} months": "{months} months",
"{month} month": "{month} month",
"{stars} stars": "{stars} stars",
diff --git a/svelte-app/src/languages/fr.json b/svelte-app/src/languages/fr.json
index ece73181e..ef59ebb6e 100644
--- a/svelte-app/src/languages/fr.json
+++ b/svelte-app/src/languages/fr.json
@@ -11,9 +11,12 @@
"Click here to": "Cliquez ici pour",
"Code block": "Bloc de code",
"Code content": "Contenu du code",
+ "Contents": "Sommaire",
"Copied": "Copié",
"Copy": "Copier",
"Copy to clipboard": "Copier dans le presse-papiers",
+ "Copy {value}": "Copier {value}",
+ "Dark": "Sombre",
"Date posted": "Date de publication",
"Duration": "Durée",
"English": "Anglais",
@@ -22,44 +25,48 @@
"Experiments": "Expériences",
"Footnotes": "Notes de bas de page",
"French": "Français",
+ "Go back": "Retour",
"Go to footnote": "Aller à la note de bas de page",
"Go to footnote source": "Aller à la source de la note de bas de page",
- "Hide stack trace": "Masquer la trace de la pile",
"Home": "Accueil",
"Internal Error": "Erreur interne",
"Invalid date": "Date invalide",
"Language": "Langue",
- "Lights off": "Lumières éteintes",
- "Lights on": "Lumières allumées",
+ "Light": "Clair",
"Links": "Liens",
"Meta": "Plus",
"More": "Plus",
"No content": "Pas de contenu",
"PGP": "PGP",
"Page content": "Contenu de la page",
+ "Pages": "Pages",
"Please": "S'il vous plaît",
"Post": "Article",
"Posts": "Articles",
"Project": "Projet",
"Projects": "Projets",
"Read more": "Lire la suite",
+ "Reading": "Lecture",
"Recent projects": "Projets récents",
"Recent thoughts": "Pensées récentes",
+ "Reload page": "Recharger la page",
"Say hello": "Dire bonjour",
"See more": "Voir plus",
- "Show stack trace": "Afficher la trace de la pile",
"Show {amount}": "Afficher {amount}",
"Skip to content": "Passer au contenu",
"Social": "Social",
"Social links": "Liens sociaux",
"Sorry, something went wrong. Please try again.": "Désolé, quelque chose s'est mal passé. Veuillez réessayer.",
+ "Summary": "Résumé",
"Switch to English": "Passer à l'Anglais",
"Switch to French": "Passer au Français",
+ "Switch to {opt}": "Passer à {opt}",
"Tags": "Tags",
"Theme": "Thème",
"Thoughts": "Pensées",
"Topic": "Sujet",
"Topics": "Sujets",
+ "Uncategorized": "Non classé",
"Unknown date": "Date inconnue",
"Use dark mode": "Utiliser le mode sombre",
"Use light mode": "Utiliser le mode clair",
@@ -98,8 +105,9 @@
"message": "Pas de contenu."
}
},
- "go back": "retourner",
"less": "moins",
+ "min left": "min rest",
+ "mins left": "mins rest",
"more": "plus",
"now": "maintenant",
"pages": {
@@ -130,8 +138,15 @@
},
"present": "présent",
"refresh the page": "rafraîchir la page",
+ "toru": {
+ "status": {
+ "playing": "Écoute de",
+ "paused": "Dernièrement écouté"
+ }
+ },
"{document} details": "Détails de {document}",
"{length} min read": "{length} minute de lecture",
+ "{length} words": "{length} mots",
"{months} months": "{months} mois",
"{month} month": "{month} mois",
"{stars} stars": "{stars} étoiles",
diff --git a/svelte-app/src/lib/consts.ts b/svelte-app/src/lib/consts.ts
index df8c4f526..dfdbbb37e 100644
--- a/svelte-app/src/lib/consts.ts
+++ b/svelte-app/src/lib/consts.ts
@@ -57,13 +57,17 @@ export const APP_ROUTES = [
path: '/etc',
hidden: false
}
-] as AppRoute[];
+] as const satisfies AppRoute[];
export const TOP_LEVEL_ROUTES = APP_ROUTES.map((r) => {
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
- const { children, ...rest } = r;
+ if (!('children' in r)) {
+ return r;
+ }
+
+ const { children: _children, ...rest } = r;
+
return rest;
-}) as Omit[];
+}) satisfies Omit[];
export const ROUTE_ORDER = [
'/',
@@ -92,8 +96,8 @@ export const ERRORS = {
export const BASE_TRANSITION_DURATION = 200 as const;
export const BASE_ANIMATION_DURATION = 300 as const;
-export const HOMEPAGE_POSTS_NUM = 3 as const;
-export const HOMEPAGE_PROJECTS_NUM = 3 as const;
+export const HOMEPAGE_POSTS_NUM = 4 as const;
+export const HOMEPAGE_PROJECTS_NUM = 4 as const;
export const RECENT_POSTS_COUNT = 99;
export const RECENT_PROJECTS_COUNT = 99;
diff --git a/svelte-app/src/lib/i18n.ts b/svelte-app/src/lib/i18n.ts
index b16e41e51..97001effc 100644
--- a/svelte-app/src/lib/i18n.ts
+++ b/svelte-app/src/lib/i18n.ts
@@ -90,9 +90,10 @@ const _translate = (
key: K,
params?: ExtractTVars extends never
? never
- : Record, string | number>
+ : Record, string | number>,
+ overrideLang?: string
): string => {
- const lang = currentLang || DEFAULT_APP_LANG;
+ const lang = overrideLang || currentLang || DEFAULT_APP_LANG;
// For any provided params, replace the corresponding placeholders if any
// e.g. "Hello {name}" with { name: "World" } becomes "Hello World"
@@ -123,7 +124,8 @@ const translate = derived<
key: K,
params?: ExtractTVars extends never
? never
- : Record, string | number>
+ : Record, string | number>,
+ overrideLang?: string
) => string
>(
currentLang,
@@ -132,9 +134,10 @@ const translate = derived<
key: K,
params?: ExtractTVars extends never
? never
- : Record, string | number>
+ : Record, string | number>,
+ overrideLang?: string
) =>
- _translate(val, key, params)
+ _translate(val, key, params, overrideLang)
);
const addSearchParams = (path: string, params?: URLSearchParams): string => {
diff --git a/svelte-app/src/lib/route-trie.ts b/svelte-app/src/lib/route-trie.ts
index d893ebc24..8c99274ec 100644
--- a/svelte-app/src/lib/route-trie.ts
+++ b/svelte-app/src/lib/route-trie.ts
@@ -23,7 +23,7 @@ export default class RouteTrie {
}
search(route: string): number | null {
- let node = this.root;
+ const node = this.root;
const parts = route.split('/').filter(Boolean);
let bestMatchIndex: number | null = null;
let bestMatchDepth = -1;
@@ -33,7 +33,9 @@ export default class RouteTrie {
bestMatchIndex = node.index;
bestMatchDepth = depth;
}
- if (depth >= parts.length) return;
+ if (depth >= parts.length) {
+ return;
+ }
const part = parts[depth];
if (node.children[part]) {
diff --git a/svelte-app/src/lib/sanity.ts b/svelte-app/src/lib/sanity.ts
index d32e2fc09..00fb872f4 100644
--- a/svelte-app/src/lib/sanity.ts
+++ b/svelte-app/src/lib/sanity.ts
@@ -5,6 +5,7 @@ import imageUrlBuilder from '@sanity/image-url';
import type { ImageUrlBuilder } from '@sanity/image-url/lib/types/builder';
import type {
FitMode,
+ ImageFormat,
SanityClientLike,
SanityImageObject,
SanityImageSource
@@ -63,6 +64,7 @@ type baseBuildImageUrlOptions = {
height?: number;
blur?: number;
fit?: FitMode;
+ format?: ImageFormat;
};
type buildImageUrlOptions = baseBuildImageUrlOptions &
@@ -78,7 +80,7 @@ type buildImageUrlOptions = baseBuildImageUrlOptions &
);
export const buildImageUrl = (
- { baseUrl, ref, crop, width, height, blur, fit }: buildImageUrlOptions = {
+ { baseUrl, ref, crop, width, height, blur, fit, format }: buildImageUrlOptions = {
baseUrl: undefined
} as buildImageUrlOptions
) => {
@@ -102,5 +104,10 @@ export const buildImageUrl = (
} else if (crop) {
baseUrl = baseUrl.fit('crop');
}
- return baseUrl.auto('format').url();
+ if (format) {
+ baseUrl = baseUrl.format(format);
+ } else {
+ baseUrl = baseUrl.auto('format');
+ }
+ return baseUrl.url();
};
diff --git a/svelte-app/src/lib/sidebar.ts b/svelte-app/src/lib/sidebar.ts
new file mode 100644
index 000000000..fd2f3e168
--- /dev/null
+++ b/svelte-app/src/lib/sidebar.ts
@@ -0,0 +1,16 @@
+/* eslint-disable func-call-spacing */
+import { writable } from 'svelte/store';
+
+import type { PostDocument, ProjectDocument } from '$types';
+
+type SidebarBlockContent = Pick<
+ PostDocument | ProjectDocument,
+ 'title' | 'desc' | 'tags' | 'date' | 'estimatedReadingTime' | 'views'
+ // eslint-disable-next-line @typescript-eslint/ban-types
+> & {};
+
+export const sidebarBlock = writable(undefined);
+
+export const sidebarHeadings = writable<
+ (PostDocument | ProjectDocument)['headings'] | undefined
+>(undefined);
diff --git a/svelte-app/src/lib/tooltips.ts b/svelte-app/src/lib/tooltips.ts
deleted file mode 100644
index 3b05eecad..000000000
--- a/svelte-app/src/lib/tooltips.ts
+++ /dev/null
@@ -1,61 +0,0 @@
-import { writable } from 'svelte/store';
-
-type BasicPlacement = 'top' | 'bottom' | 'left' | 'right';
-
-type Placement = BasicPlacement | `${BasicPlacement}-start` | `${BasicPlacement}-end`;
-
-export type Tooltip = {
- id: number;
- content: string;
- duration: number;
- placement: Placement;
- followCursor: boolean;
- target: HTMLElement;
- offset: [number, number];
- delay: number;
-};
-
-const tooltips = writable([]);
-
-const createTooltip = (data: Tooltip) => {
- tooltips.update((t) => {
- const existing = t.findIndex(
- (tooltip) => tooltip.id === data.id || tooltip.target === data.target
- );
- if (existing !== -1) {
- t.splice(existing, 1);
- }
- t.push(data);
- return t;
- });
- return data.id;
-};
-
-const updateTooltip = (
- id: number,
- data: Partial>
-) => {
- tooltips.update((t) => {
- const existing = t.findIndex((tooltip) => tooltip.id === id);
- if (existing !== -1) {
- t[existing] = { ...t[existing], ...data };
- }
- return t;
- });
-};
-
-const destroyTooltip = (id: number) => {
- tooltips.update((t) => {
- const filtered = [];
-
- for (let i = 0; i < t.length; ++i) {
- if (t[i].id !== id) {
- filtered.push(t[i]);
- }
- }
-
- return filtered;
- });
-};
-
-export { createTooltip, destroyTooltip, tooltips, updateTooltip };
diff --git a/svelte-app/src/lib/utils.ts b/svelte-app/src/lib/utils.ts
index c08c206cb..6ed02f160 100644
--- a/svelte-app/src/lib/utils.ts
+++ b/svelte-app/src/lib/utils.ts
@@ -1,10 +1,10 @@
// Misc utils that don't fit anywhere else
import { derived, get } from 'svelte/store';
+import { ROUTE_ORDER } from '$lib/consts';
import { currentLang, isLocalized } from '$lib/i18n';
import Logger from '$lib/logger';
import RouteTrie from '$lib/route-trie';
-import { ROUTE_ORDER } from '$lib/consts';
const _parseViews = (views: number | undefined, lang: string) => {
if (!views || views < 1) {
diff --git a/svelte-app/src/routes/+error.svelte b/svelte-app/src/routes/+error.svelte
index b9ba25635..4dcc84bcc 100644
--- a/svelte-app/src/routes/+error.svelte
+++ b/svelte-app/src/routes/+error.svelte
@@ -1,14 +1,17 @@
+
kio.dev | {status}
-
-
-
+
+
+
+ window.history.length > 2 ? window.history.back() : goto($linkTo('/'))}
+ />
+ window.location.reload()}
+ type="button"
+ >
+
+
+ {$t('Reload page')}
+
+
+
+
+
+ {heading}
+
+
{$page.error?.message && $page.status !== 404 ? $page.error.message : $t(message)}
-
- {$t('Please')}
- window.history.back()}>{$t('go back')}, or window.location.reload()}>{$t('refresh the page')}.
-
-
-
- {#if causes?.length}
-
-
-
(showStack = !showStack)}
- />
-
- {#if showStack}
-
-
-
{#each causes as cause, i}{cause?.trim?.()}{#if i < causes.length - 1}
{/if}{/each}
-
-
+ type="button"
+ >
+ {#if showStack}
+
+
+ {:else}
+
+
+ {/if}
+ {$t('Show {amount}', { amount: $t(showStack ? 'less' : 'more') })}
+
{/if}
+
+
+ {#if showStack}
+
+
{#each causes as cause, i}{cause?.trim?.()}{#if i < causes.length - 1}
{/if}{/each}
+
{/if}
diff --git a/svelte-app/src/routes/+layout.svelte b/svelte-app/src/routes/+layout.svelte
index be6291695..f7a7fff40 100644
--- a/svelte-app/src/routes/+layout.svelte
+++ b/svelte-app/src/routes/+layout.svelte
@@ -21,18 +21,15 @@
import { check as checkTranslations, currentLang, isLocalized, t } from '$lib/i18n';
import Settings, { listenForMQLChange, loading } from '$lib/settings';
- import Footer from '$components/footer.svelte';
- import Header from '$components/header.svelte';
import PageTransition from '$components/layouts/page-transition.svelte';
- import ScrollContainer from '$components/layouts/scroll-container.svelte';
- import TooltipManager from '$components/tooltips/manager.svelte';
+ import Sidebar from '$components/sidebar.svelte';
import type { Unsubscriber } from 'svelte/store';
let unsubscribers = [] as Unsubscriber[],
HighlightStyles: string | undefined,
setLoadingTimer: ReturnType | undefined,
- scrollShadow = { top: false, bottom: false };
+ scrollContainer: HTMLElement | null;
const { theme } = Settings,
skipToContent = (e: KeyboardEvent) => {
@@ -149,22 +146,20 @@
on:keydown={skipToContent}>{$t('Skip to content')}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
diff --git a/svelte-app/src/routes/+layout.ts b/svelte-app/src/routes/+layout.ts
index c03291472..dccf4cb45 100644
--- a/svelte-app/src/routes/+layout.ts
+++ b/svelte-app/src/routes/+layout.ts
@@ -1,4 +1,4 @@
-import { DEFAULT_APP_LANG } from '$lib/consts';
+import { DEFAULT_APP_LANG, TORU_API_URL } from '$lib/consts';
import { ENV } from '$lib/env';
import Logger from '$lib/logger';
import { findOne } from '$lib/store';
@@ -6,6 +6,7 @@ import { findOne } from '$lib/store';
import { error } from '@sveltejs/kit';
import type { LayoutLoad } from './$types';
+import type { ToruData } from '$components/sidebar/toru';
import type { SiteConfig } from '$types';
export const trailingSlash = 'ignore';
@@ -19,13 +20,38 @@ export const load = (async ({ params, url, fetch }) => {
Logger.error('Failed to load layout data:', e);
throw error(500, {
message: 'Sorry, something went wrong during load.',
+ // @ts-expect-error - Overriding base type
cause: e?.cause,
stack: e?.stack
});
})) as SiteConfig;
+ const toruData = (
+ config.enableToru
+ ? (fetch(`${TORU_API_URL}/kiosion?res=json&cover_size=medium`)
+ .then((res) => {
+ if (!res.ok) {
+ throw new Error('Failed to fetch now playing data');
+ }
+
+ return res
+ .json()
+ .then((data) => data.data)
+ .catch((e) => {
+ throw new Error('Failed to parse now playing data', e);
+ });
+ })
+ .catch((e) => {
+ Logger.error(e);
+
+ return undefined;
+ }) as Promise
)
+ : Promise.resolve(undefined)
+ ) satisfies Promise;
+
return {
pathname: url.pathname,
+ toruData,
config
};
}) satisfies LayoutLoad;
diff --git a/svelte-app/src/routes/[[lang=lang]]/+page.svelte b/svelte-app/src/routes/[[lang=lang]]/+page.svelte
index b0e96b17b..562fbe227 100644
--- a/svelte-app/src/routes/[[lang=lang]]/+page.svelte
+++ b/svelte-app/src/routes/[[lang=lang]]/+page.svelte
@@ -1,12 +1,11 @@
@@ -26,14 +24,20 @@
-
-
+
+
+
-
+
-
+
-
+
-
-
+
+
+
diff --git a/svelte-app/src/routes/[[lang=lang]]/experiments/+page.ts b/svelte-app/src/routes/[[lang=lang]]/experiments/+page.ts
deleted file mode 100644
index 53dc5a2ee..000000000
--- a/svelte-app/src/routes/[[lang=lang]]/experiments/+page.ts
+++ /dev/null
@@ -1,28 +0,0 @@
-import { TORU_API_URL } from '$lib/consts';
-import Logger from '$lib/logger';
-
-import type { PageLoad } from './$types';
-import type { ToruData } from '$components/experiments/toru';
-
-export const load = (({ fetch }) => {
- const nowPlayingData = fetch(`${TORU_API_URL}/kiosion?res=json&cover_size=medium`)
- .then((res) => {
- if (!res.ok) {
- throw new Error('Failed to fetch now playing data');
- }
-
- return res
- .json()
- .then((data) => data.data)
- .catch((e) => {
- throw new Error('Failed to parse now playing data', e);
- });
- })
- .catch((e) => {
- Logger.error(e);
-
- return undefined;
- }) satisfies Promise;
-
- return { fetch, nowPlayingData };
-}) satisfies PageLoad;
diff --git a/svelte-app/src/routes/[[lang=lang]]/thoughts/+/+page.svelte b/svelte-app/src/routes/[[lang=lang]]/thoughts/+/+page.svelte
index 8204b0aef..0352ce762 100644
--- a/svelte-app/src/routes/[[lang=lang]]/thoughts/+/+page.svelte
+++ b/svelte-app/src/routes/[[lang=lang]]/thoughts/+/+page.svelte
@@ -4,80 +4,59 @@
import ArrowButton from '$components/controls/arrow-button.svelte';
import EmptyContent from '$components/empty-content.svelte';
import HeadedBlock from '$components/headings/headed-block.svelte';
- import Hoverable from '$components/hoverable.svelte';
+ import BaseContainer from '$components/layouts/base-container.svelte';
export let data;
-
-
-
-
+
+
+
+ {data.tags?.length ?? 0}
+ {$t('Topics').toLowerCase()}
+
+
+
- {#if data.tags?.length}
-
+ {:else}
+
+ {/if}
+
+
+
diff --git a/svelte-app/src/routes/[[lang=lang]]/thoughts/+/[slug]/+page.svelte b/svelte-app/src/routes/[[lang=lang]]/thoughts/+/[slug]/+page.svelte
index 99a75b958..23efb5741 100644
--- a/svelte-app/src/routes/[[lang=lang]]/thoughts/+/[slug]/+page.svelte
+++ b/svelte-app/src/routes/[[lang=lang]]/thoughts/+/[slug]/+page.svelte
@@ -3,34 +3,36 @@
import ArrowButton from '$components/controls/arrow-button.svelte';
import EmptyContent from '$components/empty-content.svelte';
- import HeadedBlock from '$components/headings/headed-block.svelte';
+ import BaseContainer from '$components/layouts/base-container.svelte';
import DocumentList from '$components/lists/document-list.svelte';
export let data;
-
-
-
-
- {$t('Topic').toLowerCase()}:
- {data.tag.title}
-
-
+
+
+
+ #
+ {data.tag.title.toLowerCase()}
-
- {#if data.posts?.length}
-
- {:else}
-
- {/if}
-
+
+
+
+
+ {#if data.posts?.length}
+
+ {:else}
+
+ {/if}
+
+
diff --git a/svelte-app/src/routes/[[lang=lang]]/thoughts/+page.svelte b/svelte-app/src/routes/[[lang=lang]]/thoughts/+page.svelte
index d97a2df2d..17d9fabec 100644
--- a/svelte-app/src/routes/[[lang=lang]]/thoughts/+page.svelte
+++ b/svelte-app/src/routes/[[lang=lang]]/thoughts/+page.svelte
@@ -4,7 +4,7 @@
import ArrowButton from '$components/controls/arrow-button.svelte';
import EmptyContent from '$components/empty-content.svelte';
- import HeadedBlock from '$components/headings/headed-block.svelte';
+ import BaseContainer from '$components/layouts/base-container.svelte';
import DocumentList from '$components/lists/document-list.svelte';
import type { DocumentTags } from '$types';
@@ -13,7 +13,7 @@
$: description = $t('pages.thoughts.description');
- const MAX_TAGS = 6;
+ const MAX_TAGS = 5;
const tags: DocumentTags[] = [],
tagCounts: Record
= {};
@@ -68,54 +68,44 @@
-
- {#if data.posts.length}
- {#if tags.length}
-
-
(
-
- {#each tags as tag, i}
- {#if i < MAX_TAGS}
-
-
- {tag.title.toLowerCase()}{#if i < MAX_TAGS && i < tags.length - 1},{/if}
+
+
+
+ {tagCounts[tag._id]}
+ {$t(tagCounts[tag._id] === 1 ? 'Post' : 'Posts').toLowerCase()}
+
+ {/if}
+ {/each}
+
+
+
+
+
+ {#if data.posts.length}
+
+ {:else}
+
{/if}
-
-
- {:else}
-
- {/if}
-
+
+
diff --git a/svelte-app/src/routes/[[lang=lang]]/thoughts/[slug]/+page.svelte b/svelte-app/src/routes/[[lang=lang]]/thoughts/[slug]/+page.svelte
index 701e5ae4f..01057f350 100644
--- a/svelte-app/src/routes/[[lang=lang]]/thoughts/[slug]/+page.svelte
+++ b/svelte-app/src/routes/[[lang=lang]]/thoughts/[slug]/+page.svelte
@@ -4,4 +4,4 @@
export let data;
-
+
diff --git a/svelte-app/src/routes/[[lang=lang]]/thoughts/[slug]/+page.ts b/svelte-app/src/routes/[[lang=lang]]/thoughts/[slug]/+page.ts
index 133651394..d16119e15 100644
--- a/svelte-app/src/routes/[[lang=lang]]/thoughts/[slug]/+page.ts
+++ b/svelte-app/src/routes/[[lang=lang]]/thoughts/[slug]/+page.ts
@@ -16,7 +16,9 @@ export const load = (async ({ parent, fetch, params, url }) => {
const post =
// in some cases _parent isn't defined during SSR...?
- (!preview && _parent?.posts?.find?.((post) => post.slug?.current === params.slug)) ||
+ (!preview &&
+ opts.lang === DEFAULT_APP_LANG &&
+ _parent?.posts?.find?.((post) => post.slug?.current === params.slug)) ||
handleLoadError(await findOne(fetch, 'post', opts));
post && incViews(fetch, post);
diff --git a/svelte-app/src/routes/[[lang=lang]]/work/+page.svelte b/svelte-app/src/routes/[[lang=lang]]/work/+page.svelte
index 11a011c57..42dee818a 100644
--- a/svelte-app/src/routes/[[lang=lang]]/work/+page.svelte
+++ b/svelte-app/src/routes/[[lang=lang]]/work/+page.svelte
@@ -3,10 +3,10 @@
import { pageTitle } from '$lib/navigation';
import Timeline from '$components/about/timeline.svelte';
- import Divider from '$components/divider.svelte';
import EmptyContent from '$components/empty-content.svelte';
import HeadedBlock from '$components/headings/headed-block.svelte';
- import DocumentList from '$components/lists/document-list.svelte';
+ import BaseContainer from '$components/layouts/base-container.svelte';
+ import ListItem from '$components/lists/list-item.svelte';
export let data;
@@ -26,20 +26,32 @@
-
- {#if data.config?.timeline?.length}
-
- {:else}
-
-
-
- {/if}
-
-
-{#if data.projects.length}
-
+
+
+
+ {#if data.config?.timeline?.length}
+
+ {:else}
+
+
+
+ {/if}
+
+
-
-
-
-{/if}
+ {#if data.projects.length}
+
+
+
+ {#each data.projects as project}
+
+ {/each}
+
+
+
+ {/if}
+
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 14e471bb3..d9bc2b43c 100644
--- a/svelte-app/src/routes/[[lang=lang]]/work/[slug]/+page.ts
+++ b/svelte-app/src/routes/[[lang=lang]]/work/[slug]/+page.ts
@@ -37,6 +37,7 @@ export const load = (async ({ parent, fetch, params, url }) => {
>,
project =
(!preview &&
+ opts.lang === DEFAULT_APP_LANG &&
_parent?.projects?.find?.((proj) => proj.slug?.current === params.slug)) ||
handleLoadError(await findOne(fetch, 'project', opts));
diff --git a/svelte-app/src/styles/_tw.scss b/svelte-app/src/styles/_tw.scss
index c4564ad36..2c5404ae5 100644
--- a/svelte-app/src/styles/_tw.scss
+++ b/svelte-app/src/styles/_tw.scss
@@ -29,7 +29,7 @@
@apply bg-neutral-800 text-light;
&.light {
- @apply bg-neutral-100 text-dark;
+ @apply bg-neutral-0 text-dark;
}
&:not(.is-loaded) {
diff --git a/svelte-app/tests/routes/error.test.ts b/svelte-app/tests/routes/error.test.ts
index ab1d12967..ba7c68c1c 100644
--- a/svelte-app/tests/routes/error.test.ts
+++ b/svelte-app/tests/routes/error.test.ts
@@ -24,7 +24,7 @@ test('handles config load error', async ({ context, page }) => {
timeout: 4000
});
- await page.click('text=See more');
+ await page.click('text=Show more');
expect(await page.textContent('[data-test-id="error-page"]')).toContain(
'Failed to fetch config data.'
@@ -46,7 +46,7 @@ test('handles project load error', async ({ context, page }) => {
timeout: 4000
});
- await page.click('text=See more');
+ await page.click('text=Show more');
expect(await page.textContent('[data-test-id="error-page"]')).toContain(
'404: Not Found'
@@ -71,7 +71,7 @@ test('handles post load error', async ({ context, page }) => {
timeout: 4000
});
- await page.click('text=See more');
+ await page.click('text=Show more');
expect(await page.textContent('[data-test-id="error-page"]')).toContain(
'404: Not Found'
diff --git a/svelte-app/tests/routes/index.test.ts b/svelte-app/tests/routes/index.test.ts
index 58f8c1b94..d92762f3d 100644
--- a/svelte-app/tests/routes/index.test.ts
+++ b/svelte-app/tests/routes/index.test.ts
@@ -48,7 +48,7 @@ test('should render error page on failed data fetch', async ({ context, page })
await page.waitForSelector('body.is-loaded');
expect(await page.waitForSelector('[data-test-id="error-page"]')).toBeTruthy();
- await page.click('text=See more');
+ await page.click('text=Show more');
expect(await page.textContent('[data-test-id="error-page"]')).toContain(
'Failed to fetch config data.'
);
diff --git a/svelte-app/tsconfig.json b/svelte-app/tsconfig.json
index 4694e4772..94f3b0412 100644
--- a/svelte-app/tsconfig.json
+++ b/svelte-app/tsconfig.json
@@ -12,6 +12,7 @@
"noEmit": true,
"removeComments": true,
"rootDir": "./",
+ "moduleResolution": "node",
"resolveJsonModule": true,
"skipLibCheck": true,
"sourceMap": true,
@@ -27,7 +28,5 @@
"*.js",
"*.ts"
],
- "exclude": [
- "**/node_modules"
- ]
+ "exclude": ["**/node_modules"]
}
diff --git a/svelte-app/types/app/config/index.ts b/svelte-app/types/app/config/index.ts
index 964cb9ba6..e45dfccc3 100644
--- a/svelte-app/types/app/config/index.ts
+++ b/svelte-app/types/app/config/index.ts
@@ -1,4 +1,9 @@
-import type { ArbitraryTypedObject, PortableTextBlock, SanityAsset } from '$types/sanity';
+import type {
+ ArbitraryTypedObject,
+ PortableTextBlock,
+ SanityAsset,
+ SanityImageObject
+} from '$types/sanity';
interface ContentSection extends SanityAsset {
title: string;
@@ -20,6 +25,14 @@ export type WorkTimelineItem = SanityAsset & {
};
export interface SiteConfig extends SanityAsset {
+ name: string;
+ image: SanityAsset & {
+ dark: SanityImageObject;
+ light: SanityImageObject;
+ };
+ handle?: string;
+ bio?: string;
+ enableToru?: boolean;
about: ContentSection[];
meta: ContentSection[];
timeline: WorkTimelineItem[];
diff --git a/svelte-app/types/generated/index.ts b/svelte-app/types/generated/index.ts
index a419a0b9e..2aff9aa23 100644
--- a/svelte-app/types/generated/index.ts
+++ b/svelte-app/types/generated/index.ts
@@ -11,9 +11,12 @@ export type LocaleKey =
| 'Click here to'
| 'Code block'
| 'Code content'
+ | 'Contents'
| 'Copied'
| 'Copy'
| 'Copy to clipboard'
+ | 'Copy {value}'
+ | 'Dark'
| 'Date posted'
| 'Duration'
| 'English'
@@ -22,44 +25,48 @@ export type LocaleKey =
| 'Experiments'
| 'Footnotes'
| 'French'
+ | 'Go back'
| 'Go to footnote'
| 'Go to footnote source'
- | 'Hide stack trace'
| 'Home'
| 'Internal Error'
| 'Invalid date'
| 'Language'
- | 'Lights off'
- | 'Lights on'
+ | 'Light'
| 'Links'
| 'Meta'
| 'More'
| 'No content'
| 'PGP'
| 'Page content'
+ | 'Pages'
| 'Please'
| 'Post'
| 'Posts'
| 'Project'
| 'Projects'
| 'Read more'
+ | 'Reading'
| 'Recent projects'
| 'Recent thoughts'
+ | 'Reload page'
| 'Say hello'
| 'See more'
- | 'Show stack trace'
| 'Show {amount}'
| 'Skip to content'
| 'Social'
| 'Social links'
| 'Sorry, something went wrong. Please try again.'
+ | 'Summary'
| 'Switch to English'
| 'Switch to French'
+ | 'Switch to {opt}'
| 'Tags'
| 'Theme'
| 'Thoughts'
| 'Topic'
| 'Topics'
+ | 'Uncategorized'
| 'Unknown date'
| 'Use dark mode'
| 'Use light mode'
@@ -82,8 +89,9 @@ export type LocaleKey =
| 'errors.unauthorized.message'
| 'errors.unauthorized.title'
| 'errors.no-content.message'
- | 'go back'
| 'less'
+ | 'min left'
+ | 'mins left'
| 'more'
| 'now'
| 'pages.about.description'
@@ -100,8 +108,11 @@ export type LocaleKey =
| 'pages.work.title'
| 'present'
| 'refresh the page'
+ | 'toru.status.playing'
+ | 'toru.status.paused'
| '{document} details'
| '{length} min read'
+ | '{length} words'
| '{months} months'
| '{month} month'
| '{stars} stars'