diff --git a/frontend/src/app/main/ui/shapes/text/styles.cljs b/frontend/src/app/main/ui/shapes/text/styles.cljs
index 26db0e44b2..35f0126a95 100644
--- a/frontend/src/app/main/ui/shapes/text/styles.cljs
+++ b/frontend/src/app/main/ui/shapes/text/styles.cljs
@@ -74,16 +74,24 @@
font-size (:font-size data)
fill-color (or (-> data :fills first :fill-color) (:fill-color data))
fill-opacity (or (-> data :fills first :fill-opacity) (:fill-opacity data))
+ fill-gradient (or (-> data :fills first :fill-color-gradient) (:fill-color-gradient data))
[r g b a] (uc/hex->rgba fill-color fill-opacity)
text-color (when (and (some? fill-color) (some? fill-opacity))
(str/format "rgba(%s, %s, %s, %s)" r g b a))
+ gradient? (some? fill-gradient)
+
+ text-color (if gradient?
+ (uc/color->background {:gradient fill-gradient})
+ text-color)
+
fontsdb (deref fonts/fontsdb)
base #js {:textDecoration text-decoration
:textTransform text-transform
- :color (if show-text? text-color "transparent")
+ :color (if (and show-text? (not gradient?)) text-color "transparent")
+ :background (when (and show-text? gradient?) text-color)
:caretColor (or text-color "black")
:overflowWrap "initial"
:lineBreak "auto"
diff --git a/frontend/src/app/main/ui/viewer/inspect/code.cljs b/frontend/src/app/main/ui/viewer/inspect/code.cljs
index daa7fd7ad0..7738480630 100644
--- a/frontend/src/app/main/ui/viewer/inspect/code.cljs
+++ b/frontend/src/app/main/ui/viewer/inspect/code.cljs
@@ -32,6 +32,9 @@
[potok.core :as ptk]
[rumext.v2 :as mf]))
+(def embed-images? false)
+(def remove-localhost? true)
+
(def page-template
"
@@ -46,11 +49,13 @@
")
(defn format-code [code type]
- (let [code (-> code
- (str/replace "" "")
- (str/replace "><" ">\n<"))]
- (cond-> code
- (or (= type "svg") (= type "html")) (beautify/html #js {"indent_size" 2}))))
+ (cond-> code
+ (= type "svg")
+ (-> (str/replace "" "")
+ (str/replace "><" ">\n<"))
+
+ (or (= type "svg") (= type "html"))
+ (beautify/html #js {"indent_size" 2})))
(defn get-flex-elements [page-id shapes from]
(let [ids (mapv :id shapes)
@@ -189,7 +194,13 @@
(mf/use-callback
(mf/deps style-code markup-code images-data)
(fn []
- (let [markup-code (replace-map markup-code images-data)
+ (let [markup-code (cond-> markup-code
+ embed-images? (replace-map images-data))
+
+ style-code (cond-> style-code
+ remove-localhost?
+ (str/replace "http://localhost:3449" ""))
+
data (str/format page-template style-code markup-code)]
(wapi/write-to-clipboard data))))]
diff --git a/frontend/src/app/util/code_gen/markup_html.cljs b/frontend/src/app/util/code_gen/markup_html.cljs
index bdbdb5f218..2605d31d39 100644
--- a/frontend/src/app/util/code_gen/markup_html.cljs
+++ b/frontend/src/app/util/code_gen/markup_html.cljs
@@ -7,6 +7,7 @@
(ns app.util.code-gen.markup-html
(:require
["react-dom/server" :as rds]
+ [app.common.data :as d]
[app.common.data.macros :as dm]
[app.common.pages.helpers :as cph]
[app.common.types.shape.layout :as ctl]
@@ -17,6 +18,32 @@
[cuerdas.core :as str]
[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) :center)))))
+
(defn generate-html
([objects shape]
(generate-html objects shape 0))
@@ -26,6 +53,14 @@
maybe-reverse (if (ctl/any-layout? shape) reverse identity)]
(cond
+ (svg-markup? shape)
+ (let [svg-markup (generate-svg objects shape)]
+ (dm/fmt "%
\n%\n%
"
+ indent
+ (cgc/shape->selector shape)
+ svg-markup
+ indent))
+
(cph/text-shape? shape)
(let [text-shape-html (rds/renderToStaticMarkup (mf/element text/text-shape #js {:shape shape :code? true}))]
(dm/fmt "%\n%\n%
"
@@ -43,18 +78,6 @@
(cgc/shape->selector shape)
indent))
- (or (cph/path-shape? shape)
- (cph/mask-shape? shape)
- (cph/bool-shape? shape)
- (cph/svg-raw-shape? shape)
- (some? (:svg-attrs shape)))
- (let [svg-markup (generate-svg objects shape)]
- (dm/fmt "%\n%\n%
"
- indent
- (cgc/shape->selector shape)
- svg-markup
- indent))
-
(empty? (:shapes shape))
(dm/fmt "%\n%
"
indent
diff --git a/frontend/src/app/util/code_gen/style_css.cljs b/frontend/src/app/util/code_gen/style_css.cljs
index 7ab0968687..1b9fa1cf12 100644
--- a/frontend/src/app/util/code_gen/style_css.cljs
+++ b/frontend/src/app/util/code_gen/style_css.cljs
@@ -46,8 +46,7 @@ svg {
box-sizing: border-box;
}
-.text-node { background-clip: text;
- -webkit-background-clip: text; }
+.text-node { background-clip: text !important; -webkit-background-clip: text !important; }
")
diff --git a/frontend/src/app/util/code_gen/style_css_values.cljs b/frontend/src/app/util/code_gen/style_css_values.cljs
index 2b35577ad8..1dfc6d8dbc 100644
--- a/frontend/src/app/util/code_gen/style_css_values.cljs
+++ b/frontend/src/app/util/code_gen/style_css_values.cljs
@@ -11,15 +11,8 @@
[app.common.geom.matrix :as gmt]
[app.common.geom.shapes :as gsh]
[app.common.pages.helpers :as cph]
- [app.common.types.shape.layout :as ctl]))
-
-(defn svg-render?
- [shape]
- (or (cph/path-shape? shape)
- (cph/mask-shape? shape)
- (cph/bool-shape? shape)
- (cph/svg-raw-shape? shape)
- (some? (:svg-attrs shape))))
+ [app.common.types.shape.layout :as ctl]
+ [app.util.code-gen.markup-html :refer [svg-markup?]]))
(defn fill->color
[{:keys [fill-color fill-opacity fill-color-gradient]}]
@@ -107,21 +100,17 @@
(get-shape-size shape :height))
(defmethod get-value :transform
- [_ {:keys [transform] :as shape} objects]
- (let [transform
- (->> (cph/get-parents objects (:id shape))
- (reduce (fn [mtx {:keys [transform-inverse]}]
- (gmt/multiply transform-inverse mtx))
- transform))]
- (when (and (some? transform) (not (gmt/unit? transform)))
- (dm/str transform))))
+ [_ shape objects]
+ (let [parent (get objects (:parent-id shape))]
+ (dm/str (gmt/multiply (:transform shape (gmt/matrix))
+ (:transform-inverse parent (gmt/matrix))))))
(defmethod get-value :background
[_ {:keys [fills] :as shape} _]
(let [single-fill? (= (count fills) 1)
ffill (first fills)
gradient? (some? (:fill-color-gradient ffill))]
- (when (and (not (svg-render? shape)) single-fill? gradient?)
+ (when (and (not (svg-markup? shape)) single-fill? gradient?)
(fill->color ffill))))
(defmethod get-value :background-color
@@ -129,12 +118,12 @@
(let [single-fill? (= (count fills) 1)
ffill (first fills)
gradient? (some? (:fill-color-gradient ffill))]
- (when (and (not (svg-render? shape)) single-fill? (not gradient?))
+ (when (and (not (svg-markup? shape)) single-fill? (not gradient?))
(fill->color ffill))))
(defmethod get-value :background-image
[_ {:keys [fills] :as shape} _]
- (when (and (not (svg-render? shape)) (> (count fills) 1))
+ (when (and (not (svg-markup? shape)) (> (count fills) 1))
(->> fills
(map fill->color))))
@@ -153,7 +142,7 @@
(defmethod get-value :border
[_ shape _]
- (when-not (svg-render? shape)
+ (when-not (svg-markup? shape)
(get-stroke-data (first (:strokes shape)))))
(defmethod get-value :border-radius
@@ -170,11 +159,13 @@
(defmethod get-value :box-shadow
[_ shape _]
- (:shadow shape))
+ (when-not (svg-markup? shape)
+ (:shadow shape)))
(defmethod get-value :filter
[_ shape _]
- (get-in shape [:blur :value]))
+ (when-not (svg-markup? shape)
+ (get-in shape [:blur :value])))
(defmethod get-value :display
[_ shape _]
@@ -226,13 +217,13 @@
(defmethod get-value :row-gap
[_ shape _]
- (let [[g1 _] (ctl/gaps shape)]
- (when (not= g1 0) [g1])))
+ (let [[g1 g2] (ctl/gaps shape)]
+ (when (and (not= g1 g2) (not= g1 0)) [g1])))
(defmethod get-value :column-gap
[_ shape _]
- (let [[_ g2] (ctl/gaps shape)]
- (when (not= g2 0) [g2])))
+ (let [[g1 g2] (ctl/gaps shape)]
+ (when (and (not= g1 g2) (not= g2 0)) [g2])))
(defmethod get-value :padding
[_ {:keys [layout-padding]} _]