mirror of
https://github.com/penpot/penpot.git
synced 2025-03-09 22:31:50 -05:00
Merge pull request #5641 from penpot/palba-fix-shape-ref-cycle
🐛 Fix shape-ref cycles
This commit is contained in:
commit
85d3a052c9
3 changed files with 67 additions and 20 deletions
|
@ -320,6 +320,35 @@
|
||||||
(pcb/with-file-data file-data)
|
(pcb/with-file-data file-data)
|
||||||
(pcb/update-shapes shape-ids detach-shape))))))
|
(pcb/update-shapes shape-ids detach-shape))))))
|
||||||
|
|
||||||
|
|
||||||
|
(defmethod repair-error :shape-ref-cycle
|
||||||
|
[_ {:keys [shape args] :as error} file-data _]
|
||||||
|
(let [repair-component
|
||||||
|
(fn [component]
|
||||||
|
(let [objects (:objects component) ;; we only have encounter this on deleted components,
|
||||||
|
;; so the relevant objects are inside the component
|
||||||
|
to-detach (->> (:cycles-ids args)
|
||||||
|
(map #(get objects %))
|
||||||
|
(map #(ctn/get-head-shape objects %))
|
||||||
|
(map :id)
|
||||||
|
distinct
|
||||||
|
(mapcat #(ctn/get-children-in-instance objects %))
|
||||||
|
(map :id)
|
||||||
|
set)]
|
||||||
|
|
||||||
|
(update component :objects
|
||||||
|
(fn [objects]
|
||||||
|
(reduce-kv (fn [acc k v]
|
||||||
|
(if (contains? to-detach k)
|
||||||
|
(assoc acc k (ctk/detach-shape v))
|
||||||
|
(assoc acc k v)))
|
||||||
|
{}
|
||||||
|
objects)))))]
|
||||||
|
(log/dbg :hint "repairing component :shape-ref-cycle" :id (:id shape) :name (:name shape))
|
||||||
|
(-> (pcb/empty-changes nil nil)
|
||||||
|
(pcb/with-library-data file-data)
|
||||||
|
(pcb/update-component (:id shape) repair-component))))
|
||||||
|
|
||||||
(defmethod repair-error :shape-ref-in-main
|
(defmethod repair-error :shape-ref-in-main
|
||||||
[_ {:keys [shape page-id] :as error} file-data _]
|
[_ {:keys [shape page-id] :as error} file-data _]
|
||||||
(let [repair-shape
|
(let [repair-shape
|
||||||
|
|
|
@ -55,7 +55,8 @@
|
||||||
:component-nil-objects-not-allowed
|
:component-nil-objects-not-allowed
|
||||||
:instance-head-not-frame
|
:instance-head-not-frame
|
||||||
:misplaced-slot
|
:misplaced-slot
|
||||||
:missing-slot})
|
:missing-slot
|
||||||
|
:shape-ref-cycle})
|
||||||
|
|
||||||
(def ^:private schema:error
|
(def ^:private schema:error
|
||||||
[:map {:title "ValidationError"}
|
[:map {:title "ValidationError"}
|
||||||
|
@ -482,6 +483,18 @@
|
||||||
"This deleted component has children with the same swap slot"
|
"This deleted component has children with the same swap slot"
|
||||||
component file nil))))
|
component file nil))))
|
||||||
|
|
||||||
|
(defn check-ref-cycles
|
||||||
|
[component file]
|
||||||
|
(let [cycles-ids (->> component
|
||||||
|
:objects
|
||||||
|
vals
|
||||||
|
(filter #(= (:id %) (:shape-ref %)))
|
||||||
|
(map :id))]
|
||||||
|
|
||||||
|
(when (seq cycles-ids)
|
||||||
|
(report-error :shape-ref-cycle
|
||||||
|
"This deleted component has shapes with shape-ref pointing to self"
|
||||||
|
component file nil :cycles-ids cycles-ids))))
|
||||||
|
|
||||||
(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."
|
||||||
|
@ -491,7 +504,8 @@
|
||||||
"Objects list cannot be nil"
|
"Objects list cannot be nil"
|
||||||
component file nil))
|
component file nil))
|
||||||
(when (:deleted component)
|
(when (:deleted component)
|
||||||
(check-component-duplicate-swap-slot component file)))
|
(check-component-duplicate-swap-slot component file)
|
||||||
|
(check-ref-cycles component file)))
|
||||||
|
|
||||||
(defn- get-orphan-shapes
|
(defn- get-orphan-shapes
|
||||||
[{:keys [objects] :as page}]
|
[{:keys [objects] :as page}]
|
||||||
|
|
|
@ -348,24 +348,28 @@
|
||||||
(true? (= (:id component) (:id ref-component)))))
|
(true? (= (:id component) (:id ref-component)))))
|
||||||
|
|
||||||
(defn find-swap-slot
|
(defn find-swap-slot
|
||||||
[shape container file libraries]
|
([shape container file libraries]
|
||||||
(if-let [swap-slot (ctk/get-swap-slot shape)]
|
(find-swap-slot shape container file libraries #{}))
|
||||||
swap-slot
|
([shape container file libraries viewed-ids]
|
||||||
(let [ref-shape (find-ref-shape file
|
(if (contains? viewed-ids (:id shape)) ;; prevent cycles
|
||||||
container
|
nil
|
||||||
libraries
|
(if-let [swap-slot (ctk/get-swap-slot shape)]
|
||||||
shape
|
swap-slot
|
||||||
:include-deleted? true
|
(let [ref-shape (find-ref-shape file
|
||||||
:with-context? true)
|
container
|
||||||
shape-meta (meta ref-shape)
|
libraries
|
||||||
ref-file (:file shape-meta)
|
shape
|
||||||
ref-container (:container shape-meta)]
|
:include-deleted? true
|
||||||
(when ref-shape
|
:with-context? true)
|
||||||
(if-let [swap-slot (ctk/get-swap-slot ref-shape)]
|
shape-meta (meta ref-shape)
|
||||||
swap-slot
|
ref-file (:file shape-meta)
|
||||||
(if (ctk/main-instance? ref-shape)
|
ref-container (:container shape-meta)]
|
||||||
(:id shape)
|
(when ref-shape
|
||||||
(find-swap-slot ref-shape ref-container ref-file libraries)))))))
|
(if-let [swap-slot (ctk/get-swap-slot ref-shape)]
|
||||||
|
swap-slot
|
||||||
|
(if (ctk/main-instance? ref-shape)
|
||||||
|
(:id shape)
|
||||||
|
(find-swap-slot ref-shape ref-container ref-file libraries (conj viewed-ids (:id shape)))))))))))
|
||||||
|
|
||||||
(defn match-swap-slot?
|
(defn match-swap-slot?
|
||||||
[shape-main shape-inst container-inst container-main file libraries]
|
[shape-main shape-inst container-inst container-main file libraries]
|
||||||
|
|
Loading…
Add table
Reference in a new issue