mirror of
https://github.com/fastmail/Squire.git
synced 2025-01-03 13:16:31 -05:00
Better fix up of mixed inline/block content.
This commit is contained in:
parent
46706db889
commit
aca8fd4fab
4 changed files with 96 additions and 78 deletions
|
@ -508,7 +508,7 @@ function mergeContainers ( node ) {
|
||||||
var prev = node.previousSibling,
|
var prev = node.previousSibling,
|
||||||
first = node.firstChild,
|
first = node.firstChild,
|
||||||
isListItem = ( node.nodeName === 'LI' ),
|
isListItem = ( node.nodeName === 'LI' ),
|
||||||
block;
|
needsFix, block;
|
||||||
|
|
||||||
// Do not merge LIs, unless it only contains a UL
|
// Do not merge LIs, unless it only contains a UL
|
||||||
if ( isListItem && ( !first || !/^[OU]L$/.test( first.nodeName ) ) ) {
|
if ( isListItem && ( !first || !/^[OU]L$/.test( first.nodeName ) ) ) {
|
||||||
|
@ -526,7 +526,11 @@ function mergeContainers ( node ) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
detach( node );
|
detach( node );
|
||||||
|
needsFix = !isContainer( node );
|
||||||
prev.appendChild( empty( node ) );
|
prev.appendChild( empty( node ) );
|
||||||
|
if ( needsFix ) {
|
||||||
|
fixContainer( prev );
|
||||||
|
}
|
||||||
if ( first ) {
|
if ( first ) {
|
||||||
mergeContainers( first );
|
mergeContainers( first );
|
||||||
}
|
}
|
||||||
|
@ -537,6 +541,42 @@ function mergeContainers ( node ) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Recursively examine container nodes and wrap any inline children.
|
||||||
|
function fixContainer ( container ) {
|
||||||
|
var children = container.childNodes,
|
||||||
|
doc = container.ownerDocument,
|
||||||
|
wrapper = null,
|
||||||
|
i, l, child, isBR;
|
||||||
|
for ( i = 0, l = children.length; i < l; i += 1 ) {
|
||||||
|
child = children[i];
|
||||||
|
isBR = child.nodeName === 'BR';
|
||||||
|
if ( !isBR && isInline( child ) ) {
|
||||||
|
if ( !wrapper ) { wrapper = createElement( doc, 'DIV' ); }
|
||||||
|
wrapper.appendChild( child );
|
||||||
|
i -= 1;
|
||||||
|
l -= 1;
|
||||||
|
} else if ( isBR || wrapper ) {
|
||||||
|
if ( !wrapper ) { wrapper = createElement( doc, 'DIV' ); }
|
||||||
|
fixCursor( wrapper );
|
||||||
|
if ( isBR ) {
|
||||||
|
container.replaceChild( wrapper, child );
|
||||||
|
} else {
|
||||||
|
container.insertBefore( wrapper, child );
|
||||||
|
i += 1;
|
||||||
|
l += 1;
|
||||||
|
}
|
||||||
|
wrapper = null;
|
||||||
|
}
|
||||||
|
if ( isContainer( child ) ) {
|
||||||
|
fixContainer( child );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ( wrapper ) {
|
||||||
|
container.appendChild( fixCursor( wrapper ) );
|
||||||
|
}
|
||||||
|
return container;
|
||||||
|
}
|
||||||
|
|
||||||
function createElement ( doc, tag, props, children ) {
|
function createElement ( doc, tag, props, children ) {
|
||||||
var el = doc.createElement( tag ),
|
var el = doc.createElement( tag ),
|
||||||
attr, value, i, l;
|
attr, value, i, l;
|
||||||
|
@ -1114,6 +1154,7 @@ var expandRangeToBlockBoundaries = function ( range ) {
|
||||||
mergeInlines,
|
mergeInlines,
|
||||||
mergeWithBlock,
|
mergeWithBlock,
|
||||||
mergeContainers,
|
mergeContainers,
|
||||||
|
fixContainer,
|
||||||
createElement,
|
createElement,
|
||||||
|
|
||||||
forEachTextNodeInRange,
|
forEachTextNodeInRange,
|
||||||
|
@ -2092,7 +2133,7 @@ var removeList = function ( frag ) {
|
||||||
child = children[ll];
|
child = children[ll];
|
||||||
replaceWith( child, empty( child ) );
|
replaceWith( child, empty( child ) );
|
||||||
}
|
}
|
||||||
wrapTopLevelInline( listFrag, 'DIV' );
|
fixContainer( listFrag );
|
||||||
replaceWith( list, listFrag );
|
replaceWith( list, listFrag );
|
||||||
}
|
}
|
||||||
return frag;
|
return frag;
|
||||||
|
@ -2153,7 +2194,7 @@ var decreaseListLevel = function ( frag ) {
|
||||||
item = parent;
|
item = parent;
|
||||||
}
|
}
|
||||||
}, this );
|
}, this );
|
||||||
wrapTopLevelInline( frag, 'DIV' );
|
fixContainer( frag );
|
||||||
return frag;
|
return frag;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -2450,38 +2491,6 @@ var cleanTree = function ( node, allowStyles ) {
|
||||||
return node;
|
return node;
|
||||||
};
|
};
|
||||||
|
|
||||||
var wrapTopLevelInline = function ( root, tag ) {
|
|
||||||
var children = root.childNodes,
|
|
||||||
doc = root.ownerDocument,
|
|
||||||
wrapper = null,
|
|
||||||
i, l, child, isBR;
|
|
||||||
for ( i = 0, l = children.length; i < l; i += 1 ) {
|
|
||||||
child = children[i];
|
|
||||||
isBR = child.nodeName === 'BR';
|
|
||||||
if ( !isBR && isInline( child ) ) {
|
|
||||||
if ( !wrapper ) { wrapper = createElement( doc, tag ); }
|
|
||||||
wrapper.appendChild( child );
|
|
||||||
i -= 1;
|
|
||||||
l -= 1;
|
|
||||||
} else if ( isBR || wrapper ) {
|
|
||||||
if ( !wrapper ) { wrapper = createElement( doc, tag ); }
|
|
||||||
fixCursor( wrapper );
|
|
||||||
if ( isBR ) {
|
|
||||||
root.replaceChild( wrapper, child );
|
|
||||||
} else {
|
|
||||||
root.insertBefore( wrapper, child );
|
|
||||||
i += 1;
|
|
||||||
l += 1;
|
|
||||||
}
|
|
||||||
wrapper = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if ( wrapper ) {
|
|
||||||
root.appendChild( fixCursor( wrapper ) );
|
|
||||||
}
|
|
||||||
return root;
|
|
||||||
};
|
|
||||||
|
|
||||||
var notWSTextNode = function ( node ) {
|
var notWSTextNode = function ( node ) {
|
||||||
return ( node.nodeType === ELEMENT_NODE ?
|
return ( node.nodeType === ELEMENT_NODE ?
|
||||||
node.nodeName === 'BR' :
|
node.nodeName === 'BR' :
|
||||||
|
@ -2532,7 +2541,7 @@ var cleanupBRs = function ( root ) {
|
||||||
// If this is not inside a block, replace it by wrapping
|
// If this is not inside a block, replace it by wrapping
|
||||||
// inlines in DIV.
|
// inlines in DIV.
|
||||||
if ( !isBlock( block ) || !tagAfterSplit[ block.nodeName ] ) {
|
if ( !isBlock( block ) || !tagAfterSplit[ block.nodeName ] ) {
|
||||||
wrapTopLevelInline( block, 'DIV' );
|
fixContainer( block );
|
||||||
}
|
}
|
||||||
// If in a block we can split, split it instead, but only if there
|
// If in a block we can split, split it instead, but only if there
|
||||||
// is actual text content in the block. Otherwise, the <br> is a
|
// is actual text content in the block. Otherwise, the <br> is a
|
||||||
|
@ -2833,7 +2842,7 @@ var keyHandlers = {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
wrapTopLevelInline( block, 'DIV' );
|
fixContainer( block );
|
||||||
splitTag = 'DIV';
|
splitTag = 'DIV';
|
||||||
if ( !splitNode ) {
|
if ( !splitNode ) {
|
||||||
splitNode = block.firstChild;
|
splitNode = block.firstChild;
|
||||||
|
@ -3188,7 +3197,7 @@ proto.setHTML = function ( html ) {
|
||||||
cleanTree( frag, true );
|
cleanTree( frag, true );
|
||||||
cleanupBRs( frag );
|
cleanupBRs( frag );
|
||||||
|
|
||||||
wrapTopLevelInline( frag, 'DIV' );
|
fixContainer( frag );
|
||||||
|
|
||||||
// Fix cursor
|
// Fix cursor
|
||||||
var node = frag;
|
var node = frag;
|
||||||
|
|
File diff suppressed because one or more lines are too long
|
@ -42,6 +42,7 @@
|
||||||
mergeInlines,
|
mergeInlines,
|
||||||
mergeWithBlock,
|
mergeWithBlock,
|
||||||
mergeContainers,
|
mergeContainers,
|
||||||
|
fixContainer,
|
||||||
createElement,
|
createElement,
|
||||||
|
|
||||||
forEachTextNodeInRange,
|
forEachTextNodeInRange,
|
||||||
|
@ -1020,7 +1021,7 @@ var removeList = function ( frag ) {
|
||||||
child = children[ll];
|
child = children[ll];
|
||||||
replaceWith( child, empty( child ) );
|
replaceWith( child, empty( child ) );
|
||||||
}
|
}
|
||||||
wrapTopLevelInline( listFrag, 'DIV' );
|
fixContainer( listFrag );
|
||||||
replaceWith( list, listFrag );
|
replaceWith( list, listFrag );
|
||||||
}
|
}
|
||||||
return frag;
|
return frag;
|
||||||
|
@ -1081,7 +1082,7 @@ var decreaseListLevel = function ( frag ) {
|
||||||
item = parent;
|
item = parent;
|
||||||
}
|
}
|
||||||
}, this );
|
}, this );
|
||||||
wrapTopLevelInline( frag, 'DIV' );
|
fixContainer( frag );
|
||||||
return frag;
|
return frag;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1378,38 +1379,6 @@ var cleanTree = function ( node, allowStyles ) {
|
||||||
return node;
|
return node;
|
||||||
};
|
};
|
||||||
|
|
||||||
var wrapTopLevelInline = function ( root, tag ) {
|
|
||||||
var children = root.childNodes,
|
|
||||||
doc = root.ownerDocument,
|
|
||||||
wrapper = null,
|
|
||||||
i, l, child, isBR;
|
|
||||||
for ( i = 0, l = children.length; i < l; i += 1 ) {
|
|
||||||
child = children[i];
|
|
||||||
isBR = child.nodeName === 'BR';
|
|
||||||
if ( !isBR && isInline( child ) ) {
|
|
||||||
if ( !wrapper ) { wrapper = createElement( doc, tag ); }
|
|
||||||
wrapper.appendChild( child );
|
|
||||||
i -= 1;
|
|
||||||
l -= 1;
|
|
||||||
} else if ( isBR || wrapper ) {
|
|
||||||
if ( !wrapper ) { wrapper = createElement( doc, tag ); }
|
|
||||||
fixCursor( wrapper );
|
|
||||||
if ( isBR ) {
|
|
||||||
root.replaceChild( wrapper, child );
|
|
||||||
} else {
|
|
||||||
root.insertBefore( wrapper, child );
|
|
||||||
i += 1;
|
|
||||||
l += 1;
|
|
||||||
}
|
|
||||||
wrapper = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if ( wrapper ) {
|
|
||||||
root.appendChild( fixCursor( wrapper ) );
|
|
||||||
}
|
|
||||||
return root;
|
|
||||||
};
|
|
||||||
|
|
||||||
var notWSTextNode = function ( node ) {
|
var notWSTextNode = function ( node ) {
|
||||||
return ( node.nodeType === ELEMENT_NODE ?
|
return ( node.nodeType === ELEMENT_NODE ?
|
||||||
node.nodeName === 'BR' :
|
node.nodeName === 'BR' :
|
||||||
|
@ -1460,7 +1429,7 @@ var cleanupBRs = function ( root ) {
|
||||||
// If this is not inside a block, replace it by wrapping
|
// If this is not inside a block, replace it by wrapping
|
||||||
// inlines in DIV.
|
// inlines in DIV.
|
||||||
if ( !isBlock( block ) || !tagAfterSplit[ block.nodeName ] ) {
|
if ( !isBlock( block ) || !tagAfterSplit[ block.nodeName ] ) {
|
||||||
wrapTopLevelInline( block, 'DIV' );
|
fixContainer( block );
|
||||||
}
|
}
|
||||||
// If in a block we can split, split it instead, but only if there
|
// If in a block we can split, split it instead, but only if there
|
||||||
// is actual text content in the block. Otherwise, the <br> is a
|
// is actual text content in the block. Otherwise, the <br> is a
|
||||||
|
@ -1761,7 +1730,7 @@ var keyHandlers = {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
wrapTopLevelInline( block, 'DIV' );
|
fixContainer( block );
|
||||||
splitTag = 'DIV';
|
splitTag = 'DIV';
|
||||||
if ( !splitNode ) {
|
if ( !splitNode ) {
|
||||||
splitNode = block.firstChild;
|
splitNode = block.firstChild;
|
||||||
|
@ -2116,7 +2085,7 @@ proto.setHTML = function ( html ) {
|
||||||
cleanTree( frag, true );
|
cleanTree( frag, true );
|
||||||
cleanupBRs( frag );
|
cleanupBRs( frag );
|
||||||
|
|
||||||
wrapTopLevelInline( frag, 'DIV' );
|
fixContainer( frag );
|
||||||
|
|
||||||
// Fix cursor
|
// Fix cursor
|
||||||
var node = frag;
|
var node = frag;
|
||||||
|
|
|
@ -366,7 +366,7 @@ function mergeContainers ( node ) {
|
||||||
var prev = node.previousSibling,
|
var prev = node.previousSibling,
|
||||||
first = node.firstChild,
|
first = node.firstChild,
|
||||||
isListItem = ( node.nodeName === 'LI' ),
|
isListItem = ( node.nodeName === 'LI' ),
|
||||||
block;
|
needsFix, block;
|
||||||
|
|
||||||
// Do not merge LIs, unless it only contains a UL
|
// Do not merge LIs, unless it only contains a UL
|
||||||
if ( isListItem && ( !first || !/^[OU]L$/.test( first.nodeName ) ) ) {
|
if ( isListItem && ( !first || !/^[OU]L$/.test( first.nodeName ) ) ) {
|
||||||
|
@ -384,7 +384,11 @@ function mergeContainers ( node ) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
detach( node );
|
detach( node );
|
||||||
|
needsFix = !isContainer( node );
|
||||||
prev.appendChild( empty( node ) );
|
prev.appendChild( empty( node ) );
|
||||||
|
if ( needsFix ) {
|
||||||
|
fixContainer( prev );
|
||||||
|
}
|
||||||
if ( first ) {
|
if ( first ) {
|
||||||
mergeContainers( first );
|
mergeContainers( first );
|
||||||
}
|
}
|
||||||
|
@ -395,6 +399,42 @@ function mergeContainers ( node ) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Recursively examine container nodes and wrap any inline children.
|
||||||
|
function fixContainer ( container ) {
|
||||||
|
var children = container.childNodes,
|
||||||
|
doc = container.ownerDocument,
|
||||||
|
wrapper = null,
|
||||||
|
i, l, child, isBR;
|
||||||
|
for ( i = 0, l = children.length; i < l; i += 1 ) {
|
||||||
|
child = children[i];
|
||||||
|
isBR = child.nodeName === 'BR';
|
||||||
|
if ( !isBR && isInline( child ) ) {
|
||||||
|
if ( !wrapper ) { wrapper = createElement( doc, 'DIV' ); }
|
||||||
|
wrapper.appendChild( child );
|
||||||
|
i -= 1;
|
||||||
|
l -= 1;
|
||||||
|
} else if ( isBR || wrapper ) {
|
||||||
|
if ( !wrapper ) { wrapper = createElement( doc, 'DIV' ); }
|
||||||
|
fixCursor( wrapper );
|
||||||
|
if ( isBR ) {
|
||||||
|
container.replaceChild( wrapper, child );
|
||||||
|
} else {
|
||||||
|
container.insertBefore( wrapper, child );
|
||||||
|
i += 1;
|
||||||
|
l += 1;
|
||||||
|
}
|
||||||
|
wrapper = null;
|
||||||
|
}
|
||||||
|
if ( isContainer( child ) ) {
|
||||||
|
fixContainer( child );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ( wrapper ) {
|
||||||
|
container.appendChild( fixCursor( wrapper ) );
|
||||||
|
}
|
||||||
|
return container;
|
||||||
|
}
|
||||||
|
|
||||||
function createElement ( doc, tag, props, children ) {
|
function createElement ( doc, tag, props, children ) {
|
||||||
var el = doc.createElement( tag ),
|
var el = doc.createElement( tag ),
|
||||||
attr, value, i, l;
|
attr, value, i, l;
|
||||||
|
|
Loading…
Reference in a new issue