Syntax highlighting development guidelines (repository blob viewer)
This guide outlines best practices and implementation details for syntax highlighting in the repository source code viewer. GitLab uses two syntax highlighting libraries:
-
Highlight.js for client-side highlighting in the source viewer
- See the full list of supported languages
-
Rouge as a server-side fallback
- See the full list of supported languages
The source code viewer uses this dual approach to ensure broad language support and optimal performance when viewing files in the repository.
Components Overview
The syntax highlighting implementation consists of several key components:
-
blob_content_viewer.vue
: Main component for displaying file content -
source_viewer.vue
: Handles the rendering of source code -
highlight_mixin.js
: Manages the highlighting process and WebWorker communication -
highlight_utils.js
: Provides utilities for content chunking and processing
Performance Principles
Display content as quickly as possible
We optimize the display of content through a staged rendering approach:
- Immediately render the first 70 lines in plaintext (without highlighting)
- Request the WebWorker to highlight the first 70 lines
- Request the WebWorker to highlight the entire file
Maintain optimal browser performance
To maintain optimal browser performance:
- Use a WebWorker for the highlighting task so that it doesn’t block the main thread
- Break highlighted content into chunks and render them as the user scrolls using the IntersectionObserver API
Adding Syntax Highlighting Support
There are two ways to add syntax highlighting support for new languages:
- Using existing third-party language definitions
- Creating custom language definitions in our codebase
The method you choose depends on whether the language already has a Highlight.js compatible definition available.
For Languages with Third-Party Definitions
We can add third-party dependencies to our package.json
and import the dependency in highlight_js_language_loader
.
Example:
- Add the dependency to
package.json
:
// package.json
//...
"dependencies": {
"@gleam-lang/highlight.js-gleam": "^1.5.0",
//...
- Import the language in
highlight_js_language_loader.js
:
// highlight_js_language_loader.js
//...
gleam: () => import(/* webpackChunkName: 'hl-gleam' */ '@gleam-lang/highlight.js-gleam'),
//...
If the language is still displayed as plaintext, you might need to add language detection based on the file extension in highlight_mixin.js
:
if (name.endsWith('.gleam')) {
language = 'gleam';
}
For Languages Without Existing Definitions
New language definitions can be added to our codebase under ~/vue_shared/components/source_viewer/languages/
.
To add support for a new language:
- Create a new language definition file following the Highlight.js syntax.
- Register the language in
highlight_js_language_loader.js
. - Add file extension mapping in
highlight_mixin.js
if needed.
Here are two examples of custom language implementations: