Trilium Frontend API
    Preparing search index...

    Class ModelWriter

    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 module:engine/model/model~Model#change change() or module:engine/model/model~Model#enqueueChange 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 module:engine/model/schema~ModelSchema. It is possible to create incorrect model structures by using the writer. Read more about in {@glink framework/deep-dive/schema#who-checks-the-schema "Who checks the schema?"}.

    • module:engine/model/model~Model#change
    • module:engine/model/model~Model#enqueueChange
    Index

    Constructors

    • Internal

      Creates a writer instance.

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

      Parameters

      Returns ModelWriter

    Properties

    batch: Batch

    The batch to which this writer will add changes.

    model: Model

    Instance of the model on which this writer operates.

    Methods

    • Adds a module:engine/model/markercollection~Marker 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 module:engine/model/markercollection~Marker 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 module:core/editor/editor~Editor#getData editor.getData() method. When set to true it fires the module:engine/model/document~ModelDocument#event:change:data change:data event. When set to false it fires the module:engine/model/document~ModelDocument#event:change 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: { affectsData?: boolean; range: ModelRange; usingOperation: boolean }
        • OptionalaffectsData?: boolean

          Flag indicating that the marker changes the editor data.

        • range: ModelRange

          Marker range.

        • usingOperation: boolean

          Flag indicating that the marker should be added by MarkerOperation. See module:engine/model/markercollection~Marker#managedUsingOperations.

      Returns Marker

      Marker that was set.

      module:engine/model/markercollection~Marker

    • Adds a new root to the document (or re-attaches a #detachRoot detached root).

      Throws an error, if trying to add a root that is already added and attached.

      Parameters

      • rootName: string

        Name of the added root.

      • OptionalelementName: string

        The element name. Defaults to '$root' which also has some basic schema defined (e.g. $block elements are allowed inside the $root). Make sure to define a proper schema if you use a different name.

      Returns ModelRootElement

      The added root element.

    • 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 module:engine/model/range~ModelRange range instead of an module:engine/model/item~ModelItem item use module:engine/model/writer~ModelWriter#move Writer#move().

      Parameters

      Returns void

    • Creates element and inserts it at the end of the parent.

      writer.appendElement( 'paragraph', root );
      

      Parameters

      Returns void

      WITHOUT_ATTRIBUTES

    • Creates element with specified attributes and inserts it at the end of the parent.

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

      Parameters

      Returns void

      WITH_ATTRIBUTES

    • Creates text node and inserts it at the end of the parent.

      writer.appendText( 'foo', paragraph );
      

      Parameters

      Returns void

      WITHOUT_ATTRIBUTES

    • Creates text node with specified attributes and inserts it at the end of the parent.

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

      Parameters

      Returns void

      WITH_ATTRIBUTES

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

      Parameters

      • itemOrRange: ModelItem | ModelRange

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

      Returns void

    • Creates a copy of the element and returns it. Created element has the same name and attributes as the original element. If clone is deep, the original element's children are also cloned. If not, then empty element is returned.

      Parameters

      • element: ModelElement

        The element to clone.

      • Optionaldeep: boolean

        If set to true clones element and all its children recursively. When set to false, element will be cloned without any child.

      Returns ModelElement

    • Creates a new module:engine/model/documentfragment~ModelDocumentFragment document fragment.

      Returns ModelDocumentFragment

      Created document fragment.

    • Creates a new module:engine/model/element~ModelElement element.

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

      Parameters

      Returns ModelElement

      Created element.

    • Shortcut for module:engine/model/model~Model#createPositionAfter Model#createPositionAfter().

      Parameters

      • item: ModelItem

        Item after which the position should be placed.

      Returns ModelPosition

    • Shortcut for module:engine/model/model~Model#createPositionBefore Model#createPositionBefore().

      Parameters

      • item: ModelItem

        Item after which the position should be placed.

      Returns ModelPosition

    • Shortcut for module:engine/model/model~Model#createRange Model#createRange().

      Parameters

      • start: ModelPosition

        Start position.

      • Optionalend: ModelPosition

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

      Returns ModelRange

    • Shortcut for module:engine/model/model~Model#createRangeOn Model#createRangeOn().

      Parameters

      • element: ModelItem

        Element which is a parent for the range.

      Returns ModelRange

    • Creates a new module:engine/model/text~ModelText text node.

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

      Parameters

      Returns ModelText

      Created text node.

    • Detaches the root from the document.

      All content and markers are removed from the root upon detaching. New content and new markers cannot be added to the root, as long as it is detached.

      A root cannot be fully removed from the document, it can be only detached. A root is permanently removed only after you re-initialize the editor and do not specify the root in the initial data.

      A detached root can be re-attached using #addRoot.

      Throws an error if the root does not exist or the root is already detached.

      Parameters

      Returns void

    • 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 #createPositionAt 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 module:engine/model/range~ModelRange range instead of an module:engine/model/item~ModelItem item use module:engine/model/writer~ModelWriter#move Writer#move().

      Note: For a paste-like content insertion mechanism see module:engine/model/model~Model#insertContent model.insertContent().

      Parameters

      Returns void

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

      writer.insertElement( 'paragraph', 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 #createPositionAt writer.createPositionAt().

      Parameters

      Returns void

      WITHOUT_ATTRIBUTES

    • Creates and inserts element with specified attributes on given 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', { alignment: 'center' }, root, 5 );
      // Inserts paragraph at the end of a blockquote:
      writer.insertElement( 'paragraph', { alignment: 'center' }, blockquote, 'end' );
      // Inserts after an image:
      writer.insertElement( 'paragraph', { alignment: 'center' }, image, 'after' );

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

      Parameters

      Returns void

      WITH_ATTRIBUTES

    • Creates and inserts text on given position.

      writer.insertText( 'foo', 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 #createPositionAt writer.createPositionAt().

      Parameters

      • text: string

        Text data.

      • OptionalitemOrPosition: ModelItem | ModelPosition
      • Optionaloffset: ModelPositionOffset

        Offset or one of the flags. Used only when second parameter is a module:engine/model/item~ModelItem model item.

      Returns void

      WITHOUT_ATTRIBUTES

    • Creates and inserts text with specified attributes on given 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', { bold: true }, paragraph, 5 );
      // Inserts 'foo' at the end of a paragraph:
      writer.insertText( 'foo', { bold: true }, paragraph, 'end' );
      // Inserts 'foo' after an image:
      writer.insertText( 'foo', { bold: true }, image, 'after' );

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

      Parameters

      Returns void

      WITH_ATTRIBUTES

    • 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

      Returns void

    • 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 work the same way as #createPositionAt 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 module:engine/model/document~ModelDocument#roots documents roots, but you cannot move items from document fragment to the document or from one detached element to another. Use module:engine/model/writer~ModelWriter#insert in such cases.

      Parameters

      Returns void

    • Temporarily changes the module:engine/model/documentselection~ModelDocumentSelection#isGravityOverridden 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 bold="true">biz
      
      • 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.

    • Removes given model module:engine/model/item~ModelItem item or module:engine/model/range~ModelRange range.

      Parameters

      Returns void

    • Removes an attribute with given key from a module:engine/model/item~ModelItem model item or from a module:engine/model/range~ModelRange range.

      Parameters

      • key: string

        Attribute key.

      • itemOrRange: ModelItem | ModelRange

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

      Returns void

    • Removes given module:engine/model/markercollection~Marker 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: string | Marker

        Marker or marker name to remove.

      Returns void

    • 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, any, any>

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

      Returns void

    • Restores ~ModelWriter#overrideSelectionGravity gravity to default.

      Restoring the gravity is only possible using the unique identifier returned by ~ModelWriter#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 ~ModelWriter#overrideSelectionGravity.

      Returns void

    • Sets value of the attribute with given key on a module:engine/model/item~ModelItem model item or on a module:engine/model/range~ModelRange range.

      Parameters

      • key: string

        Attribute key.

      • value: unknown

        Attribute new value.

      • itemOrRange: ModelItem | ModelRange

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

      Returns void

    • Sets values of attributes on a module:engine/model/item~ModelItem model item or on a module:engine/model/range~ModelRange range.

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

      Parameters

      Returns void

    • Sets the document's selection (ranges and direction) to the specified location based on the given module:engine/model/selection~ModelSelectable selectable or creates an empty selection if no arguments were passed.

      // Sets collapsed selection at the position of the given node and an offset.
      writer.setSelection( paragraph, offset );

      Creates a range inside an module:engine/model/element~ModelElement 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 module:engine/model/item~ModelItem item which starts before the item and ends just after the item.

      writer.setSelection( paragraph, 'on' );
      

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

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

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

      See also: #setSelection:SELECTABLE setSelection( selectable, options ).

      Parameters

      Returns void

      NODE_OFFSET

    • Sets the document's selection (ranges and direction) to the specified location based on the given module:engine/model/selection~ModelSelectable 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 );

      // 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.

      See also: #setSelection:NODE_OFFSET setSelection( node, placeOrOffset, options ).

      Parameters

      Returns void

      SELECTABLE

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

      writer.setSelectionAttribute( 'italic', true );
      

      Parameters

      • key: string

        Key of the attribute to set.

      • value: unknown

        Attribute value.

      Returns void

      KEY_VALUE

    • Sets attributes on the selection. If any attribute with the same key already is set, it's value is overwritten.

      Using key-value object:

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

      Using iterable object:

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

      Parameters

      Returns void

      OBJECT

    • Moves module:engine/model/documentselection~ModelDocumentSelection#focus to the specified location.

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

      Parameters

      Returns void

    • 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

      Returns { position: ModelPosition; range: ModelRange }

      Split result with properties:

      • position - Position between split elements.
      • range - Range that stars from the end of the first split element and ends at the beginning of the first copy 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

      Returns void

    • Adds, updates or refreshes a module:engine/model/markercollection~Marker 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.

      Note: If you want to change the module:engine/view/element~ViewElement view element of the marker while its data in the model remains the same, use the dedicated module:engine/controller/editingcontroller~EditingController#reconvertMarker method.

      The options.usingOperation parameter lets you change if the marker should be managed by operations or not. See module:engine/model/markercollection~Marker 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 module:core/editor/editor~Editor#getData editor.getData() method. When set to true it fires the module:engine/model/document~ModelDocument#event:change:data change:data event. When set to false it fires the module:engine/model/document~ModelDocument#event:change 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.

      • Optionaloptions: { affectsData?: boolean; range?: ModelRange; usingOperation?: boolean }

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

        • OptionalaffectsData?: boolean

          Flag indicating that the marker changes the editor data.

        • Optionalrange?: ModelRange

          Marker range to update.

        • OptionalusingOperation?: boolean

          Flag indicated whether the marker should be added by MarkerOperation. See module:engine/model/markercollection~Marker#managedUsingOperations.

      Returns void

      module:engine/model/markercollection~Marker

    • 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 module:engine/model/range~ModelRange#isFlat Range#isFlat). If not, an error will be thrown.

      Parameters

      • range: ModelRange

        Range to wrap.

      • elementOrString: string | ModelElement

        Element or name of element to wrap the range with.

      Returns void