Skip to content

Commit

Permalink
Convert Javascript to Typescript
Browse files Browse the repository at this point in the history
  • Loading branch information
thomiceli committed Apr 3, 2023
1 parent 0eb1b10 commit 8b08c5a
Show file tree
Hide file tree
Showing 9 changed files with 324 additions and 302 deletions.
162 changes: 0 additions & 162 deletions public/editor.js

This file was deleted.

171 changes: 171 additions & 0 deletions public/editor.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,171 @@
import {EditorView, gutter, keymap, lineNumbers} from "@codemirror/view";
import {Compartment, EditorState, Facet, Line, SelectionRange} from "@codemirror/state";
import {indentLess} from "@codemirror/commands";

document.addEventListener("DOMContentLoaded", () => {
EditorView.theme({}, {dark: true});

let editorsjs: EditorView[] = [];
let editorsParentdom = document.getElementById("editors")!;
let allEditorsdom = document.querySelectorAll("#editors > .editor");
let firstEditordom = allEditorsdom[0];

const txtFacet = Facet.define<string>({
combine(values) {
return values;
},
});

let indentSize = new Compartment(),
wrapMode = new Compartment(),
indentType = new Compartment();

const newEditor = (dom: HTMLElement, value: string = ""): EditorView => {
let editor = new EditorView({
doc: value,
parent: dom,
extensions: [
lineNumbers(),
gutter({class: "cm-mygutter"}),
keymap.of([{key: "Tab", run: customIndentMore, shift: indentLess}]),
indentSize.of(EditorState.tabSize.of(2)),
wrapMode.of([]),
indentType.of(txtFacet.of("space")),
],
});

dom.querySelector<HTMLInputElement>(".editor-indent-type")!.onchange = (e) => {
let newTabType = (e.target as HTMLInputElement).value;
setIndentType(editor, !["tab", "space"].includes(newTabType) ? "space" : newTabType);
};

dom.querySelector<HTMLInputElement>(".editor-indent-size")!.onchange = (e) => {
let newTabSize = parseInt((e.target as HTMLInputElement).value);
setIndentSize(editor, ![2, 4, 8].includes(newTabSize) ? 2 : newTabSize);
};

dom.querySelector<HTMLInputElement>(".editor-wrap-mode")!.onchange = (e) => {
let newWrapMode = (e.target as HTMLInputElement).value;
setLineWrapping(editor, newWrapMode === "soft");
};

dom.addEventListener("drop", (e) => {
e.preventDefault(); // prevent the browser from opening the dropped file
(e.target as HTMLInputElement)
.closest(".editor")
.querySelector<HTMLInputElement>("input.form-filename")!.value =
e.dataTransfer.files[0].name;
});

// remove editor on delete
let deleteBtns = dom.querySelector<HTMLButtonElement>("button.delete-file");
if (deleteBtns !== null) {
deleteBtns.onclick = () => {
editorsjs.splice(editorsjs.indexOf(editor), 1);
dom.remove();
};
}

editor.dom.addEventListener("input", function inputConfirmLeave() {
if (!editor.inView) return; // skip events outside the viewport

editor.dom.removeEventListener("input", inputConfirmLeave);
window.onbeforeunload = () => {
return "Are you sure you want to quit?";
};
});

return editor;
};

function getIndentation(state: EditorState): string {
// @ts-ignore
if (indentType.get(state).value === "tab") {
return "\t";
}
// @ts-ignore
return " ".repeat(indentSize.get(state).value);
}

function customIndentMore({state, dispatch,}: { state: EditorState; dispatch: (value: any) => void; }): boolean {
let indentation = getIndentation(state);
dispatch({
...state.update(changeBySelectedLine(state, (line, changes) => {
changes.push({from: state.selection.ranges[0].from, insert: indentation,});
})),
selection: {
anchor: state.selection.ranges[0].from + indentation.length,
head: state.selection.ranges[0].from + indentation.length,
},
});
return true;
}

function changeBySelectedLine(state: EditorState, f: (line: Line, changes: any[]) => void): any {
let atLine = -1;
return state.changeByRange((range) => {
let changes: any[] = [];
for (let line = state.doc.lineAt(range.from); ;) {
if (line.number > atLine) {
f(line, changes);
atLine = line.number;
}
if (range.to <= line.to) break;
line = state.doc.lineAt(line.number + 1);
}
let changeSet = state.changes(changes);
return {
changes,
// @ts-ignore
range: new SelectionRange(changeSet.mapPos(range.anchor, 1), changeSet.mapPos(range.head, 1)),
};
});
}

function setIndentType(view: EditorView, type: string): void {
view.dispatch({effects: indentType.reconfigure(txtFacet.of(type))});
}

function setIndentSize(view: EditorView, size: number): void {
view.dispatch({effects: indentSize.reconfigure(EditorState.tabSize.of(size))});
}

function setLineWrapping(view: EditorView, enable: boolean): void {
view.dispatch({
effects: wrapMode.reconfigure(enable ? EditorView.lineWrapping : []),
});
}

let arr = Array.from(allEditorsdom);
arr.forEach((el: HTMLElement) => {
// in case we edit the gist contents
let currEditor = newEditor(el, el.querySelector<HTMLInputElement>(".form-filecontent")!.value);
editorsjs.push(currEditor);
});

document.getElementById("add-file")!.onclick = () => {
let newEditorDom = firstEditordom.cloneNode(true) as HTMLElement;

// reset the filename of the new cloned element
newEditorDom.querySelector<HTMLInputElement>('input[name="name"]')!.value = "";

// removing the previous codemirror editor
let newEditorDomCM = newEditorDom.querySelector(".cm-editor");
newEditorDomCM!.remove();

// creating the new codemirror editor and append it in the editor div
editorsjs.push(newEditor(newEditorDom));
editorsParentdom.append(newEditorDom);
};

document.querySelector<HTMLFormElement>("form#create")!.onsubmit = () => {
let j = 0;
document.querySelectorAll<HTMLInputElement>(".form-filecontent").forEach((e) => {
e.value = encodeURIComponent(editorsjs[j++].state.doc.toString());
});
};

document.onsubmit = () => {
window.onbeforeunload = null;
};
});
Loading

0 comments on commit 8b08c5a

Please sign in to comment.