The Markdown Indentation Problem

If you've ever tried to write markdown inside a component or a template literal, you've likely run into the classic whitespace trap. Most markdown parsers treat indentation beyond four spaces as a code block. So, when you write:

This is a paragraph
    This is a second paragraph

You get an output like <p>This is a paragraph</p><pre><code>This is a second paragraph</code></pre> instead of two clean paragraphs.

This forces you to strip all indentation, making your code hard to read and maintain. But there's a better way.

The Solution: A Custom Markdown Utility

I built a utility that solves this by normalizing whitespace before parsing. It detects the base indentation and removes it, so you can write naturally indented markdown without breaking the output.

Here's the core logic:

import { unified } from 'unified'
import remarkParse from 'remark-parse'
import remarkRehype from 'remark-rehype'
import rehypeStringify from 'rehype-stringify'

export function markdown(content, { inline = false } = {}) {
  // Remove base indentation from the content
  const lines = content.split('\n')
  const baseIndent = getBaseIndent(lines)
  const normalized = lines.map(line => line.slice(baseIndent)).join('\n')

  const processor = unified()
    .use(remarkParse)
    .use(remarkRehype)
    .use(rehypeStringify)

  if (inline) {
    // Wrap in a division to parse inline elements only
    const html = processor.processSync(normalized).toString()
    return html.replace(/^<p>|<\/p>$/g, '')
  }

  return processor.processSync(normalized).toString()
}

function getBaseIndent(lines) {
  const nonEmpty = lines.filter(l => l.trim())
  const indents = nonEmpty.map(l => l.match(/^\s*/)[0].length)
  return Math.min(...indents)
}

Key points:

  • The utility calculates the minimum indentation across all non-empty lines and removes it.
  • For inline content, it strips the wrapping <p> tags.
  • It works with any markdown parser; you can swap remark for marked or markdown-it.

Developer writing markdown with proper indentation in a code editor Coding Session Visual

Using the Utility in Astro

Here's how to integrate it into an Astro component:

---
import { markdown } from '@splendidlabz/utils'

const { inline = false, content } = Astro.props
const slotContent = await Astro.slots.render('default')

// Process content
const html = markdown(content || slotContent, { inline })
---

<div set:html={html} />

Then you can use it like this:

<Markdown>
  This is a paragraph
  This is a second paragraph
</Markdown>

Using the Utility in Svelte

Svelte doesn't allow dynamic slot content, so you pass the content as a prop:

<script>
  import { markdown } from '@splendidlabz/utils'
  export let content = ''
  const html = markdown(content)
</script>

{@html html}

Usage:

<Markdown content={`
  This is a paragraph
  This is a second paragraph
`} />

For React and Vue

You can easily adapt the same pattern. In React, use dangerouslySetInnerHTML; in Vue, use v-html.

Markdown component rendering in a web framework like React or Vue Software Concept Art

Caveats and Limitations

While this utility solves the indentation problem, it's not a full-featured markdown renderer. It doesn't support syntax highlighting or custom components. For that, you might need a more robust solution like react-markdown or remark plugins.

Also, note that this utility is synchronous. For very large documents, you might want to use the async API to avoid blocking the main thread.

Next Steps

If you're building a content-heavy site, consider extending this utility with:

  • Syntax highlighting for code blocks
  • Table of contents generation
  • Custom link handling

For more on improving your developer experience, check out my other posts on Claude Opus 4.6 on Azure and NVIDIA IGX Thor. The latter is a great example of how edge AI platforms are pushing the boundaries of real-time processing.

Code snippet showing a custom markdown utility function in JavaScript IT Technology Image

Conclusion

Markdown doesn't have to be a pain to integrate into your favorite framework. With this utility, you can write clean, indented markdown and get the correct HTML output every time. It's lightweight, framework-agnostic, and easy to extend.

Try it in your next project and say goodbye to whitespace headaches. For more tips and utilities, visit my blog. Happy coding!

This content was drafted using AI tools based on reliable sources, and has been reviewed by our editorial team before publication. It is not intended to replace professional advice.