GitLab Flavored Markdown (GLFM) 사양 가이드

요약

  • GitLab Flavored Markdown (GLFM)은 GitHub Flavored Markdown (GFM)을 기반으로 합니다. 이는 CommonMark를 기반으로 합니다.
  • GLFM은 두 가지 “세트”의 Markdown 구문으로 나뉩니다:
    • 공식 사양“은 특정 구현이나 환경에 의존하지 않으며, 모든 에디터에서 지원될 수 있습니다.
    • 내부 확장“은 GitLab 환경 및 메타데이터에 따라 달라질 수 있습니다.
  • 이러한 구문 세트의 모든 내용은 특별한 Markdown 파일에 의해 지정되며, 이 파일들은 CommonMark 사양 구문을 기반으로 하며, Markdown 및 해당 생성된 HTML의 사이드바 “예제”와 각 예제를 설명하는 연관된 문서를 포함합니다.
  • 또한 Markdown/YAML 파일과 그들이 포함하는 예제는 여러 목표를 달성합니다:
  • 상기 목표를 달성하기 위해 다양한 스크립트와 로직가 있습니다.

소개

GitLab은 여러 곳에서 Markdown을 지원합니다. 우리가 사용하는 Markdown 방언은 GitLab Flavored Markdown (GLFM)라고 합니다.

note
이 문서에서 GFM_은 _GitHub Flavored Markdown이 아닌 GitLab Flavored Markdown을 의미합니다. 이 문서에서 사용된 다양한 약어의 자세한 설명은 약어 섹션을 참조하세요.

GLFM 방언의 사양은 GitHub Flavored Markdown (GFM) 사양을 기반으로 하며, 다시 말해 CommonMark 사양을 기반으로 합니다. GLFM 사양에는 GFM 사양과 비교했을 때 많은 추가 기능이 포함되어 있습니다.

이 가이드는 GLFM 사양과 관련된 용어, 정의, 목표, 도구 및 구현에 대해 설명하는 개발자를 대상으로 하는 문서입니다. GitLab Flavored Markdown에 대한 사용자를 대상으로 하는 문서를 지원하고 보완하기 위한 것입니다.

note
이 가이드와 그 내용에 설명된 구현 및 파일은 여전히 진행 중인 작업입니다. 작업이 진행되는 동안, 이 가이드와 GitLab Flavored Markdown을 위한 사용자를 대상으로 하는 문서 사이의 재작성 및 통합이 있을 수 있습니다.

용어 및 정의

약어: GLFM, GHFM, GFM, CommonMark

GitHub Flavored Markdown은 널리 알려진 GFM 약어로 언급되며, 본 문서도 해당 관례를 따릅니다. 이 문서에서 GitLab Flavored Markdown은 GLFM으로 언급되며, GitHub Flavored Markdown과 구분됩니다.

불행하게도, 이 관례는 여전히 일관되게 적용되지 않았습니다. 많은 곳에서 GFM 약어가 GitLab Flavored Markdown을 가리키는 데 사용됩니다. 이러한 불일치를 해결하기 위한 오픈 이슈가 존재합니다.

일부 코드에서는 해당 로직 영역에서 GitLab 및 GitHub 사양을 동시에 참조합니다. 이러한 상황에서는 GitHub Flavored Markdown이 변수나 상수 이름으로 ghfm_과 같이 참조될 수 있습니다. 예를 들어 ghfm 약어를 사용하여 ghfm_spec_v_0.29.md GitHub Flavored Markdown 사양 파일을 사용합니다. 이 파일은 gitlab 리포지터리에 커밋되어 update_specification.rb 스크립트의 입력으로 사용됩니다.

최초의 CommonMark 사양은 CommonMark (약어 없음)이라고 언급됩니다.

다양한 Markdown 사양

사용하는 사양 형식은 CommonMark에서 사용하는 방식을 기반으로 합니다. CommonMark에서는 spec.txt 파일이 문서로서의 역할 뿐만 아니라 자동 준수 테스트의 입력으로도 작용하는 형식입니다. 이에 대한 설명은 CommonMark 사양에서 확인할 수 있습니다:

이 문서는 Markdown 구문을 모호하지 않게 지정하려는 시도입니다. Markdown 및 HTML의 사이드바 예제가 많이 포함되어 있습니다. 이러한 예제는 준수 테스트로 사용될 것을 의도되었습니다.

다음은 사양에 따라 렌더링된 HTML 버전입니다:

그러나 GLFM은 GFM 또는 CommonMark보다 더 복잡한 구문 분석, 렌더링 및 테스트 요구사항을 갖고 있습니다. 따라서 정적이고 하드코딩된 spec.txt가 없습니다. 대신, GLFM spec.txt은 다른 입력 파일을 기반으로 자동으로 생성됩니다. 이 프로세스에 대한 자세한 내용은 아래의 구현 섹션에 설명되어 있습니다.

note
2022년 12월 기준, GitHub Flavored Markdown (GFM) 사양의 HTML 버전이 최신이 아니며, 사양의 spec.txt와 일치하지 않습니다. 이에 대한 문제가 cmark-gfm 프로젝트에 보고되었습니다.

공식 사양 대 내부 확장

GitHub의 GFM과 GitLab의 GLFM은 지원하는 Markdown의 두 “세트”가 있습니다:

  • 공식 사양
  • 내부 확장

다음 분류 차트는 다양한 사양의 분류 및 용어를 보여줍니다:

CommonMark - spec.txt - 예: 제목
GFM 사양 - spec.txt - 예: 중간 선 확장
GLFM 사양 - 예: 색 칩
GFM 내부 확장 - 예: GitHub 특정 참조
GLFM 내부 확장 - 예: GitLab 특정 참조
공식 사양

GFM 및 GLFM에는 각자 공식 사양이 있으며, 이에는 다음이 포함됩니다:

  1. CommonMark 표준.
  2. CommonMark 표준에 대한 일반적인 확장.

예를 들어, GFM은 strikethrough 확장을 추가하고, GLFM은 color chips 확장을 추가합니다. 이러한 확장은 특정 구현이나 환경에 의존하지 않습니다. 이를 제3자 Markdown 렌더링 엔진에 구현할 수 있습니다.

내부 확장

GFM 및 GLFM에는 각각 내부 확장 세트도 있습니다. 이러한 확장은 GFM 또는 GLFM 공식 사양의 일부는 아니지만 GitHub 및 GitLab 내부 Markdown 렌더러 및 파서 구현의 일부입니다. 이러한 내부 확장은 종종 GitHub 또는 GitLab 구현이나 환경에 의존하며 해당 환경과 상호 작용을 통해 사용 가능한 메타데이터에 의존할 수 있습니다. 예를 들어, GitHub는 GitHub 특정 자동 링크 참조를 지원하며, GitLab은 GitLab 특정 참조도 지원합니다. 이러한 확장은 GitHub 또는 GitLab과 통합되는 제3자 Markdown 렌더링 엔진에서도 구현될 수 있습니다. 예를 들어, 편집기 또는 IDE 플러그인을 통해 사용자가 편집기나 IDE 내에서 직접 이슈, 풀 리퀘스트 또는 Merge Request의 Markdown을 편집할 수 있게 됩니다.

Markdown 예시

사양 및 이 가이드 문서의 맥락에서 예시 용어는 명시적 파싱(또는 렌더링) 동작을 보여주기 위해 역따옴표로 구분된 Markdown + HTML 쌍을 사용하는 관행을 참조하는데 특별히 사용됩니다. 이러한 맥락에서 다른 유사하거나 관련된 _예시_의 의미와 혼동해서는 안 됩니다. 예를 들어, RSpec 예시와 같은 예시와 혼동해서는 안 됩니다.

_backtick-delimited Markdown+HTML 예시 구문_에 대한 자세한 내용은 glfm_official_specification.md 파일 섹션을 참조하십시오.

파서 및 렌더러

사양의 사용 방식 및 Markdown dialeta의 관계를 이해하기 위해 _파서_와 _렌더러_의 구별을 이해하는 것이 중요합니다:

  • Markdown _파서_는 Markdown을 입력으로 받아들이고 Markdown 추상 구문 트리(AST)를 출력으로 생성합니다.
  • Markdown _렌더러_는 파서에 의해 생성된 AST를 입력으로 받아들이고 HTML(또는 PDF 또는 기타 관련된 렌더링 형식)을 출력으로 생성합니다.

GLFM 사양에 의해 주도되는 Markdown 테스트 유형

자동화된 테스트의 두 주요 유형은 GLFM 사양에 포함된 Markdown의 예시 및 데이터에 의해 주도됩니다. 이를 다음과 같이 표현합니다:

  • Markdown 일치 테스트.
  • Markdown 스냅샷 테스트.

GitLab 코드베이스에서 다양한 유형의 테스트도 발생하며, 이러한 테스트 중 일부는 GLFM Markdown dialeta와도 관련이 있습니다. 따라서 혼동을 피하기 위해 본 설명서 및 다른 곳에서 이러한 특정 유형의 사양 주도 테스트에 대해 표준 용어를 사용합니다.

Markdown 일치 테스트

note
GLFM에 대한 Markdown 일치 테스트는 아직 구현되지 않았습니다.

_마크다운 일치 테스트_는 특정 구현이 CommonMark 마크다운 사양에 준수하는지 확인하는 데 사용되는 표준 테스트 방법을 참조합니다. 이 테스트는 특정 spec.txt 사양 및 구현에 대해 CommonMark 툴인 spec_tests.py를 실행함으로써 강제적으로 수행됩니다. 자세한 내용은 사양 자체의 설명에 설명되어 있습니다.

일치 테스트는 공식 사양의 예시에 대해만 실행되어야 하며 내부 확장 예시에 대해 실행해서는 안 됩니다. 이는 내부 확장 예시가 GitLab 환경이나 메타데이터에 의존할 수 있지만 표준 CommonMark 일치 테스트 도구가 이를 지원하지 않기 때문입니다.

note
spec_tests.py는 최종적으로 Python에 의존성을 갖지 않도록 Ruby로 다시 구현될 수 있습니다.

Markdown 스냅샷 테스트

_마크다운 스냅샷 테스트_는 GitLab 코드베이스에서 수행되는 자동화된 테스트를 참조하며, 이는 GLFM 사양의 모든 예시에서 파생된 example_snapshots 픽스처 데이터를 기반으로 합니다. 이는 백엔드 RSpec 테스트 및 프론트엔드 Jest 테스트로 구성되어 있으며 이는 픽스처 데이터를 사용합니다. 이 픽스처 데이터는 YAML 파일에 포함되어 있으며 사양의 마크다운 예시를 기반으로 생성 및 업데이트되며 기존의 GLFM 파서 및 렌더러 구현에서 파생됩니다. 또한 불완전한 구현을 테스트하거나 기술을 테스트하기 위해 필요한 경우에는 명시적으로 업데이트할 수도 있습니다.

스냅샷 테스트는 모든 예시에 대해 철저히 실행되어야 하며, GLFM 공식 사양내부 확장 예시를 일치시킵니다. 이는 내부 확장 예시가 요구되는 GitLab 특정 환경 또는 메타데이터를 제공하기 위한 구성 파일을 사용하기 때문입니다. 예를 들어, glfm_example_metadata.yml와 같은 파일입니다.

스냅샷 테스트의 설계는 사용자에게 노출되는 GLFM Markdown의 정확성을 보장하는 데 도움이 됩니다. 이러한 테스트는 백엔드 및 프론트엔드 파서 및 렌더러를 철저히 검증하여 블랙박스 테스팅 접근 방식을 사용합니다. 이러한 철저한 스타일 때문에 이것은 “테스트 피라미드의 맨 위”에 해당하는 고수준 테스트 유형으로 간주될 수 있습니다.

마크다운 스냅샷 테스트에 사용된 용어에 대한 설명: </br>

  1. 마크다운 스냅샷 테스트는 Golden Master Testing 접근 방식의 한 형태로 간주될 수 있으며, Approval Testing 또는 Characterization Testing으로도 불립니다.
    1. Golden Master 용어는 원래 녹음 산업에서 유래했으며 최종 믹스를 만들거나 다른 모든 복사본을 생성하는 과정을 가리킵니다.
    2. 자세한 정보와 배경은 Characterization TestsGolden Masters를 참조하십시오.
  2. 스냅샷 용어의 사용은 다른 GitLab 프론트엔드 테스트 스위트에서 사용되는 Jest 스냅샷 테스팅의 방법을 가리키지는 않지만, 마크다운 스냅샷 테스트는 Jest 스냅샷 테스트와 동일한 철학과 패턴을 따릅니다.
    1. 스냅샷 예시 픽스처 데이터는 소스 컨트롤에 체크된 파일로 표시됩니다.
    2. 파일은 테스트 중인 코드의 구현에 따라 자동 생성 및 업데이트될 수 있습니다.
    3. 파일은 필요한 경우에는 매뉴얼으로 업데이트할 수도 있으며, 예를 들어 불완전하거나 버그가 있는 구현을 테스트하기 위해.
  3. fixture 용어의 사용은 표준 Rails database fixture 파일을 참조하지 않습니다. 대신, 이는 보다 일반적인 정의의 _test fixtures_를 참조하며 자동화된 테스트를 위한 입력 데이터를 지원합니다.
  4. 이러한 예시 스냅샷 픽스처 파일은 GLFM 사양의 나머지 부분에서 파생되고 밀접하게 관련되어 있습니다. 따라서 example_snapshots 디렉터리는 나머지 GLFM 사양 파일과 함께 동일한 폴더에 위치합니다. 이러한 픽스처 파일은 의도적으로 GitLab Rails 애플리케이션의 spec/fixtures 디렉터리에 위치하지 않습니다. 실제로 개발자들은 이러한 파일을 spec/fixtures 디렉터리로 나누기보다는 glfm_specification 디렉터리 하위에 있는 모든 것을 갖는 것이 더 간단하고 이해하기 쉽다고 판단했습니다.

아래의 normalization 섹션도 참조하십시오. 이는 마크다운 스냅샷 테스트에 사용되는 중요한 개념입니다.

구문 분석 및 렌더링

GitLab 애플리케이션에서 사용되는 Markdown 방언은 두 가지 렌더링 요구 사항을 갖고 있습니다:

  1. 다양한 위치에서 표시되는 정적 읽기 전용 HTML 형식으로 렌더링합니다.
  2. 리치 텍스트 편집기에서 편집 가능한 콘텐츠를 렌더링합니다. 리치 텍스트 편집기는 실시간 즉시 편집 가능한 Markdown 소스와 WYSIWYG 문서로의 실시간 전환을 지원합니다.

이러한 요구 사항으로 인해 GitLab은 두 개의 독립적인 파서 및 렌더러 구현을 갖고 있습니다:

  1. 백엔드 파서 / 렌더러는 정적 읽기 전용 HTML로 파싱 및 렌더링을 지원합니다. 이는 Ruby로 구현되어 있으며 libcmark-gfm의 Ruby 래퍼인 commonmarker gem을 활용합니다. libcmark-gfmCommonMark의 C 참조 구현의 확장 버전입니다.
  2. 프론트엔드 파서 / 렌더러는 리치 텍스트 편집기를 위해 파싱 및 WYSIWYG 렌더링을 지원합니다. 이는 JavaScript로 구현되었습니다. 파싱은 Remark Markdown 파서를 기반으로 하며, MDAST 추상 구문 트리(MDAST)를 생성합니다. 렌더링은 MDAST를 ProseMirror 문서로 변환하는 과정입니다. 그런 다음 ProseMirror가 ProseMirror 문서를 WYSIWYG HTML로 렌더링하는 데 사용됩니다. 이 문서에서는 Markdown을 MDAST로 변환하는 과정을 프론트엔드 / JavaScript 파서, Markdown을 WYSIWYG HTML로 렌더링하는 과정 전체를 _리치 텍스트 편집기_로 참조합니다. 필요에 따라 독립적인 프론트엔드 파서 / 렌더러 구현이 필요한 여러 요구 사항이 있습니다.
    1. 백엔드에서 사용되는 HTML 렌더러에서 정확한 소스 매핑을 지원하기에 부족한 점
    2. 지연 시간 및 대역폭 문제: 사용자가 Markdown 소스와 WYSIWYG 문서 간 전환 시마다 백엔드로 왕복할 필요를 제거하는 것
    3. WYSIWYG 문서에 지원되는 다양한 HTML 및 브라우저 렌더링 요구 사항. 예를 들어, 편집 가능한 형태로 읽기 전용 요소인 다이어그램 및 참조 표시

렌더링된 HTML의 다중 버전

GLFM 렌더러 구현(static 및 WYSIWYG)은 GLFM 공식 사양에서의 Markdown 예제에 있는 HTML과 다를 수 있습니다. 따라서 GLFM 사양의 Markdown 예제마다 예제에서 렌더링될 수 있는 HTML 버전이 3개가 됩니다:

  • 정적 HTML
  • WYSIWYG HTML
  • 규범적 HTML

정적 HTML

정적 HTML은 백엔드(Ruby) 렌더러에 의해 생성된 HTML로, 추가적인 스타일링 및 동작 HTML이 포함되어 있습니다. 예를 들어, 작업 디렉터리 항목에서 동적으로 이슈를 생성하기 위해 추가된 작업 생성 버튼 등이 있습니다. GitLab Markdown API는 이 방법을 사용하여 주어진 Markdown 문자열에 대한 HTML을 생성합니다.

Markdown 예제에 지정된 Markdown은 glfm_specification/output_example_snapshots/html.yml에서 자동으로 HTML을 생성하는 데 사용되며, 이는 update-example-snapshots.rb을 실행할 때 사용됩니다. 이러한 예제는 Markdown 스냅샷 테스트 실행 시 사용됩니다.

WYSIWYG HTML

WYSIWYG HTML은 프론트엜드(JavaScript) 리치 텍스트 편집기에 의해 생성된 HTML로, 파싱 및 렌더링 로직이 포함되어 있습니다. ProseMirror WYSIWYG 편집기에서 편집 가능한 문서를 표시하는 데 사용됩니다.

정적 HTML과 마찬가지로, Markdown 예제에 지정된 Markdown은 glfm_specification/output_example_snapshots/html.yml에서 자동으로 HTML을 생성하는 데 사용되며, 이는 update-example-snapshots.rb을 실행할 때 사용됩니다. 이러한 예제는 Markdown 스냅샷 테스트 실행 시 사용됩니다.

규범적 HTML

규범적 HTML은 Markdown에서 렌더링된 기본적이고 깨끗한 버전의 HTML로, 스타일링과 구현 특정 동작과 관련된 불필요한 클래스/요소가 없습니다.

이것은 GLFM spec.txt에 대한 Markdown 준수 테스트를 지원하는 것입니다.

이 HTML은 항상 하드코딩되며 매뉴얼으로 관리되며, 절대로 자동으로 생성되지 않습니다. 이에 대한 Markdown 예제는 다양한 Markdown 사양으로부터 어떤 예제가 원래인지를 기반으로 서로 다른 파일에 포함됩니다.

공식적인 CommonMark, GFM, 및 GLFM 사양에 속하는 Markdown 예제의 모든 모든 경우에 규범적 HTML이 항상 지정됩니다.

그러나 GLFM 내부 확장에서의 Markdown 예제에 대해서는 규범적 HTML이 지정되지 않습니다. 이는 내부 확장이 Markdown 준수 테스트를 통해 테스트되지 않기 때문에 내부 확장의 예제에 대한 규범적 HTML은 어떤 스크립트나 자동 테스트에서도 사용되지 않습니다.

다음은 규범적 HTML 예제의 원본에 대한 자세한 정보입니다:

  1. CommonMark 사양 및 GFM 확장 사양의 예제의 경우, 규범적 HTML은 GFM spec.txt에 있는 Markdown 예제 블록 내에 정확히 동일한 HTML입니다. 이러한 예제는 GFM spec.txt에서 GLFM 버전의 spec.txt로 직접 복사됩니다.
  2. GLFM 공식 사양에 속하는 예제의 경우, 규범적 HTML은 입력 사양 파일glfm_official_specification.md에 포함된 예제를 통해 매뉴얼으로 유지하고 관리됩니다.
  3. GLFM 내부 확장에 속하는 예제의 경우, 규범적 HTML 가 지정되지 않으며, 모든 예제에서 비워둬야 합니다.

HTML의 Canonicalization

백엔드(Ruby) 및 프론트엔드(JavaScript) 렌더러에서 렌더링된 정적 HTMLWYSIWYG HTML에는 특정한 외형 및 동작 요구 사항을 지원하기 위해 추가적인 스타일이나 HTML 요소가 포함될 수 있습니다.

백엔드나 프론트엔드 렌더링 로직은 canonical HTML에 대한 Markdown 준수 테스트를 수행할 때 비교할 수 있는 깨끗하고 기본적인 HTML을 직접적으로 렌더링할 수 없습니다.

그들이 직접 렌더링할 수 없어야 하는 이유는 다음과 같습니다.

  • 어떤 GitLab 애플리케이션 기능을 지원하는 것이 직접적인 요구 사항이 아닙니다.
  • 이 기능을 추가하면 구현이 복잡해지고 불필요한 요구 사항이 추가됩니다.

대신, 렌더링된 정적 또는 WYSIWYG HTML은 정규화 프로세스에 의해 canonical HTML로 변환됩니다. 이 프로세스는 정적 또는 WYSIWYG HTML에서 모든 추가적인 스타일링 및 동작 HTML을 제거하여 표준 spec.txt 사양의 canonical HTML과 정확히 일치하는 canonical HTML을 생성합니다.

이 프로세스에는 canonicalize-html.rb 스크립트를 사용합니다.

정규화

렌더링된 HTML 및 ProseMirror JSON의 버전은 여러 이유로 다를 수 있습니다. 스타일링이나 HTML 구조의 차이뿐만 아니라 속성 또는 노드의 값이 여러 다른 테스트 실행 또는 환경에서도 다를 수 있습니다. 예를 들어:

  1. 데이터베이스 레코드 식별자
  2. 네임스페이스 또는 프로젝트 식별자
  3. URI 일부
  4. 파일 경로 또는 이름
  5. 임의의 값

Markdown 스냅샷 테스트가 올바르게 작동하려면 이러한 차이를 고려하여 테스트가 신뢰성 있게 항상 다른 테스트 실행 또는 환경에서 동일하게 작동하도록 보장해야 합니다.

이러한 차이를 고려하기 위해 정규화 프로세스가 있습니다. 정규화에 대한 여러 접근 방식이 있습니다.

  1. Fixture 기반 정규화
  2. 환경 변수 기반 정규화
  3. 정규식 기반 정규화

Fixture 기반 정규화

Fixture 기반 정규화는 가능한 경우에 사용해야 합니다. 정규식 기반 정규화보다 이해하기 쉽고 간단하기 때문입니다.

Markdown 스냅샷 테스트는 RSpec를 사용하여 예제 스냅샷 파일을 생성합니다. RSpec를 사용하면 다음이 가능합니다.

  • GitLab RSpec 스위트의 다른 모든 기능과 도우미와 함께 강력한 fixture 지원 및 도우미를 사용합니다.
  • 예제 스냅샷이 생성될 때 데이터베이스 상태를 제어하기 위해 fixture를 사용합니다.
  • 이 fixture 설정을 RSpec 공유 컨텍스트로 추출합니다. 이 공유 컨텍스트는 스냅샷 테스트가 CI 스위트 또는 run-snapshot-tests.sh를 통해 로컬에서 실행되는 곳 어디에서나 동일한 데이터베이스 상태가 존재함을 보장하기 위해 사용됩니다.

이러한 fixture를 포함하는 RSpec 공유 컨텍스트는 spec/support/shared_contexts/glfm/example_snapshot_fixtures.rb에서 확인할 수 있습니다.

환경 변수 기반 정규화

경우에 따라 fixture를 사용할 수 없는 경우가 있습니다. 이 경우에는 환경 변수 지원을 도입하여 프로덕션 코드에 환경 변수를 추가할 수 있습니다. 이는 우리가 주석 예제를 생성할 때 테스트 환경에서의 무작위성을 무력화할 수 있게 해줍니다. 이는 프로덕션 코드 경로에 있지만 명시적으로 설정되지 않으면 영향을 미치지 않으므로 해를 끼치지 않습니다. 이를 통해 아래에 설명된 더 복잡한 정규식 기반 정규화를 피할 수 있습니다.

현재 이러한 예는 일반적으로 무작위인 주석 ID가 GITLAB_TEST_FOOTNOTE_ID로 설정되어 결정론적으로 오버라이드되는 경우입니다. 이는 spec/support/shared_contexts/glfm/example_snapshot_fixtures.rb 공유 컨텍스트에서 fixture 설정과 함께 설정됩니다.

정규식 기반 정규화

fixture 기반 또는 환경 변수 기반 정규화를 사용할 수 없는 경우 정규식 기반 정규화를 사용해야 합니다. 이는 강력하지만 더 복잡하며 더 많은 유지 관리가 필요합니다. 이것은 특정 예제를 이름으로 참조하고 적절한 정규식을 작성해야 합니다.

정규식 기반 정규화를 사용하면 하나의 Markdown 예제에 대한 두 가지 다른 버전의 HTML 또는 JSON에 capturing groups를 적용하여 캡처된 그룹의 내용을 동일한 고정된 값으로 바꿀 수 있는 사용자 정의 정규식을 적용할 수 있습니다.

그런 다음 두 정규화된 버전을 서로 비교하여 모든 다른 비변수 콘텐츠가 동일한지 확인할 수 있습니다.

note
여기서 특정 attribute 값 검증에 대해 신경쓰지 않으므로 변수 값들을 버리고 고정값으로 대체해도 괜찮습니다. 다른 테스트 수준에는 각각 다른 목적이 있습니다.
  1. Markdown 스냅샷 테스트는 렌더링된 HTML/JSON의 구조를 강제하고 이를 표준 사양에 준수하도록 보장합니다.
  2. 특정 Markdown 예제의 구현에 대한 개별 단위 테스트는 이러한 변수 값들에 대한 구체적이고 특정한 테스트가 책임집니다.

캐달라이징 HTML에 대해 동일한 정규식 캡처 및 교체 정규화 접근 방식을 사용합니다. 이는 사실상 동일한 프로세스이기 때문입니다. 캐달라이징은 변수 값을 직접 대체하기보다는 HTML의 비표준 부분을 제거합니다.

자세한 내용은 glfm_example_normalizations.yml을 참조하십시오.

목표

위의 모든 제약 사항을 고려하면 GLFM 사양 및 테스트 인프라와 관련된 다양한 목표를 요약할 수 있습니다.

  1. GLFM이 Markdown을 HTML로 렌더링하는 공식 사양과 진리의 단일 원본이 있습니다. 이 진리의 원본은 다음과 같은 세 가지 Markdown 파일에 의해 표현됩니다:
    1. ghfm_spec_v_?.??.md: CommonMark + GFM 예제용입니다.
    2. glfm_official_specification.md: GLFM 공식 예제용입니다.
    3. glfm_internal_extensions.md: GLFM 내부 익스텐션용입니다.
  2. 이 공식 사양은 다음을 충족합니다.
    1. 사양은 GitHub Flavored Markdown (GFM) 사양의 엄격한 상위 집합이며, 공식적으로 GFM은 엄격한 상위 집합입니다. CommonMark 사양의 경우도 마찬가지입니다.
    2. 따라서 모든 Markdown 예제의 엄의의 합집합을 포함합니다. CommonMark 및 GFM을 위한 지원이 포함되어 있으며, official specificationinternal extensions을 포함합니다.
    3. 이는 GLFM official specificationinternal extensions에 포함된 모든 추가적인 Markdown의 섹션과 예제를 포함합니다. 또한 모든 표와 동반되는 서술과 마찬가지로 CommonMark 및 GFM 예제와 같이 Markdown 예제를 포함합니다.
    4. 모든 헤더 및 Markdown 예제는 표준 형식을 갖추어야 하며, 이는 표준 CommonMark 툴인 spec_tests.py를 사용하여 처리할 수 있는 표준 형식이어야 합니다. 이 툴은 spec.txt에 포함된 모든 예제에 대해 Markdown 준수 테스트를 수행하기 위해 사용됩니다.
  3. 정적 백엔드(Ruby) 및 WYSIWYG 프론트엔드(JavaScript) 구현 모두 가장 중요한 것은 그들의 렌더된 HTML이 무엇이든 canonical HTML로 변환되어야 합니다.

구현

다음 스크립트 및 파일 세트는 복잡합니다. 그러나 위에 나열된 모든 목표를 달성할 수 있도록 설계되었으며, 다음과 같은 구현 목표를 충족시키기 위해 주의 깊게 설계되었습니다.

  1. GLFM 사양 및 관련 파일의 매뉴얼 편집, 선별 및 유지 관리량을 최소화합니다.
  2. 상위 CommonMark 사양, GFM 확장 또는 GLFM 확장에 변경 사항이 있는 경우 GLFM 사양 및 관련 파일을 업데이트하는 프로세스를 자동화하고 간소화합니다.
  3. GLFM 사양의 부분적 또는 불완전한 구현을 지원합니다. 작업 중인 작업, 버그 또는 새로운 미래의 Markdown 지원 때문에 기존 구현의 모든 기능을 수행합니다.
  4. 표준 CommonMark 일치 테스트 및 GLFM 구현별 단위/승인 Markdown 스냅샷 테스트를 포함한 다양한 테스트를 실행, 간소화 및 지원합니다.
  5. 현재 및 미래의 요구 사항을 지원하기 위해 모든 GLFM 사양 예제 주변에 확장 가능한 메타데이터를 제공하여 자동 수락 테스트 및 자동 문서 업데이트와 같은 기능을 수행합니다.

구현에 대한 문서는 다음 세 가지 섹션으로 나뉩니다:

  1. 스크립트.
  2. 사양 파일.
  3. 예제 스냅샷 파일: 이 YAML 파일은 다양한 테스트를 실행하기 위해 입력 데이터 또는 픽스처로 사용되며, glfm_specification/output_example_snapshots 아래에 위치합니다. 모든 예제 스냅샷 파일은 파서와 렌더러의 구현을 기반으로 자동으로 생성됩니다. 그러나 필요한 경우 완전하지 않은 구현을 테스트해보기 위해 직접 편집할 수도 있습니다.

스크립트

이 실행 가능한 스크립트는 사양을 유지 관리하고 테스트를 실행하는 여러 작업을 수행합니다. 각 스크립트는 scripts/glfm 아래에 위치한 셸 실행 가능한 진입점 파일을 가지고 있지만, 실제 구현은 scripts/lib/glfm 아래의 단위 테스트된 클래스에 있습니다.

note
이 스크립트 중 일부는 Ruby로 구현되어 있고, 다른 일부는 셸 스크립트입니다. 더 복잡한 사용자 정의 스크립트를 위해 Ruby 스크립트를 사용하여 단위 테스트 및 디버깅을 쉽게 하기 위해 Ruby 스크립트를 사용합니다. 쉘 스크립트는 주로 다른 셸 명령을 호출하는 간단한 스크립트에 사용되어 별도의 도구를 사용하는 도전을 피하기 위해 사용됩니다.
note
scripts/glfm 아래의 Ruby 실행 가능한 스크립트의 파일 이름에는 밑줄 대신에 대시가 있습니다. 이러한 명명법은 루비 파일의 표준이 아니지만, scripts/lib/glfm 아래의 해당 구현 클래스 진입점 파일과 구별하기 위해 사용됩니다.

update-specification.rb 스크립트

scripts/glfm/update-specification.rb 스크립트는 입력 사양 파일을 사용하여 spec.txtspec.html와 같은 출력 사양 파일을 생성하고 업데이트합니다. 또한 snapshot_spec.mdsnapshot_spec.html 출력 예제 스냅샷 파일을 생성하고 업데이트합니다.

HTML 파일은 생성된(또는 업데이트된) 마크다운을 백엔드 API에 전달하여 HTML로 렌더링됩니다.

출력 - 사양 파일
입력 - 마크다운 파일
스크립트:
spec.txt - GLFM 공식 사양 예제
spec.html - GLFM 공식 사양 예제
glfm_official_specification.md - GLFM 공식 사양 예제
update-specification.rb
출력 - 예제 스냅샷 파일
입력 - 마크다운 파일
스크립트:
snapshot_spec.md - CommonMark, GHFM, GLFM 내부 확장 예제
snapshot_spec.html - CommonMark, GHFM, GLFM 내부 확장 예제
ghfm_spec_v_0.29.md - CommonMark 및 GHFM 사양 예제
glfm_internal_extensions.md - GLFM 내부 확장 예제
update-specification.rb

canonicalize-html.rb 스크립트

scripts/glfm/canonicalize-html.rb 스크립트는 HTML의 “정규화”를 처리합니다. 이는 추가 HTML을 포함하는 정적 또는 WYSIWYG HTML 문자열을 입력으로 받아 정규 HTML 문자열을 출력하는 파이프 스루 도우미 스크립트입니다.

유닉스 철학을 기반으로 한 독립적이고 모듈식이며 단일 목적의 스크립트로 구현되었습니다. 이는 GitLab 렌더러 구현에 대한 표준 CommonMark spec_tests.py 스크립트를 실행할 때 사용하기 쉽습니다.

run-spec-tests.sh 스크립트

scripts/glfm/run-spec-tests.sh는 편리한 셸 스크립트로서 ghfm_spec_v_0.29.mdglfm_specification/output_spec/spec.txt 파일을 사용하여 CommonMark 표준 spec_tests.py 스크립트를 통해 일치하는 사양을 실행합니다. 이는 scripts/glfm/canonicalize-html.rb 도우미 스크립트를 사용하여 GLFM 렌더러 구현이 마크다운 사양 예제를 정규 HTML로 렌더링하는 지원을 테스트합니다.

