Skip to content

Multiple consecutive blank lines are collapsed into a single blank line #622

Description

@MrSolimanKing

When rendering markdown with EnrichedMarkdownText, consecutive empty lines in the source text are collapsed and rendered as a single blank line/paragraph break, no matter how many blank lines were actually in the source.

const markdown = `Paragraph one.


Paragraph two (there were 2 blank lines above, but only 1 renders).`;

<EnrichedMarkdownText markdown={markdown} flavor="github" />

Expected

Some way to preserve the actual number of blank lines from the source, either via a prop (e.g. preserveBlankLines) or a documented parsing option.

Current workaround

The only way I have found to preserve blank line count is to pre process the markdown string myself before passing it to markdown, converting every blank line after the first in a run into its own paragraph containing a non-breaking space (\u00A0), so the parser treats it as non-empty content instead of discarding it:

function preserveWhitespace(text: string): string {
  const lines = text.split('\n');
  let inFence = false;
  const output: string[] = [];
  let i = 0;
  while (i < lines.length) {
    const line = lines[i];
    if (/^\s*(```|~~~)/.test(line)) {
      inFence = !inFence;
      output.push(line);
      i++;
      continue;
    }
    if (inFence) {
      output.push(line);
      i++;
      continue;
    }
    if (line.trim() === '') {
      let blankCount = 0;
      let j = i;
      while (j < lines.length && lines[j].trim() === '') {
        blankCount++;
        j++;
      }
      output.push('');
      for (let k = 1; k < blankCount; k++) {
        output.push('\u00A0');
        output.push('');
      }
      i = j;
      continue;
    }
    let result = line.replace(/ {2,}/g, (run) => '\u00A0'.repeat(run.length - 1) + ' ');
    result += '  ';
    output.push(result);
    i++;
  }
  return output.join('\n');
}

This works, but it feels like something the library should handle natively (similar to how some markdown renderers expose a breaks-style option), rather than requiring every consumer to reimplement blank-line preservation by hand.

const finalMarkdown = useMemo(
  () => preserveWhitespace(processedContent),
  [processedContent]
);

Usage:

<EnrichedMarkdownText 
  markdown={finalMarkdown} 
/>

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions