This commit is contained in:
Aitor Moreno
2025-04-23 07:37:17 +02:00
parent 53dcd94f0d
commit c91ed5b580
2 changed files with 31 additions and 48 deletions

View File

@@ -21,7 +21,7 @@ const DEFAULT_LINE_HEIGHT = "1.2";
export function mergeStyleDeclarations(target, source) {
// This is better but it doesn't work in JSDOM
// for (const styleName of source) {
for (let index = 0; index < source.length; index++) {
for (let index = 0; index < source.length; ++index) {
const styleName = source.item(index);
const styleValue = source.getPropertyValue(styleName);
target.setProperty(styleName, styleValue);
@@ -36,7 +36,7 @@ export function mergeStyleDeclarations(target, source) {
* @returns {CSSStyleDeclaration}
*/
function resetStyleDeclaration(styleDeclaration) {
for (let index = 0; index < styleDeclaration.length; index++) {
for (let index = 0; index < styleDeclaration.length; ++index) {
const styleName = styleDeclaration.item(index);
styleDeclaration.removeProperty(styleName);
}
@@ -121,6 +121,19 @@ export function getComputedStyle(element) {
return inertElement.style;
}
/**
* Returns a property value
*
* @param {CSSStyleDeclaration} styleDeclaration
* @param {string} propertyName
* @returns {string|undefined}
*/
function getPropertyValue(styleDeclaration, propertyName) {
if (Array.from(styleDeclaration).includes(propertyName)) {
return styleDeclaration.getPropertyValue(propertyName)
}
}
/**
* Normalizes style declaration.
*
@@ -140,34 +153,39 @@ export function normalizeStyles(node, styleDefaults = getStyleDefaultsDeclaratio
// If there's a color property, we should convert it to
// a --fills CSS variable property.
const fills = styleDeclaration.getPropertyValue("--fills");
const color = styleDeclaration.getPropertyValue("color");
const fills = getPropertyValue(styleDeclaration, "--fills");
const color = getPropertyValue(styleDeclaration, "color");
if (color && !fills) {
styleDeclaration.removeProperty("color");
styleDeclaration.setProperty("--fills", getFills(color));
} else {
} else if (fills) {
styleDeclaration.setProperty("--fills", fills);
} else {
styleDeclaration.setProperty(
"--fills",
JSON.stringify([["^ ","~:fill-color","#000000","~:fill-opacity",1]]),
);
}
// If there's a font-family property and not a --font-id, then
// we remove the font-family because it will not work.
const fontFamily = styleDeclaration.getPropertyValue("font-family");
const fontId = styleDeclaration.getPropertyValue("--font-id");
const fontFamily = getPropertyValue(styleDeclaration, "font-family");
const fontId = getPropertyValue(styleDeclaration, "--font-id");
if (fontFamily && !fontId) {
styleDeclaration.removeProperty("font-family");
}
const fontSize = styleDeclaration.getPropertyValue("font-size");
const fontSize = getPropertyValue(styleDeclaration, "font-size");
if (!fontSize || fontSize === "0px") {
styleDeclaration.setProperty("font-size", DEFAULT_FONT_SIZE);
}
const lineHeight = styleDeclaration.getPropertyValue("line-height");
const lineHeight = getPropertyValue(styleDeclaration, "line-height");
if (!lineHeight || lineHeight === "" || !lineHeight.endsWith("px")) {
// TODO: Podríamos convertir unidades en decimales.
styleDeclaration.setProperty("line-height", DEFAULT_LINE_HEIGHT);
} else if (lineHeight.endsWith("px")) {
const fontSize = styleDeclaration.getPropertyValue("font-size");
const fontSize = getPropertyValue(styleDeclaration, "font-size");
styleDeclaration.setProperty(
"line-height",
parseFloat(lineHeight) / parseFloat(fontSize),

View File

@@ -46,6 +46,7 @@ import CommandMutations from "../commands/CommandMutations.js";
import { isRoot, setRootStyles } from "../content/dom/Root.js";
import { SelectionDirection } from "./SelectionDirection.js";
import SafeGuard from "./SafeGuard.js";
import { mergeStyleDeclarations } from '../content/dom/Style.js';
/**
* Supported options for the SelectionController.
@@ -56,39 +57,7 @@ import SafeGuard from "./SafeGuard.js";
/**
* SelectionController uses the same concepts used by the Selection API but extending it to support
* our own internal model based on paragraphs (in drafconst textEditorMock = TextEditorMock.createTextEditorMockWithParagraphs([
createParagraph([createInline(new Text("Hello, "))]),
createEmptyParagraph(),
createParagraph([createInline(new Text("World!"))]),
]);
const root = textEditorMock.root;
const selection = document.getSelection();
const selectionController = new SelectionController(
textEditorMock,
selection
);
focus(
selection,
textEditorMock,
root.childNodes.item(2).firstChild.firstChild,
0
);
selectionController.mergeBackwardParagraph();
expect(textEditorMock.root).toBeInstanceOf(HTMLDivElement);
expect(textEditorMock.root.children.length).toBe(2);
expect(textEditorMock.root.dataset.itype).toBe("root");
expect(textEditorMock.root.firstChild).toBeInstanceOf(HTMLDivElement);
expect(textEditorMock.root.firstChild.dataset.itype).toBe("paragraph");
expect(textEditorMock.root.firstChild.firstChild).toBeInstanceOf(
HTMLSpanElement
);
expect(textEditorMock.root.firstChild.firstChild.dataset.itype).toBe(
"inline"
);
expect(textEditorMock.root.textContent).toBe("Hello, World!");
expect(textEditorMock.root.firstChild.textContent).toBe("Hello, ");
expect(textEditorMock.root.lastChild.textContent).toBe("World!");
t.js they were called blocks) and inlines.
* our own internal model based on paragraphs (in draft.js they were called blocks) and inlines.
*/
export class SelectionController extends EventTarget {
/**
@@ -253,11 +222,7 @@ export class SelectionController extends EventTarget {
* @param {HTMLElement} element
*/
#applyStylesToCurrentStyle(element) {
for (let index = 0; index < element.style.length; index++) {
const styleName = element.style.item(index);
const styleValue = element.style.getPropertyValue(styleName);
this.#currentStyle.setProperty(styleName, styleValue);
}
mergeStyleDeclarations(this.#currentStyle, element.style);
}
/**