ソースマップのビジュアライザをテスト基盤に追加

tailwindlabs/tailwindcss

ソースマップの検証をテキストの座標比較から、入出力を並べたビジュアル表示に切り替えることで、ソースマップのデバッグとスナップショットテストの精度検証が大幅に行いやすくなりました。

背景

ソースマップのテストが、人間にとって解読困難な座標の羅列になっていたことが今回の変更のきっかけです。関連PR #19996 において @variant 処理に関するソースマップテストが追加されましたが、生成された座標(例: 3:0-3:5 <- 1:2-1:7)を目視で確認するには、入力ファイルと出力ファイルを頭の中で照らし合わせる必要がありました。

座標を並べるだけでは「正しい座標が記録されているか」を直感的に判断できず、レビューコストが高い状態でした。特にコンパイル後のCSSが長くなるほど、どの行のどの文字に対応しているかを追うのは困難になります。

技術的な変更

visualize-source-map.ts という新しいモジュールが追加され、既存のテストヘルパー formattedMappings() がこのモジュールに置き換えられました。

変更前は source-map.test.ts 内に定義された formattedMappings() 関数が SourceMapConsumer を直接呼び出し、各マッピングを dst <- src 形式の文字列として返していました。

変更前:

function formattedMappings(map: RawSourceMap) {
  const smc = new SourceMapConsumer(map)
  const annotations: Record<number, { ... }> = {}

  smc.eachMapping((mapping) => {
    let annotation = (annotations[mapping.generatedLine] = ...)
    // ...
  })
  // returns string[] like ["3:0-3:5 <- 1:2-1:7"]
}

変更後:

import { visualizeSourceMap } from './visualize-source-map'

// ...
let annotations = visualizeSourceMap(map, css)

新しい visualize-source-map.ts は2つの公開関数を提供します。

  • visualizeSourceMap(map, css): RawSourceMap を受け取り、生成されたCSSと元のソースを並べた文字列を返す。ソースマップの各マッピングポイントが ABC... といった記号でハイライトされる
  • visualizeSourceMapRanges(sources, css, ranges): SourceMapVisualizationRange[] を受け取り、任意の範囲情報を同じ形式で可視化する

内部定数として COLUMN_WIDTH = 100CONTEXT_LINES = 3 が定義されており、表示幅と前後の文脈行数を制御しています。マッピングが複数のファイルにわたる場合は、それぞれのソースファイルも並べて表示されます。

translation-map.test.ts も同様に更新されており、従来の文字列配列を返す format() 関数が SourceMapVisualizationRange[] を構築して visualizeSourceMapRanges() に渡す形式に変わっています。

import { visualizeSourceMapRanges, type SourceMapVisualizationRange } from './visualize-source-map'

function format(node: AstNode) {
  let ranges: SourceMapVisualizationRange[] = []

  for (let [oStart, oEnd, gStart, gEnd] of translate(node)) {
    ranges.push({
      original: {
        source: 'input.css',
        start: [oStart.line, oStart.column],
        end: [oEnd.line, oEnd.column],
      },
      generated: gStart && gEnd
        ? { start: [gStart.line, gStart.column], end: [gEnd.line, gEnd.column] }
        : null,
    })
  }

  return visualizeSourceMapRanges({ 'input.css': input }, css, ranges)
}

また、ビジュアライザ自体の動作を保証する visualize-source-map.test.ts も新規追加されており、単一行・複数行・複数ファイルにまたがるケースがスナップショットテストとして記録されています。

設計判断

スナップショットテストとの組み合わせを前提とした設計が採用されています。ビジュアライザの出力は人間が読みやすいテキスト形式であるため、Vitestのインラインスナップショット(toMatchInlineSnapshot)と組み合わせることで、ソースマップの変更がテストのdiffとして即座に視覚的に確認できます。

記号(ABC...)によるハイライト方式を採用することで、同一行内の複数マッピングポイントを区別できます。座標の数値を直接比較する方式では発見しにくかった「同じ行の別の列を指している」ケースも、記号の対応関係として明示されます。

