Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
add: options-addTagsWhitelist, pasteTagsWhitelist,
add: util-createTagsWhitelist,
modify: util-convertContentsForEditor, cleanHTML add whitelist argument
  • Loading branch information
JiHong88 committed Feb 16, 2020
1 parent 1d8f49c commit d9a168d
Show file tree
Hide file tree
Showing 10 changed files with 145 additions and 24 deletions.
8 changes: 8 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -284,6 +284,14 @@ plugins: [
video
] : Plugins array. default: null {Array}

// Tags whitelist--------------------------------------å---------------------------------------------------------
// _defaultTagsWhitelist : 'br|p|div|pre|blockquote|h[1-6]|ol|ul|dl|li|hr|figure|figcaption|img|iframe|audio|video|table|thead|tbody|tr|th|td|a|b|strong|var|i|em|u|ins|s|span|strike|del|sub|sup'
addTagsWhitelist : Add tags to the default tags whitelist of editor. default: '' {String}
ex) 'mark|canvas|label|select|option|input'
// _editorTagsWhitelist : _defaultTagsWhitelist + addTagsWhitelist
pasteTagsWhitelist : Whitelist of tags when pasting. default: _editorTagsWhitelist {String}
ex) 'p|h[1-6]'

// Layout-------------------------------------------------------------------------------------------------------
lang : language object. default : en {Object}
mode : The mode of the editor ('classic', 'inline', 'balloon'). default: 'classic' {String}
Expand Down
10 changes: 10 additions & 0 deletions sample/html/options.html
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,14 @@
<div class="content">
<article class="markdown-body entry-content">
<div style="background-color: #f3f3f3; padding: 4px 20px 20px 20px;">
<h4 style="color: #b94a48;">--Tags whitelist</h4>
<label><input type="checkbox" id="addTagsWhitelist">&nbsp;&nbsp;addTagsWhitelist&nbsp;&nbsp;&nbsp;</label>
<input type="text" id="addTagsWhitelist_value" placeholder="String (mark|canvas|label|select|option|input)" style="width:320px">
<br><br>
<label><input type="checkbox" id="pasteTagsWhitelist">&nbsp;&nbsp;pasteTagsWhitelist</label>
<input type="text" id="pasteTagsWhitelist_value" placeholder="String (p|h[1-4])" style="width:320px">
<br>

<h4 style="color: #b94a48;">--Layout</h4>
<label>mode&nbsp;&nbsp;</label>
<select id="mode">
Expand Down Expand Up @@ -327,6 +335,8 @@ <h2 class="sub-title">Applied options</h2>
imageTable.innerHTML = '';

