news 2026/10/7 1:15:55

搜索热词superpowers背后的真实需求:编辑器增强、本地模型工具化与自动化工作流安装指南

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
搜索热词superpowers背后的真实需求:编辑器增强、本地模型工具化与自动化工作流安装指南

1. 当“superpowers”成为一个搜索热词:我看到的真实需求分层

“superpowers”这个词最近在搜索框里频繁出现,连带“想要安装superpowers”也成了热词。第一次看到这个组合的时候,我愣了一下——它不像一个具体的软件名,也不像某个标准化的技术栈,更像是一个被用户用口语化方式表达出来的“愿望”。我在几个技术社区和工具群里蹲了几天,发现大家嘴里的“superpowers”其实指向完全不同的东西:有人想给自己的编辑器装一套能自动补全、自动重构的增强插件;有人想给本地跑的大模型接一套工具调用能力,让它能读文件、执行命令、查资料;还有人只是想要一个“让电脑变聪明”的桌面助手,能听懂自然语言就帮忙干活。

这种一词多义的现象在热词里很常见,但“superpowers”特别典型,因为它本身就是一个比喻——超级能力。用户真正想要的不是某个叫这个名字的软件,而是“让手头的工具突然变得很强”的那种体验。所以这篇内容我不打算去定义一个叫 superpowers 的产品,而是把搜索这个词的人最可能想要的几类东西拆开,讲清楚每一类到底是什么、怎么装、装完能干什么、以及最容易卡在哪一步。如果你正好在搜“想要安装superpowers”,先别急着找安装包,花几分钟对号入座,能省掉大量试错时间。

我先把这几类需求列出来,你可以直接看哪一类最像你:

需求类型典型说法本质诉求落地形态
编辑器增强“让写代码有超能力”补全、重构、跳转、AI辅助编辑器插件或扩展包
本地模型工具化“让模型能动手干活”工具调用、文件读写、命令执行本地服务加工具注册
桌面智能助手“电脑听懂人话”自然语言驱动系统操作桌面客户端加脚本桥接
自动化工作流“一键完成一堆事”任务编排、定时触发工作流引擎加节点配置

这张表不是标准分类,而是我从实际交流里归纳出来的。你会发现,同样一句“安装superpowers”,落到操作层面可能是装一个 VS Code 扩展,也可能是配一个本地 HTTP 服务,差别非常大。所以接下来的内容会按这个分层来展开,每一层都给出可复现的步骤和我自己踩过的坑。

2. 编辑器增强类“superpowers”:插件选型与安装的完整链路

2.1 先搞清楚你的编辑器到底缺什么能力

很多人一上来就问“装哪个插件能变强”,但这个问题没法直接回答,因为“强”的定义不一样。我一般会先让对方做一个小测试:打开一个你熟悉的项目,试着完成三件事——第一,在一个陌生文件里跳转到某个函数的定义;第二,把一个长函数里的某段逻辑抽成独立方法;第三,给一个没有注释的模块补上参数说明。如果你做这三件事的时候觉得顺手,那你的编辑器基础能力已经够了,缺的可能是 AI 辅助;如果第一件事就卡住,那你要的是语言服务,不是“超能力插件”。

这个判断很重要,因为编辑器增强类工具大致分两层:底层是语言服务器协议(LSP)提供的跳转、补全、诊断,上层是 AI 辅助提供的生成、重构建议、自然语言问答。很多人把这两层混在一起,装了一堆 AI 插件,结果基础的跳转还是慢,就以为是插件不行。实际上底层没配好,上层再花哨也白搭。

我自己的习惯是先把 LSP 配稳。以常见的几种语言为例,TypeScript 和 JavaScript 自带得比较好,Python 需要确认解释器路径和语言服务器是否装好,Go 和 Rust 一般通过官方工具链就能拉起。判断标准很简单:新建一个文件,输入一个标准库函数名的前几个字母,看补全列表是否在一秒内出现,并且带类型信息。如果这个都做不到,先别装 AI 插件。

