更多操作
小无编辑摘要 |
小无编辑摘要 |
||
第29行: | 第29行: | ||
* 自动转换链接 |
* 自动转换链接 |
||
* @author [[User:UnownHearn]] |
* @author [[User:UnownHearn]] |
||
* @version 1. |
* @version 1.6 (2019/03/23) |
||
*/ |
*/ |
||
(function () { |
(function () { |
||
var filter = (function (node) { |
var filter = (function (node) { |
||
if (node.nodeType == 3 /* TEXT_NODE */) { |
if (node.nodeType == 3 /* TEXT_NODE */) { |
||
第46行: | 第46行: | ||
var rules = [{ |
var rules = [{ |
||
// 两字母 + 一串数字 |
// 两字母 + 一串数字 |
||
regex: /[a-zA-Z]{2}\d+/ |
regex: /[a-zA-Z]{2}\d+/, |
||
link: function (text) { |
link: function (text) { |
||
var base; |
var base; |
||
第74行: | 第74行: | ||
} |
} |
||
if (base !== undefined) { return base + text; } |
if (base !== undefined) { return base + text; } |
||
return |
return null; |
||
} |
} |
||
}, { |
}, { |
||
// niconico mylist/ 及 user/ |
// niconico mylist/ 及 user/ |
||
regex: /(mylist|user)\/\d+/ |
regex: /(mylist|user)\/\d+/, |
||
link: "https://www.nicovideo.jp/{}" |
link: "https://www.nicovideo.jp/{}" |
||
}]; |
}]; |
||
// generate url link for given text under the rule (E.g. "sm3777" => "https://nicovideo.jp/watch/sm3777") |
|||
var nodes = []; |
|||
function generateLink(rule, linkableText) { |
|||
if (typeof rule.link === "function") { |
|||
⚫ | |||
link = rule.link(linkableText); |
|||
⚫ | |||
if (link !== null && typeof link !== "string") { |
|||
⚫ | |||
throw "The return value of link() must be either a string or null!"; |
|||
⚫ | |||
} |
|||
⚫ | |||
⚫ | |||
return rule.link.replace("{}", linkableText); |
|||
} |
} |
||
} |
} |
||
// create a <a/> element with given url link and inner text |
|||
⚫ | |||
function makeAElement(link, text) { |
|||
⚫ | |||
var |
var a = document.createElement("a"); |
||
a.className = "autolink"; |
|||
a.href = link; |
|||
a.textContent = text; |
|||
return a; |
|||
} |
|||
// try spliting the given text to three parts by rules. |
|||
function matchRules(text, rules) { |
|||
for (var ruleIndex in rules) { |
for (var ruleIndex in rules) { |
||
var rule = rules[ruleIndex]; |
var rule = rules[ruleIndex]; |
||
var match = rule.regex.exec(text); |
|||
if (match != null) { |
|||
var textBefore = text.slice(0, match.index); |
|||
var linkableText = match[0]; |
|||
var link = generateLink(rule, linkableText); |
|||
var aElement = makeAElement(link, linkableText); |
|||
var remainText = text.slice(match.index + match[0].length); |
|||
return [textBefore, aElement, remainText]; |
|||
} |
|||
⚫ | |||
return "<a class=\"autolink\" href=\"" + link + "\">" + |
|||
⚫ | |||
⚫ | |||
} |
} |
||
return ["", null, text]; |
|||
} |
|||
function main() { |
|||
if (html != node.textContent) { |
|||
var foundTextNodes = []; |
|||
var dummy = document.createElement("span"); |
|||
⚫ | |||
⚫ | |||
⚫ | |||
parentNode.replaceChild(dummy, node); |
|||
⚫ | |||
⚫ | |||
foundTextNodes.push(walker.currentNode); |
|||
} |
|||
}) |
|||
⚫ | |||
⚫ | |||
var remainText = foundTextNode.textContent; |
|||
var nodes = []; //< will only contain text nodes and <a/> element nodes |
|||
while (true) { |
|||
var rets = matchRules(remainText, rules); |
|||
var textBefore = rets[0]; |
|||
var aElement = rets[1]; |
|||
⚫ | |||
if (aElement === null) { |
|||
// no (more) matches |
|||
⚫ | |||
} |
|||
if (textBefore !== "") { |
|||
nodes.push(document.createTextNode(textBefore)); |
|||
} |
|||
nodes.push(aElement); |
|||
} |
|||
if (nodes.length !== 0) { // needs to replace |
|||
nodes.push(document.createTextNode(remainText)); |
|||
$(foundTextNode).replaceWith(nodes); |
|||
} |
|||
} |
} |
||
} |
} |
||
main(); |
|||
})(); |
})(); |
2019年3月23日 (六) 12:24的版本
"use strict";
/**
* 在鼠标移至文本与标题不同的 wikilink 上时, 弹出带有原标题的 popup
* @author [[User:UnownHearn]]
* @version 1 (2018/07/28)
*/
(function () {
// https://stackoverflow.com/questions/14346414/how-do-you-do-html-encode-using-javascript
function htmlEncode(value) {
//create a in-memory div, set it's inner text(which jQuery automatically encodes)
//then grab the encoded contents back out. The div never exists on the page.
return $('<div/>').text(value).html();
}
$(".WikiaArticle a[title]").hover(function () {
if (this.className != "") { return; } // 作为 wikilink 的超链接没有 class
var a = $(this);
var title = a.attr("title");
if (title != a.text()) {
a.append($('<span class="wikilink-popup">' + htmlEncode(title) + '</span>'));
}
}, function () {
$(this).find(".wikilink-popup").remove();
});
})();
/**
* 自动转换链接
* @author [[User:UnownHearn]]
* @version 1.6 (2019/03/23)
*/
(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 = [{
// 两字母 + 一串数字
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://www.bilibili.com/video/"; break;
case "cv": /*专栏*/ base = "https://www.bilibili.com/read/"; break;
case "am": /*音频*/ base = "https://www.bilibili.com/audio/"; 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/{}"
}];
// generate url link for given text under the rule (E.g. "sm3777" => "https://nicovideo.jp/watch/sm3777")
function generateLink(rule, linkableText) {
if (typeof rule.link === "function") {
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);
}
}
// create a <a/> element with given url link and inner text
function makeAElement(link, text) {
var a = document.createElement("a");
a.className = "autolink";
a.href = link;
a.textContent = text;
return a;
}
// try spliting the given text to three parts by rules.
function matchRules(text, rules) {
for (var ruleIndex in rules) {
var rule = rules[ruleIndex];
var match = rule.regex.exec(text);
if (match != null) {
var textBefore = text.slice(0, match.index);
var linkableText = match[0];
var link = generateLink(rule, linkableText);
var aElement = makeAElement(link, linkableText);
var remainText = text.slice(match.index + match[0].length);
return [textBefore, aElement, remainText];
}
}
return ["", null, text];
}
function main() {
var foundTextNodes = [];
var articles = document.getElementsByClassName("WikiaArticle");
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;
var nodes = []; //< will only contain text nodes and <a/> element nodes
while (true) {
var rets = matchRules(remainText, rules);
var textBefore = rets[0];
var aElement = rets[1];
remainText = rets[2];
if (aElement === null) {
// no (more) matches
break;
}
if (textBefore !== "") {
nodes.push(document.createTextNode(textBefore));
}
nodes.push(aElement);
}
if (nodes.length !== 0) { // needs to replace
nodes.push(document.createTextNode(remainText));
$(foundTextNode).replaceWith(nodes);
}
}
}
main();
})();