2
0
mirror of https://github.com/Ionaru/easy-markdown-editor synced 2025-08-14 12:42:45 -06:00

107 lines
4.0 KiB
TypeScript
Raw Normal View History

import { SelectionRange, StateEffect, Line } from "@codemirror/state";
import { ViewPlugin, ViewUpdate } from "@codemirror/view";
2023-04-28 02:51:04 +02:00
import { EasyMDE } from "../easymde";
import { countWords } from "../utils/count-words";
2023-04-28 02:51:04 +02:00
export class StatusBar {
2025-05-01 17:44:31 +02:00
element: HTMLDivElement;
2023-04-28 02:51:04 +02:00
2025-05-01 17:44:31 +02:00
#characterCount = 0;
#wordCount = 0;
#lineCount = 1;
#cursorLine = 1;
#cursorColumn = 1;
2023-04-28 02:51:04 +02:00
2025-05-01 17:44:31 +02:00
#selectionStart = 0;
#selectionEnd = 0;
2023-04-28 02:51:04 +02:00
2025-05-01 17:44:31 +02:00
constructor(private editor: EasyMDE) {
this.element = document.createElement("div");
this.element.className = "easymde-statusbar";
2023-04-28 02:51:04 +02:00
// Initial values
2025-05-01 17:44:31 +02:00
this.#characterCount = this.editor.codemirror.state.doc.length;
this.#wordCount = countWords(this.editor.codemirror.state.doc);
this.#lineCount = this.editor.codemirror.state.doc.lines;
2023-04-28 02:51:04 +02:00
const line = this.editor.codemirror.state.doc.lineAt(
this.editor.codemirror.state.selection.main.to,
);
2025-05-01 17:44:31 +02:00
this.#cursorLine = line.number;
this.#cursorColumn =
2023-04-28 02:51:04 +02:00
this.editor.codemirror.state.selection.main.to - line.from + 1;
2025-05-01 17:44:31 +02:00
this.#selectionStart = this.editor.codemirror.state.selection.main.from;
this.#selectionEnd = this.editor.codemirror.state.selection.main.to;
2023-04-28 02:51:04 +02:00
this.editor.codemirror.dispatch({
effects: StateEffect.appendConfig.of(
ViewPlugin.define(() => ({
update: (update: ViewUpdate) => {
const document = update.state.doc;
const selection = update.state.selection.main;
2025-05-01 17:44:31 +02:00
this.#characterCount = document.length;
this.#wordCount = countWords(document);
this.#lineCount = document.lines;
2023-04-28 02:51:04 +02:00
2025-05-01 17:44:31 +02:00
const direction =
this.#getSelectionDirection(selection);
2023-04-28 02:51:04 +02:00
const toLine = document.lineAt(selection.to);
const fromLine = document.lineAt(selection.from);
let cursorLine: Line;
if (direction === "left") {
2023-04-28 02:51:04 +02:00
// Cursor is at the start of the selection.
cursorLine = fromLine;
2025-05-01 17:44:31 +02:00
this.#cursorColumn =
2023-04-28 02:51:04 +02:00
selection.from - cursorLine.from;
} else {
// Cursor is at the end of the selection, or there is no selection.
cursorLine = toLine;
2025-05-01 17:44:31 +02:00
this.#cursorColumn = selection.to - cursorLine.from;
2023-04-28 02:51:04 +02:00
2025-05-01 17:44:31 +02:00
if (this.#cursorColumn > toLine.length) {
2023-04-28 02:51:04 +02:00
// Column is incorrect, can happen when Ctrl+A is used. We need to manually adjust it.
2025-05-01 17:44:31 +02:00
this.#cursorColumn = toLine.length;
2023-04-28 02:51:04 +02:00
}
}
2025-05-01 17:44:31 +02:00
this.#cursorLine = cursorLine.number;
this.#selectionStart = selection.from;
this.#selectionEnd = selection.to;
2023-04-28 02:51:04 +02:00
// We start counting columns at 1.
2025-05-01 17:44:31 +02:00
this.#cursorColumn++;
2023-04-28 02:51:04 +02:00
this.render();
},
})),
),
});
this.render();
}
2025-05-01 17:44:31 +02:00
render() {
2023-04-28 02:51:04 +02:00
this.element.innerHTML = `
2025-05-01 17:44:31 +02:00
<span class="status-bar-element">Lines: ${this.#lineCount}</span>
<span class="status-bar-element">Words: ${this.#wordCount}</span>
<span class="status-bar-element">Characters: ${this.#characterCount}</span>
<span class="status-bar-element">Pos: ${this.#cursorLine}:${this.#cursorColumn}</span>
2023-04-28 02:51:04 +02:00
`;
}
2025-05-01 17:44:31 +02:00
#getSelectionDirection(
2023-04-28 02:51:04 +02:00
selection: SelectionRange,
): "right" | "left" | undefined {
2025-05-01 17:44:31 +02:00
return selection.from === this.#selectionStart
? "right"
: // eslint-disable-next-line sonarjs/no-nested-conditional
2025-05-01 17:44:31 +02:00
selection.to === this.#selectionEnd
? "left"
: undefined;
2023-04-28 02:51:04 +02:00
}
}