AiReadCode:让代码库自动变成一本可读的书
代码读不完这是所有想深入源码的开发者都会遇到的事。我花了一段时间完整读透了 Spring AI Alibaba 这个开源框架的源码读完之后最大的收获不是搞懂了某个调用链而是意识到源码阅读的产出方式有很大问题。零散笔记、IDE结构树、随手画的依赖图都很难帮你形成一个完整的“知识体系”。所以我写了 AiReadCode——一个把代码库自动整理成“一本书”的工具。它的核心思路很简单先让机器从代码里提取结构再用语义分析把散落的类和方法编排成章节最后生成一份像书一样可顺序阅读的Markdown文档。这篇文章会把整个项目的设计思路、关键实现、实操步骤和踩坑过程完整拆开来讲适合想深度阅读开源框架、接手老项目、以及做代码资产沉淀的开发者参考。1. 为什么我会想到把代码库“变成一本书”1.1 源码阅读的碎片化困境读源码和读技术书是完全不同的体验。技术书由作者帮你设计好了阅读路径先讲整体架构再讲核心概念最后给实战案例。而源码是一个树状结构摆在你面前的是几十个包、几百个类、上千个方法没有任何人告诉你应该按什么顺序读。我读 Spring AI Alibaba 的时候有个很直观的感受点进一个方法追了三层调用之后已经忘了自己是从哪个入口进来的。IDE的Structure面板只能展示当前类的成员Call Hierarchy能画出调用链但如果你没有一个全局地图这些功能反而会让你越陷越深。更让人头大的是代码注释少得可怜核心类里往往只有几个英文注释业务语义需要靠猜。这种碎片化阅读带来的后果是你好像读了很多文件但过两周别人问你“这个框架的消息处理链路是怎样的”你只能说出几个类名讲不清整体脉络。我看完整个框架后决定不再写零散的源码笔记而是想找一个办法把整个代码库的阅读过程“书籍化”——有目录、有章节递进、有上下文铺垫。找了一圈没有合适的工具于是决定自己写一个。1.2 市面上的工具差在哪里做这个项目之前我先盘点了一下已有的方案。IDE自带的结构分析工具本质上是一个“零件拆解器”。它能告诉你某个类继承谁、引用了谁、方法签名是什么但它不会告诉你这些类在一块儿到底完成了什么业务。就好比你拆了一台发动机把所有螺丝和活塞摆在桌上但这不等于你理解了这个发动机的设计哲学。JavaDoc这类注释生成工具也是同理它只负责把注释提取成网页不解决阅读顺序和知识编排问题。也考虑过直接用大模型输入整个仓库让它总结试过之后发现问题很明显上下文窗口不够覆盖一个大中型项目而且让模型“线性读”上万个文件它根本抓不住调用关系生成的内容到处是硬伤目录也经常是编造出来的。一句话总结就是这些工具只提供了“零件”却没有提供“装配说明”。AiReadCode要做的是把“零件”先分析清楚再把它们装配成一本可读的“书”。这也是它和普通文档生成工具的本质区别——编排优先于生成。1.3 项目定位与适用场景AiReadCode 的定位不是替代IDE也不是替代代码搜索工具而是填补源码阅读场景里“全局阅读文档”这个空缺。它能自动扫描一个代码库分析模块之间的依赖关系抽取核心类与公开方法再借助语言模型的语义理解生成模块摘要最后按照入口类到扩展点的路径组织成一本分章节的书。这个东西对三类人特别有用。第一类是读开源框架源码的人拿到一个新项目跑一下工具先看目录再按章节精读效率会高很多。第二类是刚接手老项目的开发者面对一个历史包袱很重的系统与其在IDE里迷路不如先让工具产出一份结构清晰的“系统说明书”。第三类是技术管理者需要给团队新人提供代码库阅读指引工具生成的结果加人工校对就是一个很好的培训文档。2. 核心设计从“搜集信息”到“编排知识”2.1 四个核心模块AiReadCode 的整体结构分为四层扫描层、解析层、分析层、编排层。每层只负责一件事输出物是下一层的输入这个边界我一开始就定死了。扫描层负责遍历文件生成文件清单过滤掉测试、构建产物和资源文件。解析层使用语法分析器读取每个源文件的抽象语法树提取类、方法、字段、接口实现、注解和调用关系。分析层会构建全局依赖图并且调用语言模型给每个模块生成语义摘要。编排层则把这些分析结果按照“阅读路径”组装成章、节、小节最终渲染成Markdown文档。模块职责关键输出scanner递归遍历文件过滤无用目录文件清单、语言类型parser语法分析提取代码符号AST、符号表、调用关系analyzer依赖分析、语义聚类、摘要生成模块依赖图、语义标签composer章节编排、阅读路径规划书目结构、渲染文档模块边界清晰以后每一层都可以独立替换。比如解析层如果遇到不支持的语法可以换成其他解析器分析层的模型可以接远程API也可以接本地模型。2.2 解析层让机器先读懂代码结构解析层是整个项目里最容易“翻车”的地方。最开始的版本我用正则表达式去匹配类名和方法名看起来能对付简单场景但一遇到泛型、嵌套类、注解参数、内部类就直接崩溃。正则最大的问题是它不理解代码的“含义”。比如注释里面出现了class Foo这样的字符串正则就会误判再比如同一个方法有多个重载版本正则很难一一对应。后来我换成了基于语法树解析的方案。语法树把源码解析成结构化节点每个类、方法、字段、表达式都有明确的类型和层级关系。解析完之后我会生成三类核心数据符号表、调用关系表和继承关系表。符号表记录每个类包含的方法、字段、可见性和注解调用关系表记录方法之间的引用这是后面分析依赖和阅读路径的基础继承关系表记录接口实现和类继承这能帮助分析框架的扩展点。这里必须说一下为什么要花这么大力气做结构解析。因为后面所有“像书一样”的特性都依赖这套结构。没有准确的调用关系你就无法判断一个类在整个项目里处于什么位置没有符号表你就无法自动生成漂亮的API说明列表。这一步做得越扎实后面的编排就越省力。2.3 关系与语义层两路信号决定章节一个代码库里包含上千个类怎么决定谁该放在第几章、谁和谁该归到同一节我用了两路信号。第一路是硬信号来自依赖分析。扫描完成后分析层会计算每个类被谁引用以及它引用了谁。一个类如果被大量外部类引用说明它是核心类应该靠近章节开头一个类如果依赖了很多其他类说明它是业务流程的汇聚点适合作为章节入口。根据这些依赖关系我会计算每个类的“重要度分”。第二路是软信号来自语义分析。结构上相似的类不一定属于同一个业务模块比如都是配置项类但一个负责数据库、一个负责消息队列。所以我让语言模型为每个包或模块生成语义描述再对语义描述做向量化聚类。这个步骤的核心目的是把传统静态分析看不出来的主题找出来。对于一个AI框架来说模型加载、Prompt组装、工具调用、结果解析这些主题横跨多个包纯靠依赖关系是切不出来的。最终章节归属是两路信号合在一起决定的语义聚类决定大类依赖关系决定类与类之间的先后顺序。这样分出来的章节既有业务主题又有代码层面的递进感。2.4 编排层把类当“段落”把包当“章节”编排层负责把分析结果变成书的结构。我定义了一套比较通用的映射规则。项目顶层模块映射为“章”比如在 Spring AI Alibaba 里核心的模型定义、工具调用、自动配置这些顶层模块分别就会成为第一章、第二章、第三章。每个顶层模块下面的子包映射为“节”子包里的核心类映射为“小节”小节内部再细分类职责、关键字段、公开方法、调用关系、典型使用链路。一个典型章节内部的排列规则是先放模块整体说明再放入口类和配置类接着按调用深度一层层展开实现类最后把扩展点和SPI接口统一放到章末。这样读起来就像一本书先知道这章讲什么再看到一个完整例子然后深入细节最后了解怎么扩展。为什么选Markdown而不是直接生成网页或者PDF原因很实际Markdown可以进Git仓库做版本管理团队协作时diff非常清楚同时可以二次编辑AI生成的内容虽然准确率高但仍需要人工修正Markdown是门槛最低的编辑格式最后它还能很方便地导出成PDF、EPUB或者直接发布到内部知识库。3. 实操跑通一次完整的“代码成书”3.1 环境准备工具我打包成了命令行程序依赖项不大。运行环境需要 Python 3.9 以上因为解析层用了一个开源的语法分析库需要本地编译。如果你的代码库是Java或Kotlin项目建议本机装了对应语言的JDK因为某些特殊语法需要用到编译信息辅助。语言模型这一层我设计成可插拔的远程API和本地模型都行。远程的话用OpenAI兼容接口配置一个环境变量保存密钥本地的话可以用部署在GPU机器上的量化模型只是生成摘要的速度会慢一些但对小仓库来说完全能接受。我推荐至少 8GB 内存的机器扫描和解析阶段会占用比较多资源。实际压测一个包含几百个Java文件的仓库解析阶段内存占用差不多在 2GB 左右普通开发机能扛住。3.2 三步命令完成生成AiReadCode 的操作流程非常短核心只有三条命令。以阅读 Spring AI Alibaba 源码为例# 第一步扫描代码库生成文件清单和基础结构信息 aireadcode scan --path ./spring-ai-alibaba # 第二步解析依赖、生成摘要、完成章节编排 aireadcode build --config aireadcode.yaml # 第三步渲染成Markdown文档 aireadcode render --format markdown --out ./book第一步只做扫描速度很快几秒钟就能完成它会生成一个index.json文件里面是所有需要分析的源码文件列表。我建议你先跑一步看输出如果发现过滤规则不对调整配置再扫一次。第二步是核心也是耗时最长的一步。它要完成语法解析、依赖分析、调用大模型生成摘要、语义聚类、章节编排这一整套流程。它会读入上一步生成的index.json结合配置文件里的参数最终输出一本书的结构数据。第三步是纯粹的渲染把第二步生成的结构数据变成可读的Markdown。如果你愿意也可以扩展成HTML或者PDF渲染器这个后面说。3.3 配置文件的重点参数aireadcode build需要的配置文件是aireadcode.yaml下面是我用的一个比较有代表性的配置project: name: spring-ai-alibaba entryPoints: [SpringAIApplication] parser: maxFileSize: 512KB ignore: - **/test/** - **/target/** - **/generated/** analyzer: minClusterSize: 5 similarityThreshold: 0.75 composer: maxDepth: 4 includeApiDoc: true includeCallGraph: false llm: provider: openai-compatible model: qwen-plus baseUrl: apiKeyEnv: LLM_API_KEY几个重点参数说一下。parser.ignore决定哪些文件不进入分析。测试目录、构建产物目录必须过滤掉否则模型会把单元测试当成核心逻辑来总结整本书的可读性会严重下降。composer.maxDepth控制目录嵌套深度我实测默认4级就够了太深会让人觉得像看天书太浅则无法反映真实结构。analyzer.similarityThreshold是语义聚类的阈值调高会让章节分得更碎调低会把不相关的类硬凑到一章。includeCallGraph建议默认关闭因为对大多数框架来说核心类的调用关系应该在正文里用文字串联说明而不是丢出一张巨大的图。注意llm.apiKeyEnv是指定从环境变量里读取密钥而不是直接在配置文件里写密钥。这一点很重要因为这份配置最终是要提交到Git仓库的密钥写进去就麻烦了。3.4 生成结果示例拿 Spring AI Alibaba 的某个核心模块做实验生成出来的书结构大概是这样的第一章 项目总体概览 1.1 项目背景与模块地图 1.2 入口类与启动流程 1.3 配置项总表 第二章 核心模型抽象 2.1 模型接口体系 2.2 内置模型实现 2.3 模型工厂与构建链路 第三章 消息解析与工具调用 3.1 消息结构定义 3.2 工具注册与调用流程 3.3 流式响应处理 第四章 自动配置与扩展点 4.1 自动配置类解析 4.2 自定义扩展接口 4.3 SPI加载机制这个结构已经非常接近一本技术书的目录了。第一章先让读者建立整体印象第二章从核心模型讲起第三章进入具体业务链路第四章讲扩展。读的人可以顺着章节从前往后读有基础的人也能直接跳到第四章去看扩展点。生成结果的每一个小节里还会自动附带“本节涉及的核心类清单”和“阅读提示”这些都是从依赖关系里自动推导出来的不是AI编的。4. 常见问题与排查技巧4.1 解析失败导致漏类我在测试阶段遇到过不少解析失败的情况。最常见的是项目里用了 Lombok解析器拿到的源码里只有Getter和Setter注解没有实际的getXxx()方法。如果直接分析API文档里会漏掉一大批方法而且调用关系也会断掉。我的解决办法是分两步走第一步用源码解析器生成结构树第二步启动时读取编译后的字节码信息做一次补充索引把 Lombok 生成的方法、注解处理器生成的代码都补进去。如果你只是想快速生成一本书不要求100%准确可以跳过第二步但要接受API文档不够完整的问题。还有一个快速排查技巧解析完成后检查符号表里类的数量和IDE里显示的类数量对比一下差距超过10%就说明有解析失败的情况。4.2 依赖闭环导致章节顺序混乱代码库里经常存在两个包互相调用的现象。比如配置模块引用了核心模块核心模块又回过来引用配置模块的某个工具类这在真实项目里很常见。如果按照依赖关系决定阅读顺序就会陷入“先读A又必须先读B”的死循环编排逻辑会报错。我的做法是引入依赖方向惩罚机制跨包引用会降低排序权重同包内的引用则维持原权重。这样即使两个包存在循环依赖按聚合程度强的包优先分组也能排出一个相对合理的阅读顺序。另外我在配置里留了一个手动固定的输入项你可以指定某一个包必须先于另一个包出现工具会在编排时强制执行保证不能被AI带偏。4.3 AI摘要说胡话为了让每一章开篇有介绍我调用了语言模型生成模块摘要。但模型在上下文不够完整的时候会“脑补”。有一次它把一个配置类的摘要写成“负责处理用户请求”实际上这个类只负责绑定配置项。这种错误对读者很有误导性。后来我做了三件事来规避。第一给模型的提示词里加上了约束只基于提供的类和符号信息进行概括不允许补充源码之外的内容。第二先把类的签名、注释、主要方法提取出来做成“资料包”再喂给模型而不是让它直接读源码文件这样能减少无关信息干扰。第三对模型生成的摘要做置信度打分分数低于一定阈值时在这个小节里标注“AI生成摘要待人工确认”并且把原始类的源码片段附在后面让读者自己判断。4.4 大仓库处理太慢跑一个上百MB代码仓的大仓库时解析加摘要可能要十几分钟。这里有两个加速技巧比较实用。第一个是利用构建工具生成的依赖树比如 Java 项目可以用dependency:tree导出依赖关系这些信息可以直接作为分析层的输入省得自己再去解析构建文件。第二个是给AI摘要加缓存同一个类的摘要不要重复生成增量更新时只处理变化过的文件这个优化对持续更新知识库的场景帮助很大。还有一个很多人会忽略的点扫描阶段默认会进入node_modules或者venv这种目录如果不提前过滤会极其耗时。配置文件里的ignore规则一定要把依赖目录写进去我甚至建议在扫描之前先用命令行工具看一眼哪个目录最占体积再决定怎么过滤。4.5 生成“书”的阅读体验优化最后说两个提升成书质量的细节。一个是入口类识别很多项目有多个启动入口比如命令行工具和应用服务这时工具生成的章节开头可能会混乱。我建议在entryPoints里明确列出来工具会在第一章把它们放到所有内容前面。另一个是“API速查表”开关在includeApiDoc开启的状态下每个章节最后会生成一张方法签名速查表表里包含返回值、参数列表和简要说明这个表对快速索引API非常有用但对纯业务逻辑的代码库价值不大可以按需开关。我在实际使用中最大的体会是这个工具不是用来替代人工阅读的而是把阅读变成“先读目录、再读重点、最后按需深入”的高效过程。读完输出的几十章内容我对整个框架的模块边界、核心链路和扩展方式有了清晰的认知这在以前靠纯手工读源码基本不可能做到。后面我还打算让它支持增量更新、导出EPUB电子书、以及接入更多语言的解析器让“把代码库变成一本书”这件事真正成为开发者日常沉淀知识的标准动作。

