prism-autoloader.js 10 KB

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