UNPKG

10.9 kBJavaScriptView Raw
1(function () {
2 if (typeof self === 'undefined' || !self.Prism || !self.document || !document.createElement) {
3 return;
4 }
5
6 /**
7 * The dependencies map is built automatically with gulp.
8 *
9 * @type {Object<string, string | string[]>}
10 */
11 var lang_dependencies = /*dependencies_placeholder[*/{
12 "javascript": "clike",
13 "actionscript": "javascript",
14 "apex": [
15 "clike",
16 "sql"
17 ],
18 "arduino": "cpp",
19 "aspnet": [
20 "markup",
21 "csharp"
22 ],
23 "birb": "clike",
24 "bison": "c",
25 "c": "clike",
26 "csharp": "clike",
27 "cpp": "c",
28 "coffeescript": "javascript",
29 "crystal": "ruby",
30 "css-extras": "css",
31 "d": "clike",
32 "dart": "clike",
33 "django": "markup-templating",
34 "ejs": [
35 "javascript",
36 "markup-templating"
37 ],
38 "etlua": [
39 "lua",
40 "markup-templating"
41 ],
42 "erb": [
43 "ruby",
44 "markup-templating"
45 ],
46 "fsharp": "clike",
47 "firestore-security-rules": "clike",
48 "flow": "javascript",
49 "ftl": "markup-templating",
50 "gml": "clike",
51 "glsl": "c",
52 "go": "clike",
53 "groovy": "clike",
54 "haml": "ruby",
55 "handlebars": "markup-templating",
56 "haxe": "clike",
57 "hlsl": "c",
58 "java": "clike",
59 "javadoc": [
60 "markup",
61 "java",
62 "javadoclike"
63 ],
64 "jolie": "clike",
65 "jsdoc": [
66 "javascript",
67 "javadoclike",
68 "typescript"
69 ],
70 "js-extras": "javascript",
71 "json5": "json",
72 "jsonp": "json",
73 "js-templates": "javascript",
74 "kotlin": "clike",
75 "latte": [
76 "clike",
77 "markup-templating",
78 "php"
79 ],
80 "less": "css",
81 "lilypond": "scheme",
82 "markdown": "markup",
83 "markup-templating": "markup",
84 "mongodb": "javascript",
85 "n4js": "javascript",
86 "nginx": "clike",
87 "objectivec": "c",
88 "opencl": "c",
89 "parser": "markup",
90 "php": "markup-templating",
91 "phpdoc": [
92 "php",
93 "javadoclike"
94 ],
95 "php-extras": "php",
96 "plsql": "sql",
97 "processing": "clike",
98 "protobuf": "clike",
99 "pug": [
100 "markup",
101 "javascript"
102 ],
103 "purebasic": "clike",
104 "purescript": "haskell",
105 "qml": "javascript",
106 "qore": "clike",
107 "racket": "scheme",
108 "jsx": [
109 "markup",
110 "javascript"
111 ],
112 "tsx": [
113 "jsx",
114 "typescript"
115 ],
116 "reason": "clike",
117 "ruby": "clike",
118 "sass": "css",
119 "scss": "css",
120 "scala": "java",
121 "shell-session": "bash",
122 "smarty": "markup-templating",
123 "solidity": "clike",
124 "soy": "markup-templating",
125 "sparql": "turtle",
126 "sqf": "clike",
127 "swift": "clike",
128 "t4-cs": [
129 "t4-templating",
130 "csharp"
131 ],
132 "t4-vb": [
133 "t4-templating",
134 "vbnet"
135 ],
136 "tap": "yaml",
137 "tt2": [
138 "clike",
139 "markup-templating"
140 ],
141 "textile": "markup",
142 "twig": "markup",
143 "typescript": "javascript",
144 "vala": "clike",
145 "vbnet": "basic",
146 "velocity": "markup",
147 "wiki": "markup",
148 "xeora": "markup",
149 "xml-doc": "markup",
150 "xquery": "markup"
151 }/*]*/;
152
153 var lang_aliases = /*aliases_placeholder[*/{
154 "html": "markup",
155 "xml": "markup",
156 "svg": "markup",
157 "mathml": "markup",
158 "ssml": "markup",
159 "atom": "markup",
160 "rss": "markup",
161 "js": "javascript",
162 "g4": "antlr4",
163 "adoc": "asciidoc",
164 "shell": "bash",
165 "shortcode": "bbcode",
166 "rbnf": "bnf",
167 "oscript": "bsl",
168 "cs": "csharp",
169 "dotnet": "csharp",
170 "coffee": "coffeescript",
171 "conc": "concurnas",
172 "jinja2": "django",
173 "dns-zone": "dns-zone-file",
174 "dockerfile": "docker",
175 "eta": "ejs",
176 "xlsx": "excel-formula",
177 "xls": "excel-formula",
178 "gamemakerlanguage": "gml",
179 "hs": "haskell",
180 "gitignore": "ignore",
181 "hgignore": "ignore",
182 "npmignore": "ignore",
183 "webmanifest": "json",
184 "kt": "kotlin",
185 "kts": "kotlin",
186 "tex": "latex",
187 "context": "latex",
188 "ly": "lilypond",
189 "emacs": "lisp",
190 "elisp": "lisp",
191 "emacs-lisp": "lisp",
192 "md": "markdown",
193 "moon": "moonscript",
194 "n4jsd": "n4js",
195 "nani": "naniscript",
196 "objc": "objectivec",
197 "objectpascal": "pascal",
198 "px": "pcaxis",
199 "pcode": "peoplecode",
200 "pq": "powerquery",
201 "mscript": "powerquery",
202 "pbfasm": "purebasic",
203 "purs": "purescript",
204 "py": "python",
205 "rkt": "racket",
206 "rpy": "renpy",
207 "robot": "robotframework",
208 "rb": "ruby",
209 "sh-session": "shell-session",
210 "shellsession": "shell-session",
211 "smlnj": "sml",
212 "sol": "solidity",
213 "sln": "solution-file",
214 "rq": "sparql",
215 "t4": "t4-cs",
216 "trig": "turtle",
217 "ts": "typescript",
218 "tsconfig": "typoscript",
219 "uscript": "unrealscript",
220 "uc": "unrealscript",
221 "vb": "visual-basic",
222 "vba": "visual-basic",
223 "xeoracube": "xeora",
224 "yml": "yaml"
225 }/*]*/;
226
227 /**
228 * @typedef LangDataItem
229 * @property {{ success?: () => void, error?: () => void }[]} callbacks
230 * @property {boolean} [error]
231 * @property {boolean} [loading]
232 */
233 /** @type {Object<string, LangDataItem>} */
234 var lang_data = {};
235
236 var ignored_language = 'none';
237 var languages_path = 'components/';
238
239 var script = Prism.util.currentScript();
240 if (script) {
241 var autoloaderFile = /\bplugins\/autoloader\/prism-autoloader\.(?:min\.)?js(?:\?[^\r\n/]*)?$/i;
242 var prismFile = /(^|\/)[\w-]+\.(?:min\.)?js(?:\?[^\r\n/]*)?$/i;
243
244 var autoloaderPath = script.getAttribute('data-autoloader-path');
245 if (autoloaderPath != null) {
246 // data-autoloader-path is set, so just use it
247 languages_path = autoloaderPath.trim().replace(/\/?$/, '/');
248 } else {
249 var src = script.src;
250 if (autoloaderFile.test(src)) {
251 // the script is the original autoloader script in the usual Prism project structure
252 languages_path = src.replace(autoloaderFile, 'components/');
253 } else if (prismFile.test(src)) {
254 // the script is part of a bundle like a custom prism.js from the download page
255 languages_path = src.replace(prismFile, '$1components/');
256 }
257 }
258 }
259
260 var config = Prism.plugins.autoloader = {
261 languages_path: languages_path,
262 use_minified: true,
263 loadLanguages: loadLanguages
264 };
265
266
267 /**
268 * Lazily loads an external script.
269 *
270 * @param {string} src
271 * @param {() => void} [success]
272 * @param {() => void} [error]
273 */
274 function addScript(src, success, error) {
275 var s = document.createElement('script');
276 s.src = src;
277 s.async = true;
278 s.onload = function () {
279 document.body.removeChild(s);
280 success && success();
281 };
282 s.onerror = function () {
283 document.body.removeChild(s);
284 error && error();
285 };
286 document.body.appendChild(s);
287 }
288
289 /**
290 * Returns all additional dependencies of the given element defined by the `data-dependencies` attribute.
291 *
292 * @param {Element} element
293 * @returns {string[]}
294 */
295 function getDependencies(element) {
296 var deps = (element.getAttribute('data-dependencies') || '').trim();
297 if (!deps) {
298 var parent = element.parentElement;
299 if (parent && parent.tagName.toLowerCase() === 'pre') {
300 deps = (parent.getAttribute('data-dependencies') || '').trim();
301 }
302 }
303 return deps ? deps.split(/\s*,\s*/g) : [];
304 }
305
306 /**
307 * Returns whether the given language is currently loaded.
308 *
309 * @param {string} lang
310 * @returns {boolean}
311 */
312 function isLoaded(lang) {
313 if (lang.indexOf('!') >= 0) {
314 // forced reload
315 return false;
316 }
317
318 lang = lang_aliases[lang] || lang; // resolve alias
319
320 if (lang in Prism.languages) {
321 // the given language is already loaded
322 return true;
323 }
324
325 // this will catch extensions like CSS extras that don't add a grammar to Prism.languages
326 var data = lang_data[lang];
327 return data && !data.error && data.loading === false;
328 }
329
330 /**
331 * Returns the path to a grammar, using the language_path and use_minified config keys.
332 *
333 * @param {string} lang
334 * @returns {string}
335 */
336 function getLanguagePath(lang) {
337 return config.languages_path + 'prism-' + lang + (config.use_minified ? '.min' : '') + '.js'
338 }
339
340 /**
341 * Loads all given grammars concurrently.
342 *
343 * @param {string[]|string} languages
344 * @param {(languages: string[]) => void} [success]
345 * @param {(language: string) => void} [error] This callback will be invoked on the first language to fail.
346 */
347 function loadLanguages(languages, success, error) {
348 if (typeof languages === 'string') {
349 languages = [languages];
350 }
351
352 var total = languages.length;
353 var completed = 0;
354 var failed = false;
355
356 if (total === 0) {
357 if (success) {
358 setTimeout(success, 0);
359 }
360 return;
361 }
362
363 function successCallback() {
364 if (failed) {
365 return;
366 }
367 completed++;
368 if (completed === total) {
369 success && success(languages);
370 }
371 }
372
373 languages.forEach(function (lang) {
374 loadLanguage(lang, successCallback, function () {
375 if (failed) {
376 return;
377 }
378 failed = true;
379 error && error(lang);
380 });
381 });
382 }
383
384 /**
385 * Loads a grammar with its dependencies.
386 *
387 * @param {string} lang
388 * @param {() => void} [success]
389 * @param {() => void} [error]
390 */
391 function loadLanguage(lang, success, error) {
392 var force = lang.indexOf('!') >= 0;
393
394 lang = lang.replace('!', '');
395 lang = lang_aliases[lang] || lang;
396
397 function load() {
398 var data = lang_data[lang];
399 if (!data) {
400 data = lang_data[lang] = {
401 callbacks: []
402 };
403 }
404 data.callbacks.push({
405 success: success,
406 error: error
407 });
408
409 if (!force && isLoaded(lang)) {
410 // the language is already loaded and we aren't forced to reload
411 languageCallback(lang, 'success');
412 } else if (!force && data.error) {
413 // the language failed to load before and we don't reload
414 languageCallback(lang, 'error');
415 } else if (force || !data.loading) {
416 // the language isn't currently loading and/or we are forced to reload
417 data.loading = true;
418 data.error = false;
419
420 addScript(getLanguagePath(lang), function () {
421 data.loading = false;
422 languageCallback(lang, 'success');
423
424 }, function () {
425 data.loading = false;
426 data.error = true;
427 languageCallback(lang, 'error');
428 });
429 }
430 };
431
432 var dependencies = lang_dependencies[lang];
433 if (dependencies && dependencies.length) {
434 loadLanguages(dependencies, load, error);
435 } else {
436 load();
437 }
438 }
439
440 /**
441 * Runs all callbacks of the given type for the given language.
442 *
443 * @param {string} lang
444 * @param {"success" | "error"} type
445 */
446 function languageCallback(lang, type) {
447 if (lang_data[lang]) {
448 var callbacks = lang_data[lang].callbacks;
449 for (var i = 0, l = callbacks.length; i < l; i++) {
450 var callback = callbacks[i][type];
451 if (callback) {
452 setTimeout(callback, 0);
453 }
454 }
455 callbacks.length = 0;
456 }
457 }
458
459 Prism.hooks.add('complete', function (env) {
460 var element = env.element;
461 var language = env.language;
462 if (!element || !language || language === ignored_language) {
463 return;
464 }
465
466 var deps = getDependencies(element);
467 if (/^diff-./i.test(language)) {
468 // the "diff-xxxx" format is used by the Diff Highlight plugin
469 deps.push('diff');
470 deps.push(language.substr('diff-'.length));
471 } else {
472 deps.push(language);
473 }
474
475 if (!deps.every(isLoaded)) {
476 // the language or some dependencies aren't loaded
477 loadLanguages(deps, function () {
478 Prism.highlightElement(element);
479 });
480 }
481 });
482
483}());