Skip to content

Commit 5691a31

Browse files
authored
Merge pull request #3998 from udecode/fix/md
Fix: serialize markdown
2 parents fb2e126 + b335a9c commit 5691a31

File tree

4 files changed

+95
-8
lines changed

4 files changed

+95
-8
lines changed

.changeset/fifty-hats-obey.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@udecode/plate-markdown': patch
3+
---
4+
5+
Fix serialize code-block and indent-list. Add support for equation and inline-equation.

packages/markdown/src/lib/serializer/defaultSerializeMdNodesOptions.ts

Lines changed: 72 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,16 @@ export const defaultSerializeMdNodesOptions: SerializeMdOptions['nodes'] = {
2525
code_block: {
2626
type: 'code_block',
2727
serialize: (children, node) =>
28-
`\n\`\`\`${node.language || ''}\n${children}\n\`\`\`\n`,
28+
// eslint-disable-next-line @typescript-eslint/no-base-to-string
29+
`\n\`\`\`${node.lang || ''}\n${children}\`\`\`\n`,
30+
},
31+
code_line: {
32+
type: 'code_line',
33+
serialize: (children) => `${children}\n`,
34+
},
35+
equation: {
36+
type: 'equation',
37+
serialize: (children, node) => `$$\n${node.texExpression}\n$$`,
2938
},
3039
h1: { type: 'h1', serialize: (children) => `\n# ${children}\n` },
3140
h2: { type: 'h2', serialize: (children) => `\n## ${children}\n` },
@@ -52,6 +61,10 @@ export const defaultSerializeMdNodesOptions: SerializeMdOptions['nodes'] = {
5261
return `\n![${caption}](${node.url || ''})\n`;
5362
},
5463
},
64+
inline_equation: {
65+
type: 'inline_equation',
66+
serialize: (children, node) => `$${node.texExpression}$`,
67+
},
5568
italic: { isLeaf: true, type: 'italic' },
5669
li: {
5770
type: 'li',
@@ -90,9 +103,15 @@ export const defaultSerializeMdNodesOptions: SerializeMdOptions['nodes'] = {
90103
},
91104
p: {
92105
type: 'p',
93-
serialize: (children, node, { ulListStyleTypes = [] }) => {
106+
serialize: (children, node, { nodes, ulListStyleTypes = [] }) => {
94107
const listStyleType = node.listStyleType;
95108

109+
const isInTableCell =
110+
node.parent?.type === nodes.td.type ||
111+
node.parent?.type === nodes.th.type;
112+
113+
const breakTag = isInTableCell ? `<br />` : `\n`;
114+
96115
if (listStyleType) {
97116
let pre = '';
98117

@@ -104,22 +123,69 @@ export const defaultSerializeMdNodesOptions: SerializeMdOptions['nodes'] = {
104123
const listStart = node.listStart ?? 1;
105124

106125
const isOL = !ulListStyleTypes.includes(listStyleType);
107-
const treatAsLeaf =
108-
node.children.length === 1 && isLeafNode(node.children[0]);
109126

110127
// https://github.com/remarkjs/remark-react/issues/65
111128
if (isOL && listDepth > 0) {
112129
pre += ' ';
113130
}
114131

115132
// TODO: support all styles
116-
return `${pre}${isOL ? listStart + '.' : '-'} ${children}${treatAsLeaf ? '\n' : ''}`;
133+
return `${pre}${isOL ? listStart + '.' : '-'} ${children}${breakTag}`;
117134
}
118135

119-
return `\n${children}\n`;
136+
const pre = isInTableCell ? '' : '\n';
137+
138+
return `${pre}${children}${breakTag}`;
120139
},
121140
},
122141
strikethrough: { isLeaf: true, type: 'strikethrough' },
142+
table: {
143+
type: 'table',
144+
serialize: (children) => {
145+
const lines = children.split('\n').filter(Boolean);
146+
147+
// Line 0 is the header row
148+
const headerLine = lines[0].trim();
149+
150+
// Remove extra "|" from both sides
151+
let lineTrimmed = headerLine;
152+
153+
if (lineTrimmed.startsWith('|')) {
154+
lineTrimmed = lineTrimmed.slice(1);
155+
}
156+
if (lineTrimmed.endsWith('|')) {
157+
lineTrimmed = lineTrimmed.slice(0, -1);
158+
}
159+
160+
// Generate "---" separators based on number of columns
161+
const cols = lineTrimmed.split('|').length;
162+
const separator = `| ${Array(cols).fill('---').join(' | ')} |`;
163+
164+
// Insert separator line into array
165+
lines.splice(1, 0, separator);
166+
167+
// Join back into string
168+
return lines.join('\n');
169+
},
170+
},
171+
td: {
172+
type: 'td',
173+
serialize: (children) => {
174+
return `| ${children}`;
175+
},
176+
},
177+
th: {
178+
type: 'th',
179+
serialize: (children) => {
180+
return `| ${children}`;
181+
},
182+
},
183+
tr: {
184+
type: 'tr',
185+
serialize: (children) => {
186+
return `${children} |\n`;
187+
},
188+
},
123189
ul: {
124190
type: 'ul',
125191
serialize: (children, _, { listDepth }) => {

packages/markdown/src/lib/serializer/serializeMdNode.ts

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -201,8 +201,17 @@ export function serializeMdNode(
201201
type = nodes.p.type!;
202202
children = opts.breakTag;
203203
}
204-
// Skip nodes that are empty, not a list and not void.
205-
if (children === '' && !node.parent?.isList && !elOptions?.isVoid) {
204+
205+
// Skip nodes that are empty, not a list not in a table cell and not void .
206+
const isInTableCell =
207+
node.parent?.type === nodes.td.type || node.parent?.type === nodes.th.type;
208+
209+
if (
210+
children === '' &&
211+
!node.parent?.isList &&
212+
!elOptions?.isVoid &&
213+
!isInTableCell
214+
) {
206215
return;
207216
}
208217
if (isLeafNode(node)) {

packages/markdown/src/lib/serializer/types.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@ export type MdNodeTypes = {
2222
bold: string;
2323
code: string;
2424
code_block: string;
25+
code_line: string;
26+
equation: string;
2527
h1: string;
2628
h2: string;
2729
h3: string;
@@ -30,11 +32,16 @@ export type MdNodeTypes = {
3032
h6: string;
3133
hr: string;
3234
img: string;
35+
inline_equation: string;
3336
italic: string;
3437
li: string;
3538
ol: string;
3639
p: string;
3740
strikethrough: string;
41+
table: string;
42+
td: string;
43+
th: string;
44+
tr: string;
3845
ul: string;
3946
underline: string;
4047
};

0 commit comments

Comments
 (0)