Skip to content

Commit 2a0dbbf

Browse files
authored
fix: support hard line breaks to start a new paragraph (#73)
* refactor: remove flattening of paragraph parsing logic * feat: enhance paragraph parsing to support hard line breaks This update modifies the paragraph parsing logic to correctly split paragraphs on hard line breaks, improving the handling of markdown input. Additionally, new tests have been added to ensure the functionality works as expected.
1 parent 1a0206a commit 2a0dbbf

3 files changed

Lines changed: 79 additions & 11 deletions

File tree

src/parser/internal.ts

Lines changed: 22 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -118,23 +118,34 @@ function parseParagraph(
118118
// Notion doesn't deal with inline images, so we need to parse them all out
119119
// of the paragraph into individual blocks
120120
const images: notion.Block[] = [];
121-
const paragraphs: Array<notion.RichText[]> = [];
121+
const paragraphs: notion.RichText[][] = [];
122+
let currentParagraph: notion.RichText[] = [];
123+
124+
const pushParagraph = () => {
125+
if (currentParagraph.length > 0) {
126+
paragraphs.push(currentParagraph);
127+
currentParagraph = [];
128+
}
129+
};
130+
122131
element.children.forEach(item => {
123132
if (item.type === 'image') {
124133
images.push(parseImage(item, options));
125-
} else {
126-
const richText = parseInline(item) as notion.RichText[];
127-
if (richText.length) {
128-
paragraphs.push(richText);
129-
}
134+
return;
130135
}
136+
137+
if (item.type === 'break') {
138+
pushParagraph();
139+
return;
140+
}
141+
142+
const richText = parseInline(item) as notion.RichText[];
143+
currentParagraph.push(...richText);
131144
});
132145

133-
if (paragraphs.length) {
134-
return [notion.paragraph(paragraphs.flat()), ...images];
135-
} else {
136-
return images;
137-
}
146+
pushParagraph();
147+
148+
return [...paragraphs.map(notion.paragraph), ...images];
138149
}
139150

140151
function parseBlockquote(

test/integration.spec.ts

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -218,6 +218,30 @@ const hello = "hello";
218218

219219
expect(actual).toStrictEqual(expected);
220220
});
221+
222+
it('should split paragraphs on hard line breaks', () => {
223+
const text =
224+
'You can _italicize_ or **bold** text. \nThis is the second line of text.\nAnd this is in the same line';
225+
226+
const actual = markdownToBlocks(text);
227+
228+
const expected = [
229+
notion.paragraph([
230+
notion.richText('You can '),
231+
notion.richText('italicize', {annotations: {italic: true}}),
232+
notion.richText(' or '),
233+
notion.richText('bold', {annotations: {bold: true}}),
234+
notion.richText(' text.'),
235+
]),
236+
notion.paragraph([
237+
notion.richText(
238+
'This is the second line of text.\nAnd this is in the same line',
239+
),
240+
]),
241+
];
242+
243+
expect(actual).toStrictEqual(expected);
244+
});
221245
});
222246

223247
describe('markdownToRichText', () => {

test/parser.spec.ts

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -271,6 +271,39 @@ describe('gfm parser', () => {
271271
expect(actual).toStrictEqual(expected);
272272
});
273273

274+
it('should split paragraphs on hard line breaks', () => {
275+
// Simulate markdown where a line ends with two spaces followed by \n, which renders as a hard line break.
276+
// In the mdast AST this is represented as a `break` node within the paragraph.
277+
const br: md.Break = {type: 'break'} as md.Break;
278+
279+
const ast = md.root(
280+
md.paragraph(
281+
md.text('You can '),
282+
md.emphasis(md.text('italicize')),
283+
md.text(' or '),
284+
md.strong(md.text('bold')),
285+
md.text(' text.'),
286+
br,
287+
md.text('This is the second line of text'),
288+
),
289+
);
290+
291+
const actual = parseBlocks(ast, options);
292+
293+
const expected = [
294+
notion.paragraph([
295+
notion.richText('You can '),
296+
notion.richText('italicize', {annotations: {italic: true}}),
297+
notion.richText(' or '),
298+
notion.richText('bold', {annotations: {bold: true}}),
299+
notion.richText(' text.'),
300+
]),
301+
notion.paragraph([notion.richText('This is the second line of text')]),
302+
];
303+
304+
expect(actual).toStrictEqual(expected);
305+
});
306+
274307
it('should parse github extensions', () => {
275308
const ast = md.root(
276309
md.paragraph(

0 commit comments

Comments
 (0)