출력:
테스트 결과/출력
입력
스크립트:
사양 테스트 과정
spec_tests.py 출력
ghfm_spec_v_0.29.md - GLFM 사양
spec.txt - GLFM 사양
GLFM 정적
렌더러 구현
GLFM WYSIWYG
렌더러 구현
run-spec-tests.sh
spec_tests.py
canonicalize-html.sh

update-example-snapshots.rb 스크립트

scripts/glfm/update-example-snapshots.rb 스크립트는 예제 스냅샷 YAML 파일을 생성하고 업데이트합니다. 이 스크립트의 입력은 다음과 같습니다:

  • glfm_specification/output_spec/snapshot_spec.md 파일은 모든 CommonMark, GFM 및 GLFM 공식 및 내부 예제의 상위 집합을 포함합니다.
  • glfm_specification/input/gitlab_flavored_markdown/glfm_example_*.yml YAML 파일은 예제 스냅샷 파일을 생성하는 방법을 제어하는 메타데이터를 포함합니다.
출력: YAML 예제 스냩샷 파일
입력: 마크다운 입력 사양 파일
스크립트:
examples_index.yml
markdown.yml
html.yml
prosemirror_json.yml
스냅샷_spec.md
glfm_example_metadata.yml
update-example-snapshots.rb

run-snapshot-tests.sh 스크립트

scripts/glfm/run-snapshot-tests.sh 편의 쉘 스크립트는 주요 Markdown 스냅샷 테스트 RSpec 및 Jest *_spec 파일(주 앱 spec 폴더)을 실행합니다. 이는 example_snapshot YAML 파일에서 동작합니다.

실제 RSpec 및 Jest 테스트 *_spec 파일(프론트엔드 및 백엔드)은 일반적인 위치에 따라 spec 아래에 존재합니다. 이들은 다음과 같이 실행될 수 있습니다:

  • 표준 파이프라인의 일부로.
  • spec 아래의 다른 파일과 마찬가지로 명령줄 또는 IDE에서.

그러나 이들은 네 가지 서로 다른 위치에 분산되어 있습니다:

  • spec/requests에 있는 백엔드 테스트
  • ee/spec/requests에 있는 백엔드 EE 테스트
  • spec/frontend에 있는 프론트엔드 테스트
  • ee/spec/frontend에 있는 프론트엔드 EE 테스트

따라서, 이 편의 스크립트는 로컬 개발에서만 사용되도록 되어 있습니다. 한꺼번에 모든 테스트를 실행하고 단일 반환 코드를 반환하는 것을 간소화합니다. 해당 쉘 스크립트에는 관련 bundle exec rspec ...yarn jest ... 명령어만 포함되어 있습니다.

입력:
YAML
출력:
테스트 결과/출력
script:
tests:
호출
examples_index.yml
markdown.yml
html.yml
prosemirror_json.yml
rspec+jest 출력
run-snapshopt-tests.sh
관련 rspec+jest 테스트 파일

verify-all-generated-files-are-up-to-date.rb 스크립트

scripts/glfm/verify-all-generated-files-are-up-to-date.rb 스크립트는 update-specification.rb의 실험적인 서식에 대한 내용을 검증합니다. 그리고 update-example-snapshots.rb 스크립트는 없데이트한 파일에 대한 요청 결과와는 다른 리턴코드와 예외가 발생할 때, 출력된 명세 파일 또는 예제 스냅샷 파일에 대한 편집 차이가 나는 경우, 예외와 비-0 반환 코드로 실패합니다.

본 스크립트는 glfm-verify CI 작업을 통해 입력 명세 파일에 대한 변경들이 생성된 출력 명세 파일과 예제 스냅샷 파일에 반영되어 있는지 확인하기 위해 실행됩니다.

명세 파일

이 파일은 GLFM 명세 자체를 나타냅니다. 모두 루트 glfm_specification에 위치하며 사용 및 용도에 따라 하위 범주로 나누어집니다:

  • glfm_specification
    • input: 자동으로 다운로드되거나 매뉴얼으로 편집된 파일이 포함되어 있습니다. 이 파일들은 모든 다른 자동 GLFM 명세 스크립트, 프로세스 또는 테스트를 실행하는 데 필요한 최초 입력이 됩니다.
      • github_flavored_markdown: 다운로드 및 커밋된 단 하나의 ghfm_spec_v_0.29.md 명세만을 포함합니다.
      • gitlab_flavored_markdown: 모든 glfm_* 파일을 포함합니다.
    • output_spec: spec.txtspec.html 출력 명세 파일이 포함되어 있습니다. 이는 GLFM 공식 명세를 나타내고 입력 파일에서 update-specification.rb 스크립트를 실행함으로써 자동으로 생성됩니다.
    • output_example_snapshots: 출력 예제 스냅샷 파일이 포함되어 있습니다. 이는 스냅샷 테스트를 실행하기 위해 사용되며 입력 파일에서 자동으로 생성됩니다. update-specification.rbscripts/glfm/update-example-snapshots.rb 스크립트를 실행함으로써 생성됩니다.

입력 명세 파일

입력 명세 파일은 명세 자체를 나타내는 매뉴얼으로 편집된 Markdown 파일입니다. 이는 glfm_specification/input/github_flavored_markdown/*.mdglfm_specification/input/gitlab_flavored_markdown/*.md에 위치합니다.

더 많은 문맥 및 자세한 정보는 주요 명세 파일 섹션을 참조하십시오.

GitHub Flavored Markdown 명세

glfm_specification/input/github_flavored_markdown/ghfm_spec_v_0.29.md는 공식 최신 GFM spec.txt의 복사본입니다.

  • update-specification.rb 스크립트에 의해 자동으로 다운로드되고 업데이트됩니다.
  • 다운로드될 때 버전 번호가 파일 이름에 추가됩니다.
  • 확장자가 *.txt에서 *.md로 변경되어 진행합니다. 그래서 Markdown 편집기에서 더 잘 처리할 수 있습니다.

현재 추가적인 소개부록에 대한 특정 프로즈 섹션이 포함되어 있지만 예제는 포함하고 있지 않습니다.

예제를 포함하는 모든 프로즈 섹션은 다음으로 구분되는 연속적인 파일 섹션에 포함되어 있는 것으로 예상됩니다:

  1. 두 번째 H1 헤더(는 소개 섹션 이후 첫 번째)의 시작부터
  2. <!-- END TESTS --> HTML 주석 라인까지.
caution
추가적인 명확성을 위해, 본 파일은 ghfm 약어를 gfm 대신 사용합니다. 이에 대한 설명은 약어 섹션을 참조하십시오.
glfm_official_specification.md

glfm_specification/input/gitlab_flavored_markdown/glfm_official_specification.mdGLFM 공식 명세에 대한 매뉴얼으로 업데이트된 Markdown+HTML 예제 및 관련 문서 및 설명을 포함하고 있습니다.

  • 각각의 백틱-제한 spec.txt 서식에 따라 Markdown 예제가 포함되어 있으며 이는 렌더링돼야 하는 Markdown 및 해당 정규 HTML을 포함하고 있습니다.
  • GitLab 예제의 경우, 백틱 뒤의 “확장” 주석은 오직 example만 포함해야 합니다. 현재 구체적인 Markdown을 설명하는 추가적인 확장 주석을 포함하지는 않습니다. (예: example strikethrough와 같은 추가 확장 주석은 포함되어 있지 않습니다).
  • update-specification.rb 스크립트는 이를 생성된 spec.txt의 부록 이전에 새로운 섹션으로 삽입합니다.
  • 모든 GitLab 예제에 대해, H1 헤더 섹션으로 구성되어야 하며 모든 예제는 H2 또는 H3 헤더 섹션에 중첩되어 있어야 합니다.
  • H3 헤더 섹션은 H2 헤더 섹션 내에 중첩되어 있어야 합니다. 그것은 직접적으로 H1 헤더 섹션 내에 중첩되어 있어서는 안 됩니다.

추가적인 프로즈 섹션은 예제를 포함하지 않을 수 있습니다.

예제를 포함하는 모든 프로즈 섹션은 <!-- BEGIN TESTS --><!-- END TESTS --> HTML 주석 라인에 포함되어 있는 것이 필수적입니다.

glfm_specification/input/gitlab_flavored_markdown/glfm_official_specification.md 샘플 항목:

# GLFM 공식 명세 예 제내용을 가진 섹션

## 강조

### 두 개의 별표로 강조

```````````````````````````````` example
**bold**
.
<p><strong>bold</strong></p>
````````````````````````````````

### HTML로 강조

```````````````````````````````` example
<strong>
bold
</strong>
.
<p><strong>
bold
</strong></p>
````````````````````````````````
glfm_internal_extensions.md

glfm_specification/input/gitlab_flavored_markdown/glfm_internal_extensions.mdGLFM 내부 확장의 매뉴얼으로 업데이트된 Markdown 예제 및 이와 관련된 문서 및 설명으로 구성됩니다.

그 일반적인 형식은 glfm_official_specification.md와 동일하며, standard backtick-delimited spec.txt format으로 Markdown 예제를 포함하는 H1, H2, 또는 H3 섹션으로 구성됩니다.

그러나 canonical HTML section에서 설명한대로, 내부 확장 예제는 결코 Markdown 준수 테스트에 사용되지 않기 때문에 HTML 부분을 비워 두고 Markdown 부분만 지정됩니다.

이 파일에는 추가로 prose-only header sections가 포함될 수 있습니다만 이 헤더 섹션은 예제를 포함하지 않습니다.

예제를 포함하는 모든 헤더 섹션은 <!-- BEGIN TESTS --><!-- END TESTS --> HTML 주석으로 구분된 연속된 파일 섹션에 포함되어야 합니다.

glfm_specification/input/gitlab_flavored_markdown/glfm_official_specification.md의 샘플 엔트리:

caution
이 예시의 모든 줄은 | 문자로 시작합니다. 이 접두사는 markdownlint에 의한 잘못된 오류 및 다른 Markdown 편집기에서의 가능한 오류를 방지하는 데 도움이 됩니다. 이 파일은 실제로 이러한 접두사가 없어야 합니다.
|# GLFM 내부 확장 예제 섹션
|
|## 비디오
|
|```````````````````````````````` example
|![video](video.m4v "video title")
|.
|````````````````````````````````

입력 사양 구성 파일

입력 사양 구성 파일은 자동화된 GLFM 스크립트 및 프로세스의 다양한 측면을 제어하는 매뉴얼으로 관리되는 YAML 파일입니다. 이 파일들은 glfm_specification/input/gitlab_flavored_markdown/*.yml에 위치해 있습니다.

자세한 내용 및 세부 정보는 주요 specification files 섹션을 참조하십시오.

구성 파일 유효성 검사

구성 파일의 모든 매뉴얼으로 관리되는 예제 이름은 자동으로 생성된 input specification files을 기반으로 하는 output_example_snapshots/examples_index.yml에서 발견된 기존 Markdown example 이름과 일치해야 합니다.

존재하지 않는 예제 이름에 대한 잘못된 참조가 있을 경우 scripts/glfm/update-example-snapshots.rb 스크립트는 설명적인 오류와 함께 실패합니다.

이 유효성 검사의 유일한 예외는 00_로 시작하는 예제 이름으로, 이는 YAML 별칭을 위해 예약되었습니다. 자세한 내용 및 예시는 glfm_example_normalizations.yml 섹션을 참조하십시오.

glfm_example_status.yml

glfm_specification/input/gitlab_flavored_markdown/glfm_example_status.yml스크립트테스트의 동작을 제어합니다.

  • 이 파일은 매뉴얼으로 업데이트됩니다.
  • skip_update_example_snapshot* 필드는 Markdown 예제를 기반으로 스냅샷 예제 입력의 자동 생성 상태를 제어합니다.
  • skip_running_* 제어는 개별 예제에 대한 Markdown 준수 테스트 또는 Markdown 스냅샷 테스트를 건너뛸 수 있게 합니다.
  • 이를 통해 이 처리 또는 테스트를 건너뛸 때 예제가 구현되지 않았거나 부분적으로 구현되었거나, 오작동하거나, 생성될 수 없거나, 어떤 이유로 테스트를 건너뛰어야 할 때 이를 설명할 수 있게 제어할 수 있습니다.
  • 모든 항목은 기본적으로 거짓입니다. 거짓으로 평가되는 루비 값을 명시해 거짓으로 설정할 수 있습니다. 불린 true 값이 될 수 있지만 이상적으로는 해당 예제의 업데이트 또는 테스팅을 건너뛰는 이유를 설명하는 문자열이어야 합니다.
  • skip_update_example_snapshot* 항목이 true인 경우 기존값은 유지됩니다. 그러나 YAML은 다시 작성되므로 문자열 값의 스타일과 Block Chomping Indicator (|)이 수정될 수 있습니다. 왜냐하면 루비 YAML 라이브러리인 psych가 자동으로 이를 결정하기 때문입니다.

각 예제에 대해 다음과 같은 옵션 항목을 지원합니다. 이러한 값을 모두 기본적으로 false로 설정합니다.

glfm_specification/input/gitlab_flavored_markdown/glfm_example_status.yml 샘플 엔트리:

07_99_00_an_example_with_incomplete_wysiwyg_implementation_1:
  skip_update_example_snapshots: '건너뛰는 이유에 대한 설명.'
  skip_update_example_snapshot_html_static: '건너뛰는 이유에 대한 설명.'
  skip_update_example_snapshot_html_wysiwyg: '건너뛰는 이유에 대한 설명.'
  skip_update_example_snapshot_prosemirror_json: '건너뛰는 이유에 대한 설명.'
  skip_running_conformance_static_tests: '건너뛰는 이유에 대한 설명.'
  skip_running_conformance_wysiwyg_tests: '건너뛰는 이유에 대한 설명.'
  skip_running_snapshot_static_html_tests: '건너뛰는 이유에 대한 설명.'
  skip_running_snapshot_wysiwyg_html_tests: '건너뛰는 이유에 대한 설명.'
  skip_running_snapshot_prosemirror_json_tests: '건너뛰는 이유에 대한 설명.'
glfm_example_normalizations.yml

glfm_specification/input/gitlab_flavored_markdown/glfm_example_normalizations.yml화장실 기반 정규화 프로세스를 제어하는 데 사용됩니다. 이것은 하나 이상의 regex/replacement 쌍을 Markdown 예제에 대해 지정할 수 있습니다.

  • 매뉴얼으로 업데이트됩니다.
  • 예제와 해당 항목 유형에 해당하는 중첩 구조를 가지고 있습니다.
  • 중복을 피하고 여러 예제에서 regex/replacement 쌍을 공유할 수 있도록 YAML 앵커 및 별칭을 광범위하게 사용합니다.
  • YAML 앵커는 예제의 색인 번호를 기반으로 하는 명명 규칙을 사용하여 고유한 앵커 이름을 보장하고 명명 충돌을 피합니다.
note
다른 정규화 접근 방법(예: fixture-based normalization 또는 environment-variable-based normalization)은 항상 fixture-based normalization보다 선호됩니다.

glfm_specification/input/gitlab_flavored_markdown/glfm_example_normalizations.yml 샘플 항목:

# 모든 YAML 앵커는 하나 이상의 예제에서 공유되며 `00_shared` 섹션에 정의됩니다.
00_shared:
  00_uri: &00_uri
    - regex: '(href|data-src)(=")(.*?)(test-file\.(png|zip)")'
      replacement: '\1\2URI_PREFIX\4'
01_01_00__section_one__example_containing_a_uri__001:
  html:
    static:
      canonical:
        01_01_00_uri: *00_uri
      snapshot:
        01_01_00_uri: *00_uri
      wysiwyg:
        01_01_00_uri: *00_uri
  prosemirror_json:
    01_01_00_uri: *00_uri
07_01_00__gitlab_specific_markdown__footnotes__001:
  # 단일 예제 내에서만 공유되는 YAML 앵커는 예제 내에 정의되어야 합니다.
  shared:
    07_01_00_href: &07_01_00_href
      - regex: '(href)(=")(.+?)(")'
        replacement: '\1\2REF\4'
    07_01_00_id: &07_01_00_id
      - regex: '(id)(=")(.+?)(")'
        replacement: '\1\2ID\4'
  html:
    static:
      canonical:
        07_01_00_href: *07_01_00_href
        07_01_00_id: *07_01_00_id
      snapshot:
        07_01_00_href: *07_01_00_href
        07_01_00_id: *07_01_00_id
      wysiwyg:
        07_01_00_href: *07_01_00_href
        07_01_00_id: *07_01_00_id
  prosemirror_json:
    07_01_00_href: *07_01_00_href
    07_01_00_id: *07_01_00_id
glfm_example_metadata.yml

glfm_specification/input/gitlab_flavored_markdown/glfm_example_metadata.yml은 스냅샷 예제 생성 프로세스의 다른 측면을 제어합니다.

  • 매뉴얼으로 업데이트됩니다.
  • ee 필드는 예제가 EE 전용 예제인지를 결정합니다. ee 필드가 true인 경우, 예제는 ee/spec/requests/api/markdown_snapshot_spec.rb에 의해 실행되며 spec/requests/api/markdown_snapshot_spec.rb에 의해 실행되지 않습니다.
  • api_request_override_path 필드는 지정된 예제의 static HTML을 생성하는 데 사용되는 API 엔드포인트 경로를 재정의합니다. 경우에 따라 다른 엔드포인트는 동일한 Markdown에 대해 다른 HTML을 생성할 수 있으므로 동일한 Markdown에 대해 서로 다른 API 엔드포인트를 사용할 수 있어야 합니다. 기본적으로 /markdown 엔드포인트가 사용됩니다.

glfm_specification/input/gitlab_flavored_markdown/glfm_example_metadata.yml 샘플 항목:

---
08_01_00__examples_using_internal_extensions__markdown_preview_api_request_overrides__001:
  api_request_override_path: /groups/glfm_group/preview_markdown
08_01_00__examples_using_internal_extensions__markdown_preview_api_request_overrides__002:
  api_request_override_path: /glfm_group/glfm_project/preview_markdown
08_01_00__examples_using_internal_extensions__markdown_preview_api_request_overrides__003:
  api_request_override_path: /glfm_group/glfm_project/preview_markdown
08_01_00__examples_using_internal_extensions__markdown_preview_api_request_overrides__004:
  api_request_override_path: /-/snippets/preview_markdown
08_01_00__examples_using_internal_extensions__markdown_preview_api_request_overrides__005:
  api_request_override_path: /glfm_group/glfm_project/-/wikis/new_page/preview_markdown
08_01_00__examples_using_internal_extensions__markdown_preview_api_request_overrides__006:
  ee: true
  api_request_override_path: /groups/glfm_group/-/wikis/new_page/preview_markdown

출력 명세 파일

glfm_specification/output 디렉터리에는 update-specification.rb 스크립트에 의해 생성된 GLFM 명세를 나타내는 CommonMark 표준 형식의 spec.txt 파일과, 이를 입력으로 사용하여 생성된 spec.html이 포함되어 있습니다.

GLFM 명세를 나타내는 이러한 출력 spec.* 파일은 모두 매뉴얼으로 편집되거나 생성되었기 때문에 다른 input 명세 파일과 동일한 상위 폴더 glfm_specification에 위치합니다. 이것은 편의를 위해 그리고 모두 일부는 매뉴얼으로 편집되었으므로 해당 위치에 있습니다.

GFM에서 spec.txttest dir에 위치하며, CommonMark에서는 프로젝트 루트에 위치합니다. 표준 위치에 대한 선험 사례는 없습니다. 나중에 렌더링된 HTML spec.html 버전을 다른 위치나 사이트로 이동하거나 복사할지 여부를 결정할 수 있습니다.

spec.txt

glfm_specification/output_spec/spec.txt는 표준 형식의 Markdown 명세 파일로, 서술 및 Markdown + 공식 HTML 예제를 포함합니다.

GLFM 명세에서 spex.txtglfm_official_specification.md의 공식 명세 예제만을 포함하며, glfm_internal_extensions.md의 내부 확장 예제는 포함하지 않습니다.

또한, 이는 run-spec-tests.sh와 같은 다른 스크립트의 입력으로 사용됩니다.

input specification files에 의해 생성 또는 업데이트되는 update-specification.rb 스크립트에 의해 생성됩니다. 이 프로세스에 대한 다이어그램 및 자세한 내용은 update-specification.rb script section를 참조하십시오.

note
spec.txt는 Markdown 파일이지만 GFM 및 CommonMark 명세와 일관성을 유지하기 위해 *.txt 확장자로 지정되었습니다. 다른 GLFM Markdown 파일은 Markdown 서식 및 구문 강조 표시를 위해 다양한 편집기와 호환되도록 *.md 확장자로 지정됩니다.
spec.html

glfm_specification/output_spec/spec.htmlspec.txt를 기반으로 렌더링된 HTML 파일입니다. 이는 spec.txt와 동시에 update-specification.rb 스크립트에 의해 생성(또는 업데이트)됩니다.

이 파일은 “GitHub Flavored Markdown”(GFM) specificationCommonMark specification의 HTML 렌더링 버전에 해당하지만, GitLab Flavored Markdown (GLFM) 예제만 포함합니다.

note
이 HTML의 형식은 현재 GFM 및 CommonMark HTML 렌더링 명세와 완전히 일치하지 않습니다. 이는 단순히 spec.txt를 GitLab Markdown 렌더러를 통해 실행한 원시 출력만입니다. HTML을 올바르게 포맷하려면 CommonMark 프로젝트의 Lua 스크립트 및 템플릿을 복제하거나 재사용해야 합니다: CommonMark Makefile

Output example snapshot files

output_example_snapshots 디렉터리에는 update-specification.rbupdate-example-snapshots.rb 스크립트에 의해 생성된 파일이 포함되어 있습니다.

output-specification.rb 스크립트는 output_snapshot_examples/snapshot_spec.mdoutput_snapshot_examples/snapshot_spec.html을 생성합니다. 이 파일들은 입력 파일을 기반으로 생성된 예제를 포함하는 Markdown 명세 파일로, output_spec/spec.txtoutput_spec/spec.html과 유사하지만 다음과 같은 차이가 있습니다:

  1. CommonMark, GitHub Flavored Markdown 및 GitLab Flavored Markdown 명세의 모든 예제를 포함하며, 반면에 spec.*은 GLFM 명세만을 포함합니다. 이는 스냅샷 테스트 작업 시 모든 예제를 참조할 수 있도록 하기 위함입니다.
  2. 예제를 포함하는 헤더 섹션만을 포함합니다. 예제를 포함하지 않고 설명서만 포함하는 섹션은 포함하지 않습니다.

update-example-snapshots.rb 스크립트는 여러 output_snapshot_examples/*.yml 파일을 생성하며, 이는 스냅샷 테스트를 수행하는 데 사용됩니다.

백엔드(Ruby) 및 프론트엔드(JavaScript) 모두에 대한 GLFM 구현이 완료되면, 이러한 YAML 파일들은 모두 자동으로 생성될 수 있습니다. 그러나 아직 구현이 진행 중인 동안에는 skip_update_example_snapshots 키를 사용하여 glfm_specification/input/gitlab_flavored_markdown/glfm_example_status.yml에 자동 생성을 비활성화할 수 있으며, 대신 구현을 지원하기 위해 필요에 따라 매뉴얼으로 편집할 수 있습니다.

snapshot_spec.md

glfm_specification/output_example_snapshots/snapshot_spec.mdspec.txt와 같이 표준 Markdown + 공식 HTML 예제를 포함하는 Markdown 파일입니다.

이는 update-specification.rb 스크립트에 의해 생성 또는 업데이트되며, input specification files를 입력으로 사용합니다. 이 프로세스에 대한 다이어그램 및 자세한 내용은 update-specification.rb script section를 참조하십시오. 또한 update-example-snapshots.rb와 같은 다른 스크립트의 입력으로 사용됩니다.

이 파일은 spec.txt와 유사하지만 다음과 같은 차이가 있습니다:

  1. spec.txt는 GitLab Flavored Markdown의 예제만 포함하지만, snapshot_spec.md는 “GitHub Flavored Markdown”(GFM) specificationCommonMark specification 명세의 모든 예제를 포함합니다.
  2. spec.txt는 예제를 포함하지 않은 설명서 전용 섹션을 포함하는 GLFM 명세 전체를 나타내지만, snapshot_spec.md는 예제를 포함하는 헤더 섹션만으로 이루어집니다. 이는 다른 output example snapshot files의 입력으로 사용되는 것을 목적으로 하기 때문에 실제 specification file로 사용되는 것은 아닙니다.
snapshot_spec.html

glfm_specification/output_snapshot_examples/snapshot_spec.htmlsnapshot_spec.md를 기반으로 렌더링된 HTML 파일입니다. 이는 snapshot_spec.md와 동시에 update-specification.rb 스크립트에 의해 생성(또는 업데이트)됩니다.

note
이 HTML의 형식은 현재 GFM 및 CommonMark HTML 렌더링 명세와 완전히 일치하지 않습니다. 이는 단순히 snapshot_spec.md를 GitLab Markdown 렌더러를 통해 실행한 원시 출력만입니다. HTML을 올바르게 포맷하려면 CommonMark 프로젝트의 Lua 스크립트 및 템플릿을 복제하거나 재사용해야 합니다: CommonMark Makefile
### `examples_index.yml`

[`glfm_specification/output_example_snapshots/examples_index.yml`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/glfm_specification/output_example_snapshots/examples_index.yml)은 모든
CommonMark, GFM 및 GLFM 예제 이름을 포함하고 각각의 고유한 식별 이름을 가지고 있는 주요 디렉터리입니다.

- GFM `spec.txt` 명세의 계층적 섹션 및 예제에서 생성됩니다.
- CommonMark 및 GFM 예제의 경우, 이러한 섹션들은 원래 GFM `spec.txt`에서 왔습니다.
- GLFM 예제의 경우, [`glfm_official_specification.md`](#glfm_official_specificationmd) 및 [`glfm_internal_extensions.md`](#glfm_internal_extensionsmd)에서 생성됩니다.
- 각 예제에 대한 추가 메타데이터도 포함하고 있습니다:
  1. `spec_example_position` - 생성된 GLFM `spec.txt` 파일의 예제 위치
     - 이 값은 파일의 각 Markdown + HTML5 예제의 색인 순서입니다. 파일의 줄 번호가 아닙니다.
     - 표준 CommonMark 도구에는 렌더링된 HTML 파일의 각 예제에 대한 색인 번호가 포함되어 있기 때문에 이 값은 렌더링된 `spec.html` 파일에서 예제를 찾는 데 사용할 수 있습니다.
       : [https://spec.commonmark.org/0.30/#example-42](https://spec.commonmark.org/0.30/#example-42)
  1. `source_specification` - 예제의 원래 명세
     `commonmark`, `github`, 또는 `gitlab`.
- 예제 항목 이름의 네이밍 컨벤션은 중첩 된 헤더 섹션 이름과 헤더의 예제 색인을 기반으로 합니다.
  - 이 네이밍 규칙은 상대적으로 안정적인 이름과 예제 위치를 가져와야 합니다.
    CommonMark / GLFM 명세는 거의 변경되지 않으며, 동일한 섹션 7 하위 섹션에 대한 여러 GLFM 예제의 대부분은 하위 섹션의 끝에 추가됩니다.

`examples_index.yml` 샘플 항목:

```yaml
02_01_00_preliminaries_characters_and_lines_1:
  spec_example_position: 1
  source_specification: commonmark
03_01_00_blocks_and_inlines_precedence_1:
  spec_example_position: 12
  source_specification: commonmark
05_03_00_container_blocks_task_list_items_1:
  spec_example_position: 279
  source_specification: github
06_04_00_inlines_emphasis_and_strong_emphasis_1:
  spec_example_position: 360
  source_specification: github
07_01_00_audio_link_1:
  spec_example_position: 301
  source_specification: gitlab

markdown.yml

glfm_specification/output_example_snapshots/markdown.ymlglfm_specification/output_example_snapshots/examples_index.yml의 각 항목에 대한 원래의 Markdown을 포함합니다.

  • CommonMark 및 GFM Markdown의 경우, update-example-snapshots.rb 스크립트를 사용하여 표준 GFM spec.txt에서 생성(또는 업데이트)됩니다.
  • GLFM의 경우, glfm_official_specification.mdglfm_internal_extensions.md 입력 명세 파일로부터 생성(또는 업데이트)됩니다.

glfm_specification/output_example_snapshots/markdown.yml 샘플 항목:

06_04_00_inlines_emphasis_and_strong_emphasis_1: |
  *foo bar*

html.yml

glfm_specification/output_example_snapshots/html.ymlglfm_specification/output_example_snapshots/examples_index.yml의 각 항목에 대한 HTML을 포함합니다.

세 종류의 항목이 있으며, 각각에 대해 다른 HTML이 있습니다:

  • Canonical
  • Static
    • glfm_specification/output_example_snapshots/examples_index.yml의 각 항목에 대한 정적(백엔드(Ruby)에서 생성) HTML입니다.
    • 백엔드 Markdown API (또는 내부 클래스를 통한)의 update-example-snapshots.rb 스크립트를 통해 생성(또는 업데이트)됩니다. 구현이 미완료 된 정적 예제의 경우 매뉴얼으로 업데이트할 수 있습니다.
  • WYSIWYG
    • glfm_specification/output_example_snapshots/examples_index.yml의 각 항목에 대한 WYSIWYG(프런트엔드, JavaScript로 생성) HTML입니다.
    • 프런트엔드 리치 텍스트 편집기 구현을 통해 update-example-snapshots.rb 스크립트를 통해 생성(또는 업데이트)됩니다. 구현이 미완료된 WYSIWYG 예제의 경우 매뉴얼으로 업데이트할 수 있습니다.

HTML을 생성하는 동안 발생한 예외나 실패는 Error - check implementation 값으로 대체됩니다.

glfm_specification/output_example_snapshots/html.yml 샘플 항목:

06_04_00_inlines_emphasis_and_strong_emphasis_1:
  canonical: |
    <p><em>foo bar</em></p>
  static: |
    <p data-sourcepos="1:1-1:9" dir="auto"><strong>foo bar</strong></p>
  wysiwyg: |
    <p><strong>foo bar</strong></p>
note
실제 static 또는 WYSIWYG 항목은 구현이 어떻게 진화하는지에 따라 html.yml 예제와 다를 수 있습니다.

prosemirror_json.yml

glfm_specification/output_example_snapshots/prosemirror_json.ymlglfm_specification/output_example_snapshots/examples_index.yml의 각 항목에 대한 ProseMirror JSON을 포함합니다.

  • 프론트엔드 코드를 통해 update-example-snapshots.rb 스크립트를 사용하여 생성(또는 업데이트)됩니다. 구현이 미완료된 예제의 경우 매뉴얼으로 업데이트할 수 있습니다.
  • 생성 중 발생한 예외나 실패는 Error - check implementation 값으로 대체됩니다.

glfm_specification/output_example_snapshots/prosemirror_json.yml 샘플 항목:

06_04_00_inlines_emphasis_and_strong_emphasis_1: |-
  {
    "type": "doc",
    "content": [
      {
        "type": "paragraph",
        "content": [
          {
            "type": "text",
            "marks": [
              {
                "type": "bold"
              }
            ],
            "text": "foo bar"
          },
        ]
      },
    ]
  }

Workflows

이 섹션에서는 스크립트를 사용하여 GLFM 명세와 테스트를 관리하는 방법을 설명합니다.

GLFM 명세 업데이트 및 일치 테스트 실행

  1. update-specification.rb을 실행하여 GLFM 명세를 업데이트하고 출력 명세 파일을 업데이트합니다.
  2. 출력 명세 파일에 대한 결과적인 변경 사항을 시각적으로 확인하고 확인하세요.
  3. run-spec-tests.sh을 실행합니다. 이 스크립트는 아직 구현되지 않았으며 플레이스홀더 메시지만 출력합니다. 구현되면 GLFM 명세에 대한 일치 테스트를 실행해야합니다.
  4. 출력 명세 파일에 대한 모든 변경 사항을 커밋합니다.

예제 스냅샷 업데이트 및 스냅샷 테스트 실행

  1. 진행 중인 기능 또는 버그에 작업 중인 경우 입력 명세 파일에 필요한 매뉴얼 업데이트를 수행하십시오. 이는 다음을 포함할 수 있습니다:
    1. glfm_official_specification.md 또는 glfm_internal_extensions.md에서의 정식 마크다운 또는 HTML 예제를 업데이트합니다.
    2. glfm_specification/input/gitlab_flavored_markdown/glfm_example_status.yml을 업데이트하여 예제 또는 테스트의 현재 상태를 반영합니다.
  2. update-specification.rb을 실행하여 입력 명세 파일에 대한 변경 사항을 반영한 spec.txt을 업데이트합니다.
  3. 출력 명세 파일에 대한 결과적인 변경 사항을 시각적으로 확인하고 확인하세요.
  4. update-example-snapshots.rb을 실행하여 예제 스냅샷 파일을 업데이트합니다.
  5. 예제 스냅샷 파일에 대한 결과적인 변경 사항을 시각적으로 확인하고 확인하세요.
  6. 편리한 스크립트로써 run-snapshot-tests.sh를 실행하여 예제 스냅샷을 사용하는 모든 관련 프론트엔드(RSpec) 및 백엔드(Jest) 테스트를 실행합니다.
    1. 어떤 프론트엔드 또는 백엔드 스냅샷 테스트라도 개별적으로 실행할 수 있습니다.
    2. 일반적으로 연속 통합 스위트의 일환으로 모든 프론트엔드 및 백엔드 테스트도 실행됩니다.
  7. 입력 명세 파일, 출력 명세 파일 또는 예제 스냅샷 파일에 대한 모든 변경 사항을 커밋하세요.