How Markdown Here Renders Math TeX/LaTeX Formulas: A Technical Deep Dive
Markdown Here renders TeX/LaTeX formulas by detecting $...$ patterns in the markdown lexer and converting them to image tags via an external rendering service.
The adam-p/markdown-here extension adds mathematical equation support to any email client or web-based editor by transforming inline TeX/LaTeX into embedded images. Understanding how this rendering pipeline works requires examining the custom lexer rules in the marked parser, the image generation logic, and the user configuration system that powers this feature.
Detection: Custom Lexer Rules in marked.js
The extension extends the standard markdown parser in src/common/marked.js with a dedicated math detection rule. This regex captures content between single dollar signs while excluding empty or whitespace-only matches.
The lexer adds a new token rule:
math: /^\$([^ \t\n\$]([^\$]*[^ \t\n\$])?)\$/,
When the parser encounters a sequence like $x^2$, it extracts the inner TeX code—stored in capture group cap[1]—and passes it to the renderer via the options.math callback. The regex specifically prevents matching consecutive dollar signs or whitespace-dominated content, ensuring that literal dollar amounts like $100 are not mistaken for math delimiters.
Processing: The mathify Function and Image Generation
In src/common/markdown-render.js, the mathify function handles the transformation from raw TeX to HTML image elements. This function substitutes placeholders in a user-defined template with the actual mathematical content.
function mathify(mathcode) {
return userprefs['math-value']
.replace(/\{mathcode\}/ig, mathcode)
.replace(/\{urlmathcode\}/ig, encodeURIComponent(mathcode));
}
The function performs two critical replacements:
{mathcode}injects the raw TeX for thealtattribute for accessibility{urlmathcode}provides the URL-encoded version for the imagesrcattribute
By default, src/common/options-store.js configures the extension to use the Codecogs rendering service:
'math-value': '<img src="https://latex.codecogs.com/png.image?\\dpi{120}\\inline&space;{urlmathcode}" alt="{mathcode}">',
Integration: Wiring the Renderer Hook
The connection between detection and processing occurs in src/common/marked.js within the renderer logic. When the lexer matches a math token, it invokes the configured handler:
if (this.options.math && (cap = this.rules.math.exec(src))) {
out += this.options.math(cap[1]);
}
The options.math hook is initialized in src/common/markdown-render.js based on user preferences:
math: userprefs['math-enabled'] ? mathify : null,
If math-enabled is false, the extension skips math processing entirely, treating dollar signs as literal characters.
Configuration: Customizing Templates and Services
Users control math rendering through src/common/options.js, which provides UI elements for toggling the math-enabled checkbox and editing the math-value template textarea. Changes are persisted via the OptionsStore mechanism.
Advanced users can redirect rendering to alternative services by changing the template. For example, to use the Google Chart API instead of Codecogs:
<img src="https://chart.googleapis.com/chart?cht=tx&chl={urlmathcode}" alt="{mathcode}">
The same mathify logic handles the placeholder substitution regardless of the target service.
Practical Examples: Input and Output
Markdown Input:
The quadratic formula is $-b \pm \sqrt{b^2-4ac}\over 2a$ and solves any second-order polynomial.
Generated HTML Output:
<p>The quadratic formula is
<img class="mdh-math"
src="https://latex.codecogs.com/png.image?\dpi{120}\inline&space;-b%20%5Cpm%20%5Csqrt%7Bb%5E2-4ac%7D%5Cover%202a"
alt="-b \pm \sqrt{b^2-4ac}\over 2a">
and solves any second-order polynomial.
</p>
Complex Integral Example:
$\int_0^\infty e^{-x^2}\,dx = \frac{\sqrt{\pi}}{2}$
This renders as an inline image with the TeX code URL-encoded in the src attribute and preserved as alt text for accessibility.
Summary
- Detection occurs in
src/common/marked.jsvia a custom regex that identifies$...$patterns while excluding whitespace-only matches. - Processing happens in
mathifywithinsrc/common/markdown-render.js, which substitutes{mathcode}and{urlmathcode}placeholders in user-defined templates. - Default rendering uses the Codecogs image service with 120 DPI inline PNG generation.
- User control is managed through
math-enabledandmath-valuepreferences stored insrc/common/options-store.js. - Extensibility allows advanced users to configure alternative rendering services by modifying the image template.
Frequently Asked Questions
Does Markdown Here support display-style (block) equations?
Markdown Here primarily supports inline math via single dollar signs ($...$). The lexer regex in src/common/marked.js specifically looks for single delimiters and excludes newlines from the captured content. While users can include display syntax commands like \displaystyle within the inline delimiters, true block-level equation support with double dollar signs ($$...$$) is not implemented in the current lexer rules.
Is the math rendering secure for sensitive equations?
The extension sends your TeX code to external image services (default: Codecogs) via HTTPS. While the connection is encrypted, the mathematical content is processed by third-party servers. Organizations handling sensitive intellectual property should modify the math-value template in src/common/options-store.js to point to an internal LaTeX rendering service rather than public APIs.
Can I use a different image format than PNG?
Yes, by modifying the image template in the extension options. The default template in src/common/options-store.js requests PNG format from Codecogs (png.image), but you can substitute alternative endpoints that return SVG or GIF formats. Ensure your template maintains the {urlmathcode} and {mathcode} placeholders so the mathify function correctly injects the encoded equation data.
Why are my dollar signs being interpreted as math when I don't want them to?
If math-enabled is true in src/common/options-store.js, the lexer aggressively matches any content between single dollar signs that meet the character constraints. To display literal dollar signs, you must either disable math rendering entirely in the options UI (src/common/options.js) or escape the content using backticks to create inline code blocks, which the lexer processes before evaluating math rules.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →