aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--editor/editor.ts863
-rw-r--r--editor/example.ts20
-rw-r--r--editor/index.html5
3 files changed, 138 insertions, 750 deletions
diff --git a/editor/editor.ts b/editor/editor.ts
index 962ebb5..620d6b8 100644
--- a/editor/editor.ts
+++ b/editor/editor.ts
@@ -4,16 +4,12 @@
import { WuiVfsNodeInterface } from "../vfs/vfs";
const WUI_EDITOR_CLASS = "wui_editor";
-const WUI_EDITOR_CLASS_LINE = "wui_editor_line";
const WUI_EDITOR_CLASS_LINE_NUMBER = "wui_editor_line_number";
-const WUI_EDITOR_CLASS_LINE_TEXT = "wui_editor_line_text";
+const WUI_EDITOR_CLASS_CONTENT = "wui_editor_content";
export interface WuiEditorOptions {
id: string;
- is_editable: boolean;
-
- // Handler that will be called when user select lines.
- onSelection(begin: number, end: number): void;
+ isEditable: boolean;
// Handler that will be called when user press CTRL+S.
onSave(content: string): void;
@@ -21,21 +17,17 @@ export interface WuiEditorOptions {
export class WuiEditor {
id: string;
- is_editable: boolean;
- lines: WuiEditorLine[] = [];
- sel!: Selection;
- selLineStart: number = 0;
+ isEditable: boolean;
+ content: string = "";
+ totalLine: number = 0;
private el!: HTMLElement;
- private range_begin: number = -1;
- private range_end: number = -1;
- private raw_lines: string[] = [];
- private range!: Range;
- private is_key_control: boolean = false;
- private unre: WuiEditorUndoRedo = new WuiEditorUndoRedo();
+ private elLineNumber: HTMLElement = document.createElement("div");
+ private elContent: HTMLElement = document.createElement("div");
+ private isKeyControl: boolean = false;
constructor(public opts: WuiEditorOptions) {
this.id = opts.id;
- this.is_editable = opts.is_editable;
+ this.isEditable = opts.isEditable;
const el = document.getElementById(opts.id);
if (!el) {
@@ -45,791 +37,174 @@ export class WuiEditor {
this.el = el;
this.initStyle();
+ this.initLineNumber();
+ this.initContent();
this.el.classList.add(WUI_EDITOR_CLASS);
-
- const sel = window.getSelection();
- if (!sel) {
- console.error("WuiEditor: cannot get window selection", opts.id);
- return;
- }
- this.sel = sel;
- this.range = document.createRange();
-
- document.onkeydown = (ev: KeyboardEvent) => {
- this.onKeydownDocument(this, ev);
- };
- document.onkeyup = (ev: KeyboardEvent) => {
- this.onKeyupDocument(this, ev);
- };
-
- // Handle system COPY event.
- // For each selection range, add line-feed to the end of it, unless the
- // line is empty, so when we paste it back we can iterate the lines and
- // insert it as new line.
- this.el.addEventListener("copy", (ev: ClipboardEvent) => {
- ev.preventDefault();
- let text = "";
- let line = "";
- for (let i = 0; i < this.sel.rangeCount; i++) {
- line = this.sel.getRangeAt(i)?.toString();
- if (!line) {
- continue;
- }
- text += line;
-
- if (line != "\n") {
- text += "\n";
- }
- }
- ev.clipboardData?.setData("text/plain", text);
- });
}
// getContent return content of file.
getContent(): string {
- let content = "";
- for (let x = 0; x < this.lines.length; x++) {
- if (x > 0) {
- content += "\n";
- }
- content += this.lines[x]!.elText.innerText;
- }
- return content;
- }
-
- getSelectionRange(): RangeInterface {
- return {
- begin_at: this.range_begin,
- end_at: this.range_end,
- } as RangeInterface;
- }
-
- // onKeyDelete handle key "DELETE" event on line.
- //
- // Case 1: DELETE on selection.
- // We "cut" the selected text and push it to undo-redo registry.
- //
- // Case 2: DELETE on the end of line.
- // If the next line exist, join them with current line.
- //
- // Case 3: DELETE on beginning or middle of text.
- onKeyDelete(x: number, ev: KeyboardEvent) {
- ev.preventDefault();
-
- const elTextCurrent = this.lines[x]!.elText;
- const textCurr = elTextCurrent.innerText;
-
- const selString = this.sel.toString();
- if (selString.length > 0) {
- // Case 1: DELETE on selection.
- let textAfter = textCurr.slice(0, this.sel.anchorOffset);
- textAfter += textCurr.slice(this.sel.focusOffset, textCurr.length);
- this.unre.doUpdate(x, textCurr, textAfter);
- this.sel.deleteFromDocument();
- return;
- }
-
- let textAfter = "";
- const off = this.sel.focusOffset;
-
- if (off === textCurr.length) {
- // Case 2: DELETE on the end of line.
- if (x + 1 >= this.lines.length) {
- // Current line is the last line, nothing to do.
- return;
- }
+ let content: string = "";
+ let el: HTMLElement;
+ let line: string;
- const elTextAfter = this.lines[x + 1]!.elText;
- textAfter = elTextAfter.innerText;
- elTextAfter.innerText = "";
-
- this.unre.doJoin(x, textCurr, textAfter);
- this.deleteLine(x + 1);
-
- textAfter = textCurr + textAfter;
- this.lines[x]!.elText.innerText = textAfter;
- this.setCaret(elTextCurrent, off);
- return;
- }
-
- // Case 3: DELETE on beginning or middle of text.
- textAfter = textCurr.slice(0, off);
- textAfter += textCurr.slice(off + 1, textCurr.length);
-
- this.unre.doUpdate(x, textCurr, textAfter);
-
- this.lines[x]!.elText.innerText = textAfter;
- this.setCaret(elTextCurrent, off);
- }
-
- onKeyupOnLine(x: number, ev: KeyboardEvent) {
- let elTextCurr: HTMLElement;
- let elTextPrev: HTMLElement;
- let textBefore: string;
- let textAfter: string;
- let off: number;
-
- switch (ev.key) {
- case "Alt":
- case "ArrowDown":
- case "ArrowLeft":
- case "ArrowRight":
- case "ArrowUp":
- case "CapsLock":
- case "ContextMenu":
- case "End":
- case "Home":
- case "Insert":
- case "OS":
- case "PageDown":
- case "PageUp":
- case "Pause":
- case "PrintScreen":
- case "ScrollLock":
- case "Shift":
- break;
-
- case "Backspace":
- ev.preventDefault();
-
- textBefore = this.raw_lines[x]!;
- elTextCurr = this.lines[x]!.elText;
- textAfter = elTextCurr.innerText;
-
- off = this.sel.focusOffset;
- if (off > 0) {
- this.unre.doUpdate(x, textBefore, textAfter);
-
- this.raw_lines[x] = textAfter;
- this.setCaret(elTextCurr, off);
- return false;
- }
-
- // Join current line with previous.
- elTextPrev = this.lines[x - 1]!.elText;
-
- this.unre.doJoin(x - 1, elTextPrev.innerText, elTextCurr.innerText);
-
- off = elTextPrev.innerText.length;
- elTextPrev.innerText = elTextPrev.innerText + elTextCurr.innerText;
- this.raw_lines[x - 1] = elTextPrev.innerText;
-
- // Remove the current line
- this.deleteLine(x);
- this.setCaret(elTextPrev, off);
- return false;
-
- case "Enter":
- ev.preventDefault();
- break;
-
- default:
- if (this.is_key_control) {
+ this.elContent.childNodes.forEach((node: Node) => {
+ switch (node.nodeType) {
+ case Node.ELEMENT_NODE:
+ el = node as HTMLElement;
+ line = el.innerText;
break;
- }
- this.unre.doUpdate(
- x,
- this.raw_lines[x]!,
- this.lines[x]!.elText.innerText,
- );
- this.raw_lines[x] = this.lines[x]!.elText.innerText;
- }
- return true;
- }
-
- onKeydownOnLine(x: number, ev: KeyboardEvent) {
- let textBefore: string;
- let textAfter: string;
- let off: number;
- let elText: HTMLElement | undefined;
- let text: string;
-
- switch (ev.key) {
- case "ArrowUp":
- if (x == 0) {
- return false;
- }
- ev.preventDefault();
-
- elText = this.lines[x - 1]!.elText;
- off = this.sel.focusOffset;
- if (off > elText.innerText.length) {
- off = elText.innerText.length;
- }
- this.setCaret(elText, off);
-
- if (x == 1) {
- this.el.scrollTop = 0;
- } else if (x * 23 < this.el.scrollTop) {
- this.el.scrollTop -= 25;
- }
- return false;
-
- case "ArrowDown":
- if (x == this.lines.length - 1) {
- return false;
- }
- ev.preventDefault();
-
- elText = this.lines[x + 1]!.elText;
- off = this.sel.focusOffset;
- if (off > elText.innerText.length) {
- off = elText.innerText.length;
- }
- this.setCaret(elText, off);
-
- x += 2;
- if (x * 25 >= this.el.clientHeight + this.el.scrollTop) {
- this.el.scrollTop += 25;
- }
- return false;
-
- case "Delete":
- this.onKeyDelete(x, ev);
- break;
-
- case "Enter":
- ev.preventDefault();
-
- elText = this.lines[x]!.elText;
- off = this.sel.focusOffset;
- text = elText.innerText;
- textBefore = text.slice(0, off);
- textAfter = text.slice(off, text.length);
-
- this.unre.doSplit(x, textBefore, textAfter);
-
- elText.innerText = textBefore;
- this.raw_lines[x] = textBefore;
-
- this.insertNewline(x + 1, textAfter);
- if (x + 3 >= this.raw_lines.length) {
- this.el.scrollTop = this.el.scrollHeight;
- }
- break;
-
- case "Tab":
- ev.preventDefault();
-
- elText = this.lines[x]?.elText;
- if (!elText) {
+ case Node.TEXT_NODE:
+ line = node.nodeValue || "";
break;
- }
+ }
- off = this.sel.focusOffset;
- textBefore = elText.innerText;
- textAfter =
- textBefore.slice(0, off) +
- "\t" +
- textBefore.slice(off, textBefore.length);
+ if (line == "\n") {
+ content += line;
+ } else {
+ content += line + "\n";
+ }
+ });
- this.unre.doUpdate(x, textBefore, textAfter);
- elText.innerText = textAfter;
- this.raw_lines[x] = textAfter;
+ content = content.trim();
- this.setCaret(elText, off + 1);
- break;
- }
- return true;
+ return content;
}
- onMouseDownAtLine(x: number) {
- this.range_begin = x;
- }
+ // open the node for editing.
+ // The content MUST be encoded in base64.
+ open(node: WuiVfsNodeInterface): void {
+ this.content = atob(node.content);
+ this.content = this.content.replace("\r\n", "\n");
- onMouseUpAtLine(x: number) {
- this.range_end = x;
- if (this.range_end < this.range_begin) {
- return;
- }
- let y = 0;
- for (; y < this.range_begin; y++) {
- this.el.children[y]?.setAttribute("style", "");
- }
- for (; y <= this.range_end; y++) {
- this.el.children[y]?.setAttribute(
- "style",
- "background-color:lightsalmon",
- );
- }
- for (; y < this.el.children.length; y++) {
- this.el.children[y]?.setAttribute("style", "");
- }
- if (this.opts.onSelection) {
- this.opts.onSelection(this.range_begin, this.range_end);
- }
+ this.render(this.content);
}
- // setEditOff make the content not editable.
- setEditOff() {
- this.lines.forEach((line) => {
- line.setEditOff();
- });
+ private addNewLine() {
+ this.totalLine++;
+ const elLine = document.createElement("div");
+ elLine.innerText = `${this.totalLine}`;
+ this.elLineNumber.appendChild(elLine);
}
- // setEditOn make the content to be editable.
- setEditOn() {
- this.lines.forEach((line) => {
- line.setEditOn();
- });
+ private initLineNumber() {
+ this.elLineNumber.classList.add(WUI_EDITOR_CLASS_LINE_NUMBER);
+ this.el.appendChild(this.elLineNumber);
}
- // open the node for editing.
- // The content MUST be encoded in base64.
- open(node: WuiVfsNodeInterface): void {
- let content = atob(node.content);
- content = content.replace("\r\n", "\n");
- this.raw_lines = content.split("\n");
+ private initContent() {
+ if (this.opts.isEditable) {
+ this.elContent.setAttribute("contenteditable", "true");
+ this.elContent.setAttribute("spellcheck", "false");
- this.lines = [];
- this.raw_lines.forEach((rawLine, x) => {
- const line = new WuiEditorLine(x, rawLine, this);
- this.lines.push(line);
- });
-
- this.render();
- }
+ this.elContent.addEventListener("paste", () => {
+ setTimeout(() => {
+ this.render(this.getContent());
+ }, 100);
+ });
- // clearSelection clear selection range indicator.
- clearSelection() {
- if (this.range_begin < 0 || this.range_end == 0) {
- return;
- }
- for (let x = this.range_begin; x <= this.range_end; x++) {
- this.el.children[x]?.setAttribute("style", "");
+ this.elContent.onkeydown = (ev: KeyboardEvent) => {
+ this.onKeydownDocument(this, ev);
+ };
+ this.elContent.onkeyup = (ev: KeyboardEvent) => {
+ this.onKeyupDocument(this, ev);
+ };
}
- this.range_begin = -1;
- this.range_end = -1;
+ this.elContent.classList.add(WUI_EDITOR_CLASS_CONTENT);
+ this.el.appendChild(this.elContent);
}
private initStyle() {
const style = document.createElement("style");
style.type = "text/css";
style.innerText = `
- [contenteditable] {
- outline: 0px solid transparent;
- }
- .${WUI_EDITOR_CLASS} {
- background-color: cornsilk;
- font-family: monospace;
- overflow-y: auto;
- width: 100%;
- }
- .${WUI_EDITOR_CLASS_LINE} {
- display: block;
- width: 100%;
- }
- .${WUI_EDITOR_CLASS_LINE_NUMBER} {
- color: dimgrey;
- cursor: pointer;
- display: inline-block;
- padding: 4px 10px 4px 4px;
- text-align: right;
- user-select: none;
- vertical-align: top;
- width: 30px;
- }
- .${WUI_EDITOR_CLASS_LINE_NUMBER}:hover {
- background-color: lightsalmon;
- }
- .${WUI_EDITOR_CLASS_LINE_TEXT} {
- display: inline-block;
- padding: 4px;
- border-color: lightblue;
- border-width: 0px;
- border-style: solid;
- white-space: pre-wrap;
- width: calc(100% - 60px);
- }
- `;
+ [contenteditable] {
+ outline: 0px solid transparent;
+ }
+ .${WUI_EDITOR_CLASS} {
+ background-color: cornsilk;
+ border: 1px solid brown;
+ font-family: monospace;
+ line-height: 1.6em;
+ overflow-y: scroll;
+ width: 100%;
+ }
+ .${WUI_EDITOR_CLASS_LINE_NUMBER} {
+ background-color: bisque;
+ border-right: 1px dashed brown;
+ color: dimgrey;
+ font-family: monospace;
+ float: left;
+ left: 0px;
+ margin-right: 8px;
+ padding: 0px 8px;
+ position: sticky;
+ text-align: right;
+ width: 3em;
+ }
+ .${WUI_EDITOR_CLASS_CONTENT} {
+ // Do not use "float: left" to fix line break.
+ display: inline-block;
+ padding: 0px 8px;
+ white-space: pre;
+ width: calc(100% - 6em);
+ word-wrap: normal;
+ }
+ `;
document.head.appendChild(style);
}
- private doJoin(changes: ChangesInterface) {
- const line = this.lines[changes.currLine];
- if (!line) {
- return;
- }
- line.elText.innerText = changes.currText;
- this.deleteLine(changes.nextLine);
- this.setCaret(line.elText, 0);
- }
-
- private doSplit(changes: ChangesInterface) {
- const line = this.lines[changes.currLine];
- if (!line) {
- return;
- }
- line.elText.innerText = changes.currText;
- this.insertNewline(changes.nextLine, changes.nextText);
- }
-
- private doUpdate(changes: ChangesInterface) {
- const line = this.lines[changes.currLine];
- if (!line) {
- return;
- }
- line.elText.innerText = changes.currText;
- this.setCaret(line.elText, 0);
- }
-
- private doRedo() {
- const act = this.unre.redo();
- if (!act) {
- return;
- }
- switch (act.kind) {
- case "join":
- this.doJoin(act.after);
- break;
- case "split":
- this.doSplit(act.after);
- break;
- case "update":
- this.doUpdate(act.after);
- break;
- }
- }
-
- private doUndo() {
- const act = this.unre.undo();
- if (!act) {
- return;
- }
- switch (act.kind) {
- case "join":
- this.doSplit(act.before);
- break;
- case "split":
- this.doJoin(act.before);
- break;
- case "update":
- this.doUpdate(act.before);
- break;
- }
- }
-
- private deleteLine(x: number) {
- this.lines.splice(x, 1);
- this.raw_lines.splice(x, 1);
-
- // Reset the line numbers.
- for (; x < this.lines.length; x++) {
- this.lines[x]?.setNumber(x);
- }
- this.render();
- }
-
- insertNewline(x: number, text: string) {
- const newline = new WuiEditorLine(x, text, this);
- for (let y = x; y < this.lines.length; y++) {
- this.lines[y]?.setNumber(y + 1);
- }
-
- this.lines.splice(x, 0, newline);
- this.raw_lines.splice(x, 0, text);
-
- this.render();
- this.setCaret(newline.elText, 0);
- }
-
private onKeydownDocument(ed: WuiEditor, ev: KeyboardEvent) {
switch (ev.key) {
case "Control":
- ed.is_key_control = true;
- return;
+ ed.isKeyControl = true;
+ break;
- case "r":
- if (ed.is_key_control) {
- ev.preventDefault();
- ed.doRedo();
- }
- return;
+ case "Enter":
+ this.addNewLine();
+ break;
case "s":
- if (ed.is_key_control) {
+ if (ed.isKeyControl) {
ev.preventDefault();
ev.stopPropagation();
if (ed.opts.onSave) {
ed.opts.onSave(ed.getContent());
}
}
- return;
-
- case "z":
- if (ed.is_key_control) {
- ev.preventDefault();
- ed.doUndo();
- }
- return;
+ break;
}
+ return true;
}
private onKeyupDocument(ed: WuiEditor, ev: KeyboardEvent) {
switch (ev.key) {
case "Control":
- ed.is_key_control = false;
- return;
-
- case "Escape":
- ev.preventDefault();
- ed.clearSelection();
- return;
- }
- }
-
- private render() {
- this.el.innerHTML = "";
- for (const line of this.lines) {
- this.el.appendChild(line.el);
+ ed.isKeyControl = false;
+ return true;
}
+ return true;
}
- private setCaret(elText: HTMLElement, off: number) {
- if (elText.firstChild) {
- this.range.setStart(elText.firstChild, off);
- } else {
- this.range.setStart(elText, off);
- }
- this.range.collapse(true);
- this.sel.removeAllRanges();
- this.sel.addRange(this.range);
- }
-}
-
-class WuiEditorLine {
- private lineNum: number = 0;
- el!: HTMLElement;
- el_number!: HTMLElement;
- elText!: HTMLElement;
-
- constructor(
- public x: number,
- public text: string,
- ed: WuiEditor,
- ) {
- this.lineNum = x;
- if (text == "") {
- // Add line feed to make all lines layout consistent.
- text = "\n";
- }
- this.el = document.createElement("div");
- this.el.classList.add(WUI_EDITOR_CLASS_LINE);
-
- this.el_number = document.createElement("span");
- this.el_number.classList.add(WUI_EDITOR_CLASS_LINE_NUMBER);
- this.el_number.innerText = this.lineNum + 1 + "";
-
- this.el_number.onmousedown = () => {
- ed.onMouseDownAtLine(this.lineNum);
- };
- this.el_number.onmouseup = () => {
- ed.onMouseUpAtLine(this.lineNum);
- };
-
- this.elText = document.createElement("span");
- this.elText.classList.add(WUI_EDITOR_CLASS_LINE_TEXT);
- this.elText.innerText = text;
- this.elText.contentEditable = "true";
-
- this.elText.onkeydown = (ev: KeyboardEvent) => {
- return ed.onKeydownOnLine(this.lineNum, ev);
- };
- this.elText.onkeyup = (ev: KeyboardEvent) => {
- return ed.onKeyupOnLine(this.lineNum, ev);
- };
+ private render(content: string) {
+ const lines = content.split("\n");
- // onmousedown get and store the current selection and current line
- // number so we can do multiple selection later when mouse move up or
- // down.
- this.elText.onmousedown = () => {
- ed.sel.removeAllRanges();
+ this.elContent.innerText = "";
+ this.elLineNumber.innerText = "";
+ lines.forEach((line: string, x: number) => {
+ const el = document.createElement("div");
+ el.innerText = `${x + 1}`;
+ this.elLineNumber.appendChild(el);
- const sel = window.getSelection();
- if (!sel) {
- return;
+ const div = document.createElement("div");
+ div.innerText = line;
+ if (line == "") {
+ div.appendChild(document.createElement("br"));
}
-
- ed.sel = sel;
- ed.selLineStart = this.x;
- };
-
- this.elText.onmouseup = () => {
- ed.selLineStart = 0;
- };
-
- // onmousemove if the current line not same when the mousedown started,
- // add it to selection range.
- this.elText.onmousemove = () => {
- if (!ed.selLineStart) {
- return;
- }
- if (ed.selLineStart == this.x) {
- return;
- }
-
- const range = document.createRange();
- range.selectNode(this.elText);
- ed.sel.addRange(range);
- };
-
- // paste event we split the clipboard text into lines and it to editor
- // line by line.
- this.elText.addEventListener("paste", (ev: ClipboardEvent) => {
- if (!ev.clipboardData) {
- return;
- }
-
- ev.preventDefault();
-
- const text = ev.clipboardData.getData("text/plain");
- const lines = text.split("\n");
- lines.forEach((l: string, x: number) => {
- ed.insertNewline(this.x + x, l);
- });
+ this.elContent.appendChild(div);
});
- this.el.appendChild(this.el_number);
- this.el.appendChild(this.elText);
- }
-
- setNumber(x: number) {
- this.lineNum = x;
- this.el_number.innerText = x + 1 + "";
- }
-
- setEditOn() {
- this.elText.contentEditable = "true";
- }
-
- setEditOff() {
- this.elText.contentEditable = "false";
- }
-}
-
-//
-// WuiEditorUndoRedo store the state of actions.
-//
-class WuiEditorUndoRedo {
- private idx: number = 0;
- private actions: ActionInterface[] = [];
-
- doJoin(prevLine: number, prevText: string, currText: string) {
- const action: ActionInterface = {
- kind: "join",
- before: {
- currLine: prevLine,
- currText: prevText,
- nextLine: prevLine + 1,
- nextText: currText,
- },
- after: {
- currLine: prevLine,
- currText: prevText + currText,
- nextLine: prevLine + 1,
- nextText: "",
- },
- };
- if (this.actions.length > 0) {
- this.actions = this.actions.slice(0, this.idx);
- }
- this.actions.push(action);
- this.idx++;
- }
-
- doSplit(currLine: number, currText: string, nextText: string) {
- const action = {
- kind: "split",
- before: {
- currLine: currLine,
- currText: currText + nextText,
- nextLine: currLine + 1,
- nextText: "",
- },
- after: {
- currLine: currLine,
- currText: currText,
- nextLine: currLine + 1,
- nextText: nextText,
- },
- };
- if (this.actions.length > 0) {
- this.actions = this.actions.slice(0, this.idx);
- }
- this.actions.push(action);
- this.idx++;
+ this.totalLine = lines.length;
}
-
- doUpdate(lineNum: number, textBefore: string, textAfter: string) {
- const action: ActionInterface = {
- kind: "update",
- before: {
- currLine: lineNum,
- currText: textBefore,
- nextLine: 0,
- nextText: "",
- },
- after: {
- currLine: lineNum,
- currText: textAfter,
- nextLine: 0,
- nextText: "",
- },
- };
-
- if (this.actions.length > 0) {
- this.actions = this.actions.slice(0, this.idx);
- }
- this.actions.push(action);
- this.idx++;
- }
-
- undo(): ActionInterface | null {
- if (this.idx == 0) {
- return null;
- }
- this.idx--;
- const action = this.actions[this.idx];
- if (!action) {
- return null;
- }
- return action;
- }
-
- redo(): ActionInterface | null {
- if (this.idx == this.actions.length) {
- return null;
- }
- const action = this.actions[this.idx];
- if (!action) {
- return null;
- }
- this.idx++;
- return action;
- }
-}
-
-// There are three kind of action
-//
-// * update: update a single line
-// * split: split line using enter
-// * join: join line using backspace.
-//
-interface ActionInterface {
- kind: string;
- before: ChangesInterface;
- after: ChangesInterface;
-}
-
-interface ChangesInterface {
- currLine: number;
- currText: string;
- nextLine: number;
- nextText: string;
-}
-
-interface RangeInterface {
- begin_at: number;
- end_at: number;
}
diff --git a/editor/example.ts b/editor/example.ts
index a967045..39efb4c 100644
--- a/editor/example.ts
+++ b/editor/example.ts
@@ -48,13 +48,23 @@ sudo systemctl status telegraf
const opts = {
id: "editor",
- is_editable: true,
- onSelection: (begin: number, end: number) => {
- console.log("OnSelection: ", begin, end);
- },
+ isEditable: true,
onSave: (content: string) => {
- console.log("OnSave: ", content);
+ const lines = content.split("\n");
+ lines.forEach((line: string, x: number) => {
+ console.log(`${x}: ${line}`);
+ });
},
};
const wuiEditor = new WuiEditor(opts);
wuiEditor.open(nodeFile);
+
+const optsro = {
+ id: "editor-readonly",
+ isEditable: false,
+ onSave: (content: string) => {
+ console.log("OnSave: ", content);
+ },
+};
+const edro = new WuiEditor(optsro);
+edro.open(nodeFile);
diff --git a/editor/index.html b/editor/index.html
index 04a64f5..9c008c7 100644
--- a/editor/index.html
+++ b/editor/index.html
@@ -9,7 +9,10 @@
</head>
<body>
- <div id="editor"></div>
+ <p> Writable editor: </p>
+ <div id="editor" style="height:20em;"></div>
+ <p> Read only editor: </p>
+ <div id="editor-readonly" style="height:20em;"></div>
<script type="module" src="/editor/example.js"></script>
</body>