From b0b0ec35e345f6afb9eacc386fcc07e02bf3f964 Mon Sep 17 00:00:00 2001 From: d3m1d0v Date: Thu, 25 Sep 2025 18:08:11 +0300 Subject: [PATCH] fix(BaseSchema): fix serialization of empty paragraphs inside other blocks --- .../base/BaseSchema/BaseSchema.test.ts | 68 ++++++++++++++----- .../base/BaseSchema/BaseSchemaSpecs/index.ts | 3 +- 2 files changed, 53 insertions(+), 18 deletions(-) diff --git a/src/extensions/base/BaseSchema/BaseSchema.test.ts b/src/extensions/base/BaseSchema/BaseSchema.test.ts index 2c4aea1f8..763f8cf64 100644 --- a/src/extensions/base/BaseSchema/BaseSchema.test.ts +++ b/src/extensions/base/BaseSchema/BaseSchema.test.ts @@ -2,28 +2,62 @@ import {builders} from 'prosemirror-test-builder'; import {createMarkupChecker} from '../../../../tests/sameMarkup'; import {ExtensionsManager} from '../../../core'; +import {BlockquoteSpecs, blockquoteNodeName} from '../../markdown/Blockquote/BlockquoteSpecs'; import {BaseNode, BaseSchemaSpecs} from './BaseSchemaSpecs'; -const { - schema, - markupParser: parser, - serializer, -} = new ExtensionsManager({ - extensions: (builder) => builder.use(BaseSchemaSpecs, {}), -}).buildDeps(); - -const {doc, p} = builders<'doc' | 'p'>(schema, { - doc: {nodeType: BaseNode.Doc}, - p: {nodeType: BaseNode.Paragraph}, -}); +describe('BaseSchema extension', () => { + describe('common', () => { + const { + schema, + markupParser: parser, + serializer, + } = new ExtensionsManager({ + extensions: (builder) => builder.use(BaseSchemaSpecs, {}), + }).buildDeps(); -const {same} = createMarkupChecker({parser, serializer}); + const {doc, p} = builders<'doc' | 'p'>(schema, { + doc: {nodeType: BaseNode.Doc}, + p: {nodeType: BaseNode.Paragraph}, + }); -describe('BaseSchema extension', () => { - it('should parse a paragraph', () => same('hello!', doc(p('hello!')))); + const {same} = createMarkupChecker({parser, serializer}); + + it('should parse a paragraph', () => same('hello!', doc(p('hello!')))); + + it('should parse a few paragraphs', () => { + same(['hello', '', 'world!'].join('\n'), doc(p('hello'), p('world!'))); + }); + }); + + describe('preserveEmptyRows=true', () => { + const { + schema, + markupParser: parser, + serializer, + } = new ExtensionsManager({ + extensions: (builder) => + builder.use(BaseSchemaSpecs, {preserveEmptyRows: true}).use(BlockquoteSpecs), + }).buildDeps(); + + const {doc, p, bq} = builders<'doc' | 'p' | 'bq'>(schema, { + doc: {nodeType: BaseNode.Doc}, + p: {nodeType: BaseNode.Paragraph}, + bq: {nodeType: blockquoteNodeName}, + }); + + const {same} = createMarkupChecker({parser, serializer}); + + it('should serialize empty paragraph as  ', () => + same( + 'hello!\n\n \n\nworld!', + doc(p('hello!'), p(String.fromCharCode(160 /*   */)), p('world!')), + )); - it('should parse a few paragraphs', () => { - same(['hello', '', 'world!'].join('\n'), doc(p('hello'), p('world!'))); + it('should correct insert   inside other nodes', () => + same( + '> hello!\n>\n>  \n> \n> world!', + doc(bq(p('hello!'), p(String.fromCharCode(160 /*   */)), p('world!'))), + )); }); }); diff --git a/src/extensions/base/BaseSchema/BaseSchemaSpecs/index.ts b/src/extensions/base/BaseSchema/BaseSchemaSpecs/index.ts index f88bccdf2..d42fbb7ec 100644 --- a/src/extensions/base/BaseSchema/BaseSchemaSpecs/index.ts +++ b/src/extensions/base/BaseSchema/BaseSchemaSpecs/index.ts @@ -85,7 +85,8 @@ export const BaseSchemaSpecs: ExtensionAuto = (builder, } if (!isParentEmpty) { - state.write(' \n\n'); + state.write(' \n'); + state.write('\n'); } } else { state.renderInline(node);