ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

解析网页文本提取的加固:Open CoDesign 用 parse5 替换正则剥离与 EDITMODE 前向扫描优化

解析网页文本提取的加固:Open CoDesign 用 parse5 替换正则剥离与 EDITMODE 前向扫描优化 人工智能AI 应用桌面应用【免费下载链接】open-codesignOpen-source Claude Design alternative. One-click import your Claude Code / Codex API key. Prompt → prototype / slides / PDF. Multi-model (Claude, GPT, Gemini, Kimi, GLM, Ollama). BYOK, local-first, MIT.项目地址https://gitcode.com/gh_mirrors/op/open-codesign点击查看免费下载本文围绕 Open CoDesign 桌面端与运行时的一个内部加固变更展开将网页正文提取从正则剥离标签升级为基于 parse5 的惰性 HTML5 文本提取同时将预览 EDITMODE 标记的定位从通配表达式改为前向扫描并补充了畸形 HTML、深层嵌套与对抗性标记的回归测试。读完本文你将理解这一变更的动机、实现原理、测试验证方式以及如何在自己的项目里复用同样的安全与性能思路。变更背景与动机在apps/desktop/src/main/web-research-network.ts的 web 研究模块中原先提取网页可读文本的方式是ad-hoc 正则标签剥离。这种方式的问题在于正则只能匹配结构良好的 HTML而现实中的网页往往包含畸形标签、未闭合标签、嵌套注释等正则在处理这类输入时可能重构出可执行的标记例如把scrscriptbad()/scriptipt之类的畸形片段缝合成script这与只读、不执行、不加载资源的安全边界相悖。web-research-network.ts的注释明确写出了这一意图// Extract untrusted text, never HTML safe for insertion. Parsing does not execute // scripts or load resources; a regex replacement can reconstruct markup instead.同时packages/shared/src/editmode.ts中的 EDITMODE/TWEAK-SCHEMA 标记定位使用了通配表达式即在预览源中反复用[\s\S]*?之类的表达式去匹配标记块。若源码中出现大量未匹配的标记这种匹配可能在重复扫描时产生多项式级的时间开销。变更将这种通配匹配替换为前向扫描从源码位置线性推进避免了对同一段文本的反复回溯。变更一惰性加载 parse5 的 HTML5 文本提取实现位置与核心函数核心实现位于 apps/desktop/src/main/web-research-network.ts 的readableHtml函数export async function readableHtml(html: string): Promise{ text: string; title: string | null } { const { parse } await import(parse5); const document parse(html, { scriptingEnabled: true }); // ...迭代式树遍历收集文本节点 }几个关键设计点惰性动态导入parse5通过await import(parse5)按需加载只有在真正读取 HTML 页面时才加载解析器纯文本读取和应用启动都不会加载它。这是harden变更中重要的性能考量——解析器不是生产依赖之外的偶然传递依赖而是打包应用可用的直接依赖。不执行脚本、不加载资源parse5是纯解析器解析过程不执行script、不加载外部资源scriptingEnabled: true只影响解析器对脚本内容的建模方式并不会真正运行脚本。迭代式遍历而非递归readableHtml使用显式栈进行深度优先遍历见 L247-L296避免了深层嵌套 HTML 可能导致的调用栈溢出——这正对应回归测试中深层嵌套页面用例。文本提取的语义细节提取逻辑定义了两组元素集合L194-L238NON_CONTENT_ELEMENTSscript、style、noscript、template、svg、math、iframe、object、embed、canvas、video、audio等整个子树被跳过不进入正文。TEXT_BREAK_ELEMENTSp、div、section、article、标题、li、td、blockquote等在这些元素边界处插入换行保证表格单元格、列表项各自独立成行避免拼接出1243这类假数字。另外还处理了hidden属性和aria-hiddentrue的节点、HTML 注释替换为空格并做了两项后处理将连续的空白除换行外折叠为单个空格将 3 个以上连续换行压缩为\n\n。title提取也有明确的长度与空白规范化约束拼接title文本节点、压缩空白并截断到 500 字符L259-L270。返回文本仍是不可信数据变更文档明确强调preserving untrusted-text semantics提取结果是纯文本不是可安全插入的 HTML。例如lt;scriptgt;这类编码字面量会被解码为script的文本形式但它不会被当作可执行的标记。这在测试中得到了验证web-research-network.test.ts 的describe(HTML5 text extraction (not an HTML sanitizer))分组明确命名了这不是 HTML 消毒器。测试断言引号内尖括号、字符引用被正确解码一次2 3 5 4 © lt;bgt;畸形片段如scrscriptbad()/scriptipt不会产出script或!--文本。5000 层嵌套div的迭代遍历不会栈溢出输出仍是Deep text。变更二EDITMODE/TWEAK-SCHEMA 标记的前向扫描标记协议概述Open CoDesign 的设计工件源码中通过EDITMODE和TWEAK-SCHEMA标记块声明可调参数TWEAK_DEFAULTS内的 JSON 对象定义了 tokenTWEAK_SCHEMA定义了每个 token 的 UI 提示颜色、数值范围、枚举等。packages/shared/src/editmode.ts的注释给出了规范格式const TWEAK_DEFAULTS /* EDITMODE-BEGIN */{ key: value }/* EDITMODE-END */; const TWEAK_SCHEMA /* TWEAK-SCHEMA-BEGIN */{ accentColor: { kind: color }, radius: { kind: number, min: 0, max: 32, step: 2, unit: px } }/* TWEAK-SCHEMA-END */;前向扫描实现原实现使用通配表达式在源码中定位标记块新实现改为findMarker的前向扫描editmode.tsfunction findMarker( source: string, marker: string, from 0, ): { start: number; end: number } | null { let start source.indexOf(/*, from); while (start 0) { const end source.indexOf(*/, start 2); if (end 0) return null; if (compactMarkerName(source.slice(start 2, end)) marker) { return { start, end: end 2 }; } start source.indexOf(/*, end 2); } return null; }关键点线性推进每次找到*/后下一次搜索从end 2开始绝不回退因此扫描成本与源码长度呈线性关系避免了通配表达式在大量未匹配标记上重复回溯可能产生的多项式开销。容错标记名compactMarkerName会剔除标记名内部的空白/* E D I T M O D E - E N D */也能识别这来自源码编辑引擎对运行时保留字面量的严格校验需求。协议一致性findMarkerBlockL53-L65基于findMarker定位 BEGIN/END 对缺失标记返回 null没有 tweak 块而标记存在但内容非法 JSON 则是协议错误并抛出CodesignError。与源码编辑/预览的联动这个前向扫描不只服务于 tweak 面板还服务于预览的稳定性helpers.ts 的stablePreviewSourceKey用正则把 EDITMODE 块内容替换为__STABLE__占位用于计算预览 key——token 内容变化不应触发整页重载。tweak-persistence.ts 的mergeTweakTokenChanges在回写前校验 token 类型、数值范围、枚举选项并检测源码被外部修改时的冲突。source-edit-engine.ts 的runtimeReservedValue把包含 EDITMODE/TWEAK-SCHEMA 标记、ReactDOM.createRoot、!-- AGENT_BODY_BEGIN --等预览运行时控制文本的字面量判定为保留值拒绝作为可编辑文本写入防止用户把运行时控制标记当作普通文案。测试 source-edit-engine.test.ts 验证了/*EDITMODE-BEGIN*/hello/*EDITMODE-END*/、/* E D I T M O D E - E N D */、/*outer/*EDITMODE-BEGIN*/等对抗性形式都被runtime-reserved-value拒绝而普通散文如data-codesign-source-id is ordinary body text、function Application is not App不会被误判。变更三畸形 HTML、深层嵌套与对抗性标记的回归覆盖这次变更同时把三类回归测试纳入了仓库作为harden的证据链畸形 HTMLweb-research-network.test.tsscrscriptbad()/scriptipt、!-- remove --scriptalert(1)/script、嵌套注释、标题内编码的script字面量——所有这些都不会产出可执行的script或!--。深层嵌套同文件 L320-L3235000 层嵌套 div 的迭代遍历不溢出。对抗性标记source-edit-engine.test.ts带内部空白的标记、外层注释包裹的标记、裸 BEGIN/END 等都被拒绝同时 editmode.test.ts 覆盖了parseEditmodeBlock对缺失标记、非法 JSON、非对象 JSON 的协议错误路径。变更文档.changeset/harden-web-research-parsing.md声明open-codesign/desktop与open-codesign/runtime均为 patch 级别更新属于行为不变的加固性修复。可参考 WEB_SEARCH.md 了解解析器依赖的背景说明与聚焦测试命令。总结从这次变更中可以复用的三条经验解析器替代正则处理 HTML 是安全边界正则剥离能重建标记这一风险是真实存在的用真正实现 HTML5 解析算法的库如 parse5可以吸收畸形输入的歧义让只读解析与执行/加载彻底解耦。标记扫描用前向线性算法凡是需要在源码/文本中反复查找成对标记的场景都应当用indexOf线性推进而不是在重复未匹配内容上回溯的通配表达式这是可量化的最坏情况复杂度改进。加固变更必须配对抗性测试畸形片段、深层嵌套、带干扰的标记名是三类低成本高价值的回归样本它们把理论上不会出事变成测试里证明不会出事。赞分享人工智能AI 应用桌面应用【免费下载链接】open-codesignOpen-source Claude Design alternative. One-click import your Claude Code / Codex API key. Prompt → prototype / slides / PDF. Multi-model (Claude, GPT, Gemini, Kimi, GLM, Ollama). BYOK, local-first, MIT.项目地址https://gitcode.com/gh_mirrors/op/open-codesign点击查看免费下载相关推荐JetUML核心功能揭秘高效UML diagramming的7个实用技巧JetUML核心功能揭秘高效UML diagramming的7个实用技巧 JetUML是一款专注于快速UML diagramming的桌面应用为开发者和设计解析 Claude Design 系统提示词10 段式架构与 open-codesign 的 EDITMODE 协议实现解析 Claude Design 系统提示词10 段式架构与 open codesign 的 EDITMODE 协议实现 导读 本文基于 open codes人工智能AI 应用桌面应用open-codesign 定向微调Targeted Tweaks协议EDITMODE 标记的精准编辑规范与源码解析open codesign 定向微调Targeted Tweaks协议EDITMODE 标记的精准编辑规范与源码解析 本篇文章聚焦 open codesi人工智能AI 应用桌面应用上一篇10 分钟把 VR 视频转成 2D无需头显的免费全景视频播放与导出下一篇FactoryBluePrints 指南如何安装戴森球计划免费蓝图库并快速建厂创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表