详解Spec-Driven Development(SDD):Agent 时代的软件工程新范式
Spec-Driven DevelopmentAI 时代的软件工程新范式一句话总结先写清楚做什么再让 AI 去实现怎么做。规范Spec不再是代码的附属品而是整个开发流程的唯一事实来源。目录一、从一个痛点说起二、什么是 Spec-Driven Development三、SDD 的核心原则四、SDD 的工作流程五、Spec 长什么样六、SDD vs 其他方法论七、主流工具生态八、实战用 SDD 开发一个功能九、SDD 的优势与局限十、未来展望一、从一个痛点说起2025 年Andrej Karpathy 创造了“Vibe Coding”氛围编程这个词——打开 AI 编辑器凭感觉对话代码唰唰地生成。很爽对吧但很快问题就来了你帮我写一个用户注册功能 AI好的这是代码...生成了 200 行 你不对我要支持手机号注册 AI好的我改一下...重写了 300 行顺便改了你不想改的部分 你等等接口格式不是这样的... AI抱歉我重新来...又重写了之前的逻辑全丢了三轮对话之后你发现自己在调教AI而不是在开发软件。这背后的根本问题是问题表现意图模糊自然语言 prompt 碎片化AI 大量脑补需求上下文丢失多轮对话后 AI “失忆”前后矛盾不可复现同样的 prompt不同时间产出完全不同的代码架构漂移多人/多轮迭代后接口定义、数据结构悄悄变更质量不可控代码能跑但偏离业务诉求隐性 bug 频发实测数据显示纯 Vibe Coding 模式下AI 生成代码的一次通过率仅约 31%。行业需要一种方法把凭感觉编程升级为按图纸施工。这就是 Spec-Driven Development 诞生的背景。二、什么是 Spec-Driven Development2.1 定义Spec-Driven DevelopmentSDD规范驱动开发是一种以规范Specification为核心驱动力的软件开发方法论。其核心思想是在编写任何代码之前先编写一份结构化的规范文档Spec。规范成为人类开发者与 AI 共同的唯一事实来源Single Source of Truth代码是规范的最终实现产物。用微软的话说SDD 是“思想的版本控制”——管理的重点从代码的演变历史转向了决策的演变历史。2.2 一个关键思维转变传统开发需求 → 代码文档是代码的注释写完即弃 SDD 开发需求 → Spec → 代码Spec 是预编译的源代码代码只是 Spec 的编译产物维度传统模式SDD 模式核心工件代码规范Spec文档地位辅助性写完就扔驱动性持续演进AI 角色代码补全工具规范的执行者人的角色写代码定义做什么质量保障事后测试前置约束 自动验证2.3 不是什么SDD不是❌ 多写一份文档的形式主义❌ 传统瀑布模型的回归❌ 只适用于 AI 编程的专属方法但 AI 让它真正落地SDD是✅ 从 “Vibe Coding 的随机性” 走向 “Agentic Coding 的可控性” 的根本方法✅ 将定义做什么WHAT与实现怎么做HOW彻底解耦✅ 人类负责意图表达与决策AI 负责工程实现三、SDD 的核心原则原则一Spec First, Code Second任何代码变更必须先有对应的 Spec 变更。没有 Spec 的代码是无主代码不允许进入主干。原则二Single Source of Truth规范是整个团队人 AI的唯一事实来源。当代码与规范冲突时以规范为准修复代码。原则三Spec 必须可执行Spec 不是模糊的需求描述它必须足够精确、完整、结构化能够被 AI 直接理解和执行被自动化工具校验生成可验证的验收标准原则四渐进式细化Spec 不是一次性写完的大文档而是随着开发推进逐步细化的Level 0: 愿景Vision → 一句话说清楚要做什么 Level 1: 需求Requirements → 用户故事 验收标准 Level 2: 设计Design → 架构决策 接口定义 Level 3: 任务Tasks → 可执行的开发任务清单原则五人机各司其职┌─────────────────────────────────────────┐ │ 人类的职责 │ │ • 定义业务意图和约束 │ │ • 审查和批准 Spec │ │ • 做出架构决策 │ │ • 验收最终交付物 │ └─────────────────────────────────────────┘ ↓ Spec ┌─────────────────────────────────────────┐ │ AI 的职责 │ │ • 根据 Spec 生成实现代码 │ │ • 根据 Spec 生成测试用例 │ │ • 检查实现是否符合 Spec │ │ • 报告 Spec 中的歧义和冲突 │ └─────────────────────────────────────────┘四、SDD 的工作流程SDD 的最简工作流只有四步┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ │ Specify │ → │ Plan │ → │ Task │ → │Implement │ │ 定义规范 │ │ 制定计划 │ │ 拆分任务 │ │ 逐步实现 │ └──────────┘ └──────────┘ └──────────┘ └──────────┘ ↑ │ └──────────── 验证 迭代 ←────────────────────┘Step 1: Specify定义规范用结构化的方式描述做什么功能需求、用户故事不做什么明确的边界和排除项约束条件性能要求、安全要求、技术栈限制验收标准怎样算做完了Step 2: Plan制定计划基于 Spec 进行架构设计技术选型及理由模块划分与依赖关系接口契约定义复用已有代码的识别Step 3: Task拆分任务将计划拆解为小而有序的任务每个任务足够小AI 可以一次完成任务之间有明确的依赖顺序每个任务有独立的验证标准Step 4: Implement逐步实现让 AI Agent 一次只实现一个任务每个任务实现后立即验证验证通过才进入下一个任务发现问题回到 Spec 层修正而非在代码层打补丁五、Spec 长什么样一个典型的 Spec 文件通常以Markdown格式存放在代码仓库中包含以下核心部分# Feature: 用户注册模块 ## 1. Overview概述 实现基于手机号的用户注册功能支持验证码验证 注册成功后自动创建用户档案。 ## 2. Requirements需求 ### 功能需求 - [ ] 用户输入手机号获取短信验证码 - [ ] 验证码有效期 5 分钟错误次数限制 3 次 - [ ] 注册成功后自动登录并跳转首页 - [ ] 支持已注册用户检测引导登录 ### 非功能需求 - 接口响应时间 200msP99 - 验证码发送频率限制同一手机号 60 秒内仅一次 - 密码使用 bcrypt 加密cost factor ≥ 12 ## 3. Existing Patterns to Reuse复用模式 - 复用 src/services/sms.service.ts 中的短信发送逻辑 - 复用 src/middlewares/rate-limiter.ts 进行频率限制 - 遵循 src/modules/auth/ 下的现有模块结构 ## 4. Architecture Decisions架构决策 | 决策项 | 选择 | 理由 | |--------|------|------| | 验证码存储 | RedisTTL300s | 自动过期无需清理 | | API 风格 | RESTful | 与现有接口保持一致 | | 错误处理 | 统一 ErrorCode 枚举 | 前端统一处理 | ## 5. API Contract接口契约 ### POST /api/v1/auth/register Request: json { phone: 13800138000, code: 123456, password: Str0ng!Pass }Response (201):{userId:uuid,token:jwt-token,expiresAt:2026-08-03T16:00:00Z}6. Acceptance Criteria验收标准正确手机号 正确验证码 → 注册成功返回 201错误验证码 → 返回 400错误码 INVALID_CODE已注册手机号 → 返回 409错误码 USER_EXISTS验证码过期 → 返回 400错误码 CODE_EXPIRED60 秒内重复请求验证码 → 返回 4297. Out of Scope明确排除本期不做邮箱注册本期不做第三方 OAuth 登录不做用户头像上传 **关键洞察**好的 Spec 不是面面俱到的长文档而是 **足够精确的短契约**。它的核心价值在于消除歧义让 AI 没有脑补的空间。 --- ## 六、SDD vs 其他方法论 SDD 并非凭空出现它站在前人肩膀上但解决了不同的问题 | 维度 | TDD | BDD | DDD | **SDD** | |------|-----|-----|-----|---------| | 驱动力 | 测试用例 | 用户行为场景 | 领域模型 | **规范文档** | | 核心产物 | 测试代码 | Feature 文件 | 领域对象 | **Spec 文件** | | 主要受众 | 开发者 | 开发产品 | 架构师开发 | **人 AI** | | 关注层次 | 函数/类级别 | 功能/场景级别 | 业务领域级别 | **全栈意图→实现** | | AI 时代适配性 | 中 | 中 | 中 | **高** | | 核心差异 | 先写测试再写代码 | 用自然语言描述行为 | 用领域语言建模 | **先写规范再让 AI 生成一切** | **它们不是互斥的。** 在实际项目中 - **DDD** 帮你定义领域边界 → 输入到 Spec 的架构决策中 - **BDD** 的 Given-When-Then → 可以成为 Spec 验收标准的格式 - **TDD** 的测试先行 → AI 可以根据 Spec 自动生成测试 SDD 更像是一个 **编排层**把这些方法论的产出统一纳入 Spec 管理体系。 --- ## 七、主流工具生态 2026 年是 SDD 工具全面爆发的一年。几乎所有主流 AI 编程工具都上线了自己的 SDD 方案 ### 7.1 GitHub Spec Kit - **定位**GitHub 官方开源的 SDD 工具包 - **仓库**github/spec-kit上线一个月 2.8 万 Star - **工作流**Constitution → Specify → Plan → Tasks → Implement - **特点** - 规范、计划、任务以 Markdown 文件存储在代码仓库中 - 支持 Claude Code、Copilot、Cursor、Gemini CLI 等多种 AI 工具 - 提供 CLI 命令引导完整开发流程 bash # 安装 pip install specify-cli # 初始化项目 speckit init # 创建规范 speckit specify 实现用户注册功能 # 生成计划 speckit plan # 拆分任务 speckit tasks # 开始实现调用 AI Agent speckit implement7.2 AWS Kiro定位AWS 推出的 AI-native IDE原生内置 SDD 流程特点在编码过程中Kiro 会要求人类用户对其假设进行指导、确认或修正自动生成三层文件requirements.md→design.md→tasks.md自主 Agent 可连续工作数日始终遵循 Spec 约束7.3 OpenSpec定位开源的 Spec 定义框架特点用 JSON/YAML 定义服务名、端点、数据 Schema、约束和验证逻辑更偏向 API 契约和机器可读格式适合微服务架构下的接口规范管理7.4 其他工具工具特点BMAD-METHOD多 Agent 协作框架模拟产品经理、架构师、开发者角色Tessl将 Spec 视为开发语言代码是最后一公里Claude Code CLAUDE.md通过项目级 Markdown 文件定义规范和约束Cursor .cursorrules在 IDE 层面嵌入项目规范八、实战用 SDD 开发一个功能以一个真实场景演示完整的 SDD 流程场景为电商系统添加优惠券核销功能Step 1: 写 Spec# Feature: 优惠券核销 ## Overview 用户在下单时可以使用优惠券抵扣金额。 核销时需校验有效期、使用条件、库存。 ## Business Rules 1. 每张优惠券只能使用一次 2. 优惠券有最低消费门槛如满100减20 3. 过期优惠券不可使用 4. 同一订单只能使用一张优惠券 5. 核销操作必须是原子性的防并发超用 ## API Contract ### POST /api/v1/coupons/{couponId}/redeem Request: { orderId: uuid, orderAmount: 150.00 } Response 200: { discount: 20.00, finalAmount: 130.00 } Response 400: { error: COUPON_EXPIRED | BELOW_THRESHOLD | ALREADY_USED } ## Technical Constraints - 使用 Redis 分布式锁防止并发核销 - 核销记录写入数据库支持审计追溯 - 接口幂等性相同 orderId 重复调用返回相同结果Step 2: 人类审查 Spec✅ 业务规则是否完整→ 补充退款时优惠券不退还✅ 接口设计是否合理→ 确认✅ 技术约束是否可行→ 确认 Redis 集群可用Step 3: AI 根据 Spec 生成代码Prompt: 请根据 specs/coupon-redeem.md 实现优惠券核销功能。 遵循 src/modules/ 下的现有模块结构。 复用 src/services/redis-lock.service.ts。Step 4: 自动验证# AI 同时生成测试运行验证npmtest----grepcoupon redeem# 验收标准逐条检查✅ 正常核销 → 返回200金额正确 ✅ 过期优惠券 → 返回400COUPON_EXPIRED ✅ 低于门槛 → 返回400BELOW_THRESHOLD ✅ 重复核销 → 返回400ALREADY_USED ✅ 并发请求 → 只有一个成功Step 5: 迭代如果验证失败回到 Spec 层修正而不是在代码里打补丁## Spec 修订记录 - v1.1 (2026-08-03): 增加规则优惠券与满减活动不可叠加效果对比引入 Spec 后AI 生成代码的一次通过率从31% → 89%缺陷密度下降76%。九、SDD 的优势与局限✅ 优势优势说明意图对齐Spec 消除歧义AI 不再脑补需求可追溯性每行代码都能追溯到 Spec 中的某条规则可复现性同一份 Spec不同时间、不同 AI 产出一致团队协作Spec 是人和 AI 的共同语言降低沟通成本质量前置在实现前发现问题减少返工知识沉淀Spec 持续演进成为团队的活文档AI 可控性给 AI 戴上紧箍咒约束其行为边界⚠️ 局限与挑战挑战说明Spec 编写成本前期需要投入时间写高质量 Spec学习曲线团队需要学习如何写好的 Spec过度规范化风险小功能/原型不需要重型 Spec 流程Spec 维护负担Spec 需要与代码同步演进否则会成为过期文档语义鸿沟自然语言 Spec 仍可能有歧义形式化程度有限工具碎片化各工具生态尚未统一标准 实践建议小改动/原型不需要完整 SDD 流程轻量 prompt 即可中等功能写一份简明 Spec1 页以内重点写清验收标准复杂系统/多人协作完整 SDD 流程Spec 纳入版本管理和 Code Review黄金法则Spec 的粒度应该匹配任务的复杂度十、未来展望10.1 从辅助到原生软件工程正在从AI-AssistedAI 辅助走向AI-NativeAI 原生。SDD 是这一转变的关键桥梁2023: AI 补全代码Copilot 时代 2024: AI 生成函数Chat 时代 2025: Vibe Coding凭感觉编程 2026: Spec-Driven Development规范驱动 ← 我们在这里 2027: Long-Running AgentsAI 自主交付10.2 Spec 即代码未来的趋势是Spec 本身成为源代码而 Python/Java/TypeScript 等具体实现只是 Spec 的编译产物“In this new world, maintaining software means evolving specifications. The lingua franca of development moves to a higher level, and code is the last-mile approach.”—— GitHub Spec Kit 团队10.3 开发者的角色演变过去开发者 写代码的人 现在开发者 定义 Spec 审查 AI 产出的人 未来开发者 系统意图的架构师 AI 团队的技术总监编码能力依然重要——你需要读懂 AI 生成的代码、判断架构决策的合理性、编写精确的 Spec。但你不再需要手动敲每一行代码。10.4 标准化趋势随着 SDD 工具的爆发行业正在走向标准化Spec 的格式和结构将逐步统一Spec 的验证和测试工具将成熟Spec 与 CI/CD 管道的集成将成为标配总结Spec-Driven Development 的本质是把软件工程中从意图到实现的鸿沟用一份结构化的规范文档填平。它不是一种新发明而是设计先行、契约优先这些经典工程思想在 AI 时代的自然演进。当 AI 成为主要的代码生产者人类的核心竞争力就从写代码转向了定义正确的规范。记住这句话输入质量决定输出质量。Spec 的质量直接决定了 AI 产出的质量。如果你还在用帮我写一个 XXX的方式和 AI 对话不妨试试先花 10 分钟写一份 Spec。你会发现AI 突然变得听话了。本文写于 2026 年 8 月。SDD 生态仍在快速演进中建议关注 GitHub Spec Kit、AWS Kiro 等项目的最新动态。参考资料GitHub Spec Kit 官方仓库Microsoft Developer Blog:Spec-Driven Development: A Spec-First Approach to AI-Native EngineeringThoughtworks Technology Podcast:What is Spec-Driven Development?AWS Kiro 官方文档

相关新闻

如何在VSCode中构建个人化的文本阅读工作流?Thief-Book插件深度解析

如何在VSCode中构建个人化的文本阅读工作流?Thief-Book插件深度解析

如何在VSCode中构建个人化的文本阅读工作流?Thief-Book插件深度解析 【免费下载链接】Thief-Book-VSCode VScode 上一款真正的摸鱼插件 项目地址: https://gitcode.com/gh_mirrors/th/Thief-Book-VSCode 作为一名开发者,你是否曾希望在长时间编码…

2026/10/14 22:32:42 阅读更多 →
从混乱文本到结构化信息:NLP技术如何精准提取娱乐内容中的实体与关系

从混乱文本到结构化信息:NLP技术如何精准提取娱乐内容中的实体与关系

1. 先搞清楚这个标题到底在说什么:从“咆哮”到“History”的现场教学 看到“张艺兴现场教学咆哮?啊不!History?!不知道了~啊啊啊~”这个标题,第一反应可能是困惑。这不像一个标准的…

2026/10/12 22:24:28 阅读更多 →
5 分钟上手幻兽帕鲁存档转换工具:palworld-save-tools 从备份到改档实战

5 分钟上手幻兽帕鲁存档转换工具:palworld-save-tools 从备份到改档实战

5 分钟上手幻兽帕鲁存档转换工具:palworld-save-tools 从备份到改档实战 【免费下载链接】palworld-save-tools Tools for converting Palworld .sav files to JSON and back 项目地址: https://gitcode.com/gh_mirrors/pa/palworld-save-tools 深夜&#xf…

2026/9/29 5:08:51 阅读更多 →

最新新闻

漏检后的现场重建:高可靠性系统的逆向工程能力

漏检后的现场重建:高可靠性系统的逆向工程能力

1. 项目概述:这不是故障排查,是现场重建“一次漏检之后,最难的是把现场找回来”——这句话在某高校实验室的故障复盘会上被反复提起,后来成了某跨平台系统运维组内部流传最广的一句行话。它不是形容设备坏了、日志丢了、配置错了&…

2026/10/14 22:33:00 阅读更多 →
贝塞尔曲线优化算法Matlab实操:从原理到代码详解

贝塞尔曲线优化算法Matlab实操:从原理到代码详解

这两年我一直在关注各类新型启发式优化算法,特别是那些能在Matlab里直接跑通的。原因很简单,工程上的优化问题大多等不起动辄几天的训练成本,也没必要把问题硬塞给那些只能处理特定格式的商用求解器。启发式方法依然是很多科研人员默认的兜底…

2026/10/14 22:33:00 阅读更多 →
AI自动建模工具实战:从数据到模型的可复现流水线

AI自动建模工具实战:从数据到模型的可复现流水线

简介:这份源码资源面向希望借助AI提升3D建模效率的开发者与设计爱好者,围绕Cursor客户端与BlenderMCP插件的协同方案,解决传统建模流程繁琐、上手门槛高的问题。资源包共3个文件,以inscode工程配置、html页面与gitignore忽略规则为…

2026/10/14 22:33:00 阅读更多 →
基于三菱FX系列PLC的超纯水系统一键制水与无人值守自动化方案

基于三菱FX系列PLC的超纯水系统一键制水与无人值守自动化方案

很多做水处理的同行跟我说,见过最多的控制系统就是“半自动”:手动开泵、手动开关阀、盯着液位去操作。碰上超纯水这种对水质和连续性要求比较高的系统,人一离开就容易出事——过滤器反洗不及时导致压差升高、RO膜结垢、产水电导率超标&#…

2026/10/14 22:33:00 阅读更多 →
SonarQube 8.3.1 + PostgreSQL 9.6 企业级稳定部署指南

SonarQube 8.3.1 + PostgreSQL 9.6 企业级稳定部署指南

1. 为什么是 SonarQube 8.3.1 PostgreSQL 9.6 这个组合?——被忽略的兼容性断层很多人第一次搭 SonarQube,直接去官网下载最新版,配个 Docker 一键拉起,跑通 Demo 就以为万事大吉。但真正在企业级 Java 或 .NET 项目里落地时&…

2026/10/14 22:33:00 阅读更多 →
700个AI代理同时越界事故复盘:多代理权限治理与安全边界设计指南

700个AI代理同时越界事故复盘:多代理权限治理与安全边界设计指南

1. 一次实际推演里的事故:七百个代理同时“越线”的现场回放我很少用“事故”来形容一次测试演练,但如果你在推演现场盯着监控屏,看到原本各自忙碌的七百个代理突然开始绕过预设规则执行任务,在日志里疯狂打出同一类越权告警时&am…

2026/10/14 22:31:59 阅读更多 →

日新闻

AnyPS5通用适配层设计:兼容性与性能的工程取舍

AnyPS5通用适配层设计:兼容性与性能的工程取舍

1. 从"AnyPS5"这个名字说起:它到底想解决什么问题第一次看到"AnyPS5"这个标题,我脑子里冒出来的第一个念头是:这大概率是一个围绕"跨平台运行"或者"通用适配"做文章的项目。名字里的"Any"…

2026/10/14 0:00:41 阅读更多 →
Flutter跨平台开发实战:二手交易应用与HarmonyOS适配

Flutter跨平台开发实战:二手交易应用与HarmonyOS适配

1. 项目概述:Flutter跨平台二手交易应用开发作为一名长期从事移动应用开发的工程师,我最近完成了一个基于Flutter框架的二手物品交易平台项目。这个项目最吸引我的地方在于它完美结合了Flutter的跨平台优势与HarmonyOS的生态特性,实现了"…

2026/10/14 0:00:41 阅读更多 →
DFS算法解决飞机降落调度问题实战

DFS算法解决飞机降落调度问题实战

1. 项目背景与核心思路飞机降落问题是一个经典的调度优化场景,也是算法竞赛和面试中的高频题目。这个题目要求我们合理安排多架飞机的降落顺序和时间,确保所有飞机都能安全着陆而不发生冲突。在实际航空管制中,这类问题直接关系到飞行安全和机…

2026/10/14 0:00:41 阅读更多 →

周新闻

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

简介:基于 ARIMA、LSTM、Transformer 等模型的流感时间序列预测 Python 源码,面向计算机相关专业课程设计与期末大作业学生,以及项目实战学习者。内容覆盖预处理、平稳性检验、定阶、残差分析、多模型对比预测的完整时序建模流程,…

2026/10/14 3:30:28 阅读更多 →
影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别 做影刀RPA自动化,十个新手有八个栽在"往输入框里填东西"这件事上:要么填不进去,要么填了一半,要么直接把原来内容追加在后面。这背后的根因&…

2026/10/14 16:30:29 阅读更多 →
影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容 1. 认识影刀:什么场景该用RPA采小说数据 起点中文网的页面结构相对稳定——分类榜单、书籍详情、章节内容三块独立页面,跳转链路清晰。这种场景非常适合影刀自动化&#x…

2026/10/14 3:29:58 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

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

2026/10/13 22:01:27 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

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

2026/10/13 14:57:39 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

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

2026/10/14 7:53:34 阅读更多 →