Greasy Fork

Greasy Fork is available in English.

解除网页“禁用复制”

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

当前为 2020-07-07 提交的版本,查看 最新版本

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Greasemonkey 油猴子Violentmonkey 暴力猴,才能安装此脚本。

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

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

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴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);
}