2.2 插件安装的三种方式和各自的适用场景

确认底层没问题之后,再考虑装增强插件。安装方式主要有三种,我按推荐顺序说。

第一种是编辑器内置的扩展市场。这是最省事的,搜索关键词、点安装、重启,完事。优点是版本管理自动,卸载干净;缺点是有些插件在市场上的版本更新滞后,或者因为网络原因下载慢。我一般优先用这种方式,尤其是团队协作时,大家版本一致,少很多“我这里能跑你那里不行”的问题。

第二种是手动下载安装包。通常是.vsix文件,通过命令code --install-extension 文件名.vsix安装。这种方式适合内网环境、市场访问不稳定、或者需要锁定特定版本的场景。我遇到过几次市场里最新版有回归 bug,就回退到上一个版本的安装包手动装。手动装的时候要注意,装完最好在扩展列表里确认版本号,有时候旧版本没卸载干净会冲突。

第三种是从源码构建。适合你想改插件行为、或者插件本身没发布安装包的情况。一般流程是克隆仓库、安装依赖、打包、再安装。这种方式门槛最高,但可控性最强。我曾经为了改一个补全触发时机的参数,从源码构建过一次,改一行配置重新打包,比等作者发版快得多。

提示:不管用哪种方式,装完先在一个小项目里试,别直接在主仓库上开。有些插件会默认开启自动保存格式化,一打开大项目就全量重写文件,git diff 一片红,回滚都来不及。

2.3 装完之后必须调的几个参数

插件装好只是开始,默认配置往往不是最优的。我以 AI 辅助类插件为例,说几个必调项。

第一个是触发方式。默认可能是“输入即触发”,也就是你每敲一个字符它就请求一次补全。这在网络好的时候很爽,但网络一抖就卡顿,而且费额度。我一般改成手动触发,比如按一个快捷键才请求,或者延迟几百毫秒再触发。具体参数名各插件不同,但思路一样:把请求频率降下来,把控制权拿回自己手里。

第二个是上下文范围。插件需要知道你当前文件、甚至整个项目的结构才能给好建议。但上下文给太多,请求就慢,还可能把敏感代码发出去。我的做法是只开当前文件和直接依赖,项目级索引按需开启。如果插件支持本地模型,优先走本地,速度稳定且数据不出机器。

第三个是补全长度。默认可能只补一行,但很多时候你想要一整段。把最大生成长度调大,同时把“停止序列”配好,避免它一直生成下去。我一般设成生成到遇到空行或右花括号就停,这样出来的代码块比较完整。

这三个参数调完,体验会有明显提升。我见过太多人装完就用默认,然后抱怨“也就那样”,其实差的就是这几步。

2.4 实测中容易翻车的两个点

第一个翻车点是快捷键冲突。增强插件往往要占用一些组合键,而编辑器本身、输入法、甚至操作系统都可能抢同一个键。表现就是按了没反应,或者触发了别的功能。排查方法是打开快捷键设置,搜索插件名,看它绑定了哪些键,然后逐个测试。我一般会把 AI 触发键设成一个不常用的组合,比如Ctrl+Alt+;,避开常见冲突。

第二个翻车点是多插件叠加。你可能同时装了补全插件、格式化插件、lint 插件,它们都在文件保存时动手,结果互相打架。表现是保存后代码格式反复横跳,或者补全内容被格式化插件改坏。解决办法是明确分工:格式化只留一个,lint 只留一个,补全类插件关掉自动格式化。我在一个项目里曾经因为两个格式化插件同时开启,每次保存文件都多出几百行 diff,查了半天才发现是插件冲突。

3. 本地模型工具化:让模型真正“动手”而不是只“动嘴”

3.1 工具调用到底解决了什么问题

如果你搜“superpowers”是想让本地模型能读文件、跑命令、查资料,那你需要的核心能力叫工具调用。没有工具调用的时候,模型只能根据你粘贴进去的文本回答,它看不到你的磁盘,也不能执行任何操作。有了工具调用,模型可以主动发起一个请求,比如“读取 config.json”,然后你的程序去执行,把结果再喂回给模型,模型继续推理。这一来一回,模型就从“聊天”变成了“干活”。

