Skip to content

Commit fbebb3b

Browse files
authored
fix: trim blank lines from block tokens (#3939)
BREAKING CHANGE: trim trailing blank lines from block tokens
1 parent 771f5c8 commit fbebb3b

4 files changed

Lines changed: 66 additions & 7 deletions

File tree

src/Tokenizer.ts

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import {
44
splitCells,
55
findClosingBracket,
66
expandTabs,
7+
trimTrailingBlankLines,
78
} from './helpers.ts';
89
import type { Rules } from './rules.ts';
910
import type { _Lexer } from './Lexer.ts';
@@ -81,14 +82,15 @@ export class _Tokenizer<ParserOutput = string, RendererOutput = string> {
8182
code(src: string): Tokens.Code | undefined {
8283
const cap = this.rules.block.code.exec(src);
8384
if (cap) {
84-
const text = cap[0].replace(this.rules.other.codeRemoveIndent, '');
85+
const raw = this.options.pedantic
86+
? cap[0]
87+
: trimTrailingBlankLines(cap[0]);
88+
const text = raw.replace(this.rules.other.codeRemoveIndent, '');
8589
return {
8690
type: 'code',
87-
raw: cap[0],
91+
raw,
8892
codeBlockStyle: 'indented',
89-
text: !this.options.pedantic
90-
? rtrim(text, '\n')
91-
: text,
93+
text,
9294
};
9395
}
9496
}
@@ -481,12 +483,13 @@ export class _Tokenizer<ParserOutput = string, RendererOutput = string> {
481483
html(src: string): Tokens.HTML | undefined {
482484
const cap = this.rules.block.html.exec(src);
483485
if (cap) {
486+
const raw = trimTrailingBlankLines(cap[0]);
484487
const token: Tokens.HTML = {
485488
type: 'html',
486489
block: true,
487-
raw: cap[0],
490+
raw,
488491
pre: cap[1] === 'pre' || cap[1] === 'script' || cap[1] === 'style',
489-
text: cap[0],
492+
text: raw,
490493
};
491494
return token;
492495
}

src/helpers.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,20 @@ export function rtrim(str: string, c: string, invert?: boolean) {
109109
return str.slice(0, l - suffLen);
110110
}
111111

112+
export function trimTrailingBlankLines(str: string) {
113+
const lines = str.split('\n');
114+
let end = lines.length - 1;
115+
while (end >= 0 && !lines[end].trim()) {
116+
end--;
117+
}
118+
if (lines.length - end <= 2) {
119+
// we want to keep single trailing blank lines
120+
return str;
121+
}
122+
123+
return lines.slice(0, end + 1).join('\n');
124+
}
125+
112126
export function findClosingBracket(str: string, b: string) {
113127
if (str.indexOf(b[1]) === -1) {
114128
return -1;

test/unit/Lexer.test.js

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,22 @@ describe('Lexer', () => {
5959
});
6060
});
6161

62+
it('indented code with trailing blank lines', () => {
63+
expectTokens({
64+
md: ' code\n \n\t\t\n \t\n\nnext',
65+
tokens: [
66+
{ type: 'code', raw: ' code', text: 'code', codeBlockStyle: 'indented' },
67+
{ type: 'space', raw: '\n \n\t\t\n \t\n\n' },
68+
{
69+
type: 'paragraph',
70+
raw: 'next',
71+
text: 'next',
72+
tokens: [{ type: 'text', raw: 'next', text: 'next', escaped: false }],
73+
},
74+
],
75+
});
76+
});
77+
6278
it('fenced code', () => {
6379
expectTokens({
6480
md: '```\ncode\n```',
@@ -1426,6 +1442,31 @@ paragraph
14261442
],
14271443
});
14281444
});
1445+
1446+
it('html with trailing blank lines', () => {
1447+
expectTokens({
1448+
md: '<div>\n html\n</div>\n \n\t\n\nnext',
1449+
tokens: [
1450+
{
1451+
type: 'html',
1452+
raw: '<div>\n html\n</div>',
1453+
pre: false,
1454+
block: true,
1455+
text: '<div>\n html\n</div>',
1456+
},
1457+
{
1458+
type: 'space',
1459+
raw: '\n \n\t\n\n',
1460+
},
1461+
{
1462+
type: 'paragraph',
1463+
raw: 'next',
1464+
text: 'next',
1465+
tokens: [{ type: 'text', raw: 'next', text: 'next', escaped: false }],
1466+
},
1467+
],
1468+
});
1469+
});
14291470
});
14301471

14311472
describe('def', () => {

test/unit/marked.test.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1027,6 +1027,7 @@ br
10271027
['text', 'list'],
10281028
['space', ''],
10291029
['html', '<div>html</div>'],
1030+
['space', ''],
10301031
['paragraph', '[link](https://example.com)'],
10311032
['link', '[link](https://example.com)'],
10321033
['text', 'link'],

0 commit comments

Comments
 (0)