Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions src/app/src/utils/tiptap/tiptapToMdc.ts
Original file line number Diff line number Diff line change
Expand Up @@ -198,8 +198,10 @@ function createElement(node: JSONContent, tag?: string, extra: unknown = {}): MD
// Unwrap default slot (reverts `wrapChildrenWithinSlot` from `mdcToTiptap`)
children = unwrapDefaultSlot(children)

// Unwrap single paragraph child (MDC auto-unwrap feature)
children = unwrapParagraph(children)
if (tag !== 'blockquote') {
// Unwrap single paragraph child (MDC auto-unwrap feature)
children = unwrapParagraph(children)
}

return {
type: 'element',
Expand Down
288 changes: 288 additions & 0 deletions src/app/test/integration/tiptap.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2215,3 +2215,291 @@
expect(outputContent).toBe(`${inputContent}\n`)
})
})

describe('edge cases', () => {
test('div element with text and blockquote', async () => {
const inputContent = `::div
text 1

> text 2
::`

const expectedMDCJSON: MDCRoot = {
type: 'root',
children: [
{
type: 'element',
tag: 'div',
props: {},
children: [
{
type: 'element',
tag: 'p',
props: {},
children: [
{
type: 'text',
value: 'text 1',
},
],
},
{
type: 'element',
tag: 'blockquote',
props: {},
children: [
{
type: 'element',
tag: 'p',
props: {},
children: [
{
type: 'text',
value: 'text 2',
},
],
},
],
},
],
},
],
}

const expectedTiptapJSON: JSONContent = {
type: 'doc',
content: [
{
type: 'frontmatter',
attrs: {
frontmatter: {},
},
},
{
type: 'element',
attrs: {
tag: 'div',
},
content: [
{
type: 'slot',
attrs: {
name: 'default',
props: {
'v-slot:default': '',
},
},
content: [
{
type: 'paragraph',
content: [
{
type: 'text',
text: 'text 1',
},
],
},
{
type: 'blockquote',
content: [
{
type: 'paragraph',
content: [
{
type: 'text',
text: 'text 2',
},
],
},
],
},
],
},
],
},
],
}

const document = await generateDocumentFromContent('test.md', inputContent, { compress: false }) as DatabasePageItem
expect(document.body).toMatchObject(expectedMDCJSON)

const tiptapJSON: JSONContent = await mdcToTiptap(document.body as unknown as MDCRoot, {})
expect(tiptapJSON).toMatchObject(expectedTiptapJSON)

const generatedMdcJSON = await tiptapToMDC(tiptapJSON)
expect(generatedMdcJSON.body).toMatchObject(expectedMDCJSON)

const generatedDocument = createMockDocument('docs/test.md', {
body: generatedMdcJSON.body as unknown as MarkdownRoot,
...generatedMdcJSON.data,
})

const outputContent = await generateContentFromDocument(generatedDocument)
expect(outputContent).toBe(`${inputContent}\n`)

Check failure on line 2338 in src/app/test/integration/tiptap.test.ts

View workflow job for this annotation

GitHub Actions / build (ubuntu-latest, 22)

src/app/test/integration/tiptap.test.ts > edge cases > div element with text and blockquote

AssertionError: expected '::div\n> text 2\n\ntext 1\n::\n' to be '::div\ntext 1\n\n> text 2\n::\n' // Object.is equality - Expected + Received ::div - text 1 + > text 2 - > text 2 + text 1 :: ❯ src/app/test/integration/tiptap.test.ts:2338:27

Check failure on line 2338 in src/app/test/integration/tiptap.test.ts

View workflow job for this annotation

GitHub Actions / build (ubuntu-latest, 22)

src/app/test/integration/tiptap.test.ts > edge cases > div element with text and blockquote

AssertionError: expected '::div\n> text 2\n\ntext 1\n::\n' to be '::div\ntext 1\n\n> text 2\n::\n' // Object.is equality - Expected + Received ::div - text 1 + > text 2 - > text 2 + text 1 :: ❯ src/app/test/integration/tiptap.test.ts:2338:27
})

test('image after heading inside component maintains correct order', async () => {
const inputContent = `::steps
### Step 1

![Image](https://example.com/image.jpg)
::`

const expectedMDCJSON: MDCRoot = {
type: 'root',
children: [
{
type: 'element',
tag: 'steps',
props: {},
children: [
{
type: 'element',
tag: 'h3',
props: {},
children: [
{
type: 'text',
value: 'Step 1',
},
],
},
{
type: 'element',
tag: 'p',
props: {},
children: [
{
type: 'element',
tag: 'img',
props: {
src: 'https://example.com/image.jpg',
alt: 'Image',
},
children: [],
},
],
},
],
},
],
}

const expectedTiptapJSON: JSONContent = {
type: 'doc',
content: [
{
type: 'frontmatter',
attrs: {
frontmatter: {},
},
},
{
type: 'element',
attrs: {
tag: 'steps',
},
content: [
{
type: 'slot',
attrs: {
name: 'default',
props: {
'v-slot:default': '',
},
},
content: [
{
type: 'heading',
attrs: {
level: 3,
},
content: [
{
type: 'text',
text: 'Step 1',
},
],
},
{
type: 'paragraph',
content: [
{
type: 'image',
attrs: {
props: {
src: 'https://example.com/image.jpg',
alt: 'Image',
},
},
},
],
},
],
},
],
},
],
}

const document = await generateDocumentFromContent('test.md', inputContent, { compress: false }) as DatabasePageItem
expect(document.body).toMatchObject(expectedMDCJSON)

const tiptapJSON: JSONContent = await mdcToTiptap(document.body as unknown as MDCRoot, {})
expect(tiptapJSON).toMatchObject(expectedTiptapJSON)

const generatedMdcJSON = await tiptapToMDC(tiptapJSON)
expect(generatedMdcJSON.body).toMatchObject(expectedMDCJSON)

const generatedDocument = createMockDocument('docs/test.md', {
body: generatedMdcJSON.body as unknown as MarkdownRoot,
...generatedMdcJSON.data,
})

const outputContent = await generateContentFromDocument(generatedDocument)

expect(outputContent).toBe(`${inputContent}\n`)

// Custom case also valid when image is not enclosed in a paragraph
const expectedMDCJSONBis: MDCRoot = {
type: 'root',
children: [
{
type: 'element',
tag: 'steps',
props: {},
children: [
{
type: 'element',
tag: 'h3',
props: {},
children: [
{
type: 'text',
value: 'Step 1',
},
],
},
{
type: 'element',
tag: 'img',
props: {
src: 'https://example.com/image.jpg',
alt: 'Image',
},
children: [],
},
],
},
],
}

const generatedDocumentBis = createMockDocument('docs/test.md', {
body: expectedMDCJSONBis as unknown as MarkdownRoot,
})

const outputContentBis = await generateContentFromDocument(generatedDocumentBis)

expect(outputContentBis).toBe(`${inputContent}\n`)

Check failure on line 2503 in src/app/test/integration/tiptap.test.ts

View workflow job for this annotation

GitHub Actions / build (ubuntu-latest, 22)

src/app/test/integration/tiptap.test.ts > edge cases > image after heading inside component maintains correct order

AssertionError: expected '::steps\n![Image](https://example.com…' to be '::steps\n### Step 1\n\n![Image](https…' // Object.is equality - Expected + Received ::steps - ### Step 1 - - ![Image](https://example.com/image.jpg) + ![Image](https://example.com/image.jpg) + + ### Step 1 :: ❯ src/app/test/integration/tiptap.test.ts:2503:30

Check failure on line 2503 in src/app/test/integration/tiptap.test.ts

View workflow job for this annotation

GitHub Actions / build (ubuntu-latest, 22)

src/app/test/integration/tiptap.test.ts > edge cases > image after heading inside component maintains correct order

AssertionError: expected '::steps\n![Image](https://example.com…' to be '::steps\n### Step 1\n\n![Image](https…' // Object.is equality - Expected + Received ::steps - ### Step 1 - - ![Image](https://example.com/image.jpg) + ![Image](https://example.com/image.jpg) + + ### Step 1 :: ❯ src/app/test/integration/tiptap.test.ts:2503:30
})
})
Loading