Autocomplete doubles already typed characters

Hello,

I’m currently in the migration from v5 to v6.

Most of the things are working well, except one
thing which I’m not able to fix.

I added my own autocompletion suggestions.
E.g. I added the suggestion {{order_number}}
as type variable.

If I’m now in the editor and I type {{or, then I get
suggestions like {{order_number}}.

When I select this suggestion via the arrow keys and hit enter,
then {{{{order_number}} is inserted, so the first { is doubled.

Do you know how I can fix this?

As follows the code how I initialize the editor.

import { EditorView, keymap } from "@codemirror/view"
import { defaultKeymap } from "@codemirror/commands"
import { liquid } from "@codemirror/lang-liquid"
import { tomorrow } from "thememirror";
import { autocompletion } from "@codemirror/autocomplete"

function editorFromTextArea(textarea, extensions) {
    let view = new EditorView({ 
        doc: textarea.value, 
        extensions: extensions 
    })
    textarea.parentNode.insertBefore(view.dom, textarea)
    textarea.style.display = "none"
    if (textarea.form) textarea.form.addEventListener("submit", () => {
        textarea.value = view.state.doc.toString()
    })
    return view
}  

function liquidCompletions(context) {
    console.log();
    let word = context.matchBefore(/\w*/)
    let word_list_dom = $(context.view.dom).parent().nextAll(".autocomplete_list").first();
    if (word_list_dom == []) {
        word_list_dom = $("#autocomplete_list");
    }
    let word_list = [];
    if (word_list_dom && word_list_dom.text() != "") {
        word_list = word_list_dom.text().trim().split(",");
    }
    let completion_options = [];
    for (let i = 0; i < word_list.length; i++) {
        let liquid_var = word_list[i];
        completion_options.push({
            label: liquid_var,
            type: "variable"
        });
    }
    console.log(completion_options);
    if (word.from == word.to && !context.explicit)
        return null
    return {
        from: word.from,
        options: completion_options
    }
  }

$(function() {
    $('.language-liquid').each(function () {
        var editor = editorFromTextArea(this, [
            tomorrow,
            EditorView.lineWrapping,
            keymap.of([...defaultKeymap, { key: "Ctrl-Space", run: "autocomplete" }]),
            liquid(),
            EditorView.editorAttributes.of({class: "form-control"}),
            autocompletion({
                override: [liquidCompletions]
            })
        ]);
    });
});

Thank you!

Parsing the word list from the DOM on every single call to the completion source seems like a bad idea. And your key binding for Ctrl-Space is putting a string where a command function is expected. But neither of those should cause the issue you describe—I’m not sure where that’s coming from.

Thank you for your fast response.

I updated my code to check if it works with your suggestions, but still no luck.

As follows my new code:

import { EditorView, keymap } from "@codemirror/view"
import { defaultKeymap } from "@codemirror/commands"
import { liquid } from "@codemirror/lang-liquid"
import { tomorrow } from "thememirror";
import { autocompletion } from "@codemirror/autocomplete"

function editorFromTextArea(textarea, extensions) {
    let view = new EditorView({ 
        doc: textarea.value, 
        extensions: extensions 
    })
    textarea.parentNode.insertBefore(view.dom, textarea)
    textarea.style.display = "none"
    if (textarea.form) textarea.form.addEventListener("submit", () => {
        textarea.value = view.state.doc.toString()
    })
    return view
}  

function liquidCompletions(context) {
    console.log();
    let word = context.matchBefore(/\w*/)
    let word_list_dom = $(context.view.dom).parent().nextAll(".autocomplete_list").first();
    if (word_list_dom == []) {
        word_list_dom = $("#autocomplete_list");
    }
    let word_list = [];
    if (word_list_dom && word_list_dom.text() != "") {
        word_list = word_list_dom.text().trim().split(",");
    }
    let completion_options = [];
    word_list = ["{{order_number}}", "{{customer_name}}", "{{product_name}}"];
    for (let i = 0; i < word_list.length; i++) {
        let liquid_var = word_list[i];
        completion_options.push({
            label: liquid_var,
            type: "variable"
        });
    }
    console.log(completion_options);
    if (word.from == word.to && !context.explicit)
        return null
    return {
        from: word.from,
        options: completion_options
    }
  }

$(function() {
    $('.language-liquid').each(function () {
        var editor = editorFromTextArea(this, [
            tomorrow,
            EditorView.lineWrapping,
            keymap.of([...defaultKeymap]),
            liquid(),
            EditorView.editorAttributes.of({class: "form-control"}),
            autocompletion({
                override: [liquidCompletions]
            })
        ]);
    });
});

I fixed it by changing the matchbefore to .matchBefore(/[^ \n]*/)