Skip to content

程序化 API ​

English · 简体中文

当构建工具、编辑器、服务或测试需要把 CSS 作为数据获取,而不是启动命令时使用此 API。只有 CSS 字符串必填;配置、PostCSS 处理选项、浏览器目标和质量门禁均可省略。

编译一份样式表 ​

ts
import { compileAdaptiveCss } from 'postcss-adaptive-matrix'

const output = await compileAdaptiveCss('.card { padding: 24px }')
console.log(output.css)

output 包含 css、warnings、map、compatibility、gate 和完整 PostCSS result。未传 targets 时 compatibility 为 null;未传 failOn(或传 [])时 gate 为 null。语法和配置错误会拒绝 Promise。

结果归属 ​

每次编译都有独立的 AST、警告、兼容性报告和门禁结果。修改这些返回的集合不会重新配置编译器,也不会改变后续结果。但 css、map、诊断和门禁描述的是返回时的编译状态,不是 result.root 的实时视图。下游转换修改 AST 后,应通过 PostCSS 重新序列化并生成源码映射,再对修改后的输出重新运行所需审计或门禁。仅修改 AST 不会自动刷新 output.css 或之前的判定。

复用编译器 ​

ts
import { createAdaptiveCompiler } from 'postcss-adaptive-matrix'

const compile = createAdaptiveCompiler({ profiles: { app: 375 } })
const output = await compile(source, {
  process: { from: 'src/card.css', to: 'dist/card.css', map: { inline: false } },
  targets: { safari: 14 },
  failOn: ['warnings', 'compatibility'],
})

同一个编译器实例会保留转换缓存,但每次调用仍刷新按文件变化的画布与根字号。请求的目标、门禁、源码映射选项、syntax 钩子和对象形式的 stringifier 钩子会在异步处理前保存快照。保存的是函数引用,不会冻结回调内部的可变状态;上游映射对象也不会被深拷贝。

请把编译器配置视为该实例生命周期内固定的设置。创建时会保存 profile(包括流体边界和 query 对象)、媒体路由边界及根样式注入过滤数组。开发服务器加载新配置时,应创建新的编译器供后续请求使用;已经开始的调用继续使用旧实例。不要通过修改共享配置对象来重新配置运行中的编译器。

解析回调会保留函数本身,不会在创建时求值一次后固定。designWidth 或 rootValue 回调仍可按文件或重新构建返回不同标尺。回调闭包中的状态由调用方管理,并发请求重叠时也不例外。

修改 AST 后重新生成结果 ​

使用修改后的结果前,先序列化 AST,再审计新 CSS:

ts
import { compileAdaptiveCss, auditCompatibility } from 'postcss-adaptive-matrix'

const targets = { safari: 12 }
const output = await compileAdaptiveCss('.card { width: 40px }', {}, { targets })
output.result.root.walkDecls('width', (declaration) => {
  declaration.value = '40px'
})
const edited = output.result.root.toResult({ map: false })
const compatibility = auditCompatibility(edited.css, targets)
// 使用 edited.css 和 compatibility,而不是 output.css 或旧的审计。

此例有意禁用映射。如果流水线需要源码映射,请在生成新结果时传入对应路径与上游映射。构建策略也应重新计算;单独调用审计不会更新 output.gate。

门禁与映射 ​

分析会规范化 PostCSS AST 提供的完整转义 at-rule 名称,包括媒体条件和属性注册。这不会修复默认解析器已将名称拆入参数的源文本;支持范围取决于上游解析器或插件提供的 AST。

兼容性门禁必须传入 targets,不支持的特性或未知浏览器名都会失败。门禁失败仍会返回 CSS 和诊断,由调用方决定是否设置退出码。PostCSS 内联映射嵌入 CSS,因此 map 为 undefined;外部映射返回 map 对象。process.map.prev 可串接上游映射。

此 API 门禁覆盖警告和兼容性,不包含 CLI 的断点接缝分析;若接缝问题也属于构建策略,请使用 CLI JSON 报告。