相关新闻

文本匹配算法实践:单塔与双塔模型对比及训练技巧

文本匹配算法实践:单塔与双塔模型对比及训练技巧

简介:面向文本匹配算法学习与毕业设计场景的 Python 工程,完整实现 PointWise(单塔)、DSSM(双塔)、Sentence BERT(双塔)三种主流模型,并配套商品评论与商品类别匹配数据集…

2026/10/18 10:16:41 阅读更多 →
git bisect 实战:用二分查找快速定位回归 bug

git bisect 实战:用二分查找快速定位回归 bug

上周我在一个维护了很久的“某老项目”里追一个诡异的回归bug:头天晚上发版前还好好的,第二天一上班,同事就跑来说某个核心接口直接崩了。git log一看,从上次稳定到崩掉之间有三十多个提交。按我以前的习惯,肯定是倒着…

2026/10/18 10:16:41 阅读更多 →
摩天大楼电梯仿真:从建模到调度的完整实践指南

摩天大楼电梯仿真:从建模到调度的完整实践指南

简介:基于Java实现的摩天大楼电梯类型与调度算法仿真项目,模拟真实电梯运行,覆盖单向、双向、观光、高速、消防等电梯建模,并实现FCFS、最近楼层优先、最少行程时间、预调度和群控算法。通过随机生成乘客流量,可对比不…

2026/10/18 10:15:41 阅读更多 →

最新新闻

从AI算力标杆项目看智算交付:训练集群与推理平台的工程能力

从AI算力标杆项目看智算交付:训练集群与推理平台的工程能力

某智能计算技术服务商一口气拿下两个AI算力标杆项目的中标消息,这两天在我们这个圈子里讨论度不低。做智算基础设施几年下来,我的第一反应不是去猜合同金额,而是想拆解一件事:这种“AI算力标杆项目”到底在采购什么。表面看是加速…

2026/10/18 10:50:51 阅读更多 →
可重构MIMO性能增益理论分析:毫米波稀疏信道下的容量推导与仿真复现

可重构MIMO性能增益理论分析:毫米波稀疏信道下的容量推导与仿真复现

1. 从标题拆解可重构MIMO的真实研究边界 第一次看到“可重构MIMO性能增益理论分析”这个标题,很多人会下意识觉得这又是一篇堆公式的纯理论文章。但真正读过这类文献的人会知道,标题里每一个词都对应着具体的工程约束和设计取舍。我打算把这篇阅读笔记背…

2026/10/18 10:50:51 阅读更多 →
综合能源系统优化调度实战:Cplex求解冷热电联供与碳交易模型

综合能源系统优化调度实战:Cplex求解冷热电联供与碳交易模型

做综合能源系统优化的朋友,对这个方向肯定不陌生。冷、热、电、气四类能量在园区或建筑层面耦合起来,燃气轮机发电、余热回收制冷制热、不足的部分用电或燃气补充,再叠加上需求响应和碳交易这两个市场化机制——这基本就是当前综合能源系统优…

2026/10/18 10:50:51 阅读更多 →
SSM校园点餐系统本地部署与权限状态机实战指南

SSM校园点餐系统本地部署与权限状态机实战指南

简介:这是一套基于SSM框架开发的校园在线点餐系统完整源码,面向Java初学者与Web开发入门者,适用于课程设计、毕业设计及小型校园O2O项目实践。系统采用前后端分离式结构,前台支持用户注册登录、购物车、订单管理与资讯浏览&#x…

2026/10/18 10:50:51 阅读更多 →
UE4渲染源管理实战:RenderTarget与SceneCapture的坑与解法

UE4渲染源管理实战:RenderTarget与SceneCapture的坑与解法

很多做UE4开发的朋友应该都有过这样的经历:辛辛苦苦搭好场景,最后卡在了“怎么把画面干净地取出来”这一步。无论是做分屏、做小地图、做屏幕后处理、做远程像素流,还是给外部程序提供视频源,本质上都在做同一件事——管理RenderS…

2026/10/18 10:50:51 阅读更多 →
光伏电站灰损治理:轨道式智能清洁机器人全栈方案

光伏电站灰损治理:轨道式智能清洁机器人全栈方案

做光伏电站的人都知道组件脏了要洗,但真正把“灰尘偷走多少度电”这笔账算清楚的人不多。业内把灰尘遮挡组件导致的发电损失叫“灰损”,听着专业,本质很简单:组件表面被蒙上一层灰,光线进不去,电池片出力直…

2026/10/18 10:49:51 阅读更多 →

日新闻

基于GMM的语音识别系统原理与MATLAB实现详解

基于GMM的语音识别系统原理与MATLAB实现详解

说到基于高斯混合模型(GMM)的语音识别系统,很多人第一反应就是一堆数学公式,觉得门槛很高。但如果你真的在MATLAB里把它落地跑通,会发现核心其实就是三件事:把声音变成特征向量,用GMM给每个类别…

2026/10/18 0:00:55 阅读更多 →
数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理这四个字听起来挺唬人,但落到具体操作上,无非就是让计算机按你的想法“摆弄”像素。我在一个模拟项目X里用了一套特别经典的基础处理流程:对图像做反白、改调色板、彩色转灰度,最后把像素数据导出成txt文件。单看每一…

