forked from devs/PCv5
editor: Fix bullet list creation if the line is empty
This commit is contained in:
parent
371dee1f7a
commit
b062d9fa64
|
@ -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) {
|
||||
|
|
Loading…
Reference in New Issue