var options = {
toolbarWidth: document.getElementById('addTagsWhitelist').checked ? document.getElementById('addTagsWhitelist_value').value : undefined,
toolbarWidth: document.getElementById('pasteTagsWhitelist').checked ? document.getElementById('pasteTagsWhitelist_value').value : undefined,
mode: modeSelect.options[modeSelect.selectedIndex].value,
toolbarWidth: document.getElementById('toolbarWidth').checked ? document.getElementById('toolbarWidth_value').value : undefined,
stickyToolbar: document.getElementById('stickyToolbar').checked ? document.getElementById('stickyToolbar_value').value : undefined,
Expand Down
20 changes: 20 additions & 0 deletions sample/html/out/document-editor.html
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,24 @@ <h4 class="name" id="lang"><span class="type-signature"></span>lang<span
<dl class="details"></dl>


<h4 class="name" id="editorTagsWhitelistRegExp"><span class="type-signature"></span>editorTagsWhitelistRegExp<span
class="type-signature"></span></h4>
<div class="description">
Editor tags whitelist (RegExp object)<br>
<a href="./document-util.html#createTagsWhitelist">util.createTagsWhitelist</a>(<span style="color:#d73a49;">options._editorTagsWhitelist</span>)<br>
</div>
<dl class="details"></dl>


<h4 class="name" id="pasteTagsWhitelistRegExp"><span class="type-signature"></span>pasteTagsWhitelistRegExp<span
class="type-signature"></span></h4>
<div class="description">
Tag whitelist when pasting (RegExp object)<br>
<a href="./document-util.html#createTagsWhitelist">util.createTagsWhitelist</a>(<span style="color:#d73a49;">options.pasteTagsWhitelist</span>)
</div>
<dl class="details"></dl>


<h4 class="name" id="context"><span class="type-signature"></span>context {JsonObject}<span
class="type-signature"></span></h4>
<h5 class="subsection-title">Properties:</h5>
Expand Down Expand Up @@ -1882,6 +1900,8 @@ <h3>core</h3>
<li><a href="document-editor.html#pluginCallButtons">pluginCallButtons</a></li>
<li><a href="document-editor.html#initPlugins">initPlugins</a></li>
<li><a href="document-editor.html#lang">lang</a></li>
<li><a href="document-editor.html#editorTagsWhitelistRegExp">editorTagsWhitelistRegExp</a></li>
<li><a href="document-editor.html#pasteTagsWhitelistRegExp">pasteTagsWhitelistRegExp</a></li>
<li><a href="document-editor.html#context">context</a></li>
<li><a href="document-editor.html#submenu">submenu</a></li>
<li><a href="document-editor.html#submenuActiveButton">submenuActiveButton</a></li>
Expand Down
53 changes: 51 additions & 2 deletions sample/html/out/document-util.html
Original file line number Diff line number Diff line change
Expand Up @@ -263,7 +263,7 @@ <h5>Parameters:</h5>
<dl class="details"></dl>


<h4 class="name" id="convertContentsForEditor"><span class="type-signature"></span>convertContentsForEditor<span class="signature">(contents)</span><span
<h4 class="name" id="convertContentsForEditor"><span class="type-signature"></span>convertContentsForEditor<span class="signature">(contents, whitelist)</span><span
class="type-signature"> &rarr; {String}</span></h4>
<div class="description">
Converts contents into a format that can be placed in an editor.
Expand All @@ -285,6 +285,16 @@ <h5>Parameters:</h5>
</td>
<td class="description last">Contents</td>
</tr>
<tr>
<td class="name"><code>whitelist</code></td>
<td class="type">
<span class="param-type">String|RegExp</span>
</td>
<td class="description last">
Regular expression of allowed tags.<br>
RegExp object is create by <a href="#createTagsWhitelist">util.createTagsWhitelist</a> method. (<a href="./document-editor.html#editorTagsWhitelistRegExp">core.editorTagsWhitelistRegExp</a>, <a href="./document-editor.html#pasteTagsWhitelistRegExp">core.pasteTagsWhitelistRegExp</a>)
</td>
</tr>
</tbody>
</table>
<dl class="details"></dl>
Expand Down Expand Up @@ -1712,7 +1722,7 @@ <h5>Parameters:</h5>
<dl class="details"></dl>


<h4 class="name" id="cleanHTML"><span class="type-signature"></span>cleanHTML<span class="signature">(html)</span><span
<h4 class="name" id="cleanHTML"><span class="type-signature"></span>cleanHTML<span class="signature">(html, whitelist)</span><span
class="type-signature"> &rarr; {String}</span></h4>
<div class="description">
Gets the clean HTML code for editor
Expand All @@ -1734,6 +1744,44 @@ <h5>Parameters:</h5>
</td>
<td class="description last">HTML string</td>
</tr>
<tr>
<td class="name"><code>whitelist</code></td>
<td class="type">
<span class="param-type">String|RegExp</span>
</td>
<td class="description last">
Regular expression of allowed tags.<br>
RegExp object is create by <a href="#createTagsWhitelist">util.createTagsWhitelist</a> method. (<a href="./document-editor.html#editorTagsWhitelistRegExp">core.editorTagsWhitelistRegExp</a>, <a href="./document-editor.html#pasteTagsWhitelistRegExp">core.pasteTagsWhitelistRegExp</a>)
</td>
</tr>
</tbody>
</table>
<dl class="details"></dl>


<h4 class="name" id="createTagsWhitelist"><span class="type-signature"></span>createTagsWhitelist<span class="signature">(list)</span><span
class="type-signature"> &rarr; {RegExp}</span></h4>
<div class="description">
Create whitelist RegExp object.<br>
Return RegExp format: new RegExp("<span style="color:#d73a49">&lt;\\/?(</span><span style="color: #23853a;"><i style="font-size: 10px;">Loop</i>(</span><span style="color:#0a3667">?!\\b<span style="color: #23853a;">list[i]</span>\\b</span><span style="color: #23853a;">)</span><span style="color:#d73a49">)[^>^&gt;])+></span>", "<span style="color:#d73a49">g</span>")
</div>
<h5>Parameters:</h5>
<table class="params">
<thead>
<tr>
<th>Name</th>
<th>Type</th>
<th class="last">Description</th>
</tr>
</thead>
<tbody>
<tr>
<td class="name"><code>list</code></td>
<td class="type">
<span class="param-type">String</span>
</td>
<td class="description last">Tags list ("br|p|div|pre...")</td>
</tr>
</tbody>
</table>
<dl class="details"></dl>
Expand Down Expand Up @@ -1805,6 +1853,7 @@ <h3>util</h3>
<li><a href="document-util.html#removeItemAllParents">removeItemAllParents</a></li>
<li><a href="document-util.html#removeEmptyNode">removeEmptyNode</a></li>
<li><a href="document-util.html#cleanHTML">cleanHTML</a></li>
<li><a href="document-util.html#createTagsWhitelist">createTagsWhitelist</a></li>
</ul>
</nav>

Expand Down
5 changes: 4 additions & 1 deletion src/lib/constructor.js
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ export default {
editor_div.className = 'se-wrapper';

/** --- init elements and create bottom bar --- */
const initHTML = util.convertContentsForEditor(element.value);
const initHTML = util.convertContentsForEditor(element.value, options._editorTagsWhitelist);
const initElements = this._initElements(options, top_div, tool_bar.element, arrow, initHTML);

const bottomBar = initElements.bottomBar;
Expand Down Expand Up @@ -365,6 +365,9 @@ export default {
_initOptions: function (element, options) {
/** user options */
options.lang = options.lang || _defaultLang;
options._defaultTagsWhitelist = typeof options._defaultTagsWhitelist === 'string' ? options._defaultTagsWhitelist : 'br|p|div|pre|blockquote|h[1-6]|ol|ul|dl|li|hr|figure|figcaption|img|iframe|audio|video|table|thead|tbody|tr|th|td|a|b|strong|var|i|em|u|ins|s|span|strike|del|sub|sup';
options._editorTagsWhitelist = options._defaultTagsWhitelist + (typeof options.addTagsWhitelist === 'string' && options.addTagsWhitelist.length > 0 ? '|' + options.addTagsWhitelist : '');
options.pasteTagsWhitelist = typeof options.pasteTagsWhitelist === 'string' ? options.pasteTagsWhitelist : options._editorTagsWhitelist;
/** Layout */
options.mode = options.mode || 'classic'; // classic, inline, balloon
options.toolbarWidth = options.toolbarWidth ? (util.isNumber(options.toolbarWidth) ? options.toolbarWidth + 'px' : options.toolbarWidth) : 'auto';
Expand Down
1 change: 1 addition & 0 deletions src/lib/context.js
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ const _Context = function (element, cons, options) {
save: cons._toolBar.querySelector('._se_command_save'),
outdent: cons._toolBar.querySelector('._se_command_outdent')
},
options: options,
option: options
};
};
Expand Down
36 changes: 29 additions & 7 deletions src/lib/core.js
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,18 @@ export default function (context, pluginCallButtons, plugins, lang, _options) {
*/
history: null,

/**
* @description Editor tags whitelist (RegExp object)
* util.createTagsWhitelist(options._editorTagsWhitelist)
*/
editorTagsWhitelistRegExp: null,

/**
* @description Tag whitelist when pasting (RegExp object)
* util.createTagsWhitelist(options.pasteTagsWhitelist)
*/
pasteTagsWhitelistRegExp: null,

/**
* @description binded controllersOff method
* @private
Expand Down Expand Up @@ -2920,15 +2932,15 @@ export default function (context, pluginCallButtons, plugins, lang, _options) {
}

this._wd.head.innerHTML = parseDocument.head.innerHTML;
this._wd.body.innerHTML = util.convertContentsForEditor(parseDocument.body.innerHTML);
this._wd.body.innerHTML = util.convertContentsForEditor(parseDocument.body.innerHTML, this.editorTagsWhitelistRegExp);

const attrs = parseDocument.body.attributes;
for (let i = 0, len = attrs.length; i < len; i++) {
if (attrs[i].name === 'contenteditable') continue;
this._wd.body.setAttribute(attrs[i].name, attrs[i].value);
}
} else {
context.element.wysiwyg.innerHTML = code_html.length > 0 ? util.convertContentsForEditor(code_html) : '<p><br></p>';
context.element.wysiwyg.innerHTML = code_html.length > 0 ? util.convertContentsForEditor(code_html, this.editorTagsWhitelistRegExp) : '<p><br></p>';
}
},

Expand Down Expand Up @@ -3142,7 +3154,7 @@ export default function (context, pluginCallButtons, plugins, lang, _options) {
* @param {String} html HTML string
*/
setContents: function (html) {
const convertValue = util.convertContentsForEditor(html);
const convertValue = util.convertContentsForEditor(html, this.editorTagsWhitelistRegExp);
this._resetComponents();

if (!core._variable.isCodeView) {
Expand Down Expand Up @@ -3331,6 +3343,9 @@ export default function (context, pluginCallButtons, plugins, lang, _options) {
if (typeof userFunction.onload === 'function') return userFunction.onload(core, reload);
}.bind(this));

this.editorTagsWhitelistRegExp = util.createTagsWhitelist(context.option._editorTagsWhitelist);
this.pasteTagsWhitelistRegExp = util.createTagsWhitelist(context.option.pasteTagsWhitelist);

this.codeViewDisabledButtons = context.element.toolbar.querySelectorAll('.se-toolbar button:not([class~="code-view-enabled"])');
this._isInline = /inline/i.test(context.option.mode);
this._isBalloon = /balloon/i.test(context.option.mode);
Expand Down Expand Up @@ -4375,7 +4390,7 @@ export default function (context, pluginCallButtons, plugins, lang, _options) {
if (!clipboardData) return true;

const maxCharCount = core._charCount(clipboardData.getData('text/plain').length, true);
const cleanData = util.cleanHTML(clipboardData.getData('text/html'));
const cleanData = util.cleanHTML(clipboardData.getData('text/html'), core.pasteTagsWhitelistRegExp);

if (typeof userFunction.onPaste === 'function' && !userFunction.onPaste(e, cleanData, maxCharCount, core)) {
e.preventDefault();
Expand Down Expand Up @@ -4432,7 +4447,7 @@ export default function (context, pluginCallButtons, plugins, lang, _options) {
return false;
// html paste
} else {
const cleanData = util.cleanHTML(dataTransfer.getData('text/html'));
const cleanData = util.cleanHTML(dataTransfer.getData('text/html'), core.pasteTagsWhitelistRegExp);
if (cleanData) {
event._setDropLocationSelection(e);
core.execCommand('insertHTML', false, cleanData);
Expand Down Expand Up @@ -4745,10 +4760,17 @@ export default function (context, pluginCallButtons, plugins, lang, _options) {
* @param {String} contents Contents to Input
*/
appendContents: function (contents) {
const convertValue = util.convertContentsForEditor(contents);
const convertValue = util.convertContentsForEditor(contents, this.editorTagsWhitelistRegExp);

if (!core._variable.isCodeView) {
context.element.wysiwyg.innerHTML += convertValue;
const temp = util.createElement('DIV');
temp.innerHTML = convertValue;

const wysiwyg = context.element.wysiwyg;
const children = temp.children;
for (let i = 0, len = children.length; i < len; i++) {
wysiwyg.appendChild(children[i]);
}
} else {
core._setCodeView(core._getCodeView() + '\n' + util.convertHTMLForCodeView(convertValue, core._variable.codeIndent));
}
Expand Down
27 changes: 16 additions & 11 deletions src/lib/util.js
Original file line number Diff line number Diff line change
Expand Up @@ -212,9 +212,11 @@ const util = {
/**
* @description Converts contents into a format that can be placed in an editor
* @param {String} contents contents
* @param {String|RegExp} whitelist Regular expression of allowed tags.
* RegExp object is create by util.createTagsWhitelist method. (core.editorTagsWhitelistRegExp, core.pasteTagsWhitelistRegExp)
* @returns {String}
*/
convertContentsForEditor: function (contents) {
convertContentsForEditor: function (contents, whitelist) {
let returnHTML = '';
let tag = this._d.createRange().createContextualFragment(contents).childNodes;

Expand All @@ -238,7 +240,7 @@ const util = {
returnHTML = '<p>' + (contents.length > 0 ? contents : '<br>') + '</p>';
}

return this._tagConvertor(returnHTML.replace(this._deleteExclusionTags, ''));
return this._tagConvertor(!whitelist ? returnHTML : returnHTML.replace(typeof whitelist === 'string' ? this.createTagsWhitelist(whitelist) : whitelist, ''));
},

/**
Expand Down Expand Up @@ -1066,9 +1068,11 @@ const util = {
/**
* @description Gets the clean HTML code for editor
* @param {String} html HTML string
* @param {String|RegExp} whitelist Regular expression of allowed tags.
* RegExp object is create by util.createTagsWhitelist method. (core.editorTagsWhitelistRegExp, core.pasteTagsWhitelistRegExp)
* @returns {String}
*/
cleanHTML: function (html) {
cleanHTML: function (html, whitelist) {
const tagsAllowed = new this._w.RegExp('^(meta|script|link|style|[a-z]+\:[a-z]+)$', 'i');
const domTree = this._d.createRange().createContextualFragment(html).childNodes;
let cleanHTML = '';
Expand All @@ -1091,10 +1095,9 @@ const util = {
}
return t;
})
.replace(/<\/?(span[^>^<]*)>/g, '')
.replace(this._deleteExclusionTags, '');
.replace(/<\/?(span[^>^<]*)>/g, '');

return this._tagConvertor(cleanHTML || html);
return this._tagConvertor(!cleanHTML ? html : !whitelist ? cleanHTML : cleanHTML.replace(typeof whitelist === 'string' ? this.createTagsWhitelist(whitelist) : whitelist, ''));
},

/**
Expand Down Expand Up @@ -1128,12 +1131,14 @@ const util = {
},

/**
* @description Delete Exclusion tags regexp object
* @returns {Object}
* @description Create whitelist RegExp object.
* Return RegExp format: new RegExp("<\\/?(" + (?!\\b list[i] \\b) + ")[^>^<])+>", "g")
* @param {String} list Tags list ("br|p|div|pre...")
* @returns {RegExp}
* @private
*/
_deleteExclusionTags: (function () {
const exclusionTags = 'br|p|div|pre|blockquote|h[1-6]|ol|ul|dl|li|hr|figure|figcaption|img|iframe|audio|video|table|thead|tbody|tr|th|td|a|b|strong|var|i|em|u|ins|s|span|strike|del|sub|sup|mark|canvas|label|select|option|input'.split('|');
createTagsWhitelist: function (list) {
const exclusionTags = list.split('|');
let regStr = '<\\/?(';

for (let i = 0, len = exclusionTags.length; i < len; i++) {
Expand All @@ -1143,7 +1148,7 @@ const util = {
regStr += '[^>^<])+>';

return new RegExp(regStr, 'g');
})()
}
};

export default util;
Loading

0 comments on commit d9a168d

Please sign in to comment.