解除网页“禁用复制”

解除网页“禁用复制”限制

您需要先安装一个扩展,例如 篡改猴Greasemonkey暴力猴,之后才能安装此脚本。

You will need to install an extension such as Tampermonkey to install this script.

您需要先安装一个扩展,例如 篡改猴暴力猴,之后才能安装此脚本。

您需要先安装一个扩展,例如 篡改猴Userscripts ,之后才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。

您需要先安装用户脚本管理器扩展后才能安装此脚本。

(我已经安装了用户脚本管理器,让我安装!)

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

(我已经安装了用户样式管理器,让我安装!)

// ==UserScript==
// @name        解除网页“禁用复制”
// @namespace   https://blog.bgme.me
// @match       *://*/*
// @grant       GM_registerMenuCommand
// @grant       GM.registerMenuCommand
// @run-at      document-idle
// @version     1.1.0
// @author      bgme
// @description 解除网页“禁用复制”限制
// @supportURL  https://github.com/yingziwu/Greasemonkey/issues
// @icon        https://github.githubassets.com/images/icons/emoji/unicode/1f33f.png
// @license     AGPL-3.0-or-later
// ==/UserScript==

"use strict";

GM.registerMenuCommand("解除复制限制", run);

function run() {
  celery(document);
}

// 来自:https://github.com/yulanggong/celery/blob/master/celery.js
function celery(doc) {
  // uglify 优化
  var parentNode = "parentNode";
  var replaceChild = "replaceChild";
  var innerHTML = "innerHTML";
  var documentElement = "documentElement";
  var createElement = "createElement";
  var forEach = "forEach";
  var _script = "script";
  var events = "contextmenu dragstart selectstart select copy beforecopy mouseup mousedown".split(
    " "
  );

  function noop() {}

  function remove(element) {
    element[parentNode].removeChild(element);
  }

  function query(selecter) {
    return [].slice.call(doc.querySelectorAll(selecter));
  }

  function strip(element) {
    events[forEach](function (event) {
      // 移除 DOM 0 事件
      element["on" + event] = null;
    });
    var done;

    function deep() {
      _setTimeout(function () {
        if (!done) {
          try {
            var contentDocument = element.contentDocument;
            if (contentDocument.body.childNodes.length) {
              done = 1;
              celery(contentDocument);
            }
          } catch (e) {
            done = 0;
          }
        }
      }, 100);
    }

    deep();
    element.onload = deep;
  }

  // 清空所有定时器
  for (var i = setTimeout(noop, 0); i >= 0; i--) {
    clearTimeout(i);
  }
  for (i = setInterval(noop, 1e8); i >= 0; i--) {
    clearInterval(i);
  }

  var _setTimeout = setTimeout;

  // 覆盖掉延时方法
  setTimeout = setInterval = noop;

  // 通过替换 DOM 的方式移除节点上的监听事件
  query(_script)[forEach](remove);

  // frame 不能通过 innerHTML 完全重建,缓存起来
  var frames = [];
  query("iframe,frame")[forEach](function (frame) {
    frames.push(frame);
    frame[parentNode][replaceChild](doc[createElement](_script), frame);
  });

  var old = doc[documentElement][innerHTML];
  doc.open();
  doc.write("<!DOCTYPE html>");
  doc.close();
  doc[documentElement][innerHTML] = old;

  // 替换回 frame
  query(_script)[forEach](function (script) {
    script[parentNode][replaceChild](frames.shift(), script);
  });

  query("*")[forEach](strip);
  strip(doc);

  events[forEach](function (event) {
    // 阻止事件传播
    doc.addEventListener(
      event,
      function (e) {
        e.stopPropagation();
      },
      true
    );
  });

  // 移除通过样式禁用选择
  var style = doc[createElement]("style");
  style[innerHTML] =
    "*{-webkit-user-select:text!important;-moz-user-select:text!important;user-select:text!important;}";
  doc.body.appendChild(style);
}