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
Original file line number Diff line number Diff line change
Expand Up @@ -57,14 +57,25 @@ export const createCustomMarkdownSerializer = editor => {
switch (node.type.name) {
case 'doc': {
const parts = [];
// Process all children
if (node.content && node.content.size > 0) {
for (let i = 0; i < node.content.size; i++) {
const child = node.content.content[i];
if (child) parts.push(serializeNode(child, null, depth));
if (child)
parts.push({ type: child.type?.name, md: serializeNode(child, null, depth) });
}
}
return parts.join('\n\n');
// Use a hard break ( \n) between consecutive plain paragraphs so Perseus
// renders them as <br> (inline-safe). All other block transitions keep \n\n
// so marked still parses lists, headings, etc. correctly.
return parts
.map((part, idx) => {
if (idx === 0) return part.md;
const prev = parts[idx - 1];
const separator =
prev.type === 'paragraph' && part.type === 'paragraph' ? ' \n' : '\n\n';
return separator + part.md;
})
.join('');
}

case 'paragraph': {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,20 +1,17 @@
// Import the function we are testing
import { createCustomMarkdownSerializer } from '../TipTapEditor/utils/markdownSerializer';

// Mock the IMAGE_PLACEHOLDER to match what our tests expect
jest.mock('../TipTapEditor/utils/markdown', () => {
const originalModule = jest.requireActual('../TipTapEditor/utils/markdown');
return {
...originalModule,
IMAGE_PLACEHOLDER: '${CONTENTSTORAGE}',
paramsToImageMd: jest.fn(params => {
const alt = params.alt || '';
const src = params.permanentSrc ? `\${CONTENTSTORAGE}/${params.permanentSrc}` : params.src;
const dimensions = params.width && params.height ? ` =${params.width}x${params.height}` : '';
return `![${alt}](${src}${dimensions})`;
}),
};
});
// Mock the whole module to avoid pulling in the ESM `marked` library in Jest.
jest.mock('../TipTapEditor/utils/markdown', () => ({
IMAGE_PLACEHOLDER: '${CONTENTSTORAGE}',
paramsToMathMd: ({ latex }) => `$$${latex || ''}$$`,
paramsToImageMd: jest.fn(params => {
const alt = params.alt || '';
const src = params.permanentSrc ? `\${CONTENTSTORAGE}/${params.permanentSrc}` : params.src;
const dimensions = params.width && params.height ? ` =${params.width}x${params.height}` : '';
return `![${alt}](${src}${dimensions})`;
}),
}));

// mock editor object with a proper ProseMirror-like structure
const createMockEditor = docContent => {
Expand Down Expand Up @@ -177,14 +174,32 @@ describe('createCustomMarkdownSerializer', () => {
expect(getMarkdown()).toBe('- Item 1\n - Nested 1.1\n- Item 2');
});

it('should place two newlines between block elements', () => {
it('should use a hard break between consecutive paragraphs so Perseus renders them as <br>', () => {
const docContent = [
{ type: 'paragraph', content: [{ type: 'text', text: 'First paragraph.' }] },
{ type: 'paragraph', content: [{ type: 'text', text: 'Second paragraph.' }] },
];
const mockEditor = createMockEditor(docContent);
const getMarkdown = createCustomMarkdownSerializer(mockEditor);
expect(getMarkdown()).toBe('First paragraph.\n\nSecond paragraph.');
expect(getMarkdown()).toBe('First paragraph. \nSecond paragraph.');
});

it('should use two newlines between a paragraph and a non-paragraph block', () => {
const docContent = [
{ type: 'paragraph', content: [{ type: 'text', text: 'Intro.' }] },
{
type: 'bulletList',
content: [
{
type: 'listItem',
content: [{ type: 'paragraph', content: [{ type: 'text', text: 'Item A' }] }],
},
],
},
];
const mockEditor = createMockEditor(docContent);
const getMarkdown = createCustomMarkdownSerializer(mockEditor);
expect(getMarkdown()).toBe('Intro.\n\n- Item A');
});
});

Expand Down Expand Up @@ -405,7 +420,7 @@ describe('createCustomMarkdownSerializer', () => {
const mockEditor = createMockEditor(docContent);
const getMarkdown = createCustomMarkdownSerializer(mockEditor);
expect(getMarkdown()).toBe(
'<p style="text-align: center">Centered</p>\n\nNormal\n\n<p style="text-align: right">Right</p>',
'<p style="text-align: center">Centered</p> \nNormal \n<p style="text-align: right">Right</p>',
);
});

Expand Down
Loading