网站导航

语法

提取

静态候选项提取、源文件边界、分类和共享源文件的归属。

本页内容

提取会在不运行应用的情况下,从源文件中找出可能的类名。这些候选项也称为潜在类,是匹配和候选项策略的输入。找到字符串,不代表它一定生成规则、具有合法 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 返回的类没有可提取的源字符串

例如,下列源文件包含两种颜色以及固定的内边距和圆角。无需对 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 全局忽略设置。依赖包、声明文件、二进制文件、版本控制数据和生成输出会被排除。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 字面量会被排除;未知的原生声明则可能保留为候选项,供后续验证。

源文件归属

扫描器会话跟踪的是当前各源提供的结果,不是曾经遇到的所有类。更新源会替换它原本提供的结果。移除一个源时,其他当前源或安全列表仍保留的类不会被移除。

移除一个源,不会移除仍在共享的规则

定义和策略不变时,移除页面 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替换一个源的内容,包括空字符串
removeSource移除该源及其虚拟后代源
reconcileSources提供一个 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 也涵盖仅来源信息改变的更新:第二个源可以添加归属,而不改变 CSS。sources 视图呈现当前成功的源集合,包括空输入与虚拟关系。

更新源会替换它原本提供的结果

重复的文件名代表同一个源。此例没有其他源或安全列表保留旧类。

文字说明
  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>

扫描器只会看到一个完整类。更新 --headline-size 会改变浏览器中的值,不需要新的工具类规则。见可变值示例。

相同契约也适用于 (width:var(--progress)):脚本可以调用 element.style.setProperty('--progress', '40%'),而类保持不变。

如果类名本身在启动后才首次出现,静态构建就无法发现它。请提供有限范围的安全列表,或使用运行时或渐进式渲染。

候选项策略

指令用途限制
@safelist保留有限范围的外部类,例如 CMS 状态或小部件类不会绕过匹配,也不会定义缺失的工具类
@blocklist防止误判的候选项生成 CSS不会改写源文件,也不会移除任意原生 CSS

类模式、优先级和原生使用情况,见扫描指令。移除原生规则与关键帧的方法,见原生 CSS 裁剪。候选项发现与原生保留是独立策略。

样式缺失时,请先检查完整类、文件的发现边界和候选项策略,再修改编写语法。指南诊断清单会结合实际场景带你完成这些检查。