这个机制听起来简单,但落地时有几个关键设计点。第一是工具的描述要写清楚,模型才知道什么时候该调用、参数怎么填。第二是权限要控制,不能让模型随便删文件。第三是错误处理,工具执行失败时要把错误信息返回给模型,让它自己决定重试还是换方案。我见过不少人把工具注册进去就不管了,结果模型调用失败后一直重试同一个错误,陷入死循环。

3.2 最小可运行的工具调用环境怎么搭

我不建议一上来就搞复杂框架,先用最朴素的方式跑通一个工具,理解整个链路。下面是一个基于本地 HTTP 服务的最小示例,语言用 Python,因为依赖少、改起来快。

# server.py import json from http.server import BaseHTTPRequestHandler, HTTPServer TOOLS = { "read_file": { "description": "读取指定路径的文本文件内容", "parameters": { "type": "object", "properties": { "path": {"type": "string", "description": "文件路径"} }, "required": ["path"] } } } def execute_tool(name, args): if name == "read_file": with open(args["path"], "r", encoding="utf-8") as f: return f.read()[:2000] return "未知工具" class Handler(BaseHTTPRequestHandler): def do_POST(self): length = int(self.headers.get("Content-Length", 0)) body = json.loads(self.rfile.read(length)) name = body.get("name") args = body.get("arguments", {}) try: result = execute_tool(name, args) resp = {"ok": True, "result": result} except Exception as e: resp = {"ok": False, "error": str(e)} self.send_response(200) self.send_header("Content-Type", "application/json") self.end_headers() self.wfile.write(json.dumps(resp).encode()) if __name__ == "__main__": HTTPServer(("127.0.0.1", 8765), Handler).serve_forever()

这段代码起了一个本地服务,暴露一个read_file工具。模型侧需要做的,是在请求里带上工具定义,解析模型返回的工具调用意图,然后 POST 到这个服务,再把结果拼回对话。不同模型框架的接入方式不一样,但核心就是这三步:声明工具、拦截调用、回填结果。

跑通这个之后,你可以逐步加工具,比如write_file、list_dir、run_command。每加一个,都要想清楚权限边界。run_command尤其危险,我一般会限制成白名单命令,或者只允许在特定目录下执行。

3.3 工具描述写得好不好,直接决定模型会不会用

这是最容易被忽略的一点。很多人工具写好了,模型却从来不调用,或者调用时参数乱填。问题往往出在描述上。好的工具描述要回答三个问题:这个工具做什么、什么时候用、参数是什么格式。

举个例子,read_file的描述如果只写“读取文件”,模型可能在你问“这个项目结构是什么”的时候也去调它,因为它不确定该用哪个工具。改成“读取指定路径的文本文件内容,适用于查看单个文件的具体代码或配置,不适用于列出目录”,模型就能区分开。参数描述也要具体,path要说明是绝对路径还是相对路径,相对于哪里。

我自己的经验是,工具描述写完先自己读一遍,假装你是一个不知道项目背景的人,看能不能仅凭描述就正确使用。如果读不懂,模型大概率也用不好。

3.4 权限与安全:别让“超能力”变成“超风险”

工具调用给了模型操作真实系统的能力,这就必须谈边界。我的原则是三条:默认只读、写操作要确认、危险操作直接不给。

默认只读的意思是,初始只注册读取类工具,模型能看不能改。等确认它的行为符合预期,再逐步开放写权限。写操作要确认,指的是模型发起写请求时,不直接执行,而是先展示给用户,用户点确认才落地。这在桌面助手场景里尤其重要,避免模型误解意图改错文件。危险操作直接不给,比如删除目录、修改系统配置、发送网络请求,这些工具除非有非常明确的场景,否则不注册。

