GitLab Flavored Markdown (GLFM) 사양 가이드

요약

  • GitLab Flavored Markdown (GLFM)은 GitHub Flavored Markdown (GFM)에 기반하며, CommonMark를 기반으로 합니다.
  • GLFM은 두 가지 “세트”의 Markdown 구문으로 나뉩니다:
    • 공식 사양, 즉 특정 구현이나 환경에 의존하지 않고 모든 편집기에서 지원될 수 있는 것입니다.
    • 내부 확장”, 이는 GitLab 환경 및 메타데이터에 의존할 수 있습니다.
  • 각각의 구문에서 모든 것은 특수 Markdown 파일에 의해 지정되며 CommonMark 사양 구문을 기반으로 합니다. 이 파일에는 Markdown과 해당 생성된 HTML의 옆에 있는 “예제”와 각 예제를 설명하는 연결된 문서가 포함됩니다.
  • 또한 추가 정보를 담고 있는 YAML 메타데이터 파일이 있을 수 있으며, 개별 Markdown/HTML 예제의 처리 및 렌더링 방식에 대한 추가 정보가 포함될 수 있습니다.
  • 이러한 Markdown/YAML 파일과 그들이 포함하는 예제는 여러 목표를 달성합니다:
    • GLFM이 어떻게 렌더링되어야 하는지에 대한 권위있는 “진실의 원천”입니다.
    • 형식화된 HTML 문서를 렌더링함으로써 모든 예제와 관련 문서를 지원합니다.
    • 공식 사양에 대한 표준 CommonMark 준수 테스트를 실행하는 데 지원합니다.
    • GitLab 앱 내에서 자동화된 테스팅을 구동하는 데 사용되는 YAML “예제 스냅샷 파일”을 자동으로 생성하여 GitLab 내부 GLFM 처리 논리의 스냅샷 테스트를 지원합니다.
  • 이러한 목표를 달성하기 위해 다양한 스크립트 및 논리가 사용됩니다.

소개

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

note
이 문서에서 GFM_은 _GitHub Flavored Markdown을 가리키며, GitLab Flavored Markdown을 가리키지 않습니다. 이 문서에서 사용된 다양한 약어에 대한 자세한 설명은 약어 섹션을 참조하세요.

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

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

note
이 가이드와 그 안에 설명된 구현과 파일은 여전히 진행 중인 작업입니다. 작업이 진행됨에 따라 이 가이드와 GitLab Flavored Markdown을 위한 사용자 문서 간의 재작성과 통합이 있을 수 있습니다.

용어 및 정의

약어: GLFM, GHFM, GFM, CommonMark

GitHub Flavored Markdown은 GFM 약어로 널리 언급되며, 이 문서도 해당 규칙을 따릅니다. 이 문서에서는 GitLab Flavored Markdown을 GLFM으로 지칭합니다. 이는 GitHub Flavored Markdown과 구분하기 위한 것입니다.

많은 문서나 GitLab 코드 기반에서는 아직 이 규칙을 일관되게 따르지는 않습니다. 많은 곳에서 GFM 약어가 GitLab Flavored Markdown을 가리키도록 사용됩니다. 이 불일치를 해결하기 위한 오픈 이슈가 존재합니다.

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

최초의 CommonMark 사양은 CommonMark(약어 없음)으로 지칭합니다.

다양한 Markdown 사양

우리가 사용하는 사양 형식은 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 프로젝트에 제기되었습니다.

공식 사양 vs 내부 확장

GitHub의 GFM 및 GitLab의 GLFM은 두 가지 “세트”의 Markdown을 지원합니다:

  • 공식 사양
  • 내부 확장

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

graph TD CM[CommonMark - spec.txt - 예: 제목] --- GFMS[GFM 사양 - spec.txt - 예: 취소선 확장] GFMS --- GLFM[GLFM 사양 - 예: 컬러 칩] GFMS --- GFMI[GFM 내부 확장 - 예: GitHub 특정 참조] GLFM --- GLFS[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에서 문제, 풀 리퀘스트 또는 Merge Request을 직접 편집할 수 있도록 하는 에디터나 IDE 플러그인 등에서도 구현될 수 있습니다.

Markdown 예제

사양 및 이 가이드의 맥락에서 _예제_라는 용어는 특별히
백틱으로 구분된 Markdown + HTML 쌍을 사용하여 표준
CommonMark 사양 형식에서
다양한 Markdown 원본 문자열의 구문 분석(또는 렌더링) 동작을 설명하는 것을 가리킵니다.

이러한 맥락에서 다른 유사한 또는 관련된 _예제_의 의미와 혼동되지 않아야 합니다.
예를 들어 RSpec 예제와 같은 _example_의 다른 의미들과 혼동되지 않아야 합니다.

백틱으로 구분된 Markdown+HTML 예제 구문에 대한 자세한 내용은 glfm_official_specification.md 파일의 섹션을 참조하세요.

파서 및 렌더러

특정 사양의 사용 방법 및 해당 Markdown 언어와의 관련성을 이해하려면 파서_와 _렌더러 사이의 구분을 이해하는 것이 중요합니다.

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

GLFM 사양에 의해 추진되는 Markdown 테스트의 유형

자동화된 테스트의 두 가지 주요 유형은 GLFM 사양에 포함된 Markdown 예제 및 데이터에 의해 추진됩니다. 우리는 다음과 같이 참조합니다.

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

GitLab 코드베이스에서 많은 다른 유형의 테스트도 발생하며, 이러한 테스트 중 일부는 GLFM Markdown 언어와도 관련이 있습니다. 따라서 혼란을 피하기 위해 이 문서 및 기타 곳에서 이 정의된 두 가지 유형의 사양에 기반한 테스팅에 대해 표준 용어를 사용합니다.

Markdown 일치성 테스트

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

_마크다운 일치성 테스팅_은 특정 구현이 CommonMark 마크다운 사양에 준수하는지를 검증하기 위해 모든 CommonMark 마크다운 언어에서 사용하는 표준 테스트 방법을 가리킵니다. 이는 spec.txt 사양 및 구현에 대해 사양 자체에 설명된 대로 spec_tests.py 표준 CommonMark 도구를 사용하여 강제 적용됩니다.

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

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

Markdown 스냅샷 테스트

_마크다운 스냅샷 테스팅_은 GLFM 사양의 모든 예제에서 파생된 example_snapshots 픽스처 데이터를 기반으로 하는 GitLab 코드베이스에서 수행되는 자동화된 테스트를 가리킵니다. 이는 백엔드 RSpec 테스트 및 프론트엔드 Jest 테스트로 구성되며 이 테스트는 픽스처 데이터를 사용합니다. 이러한 픽스처 데이터는 YAML 파일에 포함되어 있습니다. 이 파일은 사양의 Markdown 예제 및 기존 GLFM 파서 및 렌더러 구현을 기반으로 생성 및 업데이트됩니다. 또한 미완성된 구현을 테스트하거나 버그를 테스트하는 데 필요한 경우 매뉴얼으로 업데이트될 수도 있습니다.

스냅샷 테스트는 포괄적이므로 모든 예제, 즉 GLFM 공식 사양내부 확장 예제에 대해 실행될 수 있습니다. 이는 내부 확장 예제에 필요한 GitLab 특정 환경 또는 메타데이터를 제공하는 구성 파일을 사용한다는 것을 의미합니다. 예를 들어, glfm_example_metadata.yml와 같은 것이 있습니다.

스냘샷 테스트의 설계는 사용자에게 노출되는 GLFM Markdown의 올바름을 보장하는 데 도움이 됩니다. 이를 통해 백엔드 및 프론트엔드 파서 및 렌더러블랙 박스 테스팅 방식을 사용하여 철저하게 연습됩니다. 이는 이러한 포괄적인 스타일 때문에 테스트 피라미드의 “상단”에 해당하는 종류의 테스트로 간주될 수 있습니다.

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

  1. Markdown 스냅샷 테스트는 Golden Master Testing 접근법의 한 형태로 간주할 수 있으며, 승인 테스팅 또는 특성화 테스팅이라고도 합니다.
    1. Golden Master 용어는 원래 녹음 산업에서 유래하며 모든 다른 사본이 생성되는 최종 믹스를 마스터링하거나 만드는 과정을 가리킵니다.
    2. 추가 정보와 배경을 위해 Characterization TestsGolden Masters에 대해 읽어볼 수 있습니다.
  2. 용어 _스냅샷_은 다른 곳에서 사용되는 것처럼 Jest 스냅샷 테스팅으로 가리키지는 않지만, 마크다운 스냅샷 테스팅은 동일한 철학과 패턴으로 따르고 있습니다:
    1. 스냘샷 예제 픽스처 데이터는 소스 컨트롤에 체크된 파일로 표시됩니다.
    2. 파일들은 코드 구현에 따라 자동으로 생성 및 업데이트될 수 있습니다.
    3. 필요한 경우, 예를 들어 미완성이나 버그가 있는 구현을 테스트하기 위해 매뉴얼으로 업데이트될 수도 있습니다.
  3. 용어 _fixture_의 사용은 표준 Rails 데이터베이스 fixture 파일을 가리키지 않고 보다 일반적인 정의로, 자동화된 테스트를 지원하기 위한 입력 데이터를 가리킵니다.
  4. 이러한 예제 스냘샷 픽스처 파일들은 GLFM 사양의 나머지 부분에서 유래되고 밀접하게 관련되어 있습니다. 그래서 example_snapshots 디렉터리는 나머지 GLFM 사양 파일과 함께 glfm_specification 디렉터리 아래에 공존하도록 의도되어 있습니다. 이러한 파일들은 실제로 spec/fixtures 디렉터리로 파일을 나누는 것보다 glfm_specification 디렉터리 아래의 모든 것이 있는 것이 더 단순하고 이해하기 쉽다는 점에서 개발자들에게 더 나은 것으로 판명되었다.

마크다운 스냅샷 테스팅의 중요한 개념인 normalization 섹션도 참조하세요.

구문 분석 및 렌더링

GitLab 애플리케이션에서 사용되는 Markdown 방언은 두 가지 렌더링에 대한 이중 요구 사항이 있습니다.

  1. 다양한 위치에서 표시되는 정적 읽기 전용 HTML 형식으로 렌더링
  2. 리치 텍스트 편집기에서 편집 가능한 내용을 렌더링하는 것으로, 이는 “보이는 대로 하는 것이 보이는 대로 나오는 것” (WYSIWYG) 편집기입니다. 리치 텍스트 편집기는 편집 가능한 Markdown 소스와 편집 가능한 WYSIWYG 문서 간의 실시간 즉시 전환을 지원합니다.

이러한 요구 사항으로 인해 GitLab에는 두 개의 독립적인 파서 및 렌더러 구현이 있습니다.

  1. 백엔드 파서/렌더러는 정적 읽기 전용 HTML로 파싱 및 렌더링을 지원합니다. 이는 루비로 구현되어 있습니다. 이는 libcmark-gfm의 루비 래퍼 인 commonmarker를 활용합니다. libcmark-gfm은 CommonMark의 C 참조 구현의 확장된 버전으로, 이는 CommonMark의 참조 파서의 GitHub 포크입니다.
  2. 프론트엔드 파서/렌더러는 리치 텍스트 편집기를 위해 파싱 및 WYSIWYG 렌더링을 지원합니다. 이는 JavaScript로 구현되었습니다. 파싱은 Remark Markdown 파서를 기반으로 하며, 이는 MDAST 추상 구문 트리(MDAST)를 생성합니다. 렌더링은 MDAST를 ProseMirror 문서로 변환하는 과정입니다. 그 후, ProseMirror를 사용하여 ProseMirror 문서를 WYSIWYG HTML로 렌더링합니다. 이 문서에서는 Markdown을 MDAST로 변환하는 것을 _프론트엔드/JavaScript 파서_로서, Markdown을 WYSIWYG HTML로 ProseMirror에서 렌더링하는 전체 과정을 _리치 텍스트 편집기_로서 참조합니다. 정확한 소스 매핑에 대한必인 지원 부족, 사용자가 Markdown 소스와 WYSIWYG 문서 간을 전환할 때마다 백엔드로의 왕복이 필요한 것을 없애야 하는 대역폭 및 지연 고려 등이 독립적인 프론트엔드 파서/렌더러 구현이 필요한 몇 가지 요구 사항을 이끌어냅니다.

렌더링된 HTML의 여러 버전

이러한 GLFM 렌더러 구현(정적 및 WYSIWYG)은 GLFM 공식 사양의 Markdown 예제의 정식 HTML과 달라질 수 있는 HTML을 생성합니다. 따라서 GLFM 사양의 Markdown 예제마다 예제에서 렌더링될 수 있는 3가지 버전의 HTML이 있습니다.

  • 정적 HTML
  • WYSIWYG HTML
  • 정식 HTML

정적 HTML

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

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

WYSIWYG HTML

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

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

정식 HTML

정식 HTML은 Markdown으로부터 렌더링된 깨끗하고 기본적인 HTML로, 스타일링 또는 구현 특정 동작과 관련된 불필요한 클래스/요소가 없습니다.

이는 GLFM spec.txt에 대한 Markdown 일치 테스트를 지원하기 위함입니다.

항상 고정적으로 매뉴얼으로 관리되며, HTML은 결코 자동으로 생성되지 않습니다. 이 Markdown 예제에 명시된 예제는 Markdown 사양에 따라 다른 파일에 포함됩니다.

GLFM spec.txt의 GFM spec.txt에서 문서 텍스트와 완전히 동일한 HTML이 정식 HTML인 공식 사양의 일부인 예제에 대해서는 항상 동일한 HTML으로 구성됩니다. 그래서 이러한 예제는 GFM spec.txt에서 GLFM 버전의 spec.txt로 동일하게 복사됩니다.

GLFM 공식 사양의 일부인 예제에 대한 정식 HTML은 glfm_official_specification.md 입력 사양 파일에 포함된 예제를 통해 매뉴얼으로 유지 및 관리됩니다.

GLFM 내부 확장의 일부인 예제에 대한 정식 HTML은 명시적으로 지정하지 않았으며, 모든 예제에서 비어 있어야 함을 통해 매뉴얼으로 유지 및 관리하고 있습니다.

HTML의 정규화

백엔드(루비) 및 프론트엔드(JavaScript) 렌더러에서 렌더링된 정적 HTMLWYSIWYG HTML은 특정 외형 및 동작 요구 사항을 지원하기 위해 추가적인 스타일링 또는 HTML 요소를 포함합니다.

백엔드 또는 프론트엔드 렌더링 로직에서는 정식 HTML에 대한 비교를 수행하는 데 필요한 깨끗하고 기본적인 HTML을 직접 렌더링할 수 없습니다.

그리고 그럴 필요도 없습니다. 왜냐하면:

  • 이는 GitLab 애플리케이션 기능을 지원하는 직접적인 요구 사항이 아닙니다.
  • 이 기능을 추가하는 것은 구현에 불필요한 요구 사항과 복잡성을 추가합니다.

대신 백엔드 또는 프론트엔드 렌더링된 정적 또는 WYSIWYG HTML은 정규화 프로세스에 의해 정식 HTML로 변환됩니다. 해당 프로세스는 정적 또는 WYSIWYG HTML에서 모든 추가 스타일링 및 동작적인 HTML을 제거하여 표준 spec.txt 사양의 정식 HTML과 정확히 일치하는 정식 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 지원 및 도우미 함수를 사용할 수 있습니다.
  • 예시 스냅샷을 생성할 때 데이터베이스 상태를 제어하기 위해 Fixtures를 사용할 수 있습니다.
  • 이 Fixture 설정을 RSpec shared context로 추출할 수 있습니다. 이 shared context는 예시 스냅샷 테스트가 CI 스위트를 통해 또는 로컬로 run-snapshot-tests.sh를 통해 실행될 때 어디서든 동일한 데이터베이스 상태가 존재함을 보장하기 위해 사용됩니다.

이러한 Fixtures를 포함하는 RSpec shared context를 spec/support/shared_contexts/glfm/example_snapshot_fixtures.rb에서 볼 수 있습니다.

환경 변수 기반 정규화

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

현재 footnode ID가 일반적으로 무작위이지만 GITLAB_TEST_FOOTNOTE_ID를 설정하여결정론적으로 재정의할 때 현재의 예시가 있습니다. 이는 spec/support/shared_contexts/glfm/example_snapshot_fixtures.rb에서 Fixture 설정과 함께 설정됩니다.

정규식 기반 정규화

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

정규식 기반 정규화는 특정 Markdown 예시에 대한 두 가지 다른 버전의 HTML 또는 JSON에 적용할 사용자 정의 정규식을 허용하며, 캡처 그룹의 내용을 동일한 고정 값으로 대체할 수 있습니다.

그런 다음 두 가지 정규화된 버전을 서로 비교하여 다른 변하지 않는 내용이 모두 동일한지 확인할 수 있습니다.

note
여기서 특정 속성 값 검증에 중점을 두지 않으므로 변수 값을 고정 값으로 제거하고 대체하면 괜찮습니다. 서로 다른 테스트 수준에는 각각 다른 목적이 있습니다:
  1. Markdown 스냅샷 테스트는 렌더링된 HTML/JSON의 구조를 강제하고, 규범 사양을 준수하는 것이 목적입니다.
  2. 특정 Markdown 예시의 구현에 대한 개별 단위 테스트는 특정 및 대상화된 테스트를 담당하여 이러한 변수 값을 테스트합니다.

또한 HTML의 표준화를 위해 동일한 정규식 캡처-대체 정규화 접근 방식을 사용합니다. 여기서는 변경 가능한 값만 대체하는 것이 아니라 비표준 HTML 부분을 제거합니다.

정규화가 어떻게 지정되는지에 대한 자세한 내용은 glfm_example_normalizations.yml을 참조하십시오.

목표

앞서 언급한 모든 제한 사항을 고려하여 GLFM 명세 및 테스트 인프라와 관련된 다양한 목표를 요약할 수 있습니다:

  1. GLFM이 HTML로 Markdown을 렌더링하는 공식 명세 및 참 소스가 있어야 합니다. 이 소스는 다음의 세 개의 Markdown 파일로 나타납니다:
    1. 일반 Markdown + GFM 예시를 위한 ghfm_spec_v_?.??.md
    2. GLFM 공식 예시를 위한 glfm_official_specification.md
    3. GLFM 내부 확장을 위한 glfm_internal_extensions.md
  2. 이 공식 명세는 다음을 충족해야 합니다:
    1. 명세는 CommonMark 명세의 엄격한 상위집합이며 정확한 참 소스입니다.
    2. 따라서 이 명세에는 CommonMark 및 GFM에 포함된 모든 Markdown 예시, 그리고 GLFM의 공식 명세내부 확장의 상위집합이 포함되어야 합니다.
    3. 어떠한 추가적인 Markdown도 포함하여 GLFM의 공식 명세내부 확장 에서 섹션 및 예시를 포함합니다. 또한 이 중요한 내용은 Markdown 예시 및 그와 관련된 수사와 마찬가지로 포함되어야 합니다.
    4. 모든 헤더 및 Markdown 예시는 표준 형식을 가져야 하며, 표준 CommonMark 도구인 spec_tests.py를 사용하여 처리할 수 있어야 합니다. 이 도구는 spec.txt에 포함된 모든 예시에 대한 Markdown 일치 테스트를 수행하도록 사용됩니다.
  3. 정적 백엔드(Ruby) 및 WYSIWYG 프론트엔드(JavaScript) 구현 모두 GLFM의 모든 정규 Markdown+HTML 예시를 일관되게 렌더링할 수 있어야 하며, 이는 run-spec-tests.sh에 의해 확인되어야 합니다.

    NOTE: 일관성이란 두 구현 모두 동일한 HTML를 렌더링하는 것을 의미하는 것은 아닙니다. 각각의 구현에는 HTML을 렌더링하기 위한 구현별 추가 기능이 있으므로 렌더링된 HTML은 “표준화”된 후 Markdown 일치 테스트를 수행합니다.

  4. 정적 백엔드(Ruby)와 WYSIWYG 프론트엔드(JavaScript) 구현 모두 GLFM spec.txt의 모든 Markdown 예시에 해당하는 YAML 파일 형식의 예시 스냅샷 집합이 존재해야 합니다. 이 예시 스냘샷은 모든 GLFM Markdown 예시를 위해 다음과 같은 용도를 지원합니다:
    1. 백엔드(Ruby) 파서 및 렌더러는 Markdown을 예상한 사용자 정의 정적 HTML로 변환할 수 있어야 합니다.
    2. 프론트엔드(JavaScript) 파서 및 렌더러(기능에는 GitLab 사용자 정의 코드 및 Remark가 포함됨)는 ProseMirror 문서를 나타내는 예상된 ProseMirror JSON으로 Markdown을 변환할 수 있어야 합니다.
    3. 리치 텍스트 편집기(프론트엔드(JavaScript) 파서 및 렌더러 및 ProseMirror를 포함)는 ProseMirror에 의해 렌더링된 예상된 커스텀 WYSIWYG HTML로 Markdown을 변환할 수 있어야 합니다.
    4. 리치 텍스트 편집기는 Markdown으로 변환하여 MDAST로 변환하고 ProseMirror 문서로 다시 변환한 뒤 마크다운으로 다시 변환하는 왕복 테스트를 완료할 수 있어야 합니다. 결과적으로 생성된 마크다운이 완전히 동일하며 차이가 없는지 확인합니다.

구현

다음 스크립트 및 파일 집합은 복잡합니다. 그러나 위에 나열된 모든 목표를 충족하도록 허용하며, 다음과 같은 구현 목표를 주의 깊게 고려하여 설계되었습니다.

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

구현에 대한 문서는 세 가지 섹션으로 분할됩니다:

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

스크립트

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

note
이 스크립트 중 일부는 루비로 구현되어 있고, 다른 몇 개는 셸 스크립트입니다. 루비 스크립트는 더 복잡한 사용자 정의 스크립트에 사용되어 더 쉬운 단위 테스트 및 디버깅을 가능케 하며, 다른 셸 명령을 주로 호출하는 간단한 스크립트에는 셸 스크립트가 사용됩니다.

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 스크립트, 이러한 스크립트를 실행했을 때 생성된 및 커밋된 출력 명세 파일 또는 예시 스냅숏 파일에 어떤 차이점이 있는지에 대한 예외와 비-제로 반환 코드로 실패합니다.

이 스크립트는 glfm-verify CI 작업을 통해 실행되어 입력 명세 파일에 대한 모든 변경 사항이 생성된 출력 명세 및 예시 스냅숏 파일에 반영되는지 확인합니다.

명세 파일

이 파일은 GLFM 명세 자체를 나타냅니다. 모두 루트 폴더 glfm_specification에 위치하며 사용 및 목적에 따라 하위 카테고리로 나뉘어 있습니다.

입력 명세 파일

입력 명세 파일은 명세 자체를 나타내는 매뉴얼으로 편집된 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 주석 줄까지.
note
더 분명히 하기 위해, 이 파일은 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만 포함해야 합니다. 현재 추가 확장 주석을 포함하지 않습니다.
  • update-specification.rb 스크립트는 생성된 spec.txt의 부록 이전에 새로운 섹션으로 삽입합니다.
  • H1 헤더 섹션으로 구성되어 있어야 하며, 모든 예시는 H2 또는 H3 헤더 섹션 내에 중첩되어 있어야 합니다.
  • H3 헤더 섹션은 직접적으로 H1 헤더 섹션 내에 중첩되어서는 않되며,

추가의 오로지 서술 부분 헤더 섹션을 포함할 수 있습니다.

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

입력 사양 구성 파일

입력 사양 구성 파일은 자체적으로 관리하는 YAML 파일로, 자동화된 GLFM 스크립트 및 프로세스의 다양한 측면을 제어합니다. 이 파일들은 다음 경로에 있습니다. glfm_specification/input/gitlab_flavored_markdown/*.yml.

더 많은 맥락과 세부 정보는 사양 파일 섹션을 참조하세요.

구성 파일 유효성 검사

구성 파일의 모든 매뉴얼으로 관리되는 예제 이름은 output_example_snapshots/examples_index.yml에서 찾을 수 있는 기존 마크다운 예제 이름과 일치해야 합니다. 이 파일은 입력 사양 파일을 기반으로 자동으로 생성됩니다.

존재하지 않는 예제 이름에 대한 무효한 참조가 있는 경우 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* 필드는 마크다운 예제를 기반으로 한 스냅샷 예제 항목의 자동 생성 상태를 제어합니다.
  • skip_running_* 컨트롤은 개별적인 예제에 대한 마크다운 일치 테스트 또는 마크다운 스냅샷 테스트를 건너뛸 수 있게 합니다.
  • 이를 통해 구현되지 않은 경우, 부분적으로 구현된 경우, 오류가 있는 경우, 생성할 수 없는 경우 또는 어떤 이유로든 테스트할 수 없는 경우에 대해 해당 처리 또는 테스트를 건너뛸 수 있습니다.
  • 모든 항목은 기본적으로 false로 설정됩니다. Ruby 값 중 참으로 평가되는 값을 지정하여 true로 설정할 수 있습니다. 이는 불린 true 값이 될 수 있지만, 이상적으로는 예제의 업데이트 또는 테스트를 건너뛰는 이유를 설명하는 문자열이어야 합니다.
  • skip_update_example_snapshot* 항목을 true로 설정하면 기존 값이 유지됩니다. 그러나 YAML이 다시 작성되기 때문에 문자열 값의 스타일과 블록 촘핑 표시기 (|)가 수정될 수 있습니다. 이는 Ruby psych YAML 라이브러리가 이를 자동으로 결정하기 때문입니다.

다음과 같은 선택적 항목이 각 예제에 대해 지원됩니다. 이러한 모든 항목은 기본적으로 false로 설정됩니다.

  • skip_update_example_snapshots: true인 경우, 이 예제의 항목에 대한 추가 또는 업데이트를 건너뜁니다. glfm_specification/output_example_snapshots/html.yml 파일 또는 glfm_specification/output_example_snapshots/prosemirror_json.yml 파일에서의. 이 값이 참이면 다른 skip_update_example_snapshot_* 항목 중 어느 것도 참이면 안 되며, 이렇게 될 경우 오류가 발생합니다.
  • skip_update_example_snapshot_html_static: true인 경우, static HTML에서 이 예제의 항목 추가 또는 업데이트를 건너뜁니다.
  • skip_update_example_snapshot_html_wysiwyg: true인 경우, WYSIWYG HTML에서 이 예제의 항목 추가 또는 업데이트를 건너뜁니다.
  • skip_update_example_snapshot_prosemirror_json: true인 경우, 이 예제의 항목을 glfm_specification/output_example_snapshots/prosemirror_json.yml 파일에 추가하지 않거나 업데이트를 건너뜁니다.
  • skip_running_conformance_static_tests: true인 경우, 이 예제에 대한 static HTML의 마크다운 일치 테스트를 건너뜁니다.
  • skip_running_conformance_wysiwyg_tests: true인 경우, 이 예제에 대한 WYSIWYG HTML의 마크다운 일치 테스트를 건너뜁니다.
  • skip_running_snapshot_static_html_tests: true인 경우, 다양한 버전의 렌더링된 HTML에 대한 static HTML의 마크다운 스냅샷 테스트를 건너뜁니다.
  • skip_running_snapshot_wysiwyg_html_tests: true인 경우, WYSIWYG HTML의 마크다운 스냅샷 테스트를 건너뜁니다.
  • skip_running_snapshot_prosemirror_json_tests: true인 경우, ProseMirror JSON의 마크다운 스냅샷 테스트를 건너뜁니다.

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 파일은 픽스처 기반 정규화 프로세스를 제어하는 데 사용됩니다. Markdown 예제에 대해 하나 이상의 regex/replacement 쌍을 지정할 수 있습니다.

  • 매뉴얼으로 업데이트됩니다.
  • 사용된 예제 및 해당 항목 유형과 해당 중첩 구조를 가집니다.
  • 동일한 regex/replacement 쌍이 중복되지 않도록 하고 여러 예제 사이에서 공유할 수 있도록하기 위해 YAML 앵커 및 별칭을 적극적으로 사용합니다.
  • YAML 앵커는 예제의 색인 번호를 기반으로 명명 규칙을 사용하여 고유한 앵커 이름을 보장하고 이름 충돌을 피합니다.
note
픽스처 기반 정규화환경 변수 기반 정규화와 같은 정규화에 대한 다른 접근 방식이 항상 픽스처 기반 정규화보다 우선합니다.

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

# NOTE: 하나 이상의 예제에서 공유되는 모든 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 필드는 지정된 예제에 대한 정적 HTML을 생성하는 데 사용되는 API 엔드포인트 경로를 재정의합니다. 경우에 따라 다른 엔드포인트는 다른 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 디렉터리에는 spec.txt 파일이 포함되어 있습니다. 이 파일은 update-specification.rb 스크립트에 의해 생성되는 GLFM 사양을 나타냅니다. 또한 spec.txt를 입력으로 사용하여 생성된 spec.html도 포함하고 있습니다.

GFM에서 spec.txttest dir에 위치하고 있으며, CommonMark에서는 프로젝트 루트에 위치하고 있습니다. 표준 위치에 대한 전례가 존재하지 않습니다. 나중에 렌더링된 HTML spec.html의 호스팅된 버전을 다른 위치나 사이트로 이동하거나 복사하기로 결정할 수 있습니다.

spec.txt

glfm_specification/output_spec/spec.txt는 GLFM 사양을 나타내는 표준 형식의 Markdown 사양 파일입니다. 이 파일은 공식 사양인 glfm_official_specification.md의 예제만 포함하고 있으며, 내부 확장 예제는 포함하고 있지 않습니다.

또한 해당 파일은 run-spec-tests.sh와 같은 다른 스크립트에 대한 입력으로 사용됩니다.

해당 파일은 update-specification.rb 스크립트에 의해 생성 또는 업데이트되며, 입력 사양 파일을 사용합니다. 이 프로세스에 대한 다이어그램과 자세한 설명은 update-specification.rb 스크립트 섹션을 참조하세요.

note
spec.txt가 Markdown 파일임에도 불구하고, 일관성을 유지하기 위해 *.txt 확장명을 사용합니다. 다른 모든 GLFM Markdown 파일은 다양한 편집기와 Markdown 형식 지원 및 구문 강조 기능을 활성화하기 위해 확장명 *.md를 사용합니다.
spec.html

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

해당 파일은 “GitHub Flavored Markdown”(GFM) 사양CommonMark 사양의 HTML 렌더링 버전과 대응됩니다. 그러나 GitLab Flavored Markdown (GLFM) 예제만을 포함하고 있습니다.

note
이 HTML의 형식은 현재 GFM 및 CommonMark HTML 렌더링 사양과 정확히 일치하지 않습니다. 이는 단순히 spec.txt를 GitLab Markdown 렌더러를 통해 실행한 결과일 뿐입니다. HTML을 적절하게 포맷하려면 CommonMark 프로젝트의 Lua 스크립트 및 템플릿을 복제하거나 재사용해야 합니다. CommonMark Makefile를 참조하세요.

출력 예제 스냅샷 파일

output_example_snapshots 디렉터리에는 update-specification.rbupdate-example-snapshots.rb 스크립트에서 생성된 파일이 포함되어 있습니다. 이 파일들은 glfm_specification/input 디렉터리의 파일을 기반으로 생성됩니다.

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

  1. GFM, GitHub Flavored Markdown 및 GitLab Flavored Markdown 사양을 모두 포함하는 전체 예제의 상위 집합을 포함합니다. 반면 spec.*은 GLFM 사양만을 포함합니다. 이는 스냅샷 테스트를 다룰 때 모든 예제를 참조할 수 있는 단일 위치를 제공하기 위함입니다.
  2. 예제만 포함하는 헤더 섹션만을 포함하고 있습니다. 예제가 포함되지 않은 설명에 대한 섹션은 포함되어 있지 않습니다.

update-example-snapshots.rb 스크립트는 다양한 output_snapshot_examples/*.yml 파일을 생성합니다. 해당 파일들은 스냅샷 테스트를 실행하는 데 사용되는 픽스처로 활용됩니다.

GLFM 구현이 백엔드(Ruby) 및 프론트엔드(JavaScript) 모두 완료되면 이러한 YAML 파일들은 자동으로 생성될 수 있습니다. 그러나 구현이 진행 중인 경우 glfm_specification/input/gitlab_flavored_markdown/glfm_example_status.ymlskip_update_example_snapshots 키를 사용하여 일부 예제의 자동 생성을 비활성화할 수 있습니다. 대신, 해당 예제를 구현 작업을 진행하는 데 도움이 되도록 매뉴얼으로 편집할 수 있습니다.

snapshot_spec.md

glfm_specification/output_example_snapshots/snapshot_spec.mdspec.txt와 유사한 표준 Markdown 및 대표적인 HTML 예제를 담고 있는 Markdown 파일입니다.

update-specification.rb 스크립트에 의해 생성 또는 업데이트되며, 입력 사양 파일을 사용합니다. 이 프로세스에 대한 다이어그램 및 자세한 설명은 update-specification.rb 스크립트 섹션을 참조하세요. 또한 해당 파일은 output example snapshot files의 입력으로 사용되며, 실제 specification file로 사용되지 않습니다. spec.txt, spec.html과 같은 파일만큼의 목적은 개념적인 설명만을 담은 헤더 섹션 뿐인 경우입니다.

해당 파일은 spec.txt와 다음과 같은 차이점을 가집니다:

  1. spec.txt는 GitLab Flavored Markdown의 예제만을 포함하지만, snapshot_spec.md는 “GitHub Flavored Markdown”(GFM) 사양CommonMark 사양의 전체 예제 상위 집합을 포함하고 있습니다.
  2. spec.txt는 예제가 포함되지 않은 설명에 대한 섹션도 포함하며, 적절한 specification file로 사용될 수 있으나, snapshot_spec.md는 예제만을 포함하는 헤더 섹션만을 포함하고 있습니다. 이는 다른 output example snapshot files의 입력으로 서비스하는 목적을 갖고 있으며, 실제 사양 파일로 사용되는 것은 아닙니다.
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로 렌더링된 명세와 완전히 동일하지 않습니다. HTML을 적절히 형식화하려면 CommonMark 프로젝트의 Lua 스크립트와 템플릿을 복제하거나 재사용해야 합니다. CommonMark Makefile
examples_index.yml

glfm_specification/output_example_snapshots/examples_index.yml는 모든 CommonMark, GFM 및 GLFM 예제 이름이 고유하게 식별되는 이름과 함께 있는 주요 디렉터리입니다.

  • GFM spec.txt 명세의 계층적 섹션 및 예제에서 생성됩니다.
  • CommonMark 및 GFM 예제의 경우, 이러한 섹션들은 원래 GFM spec.txt에서 나왔습니다.
  • GLFM 예제의 경우, glfm_official_specification.mdglfm_internal_extensions.md에서 생성됩니다.
  • 각 예제에 대한 spec_example_position과 같은 추가 메타데이터도 포함됩니다.
    • spec_example_position - 파일의 각 Markdown + HTML5 예제의 인덱스 순서입니다.
      • 이 값은 파일의 행 번호가 아니라 파일에서 각 예제의 인덱스 번호입니다.
      • 표준 CommonMark 도구는 렌더링된 HTML 파일에서 각 예제의 인덱스 번호를 포함하고 있으므로 이 값은 렌더링된 spec.html 파일에서 예제를 찾는 데 사용할 수 있습니다. 예를 들어: https://spec.commonmark.org/0.30/#example-42
    • source_specification - 예제가 원래 어떤 명세에서 나왔는지를 나타냅니다: commonmark, github, 또는 gitlab.
  • 예제 항목 이름의 네이밍 컨벤션은 중첩된 헤더 섹션 이름과 헤더의 예제 위치에 기반합니다.
    • 이 네이밍 규칙은 상당히 안정적인 이름과 예제 위치를 보장해야 합니다. CommonMark / GLFM 명세는 거의 변경되지 않으며, 대부분의 GLFM 예제는 동일한 섹션 7 하위 섹션에 대해 여러 예제가 존재하는 경우에 추가됩니다.

examples_index.yml 샘플 항목:

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.yml에는 glfm_specification/output_example_snapshots/examples_index.yml의 각 항목에 대한 원시 Markdown이 포함되어 있습니다:

  • CommonMark 및 GFM Markdown의 경우, 표준 GFM spec.txt를 사용하여 update-example-snapshots.rb 스크립트를 통해 생성(또는 업데이트)됩니다.
  • 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.yml에는 glfm_specification/output_example_snapshots/examples_index.yml의 각 항목에 대한 HTML이 포함되어 있습니다.

세 가지 유형의 항목이 있으며, 각각에 대해 다른 HTML이 있습니다:

  • 캐노니컬(Canonical)
  • 정적(Static)
    • glfm_specification/output_example_snapshots/examples_index.yml의 각 항목에 대한 정적(백엔드(Ruby) 생성) HTML입니다.
    • update-example-snapshots.rb 스크립트를 통해 백엔드 Markdown API(또는 기본적인 내부 클래스)에서 생성(또는 업데이트)됩니다. 하지만 구현이 미완료된 정적 예제의 경우 매뉴얼으로 업데이트될 수 있습니다.
  • 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.yml에는 glfm_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"
          },
        ]
      },
    ]
  }

작업 흐름

이 섹션에서는 스크립트를 사용하여 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의 규격화된 Markdown 또는 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를 실행하여 모든 관련 frontend(RSpec) 및 backend(Jest) 테스트를 실행합니다.
    1. 어떤 frontend 또는 backend 스냅샷 테스트든 개별적으로 실행할 수도 있습니다.
    2. 일반적으로 continuous integration 스위트의 일부로 모든 frontend 및 backend 테스트도 실행됩니다.
  7. 입력 사양 파일, 출력 사양 파일, 또는 예제 스냅샷 파일에 대한 변경 사항을 커밋합니다.