diff --git a/CHANGES.md b/CHANGES.md
index fd01e4c3b1..09ea41efce 100644
--- a/CHANGES.md
+++ b/CHANGES.md
@@ -1,5 +1,11 @@
# CHANGELOG
+## 2.5.4 (Unreleased)
+
+### :sparkles: New features
+
+- Add support for WEBP format on shape export [Github #6053](https://github.com/penpot/penpot/pull/6053) and [Github #6074](https://github.com/penpot/penpot/pull/6074)
+
## 2.5.3
### :bug: Bugs fixed
diff --git a/common/src/app/common/types/shape/export.cljc b/common/src/app/common/types/shape/export.cljc
index bd2bee0a51..feb7f8dec6 100644
--- a/common/src/app/common/types/shape/export.cljc
+++ b/common/src/app/common/types/shape/export.cljc
@@ -8,7 +8,7 @@
(:require
[app.common.schema :as sm]))
-(def types #{:png :jpeg :svg :pdf})
+(def types #{:png :jpeg :webp :svg :pdf})
(def schema:export
[:map {:title "ShapeExport"}
diff --git a/docs/user-guide/exporting/index.njk b/docs/user-guide/exporting/index.njk
index 63f9d9fb24..d685a66834 100644
--- a/docs/user-guide/exporting/index.njk
+++ b/docs/user-guide/exporting/index.njk
@@ -27,7 +27,7 @@ title: 07ยท Exporting objects
- Size - Options for the most common sizing scales.
- Suffix - Especially useful if you are exporting at different scales.
- - File format - PNG, SVG, JPEG, PDF.
+ - File format - PNG, JPEG, WEBP, SVG, PDF.
Exporting multiple elements
diff --git a/exporter/src/app/renderer.cljs b/exporter/src/app/renderer.cljs
index b4abaca4bc..4a7cf8af73 100644
--- a/exporter/src/app/renderer.cljs
+++ b/exporter/src/app/renderer.cljs
@@ -15,7 +15,7 @@
(s/def ::name ::us/string)
(s/def ::suffix ::us/string)
-(s/def ::type #{:jpeg :png :pdf :svg})
+(s/def ::type #{:png :jpeg :webp :pdf :svg})
(s/def ::page-id ::us/uuid)
(s/def ::file-id ::us/uuid)
(s/def ::share-id ::us/uuid)
@@ -40,6 +40,7 @@
(case type
:png (rb/render params on-object)
:jpeg (rb/render params on-object)
+ :webp (rb/render params on-object)
:pdf (rp/render params on-object)
:svg (rs/render params on-object)))
diff --git a/exporter/src/app/renderer/bitmap.cljs b/exporter/src/app/renderer/bitmap.cljs
index 38022db739..750102af79 100644
--- a/exporter/src/app/renderer/bitmap.cljs
+++ b/exporter/src/app/renderer/bitmap.cljs
@@ -34,7 +34,11 @@
(bw/wait-for node)
(case type
:png (bw/screenshot node {:omit-background? true :type type :path path})
- :jpeg (bw/screenshot node {:omit-background? false :type type :path path}))
+ :jpeg (bw/screenshot node {:omit-background? false :type type :path path})
+ :webp (p/let [png-path (sh/tempfile :prefix "penpot.tmp.render.bitmap." :suffix ".png")]
+ ;; playwright only supports jpg and png, we need to convert it afterwards
+ (bw/screenshot node {:omit-background? true :type :png :path png-path})
+ (sh/run-cmd! (str "convert " png-path " -quality 100 WEBP:" path))))
(on-object (assoc object :path path))))
(render [uri page]
diff --git a/exporter/src/app/util/mime.cljs b/exporter/src/app/util/mime.cljs
index 18601cbd07..7bb0ce77c7 100644
--- a/exporter/src/app/util/mime.cljs
+++ b/exporter/src/app/util/mime.cljs
@@ -15,6 +15,7 @@
(case type
:png ".png"
:jpeg ".jpg"
+ :webp ".webp"
:svg ".svg"
:pdf ".pdf"
:zip ".zip"))
@@ -26,6 +27,7 @@
:pdf "application/pdf"
:svg "image/svg+xml"
:jpeg "image/jpeg"
- :png "image/png"))
+ :png "image/png"
+ :webp "image/webp"))
diff --git a/frontend/src/app/main/data/exports/assets.cljs b/frontend/src/app/main/data/exports/assets.cljs
index 1e800aee6d..b1f0293993 100644
--- a/frontend/src/app/main/data/exports/assets.cljs
+++ b/frontend/src/app/main/data/exports/assets.cljs
@@ -266,10 +266,10 @@
(defn export-shapes-event
[exports origin]
(let [types (reduce (fn [counts {:keys [type]}]
- (if (#{:png :pdf :svg :jpeg} type)
+ (if (#{:png :jpeg :webp :svg :pdf} type)
(update counts type inc)
counts))
- {:png 0, :pdf 0, :svg 0, :jpeg 0}
+ {:png 0, :jpeg 0, :webp 0, :pdf 0, :svg 0}
exports)]
(ptk/event
::ev/event (merge types
diff --git a/frontend/src/app/main/ui/inspect/exports.cljs b/frontend/src/app/main/ui/inspect/exports.cljs
index 8c5495ad1e..5f1aa2118e 100644
--- a/frontend/src/app/main/ui/inspect/exports.cljs
+++ b/frontend/src/app/main/ui/inspect/exports.cljs
@@ -37,7 +37,7 @@
scale-enabled?
(mf/use-callback
(fn [export]
- (#{:png :jpeg} (:type export))))
+ (#{:png :jpeg :webp} (:type export))))
in-progress? (:in-progress xstate)
@@ -123,6 +123,7 @@
format-options [{:value "png" :label "PNG"}
{:value "jpeg" :label "JPG"}
+ {:value "webp" :label "WEBP"}
{:value "svg" :label "SVG"}
{:value "pdf" :label "PDF"}]]
diff --git a/frontend/src/app/main/ui/inspect/exports.scss b/frontend/src/app/main/ui/inspect/exports.scss
index 8244d9e23f..f7365067c8 100644
--- a/frontend/src/app/main/ui/inspect/exports.scss
+++ b/frontend/src/app/main/ui/inspect/exports.scss
@@ -51,7 +51,7 @@
.element-group {
display: grid;
- grid-template-columns: repeat(8, 1fr);
+ grid-template-columns: repeat(9, 1fr);
column-gap: $s-4;
.action-btn {
@extend .button-tertiary;
@@ -64,13 +64,13 @@
}
.input-wrapper {
- grid-column: span 7;
+ grid-column: span 8;
display: grid;
grid-template-columns: subgrid;
}
.format-select {
- grid-column: span 2;
+ grid-column: span 3;
padding: 0;
.dropdown-upwards {
diff --git a/frontend/src/app/main/ui/workspace/sidebar/options/menus/exports.cljs b/frontend/src/app/main/ui/workspace/sidebar/options/menus/exports.cljs
index dd8908d76d..415d0295a1 100644
--- a/frontend/src/app/main/ui/workspace/sidebar/options/menus/exports.cljs
+++ b/frontend/src/app/main/ui/workspace/sidebar/options/menus/exports.cljs
@@ -53,7 +53,7 @@
scale-enabled?
(mf/use-fn
(fn [export]
- (#{:png :jpeg} (:type export))))
+ (#{:png :jpeg :webp} (:type export))))
on-download
(mf/use-fn
@@ -173,6 +173,7 @@
format-options [{:value "png" :label "PNG"}
{:value "jpeg" :label "JPG"}
+ {:value "webp" :label "WEBP"}
{:value "svg" :label "SVG"}
{:value "pdf" :label "PDF"}]]
diff --git a/frontend/src/app/main/ui/workspace/sidebar/options/menus/exports.scss b/frontend/src/app/main/ui/workspace/sidebar/options/menus/exports.scss
index 6bf3152dd4..0f9aae670e 100644
--- a/frontend/src/app/main/ui/workspace/sidebar/options/menus/exports.scss
+++ b/frontend/src/app/main/ui/workspace/sidebar/options/menus/exports.scss
@@ -32,18 +32,18 @@
.element-group {
display: grid;
- grid-template-columns: repeat(8, 1fr);
+ grid-template-columns: repeat(9, 1fr);
column-gap: $s-4;
}
.input-wrapper {
- grid-column: span 7;
+ grid-column: span 8;
display: grid;
grid-template-columns: subgrid;
}
.format-select {
- grid-column: span 2;
+ grid-column: span 3;
padding: 0;
.dropdown-upwards {
diff --git a/frontend/src/app/plugins/format.cljs b/frontend/src/app/plugins/format.cljs
index 829476da0b..6555f6a367 100644
--- a/frontend/src/app/plugins/format.cljs
+++ b/frontend/src/app/plugins/format.cljs
@@ -261,7 +261,7 @@
:hidden hidden})))
;; export interface Export {
-;; type: 'png' | 'jpeg' | 'svg' | 'pdf';
+;; type: 'png' | 'jpeg' | 'webp' | 'svg' | 'pdf';
;; scale: number;
;; suffix: string;
;; }
diff --git a/frontend/src/app/plugins/parser.cljs b/frontend/src/app/plugins/parser.cljs
index 8d884350dd..0ce6aad418 100644
--- a/frontend/src/app/plugins/parser.cljs
+++ b/frontend/src/app/plugins/parser.cljs
@@ -243,7 +243,7 @@
;; export interface Export {
-;; type: 'png' | 'jpeg' | 'svg' | 'pdf';
+;; type: 'png' | 'jpeg' | 'webp' | 'svg' | 'pdf';
;; scale: number;
;; suffix: string;
;; }