7rikazhexde’s tech log

技術的な興味関心、備忘録、アウトプットなどを書いています。

Markdownリンターのmarkdownlint-cli/markdownlint-cli2の情報とpre-commitフックの設定方法について

概要

qiitaの記事でvscode拡張機能markdownlintを使用していることに触れました。

qiita.com

GitHubのプロジェクトでは基本的にpre-commit hooksを使用してコミット前に文法や体裁をチェックしています。pre-commitスクリプトの作成とフックはpre-commitで管理しています。

また、マークダウン用のpre-commitフックとして、mdformatを使用しているのですが、markdownlintのフックとして、markdownlint-climarkdownlint-cli2というpre-commitフックがあることを知り試してみることにしました。

本記事はCLIツールの紹介と使い方についてまとめた記事になります。

注意事項

2023/09/22時点の情報です。
最新の情報はプロジェクトのGitHubページを確認してください。

個人的な見解

記事ではmarkdownlint-climarkdownlint-cli2を紹介しますが、 個人的にはvscode拡張(markdownlint)+pre-commitフック(markdownlint-cli)--fixオプションは指定しない(=修正まではしない)指定が良いと思います。

理由はvscode拡張のmardkdownlintの警告に対してフォーマットした場合とmarkdownlint-climarkdownlint-cli2でそれぞれフォーマットとした場合とで異なる結果になるためです。

警告を解消しても意図した変換(修正)にならないのであれば意味がありません。 そのため、文法や体裁のチェックまで実行することが良いと個人的には思います。

pre-commitフックでmarkdownlint-cli/cli2を使用する意味

markdownlint-clivscode機能拡張であり、タブ表示したファイルのフォーマットチェックとファイル保存時に自動でフォーマットすることができます。

一方でpre-commitフックでは、設定上は全マークダウンファイルをチェック対象にすることができます。 基本的にファイル保存すると思うのでpre-commitフックの設定はしなくても良いですが、個人的にはタブ表示以外のファイルも文法や体裁をチェックしたほうが良いと思います。

markdownlintについて

以下記事でまとめていますので参照ください。

7rikazhexde.github.io

簡単にまとめると以下です。

  • フォーマットルール が存在する
  • vscode機能拡張をインストール、設定するとファイル保存時にフォーマット処理を実行できる
  • configファイルを設定すればルール適用有無を変更できる

markdownlint-cliについて

MarkdownLintのコマンドラインインターフェイス(CLI)です。 使い方はUsageを確認してください。

markdownlint-cli2について

markdownlint-cli2はmarkdownlint-cliと基本的に同じ機能をサポートしており、並行処理により高速化を実現していると記載されています。

参考情報

pre-commitフック設定(.pre-commit-config.yaml)

設定はmkdocsで作成した静的サイトのコンテンツの元になるMarkdownファイルに適用した例で説明します。

github.com

まずconfigファイル(.markdownlint.jsonc)について説明します。configファイルはmarkdownファイルに対して、フォーマットのルール適用を有無を指定できます。コマンド実行では--config`で指定することでconfigファイルを指定することができます。

以下の設定ではREADME.mddocs`ディレクトリ以下のすべてのMarkdownファイルに対してconfigファイル指定でフォーマットチェックを実行する方法です。

markdownlint-cli

  - repo: https://github.com/igorshubovych/markdownlint-cli
    rev: v0.36.0
    hooks:
      - id: markdownlint
        args:
          [
            #"--fix", # フォーマット指定は無効にする。
            "--config",
            ".markdownlint.jsonc",
            "README.md",
            "docs/**/*.md",
          ]

markdownlint-cli2

  - repo: https://github.com/DavidAnson/markdownlint-cli2
    rev: v0.10.0
    hooks:
      - id: markdownlint-cli2
        args:
          [
            #"--fix", # フォーマット指定は無効にする。
            "--config",
            ".markdownlint.jsonc",
            "README.md",
            "docs/**/*.md",
          ]

補足

markdownlint-cli2にはmarkdownlint-cli2-fixというコマンドも可能ですが非推奨のようです。markdownlint-cli2-fixはmarkdownlint-cli2の--fixオプション指定と同じとのことです。

Deprecated

The following command behaves similarly, defaulting the fix property to true:

markdownlint-cli2-fix "*/.md" "#node_modules" Otherwise, markdownlint-cli2-fix behaves the same as markdownlint-cli2.

構成ファイル(.markdownlint.jsonc)

いくつか除外するルールを設定しています。 その他の例はGitHub記載の .markdownlint.jsonc, .markdownlint.yamlを確認してください。 markdownlint-cliではコンフィグファイルにjson,yamlをサポートし、markdownlint-cli2ではその他のファイルもサポートしています。(詳細)

{
  // Reference : https://github.com/markdownlint/markdownlint/blob/main/docs/creating_rules.md

  // Unordered list indentation / 番号なしリストのインデント
  //"MD007": false,

  // Trailing spaces / 末尾のスペース
  //"MD009": false,

  // Hard tabs / インデントのタブ
  //"MD010": false,

  // Line length / 行の長さ
  "MD013": false,

  // Dollar signs used before commands without showing output / コマンドの前にドル記号を使用して出力を表示しない
  // コードブロックでコマンドライン(bash/zsh)を書く場合、コピー&ペーストを考慮すると、
  // "$"や"%"は表示しない方が良いので警告を有効にする。(見た目重視であれば無効にする。)
  //"MD014": false,

  // Multiple headings with the same content / 同じ内容の複数の見出し
  "MD024": false,

  // Multiple top-level headings in the same document / 同じドキュメント内の複数のトップレベルの見出し
  "MD025": false,

  // Trailing punctuation in heading / 見出しの末尾の句読点
  "MD026": false,

  // Inline HTML / raw HTMLの記入
  // MD009を無効にする変わりに改行に<br/>を使用するため無効にする。
  "MD033": false

  // Fenced code blocks should have a language specified / フェンスされたコードブロックには言語を指定する必要があります
  // 言語に問わずハイライトした方が良いので有効にする。
  //"MD040": false
}

実行結果例

MD012の警告の例で実行します。

MD012警告例

エラーが複数表示されていますが、正しくエラーが指摘されています。

markdownlint-cli

% poetry run pre-commit run --all-files

markdownlint.............................................................Failed
- hook id: markdownlint
- exit code: 1

docs/application/inkscape/inkscape-tips.en.md:14 MD012/no-multiple-blanks Multiple consecutive blank lines [Expected: 1; Actual: 2]
docs/application/inkscape/inkscape-tips.en.md:15 MD012/no-multiple-blanks Multiple consecutive blank lines [Expected: 1; Actual: 3]
docs/application/inkscape/inkscape-tips.en.md:14 MD012/no-multiple-blanks Multiple consecutive blank lines [Expected: 1; Actual: 2]
docs/application/inkscape/inkscape-tips.en.md:15 MD012/no-multiple-blanks Multiple consecutive blank lines [Expected: 1; Actual: 3]
docs/application/inkscape/inkscape-tips.en.md:14 MD012/no-multiple-blanks Multiple consecutive blank lines [Expected: 1; Actual: 2]
docs/application/inkscape/inkscape-tips.en.md:15 MD012/no-multiple-blanks Multiple consecutive blank lines [Expected: 1; Actual: 3]
docs/application/inkscape/inkscape-tips.en.md:14 MD012/no-multiple-blanks Multiple consecutive blank lines [Expected: 1; Actual: 2]
docs/application/inkscape/inkscape-tips.en.md:15 MD012/no-multiple-blanks Multiple consecutive blank lines [Expected: 1; Actual: 3]

markdownlint-cli2

% poetry run pre-commit run --all-files

markdownlint-cli2........................................................Failed
- hook id: markdownlint-cli2
- exit code: 1

