3

手把手教你开发一个浏览器翻译插件

 2 years ago
source link: https://segmentfault.com/a/1190000040696715
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

手把手教你开发一个浏览器翻译插件

发布于 9 月 16 日

最近在研究一些比较有意思的东西,前几天玩了一个微信聊天机器人,美化图片的,今天想写个浏览器插件。话不多说直接开始。

想写一个浏览器插件比较简单,跟我们平常开发项目一样,首先创建一个文件夹,保证下面会有一个manifest.json文件即可。

这是我的项目结构:

image.png

注意:这里会有个小坑,mainfest.json文件名一定要写对,不然使用开发者模式加载插件的时候就会报错。

接下来是一个最基本的配置

{
    "name": "IRON MAN",
    "version": "1.0.0",
    "description": "I am iron man",
    "manifest_version": 2,
    "background": {
        "scripts": [
            "background.js"
        ],
        "persistent": false
    },
    "icons": {
        "16": "images/4.png",
        "48": "images/4.png",
        "128": "images/4.png"
    },
    "page_action": {
        "default_popup": "popup.html",
        "default_icon": "images/4.png"
    }
}

配置好之后就可以去浏览器中添加插件了,就是这么简单

从右上角菜单->更多工具->扩展程序可以进入 插件管理页面,也可以直接在地址栏输入 chrome://extensions 访问。

勾选开发者模式即可以文件夹的形式直接加载插件,否则只能安装.crx格式的文件。
image.png

manifest.json的配置:

manifest.json中,manifest_versionnameversion3个是必不可少的,descriptionicons是推荐的。

这里贴一下从大佬那里粘贴来的解析:

{
    // 清单文件的版本,这个必须写,而且必须是2
    "manifest_version": 2,
    // 插件的名称
    "name": "demo",
    // 插件的版本
    "version": "1.0.0",
    // 插件描述
    "description": "简单的Chrome扩展demo",
    // 图标,一般偷懒全部用一个尺寸的也没问题
    "icons":
    {
        "16": "img/icon.png",
        "48": "img/icon.png",
        "128": "img/icon.png"
    },
    // 会一直常驻的后台JS或后台页面
    "background":
    {
        // 2种指定方式,如果指定JS,那么会自动生成一个背景页
        "page": "background.html"
        //"scripts": ["js/background.js"]
    },
    // 浏览器右上角图标设置,browser_action、page_action、app必须三选一
    "browser_action": 
    {
        "default_icon": "img/icon.png",
        // 图标悬停时的标题,可选
        "default_title": "这是一个示例Chrome插件",
        "default_popup": "popup.html"
    },
    // 当某些特定页面打开才显示的图标
    /*"page_action":
    {
        "default_icon": "img/icon.png",
        "default_title": "我是pageAction",
        "default_popup": "popup.html"
    },*/
    // 需要直接注入页面的JS
    "content_scripts": 
    [
        {
            //"matches": ["http://*/*", "https://*/*"],
            // "<all_urls>" 表示匹配所有地址
            "matches": ["<all_urls>"],
            // 多个JS按顺序注入
            "js": ["js/jquery-1.8.3.js", "js/content-script.js"],
            // JS的注入可以随便一点,但是CSS的注意就要千万小心了,因为一不小心就可能影响全局样式
            "css": ["css/custom.css"],
            // 代码注入的时间,可选值: "document_start", "document_end", or "document_idle",最后一个表示页面空闲时,默认document_idle
            "run_at": "document_start"
        },
        // 这里仅仅是为了演示content-script可以配置多个规则
        {
            "matches": ["*://*/*.png", "*://*/*.jpg", "*://*/*.gif", "*://*/*.bmp"],
            "js": ["js/show-image-content-size.js"]
        }
    ],
    // 权限申请
    "permissions":
    [
        "contextMenus", // 右键菜单
        "tabs", // 标签
        "notifications", // 通知
        "webRequest", // web请求
        "webRequestBlocking",
        "storage", // 插件本地存储
        "http://*/*", // 可以通过executeScript或者insertCSS访问的网站
        "https://*/*" // 可以通过executeScript或者insertCSS访问的网站
    ],
    // 普通页面能够直接访问的插件资源列表,如果不设置是无法直接访问的
    "web_accessible_resources": ["js/inject.js"],
    // 插件主页,这个很重要,不要浪费了这个免费广告位
    "homepage_url": "https://www.baidu.com",
    // 覆盖浏览器默认页面
    "chrome_url_overrides":
    {
        // 覆盖浏览器默认的新标签页
        "newtab": "newtab.html"
    },
    // Chrome40以前的插件配置页写法
    "options_page": "options.html",
    // Chrome40以后的插件配置页写法,如果2个都写,新版Chrome只认后面这一个
    "options_ui":
    {
        "page": "options.html",
        // 添加一些默认的样式,推荐使用
        "chrome_style": true
    },
    // 向地址栏注册一个关键字以提供搜索建议,只能设置一个关键字
    "omnibox": { "keyword" : "go" },
    // 默认语言
    "default_locale": "zh_CN",
    // devtools页面入口,注意只能指向一个HTML文件,不能是JS文件
    "devtools_page": "devtools.html"
}

