Greasy Fork 支持简体中文。

Moegirlpedia Preview Fix

Fix Moegirlpedia Mouse Hover Preview

// ==UserScript==
// @name        Moegirlpedia Preview Fix
// @name:zh-CN  萌娘百科预览修复
// @namespace   https://greasyfork.org/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();
          }
        }
      };
    });
  })();
})();