Skip to content

Commit 4824813

Browse files
authored
fix(CodeBlock): fix parsing and serialization of code and fence blocks (#96)
1. Remove extra new line at the end of content of code and fence blocks 2. Always add new line to node.textContent of codeblock when serializing
1 parent c975ddf commit 4824813

File tree

4 files changed

+21
-14
lines changed

4 files changed

+21
-14
lines changed

src/core/markdown/MarkdownParser.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -183,7 +183,11 @@ export class MarkdownParser implements Parser {
183183

184184
if (tokenSpec.noCloseToken) {
185185
this.openNode(schemaSpec, attrs);
186-
this.addText(yfmToken.content);
186+
let {content} = yfmToken;
187+
if (tokenSpec.prepareContent) {
188+
content = tokenSpec.prepareContent(content);
189+
}
190+
this.addText(content);
187191
this.closeNode();
188192

189193
return;

src/core/types/parser.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,4 +20,6 @@ export interface ParserToken {
2020
// То есть контент лежит в поле content токена, а не между открывающим и закрывающим токенами.
2121
noCloseToken?: boolean;
2222
ignore?: boolean;
23+
/** only for tokens with type=block */
24+
prepareContent?: (content: string) => string;
2325
}

src/extensions/markdown/CodeBlock/CodeBlock.test.ts

Lines changed: 6 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -22,30 +22,24 @@ describe('CodeBlock extension', () => {
2222
it('should parse a code block', () =>
2323
same(
2424
'Some code:\n\n```\nHere it is\n```\n\nPara',
25-
doc(
26-
p('Some code:'),
27-
cb({[codeBlockLangAttr]: ''}, schema.text('Here it is\n')),
28-
p('Para'),
29-
),
25+
doc(p('Some code:'), cb({[codeBlockLangAttr]: ''}, 'Here it is'), p('Para')),
3026
));
3127

3228
it('parses an intended code block', () =>
3329
parse(
3430
'Some code:\n\n Here it is\n\nPara',
35-
doc(p('Some code:'), cb('Here it is\n'), p('Para')),
31+
doc(p('Some code:'), cb('Here it is'), p('Para')),
3632
));
3733

3834
it('should parse a fenced code block with info string', () =>
3935
same(
4036
'foo\n\n```javascript\n1\n```',
41-
doc(
42-
p('foo'),
43-
schema.node(codeBlockNodeName, {[codeBlockLangAttr]: 'javascript'}, [
44-
schema.text('1\n'),
45-
]),
46-
),
37+
doc(p('foo'), cb({[codeBlockLangAttr]: 'javascript'}, '1')),
4738
));
4839

40+
it('should parse a fenced code block with multiple new lines at the end', () =>
41+
same('```\nsome code\n\n\n\n```', doc(cb({[codeBlockLangAttr]: ''}, 'some code\n\n\n'))));
42+
4943
// TODO: parsed: doc(paragraph("code\nblock"))
5044
it.skip('should parse html - pre tag', () => {
5145
parseDOM(schema, '<pre><code>code\nblock</code></pre>', doc(cb('code\nblock')));

src/extensions/markdown/CodeBlock/CodeBlockSpecs/index.ts

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,12 +39,14 @@ export const CodeBlockSpecs: ExtensionAuto<CodeBlockSpecsOptions> = (builder, op
3939
name: codeBlockNodeName,
4040
type: 'block',
4141
noCloseToken: true,
42+
prepareContent: removeNewLineAtEnd, // content of code blocks contains extra \n at the end
4243
},
4344
},
4445
toYfm: (state, node) => {
4546
state.write('```' + (node.attrs[codeBlockLangAttr] || '') + '\n');
4647
state.text(node.textContent, false);
47-
state.ensureNewLine();
48+
// Add a newline to the current content before adding closing marker
49+
state.write('\n');
4850
state.write('```');
4951
state.closeBlock(node);
5052
},
@@ -59,10 +61,15 @@ export const CodeBlockSpecs: ExtensionAuto<CodeBlockSpecsOptions> = (builder, op
5961
type: 'block',
6062
noCloseToken: true,
6163
getAttrs: (tok) => ({[codeBlockLangAttr]: tok.info || ''}),
64+
prepareContent: removeNewLineAtEnd, // content of fence blocks contains extra \n at the end
6265
},
6366
},
6467
toYfm: () => {
6568
throw new Error('Unexpected toYfm() call on fence node');
6669
},
6770
}));
6871
};
72+
73+
function removeNewLineAtEnd(content: string): string {
74+
return content.endsWith('\n') ? content.slice(0, content.length - 1) : content;
75+
}

0 commit comments

Comments
 (0)