-
Notifications
You must be signed in to change notification settings - Fork 40
T/ckeditor5 table/99: Selection post-fixer improvements. #1608
Changes from 8 commits
3b19330
efa318b
ecffa73
6e47945
ef8352c
1d54e74
33aa691
02ce918
6862a79
d1a522f
92f9a9f
d1debb9
5a055e1
b16b0f0
d964375
9cf3a14
9172eee
77d39f2
da417e0
3398e5d
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -159,6 +159,7 @@ function tryFixingCollapsedRange( range, schema ) { | |
// | ||
// @param {module:engine/model/range~Range} range Expanded range to fix. | ||
// @param {module:engine/model/schema~Schema} schema | ||
|
||
// @returns {module:engine/model/range~Range|null} Returns fixed range or null if range is valid. | ||
function tryFixingNonCollapsedRage( range, schema ) { | ||
const start = range.start; | ||
|
@@ -183,9 +184,13 @@ function tryFixingNonCollapsedRage( range, schema ) { | |
// - [<block>foo</block>] -> <block>[foo]</block> | ||
// - [<block>foo]</block> -> <block>[foo]</block> | ||
// - <block>f[oo</block>] -> <block>f[oo]</block> | ||
// - [<block>foo</block><object></object>] -> <block>[foo</block><object></object>] | ||
if ( checkSelectionOnNonLimitElements( start, end, schema ) ) { | ||
const fixedStart = schema.getNearestSelectionRange( start, 'forward' ); | ||
const fixedEnd = schema.getNearestSelectionRange( end, 'backward' ); | ||
const isStartObject = start.nodeAfter && schema.isObject( start.nodeAfter ); | ||
const fixedStart = isStartObject ? null : schema.getNearestSelectionRange( start, 'forward' ); | ||
jodator marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
const isEndObject = end.nodeBefore && schema.isObject( end.nodeBefore ); | ||
const fixedEnd = isEndObject ? null : schema.getNearestSelectionRange( end, 'backward' ); | ||
jodator marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
return new Range( fixedStart ? fixedStart.start : start, fixedEnd ? fixedEnd.start : end ); | ||
jodator marked this conversation as resolved.
Show resolved
Hide resolved
|
||
} | ||
|
@@ -197,13 +202,23 @@ function tryFixingNonCollapsedRage( range, schema ) { | |
// At this point we eliminated valid positions on text nodes so if one of range positions is placed inside a limit element | ||
// then the range crossed limit element boundaries and needs to be fixed. | ||
if ( isStartInLimit || isEndInLimit ) { | ||
const bothInSameParent = ( !!start.nodeAfter && !!end.nodeBefore ) && start.nodeAfter === end.nodeBefore; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think we can omit There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Also, I am not sure if the name is correct. It's more that the selection is on the same element, isn't it? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The name is correct but the check is not. Updated to look for parent check. |
||
|
||
const expandStart = isStartInLimit && ( !bothInSameParent || !isInObject( start.nodeAfter, schema ) ); | ||
const expandEnd = isEndInLimit && ( !bothInSameParent || !isInObject( end.nodeBefore, schema ) ); | ||
|
||
// Although we've already found limit element on start/end positions we must find the outer-most limit element. | ||
// as limit elements might be nested directly inside (ie table > tableRow > tableCell). | ||
const startPosition = Position._createAt( startLimitElement, 0 ); | ||
const endPosition = Position._createAt( endLimitElement, 0 ); | ||
let fixedStart = start; | ||
let fixedEnd = end; | ||
|
||
if ( expandStart ) { | ||
fixedStart = Position._createBefore( findOuterMostIsLimitAncestor( startLimitElement, schema ) ); | ||
} | ||
|
||
const fixedStart = isStartInLimit ? expandSelectionOnIsLimitNode( startPosition, schema, 'start' ) : start; | ||
const fixedEnd = isEndInLimit ? expandSelectionOnIsLimitNode( endPosition, schema, 'end' ) : end; | ||
if ( expandEnd ) { | ||
fixedEnd = Position._createAfter( findOuterMostIsLimitAncestor( endLimitElement, schema ) ); | ||
} | ||
|
||
return new Range( fixedStart, fixedEnd ); | ||
} | ||
|
@@ -212,34 +227,45 @@ function tryFixingNonCollapsedRage( range, schema ) { | |
return null; | ||
} | ||
|
||
// Expands selection so it contains whole limit node. | ||
// Finds the outer-most ancestor. | ||
// | ||
// @param {module:engine/model/position~Position} position | ||
// @param {module:engine/model/node~Node} startingNode | ||
// @param {module:engine/model/schema~Schema} schema | ||
// @param {String} expandToDirection Direction of expansion - either 'start' or 'end' of the range. | ||
// @returns {module:engine/model/position~Position} | ||
function expandSelectionOnIsLimitNode( position, schema, expandToDirection ) { | ||
let node = position.parent; | ||
let parent = node; | ||
// @returns {module:engine/model/node~Node} | ||
function findOuterMostIsLimitAncestor( startingNode, schema ) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'd call it |
||
let isLimitNode = startingNode; | ||
let parent = isLimitNode; | ||
|
||
// Find outer most isLimit block as such blocks might be nested (ie. in tables). | ||
while ( schema.isLimit( parent ) && parent.parent ) { | ||
node = parent; | ||
isLimitNode = parent; | ||
parent = parent.parent; | ||
} | ||
|
||
// Depending on direction of expanding selection return position before or after found node. | ||
return expandToDirection === 'start' ? Position._createBefore( node ) : Position._createAfter( node ); | ||
return isLimitNode; | ||
} | ||
|
||
// Checks whether both range ends are placed around non-limit elements. | ||
// Checks whether one of range ends is placed around non-limit elements. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ends => boundaries There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. one => any |
||
// | ||
// @param {module:engine/model/position~Position} start | ||
// @param {module:engine/model/position~Position} end | ||
// @param {module:engine/model/schema~Schema} schema | ||
// @returns {Boolean} | ||
function checkSelectionOnNonLimitElements( start, end, schema ) { | ||
const startIsOnBlock = ( start.nodeAfter && !schema.isLimit( start.nodeAfter ) ) || schema.checkChild( start, '$text' ); | ||
const endIsOnBlock = ( end.nodeBefore && !schema.isLimit( end.nodeBefore ) ) || schema.checkChild( end, '$text' ); | ||
|
||
return startIsOnBlock && endIsOnBlock; | ||
// We should fix such selection when one of those nodes needs fixing. | ||
return startIsOnBlock || endIsOnBlock; | ||
} | ||
|
||
// Checks if node exists and if it's an object. | ||
// | ||
// @param {module:engine/model/node~Node} node | ||
// @param {module:engine/model/schema~Schema} schema | ||
// @returns {Boolean} | ||
function isInObject( node, schema ) { | ||
return node && schema.isObject( node ); | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🤔