2023-12-19 22:17:12 -05:00
|
|
|
import { detach, getLength } from '../node/Node';
|
2023-01-22 19:35:12 -05:00
|
|
|
import { moveRangeBoundariesDownTree } from '../range/Boundaries';
|
|
|
|
import { deleteContentsOfRange } from '../range/InsertDelete';
|
|
|
|
|
|
|
|
import type { Squire } from '../Editor';
|
|
|
|
import { linkifyText } from './KeyHelpers';
|
2023-09-19 01:44:27 -05:00
|
|
|
import {
|
|
|
|
getStartBlockOfRange,
|
|
|
|
rangeDoesEndAtBlockBoundary,
|
|
|
|
} from '../range/Block';
|
|
|
|
import { SHOW_TEXT, TreeIterator } from '../node/TreeIterator';
|
2023-12-19 22:17:12 -05:00
|
|
|
import { ZWS } from '../Constants';
|
2023-01-22 19:35:12 -05:00
|
|
|
|
|
|
|
// ---
|
|
|
|
|
2023-09-19 01:44:27 -05:00
|
|
|
const Space = (self: Squire, event: KeyboardEvent, range: Range): void => {
|
2023-01-22 19:35:12 -05:00
|
|
|
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);
|
2023-09-19 01:44:27 -05:00
|
|
|
} else if (rangeDoesEndAtBlockBoundary(range, root)) {
|
|
|
|
const block = getStartBlockOfRange(range, root);
|
|
|
|
if (block && block.nodeName !== 'PRE') {
|
2023-09-26 23:56:00 -05:00
|
|
|
const text = block.textContent?.trimEnd().replace(ZWS, '');
|
2023-09-19 01:44:27 -05:00
|
|
|
if (text === '*' || text === '1.') {
|
|
|
|
event.preventDefault();
|
2023-12-19 22:17:12 -05:00
|
|
|
self.insertPlainText(' ', false);
|
|
|
|
self._docWasChanged();
|
|
|
|
self.saveUndoState(range);
|
2023-09-19 01:44:27 -05:00
|
|
|
const walker = new TreeIterator<Text>(block, SHOW_TEXT);
|
|
|
|
let textNode: Text | null;
|
|
|
|
while ((textNode = walker.nextNode())) {
|
2023-12-19 22:17:12 -05:00
|
|
|
detach(textNode);
|
2023-09-19 01:44:27 -05:00
|
|
|
}
|
|
|
|
if (text === '*') {
|
|
|
|
self.makeUnorderedList();
|
|
|
|
} else {
|
|
|
|
self.makeOrderedList();
|
|
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
2023-01-22 19:35:12 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
// 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 };
|