import { TLRichText, toRichText } from '@tldraw/editor' import { isEmptyRichText, renderHtmlFromRichTextWithExtensions, tipTapDefaultExtensions, } from './richText' const render = (content: TLRichText['content']) => renderHtmlFromRichTextWithExtensions( { type: 'doc', content } as TLRichText, tipTapDefaultExtensions ) describe('renderHtmlFromRichTextWithExtensions', () => { it('fills an empty paragraph with a line break so the browser does not collapse it', () => { expect(render([{ type: 'paragraph' }])).toBe('


') }) it('keeps an explicit direction on an empty paragraph', () => { // A `dir` of `ltr`/`rtl` rather than the default `auto` comes from pasted HTML that carried // one, or from TipTap's `setTextDirection`. Dropping it would re-align the blank line. expect(render([{ type: 'paragraph', attrs: { dir: 'rtl' } }])).toBe('


') expect(render([{ type: 'paragraph', attrs: { dir: 'ltr' } }])).toBe('


') }) it('fills a paragraph with no attributes at all', () => { // Extension sets without TipTap's TextDirection render a bare `

`. expect(render([{ type: 'paragraph', attrs: { dir: null } }])).toBe('


') }) it('leaves paragraphs with content alone', () => { expect(render([{ type: 'paragraph', content: [{ type: 'text', text: 'hello' }] }])).toBe( '

hello

' ) }) it('fills every empty paragraph, including ones nested in a list item', () => { expect( render([ { type: 'paragraph' }, { type: 'paragraph', content: [{ type: 'text', text: 'hello' }] }, { type: 'paragraph' }, { type: 'bulletList', content: [{ type: 'listItem', content: [{ type: 'paragraph' }] }], }, ]) ).toBe( '


hello


' + '' ) }) }) describe('isEmptyRichText', () => { it('treats a paragraph with no content key as empty (interactive editor output)', () => { expect(isEmptyRichText(toRichText(''))).toBe(true) }) it('treats a paragraph with an empty content array as empty (programmatic authoring)', () => { const richText: TLRichText = { type: 'doc', content: [{ type: 'paragraph', attrs: { dir: 'auto' }, content: [] }], } expect(isEmptyRichText(richText)).toBe(true) }) it('treats a doc with an empty content array as empty (hand-authored / importer form)', () => { const richText: TLRichText = { type: 'doc', content: [] } expect(isEmptyRichText(richText)).toBe(true) }) it('treats a paragraph with text as non-empty', () => { expect(isEmptyRichText(toRichText('Hello'))).toBe(false) }) it('treats multiple paragraphs as non-empty', () => { const richText: TLRichText = { type: 'doc', content: [ { type: 'paragraph', content: [] }, { type: 'paragraph', content: [] }, ], } expect(isEmptyRichText(richText)).toBe(false) }) })