mirror of
https://github.com/penpot/penpot.git
synced 2026-08-25 22:29:03 +00:00
✨ Project nested shapes recursively into the graph
This commit is contained in:
parent
50c648e940
commit
b623ab0e17
@ -7,13 +7,14 @@
|
|||||||
(ns app.graph.project.document
|
(ns app.graph.project.document
|
||||||
"Project a Penpot file-data map into Ladybug nodes and structural edges.
|
"Project a Penpot file-data map into Ladybug nodes and structural edges.
|
||||||
|
|
||||||
Vertical slice: Document, Page, top-level shapes, and `IsChildOf` edges
|
Projects Document, Page, the full shape tree (skipping the root frame),
|
||||||
mirroring beadpot's `add_document` first pass."
|
and `IsChildOf` edges from shapes to their page or container parent."
|
||||||
(:require
|
(:require
|
||||||
[app.common.logging :as l]
|
[app.common.logging :as l]
|
||||||
[app.common.uuid :as uuid]
|
[app.common.uuid :as uuid]
|
||||||
[app.graph.ladybug :as ladybug]
|
[app.graph.ladybug :as ladybug]
|
||||||
[app.graph.project.specs :as specs]
|
[app.graph.project.specs :as specs]
|
||||||
|
[app.graph.schema :as graph.schema]
|
||||||
[clojure.string :as str]))
|
[clojure.string :as str]))
|
||||||
|
|
||||||
(def root-frame-id
|
(def root-frame-id
|
||||||
@ -65,37 +66,69 @@
|
|||||||
[shape]
|
[shape]
|
||||||
(get shape-type->table (keyword (:type shape))))
|
(get shape-type->table (keyword (:type shape))))
|
||||||
|
|
||||||
|
(defn- shape-node-attrs
|
||||||
|
[shape]
|
||||||
|
{:id (:id shape)
|
||||||
|
:name (:name shape)})
|
||||||
|
|
||||||
|
(defn- container-table?
|
||||||
|
[table]
|
||||||
|
(contains? graph.schema/container-node-tables table))
|
||||||
|
|
||||||
|
(defn- child-shape-ids
|
||||||
|
"Child ids in Penpot z-order (reversed from the stored :shapes list)."
|
||||||
|
[parent]
|
||||||
|
(when-let [shapes (:shapes parent)]
|
||||||
|
(vec (reverse shapes))))
|
||||||
|
|
||||||
|
(declare project-shape-ids)
|
||||||
|
|
||||||
|
(defn- project-shape
|
||||||
|
"Project one shape node and recurse into its children."
|
||||||
|
[objects statements stats table shape parent-table parent-id position]
|
||||||
|
(let [shape-id (:id shape)
|
||||||
|
statements' (conj statements
|
||||||
|
(validated-node-statement specs/check-shape-node table
|
||||||
|
(shape-node-attrs shape))
|
||||||
|
(merge-edge-statement table shape-id
|
||||||
|
parent-table parent-id position))
|
||||||
|
stats' (update stats :shapes inc)]
|
||||||
|
(if-let [child-ids (when (container-table? table)
|
||||||
|
(child-shape-ids shape))]
|
||||||
|
(project-shape-ids objects statements' stats' table shape-id child-ids)
|
||||||
|
[statements' stats'])))
|
||||||
|
|
||||||
|
(defn- project-shape-ids
|
||||||
|
[objects statements stats parent-table parent-id child-ids]
|
||||||
|
(reduce
|
||||||
|
(fn [[stmts st] [position shape-id]]
|
||||||
|
(if-let [shape (get objects shape-id)]
|
||||||
|
(if-let [table (shape-table shape)]
|
||||||
|
(project-shape objects stmts st table shape parent-table parent-id position)
|
||||||
|
(do
|
||||||
|
(l/wrn :hint "unsupported shape type for graph slice"
|
||||||
|
:shape-id (str shape-id)
|
||||||
|
:type (:type shape))
|
||||||
|
[stmts st]))
|
||||||
|
(do
|
||||||
|
(l/wrn :hint "missing shape in page objects"
|
||||||
|
:shape-id (str shape-id))
|
||||||
|
[stmts st])))
|
||||||
|
[statements stats]
|
||||||
|
(map-indexed vector child-ids)))
|
||||||
|
|
||||||
(defn- project-page
|
(defn- project-page
|
||||||
[statements stats doc-id page position]
|
[statements stats doc-id page position]
|
||||||
(let [page-id (:id page)
|
(let [page-id (:id page)
|
||||||
objects (:objects page)
|
objects (:objects page)
|
||||||
root (get objects root-frame-id)
|
root (get objects root-frame-id)
|
||||||
top-level-ids (when root (vec (reverse (:shapes root))))
|
statements' (conj statements
|
||||||
statements' (conj statements
|
(validated-node-statement specs/check-page "Page"
|
||||||
(validated-node-statement specs/check-page "Page"
|
(page-attrs page position))
|
||||||
(page-attrs page position))
|
(merge-edge-statement "Page" page-id "Document" doc-id position))
|
||||||
(merge-edge-statement "Page" page-id "Document" doc-id position))
|
stats' (update stats :pages inc)]
|
||||||
stats' (update stats :pages inc)]
|
(if-let [top-level-ids (child-shape-ids root)]
|
||||||
(if (seq top-level-ids)
|
(project-shape-ids objects statements' stats' "Page" page-id top-level-ids)
|
||||||
(reduce
|
|
||||||
(fn [[stmts st] [shape-pos shape-id]]
|
|
||||||
(if-let [shape (get objects shape-id)]
|
|
||||||
(if-let [table (shape-table shape)]
|
|
||||||
[(-> stmts
|
|
||||||
(conj (validated-node-statement specs/check-shape-node table
|
|
||||||
{:id (:id shape)
|
|
||||||
:name (:name shape)})
|
|
||||||
(merge-edge-statement table (:id shape)
|
|
||||||
"Page" page-id shape-pos)))
|
|
||||||
(update st :shapes inc)]
|
|
||||||
(do
|
|
||||||
(l/wrn :hint "unsupported shape type for graph slice"
|
|
||||||
:shape-id (str shape-id)
|
|
||||||
:type (:type shape))
|
|
||||||
[stmts st]))
|
|
||||||
[stmts st]))
|
|
||||||
[statements' stats']
|
|
||||||
(map-indexed vector top-level-ids))
|
|
||||||
[statements' stats'])))
|
[statements' stats'])))
|
||||||
|
|
||||||
(defn projection-statements
|
(defn projection-statements
|
||||||
|
|||||||
@ -13,7 +13,10 @@
|
|||||||
[clojure.string :as str]))
|
[clojure.string :as str]))
|
||||||
|
|
||||||
(def schema-version
|
(def schema-version
|
||||||
"penpot-graph-slice-1")
|
"penpot-graph-slice-2")
|
||||||
|
|
||||||
|
(def container-node-tables
|
||||||
|
#{"Frame" "Group" "Boolean" "SVGRaw"})
|
||||||
|
|
||||||
(def node-tables
|
(def node-tables
|
||||||
[{:name "Document"
|
[{:name "Document"
|
||||||
@ -70,9 +73,13 @@
|
|||||||
(str "CREATE REL TABLE `IsChildOf` ("
|
(str "CREATE REL TABLE `IsChildOf` ("
|
||||||
"FROM `Page` TO `Document`, "
|
"FROM `Page` TO `Document`, "
|
||||||
(str/join ", "
|
(str/join ", "
|
||||||
(map (fn [shape]
|
(concat
|
||||||
(str "FROM `" shape "` TO `Page`"))
|
(map (fn [shape]
|
||||||
shape-node-tables))
|
(str "FROM `" shape "` TO `Page`"))
|
||||||
|
shape-node-tables)
|
||||||
|
(for [shape shape-node-tables
|
||||||
|
container container-node-tables]
|
||||||
|
(str "FROM `" shape "` TO `" container "`"))))
|
||||||
", `position` INT64);"))
|
", `position` INT64);"))
|
||||||
|
|
||||||
(defn ddl-statements
|
(defn ddl-statements
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user