暫無描述
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

prism.js 21KB

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