接下来一步一步介绍我是怎么实现两个插件的功能的

1. 注册监听事件

在扩展程序的background脚本中注册监听事件:在脚本加载之后即触发监听

chrome.runtime.onInstalled.addListener(function () {
    chrome.storage.sync.set({ color: '#e84f20' }, function () {
        console.log("虾皮的橙色");
    });
     chrome.declarativeContent.onPageChanged.removeRules(undefined, function () {
        chrome.declarativeContent.onPageChanged.addRules([{
            conditions: [new chrome.declarativeContent.PageStateMatcher({
                pageUrl: { hostEquals: 'www.baidu.com' },
            })
            ],
            actions: [new chrome.declarativeContent.ShowPageAction()]
        }]);
    });
});

2.注册权限

因为我们在background中使用了chrome.storage等api,需要在manifest.json中注册

   "permissions": [
        "storage",
        "declarativeContent",
        "tabs",
        "activeTab",
        "contextMenus",
    ],

3. 在扩展程序页面刷新我们的扩展程序

image.png

点击查看背景页,可以看到打印内容

image.png

4.引入ICON图标

其实之前放出的配置文件中已经配置了图标,在上面的截图中也可以看到钢铁侠的图标。那么这里提两点注意点:

  • 对于未压缩的扩展程序,只能使用png图标。
  • 图标是可以适配不同的大小的,懒的话就全用一个。

5. 引入popup页面

我在页面中简单写了两个功能:让页面变色,让页面颜色恢复。

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        .btn {
            height: 50px;
            background-color: #e84f20;
            border-radius: 4px;
            line-height: 50px;
            text-align: center;
            padding: 0 5px;
            color: #fff;
            margin-right: 20px;
        }

        .wrapper {
            width: 500px;
            display: flex;
            align-items: center;
            justify-content: center;
        }
    </style>
</head>

<body>
    <div class="wrapper">
        <Button id="btn" class="btn">点击变成虾皮红</Button>
        <Button id='clear' class="btn">恢复</Button>
    </div>
    <script src="./popup.js"></script>
</body>

</html>

js文件如下:

let changeColor = document.getElementById('btn');
let clear = document.getElementById('clear');
chrome.storage.sync.get('color', function (data) {
    changeColor.style.backgroundColor = data.color;
    changeColor.setAttribute('value', data.color);
});
changeColor.onclick = function (element) {
    let color = element.target.value;
    chrome.tabs.query({ active: true, currentWindow: true }, function (tabs) {
        chrome.tabs.executeScript(
            tabs[0].id,
            { code: 'document.body.style.backgroundColor = "' + color + '";' });
    });
};
clear.onclick = (ele) => {
    chrome.tabs.query({ active: true, currentWindow: true }, function (tabs) {
        let color = '#fff'
        chrome.tabs.executeScript(
            tabs[0].id,
            { code: 'document.body.style.backgroundColor = "' + color + '";' });
    });
}

使用chrome.storage.sync.get获取内存中的颜色。使用chrome.tabs.executeScript往页面注入脚本。

需要注意的是:我们使用到的chrome API 都需要在manifest.json中配置

现在我们就可以在baidu的页面中玩我们的插件了!

image.png

点击之后的样子

image.png

也可以将颜色恢复。

那么第一个给网站变颜色和恢复的功能已经完成了。接下来想做个翻译的功能。

6.继续添加background脚本

   chrome.contextMenus.create({
        id: "9527",
        contexts: ['selection'],
        title: '让钢铁侠翻译:%s', // 显示的文字,除非为“separator”类型否则此参数必需,如果类型为“selection”,可以使用%s显示选定的文本
    })
    console.log(chrome.contextMenus)
    chrome.contextMenus.onClicked.addListener((info, tab) => {
        const query = info.selectionText;
        const url = "https://fanyi.baidu.com/translate?#est/zh/" + query;
        chrome.tabs.create({ url: url });
    })

这段脚本的功能是在页面中创建一个右键的操作菜单,如图所示

image.png

我们可以添加监听事件在点击的时候去对应的网址做一些事情。例子中我是给选中的文本添加了一个翻译的功能,通过监听点击事件跳转到百度翻译,并把选中文本带过去进行翻译。

image.png

这里同样需要注意:contextMenus需要在manijest.json中注册。

到这里我们的功能就已经完全实现了。由于才思不够敏捷,暂时没什么更加实用功能的研发。希望各位可以才思泉涌给我一些建议~~

网上一些比较全的教程+API

谷歌插件开发API

插件开发指南

最后谢谢大家!


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK