From b2439694af99ac362b63141ea2ec8287410f3a95 Mon Sep 17 00:00:00 2001 From: Alonso Torres Date: Fri, 12 Jun 2026 09:10:36 +0200 Subject: [PATCH] :bug: Fix float precision in typography line-height/letter-spacing string conversion (#9973) --- .../src/app/main/data/workspace/texts.cljs | 4 +- .../sidebar/options/menus/typography.cljs | 2 +- .../data/workspace_texts_test.cljs | 104 +++++++++++++++++- 3 files changed, 106 insertions(+), 4 deletions(-) diff --git a/frontend/src/app/main/data/workspace/texts.cljs b/frontend/src/app/main/data/workspace/texts.cljs index 6d6f1b691b..30b2ecf40b 100644 --- a/frontend/src/app/main/data/workspace/texts.cljs +++ b/frontend/src/app/main/data/workspace/texts.cljs @@ -957,10 +957,10 @@ txt/text-transform-attrs))) values (cond-> values (number? (:line-height values)) - (update :line-height str) + (update :line-height #(str (mth/precision % 2))) (number? (:letter-spacing values)) - (update :letter-spacing str)) + (update :letter-spacing #(str (mth/precision % 2)))) typ-id (uuid/next) typ (-> (if multiple? diff --git a/frontend/src/app/main/ui/workspace/sidebar/options/menus/typography.cljs b/frontend/src/app/main/ui/workspace/sidebar/options/menus/typography.cljs index ea54329e8f..38c15568dd 100644 --- a/frontend/src/app/main/ui/workspace/sidebar/options/menus/typography.cljs +++ b/frontend/src/app/main/ui/workspace/sidebar/options/menus/typography.cljs @@ -382,7 +382,7 @@ letter-spacing (or letter-spacing "0") handle-change (fn [value attr] - (on-change {attr (str value)}))] + (on-change {attr (ust/format-precision value 2)}))] [:div {:class (stl/css :spacing-options)} [:div {:class (stl/css :line-height) diff --git a/frontend/test/frontend_tests/data/workspace_texts_test.cljs b/frontend/test/frontend_tests/data/workspace_texts_test.cljs index bbb1fe2421..15db703ef8 100644 --- a/frontend/test/frontend_tests/data/workspace_texts_test.cljs +++ b/frontend/test/frontend_tests/data/workspace_texts_test.cljs @@ -7,9 +7,13 @@ (ns frontend-tests.data.workspace-texts-test (:require [app.common.geom.rect :as grc] + [app.common.test-helpers.files :as cthf] + [app.common.test-helpers.shapes :as cths] [app.common.types.shape :as cts] + [app.common.types.text :as txt] [app.main.data.workspace.texts :as dwt] - [cljs.test :as t :include-macros true])) + [cljs.test :as t :include-macros true] + [frontend-tests.helpers.state :as ths])) ;; --------------------------------------------------------------------------- ;; Helpers @@ -272,3 +276,101 @@ result (dwt/apply-text-modifier shape {:width 200 :position-data pd})] (t/is (some? result)) (t/is (some? (:selrect result)))))) + +;; --------------------------------------------------------------------------- +;; Tests: add-typography event normalises float line-height / letter-spacing +;; +;; These tests exercise the full add-typography event path in texts.cljs: +;; a text shape whose content nodes carry float line-height / letter-spacing +;; values (as produced by JS float arithmetic) must yield a typography entry +;; in the file with properly-rounded *string* values, not the raw floats. +;; +;; Root cause reproduced here: JS float arithmetic (e.g. 1.3 - 0.1) can +;; produce 1.2000000000000002 instead of 1.2. Without the fix, that number +;; survives through add-typography unchanged, and (ctt/check-typography) +;; would throw because :line-height must be a :string. +;; With the fix (mth/precision + str), it is normalised to "1.2" before the +;; schema check runs. +;; --------------------------------------------------------------------------- + +(t/deftest add-typography-normalises-float-line-height + (t/async + done + (let [;; Exact value reproduced from the issue: 1.3 - 0.1 in JS + float-lh 1.2000000000000002 + content (txt/change-text nil "hello" :line-height float-lh) + file (-> (cthf/sample-file :file1) + (cths/add-sample-shape :text1 + :type :text + :x 0 :y 0 + :content content)) + shape-id (:id (cths/get-shape file :text1)) + file-id (:id file) + store (ths/setup-store file) + events [;; Pre-select the text shape so add-typography can find it + (fn [state] (assoc-in state [:workspace-local :selected] #{shape-id})) + (dwt/add-typography file-id)]] + + (ths/run-store + store done events + (fn [new-state] + (let [file' (ths/get-file-from-state new-state) + typographies (vals (get-in file' [:data :typographies]))] + (t/is (= 1 (count typographies)) + "exactly one typography was added") + (t/is (= "1.2" (:line-height (first typographies))) + "float line-height is normalised to 2-decimal string"))))))) + +(t/deftest add-typography-truncates-line-height-to-two-decimals + (t/async + done + (let [;; A value with more than 2 decimal places: 1.234234234 → "1.23" + long-lh 1.234234234 + content (txt/change-text nil "hello" :line-height long-lh) + file (-> (cthf/sample-file :file1) + (cths/add-sample-shape :text1 + :type :text + :x 0 :y 0 + :content content)) + shape-id (:id (cths/get-shape file :text1)) + file-id (:id file) + store (ths/setup-store file) + events [(fn [state] (assoc-in state [:workspace-local :selected] #{shape-id})) + (dwt/add-typography file-id)]] + + (ths/run-store + store done events + (fn [new-state] + (let [file' (ths/get-file-from-state new-state) + typographies (vals (get-in file' [:data :typographies]))] + (t/is (= 1 (count typographies)) + "exactly one typography was added") + (t/is (= "1.23" (:line-height (first typographies))) + "line-height with more than 2 decimals is truncated to 2"))))))) + +(t/deftest add-typography-normalises-float-letter-spacing + (t/async + done + (let [;; Analogous imprecision for letter-spacing + float-ls 0.10000000000000001 + content (txt/change-text nil "hello" :letter-spacing float-ls) + file (-> (cthf/sample-file :file1) + (cths/add-sample-shape :text1 + :type :text + :x 0 :y 0 + :content content)) + shape-id (:id (cths/get-shape file :text1)) + file-id (:id file) + store (ths/setup-store file) + events [(fn [state] (assoc-in state [:workspace-local :selected] #{shape-id})) + (dwt/add-typography file-id)]] + + (ths/run-store + store done events + (fn [new-state] + (let [file' (ths/get-file-from-state new-state) + typographies (vals (get-in file' [:data :typographies]))] + (t/is (= 1 (count typographies)) + "exactly one typography was added") + (t/is (= "0.1" (:letter-spacing (first typographies))) + "float letter-spacing is normalised to 2-decimal string")))))))