news 2026/9/13 19:39:51

UnoCSS Autocomplete 引擎详解:@unocss/autocomplete 的模板 DSL、建议生成流程与 IDE 集成原理

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
UnoCSS Autocomplete 引擎详解:@unocss/autocomplete 的模板 DSL、建议生成流程与 IDE 集成原理

UnoCSS Autocomplete 引擎详解:@unocss/autocomplete 的模板 DSL、建议生成流程与 IDE 集成原理

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

@unocss/autocomplete是 UnoCSS 的自动补全工具包(Autocomplete utils for UnoCSS),它被内嵌于 UnoCSS Playground 和 VS Code 扩展中,为 UnoCSS 类名提供实时的输入建议。读完本文,你将掌握该包的公共 API 与可选参数、自动补全模板的 DSL 语法(静态规则、动态规则meta配置、$theme推断)、建议结果的生成与排序机制,以及它在 Language Server / Playground 中的实际调用方式。

包定位与基本信息

根据 packages-engine/autocomplete/README.md 的说明,@unocss/autocomplete的定位是一句话:UnoCSS 的自动补全工具集,内嵌于 Playground 与 VS Code 扩展。官方使用文档位于 docs/tools/autocomplete.md。

从 package.json 可以看到包的工程信息(以当前仓库为准):

  • 包名@unocss/autocomplete,当前仓库版本为66.10.0,ESM 包("type": "module"),入口./dist/index.mjs,类型声明./dist/index.d.mts
  • 运行时依赖只有两个:fzf(fuzzy 匹配)与lru-cache(建议结果缓存),均通过 pnpmcatalog:utils锁定版本;
  • @unocss/core仅作为devDependenciesworkspace:*)引用,因为createAutocomplete接受的是 core 生成的UnoGenerator实例。

入口 src/index.ts 只做再导出:createparsetypesutils四个模块的公共 API 全部从这里暴露。

核心 API:createAutocomplete

包的唯一工厂函数是 src/create.ts 中的createAutocomplete(uno, options),参数与返回结构定义在 src/types.ts。

选项 AutocompleteOptions

选项类型默认值说明
matchType'prefix' \| 'fuzzy''prefix'前缀匹配或模糊匹配。fuzzy模式基于fzf库,tiebreakers 为byStartAsc(匹配起始位置靠前优先)与byLengthAsc(更短优先)
throwErrorsbooleantrue模板解析出错误时是否抛出异常。Language Server 等长期运行场景通常传false(见下文集成部分)

返回对象 UnocssAutocomplete

export interface UnocssAutocomplete { suggest: (input: string, allowsEmptyInput?: boolean) => Promise<string[]> suggestInFile: (content: string, cursor: number) => Promise<SuggestResult | undefined> templates: (string | AutoCompleteFunction)[] cache: LRUCache<string, string[]> errorCache: Map<string, AutocompleteParseError[]> reset: () => void enumerate: () => Promise<Set<string>> }

