Go.dev Golang Website Code Highlight

Golang code highlighter

目前为 2023-12-22 提交的版本。查看 最新版本

  1. // ==UserScript==
  2. // @name Go.dev Golang Website Code Highlight
  3. // @version 1.1.7
  4. // @description Golang code highlighter
  5. // @author Anton Vi
  6. // @match https://*.go.dev/*
  7.  
  8. // @resource IMPORTED_CSS https://cdnjs.cloudflare.com/ajax/libs/prism/1.29.0/themes/prism-tomorrow.min.css
  9.  
  10. // @grant GM_getResourceText
  11. // @grant GM_addStyle
  12. // @license GNU GPLv3
  13.  
  14. // @exclude https://go.dev/tour/*
  15. // @exclude https://go.dev/solutions/*
  16. // @exclude https://go.dev/security/*
  17. // @namespace GolangDevNamespace
  18. // ==/UserScript==
  19.  
  20. (function() {
  21.  
  22. 'use strict';
  23.  
  24. document.addEventListener('readystatechange', (e) => {
  25. if (e.target.readyState === 'complete') {
  26. resetBlogCss();
  27. start();
  28. }
  29. })
  30.  
  31.  
  32. })();
  33.  
  34. function resetBlogCss() {
  35. // reset styles for go dev blog
  36. let css = `#blog pre, #content .code, #content .playground {
  37. background: black;
  38. font-family: Consolas,Monaco,'Andale Mono','Ubuntu Mono',monospace;
  39. font-size: 1rem;
  40. }`;
  41. GM_addStyle(css);
  42.  
  43. }
  44.  
  45. function start() {
  46. // create Prisma object
  47. window.Prism = window.Prism || {};
  48. // no highlight on auto
  49. Prism.manual = true;
  50.  
  51. // add highlight styles css
  52. const my_css = GM_getResourceText("IMPORTED_CSS");
  53. GM_addStyle(my_css);
  54.  
  55.  
  56. // loop pre-s and add code child elements for highlight
  57. let pre_s = document.getElementsByTagName('pre');
  58. for (let el of pre_s) {
  59. // skip pre element for ==Output== code run in documentation
  60. if (el.getElementsByClassName('Documentation-exampleOutputLabel').length > 0) {
  61. continue;
  62. }
  63.  
  64. el.className = 'language-go';
  65.  
  66.  
  67. if (!el.getElementsByTagName('code').length > 0) {
  68. let text = el.innerHTML;
  69. el.innerHTML = '';
  70.  
  71. let code = document.createElement('code');
  72. code.innerHTML = text;
  73. code.className = 'language-go';
  74. el.appendChild(code);
  75. }
  76.  
  77. }
  78.  
  79.  
  80. // get examples in go library doc
  81. let divS = document.getElementsByClassName('Documentation-exampleDetailsBody');
  82. for (divEl of divS) {
  83. let outputPre = divEl.getElementsByTagName('pre')[0];
  84. outputPre.className = 'language-go';
  85.  
  86.  
  87. let textareaBlock = divEl.querySelector('textarea.Documentation-exampleCode.code');
  88. textareaBlock.style.display = 'none';
  89. // textareaBlock.remove();
  90. divEl.insertAdjacentHTML('afterbegin', '<pre class="language-go"><code>' + textareaBlock.value + '</code></pre>');
  91.  
  92.  
  93. }
  94.  
  95.  
  96. // start prism
  97. initPrismCore();
  98.  
  99. // add languages syntax
  100. addClikeSyntax();
  101. addGoSyntax();
  102.  
  103.  
  104. // start highlight syntax
  105. Prism.highlightAll();
  106.  
  107. }
  108.  
  109. function initPrismCore() {
  110. var _self = "undefined" != typeof window ? window : "undefined" != typeof WorkerGlobalScope && self instanceof WorkerGlobalScope ? self : {},
  111. Prism = function(e) {
  112. var n = /(?:^|\s)lang(?:uage)?-([\w-]+)(?=\s|$)/i,
  113. t = 0,
  114. r = {},
  115. a = {
  116. manual: e.Prism && e.Prism.manual,
  117. disableWorkerMessageHandler: e.Prism && e.Prism.disableWorkerMessageHandler,
  118. util: {
  119. encode: function e(n) { return n instanceof i ? new i(n.type, e(n.content), n.alias) : Array.isArray(n) ? n.map(e) : n.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/\u00a0/g, " ") },
  120. type: function(e) { return Object.prototype.toString.call(e).slice(8, -1) },
  121. objId: function(e) { return e.__id || Object.defineProperty(e, "__id", { value: ++t }), e.__id },
  122. clone: function e(n, t) {
  123. var r, i;
  124. switch (t = t || {}, a.util.type(n)) {
  125. case "Object":
  126. if (i = a.util.objId(n), t[i]) return t[i];
  127. for (var l in r = {}, t[i] = r, n) n.hasOwnProperty(l) && (r[l] = e(n[l], t));
  128. return r;
  129. case "Array":
  130. return i = a.util.objId(n), t[i] ? t[i] : (r = [], t[i] = r, n.forEach((function(n, a) { r[a] = e(n, t) })), r);
  131. default:
  132. return n
  133. }
  134. },
  135. getLanguage: function(e) {
  136. for (; e;) {
  137. var t = n.exec(e.className);
  138. if (t) return t[1].toLowerCase();
  139. e = e.parentElement
  140. }
  141. return "none"
  142. },
  143. setLanguage: function(e, t) { e.className = e.className.replace(RegExp(n, "gi"), ""), e.classList.add("language-" + t) },
  144. currentScript: function() {
  145. if ("undefined" == typeof document) return null;
  146. if ("currentScript" in document) return document.currentScript;
  147. try { throw new Error } catch (r) {
  148. var e = (/at [^(\r\n]*\((.*):[^:]+:[^:]+\)$/i.exec(r.stack) || [])[1];
  149. if (e) {
  150. var n = document.getElementsByTagName("script");
  151. for (var t in n)
  152. if (n[t].src == e) return n[t]
  153. }
  154. return null
  155. }
  156. },
  157. isActive: function(e, n, t) {
  158. for (var r = "no-" + n; e;) {
  159. var a = e.classList;
  160. if (a.contains(n)) return !0;
  161. if (a.contains(r)) return !1;
  162. e = e.parentElement
  163. }
  164. return !!t
  165. }
  166. },
  167. languages: {
  168. plain: r,
  169. plaintext: r,
  170. text: r,
  171. txt: r,
  172. extend: function(e, n) { var t = a.util.clone(a.languages[e]); for (var r in n) t[r] = n[r]; return t },
  173. insertBefore: function(e, n, t, r) {
  174. var i = (r = r || a.languages)[e],
  175. l = {};
  176. for (var o in i)
  177. if (i.hasOwnProperty(o)) {
  178. if (o == n)
  179. for (var s in t) t.hasOwnProperty(s) && (l[s] = t[s]);
  180. t.hasOwnProperty(o) || (l[o] = i[o])
  181. } var u = r[e];
  182. return r[e] = l, a.languages.DFS(a.languages, (function(n, t) { t === u && n != e && (this[n] = l) })), l
  183. },
  184. DFS: function e(n, t, r, i) {
  185. i = i || {};
  186. var l = a.util.objId;
  187. for (var o in n)
  188. if (n.hasOwnProperty(o)) {
  189. t.call(n, o, n[o], r || o);
  190. var s = n[o],
  191. u = a.util.type(s);
  192. "Object" !== u || i[l(s)] ? "Array" !== u || i[l(s)] || (i[l(s)] = !0, e(s, t, o, i)) : (i[l(s)] = !0, e(s, t, null, i))
  193. }
  194. }
  195. },
  196. plugins: {},
  197. highlightAll: function(e, n) { a.highlightAllUnder(document, e, n) },
  198. highlightAllUnder: function(e, n, t) {
  199. var r = { callback: t, container: e, selector: 'code[class*="language-"], [class*="language-"] code, code[class*="lang-"], [class*="lang-"] code' };
  200. a.hooks.run("before-highlightall", r), r.elements = Array.prototype.slice.apply(r.container.querySelectorAll(r.selector)), a.hooks.run("before-all-elements-highlight", r);
  201. for (var i, l = 0; i = r.elements[l++];) a.highlightElement(i, !0 === n, r.callback)
  202. },
  203. highlightElement: function(n, t, r) {
  204. var i = a.util.getLanguage(n),
  205. l = a.languages[i];
  206. a.util.setLanguage(n, i);
  207. var o = n.parentElement;
  208. o && "pre" === o.nodeName.toLowerCase() && a.util.setLanguage(o, i);
  209. var s = { element: n, language: i, grammar: l, code: n.textContent };
  210.  
  211. function u(e) { s.highlightedCode = e, a.hooks.run("before-insert", s), s.element.innerHTML = s.highlightedCode, a.hooks.run("after-highlight", s), a.hooks.run("complete", s), r && r.call(s.element) }
  212. if (a.hooks.run("before-sanity-check", s), (o = s.element.parentElement) && "pre" === o.nodeName.toLowerCase() && !o.hasAttribute("tabindex") && o.setAttribute("tabindex", "0"), !s.code) return a.hooks.run("complete", s), void(r && r.call(s.element));
  213. if (a.hooks.run("before-highlight", s), s.grammar)
  214. if (t && e.Worker) {
  215. var c = new Worker(a.filename);
  216. c.onmessage = function(e) { u(e.data) }, c.postMessage(JSON.stringify({ language: s.language, code: s.code, immediateClose: !0 }))
  217. } else u(a.highlight(s.code, s.grammar, s.language));
  218. else u(a.util.encode(s.code))
  219. },
  220. highlight: function(e, n, t) { var r = { code: e, grammar: n, language: t }; if (a.hooks.run("before-tokenize", r), !r.grammar) throw new Error('The language "' + r.language + '" has no grammar.'); return r.tokens = a.tokenize(r.code, r.grammar), a.hooks.run("after-tokenize", r), i.stringify(a.util.encode(r.tokens), r.language) },
  221. tokenize: function(e, n) {
  222. var t = n.rest;
  223. if (t) {
  224. for (var r in t) n[r] = t[r];
  225. delete n.rest
  226. }
  227. var a = new s;
  228. return u(a, a.head, e), o(e, a, n, a.head, 0),
  229. function(e) { for (var n = [], t = e.head.next; t !== e.tail;) n.push(t.value), t = t.next; return n }(a)
  230. },
  231. hooks: {
  232. all: {},
  233. add: function(e, n) {
  234. var t = a.hooks.all;
  235. t[e] = t[e] || [], t[e].push(n)
  236. },
  237. run: function(e, n) {
  238. var t = a.hooks.all[e];
  239. if (t && t.length)
  240. for (var r, i = 0; r = t[i++];) r(n)
  241. }
  242. },
  243. Token: i
  244. };
  245.  
  246. function i(e, n, t, r) { this.type = e, this.content = n, this.alias = t, this.length = 0 | (r || "").length }
  247.  
  248. function l(e, n, t, r) {
  249. e.lastIndex = n;
  250. var a = e.exec(t);
  251. if (a && r && a[1]) {
  252. var i = a[1].length;
  253. a.index += i, a[0] = a[0].slice(i)
  254. }
  255. return a
  256. }
  257.  
  258. function o(e, n, t, r, s, g) {
  259. for (var f in t)
  260. if (t.hasOwnProperty(f) && t[f]) {
  261. var h = t[f];
  262. h = Array.isArray(h) ? h : [h];
  263. for (var d = 0; d < h.length; ++d) {
  264. if (g && g.cause == f + "," + d) return;
  265. var v = h[d],
  266. p = v.inside,
  267. m = !!v.lookbehind,
  268. y = !!v.greedy,
  269. k = v.alias;
  270. if (y && !v.pattern.global) {
  271. var x = v.pattern.toString().match(/[imsuy]*$/)[0];
  272. v.pattern = RegExp(v.pattern.source, x + "g")
  273. }
  274. for (var b = v.pattern || v, w = r.next, A = s; w !== n.tail && !(g && A >= g.reach); A += w.value.length, w = w.next) {
  275. var E = w.value;
  276. if (n.length > e.length) return;
  277. if (!(E instanceof i)) {
  278. var P, L = 1;
  279. if (y) {
  280. if (!(P = l(b, A, e, m)) || P.index >= e.length) break;
  281. var S = P.index,
  282. O = P.index + P[0].length,
  283. j = A;
  284. for (j += w.value.length; S >= j;) j += (w = w.next).value.length;
  285. if (A = j -= w.value.length, w.value instanceof i) continue;
  286. for (var C = w; C !== n.tail && (j < O || "string" == typeof C.value); C = C.next) L++, j += C.value.length;
  287. L--, E = e.slice(A, j), P.index -= A
  288. } else if (!(P = l(b, 0, E, m))) continue;
  289. S = P.index;
  290. var N = P[0],
  291. _ = E.slice(0, S),
  292. M = E.slice(S + N.length),
  293. W = A + E.length;
  294. g && W > g.reach && (g.reach = W);
  295. var z = w.prev;
  296. if (_ && (z = u(n, z, _), A += _.length), c(n, z, L), w = u(n, z, new i(f, p ? a.tokenize(N, p) : N, k, N)), M && u(n, w, M), L > 1) {
  297. var I = { cause: f + "," + d, reach: W };
  298. o(e, n, t, w.prev, A, I), g && I.reach > g.reach && (g.reach = I.reach)
  299. }
  300. }
  301. }
  302. }
  303. }
  304. }
  305.  
  306. function s() {
  307. var e = { value: null, prev: null, next: null },
  308. n = { value: null, prev: e, next: null };
  309. e.next = n, this.head = e, this.tail = n, this.length = 0
  310. }
  311.  
  312. function u(e, n, t) {
  313. var r = n.next,
  314. a = { value: t, prev: n, next: r };
  315. return n.next = a, r.prev = a, e.length++, a
  316. }
  317.  
  318. function c(e, n, t) {
  319. for (var r = n.next, a = 0; a < t && r !== e.tail; a++) r = r.next;
  320. n.next = r, r.prev = n, e.length -= a
  321. }
  322. if (e.Prism = a, i.stringify = function e(n, t) {
  323. if ("string" == typeof n) return n;
  324. if (Array.isArray(n)) { var r = ""; return n.forEach((function(n) { r += e(n, t) })), r }
  325. var i = { type: n.type, content: e(n.content, t), tag: "span", classes: ["token", n.type], attributes: {}, language: t },
  326. l = n.alias;
  327. l && (Array.isArray(l) ? Array.prototype.push.apply(i.classes, l) : i.classes.push(l)), a.hooks.run("wrap", i);
  328. var o = "";
  329. for (var s in i.attributes) o += " " + s + '="' + (i.attributes[s] || "").replace(/"/g, "&quot;") + '"';
  330. return "<" + i.tag + ' class="' + i.classes.join(" ") + '"' + o + ">" + i.content + "</" + i.tag + ">"
  331. }, !e.document) return e.addEventListener ? (a.disableWorkerMessageHandler || e.addEventListener("message", (function(n) {
  332. var t = JSON.parse(n.data),
  333. r = t.language,
  334. i = t.code,
  335. l = t.immediateClose;
  336. e.postMessage(a.highlight(i, a.languages[r], r)), l && e.close()
  337. }), !1), a) : a;
  338. var g = a.util.currentScript();
  339.  
  340. function f() { a.manual || a.highlightAll() }
  341. if (g && (a.filename = g.src, g.hasAttribute("data-manual") && (a.manual = !0)), !a.manual) { var h = document.readyState; "loading" === h || "interactive" === h && g && g.defer ? document.addEventListener("DOMContentLoaded", f) : window.requestAnimationFrame ? window.requestAnimationFrame(f) : window.setTimeout(f, 16) }
  342. return a
  343. }(_self);
  344. "undefined" != typeof module && module.exports && (module.exports = Prism), "undefined" != typeof global && (global.Prism = Prism);
  345. }
  346.  
  347. function addClikeSyntax() {
  348. Prism.languages.clike = {
  349. comment: [{ pattern: /(^|[^\\])\/\*[\s\S]*?(?:\*\/|$)/, lookbehind: !0, greedy: !0 },
  350. { pattern: /(^|[^\\:])\/\/.*/, lookbehind: !0, greedy: !0 }
  351. ],
  352. string: { pattern: /(["'])(?:\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1/, greedy: !0 },
  353. "class-name": { pattern: /(\b(?:class|extends|implements|instanceof|interface|new|trait)\s+|\bcatch\s+\()[\w.\\]+/i, lookbehind: !0, inside: { punctuation: /[.\\]/ } },
  354. keyword: /\b(?:break|catch|continue|do|else|finally|for|function|if|in|instanceof|new|null|return|throw|try|while)\b/,
  355. boolean: /\b(?:false|true)\b/,
  356. function: /\b\w+(?=\()/,
  357. number: /\b0x[\da-f]+\b|(?:\b\d+(?:\.\d*)?|\B\.\d+)(?:e[+-]?\d+)?/i,
  358. operator: /[<>]=?|[!=]=?=?|--?|\+\+?|&&?|\|\|?|[?*/~^%]/,
  359. punctuation: /[{}[\];(),.:]/
  360. };
  361. }
  362.  
  363. function addGoSyntax() {
  364. Prism.languages.go = Prism.languages
  365. .extend("clike", {
  366. string: { pattern: /(^|[^\\])"(?:\\.|[^"\\\r\n])*"|`[^`]*`/, lookbehind: !0, greedy: !0 },
  367. keyword: /\b(?:break|case|chan|const|continue|default|defer|else|fallthrough|for|func|go(?:to)?|if|import|interface|map|package|range|return|select|struct|switch|type|var)\b/,
  368. boolean: /\b(?:_|false|iota|nil|true)\b/,
  369. number: [/\b0(?:b[01_]+|o[0-7_]+)i?\b/i, /\b0x(?:[a-f\d_]+(?:\.[a-f\d_]*)?|\.[a-f\d_]+)(?:p[+-]?\d+(?:_\d+)*)?i?(?!\w)/i, /(?:\b\d[\d_]*(?:\.[\d_]*)?|\B\.\d[\d_]*)(?:e[+-]?[\d_]+)?i?(?!\w)/i],
  370. operator: /[*\/%^!=]=?|\+[=+]?|-[=-]?|\|[=|]?|&(?:=|&|\^=?)?|>(?:>=?|=)?|<(?:<=?|=|-)?|:=|\.\.\./,
  371. builtin: /\b(?:append|bool|byte|cap|close|complex|complex(?:64|128)|copy|delete|error|float(?:32|64)|u?int(?:8|16|32|64)?|imag|len|make|new|panic|print(?:ln)?|real|recover|rune|string|uintptr)\b/
  372. }),
  373. Prism.languages.insertBefore("go", "string", { char: { pattern: /'(?:\\.|[^'\\\r\n]){0,10}'/, greedy: !0 } }), delete Prism.languages.go["class-name"];
  374. }