首页

最近更新.rss.xml

下载量居然快三千了,这是我做的最受欢迎的 npm 工具了,非常感谢大家。
我一直找不到一个好的方法来描述我这个工具到底是啥,直到前天有个群友跟我说,这应该叫做内鬼版的devtools mcp,非常精准的描述了这玩意能干啥
给 vite-plugin-pilot 的 ai 操作加了一个绚酷的动效
给 vite-plugin-pilot 的 ai 操作加了一个绚酷的动效
我一直找不到一个好的方法来描述我这个工具到底是啥,直到前天有个群友跟我说,这应该叫做内鬼版的devtools mcp,非常精准的描述了这玩意能干啥
下载量居然快三千了,这是我做的最受欢迎的 npm 工具了,非常感谢大家。
我让 cc 开发的一个辅助他来帮我开发前端程序的vite插件
我让 cc 开发的一个辅助他来帮我开发前端程序的vite插件

搓了个 Vite 插件,让 Agent 能自己 debug 前端代码

向大家推荐一个我做的 Vite 插件 —— vite-plugin-pilot
效果基本可以媲美 Chrome DevTools MCP,用来开发一些运行在稀奇古怪环境(比如你在开发浏览器插件、嵌入式 Webview、某个定制化的客户端)的前端程序的时候非常好用,即便是开发正常前端程序也能达到和 chrome devtools mcp 差不多的效果
这个的作用很简单,就是让 agent 能够在前端使用 eval 执行 js,这样他就能自己检查自己写的前端程序有没有什么bug之类的了
还可以用于探索一些稀奇古怪环境的运行时下怎么实现一些功能,agent同样是有自己探索的能力的,但是这些运行时是没法运行 chrome devtools mcp 这些工具
这个项目本身是我使用 glm5-turbo + cc 迭代出来的,一开始是一个项目中的 vite-plugin.ts 文件,结果发现就这么简单的提供给 agent 在页面执行js的能力就能让他的开发 测试和debug能力得到大幅的提升
想和大家分享的一个有意思的点是在这个迭代过程中本身也是用到了 vite-plugin-pilot 项目中有一个 playground ,我只要提供思路 glm5-turbo 就能自己利用 vite-plugin-pilot 在 playground 中测试使用他的顺手度并完善,由于这个插件完全是由 agent 使用这个插件自身迭代出来的,所以我相信对于agent而言他会能非常顺手的来使用这个工具
事实上在我工作中的真实场景,他确实能够很好的工作在开发插件场景下,能够自行实现功能并测试直到正确完成
于是便创建了一个单独的项目发布出来,希望能够帮助到各位前端开发者❤️
​​
​​
想和大家分享的一个有意思的点是在这个迭代过程中本身也是用到了 vite-plugin-pilot 项目中有一个 playground ,我只要提供思路 glm5-turbo 就能自己利用 vite-plugin-pilot 在 playground 中测试使用他的顺手度并完善,由于这个插件完全是由 agent 使用这个插件自身迭代出来的,所以我相信对于agent而言他会能非常顺手的来使用这个工具
于是便创建了一个单独的项目发布出来,希望能够帮助到各位前端开发者❤️
事实上在我工作中的真实场景,他确实能够很好的工作在开发插件场景下,能够自行实现功能并测试直到正确完成
这个项目本身是我使用 glm5-turbo + cc 迭代出来的,一开始是一个项目中的 vite-plugin.ts 文件,结果发现就这么简单的提供给 agent 在页面执行js的能力就能让他的开发 测试和debug能力得到大幅的提升
效果基本可以媲美 Chrome DevTools MCP,用来开发一些运行在稀奇古怪环境(比如你在开发浏览器插件、嵌入式 Webview、某个定制化的客户端)的前端程序的时候非常好用,即便是开发正常前端程序也能达到和 chrome devtools mcp 差不多的效果
向大家推荐一个我做的 Vite 插件 —— vite-plugin-pilot
还可以用于探索一些稀奇古怪环境的运行时下怎么实现一些功能,agent同样是有自己探索的能力的,但是这些运行时是没法运行 chrome devtools mcp 这些工具
这个的作用很简单,就是让 agent 能够在前端使用 eval 执行 js,这样他就能自己检查自己写的前端程序有没有什么bug之类的了

工具收藏

数据库: pocketbase 低代码快速开发 nocodb nocobase
请求mock:pocket-mocker 我以前也想过做这种的mock。
inngest 可扩展、低延迟、事件驱动的持久执行平台。 支持部署到无服务器、服务器或边缘的功能。
智能配置加载器 ts文件作为配置
数据库: pocketbase 低代码快速开发 nocodb nocobase
现在还有 nocobase

