sorry
This commit is contained in:
parent
b19c87b5d6
commit
c397cda8af
155
src/js/editor.ts
155
src/js/editor.ts
|
|
@ -5,16 +5,19 @@ import { focusInput } from "./focus.js"
|
|||
const INDENT_SIZE = 2
|
||||
|
||||
export function initEditor() {
|
||||
document.addEventListener("input", adjustHeight)
|
||||
document.addEventListener("input", handleAdjustHeight)
|
||||
focusTextareaOnCreation()
|
||||
}
|
||||
|
||||
function adjustHeight(e: Event) {
|
||||
function handleAdjustHeight(e: Event) {
|
||||
const target = e.target as HTMLElement
|
||||
if (target?.matches(".editor")) {
|
||||
target.style.height = "auto"
|
||||
target.style.height = target.scrollHeight + "px"
|
||||
}
|
||||
if (target?.matches(".editor"))
|
||||
adjustHeight(target as HTMLTextAreaElement)
|
||||
}
|
||||
|
||||
function adjustHeight(editor: HTMLTextAreaElement) {
|
||||
editor.style.height = "auto"
|
||||
editor.style.height = editor.scrollHeight + "px"
|
||||
}
|
||||
|
||||
function focusTextareaOnCreation() {
|
||||
|
|
@ -33,23 +36,73 @@ function focusTextareaOnCreation() {
|
|||
}
|
||||
|
||||
function keydownHandler(e: KeyboardEvent) {
|
||||
const target = e.target as HTMLTextAreaElement
|
||||
const editor = e.target as HTMLTextAreaElement
|
||||
|
||||
if (e.key === "Tab") {
|
||||
e.preventDefault()
|
||||
if (e.shiftKey)
|
||||
removeTab(target)
|
||||
removeTab(editor)
|
||||
else
|
||||
insertTab(target)
|
||||
insertTab(editor)
|
||||
} else if (e.ctrlKey && e.key === "c") {
|
||||
focusInput()
|
||||
} else if ((e.ctrlKey && e.key === "s") || (e.ctrlKey && e.key === "Enter")) {
|
||||
e.preventDefault()
|
||||
send({
|
||||
id: target.dataset.path,
|
||||
id: editor.dataset.path,
|
||||
type: "save-file",
|
||||
data: target.value
|
||||
data: editor.value
|
||||
})
|
||||
} else if (e.key === "{") {
|
||||
if (editor.selectionStart !== editor.selectionEnd) {
|
||||
insertAroundSelection(editor, '{', '}')
|
||||
e.preventDefault()
|
||||
} else {
|
||||
setTimeout(() => insertAfterCaret(editor, "}"), 0)
|
||||
}
|
||||
} else if (e.key === "}" && isNextChar(editor, '}')) {
|
||||
moveOneRight(editor)
|
||||
e.preventDefault()
|
||||
|
||||
} else if (e.key === "[") {
|
||||
if (editor.selectionStart !== editor.selectionEnd) {
|
||||
insertAroundSelection(editor, '[', ']')
|
||||
e.preventDefault()
|
||||
} else {
|
||||
setTimeout(() => insertAfterCaret(editor, "]"), 0)
|
||||
}
|
||||
} else if (e.key === "]" && isNextChar(editor, ']')) {
|
||||
moveOneRight(editor)
|
||||
e.preventDefault()
|
||||
|
||||
} else if (e.key === "(") {
|
||||
if (editor.selectionStart !== editor.selectionEnd) {
|
||||
insertAroundSelection(editor, '(', ')')
|
||||
e.preventDefault()
|
||||
} else {
|
||||
setTimeout(() => insertAfterCaret(editor, ")"), 0)
|
||||
}
|
||||
} else if (e.key === ")" && isNextChar(editor, ')')) {
|
||||
moveOneRight(editor)
|
||||
e.preventDefault()
|
||||
} else if (e.key === '"') {
|
||||
if (isNextChar(editor, '"')) {
|
||||
moveOneRight(editor)
|
||||
e.preventDefault()
|
||||
} else if (editor.selectionStart !== editor.selectionEnd) {
|
||||
insertAroundSelection(editor, '"', '"')
|
||||
e.preventDefault()
|
||||
} else {
|
||||
setTimeout(() => insertAfterCaret(editor, '"'), 0)
|
||||
}
|
||||
} else if (e.key === "Enter") {
|
||||
indentNewlineForBraces(e, editor)
|
||||
}
|
||||
}
|
||||
|
||||
function moveOneRight(editor: HTMLTextAreaElement) {
|
||||
const pos = editor.selectionStart
|
||||
editor.selectionStart = editor.selectionEnd = pos + 1
|
||||
}
|
||||
|
||||
function insertTab(editor: HTMLTextAreaElement) {
|
||||
|
|
@ -73,3 +126,83 @@ function removeTab(editor: HTMLTextAreaElement) {
|
|||
editor.selectionEnd = end - INDENT_SIZE
|
||||
}
|
||||
}
|
||||
|
||||
function insertAfterCaret(editor: HTMLTextAreaElement, char: string) {
|
||||
const pos = editor.selectionStart
|
||||
editor.value = editor.value.slice(0, pos) + char + editor.value.slice(pos)
|
||||
editor.selectionStart = editor.selectionEnd = pos
|
||||
}
|
||||
|
||||
function isNextChar(editor: HTMLTextAreaElement, char: string): boolean {
|
||||
return editor.value[editor.selectionStart] === char
|
||||
}
|
||||
|
||||
function indentNewlineForBraces(e: KeyboardEvent, editor: HTMLTextAreaElement) {
|
||||
e.preventDefault()
|
||||
|
||||
if (isBetween(editor, "{", "}") || isBetween(editor, "[", "]")) {
|
||||
setTimeout(() => insertMoreIndentedNewline(editor), 0)
|
||||
} else {
|
||||
setTimeout(() => insertIndentedNewline(editor), 0)
|
||||
}
|
||||
}
|
||||
|
||||
function isBetween(editor: HTMLTextAreaElement, start: string, end: string): boolean {
|
||||
const pos = editor.selectionStart
|
||||
const val = editor.value
|
||||
|
||||
if (pos <= 0 || pos >= val.length) return false
|
||||
return val[pos - 1] === start && val[pos] === end
|
||||
}
|
||||
|
||||
function insertIndentedNewline(editor: HTMLTextAreaElement) {
|
||||
const pos = editor.selectionStart
|
||||
|
||||
const before = editor.value.slice(0, pos)
|
||||
|
||||
const prevLineStart = before.lastIndexOf("\n", pos - 1) + 1
|
||||
const prevLine = before.slice(prevLineStart)
|
||||
|
||||
let leading = 0
|
||||
while (prevLine[leading] === " ") leading++
|
||||
|
||||
const indent = " ".repeat(leading)
|
||||
|
||||
const insert = "\n" + indent
|
||||
editor.value = editor.value.slice(0, pos) + insert + editor.value.slice(pos)
|
||||
|
||||
const newPos = pos + insert.length
|
||||
editor.selectionStart = editor.selectionEnd = newPos
|
||||
|
||||
adjustHeight(editor)
|
||||
}
|
||||
|
||||
function insertAroundSelection(editor: HTMLTextAreaElement, before: string, after: string) {
|
||||
const start = editor.selectionStart
|
||||
const end = editor.selectionEnd
|
||||
|
||||
editor.value = editor.value.slice(0, start) + before + editor.value.slice(start, end) + after + editor.value.slice(end)
|
||||
}
|
||||
|
||||
function insertMoreIndentedNewline(editor: HTMLTextAreaElement) {
|
||||
const pos = editor.selectionStart
|
||||
|
||||
const before = editor.value.slice(0, pos)
|
||||
|
||||
const prevLineStart = before.lastIndexOf("\n", pos - 1) + 1
|
||||
const prevLine = before.slice(prevLineStart)
|
||||
|
||||
let leading = 0
|
||||
while (prevLine[leading] === " ") leading++
|
||||
|
||||
const oldIndent = " ".repeat(leading)
|
||||
const newIndent = " ".repeat(leading + INDENT_SIZE)
|
||||
|
||||
const insert = "\n" + newIndent + "\n" + oldIndent
|
||||
editor.value = editor.value.slice(0, pos) + insert + editor.value.slice(pos)
|
||||
|
||||
const newPos = pos + insert.length
|
||||
editor.selectionStart = editor.selectionEnd = newPos - 1 - oldIndent.length
|
||||
|
||||
adjustHeight(editor)
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user