fix: paragraph styles apply to every block, not just the first
The document's content ended in an optional noteSection, so the content match after the first child offered noteSection as its defaultType — and that is what TipTap's clearNodes converts a block into. Every style command on a top-level block past the first threw "Invalid content for node type noteSection" and applied nothing. Spelling the same language as an alternation puts a paragraph first again.
This commit is contained in:
1 parent
dc1f5bb7b1
commit
8b1bef9706
2 files changed
+32
-1
No files matched your search
@@ -79,7 +79,12 @@ import { Insertion, Deletion, TrackChanges } from './extensions/trackChanges';
|
||||
export const extensions = [
|
||||
// textBox and columns have their own groups so only the document (not
|
||||
// cells/lists/boxes) admits them; the note section is last or nowhere.
|
||||
Document.extend({ content: '(block | textBox | columns)+ noteSection?' }),
|
||||
// Spelled as an alternation, not `… + noteSection?`: with the trailing optional the
|
||||
// match state after the first block offers noteSection first, and that is the type
|
||||
// TipTap's clearNodes converts a block into (`contentMatchAt(i).defaultType`).
|
||||
Document.extend({
|
||||
content: '((block | textBox | columns)+ noteSection) | (block | textBox | columns)+',
|
||||
}),
|
||||
Paragraph,
|
||||
Text,
|
||||
Bold,
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
import { describe, it, expect } from 'vitest';
|
||||
import { getSchema } from '@tiptap/core';
|
||||
import { extensions } from '../../src/lib/editor/extensions';
|
||||
|
||||
// TipTap's clearNodes rewrites a block into its parent's `defaultType`, so the
|
||||
// document's must stay a paragraph at every index — noteSection there made every
|
||||
// style command on a block past the first throw (Invalid content for noteSection).
|
||||
describe('document content expression', () => {
|
||||
it('offers a paragraph as the default type at every index', () => {
|
||||
const schema = getSchema(extensions);
|
||||
const p = schema.nodes.paragraph.createAndFill()!;
|
||||
const doc = schema.nodes.doc.create(null, [p, p, p]);
|
||||
for (let i = 0; i <= doc.childCount; i++) {
|
||||
expect(doc.contentMatchAt(i).defaultType?.name).toBe('paragraph');
|
||||
}
|
||||
});
|
||||
|
||||
it('still admits a note section, last only', () => {
|
||||
const schema = getSchema(extensions);
|
||||
const p = schema.nodes.paragraph.createAndFill()!;
|
||||
const note = schema.nodes.note.create(null, p);
|
||||
const section = schema.nodes.noteSection.create(null, note);
|
||||
expect(() => schema.nodes.doc.createChecked(null, [p, section])).not.toThrow();
|
||||
expect(() => schema.nodes.doc.createChecked(null, [section, p])).toThrow();
|
||||
});
|
||||
});
|
||||
Reference in new issue
Block a user