0
Fork 0
mirror of https://github.com/fastmail/Squire.git synced 2024-12-22 15:23:29 -05:00

Squire#removeAllFormatting() implemented, replaces range contents with style-sanitized version.

This commit is contained in:
Gert K. Sønderby 2015-06-03 17:03:10 +02:00 committed by Neil Jenkins
parent d16de00a23
commit 654706f15f
2 changed files with 164 additions and 0 deletions

View file

@ -3620,6 +3620,88 @@ proto.setTextDirection = function ( direction ) {
return this.focus(); return this.focus();
}; };
function forEachChildInRange( rootNode, range, iterator ) {
var walker = new TreeWalker( rootNode, SHOW_ELEMENT,
function ( node ) {
return node.parentNode === rootNode &&
isNodeContainedInRange( range, node, false /* include partials */ );
}
);
var node;
while ( node = walker.nextNode() ) {
iterator( node );
}
}
function mapEachChildInRange( rootNode, range, iterator ) {
var output = [];
forEachChildInRange( rootNode, range, function ( node ) {
output.push( iterator( node ) );
} );
return output;
}
var stylingNodeNames = /(^|>)(?:B|I|S|SUB|SUP|U|BLOCKQUOTE|OL|UL|LI|T(?:ABLE|BODY|HEAD|FOOT|R|D|H))(>|$)/;
proto.removeAllFormatting = function ( range ) {
if ( !range && !( range = this.getSelection() ) || range.collapsed ) {
return false;
}
var stopNode = range.commonAncestorContainer;
while ( stylingNodeNames.test( getPath( stopNode ) ) ) {
stopNode = stopNode.parentNode;
}
if (stopNode.nodeType === TEXT_NODE) {
return false;
}
moveRangeBoundariesUpTree( range, stopNode );
this._saveRangeToBookmark( range );
var doc = stopNode.ownerDocument;
var startContainer = range.startContainer;
var startOffset = range.startOffset;
var endContainer = range.endContainer;
var endOffset = range.endOffset;
// Split end point first to avoid problems when end and start in same container.
split( endContainer, endOffset, stopNode );
split( startContainer, startOffset, stopNode );
range = this._getRangeAndRemoveBookmark(null, true);
moveRangeBoundariesUpTree( range, stopNode );
this._saveRangeToBookmark( range );
var that = this;
var contents = [];
forEachChildInRange( stopNode, range, function cleanSingleNode( node ) {
if ( isContainer( node ) ) {
forEachChildInRange( node, range, cleanSingleNode );
} else if ( isBlock( node ) ) {
var block = that.createDefaultBlock();
block.appendChild( doc.createTextNode( node.textContent ) );
contents.push( block );
} else if ( isInline( node ) ) {
contents.push( doc.createTextNode( node.textContent ) );
}
} );
var oldContents = mapEachChildInRange( stopNode, range, function ( node ) {
return node;
} );
contents.forEach( function ( node ) {
stopNode.insertBefore( node, oldContents[0] );
} );
oldContents.forEach( function ( node ) {
stopNode.removeChild( node );
} );
this.setSelection( this._getRangeAndRemoveBookmark() );
};
proto.increaseQuoteLevel = command( 'modifyBlocks', increaseBlockQuoteLevel ); proto.increaseQuoteLevel = command( 'modifyBlocks', increaseBlockQuoteLevel );
proto.decreaseQuoteLevel = command( 'modifyBlocks', decreaseBlockQuoteLevel ); proto.decreaseQuoteLevel = command( 'modifyBlocks', decreaseBlockQuoteLevel );

View file

@ -2162,6 +2162,88 @@ proto.setTextDirection = function ( direction ) {
return this.focus(); return this.focus();
}; };
function forEachChildInRange( rootNode, range, iterator ) {
var walker = new TreeWalker( rootNode, SHOW_ELEMENT,
function ( node ) {
return node.parentNode === rootNode &&
isNodeContainedInRange( range, node, false /* include partials */ );
}
);
var node;
while ( node = walker.nextNode() ) {
iterator( node );
}
}
function mapEachChildInRange( rootNode, range, iterator ) {
var output = [];
forEachChildInRange( rootNode, range, function ( node ) {
output.push( iterator( node ) );
} );
return output;
}
var stylingNodeNames = /(^|>)(?:B|I|S|SUB|SUP|U|BLOCKQUOTE|OL|UL|LI|T(?:ABLE|BODY|HEAD|FOOT|R|D|H))(>|$)/;
proto.removeAllFormatting = function ( range ) {
if ( !range && !( range = this.getSelection() ) || range.collapsed ) {
return false;
}
var stopNode = range.commonAncestorContainer;
while ( stylingNodeNames.test( getPath( stopNode ) ) ) {
stopNode = stopNode.parentNode;
}
if (stopNode.nodeType === TEXT_NODE) {
return false;
}
moveRangeBoundariesUpTree( range, stopNode );
this._saveRangeToBookmark( range );
var doc = stopNode.ownerDocument;
var startContainer = range.startContainer;
var startOffset = range.startOffset;
var endContainer = range.endContainer;
var endOffset = range.endOffset;
// Split end point first to avoid problems when end and start in same container.
split( endContainer, endOffset, stopNode );
split( startContainer, startOffset, stopNode );
range = this._getRangeAndRemoveBookmark(null, true);
moveRangeBoundariesUpTree( range, stopNode );
this._saveRangeToBookmark( range );
var that = this;
var contents = [];
forEachChildInRange( stopNode, range, function cleanSingleNode( node ) {
if ( isContainer( node ) ) {
forEachChildInRange( node, range, cleanSingleNode );
} else if ( isBlock( node ) ) {
var block = that.createDefaultBlock();
block.appendChild( doc.createTextNode( node.textContent ) );
contents.push( block );
} else if ( isInline( node ) ) {
contents.push( doc.createTextNode( node.textContent ) );
}
} );
var oldContents = mapEachChildInRange( stopNode, range, function ( node ) {
return node;
} );
contents.forEach( function ( node ) {
stopNode.insertBefore( node, oldContents[0] );
} );
oldContents.forEach( function ( node ) {
stopNode.removeChild( node );
} );
this.setSelection( this._getRangeAndRemoveBookmark() );
};
proto.increaseQuoteLevel = command( 'modifyBlocks', increaseBlockQuoteLevel ); proto.increaseQuoteLevel = command( 'modifyBlocks', increaseBlockQuoteLevel );
proto.decreaseQuoteLevel = command( 'modifyBlocks', decreaseBlockQuoteLevel ); proto.decreaseQuoteLevel = command( 'modifyBlocks', decreaseBlockQuoteLevel );