handson-md-link-checker
Version:
高性能並列処理マークダウンリンクチェッカー - Markdown文書内の壊れたリンク(404/410エラー)を検出
421 lines (311 loc) • 13.4 kB
Markdown
※AIが書いてます。
高性能並列処理マークダウンリンクチェッカー - Markdown文書内の壊れたリンク(404/410エラー)を正確に検出
- ⚡ **高速並列処理**: Worker Threadsによる最大16並列処理
- 🎯 **正確な検出**: 404/410エラーのみを検出(アクセス制限は無視)
- 🌏 **日本語対応**: 日本語プレースホルダーを自動除外
- 📊 **詳細レポート**: JSON形式の詳細な結果出力
- 🔧 **GitHub Actions統合**: CI/CDパイプラインに簡単統合
- 📝 **複数形式対応**: Markdown、HTML、直接URL記載に対応
```bash
npm install -g handson-md-link-checker
npm install handson-md-link-checker
npx handson-md-link-checker ./docs
```
```bash
md-link-checker
md-link-checker ./docs
md-link-checker --ignore-github-auth ./docs
md-link-checker --explicit-links-only ./docs
md-link-checker ./article.md
md-link-checker --help
```
```
🔗 handson-md-link-checker v1.0.0
📁 Target: /path/to/docs
🔍 Starting link check...
Found 45 markdown files
📄 Collecting links from all files...
Found 234 total links (198 unique)
🚀 Checking links with optimized parallel processing...
Using 8 workers with 24 chunks (8 tasks per chunk)
✅ Link check completed
❌ Found 3 broken links:
- https://example.com/broken-page
Status: 404
File: docs/example.md:26
📝 Report saved to link-check-report.json
```
## プログラマティック使用方法
### 基本的な使用方法
```javascript
const LinkChecker = require('handson-md-link-checker');
const checker = new LinkChecker();
// ディレクトリをチェック
checker.run('./docs').then(() => {
console.log('チェック完了');
}).catch(error => {
console.error('エラー:', error);
});
```
```javascript
const LinkChecker = require('handson-md-link-checker');
const checker = new LinkChecker();
async function checkLinks() {
try {
const result = await checker.checkDirectory('./docs', true); // silentモード
console.log(`チェック結果:`);
console.log(`- ファイル数: ${result.totalFiles}`);
console.log(`- 総リンク数: ${result.totalLinks}`);
console.log(`- 壊れたリンク数: ${result.totalBrokenLinks}`);
if (!result.success) {
result.brokenLinks.forEach(link => {
console.log(`❌ ${link.url} (${link.status}) in ${link.file}:${link.line}`);
});
}
return result.success;
} catch (error) {
console.error('チェック中にエラーが発生しました:', error);
return false;
}
}
checkLinks();
```
```javascript
const { LinkChecker } = require('handson-md-link-checker');
const checker = new LinkChecker({
maxWorkers: 4, // 最大ワーカー数
timeout: 5000, // タイムアウト時間(ms)
batchSize: 50, // バッチサイズ
ignoreGithubAuth: true, // GitHub認証必要ページを除外
explicitLinksOnly: true, // 明示的リンクのみをチェック
excludePatterns: [ // 追加の除外パターン
/internal\.example\.com/,
/test\.localhost/
]
});
const result = await checker.checkDirectory('./docs');
```
```javascript
const LinkChecker = require('handson-md-link-checker');
const checker = new LinkChecker();
// 単一URLをチェック
const result = await checker.checkSingleUrl('https://example.com');
if (result) {
console.log(`壊れたリンク: ${result.url} (${result.status})`);
} else {
console.log('リンクは正常です');
}
```
```javascript
const LinkChecker = require('handson-md-link-checker');
const checker = new LinkChecker();
const urls = [
'https://example.com',
'https://github.com',
'https://broken-link.example.com'
];
const brokenLinks = await checker.checkUrls(urls, true);
console.log(`${brokenLinks.length} 個の壊れたリンクが見つかりました`);
```
- `404 Not Found` - ページが存在しない
- `410 Gone` - ページが永続的に削除された
- `DNS_ERROR` - ドメインが存在しない
- `CONNECTION_REFUSED` - サーバーがダウンしている
- `403 Forbidden` - アクセス制限(リンクは有効)
- `405 Method Not Allowed` - HEADリクエストが無効(リンクは有効)
- `429 Too Many Requests` - レート制限(一時的)
- `503 Service Unavailable` - サービス停止(一時的)
- タイムアウトエラー - ネットワークの一時的問題
- Markdownリンク: `[テキスト](https://example.com)`
- HTMLリンク: `<a href="https://example.com">テキスト</a>`
- HTML画像: `<img src="https://example.com/image.jpg">`
- 壊れたMarkdown: `[テキスト](url](url)` などの記載ミス
- 直接URL: `https://example.com`
- 技術文書の説明用URL: `API: \`https://api.example.com/v1/users\``
`--explicit-links-only` オプションを使用すると、暗示的リンクをスキップして明示的リンクのみをチェックします。これにより、技術文書でのAPI説明などで発生する偽陽性を回避できます。
以下のパターンは自動的に除外されます:
```javascript
// プレースホルダー
/example\\.com/, /localhost/, /your-[\\w-]+/
// 日本語プレースホルダー
/ユーザー名\\.github\\.io/, /<ココ>/, /○+/
// 英語圏ドメイン + 日本語(プレースホルダー)
/github\\.com\\/.*[ぁ-ゟァ-ヶー一-龯]/
// その他
/^mailto:/, /^tel:/, /^
```
このツールは、GitHub Actionsのカスタムアクションとして利用するのが最も簡単で推奨される方法です。
CI/CDパイプラインに組み込むことで、リポジトリ内のリンク切れを継続的にチェックできます。
外部のリポジトリからこのアクションを呼び出すには、ワークフローファイル(例: `.github/workflows/link-check.yml`)に以下のように記述します。
**基本的な使用例:**
```yaml
name: Check Markdown Links
on:
push:
branches:
- main
pull_request:
branches:
- main
workflow_dispatch:
jobs:
check-links:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Run Markdown Link Checker
id: link-check
uses: n0bisuke/linkchecker@main
with:
directory: './docs'
```
**入力 (`inputs`)**:
* `directory`: チェック対象のディレクトリまたはファイルパス。デフォルトは `.` (カレントディレクトリ)。
**出力 (`outputs`)**:
* `broken_links_count`: 見つかった壊れたリンクの数。この出力を後続のステップで利用できます。
リンクチェックを実行し、結果レポート (`link-check-report.json`) に変更があった場合に自動でリポジトリにコミットするワークフローの例です。
**注意点:**
* このワークフローがリポジトリに書き込む(`git push`する)ためには、ジョブに `permissions: contents: write` を設定する必要があります。
* コミットメッセージに `[skip ci]` を含めることで、このコミットによってワークフローが再度トリガーされる無限ループを防ぎます。
```yaml
name: Check Links and Commit Report
on:
push:
branches:
- main
workflow_dispatch:
jobs:
check-and-commit:
runs-on: ubuntu-latest
permissions:
contents: write
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Run Markdown Link Checker
id: link-check
uses: n0bisuke/linkchecker@main
with:
directory: '.'
- name: Commit and push if report changed
run: |
git config --global user.name 'github-actions[bot]'
git config --global user.email 'github-actions[bot]@users.noreply.github.com'
if [[ -n $(git status --porcelain link-check-report.json) ]]; then
echo "Report has changes. Committing and pushing..."
git add link-check-report.json
git commit -m "docs: Update link check report [skip ci]"
git push
else
echo "No changes to the report. Nothing to commit."
fi
```
アクションを使わずに、npmパッケージとして直接インストールして実行することも可能です。
```yaml
jobs:
check-links:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
- name: Install Link Checker
run: npm install -g handson-md-link-checker
- name: Check Links
run: md-link-checker ./docs
- name: Upload Report
if: always()
uses: actions/upload-artifact@v4
with:
name: link-check-report
path: link-check-report.json
```
**リンク切れを検出した場合、ワークフローは「失敗」します**
このアクションは、壊れたリンクを1つでも検出すると、意図的にワークフローを失敗させます(非ゼロの終了コードを返します)。これは、問題の存在を明確に知らせるための、CI/CDツールにおける一般的な挙動です。
もし、リンク切れが見つかってもワークフローを止めずに後続の処理を続けたい場合は、`continue-on-error` オプションを利用してください。
**continue-on-error の使用例:**
```yaml
- name: Run Markdown Link Checker
id: link-check
uses: n0bisuke/linkchecker@main
continue-on-error: true
with:
directory: '.'
```
| オプション | デフォルト | 説明 |
|-----------|-----------|------|
| `maxWorkers` | CPU数×4(最大16) | 並列ワーカー数 |
| `timeout` | 8000 | HTTPリクエストタイムアウト(ms) |
| `batchSize` | 100 | バッチ処理サイズ |
| `ignoreGithubAuth` | false | GitHub認証必要ページを除外 |
| `explicitLinksOnly` | false | 明示的リンクのみをチェック |
| `excludePatterns` | [内蔵パターン] | 追加の除外正規表現 |
- **1000+ URL**: 約30-45秒
- **メモリ効率**: ワーカースレッドによる制御された並列処理
- **ネットワーク負荷**: 適切なレート制限とリトライロジック
- **CI/CD最適化**: 最小限のリソース使用
1. **偽陽性が多い**
- 除外パターンを追加してください
- アクセス制限のあるサイトは自動的に無視されます
2. **処理が遅い**
- `maxWorkers`を調整してください
- `timeout`を短くしてください
3. **メモリ使用量が多い**
- `batchSize`を小さくしてください
- `maxWorkers`を減らしてください
MIT
Issues and Pull Requests are welcome!
Repository: https://github.com/n0bisuke/linkchecker
- 初回リリース
- Worker Threads による並列処理
- 日本語プレースホルダー除外機能
- GitHub Actions 統合
- プログラマティック API