diff --git a/frontend/src/app/render_wasm/api/fonts.cljs b/frontend/src/app/render_wasm/api/fonts.cljs index 7acb5c88ff..0e095d1cc8 100644 --- a/frontend/src/app/render_wasm/api/fonts.cljs +++ b/frontend/src/app/render_wasm/api/fonts.cljs @@ -158,7 +158,7 @@ (defn- store-font-id [shape-id font-data asset-id emoji? fallback?] (when asset-id - (let [uri (font-id->ttf-url (:font-id font-data) asset-id (:font-variant-id font-data) (:weight font-data) (:style font-data)) + (let [uri (font-id->ttf-url (:font-id font-data) asset-id (:font-variant-id font-data) (:weight font-data) (:style-name font-data)) id-buffer (uuid/get-u32 (:wasm-id font-data)) font-data (assoc font-data :family-id-buffer id-buffer) font-stored? (not= 0 (h/call wasm/internal-module "_is_font_uploaded" @@ -200,7 +200,7 @@ font-style-fallback (or (:font-style span) (:font-style paragraph)) font-data (font-db-data font-id font-variant-id font-weight-fallback font-style-fallback)] (-> span - (assoc :font-variant-id (or (:name font-data) (:id font-data) font-variant-id) + (assoc :font-variant-id (or (:id font-data) (:id font-data) font-variant-id) :font-weight (or (:weight font-data) font-weight-fallback) :font-style (or (:style font-data) font-style-fallback))))) @@ -212,7 +212,7 @@ font-style-fallback (:font-style paragraph) font-data (font-db-data font-id font-variant-id font-weight-fallback font-style-fallback)] (-> paragraph - (assoc :font-variant-id (or (:name font-data) (:id font-data) font-variant-id) + (assoc :font-variant-id (or (:id font-data) (:id font-data) font-variant-id) :font-weight (or (:weight font-data) font-weight-fallback) :font-style (or (:style font-data) font-style-fallback))))) @@ -284,24 +284,29 @@ [shape-id font] (let [font-id (get font :font-id) font-variant-id (get font :font-variant-id) + normalized-variant-id (when font-variant-id + (-> font-variant-id + (str/lower) + (str/replace #"\s+" ""))) font-weight-fallback (or (get font :font-weight) 400) font-style-fallback (or (get font :font-style) "normal") emoji? (get font :is-emoji false) fallback? (get font :is-fallback false) - font-data (font-db-data font-id font-variant-id font-weight-fallback font-style-fallback) + font-data (font-db-data font-id normalized-variant-id font-weight-fallback font-style-fallback) wasm-id (font-id->uuid font-id) raw-weight (or (:weight font-data) font-weight-fallback) weight (serialize-font-weight raw-weight) - style (serialize-font-style (cond - (str/includes? font-variant-id "italic") "italic" - (str/includes? raw-weight "italic") "italic" - :else font-style-fallback)) - variant-id (or (:name font-data) font-variant-id) + style (cond + (str/includes? (or normalized-variant-id "") "italic") "italic" + (str/includes? raw-weight "italic") "italic" + :else font-style-fallback) + variant-id (or (:id font-data) normalized-variant-id) asset-id (font-id->asset-id font-id variant-id raw-weight style) font-data {:wasm-id wasm-id :font-id font-id :font-variant-id variant-id - :style style + :style (serialize-font-style style) + :style-name style :weight weight}] (store-font-id shape-id font-data asset-id emoji? fallback?))) @@ -329,7 +334,7 @@ font-style-fallback (or font-style (:font-style txt/default-typography) "normal") font-data (font-db-data resolved-font-id resolved-variant-id font-weight-fallback font-style-fallback) font-ref {:font-id resolved-font-id - :font-variant-id (or (:name font-data) (:id font-data) resolved-variant-id) + :font-variant-id (or (:id font-data) (:name font-data) resolved-variant-id) :font-weight (or (:weight font-data) font-weight-fallback) :font-style (or (:style font-data) font-style-fallback)}] (conj result font-ref))) diff --git a/frontend/text-editor/src/editor/content/dom/Style.js b/frontend/text-editor/src/editor/content/dom/Style.js index 0a7f31d02a..cc11320495 100644 --- a/frontend/text-editor/src/editor/content/dom/Style.js +++ b/frontend/text-editor/src/editor/content/dom/Style.js @@ -339,13 +339,14 @@ export function setStylesFromObject(element, allowedStyles, styleObject) { continue; } let styleValue = styleObject[styleName]; + if (!styleValue) + continue; + if (styleName === "font-family") { styleValue = sanitizeFontFamily(styleValue); } - if (styleValue) { - setStyle(element, styleName, styleValue, styleUnit); - } + setStyle(element, styleName, styleValue, styleUnit); } return element; } diff --git a/frontend/text-editor/src/editor/controllers/SelectionController.js b/frontend/text-editor/src/editor/controllers/SelectionController.js index 9a452e4795..edfe69c03e 100644 --- a/frontend/text-editor/src/editor/controllers/SelectionController.js +++ b/frontend/text-editor/src/editor/controllers/SelectionController.js @@ -238,7 +238,11 @@ export class SelectionController extends EventTarget { #applyStylesFromElementToCurrentStyle(element) { for (let index = 0; index < element.style.length; index++) { const styleName = element.style.item(index); + if (styleName === "--fills") { + continue; + } let styleValue = element.style.getPropertyValue(styleName); + if (styleName === "font-family") { styleValue = sanitizeFontFamily(styleValue); } @@ -1939,11 +1943,21 @@ export class SelectionController extends EventTarget { const textSpan = this.startTextSpan; const midText = startNode.splitText(startOffset); const endText = midText.splitText(endOffset - startOffset); - const midTextSpan = createTextSpanFrom(textSpan, midText, newStyles); - textSpan.after(midTextSpan); - if (endText.length > 0) { - const endTextSpan = createTextSpan(endText, textSpan.style); - midTextSpan.after(endTextSpan); + + // Only create text span if midText is not empty + if (midText.nodeValue && midText.nodeValue.length > 0) { + const midTextSpan = createTextSpanFrom(textSpan, midText, newStyles); + textSpan.after(midTextSpan); + if (endText.length > 0) { + const endTextSpan = createTextSpan(endText, textSpan.style); + midTextSpan.after(endTextSpan); + } + } else { + // If midText is empty, just create endTextSpan if needed + if (endText.length > 0) { + const endTextSpan = createTextSpan(endText, textSpan.style); + textSpan.after(endTextSpan); + } } // NOTE: This is necessary because sometimes @@ -1960,7 +1974,7 @@ export class SelectionController extends EventTarget { // the styles are applied to the current caret else if ( this.startOffset === this.endOffset && - this.endOffset === endNode.nodeValue.length + this.endOffset === endNode.nodeValue?.length ) { const newTextSpan = createVoidTextSpan(newStyles); this.endTextSpan.after(newTextSpan); @@ -1996,7 +2010,8 @@ export class SelectionController extends EventTarget { // new text span. if ( this.#textNodeIterator.currentNode === startNode && - startOffset > 0 + startOffset > 0 && + startOffset < (startNode.nodeValue?.length || 0) ) { const newTextSpan = splitTextSpan(textSpan, startOffset); setTextSpanStyles(newTextSpan, newStyles); @@ -2011,14 +2026,15 @@ export class SelectionController extends EventTarget { (this.#textNodeIterator.currentNode !== startNode && this.#textNodeIterator.currentNode !== endNode) || (this.#textNodeIterator.currentNode === endNode && - endOffset === endNode.nodeValue.length) + endOffset === endNode.nodeValue?.length) ) { setTextSpanStyles(textSpan, newStyles); // If we're at end node } else if ( this.#textNodeIterator.currentNode === endNode && - endOffset < endNode.nodeValue.length + endOffset < endNode.nodeValue?.length && + endOffset > 0 ) { const newTextSpan = splitTextSpan(textSpan, endOffset); setTextSpanStyles(textSpan, newStyles); diff --git a/frontend/text-editor/src/editor/controllers/StyleDeclaration.js b/frontend/text-editor/src/editor/controllers/StyleDeclaration.js index 3b2bf5d88d..fcca9e39b4 100644 --- a/frontend/text-editor/src/editor/controllers/StyleDeclaration.js +++ b/frontend/text-editor/src/editor/controllers/StyleDeclaration.js @@ -81,6 +81,8 @@ export class StyleDeclaration { return this.setProperty(name, value); } else if (currentValue === "" && ["initial", "none"].includes(value)) { return this.setProperty(name, value); + } else if (currentValue !== value && name === "--fills") { + return this.setProperty(name, value); } else if (currentValue !== value) { return this.setProperty(name, "mixed"); }