prism-diff-highlight.js 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990
  1. (function () {
  2. if (typeof Prism === 'undefined') {
  3. return;
  4. }
  5. var LANGUAGE_REGEX = /^diff-([\w-]+)/i;
  6. var HTML_TAG = /<\/?(?!\d)[^\s>\/=$<%]+(?:\s(?:\s*[^\s>\/=]+(?:\s*=\s*(?:"[^"]*"|'[^']*'|[^\s'">=]+(?=[\s>]))|(?=[\s/>])))+)?\s*\/?>/g;
  7. //this will match a line plus the line break while ignoring the line breaks HTML tags may contain.
  8. var HTML_LINE = RegExp(/(?:__|[^\r\n<])*(?:\r\n?|\n|(?:__|[^\r\n<])(?![^\r\n]))/.source.replace(/__/g, function () { return HTML_TAG.source; }), 'gi');
  9. var warningLogged = false;
  10. Prism.hooks.add('before-sanity-check', function (env) {
  11. var lang = env.language;
  12. if (LANGUAGE_REGEX.test(lang) && !env.grammar) {
  13. env.grammar = Prism.languages[lang] = Prism.languages.diff;
  14. }
  15. });
  16. Prism.hooks.add('before-tokenize', function (env) {
  17. if (!warningLogged && !Prism.languages.diff && !Prism.plugins.autoloader) {
  18. warningLogged = true;
  19. console.warn("Prism's Diff Highlight plugin requires the Diff language definition (prism-diff.js)." +
  20. "Make sure the language definition is loaded or use Prism's Autoloader plugin.");
  21. }
  22. var lang = env.language;
  23. if (LANGUAGE_REGEX.test(lang) && !Prism.languages[lang]) {
  24. Prism.languages[lang] = Prism.languages.diff;
  25. }
  26. });
  27. Prism.hooks.add('wrap', function (env) {
  28. var diffLanguage; var diffGrammar;
  29. if (env.language !== 'diff') {
  30. var langMatch = LANGUAGE_REGEX.exec(env.language);
  31. if (!langMatch) {
  32. return; // not a language specific diff
  33. }
  34. diffLanguage = langMatch[1];
  35. diffGrammar = Prism.languages[diffLanguage];
  36. }
  37. var PREFIXES = Prism.languages.diff && Prism.languages.diff.PREFIXES;
  38. // one of the diff tokens without any nested tokens
  39. if (PREFIXES && env.type in PREFIXES) {
  40. /** @type {string} */
  41. var content = env.content.replace(HTML_TAG, ''); // remove all HTML tags
  42. /** @type {string} */
  43. var decoded = content.replace(/&lt;/g, '<').replace(/&amp;/g, '&');
  44. // remove any one-character prefix
  45. var code = decoded.replace(/(^|[\r\n])./g, '$1');
  46. // highlight, if possible
  47. var highlighted;
  48. if (diffGrammar) {
  49. highlighted = Prism.highlight(code, diffGrammar, diffLanguage);
  50. } else {
  51. highlighted = Prism.util.encode(code);
  52. }
  53. // get the HTML source of the prefix token
  54. var prefixToken = new Prism.Token('prefix', PREFIXES[env.type], [/\w+/.exec(env.type)[0]]);
  55. var prefix = Prism.Token.stringify(prefixToken, env.language);
  56. // add prefix
  57. var lines = []; var m;
  58. HTML_LINE.lastIndex = 0;
  59. while ((m = HTML_LINE.exec(highlighted))) {
  60. lines.push(prefix + m[0]);
  61. }
  62. if (/(?:^|[\r\n]).$/.test(decoded)) {
  63. // because both "+a\n+" and "+a\n" will map to "a\n" after the line prefixes are removed
  64. lines.push(prefix);
  65. }
  66. env.content = lines.join('');
  67. if (diffGrammar) {
  68. env.classes.push('language-' + diffLanguage);
  69. }
  70. }
  71. });
  72. }());