MediaWiki:Gadget-DotsSyntaxHighlighter.js:修订间差异
跳到导航
跳到搜索
imported>=海豚= 无编辑摘要 |
imported>=海豚= 无编辑摘要 |
||
| 第1行: | 第1行: | ||
// | /* Based on https://www.mediawiki.org/wiki/User:Remember_the_dot/Syntax_highlighter.js */ | ||
// | /* https://www.mediawiki.org/wiki/User:NicoV/Syntax_highlighter.js */ | ||
/* This file may be used under the terms of any of the following | /* This file may be used under the terms of any of the following | ||
licenses, as well as any later version of the same licenses: | licenses, as well as any later version of the same licenses: | ||
| 第15行: | 第14行: | ||
*/ | */ | ||
mw.loader.using("jquery.client", function() { | mw.loader.using("jquery.client", function() { | ||
"use strict"; | "use strict"; | ||
var wpTextbox0; | var wpTextbox0; | ||
var wpTextbox1; | var wpTextbox1; | ||
var syntaxStyleTextNode; | var syntaxStyleTextNode; | ||
var lastText; | var lastText; | ||
var maxSpanNumber = -1; | var maxSpanNumber = -1; | ||
var highlightSyntaxIfNeededIntervalID; | var highlightSyntaxIfNeededIntervalID; | ||
var attributeObserver; | var attributeObserver; | ||
var parentObserver; | var parentObserver; | ||
var wgUrlProtocols = mw.config.get("wgUrlProtocols"); | var wgUrlProtocols = mw.config.get("wgUrlProtocols"); | ||
var entityRegexBase = "&(?:(?:n(?:bsp|dash)|m(?:dash|inus)|lt|e[mn]sp|thinsp|amp|quot|gt|shy|zwn?j|lrm|rlm|Alpha|Beta|Epsilon|Zeta|Eta|Iota|Kappa|[Mm]u|micro|Nu|[Oo]micron|[Rr]ho|Tau|Upsilon|Chi)|#x[0-9a-fA-F]+);\n*"; | var entityRegexBase = "&(?:(?:n(?:bsp|dash)|m(?:dash|inus)|lt|e[mn]sp|thinsp|amp|quot|gt|shy|zwn?j|lrm|rlm|Alpha|Beta|Epsilon|Zeta|Eta|Iota|Kappa|[Mm]u|micro|Nu|[Oo]micron|[Rr]ho|Tau|Upsilon|Chi)|#x[0-9a-fA-F]+);\n*"; | ||
| 第68行: | 第31行: | ||
function breakerRegexWithPrefix(prefix) | function breakerRegexWithPrefix(prefix) | ||
{ | { | ||
return new RegExp("(" + prefix + ")\n*|" + breakerRegexBase, "gm"); | return new RegExp("(" + prefix + ")\n*|" + breakerRegexBase, "gm"); | ||
} | } | ||
| 第75行: | 第37行: | ||
return new RegExp("(</" + tagName + ">)\n*|" + entityRegexBase, "gm"); | return new RegExp("(</" + tagName + ">)\n*|" + entityRegexBase, "gm"); | ||
} | } | ||
var defaultBreakerRegex | var defaultBreakerRegex = new RegExp(breakerRegexBase, "gm"); | ||
var wikilinkBreakerRegex | var wikilinkBreakerRegex = breakerRegexWithPrefix("]][a-zA-Z]*"); | ||
var namedExternalLinkBreakerRegex = breakerRegexWithPrefix("]"); | var namedExternalLinkBreakerRegex = breakerRegexWithPrefix("]"); | ||
var parameterBreakerRegex | var parameterBreakerRegex = breakerRegexWithPrefix("}}}"); | ||
var templateBreakerRegex | var templateBreakerRegex = breakerRegexWithPrefix("}}"); | ||
var tableBreakerRegex | var tableBreakerRegex = breakerRegexWithPrefix("\\|}"); | ||
var headingBreakerRegex | var headingBreakerRegex = breakerRegexWithPrefix("\n"); | ||
var tagBreakerRegexCache | var tagBreakerRegexCache = {}; | ||
var nowikiTagBreakerRegexCache | var nowikiTagBreakerRegexCache = {}; | ||
function highlightSyntax() | function highlightSyntax() | ||
{ | { | ||
lastText = wpTextbox1.value; | lastText = wpTextbox1.value; | ||
var text = lastText.replace(/['\\]/g, "\\$&") + "\n"; | |||
var i = 0; | |||
var text = lastText.replace(/['\\]/g, "\\$&") + "\n"; | |||
var i = 0; | |||
var css = ""; | var css = ""; | ||
| 第100行: | 第58行: | ||
var before = true; | var before = true; | ||
function writeText(text, color) | function writeText(text, color) | ||
{ | { | ||
if (color != lastColor) | if (color != lastColor) | ||
{ | { | ||
css += "'}#s" + spanNumber; | |||
css += "'}#s" + spanNumber; | |||
if (before) | if (before) | ||
{ | { | ||
| 第122行: | 第76行: | ||
if (color) | if (color) | ||
{ | { | ||
css += "background-color:" + color + ";"; | css += "background-color:" + color + ";"; | ||
} | } | ||
| 第130行: | 第83行: | ||
css += text; | css += text; | ||
} | } | ||
function highlightBlock(color, breakerRegex, assumedBold, assumedItalic) | function highlightBlock(color, breakerRegex, assumedBold, assumedItalic) | ||
| 第157行: | 第92行: | ||
if (match[1]) | if (match[1]) | ||
{ | { | ||
writeText(text.substring(i, breakerRegex.lastIndex), color); | writeText(text.substring(i, breakerRegex.lastIndex), color); | ||
i = breakerRegex.lastIndex; | i = breakerRegex.lastIndex; | ||
| 第164行: | 第98行: | ||
var endIndexOfLastColor = breakerRegex.lastIndex - match[0].length; | var endIndexOfLastColor = breakerRegex.lastIndex - match[0].length; | ||
if (i < endIndexOfLastColor) | if (i < endIndexOfLastColor) | ||
{ | { | ||
writeText(text.substring(i, endIndexOfLastColor), color); | writeText(text.substring(i, endIndexOfLastColor), color); | ||
| 第171行: | 第105行: | ||
i = breakerRegex.lastIndex; | i = breakerRegex.lastIndex; | ||
switch (match[0].charAt(0)) | switch (match[0].charAt(0)) | ||
{ | { | ||
case "[": | case "[": | ||
if (match[0].charAt(1) == "[") | if (match[0].charAt(1) == "[") | ||
{ | { | ||
writeText("[[", syntaxHighlighterConfig.wikilinkColor || color); | writeText("[[", syntaxHighlighterConfig.wikilinkColor || color); | ||
highlightBlock(syntaxHighlighterConfig.wikilinkColor || color, wikilinkBreakerRegex); | highlightBlock(syntaxHighlighterConfig.wikilinkColor || color, wikilinkBreakerRegex); | ||
| 第182行: | 第115行: | ||
else | else | ||
{ | { | ||
writeText(match[0], syntaxHighlighterConfig.externalLinkColor || color); | writeText(match[0], syntaxHighlighterConfig.externalLinkColor || color); | ||
highlightBlock(syntaxHighlighterConfig.externalLinkColor || color, namedExternalLinkBreakerRegex); | highlightBlock(syntaxHighlighterConfig.externalLinkColor || color, namedExternalLinkBreakerRegex); | ||
| 第192行: | 第124行: | ||
if (match[0].length == 3) | if (match[0].length == 3) | ||
{ | { | ||
writeText("{{{", syntaxHighlighterConfig.parameterColor || color); | writeText("{{{", syntaxHighlighterConfig.parameterColor || color); | ||
highlightBlock(syntaxHighlighterConfig.parameterColor || color, parameterBreakerRegex); | highlightBlock(syntaxHighlighterConfig.parameterColor || color, parameterBreakerRegex); | ||
| 第198行: | 第129行: | ||
else | else | ||
{ | { | ||
writeText("{{", syntaxHighlighterConfig.templateColor || color); | writeText("{{", syntaxHighlighterConfig.templateColor || color); | ||
highlightBlock(syntaxHighlighterConfig.templateColor || color, templateBreakerRegex); | highlightBlock(syntaxHighlighterConfig.templateColor || color, templateBreakerRegex); | ||
} | } | ||
} | } | ||
else | else | ||
{ | { | ||
writeText("{|", syntaxHighlighterConfig.tableColor || color); | writeText("{|", syntaxHighlighterConfig.tableColor || color); | ||
highlightBlock(syntaxHighlighterConfig.tableColor || color, tableBreakerRegex); | highlightBlock(syntaxHighlighterConfig.tableColor || color, tableBreakerRegex); | ||
| 第213行: | 第142行: | ||
if (match[0].charAt(1) == "!") | if (match[0].charAt(1) == "!") | ||
{ | { | ||
writeText(match[0], syntaxHighlighterConfig.commentColor || color); | writeText(match[0], syntaxHighlighterConfig.commentColor || color); | ||
break; | break; | ||
| 第219行: | 第147行: | ||
else | else | ||
{ | { | ||
var tagEnd = text.indexOf(">", i) + 1; | var tagEnd = text.indexOf(">", i) + 1; | ||
if (tagEnd == 0) | if (tagEnd == 0) | ||
{ | { | ||
writeText("<", color); | writeText("<", color); | ||
i = i - match[0].length + 1; | i = i - match[0].length + 1; | ||
| 第230行: | 第155行: | ||
} | } | ||
if (text.charAt(tagEnd - 2) == "/") | if (text.charAt(tagEnd - 2) == "/" || syntaxHighlighterConfig.voidTags.indexOf(match[0].substring(1)) != -1) | ||
{ | { | ||
writeText(text.substring(i - match[0].length, tagEnd), syntaxHighlighterConfig.tagColor || color); | writeText(text.substring(i - match[0].length, tagEnd), syntaxHighlighterConfig.tagColor || color); | ||
i = tagEnd; | i = tagEnd; | ||
| 第242行: | 第166行: | ||
if (syntaxHighlighterConfig.sourceTags.indexOf(tagName) != -1) | if (syntaxHighlighterConfig.sourceTags.indexOf(tagName) != -1) | ||
{ | { | ||
var stopAfter = "</" + tagName + ">"; | var stopAfter = "</" + tagName + ">"; | ||
var endIndex = text.indexOf(stopAfter, i); | var endIndex = text.indexOf(stopAfter, i); | ||
| 第258行: | 第181行: | ||
else if (syntaxHighlighterConfig.nowikiTags.indexOf(tagName) != -1) | else if (syntaxHighlighterConfig.nowikiTags.indexOf(tagName) != -1) | ||
{ | { | ||
writeText(text.substring(i - match[0].length, tagEnd), syntaxHighlighterConfig.tagColor || color); | writeText(text.substring(i - match[0].length, tagEnd), syntaxHighlighterConfig.tagColor || color); | ||
i = tagEnd; | i = tagEnd; | ||
| 第265行: | 第187行: | ||
else | else | ||
{ | { | ||
writeText(text.substring(i - match[0].length, tagEnd), syntaxHighlighterConfig.tagColor || color); | writeText(text.substring(i - match[0].length, tagEnd), syntaxHighlighterConfig.tagColor || color); | ||
i = tagEnd; | i = tagEnd; | ||
| 第278行: | 第199行: | ||
break; | break; | ||
case "=": | case "=": | ||
if (/[^=]=+$/.test(text.substring(i, text.indexOf("\n", i)))) | if (/[^=]=+$/.test(text.substring(i, text.indexOf("\n", i)))) | ||
{ | { | ||
writeText("=", syntaxHighlighterConfig.headingColor || color); | writeText("=", syntaxHighlighterConfig.headingColor || color); | ||
highlightBlock(syntaxHighlighterConfig.headingColor || color, headingBreakerRegex); | highlightBlock(syntaxHighlighterConfig.headingColor || color, headingBreakerRegex); | ||
| 第286行: | 第206行: | ||
else | else | ||
{ | { | ||
writeText("=", color); | writeText("=", color); | ||
} | } | ||
break; | break; | ||
| 第292行: | 第212行: | ||
case "#": | case "#": | ||
case ":": | case ":": | ||
writeText(match[0], syntaxHighlighterConfig.listOrIndentColor || color); | writeText(match[0], syntaxHighlighterConfig.listOrIndentColor || color); | ||
break; | break; | ||
case ";": | case ";": | ||
writeText(";", syntaxHighlighterConfig.headingColor || color); | writeText(";", syntaxHighlighterConfig.headingColor || color); | ||
highlightBlock(syntaxHighlighterConfig.headingColor || color, headingBreakerRegex); | highlightBlock(syntaxHighlighterConfig.headingColor || color, headingBreakerRegex); | ||
break; | break; | ||
case "-": | case "-": | ||
writeText(match[0], syntaxHighlighterConfig.hrColor || color); | writeText(match[0], syntaxHighlighterConfig.hrColor || color); | ||
break; | break; | ||
| 第309行: | 第225行: | ||
if (match[0].length == 6) | if (match[0].length == 6) | ||
{ | { | ||
if (assumedBold) | if (assumedBold) | ||
{ | { | ||
if (assumedItalic) | if (assumedItalic) | ||
{ | { | ||
assumedBold = false; | assumedBold = false; | ||
} | } | ||
else | else | ||
{ | { | ||
return; | return; | ||
} | } | ||
| 第327行: | 第238行: | ||
else | else | ||
{ | { | ||
if (assumedItalic) | if (assumedItalic) | ||
{ | { | ||
assumedBold = true; | assumedBold = true; | ||
} | } | ||
else | else | ||
{ | { | ||
highlightBlock(syntaxHighlighterConfig.boldOrItalicColor || color, defaultBreakerRegex, true, false); | highlightBlock(syntaxHighlighterConfig.boldOrItalicColor || color, defaultBreakerRegex, true, false); | ||
} | } | ||
| 第343行: | 第250行: | ||
else | else | ||
{ | { | ||
if (assumedItalic) | if (assumedItalic) | ||
{ | { | ||
if (assumedBold) | if (assumedBold) | ||
{ | { | ||
assumedItalic = false; | assumedItalic = false; | ||
} | } | ||
else | else | ||
{ | { | ||
return; | return; | ||
} | } | ||
| 第361行: | 第263行: | ||
else | else | ||
{ | { | ||
if (assumedBold) | if (assumedBold) | ||
{ | { | ||
assumedItalic = true; | assumedItalic = true; | ||
} | } | ||
else | else | ||
{ | { | ||
highlightBlock(syntaxHighlighterConfig.boldOrItalicColor || color, defaultBreakerRegex, false, true); | highlightBlock(syntaxHighlighterConfig.boldOrItalicColor || color, defaultBreakerRegex, false, true); | ||
} | } | ||
| 第377行: | 第275行: | ||
break; | break; | ||
case "&": | case "&": | ||
writeText(match[0], syntaxHighlighterConfig.entityColor || color); | writeText(match[0], syntaxHighlighterConfig.entityColor || color); | ||
break; | break; | ||
case "~": | case "~": | ||
writeText(match[0], syntaxHighlighterConfig.signatureColor || color); | writeText(match[0], syntaxHighlighterConfig.signatureColor || color); | ||
break; | break; | ||
default: | default: | ||
writeText(match[0], syntaxHighlighterConfig.externalLinkColor || color); | writeText(match[0], syntaxHighlighterConfig.externalLinkColor || color); | ||
} | } | ||
| 第391行: | 第286行: | ||
} | } | ||
var startTime = Date.now(); | var startTime = Date.now(); | ||
highlightBlock("", defaultBreakerRegex); | highlightBlock("", defaultBreakerRegex); | ||
if (i < text.length) | if (i < text.length) | ||
{ | { | ||
| 第402行: | 第294行: | ||
} | } | ||
var endTime = Date.now(); | var endTime = Date.now(); | ||
if (endTime - startTime > syntaxHighlighterConfig.timeout) | if (endTime - startTime > syntaxHighlighterConfig.timeout) | ||
{ | { | ||
| 第429行: | 第307行: | ||
var errorMessage = { | var errorMessage = { | ||
zh: " 由于渲染耗时过长, Syntax highlighting 已在本页禁用。在设定中渲染时间被限制在$1 毫秒以内,但这次我们耗去了$2 毫秒。您可以尝试关闭一些标签页和程序,并点击“显示预览”或“显示更改”。如果这不起作用,请尝试更换一个不同的浏览器。如果这还不起作用,请尝试更换一个更快的电脑=w=。", | |||
en: "Syntax highlighting on this page was disabled because it took too long. The maximum allowed highlighting time is $1ms, and your computer took $2ms. Try closing some tabs and programs and clicking \"Show preview\" or \"Show changes\". If that doesn't work, try a different web browser, and if that doesn't work, try a faster computer.", | en: "Syntax highlighting on this page was disabled because it took too long. The maximum allowed highlighting time is $1ms, and your computer took $2ms. Try closing some tabs and programs and clicking \"Show preview\" or \"Show changes\". If that doesn't work, try a different web browser, and if that doesn't work, try a faster computer.", | ||
}; | }; | ||
var wgUserLanguage = mw.config.get("wgUserLanguage"); | var wgUserLanguage = mw.config.get("wgUserLanguage"); | ||
| 第460行: | 第324行: | ||
} | } | ||
if (maxSpanNumber < spanNumber) | if (maxSpanNumber < spanNumber) | ||
{ | { | ||
| 第473行: | 第335行: | ||
} | } | ||
syntaxStyleTextNode.nodeValue = css.substring(2).replace(/\n/g, "\\A ") + "'}"; | syntaxStyleTextNode.nodeValue = css.substring(2).replace(/\n/g, "\\A ") + "'}"; | ||
} | } | ||
| 第504行: | 第363行: | ||
} | } | ||
function highlightSyntaxIfNeeded() | function highlightSyntaxIfNeeded() | ||
{ | { | ||
| 第558行: | 第415行: | ||
window.syntaxHighlighterConfig = window.syntaxHighlighterConfig || {}; | window.syntaxHighlighterConfig = window.syntaxHighlighterConfig || {}; | ||
configureColor("backgroundColor", "#FFF", false); | |||
configureColor("backgroundColor", | configureColor("foregroundColor", "#000", false); | ||
configureColor("foregroundColor", | configureColor("boldOrItalicColor", "#EEE", true); | ||
configureColor("boldOrItalicColor", | configureColor("commentColor", "#EFE", true); | ||
configureColor("commentColor", | configureColor("entityColor", "#DFD", true); | ||
configureColor("entityColor", | configureColor("externalLinkColor", "#EFF", true); | ||
configureColor("externalLinkColor", | configureColor("headingColor", "#EEE", true); | ||
configureColor("headingColor", | configureColor("hrColor", "#EEE", true); | ||
configureColor("hrColor", | configureColor("listOrIndentColor", "#EFE", true); | ||
configureColor("listOrIndentColor", | configureColor("parameterColor", "#FC6", true); | ||
configureColor("parameterColor", | configureColor("signatureColor", "#FC6", true); | ||
configureColor("signatureColor", | configureColor("tagColor", "#FEF", true); | ||
configureColor("tagColor", | configureColor("tableColor", "#FFC", true); | ||
configureColor("tableColor", | configureColor("templateColor", "#FFC", true); | ||
configureColor("templateColor", | configureColor("wikilinkColor", "#EEF", true); | ||
configureColor("wikilinkColor", | |||
syntaxHighlighterConfig.nowikiTags = syntaxHighlighterConfig.nowikiTags || syntaxHighlighterSiteConfig.nowikiTags || ["nowiki", "pre"]; | syntaxHighlighterConfig.nowikiTags = syntaxHighlighterConfig.nowikiTags || syntaxHighlighterSiteConfig.nowikiTags || ["nowiki", "pre"]; | ||
syntaxHighlighterConfig.sourceTags = syntaxHighlighterConfig.sourceTags || syntaxHighlighterSiteConfig.sourceTags || ["math", "syntaxhighlight", "source", "timeline", "hiero"]; | syntaxHighlighterConfig.sourceTags = syntaxHighlighterConfig.sourceTags || syntaxHighlighterSiteConfig.sourceTags || ["math", "syntaxhighlight", "source", "timeline", "hiero", "score"]; | ||
syntaxHighlighterConfig.voidTags = syntaxHighlighterConfig.voidTags || syntaxHighlighterSiteConfig.voidTags || ["br", "hr"]; | |||
syntaxHighlighterConfig.timeout = syntaxHighlighterConfig.timeout || syntaxHighlighterSiteConfig.timeout || 50; | syntaxHighlighterConfig.timeout = syntaxHighlighterConfig.timeout || syntaxHighlighterSiteConfig.timeout || 50; | ||
| 第590行: | 第445行: | ||
syntaxStyleTextNode = syntaxStyleElement.appendChild(document.createTextNode("")); | syntaxStyleTextNode = syntaxStyleElement.appendChild(document.createTextNode("")); | ||
var wpTextbox1Style = window.getComputedStyle(wpTextbox1); | var wpTextbox1Style = window.getComputedStyle(wpTextbox1); | ||
var resize = (wpTextbox1Style.resize == "vertical" || wpTextbox1Style.resize == "both" ? "vertical" : "none"); | var resize = (wpTextbox1Style.resize == "vertical" || wpTextbox1Style.resize == "both" ? "vertical" : "none"); | ||
wpTextbox0.dir | wpTextbox0.dir = wpTextbox1.dir; | ||
wpTextbox0.id | wpTextbox0.id = "wpTextbox0"; | ||
wpTextbox0.lang | wpTextbox0.lang = wpTextbox1.lang; | ||
wpTextbox0.style.backgroundColor | wpTextbox0.style.backgroundColor = syntaxHighlighterConfig.backgroundColor; | ||
wpTextbox0.style.boxSizing | wpTextbox0.style.boxSizing = "border-box"; | ||
wpTextbox0.style.clear | wpTextbox0.style.clear = wpTextbox1Style.clear; | ||
wpTextbox0.style.color | wpTextbox0.style.color = "transparent"; | ||
wpTextbox0.style.fontFamily | wpTextbox0.style.fontFamily = wpTextbox1Style.fontFamily; | ||
wpTextbox0.style.fontSize | wpTextbox0.style.fontSize = wpTextbox1Style.fontSize; | ||
wpTextbox0.style.lineHeight | wpTextbox0.style.lineHeight = "normal"; | ||
wpTextbox0.style.marginBottom | wpTextbox0.style.marginBottom = "0"; | ||
wpTextbox0.style.marginLeft | wpTextbox0.style.marginLeft = "0"; | ||
wpTextbox0.style.marginRight | wpTextbox0.style.marginRight = "0"; | ||
wpTextbox0.style.marginTop | wpTextbox0.style.marginTop = "0"; | ||
wpTextbox0.style.overflowX | wpTextbox0.style.overflowX = "auto"; | ||
wpTextbox0.style.overflowY | wpTextbox0.style.overflowY = "scroll"; | ||
wpTextbox0.style.resize | wpTextbox0.style.resize = resize; | ||
wpTextbox0.style.tabSize | wpTextbox0.style.tabSize = wpTextbox1Style.tabSize; | ||
wpTextbox0.style.whiteSpace | wpTextbox0.style.whiteSpace = "pre-wrap"; | ||
wpTextbox0.style.width | wpTextbox0.style.width = "100%"; | ||
wpTextbox0.style.wordWrap | wpTextbox0.style.wordWrap = "normal"; | ||
wpTextbox1.style.backgroundColor | wpTextbox1.style.backgroundColor = "transparent"; | ||
wpTextbox1.style.boxSizing | wpTextbox1.style.boxSizing = "border-box"; | ||
wpTextbox1.style.color = syntaxHighlighterConfig.foregroundColor; | |||
wpTextbox1.style.color | wpTextbox1.style.fontSize = wpTextbox1Style.fontSize; | ||
wpTextbox1.style.lineHeight = "normal"; | |||
wpTextbox1.style.fontSize | wpTextbox1.style.marginBottom = wpTextbox1Style.marginBottom; | ||
wpTextbox1.style.lineHeight | wpTextbox1.style.marginLeft = "0"; | ||
wpTextbox1.style.marginBottom | wpTextbox1.style.marginRight = "0"; | ||
wpTextbox1.style.marginLeft | wpTextbox1.style.overflowX = "auto"; | ||
wpTextbox1.style.marginRight | wpTextbox1.style.overflowY = "scroll"; | ||
wpTextbox1.style.overflowX | wpTextbox1.style.padding = "0"; | ||
wpTextbox1.style.overflowY | wpTextbox1.style.resize = resize; | ||
wpTextbox1.style.padding | wpTextbox1.style.width = "100%"; | ||
wpTextbox1.style.resize | wpTextbox1.style.wordWrap = "normal"; | ||
wpTextbox1.style.width | |||
wpTextbox1.style.wordWrap | |||
wpTextbox1.style.height = wpTextbox0.style.height = wpTextbox1.offsetHeight + "px"; | wpTextbox1.style.height = wpTextbox0.style.height = wpTextbox1.offsetHeight + "px"; | ||
wpTextbox1.style.marginTop = -wpTextbox1.offsetHeight + "px"; | |||
wpTextbox1.style.marginTop | |||
wpTextbox1.parentNode.insertBefore(wpTextbox0, wpTextbox1); | wpTextbox1.parentNode.insertBefore(wpTextbox0, wpTextbox1); | ||
| 第657行: | 第503行: | ||
} | } | ||
var wgAction = mw.config.get("wgAction"); | var wgAction = mw.config.get("wgAction"); | ||
var layoutEngine = $.client.profile().layout; | var layoutEngine = $.client.profile().layout; | ||
if ((wgAction == "edit" || wgAction == "submit") && mw.config.get("wgPageContentModel") == "wikitext" && layoutEngine != "trident" && layoutEngine != "edge") | if ((wgAction == "edit" || wgAction == "submit") && mw.config.get("wgPageContentModel") == "wikitext" && layoutEngine != "trident" && layoutEngine != "edge") | ||
{ | { | ||
if (document.readyState == "complete") | if (document.readyState == "complete") | ||
{ | { | ||
2020年6月21日 (日) 15:37的版本
/* Based on https://www.mediawiki.org/wiki/User:Remember_the_dot/Syntax_highlighter.js */
/* https://www.mediawiki.org/wiki/User:NicoV/Syntax_highlighter.js */
/* This file may be used under the terms of any of the following
licenses, as well as any later version of the same licenses:
GNU General Public License 2.0
<https://www.gnu.org/licenses/old-licenses/gpl-2.0.html>
Creative Commons Attribution-ShareAlike 3.0 Unported License
<https://creativecommons.org/licenses/by-sa/3.0/>
GNU Free Documentation License 1.2
<https://www.gnu.org/licenses/old-licenses/fdl-1.2.html>
*/
mw.loader.using("jquery.client", function() {
"use strict";
var wpTextbox0;
var wpTextbox1;
var syntaxStyleTextNode;
var lastText;
var maxSpanNumber = -1;
var highlightSyntaxIfNeededIntervalID;
var attributeObserver;
var parentObserver;
var wgUrlProtocols = mw.config.get("wgUrlProtocols");
var entityRegexBase = "&(?:(?:n(?:bsp|dash)|m(?:dash|inus)|lt|e[mn]sp|thinsp|amp|quot|gt|shy|zwn?j|lrm|rlm|Alpha|Beta|Epsilon|Zeta|Eta|Iota|Kappa|[Mm]u|micro|Nu|[Oo]micron|[Rr]ho|Tau|Upsilon|Chi)|#x[0-9a-fA-F]+);\n*";
var breakerRegexBase = "\\[(?:\\[|(?:" + wgUrlProtocols + "))|\\{(?:\\{\\{?|\\|)|<(?:[:A-Z_a-z\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u02FF\u0370-\u037D\u037F-\u1FFF\u200C\u200D\u2070-\u218F\u2C00-\u2FEF\u3001-\uD7FF\uF900-\uFDCF\uFDF0-\uFFFD][:\\w\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u02FF\u0370-\u037D\u037F-\u1FFF\u200C\u200D\u2070-\u218F\u2C00-\u2FEF\u3001-\uD7FF\uF900-\uFDCF\uFDF0-\uFFFD-\\.\u00B7\u0300-\u036F\u203F-\u203F-\u2040]*(?=/?>| |\n)|!--[^]*?-->\n*)|(?:" + wgUrlProtocols.replace("|\\/\\/", "") + ")[^\\s\"<>[\\]{-}]*[^\\s\",\\.:;<>[\\]{-}]\n*|^(?:=|[*#:;]+\n*|-{4,}\n*)|\\\\'\\\\'(?:\\\\')?|~{3,5}\n*|" + entityRegexBase;
function breakerRegexWithPrefix(prefix)
{
return new RegExp("(" + prefix + ")\n*|" + breakerRegexBase, "gm");
}
function nowikiTagBreakerRegex(tagName)
{
return new RegExp("(</" + tagName + ">)\n*|" + entityRegexBase, "gm");
}
var defaultBreakerRegex = new RegExp(breakerRegexBase, "gm");
var wikilinkBreakerRegex = breakerRegexWithPrefix("]][a-zA-Z]*");
var namedExternalLinkBreakerRegex = breakerRegexWithPrefix("]");
var parameterBreakerRegex = breakerRegexWithPrefix("}}}");
var templateBreakerRegex = breakerRegexWithPrefix("}}");
var tableBreakerRegex = breakerRegexWithPrefix("\\|}");
var headingBreakerRegex = breakerRegexWithPrefix("\n");
var tagBreakerRegexCache = {};
var nowikiTagBreakerRegexCache = {};
function highlightSyntax()
{
lastText = wpTextbox1.value;
var text = lastText.replace(/['\\]/g, "\\$&") + "\n";
var i = 0;
var css = "";
var spanNumber = 0;
var lastColor;
var before = true;
function writeText(text, color)
{
if (color != lastColor)
{
css += "'}#s" + spanNumber;
if (before)
{
css += ":before{";
before = false;
}
else
{
css += ":after{";
before = true;
++spanNumber;
}
if (color)
{
css += "background-color:" + color + ";";
}
css += "content:'";
lastColor = color;
}
css += text;
}
function highlightBlock(color, breakerRegex, assumedBold, assumedItalic)
{
var match;
for (breakerRegex.lastIndex = i; match = breakerRegex.exec(text); breakerRegex.lastIndex = i)
{
if (match[1])
{
writeText(text.substring(i, breakerRegex.lastIndex), color);
i = breakerRegex.lastIndex;
return;
}
var endIndexOfLastColor = breakerRegex.lastIndex - match[0].length;
if (i < endIndexOfLastColor)
{
writeText(text.substring(i, endIndexOfLastColor), color);
}
i = breakerRegex.lastIndex;
switch (match[0].charAt(0))
{
case "[":
if (match[0].charAt(1) == "[")
{
writeText("[[", syntaxHighlighterConfig.wikilinkColor || color);
highlightBlock(syntaxHighlighterConfig.wikilinkColor || color, wikilinkBreakerRegex);
}
else
{
writeText(match[0], syntaxHighlighterConfig.externalLinkColor || color);
highlightBlock(syntaxHighlighterConfig.externalLinkColor || color, namedExternalLinkBreakerRegex);
}
break;
case "{":
if (match[0].charAt(1) == "{")
{
if (match[0].length == 3)
{
writeText("{{{", syntaxHighlighterConfig.parameterColor || color);
highlightBlock(syntaxHighlighterConfig.parameterColor || color, parameterBreakerRegex);
}
else
{
writeText("{{", syntaxHighlighterConfig.templateColor || color);
highlightBlock(syntaxHighlighterConfig.templateColor || color, templateBreakerRegex);
}
}
else
{
writeText("{|", syntaxHighlighterConfig.tableColor || color);
highlightBlock(syntaxHighlighterConfig.tableColor || color, tableBreakerRegex);
}
break;
case "<":
if (match[0].charAt(1) == "!")
{
writeText(match[0], syntaxHighlighterConfig.commentColor || color);
break;
}
else
{
var tagEnd = text.indexOf(">", i) + 1;
if (tagEnd == 0)
{
writeText("<", color);
i = i - match[0].length + 1;
break;
}
if (text.charAt(tagEnd - 2) == "/" || syntaxHighlighterConfig.voidTags.indexOf(match[0].substring(1)) != -1)
{
writeText(text.substring(i - match[0].length, tagEnd), syntaxHighlighterConfig.tagColor || color);
i = tagEnd;
}
else
{
var tagName = match[0].substring(1);
if (syntaxHighlighterConfig.sourceTags.indexOf(tagName) != -1)
{
var stopAfter = "</" + tagName + ">";
var endIndex = text.indexOf(stopAfter, i);
if (endIndex == -1)
{
endIndex = text.length;
}
else
{
endIndex += stopAfter.length;
}
writeText(text.substring(i - match[0].length, endIndex), syntaxHighlighterConfig.tagColor || color);
i = endIndex;
}
else if (syntaxHighlighterConfig.nowikiTags.indexOf(tagName) != -1)
{
writeText(text.substring(i - match[0].length, tagEnd), syntaxHighlighterConfig.tagColor || color);
i = tagEnd;
highlightBlock(syntaxHighlighterConfig.tagColor || color, nowikiTagBreakerRegexCache[tagName]);
}
else
{
writeText(text.substring(i - match[0].length, tagEnd), syntaxHighlighterConfig.tagColor || color);
i = tagEnd;
if (!tagBreakerRegexCache[tagName])
{
tagBreakerRegexCache[tagName] = breakerRegexWithPrefix("</" + tagName + ">");
}
highlightBlock(syntaxHighlighterConfig.tagColor || color, tagBreakerRegexCache[tagName]);
}
}
}
break;
case "=":
if (/[^=]=+$/.test(text.substring(i, text.indexOf("\n", i))))
{
writeText("=", syntaxHighlighterConfig.headingColor || color);
highlightBlock(syntaxHighlighterConfig.headingColor || color, headingBreakerRegex);
}
else
{
writeText("=", color);
}
break;
case "*":
case "#":
case ":":
writeText(match[0], syntaxHighlighterConfig.listOrIndentColor || color);
break;
case ";":
writeText(";", syntaxHighlighterConfig.headingColor || color);
highlightBlock(syntaxHighlighterConfig.headingColor || color, headingBreakerRegex);
break;
case "-":
writeText(match[0], syntaxHighlighterConfig.hrColor || color);
break;
case "\\":
writeText(match[0], syntaxHighlighterConfig.boldOrItalicColor || color);
if (match[0].length == 6)
{
if (assumedBold)
{
if (assumedItalic)
{
assumedBold = false;
}
else
{
return;
}
}
else
{
if (assumedItalic)
{
assumedBold = true;
}
else
{
highlightBlock(syntaxHighlighterConfig.boldOrItalicColor || color, defaultBreakerRegex, true, false);
}
}
}
else
{
if (assumedItalic)
{
if (assumedBold)
{
assumedItalic = false;
}
else
{
return;
}
}
else
{
if (assumedBold)
{
assumedItalic = true;
}
else
{
highlightBlock(syntaxHighlighterConfig.boldOrItalicColor || color, defaultBreakerRegex, false, true);
}
}
}
break;
case "&":
writeText(match[0], syntaxHighlighterConfig.entityColor || color);
break;
case "~":
writeText(match[0], syntaxHighlighterConfig.signatureColor || color);
break;
default:
writeText(match[0], syntaxHighlighterConfig.externalLinkColor || color);
}
}
}
var startTime = Date.now();
highlightBlock("", defaultBreakerRegex);
if (i < text.length)
{
writeText(text.substring(i), "");
}
var endTime = Date.now();
if (endTime - startTime > syntaxHighlighterConfig.timeout)
{
clearInterval(highlightSyntaxIfNeededIntervalID);
wpTextbox1.removeEventListener("input", highlightSyntax);
wpTextbox1.removeEventListener("scroll", syncScrollX);
wpTextbox1.removeEventListener("scroll", syncScrollY);
attributeObserver.disconnect();
parentObserver.disconnect();
syntaxStyleTextNode.nodeValue = "";
var errorMessage = {
zh: "由于渲染耗时过长, Syntax highlighting 已在本页禁用。在设定中渲染时间被限制在$1毫秒以内,但这次我们耗去了$2毫秒。您可以尝试关闭一些标签页和程序,并点击“显示预览”或“显示更改”。如果这不起作用,请尝试更换一个不同的浏览器。如果这还不起作用,请尝试更换一个更快的电脑=w=。",
en: "Syntax highlighting on this page was disabled because it took too long. The maximum allowed highlighting time is $1ms, and your computer took $2ms. Try closing some tabs and programs and clicking \"Show preview\" or \"Show changes\". If that doesn't work, try a different web browser, and if that doesn't work, try a faster computer.",
};
var wgUserLanguage = mw.config.get("wgUserLanguage");
errorMessage = errorMessage[wgUserLanguage] || errorMessage[wgUserLanguage.substring(0, wgUserLanguage.indexOf("-"))] || errorMessage.en;
wpTextbox1.style.backgroundColor = "";
wpTextbox1.style.marginTop = "0";
wpTextbox0.removeAttribute("dir");
wpTextbox0.removeAttribute("lang");
wpTextbox0.setAttribute("style", "color:red; font-size:small");
wpTextbox0.textContent = errorMessage.replace("$1", syntaxHighlighterConfig.timeout).replace("$2", endTime - startTime);
return;
}
if (maxSpanNumber < spanNumber)
{
var fragment = document.createDocumentFragment();
do
{
fragment.appendChild(document.createElement("span")).id = "s" + ++maxSpanNumber;
}
while (maxSpanNumber < spanNumber);
wpTextbox0.appendChild(fragment);
}
syntaxStyleTextNode.nodeValue = css.substring(2).replace(/\n/g, "\\A ") + "'}";
}
function syncScrollX()
{
wpTextbox0.scrollLeft = wpTextbox1.scrollLeft;
}
function syncScrollY()
{
wpTextbox0.scrollTop = wpTextbox1.scrollTop;
}
function syncTextDirection()
{
wpTextbox0.dir = wpTextbox1.dir;
}
function syncParent()
{
if (wpTextbox1.previousSibling != wpTextbox0)
{
wpTextbox1.parentNode.insertBefore(wpTextbox0, wpTextbox1);
parentObserver.disconnect();
parentObserver.observe(wpTextbox1.parentNode, {childList: true});
}
}
function highlightSyntaxIfNeeded()
{
if (wpTextbox1.value != lastText)
{
highlightSyntax();
}
if (wpTextbox1.scrollLeft != wpTextbox0.scrollLeft)
{
syncScrollX();
}
if (wpTextbox1.scrollTop != wpTextbox0.scrollTop)
{
syncScrollY();
}
if (wpTextbox1.offsetHeight != wpTextbox0.offsetHeight)
{
var height = wpTextbox1.offsetHeight + "px";
wpTextbox0.style.height = height;
wpTextbox1.style.marginTop = "-" + height;
}
}
function setup()
{
function configureColor(parameterName, hardcodedFallback, defaultOk)
{
if (typeof(syntaxHighlighterConfig[parameterName]) == "undefined")
{
syntaxHighlighterConfig[parameterName] = syntaxHighlighterSiteConfig[parameterName];
}
if (syntaxHighlighterConfig[parameterName] == "normal")
{
syntaxHighlighterConfig[parameterName] = hardcodedFallback;
}
else if (typeof(syntaxHighlighterConfig[parameterName]) != "undefined")
{
return;
}
else if (typeof(syntaxHighlighterConfig.defaultColor) != "undefined" && defaultOk)
{
syntaxHighlighterConfig[parameterName] = syntaxHighlighterConfig.defaultColor;
}
else
{
syntaxHighlighterConfig[parameterName] = hardcodedFallback;
}
}
window.syntaxHighlighterSiteConfig = window.syntaxHighlighterSiteConfig || {};
window.syntaxHighlighterConfig = window.syntaxHighlighterConfig || {};
configureColor("backgroundColor", "#FFF", false);
configureColor("foregroundColor", "#000", false);
configureColor("boldOrItalicColor", "#EEE", true);
configureColor("commentColor", "#EFE", true);
configureColor("entityColor", "#DFD", true);
configureColor("externalLinkColor", "#EFF", true);
configureColor("headingColor", "#EEE", true);
configureColor("hrColor", "#EEE", true);
configureColor("listOrIndentColor", "#EFE", true);
configureColor("parameterColor", "#FC6", true);
configureColor("signatureColor", "#FC6", true);
configureColor("tagColor", "#FEF", true);
configureColor("tableColor", "#FFC", true);
configureColor("templateColor", "#FFC", true);
configureColor("wikilinkColor", "#EEF", true);
syntaxHighlighterConfig.nowikiTags = syntaxHighlighterConfig.nowikiTags || syntaxHighlighterSiteConfig.nowikiTags || ["nowiki", "pre"];
syntaxHighlighterConfig.sourceTags = syntaxHighlighterConfig.sourceTags || syntaxHighlighterSiteConfig.sourceTags || ["math", "syntaxhighlight", "source", "timeline", "hiero", "score"];
syntaxHighlighterConfig.voidTags = syntaxHighlighterConfig.voidTags || syntaxHighlighterSiteConfig.voidTags || ["br", "hr"];
syntaxHighlighterConfig.timeout = syntaxHighlighterConfig.timeout || syntaxHighlighterSiteConfig.timeout || 50;
syntaxHighlighterConfig.nowikiTags.forEach(function(tagName) {
nowikiTagBreakerRegexCache[tagName] = nowikiTagBreakerRegex(tagName);
});
wpTextbox0 = document.createElement("div");
wpTextbox1 = document.getElementById("wpTextbox1");
var syntaxStyleElement = document.createElement("style");
syntaxStyleTextNode = syntaxStyleElement.appendChild(document.createTextNode(""));
var wpTextbox1Style = window.getComputedStyle(wpTextbox1);
var resize = (wpTextbox1Style.resize == "vertical" || wpTextbox1Style.resize == "both" ? "vertical" : "none");
wpTextbox0.dir = wpTextbox1.dir;
wpTextbox0.id = "wpTextbox0";
wpTextbox0.lang = wpTextbox1.lang;
wpTextbox0.style.backgroundColor = syntaxHighlighterConfig.backgroundColor;
wpTextbox0.style.boxSizing = "border-box";
wpTextbox0.style.clear = wpTextbox1Style.clear;
wpTextbox0.style.color = "transparent";
wpTextbox0.style.fontFamily = wpTextbox1Style.fontFamily;
wpTextbox0.style.fontSize = wpTextbox1Style.fontSize;
wpTextbox0.style.lineHeight = "normal";
wpTextbox0.style.marginBottom = "0";
wpTextbox0.style.marginLeft = "0";
wpTextbox0.style.marginRight = "0";
wpTextbox0.style.marginTop = "0";
wpTextbox0.style.overflowX = "auto";
wpTextbox0.style.overflowY = "scroll";
wpTextbox0.style.resize = resize;
wpTextbox0.style.tabSize = wpTextbox1Style.tabSize;
wpTextbox0.style.whiteSpace = "pre-wrap";
wpTextbox0.style.width = "100%";
wpTextbox0.style.wordWrap = "normal";
wpTextbox1.style.backgroundColor = "transparent";
wpTextbox1.style.boxSizing = "border-box";
wpTextbox1.style.color = syntaxHighlighterConfig.foregroundColor;
wpTextbox1.style.fontSize = wpTextbox1Style.fontSize;
wpTextbox1.style.lineHeight = "normal";
wpTextbox1.style.marginBottom = wpTextbox1Style.marginBottom;
wpTextbox1.style.marginLeft = "0";
wpTextbox1.style.marginRight = "0";
wpTextbox1.style.overflowX = "auto";
wpTextbox1.style.overflowY = "scroll";
wpTextbox1.style.padding = "0";
wpTextbox1.style.resize = resize;
wpTextbox1.style.width = "100%";
wpTextbox1.style.wordWrap = "normal";
wpTextbox1.style.height = wpTextbox0.style.height = wpTextbox1.offsetHeight + "px";
wpTextbox1.style.marginTop = -wpTextbox1.offsetHeight + "px";
wpTextbox1.parentNode.insertBefore(wpTextbox0, wpTextbox1);
document.head.appendChild(syntaxStyleElement);
wpTextbox1.addEventListener("input", highlightSyntax);
wpTextbox1.addEventListener("scroll", syncScrollX);
wpTextbox1.addEventListener("scroll", syncScrollY);
attributeObserver = new MutationObserver(syncTextDirection);
attributeObserver.observe(wpTextbox1, {attributes: true});
parentObserver = new MutationObserver(syncParent);
parentObserver.observe(wpTextbox1.parentNode, {childList: true});
highlightSyntaxIfNeededIntervalID = setInterval(highlightSyntaxIfNeeded, 500);
highlightSyntax();
}
var wgAction = mw.config.get("wgAction");
var layoutEngine = $.client.profile().layout;
if ((wgAction == "edit" || wgAction == "submit") && mw.config.get("wgPageContentModel") == "wikitext" && layoutEngine != "trident" && layoutEngine != "edge")
{
if (document.readyState == "complete")
{
setup();
}
else
{
window.addEventListener("load", setup);
}
}
});