mirror of
https://github.com/penpot/penpot.git
synced 2025-06-07 20:41:40 +02:00
✨ Information panels
This commit is contained in:
parent
04f620ec00
commit
1e48221d7b
10 changed files with 713 additions and 18 deletions
|
@ -93,12 +93,13 @@
|
|||
(update [_ state]
|
||||
(let [objects (:objects page)
|
||||
frames (extract-frames objects)]
|
||||
(assoc state :viewer-data {:project project
|
||||
:objects objects
|
||||
:file file
|
||||
:page page
|
||||
:frames frames
|
||||
:share-token share-token})))))
|
||||
(-> state
|
||||
(assoc :viewer-data {:project project
|
||||
:objects objects
|
||||
:file file
|
||||
:page page
|
||||
:frames frames
|
||||
:share-token share-token}))))))
|
||||
|
||||
(def create-share-link
|
||||
(ptk/reify ::create-share-link
|
||||
|
|
|
@ -36,7 +36,7 @@
|
|||
(let [color (if (string? color) {:color color :opacity 1} color)
|
||||
{:keys [name color opacity gradient]} color
|
||||
color-str (or name color (gradient-type->string (:type gradient)))]
|
||||
(when (= size :big)
|
||||
(when (or (not size) (= size :big))
|
||||
[:span.color-text {:on-click #(when on-click (on-click %))
|
||||
:on-double-click #(when on-double-click (on-double-click %))
|
||||
:title name } color-str])))
|
||||
|
|
|
@ -43,6 +43,12 @@
|
|||
frames (:frames data [])
|
||||
objects (:objects data)
|
||||
frame (get frames index)]
|
||||
|
||||
(mf/use-effect
|
||||
(mf/deps index)
|
||||
(fn []
|
||||
(st/emit! (dv/select-shape (:id frame)))))
|
||||
|
||||
[:section.viewer-preview
|
||||
(cond
|
||||
(empty? frames)
|
||||
|
@ -60,7 +66,7 @@
|
|||
[:& render-frame-svg {:frame-id (:id frame)
|
||||
:zoom (:zoom local)
|
||||
:objects objects}]]
|
||||
[:& attributes-sidebar]])]))
|
||||
[:& attributes-sidebar {:frame frame}]])]))
|
||||
|
||||
(mf/defc handoff-content
|
||||
[{:keys [data local index] :as props}]
|
||||
|
|
248
frontend/src/app/main/ui/viewer/handoff/attrib_panel.cljs
Normal file
248
frontend/src/app/main/ui/viewer/handoff/attrib_panel.cljs
Normal file
|
@ -0,0 +1,248 @@
|
|||
;; This Source Code Form is subject to the terms of the Mozilla Public
|
||||
;; License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
;; file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
;;
|
||||
;; This Source Code Form is "Incompatible With Secondary Licenses", as
|
||||
;; defined by the Mozilla Public License, v. 2.0.
|
||||
;;
|
||||
;; Copyright (c) 2020 UXBOX Labs SL
|
||||
|
||||
(ns app.main.ui.viewer.handoff.attrib-panel
|
||||
(:require
|
||||
[rumext.alpha :as mf]
|
||||
[cuerdas.core :as str]
|
||||
[app.config :as cfg]
|
||||
[app.util.i18n :refer [locale t]]
|
||||
[app.common.geom.shapes :as gsh]
|
||||
[app.common.math :as mth]
|
||||
[app.main.ui.icons :as i]
|
||||
[app.util.color :as uc]
|
||||
[app.util.text :as ut]
|
||||
[app.main.fonts :as fonts]
|
||||
[app.main.ui.components.color-bullet :refer [color-bullet color-name]]))
|
||||
|
||||
(mf/defc color-row [{:keys [color]}]
|
||||
(let [locale (mf/deref locale)]
|
||||
[:div.attributes-color-row
|
||||
[:& color-bullet {:color color}]
|
||||
|
||||
[:*
|
||||
[:& color-name {:color color}]
|
||||
(when-not (:gradient color) [:div (str (* 100 (:opacity color)) "%")])]
|
||||
|
||||
[:select
|
||||
[:option (t locale "handoff.attributes.color.hex")]
|
||||
[:option (t locale "handoff.attributes.color.rgba")]
|
||||
[:option (t locale "handoff.attributes.color.hsla")]]
|
||||
|
||||
[:button.attributes-copy-button i/copy]]))
|
||||
|
||||
(mf/defc layout-panel
|
||||
[{:keys [shape locale]}]
|
||||
[:div.attributes-block
|
||||
[:div.attributes-block-title
|
||||
[:div.attributes-block-title-text (t locale "handoff.attributes.layout")]
|
||||
[:button.attributes-copy-button i/copy]]
|
||||
|
||||
[:div.attributes-unit-row
|
||||
[:div.attributes-label (t locale "handoff.attributes.layout.width")]
|
||||
[:div.attributes-value (mth/precision (:width shape) 2) "px"]
|
||||
[:button.attributes-copy-button i/copy]]
|
||||
|
||||
[:div.attributes-unit-row
|
||||
[:div.attributes-label (t locale "handoff.attributes.layout.height")]
|
||||
[:div.attributes-value (mth/precision (:height shape) 2) "px"]
|
||||
[:button.attributes-copy-button i/copy]]
|
||||
|
||||
(when (not= (:x shape) 0)
|
||||
[:div.attributes-unit-row
|
||||
[:div.attributes-label (t locale "handoff.attributes.layout.left")]
|
||||
[:div.attributes-value (mth/precision (:x shape) 2) "px"]
|
||||
[:button.attributes-copy-button i/copy]])
|
||||
|
||||
(when (not= (:y shape) 0)
|
||||
[:div.attributes-unit-row
|
||||
[:div.attributes-label (t locale "handoff.attributes.layout.top")]
|
||||
[:div.attributes-value (mth/precision (:y shape) 2) "px"]
|
||||
[:button.attributes-copy-button i/copy]])
|
||||
|
||||
(when (not= (:rotation shape) 0)
|
||||
[:div.attributes-unit-row
|
||||
[:div.attributes-label (t locale "handoff.attributes.layout.rotation")]
|
||||
[:div.attributes-value (mth/precision (:rotation shape) 2) "deg"]
|
||||
[:button.attributes-copy-button i/copy]])])
|
||||
|
||||
(mf/defc fill-panel
|
||||
[{:keys [shape locale]}]
|
||||
(let [{:keys [fill-color fill-opacity fill-color-gradient fill-ref-id fill-ref-file-id]} shape]
|
||||
(when (or fill-color fill-color-gradient)
|
||||
[:div.attributes-block
|
||||
[:div.attributes-block-title
|
||||
[:div.attributes-block-title-text (t locale "handoff.attributes.fill")]
|
||||
[:button.attributes-copy-button i/copy]]
|
||||
|
||||
(let [color {:color fill-color
|
||||
:opacity fill-opacity
|
||||
:gradient fill-color-gradient
|
||||
:id fill-ref-id
|
||||
:file-id fill-ref-file-id}]
|
||||
[:& color-row {:color color}])])))
|
||||
|
||||
(mf/defc stroke-panel
|
||||
[{:keys [shape locale]}]
|
||||
(when (and (:stroke-style shape) (not= (:stroke-style shape) :none))
|
||||
(let [{:keys [stroke-style stroke-alignment stroke-width
|
||||
stroke-color stroke-opacity stroke-color-gradient
|
||||
stroke-color-ref-id stroke-color-file-id]} shape
|
||||
color {:color stroke-color
|
||||
:opacity stroke-opacity
|
||||
:gradient stroke-color-gradient
|
||||
:id stroke-color-ref-id
|
||||
:file-id stroke-color-file-id}]
|
||||
[:div.attributes-block
|
||||
[:div.attributes-block-title
|
||||
[:div.attributes-block-title-text (t locale "handoff.attributes.stroke")]
|
||||
[:button.attributes-copy-button i/copy]]
|
||||
|
||||
[:& color-row {:color color}]
|
||||
|
||||
[:div.attributes-stroke-row
|
||||
[:div.attributes-label (t locale "handoff.attributes.stroke.width")]
|
||||
[:div.attributes-value (str stroke-width) "px"]
|
||||
[:div.attributes-value (->> stroke-style name (str "handoff.attributes.stroke.style.") (t locale))]
|
||||
[:div.attributes-label (->> stroke-alignment name (str "handoff.attributes.stroke.alignment.") (t locale))]
|
||||
[:button.attributes-copy-button i/copy]]])))
|
||||
|
||||
(mf/defc shadow-panel [{:keys [shape locale]}]
|
||||
(when (seq (:shadow shape))
|
||||
[:div.attributes-block
|
||||
[:div.attributes-block-title
|
||||
[:div.attributes-block-title-text (t locale "handoff.attributes.shadow")]
|
||||
[:button.attributes-copy-button i/copy]]
|
||||
|
||||
(for [shadow (:shadow shape)]
|
||||
(do
|
||||
(prn "???" (:spread shadow))
|
||||
[:*
|
||||
[:div.attributes-shadow-row
|
||||
[:div.attributes-label (->> shadow :style name (str "handoff.attributes.shadow.style.") (t locale))]
|
||||
[:div.attributes-shadow
|
||||
[:div.attributes-label (t locale "handoff.attributes.shadow.shorthand.offset-x")]
|
||||
[:div.attributes-value (str (:offset-x shadow))]]
|
||||
|
||||
[:div.attributes-shadow
|
||||
[:div.attributes-label (t locale "handoff.attributes.shadow.shorthand.offset-y")]
|
||||
[:div.attributes-value (str (:offset-y shadow))]]
|
||||
|
||||
[:div.attributes-shadow
|
||||
[:div.attributes-label (t locale "handoff.attributes.shadow.shorthand.blur")]
|
||||
[:div.attributes-value (str (:blur shadow))]]
|
||||
|
||||
[:div.attributes-shadow
|
||||
[:div.attributes-label (t locale "handoff.attributes.shadow.shorthand.spread")]
|
||||
[:div.attributes-value (str (:spread shadow))]]
|
||||
|
||||
[:button.attributes-copy-button i/copy]]
|
||||
[:& color-row {:color (:color shadow)}]]))]))
|
||||
|
||||
(mf/defc blur-panel [{:keys [shape locale]}]
|
||||
(when (:blur shape)
|
||||
[:div.attributes-block
|
||||
[:div.attributes-block-title
|
||||
[:div.attributes-block-title-text (t locale "handoff.attributes.blur")]
|
||||
[:button.attributes-copy-button i/copy]]
|
||||
|
||||
[:div.attributes-unit-row
|
||||
[:div.attributes-label (t locale "handoff.attributes.blur.value")]
|
||||
[:div.attributes-value (-> shape :blur :value) "px"]
|
||||
[:button.attributes-copy-button i/copy]]]))
|
||||
|
||||
(mf/defc image-panel [{:keys [shape locale]}]
|
||||
[:div.attributes-block
|
||||
[:div.attributes-image-row
|
||||
[:div.attributes-image
|
||||
[:img {:src (cfg/resolve-media-path (-> shape :metadata :path))}]]]
|
||||
[:div.attributes-unit-row
|
||||
[:div.attributes-label (t locale "handoff.attributes.image.width")]
|
||||
[:div.attributes-value (-> shape :metadata :width) "px"]]
|
||||
[:div.attributes-unit-row
|
||||
[:div.attributes-label (t locale "handoff.attributes.image.height")]
|
||||
[:div.attributes-value (-> shape :metadata :height) "px"]]
|
||||
(let [filename (last (str/split (-> shape :metadata :path) "/"))]
|
||||
[:a.download-button {:target "_blank"
|
||||
:download filename
|
||||
:href (cfg/resolve-media-path (-> shape :metadata :path))}
|
||||
(t locale "handoff.attributes.image.download")])])
|
||||
|
||||
(mf/defc typography-panel [{:keys [shape locale]}]
|
||||
(let [font (ut/search-text-attrs (:content shape)
|
||||
(keys ut/default-text-attrs))
|
||||
font (merge ut/default-text-attrs font)]
|
||||
[:div.attributes-block
|
||||
[:div.attributes-block-title
|
||||
[:div.attributes-block-title-text (t locale "handoff.attributes.typography")]
|
||||
[:button.attributes-copy-button i/copy]]
|
||||
|
||||
[:div.attributes-unit-row
|
||||
[:div.attributes-label (t locale "handoff.attributes.typography.font-family")]
|
||||
[:div.attributes-value (-> font :font-id fonts/get-font-data :name)]
|
||||
[:button.attributes-copy-button i/copy]]
|
||||
|
||||
[:div.attributes-unit-row
|
||||
[:div.attributes-label (t locale "handoff.attributes.typography.font-style")]
|
||||
[:div.attributes-value (str (:font-style font))]
|
||||
[:button.attributes-copy-button i/copy]]
|
||||
|
||||
[:div.attributes-unit-row
|
||||
[:div.attributes-label (t locale "handoff.attributes.typography.font-size")]
|
||||
[:div.attributes-value (str (:font-size font)) "px"]
|
||||
[:button.attributes-copy-button i/copy]]
|
||||
|
||||
[:div.attributes-unit-row
|
||||
[:div.attributes-label (t locale "handoff.attributes.typography.line-height")]
|
||||
[:div.attributes-value (str (:line-height font)) "px"]
|
||||
[:button.attributes-copy-button i/copy]]
|
||||
|
||||
[:div.attributes-unit-row
|
||||
[:div.attributes-label (t locale "handoff.attributes.typography.letter-spacing")]
|
||||
[:div.attributes-value (str (:letter-spacing font)) "px"]
|
||||
[:button.attributes-copy-button i/copy]]
|
||||
|
||||
[:div.attributes-unit-row
|
||||
[:div.attributes-label (t locale "handoff.attributes.typography.text-decoration")]
|
||||
[:div.attributes-value (->> font :text-decoration (str "handoff.attributes.typography.text-decoration.") (t locale))]
|
||||
[:button.attributes-copy-button i/copy]]
|
||||
|
||||
[:div.attributes-unit-row
|
||||
[:div.attributes-label (t locale "handoff.attributes.typography.text-transform")]
|
||||
[:div.attributes-value (->> font :text-transform (str "handoff.attributes.typography.text-transform.") (t locale))]
|
||||
[:button.attributes-copy-button i/copy]]]))
|
||||
|
||||
(mf/defc content-panel [{:keys [shape locale]}]
|
||||
[:div.attributes-block
|
||||
[:div.attributes-block-title
|
||||
[:div.attributes-block-title-text (t locale "handoff.attributes.content")]
|
||||
[:button.attributes-copy-button i/copy]]
|
||||
|
||||
[:div.attributes-content-row
|
||||
[:pre.attributes-content (ut/content->text (:content shape))]
|
||||
[:button.attributes-copy-button i/copy]]])
|
||||
|
||||
(mf/defc attrib-panel [{:keys [shape frame options]}]
|
||||
(let [locale (mf/deref locale)]
|
||||
[:div.element-options
|
||||
(for [option options]
|
||||
[:>
|
||||
(case option
|
||||
:layout layout-panel
|
||||
:fill fill-panel
|
||||
:stroke stroke-panel
|
||||
:shadow shadow-panel
|
||||
:blur blur-panel
|
||||
:image image-panel
|
||||
:typography typography-panel
|
||||
:content content-panel
|
||||
)
|
||||
{:shape (gsh/translate-to-frame shape frame)
|
||||
:frame frame
|
||||
:locale locale}])]))
|
110
frontend/src/app/main/ui/viewer/handoff/attributes/layout.cljs
Normal file
110
frontend/src/app/main/ui/viewer/handoff/attributes/layout.cljs
Normal file
|
@ -0,0 +1,110 @@
|
|||
;; This Source Code Form is subject to the terms of the Mozilla Public
|
||||
;; License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
;; file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
;;
|
||||
;; This Source Code Form is "Incompatible With Secondary Licenses", as
|
||||
;; defined by the Mozilla Public License, v. 2.0.
|
||||
;;
|
||||
;; Copyright (c) 2020 UXBOX Labs SL
|
||||
|
||||
(ns app.main.ui.viewer.handoff.attributes.layout
|
||||
(:require
|
||||
[rumext.alpha :as mf]
|
||||
[app.main.ui.icons :as i]
|
||||
[app.main.ui.components.color-bullet :refer [color-bullet color-name]]))
|
||||
|
||||
|
||||
(mf/defc layout-panel [{:keys [shapes]}]
|
||||
(prn "???" shapes)
|
||||
[:*
|
||||
[:div.attributes-block
|
||||
[:div.attributes-block-title
|
||||
[:div.attributes-block-title-text "Layout"]
|
||||
[:button.attributes-copy-button i/copy]]
|
||||
|
||||
[:div.attributes-unit-row
|
||||
[:div.attributes-label "Width"]
|
||||
[:div.attributes-value "100px"]
|
||||
[:button.attributes-copy-button i/copy]]
|
||||
|
||||
[:div.attributes-unit-row
|
||||
[:div.attributes-label "Height"]
|
||||
[:div.attributes-value "100px"]
|
||||
[:button.attributes-copy-button i/copy]]
|
||||
|
||||
[:div.attributes-unit-row
|
||||
[:div.attributes-label "Top"]
|
||||
[:div.attributes-value "100px"]
|
||||
[:button.attributes-copy-button i/copy]]
|
||||
|
||||
[:div.attributes-unit-row
|
||||
[:div.attributes-label "Left"]
|
||||
[:div.attributes-value "100px"]
|
||||
[:button.attributes-copy-button i/copy]]]
|
||||
|
||||
[:div.attributes-block
|
||||
[:div.attributes-block-title
|
||||
[:div.attributes-block-title-text "Fill"]
|
||||
[:button.attributes-copy-button i/copy]]
|
||||
|
||||
[:div.attributes-shadow-row
|
||||
[:div.attributes-label "Drop"]
|
||||
[:div.attributes-shadow
|
||||
[:div.attributes-label "X"]
|
||||
[:div.attributes-value "4"]]
|
||||
|
||||
[:div.attributes-shadow
|
||||
[:div.attributes-label "Y"]
|
||||
[:div.attributes-value "4"]]
|
||||
|
||||
[:div.attributes-shadow
|
||||
[:div.attributes-label "B"]
|
||||
[:div.attributes-value "0"]]
|
||||
|
||||
[:div.attributes-shadow
|
||||
[:div.attributes-label "B"]
|
||||
[:div.attributes-value "0"]]
|
||||
|
||||
[:button.attributes-copy-button i/copy]]
|
||||
|
||||
[:div.attributes-color-row
|
||||
[:& color-bullet {:color {:color "#000000" :opacity 0.5}}]
|
||||
|
||||
[:*
|
||||
[:div "#000000"]
|
||||
[:div "100%"]]
|
||||
|
||||
[:select
|
||||
[:option "Hex"]
|
||||
[:option "RGBA"]
|
||||
[:option "HSLA"]]
|
||||
|
||||
[:button.attributes-copy-button i/copy]]
|
||||
|
||||
[:div.attributes-stroke-row
|
||||
[:div.attributes-label "Width"]
|
||||
[:div.attributes-value "1px"]
|
||||
[:div.attributes-value "Solid"]
|
||||
[:div.attributes-label "Center"]
|
||||
[:button.attributes-copy-button i/copy]]]
|
||||
|
||||
[:div.attributes-block
|
||||
[:div.attributes-block-title
|
||||
[:div.attributes-block-title-text "Content"]
|
||||
[:button.attributes-copy-button i/copy]]
|
||||
|
||||
[:div.attributes-content-row
|
||||
[:div.attributes-content
|
||||
"Hi, how are you"]
|
||||
[:button.attributes-copy-button i/copy]]]
|
||||
|
||||
[:div.attributes-block
|
||||
[:div.attributes-image-row
|
||||
[:div.attributes-image
|
||||
#_[:img {:src "https://www.publico.es/tremending/wp-content/uploads/2019/05/Cxagv.jpg"}]
|
||||
#_[:img {:src "https://i.blogs.es/3861b2/grumpy-cat/1366_2000.png"}]
|
||||
[:img {:src "https://abs.twimg.com/favicons/twitter.ico"}]
|
||||
]]
|
||||
[:button.download-button "Dowload source image"]]
|
||||
|
||||
])
|
|
@ -10,16 +10,48 @@
|
|||
(ns app.main.ui.viewer.handoff.attributes-sidebar
|
||||
(:require
|
||||
[rumext.alpha :as mf]
|
||||
[okulary.core :as l]
|
||||
[app.main.store :as st]
|
||||
[app.main.ui.icons :as i]
|
||||
[app.main.ui.components.tab-container :refer [tab-container tab-element]]))
|
||||
[app.main.ui.components.tab-container :refer [tab-container tab-element]]
|
||||
[app.main.ui.viewer.handoff.attrib-panel :refer [attrib-panel]]))
|
||||
|
||||
(mf/defc info-panel []
|
||||
[:div.element-options])
|
||||
(defn make-selected-shapes-iref
|
||||
[]
|
||||
(let [selected->shapes
|
||||
(fn [state]
|
||||
(let [selected (get-in state [:viewer-local :selected])
|
||||
objects (get-in state [:viewer-data :page :objects])
|
||||
resolve-shape #(get objects %)]
|
||||
(mapv resolve-shape selected)))]
|
||||
#(l/derived selected->shapes st/state)))
|
||||
|
||||
(mf/defc info-panel [{:keys [frame]}]
|
||||
(let [selected-ref (mf/use-memo (make-selected-shapes-iref))
|
||||
shapes (mf/deref selected-ref)]
|
||||
(if (> (count shapes) 1)
|
||||
;; Multiple selection
|
||||
nil
|
||||
;; Single shape
|
||||
(when-let [shape (first shapes)]
|
||||
(let [options
|
||||
(case (:type shape)
|
||||
:frame [:layout :fill]
|
||||
:group [:layout]
|
||||
:rect [:layout :fill :stroke :shadow :blur]
|
||||
:circle [:layout :fill :stroke :shadow :blur]
|
||||
:path [:layout :fill :stroke :shadow :blur]
|
||||
:curve [:layout :fill :stroke :shadow :blur]
|
||||
:image [:image :layout :shadow :blur]
|
||||
:text [:layout :fill :typography :content :shadow :blur])]
|
||||
[:& attrib-panel {:frame frame
|
||||
:shape shape
|
||||
:options options}])))))
|
||||
|
||||
(mf/defc code-panel []
|
||||
[:div.element-options])
|
||||
|
||||
(mf/defc attributes-sidebar []
|
||||
(mf/defc attributes-sidebar [{:keys [frame]}]
|
||||
(let [section (mf/use-state :info #_:code)]
|
||||
[:aside.settings-bar.settings-bar-right
|
||||
[:div.settings-bar-inside
|
||||
|
@ -31,8 +63,7 @@
|
|||
[:& tab-container {:on-change-tab #(reset! section %)
|
||||
:selected @section}
|
||||
[:& tab-element {:id :info :title "Info"}
|
||||
[:& info-panel]]
|
||||
[:& info-panel {:frame frame}]]
|
||||
|
||||
[:& tab-element {:id :code :title "Code"}
|
||||
[:& code-panel]]]]]]]))
|
||||
|
||||
|
|
|
@ -46,7 +46,7 @@
|
|||
(let [hover (get-in state [:viewer-local :hover])
|
||||
objects (get-in state [:viewer-data :page :objects])
|
||||
resolve-shape #(get objects %)]
|
||||
(map resolve-shape hover)))]
|
||||
(mapv resolve-shape hover)))]
|
||||
#(l/derived hover->shapes st/state)))
|
||||
|
||||
(mf/defc selection-feedback [{:keys [frame]}]
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
(ns app.util.text)
|
||||
(ns app.util.text
|
||||
(:require
|
||||
[cuerdas.core :as str]))
|
||||
|
||||
(defonce default-text-attrs
|
||||
{:font-id "sourcesanspro"
|
||||
|
@ -11,7 +13,9 @@
|
|||
:letter-spacing "0"
|
||||
:text-transform "none"
|
||||
:text-align "left"
|
||||
:text-decoration "none"})
|
||||
:text-decoration "none"
|
||||
:fill-color "#000000"
|
||||
:fill-opacity 1})
|
||||
|
||||
(def typography-fields
|
||||
[:font-id
|
||||
|
@ -38,3 +42,20 @@
|
|||
[map-fn node]
|
||||
(cond-> (map-fn node)
|
||||
(:children node) (update :children (fn [children] (mapv #(map-node map-fn %) children)))))
|
||||
|
||||
(defn content->text
|
||||
[node]
|
||||
(str
|
||||
(if (:children node)
|
||||
(str/join (if (= "paragraph-set" (:type node)) "\n" "") (map content->text (:children node)))
|
||||
(:text node ""))))
|
||||
|
||||
(defn search-text-attrs
|
||||
[node attrs]
|
||||
|
||||
(let [rec-fn
|
||||
(fn rec-fn [current node]
|
||||
(let [current (reduce rec-fn current (:children node []))]
|
||||
(merge current
|
||||
(select-keys node attrs))))]
|
||||
(rec-fn {} node)))
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue