news 2026/9/13 16:58:28

UnoCSS Autocomplete 完全指南:为原子化 CSS 打造智能补全

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
UnoCSS Autocomplete 完全指南:为原子化 CSS 打造智能补全

UnoCSS Autocomplete 完全指南:为原子化 CSS 打造智能补全

【免费下载链接】unocssThe instant on-demand atomic CSS engine.项目地址: https://gitcode.com/GitHub_Trending/un/unocss

UnoCSS 的 Autocomplete 是一套面向智能提示的可定制机制,它内置于 Playground 与 VS Code 扩展,让开发者输入诸如bg-m-这类前缀时就能即时获得精准的补全建议。本文以 UnoCSS 仓库中 autocomplete 配置文档 与 autocomplete 工具文档 为主线,结合 @unocss/autocomplete 的源码实现与测试用例,系统讲解其配置结构、DSL 语法、shorthands、extractors,以及如何在自定义规则中声明补全模板,帮助你为项目配置出贴合主题体系与业务习惯的智能提示。

Autocomplete 是什么,运行在哪里

Autocomplete 是 UnoCSS 的"智能建议"能力:当你在 Playground 或 VS Code 扩展 中输入候选类名时,它负责解析你的输入并返回可用的补全列表。这套能力由独立包@unocss/autocomplete提供(源码见 packages-engine/autocomplete/src),核心入口是createAutocomplete(uno, options),返回一个包含suggestsuggestInFiletemplatesenumerate等能力的对象(见 create.ts)。

从集成侧看,语言服务器(Language Server)在收到补全请求时,正是通过createAutocomplete(ctx.uno, { matchType, throwErrors: false })构建补全器,然后调用suggest/suggestInFile返回结果(见 completion.ts)。这意味着你配置的 autocomplete 模板会直接作用于编辑器中的补全弹窗。

配置总览:三个核心字段

uno.config.ts的根配置中加入autocomplete字段即可开启定制:

