<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="4.3.4">Jekyll</generator><link href="https://anl.gg/feed.xml" rel="self" type="application/atom+xml" /><link href="https://anl.gg/" rel="alternate" type="text/html" /><updated>2026-04-16T01:44:13+00:00</updated><id><a href="https://anl.gg/feed.xml">https://anl.gg/feed.xml</a></id><title type="html">Ask and learn.</title><subtitle>一个充满热情的 Ruby / JavaScript / Python 程序员，远程工作者，生活在西安，也是西安谷歌开发者社区的组织者之一。</subtitle><entry><title type="html">为了偷懒，我又重写了那个发 Telegram 的 Chrome 扩展</title><link href="https://anl.gg/post/303/" rel="alternate" type="text/html" title="为了偷懒，我又重写了那个发 Telegram 的 Chrome 扩展" /><published>2026-02-04T00:00:00+00:00</published><updated>2026-02-04T00:00:00+00:00</updated><id><a href="https://anl.gg/post/303">https://anl.gg/post/303</a></id><content type="html" xml:base="https://anl.gg/post/303/"><![CDATA[<p>之前在写 <a href="https://anl.gg/post/283/">《为了方便分享双马尾到 TG，我做了个开源的 Chrome 扩展》</a> 这篇文章时，我介绍过自己写的一个简易 Chrome 扩展。当时的初衷很简单，就是为了省去“保存图片 -&gt; 打开 TG -&gt; 粘贴 -&gt; 复制来源链接 -&gt; 发送”这一套繁琐的流程。</p>

<p>不过那个版本的工具虽然能用，但确实比较粗糙（毕竟是自用的）。所有的配置，比如 Bot Token 和 频道 ID，都是硬编码在代码文件里的。如果我只想发双马尾，那还没问题，但当我开始需要同时维护像素画频道时，问题就来了。我总不能为了发不同的频道，装两个代码一样的扩展，然后改两份代码吧？作为一个喜欢犯懒的程序员，面对重复劳动，唯一的解决办法就是——<strong>再造一个更好用的轮子</strong>。</p>

<p>于是，<strong>TelegramPoster</strong> 诞生了。</p>

<p><img width="1080" height="604" alt="TelegramPoster" src="https://github.com/user-attachments/assets/729563c9-73fb-4447-861c-8c1b7c46e281" /></p>

<h3 id="它是干什么的">它是干什么的？</h3>

<p>简单来说，这是一个通用的、可以图形化配置的 Chrome 扩展，用来帮你快速把网页上的图片发布到 Telegram 频道或群组。</p>

<p>相比于前序版本，这个“改进版”主要强在以下几点：</p>

<h4 id="1-图形化配置告别硬编码">1. 图形化配置，告别硬编码</h4>
<p>现在你不需要去改代码了。扩展提供了一个干净的选项页面，你可以在里面添加多个 Bot，配置多个频道（Channel）或群组。想发哪个频道，直接在界面上选就行。</p>

<p><img width="903" height="544" alt="Telegram Bot Management" src="https://github.com/user-attachments/assets/19aeef70-a1df-4465-8cb7-f0eda4ad0bc0" /></p>

<h4 id="2-多频道和群组管理">2. 多频道和群组管理</h4>
<p>不管是频道（Channel）还是讨论组（Group），工具都完美支持。因为我有两个频道，现在的工具支持添加发布目标。在发图的时候，下拉菜单选一下，是发给“Awesome Pigtails”还是“PixelFan”，一键切换。</p>

<p><img width="763" height="1137" alt="Telegram Chat Management" src="https://github.com/user-attachments/assets/61ae535e-84b7-41cb-93db-d408af978794" /></p>

<h4 id="3-预设的文案模板">3. 预设的文案模板</h4>
<p>这也是我最看重的功能。我分享图片时有个原则：<strong>尊重原作者，尽量保留来源</strong>。
新版扩展支持自定义文案模板。比如我可以设置成：</p>

<div class="language-text highlighter-rouge"><div class="highlight"><pre class="highlight"><code>\{\{pageTitle\}\}

From: \{\{pageUrl\}\}
</code></pre></div></div>

<p>除了标题和链接，工具还支持其它几个实用的变量：</p>

<ul>
  <li><code class="language-plaintext highlighter-rouge">\{\{pageDomain\}\}</code>: 网站域名</li>
  <li><code class="language-plaintext highlighter-rouge">\{\{pageUrlClean\}\}</code>: 去除参数的干净链接（对于清理一些追踪参数很有用）</li>
</ul>

<p>当你右键点击图片选择“Publish To Telegram”时，它会自动抓取当前网页的标题和链接填进去。不用自己复制粘贴，直接点发送就好。</p>

<h3 id="如何使用">如何使用？</h3>

<p>我是有计划把它发布到 Chrome Web Store 的，只是还需要做一些准备工作。目前的开源版本算是给大家先尝个鲜。</p>

<ol>
  <li>下载源码并安装（目前需要通过开发者模式加载）。</li>
  <li>在扩展里配置好你的 Bot 和 目标频道。</li>
  <li>在网页上也就是你浏览美图的时候，直接<strong>右键点击图片</strong>。</li>
  <li>在菜单里选择 <strong>“Publish To Telegram”</strong>。</li>
  <li>在弹出的窗口里确认一下文案（也可以临时编辑），点发布。</li>
</ol>

<p>搞定！图片就会带着配置好的文案出现在你的频道里。</p>

<h3 id="开源地址">开源地址</h3>

<p>和以前一样，这个工具也是开源的。</p>

<p>👉 <strong>Github</strong>: <a href="https://github.com/greatghoul/TelegramPoster">https://github.com/greatghoul/TelegramPoster</a></p>

<p>如果你也有管理 Telegram 频道的需求，或者纯粹想偷个懒方便地把图存到 TG 里，欢迎下载试用。如果觉得好用，别忘了去 Github 点个 Star。</p>

<h3 id="频道推荐">频道推荐</h3>

<p>最后，欢迎关注我维护的两个频道：</p>

<p><strong>PixelFan</strong>: 分享各种好看的像素画艺术</p>

<blockquote>
  <p><a href="https://t.me/PixelFanFeed">https://t.me/PixelFanFeed</a></p>
</blockquote>

<p><strong>Awesome Pigtails</strong>: 双马尾美图分享</p>

<blockquote>
  <p><a href="https://t.me/pigtails">https://t.me/pigtails</a></p>
</blockquote>

<hr />

<p>文章同步发表于微信公众号<strong>老狗拾光</strong>，欢迎关注。</p>

<p><img src="https://github.com/user-attachments/assets/1a652b8b-7f5b-4879-af52-65e1fe3f7b4d" alt="微信公众号老狗拾光" /></p>]]></content><author><name></name></author><category term="Chrome Extension" /><category term="Telegram" /><summary type="html"><![CDATA[之前在写 《为了方便分享双马尾到 TG，我做了个开源的 Chrome 扩展》 这篇文章时，我介绍过自己写的一个简易 Chrome 扩展。当时的初衷很简单，就是为了省去“保存图片 -&gt; 打开 TG -&gt; 粘贴 -&gt; 复制来源链接 -&gt; 发送”这一套繁琐的流程。]]></summary></entry><entry><title type="html">我开始使用纸笔记录习惯养成了</title><link href="https://anl.gg/post/300/" rel="alternate" type="text/html" title="我开始使用纸笔记录习惯养成了" /><published>2026-01-12T00:00:00+00:00</published><updated>2026-01-12T00:00:00+00:00</updated><id><a href="https://anl.gg/post/300">https://anl.gg/post/300</a></id><content type="html" xml:base="https://anl.gg/post/300/"><![CDATA[<p>想要长期坚持习惯，真的挺不容易的，我之前一直是使用习惯养成之类的 App，但是时长了之后，就有点腻了。鉴于我平时更倾向于 使用纸笔来规划待办事项，所以我就想着干脆习惯也使用纸笔来记录。</p>

<p>有天我我偶然打开 github，然后突然就觉得，为什么不做一个年度习惯追踪的图表呢？</p>

<p><img src="https://github.com/user-attachments/assets/e6f31472-374d-456a-a2b0-c71cc2bd71fc" alt="Image" /></p>

<p>于是立马下载了几个 Excel 模板，结果改一会儿就烦了，我实在是没有什么 Excel 设计的天赋，设置合适的格式和列宽什么的， 需要大师的重复工具，而我又着实是一个懒人，就决定自己做一个生成器，这样可以用程序精准的生成表格的尺寸和样式。</p>

<p><img src="https://github.com/user-attachments/assets/f4380bdd-14e9-457b-b775-93742443b0f1" alt="Image" /></p>

<p>于是用网页做了一版简单图表，我把它打印出来贴在书柜上，这样我随时都能看到，在每天的格式上画线表示一次，用了一段时间， 效果不错。不过就是每次找日期都需要横向看到最左边，有时候还容易画错。</p>

<p>于是又小小的改进了一下，直接把日期写在格子里面，并且标出周末，这样找日期就方便很多了。</p>

<p><img src="https://github.com/user-attachments/assets/0796fcf3-c923-45d2-bd1a-b129eee24d2b" alt="Image" /></p>

<p>这个工具是为方便打印而设计的，如果尝试一张 A4 纸只打印一张图表太过浪费，还支持打印多张图表在一张纸里面，最多支持4张。 这样更节省纸张。可以指定特定的年份来标记周末，也可以不设定年份，这样一个月最多31 格，可以自己自由发挥。</p>

<p>一页多张这个功能，虽然如果使用打印机的节省纸张的功能，也能实现，但是它的入口有点深，普通用户可能需要一些操作才能找到。 而让程序直接在页面上画出多张，就更加简单方便了。</p>

<p><img src="https://github.com/user-attachments/assets/7d6359a3-960c-493b-b981-30e2635da1a4" alt="Image" /></p>

<p>你可以通过访问这个网页或者查看原文来自己生成图表</p>

<p><a href="https://feather-tools.com/habit-tracker">https://feather-tools.com/habit-tracker</a></p>

<p>也可以直接下载图片打印，开启你的 2026 年的习惯养成之旅。</p>

<p><img src="https://github.com/user-attachments/assets/138969f4-e5ed-40f9-9cc0-64ec116bfc4b" alt="Image" /></p>

<hr />

<p>文章同步发表于微信公众号<strong>老狗拾光</strong>，欢迎关注。</p>

<p><img src="https://github.com/user-attachments/assets/1a652b8b-7f5b-4879-af52-65e1fe3f7b4d" alt="微信公众号老狗拾光" /></p>]]></content><author><name></name></author><summary type="html"><![CDATA[想要长期坚持习惯，真的挺不容易的，我之前一直是使用习惯养成之类的 App，但是时长了之后，就有点腻了。鉴于我平时更倾向于 使用纸笔来规划待办事项，所以我就想着干脆习惯也使用纸笔来记录。]]></summary></entry><entry><title type="html">使用 MacroDroid 自制简易报时器应用</title><link href="https://anl.gg/post/298/" rel="alternate" type="text/html" title="使用 MacroDroid 自制简易报时器应用" /><published>2025-12-22T00:00:00+00:00</published><updated>2025-12-22T00:00:00+00:00</updated><id><a href="https://anl.gg/post/298">https://anl.gg/post/298</a></id><content type="html" xml:base="https://anl.gg/post/298/"><![CDATA[<p>作为一个常年居家办公的程序员+奶爸，日常做饭，接送孩子都是必不可少的，尤其是这一学期，孩子不继续在学校午托，而是每天接回家吃午饭睡午觉，我一天和孩子打交道的时间也变得多了起来，早晚和中午都需要接送。</p>

<p>尤其是中午本就时间紧张，需要格外注意做饭和路上的时间消耗。之前我都是通过定闹钟的方式，不过总是有时间焦虑，时不时要看下手机上的时间，有时手还是湿的很不方便，于是想找个自动报时的应用。在市场上找了几个，都不满意，于是决定自己做一个。</p>

<p>正好今年比较迷 MacroDroid，这次就是它了。</p>

<blockquote>
  <p>MacroDroid 是一款操作简单、功能强大的安卓自动化应用，通过选择触发器、动作和可选约束，无需编程知识就能快速创建宏，自动完成文件管理、模式切换等各类手机任务。</p>
</blockquote>

<p>MacroDroid 是一款操作简单、功能强大的安卓自动化应用，通过选择触发器、动作和可选约束，无需编程知识就能快速创建宏，自动完成文件管理、模式切换等各类手机任务。</p>

<p><img width="1080" height="392" alt="Image" src="https://github.com/user-attachments/assets/509ccae0-1a02-478e-a4ce-ee39d6b3668c" /></p>

<p><a href="https://www.macrodroid.com/">https://www.macrodroid.com/</a></p>

<h2 id="功能简介">功能简介</h2>

<p>对于这个报时应用，我的设计是这样的：</p>

<h3 id="支持语音播报消耗的分钟数或几点几分">支持语音播报消耗的分钟数或几点几分</h3>

<p>考虑过在启动报时时选择使用哪种类型，但是每次都要这样选感觉很麻烦，所幸我是用 MacroDroid 而不是开发应用，可以直接复制成两个脚本，各自使用不同的时间格式来播报，这样可以减少一次点击。相比应用，脚本还是方便呀。</p>

<ul>
  <li><strong>按时分报的模式</strong>
主要是为了关注接送孩子的时间点而设计的，比如备菜备一半，听到时间可能来不及了，可以先不起锅，避免卡着时间不上不下。</li>
  <li><strong>按分钟报的模式</strong>
主要是为了应对计划时长的活动，比如我日常吃完饭会下楼健走半小时，或者睡觉前玩半小时游戏，可以通过播报知道自己的锻炼或游玩进度。</li>
</ul>

<p>对于播报，还需要一个额外的设置，就是间隔时长，可以从一些预定义的选项中直接选择，比如 1分钟，2分钟，5分钟，半小时等。</p>

<p><img width="1080" height="1186" alt="Image" src="https://github.com/user-attachments/assets/42ef3ad7-9b73-4345-93bd-0a156341c777" /></p>

<h3 id="可以方便的启动和结束报时">可以方便的启动和结束报时</h3>

<p>MacroDroid 有一个很赞的设计，就是侧边滑出快捷启动脚本，这样在任何时候，我都可以快捷启动报时脚本。</p>

<p><img src="https://github.com/user-attachments/assets/772ccee6-1445-4995-9b36-244fb12c4dc6" alt="Image" /></p>

<p>对于快速结束，会在计时时显示一个通知，一方面显示当时的时间消耗，一方面用于点击结束计时。</p>

<p><img width="1080" height="2412" alt="Image" src="https://github.com/user-attachments/assets/ca302cb3-a808-4c7a-90af-e632f44cde3d" /></p>

<h2 id="脚本概览">脚本概览</h2>

<p>这是从 MacroDroid 导出的脚本概览图，大致能看出这个报时应用的逻辑：<strong>在循环中计算时间后按照格式语音播报，然后等待指定的时间间隔再继续直到被中断。</strong></p>

<p><img width="726" height="1314" alt="Image" src="https://github.com/user-attachments/assets/05325929-db76-4dd4-a94d-4f125a8274b2" /></p>

<p>你可以参考着制作自己的报时脚本，或者直接下载我的文件。</p>

<p><a href="https://t.zsxq.com/XOM0v">https://t.zsxq.com/XOM0v</a></p>

<p><a href="https://github.com/user-attachments/files/24288122/MacroDroid.zip">MacroDroid报时宏.zip</a></p>

<p>其实不止是 MacroDroid, Android 上面的 Automate, Tasker, 以及 iOS 上面的快捷指令都可以很容易做出这样的脚本，也很容易按自己的需求做调整。</p>

<hr />

<p>文章同步发表于微信公众号<strong>老狗拾光</strong>，欢迎关注。</p>

<p><img src="https://github.com/user-attachments/assets/1a652b8b-7f5b-4879-af52-65e1fe3f7b4d" alt="微信公众号老狗拾光" /></p>]]></content><author><name></name></author><category term="分享工具" /><category term="MacroDroid" /><summary type="html"><![CDATA[作为一个常年居家办公的程序员+奶爸，日常做饭，接送孩子都是必不可少的，尤其是这一学期，孩子不继续在学校午托，而是每天接回家吃午饭睡午觉，我一天和孩子打交道的时间也变得多了起来，早晚和中午都需要接送。]]></summary></entry><entry><title type="html">ContextMenuManager - 开源 Windows 右键菜单管理工具</title><link href="https://anl.gg/post/292-context-menu-manager/" rel="alternate" type="text/html" title="ContextMenuManager - 开源 Windows 右键菜单管理工具" /><published>2025-11-18T00:00:00+00:00</published><updated>2025-11-18T00:00:00+00:00</updated><id><a href="https://anl.gg/post/292-context-menu-manager">https://anl.gg/post/292-context-menu-manager</a></id><content type="html" xml:base="https://anl.gg/post/292-context-menu-manager/"><![CDATA[<p><a href="https://github.com/BluePointLilac/ContextMenuManager">https://github.com/BluePointLilac/ContextMenuManager</a></p>

<p>最近想给 Windows 加一个文件夹右键使用 Trae 打开的菜单，但是自己整注册表好几次都没有成功，后来找了这个工具，很容易就弄好了。对于自己不熟悉的东西，还是使用图形界面工具更方便一些。</p>

<blockquote>
  <p>开源，官方说明是支持到 Win10, 但其实 Win11 亲测可用。可以添加/编辑/删除/启用/禁用各项右键菜单，还支持新增/打开方式/发送到这些折叠菜单的项目。</p>
</blockquote>

<p><img width="852" height="642" alt="Image" src="https://github.com/user-attachments/assets/06086867-e1df-4fcc-9e0e-44acc2782035" /></p>

<p><img width="775" height="308" alt="Image" src="https://github.com/user-attachments/assets/df81cf4c-32e3-415f-b66d-33907d007d59" /></p>

<hr />

<p>文章同步发表于微信公众号<strong>老狗拾光</strong>，欢迎关注。</p>

<p><img src="https://github.com/user-attachments/assets/1a652b8b-7f5b-4879-af52-65e1fe3f7b4d" alt="微信公众号老狗拾光" /></p>]]></content><author><name></name></author><category term="分享工具" /><summary type="html"><![CDATA[https://github.com/BluePointLilac/ContextMenuManager]]></summary></entry><entry><title type="html">做了一个批量为图片标注序号的工具</title><link href="https://anl.gg/post/291/" rel="alternate" type="text/html" title="做了一个批量为图片标注序号的工具" /><published>2025-08-04T00:00:00+00:00</published><updated>2025-08-04T00:00:00+00:00</updated><id><a href="https://anl.gg/post/291">https://anl.gg/post/291</a></id><content type="html" xml:base="https://anl.gg/post/291/"><![CDATA[<p>继上次尝试<a href="https://www.anl.gg/post/288/">用纯浏览器生成视频</a>之后，我最近又做了一个新尝试，使用纯浏览器端处理图片并打包成ZIP，简单的图片处理并不是什么难题，关键是打包的实现，不过经过验证发现是完全可行的。</p>

<h3 id="先简单看下成果">先简单看下成果</h3>

<p><img src="https://github.com/user-attachments/assets/6848f3ac-4606-445e-ba39-a56acf8aba75" alt="Image" /></p>

<p><img src="https://github.com/user-attachments/assets/ec5e6a39-0182-41da-af7e-f202622c4e86" alt="Image" /></p>

<p><a href="https://feathertools.top/number-images">https://feathertools.top/number-images</a></p>

<h3 id="功能介绍">功能介绍</h3>

<p>这是一个批量为图片加数字/字母序号标注的在线工具，虽然是在线工具，但是文件并不会上传到服务器，只是加载到浏览器内存里面，后面的图片处理和打包下载也都是完全本地实现的，主打一个数据安全。</p>

<p>工具支持对选择的图片进行拖拽排序并对序号的类型，起始值，以及外观和位置做简单的自定义。</p>

<p>字母类型序号可以支持到 Excel 那种列名的形式 A, B, AA, AB, AC…，只要电脑内存够大，理论上是可以处理很多图片的，</p>

<h3 id="想法来源">想法来源</h3>

<p>早在十几年前，当我媳妇还是女朋友的时候，我帮她给论文用的图片素材添加标号时，PS 了半天都没搞定，非常丢脸，后来用 Python PIL 实现了，才渡过了难关。</p>

<p>最近做工具站时，想到可能别人的女朋友也有类似的需求，又玩不转P图工具，没有趁手的软件，使用其它在线工具又担心自己的资料泄露。那狗哥我的工具就很适合了，这个功德我得做。</p>

<p><img src="https://github.com/user-attachments/assets/f208c85b-5d2d-4094-8a40-5b97ece7c04b" alt="Image" /></p>

<p><a href="https://www.anl.gg/post/134-draw-char-in-picture-using-pil/">https://www.anl.gg/post/134-draw-char-in-picture-using-pil/</a></p>

<h3 id="技术细节">技术细节</h3>

<p>虽然部分代码是 AI 写的，但是我自己也是参与了技术细节的，这里简单分享一下。</p>

<h4 id="1-图片排序">1. 图片排序</h4>

<p>最开始的拖拽排序是用 dragstart, dragenter, dragend 事件实现的，但是在移动端测试时，发现不工作，后来又加入了 touch 相关事件的支持，但是还是问题多多，后来查询资料后才发现可以使用 pointerdown, pointermove, pointerup 来替代 drag 和 touch 事件来兼容桌面端和移动端。</p>

<p><img src="https://github.com/user-attachments/assets/953ee25e-815b-479d-bca2-629e5a153515" alt="Image" /></p>

<h4 id="2-字母序号生成">2. 字母序号生成</h4>

<p>为了支持 A, B, AC, AD, AAA 这样 Excel 风格的序号，写了一个简单的方法。</p>

<div class="language-js highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">function</span> <span class="nf">numberToLetter</span><span class="p">(</span><span class="nx">number</span><span class="p">)</span> <span class="p">{</span>
    <span class="k">if </span><span class="p">(</span><span class="nx">number</span> <span class="o">&lt;=</span> <span class="mi">0</span><span class="p">)</span> <span class="k">return</span> <span class="dl">''</span><span class="p">;</span>
    
    <span class="kd">const</span> <span class="nx">remainder</span> <span class="o">=</span> <span class="nx">number</span> <span class="o">%</span> <span class="mi">26</span> <span class="o">||</span> <span class="mi">26</span><span class="p">;</span>
    <span class="kd">const</span> <span class="nx">letter</span> <span class="o">=</span> <span class="nb">String</span><span class="p">.</span><span class="nf">fromCharCode</span><span class="p">(</span><span class="mi">64</span> <span class="o">+</span> <span class="nx">remainder</span><span class="p">);</span>
    <span class="kd">const</span> <span class="nx">quotient</span> <span class="o">=</span> <span class="nb">Math</span><span class="p">.</span><span class="nf">floor</span><span class="p">((</span><span class="nx">number</span> <span class="o">-</span> <span class="mi">1</span><span class="p">)</span> <span class="o">/</span> <span class="mi">26</span><span class="p">);</span>
    
    <span class="k">return</span> <span class="nf">numberToLetter</span><span class="p">(</span><span class="nx">quotient</span><span class="p">)</span> <span class="o">+</span> <span class="nx">letter</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>

<h4 id="3-为图片生成-blob-url">3. 为图片生成 blob URL</h4>

<p>因为可能涉及比较多数据或者比较大图片的处理，我又没有做上传的功能，为了方便图片显示，为图片生成了 Blob URL，类似下面的 URL，用于图片显示。</p>

<p>blob:<a href="https://feathertools.top/9d8ec45c-57ce-4685-b728-530a76e95918">https://feathertools.top/9d8ec45c-57ce-4685-b728-530a76e95918</a></p>

<div class="language-js highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">function</span> <span class="nf">getBlob</span><span class="p">(</span><span class="nx">canvas</span><span class="p">,</span> <span class="nx">quality</span> <span class="o">=</span> <span class="mf">0.9</span><span class="p">)</span> <span class="p">{</span>
    <span class="k">return</span> <span class="k">new</span> <span class="nc">Promise</span><span class="p">((</span><span class="nx">resolve</span><span class="p">)</span> <span class="o">=&gt;</span> <span class="p">{</span>
        <span class="nx">canvas</span><span class="p">.</span><span class="nf">toBlob</span><span class="p">(</span><span class="nx">resolve</span><span class="p">,</span> <span class="dl">'</span><span class="s1">image/png</span><span class="dl">'</span><span class="p">,</span> <span class="nx">quality</span><span class="p">);</span>
    <span class="p">});</span>
<span class="p">}</span>

<span class="kd">const</span> <span class="nx">processedBlob</span> <span class="o">=</span> <span class="k">await</span> <span class="nf">getBlob</span><span class="p">(</span><span class="nx">canvas</span><span class="p">);</span>
<span class="nx">URL</span><span class="p">.</span><span class="nf">createObjectURL</span><span class="p">(</span><span class="nx">processedBlob</span><span class="p">);</span>
</code></pre></div></div>

<p>按理说，生成了 Blob URL，应该在合适的时机销毁的，但是我目前还没有想到比较合适的时机，只能暂时寄希望于标签页关闭了。</p>

<div class="language-js highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nx">URL</span><span class="p">.</span><span class="nf">revokeObjectURL</span><span class="p">(</span><span class="nx">objectURL</span><span class="p">)</span>
</code></pre></div></div>

<h4 id="4-打包-zip">4. 打包 ZIP</h4>

<p>为了方便下载处理后的图片，需要将文件打包成 ZIP，这里使用了 JSZip 这个包。</p>

<div class="language-js highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">const</span> <span class="nx">zip</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">JSZip</span><span class="p">();</span>
<span class="k">for </span><span class="p">(</span><span class="kd">let</span> <span class="nx">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="nx">i</span> <span class="o">&lt;</span> <span class="nx">processedImages</span><span class="p">.</span><span class="nx">length</span><span class="p">;</span> <span class="nx">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span>
    <span class="kd">const</span> <span class="nx">image</span> <span class="o">=</span> <span class="nx">processedImages</span><span class="p">[</span><span class="nx">i</span><span class="p">];</span>
    <span class="nx">zip</span><span class="p">.</span><span class="nf">file</span><span class="p">(</span><span class="s2">`image_</span><span class="p">${</span><span class="nx">i</span> <span class="o">+</span> <span class="mi">1</span><span class="p">}</span><span class="s2">_</span><span class="p">${</span><span class="nx">image</span><span class="p">.</span><span class="nx">name</span><span class="p">}</span><span class="s2">`</span><span class="p">,</span> <span class="nx">image</span><span class="p">.</span><span class="nx">processedBlob</span><span class="p">);</span>
<span class="p">}</span>

<span class="c1">// Generate the zip file and trigger download</span>
<span class="kd">const</span> <span class="nx">content</span> <span class="o">=</span> <span class="k">await</span> <span class="nx">zip</span><span class="p">.</span><span class="nf">generateAsync</span><span class="p">({</span> <span class="na">type</span><span class="p">:</span> <span class="dl">'</span><span class="s1">blob</span><span class="dl">'</span> <span class="p">});</span>
<span class="nf">downloadFile</span><span class="p">(</span><span class="nx">content</span><span class="p">,</span> <span class="dl">'</span><span class="s1">processed_images.zip</span><span class="dl">'</span><span class="p">);</span>
</code></pre></div></div>

<hr />

<p>文章同步发表于微信公众号<strong>老狗拾光</strong>，欢迎关注。</p>

<p><img src="https://github.com/user-attachments/assets/1a652b8b-7f5b-4879-af52-65e1fe3f7b4d" alt="微信公众号老狗拾光" /></p>]]></content><author><name></name></author><category term="分享创造" /><summary type="html"><![CDATA[继上次尝试用纯浏览器生成视频之后，我最近又做了一个新尝试，使用纯浏览器端处理图片并打包成ZIP，简单的图片处理并不是什么难题，关键是打包的实现，不过经过验证发现是完全可行的。]]></summary></entry><entry><title type="html">你其实可以尝试用纸笔来记录血压</title><link href="https://anl.gg/post/290/" rel="alternate" type="text/html" title="你其实可以尝试用纸笔来记录血压" /><published>2025-07-22T00:00:00+00:00</published><updated>2025-07-22T00:00:00+00:00</updated><id><a href="https://anl.gg/post/290">https://anl.gg/post/290</a></id><content type="html" xml:base="https://anl.gg/post/290/"><![CDATA[<p>人到中年，多多少少是有些提升的，老狗我作为一个终身学习者，兢兢业业这么多年，不但增长了知识和技能，发际线和体重自然也是水涨船高，尤其近几年，血压也不甘落后，成为了困扰我工作和生活的主要问题。</p>

<p>对于高血压患者，监测血压就变成了日常，但是忙起来，却是非常容易忘记，试过很多应用，刚开始还能规律的记录，后来也就不了了之了。唯一坚持的比较久的方式，是网上找了个 Excel，打印出来贴柜子上，用纸笔来自己画折线图记录，随手可得，唯一的缺点是，<strong>那个 Excel 设计的不是很合理，标线粒度太大，绘制时有些麻烦</strong>，我甚至自己用直尺和铅笔画了线。</p>

<p>Excel 这东西，用过的人都知道，想要大量修改样式，那是非常麻烦的，所以画一段时间，也就不画了。</p>

<p><img src="https://github.com/user-attachments/assets/6be31a49-4104-4151-9fde-c343807fe3dc" alt="Image" /></p>

<p>最近因为擅自停药又疏于锻炼，已经被媳妇说了很多次了。我本以为自己不难受就说明没问题，前几天偷偷量了几次，结果并不理想，看来是自欺欺人了，痛定思痛，老狗我下定决心重新把血压控制起来。</p>

<p>正好最近在做自己的工具站，想着吃自己的狗粮，于是给自己做了一个血压追踪图的生成打印工具，可以生成月/周/双周的血压追踪图表：</p>

<ul>
  <li>适配了 A4 纸的尺寸，可以直接打印。</li>
  <li>月固定为 31 天，保存图片后，可以重复打印，无需重复生成。</li>
  <li>每天分成3个刻度，方便记录早中晚的血压。</li>
</ul>

<p><img src="https://github.com/user-attachments/assets/20f42d05-9135-4ad6-90ee-f05b7d9ccfaf" alt="Image" /></p>

<p>打印出来后，可以用不同的颜色的笔来记录舒张压，收缩压以及心跳值，方便又直观。</p>

<p>如果你也是高血压患者，不妨试试这种记录方式。身体是革命的本钱，大家共勉。</p>

<p><a href="https://feathertools.top/printable-blood-pressure-chart">https://feathertools.top/printable-blood-pressure-chart</a></p>

<hr />

<p>文章同步发表于微信公众号<strong>老狗拾光</strong>，欢迎关注。</p>

<p><img src="https://github.com/user-attachments/assets/1a652b8b-7f5b-4879-af52-65e1fe3f7b4d" alt="微信公众号老狗拾光" /></p>]]></content><author><name></name></author><category term="分享创造" /><summary type="html"><![CDATA[人到中年，多多少少是有些提升的，老狗我作为一个终身学习者，兢兢业业这么多年，不但增长了知识和技能，发际线和体重自然也是水涨船高，尤其近几年，血压也不甘落后，成为了困扰我工作和生活的主要问题。]]></summary></entry><entry><title type="html">终于解决了在微信公众号插入链接的问题</title><link href="https://anl.gg/post/289/" rel="alternate" type="text/html" title="终于解决了在微信公众号插入链接的问题" /><published>2025-07-19T00:00:00+00:00</published><updated>2025-07-19T00:00:00+00:00</updated><id><a href="https://anl.gg/post/289">https://anl.gg/post/289</a></id><content type="html" xml:base="https://anl.gg/post/289/"><![CDATA[<p>在上一篇文章 <a href="https://www.anl.gg/post/288/">沙雕图发布流程再优化，本地存储+自动配音生成视频</a> 中，我有预告会分享我在公众号文章中插入链接二维码所使用的工具，老狗我向来言出法随的，今天就正式把我的二维码生成工具做成独立的 Chrome 扩展，开源出来啦。</p>

