Greasy Fork

来自缓存

Greasy Fork is available in English.

Switch to Mobile Wikipedia/Wiktionary and Back, Autoload Mobile Page

Automatically loads Mobile Wikipedia if you visit the desktop version of Wikipedia from a different site; provides a shortcut to switch between the two and stays on the version you switched to.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

// ==UserScript==
// @name         Switch to Mobile Wikipedia/Wiktionary and Back, Autoload Mobile Page
// @namespace    http://tampermonkey.net/
// @version      0.11
// @description  Automatically loads Mobile Wikipedia if you visit the desktop version of Wikipedia from a different site; provides a shortcut to switch between the two and stays on the version you switched to.
// @author       http://greasyfork.icu/en/users/728793-keyboard-shortcuts
// @icon         https://en.wikipedia.org/favicon.ico
// @match        https://*.wikipedia.org/*
// @match        https://*.wiktionary.org/*
// @match        https://*.wikimedia.org/*
// @match        https://*.wikiquote.org/*
// @match        https://*.wikibooks.org/*
// @license      MIT
// ==/UserScript==

/* jshint esversion: 6 */

// CONFIGURE THE SCRIPT HERE (set any of these to true or false, no other value):
const AUTOLOAD_MOBILE = true; // if set to true, loads the mobile page automatically when landing on a Wikimedia website.
const ENABLE_MOBILE_DESKTOP_SHORTCUT = true; // if set to true, lets you switch between mobile and non-mobile with ctrl-m on Windows or alt-m on Mac.
const ENABLE_EDIT_SHORTCUT = true; // if set to true, lets you edit an article with ctrl-e on Windows or alt-e on Mac.
const VIEW_HISTORY_IN_DESKTOP_MODE = true; // if set to true, view a wiki page's edit history in desktop mode. This is set to true by default since the history view on mobile is severely limited.
const LOG_DEBUG_MESSAGES = false; // if set to true, lets the script log debug information as it runs.
const REQUIRE_MODIFIER_FOR_SHORTCUTS = true;
// (END OF CONFIGURATION)

const WEBSITES = ['wikipedia', 'wiktionary', 'wikimedia', 'wikiquote', 'wikibooks'].join('|'); // in order to reuse this list underneath we have to use the RegExp constructor instead of the literal syntax.
const FULL_URL_REGEX = new RegExp('^(?<prefix>https?://[^/]*)(?<suffix>\\.(' + WEBSITES + ')\\.org/.*)');
const DOMAIN_REGEX = new RegExp('^(?<prefix>[^/]*)(?<suffix>\\.(' + WEBSITES + ')\\.org)');
const LANGUAGE_REGEX = new RegExp('^(https?://)(?<lang>[a-z]+)(\\.(' + WEBSITES + ')\\.org/.*)');
const DISABLED_ON_DOMAINS_REGEX = /^((cxserver|donate|dyna|foundation|lists|login|maps|outreach|phab|stats|toolsadmin|upload|wikitech|www)\.wikimedia.org)$/;

const EDIT_SUFFIX = 'action=edit';

function isMobile(match) {
    return match.groups.prefix.endsWith('.m');
}

function changeDomainToMobile(match) {
    return match.groups.prefix + '.m' + match.groups.suffix;
}

function changeDomainToDesktop(match) {
    return match.groups.prefix.substr(0, match.groups.prefix.length - 2) + match.groups.suffix;
}

function loadMobilePage(originalUrl, match) {
    const mobileUrl = new URL(changeDomainToMobile(match));
    location.href = mobileUrl.protocol + '//' + mobileUrl.host + mobileUrl.pathname + (originalUrl.search || '');
}

function switchToMobileOrBack(match) {
    const url = new URL(location.href);
    const altDomain = changeDomainToMobileOrBack(url);
    location.href = url.protocol + '//' + altDomain + url.pathname + (url.search || '');
}

function debugLog() {
    if (LOG_DEBUG_MESSAGES) {
        console.log.apply(null, arguments);
    }
}

function changeDomainToMobileOrBack(url) {
    const domain = url.hostname;
    const match = DOMAIN_REGEX.exec(domain);
    if (!match) {
        debugLog('Failed to convert domain:', domain);
        return domain;
    } else if (isMobile(match)) {
        return changeDomainToDesktop(match);
    } else {
        return changeDomainToMobile(match);
    }
}

function currentlyEditing() {
    const url = new URL(location.href);
    return (url.search.indexOf(EDIT_SUFFIX) !== -1 || url.hash.indexOf('#/editor/') != -1);
}

function switchToEditMode(match) {
    if (!currentlyEditing()) {
        const url = new URL(location.href);
        if (isMobile(match)) { // mobile: switch back to non-mobile page and add edit suffix
            location.href = url.protocol + '//' + changeDomainToMobileOrBack(url) + url.pathname + '?' + EDIT_SUFFIX;
        } else {
            location.href = url.protocol + '//' + url.host + url.pathname + '?' + EDIT_SUFFIX;
        }
    }
}