PR本文にも記載されているとおり、この変更はテスト基盤のみを対象としており、プロダクションのソースコードには一切変更を加えていませんvisualize-source-map.ts はテスト用途のモジュールとして分離されているため、バンドルサイズや実行時の動作への影響はありません。

まとめ

ソースマップのテストインフラを座標比較からビジュアル表示へ刷新したことで、マッピングの正確性をスナップショットdiffとして確認できる体制が整いました。ソースマップに変更が生じた際のレビューコストが下がり、@variant 処理の複雑化に伴うマッピング検証の精度向上に貢献します。

記事メタデータ

Generated by:
Claude Sonnet 4.6 for DiffDaily
LLM Trace:
0e9fccf5

この記事はAIによって自動生成されています。内容の正確性については、必ずソースコードやPRを確認してください。

品質レビュー結果

Review Status:
承認済み
Review Count:
1回
Reviewed by:
Gemini 2.5 Pro for DiffDaily

Review Criteria:

記事構成 ✓ PASS

Title, Context, Technical Detailの存在と明確さ

リード文(総論)→背景・技術詳細・設計判断(各論)→まとめ(結論)という理想的な構成です。各セクションの役割が明確で、読者が変更の文脈と内容をスムーズに理解できます。

カスタムMarkdown構文 ✓ PASS

シンタックスハイライト・GitHubリンク記法の正確性

ファイル名付きのシンタックスハイライト(```言語:ファイルパス)およびPR番号のリンク記法([#123](URL))が、ガイドラインに沿って正しく使用されています。

対象読者への適合性 ✓ PASS

エンジニア向けの適切な技術レベルと表現

「ソースマップ」や「スナップショットテスト」などの用語を前提としており、専門知識を持つエンジニアという対象読者に適した技術レベルと表現で書かれています。

パラグラフ・ライティング ✓ PASS

トピックセンテンス・1段落1トピック・段落長

各セクションが総論→各論で構成され、各パラグラフがトピックセンテンスで始まるなど、パラグラフ・ライティングの原則が徹底されています。非常に読みやすい構造です。

Diff内容との照合 ✓ PASS

コードブロックとDiff内容の一致

記事内で引用されているコードブロック(変更前・変更後)は、提供されたDiff情報と正確に一致しています。ファイルパスの指定も正確です。

技術用語の正確性 ✓ PASS

技術用語の正確な使用

「RawSourceMap」「SourceMapVisualizationRange」など、PRやコード内で使用されている技術用語を正確に使用できています。

説明の技術的正確性 ✓ PASS

技術的主張の正確性と論理性

「visualize-source-map.tsの追加」「formattedMappings()からの置き換え」といった説明は、すべてDiff情報によって裏付けられており、技術的に正確です。

事実の突合 ✓ PASS

PR情報による主張の裏付け(ハルシネーション検出)

記事内のすべての主張(関連PR#19996との関係、スナップショットテストとの連携、テスト基盤のみの変更など)は、PRのDescriptionで完全に裏付けられており、ハルシネーションは検出されませんでした。

数値・固有名詞の確認 ✓ PASS

PR番号・コミットID・バージョン等の正確性

PR番号(#19997, #19996)や、コード内の定数(COLUMN_WIDTH = 100, CONTEXT_LINES = 3)などが正確に記載されています。

タイトル・説明との一致 ✓ PASS

記事タイトル・説明とPR内容の一致

記事のタイトル「ソースマップのビジュアライザをテスト基盤に追加」は、PRのタイトル「Add source map visualization for tests」の内容を正確に反映しています。

外部知識の正確性 ✓ PASS

PRに記載のない外部知識(LTS、サポート状況など)の不使用

PR情報に記載のないバージョン情報やリリース予定など、外部知識の持ち込みは見られませんでした。すべての情報が提供された資料に基づいています。

時間表現の正確性 ✓ PASS

時間表現がPR情報と一致しているか

時間的な前後関係や状態(変更前・変更後)の記述は正確であり、PR情報との矛盾はありません。