diff --git a/packages/ckeditor5-engine/src/dataprocessor/dataprocessor.jsdoc b/packages/ckeditor5-engine/src/dataprocessor/dataprocessor.jsdoc index 673ef7d8595..a116ceed5a2 100644 --- a/packages/ckeditor5-engine/src/dataprocessor/dataprocessor.jsdoc +++ b/packages/ckeditor5-engine/src/dataprocessor/dataprocessor.jsdoc @@ -49,3 +49,16 @@ * @param {module:engine/view/matcher~MatcherPattern} pattern Pattern matching all view elements whose content should * be treated as plain text. */ + +/** + * If the processor is set to use marked fillers, it will insert nbsp fillers wrapped in spans + * (` `), instead of regular nbsp characters (` `). + * + * This mode allows for more precise handling of block fillers (so they don't leak into editor content) but bloats the editor + * data with additional markup. + * + * This mode may be required by some features and will be turned on by them automatically. + * + * @method #useFillerType + * @param {'default'|'marked'} type Whether to use default or marked nbsp block fillers. + */ diff --git a/packages/ckeditor5-engine/src/dataprocessor/htmldataprocessor.js b/packages/ckeditor5-engine/src/dataprocessor/htmldataprocessor.js index f0d50fde4d5..4b1de28b9f2 100644 --- a/packages/ckeditor5-engine/src/dataprocessor/htmldataprocessor.js +++ b/packages/ckeditor5-engine/src/dataprocessor/htmldataprocessor.js @@ -93,6 +93,21 @@ export default class HtmlDataProcessor { this._domConverter.registerRawContentMatcher( pattern ); } + /** + * If the processor is set to use marked fillers, it will insert nbsp fillers wrapped in spans + * (` `), instead of regular nbsp characters (` `). + * + * This mode allows for more precise handling of block fillers (so they don't leak into editor content) but bloats the editor + * data with additional markup. + * + * This mode may be required by some features and will be turned on by them automatically. + * + * @param {'default'|'marked'} type Whether to use default or marked nbsp block fillers. + */ + useFillerType( type ) { + this._domConverter.blockFillerMode = type == 'marked' ? 'markedNbsp' : 'nbsp'; + } + /** * Converts an HTML string to its DOM representation. Returns a document fragment containing nodes parsed from * the provided data. diff --git a/packages/ckeditor5-engine/src/dataprocessor/xmldataprocessor.js b/packages/ckeditor5-engine/src/dataprocessor/xmldataprocessor.js index c2162788dc6..141dbef9925 100644 --- a/packages/ckeditor5-engine/src/dataprocessor/xmldataprocessor.js +++ b/packages/ckeditor5-engine/src/dataprocessor/xmldataprocessor.js @@ -110,6 +110,21 @@ export default class XmlDataProcessor { this._domConverter.registerRawContentMatcher( pattern ); } + /** + * If the processor is set to use marked fillers, it will insert nbsp fillers wrapped in spans + * (` `), instead of regular nbsp characters (` `). + * + * This mode allows for more precise handling of block fillers (so they don't leak into editor content) but bloats the editor + * data with additional markup. + * + * This mode may be required by some features and will be turned on by them automatically. + * + * @param {'default'|'marked'} type Whether to use default or marked nbsp block fillers. + */ + useFillerType( type ) { + this._domConverter.blockFillerMode = type == 'marked' ? 'markedNbsp' : 'nbsp'; + } + /** * Converts an XML string to its DOM representation. Returns a document fragment containing nodes parsed from * the provided data. diff --git a/packages/ckeditor5-engine/src/view/domconverter.js b/packages/ckeditor5-engine/src/view/domconverter.js index e263bb9d41a..5e4e3b86b99 100644 --- a/packages/ckeditor5-engine/src/view/domconverter.js +++ b/packages/ckeditor5-engine/src/view/domconverter.js @@ -17,7 +17,10 @@ import ViewSelection from './selection'; import ViewDocumentFragment from './documentfragment'; import ViewTreeWalker from './treewalker'; import Matcher from './matcher'; -import { BR_FILLER, getDataWithoutFiller, INLINE_FILLER_LENGTH, isInlineFiller, NBSP_FILLER, startsWithFiller } from './filler'; +import { + BR_FILLER, INLINE_FILLER_LENGTH, NBSP_FILLER, MARKED_NBSP_FILLER, + getDataWithoutFiller, isInlineFiller, startsWithFiller +} from './filler'; import global from '@ckeditor/ckeditor5-utils/src/dom/global'; import indexOf from '@ckeditor/ckeditor5-utils/src/dom/indexof'; @@ -26,8 +29,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( document ); +const BR_FILLER_REF = BR_FILLER( document ); // eslint-disable-line new-cap +const NBSP_FILLER_REF = NBSP_FILLER( document ); // eslint-disable-line new-cap +const MARKED_NBSP_FILLER_REF = MARKED_NBSP_FILLER( document ); // eslint-disable-line new-cap /** * `DomConverter` is a set of tools to do transformations between DOM nodes and view nodes. It also handles @@ -60,8 +64,7 @@ export default class DomConverter { /** * The mode of a block filler used by the DOM converter. * - * @readonly - * @member {'br'|'nbsp'} module:engine/view/domconverter~DomConverter#blockFillerMode + * @member {'br'|'nbsp'|'markedNbsp'} module:engine/view/domconverter~DomConverter#blockFillerMode */ this.blockFillerMode = options.blockFillerMode || 'br'; @@ -86,16 +89,6 @@ export default class DomConverter { */ this.blockElements = [ 'p', 'div', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'li', 'dd', 'dt', 'figcaption', 'td', 'th' ]; - /** - * Block {@link module:engine/view/filler filler} creator, which is used to create all block fillers during the - * view-to-DOM conversion and to recognize block fillers during the DOM-to-view conversion. - * - * @readonly - * @private - * @member {Function} module:engine/view/domconverter~DomConverter#_blockFiller - */ - this._blockFiller = this.blockFillerMode == 'br' ? BR_FILLER : NBSP_FILLER; - /** * The DOM-to-view mapping. * @@ -297,7 +290,7 @@ export default class DomConverter { for ( const childView of viewElement.getChildren() ) { if ( fillerPositionOffset === offset ) { - yield this._blockFiller( domDocument ); + yield this._getBlockFiller( domDocument ); } yield this.viewToDom( childView, domDocument, options ); @@ -306,7 +299,7 @@ export default class DomConverter { } if ( fillerPositionOffset === offset ) { - yield this._blockFiller( domDocument ); + yield this._getBlockFiller( domDocument ); } } @@ -413,7 +406,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 ( this.isBlockFiller( domNode, this.blockFillerMode ) ) { + if ( this.isBlockFiller( domNode ) ) { return null; } @@ -581,7 +574,7 @@ export default class DomConverter { * @returns {module:engine/view/position~Position} viewPosition View position. */ domPositionToView( domParent, domOffset ) { - if ( this.isBlockFiller( domParent, this.blockFillerMode ) ) { + if ( this.isBlockFiller( domParent ) ) { return this.domPositionToView( domParent.parentNode, indexOf( domParent ) ); } @@ -863,13 +856,13 @@ export default class DomConverter { return domNode.isEqualNode( BR_FILLER_REF ); } - // Special case for


in which case the
should be treated as filler even - // when we're in the 'nbsp' mode. See ckeditor5#5564. + // Special case for


in which
should be treated as filler even when we are not in the 'br' mode. See ckeditor5#5564. if ( domNode.tagName === 'BR' && hasBlockParent( domNode, this.blockElements ) && domNode.parentNode.childNodes.length === 1 ) { return true; } - return isNbspBlockFiller( domNode, this.blockElements ); + // If not in 'br' mode, try recognizing both marked and regular nbsp block fillers. + return domNode.isEqualNode( MARKED_NBSP_FILLER_REF ) || isNbspBlockFiller( domNode, this.blockElements ); } /** @@ -956,6 +949,24 @@ export default class DomConverter { this._rawContentElementMatcher.add( pattern ); } + /** + * Returns block {@link module:engine/view/filler filler} node based on current {@link #blockFillerMode} setting. + * + * @private + * @params {Document} domDocument + * @returns {Node} filler + */ + _getBlockFiller( domDocument ) { + switch ( this.blockFillerMode ) { + case 'nbsp': + return NBSP_FILLER( domDocument ); // eslint-disable-line new-cap + case 'markedNbsp': + return MARKED_NBSP_FILLER( domDocument ); // eslint-disable-line new-cap + case 'br': + return BR_FILLER( domDocument ); // eslint-disable-line new-cap + } + } + /** * Checks if the given DOM position is a correct place for selection boundary. See {@link #isDomSelectionCorrect}. * @@ -1320,7 +1331,7 @@ function forEachDomNodeAncestor( node, callback ) { // @param {Node} domNode DOM node. // @returns {Boolean} function isNbspBlockFiller( domNode, blockElements ) { - const isNBSP = isText( domNode ) && domNode.data == '\u00A0'; + const isNBSP = domNode.isEqualNode( NBSP_FILLER_REF ); return isNBSP && hasBlockParent( domNode, blockElements ) && domNode.parentNode.childNodes.length === 1; } @@ -1340,8 +1351,9 @@ function hasBlockParent( domNode, blockElements ) { * * Possible values: * - * * `br` - for `
` block filler used in editing view, - * * `nbsp` - for ` ` block fillers used in the data. + * * `br` - for `
` block filler used in the editing view, + * * `nbsp` - for ` ` block fillers used in the data, + * * `markedNbsp` - for nbsp block fillers wrapped in a span: ` ` used in the data. * * @typedef {String} module:engine/view/filler~BlockFillerMode */ diff --git a/packages/ckeditor5-engine/src/view/filler.js b/packages/ckeditor5-engine/src/view/filler.js index 1d73295568b..39f17e58d1a 100644 --- a/packages/ckeditor5-engine/src/view/filler.js +++ b/packages/ckeditor5-engine/src/view/filler.js @@ -18,7 +18,8 @@ import isText from '@ckeditor/ckeditor5-utils/src/dom/istext'; * it is transparent for the selection, so when the caret is before the `
` and user presses right arrow he will be * moved to the next paragraph, not after the `
`. The disadvantage is that it breaks a block, so it can not be used * in the middle of a line of text. The {@link module:engine/view/filler~BR_FILLER `
` filler} can be replaced with any other - * character in the data output, for instance {@link module:engine/view/filler~NBSP_FILLER non-breaking space}. + * character in the data output, for instance {@link module:engine/view/filler~NBSP_FILLER non-breaking space} or + * {@link module:engine/view/filler~MARKED_NBSP_FILLER marked non-breaking space}. * * * Inline filler is a filler which does not break a line of text, so it can be used inside the text, for instance in the empty * `` surrendered by text: `foobar`, if we want to put the caret there. CKEditor uses a sequence of the zero-width @@ -38,16 +39,34 @@ import isText from '@ckeditor/ckeditor5-utils/src/dom/istext'; * Non-breaking space filler creator. This is a function which creates ` ` text node. * It defines how the filler is created. * + * @see module:engine/view/filler~MARKED_NBSP_FILLER * @see module:engine/view/filler~BR_FILLER * @function */ export const NBSP_FILLER = domDocument => domDocument.createTextNode( '\u00A0' ); +/** + * Marked non-breaking space filler creator. This is a function which creates ` ` element. + * It defines how the filler is created. + * + * @see module:engine/view/filler~NBSP_FILLER + * @see module:engine/view/filler~BR_FILLER + * @function + */ +export const MARKED_NBSP_FILLER = domDocument => { + const span = domDocument.createElement( 'span' ); + span.dataset.ckeFiller = true; + span.innerHTML = '\u00A0'; + + return span; +}; + /** * `
` filler creator. This is a function which creates `
` element. * It defines how the filler is created. * * @see module:engine/view/filler~NBSP_FILLER + * @see module:engine/view/filler~MARKED_NBSP_FILLER * @function */ export const BR_FILLER = domDocument => { diff --git a/packages/ckeditor5-engine/tests/dataprocessor/htmldataprocessor.js b/packages/ckeditor5-engine/tests/dataprocessor/htmldataprocessor.js index 5b2785fb935..9df53d24a0d 100644 --- a/packages/ckeditor5-engine/tests/dataprocessor/htmldataprocessor.js +++ b/packages/ckeditor5-engine/tests/dataprocessor/htmldataprocessor.js @@ -133,4 +133,20 @@ describe( 'HtmlDataProcessor', () => { expect( fragment.getChild( 1 ).getCustomProperty( '$rawContent' ) ).to.equal( ' abc ' ); } ); } ); + + describe( 'useFillerType()', () => { + it( 'should turn on and off using marked block fillers', () => { + const fragment = parse( '' ); + + expect( dataProcessor.toData( fragment ) ).to.equal( '

 

' ); + + dataProcessor.useFillerType( 'marked' ); + + expect( dataProcessor.toData( fragment ) ).to.equal( '

 

' ); + + dataProcessor.useFillerType( 'default' ); + + expect( dataProcessor.toData( fragment ) ).to.equal( '

 

' ); + } ); + } ); } ); diff --git a/packages/ckeditor5-engine/tests/dataprocessor/xmldataprocessor.js b/packages/ckeditor5-engine/tests/dataprocessor/xmldataprocessor.js index eeb043b6510..824b74cec79 100644 --- a/packages/ckeditor5-engine/tests/dataprocessor/xmldataprocessor.js +++ b/packages/ckeditor5-engine/tests/dataprocessor/xmldataprocessor.js @@ -122,4 +122,20 @@ describe( 'XmlDataProcessor', () => { expect( fragment.getChild( 1 ).getCustomProperty( '$rawContent' ) ).to.equal( ' abc ' ); } ); } ); + + describe( 'useFillerType()', () => { + it( 'should turn on and off using marked block fillers', () => { + const fragment = parse( '' ); + + expect( dataProcessor.toData( fragment ) ).to.equal( '

 

' ); + + dataProcessor.useFillerType( 'marked' ); + + expect( dataProcessor.toData( fragment ) ).to.equal( '

 

' ); + + dataProcessor.useFillerType( 'default' ); + + expect( dataProcessor.toData( fragment ) ).to.equal( '

 

' ); + } ); + } ); } ); diff --git a/packages/ckeditor5-engine/tests/view/domconverter/domconverter.js b/packages/ckeditor5-engine/tests/view/domconverter/domconverter.js index 7806c1948ae..c30f28cc18f 100644 --- a/packages/ckeditor5-engine/tests/view/domconverter/domconverter.js +++ b/packages/ckeditor5-engine/tests/view/domconverter/domconverter.js @@ -10,7 +10,7 @@ import ViewEditable from '../../../src/view/editableelement'; import ViewDocument from '../../../src/view/document'; import ViewUIElement from '../../../src/view/uielement'; import ViewContainerElement from '../../../src/view/containerelement'; -import { BR_FILLER, INLINE_FILLER, INLINE_FILLER_LENGTH, NBSP_FILLER } from '../../../src/view/filler'; +import { BR_FILLER, INLINE_FILLER, INLINE_FILLER_LENGTH, NBSP_FILLER, MARKED_NBSP_FILLER } from '../../../src/view/filler'; import testUtils from '@ckeditor/ckeditor5-core/tests/_utils/utils'; import global from '@ckeditor/ckeditor5-utils/src/dom/global'; import { StylesProcessor } from '../../../src/view/stylesmap'; @@ -295,88 +295,96 @@ describe( 'DomConverter', () => { } ); describe( 'isBlockFiller()', () => { - describe( 'mode "nbsp"', () => { - beforeEach( () => { - converter = new DomConverter( viewDocument, { blockFillerMode: 'nbsp' } ); - } ); + for ( const mode of [ 'nbsp', 'markedNbsp' ] ) { + describe( 'mode "' + mode + '"', () => { + beforeEach( () => { + converter = new DomConverter( viewDocument, { blockFillerMode: mode } ); + } ); - it( 'should return true if the node is an nbsp filler and is a single child of a block level element', () => { - const nbspFillerInstance = NBSP_FILLER( document ); // eslint-disable-line new-cap + it( 'should return true if the node is an nbsp filler and is a single child of a block level element', () => { + const nbspFillerInstance = NBSP_FILLER( document ); // eslint-disable-line new-cap - const context = document.createElement( 'div' ); - context.appendChild( nbspFillerInstance ); + const context = document.createElement( 'div' ); + context.appendChild( nbspFillerInstance ); - expect( converter.isBlockFiller( nbspFillerInstance ) ).to.be.true; - } ); + expect( converter.isBlockFiller( nbspFillerInstance ) ).to.be.true; + } ); - it( 'should return false if the node is an nbsp filler and is not a single child of a block level element', () => { - const nbspFillerInstance = NBSP_FILLER( document ); // eslint-disable-line new-cap + it( 'should return false if the node is an nbsp filler and is not a single child of a block level element', () => { + const nbspFillerInstance = NBSP_FILLER( document ); // eslint-disable-line new-cap - const context = document.createElement( 'div' ); - context.appendChild( nbspFillerInstance ); - context.appendChild( document.createTextNode( 'a' ) ); + const context = document.createElement( 'div' ); + context.appendChild( nbspFillerInstance ); + context.appendChild( document.createTextNode( 'a' ) ); - expect( converter.isBlockFiller( nbspFillerInstance ) ).to.be.false; - } ); + expect( converter.isBlockFiller( nbspFillerInstance ) ).to.be.false; + } ); - it( 'should return false if there are two nbsp fillers in a block element', () => { - const nbspFillerInstance = NBSP_FILLER( document ); // eslint-disable-line new-cap + it( 'should return false if there are two nbsp fillers in a block element', () => { + const nbspFillerInstance = NBSP_FILLER( document ); // eslint-disable-line new-cap - const context = document.createElement( 'div' ); - context.appendChild( nbspFillerInstance ); - context.appendChild( NBSP_FILLER( document ) ); // eslint-disable-line new-cap + const context = document.createElement( 'div' ); + context.appendChild( nbspFillerInstance ); + context.appendChild( NBSP_FILLER( document ) ); // eslint-disable-line new-cap - expect( converter.isBlockFiller( nbspFillerInstance ) ).to.be.false; - } ); + expect( converter.isBlockFiller( nbspFillerInstance ) ).to.be.false; + } ); - it( 'should return false filler is placed in a non-block element', () => { - const nbspFillerInstance = NBSP_FILLER( document ); // eslint-disable-line new-cap + it( 'should return false filler is placed in a non-block element', () => { + const nbspFillerInstance = NBSP_FILLER( document ); // eslint-disable-line new-cap - const context = document.createElement( 'span' ); - context.appendChild( nbspFillerInstance ); + const context = document.createElement( 'span' ); + context.appendChild( nbspFillerInstance ); - expect( converter.isBlockFiller( nbspFillerInstance ) ).to.be.false; - } ); + expect( converter.isBlockFiller( nbspFillerInstance ) ).to.be.false; + } ); - it( 'should return false if the node is an instance of the BR block filler', () => { - const brFillerInstance = BR_FILLER( document ); // eslint-disable-line new-cap + it( 'should return false if the node is an instance of the BR block filler', () => { + const brFillerInstance = BR_FILLER( document ); // eslint-disable-line new-cap - expect( converter.isBlockFiller( brFillerInstance ) ).to.be.false; - } ); + expect( converter.isBlockFiller( brFillerInstance ) ).to.be.false; + } ); - it( 'should return false for inline filler', () => { - expect( converter.isBlockFiller( document.createTextNode( INLINE_FILLER ) ) ).to.be.false; - } ); + it( 'should return false for inline filler', () => { + expect( converter.isBlockFiller( document.createTextNode( INLINE_FILLER ) ) ).to.be.false; + } ); - it( 'should return false for a normal
element', () => { - const context = document.createElement( 'div' ); - context.innerHTML = 'x
x'; + it( 'should return false for a normal
element', () => { + const context = document.createElement( 'div' ); + context.innerHTML = 'x
x'; - expect( converter.isBlockFiller( context.childNodes[ 1 ] ) ).to.be.false; - } ); + expect( converter.isBlockFiller( context.childNodes[ 1 ] ) ).to.be.false; + } ); - // SPECIAL CASE (see ckeditor5#5564). - it( 'should return true for a
element which is the only child of its block parent', () => { - const context = document.createElement( 'div' ); - context.innerHTML = '
'; + // SPECIAL CASE (see ckeditor5#5564). + it( 'should return true for a
element which is the only child of its block parent', () => { + const context = document.createElement( 'div' ); + context.innerHTML = '
'; - expect( converter.isBlockFiller( context.firstChild ) ).to.be.true; - } ); + expect( converter.isBlockFiller( context.firstChild ) ).to.be.true; + } ); - it( 'should return false for a
element which is the only child of its non-block parent', () => { - const context = document.createElement( 'span' ); - context.innerHTML = '
'; + it( 'should return false for a
element which is the only child of its non-block parent', () => { + const context = document.createElement( 'span' ); + context.innerHTML = '
'; - expect( converter.isBlockFiller( context.firstChild ) ).to.be.false; - } ); + expect( converter.isBlockFiller( context.firstChild ) ).to.be.false; + } ); - it( 'should return false for a
element which is followed by an nbsp', () => { - const context = document.createElement( 'span' ); - context.innerHTML = '
 '; + it( 'should return false for a
element which is followed by an nbsp', () => { + const context = document.createElement( 'span' ); + context.innerHTML = '
 '; - expect( converter.isBlockFiller( context.firstChild ) ).to.be.false; + expect( converter.isBlockFiller( context.firstChild ) ).to.be.false; + } ); + + it( 'should return true if the node is an instance of the marked nbsp block filler', () => { + const markedNbspFillerInstance = MARKED_NBSP_FILLER( document ); // eslint-disable-line new-cap + + expect( converter.isBlockFiller( markedNbspFillerInstance ) ).to.be.true; + } ); } ); - } ); + } describe( 'mode "br"', () => { beforeEach( () => { diff --git a/packages/ckeditor5-engine/tests/view/domconverter/view-to-dom.js b/packages/ckeditor5-engine/tests/view/domconverter/view-to-dom.js index 9fd50253229..0f701eae1f8 100644 --- a/packages/ckeditor5-engine/tests/view/domconverter/view-to-dom.js +++ b/packages/ckeditor5-engine/tests/view/domconverter/view-to-dom.js @@ -14,7 +14,7 @@ import ViewEmptyElement from '../../../src/view/emptyelement'; import DomConverter from '../../../src/view/domconverter'; import ViewDocumentFragment from '../../../src/view/documentfragment'; import ViewDocument from '../../../src/view/document'; -import { INLINE_FILLER, INLINE_FILLER_LENGTH } from '../../../src/view/filler'; +import { INLINE_FILLER, INLINE_FILLER_LENGTH, BR_FILLER, NBSP_FILLER, MARKED_NBSP_FILLER } from '../../../src/view/filler'; import { parse } from '../../../src/dev-utils/view'; @@ -663,6 +663,39 @@ describe( 'DomConverter', () => { expect( domChildren[ 1 ].data ).to.equal( 'foo' ); } ); + it( 'should add proper filler type - br', () => { + converter.blockFillerMode = 'br'; + + const viewP = parse( '' ); + + const domChildren = Array.from( converter.viewChildrenToDom( viewP, document ) ); + const filler = domChildren[ 0 ]; + + expect( filler.isEqualNode( BR_FILLER( document ) ) ).to.be.true; // eslint-disable-line new-cap + } ); + + it( 'should add proper filler type - nbsp', () => { + converter.blockFillerMode = 'nbsp'; + + const viewP = parse( '' ); + + const domChildren = Array.from( converter.viewChildrenToDom( viewP, document ) ); + const filler = domChildren[ 0 ]; + + expect( filler.isEqualNode( NBSP_FILLER( document ) ) ).to.be.true; // eslint-disable-line new-cap + } ); + + it( 'should add proper filler type - markedNbsp', () => { + converter.blockFillerMode = 'markedNbsp'; + + const viewP = parse( '' ); + + const domChildren = Array.from( converter.viewChildrenToDom( viewP, document ) ); + const filler = domChildren[ 0 ]; + + expect( filler.isEqualNode( MARKED_NBSP_FILLER( document ) ) ).to.be.true; // eslint-disable-line new-cap + } ); + it( 'should pass options', () => { const viewP = parse( 'foobar' ); diff --git a/packages/ckeditor5-markdown-gfm/src/gfmdataprocessor.js b/packages/ckeditor5-markdown-gfm/src/gfmdataprocessor.js index 7bc6f498fbb..485b513047e 100644 --- a/packages/ckeditor5-markdown-gfm/src/gfmdataprocessor.js +++ b/packages/ckeditor5-markdown-gfm/src/gfmdataprocessor.js @@ -83,4 +83,10 @@ export default class GFMDataProcessor { registerRawContentMatcher( pattern ) { this._htmlDP.registerRawContentMatcher( pattern ); } + + /** + * This method does not have an effect on data processor result. It exists for compatibility with + * {@link module:engine/dataprocessor/dataprocessor~DataProcessor `DataProcessor` interface}. + */ + useFillerType() {} } diff --git a/packages/ckeditor5-markdown-gfm/tests/gfmdataprocessor/gfmdataprocessor.js b/packages/ckeditor5-markdown-gfm/tests/gfmdataprocessor/gfmdataprocessor.js new file mode 100644 index 00000000000..8fa6d261862 --- /dev/null +++ b/packages/ckeditor5-markdown-gfm/tests/gfmdataprocessor/gfmdataprocessor.js @@ -0,0 +1,25 @@ +/** + * @license Copyright (c) 2003-2021, CKSource - Frederico Knabben. All rights reserved. + * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license + */ + +import GFMDataProcessor from '../../src/gfmdataprocessor'; +import ViewDocument from '@ckeditor/ckeditor5-engine/src/view/document'; +import { StylesProcessor } from '@ckeditor/ckeditor5-engine/src/view/stylesmap'; + +describe( 'GFMDataProcessor', () => { + let dataProcessor, viewDocument; + + beforeEach( () => { + viewDocument = new ViewDocument( new StylesProcessor() ); + dataProcessor = new GFMDataProcessor( viewDocument ); + } ); + + describe( 'useFillerType()', () => { + it( 'should have this method to be compatible with `DataProcessor` interface', () => { + expect( () => { + dataProcessor.useFillerType( 'default' ); + } ).not.to.throw(); + } ); + } ); +} );