<p><img src="https://github.com/user-attachments/assets/41f3ef62-65b0-4d90-add2-160908b9907e" alt="Image" /></p>

<p>这种带页面标题和链接信息的二维码，我在自己的两个公众号上面都有大量使用。</p>

<h3 id="前世今生">前世今生</h3>

<p>之前远程工作者停更，也有很大一部分原因是放超链接太不方便了，而我分享的又大都是资源类的内容，链接使用的比较频繁，作为个人订阅号，没有外链权限，想要让读者能够方便的跳转到目标链接，还真是不容易。</p>

<p>回想自己一步步改进插入链接二维码方式的心路历程，还真是有点自我感动：</p>

<ol>
  <li><a href="https://www.anl.gg/post/272/">分享工具 - 设计工具，二维码生成器，计算器以及侧边栏笔记</a> 的时候，我是使用二维码生成的网站，搭配一个在线设计工具网站制作卡片模板，每次疯狂复制粘贴，才能搞定一个二维码卡片的制作。</li>
  <li><a href="https://www.anl.gg/post/276/">自动化：小书签已经不够用了，上油猴脚本！</a>的时候，我是借助油猴脚本来通过 Canvas 绘制二维码信息卡，已经快了很多了，但是只能支持特定的网站。</li>
  <li>之后我还分享了如何借助 Vibe Coding 来一步步制作二维码信息卡生成器的详细过程。<a href="https://www.anl.gg/post/278/">自动化：借助 AI 为 Pixilart 网站创建二维码分享卡片</a></li>
</ol>

<p>后来又做了更通用的生成器在自用 Chrome 扩展里面，已经极大的提高了效率了。</p>

<p><img src="https://github.com/user-attachments/assets/a0edd0b7-fad8-47cd-bbc5-55c43103dd24" alt="Image" /></p>

<p>这一步步的改进，都是在慢慢积累力量，提高效率，我很喜欢这种慢慢进步的感觉。</p>

<h3 id="上线-chrome-商店">上线 Chrome 商店</h3>

<p>当我自己日常使用已经没有什么大问题的时候，我把这个功能发布成了一个独立的 Chrome 浏览器扩展，开源并上线到了 Chrome Webstore.</p>

<p><a href="https://chromewebstore.google.com/detail/link-qrcode-generator/jbadicnkfjhcogmfcbkgdbfefnkekblj">https://chromewebstore.google.com/detail/link-qrcode-generator/jbadicnkfjhcogmfcbkgdbfefnkekblj</a></p>

<p>主要特性：</p>

