0
Fork 0
mirror of https://github.com/penpot/penpot.git synced 2025-02-12 18:18:24 -05:00

Add write apis to the plugins

This commit is contained in:
alonso.torres 2024-04-22 15:40:01 +02:00
parent c85f76300a
commit 00de89197e
4 changed files with 160 additions and 29 deletions

View file

@ -381,6 +381,53 @@
(-> (rec-style-text-map [] node {}) (-> (rec-style-text-map [] node {})
reverse))) reverse)))
(defn content->text
"Given a root node of a text content extracts the texts with its associated styles"
[content]
(letfn [(add-node [acc node]
(cond
(is-paragraph-node? node)
(conj acc [])
(is-text-node? node)
(let [i (dec (count acc))]
(update acc i conj (:text node)))
:else
acc))]
(->> (node-seq content)
(reduce add-node [])
(map #(str/join "" %))
(str/join "\n"))))
(defn change-text
"Changes the content of the text shape to use the text as argument. Will use the styles of the
first paragraph and text that is present in the shape (and override the rest)"
[shape text]
(let [content (:content shape)
paragraph-style (select-keys (->> content (node-seq is-paragraph-node?) first) text-all-attrs)
text-style (select-keys (->> content (node-seq is-text-node?) first) text-all-attrs)
paragraph-texts (str/split text "\n")
paragraphs
(->> paragraph-texts
(mapv
(fn [pt]
(merge
paragraph-style
{:type "paragraph"
:children [(merge {:text pt} text-style)]}))))
new-content
{:type "root"
:children
[{:type "paragraph-set"
:children paragraphs}]}]
(assoc shape :content new-content)))
(defn index-content (defn index-content
"Adds a property `$id` that identifies the current node inside" "Adds a property `$id` that identifies the current node inside"
([content] ([content]

View file

@ -8,8 +8,11 @@
"RPC for plugins runtime." "RPC for plugins runtime."
(:require (:require
[app.common.data.macros :as dm] [app.common.data.macros :as dm]
[app.common.files.changes-builder :as cb]
[app.common.record :as cr] [app.common.record :as cr]
[app.common.types.shape :as cts]
[app.common.uuid :as uuid] [app.common.uuid :as uuid]
[app.main.data.workspace.changes :as ch]
[app.main.store :as st] [app.main.store :as st]
[app.plugins.events :as events] [app.plugins.events :as events]
[app.plugins.file :as file] [app.plugins.file :as file]
@ -37,8 +40,9 @@
(getPage (getPage
[_] [_]
(let [page-id (:current-page-id @st/state)] (let [page-id (:current-page-id @st/state)
(page/data->page-proxy (dm/get-in @st/state [:workspace-data :pages-index page-id])))) page (dm/get-in @st/state [:workspace-data :pages-index page-id])]
(page/data->page-proxy page)))
(getSelected (getSelected
[_] [_]
@ -64,11 +68,26 @@
(let [theme (get-in @st/state [:profile :theme])] (let [theme (get-in @st/state [:profile :theme])]
(if (or (not theme) (= theme "default")) (if (or (not theme) (= theme "default"))
"dark" "dark"
(get-in @st/state [:profile :theme]))))) (get-in @st/state [:profile :theme]))))
(createRectangle
[_]
(let [page-id (:current-page-id @st/state)
page (dm/get-in @st/state [:workspace-data :pages-index page-id])
shape (cts/setup-shape {:type :rect
:x 0 :y 0 :width 100 :height 100})
changes
(-> (cb/empty-changes)
(cb/with-page page)
(cb/with-objects (:objects page))
(cb/add-object shape))]
(st/emit! (ch/commit-changes changes))
(shape/data->shape-proxy shape))))
(defn create-context (defn create-context
[] []
(cr/add-properties! (cr/add-properties!
(PenpotContext.) (PenpotContext.)
{:name "root" :get #(.getRoot ^js %)} {:name "root" :get #(.getRoot ^js %)}
{:name "currentPage" :get #(.getPage ^js %)})) {:name "currentPage" :get #(.getPage ^js %)}
{:name "selection" :get #(.getSelectedShapes ^js %)}))

View file

@ -53,12 +53,10 @@
"dark" "dark"
new-theme)))) new-theme))))
(defmethod handle-state-change :default (defmethod handle-state-change :default
[_ _ _] [_ _ _]
::not-changed) ::not-changed)
(defn add-listener (defn add-listener
[type callback] [type callback]
(let [key (js/Symbol) (let [key (js/Symbol)

View file

@ -7,8 +7,12 @@
(ns app.plugins.shape (ns app.plugins.shape
"RPC for plugins runtime." "RPC for plugins runtime."
(:require (:require
[app.common.data :as d]
[app.common.data.macros :as dm] [app.common.data.macros :as dm]
[app.common.files.helpers :as cfh]
[app.common.record :as crc] [app.common.record :as crc]
[app.common.text :as txt]
[app.main.data.workspace :as udw]
[app.main.data.workspace.changes :as dwc] [app.main.data.workspace.changes :as dwc]
[app.main.store :as st] [app.main.store :as st]
[app.plugins.utils :refer [get-data get-data-fn]] [app.plugins.utils :refer [get-data get-data-fn]]
@ -18,24 +22,51 @@
(defn- make-fills (defn- make-fills
[fills] [fills]
;; TODO: Transform explicitly? (.freeze
(apply array js/Object
(->> fills (apply array
(map #(clj->js % {:keyword-fn (fn [k] (str/camel (name k)))}))))) (->> fills
;; TODO: Transform explicitly instead of cljs->js?
(map #(clj->js % {:keyword-fn (fn [k] (str/camel (name k)))}))))))
(defn- make-strokes
[strokes]
(.freeze
js/Object
(apply array
(->> strokes
;; TODO: Transform explicitly instead of cljs->js?
(map #(clj->js % {:keyword-fn (fn [k] (str/camel (name k)))}))))))
(defn- locate-shape (defn- locate-shape
[shape-id] [shape-id]
(let [page-id (:current-page-id @st/state)] (let [page-id (:current-page-id @st/state)]
(dm/get-in @st/state [:workspace-data :pages-index page-id :objects shape-id]))) (dm/get-in @st/state [:workspace-data :pages-index page-id :objects shape-id])))
(deftype ShapeProxy [#_:clj-kondo/ignore _data] (defn- get-state
([self attr]
(let [id (get-data self :id)
page-id (d/nilv (get-data self :page-id) (:current-page-id @st/state))]
(dm/get-in @st/state [:workspace-data :pages-index page-id :objects id attr])))
([self attr mapfn]
(-> (get-state self attr)
(mapfn))))
(deftype ShapeProxy [^:mutable #_:clj-kondo/ignore _data]
Object Object
(getChildren (getChildren
[self] [self]
(apply array (->> (get-data self :shapes) (apply array (->> (get-state self :shapes)
(map locate-shape) (map locate-shape)
(map data->shape-proxy)))) (map data->shape-proxy))))
(resize
[self width height]
(let [id (get-data self :id)]
(st/emit! (udw/update-dimensions [id] :width width)
(udw/update-dimensions [id] :height height))))
(clone [_] (.log js/console (clj->js _data))) (clone [_] (.log js/console (clj->js _data)))
(delete [_] (.log js/console (clj->js _data))) (delete [_] (.log js/console (clj->js _data)))
(appendChild [_] (.log js/console (clj->js _data)))) (appendChild [_] (.log js/console (clj->js _data))))
@ -48,25 +79,61 @@
(defn data->shape-proxy (defn data->shape-proxy
[data] [data]
(crc/add-properties! (-> (ShapeProxy. data)
(ShapeProxy. data) (crc/add-properties!
{:name "_data" {:name "_data"
:enumerable false} :enumerable false}
{:name "id" {:name "id"
:get (get-data-fn :id str)} :get (get-data-fn :id str)}
{:name "name" {:name "type"
:get (get-data-fn :name) :get (get-data-fn :type)}
:set (fn [self value]
(let [id (get-data self :id)]
(st/emit! (dwc/update-shapes [id] #(assoc % :name value)))))}
{:name "children" {:name "x"
:get #(.getChildren ^js %)} :get #(get-state % :x)
:set
(fn [self value]
(let [id (get-data self :id)]
(st/emit! (udw/update-position id {:x value}))))}
{:name "fills" {:name "y"
:get (get-data-fn :fills make-fills) :get #(get-state % :y)
;;:set (fn [self value] (.log js/console self value)) :set
})) (fn [self value]
(let [id (get-data self :id)]
(st/emit! (udw/update-position id {:y value}))))}
{:name "width"
:get #(get-state % :width)}
{:name "height"
:get #(get-state % :height)}
{:name "name"
:get #(get-state % :name)
:set (fn [self value]
(let [id (get-data self :id)]
(st/emit! (dwc/update-shapes [id] #(assoc % :name value)))))}
{:name "children"
:get #(.getChildren ^js %)}
{:name "fills"
:get #(get-state % :fills make-fills)
;;:set (fn [self value] (.log js/console self value))
}
{:name "strokes"
:get #(get-state % :strokes make-strokes)
;;:set (fn [self value] (.log js/console self value))
})
(cond-> (cfh/text-shape? data)
(crc/add-properties!
{:name "characters"
:get #(get-state % :content txt/content->text)
:set (fn [self value]
(let [id (get-data self :id)]
(st/emit! (dwc/update-shapes [id] #(txt/change-text % value)))))}))))