template-integration.js 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118
  1. import DOMPurify from 'dompurify';
  2. var Markdown = require('markdown-it')({
  3. html: true,
  4. linkify: true,
  5. typographer: true,
  6. breaks: true,
  7. });
  8. import markdownItMermaid from "@liradb2000/markdown-it-mermaid";
  9. // Static URL Scheme Listing
  10. var urlschemes = [
  11. "aodroplink",
  12. "thunderlink",
  13. "cbthunderlink",
  14. "onenote",
  15. "file",
  16. "abasurl",
  17. "conisio",
  18. "mailspring"
  19. ];
  20. // Better would be a field in the admin backend to set this dynamically
  21. // instead of putting all known or wanted url schemes here hard into code
  22. // but i was not able to access those settings
  23. // var urlschemes = currentSetting.automaticLinkedUrlSchemes.split('\n');
  24. // put all url schemes into the linkify configuration to automatically make it clickable
  25. for(var i=0; i<urlschemes.length;i++){
  26. //console.log("adding autolink for "+urlschemes[i]);
  27. Markdown.linkify.add(urlschemes[i]+":",'http:');
  28. }
  29. // build fitting regex
  30. var regex = RegExp('^(' + urlschemes.join('|') + '):', 'gim');
  31. // Add a hook to enforce URI scheme allow-list
  32. DOMPurify.addHook('afterSanitizeAttributes', function (node) {
  33. // build an anchor to map URLs to
  34. var anchor = document.createElement('a');
  35. // check all href attributes for validity
  36. if (node.hasAttribute('href')) {
  37. anchor.href = node.getAttribute('href');
  38. if (anchor.protocol && !anchor.protocol.match(regex)) {
  39. node.removeAttribute('href');
  40. }
  41. }
  42. // check all action attributes for validity
  43. if (node.hasAttribute('action')) {
  44. anchor.href = node.getAttribute('action');
  45. if (anchor.protocol && !anchor.protocol.match(regex)) {
  46. node.removeAttribute('action');
  47. }
  48. }
  49. // check all xlink:href attributes for validity
  50. if (node.hasAttribute('xlink:href')) {
  51. anchor.href = node.getAttribute('xlink:href');
  52. if (anchor.protocol && !anchor.protocol.match(regex)) {
  53. node.removeAttribute('xlink:href');
  54. }
  55. }
  56. });
  57. /*
  58. // Additional safeAttrValue function to allow for other specific protocols
  59. // See https://github.com/leizongmin/js-xss/issues/52#issuecomment-241354114
  60. function mySafeAttrValue(tag, name, value, cssFilter) {
  61. // only when the tag is 'a' and attribute is 'href'
  62. // then use your custom function
  63. if (tag === 'a' && name === 'href') {
  64. // only filter the value if starts with an registered url scheme
  65. urlscheme = value.split(/:/);
  66. //console.log("validating "+urlscheme[0]);
  67. if(urlschemes.includes(urlscheme[0])) return value;
  68. else {
  69. // use the default safeAttrValue function to process all non cbthunderlinks
  70. return sanitizeXss.safeAttrValue(tag, name, value, cssFilter);
  71. }
  72. // } else if (tag === 'svg') {
  73. // return `<img src="data:image/svg+xml;base64,` + atob(value) + `"></img>`;
  74. } else {
  75. // use the default safeAttrValue function to process it
  76. return sanitizeXss.safeAttrValue(tag, name, value, cssFilter);
  77. }
  78. };
  79. */
  80. var emoji = require('markdown-it-emoji');
  81. Markdown.use(emoji);
  82. Markdown.use(markdownItMermaid);
  83. if (Package.ui) {
  84. const Template = Package.templating.Template;
  85. const UI = Package.ui.UI;
  86. const HTML = Package.htmljs.HTML;
  87. const Blaze = Package.blaze.Blaze; // implied by `ui`
  88. UI.registerHelper('markdown', new Template('markdown', function () {
  89. const self = this;
  90. let text = '';
  91. if (self.templateContentBlock) {
  92. text = Blaze._toText(self.templateContentBlock, HTML.TEXTMODE.STRING);
  93. }
  94. return HTML.Raw(DOMPurify.sanitize(Markdown.render(text), {ALLOW_UNKNOWN_PROTOCOLS: true}));
  95. }));
  96. }