구문 강조 개발 가이드라인 (리포지터리 blob 뷰어)
GitLab v19.4요약
이 가이드는 리포지터리 소스 코드 뷰어의 구문 강조에 대한 모범 사례와 구현 세부 사항을 설명합니다. 소스 코드 뷰어는 이 두 가지 방식을 함께 사용해 폭넓은 언어 지원과 리포지터리 파일 조회 성능을 확보합니다. 구문 강조 구현은 다음 주요 컴포넌트로 이루어집니다.
이 가이드는 리포지터리 소스 코드 뷰어의 구문 강조에 대한 모범 사례와 구현 세부 사항을 설명합니다. GitLab은 두 가지 구문 강조 라이브러리를 사용합니다.
- 소스 뷰어의 클라이언트 측 강조에는 Highlight.js를 사용합니다.
- 지원 언어 전체 목록을 참고합니다.
- 서버 측 폴백에는 Rouge를 사용합니다.
- 지원 언어 전체 목록을 참고합니다.
소스 코드 뷰어는 이 두 가지 방식을 함께 사용해 폭넓은 언어 지원과 리포지터리 파일 조회 성능을 확보합니다.
컴포넌트 개요#
구문 강조 구현은 다음 주요 컴포넌트로 이루어집니다.
blob_content_viewer.vue: 파일 콘텐츠를 표시하는 기본 컴포넌트입니다.source_viewer.vue: 소스 코드 렌더링을 담당합니다.highlight_mixin.js: 강조 처리와 WebWorker 통신을 관리합니다.highlight_utils.js: 콘텐츠 청크 분할과 처리를 위한 유틸리티를 제공합니다.
성능 원칙#
콘텐츠를 최대한 빠르게 표시#
단계적 렌더링 방식으로 콘텐츠 표시를 최적화합니다.
- 처음 70줄을 강조 없이 평문으로 즉시 렌더링합니다.
- WebWorker에 처음 70줄의 강조를 요청합니다.
- WebWorker에 파일 전체의 강조를 요청합니다.
브라우저 성능 유지#
브라우저 성능을 양호하게 유지하는 방법은 다음과 같습니다.
- 강조 작업이 메인 스레드를 막지 않도록 WebWorker를 사용합니다.
- 강조된 콘텐츠를 청크로 나누고 IntersectionObserver API로 사용자가 스크롤할 때 렌더링합니다.
구문 강조 지원 추가#
새 언어의 구문 강조 지원은 다음 방법으로 추가할 수 있습니다.
- 기존 서드파티 언어 정의를 사용합니다.
- GitLab 코드베이스에 사용자 지정 언어 정의를 만듭니다.
어떤 방법을 선택할지는 해당 언어에 Highlight.js 호환 정의가 이미 있는지에 따라 달라집니다.
서드파티 정의가 있는 언어#
package.json에 서드파티 의존성을 추가하고 highlight_js_language_loader에서 해당 의존성을 import 할 수 있습니다.
예시는 다음과 같습니다.
package.json에 의존성을 추가합니다.
// package.json
//...
"dependencies": {
"@gleam-lang/highlight.js-gleam": "^1.5.0",
//...
highlight_js_language_loader.js에서 해당 언어를 import 합니다.
// highlight_js_language_loader.js
//...
gleam: () => import(/* webpackChunkName: 'hl-gleam' */ '@gleam-lang/highlight.js-gleam'),
//...
언어가 여전히 평문으로 표시된다면 highlight_mixin.js에 파일 확장자 기반 언어 감지를 추가해야 할 수 있습니다.
if (name.endsWith('.gleam')) {
language = 'gleam';
}
기존 정의가 없는 언어#
새 언어 정의는 ~/vue_shared/components/source_viewer/languages/ 아래에 코드베이스로 추가할 수 있습니다.
새 언어 지원을 추가하는 방법은 다음과 같습니다.
- Highlight.js 문법에 따라 새 언어 정의 파일을 만듭니다.
highlight_js_language_loader.js에 해당 언어를 등록합니다.- 필요하다면
highlight_mixin.js에 파일 확장자 매핑을 추가합니다.
사용자 지정 언어 구현 예시는 다음 두 가지입니다.
색상 스킴 미리보기 썸네일#
사용자 환경 설정의 구문 강조 색상 스킴마다
app/assets/images/<scheme>-scheme-preview.png에 미리보기 썸네일이 있습니다. 하나의 HTML 템플릿이 모든 썸네일을
GitLab Mono로 렌더링하므로, 썸네일은 스킴 간에 일관성을 유지하면서 각 스킴의 팔레트와 일치합니다.
스킴을 추가하거나 테마 색상을 변경한 뒤에는 썸네일을 다시 생성합니다.
bundle exec rake gitlab:color_schemes:preview_images
이 작업은 Rouge 렉서로 샘플 스니펫을 토큰화합니다. 각 토큰은 스킴 스타일시트
(app/assets/stylesheets/highlight/themes/<scheme>.scss)에서 해당 토큰의 클래스가 가진 값으로
색을 입히므로, 새 테마는 그 색상 맵에서 일치하는 미리보기를 얻습니다. 이 작업은 2배 크기로 렌더링한 뒤
결과를 축소해 글자 가장자리를 매끄럽게 유지하고,
이어서 pngquant를 실행해 썸네일 용량을 작게 유지합니다.
이 작업에는 헤드리스 Chrome 또는 Chromium 바이너리가 필요합니다. 바이너리가 PATH에 없다면
CHROME_BIN을 설정합니다. 출력을 최적화하려면 pngquant를 설치합니다. pngquant가 없으면
이 작업은 경고를 남기고 최적화를 건너뜁니다.