init elas atelier #1

Merged
nvrl merged 82 commits from ela into main 2026-05-18 13:55:42 +02:00
4 changed files with 27 additions and 4 deletions
Showing only changes of commit 2ace527c9f - Show all commits
@@ -6,6 +6,8 @@ const PAGE_SIZE = 9;
interface CoverImage { interface CoverImage {
url: string; url: string;
alt: string; alt: string;
w?: number;
h?: number;
} }
interface Post { interface Post {
@@ -135,7 +137,11 @@ export default function PostList({ posts: initialPosts, isAdmin = false }: Props
<img <img
src={post.cover_image!.url} src={post.cover_image!.url}
alt={post.cover_image!.alt || displayTitle} alt={post.cover_image!.alt || displayTitle}
width={post.cover_image!.w}
height={post.cover_image!.h}
loading={idx < 3 ? 'eager' : 'lazy'} loading={idx < 3 ? 'eager' : 'lazy'}
decoding={idx === 0 ? 'sync' : 'async'}
fetchPriority={idx === 0 ? 'high' : undefined}
/> />
) : ( ) : (
<div <div
+16 -2
View File
@@ -79,8 +79,22 @@ const KATEX_TAGS = [
'mpadded', 'menclose', 'mpadded', 'menclose',
]; ];
export function renderMarkdown(src: string): string { export interface ImageDim { w: number; h: number }
const html = renderer.parse(src, { async: false }) as string; export type ImageDims = Record<string, ImageDim>;
function injectDimensions(html: string, dims?: ImageDims): string {
if (!dims) return html;
return html.replace(/<img\s+src="([^"]+)"([^>]*?)\s*\/?>/g, (match, src, rest) => {
const d = dims[src];
if (!d) return match;
if (/\swidth\s*=/.test(rest) || /\sheight\s*=/.test(rest)) return match;
return `<img src="${src}" width="${d.w}" height="${d.h}"${rest} />`;
});
}
export function renderMarkdown(src: string, dims?: ImageDims): string {
let html = renderer.parse(src, { async: false }) as string;
html = injectDimensions(html, dims);
return DOMPurify.sanitize(html, { return DOMPurify.sanitize(html, {
ADD_TAGS: [...KATEX_TAGS, 'figure', 'figcaption'], ADD_TAGS: [...KATEX_TAGS, 'figure', 'figcaption'],
ADD_ATTR: ['aria-hidden', 'style', 'id', 'class', 'encoding', 'mathvariant', 'displaystyle', 'scriptlevel', 'loading'], ADD_ATTR: ['aria-hidden', 'style', 'id', 'class', 'encoding', 'mathvariant', 'displaystyle', 'scriptlevel', 'loading'],
+2
View File
@@ -9,6 +9,8 @@ const API_URL = process.env.PUBLIC_API_URL || 'http://localhost:3000';
interface CoverImage { interface CoverImage {
url: string; url: string;
alt: string; alt: string;
w?: number;
h?: number;
} }
interface Post { interface Post {
+3 -2
View File
@@ -8,7 +8,7 @@ import { renderMarkdown } from '../../lib/markdown';
const { slug } = Astro.params; const { slug } = Astro.params;
const API_URL = (typeof process !== 'undefined' ? process.env.PUBLIC_API_URL : import.meta.env.PUBLIC_API_URL) || 'http://localhost:3000'; const API_URL = (typeof process !== 'undefined' ? process.env.PUBLIC_API_URL : import.meta.env.PUBLIC_API_URL) || 'http://localhost:3000';
interface CoverImage { url: string; alt: string } interface CoverImage { url: string; alt: string; w?: number; h?: number }
interface PostNeighbor { interface PostNeighbor {
slug: string; slug: string;
title?: string; title?: string;
@@ -26,6 +26,7 @@ interface PostDetail {
image_count: number; image_count: number;
prev?: PostNeighbor; prev?: PostNeighbor;
next?: PostNeighbor; next?: PostNeighbor;
dimensions?: Record<string, { w: number; h: number }>;
} }
function formatDate(d: string) { function formatDate(d: string) {
@@ -45,7 +46,7 @@ try {
const postRes = await fetch(`${API_URL}/api/posts/${encodeURIComponent(slug ?? '')}`); const postRes = await fetch(`${API_URL}/api/posts/${encodeURIComponent(slug ?? '')}`);
if (postRes.ok) { if (postRes.ok) {
post = await postRes.json(); post = await postRes.json();
html = renderMarkdown(post!.content); html = renderMarkdown(post!.content, post!.dimensions);
} else { } else {
error = 'Work not found in the catalogue'; error = 'Work not found in the catalogue';
} }