还有一个细节是路径校验。模型给的路径可能是相对路径、可能带..、可能是符号链接。执行前要统一转成绝对路径,并检查是否在允许的根目录下。我见过因为没做这个校验,模型读到了项目目录之外的文件。虽然多数时候无害,但习惯要养好。

4. 桌面智能助手方向:把自然语言变成系统操作的桥接思路

4.1 这类需求和前两类的本质区别

桌面助手类的“superpowers”跟前两类不一样的地方在于,它的输入是自然语言,输出是系统层面的动作,比如打开应用、整理文件、填写表单。它不依赖编辑器,也不一定依赖大模型,核心是一个“意图到动作”的映射层。你可以用规则做,也可以用模型做,但最终都要落到具体的系统调用上。

我之所以把它单独拎出来,是因为很多人搜“安装superpowers”其实想要的是这个——一个能听懂人话的桌面工具。但这类工具往往没有统一的安装包,因为每个人的系统环境、常用操作、权限配置都不一样。更现实的做法是自己搭一个轻量桥接,把最常用的几个操作接进去。

4.2 从最常用的三个动作开始搭

不要一上来就追求“什么都能干”,先选三个你每天重复最多的动作。我的选择通常是:打开指定项目目录、在目录里搜索文件名、把剪贴板内容存成带时间戳的文件。这三个动作覆盖了大部分日常整理需求,而且实现简单。

实现方式可以用脚本加全局快捷键。比如写一个 Python 脚本,监听一个快捷键,弹出输入框,你输入自然语言,脚本用简单的关键词匹配或本地小模型解析意图,然后执行对应动作。下面是一个极简的意图解析示例:

import os, datetime, subprocess def handle(text): text = text.strip() if text.startswith("打开"): target = text[2:].strip() path = os.path.expanduser(f"~/projects/{target}") if os.path.isdir(path): subprocess.Popen(["xdg-open", path]) return f"已打开 {path}" return f"目录不存在: {path}" if text.startswith("搜索"): keyword = text[2:].strip() result = subprocess.run( ["find", os.path.expanduser("~/projects"), "-name", f"*{keyword}*"], capture_output=True, text=True ) return result.stdout[:1000] or "没有匹配" if text.startswith("保存"): content = text[2:].strip() name = datetime.datetime.now().strftime("%Y%m%d_%H%M%S") + ".txt" path = os.path.expanduser(f"~/notes/{name}") with open(path, "w", encoding="utf-8") as f: f.write(content) return f"已保存到 {path}" return "没听懂"

这个脚本很粗糙,但它跑通了“自然语言到动作”的完整链路。你可以把关键词匹配换成模型调用,把动作扩展到更多场景。关键是先有一个能用的版本,再逐步迭代。

4.3 全局快捷键和输入框的绑定细节

脚本写好了,怎么触发是个问题。我试过几种方式,最后觉得最稳的是用系统自带的快捷键工具绑定一个命令,命令里调用一个弹出输入框的小程序。Linux 下可以用zenity或rofi,macOS 下可以用osascript,Windows 下可以用 PowerShell 的输入框。这样你按一个键,输入一句话,回车,动作就执行了。

这里有个细节:输入框的焦点和剪贴板。有时候你想把选中的文字直接作为输入,而不是重新打字。可以在快捷键命令里先模拟一次复制,再读取剪贴板作为默认值。这样体验会顺很多。我自己的习惯是,选中文字按快捷键,输入框里已经带上了选中的内容,我只需要补几个字说明要干什么。

4.4 这类方案的天花板在哪里

说实话,自己搭的桌面助手很难做到“什么都能干”。它的天花板取决于你接了多少动作、意图解析有多准。关键词匹配在动作少的时候够用,动作一多就互相干扰。换成模型解析会好一些,但模型也可能理解错,而且每次都要请求,延迟上来了。

我的建议是把它定位成“个人常用操作的快捷入口”,而不是“通用人工智能助手”。你每天重复的那几件事,接进去,省下的时间就很可观了。追求大而全,往往最后什么都不好用。我见过有人花几周搭了一个能控制几十个应用的助手,结果因为每个动作都要记特定说法,用起来比直接点鼠标还慢。

