You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
NotePostApp/www/js/markdowneditor.js

143 lines
5.1 KiB
JavaScript

/*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
class MarkdownEditor {
constructor(textarea, toolbar, buttons) {
this.textarea = textarea;
this.toolbar = toolbar;
if (typeof buttons != "undefined") {
for (var i = 0; i < buttons.length; i++) {
var div = document.createElement('div');
if (buttons[i]['spacer']) {
div.className = "toolbar-spacer";
div.innerHTML = "|";
} else {
div.className = "toolbar-button";
if (typeof buttons[i]['linestart'] == "string") {
div.setAttribute("data-linestart", buttons[i]['linestart']);
div.setAttribute("data-padspace", buttons[i]['padspace'] ? 1 : 0);
div.setAttribute("data-maximum", buttons[i]['maximum']);
} else {
div.setAttribute("data-before", buttons[i]['before']);
div.setAttribute("data-after", buttons[i]['after']);
}
div.innerHTML = "<i class=\"" + buttons[i]['icon'] + " fa-fw\"></i>";
}
toolbar.appendChild(div);
}
}
var btns = toolbar.getElementsByClassName("toolbar-button");
var editorobj = this;
for (var i = 0; i < btns.length; i++) {
btns[i].addEventListener('click', function () {
if (editorobj.textarea.value.length == editorobj.getCursorPosition()[0] && editorobj.textarea.value.length == editorobj.getCursorPosition()[1]) {
//return;
}
if (typeof this.dataset.linestart == "string") {
editorobj.formatline(this.dataset.linestart, this.dataset.padspace, this.dataset.maximum);
} else {
editorobj.format(this.dataset.before, this.dataset.after);
}
editorobj.textarea.focus();
}, false);
}
}
formatline(start, padspace, maximum) {
var text = this.getText();
var cursor = this.getCursorPosition();
var startofline = cursor[0];
while (startofline - 1 > 0 && text[startofline - 1] != "\n") {
startofline--;
}
console.log("startofline", startofline, text[startofline - 1]);
// Check if the line is already formatted and count how many times
var falsestart = startofline;
var count = 0;
while (falsestart != text.length && text.slice(falsestart, falsestart + start.length) == start) {
falsestart += start.length;
count++;
}
console.log("falsestart", falsestart);
// Check if we're allowed to add another formatting mark
if (count > 0) {
if (maximum <= count) {
return;
}
}
// If it's the first one and a space is needed after
if (count == 0 && padspace == 1) {
start += " ";
}
text = [text.slice(0, startofline), start, text.slice(startofline)].join('');
this.textarea.value = text;
this.textarea.selectionStart = cursor[0] + start.length;
this.textarea.selectionEnd = cursor[0] + start.length;
}
format(before, after) {
var text = this.getText();
var cursor = this.getCursorPosition();
var origcursor = this.getCursorPosition();
if (cursor[0] == cursor[1]) {
// Walk backwards and forwards to get the whole word
while (cursor[0] - 1 >= 0 && text[cursor[0] - 1] != " " && text[cursor[0] - 1] != "\n") {
cursor[0]--;
}
while (cursor[1] < text.length && text[cursor[1]] != " " && text[cursor[1]] != "\n") {
cursor[1]++;
}
}
var subject = text.substring(cursor[0], cursor[1]);
if (subject.startsWith(before) && subject.endsWith(after)) {
// Don't do anything
return;
}
if (subject == "") {
subject = " ";
origcursor[0]++;
origcursor[1]++;
}
subject = before + subject + after;
text = [text.slice(0, cursor[0]), subject, text.slice(cursor[1])].join('');
this.textarea.value = text;
this.textarea.selectionStart = origcursor[0] + before.length;
this.textarea.selectionEnd = origcursor[1] + before.length;
}
getCursorPosition() {
var start = this.textarea.selectionStart;
var end = this.textarea.selectionEnd;
console.log([start, end], this.textarea.value.length);
return [start, end];
}
/**
* Get the textarea value, with an extra newline if needed.
* @returns string
*/
getText() {
var text = this.textarea.value;
// if (text[text.length - 1] != "\n") {
// text += "\n";
// }
return text;
}
}