🐛 Replace stale font identities in text test edits

Clear raw font identity fields owned by a requested family, weight or
italic edit. Preserve the other font unit and retain opaque identities
when changing an unrelated style such as size (F226).

Four assertions fail before the correction. Focused notation, source,
text sync/switch and golden checks pass 51 tests and 1,887 assertions.
Full common JVM/JS, frontend, backend and exporter suites and applicable
lint/format checks pass. All six generated properties pass 40 programs
at seed 712. Golden data and production behavior are unchanged.

AI-assisted-by: GPT-6
This commit is contained in:
alonso.torres 2026-10-28 00:06:57 +01:00
parent e4239e02b7
commit e4fb356cb5
2 changed files with 60 additions and 2 deletions

View File

@ -332,14 +332,18 @@
(defn restyle
"Set the run style `k` to `v` on every run of `text`.
Named colors and explicit fills replace each other."
Named colors and explicit fills replace each other. Font edits replace
stale raw identities while preserving the other font unit."
[text k v]
(update-paragraphs text
(fn [[style runs]]
[style (map (fn [[letters run-style]]
[letters (cond-> (assoc run-style k v)
(= k :color) (dissoc :fills)
(= k :fills) (dissoc :color))])
(= k :fills) (dissoc :color)
(= k :family) (dissoc :font-family :font-id)
(= k :weight) (dissoc :font-weight :font-variant-id)
(= k :italic) (dissoc :font-style :font-variant-id))])
(detach-typography runs k))])))
(defn restyle-paragraphs

View File

@ -30,6 +30,60 @@
(t/is (= [[["Library text" {:fills nil :size 18}]]] styled))
(t/is (nil? (get-in (thtx/content styled) [:children 0 :children 0 :children 0 :fills])))))
(defn- get-run
[text]
(first (txt/node-seq txt/is-text-node? (thtx/content text))))
(t/deftest font-family-edit-replaces-the-raw-family-identity
(let [text (thtx/normalize [[["Custom font" {:family "Roboto" :font-id "custom-font"
:weight 700 :font-style "oblique"
:font-variant-id "opaque-variant" :size 18 :color :blue}]]])
before (get-run text)
after (get-run (thtx/restyle text :family "Inter"))]
(t/is (= {:font-family "Inter" :font-id "gfont-inter"}
(select-keys after [:font-family :font-id])))
(t/is (= (select-keys before [:font-weight :font-style :font-variant-id])
(select-keys after [:font-weight :font-style :font-variant-id]))
"a family edit preserves the weight unit's opaque identity")
(t/is (= (select-keys before [:text :font-size :fills])
(select-keys after [:text :font-size :fills])))))
(t/deftest font-weight-edit-replaces-the-raw-variant-identity
(let [text (thtx/normalize [[["Custom font" {:family "Roboto" :font-id "custom-font"
:font-variant-id "opaque-variant" :italic true
:size 18 :color :blue}]]])
before (get-run text)
after (get-run (thtx/restyle text :weight 700))]
(t/is (= {:font-weight "700" :font-style "italic" :font-variant-id "700italic"}
(select-keys after [:font-weight :font-style :font-variant-id])))
(t/is (= (select-keys before [:font-family :font-id])
(select-keys after [:font-family :font-id])))
(t/is (= (select-keys before [:text :font-size :fills])
(select-keys after [:text :font-size :fills])))))
(t/deftest font-style-edit-replaces-the-raw-style-and-variant-identities
(doseq [[italic style variant] [[true "italic" "700italic"] [false "normal" "700"]]]
(let [text (thtx/normalize [[["Custom font" {:family "Roboto" :font-id "custom-font"
:weight 700 :font-style "oblique"
:font-variant-id "opaque-variant" :size 18 :color :blue}]]])
before (get-run text)
after (get-run (thtx/restyle text :italic italic))]
(t/is (= {:font-weight "700" :font-style style :font-variant-id variant}
(select-keys after [:font-weight :font-style :font-variant-id])))
(t/is (= (select-keys before [:font-family :font-id])
(select-keys after [:font-family :font-id])))
(t/is (= (select-keys before [:text :font-size :fills])
(select-keys after [:text :font-size :fills]))))))
(t/deftest other-text-edits-keep-opaque-font-identities
(let [text (thtx/normalize [[["Custom font" {:family "Roboto" :font-id "custom-font"
:weight 700 :font-style "oblique"
:font-variant-id "opaque-variant" :size 18 :color :blue}]]])
before (get-run text)
after (get-run (thtx/restyle text :size 24))]
(t/is (= "24" (:font-size after)))
(t/is (= (dissoc before :font-size) (dissoc after :font-size)))))
(t/deftest content-is-written-as-the-editors-write-it
(let [content (thtx/content [[["Price: "] ["$10" {:weight 700 :color :red}]]])
paragraph (first (txt/node-seq txt/is-paragraph-node? content))