I am trying to create an extension to replace variables of the form ${variable}
with a ReactJS component. It works very well, but when there are many variables, it slows down.
I based myself on the example in the documentation:
const variableMatcher = new MatchDecorator({
regexp: /\${([^}\r\n]+)}/g,
decoration: (match, view, pos) => {
return Decoration.replace({
widget: new VariableWidget(
match[1],
view,
pos + 2,
pos + match[0].length - 1
),
});
},
});
const variableHighlighter: Extension = ViewPlugin.fromClass(
class {
decorations: DecorationSet;
constructor(view: EditorView) {
this.decorations = variableMatcher.createDeco(view);
}
update(update: ViewUpdate) {
this.decorations = variableMatcher.updateDeco(update, this.decorations);
}
},
{
decorations: (instance) => instance.decorations,
provide: (plugin) =>
EditorView.atomicRanges.of((view) => {
return view.plugin(plugin)?.decorations || Decoration.none;
}),
}
);
I have the impression that every time I add a character in the editor, the entire content is reprocessed because when I put a console.log(match)
here:
decoration: (match, view, pos) => {
console.log(match);
return Decoration.replace({
widget: new VariableWidget(
match[1],
view,
pos + 2,
pos + match[0].length - 1
),
});
}
All variables are displayed in the console.
By debugging a bit here:
update(update: ViewUpdate) {
this.decorations = variableMatcher.updateDeco(update, this.decorations);
}
We realize that the updateDeco
of the MatchDecorator
calls createDeco
when viewportChanged
is true
(so always true
when I add a character).
I therefore feel that this is what causes the slowdowns since everything is recreated with each new character addition. The most logical thing would be to update only the line that contains modifications, right?
I think I am missing an important point.
Thank you for your help.