打开/关闭菜单
打开/关闭个人菜单
未登录
未登录用户的IP地址会在进行任意编辑后公开展示。

MediaWiki:Common.js:修订间差异

MediaWiki界面页面
 
(strings that detached from the raw input are escaped (these strings are set with jQuery's .text() method))
第2行: 第2行:




 
 
/**
/**
* 自动转换链接
* 自动转换链接 - automatically convert texts to links
* @author [[User:UnownHearn]]
* @author [[User:UnownHearn]]
* @version 1.4 (2019/03/18)
* @version 1.8 (2019/03/31)
*/
*/
(function () { /* 自动链接 */
(function () {
    var filter = (function (node) {
 
        if (node.nodeType == 3 /* TEXT_NODE */) {
            return NodeFilter.FILTER_ACCEPT;
        } else if (node.nodeType != 1 /* ELEMENT_NODE */
            || node.tagName.toLowerCase() == "a"
            || node.classList.contains("no-autolink")) {
            return NodeFilter.FILTER_REJECT;
        }
        return NodeFilter.FILTER_SKIP;
 
    })
 
     var rules = [{
     var rules = [{
         // id: ["sm", "nm"],
         // 两字母 + 一串数字
         regex: /(sm|nm|im|av|ac)\d+/g,
         regex: /[a-zA-Z]{2}\d+/,
         link: function (text) {
         link: function (text) {
            var base;
             switch (text.slice(0, 2)) {
             switch (text.slice(0, 2)) {
                 case "sm": case "nm":
                // niconico 主要
                    return "https://www.nicovideo.jp/watch/" + text;
                 case "sm": case "nm": base = "https://www.nicovideo.jp/watch/"; break;
                 case "im":
                 case "im": base = "https://seiga.nicovideo.jp/seiga/"; break;
                    return "https://seiga.nicovideo.jp/seiga/" + text;
                // bilibili
                 case "av":
                 case "av": base = "https://acg.tv/"; break;
                    return "https://www.bilibili.com/video/" + text;
                case "cv": /*专栏*/ base = "https://www.bilibili.com/read/"; break;
                 case "ac":
                case "am": /*音频*/ base = "https://www.bilibili.com/audio/"; break;
                    return "http://www.acfun.cn/v/" + text;
                case "ml": /*~~my~~medialist*/ base = "https://www.bilibili.com/medialist/play/"; break;
                // acfun
                 case "ac": base = "http://www.acfun.cn/v/"; break;
                // niconico 其他, 参考: https://dic.nicovideo.jp/a/nico.ms
                case "sg": case "mg": case "bk": /*静画*/ base = "https://seiga.nicovideo.jp/watch/"; break;
                case "lv": /*生放送*/ base = "https://live.nicovideo.jp/watch/"; break;
                /* l/co 略去 */
                case "co": /*社区*/ base = "https://com.nicovideo.jp/community/"; break;
                case "ch": /*频道*/ base = "https://ch.nicovideo.jp/channel/"; break;
                case "ar": /*频道文章*/ base = "https://ch.nicovideo.jp/article/"; break;
                case "nd": /*直贩*/ base = "https://chokuhan.nicovideo.jp/products/detail/"; break;
                /* 市场略去 */
                case "ap": /*应用*/ base = "https://app.nicovideo.jp/app/"; break;
                case "jk": /*实况*/ base = "https://jk.nicovideo.jp/watch/"; break;
                case "nc": /*共有*/ base = "https://www.niconicommons.jp/material/"; break;
                case "nw": /*新闻*/ base = "https://news.nicovideo.jp/watch/"; break;
             }
             }
            if (base !== undefined) { return base + text; }
            return null;
         }
         }
     }, {
     }, {
         // id: ["mylist", "user"],
         // niconico mylist/ 及 user/
         regex: /(mylist|user)\/\d+/g,
         regex: /(mylist|user)\/\d+/,
         link: "https://www.nicovideo.jp/{}"
         link: "https://www.nicovideo.jp/{}"
     }];
     }];
 
 
     var nodes = [];
     // Returns the url the given `linkableText` represents (E.g. "sm3777" => "https://nicovideo.jp/watch/sm3777")
 
     function generateLink(rule, linkableText) {
    var as = document.getElementsByClassName("WikiaArticle");
        if (typeof rule.link === "function") {
     Array.prototype.forEach.call(as, function (a) {
            var link = rule.link(linkableText);
        var walker = document.createTreeWalker(a, NodeFilter.SHOW_ALL, { acceptNode: filter });
            if (link !== null && typeof link !== "string") {
        while (walker.nextNode()) {
                throw "The return value of link() must be either a string or null!";
             nodes.push(walker.currentNode);
            }
            return link;
        } else {
             return rule.link.replace("{}", linkableText);
         }
         }
     })
     }
 
 
     for (var nodeIndex in nodes) {
    // Creates an <a>nchor element with given url `link` and `text`
         var node = nodes[nodeIndex];
    //
         var html = node.textContent;
    // the returned element has one and only one text node as its child.
 
    function createAnchorElement(link, text) {
        return $("<a/>").addClass("autolink").attr("href", link).text(text).get(0);
 
        // var a = document.createElement("a");
        // a.className = "autolink";
        // a.href = link;
        // a.textContent = text;
        // return a;
    }
 
    // Tries detaching a linkable text from given `text` with given `rules`
    //
    // If `text` matches a rule, it will return a tuple contains:
    //      text before the linkable text,
    //      <a>nchor element that represents the linkable text (or a text node if the text is actually not linkable),
    //      text after the linkable text;
    // Otherwise, it will return a tuple contains: "", null, and the original text.
     function detachLinkableText(text, rules) {
        var textBefore = "";
         var node = null;
         var textAfter = text;
        var lastMatch = null;
         for (var ruleIndex in rules) {
         for (var ruleIndex in rules) {
             var rule = rules[ruleIndex];
             var rule = rules[ruleIndex];
             html = html.replace(rule.regex, function (old) {
             var match = rule.regex.exec(text);
                 var link;
            if (match != null && (lastMatch === null || match.index < lastMatch.index)) {
                 if (typeof rule.link === "function") {
                lastMatch = match;
                     link = rule.link(old);
                textBefore = text.slice(0, match.index);
 
                var linkableText = match[0];
                 var link = generateLink(rule, linkableText);
                 if (link == null) {
                     node = document.createTextNode(linkableText);
                 } else {
                 } else {
                     link = rule.link.replace("{}", old);
                     node = createAnchorElement(link, linkableText);
                }
               
                textAfter = text.slice(match.index + linkableText.length);
            }
        }
        return [textBefore, node, textAfter];
    }
 
    function main() {
        var foundTextNodes = [];
 
        { //< put all text nodes that under `.WikiaArticle` elements but not under `a` or `.no-autolink` elements into `foundTextNodes`
            var articles = document.getElementsByClassName("WikiaArticle");
            var filter = (function (node) {
                if (node.nodeType == 3 /* TEXT_NODE */) {
                    return NodeFilter.FILTER_ACCEPT;
                } else if (node.nodeType != 1 /* ELEMENT_NODE */
                    || node.tagName.toLowerCase() == "a"
                    || node.classList.contains("no-autolink")) {
                    return NodeFilter.FILTER_REJECT;
                }
                return NodeFilter.FILTER_SKIP;
            })
            Array.prototype.forEach.call(articles, function (article) {
                var walker = document.createTreeWalker(article, NodeFilter.SHOW_ALL, { acceptNode: filter });
                while (walker.nextNode()) {
                    foundTextNodes.push(walker.currentNode);
                 }
                 }
                return "<a class=\"autolink\" href=\"" + link + "\">" +
             })
                    old + "</a>";
             });
         }
         }
 
 
         if (html != node.textContent) {
         for (var nodeIndex in foundTextNodes) {
            var parentNode = node.parentNode;
            var foundTextNode = foundTextNodes[nodeIndex];
            var dummy = document.createElement("span");
            var remainText = foundTextNode.textContent;
             dummy.innerHTML = html;
            // this array will only contain text nodes and <a>nchor element nodes that have text nodes
            parentNode.replaceChild(dummy, node);
            var nodes = [];
 
            while (true) {
                var oldRemainText = remainText;
 
                var rets = detachLinkableText(remainText, rules);
                var textBefore = rets[0];
                var elem = rets[1];
                remainText = rets[2];
                if (elem === null) {
                    // no rule matches
                    break;
                }
                if (textBefore !== "") {
                    nodes.push(document.createTextNode(textBefore));
                }
                nodes.push(elem);
 
                // `detachLinkableText()` splits the `remainText` into 3 parts: `textBefore`, `elem`, and the new `remainText`.
                // as long as `elem` is not null, the new `remainText` will always be shorter than the old one.
                //
                // this check ensures that the outer `while (true)` loop won't be an infinite loop even if `detachLinkableText()` not working properly
                if (remainText.length >= oldRemainText.length) {
                    throw "oof";
                }
             }
 
            if (nodes.length !== 0) { //< check if need to replace the original node
                nodes.push(document.createTextNode(remainText));
                $(foundTextNode).replaceWith(nodes);
            }
         }
         }
     }
     }
    main();
})();
})();

2019年4月4日 (四) 21:43的版本

/* 此处的JavaScript将加载于所有用户每一个页面。 */



/**
* 自动转换链接 - automatically convert texts to links
* @author [[User:UnownHearn]]
* @version 1.8 (2019/03/31)
*/
(function () {

    var rules = [{
        // 两字母 + 一串数字
        regex: /[a-zA-Z]{2}\d+/,
        link: function (text) {
            var base;
            switch (text.slice(0, 2)) {
                // niconico 主要
                case "sm": case "nm": base = "https://www.nicovideo.jp/watch/"; break;
                case "im": base = "https://seiga.nicovideo.jp/seiga/"; break;
                // bilibili
                case "av": base = "https://acg.tv/"; break;
                case "cv": /*专栏*/ base = "https://www.bilibili.com/read/"; break;
                case "am": /*音频*/ base = "https://www.bilibili.com/audio/"; break;
                case "ml": /*~~my~~medialist*/ base = "https://www.bilibili.com/medialist/play/"; break;
                // acfun
                case "ac": base = "http://www.acfun.cn/v/"; break;
                // niconico 其他, 参考: https://dic.nicovideo.jp/a/nico.ms
                case "sg": case "mg": case "bk": /*静画*/ base = "https://seiga.nicovideo.jp/watch/"; break;
                case "lv": /*生放送*/ base = "https://live.nicovideo.jp/watch/"; break;
                /* l/co 略去 */
                case "co": /*社区*/ base = "https://com.nicovideo.jp/community/"; break;
                case "ch": /*频道*/ base = "https://ch.nicovideo.jp/channel/"; break;
                case "ar": /*频道文章*/ base = "https://ch.nicovideo.jp/article/"; break;
                case "nd": /*直贩*/ base = "https://chokuhan.nicovideo.jp/products/detail/"; break;
                /* 市场略去 */
                case "ap": /*应用*/ base = "https://app.nicovideo.jp/app/"; break;
                case "jk": /*实况*/ base = "https://jk.nicovideo.jp/watch/"; break;
                case "nc": /*共有*/ base = "https://www.niconicommons.jp/material/"; break;
                case "nw": /*新闻*/ base = "https://news.nicovideo.jp/watch/"; break;
            }
            if (base !== undefined) { return base + text; }
            return null;
        }
    }, {
        // niconico mylist/ 及 user/
        regex: /(mylist|user)\/\d+/,
        link: "https://www.nicovideo.jp/{}"
    }];

    // Returns the url the given `linkableText` represents (E.g. "sm3777" => "https://nicovideo.jp/watch/sm3777")
    function generateLink(rule, linkableText) {
        if (typeof rule.link === "function") {
            var link = rule.link(linkableText);
            if (link !== null && typeof link !== "string") {
                throw "The return value of link() must be either a string or null!";
            }
            return link;
        } else {
            return rule.link.replace("{}", linkableText);
        }
    }

    // Creates an <a>nchor element with given url `link` and `text`
    //
    // the returned element has one and only one text node as its child.
    function createAnchorElement(link, text) {
        return $("<a/>").addClass("autolink").attr("href", link).text(text).get(0);

        // var a = document.createElement("a");
        // a.className = "autolink";
        // a.href = link;
        // a.textContent = text;
        // return a;
    }

    // Tries detaching a linkable text from given `text` with given `rules`
    //
    // If `text` matches a rule, it will return a tuple contains: 
    //      text before the linkable text,
    //      <a>nchor element that represents the linkable text (or a text node if the text is actually not linkable),
    //      text after the linkable text;
    // Otherwise, it will return a tuple contains: "", null, and the original text.
    function detachLinkableText(text, rules) {
        var textBefore = "";
        var node = null;
        var textAfter = text;
        var lastMatch = null;
        for (var ruleIndex in rules) {
            var rule = rules[ruleIndex];
            var match = rule.regex.exec(text);
            if (match != null && (lastMatch === null || match.index < lastMatch.index)) {
                lastMatch = match;
                textBefore = text.slice(0, match.index);

                var linkableText = match[0];
                var link = generateLink(rule, linkableText);
                if (link == null) {
                    node = document.createTextNode(linkableText);
                } else {
                    node = createAnchorElement(link, linkableText);
                }
                
                textAfter = text.slice(match.index + linkableText.length);
            }
        }
        return [textBefore, node, textAfter];
    }

    function main() {
        var foundTextNodes = [];

        { //< put all text nodes that under `.WikiaArticle` elements but not under `a` or `.no-autolink` elements into `foundTextNodes`
            var articles = document.getElementsByClassName("WikiaArticle");
            var filter = (function (node) {
                if (node.nodeType == 3 /* TEXT_NODE */) {
                    return NodeFilter.FILTER_ACCEPT;
                } else if (node.nodeType != 1 /* ELEMENT_NODE */
                    || node.tagName.toLowerCase() == "a"
                    || node.classList.contains("no-autolink")) {
                    return NodeFilter.FILTER_REJECT;
                }
                return NodeFilter.FILTER_SKIP;
            })
            Array.prototype.forEach.call(articles, function (article) {
                var walker = document.createTreeWalker(article, NodeFilter.SHOW_ALL, { acceptNode: filter });
                while (walker.nextNode()) {
                    foundTextNodes.push(walker.currentNode);
                }
            })
        }

        for (var nodeIndex in foundTextNodes) {
            var foundTextNode = foundTextNodes[nodeIndex];
            var remainText = foundTextNode.textContent;
            // this array will only contain text nodes and <a>nchor element nodes that have text nodes
            var nodes = [];

            while (true) {
                var oldRemainText = remainText;

                var rets = detachLinkableText(remainText, rules);
                var textBefore = rets[0];
                var elem = rets[1];
                remainText = rets[2];
                if (elem === null) {
                    // no rule matches
                    break;
                }
                if (textBefore !== "") {
                    nodes.push(document.createTextNode(textBefore));
                }
                nodes.push(elem);

                // `detachLinkableText()` splits the `remainText` into 3 parts: `textBefore`, `elem`, and the new `remainText`.
                // as long as `elem` is not null, the new `remainText` will always be shorter than the old one.
                //
                // this check ensures that the outer `while (true)` loop won't be an infinite loop even if `detachLinkableText()` not working properly
                if (remainText.length >= oldRemainText.length) {
                    throw "oof";
                }
            }

            if (nodes.length !== 0) { //< check if need to replace the original node
                nodes.push(document.createTextNode(remainText));
                $(foundTextNode).replaceWith(nodes);
            }
        }
    }

    main();

})();