0
Fork 0
mirror of https://github.com/penpot/penpot.git synced 2025-01-08 07:50:43 -05:00

Merge pull request #5383 from penpot/azazeln28-fix-text-editor-more-issues

🐛 Fix text editor issues
This commit is contained in:
Andrey Antukh 2024-11-29 10:17:43 +01:00 committed by GitHub
commit 5e2b847202
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 30 additions and 13 deletions

View file

@ -150,6 +150,7 @@ export function normalizeStyles(node, styleDefaults) {
} }
return styleDeclaration return styleDeclaration
} }
/** /**
* Sets a single style property value of an element. * Sets a single style property value of an element.
* *
@ -210,6 +211,8 @@ export function getStyleFromDeclaration(style, styleName, styleUnit) {
const styleValueAsNumber = parseFloat(styleValue); const styleValueAsNumber = parseFloat(styleValue);
if (styleName === "font-size") { if (styleName === "font-size") {
return getStyleFontSize(styleValueAsNumber, styleValue); return getStyleFontSize(styleValueAsNumber, styleValue);
} else if (styleName === "line-height") {
return styleValue
} }
if (Number.isNaN(styleValueAsNumber)) { if (Number.isNaN(styleValueAsNumber)) {
return styleValue; return styleValue;

View file

@ -479,6 +479,9 @@ export class SelectionController extends EventTarget {
* Selects all content. * Selects all content.
*/ */
selectAll() { selectAll() {
if (this.#textEditor.isEmpty) {
return this
}
this.#selection.selectAllChildren(this.#textEditor.root); this.#selection.selectAllChildren(this.#textEditor.root);
return this; return this;
} }
@ -1466,8 +1469,8 @@ export class SelectionController extends EventTarget {
let previousNode = null; let previousNode = null;
let nextNode = null; let nextNode = null;
// This is the simplest case, when the startNode and the endNode // This is the simplest case, when the startNode and
// are the same and they're a textNode. // the endNode are the same and they're textNodes.
if (startNode === endNode) { if (startNode === endNode) {
this.#textNodeIterator.currentNode = startNode; this.#textNodeIterator.currentNode = startNode;
previousNode = this.#textNodeIterator.previousNode(); previousNode = this.#textNodeIterator.previousNode();
@ -1510,15 +1513,17 @@ export class SelectionController extends EventTarget {
do { do {
SafeGuard.update(); SafeGuard.update();
const currentNode = this.#textNodeIterator.currentNode; const { currentNode } = this.#textNodeIterator;
// We retrieve the inline and paragraph of the // We retrieve the inline and paragraph of the
// current node. // current node.
const inline = getInline(this.#textNodeIterator.currentNode); const inline = getInline(currentNode);
const paragraph = getParagraph(this.#textNodeIterator.currentNode); const paragraph = getParagraph(currentNode);
affectedInlines.add(inline);
affectedParagraphs.add(paragraph);
let shouldRemoveNodeCompletely = false; let shouldRemoveNodeCompletely = false;
if (this.#textNodeIterator.currentNode === startNode) { if (currentNode === startNode) {
if (startOffset === 0) { if (startOffset === 0) {
// We should remove this node completely. // We should remove this node completely.
shouldRemoveNodeCompletely = true; shouldRemoveNodeCompletely = true;
@ -1526,7 +1531,7 @@ export class SelectionController extends EventTarget {
// We should remove this node partially. // We should remove this node partially.
currentNode.nodeValue = currentNode.nodeValue.slice(0, startOffset); currentNode.nodeValue = currentNode.nodeValue.slice(0, startOffset);
} }
} else if (this.#textNodeIterator.currentNode === endNode) { } else if (currentNode === endNode) {
if (isLineBreak(endNode) if (isLineBreak(endNode)
|| (isTextNode(endNode) || (isTextNode(endNode)
&& endOffset === endNode.nodeValue.length)) { && endOffset === endNode.nodeValue.length)) {
@ -1549,13 +1554,11 @@ export class SelectionController extends EventTarget {
if (currentNode === startNode) { if (currentNode === startNode) {
continue; continue;
} }
if (currentNode === endNode) {
break;
}
if (inline.childNodes.length === 0) { if (inline.childNodes.length === 0) {
inline.remove(); inline.remove();
} }
if (paragraph !== startParagraph && paragraph.children.length === 0) { if (paragraph !== startParagraph && paragraph.children.length === 0) {
paragraph.remove(); paragraph.remove();
} }
@ -1576,13 +1579,16 @@ export class SelectionController extends EventTarget {
} }
} }
if (startInline.childNodes.length === 0 && endInline.childNodes.length > 0) { if (startInline.childNodes.length === 0
&& endInline.childNodes.length > 0) {
startInline.remove(); startInline.remove();
return this.collapse(endNode, 0); return this.collapse(endNode, 0);
} else if (startInline.childNodes.length > 0 && endInline.childNodes.length === 0) { } else if (startInline.childNodes.length > 0
&& endInline.childNodes.length === 0) {
endInline.remove(); endInline.remove();
return this.collapse(startNode, startOffset); return this.collapse(startNode, startOffset);
} else if (startInline.childNodes.length === 0 && endInline.childNodes.length === 0) { } else if (startInline.childNodes.length === 0
&& endInline.childNodes.length === 0) {
const previousInline = startInline.previousElementSibling; const previousInline = startInline.previousElementSibling;
const nextInline = endInline.nextElementSibling; const nextInline = endInline.nextElementSibling;
startInline.remove(); startInline.remove();
@ -1641,6 +1647,14 @@ export class SelectionController extends EventTarget {
midInline.after(endInline); midInline.after(endInline);
} }
// NOTE: This is necessary because sometimes
// inlines are splitted from the beginning
// to a mid offset and then the starting node
// remains empty.
if (inline.firstChild.nodeValue === "") {
inline.remove();
}
// FIXME: This can change focus <-> anchor order. // FIXME: This can change focus <-> anchor order.
this.setSelection(midText, 0, midText, midText.nodeValue.length); this.setSelection(midText, 0, midText, midText.nodeValue.length);