ナビゲーション

構文

抽出

静的な候補の抽出、ソースの境界、分類、共有ソースの所属。

このページの内容

抽出はアプリケーションを実行せずに、ソースからクラス名の候補を見つけます。潜在クラスとも呼ぶこれらの候補は、照合と候補ポリシーへの入力です。文字列が見つかっても、ルールを生成すること、CSS 値が有効であること、特定のブラウザーで動くことは保証されません。

このページでは、ソースの境界、静的抽出、候補の分類、ソースの所属を定義します。発見できるクラスの書き方とスタイルがない場合の診断は、クラス名のスキャンで説明しています。パスとクラスパターンの文法はスキャンのディレクティブが定義します。

完全な静的文字列

抽出器はソース言語の構造を使います。JavaScript や TypeScript の文字列は、className の外でも候補になります。表示用のテキストとしてコンポーネントに渡したクラスも、発見されることがあります。スキャナーは、実行される分岐や、ランタイムに関数が返す値を推論しません。

ソースの形式抽出できる内容
HTML class="p-md shadow-md"両方の完全なクラス
JSX className="p-md"完全なクラス
error ? 'bg-red-60' : 'bg-green-60'両方の静的な分岐
{ compact: 'p-sm', roomy: 'p-lg' }オブジェクト内の完全な値
完全な静的クラス部分を含むテンプレートリテラルその完全な部分
'bg-' + tone、またはクラス名の途中にあるテンプレート補間bg-red-60 などの完成形は推論しない
ランタイムに API からだけ返されるクラス抽出するソース文字列がない

たとえば、次のソースは 2 つの色と、固定の padding と角丸を含みます。オブジェクト内の完全なクラスを発見するために、tone の補間を評価する必要はありません。

const tones = {  neutral: 'bg-surface-base fg-text-neutral',  destructive: 'bg-red-70 fg-white'}const className = `px-md r-md ${tones.destructive}`

抽出されるクラスは bg-surface-base、fg-text-neutral、bg-red-70、fg-white、px-md、r-md です。この例が destructive の分岐を選んでいても、スキャナーは出力をその分岐だけに絞りません。

候補の分類

抽出後は、有効な manifest とスタイルシートの登録内容が候補の役割を決めます。未知の通常のアプリケーションクラスが、自動的に Master CSS のエラーになるわけではありません。

候補結果
p-md などの登録済みプリセットユーティリティ一致するユーティリティルールと依存関係を生成
プロジェクト定義の @utility クラスプロジェクトのコンパイル済み manifest に登録されたルールを生成
.card などの登録済みネイティブクラスネイティブの使用状況を記録し、新しいユーティリティは生成しない
定義に一致しないアプリケーションクラスMaster が生成するルールはない
形式が不正な Master クラスルールはなく、検査で構文診断を報告できる
一致したが CSS 値が無効または未知のクラスCSS を出力する場合があり、照合だけでは値の有効性やブラウザー対応は証明できない
<article class="card p-md shadow-md">Release notes</article>

ここでは p-md と shadow-md をプリセットで解決します。card がネイティブルールを保持するのは、プロジェクトが実際にそのルールを提供し、プルーニングのポリシーが使用状況を考慮する場合だけです。ネイティブスタイルシートは既定で保持され、スキャン自体がプルーニングを有効にすることはありません。

生成された CSS
@layer theme {  :root,  :host {    --spacing-md: 1rem  }  :root,  :host {    --shadow-md: 0 0 0 1px light-dark(oklch(0% 0 none / .05), oklch(100% 0 none / .06)), 0 1px 1px -.5px light-dark(oklch(0% 0 none / .045), oklch(0% 0 none / .3)), 0 2px 2px -1px light-dark(oklch(0% 0 none / .04), oklch(0% 0 none / .26)), 0 4px 4px -2px light-dark(oklch(0% 0 none / .04), oklch(0% 0 none / .24)), 0 8px 8px -4px light-dark(oklch(0% 0 none / .045), oklch(0% 0 none / .26))  }}@layer utilities {  .shadow-md {    box-shadow: var(--shadow-md)  }  .p-md {    padding: var(--spacing-md)  }}

コンパイラーによる照合、CSS 構文の検証、CSS 値の検証、ブラウザー対応は別の確認事項です。クラスの検査で区別してください。一致したクラスにも、ブラウザーのカスケードと計算値の規則が適用されます。

ソースの境界

ビルド統合と CLI は、HTML、JavaScript、TypeScript、JSX、TSX、対応フレームワークのソース、Markdown、MDX、PHP など、一般的なプロジェクトのソースファイルを探索します。通常のアプリケーションファイルに広範な @source を書く必要はありません。

自動探索は、プロジェクトと上位ワークスペースの .gitignore に従い、Git のグローバルな除外設定は使いません。依存パッケージ、宣言ファイル、バイナリ、VCS データ、生成出力は除外されます。Master の出力と現在のバンドラーの出力はスキャン入力にならず、Next.js では設定された distDir を使います。

ディレクティブ探索への影響
@source自動探索や .gitignore で除外されたファイルも含め、追加のパスを明示的に対象にする
@source notパスを除外し、包含の指定より優先する

これらの例外は、共有ワークスペースのソース、外部コンテンツ、範囲を限定したプルーニングのルートに使います。相対パスの規則と対応形式はスキャンのディレクティブを参照してください。

フレームワーク統合は、コンパイル済みの表示用文字列を再スキャンするより、元の MDX、Vue、Svelte ソースを優先します。抽出器の言語種別は重要です。意図的なプレーンテキスト入力には kind: 'raw' を使えますが、解析に失敗したソースのフォールバックではありません。

Markdown と MDX

