Greasy Fork

来自缓存

Greasy Fork is available in English.

萌娘百科预览修复

修复萌娘百科鼠标悬停预览

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

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

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

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

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

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

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

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

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

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

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

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

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

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

// ==UserScript==
// @name        Moegirlpedia Preview Fix
// @name:zh-CN  萌娘百科预览修复
// @namespace   http://greasyfork.icu/zh-CN/users/163820-ysc3839
// @description Fix Moegirlpedia Mouse Hover Preview
// @description:zh-CN 修复萌娘百科鼠标悬停预览
// @license     MIT
// @grant       GM_xmlhttpRequest
// @grant       unsafeWindow
// @version     3
// @author      ysc3839
// @match       *://zh.moegirl.org.cn/*
// @run-at      document-idle
// ==/UserScript==

(function () {
  let first_load = true;
  (function f() {
    const $ = unsafeWindow.jQuery;
    if (!$) {
      if (first_load) {
        first_load = false;
        setTimeout(f, 100);
      }
      return;
    }

    const API_PATH = '/api.php';
    // https://developer.mozilla.org/en-US/docs/Glossary/Forbidden_header_name
    const FORBIDDEN_HEADERS = new Set([
      'Accept-Charset',
      'Accept-Encoding',
      'Access-Control-Request-Headers',
      'Access-Control-Request-Method',
      'Connection',
      'Content-Length',
      'Cookie',
      'Date',
      'DNT',
      'Expect',
      'Host',
      'Keep-Alive',
      'Origin',
      'Permissions-Policy',
      'Referer',
      'TE',
      'Trailer',
      'Transfer-Encoding',
      'Upgrade',
      'Via',
    ]);

    $.ajaxTransport('json', function (options) {
      if (options.crossDomain || !options.async) return;
      if (!options.url.startsWith(API_PATH)) return;
      const u = new URL(options.url, document.baseURI);
      if (u.pathname !== API_PATH || u.host !== location.host) return;

      const s = u.searchParams;
      const prop = s.get('prop');
      if (prop) {
        const p = new Set(prop.split('|'));
        p.delete('revisions');
        s.set('prop', Array.from(p).join('|'));
      }
      s.delete('rvprop');
      s.delete('uselang');

      let callback;
      return {
        send: function (headers, complete) {
          // Apply custom fields if provided
          if (options.xhrFields) {
            console.warn('options.xhrFields unsupported', options.xhrFields);
          }

          // X-Requested-With header
          // For cross-domain requests, seeing as conditions for a preflight are
          // akin to a jigsaw puzzle, we simply never set it to be sure.
          // (it can always be set on a per-request basis or even using ajaxSetup)
          // For same-domain requests, won't change header if already provided.
          if (!options.crossDomain && !headers['X-Requested-With']) {
            headers['X-Requested-With'] = 'XMLHttpRequest';
          }

          // Remove forbidden headers
          for (let i in headers) {
            if (i.startsWith('Proxy-') || i.startsWith('Sec-') || FORBIDDEN_HEADERS.has(i)) {
              delete headers[i];
            }
          }

          let controller;

          // Callback
          callback = function (type) {
            return function (xhr) {
              if (callback) {
                callback = null;

                if (type === 'abort') {
                  if (controller)
                    controller.abort();
                } else if (type === 'error') {
                  complete(
                    xhr.status,
                    xhr.statusText
                  );
                } else {
                  complete(
                    (xhr.status === 0) ? 200 : xhr.status,
                    xhr.statusText,
                    { text: xhr.responseText },
                    xhr.responseHeaders
                  );
                }
              }
            };
          };

          // Listen to events
          const onload = callback();
          const onerror = callback('error');

          // Create the abort callback
          callback = callback('abort');

          try {
            // Do send the request (this may raise an exception)
            controller = GM_xmlhttpRequest({
              url: u.href,
              method: options.type,
              user: options.username,
              password: options.password,
              overrideMimeType: options.mimeType,
              headers,
              data: options.hasContent && options.data || null,
              anonymous: true, // Sending cookie may cause server return api error
              onload,
              onabort: onerror,
              onerror,
              ontimeout: onerror,
            });
          } catch (e) {
            // trac-14683: Only rethrow if this hasn't been notified as an error yet
            if (callback) {
              throw e;
            }
          }
        },

        abort: function () {
          if (callback) {
            callback();
          }
        }
      };
    });
  })();
})();