☰
Imba 项目中的 CSS 值定义语法:解读 MDN CSS 数据集的 syntaxes.json
2026/10/8 7:54:32 网站建设 项目流程
  • 编程语言
  • 编译器
  • 语言运行时

【免费下载链接】imba

🐤 The friendly full-stack language

项目地址:https://gitcode.com/gh_mirrors/im/imba
点击查看免费下载

CSS 值定义语法(CSS value definition syntax)是描述 CSS 属性“合法取值”的正式文法。在 Imba 仓库中,apps/imba.io/scripts/mdn-data/css/syntaxes.json收录了 MDN 数据集中数百条这样的语法定义,它们与属性定义、类型定义相互引用,共同构成了 Imba 样式系统自动生成类型声明(styles.generated.d.ts)的数据底座。读完本文,你将掌握 syntaxes.json 的数据结构、schema 约束、语法条目之间与类型条目之间的引用关系,以及 Imba 的 CSS 正式语法解析器是如何消费这些定义、将其转化为编辑器智能提示与类型检查能力的。

syntaxes.json 在 MDN CSS 数据目录中的位置与作用

在apps/imba.io/scripts/mdn-data/css/目录下,CSS 数据被拆分为六类,分别对应六个 JSON 数据文件、对应的 schema 文件与说明文档:

数据类别数据文件结构约束
规则(at-rules)at-rules.jsonat-rules.schema.json
属性(properties)properties.jsonproperties.schema.json
选择器(selectors)selectors.jsonselectors.schema.json
语法(syntaxes)syntaxes.jsonsyntaxes.schema.json
类型(types)types.jsontypes.schema.json
单位(units)units.jsonunits.schema.json

这些数据通过 index.js 统一汇总导出:

module.exports = { atRules: require('./at-rules'), selectors: require('./selectors'), types: require('./types'), properties: require('./properties'), syntaxes: require('./syntaxes'), units: require('./units'), }

properties.json负责给每个 CSS 属性声明其正式语法,而syntaxes.json负责把语法中出现的抽象片段(如<attachment>、<alpha-value>)拆成可复用的定义。二者配合,才能把“属性允许哪些值”完整描述出来。

schema 约束:每个条目都必须是一个 syntax 字符串

syntaxes.schema.json 给出了语法条目的结构约束:整个文件是一个对象,每个键对应一个语法名,每个值都是一个对象,且必须且只能包含一个名为syntax的字符串字段:

{ "type": "object", "additionalProperties": { "type": "object", "additionalProperties": false, "required": [ "syntax" ], "properties": { "syntax": { "type": "string" } } } }

也就是说,syntaxes.json中不存在任何元数据字段(如描述、浏览器兼容性),它是一份纯粹“语法即数据”的字典,键名即被引用名,键值即正式语法表达式。

基本单元:关键字与|分隔的取值集合

syntaxes.json中最常见的定义,是由竖线|分隔的关键字集合。原文档以background-attachment属性为例:属性定义引用<attachment>语法,而<attachment>在 syntaxes.json 中被定义为三个关键字之一:

properties.json中的定义:

"background-attachment": { "syntax": "<attachment>#" }

syntaxes.json中的定义:

"attachment": { "syntax": "scroll | fixed | local" }

这里出现了两个值得注意的细节:

  • <attachment>与attachment的对应关系:语法中的<attachment>(尖括号包裹)表示“引用名为 attachment 的语法条目”,去掉尖括号即是 syntaxes.json 中的键名;
  • #是重复修饰符:<attachment>#表示该语法可以出现一次或多次,且多个取值之间以逗号分隔(参见 parser.js 中multiplier["#"]的实现,它把数量区间设为[1, 20]并指定分隔符为,)。

类似的关键字集合定义在数据文件中大量存在,例如:

"absolute-size": { "syntax": "xx-small | x-small | small | medium | large | x-large | xx-large | xxx-large" }

|在正式文法中表示“多选一”(exactly one of them must occur),这是 CSS 值定义语法中最基础的组合子。

引用 CSS 类型:从语法到类型数据

语法并不局限于关键字,还可以引用 CSS 基础数据类型。原文档给出的alpha-value示例:

"alpha-value": { "syntax": "<number> | <percentage>" }

这里的<number>与<percentage>是 CSS 类型(types)条目,定义在 types.json 中。于是alpha-value表达的含义是:该取值要么是一个 number 类型,要么是一个 percentage 类型——例如opacity: 0.5与opacity: 50%都合法。

在 Imba 的解析器实现中,<number>、<percentage>这类基础类型并非只依赖 JSON 数据,而是由 css-syntax-parser/index.js 中的reference对象用正则表达式直接落地,例如:

"number": CSSFormalSyntaxParser.generateRegExpType(/^[+-]?([0-9]*\.[0-9]+|[0-9]+)(e[+-]?[0-9]+)?$/, "1"), "percentage": CSSFormalSyntaxParser.generateRegExpListType(/^[+|-]?([0-9]*\.[0-9]+|[0-9]+)(e[+-]?[0-9]+)?%$/i, /^[+|-]?(?:[0-9]*\.[0-9]+|[0-9]+)(e[+-]?[0-9]+)?$/i, "1%", ["%"]),

其中generateRegExpType生成“正则校验 + 默认值”的数据类型,generateRegExpListType额外附带单位列表(用于生成补全建议)。从源码结构看,这保证了number的浮点与科学计数法写法、percentage的%后缀都能被精确校验。

语法条目之间的相互引用

syntaxes.json不只是“叶子定义”,语法条目之间可以层层引用、互相组合。原文档给出了length-percentage被shape-radius复用的例子:

"length-percentage": { "syntax": "<length> | <percentage>" }, "shape-radius": { "syntax": "<length-percentage> | closest-side | farthest-side" }

展开后,shape-radius的合法取值等价于<length> | <percentage> | closest-side | farthest-side。这种“组合式”定义避免了在多个属性语法中重复书写同一段表达式,也让clip-path、shape-outside等属性(见 css-syntax-parser/index.js 中clip-path: "<clip-source> | [ <basic-shape> || <geometry-box> ] | none"的属性引用表)共享同一套几何半径规则。

引用解析在解析器中由combinator["<"]的prepare方法完成:遇到<xxx>时,先在basicDataType(基础类型)中查找,找不到再到property(属性引用)中查找;找到的是字符串则递归解析其语法,是正则则构造组件检查器,并在递归解析成功后回写缓存(见 parser.js 中Undefined import的错误处理与结果缓存逻辑)。

更复杂的文法:组合子、分组与数量修饰符

原文档明确指出,CSS 语法可以比“用|分隔的关键字”复杂得多。从 parser.js 的combinator定义可以看到,解析器完整支持 CSS 值定义语法中的全部组合子,并按优先级排序:

组合子含义优先级
空格并列,所有组件必须按顺序出现4
&&全部组件都必须出现,但顺序任意3
||至少一个组件出现,顺序任意2
\|多选一,恰好一个出现1
[...]分组0
<...>引用其他语法/类型0

以及multiplier中的数量修饰符:*(0~20 次)、+(1~20 次)、?(0~1 次)、{m,n}(指定次数区间,支持∞)、#(逗号分隔的重复,可写作#{2,}等)。

这些原语组合在一起,就能表达真实世界里复杂属性的完整语法。例如数据文件中的网格轨道与渐变定义:

"auto-repeat": { "syntax": "repeat( [ auto-fill | auto-fit ] , [ <line-names>? <fixed-size> ]+ <line-names>? )" }, "auto-track-list": { "syntax": "[ <line-names>? [ <fixed-size> | <fixed-repeat> ] ]* <line-names>? <auto-repeat> [ <line-names>? [ <fixed-size> | <fixed-repeat> ] ]* <line-names>?" }

以及背景层定义:

"bg-layer": { "syntax": "<bg-image> || <bg-position> [ / <bg-size> ]? || <repeat-style> || <attachment> || <box> || <box>" }

<bg-layer>恰好演示了||的语义:背景各组成部分可以任意顺序出现,只要全部(或按?修饰部分可选)覆盖即可。解析器对&&/||采用回溯式搜索(process中通过复制stringObjt、记录cantFound集合来尝试不同排列组合),从实现层面印证了“顺序任意”的文法语义。

在 Imba 中的实际应用:从 syntaxes.json 到类型声明

syntaxes.json并非孤立的数据文件,它直接服务于 Imba 样式系统的类型生成流程。

generate-typings.imba 是这一流程的核心脚本,其关键步骤是:

  1. 导入css-data.json(由 mdn-data 数据加工而来)以及css-syntax-parser导出的parser与propertyReference;
  2. 对每个属性,用parser.prototype.parseSyntax(format)解析其正式语法,得到语法树的组件数量上限(maxlen),据此决定生成set(...)方法签名需要的参数个数:
    let len = Math.min(item.type..maxlen or 1, 4) let nr = 1 while nr < len sign += ", arg{nr++}: any"
  3. 将属性名中的连字符转换为合法标识符(str.replace(/\-/g,'Ξ')),为每个属性生成一个interface xxx extends _类型声明;
  4. 结合主题(StyleTheme、theme.variants)把调色板、字号、阴影、圆角、缓动曲线等变体值也生成为可补全的枚举类型;
  5. 最终写入typings/styles.generated.d.ts。

这一整条链路(JSON 数据 → 正式语法解析 → d.ts 生成)意味着:syntaxes.json 中任何语法条目的增删,都会直接影响 Imba 编辑器里样式属性的补全候选与参数提示。可以推断,这就是 Imba 能把 CSS 书写体验做到“接近类型安全”的机制之一——样式属性的合法值并非手写硬编码,而是从 MDN 数据集自动推导的。

小结

syntaxes.json是 MDN CSS 数据集中“语法的字典”:它以syntax字符串承载 CSS 值定义语法,通过尖括号引用、组合子、数量修饰符把关键字、基础类型与复合语法串联成一张可递归展开的网。在 Imba 仓库中,这张网经由 css-syntax-parser 的正式语法解析器落地为可校验、可补全的类型声明,成为 Imba 全栈样式系统中“CSS 即类型”能力的数据基石。

想继续深入,可以阅读 syntaxes.json 查看完整的语法条目,对照 syntaxes.schema.json 理解其结构约束,再结合 parser.js 追踪组合子与乘数在解析阶段的处理细节。

  • 编程语言
  • 编译器
  • 语言运行时

【免费下载链接】imba

🐤 The friendly full-stack language

项目地址:https://gitcode.com/gh_mirrors/im/imba
点击查看免费下载

相关推荐

上一篇:dynamic-datasource异步任务数据源:隔离级别配置终极指南
下一篇:EventSource Polyfill:打破浏览器壁垒,实现跨平台实时通信的统一方案

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询