// ==UserScript== | |
// @name Highlightify | |
// @namespace https://github.com/lionel-rowe/ | |
// @version 0.4 | |
// @description Highlightify Stack Exchange | |
// @author @lionel-rowe | |
// @match https://meta.stackexchange.com/* | |
// @grant none | |
// ==/UserScript== | |
/* global StackExchange */ | |
{ // containing block - prevent global pollution | |
const makeUrl = lang => `https://cdnjs.cloudflare.com/ajax/libs/highlight.js/10.2.0/languages/${lang}.min.js` | |
// scraped from https://github.com/highlightjs/highlight.js/blob/913f0e55435d56daf5bfbb6888ac9c371ec31cdc/SUPPORTED_LANGUAGES.md using | |
// [...document.querySelector('tbody') | |
// .querySelectorAll('tr')] | |
// .filter(el => ![...el.querySelectorAll('td')][2].textContent.trim()) | |
// .map(el => [...el.querySelectorAll('td')].slice(0, 2).map(el => el.textContent)) | |
// .reduce((langs, [lang, classes]) => { | |
// const aliases = classes.trim().split(/[ ,]+/) | |
// aliases.forEach(alias => langs[alias] = aliases[0]) | |
// return langs | |
// }, {}) | |
const aliases = new Map(Object.entries({'1c':'1c',abnf:'abnf',accesslog:'accesslog',ada:'ada',arduino:'arduino',ino:'arduino',armasm:'armasm',arm:'armasm',avrasm:'avrasm',actionscript:'actionscript',as:'actionscript',angelscript:'angelscript',asc:'angelscript',apache:'apache',apacheconf:'apache',applescript:'applescript',osascript:'applescript',arcade:'arcade',asciidoc:'asciidoc',adoc:'asciidoc',aspectj:'aspectj',autohotkey:'autohotkey',autoit:'autoit',awk:'awk',mawk:'awk',nawk:'awk',gawk:'awk',bash:'bash',sh:'bash',zsh:'bash',basic:'basic',bnf:'bnf',brainfuck:'brainfuck',bf:'brainfuck',csharp:'csharp',cs:'csharp',c:'c',h:'c',cpp:'cpp',hpp:'cpp',cc:'cpp',hh:'cpp','c++':'cpp','h++':'cpp',cxx:'cpp',hxx:'cpp',cal:'cal',cos:'cos',cls:'cos',cmake:'cmake','cmake.in':'cmake',coq:'coq',csp:'csp',css:'css',capnproto:'capnproto',capnp:'capnproto',clojure:'clojure',clj:'clojure',coffeescript:'coffeescript',coffee:'coffeescript',cson:'coffeescript',iced:'coffeescript',crmsh:'crmsh',crm:'crmsh',pcmk:'crmsh',crystal:'crystal',cr:'crystal',d:'d',dns:'dns',zone:'dns',bind:'dns',dos:'dos',bat:'dos',cmd:'dos',dart:'dart',delphi:'delphi',dpr:'delphi',dfm:'delphi',pas:'delphi',pascal:'delphi',freepascal:'delphi',lazarus:'delphi',lpr:'delphi',lfm:'delphi',diff:'diff',patch:'diff',django:'django',jinja:'django',dockerfile:'dockerfile',docker:'dockerfile',dsconfig:'dsconfig',dts:'dts',dust:'dust',dst:'dust',ebnf:'ebnf',elixir:'elixir',elm:'elm',erlang:'erlang',erl:'erlang',excel:'excel',xls:'excel',xlsx:'excel',fsharp:'fsharp',fs:'fsharp',fix:'fix',fortran:'fortran',f90:'fortran',f95:'fortran',gcode:'gcode',nc:'gcode',gams:'gams',gms:'gams',gauss:'gauss',gss:'gauss',gherkin:'gherkin',go:'go',golang:'go',golo:'golo',gololang:'golo',gradle:'gradle',groovy:'groovy',xml:'xml',html:'xml',xhtml:'xml',rss:'xml',atom:'xml',xjb:'xml',xsd:'xml',xsl:'xml',plist:'xml',svg:'xml',http:'http',https:'http',haml:'haml',handlebars:'handlebars',hbs:'handlebars','html.hbs':'handlebars','html.handlebars':'handlebars',haskell:'haskell',hs:'haskell',haxe:'haxe',hx:'haxe',hy:'hy',hylang:'hy',ini:'ini',toml:'ini',inform7:'inform7',i7:'inform7',irpf90:'irpf90',json:'json',java:'java',jsp:'java',javascript:'javascript',js:'javascript',jsx:'javascript',kotlin:'kotlin',kt:'kotlin',tex:'tex',leaf:'leaf',lasso:'lasso',ls:'livescript',lassoscript:'lasso',less:'less',ldif:'ldif',lisp:'lisp',livecodeserver:'livecodeserver',livescript:'livescript',lua:'lua',makefile:'makefile',mk:'makefile',mak:'makefile',markdown:'markdown',md:'markdown',mkdown:'markdown',mkd:'markdown',mathematica:'mathematica',mma:'mathematica',wl:'mathematica',matlab:'matlab',maxima:'maxima',mel:'mel',mercury:'mercury',mizar:'mizar',mojolicious:'mojolicious',monkey:'monkey',moonscript:'moonscript',moon:'moonscript',n1ql:'n1ql',nsis:'nsis',nginx:'nginx',nginxconf:'nginx',nimrod:'nimrod',nix:'nix',ocaml:'ocaml',ml:'sml',objectivec:'objectivec',mm:'objectivec',objc:'objectivec','obj-c':'objectivec','obj-c++':'objectivec','objective-c++':'objectivec',glsl:'glsl',openscad:'openscad',scad:'openscad',ruleslanguage:'ruleslanguage',oxygene:'oxygene',pf:'pf','pf.conf':'pf',php:'php',php3:'php',php4:'php',php5:'php',php6:'php',php7:'php',parser3:'parser3',perl:'perl',pl:'perl',pm:'perl',plaintext:'plaintext',txt:'plaintext',text:'plaintext',pony:'pony',pgsql:'pgsql',postgres:'pgsql',postgresql:'pgsql',powershell:'powershell',ps:'powershell',ps1:'powershell',processing:'processing',prolog:'prolog',properties:'properties',protobuf:'protobuf',puppet:'puppet',pp:'puppet',python:'python',py:'python',gyp:'python',profile:'profile','python-repl':'python-repl',pycon:'python-repl',k:'k',kdb:'k',qml:'qml',r:'r',reasonml:'reasonml',re:'reasonml',rib:'rib',rsl:'rsl',graph:'graph',instances:'graph',ruby:'ruby',rb:'ruby',gemspec:'ruby',podspec:'ruby',thor:'ruby',irb:'ruby',rust:'rust',rs:'rust',SAS:'SAS',sas:'SAS',scss:'scss',sql:'sql',p21:'p21',step:'p21',stp:'p21',scala:'scala',scheme:'scheme',scilab:'scilab',sci:'scilab',shell:'shell',console:'shell',smali:'smali',smalltalk:'smalltalk',st:'smalltalk',sml:'sml',stan:'stan',stanfuncs:'stan',stata:'stata',stylus:'stylus',styl:'stylus',subunit:'subunit',swift:'swift',tcl:'tcl',tk:'tcl',tap:'tap',thrift:'thrift',tp:'tp',twig:'twig',craftcms:'twig',typescript:'typescript',ts:'typescript',vbnet:'vbnet',vb:'vbnet',vbscript:'vbscript',vbs:'vbscript',vhdl:'vhdl',vala:'vala',verilog:'verilog',v:'verilog',vim:'vim',axapta:'axapta','x++':'axapta',x86asm:'x86asm',xl:'xl',tao:'xl',xquery:'xquery',xpath:'xquery',xq:'xquery',yml:'yml',yaml:'yml',zephir:'zephir',zep:'zephir'})) | |
aliases.set('none', 'plaintext') | |
const highlightify = () => { | |
const langData = [...document.querySelectorAll('pre[class*=lang-]')] | |
.reduce((data, el) => { | |
const alias = [...el.classList].find(c => c.startsWith('lang-')).slice(5) | |
const canonicalName = aliases.get(alias) | |
if (canonicalName) { | |
data[canonicalName] = [...(data[canonicalName] || []), el] | |
} | |
return data | |
}, {}) | |
Object.entries(langData).forEach(async ([lang, els]) => { | |
if (StackExchange.highlightjs.instance.getLanguage(lang)) return | |
const res = await fetch(makeUrl(lang)) | |
const src = await res.text() | |
/* eslint-disable-next-line no-new-func */ | |
new Function('hljs', src)(StackExchange.highlightjs.instance) | |
els.forEach(el => { | |
el.classList.add('hljs') | |
const code = el.querySelector('code') | |
code.innerHTML = StackExchange.highlightjs.instance.highlight(lang, code.textContent).value | |
}) | |
}) | |
} | |
const root = document.head | |
const selector = 'script[src*="highlightjs"]' | |
const callback = (mutations, observer) => { | |
for (const mutation of mutations) { | |
const node = mutation.addedNodes[0] | |
if (!node) continue | |
if (node.nodeType === Node.ELEMENT_NODE && node.matches(selector)) { | |
node.addEventListener('load', highlightify) | |
observer.disconnect() | |
return | |
} | |
} | |
} | |
const el = root.querySelector(selector) | |
if (el && window.StackExchange && StackExchange.highlightjs && StackExchange.highlightjs.instance) { | |
highlightify() | |
} else if (el) { | |
el.addEventListener('load', highlightify) | |
} else { | |
new MutationObserver(callback).observe(root, { childList: true }) | |
} | |
} // end containing block |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment