GitLab Flavored Markdown(GLFM) 仕様ガイド

要約

  • _GitLab_Flavored Markdown(GLFM) は_GitHub_Flavored Markdown (GFM)をベースにしており、CommonMarkをベースにしています。
  • GLFMはMarkdown構文の2つの「セット」に分かれています:
    • 公式仕様」は特定の実装や環境に依存せず、どのエディタでもサポートされます。
    • GitLabの環境やメタデータに依存する可能性のある“内部拡張“。
  • これらの構文はすべて、CommonMark仕様の構文に基づいた特別なMarkdownファイルによって指定されます。このファイルには、Markdownとそれに対応する生成されたHTMLの「例」と、それぞれの例を説明する関連文書が並んでいます。
  • また、YAMLメタデータファイルもあり、個々のMarkdown/HTML例がどのように処理され、レンダリングされるべきかについての追加情報が含まれています。
  • これらのMarkdown/YAMLファイルとそれらが含むコンテナは複数の目的を果たします:
  • 上記の目標を達成するために、様々なスクリプトとロジックがあります。

導入

GitLabは様々な場所でMarkdownをサポートしています。私たちが使っているMarkdownの方言はGitLab Flavored Markdown(GLFM) と呼ばれています。

note
この文書では、_GFM_は_GitHub_Flavored Markdown のことであり、_GitLab_Flavored Markdown のことではありません。この文書で使われているさまざまな略語についての詳しい説明は、略語のセクションを参照ください。

GLFM方言の仕様はGitHub Flavored Markdown(GFM) 仕様に基づいています。GLFM仕様には、GFM仕様に比べて多くの追加事項があります。

このガイドは、GLFM仕様に関連するさまざまな用語や定義、目標、ツール、実装について説明する開発者向けのドキュメントです。GitLab Flavored Markdownのユーザー向けドキュメントをサポートし、補強することを目的としています。

note
このガイドとその中で説明されている実装やファイルはまだ作業中です。作業が進むにつれて、このガイドとGitLab Flavored Markdownのユーザー向けドキュメントの間で書き換えや統合が行われる可能性があります。

用語と定義

略語GLFM、GHFM、GFM、コモンマーク

_GitHub_Flavored MarkdownはGFMという頭字語で広く呼ばれており、このドキュメントもそれに従います。_GitLab_Flavored MarkdownはGitHub Flavored Markdownと区別するために、このドキュメントではGLFMと呼びます。

残念ながら、この慣例は他のドキュメントやGitLabコードベースではまだ一貫して守られていません。多くの場所で、GFMという頭字語が_GitLab_Flavored Markdownを指すのに使われています。この矛盾を解決するためのオープンイシューが存在します。

コードの中には、ロジックの同じ領域で GitLab と GitHub の両方の仕様を同時に参照している場所があります。このような状況では、混乱を避けるために_GitHub_Flavored Markdownをghfm_ のような変数名や定数名で参照することがあります。例えば、ghfm_spec_v_0.29.md GitHub Flavored Markdown 仕様ファイルgitlab リポジトリにコミットされ、update_specification.rb スクリプトの入力として使用されますが、ghfm の頭文字を使用しています。

オリジナルのCommonMark仕様は_CommonMark_(頭文字なし)と呼ばれています。

さまざまなMarkdown仕様

私たちが使用している仕様書フォーマットは、CommonMarkで使用されているアプローチに基づいています。spec.txt ファイルは、ドキュメントとして機能するだけでなく、自動化された適合性テストの入力としても使用できるフォーマットになっています。これはCommonMark仕様で説明されています:

このドキュメントはMarkdown構文を明確に指定することを試みます。それはMarkdownとHTMLを並べた多くの例を含んでいます。これらの例は適合性テストを兼ねています。

仕様のHTMLレンダリング・バージョンはこちらです:

しかし、GLFMはGFMやCommonMarkよりも複雑な解析、レンダリング、テストが必要です。そのため、静的でハードコードされ、手動で更新されるspec.txt はありません。その代わり、GLFMspec.txt は他の入力ファイルに基づいて自動的に生成されます。このプロセスについては、以下の実装のセクションで詳しく説明します。

note
2022年12月現在、GitHub Flavored Markdown(GFM) 仕様のHTMLバージョンは古く、仕様のspec.txtと一致していません。このことを報告するためにspec.txtcmark-gfm プロジェクトでspec.txtイシューが提出されています。

公式仕様と内部拡張の比較

GitHubのGFMとGitLabのGLFMには、サポートするMarkdownの「セット」が2つあります:

  • 公式仕様
  • 内部拡張

以下のChartは、様々な仕様の分類と用語を示しています:

graph TD CM[CommonMark - spec.txt - for example, headings] --- GFMS[GFM Specification - spec.txt - for example, strikethrough extension] GFMS --- GLFM[GLFM Specification - for example, color chips] GFMS --- GFMI[GFM internal extensions - for example, GitHub-specific references] GLFM --- GLFS[GLFM internal extensions - for example, GitLab-specific references]
公式仕様

GFMとGLFMは、それぞれ公式仕様書を定めています:

  1. コモンマーク規格
  2. CommonMark 規格の汎用拡張。

例えば、GFM はstrikethrough 拡張を追加し、GLFM はcolor chips 拡張 を追加します。公式仕様のこれらの拡張機能は、特定の実装や環境に依存しません。これらはサードパーティのMarkdownレンダリング・エンジンで実装することができます。

内部拡張

GFMとGLFMはそれぞれ内部拡張機能を持っています。これらの拡張はGFMやGLFMの公式仕様の一部ではなく、GitHubやGitLab内部のMarkdownレンダラーやパーサーの実装の一部です。これらの内部拡張は、GitHubやGitLabの実装や環境に依存していることが多く、それらの環境との相互作用によってのみ利用可能なメタデータに依存していることがあります。例えば、GitHubはGitHub固有の自動リンク参照をサポートしており、GitLabもGitLab固有の参照をサポートしています。これらはGitHubやGitLabとインテグレーションするサードパーティのMarkdownレンダリングエンジンによって実装されることもあります。例えば、エディタやIDEのプラグインで、ユーザーはエディタやIDE内でイシュー、プルリクエスト、マージリクエストのMarkdownを直接編集することができます。

Markdownの例

仕様とこのガイドの文脈のあらゆるところで、_例という_用語は、標準的なCommonMark仕様フォーマットにおける様々なMarkdownソース文字列の正規パース(またはレンダリング)動作を説明するために、バックティックで区切られたMarkdown + HTMLペアを使用する慣習を指すために特別に使用されています。

この文脈では、RSpecのexampleのような_exampleの_他の類似または関連する意味と混同しないでください。

バックティックで区切られたMarkdown+HTMLのexample構文の詳細については、glfm_official_specification.md ファイルのセクションを参照してください。

パーサーとレンダラー

仕様が使用されるさまざまな方法を理解し、指定されたMarkdown方言にどのように関連するかを理解するためには、パーサーと _レンダ_ラーの区別を理解することが重要です:

  • Markdown_パーサーは_入力としてMarkdownを受け入れ、出力としてMarkdown Abstract Syntax Tree(AST) を生成します。
  • Markdown_レンダラーは_パーサーによって生成されたASTを受け入れ、出力としてHTML(またはPDF、またはその他の関連するレンダリングフォーマット)を生成します。

GLFM仕様によって駆動されるMarkdownテストのタイプ

自動テストの2つの主なタイプは、GLFM仕様に含まれるMarkdownの例とデータによって駆動されます。私たちはそれらをこう呼びます:

  • Markdown適合性テスト。
  • Markdownスナップショットテスト。

GitLab のコードベースには他にも多くの種類のテストがあり、その中には GLFM Markdown 方言に関連するものもあります。そのため、混乱を避けるために、この文書や他の場所で言及されている二種類の仕様駆動型テストにはこれらの標準的な用語を使います。

Markdown適合性テスト

note
GLFMのMarkdown適合性テストはまだ実装されていません。

Markdown適合性テストは、特定の実装がCommonMark Markdown仕様に適合していることを検証するために、すべてのCommonMark Markdown方言で使用される標準的なテスト方法を指します。仕様自体に記述されているように、与えられたspec.txt 仕様と実装に対して標準的なCommonMarkツールspec_tests.py を実行することによって実施されます。

適合性テストはGLFM公式仕様の 例に対してのみ_実行され、内部拡張の例に対しては実行さ_れません。これは、内部拡張例はGitLab環境やメタデータに依存している可能性がありますが、標準的なCommonMark適合性テストツールはこれをサポートしていないからです。

note
spec_tests.py Python に依存しないように、最終的には Ruby で再実装されるかもしれません。

Markdownスナップショットテスト

_Markdownスナップショットテストは_GitLabコードベースで実行される自動テストのことで、GLFM仕様のすべての例から得られたexample_snapshots フィクスチャデータによって駆動されます。バックエンドのRSpecテストと、フィクスチャデータを使うフロントエンドのJestテストの両方で構成されています。このフィクスチャデータは YAML ファイルにコンテナされています。これらのファイルは仕様の中のMarkdownの例と、既存のGLFMパーサーとレンダリングの実装に基づいて生成され、更新されます。また、不完全な実装をテストドライブするために、必要に応じて手動で更新されることもあります。

スナップショットテストは包括的であることを意図しているので、GLFM公式仕様と 内部拡張の例の両方、_すべての_例に対して実行されます。つまり、glfm_example_metadata.ymlのような内部拡張例で必要とされる GitLab 固有の環境やメタデータを提供するための設定ファイルを使います。

スナップショットテストの設計は、ユーザー向けのGLFM Markdownの正しさを保証するのに役立ちます。このテストでは、ブラックボックステストのアプローチを使って、バックエンドとフロントエンドのパーサーとレンダラーを徹底的に調べます。この包括的なスタイルにより、「テストピラミッドの頂点」に位置する高レベルテストの一種と考えることができます。

Markdownスナップショットテストに使用される用語について:

  1. Markdownスナップショットテストは、承認テストまたは特性テストとも呼ばれるゴールデンマスターテストアプローチの一形態と考えることができます。
    1. ゴールデンマスターという用語はもともとレコーディング業界に由来し、マスタリングのプロセス、つまり、他のすべてのコピーが作成される最終的なミックスを作成することを指します。
    2. より詳しい情報と背景については、キャラクタライゼーション・テストと ゴールデン・マスターをお読みください。
  2. _スナップショットという_言葉の使い方は、GitLabのフロントエンドテストスイートで使われているようなJestスナップショットテストのアプローチを指すものではありません。しかし、Markdown のスナップショットテストは Jest のスナップショットテストと同じ考え方とパターンに従います:
    1. スナップショットの例のフィクスチャデータは、ソースコントロールにチェックされるファイルとして表されます。
    2. ファイルは自動的に生成され、テスト対象のコードの実装に基づいて更新されます。
    3. また、不完全な実装やバグのある実装の変更をテストするためなど、 必要に応じてファイルを手動で更新することもできます。
  3. _フィクスチャという_用語の用法は、標準的なRailsデータベースのフィクスチャファイルを指すものではありません。代わりに、自動テストをサポートする入力データとして、より一般的な定義の _テストフィクスチャを_指します。
  4. これらのスナップショット例のフィクスチャファイルは、GLFM仕様の残りの部分から生成され、密接に関連しています。そのため、example_snapshots ディレクトリは、glfm_specification ディレクトリの下に、残りのGLFM仕様ファイルと一緒に配置されています。これらは意図的に_、_GitLab Railsアプリケーションのフィクスチャデータの残りと一緒にspec/fixtures 。実際には、開発者はこれらのファイルをspec/fixtures ディレクトリに分割するよりも、glfm_specification ディレクトリの下にすべてを配置する方がシンプルでわかりやすいと考えています。

以下の正規化のセクションもご覧ください。これはMarkdownスナップショットテストで使用される重要な概念です。

構文解析とレンダリング

GitLabアプリケーションで使われているMarkdown方言には、レンダリングに二重の要件があります:

  1. 静的な読み取り専用のHTMLフォーマットへのレンダリング。
  2. What You See Is What You Get”(WYSIWYG)エディタであるリッチテキストエディタでの編集可能なコンテンツのレンダリング。リッチテキストエディタは、編集可能なMarkdownソースと編集可能なWYSIWYGドキュメント間のリアルタイムの即時切り替えをサポートします。

これらの要件は、GitLabが2つの独立したパーサーとレンダラーの実装を持っていることを意味します:

  1. バックエンドのパーサー/レンダラーは、_静的な_読み取り専用HTMLのパースとレンダリングをサポートします。Rubyで実装されています。これはlibcmark-gfmの Ruby ラッパーであるcommonmarker gem を活用しています。libcmark-gfmCommonMarkの C リファレンス実装の拡張バージョンです。
  2. フロントエンドのパーサー/レンダラーは、リッチテキストエディタの解析と_WYSIWYG_レンダリングをサポートします。JavaScriptで実装されています。パーシングはRemarkMarkdownパーサーに基づいており、MDAST Abstract Syntax Tree(MDAST)を生成します。レンダリングはMDASTをProseMirrorドキュメントに変換するプロセスです。そして、ProseMirrorはProseMirrorドキュメントをWYSIWYG HTMLにレンダリングするために使用されます。このドキュメントでは、MarkdownをMDASTに変換するプロセスを_フロントエンド/JavaScriptパーサーと_呼び、ProseMirrorでMarkdownをWYSIWYG HTMLにレンダリングするプロセス全体を_リッチテキストエディタと_呼びます。独立したフロントエンドパーサー/レンダラー実装の必要性には、以下のような要件があります:
    1. バックエンドで使用されるHTMLレンダラー実装に、正確なソース マッピングに必要なサポートがないこと。
    2. 待ち時間と帯域幅に関する懸念: ユーザーがMarkdownソースとWYSIWYGドキュメントを切り替えるたびに、バックエンドへのラウンドトリップが不要になります。
    3. WYSIWYGドキュメントに対するさまざまなHTMLおよびブラウザのレンダリング要件。たとえば、ダイアグラムや参照などの読み取り専用の要素を編集可能な形で表示することなど。

レンダリングされたHTMLの複数のバージョン

これらのGLFMレンダラー実装(静的およびWYSIWYG)はどちらも、GLFMの標準的なHTML例とは異なるHTMLを生成します。 公式仕様のHTML例とは異なる可能性があります。したがって、GLFM仕様のすべてのMarkdownの例に対して、3つのバージョンのHTMLがその例からレンダリングされる可能性があります:

  • 静的HTML
  • WYSIWYG HTML
  • 正規のHTML

静的HTML

静的HTMLはバックエンド(Ruby)のレンダラーによって生成されるHTMLで、余分なスタイリングや動作HTMLを含んでいます。例えば、タスクリストの項目から動的にイシューを作成するために追加されたタスク作成ボタンなどです。GitLabMarkdown 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

Canonical HTMLはMarkdownからレンダリングされるHTMLのクリーンで基本的なバージョンで、スタイルやその他の実装特有の動作に関連する不要なクラスや要素はありません。

その目的はGLFMspec.txtに対するMarkdownの適合性テストをサポートすることです。

常にハードコードされ、手動で管理され、HTMLが自動的に生成されることはありません。HTMLを指定するMarkdownの例は、どのMarkdown仕様に由来するかによって、異なるファイルにコンテナされています。

カノニカルHTMLは 常に指定されていますCommonMark,GFM, andGLFM 公式仕様のすべてのMarkdownの例で指定されています。

しかし 指定されることはありませんGLFM内部拡張についてはMarkdownの例では指定されていません。これは内部拡張がMarkdownの適合性テストでテストされることがないからです。そのため、内部拡張の例のcanonical HTMLは、スクリプトや自動化されたテストで使われることはありません。

以下はcanonical HTMLサンプルのソースについての詳細です:

  1. CommonMark仕様とGFM拡張仕様の一部である例については、正準HTMLはGFMspec.txt Markdown例ブロックにあるものと全く同じHTMLです。これらの例はGFMspec.txt からGLFM版spec.txtにそのままコピーされています。
  2. GLFMの一部である例については 公式仕様GLFM公式仕様の一部である例については、glfm_official_specification.md入力仕様ファイルに含まれる例によって、標準的なHTMLが手動でメンテナーされ、管理されています。
  3. GLFM 内部拡張GLFM内部拡張の一部である例では、標準的なHTMLは決して指定されず、glfm_internal_extensions.md 入力仕様ファイルに含まれるすべての例で空のままでなければなりません。

HTMLの正規化

バックエンド(Ruby)およびフロントエンド(JavaScript)レンダラーからレンダリングされた静的 HTMLおよびWYSIWYG HTMLには、通常、特定の外観要件や動作要件をサポートするために、余分なスタイリングや HTML 要素が含まれています。

バックエンドもフロントエンドのレンダリングロジックも、GLFM公式仕様例の Markdown適合性テストを実行する際に正規HTMLとの比較を行うために必要な、クリーンで基本的なHTMLを直接レンダリングすることはできません。

なぜなら

  • GitLabアプリケーションの機能をサポートするための直接的な要件ではないからです。
  • この機能を追加すると、実装に不必要な要件や複雑さが加わります。

代わりに、レンダリングされた静的HTMLやWYSIWYG HTMLは、_正規化_処理によって正規HTMLに変換されます。このプロセスは、静的HTMLやWYSIWYG HTMLから余分なスタイルや動作のHTMLをすべて取り除くことができ、その結果、標準spec.txt 仕様にある正規化HTMLの例と正確に一致する正規化HTMLになります。

この処理にはcanonicalize-html.rb スクリプト を使ってください。

正規化

レンダリングされた HTML と ProseMirror JSON のバージョンは、さまざまな理由で異なることがあります。スタイリングや HTML 構造の違いだけでなく、属性やノードの値もテスト実行や環境によって異なる場合があります。たとえば、次のようになります:

  1. データベースのレコード識別子
  2. 名前空間またはプロジェクトの識別子
  3. URIの一部
  4. ファイルパスまたはファイル名
  5. ランダム値

Markdownスナップショットテストが適切に動作するためには、テストの信頼性を確保し、異なるテスト実行や環境間で常に同じ動作をするように、これらの違いを考慮する必要があります。

これらの違いを考慮するために、次のようなプロセスがあります。 正規化.正規化にはいくつかの方法があります:

  1. フィクスチャベースの正規化
  2. 環境変数ベースの正規化
  3. 正規表現ベースの正規化

フィクスチャベースの正規化

正規表現に基づく正規化よりもシンプルで理解しやすいので、可能な限りフィクスチャに基づく正規化を使うべきです。

Markdownスナップショットテストではスナップショットファイルの例を生成するためにRSpecを使用します。RSpecでは以下のことが可能です:

  • GitLab RSpecスイートの他の部分と同じ強力なフィクスチャサポートとヘルパーを使用します。
  • サンプルのスナップショットが生成されるときのデータベースの状態を制御するためにフィクスチャを使いましょう。
  • このフィクスチャの設定を RSpec の共有コンテキストに展開します。この共有コンテキストは、スナップショットテストが CI スイートあるいはrun-snapshot-tests.sh を経由して内部で実行される場合に、同じデータベース状態が存在することを保証するために使用されます。

spec/support/shared_contexts/glfm/example_snapshot_fixtures.rb で、これらのフィクスチャを含む RSpec 共有コンテキストを見ることができます。

環境変数ベースの正規化

場合によっては、フィクスチャは変化する値を制御できないので、使えないかもしれません。このような場合、運用コードに環境変数のサポートを導入することで、脚注の例のHTMLを生成するときにテスト環境のランダム性を上書きすることができます。環境変数が実運用コードのパスにあっても、明示的に設定されない限り何の効果もありません。これにより、後述するより複雑な正規表現に基づく正規化を避けることができます。

現在の例では、通常はランダムである脚注IDを、GITLAB_TEST_FOOTNOTE_IDを設定することで決定論的に上書きしています。これは、spec/support/shared_contexts/glfm/example_snapshot_fixtures.rb 共有コンテキストのフィクスチャのセットアップとともに設定されます。

正規表現ベースの正規化

フィクスチャベースの正規化も環境変数ベースの正規化も使えない場合、正規表現ベースの正規化を使います。これは強力ですが、より複雑で、よりメンテナンスが必要です。特定の例を名前で参照し、適切な正規表現を作成する必要があります。

正規表現ベースの正規化では、カスタム正規表現で キャプチャグループを2つの異なるバージョンのHTMLまたはJSONに適用し、キャプチャされたグループの内容を同じ固定値に置き換えることができます。

そして、正規化された2つのバージョンを比較し、変数以外のコンテンツがすべて同じであることを確認することができます。

note
ここでは、特定の属性値の検証にはこだわらないので、正規化によって変数値が破棄され、固定値に置き換えられても問題ありません。異なるテストレベルには異なる目的があります:
  1. Markdownスナップショット・テストはレンダリングされたHTML/JSONの構造を強制し、正規化仕様に準拠していることを確認することを目的としています。
  2. 特定のMarkdownの例に対する実装の個々のユニットテストは、これらの変数値の特定の、そして、ターゲットを絞ったテストを担当します。

また、HTMLの正規化にもこの同じ正規表現キャプチャと置換の正規化アプローチを使用しています。正規化では、単に変数値を置き換えるのではなく、HTMLの正規化されていない部分を削除します。

正規化の指定方法についての詳しい説明はglfm_example_normalizations.yml を参照してください。

目標

上記のすべての制約を考えると、GLFM仕様とテストインフラに関連するさまざまな目標を要約することができます:

  1. GLFMがどのようにMarkdownをHTMLにレンダリングするかについて、公式の仕様と単一の真実の源があります。この真実の源は、3つのMarkdownファイルで表されます:
    1. ghfm_spec_v_?.??.md CommonMark + GFMの例です。
    2. glfm_official_specification.md GLFM公式の例
    3. glfm_internal_extensions.md GLFM内部拡張用。
  2. この公式仕様はこれらの要求を満たしています:
    1. GFMCommonMark 仕様の厳密なスーパーセットであるように、この仕様は GitHub Flavored Markdown(GFM) 仕様の厳密なスーパーセットです。
    2. したがって、CommonMarkとGFMのすべてのMarkdownサンプルのスーパーセット、GLFM公式仕様と 内部拡張が含まれています。
    3. GLFM公式仕様と 内部拡張に含まれるすべての追加的なMarkdownのセクションと例を含み、CommonMarkとGFMの例と同じように、Markdownの例と付随するすべての散文があります。
    4. すべてのヘッダーとMarkdownの例はspec.txtに含まれるすべての例に対してMarkdownの適合性テストを行うために使われる標準的なCommonMarkツールspec_tests.py で処理できる標準フォーマットでなければなりません。
  3. 静的バックエンド(Ruby)とWYSIWYGフロントエンド(JavaScript)の両方の実装のためのGLFMパーサーとHTMLレンダラーは、run-spec-tests.sh によって検証されたように、仕様のすべての正規のMarkdown + HTML例の_一貫した_レンダリングをサポートします。

    note
    一貫しているというのは、これらの実装の両方が同一のHTMLにレンダリングするという意味ではありません。これらの実装はそれぞれ、レンダリングするHTMLに異なる実装固有の追加を行っているため、レンダリングされたHTMLはMarkdownの適合性テストを実行する前に、標準的なHTMLに“正規化 “されます。
  4. 静的なバックエンド(Ruby)とWYSIWYGフロントエンド(JavaScript)の_両方の_実装のために、GLFMspec.txt のすべてのMarkdownの例に対応するYAMLファイルの形でスナップショットの例のセットが存在します。これらのスナップショットはGLFMのすべてのMarkdownの例で以下の使い方をサポートしています:
    1. バックエンド(Ruby)のパーサーとレンダラーはMarkdownを期待されるカスタム静的HTMLに変換することができます。
    2. フロントエンド(JavaScript)のパーサーとレンダラー(GitLabのカスタムコードとRemarkを含む)は、MarkdownをProseMirrorドキュメントを表す期待されるProseMirror JSONに変換することができます。
    3. リッチテキストエディタ(フロントエンド(JavaScript)パーサーとレンダラー、ProseMirrorを含む)は、MarkdownをProseMirrorによってレンダリングされる期待されるカスタムWYSIWYG HTMLに変換できます。
    4. リッチテキストエディタは、MarkdownからMDAST、ProseMirrorドキュメントに変換し、Markdownに戻すラウンドトリップテストを行うことができます。これにより、結果のMarkdownがまったく同じであり、相違がないことが確認されます。

実施

以下のスクリプトとファイルのセットは複雑です。しかし、上記のすべての目標を達成することを可能にし、以下の実装目標を達成するために慎重に設計されています:

  1. GLFM仕様と関連ファイルの手動編集、管理、保守を最小限にすること。
  2. アップストリームのCommonMark仕様、GFM拡張、GLFM拡張に変更があった場合、GLFM仕様と関連ファイルを更新するプロセスを自動化し、簡素化します。
  3. GLFM仕様の部分的または不完全な実装を、進行中の作業、バグ、または新しい将来のMarkdownサポートに関わらず、サポートします。
  4. 標準的なCommonMark適合性テストとGLFM実装固有のユニット/受け入れMarkdownスナップショットテストを含む、さまざまなテストの自動化、簡素化、および実行をサポートします。
  5. 自動化された受け入れテストや自動化されたドキュメンテーションの更新のような、現在と将来の要求をサポートするために、すべてのGLFM仕様例の周りに拡張可能なメタデータの豊富なセットを提供します。

実装に関する文書は3つのセクションに分かれています:

  1. スクリプト
  2. 仕様ファイル
  3. スナップショットファイルの例:これらの YAML ファイルはさまざまなテストを実行するための入力データやフィクスチャとして使われ、glfm_specification/output_example_snapshots の下にあります。すべてのスナップショットファイルは仕様ファイルとパーサーとレンダラーの実装に基づいて自動的に生成されます。ただし、不完全な実装をテストドライブする場合など、必要に応じて直接編集することもできます。

スクリプト

これらの実行スクリプトは、仕様のメンテンナンスやテストの実行に関連するさまざまなタスクを実行します。各スクリプトは、scripts/glfm にあるシェル実行可能なエントリポイントファイルを持っていますが、実際の実装はscripts/lib/glfm のユニットテストされたクラスで行われます。

note
これらのスクリプトは Ruby で実装されているものもあれば、Shell スクリプトのものもあります。Ruby スクリプトは、より複雑なカスタム・スクリプトに使用され、単体テストとデバッグを容易にします。シェルスクリプトは、Rubyスクリプトから他のシェルサブプロセスを実行することに関連する課題を回避するために、主に他のシェルコマンドを呼び出す、より単純なスクリプトに使用されます。
note
scripts/glfm の Ruby 実行スクリプトのファイル名には、アンダースコアではなくダッシュが使われています。この命名はRubyファイルとしては標準的ではありませんが、ファイル名で検索する際に、scripts/lib/glfm の対応する実装クラスエントリポイントファイルと区別するために使われています。

update-specification.rb スクリプト

scripts/glfm/update-specification.rb スクリプトは、入力仕様ファイルを使用して、spec.txtspec.html 出力仕様ファイル、およびsnapshot_spec.mdsnapshot_spec.html 出力例スナップショットファイルの Markdown と HTML 出力ファイルを生成および更新します。

HTMLファイルは、生成された(または更新された)MarkdownをHTMLにレンダリングするためにバックエンドAPIに渡すことで作成されます。

graph LR subgraph script: S{update-specification.rb} end subgraph input - markdown files I1[glfm_official_specification.md - GLFM official specification examples] --> S end subgraph output - specification files S --> O1[spec.txt - GLFM official specification examples] S --> O2[spec.html - GLFM official specification examples] end
graph LR subgraph script: S{update-specification.rb} end subgraph input - markdown files I1[ghfm_spec_v_0.29.md - CommonMark and GHFM specification examples] --> S I2[glfm_internal_extensions.md - GLFM internal extension examples] --> S end subgraph output - example snapshot files S --> O1[snapshot_spec.md - CommonMark, GHFM, GLFM internal extension examples] S --> O2[snapshot_spec.html - CommonMark, GHFM, GLFM internal extension examples] end

canonicalize-html.rb スクリプト

scripts/glfm/canonicalize-html.rbHTMLの「正規化」を扱います。これは、余分なHTMLを含む静的またはWYSIWYGのHTML文字列を入力として受け取り、正規化されたHTML文字列を出力するパイプスルーのヘルパースクリプトです。

Unixの哲学に基づき、スタンドアロンでモジュール化された単一目的のスクリプトとして実装されています。GitLabレンダラーの実装に対して、標準のCommonMarkspec_tests.py スクリプトを実行すると、カノニカルHTMLを期待するため、使いやすいです。

run-spec-tests.sh スクリプト

scripts/glfm/run-spec-tests.sh spec_tests.py このスクリプトは、scripts/glfm/canonicalize-html.rb ヘルパースクリプトでghfm_spec_v_0.29.mdglfm_specification/output_spec/spec.txt ファイルを使用し、GLFMレンダラー実装がMarkdown仕様の例を正規化されたHTMLにレンダリングするためのサポートをテストします。

graph LR subgraph scripts: A{run-spec-tests.sh} --> C subgraph specification testing process B[canonicalize-html.sh] --> C C[spec_tests.py] end end subgraph input D1[ghfm_spec_v_0.29.md GLFM specification] --> C D2[spec.txt GLFM specification] --> C E((GLFM static<br/>renderer implementation)) --> B F((GLFM WYSIWYG<br/>renderer implementation)) --> B end subgraph output:<br/>test results/output C --> G[spec_tests.py output] end

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ファイル。スナップショットファイルの生成方法を制御するためのメタデータが含まれています。
graph LR subgraph script: A{update-example-snapshots.rb} end subgraph input: markdown input specification files B1[snapshot_spec.md] --> A C1[glfm_example_status.yml] --> A C2[glfm_example_normalizations.yml] --> A C3[glfm_example_metadata.yml] --> A end subgraph output: YAML example snapshot files A --> E[examples_index.yml] A --> F[markdown.yml] A --> G[html.yml] A --> H[prosemirror_json.yml] end

run-snapshot-tests.sh スクリプト

scripts/glfm/run-snapshot-tests.sh 便利なシェルスクリプトはexample_snapshot YAMLファイルによって駆動されるRSpecとJest*_spec ファイル (メインアプリspec フォルダから) に関連するすべてのMarkdownスナップショットを実行します。

実際のRSpecとJestのテストファイル*_spec (フロントエンドとバックエンド)は、spec 、対応する実装の場所と一致する、通常の関連する場所にあります。これらは次のどちらかで実行できます:

  • 標準パイプラインの一部として。
  • コマンドラインやIDEから、specの他のファイルと同じように。

しかし、これらは4つの異なる場所に分散しています:

  • バックエンドテストはspec/requests の下にあります。
  • ee/spec/requests でのバックエンド EE テスト .
  • spec/frontend でのフロントエンドのテスト。
  • ee/spec/frontend のフロントエンド EE テスト .

したがって、この便利なスクリプトは、ローカル開発者のみが使用することを想定しています。すべてのテストを一度に実行し、単一のリターンコードを返すことができます。このスクリプトには、関連するbundle exec rspec ... およびyarn jest ... コマンド用のシェルスクリプトコマンドのみが含まれています。

graph LR subgraph tests: B[relevant rspec+jest test files] end subgraph script: A{run-snapshopt-tests.sh} -->|invokes| B end subgraph output:<br/>test results/output B --> H[rspec+jest output] end subgraph input:<br/>YAML C[examples_index.yml] --> B D[markdown.yml] --> B E[html.yml] --> B F[prosemirror_json.yml] --> B end

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 の下にあり、さらに用途や目的に応じてサブカテゴリーに分けられています:

  • glfm_specification
    • input:ダウンロードまたは手動で編集されたファイルを含みます。これらは、他のすべての自動化されたGLFM仕様スクリプト、プロセス、またはテストを動かすためのオリジナルの入力です。
      • github_flavored_markdown:ダウンロードされ、コミットされたghfm_spec_v_0.29.md 仕様のみを含みます。
      • gitlab_flavored_markdown:すべてのglfm_* ファイルを含みます。
        • *.md これはGLFM仕様と関連するすべての例の真理の源です。
        • *.yml 自動化された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 は、公式の最新版GFMspec.txtのコピーです。

  • update-specification.rb スクリプトによって自動的にダウンロードされ、更新されます。
  • ダウンロードされると、ファイル名にバージョン番号が追加されます。
  • 拡張子はMarkdownエディターで扱いやすいように、*.txt から*.md に変更されています。

現在、序文と 付録の散文のみのヘッダーセクションが追加されています。

例を含むすべてのヘッダーセクションは、次のように区切られた連続したファイルセクションに含まれることが期待されています:

  1. 2番目のH1ヘッダーの冒頭(「はじめに」セクションの後の最初のヘッダー)
  2. <!-- END TESTS --> HTMLコメント行。
note
字語のセクションで説明したように、このファイルでは、gfm の代わりに、ghfm の頭字語を使用しています。
glfm_official_specification.md

glfm_specification/input/gitlab_flavored_markdown/glfm_official_specification.md GLFM公式仕様のために手動で更新されたMarkdown+HTMLの例と、関連する文書と説明から構成されています。

  • これは、標準のバックティックで区切られたspec.txt フォーマットの[Markdownの例](#markdown-examples) 、それぞれのMarkdownとレンダリングされるべき対応する正規のHTMLを含んでいます。
  • すべてのGitLabの例では、バックティックの後の “extension “アノテーションはexample のみです。GitHub Flavored Markdownの例ではこのような追加のアノテーションが含まれていますが(例えばexample strikethrough )、現在のところ特定のMarkdownを説明する追加の拡張アノテーションは含まれていません。
  • update-specification.rb スクリプトは生成されたspec.txt の付録の前に新しいセクションとして挿入します。
  • これはH1 のヘッダーセクションで構成され、すべての例はH2 またはH3 のヘッダーセクションの中に2レベルまたは3レベル深く入れ子になっています。
  • H3 ヘッダーセクションはH2 ヘッダーセクションの中に入れ子になっていなければなりません。H1 ヘッダーセクションの中に直接入れ子にすることはできません。

例文を含まない、散文だけのヘッダーセクションを追加_してもかまいません_。

例を含むすべてのヘッダーセクションは、<!-- BEGIN TESTS --><!-- END TESTS --> HTMLコメント行で区切られた、連続したファイルセクション内に含まれて_いなければなりません_。

glfm_specification/input/gitlab_flavored_markdown/glfm_official_specification.md サンプルエントリ

# Section with GLFM official specification examples

## Strong
{: #strong}

### Strong with two asterisks
{: #strong-with-two-asterisks}

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

### Strong with HTML
{: #strong-with-html}

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

glfm_specification/input/gitlab_flavored_markdown/glfm_internal_extensions.md 手動で更新されたGLFM内部拡張のMarkdownサンプルと、それに関連する文書と説明から構成されています。

その一般的なフォーマットはglfm_official_specification.mdと同じで、H1,H2, またはH3 のセクションで構成され、標準のバックティック区切りのspec.txt フォーマットMarkdown サンプルが含まれています。

しかし、標準的なHTMLのセクションで説明されたように、各例のMarkdownの部分だけが指定され、HTMLの部分は空のままです。

例文を含まない、散文だけのヘッダーセクションを追加_してもかまいません_。

例を含むすべてのヘッダーセクションは、<!-- BEGIN TESTS --><!-- END TESTS --> HTMLコメント行で区切られた、連続したファイルセクション内に含まれて_いなければなりません_。

glfm_specification/input/gitlab_flavored_markdown/glfm_official_specification.md サンプルエントリ

note
この例のすべての行の先頭に| 。この接頭辞は、このファイルがmarkdownlint でチェックされたときの誤ったエラーや、他のMarkdownエディタでのエラーの可能性を避けるのに役立ちます。実際のファイルには、これらの接頭辞|
|# Section with GLFM Internal Extension Examples
|
|## Video
|
|```````````````````````````````` example
|![video](video.m4v "video title")
|.
|````````````````````````````````

入力仕様設定ファイル

入力設定ファイルは、自動化されたGLFMスクリプトとプロセスの様々な側面を制御する手動でキュレーションされたYAMLファイルです。これらのファイルはglfm_specification/input/gitlab_flavored_markdown/*.yml にあります。

より多くのコンテキストと詳細については、メイン仕様ファイルのセクションを参照してください。

設定ファイルの検証

設定ファイル内の手動でキュレーションされたサンプル名はすべて、output_example_snapshots/examples_index.yml入力仕様ファイルに基づいて自動的に生成される既存のMarkdownサンプル名に対応していなければなりません。

存在しないサンプル名への無効な参照がある場合、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スナップショットテストを個々の例に対してスキップすることを許可します。
  • これにより、さまざまな例が未実装、部分的な実装、壊れている、生成できない、何らかの理由でテストできない場合に、この処理やテストをスキップすることを制御することができます。
  • すべてのエントリのデフォルトは false です。trueと評価されるRubyの値を指定することで、trueに設定することができます。これはtrue の真偽値でもよいのですが、理想的には、サンプルの更新やテストがスキップされる理由を説明する文字列であるべきです。
  • skip_update_example_snapshot* のエントリが真であるとき、既存の値は保存されます。psych しかしながら、YAML は書き直されるので、文字列の値のスタイルとBlock Chomping Indicator (|) は修正される可能性があります。

それぞれの例では次のオプションのエントリがサポートされています。デフォルトは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: 'An explanation of the reason for skipping.'
  skip_update_example_snapshot_html_static: 'An explanation of the reason for skipping.'
  skip_update_example_snapshot_html_wysiwyg: 'An explanation of the reason for skipping.'
  skip_update_example_snapshot_prosemirror_json: 'An explanation of the reason for skipping.'
  skip_running_conformance_static_tests: 'An explanation of the reason for skipping.'
  skip_running_conformance_wysiwyg_tests: 'An explanation of the reason for skipping.'
  skip_running_snapshot_static_html_tests: 'An explanation of the reason for skipping.'
  skip_running_snapshot_wysiwyg_html_tests: 'An explanation of the reason for skipping.'
  skip_running_snapshot_prosemirror_json_tests: 'An explanation of the reason for skipping.'
glfm_example_normalizations.yml

glfm_specification/input/gitlab_flavored_markdown/glfm_example_normalizations.ymlフィクスチャベースの正規化プロセスをコントロールするために使用されます。1つもしくは複数のregex/replacement のペアをMarkdownのサンプルに指定することができます。

  • 手動で更新します。
  • これは、参照する例とエントリーのタイプに対応する入れ子構造を持っています。
  • regex/replacement のペアの重複を避け、複数のサンプルで共有できるようにするために、YAMLアンカーとエイリアスを広範囲に使います。
  • YAMLアンカーはユニークなアンカー名を保証し名前の衝突を避けるためにサンプルのインデックス番号に基づいた命名規約を使います。

glfm_specification/input/gitlab_flavored_markdown/glfm_example_normalizations.yml サンプルエントリ

# NOTE: All YAML anchors which are shared across one or more examples are defined in the `00_shared` section.
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 anchors which are only shared within a single example should be defined within the example
  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します。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エンドポイントパスをオーバーライドします。異なるエンドポイントは、場合によっては異なる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.txt を入力として生成されるレンダリングされたspec.html も含まれます。

GLFM仕様を表すこれらの出力spec.* ファイルは、他のinput 仕様ファイルと同じ親フォルダglfm_specification の下に配置されています。これらは便宜上、また手動で編集されたファイルと生成されたファイルが混在しているため、ここに置かれています。

GFMでは、spec.txttest dirにあり、CommonMarkではプロジェクトルートにあります。標準的な場所の前例はありません。将来、レンダリングされたHTMLspec.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 のような他のスクリプトの入力にもなっています。

入力仕様ファイルを入力として、update-specification.rb スクリプトによって生成または更新されます。このプロセスの図と詳細については、update-specification.rb スクリプトセクション を参照してください。

note
spec.txt はMarkdownファイルですが、GFMやCommonMarkの仕様との整合性を保つため、*.txt という拡張子をつけています。他のすべてのGLFM Markdownファイルは、Markdownフォーマットとシンタックスハイライトを有効にするための様々なエディタとの互換性のために、*.md 拡張子で命名されています。
spec.html

glfm_specification/output_spec/spec.html は、spec.txt に基づいてレンダリングされたHTMLファイルです。これはspec.txtと同時にupdate-specification.rb スクリプトによって生成(または更新)されます。

これは “GitHub Flavored Markdown” (GFM)仕様と CommonMark仕様のHTMLレンダリング版に相当しますが、GitLab Flavored Markdown(GLFM) の例のみが含まれています。

note

このHTMLのフォーマットは、現在のところGFMとCommonMarkのHTMLレンダリング仕様と同一ではありません。これはGitLab Markdownレンダラーでspec.txt 。HTMLを適切にフォーマットするには、CommonMarkプロジェクトのLuaスクリプトとテンプレートを複製または再利用する必要があります:CommonMark Makefile

スナップショットファイルの出力例

output_example_snapshots ディレクトリには、glfm_specification/input ディレクトリのファイルに基づいて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ファイルはすべて自動的に生成されます。しかしながら、実装がまだ進行中である間は、glfm_specification/input/gitlab_flavored_markdown/glfm_example_status.ymlskip_update_example_snapshots キーを使っていくつかの例の自動生成を無効にすることができます。代わりに、実装を促進するために必要に応じて手動で編集できます。

snapshot_spec.md

glfm_specification/output_example_snapshots/snapshot_spec.md はMarkdownファイルで、spec.txt のような標準的なMarkdown + 標準的なHTMLの例を含んでいます。

これは、入力仕様ファイルを入力として、update-specification.rb スクリプトによって生成または更新されます。このプロセスの図と詳細については、update-specification.rb スクリプトセクション を参照してください。また、update-example-snapshots.rb のような他のスクリプトの入力としても機能します。

spec.txt と似ていますが、以下の点が異なります:

  1. spec.txt にはGitLab Flavored Markdownの例のみが含まれていますが、snapshot_spec.md 。また、”GitHub Flavored Markdown” (GFMspec.txt)仕様とspec.txt CommonMark仕様の例の完全なスーパーセットも含まれています。
  2. spec.txt はGLFM仕様の全文を表し、説明文のみで例文を含まない追加のヘッダーセクションを含みますが、snapshot_spec.md は例文を含むヘッダーセクションのみで構成されています。これは、このファイルの目的が、他のoutput example snapshot files の入力として機能することであり、spec.txtspec.htmlのような実際の仕様ファイルとして機能することを意図していないからです。
snapshot_spec.html

glfm_specification/output_snapshot_examples/snapshot_spec.html は、snapshot_spec.md に基づいてレンダリングされたHTMLファイルです。これはsnapshot_spec.mdと同時にupdate-specification.rb スクリプトによって生成(または更新)されます。

note
このHTMLのフォーマットは現在のところGFMやCommonMarkのHTMLレンダリング仕様と同一ではありません。これは、snapshot_spec.md を GitLab Markdown レンダラーを通して実行した生の出力に過ぎません。HTMLを適切にフォーマットするには、CommonMarkプロジェクトのLuaスクリプトとテンプレートを複製または再利用する必要があります:snapshot_spec.mdCommonMark Makefilesnapshot_spec.md
examples_index.yml

glfm_specification/output_example_snapshots/examples_index.yml は、CommonMark、GFM、GLFMのすべての例名のメインリストで、それぞれ一意に識別できる名前が付けられています。

  • GFMspec.txt 仕様書の階層的なセクションと例から生成されます。
  • CommonMark と GFM の例については、これらのセクションはもともと GFMspec.txt から取得したものです。
  • GLFMの例については、glfm_official_specification.mdglfm_internal_extensions.md から生成されています。
  • また、以下のような各例に関する特別なメタデータも含まれています:
    1. spec_example_position - 生成されたGLFMspec.txt ファイル内の例の位置。
      • この値はファイル内の個々のMarkdown + HTML5例のインデックス順です。ファイルの行番号では_ありません_。
      • この値は、レンダリングされたspec.html ファイル内の例を見つけるために使用できます。標準の CommonMark ツールには、レンダリングされた HTML ファイル内の各例のインデックス番号が含まれているからです。例:https://spec.commonmark.org/0.30/#example-42
    2. source_specification - この例が元々どの仕様に由来するか:commonmarkgithub 、またはgitlab
  • exampleエントリ名の命名規則は、入れ子になったヘッダーセクション名とヘッダーの exampleインデックスに基づいています。
    • この命名規則は、かなり安定した名前と例の位置になるはずです。CommonMark / GLFMの仕様が変更されることはほとんどなく、同じセクション7のサブセクションに複数の例が存在するほとんどのGLFMの例は、サブセクションの最後に追加されます。

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については、update-example-snapshots.rb スクリプトを使用して、標準のGFMspec.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.yml glfm_specification/output_example_snapshots/examples_index.yml の各エントリの HTML を含みます:

3種類のエントリーが存在し、それぞれに異なるHTMLがあります:

  • 正規表現
  • 静的
    • これは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.yml の各エントリの ProseMirror JSON がコンテナに格納されています。glfm_specification/output_example_snapshots/examples_index.yml

  • これは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 を便利なスクリプトとして実行し、 サンプルスナップショットを使用するフロントエンド (RSpec) およびバックエンド (Jest) のテストをすべて実行します。
    1. フロントエンドやバックエンドのスナップショットテストを個別に実行することもできます。
    2. すべてのフロントエンドとバックエンドのテストは、継続的インテグレーションスイートの一部として実行されます。
  7. 入力仕様ファイル出力仕様ファイル、あるいはスナップショット例のファイルに対するすべての変更をコミットします。