diff --git a/src/components/deck-card-editor.vue b/src/components/deck-card-editor.vue index 96f6349..d69a8a2 100644 --- a/src/components/deck-card-editor.vue +++ b/src/components/deck-card-editor.vue @@ -33,7 +33,10 @@ import { getActiveMarksAndBlocks, State, movementKeys, - controlSequenceKeys + controlSequenceKeys, + isRootNode, + isTextNode, + moveCaretToEOL } from '@/editor' @Component({ @@ -76,7 +79,6 @@ export default class DeckCardEditor extends Vue { } private editorAction (action: string) { - console.log('action', action) const content = this.$refs.content as HTMLElement content.focus() @@ -104,7 +106,27 @@ export default class DeckCardEditor extends Vue { // arrow keys, enter, delete, etc const isMove = movementKeys.indexOf(event.key) >= 0 - if (isCtrlSq || isMove) this.syncMenuState() + if (isCtrlSq || isMove) { + return this.syncMenuState() + } else if (!event.ctrlKey && event.key.length === 1) { + // this should capture all normal typable letters and numbers + // TODO: this needs to be done on text pasting as well + + // some browsers create bogus root level text nodes, so whenever + // something is typed in such a root level node, we simply wrap it with + // a paragraph + const sel = window.getSelection()?.focusNode + if (sel && isTextNode(sel) && isRootNode(sel.parentElement as HTMLElement)) { + console.debug(`Typed letter "${event.key} into root node, throwing a
at it!"`) + document.execCommand('formatblock', false, 'P') + + // Firefox behaves nicely and leaves the caret alone after surrounding + // the text node with a
. Unlike Chromium that moves the caret to
+ // the beginning of the new paragraph. To mitigate that, we set the
+ // caret to end-of-line manually.
+ moveCaretToEOL()
+ }
+ }
}
private start () {
diff --git a/src/editor/caret.ts b/src/editor/caret.ts
new file mode 100644
index 0000000..0dcf253
--- /dev/null
+++ b/src/editor/caret.ts
@@ -0,0 +1,19 @@
+function collapseRange (node: Node, toStart = false) {
+ const range = document.createRange()
+ range.selectNode(node)
+ range.collapse(toStart)
+ const sel = window.getSelection()
+ if (sel) {
+ sel.removeAllRanges()
+ sel.addRange(range)
+ }
+}
+
+export function moveCaretToBOL () {
+ const node = window.getSelection()?.focusNode
+ if (node) collapseRange(node, true)
+}
+export function moveCaretToEOL () {
+ const node = window.getSelection()?.focusNode
+ if (node) collapseRange(node, false)
+}
diff --git a/src/editor/index.ts b/src/editor/index.ts
index 8f23a94..09028fe 100644
--- a/src/editor/index.ts
+++ b/src/editor/index.ts
@@ -1,5 +1,18 @@
import { elementNameToMenuState, marks, blocks } from './constants'
+export {
+ isRootNode,
+ isRootChild,
+ isElementNode,
+ isTextNode,
+ isEmptyTextNode
+} from './node'
+
+export {
+ moveCaretToBOL,
+ moveCaretToEOL
+} from './caret'
+
export type State = KV