跳过某博客的复制限制——我的油猴插件开发初体验

439 阅读3分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第5天,点击查看活动详情

事件篇

众所周知,作为一个CV工程师,最重要的就是对代码进行Ctrl+C和Ctrl+V的操作,然而,当我进入到某博客时,遇到了这样的情况:

不仅是说无法直接复制整段代码,就算想要用鼠标选中复制其中的一段也无法选中。

疑惑篇

登录就登录吧,有github三方登录的方式,方便快捷。然而那时不知道是API抽风了还是咋回事,居然授权失败了!难道我还要去现注册一个账号吗?这也太麻烦了……

不行试试用控制台看看吧,不幸的是,DOM结构中代码各行都加了标签,那完全没办法复制了:

既然如此,那就从CSS上下手吧,一般来说,拖动无法复制一般都是由CSS的user-select属性来控制的。选中代码区域相关的DOM,在样式筛选条件中输入user-select,果不其然,出现了user-select属性:

这时候,将user-select属性改为text即可(关于user-select属性的更多内容,可以查看Mozilla文档)。

解决篇

那么,总不能每次都要打开控制台来修改CSS属性吧,有没有啥办法每次启动这个博客页面就直接改掉它呢?

这时候,油猴插件就排上用场了。

油猴插件是一个浏览器插件,Chrome、Foxmail和Edge上都有,它可以理解为一个JS脚本注入,就是说在可以在特定的页面打开前运行自定义的用户脚本,正好符合我当前的需求。

在需要运行的页面上,点开油猴插件菜单,点击添加新脚本,便可以进入到新脚本的编辑页面:

脚本的上半部分是一些基础属性的设置,比如名字、图标、命名空间等,如果是你自己用的话,其他的不用管,直接去修改@match项就好了,这个表示的是脚本执行的页面,比如我这个,需要在这个网站的所有博客文章下生效,因此我将这一行改为带有通配符的地址:

// @match        http*://*.blog.xxxx.net/*/article/details/*

之后就可以运行自己的脚本了,修改code标签的user-select属性,不过与其去费劲修改style标签或者CSS文件,不如直接去给code标签加入内联样式,我是这么写的:

document.querySelectorAll("code").forEach(function (item) {
    item.style = item.style + ";user-select: text !important;";
})

与此同时,不如直接把登录复制按钮变成复制全文吧:

// 将所有登录复制按钮变成全选
document.querySelectorAll(".hljs-button").forEach(function (item) {
    item.dataset.title = "复制全部";
    return item;
})
try {
    // 重写登录复制方法
    window.hljs.signin = e => {
        var preNode = e.path.filter(item => item.tagName == "PRE")[0];
        // 选中一段文字
        let selection = window.getSelection();
        let range = document.createRange();
        range.selectNode(preNode);
        selection.removeAllRanges();
        selection.addRange(range);
        // 执行复制命令
        document.execCommand('copy', false, null);
        e.target.dataset.title = "复制成功";
        setTimeout(() => {
            e.target.dataset.title = "复制全部";
        }, 1000);
    }
    // 重写另一个登录方法(需要去除行号和版权声明)
    window.mdcp.signin = e => {
        // 避免拖动选择代码时直接触发了复制全部
        if (!e.target.className.includes("hljs-button")) return;
        var preNode = e.path.filter(item => item.tagName == "CODE")[0];
        // 选中一段文字
        let selection = window.getSelection();
        let range = document.createRange();
        range.selectNode(preNode);
        selection.removeAllRanges();
        selection.addRange(range);
        // 执行复制命令
        document.execCommand('copy', false, null);
        e.target.dataset.title = "复制成功";
        setTimeout(() => {
            e.target.dataset.title = "复制全部";
        }, 1000);
    }
}
catch { }

后来有有朋友提出,部分页面需要登录才能查看全文,那就一起解决掉:

// 解除关注才能查看全文的限制
$('#article_content').removeAttr("style");
$('.hide-article-box').remove();

搞定了,这下只要一进入页面就可以直接复制了,免去了登录的烦恼~

番外

为了能分享出来,我将脚本上传到了GreasyFork,并通过github上的release进行关联使之能够自动更新:

这样只要我更新github上的代码并发到release中,脚本就会自动更新了: