写给未来的 AI 助手(Agent): 这份文档总结了本项目的架构设计、业务逻辑以及迭代过程中形成的关键决策。请在接手后续开发或进行 Debug 时,首先阅读本文档以建立正确的项目上下文。
本项目是一个纯前端的 Web 端 Wayland 协议日志阅读器。
它用于解析并可视化由设置了 WAYLAND_DEBUG=1 环境变量产生出的调试日志,以友好的 UI(包含语法高亮、侧边栏对象追踪、搜索与过滤)帮助开发者排查 Wayland 协议的通讯细节。
- 部署环境:纯静态 Web 应用,托管于 GitHub Pages。
- 依赖声明:零依赖。没有使用 React/Vue、没有使用 npm、没有使用 TailwindCSS。全部由纯 HTML、CSS 和 Vanilla JavaScript 构建。
项目代码极度精简,主要围绕两个文件展开:
index.html(View & Controller):- 包含所有的布局结构、CSS 样式(深色护眼模式)。
- 处理所有的交互逻辑(拖拽文件、粘贴、搜索、过滤、侧边栏拖拽重置宽度)。
- 负责构建 DOM (
renderLog) 并管理全局状态(如过滤开关、多选对象highlightedUniqueIds、搜索匹配高亮)。
wayland-debug-tools.js(Model / Parser):- 核心的日志解析引擎。
- 使用正则表达式匹配现代 Wayland 日志格式:
[timestamp] {Queue Name} obj#id.fn(...)。 - 负责将纯文本拆解为结构化的数据 (
event,request,comment),并跟踪所有的对象生成与参数关联(appState)。
未来的 Agent 在修改代码时,请务必注意以下几点历史遗留的知识和决策:
- 现象:在 Wayland 协议中,对象销毁后,其 ID(如
wl_callback#38)会被频繁回收重用。 - 处理策略:解析器(
wayland-debug-tools.js)在遇到new id时,如果发现id已经在liveObjectsById字典中,直接覆盖即可,无需抛出异常。 - 唯一标识:为了区分复用同一个 ID 的不同对象生命周期,我们为每个新对象生成了
uniqueId。UI 层的所有高亮和选择,必须依赖uniqueId而不是协议原生的id。
- 数据结构:在
index.html中,选中的对象保存在let highlightedUniqueIds = new Set();中。 - 功能表现:用户可以点击左侧侧边栏的 Object Chip,或日志行中的对象标签,实现多对象的叠加选择。
- 过滤联动:当开启“仅高亮对象” (
highlight-only) 时,只有事件/请求的发送者 (object) 或参数 (args) 中包含了任何一个存在于highlightedUniqueIds里的对象,该行才会被显示。
- 过滤模式 (Filter):不包含搜索词的行会被直接隐藏(在构建 DOM 时被丢弃)。
- 搜索模式 (Search):不隐藏任何行,保留完整的日志上下文流。
- 匹配的行会添加
.search-match(蓝色发光边带)。 - 当前通过导航按钮(上一个/下一个)激活的行会添加
.search-active(带有高亮背景色和强烈的纯白 Outline 以增加辨识度)。 - 搜索导航具有状态数组
currentSearchMatches和currentSearchIndex。
- 匹配的行会添加
- 日志正则
logLine会捕获最前面的时间戳字符串,并由parseFloat()转化为line.timestamp。 - 如果开启了相对时间 (
showTimeDiff = true),系统会寻找日志中第一个有效的数字时间戳作为基准 0 点,后续日志显示为相对时间差(如[+0.016]),便于排查性能和延迟问题。
- 功能描述:在事件/请求的参数列表中显示参数名,如
repeat_info(rate: 25, delay: 600)。 - 数据来源:
protocols/build-all.sh批量扫描系统协议目录,调用convert-xml.py生成protocols/all-protocols.json,再封装为protocols/all-protocols.js(const ALL_PROTOCOL_DATA = {...};)。 - 加载方式:通过
<script src="protocols/all-protocols.js">同步加载,protocol-data.js在初始化时自动检测并合并该全局变量。不能用异步 fetch,否则renderLog()会在数据到达前执行,导致参数名不显示。 - 特殊逻辑:对于
wl_registry.bind等具有"未指定接口 (untyped new_id)"的参数,convert-xml.py会将其扩展为 3 个显示参数(interface, version, id),以匹配 libwayland 的调试输出格式。 - 重新生成:修改系统协议后,在
protocols/目录下运行bash build-all.sh即可更新。
- 当前做法:
renderLog()会清空log-panel并使用DocumentFragment一次性全量插入所有通过了过滤条件的行。 - 潜在瓶颈:对于十万行以上的巨型日志,如果用户选择显示所有内容(不进行任何过滤),DOM 的一次性生成会导致浏览器短时间卡顿。
- 未来优化建议:如果未来用户抱怨性能问题,请不要盲目引入第三方库,建议使用原生的 Virtual Scrolling (虚拟列表) 技术来重构
renderLog()的输出。
Keep it simple, keep it fast. 🚀