我目前在看英语网页的时候, 经常开着沉浸式翻译这个插件, 使用体验是很棒, 但是感觉这样容易形成依赖和偷懒的心理, 对提升英语阅读能力帮助不大。
我想自己做一个浏览器插件来自用,实现以下功能:
- 检测到网页为英文语言时自动启用。
- 将页面上的文本识别出来,拆分为独立的单词。
- 和本地存储的一个词库对比,不认识的单词标记为红色,不在词库中标记为绿色,已经认识的不做处理。
- 有颜色标记的单词可以点击并弹出模态窗口,在里面可以添加中文释义,查询词典,修改单词在词典中的状态。
- 将上面所述的改动替换回文本的原有节点,不影响整体页面布局的前提下,增强英语的阅读体验和交互性。
其实还是我在Lang Big Bang项目中所做的那些,只是在那里面是导入自己感兴趣的文章来学习英语。而插件可以在浏览任何一个网页时实现这个效果,更加自由并且灵活一些。目前我还想要开发一个 APP,长期的目标是数据互通,手机上可以学习,浏览器里随时可以阅读,网页上可以方便做导入。
大概看了下谷歌的开发文档, 做了一个小测验,目前感觉有实现的可能。做了一个小 demo,搭了一个大概的脚手架。
manifest.json 定义整个项目的结构、功能、权限,可以视为一个入口文件。
{
"manifest_version": 3,
"name": "Lang Bigbang",
"version": "1.0",
"description": "Learning english by reading in a simple way.",
"icons": {
"16": "images/icon-16.png",
"32": "images/icon-32.png",
"48": "images/icon-48.png",
"128": "images/icon-128.png"
},
"content_scripts": [
{
"js": ["scripts/content.js"],
"css": ["styles/content.css"],
"matches": ["https://developer.chrome.com/*"]
}
],
"permissions": ["storage", "unlimitedStorage"]
}
content.js 测试了对页面文本的提取和注入 (dom 操作的 API,可以查看mdn 文档)。
之所以延时执行是因为要等页面本身的 js 先加载完成,以免读取不到文本或者读取不完整。
const tags = ['P', 'STRONG', 'EM', 'TIME', 'H1', 'H2', 'H3', 'H4', 'H5', 'H6'];
function getText(node) {
let text = '';
if (node.nodeType === Node.TEXT_NODE) {
if (tags.includes(node.parentNode.tagName)) {
text += node.textContent + ' ';
}
} else if (node.nodeType === Node.ELEMENT_NODE) {
for (let child of node.childNodes) {
text += getText(child);
}
}
return text;
}
setTimeout(function () {
const body = document.querySelector('body');
const allText = getText(body);
if (allText) {
const out = document.createElement('p');
out.classList.add('bigtitle');
out.textContent = allText;
document.body.insertAdjacentElement('afterbegin', out);
} else {
console.log('No allText found');
}
}, 2000);
接下来还有很多的细节需要完善, 比如本地存储怎么实现查词和写入? 更进一步的话,怎么实现本地数据和 supabase 互通同步,怎么做登录验证? 怎么替换原有的文本节点? 可能需要找某一天有大块的时间来研究下。 今天时间有限,先暂时做一个记录,以待后续。
What I Leraned?
- 实现一个扩展程序的流程。怎么创建文件和浏览器调试。manifest.json 的配置,图标、js\css、权限清单等。
- 通过 content_scripts 可以读取并修改目标网页的 dom。js 中操作页面 dom 的一些 api。