mirror of
https://github.com/penpot/penpot.git
synced 2026-09-11 14:39:35 +00:00
🐛 Fix fontFamilies token property mapping in Plugin API (#11566)
* 🐛 Fix fontFamilies token property mapping in Plugin API The Plugin API exposes the font-family token property as `fontFamilies`, while Penpot stores the canonical applied-token attribute as `:font-family`. The bidirectional plugin/internal attribute map did not contain that alias, so explicit `applyToken(..., ["fontFamilies"])` validation rejected the property and applied-token readback exposed the undocumented singular `fontFamily`. Add `:font-family -> :font-families` to the existing canonical alias map. The reverse mapping is derived automatically, keeping application and readback symmetric without introducing a font-specific code path. Closes #11405 AI-assisted-by: Omen Alpha Signed-off-by: 최준수 <junsoo1172@gmail.com> * 🐛 Fix fontFamilies e2e test to target a text shape The fontFamilies end-to-end regression created a flex layout frame, whose attribute set (frame-with-layout-attributes) excludes :font-family. The workspace token application filters such shapes, so the internal binding and readback assertions would pass vacuously without exercising the alias. Target an actual `:text` shape (ctho/add-text) instead, so the test verifies the full JS "fontFamilies" -> schema -> alias -> canonical :font-family -> camelCase readback path. AI-assisted-by: Omen Alpha Signed-off-by: 최준수 <junsoo1172@gmail.com> * 🐛 Fix fontFamilies test WASM error and add changelog entry The text-shape fontFamilies e2e applies a layout-affecting token via wasm renderer path, hitting missing WASM exports under Node. Merge thw/setup-wasm-mocks! into the :each fixture and add plugins CHANGELOG entry for the fontFamilies alias fix. AI-assisted-by: muse-spark-1.3-contributor Related to #11566 Signed-off-by: makesomethingshit <junsoo1172@gmail.com> --------- Signed-off-by: 최준수 <junsoo1172@gmail.com> Signed-off-by: makesomethingshit <junsoo1172@gmail.com>
This commit is contained in:
parent
dc12f1db91
commit
30849babcc
@ -41,7 +41,9 @@
|
||||
:m1 :margin-top
|
||||
:m2 :margin-right
|
||||
:m3 :margin-bottom
|
||||
:m4 :margin-left})
|
||||
:m4 :margin-left
|
||||
|
||||
:font-family :font-families})
|
||||
|
||||
(def ^:private map:token-attr-plugin->token-attr
|
||||
(merge
|
||||
|
||||
@ -22,9 +22,14 @@
|
||||
[cljs.test :as t :include-macros true]
|
||||
[frontend-tests.helpers.mock :as mock]
|
||||
[frontend-tests.helpers.state :as ths]
|
||||
[frontend-tests.helpers.wasm :as thw]
|
||||
[potok.v2.core :as ptk]))
|
||||
|
||||
(t/use-fixtures :each {:before cthi/reset-idmap!})
|
||||
(t/use-fixtures :each
|
||||
{:before (fn []
|
||||
(cthi/reset-idmap!)
|
||||
(thw/setup-wasm-mocks!))
|
||||
:after thw/teardown-wasm-mocks!})
|
||||
|
||||
(def ^:private get-resolved-value @#'ptok/get-resolved-value)
|
||||
|
||||
@ -81,6 +86,18 @@
|
||||
(t/is (= :m3 (ptok/token-attr-plugin->token-attr :margin-bottom)))
|
||||
(t/is (= :m4 (ptok/token-attr-plugin->token-attr :margin-left))))
|
||||
|
||||
(t/deftest token-attr-plugin->token-attr-resolves-font-family-alias
|
||||
;; Plugin-facing `fontFamilies` (kebab-cased to `:font-families` by the
|
||||
;; schema layer) maps to the canonical internal `:font-family`.
|
||||
(t/is (= :font-family (ptok/token-attr-plugin->token-attr :font-families)))
|
||||
(t/is (= :font-family (ptok/token-attr-plugin->token-attr "font-families"))))
|
||||
|
||||
(t/deftest token-attr->token-attr-plugin-resolves-font-family-alias
|
||||
;; Symmetric direction: the canonical internal attribute maps to the
|
||||
;; plural plugin-facing name so applied-token readback serializes as
|
||||
;; camelCase `fontFamilies`, not the undocumented singular `fontFamily`.
|
||||
(t/is (= :font-families (ptok/token-attr->token-attr-plugin :font-family))))
|
||||
|
||||
(t/deftest token-attr-plugin->token-attr-coerces-string-input
|
||||
;; This is the actual regression — JS plugin calls supply strings.
|
||||
(t/is (= :fill (ptok/token-attr-plugin->token-attr "fill")))
|
||||
@ -150,6 +167,57 @@
|
||||
(done)))
|
||||
0))))
|
||||
|
||||
(t/deftest shape-apply-token-accepts-font-families
|
||||
(t/async
|
||||
done
|
||||
(let [set-id (cthi/new-id! :token-set)
|
||||
token-id (cthi/new-id! :font-family-token)
|
||||
file (-> (cthf/sample-file :file1 :page-label :page1)
|
||||
(ctho/add-text :text1 "Hello World!")
|
||||
(ctht/add-tokens-lib)
|
||||
(ctht/update-tokens-lib
|
||||
#(-> %
|
||||
(ctob/add-set
|
||||
(ctob/make-token-set :id set-id
|
||||
:name "fonts"))
|
||||
(ctob/add-theme
|
||||
(ctob/make-token-theme :name "theme"
|
||||
:sets #{"fonts"}))
|
||||
(ctob/set-active-themes #{"/theme"})
|
||||
(ctob/add-token
|
||||
set-id
|
||||
(ctob/make-token :id token-id
|
||||
:name "font.primary"
|
||||
:type :font-family
|
||||
:value ["Inter"])))))
|
||||
store (ths/setup-store file)
|
||||
_ (set! st/state store)
|
||||
_ (set! st/stream (ptk/input-stream store))
|
||||
^js context (api/create-context "00000000-0000-0000-0000-000000000000")
|
||||
^js page (.-currentPage context)
|
||||
^js shape (.getShapeById page (str (cthi/id :text1)))
|
||||
^js library (.-library context)
|
||||
^js local (.-local library)
|
||||
^js catalog (.-tokens local)
|
||||
^js token-set (.getSetById catalog (str set-id))
|
||||
^js token (.getTokenById token-set (str token-id))]
|
||||
(.applyToken shape token #js ["fontFamilies"])
|
||||
(js/setTimeout
|
||||
(fn []
|
||||
(let [shape-id (cthi/id :text1)
|
||||
page-id (cthf/current-page-id file)]
|
||||
;; Plugin readback exposes the documented plural key.
|
||||
(t/is (= "font.primary" (.. shape -tokens -fontFamilies)))
|
||||
;; The undocumented singular spelling must not leak.
|
||||
(t/is (undefined? (.. shape -tokens -fontFamily)))
|
||||
;; Internal state keeps the canonical `:font-family` key.
|
||||
(t/is (= "font.primary"
|
||||
(get-in @store
|
||||
[:files (:id file) :data :pages-index page-id
|
||||
:objects shape-id :applied-tokens :font-family])))
|
||||
(done)))
|
||||
0))))
|
||||
|
||||
(t/deftest token-attr?-rejects-unknown-input
|
||||
(t/is (false? (boolean (ptok/token-attr? :not-a-real-attr))))
|
||||
(t/is (false? (boolean (ptok/token-attr? "not-a-real-attr"))))
|
||||
|
||||
@ -11,6 +11,7 @@
|
||||
- **plugins-runtime**: `Library.createComponent()` now rejects invalid input (an empty shape list, or a shape inside a component copy) with a validation error instead of returning a component proxy pointing at nothing.
|
||||
- **plugins-runtime**: Setting an individual padding/margin side (`leftPadding`, `topMargin`, …) now re-derives the padding/margin type, switching to `multiple` when the four sides stop being symmetric (so the value is actually painted) and back to `simple` once top/bottom and left/right are mirrored again.
|
||||
- **plugins-runtime**: Removed the premature deep-hardening of the host plugin context, which froze shared host functions (including `Function.prototype`) before SES override taming, causing `TypeError: Cannot assign to read only property 'toString'` on later host-side function extension. Related to #11001.
|
||||
- **plugins-runtime**: Fixed the `fontFamilies` token property mapping so `Shape.applyToken(token, ["fontFamilies"])` resolves to the canonical `:font-family` attribute and applied-token readback exposes the documented `fontFamilies` key instead of the undocumented singular `fontFamily`. Closes #11405.
|
||||
|
||||
## 1.5.0 (2026-07-08)
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user