Skip to main content

Quick start

This guide will get you parsing markdown in under 5 minutes. We’ll cover both basic parsing and streaming mode for incremental content.

Basic parsing

1

Import the parser

Start by importing the MarkdownParser class:
import { MarkdownParser } from "markdown-parser";
2

Create a parser instance

Instantiate the parser:
const parser = new MarkdownParser();
3

Parse markdown text

Call the parse method with your markdown string:
const nodes = parser.parse("# Hello World\nThis is a paragraph.");
The parser returns an array of typed block nodes:
// Result:
[
  { 
    type: "heading", 
    level: 1, 
    children: [{ type: "text", text: "Hello World" }] 
  },
  { 
    type: "paragraph", 
    children: [{ type: "text", text: "This is a paragraph." }] 
  }
]

Streaming mode

Streaming mode is perfect for parsing incremental content like LLM responses. The parser maintains state between calls and only returns finalized blocks.
1

Enable streaming mode

Create a parser instance and enable streaming:
import { MarkdownParser } from "markdown-parser";

const parser = new MarkdownParser();
2

Parse the first chunk

Pass the first chunk of content with stream: true:
const partialNodes = parser.parse("# Hello World\nThis", { stream: true });
The parser emits the heading (which is complete) but buffers the incomplete paragraph:
// Returns:
[
  { 
    type: "heading", 
    level: 1, 
    children: [{ type: "text", text: "Hello World" }] 
  }
]
3

Parse subsequent chunks

Continue parsing as more content arrives:
const moreNodes = parser.parse(" is a paragraph.\n\nThis is another paragraph.", { stream: true });
The first paragraph is now complete and gets emitted:
// Returns:
[
  { 
    type: "paragraph", 
    children: [{ type: "text", text: "This is a paragraph." }] 
  }
]
4

Finalize the stream

When the stream ends, call parse with stream: false or an empty string to emit remaining blocks:
const finalNodes = parser.parse("", { stream: false });
Any buffered content gets finalized:
// Returns:
[
  { 
    type: "paragraph", 
    children: [{ type: "text", text: "This is another paragraph." }] 
  }
]
In streaming mode, the parser keeps internal state across calls. Only blocks that are finalized (closed) are returned in each parse call.

React integration

Render markdown using React Server Components:
1

Import the component

import { Markdown } from "react-markdown-parser";
2

Render markdown content

Pass your markdown string to the content prop:
export function Article({ content }: { content: string }) {
  return (
    <div className="prose">
      <Markdown content={content} />
    </div>
  );
}
3

Customize components (optional)

Override default rendering with custom components:
<Markdown
  content={content}
  components={{
    CodeBlock: ({ content, info }) => {
      // Add syntax highlighting
      return (
        <pre data-lang={info}>
          <code>{content}</code>
        </pre>
      );
    },
    Link: ({ href, children }) => {
      // Add custom link handling
      return (
        <a href={href} rel="noreferrer">
          {children}
        </a>
      );
    },
  }}
/>

Complete example

Here’s a complete example parsing markdown with all major features:
import { MarkdownParser } from "markdown-parser";

const parser = new MarkdownParser();

const markdown = `
# Markdown Parser

A **modern** parser with _streaming_ support.

## Features

- Full CommonMark support
- Streaming mode
- TypeScript types

## Code Example

\`\`\`typescript
const parser = new MarkdownParser();
const nodes = parser.parse("# Hello");
\`\`\`

> Blockquotes are supported too!

| Feature | Supported |
| --- | --- |
| Tables | ✓ |
| Lists | ✓ |
`;

const nodes = parser.parse(markdown);

console.log(nodes);
// Array of typed block nodes:
// - heading (level 1)
// - paragraph with strong and emphasis
// - heading (level 2)
// - list (unordered)
// - heading (level 2)
// - code-block (with language)
// - blockquote
// - table
The parser follows the CommonMark specification for all parsing behavior, ensuring consistent and predictable results.

Working with node types

All nodes are fully typed. Use TypeScript’s type narrowing to handle different node types:
import { MarkdownParser, type BlockNode } from "markdown-parser";

const parser = new MarkdownParser();
const nodes = parser.parse("# Title\n\nParagraph");

for (const node of nodes) {
  switch (node.type) {
    case "heading":
      console.log(`Heading level ${node.level}`);
      break;
    case "paragraph":
      console.log("Paragraph");
      break;
    case "code-block":
      console.log(`Code block: ${node.info}`);
      break;
    // ... handle other types
  }
}

Next steps

API reference

Explore all available methods and node types

React components

Learn about customizing React component rendering

Streaming guide

Deep dive into streaming mode for LLM integration

Node types

Complete reference for all block and inline nodes

Build docs developers (and LLMs) love