Claude Code案例-浏览器插件开发之notion to markdown剪切板(已开源)
1. 为什么我要自己写一个 Notion 转 Markdown 剪切板插件我平时主力笔记软件就是 Notion写完之后经常要发到 CSDN、知乎这类支持 Markdown 的平台。Notion 自带的导出功能会给你一个 zip里面是.md文件加一堆本地图片还得手动解压、上传图床、再复制正文流程特别割裂。我真正想要的动作只有一个在 Notion 页面里点一下Markdown 全文含图片外链直接进剪切板切到编辑器 CtrlV 就完事。搜了一圈排名靠前的方案基本是 GitHub Action 形态的 notion2markdown它的定位是把 Notion 内容同步到静态站点需要配 workflow、配 secret跟随手复制完全不是一个场景。也有在线转换网站但要把私有页面内容贴给第三方我是不太放心的。所以结论很明确市面缺一个浏览器插件形态、本地完成转换、结果直接进剪切板的工具。这个需求特别适合拿来练 Claude Code。它足够小两小时能出可用版本又足够完整涉及 manifest v3、content script、跨域请求、第三方 SDK 打包这些真实工程问题。下面我会把插件结构、manifest 配置、内容提取与转换逻辑、以及我踩过的报错全部摊开你可以直接照着复刻一个。核心检索词先摆在这Claude Code 开发浏览器插件、Notion 转 Markdown、复制到剪切板这三件事本文都会给到可复制的配置。技术栈上我选的是 Notion 官方 API 客户端notionhq/client拉取块数据notion-to-md做块到 Markdown 的转换图片走腾讯云 COS 的cos-js-sdk-v5上传后替换链接构建用 Webpack 5。这套组合是 Claude Code 在读完参考项目后自己给出的方案我基本没改。2. 用 Claude Code 搭插件的准备工作与 TaoToken 接入配置在正式写代码前得先让 Claude Code 能稳定跑起来。我这边是通过 TaoToken 接入的它把模型调用统一成一个 OpenAI 兼容的入口配置一次就能在 Claude Code、Cline 这类工具里复用。官网地址是 https://taotoken.net/?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content API 入口是 https://taotoken.net/api 注意 API 地址后面不加任何查询参数。先说清楚三件套这是所有接入的通用公式Base URL、API Key、Model ID。缺任何一个都会在请求阶段直接失败。Base URL 填https://taotoken.net/apiAPI Key 在控制台的 API Keys 页面生成Model ID 按你实际要用的模型填。下面这段是 Claude Code 的 settings 配置路径是~/.claude/settings.json直接复制改 Key 即可{ env: { ANTHROPIC_BASE_URL: https://taotoken.net/api, ANTHROPIC_AUTH_TOKEN: sk-你的TaoToken密钥, ANTHROPIC_MODEL: claude-sonnet-4-5-20250929 } }如果你用的是 Codex 系工具配置落在~/.codex/auth.json结构不太一样注意别混{ OPENAI_API_KEY: sk-你的TaoToken密钥, OPENAI_BASE_URL: https://taotoken.net/api }Cline 这类 VS Code 插件则是在设置面板里填 Base URL 和 KeyModel ID 手动输入。三者的共同点就是上面那三件套配完先别急着写业务代码跑一个最小请求验证通路。我习惯用 curl 先探一下curl https://taotoken.net/api/v1/chat/completions \ -H Authorization: Bearer sk-你的TaoToken密钥 \ -H Content-Type: application/json \ -d { model: claude-sonnet-4-5-20250929, messages: [{role: user, content: 回复 ok}] }返回里能看到choices[0].message.content就说明链路通了。这一步很关键因为后面插件调试时如果报错你得能区分是模型接入的问题还是插件本身的问题。我建议把 Key 单独放一个环境变量文件别硬编码进仓库Claude Code 生成代码时也提醒它不要写死密钥。准备工作还包括Chrome 打开chrome://extensions开启开发者模式Notion 那边创建一个 Integration 拿到 token并把目标页面授权给这个 Integration。腾讯云 COS 建一个存储桶拿到 SecretId、SecretKey、Bucket 和 Region。这些凭据后面会填进插件的配置页先备齐。3. 可复制的 manifest 与转换逻辑配置插件目录结构我让 Claude Code 按下面这样组织清晰且好维护notion-to-markdown-extension/ ├── manifest.json ├── src/ │ ├── background.js │ ├── content.js │ ├── popup.html │ ├── popup.js │ └── converter.js ├── package.json └── webpack.config.jsmanifest.json是 MV3 格式权限要开activeTab、scripting、storagehost 权限要覆盖 Notion 和 COS 域名否则 fetch 会被拦{ manifest_version: 3, name: Notion to Markdown Clipboard, version: 1.0.0, description: 一键把 Notion 页面转成 Markdown 并写入剪切板, permissions: [activeTab, scripting, storage, clipboardWrite], host_permissions: [ https://api.notion.com/*, https://*.myqcloud.com/* ], background: { service_worker: background.js }, action: { default_popup: popup.html }, content_scripts: [ { matches: [https://www.notion.so/*], js: [content.js] } ] }转换核心在converter.js思路是先用 Notion API 拿到 pageId 对应的 block 树再交给notion-to-md转字符串最后把图片块替换成 COS 外链import { Client } from notionhq/client; import { NotionToMarkdown } from notion-to-md; import COS from cos-js-sdk-v5; const notion new Client({ auth: NOTION_TOKEN }); const n2m new NotionToMarkdown({ notionClient: notion }); const cos new COS({ SecretId: COS_SECRET_ID, SecretKey: COS_SECRET_KEY }); async function uploadImage(buffer, key) { return new Promise((resolve, reject) { cos.putObject({ Bucket: COS_BUCKET, Region: COS_REGION, Key: key, Body: buffer }, (err, data) { if (err) return reject(err); resolve(https://${COS_BUCKET}.cos.${COS_REGION}.myqcloud.com/${key}); }); }); } export async function pageToMarkdown(pageId) { const mdblocks await n2m.pageToMarkdown(pageId); const mdString n2m.toMarkdownString(mdblocks); return mdString.parent; }图片处理是最容易翻车的地方。Notion 的图片块返回的是带签名的临时 URL一小时后失效所以必须下载后转存到自己的 COS再把 Markdown 里的链接替换掉。Claude Code 一开始没处理这个我贴了报错它才补上uploadImage这段。background.js负责接收 popup 的指令、调用 converter、把结果写回剪切板chrome.runtime.onMessage.addListener((msg, sender, sendResponse) { if (msg.type CONVERT) { pageToMarkdown(msg.pageId) .then(md sendResponse({ ok: true, md })) .catch(e sendResponse({ ok: false, error: e.message })); return true; } });注意MV3 的 service worker 不能直接用navigator.clipboard写剪切板的动作要放在 popup 或 content script 里执行background 只做数据搬运。4. 验证请求与成功结果从 Notion 页面到粘贴出 Markdown配置填完后先做一次端到端验证。打开一个已授权给 Integration 的 Notion 页面点插件图标popup 里会显示当前 pageId 和一个转换并复制按钮。点下去之后正常流程是background 调 Notion API 拉块 → converter 转 Markdown → 图片上传 COS → 返回完整字符串 → popup 写入剪切板。验证成功有几个可观察的信号。第一popup 里出现已复制 N 字符的提示第二切到任意 Markdown 编辑器 CtrlV标题层级、列表、代码块都保留第三图片链接是https://你的bucket.cos.区域.myqcloud.com/...这种你自己的域名而不是 Notion 的临时签名地址。我实测下来一篇带 5 张图、3 个代码块的笔记从点击到粘贴完成大概 3 到 5 秒主要耗时在图片上传。如果你想更严谨地验证转换质量可以拿一篇结构复杂的页面测包含 to-do、toggle、callout、嵌套列表。notion-to-md对大部分块支持良好但 callout 会转成引用块toggle 会展开成普通内容这些差异你要心里有数。下面是一个转换前后的对照方便你判断结果是否符合预期Notion 块类型转换后 Markdown备注Heading 1/2/3#/##/###层级保留Bulleted list-嵌套用缩进Code block三反引号 语言语言标识可能丢失Image![alt](COS外链)需自行转存Callout引用块图标丢失验证阶段还有一个动作值得做把转换函数单独抽出来在 Node 里跑一遍不依赖浏览器环境。这样出问题时能快速定位是 API 层、转换层还是插件通信层的问题。我当时的做法是写一个test.js直接 import converter传入 pageId打印结果。这一步帮我省了大量在浏览器里反复点的时间。5. 本篇常见报错排查401、Illegal invocation 与图片失效调试过程中我遇到的报错基本集中在下面几类逐个说清楚原因和解法。第一类是Error: Failed to execute fetch on Window: Illegal invocation。这个报错我卡了最久Claude Code 也迭代了两三次才修好。根因是fetch被解构或赋值后脱离了window上下文比如写成const { fetch } window再调用就会触发。解法是始终用window.fetch(...)或fetch.call(window, ...)别把方法单独拎出来。如果你在 content script 里调用还要注意 MV3 的隔离环境跨域请求建议统一走 background。第二类是 401。这个几乎都是凭据问题对照检查三件套Notion token 是否以secret_或ntn_开头、是否把页面 share 给了对应 Integration、TaoToken 的 Key 是否过期。如果返回体里是unauthorized先看 Notion 侧如果是模型调用返回 401检查ANTHROPIC_AUTH_TOKEN有没有多余空格。我踩过的坑是复制 Key 时带了个换行排查了十分钟。第三类是Cannot read properties of undefined (reading choices)。这通常出现在你直接解析模型返回时说明请求根本没成功返回体是错误对象而不是标准结构。正确做法是先判断response.ok再取choices。这类报错在接入初期很常见本质是错误处理没写全。第四类是图片 403 或链接过期。Notion 的图片 URL 带签名超过有效期就失效。如果你没做转存粘贴出去的 Markdown 过一会儿图就挂了。解法就是前面说的下载后传 COS 再替换。COS 这边如果报AccessDenied检查存储桶权限是不是私有读写、SecretId 有没有对应权限。第五类是 OAuth 相关报错。如果你走的是 Notion 的 OAuth 授权流程而不是内部 Integration token回调地址必须和 Notion 后台配置的完全一致包括协议和端口。本地调试时用http://localhost容易被拒建议直接配一个固定的回调路径。提示排查顺序建议从外到内——先 curl 验证模型通路再验证 Notion API最后才怀疑插件代码。这样能避免在错误的方向上浪费时间。6. 后续迭代与接入入口基础版本跑通后我又迭代了几个方向。一个是兼容 Cookie 方案不依赖 Integration token直接从浏览器已登录的 Notion 会话里取数据好处是用户零配置坏处是稳定性受 Notion 前端改动影响目前还在调。另一个是给 popup 加了转换选项比如是否上传图片、是否保留 callout 图标、代码块语言标识补全。这些都可以让 Claude Code 帮你加描述清楚需求它就能改。如果你也想从零做一遍建议按这个顺序推进先用 curl 把 TaoToken 通路跑通再单独写一个 Node 脚本验证 Notion API 和转换逻辑最后才包成插件。这样每一步都有独立验证点出问题好定位。模型调用入口在 https://taotoken.net/api 密钥在控制台的 API Keys 页面生成接入文档在 doc 页面有完整说明。需要长期跑编码和 Agent 任务的可以看下 Coding Plan按用量规划更省心。真正动手写的时候你会发现卡住你的从来不是不会写代码而是某个具体的报错和某个没配对的环境变量。把这两样解决掉一个小工具两小时就能出来。

相关新闻

【AI 辅助开发系列】Visual Studio 中 GitHub Copilot 注释生成实战:把 settings 改到 TaoToken 让文档更清晰

【AI 辅助开发系列】Visual Studio 中 GitHub Copilot 注释生成实战:把 settings 改到 TaoToken 让文档更清晰

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/10 2:20:19 阅读更多 →
适合家用的中频治疗仪品牌梳理,康民人等含二类医疗器械资质产品

适合家用的中频治疗仪品牌梳理,康民人等含二类医疗器械资质产品

适合家用的中频治疗仪品牌梳理:康民人等含二类医疗器械资质产品解析随着家庭健康管理意识的普及,中频治疗仪作为一种常见的物理康复辅助设备,正逐渐融入大众的日常生活。在选购此类产品时,消费者不仅关注操作的便捷性和居家适用性…

2026/10/10 0:30:21 阅读更多 →
Exa Search MCP 接入 TaoToken:Node.js 搜索 API 密钥配置与 TRAE 联调大纲

Exa Search MCP 接入 TaoToken:Node.js 搜索 API 密钥配置与 TRAE 联调大纲

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/9 12:54:33 阅读更多 →

最新新闻

绝缘子缺陷检测数据集清洗与工业级训练实战指南

绝缘子缺陷检测数据集清洗与工业级训练实战指南

简介:本资源是面向电力AI研发人员、工业视觉工程师及智能巡检系统开发者的绝缘子缺陷检测专用YOLO格式数据集,解决无人机航拍场景下绝缘子破损、污闪、积雪等9类典型缺陷的精准识别与定位难题。数据集共2139张真实巡检图像(含训练/验证/测试集…

2026/10/12 0:05:01 阅读更多 →
牙科影像龋齿四级像素级分割数据集与临床落地实践

牙科影像龋齿四级像素级分割数据集与临床落地实践

简介:本资源是一套面向医学影像AI研究者与口腔临床算法开发者的专业蛀牙分割数据集,专为U-Net、DeepLab等分割模型训练设计,解决真实场景下多类别蛀牙区域精细识别与程度量化评估难题。数据集含400张高精度口腔内窥镜及X光影像(对…

2026/10/12 0:05:01 阅读更多 →
条形码目标检测数据集实战:从YOLOv8训练到部署

条形码目标检测数据集实战:从YOLOv8训练到部署

简介:这是一份面向目标检测与计算机视觉学习者的条形码识别数据集,涵盖零售、物流、制造等场景下的真实商品条码图像,适合用于训练YOLO系列模型或开展算法实验。数据集共684张图片,按训练集624张、验证集60张划分,采用…

2026/10/12 0:04:01 阅读更多 →
MongoDB复制集扩缩容实战:从rs.add到选主事故复盘

MongoDB复制集扩缩容实战:从rs.add到选主事故复盘

月初帮业务团队扩容一套 MongoDB 复制集,需求描述只有一句话:“加一台新机器进复制集,扛一下读流量。”我反问了一句:“你打算怎么加?”对方很自信:“rs.add() 啊,一行命令的事。”我当场就把计…

2026/10/12 0:04:01 阅读更多 →
Debian新手入门:从部署到日常操作的完整指南

Debian新手入门:从部署到日常操作的完整指南

第一次装完Debian,盯着黑乎乎的终端窗口迷茫好一会儿,这是我至今印象很深的场景。系统能开机、能登录,但下一步该敲什么命令完全没头绪。后来用久了才想明白一件事:Linux的入门难点从来不是"怎么把系统装上"&#xff0c…

2026/10/12 0:04:01 阅读更多 →
多模态大模型入门:从原理到实战,一文搞懂图文音视频一体模型

多模态大模型入门:从原理到实战,一文搞懂图文音视频一体模型

一、什么是多模态大模型? 💡 核心定义:多模态大模型是能够同时处理、理解和生成文本、图像、音频、视频等多种模态信息的人工智能模型。它打破了传统单模态模型(如仅处理文本的GPT-3或仅处理图像的ResNet)的限制&#…

2026/10/12 0:04:00 阅读更多 →

日新闻

复古胶片颗粒感噪点合成器:Canvas ImageData 像素高斯杂色注入算法

复古胶片颗粒感噪点合成器:Canvas ImageData 像素高斯杂色注入算法

在数码相机、高清显示屏与现代矢量图形技术高度发达的今天,画面可以做到绝对的锐利、平滑与无瑕。然而,当一张秋日手账插画或拍立得照片过于“平整无瑕”时,往往会散发出一种冰冷生硬的“数码塑料感(Digital Plasticity&#xff0…

2026/10/12 0:00:59 阅读更多 →
活字印刷古籍线装排版:Canvas 竖排文字与栏线自适应算法

活字印刷古籍线装排版:Canvas 竖排文字与栏线自适应算法

在现代网页与移动端设计中,横排(Horizontal Layout)早已经成为了绝对的主流。然而,当我们翻开泛黄的线装古籍、宋版木刻诗集,或是欣赏一张茶道雅集的手写便签时,那种**自上而下纵向书写、自右向左逐列铺展&…

2026/10/12 0:00:59 阅读更多 →
周日晚间的“精神松绑减震器”:无压力情绪倾倒箱与温和轻声陪伴

周日晚间的“精神松绑减震器”:无压力情绪倾倒箱与温和轻声陪伴

每到周日的晚上八点到十点,很多人心里都会悄悄亮起一盏警示灯。 在心理学上,这种现象有一个专门的称谓——“周日夜晚焦虑症(Sunday Scaries)”。明天又是周一,闹钟又要重新在七点响彻卧房;脑海里仿佛有一个…

2026/10/12 0:00:59 阅读更多 →

周新闻

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

简介:基于 ARIMA、LSTM、Transformer 等模型的流感时间序列预测 Python 源码,面向计算机相关专业课程设计与期末大作业学生,以及项目实战学习者。内容覆盖预处理、平稳性检验、定阶、残差分析、多模型对比预测的完整时序建模流程,…

2026/10/11 0:00:27 阅读更多 →
影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

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

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

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

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

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

2026/10/11 0:00:27 阅读更多 →

月新闻

我发现了一个新思路:用 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/11 10:45:37 阅读更多 →
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/11 14:36:53 阅读更多 →
黑夜航拍船只数据集训练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/11 14:36:54 阅读更多 →