Markdown と MDX の抽出は構文木を使います。実際の HTML/JSX、ESM、式は対象になりますが、文章、インラインコード、通常のコードフェンス、frontmatter は対象外です。そのため、クラスを示す文書のコードフェンスが暗黙に実行例になることはありません。

ホストは parentSource を使って実行例を仮想ソースとして登録するか、その有限のクラスを明示的にセーフリストへ追加できます。仮想入力は実行内容の所属を明確にし、実際の例のソースと言語種別はホストが提供します。

不正なソースは SOURCE_PARSE_ERROR を報告します。開発時は直前に成功した結果を保持し、本番ビルドは失敗します。解析や読み込みの失敗は、空のソースへの更新とは異なります。

ソース位置

抽出は文字列だけでなく、候補の出現箇所も報告できます。元の UTF-16 範囲、抽出器、内容種別、owner、対象に含めた理由や除外した理由です。エンコードされた属性でも元のソース範囲を保ちます。完全な URL リテラルは除外しますが、未知のネイティブ宣言は後の検証用に候補として残ることがあります。

ソースの所属

スキャナーセッションが追跡するのは現在の各ソースから得た結果であり、過去に見つけたすべてのクラスではありません。ソースを更新すると、そのソースの結果を置き換えます。1 つのソースを削除しても、ほかの現在のソースやセーフリストが保持するクラスは削除しません。

1 つのソースを削除しても共有ルールは消えない

定義とポリシーが変わらなければ、ページ A を削除してもページ B の p-md への参照は残ります。生成 CSS が同じままでも、ソースの所属は変わります。

テキストによる説明
  1. 最初は page-a.tsx と page-b.tsx の両方が、完全な p-md クラスを含みます。
  2. page-a.tsx を削除すると、そのソースの結果だけが削除されます。page-b.tsx からの有効なつながりが、共有ユーティリティと依存する --spacing-md を保持します。
  3. 現在のソースにもセーフリストにも保持されなくなった場合、ユーティリティを除去できます。ソースの更新は結果を置き換えるもので、過去のクラスを蓄積しません。
  4. 図は保持するユーティリティ宣言を示します。テーマの依存関係は別途説明し、完全なスタイルシートとして再掲するものではありません。

これらのセッション操作は、@master/css-tooling/scanner/node の MasterCSSScanner から使えます。ソースの所属を扱う操作であり、統合の利用者は通常、ビルドプラグインに実行を任せます。

操作所属への影響
collectCandidates抽出のみを行い、ソースの結果を保持しない
scanSource空文字列も含め、1 つのソースの内容を置き換える
removeSourceそのソースと仮想の子孫ソースを削除
reconcileSources1 つの owner の次の完全なソース集合を指定
registerNativeClassesスタイルシートのソースにネイティブクラスの識別情報を登録
removeOwnerその owner のソースとネイティブ登録を削除
await scanner.scanSource('page.mdx', content, { owner: 'pages' })await scanner.scanSource('page.mdx#live', html, {  owner: 'pages', parentSource: 'page.mdx', kind: 'html'})scanner.removeSource('page.mdx', { owner: 'pages' })

page.mdx を削除すると、その仮想の例も削除されます。別の owner の参照は独立しています。再照合では、その owner に渡した入力だけを保持します。明示的に保持した仮想入力は、親ソースが外部で管理されていても、その集合に残ります。

changed は生成出力やプルーニング入力の変更を示します。sourceChanged は由来だけの更新も捉えます。2 つ目のソースが CSS を変えずに所属を追加する場合などです。sources ビューは、空の入力や仮想関係も含む、現在の成功したソース集合を公開します。

ソースの更新はそのソースの結果を置き換える

同じファイル名は 1 つのソースを表します。この例では、古いクラスを保持する別のソースやセーフリストはありません。

テキストによる説明
  1. 最初の card.html は p-sm と r-md を提供します。次の内容は p-lg と r-md を提供します。
  2. 同じソースを再スキャンすると、その結果を置き換えます。r-md は残り、p-lg が追加され、p-sm は保持されなくなります。
  3. 別の現在のソースやセーフリストが、引き続き p-sm を保持する場合もあります。ソースの更新は、過去に見つけた全クラスを蓄積しません。

ランタイムの値

クラス名を変えずに値を変えられます。完全なネイティブ宣言クラスで、マークアップやスクリプトが指定するカスタムプロパティを参照できます。

<h1 class="(font-size:var(--headline-size))" style="--headline-size: 2rem">Launch notes</h1>

スキャナーには 1 つの完全なクラスが見えます。--headline-size を更新すると、新しいユーティリティルールなしでブラウザーの値が変わります。変化する値の実例を参照してください。

同じ仕様は (width:var(--progress)) にも適用されます。スクリプトから element.style.setProperty('--progress', '40%') を呼び出しても、クラスはそのままです。

クラス名自体が起動後に初めて現れる場合、静的ビルドでは発見できません。範囲を限定したセーフリストを用意するか、ランタイムまたはプログレッシブレンダリングを使います。

候補ポリシー

ディレクティブ用途制限
@safelistCMS の状態やウィジェットのクラスなど、範囲を限定した外部クラスを保持照合を省略せず、未定義のユーティリティも定義しない
@blocklist誤検出した候補による CSS の生成を防ぐソースを書き換えず、任意のネイティブ CSS も削除しない

クラスパターン、優先順位、ネイティブの使用状況はスキャンのディレクティブを参照してください。ネイティブルールとキーフレームの除去はネイティブ CSS のプルーニングを参照してください。候補の探索とネイティブの保持は別のポリシーです。

スタイルがない場合は、記述構文を変える前に、完全なクラス、ファイルの探索境界、候補ポリシーを確認します。ガイドの診断チェックリストでは、実際の文脈で確認する手順を説明しています。