分析器检查数学表达式和裸视口单位值,包括未设置 fluid 边界的画布输出。这是语法启发式判断,不是编译来源证明:手写流式表达式也可能产生诊断;纯固定像素之间的变化仍不报告。

诊断长度求值对嵌套表达式及一元操作设有 128 层递归下降预算,超出后返回未知,避免 JavaScript 调用栈溢出。这限制的是分析而非 CSS 编译;没有诊断不代表此类值已获验证。

连续性分析在每个已知断点上下各 0.05 CSS 像素处采样,以容纳常见的 0.02px 间隙。这不是精确的极限计算:更窄的中间区间可能被采样跨过。分析结果是需要调查的诊断证据,不是所有视口宽度都连续的证明。

也可以在进程内把导出的分析器与编译结果组合使用。转换和分析必须使用相同的根字号(默认值为 16)。动态根字号应按文件求值一次,再把数值传给两者,不要重复调用可能变化的回调。

ts
import { compileAdaptiveCss, findContinuityIssues } from 'postcss-adaptive-matrix'

const rootValue = 20
const output = await compileAdaptiveCss(source, { rootValue })
const seams = findContinuityIssues(output.result.root, rootValue)
const accepted = output.gate?.passed !== false && seams.length === 0

分析器接受 Root 或 PostCSS Document。Document 内各份样式表独立分析,再按 Root 顺序汇总;规则和自定义属性不会跨 Root 混用。如果需要把结果对应到具体文件,或为不同文件使用不同根字号,请逐个 Root 调用。

这是一项静态检查,用于发现可计算的视口断点处长度反向缩小,不是布局或视觉测试。无法解析的值和条件会被跳过;报告为空不能证明所有响应式布局都正确。根字号可省略,默认值为 16;显式传入时必须是正有限数,否则分析器抛出 RangeError。

包内包含 ESM 与 CommonJS 类型声明。可直接导入 AdaptiveCompileOptions、AdaptiveCompileResult、AdaptiveCompileGate 和 AdaptiveCompileGateCategory,无需重复声明结果契约。

纯服务端 TypeScript 项目 ​

主入口 postcss-adaptive-matrix 支持 NodeNext 模块解析及 lib: ["ES2022"],无需 DOM 类型库。消费者测试覆盖开启 exactOptionalPropertyTypes 的 ESM 和 CommonJS。独立入口 postcss-adaptive-matrix/runtime 描述 Window、HTMLElement 等浏览器对象,使用它的浏览器项目需要 DOM 类型。仅在 Node 服务中编译 CSS 时,不必导入该辅助入口。

异常与恢复 ​

连续性诊断的 token 替换按每次解析设限:最多 4,096 次替换调用、累计 1,048,576 个输入 UTF-16 码元及 65,536 个输出码元。超限返回未知并跳过该比较;下一次解析重新计数。这些是诊断限制,不是 CSS 编译限制或进程内存保证。

CSS 语法错误、非法请求或配置回调抛错会拒绝编译 Promise;诊断门禁失败则不会。因此,在构建接收输出之前,应检查 output.gate?.passed === false。警告和 PostCSS 结果归属各次调用,同一个编译器中的失败请求或警告不会污染后续请求。即使回调曾经抛错,下一次编译也会重新读取动态画布与根字号。

ts
const compile = createAdaptiveCompiler()
try {
  const output = await compile('.card { padding: 24px }', { failOn: 'warnings' })
  if (output.gate?.passed === false) {
    console.error('CSS 质量门禁未通过', output.warnings.map((warning) => warning.text))
  } else {
    console.log(output.css)
  }
} catch (error) {
  console.error('CSS 编译失败', error instanceof Error ? error.message : '未知错误')
}

在服务端使用时,详细诊断应保留在可信日志中:源码路径和原始 CSS 可能含敏感信息。向不可信客户端返回适当的公开错误,不要直接暴露原始异常。

基于 MIT 协议发布