🐛 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
This commit is contained in:
Andrey Antukh 2026-04-13 17:05:19 +00:00 committed by Eva Marco
parent b5922d32ca
commit b02d54b21e
4 changed files with 13 additions and 8 deletions

View File

@ -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))

View File

@ -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

View File

@ -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?

View File

@ -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]