0
Fork 0
mirror of https://github.com/fastmail/Squire.git synced 2024-12-22 15:23:29 -05:00
Squire/source/keyboard/Space.ts
Neil Jenkins 9f5df9e5c0 Fix format intent lost after pressing Space
On Chrome, if you made an inline formatting change, this would insert a
new <span> with a ZWS inside so we could focus it. Pressing Space would
remove this ZWS resulting in the focus ending up outside and so the
formatting would be lost. We were removing the ZWS so we could check
if we were at a block boundary correctly; instead, I've made it so the
boundary check can handle trailing or leading ZWS (see previous commit).
2023-09-27 14:56:00 +10:00

82 lines
2.6 KiB
TypeScript

import { getLength } from '../node/Node';
import { moveRangeBoundariesDownTree } from '../range/Boundaries';
import { deleteContentsOfRange } from '../range/InsertDelete';
import type { Squire } from '../Editor';
import { linkifyText } from './KeyHelpers';
import {
getStartBlockOfRange,
rangeDoesEndAtBlockBoundary,
} from '../range/Block';
import { SHOW_TEXT, TreeIterator } from '../node/TreeIterator';
import { ZWS, cantFocusEmptyTextNodes } from '../Constants';
// ---
const Space = (self: Squire, event: KeyboardEvent, range: Range): void => {
let node: Node | null;
const root = self._root;
self._recordUndoState(range);
self._getRangeAndRemoveBookmark(range);
// Delete the selection if not collapsed
if (!range.collapsed) {
deleteContentsOfRange(range, root);
self._ensureBottomLine();
self.setSelection(range);
self._updatePath(range, true);
} else if (rangeDoesEndAtBlockBoundary(range, root)) {
const block = getStartBlockOfRange(range, root);
if (block && block.nodeName !== 'PRE') {
const text = block.textContent?.trimEnd().replace(ZWS, '');
if (text === '*' || text === '1.') {
event.preventDefault();
const walker = new TreeIterator<Text>(block, SHOW_TEXT);
let textNode: Text | null;
while ((textNode = walker.nextNode())) {
textNode.data = cantFocusEmptyTextNodes ? ZWS : '';
}
if (text === '*') {
self.makeUnorderedList();
} else {
self.makeOrderedList();
}
return;
}
}
}
// If the cursor is at the end of a link (<a>foo|</a>) then move it
// outside of the link (<a>foo</a>|) so that the space is not part of
// the link text.
node = range.endContainer;
if (range.endOffset === getLength(node)) {
do {
if (node.nodeName === 'A') {
range.setStartAfter(node);
break;
}
} while (
!node.nextSibling &&
(node = node.parentNode) &&
node !== root
);
}
// Linkify text
if (self._config.addLinks) {
const linkRange = range.cloneRange();
moveRangeBoundariesDownTree(linkRange);
const textNode = linkRange.startContainer as Text;
const offset = linkRange.startOffset;
setTimeout(() => {
linkifyText(self, textNode, offset);
}, 0);
}
self.setSelection(range);
};
// ---
export { Space };