summernote-cleaner.js (11089B)
1 /* https://github.com/DiemenDesign/summernote-cleaner */ 2 (function (factory) { 3 if (typeof define === 'function' && define.amd) { 4 define(['jquery'], factory); 5 } else if (typeof module === 'object' && module.exports) { 6 module.exports = factory(require('jquery')); 7 } else { 8 factory(window.jQuery); 9 } 10 } 11 (function ($) { 12 $.extend(true, $.summernote.lang, { 13 'en-US': { 14 cleaner: { 15 tooltip: 'Cleaner', 16 not: 'Text has been Cleaned!!!', 17 limitText: 'Text', 18 limitHTML: 'HTML' 19 } 20 } 21 }); 22 $.extend($.summernote.options, { 23 cleaner: { 24 action: 'both', // both|button|paste 'button' only cleans via toolbar button, 'paste' only clean when pasting content, both does both options. 25 newline: '<br>', // Summernote's default is to use '<p><br></p>' 26 notStyle: 'position:absolute;top:0;left:0;right:0', 27 icon: '<i class="note-icon"><svg xmlns="http://www.w3.org/2000/svg" id="libre-paintbrush" viewBox="0 0 14 14" width="14" height="14"><path d="m 11.821425,1 q 0.46875,0 0.82031,0.311384 0.35157,0.311384 0.35157,0.780134 0,0.421875 -0.30134,1.01116 -2.22322,4.212054 -3.11384,5.035715 -0.64956,0.609375 -1.45982,0.609375 -0.84375,0 -1.44978,-0.61942 -0.60603,-0.61942 -0.60603,-1.469866 0,-0.857143 0.61608,-1.419643 l 4.27232,-3.877232 Q 11.345985,1 11.821425,1 z m -6.08705,6.924107 q 0.26116,0.508928 0.71317,0.870536 0.45201,0.361607 1.00781,0.508928 l 0.007,0.475447 q 0.0268,1.426339 -0.86719,2.32366 Q 5.700895,13 4.261155,13 q -0.82366,0 -1.45982,-0.311384 -0.63616,-0.311384 -1.0212,-0.853795 -0.38505,-0.54241 -0.57924,-1.225446 -0.1942,-0.683036 -0.1942,-1.473214 0.0469,0.03348 0.27455,0.200893 0.22768,0.16741 0.41518,0.29799 0.1875,0.130581 0.39509,0.24442 0.20759,0.113839 0.30804,0.113839 0.27455,0 0.3683,-0.247767 0.16741,-0.441965 0.38505,-0.753349 0.21763,-0.311383 0.4654,-0.508928 0.24776,-0.197545 0.58928,-0.31808 0.34152,-0.120536 0.68974,-0.170759 0.34821,-0.05022 0.83705,-0.07031 z"/></svg></i>', 28 keepHtml: true, //Remove all Html formats 29 keepOnlyTags: [], // If keepHtml is true, remove all tags except these 30 keepClasses: false, //Remove Classes 31 badTags: ['style', 'script', 'applet', 'embed', 'noframes', 'noscript', 'html'], //Remove full tags with contents 32 badAttributes: ['style', 'start'], //Remove attributes from remaining tags 33 limitChars: 520, // 0|# 0 disables option 34 limitDisplay: 'both', // none|text|html|both 35 limitStop: false // true/false 36 } 37 }); 38 $.extend($.summernote.plugins, { 39 'cleaner':function (context) { 40 var self = this, 41 ui = $.summernote.ui, 42 $note = context.layoutInfo.note, 43 $editor = context.layoutInfo.editor, 44 options = context.options, 45 lang = options.langInfo; 46 var cleanText = function (txt, nlO) { 47 var out = txt; 48 if (!options.cleaner.keepClasses) { 49 var sS = /(\n|\r| class=(")?Mso[a-zA-Z]+(")?)/g; 50 out = txt.replace(sS, ' '); 51 } 52 var nL = /(\n)+/g; 53 out = out.replace(nL, nlO); 54 if (options.cleaner.keepHtml) { 55 var cS = new RegExp('<!--(.*?)-->', 'gi'); 56 out = out.replace(cS, ''); 57 var tS = new RegExp('<(/)*(meta|link|\\?xml:|st1:|o:|font)(.*?)>', 'gi'); 58 out = out.replace(tS, ''); 59 var bT = options.cleaner.badTags; 60 for (var i = 0; i < bT.length; i++) { 61 tS = new RegExp('<' + bT[i] + '\\b.*>.*</' + bT[i] + '>', 'gi'); 62 out = out.replace(tS, ''); 63 } 64 var allowedTags = options.cleaner.keepOnlyTags; 65 if (typeof(allowedTags) == "undefined") allowedTags = []; 66 if (allowedTags.length > 0) { 67 allowedTags = (((allowedTags||'') + '').toLowerCase().match(/<[a-z][a-z0-9]*>/g) || []).join(''); 68 var tags = /<\/?([a-z][a-z0-9]*)\b[^>]*>/gi; 69 out = out.replace(tags, function($0, $1) { 70 return allowedTags.indexOf('<' + $1.toLowerCase() + '>') > -1 ? $0 : '' 71 }); 72 } 73 var bA = options.cleaner.badAttributes; 74 for (var ii = 0; ii < bA.length; ii++ ) { 75 //var aS=new RegExp(' ('+bA[ii]+'="(.*?)")|('+bA[ii]+'=\'(.*?)\')', 'gi'); 76 var aS = new RegExp(' ' + bA[ii] + '=[\'|"](.*?)[\'|"]', 'gi'); 77 out = out.replace(aS, ''); 78 } 79 } 80 return out; 81 }; 82 if (options.cleaner.action == 'both' || options.cleaner.action == 'button') { 83 context.memo('button.cleaner', function () { 84 var button = ui.button({ 85 contents: options.cleaner.icon, 86 tooltip: lang.cleaner.tooltip, 87 container: 'body', 88 click:function () { 89 if ($note.summernote('createRange').toString()) 90 $note.summernote('pasteHTML', $note.summernote('createRange').toString()); 91 else 92 $note.summernote('code', cleanText($note.summernote('code'))); 93 if ($editor.find('.note-status-output').length > 0) 94 $editor.find('.note-status-output').html('<div class="alert alert-success">' + lang.cleaner.not + '</div>'); 95 else 96 $editor.find('.note-editing-area').append('<div class="alert alert-success" style="' + options.cleaner.notStyle + '">' + lang.cleaner.not + '</div>'); 97 } 98 }); 99 return button.render(); 100 }); 101 } 102 this.events = { 103 'summernote.init':function () { 104 if ($editor.find('.note-status-output').length < 1) { 105 $editor.find('.note-statusbar').prepend('<output class="note-status-output"></output>'); 106 $("head").append('<style>.note-statusbar .note-status-output{display:block;padding-top:7px;width:100%;font-size:14px;line-height:1.42857143;height:25px;color:#000}.note-statusbar .pull-right{float:right!important}.note-statusbar .note-status-output .text-muted{color:#777}.note-statusbar .note-status-output .text-primary{color:#286090}.note-statusbar .note-status-output .text-success{color:#3c763d}.note-statusbar .note-status-output .text-info{color:#31708f}.note-statusbar .note-status-output .text-warning{color:#8a6d3b}.note-statusbar .note-status-output .text-danger{color:#a94442}.note-statusbar .alert{margin:-7px 0 0 0;padding:2px 10px;border:1px solid transparent;border-radius:0}.note-statusbar .alert .note-icon{margin-right:5px}.note-statusbar .alert-success{color:#3c763d!important;background-color: #dff0d8 !important;border-color:#d6e9c6}.note-statusbar .alert-info{color:#31708f;background-color:#d9edf7;border-color:#bce8f1}.note-statusbar .alert-warning{color:#8a6d3b;background-color:#fcf8e3;border-color:#faebcc}.note-statusbar .alert-danger{color:#a94442;background-color:#f2dede;border-color:#ebccd1}</style>'); 107 } 108 if (options.cleaner.limitChars != 0 || options.cleaner.limitDisplay != 'none') { 109 var textLength = $editor.find(".note-editable").text().replace(/(<([^>]+)>)/ig, "").replace(/( )/, " "); 110 var codeLength = $editor.find('.note-editable').html(); 111 var lengthStatus = ''; 112 if (textLength.length > options.cleaner.limitChars && options.cleaner.limitChars > 0) 113 lengthStatus += 'text-danger">'; 114 else 115 lengthStatus += '">'; 116 if (options.cleaner.limitDisplay == 'text' || options.cleaner.limitDisplay == 'both') lengthStatus += lang.cleaner.limitText + ': ' + textLength.length; 117 if (options.cleaner.limitDisplay == 'both') lengthStatus += ' / '; 118 if (options.cleaner.limitDisplay == 'html' || options.cleaner.limitDisplay == 'both') lengthStatus += lang.cleaner.limitHTML + ': ' + codeLength.length; 119 $editor.find('.note-status-output').html('<small class="pull-right ' + lengthStatus + ' </small>'); 120 } 121 }, 122 'summernote.keydown':function (we, e) { 123 if (options.cleaner.limitChars != 0 || options.cleaner.limitDisplay != 'none') { 124 var textLength = $editor.find(".note-editable").text().replace(/(<([^>]+)>)/ig, "").replace(/( )/, " "); 125 var codeLength = $editor.find('.note-editable').html(); 126 var lengthStatus = ''; 127 if (options.cleaner.limitStop == true && textLength.length >= options.cleaner.limitChars) { 128 var key = e.keyCode; 129 allowed_keys = [8, 37, 38, 39, 40, 46] 130 if ($.inArray(key, allowed_keys) != -1) { 131 $editor.find('.cleanerLimit').removeClass('text-danger'); 132 return true; 133 } else { 134 $editor.find('.cleanerLimit').addClass('text-danger'); 135 e.preventDefault(); 136 e.stopPropagation(); 137 } 138 } else { 139 if (textLength.length > options.cleaner.limitChars && options.cleaner.limitChars > 0) 140 lengthStatus += 'text-danger">'; 141 else 142 lengthStatus += '">'; 143 if (options.cleaner.limitDisplay == 'text' || options.cleaner.limitDisplay == 'both') 144 lengthStatus += lang.cleaner.limitText + ': ' + textLength.length; 145 if (options.cleaner.limitDisplay == 'both') 146 lengthStatus += ' / '; 147 if (options.cleaner.limitDisplay == 'html' || options.cleaner.limitDisplay == 'both') 148 lengthStatus += lang.cleaner.limitHTML + ': ' + codeLength.length; 149 $editor.find('.note-status-output').html('<small class="cleanerLimit pull-right ' + lengthStatus + ' </small>'); 150 } 151 } 152 }, 153 'summernote.paste':function (we, e) { 154 if (options.cleaner.action == 'both' || options.cleaner.action == 'paste') { 155 e.preventDefault(); 156 var ua = window.navigator.userAgent; 157 var msie = ua.indexOf("MSIE "); 158 msie = msie > 0 || !!navigator.userAgent.match(/Trident.*rv\:11\./); 159 var ffox = navigator.userAgent.toLowerCase().indexOf('firefox') > -1; 160 if (msie) 161 var text = window.clipboardData.getData("Text"); 162 else 163 var text = e.originalEvent.clipboardData.getData(options.cleaner.keepHtml ? 'Text' : 'text/plain'); 164 if (text) { 165 if (msie || ffox) 166 setTimeout(function(){$note.summernote('pasteHTML', cleanText(text, options.cleaner.newline));}, 1); 167 else 168 $note.summernote('pasteHTML', cleanText(text, options.cleaner.newline)); 169 if ($editor.find('.note-status-output').length > 0) 170 $editor.find('.note-status-output').html('<div class="summernote-cleanerAlert alert alert-success">' + lang.cleaner.not + '</div>'); 171 else 172 $editor.find('.note-resizebar').append('<div class="summernote-cleanerAlert alert alert-success" style="' + options.cleaner.notStyle + '">' + lang.cleaner.not + '</div>'); 173 } 174 } 175 } 176 } 177 } 178 }); 179 }));