suneditor 2.43.8 → 2.43.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "suneditor",
3
- "version": "2.43.8",
3
+ "version": "2.43.9",
4
4
  "description": "Pure JavaScript based WYSIWYG web editor",
5
5
  "author": "JiHong.Lee",
6
6
  "license": "MIT",
@@ -460,6 +460,7 @@ export default {
460
460
  options.toolbarWidth = options.toolbarWidth ? (util.isNumber(options.toolbarWidth) ? options.toolbarWidth + 'px' : options.toolbarWidth) : 'auto';
461
461
  options.toolbarContainer = typeof options.toolbarContainer === 'string' ? document.querySelector(options.toolbarContainer) : options.toolbarContainer;
462
462
  options.stickyToolbar = (/balloon/i.test(options.mode) || !!options.toolbarContainer) ? -1 : options.stickyToolbar === undefined ? 0 : (/^\d+/.test(options.stickyToolbar) ? util.getNumber(options.stickyToolbar, 0) : -1);
463
+ options.hideToolbar = !!options.hideToolbar;
463
464
  options.fullScreenOffset = options.fullScreenOffset === undefined ? 0 : (/^\d+/.test(options.fullScreenOffset) ? util.getNumber(options.fullScreenOffset, 0) : 0);
464
465
  options.fullPage = !!options.fullPage;
465
466
  options.iframe = options.fullPage || !!options.iframe;
@@ -928,6 +929,8 @@ export default {
928
929
  tool_cover.className = 'se-toolbar-cover';
929
930
  tool_bar.appendChild(tool_cover);
930
931
 
932
+ if (options.hideToolbar) tool_bar.style.display = 'none';
933
+
931
934
  return {
932
935
  'element': tool_bar,
933
936
  'plugins': plugins,
package/src/lib/core.js CHANGED
@@ -283,6 +283,7 @@ export default function (context, pluginCallButtons, plugins, lang, options, _re
283
283
  * @private
284
284
  */
285
285
  _attributesWhitelistRegExp: null,
286
+ _attributesWhitelistRegExp_all_data: null,
286
287
 
287
288
  /**
288
289
  * @description Attributes blacklist used by the cleanHTML method
@@ -469,6 +470,14 @@ export default function (context, pluginCallButtons, plugins, lang, options, _re
469
470
  */
470
471
  _styleCommandMap: null,
471
472
 
473
+ /**
474
+ * @private
475
+ */
476
+ _cleanStyleRegExp: {
477
+ span: new _w.RegExp('\s*(font-family|font-size|color|background-color)\s*:[^;]+(?!;)*', 'ig'),
478
+ format: new _w.RegExp('\s*(text-align|margin-left|margin-right)\s*:[^;]+(?!;)*', 'ig')
479
+ },
480
+
472
481
  /**
473
482
  * @description Variables used internally in editor operation
474
483
  * @property {Boolean} isCodeView State of code view
@@ -5093,6 +5102,46 @@ export default function (context, pluginCallButtons, plugins, lang, options, _re
5093
5102
  .replace(this.editorTagsBlacklistRegExp, '');
5094
5103
  },
5095
5104
 
5105
+ _cleanStyle: function (m, v, tagName) {
5106
+ const sv = m.match(/style\s*=\s*(?:"|')[^"']*(?:"|')/);
5107
+ if (sv) {
5108
+ if (!v) v = [];
5109
+ const style = sv[0].replace(/"/g, '').match(this._cleanStyleRegExp[tagName]);
5110
+ if (style) {
5111
+ const allowedStyle = [];
5112
+ for (let i = 0, len = style.length, r; i < len; i++) {
5113
+ r = style[i].match(/(.+)(:)([^:]+$)/);
5114
+ if (r && !/inherit|initial/i.test(r[3])) {
5115
+ const k = util.kebabToCamelCase(r[1].trim());
5116
+ const v = this.wwComputedStyle[k].replace(/"/g, '');
5117
+ const c = r[3].trim();
5118
+ switch (k) {
5119
+ case 'fontFamily':
5120
+ if (!options.plugins.font || options.font.indexOf(c) === -1) continue;
5121
+ break;
5122
+ case 'fontSize':
5123
+ if (!options.plugins.fontSize) continue;
5124
+ break;
5125
+ case 'color':
5126
+ if (!options.plugins.fontColor) continue;
5127
+ break;
5128
+ case 'backgroundColor':
5129
+ if (!options.plugins.hiliteColor) continue;
5130
+ break;
5131
+ }
5132
+
5133
+ if (v !== c) {
5134
+ allowedStyle.push(r[0]);
5135
+ }
5136
+ }
5137
+ }
5138
+ if (allowedStyle.length > 0) v.push('style="' + allowedStyle.join(';') + '"');
5139
+ }
5140
+ }
5141
+
5142
+ return v;
5143
+ },
5144
+
5096
5145
  /**
5097
5146
  * @description Tag and tag attribute check RegExp function. (used by "cleanHTML" and "convertContentsForEditor")
5098
5147
  * @param {Boolean} lowLevelCheck Row level check
@@ -5109,64 +5158,38 @@ export default function (context, pluginCallButtons, plugins, lang, options, _re
5109
5158
 
5110
5159
  // blacklist
5111
5160
  const bAttr = this._attributesTagsBlacklist[tagName];
5161
+ m = m.replace(/\s(?:on[a-z]+)\s*=\s*(")[^"]*\1/ig, '');
5112
5162
  if (bAttr) m = m.replace(bAttr, '');
5113
5163
  else m = m.replace(this._attributesBlacklistRegExp, '');
5114
5164
 
5115
5165
  // whitelist
5116
5166
  const wAttr = this._attributesTagsWhitelist[tagName];
5117
5167
  if (wAttr) v = m.match(wAttr);
5118
- else v = m.match(this._attributesWhitelistRegExp);
5119
-
5120
- // anchor
5121
- if (!lowLevelCheck || /<a\b/i.test(t)) {
5122
- const sv = m.match(/(?:(?:id|name)\s*=\s*(?:"|')[^"']*(?:"|'))/g);
5123
- if (sv) {
5124
- if (!v) v = [];
5125
- v.push(sv[0]);
5126
- }
5127
- }
5168
+ else v = m.match(lowLevelCheck ? this._attributesWhitelistRegExp : this._attributesWhitelistRegExp_all_data);
5128
5169
 
5129
- // span
5130
- if ((!lowLevelCheck || /<span/i.test(t)) && (!v || !/style=/i.test(v.toString()))) {
5131
- const sv = m.match(/style\s*=\s*(?:"|')[^"']*(?:"|')/);
5132
- if (sv) {
5133
- if (!v) v = [];
5134
- const style = sv[0].replace(/&quot;/g, '').match(/\s*(font-family|font-size|color|background-color)\s*:[^;]+(?!;)*/ig);
5135
- if (style) {
5136
- const allowedStyle = [];
5137
- for (let i = 0, len = style.length, r; i < len; i++) {
5138
- r = style[i].match(/(.+)(:)([^:]+$)/);
5139
- if (r && !/inherit|initial/i.test(r[3])) {
5140
- const k = util.kebabToCamelCase(r[1].trim());
5141
- const v = this.wwComputedStyle[k].replace(/"/g, '');
5142
- const c = r[3].trim();
5143
- switch (k) {
5144
- case 'fontFamily':
5145
- if (options.plugins.font ? options.font.indexOf(c) === -1 : true) continue;
5146
- break;
5147
- case 'fontSize':
5148
- if (!options.plugins.fontSize) continue;
5149
- break;
5150
- case 'color':
5151
- if (!options.plugins.fontColor) continue;
5152
- break;
5153
- case 'backgroundColor':
5154
- if (!options.plugins.hiliteColor) continue;
5155
- break;
5156
- }
5157
-
5158
- if (v !== c) {
5159
- allowedStyle.push(r[0]);
5160
- }
5161
- }
5162
- }
5163
- if (allowedStyle.length > 0) v.push('style="' + allowedStyle.join(';') + '"');
5170
+ // attribute
5171
+ if (lowLevelCheck) {
5172
+ if (tagName === 'a') {
5173
+ const sv = m.match(/(?:(?:id|name)\s*=\s*(?:"|')[^"']*(?:"|'))/g);
5174
+ if (sv) {
5175
+ if (!v) v = [];
5176
+ v.push(sv[0]);
5177
+ }
5178
+ } else if (!v || !/style=/i.test(v.toString())) {
5179
+ if (tagName === 'span') {
5180
+ v = this._cleanStyle(m, v, 'span');
5181
+ } else if (/^(P|DIV|H[1-6]|PRE)$/i.test(tagName)) {
5182
+ v = this._cleanStyle(m, v, 'format');
5164
5183
  }
5165
5184
  }
5185
+ } else {
5186
+ const sv = m.match(/style\s*=\s*(?:"|')[^"']*(?:"|')/);
5187
+ if (sv && !v) v = [sv[0]];
5188
+ else if (sv && !v.some(function (v) { return /^style/.test(v.trim()); })) v.push(sv[0]);
5166
5189
  }
5167
5190
 
5168
5191
  // img
5169
- if (/<img/i.test(t)) {
5192
+ if (tagName === 'img') {
5170
5193
  let w = '', h = '';
5171
5194
  const sv = m.match(/style\s*=\s*(?:"|')[^"']*(?:"|')/);
5172
5195
  if (!v) v = [];
@@ -5695,7 +5718,8 @@ export default function (context, pluginCallButtons, plugins, lang, options, _re
5695
5718
  // set whitelist
5696
5719
  const getRegList = function (str, str2) { return !str ? '^' : (str === '*' ? '[a-z-]+' : (!str2 ? str : (str + '|' + str2))); };
5697
5720
  // tags
5698
- const defaultAttr = 'contenteditable|colspan|rowspan|target|href|download|rel|src|alt|class|type|controls|data-format|data-size|data-file-size|data-file-name|data-origin|data-align|data-image-link|data-rotate|data-proportion|data-percentage|origin-size|data-exp|data-font-size';
5721
+ const defaultAttr = 'contenteditable|colspan|rowspan|target|href|download|rel|src|alt|class|type|controls|origin-size';
5722
+ const dataAttr = 'data-format|data-size|data-file-size|data-file-name|data-origin|data-align|data-image-link|data-rotate|data-proportion|data-percentage|data-exp|data-font-size';
5699
5723
  this._allowHTMLComments = options._editorTagsWhitelist.indexOf('//') > -1 || options._editorTagsWhitelist === '*';
5700
5724
  // html check
5701
5725
  this._htmlCheckWhitelistRegExp = new wRegExp('^(' + getRegList(options._editorTagsWhitelist.replace('|//', ''), '') + ')$', 'i');
@@ -5722,7 +5746,8 @@ export default function (context, pluginCallButtons, plugins, lang, options, _re
5722
5746
  }
5723
5747
  }
5724
5748
 
5725
- this._attributesWhitelistRegExp = new wRegExp('\\s(?:' + (allAttr || defaultAttr) + ')' + regEndStr, 'ig');
5749
+ this._attributesWhitelistRegExp = new wRegExp('\\s(?:' + (allAttr || defaultAttr + '|' + dataAttr) + ')' + regEndStr, 'ig');
5750
+ this._attributesWhitelistRegExp_all_data = new wRegExp('\\s(?:' + ((allAttr || defaultAttr) + '|data-[a-z0-9\\-]+') + ')' + regEndStr, 'ig');
5726
5751
  this._attributesTagsWhitelist = tagsAttr;
5727
5752
 
5728
5753
  // blacklist