autocomplete: { templates: [ // 主题推断(theme inferring) 'bg-$color/<opacity>', // 简写(short hands) 'text-<font-size>', // 逻辑 OR 组 '(b|border)-(solid|dashed|dotted|double|hidden|none)', // 常量 'w-half', ], shorthands: { // 等价于 `opacity: "(0|10|20|30|40|50|60|70|90|100)"` 'opacity': Array.from({ length: 11 }, (_, i) => i * 10), 'font-size': '(xs|sm|base|lg|xl|2xl|3xl|4xl|5xl|6xl|7xl|8xl|9xl)', // 覆盖内置简写 'num': '(0|1|2|3|4|5|6|7|8|9)', }, extractors: [ // ...extractors ], }

三个字段的分工如下:

  • templates:使用一套简单 DSL 指定补全建议(详见下一节)。它可以接收字符串模板,也可以接收返回建议列表的函数(AutoCompleteFunction)。
  • shorthands:简写名到模板的映射表。当值为数组时,会被自动拼成一个逻辑 OR 组(即用|连接并包上())。
  • extractors:负责从源码上下文中"拾取"可能正在输入的类,并把类名风格的建议转换为当前场景下正确的格式(例如将 attributify 属性值还原为可替换的形式)。

对应类型定义见 core 的 UserConfig,其中明确了:templates可为Arrayable<AutoCompleteFunction | AutoCompleteTemplate>shorthands的 value 可为string | string[]

在配置合并层面,config.ts 会把所有 preset 与用户配置中的templates去重合并、按order排序extractors,并通过mergeAutocompleteShorthands合并shorthands。因此,各 preset 自带的内置补全与你的自定义模板是共存而非互斥的。

templates DSL 详解

模板 DSL 的核心语法由parseAutocomplete实现(见 parse.ts)。解析器会把模板拆解为三种节点类型(见 types.ts):

  1. static(静态文本):如m-w-,按字面匹配;
  2. group(逻辑 OR 组):以|分隔、被()包裹的候选值;
  3. theme(主题推断):以$开头,指向 theme 对象的某个属性。

(...|...):逻辑 OR 组

|分隔一组候选项,当输入命中其中某些项时,这些项会被作为建议返回。例如模板(border|b)-(solid|dashed|dotted|double|hidden|none)

  • 输入b-do→ 建议b-dottedb-double

这一行为与 autocomplete-parse.test.ts 的断言完全一致:解析器会把(border|b)拆成values: ['border', 'b']的 group 节点,且支持可空组(如(-suffix|))来生成带后缀与不带后缀的完整候选。

<...>:内置 shorthands

尖括号内的名称是内置简写,当前支持:

  • <num>(0|1|2|3|4|5|6|8|10|12|24|36)
  • <percent>(0|10|20|30|40|50|60|70|80|90|100)
  • <percentage>(10%|20%|30%|40%|50%|60%|70%|80%|90%|100%)
  • <directions>(x|y|t|b|l|r|s|e)

这些内置定义见 parse.ts。解析时,/<\w+>/g会先被替换为对应的正则片段;若引用了未定义的简写名,会抛出AutocompleteParseError(提示Unknown template shorthand: <key>)。

例如模板m-<num>

  • 输入m-→ 建议m-1m-2m-3

(m|p)<directions>-<num>则会组合出pt-0pt-1px-2mb-4这类完整候选(见 autocomplete-parse.test.ts)。

$...:主题推断(theme inferring)

$开头引用主题对象,例如$colors会枚举 theme 中colors对象的所有属性名。主题可以多级嵌套,例如$animation.keyframes会深入 theme 的animation.keyframes结构。

  • 模板text-$colors:输入text-r→ 建议text-redtext-rose

解析实现(parse.ts)会把$后的路径按.切分逐层深入 theme 对象,并过滤掉DEFAULT键(ignoredThemeKeys = ['DEFAULT'])以及_开头的内部键。同时支持$路径用|并列(如$colors|$spacing)以合并多个主题分支的候选。

多模板组合

templates数组可同时传入多个模板,补全时取并集。例如:

  • 模板:['(border|b)-<num>', '(border|b)-<directions>-<num>']
  • 输入b-→ 建议b-xb-yb-1b-2
  • 输入b-x-→ 建议b-x-1b-x-2

在内部,所有模板会被预解析并缓存(create.ts),然后与静态规则、动态规则、shortcuts、variants 中声明的模板一起参与建议生成(见下文"在规则中声明 autocomplete")。

shorthands:自定义与覆盖简写

shorthands让你用语义化名字包装一组候选值,并在模板中通过<name>引用:

shorthands: { // 数组会被自动转换为逻辑 OR 组 'opacity': Array.from({ length: 11 }, (_, i) => i * 10), 'font-size': '(xs|sm|base|lg|xl|2xl|3xl|4xl|5xl|6xl|7xl|8xl|9xl)', // 覆盖内置简写 'num': '(0|1|2|3|4|5|6|7|8|9)', }

要点:

  • value 为字符串时直接作为模板片段使用;为数组时等价于(<a>|<b>|…)的 OR 组。例如上面的opacity数组等价于字符串(0|10|20|30|40|50|60|70|90|100)
  • 自定义简写会覆盖同名内置简写:例如把num重定义为(0|1|2|3|4|5|6|7|8|9),那么所有模板中出现的<num>都会使用新的候选集。源码层面,parse.ts 在解析时通过{ ...shorthands, ...extraShorthands }合并,后者的优先级更高。

extractors:从代码上下文拾取候选类

extractors是补全能力的进阶开关:它们读取光标所在位置的文件内容,判断用户正在输入什么(例如处于某个标签属性、某个 class 属性或某段自由文本内),返回"已提取的输入片段"以及如何把补全建议转换/回填的规则。

AutoCompleteExtractor的核心接口包含(见 core 类型 附近):

  • extract({ content, cursor }):返回{ extracted, transformSuggestions?, resolveReplacement? }null
  • resolveReplacement(suggestion):将建议转换为{ start, end, replacement }用于精确替换光标附近文本;
  • transformSuggestions(suggestions):把类名风格的建议改写为当前输入场景下的正确格式。

suggestInFile中,补全器会先尝试按 extractor 提取输入(create.ts);若没有 extractor 命中,则退回到通用边界识别searchUsageBoundary,它会扫描光标前后,识别class=""className=""@apply等上下文并排除引号、空白与;等分隔符(utils.ts)。

实例:attributify 自动补全提取器

官方在 preset-attributify/src/autocomplete.ts 中实现了一个典型的 extractor,它处理的是 attributify 风格(如<div bg="blue-500">)的补全:

  • 先用正则定位光标所在的 HTML 元素及属性区间;
  • 跳过class/className/:class这类常规属性;
  • 若光标在属性名上,则把属性名当作待补全输入(例如输入bg);
  • 若光标在属性值上,则将属性名-拼到值前作为补全输入,并利用transformSuggestionsbg-blue-500这类类名风格建议还原为blue-500属性值风格,同时resolveReplacement保证替换范围精确命中。

这就是为什么在 Playground 的 attributify 模式下输入<div b时,可以补出bgborder等属性名;输入<div bg="b时,可以补出blue-500black等值。这也是原文档建议"参考 attributify extractor 实现自定义提取器"的最佳范本。

在规则与 shortcuts 中声明 autocomplete(meta 方式)

除全局autocomplete.templates外,静态规则天然可补全:只要规则是静态字符串(如['flex', { display: 'flex' }]),createAutocomplete会将其键名收集进staticUtils,无需任何配置即可补出flex(create.ts)。

动态规则则需要通过第三个元素meta声明autocomplete

rules: [ [ /^m-(\d)$/, ([, d]) => ({ margin: `${d / 4}rem` }), { autocomplete: 'm-<num>' }, // <-- 这里 ], ]

reset()中,补全器会从以下来源收集全部模板(create.ts):

  1. uno.config.autocomplete.templates(全局模板);
  2. 所有动态规则的meta.autocomplete
  3. 所有 shortcuts 的meta.autocomplete
  4. 所有 variants 的autocomplete

因此快捷方式也可以携带补全声明。core的类型定义(types.ts)确认了 rules、shortcuts、variants 均支持autocomplete?: Arrayable<AutoCompleteTemplate>

以 preset-wind3 的动画规则为例,仓库源码中大量使用这一机制(animation.ts):

{ autocomplete: ['animate-keyframes-$animation.keyframes', 'keyframes-$animation.keyframes'] } { autocomplete: 'animate-$animation.keyframes' } { autocomplete: ['animate-duration', 'animate-duration-$duration'] } { autocomplete: [ 'animate-(fill|mode|fill-mode)', 'animate-(fill|mode|fill-mode)-(none|forwards|backwards|both|inherit|initial|revert|revert-layer|unset)', 'animate-(none|forwards|backwards|both|inherit|initial|revert|revert-layer|unset)', ], }

可以看到,把meta.autocomplete与全局templates结合,是给现有预设规则"加餐"补全的标准姿势。

补全行为与内部机制

建议来源与排序

一次suggest(input)会并行收集四路建议(create.ts):

  1. suggestSelf:直接尝试把输入作为合法 token 解析(uno.parseToken),命中则原样返回;
  2. suggestStatic:从静态规则 / 字符串 shortcuts 中按前缀过滤;
  3. suggestUnoCache:从生成器的已缓存 token 中匹配;
  4. suggestFromTemplates:所有已解析模板的suggest结果,加上函数型模板。

随后会做去重、过滤以-结尾的残缺建议、过滤blocklist中被屏蔽的类(uno.isBlocked),并按"含数字的排后面 +Intl.Collator数值感知排序"输出(create.ts)。测试 autocomplete.test.ts 专门验证了被 blocklist 屏蔽的规则不会出现在建议中。

matchType:prefix 与 fuzzy

createAutocomplete支持两个选项(types.ts):

  • matchType: 'prefix' | 'fuzzy'(默认'prefix'):前缀匹配,或基于 fzf 的模糊匹配;
  • throwErrors: boolean(默认true):模板解析出错时是否直接抛出。

fuzzy 模式下会使用fzf库对结果做打分排序(create.ts),并有独立的 autocomplete-fuzzy.test.ts 覆盖。语言服务器在调用时传入了throwErrors: false,因此某个模板写错不会让整个编辑器补全崩溃。

suggestInFile 与 enumerate

  • suggestInFile(content, cursor):面向编辑器光标场景,先尝试 extractor,再退回到边界识别,返回带resolveReplacement的结果(create.ts);
  • enumerate():枚举从aazz等组合的完整建议集合,通常用于生成完整的候选清单或文档统计(create.ts)。

此外建议结果带有 LRU 缓存(max: 5000)与模板解析缓存,保证编辑过程中的高频补全请求足够流畅。

实践建议与注意事项

  1. 优先复用内置简写<num><percent><percentage><directions>已覆盖大部分数值/方向类补全需求,先组合再自定义。
  2. 主题推断优先于硬编码$colors$duration$animation.keyframes这类引用会随 theme 扩展自动生效,比写死候选列表更易维护。
  3. 数组即 OR 组:在shorthands中使用数组(如Array.from({ length: 11 }, (_, i) => i * 10))可避免手写一长串|
  4. 自定义 extractor 参考 attributify 实现:如果你为某种模板语法(如 Vue 指令、JSX 属性)做补全,直接参考 preset-attributify/src/autocomplete.ts 的extract/transformSuggestions/resolveReplacement三段式写法。
  5. 模板写错会报错:全局配置下默认throwErrors: true,解析失败的模板会在启动时抛出带模板原文的AutocompleteParseError,方便你定位;编辑器侧则关闭了抛错以免影响体验。
  6. blocklist 优先级最高:被 blocklist 的类即使命中模板也不会出现在建议里。

延伸阅读

  • 配置总览:docs/config/index.md
  • VS Code 扩展接入:docs/integrations/vscode.md
  • 源码实现:packages-engine/autocomplete/src、autocomplete 测试
  • Attributify 提取器参考:packages-presets/preset-attributify/src/autocomplete.ts
  • 内置规则 meta 示例:packages-presets/preset-wind3/src/rules/animation.ts

【免费下载链接】unocssThe instant on-demand atomic CSS engine.项目地址: https://gitcode.com/GitHub_Trending/un/unocss

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

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/13 16:55:27

PDF补丁丁:开源PDF书签编辑与文档合并指南

PDF补丁丁&#xff1a;开源PDF书签编辑与文档合并指南 【免费下载链接】PDFPatcher PDF补丁丁——PDF工具箱&#xff0c;可以编辑书签、剪裁旋转页面、解除限制、提取或合并文档&#xff0c;探查文档结构&#xff0c;提取图片、转成图片等等 项目地址: https://gitcode.com/G…

作者头像 李华
网站建设 2026/9/13 16:54:55

Ollama API 全量响应SDK实战教程:流式/非流式对接、异常处理与生产落地

本地大模型落地的核心痛点从来不是模型运行&#xff0c;而是接口标准化对接。很多开发者搭建完Ollama本地模型环境后&#xff0c;只会用官方简单示例代码&#xff0c;无法区分流式与非流式响应逻辑&#xff0c;不懂异常捕获、参数调优、多轮对话封装&#xff0c;上线后频繁出现…

作者头像 李华
网站建设 2026/9/13 16:54:34

配送中心选址优化:基于免疫算法的MATLAB实现与调参实战

简介&#xff1a;这是一份基于MATLAB实现免疫算法求解配送中心选址问题的完整代码&#xff0c;面向物流工程、运筹优化及智能计算方向的师生与开发者&#xff0c;可作为组合优化问题启发式算法的研究范例、课程设计或二次开发基础。压缩包内共十六个文件&#xff0c;包含十三个…

作者头像 李华
网站建设 2026/9/13 16:54:15

ADC与CAN双结点协同控制:时序同步与系统级设计

1. 项目概述&#xff1a;为什么“ADC/CAN双结点控制”不是两个功能的简单拼凑&#xff1f; “P3&#xff1a;ADC/CAN双结点控制”这个标题乍看像一个嵌入式系统课程设计的编号&#xff0c;但背后藏着工业现场最真实、最棘手的协同控制逻辑。它不是把ADC采样和CAN通信两件事分别…

作者头像 李华