🐛 Fix v2 text editor detaching typography tokens (#10402)

This commit is contained in:
Alejandro Alonso 2026-06-24 18:20:21 +02:00 committed by GitHub
parent 27274a56fd
commit b096832bf5
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 55 additions and 8 deletions

View File

@ -78,6 +78,11 @@
text-transform-attrs
text-fills))
(def text-span-attrs
"Inline text span attrs. Line-height is paragraph-level in the DOM editor;
it may still be stored redundantly on span nodes."
(vec (remove #{:line-height} text-node-attrs)))
(defn text-node-attr?
[attr]
(d/index-of text-node-attrs attr))
@ -317,9 +322,16 @@
"Given two content text structures, conformed by maps and vectors,
compare them, and returns a set with the attributes that have changed.
This is independent of the text structure, so if the structure changes
but the attributes are the same, it will return an empty set."
but the attributes are the same, it will return an empty set.
Line-height on text nodes is ignored: it is a paragraph-level attribute
and may be stored redundantly on spans (e.g. after token apply)."
[a b]
(let [diff-attrs (compare-text-content a b
(let [strip-span-line-height
#(transform-nodes is-text-node? (fn [node] (dissoc node :line-height)) %)
a (strip-span-line-height a)
b (strip-span-line-height b)
diff-attrs (compare-text-content a b
{:text-cb identity
:attribute-cb (fn [acc attr] (conj acc attr))})]
(if-not (contains? diff-attrs :text-content-structure)

View File

@ -76,8 +76,31 @@
(assoc-in content-base [:children 0 :children 0 :children 0 :font-family] "Arial"))
(def content-changed-line-height
(assoc-in content-base [:children 0 :children 0 :line-height] "1.5"))
(def content-redundant-span-line-height
(assoc-in content-base [:children 0 :children 0 :children 0 :line-height] "1.5"))
;; Token apply may store line-height on paragraph and spans; after a DOM
;; round-trip spans no longer carry it (paragraph-level in the editor).
(def content-token-like-line-height
(-> content-base
(assoc-in [:children 0 :children 0 :line-height] 1.4)
(assoc-in [:children 0 :children 0 :children 0 :line-height] 1.4)))
(def content-after-editor-roundtrip
(update-in content-token-like-line-height
[:children 0 :children 0 :children 0]
dissoc :line-height))
;; from_dom used to merge default nil typography refs on import.
(def content-explicit-nil-typography-refs
(-> content-base
(assoc-in [:children 0 :children 0 :typography-ref-id] nil)
(assoc-in [:children 0 :children 0 :typography-ref-file] nil)
(assoc-in [:children 0 :children 0 :children 0 :typography-ref-id] nil)
(assoc-in [:children 0 :children 0 :children 0 :typography-ref-file] nil)))
(def content-changed-letter-spacing
(assoc-in content-base [:children 0 :children 0 :children 0 :letter-spacing] "2"))
@ -185,6 +208,10 @@
;; Other text-node-attr categories
attrs-font-family (cttx/get-diff-attrs content-base content-changed-font-family)
attrs-line-height (cttx/get-diff-attrs content-base content-changed-line-height)
attrs-span-line-height (cttx/get-diff-attrs content-base content-redundant-span-line-height)
attrs-roundtrip-line-height (cttx/get-diff-attrs content-token-like-line-height
content-after-editor-roundtrip)
attrs-nil-typography-refs (cttx/get-diff-attrs content-base content-explicit-nil-typography-refs)
attrs-letter-spacing (cttx/get-diff-attrs content-base content-changed-letter-spacing)
attrs-text-decoration (cttx/get-diff-attrs content-base content-changed-text-decoration)
attrs-text-transform (cttx/get-diff-attrs content-base content-changed-text-transform)
@ -215,6 +242,9 @@
;; Each text-node-attr category reports correct attr key
(t/is (= #{:font-family} attrs-font-family))
(t/is (= #{:line-height} attrs-line-height))
(t/is (= #{} attrs-span-line-height))
(t/is (= #{} attrs-roundtrip-line-height))
(t/is (= #{} attrs-nil-typography-refs))
(t/is (= #{:letter-spacing} attrs-letter-spacing))
(t/is (= #{:text-decoration} attrs-text-decoration))
(t/is (= #{:text-transform} attrs-text-transform))

View File

@ -51,13 +51,19 @@
[_ style-decode] (get styles/mapping key)]
(style-decode (.getPropertyValue style style-name)))
(let [style-name (styles/get-style-name key)]
(styles/normalize-attr-value key (.getPropertyValue style style-name))))]
(assoc acc key (if (value-empty? value) (get defaults key) value))))
(styles/normalize-attr-value key (.getPropertyValue style style-name))))
default (get defaults key)
final-value (if (value-empty? value) default value)]
;; Omit attrs with no CSS value when the default is nil (e.g.
;; typography-ref-id). Avoids polluting round-tripped content.
(if (and (value-empty? value) (nil? default))
acc
(assoc acc key final-value))))
{} attrs)))
(defn get-text-span-styles
[element]
(get-attrs-from-styles element txt/text-node-attrs (txt/get-default-text-attrs)))
(get-attrs-from-styles element txt/text-span-attrs (txt/get-default-text-attrs)))
(defn get-paragraph-styles
[element]

View File

@ -94,9 +94,8 @@
(defn get-text-span-styles
[inline paragraph]
(let [node (if (= "" (:text inline)) paragraph inline)
styles (get-styles-from-attrs node txt/text-node-attrs txt/default-text-attrs)]
(dissoc styles :line-height)))
(let [node (if (= "" (:text inline)) paragraph inline)]
(get-styles-from-attrs node txt/text-span-attrs txt/default-text-attrs)))
(defn normalize-spaces
"Add zero-width spaces after forward slashes to enable word breaking"