javascriptgoogle-chrome-extensionckeditor5

In a chrome extension on a CKEditor5 instance, how to delete last x characters at caret position before inserting content


I am working on a chrome extension which replaces abbreviations with expanded text. I am handling a specific case for CKEditor5. As the CKEditor instance is available only in the background executing a script in world 'MAIN', I execute this script there:

function injectScript(text, shortcut) {
    const ckEditorElement = document.querySelector('.ck-editor__editable');

    const ckEditorInstance = ckEditorElement?.ckeditorInstance;

    if (ckEditorInstance) {
        ckEditorInstance.model.change( writer => {
            const insertPosition = ckEditorInstance.model.document.selection.getFirstPosition();

            const selectionAttributes = ckEditorInstance.model.document.selection.getAttributes();

            // Delete the last `shortcut.length` characters before inserting content

            ckEditorInstance.model.insertContent( writer.createText( text, selectionAttributes ), insertPosition );
        });
    }
}

What I can't figure out is how to delete the abbreviation before inserting the expanded text.

For example: if I write //brb I want to remove that abbreviation and replace it with be right back. Currently I get something like //brbe right back as I haven't figured out how to delete it.

I tried using this function on the model that I found in the documentation https://ckeditor.com/docs/ckeditor5/latest/api/module_engine_model_model-Model.html#function-deleteContent but I can't figure out if this is the right function for this and how to use it.


Solution

  • I found a solution myself.

    const startPosition = insertPosition.getShiftedBy(-shortcut.length);
    
    const range = writer.createRange(startPosition, insertPosition);
    
    const selection = writer.createSelection(range);
    
    ckEditorInstance.model.deleteContent(selection);
    
    1. Clone a position at the start of the abbreviation by using getShiftedBy
    2. Create a range using those two positions
    3. Create a selection using the range
    4. Pass the selection to deleteContent function on the model.