为什么写这个插件
每次做完调研,浏览器里开着 20+ 个标签页,想把链接整理到 Obsidian 笔记里,只能一个一个手动复制粘贴 --- 格式还乱七八糟。
搜了一圈 Chrome 商店,现有的方案要么太臃肿(OneTab 200 万用户但功能过重),要么只支持纯文本,要么多年不更新。
于是自己动手写了一个:TabScribe 。

它能做什么
一键把当前窗口(或所有窗口)的全部标签页复制到剪贴板,支持 4 种输出格式:
| 格式 | 示例 | 适用场景 |
|---|---|---|
| Markdown | [标题](链接) |
Obsidian / Notion / VS Code 笔记 |
| JSON | [{title, url}] |
数据分析 / API 对接 |
| 纯文本 | 自定义分隔符 | 快速列表 / CSV 导出 |
| HTML | <ul><li><a> |
网页笔记 |
核心功能
- ⚡ 快捷键 Alt+Shift+C --- 不开弹窗就能复制
- 💾 标签组保存与恢复 --- 保存当前标签页为一个命名组,下次一键在新窗口恢复
- 📤 导出文件 --- 支持 .md / .txt / .json / .html,文件名带时间戳
- 🎯 智能过滤 --- 自动排除 chrome:// / edge:// 等系统页面,可选排除固定标签页
- 🔧 自定义分隔符 --- 纯文本模式下可自定义分隔符(如
|导出 CSV 风格) - 🌐 12 种语言 --- 中英日韩德法西葡俄印尼语
- 🌙 深色模式 --- 自动跟随系统主题
技术实现
技术栈
Preact + TypeScript + Tailwind CSS + Vite + crxjs
打包体积:~63KB(gzip 后 ~17KB)
运行时外部依赖:0
选择 Preact 而非 React 的原因很简单:Chrome 插件的弹窗界面不需要一个 40KB+ 的框架,Preact 的 3KB 体积更适合这个场景。
Manifest V3 剪贴板写入的坑
这是开发过程中最大的技术难点。
Manifest V3 用 Service Worker 替代了 Background Page,而 Service Worker 没有 DOM --- 这意味着 document.execCommand('copy') 这个经典降级方案不生效。
我实现了一个三层降级策略:
typescript
// 第一层:Clipboard API(Popup / Offscreen Document)
await navigator.clipboard.write([new ClipboardItem({...})]);
// 第二层:execCommand 降级(Popup 上下文)
document.execCommand('copy');
// 第三层:Chrome Offscreen Document API(Service Worker 上下文)
await chrome.offscreen.createDocument({...});
i18n 国际化
直接用了 Chrome 内置的 chrome.i18n API,12 个语言文件各一个 JSON。manifest.json 中的名称和描述使用 __MSG_key__ 占位符,Chrome 商店自动展示对应语言版本。
json
{
"extensionName": { "message": "TabScribe" },
"extensionDesc": { "message": "一键批量复制所有标签页为 Markdown、JSON、HTML" }
}
隐私设计
这个插件不收集任何数据。
- 无埋点、无统计
- 无外部服务器
- 无网络请求(除 Chrome 自动更新外)
- 所有数据存储在
chrome.storage.local
仅申请 6 个最低必要权限,每个都有明确用途:
| 权限 | 用途 |
|---|---|
tabs |
读取标签页标题和 URL |
clipboardWrite |
写入剪贴板 |
storage |
本地存储设置和标签组 |
commands |
注册键盘快捷键 |
downloads |
导出文件到本地 |
offscreen |
Service Worker 中剪贴板访问 |
安装体验
🔗 TabScribe on Chrome Web Store
完全免费,无需注册,无需登录。
使用 Preact + TypeScript + Tailwind CSS 构建。源码:GitHub