news 2026/9/7 4:07:56

192KB轻量文件管理工具:不打包编译器,回归Unix一切皆文件哲学

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
192KB轻量文件管理工具:不打包编译器,回归Unix一切皆文件哲学

今天想和大家聊一个自己觉得很“反潮流”的小工具。以前我们总觉得,开发工具应当越来越强、越来越大,装上之后什么都能干。但用久了你就发现,很多时候你想做的事情其实非常简单——找一个配置文件,改一行参数,在某个目录下面批量重命名一批备份文件——结果却必须先启动一个几百 MB 的应用,等它加载一堆插件,然后才轮到真正动手。

这个工具把场景反过来:它只有 192KB,不做代码提示,不管编译,不打包任何编译器,甚至连一个图形界面都不强求,只把“文件管理”这一件事做到位。它的设计理念,是延续 Unix 系统里那个经典的抽象——一切皆文件

我的基本判断是,这类轻量工具的价值不在于“大而全”,而在于它为你重新留出了选择的自由:它知道编译器是编译器的事,文件管理是文件管理的事,两者通过一条简单的配置即可协作。这篇文章会系统梳理这个工具的设计思路、安装方式、核心用法、与编译器的协作方法,以及常见问题的排查路径。读完你可以判断它适不适合进入你的工作流,也可以直接上手体验。

1. 这篇文章真正要解决的问题

如果你平时的工作流是“打开 IDE → 建项目 → 写代码 → 跑测试”,那这个 192KB 的工具对你来说可能不是必需品。但如果你经常面临下面这几种场景,它可能正好补上你工具箱里的一块拼图。

第一种场景是“只想改个文件,结果要养一个重型应用”。比如线上服务器出了个问题,你 SSH 上去,想快速看一眼/etc/nginx/nginx.conf最近有没有人改过,或者/var/log/app/下面哪些日志文件今天增长最快。你需要的只是定位、查看、过滤、统计。这时候你会发现,图形化文件管理器和庞大的 IDE 都用不上,能用的反而是终端里一个足够快的文件浏览命令。

第二种场景是“工具链之间互相打架”。很多开发工具为了做到开箱即用,会捆绑自己的编译器、语言服务、依赖解析器。好处是用户不用额外安装,坏处是一旦项目里已经有一套系统级的 GCC、Clang 或者 Makefile,两套环境很容易产生版本冲突。尤其是做嵌入式开发、内核模块、C/C++ 交叉编译的朋友,对这类问题应该深有体会。

第三种场景是“文件管理这个需求被严重高估了复杂度”。文件管理的本质是什么?是找到文件、查看文件、移动文件、批量处理文件。它不一定要和代码编辑、版本控制、远程部署全部揉在一起。工具越专注于一个边界,使用起来就越不容易出意外。

围绕这几种场景,这个 192KB 文件管理工具给出了自己的答案:

  • 不打包编译器,意味着即使你系统里装的是 GCC 12 或 Clang 16,也不会因为用了这个工具而被强行走另一套编译工具链。
  • 一切皆文件,意味着文件、目录、设备、甚至是进程信息,都可以用同一套文件操作的心智模型去理解。
  • 体积小,意味着分发简单、启动快、依赖少,尤其适合放到 U 盘或者服务器上应急使用。

直接说结论:这个工具适合三类人——长期在终端下工作的开发者、需要频繁管理远程服务器文件的运维人员,以及那些不想再为一个简单文件操作而启动重型应用的“效率控”。如果你不在这些场景里,也不必勉强,但它的设计思路仍然值得读下去。

2. 基础概念与核心原理

2.1 什么是“一切皆文件”

“一切皆文件”是 Unix 设计哲学里最核心的一句话。它并不是说计算机里所有的东西都像 Word 文档一样,而是说:操作系统向用户暴露资源时,统一提供了“打开、读、写、关闭”这套文件接口

比如在/dev目录下,磁盘、鼠标、键盘这些硬件设备都对应一个设备文件。在/proc目录下,CPU、内存、内核参数都以文件的形式呈现。你可以用一条cat /proc/cpuinfo命令,像读普通文本文件一样读取 CPU 信息。Socket、管道、标准输入输出也是文件,命令行里的重定向与管道,本质上是把文件描述符连接起来。

这个抽象带来的最大好处是接口统一。程序不需要针对每种资源单独实现一套 API,只要学会操作文件,也就学会了访问大多数系统资源。文件管理工具继承了这个传统:它管理的对象不只是普通文件和目录,还可能包括挂载点、符号链接、隐藏文件,以及与系统设备关联的虚拟文件。

2.2 “不打包编译器”到底意味着什么

很多现代开发工具选择把编译器、运行时、构建工具链全部内置,这样用户“下载即用”,体验确实很顺滑。但代价也很明显:安装包体积从几十 MB 涨到几百 MB,甚至超过一个大型应用;工具链的版本被绑定在发布版本里,用户很难单独升级编译器;一旦项目需要交叉编译或者特殊参数,内置工具链往往不够灵活。

这个 192KB 工具选择了一种更老的、也更 Unix 的做法:自己不做编译器,只负责把“命令”交还给系统。它不会在安装包里塞一个 GCC 或 Clang,而是当你需要编译时,在配置文件里指定要执行的命令,比如gcc main.c -o app,工具负责调用系统中已有的编译器,并把输出回显给你。

这样处理有三个看得见的好处:

  • 工具本身的体积保持在 192KB 左右的量级,不会因为捆绑工具链而膨胀。
  • 编译器的选择权始终在你的手里,你可以用系统 GCC、也可以用自定义路径下的交叉编译器。
  • 工具和编译环境之间通过“命令字符串”协作,不存在二进制层面的绑定关系,因此也不会把编译环境的脏数据带进来。

换句话说,这个工具对你编译能力的要求是:系统里已经有一个能用的编译器,并且它已经加入了 PATH 环境变量。如果你连这一步都没有,那问题不是工具不好用,而是编译链路本身还没有准备好。

2.3 192KB 这个数字为什么值得关注

现代软件动辄就是几百 MB 的安装包,一个安装包小于 1MB 反而显得很反常。这正是它的价值所在。下表可以直观对比一下常见开发工具与这个工具的体积差异:

工具/软件安装包/占用体积量级核心定位
本工具约 192KB终端文件管理,不捆绑编译器
传统文本编辑器 Vim1~2MB终端文本编辑
常见轻量级 IDE100MB 以上代码编辑、语言服务、调试
大型集成开发环境几百 MB 到几 GB全功能开发平台
现代办公套件数 GB文档、表格、演示

从这个表能看出,192KB 属于“工具链里可以被忽略的那一类体积”。它的意义不只是省了几十兆磁盘空间,更在于:当软件体量足够小时,用户可以在一分钟内完成下载和部署,可以把工具装进 Git 仓库,甚至可以直接读源码确认它的行为。

如果要在工程层面上给出一个合理的猜测,这个工具很可能采用了静态编译、未捆绑运行时、并且没有引入图形界面渲染引擎。所以它的体积才能压缩到这种量级。具体实现方式需要看官方发布说明,但方向是明确的:它把预算全部花在了文件管理本身。

3. 环境准备与前置条件

这个工具的定位是轻量、可移植,所以环境准备并不复杂。但为了让文章里的示例命令能直接跑通,有必要先确认几项基础条件。

操作系统

从设计理念和“一切皆文件”的典型使用场景来看,这个工具大概率是为类 Unix 系统准备的。也就是说:

  • Linux 发行版,如 Ubuntu、Debian、CentOS、Rocky Linux、Arch Linux,会是最自然的运行环境。
  • macOS 也属于类 Unix 系统,理论上可以使用,具体兼容性需要参考项目发布说明。
  • Windows 原生环境下,如果工具没有提供 Windows 版本,可以借助 WSL(Windows Subsystem for Linux)来运行,或者确认项目是否发布了原生 Windows 二进制。不要盲目假设它一定支持 Windows。

终端环境

