为 Vue SFC REPL 添加 UnoCSS

为 Vue SFC REPL 添加 UnoCSS 支持,可用于 Vue + UnoCss 的 demo 集。

preview 部署在 vue-repl-two.vercel.app

简析原项目

这里只挑选核心的目录/文件。

  • 📁codemirror - 编辑器的 codemirror 实现
  • 📁monaco - 编辑器的 monaco editor 实现,包括 vue language service 的 worker
  • 📁editor
    • FileSelector.vue - 输入标签列表
  • 📁output
    • Output.vue - 输出面板
    • Sandbox.vue - 预览沙盒
    • srcdoc.html - 预览沙盒的 srcdoc
  • store.ts - 源码文件、配置文件、编译器、编译输出等状态管理

编辑器输入源码和配置文件,通过 Vue SFC compiler 编译,输出并在 iframe 沙盒中预览。

改造方案

为了实现 UnoCSS 的输入、输出、预览,改造点如下:

  1. 添加 uno.config.ts 输入,在 store.ts 中和 tsconfig.json、import map 一并管理,监听并编译 uno.config.ts,生成 config。
  2. 构造 UnoCSS 生成器;监听源码,根据输入源码生成 uno.css,在 Output.vue 添加输出标签
  3. uno.css 插入到预览沙盒 iframe 的一个 <style> 标签中。

上述内容中,输入输出的添加比较简单,本文略,下面说说 uno.config.ts 的在线编译。

完整代码可查看笔者的 fork

在线编译 uno.config.ts

参考 UnoCSS Playground 实现,UnoCSS 编译的核心代码如下:

ts 复制代码
import { $fetch } from 'ofetch'

export async function evaluateUserConfig<U = UserConfig>(
   configStr: string,
   version: string = 'latest',
 ): Promise<U | undefined> {
   const modulesCache = globalCache
   const moduleMap =
     version === 'latest'
       ? unocssBundle
       : new Map(
           unocssBundle
             .keys()
             .map((p) => [
               p,
               () => import(/* @vite-ignore */ `https://esm.sh/${p}@${version}`),
             ]),
         )
 
   const code = configStr
     .replace(
       /import\s(.*?)\sfrom\s*(['"])unocss\2/g,
       'const $1 = await __import("unocss");',
     )
     .replace(
       /import\s*(\{[\s\S]*?\})\s*from\s*(['"])([\w@/-]+)\2/g,
       'const $1 = await __import("$3");',
     )
     .replace(
       /import\s(.*?)\sfrom\s*(['"])([\w@/-]+)\2/g,
       'const $1 = (await __import("$3")).default;',
     )
     .replace(/export default /, 'return ')
     .replace(/\bimport\s*\(/, '__import(')
 
   // bypass vite interop
   // eslint-disable-next-line no-new-func
   const _import = new Function('a', 'return import(a);')
   const __import = (name: string): any => {
     if (!modulesCache.has(name)) {
       modulesCache.set(
         name,
         moduleMap.has(name)
           ? moduleMap.get(name)!()
           : name.endsWith('.json')
             ? $fetch(CDN_BASE + name, { responseType: 'json' }).then((r) => ({
                 default: r,
               }))
             : _import(CDN_BASE + name),
       )
     }
     return modulesCache.get(name)
   }
 
   const fn = new AsyncFunction('__import', code)
   const result = await fn(__import)
 
   if (result) return result
 }

evaluateUserConfig 读取 uno.config.ts,将 import 语句解析并替换为预先准备好(或指定版本下载)的模块。

总结

本文简析了 Vue SFC REPL 项目,在此基础上通过在线编译 uno.config.ts 添加了UnoCSS 的输入、输出、预览,交互和原交互无缝融合。

下期预告: 现在的编辑器不支持 UnoCSS Token 的 hover、autocomplete、underline 等功能。下期加上。

相关推荐
AI砖家28 分钟前
Claude Code Superpowers 安装使用指南:让 AI 编程从“业余”走向“工程化”
前端·人工智能·python·ai编程·代码规范
李白的天不白39 分钟前
webpack 与axios 版本冲突问题
前端·webpack·node.js
Java后端的Ai之路1 小时前
模型调好了怎么给老板看?用这玩意儿5分钟出Demo,连前端都不用学:Gradio 6全栈实战指南
前端·机器学习·gradio
木斯佳1 小时前
前端八股文面经大全:中科星图前端日常实习(2026-04-29)·面经深度解析
前端
heRs BART1 小时前
spring-boot-starter和spring-boot-starter-web的关联
前端
龙猫里的小梅啊1 小时前
CSS(七)CSS列表控制
前端·css
浩冉学编程1 小时前
微信小程序中基于java后端实现官方的文本内容安全识别msgSecCheck
java·前端·安全·微信小程序·小程序·微信公众平台·内容安全审核
李李李勃谦2 小时前
鸿蒙PC配色方案工具:取色、配色生成与 CSS 导出
前端·css·华为·harmonyos
Jul1en_2 小时前
Claude 迁移 Codex 工作流迁移与更新
java·服务器·前端·后端·ai编程
Heo2 小时前
14_React 中的更新队列 updateQueue
前端·javascript·面试