editor: Fix bullet list creation if the line is empty

This commit is contained in:
Eragon 2022-11-17 22:00:44 +01:00
parent 371dee1f7a
commit b062d9fa64
Signed by untrusted user: Eragon
GPG Key ID: 087126EBFC725006
1 changed files with 111 additions and 111 deletions

View File

@ -5,153 +5,153 @@
Returns [the div.editor, the button, the textarea] */
function editor_event_source(event)
{
let button = undefined;
let editor = undefined;
let button = undefined;
let editor = undefined;
/* Grab the button and the parent editor block. The onclick event itself
usually reports the SVG in the button as the source */
let node = event.target || event.srcElement;
while(node != document.body) {
if(node.tagName == "BUTTON" && !button) {
button = node;
}
if(node.classList.contains("editor") && !editor) {
editor = node;
break;
}
node = node.parentNode;
}
if(!button || !editor) return;
/* Grab the button and the parent editor block. The onclick event itself
usually reports the SVG in the button as the source */
let node = event.target || event.srcElement;
while(node != document.body) {
if(node.tagName == "BUTTON" && !button) {
button = node;
}
if(node.classList.contains("editor") && !editor) {
editor = node;
break;
}
node = node.parentNode;
}
if(!button || !editor) return;
const ta = editor.querySelector("textarea");
return [editor, button, ta];
const ta = editor.querySelector("textarea");
return [editor, button, ta];
}
/* Replace the range [start:end) with the new contents, and returns the new
interval [start:end) (ie. the range where the contents are now located). */
function editor_replace_range(textarea, start, end, contents)
{
ta.value = ta.value.substring(0, start)
+ contents
+ ta.value.substring(end);
ta.value = ta.value.substring(0, start)
+ contents
+ ta.value.substring(end);
return [start, start + contents.length];
return [start, start + contents.length];
}
/* Event handler that inserts the button's data-before and data-after
attributes around the selection. */
function editor_insert_around(event)
{
const [editor, button, ta] = editor_event_source(event);
ta.focus();
let indexStart = ta.selectionStart;
let indexEnd = ta.selectionEnd;
const [editor, button, ta] = editor_event_source(event);
ta.focus();
let indexStart = ta.selectionStart;
let indexEnd = ta.selectionEnd;
const before = button.dataset.before || "";
const after = button.dataset.after || "";
const before = button.dataset.before || "";
const after = button.dataset.after || "";
let [start, end] = editor_replace_range(ta, indexStart, indexEnd,
before + ta.value.substring(indexStart, indexEnd) + after);
let [start, end] = editor_replace_range(ta, indexStart, indexEnd,
before + ta.value.substring(indexStart, indexEnd) + after);
/* Restore selection */
if(indexStart != indexEnd) {
ta.selectionStart = start;
ta.selectionEnd = end;
}
else {
ta.selectionStart = ta.selectionEnd =start + before.length;
}
/* Restore selection */
if(indexStart != indexEnd) {
ta.selectionStart = start;
ta.selectionEnd = end;
}
else {
ta.selectionStart = ta.selectionEnd =start + before.length;
}
}
/* Event handler that modifies each line within the selection through a
generic function. */
function editor_act_on_lines(event, fn)
{
const [editor, button, ta] = editor_event_source(event);
ta.focus();
let indexStart = ta.selectionStart;
let indexEnd = ta.selectionEnd;
const [editor, button, ta] = editor_event_source(event);
ta.focus();
let indexStart = ta.selectionStart;
let indexEnd = ta.selectionEnd;
let firstLineIndex = ta.value.substring(0, indexStart).lastIndexOf('\n');
if(firstLineIndex < 0)
firstLineIndex = 0;
else
firstLineIndex += 1;
let firstLineIndex = ta.value.substring(0, indexStart).lastIndexOf('\n');
if(firstLineIndex < 0)
firstLineIndex = 0;
else
firstLineIndex += 1;
let lastLineIndex = ta.value.substring(indexEnd).indexOf('\n');
if(lastLineIndex < 0)
lastLineIndex = ta.value.length;
else
lastLineIndex += indexEnd;
let lastLineIndex = ta.value.substring(indexEnd).indexOf('\n');
if(lastLineIndex < 0)
lastLineIndex = ta.value.length;
else
lastLineIndex += indexEnd;
let lines = ta.value.substring(firstLineIndex, lastLineIndex).split('\n');
let lines = ta.value.substring(firstLineIndex, lastLineIndex).split('\n');
for(let i = 0; i < lines.length; i++)
lines[i] = fn(lines[i]);
for(let i = 0; i < lines.length; i++)
lines[i] = fn(lines[i]);
let [start, end] = editor_replace_range(ta, firstLineIndex, lastLineIndex,
lines.join('\n'));
let [start, end] = editor_replace_range(ta, firstLineIndex, lastLineIndex,
lines.join('\n'));
ta.selectionStart = start;
ta.selectionEnd = end;
ta.selectionStart = start;
ta.selectionEnd = end;
}
function editor_set_title(event, level, diff)
{
editor_act_on_lines(event, function(line) {
/* Strip all the initial # (and count them) */
let count = 0;
while(count < line.length && line[count] == '#') count++;
editor_act_on_lines(event, function(line) {
/* Strip all the initial # (and count them) */
let count = 0;
while(count < line.length && line[count] == '#') count++;
let contents_index = count;
if(count < line.length && line[count] == ' ') contents_index++;
let contents = line.slice(contents_index);
let contents_index = count;
if(count < line.length && line[count] == ' ') contents_index++;
let contents = line.slice(contents_index);
if(level > 0 || count == 1 && diff == -1) {
/* Remove the title if the corresponding level is re-requested */
if(count == level || count == 1 && diff == -1)
return contents;
/* Otherwise, add it */
else
return '#'.repeat(level) + ' ' + contents;
}
else if(count > 0) {
/* Apply the difference */
let new_level = Math.max(1, Math.min(6, count + diff));
return '#'.repeat(new_level) + ' ' + contents;
}
return line;
});
if(level > 0 || count == 1 && diff == -1) {
/* Remove the title if the corresponding level is re-requested */
if(count == level || count == 1 && diff == -1)
return contents;
/* Otherwise, add it */
else
return '#'.repeat(level) + ' ' + contents;
}
else if(count > 0) {
/* Apply the difference */
let new_level = Math.max(1, Math.min(6, count + diff));
return '#'.repeat(new_level) + ' ' + contents;
}
return line;
});
}
function editor_quote(event)
{
editor_act_on_lines(event, function(line) {
editor_act_on_lines(event, function(line) {
/* Strip all the initial > (and count them) */
let count = 0;
let count = 0;
while(count < line.length && line[count] == '>') count++;
let contents_index = count;
if(count < line.length && line[count] == ' ') contents_index++;
let contents = line.slice(contents_index);
let contents_index = count;
if(count < line.length && line[count] == ' ') contents_index++;
let contents = line.slice(contents_index);
/* Apply the difference */
/* Apply the difference */
return '>'.repeat(count + 1) + ' ' + contents;
});
});
}
function editor_bullet_list(event)
{
editor_act_on_lines(event, function(line) {
editor_act_on_lines(event, function(line) {
let ident_match = line.match(/^[\t]+/m) ?? [''];
let ident = ident_match[0];
let count = ident.length;
const contents = line.slice(count);
if(count < line.length && line[count] != '-') return '- ' + contents;
if((count < line.length || count == 0) && line[count] != '-') return '- ' + contents;
return ident + "\t" + contents;
});
});
}
previewTimeout = null;
@ -159,28 +159,28 @@ ta = document.querySelector(".editor textarea");
ta.addEventListener('keydown', function(e) {
// Tab insert some spaces
// Ctrl+Enter send the form
let keyCode = e.keyCode || e.which;
if (keyCode == 9) {
let keyCode = e.keyCode || e.which;
if (keyCode == 9) {
// TODO Add one tab to selected text without replacing it
e.preventDefault();
e.preventDefault();
let start = e.target.selectionStart;
let end = e.target.selectionEnd;
// set textarea value to: text before caret + tab + text after caret
e.target.value = e.target.value.substring(0, start) + "\t" + e.target.value.substring(end);
e.target.selectionEnd = start + 1;
}
if (e.ctrlKey && keyCode == 13) {
let t = e.target;
while(! (t instanceof HTMLFormElement)) {
t = t.parentNode;
}
try {
t.submit();
} catch(exception) {
t.submit.click();
}
}
let start = e.target.selectionStart;
let end = e.target.selectionEnd;
// set textarea value to: text before caret + tab + text after caret
e.target.value = e.target.value.substring(0, start) + "\t" + e.target.value.substring(end);
e.target.selectionEnd = start + 1;
}
if (e.ctrlKey && keyCode == 13) {
let t = e.target;
while(! (t instanceof HTMLFormElement)) {
t = t.parentNode;
}
try {
t.submit();
} catch(exception) {
t.submit.click();
}
}
// Set a timeout for refreshing the preview
if (previewTimeout != null) {