Markdown を書くことができる人は多いですが、良い Markdown を書くことができる人は少ないです。ファイル内の Markdown の文法やスタイルをチェックし、解決策を提案し、問題を自動修正し、さらには中英文の間に「盤古之白」を自動的に補完する「秘書」として機能するツールはありませんか?この記事で紹介する Markdown 文法チェッカーはそれを実現します。
はじめに#
Markdown を書くことができる人は多いですが、良い Markdown を書くことができる人は少ないです。これは Markdown エコシステム自体の問題でもあります:文法のバリエーションと実装方法は多種多様で、互換性がなく、さらには相互に矛盾しています。
一方で、Markdown の技術仕様を注意深く読むために時間をかける人はほとんどいません。ほとんどの人は「速成」の記事を一、二回読んだだけで、自分で判断してしまい、細かい問題には注意を払っていません。執筆中に問題に直面しても、想像や直感で適当に判断しています。
そのため、文法が自由すぎて、レイアウトが乱雑で、読者やレイアウトソフトウェアを困惑させる Markdown ファイルが大量に生まれています。
JavaScript には ESLint があり、Python には PyLint がありますが、Markdown にも markdownlint があるのでしょうか?答えはもちろん「はい」です!
例#
このブログのソースコードには markdownlint の規範が組み込まれていますので、ブログのソースコードをダウンロードして設定を確認できます。
{{< link href="http://github.com/Lruihao/hugo-blog" content="Lruihao/hugo-blog" card=true >}}
markdownlint の導入#
markdownlint は Markdown 文法チェックツールで、Markdown ファイル内の文法エラーや不規則な書き方をチェックし、Markdown をきれいで衛生的に保つことができます。
markdownlint には 2 つのバージョンがあり、Mark Harrisonによる Ruby ベースのオリジナルと、David Ansonによる Node.js ベースの移植版があります。Node.js 版は人気と活発さで後から追い上げてきたため、この記事では Node.js 版を例にします。
markdownlint は複数のシーンで使用できます。例えば:
この記事の主な目的は、markdownlint-cli2 の使用を紹介することです。これはプロジェクトに統合でき、チーム協力を便利にします。
markdownlint cli の歴史#
David のブログによると1、2015 年頃にIgor Shubovychと彼が CLI ツールの開発について話し合ったとき、David はまだ準備ができていなかったため、Igor は独自にmarkdownlint-cliという CLI ツールを開発しました。
2 年の発展を経て、ますます多くの人々が markdownlint-cli を使用し始め、David は markdownlint-cli プロジェクトにコードを貢献し、新機能を追加し、その後 3 年間主要なメンテナンス担当者となりました。2020 年までに、David は他のプロジェクトでいくつかのことを変更するのが難しいと感じ(後方互換性の問題が関与する可能性があります)、彼はmarkdownlint-cli2という新しいプロジェクトを再構築しました。これは markdownlint-cli を基に改善され、より高速な実行速度、柔軟な設定、依存関係の削減などの利点を持っています。
現在、これらの 2 つのツールは markdownlint の更新に合わせて更新されています。すでに markdownlint-cli を使用している古いプロジェクトは、未知の問題を避けるために引き続き使用できます。新しく導入されたプロジェクトには、より強力な markdownlint-cli2 の使用を検討できます。
markdownlint-cli2 のインストール#
npm install markdownlint-cli2 --save-dev
ショートカットコマンドの設定:
{
"scripts": {
"lint:md": "markdownlint-cli2 \"content/**/*.md\"",
"fix:md": "npm run lint:md -- --fix"
}
}
markdownlint-rule-search-replace
プラグインのインストール2:
npm install markdownlint-rule-search-replace --save-dev
プロジェクトのルートディレクトリに.markdownlint.jsonc
ファイルを作成し、ルールを設定します:
// このファイルはMarkdownlintの設定を定義します。詳細については
// https://github.com/DavidAnson/markdownlint/blob/main/doc/Rules.md
// 各ルールの詳細を参照してください。
{
"default": true,
"ul-style": {
"style": "dash"
},
"ul-indent": {
"indent": 2
},
"no-hard-tabs": {
"spaces_per_tab": 2
},
"line-length": false,
"no-duplicate-header": {
"allow_different_nesting": true
},
"single-title": {
"front_matter_title": "^\\s*title\\s*[:=]"
},
"no-trailing-punctuation": {
"punctuation": ".,;:"
},
// 連続したノート/コールアウトは現在このルールに準拠していません
"no-blanks-blockquote": false,
// インデントからのリストの誤った終了をキャッチするために順序付き番号を強制
"ol-prefix": {
"style": "ordered"
},
"no-inline-html": {
"allowed_elements": [
"br",
"code",
"details",
"div",
"img",
"kbd",
"p",
"pre",
"sub",
"summary",
"sup",
"table",
"tbody",
"td",
"tfoot",
"th",
"thead",
"tr",
"ul",
"ol",
"var",
"ruby",
"rp",
"rt",
"i"
]
},
"no-bare-urls": false,
// 偽陽性が多すぎます
"fenced-code-language": false,
"code-block-style": {
"style": "fenced"
},
"no-space-in-code": false,
"emphasis-style": {
"style": "underscore"
},
"strong-style": {
"style": "asterisk"
},
// https://github.com/OnkarRuikar/markdownlint-rule-search-replace
"search-replace": {
"rules": [
{
"name": "nbsp",
"message": "ノーブレークスペースを使用しないでください",
"searchPattern": "/ /g",
"replace": " ",
"searchScope": "all"
},
{
// zh-cn/zh-twは代わりにダブルエムダッシュを好みます
"name": "em-dash",
"message": "'--'を使用しないでください。代わりにエムダッシュ(—)を使用してください",
"search": " -- ",
"replace": " — ",
"searchScope": "text"
},
{
"name": "trailing-spaces",
"message": "末尾のスペースを避けてください",
"searchPattern": "/ +$/gm",
"replace": "",
"searchScope": "all"
},
{
"name": "double-spaces",
"message": "ダブルスペースを避けてください",
"searchPattern": "/([^\\s>]) ([^\\s|])/g",
"replace": "$1 $2",
"searchScope": "text"
},
{
"name": "stuck-definition",
"message": "文字が定義の説明マーカーにくっついています",
"searchPattern": "/- :(\\w)/g",
"replace": "- : $1",
"searchScope": "text"
},
{
"name": "localhost-links",
"message": "リンクにlocalhostを使用しないでください",
"searchPattern": "/\\]\\(https?:\\/\\/localhost:\\d+\\//g",
"replace": "](/",
"searchScope": "text"
},
// zh-cnはルールを好みます
{
"name": "double-em-dash",
"message": "'--'を使用しないでください。代わりにダブルエムダッシュ(——)を使用してください",
"search": " -- ",
"replace": "——",
"searchScope": "text"
},
{
"name": "force-pronoun",
"message": "'您'の代わりに'你'を使用することを検討してください",
"searchPattern": "/您/g",
"searchScope": "text"
}
]
}
}
プロジェクトのルートディレクトリに.markdownlint-cli2.jsonc
ファイルを作成し、ルールを設定します:
{
"config": {
"extends": "./.markdownlint.jsonc"
},
"customRules": ["markdownlint-rule-search-replace"],
"ignores": [
"node_modules",
".git",
".github",
"**/conflicting/**",
"**/orphaned/**"
]
}
lint-staged のインストール#
npm install lint-staged --save-dev
.lintstagedrc.json
を設定します:
{
"content/**/*.md": "markdownlint-cli2 --fix"
}
husky のインストール#
npx husky-init && npm install
.husky/pre-commit
を設定します:
#!/usr/bin/env sh
. "$(dirname -- "$0")/_/husky.sh"
npx lint-staged
これにより、コードをコミットするたびに、content ディレクトリ内のすべての Markdown ファイルの文法エラーが自動的にチェックされ、修正されます。
AutoCorrect の導入#
盤古之白#
多くの中国語コミュニティでは、中英文の間に手動でスペースを追加することが一般的で、これを「盤古之白」と呼びます。この要求が合理的かどうか、またどのように満たすべきかは非常に価値のある話題ですが、この記事の範囲を超えています3。
ここでは、簡単に言うと、中英文の間にスペースを追加するのは、視覚的な区別を実現し、より美しく読みやすくするためです。理想的には、この「スペース」はレイアウトエンジンによって自動的に追加されるべきで、幅は全角スペースの 1/4(em)が望ましいです。しかし、数字のレイアウト環境は複雑で変化に富んでいるため、ほとんどの場合(最も一般的なウェブ環境を含む)、レイアウトエンジンがこの能力を持つことを期待することはできません。そのため、代わりに手動で半角スペースを挿入して、類似の効果を得ることになります(その幅は通常1/4 em に近いです)。
中英文の間に手動でスペースを追加したい場合、何か自動チェックや補完の方法はありますか?
答えはもちろん「あります」、しかも選択肢は一つではありません。
pangu.js#
その中で、最も有名なのはpangu.jsプロジェクトかもしれません。「なぜあなたたちはスペースを追加できないのですか?」というブラウザプラグインを使ったことがあるなら、pangu.js を使ったことがあるということです —— それは同じ作者によって作られ、pangu.js を基にしています。Hugo FixIt テーマも pangu.js を内蔵しており、ブログ記事の内容の中西混排を自動的に最適化します。
AutoCorrect#
もう一つの選択肢はAutoCorrectです。主にテキスト内容に焦点を当てた pangu.js とは異なり、AutoCorrect は Ruby 言語の中国語コミュニティから生まれたため、最初からプログラミングコードの中英混排シーンを考慮しています(このプロジェクトのテストファイルを参照できます)、汎用性が高いです。
pangu.js と AutoCorrect の比較:
プロジェクト | オンライン版 | VSCode 拡張 | コマンドラインツール |
---|---|---|---|
pangu.js | ❌ | ❌ | ✅ |
AutoCorrect | AutoCorrect Editor | AutoCorrect | ✅ |
- pangu.js には公式の VSCode プラグインはなく、最も多く使用されているのは xlthu が開発したPangu-Markdownというサードパーティの移植版です
- pangu.js のコマンドラインツールは Node.js に制限されており、npm を通じてインストールする必要があります:
npm i pangu
- AutoCorrect のコマンドラインツールは独立してインストールでき、Rust、Node.js などの他の言語バージョンもあります
私はブログ、VSCode、ブラウザプラグインの中で pangu.js を使用してきましたが、長い間、多くの問題に気づいてきました。その便利さは同時に「暴力」をもたらし、処理ルールが制御できないため、常に頭を悩ませてきました。そこでこの記事では AutoCorrect を pangu.js の代わりに使用することを試みました。実際、AutoCorrect の効果は確かにより良いです。
NPM で AutoCorrect を使用する#
autocorrect-node
をインストールします:
npm install autocorrect-node --save-dev
ショートカットコマンドを変更します:
{
"scripts": {
"fix:md": "autocorrect content --fix && markdownlint-cli2 \"content/**/*.md\" --fix",
"lint:md": "autocorrect content --lint && markdownlint-cli2 \"content/**/*.md\""
}
}
.lintstagedrc.json
を変更します:
{
"content/**/*.md": [
"autocorrect --fix",
"markdownlint-cli2 --fix"
]
}
新たに.autocorrectignore
を追加します:
# AutoCorrect Link ignore rules.
# https://github.com/huacnlee/autocorrect
#
# .gitignoreのように、このファイルはAutoCorrectにどのファイルをチェックする必要があるかを伝え、無視すべきファイルを指定します。
node_modules/
build/
public/
resources/
npx autocorrect init
を実行してデフォルトの.autocorrectrc
設定を取得し、次のルールを追加します:
textRules:
# `LC_ALL=C sort`コマンドでソート
一二三,四五六.七八九: 0
まとめ#
この記事では、markdownlint-cli2 と AutoCorrect の 2 つのツールを主に紹介しました。前者は Markdown の文法とスタイルをチェックするために使用され、後者は中英文の間の「盤古之白」を自動的に補完するために使用されます。これらの 2 つのツールはプロジェクトに統合でき、統一された規範とチーム協力を便利にします。
Footnotes#
-
一つが良ければ、二つはもっと良い [markdownlint-cli2 は markdownlint の新しいタイプのコマンドラインインターフェースです] ↩
-
markdownlint-rule-search-replaceは検索と置換パターンのカスタム markdownlint ルールです ↩
-
さらなる興味がある場合は、Zhihu のディスカッション「中英文混排時中文与英文之间是否要有空格?」や、W3C 標準草案《中文排版需求》§3.2.2、およびポッドキャスト「字談字畅」第 14 期をお聞きください。 ↩