prism-autolinker.js 1.8 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576
  1. (function () {
  2. if (typeof Prism === 'undefined') {
  3. return;
  4. }
  5. var url = /\b([a-z]{3,7}:\/\/|tel:)[\w\-+%~/.:=&!$'()*,;@]+(?:\?[\w\-+%~/.:=?&!$'()*,;@]*)?(?:#[\w\-+%~/.:#=?&!$'()*,;@]*)?/;
  6. var email = /\b\S+@[\w.]+[a-z]{2}/;
  7. var linkMd = /\[([^\]]+)\]\(([^)]+)\)/;
  8. // Tokens that may contain URLs and emails
  9. var candidates = ['comment', 'url', 'attr-value', 'string'];
  10. Prism.plugins.autolinker = {
  11. processGrammar: function (grammar) {
  12. // Abort if grammar has already been processed
  13. if (!grammar || grammar['url-link']) {
  14. return;
  15. }
  16. Prism.languages.DFS(grammar, function (key, def, type) {
  17. if (candidates.indexOf(type) > -1 && !Array.isArray(def)) {
  18. if (!def.pattern) {
  19. def = this[key] = {
  20. pattern: def
  21. };
  22. }
  23. def.inside = def.inside || {};
  24. if (type == 'comment') {
  25. def.inside['md-link'] = linkMd;
  26. }
  27. if (type == 'attr-value') {
  28. Prism.languages.insertBefore('inside', 'punctuation', { 'url-link': url }, def);
  29. } else {
  30. def.inside['url-link'] = url;
  31. }
  32. def.inside['email-link'] = email;
  33. }
  34. });
  35. grammar['url-link'] = url;
  36. grammar['email-link'] = email;
  37. }
  38. };
  39. Prism.hooks.add('before-highlight', function (env) {
  40. Prism.plugins.autolinker.processGrammar(env.grammar);
  41. });
  42. Prism.hooks.add('wrap', function (env) {
  43. if (/-link$/.test(env.type)) {
  44. env.tag = 'a';
  45. var href = env.content;
  46. if (env.type == 'email-link' && href.indexOf('mailto:') != 0) {
  47. href = 'mailto:' + href;
  48. } else if (env.type == 'md-link') {
  49. // Markdown
  50. var match = env.content.match(linkMd);
  51. href = match[2];
  52. env.content = match[1];
  53. }
  54. env.attributes.href = href;
  55. // Silently catch any error thrown by decodeURIComponent (#1186)
  56. try {
  57. env.content = decodeURIComponent(env.content);
  58. } catch (e) { /* noop */ }
  59. }
  60. });
  61. }());