Fix client-driven directive updates
parent
56e5466b19
commit
0ebbe2e7f3
|
@ -15,13 +15,13 @@ export async function updateDirectivesOnPageCommand() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Collect all directives and their body replacements
|
// Collect all directives and their body replacements
|
||||||
const replacements: { startInst: string; text?: string }[] = [];
|
const replacements: { fullMatch: string; text?: string }[] = [];
|
||||||
|
|
||||||
await replaceAsync(
|
await replaceAsync(
|
||||||
text,
|
text,
|
||||||
directiveRegex,
|
directiveRegex,
|
||||||
async (fullMatch, startInst, _type, _arg, _body, endInst, index) => {
|
async (fullMatch, startInst, _type, _arg, _body, endInst, index) => {
|
||||||
const replacement: { startInst: string; text?: string } = { startInst };
|
const replacement: { fullMatch: string; text?: string } = { fullMatch };
|
||||||
// Pushing to the replacement array
|
// Pushing to the replacement array
|
||||||
replacements.push(replacement);
|
replacements.push(replacement);
|
||||||
const currentNode = nodeAtPos(tree, index + 1);
|
const currentNode = nodeAtPos(tree, index + 1);
|
||||||
|
@ -44,34 +44,32 @@ export async function updateDirectivesOnPageCommand() {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
let counter = 0;
|
|
||||||
// Iterate again and replace the bodies. Iterating again (not using previous positions)
|
// Iterate again and replace the bodies. Iterating again (not using previous positions)
|
||||||
// because text may have changed in the mean time (directive processing may take some time)
|
// because text may have changed in the mean time (directive processing may take some time)
|
||||||
// Hypothetically in the mean time directives in text may have been changed/swapped, in which
|
// Hypothetically in the mean time directives in text may have been changed/swapped, in which
|
||||||
// case this will break. This would be a rare edge case, however.
|
// case this will break. This would be a rare edge case, however.
|
||||||
await replaceAsync(
|
for (const replacement of replacements) {
|
||||||
text,
|
// Fetch the text every time, because dispatch() will have been made changes
|
||||||
directiveRegex,
|
const text = await editor.getText();
|
||||||
async (fullMatch, startInst, _type, _arg, _body, endInst, index) => {
|
// Determine the current position
|
||||||
const replacement = replacements[counter++];
|
const index = text.indexOf(replacement.fullMatch);
|
||||||
if (!replacement.text) {
|
|
||||||
return `${startInst}\n$**ERROR:** Internal error, no replacement found\n${endInst}`;
|
// This may happen if the query itself, or the user is editing inside the directive block (WHY!?)
|
||||||
}
|
if (index === -1) {
|
||||||
if (replacement.text === fullMatch) {
|
console.warn(
|
||||||
// No change, no need to dispatch
|
"Could not find directive in text, skipping",
|
||||||
return fullMatch;
|
replacement.fullMatch,
|
||||||
}
|
);
|
||||||
// Dispatch the change as a somewhat minimal diff in order not to interfere with current editing
|
continue;
|
||||||
await editor.dispatch({
|
}
|
||||||
changes: {
|
await editor.dispatch({
|
||||||
from: index,
|
changes: {
|
||||||
to: index + fullMatch.length,
|
from: index,
|
||||||
insert: replacement.text,
|
to: index + replacement.fullMatch.length,
|
||||||
},
|
insert: replacement.text,
|
||||||
});
|
},
|
||||||
return replacement.text;
|
});
|
||||||
},
|
}
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Called from client, running on server
|
// Called from client, running on server
|
||||||
|
|
Loading…
Reference in New Issue