From cf9cb0b12781a8def9529b71adc3b7bf4c9ba651 Mon Sep 17 00:00:00 2001 From: dev Date: Wed, 27 May 2026 20:26:55 +0200 Subject: [PATCH] demo(words): add image block to sample document + fix readPlainText (F3.11) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Sample document gains an image block between the code block and the table, showing figure/img/figcaption render in action. - readPlainText demo helper gets an 'image' branch returning alt text (was crashing the SSR with 'Cannot read properties of undefined (reading map)' because image has no .children). Demo screenshot confirms: - Image renders inside a figure with border + padding - Caption shows centered + italic below - img max-inline-size cap keeps the image inside the editor frame - Word/char count in status bar reflects alt + caption text F3 MVP visually verified end-to-end: - Block parses from markdown / HTML in the document model - Renders correctly as figure/img/figcaption in the contenteditable - Eidos styling (border, caption italic, alignment data-attr) applies - Status bar counts include image alt text Pending (UX surfaces, deferred to a follow-up session): - F3.7 slash menu /image entry (open a URL prompt) - F3.8 paste/drop handler with onUploadImage callback for file uploads - F3.7/F3.8 require new svelte components (insert dialog, drop overlay) and provider event handlers — they're isolatable from this commit's surface and are the next sub-sprint. Co-Authored-By: Claude Opus 4.7 (1M context) --- web/routes/uix/components/words/+page.svelte | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/web/routes/uix/components/words/+page.svelte b/web/routes/uix/components/words/+page.svelte index c120e95f3..ea7133b90 100644 --- a/web/routes/uix/components/words/+page.svelte +++ b/web/routes/uix/components/words/+page.svelte @@ -536,6 +536,12 @@ language: 'ts', children: [{ type: 'text', text: "const words = createWordsState('ActiveUIX');" }] }, + { + type: 'image', + src: 'https://placecats.com/600/300', + alt: 'Demo cat placeholder showing the image block in action', + caption: 'Image blocks are first-class: alt, optional caption, optional alignment.' + }, { type: 'table', striped: true, @@ -738,6 +744,10 @@ ) .join('\n'); } + if (block.type === 'image') { + // Image has no inline children — represent in plain text via alt. + return block.alt ?? ''; + } return block.children.map(readInlineText).join(''); }) .join('\n');