gitlab-ce/doc/development/fe_guide/blob_syntax_highlighting.md

102 lines
4.3 KiB
Markdown

---
stage: Create
group: Source Code
info: Any user with at least the Maintainer role can merge updates to this content. For details, see https://docs.gitlab.com/ee/development/development_processes.html#development-guidelines-review.
---
# 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](https://highlightjs.org/) for client-side highlighting in the source viewer
- See the [full list of supported languages](https://github.com/highlightjs/highlight.js/blob/main/SUPPORTED_LANGUAGES.md)
- [Rouge](https://rubygems.org/gems/rouge) as a server-side fallback
- See the [full list of supported languages](https://github.com/rouge-ruby/rouge/wiki/list-of-supported-languages-and-lexers)
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:
1. Immediately render the first 70 lines in plaintext (without highlighting)
1. Request the WebWorker to highlight the first 70 lines
1. 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](https://developer.mozilla.org/en-US/docs/Web/API/Intersection_Observer_API)
## Adding Syntax Highlighting Support
There are two ways to add syntax highlighting support for new languages:
1. Using existing third-party language definitions
1. 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`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/package.json) and import the dependency in [`highlight_js_language_loader`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/app/assets/javascripts/content_editor/services/highlight_js_language_loader.js#L260).
**Example:**
- Add the dependency to `package.json`:
```javascript
// package.json
//...
"dependencies": {
"@gleam-lang/highlight.js-gleam": "^1.5.0",
//...
```
- Import the language in `highlight_js_language_loader.js`:
```javascript
// 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`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/app/assets/javascripts/repository/mixins/highlight_mixin.js):
```javascript
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/`](https://gitlab.com/gitlab-org/gitlab/-/tree/master/app/assets/javascripts/vue_shared/components/source_viewer/languages/).
To add support for a new language:
1. Create a new language definition file following the [Highlight.js syntax](https://highlightjs.readthedocs.io/en/latest/language-contribution.html).
1. Register the language in `highlight_js_language_loader.js`.
1. Add file extension mapping in `highlight_mixin.js` if needed.
Here are two examples of custom language implementations:
1. [Svelte](https://gitlab.com/gitlab-org/gitlab/-/commit/0680b3a27b3973287ae6a973703faf9472535c47)
1. [CODEOWNERS](https://gitlab.com/gitlab-org/gitlab/-/commit/825fd1e97df582b9f2654fc248c15e073d78d82b)