各成员的职责(对应 src/types.ts#L35-L43):

  • suggest(input):给定一个正在输入的 token,返回建议列表。空输入默认直接返回空数组(除非显式传allowsEmptyInput = true);
  • suggestInFile(content, cursor):给定整个文件内容与光标位置,定位当前正在编辑的 class 片段并给出带替换区间的建议(IDE 补全的真正入口);
  • templates:收集到的全部模板(字符串模板 + 自定义函数),可按需追加运行时动态模板;
  • cache:容量为 5000 条的 LRU 缓存(src/create.ts#L12),避免对同一输入重复计算;
  • errorCache:模板解析错误缓存,配合throwErrors控制报错时机;
  • reset():清空全部缓存并重新从uno.config收集静态工具类与模板(配置热更新后需要调用);
  • enumerate():以aazz及双字母组合为探针批量调用suggest,并对命中结果再做一轮xxx-后缀展开,用于穷举当前配置下可能存在的全部工具类。

建议数据的四条来源通道

suggest()的核心逻辑在 src/create.ts#L67-L114。它并非只做“字符串前缀过滤”,而是分四条并行通道取建议,再统一合并排序:

const result = processSuggestions( await Promise.all([ suggestSelf(processed), // 1. 真实可解析 token suggestStatic(processed), // 2. 静态规则 + 静态快捷方式 suggestUnoCache(processed), // 3. 生成器已命中的缓存 token suggestFromTemplates(processed), // 4. 模板 DSL 展开 ]), variantPrefix, variantSuffix, )
  1. suggestSelf:调用uno.parseToken(input, '-')真实解析一次,若 token 能产出 CSS,则说明输入本身就是一个完整合法工具类,直接把它列为首条建议(这也是测试中ac.suggest('m-1')第一个结果就是m-1的原因,见 test/autocomplete.test.ts#L46-L53);
  2. suggestStaticreset()时从uno.config.rulesStaticMap的键与字符串形式的 shortcuts 收集出的静态工具类名,默认按前缀过滤,fuzzy模式下直接全量交给Fzf匹配;
  3. suggestUnoCache:通过uno.getCachedTokens(input)查询生成器内存中已经生成过 CSS 的 token——即“你在项目里用过的类”天然获得补全优先级;
  4. suggestFromTemplates:对reset()阶段解析好的全部模板逐一调用其suggest,并额外执行用户以函数形式注册的自定义模板。这里用Promise.allSettled容错,单个模板失败不会拖垮整个补全。

Variant 的剥离与还原

输入往往带有 variant 前缀(如hover:m-)。suggest先通过uno.matchVariants(_input)匹配出已存在的 variant,把输入拆成variantPrefix + 主体 + variantSuffix三段,只对“主体”做补全,最后由processSuggestions把前后缀拼回(src/create.ts#L81-L104)。若 variant 会改写主体部分导致无法逆向定位,源码中会回退到idx = 0处理。此外,若配置了@unocss/preset-attributify,会先根据 preset 的prefix选项剥离或还原 attributify 前缀。

排序规则

processSuggestions(src/create.ts#L222-L233)先uniq去重、过滤以-结尾和uno.isBlocked(i)命中 blocklist 的结果,再用预编译的Intl.Collator(numeric: true)排序,并让不含数字的建议排在含数字的建议之前——这解释了文档示例中输入b-b-xb-y会先于b-1b-2出现。

自动补全模板 DSL

这部分是官方文档 docs/tools/autocomplete.md 的核心内容,实现位于 src/parse.ts。

静态规则:零配置生效

rules: [ ['flex', { display: 'flex' }] ]

静态规则不需要任何额外配置——它们的名称会进入rulesStaticMap,自动成为suggestStatic的数据源。

动态规则:meta 中的 autocomplete 字段

动态规则(正则匹配)无法枚举,需要在规则的第三个参数meta中提供补全模板:

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

从 core 的类型定义 看,模板的合法来源有四处,reset()时统一收集(src/create.ts#L193-L198):

  • rulesmeta.autocomplete
  • shortcutsmeta.autocomplete(同样支持数组);
  • variantsmeta.autocomplete
  • 用户配置项config.autocomplete.templates

模板语法

模板使用一套简单 DSL,解析过程在parseAutocomplete(template, theme, extraShorthands)中完成:

  • (...|...)逻辑或分组:以|分隔的候选值,命中其中任意一项即可参与匹配;
  • <...>内建简写:当前支持<num><percent><directions>。源码中的实际取值是(src/parse.ts#L19-L24):
    • <num>展开为(0|1|2|3|4|5|6|8|10|12|24|36)
    • <percent>展开为(0|10|20|…|100)
    • <percentage>展开为(10%|20%|…|100%)
    • <directions>展开为(x|y|t|b|l|r|s|e)
  • $...theme 推断:例如$colors会列出 theme 中colors对象的全部属性;还支持点路径($colors.red之类的嵌套访问)与|组合多个 theme 对象。解析时会过滤掉DEFAULT键与_前缀的私有键(ignoredThemeKeysgetValuesFromPartTemplate中的过滤逻辑)。

另外,theme 中嵌套的对象会被递归展开成key-subKey形式参与组合(getValuesFromPartTemplate对对象值递归处理),这就是bg-gradient-$colors之类模板能推出多级色阶的原因。

自定义简写

config.autocomplete.shorthands允许注册项目级简写(值为字符串,或数组——数组会用|连接并包上括号,见 core 类型注释),在parseAutocomplete中与内建简写合并后统一替换<key>占位符。遇到未知简写会记录Unknown template shorthand错误。

官方文档示例

以下示例完整继承自 docs/tools/autocomplete.md:

  • 示例 1模板(border|b)-(solid|dashed|dotted|double|hidden|none),输入b-do,建议b-dottedb-double
  • 示例 2模板m-<num>,输入m-,建议m-1m-2m-3…;
  • 示例 3模板text-$colors,输入text-r,建议text-redtext-rose…;
  • 示例 4多模板['(border|b)-<num>', '(border|b)-<directions>-<num>']:输入b-得到b-xb-yb-1b-2…;输入b-x-得到b-x-1b-x-2…(注意排序上无数字项在前)。

解析后的模板被编译为ParsedAutocompleteTemplate:一组partsstatic/group/theme三种类型)加一个suggest闭包。前缀匹配走一套逐 part 状态机(对 static 段做双向 startsWith 校验、group 段做精确前缀消费、theme 段支持嵌套对象回插);fuzzy模式下则直接基于getAllCombination(parts)(对各 part 取值做笛卡尔积,见 src/utils.ts#L70-L83 的cartesian)预生成全部组合,再交给Fzf打分。

错误处理

模板解析错误封装为AutocompleteParseError(src/parse.ts#L7-L17),携带出错模板文本;throwErrors: true时在reset()末尾把所有错误合并为一个 Error 抛出,便于开发期尽早暴露配置问题。

文件内补全:suggestInFile 与提取器

suggestInFile(content, cursor)(src/create.ts#L116-L147)是 Language Server 等集成方真正调用的入口,流程为:

  1. searchAttrKey判断光标是否处于 HTML 属性值内部(影响是否允许空输入);
  2. 依次尝试config.autocomplete.extractors中的自定义提取器(extractor.extract({ content, cursor })),提取器可以额外提供transformSuggestionsresolveReplacement,把 class 风格建议转换成属性风格;
  3. 提取器未命中时走常规边界探测searchUsageBoundary(src/utils.ts#L1-L61):以空白、引号、>;等为界向外扩展出当前 token;若启用 attributify preset 则直接返回该边界;否则还要向前校验该 token 确实位于class=className=@apply上下文中,避免在无关文本里弹补全;
  4. 调用suggest得到建议,并返回SuggestResult——包含[原始建议, 显示建议]对与一个resolveReplacement回调,回调给出替换区间的start/end/replacement,IDE 据此完成文本替换。

配置侧对应config.autocomplete的三个字段(packages-engine/core/src/types.ts#L519-L535):templates(自定义模板/函数)、extractors(自定义提取器)、shorthands(自定义简写)。

在 UnoCSS 生态中的实际调用

从源码结构看,仓库内有三类消费方:

  • Language Server(VS Code 扩展后端):packages-integrations/language-server/src/capabilities/completion.ts 为每个UnocssPluginContext缓存一个createAutocomplete(ctx.uno, { matchType, throwErrors: false })实例,matchType由用户设置决定,并暴露resetAutoCompleteCache在配置变更时清理缓存。VS Code 扩展本体位于 packages-integrations/vscode;
  • Playground:playground/src/composables/uno.ts 中同样基于该包构建实时补全;
  • 文档站内搜索:virtual-shared/docs/src/search.ts 使用它按配置枚举可用的工具类。

测试与验证

包的测试位于packages-engine/autocomplete/test/,可在仓库根目录用 vitest 运行验证:

  • autocomplete.test.ts:用presetWind3+presetAttributify构建生成器,验证m-1首条建议为自身、非法输入不被建议、blocklist 生效,并对约 50 个前缀(m-bg-text-red-等)的建议快照做了断言,快照文件在 test/snapshots/autocomplete.test.ts.snap;
  • autocomplete-fuzzy.test.ts:验证matchType: 'fuzzy'行为;
  • autocomplete-parse.test.ts:覆盖模板 DSL 解析(含错误模板用例);
  • autocomplete-utils.test.ts:覆盖searchUsageBoundary/searchAttrKey的边界探测。

其中主测试还演示了 shortcuts 携带动态模板的写法:[/^bg-mode-(.+)$/, ([, mode]) => \bg-blend-${mode}`, { autocomplete: ['bg-mode-(color|normal)'] }]`,与上文“动态规则”一节完全对应。

许可

@unocss/autocomplete采用 MIT 许可(MIT License © 2021-PRESENT Anthony Fu),与仓库整体一致(见 LICENSE)。

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

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

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

LabVIEW视觉目标跟踪原理与实现:从模板匹配到卡尔曼滤波

简介&#xff1a;面向 LabVIEW 开发者与机器视觉学习者的目标跟踪与颜色跟踪示例包&#xff0c;适合用 LabVIEW 完成视觉算法验证、课程设计或项目原型开发。资源围绕视觉 labview 主题&#xff0c;提供从图像获取、预处理、特征提取到跟踪算法实现的可运行 VI&#xff0c;以及…

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

解决electron安装不了的问题

在安装之前&#xff0c;先设置npmrc: 在项目根目录创建.npmrc文件。添加完.npmrc文件后即可安装成功 .npmrc 文件的内容如下 registryhttps://registry.npmmirror.com/ electron_mirrorhttps://npmmirror.com/mirrors/electron/ electron_builder_binaries_mirrorhttps://npmmi…

作者头像 李华
网站建设 2026/9/13 19:33:17

S形非线性调频信号设计:MATLAB实现与旁瓣抑制原理

简介&#xff1a;本资源是一套面向通信与雷达信号处理方向的MATLAB实践材料&#xff0c;聚焦S形非线性调频&#xff08;NLFM&#xff09;信号建模与分析&#xff0c;适用于高校电子/通信专业高年级学生、研究生及工程技术人员开展课程设计、课题仿真或低截获概率波形研究。压缩…

作者头像 李华