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:
parent
d16de00a23
commit
654706f15f
2 changed files with 164 additions and 0 deletions
|
@ -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 );
|
||||||
|
|
||||||
|
|
|
@ -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 );
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue