0
Fork 0
mirror of https://github.com/penpot/penpot.git synced 2025-01-10 00:40:30 -05:00

🐛 Add validator and repair for duplicated slots on deleted components

This commit is contained in:
Pablo Alba 2024-06-17 14:46:37 +02:00 committed by Andrés Moya
parent 4546e98dc6
commit 4e6c1857dd
2 changed files with 56 additions and 10 deletions

View file

@ -496,6 +496,36 @@
(pcb/with-file-data file-data) (pcb/with-file-data file-data)
(pcb/update-shapes (map :id child-with-duplicate) repair-shape)))) (pcb/update-shapes (map :id child-with-duplicate) repair-shape))))
(defmethod repair-error :component-duplicate-slot
[_ {:keys [shape] :as error} file-data _]
(let [main-shape (get-in shape [:objects (:main-instance-id shape)])
childs (map #(get (:objects shape) %) (:shapes main-shape))
childs-with-duplicate (let [result (reduce (fn [[seen duplicates] item]
(let [swap-slot (ctk/get-swap-slot item)]
(if (contains? seen swap-slot)
[seen (conj duplicates item)]
[(conj seen swap-slot) duplicates])))
[#{} []]
childs)]
(second result))
duplicated-ids (set (mapv :id childs-with-duplicate))
repair-component
(fn [component]
(let [objects (reduce-kv (fn [acc k v]
(if (contains? duplicated-ids k)
(assoc acc k (ctk/remove-swap-slot v))
(assoc acc k v)))
{}
(:objects component))]
(assoc component :objects objects)))]
(log/dbg :hint "repairing component :component-duplicated-slot" :id (:id shape) :name (:name shape))
(-> (pcb/empty-changes nil)
(pcb/with-library-data file-data)
(pcb/update-component (:id shape) repair-component))))
(defmethod repair-error :missing-slot (defmethod repair-error :missing-slot
[_ {:keys [shape page-id args] :as error} file-data _] [_ {:keys [shape page-id args] :as error} file-data _]
(let [repair-shape (let [repair-shape

View file

@ -31,6 +31,7 @@
:child-not-found :child-not-found
:frame-not-found :frame-not-found
:invalid-frame :invalid-frame
:component-duplicate-slot
:component-not-main :component-not-main
:component-main-external :component-main-external
:component-not-found :component-not-found
@ -65,7 +66,7 @@
[:shape {:optional true} :map] ; Cannot validate a shape because here it may be broken [:shape {:optional true} :map] ; Cannot validate a shape because here it may be broken
[:shape-id {:optional true} ::sm/uuid] [:shape-id {:optional true} ::sm/uuid]
[:file-id ::sm/uuid] [:file-id ::sm/uuid]
[:page-id ::sm/uuid]])) [:page-id {:optional true} [:maybe ::sm/uuid]]]))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ERROR HANDLING ;; ERROR HANDLING
@ -297,17 +298,21 @@
"This shape should not have swap slot" "This shape should not have swap slot"
shape file page))) shape file page)))
(defn- check-duplicate-swap-slot (defn- has-duplicate-swap-slot?
"Validate that the children of this shape does not have duplicated slots." [shape container]
[shape file page] (let [shapes (map #(get (:objects container) %) (:shapes shape))
(let [shapes (map #(get (:objects page) %) (:shapes shape))
slots (->> (map #(ctk/get-swap-slot %) shapes) slots (->> (map #(ctk/get-swap-slot %) shapes)
(remove nil?)) (remove nil?))
counts (frequencies slots)] counts (frequencies slots)]
(when (some (fn [[_ count]] (> count 1)) counts) (some (fn [[_ count]] (> count 1)) counts)))
(report-error :duplicate-slot
"This shape has children with the same swap slot" (defn- check-duplicate-swap-slot
shape file page)))) "Validate that the children of this shape does not have duplicated slots."
[shape file page]
(when (has-duplicate-swap-slot? shape page)
(report-error :duplicate-slot
"This shape has children with the same swap slot"
shape file page)))
(defn- check-shape-main-root-top (defn- check-shape-main-root-top
"Root shape of a top main instance: "Root shape of a top main instance:
@ -468,13 +473,24 @@
shape file page) shape file page)
(check-shape-not-component shape file page libraries)))))))) (check-shape-not-component shape file page libraries))))))))
(defn check-component-duplicate-swap-slot
[component file]
(let [shape (get-in component [:objects (:main-instance-id component)])]
(when (has-duplicate-swap-slot? shape component)
(report-error :component-duplicate-slot
"This deleted component has children with the same swap slot"
component file nil))))
(defn- check-component (defn- check-component
"Validate semantic coherence of a component. Report all errors found." "Validate semantic coherence of a component. Report all errors found."
[component file] [component file]
(when (and (contains? component :objects) (nil? (:objects component))) (when (and (contains? component :objects) (nil? (:objects component)))
(report-error :component-nil-objects-not-allowed (report-error :component-nil-objects-not-allowed
"Objects list cannot be nil" "Objects list cannot be nil"
component file nil))) component file nil))
(when (:deleted component)
(check-component-duplicate-swap-slot component file)))
(defn- get-orphan-shapes (defn- get-orphan-shapes
[{:keys [objects] :as page}] [{:keys [objects] :as page}]