# How Markdown Here Converts Markdown to HTML: The Rendering Pipeline Explained

> Discover the Markdown Here rendering pipeline. Learn how it converts Markdown to HTML using the marked parser with custom extensions for syntax highlighting and math, then injects styled HTML.

- Repository: [Adam Pritchard/markdown-here](https://github.com/adam-p/markdown-here)
- Tags: internals
- Published: 2026-03-05

---

**Markdown Here converts Markdown to HTML through a three-stage pipeline that captures user input, processes it through the `marked` parser with custom extensions for syntax highlighting and math, then injects styled HTML back into the email compose area.**

The rendering pipeline in the `adam-p/markdown-here` repository is designed to keep heavy processing out of the content script while maintaining fast performance in browser extensions. This lightweight architecture enables seamless Markdown rendering directly within email clients like Gmail and Outlook.

## Stage 1: Capture and Dispatch (Content Script Entry Point)

When a user invokes Markdown Here, the process begins in the browser extension's content script. The **[`src/chrome/contentscript.js`](https://github.com/adam-p/markdown-here/blob/main/src/chrome/contentscript.js)** file extracts the selected text (or the entire textarea content) and dispatches the raw Markdown string to the core rendering engine.

The entry point function **`markdownHere()`** in [`src/common/markdown-here.js`](https://github.com/adam-p/markdown-here/blob/main/src/common/markdown-here.js) receives four critical arguments:

```javascript
markdownHere(document, markdownRenderer, logger, renderComplete);

```

The `markdownRenderer` parameter acts as a thin wrapper around **`MarkdownRender.markdownRender()`**, which lives in [`src/common/markdown-render.js`](https://github.com/adam-p/markdown-here/blob/main/src/common/markdown-render.js). This abstraction allows the content script to remain lightweight while delegating parsing work to the shared core library.

## Stage 2: Core Rendering Engine (markdown-render.js)

The heart of the Markdown to HTML conversion resides in **[`src/common/markdown-render.js`](https://github.com/adam-p/markdown-here/blob/main/src/common/markdown-render.js)**. The **`markdownRender()`** method orchestrates the transformation using three specialized external libraries configured through the `markedOptions` object (defined at lines 75-96).

### The Marked Parser with Custom Renderer

Markdown Here leverages the **`marked`** library (bundled in [`src/common/marked.js`](https://github.com/adam-p/markdown-here/blob/main/src/common/marked.js)) as its primary parser. Unlike standard implementations, the extension creates a custom `Renderer` instance to inject additional functionality:

- **Header anchor links** via `sanitizeLinkForAnchor` when the `header-anchors-enabled` preference is active
- **Automatic URL scheme addition** for bare URLs lacking protocols
- **Optional math rendering** through the `mathify` function when `math-enabled` is true

The core parsing call executes as follows:

```javascript
var renderedMarkdown = marked(mdText, markedOptions);

```

### Syntax Highlighting with highlight.js

Code blocks receive automatic syntax highlighting through **[`highlight.js`](https://github.com/adam-p/markdown-here/blob/main/highlight.js)**. The integration occurs via the `highlight` callback within `markedOptions`, which analyzes code language and applies the appropriate CSS classes. The `langPrefix` option specifically injects the `hljs` class into code blocks, ensuring compatibility with highlight.js themes.

### Math Rendering and Header Anchors

For users requiring mathematical notation, the pipeline conditionally processes LaTeX expressions through the math rendering helper. Header anchors are simultaneously processed to generate permalink fragments, allowing recipients to navigate long email documents via clickable table-of-contents links.

## Stage 3: Post-Processing and DOM Injection

After `markdownRender()` returns the HTML string, **`markdownHere()`** (lines 466-472 in [`src/common/markdown-here.js`](https://github.com/adam-p/markdown-here/blob/main/src/common/markdown-here.js)) performs final preparation before insertion:

1. **Container Wrapping** – The HTML is wrapped in a `<div class="mdh">` container to namespace the content
2. **Style Injection** – The CSS stylesheet (generated from [`src/chrome/markdown.css`](https://github.com/adam-p/markdown-here/blob/main/src/chrome/markdown.css) and injected via [`mdh.css`](https://github.com/adam-p/markdown-here/blob/main/mdh.css)) is attached to ensure the preview matches the final email appearance
3. **Content Replacement** – The content script's `markdownRenderComplete()` callback (defined at line 72 in [`src/chrome/contentscript.js`](https://github.com/adam-p/markdown-here/blob/main/src/chrome/contentscript.js)) replaces the original textarea or compose field content with the rendered HTML

The final styled HTML is then handed back to the host client (Gmail, Outlook, etc.) and displayed as the email body. For fallback scenarios, **`jsHtmlToText`** (via `htmlToText`) extracts plain-text from the generated HTML.

## Summary

- **Three-stage architecture**: Capture → Parse → Inject keeps the extension fast and modular
- **Primary parser**: `marked` with a custom Renderer for anchors, URLs, and math
- **Syntax highlighting**: [`highlight.js`](https://github.com/adam-p/markdown-here/blob/main/highlight.js) processes code blocks with `hljs` CSS classes
- **Entry points**: [`src/chrome/contentscript.js`](https://github.com/adam-p/markdown-here/blob/main/src/chrome/contentscript.js) captures input; [`src/common/markdown-here.js`](https://github.com/adam-p/markdown-here/blob/main/src/common/markdown-here.js) orchestrates the pipeline
- **Core rendering**: [`src/common/markdown-render.js`](https://github.com/adam-p/markdown-here/blob/main/src/common/markdown-render.js) contains the `markdownRender()` function that coordinates all conversion logic
- **Styling**: [`src/chrome/markdown.css`](https://github.com/adam-p/markdown-here/blob/main/src/chrome/markdown.css) provides email-compatible CSS injected via the `mdh` class wrapper

## Frequently Asked Questions

### What parser does Markdown Here use for Markdown conversion?

Markdown Here uses the **`marked`** library, bundled in [`src/common/marked.js`](https://github.com/adam-p/markdown-here/blob/main/src/common/marked.js), as its primary parser. According to the `adam-p/markdown-here` source code, the extension instantiates a custom `Renderer` class to modify default behavior, adding features like header anchors and automatic URL scheme detection while maintaining standard GitHub Flavored Markdown (GFM) compatibility.

### How does Markdown Here handle code syntax highlighting?

The pipeline integrates **[`highlight.js`](https://github.com/adam-p/markdown-here/blob/main/highlight.js)** through the `markedOptions.highlight` callback. When `markdownRender()` processes code blocks, it passes the code content to highlight.js, which returns syntax-colored HTML with the `hljs` CSS class prefix. This occurs during the `marked(mdText, markedOptions)` call in [`src/common/markdown-render.js`](https://github.com/adam-p/markdown-here/blob/main/src/common/markdown-render.js).

### Can Markdown Here render mathematical equations?

Yes, when the `math-enabled` preference is active, the rendering pipeline includes a **`mathify`** processing step within the custom `marked` Renderer. This step detects LaTeX syntax in the Markdown input and converts it to renderable mathematical notation before the final HTML generation completes.

### Where is the rendering logic located in the source code?

The rendering logic is split across three primary files: **[`src/chrome/contentscript.js`](https://github.com/adam-p/markdown-here/blob/main/src/chrome/contentscript.js)** handles initial text capture and final insertion; **[`src/common/markdown-here.js`](https://github.com/adam-p/markdown-here/blob/main/src/common/markdown-here.js)** contains the `markdownHere()` entry point that coordinates the pipeline; and **[`src/common/markdown-render.js`](https://github.com/adam-p/markdown-here/blob/main/src/common/markdown-render.js)** houses the `MarkdownRender.markdownRender()` method that executes the actual Markdown to HTML conversion using `marked` and [`highlight.js`](https://github.com/adam-p/markdown-here/blob/main/highlight.js).