|
|
@@ -7,7 +7,7 @@
|
|
|
* @module engine/view/domconverter
|
|
|
*/
|
|
|
|
|
|
-/* globals document, Node, NodeFilter, Text */
|
|
|
+/* globals window, document, Node, NodeFilter, Text */
|
|
|
|
|
|
import ViewText from './text';
|
|
|
import ViewElement from './element';
|
|
|
@@ -16,15 +16,7 @@ import ViewRange from './range';
|
|
|
import ViewSelection from './selection';
|
|
|
import ViewDocumentFragment from './documentfragment';
|
|
|
import ViewTreeWalker from './treewalker';
|
|
|
-import {
|
|
|
- BR_FILLER,
|
|
|
- NBSP_FILLER,
|
|
|
- INLINE_FILLER_LENGTH,
|
|
|
- isBlockFiller,
|
|
|
- isInlineFiller,
|
|
|
- startsWithFiller,
|
|
|
- getDataWithoutFiller
|
|
|
-} from './filler';
|
|
|
+import { BR_FILLER, getDataWithoutFiller, INLINE_FILLER_LENGTH, isInlineFiller, NBSP_FILLER, startsWithFiller } from './filler';
|
|
|
|
|
|
import global from '@ckeditor/ckeditor5-utils/src/dom/global';
|
|
|
import indexOf from '@ckeditor/ckeditor5-utils/src/dom/indexof';
|
|
|
@@ -33,6 +25,9 @@ import getCommonAncestor from '@ckeditor/ckeditor5-utils/src/dom/getcommonancest
|
|
|
import isText from '@ckeditor/ckeditor5-utils/src/dom/istext';
|
|
|
import { isElement } from 'lodash-es';
|
|
|
|
|
|
+// eslint-disable-next-line new-cap
|
|
|
+const BR_FILLER_REF = BR_FILLER( window.document );
|
|
|
+
|
|
|
/**
|
|
|
* DomConverter is a set of tools to do transformations between DOM nodes and view nodes. It also handles
|
|
|
* {@link module:engine/view/domconverter~DomConverter#bindElements binding} these nodes.
|
|
|
@@ -387,7 +382,7 @@ export default class DomConverter {
|
|
|
* or `null` if DOM node is a {@link module:engine/view/filler filler} or the given node is an empty text node.
|
|
|
*/
|
|
|
domToView( domNode, options = {} ) {
|
|
|
- if ( isBlockFiller( domNode, this.blockFillerMode ) ) {
|
|
|
+ if ( this.isBlockFiller( domNode, this.blockFillerMode ) ) {
|
|
|
return null;
|
|
|
}
|
|
|
|
|
|
@@ -545,7 +540,7 @@ export default class DomConverter {
|
|
|
* @returns {module:engine/view/position~Position} viewPosition View position.
|
|
|
*/
|
|
|
domPositionToView( domParent, domOffset ) {
|
|
|
- if ( isBlockFiller( domParent, this.blockFillerMode ) ) {
|
|
|
+ if ( this.isBlockFiller( domParent, this.blockFillerMode ) ) {
|
|
|
return this.domPositionToView( domParent.parentNode, indexOf( domParent ) );
|
|
|
}
|
|
|
|
|
|
@@ -803,6 +798,23 @@ export default class DomConverter {
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
+ * Checks if the node is an instance of the block filler for this DOM converter.
|
|
|
+ *
|
|
|
+ * const converter = new DomConverter( { blockFillerMode: 'br' } );
|
|
|
+ *
|
|
|
+ * converter.isBlockFiller( BR_FILLER( document ) ); // true
|
|
|
+ * converter.isBlockFiller( NBSP_FILLER( document ) ); // false
|
|
|
+ *
|
|
|
+ * **Note:**: For the `'nbsp'` mode the method also checks context of a node so it cannot be a detached node.
|
|
|
+ *
|
|
|
+ * @param {Node} domNode DOM node to check.
|
|
|
+ * @returns {Boolean} True if a node is considered a block filler for given mode.
|
|
|
+ */
|
|
|
+ isBlockFiller( domNode ) {
|
|
|
+ return this.blockFillerMode == 'br' ? domNode.isEqualNode( BR_FILLER_REF ) : isNbspBlockFiller( domNode, this.blockElements );
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
* Returns `true` if given selection is a backward selection, that is, if it's `focus` is before `anchor`.
|
|
|
*
|
|
|
* @param {Selection} DOM Selection instance to check.
|
|
|
@@ -1213,3 +1225,36 @@ function forEachDomNodeAncestor( node, callback ) {
|
|
|
node = node.parentNode;
|
|
|
}
|
|
|
}
|
|
|
+
|
|
|
+// Checks if given node is a nbsp block filler.
|
|
|
+//
|
|
|
+// A is a block filler only if it is a single child of a block element.
|
|
|
+//
|
|
|
+// @param {Node} domNode DOM node.
|
|
|
+// @returns {Boolean}
|
|
|
+function isNbspBlockFiller( domNode, blockElements ) {
|
|
|
+ const isNBSP = isText( domNode ) && domNode.data == '\u00A0';
|
|
|
+
|
|
|
+ return isNBSP && hasBlockParent( domNode, blockElements ) && domNode.parentNode.childNodes.length === 1;
|
|
|
+}
|
|
|
+
|
|
|
+// Checks if domNode has block parent.
|
|
|
+//
|
|
|
+// @param {Node} domNode DOM node.
|
|
|
+// @returns {Boolean}
|
|
|
+function hasBlockParent( domNode, blockElements ) {
|
|
|
+ const parent = domNode.parentNode;
|
|
|
+
|
|
|
+ return parent && parent.tagName && blockElements.includes( parent.tagName.toLowerCase() );
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * Enum representing type of the block filler.
|
|
|
+ *
|
|
|
+ * Possible values:
|
|
|
+ *
|
|
|
+ * * `br` - for `<br>` block filler used in editing view,
|
|
|
+ * * `nbsp` - for ` ` block fillers used in the data.
|
|
|
+ *
|
|
|
+ * @typedef {String} module:engine/view/filler~BlockFillerMode
|
|
|
+ */
|