Class

Writer (engine/model)

@ckeditor/ckeditor5-engine/src/model/writer

class

The model can only be modified by using the writer. It should be used whenever you want to create a node, modify child nodes, attributes or text, set the selection's position and its attributes.

The instance of the writer is only available in the change() or enqueueChange().

model.change( writer => {
    writer.insertText( 'foo', paragraph, 'end' );
} );

Note that the writer should never be stored and used outside of the change() and enqueueChange() blocks.

Note that writer's methods do not check the Schema. It is possible to create incorrect model structures by using the writer. Read more about in "Who checks the schema?".

Filtering

Properties

  • batch : Batch

    readonly

    The batch to which this writer will add changes.

  • model : Model

    readonly

    Instance of the model on which this writer operates.

Methods

  • constructor( model, batch )

    protected

    Creates a writer instance.

    Note: It is not recommended to use it directly. Use Model#change() or Model#enqueueChange() instead.

    Parameters

    model : Model
    batch : Batch
  • addMarker( name, options = { options.usingOperation, options.range, [options.affectsData] } ) → Marker

    Adds a marker. Marker is a named range, which tracks changes in the document and updates its range automatically, when model tree changes.

    As the first parameter you can set marker name.

    The required options.usingOperation parameter lets you decide if the marker should be managed by operations or not. See marker class description to learn about the difference between markers managed by operations and not-managed by operations.

    The options.affectsData parameter, which defaults to false, allows you to define if a marker affects the data. It should be true when the marker change changes the data returned by the editor.getData() method. When set to true it fires the change:data event. When set to false it fires the change event.

    Create marker directly base on marker's name:

    addMarker( markerName, { range, usingOperation: false } );

    Create marker using operation:

    addMarker( markerName, { range, usingOperation: true } );

    Create marker that affects the editor data:

    addMarker( markerName, { range, usingOperation: false, affectsData: true } );

    Note: For efficiency reasons, it's best to create and keep as little markers as possible.

    Parameters

    name : String

    Name of a marker to create - must be unique.

    options : Object
    Properties
    options.usingOperation : Boolean

    Flag indicating that the marker should be added by MarkerOperation. See managedUsingOperations.

    options.range : Range

    Marker range.

    [ options.affectsData ] : Boolean

    Flag indicating that the marker changes the editor data.

    Defaults to false

    Returns

    Marker

    Marker that was set.

    Related:

  • append( item, parent )

    Inserts item at the end of the given parent.

    const paragraph = writer.createElement( 'paragraph' );
    writer.append( paragraph, root );

    Note that if the item already has parent it will be removed from the previous parent.

    If you want to move range instead of an item use Writer#move().

    Parameters

    item : Item | DocumentFragment

    Item or document fragment to insert.

    parent : Element | DocumentFragment
  • appendElement( name, [ attributes ], parent )

    Creates element and inserts it at the end of the parent. You can optionally set attributes:

    writer.appendElement( 'paragraph', root );
    writer.appendElement( 'paragraph', { alignment: 'center' }, root );

    Parameters

    name : String

    Name of the element.

    [ attributes ] : Object

    Elements attributes.

    parent : Element | DocumentFragment
  • appendText( text, [ attributes ], parent )

    Creates text node and inserts it at the end of the parent. You can optionally set text attributes:

    writer.appendText( 'foo', paragraph );
    writer.appendText( 'foo', { bold: true }, paragraph );

    Parameters

    text : String

    Text data.

    [ attributes ] : Object

    Text attributes.

    parent : Element | DocumentFragment
  • clearAttributes( itemOrRange )

    Removes all attributes from all elements in the range or from the given item.

    Parameters

    itemOrRange : Item | Range

    Model item or range from which all attributes will be removed.

  • createDocumentFragment() → DocumentFragment

    Returns

    DocumentFragment

    Created document fragment.

  • createElement( name, [ attributes ] ) → Element

    Creates a new element.

    writer.createElement( 'paragraph' );
    writer.createElement( 'paragraph', { alignment: 'center' } );

    Parameters

    name : String

    Name of the element.

    [ attributes ] : Object

    Elements attributes.

    Returns

    Element

    Created element.

  • createPositionAfter( item ) → Position

    Parameters

    item : Item

    Item after which the position should be placed.

    Returns

    Position
  • createPositionAt( itemOrPosition, [ offset ] ) → Position

    Parameters

    itemOrPosition : Item | Position
    [ offset ] : Number | 'end' | 'before' | 'after'

    Offset or one of the flags. Used only when first parameter is a model item.

    Returns

    Position
  • createPositionBefore( item ) → Position

    Parameters

    item : Item

    Item after which the position should be placed.

    Returns

    Position
  • createPositionFromPath( root, path, [ stickiness ] ) → Position

    Parameters

    root : Element | DocumentFragment

    Root of the position.

    path : Array.<Number>

    Position path. See path.

    [ stickiness ] : PositionStickiness

    Position stickiness. See PositionStickiness.

    Defaults to 'toNone'

    Returns

    Position
  • createRange( start, [ end ] ) → Range

    Parameters

    start : Position

    Start position.

    [ end ] : Position

    End position. If not set, range will be collapsed at start position.

    Returns

    Range
  • createRangeIn( element ) → Range

    Parameters

    element : Element

    Element which is a parent for the range.

    Returns

    Range
  • createRangeOn( element ) → Range

    Parameters

    element : Element

    Element which is a parent for the range.

    Returns

    Range
  • createSelection( selectable, [ placeOrOffset ], [ options ] = { [options.backward] } ) → Selection

    Parameters

    selectable : Selectable
    [ placeOrOffset ] : Number | 'before' | 'end' | 'after' | 'on' | 'in'

    Sets place or offset of the selection.

    [ options ] : Object
    Properties
    [ options.backward ] : Boolean

    Sets this selection instance to be backward.

    Returns

    Selection
  • createText( data, [ attributes ] ) → Text

    Creates a new text node.

    writer.createText( 'foo' );
    writer.createText( 'foo', { bold: true } );

    Parameters

    data : String

    Text data.

    [ attributes ] : Object

    Text attributes.

    Returns

    Text

    Created text node.

  • insert( item, itemOrPosition, [ offset ] )

    Inserts item on given position.

    const paragraph = writer.createElement( 'paragraph' );
    writer.insert( paragraph, position );

    Instead of using position you can use parent and offset:

    const text = writer.createText( 'foo' );
    writer.insert( text, paragraph, 5 );

    You can also use end instead of the offset to insert at the end:

    const text = writer.createText( 'foo' );
    writer.insert( text, paragraph, 'end' );

    Or insert before or after another element:

    const paragraph = writer.createElement( 'paragraph' );
    writer.insert( paragraph, anotherParagraph, 'after' );

    These parameters works the same way as writer.createPositionAt().

    Note that if the item already has parent it will be removed from the previous parent.

    Note that you cannot re-insert a node from a document to a different document or a document fragment. In this case, model-writer-insert-forbidden-move is thrown.

    If you want to move range instead of an item use Writer#move().

    Note: For a paste-like content insertion mechanism see model.insertContent().

    Parameters

    item : Item | DocumentFragment

    Item or document fragment to insert.

    itemOrPosition : Item | Position
    [ offset ] : Number | 'end' | 'before' | 'after'

    Offset or one of the flags. Used only when second parameter is a model item.

    Defaults to 0

  • insertElement( name, [ attributes ], itemOrPosition, [ offset ] )

    Creates and inserts element on given position. You can optionally set attributes:

    writer.insertElement( 'paragraph', position );
    writer.insertElement( 'paragraph', { alignment: 'center' }, position );

    Instead of using position you can use parent and offset or define that text should be inserted at the end or before or after other node:

    // Inserts paragraph in the root at offset 5:
    writer.insertElement( 'paragraph', root, 5 );
    // Inserts paragraph at the end of a blockquote:
    writer.insertElement( 'paragraph', blockquote, 'end' );
    // Inserts after an image:
    writer.insertElement( 'paragraph', image, 'after' );

    These parameters works the same way as writer.createPositionAt().

    Parameters

    name : String

    Name of the element.

    [ attributes ] : Object

    Elements attributes.

    itemOrPosition : Item | Position
    [ offset ] : Number | 'end' | 'before' | 'after'

    Offset or one of the flags. Used only when third parameter is a model item.

  • insertText( data, [ attributes ], itemOrPosition, [ offset ] )

    Creates and inserts text on given position. You can optionally set text attributes:

    writer.insertText( 'foo', position );
    writer.insertText( 'foo', { bold: true }, position );

    Instead of using position you can use parent and offset or define that text should be inserted at the end or before or after other node:

    // Inserts 'foo' in paragraph, at offset 5:
    writer.insertText( 'foo', paragraph, 5 );
    // Inserts 'foo' at the end of a paragraph:
    writer.insertText( 'foo', paragraph, 'end' );
    // Inserts 'foo' after an image:
    writer.insertText( 'foo', image, 'after' );

    These parameters work in the same way as writer.createPositionAt().

    Parameters

    data : String

    Text data.

    [ attributes ] : Object

    Text attributes.

    itemOrPosition : Item | Position
    [ offset ] : Number | 'end' | 'before' | 'after'

    Offset or one of the flags. Used only when third parameter is a model item.

  • merge( position )

    Merges two siblings at the given position.

    Node before and after the position have to be an element. Otherwise writer-merge-no-element-before or writer-merge-no-element-after error will be thrown.

    Parameters

    position : Position

    Position between merged elements.

  • move( range, itemOrPosition, [ offset ] )

    Moves all items in the source range to the target position.

    writer.move( sourceRange, targetPosition );

    Instead of the target position you can use parent and offset or define that range should be moved to the end or before or after chosen item:

    // Moves all items in the range to the paragraph at offset 5:
    writer.move( sourceRange, paragraph, 5 );
    // Moves all items in the range to the end of a blockquote:
    writer.move( sourceRange, blockquote, 'end' );
    // Moves all items in the range to a position after an image:
    writer.move( sourceRange, image, 'after' );

    These parameters works the same way as writer.createPositionAt().

    Note that items can be moved only within the same tree. It means that you can move items within the same root (element or document fragment) or between documents roots, but you can not move items from document fragment to the document or from one detached element to another. Use insert in such cases.

    Parameters

    range : Range

    Source range.

    itemOrPosition : Item | Position
    [ offset ] : Number | 'end' | 'before' | 'after'

    Offset or one of the flags. Used only when second parameter is a model item.

  • overrideSelectionGravity() → String

    Temporarily changes the gravity of the selection from left to right.

    The gravity defines from which direction the selection inherits its attributes. If it's the default left gravity, then the selection (after being moved by the user) inherits attributes from its left-hand side. This method allows to temporarily override this behavior by forcing the gravity to the right.

    For the following model fragment:

    <$text bold="true" linkHref="url">bar[]</$text><$text bold="true">biz</$text>
    • Default gravity: selection will have the bold and linkHref attributes.
    • Overridden gravity: selection will have bold attribute.

    Note: It returns an unique identifier which is required to restore the gravity. It guarantees the symmetry of the process.

    Returns

    String

    The unique id which allows restoring the gravity.

  • remove( itemOrRange )

    Removes given model item or range.

    Parameters

    itemOrRange : Item | Range

    Model item or range to remove.

  • removeAttribute( key, itemOrRange )

    Removes an attribute with given key from a model item or from a range.

    Parameters

    key : String

    Attribute key.

    itemOrRange : Item | Range

    Model item or range from which the attribute will be removed.

  • removeMarker( markerOrName )

    Removes given marker or marker with given name. The marker is removed accordingly to how it has been created, so if the marker was created using operation, it will be destroyed using operation.

    Parameters

    markerOrName : Marker | String

    Marker or marker name to remove.

  • removeSelectionAttribute( keyOrIterableOfKeys )

    Removes attribute(s) with given key(s) from the selection.

    Remove one attribute:

    writer.removeSelectionAttribute( 'italic' );

    Remove multiple attributes:

    writer.removeSelectionAttribute( [ 'italic', 'bold' ] );

    Parameters

    keyOrIterableOfKeys : String | Iterable.<String>

    Key of the attribute to remove or an iterable of attribute keys to remove.

  • rename( element, newName )

    Renames the given element.

    Parameters

    element : Element

    The element to rename.

    newName : String

    New element name.

  • restoreSelectionGravity( uid )

    Restores overrideSelectionGravity gravity to default.

    Restoring the gravity is only possible using the unique identifier returned by overrideSelectionGravity. Note that the gravity remains overridden as long as won't be restored the same number of times it was overridden.

    Parameters

    uid : String

    The unique id returned by overrideSelectionGravity.

  • setAttribute( key, value, itemOrRange )

    Sets value of the attribute with given key on a model item or on a range.

    Parameters

    key : String

    Attribute key.

    value : *

    Attribute new value.

    itemOrRange : Item | Range

    Model item or range on which the attribute will be set.

  • setAttributes( attributes, itemOrRange )

    Sets values of attributes on a model item or on a range.

    writer.setAttributes( {
        bold: true,
        italic: true
    }, range );

    Parameters

    attributes : Object

    Attributes keys and values.

    itemOrRange : Item | Range

    Model item or range on which the attributes will be set.

  • setSelection( selectable, [ placeOrOffset ], [ options ] = { [options.backward] } )

    Sets the document's selection (ranges and direction) to the specified location based on the given selectable or creates an empty selection if no arguments were passed.

    // Sets selection to the given range.
    const range = writer.createRange( start, end );
    writer.setSelection( range );
    
    // Sets selection to given ranges.
    const ranges = [ writer.createRange( start1, end2 ), writer.createRange( star2, end2 ) ];
    writer.setSelection( ranges );
    
    // Sets selection to other selection.
    const otherSelection = writer.createSelection();
    writer.setSelection( otherSelection );
    
    // Sets selection to the given document selection.
    const documentSelection = model.document.selection;
    writer.setSelection( documentSelection );
    
    // Sets collapsed selection at the given position.
    const position = writer.createPosition( root, path );
    writer.setSelection( position );
    
    // Sets collapsed selection at the position of the given node and an offset.
    writer.setSelection( paragraph, offset );

    Creates a range inside an element which starts before the first child of that element and ends after the last child of that element.

    writer.setSelection( paragraph, 'in' );

    Creates a range on an item which starts before the item and ends just after the item.

    writer.setSelection( paragraph, 'on' );
    
    // Removes all selection's ranges.
    writer.setSelection( null );

    Writer#setSelection() allow passing additional options (backward) as the last argument.

    // Sets selection as backward.
    writer.setSelection( range, { backward: true } );

    Throws writer-incorrect-use error when the writer is used outside the change() block.

    Parameters

    selectable : Selectable
    [ placeOrOffset ] : Number | 'before' | 'end' | 'after' | 'on' | 'in'

    Sets place or offset of the selection.

    [ options ] : Object
    Properties
    [ options.backward ] : Boolean

    Sets this selection instance to be backward.

  • setSelectionAttribute( keyOrObjectOrIterable, [ value ] )

    Sets attribute(s) on the selection. If attribute with the same key already is set, it's value is overwritten.

    Using key and value pair:

    writer.setSelectionAttribute( 'italic', true );

    Using key-value object:

    writer.setSelectionAttribute( { italic: true, bold: false } );

    Using iterable object:

    writer.setSelectionAttribute( new Map( [ [ 'italic', true ] ] ) );

    Parameters

    keyOrObjectOrIterable : String | Object | Iterable.<*>

    Key of the attribute to set or object / iterable of key => value attribute pairs.

    [ value ] : *

    Attribute value.

  • setSelectionFocus( itemOrPosition, [ offset ] )

    Moves focus to the specified location.

    The location can be specified in the same form as writer.createPositionAt() parameters.

    Parameters

    itemOrPosition : Item | Position
    [ offset ] : Number | 'end' | 'before' | 'after'

    Offset or one of the flags. Used only when first parameter is a model item.

    Defaults to 0

  • split( position, [ limitElement ] ) → Object

    Splits elements starting from the given position and going to the top of the model tree as long as given limitElement is reached. When limitElement is not defined then only the parent of the given position will be split.

    The element needs to have a parent. It cannot be a root element nor a document fragment. The writer-split-element-no-parent error will be thrown if you try to split an element with no parent.

    Parameters

    position : Position

    Position of split.

    [ limitElement ] : Node

    Stop splitting when this element will be reached.

    Returns

    Object

    result Split result.

    Position

    result.position Position between split elements.

    Range

    result.range Range that stars from the end of the first split element and ends at the beginning of the first copy element.

  • unwrap( element )

    Unwraps children of the given element – all its children are moved before it and then the element is removed. Throws error if you try to unwrap an element which does not have a parent.

    Parameters

    element : Element

    Element to unwrap.

  • updateMarker( markerOrName, [ options ] = { [options.range], [options.usingOperation], [options.affectsData] } )

    Adds, updates or refreshes a marker. Marker is a named range, which tracks changes in the document and updates its range automatically, when model tree changes. Still, it is possible to change the marker's range directly using this method.

    As the first parameter you can set marker name or instance. If none of them is provided, new marker, with a unique name is created and returned.

    As the second parameter you can set the new marker data or leave this parameter as empty which will just refresh the marker by triggering downcast conversion for it. Refreshing the marker is useful when you want to change the marker view element without changing any marker data.

    let isCommentActive = false;
    
    model.conversion.markerToHighlight( {
        model: 'comment',
        view: data => {
            const classes = [ 'comment-marker' ];
    
            if ( isCommentActive ) {
                classes.push( 'comment-marker--active' );
            }
    
            return { classes };
        }
    } );
    
    // Change the property that indicates if marker is displayed as active or not.
    isCommentActive = true;
    
    // And refresh the marker to convert it with additional class.
    model.change( writer => writer.updateMarker( 'comment' ) );

    The options.usingOperation parameter lets you change if the marker should be managed by operations or not. See marker class description to learn about the difference between markers managed by operations and not-managed by operations. It is possible to change this option for an existing marker.

    The options.affectsData parameter, which defaults to false, allows you to define if a marker affects the data. It should be true when the marker change changes the data returned by the editor.getData() method. When set to true it fires the change:data event. When set to false it fires the change event.

    Update marker directly base on marker's name:

    updateMarker( markerName, { range } );

    Update marker using operation:

    updateMarker( marker, { range, usingOperation: true } );
    updateMarker( markerName, { range, usingOperation: true } );

    Change marker's option (start using operations to manage it):

    updateMarker( marker, { usingOperation: true } );

    Change marker's option (inform the engine, that the marker does not affect the data anymore):

    updateMarker( markerName, { affectsData: false } );

    Parameters

    markerOrName : String | Marker

    Name of a marker to update, or a marker instance.

    [ options ] : Object

    If options object is not defined then marker will be refreshed by triggering downcast conversion for this marker with the same data.

    Properties
    [ options.range ] : Range

    Marker range to update.

    [ options.usingOperation ] : Boolean

    Flag indicated whether the marker should be added by MarkerOperation. See managedUsingOperations.

    [ options.affectsData ] : Boolean

    Flag indicating that the marker changes the editor data.

    Related:

  • wrap( range, elementOrString )

    Wraps the given range with the given element or with a new element (if a string was passed).

    Note: range to wrap should be a "flat range" (see Range#isFlat). If not, an error will be thrown.

    Parameters

    range : Range

    Range to wrap.

    elementOrString : Element | String

    Element or name of element to wrap the range with.

  • _addOperationForAffectedMarkers( type, positionOrRange )

    private

    For given action type and positionOrRange where the action happens, this function finds all affected markers and applies a marker operation with the new marker range equal to the current range. Thanks to this, the marker range can be later correctly processed during undo.

    Parameters

    type : 'move' | 'merge'

    Writer action type.

    positionOrRange : Position | Range

    Position or range where the writer action happens.

  • _assertWriterUsedCorrectly()

    private

    Throws writer-detached-writer-tries-to-modify-model error when the writer is used outside of the change() block.

  • _merge( position )

    private

    Performs merge action in a non-detached tree.

    Parameters

    position : Position

    Position between merged elements.

  • _mergeDetached( position )

    private

    Performs merge action in a detached tree.

    Parameters

    position : Position

    Position between merged elements.

  • _removeSelectionAttribute( key )

    private

    Parameters

    key : String

    Key of the attribute to remove.

  • _setSelectionAttribute( key, value )

    private

    Parameters

    key : String

    Key of the attribute to remove.

    value : *

    Attribute value.