justify, which the site could always render
`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) <noreply@anthropic.com>
This commit is contained in:
+28
-13
@@ -5,6 +5,7 @@ import Link from '@tiptap/extension-link';
|
|||||||
import TextAlign from '@tiptap/extension-text-align';
|
import TextAlign from '@tiptap/extension-text-align';
|
||||||
import {
|
import {
|
||||||
AlignCenter,
|
AlignCenter,
|
||||||
|
AlignJustify,
|
||||||
AlignLeft,
|
AlignLeft,
|
||||||
AlignRight,
|
AlignRight,
|
||||||
Bold,
|
Bold,
|
||||||
@@ -30,7 +31,7 @@ import {
|
|||||||
*
|
*
|
||||||
* ── The toolbar is what the site can actually render ──
|
* ── 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
|
* 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
|
* looks right while editing and wrong when published — the worst kind of editor, since the person only
|
||||||
* finds out after saying it is done.
|
* finds out after saying it is done.
|
||||||
@@ -75,6 +76,19 @@ const Tool = ({
|
|||||||
</button>
|
</button>
|
||||||
);
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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 }) => (
|
const Toolbar = ({ editor }: { editor: Editor }) => (
|
||||||
<div className="flex flex-wrap items-center gap-0.5 border-b border-border px-1 py-1">
|
<div className="flex flex-wrap items-center gap-0.5 border-b border-border px-1 py-1">
|
||||||
<Tool label="Bold" onClick={() => editor.chain().focus().toggleBold().run()} active={editor.isActive('bold')}>
|
<Tool label="Bold" onClick={() => editor.chain().focus().toggleBold().run()} active={editor.isActive('bold')}>
|
||||||
@@ -117,20 +131,21 @@ const Toolbar = ({ editor }: { editor: Editor }) => (
|
|||||||
|
|
||||||
<span className="mx-1 h-4 w-px bg-border" />
|
<span className="mx-1 h-4 w-px bg-border" />
|
||||||
|
|
||||||
{(['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 }) => (
|
||||||
<Tool
|
<Tool
|
||||||
key={align}
|
key={value}
|
||||||
label={`Align ${align}`}
|
label={`Align ${value}`}
|
||||||
onClick={() => editor.chain().focus().setTextAlign(align).run()}
|
onClick={() => editor.chain().focus().setTextAlign(value).run()}
|
||||||
active={editor.isActive({ textAlign: align })}
|
active={editor.isActive({ textAlign: value })}
|
||||||
>
|
>
|
||||||
{align === 'left' ? (
|
<Icon className="size-3.5" />
|
||||||
<AlignLeft className="size-3.5" />
|
|
||||||
) : align === 'center' ? (
|
|
||||||
<AlignCenter className="size-3.5" />
|
|
||||||
) : (
|
|
||||||
<AlignRight className="size-3.5" />
|
|
||||||
)}
|
|
||||||
</Tool>
|
</Tool>
|
||||||
))}
|
))}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user