Created
February 10, 2022 05:08
-
-
Save colinwilson/0c436d6b34cf935506b1bdae65d21dfb to your computer and use it in GitHub Desktop.
Custom PrismJS Autoloader
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(function () { | |
if (typeof Prism === 'undefined' || typeof document === 'undefined') { | |
return; | |
} | |
/* eslint-disable */ | |
/** | |
* The dependencies map is built automatically with gulp. | |
* | |
* @type {Object<string, string | string[]>} | |
*/ | |
var lang_dependencies = /*dependencies_placeholder[*/{ | |
"javascript": "clike", | |
"actionscript": "javascript", | |
"apex": [ | |
"clike", | |
"sql" | |
], | |
"arduino": "cpp", | |
"aspnet": [ | |
"markup", | |
"csharp" | |
], | |
"birb": "clike", | |
"bison": "c", | |
"c": "clike", | |
"csharp": "clike", | |
"cpp": "c", | |
"cfscript": "clike", | |
"chaiscript": [ | |
"clike", | |
"cpp" | |
], | |
"coffeescript": "javascript", | |
"crystal": "ruby", | |
"css-extras": "css", | |
"d": "clike", | |
"dart": "clike", | |
"django": "markup-templating", | |
"ejs": [ | |
"javascript", | |
"markup-templating" | |
], | |
"etlua": [ | |
"lua", | |
"markup-templating" | |
], | |
"erb": [ | |
"ruby", | |
"markup-templating" | |
], | |
"fsharp": "clike", | |
"firestore-security-rules": "clike", | |
"flow": "javascript", | |
"ftl": "markup-templating", | |
"gml": "clike", | |
"glsl": "c", | |
"go": "clike", | |
"groovy": "clike", | |
"haml": "ruby", | |
"handlebars": "markup-templating", | |
"haxe": "clike", | |
"hlsl": "c", | |
"idris": "haskell", | |
"java": "clike", | |
"javadoc": [ | |
"markup", | |
"java", | |
"javadoclike" | |
], | |
"jolie": "clike", | |
"jsdoc": [ | |
"javascript", | |
"javadoclike", | |
"typescript" | |
], | |
"js-extras": "javascript", | |
"json5": "json", | |
"jsonp": "json", | |
"js-templates": "javascript", | |
"kotlin": "clike", | |
"latte": [ | |
"clike", | |
"markup-templating", | |
"php" | |
], | |
"less": "css", | |
"lilypond": "scheme", | |
"liquid": "markup-templating", | |
"markdown": "markup", | |
"markup-templating": "markup", | |
"mongodb": "javascript", | |
"n4js": "javascript", | |
"objectivec": "c", | |
"opencl": "c", | |
"parser": "markup", | |
"php": "markup-templating", | |
"phpdoc": [ | |
"php", | |
"javadoclike" | |
], | |
"php-extras": "php", | |
"plsql": "sql", | |
"processing": "clike", | |
"protobuf": "clike", | |
"pug": [ | |
"markup", | |
"javascript" | |
], | |
"purebasic": "clike", | |
"purescript": "haskell", | |
"qsharp": "clike", | |
"qml": "javascript", | |
"qore": "clike", | |
"racket": "scheme", | |
"cshtml": [ | |
"markup", | |
"csharp" | |
], | |
"jsx": [ | |
"markup", | |
"javascript" | |
], | |
"tsx": [ | |
"jsx", | |
"typescript" | |
], | |
"reason": "clike", | |
"ruby": "clike", | |
"sass": "css", | |
"scss": "css", | |
"scala": "java", | |
"shell-session": "bash", | |
"smarty": "markup-templating", | |
"solidity": "clike", | |
"soy": "markup-templating", | |
"sparql": "turtle", | |
"sqf": "clike", | |
"squirrel": "clike", | |
"t4-cs": [ | |
"t4-templating", | |
"csharp" | |
], | |
"t4-vb": [ | |
"t4-templating", | |
"vbnet" | |
], | |
"tap": "yaml", | |
"tt2": [ | |
"clike", | |
"markup-templating" | |
], | |
"textile": "markup", | |
"twig": "markup-templating", | |
"typescript": "javascript", | |
"v": "clike", | |
"vala": "clike", | |
"vbnet": "basic", | |
"velocity": "markup", | |
"wiki": "markup", | |
"xeora": "markup", | |
"xml-doc": "markup", | |
"xquery": "markup" | |
}/*]*/; | |
var lang_aliases = /*aliases_placeholder[*/{ | |
"html": "markup", | |
"xml": "markup", | |
"svg": "markup", | |
"mathml": "markup", | |
"ssml": "markup", | |
"atom": "markup", | |
"rss": "markup", | |
"js": "javascript", | |
"g4": "antlr4", | |
"ino": "arduino", | |
"adoc": "asciidoc", | |
"avs": "avisynth", | |
"avdl": "avro-idl", | |
"shell": "bash", | |
"shortcode": "bbcode", | |
"rbnf": "bnf", | |
"oscript": "bsl", | |
"cs": "csharp", | |
"dotnet": "csharp", | |
"cfc": "cfscript", | |
"coffee": "coffeescript", | |
"conc": "concurnas", | |
"jinja2": "django", | |
"dns-zone": "dns-zone-file", | |
"dockerfile": "docker", | |
"gv": "dot", | |
"eta": "ejs", | |
"xlsx": "excel-formula", | |
"xls": "excel-formula", | |
"gamemakerlanguage": "gml", | |
"gni": "gn", | |
"go-mod": "go-module", | |
"hbs": "handlebars", | |
"hs": "haskell", | |
"idr": "idris", | |
"gitignore": "ignore", | |
"hgignore": "ignore", | |
"npmignore": "ignore", | |
"webmanifest": "json", | |
"kt": "kotlin", | |
"kts": "kotlin", | |
"kum": "kumir", | |
"tex": "latex", | |
"context": "latex", | |
"ly": "lilypond", | |
"emacs": "lisp", | |
"elisp": "lisp", | |
"emacs-lisp": "lisp", | |
"md": "markdown", | |
"moon": "moonscript", | |
"n4jsd": "n4js", | |
"nani": "naniscript", | |
"objc": "objectivec", | |
"qasm": "openqasm", | |
"objectpascal": "pascal", | |
"px": "pcaxis", | |
"pcode": "peoplecode", | |
"pq": "powerquery", | |
"mscript": "powerquery", | |
"pbfasm": "purebasic", | |
"purs": "purescript", | |
"py": "python", | |
"qs": "qsharp", | |
"rkt": "racket", | |
"razor": "cshtml", | |
"rpy": "renpy", | |
"robot": "robotframework", | |
"rb": "ruby", | |
"sh-session": "shell-session", | |
"shellsession": "shell-session", | |
"smlnj": "sml", | |
"sol": "solidity", | |
"sln": "solution-file", | |
"rq": "sparql", | |
"t4": "t4-cs", | |
"trickle": "tremor", | |
"troy": "tremor", | |
"trig": "turtle", | |
"ts": "typescript", | |
"tsconfig": "typoscript", | |
"uscript": "unrealscript", | |
"uc": "unrealscript", | |
"url": "uri", | |
"vb": "visual-basic", | |
"vba": "visual-basic", | |
"webidl": "web-idl", | |
"mathematica": "wolfram", | |
"nb": "wolfram", | |
"wl": "wolfram", | |
"xeoracube": "xeora", | |
"yml": "yaml" | |
}/*]*/; | |
/* eslint-enable */ | |
/** | |
* @typedef LangDataItem | |
* @property {{ success?: () => void, error?: () => void }[]} callbacks | |
* @property {boolean} [error] | |
* @property {boolean} [loading] | |
*/ | |
/** @type {Object<string, LangDataItem>} */ | |
var lang_data = {}; | |
var ignored_language = ['none','terminal']; | |
var languages_path = 'components/'; | |
var script = Prism.util.currentScript(); | |
if (script) { | |
var autoloaderFile = /\bplugins\/autoloader\/prism-autoloader\.(?:min\.)?js(?:\?[^\r\n/]*)?$/i; | |
var prismFile = /(^|\/)[\w-]+\.(?:min\.)?js(?:\?[^\r\n/]*)?$/i; | |
var autoloaderPath = script.getAttribute('data-autoloader-path'); | |
if (autoloaderPath != null) { | |
// data-autoloader-path is set, so just use it | |
languages_path = autoloaderPath.trim().replace(/\/?$/, '/'); | |
} else { | |
var src = script.src; | |
if (autoloaderFile.test(src)) { | |
// the script is the original autoloader script in the usual Prism project structure | |
languages_path = src.replace(autoloaderFile, 'components/'); | |
} else if (prismFile.test(src)) { | |
// the script is part of a bundle like a custom prism.js from the download page | |
languages_path = src.replace(prismFile, '$1components/'); | |
} | |
} | |
} | |
var config = Prism.plugins.autoloader = { | |
languages_path: languages_path, | |
use_minified: true, | |
loadLanguages: loadLanguages | |
}; | |
/** | |
* Lazily loads an external script. | |
* | |
* @param {string} src | |
* @param {() => void} [success] | |
* @param {() => void} [error] | |
*/ | |
function addScript(src, success, error) { | |
var s = document.createElement('script'); | |
s.src = src; | |
s.async = true; | |
s.onload = function () { | |
document.body.removeChild(s); | |
success && success(); | |
}; | |
s.onerror = function () { | |
document.body.removeChild(s); | |
error && error(); | |
}; | |
document.body.appendChild(s); | |
} | |
/** | |
* Returns all additional dependencies of the given element defined by the `data-dependencies` attribute. | |
* | |
* @param {Element} element | |
* @returns {string[]} | |
*/ | |
function getDependencies(element) { | |
var deps = (element.getAttribute('data-dependencies') || '').trim(); | |
if (!deps) { | |
var parent = element.parentElement; | |
if (parent && parent.tagName.toLowerCase() === 'pre') { | |
deps = (parent.getAttribute('data-dependencies') || '').trim(); | |
} | |
} | |
return deps ? deps.split(/\s*,\s*/g) : []; | |
} | |
/** | |
* Returns whether the given language is currently loaded. | |
* | |
* @param {string} lang | |
* @returns {boolean} | |
*/ | |
function isLoaded(lang) { | |
if (lang.indexOf('!') >= 0) { | |
// forced reload | |
return false; | |
} | |
lang = lang_aliases[lang] || lang; // resolve alias | |
if (lang in Prism.languages) { | |
// the given language is already loaded | |
return true; | |
} | |
// this will catch extensions like CSS extras that don't add a grammar to Prism.languages | |
var data = lang_data[lang]; | |
return data && !data.error && data.loading === false; | |
} | |
/** | |
* Returns the path to a grammar, using the language_path and use_minified config keys. | |
* | |
* @param {string} lang | |
* @returns {string} | |
*/ | |
function getLanguagePath(lang) { | |
return config.languages_path + 'prism-' + lang + (config.use_minified ? '.min' : '') + '.js'; | |
} | |
/** | |
* Loads all given grammars concurrently. | |
* | |
* @param {string[]|string} languages | |
* @param {(languages: string[]) => void} [success] | |
* @param {(language: string) => void} [error] This callback will be invoked on the first language to fail. | |
*/ | |
function loadLanguages(languages, success, error) { | |
if (typeof languages === 'string') { | |
languages = [languages]; | |
} | |
var total = languages.length; | |
var completed = 0; | |
var failed = false; | |
if (total === 0) { | |
if (success) { | |
setTimeout(success, 0); | |
} | |
return; | |
} | |
function successCallback() { | |
if (failed) { | |
return; | |
} | |
completed++; | |
if (completed === total) { | |
success && success(languages); | |
} | |
} | |
languages.forEach(function (lang) { | |
loadLanguage(lang, successCallback, function () { | |
if (failed) { | |
return; | |
} | |
failed = true; | |
error && error(lang); | |
}); | |
}); | |
} | |
/** | |
* Loads a grammar with its dependencies. | |
* | |
* @param {string} lang | |
* @param {() => void} [success] | |
* @param {() => void} [error] | |
*/ | |
function loadLanguage(lang, success, error) { | |
var force = lang.indexOf('!') >= 0; | |
lang = lang.replace('!', ''); | |
lang = lang_aliases[lang] || lang; | |
function load() { | |
var data = lang_data[lang]; | |
if (!data) { | |
data = lang_data[lang] = { | |
callbacks: [] | |
}; | |
} | |
data.callbacks.push({ | |
success: success, | |
error: error | |
}); | |
if (!force && isLoaded(lang)) { | |
// the language is already loaded and we aren't forced to reload | |
languageCallback(lang, 'success'); | |
} else if (!force && data.error) { | |
// the language failed to load before and we don't reload | |
languageCallback(lang, 'error'); | |
} else if (force || !data.loading) { | |
// the language isn't currently loading and/or we are forced to reload | |
data.loading = true; | |
data.error = false; | |
addScript(getLanguagePath(lang), function () { | |
data.loading = false; | |
languageCallback(lang, 'success'); | |
}, function () { | |
data.loading = false; | |
data.error = true; | |
languageCallback(lang, 'error'); | |
}); | |
} | |
} | |
var dependencies = lang_dependencies[lang]; | |
if (dependencies && dependencies.length) { | |
loadLanguages(dependencies, load, error); | |
} else { | |
load(); | |
} | |
} | |
/** | |
* Runs all callbacks of the given type for the given language. | |
* | |
* @param {string} lang | |
* @param {"success" | "error"} type | |
*/ | |
function languageCallback(lang, type) { | |
if (lang_data[lang]) { | |
var callbacks = lang_data[lang].callbacks; | |
for (var i = 0, l = callbacks.length; i < l; i++) { | |
var callback = callbacks[i][type]; | |
if (callback) { | |
setTimeout(callback, 0); | |
} | |
} | |
callbacks.length = 0; | |
} | |
} | |
Prism.hooks.add('complete', function (env) { | |
var element = env.element; | |
var language = env.language; | |
if (!element || !language || ignored_language.includes(language)) { | |
return; | |
} | |
var deps = getDependencies(element); | |
if (/^diff-./i.test(language)) { | |
// the "diff-xxxx" format is used by the Diff Highlight plugin | |
deps.push('diff'); | |
deps.push(language.substr('diff-'.length)); | |
} else { | |
deps.push(language); | |
} | |
if (!deps.every(isLoaded)) { | |
// the language or some dependencies aren't loaded | |
loadLanguages(deps, function () { | |
Prism.highlightElement(element); | |
}); | |
} | |
}); | |
}()); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment