@@ -180,6 +180,24 @@ export function getTagsByName (host, range, tagName) {
180180 } )
181181}
182182
183+ export function getTagsByNameAndAttributes ( host , range , elem ) {
184+ return getTags ( host , range , ( node ) => {
185+ return node . nodeName === elem . nodeName . toUpperCase ( ) &&
186+ areSameAttributes ( node . attributes , elem . attributes )
187+ } )
188+ }
189+
190+ export function areSameAttributes ( attrs1 , attrs2 ) {
191+ if ( attrs1 . length !== attrs2 . length ) return false
192+
193+ for ( var i = 0 ; i < attrs1 . length ; i ++ ) {
194+ const attr = attrs2 [ attrs1 [ i ] . name ]
195+ if ( ! ( attr && attr . value === attrs1 [ i ] . value ) ) return false
196+ }
197+
198+ return true
199+ }
200+
183201// Get all tags that start or end inside the range
184202export function getInnerTags ( range , filterFunc ) {
185203 return range . getNodes ( [ nodeType . elementNode ] , filterFunc )
@@ -233,11 +251,11 @@ export function expandTo (host, range, elem) {
233251}
234252
235253export function toggleTag ( host , range , elem ) {
236- const elems = getTagsByName ( host , range , elem . nodeName )
254+ const elems = getTagsByNameAndAttributes ( host , range , elem )
237255
238256 if ( elems . length === 1 &&
239257 isExactSelection ( range , elems [ 0 ] , 'visible' ) ) {
240- return removeFormatting ( host , range , elem . nodeName )
258+ return removeFormattingElem ( host , range , elem )
241259 }
242260
243261 return forceWrap ( host , range , elem )
@@ -249,7 +267,7 @@ export function isWrappable (range) {
249267
250268export function forceWrap ( host , range , elem ) {
251269 let restoredRange = restoreRange ( host , range , ( ) => {
252- nuke ( host , range , elem . nodeName )
270+ nukeElem ( host , range , elem )
253271 } )
254272
255273 // remove all tags if the range is not wrappable
@@ -285,6 +303,12 @@ export function unwrap (elem) {
285303 : $elem . remove ( )
286304}
287305
306+ export function removeFormattingElem ( host , range , elem ) {
307+ return restoreRange ( host , range , ( ) => {
308+ nukeElem ( host , range , elem )
309+ } )
310+ }
311+
288312export function removeFormatting ( host , range , tagName ) {
289313 return restoreRange ( host , range , ( ) => {
290314 nuke ( host , range , tagName )
@@ -301,6 +325,18 @@ export function nuke (host, range, tagName) {
301325 } )
302326}
303327
328+ // Unwrap all tags this range is affected by.
329+ // Can also affect content outside of the range.
330+ export function nukeElem ( host , range , node ) {
331+ getTags ( host , range ) . forEach ( ( elem ) => {
332+ if ( elem . nodeName !== 'BR' && ( ! node ||
333+ ( elem . nodeName === node . nodeName . toUpperCase ( ) &&
334+ areSameAttributes ( elem . attributes , node . attributes ) ) ) ) {
335+ unwrap ( elem )
336+ }
337+ } )
338+ }
339+
304340// Insert a single character (or string) before or after the
305341// the range.
306342export function insertCharacter ( range , character , atStart ) {
0 commit comments