diff --git a/.gitignore b/.gitignore
index 7e3654e7d8..b4ea7ee77c 100644
--- a/.gitignore
+++ b/.gitignore
@@ -41,6 +41,7 @@
/backend/resources/public/assets
/backend/resources/public/media
/backend/target/
+/backend/experiments
/bundle*
/cd.md
/clj-profiler/
@@ -51,9 +52,6 @@
/exporter/target
/frontend/.storybook/preview-body.html
/frontend/.storybook/preview-head.html
-/frontend/cypress/fixtures/validuser.json
-/frontend/cypress/videos/*/
-/frontend/cypress/videos/*/
/frontend/dist/
/frontend/npm-debug.log
/frontend/out/
@@ -70,6 +68,8 @@
/vendor/svgclean/bundle*.js
/web
/library/target/
+/library/*.zip
+/external
clj-profiler/
node_modules
diff --git a/CHANGES.md b/CHANGES.md
index 941d414c0d..51a4e95d33 100644
--- a/CHANGES.md
+++ b/CHANGES.md
@@ -40,6 +40,7 @@
- Improve text layer auto-resize: auto-width switches to auto-height on horizontal resize, and only switches to fixed on vertical resize [Taiga #11578](https://tree.taiga.io/project/penpot/issue/11578)
- Highlight first font in font selector search. Apply only on Enter or click. [Taiga #11579](https://tree.taiga.io/project/penpot/issue/11579)
- Add the ability to show login dialog on profile settings [Github #6871](https://github.com/penpot/penpot/pull/6871)
+- Improve the application of tokens with object specific tokens [Taiga #10209](https://tree.taiga.io/project/penpot/us/10209)
### :bug: Bugs fixed
@@ -56,6 +57,9 @@
- Fix duplicating pages with mainInstance shapes nested inside groups [Taiga #10774](https://tree.taiga.io/project/penpot/issue/10774)
- Fix ESC key not closing Add/Manage Libraries modal [Taiga #11523](https://tree.taiga.io/project/penpot/issue/11523)
- Fix copying a shadow color from info tab [Taiga #11211](https://tree.taiga.io/project/penpot/issue/11211)
+- Fix remove color button in the gradient editor [Taiga #11623](https://tree.taiga.io/project/penpot/issue/11623)
+- Fix "Copy as SVG" generates different code from the Inspect panel [Taiga #11519](https://tree.taiga.io/project/penpot/issue/11519)
+- Fix overriden tokens in text copies are not preserved [Taiga #11486](https://tree.taiga.io/project/penpot/issue/11486)
## 2.8.1 (Unreleased)
diff --git a/common/src/app/common/types/container.cljc b/common/src/app/common/types/container.cljc
index 6c7e468314..c231ba222c 100644
--- a/common/src/app/common/types/container.cljc
+++ b/common/src/app/common/types/container.cljc
@@ -518,15 +518,31 @@
;; --- SHAPE UPDATE
(defn- get-token-groups
+ "Get the sync attrs groups that are affected by changes in applied tokens.
+
+ If any token has been applied or unapplied in the shape, calculate the corresponding
+ attributes and get the groups. If some of the attributes are to be applied in the
+ content nodes of a text shape, also return the content groups (only for attributes,
+ so the text is not touched)."
[shape new-applied-tokens]
- (let [old-applied-tokens (d/nilv (:applied-tokens shape) #{})
- changed-token-attrs (filter #(not= (get old-applied-tokens %) (get new-applied-tokens %))
- ctt/all-keys)
- changed-groups (into #{}
- (comp (map ctt/token-attr->shape-attr)
- (map #(get ctk/sync-attrs %))
- (filter some?))
- changed-token-attrs)]
+ (let [old-applied-tokens (d/nilv (:applied-tokens shape) #{})
+ changed-token-attrs (filter #(not= (get old-applied-tokens %) (get new-applied-tokens %))
+ ctt/all-keys)
+ text-shape? (= (:type shape) :text)
+ attrs-in-text-content? (some #(ctt/attrs-in-text-content %)
+ changed-token-attrs)
+
+ changed-groups (into #{}
+ (comp (map ctt/token-attr->shape-attr)
+ (map #(get ctk/sync-attrs %))
+ (filter some?))
+ changed-token-attrs)
+
+ changed-groups (if (and text-shape?
+ (d/not-empty? changed-groups)
+ attrs-in-text-content?)
+ (conj changed-groups :content-group :text-content-attribute)
+ changed-groups)]
changed-groups))
(defn set-shape-attr
diff --git a/common/src/app/common/types/token.cljc b/common/src/app/common/types/token.cljc
index 1f9cf0ace1..a08d7fd166 100644
--- a/common/src/app/common/types/token.cljc
+++ b/common/src/app/common/types/token.cljc
@@ -273,6 +273,13 @@
[attributes token-type]
(seq (appliable-attrs attributes token-type)))
+;; Token attrs that are set inside content blocks of text shapes, instead
+;; at the shape level.
+(def attrs-in-text-content
+ (set/union
+ typography-keys
+ #{:fill}))
+
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; TOKENS IN SHAPES
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
diff --git a/docs/technical-guide/getting-started/kubernetes.md b/docs/technical-guide/getting-started/kubernetes.md
index 142f498947..a3fac318e3 100644
--- a/docs/technical-guide/getting-started/kubernetes.md
+++ b/docs/technical-guide/getting-started/kubernetes.md
@@ -97,6 +97,11 @@ file itself, which you can use as a basis for creating your own settings.
You can also consult the list of parameters on the
ArtifactHub page of the project.
+### Using OpenShift?
+If you are deploying Penpot on OpenShift, we recommend following the specific guidelines provided in our Penpot-helm documentation:
+`Installing the chart with OpenShift requirements`
+
+Make sure to review the section **OpenShift Requirements** for important security and compatibility considerations.
## Upgrade Penpot
diff --git a/frontend/src/app/main/data/preview.cljs b/frontend/src/app/main/data/preview.cljs
index 7be41d6e2d..fc4d4ca5dd 100644
--- a/frontend/src/app/main/data/preview.cljs
+++ b/frontend/src/app/main/data/preview.cljs
@@ -80,8 +80,7 @@
(cb/format-code style-type)))
markup-code
- (-> (cg/generate-markup-code objects markup-type [shape])
- (cb/format-code markup-type))]
+ (cg/generate-formatted-markup-code objects markup-type [shape])]
(update-preview-window
preview
diff --git a/frontend/src/app/main/data/workspace/clipboard.cljs b/frontend/src/app/main/data/workspace/clipboard.cljs
index 202d1082da..9cf3ff1ccb 100644
--- a/frontend/src/app/main/data/workspace/clipboard.cljs
+++ b/frontend/src/app/main/data/workspace/clipboard.cljs
@@ -346,8 +346,8 @@
(gsh/translate-to-frame % (get objects parent-frame-id)))
shapes (mapv maybe-translate selected)
- svg (svg/generate-markup objects shapes)]
- (wapi/write-to-clipboard svg)))))
+ svg-formatted (svg/generate-formatted-markup objects shapes)]
+ (wapi/write-to-clipboard svg-formatted)))))
(defn copy-selected-css
[]
diff --git a/frontend/src/app/main/ui/inspect/attributes/text.cljs b/frontend/src/app/main/ui/inspect/attributes/text.cljs
index 5dab13e6b5..8ec9beba31 100644
--- a/frontend/src/app/main/ui/inspect/attributes/text.cljs
+++ b/frontend/src/app/main/ui/inspect/attributes/text.cljs
@@ -10,7 +10,8 @@
[app.common.data :as d]
[app.common.data.macros :as dm]
[app.common.types.fills :as types.fills]
- [app.common.types.text :as txt]
+ [app.common.types.text :as types.text]
+ [app.common.text :as txt]
[app.main.fonts :as fonts]
[app.main.refs :as refs]
[app.main.store :as st]
@@ -174,7 +175,7 @@
(let [style-text-blocks (->> (:content shape)
(txt/content->text+styles)
(remove (fn [[_ text]] (str/empty? (str/trim text))))
- (mapv (fn [[style text]] (vector (merge (txt/get-default-text-attrs) style) text))))]
+ (mapv (fn [[style text]] (vector (merge (types.text/get-default-text-attrs) style) text))))]
(for [[idx [full-style text]] (map-indexed vector style-text-blocks)]
[:& typography-block {:key idx
diff --git a/frontend/src/app/main/ui/inspect/code.cljs b/frontend/src/app/main/ui/inspect/code.cljs
index eaca3f114c..7268a120e6 100644
--- a/frontend/src/app/main/ui/inspect/code.cljs
+++ b/frontend/src/app/main/ui/inspect/code.cljs
@@ -149,8 +149,7 @@
(mf/use-memo
(mf/deps markup-type shapes images-data)
(fn []
- (-> (cg/generate-markup-code objects markup-type shapes)
- (cb/format-code markup-type))))
+ (cg/generate-formatted-markup-code objects markup-type shapes)))
on-markup-copied
(mf/use-fn
diff --git a/frontend/src/app/main/ui/settings/subscription.cljs b/frontend/src/app/main/ui/settings/subscription.cljs
index 2f2819c896..650e20e0df 100644
--- a/frontend/src/app/main/ui/settings/subscription.cljs
+++ b/frontend/src/app/main/ui/settings/subscription.cljs
@@ -6,7 +6,6 @@
[app.main.data.auth :as da]
[app.main.data.event :as ev]
[app.main.data.modal :as modal]
- [app.main.data.profile :as du]
[app.main.refs :as refs]
[app.main.repo :as rp]
[app.main.router :as rt]
@@ -319,12 +318,6 @@
(if (= success-modal-is-trial? "true")
(tr "subscription.settings.enterprise-trial")
(tr "subscription.settings.enterprise")))})
- (du/update-profile-props {:subscription
- (-> subscription
- (assoc :type (if (= params-subscription "subscribed-to-penpot-unlimited")
- "unlimited"
- "enterprise"))
- (assoc :status "trialing"))})
(rt/nav :settings-subscription {} {::rt/replace true})))))
[:section {:class (stl/css :dashboard-section)}
diff --git a/frontend/src/app/main/ui/workspace/colorpicker.cljs b/frontend/src/app/main/ui/workspace/colorpicker.cljs
index 72f08e4d91..1914b6c2ad 100644
--- a/frontend/src/app/main/ui/workspace/colorpicker.cljs
+++ b/frontend/src/app/main/ui/workspace/colorpicker.cljs
@@ -276,10 +276,9 @@
handle-gradient-remove-stop
(mf/use-fn
(mf/deps state)
- (fn [stop]
+ (fn [index]
(when (> (count (:stops state)) 2)
- (when-let [index (d/index-of-pred (:stops state) #(= % stop))]
- (st/emit! (dc/remove-gradient-stop index))))))
+ (st/emit! (dc/remove-gradient-stop index)))))
handle-stop-edit-start
(mf/use-fn
diff --git a/frontend/src/app/main/ui/workspace/colorpicker/gradients.cljs b/frontend/src/app/main/ui/workspace/colorpicker/gradients.cljs
index 93443d7c41..1d37da025f 100644
--- a/frontend/src/app/main/ui/workspace/colorpicker/gradients.cljs
+++ b/frontend/src/app/main/ui/workspace/colorpicker/gradients.cljs
@@ -80,10 +80,10 @@
handle-remove-stop
(mf/use-callback
- (mf/deps on-remove-stop stop)
+ (mf/deps on-remove-stop index)
(fn []
(when on-remove-stop
- (on-remove-stop stop))))
+ (on-remove-stop index))))
handle-focus-stop-offset
(mf/use-fn
diff --git a/frontend/src/app/plugins/api.cljs b/frontend/src/app/plugins/api.cljs
index 9e3e26c648..cc65f10883 100644
--- a/frontend/src/app/plugins/api.cljs
+++ b/frontend/src/app/plugins/api.cljs
@@ -410,7 +410,7 @@
:else
(let [objects (u/locate-objects)
shapes (into [] (map u/proxy->shape) shapes)]
- (cg/generate-markup-code objects type shapes)))))
+ (cg/generate-formatted-markup-code objects type shapes)))))
:generateStyle
(fn [shapes options]
diff --git a/frontend/src/app/util/code_gen.cljs b/frontend/src/app/util/code_gen.cljs
index 99c5a4e89c..953b61165a 100644
--- a/frontend/src/app/util/code_gen.cljs
+++ b/frontend/src/app/util/code_gen.cljs
@@ -6,6 +6,7 @@
(ns app.util.code-gen
(:require
+ [app.util.code-beautify :as cb]
[app.util.code-gen.markup-html :as html]
[app.util.code-gen.markup-svg :as svg]
[app.util.code-gen.style-css :as css]))
@@ -18,6 +19,11 @@
"svg" svg/generate-markup)]
(generate-markup objects shapes)))
+(defn generate-formatted-markup-code
+ [objects type shapes]
+ (let [markup (generate-markup-code objects type shapes)]
+ (cb/format-code markup type)))
+
(defn generate-style-code
([objects type root-shapes all-shapes]
(generate-style-code objects type root-shapes all-shapes nil))
diff --git a/frontend/src/app/util/code_gen/markup_svg.cljs b/frontend/src/app/util/code_gen/markup_svg.cljs
index a25177bee2..65044af6d7 100644
--- a/frontend/src/app/util/code_gen/markup_svg.cljs
+++ b/frontend/src/app/util/code_gen/markup_svg.cljs
@@ -8,6 +8,7 @@
(:require
["react-dom/server" :as rds]
[app.main.render :as render]
+ [app.util.code-beautify :as cb]
[cuerdas.core :as str]
[rumext.v2 :as mf]))
@@ -24,3 +25,8 @@
(->> shapes
(map #(generate-svg objects %))
(str/join "\n")))
+
+(defn generate-formatted-markup
+ [objects shapes]
+ (let [markup (generate-markup objects shapes)]
+ (cb/format-code markup "svg")))