2026/10/18 0:00:55 阅读更多 →
机器人大脑技术盘点:具身智能的感知、决策与数据闭环

机器人大脑技术盘点:具身智能的感知、决策与数据闭环

如果你的信息流最近也天天刷到“机器人大脑”这个词,你会发现一个很有意思的现象:每个人说的“大脑”根本不是同一个东西。有人指的是大语言模型,有人指的是运动控制系统,还有人指的是能理解物理世界的端到端模型。在2026年这个时…

2026/10/18 0:00:55 阅读更多 →

周新闻

基于GMM的语音识别系统原理与MATLAB实现详解

基于GMM的语音识别系统原理与MATLAB实现详解

说到基于高斯混合模型(GMM)的语音识别系统,很多人第一反应就是一堆数学公式,觉得门槛很高。但如果你真的在MATLAB里把它落地跑通,会发现核心其实就是三件事:把声音变成特征向量,用GMM给每个类别…

2026/10/18 0:00:55 阅读更多 →
数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理这四个字听起来挺唬人,但落到具体操作上,无非就是让计算机按你的想法“摆弄”像素。我在一个模拟项目X里用了一套特别经典的基础处理流程:对图像做反白、改调色板、彩色转灰度,最后把像素数据导出成txt文件。单看每一…

2026/10/18 0:00:55 阅读更多 →
机器人大脑技术盘点:具身智能的感知、决策与数据闭环

机器人大脑技术盘点:具身智能的感知、决策与数据闭环

如果你的信息流最近也天天刷到“机器人大脑”这个词,你会发现一个很有意思的现象:每个人说的“大脑”根本不是同一个东西。有人指的是大语言模型,有人指的是运动控制系统,还有人指的是能理解物理世界的端到端模型。在2026年这个时…

2026/10/18 0:00:55 阅读更多 →

月新闻

我发现了一个新思路:用 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/18 0:55:02 阅读更多 →
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/17 17:22:31 阅读更多 →
黑夜航拍船只数据集训练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/16 14:23:36 阅读更多 →