prism.js 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872
  1. /* **********************************************
  2. Begin prism-core.js
  3. ********************************************** */
  4. var _self = (typeof window !== 'undefined') ?
  5. window // if in browser
  6. :
  7. (
  8. (typeof WorkerGlobalScope !== 'undefined' && self instanceof WorkerGlobalScope) ?
  9. self // if in worker
  10. :
  11. {} // if in node js
  12. );
  13. /**
  14. * Prism: Lightweight, robust, elegant syntax highlighting
  15. * MIT license http://www.opensource.org/licenses/mit-license.php/
  16. * @author Lea Verou http://lea.verou.me
  17. */
  18. var Prism = (function() {
  19. // Private helper vars
  20. var lang = /\blang(?:uage)?-([\w-]+)\b/i;
  21. var uniqueId = 0;
  22. var _ = _self.Prism = {
  23. manual: _self.Prism && _self.Prism.manual,
  24. disableWorkerMessageHandler: _self.Prism && _self.Prism.disableWorkerMessageHandler,
  25. util: {
  26. encode: function(tokens) {
  27. if (tokens instanceof Token) {
  28. return new Token(tokens.type, _.util.encode(tokens.content), tokens.alias);
  29. } else if (_.util.type(tokens) === 'Array') {
  30. return tokens.map(_.util.encode);
  31. } else {
  32. return tokens.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/\u00a0/g, ' ');
  33. }
  34. },
  35. type: function(o) {
  36. return Object.prototype.toString.call(o).match(/\[object (\w+)\]/)[1];
  37. },
  38. objId: function(obj) {
  39. if (!obj['__id']) {
  40. Object.defineProperty(obj, '__id', {
  41. value: ++uniqueId
  42. });
  43. }
  44. return obj['__id'];
  45. },
  46. // Deep clone a language definition (e.g. to extend it)
  47. clone: function(o, visited) {
  48. var type = _.util.type(o);
  49. visited = visited || {};
  50. switch (type) {
  51. case 'Object':
  52. if (visited[_.util.objId(o)]) {
  53. return visited[_.util.objId(o)];
  54. }
  55. var clone = {};
  56. visited[_.util.objId(o)] = clone;
  57. for (var key in o) {
  58. if (o.hasOwnProperty(key)) {
  59. clone[key] = _.util.clone(o[key], visited);
  60. }
  61. }
  62. return clone;
  63. case 'Array':
  64. if (visited[_.util.objId(o)]) {
  65. return visited[_.util.objId(o)];
  66. }
  67. var clone = [];
  68. visited[_.util.objId(o)] = clone;
  69. o.forEach(function(v, i) {
  70. clone[i] = _.util.clone(v, visited);
  71. });
  72. return clone;
  73. }
  74. return o;
  75. }
  76. },
  77. languages: {
  78. extend: function(id, redef) {
  79. var lang = _.util.clone(_.languages[id]);
  80. for (var key in redef) {
  81. lang[key] = redef[key];
  82. }
  83. return lang;
  84. },
  85. /**
  86. * Insert a token before another token in a language literal
  87. * As this needs to recreate the object (we cannot actually insert before keys in object literals),
  88. * we cannot just provide an object, we need anobject and a key.
  89. * @param inside The key (or language id) of the parent
  90. * @param before The key to insert before. If not provided, the function appends instead.
  91. * @param insert Object with the key/value pairs to insert
  92. * @param root The object that contains `inside`. If equal to Prism.languages, it can be omitted.
  93. */
  94. insertBefore: function(inside, before, insert, root) {
  95. root = root || _.languages;
  96. var grammar = root[inside];
  97. if (arguments.length == 2) {
  98. insert = arguments[1];
  99. for (var newToken in insert) {
  100. if (insert.hasOwnProperty(newToken)) {
  101. grammar[newToken] = insert[newToken];
  102. }
  103. }
  104. return grammar;
  105. }
  106. var ret = {};
  107. for (var token in grammar) {
  108. if (grammar.hasOwnProperty(token)) {
  109. if (token == before) {
  110. for (var newToken in insert) {
  111. if (insert.hasOwnProperty(newToken)) {
  112. ret[newToken] = insert[newToken];
  113. }
  114. }
  115. }
  116. ret[token] = grammar[token];
  117. }
  118. }
  119. // Update references in other language definitions
  120. _.languages.DFS(_.languages, function(key, value) {
  121. if (value === root[inside] && key != inside) {
  122. this[key] = ret;
  123. }
  124. });
  125. return root[inside] = ret;
  126. },
  127. // Traverse a language definition with Depth First Search
  128. DFS: function(o, callback, type, visited) {
  129. visited = visited || {};
  130. for (var i in o) {
  131. if (o.hasOwnProperty(i)) {
  132. callback.call(o, i, o[i], type || i);
  133. if (_.util.type(o[i]) === 'Object' && !visited[_.util.objId(o[i])]) {
  134. visited[_.util.objId(o[i])] = true;
  135. _.languages.DFS(o[i], callback, null, visited);
  136. } else if (_.util.type(o[i]) === 'Array' && !visited[_.util.objId(o[i])]) {
  137. visited[_.util.objId(o[i])] = true;
  138. _.languages.DFS(o[i], callback, i, visited);
  139. }
  140. }
  141. }
  142. }
  143. },
  144. plugins: {},
  145. highlightAll: function(async, callback) {
  146. _.highlightAllUnder(document, async, callback);
  147. },
  148. highlightAllUnder: function(container, async, callback) {
  149. var env = {
  150. callback: callback,
  151. selector: 'code[class*="language-"], [class*="language-"] code, code[class*="lang-"], [class*="lang-"] code'
  152. };
  153. _.hooks.run("before-highlightall", env);
  154. var elements = env.elements || container.querySelectorAll(env.selector);
  155. for (var i = 0, element; element = elements[i++];) {
  156. _.highlightElement(element, async ===true, env.callback);
  157. }
  158. },
  159. highlightElement: function(element, async, callback) {
  160. // Find language
  161. var language, grammar, parent = element;
  162. while (parent && !lang.test(parent.className)) {
  163. parent = parent.parentNode;
  164. }
  165. if (parent) {
  166. language = (parent.className.match(lang) || [, ''])[1].toLowerCase();
  167. grammar = _.languages[language];
  168. }
  169. // Set language on the element, if not present
  170. element.className = element.className.replace(lang, '').replace(/\s+/g, ' ') + ' language-' + language;
  171. if (element.parentNode) {
  172. // Set language on the parent, for styling
  173. parent = element.parentNode;
  174. if (/pre/i.test(parent.nodeName)) {
  175. parent.className = parent.className.replace(lang, '').replace(/\s+/g, ' ') + ' language-' + language;
  176. }
  177. }
  178. var code = element.textContent;
  179. var env = {
  180. element: element,
  181. language: language,
  182. grammar: grammar,
  183. code: code
  184. };
  185. _.hooks.run('before-sanity-check', env);
  186. if (!env.code || !env.grammar) {
  187. if (env.code) {
  188. _.hooks.run('before-highlight', env);
  189. env.element.textContent = env.code;
  190. _.hooks.run('after-highlight', env);
  191. }
  192. _.hooks.run('complete', env);
  193. return;
  194. }
  195. _.hooks.run('before-highlight', env);
  196. if (async &&_self.Worker) {
  197. var worker = new Worker(_.filename);
  198. worker.onmessage = function(evt) {
  199. env.highlightedCode = evt.data;
  200. _.hooks.run('before-insert', env);
  201. env.element.innerHTML = env.highlightedCode;
  202. callback && callback.call(env.element);
  203. _.hooks.run('after-highlight', env);
  204. _.hooks.run('complete', env);
  205. };
  206. worker.postMessage(JSON.stringify({
  207. language: env.language,
  208. code: env.code,
  209. immediateClose: true
  210. }));
  211. } else {
  212. env.highlightedCode = _.highlight(env.code, env.grammar, env.language);
  213. _.hooks.run('before-insert', env);
  214. env.element.innerHTML = env.highlightedCode;
  215. callback && callback.call(element);
  216. _.hooks.run('after-highlight', env);
  217. _.hooks.run('complete', env);
  218. }
  219. },
  220. highlight: function(text, grammar, language) {
  221. var env = {
  222. code: text,
  223. grammar: grammar,
  224. language: language
  225. };
  226. _.hooks.run('before-tokenize', env);
  227. env.tokens = _.tokenize(env.code, env.grammar);
  228. _.hooks.run('after-tokenize', env);
  229. return Token.stringify(_.util.encode(env.tokens), env.language);
  230. },
  231. matchGrammar: function(text, strarr, grammar, index, startPos, oneshot, target) {
  232. var Token = _.Token;
  233. for (var token in grammar) {
  234. if (!grammar.hasOwnProperty(token) || !grammar[token]) {
  235. continue;
  236. }
  237. if (token == target) {
  238. return;
  239. }
  240. var patterns = grammar[token];
  241. patterns = (_.util.type(patterns) === "Array") ? patterns : [patterns];
  242. for (var j = 0; j < patterns.length; ++j) {
  243. var pattern = patterns[j],
  244. inside = pattern.inside,
  245. lookbehind = !!pattern.lookbehind,
  246. greedy = !!pattern.greedy,
  247. lookbehindLength = 0,
  248. alias = pattern.alias;
  249. if (greedy && !pattern.pattern.global) {
  250. // Without the global flag, lastIndex won't work
  251. var flags = pattern.pattern.toString().match(/[imuy]*$/)[0];
  252. pattern.pattern = RegExp(pattern.pattern.source, flags + "g");
  253. }
  254. pattern = pattern.pattern || pattern;
  255. // Don’t cache length as it changes during the loop
  256. for (var i = index, pos = startPos; i < strarr.length; pos += strarr[i].length, ++i) {
  257. var str = strarr[i];
  258. if (strarr.length > text.length) {
  259. // Something went terribly wrong, ABORT, ABORT!
  260. return;
  261. }
  262. if (str instanceof Token) {
  263. continue;
  264. }
  265. if (greedy && i != strarr.length - 1) {
  266. pattern.lastIndex = pos;
  267. var match = pattern.exec(text);
  268. if (!match) {
  269. break;
  270. }
  271. var from = match.index + (lookbehind ? match[1].length : 0),
  272. to = match.index + match[0].length,
  273. k = i,
  274. p = pos;
  275. for (var len = strarr.length; k < len && (p < to || (!strarr[k].type && !strarr[k - 1].greedy)); ++k) {
  276. p += strarr[k].length;
  277. // Move the index i to the element in strarr that is closest to from
  278. if (from >= p) {
  279. ++i;
  280. pos = p;
  281. }
  282. }
  283. // If strarr[i] is a Token, then the match starts inside another Token, which is invalid
  284. if (strarr[i] instanceof Token) {
  285. continue;
  286. }
  287. // Number of tokens to delete and replace with the new match
  288. delNum = k - i;
  289. str = text.slice(pos, p);
  290. match.index -= pos;
  291. } else {
  292. pattern.lastIndex = 0;
  293. var match = pattern.exec(str),
  294. delNum = 1;
  295. }
  296. if (!match) {
  297. if (oneshot) {
  298. break;
  299. }
  300. continue;
  301. }
  302. if (lookbehind) {
  303. lookbehindLength = match[1] ? match[1].length : 0;
  304. }
  305. var from = match.index + lookbehindLength,
  306. match = match[0].slice(lookbehindLength),
  307. to = from + match.length,
  308. before = str.slice(0, from),
  309. after = str.slice(to);
  310. var args = [i, delNum];
  311. if (before) {
  312. ++i;
  313. pos += before.length;
  314. args.push(before);
  315. }
  316. var wrapped = new Token(token, inside ? _.tokenize(match, inside) : match, alias, match, greedy);
  317. args.push(wrapped);
  318. if (after) {
  319. args.push(after);
  320. }
  321. Array.prototype.splice.apply(strarr, args);
  322. if (delNum != 1)
  323. _.matchGrammar(text, strarr, grammar, i, pos, true, token);
  324. if (oneshot)
  325. break;
  326. }
  327. }
  328. }
  329. },
  330. tokenize: function(text, grammar, language) {
  331. var strarr = [text];
  332. var rest = grammar.rest;
  333. if (rest) {
  334. for (var token in rest) {
  335. grammar[token] = rest[token];
  336. }
  337. delete grammar.rest;
  338. }
  339. _.matchGrammar(text, strarr, grammar, 0, 0, false);
  340. return strarr;
  341. },
  342. hooks: {
  343. all: {},
  344. add: function(name, callback) {
  345. var hooks = _.hooks.all;
  346. hooks[name] = hooks[name] || [];
  347. hooks[name].push(callback);
  348. },
  349. run: function(name, env) {
  350. var callbacks = _.hooks.all[name];
  351. if (!callbacks || !callbacks.length) {
  352. return;
  353. }
  354. for (var i = 0, callback; callback = callbacks[i++];) {
  355. callback(env);
  356. }
  357. }
  358. }
  359. };
  360. var Token = _.Token = function(type, content, alias, matchedStr, greedy) {
  361. this.type = type;
  362. this.content = content;
  363. this.alias = alias;
  364. // Copy of the full string this token was created from
  365. this.length = (matchedStr || "").length | 0;
  366. this.greedy = !!greedy;
  367. };
  368. Token.stringify = function(o, language, parent) {
  369. if (typeof o == 'string') {
  370. return o;
  371. }
  372. if (_.util.type(o) === 'Array') {
  373. return o.map(function(element) {
  374. return Token.stringify(element, language, o);
  375. }).join('');
  376. }
  377. var env = {
  378. type: o.type,
  379. content: Token.stringify(o.content, language, parent),
  380. tag: 'span',
  381. classes: ['token', o.type],
  382. attributes: {},
  383. language: language,
  384. parent: parent
  385. };
  386. if (o.alias) {
  387. var aliases = _.util.type(o.alias) === 'Array' ? o.alias : [o.alias];
  388. Array.prototype.push.apply(env.classes, aliases);
  389. }
  390. _.hooks.run('wrap', env);
  391. var attributes = Object.keys(env.attributes).map(function(name) {
  392. return name + '="' + (env.attributes[name] || '').replace(/"/g, '&quot;') + '"';
  393. }).join(' ');
  394. return '<' + env.tag + ' class="' + env.classes.join(' ') + '"' + (attributes ? ' ' + attributes : '') + '>' + env.content + '</' + env.tag + '>';
  395. };
  396. if (!_self.document) {
  397. if (!_self.addEventListener) {
  398. // in Node.js
  399. return _self.Prism;
  400. }
  401. if (!_.disableWorkerMessageHandler) {
  402. // In worker
  403. _self.addEventListener('message', function(evt) {
  404. var message = JSON.parse(evt.data),
  405. lang = message.language,
  406. code = message.code,
  407. immediateClose = message.immediateClose;
  408. _self.postMessage(_.highlight(code, _.languages[lang], lang));
  409. if (immediateClose) {
  410. _self.close();
  411. }
  412. }, false);
  413. }
  414. return _self.Prism;
  415. }
  416. //Get current script and highlight
  417. var script = document.currentScript || [].slice.call(document.getElementsByTagName("script")).pop();
  418. if (script) {
  419. _.filename = script.src;
  420. if (!_.manual && !script.hasAttribute('data-manual')) {
  421. if (document.readyState !== "loading") {
  422. if (window.requestAnimationFrame) {
  423. window.requestAnimationFrame(_.highlightAll);
  424. } else {
  425. window.setTimeout(_.highlightAll, 16);
  426. }
  427. } else {
  428. document.addEventListener('DOMContentLoaded', _.highlightAll);
  429. }
  430. }
  431. }
  432. return _self.Prism;
  433. })();
  434. if (typeof module !== 'undefined' && module.exports) {
  435. module.exports = Prism;
  436. }
  437. // hack for components to work correctly in node.js
  438. if (typeof global !== 'undefined') {
  439. global.Prism = Prism;
  440. }
  441. /* **********************************************
  442. Begin prism-markup.js
  443. ********************************************** */
  444. Prism.languages.markup = {
  445. 'comment': /<!--[\s\S]*?-->/,
  446. 'prolog': /<\?[\s\S]+?\?>/,
  447. 'doctype': /<!DOCTYPE[\s\S]+?>/i,
  448. 'cdata': /<!\[CDATA\[[\s\S]*?]]>/i,
  449. 'tag': {
  450. pattern: /<\/?(?!\d)[^\s>\/=$<%]+(?:\s+[^\s>\/=]+(?:=(?:("|')(?:\\[\s\S]|(?!\1)[^\\])*\1|[^\s'">=]+))?)*\s*\/?>/i,
  451. greedy: true,
  452. inside: {
  453. 'tag': {
  454. pattern: /^<\/?[^\s>\/]+/i,
  455. inside: {
  456. 'punctuation': /^<\/?/,
  457. 'namespace': /^[^\s>\/:]+:/
  458. }
  459. },
  460. 'attr-value': {
  461. pattern: /=(?:("|')(?:\\[\s\S]|(?!\1)[^\\])*\1|[^\s'">=]+)/i,
  462. inside: {
  463. 'punctuation': [
  464. /^=/,
  465. {
  466. pattern: /(^|[^\\])["']/,
  467. lookbehind: true
  468. }
  469. ]
  470. }
  471. },
  472. 'punctuation': /\/?>/,
  473. 'attr-name': {
  474. pattern: /[^\s>\/]+/,
  475. inside: {
  476. 'namespace': /^[^\s>\/:]+:/
  477. }
  478. }
  479. }
  480. },
  481. 'entity': /&#?[\da-z]{1,8};/i
  482. };
  483. Prism.languages.markup['tag'].inside['attr-value'].inside['entity'] =
  484. Prism.languages.markup['entity'];
  485. // Plugin to make entity title show the real entity, idea by Roman Komarov
  486. Prism.hooks.add('wrap', function(env) {
  487. if (env.type === 'entity') {
  488. env.attributes['title'] = env.content.replace(/&amp;/, '&');
  489. }
  490. });
  491. Prism.languages.xml = Prism.languages.markup;
  492. Prism.languages.html = Prism.languages.markup;
  493. Prism.languages.mathml = Prism.languages.markup;
  494. Prism.languages.svg = Prism.languages.markup;
  495. /* **********************************************
  496. Begin prism-css.js
  497. ********************************************** */
  498. Prism.languages.css = {
  499. 'comment': /\/\*[\s\S]*?\*\//,
  500. 'atrule': {
  501. pattern: /@[\w-]+?.*?(?:;|(?=\s*\{))/i,
  502. inside: {
  503. 'rule': /@[\w-]+/
  504. // See rest below
  505. }
  506. },
  507. 'url': /url\((?:(["'])(?:\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1|.*?)\)/i,
  508. 'selector': /[^{}\s][^{};]*?(?=\s*\{)/,
  509. 'string': {
  510. pattern: /("|')(?:\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1/,
  511. greedy: true
  512. },
  513. 'property': /[-_a-z\xA0-\uFFFF][-\w\xA0-\uFFFF]*(?=\s*:)/i,
  514. 'important': /\B!important\b/i,
  515. 'function': /[-a-z0-9]+(?=\()/i,
  516. 'punctuation': /[(){};:]/
  517. };
  518. Prism.languages.css['atrule'].inside.rest = Prism.languages.css;
  519. if (Prism.languages.markup) {
  520. Prism.languages.insertBefore('markup', 'tag', {
  521. 'style': {
  522. pattern: /(<style[\s\S]*?>)[\s\S]*?(?=<\/style>)/i,
  523. lookbehind: true,
  524. inside: Prism.languages.css,
  525. alias: 'language-css',
  526. greedy: true
  527. }
  528. });
  529. Prism.languages.insertBefore('inside', 'attr-value', {
  530. 'style-attr': {
  531. pattern: /\s*style=("|')(?:\\[\s\S]|(?!\1)[^\\])*\1/i,
  532. inside: {
  533. 'attr-name': {
  534. pattern: /^\s*style/i,
  535. inside: Prism.languages.markup.tag.inside
  536. },
  537. 'punctuation': /^\s*=\s*['"]|['"]\s*$/,
  538. 'attr-value': {
  539. pattern: /.+/i,
  540. inside: Prism.languages.css
  541. }
  542. },
  543. alias: 'language-css'
  544. }
  545. }, Prism.languages.markup.tag);
  546. }
  547. /* **********************************************
  548. Begin prism-clike.js
  549. ********************************************** */
  550. Prism.languages.clike = {
  551. 'comment': [{
  552. pattern: /(^|[^\\])\/\*[\s\S]*?(?:\*\/|$)/,
  553. lookbehind: true
  554. },
  555. {
  556. pattern: /(^|[^\\:])\/\/.*/,
  557. lookbehind: true,
  558. greedy: true
  559. }
  560. ],
  561. 'string': {
  562. pattern: /(["'])(?:\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1/,
  563. greedy: true
  564. },
  565. 'class-name': {
  566. pattern: /((?:\b(?:class|interface|extends|implements|trait|instanceof|new)\s+)|(?:catch\s+\())[\w.\\]+/i,
  567. lookbehind: true,
  568. inside: {
  569. punctuation: /[.\\]/
  570. }
  571. },
  572. 'keyword': /\b(?:if|else|while|do|for|return|in|instanceof|function|new|try|throw|catch|finally|null|break|continue)\b/,
  573. 'boolean': /\b(?:true|false)\b/,
  574. 'function': /[a-z0-9_]+(?=\()/i,
  575. 'number': /\b0x[\da-f]+\b|(?:\b\d+\.?\d*|\B\.\d+)(?:e[+-]?\d+)?/i,
  576. 'operator': /--?|\+\+?|!=?=?|<=?|>=?|==?=?|&&?|\|\|?|\?|\*|\/|~|\^|%/,
  577. 'punctuation': /[{}[\];(),.:]/
  578. };
  579. /* **********************************************
  580. Begin prism-javascript.js
  581. ********************************************** */
  582. Prism.languages.javascript = Prism.languages.extend('clike', {
  583. 'keyword': /\b(?:as|async|await|break|case|catch|class|const|continue|debugger|default|delete|do|else|enum|export|extends|finally|for|from|function|get|if|implements|import|in|instanceof|interface|let|new|null|of|package|private|protected|public|return|set|static|super|switch|this|throw|try|typeof|var|void|while|with|yield)\b/,
  584. 'number': /\b(?:0[xX][\dA-Fa-f]+|0[bB][01]+|0[oO][0-7]+|NaN|Infinity)\b|(?:\b\d+\.?\d*|\B\.\d+)(?:[Ee][+-]?\d+)?/,
  585. // Allow for all non-ASCII characters (See http://stackoverflow.com/a/2008444)
  586. 'function': /[_$a-z\xA0-\uFFFF][$\w\xA0-\uFFFF]*(?=\s*\()/i,
  587. 'operator': /-[-=]?|\+[+=]?|!=?=?|<<?=?|>>?>?=?|=(?:==?|>)?|&[&=]?|\|[|=]?|\*\*?=?|\/=?|~|\^=?|%=?|\?|\.{3}/
  588. });
  589. Prism.languages.insertBefore('javascript', 'keyword', {
  590. 'regex': {
  591. pattern: /((?:^|[^$\w\xA0-\uFFFF."'\])\s])\s*)\/(\[[^\]\r\n]+]|\\.|[^/\\\[\r\n])+\/[gimyu]{0,5}(?=\s*($|[\r\n,.;})\]]))/,
  592. lookbehind: true,
  593. greedy: true
  594. },
  595. // This must be declared before keyword because we use "function" inside the look-forward
  596. 'function-variable': {
  597. pattern: /[_$a-z\xA0-\uFFFF][$\w\xA0-\uFFFF]*(?=\s*=\s*(?:function\b|(?:\([^()]*\)|[_$a-z\xA0-\uFFFF][$\w\xA0-\uFFFF]*)\s*=>))/i,
  598. alias: 'function'
  599. },
  600. 'constant': /\b[A-Z][A-Z\d_]*\b/
  601. });
  602. Prism.languages.insertBefore('javascript', 'string', {
  603. 'template-string': {
  604. pattern: /`(?:\\[\s\S]|\${[^}]+}|[^\\`])*`/,
  605. greedy: true,
  606. inside: {
  607. 'interpolation': {
  608. pattern: /\${[^}]+}/,
  609. inside: {
  610. 'interpolation-punctuation': {
  611. pattern: /^\${|}$/,
  612. alias: 'punctuation'
  613. },
  614. rest: null // See below
  615. }
  616. },
  617. 'string': /[\s\S]+/
  618. }
  619. }
  620. });
  621. Prism.languages.javascript['template-string'].inside['interpolation'].inside.rest = Prism.languages.javascript;
  622. if (Prism.languages.markup) {
  623. Prism.languages.insertBefore('markup', 'tag', {
  624. 'script': {
  625. pattern: /(<script[\s\S]*?>)[\s\S]*?(?=<\/script>)/i,
  626. lookbehind: true,
  627. inside: Prism.languages.javascript,
  628. alias: 'language-javascript',
  629. greedy: true
  630. }
  631. });
  632. }
  633. Prism.languages.js = Prism.languages.javascript;
  634. /* **********************************************
  635. Begin prism-file-highlight.js
  636. ********************************************** */
  637. (function() {
  638. if (typeof self === 'undefined' || !self.Prism || !self.document || !document.querySelector) {
  639. return;
  640. }
  641. self.Prism.fileHighlight = function() {
  642. var Extensions = {
  643. 'js': 'javascript',
  644. 'py': 'python',
  645. 'rb': 'ruby',
  646. 'ps1': 'powershell',
  647. 'psm1': 'powershell',
  648. 'sh': 'bash',
  649. 'bat': 'batch',
  650. 'h': 'c',
  651. 'tex': 'latex'
  652. };
  653. Array.prototype.slice.call(document.querySelectorAll('pre[data-src]')).forEach(function(pre) {
  654. var src = pre.getAttribute('data-src');
  655. var language, parent = pre;
  656. var lang = /\blang(?:uage)?-([\w-]+)\b/i;
  657. while (parent && !lang.test(parent.className)) {
  658. parent = parent.parentNode;
  659. }
  660. if (parent) {
  661. language = (pre.className.match(lang) || [, ''])[1];
  662. }
  663. if (!language) {
  664. var extension = (src.match(/\.(\w+)$/) || [, ''])[1];
  665. language = Extensions[extension] || extension;
  666. }
  667. var code = document.createElement('code');
  668. code.className = 'language-' + language;
  669. pre.textContent = '';
  670. code.textContent = 'Loading…';
  671. pre.appendChild(code);
  672. var xhr = new XMLHttpRequest();
  673. xhr.open('GET', src, true);
  674. xhr.onreadystatechange = function() {
  675. if (xhr.readyState == 4) {
  676. if (xhr.status < 400 && xhr.responseText) {
  677. code.textContent = xhr.responseText;
  678. Prism.highlightElement(code);
  679. } else if (xhr.status >= 400) {
  680. code.textContent = '✖ Error ' + xhr.status + ' while fetching file: ' + xhr.statusText;
  681. } else {
  682. code.textContent = '✖ Error: File does not exist or is empty';
  683. }
  684. }
  685. };
  686. xhr.send(null);
  687. });
  688. if (Prism.plugins.toolbar) {
  689. Prism.plugins.toolbar.registerButton('download-file', function(env) {
  690. var pre = env.element.parentNode;
  691. if (!pre || !/pre/i.test(pre.nodeName) || !pre.hasAttribute('data-src') || !pre.hasAttribute('data-download-link')) {
  692. return;
  693. }
  694. var src = pre.getAttribute('data-src');
  695. var a = document.createElement('a');
  696. a.textContent = pre.getAttribute('data-download-link-label') || 'Download';
  697. a.setAttribute('download', '');
  698. a.href = src;
  699. return a;
  700. });
  701. }
  702. };
  703. document.addEventListener('DOMContentLoaded', self.Prism.fileHighlight);
  704. })();