How Markdown Here Implements Syntax Highlighting with Highlight.js
Markdown Here integrates Highlight.js by injecting the library into the extension's options page, then configuring the marked parser with a custom highlight callback that detects languages and returns colorized HTML wrapped in hljs CSS classes.
Markdown Here is a popular open-source browser extension that renders Markdown text into formatted HTML in email clients and web forms. One of its most valued features is syntax highlighting for fenced code blocks, which it achieves by leveraging the Highlight.js library. The implementation involves careful coordination between the extension's options storage, the Markdown parser configuration, and runtime theme management.
Loading the Highlight.js Library
The extension loads Highlight.js and its associated CSS themes through explicit script injection and configuration defaults, ensuring the library is available both for rendering previews and for the options page interface.
Script and Stylesheet Injection
In src/common/options.html, the Highlight.js library is loaded via a standard script tag:
<script src="highlightjs/highlight.js"></script>
Source: src/common/options.html (line 646)
This makes the hljs object available globally for the options page preview functionality.
Theme Management and Defaults
The default syntax highlighting theme is defined in src/common/options-store.js using the GitHub theme:
'syntax-css': {'__defaultFromFile__': '/common/highlightjs/styles/github.css', '__dataType__': 'text'}
Source: src/common/options-store.js (line 122)
To populate the theme selector in the options page, the extension reads a JSON catalogue of available themes:
Utils.getLocalFile(
Utils.getLocalURL('/common/highlightjs/styles/styles.json'), 'json',
function (syntaxStyles) { … });
Source: src/common/options.js (lines 71-78)
This allows users to switch between bundled themes like Monokai, Solarized, or GitHub without external dependencies.
Integrating Syntax Highlighting into the Markdown Parser
Markdown Here uses a custom build of marked, a JavaScript Markdown parser. The integration point is the highlight callback option, which intercepts code blocks during rendering and processes them through Highlight.js.
The Highlight Callback Function
In src/common/markdown-render.js, the marked parser is configured with a custom highlight function:
highlight: function (codeText, codeLanguage) {
if (codeLanguage &&
hljs.getLanguage(codeLanguage.toLowerCase())) {
return hljs.highlight(codeText,
{ language: codeLanguage.toLowerCase(),
ignoreIllegals: true }).value;
}
return codeText;
}
Source: src/common/markdown-render.js (lines 88-95)
This function performs three critical operations:
- Language Detection: Uses
hljs.getLanguage()to verify that Highlight.js supports the specified language (case-insensitive). - Syntax Highlighting: Calls
hljs.highlight()withignoreIllegals: trueto gracefully handle unrecognized tokens without throwing errors. - Fallback Handling: Returns the raw code text if no language is specified or recognized, ensuring the block still renders as plain text.
CSS Class Configuration
To ensure the highlighted output receives proper styling, the marked configuration sets a specific language prefix:
langPrefix: 'hljs language-',
Source: same file, line 86.
This prefix results in HTML output like <code class="hljs language-javascript">, which satisfies Highlight.js theme requirements—the hljs class triggers the theme's base styling, while the language-* class allows for language-specific overrides.
End-to-End Rendering Flow
Understanding the complete syntax highlighting pipeline helps clarify how the components interact:
-
User Input: A fenced code block is written with a language specifier:
```javascript function greet(name) { console.log('Hi '+name); } -
Parser Invocation: Marked identifies the code block and extracts the language (
javascript) and content. -
Highlight Processing: The custom highlight callback validates the language against
hljs.getLanguage(), then callshljs.highlight()to generate colorized HTML withignoreIllegals: true. -
HTML Generation: Marked wraps the highlighted code in
<pre><code class="hljs language-javascript">…</code></pre>. -
Styling Application: The extension injects the selected theme CSS (e.g.,
github.css) into the email compose window, applying colors to thehljsclasses.
Practical Implementation Example
Below is a minimal, runnable example demonstrating the same Highlight.js integration pattern used by Markdown Here:
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="highlightjs/styles/github.css">
<script src="highlightjs/highlight.js"></script>
</head>
<body>
<pre><code id="code-block"></code></pre>
<script>
const sourceCode = `function calculateTotal(items) {
return items.reduce((sum, item) => sum + item.price, 0);
}`;
// Check if language is supported
if (hljs.getLanguage('javascript')) {
// Apply syntax highlighting with error tolerance
const highlighted = hljs.highlight(sourceCode, {
language: 'javascript',
ignoreIllegals: true
}).value;
document.getElementById('code-block').innerHTML = highlighted;
document.getElementById('code-block').className = 'hljs language-javascript';
}
</script>
</body>
</html>
This example mirrors the production implementation in src/common/markdown-render.js, showing how to safely handle language detection and apply the hljs class for theme compatibility.
Summary
- Library Loading: Highlight.js is injected via
src/common/options.htmland configured with default themes insrc/common/options-store.js. - Parser Integration: The
highlightcallback insrc/common/markdown-render.jsbridges marked and Highlight.js, usinghljs.getLanguage()for validation andhljs.highlight()for processing. - CSS Classes: The
langPrefix: 'hljs language-'configuration ensures themes apply correctly to rendered code blocks. - Error Handling: The
ignoreIllegals: trueoption prevents crashes when code contains tokens unexpected by the language definition.
Frequently Asked Questions
How does Markdown Here detect the programming language in a code block?
Markdown Here relies on the language specifier provided in the fenced code block (e.g., ```javascript). The highlight callback in src/common/markdown-render.js passes this string to hljs.getLanguage() to verify support before calling hljs.highlight(). If the language is unsupported or omitted, the code renders as plain text without highlighting.
Can I use a custom Highlight.js theme with Markdown Here?
Yes. While the extension defaults to github.css as defined in src/common/options-store.js, the options page loads a catalogue of bundled themes from src/common/highlightjs/styles/styles.json. Users can select alternatives like Monokai or Solarized through the UI, and the extension injects the corresponding CSS into the compose window.
What happens if Highlight.js doesn't recognize the language specified?
If hljs.getLanguage() returns falsy for the specified language, the highlight callback in src/common/markdown-render.js returns the raw code text unchanged. This ensures the code block still appears in the output, just without colorization, preventing rendering failures due to typos or unsupported language identifiers.
Is the syntax highlighting applied in real-time or during rendering?
Syntax highlighting is applied during the rendering phase when the user triggers the Markdown Here conversion (typically via a hotkey or button click). The markdown-render.js module processes the entire document at once, calling hljs.highlight() for each fenced code block before injecting the final HTML into the compose window.
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 →