Merge remote-tracking branch 'origin/staging' into develop

This commit is contained in:
Andrey Antukh 2026-08-05 17:30:41 +02:00
commit 5b26913cd3
7 changed files with 112 additions and 20 deletions

View File

@ -8,8 +8,7 @@
"author": "Andrey Antukh",
"license": "MPL-2.0",
"dependencies": {
"draft-js": "penpot/draft-js.git#c58ebd9429a6359d72a88cff87e078aaf6fe285d",
"immutable": "^5.1.9"
"draft-js": "penpot/draft-js.git#c58ebd9429a6359d72a88cff87e078aaf6fe285d"
},
"peerDependencies": {
"react": ">=0.17.0",

View File

@ -18,7 +18,6 @@ overrides:
postcss@<8.5.10: ^8.5.10
yaml@>=2.0.0 <2.8.3: ^2.8.3
playwright@>=1.61.1 <2.0.0-0: 1.62.1
immutable@<4.3.9: ^4.3.9
patchedDependencies:
'@zip.js/zip.js@2.8.34': 7b556bbd426f152eb086f0126a53900e369a95cf64357c380b7c8d8e940c3d95
@ -271,9 +270,6 @@ importers:
draft-js:
specifier: penpot/draft-js.git#c58ebd9429a6359d72a88cff87e078aaf6fe285d
version: https://codeload.github.com/penpot/draft-js/tar.gz/c58ebd9429a6359d72a88cff87e078aaf6fe285d(encoding@0.1.13)(react-dom@19.2.8(react@19.2.8))(react@19.2.8)
immutable:
specifier: ^5.1.9
version: 5.1.9
react:
specifier: '>=0.17.0'
version: 19.2.8
@ -2193,6 +2189,11 @@ packages:
'@volar/typescript@2.4.28':
resolution: {integrity: sha512-Ja6yvWrbis2QtN4ClAKreeUZPVYMARDYZl9LMEv1iQ1QdepB6wn0jTRxA9MftYmYa4DQ4k/DaSZpFPUfxl8giw==}
peerDependencies:
typescript: '*'
peerDependenciesMeta:
typescript:
optional: true
'@webcontainer/env@1.1.1':
resolution: {integrity: sha512-6aN99yL695Hi9SuIk1oC88l9o0gmxL1nGWWQ/kNy81HigJ0FoaoTXpytCj6ItzgyCEwA9kF1wixsTuv5cjsgng==}
@ -3510,8 +3511,9 @@ packages:
resolution: {integrity: sha512-BAg6QkE8W+TuQLrrw0Ugr7HegXduRuuj8/ti2kSOc+jz1dmx8/WNcjr6XGnq5YpDWxFwwaavqD0+jIUOKelTsw==}
engines: {node: '>= 4'}
immutable@4.3.9:
resolution: {integrity: sha512-ObHy4YN7ycwZOUCLI1/6svfyAFu7vL8RhAvVu/bh/RZW9EPlOyDaQ9jDQWCtdqzaXUjgXZCW1migtHE7YI7UGQ==}
immutable@3.8.3:
resolution: {integrity: sha512-AUY/VyX0E5XlibOmWt10uabJzam1zlYjwiEgQSDc5+UIkFNaF9WM0JxXKaNMGf+F/ffUF+7kRKXM9A7C0xXqMg==}
engines: {node: '>=0.10.0'}
immutable@5.1.9:
resolution: {integrity: sha512-m8nVez3rwrgmWxtLMt1ZYXB2Lv7OKYn/disyxAlSDYAlKSlFoPPfIAmAM/M5xqL4m4C/wAPw7S2/CNaUii1Hxg==}
@ -7559,11 +7561,13 @@ snapshots:
'@volar/source-map@2.4.28': {}
'@volar/typescript@2.4.28':
'@volar/typescript@2.4.28(typescript@6.0.3)':
dependencies:
'@volar/language-core': 2.4.28
path-browserify: 1.0.1
vscode-uri: 3.1.0
optionalDependencies:
typescript: 6.0.3
'@webcontainer/env@1.1.1': {}
@ -8332,7 +8336,7 @@ snapshots:
draft-js@https://codeload.github.com/penpot/draft-js/tar.gz/c58ebd9429a6359d72a88cff87e078aaf6fe285d(encoding@0.1.13)(react-dom@19.2.8(react@19.2.8))(react@19.2.8):
dependencies:
fbjs: 3.0.5(encoding@0.1.13)
immutable: 4.3.9
immutable: 3.8.3
object-assign: 4.1.1
react: 19.2.8
react-dom: 19.2.8(react@19.2.8)
@ -9081,7 +9085,7 @@ snapshots:
ignore@7.0.6: {}
immutable@4.3.9: {}
immutable@3.8.3: {}
immutable@5.1.9: {}
@ -11197,7 +11201,7 @@ snapshots:
unplugin-dts@1.0.3(@microsoft/api-extractor@7.56.2(@types/node@26.1.2))(esbuild@0.28.1)(rolldown@1.2.1)(rollup@4.61.1)(supports-color@10.2.2)(typescript@6.0.3)(vite@8.2.0(@types/node@26.1.2)(esbuild@0.28.1)(sass-embedded@1.100.0)(sass@1.102.0)):
dependencies:
'@rollup/pluginutils': 5.4.0(rollup@4.61.1)
'@volar/typescript': 2.4.28
'@volar/typescript': 2.4.28(typescript@6.0.3)
compare-versions: 6.1.1
debug: 4.4.3(supports-color@10.2.2)
kolorist: 1.8.0

View File

@ -32,4 +32,3 @@ overrides:
postcss@<8.5.10: ^8.5.10
yaml@>=2.0.0 <2.8.3: ^2.8.3
playwright@>=1.61.1 <2.0.0-0: "1.62.1"
immutable@<4.3.9: ^4.3.9

View File

@ -15,6 +15,7 @@
["react-dom/server" :as rds]
[app.common.data :as d]
[app.common.data.macros :as dm]
[app.common.exceptions :as ex]
[app.common.files.helpers :as cfh]
[app.common.geom.point :as gpt]
[app.common.geom.rect :as grc]
@ -59,6 +60,7 @@
[rumext.v2 :as mf]))
(def ^:const viewbox-decimal-precision 3)
(def ^:const max-export-dimension 100000)
(def ^:private default-color clr/canvas)
(mf/defc background
@ -82,12 +84,20 @@
(let [bounds
(->> root-objects
(map (partial gsb/get-object-bounds objects))
(grc/join-rects))]
(grc/join-rects))
bounds (-> bounds
(update :x mth/finite 0)
(update :y mth/finite 0)
(update :width mth/finite 100000)
(update :height mth/finite 100000))]
(when (or (> (:width bounds) max-export-dimension)
(> (:height bounds) max-export-dimension)
(> (+ (:x bounds) (:width bounds)) max-export-dimension)
(> (+ (:y bounds) (:height bounds)) max-export-dimension))
(ex/raise :type :validation
:code :export-area-too-large
:hint "export area exceeds maximum allowed dimensions"))
(-> bounds
(update :x mth/finite 0)
(update :y mth/finite 0)
(update :width mth/finite 100000)
(update :height mth/finite 100000)
(grc/update-rect :position)
(grc/fix-aspect-ratio aspect-ratio))))))

