From 5c2d3baac0784506732eb25480815cb7218498ec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Padez?= Date: Mon, 31 Aug 2026 05:54:44 +0100 Subject: [PATCH] justify, which the site could always render MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `rt-justify` has been in the sanitiser's allowlist all along, and styles.css gives it `text-align: justify` with `hyphens: auto` — hyphenation being what stops justified text opening rivers of white space between words. Only the toolbar was missing it. The four are now a list beside the toolbar rather than a ternary chain, and the comment says what it has to match: ALIGN_CLASSES in the site's rich-text.ts. A fifth offered here would be stripped on save, silently, leaving somebody pressing a button that appears to do nothing. Co-Authored-By: Claude Opus 5 (1M context) --- web/RichText.tsx | 41 ++++++++++++++++++++++++++++------------- 1 file changed, 28 insertions(+), 13 deletions(-) diff --git a/web/RichText.tsx b/web/RichText.tsx index 5322f7b..697201f 100644 --- a/web/RichText.tsx +++ b/web/RichText.tsx @@ -5,6 +5,7 @@ import Link from '@tiptap/extension-link'; import TextAlign from '@tiptap/extension-text-align'; import { AlignCenter, + AlignJustify, AlignLeft, AlignRight, Bold, @@ -30,7 +31,7 @@ import { * * ── The toolbar is what the site can actually render ── * - * Bold, italic, strike, a heading, two lists, three alignments, a link. Not because tiptap cannot do + * Bold, italic, strike, a heading, two lists, four alignments, a link. Not because tiptap cannot do * more, but because anything offered here that the site's stylesheet has no rule for produces copy that * looks right while editing and wrong when published — the worst kind of editor, since the person only * finds out after saying it is done. @@ -75,6 +76,19 @@ const Tool = ({ ); +/** + * The alignments the toolbar offers. + * + * The same four the site's sanitiser accepts — ALIGN_CLASSES in src/rich-text.ts. A fifth offered here + * would be stripped on save, silently, leaving somebody pressing a button that appears to do nothing. + */ +const ALIGNMENTS = [ + { value: 'left' as const, Icon: AlignLeft }, + { value: 'center' as const, Icon: AlignCenter }, + { value: 'right' as const, Icon: AlignRight }, + { value: 'justify' as const, Icon: AlignJustify }, +]; + const Toolbar = ({ editor }: { editor: Editor }) => (
editor.chain().focus().toggleBold().run()} active={editor.isActive('bold')}> @@ -117,20 +131,21 @@ const Toolbar = ({ editor }: { editor: Editor }) => ( - {(['left', 'center', 'right'] as const).map((align) => ( + {/* + Four alignments, justify included. + + The site has always been able to render it: `rt-justify` is in the sanitiser's allowlist and + styles.css gives it `text-align: justify` with `hyphens: auto` — hyphenation being what stops + justified text opening rivers of white space between words. Only the toolbar was missing. + */} + {ALIGNMENTS.map(({ value, Icon }) => ( editor.chain().focus().setTextAlign(align).run()} - active={editor.isActive({ textAlign: align })} + key={value} + label={`Align ${value}`} + onClick={() => editor.chain().focus().setTextAlign(value).run()} + active={editor.isActive({ textAlign: value })} > - {align === 'left' ? ( - - ) : align === 'center' ? ( - - ) : ( - - )} + ))}