0
Fork 0
mirror of https://github.com/penpot/penpot.git synced 2025-02-18 21:06:11 -05:00

Merge pull request #3673 from penpot/alotor-codegen-fixes

🐛 Fix some cases for the html preview
This commit is contained in:
Aitor Moreno 2023-09-27 13:54:11 +02:00 committed by GitHub
commit 22d7ab9590
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 191 additions and 71 deletions

View file

@ -48,11 +48,11 @@
(beautify/html #js {"indent_size" 2}))) (beautify/html #js {"indent_size" 2})))
(defn update-preview-window (defn update-preview-window
[preview code] [preview code width height]
(when preview (when preview
(if (aget preview "load") (if (aget preview "load")
(.load preview code) (.load preview code width height)
(ts/schedule #(update-preview-window preview code))))) (ts/schedule #(update-preview-window preview code width height)))))
(defn shapes->fonts (defn shapes->fonts
[shapes] [shapes]
@ -92,7 +92,11 @@
(-> (cg/generate-markup-code objects markup-type [shape]) (-> (cg/generate-markup-code objects markup-type [shape])
(format-code markup-type))] (format-code markup-type))]
(update-preview-window preview (str/format page-template style-code markup-code)))))))))) (update-preview-window
preview
(str/format page-template style-code markup-code)
(-> shape :selrect :width)
(-> shape :selrect :height))))))))))
(defn open-preview-selected (defn open-preview-selected
[] []

View file

@ -8,6 +8,7 @@
(:require (:require
[app.main.data.events :as ev] [app.main.data.events :as ev]
[app.main.data.exports :as de] [app.main.data.exports :as de]
[app.main.data.preview :as dp]
[app.main.data.shortcuts :as ds] [app.main.data.shortcuts :as ds]
[app.main.data.workspace :as dw] [app.main.data.workspace :as dw]
[app.main.data.workspace.colors :as mdc] [app.main.data.workspace.colors :as mdc]
@ -539,8 +540,12 @@
:bool-exclude {:tooltip (ds/meta (ds/alt "E")) :bool-exclude {:tooltip (ds/meta (ds/alt "E"))
:command (ds/c-mod "alt+e") :command (ds/c-mod "alt+e")
:subsections [:shape] :subsections [:shape]
:fn #(emit-when-no-readonly (dw/create-bool :exclude))}} :fn #(emit-when-no-readonly (dw/create-bool :exclude))}
)
;; PREVIEW
:preview-frame {:tooltip (ds/meta (ds/alt ds/enter))
:command (ds/c-mod "alt+enter")
:fn #(emit-when-no-readonly (dp/open-preview-selected))}})
(def opacity-shortcuts (def opacity-shortcuts
(into {} (->> (into {} (->>

View file

@ -24,11 +24,13 @@
handle-load handle-load
(mf/use-callback (mf/use-callback
(fn [data] (fn [data width height]
(prn "handle-load" data) (prn "handle-load" data)
(reset! last-data* data) (reset! last-data* data)
(let [iframe-dom (mf/ref-val iframe-ref)] (let [iframe-dom (mf/ref-val iframe-ref)]
(when iframe-dom (when iframe-dom
(-> iframe-dom (aset "width" width))
(-> iframe-dom (aset "height" height))
(-> iframe-dom .-contentWindow .-document .open) (-> iframe-dom .-contentWindow .-document .open)
(-> iframe-dom .-contentWindow .-document (.write data)) (-> iframe-dom .-contentWindow .-document (.write data))
(-> iframe-dom .-contentWindow .-document .close))))) (-> iframe-dom .-contentWindow .-document .close)))))
@ -65,11 +67,5 @@
[:iframe {:ref load-ref [:iframe {:ref load-ref
:frameborder "0" :frameborder "0"
:scrolling "no" :scrolling "no"
:style {:width (str (* 100 (if (> zoom 1) :style {:transform-origin "top center"
(* 1 zoom)
(/ 1 zoom))) "%")
:height (str (* 100 (if (> zoom 1)
(* 1 zoom)
(/ 1 zoom))) "%")
:transform-origin "left top"
:transform (str "scale(" zoom ")")}}]]])) :transform (str "scale(" zoom ")")}}]]]))

View file

@ -6,7 +6,11 @@
(ns app.util.code-gen.common (ns app.util.code-gen.common
(:require (:require
[app.common.data :as d]
[app.common.data.macros :as dm] [app.common.data.macros :as dm]
[app.common.geom.matrix :as gmt]
[app.common.pages.helpers :as cph]
[app.common.types.shape.layout :as ctl]
[cuerdas.core :as str])) [cuerdas.core :as str]))
(defn shape->selector (defn shape->selector
@ -23,3 +27,36 @@
selector (if (str/starts-with? selector "-") (subs selector 1) selector)] selector (if (str/starts-with? selector "-") (subs selector 1) selector)]
selector) selector)
"")) ""))
(defn svg-markup?
"Function to determine whether a shape is rendered in HTML+CSS or is rendered
through a SVG"
[shape]
(or
;; path and path-like shapes
(cph/path-shape? shape)
(cph/bool-shape? shape)
;; imported SVG images
(cph/svg-raw-shape? shape)
(some? (:svg-attrs shape))
;; CSS masks are not enough we need to delegate to SVG
(cph/mask-shape? shape)
;; Texts with shadows or strokes we render in SVG
(and (cph/text-shape? shape)
(or (d/not-empty? (:shadow shape))
(d/not-empty? (:strokes shape))))
;; When a shape has several strokes or the stroke is not a "border"
(or (> (count (:strokes shape)) 1)
(and (= (count (:strokes shape)) 1)
(not= (-> shape :strokes first :stroke-alignment) :inner)))))
(defn has-wrapper?
[objects shape]
;; Layout children with a transform should be wrapped
(and (ctl/any-layout-immediate-child? objects shape)
(not (gmt/unit? (:transform shape)))))

View file

@ -18,32 +18,6 @@
[cuerdas.core :as str] [cuerdas.core :as str]
[rumext.v2 :as mf])) [rumext.v2 :as mf]))
(defn svg-markup?
"Function to determine whether a shape is rendered in HTML+CSS or is rendered
through a SVG"
[shape]
(or
;; path and path-like shapes
(cph/path-shape? shape)
(cph/bool-shape? shape)
;; imported SVG images
(cph/svg-raw-shape? shape)
(some? (:svg-attrs shape))
;; CSS masks are not enough we need to delegate to SVG
(cph/mask-shape? shape)
;; Texts with shadows or strokes we render in SVG
(and (cph/text-shape? shape)
(or (d/not-empty? (:shadow shape))
(d/not-empty? (:strokes shape))))
;; When a shape has several strokes or the stroke is not a "border"
(or (> (count (:strokes shape)) 1)
(and (= (count (:strokes shape)) 1)
(not= (-> shape :strokes first :stroke-alignment) :inner)))))
(defn generate-html (defn generate-html
([objects shape] ([objects shape]
(generate-html objects shape 0)) (generate-html objects shape 0))
@ -54,7 +28,7 @@
shape-html shape-html
(cond (cond
(svg-markup? shape) (cgc/svg-markup? shape)
(let [svg-markup (generate-svg objects shape)] (let [svg-markup (generate-svg objects shape)]
(dm/fmt "%<div class=\"%\">\n%\n%</div>" (dm/fmt "%<div class=\"%\">\n%\n%</div>"
indent indent
@ -98,7 +72,15 @@
(maybe-reverse) (maybe-reverse)
(map #(generate-html objects (get objects %) (inc level))) (map #(generate-html objects (get objects %) (inc level)))
(str/join "\n")) (str/join "\n"))
indent))] indent))
shape-html
(if (cgc/has-wrapper? objects shape)
(dm/fmt "<div class=\"%\">%</div>"
(dm/str (cgc/shape->selector shape) "-wrapper")
shape-html)
shape-html)]
(dm/fmt "%<!-- % -->\n%" indent (dm/str (d/name (:type shape)) ": " (:name shape)) shape-html)))) (dm/fmt "%<!-- % -->\n%" indent (dm/str (d/name (:type shape)) ": " (:name shape)) shape-html))))
(defn generate-markup (defn generate-markup

View file

@ -8,8 +8,11 @@
(:require (:require
[app.common.data :as d] [app.common.data :as d]
[app.common.data.macros :as dm] [app.common.data.macros :as dm]
[app.common.geom.matrix :as gmt]
[app.common.geom.shapes :as gsh]
[app.common.pages.helpers :as cph] [app.common.pages.helpers :as cph]
[app.common.text :as txt] [app.common.text :as txt]
[app.common.types.shape.layout :as ctl]
[app.main.ui.shapes.text.styles :as sts] [app.main.ui.shapes.text.styles :as sts]
[app.util.code-gen.common :as cgc] [app.util.code-gen.common :as cgc]
[app.util.code-gen.style-css-formats :refer [format-value]] [app.util.code-gen.style-css-formats :refer [format-value]]
@ -50,6 +53,19 @@ svg {
") ")
(def shape-wrapper-css-properties
#{:flex-shrink
:margin
:max-height
:min-height
:max-width
:min-width
:align-self
:justify-self
:grid-column
:grid-row
:z-index})
(def shape-css-properties (def shape-css-properties
[:position [:position
:left :left
@ -82,6 +98,7 @@ svg {
;; Flex related properties ;; Flex related properties
:flex-direction :flex-direction
:flex-wrap :flex-wrap
:flex
;; Grid related properties ;; Grid related properties
:grid-template-rows :grid-template-rows
@ -118,6 +135,24 @@ svg {
(when-let [value (get-value property shape objects)] (when-let [value (get-value property shape objects)]
[property value])) [property value]))
(defn shape->wrapper-css-properties
[shape objects]
(when (and (ctl/any-layout-immediate-child? objects shape)
(not (gmt/unit? (:transform shape))))
(let [{:keys [width height]} (gsh/shapes->rect [shape])]
(cond-> [[:position "relative"]
[:width width]
[:height height]]
(ctl/flex-layout-immediate-child? objects shape)
(conj [:flex-shrink 0])))))
(defn shape->wrapper-child-css-properties
[shape objects]
(when (and (ctl/any-layout-immediate-child? objects shape) (not (gmt/unit? (:transform shape))))
[[:position "absolute"]
[:left "50%"]
[:top "50%"]]))
(defn shape->css-properties (defn shape->css-properties
"Given a shape extract the CSS properties in the format of list [property value]" "Given a shape extract the CSS properties in the format of list [property value]"
[shape objects properties] [shape objects properties]
@ -143,9 +178,10 @@ svg {
(defn format-css-properties (defn format-css-properties
"Format a list of [property value] into a list of css properties in the format 'property: value;'" "Format a list of [property value] into a list of css properties in the format 'property: value;'"
[properties options] [properties options]
(->> properties (when properties
(map #(dm/str " " (format-css-property % options))) (->> properties
(str/join "\n"))) (map #(dm/str " " (format-css-property % options)))
(str/join "\n"))))
(defn get-shape-properties-css (defn get-shape-properties-css
([objects shape properties] ([objects shape properties]
@ -199,13 +235,40 @@ svg {
(get-shape-css-selector shape objects nil)) (get-shape-css-selector shape objects nil))
([shape objects options] ([shape objects options]
(let [properties (-> shape (let [selector (cgc/shape->selector shape)
(shape->css-properties objects shape-css-properties)
(format-css-properties options)) wrapper? (cgc/has-wrapper? objects shape)
selector (cgc/shape->selector shape)]
(str/join "\n" [(str/fmt "/* %s */" (:name shape)) css-properties
(if wrapper?
(filter (complement shape-wrapper-css-properties) shape-css-properties)
shape-css-properties)
properties
(-> shape
(shape->css-properties objects css-properties)
(format-css-properties options))
wrapper-properties
(when wrapper?
(-> (d/concat-vec
(shape->css-properties shape objects shape-wrapper-css-properties)
(shape->wrapper-css-properties shape objects))
(format-css-properties options)))
wrapper-child-properties
(when wrapper?
(-> shape
(shape->wrapper-child-css-properties objects)
(format-css-properties options)))]
(str/join
"\n"
(filter some? [(str/fmt "/* %s */" (:name shape))
(when wrapper? (str/fmt ".%s-wrapper {\n%s\n}" selector wrapper-properties))
(when wrapper? (str/fmt ".%s-wrapper > * {\n%s\n}" selector wrapper-child-properties))
(str/fmt ".%s {\n%s\n}" selector properties) (str/fmt ".%s {\n%s\n}" selector properties)
(when (cph/text-shape? shape) (generate-text-css shape))])))) (when (cph/text-shape? shape) (generate-text-css shape))])))))
(defn get-css-property (defn get-css-property
([objects shape property] ([objects shape property]

View file

@ -33,7 +33,6 @@
:margin :size-array :margin :size-array
:grid-template-rows :tracks :grid-template-rows :tracks
:grid-template-columns :tracks :grid-template-columns :tracks
:transform :matrix
}) })
(defmulti format-value (defmulti format-value

View file

@ -7,12 +7,14 @@
(ns app.util.code-gen.style-css-values (ns app.util.code-gen.style-css-values
(:require (:require
[app.common.data :as d]
[app.common.data.macros :as dm] [app.common.data.macros :as dm]
[app.common.geom.matrix :as gmt] [app.common.geom.matrix :as gmt]
[app.common.geom.shapes :as gsh] [app.common.geom.shapes :as gsh]
[app.common.pages.helpers :as cph] [app.common.pages.helpers :as cph]
[app.common.types.shape.layout :as ctl] [app.common.types.shape.layout :as ctl]
[app.util.code-gen.markup-html :refer [svg-markup?]])) [app.main.ui.formats :as fmt]
[app.util.code-gen.common :as cgc]))
(defn fill->color (defn fill->color
[{:keys [fill-color fill-opacity fill-color-gradient]}] [{:keys [fill-color fill-opacity fill-color-gradient]}]
@ -30,7 +32,7 @@
(not (ctl/layout-absolute? shape)) (not (ctl/layout-absolute? shape))
(or (cph/group-like-shape? shape) (or (cph/group-like-shape? shape)
(cph/frame-shape? shape) (cph/frame-shape? shape)
(svg-markup? shape))) (cgc/svg-markup? shape)))
(cph/root-frame? shape)) (cph/root-frame? shape))
:relative :relative
@ -66,14 +68,37 @@
[_ shape objects] [_ shape objects]
(get-shape-position shape objects :y)) (get-shape-position shape objects :y))
(defmethod get-value :flex
[_ shape objects]
(let [parent (cph/get-parent objects (:id shape))]
(when (and (ctl/flex-layout-immediate-child? objects shape)
(or (and (contains? #{:row :reverse-row} (:layout-flex-dir parent))
(= :fill (:layout-item-h-sizing shape)))
(and (contains? #{:column :column-row} (:layout-flex-dir parent))
(= :fill (:layout-item-v-sizing shape)))))
1)))
(defn get-shape-size (defn get-shape-size
[shape objects type] [shape objects type]
(let [sizing (if (= type :width) (let [parent (cph/get-parent objects (:id shape))
sizing (if (= type :width)
(:layout-item-h-sizing shape) (:layout-item-h-sizing shape)
(:layout-item-v-sizing shape))] (:layout-item-v-sizing shape))]
(cond (cond
(or (and (ctl/any-layout? shape) (= sizing :auto) (not (svg-markup? shape))) (and (ctl/flex-layout-immediate-child? objects shape)
(and (ctl/any-layout-immediate-child? objects shape) (= sizing :fill))) (or (and (= type :height)
(contains? #{:row :reverse-row} (:layout-flex-dir parent))
(= :fill (:layout-item-v-sizing shape)))
(and (= type :width)
(contains? #{:column :column-row} (:layout-flex-dir parent))
(= :fill (:layout-item-h-sizing shape)))))
:fill
(and (ctl/flex-layout-immediate-child? objects shape) (= sizing :fill))
nil
(or (and (ctl/any-layout? shape) (= sizing :auto) (not (cgc/svg-markup? shape)))
(and (ctl/grid-layout-immediate-child? objects shape) (= sizing :fill)))
sizing sizing
(some? (:selrect shape)) (some? (:selrect shape))
@ -92,21 +117,25 @@
(defmethod get-value :transform (defmethod get-value :transform
[_ shape objects] [_ shape objects]
(when-not (svg-markup? shape) (when-not (cgc/svg-markup? shape)
(let [parent (get objects (:parent-id shape)) (let [parent (get objects (:parent-id shape))
transform transform
(gmt/multiply (:transform shape (gmt/matrix)) (gmt/multiply (:transform shape (gmt/matrix))
(:transform-inverse parent (gmt/matrix)))] (:transform-inverse parent (gmt/matrix)))
(when-not (gmt/unit? transform)
transform)))) transform-str (when-not (gmt/unit? transform) (fmt/format-matrix transform))]
(if (cgc/has-wrapper? objects shape)
(dm/str "translate(-50%, -50%) " (d/nilv transform-str ""))
transform-str))))
(defmethod get-value :background (defmethod get-value :background
[_ {:keys [fills] :as shape} _] [_ {:keys [fills] :as shape} _]
(let [single-fill? (= (count fills) 1) (let [single-fill? (= (count fills) 1)
ffill (first fills) ffill (first fills)
gradient? (some? (:fill-color-gradient ffill))] gradient? (some? (:fill-color-gradient ffill))]
(when (and (not (svg-markup? shape)) (not (cph/group-shape? shape)) single-fill? gradient?) (when (and (not (cgc/svg-markup? shape)) (not (cph/group-shape? shape)) single-fill? gradient?)
(fill->color ffill)))) (fill->color ffill))))
(defmethod get-value :background-color (defmethod get-value :background-color
@ -114,12 +143,12 @@
(let [single-fill? (= (count fills) 1) (let [single-fill? (= (count fills) 1)
ffill (first fills) ffill (first fills)
gradient? (some? (:fill-color-gradient ffill))] gradient? (some? (:fill-color-gradient ffill))]
(when (and (not (svg-markup? shape)) (not (cph/group-shape? shape)) single-fill? (not gradient?)) (when (and (not (cgc/svg-markup? shape)) (not (cph/group-shape? shape)) single-fill? (not gradient?))
(fill->color ffill)))) (fill->color ffill))))
(defmethod get-value :background-image (defmethod get-value :background-image
[_ {:keys [fills] :as shape} _] [_ {:keys [fills] :as shape} _]
(when (and (not (svg-markup? shape)) (not (cph/group-shape? shape)) (> (count fills) 1)) (when (and (not (cgc/svg-markup? shape)) (not (cph/group-shape? shape)) (> (count fills) 1))
(->> fills (->> fills
(map fill->color)))) (map fill->color))))
@ -138,7 +167,7 @@
(defmethod get-value :border (defmethod get-value :border
[_ shape _] [_ shape _]
(when-not (svg-markup? shape) (when-not (cgc/svg-markup? shape)
(get-stroke-data (first (:strokes shape))))) (get-stroke-data (first (:strokes shape)))))
(defmethod get-value :border-radius (defmethod get-value :border-radius
@ -155,12 +184,12 @@
(defmethod get-value :box-shadow (defmethod get-value :box-shadow
[_ shape _] [_ shape _]
(when-not (svg-markup? shape) (when-not (cgc/svg-markup? shape)
(:shadow shape))) (:shadow shape)))
(defmethod get-value :filter (defmethod get-value :filter
[_ shape _] [_ shape _]
(when-not (svg-markup? shape) (when-not (cgc/svg-markup? shape)
(get-in shape [:blur :value]))) (get-in shape [:blur :value])))
(defmethod get-value :display (defmethod get-value :display
@ -258,8 +287,15 @@
(defmethod get-value :flex-shrink (defmethod get-value :flex-shrink
[_ shape objects] [_ shape objects]
(when (and (ctl/flex-layout-immediate-child? objects shape) (when (and (ctl/flex-layout-immediate-child? objects shape)
(not= :fill (:layout-item-h-sizing shape))
(not= :fill (:layout-item-v-sizing shape)) (not (and (contains? #{:row :reverse-row} (:layout-flex-dir shape))
(= :fill (:layout-item-h-sizing shape))))
(not (and (contains? #{:column :column-row} (:layout-flex-dir shape))
(= :fill (:layout-item-v-sizing shape))))
;;(not= :fill (:layout-item-h-sizing shape))
;;(not= :fill (:layout-item-v-sizing shape))
(not= :auto (:layout-item-h-sizing shape)) (not= :auto (:layout-item-h-sizing shape))
(not= :auto (:layout-item-v-sizing shape))) (not= :auto (:layout-item-v-sizing shape)))
0)) 0))
@ -336,5 +372,3 @@
(defmethod get-value :default (defmethod get-value :default
[property shape _] [property shape _]
(get shape property)) (get shape property))