<ul>
  <li>🚀 <strong>一键生成</strong>：立即创建包含页面标题和URL的二维码</li>
  <li>🔍 <strong>信息丰富的二维码</strong>：用户在扫描前即可看到网页详情 - 告别盲目链接！</li>
  <li>🔄 <strong>自动填充</strong>：自动填充当前页面信息</li>
  <li>✏️ <strong>可自定义</strong>：随时编辑标题或URL - 二维码立即更新</li>
  <li>📋 <strong>轻松分享</strong>：右键点击复制或保存二维码图片</li>
  <li>🌐 <strong>多语言支持</strong>：支持英文和中文</li>
  <li>🔒 <strong>安全本地</strong>：二维码完全在本地生成，不会向任何服务器发送数据</li>
</ul>

<h3 id="代码开源">代码开源</h3>

<p>项目同时也开源在 Github</p>

<p><a href="https://github.com/greatghoul/CrxLinkQRCode">https://github.com/greatghoul/CrxLinkQRCode</a></p>

<p>目前生成卡片的功能还比较简单，只有一种样式，宽度也是固定的，不过后面我都会改进的，添加更多的定制功能、卡片样式和排版，以适应更多场景。</p>

<p>我只做了对 Chrome 浏览器的适配，别的内核的浏览器，我没有做测试，如果不可以用，你可以尝试自己修改代码，本项目使用宽松的 MIT 开源协议。</p>

<p>扩展采用无构建方式开发，修改文件立即生效，不需要复杂的 Build 过程，即使你不太懂开发，也可以借助 AI 来做简单的修改和样式调整。</p>

<h3 id="免安装版本">免安装版本</h3>

<p>除了扩展程序，我也提供了一个免安装的在线版本，不过在线版本因为没有办法借力 Chrome  Extension 的 API 来获取网页信息，抓取网页标题的功能对于一些反爬限制比较强的网站，可能会失效，有时需要自己编辑修改标题。</p>

<p><img src="https://github.com/user-attachments/assets/f1839416-f1c8-441c-a984-088620368b1c" alt="Image" /></p>

<p><a href="https://feathertools.top/rich-qrcode">https://feathertools.top/rich-qrcode</a></p>

<hr />

<p>文章同步发表于微信公众号<strong>老狗拾光</strong>，欢迎关注。</p>

<p><img src="https://github.com/user-attachments/assets/1a652b8b-7f5b-4879-af52-65e1fe3f7b4d" alt="微信公众号老狗拾光" /></p>]]></content><author><name></name></author><category term="分享创造" /><summary type="html"><![CDATA[在上一篇文章 沙雕图发布流程再优化，本地存储+自动配音生成视频 中，我有预告会分享我在公众号文章中插入链接二维码所使用的工具，老狗我向来言出法随的，今天就正式把我的二维码生成工具做成独立的 Chrome 扩展，开源出来啦。]]></summary></entry><entry><title type="html">沙雕图发布流程再优化，本地存储+自动配音生成视频</title><link href="https://anl.gg/post/288/" rel="alternate" type="text/html" title="沙雕图发布流程再优化，本地存储+自动配音生成视频" /><published>2025-07-18T00:00:00+00:00</published><updated>2025-07-18T00:00:00+00:00</updated><id><a href="https://anl.gg/post/288">https://anl.gg/post/288</a></id><content type="html" xml:base="https://anl.gg/post/288/"><![CDATA[<p>之前有发过一篇文章<a href="https://www.anl.gg/post/280/">[自动化] 为了方便发今日头条，我做了一个浏览器扩展</a>，介绍我借助浏览器扩展，快速收集沙雕图到 Notion 然后生成图文后发布到今日头条的过程。</p>

<p>最近在原本生成文章的基础上，我对这个扩展做了一些大的升级：</p>

<p><img src="https://github.com/user-attachments/assets/a44a1c62-44d4-4bd9-96c2-b034c1f7c366" alt="Image" /></p>

<ol>
  <li>放弃 Notion 改用本地存储来管理图片素材</li>
  <li>加入视频生成功能，自动剪辑和配音选择的图文，生成横版和竖版视频</li>
</ol>

<h3 id="为什么放弃-notion">为什么放弃 Notion</h3>

<p>在上一篇文章中，我有讲过，Notion 的上传附件的 API 有问题，只能借助第三方平台，这样很不方便，导致整理添加素材的时间很长，因为多了一个请求。其实后台我有换到 Airtable，它的 API 支持更全面，管理起来也更方便，但是每次保存图片素材依然要等待好几秒。</p>

<p><img width="1080" height="764" alt="Image" src="https://github.com/user-attachments/assets/1d5ad80f-fb90-44f5-b97c-2fc29b31733c" /></p>

<p>因为主要是自用，而且我也<strong>暂时没有同步的需求</strong>，所以又改为使用本地存储，使用 IndexedDB 来在浏览器本地管理图片素材了。</p>

<p><img width="796" height="239" alt="Image" src="https://github.com/user-attachments/assets/65be6103-97b9-4498-9ad3-af20f3c11df6" /></p>

<p>当然还有一个目的，就是我想把这个扩展开源处理，给更多普通人使用，所以想尽量减小存储功能的依赖。</p>

<p>而且改为本地存储，保存图片速度那自然是极大的提升。</p>

<p><img src="https://github.com/user-attachments/assets/6301ca58-5bec-492b-ad81-23ee8b1fdfe2" alt="Image" /></p>

<h3 id="加入视频生成功能">加入视频生成功能</h3>

<p>沙雕图这种东西，似乎在头条没有什么市场，图文几乎没有什么阅读量，我之前有试过手动剪辑成视频，效果比文章好一些（但是效果还是惨淡），发到抖音上面，播放还能更多一些。</p>

<p><img width="1080" height="676" alt="Image" src="https://github.com/user-attachments/assets/e62752d1-4a31-41da-8437-7e2eb35a52c3" /></p>

<p>我猜测，一方面，相比图文，大众更愿意尝试视频内容。另一方面，头条的用户群体对沙雕图这种年轻人玩的东西，可能本身也不太感冒，一些梗，他们也看不懂。</p>

<p><img width="1080" height="527" alt="Image" src="https://github.com/user-attachments/assets/49142a23-cf3b-4adb-8b12-adc359cd89fc" /></p>

<p>视频虽然美好，但是剪辑实在太累了，完全不想搞，之前搞过一个宠物类型讲故事的抖音号，试着剪辑过几个作品，效果还不错，但是剪辑的工作实在让我提不起兴趣继续去尝试。人太懒了，没有办法。</p>

<p>其实沙雕图我也不太想继续剪辑的，但是我无意中发现了 Bilibili 开源的一个视频剪辑的 JavaScript Package, WebAV，竟然可以直接在浏览器端进行视频合成。这一下打开了新世界的大门。</p>

<p><a href="https://www.bilibili.com/opus/993580696128716883">纯Web视频剪辑 - 哔哩哔哩</a></p>

<p><a href="https://github.com/WebAV-Tech/WebAV">Github - WebAV-Tech/WebAV</a></p>

<p>简单了解之后，知道是使用的 WebCodecs API 进行的视频渲染的工作，于是让 AI 做了简单的尝试后，我发现这个方案可行，可以解决我不想手动剪辑视频的大问题。</p>

<p>不过我的扩展使用了纯前端无构建的方案，不想使用这么重的库，所以直接使用 WebCodecs 完成了图片生成视频幻灯片的工作。</p>

<video controls="" src="https://github.com/user-attachments/assets/de18eb32-b536-4dea-b22f-b2ab02657ca8"></video>

<h3 id="文本配音">文本配音</h3>

<p>你可能注意到，上面生成的视频中，是有配音的。没错，我加了配音，不然光播放图片显得很突兀，而且观众可能也没有耐心去读图上片的文字，而且有时候，图上并没有文字或者我对图片有自己的见解。看图时顺便播放解说是个不错的选择。</p>

<p>我本来是想用 Windows自带的 TTS 合成的，效果虽然不好，但是重在免费。但可惜的是，虽然支持合成语音，但是不支持录制并渲染到视频里面，只能寻找 API 了。</p>

<p>逛了一圈，最终选择了 Amazon Polly，毕竟它的免费配额还蛮多的。</p>

<p><img src="https://github.com/user-attachments/assets/e05e4ced-d736-431b-ba9a-3e3cbb4e4ab3" alt="Image" /></p>

<p><a href="https://aws.amazon.com/cn/polly/">https://aws.amazon.com/cn/polly/</a></p>

<p>通过 Amazon Polly 将每张图片的描述文字转换为中文语音，插入到视频中，并让对应的图片和音频保持一样的时长再切换到下一张。</p>

<p>我是想把工具开源的，这个服务只能免费用一年，而且国内用户并不是很方便申请，所以后面我其实还是想换成国内的服务或者其它易于获得的免费方案的。如果你有这方面的经验，欢迎在评论区告知。Image</p>

<p>总之，这样一个简易的带语音解说的幻灯片视频就出来了。为了让视频显得活泼一些，我还在背景中循环播放了一段轻快的音乐。</p>

