From 81509d81f9916b81610e8edbe8fbbc9bee1663a8 Mon Sep 17 00:00:00 2001 From: JiHong88 <0125ses@hanmail.net> Date: Fri, 17 Dec 2021 17:55:44 +0900 Subject: [PATCH] add: #848 options-lineAttrReset --- README.md | 4 ++++ sample/html/options.html | 4 ++++ src/lib/constructor.js | 1 + src/lib/core.js | 40 +++++++++++++++++++++++++++++++- src/options.d.ts | 17 ++++++++++---- test/dev/suneditor_build_test.js | 4 +++- 6 files changed, 64 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 6b1200006..82e5e3d85 100644 --- a/README.md +++ b/README.md @@ -428,6 +428,10 @@ attributesBlacklist : Add attribute blacklist of tags that should be deleted i // Layout------------------------------------------------------------------------------------------------------- mode : The mode of the editor ('classic', 'inline', 'balloon', 'balloon-always'). default: 'classic' {String} rtl : If true, the editor is set to RTL(Right To Left) mode. default: false {Boolean} +lineAttrReset : Deletes other attributes except for the property set at the time of line break. + If there is no value, no all attribute is deleted. default: '' {String} + ex) 'class|style': Attributes other than "class" and "style" are deleted at line break. + '*': All attributes are deleted at line break. toolbarWidth : The width of the toolbar. Applies only when the editor mode is 'inline' or 'balloon' mode. default: 'auto' {Number|String} toolbarContainer: A custom HTML selector placing the toolbar inside. diff --git a/sample/html/options.html b/sample/html/options.html index f2372d41f..cde68adf6 100644 --- a/sample/html/options.html +++ b/sample/html/options.html @@ -134,6 +134,9 @@

--Layout





+ + +



@@ -601,6 +604,7 @@

Applied options

}, mode: modeSelect.options[modeSelect.selectedIndex].value, rtl: document.getElementById('rtl').checked, + lineAttrReset: document.getElementById('lineAttrReset').checked ? document.getElementById('lineAttrReset_value').value : undefined, toolbarWidth: document.getElementById('toolbarWidth').checked ? document.getElementById('toolbarWidth_value').value : undefined, toolbarContainer: document.getElementById('toolbarContainer').checked ? '#custom_toolbar' : undefined, stickyToolbar: document.getElementById('stickyToolbar').checked ? document.getElementById('stickyToolbar_value').value : undefined, diff --git a/src/lib/constructor.js b/src/lib/constructor.js index d62b183f8..56b4217ad 100755 --- a/src/lib/constructor.js +++ b/src/lib/constructor.js @@ -432,6 +432,7 @@ export default { /** Layout */ options.mode = options.mode || 'classic'; // classic, inline, balloon, balloon-always options.rtl = !!options.rtl; + options.lineAttrReset = typeof options.lineAttrReset === 'string' && options.lineAttrReset ? options.lineAttrReset === '*' ? '*' : new RegExp('^(' + options.lineAttrReset + ')$', 'i') : null; options._editableClass = 'sun-editor-editable' + (options.rtl ? ' se-rtl' : ''); options._printClass = typeof options._printClass === 'string' ? options._printClass : null; options.toolbarWidth = options.toolbarWidth ? (util.isNumber(options.toolbarWidth) ? options.toolbarWidth + 'px' : options.toolbarWidth) : 'auto'; diff --git a/src/lib/core.js b/src/lib/core.js index f35aaa98e..df3374134 100755 --- a/src/lib/core.js +++ b/src/lib/core.js @@ -1511,7 +1511,7 @@ export default function (context, pluginCallButtons, plugins, lang, options, _re * @returns {Element} */ appendFormatTag: function (element, formatNode) { - if (!element.parentNode) return null; + if (!element || !element.parentNode) return null; const currentFormatEl = util.getFormatElement(this.getSelectionNode(), null); let oFormat = null; @@ -6789,6 +6789,44 @@ export default function (context, pluginCallButtons, plugins, lang, options, _re temp = !temp ? newFormat.firstChild : temp.appendChild(newFormat.firstChild); core.setRange(temp, 0, temp, 0); + break; + } else if (options.lineAttrReset && formatEl) { + e.preventDefault(); + e.stopPropagation(); + + let newEl; + if (!range.collapsed) { + const isMultiLine = util.getFormatElement(range.startContainer, null) !== util.getFormatElement(range.endContainer, null); + const r = core.removeNode(); + if (isMultiLine) { + newEl = util.getFormatElement(r.container, null); + + if (!r.prevContainer) { + const newFormat = formatEl.cloneNode(false); + newFormat.innerHTML = '
'; + newEl.parentNode.insertBefore(newFormat, newEl); + } else if (newEl !== formatEl && newEl.nextElementSibling === formatEl) { + newEl = formatEl; + } + } else { + newEl = util.splitElement(r.container, r.offset, 0); + } + } else { + newEl = util.splitElement(range.endContainer, range.endOffset, 0); + } + + const resetAttr = options.lineAttrReset === '*' ? null : options.lineAttrReset; + const attrs = newEl.attributes; + let i = 0; + while (attrs[i]) { + if (resetAttr && resetAttr.test(attrs[i].name)) { + i++; + continue; + } + newEl.removeAttribute(attrs[i].name); + } + core.setRange(newEl.firstChild, 0, newEl.firstChild, 0); + break; } diff --git a/src/options.d.ts b/src/options.d.ts index 170a70707..e51146f9c 100644 --- a/src/options.d.ts +++ b/src/options.d.ts @@ -64,6 +64,13 @@ export interface SunEditorOptions { * If true, the editor is set to RTL(Right To Left) mode. */ rtl?: boolean; + /** + * Deletes other attributes except for the property set at the time of line break. + * If there is no value, no all attribute is deleted. + * @example 'class|style': Attributes other than "class" and "style" are deleted at line break. + * '*': All attributes are deleted at line break. + */ + lineAttrReset?: string; /** * Button List */ @@ -318,7 +325,7 @@ export interface SunEditorOptions { imageMultipleFile?: boolean; /** * Define the "accept" attribute of the input. - * ex) "*" or ".jpg, .png .." + * @example "*" or ".jpg, .png .." */ imageAccept?: string; /** @@ -497,9 +504,11 @@ export interface SunEditorOptions { * HR * ===== */ - // Defines the hr items. - // "class" or "style" must be specified. - // EX) [{name: "solid", class: "__se__xxx", style: "border-style: outset;"}] + /** + * Defines the hr items. + * "class" or "style" must be specified. + * @example [{name: "solid", class: "__se__xxx", style: "border-style: outset;"}] + */ hrItems?: { name: string; class?: string; style?: string }[]; /** * Key actions diff --git a/test/dev/suneditor_build_test.js b/test/dev/suneditor_build_test.js index 35dff9d12..b37cf5481 100644 --- a/test/dev/suneditor_build_test.js +++ b/test/dev/suneditor_build_test.js @@ -419,6 +419,7 @@ let ss = window.ss = suneditor.create(document.getElementById('editor1'), { //

SunEditor distributed under the MIT license.
//

// `, + lineAttrReset: '*', alignItems: ['left', 'right', 'center'], value: "ss", linkTargetNewWindow: true, @@ -946,6 +947,7 @@ let s2 = window.s2 = editor.create(document.getElementById('editor2'), { ]], ], plugins: plugins, + // value: 'abc', minHeight : 300, charCounter: true, font: [ @@ -954,7 +956,7 @@ let s2 = window.s2 = editor.create(document.getElementById('editor2'), { ], iframe: true, fullPage: true, - imageMultipleFile: true + imageMultipleFile: true, }); s2.onResizeEditor = (height, prevHeight, core) => {