markdownlint-cli2 v0.10.0 (markdownlint v0.31.1)
Finding: README.md docs/**/*.md docs/markdown/index.md docs/application/vscode/index.en.md docs/application/vscode/index.md docs/application/workflowy/workflowy-tips.md docs/programming-language/index.en.md docs/sample/sample-tips.md docs/application/vscode/setting-tips.md docs/programming-language/python/pymysql-tips.en.md docs/markdown/markdown-tips.en.md docs/command-line-tool/vi/vi-tips.en.md docs/application/inkscape/inkscape-tips.en.md docs/sample/sample-tips.en.md docs/programming-language/applescript/index.en.md docs/raspberrypi/index.md docs/application/index.md
Linting: 59 file(s)
Summary: 2 error(s)
docs/application/inkscape/inkscape-tips.en.md:14 MD012/no-multiple-blanks Multiple consecutive blank lines [Expected: 1; Actual: 2]
docs/application/inkscape/inkscape-tips.en.md:15 MD012/no-multiple-blanks Multiple consecutive blank lines [Expected: 1; Actual: 3]
markdownlint-cli2 v0.10.0 (markdownlint v0.31.1)
Finding: README.md docs/**/*.md docs/programming-language/python/pymysql-tips.md docs/command-line-tool/index.md docs/sample/index.md docs/application/obsidian/obsidian-tips.md docs/database/mariadb-tips.md README.md docs/command-line-tool/index.en.md docs/database/index.md docs/programming-language/python/pre-commit-tips.md docs/programming-language/python/post-commit-tips.md docs/programming-language/python/mdformat-tips.md docs/application/index.en.md docs/application/vscode/setting-tips.en.md docs/application/vscode/extention-tips.en.md docs/programming-language/python/dash-plotly-tips.en.md
Linting: 59 file(s)
Summary: 2 error(s)
docs/application/inkscape/inkscape-tips.en.md:14 MD012/no-multiple-blanks Multiple consecutive blank lines [Expected: 1; Actual: 2]
docs/application/inkscape/inkscape-tips.en.md:15 MD012/no-multiple-blanks Multiple consecutive blank lines [Expected: 1; Actual: 3]
markdownlint-cli2 v0.10.0 (markdownlint v0.31.1)
Finding: README.md docs/**/*.md docs/programming-language/applescript/example.md docs/raspberrypi/index.en.md docs/programming-language/python/dash-plotly-tips.md docs/raspberrypi/raspberrypi-ubuntu-tips.md docs/programming-language/python/pre-commit-tips.en.md docs/database/mariadb-tips.en.md docs/application/inkscape/inkscape-tips.md docs/raspberrypi/raspberrypi-ubuntu-tips.en.md docs/index.en.md docs/command-line-tool/git/git-tips.md docs/programming-language/python/mkdocs-tips.en.md docs/sample/index.en.md docs/markdown/index.en.md docs/programming-language/python/mkdocs-tips.md docs/application/obsidian/obsidian-tips.en.md
Linting: 59 file(s)
Summary: 2 error(s)
docs/application/inkscape/inkscape-tips.en.md:14 MD012/no-multiple-blanks Multiple consecutive blank lines [Expected: 1; Actual: 2]
docs/application/inkscape/inkscape-tips.en.md:15 MD012/no-multiple-blanks Multiple consecutive blank lines [Expected: 1; Actual: 3]
markdownlint-cli2 v0.10.0 (markdownlint v0.31.1)
Finding: README.md docs/**/*.md docs/programming-language/python/post-commit-tips.en.md docs/index.md docs/programming-language/python/index.md docs/application/vscode/extention-tips.md docs/programming-language/applescript/index.md docs/command-line-tool/git/git-tips.en.md docs/programming-language/applescript/example.en.md docs/programming-language/python/mdformat-tips.en.md docs/database/index.en.md docs/command-line-tool/vi/vi-tips.md docs/application/workflowy/workflowy-tips.en.md docs/programming-language/python/index.en.md docs/markdown/markdown-tips.md docs/programming-language/index.md
Linting: 59 file(s)
Summary: 2 error(s)
docs/application/inkscape/inkscape-tips.en.md:14 MD012/no-multiple-blanks Multiple consecutive blank lines [Expected: 1; Actual: 2]
docs/application/inkscape/inkscape-tips.en.md:15 MD012/no-multiple-blanks Multiple consecutive blank lines [Expected: 1; Actual: 3]

実行結果(--fix指定)

「個人的な見解」で説明しましたが、vscode拡張(markdownlint)では14,15行目が削除されるような修正がされるのですが、markdownlint-cli/cli2では変換結果が異なります。(cli/cli2でも変換結果が異なります。)

vscode拡張(markdownlint)と同じ修正結果もあるのですが、他にも異なる結果が見受けられました。これでは修正作業にも時間がかかってしまいます。そのため、エラーチェックまでに--fix指定はせずに実行すべきという意見です。

markdownlint-cli

MD012_markdown-cli_fix

markdownlint.............................................................Failed
- hook id: markdownlint
- files were modified by this hook

markdownlint-cli2

MD012_markdown-cli2_fix

markdownlint-cli2........................................................Failed
- hook id: markdownlint-cli2
- files were modified by this hook

markdownlint-cli2 v0.10.0 (markdownlint v0.31.1)
Finding: README.md docs/**/*.md docs/markdown/index.md docs/application/vscode/index.en.md docs/application/vscode/index.md docs/application/workflowy/workflowy-tips.md docs/programming-language/index.en.md docs/sample/sample-tips.md docs/application/vscode/setting-tips.md docs/programming-language/python/pymysql-tips.en.md docs/markdown/markdown-tips.en.md docs/command-line-tool/vi/vi-tips.en.md docs/application/inkscape/inkscape-tips.en.md docs/sample/sample-tips.en.md docs/programming-language/applescript/index.en.md docs/raspberrypi/index.md docs/application/index.md
Linting: 59 file(s)
Summary: 0 error(s)
markdownlint-cli2 v0.10.0 (markdownlint v0.31.1)
Finding: README.md docs/**/*.md docs/programming-language/python/pymysql-tips.md docs/command-line-tool/index.md docs/sample/index.md docs/application/obsidian/obsidian-tips.md docs/database/mariadb-tips.md README.md docs/command-line-tool/index.en.md docs/database/index.md docs/programming-language/python/pre-commit-tips.md docs/programming-language/python/post-commit-tips.md docs/programming-language/python/mdformat-tips.md docs/application/index.en.md docs/application/vscode/setting-tips.en.md docs/application/vscode/extention-tips.en.md docs/programming-language/python/dash-plotly-tips.en.md
Linting: 59 file(s)
Summary: 0 error(s)
markdownlint-cli2 v0.10.0 (markdownlint v0.31.1)
Finding: README.md docs/**/*.md docs/programming-language/applescript/example.md docs/raspberrypi/index.en.md docs/programming-language/python/dash-plotly-tips.md docs/raspberrypi/raspberrypi-ubuntu-tips.md docs/programming-language/python/pre-commit-tips.en.md docs/database/mariadb-tips.en.md docs/application/inkscape/inkscape-tips.md docs/raspberrypi/raspberrypi-ubuntu-tips.en.md docs/index.en.md docs/command-line-tool/git/git-tips.md docs/programming-language/python/mkdocs-tips.en.md docs/sample/index.en.md docs/markdown/index.en.md docs/programming-language/python/mkdocs-tips.md docs/application/obsidian/obsidian-tips.en.md
Linting: 59 file(s)
Summary: 0 error(s)
markdownlint-cli2 v0.10.0 (markdownlint v0.31.1)
Finding: README.md docs/**/*.md docs/programming-language/python/post-commit-tips.en.md docs/index.md docs/programming-language/python/index.md docs/application/vscode/extention-tips.md docs/programming-language/applescript/index.md docs/command-line-tool/git/git-tips.en.md docs/programming-language/applescript/example.en.md docs/programming-language/python/mdformat-tips.en.md docs/database/index.en.md docs/command-line-tool/vi/vi-tips.md docs/application/workflowy/workflowy-tips.en.md docs/programming-language/python/index.en.md docs/markdown/markdown-tips.md docs/programming-language/index.md
Linting: 59 file(s)
Summary: 0 error(s)

補足: mdformatでチェックまで実行する方法

上記変換差異はmdformatにも言えることです。 mdformatではチェックまで実行する場合は引数に--checkを指定することで有効にできます。

まとめ

Markdownリンターのmarkdownlint-cli/markdownlint-cli2の情報とpre-commitフックの設定方法について紹介しました。

mdformatを使用していますが、処理の速度的にはmarkdownlint-cli2 < mdformat < markdownlint-cliという印象です。

それぞれフォーマットまで使用できた方が良いですが、意図した変換にならないこともあるため注意は必要です。 ただ、便利なツールではあるので、コミット時の差分チェックと合わせて利用することでファイル管理がしやすくなると思います。

以上です。