<p><a href="https://pixabay.com/music/happy-childrens-tunes-cute-happy-kids-354678/">https://pixabay.com/music/happy-childrens-tunes-cute-happy-kids-354678/</a></p>

<h3 id="视频转码">视频转码</h3>

<p>通过 WebCodecs 生成的视频，是 webm 格式的，虽然也可以上传到头条等平台，但是不支持提取封面，还是 mp4 格式适配性更强一些。</p>

<p><img src="https://github.com/user-attachments/assets/1595cf75-8af2-44c5-b452-56152b395ee6" alt="Image" /></p>

<p>但我有尝试过通过浏览器生成 MP4 视频，但是都可耻的失败了，一方面需要更多的依赖库，还和浏览器环境有关系。另一方面我本身对视频渲染的技术并不熟悉，即使有 AI 加持，出了问题我依然排查不出来。不想在这上面浪费时间，于是转换思路，使用 ffmpeg 来实现转码的工作。</p>

<video controls="" src="https://github.com/user-attachments/assets/3b603d5e-8cdf-43fb-9895-4230fb328499"></video>

<p>我写了一个 BAT 脚本来查看下载文件夹中的 .webm 文件，然后通过输入选择来实现快速转换。</p>

<p>关键命令是</p>

<div class="language-bat highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">set</span> <span class="s2">"FFMPEG_PATH=C:\Applications\ffmpeg\bin\ffmpeg.exe"</span>
<span class="s2">"</span><span class="nv">!FFMPEG_CMD!</span><span class="s2">"</span> <span class="na">-y -i </span><span class="s2">"</span><span class="nv">!SELECTED_PATH!</span><span class="s2">"</span> <span class="na">-c</span><span class="nl">:v</span> <span class="kd">libx264</span> <span class="na">-c</span><span class="nl">:a</span> <span class="kd">aac</span> <span class="s2">"</span><span class="nv">!OUTPUT_FILE!</span><span class="s2">"</span>
</code></pre></div></div>

<p>完整的代码</p>

<p><a href="https://gist.github.com/greatghoul/556c9f129efb25ac10eea38e97a0a42e">https://gist.github.com/greatghoul/556c9f129efb25ac10eea38e97a0a42e</a></p>

<p>脚本是 AI 帮我写的，我其实看不懂。Image</p>

<p>这样就能很容易地获得 mp4 格式的视频，上传到平台就很方便了。</p>

<h3 id="代码开源">代码开源</h3>

<p>在 AI 盛行的今天，普通人制作属于自己的软件，变得更加容易，但是从源代码构建成可直接运行的应用程序却依然有一定的门槛，尤其是在 Windows 平台上，连开发者自己要搞定开发环境都要经过一番折腾，就更别提非开发者群体了。</p>

<p>我觉得目前纯 JavaScript 已经可以实现很多功能，很多功能甚至可以使用纯静态页面或者浏览器扩展来运行，为了方便更多非程序员可以轻松的修改应用，而不用苦恼如何安装 node.js 以及 node modules，这个扩展项目我使用了 Preact (一个类似 React 的前端框架) 的无构建方案，解压载入 Chrome 即可运行。</p>

<p><a href="https://preactjs.com/guide/v10/getting-started/#no-build-tools-route">https://preactjs.com/guide/v10/getting-started/#no-build-tools-route</a></p>

<p>代码以 MIT 协议开源在 Github，基本可以随意去修改和使用。</p>

<p><a href="https://github.com/greatghoul/CrxMediaMate/">https://github.com/greatghoul/CrxMediaMate/</a></p>

<p>这个扩展不会发布到  Chrome 扩展商店，所以你需要在开发者模式中去加载使用。</p>

<p>即使你不是开发者，如果和我的使用场景类似，也可以借助 AI 去按照自己的需求修改，然后直接使用而不需要构建的过程。</p>

<p>如果有时发现修改没有生效，可以尝试重载扩展</p>

<p><img src="https://github.com/user-attachments/assets/ab75a715-b697-4d5a-8540-5f5c6a2ce8a9" alt="Image" /></p>

<h3 id="技术支持和交流群">技术支持和交流群</h3>

<p>作为开发者，开源的代码以及加上 AI 的辅助，你几乎不需要任何技术支持，这个扩展也仅可作为抛砖引玉，你可以尝试打造更适合自己的收集，整理发布的工作流工具。</p>

<p>当然，作为开源项目，也欢迎 Issue 和 PR，我是有打算加入备份、Notion/Airtable 同步、视频字幕、设置页面等一系列功能的。</p>

<p>如果你不是开发者，又想获得一些技术支持，欢迎加入我的知识星球。</p>

<p>星球也并非专为该扩展而建立，我还有在做一些其它能够自动化信息发布的扩展和工具。</p>

<p>比如，不借助 API 的多平台信息发布工具</p>

<p><img src="https://github.com/user-attachments/assets/21e08426-c6e6-422a-8c4e-5226b4ec6fd6" alt="Image" /></p>

<p>我文章中用到的二维码生成工具</p>

<p><img src="https://github.com/user-attachments/assets/e82dbb8c-311f-4547-8346-e987c57c4d99" alt="Image" /></p>

<p>以及一些手机/电脑自动化的脚本，比如简单的手机自动点击器（用来玩游戏），我的世界自动行走和自动左右键点击器，应用自动签到，链接内容朗读等等。</p>

<p>如果你也对 Chrome 扩展开发，油猴脚本，手机/电脑自动化，以及试用各种有趣有用的工具感兴趣，欢迎加入我的知识星球老狗工坊一起交流。 如果你对开发并不了解，星球也可以提供一定的技术支持。</p>

<p><strong>如果你有有趣的需求，而我也觉得有意思，我也会考虑做成 Chrome 扩展或者油猴脚本，开源出来或者发在星球里面。</strong></p>

<p><a href="https://wx.zsxq.com/group/88882844441282">https://wx.zsxq.com/group/88882844441282</a></p>

<hr />

<p>文章同步发表于微信公众号<strong>老狗拾光</strong>，欢迎关注。</p>

<p><img src="https://github.com/user-attachments/assets/1a652b8b-7f5b-4879-af52-65e1fe3f7b4d" alt="微信公众号老狗拾光" /></p>]]></content><author><name></name></author><category term="分享创造" /><summary type="html"><![CDATA[之前有发过一篇文章[自动化] 为了方便发今日头条，我做了一个浏览器扩展，介绍我借助浏览器扩展，快速收集沙雕图到 Notion 然后生成图文后发布到今日头条的过程。]]></summary></entry><entry><title type="html">经常使用 Google 搜索，我做了个 Chrome 扩展</title><link href="https://anl.gg/post/287/" rel="alternate" type="text/html" title="经常使用 Google 搜索，我做了个 Chrome 扩展" /><published>2025-06-23T00:00:00+00:00</published><updated>2025-06-23T00:00:00+00:00</updated><id><a href="https://anl.gg/post/287">https://anl.gg/post/287</a></id><content type="html" xml:base="https://anl.gg/post/287/"><![CDATA[<p>其实早在 2018 年，我就做了这个扩展，目的是为了方便搜集远程工作机会和文章。</p>

<p><img width="1000" height="597" alt="Image" src="https://github.com/user-attachments/assets/ccfb0d6f-ef3d-4da5-b91a-383fbaba182f" /></p>

<p>我近期在<a href="https://mp.weixin.qq.com/s?__biz=MzIyMDc3NDI5Mg==&amp;mid=2247484510&amp;idx=1&amp;sn=56342ea99f3b8d85987f11f293bf9213&amp;scene=21#wechat_redirect">2025年，应该如何寻找远程工作？</a>这篇文章中也有提及过我搜索的方法。</p>

<p>今天重新分享这个工具，是因为我做了更新，Chrome 应用商店因为强制升级 Mnifest v3，导致我之前的扩展被下架了，最近我升级了 v3，并使用 Preact 重写了整个应用，终于可以重新和大家见面了。</p>

<h3 id="主要功能">主要功能</h3>

<p>保存和管理 Google 搜索结果的链接，是一个专为搜索结果页面设计的类似书签管理的工具，支持添加，编辑，查看和替换。</p>

<p><img width="479" height="477" alt="Image" src="https://github.com/user-attachments/assets/cecbdb17-805c-4932-873e-6b76aed54f3e" /></p>

<h3 id="优化了用户引导">优化了用户引导</h3>

<p>因为有用户反映不会使用，这次专门加入了一个引导页面，必须在 Google 搜索结果页面打开扩展，才可以添加</p>

<p><img src="https://github.com/user-attachments/assets/2db5c516-0b42-47f9-bb06-496435204660" alt="Image" /></p>

<p><img src="https://github.com/user-attachments/assets/291ee302-9235-4564-966f-2e6ec58e2380" alt="Image" /></p>

<p><img src="https://github.com/user-attachments/assets/d0924d34-ad5c-404e-9aa8-ff159895174e" alt="Image" /></p>

