mirror of
https://github.com/penpot/penpot.git
synced 2025-08-07 14:38:33 +02:00
🐛 Fix problems with old texts
This commit is contained in:
parent
ec63d23666
commit
64ffa9bb3f
10 changed files with 107 additions and 77 deletions
|
@ -224,7 +224,7 @@
|
||||||
:internal.shape.text.position-data/font-size
|
:internal.shape.text.position-data/font-size
|
||||||
:internal.shape.text.position-data/font-style
|
:internal.shape.text.position-data/font-style
|
||||||
:internal.shape.text.position-data/font-weight
|
:internal.shape.text.position-data/font-weight
|
||||||
:internal.shape.text.position-data/rtl?
|
:internal.shape.text.position-data/rtl
|
||||||
:internal.shape.text.position-data/text
|
:internal.shape.text.position-data/text
|
||||||
:internal.shape.text.position-data/text-decoration
|
:internal.shape.text.position-data/text-decoration
|
||||||
:internal.shape.text.position-data/text-transform]
|
:internal.shape.text.position-data/text-transform]
|
||||||
|
@ -243,7 +243,7 @@
|
||||||
(s/def :internal.shape.text.position-data/font-size string?)
|
(s/def :internal.shape.text.position-data/font-size string?)
|
||||||
(s/def :internal.shape.text.position-data/font-style string?)
|
(s/def :internal.shape.text.position-data/font-style string?)
|
||||||
(s/def :internal.shape.text.position-data/font-weight string?)
|
(s/def :internal.shape.text.position-data/font-weight string?)
|
||||||
(s/def :internal.shape.text.position-data/rtl? boolean?)
|
(s/def :internal.shape.text.position-data/rtl boolean?)
|
||||||
(s/def :internal.shape.text.position-data/text string?)
|
(s/def :internal.shape.text.position-data/text string?)
|
||||||
(s/def :internal.shape.text.position-data/text-decoration string?)
|
(s/def :internal.shape.text.position-data/text-decoration string?)
|
||||||
(s/def :internal.shape.text.position-data/text-transform string?)
|
(s/def :internal.shape.text.position-data/text-transform string?)
|
||||||
|
|
|
@ -117,13 +117,31 @@
|
||||||
|
|
||||||
;; --- Helpers
|
;; --- Helpers
|
||||||
|
|
||||||
|
(defn to-new-fills
|
||||||
|
[data]
|
||||||
|
[(d/without-nils (select-keys data [:fill-color :fill-opacity :fill-color-gradient :fill-color-ref-id :fill-color-ref-file]))])
|
||||||
|
|
||||||
(defn- shape-current-values
|
(defn- shape-current-values
|
||||||
[shape pred attrs]
|
[shape pred attrs]
|
||||||
(let [root (:content shape)
|
(let [root (:content shape)
|
||||||
nodes (->> (txt/node-seq pred root)
|
nodes (->> (txt/node-seq pred root)
|
||||||
(map #(if (txt/is-text-node? %)
|
(map (fn [node]
|
||||||
(merge txt/default-text-attrs %)
|
(if (txt/is-text-node? node)
|
||||||
%)))]
|
(let [fills
|
||||||
|
(cond
|
||||||
|
(or (some? (:fill-color node))
|
||||||
|
(some? (:fill-opacity node))
|
||||||
|
(some? (:fill-color-gradient node)))
|
||||||
|
(to-new-fills node)
|
||||||
|
|
||||||
|
(some? (:fills node))
|
||||||
|
(:fills node)
|
||||||
|
|
||||||
|
:else
|
||||||
|
(:fills txt/default-text-attrs))]
|
||||||
|
(-> (merge txt/default-text-attrs node)
|
||||||
|
(assoc :fills fills)))
|
||||||
|
node))))]
|
||||||
(attrs/get-attrs-multi nodes attrs)))
|
(attrs/get-attrs-multi nodes attrs)))
|
||||||
|
|
||||||
(defn current-root-values
|
(defn current-root-values
|
||||||
|
@ -140,8 +158,10 @@
|
||||||
(defn current-text-values
|
(defn current-text-values
|
||||||
[{:keys [editor-state attrs shape]}]
|
[{:keys [editor-state attrs shape]}]
|
||||||
(if editor-state
|
(if editor-state
|
||||||
(-> (ted/get-editor-current-inline-styles editor-state)
|
(let [result (-> (ted/get-editor-current-inline-styles editor-state)
|
||||||
(select-keys attrs))
|
(select-keys attrs))
|
||||||
|
result (if (empty? result) txt/default-text-attrs result)]
|
||||||
|
result)
|
||||||
(shape-current-values shape txt/is-text-node? attrs)))
|
(shape-current-values shape txt/is-text-node? attrs)))
|
||||||
|
|
||||||
|
|
||||||
|
@ -220,24 +240,27 @@
|
||||||
(cph/group-shape? shape) (cph/get-children-ids objects id))]
|
(cph/group-shape? shape) (cph/get-children-ids objects id))]
|
||||||
(rx/of (dch/update-shapes shape-ids #(update-text-content % update-node? attrs/merge attrs))))))))
|
(rx/of (dch/update-shapes shape-ids #(update-text-content % update-node? attrs/merge attrs))))))))
|
||||||
|
|
||||||
|
(defn migrate-node
|
||||||
|
[node]
|
||||||
|
(let [color-attrs (select-keys node [:fill-color :fill-opacity :fill-color-ref-id :fill-color-ref-file :fill-color-gradient])]
|
||||||
|
(cond-> node
|
||||||
|
(d/not-empty? color-attrs)
|
||||||
|
(-> (dissoc :fill-color :fill-opacity :fill-color-ref-id :fill-color-ref-file :fill-color-gradient)
|
||||||
|
(assoc :fills [color-attrs]))
|
||||||
|
|
||||||
|
(nil? (:fills node))
|
||||||
|
(assoc :fills (:fills txt/default-text-attrs)))))
|
||||||
|
|
||||||
(defn migrate-content
|
(defn migrate-content
|
||||||
[content]
|
[content]
|
||||||
(txt/transform-nodes
|
(txt/transform-nodes (some-fn txt/is-text-node? txt/is-paragraph-node?) migrate-node content))
|
||||||
#(or (txt/is-text-node? %) (txt/is-paragraph-node? %))
|
|
||||||
(fn [node]
|
|
||||||
(let [color-attrs (select-keys node [:fill-color :fill-opacity :fill-color-ref-id :fill-color-ref-file :fill-color-gradient])]
|
|
||||||
(cond-> node
|
|
||||||
(d/not-empty? color-attrs)
|
|
||||||
(-> (dissoc :fill-color :fill-opacity :fill-color-ref-id :fill-color-ref-file :fill-color-gradient)
|
|
||||||
(assoc :fills [color-attrs])))))
|
|
||||||
content))
|
|
||||||
|
|
||||||
(defn update-text-with-function
|
(defn update-text-with-function
|
||||||
[id update-node-fn]
|
[id update-node-fn]
|
||||||
(ptk/reify ::update-text-with-function
|
(ptk/reify ::update-text-with-function
|
||||||
ptk/UpdateEvent
|
ptk/UpdateEvent
|
||||||
(update [_ state]
|
(update [_ state]
|
||||||
(d/update-in-when state [:workspace-editor-state id] ted/update-editor-current-inline-styles-fn update-node-fn))
|
(d/update-in-when state [:workspace-editor-state id] ted/update-editor-current-inline-styles-fn (comp update-node-fn migrate-node)))
|
||||||
|
|
||||||
ptk/WatchEvent
|
ptk/WatchEvent
|
||||||
(watch [_ state _]
|
(watch [_ state _]
|
||||||
|
@ -245,10 +268,7 @@
|
||||||
(let [objects (wsh/lookup-page-objects state)
|
(let [objects (wsh/lookup-page-objects state)
|
||||||
shape (get objects id)
|
shape (get objects id)
|
||||||
|
|
||||||
update-node?
|
update-node? (some-fn txt/is-text-node? txt/is-paragraph-node?)
|
||||||
(fn [node]
|
|
||||||
(or (txt/is-text-node? node)
|
|
||||||
(txt/is-paragraph-node? node)))
|
|
||||||
|
|
||||||
shape-ids
|
shape-ids
|
||||||
(cond
|
(cond
|
||||||
|
|
|
@ -48,11 +48,10 @@
|
||||||
(mf/set-ref-val! prev-obs-ref mutation-obs)
|
(mf/set-ref-val! prev-obs-ref mutation-obs)
|
||||||
(.observe mutation-obs node options))))))]
|
(.observe mutation-obs node options))))))]
|
||||||
|
|
||||||
(mf/use-effect
|
(mf/with-effect
|
||||||
(fn []
|
(fn []
|
||||||
(fn []
|
(when-let [^js prev-obs (mf/ref-val prev-obs-ref)]
|
||||||
(when-let [^js prev-obs (mf/ref-val prev-obs-ref)]
|
(.disconnect prev-obs)
|
||||||
(.disconnect prev-obs)
|
(mf/set-ref-val! prev-obs-ref nil))))
|
||||||
(mf/set-ref-val! prev-obs-ref nil)))))
|
|
||||||
|
|
||||||
[node-ref set-node]))
|
[node-ref set-node]))
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
|
|
||||||
(ns app.main.ui.render
|
(ns app.main.ui.render
|
||||||
(:require
|
(:require
|
||||||
|
[app.common.data :as d]
|
||||||
[app.common.geom.matrix :as gmt]
|
[app.common.geom.matrix :as gmt]
|
||||||
[app.common.geom.point :as gpt]
|
[app.common.geom.point :as gpt]
|
||||||
[app.common.geom.shapes :as gsh]
|
[app.common.geom.shapes :as gsh]
|
||||||
|
@ -92,12 +93,11 @@
|
||||||
(mf/with-memo [objects]
|
(mf/with-memo [objects]
|
||||||
(render/shape-wrapper-factory objects))
|
(render/shape-wrapper-factory objects))
|
||||||
|
|
||||||
text-shapes
|
is-text? (fn [shape] (= :text (:type shape)))
|
||||||
(->> objects
|
|
||||||
(filter (fn [[_ shape]] (= :text (:type shape))))
|
|
||||||
(mapv second))
|
|
||||||
|
|
||||||
render-texts? (and render-texts? (some #(nil? (:position-data %)) text-shapes))]
|
text-shapes (sequence (comp (map second) (filter is-text?)) objects)
|
||||||
|
|
||||||
|
render-texts? (and render-texts? (d/seek (comp nil? :position-data) text-shapes))]
|
||||||
|
|
||||||
(mf/with-effect [width height]
|
(mf/with-effect [width height]
|
||||||
(dom/set-page-style {:size (str (mth/ceil width) "px "
|
(dom/set-page-style {:size (str (mth/ceil width) "px "
|
||||||
|
|
|
@ -89,11 +89,11 @@
|
||||||
(cond
|
(cond
|
||||||
(contains? shape :fill-image)
|
(contains? shape :fill-image)
|
||||||
(let [fill-image-id (str "fill-image-" render-id)]
|
(let [fill-image-id (str "fill-image-" render-id)]
|
||||||
{:fill (str/format "url(#%s)" fill-image-id)})
|
{:fill (str "url(#" fill-image-id ")")})
|
||||||
|
|
||||||
(contains? shape :fill-color-gradient)
|
(contains? shape :fill-color-gradient)
|
||||||
(let [fill-color-gradient-id (str "fill-color-gradient_" render-id (if index (str "_" index) ""))]
|
(let [fill-color-gradient-id (str "fill-color-gradient_" render-id (if index (str "_" index) ""))]
|
||||||
{:fill (str/format "url(#%s)" fill-color-gradient-id)})
|
{:fill (str "url(#" fill-color-gradient-id ")")})
|
||||||
|
|
||||||
(contains? shape :fill-color)
|
(contains? shape :fill-color)
|
||||||
{:fill (:fill-color shape)}
|
{:fill (:fill-color shape)}
|
||||||
|
|
|
@ -45,19 +45,18 @@
|
||||||
(= :path (:type shape))
|
(= :path (:type shape))
|
||||||
(obj/set! "patternTransform" transform))]
|
(obj/set! "patternTransform" transform))]
|
||||||
|
|
||||||
[:*
|
(for [[shape-index shape] (d/enumerate (or (:position-data shape) [shape]))]
|
||||||
(for [[_shape-index shape] (d/enumerate (or (:position-data shape) [shape]))]
|
[:*
|
||||||
(for [[fill-index value] (-> (d/enumerate (:fills shape [])) reverse)]
|
(for [[fill-index value] (-> (d/enumerate (:fills shape [])) reverse)]
|
||||||
(cond (some? (:fill-color-gradient value))
|
(when (some? (:fill-color-gradient value))
|
||||||
(case (d/name (:type (:fill-color-gradient value)))
|
(let [props #js {:id (str "fill-color-gradient_" render-id "_" fill-index)
|
||||||
"linear" [:> grad/linear-gradient #js {:id (str "fill-color-gradient_" render-id "_" fill-index)
|
:gradient (:fill-color-gradient value)
|
||||||
:gradient (:fill-color-gradient value)
|
:shape shape}]
|
||||||
:shape shape}]
|
(case (d/name (:type (:fill-color-gradient value)))
|
||||||
"radial" [:> grad/radial-gradient #js {:id (str "fill-color-gradient_" render-id "_" fill-index)
|
"linear" [:> grad/linear-gradient props]
|
||||||
:gradient (:fill-color-gradient value)
|
"radial" [:> grad/radial-gradient props]))))
|
||||||
:shape shape}]))))
|
|
||||||
|
|
||||||
(for [[shape-index shape] (d/enumerate (or (:position-data shape) [shape]))]
|
|
||||||
(let [fill-id (str "fill-" shape-index "-" render-id)]
|
(let [fill-id (str "fill-" shape-index "-" render-id)]
|
||||||
[:> :pattern (-> (obj/clone pattern-attrs)
|
[:> :pattern (-> (obj/clone pattern-attrs)
|
||||||
(obj/set! "id" fill-id))
|
(obj/set! "id" fill-id))
|
||||||
|
@ -70,4 +69,4 @@
|
||||||
(when has-image
|
(when has-image
|
||||||
[:image {:xlinkHref (get embed uri uri)
|
[:image {:xlinkHref (get embed uri uri)
|
||||||
:width width
|
:width width
|
||||||
:height height}])]]))]))))
|
:height height}])]])])))))
|
||||||
|
|
|
@ -87,11 +87,22 @@
|
||||||
:caretColor (or text-color "black")
|
:caretColor (or text-color "black")
|
||||||
:overflowWrap "initial"}
|
:overflowWrap "initial"}
|
||||||
|
|
||||||
base (-> base
|
fills
|
||||||
(obj/set! "--fills" (transit/encode-str (:fills data)))
|
(cond
|
||||||
#_(obj/set! "--fill-color" fill-color)
|
(some? (:fills data))
|
||||||
#_(obj/set! "--fill-color-gradient" (transit/encode-str (:fill-color-gradient data)))
|
(:fills data)
|
||||||
#_(obj/set! "--fill-opacity" fill-opacity))]
|
|
||||||
|
(or (some? (:fill-color data))
|
||||||
|
(some? (:fill-opacity data))
|
||||||
|
(some? (:fill-color-gradient data)))
|
||||||
|
[(d/without-nils (select-keys data [:fill-color :fill-opacity :fill-color-gradient :fill-color-ref-id :fill-color-ref-file]))]
|
||||||
|
|
||||||
|
(nil? (:fills data))
|
||||||
|
[{:fill-color "#000000" :fill-opacity 1}])
|
||||||
|
|
||||||
|
base (cond-> base
|
||||||
|
(some? fills)
|
||||||
|
(obj/set! "--fills" (transit/encode-str fills)))]
|
||||||
|
|
||||||
(when (and (string? letter-spacing)
|
(when (and (string? letter-spacing)
|
||||||
(pos? (alength letter-spacing)))
|
(pos? (alength letter-spacing)))
|
||||||
|
|
|
@ -57,10 +57,9 @@
|
||||||
:textTransform (:text-transform data)
|
:textTransform (:text-transform data)
|
||||||
:textDecoration (:text-decoration data)
|
:textDecoration (:text-decoration data)
|
||||||
:fontStyle (:font-style data)
|
:fontStyle (:font-style data)
|
||||||
:direction (if (:rtl? data) "rtl" "ltr")
|
:direction (if (:rtl data) "rtl" "ltr")
|
||||||
:whiteSpace "pre"}
|
:whiteSpace "pre"}
|
||||||
(obj/set! "fill" (str "url(#fill-" index "-" render-id ")"))
|
(obj/set! "fill" (str "url(#fill-" index "-" render-id ")")))})]
|
||||||
#_(attrs/add-fill data (get-gradient-id index)))})]
|
|
||||||
[:& shape-custom-stroke {:shape shape :index index}
|
[:& shape-custom-stroke {:shape shape :index index}
|
||||||
[:> :text props (:text data)]]))]]))
|
[:> :text props (:text data)]]))]]))
|
||||||
|
|
||||||
|
|
|
@ -131,25 +131,26 @@
|
||||||
sid-ref (mf/use-ref nil)
|
sid-ref (mf/use-ref nil)
|
||||||
|
|
||||||
handle-change-foreign-object
|
handle-change-foreign-object
|
||||||
(fn [node]
|
(mf/use-callback
|
||||||
(when-let [position-data (utp/calc-position-data node)]
|
(fn [node]
|
||||||
(let [parent (dom/get-parent node)
|
(when-let [position-data (utp/calc-position-data node)]
|
||||||
parent-transform (dom/get-attribute parent "transform")
|
(let [parent (dom/get-parent node)
|
||||||
node-transform (dom/get-attribute node "transform")
|
parent-transform (dom/get-attribute parent "transform")
|
||||||
|
node-transform (dom/get-attribute node "transform")
|
||||||
|
|
||||||
parent-mtx (usvg/parse-transform parent-transform)
|
parent-mtx (usvg/parse-transform parent-transform)
|
||||||
node-mtx (usvg/parse-transform node-transform)
|
node-mtx (usvg/parse-transform node-transform)
|
||||||
|
|
||||||
;; We need to see what transformation is applied in the DOM to reverse it
|
;; We need to see what transformation is applied in the DOM to reverse it
|
||||||
;; before calculating the position data
|
;; before calculating the position data
|
||||||
mtx (-> (gmt/multiply parent-mtx node-mtx)
|
mtx (-> (gmt/multiply parent-mtx node-mtx)
|
||||||
(gmt/inverse))
|
(gmt/inverse))
|
||||||
|
|
||||||
position-data
|
position-data
|
||||||
(->> position-data
|
(->> position-data
|
||||||
(mapv #(merge % (-> (select-keys % [:x :y :width :height])
|
(mapv #(merge % (-> (select-keys % [:x :y :width :height])
|
||||||
(gsh/transform-rect mtx)))))]
|
(gsh/transform-rect mtx)))))]
|
||||||
(reset! local-position-data position-data))))
|
(reset! local-position-data position-data)))))
|
||||||
|
|
||||||
[node-ref on-change-node] (use-mutable-observer handle-change-foreign-object)
|
[node-ref on-change-node] (use-mutable-observer handle-change-foreign-object)
|
||||||
|
|
||||||
|
|
|
@ -22,9 +22,10 @@
|
||||||
(.setEnd range node end-i)
|
(.setEnd range node end-i)
|
||||||
(.getClientRects range)))
|
(.getClientRects range)))
|
||||||
|
|
||||||
|
;; TODO: Evaluate to change this function to Javascript
|
||||||
(defn parse-text-nodes
|
(defn parse-text-nodes
|
||||||
"Given a text node retrieves the rectangles for everyone of its paragraphs and its text."
|
"Given a text node retrieves the rectangles for everyone of its paragraphs and its text."
|
||||||
[parent-node rtl? text-node]
|
[parent-node rtl text-node]
|
||||||
|
|
||||||
(let [content (.-textContent text-node)
|
(let [content (.-textContent text-node)
|
||||||
text-size (.-length content)]
|
text-size (.-length content)]
|
||||||
|
@ -45,7 +46,7 @@
|
||||||
;; If the rects increase means we're in a new paragraph
|
;; If the rects increase means we're in a new paragraph
|
||||||
(if (> (.-length rects) 1)
|
(if (> (.-length rects) 1)
|
||||||
(let [entry {:node parent-node
|
(let [entry {:node parent-node
|
||||||
:position (dom/bounding-rect->rect (if rtl? (second rects) (first rects)))
|
:position (dom/bounding-rect->rect (if rtl (second rects) (first rects)))
|
||||||
:text current}]
|
:text current}]
|
||||||
(recur to-i to-i "" (conj result entry)))
|
(recur to-i to-i "" (conj result entry)))
|
||||||
(recur from-i (inc to-i) (str current (nth content to-i)) result)))))))
|
(recur from-i (inc to-i) (str current (nth content to-i)) result)))))))
|
||||||
|
@ -86,9 +87,9 @@
|
||||||
(->> text-nodes
|
(->> text-nodes
|
||||||
(mapcat
|
(mapcat
|
||||||
(fn [parent-node]
|
(fn [parent-node]
|
||||||
(let [rtl? (= "rtl" (.-dir (.-parentElement parent-node)))]
|
(let [rtl (= "rtl" (.-dir (.-parentElement parent-node)))]
|
||||||
(->> (.-childNodes parent-node)
|
(->> (.-childNodes parent-node)
|
||||||
(mapcat #(parse-text-nodes parent-node rtl? %))))))
|
(mapcat #(parse-text-nodes parent-node rtl %))))))
|
||||||
(mapv #(update % :position translate-rect))))))
|
(mapv #(update % :position translate-rect))))))
|
||||||
|
|
||||||
(defn calc-position-data
|
(defn calc-position-data
|
||||||
|
@ -101,15 +102,15 @@
|
||||||
(->> text-data
|
(->> text-data
|
||||||
(mapv (fn [{:keys [node position text]}]
|
(mapv (fn [{:keys [node position text]}]
|
||||||
(let [{:keys [x y width height]} position
|
(let [{:keys [x y width height]} position
|
||||||
rtl? (= "rtl" (.-dir (.-parentElement ^js node)))
|
rtl (= "rtl" (.-dir (.-parentElement ^js node)))
|
||||||
styles (js/getComputedStyle ^js node)
|
styles (js/getComputedStyle ^js node)
|
||||||
get (fn [prop]
|
get (fn [prop]
|
||||||
(let [value (.getPropertyValue styles prop)]
|
(let [value (.getPropertyValue styles prop)]
|
||||||
(when (and value (not= value ""))
|
(when (and value (not= value ""))
|
||||||
value)))]
|
value)))]
|
||||||
(d/without-nils
|
(d/without-nils
|
||||||
{:rtl? rtl?
|
{:rtl rtl
|
||||||
:x (if rtl? (+ x width) x)
|
:x (if rtl (+ x width) x)
|
||||||
:y (+ y height)
|
:y (+ y height)
|
||||||
:width width
|
:width width
|
||||||
:height height
|
:height height
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue