mirror of
https://github.com/penpot/penpot.git
synced 2026-03-19 17:03:44 +00:00
wip
This commit is contained in:
@@ -6,8 +6,26 @@
|
||||
|
||||
(ns app.common.files.comp-processors
|
||||
(:require
|
||||
[app.common.types.component :as ctk]
|
||||
[app.common.types.file :as ctf]))
|
||||
|
||||
(defn fix-missing-swap-slots
|
||||
[file]
|
||||
file)
|
||||
(defn fix-missing-swap-slots
|
||||
[file libraries]
|
||||
(ctf/update-all-shapes
|
||||
file
|
||||
(fn [shape]
|
||||
(if (and (ctk/instance-head? shape) (ctk/in-component-copy? shape))
|
||||
(let [{:keys [container]}
|
||||
(meta shape)
|
||||
|
||||
ref-shape
|
||||
(ctf/find-ref-shape file container libraries shape :include-deleted? true :with-context? true)]
|
||||
(println "comparing" (:name shape) "with ref" (some-> ref-shape :name))
|
||||
(if ref-shape
|
||||
(if (and (not= (:shape-ref shape) (:id ref-shape))
|
||||
(nil? (ctk/get-swap-slot shape)))
|
||||
(let [updated-shape (ctk/set-swap-slot shape (:id ref-shape))]
|
||||
{:result :update :updated-shape updated-shape})
|
||||
{:result :keep})
|
||||
{:result :keep}))
|
||||
{:result :keep}))))
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
[app.common.types.components-list :as ctkl]
|
||||
[app.common.types.pages-list :as ctpl]
|
||||
[app.common.types.plugins :refer [schema:plugin-data]]
|
||||
[app.common.types.shape :as cts]
|
||||
[app.common.types.shape-tree :as ctst]
|
||||
[app.common.types.shape.layout :as ctl]
|
||||
[app.common.types.text :as cttx]
|
||||
@@ -55,6 +56,10 @@
|
||||
[page-or-component type]
|
||||
(assoc page-or-component :type type))
|
||||
|
||||
(defn unmake-container
|
||||
[container]
|
||||
(dissoc container :type))
|
||||
|
||||
(defn page?
|
||||
[container]
|
||||
(= (:type container) :page))
|
||||
|
||||
@@ -225,6 +225,86 @@
|
||||
(ctpl/update-page file-data (:id container) f)
|
||||
(ctkl/update-component file-data (:id container) f)))
|
||||
|
||||
(defn update-pages
|
||||
"Update all pages inside the file"
|
||||
[file-data f]
|
||||
(update file-data :pages-index d/update-vals
|
||||
(fn [page]
|
||||
(-> page
|
||||
(ctn/make-container :page)
|
||||
(f)
|
||||
(ctn/unmake-container)))))
|
||||
|
||||
(defn update-components
|
||||
"Update all components inside the file"
|
||||
[file-data f]
|
||||
(d/update-when file-data :components d/update-vals
|
||||
(fn [component]
|
||||
(-> component
|
||||
(ctn/make-container :component)
|
||||
(f)
|
||||
(ctn/unmake-container)))))
|
||||
|
||||
(defn update-containers
|
||||
"Update all pages and components inside the file"
|
||||
[file-data f]
|
||||
(-> file-data
|
||||
(update-pages f)
|
||||
(update-components f)))
|
||||
|
||||
(defn update-objects-tree
|
||||
"Do a depth-first traversal of the shapes in a container, doing different kinds of updates.
|
||||
The function f receives a shape with a context metadata with the container.
|
||||
It must return a map with the following keys:
|
||||
- :result -> :keep, :update or :remove
|
||||
- :updated-shape -> the updated shape if result is :update"
|
||||
[container f]
|
||||
(letfn [(update-shape-recursive
|
||||
[container shape-id]
|
||||
(let [shape (ctst/get-shape container shape-id)]
|
||||
(when (not shape)
|
||||
(throw (ex-info "Shape not found" {:shape-id shape-id})))
|
||||
(let [shape (with-meta shape {:container container})
|
||||
|
||||
{:keys [result updated-shape]} (f shape)
|
||||
|
||||
container'
|
||||
(case result
|
||||
:keep
|
||||
container
|
||||
|
||||
:update
|
||||
(ctst/set-shape container updated-shape)
|
||||
|
||||
:remove
|
||||
(ctst/delete-shape container shape-id true)
|
||||
|
||||
:else
|
||||
(throw (ex-info "Invalid result from update function" {:result result})))]
|
||||
|
||||
(reduce update-shape-recursive
|
||||
container'
|
||||
(:shapes shape)))))]
|
||||
|
||||
(let [root-id (if (ctn/page? container)
|
||||
uuid/zero
|
||||
(:main-instance-id container))]
|
||||
|
||||
(if (:objects container)
|
||||
(update-shape-recursive container root-id)
|
||||
container))))
|
||||
|
||||
(defn update-all-shapes
|
||||
"Update all shapes in the file, using the update-objects-tree function for each container"
|
||||
[file f]
|
||||
(update-file-data
|
||||
file
|
||||
(fn [file-data]
|
||||
(update-containers
|
||||
file-data
|
||||
(fn [container]
|
||||
(update-objects-tree container f))))))
|
||||
|
||||
;; Asset helpers
|
||||
(defn find-component-file
|
||||
[file libraries component-file]
|
||||
|
||||
@@ -6,47 +6,118 @@
|
||||
|
||||
(ns common-tests.files.comp-processors-test
|
||||
(:require
|
||||
[app.common.files.comp-processors :as cfcp]
|
||||
;; [app.common.test-helpers.components :as thc]
|
||||
[app.common.data :as d]
|
||||
[app.common.files.comp-processors :as cfcp]
|
||||
[app.common.test-helpers.components :as thc]
|
||||
[app.common.test-helpers.compositions :as tho]
|
||||
[app.common.test-helpers.files :as thf]
|
||||
;; [app.common.test-helpers.ids-map :as thi]
|
||||
;; [app.common.test-helpers.shapes :as ths]
|
||||
[app.common.test-helpers.ids-map :as thi]
|
||||
[app.common.test-helpers.shapes :as ths]
|
||||
[app.common.types.component :as ctk]
|
||||
[clojure.test :as t]))
|
||||
|
||||
(t/deftest test-fix-missing-swap-slots
|
||||
|
||||
(t/testing "empty file should not need any action"
|
||||
(let [file (thf/sample-file :file1)]
|
||||
(t/is (= file (cfcp/fix-missing-swap-slots file)))))
|
||||
(let [file (thf/sample-file :file1)
|
||||
file' (cfcp/fix-missing-swap-slots file {})]
|
||||
(t/is (empty? (d/map-diff file file')))))
|
||||
|
||||
(t/testing "file without components should not need any action"
|
||||
(let [file
|
||||
;; :frame1 [:name Frame1]
|
||||
;; :child1 [:name Rect1]
|
||||
(-> (thf/sample-file :file1)
|
||||
(tho/add-frame-with-child :frame1 :shape1))]
|
||||
(tho/add-frame-with-child :frame1 :shape1))
|
||||
|
||||
(t/is (= file (cfcp/fix-missing-swap-slots file)))))
|
||||
|
||||
(t/testing "file with not swapped components should not need any action"
|
||||
file' (cfcp/fix-missing-swap-slots file {})]
|
||||
|
||||
(t/is (empty? (d/map-diff file file')))))
|
||||
|
||||
(t/testing "file with nested not swapped components should not need any action"
|
||||
(let [file
|
||||
;; {:main1-root} [:name Frame1] # [Component :component1]
|
||||
;; :main1-child [:name Rect1]
|
||||
;;
|
||||
;; {:main2-root} [:name Frame2] # [Component :component2]
|
||||
;; :nested-head [:name Frame1] @--> [Component :component1] :main1-root
|
||||
;; <no-label> [:name Rect1] ---> :main1-child
|
||||
;;
|
||||
;; :copy2 [:name Frame2] #--> [Component :component2] :main2-root
|
||||
;; <no-label> [:name Frame1] @--> [Component :component1] :nested-head
|
||||
;; <no-label> [:name Rect1] ---> <no-label>
|
||||
;; {:main1-root} [:name Frame1] # [Component :component1]
|
||||
;; :main1-child [:name Rect1]
|
||||
;;
|
||||
;; {:main2-root} [:name Frame2] # [Component :component2]
|
||||
;; :nested-head [:name Frame1] @--> [Component :component1] :main1-root
|
||||
;; <no-label> [:name Rect1] ---> :main1-child
|
||||
;;
|
||||
;; :copy2 [:name Frame2] #--> [Component :component2] :main2-root
|
||||
;; <no-label> [:name Frame1] @--> [Component :component1] :nested-head
|
||||
;; <no-label> [:name Rect1] ---> <no-label>
|
||||
(-> (thf/sample-file :file1)
|
||||
(tho/add-nested-component-with-copy :component1 :main1-root :main1-child
|
||||
:component2 :main2-root :nested-head
|
||||
:copy2 :copy2-root))]
|
||||
:copy2 :copy2-root))
|
||||
|
||||
(t/is (= file (cfcp/fix-missing-swap-slots file)))))
|
||||
|
||||
|
||||
)
|
||||
file' (cfcp/fix-missing-swap-slots file {})]
|
||||
|
||||
(t/is (empty? (d/map-diff file file')))))
|
||||
|
||||
(t/testing "file with a normally swapped copy should not need any action"
|
||||
(let [file
|
||||
;; {:main1-root} [:name Frame1] # [Component :component1]
|
||||
;; :main1-child [:name Rect1]
|
||||
;;
|
||||
;; {:main2-root} [:name Frame2] # [Component :component2]
|
||||
;; :nested-head [:name Frame1] @--> [Component :component1] :main1-root
|
||||
;; <no-label> [:name Rect1] ---> :main1-child
|
||||
;;
|
||||
;; {:main3-root} [:name Frame3] # [Component :component3]
|
||||
;; :main3-child [:name Rect3]
|
||||
;;
|
||||
;; :copy2 [:name Frame2] #--> [Component :component2] :main2-root
|
||||
;; :copy2-nested-head [:name Frame3] @--> [Component :component3] :main3-root
|
||||
;; {swap-slot :nested-head}
|
||||
;; <no-label> [:name Rect3] ---> :main3-child
|
||||
(-> (thf/sample-file :file1)
|
||||
(tho/add-nested-component :component1 :main1-root :main1-child
|
||||
:component2 :main2-root :nested-head)
|
||||
(thc/instantiate-component :component2 :copy2 :children-labels [:copy2-nested-head])
|
||||
(tho/add-simple-component :component3 :main3-root :main3-child
|
||||
:root-params {:name "Frame3"}
|
||||
:child-params {:name "Rect3"})
|
||||
(tho/swap-component-in-first-child :copy2 :component3))
|
||||
|
||||
file' (cfcp/fix-missing-swap-slots file {})]
|
||||
|
||||
(t/is (empty? (d/map-diff file file')))))
|
||||
|
||||
(t/testing "file with a swapped copy with broken slot should have it repaired"
|
||||
(println "==start test==================================================")
|
||||
(let [file
|
||||
;; {:main1-root} [:name Frame1] # [Component :component1]
|
||||
;; :main1-child [:name Rect1]
|
||||
;;
|
||||
;; {:main2-root} [:name Frame2] # [Component :component2]
|
||||
;; :nested-head [:name Frame1] @--> [Component :component1] :main1-root
|
||||
;; <no-label> [:name Rect1] ---> :main1-child
|
||||
;;
|
||||
;; {:main3-root} [:name Frame3] # [Component :component3]
|
||||
;; :main3-child [:name Rect3]
|
||||
;;
|
||||
;; :copy2 [:name Frame2] #--> [Component :component2] :main2-root
|
||||
;; :copy2-nested-head [:name Frame3] @--> [Component :component3] :main3-root
|
||||
;; NO SWAP SLOT
|
||||
;; <no-label> [:name Rect3] ---> :main3-child
|
||||
(-> (thf/sample-file :file1)
|
||||
(tho/add-nested-component :component1 :main1-root :main1-child
|
||||
:component2 :main2-root :nested-head)
|
||||
(thc/instantiate-component :component2 :copy2 :children-labels [:copy2-nested-head])
|
||||
(tho/add-simple-component :component3 :main3-root :main3-child
|
||||
:root-params {:name "Frame3"}
|
||||
:child-params {:name "Rect3"})
|
||||
(tho/swap-component-in-first-child :copy2 :component3)
|
||||
(ths/update-shape :copy2-nested-head :touched nil))
|
||||
|
||||
file' (cfcp/fix-missing-swap-slots file {})
|
||||
|
||||
diff (d/map-diff file file')
|
||||
|
||||
copy2-nested-head' (ths/get-shape file' :copy2-nested-head)]
|
||||
|
||||
(thf/dump-file file :keys [:name :swap-slot-label] :show-refs? true)
|
||||
(println "====================================================")
|
||||
(prn "diff" diff)
|
||||
(t/is (= (ctk/get-swap-slot copy2-nested-head') (thi/id :nested-head))))))
|
||||
|
||||
Reference in New Issue
Block a user