new functions
This commit is contained in:
+73
-22
@@ -1,26 +1,77 @@
|
||||
function selection(editor) {
|
||||
return { start: editor.selectionStart, end: editor.selectionEnd };
|
||||
}
|
||||
|
||||
function toggleWrap(editor, before, after = before, placeholder = "tekst") {
|
||||
let { start, end } = selection(editor);
|
||||
const value = editor.value;
|
||||
const selected = value.slice(start, end);
|
||||
|
||||
if (start >= before.length && value.slice(start - before.length, start) === before && value.slice(end, end + after.length) === after) {
|
||||
editor.setRangeText(selected, start - before.length, end + after.length, "select");
|
||||
return;
|
||||
}
|
||||
if (selected.startsWith(before) && selected.endsWith(after) && selected.length >= before.length + after.length) {
|
||||
editor.setRangeText(selected.slice(before.length, -after.length), start, end, "select");
|
||||
return;
|
||||
}
|
||||
|
||||
const text = selected || placeholder;
|
||||
editor.setRangeText(before + text + after, start, end, "select");
|
||||
if (!selected) editor.setSelectionRange(start + before.length, start + before.length + text.length);
|
||||
}
|
||||
|
||||
function togglePrefix(editor, prefixFactory) {
|
||||
const { start, end } = selection(editor);
|
||||
const lineStart = editor.value.lastIndexOf("\n", start - 1) + 1;
|
||||
const selected = editor.value.slice(lineStart, end);
|
||||
const lines = selected.split("\n");
|
||||
const prefixes = lines.map((_, index) => typeof prefixFactory === "function" ? prefixFactory(index) : prefixFactory);
|
||||
const allPrefixed = lines.every((line, index) => line.startsWith(prefixes[index]));
|
||||
const replacement = lines.map((line, index) => allPrefixed ? line.slice(prefixes[index].length) : prefixes[index] + line).join("\n");
|
||||
editor.setRangeText(replacement, lineStart, end, "select");
|
||||
}
|
||||
|
||||
export function applyFormat(editor, format) {
|
||||
const wrap = (before, after = before, placeholder = "tekst") => {
|
||||
const start = editor.selectionStart, end = editor.selectionEnd;
|
||||
const selected = editor.value.slice(start, end) || placeholder;
|
||||
editor.setRangeText(before + selected + after, start, end, "select");
|
||||
};
|
||||
const prefix = (value) => {
|
||||
const start = editor.selectionStart, end = editor.selectionEnd;
|
||||
const lineStart = editor.value.lastIndexOf("\n", start - 1) + 1;
|
||||
const selected = editor.value.slice(lineStart, end);
|
||||
editor.setRangeText(selected.split("\n").map((line, index) => typeof value === "function" ? value(index) + line : value + line).join("\n"), lineStart, end, "select");
|
||||
};
|
||||
if (format === "bold") wrap("**");
|
||||
if (format === "italic") wrap("*");
|
||||
if (format === "strike") wrap("~~");
|
||||
if (format === "heading" || format === "heading2") prefix("## ");
|
||||
if (format === "heading1") prefix("# ");
|
||||
if (format === "heading3") prefix("### ");
|
||||
if (format === "heading4") prefix("#### ");
|
||||
if (format === "bullet") prefix("- ");
|
||||
if (format === "number") prefix((index) => `${index + 1}. `);
|
||||
if (format === "quote") prefix("> ");
|
||||
if (format === "link") wrap("[", "](https://)", "description");
|
||||
if (format === "bold") toggleWrap(editor, "**");
|
||||
if (format === "italic") toggleWrap(editor, "*");
|
||||
if (format === "strike") toggleWrap(editor, "~~");
|
||||
if (format === "heading" || format === "heading2") togglePrefix(editor, "## ");
|
||||
if (format === "heading1") togglePrefix(editor, "# ");
|
||||
if (format === "heading3") togglePrefix(editor, "### ");
|
||||
if (format === "heading4") togglePrefix(editor, "#### ");
|
||||
if (format === "bullet") togglePrefix(editor, "- ");
|
||||
if (format === "number") togglePrefix(editor, index => `${index + 1}. `);
|
||||
if (format === "task") togglePrefix(editor, "- [ ] ");
|
||||
if (format === "quote") togglePrefix(editor, "> ");
|
||||
if (format === "link") toggleWrap(editor, "[", "](https://)", "description");
|
||||
if (format === "inline-code") toggleWrap(editor, "`", "`", "code");
|
||||
if (format === "highlight") toggleWrap(editor, "==", "==", "important");
|
||||
if (format === "subscript") toggleWrap(editor, "~", "~", "2");
|
||||
if (format === "superscript") toggleWrap(editor, "^", "^", "2");
|
||||
if (format === "codeblock") toggleWrap(editor, "```text\n", "\n```", "code");
|
||||
if (format === "table") toggleWrap(editor, "| Column 1 | Column 2 |\n| --- | --- |\n| ", " | value |", "value");
|
||||
if (format === "footnote") toggleWrap(editor, "", "[^1]\n\n[^1]: Footnote text", "Text with footnote");
|
||||
if (format === "definition") toggleWrap(editor, "", "\n: Definition", "Term");
|
||||
if (format === "horizontal-rule") toggleWrap(editor, "\n---\n", "", "");
|
||||
editor.focus();
|
||||
editor.dispatchEvent(new Event("input", { bubbles: true }));
|
||||
}
|
||||
|
||||
export function bindFormatShortcuts(editor) {
|
||||
editor.addEventListener("keydown", event => {
|
||||
const primary = event.ctrlKey || event.metaKey;
|
||||
let format = null;
|
||||
if (primary && !event.shiftKey && event.key.toLowerCase() === "b") format = "bold";
|
||||
else if (primary && !event.shiftKey && event.key.toLowerCase() === "i") format = "italic";
|
||||
else if (primary && event.shiftKey && event.key.toLowerCase() === "x") format = "strike";
|
||||
else if (primary && !event.shiftKey && event.key.toLowerCase() === "k") format = "link";
|
||||
else if (primary && event.shiftKey && event.key === "7") format = "number";
|
||||
else if (primary && event.shiftKey && event.key === "8") format = "bullet";
|
||||
else if (primary && event.shiftKey && event.key === "9") format = "task";
|
||||
else if (event.altKey && /^[1-4]$/.test(event.key)) format = `heading${event.key}`;
|
||||
if (!format) return;
|
||||
event.preventDefault();
|
||||
applyFormat(editor, format);
|
||||
});
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user