Skip to content

Commit 67c945e

Browse files
chore: Bump @tiptap to v3 (#525)
1 parent 7932ea3 commit 67c945e

8 files changed

Lines changed: 268 additions & 267 deletions

File tree

.changeset/sour-hairs-judge.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@aragon/gov-ui-kit': minor
3+
---
4+
5+
Bump @tiptap to v3

package.json

Lines changed: 7 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -54,23 +54,20 @@
5454
"@radix-ui/react-toggle-group": "^1.1.0",
5555
"@radix-ui/react-tooltip": "^1.2.0",
5656
"@radix-ui/react-visually-hidden": "^1.2.0",
57-
"@tiptap/core": "^2.26.0",
58-
"@tiptap/extension-code-block": "^2.26.0",
59-
"@tiptap/extension-image": "^2.26.0",
60-
"@tiptap/extension-link": "^2.26.0",
61-
"@tiptap/extension-placeholder": "^2.26.0",
62-
"@tiptap/extension-text-style": "^2.26.0",
63-
"@tiptap/pm": "^2.26.0",
64-
"@tiptap/react": "^2.26.0",
65-
"@tiptap/starter-kit": "^2.26.0",
57+
"@tiptap/core": "^3.5.0",
58+
"@tiptap/extension-image": "^3.5.0",
59+
"@tiptap/extensions": "^3.5.0",
60+
"@tiptap/pm": "^3.5.0",
61+
"@tiptap/react": "^3.5.0",
62+
"@tiptap/starter-kit": "^3.5.0",
6663
"blockies-ts": "^1.0.0",
6764
"classnames": "^2.5.0",
6865
"framer-motion": "^12.23.0",
6966
"luxon": "^3.7.0",
7067
"react-dropzone": "^14.3.0",
7168
"react-imask": "^7.6.0",
7269
"sanitize-html": "^2.17.0",
73-
"tiptap-markdown": "^0.8.10"
70+
"tiptap-markdown": "^0.9.0"
7471
},
7572
"peerDependencies": {
7673
"@tailwindcss/typography": "^0.5.0",

src/core/components/documentParser/documentParser.stories.tsx

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -36,8 +36,7 @@ This is a **markdown** ~~formatted text~~ with \`inline code\`.
3636
const x = 10;
3737
\`\`\`
3838
39-
![Sample Image](https://aragon-1.mypinata.cloud/ipfs/QmX4q3fu1QkSfdVFUAmSUWziCmnXtitp2TVKLbrFVBcPvv)
40-
`,
39+
![Sample Image](https://aragon-1.mypinata.cloud/ipfs/QmX4q3fu1QkSfdVFUAmSUWziCmnXtitp2TVKLbrFVBcPvv)`,
4140
},
4241
};
4342

@@ -57,8 +56,7 @@ export const WithHTML: Story = {
5756
</li>
5857
</ul>
5958
<pre><code>const x = 10;</code></pre>
60-
<img src="https://aragon-1.mypinata.cloud/ipfs/QmX4q3fu1QkSfdVFUAmSUWziCmnXtitp2TVKLbrFVBcPvv" alt="Sample Image">
61-
`,
59+
<img src="https://aragon-1.mypinata.cloud/ipfs/QmX4q3fu1QkSfdVFUAmSUWziCmnXtitp2TVKLbrFVBcPvv" alt="Sample Image">`,
6260
},
6361
};
6462

src/core/components/documentParser/documentParser.tsx

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
import { Image } from '@tiptap/extension-image';
2-
import TipTapLink from '@tiptap/extension-link';
32
import { EditorContent, useEditor } from '@tiptap/react';
43
import { StarterKit } from '@tiptap/starter-kit';
54
import classNames from 'classnames';
@@ -33,11 +32,11 @@ export const DocumentParser: React.FC<IDocumentParserProps> = (props) => {
3332
return sanitizeHtml(document, { allowedTags, allowedAttributes, disallowedTagsMode });
3433
};
3534

36-
const extensions = [StarterKit, Image, Markdown, TipTapLink.configure({ openOnClick: false })];
35+
const extensions = [StarterKit.configure({ link: { openOnClick: false } }), Image, Markdown];
3736
const parser = useEditor({ editable: false, immediatelyRender, extensions, content: sanitizeDocument(document) });
3837

3938
useEffect(() => {
40-
parser?.commands.setContent(sanitizeDocument(document), true);
39+
parser.commands.setContent(sanitizeDocument(document));
4140
}, [document, parser]);
4241

4342
return (

src/core/components/forms/textAreaRichText/textAreaRichText.stories.tsx

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,15 @@ export const Controlled: Story = {
4141
'<p>Hello <strong>dev</strong>, check this <a href="https://aragon.org" target="_blank">link</a>.</p>',
4242
);
4343

44-
return <TextAreaRichText value={value} onChange={setValue} {...props} />;
44+
return (
45+
<div className="flex grow flex-col gap-2">
46+
<TextAreaRichText value={value} onChange={setValue} {...props} />
47+
<div className="flex flex-col gap-1">
48+
<p className="text-md text-neutral-800">Output</p>
49+
<p className="text-neutral-500">{value}</p>
50+
</div>
51+
</div>
52+
);
4553
},
4654
};
4755

src/core/components/forms/textAreaRichText/textAreaRichText.test.tsx

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,13 @@ describe('<TextAreaRichText /> component', () => {
7272
expect(onChange).toHaveBeenLastCalledWith('# test');
7373
});
7474

75+
it("replaces backslash and newline soft breaks with two-space newlines when valueFormat is 'markdown'", async () => {
76+
const onChange = jest.fn();
77+
render(createTestComponent({ onChange, valueFormat: 'markdown' }));
78+
await userEvent.type(screen.getByRole('textbox'), 'line 1{shift>}{enter}{/shift}line 2');
79+
expect(onChange).toHaveBeenLastCalledWith('line 1 \nline 2');
80+
});
81+
7582
it('defaults to empty string instead of empty paragraph when input is empty', async () => {
7683
const onChange = jest.fn();
7784
render(createTestComponent({ onChange }));
@@ -80,12 +87,10 @@ describe('<TextAreaRichText /> component', () => {
8087
expect(onChange).toHaveBeenLastCalledWith('');
8188
});
8289

83-
it('formats pasted markdown content', async () => {
90+
it('correctly formats pasted markdown content', async () => {
8491
const onChange = jest.fn();
8592
render(createTestComponent({ onChange }));
86-
const event = {
87-
getData: (type: string) => (type === 'text/plain' ? '# Heading' : ''),
88-
} as DataTransfer;
93+
const event = { getData: (type: string) => (type === 'text/plain' ? '# Heading' : '') } as DataTransfer;
8994
await userEvent.click(screen.getByRole('textbox'));
9095
await userEvent.paste(event);
9196
expect(onChange).toHaveBeenLastCalledWith('<h1>Heading</h1>');

src/core/components/forms/textAreaRichText/textAreaRichText.tsx

Lines changed: 9 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
1-
import { Link } from '@tiptap/extension-link';
2-
import { Placeholder } from '@tiptap/extension-placeholder';
1+
import { Placeholder } from '@tiptap/extensions';
32
import { EditorContent, useEditor } from '@tiptap/react';
43
import { StarterKit } from '@tiptap/starter-kit';
54
import classNames from 'classnames';
@@ -69,13 +68,8 @@ export const TextAreaRichText: React.FC<ITextAreaRichTextProps> = (props) => {
6968
const randomId = useRandomId(id);
7069

7170
const extensions = [
72-
StarterKit,
73-
Placeholder.configure({
74-
placeholder,
75-
emptyNodeClass: placeholderClasses,
76-
showOnlyWhenEditable: false,
77-
}),
78-
Link,
71+
StarterKit.configure({ trailingNode: false }),
72+
Placeholder.configure({ placeholder, emptyNodeClass: placeholderClasses, showOnlyWhenEditable: false }),
7973
Markdown.configure({ transformPastedText: true }),
8074
];
8175

@@ -86,7 +80,7 @@ export const TextAreaRichText: React.FC<ITextAreaRichTextProps> = (props) => {
8680
immediatelyRender,
8781
editorProps: {
8882
attributes: {
89-
class: 'outline-hidden p-4 [overflow-wrap:anywhere]! prose prose-neutral min-h-40 h-full max-w-none leading-normal',
83+
class: 'relative outline-hidden p-4 [overflow-wrap:anywhere]! prose prose-neutral min-h-40 h-full max-w-none leading-normal',
9084
role: 'textbox',
9185
'aria-labelledby': randomId,
9286
},
@@ -101,13 +95,11 @@ export const TextAreaRichText: React.FC<ITextAreaRichTextProps> = (props) => {
10195
html: () => editor.getHTML(),
10296
text: () => editor.getText(),
10397
markdown: () => {
104-
const markdownStorage = editor.storage.markdown as MarkdownStorage | undefined;
98+
const { storage } = editor;
99+
const markdownStorage = 'markdown' in storage ? (storage.markdown as MarkdownStorage) : undefined;
105100

106-
if (markdownStorage) {
107-
return markdownStorage.getMarkdown();
108-
}
109-
110-
return editor.getHTML();
101+
// Replace soft break syntax emitted by tiptap-markdown (backslash + newline) with standard two-space newline
102+
return markdownStorage?.getMarkdown().replace(/\\\n/g, ' \n');
111103
},
112104
};
113105

@@ -131,7 +123,7 @@ export const TextAreaRichText: React.FC<ITextAreaRichTextProps> = (props) => {
131123

132124
// Update editable setting on Tiptap editor on disabled property change
133125
useEffect(() => {
134-
editor?.setEditable(!disabled);
126+
editor.setEditable(!disabled);
135127
}, [editor, disabled]);
136128

137129
// Add keydown listener to reset expanded state on ESC key down

0 commit comments

Comments
 (0)