View File

@ -734,8 +734,8 @@
display: flex;
justify-content: center;
align-items: center;
width: $sz-32;
height: $sz-32;
width: $sz-48;
height: $sz-48;
&:hover {
--icon-stroke: var(--color-accent-primary);

View File

@ -0,0 +1,78 @@
;; This Source Code Form is subject to the terms of the Mozilla Public
;; License, v. 2.0. If a copy of the MPL was not distributed with this
;; file, You can obtain one at http://mozilla.org/MPL/2.0/.
;;
;; Copyright (c) KALEIDOS INC Sucursal en España SL
(ns frontend-tests.render-dimensions-test
(:require
[app.common.geom.rect :as grc]
[app.common.geom.shapes.bounds :as gsb]
[app.common.test-helpers.files :as cthf]
[app.common.test-helpers.ids-map :as cthi]
[app.common.test-helpers.shapes :as cths]
[app.common.types.shape :as cts]
[app.common.uuid :as uuid]
[app.main.render :as render]
[cljs.test :as t :include-macros true]))
(defn- make-objects
"Create a proper objects map with a root frame and the given shapes."
[& shapes]
(let [root-frame (cts/setup-shape {:id uuid/zero
:type :frame
:parent-id uuid/zero
:frame-id uuid/zero
:name "Root Frame"
:shapes (mapv :id shapes)})
objects {uuid/zero root-frame}]
(reduce (fn [objs shape]
(assoc objs (:id shape) (assoc shape :frame-id uuid/zero)))
objects
shapes)))
(t/deftest calculate-dimensions-normal-bounds
(t/testing "Normal bounding box should pass"
(let [shape1 (cts/setup-shape {:type :rect :x 100 :y 100 :width 200 :height 150})
shape2 (cts/setup-shape {:type :rect :x 400 :y 300 :width 100 :height 100})
objects (make-objects shape1 shape2)
result (render/calculate-dimensions objects nil)]
(t/is (some? result))
(t/is (<= (:width result) render/max-export-dimension))
(t/is (<= (:height result) render/max-export-dimension)))))
(t/deftest calculate-dimensions-extreme-width
(t/testing "Extreme width should throw export-area-too-large"
(let [shape (cts/setup-shape {:type :rect :x 0 :y 0 :width 200000 :height 100})
objects (make-objects shape)]
(t/is (thrown-with-msg?
js/Error
#"export area exceeds maximum allowed dimensions"
(render/calculate-dimensions objects nil))))))
(t/deftest calculate-dimensions-extreme-height
(t/testing "Extreme height should throw export-area-too-large"
(let [shape (cts/setup-shape {:type :rect :x 0 :y 0 :width 100 :height 200000})
objects (make-objects shape)]
(t/is (thrown-with-msg?
js/Error
#"export area exceeds maximum allowed dimensions"
(render/calculate-dimensions objects nil))))))
(t/deftest calculate-dimensions-extreme-position
(t/testing "Shape at extreme position should throw export-area-too-large"
(let [shape (cts/setup-shape {:type :rect :x 500000 :y 500000 :width 100 :height 100})
objects (make-objects shape)]
(t/is (thrown-with-msg?
js/Error
#"export area exceeds maximum allowed dimensions"
(render/calculate-dimensions objects nil))))))
(t/deftest calculate-dimensions-exactly-at-limit
(t/testing "Bounding box exactly at limit should pass"
(let [shape (cts/setup-shape {:type :rect :x 0 :y 0 :width render/max-export-dimension :height render/max-export-dimension})
objects (make-objects shape)
result (render/calculate-dimensions objects nil)]
(t/is (some? result))
(t/is (<= (:width result) render/max-export-dimension))
(t/is (<= (:height result) render/max-export-dimension)))))

View File

@ -51,6 +51,7 @@
[frontend-tests.plugins.tokens-test]
[frontend-tests.plugins.utils-test]
[frontend-tests.plugins.value-objects-test]
[frontend-tests.render-dimensions-test]
[frontend-tests.render-wasm.process-objects-test]
[frontend-tests.render-wasm.text-editor-apply-styles-test]
[frontend-tests.render-wasm.text-editor-caret-color-test]
@ -162,6 +163,7 @@
'frontend-tests.ui.gradient-handlers-test
'frontend-tests.ui.layout-container-multiple-test
'frontend-tests.ui.measures-menu-props-test
'frontend-tests.render-dimensions-test
'frontend-tests.text-editor-paste-guard-test
'frontend-tests.ui.settings-password-schema-test
'frontend-tests.ui.settings-shortcuts-test