/**
 * Returns whether this is a history view of a page's changes, on a mobile Wiki.
 */
function isMobileSpecialHistoryPage(currentWiki) {
    return isMobile(currentWiki) && (location.href.indexOf('/Special:History/') !== -1);
}

/**
 * For a Special:History page, return the name of the Wiki page being examined.
 */
function extractPageNameFromSpecialHistoryPage(pathname) {
    const regex = /\/wiki\/Special:History\/(?<pagename>[^\/]+)\/?.*$/;
    const match = regex.exec(pathname);
    return match ? match.groups.pagename : null;
}

/**
 * An additional regex lets us disable the auto-switch behavior for some domains, like upload.wikimedia.org which doesn't have a .m version.
 */
function isMobileDisabledForThisDomain() {
    const url = new URL(location.href);
    const match = DISABLED_ON_DOMAINS_REGEX.exec(url.hostname);
    debugLog(`isMobileDisabledForThisDomain(${url.hostname}) -> ${!!match}`);
    return !!match;
}

(function() {
    'use strict';

    const url = new URL(location.href);
    const previousHref = document.referrer || '';
    const referrerWiki = FULL_URL_REGEX.exec(previousHref); // match object for the referrer
    const currentWiki = FULL_URL_REGEX.exec(location.href); // match object for the current address
    const disabledForDomain = isMobileDisabledForThisDomain(); // make sure we don't have an exclusion rule for this domain


    if (VIEW_HISTORY_IN_DESKTOP_MODE && isMobileSpecialHistoryPage(currentWiki)) { // extract domain and page, and redirect to full equivalent desktop page
        const nonMobileDomain = changeDomainToMobileOrBack(url);
        const pageName = extractPageNameFromSpecialHistoryPage(url.pathname);
        if (nonMobileDomain && pageName) {
            debugLog(`VIEW_HISTORY_IN_DESKTOP_MODE enabled, going to ${nonMobileDomain} for ${pageName} history`);
            const newUrl = `https://${nonMobileDomain}/w/index.php?title=${pageName}&action=history`;
            location.href = newUrl;
            return;
        }
    }

    if (AUTOLOAD_MOBILE) {
        const willSwitch = (currentWiki && !isMobile(currentWiki) && !disabledForDomain);
        if (!referrerWiki) { // referrer is *not* Wikimedia: make sure we hit the mobile website first
            if (willSwitch) { // First visit: switch to mobile by default
                loadMobilePage(url, currentWiki);
            }
        } else { // referrer is a Wikimedia site; check if it's a different language and switch to mobile if so
            const curLangMatch = LANGUAGE_REGEX.exec(location.href);
            const prevLangMatch = LANGUAGE_REGEX.exec(previousHref);
            if (curLangMatch && prevLangMatch && curLangMatch.groups.lang !== prevLangMatch.groups.lang) {
                debugLog(`Referrer is a Wikimedia site, but language went from ${ prevLangMatch.groups.lang } to ${ curLangMatch.groups.lang }. Will switch: ${ (willSwitch ? 'YES' : 'NO') }`);
                if (willSwitch) { // Language change: switch to mobile as if we came from a third-party website
                    loadMobilePage(url, currentWiki);
                }
            }
        }
    }

    /**
     * Validates that the event has either Alt or Ctrl set (but not both), but only if REQUIRE_MODIFIER_FOR_SHORTCUTS is set to true.
     * If it's false, validates that neither are set.
     */
    function hasModifierIfRequired(e) {
        if (REQUIRE_MODIFIER_FOR_SHORTCUTS) {
            return ((e.altKey || e.ctrlKey) && (e.altKey ^ e.ctrlKey)); // either, but not both.
        } else {
            return !(e.altKey || e.ctrlKey);
        }
    }

    function fieldAllowsInput(e) {
        const field = e.target;
        return (field.getAttribute("contenteditable") == "true") ||
               (field.tagName !== undefined && (field.tagName === 'TEXTAREA' || field.tagName === 'INPUT'));
    }

    function handleEvent(e) {
        if (!currentWiki) { // not on a Wikimedia website
            return;
        }
        if(currentlyEditing() || fieldAllowsInput(e)) { // not for edit modes, and not if the field is a text input
            return;
        }
        if (ENABLE_MOBILE_DESKTOP_SHORTCUT && hasModifierIfRequired(e) && e.code === 'KeyM') { // (ctrl-m or alt-m with modifiers, just "m" otherwise)
            switchToMobileOrBack(currentWiki);
        } else if (ENABLE_EDIT_SHORTCUT && hasModifierIfRequired(e) && e.code === 'KeyE') { // (ctrl-e or alt-e with modifiers, just "e" otherwise)
            debugLog('switching to edit mode');
            switchToEditMode(currentWiki);
        }
    }

    if (ENABLE_MOBILE_DESKTOP_SHORTCUT || ENABLE_EDIT_SHORTCUT) {
        addEventListener("keydown", handleEvent); // use keydown to catch shortcuts using modifier keys like ctrl or alt
    }

})();