5. 自动化工作流:把零散动作串成一条流水线

5.1 什么时候你需要工作流而不是单个工具

单个工具解决的是“一步操作”,工作流解决的是“一串操作”。比如你每天要做的可能是:拉取最新代码、跑测试、如果通过就打包、把包传到某个目录、发一条通知。这五步如果手动做,每天花十几分钟;串成工作流,一键触发或者定时触发,几分钟就完事。

判断标准很简单:如果你发现自己在重复执行同一组操作,而且顺序基本固定,那就值得做成工作流。不需要一开始就上重型引擎,先用脚本串起来,跑顺了再考虑可视化编排。

5.2 用脚本串工作流的最小实践

我一般先用一个 shell 脚本或 Python 脚本把步骤写死,确认每一步都能跑通,再考虑参数化和错误处理。下面是一个典型的构建发布脚本骨架:

#!/usr/bin/env bash set -euo pipefail PROJECT_DIR="$HOME/projects/myapp" BUILD_DIR="$PROJECT_DIR/dist" RELEASE_DIR="$HOME/releases" cd "$PROJECT_DIR" echo "[1/5] 拉取最新代码" git pull --rebase echo "[2/5] 安装依赖" npm ci echo "[3/5] 运行测试" npm test echo "[4/5] 构建产物" npm run build echo "[5/5] 归档产物" mkdir -p "$RELEASE_DIR" tar -czf "$RELEASE_DIR/app-$(date +%Y%m%d_%H%M%S).tar.gz" -C "$BUILD_DIR" . echo "完成"

这个脚本的关键是set -euo pipefail,任何一步失败就停,不会带着错误继续往下跑。我见过不少脚本没加这个,测试失败了还继续打包,最后发出去的是坏包。另外每一步都有 echo,跑的时候知道进行到哪了,出问题也好定位。

5.3 定时触发和手动触发的取舍

工作流跑通之后,要考虑什么时候触发。定时触发适合那些“每天固定时间做”的事,比如每天早上拉代码跑测试。手动触发适合“我想做的时候才做”的事,比如发布。两者可以共存,同一个脚本,定时任务调它,快捷键也调它。

定时触发在 Linux 下用cron,macOS 下用launchd,Windows 下用任务计划程序。配置的时候注意环境变量,定时任务的环境往往比交互式 shell 干净,脚本里用到的命令路径最好写绝对路径,或者显式 source 环境配置。我踩过这个坑:手动跑没问题,定时跑就报“命令找不到”,查了半天是 PATH 不一样。

5.4 工作流出问题时怎么快速定位

工作流最怕的是“静默失败”——看起来跑了,其实某一步没生效。我的做法是每一步都留日志,输出到带时间戳的文件里。出问题时先看日志,确认卡在哪一步,再单独把那一步的命令拎出来手动跑。如果手动跑没问题,那就是环境差异;如果手动跑也失败,那就是命令本身的问题。

还有一个技巧是加“干跑”模式。脚本里加一个DRY_RUN变量,为真的时候只打印要执行的命令,不真正执行。这样在改脚本的时候可以先干跑一遍,确认命令拼得对,再真正跑。这个习惯帮我避免了好几次误删和误覆盖。

6. 绕不开的安装问题:依赖、权限和版本冲突的排查顺序

6.1 安装失败时先看这三样

不管你装的是编辑器插件、本地服务还是工作流工具,安装失败时我一般按这个顺序查:第一,看错误信息的第一行,往往最关键,后面的堆栈是连锁反应;第二,确认依赖是否齐全,尤其是运行环境和包管理器版本;第三,确认权限,是不是要写系统目录但当前用户没权限。

这三样能解决大部分安装问题。我见过有人对着几十行报错查了半天,其实第一行就写了“permission denied”。也见过依赖版本不对,装的是新包但运行的是旧环境。先把这三样过一遍,能省很多时间。

