2323 * mediator.exec('format:clean', elem); // Clean the HTML inside elem
2424 */
2525import Module from '../core/Module' ;
26- import commands from '../utils/commands' ;
2726import DOM from '../utils/DOM' ;
2827import zeroWidthSpace from '../utils/zeroWidthSpace' ;
2928
30- import toolbarConfig from '../config/toolbar' ;
31-
32- let validTags = toolbarConfig . getValidTags ( ) ;
33- let blockTags = toolbarConfig . getBlockTags ( ) ;
34- let listTags = toolbarConfig . getListTags ( ) ;
29+ let validTags , blockTags , listTags ;
3530
3631const BaseFormatter = Module ( {
3732 name : 'BaseFormatter' ,
@@ -49,7 +44,12 @@ const BaseFormatter = Module({
4944 }
5045 } ,
5146 methods : {
52- init ( ) { } ,
47+ init ( ) {
48+ const { mediator } = this ;
49+ validTags = mediator . get ( 'config:toolbar:validTags' ) ;
50+ blockTags = mediator . get ( 'config:toolbar:blockTags' ) ;
51+ listTags = mediator . get ( 'config:toolbar:listTags' ) ;
52+ } ,
5353
5454 /**
5555 * @func exportToCanvas
@@ -64,10 +64,7 @@ const BaseFormatter = Module({
6464 this . injectHooks ( rootElement ) ;
6565
6666 const rangeCoordinates = mediator . get ( 'selection:range:coordinates' ) ;
67- const clonedNodes = this . cloneNodes ( rootElement ) ;
68- clonedNodes . forEach ( ( node ) => {
69- DOM . trimNodeText ( node ) ;
70- } ) ;
67+ const clonedNodes = DOM . cloneNodes ( rootElement , { trim : true } ) ;
7168
7269 mediator . exec ( 'canvas:content' , clonedNodes ) ;
7370 mediator . exec ( 'canvas:select:by:coordinates' , rangeCoordinates ) ;
@@ -109,7 +106,7 @@ const BaseFormatter = Module({
109106 formatDefault ( ) {
110107 const { mediator } = this ;
111108 const rootElem = mediator . get ( 'selection:rootelement' ) ;
112- commands . defaultBlockFormat ( ) ;
109+ mediator . exec ( 'commands:format:default' ) ;
113110 this . removeStyledSpans ( rootElem ) ;
114111 } ,
115112
@@ -141,14 +138,6 @@ const BaseFormatter = Module({
141138 /**
142139 * PRIVATE METHODS:
143140 */
144- cloneNodes ( rootElement ) {
145- let clonedNodes = [ ] ;
146- rootElement . childNodes . forEach ( ( node ) => {
147- clonedNodes . push ( node . cloneNode ( true ) ) ;
148- } ) ;
149- return clonedNodes ;
150- } ,
151-
152141 injectHooks ( rootElement ) {
153142 while ( ! / \w + / . test ( rootElement . firstChild . textContent ) ) {
154143 DOM . removeNode ( rootElement . firstChild ) ;
@@ -165,18 +154,21 @@ const BaseFormatter = Module({
165154 formatEmptyNewLine ( ) {
166155 const { mediator } = this ;
167156 const anchorNode = mediator . get ( 'selection:anchornode' ) ;
168- const canDefaultNewline = ! ( anchorNode . innerText && anchorNode . innerText . trim ( ) . length ) && ! DOM . isIn ( anchorNode , toolbarConfig . preventNewlineDefault ) ;
157+ const preventNewlineDefault = mediator . get ( 'config:toolbar:preventNewlineDefault' ) ;
158+ const canDefaultNewline = ! ( anchorNode . innerText && anchorNode . innerText . trim ( ) . length ) && ! DOM . isIn ( anchorNode , preventNewlineDefault ) ;
169159 const anchorIsContentEditable = anchorNode . hasAttribute && anchorNode . hasAttribute ( 'contenteditable' ) ;
170160
171161 if ( canDefaultNewline || anchorIsContentEditable ) {
172162 this . formatDefault ( ) ;
173163 }
174164 } ,
175165
176- formateBlockquoteNewLine ( ) {
166+ formatBlockquoteNewLine ( ) {
177167 const { mediator } = this ;
178168
179- commands . exec ( 'outdent' ) ;
169+ mediator . exec ( 'commands:exec' , {
170+ command : 'outdent'
171+ } ) ;
180172 this . formatDefault ( ) ;
181173
182174 const currentRangeClone = mediator . get ( 'selection:range' ) . cloneRange ( ) ;
@@ -207,7 +199,7 @@ const BaseFormatter = Module({
207199 const isContentEditable = startContainer . nodeType === Node . ELEMENT_NODE && startContainer . hasAttribute ( 'contenteditable' ) ;
208200
209201 if ( containerIsBlockquote ) {
210- this . formateBlockquoteNewLine ( ) ;
202+ this . formatBlockquoteNewLine ( ) ;
211203 } else if ( containerIsEmpty || isContentEditable ) {
212204 this . formatEmptyNewLine ( ) ;
213205 }
@@ -235,9 +227,10 @@ const BaseFormatter = Module({
235227 const isLastChild = brNode === brNode . parentNode . lastChild ;
236228 const isDoubleBreak = brNode . nextSibling && brNode . nextSibling . nodeName === 'BR' ;
237229 const isInBlock = DOM . isIn ( brNode , blockTags , rootElem ) ;
230+ const isOrphan = brNode . parentNode === rootElem ;
238231
239- if ( isLastChild ) {
240- brNodesToRemove . push ( isLastChild ) ;
232+ if ( isLastChild || isOrphan ) {
233+ brNodesToRemove . push ( brNode ) ;
241234 return ;
242235 }
243236
@@ -291,8 +284,9 @@ const BaseFormatter = Module({
291284 let isInvalid = validTags . indexOf ( currentNode . nodeName ) < 0 ;
292285 let isBrNode = currentNode . nodeName === 'BR' ; // BR nodes are handled elsewhere
293286 let isTypesterElem = currentNode . className && / t y p e s t e r / . test ( currentNode . className ) ;
287+ let isElement = currentNode . nodeType !== Node . TEXT_NODE ;
294288
295- if ( isInvalid && ! isBrNode && ! isTypesterElem ) {
289+ if ( isInvalid && ! isBrNode && ! isTypesterElem && isElement ) {
296290 invalidElements . unshift ( currentNode ) ;
297291 }
298292 }
@@ -312,6 +306,7 @@ const BaseFormatter = Module({
312306
313307 defaultOrphanedTextNodes ( rootElem ) {
314308 const { childNodes } = rootElem ;
309+
315310 for ( let i = 0 ; i < childNodes . length ; i ++ ) {
316311 let childNode = childNodes [ i ] ;
317312 if ( childNode . nodeType === Node . TEXT_NODE && / \w + / . test ( childNode . textContent ) ) {
0 commit comments