zfb
GitHub リポジトリ

検索したい単語を入力

いつでも検索バーを開ける

リンク検証

ビルド時に内部リンクとアンカーフラグメントを検証し、壊れた参照が本番環境に届く前に検出する。

linkValidation 機能は、ビルド内のすべての <a href> と <img src> をたどり、内部リンクとアンカーフラグメントが正しく解決されるかを検証します。壊れたリンクはビルド診断を生成します — デフォルトでは警告、failOnBroken: true を設定するとエラーになります。

linkValidation ブロック自体に手を入れずに CI をリンク整合性でゲートしたい場合(プリセットがそのブロックを所有しているときなど)は、トップレベルの strictBrokenLinks 設定フィールドか zfb build --strict-broken を使います。後述の strict モードを参照してください。

外部 URL(http://、https://、mailto: など)はデフォルトで黙ってスキップされます。

有効化

// zfb.config.ts
import { defineConfig } from "zfb/config";

export default defineConfig({
  markdown: {
    features: {
      linkValidation: {},   // デフォルト: 警告のみ、外部 URL はスキップ
    },
  },
});

壊れたリンクでビルドを失敗させるには:

linkValidation: { failOnBroken: true },

検証される対象

  • 素のアンカーフラグメント — #section-id は、現在のファイル内の既知のアンカーに一致しなければなりません。

  • アンカーなしのファイルリンク — ./other.md は、プロジェクトルート以下に存在するファイルへ解決されなければなりません。

  • アンカー付きのファイルリンク — ./other.md#section-id は、解決可能なファイルと、そのファイル内の一致するアンカーの両方を必要とします。

既知のアンカーには HeadingLinksPlugin が生成する見出し ID、<span id="note" /> などの組み込み JSX 要素のリテラル id 属性、<a> のリテラル name 属性が含まれます。下記の anchorComponents で、DOM ID を出力するコンポーネントの prop も宣言できます。ファイル横断のレジストリはビルド中に構築され、トランスクルージョン経由の見出しとアンカーも含みます。

スキップされる対象

  • http://、https://、mailto:、tel: で始まる外部 URL。

  • BuildContext なしで描画されたファイル内のリンク(例: コンテキストを伴わない単純なインメモリのパイプライン呼び出し)。

  • 対象ファイルがバンドラーの走査対象ディレクトリ(pages、コンテンツコレクション、components、layouts)の外にある、ファイル横断のアンカーリンク。これらは存在チェックのみの検証に格下げされます。ファイルはディスク上に存在しなければなりませんが、フラグメントはチェックされません。対象ファイルがビルドに含まれている場合は、フラグメントも常に検証されます。

オプション

  • failOnBroken — true のとき、壊れたリンクは Error 診断を出力します(ビルドが失敗します)。デフォルト: false(警告のみ)。このブロックの外から有効にすることもできます — strict モードを参照してください。

  • anchorComponents — MDX JSX コンポーネントの正確な名前から、DOM ID として出力される prop への任意のマップです。例:

linkValidation: {
  anchorComponents: { EvidenceAnchor: "id", "UI.Anchor": "anchorId" },
}

これにより <EvidenceAnchor id="part-a" /> と <UI.Anchor anchorId="part-b" /> は、ネストした JSX や表の中でも #part-a と #part-b を登録します。名前は大文字と小文字を区別し、MDX JSX パーサーが解釈する表記と完全に一致する必要があります。対応する Unicode 名も使えます。この宣言は、コンポーネントがその prop を DOM の id として出力するというプロジェクト側の保証です。登録されるのは空でない文字列リテラルだけです。式(id={value})、スプレッド({...props})、空の値、未宣言のコンポーネントの prop は対象外です。プリセット間では最初の宣言が優先され、プロジェクト設定はプリセットの宣言を上書きします。存在しないフラグメントは従来どおり診断され、failOnBroken と strict モードが適用されます。

strict モード

failOnBroken は linkValidation ブロックの中にありますが、そのブロックが常に自分の手中にあるとは限りません。プリセットがそのブロックを所有し、failOnBroken: false を焼き込んでいることもあります。そのため zfb は、これを上書きするトップレベルのスイッチを、設定フィールドと zfb build のフラグの両方として提供しています。

// zfb.config.ts
import { defineConfig } from "zfb/config";

export default defineConfig({
  strictBrokenLinks: true,
});
zfb build --strict-broken      # このビルドを壊れたリンクで失敗させる
zfb build --no-strict-broken   # このビルドは失敗させない

設定リファレンスの strictBrokenLinks と、CLI リファレンスの zfb build のフラグを参照してください。

リンク検証を強制的に有効化する

linkValidation の設定がまったくないプロジェクトで strict モードを有効にしても、黙って何も起きないということはありません。デフォルト設定でリンク検証を有効にし、かつ壊れたリンクでビルドを失敗させます。「strict broken links」という名前のスイッチが素のプロジェクトで静かに何もしないのは落とし穴でしかないため、常に効果を持つようになっています。

linkValidation がすでに設定されている場合は、上書きされるのは failOnBroken だけです。そのブロック内の他のオプションも、markdown および markdown.features 配下の兄弟設定も、いっさい変更されません。

優先順位

優先度の高い順に 3 段階です。

  1. 明示的な CLI フラグ — --strict-broken または --no-strict-broken。この 2 つは排他で、同時に渡すとエラーになります。

  2. strictBrokenLinks 設定フィールド。

  3. デフォルトの false。

フラグを省略することと --no-strict-broken を渡すことは同じではありません。省略した場合は設定値にフォールスルーしますが、--no-strict-broken は設定値を明示的に上書きします。これは minifyHtml と --minify-html / --no-minify-html が使っているのと同じ 3 値の仕組みです。

build 専用 — zfb dev は影響を受けない

strict モードは zfb build の内部で解決され、そのコマンドにのみ適用されます。zfb dev が strict オーバーレイを見ることはなく、リンク検証はあくまで自分で書いた linkValidation 設定どおりに振る舞います。linkValidation ブロックがないプロジェクトは、strictBrokenLinks: true を設定していても dev ではリンク検証がまったく行われませんし、自分で failOnBroken: true を設定しているプロジェクトは、従来どおり dev でもその severity を保ちます。狙いは CI をゲートすることであって、開発のインナーループを変えることではありません。

--no-strict-broken がしないこと

--no-strict-broken が無効にするのは、トップレベルの strict オーバーレイだけです。linkValidation ブロック側で独立に、かつ明示的に failOnBroken: true が設定されている場合、それを引き下げることはありません。そちらはより限定的な別のつまみであり、このフラグにかかわらず有効なままです。

markdown: { features: { linkValidation: { failOnBroken: true } } },

このように設定されたプロジェクトは、zfb build --no-strict-broken を付けても壊れたリンクで失敗します。緩めたい場合は failOnBroken 自体を変更してください。

zfb には、壊れたリンクを扱う仕組みがもう 1 つ、完全に独立して存在します。resolveMarkdownLinks の onBrokenLinks オプションで、リゾルバが書き換えられなかった .md / .mdx リンクを報告するものです。この 2 つは統合されていませんし、統合する予定もありません。

この機能resolveMarkdownLinks
設定パスmarkdown.features.linkValidationresolveMarkdownLinks
severity のつまみfailOnBroken、および strictBrokenLinks / --strict-brokenonBrokenLinks: "warn" | "error" | "ignore"
診断の文言broken link: …broken markdown link in {file}: … could not be resolved…

strictBrokenLinks と --strict-broken は onBrokenLinks には影響しません。解決できないマークダウンリンクでもビルドを失敗させたい場合は、あわせて onBrokenLinks: "error" を設定してください。

診断フォーマット

診断は MarkdownDiagnostic の共有 BrokenLink バリアントに従います:

  • severity — failOnBroken に応じて Warning または Error。

  • url — 著者が記述したままの生の href または src の値。

  • location.path — 壊れたリンクを含むソースファイルの絶対パス。

980 での挙動変更

issue #980 以前は、ファイル横断のアンカーフラグメント(./other.md#section)は存在のみが検証され、フラグメント自体は対象ファイルの見出しに対してチェックされていませんでした。#980 以降は、ビルド内のすべてのファイルについて、コンパイル後にフラグメントが検証されます。failOnBroken: true のもとで壊れたファイル横断アンカーを含みながら以前は通過していたビルドは、今後は失敗します。

フェーズ

2 つのフェーズで実行されます:

  1. コンパイルごとの hast フェーズ — LinkValidationPlugin が同一ファイル内のアンカー(#section-id)を即座に検証し、コンパイル後に解決するファイル横断フラグメントの候補を記録します。

  2. コンパイル後のバンドラーパス — すべてのファイルがコンパイルされた後、バンドラーは各ファイルの記録済み見出しから見出しマップを構築し、記録済みのファイル横断候補をそれぞれ検証します。検出結果は、他の Markdown 診断と同じ severity ゲートを通じて振り分けられます。

Revision History

作成更新