<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>前端 on Leanku 的博客</title><link>https://www.leanku.com/tags/%E5%89%8D%E7%AB%AF/</link><description>Recent content in 前端 on Leanku 的博客</description><generator>Hugo</generator><language>zh-cn</language><lastBuildDate>Wed, 22 Jan 2025 00:00:00 +0800</lastBuildDate><atom:link href="https://www.leanku.com/tags/%E5%89%8D%E7%AB%AF/index.xml" rel="self" type="application/rss+xml"/><item><title>Chrome 插件开发实战：一键把当前页面存为 Markdown</title><link>https://www.leanku.com/post/tools/chrome-extension-development-practice/</link><pubDate>Wed, 22 Jan 2025 00:00:00 +0800</pubDate><guid>https://www.leanku.com/post/tools/chrome-extension-development-practice/</guid><description>&lt;p&gt;从一行代码到 Chrome Web Store 上架。本文用一个具体例子走通 Chrome 插件开发完整流程：manifest.json、content script、popup 通信、文件下载、用户偏好存储、上架审核。&lt;/p&gt;&#10;&lt;h2 id="为什么要做这个插件"&gt;为什么要做这个插件&lt;/h2&gt;&#10;&lt;p&gt;我经常在浏览器里看技术文章。看到好的想存到 Obsidian，复制粘贴格式全乱。打开&amp;quot;另存为&amp;quot;保存下来是带广告、导航栏、侧边栏的 HTML。想找一个干净的 Markdown 版本，要么没有，要么是闭源插件不敢装。&lt;/p&gt;&#10;&lt;p&gt;装个现成插件不放心。写个 userscript 分发麻烦。干脆自己写一个。&lt;/p&gt;&#10;&lt;p&gt;这是个&amp;quot;改造已有网站&amp;quot;的小工具，Chrome 插件是最合适的形态。如果你还不确定插件是不是解决你问题的最佳方案，可以先看 &lt;a href="https://www.leanku.com/post/tools/chrome-extension-development-intro/"&gt;《Chrome 插件开发》&lt;/a&gt;。&lt;/p&gt;&#10;&lt;h2 id="我们要做的版本"&gt;我们要做的版本&lt;/h2&gt;&#10;&lt;p&gt;最终交付一个能本地转、能下载、能存用户偏好的插件：&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;点击工具栏图标，弹出一个 popup&lt;/li&gt;&#10;&lt;li&gt;popup 上一个按钮&amp;quot;保存为 Markdown&amp;quot;&lt;/li&gt;&#10;&lt;li&gt;点击后，把当前页面转成干净的 Markdown，触发下载&lt;/li&gt;&#10;&lt;li&gt;几个 checkbox 让用户自定义：是否包含图片、是否包含代码块、文件名格式&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p&gt;这个版本足够简单，又覆盖了插件开发的核心链路：content script、popup 通信、文件下载、用户偏好存储。&lt;/p&gt;&#10;&lt;h2 id="准备工作"&gt;准备工作&lt;/h2&gt;&#10;&lt;p&gt;&lt;strong&gt;需要：&lt;/strong&gt;&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;Chrome 浏览器（任何最近版本都行）&lt;/li&gt;&#10;&lt;li&gt;一个空文件夹&lt;/li&gt;&#10;&lt;li&gt;一个文本编辑器&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p&gt;&lt;strong&gt;不需要：&lt;/strong&gt;&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;Node.js&lt;/li&gt;&#10;&lt;li&gt;npm&lt;/li&gt;&#10;&lt;li&gt;任何前端框架&lt;/li&gt;&#10;&lt;li&gt;任何构建工具&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p&gt;整个项目就是几个静态文件，加一个第三方库。装一个依赖就要搭构建，搭构建就要讲 webpack / vite / TypeScript，整个文章会跑偏。&lt;/p&gt;&#10;&lt;p&gt;&lt;strong&gt;第三方库：Turndown.js&lt;/strong&gt;&lt;/p&gt;&#10;&lt;p&gt;用来把 HTML 转成 Markdown。同类插件 80% 在用，成熟稳定。&lt;/p&gt;&#10;&lt;p&gt;下载地址：&lt;a href="https://unpkg.com/turndown@7.2.0/dist/turndown.js"&gt;https://unpkg.com/turndown@7.2.0/dist/turndown.js&lt;/a&gt;&lt;/p&gt;&#10;&lt;p&gt;下载下来保存到 &lt;code&gt;vendor/turndown.js&lt;/code&gt;（自己创建 &lt;code&gt;vendor&lt;/code&gt; 目录）。&lt;/p&gt;&#10;&lt;p&gt;&lt;strong&gt;项目结构：&lt;/strong&gt;&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 1&lt;/span&gt;&lt;span class="cl"&gt;markdown-saver/&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 2&lt;/span&gt;&lt;span class="cl"&gt;├── manifest.json&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 3&lt;/span&gt;&lt;span class="cl"&gt;├── content.js&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 4&lt;/span&gt;&lt;span class="cl"&gt;├── popup.html&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 5&lt;/span&gt;&lt;span class="cl"&gt;├── popup.js&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 6&lt;/span&gt;&lt;span class="cl"&gt;├── icons/&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 7&lt;/span&gt;&lt;span class="cl"&gt;│ ├── icon16.png&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 8&lt;/span&gt;&lt;span class="cl"&gt;│ ├── icon32.png&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 9&lt;/span&gt;&lt;span class="cl"&gt;│ ├── icon48.png&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;10&lt;/span&gt;&lt;span class="cl"&gt;│ └── icon128.png&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;11&lt;/span&gt;&lt;span class="cl"&gt;└── vendor/&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;12&lt;/span&gt;&lt;span class="cl"&gt; └── turndown.js&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;图标先随便找 4 张占位图（每个尺寸一张），后面会讲商店要求。&lt;/p&gt;</description></item><item><title>Chrome 插件开发</title><link>https://www.leanku.com/post/tools/chrome-extension-development-intro/</link><pubDate>Wed, 15 Jan 2025 00:00:00 +0800</pubDate><guid>https://www.leanku.com/post/tools/chrome-extension-development-intro/</guid><description>&lt;h2 id="从一个真实问题开始"&gt;从一个真实问题开始&lt;/h2&gt;&#10;&lt;p&gt;我经常在浏览器里看技术文章。看到好的想存到 Obsidian，复制粘贴格式全乱。打开&amp;quot;另存为&amp;quot;保存下来是带广告、导航栏、侧边栏的 HTML。想找一个干净的 Markdown 版本，要么没有，要么是闭源插件不敢用。&lt;/p&gt;&#10;&lt;p&gt;于是我开始想：我能不能自己写一个？&lt;/p&gt;&#10;&lt;p&gt;这是个典型的&amp;quot;想动手&amp;quot;时刻。但真正动手之前，有几个更前置的问题需要想清楚：&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;Chrome 插件到底是什么？和 userscript、网页工具、PWA 差在哪？&lt;/li&gt;&#10;&lt;li&gt;我想做的这个事，到底该用哪种形态？&lt;/li&gt;&#10;&lt;li&gt;学 Chrome 插件的&amp;quot;投资回报&amp;quot;如何？是一次性投入还是持续折腾？&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p&gt;写这篇文章的目的，是在你打开 &lt;code&gt;manifest.json&lt;/code&gt; 之前，帮你想清楚这三个问题。&lt;/p&gt;&#10;&lt;h2 id="插件是什么"&gt;插件是什么&lt;/h2&gt;&#10;&lt;p&gt;先把&amp;quot;插件&amp;quot;这个词拆开看。&lt;/p&gt;&#10;&lt;p&gt;&lt;strong&gt;Chrome 插件&lt;/strong&gt;（Chrome Extension），也叫浏览器扩展，本质上是一段运行在 Chrome 浏览器里的代码。它能访问一些普通网页拿不到的 API，比如读取当前标签页的 URL、修改请求头、在用户点击工具栏图标时弹出一个小页面。&lt;/p&gt;&#10;&lt;p&gt;可以把它理解为：&lt;/p&gt;&#10;&lt;blockquote&gt;&#10;&lt;p&gt;&lt;strong&gt;插件 = 对浏览器的扩展能力 + 对已有网站的增强能力&lt;/strong&gt;&lt;/p&gt;&#10;&lt;/blockquote&gt;&#10;&lt;p&gt;注意两个关键词：&lt;strong&gt;&amp;ldquo;对浏览器&amp;rdquo;&lt;/strong&gt; 和 &lt;strong&gt;&amp;ldquo;对已有网站&amp;rdquo;&lt;/strong&gt;。这两个词决定了插件能做什么、不能做什么。&lt;/p&gt;&#10;&lt;p&gt;&lt;strong&gt;对浏览器&lt;/strong&gt;意味着插件能拿到浏览器层面的能力，比如：&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;操作标签页（关闭、新建、切换）&lt;/li&gt;&#10;&lt;li&gt;读取和修改浏览器历史&lt;/li&gt;&#10;&lt;li&gt;拦截和修改网络请求&lt;/li&gt;&#10;&lt;li&gt;在工具栏添加图标&lt;/li&gt;&#10;&lt;li&gt;监听键盘快捷键&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p&gt;&lt;strong&gt;对已有网站&lt;/strong&gt;意味着插件的核心战场是&amp;quot;改造现有网站&amp;quot;，比如：&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;给维基百科加一个深色模式&lt;/li&gt;&#10;&lt;li&gt;给 GitHub 加一个一键复制文件链接的按钮&lt;/li&gt;&#10;&lt;li&gt;给掘金、知乎、CSDN 屏蔽某些干扰元素&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p&gt;&lt;strong&gt;插件能做什么、不能做什么&lt;/strong&gt;&lt;/p&gt;&#10;&lt;p&gt;能做的：&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;改造已有网站（修改 DOM、注入脚本）&lt;/li&gt;&#10;&lt;li&gt;提供一个常驻工具栏入口（点击图标触发动作）&lt;/li&gt;&#10;&lt;li&gt;跨页面保存数据（用户的偏好、笔记、历史）&lt;/li&gt;&#10;&lt;li&gt;监听浏览器事件（标签页变化、下载事件）&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p&gt;不能做（或做起来很费劲）：&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;完全独立的产品（需要服务端配合的复杂功能）&lt;/li&gt;&#10;&lt;li&gt;移动端体验（Chrome 插件不适用于移动浏览器）&lt;/li&gt;&#10;&lt;li&gt;高性能要求的事（不适合跑复杂的计算任务）&lt;/li&gt;&#10;&lt;li&gt;跨浏览器一致体验（Firefox、Edge、Safari 各有差异）&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;h2 id="什么时候该用插件"&gt;什么时候该用插件&lt;/h2&gt;&#10;&lt;p&gt;给几个真实场景，帮你判断。&lt;/p&gt;&#10;&lt;p&gt;&lt;strong&gt;适合用插件的场景：&lt;/strong&gt;&lt;/p&gt;&#10;&lt;ol&gt;&#10;&lt;li&gt;&lt;strong&gt;改造已有网站&lt;/strong&gt;：给某个你不喜欢的网站加功能或去干扰&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;跨页面工具&lt;/strong&gt;：复制当前页面内容、抓取数据、自动填表&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;浏览器层的小工具&lt;/strong&gt;：标签页管理、下载管理、截图、翻译&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;给开发者自己用&lt;/strong&gt;：调试、API 测试、页面抓取&lt;/li&gt;&#10;&lt;/ol&gt;&#10;&lt;p&gt;&lt;strong&gt;不适合用插件的场景：&lt;/strong&gt;&lt;/p&gt;</description></item></channel></rss>