<h3 id="增加了垃圾箱">增加了垃圾箱</h3>

<p>因为删除操作没有确认步骤，所以添加了一个垃圾箱的功能，方便恢复误删的内容。</p>

<p><img width="479" height="477" alt="Image" src="https://github.com/user-attachments/assets/9fa399b6-c909-44ae-89f3-fb5968da58cf" /></p>

<h3 id="后续规划">后续规划</h3>

<p>后续我还打算为这个扩展支持更多实用的功能：</p>

<ul>
  <li>自动为保存的搜索创建书签</li>
  <li>支持导入和导出</li>
  <li>监听并提醒搜索结果的新记录数量</li>
  <li>分享搜索关键字配置</li>
  <li>在 Google 搜索结果页面添加快速添加/编辑入口</li>
  <li>支持更多的搜索引擎</li>
</ul>

<h3 id="欢迎试用">欢迎试用</h3>

<p>如果你也有和我类似经常需要搜索特定关键字的需求，欢迎下载试用。</p>

<p><a href="https://github.com/greatghoul/saved-search">https://github.com/greatghoul/saved-search</a></p>

<p><a href="https://chromewebstore.google.com/detail/saved-search/jflpdngeeiboimjmmcfbkkckcaimafbj?authuser=0&amp;hl=en-US">https://chromewebstore.google.com/detail/saved-search/jflpdngeeiboimjmmcfbkkckcaimafbj?authuser=0&amp;hl=en-US</a></p>

<hr />

<p>文章同步发表于微信公众号<strong>老狗拾光</strong>，欢迎关注。</p>

<p><img src="https://github.com/user-attachments/assets/1a652b8b-7f5b-4879-af52-65e1fe3f7b4d" alt="微信公众号老狗拾光" /></p>]]></content><author><name></name></author><category term="分享创造" /><summary type="html"><![CDATA[其实早在 2018 年，我就做了这个扩展，目的是为了方便搜集远程工作机会和文章。]]></summary></entry><entry><title type="html">自制微信公众号文章排版工具</title><link href="https://anl.gg/post/286/" rel="alternate" type="text/html" title="自制微信公众号文章排版工具" /><published>2025-06-06T00:00:00+00:00</published><updated>2025-06-06T00:00:00+00:00</updated><id><a href="https://anl.gg/post/286">https://anl.gg/post/286</a></id><content type="html" xml:base="https://anl.gg/post/286/"><![CDATA[<p>在前面的文章 <a href="https://www.anl.gg/post/285/">一键同步远程工作信息到TG，豆瓣小组，知识星球</a> 中，狗哥我预告过要更新我的工具，自动生成远程工作者微信文章的排版，如今已经达成目标了。</p>

<h3 id="先看视频">先看视频</h3>

<video controls="" src="https://github.com/user-attachments/assets/bd5d9baa-6844-401c-9055-40ed04e516e6"></video>

<p>只需要选择要分享的工作机会，就会自动生成文章内容，以及网站页面对应的二维码，兼容微信公众号的默认样式，直接复制粘贴就可以直接发布</p>

<p>相比我以前的流程，效率直接满格。</p>

<ol>
  <li>复制排版后的工作信息</li>
  <li>切换到公众号编辑器</li>
  <li>插入一个单元格（类似卡片的效果）并粘贴信息</li>
  <li>加粗标题</li>
  <li>为链接加上样式</li>
  <li>切换到网站复制二维码图片</li>
  <li>切换回公众号编辑器粘贴图片</li>
</ol>

<p>（这仅仅是排版一条工作信息的操作）</p>

<p>现在效率提升了，文章中能够分享的工作信息数量自然也就增加了，一言以蔽之，<strong>生产力提高了</strong>。</p>

<h3 id="排版的原理">排版的原理</h3>

<p>通过浏览器的<strong>开发人员工具审查元素</strong>，就可以看到微信公众号编辑器时如何组织 html 节点的，那么只需要再排版工具中模拟这样的结构，即可实现相同的排版效果。</p>

<p>公众号最基本的排版元素是 section，它的结构是这样的。</p>

<div class="language-html highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt">&lt;section&gt;&lt;span</span> <span class="na">leaf</span><span class="nt">&gt;</span>分享最近的远程工作机会。<span class="nt">&lt;/span&gt;&lt;/section&gt;</span>

</code></pre></div></div>

<p>这是不带任何样式的一个行。如果需要为文字添加颜色，它会在 span[leaf] 下再插入 span，并使用 style 属性来设置字体样式。</p>

<div class="language-html highlighter-rouge"><div class="highlight"><pre class="highlight"><code>
<span class="nt">&lt;section&gt;</span>
  <span class="nt">&lt;span</span> <span class="na">leaf</span><span class="nt">&gt;</span>
    <span class="nt">&lt;span</span> <span class="na">textstyle</span> <span class="na">style=</span><span class="s">"color: rgb(0, 122, 170);"</span><span class="nt">&gt;</span>
    招聘信息均收集自网络，是否靠谱请自行判断，如有投递意愿，请访问原文联系。
    <span class="nt">&lt;/span&gt;</span>
  <span class="nt">&lt;/span&gt;</span>
<span class="nt">&lt;/section&gt;</span>
</code></pre></div></div>

<p><img width="802" height="165" alt="Image" src="https://github.com/user-attachments/assets/9d3394c8-2edf-456f-a51d-713d5f6534be" /></p>

<p>当然，你也可以设置其他样式，比如 font-weight: bold 之类的。</p>

<p>对于单元格内的多行元素，则是使用 p 替代 section 标签。</p>

<div class="language-html highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt">&lt;table&gt;</span>
  <span class="nt">&lt;tbody&gt;</span>
    <span class="nt">&lt;tr&gt;</span>
      <span class="nt">&lt;td</span> <span class="na">data-colwidth=</span><span class="s">"576"</span><span class="nt">&gt;</span>
        <span class="nt">&lt;p&gt;&lt;span</span> <span class="na">leaf</span><span class="nt">&gt;&lt;span</span> <span class="na">textstyle</span> <span class="na">style=</span><span class="s">"font-weight: bold;"</span><span class="nt">&gt;</span>${job.title}<span class="nt">&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;</span>
        <span class="nt">&lt;p&gt;&lt;span</span> <span class="na">leaf</span><span class="nt">&gt;&lt;</span><span class="err">${</span><span class="na">JobUrl</span><span class="err">}</span> <span class="na">url=</span><span class="s">${pageUrl}</span> <span class="nt">/&gt;&lt;/span&gt;&lt;/p&gt;</span>
        <span class="nt">&lt;p&gt;&lt;span</span> <span class="na">leaf</span><span class="nt">&gt;&lt;/span&gt;&lt;/p&gt;</span>
        <span class="nt">&lt;p&gt;&lt;span</span> <span class="na">leaf</span><span class="nt">&gt;</span>来源: ${job.source}<span class="nt">&lt;/span&gt;&lt;/p&gt;</span>
        <span class="nt">&lt;p&gt;&lt;span</span> <span class="na">leaf</span><span class="nt">&gt;</span>原文: <span class="nt">&lt;</span><span class="err">${</span><span class="na">JobUrl</span><span class="err">}</span> <span class="na">url=</span><span class="s">${job.source_url}</span> <span class="nt">/&gt;&lt;/span&gt;&lt;/p&gt;</span>
        <span class="nt">&lt;p&gt;&lt;span</span> <span class="na">leaf</span><span class="nt">&gt;</span>摘要: ${job.note}<span class="nt">&lt;/span&gt;&lt;/p&gt;</span>
      <span class="nt">&lt;/td&gt;</span>
    <span class="nt">&lt;/tr&gt;</span>
  <span class="nt">&lt;/tbody&gt;</span>
<span class="nt">&lt;/table&gt;</span>
</code></pre></div></div>

<p>对于链接，则需要指定一个特殊的 class</p>

<div class="language-html highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt">&lt;a</span> <span class="na">href=</span><span class="s">${url}</span> <span class="na">target=</span><span class="s">"_blank"</span> <span class="na">class=</span><span class="s">"normal_text_link"</span> <span class="na">style=</span><span class="s">"color: rgb(0, 122, 170);"</span><span class="nt">&gt;</span>
  <span class="nt">&lt;span</span> <span class="na">textstyle</span> <span class="na">style=</span><span class="s">"color: rgb(0, 122, 170); text-decoration: underline;"</span><span class="nt">&gt;</span>${url}<span class="nt">&lt;/span&gt;</span>
<span class="nt">&lt;/a&gt;</span>
</code></pre></div></div>

<p>这样链接会有一个外链的图标。</p>

<p><img width="815" height="419" alt="Image" src="https://github.com/user-attachments/assets/a73bfd9f-6b96-4a32-a91d-cecedb148a83" /></p>

<p>不过，<strong>微信是不允许自己域名以外的网址外链的</strong>，对于外部链接，即使你在粘贴时能看到链接生效，保存后依然不会起到作用。</p>

