mirror of
https://github.com/CharaChorder/DeviceManager.git
synced 2026-01-20 17:03:42 +00:00
81 lines
1.7 KiB
TypeScript
81 lines
1.7 KiB
TypeScript
import {
|
|
Decoration,
|
|
EditorView,
|
|
ViewPlugin,
|
|
ViewUpdate,
|
|
WidgetType,
|
|
} from "@codemirror/view";
|
|
import { syntaxTree } from "@codemirror/language";
|
|
import type { Range } from "@codemirror/state";
|
|
|
|
export class DelimWidget extends WidgetType {
|
|
constructor() {
|
|
super();
|
|
}
|
|
|
|
override eq(other: DelimWidget) {
|
|
return true;
|
|
}
|
|
|
|
toDOM() {
|
|
const element = document.createElement("span");
|
|
element.innerHTML = " ⇛ ";
|
|
element.style.scale = "1.8";
|
|
element.style.opacity = "0.5";
|
|
return element;
|
|
}
|
|
|
|
override ignoreEvent() {
|
|
return false;
|
|
}
|
|
|
|
override destroy() {}
|
|
}
|
|
|
|
function actionWidgets(view: EditorView) {
|
|
const widgets: Range<Decoration>[] = [];
|
|
for (const { from, to } of view.visibleRanges) {
|
|
syntaxTree(view.state).iterate({
|
|
from,
|
|
to,
|
|
enter: (node) => {
|
|
if (node.name !== "PhraseDelim") return;
|
|
let deco = Decoration.replace({
|
|
widget: new DelimWidget(),
|
|
});
|
|
widgets.push(deco.range(node.from, node.to));
|
|
},
|
|
});
|
|
}
|
|
return Decoration.set(widgets);
|
|
}
|
|
|
|
export const delimPlugin = ViewPlugin.fromClass(
|
|
class {
|
|
decorations = Decoration.none;
|
|
|
|
constructor(view: EditorView) {
|
|
this.decorations = actionWidgets(view);
|
|
}
|
|
|
|
update(update: ViewUpdate) {
|
|
if (
|
|
update.docChanged ||
|
|
update.viewportChanged ||
|
|
syntaxTree(update.startState) != syntaxTree(update.state)
|
|
)
|
|
this.decorations = actionWidgets(update.view);
|
|
}
|
|
},
|
|
{
|
|
decorations(instance) {
|
|
return instance.decorations;
|
|
},
|
|
provide(plugin) {
|
|
return EditorView.atomicRanges.of(
|
|
(view) => view.plugin(plugin)?.decorations ?? Decoration.none,
|
|
);
|
|
},
|
|
},
|
|
);
|