Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
// ==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