15 · 源码地图与阅读路线
这一章用于“按问题反查文件”。行号以分析快照 1.7.1 为准,函数名比行号更稳定。
一、顶层入口
| 文件 | 入口/关键符号 | 你来这里找什么 |
|---|---|---|
src/background.ts | initialize, runtime listeners | tab、消息、快捷键、菜单、fetch proxy |
src/content.ts | IIFE message listener | 页面抽取、iframe、高亮单实例 |
src/core/popup.ts | initializeUI | 剪藏主流程与字段 UI |
src/core/settings.ts | DOMContentLoaded composition | 设置页初始化 |
src/core/highlights.ts | loadData, render* | 高亮库 |
src/core/reader-view.ts | loadArticle | 独立 Reader page |
src/reader-script.ts | injected boot | 原网页 Reader 启动 |
src/api.ts | clip, matchTemplate | 环境无关核心 |
src/cli.ts | main | Node CLI |
二、一次剪藏按调用顺序
core/popup.ts
initializeUI()
initializeExtension(tabId)
refreshFields()
↓
utils/content-extractor.ts
extractPageContent()
initializePageContent()
↓
content.ts
action=getPageContent
↓
Defuddle.parseAsync() / createMarkdownContent()
↓
utils/shared.ts
buildVariables()
↓
utils/triggers.ts
initializeTriggers() / findMatchingTemplate()
↓
utils/template-compiler.ts
compileTemplate()
↓
tokenizer.ts → parser.ts → renderer.ts → filters.ts
↓
shared.ts / obsidian-note-creator.ts
formatPropertyValue() / generateFrontmatter() / saveToObsidian()三、模板引擎地图
| 文件 | 核心符号 | 职责 |
|---|---|---|
utils/tokenizer.ts | tokenize | 字符流 → Token[] |
utils/parser.ts | parse, validateVariables, validateFilters | Token[] → AST + diagnostics |
utils/renderer.ts | render, renderAST | AST + context → string |
utils/template-compiler.ts | compileTemplate, processVariables | 环境 resolver 与两阶段编译 |
utils/resolver.ts | resolveVariableAsync | 浏览器变量解析兼容路径 |
utils/parser-utils.ts | parser state helpers | filter string legacy parser |
utils/variables/simple.ts | processSimpleVariable | 普通 deferred variable |
utils/variables/selector.ts | processSelector, resolveSelector | 页面 DOM 查询 |
utils/variables/schema.ts | processSchema | schema 兼容处理 |
utils/variables/prompt.ts | processPrompt | AI 结果占位 |
utils/variables/model.ts | model helpers | 当前模型元数据 |
utils/filters.ts | registry/apply | 执行与校验元数据 |
四、过滤器文件索引
src/utils/filters/ 每个 filter 一个文件。按任务找:
命名:camel capitalize kebab lower pascal safe_name snake title uncamel upper
集合:first join last length map merge nth object reverse slice split unique
Markdown:blockquote callout footnote fragment_link image link list markdown table template wikilink
HTML:html_to_json remove_attr remove_html remove_tags replace_tags strip_attr strip_md strip_tags
数字时间:calc date date_modify duration number_format round
文本:decode_uri replace trim unescape大多数同名 *.test.ts 就在旁边。
五、高亮地图
| 文件 | 符号 | 职责 |
|---|---|---|
utils/highlighter.ts | handleTextSelection | Selection → data |
| 同上 | createTextQuoteAnchor | exact/prefix/suffix |
| 同上 | mergeOverlappingHighlights | 合并 |
| 同上 | saveHighlights/loadHighlights | local persistence |
| 同上 | buildExportedPage | 导出模型 |
utils/highlighter-overlays.ts | renderTextHighlight | data → CSS Highlight |
| 同上 | buildNormalizedTextIndex | quote fallback index |
| 同上 | planHighlightOverlayRects | element overlay |
utils/content-extractor.ts | processHighlights | 高亮回注抽取正文 |
managers/highlights-manager.ts | manager CRUD | 设置/数据管理 |
core/highlights.ts | renderSidebar/renderMain | 高亮库 UI |
调试恢复失败
按顺序检查:
normalizeUrl key
→ stored highlight type/content
→ XPath + offsets
→ quote exact/prefix/suffix
→ normalized text index
→ cache invalidation
→ CSS Highlight registry / overlay rect六、Reader 地图
| 文件 | 关键符号 | 职责 |
|---|---|---|
utils/reader.ts | Reader.apply | 页面重构主入口 |
| 同上 | Reader.restore | 恢复/cleanup |
| 同上 | Reader.toggle | 生命周期切换 |
| 同上 | Reader.updateReaderContent | 独立页 SPA 导航更新 |
core/reader-view.ts | fetchWithRedirects, loadArticle | fetch + Defuddle |
reader-script.ts | boot | 注入页面事件监听 |
utils/reader-transcript.ts | wireTranscript | 媒体字幕联动 |
utils/font-utils.ts | font helpers | 本地字体与 CSS |
utils/iframe-resize.ts | resize | embedded/reader 宽高 |
styles/reader/* | partials | headings/table/code/footnote 等 |
七、Interpreter 地图
managers/interpreter-settings.ts
provider/model CRUD + preset
↓
utils/interpreter.ts
collectPromptVariables()
initializeInterpreter()
handleInterpreterUI()
sendToLLM()
parseLLMResponse()
replacePromptVariables()
↓
utils/token-counter.ts
utils/variables/prompt.ts
utils/variables/model.ts
providers.json请求失败先查 sendToLLM 的 provider branch;回填失败查 parseLLMResponse 与 prompt key。
八、设置与存储地图
| 文件 | 职责 |
|---|---|
utils/storage-utils.ts | Settings 默认、load/save、stats/history |
managers/general-settings.ts | 一般设置 UI |
managers/reader-settings.ts | Reader 设置 UI |
managers/interpreter-settings.ts | AI provider/model UI |
managers/template-manager.ts | template persistence |
managers/template-ui.ts | template editor |
managers/property-types-manager.ts | property type mapping |
managers/settings-section-ui.ts | sidebar section |
utils/auto-save.ts | debounce settings save |
utils/import-export.ts | template sharing |
utils/drag-and-drop.ts | template ordering |
utils/routing.ts | settings URL section |
九、平台与构建地图
package.json scripts/dependencies/exports
webpack.config.js 10 entries + assets + zip
manifest.chrome.json sidePanel + DNR + MV3 worker
manifest.firefox.json webRequest + optional hosts + Gecko
manifest.safari.json nativeMessaging
utils/browser-polyfill.ts source stub / webpack alias
utils/browser-detection.ts feature/platform class
utils/active-tab-manager.ts URL/tab validation
scripts/build-api.mjs ESM API
scripts/build-cli.mjs CommonJS CLI + DOM globals十、类型地图
src/types/types.ts:
| 类型 | 消费者 |
|---|---|
Template, Property | popup/settings/compiler/API/CLI |
PromptVariable | Interpreter |
Provider, ModelConfig | Interpreter settings/request |
ReaderSettings | Reader/settings/storage |
Settings | 全产品聚合状态 |
HistoryEntry, Rating | 本地历史/统计 UI |
Conversation* | transcript/conversation extraction |
Footnote | reader/filters |
高亮类型定义在 utils/highlighter.ts,模板 AST 类型定义在 utils/parser.ts,因为它们是子系统内部协议。
十一、按改动任务找入口
新增 popup 动作
popup HTML + core/popup.ts
→ background action router(若需浏览器能力)
→ content action listener(若需 DOM)
→ i18n locale keys
→ styles新增模板能力
先判断是 variable/filter/control syntax,分别从 shared/variables、filters、tokenizer 进入,避免把所有能力塞进 compiler。
新增浏览器
manifest
→ webpack env/output
→ browser detection
→ permission/network adapter
→ store package
→ real-browser matrix修改 Reader DOM
同时搜索 apply 创建点与 restore 清理点,再检查 highlighter cache、outline、transcript、mobile/RTL styles。
修改高亮 schema
同时修改 load migration、save、export、content injection、highlights library 与 fixtures,不能只改 interface。
十二、推荐的二次阅读路线
想做自己的 Clipper
api.ts → shared.ts → template-compiler.ts → filters.ts → cli.ts
想学浏览器扩展架构
三份 manifest → webpack → background → content → popup。
想学 DSL
tokenizer tests → tokenizer → parser tests → parser → renderer tests → renderer。
想学稳定 DOM 定位
highlighter.ts 的 data types → quote anchor → overlays normalized index → tests。
想学 Reader
reader-view(较短)→ Reader.apply/restore → outline/theme → transcript → styles。
十三、最终心智模型
┌──────── browser platform ────────┐
User action → popup ───▶│ background router ──▶ content DOM│
└───────────────────────────────────┘
│
Defuddle
│
normalized variables
│
┌───────────────────┴──────────────────┐
│ template DSL │
│ tokenize → parse → validate → render │
└───────────────────┬──────────────────┘
│
typed Markdown note
│
Obsidian / file / clipboard / API
Parallel stateful systems:
Highlight data ↔ DOM anchors ↔ Reader DOM
Settings sync ↔ managers ↔ runtime caches
Prompt variables ↔ provider adapters ↔ template fields如果只能记住一句话:这个项目用平台适配层拿到网页,用内容层把网页变成变量,用模板语言把变量变成笔记,再用多个 writer/体验子系统把结果送到用户真正工作的地方。