创建一个可以复制百度文库的Chrome插件

具体如何编写Chrome扩展,可以查看Google提供的API文档。本次我打算编写一个简易版本,右键提供一个上下文菜单,复制文本。一些文本屏蔽的内容较少,也有方法查看。如下图所示。
自恋者的动力学分析

准备图标

新建文件夹CopyText,这将是我们的插件目录。
前往iconfont选择一个合适的图标,尺寸准备16,32,48,64,128
图片
想要获得代码提示,需要在WebStorm中导入库。
2
点击download,找到chrome
3
现在,你就可以获得代码提示功能。

编写清单文件(manifest.json)

{
  "name": "Copy Text",
  "version": "0.1",
  "manifest_version": 3,
  "background": {
    "service_worker": "background.js"
  },
  "icons": {
    "16": "icons/copy16.png",
    "32": "icons/copy32.png",
    "48": "icons/copy48.png",
    "64": "icons/copy64.png",
    "128": "icons/copy128.png"
  }
}

manifest_version非常重要,只能写成数字3,manifest_version2在未来会被废弃。
打开开发者模式并且加载文件夹

编写后台脚本

MV3的后台脚本使用了service worker
我们将要使用到contextMenus,因此需要在manifest.json中声明权限。
在这里插入图片描述
查看API文档使用即可。
我尝试了解除阻止右键菜单事件,发现不好处理。因为Event.addEventListener触发事件为匿名函数就不好处理。
为了,我们采取捕获网络请求的方式。Chrome提供了webRequest用于捕获请求,同时完成剪切操作需要scriptingtabs
为此声明权限:
在这里插入图片描述
在Chrome中捕获请求
在这里插入图片描述

这就是我们要捕获的请求;

async function getPageUrl() {
    let pagesRequest = []
    chrome.webRequest.onHeadersReceived.addListener(details => {
        // console.log(details.url)
        if (details.url.indexOf('0.json') !== -1) {
            pagesRequest.push(details.url)
        }
    }, {urls: ["https://*.bdimg.com/*"]})
    return pagesRequest
}

拿到url后排序

urls.sort((u1, u2) => {
        let q1 = getQuery(u1);
        let q2 = getQuery(u2);
        let s1 = q1['x-bce-range'].split('-')[0];
        let s2 = q2['x-bce-range'].split('-')[0];
        return s2 - s1
    })
 function getQuery(u) {
    const url = decodeURI(u); // 获取url中"?"符后的字串(包括问号)
    let query = {};
    if (url.indexOf("?") !== -1) {
        const str = url.substr(1);
        const pairs = str.split("&");
        for (let i = 0; i < pairs.length; i++) {
            const pair = pairs[i].split("=");
            query[pair[0]] = pair[1];
        }
    }
    return query;  // 返回对象
}

将他们拼接成文本


async function collectParagraph(...urls) {
    let article = ""

    for (let url of urls) {
        console.log('当前url:', url);
        let response = await fetch(url, {
            "headers": {
                "accept": "*/*",
                "accept-language": "zh-CN,zh;q=0.9",
                "sec-ch-ua": "\" Not A;Brand\";v=\"99\", \"Chromium\";v=\"98\", \"Google Chrome\";v=\"98\"",
                "sec-ch-ua-mobile": "?0",
                "sec-ch-ua-platform": "\"Windows\"",
                "sec-fetch-dest": "script",
                "sec-fetch-mode": "no-cors",
                "sec-fetch-site": "cross-site"
            },
            "referrer": "https://wenku.baidu.com/",
            "referrerPolicy": "strict-origin-when-cross-origin",
            "body": null,
            "method": "GET",
            "mode": "cors",
            "credentials": "omit"
        });
        let result = await response.text()
        let content = JSON.parse(result.substring(8, result.length - 1));
        for (let para of content.body) {
            // console.log(para.c)
            article += para.c;
            if (para.ps != null)
                for (let i = 0; i < para.ps["_enter"]; i++) {
                    article += '\n';
                }
        }
    }
    return article;
}

复制到剪切板

async function copyText(text) {
    let currentTab = await getCurrentTab();
    await chrome.scripting.executeScript({
        target: {tabId: currentTab.id},
        func: (text) => {
            navigator.clipboard.writeText(text).then(function () {
                console.log("success")
            }, function () {
                console.log("failed")
            });
        },
        args: [text]
    })
}

主函数执行整个过程

(async () => {
    chrome.runtime.onInstalled.addListener(() => {
        chrome.contextMenus.create({
            contexts: ['selection', 'page'],
            title: "复制文本",
            id: "copyMenu",
        })
    })
    let urls = await getPageUrl();
    urls.sort((u1, u2) => {
        let q1 = getQuery(u1);
        let q2 = getQuery(u2);
        let s1 = q1['x-bce-range'].split('-')[0];
        let s2 = q2['x-bce-range'].split('-')[0];
        return s2 - s1
    })

    async function handleContextMenus(info) {
        let article = ""

        if (info.menuItemId === 'copyMenu' && info.selectionText !== undefined) {
            await copyText(info.selectionText)
        } else if (info.menuItemId === 'copyMenu' && info.pageUrl.indexOf('https://wenku.baidu.com') !== -1) {
            article += await collectParagraph(...urls)
            await copyText(article)
        }
    }

    chrome.contextMenus.onClicked.addListener((async info => {
        await handleContextMenus(info);
    }))

})();

最后清单文件是:

{
  "name": "Copy Text",
  "version": "0.1",
  "manifest_version": 3,
  "author": "叶秋明",
  "description": "复制文本和获取百度文库的内容",
  "background": {
    "service_worker": "background.js"
  },
  "icons": {
    "16": "icons/copy16.png",
    "32": "icons/copy32.png",
    "48": "icons/copy48.png",
    "64": "icons/copy64.png",
    "128": "icons/copy128.png"
  },
  "permissions": [
    "contextMenus",
    "tabs",
    "scripting",
    "webRequest"
  ],
  "host_permissions": [
    "https://wenku.baidu.com/*",
    "https://*.bdimg.com/*",
    "<all_urls>"
  ]
}
  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值