6.2 版本冲突的典型表现和隔离手段

版本冲突的典型表现是:装的时候没报错,跑的时候报“找不到符号”或者“接口不匹配”。这通常是因为不同组件依赖了同一个库的不同版本。解决办法是隔离环境。Python 用虚拟环境,Node 用项目内node_modules,系统级工具用容器或独立目录。

我自己的习惯是,任何新工具都先在一个独立环境里试,确认没问题再考虑全局装。全局装虽然方便,但一旦冲突,排查起来很痛苦。独立环境的好处是,坏了直接删掉重来,不影响其他东西。

6.3 网络原因导致的安装中断怎么处理

安装过程中如果卡在下载环节,先确认是网络问题还是源的问题。可以换一个镜像源试试,或者手动下载安装包再本地安装。手动下载的好处是能看到下载进度,断了还能续。我一般会优先找官方提供的离线包,尤其是大体积的工具。

如果必须在线装,设置合理的超时和重试。很多包管理器支持配置超时时间和重试次数,调大一点,避免网络抖动导致失败。但也不要无限重试,卡太久就换方式。

7. 我在这几类“superpowers”实践里攒下的几条硬经验

第一,先明确你要的是哪一类能力,再动手装。编辑器增强、模型工具化、桌面助手、工作流,这四类的技术栈和安装方式完全不同。搜到一篇教程就照着做,很可能做了一半发现不是你要的。花五分钟对号入座,比盲目试错省几个小时。

第二,任何给模型或自动化工具开放系统权限的操作,都从只读开始。确认行为符合预期再逐步放开。我见过因为一上来就给了写权限,模型误改配置文件导致环境起不来的情况。只读起步,是成本最低的安全策略。

第三,工具描述和脚本日志的重要性被严重低估。工具描述写清楚,模型才用得对;脚本日志写清楚,出问题才查得快。这两件事在顺利的时候看不出价值,一旦出问题就是救命稻草。

第四,别追求一步到位。先用最朴素的方式跑通最小闭环,再迭代。我搭桌面助手的时候,第一版只支持“打开目录”一个动作,但跑通之后,加第二个、第三个动作就很快了。反过来,如果一开始就想设计一个支持几十个动作的框架,很可能卡在架构上,迟迟跑不起来。

第五,环境隔离是底线。不管是 Python 虚拟环境、Node 项目内依赖,还是容器,新东西先在隔离环境里试。全局环境是共享资源,弄脏了影响的是所有项目。这个习惯我坚持了很多年,帮我省了无数次重装系统的时间。

最后说一个我自己的体会:所谓“superpowers”,真正有用的不是某个工具本身,而是你把重复劳动交给自动化之后省下来的注意力。工具会过时,插件会停更,但“识别重复、设计流程、逐步自动化”这套思路不会过时。你搜这个词、想装这个东西,本质上是在找一种更省力的工作方式。方向对了,具体装什么反而没那么重要。

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

Altium Designer元件封装快速构建与对应:避开PCB设计中的封装坑

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/10/7 1:15:40

苹果品种分类数据集实战:从580张JPEG到ResNet18训练全流程

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/10/7 1:14:40

LPDDR5布线指南:层叠、阻抗、等长与电源完整性实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/10/7 1:14:05

SAP销售订单抬头增强:BADI_SLS_HEAD_SCR_CUT完整实施指南

去年在项目上接到一个SD增强需求:销售订单VA01/VA02抬头要加三个自定义字段,客户还特别强调不要再用老一套的USER EXIT,要求用BADI_SLS_HEAD_SCR_CUT来扩展抬头屏幕。当时我翻了不少帖子,发现很多人对BADI_SLS_HEAD_SCR_CUT要么一…

作者头像 李华
网站建设 2026/10/7 1:13:05

2025年用C++和MFC复刻植物大战僵尸:从零搭建到避坑指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/10/7 1:12:56

Java web学生选课系统课程设计:源码、数据库与报告完整拆解

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华