mirror of
https://github.com/penpot/penpot.git
synced 2025-12-11 22:14:05 +01:00
WIP
This commit is contained in:
@@ -21,7 +21,7 @@ const DEFAULT_LINE_HEIGHT = "1.2";
|
|||||||
export function mergeStyleDeclarations(target, source) {
|
export function mergeStyleDeclarations(target, source) {
|
||||||
// This is better but it doesn't work in JSDOM
|
// This is better but it doesn't work in JSDOM
|
||||||
// for (const styleName of source) {
|
// 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 styleName = source.item(index);
|
||||||
const styleValue = source.getPropertyValue(styleName);
|
const styleValue = source.getPropertyValue(styleName);
|
||||||
target.setProperty(styleName, styleValue);
|
target.setProperty(styleName, styleValue);
|
||||||
@@ -36,7 +36,7 @@ export function mergeStyleDeclarations(target, source) {
|
|||||||
* @returns {CSSStyleDeclaration}
|
* @returns {CSSStyleDeclaration}
|
||||||
*/
|
*/
|
||||||
function resetStyleDeclaration(styleDeclaration) {
|
function resetStyleDeclaration(styleDeclaration) {
|
||||||
for (let index = 0; index < styleDeclaration.length; index++) {
|
for (let index = 0; index < styleDeclaration.length; ++index) {
|
||||||
const styleName = styleDeclaration.item(index);
|
const styleName = styleDeclaration.item(index);
|
||||||
styleDeclaration.removeProperty(styleName);
|
styleDeclaration.removeProperty(styleName);
|
||||||
}
|
}
|
||||||
@@ -121,6 +121,19 @@ export function getComputedStyle(element) {
|
|||||||
return inertElement.style;
|
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.
|
* Normalizes style declaration.
|
||||||
*
|
*
|
||||||
@@ -140,34 +153,39 @@ export function normalizeStyles(node, styleDefaults = getStyleDefaultsDeclaratio
|
|||||||
|
|
||||||
// If there's a color property, we should convert it to
|
// If there's a color property, we should convert it to
|
||||||
// a --fills CSS variable property.
|
// a --fills CSS variable property.
|
||||||
const fills = styleDeclaration.getPropertyValue("--fills");
|
const fills = getPropertyValue(styleDeclaration, "--fills");
|
||||||
const color = styleDeclaration.getPropertyValue("color");
|
const color = getPropertyValue(styleDeclaration, "color");
|
||||||
if (color && !fills) {
|
if (color && !fills) {
|
||||||
styleDeclaration.removeProperty("color");
|
styleDeclaration.removeProperty("color");
|
||||||
styleDeclaration.setProperty("--fills", getFills(color));
|
styleDeclaration.setProperty("--fills", getFills(color));
|
||||||
} else {
|
} else if (fills) {
|
||||||
styleDeclaration.setProperty("--fills", 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
|
// If there's a font-family property and not a --font-id, then
|
||||||
// we remove the font-family because it will not work.
|
// we remove the font-family because it will not work.
|
||||||
const fontFamily = styleDeclaration.getPropertyValue("font-family");
|
const fontFamily = getPropertyValue(styleDeclaration, "font-family");
|
||||||
const fontId = styleDeclaration.getPropertyValue("--font-id");
|
const fontId = getPropertyValue(styleDeclaration, "--font-id");
|
||||||
if (fontFamily && !fontId) {
|
if (fontFamily && !fontId) {
|
||||||
styleDeclaration.removeProperty("font-family");
|
styleDeclaration.removeProperty("font-family");
|
||||||
}
|
}
|
||||||
|
|
||||||
const fontSize = styleDeclaration.getPropertyValue("font-size");
|
const fontSize = getPropertyValue(styleDeclaration, "font-size");
|
||||||
if (!fontSize || fontSize === "0px") {
|
if (!fontSize || fontSize === "0px") {
|
||||||
styleDeclaration.setProperty("font-size", DEFAULT_FONT_SIZE);
|
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")) {
|
if (!lineHeight || lineHeight === "" || !lineHeight.endsWith("px")) {
|
||||||
// TODO: Podríamos convertir unidades en decimales.
|
// TODO: Podríamos convertir unidades en decimales.
|
||||||
styleDeclaration.setProperty("line-height", DEFAULT_LINE_HEIGHT);
|
styleDeclaration.setProperty("line-height", DEFAULT_LINE_HEIGHT);
|
||||||
} else if (lineHeight.endsWith("px")) {
|
} else if (lineHeight.endsWith("px")) {
|
||||||
const fontSize = styleDeclaration.getPropertyValue("font-size");
|
const fontSize = getPropertyValue(styleDeclaration, "font-size");
|
||||||
styleDeclaration.setProperty(
|
styleDeclaration.setProperty(
|
||||||
"line-height",
|
"line-height",
|
||||||
parseFloat(lineHeight) / parseFloat(fontSize),
|
parseFloat(lineHeight) / parseFloat(fontSize),
|
||||||
|
|||||||
@@ -46,6 +46,7 @@ import CommandMutations from "../commands/CommandMutations.js";
|
|||||||
import { isRoot, setRootStyles } from "../content/dom/Root.js";
|
import { isRoot, setRootStyles } from "../content/dom/Root.js";
|
||||||
import { SelectionDirection } from "./SelectionDirection.js";
|
import { SelectionDirection } from "./SelectionDirection.js";
|
||||||
import SafeGuard from "./SafeGuard.js";
|
import SafeGuard from "./SafeGuard.js";
|
||||||
|
import { mergeStyleDeclarations } from '../content/dom/Style.js';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Supported options for the SelectionController.
|
* 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
|
* 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([
|
* our own internal model based on paragraphs (in draft.js they were called blocks) and inlines.
|
||||||
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.
|
|
||||||
*/
|
*/
|
||||||
export class SelectionController extends EventTarget {
|
export class SelectionController extends EventTarget {
|
||||||
/**
|
/**
|
||||||
@@ -253,11 +222,7 @@ export class SelectionController extends EventTarget {
|
|||||||
* @param {HTMLElement} element
|
* @param {HTMLElement} element
|
||||||
*/
|
*/
|
||||||
#applyStylesToCurrentStyle(element) {
|
#applyStylesToCurrentStyle(element) {
|
||||||
for (let index = 0; index < element.style.length; index++) {
|
mergeStyleDeclarations(this.#currentStyle, element.style);
|
||||||
const styleName = element.style.item(index);
|
|
||||||
const styleValue = element.style.getPropertyValue(styleName);
|
|
||||||
this.#currentStyle.setProperty(styleName, styleValue);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
Reference in New Issue
Block a user