diff --git a/CHANGES.md b/CHANGES.md index 963a6f5d85..51a4f5f319 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -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 diff --git a/backend/test/backend_tests/helpers.clj b/backend/test/backend_tests/helpers.clj index d504e05aa8..20f83ce455 100644 --- a/backend/test/backend_tests/helpers.clj +++ b/backend/test/backend_tests/helpers.clj @@ -549,6 +549,44 @@ (io/copy r sw) (.toString sw)))) +(defn parse-sse + [content] + (let [state + (reduce (fn [{:keys [events data event id] :as state} line] + (cond + ;; empty line → dispatch event if we have data + (str/blank? line) + (if (seq data) + (-> state + (update :events conj {:event (or event "message") + :data (-> (str/join "\n" data))}) + (assoc :data [] :event nil)) + state) + + ;; comment line (starts with :) + (str/starts-with? line ":") + state + + :else + (let [[field raw-value] (str/split line #":" 2) + value (some-> raw-value (str/replace #"^ " ""))] + (case field + "data" (update state :data conj (or value "")) + "event" (assoc state :event value) + ;; ignore retry and unknown fields + state)))) + {:events [] :data [] :event nil} + (str/split content #"\r?\n")) + + ;; handle unterminated last event (no trailing blank line) + state (if (seq (:data state)) + (update state :events conj + {:event (or (:event state) "message") + :data (str/join "\n" (:data state))}) + state)] + + (:events state))) + (defn consume-sse [callback] (let [{:keys [::yres/status ::yres/body ::yres/headers] :as response} (callback {}) @@ -558,12 +596,9 @@ (try (px/exec! :virtual #(rcp/write-body-to-stream body nil output)) (into [] - (map (fn [event] - (let [[item1 item2] (re-seq #"(.*): (.*)\n?" event)] - - [(keyword (nth item1 2)) - (tr/decode-str (nth item2 2))]))) - (-> (slurp' input) - (str/split "\n\n"))) + (map (fn [{:keys [event data]}] + [(keyword event) + (tr/decode-str data)])) + (parse-sse (slurp' input))) (finally (.close input))))) diff --git a/common/src/app/common/files/migrations.cljc b/common/src/app/common/files/migrations.cljc index 87c9c90da5..958fdbcc27 100644 --- a/common/src/app/common/files/migrations.cljc +++ b/common/src/app/common/files/migrations.cljc @@ -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"])) diff --git a/common/src/app/common/schema.cljc b/common/src/app/common/schema.cljc index c2523c8149..cd96d5faa9 100644 --- a/common/src/app/common/schema.cljc +++ b/common/src/app/common/schema.cljc @@ -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] diff --git a/common/src/app/common/types/shape/shadow.cljc b/common/src/app/common/types/shape/shadow.cljc index 32545336cd..c4ae1a5610 100644 --- a/common/src/app/common/types/shape/shadow.cljc +++ b/common/src/app/common/types/shape/shadow.cljc @@ -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))