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)
})
})