From b02d54b21e71dbc7a6e37ffaa489868e728d4493 Mon Sep 17 00:00:00 2001 From: Andrey Antukh Date: Mon, 13 Apr 2026 17:05:19 +0000 Subject: [PATCH] :bug: Dissoc typography-ref-file and typography-ref-id when nil instead of assigning nil When detaching a typography, the code was setting typography-ref-file and typography-ref-id to nil instead of removing the keys entirely. This caused nil values to leak into text node data through multiple code paths (Draft.js styles, WASM text editor, v2 editor). Fix the issue by: - Filtering nil values in attrs-to-styles (legacy Draft.js encoder) - Using d/txt-merge instead of merge in WASM apply-attrs-to-paragraph - Filtering nil values in attrs->styles (v2 editor style mapper) - Filtering nil values in updateBlockData calls in Draft.js editor - Removing hardcoded nil assignments in text-editor-get-current-styles - Filtering nil values in insert-text before encoding --- common/src/app/common/text.cljc | 4 +++- frontend/src/app/render_wasm/text_editor.cljs | 7 +++---- frontend/src/app/util/text/content/styles.cljs | 4 +++- frontend/src/app/util/text_editor.cljs | 6 ++++-- 4 files changed, 13 insertions(+), 8 deletions(-) diff --git a/common/src/app/common/text.cljc b/common/src/app/common/text.cljc index e0ed3515e6..cc997f62d6 100644 --- a/common/src/app/common/text.cljc +++ b/common/src/app/common/text.cljc @@ -37,7 +37,9 @@ (defn attrs-to-styles [attrs] (reduce-kv (fn [res k v] - (conj res (encode-style k v))) + (if (some? v) + (conj res (encode-style k v)) + res)) #{} attrs)) diff --git a/frontend/src/app/render_wasm/text_editor.cljs b/frontend/src/app/render_wasm/text_editor.cljs index 1cfb5b834c..6c578732bc 100644 --- a/frontend/src/app/render_wasm/text_editor.cljs +++ b/frontend/src/app/render_wasm/text_editor.cljs @@ -7,6 +7,7 @@ (ns app.render-wasm.text-editor "Text editor WASM bindings" (:require + [app.common.data :as d] [app.common.types.fills.impl :as types.fills.impl] [app.common.uuid :as uuid] [app.main.fonts :as main-fonts] @@ -310,8 +311,6 @@ :font-family (text-editor-get-style-property font-family-state font-id) :font-id (text-editor-get-style-property font-family-state font-id) :font-variant-id (text-editor-get-style-property font-variant-id-state font-variant-id-computed) - :typography-ref-file nil - :typography-ref-id nil :selected-colors selected-colors :fills fills}] @@ -582,8 +581,8 @@ (recur (rest spans) span-end (conj acc span)) (let [before (when (> ol-start pos) (assoc span :text (subs text 0 (- ol-start pos)))) - selected (merge span attrs - {:text (subs text (- ol-start pos) (- ol-end pos))}) + selected (d/txt-merge (assoc span :text (subs text (- ol-start pos) (- ol-end pos))) + attrs) after (when (< ol-end span-end) (assoc span :text (subs text (- ol-end pos))))] (recur (rest spans) span-end diff --git a/frontend/src/app/util/text/content/styles.cljs b/frontend/src/app/util/text/content/styles.cljs index c67ca4d629..0adc821d46 100644 --- a/frontend/src/app/util/text/content/styles.cljs +++ b/frontend/src/app/util/text/content/styles.cljs @@ -132,7 +132,9 @@ "Maps attrs to styles" [styles] (let [mapped-styles - (into {} (map attr->style styles))] + (into {} (comp (filter (fn [[_ v]] (some? v))) + (map attr->style)) + styles)] (clj->js mapped-styles))) (defn style-needs-mapping? diff --git a/frontend/src/app/util/text_editor.cljs b/frontend/src/app/util/text_editor.cljs index ab746f7393..3ec29a89fc 100644 --- a/frontend/src/app/util/text_editor.cljs +++ b/frontend/src/app/util/text_editor.cljs @@ -8,6 +8,7 @@ "Draft related abstraction functions." (:require ["@penpot/draft-js" :as impl] + [app.common.data :as d] [app.common.text :as legacy.txt])) ;; --- CONVERSION @@ -93,7 +94,7 @@ (let [update-blocks (fn [state block-key] (if (empty? (impl/getBlockContent state block-key)) - (impl/updateBlockData state block-key (clj->js attrs)) + (impl/updateBlockData state block-key (clj->js (d/without-nils attrs))) (let [attrs (-> (impl/getInlineStyle state block-key 0) (legacy.txt/styles-to-attrs) @@ -156,7 +157,8 @@ (impl/setSelection $ selection))))) (defn insert-text [state text attrs] - (let [style (legacy.txt/attrs-to-styles attrs)] + (let [attrs (d/without-nils attrs) + style (legacy.txt/attrs-to-styles attrs)] (impl/insertText state text (clj->js attrs) (clj->js style)))) (defn get-style-override [state]