Moegirlpedia Preview Fix

Fix Moegirlpedia Mouse Hover Preview

目前為 2024-02-17 提交的版本,檢視 最新版本

您需要先安裝使用者腳本管理器擴展,如 TampermonkeyGreasemonkeyViolentmonkey 之後才能安裝該腳本。

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

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyViolentmonkey 後才能安裝該腳本。

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyUserscripts 後才能安裝該腳本。

你需要先安裝一款使用者腳本管理器擴展,比如 Tampermonkey,才能安裝此腳本

您需要先安裝使用者腳本管理器擴充功能後才能安裝該腳本。

(我已經安裝了使用者腳本管理器,讓我安裝!)

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

(我已經安裝了使用者樣式管理器,讓我安裝!)

// ==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     2
// @author      ysc3839
// @match       *://zh.moegirl.org.cn/*
// @run-at      document-idle
// ==/UserScript==

(function () {
  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',
  ]);

  const $ = unsafeWindow.jQuery;
  if (!$) return;

  $.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();
        }
      }
    };
  });
})();