<p>本来我以为这样直接粘贴到微信后，自然会有微信编辑器的样式，但是发现实际上是不行的，即使结构一致，样式也不会继承。</p>

<p><img src="https://github.com/user-attachments/assets/cda0a27c-e6a5-4c0f-a53e-7f8e3584a18b" alt="Image" /></p>

<p>还需要将这些元素的样式写入文章排版工具的样式表，这些样式，可以从通过审查元素拿到，很容易。</p>

<div class="language-html highlighter-rouge"><div class="highlight"><pre class="highlight"><code>.article-preview section {
  margin-top: 0px;
  margin-bottom: 24px;
}
.article-preview table {
  border-collapse: collapse;
  table-layout: fixed;
  ...
}
...
.article-preview img {
  height: auto !important;
  max-width: 100%;
}
</code></pre></div></div>

<hr />

<p>当然，如果你想创作自己的排版风格，不适用微信默认排版，那么完全可以自己设计样式，不需要去复制微信公众号默认的样式。</p>

<h3 id="排版工具的实现">排版工具的实现</h3>

<p><img src="https://github.com/user-attachments/assets/c09559cf-1b5e-4ee0-892e-1302c6119dbe" alt="Image" /></p>

<p>至于我的排版工具，其实很简单，借助 AI 很容易就搞定了。</p>

<p>作为一个后端开发，不是很喜欢前端的构建工具，所以在前端框架上，我选择的是一个类似 react 的 no build 工具 – preact.</p>

<p><a href="https://preactjs.com/guide/v10/getting-started/">https://preactjs.com/guide/v10/getting-started/</a></p>

<div class="language-html highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt">&lt;script </span><span class="na">type=</span><span class="s">"module"</span><span class="nt">&gt;</span>
  <span class="k">import</span> <span class="p">{</span> <span class="nx">h</span><span class="p">,</span> <span class="nx">render</span> <span class="p">}</span> <span class="k">from</span> <span class="dl">'</span><span class="s1">https://esm.sh/preact</span><span class="dl">'</span><span class="p">;</span>
  <span class="k">import</span> <span class="nx">htm</span> <span class="k">from</span> <span class="dl">'</span><span class="s1">https://esm.sh/htm</span><span class="dl">'</span><span class="p">;</span>
  <span class="c1">// Initialize htm with Preact</span>
  <span class="kd">const</span> <span class="nx">html</span> <span class="o">=</span> <span class="nx">htm</span><span class="p">.</span><span class="nf">bind</span><span class="p">(</span><span class="nx">h</span><span class="p">);</span>
  <span class="kd">function</span> <span class="nf">App</span> <span class="p">(</span><span class="nx">props</span><span class="p">)</span> <span class="p">{</span>
    <span class="k">return</span> <span class="nx">html</span><span class="s2">`&lt;h1&gt;Hello </span><span class="p">${</span><span class="nx">props</span><span class="p">.</span><span class="nx">name</span><span class="p">}</span><span class="s2">!&lt;/h1&gt;`</span><span class="p">;</span>
  <span class="p">}</span>
  <span class="nx">render</span><span class="p">(</span><span class="nx">html</span><span class="s2">`&lt;</span><span class="p">${</span><span class="nx">App</span><span class="p">}</span><span class="s2"> name="World" /&gt;`</span><span class="p">,</span> <span class="nb">document</span><span class="p">.</span><span class="nx">body</span><span class="p">);</span>
<span class="nt">&lt;/script&gt;</span>
</code></pre></div></div>

<p>对于简单的场景，它完全可以替代 react, 并且也支持 component, 写法也和 react 差异不大。</p>

<div class="language-js highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">const</span> <span class="nx">JobUrl</span> <span class="o">=</span> <span class="p">({</span> <span class="nx">url</span> <span class="p">})</span> <span class="o">=&gt;</span> <span class="p">{</span>
  <span class="k">return</span> <span class="nx">html</span><span class="s2">`
    &lt;a href=</span><span class="p">${</span><span class="nx">url</span><span class="p">}</span><span class="s2"> target="_blank" class="normal_text_link" style="color: rgb(0, 122, 170);"&gt;
      &lt;span textstyle style="color: rgb(0, 122, 170); text-decoration: underline;"&gt;</span><span class="p">${</span><span class="nx">url</span><span class="p">}</span><span class="s2">&lt;/span&gt;
    &lt;/a&gt;
  `</span>
<span class="p">}</span>

<span class="kd">const</span> <span class="nx">JobCard</span> <span class="o">=</span> <span class="p">({</span> <span class="nx">job</span> <span class="p">})</span> <span class="o">=&gt;</span> <span class="p">{</span>
  <span class="kd">const</span> <span class="nx">pageUrl</span> <span class="o">=</span> <span class="s2">`https://remote-info.cn/jobs/</span><span class="p">${</span><span class="nx">job</span><span class="p">.</span><span class="nx">id</span><span class="p">}</span><span class="s2">`</span><span class="p">;</span>
  <span class="k">return</span> <span class="nx">html</span><span class="s2">`
    &lt;table&gt;
      &lt;tbody&gt;
        &lt;tr&gt;
          &lt;td data-colwidth="576"&gt;
            &lt;p&gt;&lt;span leaf&gt;&lt;span textstyle style="font-weight: bold;"&gt;</span><span class="p">${</span><span class="nx">job</span><span class="p">.</span><span class="nx">title</span><span class="p">}</span><span class="s2">&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
            &lt;p&gt;&lt;span leaf&gt;&lt;</span><span class="p">${</span><span class="nx">JobUrl</span><span class="p">}</span><span class="s2"> url=</span><span class="p">${</span><span class="nx">pageUrl</span><span class="p">}</span><span class="s2"> /&gt;&lt;/span&gt;&lt;/p&gt;
            &lt;p&gt;&lt;span leaf&gt;&lt;/span&gt;&lt;/p&gt;
            &lt;p&gt;&lt;span leaf&gt;来源: </span><span class="p">${</span><span class="nx">job</span><span class="p">.</span><span class="nx">source</span><span class="p">}</span><span class="s2">&lt;/span&gt;&lt;/p&gt;
            &lt;p&gt;&lt;span leaf&gt;原文: &lt;</span><span class="p">${</span><span class="nx">JobUrl</span><span class="p">}</span><span class="s2"> url=</span><span class="p">${</span><span class="nx">job</span><span class="p">.</span><span class="nx">source_url</span><span class="p">}</span><span class="s2"> /&gt;&lt;/span&gt;&lt;/p&gt;
            &lt;p&gt;&lt;span leaf&gt;摘要: </span><span class="p">${</span><span class="nx">job</span><span class="p">.</span><span class="nx">note</span><span class="p">}</span><span class="s2">&lt;/span&gt;&lt;/p&gt;
          &lt;/td&gt;
        &lt;/tr&gt;
      &lt;/tbody&gt;
    &lt;/table&gt;
    &lt;section&gt;&lt;span leaf&gt;&lt;</span><span class="p">${</span><span class="nx">QRCode</span><span class="p">}</span><span class="s2"> title=</span><span class="p">${</span><span class="nx">job</span><span class="p">.</span><span class="nx">title</span><span class="p">}</span><span class="s2"> url=</span><span class="p">${</span><span class="nx">pageUrl</span><span class="p">}</span><span class="s2"> note=</span><span class="p">${</span><span class="nx">job</span><span class="p">.</span><span class="nx">note</span><span class="p">}</span><span class="s2"> /&gt;&lt;/span&gt;&lt;/section&gt;
    &lt;section&gt;&lt;span leaf&gt;&lt;/span&gt;&lt;/section&gt;
  `</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>

<p>工作机会列表，则是采集自我的网站<a href="https://remote-info.cn/">远程工作者</a>。</p>

<p>至于生成二维码卡片，我在文章 <a href="https://www.anl.gg/post/278/">自动化：借助 AI 为 Pixilart 网站创建二维码分享卡片</a> 中有详细介绍过，这里不再赘述。</p>

<h3 id="总结">总结</h3>

<p>AI 让开发变得容易了很多，如果你有掌握一些开发的基础知识，那么遇到一些电脑上的重复工作，其实可以尝试着自己去创造工具，而不是去寻找工具。</p>

<hr />

<p>文章同步发表于微信公众号<strong>老狗拾光</strong>，欢迎关注。</p>

<p><img src="https://github.com/user-attachments/assets/1a652b8b-7f5b-4879-af52-65e1fe3f7b4d" alt="微信公众号老狗拾光" /></p>]]></content><author><name></name></author><category term="分享创造" /><summary type="html"><![CDATA[在前面的文章 一键同步远程工作信息到TG，豆瓣小组，知识星球 中，狗哥我预告过要更新我的工具，自动生成远程工作者微信文章的排版，如今已经达成目标了。]]></summary></entry></feed>