From e3e504310aae16bd24b5e00e23d0b307aace529f Mon Sep 17 00:00:00 2001 From: "Sam X. Chen" Date: Mon, 22 Jul 2019 13:53:37 -0400 Subject: Add Feature: Comments can be richer (can support some safe HTML tags) --- .meteor/packages | 1 + .meteor/versions | 2 + client/components/main/editor.js | 132 +++++++++++++++++++++++++++++++++++++-- 3 files changed, 129 insertions(+), 6 deletions(-) diff --git a/.meteor/packages b/.meteor/packages index ccbff63d..875b1f98 100644 --- a/.meteor/packages +++ b/.meteor/packages @@ -94,3 +94,4 @@ lamhieu:unblock meteorhacks:aggregate@1.3.0 wekan-markdown konecty:mongo-counter +summernote:summernote diff --git a/.meteor/versions b/.meteor/versions index 13400796..2ca1d706 100644 --- a/.meteor/versions +++ b/.meteor/versions @@ -168,6 +168,7 @@ standard-minifier-css@1.5.3 standard-minifier-js@2.4.1 staringatlights:fast-render@3.2.0 staringatlights:inject-data@2.3.0 +summernote:summernote@0.8.1 tap:i18n@1.8.2 templates:tabs@2.3.0 templating@1.3.2 @@ -175,6 +176,7 @@ templating-compiler@1.3.3 templating-runtime@1.3.2 templating-tools@1.1.2 tracker@1.2.0 +twbs:bootstrap@3.3.6 ui@1.0.13 underscore@1.0.10 url@1.2.0 diff --git a/client/components/main/editor.js b/client/components/main/editor.js index 2824723d..400043f2 100755 --- a/client/components/main/editor.js +++ b/client/components/main/editor.js @@ -1,9 +1,7 @@ Template.editor.onRendered(() => { - const $textarea = this.$('textarea'); - - autosize($textarea); - - $textarea.escapeableTextComplete([ + const textareaSelector = 'textarea'; + const disableRicherEditor = Meteor.settings.public.NO_RICHER_EDITOR; + const mentions = [ // User mentions { match: /\B@([\w.]*)$/, @@ -27,7 +25,129 @@ Template.editor.onRendered(() => { }, index: 1, }, - ]); + ]; + if (!disableRicherEditor) { + const isSmall = Utils.isMiniScreen(); + const toolbar = isSmall + ? [ + ['font', ['bold', 'underline']], + ['fontsize', ['fontsize']], + ['color', ['color']], + ['table', ['table']], + ['view', ['fullscreen']], + ] + : [ + ['style', ['style']], + ['font', ['bold', 'underline', 'clear']], + ['fontsize', ['fontsize']], + ['fontname', ['fontname']], + ['color', ['color']], + ['para', ['ul', 'ol', 'paragraph']], + ['table', ['table']], + //['insert', ['link', 'picture', 'video']], // iframe tag will be sanitized TODO if iframe[class=note-video-clip] can be added into safe list, insert video can be enabled + ['insert', ['link', 'picture']], + ['view', ['fullscreen', 'help']], + ]; + const cleanPastedHTML = function(input) { + const badTags = [ + 'style', + 'script', + 'applet', + 'embed', + 'noframes', + 'noscript', + 'meta', + 'link', + 'button', + 'form', + ].join('|'); + const badPatterns = new RegExp( + `(?:${[ + `<(${badTags})s*[^>][\\s\\S]*?<\\/\\1>`, + `<(${badTags})[^>]*?\\/>`, + ].join('|')})`, + 'gi', + ); + let output = input; + // remove bad Tags + output = output.replace(badPatterns, ''); + // remove attributes ' style="..."' + const badAttributes = new RegExp( + `(?:${[ + 'on\\S+=([\'"]?).*?\\1', + 'href=([\'"]?)javascript:.*?\\2', + 'style=([\'"]?).*?\\3', + 'target=\\S+', + ].join('|')})`, + 'gi', + ); + output = output.replace(badAttributes, ''); + output = output.replace(/(