Please don't be angry, I don't know what I am doing. My end goal is to create a simple plugin for Obsidian which adds line numbering to codeblocks in the editor/live-preview mode, and I can highlight specific lines. As far as I know Obsidian uses CodeMirror editor. I also found that there is theoretically a simple way to add a gutter as described here: https://codemirror.net/examples/gutter/ but I couldn't make it work. The below code does work (sort of...). It does add line numbering, but the text which the codeblocks contains disappears. I would really appreciate if someone could provide a simple example, or correct my code, or point me in the right direction.
My code so far:
class EmojiListPlugin implements PluginValue {
decorations: DecorationSet;
constructor(view: EditorView) {
this.decorations = this.buildDecorations(view);
}
update(update: ViewUpdate) {
if (update.docChanged || update.viewportChanged) {
this.decorations = this.buildDecorations(update.view);
}
}
destroy() {}
buildDecorations(view: EditorView): DecorationSet {
const builder = new RangeSetBuilder<Decoration>();
let lineNumber = 1;
for (let { from, to } of view.visibleRanges) {
syntaxTree(view.state).iterate({ from, to, enter(node) {
console.log("+++ node enter");
if (node.type.id === 3 ) {
// opening ```
}
if (node.type.id === 5 ) {
builder.add(
node.from,
node.to,
Decoration.replace({
widget: new LineNumberingWidget(lineNumber ),
})
);
lineNumber++;
}
if (node.type.id === 6 ) {
// closing ```
lineNumber = 1;
}
},
leave(node)
{
// console.log("--- node exit");
},
});
}
return builder.finish();
}// buildDecorations
}// EmojiListPlugin
const pluginSpec: PluginSpec<EmojiListPlugin> = {
decorations: (value: EmojiListPlugin) => value.decorations,
widget: (value: EmojiListPlugin) => new LineNumberingWidget(value.lineNumber),
};
class LineNumberingWidget extends WidgetType {
lineNumber: number;
constructor(lineNumber: number ) {
super();
this.lineNumber = lineNumber;
}
toDOM(view: EditorView): HTMLElement {
// create an element for the line number
const lineNumberElement = document.createElement("span");
lineNumberElement.classList.add("gutter");
lineNumberElement.innerText = `${this.lineNumber}: `;
return lineNumberElement;
}// toDOM
}// LineNumberingWidget
export const emojiListPlugin = ViewPlugin.fromClass(
EmojiListPlugin,
pluginSpec
);
export default class LineNumberingPlugin extends Plugin {
settings: LinkifySettings;
viewPlugins: LinkifyViewPlugin[] = [];
async onload() {
this.registerEditorExtension( ViewPlugin.fromClass(EmojiListPlugin, pluginSpec));
console.log("Plugin is registered");
}
}