进阶技巧#
请选择你感兴趣的部分进行阅读.
常用资源网站#
免费字体#
你可以从 ZeoSeven Fonts 中找到很多免费字体.
以 Sarasa Gothic 更纱黑体 Mono 为例, 我们搜索到它, 进入它的页面, 点击右上角的即会跳转到对应内容, 选择 然后点击复制即可.
免费图标#
你可以从 FontAwesome 中找到很多免费图标. 它们在前端界面中直接可用.
免费 CDN#
jsdelivr 为所有 npm 库和 github 文件提供了 CDN 支持, 你可以直接在脚本或界面中引用它们.
需要注意的是, 你应该用 https://testingcf.jsdelivr.net 这个国内也能访问的镜像, 而不是直接用 https://cdn.jsdelivr.net.
提示
如果是需要为项目加入第三方库, 推荐直接通过 pnpm add 第三方库 来添加它们, 模板文件夹已经配置好会在打包时将第三方库转换为 jsdelivr 链接, 从而避免在多个脚本或界面中重复打包它们, 具体见下文 "调整模板配置" 部分.
颜色对比度检查器#
无论界面设计成什么样, 你都应该保证界面的可读性.
其中重要的一点是, 保证背景颜色和文字颜色之间的对比足够强, 让玩家能看清楚文字. 为此你可以使用 Adobe 颜色对比度检查器.
前端界面正则的推荐写法#
提高正则容错率#
你的前端界面可能对应于 AI 很复杂的输出格式, 但这些格式应该由前端界面的代码通过 getChatMessages 获取楼层消息内容后处理, 而不应该在酒馆正则里拿 $1 等处理.
前端界面正则唯一要做的是定位前端界面应该在的位置, 而不是处理输出数据.
例如, 如果你的输出格式是: (并不是说我推荐这种格式)
<status>
心情:→(平静通话)
衣着:居家长T恤
角色阶段:暗中观察
位置:自己房间
行动:结束与user通话
下一步行动:准备就寝
身体:及腰银发散落,深紫色的眼眸中带着一丝遗憾,白皙的肌肤在月光下泛着珍珠般的光泽,散发着淡淡的茶香
内心:心爱找他有什么事呢...不知道他会不会陪我过生日...
求签问卦:月下逢君意/花开并蒂时/缘定三生后
</status>
前端界面正则只需要定位这一段文本即可:
脚本名称: [界面]状态栏
查找正则表达式: <status>.*</status> # 正则不需要在意里面具体是什么
替换为: 前端界面的 html 代码块
作用范围:
- [x] 用户输入
- [x] AI输出
短暂:
- [x] 仅格式显示
- [ ] 仅格式提示词
而在代码中, 要求 AI 使用 getChatMessages 获取整条消息, 然后告诉 AI 对应的数据是什么格式:
// 获取整条消息
const chat_message = getChatMessages(getCurrentMessageId())[0];
// AI 按照你给定的格式自行捕获数据... 例如这里是 `<status>(.*)</status>`
const match = chat_message.message.match(/<status>(.*)<\/status>/);
/* AI 继续拆分数据里的各段文字, 从而在前端界面上使用 */
避免渲染卡顿#
前端界面的渲染过程为: 酒馆正则将内容替换成代码块并渲染出来 -> 酒馆助手将代码块替换为前端界面 (仅需几毫秒) -> 前端界面按代码加载 (取决于网络和设备性能).
也就是说, 其实酒馆助手负责的部分仅需几毫秒, 前端界面的加载速度完全取决于玩家的网络、设备性能和……"酒馆正则将内容替换成代码块并渲染出来".
酒馆渲染代码块这一过程是不可避免的! 而且, 哪怕酒馆助手已经优化了其中一个环节, 它还是非常卡——前端界面代码越多越卡!
为此, 你可以像下文发布会自动更新的前端界面、脚本或美化样式那样, 将 html 转换为链接, 而正则代码块里只加载链接. 这样酒馆需要渲染的代码块内容没多少, 自然不会卡顿.
怎么实现xxx功能#
酒馆助手有哪些功能?#
本编写模板有一个 @types 文件夹, 其内是酒馆助手和酒馆的接口类型定义, AI 可以据此了解能对酒馆进行什么操作.
不过,
AI 的注意力是有限的, 它也许没注意到酒馆助手直接支持某个功能, 而把代码复杂化;
由于你不知道酒馆助手支持某个功能, 你可能完全没想到能实现某件事情. (例如, 你可以在脚本里用一行代码实现角色卡绑定预设!)
因此, 我建议你也通过酒馆助手文档或直接阅读 @types 文件来了解一下酒馆助手的功能.
用 figma 像做 PPT 一样设计界面#
figma 是专业的前端原型设计软件, 它预制了大量模板 (包括很多大厂的原生设计). 通过它, 你可以像做 PPT 一样自己设计界面而不必祈祷 AI 审美足够好.
在 figma 中用预制组件像做 PPT 一样设计界面
在设计完成后, 你可以配置 figma MCP 让 AI 直接按照你设计好的界面编写实际代码, 具体配置方法可能因时间而变而且很简单, 因此请自行研究或阅读帖子原帖的旧教程部分. 它不仅配置简单, 使用也很简单, 例如:
像 PPT 一样做好设计后, 发给 AI 让它实际编写#
编写结果#
此外, figma 也推出了 AI 功能. 由于它是专业前端原型设计软件, 它的 AI 设计出的界面一般比其他 AI 好看许多.
执行酒馆的 /STScript 命令#
你可以通过 triggerSlash 或 SillyTavern.executeSlashCommandsWithOptions 来执行酒馆的 STScript 命令, 如触发 AI 回复 (triggerSlash('/trigger'))、刷新网页 (triggerSlash('/reload-page')) 等.
编写模板已经在 slash_command.txt 中提供了命令列表给 AI; 如果需要人工查询, 请使用命令手册
在脚本中用 jquery 修改酒馆页面、添加新界面等#
在脚本中, 你可以用 jquery 来
修改酒馆网页现有元素, 酒馆助手内置库中的预设条目更多按钮、预设防误触等脚本.
添加新界面, 如日记络络中的流式 Galgame 界面、输入助手、文生图、行动选择框、压缩相邻消息等脚本.
也就是说, 给酒馆现在的界面做额外功能、悬浮框、外置手机、流式界面、完全去掉酒馆楼层换成你自己的界面等等, 都能脚本实现.
编写模板里的 AI 直接会这些, 而我也在编写模板里提供了 createScriptIdDiv 和 createScriptIdIframe 方便制作这些功能.
制作流式或同层界面#
编写模板里的 AI 直接会使用以下列出的两种方案. 例如, 你可以直接要求:
制作一个流式楼层界面,它使得楼层只会显示最新一段文本.
日记络络中的流式 Galgame 界面
同层前端界面#
要简单做流式传输, 我们使用酒馆助手的前端界面, 在其中设计按钮来触发酒馆助手的generate函数.
也就是说:
玩家只在一个前端界面内进行游玩
对于玩家的输入, 我们通过前端助手的
generate、generateRaw命令自行要求 ai 回复.如果需要流式显示, 我们监听
iframe_events.STREAM_TOKEN_RECEIVED_FULLY事件来获取流式传输文本.我们依旧使用酒馆的楼层机制记录剧情: 将前端界面正则调成最大深度
0, 然后用setChatMessages、createChatMessages、deleteChatMessages等函数的{ refresh: 'none' }参数来修改消息楼层但不刷新显示. 由于不会刷新显示, 玩家可以继续游玩你的界面, 但剧情记录等又能直接利用酒馆的楼层机制, 你不需要写一堆额外的代码来制作记录剧情功能.
流式楼层界面#
前面提到我们可以在酒馆助手脚本中用 jquery 修改页面元素, 那么我们完全可以把酒馆的楼层显示隐藏起来, 自己在它原本的位置制作一个楼层显示:
监听
tavern_events.MESSAGE_SEND -> message_id, 我们可以知道玩家要求了酒馆调用 AI 生成;监听
tavern_events.STREAM_TOKEN_RECEIVED -> text, 我们可以获取流式传输文本;监听
tavern_events.MESSAGE_RECEIVED -> message_id, 我们可以知道酒馆结束了回复.
这样一来, 我们可以自己获取流式传输文本, 自己控制该怎么显示界面.
例如, 假设我们让 AI 以 YAML 的形式发送对话, 流式过程中可能得到:
- 角色: 络络
对话: 杂鱼喵
- 角色: 青空莉
对话: 杂鱼哦
- 角色: 络络
对
我们可以在还没收到消息时就显示 Galgame 对话界面, 而只将格式已经完整的对话添加到界面中, 允许玩家在流式时就翻页阅读.
我在 util/streaming.ts 中提供了一种流式楼层界面框架, 因此编写模板里的 AI 已经直接会怎么做了. 例如, 你可以直接要求:
制作一个流式楼层界面,它使得楼层只会显示最新一段文本.
对发送出的提示词进行修改#
除了通过 jquery 修改页面元素, 脚本也可以监听酒馆的提示词发送事件, 进而自行修改提示词.
要做到这一点, 我们可以监听的事件有很多, 如: (按请求生成时事件发生先后顺序)
tavern_events.GENERATE_AFTER_COMBINE_PROMPTStavern_events.CHAT_COMPLETION_PROMPT_READYtavern_events.GENERATE_AFTER_DATA(提示词模板、酒馆助手宏发生在这里)tavern_events.CHAT_COMPLETION_SETTINGS_READY
此处以 tavern_events.CHAT_COMPLETION_PROMPT_READY 为例:
eventOn(
tavern_events.CHAT_COMPLETION_PROMPT_READY,
(event_data: Parameters<ListenerType['chat_completion_prompt_ready']>[0]) => {
_.remove(event_data.messages, (message => message.role === 'user'));
},
);
noass 等压缩相邻消息、合并消息的功能就是这么做的, 例如压缩相邻消息.
注意修改方式
不要用 event_data.chat = [{role: 'system', message: '你好'}] 之类的方法, 这是让 event_data.messages 指向一个新数组, 而不是修改 event_data.messages 原本指向的数组.
你应该使用:
lodash 中的某些原地修改函数
数组的
splice、push等原地修改函数
控制世界书条目的激活#
见于酒馆如何处理世界书.
发布会自动更新的前端界面、脚本或美化样式#
还记得我们是如何实现实时修改前端界面或脚本的吗? 我们利用 将本地文件夹转换为了网络链接, 而正则或脚本通过网络链接来加载最新打包内容.
既然这样, 我们完全可以发布一个网络链接给玩家, 从而让玩家永远加载到最新的前端界面或脚本!
提示
如果使用自己的服务器来部署链接, 请注意设置 https, 否则使用 https 的云酒馆玩家将不可访问.
利用 github 和 jsdelivr#
最简单的方式是利用 jsdelivr 为 github 文件提供的 CDN 功能. 对于上传在 github.com/组织名/仓库名 中 路径 下的文件, 你可以直接用 https://testingcf.jsdelivr.net/gh/组织名/仓库名/路径 来访问它们.
酒馆助手内置库即采用了这种方法. 例如, 如果你从中导入标签化, 编辑它就会发现它的代码里仅有一行:
import 'https://testingcf.jsdelivr.net/gh/StageDog/tavern_resource/dist/酒馆助手/标签化/index.js'
而前端界面可以写成:
<body>
<script>
$('body').load('https://testingcf.jsdelivr.net/gh/lolo-desu/lolocard/dist/日记络络/界面/介绍页/index.html')
</script>
</body>
甚至, 你也可以用 jsdelivr 发布会自动更新的酒馆美化:
@import url("https://testingcf.jsdelivr.net/gh/lolo-desu/lolocard/src/思维链美化/酒馆自带推理块版/暗色.css");
为了方便你得到这样的 jsdelivr 链接, 编写模板已经配置了 github 自动工作流. 你可以在 StageDog/tavern_helper_template 用 来创建一个新仓库, 并按照仓库 README 说明进行配置, 然后将它克隆到本地使用.
这样一来, 你只需要负责在 src 文件夹下修改代码, 完成后上传到 github 仓库; 上传后, 自动工作流将会为你自动打包最新结果到 dist 文件夹.
然而, jsdelivr 主服务器、jsdelivr 镜像服务器 (为了国内直连) 和玩家的浏览器都会缓存文件, 因此并不是 github 上文件更新后, 这个链接就会立即得到最新的打包结果.
除了等待服务器自行刷新缓存, 你可以通过以下方式来加快缓存刷新:
如果你是从 StageDog/tavern_helper_template 来创建的新仓库, 并按照仓库 README 说明完成了配置, 它的自动工作流会自动打包结果并更新版本号, 从而做到 12h 刷新 jsdelivr 主服务器缓存
等仓库更新版本号后,在 https://www.jsdelivr.com/tools/purge 中输入要使用的链接, 将
testingcf.jsdelivr改成cdn.jsdelivr, 然后点击确认, 能立即刷新 jsdelivr 主服务器缓存, 但镜像服务器缓存不会刷新玩家主动清除浏览器缓存
或者, 你可以暂时换个还没缓存你文件的镜像网站来访问:
testingcf.jsdelivr.net
fastly.jsdelivr.net
gcore.jsdelivr.net
利用 cloudflare r2#
cloudflare 免费为你提供了 10GB 对象存储服务, 你可以将它作为图床、前端界面或脚本的上传仓库……具体用法请在网上搜索教程.
发布会自动更新角色卡#
提示
我已经制作了泛用的自动更新角色卡、预设脚本, 如果不想知道原理, 可以直接使用.
酒馆助手提供了导入/更新角色卡的接口 importRawCharacter, 我们可以利用它编写一个脚本来实现角色卡的自动更新.
总的来说, 你需要以下内容:
- 能够获取最新角色卡文件
你可以直接像上文我们自动更新前端界面、脚本一样, 使用 jsdelivr 网络链接 (
fetch(链接, { cache: 'no-store' })); 也可以用你自己的云存储链接.- 能够获取角色卡最新版本号
针对这个, 你也可以上传一个
版本号文件到 github 仓库中, 然后通过 jsdelivr 网络链接获取它.- 能够获取玩家当前所用角色卡的版本号
你可以使用来记录版本号, 这在脚本中可以用
getCharacter接口获取.
这样一来, 只要我们在更新角色卡后, 将最新角色卡文件和最新版本号上传到 github 仓库, 玩家就会收到角色卡更新了.
为了让这个更新过程更为自动化, 你可以学习实时编写角色卡、世界书或预设, 然后调整模板文件夹中的 tavern_sync.yaml 配置文件:
你可以像
示例/角色卡示例那样, 在 VSCode 里让 AI 或自己修改角色卡的第一条消息、世界书、版本号等;修改完成后, 你直接将更改上传到 github, github 会自动打包你配置了的所有角色卡、世界书或预设;
例如, 你可以删掉
示例/角色卡示例/角色卡示例.png, 然后运行node tavern_sync.mjs bundle all. 完成后, 就会发现示例/角色卡示例/角色卡示例.png又出现了.
由于 github 上的角色卡、世界书或预设文件已经更新, 脚本会检测到版本号不同, 从而为玩家更新角色卡.
导入文件文本内容#
你可能需要在代码里获取本地 json 等文件内容, 那么可以直接用 import string from './文件?raw' 来将文件内容作为字符串导入.
与外部应用程序通信#
模板可以安装和使用 socket.io-client 乃至所有浏览器环境支持的第三方库, 从而和外部应用程序进行通信. 实时编写角色卡、世界书或预设 (StageDog/tavern_sync) 就是如此实现的.
如果你要传输数据, 请注意调整服务器端的 maxHttpBufferSize 参数, 它默认仅为 1mb.
调整模板配置#
自定义项目配置#
在
AGENTS.md和.agents中, 我预先为项目配置了一些编程助手编写规则 (相当于给编程助手添加了一个全局世界书). 你完全可以自行编写更多规则.在
package.json中, 我预先为项目代码添加了 jquery、zod 等方便的第三方库 (具体请查看dependencies部分). 你可以让 AI 或自己用pnpm add 第三方库添加更多需要的第三方库, 它们一般添加上就能直接使用.
使用 vue 编写前端界面#
酒馆助手前端界面和脚本可以直接使用 vue, 它会让界面制作变得更为简单. 示例/前端界面示例 就是这么做的.
提示
如果你想制作不依赖于酒馆的单独页面, 则也可以使用 StageDog/vue_template.
除了 vue 之外, 我还配置了 gsap、pinia、vue-router、vueuse 等库, 让你无论是实现打字机效果、做可调整元素顺序的列表、给设置做浏览器缓存、让界面全屏、发送系统通知等等都异常简单. AI 很会, 拷打 AI.
你可以安装 vue.js devtools, 从而在 F12 所打开的开发者工具中新增 vue 选项卡, 得到 vue 更多调试功能.
几行代码实现打字机效果
gsap.registerPlugin(SplitText);
split = SplitText.create('.text', { type: 'chars' });
gsap.from(split.chars, {
opacity: 1,
duration: 0.1,
ease: 'power4',
stagger: 0.04,
});
给界面设置浏览器缓存
// 我们需要从 localStorage 中获取 count 的值
let count = localStorage.getItem('count');
// 我们得转换值为字符串再赋值给 count🤢
count = String(5);
// 我们得记住保存变量结果回 localStorage🤢
localStorage.setItem('count', count);
import { useLocalStorage } from '@vueuse/core';
// 对 `count` 的改变都会被直接保存到浏览器缓存中, 我们可以随便用 `count` 变量!
const count = useLocalStorage<number>('count', 0);
// 而且变量类型就是我们需要的类型!
count.value = 5;
我觉得很有用的 vueuse 功能
更多请自行查阅文档(英文/中文); 当然你可以直接问 ai, 它也许知道.
- @vueuse/core - 状态 (State)
共享 composable 状态: useSharedComposable
自动缓存数据到浏览器, 当然你可能更想用下面会提到的 useIDBKeyval: useLocalStorage
- @vueuse/core - 元素 (Elements)
可拖动元素: useDraggable
元素大小: useElementSize
检测元素大小发生改变: useResizeObserver
检测 DOM 发生改变: useMutationObserver
检测页面滚动: useWindowScroll
标签页间、iframe 间通信: useBroadcastChannel
- @vueuse/core - 浏览器 (Browser)
剪贴板: useClipboard 和 useClipboardItems
监听事件, 支持组件卸载时自动释放: useEventListener
点击导入文件时打开的文件选择框: useFileDialog
全屏化: useFullscreen
从 Blob 创建 URL, 支持组件卸载时自动释放: useObjectUrl
向页面加载
<script>, 支持type: 'module', 支持组件卸载时自动释放: useScriptTag向页面加载
<style>, 支持组件卸载时自动释放: useStyleTag自动适配输入框大小: useTextareaAutosize
使用网页通知功能 (我嘞个 AI 回复结束后通知): useWebNotification
- @vueuse/core - 传感器 (Sensors)
点击了选定元素之外的地方: onClickOutside
某个元素被移除: useElementRemoval
某个键盘按键: onKeyStroke
键盘修饰符: useKeyModifier
按键组合: useMagicKeys
长按按钮: onLongPress
按键时自动聚焦到输入框: onStartTyping
当前鼠标所在的元素: useElementByPoint
元素是否被鼠标悬停: useElementHover
元素是否被聚焦: useElementFocus 和 useFocusWithin
显示帧数: useFps
用户处于空闲状态, 多少秒没和界面交互过: useIdle
让元素可以无限滑动: useInfiniteScroll
鼠标位置: useMouse
鼠标点击: useMousePressed
鼠标不在网页内: usePageLeave
鼠标长按滑动: usePointerSwipe
触控滑动: useSwipe
元素内的滚动: useScroll
锁定元素内的滚动: useScrollLock
- @vueuse/core - 网络 (Network)
响应式请求 url 内容, 可简单取消请求, 会在 url 变更时重新请求: useFetch
- @vueuse/core - 动画 (Animation)
你可以使用 gsap
过一段时间后触发: useTimeout 和 useTimeoutFn
每过一段时间触发: useInterval 和 useIntervalFn
当前时间: useNow
- @vueuse/core - 组件 (Component)
自己写代码才需要, 可能全都能用上, 因此自行查阅
同时进行
computed和inject: computedInject在组件中创建可复用的 template: createReusableTemplate
在组件中将 template 设置为异步渲染: createAsyncComponent
对
v-for绑定 ref: useTemplateRefsList虚拟列表, 仅渲染实际可见的部分: vueVirtualScroller
- @vueuse/core - 监听 (Watch)
自己写代码才需要, 可能全都能用上, 因此自行查阅
等待条件满足: util
监听数组, 相比于
watch还能得到数组新增元素和移除元素情况: watchArray监听最多 n 次: watchAtMost 和 watchOnce
防抖监听 (仅当一定时间内监听没触发后, 监听所回调的函数才会执行): watchDebounced
节流监听 (一定时间内仅能执行一次函数): watchThrottled
可在一定情况下忽略的监听: watchIgnorable
可暂停的监听: watchPausable
可主动触发的监听: watchTriggerable
仅在条件满足时才触发的监听: watchWithFilter
- @vueuse/core - 响应性 (Reactivity)
自己写代码才需要, 可能全都能用上, 因此自行查阅
异步的计算属性: computedAsync
自行定义依赖项的计算属性: computedWithControl
将非响应式函数转换为响应式函数: reactify
将对象内的非响应式函数转换为响应式函数: reactifyObject
响应性地忽略响应式对象中的某些字段: reactiveOmit
响应性地提取响应式对象中的某些字段: reactivePick
过段时间后将会重置成默认值的 ref: refAutoReset
可以自行重置成默认值的 ref: refManualReset
如果值为 undefined 则采用默认值的 ref: refDefault
允许自行控制是否触发响应的 ref: refWithControl
防抖响应 (仅当一定时间内 ref 没被改变后, ref 才会被修改): refDebounced
节流响应 (一定时间内 ref 仅能被修改一次): refThrottled
- @vueuse/core - 数组 (Array)
自己写代码才需要, 可能全都能用上, 因此自行查阅
简单地说就是数组各个函数的响应性版本
- @vueuse/core - Time (时间)
倒计时: useCountdown
格式化日期时间: useDateFormat
计算时间差: useTimeAgo 和 useTimeAgoIntl
- @vueuse/core - 工具 (Utilities)
自己写代码才需要, 可能全都能用上, 因此自行查阅
让不接受 ref 的函数能接受 ref (但依旧不是响应式执行): createUnrefFn
获取变量的 base64 字符串: useBase64
计数器: useCounter
确认框: useConfirmDialog
防抖执行 (仅当一定时间内不调用某个函数后, 函数才会执行): useDebounceFn
节流执行 (一定时间内仅能执行一次函数): useThrottleFn
记忆执行 (执行后, 以后对函数的调用直接返回结果): useMemoize
记录 ref 的上一个值 (需要提前创建 ref): usePrevious
多步骤向导界面: useStepper
开关 boolean 值: useToggle
响应式转换字符串为数字: useToNumber
响应式转换数字为字符串: useToString
- @vueuse/integrations
表单检验: useAsyncValidator
自动缓存数据到 indexedDB, 它相比于 useLocalStorage 能存储更多数据: useIDBKeyval
模糊搜索: useFuse
可调整元素顺序的列表: useSortable
- @vueuse/sound
播放声音: useSound
允许代码分块#
默认情况下, 前端界面或脚本会打包成单个文件, 但如果你以网络链接的形式发布前端界面或脚本, 则可以打包成多个文件块让玩家在游玩中按需加载.
为了允许代码分块, 你需要删去 webpack.config.ts 中的 new webpack.optimize.LimitChunkCountPlugin({ maxChunks: 1 }) 这一句.
混淆代码#
无论前端界面还是脚本, 你都可以在 index.ts 中添加一行 // @obfuscate 来指示打包时应该混淆代码.
混淆后的代码依旧能正常使用, 只是代码本身很难辨认. (当然我更建议你将源代码分享出来供人学习, 我添加这个功能只是因为我将预设及破限塞进了代码里, 如果在 github 仓库里直接发布可能会被注意到)
混淆后的代码#
不自动打包代码#
如果你是从模板新建仓库的形式使用编写模板, 那么可以在 index.ts 中添加一行 // @no-ci 来指示 CI 工作流不自动打包某个前端界面或脚本.
自定义 tailwindcss 配置#
tailwindcss 提供了许多组件类, 允许你不总是自定义类然后设置样式:
<p class="content-text">Hello, world!</p>
.content-text {
font-size: 30px;
line-height: 36px;
--tw-font-weight: 500;
font-weight: 500;
color: #030712;
}
<p class="text-3xl font-medium text-gray-950">Hello, world!</p>
模板并不强制你用 tailwindcss, 因此没有开启 tailwindcss 很多检查. 如果需要, 你可以自行去 eslint.config.mjs 调整它.
{
files: ['src/**/*.{html,vue,js,ts}'], // 调整检查范围
plugins: {
'better-tailwindcss': eslintPluginBetterTailwindcss,
},
rules: {
...eslintPluginBetterTailwindcss.configs['recommended-warn'].rules,
...eslintPluginBetterTailwindcss.configs['recommended-error'].rules,
// class 过长时自动换行
// 这和 Ctrl + S 所触发的自动格式化软件 Prettier 相冲突, 需要时必须在 html 标签上一行加一句 <!-- prettier-ignore-attribute -->
'better-tailwindcss/enforce-consistent-line-wrapping': [
'off', // 改为 `warn` 或 `error` 则开启
{ printWidth: 120 }
],
// 禁止在 html 中使用 tailwindcss 不支持的类
// 由此, 如果写了 tailwindcss 不支持的类, 将会报错
'better-tailwindcss/no-unknown-classes': [
'off',
{ ignore: ['fa-*'] } // FontAwesome 图标类没有被 tailwindcss 注册, 我们应该让检查忽略它避免报错
],
},
settings: {
'better-tailwindcss': {
entryPoint: 'src/global.css',
tailwindConfig: 'tailwind.config.js',
},
},
},
// 你可以复制上面的 {} 块, 通过改变 `files` 为不同范围设置不同检查