MuPDF JavaScript 绑定中 StructuredTextWalker 详解:遍历页面文本、图片、矢量与结构树的完整回调机制
图形学图像处理【免费下载链接】mupdfmupdf mirror项目地址https://gitcode.com/gh_mirrors/mu/mupdf点击查看免费下载本文以 MuPDF JavaScript 绑定中的StructuredTextWalker接口为核心完整讲解StructuredText.prototype.walk()提供的全部回调方法、每个回调的参数含义与触发条件并结合source/tools/murun.c中的 C 实现、include/mupdf/fitz/structured-text.h头文件与platform/wasm/lib/mupdf.ts中的实现说明回调背后对应的数据结构、选项开关如preserve-images、vectors、structured以及字符 flags 的位定义。读完本文你可以编写自定义的 walker 对象精确提取页面中每一个文本块、每一行、每个字符的坐标、字体、颜色与方向信息同时按选项收集图片、矢量图形与文档结构树。StructuredTextWalker 是什么一个StructuredTextWalker是一个带可选回调方法的对象用于迭代StructuredText对象的内容。官方参考文档见 StructuredTextWalker.rst其接口定义如下// |interface_type|这是一个接口类型的构造函数接口对象 class StructuredTextWalker { ... }在 JavaScript 绑定中你不需要“构造”一个 walker——只需要提供一个包含部分或全部回调方法的普通对象传给StructuredText.prototype.walk(walker)即可。MuPDF 在遍历时会逐个检查回调是否存在只调用你实际提供的方法因此 walker 的所有回调都是可选的。StructuredText对象本身不能直接构造需要通过Page.prototype.toStructuredText()获得详见 StructuredText 参考文档。该文档给出的最简遍历示例var sText page.toStructuredText() sText.walk({ beginLine: function (bbox, wmode, direction) { console.log(beginLine, bbox, wmode, direction) }, endLine: function () { console.log(endLine) }, beginTextBlock: function (bbox) { console.log(beginTextBlock, bbox) }, endTextBlock: function () { console.log(endTextBlock) }, beginStruct: function (standard, raw, index) { console.log(beginStruct, standard, raw, index) }, endStruct: function () { console.log(endStruct) }, onChar: function (utf, origin, font, size, quad, argb, flags) { console.log(onChar, utf, origin, font, size, quad, argb, flags) }, onImageBlock: function (bbox, transform, image) { console.log(onImageBlock, bbox, transform, image) }, onVector: function (bbox, flags, argb) { console.log(onVector, bbox, flags, argb) }, })全部回调方法逐一说明walk()按块block迭代StructuredText。对文本块会逐行遍历其行对每一行再逐字符遍历。每遇到一个块、行或字符就会触发对应的 walker 方法。完整回调清单如下回调方法参数触发时机beginTextBlock(bbox)Rect bboxStructuredText中每个文本块之前endTextBlock()无每个文本块之后beginLine(bbox, wmode, direction)Rect bbox、number wmode、Point direction文本块中每一行文字之前endLine()无每一行文字之后beginStruct(standard, raw, index)string standard、string raw、number index一个新的结构元素structure element开始时它未必与块/行严格嵌套endStruct()无每个结构元素之后onChar(c, origin, font, size, quad, color, flags)string c、Point origin、Font font、number size、Quad quad、Color color、number flags一行文字中的每一个字符onImageBlock(bbox, transform, image)Rect bbox、Matrix transform、Image imageStructuredText中的每个图片前提是提取选项设置了 preserve imagesonVector(bbox, flags, rgb)Rect bbox、Object flags、Array of number rgbStructuredText中的每个矢量图形前提是提取选项设置了 collect vectors下面对几个关键回调的参数展开说明。beginLine方向向量与 wmodebeginLine(bbox, wmode, direction)在块内每行文字开始前被调用bbox该行的边界框wmode书写模式0 表示水平书写1 表示垂直书写对应 C 头文件中fz_stext_line的wmode字段见 structured-text.hdirection基线的单位方向向量是归一化的Point。官方文档特别指出beginLine的direction参数是一个向量例如[0, 1]你可以对这个向量做三角运算来计算行的旋转角度。例如对水平文本direction约为[1, 0]角度为 0对向下书写的垂直文本约为[0, 1]角度为 90 度beginLine: function (bbox, wmode, direction) { // direction 是归一化基线方向(x, y) 对应角度弧度 var rotation Math.atan2(direction[1], direction[0]) var degrees rotation * 180 / Math.PI console.log(line direction:, direction, rotation:, degrees) }从 C 源码看direction直接来自fz_stext_line.dir字段头文件注释明确其为 “normalized direction of baseline”基线的归一化方向因此可以直接参与三角计算。onChar字符回调与 flags 位含义onChar对一行中的每个字符调用一次参数为c该字符UTF 编码的字符串通常是一个码点origin字符原点基线起点font该字符使用的Font对象size字号quad字符四边形用于精确定位可处理旋转/斜切color字符颜色sRGB 格式flags位标志组合含义由 C 层的fz_stext_char_flags枚举定义见 structured-text.h位值标志名含义1FZ_STEXT_STRIKEOUT删除线2FZ_STEXT_UNDERLINE下划线4FZ_STEXT_SYNTHETIC合成字形8FZ_STEXT_BOLD粗体真实或“伪”粗体16FZ_STEXT_FILLED填充绘制32FZ_STEXT_STROKED描边绘制64FZ_STEXT_CLIPPED被裁剪128FZ_STEXT_UNICODE_IS_CIDunicode 字段实际返回的是 CID256FZ_STEXT_UNICODE_IS_GIDunicode 字段实际返回的是 GID512FZ_STEXT_SYNTHETIC_LARGE大幅合成1024FZ_STEXT_HIGHLIGHT高亮这些样式类标志删除线、下划线、粗体等只有在提取时设置了collect-styles之类的选项后才会有意义。例如检测粗体字符onChar: function (c, origin, font, size, quad, color, flags) { if (flags 8) console.log(bold char:, c) if (flags 2) console.log(underlined char:, c) }需要注意的一点差异参考文档描述的签名是 7 个参数但从 murun.c 的实现mutool run使用的 JS 引擎绑定看onChar实际压入了 8 个参数——在flags之后还有一个bidi值奇数表示 RTL偶数表示 LTR而 wasm 绑定的 TypeScript 接口 中onChar的最后一个参数名就是bidi。编写回调时建议用函数剩余参数或只取前几个参数避免因绑定不同而多出一个尾参。同理murun.c中beginTextBlock还会附带一个块级flags对齐方式作为第二参数。onImageBlock需要 preserve images 选项onImageBlock(bbox, transform, image)对StructuredText中的每个图片调用前提是提取选项设置了 preserve images选项名preserve-images对应 C 层FZ_STEXT_PRESERVE_IMAGES见 structured-text.h。若没有设置该选项图片会被直接忽略回调永远不会触发。bbox图片在页面上的边界框transform图片变换矩阵imageImage对象可进一步读取像素数据。onVector需要 collect vectors 选项onVector(bbox, flags, rgb)对StructuredText中的每个矢量调用前提是提取选项设置了 collect vectors选项名vectors对应FZ_STEXT_COLLECT_VECTORS。参数bbox矢量图形的边界框flags形如{ isStroked: boolean, isRectangle: boolean }的对象rgb颜色数值数组。从 murun.c 的实现看flags 对象实际还会带上第三个字段continues表示该矢量是某条多段路径的一部分后续还有同一路径的段对应 C 层FZ_STEXT_VECTOR_CONTINUES完整的矢量标志枚举定义在 structured-text.h还包含isHighlight、isUnderline、isStrikeout等派生标志。beginStruct / endStruct结构树的深度优先遍历beginStruct(standard, raw, index)用于指示一个新的结构元素开始官方文档特别提醒它未必与文本块或行整齐嵌套May not be neatly nested within blocks or linesstandard标准结构类型名如Document、Section、Heading等来自 C 层fz_structure枚举经fz_structure_to_string转换raw文档自定义的非标准结构类型原始字符串index该节点在其所在层级的序号。这三个参数如何产生、为什么需要index在 C 头文件的长注释中有完整解释见 structured-text.hPDF 的结构树structure tree通过 MCID 标记内容归属文档内容在绘制顺序上可能与逻辑树顺序不一致。MuPDF 会把这棵树转换成begin_structure/end_structure的嵌套调用序列并且每次begin_structure都附带该节点在本层树中的index例如begin_structure(DOC, 0) begin_structure(STORY, 0) begin_structure(SECTION, 0) begin_structure(HEADING, 0)以及begin_structure(DOC, 0) begin_structure(STORY, 0) begin_structure(SECTION, 0) begin_structure(SUBSECTION, 1)有了index之后两处的SECTION/HEADING、SECTION/SUBSECTION的层级关系就变得无歧义了。MuPDF 会自动发送最小的一组end_structure/begin_structure配对来在树节点之间移动调用方只需按到达顺序处理即可。此外为了在结构化文本的数据结构里承载这种信息引入了新的STRUCT块类型使原本的线性块列表变成一棵树因此遍历结构信息需要按深度优先顺序进行。从murun.c的实现stext_walk可以印证遇到FZ_STEXT_BLOCK_STRUCT块时先调用beginStruct参数为standard字符串、raw字符串、index然后递归深入其first_block子列表最后调用endStruct()正好是深度优先遍历。walk() 的底层实现块类型分发JavaScript 绑定的walk()最终落到 C 层的块链表遍历上。以mutool run使用的实现 stext_walk() 为例它按块类型分发块类型C 枚举值分发动作文本块FZ_STEXT_BLOCK_TEXT调beginTextBlock逐行调beginLine/onChar/endLine最后endTextBlock图片块FZ_STEXT_BLOCK_IMAGE若 walker 提供onImageBlock则调用结构块FZ_STEXT_BLOCK_STRUCT若有down子结构beginStruct→ 递归子块 →endStruct矢量块FZ_STEXT_BLOCK_VECTOR若 walker 提供onVector则调用网格块FZ_STEXT_BLOCK_GRID当前 JS 回调中无对应方法块类型的完整枚举TEXT0、IMAGE1、STRUCT2、VECTOR3、GRID4见 structured-text.h。wasm 绑定的 TypeScript 实现 同样是这套逻辑先取first_block循环内根据block_type分发最后跟随block-next前进——也就是说对非结构页面walk 的顺序就是页面上块链表的线性顺序一旦设置了结构选项结构块会携带树形子链遍历自然转为深度优先。Java 平台也有等价的接口定义可作交叉参考StructuredTextWalker.java其中onChar明确带出flags与bidi两个尾参beginTextBlock带出块级flags与murun.c的 JS 实现一致。选项开关哪些数据能被收集到walker 的哪些回调会触发取决于toStructuredText()时传入的选项字符串。选项语法逗号分隔键值对、URL query 或 JSON 三种等价形式见 option-strings.md结构化文本选项全集见 stext-options.md。与 walker 直接相关的核心选项选项对应 C 标志对 walker 的影响preserve-imagesFZ_STEXT_PRESERVE_IMAGES打开后才有onImageBlock回调vectorsFZ_STEXT_COLLECT_VECTORS打开后才有onVector回调structuredFZ_STEXT_COLLECT_STRUCTURE打开后才有beginStruct/endStruct回调块列表变为树形preserve-spansFZ_STEXT_PRESERVE_SPANS同一行不合并 spanasJSON()需要它preserve-whitespaceFZ_STEXT_PRESERVE_WHITESPACE空白按原始形式保留preserve-ligaturesFZ_STEXT_PRESERVE_LIGATURES连字不展开为单个字符inhibit-spacesFZ_STEXT_INHIBIT_SPACES不在字符大间隙处补空格dehyphenateFZ_STEXT_DEHYPHENATE行尾连字符按软连字处理ignore-actualtextFZ_STEXT_IGNORE_ACTUALTEXT不应用 ActualText 替换clip/clip-rectFZ_STEXT_CLIP/FZ_STEXT_CLIP_RECT排除被完全裁剪的内容或限定收集区域lazy-vectors/fuzzy-vectorsFZ_STEXT_LAZY_VECTORS/FZ_STEXT_FUZZY_VECTORS控制矢量收集的行为延迟合并、模糊合并同色矩形各选项的完整注释含accurate-bboxes、collect-styles、segment、table-hunt等见 structured-text.h。一个典型的“全量收集”用法var sText page.toStructuredText(preserve-images,vectors,structured,preserve-spans) sText.walk({ beginTextBlock: function (bbox) { console.log(text block at, bbox) }, beginLine: function (bbox, wmode, direction) { console.log(line, wmode:, wmode, dir:, direction) }, onChar: function (c, origin, font, size, quad, color, flags) { // flags 8 为粗体flags 2 为下划线 if (flags 8) console.log(bold:, c) }, beginStruct: function (standard, raw, index) { console.log(enter struct:, standard, raw, index) }, endStruct: function () { console.log(exit struct) }, onImageBlock: function (bbox, transform, image) { console.log(image block at, bbox) }, onVector: function (bbox, flags, rgb) { console.log(vector, bbox, JSON.stringify(flags), rgb) } })实战要点与注意事项回调全部可选实现层在每次分发前都会检查回调是否存在如 murun.c 中的js_hasproperty判断只提供你关心的方法即可不需要的分支不会带来调用开销。触发条件由选项决定忘记preserve-images就没有onImageBlock忘记vectors就没有onVector忘记structured就没有beginStruct/endStruct。这与文档描述一致——这两个/三组回调默认不会触发。结构回调不与块/行整齐嵌套结构信息是树文本块是线性列表两者交织。walker 的到达顺序是深度优先的若要重建结构层级必须同时利用index参数与begin/end配对自行维护栈。行方向可用三角函数求角度direction是归一化向量Math.atan2(direction[1], direction[0])即可得到基线角度用于识别旋转文本、竖排文本wmode1等。字符级信息足够精细onChar提供 origin、quad、font、size、color 与 flags足以实现逐字符高亮、复制选区或按样式重建富文本quad是处理旋转字符定位的关键参数。不同绑定的参数小差异murun.cJS 引擎绑定的onChar会多传一个bidi参数beginTextBlock会多传一个块级 flagswasm 接口的onChar尾参名为bidi而省略了flags。跨绑定编写 walker 时建议以实际收到的参数为准做防御性处理。与 walk 互补的便捷方法StructuredText还提供asText()、asHTML(id)、asJSON(scale)、search(needle)、highlight(p, q)、copy(p, q)等方法见 StructuredText.rst。当你只需要纯文本、JSON 或搜索结果时可以不用手写 walker当需要自定义遍历逻辑如统计字体使用、按结构树分组导出时walk()才是正确的工具。同类回调模式的其他示例仓库中的 trace-device.js 演示了同一种“回调对象”编程风格用mutool run运行将每个绘图/文本操作打印出来与 walker 的写法一脉相承可作为理解 MuPDF 回调式 API 的入门示例。小结StructuredTextWalker是 MuPDF JavaScript 绑定中把StructuredText的块/行/字符三级数据完整“摊开”给应用层的接口文本块、行与字符走beginTextBlock→beginLine→onChar→endLine→endTextBlock的严格嵌套调用图片与矢量分别由选项控制的onImageBlock、onVector回调交付文档结构树则通过带index的beginStruct/endStruct以深度优先顺序呈现且允许与块/行不完全嵌套。结合 stext-options.md 中列出的选项、structured-text.h 中的结构定义与 murun.c 的分发实现你可以准确判断每个回调的触发时机与参数语义编写出可靠的页面内容遍历逻辑。赞分享图形学图像处理【免费下载链接】mupdfmupdf mirror项目地址https://gitcode.com/gh_mirrors/mu/mupdf点击查看免费下载相关推荐MuPDF 结构化文本遍历StructuredTextWalker 回调协议深度解析MuPDF 结构化文本遍历StructuredTextWalker 回调协议深度解析 StructuredTextWalker 是 MuPDF JavaScr桌面应用文档MuPDF JavaScript 绑定 PathWalker 接口详解用回调遍历路径绘制指令MuPDF JavaScript 绑定 PathWalker 接口详解用回调遍历路径绘制指令 PathWalker 是 MuPDF JavaScript 绑定图形学图像处理MuPDF JavaScript PathWalker 接口深度解析通过回调遍历 Path 矢量绘图指令MuPDF JavaScript PathWalker 接口深度解析通过回调遍历 Path 矢量绘图指令 PathWalker 是 MuPDF JavaScr桌面应用文档创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

相关新闻

Gym环境完全指南:核心接口、自定义环境与避坑实践

Gym环境完全指南:核心接口、自定义环境与避坑实践

很多人第一次接触强化学习,跑通第一个示例用的几乎都是Gym环境。我记得自己刚入坑那会儿,光搞明白env.step()到底该传什么、返回值又是什么,就折腾了一整天。网上教程虽然多,但大多数都在讲算法,真正把环境本身讲透的反…

2026/10/14 1:54:16 阅读更多 →
Pyenv详解:Python版本管理的核心原理与工程实践

Pyenv详解:Python版本管理的核心原理与工程实践

/* 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 1:54:15 阅读更多 →
并行编程——MPI 和OpenMPI 基本概念学习(一)

并行编程——MPI 和OpenMPI 基本概念学习(一)

文章大纲引言一、MPI 概述二、MPI基础数据类型1、使用MPI_Type_create_struct创建结构体类型数据类型1.1、在C中定义结构体并确定成员偏移量1.2、创建自定义 MPI 数据类型2、使用MPI_Type_create_subarray创建子数组类型数据类型2.1、确定子数组的形状和位置2.2、创建自定义 MP…

2026/10/14 1:53:15 阅读更多 →

最新新闻

2026 PCSX2 开源PS2模拟器:2500款老游戏在PC上稳跑

2026 PCSX2 开源PS2模拟器:2500款老游戏在PC上稳跑

2026 PCSX2 开源PS2模拟器:2500款老游戏在PC上稳跑 【免费下载链接】pcsx2 PCSX2 - The Playstation 2 Emulator 项目地址: https://gitcode.com/GitHub_Trending/pc/pcsx2 把BIOS文件丢进一个文件夹,拖入一张光盘镜像,PS2的开机动画就…

2026/10/14 2:46:28 阅读更多 →
CDL网表与LVS实战:从语法到版图提取的避坑指南

CDL网表与LVS实战:从语法到版图提取的避坑指南

简介:电路描述语言(CDL)教学演示文稿围绕C17基准电路,系统讲解如何用该语言描述电路结构、连接关系和逻辑功能,面向数字电路课程学习者、EDA入门者及需要完成电路描述实验报告的学生。内容先梳理语法规则,将…

2026/10/14 2:46:28 阅读更多 →
仓颉标准库 std.argopt 命令行参数解析指南:parseArguments 与 ArgumentSpec 实战详解

仓颉标准库 std.argopt 命令行参数解析指南:parseArguments 与 ArgumentSpec 实战详解

人工智能AI 技能文档开发工具 【免费下载链接】DocAgent 项目地址: https://gitcode.com/Cangjie-SIG/DocAgent 点击查看 免费下载 std.argopt 是仓颉(Cangjie)标准库中负责命令行参数解析的包,它提供从命令行参数字符串中解析出…

2026/10/14 2:46:28 阅读更多 →
LinkSwift:如何快速简单地完成网盘直链解析,一键拿到 8 大网盘直链

LinkSwift:如何快速简单地完成网盘直链解析,一键拿到 8 大网盘直链

LinkSwift:如何快速简单地完成网盘直链解析,一键拿到 8 大网盘直链 【免费下载链接】Online-disk-direct-link-download-assistant 一个基于 JavaScript 的网盘文件下载地址获取工具。基于【网盘直链下载助手】修改 ,支持 百度网盘 / 阿里云盘…

2026/10/14 2:46:28 阅读更多 →
Spring Data JPA实战:实体映射、事务控制与N+1优化

Spring Data JPA实战:实体映射、事务控制与N+1优化

1. 项目概述:为什么一个“JPA实战Demo”值得花三小时重写五遍你是不是也经历过这样的场景:刚学完JPA的基础注解——Entity、Id、GeneratedValue,信心满满地新建一个User类,跑起来却报org.hibernate.MappingException: Unknown ent…

2026/10/14 2:46:28 阅读更多 →
Vue 3 轻量级数据透视表组件:支持拖拽+聚合+Excel导出

Vue 3 轻量级数据透视表组件:支持拖拽+聚合+Excel导出

简介:这是一份面向Vue.js中高级开发者的数据透视表功能实现组件包,专为需要在Web应用中快速集成交互式聚合分析表格的前端工程师设计。资源提供两个核心Vue组件:支持拖放配置行列的完整数据透视表,以及轻量级仅聚合功能的PivotTab…

2026/10/14 2:45:28 阅读更多 →

日新闻

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/13 2:54:56 阅读更多 →
影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

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

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

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

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

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

2026/10/13 1:58:08 阅读更多 →

月新闻

我发现了一个新思路:用 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/12 18:11:17 阅读更多 →