写一个扩展功能不难。难的是把日常那一堆需求塞进同一个壳子,还别互相踩。
翻译要弹窗和划词,新标签页想看天气汇率,书签得同步到自己的服务。GitHub 偶尔打包下个目录,V2EX 想自动签到,长列表懒得点下一页。代理、扩展开关、站点 Cookie 又不想再装四五套。每样单独装一个,图标能挤满工具栏,权限重复,设置散得到处都是。从零写倒也能写,就是 Service Worker 说停就停、右键菜单互相覆盖、content script 把宿主页样式搞脏,这些坑得反复踩。
formant 是冲着这件事做的。Chrome Manifest V3,原生 HTML / CSS / JS,后台走 Oolaf mono 的 Client API。不是演示按钮那种空壳,常用的已经串进去了。

设置用一套 option.html 挂多个面板。总开关在 #features,细节进对应锚点。工具栏图标始终打开 formant popup,不把入口让给某个子模块。后来功能加多了,popup 里也能进书签、站点数据、扩展管理;二级页顶栏统一成返回翻译加当前标题,操作放下面工具条,免得小窗口里再叠一套顶栏。


密钥不进扩展仓库。本机只存 mono 地址和一把 Client API Key;GPT、百度、天气这些放 Admin 的 Formant 配置组。翻译失败链路也写死了:Google 直连不行走 mono Google,再不行百度。词库打分用合并后的结果,不拿一份静态表当唯一真相。
划词面板、GitHub 下载进度、AutoPagerize 状态条、手势轨迹,尽量都进 Shadow DOM。跟页面通信走 chrome.runtime / chrome.tabs,密钥不塞进 content script。Service Worker 按随时会被杀掉来写,重要状态落 chrome.storage。
代码按模块拆:翻译、词库、New Tab、书签、GitZip、V2EX、自动翻页、代理、扩展管理、站点数据、鼠标手势,各有 bridge 和 option 面板。新能力往面板上挂,不为单项另开独立设置页。自有源码单文件卡在 500 行附近,background 和 popup 不无限胀。
翻译和词库
入口就那些:popup 输入框、划词浮标、右键「用 formant 翻译」。模式有自动 / Google / GPT / 全部。本地打分看脚本、词库和句式,简单的走 Google,绕的可以并行 GPT。原文译文都能读。默认模式和目标语言存在 chrome.storage.local,popup 和划词共用。popup 打开会自动聚焦输入框。

内置 en / zh / ja / ko / tr 俚语包,只读,能停用。自定义包在本机,JSON 导入可以新建、合并、替换。管理在 option.html#lexicon。

New Tab
覆盖浏览器新标签页,布局能同步到 mono。第一行四张卡:天气、假期、汇率、热点英语。天气大概十分钟单独刷一次,别的卡片不动。热点英语词数可配,单词上方标美式 IPA,释义和谐音默认马赛克,点一下揭开。能单词语,也能整卡连读。已会的剔掉,会补新的上来。
换电脑打开空主页会自动拉云端;空布局点同步,不会把云端已有的盖掉。壁纸、遮罩、城市在 #newtab,连 mono 仍在 #sync。

书签和图片
书签变更会防抖上传,也能手动同步。按 Client API Key 隔离,不是全站一个池。空文件夹列表不会覆盖云端。换一把 Key,本机 New Tab、词卡、手势缓存会清掉,免得串数据。

图片右键可以另存 PNG / JPG,转码在扩展里做,要 downloads 权限。

GitZip、V2EX、自动翻页
GitHub 公开仓库、目录、文件页可以勾选打包。单文件、目录 ZIP、多选、整仓都行。只走公开 API,不存 GitHub PAT,不接 OAuth。匿名接口有速率上限,大目录或狂点可能被限,面板会提示。选择方式和主题在 #gitzip。关掉总开关,页面注入和菜单一起停,popup 还在。

V2EX Plus 是上游 GPLv3 模块改过来的:自动签到、未读角标、楼中楼、用户卡、sov2ex。设置字段还用 chrome.storage.sync.options,跟上游兼容。关掉就停 alarm、badge、DNR 和页面增强,工具栏点击行为不动。带这个模块一起分发,整体按 GPLv3 处理。

AutoPagerize 滚到底会接下页。内置一大坨站点 XPath,Google / Bing 有优先覆盖,也能配排除列表。同域带 cookie 拉,跨域才走 background。HTML 解析后先去掉脚本再插入,避免宿主页跑远端代码。

鼠标手势
后来加的,默认关着。本机要是还开着 smartUp,两边会抢右键,只开一个就行。开了之后,普通网页按住右键划,路径收成 L / R / U / D。默认左退右进,上下刷新,右下关当前标签,上到顶,下到底。
设置页点某个动作的「绘制」,画板里按住左键划一下松手就绑上。网页上仍是右键。位移太小放行系统菜单,输入框和可编辑区域不触发。轨迹 Shadow DOM。同一路径不能绑两个动作。
映射能同步到 mono,跟 New Tab 一样按 Client API Key。「刷新」是拉,「同步」是推。空映射不会覆盖云端已有的。总开关只存在本机,不同步。chrome://、商店页、PDF 注入不进去。
代理、扩展、站点数据
代理走 chrome.proxy.settings:直连、系统代理、PAC(URL 或本地脚本)、最多五条固定服务器。默认偏系统代理,固定代理端口默认 7890。细配在 #proxy,popup 顶上能快捷切。不做账号密码认证,也没整包塞第三方代理扩展。

扩展管理用 chrome.management 列出本机扩展,能搜、能开关,formant 自己不出现。完整面板在 #extensions,popup 顶栏也有二级入口。不做分组、锁定、别名那一套。

站点数据在 popup 里读当前 http / https 页的 Cookie、localStorage、sessionStorage。进去和切 Tab 会自动拉。能复制、单条删、整页清,都要确认。Cookie 经 background 转发。不搞跨站批量写。

JSON Prettify 是 DevTools 面板加内容脚本查看器,接口返回直接能看。

各模块有总开关。关了停运行时,配置尽量留着。权限按能力要:alarms、bookmarks、contextMenus、cookies、downloads、management、proxy、scripting、storage 这些;GitHub、V2EX、Imgur 的 host 按需列。右键菜单按自己的 ID 增删,不 removeAll() 把别人的菜单清掉。

和 mono
扩展侧就两样:环境(dev 连本地,prod 连 www.oolaf.top)和一把 Client API Key。设置页顶栏会显示 Key 指纹,不展示全文。New Tab 布局、热点英语、书签、手势映射都按这把 Key 隔离。
服务端大概是这些:formant.translate.* 翻译通道,formant.weather.* / formant.exchange.* 天气汇率,formant.vocab.model_key / card_size 热点英语,formant.newtab.default_home 默认主页。密钥只放 Admin,不进扩展仓库。
本地加载
Chrome 打开 chrome://extensions,打开开发者模式
「加载已解压的扩展程序」,选中仓库里的 formant/ 目录
打开 option.html#sync,填环境和 Client API Key
到 #features 打开要用的模块,再到对应面板细调
版本号看 formant/manifest.json 的 version。要改某一块,从对应 bridge 或 option 面板顺着读就行。
确认评论邮箱
邀请制评论