🐛 Restrict shadow colors to plain colors only

Previously, shadows used a general-purpose color schema that allowed
to have gradients and images on the data structure. This commit fixes
that using a specific schema for shadow colors that only allows plain
colors.

A migration is added to clean up existing shadows with non-plain
colors.
This commit is contained in:
Andrey Antukh 2025-11-06 14:40:56 +01:00
parent 097897d8da
commit e979476b0e
4 changed files with 69 additions and 39 deletions

View File

@ -76,6 +76,7 @@
- Fix options button does not work for comments created in the lower part of the screen [Taiga #12422](https://tree.taiga.io/project/penpot/issue/12422)
- Fix problem when checking usage with removed teams [Taiga #12442](https://tree.taiga.io/project/penpot/issue/12442)
- Fix focus mode persisting across page/file navigation [Taiga #12469](https://tree.taiga.io/project/penpot/issue/12469)
- Fix shadow color validation [Github #7705](https://github.com/penpot/penpot/pull/7705)
## 2.10.1

View File

@ -1357,38 +1357,6 @@
(update :pages-index d/update-vals update-container)
(d/update-when :components d/update-vals update-container))))
(defmethod migrate-data "0004-clean-shadow-color"
[data _]
(let [decode-color (sm/decoder types.color/schema:color sm/json-transformer)
clean-shadow-color
(fn [color]
(let [ref-id (get color :id)
ref-file (get color :file-id)]
(-> (d/without-qualified color)
(select-keys [:opacity :color :gradient :image :ref-id :ref-file])
(cond-> ref-id
(assoc :ref-id ref-id))
(cond-> ref-file
(assoc :ref-file ref-file))
(decode-color))))
clean-shadow
(fn [shadow]
(update shadow :color clean-shadow-color))
update-object
(fn [object]
(d/update-when object :shadow #(mapv clean-shadow %)))
update-container
(fn [container]
(d/update-when container :objects d/update-vals update-object))]
(-> data
(update :pages-index d/update-vals update-container)
(d/update-when :components d/update-vals update-container))))
(defmethod migrate-data "0005-deprecate-image-type"
[data _]
(letfn [(update-object [object]
@ -1630,6 +1598,45 @@
;; as value; this migration fixes it.
(d/update-when data :components d/update-vals d/without-nils))
(defmethod migrate-data "0015-clean-shadow-color"
[data _]
(let [decode-shadow-color
(sm/decoder ctss/schema:color sm/json-transformer)
clean-shadow-color
(fn [color]
(let [ref-id (get color :id)
ref-file (get color :file-id)]
(-> (d/without-qualified color)
(select-keys ctss/color-attrs)
(cond-> ref-id
(assoc :ref-id ref-id))
(cond-> ref-file
(assoc :ref-file ref-file))
(decode-shadow-color)
(d/without-nils))))
clean-shadow
(fn [shadow]
(update shadow :color clean-shadow-color))
clean-xform
(comp
(keep clean-shadow)
(filter ctss/valid-shadow?))
update-object
(fn [object]
(d/update-when object :shadow #(into [] clean-xform %)))
update-container
(fn [container]
(d/update-when container :objects d/update-vals update-object))]
(-> data
(update :pages-index d/update-vals update-container)
(d/update-when :components d/update-vals update-container))))
(def available-migrations
(into (d/ordered-set)
["legacy-2"
@ -1689,7 +1696,6 @@
"0002-clean-shape-interactions"
"0003-fix-root-shape"
"0003-convert-path-content-v2"
"0004-clean-shadow-color"
"0005-deprecate-image-type"
"0006-fix-old-texts-fills"
"0008-fix-library-colors-v4"
@ -1701,4 +1707,5 @@
"0013-fix-component-path"
"0013-clear-invalid-strokes-and-fills"
"0014-fix-tokens-lib-duplicate-ids"
"0014-clear-components-nil-objects"]))
"0014-clear-components-nil-objects"
"0015-clean-shadow-color"]))

View File

@ -36,7 +36,7 @@
(defn type
[s]
(m/-type s))
(m/type s default-options))
(defn properties
[s]
@ -46,6 +46,10 @@
[s]
(m/type-properties s))
(defn children
[s]
(m/children s default-options))
(defn schema
[s]
(if (schema? s)
@ -127,9 +131,19 @@
(defn keys
"Given a map schema, return all keys as set"
[schema]
(->> (entries schema)
(into #{} xf:map-key)))
[schema']
(let [schema' (m/schema schema' default-options)]
(case (m/type schema')
:map
(->> (entries schema')
(into #{} xf:map-key))
:merge
(->> (m/children schema')
(mapcat m/entries)
(into #{} xf:map-key))
(throw (ex-info "not supported schema type" {:type (m/type schema')})))))
(defn update-properties
[s f & args]

View File

@ -11,6 +11,14 @@
(def styles #{:drop-shadow :inner-shadow})
(def schema:color
[:merge {:title "ShadowColor"}
ctc/schema:color-attrs
ctc/schema:plain-color])
(def color-attrs
(sm/keys schema:color))
(def schema:shadow
[:map {:title "Shadow"}
[:id [:maybe ::sm/uuid]]
@ -20,7 +28,7 @@
[:blur ::sm/safe-number]
[:spread ::sm/safe-number]
[:hidden :boolean]
[:color ctc/schema:color]])
[:color schema:color]])
(def check-shadow
(sm/check-fn schema:shadow))