最近实践

notehttps://z2h.cn/hanzi 字帖生成网站,田字格
note​ amd 利用 npu 的办法:https://ryzenai.docs.amd.com/en/latest/inst.html https://lemonade-server.ai/ https://github.com/amd/gaia?tab=readme-ov-file 主要还是 lemonade-server ,gaia 也是连接的 gaia (直接安装 gaia 会自动安装 lemonade-server
好文推荐https://vue-bits.dev/ 非常绚酷的 vue 动画库
好文推荐​ 浏览器插件开发最佳实践 https://wxt.dev/guide/installation.html
我最近做了一个开源富文本编辑器:在线demohttps://github.com/2234839/range-warp
netsh interface portproxy add v4tov4 listenport=9222 listenaddress=0.0.0.0 connectport=9222 connectaddress=127.0.0.1
今天试了一下完全没有问题,首先在浏览器中访问
New-NetFirewallRule -DisplayName "Chrome Remote Debug" -Direction Inbound -LocalPort 9222 -Protocol TCP -Action Allow
& "C:\Program Files\Google\Chrome\Application\chrome.exe" --remote-debugging-port=9222 --remote-debugging-address=0.0.0.0
然后去 claude code 中配置 mcp 如下
勾选 [ ] Allow remote debugging for this browser instance
我开发代码使用的是 wsl ,然后我的浏览器在 widnwos 上,所以我需要能够使用chrome-devtools-mcp 链接远程电脑的浏览器

但是

这里的细节太多了,太折磨人了,下面是我遇到的一部分问题的思考,还有更多的细节在代码里以及肯定还有好多我没考虑的(从右到左的文字啥的从来就不打算处理,我的场景用不到)
富文本包裹容器问题:所有加粗,高亮等样式效果都可以视为一个包裹容器,所以应用样式和取消样式就是计算包裹容器的范围应该如何处理。
现在有一个问题:跨段落的容器包裹如何处理?
1.
单容器元素包裹:直接创建一个元素将内容包裹进去
2.
分段包裹:为每个段落中的部分创建一个内联容器
1.
这种方法就失去了包裹语义:考虑如果容器间被插入了容器,显然新容器无法被包裹,但是对于加粗高亮等容器而言这是可接受的
1.
这是大部分编辑器的做法,解决插入问题他们依赖自定义数据模型和强控制用户输入的方案
2.
为所有容器分配相同的id,来表示他们是一个组,并且这些元素本身可以视为锚点
1.
剪贴板清洗(html规范化):hack 剪切和复制功能,避免剪切锚点粘贴到其他地方导致包裹范围出现变化,也就是容器注册时应该要注册一下他是否可以被复制(注意不是禁止复制,是复制后的剪贴板中有文本,有html(这个html没有禁止复制的容器,但容器内的其他容器的html是可以存在的))
3.
锚点虚拟容器包裹,通过两个锚点来确定一个范围,这样可以解决2的问题
1.
锚点元素被剪切或者复制粘贴了怎么办?
这里的细节太多了,太折磨人了,下面是我遇到的一部分问题的思考,还有更多的细节在代码里以及肯定还有好多我没考虑的(从右到左的文字啥的从来就不打算处理,我的场景用不到)
富文本包裹容器问题:所有加粗,高亮等样式效果都可以视为一个包裹容器,所以应用样式和取消样式就是计算包裹容器的范围应该如何处理。
现在有一个问题:跨段落的容器包裹如何处理?
1.
单容器元素包裹:直接创建一个元素将内容包裹进去
2.
分段包裹:为每个段落中的部分创建一个内联容器
1.
这种方法就失去了包裹语义:考虑如果容器间被插入了容器,显然新容器无法被包裹,但是对于加粗高亮等容器而言这是可接受的
1.
这是大部分编辑器的做法,解决插入问题他们依赖自定义数据模型和强控制用户输入的方案
2.
为所有容器分配相同的id,来表示他们是一个组,并且这些元素本身可以视为锚点
1.
剪贴板清洗(html规范化):hack 剪切和复制功能,避免剪切锚点粘贴到其他地方导致包裹范围出现变化,也就是容器注册时应该要注册一下他是否可以被复制(注意不是禁止复制,是复制后的剪贴板中有文本,有html(这个html没有禁止复制的容器,但容器内的其他容器的html是可以存在的))
3.
锚点虚拟容器包裹,通过两个锚点来确定一个范围,这样可以解决2的问题
1.
锚点元素被剪切或者复制粘贴了怎么办?

怎么做

本来只是想要做一个适配层:就是为老富文本编辑器添加各种自定义容器(书签,修订)功能
结果经过研究发现只要实现通过下标选中任意一段文本可以为他添加某容器包裹或者移除某容器包裹居然就可以实现一个基本完备的富文本编辑器了!
于是这个适配层本身也能是一个富文本编辑器,还可以叠加在任何以 contenteditor 为基础实现的富文本系统上,我测试了一下叠加在 ueditor plus上基本也没啥毛病,,叠加一层中间层果然能解决任何问题😂
于是这个适配层本身也能是一个富文本编辑器,还可以叠加在任何以 contenteditor 为基础实现的富文本系统上,我测试了一下叠加在 ueditor plus上基本也没啥毛病,,叠加一层中间层果然能解决任何问题😂
结果经过研究发现只要实现通过下标选中任意一段文本可以为他添加某容器包裹或者移除某容器包裹居然就可以实现一个基本完备的富文本编辑器了!
本来只是想要做一个适配层:就是为老富文本编辑器添加各种自定义容器(书签,修订)功能

为什么做

先说一下为什么已经有了这么多成熟的产品我还在自己做吧
首先我的场景是要给老的富文本编辑器添加书签和修订功能,但老项目已经有点克苏鲁(混沌化)了而且直接替换成其他编辑器显然也不具备可行性,没有足够的时间来做这件事情,所以我想自己做一层适配层来隔绝老代码的精神污染
首先我的场景是要给老的富文本编辑器添加书签和修订功能,但老项目已经有点克苏鲁(混沌化)了而且直接替换成其他编辑器显然也不具备可行性,没有足够的时间来做这件事情,所以我想自己做一层适配层来隔绝老代码的精神污染
先说一下为什么已经有了这么多成熟的产品我还在自己做吧
以前看到为什么都说富文本编辑器是天坑?这个问题还以为和我没什么关系,结果现在就开始踩坑了🤣
bitcoin:14VLbtYR2BVnBQmKgj4pcGgc9CiauiytSw
还是参考 https://github.com/likelovewant/ollama-for-amd/releases/tag/v0.16.1 这个文档手动弄吧,下面这个有时候会芋道网络问题

约束cc执行多轮完整任务

/loop 持续优化程序,分析性能(不要滥用缓存去优化程序优化尽量针对算法或思路导致的数量级性能差距,否则小优化没有必要,我们还是要更考虑可读性),和业务上是否存在问题,是否可以精简代码,探索最佳实践,改动完毕需要执行完整测试并修复测试问题 。还可以测试并优化实际运行的程序:你可以通过远程执行js和查看log​ 通过 loop 命令是最佳方案了
bash
在你的 todos中记录这个要求,独立的五轮 每一轮:换一个思路梳理项目中整个代币系统并评估-修复-评估修复效果-再修复(如果有必要)-下一轮 (请自行修复,修复后再反复进行审查,不用询问我)
log
分析下面的任务需求,思考可能会涉及到哪些文件 任务需求: 然后找出所有会涉及到的文件。 为每一个文件创建一个 todo 任务事项,todos中描述这个文件地址和需要做什么(注意:是要为每个文件单独创建一个,禁止合并创建) 然后视情况利用agent能力批量逐项处理todo。
/loop 持续优化程序,分析性能(不要滥用缓存去优化程序优化尽量针对算法或思路导致的数量级性能差距,否则小优化没有必要,我们还是要更考虑可读性),和业务上是否存在问题,是否可以精简代码,探索最佳实践,改动完毕需要执行完整测试并修复测试问题 。还可以测试并优化实际运行的程序:你可以通过远程执行js和查看log​ 通过 loop 命令是最佳方案了
所见即所得 & 实时计算 & 结果显示智能对齐

他还可成通过这种方法来获取vue组件实例在运行时执行实例方法

js
[RemoteExec] 执行远程 JS 代码: (function() { let el = document.querySelector("[contenteditable]"); let vueComp = null; while (el) { if (el.__vueParentComponent) { vueComp = el.__vueParentComponent; break; } el = el.parentElement; } if (vueComp && vueComp.exposed) { const editorRef = vueComp.exposed.editor; const editor = editorRef && editorRef.value ? editorRef.value : editorRef; if (editor && editor._adapter) { const hasBackwardMerge = editor._adapter.mergeAdjacentSameTags ? editor._adapter.mergeAdjacentSameTags.toString().indexOf("向前合并") !== -1 : false; const container = document.querySelector("[contenteditable]"); container.innerHTML = "
123
456
789
"; editor.applyStyle(4, 5, "bold"); return JSON.stringify({ hasBackwardMerge, resultHTML: container.innerHTML, merged: container.innerHTML.indexOf("456") !== -1 }); } } return "no adapter"; })();