工具以命令行为主,那么一个正常工作的终端模拟器是必须的。这里要避免一个误区:你没有必要为了使用它去安装某个特定终端。Windows Terminal、GNOME Terminal、iTerm2、PuTTY 风格的 SSH 客户端,只要能把标准输入输出正确传给程序,基本都可以用。

编译器

工具本身不打包编译器,但如果你希望它帮你执行编译任务,那么系统 PATH 环境变量里需要存在可用的编译器。例如:

  • 查看 GCC 版本:
    gcc --version
  • 查看 Clang 版本:
    clang --version
  • 检查 make 是否存在:
    make --version

如果这些命令都提示“command not found”,说明编译工具链还没有安装。以 Ubuntu 为例,安装基础编译工具的命令是:

sudo apt update sudo apt install build-essential

需要说明的是,版本请以实际项目为准,本文重点演示通用思路,不绑定特定编译器版本号。

4. 核心功能与设计思路

这个工具的功能边界非常清楚:管理文件,而不是管理整个开发过程。基于这个前提,它应该覆盖下面这些核心能力。

4.1 文件浏览与快速定位

在终端下查看目录内容,常见的方式是lscd。它们很好用,但在目录层级很深、文件数量很大的场景下,效率会明显下降。这个工具要解决的第一个问题,就是让“找文件”这个动作更快

你可以把它理解成一种“终端下的资源管理器”:它以目录为单位展示文件列表,支持键盘快捷键进入子目录、返回上级目录,同时显示文件大小、修改时间、权限信息。但它不打算替代 Vim 或 VS Code,它只负责让你在几个目录之间快速跳转。

4.2 文件搜索与过滤

如果只是浏览,那和ls -R没有本质区别。真正拉开差距的是搜索与过滤

一个典型的场景是:你在一个大型前端项目里,想找出所有测试文件里包含“TODO”注释的代码片段。传统做法是用grep -rn "TODO" test/,但如果你已经在这个文件管理工具中定位到了test/目录,直接输入过滤条件,工具会基于当前目录树做匹配,效果更直观。

在“一切皆文件”的思路下,搜索不限于文件名,还可以计算目录占用空间、按扩展名分类、找出最近一天修改过的文件。这些能力本质上都是对“文件视图”做筛选,而不是真正改动文件本身。

4.3 文件操作:复制、移动、重命名、删除

这是任何文件管理工具都不能缺失的部分。需要注意的是,命令行工具的删除操作大多没有回收站概念。即使工具提供了确认交互,误删依然是实际使用中的最高风险之一。这个工具的设计文档如果没有特别说明“可恢复”,你就应该默认删除是不可逆的。

在工程实践中,批量重命名是一个很常见的需求。比如一批日志文件的命名格式需要从20240101.log改成app-20240101.log,手写 Shell 循环也可以做,但在可视化目录视图里确认目标文件列表会更安全。工具是否支持这种“先选择,后操作”的模式,是判断它设计成熟度的一个关键指标。

4.4 视图与定制

文件管理不只是“看到一个列表”。好的工具至少应该支持:

  • 显示或隐藏隐藏文件。
  • 按名称、修改时间、大小排序。
  • 分页展示,避免一次性输出过多内容。
  • 自定义默认启动目录。
  • 自定义快捷键。

这些不复杂,但决定了工具是否真的适合日常使用。如果配置项太过简陋,使用者很快会回到lscdfind的老路上。

4.5 调用外部命令

这是“不打包编译器”理念的自然延伸。工具本身不做编译,但它要能方便地调用系统命令。最简单的形态是:在工具界面里按下一个按键,输入一条命令,工具把命令交给系统 Shell 执行,并显示结果。更高级的形态是,用户可以为常用操作预设命令别名,比如按F5执行“编译当前目录下的 C 文件”。

这里有一个非常重要的安全边界:工具执行外部命令时,本质上是把终端权限交给了命令字符串。如果你让它执行rm -rf /,它真的会执行。让工具支持外部命令是好事,但必须在配置和权限设计上保持克制。

5. 快速上手与基础命令示例

这一部分假设你已经在本地环境里获得了这个工具的二进制文件,并且它被放到了 PATH 目录下。为了让示例更直观,下文统一使用fm作为命令名。如果实际命令名不同,替换成真实命令即可。

5.1 查看帮助

任何工具都有第一次使用的学习成本。优先看帮助信息:

fm --help

预期输出会列出可用选项,例如:

Usage: fm [OPTIONS] [PATH] Options: -d, --dir PATH 打开指定目录 -s, --search TEXT 按文件名正则表达式搜索 -f, --filter TEXT 按扩展名过滤 -H, --hidden 显示隐藏文件 --sort NAME|TIME|SIZE 排序方式 -v, --version 显示版本信息 -h, --help 显示帮助

需要提醒的是,具体选项一定以实际版本为准,不要拿着文档死记。

5.2 启动并进入目录

最简单的启动方式是直接指定目录:

fm /var/log

如果工具支持交互式界面,你会看到/var/log目录下的文件列表,然后可以通过上下箭头选择文件、回车进入目录、按返回键回到上级目录。如果不支持交互模式,工具可能只是快速打印目录内容后退出,这取决于它的定位。

5.3 搜索文件

假设你想找到当前项目里所有.md文件,并且文件名里包含readme,可以使用:

fm -s "readme.*\.md$" .

如果工具输出的是匹配文件的列表,那么每条结果会是一行完整的路径:

./docs/readme.md ./components/button/readme.md ./scripts/build-readme.md

这里使用的是一种简单的正则表达式模式。需要提醒的是,不同工具对正则的支持程度不一样。保守做法是,先用最简单的纯字符串关键字测试,再逐步增加正则规则。

5.4 批量查看目录占用

在服务器磁盘告警的时候,你通常需要找到哪个目录占用了最多的空间。“一切皆文件”的思路下,目录也是一个可以被读取和统计的文件。一个可能的用法是:

fm --sort SIZE /var

工具默认按文件大小排序,你就能迅速看到占用空间最大的子目录或文件。如果工具本身不提供这个功能,你仍然可以用系统命令辅助:

du -sh /var/* | sort -h

这里想表达的是:这个工具不一定能完全替代 Shell 管道,但它应该尽量减少你切换工具的次数。

6. 配置“编译命令”并集成外部编译器

既然不打包编译器,那用户就必须通过配置告诉工具“你要调用谁”。为了方便讨论,下面给出一个示意性的配置文件结构。

6.1 配置文件位置

按照常见的类 Unix 习惯,配置文件可能位于:

  • ~/.config/fm/config.toml
  • 或者~/.fmrc

具体路径以项目说明为准。下面示例使用 TOML 格式,因为它结构清晰、注释友好。

6.2 配置内容示例

# 文件路径:~/.config/fm/config.toml default_dir = "/home/me/projects" [view] show_hidden = false sort_by = "name" theme = "default" [editor] # 按 F3 时打开文件的编辑器 command = "vim" [build] # 按 F5 时执行的默认编译命令 command = "make" # 允许显示编译过程的实时输出 show_output = true [commands] # 自定义快捷命令:按 F7 清理编译产物 f7 = "rm -rf build dist *.o" [search] # 是否默认忽略 .git 目录 ignore_git = true

这里的关键节点有三个。

第一个是[build]节点。它指定了默认编译命令是make。如果你的项目不是用 Makefile 构建,而是一个单独的 C 文件,可以改成:

[build] command = "gcc main.c -o app && ./app" show_output = true

第二个是[commands]节点。它允许用户预设自定义命令,并在工具里通过快捷键触发。例如用 F7 清理编译产物。要注意:命令会以当前文件的所在目录作为工作目录执行,所以路径要写清楚。

第三个是[search]节点。它告诉你搜索时会自动跳过.git目录。在 Git 项目里,这能大幅提升搜索速度,也避免把.git里的二进制对象当作业务文件展示。

6.3 调用系统的交叉编译器

如果你做嵌入式开发,经常需要调用某个工具链前缀对应的 GCC,例如arm-linux-gnueabihf-gcc。此时不需要工具内置编译器,只需要在配置里把完整命令写清楚:

[build] command = "arm-linux-gnueabihf-gcc -mcpu=cortex-a7 -mfloat-abi=hard main.c -o app.bin" show_output = true

这正体现“不打包编译器”的灵活之处。工具不关心你是本机编译还是交叉编译,它只负责把命令交给系统 Shell。需要确认的是,这个交叉编译器必须已经安装,并且通过which arm-linux-gnueabihf-gcc能在 PATH 中找到。

6.4 运行与验证

配置完成之后,按工具说明的快捷键(示例里是 F5)触发编译。如果配置正确,你会在工具的输出区域看到:

$ make gcc main.c -o app

没有报错,退出码为 0,意味着编译成功。如果编译器找不到头文件,输出区会显示:

fatal error: stdio.h: No such file or directory

这种情况说明系统缺少开发头文件,不是工具的问题,应该去检查编译依赖。

7. 常见问题与排查方法

轻量工具也会有自己的坑。以下问题是这类“终端文件管理 + 外部命令集成”工具最容易遇到的共性场景,可以直接作为排查清单使用。

问题现象可能原因排查方式解决方案
启动提示 Permission denied二进制文件没有执行权限检查ls -l权限位执行chmod +x fm后重试
搜索不到任何文件当前目录路径写错,或正则语法不被支持先用绝对路径测试,再简化正则表达式调整路径或使用纯关键字搜索
中文字符显示乱码终端编码与系统 locale 不一致查看locale输出,确认 UTF-8 已生效设置LANG=en_US.UTF-8C.UTF-8
按 F5 编译命令没反应[build].command配置为空,或当前目录下没有构建脚本在配置中写入完整命令,手动在终端执行一遍验证补齐配置命令,确保命令本身可执行
编译提示 command not found编译器不在 PATH 中执行which gcc检查路径将编译器所在目录加入 PATH,或用绝对路径
删除文件后后悔工具没有回收站机制检查项目文档是否支持可恢复删除删除前备份,或使用mv file /tmp/代替删除
Windows 下打开异常工具未提供原生 Windows 版本查看项目发布页是否有 Windows 二进制优先使用 WSL,或等待原生版本
打开大目录卡顿目录文件数量巨大,默认全量加载观察 CPU 和磁盘 I/O 是否突增用搜索/过滤缩小范围,避免直接打开大型日志目录

排查时不要一上来就怀疑工具坏了。第一优先级永远是看错误输出本身,它会把真正的问题暴露出来。第二是确认“这条命令在普通 Shell 里能不能跑通”,如果普通 Shell 也跑不通,那不是工具的问题,是系统环境的问题。

8. 最佳实践与工程建议

8.1 安全边界:删除和权限

文件管理工具的删除操作通常直接调用底层系统调用,没有回收站。我的建议是,在工具里养成两个习惯:

  • 删除前先搜索并确认文件列表,再执行删除。
  • 重要目录在删除前先在外部做一次tarcp -r备份。

不要在 root 权限下长期使用这个工具。日常操作使用普通用户,需要提权时临时使用sudo。这种最小权限原则不只适用于该工具,适用于所有文件管理类工具。

8.2 外部命令的注入风险

配置文件里的自定义命令会被提交给 Shell 执行,这意味着配置本身需要被当作可执行代码来对待。如果你从网络上下载了一份别人的config.toml,里面写了一条包含curl ... | sh的命令,按下快捷键后它就会执行。

安全建议:

  • 只使用自己编写的配置。
  • 项目共享配置入库前要做 review。
  • 如果工具支持把命令绑定到快捷键,不要绑定rm -rf这类危险命令。

8.3 配置文件的版本管理

由于工具本身只有 192KB,配置文件往往比工具占用的心智还重要。建议把配置文件纳入自己的 dotfiles 仓库,用 Git 管理。换新机器时,只需要安装工具、拉取 dotfiles、软链接配置文件,几分钟就能恢复工作环境。

示例:

mkdir -p ~/.config/fm ln -s ~/dotfiles/fm/config.toml ~/.config/fm/config.toml

这样每一次配置改动都能被 Git 记录,出了问题也能快速回滚。

8.4 与系统命令行工具的互补

这个工具不应该替代findgrepdu,它应该成为你使用这些命令之前的一个“视觉入口”。比如你在工具里浏览到了/var/log/nginx,想查看今天请求最多的 IP,你可以直接进入命令行执行:

grep "2024-06-01" /var/log/nginx/access.log | awk '{print $1}' | sort | uniq -c | sort -nr

工具的作用是帮你更快定位文件,数据加工仍然交给系统命令。这才符合“一切皆文件”背后的 Unix 哲学:工具之间通过文本流协作,而不是一个工具包办所有事情。

8.5 性能优化

对于几十 GB 的日志目录,不要试图在工具里展开整个目录树。先使用过滤条件缩小范围,比如只搜索最近 24 小时修改过的.log文件。轻量工具的优势是启动快,但也不意味着它能像数据库一样处理海量文件。如果文件数量超过几万个,优先使用findxargs做离线处理,而不是交互式目录浏览。

8.6 如何参与这个项目的共建

标题最后那句“能来一起玩吗”,其实点明了这个项目当前的状态:它可能还不是一个成熟的“产品”,而是一个需要社区反馈来打磨的开源项目。如果你想参与,比较稳妥的路径有三种:

  • 先安装并真实使用一周,记录下不顺手的地方。
  • 去项目仓库提 Issue,描述你遇到的具体场景,尽量附带操作步骤和输出。
  • 如果你会写代码,可以从微小的功能点切入,比如增加一种排序方式、修复一个路径解析问题。

参与开源项目最忌一上来就要重构。小步提交、积极回复评审意见,反而是更容易被维护者接受的方式。

9. 总结与后续学习方向

这个 192KB 文件管理工具真正打动我的地方,不是它的代码量有多精简,而是它明确承认了一个事实:编译器不该被塞进每一个工具里,文件管理也不该承担所有的开发功能。在绝大多数 IDE 都在做加法的时候,它做的是减法。

如果你愿意动手,下一步可以这样做:

  1. 在虚拟机或开发机上安装它,用真实项目跑一周,重点测试“搜索文件”“目录跳转”“调用外部编译命令”这三个核心动作。
  2. 把配置收进 dotfiles 仓库,保持可迁移。
  3. 在项目仓库里提交一份使用反馈,或者写一篇自己的使用记录,这会帮助维护者更快改进细节。

往更深处看,“一切皆文件”这个概念仍然值得继续学习。等你对这个工具的操作已经足够熟悉,可以去研究/proc/sys虚拟文件系统,了解设备节点、符号链接、管道和 Socket 在文件模型里的位置。你会发现,工具本身只是入口,真正给你带来能力提升的,是这套已经延续了几十年的操作系统抽象。轻量工具的价值,正在于帮你重新看见这些底层事实。

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

OpenCV实战学习路线:从图像处理基础到企业级项目落地

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

作者头像 李华
网站建设 2026/9/7 4:05:46

3DMAX新手入门:从环境排查到卡通角色建模完整流程

刚把 3DMAX 装好,满脑子都是“今天一定要做出一个完整的卡通角色”,结果双击图标,启动界面闪一下就没了;好不容易装完,安装过程又报一个 1603 错误;就算顺利打开软件,面对四个视图和密密麻麻的工…

作者头像 李华
网站建设 2026/9/7 4:04:40

游戏军团队友信任体系构建:从数据记录到量化评估的完整方案

在多人策略游戏中,一个人的操作上限始终有限,真正决定军团能走多远的,往往不是某个人的神操作,而是整个“茶碗军推网络”里有没有一批值得背靠背信任的队友。这里的“军推”可以理解为军团推进、集结协作,也可以看作是…

作者头像 李华
网站建设 2026/9/7 4:03:24

ComfyUI漫剧工作流学习路径:从缺包报错到稳定批量产出

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

作者头像 李华
网站建设 2026/9/7 4:03:18

NSK轴承手册PDF高效使用指南:型号查询、寿命计算与选型要点

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

作者头像 李华