blob: 049b06e04e294bda3c63d62e6caae6f384f4d1b4 [file] [log] [blame]
/**
* @module modules/textarea-numbers-sk
* @description <h2><code>textarea-numbers-sk</code></h2>
*
* A code editor element with numbers and the ability to mark lines that contain
* errors.
*/
import 'codemirror/mode/clike/clike'; // Syntax highlighting for c-like languages.
import { define } from 'elements-sk/define';
import CodeMirror from 'codemirror';
import { ElementSk } from '../../../infra-sk/modules/ElementSk';
import { isDarkMode } from '../../../infra-sk/modules/theme-chooser-sk/theme-chooser-sk';
export class TextareaNumbersSk extends ElementSk {
/** The CodeMirror control. */
private codeMirror: CodeMirror.Editor | null = null;
/** All the lines we've marked as having errors. */
private errorLines: CodeMirror.TextMarker[] = [];
/** Returns the CodeMirror theme based on the state of the page's darkmode.
*
* For this to work the associated CSS themes must be loaded. See
* textarea-numbers-sk.scss.
*/
private static themeFromCurrentMode = () => (isDarkMode() ? 'base16-dark' : 'base16-light');
connectedCallback(): void {
super.connectedCallback();
// Creates and attaches the CodeMirror control as this elements only child.
// Note we don't call _render().
this.codeMirror = CodeMirror(this, {
lineNumbers: true,
mode: 'text/x-c++src',
theme: TextareaNumbersSk.themeFromCurrentMode(),
viewportMargin: Infinity,
});
this._upgradeProperty('value');
// Listen for theme changes.
document.addEventListener('theme-chooser-toggle', () => {
this.codeMirror!.setOption(
'theme',
TextareaNumbersSk.themeFromCurrentMode(),
);
});
}
/** Removes all error line annotations. */
clearErrors(): void{
this.errorLines.forEach((textMarker) => {
textMarker.clear();
});
}
/** Indicates there is an error on line n. */
setErrorLine(n: number): void {
// Set the class of that line to 'cm-error'.
this.errorLines.push(
this.codeMirror!.markText(
{ line: n - 1, ch: 0 },
{ line: n - 1, ch: 200 }, // Some large number for the character offset.
{
className: 'cm-error', // See the base16-dark.css file in CodeMirror for the class name.
},
)!,
);
}
/** Move the cursor to the given row and column. */
setCursor(row: number, col: number): void {
this.codeMirror!.focus();
this.codeMirror!.setCursor({ line: row - 1, ch: col - 1 });
}
/** @prop The text content of the edit box. */
get value(): string {
if (!this.codeMirror) {
return '';
}
return this.codeMirror!.getValue();
}
set value(val: string) {
if (this.codeMirror) {
this.codeMirror!.setValue(val);
}
this.clearErrors();
}
}
define('textarea-numbers-sk', TextareaNumbersSk);