type/main.js

247 lines
5.7 KiB
JavaScript
Raw Normal View History

2016-09-29 15:31:59 +00:00
// global vars
var editor; // code mirror instance
var incompleteMark;
var focused = false;
let invalids = [];
// fetch file and setup
2016-09-30 23:48:42 +00:00
let hash = window.location.hash.substring(1);
let hashBits = hash.split("/");
let repo = hashBits.slice(0, 3).join("/");
let filePath = hashBits.slice(3, hashBits.length).join("/");
2016-09-29 15:31:59 +00:00
$.get({
2016-09-30 23:48:42 +00:00
url: `https://raw.githubusercontent.com/${repo}/${filePath}`,
2016-09-29 15:43:31 +00:00
success: (code) => {
2016-09-30 23:48:42 +00:00
let parts = filePath.split(".");
2016-09-29 15:31:59 +00:00
let fileExtension = parts[parts.length - 1];
2016-09-30 23:14:03 +00:00
let lang = getLanguageByExtension(fileExtension);
2016-09-29 15:43:31 +00:00
$.get({
2016-09-30 23:14:03 +00:00
url: `/codemirror/mode/${lang.file}/${lang.file}.js`,
2016-09-29 15:43:31 +00:00
success: (data) => {
eval(data);
2016-09-30 23:14:03 +00:00
setup(code, lang.mime);
2016-09-29 15:43:31 +00:00
}
});
2016-09-29 01:20:57 +00:00
}
2016-09-28 22:33:02 +00:00
});
2016-09-29 15:31:59 +00:00
// setup
2016-09-30 23:14:03 +00:00
function setup(data, mime) {
2016-09-29 16:24:15 +00:00
let el = document.getElementById("editor");
el.value = data;
editor = CodeMirror.fromTextArea(el, {
2016-09-30 23:14:03 +00:00
mode: mime,
2016-09-29 15:31:59 +00:00
readOnly: true,
autofocus: true,
extraKeys: {
Up: () => {},
Down: () => {},
Left: () => {},
Right: () => {}
}
});
2016-09-28 22:33:02 +00:00
2016-09-29 16:24:15 +00:00
editor.setSize("100%", "100%");
2016-09-30 23:48:42 +00:00
localforage.getItem(repo)
.then((val) => {
var startPos; // the initial position of the cursor
if (val && val[filePath] && val[filePath].pos) {
startPos = val[filePath].pos;
} else {
startPos = { line: 0, ch: 0 };
}
2016-09-28 22:33:02 +00:00
2016-09-30 23:48:42 +00:00
saveCursor();
editor.setCursor(startPos);
2016-09-28 22:33:02 +00:00
2016-09-30 23:48:42 +00:00
incompleteMark = editor.doc.markText(editor.getCursor(), getEndPos(), {
className: "incomplete"
});
2016-09-29 15:31:59 +00:00
2016-09-30 23:48:42 +00:00
focused = true;
2016-09-28 22:33:02 +00:00
2016-09-30 23:48:42 +00:00
editor.on("focus", (instance, event) => {
focused = true;
});
editor.on("blur", (instance, event) => {
focused = false;
});
2016-09-28 22:33:02 +00:00
2016-09-30 23:48:42 +00:00
editor.on("mousedown", (instance, event) => {
event.preventDefault();
editor.focus();
});
2016-09-28 22:33:02 +00:00
2016-09-30 23:48:42 +00:00
document.addEventListener("keypress", (event) => {
if (focused) {
event.preventDefault();
2016-09-28 22:33:02 +00:00
2016-09-30 23:48:42 +00:00
let pos = editor.getCursor();
2016-09-29 15:31:59 +00:00
let line = editor.doc.getLine(pos.line);
2016-09-30 23:48:42 +00:00
let char = line.charCodeAt(pos.ch);
if (event.charCode != char) {
let mark = editor.doc.markText(pos, {line: pos.line, ch: pos.ch + 1}, {
className: "invalid"
});
if (!invalids[pos.line]) invalids[pos.line] = [];
invalids[pos.line][pos.ch] = mark;
2016-09-29 15:31:59 +00:00
}
2016-09-30 23:48:42 +00:00
editor.setCursor({ line: pos.line, ch: pos.ch + 1 });
updateIncompleteMark();
2016-09-28 22:33:02 +00:00
}
2016-09-30 23:48:42 +00:00
});
document.addEventListener("keydown", (event) => {
if (focused) {
var result = false;
if (event.keyCode == 8) { // delete
result = true;
let pos = editor.getCursor();
if (pos.ch == 0) { // move up 1 line {
moveToEndOfPreviousLine();
} else { // move back 1 char
let line = editor.doc.getLine(pos.line);
if (line.hasOnlyWhiteSpaceBeforeIndex(pos.ch)) {
moveToEndOfPreviousLine();
} else {
editor.setCursor({ line: pos.line, ch: pos.ch - 1 });
}
}
2016-09-28 22:33:02 +00:00
2016-09-30 23:48:42 +00:00
let newPos = editor.getCursor();
let lineInvalids = invalids[newPos.line];
if (lineInvalids) {
let mark = lineInvalids[newPos.ch];
if (mark) {
mark.clear();
lineInvalids.splice(newPos.ch, 1);
}
}
2016-09-28 22:33:02 +00:00
2016-09-30 23:48:42 +00:00
updateIncompleteMark();
} else if (event.keyCode == 13) { // enter
result = true;
let pos = editor.getCursor();
if (pos.line != editor.doc.size - 1) {
let currentLine = editor.doc.getLine(pos.line);
let trimmed = currentLine.trim();
if (editor.getCursor().ch >= currentLine.indexOf(trimmed) + trimmed.length) {
var newLine = pos.line;
while (true) {
newLine++;
if (newLine >= editor.doc.size) { // go to end of last line
editor.setCursor(getEndPos());
break;
} else { // try go to next line
let newText = editor.doc.getLine(newLine);
let newTrimmed = newText.trim();
if (newTrimmed.length != 0) { // line is not empty (whitespace-only)
let ch = newText.indexOf(newTrimmed);
editor.setCursor({ line: newLine, ch: ch });
break;
}
}
2016-09-30 13:08:07 +00:00
}
2016-09-30 23:48:42 +00:00
updateIncompleteMark();
2016-09-30 13:08:07 +00:00
}
}
2016-09-30 23:48:42 +00:00
}
if (result) {
event.preventDefault();
2016-09-29 15:31:59 +00:00
}
2016-09-28 22:33:02 +00:00
}
2016-09-30 23:48:42 +00:00
});
2016-09-28 22:33:02 +00:00
2016-09-30 23:48:42 +00:00
})
.catch((e) => {
throw e;
});
2016-09-29 15:31:59 +00:00
}
2016-09-28 22:33:02 +00:00
function moveToEndOfPreviousLine() {
let pos = editor.getCursor();
if (pos.line > 0) {
2016-09-30 13:08:07 +00:00
var newLine = pos.line;
while (true) {
newLine--;
let text = editor.doc.getLine(newLine);
let trimmed = text.trim();
if (trimmed.length != 0) {
let ch = text.indexOf(trimmed) + trimmed.length;
editor.setCursor({ line: newLine, ch: ch });
break;
}
}
2016-09-28 22:33:02 +00:00
}
}
function isComplete() {
2016-09-30 13:08:07 +00:00
if (!areAllNextLinesEmpty()) {
if (incompleteMark.lines.length != 0) {
return false;
}
2016-09-28 22:52:48 +00:00
}
2016-09-28 22:33:02 +00:00
for (var i = 0; i < invalids.length; i++) {
let arr = invalids[i];
2016-09-29 15:34:26 +00:00
if (arr) {
for (var j = 0; j < arr.length; j++) {
if (arr[j]) {
return false;
}
2016-09-28 22:33:02 +00:00
}
}
}
return true;
}
2016-09-30 13:08:07 +00:00
function areAllNextLinesEmpty() {
let pos = editor.getCursor();
for (var i = pos.line + 1; i < editor.doc.size; i++) {
let line = editor.doc.getLine(i);
if (line.trim().length != 0) {
return false;
}
}
return true;
}
2016-09-28 22:33:02 +00:00
function getEndPos() {
return { line: editor.doc.size, ch: editor.doc.getLine(editor.doc.size - 1).length };
}
function updateIncompleteMark() {
incompleteMark.clear();
incompleteMark = editor.doc.markText(editor.getCursor(), getEndPos(), {
className: "incomplete"
});
}
2016-09-30 23:48:42 +00:00
function saveCursor() {
localforage.getItem(repo)
.then((val) => {
if (!val) val = {};
val[filePath] = {
pos: editor.getCursor()
};
localforage.setItem(repo, val)
.catch((e) => {
throw e;
});
})
.catch((e) => {
throw e;
});
setTimeout(saveCursor, 15000);
}
String.prototype.hasOnlyWhiteSpaceBeforeIndex = function(index) {
return this.substring(index) == this.trim();
2016-09-28 22:33:02 +00:00
};