Compare commits

..

3422 Commits

Author SHA1 Message Date
Andrey Antukh
5abc1aafb4 Merge tag '2.12.0-RC3' 2025-12-12 12:19:29 +01:00
Andrey Antukh
2f46cbc0d4 Make render wasm import on worker http cache aware 2025-12-11 13:27:20 +01:00
Andrey Antukh
53be6f996b 🐛 Fix issues on build processs related to render-wasm 2025-12-11 12:41:19 +01:00
Andrey Antukh
5a260294a1 🔧 Update build-tag.yml github workflow 2025-12-11 12:00:42 +01:00
Andrey Antukh
3f6e44316e 🐛 Add missing node depes install on render-wasm 2025-12-11 11:51:47 +01:00
Eva Marco
77ef8e6fe6 🐛 Fix scroll on move library modal (#7952) 2025-12-11 10:46:54 +01:00
Alejandro Alonso
916b7709dc Update Pencil Penpot Design System System template in carousel (#7948) 2025-12-10 15:09:28 +01:00
Eva Marco
443e41fea4 🐛 Fix multiple selection with color tokens (#7941) 2025-12-10 14:36:08 +01:00
Alejandro Alonso
c7c9b04095 Merge pull request #7944 from penpot/niwinz-staging-exporter-fix
🐛 Fix incorrect resource lifetime handling on exporter
2025-12-10 14:35:20 +01:00
Eva Marco
c61a0c0332 📚 Add line to changelog (#7945) 2025-12-10 13:58:18 +01:00
Eva Marco
8707ff6511 🎉 Add spanish translation 2025-12-10 13:12:30 +01:00
Florian Schroedl
3d8a251741 🐛 Disallow font-family referencing composite token 2025-12-10 13:12:30 +01:00
Andrey Antukh
34e84ee3c8 🐛 Fix incorrect resource lifetime handling on exporter 2025-12-10 13:02:31 +01:00
Alejandro Alonso
e8201402a7 Merge pull request #7938 from penpot/niwinz-staging-bugfix-5
🐛 Fix several issues
2025-12-10 12:05:42 +01:00
Aitor Moreno
8a22477b96 Merge pull request #7932 from penpot/niwinz-staging-worker-wasm-load
🐛 Fix WASM loading strategy on worker
2025-12-10 11:47:31 +01:00
Alejandro Alonso
3e684ea54f ⬆️ Update svgo dependency on frontend (#7936) 2025-12-10 10:07:02 +01:00
Andrey Antukh
98039f13d8 🐛 Fix main toolbar z-index 2025-12-10 09:47:40 +01:00
Alejandro Alonso
40c27591f6 🐛 Fix svg import (#7925) 2025-12-10 08:36:54 +01:00
Andrey Antukh
91d20a46d1 💄 Add cosmetic changes to exports assets progress component 2025-12-10 08:23:05 +01:00
Andrey Antukh
50bead7c56 🐛 Fix react warning on having p inside p on assets export progress 2025-12-10 08:22:41 +01:00
Andrey Antukh
b75b999903 📎 Fix devenv jvm warning 2025-12-10 08:22:05 +01:00
Andrey Antukh
810f1721c8 🐛 Fix recursion render on subscription modal 2025-12-10 07:54:52 +01:00
Andrey Antukh
a4646373cf ♻️ Refactor wasm loading strategy on worker 2025-12-09 19:41:19 +01:00
Andrey Antukh
f111cbb2a4 Add better cache config on devenv nginx 2025-12-09 19:38:30 +01:00
Aitor Moreno
a614207f7e 🐛 Fix exporter failing with HTTPS 2025-12-09 16:08:20 +01:00
Luis de Dios
6ce3249c6d 🐛 Fix color format does not switch in the view mode (#7923)
* 🐛 Fix color format does not switch in the inspect mode of the view mode

* ♻️ Update components
2025-12-09 14:38:15 +01:00
Pablo Alba
b0351be724 🐛 Fix switch variants with paths 2025-12-09 11:08:55 +01:00
Andrey Antukh
b8392b3731 🐛 Fix regression on sending team invitations (#7912) 2025-12-05 12:36:06 +01:00
Andrey Antukh
935728aa39 🔧 Backport build-tag github workflow from develop 2025-12-05 10:26:01 +01:00
Andrey Antukh
77dba477ca 🔧 Backport build-tag github workflow from develop 2025-12-05 10:25:03 +01:00
Eva Marco
b6598d1f07 🐛 Fix scrollbar on color modal (#7906) 2025-12-05 09:55:41 +01:00
Xaviju
bf1dc21c75 💄 Hide themes & sets panels when none active (#7902) 2025-12-04 14:11:57 +01:00
Alejandro Alonso
46c20a993f Merge pull request #7904 from penpot/niwinz-staging-fix-invitation-resend
🐛 Fix exception on resending invitation
2025-12-04 11:56:07 +01:00
Andrey Antukh
0e0106f69a 🐛 Add correct assertion on create-invitation fn 2025-12-04 11:38:32 +01:00
Andrey Antukh
19bb69cc60 Improve invalid schema error report 2025-12-04 11:38:16 +01:00
Alejandro Alonso
504eb70988 Merge pull request #7885 from penpot/niwinz-staging-bugfix-2
🐛 Make workspace palette reposition on left sidebar collapse
2025-12-04 11:19:20 +01:00
Xaviju
75a2331edf 💄 Set low-emphasis color for both light/dark modes (#7884) 2025-12-04 11:04:07 +01:00
Alejandro Alonso
c2b4c9907d Merge pull request #7886 from penpot/niwinz-staging-bugfix-3
🐛 Fix casing on a translation of export files modal option
2025-12-04 10:59:51 +01:00
Alejandro Alonso
bd5bbcae26 Merge pull request #7894 from penpot/niwinz-staging-bugfix-4
🐛 Fix incorrect interaction betwen hower and scroll on assets sidebar
2025-12-04 10:58:54 +01:00
Andrey Antukh
84273508ad 🐛 Fix incorrect interaction betwen hower and scroll on assets sidebar 2025-12-04 10:56:29 +01:00
Andrey Antukh
9245ba6bc2 💄 Adapt component style for assets-local-library on sidebar assets 2025-12-04 10:55:57 +01:00
Andrey Antukh
4be046406d Pass direct args instead of a vector to toggle-values on sidebar assets 2025-12-04 10:55:57 +01:00
Alejandro Alonso
84c747cd31 Merge pull request #7883 from penpot/niwinz-staging-bugfix
🐛 Fix exception on paste text on comments input
2025-12-04 10:32:07 +01:00
Alejandro Alonso
0036a9a0cd Merge pull request #7865 from penpot/niwinz-staging-audit
 Add minor improvements to the audit module
2025-12-04 10:04:00 +01:00
Alejandro Alonso
2105c3a68c Merge pull request #7866 from penpot/niwinz-staging-fix-emails
🐛 Change internal ordering on how email parts are assembled
2025-12-04 09:56:22 +01:00
Belén Albeza
38efa88460 🐛 Fix unpublish library modal not scrolling file list (#7892)
* 🐛 Fix unpublish library modal not scrolling when the linked files list is too long

* 💄 Remove deprecated tokens in unpublish library modal

* 🔧 Update CHANGELOG
2025-12-03 22:41:20 +01:00
Pablo Alba
6e254c2cf4 🐛 Fix change of library on swap (#7898) 2025-12-03 22:40:23 +01:00
Andrey Antukh
6251fa6b22 🐛 Close other open context menus on open a context menu (#7895) 2025-12-03 18:50:00 +01:00
alonso.torres
aedd8cc11e 🐛 Fix problem when renaming variants in plugins 2025-12-03 17:42:17 +01:00
Alonso Torres
2f0853f5cc 🐛 Fix problem with variant plugins api (#7890) 2025-12-03 13:27:32 +01:00
Juan de la Cruz
648e660bcf 🎉 Add new content and images for the slides of 2.12 (#7874)
* 🎉 Add new slide's content

* 🎉 Add new slides images

* 📎 Fix clj fmt

---------

Co-authored-by: Andrey Antukh <niwi@niwi.nz>
2025-12-03 13:26:55 +01:00
Slava "nerfur" Voronzoff
bee2f70bfa 🐛 Add missing amd64 option on arch detection code on mange.sh script
Signed-off-by: Slava "nerfur" Voronzoff <nerfur@gmail.com>
2025-12-03 13:09:49 +01:00
Pablo Alba
00f8eac8fa 🐛 Fix can't delete unsaved variant prop (#7878) 2025-12-03 13:03:17 +01:00
Dalai Felinto
df7caacb45 🐛 Fix crash in token grid view due to tooltip validation (#7887)
The color tokens in grid view have a tooltip which is a map.
This is done so the frontend can render:

```
Name: foo
Resolved value: #000000
```

However the validation scheme for tooltips was only accepting functions
and strings.

---

How to reproduce the original (unreported) crash:
* Create a color token
* Create a shape, add a fill
* Pick a color, chose the Token options
* Click on the Grid View

Crash: `{:hint "invalid props on component tooltip*\n\n  -> 'content'
    should be a string\n"}`

Signed-off-by: Dalai Felinto <dalai@blender.org>
Co-authored-by: Dalai Felinto <dalai@blender.org>
2025-12-03 13:01:36 +01:00
Marina López
49bbdfb257 🐛 Fix U and E icon displayed in project list (#7875)
* 🐛 Fix U and E icon displayed in project lis

* 🐛 Fix U and E icon displayed in project list
2025-12-03 12:50:51 +01:00
Andrey Antukh
94af978be8 🐛 Fix casing on a translation of export files modal option 2025-12-03 10:22:45 +01:00
Andrey Antukh
feababe2a8 🐛 Make workspace palette reposition on left sidebar collapse 2025-12-03 09:56:14 +01:00
Andrey Antukh
5ef06685fc 💄 Add cosmetic improvements to workspace palette component 2025-12-03 09:38:23 +01:00
Andrey Antukh
57fcec5afc 🐛 Make from-synthetic-clipboard-event function return always a stream
Causes an execption on steam processing when it returns nil
2025-12-03 08:32:38 +01:00
Andrey Antukh
58f82da61e 🐛 Fix exception on paste text on comments input 2025-12-03 08:20:58 +01:00
Andrey Antukh
a28c5b61ca 💄 Adapt viewport paste code codestyle
And remove some not necessary constructions
2025-12-03 08:09:13 +01:00
Andrey Antukh
9123d199b7 🐛 Fix scripts/fmt 2025-12-02 17:43:21 +01:00
Andrey Antukh
eeaf28bb25 📎 Disable caddy logging 2025-12-02 13:27:09 +01:00
Andrey Antukh
6b8091bb90 Make devenv https and http2 capable (#7871)
Making it more similar on how it runs on production
environments and improves large amount of files loading
thanks to http2.
2025-12-02 10:49:37 +01:00
Madalena Melo
bba02473d5 📚 Update subtitles in the new user guide cards (#7823)
Co-authored-by: Andres Gonzalez <andres.gonzalez79@gmail.com>
2025-12-02 09:21:05 +01:00
Andrey Antukh
77c9d8a2c8 🐛 Revert exporter dockerfile changes 2025-12-01 14:32:00 +01:00
Andrey Antukh
95b7784a42 🐛 Change internal ordering on how email parts are assembled
This fixes the html email rendering on gmail. Other clients (like proton,
emailcatcher) properly renders html independently of the order of parts
on the multipart email structure but gmail requires that html should be
the last one.
2025-12-01 14:27:21 +01:00
Andrey Antukh
4690f740b9 Add minor improvements to the audit module 2025-12-01 13:57:55 +01:00
Xaviju
529c4eb38a 💄 Avoid code tab overflow (#7854) 2025-12-01 11:37:37 +01:00
Andrey Antukh
c3a9919c4d 🐛 Fix typo on exporter dockerfile 2025-12-01 11:19:41 +01:00
Juanfran
10a2732a55 Merge pull request #7863 from penpot/niwinz-staging-improve-yarn-independency
 Use setup script on exporter instead of direct commands
2025-12-01 10:13:58 +01:00
Andrey Antukh
40e3617138 Use setup script on exporter instead of direct commands 2025-12-01 09:23:11 +01:00
Andrey Antukh
b18c421415 📎 Update .gitignore 2025-12-01 09:20:33 +01:00
Andrey Antukh
e7029f2182 Make automatic workflows not dependent on yarn 2025-12-01 08:17:52 +01:00
Alonso Torres
2c3becb408 🐛 Fix problem with plugins content attribute (#7835) 2025-11-28 13:41:27 +01:00
Xaviju
a4e6aa0588 💄 Limit inspect layer info message to avoid overflow (#7847) 2025-11-28 10:19:02 +01:00
Andrey Antukh
7fe20b65dc 🔧 Add more cache efficient configuration for devenv nginx 2025-11-27 17:59:12 +01:00
Andrey Antukh
e5638cd769 ⬆️ Update clojure tools version on devenv 2025-11-27 17:58:56 +01:00
Eva Marco
8e79dfcb82 🐛 Fix input variant 2025-11-27 17:54:11 +01:00
Eva Marco
508db99a57 🐛 Restore empty field error on dimension, text-case and color forms 2025-11-27 17:54:11 +01:00
Andrey Antukh
3c6c9894da 🐛 Restore empty value error on border radius token form 2025-11-27 17:54:11 +01:00
Andrey Antukh
972b23e6c0 🐛 Fix incorect pred build on ::sm/text schema 2025-11-27 17:54:11 +01:00
Andrey Antukh
28f550d533 🔥 Remove commented code 2025-11-27 17:54:11 +01:00
Elena Torró
2b20f75fd4 Merge pull request #7837 from penpot/ladybenko-12719-fix-editor-unicode-fonts
🐛 Fix editor not using fallback fonts for selected text
2025-11-27 17:37:00 +01:00
Belén Albeza
4d6d7a6a3d 🐛 Fix emoji font not being used as fallback in text editor dom 2025-11-27 17:23:20 +01:00
Andrey Antukh
db1ab7be69 📎 Run worker bundling serially on devenv 2025-11-27 16:09:15 +01:00
Andrey Antukh
fcbe9d92dc 🐛 Fix unexpected exception on rendering feedback email
Looks like a bug on selmer library
2025-11-27 16:09:15 +01:00
Andrey Antukh
9998ce0bb4 🔥 Remove fipps direct dependency 2025-11-27 16:09:15 +01:00
Andrey Antukh
6061391c89 Don't require cljs.analyzer api under cljs on data.macros
Reduces the final production bundle size
2025-11-27 16:09:15 +01:00
Andrey Antukh
eabf6e36ed Remove a level of indentation on subscriptions-dashboard tests 2025-11-27 16:09:15 +01:00
Andrey Antukh
04274e53fa 📎 Fix advanced compilation warnings related to jsdoc 2025-11-27 16:09:15 +01:00
Andrey Antukh
52dd9271a9 🐛 Encode header values as strings on audit archive task 2025-11-27 16:09:15 +01:00
andrés gonzález
8f5a81e179 📚 Add info about boolean variants (#7828) 2025-11-27 16:03:11 +01:00
Alonso Torres
a940c08da9 🐛 Fix problem with worker bundling in development (#7844) 2025-11-27 14:13:48 +01:00
Alejandro Alonso
3de4473251 Merge pull request #7845 from penpot/elenatorro-fix-case
🐛 Fix editor vertical align default case
2025-11-27 14:00:12 +01:00
Andrey Antukh
0735140f07 🔧 Change concurrency rules on tests github workflow 2025-11-27 13:46:48 +01:00
Elena Torro
dc8a07099d 🐛 Fix vertical align default case 2025-11-27 13:38:51 +01:00
Elena Torró
90dcf04fb0 Merge pull request #7841 from penpot/superalex-fix-boolean-operators-no-selection
🐛 Fix boolean operators no selection
2025-11-27 12:50:16 +01:00
Belén Albeza
f84c236e02 🐛 Fix text editor v2 not using fallback fonts for selected text 2025-11-27 12:26:39 +01:00
Alejandro Alonso
63959a22cc 🐛 Fix svg attrs 2025-11-27 12:23:46 +01:00
Alejandro Alonso
8840246425 🐛 Fix bleeding masks 2025-11-27 12:23:46 +01:00
Alejandro Alonso
62ec66cd15 🔧 Adding more e2e tests for nested frames with clipping 2025-11-27 12:23:46 +01:00
Alejandro Alonso
e3b87390f6 🐛 Fix nested shadows clipping 2025-11-27 12:23:46 +01:00
Alejandro Alonso
d9ab28e6ed 🐛 Fix nested clipping 2025-11-27 12:23:46 +01:00
Belén Albeza
9183dbbc43 🔧 Fix lint error (rust) 2025-11-27 11:51:05 +01:00
Andrey Antukh
74d00473e9 Add missing render-wasm to the ci workflow 2025-11-27 11:51:05 +01:00
Alejandro Alonso
1c70f5a36b 🐛 Fix boolean operatos shown when there is no selection 2025-11-27 11:22:15 +01:00
Andrey Antukh
b23e0c0642 Add tempfile storage bucket handler test case (#7839) 2025-11-27 10:27:57 +01:00
Marina López
db0cbbbc2e 🐛 Fix logic preventing incorrect trial flow in subscription modal (#7831) 2025-11-26 12:08:02 +01:00
alonso.torres
48304bd26f 🐛 Fix issue when exporting files 2025-11-26 12:04:34 +01:00
Elena Torro
60e32bbc71 🐛 Fix text editor vertical align 2025-11-26 11:46:47 +01:00
André Carvalhais
54451608dc 💄 Fix spelling of 'smtp' in email configuration section
Corrected the spelling of 'smtp' in the documentation.

Signed-off-by: André Carvalhais <carvalhais@live.com>
2025-11-26 08:11:27 +01:00
Alejandro Alonso
b7727122d5 Merge pull request #7829 from penpot/alotor-fixes
🐛 Fix problem with thumbnails in parallel
2025-11-26 07:21:49 +01:00
alonso.torres
8880f07a6a 🐛 Fix problem with thumbnails in parallel 2025-11-25 17:56:00 +01:00
andrés gonzález
aaca2c41d8 📚 Add metadescriptions to some help center pages (#7821) 2025-11-25 17:00:14 +01:00
Belén Albeza
33417a4b20 🐛 Fix svg attrs stroke-linecap stroke-linejoin fill-rule 2025-11-25 12:43:40 +01:00
Andrés Moya
2640889dc8 🐛 Fix backwards compatibility importing files with token themes 2025-11-25 10:56:33 +01:00
alonso.torres
dd5f3396d1 🐛 Fix problem with layout z-index 2025-11-24 17:48:58 +01:00
Andrey Antukh
dedeae8641 🐛 Fix incorrect subscription fetching after profile registration 2025-11-24 14:36:46 +01:00
Andrey Antukh
a7552d412a Add explicit network asingation and alias on devenv compose 2025-11-24 14:36:46 +01:00
Aitor Moreno
f58475a7c9 🐛 Fix pasting application/transit+json (#7812) 2025-11-24 14:36:24 +01:00
Marina López
00bbb0bfb6 ♻️ Add format and refactor payments 2025-11-24 11:41:03 +01:00
Andrey Antukh
d93fe89c12 📎 Backport CI github workflog from develop 2025-11-24 10:48:51 +01:00
Andrey Antukh
6e44330af4 Merge remote-tracking branch 'origin/develop' into staging 2025-11-24 09:42:45 +01:00
Andrey Antukh
624805fd6b Merge remote-tracking branch 'weblate/develop' into develop 2025-11-24 09:32:06 +01:00
Eva Marco
9b6bb77422 Materialize several tokens related flags (#7773)
* 📚 Add line to changelog

* ♻️ Remove typography types flag

* ♻️ Remove composite typography token flag

* ♻️ Remove token units flag

* 🎉 Activate by default two token flags

* ♻️ Update inspect tab tests to navigate to the right info tab

* 🐛 Fix test

---------

Co-authored-by: Xavier Julian <xavier.julian@kaleidos.net>
2025-11-24 09:26:05 +01:00
Yamila Moreno
9b8e04bb3c 🐳 Remove minio service from docker-compose.yml (#7809) 2025-11-24 08:15:36 +01:00
Edgars Andersons
2e919809c9 🌐 Add translations for: Latvian
Currently translated at 94.1% (1873 of 1990 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/lv/
2025-11-23 12:51:20 +00:00
Nicola Bortoletto
645e123e3a 🌐 Add translations for: Italian
Currently translated at 98.8% (1967 of 1990 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/it/
2025-11-23 12:51:17 +00:00
Oğuz Ersen
cfb94d17b6 🌐 Add translations for: Turkish
Currently translated at 99.8% (1987 of 1990 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/tr/
2025-11-22 10:51:22 +00:00
Keunes
e9cb409ca4 🌐 Add translations for: Dutch
Currently translated at 99.8% (1987 of 1990 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/nl/
2025-11-22 10:51:19 +00:00
jonnysemon
8a0cd75257 🌐 Add translations for: Arabic
Currently translated at 56.6% (1128 of 1990 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/ar/
2025-11-22 10:51:17 +00:00
Pablo Alba
fae488b15a 🐛 Fix after changing a variant property value, the value appears as empty (#7791) 2025-11-21 17:51:12 +01:00
Elena Torró
b82828632e Merge pull request #7807 from penpot/alotor-fix-hover-text
🐛 Fix hover text
2025-11-21 15:35:41 +01:00
alonso.torres
bf24e22588 🐛 Fix hover text 2025-11-21 14:27:15 +01:00
Alejandro Alonso
7399b4d423 📚 Remove wrong line on CHANGES 2025-11-21 14:21:14 +01:00
Alejandro Alonso
77b9eee6bd 🐛 Fix svg fills defined in svg-attrs with url or color format 2025-11-21 14:15:27 +01:00
Elena Torro
55896db49e 🔧 Check for emtpy/nil attrs when getting inline style 2025-11-21 14:10:23 +01:00
Elena Torró
f4c569d619 Merge pull request #7802 from penpot/alotor-fix-text-data-problem
🐛 Fix problems with text editor size
2025-11-21 13:41:38 +01:00
alonso.torres
ca2cf18a49 🐛 Fix problems with text editor size 2025-11-21 13:17:43 +01:00
Andrey Antukh
6e352c167c 🐛 Fix dev build of frontend 2025-11-21 13:02:44 +01:00
Andrey Antukh
3ec001de44 🔧 Add nitrate url to devenv nginx (#7800) 2025-11-21 12:30:49 +01:00
Elena Torró
a1f11c89f2 Merge pull request #7799 from penpot/alotor-fix-text-data-problem
🐛 Fix problem with text data serialization
2025-11-21 12:30:35 +01:00
alonso.torres
33d70f0e45 🐛 Fix problem with text data serialization 2025-11-21 12:07:01 +01:00
Elena Torró
4f24a8f5f1 Merge pull request #7770 from penpot/ladybenko-12587-fix-text-editor-crash-empty
🐛 Fix crash when using a font family with a number in its name
2025-11-21 12:02:40 +01:00
Andrey Antukh
b03cfffb9e Restore the dashboard thumbnail rendering using wasm (#7796)
* Revert "🐛 Rollback esm worker (#7792)"

This reverts commit 0120a5335b.

* 🐛 Fix incorrect manifest reading on building worker
2025-11-21 11:42:40 +01:00
Elena Torró
956ad88e51 Merge pull request #7795 from penpot/alotor-fix-paste-crash
🐛 Fix paste crash
2025-11-21 11:00:00 +01:00
Belén Albeza
76f5c73de6 Remove leftover console.log/trace 2025-11-21 10:59:15 +01:00
Belén Albeza
c6dd3e0eeb Add missing param to cut handler 2025-11-21 10:28:48 +01:00
alonso.torres
fde73f30b9 🐛 Fix paste crash 2025-11-21 09:51:54 +01:00
Edgars Andersons
9d35a4317c 🌐 Add translations for: Latvian
Currently translated at 93.6% (1864 of 1990 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/lv/
2025-11-21 05:51:27 +00:00
jonnysemon
e7ccfeccbf 🌐 Add translations for: Arabic
Currently translated at 56.6% (1128 of 1990 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/ar/
2025-11-21 05:51:26 +00:00
Stephan Paternotte
aa043d284f 🌐 Add translations for: Dutch
Currently translated at 99.8% (1987 of 1990 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/nl/
2025-11-21 05:51:21 +00:00
Alejandro Alonso
537dd171c0 Merge pull request #7793 from penpot/alotor-tiles-improvement
 Improve cache rendering
2025-11-20 18:50:24 +01:00
alonso.torres
c2026918a4 Improve cache rendering 2025-11-20 17:33:37 +01:00
Alonso Torres
0120a5335b 🐛 Rollback esm worker (#7792) 2025-11-20 16:07:22 +01:00
Belén Albeza
d0d2f43ca1 🐛 Fix text editor crash with font families with a number in their name 2025-11-20 15:22:40 +01:00
Alejandro Alonso
7e33a7c1a7 Merge pull request #7666 from penpot/azazeln28-feat-allow-disabling-rich-paste
🎉 Add an option to enable and disable HTML paste
2025-11-20 14:17:16 +01:00
Elena Torró
c13b58f42a Merge pull request #7764 from penpot/superalex-fix-blurs
🐛 Fix shadows and blurs
2025-11-20 13:37:57 +01:00
alonso.torres
a5c9f9e454 📚 Adds contributor to the changelog 2025-11-20 13:35:43 +01:00
Aitor Moreno
d73be5832b 🎉 Add an option to enable and disable HTML paste 2025-11-20 13:33:51 +01:00
Alejandro Alonso
e1f2fca4af Merge pull request #7771 from penpot/elenatorro-12541-improve-text-selection-and-cursor
 Improve text shape selection
2025-11-20 13:33:48 +01:00
Diana Veiga
37d5a31589 Drop zoom snap (#7774)
*  Remove const `zoom-half-pixel-precision`

* ♻️ Adjust usages
2025-11-20 13:28:45 +01:00
Luis de Dios
177bdaa72c 🐛 Fix variant toggle does not work for uppercase or mixed case (#7716)
* 🐛 Fix variant toggle does not work for uppercase or mixed case

* 📎 PR changes
2025-11-20 13:27:04 +01:00
Aitor Moreno
38ab2c61b9 Merge pull request #7782 from penpot/alotor-wasm-thumbnails
 Render WASM dashboard thumbnails
2025-11-20 13:12:26 +01:00
Marina López
cc32b22e8a Add improvements to the payment flow (#7776)
*  Add improvements payment flow

* 📎 PR feedback

* 📎 Fix conflicts
2025-11-20 13:07:57 +01:00
Alejandro Alonso
d331c5ad83 Merge pull request #7769 from penpot/niwinz-develop-exporter-refactor
 Remove exporter dependency on shared-fs on scaling
2025-11-20 12:44:34 +01:00
iPagar
6c6c2c3012 📚 Update copyright year on doc (#7502)
Signed-off-by: iPagar <iPagar@users.noreply.github.com>
2025-11-20 12:38:31 +01:00
Andrey Antukh
81632a03dd ♻️ Make exporter upload resources using backend management api
Instead of custon shared fs approach. This commit fixes the main
scalability issue of exporter removing the need of shared-fs
for make it work with multiple instances.
2025-11-20 12:20:13 +01:00
Andrey Antukh
4fddf3d986 ♻️ Make management key derivable from secret key
Still preserves the ability to set management
2025-11-20 12:20:13 +01:00
Andrey Antukh
57aa9a585b 🔧 Add explicit network alias for minio on devenv 2025-11-20 12:20:13 +01:00
Andrey Antukh
f71f491590 🐛 Fix incorrect bearer token decoding 2025-11-20 12:20:13 +01:00
Andrey Antukh
6ae2401c5e ♻️ Change how shapes are validated after changes apply operation 2025-11-20 12:08:48 +01:00
Andrey Antukh
53d8a2d6d7 🔥 Remove obsolete code on :move-objects related to old components 2025-11-20 12:08:48 +01:00
Andrey Antukh
bd65f3932e 🐛 Fix a race condition on move-object
That happens when an in-flight move-object change tries
to move object to an already deleted parent
2025-11-20 12:08:48 +01:00
alonso.torres
59845b756f Render WASM dashboard thumbnails 2025-11-20 11:56:25 +01:00
Alejandro Alonso
b8c0c5c310 Merge pull request #7742 from penpot/alotor-plugins-improvements
 Plugin API improvements with images and indexes
2025-11-20 11:47:50 +01:00
Alejandro Alonso
cfa8c21ee6 Merge pull request #7788 from penpot/elenatorro-fix-insert-shape-on-empty-frame
🐛 Fix insert shape on empty frame
2025-11-20 11:44:13 +01:00
Elena Torro
624bdaec88 Show text cursor in the entire text rect 2025-11-20 11:42:07 +01:00
Alejandro Alonso
24745bed40 🐛 Fix shadows and blurs for high levels of zoom 2025-11-20 11:25:23 +01:00
Eva Marco
d26c08f8e2 ♻️ Replace token forms (#7759)
* 🎉 Create dimensions form

* 🎉 Create text-case form

* 🎉 Create color form

* ♻️ Remove unused code on form file
2025-11-20 11:04:39 +01:00
Elena Torro
36adbd9118 🐛 Fix insert shape on empty frame 2025-11-20 10:59:44 +01:00
Elena Torró
0a3fe9836a Merge pull request #7777 from penpot/superalex-fix-extrect-calculation
🐛 Fix extrect calculation
2025-11-20 09:57:59 +01:00
Andrey Antukh
fef0c11503 🔧 Update tests github flow 2025-11-20 09:37:38 +01:00
Alejandro Alonso
7e858784a1 Merge pull request #7785 from penpot/niwinz-develop-binary-fills
🐛 Fix invalid fills schema when binary fills are used
2025-11-20 09:06:45 +01:00
Miguel de Benito Delgado
203368c2ee Add parameter to openPage to toggle new window behaviour (#7753)
*  Add parameter to openPage() to toggle opening a new tab/window

* 💄 Fix formatting
2025-11-20 08:05:08 +01:00
Alejandro Alonso
4f54469629 Merge pull request #7747 from penpot/niwinz-develop-storage-changes
 Make the binfile exportation process more reliable
2025-11-20 07:58:57 +01:00
Andrey Antukh
5343e799f8 🐛 Fix invalid fills schema when binary fills are used 2025-11-20 07:45:37 +01:00
Andrey Antukh
51e54a6bad 🐛 Fix incorrect project restoration on restoring file (#7778) 2025-11-19 18:24:24 +01:00
Aitor Moreno
f609747322 🐛 Fix inert element error 2025-11-19 18:23:44 +01:00
Andrey Antukh
26ad039d99 ⬆️ Update playwright dependency on frontend 2025-11-19 18:23:44 +01:00
Andrey Antukh
3136096123 🔧 Add general improvements to integration tests
This commit marks as skip (temporal) several flaky/randomly-failing
tests.

It also moves the integration test execution from circleci to github
actions.
2025-11-19 18:23:44 +01:00
Andrey Antukh
122d3bc41c 💄 Add code formatting for js on frontend 2025-11-19 18:23:44 +01:00
Andrey Antukh
3b52051113 Fix closure compiler issues on clipboard js impl
With minor naming fixes
2025-11-19 18:23:44 +01:00
Aitor Moreno
32e1b55658 ♻️ Refactor clipboard 2025-11-19 18:23:44 +01:00
Andrey Antukh
e9d177eae3 Make the binfile export process more resilent to errors
The current binfile export process uses a streaming technique. The
major problem with the streaming approach is the case when an error
happens on the middle of generation, because we have no way to
notify the user about the error (because the response is already
is sent and contents are streaming directly to the user
client/browser).

This commit replaces the streaming with temporal files and SSE
encoded response for emit the export progress events; once the
exportation is finished, a temporal uri to the exported artifact
is emited to the user via "end" event and the frontend code
will automatically trigger the download.

Using the SSE approach removes possible transport timeouts on export
large files by sending progress data over the open connection.

This commit also removes obsolete code related to old binfile
formats.
2025-11-19 17:28:55 +01:00
Andrey Antukh
d42c65b9ca Improve logging on shape detach operation 2025-11-19 17:28:55 +01:00
Andrey Antukh
86ad56797b Simplify tempfile deletion handling
Mainly removes the jvm on-exit hook usage because it can lead
to slow stops and unnecesary memory consumption over the time
the jvm is running.
2025-11-19 17:28:55 +01:00
Andrey Antukh
63497b8930 Add tempfile bucket to the storage subsystem
This enables storing temporal files under storage subsystem. The
temporal objects (the objects that uses templfile bucket) will
always evaluate to "for deletion" after touched garbage collection;
and the deletion threshold will be 2 hours (the threshold is always
calculated from the instant when the touched garbage collector is
running).
2025-11-19 17:28:55 +01:00
Andrey Antukh
94719eebf8 ♻️ Make storage and other objects deletion task vclock aware
This simplifes the mental model on how it works and simplifies testing
of the related code.

This also normalizes storage object deletion in the same way as the
rest of objects in penpot (now future deletion date on storage object
also means storage object to be deleted).
2025-11-19 17:28:55 +01:00
Andrey Antukh
9532dea2c6 📎 Skip inspect integration tests (#7781) 2025-11-19 17:26:40 +01:00
Andrey Antukh
40e1e27bf0 🐛 Fix not covered case on schema decode fn on tokens-lib 2025-11-19 15:04:49 +01:00
Andrés Moya
4338f97e9f 🐛 Allow deleting the library in the undo change of add tokens-lib 2025-11-19 15:04:49 +01:00
Andrey Antukh
2c4ec43d5f 🐛 Fix invalid syntax on translation files 2025-11-19 15:03:26 +01:00
Andrey Antukh
3d782a322d 🐛 Fix issue related to labels.code on translations 2025-11-19 14:53:13 +01:00
Andrey Antukh
407d28d187 🌐 Rehash and sync translation files 2025-11-19 14:18:41 +01:00
Andrey Antukh
bf582ec55f 🌐 Add several fixes on weblate merge 2025-11-19 13:25:11 +01:00
Andrey Antukh
858bc05ed5 Merge remote-tracking branch 'weblate/develop' into develop 2025-11-19 13:11:07 +01:00
Andrey Antukh
cd01386210 📎 Set version 1.1.0 final to sdk/library 2025-11-19 13:04:29 +01:00
Xaviju
3b2bb5f225 ♻️ Follow translations guidelines on several inspect components (#7766)
Signed-off-by: Xaviju <xavier.julian@kaleidos.net>
2025-11-19 13:03:25 +01:00
Alejandro Alonso
fe3bc96d0d Merge pull request #7772 from penpot/niwinz-develop-auth-bugfix
 Improvements to the auth internal flows changes
2025-11-19 12:46:10 +01:00
Alejandro Alonso
28f23f397e 🐛 Fix extrect calculation 2025-11-19 12:38:01 +01:00
Andrey Antukh
a487dfe004 Add better approach for cookie token decoding
Remove unnecesary decoding for old tokens and add key identifier
and versioning to cookie tokens for handle future changes.
2025-11-19 07:47:52 +01:00
Andrey Antukh
4f29156929 📎 Add better formatting of public-uri on db report 2025-11-18 20:35:26 +01:00
Andrey Antukh
ce2d3d1652 🐛 Fix incorrect handling of session renewal
A regression introduced in the prev auth refactor.
2025-11-18 20:35:16 +01:00
Andrey Antukh
3639ff9dbc 🔧 Update devenv logging configuration 2025-11-18 20:34:17 +01:00
Andrey Antukh
ca5ec734a0 Merge remote-tracking branch 'origin/staging' into develop 2025-11-18 18:19:36 +01:00
Andrey Antukh
b08da4c3ff Merge remote-tracking branch 'origin/main' into staging 2025-11-18 18:19:11 +01:00
Yamila Moreno
c9bec3924d 🐳 Use the secret key both in the backend and the exporter (#7746) 2025-11-18 18:18:49 +01:00
Yamila Moreno
6e725a75e1 🐳 Use the secret key both in the backend and the exporter (#7746) 2025-11-18 18:17:34 +01:00
Anton Palmqvist
81c3b84972 🌐 Add translations for: Swedish
Currently translated at 99.8% (1953 of 1956 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/sv/
2025-11-18 14:52:28 +01:00
jonnysemon
5868f7f6b2 🌐 Add translations for: Arabic
Currently translated at 57.7% (1130 of 1956 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/ar/
2025-11-18 14:52:25 +01:00
Tiago José
653567d7de 🌐 Add translations for: Portuguese (Brazil)
Currently translated at 71.6% (1402 of 1956 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/pt_BR/
2025-11-18 14:51:51 +01:00
Alejandro Alonso
ce651fa0a9 Merge pull request #7767 from penpot/alotor-fix-problem-compatibility
🐛 Fix problem with tainted canvas in thumbnails
2025-11-18 14:15:06 +01:00
alonso.torres
e8a26ef83b 🐛 Fix problem with tainted canvas in thumbnails 2025-11-18 13:05:56 +01:00
alonso.torres
8fd17c9c84 🐛 Fix problem not checking feature flag 2025-11-18 13:05:29 +01:00
Xaviju
64b892f82d ♻️ Copy shorthands using user selected color space (#7752)
* ♻️ Copy shorthands using user selected color space

* ♻️ Add tests to ensure color space changes affect all properties
2025-11-18 10:54:10 +01:00
Alejandro Alonso
04185b3544 Merge pull request #7762 from penpot/alotor-fix-selection
🐛 Fix problem with selection and text shapes for new render
2025-11-18 10:39:36 +01:00
alonso.torres
0a01fc8af9 🐛 Fix problem with selection and text shapes for new render 2025-11-18 09:34:17 +01:00
Alejandro Alonso
ae624b3728 Merge pull request #7760 from penpot/elenatorro-12533-fix-selection-and-paste-and-word-deletion
🐛 Fix text editor select all functionality and inner paste corner cases
2025-11-18 09:31:57 +01:00
Alejandro Alonso
a48b719966 Merge pull request #7748 from penpot/elenatorro-12586-fix-offset-y-on-new-lines
🐛 Fix new lines spacing between paragraphs
2025-11-18 09:23:22 +01:00
Elena Torró
6425c0cb7d Merge pull request #7757 from penpot/superalex-fix-apply-shadow-and-blur-bounds
🐛 Fix apply shadow and blur bounds
2025-11-17 16:50:15 +01:00
Elena Torro
368f4cfe81 🐛 Fix text editor select all functionality and inner paste corner cases 2025-11-17 16:24:52 +01:00
Alejandro Alonso
fdffa14d75 🐛 Fix apply shadow and blur bounds 2025-11-17 15:20:22 +01:00
Eva Marco
7fe965a870 🎉 Add new form system on workspace (#7738)
* 🎉 Add new form system on border-radius token modals

* ♻️ Create new namespace and separate components

* ♻️ Refactor submit button

---------

Co-authored-by: Andrey Antukh <niwi@niwi.nz>
2025-11-17 13:44:56 +01:00
Anton Palmqvist
d03f5c10fb 🌐 Add translations for: Swedish
Currently translated at 99.8% (1953 of 1956 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/sv/
2025-11-15 20:51:48 +00:00
Anton Palmqvist
3eb0f1c225 🌐 Add translations for: Swedish
Currently translated at 88.9% (1740 of 1956 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/sv/
2025-11-14 18:51:24 +01:00
Elena Torro
127fa931c7 🐛 Fix new lines spacing between paragraphs 2025-11-14 12:00:39 +01:00
Andrey Antukh
30413dbc66 Add small changes to the auth/login button label (#7754)
* 📎 Update changelog

*  Update login button label

* 📎 Adapt playwright tests
2025-11-14 11:35:10 +01:00
Andrey Antukh
2810ae681f ⬆️ Update yarn requirement on library module 2025-11-14 11:15:26 +01:00
Andrey Antukh
d706bb7c8d 🐛 Fix validation issues with dtcg-node schema 2025-11-14 11:15:26 +01:00
Andrey Antukh
ef271db879 🎉 Add addTokensLib method to the library 2025-11-14 11:15:26 +01:00
Andrey Antukh
ec5e814a72 ⬆️ Update npm deps on library 2025-11-14 11:15:26 +01:00
Andrey Antukh
c44fd2dd1d 💄 Use correct comments style on tokens-lib 2025-11-14 11:15:26 +01:00
Andrey Antukh
6aa797f51b Normalize token theme serialization to JSON 2025-11-14 11:15:26 +01:00
Andrés Moya
3cc54fd988 🎉 Add design tokens to plugins API (#7602)
Co-authored-by: alonso.torres <alonso.torres@kaleidos.net>
2025-11-14 11:14:56 +01:00
Xaviju
2233f34a15 🎉 Set default button behaviour as type button instead of submit (#7741) 2025-11-14 10:25:38 +01:00
Andrey Antukh
839bb470df Merge remote-tracking branch 'origin/staging' into develop 2025-11-14 09:55:14 +01:00
Eva Marco
450ce869ba 🐛 Fix gap on export section on sidebar 2025-11-14 09:08:33 +01:00
Xaviju
665587d492 ♻️ Review inspect tab UI (#7727)
* ♻️ Review inspect tab UI

* ♻️ Capitalize English strings and remove from styles

* ♻️ Set a minimum size por color space selector and adjust visually the UI

* 🐛 Fix error on hooks order when selecting texts

* 🐛 Set minim size to inspect tab element

* 🐛 Fix broken typography panel

* ♻️ Design review
2025-11-13 22:19:43 +01:00
Elena Torró
8aaa953604 Merge pull request #7730 from penpot/alotor-fixes-layouts
 Fix new render problems with layout
2025-11-13 16:38:20 +01:00
Marina López
a2cb84ba0d Add improvements payment flow 2025-11-13 13:48:27 +01:00
alonso.torres
639952abc8 🐛 Fix problems with text positioning in layout 2025-11-13 12:31:26 +01:00
alonso.torres
2d63730bfa Improved performance in modifiers 2025-11-13 12:31:26 +01:00
alonso.torres
c1638817b2 🐛 Fix problem with frame titles not moving 2025-11-13 12:31:26 +01:00
alonso.torres
76f6f71e02 🐛 Fix z-ordering for flex elements 2025-11-13 12:31:26 +01:00
alonso.torres
0a700864c9 🐛 Fix problem with grid layout modifiers 2025-11-13 12:31:26 +01:00
Yamila Moreno
04ce4c3233 🔧 Fix repository name in release.yml (#7731) 2025-11-13 11:42:33 +01:00
Andrey Antukh
befcca86df 📚 Update changelog 2025-11-12 21:37:16 +01:00
Andrey Antukh
b7bae3850b 🐛 Fix webp exportation on exporter docker image (#7739) 2025-11-12 21:31:19 +01:00
Elena Torró
3f05dae455 Merge pull request #7735 from penpot/superalex-fix-create-empty-text
🐛 Fix some text issues
2025-11-12 17:48:41 +01:00
alonso.torres
48c9fb5690 Add methods to plugins for modifying indices 2025-11-12 17:07:38 +01:00
alonso.torres
4cdf1eed0c 🐛 Add method to retrieve image data in plugins 2025-11-12 17:07:38 +01:00
Aitor Moreno
4a887840c6 Merge pull request #7737 from penpot/sueralex-fix-shadows-clipping
🐛 Fix shadows clipping
2025-11-12 16:58:06 +01:00
Elena Torró
10cf2c7f35 Merge pull request #7729 from penpot/ladybenko-12514-fix-font-variants
🐛 Fix downloading wrong font variant
2025-11-12 15:30:08 +01:00
Belén Albeza
d048a251f1 🐛 Fix render of text baseline (wasm) 2025-11-12 14:59:57 +01:00
Belén Albeza
0b3fc6a663 🔧 Fix broken playwright tests (wasm render) 2025-11-12 14:48:31 +01:00
Andrey Antukh
363b4e3778 ♻️ Make the SSO code more modular (#7575)
* 📎 Disable by default social auth on devenv

* 🎉 Add the ability to import profile picture from SSO provider

* 📎 Add srepl helper for insert custom sso config

* 🎉 Add custom SSO auth flow
2025-11-12 12:49:10 +01:00
Andrey Antukh
f248ab5644 🐛 Relax schema for importing plain path data related to curve-to command 2025-11-12 12:13:17 +01:00
Alejandro Alonso
33da6fbec2 🐛 Fix shadows clipping 2025-11-12 11:47:53 +01:00
Belén Albeza
07bede8ba2 🐛 Fix unicode ranges for codepoints that need surrogate pairs 2025-11-12 10:11:19 +01:00
Eva Marco
05bea14a88 🐛 Fix review selected colors (#7715)
* 🐛 Fix gap between token sets

* 🐛 Show token selected on color selecction modal
2025-11-12 10:04:29 +01:00
Alejandro Alonso
718f42aa94 🐛 Fix deselect and delete events for empty texts 2025-11-12 08:33:17 +01:00
Alejandro Alonso
f2f8a488ad Merge pull request #7724 from penpot/elenatorro-12551-fix-blurs-and-shadows-bounding-box
🐛 Fix extrect calculation for shadows and blurs depending on the scale
2025-11-12 08:25:50 +01:00
Alejandro Alonso
7594f1883b 🐛 Fix create empty text 2025-11-12 08:20:58 +01:00
Belén Albeza
5c2dde7308 🐛 Fix font family not being updated when changed from dropdown 2025-11-11 15:52:18 +01:00
Belén Albeza
483a1bd703 🐛 Fix downloading wrong font variant 2025-11-11 14:44:56 +01:00
Andrey Antukh
e1a275c7a9 Merge remote-tracking branch 'origin/staging' into develop 2025-11-11 14:07:07 +01:00
Andrey Antukh
96d9724516 📎 Update changelog 2025-11-11 14:04:04 +01:00
Andrey Antukh
8158f2956f Backport github release workflow from develop 2025-11-11 14:01:25 +01:00
Eva Marco
e45994e836 🐛 Fix color row opacity (#7550) 2025-11-11 13:30:08 +01:00
Xaviju
83da59e03c Add composite shadow token to inspect tab (#7703) 2025-11-11 13:28:11 +01:00
Yamila Moreno
fb21a98b0c Merge pull request #7706 from penpot/yms-fix-release-docker-images
🚧 Fix docker images arch during release
2025-11-11 13:21:21 +01:00
Elena Torro
23baf6d18b 🐛 Fix extrect calculation for shadows and blurs depending on the scale 2025-11-11 12:50:15 +01:00
Andrey Antukh
28cf67e7ff 🎉 Add management RPC API (#7700)
* 🎉 Add management RPC API

And refactor internal http auth flow

* 📎 Adjust final url namings

* 📚 Update changelog
2025-11-10 17:10:59 +01:00
Elena Torro
1b50c13c4d 🐛 Render shadows on nested shapes 2025-11-10 14:13:49 +01:00
Pablo Alba
7de95e108b 🐛 Fix crash when using decimal values for X/Y or width/height (#7722) 2025-11-10 11:28:00 +01:00
Luis de Dios
c6b907d05c 📚 Improve switch component documentation (#7714) 2025-11-10 11:00:44 +01:00
Pablo Alba
ffb4d6a890 🐛 Fix input confirmation behavior is not uniform 2025-11-10 09:50:26 +01:00
Ahmad HosseinBor
69c4a8932a 🌐 Add translations for: Persian
Currently translated at 40.2% (787 of 1956 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/fa/
2025-11-10 08:51:23 +01:00
Luis de Dios
fa25307c05 🐛 Fix correct alignment of property names (#7717) 2025-11-09 17:52:11 +01:00
Xaviju
43a136a9e9 💄 Fix minor style details on DS select ghost variant (#7707) 2025-11-07 22:46:57 +01:00
Yamila Moreno
3ec4c96b48 🚧 Fix docker images arch during release 2025-11-07 17:50:09 +01:00
Eva Marco
2eaeb8e9a5 🐛 Fix flex children subgrid gap 2025-11-07 13:49:45 +01:00
Andrey Antukh
604f6ca024 🐛 Fix incorrect value coercing on legacy select component (#7710)
on managing values with select
2025-11-07 13:16:39 +01:00
Andrey Antukh
e3cf70d3a8 Add URI to the report.txt (#7709) 2025-11-07 13:16:21 +01:00
Alejandro Alonso
6aedac35f2 🐛 Fix wasm erros when images are not found 2025-11-07 13:08:41 +01:00
Alejandro Alonso
a11b0f54d7 🐛 Fix changing properties resizes the text box height 2025-11-07 12:34:51 +01:00
Belén Albeza
ec0dc2931c Update copyright string in static page (#7701) 2025-11-07 10:54:27 +01:00
Andrey Antukh
9d65d11c91 Merge remote-tracking branch 'origin/staging' into develop 2025-11-07 10:43:27 +01:00
Luis de Dios
f00fd1d5a8 🎉 Use toggle for switching boolean variant property names (#7564) 2025-11-07 09:47:57 +01:00
Alejandro Alonso
d796dbb572 Merge pull request #7705 from penpot/niwinz-staging-fix-shadows
🐛 Restrict shadow colors to plain colors only
2025-11-06 16:10:02 +01:00
Andrey Antukh
e979476b0e 🐛 Restrict shadow colors to plain colors only
Previously, shadows used a general-purpose color schema that allowed
to have gradients and images on the data structure. This commit fixes
that using a specific schema for shadow colors that only allows plain
colors.

A migration is added to clean up existing shadows with non-plain
colors.
2025-11-06 15:54:50 +01:00
Andrey Antukh
097897d8da Add better sse parser for backend tests 2025-11-06 15:54:50 +01:00
Alejandro Alonso
ba092f03e1 🎉 Use Vec instead of Indexset 2025-11-06 14:16:07 +01:00
Alejandro Alonso
61202e1cab Merge pull request #7698 from penpot/elenatorro-fix-word-breaking-different-browsers
🔧 Fix cross-browser text issues
2025-11-06 12:34:22 +01:00
Elena Torro
f496ba78f3 🔧 Fix cross-browser text issues 2025-11-06 12:20:02 +01:00
Alejandro Alonso
b9a0c6d932 Merge pull request #7702 from penpot/alotor-tiles-fixes
 Removed some artifacts when tile rendering
2025-11-06 12:11:23 +01:00
alonso.torres
a59ce2ed16 Removed some artifacts when tile rendering 2025-11-06 11:46:02 +01:00
Xaviju
c221b9366f Add e2e tests to inspect tab (#7685) 2025-11-06 10:07:50 +01:00
Alejandro Alonso
8e0aa683a1 Merge pull request #7583 from penpot/niwinz-develop-backend-access-deleted-files
 Add RPC methods for enable access to deleted but recoverable projects and files
2025-11-06 06:44:56 +01:00
Alejandro Alonso
445d40b71c Merge pull request #7691 from penpot/alotor-improved-render-tiling
 Improve tile rendering updating
2025-11-05 17:29:25 +01:00
Alejandro Alonso
7889578ced 🎉 Use textures directly for images 2025-11-05 17:16:06 +01:00
alonso.torres
a230d2fcf6 Improve tile rendering updating 2025-11-05 17:16:06 +01:00
Belén Albeza
78fde35df9 🔧 Upgrade storybook (#7693)
* 🔧 Upgrade to storybook 9.x

* 🔧 Upgrade to storybook 10.x

* 🔧 Update watch:storybook script so it builds its assets dependencies first

* 🔧 Use vitest for storybook tests (test-storybook was deprecated)
2025-11-05 17:15:19 +01:00
Eva Marco
bb65782d08 🎉 Add sidebar css variables (#7645)
* 🎉 Add sidebar css variables

* 🎉 Explain more in depth the grid structure
2025-11-05 14:06:26 +01:00
Alejandro Alonso
02a1992a0a Merge pull request #7694 from penpot/niwinz-staging-runner-fixes
🐛 Fix precision issues on worker task scheduling mechanism
2025-11-05 12:18:23 +01:00
Andrey Antukh
1cce82f958 Merge remote-tracking branch 'origin/staging' into develop 2025-11-05 12:15:15 +01:00
Alejandro Alonso
a576c0404a 🐛 Fix focus mode across page and file navigation (#7695) 2025-11-05 12:05:00 +01:00
Andrey Antukh
7d5c1c9b5f Make file-gc-scheduler task compatible with virtual clock
And simplify implementation
2025-11-05 10:47:31 +01:00
Andrey Antukh
cd53d3659c 🐛 Truncate worker scheduled-at to milliseconds
The nanosecond precision has the problem with transit serialization
roundtrip used for pass data on the worker scheduler throught redis
and generates unnecesary rescheduling.
2025-11-05 10:47:31 +01:00
Andrey Antukh
132f7d6d3e ♻️ Add minor refactor on tokens main form (#7690) 2025-11-05 10:37:38 +01:00
Alejandro Alonso
b2a9c55874 Merge pull request #7674 from penpot/elenatorro-12478-fix-new-lines
🐛 Fix new lines issues
2025-11-05 10:13:41 +01:00
Alejandro Alonso
d610e7c892 Merge pull request #7671 from penpot/niwinz-develop-path-data-fix
🐛 Relax schema for importing plain path data related to curve-to command
2025-11-05 10:04:03 +01:00
Alejandro Alonso
1b5557759a Merge pull request #7687 from penpot/ladybenko-12440-fix-corrupt-files
🐛 Fix wasm crash when loading a file with missing font assets
2025-11-05 07:57:39 +01:00
Belén Albeza
8148da58ed 🐛 Fix wasm crash when loading a file with missing font assets 2025-11-05 07:47:16 +01:00
Alejandro Alonso
537f681944 Merge pull request #7692 from penpot/niwinz-develop-logging-improvements
 Remove unnecesary report on duplicate email error validation
2025-11-05 07:46:16 +01:00
Alejandro Alonso
9e7ec594ca Merge pull request #7680 from penpot/niwinz-staging-file-export-fix
🐛 Fix race condition on file export process
2025-11-05 07:45:26 +01:00
Alejandro Alonso
7c529eedd4 Merge pull request #7682 from penpot/niwinz-staging-worker-runner-exceptions
🐛 Fix incorrect status return on worker runner
2025-11-05 07:44:28 +01:00
Alejandro Alonso
500c5c81d4 Merge pull request #7686 from penpot/elenatorro-12499-fix-nested-blur
🐛 Fix children blur rendering
2025-11-05 07:27:43 +01:00
Alejandro Alonso
6ea69c94ee 🎉 Improve big images performance 2025-11-04 22:02:34 +01:00
Andrey Antukh
9b3f68ad14 Remove unnecesary report on duplicate email error validation 2025-11-04 20:34:25 +01:00
Andrey Antukh
34363320ae Merge branch 'main' into staging 2025-11-04 16:49:53 +01:00
Andrey Antukh
092a5139e3 🐛 Fix incorrect token sets migration (#7673) 2025-11-04 16:49:08 +01:00
Andrey Antukh
4a01121043 Merge tag '2.11.0-RC3' 2025-11-04 16:43:32 +01:00
Elena Torro
564ad8adba 🐛 Fix children blur rendering 2025-11-04 15:37:49 +01:00
Andrey Antukh
78e2d6fec3 🐛 Relax schema for importing plain path data related to curve-to command 2025-11-04 12:59:26 +01:00
Andrey Antukh
c850f101d3 Merge remote-tracking branch 'origin/staging' into develop 2025-11-04 12:49:57 +01:00
Andrey Antukh
49721c0bcd Add better logging context report on worker runner 2025-11-04 12:44:38 +01:00
Andrey Antukh
c214cc1544 🐛 Do not process runner result if no result returned 2025-11-04 12:44:38 +01:00
Andrey Antukh
eaabe54c4b 💄 Check the runner task exists as first condition 2025-11-04 12:44:38 +01:00
Eva Marco
21fb38e5bd 🐛 Fixes some problems with dropdowns and token inputs (#7640)
* 🐛 Fix apply color token on strokes

* 🐛 Fix size and position of some numeric inputs

* 🐛 Fix padding token application

* ♻️ Fix ci

* 🐛 Fix selected color tick

* 🐛 Fix comments and design review
2025-11-04 12:39:41 +01:00
Luis de Dios
37aa59b164 🐛 Fix hidden advanced frame grid options menu (#7681) 2025-11-04 11:57:52 +01:00
Elena Torro
24e4ece323 🐛 Fix line-height rendering on empty lines 2025-11-04 11:25:14 +01:00
Andrey Antukh
cbae3dca34 Simplify the approach for return streamable body
Removing unnecesary syntax overhead with simplier abstraction
2025-11-04 10:56:05 +01:00
Andrey Antukh
8307b699bf 🐛 Remove a race condition on file export
Caused when file is deleted in the middle of an exportation. The
current export process is not transactional, and on file deletion
several queries can start return not-found exception because of
concurrent file deletion.

With the changes on this PR we allow query deleted files internally
on the exportation process and make it resilent to possible
concurrent deletion.
2025-11-04 10:56:05 +01:00
Andrey Antukh
cd6865f54b ⬆️ Update yetti dependency
Bugfixes
2025-11-04 10:56:05 +01:00
Elena Torro
e673035817 🔧 Filter out empty paragraph content 2025-11-04 09:57:13 +01:00
Stas Haas
f6e77c09b3 🌐 Add translations for: German
Currently translated at 90.4% (1770 of 1956 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/de/
2025-11-03 21:51:14 +01:00
Elena Torro
87fc71b55d 🐛 Ignore non-frequent chars 2025-11-03 17:08:38 +01:00
Elena Torro
b76bfa2197 🐛 Fix width on rotation 2025-11-03 16:37:17 +01:00
Andrey Antukh
88493f6805 🐛 Fix incorrect query for subscription editors (#7672)
Default teams should be present on the query results
2025-11-03 16:14:24 +01:00
Pablo Alba
69bbdad570 🐛 Fix nested variant in a component doesn't keep inherited overrides (3) 2025-11-03 15:36:37 +01:00
Pablo Alba
df4279bdee Revert "🐛 Fix nested variant in a component doesn't keep inherited overrides (2)"
This reverts commit 7c6515aa7b.
2025-11-03 15:36:37 +01:00
Alejandro Alonso
c8c901ee4c Merge pull request #7670 from penpot/ladybenko-fix-broken-wasm-test
 Fix broken wasm test
2025-11-03 14:49:29 +01:00
Belén Albeza
8f0e5e36e9 Fix broken wasm test 2025-11-03 14:18:15 +01:00
Andrés Moya
a5e9f7229b 💄 Fix tests nesting 2025-11-03 14:02:29 +01:00
Andrés Moya
5f22220a8b 🐛 Add test to catch a fixed bug and avoid regressions 2025-11-03 14:02:29 +01:00
Luis de Dios
6c7661b04d 🐛 Fix add missing use in SCSS 2025-11-03 12:47:25 +01:00
Alejandro Alonso
b867f276f2 Merge pull request #7665 from penpot/superalex-fix-texts-migrations
🐛 Fix texts migrations
2025-11-03 12:20:16 +01:00
Alejandro Alonso
da8d7a78cf 🐛 Add migration for texts with fills only in position-data 2025-11-03 12:06:41 +01:00
Alejandro Alonso
ec4936f5fe 🐛 Fix 0006 migration for strings that should be uuids 2025-11-03 12:06:41 +01:00
Alejandro Alonso
dd9ec54bd1 Merge pull request #7664 from penpot/alotor-performance-improvements
 Improve boolean calculations
2025-11-03 12:04:36 +01:00
Alejandro Alonso
3ad4b0a453 Merge pull request #7657 from penpot/elenatorro-12448-fix-text-tabs
🐛 Fix tabs rendering
2025-11-03 11:53:20 +01:00
Belén Albeza
83cd9c3db6 🔧 Fix rust linter errors 2025-11-03 11:45:05 +01:00
Andrey Antukh
399feec032 ⬆️ Update rust to 1.91 2025-11-03 11:45:00 +01:00
Andrey Antukh
481fa44f18 Merge remote-tracking branch 'origin/staging' into develop 2025-11-03 11:41:13 +01:00
Andrey Antukh
42c9f2123d Merge pull request #7663 from penpot/niwinz-staging-update-rust
⬆️ Update rust to 1.91
2025-11-03 11:26:01 +01:00
Elena Torro
d18a018236 🔧 Fix tab rendering with the text editor 2025-11-03 11:02:28 +01:00
Belén Albeza
4ab6ecec21 🔧 Fix rust linter errors 2025-11-03 10:43:35 +01:00
alonso.torres
b39c00fbf6 Improve boolean calculations 2025-11-03 09:50:29 +01:00
Andrey Antukh
8a0fddf1e4 ⬆️ Update rust to 1.91 2025-11-03 09:10:40 +01:00
Luis de Dios
95fdd75030 🐛 Fix misaligned right sidebar menus 2025-11-03 08:34:09 +01:00
Andrey Antukh
54489c4285 🔧 Add better regex for commit checker 2025-11-01 18:46:26 +01:00
Stas Haas
e7b8ad8ee2 🌐 Add translations for: German
Currently translated at 89.3% (1747 of 1956 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/de/
2025-11-01 10:51:52 +00:00
Andrey Antukh
6815806669 Merge remote-tracking branch 'origin/staging' into develop 2025-10-31 18:15:12 +01:00
Andrey Antukh
febe87aa7b 🐛 Fix incorrect checksum of the jdk on dockerfiles 2025-10-31 18:01:55 +01:00
Andrey Antukh
83763b46ce Add RPC methods for manage deleted files
This includes: get already deletedf files, restore deleted files
and permanently delete files marked for deletion.
2025-10-31 16:07:23 +01:00
Andrey Antukh
1ddc196484 Make the get-projects return deleted projects
And adapt the frontend code to properly filter
deleted projects on appropriate pages
2025-10-31 16:07:23 +01:00
Andrey Antukh
37d4844518 💄 Add minor cosmetic changes to get-project-files rpc method 2025-10-31 16:07:23 +01:00
Andrey Antukh
76e610dd06 🔥 Remove duplicated functions from file tests namespace 2025-10-31 16:07:23 +01:00
Andrés Moya
99e8b22672 🐛 Fix theme validation when still no tokens library exists 2025-10-31 16:04:50 +01:00
Andrey Antukh
65adbfaadb Merge remote-tracking branch 'origin/staging' into develop 2025-10-31 14:50:59 +01:00
Andrey Antukh
0581c60800 ⬆️ Update jdk and node on docker images 2025-10-31 14:50:12 +01:00
Andrey Antukh
7e92408807 ⬆️ Update jdk and node on devenv 2025-10-31 14:50:12 +01:00
Marina López
03eeeda44f Add improvements payment flow 2025-10-31 14:15:22 +01:00
Alejandro Alonso
2f33009e69 Merge pull request #7655 from penpot/superalex-add-migration-to-fix-text-attrs-with-blank-strings
📎 Add migration to fix text attrs with blank strings
2025-10-31 13:58:42 +01:00
Alejandro Alonso
1d5c407456 📎 Add migration to fix text attrs with blank strings 2025-10-31 13:30:46 +01:00
Alejandro Alonso
aa15232cc7 Merge pull request #7648 from penpot/alotor-performance-improvements
 Add performance improvements for wasm render
2025-10-31 12:22:14 +01:00
Andrey Antukh
f53935f5df Merge remote-tracking branch 'origin/staging' into develop 2025-10-31 12:13:29 +01:00
alonso.torres
de04026dc8 After review changes 2025-10-31 12:04:52 +01:00
alonso.torres
f3b914534f Add scale_content to shapes_pool 2025-10-31 11:56:28 +01:00
alonso.torres
fcc9282304 Fix problems with SVGraw and modifiers 2025-10-31 11:56:28 +01:00
alonso.torres
122619b197 Support for booleans dynamic transforms 2025-10-31 11:56:28 +01:00
alonso.torres
dbf9bdceb5 Removed modifiers from code 2025-10-31 11:56:28 +01:00
Alejandro Alonso
f6eb492329 🐛 Fig shapes pool extending size 2025-10-31 11:56:28 +01:00
Alejandro Alonso
c66a8f5dc5 Improve shapes pool performance 2025-10-31 11:56:28 +01:00
alonso.torres
ed4df73e42 Changes to modifiers 2025-10-31 11:56:28 +01:00
alonso.torres
59e745e9ab Improve performance of group bounds 2025-10-31 11:56:28 +01:00
alonso.torres
d4b4d943c6 Store bounds inside the shape 2025-10-31 11:56:28 +01:00
alonso.torres
e4b4f1bd08 Removed all_ancestors traversals 2025-10-31 11:56:28 +01:00
alonso.torres
e58b2453b1 Removed method set_selrect_for_current_shape 2025-10-31 11:56:28 +01:00
alonso.torres
e9230b8b54 Change internal data type for tiles 2025-10-31 11:56:28 +01:00
alonso.torres
9d7cac5e73 Improved performance of children ancestors 2025-10-31 11:56:28 +01:00
alonso.torres
17fefcf0bc Changes WASM serialization mechanism 2025-10-31 11:56:28 +01:00
Alejandro Alonso
4367bd2dc6 Merge pull request #7651 from penpot/niwinz-email-bugfix-1
🐛 Fix regression on sending quote notification email
2025-10-31 11:23:39 +01:00
Miguel de Benito Delgado
6e2b2e8924 📚 Update increase/decrease font shortcuts (#7652) 2025-10-31 11:21:53 +01:00
Andrey Antukh
f3805e3b70 🐛 Fix regression on sending quote notification email 2025-10-31 10:56:33 +01:00
David Barragán Merino
262937c421 📚 Add recommendations for valkey/redis configuration 2025-10-31 10:45:33 +01:00
Alejandro Alonso
15ee75a692 Merge pull request #7647 from penpot/elenatorro-remove-unnecessary-text-properties
🔧 Remove unused text attrs
2025-10-31 09:56:12 +01:00
Alonso Torres
942e3300dd 🐛 Fix problem when checking usage with removed teams (#7638) 2025-10-31 09:22:31 +01:00
Elena Torro
eaa3904a3a 🔧 Remove unused text attrs 2025-10-31 09:22:01 +01:00
Alejandro Alonso
0c66b5db73 📎 Set stronger text validation (#7646) 2025-10-31 09:19:53 +01:00
Elena Torró
cc40448cb5 Merge pull request #7644 from penpot/azazeln28-fix-empty-text-attr-defaults
🐛 Fix empty text attr defaults
2025-10-31 09:00:19 +01:00
Alejandro Alonso
6a2029ca3b 🐛 Fix error comment message after the demo account creation (#7615) 2025-10-31 08:56:34 +01:00
David Barragán Merino
f32913adcf 📚 Adapt doc with the storage settings changes (#7607) 2025-10-31 08:56:06 +01:00
Juan de la Cruz
d906f05a6f 🎉 Add 2.11 release slides and images (#7606) 2025-10-31 08:54:19 +01:00
Yamila Moreno
2402334fb2 Merge pull request #7641 from penpot/yms-add-bundle-version-to-docker-metadata
🚧 Add bundle version to Docker metadata
2025-10-30 15:12:46 +01:00
Elena Torró
c3e2621ed5 Merge pull request #7643 from penpot/superalex-serialize-font-weight-properly
🐛 Serialize font weight properly
2025-10-30 14:59:47 +01:00
Yamila Moreno
d37695d7a5 🚧 Add bundle version to Docker metadata 2025-10-30 14:36:23 +01:00
Aitor Moreno
fadbe24aaa 🐛 Fix empty text attr defaults 2025-10-30 14:16:30 +01:00
Alejandro Alonso
9d29d5e8cc 🐛 Serialize font weight properly 2025-10-30 14:15:57 +01:00
Florian Schroedl
e681f95a70 Add box shadow token 2025-10-30 14:05:42 +01:00
Alejandro Alonso
5c8b401037 Merge pull request #7637 from penpot/elenatorro-12439-fix-fonts-default-values
🐛 Fix default font size in text spans
2025-10-30 11:14:20 +01:00
Elena Torro
9dfb0ebe84 🐛 Fix default font size in text spans 2025-10-29 17:23:29 +01:00
Alejandro Alonso
08162c825d Merge pull request #7633 from penpot/superalex-options-button-does-not-work-for-comments-created-in-the-lower-part-of-the-screen-with-an-active-reply-field
🐛 Fix options button does not work for comments created in the lower part of the screen
2025-10-29 16:18:21 +01:00
Alejandro Alonso
bc700334ca 🐛 Fix options button does not work for comments created in the lower part of the screen 2025-10-29 16:17:57 +01:00
Alejandro Alonso
133590f19c Merge pull request #7635 from penpot/alotor-fix-paste-position
🐛 Fix paste without selection sends the new element in the back
2025-10-29 16:16:17 +01:00
alonso.torres
66c5a0570e 🐛 Fix paste without selection sends the new element in the back 2025-10-29 16:15:55 +01:00
Andrés Moya
94cbf9d8f2 🎉 Add integration test to check new validation 2025-10-29 15:40:45 +01:00
Andrés Moya
70143f8ae3 🐛 Fix theme renaming and small refactor tokens forms validation 2025-10-29 15:40:45 +01:00
Xaviju
6c824651df 🎉 Add copy shortands button to panels (#7580)
* 🎉 Add copy shorthands button to panels
* 🎉 Add shorthand for strokes
* 🎉 Add shorthand for fonts
* 🎉 Add shorthand for borders
* 🎉 Add shorthand for padding
* 🎉 Add shorthand for grid
* 🎉 Add shorthand for layout element
* 🐛 Refactor to fix hook rendering
2025-10-29 13:51:36 +01:00
David Barragán Merino
1b81ddebb4 🐛 Fix some paths and add missed nginx config file for the storybook docker image 2025-10-29 13:46:29 +01:00
David Barragán Merino
6076df5c80 🎉 Detach storybook from the frontend build process 2025-10-29 13:45:54 +01:00
Alejandro Alonso
6d2d66a079 Merge pull request #7634 from penpot/alotor-fix-editable-label
🐛 Fix problem with certain text input and drag/drop
2025-10-29 12:50:03 +01:00
Alejandro Alonso
239af4fb82 🐛 Fix problem with text grow types 2025-10-29 12:40:11 +01:00
alonso.torres
0ad4a9ca7e 🐛 Fix problem with certain text input and drag/drop 2025-10-29 12:35:13 +01:00
David Barragán Merino
034463e63a 🐛 Fix some paths and add missed nginx config file for the storybook docker image 2025-10-29 12:02:32 +01:00
Eva Marco
aadc1aac1c 🐛 Fix some error translations 2025-10-29 11:14:20 +01:00
Elena Torró
2cdc76f1af Merge pull request #7573 from penpot/superalex-select-boards-to-export-to-pdf
 Select boards to export to PDF
2025-10-29 10:13:32 +01:00
alonso.torres
23f49237f8 🐛 Fix problem with plugins generating code for pages different than current one 2025-10-29 10:08:41 +01:00
Xaviju
93fb54c116 Enable single color-space selector for styles and computed… (#7525)
*  Enable single color-space selector for styles and computed tab
2025-10-29 09:53:37 +01:00
Alejandro Alonso
7565bb8d24 Merge pull request #7466 from penpot/bameda-storybook-detachment
🎉 Detach storybook from the frontend build process
2025-10-29 09:53:18 +01:00
Alejandro Alonso
0d394ee962 Merge pull request #7593 from penpot/eva-fix-some-translations
🐛 Fix some error translations
2025-10-29 09:36:06 +01:00
Alejandro Alonso
c4bebc1b0a Merge pull request #7625 from penpot/elenatorro-12374-fix-remove-selection
🐛 Fix text selection
2025-10-29 09:35:56 +01:00
Elena Torro
6edc29dce2 🐛 Fix text selection 2025-10-29 09:20:51 +01:00
Eva Marco
d773e3a966 🐛 Fix some error translations 2025-10-29 09:20:07 +01:00
Alejandro Alonso
e18aef1d39 Merge pull request #7610 from mdbenito/fix/conflicting-selection-shortcut-text-shape
🐛 Fix conflicting shortcut in text editor
2025-10-29 08:45:05 +01:00
Alejandro Alonso
b033690239 Merge pull request #7618 from penpot/andy-docs-typography-token
📚 Add typography token to the user guide
2025-10-29 08:22:20 +01:00
Alejandro Alonso
9f732eb45a Merge pull request #7595 from penpot/esther-moreno-user-guide-new-architecture
📚 New architecture in user guide
2025-10-29 08:02:45 +01:00
Alejandro Alonso
474453a503 Merge pull request #7594 from penpot/eva-fix-dropdown-submenu
🐛 Fix submenu visibility
2025-10-29 07:53:06 +01:00
Alejandro Alonso
c3d40659a9 Merge pull request #7600 from penpot/elenatorro-12344-fix-different-text-span-font-sizes
🔧 Add support for text spans of different sizes
2025-10-29 07:25:49 +01:00
David Barragán Merino
15e2b35afc 🎉 Detach storybook from the frontend build process 2025-10-28 20:58:50 +01:00
Elena Torró
ad15887d57 Merge pull request #7623 from penpot/superalex-fix-nested-fills-for-shapes-with-svg-attrs
🐛 Fix nested fills for shapes with svg attrs
2025-10-28 16:01:27 +01:00
Elena Torró
d01f921344 Merge pull request #7624 from penpot/superalex-fix-prevent-rendering-of-unused-fill-slots-in-shapes
🐛 Prevent rendering of unused fill slots in shapes
2025-10-28 15:54:51 +01:00
Alejandro Alonso
9e035ec4fe Merge pull request #7605 from penpot/ladybenko-fix-text-playground-crash
🔧 Fix text-related playgrounds (wasm)
2025-10-28 14:11:52 +01:00
Alejandro Alonso
fbacdf0351 🔧 Fix shapes-related playgrounds (wasm) 2025-10-28 14:09:24 +01:00
Alejandro Alonso
3f4d699395 🐛 Prevent rendering of unused fill slots in shapes 2025-10-28 13:35:34 +01:00
Alejandro Alonso
1626371337 Merge pull request #7619 from penpot/elenatorro-11889-fix-text-span-selection
🐛 Fix data-itype for text spans
2025-10-28 13:33:19 +01:00
Marina López
4d8a70f1fa Improvements payments 2025-10-28 12:36:32 +01:00
Alejandro Alonso
14d5de29da 🐛 Fix nested fills for shapes with svg attrs 2025-10-28 12:25:57 +01:00
Esther Moreno
df718c940f 📚 New architecture in user guide 2025-10-28 11:04:09 +01:00
Elena Torro
80c78d9cd4 🐛 Fix pasting text within an existing text 2025-10-28 09:39:52 +01:00
Pablo Alba
e2ce226814 🐛 Fix remove flex button doesn’t work within variant 2025-10-28 09:38:38 +01:00
Elena Torro
28c4c1a286 🐛 Fix data-itype for text spans 2025-10-27 16:55:51 +01:00
alonso.torres
f64105ad08 🐛 Fix problem with changing gap in flex layout 2025-10-27 16:29:59 +01:00
Andres Gonzalez
a346d29d76 📚 Add typography token to the user guide 2025-10-27 15:18:14 +01:00
Ingrid Pigueron
ccb7b41b3a 🌐 Add translations for: French
Currently translated at 98.3% (1923 of 1956 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/fr/
2025-10-27 12:02:59 +00:00
Elena Torro
2c37c5c8ed 🔧 Add support for text spans of different sizes 2025-10-27 12:43:41 +01:00
Andrés Moya
ed767d9a5b 🐛 Fix library update notificacions showing when they should not 2025-10-27 11:14:41 +01:00
Miguel de Benito Delgado
57bfca4062 🐛 Maintain selection after font change 2025-10-26 12:02:20 +00:00
Miguel de Benito Delgado
e9dcd64463 🐛 Fix conflicting shortcut in text editor 2025-10-26 11:11:50 +00:00
Belén Albeza
b498056c01 🔧 Fix text-related playgrounds (wasm) 2025-10-24 14:35:28 +02:00
Andrés Moya
81f851cad4 🔧 Deactivate debug traces for fonts module 2025-10-24 11:49:43 +02:00
Pablo Alba
245190f4f9 🐛 Fix variant validation when nil 2025-10-24 10:59:16 +02:00
Alejandro Alonso
479ce99b32 Improve setting svg attrs in wasm 2025-10-24 10:35:30 +02:00
Alejandro Alonso
6290b88d2e Merge pull request #7601 from penpot/alotor-fix-text-grow-type-problem
🐛 Fix problem with text grow types
2025-10-24 09:45:47 +02:00
Elena Torró
dba718b850 Merge pull request #7484 from penpot/superalex-fix-text-line-height-values-are-wrong
🐛 Text line-height values are wrong
2025-10-24 08:49:35 +02:00
alonso.torres
7c1205018b 🐛 Fix problem with text grow types 2025-10-23 17:39:18 +02:00
Elena Torró
89763d7c5a Merge pull request #7554 from penpot/azazeln28-fix-text-editor-v2-issues
🐛 Fix text editor v2 render integration issues
2025-10-23 15:55:54 +02:00
Aitor Moreno
7f6af6179b 🐛 Fix paste when collpaseNode is a br 2025-10-23 15:06:32 +02:00
Aitor Moreno
ceb184782f 🐛 Fix text editor paste inline/paragraph 2025-10-23 15:06:01 +02:00
Aitor Moreno
247c5c3700 Merge pull request #7588 from penpot/elenatorro-fix-text-tests
🔧 Fix text align selrect
2025-10-23 15:04:48 +02:00
Pablo Alba
0882c448f6 📎 Cleanup log files 2025-10-23 14:34:26 +02:00
Belén Albeza
f8cebb9d63 🐛 Fix scroll bar in design tab (#7582)
* 🐛 Fix scroll bar in design tab

* ♻️ Remove deprecated css tokens in options.scss
2025-10-23 14:11:11 +02:00
Alejandro Alonso
1e248c7177 🐛 Fix demo accounts creation 2025-10-23 13:45:11 +02:00
Elena Torró
351a35dad6 Merge pull request #7574 from penpot/azazeln28-refactor-text-struct-naming
♻️ Rename textleafs and inline to textspan
2025-10-23 13:39:36 +02:00
Aitor Moreno
eb088c31c1 🔧 Rename textleafs and inlines to keep coherence between render and editor 2025-10-23 13:04:21 +02:00
Belén Albeza
45af469a11 🐛 Fix invite selection copy
* 🐛 Fix selected invitations copy not being localized/pluralized

*  Add integration test for team invites + fixes unaccessible dom
2025-10-23 12:04:34 +02:00
Eva Marco
232f2271d3 🐛 Fix submenu visibility 2025-10-23 11:52:03 +02:00
Elena Torro
a30315c91c 🔧 Fix text align selrect and update regression tests 2025-10-23 11:44:40 +02:00
Pablo Alba
04542e1e66 Add variants to plugins API 2025-10-23 10:52:10 +02:00
Alejandro Alonso
36c986d8e8 🐛 Fix file doesn’t open after deleting the library used in it 2025-10-23 09:51:10 +02:00
Alejandro Alonso
38c3b2eaba Merge pull request #7584 from penpot/alotor-fix-flex-issue
🐛 Fix problem with flex type conversions
2025-10-22 16:49:56 +02:00
alonso.torres
98e91ecda5 🐛 Fix problem with flex type conversions 2025-10-22 16:03:51 +02:00
Alejandro Alonso
54ac64db4b Merge pull request #7578 from penpot/supealex-fix-selected-colors-children-shapes-in-multiple-selection
🐛 Fix selected colors not showing colors from children shapes in multiple selection
2025-10-22 15:18:58 +02:00
Alejandro Alonso
30ca6bf6ff 🐛 Fix selected colors not showing colors from children shapes in multiple selection 2025-10-22 14:53:06 +02:00
David Barragán Merino
81a364dfc4 🐳 Set default values for maxmemory and maxmemory-policy in Valkey 2025-10-22 13:43:30 +02:00
Pablo Alba
c6b9954af8 🐛 Fix nested variant in a component doesn't keep inherited overrides 2025-10-22 13:35:22 +02:00
Alejandro Alonso
f120cf82d3 Select boards to export to PDF 2025-10-22 13:19:10 +02:00
Belén Albeza
7ec335ae96 🐛 Fix export element crashing the app 2025-10-22 13:02:55 +02:00
Eva Marco
8dcc46aba8 🐛 Fix color row opacity (#7550) 2025-10-22 12:20:58 +02:00
Xaviju
058a555594 🎉 Add shadow panel to inspect styles tab (#7566) 2025-10-22 12:17:14 +02:00
Luis de Dios
e073b89604 🐛 Fix property input remains editable after keeping default property name (#7549)
* 🐛 Fix property input remains focused when keeping default property name

* 📎 PR changes
2025-10-22 10:48:03 +02:00
Elena Torró
140290cd60 Merge pull request #7556 from penpot/ladybenko-12362-fix-underline-spacing
🐛 Fix underline not matching spacing/thickness
2025-10-22 10:21:48 +02:00
Pablo Alba
5e6af5aea9 🐛 Fix text override is lost after switch 2025-10-22 09:43:12 +02:00
Alejandro Alonso
5df2a740b9 Merge pull request #7571 from penpot/superalex-fix-cleaning-nested-fills
🐛 Fix cleaning nested fills
2025-10-21 17:05:00 +02:00
Pablo Alba
fd596a1371 🐛 Fix incorrect behavior of Alt + Drag for variants 2025-10-21 17:02:10 +02:00
Belén Albeza
87221eb7db 🐛 Fix underline not matching spacing/thickness 2025-10-21 16:57:02 +02:00
Aitor Moreno
69f2e131d7 Merge pull request #7570 from penpot/elenatorro-12386-fix-missplaced-text-strokes
🐛 Fix texts offset-y calculation when there are multiple lines and stroke paints
2025-10-21 16:46:53 +02:00
Alejandro Alonso
69da63e01c 🐛 Fix cleaning nested fills 2025-10-21 16:45:53 +02:00
Elena Torro
dc689f9756 🐛 Fix texts offset-y calculation when there are multiple lines and stroke paints 2025-10-21 16:13:40 +02:00
Marina López
82e1a5003c 🐛 Fix condition report feedback 2025-10-21 15:29:06 +02:00
Andrey Antukh
024697ff87 Add cause stack trace logging on ui error boundary 2025-10-21 15:04:53 +02:00
alonso.torres
fc4b717287 🐛 Fix problem with CI 2025-10-21 14:45:59 +02:00
Marina López
9e8cdc8a3f 🐛 Fix search shortcut 2025-10-21 13:28:31 +02:00
Elena Torro
a51fd009bc 🔧 Improve text tiles intersection on changes 2025-10-21 13:21:02 +02:00
David Barragán Merino
f795f20ef8 📎 Notify about failures in releasing and creating docker images 2025-10-21 13:16:04 +02:00
Eva Marco
ca21e7e8b4 🐛 Fix font size placeholder 2025-10-21 12:27:15 +02:00
alonso.torres
93e7f2950b 🐛 Fix problem with multiple selection and shadows 2025-10-21 12:27:14 +02:00
Xaviju
d0e5d0d952 Display resolved value for composite typography tokens (#7537)
*  Display resolved value for composite typography tokens tooltip

*  Add missing key to iteration
2025-10-21 11:30:34 +02:00
Andrey Antukh
e4c07e0ec0 Merge staging into develop 2025-10-21 11:23:59 +02:00
alonso.torres
068caf2784 Merge remote-tracking branch 'origin/staging' into develop 2025-10-21 11:19:21 +02:00
Xavier Julian
436bc23da4 🐛 Remove duplicated tokens on stroke panel 2025-10-21 10:56:38 +02:00
Pablo Alba
579de6558a 🐛 Fix on copy instance inside a components chain touched are missing 2025-10-21 10:37:07 +02:00
Pablo Alba
2d45cba36c 🐛 Fix Restoring a variant from another file makes it overlap 2025-10-21 10:09:50 +02:00
Alejandro Alonso
cf21ffb30f Merge pull request #7528 from penpot/alotor-set-children
 Add set_children granular methods for performance
2025-10-21 09:57:22 +02:00
Elena Torró
7a2fe232d5 Merge pull request #7527 from penpot/ladybenko-12329-break-editor-word
🐛 Make internal DOM of text editor v2 break words as the render engine does
2025-10-21 09:41:15 +02:00
Alejandro Alonso
9e17a0e65d 🐛 Fix unread comments 2025-10-21 09:30:01 +02:00
Pablo Alba
220c27c354 🐛 Fix nested variant in a component doesn't keep inherited overrides (2) 2025-10-20 18:28:10 +02:00
Pablo Alba
b0e4257e56 📚 Remove wrong line on CHANGES 2025-10-17 14:20:31 +02:00
Pablo Alba
b3cb7df33c 🐛 Fix nested variant in a component doesn't keep inherited overrides 2025-10-17 14:01:54 +02:00
Pablo Alba
fec420b6e9 🐛 Fix variants not syncronizing tokens on switch 2025-10-17 13:46:49 +02:00
Eva Marco
35af5455a0 🐛 Fix dropdown width (#7534) 2025-10-17 13:39:29 +02:00
AlexTECPlayz
597fba79cc 🌐 Add translations for: Romanian
Currently translated at 99.8% (1953 of 1956 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/ro/
2025-10-17 13:07:28 +02:00
Luis de Dios
216b2d3072 🐛 Fix drag & drop functionality is swapping instead or reordering (#7489)
* 🐛 Fix drag & drop functionality is swapping instead or reordering

* ♻️ SCSS improvements
2025-10-17 12:12:34 +02:00
Eva Marco
bbc6709943 🐛 Fix applying color tokens on a row from colorpicker (#7524) 2025-10-17 11:10:10 +02:00
Eva Marco
14f6e22610 🐛 Fix composite token placeholders (#7526)
* 🐛 Fix composite token placeholders

* 📚 Recover some translations
2025-10-17 10:57:32 +02:00
Eva Marco
2f27a78bc0 🐛 Fix color row erros from review (#7516)
* 🐛 Fix text Ellipsis on token color row

* 🐛 Fix show token only on first stroke

* 🐛 Fix detach broken token
2025-10-17 10:39:41 +02:00
Marina López
f5761066a9 Merge pull request #7511 from penpot/marina-improve-users-give-feedback
 Improve the way users give us feedback
2025-10-17 10:19:34 +02:00
Andrey Antukh
3665bccaed Merge remote-tracking branch 'origin/staging' into develop 2025-10-17 09:43:30 +02:00
Andrey Antukh
fbbee98c3d Add proper backend integration of for new feedback form 2025-10-17 09:40:27 +02:00
Marina López
854ad5bb4d Improve the way users give us feedback 2025-10-17 09:39:58 +02:00
Andrey Antukh
a32f44a62c 🐛 Use correct error boundary fallback on ui ns 2025-10-17 09:39:58 +02:00
Andrey Antukh
95f58ffda5 Allow add attachements on emails 2025-10-17 09:39:58 +02:00
Andrey Antukh
e8e27c25c0 💄 Fix naming on several components under ui ns
Following the current naming convention
2025-10-17 09:39:58 +02:00
Andrey Antukh
42c416e3cb 📎 Add user feedback defaults to backend scripts/_env 2025-10-17 09:39:58 +02:00
Andrés Moya
5ad04e0f4c 🐛 Fix error when selecting set in theme 2025-10-16 16:17:16 +02:00
Belén Albeza
9f4db4479c 🐛 Make internal DOM of text editor v2 break words as the render engine does 2025-10-16 15:55:53 +02:00
alonso.torres
66997d2bc9 Add set_children granular methods for performance 2025-10-16 15:33:08 +02:00
Alejandro Alonso
7350329658 🐛 Filter svg attrs supported in wasm 2025-10-16 14:48:22 +02:00
Elena Torró
544b118925 Merge pull request #7361 from penpot/azazeln28-feat-dom-textarea-position
🎉 Text Editor DOM textarea position
2025-10-16 14:30:41 +02:00
Alejandro Alonso
8ceb909cda Merge pull request #7490 from penpot/elenatorro-12258-fix-text-shapes-intersection
🐛 Fix text tiles intersection
2025-10-16 14:23:41 +02:00
Elena Torro
af54e6ccc2 🔧 Fix text layout extrect intersection and refactor calculate_extrect function 2025-10-16 14:00:59 +02:00
Elena Torro
6ef0b8fd16 🔧 Update fixed visual tests 2025-10-16 14:00:54 +02:00
Alejandro Alonso
4a6d143a15 Merge pull request #7522 from penpot/alotor-render-performance
 New render small performance optimizations
2025-10-16 13:45:49 +02:00
David Barragán Merino
07dedbd3bb 📎 Fix registry uri
Signed-off-by: David Barragán Merino <david.barragan@kaleidos.net>
2025-10-16 13:06:34 +02:00
Aitor Moreno
7ca8bf32b2 🎉 Set DOM text editor element caret 2025-10-16 12:59:24 +02:00
alonso.torres
2e6fb1b9c5 New render small performance optimizations 2025-10-16 12:40:29 +02:00
AlexTECPlayz
43b03b9714 🌐 Add translations for: Romanian
Currently translated at 99.8% (1953 of 1956 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/ro/
2025-10-16 12:07:26 +02:00
Alejandro Alonso
8e8d46b314 🐛 Fix performance macros disabled in production mode 2025-10-16 12:01:29 +02:00
Eva Marco
e964f9820e 🐛 Fix tooltip position of proportion lock button (#7519) 2025-10-16 11:40:19 +02:00
Pablo Alba
d933e91c6c 🐛 Fix variants not syncronizing tokens on switch 2025-10-16 11:21:18 +02:00
Eva Marco
24264e7d8a 🎉 Replace numeric inputs on layout menus (#7488)
* 🎉 Replace numeric inputs on layout menus

* 🎉 Add numeric inputs on gaps

* ♻️ Refactor scss file

* 🐛 Fix comments
2025-10-16 10:05:25 +02:00
Xaviju
5b77df997b 🐛 Remove color validation for non-color tokens in strokes (#7513) 2025-10-16 09:54:50 +02:00
Xaviju
968274096d 🐛 Fix visual glitch in transparent background for swatch component (#7509) 2025-10-16 09:54:33 +02:00
Alejandro Alonso
392e3ac34e Merge pull request #7507 from penpot/elenatorro-11974-fix-resize-on-blocked-shapes
🐛 Fix resize on blocked shapes from the viewport
2025-10-16 09:17:13 +02:00
Alejandro Alonso
9266ace537 Merge pull request #7514 from penpot/ladybenko-12293-fix-scroll-inspect
🐛 Fix scrollbar in the inspect tab
2025-10-16 07:07:56 +02:00
Elena Torro
e8336a401e 🐛 Do not show resize controls when a selected shape is blocked 2025-10-16 06:43:34 +02:00
Elena Torro
18048a4b2e 🐛 Do not select a blocked frame when clicking its name 2025-10-16 06:42:45 +02:00
Elena Torro
e28d4eaff1 🐛 Do not allow to resize a shape that is blocked from the viewport 2025-10-16 06:42:45 +02:00
Alejandro Alonso
fae574796f Merge pull request #7512 from penpot/elenatorro-11963-change-font-styles-label
🌐 Add font-style label on workspace assets
2025-10-16 06:36:39 +02:00
Belén Albeza
b057ed1b9a 🐛 Fix scroll on inspect tab 2025-10-15 15:30:27 +02:00
Elena Torro
db59209b21 🌐 Add font-style label on workspace assets 2025-10-15 14:41:15 +02:00
Alejandro Alonso
a62f1fb46f Merge pull request #7505 from penpot/elenatorro-review-extrect
🔧 Fix extrect and selrect debug interactivity
2025-10-15 14:02:22 +02:00
Alejandro Alonso
ffd2aa03a9 Merge pull request #7510 from penpot/alotor-bugfix-pan-with-guides
🐛 Fix pan cursor not disabling viewport guides
2025-10-15 13:36:12 +02:00
Xaviju
f1ebcaf635 Add composite typography token to text panel (#7496) 2025-10-15 13:21:30 +02:00
alonso.torres
6a4d0f05bc 🐛 Fix pan cursor not disabling viewport guides 2025-10-15 13:02:56 +02:00
Alejandro Alonso
4d751c5acd Merge pull request #7504 from penpot/azazeln28-feat-webgl-error
🎉 Add debug and alert when WebGL is unsupported
2025-10-15 12:51:45 +02:00
Alejandro Alonso
2c5abb0cbf Merge pull request #7506 from penpot/niwinz-staging-hotfix-6-comments-threads
 Add minor comment threads queries optimization
2025-10-15 12:04:42 +02:00
Andrey Antukh
7f6bffdbfc Add minor comment threads queries optimization 2025-10-15 11:45:24 +02:00
Andrey Antukh
9a5efe8671 Merge remote-tracking branch 'origin/staging' into develop 2025-10-15 11:32:15 +02:00
Andrey Antukh
e0dd8247d4 Merge branch 'main' into staging 2025-10-15 11:25:36 +02:00
Andrey Antukh
1f65e2f560 Merge branch 'staging' into develop 2025-10-15 11:22:03 +02:00
Andrey Antukh
abad6a15bc Merge branch 'main' into staging 2025-10-15 11:21:43 +02:00
Alejandro Alonso
bf6874a96d Merge pull request #7460 from penpot/ladybenko-12205-cap-fills-text
 Cap the amount of text fills
2025-10-15 11:17:32 +02:00
Alejandro Alonso
7cdb1925d6 Merge pull request #7497 from penpot/ladybenko-12287-text-fills
🐛 Fix adding/removing identical text fills
2025-10-15 11:00:00 +02:00
Alejandro Alonso
aec4464749 Merge pull request #7498 from penpot/niwinz-staging-hotfix-4
 Make worker subsystem more resilent to redis restarts
2025-10-15 10:39:04 +02:00
Alejandro Alonso
1d14644250 Merge pull request #7494 from penpot/niwinz-staging-hotfix-3
 Use system clock for check invitation expiration
2025-10-15 10:23:48 +02:00
Alejandro Alonso
fad148e6a6 📎 Reorder jvm opts on _env 2025-10-15 10:15:06 +02:00
Elena Torro
3c05067c99 🔧 Fix extrect and selrect debug interactivity 2025-10-15 10:10:24 +02:00
Aitor Moreno
bbb78904fb 🎉 Add debug and alert when WebGL is unsupported 2025-10-15 10:06:02 +02:00
Alejandro Alonso
879caf66eb Merge pull request #7493 from penpot/niwinz-staging-hotfix-2
🐛 Fix corrner case on error report validation
2025-10-15 09:51:52 +02:00
Andrey Antukh
4daf086214 📎 Backport circleci config from develop 2025-10-15 09:33:42 +02:00
Andrey Antukh
c8b3a41117 📎 Backport all github workflows from develop 2025-10-15 09:33:42 +02:00
Andrey Antukh
c9dcc8a4ee 🐛 Add migration for clearing :objects nil from components
on the local library
2025-10-15 09:33:40 +02:00
Stephan Paternotte
4739c4730c 🌐 Add translations for: Dutch
Currently translated at 99.8% (1953 of 1956 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/nl/
2025-10-14 19:08:02 +02:00
Edgars Andersons
603bb860ba 🌐 Add translations for: Latvian
Currently translated at 95.3% (1866 of 1956 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/lv/
2025-10-14 19:08:01 +02:00
Yaron Shahrabani
55d9ca1439 🌐 Add translations for: Hebrew
Currently translated at 99.4% (1945 of 1956 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/he/
2025-10-14 19:07:59 +02:00
Oğuz Ersen
a2f397c329 🌐 Add translations for: Turkish
Currently translated at 99.8% (1953 of 1956 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/tr/
2025-10-14 19:07:57 +02:00
Roman D
ada4e72c27 🌐 Add translations for: Russian
Currently translated at 78.2% (1530 of 1956 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/ru/
2025-10-14 19:07:54 +02:00
Andrey Antukh
17376dfa3f Add mark-file-as-trimmed srepl helper 2025-10-14 19:04:02 +02:00
Andrey Antukh
8d65e1cc94 Simplify reset-password srepl helper 2025-10-14 19:04:02 +02:00
Andrey Antukh
d4de367499 🐛 Fix ::sm/set schema validation
It has several corner cases where set specific type
is not checked. It also now checks for ordered type
specifically when ordered is specified
2025-10-14 19:04:02 +02:00
Andrey Antukh
25521b18ff Make the restriction errors report as warning to logging 2025-10-14 19:04:02 +02:00
Andrey Antukh
39bdf026ca 🐛 Fix corrner case on error report validationt 2025-10-14 19:03:59 +02:00
Andrey Antukh
1b6a833166 🐛 Add migration for fix fills on position-data 2025-10-14 18:11:42 +02:00
Andrey Antukh
928dcf5cb8 🐛 Fix migrations set decoding on binfile import
that causes incorrect migration ordering on the table
2025-10-14 18:11:42 +02:00
Elena Torró
12e91751c3 🔧 Improve debugging UI (#7500) 2025-10-14 17:29:04 +02:00
David Barragán Merino
0f0c8466be 📎 Add bundle version to the metadata in S3 2025-10-14 16:30:31 +02:00
Belén Albeza
204d0dfb9d Add integration test to check fills limit in UI 2025-10-14 16:14:53 +02:00
Belén Albeza
e4a3fc3940 Limit the amount of text fills passed to wasm 2025-10-14 16:05:03 +02:00
Andrey Antukh
5ae173f01c Make worker subsystem more resilent to redis restarts 2025-10-14 15:48:54 +02:00
Belén Albeza
840c1f59bc 🐛 Fix adding/removing identical text fills 2025-10-14 15:34:44 +02:00
Francis Santiago
29dc99deae 🔧 Replace ADD with COPY in Dockerfiles to fix hadolint warnings 2025-10-14 13:53:48 +02:00
Andrey Antukh
f7b3913c71 Use system clock for check invitation expiration
instead of db time
2025-10-14 13:35:50 +02:00
alonso.torres
025f0d2fdb 🐛 Fix problem with tiles and transform 2025-10-14 12:51:48 +02:00
Andrey Antukh
85591bd579 Merge branch 'main' into staging 2025-10-14 12:30:21 +02:00
Andrey Antukh
b3ae54775b 📎 Update changelog 2025-10-14 12:26:56 +02:00
Eva Marco
045aa7c788 🎉 Add tokens to color selection (#7447)
* 🎉 Add tokens to color row

* 🎉 Add color-token to stroke input

* 🐛 Fix change token on multiselection with groups

* 🎉 Create token colors on selected-colors section

* ♻️ Fix comments
2025-10-14 11:17:14 +02:00
Alejandro Alonso
497282d964 Merge pull request #7491 from penpot/niwinz-staging-fix-fills-position-data
🐛 Add migration for fix fills on position-data
2025-10-14 10:45:25 +02:00
Andrey Antukh
362bb7d2f6 🐛 Add migration for fix fills on position-data 2025-10-14 10:34:19 +02:00
Alejandro Alonso
b4cd955484 🐛 Text line-height values are wrong 2025-10-14 07:53:37 +02:00
Andrey Antukh
55353b80a2 🔧 Simplfy circleci workflow dependencies 2025-10-13 18:54:47 +02:00
Andrey Antukh
c46ab38d58 🔧 Add missing construction_worker to commit checker regex 2025-10-13 18:54:40 +02:00
Andrey Antukh
0f3ca67773 🔧 Simplfy circleci workflow dependencies 2025-10-13 18:53:39 +02:00
Andrey Antukh
1c06c87acf 🔧 Add missing construction_worker to commit checker regex 2025-10-13 18:53:39 +02:00
Andrey Antukh
d532558bab Merge remote-tracking branch 'origin/staging' into develop 2025-10-13 18:41:18 +02:00
Andrey Antukh
a4192ce835 🐛 Fix incorrect file data migration from db to legacy-db 2025-10-13 18:41:02 +02:00
Andrey Antukh
d3e28a8307 🐛 Set correct name to tokens lib data reader 2025-10-13 18:41:02 +02:00
Andrey Antukh
3122917872 Add more file-grained validation for tokens lib migration helpers 2025-10-13 18:41:02 +02:00
Andrey Antukh
95df07a364 Add strong file schema validation after file data migration 2025-10-13 18:41:02 +02:00
Andrey Antukh
71ed845307 Merge remote-tracking branch 'origin/staging' into develop 2025-10-13 16:35:53 +02:00
Andrey Antukh
c9761684c1 🐛 Fix regression introduced on duplicate-id on token-sets commit 2025-10-13 16:35:17 +02:00
Andrey Antukh
dd35c82824 Merge remote-tracking branch 'origin/staging' into develop 2025-10-13 15:19:07 +02:00
Andrey Antukh
515b381f66 🐛 Fix random failure of tokens lib test 2025-10-13 15:16:53 +02:00
Andrés Moya
160873c63e 🐛 Remove duplicated token set ids 2025-10-13 15:16:53 +02:00
Andrey Antukh
fc35dc77ce 🐛 Enable migrations on calculate file library summary 2025-10-13 14:52:39 +02:00
Andrey Antukh
b5648e1241 ⬆️ Update yarn to 2.10.3 on frontend module 2025-10-13 14:52:39 +02:00
Andrey Antukh
d07e00da21 🐛 Fix incorrect filtering of unread comment threads
Do not return threads for deleted files
2025-10-13 14:52:39 +02:00
Xaviju
253605f6cc 🎉 Add text panel to inspect styles tab (#7413) 2025-10-13 14:20:55 +02:00
Xaviju
2548bec651 🐛 Fix visual glitch in background for swatch component (#7468) 2025-10-13 14:20:14 +02:00
Andrey Antukh
da5da00bd4 📚 Update changelog 2025-10-13 14:08:33 +02:00
Andrey Antukh
72b44240b1 Merge branch 'develop' into staging 2025-10-13 13:30:43 +02:00
Andrey Antukh
b21f79490b Merge remote-tracking branch 'origin/staging' into develop 2025-10-13 13:22:26 +02:00
Andrey Antukh
db09eacd4c Merge remote-tracking branch 'origin/main' into staging 2025-10-13 13:22:07 +02:00
Andrey Antukh
731afb0e70 📚 Update changelog 2025-10-13 13:19:18 +02:00
Pablo Alba
1080251d9a Add missing variant-switch tracking event 2025-10-13 13:01:02 +02:00
Andrey Antukh
ea5bfbd72d 📎 Add token-typography-composite config flag to defaults 2025-10-13 12:54:27 +02:00
David Barragán Merino
b10dcb2d63 🐳 Prevent error if config.js is a bind mounted file 2025-10-13 12:42:23 +02:00
Andrey Antukh
c4cd665594 📎 Enable redis-cache flag on devenv start scripts 2025-10-13 12:32:29 +02:00
Andrey Antukh
1eb6f33bdd Enable optional caching of results for file summary RPC methods 2025-10-13 12:32:29 +02:00
Andrey Antukh
62dffd30a4 ♻️ Refactor redis internal API
The main idea behind this refactor is make the
API less especialized for specific use of out internal
submidules and make it more general and usable
for more general purposes (per example cache)
2025-10-13 12:32:29 +02:00
Andrey Antukh
12a4934c41 Allow pass :load-data? false to get-file 2025-10-13 12:32:29 +02:00
Andrey Antukh
e3bd9148f2 Add ::sm/atom to schemas 2025-10-13 12:32:29 +02:00
Alejandro Alonso
2b7bd8fa5c 🐛 Fix deleted files are accesible 2025-10-13 12:24:05 +02:00
Andrey Antukh
5717708b56 ♻️ Refactor file storage
Make it more scallable and make it easily extensible
2025-10-13 12:24:05 +02:00
Andrey Antukh
27bed84543 Improve netty io executor shutdown 2025-10-13 12:24:05 +02:00
Andrey Antukh
c6529f9585 🐛 Fix corner case on worker runner 2025-10-13 12:24:05 +02:00
Andrey Antukh
30e139ed10 🔥 Remove binary fills flag (#7462)
* 🐛 Add missing IEmptyableCollection protocol impl for wasm Shape

* 🔥 Remove frontend-binary-fills flag

*  Fix fill-limit integration tests

---------

Co-authored-by: Belén Albeza <belen@hey.com>
2025-10-13 12:14:25 +02:00
Andrey Antukh
0aadc3b6b3 Add management shared key authentication 2025-10-13 11:49:58 +02:00
Andrey Antukh
21a7ecb3fe 🔥 Remove obsolete code with object wrapping on components 2025-10-13 11:36:22 +02:00
Andrey Antukh
65a2b10875 Make component path mandatory on validations
And ensure it already present with a migration
2025-10-13 11:36:22 +02:00
Xavier Julian
9e676a7ab2 🐛 Fix unnecesarily overcomplated key generation 2025-10-13 11:30:47 +02:00
Xavier Julian
3d1933411b 🐛 Fix broken layout when multiple fill/strokes with tokens 2025-10-13 11:30:47 +02:00
VKing9
a44f1bb09c 🌐 Add translations for: Hindi
Currently translated at 92.2% (1805 of 1956 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/hi/
2025-10-13 11:26:55 +02:00
Henrik Allberg
65e59c8857 🌐 Add translations for: Swedish
Currently translated at 81.5% (1595 of 1956 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/sv/
2025-10-13 11:26:55 +02:00
Црнобог
2833854d8d 🌐 Add translations for: Serbian
Currently translated at 70.3% (1377 of 1956 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/sr/
2025-10-13 11:26:54 +02:00
Alejandro Alonso
19e367e112 🌐 Add translations for: Yoruba
Currently translated at 60.3% (1181 of 1956 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/yo/
2025-10-13 11:26:54 +02:00
Alejandro Alonso
3f731f57e6 🌐 Add translations for: Hausa
Currently translated at 63.7% (1247 of 1956 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/ha/
2025-10-13 11:26:54 +02:00
Stephan Paternotte
b740ee254e 🌐 Add translations for: Dutch
Currently translated at 99.6% (1949 of 1956 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/nl/
2025-10-13 11:26:53 +02:00
Sebastiaan Pasma
97d9480c8b 🌐 Add translations for: Dutch
Currently translated at 99.6% (1949 of 1956 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/nl/
2025-10-13 11:26:53 +02:00
Edgars Andersons
f1fcc77f74 🌐 Add translations for: Latvian
Currently translated at 94.6% (1852 of 1956 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/lv/
2025-10-13 11:26:52 +02:00
Ņikita K
d078c49fe7 🌐 Add translations for: Latvian
Currently translated at 94.6% (1852 of 1956 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/lv/
2025-10-13 11:26:52 +02:00
Denys Kisil
9d30a1c1e9 🌐 Add translations for: Ukrainian (ukr_UA)
Currently translated at 93.4% (1827 of 1956 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/ukr_UA/
2025-10-13 11:26:52 +02:00
Zvonimir Juranko
3b9f732b16 🌐 Add translations for: Croatian
Currently translated at 82.2% (1608 of 1956 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/hr/
2025-10-13 11:26:51 +02:00
Dário
0a9c191582 🌐 Add translations for: Portuguese (Portugal)
Currently translated at 80.6% (1578 of 1956 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/pt_PT/
2025-10-13 11:26:51 +02:00
Amerey.eu
cc6175d39c 🌐 Add translations for: Czech
Currently translated at 81.9% (1603 of 1956 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/cs/
2025-10-13 11:26:50 +02:00
Mikel Larreategi
b424c0f84b 🌐 Add translations for: Basque
Currently translated at 59.3% (1161 of 1956 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/eu/
2025-10-13 11:26:50 +02:00
Radek Sawicki
29495474b1 🌐 Add translations for: Polish
Currently translated at 58.0% (1136 of 1956 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/pl/
2025-10-13 11:26:49 +02:00
Nicola Bortoletto
7c0bd4ac9a 🌐 Add translations for: Italian
Currently translated at 99.4% (1945 of 1956 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/it/
2025-10-13 11:26:49 +02:00
william chen
b98f5a9851 🌐 Add translations for: Chinese (Traditional Han script)
Currently translated at 82.2% (1608 of 1956 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/zh_Hant/
2025-10-13 11:26:48 +02:00
Yaron Shahrabani
4d823af46d 🌐 Add translations for: Hebrew
Currently translated at 99.2% (1942 of 1956 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/he/
2025-10-13 11:26:48 +02:00
Linerly
ecec2db29e 🌐 Add translations for: Indonesian
Currently translated at 87.2% (1706 of 1956 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/id/
2025-10-13 11:26:47 +02:00
Alejandro Alonso
55d2d53a22 🌐 Add translations for: Arabic
Currently translated at 57.0% (1115 of 1956 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/ar/
2025-10-13 11:26:46 +02:00
Mahmoud A. Rabo
86f7bec171 🌐 Add translations for: Arabic
Currently translated at 57.0% (1115 of 1956 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/ar/
2025-10-13 11:26:45 +02:00
AlexTECPlayz
5c6d296e60 🌐 Add translations for: Romanian
Currently translated at 65.6% (1284 of 1956 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/ro/
2025-10-13 11:26:45 +02:00
George Lemon
bda6c61a11 🌐 Add translations for: Romanian
Currently translated at 65.6% (1284 of 1956 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/ro/
2025-10-13 11:26:44 +02:00
Allan Nordhøy
3aa966e553 🌐 Add translations for: Norwegian Bokmål
Currently translated at 8.3% (164 of 1956 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/nb_NO/
2025-10-13 11:26:44 +02:00
Marius
9ce0b9c86e 🌐 Add translations for: German
Currently translated at 89.0% (1741 of 1956 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/de/
2025-10-13 11:26:43 +02:00
Pablo Alba
42ab42fb56 🌐 Add translations for: German
Currently translated at 89.0% (1741 of 1956 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/de/
2025-10-13 11:26:43 +02:00
Hugo Figueira
7b60d386fb 🌐 Add translations for: Portuguese (Brazil)
Currently translated at 64.9% (1271 of 1956 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/pt_BR/
2025-10-13 11:26:42 +02:00
Anonymous
ae60a7260c 🌐 Add translations for: Chinese (Simplified Han script)
Currently translated at 92.6% (1813 of 1956 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/zh_Hans/
2025-10-13 11:26:42 +02:00
Çağlar Yeşilyurt
bfacdc414f 🌐 Add translations for: Turkish
Currently translated at 93.7% (1833 of 1956 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/tr/
2025-10-13 11:26:42 +02:00
Vint Prox
29628eea0a 🌐 Add translations for: Russian
Currently translated at 73.1% (1430 of 1956 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/ru/
2025-10-13 11:26:41 +02:00
The_BadUser
6d7723c36b 🌐 Add translations for: Russian
Currently translated at 73.1% (1430 of 1956 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/ru/
2025-10-13 11:26:40 +02:00
Anonymous
710008ee9e 🌐 Add translations for: Greek
Currently translated at 26.1% (511 of 1956 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/el/
2025-10-13 11:26:40 +02:00
Pablo Alba
a15be5c2d0 🌐 Add translations for: French
Currently translated at 94.7% (1853 of 1956 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/fr/
2025-10-13 11:26:40 +02:00
Aryiu
45a09928b3 🌐 Add translations for: Catalan
Currently translated at 54.8% (1073 of 1956 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/ca/
2025-10-13 11:26:39 +02:00
Hosted Weblate
bae5196d1e 🌐 Merge branch 'origin/develop' into Weblate. 2025-10-13 11:24:12 +02:00
Edgars Andersons
91fe7b2dd6 🌐 Add translations for: Latvian
Currently translated at 94.8% (1856 of 1956 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/lv/
2025-10-13 11:23:18 +02:00
Oğuz Ersen
df6448e32e 🌐 Add translations for: Turkish
Currently translated at 93.9% (1837 of 1956 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/tr/
2025-10-13 11:23:16 +02:00
Luis de Dios
a9a9245ab6 🐛 Fix component number has no singular translation string (#7469) 2025-10-13 11:22:25 +02:00
Eva Marco
e18f20666b 🔧 Add scss refactor as element on PR checklist (#7480) 2025-10-13 11:21:12 +02:00
Eva Marco
adafe0648c ♻️ Fix component schemas (#7481) 2025-10-13 11:20:43 +02:00
Andrey Antukh
1b9deecefc Make the binfile import process more resilient (#7464)
on small inconsistencies on file media object references
2025-10-13 11:13:10 +02:00
Nicola Bortoletto
666410602b 🌐 Add translations for: Italian
Currently translated at 99.6% (1949 of 1956 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/it/
2025-10-11 07:07:23 +02:00
Stephan Paternotte
c956600d64 🌐 Add translations for: Dutch
Currently translated at 99.8% (1953 of 1956 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/nl/
2025-10-08 18:07:31 +00:00
Edgars Andersons
2100c8a115 🌐 Add translations for: Latvian
Currently translated at 94.5% (1850 of 1956 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/lv/
2025-10-08 18:07:29 +00:00
Yaron Shahrabani
d4fd246622 🌐 Add translations for: Hebrew
Currently translated at 99.4% (1946 of 1956 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/he/
2025-10-08 18:07:25 +00:00
David Barragán Merino
71fd6640af 👷 Automate publication of docker images in a new release 2025-10-08 17:15:10 +02:00
Alonso Torres
40e9a78f67 Add telemetry for events performance measures (#7457) 2025-10-08 14:03:09 +02:00
Alejandro Alonso
551a25661f Improve ancestors modifiers performance 2025-10-08 12:10:18 +02:00
Luis de Dios
544bedf7c2 🎉 Reorder properties for a component (#7429)
* 🎉 Reorder properties when a component with variants is selected

* 🎉 Reorder properties when a single variant is selected

* ♻️ Refactor SCSS and component structure

* 📚 Update changelog

* 📎 PR changes (styling)

* 📎 PR changes (functionality)
2025-10-08 11:27:01 +02:00
Andrey Antukh
4937580585 🌐 Rehash and validate translation files 2025-10-07 18:38:28 +02:00
VKing9
dba0f11670 🌐 Add translations for: Hindi
Currently translated at 92.6% (1810 of 1954 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/hi/
2025-10-07 18:38:28 +02:00
Henrik Allberg
776af8ea22 🌐 Add translations for: Swedish
Currently translated at 81.7% (1597 of 1954 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/sv/
2025-10-07 18:38:28 +02:00
Црнобог
38e0d0035f 🌐 Add translations for: Serbian
Currently translated at 70.6% (1380 of 1954 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/sr/
2025-10-07 18:38:28 +02:00
Anonymous
f0c01d8714 🌐 Add translations for: Yoruba
Currently translated at 60.5% (1184 of 1954 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/yo/
2025-10-07 18:38:28 +02:00
Anonymous
678c4acdbc 🌐 Add translations for: Igbo
Currently translated at 26.4% (516 of 1954 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/ig/
2025-10-07 18:38:28 +02:00
Anonymous
9b76048c2f 🌐 Add translations for: Malay
Currently translated at 34.6% (678 of 1954 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/ms/
2025-10-07 18:38:28 +02:00
Anonymous
2cf98745d7 🌐 Add translations for: Hausa
Currently translated at 63.9% (1250 of 1954 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/ha/
2025-10-07 18:38:28 +02:00
Stephan Paternotte
267acc5b80 🌐 Add translations for: Dutch
Currently translated at 97.1% (1898 of 1954 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/nl/
2025-10-07 18:38:28 +02:00
Anonymous
ae38c8e840 🌐 Add translations for: Latvian
Currently translated at 94.6% (1850 of 1954 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/lv/
2025-10-07 18:38:27 +02:00
Edgars Andersons
1128303fa1 🌐 Add translations for: Latvian
Currently translated at 94.6% (1850 of 1954 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/lv/
2025-10-07 18:38:27 +02:00
Denys Kisil
5d1981047d 🌐 Add translations for: Ukrainian (ukr_UA)
Currently translated at 93.5% (1828 of 1954 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/ukr_UA/
2025-10-07 18:38:27 +02:00
al0cam
0dae2a3c24 🌐 Add translations for: Croatian
Currently translated at 82.3% (1610 of 1954 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/hr/
2025-10-07 18:38:27 +02:00
TheScientistPT
766accde29 🌐 Add translations for: Portuguese (Portugal)
Currently translated at 80.8% (1580 of 1954 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/pt_PT/
2025-10-07 18:38:27 +02:00
Anonymous
c5f8bd5bea 🌐 Add translations for: Czech
Currently translated at 82.1% (1605 of 1954 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/cs/
2025-10-07 18:38:27 +02:00
Amerey.eu
4edfcba350 🌐 Add translations for: Czech
Currently translated at 82.1% (1605 of 1954 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/cs/
2025-10-07 18:38:27 +02:00
Nicola Bortoletto
ce20059a4c 🌐 Add translations for: Italian
Currently translated at 96.9% (1895 of 1954 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/it/
2025-10-07 18:38:27 +02:00
william chen
27fa0c0721 🌐 Add translations for: Chinese (Traditional Han script)
Currently translated at 82.3% (1610 of 1954 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/zh_Hant/
2025-10-07 18:38:27 +02:00
Yaron Shahrabani
ee83a07674 🌐 Add translations for: Hebrew
Currently translated at 96.7% (1891 of 1954 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/he/
2025-10-07 18:38:27 +02:00
Linerly
57123569eb 🌐 Add translations for: Indonesian
Currently translated at 87.4% (1708 of 1954 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/id/
2025-10-07 18:38:27 +02:00
Anonymous
d112e83b0d 🌐 Add translations for: German
Currently translated at 89.2% (1743 of 1954 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/de/
2025-10-07 18:38:27 +02:00
Stas Haas
b259ca2cd1 🌐 Add translations for: German
Currently translated at 89.2% (1743 of 1954 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/de/
2025-10-07 18:38:27 +02:00
Rick Benetti
56db7078ae 🌐 Add translations for: Portuguese (Brazil)
Currently translated at 65.1% (1273 of 1954 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/pt_BR/
2025-10-07 18:38:27 +02:00
Anonymous
7a75002cc9 🌐 Add translations for: Chinese (Simplified Han script)
Currently translated at 92.9% (1817 of 1954 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/zh_Hans/
2025-10-07 18:38:27 +02:00
DoubleCat
77ad1f57be 🌐 Add translations for: Chinese (Simplified Han script)
Currently translated at 92.9% (1817 of 1954 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/zh_Hans/
2025-10-07 18:38:27 +02:00
Jun Fang
9f881e49e5 🌐 Add translations for: Chinese (Simplified Han script)
Currently translated at 92.9% (1817 of 1954 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/zh_Hans/
2025-10-07 18:38:27 +02:00
Anonymous
238578f243 🌐 Add translations for: Turkish
Currently translated at 73.1% (1429 of 1954 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/tr/
2025-10-07 18:38:27 +02:00
The_BadUser
49d9dd7161 🌐 Add translations for: Russian
Currently translated at 73.2% (1432 of 1954 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/ru/
2025-10-07 18:38:27 +02:00
Vin
be28a310f7 🌐 Add translations for: Russian
Currently translated at 73.2% (1432 of 1954 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/ru/
2025-10-07 18:38:27 +02:00
Anonymous
460aafbedf 🌐 Add translations for: French
Currently translated at 94.8% (1854 of 1954 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/fr/
2025-10-07 18:38:27 +02:00
Corentin Noël
9ba995edd9 🌐 Add translations for: French
Currently translated at 94.8% (1854 of 1954 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/fr/
2025-10-07 18:38:27 +02:00
Deleted User
85b15e4896 🌐 Add translations for: Spanish
Currently translated at 97.0% (1896 of 1954 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/es/
2025-10-07 18:38:27 +02:00
Anonymous
1420e8a59c 🌐 Add translations for: Spanish
Currently translated at 97.0% (1896 of 1954 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/es/
2025-10-07 18:38:27 +02:00
Hosted Weblate
3aa647e1f6 🌐 Update translation files
Updated by "Cleanup translation files" hook in Weblate.

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/
2025-10-07 18:38:27 +02:00
Pablo Alba
11b7b458bf 🐛 Auto-width changes to fixed when switching variants (#7449)
* 🐛 Auto-width changes to fixed when switching variants

* 📎 Fix typo on changes

---------

Co-authored-by: Andrey Antukh <niwi@niwi.nz>
2025-10-07 18:29:18 +02:00
Andrey Antukh
cfa607f57f Merge remote-tracking branch 'weblate/develop' into develop 2025-10-07 18:23:36 +02:00
Andrey Antukh
cea0143327 Add extra tenant validation for virtual clock dbg pannel 2025-10-07 18:21:13 +02:00
Andrey Antukh
b8158ffec8 Merge remote-tracking branch 'origin/staging' into develop 2025-10-07 16:03:17 +02:00
Pablo Alba
640894acd8 🐛 Fix Restoring a variant from another file makes it overlap (#7448) 2025-10-07 16:01:59 +02:00
Alejandro Alonso
90bfae3ec1 Merge pull request #7456 from penpot/elenatorro-12248-fix-shadows-order
🔧 Always return shadows in reverse order
2025-10-07 13:16:49 +02:00
Alejandro Alonso
73ed5f8bc5 Merge pull request #7402 from penpot/niwinz-develop-enhancements-3
 Add additional http middlewares
2025-10-07 13:00:30 +02:00
Andrey Antukh
2c1a8b59ba Add client header check middleware
As an additional csrf protection for API requests
2025-10-07 12:47:14 +02:00
Andrey Antukh
47d9c6f282 Add sec-fetch metadata middleware support 2025-10-07 12:47:14 +02:00
Andrey Antukh
14d53c224f 🔥 Remove unused auth-data cookie asignation 2025-10-07 12:47:12 +02:00
Elena Torró
a1b8eb7074 Merge pull request #7454 from penpot/elenatorro-12247-fix-line-height-min-value
🔧 Allow line height values from 0 to 1
2025-10-07 12:29:16 +02:00
Alejandro Alonso
e0f9bbb23f Merge pull request #7432 from penpot/niwinz-develop-virtual-clock
🎉 Add virtual clock support
2025-10-07 12:27:49 +02:00
Elena Torro
9b16a6bbd1 🔧 Always return shadows in reverse order 2025-10-07 12:26:51 +02:00
Marina López
fede63ac0b Update Design System template in carousel 2025-10-07 12:14:12 +02:00
Eva Marco
ea1ab7c23b 🐛 Fix modal title on edit token (#7453)
* 🐛 Fix modal title on edit token

* 🐛 Fix font size on numeric input

* ♻️ Update color token border on hover

* ♻️ Use swatch component on token pill
2025-10-07 12:11:40 +02:00
Andrey Antukh
61d9b57bc7 ♻️ Refactor internal tokens API
Mainly make it receive the whol cfg/system instead only props. This
makes the api more flexible for a future extending without the need
to change the api again.
2025-10-07 12:08:00 +02:00
Andrey Antukh
bd63598185 🎉 Add virtual clock implementation 2025-10-07 12:08:00 +02:00
Eva Marco
31af6aebbd 🐛 Fix swatch error on text without fills (#7451) 2025-10-07 10:08:46 +02:00
Andrey Antukh
cc5f86bc84 🐛 Set correct path if is not provided on sdk addComponent method 2025-10-07 09:57:41 +02:00
Elena Torro
68cd7075c0 🔧 Allow line height values from 0 to 1 2025-10-07 09:28:24 +02:00
Andrey Antukh
11ff64b362 Merge tag '2.10.1-RC3' 2025-10-06 12:12:27 +02:00
Andrey Antukh
57a7b5b1da Merge remote-tracking branch 'origin/staging' into develop 2025-10-06 12:12:05 +02:00
Andrey Antukh
cf24bdd7a8 Merge remote-tracking branch 'origin/main' into staging 2025-10-06 12:10:44 +02:00
Andrey Antukh
683db071d6 Merge remote-tracking branch 'origin/staging' into develop 2025-10-06 12:09:57 +02:00
Andrey Antukh
d3943b9162 Merge branch 'niwinz-staging-library-changes' into staging 2025-10-06 11:59:17 +02:00
Andrey Antukh
613acd5b29 📎 Update version on library/package.json file 2025-10-06 11:56:23 +02:00
Andrey Antukh
987dea8048 📚 Update changelog 2025-10-06 11:53:50 +02:00
Andrey Antukh
6b0d0a302f Enable variant attrs on SDK addComponent method 2025-10-06 11:53:50 +02:00
Andrey Antukh
588eb0b4fa ⬆️ Update shadow-cljs dependency on sdk 2025-10-06 11:53:50 +02:00
Andrey Antukh
b30cb0e084 Allow pass variant related attrs on add-component change 2025-10-06 11:53:50 +02:00
Andrey Antukh
9244501c6e Add variants/v1 feature to default features emited by sdk 2025-10-06 11:53:50 +02:00
Alonso Torres
d5b743c604 🐛 Fix problem with text in plugins (#7446) 2025-10-06 11:19:33 +02:00
Andrey Antukh
e38dd21307 ⬆️ Update exported dependencies 2025-10-06 10:56:04 +02:00
Andrey Antukh
8c91109c63 📚 Update changelog 2025-10-06 09:38:01 +02:00
Andrey Antukh
c3eabbdb25 📎 Enable the fdata/objects-map feature by default
Using config flags
2025-10-06 09:38:01 +02:00
Andrey Antukh
67661674e2 Make deleted fonts fixer to run with more granular stragegy
Instead of running it on all the file, only run it to local library
and the current page, reducing considerably the overhead of analyzing
the whole file on each file load.

It stills executes for page each time the page is loaded, and add
some kind of local cache for not doing repeated work each time page
loads is pending to be implemented in other commit.
2025-10-06 09:38:01 +02:00
Andrey Antukh
c70e7f3876 Add logging to frontend repo namespace 2025-10-06 09:38:01 +02:00
Andrey Antukh
0295f0f7c8 Add better workspace file indexing strategy
Improve file indexes initialization on workspace.

Instead of initialize indexes for all pages only initialize
indexes for the loaded page.
2025-10-06 09:38:01 +02:00
Andrey Antukh
54bb879cb6 📎 Add several missing imports on repl related namespaces 2025-10-06 09:38:01 +02:00
Andrey Antukh
b72704e54b Set explicit no-buffering for sse responses 2025-10-06 09:19:48 +02:00
Natacha
362a31dd22 Add typography composite token to changelog (#7434)
Signed-off-by: Natacha <natachamenjibar@gmail.com>
2025-10-06 09:17:29 +02:00
Yamila Moreno
6c6ec7a620 Merge pull request #7433 from penpot/yms-improve-self-host-documentation
📚 Improve self-host documentation
2025-10-03 13:24:37 +02:00
Yamila Moreno
21a7d30c5e 📚 Improve self-host documentation 2025-10-03 13:21:06 +02:00
Andrés Moya
52fef6c318 🐛 Fix sync errors when there is a broken swap slot 2025-10-03 12:51:33 +02:00
Eva Marco
fc8029abf7 🐛 Fix some errors from reviews (#7421)
* 🐛 Fix errors con colorpicker

* 🐛 Fix modal size

* 🐛 Fix form padding

* 🐛 Fix edit modal title

* 🐛 Fix resolved value message

* 🐛 Fix CI
2025-10-03 11:25:56 +02:00
Eva Marco
44f6c2f83c 🎉 Show tokens on color inputs (#7377)
* 🎉 Add tokens to color row

* 🎉 Add color-token to stroke input

* 🐛 FIx change token on multiselection with groups

* 🔧 Add config flag

* 🐛 Fix comments
2025-10-03 11:19:01 +02:00
Eva Marco
a4f20564af 🐛 Fix numeric input errors detected on review (#7427)
* 🐛 Fix review errors

* 📚 Add docs for numeric input component

* 🐛 Sort tokens alphabetically
2025-10-03 10:14:25 +02:00
Eva Marco
93d4b19477 🐛 Fix shadow inputs (#7426) 2025-10-03 10:13:27 +02:00
Aitor Moreno
7dd26dee13 Merge pull request #7428 from penpot/elenatorro-fix-shadows-order
🐛 Fix shadows order
2025-10-02 17:16:58 +02:00
Elena Torró
4594635009 Merge pull request #7399 from penpot/ladybenko-12164-handle-font-404
🐛 Fix internal error when fonts return 404 (wasm)
2025-10-02 16:42:58 +02:00
Elena Torro
7e852cb3ac 🐛 Fix shadows order 2025-10-02 16:40:20 +02:00
Belén Albeza
6e82b0f1ba 🐛 Fix shadow serialization (#7423) 2025-10-02 15:17:01 +02:00
Florian Schroedl
472148ff9d 🐛 Fix empty values re-triggering validation 2025-10-02 14:31:55 +02:00
Florian Schroedl
d01df7738a ♻️ Extract composite component wrapper 2025-10-02 14:31:55 +02:00
Xaviju
73222f22d0 🎉 Add stroke panel to inspect styles tab (#7408) 2025-10-02 13:58:08 +02:00
Andrey Antukh
b90aba0f95 Merge tag '2.10.0' 2025-10-02 12:37:58 +02:00
Florian Schroedl
17fe012f7e 🐛 Fix form not being saveable when editing composite token and switching tabs 2025-10-02 10:48:14 +02:00
Belén Albeza
60f45d1fd7 🐛 Fix internal error crash when attempting to download a font resource that returns 404 2025-10-02 09:58:38 +02:00
alonso.torres
979b4276ca 🐛 Fix problem with component swapping panel 2025-10-02 09:10:21 +02:00
Elena Torró
a32fe40528 Merge pull request #7409 from penpot/ladybenko-fix-wasm-playwright-ci
🔧 Fix Playwright config in CI to include the wasm build
2025-10-02 09:03:12 +02:00
Natacha
b602df549e Add new shadow icons (#7416)
*  Adds new shadow icons

Signed-off-by: Natacha <natachamenjibar@gmail.com>

*  Add shadow icons

Signed-off-by: Natacha <natachamenjibar@gmail.com>

*  Adds shadow icons

Signed-off-by: Natacha <natachamenjibar@gmail.com>

* 📎 Fix wrong svg

Signed-off-by: Natacha <natachamenjibar@gmail.com>

* 📎 Fix wrong svg

Signed-off-by: Natacha <natachamenjibar@gmail.com>

* 📎 Fix wrong svg

Signed-off-by: Natacha <natachamenjibar@gmail.com>

---------

Signed-off-by: Natacha <natachamenjibar@gmail.com>
2025-10-01 17:11:19 +02:00
Luis de Dios
7f1ab08ec8 🐛 Fix use a pointer cursor for adding variant from the viewport (#7410) 2025-10-01 17:01:07 +02:00
Luis de Dios
1263ea11fa 🐛 Fix order of component menu options in assets tab (#7388)
* 🐛 Reorder component menu options in assets tab

* ♻️ Use new component syntax

* 📚 Add bugfix to changelog

* ♻️ Code restructuring and SCSS improvements
2025-10-01 17:00:27 +02:00
Yamila Moreno
ce26c52b30 👷 Automate docker images creation 2025-10-01 14:54:00 +02:00
Yamila Moreno
5c8b3ac3d6 👷 Automate docker images creation 2025-10-01 13:41:03 +02:00
Aitor Moreno
bd4d576172 Merge pull request #7412 from penpot/elenatorro-fix-loop-all-ancestors
🐛 Break loop when no parent is present
2025-10-01 13:36:16 +02:00
Elena Torro
e10169b3db 🐛 Break loop when no parent is present 2025-10-01 12:43:56 +02:00
Elena Torró
f119a9548d Merge pull request #7411 from penpot/azazeln28-fix-issue-12185-wrong-text-width-height-layout
🐛 Fix wrong text auto width/height layout
2025-10-01 12:40:58 +02:00
Aitor Moreno
c097aef152 🐛 Fix wrong text auto width/height layout 2025-10-01 12:27:38 +02:00
Andrey Antukh
000fa51c73 🐛 Fix zip handling on exporter 2025-10-01 11:56:57 +02:00
Belén Albeza
d815494ffa 🔧 Fix playwright config to do a wasm build 2025-10-01 11:27:13 +02:00
Andrey Antukh
a25ba6b482 📎 Fix incorrect regex for match merge and revert commits 2025-10-01 11:07:21 +02:00
Andrey Antukh
e8434c3370 📎 Update devenv tmux script to start exporter using yarn 2025-10-01 10:59:41 +02:00
Andrey Antukh
7cf4ec2792 ♻️ Make the exporter build as esm module 2025-10-01 10:58:03 +02:00
Andrey Antukh
365ce25996 Merge remote-tracking branch 'origin/staging' into develop 2025-10-01 10:50:19 +02:00
Andrey Antukh
01ef55e4f4 Revert " Add minor improvement to cljs impl logging"
This reverts commit 960b76f760.
2025-10-01 10:48:24 +02:00
Andrey Antukh
3b81c1d750 Revert "♻️ Make the exporter build as esm module"
This reverts commit d0f34f06a9.
2025-10-01 10:47:47 +02:00
Elena Torró
40b34da788 Merge pull request #7269 from penpot/azazeln28-feat-caret-position
🎉 Feat caret position
2025-10-01 09:43:03 +02:00
Aitor Moreno
732c79b7b5 🎉 Add function to retrieve caret position 2025-10-01 09:18:46 +02:00
Andrey Antukh
d0f34f06a9 ♻️ Make the exporter build as esm module 2025-10-01 08:10:37 +02:00
Andrey Antukh
23d5bdd20b 🐛 Add missing poppler-tools dependency on devenv 2025-10-01 08:10:37 +02:00
Andrey Antukh
9f2dc06c95 Add missing srepl helper for disable objects-map feat 2025-10-01 08:10:37 +02:00
Andrey Antukh
62563d28d0 📎 Bump library version to 1.0.9
Mainly fixes dependencies declaration on package.json file
2025-09-30 21:55:17 +02:00
Andrey Antukh
21e2ee9904 🐛 Fix dependencies on library 2025-09-30 21:53:04 +02:00
brian mwenda
e6c418eb9c 🐛 Improve auto-width to fixed conversion logic in layout contexts
Signed-off-by: Brian Mwenda <brian@nathandigital.com>
2025-09-30 21:48:03 +02:00
Luis de Dios
de5ff227d2 🎉 Create variant from the viewport (#7357)
* 🎉 Create variant from the viewport

* ♻️ Use DS styles and new component syntax

* 📎 PR changes
2025-09-30 18:15:17 +02:00
Florian Schroedl
0f67730198 🐛 Dont forward default-value for mismatching tab-type 2025-09-30 14:27:40 +02:00
Florian Schroedl
3da02e2b6b 🐛 Fixes resolved values being prefilled for existing referenced composite token 2025-09-30 14:27:40 +02:00
Florian Schroedl
ab80021fb1 🐛 Fix performance issue on font-family 2025-09-30 14:27:40 +02:00
Xaviju
f31e9b8ac9 🎉 Add blur panel to inspect styles tab (#7397) 2025-09-30 13:08:52 +02:00
Andrey Antukh
7d16515eb7 Add minor enhacements to logging on frontend (#7401)
*  Add logging consistency enhacements on fonts loading

*  Disable data evens ns logging

*  Simplify flags logging on application initialization

*  Improve features logging
2025-09-30 11:59:41 +02:00
Pablo Alba
cd9ba482e3 🐛 Load dependant libraries, and don't allow unload them 2025-09-30 09:55:21 +02:00
David Barragán Merino
dff1ca23d3 📚 Update changelog 2025-09-29 18:08:28 +02:00
Andrey Antukh
c363d4d937 📎 Bump library version 2025-09-29 13:44:14 +02:00
Andrey Antukh
de25a24a6d 🐛 Fix backend repl start issue with jdk 24 2025-09-29 13:35:48 +02:00
Andrey Antukh
accc9a173f Merge remote-tracking branch 'origin/staging' into develop 2025-09-29 13:24:31 +02:00
Andrey Antukh
2d364dde5c Add several minor enhacements to features subsystem
Mainly fixes the team non-inheritable features handling and
removes unnecesary/duplicate checks.
2025-09-29 13:23:16 +02:00
Andrey Antukh
c892a9f254 Integrate objects-map usage on backend and frontend 2025-09-29 13:23:16 +02:00
Andrey Antukh
aaae35fb51 🎉 Add multiplatform impl of ObjectsMap
The new type get influentiated by the ObjectsMap impl on backend
code but with simplier implementation that no longer restricts keys
to UUID type but preserves the same performance characteristics.

This type encodes and decodes correctly both in fressian (backend)
and transit (backend and frontend).

This is an initial implementation and several memory usage
optimizations are still missing.
2025-09-29 13:23:16 +02:00
Andrey Antukh
960b76f760 Add minor improvement to cljs impl logging
Mainly reduce the emmited code, that will contribute to reduce the
bundle size and also adds timestamp to the default output.
2025-09-29 13:23:16 +02:00
Andrey Antukh
d921e7eaa3 📎 Add not-empty generator to schema generator ns 2025-09-29 13:23:16 +02:00
Andrey Antukh
49f06b25fa 📚 Update changelog 2025-09-29 13:23:01 +02:00
Andrey Antukh
5ffb7ae2ec Add warning on using deprecated storage config 2025-09-29 13:23:01 +02:00
Andrey Antukh
27945ace65 Revert deprecated storage config cleaning 2025-09-29 13:23:01 +02:00
María Valderrama
e39bf0b439 Invitations management improvements (#7230)
*  Invitations management improvements

* 📎 Change invite email subject

* 📎 Update icon usage

* ♻️ Fix css file

---------

Co-authored-by: Eva Marco <evamarcod@gmail.com>
2025-09-29 13:18:57 +02:00
Alonso Torres
deee7f7334 Merge pull request #7366 from penpot/niwinz-develop-page-data-type
 Add several enhancements for reduce workspace file load time
2025-09-29 12:43:34 +02:00
Xaviju
20d61cbce2 Create ghost variant for select DS component (#7392) 2025-09-29 12:24:20 +02:00
Andrés Moya
9ad8d3fd08 🔧 Make small improvements from PR comments 2025-09-29 12:16:42 +02:00
Andrés Moya
4c35571336 🔧 Read and modify token themes by id 2025-09-29 12:16:42 +02:00
Andrés Moya
37679b7ec6 🔧 Organize token changes API 2025-09-29 12:16:42 +02:00
Andrés Moya
194eded930 🔧 Unify path name helper functions 2025-09-29 12:16:42 +02:00
Andrés Moya
4e607d8da2 💄 Clarify and reorder interfaces 2025-09-29 12:16:42 +02:00
Andrés Moya
f5fd978a07 🔧 Retrieve tokens from library and not from set 2025-09-29 12:16:42 +02:00
Andrés Moya
b28be62845 🔧 Fix rebase problems 2025-09-29 12:16:42 +02:00
Andrés Moya
d76a5c615c 🔧 Modify token sets by id instead of name and review usage 2025-09-29 12:16:42 +02:00
Andrés Moya
03e05da41e 💄 Normalize some attributes of changes 2025-09-29 12:16:42 +02:00
Andrés Moya
5f886e141a 💄 Minor changes 2025-09-29 12:16:42 +02:00
Andrés Moya
021b8f81ca 🔧 Read token sets by id instead of name 2025-09-29 12:16:42 +02:00
Andrey Antukh
f32112544e Make deleted fonts fixer to run with more granular stragegy
Instead of running it on all the file, only run it to local library
and the current page, reducing considerably the overhead of analyzing
the whole file on each file load.

It stills executes for page each time the page is loaded, and add
some kind of local cache for not doing repeated work each time page
loads is pending to be implemented in other commit.
2025-09-29 12:07:49 +02:00
Andrey Antukh
27e311277a Add logging to frontend repo namespace 2025-09-29 12:07:49 +02:00
Andrey Antukh
b9030fcc73 Add better workspace file indexing strategy
Improve file indexes initialization on workspace.

Instead of initialize indexes for all pages only initialize
indexes for the loaded page.
2025-09-29 12:07:49 +02:00
Andrey Antukh
e1519f0ee4 Integrate objects-map usage on backend and frontend 2025-09-29 12:07:48 +02:00
Andrey Antukh
7fefe6dbc8 🎉 Add multiplatform impl of ObjectsMap
The new type get influentiated by the ObjectsMap impl on backend
code but with simplier implementation that no longer restricts keys
to UUID type but preserves the same performance characteristics.

This type encodes and decodes correctly both in fressian (backend)
and transit (backend and frontend).

This is an initial implementation and several memory usage
optimizations are still missing.
2025-09-29 12:06:56 +02:00
Andrey Antukh
fdf70ae9c1 Fix docstring on common.weak ns function 2025-09-29 12:06:56 +02:00
Andrey Antukh
528315b75c 📎 Add not-empty generator to schema generator ns 2025-09-29 12:06:56 +02:00
Andrey Antukh
42d03a0325 📎 Add several missing imports on repl related namespaces 2025-09-29 12:06:56 +02:00
Andrey Antukh
0346c48b03 Add several minor enhacements to features subsystem
Mainly fixes the team non-inheritable features handling and
removes unnecesary/duplicate checks.
2025-09-29 12:06:56 +02:00
Andrey Antukh
1d54fe2e24 Add support for emit messages without waiting response on worker 2025-09-29 12:06:56 +02:00
Andrey Antukh
255f5af2e3 Add several enhacements to buffer namespace
The changes are just for completenes.
2025-09-29 12:06:56 +02:00
Andrey Antukh
eea65b12dd Add minor improvement to cljs impl logging
Mainly reduce the emmited code, that will contribute to reduce the
bundle size and also adds timestamp to the default output.
2025-09-29 12:06:56 +02:00
Andrey Antukh
d4b7f231c7 🔧 Add missing config for on commit checker 2025-09-29 12:05:09 +02:00
Andrey Antukh
473066cf5c 🔧 Add missing config for on commit checker 2025-09-29 12:04:37 +02:00
andrés gonzález
d1607fbe54 💄 Update Help Center images (#7266) 2025-09-29 11:54:47 +02:00
Xaviju
5e84bda404 🎉 Add SVG panel to inspect styles tab (#7373) 2025-09-29 09:53:15 +02:00
Andrey Antukh
c1058c7fdb ♻️ Add minor refactor for internal concurrency model
Replace general usage of virtual threads with platform threads
and use virtual threads for lightweight procs such that websocket
connections. This decision is made mainly because virtual threads
does not appear on thread dumps in an easy way so debugging issues
becomes very difficult.

The threads requirement of penpot for serving http requests
is not very big so having so this decision does not really affects
the resource usage.
2025-09-26 14:35:06 +02:00
Andrey Antukh
9d907071aa ⬆️ Update dependencies (#7330)
* ⬆️ Update to JDK25 on the devenv

* ⬆️ Update dependencies

* 🔥 Remove unused flag from devenv backend startup scripts

*  Enable shenandoah gc on backend scripts/repl
2025-09-26 13:43:43 +02:00
Elena Torró
c32b94abcf Merge pull request #7343 from penpot/elenatorro-12118-support-large-svg-files
🐛 Fix parsing large paths with multiple subpaths
2025-09-26 13:35:17 +02:00
Elena Torro
9d8ad0ea6e 🐛 Fix parsing large paths with multiple subpaths 2025-09-26 13:04:47 +02:00
Yamila Moreno
2b1e107a44 Merge pull request #7390 from penpot/yms-add-curl-dependency
🐳 Add curl to the backend image
2025-09-26 11:40:42 +02:00
Yamila Moreno
2196318cfc 🐳 Add curl to the backend image 2025-09-26 11:23:02 +02:00
Yamila Moreno
b3d1701698 Merge pull request #7355 from penpot/yms-docker-update-nginx-entrypoint
🐳 Improve Docker nginx
2025-09-26 10:49:24 +02:00
Yamila Moreno
042bd03beb 🐳 Improve Docker nginx 2025-09-26 10:31:23 +02:00
andrés gonzález
cce1dd86a2 💄 Change variants video source to peertube (#7387) 2025-09-26 10:21:41 +02:00
Juan de la Cruz
a39a127f03 🐛 Fix underline text in template card at carrusel 2025-09-26 09:56:05 +02:00
Pablo Alba
bd665f70bf 💄 Add new library modal UI tweaks 2025-09-25 22:56:27 +02:00
Eva Marco
e184a9a8b9 🐛 Fix context menu on spacing tokens (#7382) 2025-09-25 17:28:46 +02:00
Elena Torró
9b90236b72 Merge pull request #7385 from penpot/elenatorro-improve-image-load-performance
🔧 Improve image parsing performance
2025-09-25 17:20:49 +02:00
Elena Torro
bf6cdf729d 🔧 Improve image parsing performance 2025-09-25 17:17:42 +02:00
Belén Albeza
361bdb4a04 ♻️ Decouple serialization from text/layout models" (#7360)
* ♻️ Move text serialization code to wasm module

* ♻️ Add serializer for TextAlign

* ♻️ Add serializers for TextDirection and TextDecoration

* ♻️ Add serializer for TextTransform

* ♻️ Remove unused font_style from TextLeaf model

* ♻️ Refactor parsing of TextLeaf from bytes

* ♻️ Decouple tight serialization of Paragraph
2025-09-25 16:54:07 +02:00
andrés gonzález
58c6c94cb8 📚 Update boards info at the user guide (#7383) 2025-09-25 16:36:35 +02:00
Elena Torró
3827aa6bd4 Merge pull request #7344 from penpot/elenatorro-11542-truncate-long-font-names-on-fonts-menu
🔧 Use two lines text ellipsis on custom font names
2025-09-25 15:25:50 +02:00
Xaviju
adf7b0df50 🎉 Add visibility panel to inspect styles tab (#7362) 2025-09-25 12:52:43 +02:00
Elena Torro
97b4491a27 🔧 Use two lines text ellipsis on custom font names 2025-09-25 12:49:33 +02:00
andrés gonzález
ecee7ecfc7 📚 Update workspace info at the user guide (#7376) 2025-09-25 12:24:59 +02:00
Xavier Julian
015bd9e453 🎉 Inspect styles tab: fill panel 2025-09-25 11:31:15 +02:00
Belén Albeza
49d5987b15 💄 Add deprecated namespace and fix import for remaining scss files (#7379) 2025-09-25 11:27:10 +02:00
Belén Albeza
a5e4de97e3 💄 Use deprecated prefix for deprecated scss vars and mixins (#7375) 2025-09-25 09:22:25 +02:00
Alonso Torres
378be9473d 🐛 Fix problem with export size (#7374) 2025-09-25 08:50:31 +02:00
Juan de la Cruz
412cf61d7d 🐛 Remove translations form inspect tab text properties (#7369) 2025-09-25 08:48:41 +02:00
Juan de la Cruz
754a1b6fa2 🐛 Fix loading tips wording (#7368) 2025-09-25 08:48:10 +02:00
Eva Marco
a4ada6dc8a 🐛 Add default flags for tokens (#7367) 2025-09-25 08:47:04 +02:00
Elenzakaleidos
ec94d08f4a 🎉 Update README.md with Variants (#7353)
Update the Readme with new text and image that include Variants as feature

Signed-off-by: Elenzakaleidos <elena.scilinguo@kaleidos.net>
2025-09-25 08:46:02 +02:00
Alonso Torres
b6b2d28464 🐛 Fix problem with flow not being deleted (#7371) 2025-09-24 18:06:26 +02:00
Elena Torro
32770c685a 🐛 Do not add shadows on hidden children 2025-09-24 14:42:57 +02:00
andrés gonzález
b770145436 💄 Update variants video at the user guide (#7363) 2025-09-24 13:41:20 +02:00
Eva Marco
441dc33e38 ♻️ Add shortcut to scss import paths (#7364)
* 🎉 Add config for shortcut imports

* ♻️ Change import paths
2025-09-24 11:18:34 +02:00
Eva Marco
3f87e768a7 ♻️ Fix color token reviews (#7322)
* ♻️ Fix some review changes

* 🐛 Fix more errors

* 🎉 Create token from colorpicker fixed

---------

Co-authored-by: Andrey Antukh <niwi@niwi.nz>
2025-09-24 11:13:52 +02:00
David Barragán Merino
09e9340ba6 💄 Fix a description and remove an unused event 2025-09-24 09:38:42 +02:00
David Barragán Merino
d5ff7b4144 📎 Add DevEnv builder workflow 2025-09-23 23:26:11 +02:00
David Barragán Merino
ef0aee0a09 📎 Automatically publish github release and docker images with final version tags 2025-09-23 23:25:52 +02:00
Andrey Antukh
1e9682376e Merge remote-tracking branch 'origin/staging' into develop 2025-09-23 12:20:49 +02:00
Andrey Antukh
11b75408fe 🐛 Fix regression on importing binfile-v1 files (#7359) 2025-09-23 11:38:33 +02:00
Andrey Antukh
59f7ede4ff 🐛 Add migration for properly decode all position data on text shapes 2025-09-23 11:34:24 +02:00
Pablo Alba
c9b61745a0 🎉 Switch several variant copies at the same time 2025-09-23 11:31:57 +02:00
Andrés Moya
8954b05d76 🐛 Fix error exporting a file with deleted tokens (#7356) 2025-09-22 17:41:31 +02:00
Aitor Moreno
974b76d7bd Merge pull request #7267 from penpot/azazeln28-feat-text-layout
🎉 Add internal TextContent layout data
2025-09-22 16:21:06 +02:00
Aitor Moreno
f505fcfa0d 🎉 Add internal TextContent layout data 2025-09-22 16:01:23 +02:00
Belén Albeza
e4d610d503 ♻️ Decouple shapes serialization from model (rust) (#7328)
* ♻️ Move shape type serialization to wasm module

* ♻️ Refactor serialization of constraints and vertical alignment into wasm module

* ♻️ Refactor serialization and model of shape blur

* ♻️ Refactor bool serialization to the wasm module

* ♻️ Split wasm::layout into submodules

* ♻️ Refactor serialization of AlignItems, AlignContent, JustifyItems and JustifyContent

* ♻️ Refactor serialization of WrapType and FlexDirection

* ♻️ Refactor serialization of JustifySelf

* ♻️ Refactor serialization of GridCell

* ♻️ Refactor serialization of AlignSelf

* 🐛 Fix AlignSelf not being serialized

* ♻️ Refactor handling of None variants in Raw* enums

* ♻️ Refactor serialization of grid direction

* ♻️ Refactor serialization of GridTrack and GridTrackType

* ♻️ Refactor serialization of Sizing

* ♻️ Refactor serialization of ShadowStyle

* ♻️ Refactor serialization of StrokeCap and StrokeStyle

* ♻️ Refactor serialization of BlendMode

* ♻️ Refactor serialization of FontStyle

* ♻️ Refactor serialization of GrowType
2025-09-22 13:47:54 +02:00
Andrey Antukh
cb4c155b32 📎 Uncomment previously commented migrations 2025-09-22 11:38:52 +02:00
Andrey Antukh
0b346e02ff 🐛 Fix incorrect options pass on decode-file 2025-09-22 11:30:42 +02:00
Madalena Melo
5c23a678cc Merge pull request #7342 from penpot/madalenapmelo-kp-patch-1
📚 Add reference to the Teams section on the Dashboard section
2025-09-22 11:23:29 +02:00
Andrey Antukh
946f641917 📎 Disable possible problematic migrations 2025-09-22 11:12:43 +02:00
David Barragán Merino
fb3923924b 📎 Change the name of some action workflows 2025-09-22 09:58:26 +02:00
Florian Schroedl
c882e8347a Add line-height to composite typography token 2025-09-22 09:52:56 +02:00
Pablo Alba
c1fd1a3b42 📚 Add variants doc for SDK (#7351)
* 📚 Add variants doc for SDK

* 📚 Spelling & style improvements

---------

Co-authored-by: Luis de Dios <luis.dedios@kaleidos.net>
2025-09-21 22:15:27 +02:00
Eva Marco
b1fe32baea ♻️ Remove deprecated @import from scss files (#7347)
* 🐛 Fix import warnings 1 of 2

* 🐛 Fix import warnings 2 of 2

* 🐛 Fix visual tests and format files

* 🐛 Fix mixed declarations on scss
2025-09-19 11:50:08 +02:00
Andrey Antukh
fb7a7d02da Merge pull request #7205 from penpot/niwinz-measures-tokens-backup
♻️ Replace numeric inputs on measure options
2025-09-19 11:44:17 +02:00
Eva Marco
20dfc2a216 🐛 Fix typo on event name (#7350) 2025-09-19 11:40:53 +02:00
Eva Marco
d7d2d36e0a ♻️ Replace measure inputs for numeric input component 2025-09-19 11:28:22 +02:00
Andrey Antukh
07904bcc5d ♻️ Add needed changes to get tokens from sidebar
This reverts commit afe149f702148d86d1dea6cb6a537917ce7202aa.
2025-09-19 10:26:29 +02:00
Andrey Antukh
9686075104 🐛 Fix translations 2025-09-18 12:02:45 +02:00
María Valderrama
436e0e847d 🐛 Fix current version on sidebar 2025-09-18 11:56:47 +02:00
Eva Marco
d50b070a64 🎉 Add usefull mixins to DS (#7340) 2025-09-18 10:47:55 +02:00
Andrey Antukh
80cb48fd6a Merge remote-tracking branch 'origin/staging' into develop 2025-09-18 10:44:21 +02:00
Andrey Antukh
e88039e46a 🐛 Fix future linter issues on wasm shape impl 2025-09-17 16:53:02 +02:00
Andrey Antukh
3c45a8d0b4 Allow delete subscriptions on profile deletion request 2025-09-17 16:53:02 +02:00
Aitor Moreno
c9d71f3b2d 🐛 Fix conflicting shortcuts (text alignment) (#7339) 2025-09-17 16:52:44 +02:00
Madalena Melo
49c6efbc22 📚 Add reference to the Teams section on the Dashboard section
https://tree.taiga.io/project/penpot/task/11806

Signed-off-by: Madalena Melo <madalena.melo@kaleidos.net>
2025-09-17 16:17:24 +02:00
Andrey Antukh
9f37175775 🐛 Fix incorrect path data content initialization on pluings api 2025-09-17 15:19:41 +02:00
andrés gonzález
5ed870cc6e 📚 Update shortcuts docs (#7341) 2025-09-17 14:13:00 +02:00
Andrey Antukh
4fb1c7a630 Merge remote-tracking branch 'origin/staging' into develop 2025-09-17 13:46:49 +02:00
Pablo Alba
2a3d7e470d 📚 Update changelog with variants info (#7335) 2025-09-17 13:45:59 +02:00
Eva Marco
f654eb2dcd 🐛 Fix font weight input placehoder (#7338) 2025-09-17 13:44:11 +02:00
Belén Albeza
c21d705143 🐛 Remove shortcuts for inc/dec line height and letter spacing (#7337) 2025-09-17 12:35:39 +02:00
Andrey Antukh
85c1750706 🐛 Fix backend last migration naming (#7333) 2025-09-17 10:47:14 +02:00
Luis de Dios
e2151409bf 🐛 Fix wrong number of components in the library modal (#7332) 2025-09-17 09:25:23 +02:00
Luis de Dios
4fe6cfc57a 🐛 Fix focus the first property value when creating a variant (#7329) 2025-09-16 23:25:18 +02:00
David Barragán Merino
fd37fdde93 📎 Add release action workflow 2025-09-16 18:06:06 +02:00
David Barragán Merino
66b1d5b7bd Merge remote-tracking branch 'origin/staging' into develop 2025-09-16 16:26:23 +02:00
Andrés Moya
2eed7444b7 🔧 Add migration to automatically fix validation errors 2025-09-16 16:11:58 +02:00
Xavier Julian
2bf7a9dd5f ♻️ Remove unneeded fn parameters 2025-09-16 14:17:14 +02:00
Xavier Julian
7bacd8fbca ♻️ Refactor defmulti fn into case switches 2025-09-16 14:17:14 +02:00
Luis de Dios
ef376fbb7b Add shortcut for creating variant to the shortcuts panel (#7319)
*  Add shortcut for creating variant to the shortcuts panel

* ♻️ Update components to new rumext syntax

* 🐛 Fix unique "key" prop error for each child in a list

* ♻️ Remove deprecated icons and CSS cleanup

* 📎 PR changes
2025-09-16 14:06:47 +02:00
Aitor Moreno
b883882a32 🐛 Fix onboarding select keyboard interaction (#7295) 2025-09-16 13:59:15 +02:00
Pablo Alba
18d5b84b00 🐛 Fix variants events (#7320)
* 🐛 Add missing event add-component-to-variant

* 🐛 Fix event apply-tokens, param applied-to-variant

* 🐛 Fix missing case on event "add new variant"

* 🐛 Fix event combine-as-variants

* 🐛 Fix event variant-edit-property-name

* 🐛 On variants events, change trigger for origin

* 🐛 Split combine-as-variants to not have an optional first parameter
2025-09-16 13:09:23 +02:00
Belén Albeza
e5e11b6383 🔧 Autogenerate serialization values for wasm enums (#7296)
* 🔧 Autogenerate serialization values for wasm enums

* 🔧 Add serializer values to the wasm api

*  Avoid converting to a clojure map the serializer js object

* 🔧 Update watch script for autoserialized enums

* 🐛 Fix missing serializer values
2025-09-16 12:29:14 +02:00
Eva Marco
01e963ae35 🐛 Fix font name hot update (#7316) 2025-09-16 12:23:41 +02:00
Eva Marco
90a80c4b63 🐛 Fix Uppercase on add token button (#7314) 2025-09-16 12:05:55 +02:00
VKing9
1bd45d3f8a 🌐 Add translations for: Hindi
Currently translated at 95.2% (1825 of 1917 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/hi/
2025-09-16 12:02:02 +02:00
Andrey Antukh
b56f237780 Merge remote-tracking branch 'origin/staging' into develop 2025-09-16 11:38:58 +02:00
Xavier Julian
4970ae3eb4 💄 Align tokens panel vertically to the top 2025-09-16 11:38:33 +02:00
Aitor Moreno
c62fadac47 🐛 Fix fast move with distance (#7302)
* 🐛 Fix fast move with distance

* 📎 Remove duplicated shourtcuts

---------

Co-authored-by: Andrey Antukh <niwi@niwi.nz>
2025-09-16 11:36:21 +02:00
Andrés Moya
a264f84e6c 🔧 Deactivate validation temporarily 2025-09-16 11:34:38 +02:00
Elena Torró
2e21f084fc 🐛 Fix boolean operations on rotated shapes (#7309) 2025-09-15 14:46:56 +02:00
Xavier Julian
55513b9ae5 🎉 Inspect styles tab: layout element panel 2025-09-15 13:39:00 +02:00
Luis de Dios
9311ee4c87 🐛 Fix show in assets panel option for component of variants (#7311) 2025-09-15 13:13:12 +02:00
Eva Marco
07d0062645 🐛 Fix sets shown without color tokens (#7312) 2025-09-15 10:38:06 +02:00
Xavier Julian
f4b38af649 Display border-radius as logical properties in inspect tab 2025-09-15 09:46:01 +02:00
Andrey Antukh
6e7bcd1243 Merge remote-tracking branch 'origin/staging' into develop 2025-09-12 16:55:25 +02:00
Andrey Antukh
b8c8579ff5 Merge pull request #7310 from penpot/niwinz-staging-update-jdk
⬆️ Update node and jdk (patch)
2025-09-12 16:54:49 +02:00
Andrey Antukh
82295c79d4 ⬆️ Update jdk to 24.0.2+12 2025-09-12 16:47:25 +02:00
Andrey Antukh
5174591058 ⬆️ Update nodejs to v22.19.0 2025-09-12 16:44:26 +02:00
Andrés Moya
ed3fc5b8b2 🐛 Fix detaching a nested copy inside a main component (#7304)
* 🐛 Fix detaching a nested copy inside a main component

* 💄 Rename functions for more semantic precission
2025-09-12 16:00:01 +02:00
Pablo Alba
f5f9157786 🐛 Fix paste behavior according to the selected element 2025-09-12 15:17:26 +02:00
Juan de la Cruz
658303fa36 🎉 Add 2.10 release slides (#7293) 2025-09-12 15:06:18 +02:00
Andrey Antukh
6cb0cb7f98 Merge remote-tracking branch 'origin/staging' into develop 2025-09-12 14:49:52 +02:00
Andrey Antukh
84013c21fa Merge pull request #7308 from penpot/niwinz-staging-update-deps
⬆️ Update dependencies
2025-09-12 14:47:53 +02:00
Andrey Antukh
f3062ade39 ⬆️ Update jakarta.mail dependency 2025-09-12 14:28:14 +02:00
Andrey Antukh
ca19d4deeb ⬆️ Update postgresql jdbc dependency 2025-09-12 14:28:14 +02:00
Andrey Antukh
dfceccca3d ⬆️ Update aws s3 sdk version
This transitivelly updates the netty library version
that comes with fixes for several security issues
2025-09-12 14:28:14 +02:00
Luis de Dios
9e2d3b1fa1 🐛 Fix position of annotation for variants (#7306) 2025-09-12 14:05:36 +02:00
Florian Schroedl
4dc0f3b4eb 🐛 Fix make-token throwing because of error in name, keep preview value 2025-09-12 13:49:25 +02:00
andrés gonzález
215288b6b4 📚 Update Design Tokens doc (#7265) 2025-09-12 11:15:23 +02:00
andrés gonzález
2e2c3e7bac 📚 Add doc for variants (#7258) 2025-09-12 11:15:03 +02:00
Xavier Julian
0210b310b7 🎉 Inspect styles tab: layout panel 2025-09-12 10:27:41 +02:00
Stas Haas
c77efc657c 🌐 Add translations for: German
Currently translated at 91.7% (1758 of 1917 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/de/
2025-09-12 10:03:18 +02:00
Eva Marco
ce1e44eda4 ♻️ Refactor set titles (#7301) 2025-09-12 08:46:05 +02:00
Marina López
48825e1e59 Show current penpot version 2025-09-11 13:18:42 +02:00
Florian Schroedl
61cfe2d142 🐛 Fix font-family being split up when restoring from backup value 2025-09-11 12:33:26 +02:00
Eva Marco
2d68f4dfd3 🐛 Fix icons (#7299) 2025-09-11 09:42:11 +02:00
Elena Torró
1e23937aa5 Merge pull request #7291 from penpot/superalex-fix-boolean-and-group-shadows
🐛 Fix boolean and group shadows
2025-09-11 09:27:56 +02:00
Eva Marco
aecaf51953 Add color token on colorpicker (#7197)
*  Add token aplication to colorpicker

* 🐛 Change fn name

* 🐛 Change scss from file

* 🐛 Change color for direct-color

* 🐛 Remove vector from fns

* 🐛 Fix CI

* 🐛 Change color-option name

* 🐛 Fix comments

* 🐛 Remove sets without color tokens
2025-09-11 09:13:43 +02:00
Alejandro Alonso
da05d6b67d 🐛 Fix boolean and group shadows 2025-09-10 15:59:39 +02:00
Alejandro Alonso
99a100ad63 Merge pull request #7264 from penpot/elenatorro-12002-draw-shadows-and-blurs-on-texts-on-surfaces
🐛 Fix text shadows and blur and refactor text rendering
2025-09-10 15:50:33 +02:00
Elena Torró
bd3bcb4b18 Merge pull request #7284 from penpot/superalex-fix-blend-mode
🐛 Fix updating blend mode for shapes
2025-09-10 15:03:17 +02:00
Elena Torró
534c7864fc Merge pull request #7285 from penpot/superalex-fix-cornder-radius
🐛 Fix corner radius
2025-09-10 14:59:06 +02:00
Elena Torro
4bd2eba573 🐛 Fix text shadows and blur and refactor text rendering 2025-09-10 14:20:24 +02:00
Xavier Julian
563f608255 🐛 Display token themes as a string 2025-09-10 13:55:54 +02:00
Alejandro Alonso
382b5e7e3a Merge remote-tracking branch 'origin/staging' into develop 2025-09-10 12:33:54 +02:00
Eva Marco
a503f8ae93 ♻️ Refactor composite token UI (#7287)
* ♻️ Refactor composite token UI

* 🐛 Fix comments
2025-09-10 12:16:39 +02:00
Xavier Julian
e1935fb3fb 🎉 Inspect styles tab: geometry panel 2025-09-10 11:01:19 +02:00
Alejandro Alonso
7ac44009d5 Merge pull request #7288 from penpot/luis-12042-context-menu-variant
🐛 Fix create a variant using the contextual menu
2025-09-09 16:27:35 +02:00
Luis de Dios
f22eef5bf6 🐛 Fix create a variant using the contextual menu 2025-09-09 15:59:04 +02:00
Florian Schroedl
b3763dec3f Typography import-export 2025-09-09 13:30:38 +02:00
Alejandro Alonso
7c61049103 Merge pull request #7257 from penpot/azazeln28-fix-issue-11992-cannot-move-elements-up-or-down
🐛 Fix moving elements up or down while pressing alt
2025-09-09 11:07:58 +02:00
Alejandro Alonso
fe819c6ec4 Merge pull request #7286 from penpot/azazeln28-fix-text-editor-v1-paste
🐛 Fix text editor v1 paste HTML
2025-09-09 11:05:17 +02:00
Aitor Moreno
1a4594a615 🐛 Fix text editor v1 paste HTML 2025-09-09 10:48:15 +02:00
Alejandro Alonso
41751d60d2 🐛 Fix corner radius 2025-09-09 10:24:56 +02:00
Yamila Moreno
8bd0edca46 Merge pull request #7282 from penpot/yms-update-ci
📎 Update CI
2025-09-09 09:30:18 +02:00
David Barragán Merino
d2bff2853f Merge pull request #7283 from penpot/bameda-upgrade-docker-images-dependencies
🐳 Update the version of node and nginx-unprivileged
2025-09-09 09:29:36 +02:00
Alejandro Alonso
e2f22b86c7 🐛 Fix updating blend mode for shapes 2025-09-09 09:19:09 +02:00
Aitor Moreno
ff96f7be85 🐛 Fix moving elements up or down while pressing alt 2025-09-09 09:19:00 +02:00
Alejandro Alonso
108b5ab225 🐛 Fix missing filter-icon 2025-09-09 09:05:42 +02:00
Alejandro Alonso
a403af7ebd 🐛 Fix plugin installation link 2025-09-09 08:47:09 +02:00
Alejandro Alonso
43a238a896 Merge remote-tracking branch 'origin/staging' into develop 2025-09-09 08:40:35 +02:00
Alejandro Alonso
e3c9588c1c Merge pull request #7279 from penpot/palba-variants-events2
🎉 Add "advanced" events to variants
2025-09-09 07:03:22 +02:00
Alejandro Alonso
25b63e5675 Merge pull request #7280 from penpot/palba-fix-variants-duplicate
🐛 Fix bad selection after variant duplicate
2025-09-09 06:49:34 +02:00
David Barragán Merino
6c59d633cd 🐳 Update the version of node and nginx-unprivileged 2025-09-08 18:36:31 +02:00
Yamila Moreno
daa408e291 📎 Update CI 2025-09-08 16:51:05 +02:00
Andrés Moya
bb0a891638 📚 Update changelog 2025-09-08 16:49:27 +02:00
Florian Schrödl
8aed47dad3 Allow references to other typography tokens (#7251) 2025-09-08 16:45:18 +02:00
Pablo Alba
c5bd183f73 🐛 Fix bad selection after variant duplicate 2025-09-08 16:33:38 +02:00
Pablo Alba
06441063f2 Add "advanced" events to variants 2025-09-08 15:33:14 +02:00
Elena Torró
0e23c9f6ab Merge pull request #7278 from penpot/superalex-fix-fill-stroke-opacity-shouldnt-affect-shadows
🐛 Fix fills and strokes opacity shouldn't affect shadows
2025-09-08 14:08:20 +02:00
Alejandro Alonso
8fff9afee6 🐛 Fix fills and strokes opacity shouldn't affect shadows 2025-09-08 13:04:52 +02:00
Alejandro Alonso
9f11a2cb32 🐛 Fix context menu shape ids (#7277)
This reverts commit 1929ee36ed.
2025-09-08 11:59:54 +02:00
Xavier Julian
ff55318c04 🎉 Inspect styles tab: variants panel 2025-09-08 11:59:33 +02:00
Elena Torró
41b7957eff Merge pull request #7274 from penpot/superalex-refactor-drop-shadows
🐛 Fixing nested shadows
2025-09-08 11:38:19 +02:00
Alejandro Alonso
053b2c6248 Merge pull request #7253 from penpot/marina-payments-incorrect-date-plan
🐛 Fix incorrect date displayed for support plan
2025-09-08 11:22:48 +02:00
Alejandro Alonso
7e52aadb98 🐛 Fixing nested shadows 2025-09-08 11:20:03 +02:00
Marina López
fad058ee59 🐛 Fix incorrect date displayed for support plan 2025-09-08 11:06:57 +02:00
Alejandro Alonso
69f41c300f Merge pull request #7199 from penpot/elenatorro-11844-fix-font-long-names
🐛 Fix custom font-long names overflow
2025-09-08 10:48:54 +02:00
Elena Torro
18c5e0b9a8 🐛 Fix font long name overflow 2025-09-08 10:31:35 +02:00
Alejandro Alonso
568c2fd9d7 Merge pull request #7271 from penpot/eva-bugfixing-release
🐛 Fix several bugs
2025-09-08 10:23:05 +02:00
Luis de Dios
794eb78aca ♻️ Refactor icon namespaces (#7262)
* ♻️ Rename old icons as deprecated

* ♻️ Take icons from the namespace for the icon component

* ♻️ Take icons from the namespace for the icon-button component
2025-09-08 10:02:33 +02:00
Florian Schrödl
e761bcac85 🐛 Fix text-transform not unapplyng text-case token (#7272) 2025-09-08 09:34:58 +02:00
Eva Marco
1929ee36ed 🐛 Fix ungroup option missing 2025-09-08 09:18:43 +02:00
Nicola Bortoletto
26f123f466 🌐 Add translations for: Italian
Currently translated at 99.7% (1912 of 1917 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/it/
2025-09-06 09:02:02 +02:00
DoubleCat
d9f186524d 🌐 Add translations for: Chinese (Simplified Han script)
Currently translated at 95.6% (1834 of 1917 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/zh_Hans/
2025-09-06 09:02:00 +02:00
Eva Marco
84cccd1b79 🐛 Fix alignment row on single shape selection 2025-09-05 13:54:46 +02:00
Eva Marco
e66d44ca81 🐛 Fix wrong icon on path layer 2025-09-05 13:54:19 +02:00
Eva Marco
2f3b464715 🎉 Add base font size flag (#7270) 2025-09-05 13:36:32 +02:00
Pablo Alba
286e477ad5 🐛 Change variants nesting error texts 2025-09-05 12:34:16 +02:00
Andrés Moya
6e6749f42e 🔧 Add unit tests to apply layout tokens 2025-09-05 11:11:48 +02:00
Andrés Moya
7b6aa0c12a 🐛 Unapply layout item tokens when moving out of a layout 2025-09-05 11:11:48 +02:00
Nicola Bortoletto
5f33ce9ef6 🌐 Add translations for: Italian
Currently translated at 98.2% (1883 of 1917 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/it/
2025-09-04 19:01:57 +02:00
Pablo Alba
409f95ac17 Add basic variants events (#7249)
*  Add basic variants events

*  MR changes
2025-09-04 17:00:09 +02:00
Florian Schroedl
25950be077 🐛 Fix when font-weight is a computed int (math resolver) 2025-09-04 13:06:57 +02:00
Florian Schroedl
5230d54551 🐛 Fix when font-weight is a computed int (math resolver) 2025-09-04 12:23:43 +02:00
Alejandro Alonso
a79be05261 🐛 Fix selection and devtools problem (#7259) 2025-09-04 09:29:38 +02:00
Alejandro Alonso
9eda1d0d78 Merge pull request #7256 from penpot/ladybenko-8371-fix-iconsistent-naming
🐛 Fix inconsistent naming for Flatten
2025-09-04 07:34:10 +02:00
Belén Albeza
f6c4f800c4 📚 Update changelog 2025-09-04 07:13:30 +02:00
Belén Albeza
f363d6a801 Add integration test for Flatten menu option 2025-09-04 07:13:16 +02:00
Belén Albeza
e88ce0d52f 🐛 Unify flatten naming 2025-09-04 07:13:16 +02:00
Alejandro Alonso
fe5fe7a933 Merge pull request #7252 from penpot/mavalroot-typos
🐛 Fix typos
2025-09-04 07:05:37 +02:00
Belén Albeza
9c77296858 🔧 Make the watch script to compile the debug css when not in production env (#7250) 2025-09-03 13:45:11 +02:00
Xavier Julian
34da6b64df 🎉 Inspect styles tab tokens panel 2025-09-03 13:01:38 +02:00
María Valderrama
699cc147b5 🐛 Fix typos 2025-09-03 11:20:12 +02:00
Corentin Noël
4becd35e52 🌐 Add translations for: French
Currently translated at 97.6% (1871 of 1917 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/fr/
2025-09-03 09:02:01 +00:00
Luis de Dios
b1d792a757 🐛 Fix icons do not appear in swap panel and annotations (#7240)
* 🐛 Fix icons do not appear in swap panel and annotations

* 📎 PR changes
2025-09-03 10:57:47 +02:00
Florian Schroedl
18e6842e35 ♻️ Revert trigger interactive via actionize and propagation 2025-09-03 10:10:34 +02:00
Florian Schroedl
c4481be39f ♻️ Revert trigger interactive via actionize and propagation 2025-09-03 09:42:40 +02:00
Andrés Moya
0df420d353 🐛 Fix setting shape size to zero 2025-09-03 08:57:26 +02:00
Elena Torró
f60b6a4869 Merge pull request #7247 from penpot/ladybenko-11983-textlayout-module
♻️ Refactor into new textlayout module
2025-09-02 17:17:12 +02:00
Belén Albeza
3e02dc550f ♻️ Create type alias for ParagraphBuilderGroup 2025-09-02 15:32:10 +02:00
Belén Albeza
1cf0de395c ♻️ Rename get_children to children (Paragraph) 2025-09-02 15:30:54 +02:00
Belén Albeza
d40b68c004 ♻️ Refactor and rename ParagraphBuilder instantiating from TextContent 2025-09-02 15:22:05 +02:00
Belén Albeza
50b9e8c6e6 ♻️ Rename TextContent::get_width to TextContent::width 2025-09-02 15:07:13 +02:00
Belén Albeza
d25f9cd4bd ♻️ Move auto_width and auto_height to their own textlayout module 2025-09-02 15:03:46 +02:00
Pablo Alba
dac2d31b35 🐛 Don't allow a variant switch when that will provoke a components loop 2025-09-02 15:03:38 +02:00
Florian Schroedl
bedb98ad9f Add context menu for typography 2025-09-02 13:19:45 +02:00
Elena Torró
5f37601122 🐛 Fix different fonts on texts shadows (#7214)
* 🐛 Fix different fonts on texts shadows

* 🔧 Refactor text rendering and move text-decoration logic outside

* 🔧 Use transparency correctly
2025-09-02 12:56:07 +02:00
Pablo Alba
1d3a1a094a 🐛 Missing component copy options on the context menu 2025-09-02 12:49:53 +02:00
Andrés Moya
9652996f07 🐛 Add validation for text shapes with wrong register of overrides 2025-09-02 12:49:41 +02:00
Pablo Alba
796aaed11e 🐛 Fix prop creation on variants move layer 2025-09-02 10:01:30 +02:00
Alejandro Alonso
1da69cfa38 📎 Add next release entries to the changelog 2025-09-01 11:10:09 +02:00
Luis de Dios
2a2735cd67 💄 Adjust design details of some components (#7225) 2025-09-01 11:02:36 +02:00
Nicola Bortoletto
b0712b6dc5 🌐 Add translations for: Italian
Currently translated at 96.1% (1844 of 1917 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/it/
2025-09-01 11:02:03 +02:00
Yaron Shahrabani
cc31ee50df 🌐 Add translations for: Hebrew
Currently translated at 99.5% (1908 of 1917 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/he/
2025-09-01 11:02:01 +02:00
Elena Torró
0552b6e713 Merge pull request #7189 from penpot/azazeln28-feat-text-playground-fonts
🎉 Add multiple fonts to text editor WASM playground
2025-09-01 10:54:40 +02:00
Alejandro Alonso
30e655b1da Merge pull request #7236 from penpot/eva-fix-padding-sidebar
🐛 Fix wrong spacing
2025-09-01 10:35:21 +02:00
Alejandro Alonso
0aeecc6268 Merge pull request #7234 from penpot/palba-variants-activate-for-everyone
🎉 Activate variants for everyone
2025-09-01 10:27:44 +02:00
Eva Marco
5cec006a76 🐛 Fix wrong spacing 2025-09-01 10:15:52 +02:00
Pablo Alba
307e06372b 🎉 Activate variants for everyone 2025-09-01 09:58:14 +02:00
Xaviju
9f24e76c27 🌐 Convert translation single word to label (#7220) 2025-09-01 08:44:06 +02:00
Xavier Julian
7954eaf529 🎉 Inspect styles tab attributes container box 2025-08-31 14:58:11 +02:00
Stephan Paternotte
63456d2b75 🌐 Add translations for: Dutch
Currently translated at 99.8% (1915 of 1917 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/nl/
2025-08-31 06:05:48 +00:00
Stephan Paternotte
6a4a22c77a 🌐 Add translations for: Dutch
Currently translated at 99.8% (1915 of 1917 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/nl/
2025-08-29 17:01:57 +02:00
Edgars Andersons
32ad35aa19 🌐 Add translations for: Latvian
Currently translated at 97.3% (1867 of 1917 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/lv/
2025-08-29 17:01:56 +02:00
Yaron Shahrabani
e1522f1e8a 🌐 Add translations for: Hebrew
Currently translated at 99.1% (1900 of 1917 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/he/
2025-08-29 17:01:54 +02:00
Corentin Noël
05093a32f3 🌐 Add translations for: French
Currently translated at 97.4% (1868 of 1917 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/fr/
2025-08-29 17:01:53 +02:00
Eva Marco
fe406b577e 📚 Add comment to not translated string 2025-08-29 14:26:52 +02:00
Eva Marco
76c03af024 ♻️ Fix how files are used on scss files (#7208) 2025-08-29 13:55:50 +02:00
Andrey Antukh
fe5cdcbdc7 🐛 Do not render assets sidebar context menu if it is not open (#7222)
This commit is a workaround to an issue that happens when you performing
multiple selection of several shapes (including components) and an
exception is raised of max depth of updates. The issue is still not
solved, we justo do not render the context menu when user performs
the selection on the workspace.

That issue/exception happens only we have context-menu* component
rendered independently of its visibility and dev-tools open
2025-08-29 13:53:55 +02:00
Florian Schroedl
2479a06f9a 🐛 Fix token create not disabled when creating token without value 2025-08-29 13:41:38 +02:00
Florian Schroedl
fc5e4a821b ♻️ Use interactive update functions only on user actions 2025-08-29 13:38:41 +02:00
Florian Schroedl
3cdbc27de9 Unapply font-weight token when changing font-family 2025-08-29 13:38:41 +02:00
Florian Schroedl
a8ed1371d4 Find closest variant when updating font family 2025-08-29 13:38:41 +02:00
Andrey Antukh
e7bac41c37 Merge pull request #7202 from penpot/niwinz-develop-sidebar-refactor-2
♻️ Refactor right sidebar state management
2025-08-29 12:10:51 +02:00
Andrey Antukh
dede2a8f8e 💄 Fix JS files formatting issues 2025-08-29 11:25:58 +02:00
Andrey Antukh
e94abad3eb Add efficiency refactor for layer-menu* 2025-08-29 11:25:58 +02:00
Andrey Antukh
f8bc6e12a9 Improve efficiency of border radius menu 2025-08-29 11:25:58 +02:00
Andrey Antukh
a2c3208af9 🐛 Fix regression on not updating measures ui on moving frames 2025-08-29 11:25:58 +02:00
Andrey Antukh
a303df9c34 ♻️ Refactor right sidebar state management
Also removing duplicated refs and improve efficiency of
several other refs used on sidebar.
2025-08-29 11:25:58 +02:00
Kelp
bda24f3829 📎 Update Changelog to add font weight token (#7216)
Add font weight to changes.md

Signed-off-by: Kelp <5446186+NatachaMenjibar@users.noreply.github.com>
2025-08-29 11:04:36 +02:00
Elena Torró
94fd3119e8 Merge pull request #7175 from penpot/superalex-fix-clipping
🐛 Fix clipping
2025-08-29 11:03:07 +02:00
María Valderrama
c8091b42a7 🐛 Fix navigation arrows in Libraries & Templates carousel (#7217) 2025-08-29 10:51:00 +02:00
Xaviju
41a859b444 🌐 Recover lost variant translation (#7215) 2025-08-29 09:50:33 +02:00
Aitor Moreno
1cf20f7604 Merge pull request #7203 from penpot/elenatorro-fix-text-decoration-leaf-position
🐛 Fix line height on texts and improve text decoration rendering
2025-08-28 16:21:40 +02:00
Andrey Antukh
629541bc9d 🐛 Fix incorrect recursion on looking boolean parent (#7212) 2025-08-28 16:13:14 +02:00
Alejandro Alonso
44245d1b5f 🐛 Fix position-data validator (#7194) 2025-08-28 15:46:23 +02:00
Luis de Dios
a8692c72c6 Show create variant shortcut also for stand-alone components (#7195) 2025-08-28 15:45:53 +02:00
Elena Torró
7b7da59ca9 Merge pull request #7200 from penpot/ladybenko-11552-fix-font-styles
🐛 Fix new inline text styles not being applied correctly
2025-08-28 15:34:54 +02:00
Elena Torro
b78e3159d1 📚 Add wasm playground internal docs 2025-08-28 15:10:56 +02:00
Luis de Dios
2106028350 🐛 Fix color of variant property names in the design tab (#7204) 2025-08-28 12:51:04 +02:00
Andrey Antukh
c2e7f9dc42 ⬆️ Update base deps (#7207) 2025-08-28 12:50:39 +02:00
Andrey Antukh
8568098c5e 🌐 Validate and rehash translation files 2025-08-28 12:49:35 +02:00
VKing9
c8bc1ef1d2 🌐 Add translations for: Hindi
Currently translated at 94.8% (1816 of 1915 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/hi/
2025-08-28 12:46:50 +02:00
Stephan Paternotte
59bd434d05 🌐 Add translations for: Dutch
Currently translated at 97.5% (1869 of 1915 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/nl/
2025-08-28 12:46:50 +02:00
Edgars Andersons
3cf1e53340 🌐 Add translations for: Latvian
Currently translated at 96.0% (1839 of 1915 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/lv/
2025-08-28 12:46:50 +02:00
Denys Kisil
24f0956630 🌐 Add translations for: Ukrainian (ukr_UA)
Currently translated at 95.8% (1835 of 1915 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/ukr_UA/
2025-08-28 12:46:49 +02:00
Nicola Bortoletto
91991d5b32 🌐 Add translations for: Italian
Currently translated at 95.3% (1826 of 1915 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/it/
2025-08-28 12:46:49 +02:00
Yaron Shahrabani
447b6ed1ab 🌐 Add translations for: Hebrew
Currently translated at 97.3% (1864 of 1915 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/he/
2025-08-28 12:46:49 +02:00
Stas Haas
336486fecd 🌐 Add translations for: German
Currently translated at 89.2% (1710 of 1915 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/de/
2025-08-28 12:46:48 +02:00
Jun Fang
bbd417c119 🌐 Add translations for: Chinese (Simplified Han script)
Currently translated at 91.8% (1758 of 1915 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/zh_Hans/
2025-08-28 12:46:48 +02:00
Ingrid Pigueron
e3ffd45a18 🌐 Add translations for: French
Currently translated at 96.4% (1847 of 1915 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/fr/
2025-08-28 12:46:48 +02:00
Unreal Vision
52a4a46ebd 🌐 Add translations for: French
Currently translated at 96.4% (1847 of 1915 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/fr/
2025-08-28 12:46:48 +02:00
Elena Torro
025423a75e 🐛 Fix line height on texts and improve text decoration rendering 2025-08-28 12:40:23 +02:00
Hosted Weblate
a6f17e35dd 🌐 Update translation files
Updated by "Cleanup translation files" hook in Weblate.

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/
2025-08-28 12:37:27 +02:00
Andrey Antukh
9a8cac3cac Merge remote-tracking branch 'weblate/develop' into develop 2025-08-28 12:36:51 +02:00
Aitor Moreno
884b857d17 🐛 Fix paste RTF crashes text editor (#7196) 2025-08-28 11:53:39 +02:00
Florian Schroedl
a20bbeff79 🔧 Add ff for typography composite token 2025-08-28 10:42:58 +02:00
Eva Marco
2a5f1f870b 🐛 Fix padding of input field component (#7198) 2025-08-28 10:30:33 +02:00
Luis de Dios
cf5303a39c ♻️ Title bar refactor (#7201) 2025-08-28 09:51:53 +02:00
Andrey Antukh
bf1e26c4e6 Merge pull request #7182 from penpot/niwinz-measures-menu-changes
♻️ Add efficiency refactor for sidebar
2025-08-28 08:40:44 +02:00
Andrey Antukh
4713d943d1 ♻️ Add efficiency refactor for workspace sidebars
The main changes are for right sidebar but left sidebar is also
slightly affected beacuse of the move where the active tokes are
resolved.
2025-08-27 17:56:35 +02:00
Eva Marco
df083cb315 🐛 Fix corner case on tooltip positioning 2025-08-27 17:56:35 +02:00
Eva Marco
6401b25964 💄 Format tab-switcher stories jsx file 2025-08-27 17:56:35 +02:00
Andrey Antukh
65f4adc68e Add minor efficiency enhancements to numeric-input* 2025-08-27 17:56:35 +02:00
Andrey Antukh
dfab472522 💄 Add minor cosmetic change to shape layout type helper 2025-08-27 17:56:35 +02:00
Belén Albeza
9759adf747 🐛 Fix new inline text styles not being applied correctly 2025-08-27 16:52:57 +02:00
Andrey Antukh
9ae1a08573 🐛 Make the app.common.time/inst nil safe 2025-08-27 14:17:11 +02:00
Ingrid Pigueron
ddab2cab14 🌐 Add translations for: French
Currently translated at 98.1% (1867 of 1902 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/fr/
2025-08-27 14:15:14 +02:00
Andrey Antukh
cf1a8fff65 Merge remote-tracking branch 'origin/develop' into develop 2025-08-27 13:19:53 +02:00
Andrey Antukh
45be4769d7 Merge remote-tracking branch 'origin/staging' into develop 2025-08-27 13:19:06 +02:00
María Valderrama
a68c41709a 🐛 Fix misleading affordance in saved versions (#7192) 2025-08-27 13:01:54 +02:00
Xaviju
4290bce718 🎉 Inspect tab layout switcher and computed feature (#7166) 2025-08-27 13:01:01 +02:00
Pablo Alba
3dd237002b 🐛 Fix combine as variants from assets tab selects wrong components (#7190) 2025-08-27 13:00:28 +02:00
Andrey Antukh
e0fb112bfb 📎 Update changelog 2025-08-27 12:52:24 +02:00
Andrey Antukh
2629537fd3 Merge branch 'subscriptions-enhancements' into staging 2025-08-27 12:51:34 +02:00
Marina López
cb7711f637 🐛 Fix integration tests 2025-08-27 12:30:48 +02:00
Andrey Antukh
a114e9adb0 Add logging for management update-customer method 2025-08-27 12:02:39 +02:00
Andrey Antukh
5fed5fa158 Add transactions support on management api 2025-08-27 12:00:03 +02:00
Andrey Antukh
6c8873c7f5 🐛 Ensure for-update locking is used on updating profile props 2025-08-27 11:59:35 +02:00
Andrey Antukh
37b0c4adc0 🐛 Add support fror ::db/for-update on sql ns 2025-08-27 11:58:42 +02:00
Florian Schroedl
9106617436 🎉 Add composite typography token 2025-08-27 11:35:56 +02:00
Yamila Moreno
68a95cf0d0 📎 Fix CI inputs 2025-08-27 11:21:34 +02:00
Yamila Moreno
1438632dde 📎 Fix CI inputs 2025-08-27 11:19:42 +02:00
Florian Schroedl
112fa46896 🐛 Fix case-sensitivity and multi word italic in font weight parsing 2025-08-27 11:15:21 +02:00
Yamila Moreno
6da5bbf33a 📎 Fix CI inputs 2025-08-27 11:14:56 +02:00
Yamila Moreno
95faf340c4 📎 Fix CI inputs 2025-08-27 11:13:13 +02:00
Marina López
723ea508df 🐛 Fix missing link for enterprise trial 2025-08-27 10:56:17 +02:00
Yamila Moreno
cbe538261c 📎 Fix CI inputs 2025-08-27 10:42:13 +02:00
Yamila Moreno
1925e6782f 📎 Fix CI inputs 2025-08-27 10:33:17 +02:00
Yamila Moreno
bcd950c141 📎 Fix CI inputs 2025-08-27 10:11:56 +02:00
Aitor Moreno
b215689566 🎉 Add multiple fonts to text editor WASM playground 2025-08-27 09:57:55 +02:00
Pablo Alba
dfe0f64c7c Add variants advanced retrieve tests (#7183) 2025-08-26 16:40:27 +02:00
Andrey Antukh
9de3910526 Add missing impl for Associative on LoadableWeakValueMap (#7188) 2025-08-26 16:39:48 +02:00
Luis de Dios
59eb75d8c3 💄 Style improvements in the component list & grid (#7185) 2025-08-26 16:35:09 +02:00
Florian Schroedl
6670b76ccc Show warning when applying token with non-matching font variant 2025-08-26 16:12:07 +02:00
Florian Schroedl
09b9383a0b Choose closest font weight for token weight when no matching weight is found 2025-08-26 16:12:07 +02:00
Eva Marco
31e37f352d 🐛 Fix token option schema (#7186)
* 🐛 Fix token option schema

* 🐛 Fix numeric-input schema
2025-08-26 14:06:59 +02:00
Yamila Moreno
c5958e4d61 📎 Add storybook to CI bundle 2025-08-26 10:45:08 +02:00
Luis de Dios
f1e7149e88 Add shortcuts for creating variants and properties (#7181)
*  Add shortcuts for creating variants and properties

* 📎 PR changes
2025-08-26 09:32:41 +02:00
Pablo Alba
d80ef17623 🐛 Fix cut pasting a variant into its own parent (#7179) 2025-08-26 09:25:52 +02:00
Andrey Antukh
ffe469ce71 Merge pull request #7159 from penpot/niwinz-develop-migrations-fixes
♻️ Add a better approach for load libraries on file validation and migrations
2025-08-26 09:25:23 +02:00
Andrey Antukh
c35bb6e09a 🎉 Add loadable weak map impl for libraries loading on validation and migration 2025-08-26 09:03:25 +02:00
Alejandro Alonso
8d404d97a1 🐛 Fix clipping 2025-08-26 08:52:42 +02:00
Andrey Antukh
fa2b0bd67c Don't migrate libraries on accessing them on file data migrations
We don't migrate the libraries for avoid cascade migration; it is not ideal
but it reduces the total of the required memory needed for process a single
file migration that requires libraries to be loaded.
2025-08-26 08:15:45 +02:00
Andrey Antukh
9563d1b1f6 Merge pull request #6635 from penpot/eva-add-numeric-input
 Add numeric input component
2025-08-25 19:42:47 +02:00
Eva Marco
33fc578f96 🎉 Add numeric-input component to DS
A new numeric-input impl compatible with tokens
2025-08-25 18:52:39 +02:00
Andrey Antukh
79786dde16 🎉 Add helpers for work with weak references and weak data structs 2025-08-25 18:52:39 +02:00
Marina López
926b2c9cfb 🐛 Fix doble click to submit subscription 2025-08-25 15:42:47 +02:00
Andrés Moya
c1b2aa7628 🐛 Add handler to correctly encode cljs dates to json 2025-08-25 13:52:38 +02:00
Andrey Antukh
991b26b73f 🐛 Fix undo transaction handling on creating a variant from group of components 2025-08-25 11:48:46 +02:00
Andrey Antukh
254a7461b2 Simplify commit-undo-transaction impl 2025-08-25 11:48:46 +02:00
Andrey Antukh
1384ed8aba Remove duplicated execution of check-open-transactions 2025-08-25 11:48:46 +02:00
Andrey Antukh
c9393c0cfb Remove repeated/duplucated lookups on start-undo-transaction 2025-08-25 11:48:46 +02:00
Pablo Alba
6eeb55fb88 🐛 Fix after variant switch children layouts aren't updated (#7177) 2025-08-25 11:35:33 +02:00
Andrey Antukh
c759afc10d 🔥 Remove unnecessary and broken unique-editors field
From the get-teams rpc method response
2025-08-25 11:33:34 +02:00
Marina López
090cb63568 🐛 Fix condition for members warning 2025-08-25 11:07:19 +02:00
Andrey Antukh
f223831766 Refresh subscription info when member role is updated 2025-08-25 10:53:48 +02:00
Marina López
854f286364 ♻️ Fix subscriptions inconsistencies 2025-08-25 10:53:48 +02:00
Andrey Antukh
2846b80cf7 Add rpc methods for obtain editors 2025-08-25 10:53:12 +02:00
Andrey Antukh
ad0ef82ffc 🎉 Add management http api 2025-08-25 10:53:12 +02:00
Elena Torró
3bb547fc45 🐛 Parse rx and ry SVG values correctly (#7176) 2025-08-25 10:44:11 +02:00
Pablo Alba
c3b326d95e 🐛 Fix duplicating a page with variants should duplicate them (#7172)
* 🐛 Fix duplicating a page with variants should duplicate them

*  MR changes
2025-08-25 10:41:03 +02:00
Luis de Dios
8c1a97dac5 Make some improvements to the swap panel (#7174)
* 💄 Visual improvements in swap panel

* ♻️ Refactor search-bar component to use DS icons

* 📎 PR changes
2025-08-25 10:40:20 +02:00
Alejandro Alonso
4053e8c8db Merge pull request #7173 from penpot/elenatorro-11735-fix-text-auto-width
🐛 Fix paragraph layout width on autowidth
2025-08-22 15:16:40 +02:00
Xaviju
ee86a3943d Update code to use design system icon (#7145) 2025-08-22 14:27:11 +02:00
Elena Torro
46b3e174ed 🐛 Fix paragraph layout width on autowidth 2025-08-22 13:55:24 +02:00
Alejandro Alonso
c0c2c9489c Merge pull request #7170 from penpot/elenatorro-fix-text-tests
🔧 Update and fix text tests
2025-08-22 13:34:00 +02:00
Elena Torró
c05c179d67 Merge pull request #7167 from penpot/azazeln28-feat-text-editor-wasm-playground
🎉 Add Text Editor WASM Playground
2025-08-22 12:47:41 +02:00
Aitor Moreno
596193d34d 🎉 Add missing styles on text leaves 2025-08-22 12:22:51 +02:00
Aitor Moreno
15eee0d8d8 🎉 Add Text Editor WASM Playground 2025-08-22 12:22:51 +02:00
Elena Torro
0b7444e8ff 🐛 Use SrcIn only when there is only one inner stroke, otherwise use erode filter 2025-08-22 09:54:15 +02:00
Elena Torro
96a91dc710 🔧 Add missing emoji ranges 2025-08-22 09:54:03 +02:00
Elena Torro
503d431d8e 🔧 Fix and update text use cases 2025-08-22 09:53:50 +02:00
Alejandro Alonso
ed5875f29a Merge pull request #7154 from penpot/niwinz-staging-bug-1
🐛 Fix incorrect show request-access dialog on not-found on viewer
2025-08-22 09:19:47 +02:00
Yamila Moreno
b12d44150b 📎 Fix and improve ci 2025-08-21 17:42:37 +02:00
Andrey Antukh
66f5eb57b9 🐛 Fix incorrect fills coerce to binary type when flag is disabled (#7169) 2025-08-21 15:11:14 +02:00
Pablo Alba
7023880e67 🐛 On a variants switch, keep the value of the rotation and its transformations (#7165) 2025-08-21 13:55:16 +02:00
Andrey Antukh
0e4cf23a93 🐛 Fix incorrect type coerce operations (#7168)
A regression introduced in previous commits that causes
a browser tab totally killed by memory usage.
2025-08-21 13:52:47 +02:00
Elena Torró
3f93b0d44b Merge pull request #7098 from penpot/superalex-fix-big-blur-2
🐛 Fix big blur rendering for wasm render
2025-08-21 09:23:26 +02:00
Elena Torró
4a6c3d6ad3 Merge pull request #7152 from penpot/superalex-update-skia-binaries
🎉 Update skia binares to 0.87.0
2025-08-21 09:10:37 +02:00
Alejandro Alonso
478439f055 🐛 Fix big blur rendering for wasm render 2025-08-21 08:47:25 +02:00
Alejandro Alonso
9ef2454210 🎉 Update skia binares to 0.87.0 2025-08-21 07:38:46 +02:00
Andrey Antukh
a702fee3cd Merge pull request #7143 from penpot/luis-11856-adjust-component-title
 Adjust the appearance of the variant-related elements in the design tab
2025-08-20 17:41:50 +02:00
Pablo Alba
cac639d267 🐛 Fix deleting a variant from assets panel (#7147) 2025-08-20 17:38:11 +02:00
Elena Torró
0daf548773 Merge pull request #7146 from penpot/superlaex-fix-open-path-calculation
🐛 Fix open path calculation
2025-08-20 16:38:17 +02:00
Alejandro Alonso
9249a5d4ea Merge pull request #7155 from penpot/elenatorro-use-erode-image-filter-for-inner-strokes-with-opacity
🐛 Fix inner strokes with opacity using erode instead of multiple blending modes
2025-08-20 15:55:50 +02:00
Andrey Antukh
4c83feaa31 Merge remote-tracking branch 'origin/staging' into develop 2025-08-20 13:56:58 +02:00
Luis de Dios
4d8ad19eea 💄 Improve the alignment, spaces and sizes of the variant elements 2025-08-20 13:51:04 +02:00
Luis de Dios
e7e7d576b2 ♻️ Adapt title-bar component 2025-08-20 13:36:10 +02:00
Luis de Dios
7f2af1c355 Adjust component title 2025-08-20 13:36:10 +02:00
Andrey Antukh
ad38a21053 🐛 Fix incorrect show request-access dialog on not-found on viewer
When a user is not-authenticated
2025-08-20 13:35:20 +02:00
Elena Torro
9bb92277e4 🐛 Fix inner strokes with opacity using erode instead of multiple blending modes 2025-08-20 13:32:20 +02:00
Alejandro Alonso
643621a389 Merge pull request #7119 from penpot/niwinz-develop-type-hints
 Add several performance enhancements
2025-08-20 12:58:43 +02:00
Alejandro Alonso
ef8d2e7418 Merge pull request #7082 from penpot/niwinz-staging-changes-fix
♻️ Refactor schema references and openapi.json output
2025-08-20 12:55:16 +02:00
Andrey Antukh
adffac4eec Merge remote-tracking branch 'origin/main' into staging 2025-08-20 12:49:31 +02:00
Andrey Antukh
575342b3bb ♻️ Use direct schemas instead of references
Only a very common use, basic types schemas should be used as
reference (with namespaced keywords)
2025-08-20 12:33:07 +02:00
Alejandro Alonso
b6ecb4368e Merge pull request #7044 from penpot/niwinz-develop-refactor-versions-sidebar
♻️ Refactor versions sidebar
2025-08-20 12:00:28 +02:00
Pablo Alba
081df7fc03 🐛 Fix combine variants move items 2025-08-20 11:07:51 +02:00
Yamila Moreno
358343b4df 📎 Add build tag workflow and minor changes 2025-08-20 10:51:05 +02:00
Andrey Antukh
d7c19325cc Add better type references naming on openapi output 2025-08-20 10:47:56 +02:00
Andrey Antukh
b472a8ab19 Add general improvement to openapi and js-like doc output 2025-08-20 09:41:01 +02:00
Andrey Antukh
2b83d0d0e9 Add generative test case for openapi json serialization
This will prevent possible regression on introducing schemas without
generators or schema with generators that can't be serialized to json.
2025-08-20 09:38:57 +02:00
Andrey Antukh
911ac263fa 🐛 Use ::sm/any instead of any for get-file-fragment rpc method schema
The usage of `any?` predicate as-is uses the standard any generator that
causes to generate java.lang.Character instances created that are not
properly serialiable to JSON. The `::sm/any` schema delimits the
generator to a commonly known serializable types on json.
2025-08-20 09:38:55 +02:00
Andrey Antukh
545c78eb74 🐛 Add missing generators 2025-08-20 09:38:13 +02:00
Andrey Antukh
124b098c92 🔥 Remove already deprecated change spec 2025-08-20 09:38:13 +02:00
Andrey Antukh
43ed430475 📎 Update .gitignore file 2025-08-20 09:38:13 +02:00
Andrey Antukh
edd3b1512e 🐛 Add missing attrs to add-component change schema 2025-08-20 09:38:13 +02:00
Andrey Antukh
d9623c3c88 🐛 Add proper schema for decoding :obj on add-obj change 2025-08-20 09:38:13 +02:00
Andrey Antukh
f052e31ff0 🐛 Fix incorrect handling of assign operation on changes protocol 2025-08-20 09:38:13 +02:00
Yamila Moreno
73dfe12ec9 📚 Update k8s documentation 2025-08-20 09:04:25 +02:00
Alejandro Alonso
0c3d73745e 🐛 Fix open path calculation 2025-08-20 09:00:04 +02:00
Aitor Moreno
a6ecc4fb3c Merge pull request #7106 from penpot/niwinz-develop-modifiers-enhacements
 Several enhancements on how shape data is written on memory
2025-08-19 17:05:25 +02:00
Denys Kisil
625d9ab188 🌐 Add translations for: Ukrainian (ukr_UA)
Currently translated at 97.9% (1863 of 1902 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/ukr_UA/
2025-08-19 11:03:09 +00:00
Jun Fang
e6cc15e19b 🌐 Add translations for: Chinese (Simplified Han script)
Currently translated at 93.1% (1771 of 1902 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/zh_Hans/
2025-08-19 11:03:07 +00:00
王世阳
0af2cd6413 🌐 Add translations for: Chinese (Simplified Han script)
Currently translated at 93.1% (1771 of 1902 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/zh_Hans/
2025-08-19 11:03:05 +00:00
IsCycleBai
443e0b0206 🌐 Add translations for: Chinese (Simplified Han script)
Currently translated at 93.1% (1771 of 1902 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/zh_Hans/
2025-08-19 11:03:04 +00:00
Jun Fang
a4fa5e9304 🌐 Add translations for: Chinese (Simplified Han script)
Currently translated at 93.1% (1771 of 1902 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/zh_Hans/
2025-08-19 11:03:02 +00:00
IsCycleBai
d94c311a1e 🌐 Add translations for: Chinese (Simplified Han script)
Currently translated at 93.1% (1771 of 1902 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/zh_Hans/
2025-08-19 11:03:01 +00:00
Pablo Alba
c0c8390a7d 🐛 Fix restoring component inside flex 2025-08-19 12:15:30 +02:00
Andrey Antukh
f4be117219 🔥 Remove app.common.time/duration usage on frontend (#7139)
Is broken and not necessary; duration class is no longer
available on frontend code.
2025-08-19 10:36:34 +02:00
Andrey Antukh
7eb590e9fd ♻️ Refactor versions sidebar 2025-08-18 21:57:47 +02:00
Andrey Antukh
6588913141 ♻️ Remove several level of unnecesary allocation on writing text 2025-08-18 21:54:36 +02:00
Andrey Antukh
5c4a60aee7 Make mem write helpers receive offset as first arg 2025-08-18 21:54:36 +02:00
Andrey Antukh
af02e12685 🎉 Add missing write-u32 helper to mem ns 2025-08-18 21:54:36 +02:00
Andrey Antukh
675864ce0b Remove incorrect usage of dm/get-prop 2025-08-18 21:54:36 +02:00
Andrey Antukh
c55f3182d8 💄 Rename text-dimensions to get-text-dimensions 2025-08-18 21:49:00 +02:00
Andrey Antukh
0d6eac7656 💄 Add mainly cosmetic changes to set-shape-shadows
Mainly replace a loop with run! that used reduce as impl.
After measuring there are no real difference between using
the more complex loop and more simplier run!; in parity of
performance we prefer simplier approach.
2025-08-18 21:49:00 +02:00
Andrey Antukh
7acfd199aa 💄 Add mainly cosmetic changes to set-layout-child 2025-08-18 21:49:00 +02:00
Andrey Antukh
33d6f543a1 Remove several not necessary allocations from set-grid-layout-cells 2025-08-18 21:49:00 +02:00
Luis de Dios
4237ef572e 🐛 Fix use ellipsis when property names are too long (#7135) 2025-08-18 21:36:56 +02:00
Pablo Alba
6babea8b12 🐛 Fix alert for bad formula not showing in copies of variants (#7126)
* 🐛 Fix alert for bad formula not showing in copies of variants

*  MR changes
2025-08-18 21:36:29 +02:00
Pablo Alba
6b7f91c671 🐛 Fix weird resizing on combine variants with constraints scale (#7134) 2025-08-18 21:35:04 +02:00
Pablo Alba
b3b183c151 🐛 Fix duplicate a variant when all have bad formulae crashes 2025-08-18 17:09:20 +02:00
Yamila Moreno
59f2ee87e6 📎 Improve github actions 2025-08-18 15:28:15 +02:00
Pablo Alba
6af8940a46 🐛 On variant create do not set sizing 2025-08-18 15:14:36 +02:00
Xavier Julian
e1a1110f06 📎 Update changelog with new typography tokens 2025-08-18 13:50:14 +02:00
Pablo Alba
1dcf1e0b0f 🐛 Fix :show-content wasn't on components sync-attrs 2025-08-18 13:17:09 +02:00
Yamila Moreno
4c3e345c9c 📎 Fix github actions 2025-08-18 13:05:45 +02:00
Andrey Antukh
a3b9a9f07b Remove reflection calls from buffer macros 2025-08-18 13:03:10 +02:00
Andrey Antukh
17ec360720 Add several missing type hints for avoid reflection and autoboxing 2025-08-18 13:03:10 +02:00
Andrey Antukh
89b67d59d5 Fix autoboxing on path type impl 2025-08-18 13:03:10 +02:00
Andrey Antukh
77be00014e Remove reflection on geom rect code 2025-08-18 13:03:10 +02:00
Andrey Antukh
e336f287b6 Remove reflection on geom matrix code 2025-08-18 13:03:10 +02:00
Andrey Antukh
50aa6ff306 Remove reflection calls on binfile v3 code 2025-08-18 13:03:10 +02:00
Alejandro Alonso
56f162f219 Merge pull request #7133 from penpot/superalex-fix-create-variant-doesnt-work-2
🐛 Create variant doesn't work
2025-08-18 13:02:33 +02:00
Pablo Alba
f7a0c4139a 🐛 Fix you can add a rect into a variant container (#7137) 2025-08-18 13:02:27 +02:00
Alejandro Alonso
7c39e321c4 Merge pull request #7136 from penpot/niwinz-develop-fix-inconsistencies-on-text-shortcuts
🐛 Fix several inconsistencies and duplicated shortcuts
2025-08-18 12:57:18 +02:00
Andrey Antukh
ce6a863599 🐛 Fix several inconsistencies and duplicated shortcuts 2025-08-18 12:31:09 +02:00
Alejandro Alonso
832690e71e 🐛 Create variant doesn't work 2025-08-18 11:58:24 +02:00
Pablo Alba
7526cb0d71 🐛 Fix on variants rotation override is not preserving properly (#7120) 2025-08-18 11:57:58 +02:00
andrés gonzález
3292109ab0 🐛 Fix typos in modal about variant connections (#7122) 2025-08-18 11:47:23 +02:00
Elena Torró
be376d2030 Merge pull request #7124 from penpot/ladybenko-11799-fix-remove-layout
🐛 Fix removing layout (wasm)
2025-08-18 09:52:22 +02:00
Alejandro Alonso
4d455b5e9f Merge pull request #7125 from penpot/elenatorro-11842-fix-groups-rendering-on-drag
🐛 Fix Group extrect calculation
2025-08-18 09:36:58 +02:00
Edgars Andersons
50ce28e378 🌐 Add translations for: Latvian
Currently translated at 98.4% (1872 of 1902 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/lv/
2025-08-15 21:02:02 +02:00
Yaron Shahrabani
1eee8e2ce8 🌐 Add translations for: Hebrew
Currently translated at 99.7% (1897 of 1902 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/he/
2025-08-15 21:02:00 +02:00
Elena Torro
5e6ce9172f 🔧 Return always a shader on merge_fills for consistency 2025-08-14 16:08:03 +02:00
Elena Torró
03adbc2ae8 🔧 Update multiple emoji test and increase resulting image (#7113) 2025-08-14 15:47:55 +02:00
Belén Albeza
e63a3f76f7 🐛 Fix open/close path detection in wasm (#7110)
* 🐛 Fix open/close path detection in wasm

* 💄 Remove leftover code
2025-08-14 15:45:09 +02:00
Elena Torro
6d42d456fb 🐛 Fix Group extrect calculation 2025-08-14 15:39:45 +02:00
Belén Albeza
c818b6f88f 🐛 Fix layout and constraints not being cleared 2025-08-14 15:38:23 +02:00
Belén Albeza
3f3c7905b4 ♻️ Refactor wasm layout functions to their own submodule 2025-08-14 14:17:49 +02:00
Elena Torró
e8dd13beb2 Merge pull request #7118 from penpot/superalex-fix-extrect-invalidation-for-texts
🐛 Fix extrect invalidation for texts
2025-08-14 13:43:42 +02:00
Elena Torró
fc6b64aa68 Merge pull request #7121 from penpot/superalex-fix-set-corners
🐛 Fix set corners
2025-08-14 13:34:43 +02:00
Alejandro Alonso
5e0a2f66e3 🐛 Fix set corners 2025-08-14 11:50:40 +02:00
Pablo Alba
108d4fabba 🐛 Fix menu entry not showing on assets tab (#7115)
* 🐛 Fix menu entry not showing on assets tab

*  MR changes
2025-08-14 10:39:47 +02:00
Pablo Alba
2e277a39ca 🐛 Fix flick on design tab after variant switch (#7116) 2025-08-14 08:14:06 +02:00
Pablo Alba
814ec43714 🐛 Fix variants nesting loops (#7112)
* 🐛 Fix variants nesting loops

*  MR changes
2025-08-14 08:08:31 +02:00
Andrey Antukh
54bb9ea755 Merge remote-tracking branch 'origin/staging' into develop 2025-08-14 08:06:15 +02:00
Pablo Alba
374e921672 🐛 Fix variants change property name multiple selection 2025-08-13 17:29:03 +02:00
Alejandro Alonso
64e5ea93a0 🐛 Fix extrect invalidation for texts 2025-08-13 14:32:23 +02:00
Pablo Alba
2562d70880 🐛 Fix crash dragging external component into a variant without props (#7111) 2025-08-13 14:29:56 +02:00
Alejandro Alonso
d99ef29152 Merge pull request #7029 from penpot/elenatorro-11691-fix-default-text-fill
🔧 Fix text default color and inner stroke opacity
2025-08-13 12:52:14 +02:00
Edgars Andersons
d5a2cd9cd2 🌐 Add translations for: Latvian
Currently translated at 97.8% (1862 of 1902 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/lv/
2025-08-13 12:02:14 +02:00
Elena Torro
82d2889e96 🔧 Improve text strokes blending 2025-08-13 11:50:09 +02:00
Eva Marco
ff2e845f2c 🐛 Fix double click on set name input (#7096) 2025-08-13 09:23:53 +02:00
Florian Schrödl
ccd6ae5ade 🐛 Don't allow letter-spacing value with % (#7100) 2025-08-13 08:31:43 +02:00
Yaron Shahrabani
36bafc0d40 📎 Fix typo on translations 2025-08-12 17:58:10 +02:00
Pablo Alba
f7746b8f94 Add create variants in bulk interactions from assets tab (#7102)
*  Add create variants in bulk interactions from assets tab

*  MR changes
2025-08-12 17:56:47 +02:00
Pablo Alba
537c5ca7b8 🐛 Fix missing selection after swap (#7104) 2025-08-12 17:56:03 +02:00
Pablo Alba
4901a80684 🐛 Fix flex layout everrides are not mantained on variant switch (#7105) 2025-08-12 17:55:29 +02:00
Pablo Alba
03b5d44a7c Merge pull request #7101 from penpot/palba-variants-bulk-root
🐛 Fix bad name on variants bulk when the parent is root
2025-08-12 17:04:13 +02:00
Andrey Antukh
8e51aa8df4 🐛 Fix regression on set-shape-children introduced in prev merge 2025-08-12 16:03:34 +02:00
Andrey Antukh
029a9674ca Merge pull request #7103 from penpot/niwinz-develop-modifiers-enhacements
♻️ Sanitize heap write and read operations
2025-08-12 13:11:02 +02:00
Alejandro Alonso
68cee1b1f1 Merge pull request #7076 from penpot/ladybenko-11755-fix-color-picker
🐛 Fix color picker not working with the new renderer
2025-08-12 11:57:21 +02:00
Aitor Moreno
3f74e230b2 Merge pull request #7092 from penpot/superalex-fix-artifacts-while-panning
🐛 Fix artifacts while panning in wasm render
2025-08-12 11:52:18 +02:00
Elena Torró
6bf1919f8d Merge pull request #7094 from penpot/superalex-fix-ctrl-b-for-editor-v2
🐛 Fix ctrl+b for editor v2
2025-08-12 11:36:24 +02:00
Andrey Antukh
e69d61eaf4 Add facilities for work with dataview with common alases 2025-08-12 11:27:13 +02:00
Alejandro Alonso
2f83f22753 🐛 Fix artifacts while panning in wasm render 2025-08-12 11:23:13 +02:00
Andrey Antukh
f9d757bb85 Move several mem write helpers to mem.heap32 ns
For simplify usage and make it clear the required addressing
is used for that functions
2025-08-12 10:53:02 +02:00
Andrey Antukh
6b6e80f4b8 🐛 Fix regression introduced on the set-grid-layout-cells fn
Incorrect data is used for calcultate the size
2025-08-12 10:33:50 +02:00
Andrey Antukh
f32b92a5b0 Assign defaults on serializers instead on api
For make the operations more efficient
2025-08-12 10:33:08 +02:00
Andrey Antukh
761a0a7009 Improve memory write operations on set-grid-layout-rows 2025-08-12 10:32:35 +02:00
Andrey Antukh
129d3e61fa 🎉 Add missing wrap method on buffer abstraction 2025-08-12 10:30:02 +02:00
Stephan Paternotte
aa94671002 🌐 Add translations for: Dutch
Currently translated at 100.0% (1902 of 1902 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/nl/
2025-08-12 10:02:02 +02:00
Nicola Bortoletto
52cf136f84 🌐 Add translations for: Italian
Currently translated at 96.7% (1841 of 1902 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/it/
2025-08-12 10:02:01 +02:00
Yaron Shahrabani
808427795c 🌐 Add translations for: Hebrew
Currently translated at 99.6% (1895 of 1902 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/he/
2025-08-12 10:01:59 +02:00
Andrey Antukh
3f71734cb4 Remove unnecessary anon fn allocation on set-grid-layout-data
And remove incorrect use of dm/get prop for non statically known
attributes of shape
2025-08-12 09:59:18 +02:00
Andrey Antukh
9f14edb0d7 Remove unnecessary anonymouns fn allocation from set-flex-layout
And also removes usage of dm/get-prop for props that are known to be
not static
2025-08-12 09:59:18 +02:00
Andrey Antukh
7fa7a806a8 Remove unnecesary allocation of corners on wasm api set-shape 2025-08-12 09:59:18 +02:00
Andrey Antukh
d364f4db62 ♻️ Sanitize heap write and read operations
Mainly improves the offset management making it less
error prone, encapsulating the write operation and offeset
management into write-* operations with proper asserts
for the expected heap type.
2025-08-12 09:59:18 +02:00
Andrey Antukh
f2c431d029 Merge pull request #7041 from penpot/alotor-wasm-bools
 Add wasm boolean calculations
2025-08-12 08:07:18 +02:00
Belén Albeza
6a667c30d6 🐛 Fix color picking sometimes not picking color and/or getting stuck in a react infinite update loop 2025-08-11 17:02:12 +02:00
Alejandro Alonso
de637fcf4e 🐛 Fix ctrl+b for editor v2 2025-08-11 14:56:04 +02:00
Aitor Moreno
132069472c Merge pull request #7067 from penpot/superalex-fix-frames-extrect-calculation
🐛 Fix frames extrect calculation
2025-08-11 13:57:29 +02:00
Elena Torro
172c6ad4b8 🔧 Set fill paint as transparent when there are no fills 2025-08-11 13:52:49 +02:00
Andrey Antukh
73a72ec1c7 💄 Add naming and docstring consistency fixes to wasm api 2025-08-11 12:49:01 +02:00
Andrey Antukh
c39a8d84ac 💄 Abstract call to mem/free on wasm api ns 2025-08-11 10:30:14 +02:00
Andrey Antukh
027e5c64cc Reduce compexity on set-shape-children wasm api method 2025-08-11 10:30:14 +02:00
Andrey Antukh
ba42c9b85e Add improved interop between wasm bool and common code 2025-08-11 10:30:14 +02:00
alonso.torres
cd1be43384 Add support for boolean shapes 2025-08-11 10:30:14 +02:00
Andrey Antukh
6176027263 Import translatiosn from weblate
commit 17905edb9d24c9ae60921d94d1367a6e91df2b51
Author: VKing9 <vaibhavrathod2282@gmail.com>
Date:   Mon Aug 11 09:17:44 2025 +0200

    🌐 Add translations for: Hindi

    Currently translated at 96.1% (1829 of 1902 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/hi/

commit b57270851a843c64af8698ea7f8300cab1be75cf
Author: Henrik Allberg <henrik@thexorb.com>
Date:   Mon Aug 11 09:19:56 2025 +0200

    🌐 Add translations for: Swedish

    Currently translated at 84.4% (1607 of 1902 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/sv/

commit 3aa31a7a52ba54126d3d14f6f24ea493f17ef99e
Author: Црнобог <68vuletic@gmail.com>
Date:   Mon Aug 11 09:19:49 2025 +0200

    🌐 Add translations for: Serbian

    Currently translated at 73.0% (1389 of 1902 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/sr/

commit c451f75888be5d27aac35c716375cf722ccb805a
Author: Alejandro Alonso <alejandro.alonso@kaleidos.net>
Date:   Mon Aug 11 09:20:32 2025 +0200

    🌐 Add translations for: Yoruba

    Currently translated at 62.7% (1193 of 1902 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/yo/

commit 64d084cfef057cdd635874aad961ad1f42cc16ab
Author: Alejandro Alonso <alejandro.alonso@kaleidos.net>
Date:   Mon Aug 11 09:17:58 2025 +0200

    🌐 Add translations for: Igbo

    Currently translated at 27.2% (518 of 1902 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/ig/

commit afee2e44bb22dfd28d55704cb1c387bf33b271ec
Author: Revenant <mohdmuizz22@yahoo.com>
Date:   Mon Aug 11 09:18:44 2025 +0200

    🌐 Add translations for: Malay

    Currently translated at 35.7% (680 of 1902 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/ms/

commit 27a43f53a486f9794e3d739793ca03cf11888240
Author: Alejandro Alonso <alejandro.alonso@kaleidos.net>
Date:   Mon Aug 11 09:17:27 2025 +0200

    🌐 Add translations for: Hausa

    Currently translated at 66.1% (1259 of 1902 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/ha/

commit 76d634a8da529ca27ff4f50d044ef8077b995b42
Author: Stephan Paternotte <stephan@paternottes.net>
Date:   Mon Aug 11 09:19:06 2025 +0200

    🌐 Add translations for: Dutch

    Currently translated at 96.2% (1830 of 1902 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/nl/

commit eacdded92d1c8be56117e8d5ca0cf99db0d6b506
Author: Edgars Andersons <Edgars+Weblate@gaitenis.id.lv>
Date:   Mon Aug 11 09:18:35 2025 +0200

    🌐 Add translations for: Latvian

    Currently translated at 96.2% (1830 of 1902 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/lv/

commit 162163d566ef2ff89c3f96e0dbddfc24ea89bbe0
Author: Ņikita K <nikita.kozlovs@gmail.com>
Date:   Mon Aug 11 09:18:31 2025 +0200

    🌐 Add translations for: Latvian

    Currently translated at 96.2% (1830 of 1902 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/lv/

commit 01275a3458f485aeef190bf6588e0e45e8fad334
Author: Suhwan Kim <jgk9282@gmail.com>
Date:   Mon Aug 11 09:18:19 2025 +0200

    🌐 Add translations for: Korean

    Currently translated at 11.4% (218 of 1902 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/ko/

commit 03ba18cda687c3738bdcb6f49fd179eb449b50a3
Author: Denys Kisil <ossenjoyer@proton.me>
Date:   Mon Aug 11 09:20:29 2025 +0200

    🌐 Add translations for: Ukrainian (ukr_UA)

    Currently translated at 96.2% (1830 of 1902 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/ukr_UA/

commit ec77d8ada6f02abd03676febc1b2974c91bc907c
Author: al0cam <benjaminsikac@gmail.com>
Date:   Mon Aug 11 09:17:46 2025 +0200

    🌐 Add translations for: Croatian

    Currently translated at 85.2% (1621 of 1902 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/hr/

commit fce74589887b1439e73324fea8e145273a1a9236
Author: Zvonimir Juranko <zjuranko@gmail.com>
Date:   Mon Aug 11 09:17:46 2025 +0200

    🌐 Add translations for: Croatian

    Currently translated at 85.2% (1621 of 1902 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/hr/

commit e16c2c3118755810d07738671cbd2f7c6452e328
Author: TheScientistPT <joao.ed.reis.gomes@gmail.com>
Date:   Mon Aug 11 09:19:29 2025 +0200

    🌐 Add translations for: Portuguese (Portugal)

    Currently translated at 83.5% (1589 of 1902 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/pt_PT/

commit 7a394c7d4e3d2d43c93218f2e191919a1c23c864
Author: Dário <dariogomes@gmail.com>
Date:   Mon Aug 11 09:19:29 2025 +0200

    🌐 Add translations for: Portuguese (Portugal)

    Currently translated at 83.5% (1589 of 1902 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/pt_PT/

commit 32c157b0c377fbcefeb83c1f1559d32ed935367f
Author: Amerey.eu <info@amerey.eu>
Date:   Mon Aug 11 09:15:59 2025 +0200

    🌐 Add translations for: Czech

    Currently translated at 84.9% (1615 of 1902 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/cs/

commit 3abf6a572727a8a93d6e0fac5f037c9383f213b0
Author: Mikel Larreategi <mlarreategi@codesyntax.com>
Date:   Mon Aug 11 09:16:45 2025 +0200

    🌐 Add translations for: Basque

    Currently translated at 61.4% (1169 of 1902 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/eu/

commit b9165b23d30672f41324dc0135e6d519c0b704d1
Author: Radek Sawicki <radek@sqrc.pl>
Date:   Mon Aug 11 09:19:09 2025 +0200

    🌐 Add translations for: Polish

    Currently translated at 59.9% (1141 of 1902 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/pl/

commit b02c4cc7df984212eee183f813c7f5f16cd4c9eb
Author: Nicola Bortoletto <nicola.bortoletto@live.com>
Date:   Mon Aug 11 09:18:08 2025 +0200

    🌐 Add translations for: Italian

    Currently translated at 96.2% (1830 of 1902 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/it/

commit 4eae1c68c2c17d438282a3d5f246609c97bf0064
Author: Valentina Chapellu <valentina.chapellu@gmail.com>
Date:   Mon Aug 11 09:18:04 2025 +0200

    🌐 Add translations for: Italian

    Currently translated at 96.2% (1830 of 1902 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/it/

commit 225484e99e58fdf32dd888f70bb95f3070b16dc2
Author: Ahmad HosseinBor <123hozeifeh@gmail.com>
Date:   Mon Aug 11 09:16:52 2025 +0200

    🌐 Add translations for: Persian

    Currently translated at 41.0% (780 of 1902 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/fa/

commit 56ad686a1bf5634d52929790a315263fa77f2999
Author: william chen <william.fromtw@gmail.com>
Date:   Mon Aug 11 09:20:46 2025 +0200

    🌐 Add translations for: Chinese (Traditional Han script)

    Currently translated at 85.1% (1620 of 1902 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/zh_Hant/

commit 8d7c4c97556f7e5f001183535df09a1c796cdec1
Author: im424 <424@live.hk>
Date:   Mon Aug 11 09:20:46 2025 +0200

    🌐 Add translations for: Chinese (Traditional Han script)

    Currently translated at 85.1% (1620 of 1902 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/zh_Hant/

commit 00eea4f7f6fb6a02cd4256a5269d76d5ee678c3f
Author: Yaron Shahrabani <sh.yaron@gmail.com>
Date:   Mon Aug 11 09:17:37 2025 +0200

    🌐 Add translations for: Hebrew

    Currently translated at 96.2% (1830 of 1902 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/he/

commit 23bed6b374ceee65a2c257ea3c32b9a8726a619d
Author: Linerly <linerly@proton.me>
Date:   Mon Aug 11 09:17:52 2025 +0200

    🌐 Add translations for: Indonesian

    Currently translated at 90.3% (1719 of 1902 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/id/

commit ab3fb9f1b6b0596f564a1e4ba580a55b2ee5a556
Author: Mahmoud A. Rabo <Mahmoud@s3geeks.com>
Date:   Mon Aug 11 09:15:34 2025 +0200

    🌐 Add translations for: Arabic

    Currently translated at 58.8% (1120 of 1902 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/ar/

commit e1dd8905c6290e7f634de0e0e5228ac38cdbce4d
Author: AlexTECPlayz <alextec70@outlook.com>
Date:   Mon Aug 11 09:19:36 2025 +0200

    🌐 Add translations for: Romanian

    Currently translated at 68.1% (1296 of 1902 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/ro/

commit fb3401c258f195d23a0f33461cd596eaf10b8751
Author: George Lemon <george@getvasco.com>
Date:   Mon Aug 11 09:19:35 2025 +0200

    🌐 Add translations for: Romanian

    Currently translated at 68.1% (1296 of 1902 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/ro/

commit b8e351851472436c70ecf51a59f87dfbc038c2cf
Author: Allan Nordhøy <epost@anotheragency.no>
Date:   Mon Aug 11 09:18:56 2025 +0200

    🌐 Add translations for: Norwegian Bokmål

    Currently translated at 8.7% (166 of 1902 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/nb_NO/

commit 322b67dabc5332d11e004d1ddbd1109c612a8460
Author: Stas Haas <stas@girafic.de>
Date:   Mon Aug 11 09:16:14 2025 +0200

    🌐 Add translations for: German

    Currently translated at 90.1% (1714 of 1902 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/de/

commit c46e2d73039f3dcb6c7840060a7086829287ff80
Author: Pablo Alba <pablo.alba@kaleidos.net>
Date:   Mon Aug 11 09:16:12 2025 +0200

    🌐 Add translations for: German

    Currently translated at 90.1% (1714 of 1902 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/de/

commit fbc774fe28c2e051c5f7926135955ad39146eff4
Author: Eranot <renato.konflanz@unochapeco.edu.br>
Date:   Mon Aug 11 09:19:23 2025 +0200

    🌐 Add translations for: Portuguese (Brazil)

    Currently translated at 67.0% (1276 of 1902 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/pt_BR/

commit a8f110374dc910462a7e83010b93f01c5ef5c514
Author: 王世阳 <wangshiyangchina@gmail.com>
Date:   Mon Aug 11 09:20:38 2025 +0200

    🌐 Add translations for: Chinese (Simplified Han script)

    Currently translated at 72.0% (1370 of 1902 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/zh_Hans/

commit 9a31a6239be28d43157132bfa9d6d7d2543b26ec
Author: Anonymous <noreply@weblate.org>
Date:   Mon Aug 11 09:20:38 2025 +0200

    🌐 Add translations for: Chinese (Simplified Han script)

    Currently translated at 72.0% (1370 of 1902 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/zh_Hans/

commit 024ff5c9ed52bca1112828512c60ee3049d956c0
Author: Merih Güz <iletisim@merihguz.com>
Date:   Mon Aug 11 09:20:17 2025 +0200

    🌐 Add translations for: Turkish

    Currently translated at 75.6% (1438 of 1902 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/tr/

commit 5de31af3af03876f5af4bdba91c17b4889386fe9
Author: Çağlar Yeşilyurt <grch@mm.st>
Date:   Mon Aug 11 09:20:17 2025 +0200

    🌐 Add translations for: Turkish

    Currently translated at 75.6% (1438 of 1902 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/tr/

commit 92ad28a35d98930a895bf9c070aeecce3056a643
Author: The_BadUser <vanjavs41@gmail.com>
Date:   Mon Aug 11 09:19:43 2025 +0200

    🌐 Add translations for: Russian

    Currently translated at 75.8% (1442 of 1902 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/ru/

commit ed9522d50281d56df8ccf7257f028e1ff317b4bc
Author: Vin <k3kelm4vw@mozmail.com>
Date:   Mon Aug 11 09:19:43 2025 +0200

    🌐 Add translations for: Russian

    Currently translated at 75.8% (1442 of 1902 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/ru/

commit 52b2837ef77449020f18d5fb4a3c8af539fe477e
Author: Anonymous <noreply@weblate.org>
Date:   Mon Aug 11 09:16:19 2025 +0200

    🌐 Add translations for: Greek

    Currently translated at 27.0% (515 of 1902 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/el/

commit 15656760a1546bc877149797fd322f489cd9030a
Author: Ingrid Pigueron <ingridp.uxr@gmail.com>
Date:   Mon Aug 11 09:17:17 2025 +0200

    🌐 Add translations for: French

    Currently translated at 96.1% (1829 of 1902 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/fr/

commit d6952275de5e9a83bfe4d2238147c80bcfa1e35b
Author: Unreal Vision <unrealvisionyt@gmail.com>
Date:   Mon Aug 11 09:17:14 2025 +0200

    🌐 Add translations for: French

    Currently translated at 96.1% (1829 of 1902 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/fr/

commit 828f535facc0a9d3c586fed027b23443b0698ee2
Author: Louis Chance <contact@louischance.com>
Date:   Mon Aug 11 09:17:13 2025 +0200

    🌐 Add translations for: French

    Currently translated at 96.1% (1829 of 1902 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/fr/

commit 0656f7836a630f409d9fc575e132f250eec7f5a3
Author: Pablo Alba <pablo.alba@kaleidos.net>
Date:   Mon Aug 11 09:17:13 2025 +0200

    🌐 Add translations for: French

    Currently translated at 96.1% (1829 of 1902 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/fr/

commit 0497701d1ca4134549c5b8bd4419466f87111fcd
Author: Anonymous <noreply@weblate.org>
Date:   Mon Aug 11 09:16:31 2025 +0200

    🌐 Add translations for: Spanish

    Currently translated at 97.2% (1850 of 1902 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/es/

commit 22c77ac2bf5fa9f5945bd680b97fafe5779b7324
Author: Andrey Antukh <niwi@niwi.nz>
Date:   Mon Aug 11 09:16:25 2025 +0200

    🌐 Add translations for: Spanish

    Currently translated at 97.2% (1850 of 1902 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/es/

commit cdd3b23d7ccb1cf00fa3b66788df69449f012de7
Author: Aryiu <aryiu@users.noreply.hosted.weblate.org>
Date:   Mon Aug 11 09:15:52 2025 +0200

    🌐 Add translations for: Catalan

    Currently translated at 56.6% (1078 of 1902 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/ca/

commit 41ab7871188c93469c9e94ade3c495a7380450e1
Author: Hosted Weblate <hosted@weblate.org>
Date:   Mon Aug 11 09:15:14 2025 +0200

    🌐 Update translation files

    Updated by "Cleanup translation files" hook in Weblate.

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/

commit 4f46b6b42a9660cdceaf231e9e20615b4e64c8fe
Merge: 58bd7c6bd4 2239711f15
Author: Hosted Weblate <hosted@weblate.org>
Date:   Mon Aug 11 09:15:10 2025 +0200

    🌐 Merge branch 'origin/develop' into Weblate.

commit 2239711f15f62c29cb7eb1981874ae81019d4b3e
Author: Stas Haas <stas@girafic.de>
Date:   Tue Jul 29 07:59:24 2025 +0200

    🌐 Add translations for: German

    Currently translated at 92.6% (1721 of 1857 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/de/

commit 836068ca8cbc3e72a96bfa4be1d239ad2d516d32
Author: VKing9 <vaibhavrathod2282@gmail.com>
Date:   Thu Jul 10 08:41:57 2025 +0200

    🌐 Add translations for: Hindi

    Currently translated at 100.0% (1857 of 1857 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/hi/

commit 1c2958825198a6194bf99db5cc50a3a386df98f6
Author: VKing9 <vaibhavrathod2282@gmail.com>
Date:   Thu Jul 10 07:58:53 2025 +0200

    🌐 Add translations for: Hindi

    Currently translated at 100.0% (1857 of 1857 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/hi/

commit c0f884b12350225c897e0f0843e09a02ea1c6639
Author: VKing9 <vaibhavrathod2282@gmail.com>
Date:   Thu Jul 10 07:56:18 2025 +0200

    🌐 Add translations for: Hindi

    Currently translated at 100.0% (1857 of 1857 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/hi/

commit 4692c0019c9d09a1019b6605d748d8f3144edf68
Author: VKing9 <vaibhavrathod2282@gmail.com>
Date:   Thu Jul 10 07:51:22 2025 +0200

    🌐 Add translations for: Hindi

    Currently translated at 100.0% (1857 of 1857 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/hi/

commit 6f74a30b90e39d1cb998dd7a37931d1a55a1bbfb
Author: VKing9 <vaibhavrathod2282@gmail.com>
Date:   Thu Jul 10 07:44:43 2025 +0200

    🌐 Add translations for: Hindi

    Currently translated at 100.0% (1857 of 1857 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/hi/

commit e657464742dc9f151313d4450025fd3ac57a6732
Author: VKing9 <vaibhavrathod2282@gmail.com>
Date:   Thu Jul 10 07:39:28 2025 +0200

    🌐 Add translations for: Hindi

    Currently translated at 100.0% (1857 of 1857 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/hi/

commit a41e8ed7865083123703710fbdacaa5ee9e506fa
Author: VKing9 <vaibhavrathod2282@gmail.com>
Date:   Thu Jul 10 07:34:59 2025 +0200

    🌐 Add translations for: Hindi

    Currently translated at 100.0% (1857 of 1857 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/hi/

commit 4d27f8cb303b27f9ddba30d2a2fbc2163c920694
Author: VKing9 <vaibhavrathod2282@gmail.com>
Date:   Thu Jul 10 07:27:34 2025 +0200

    🌐 Add translations for: Hindi

    Currently translated at 100.0% (1857 of 1857 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/hi/

commit b5369fa2380beaa190265df4847c81af713bf348
Author: VKing9 <vaibhavrathod2282@gmail.com>
Date:   Thu Jul 10 07:03:29 2025 +0200

    🌐 Add translations for: Hindi

    Currently translated at 100.0% (1857 of 1857 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/hi/

commit 4d639b62f29e469abce6f463208079e73f70b146
Author: VKing9 <vaibhavrathod2282@gmail.com>
Date:   Thu Jul 10 07:02:50 2025 +0200

    🌐 Add translations for: Hindi

    Currently translated at 100.0% (1857 of 1857 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/hi/

commit ddb5fe44ee8e12f6592b4cbf3f0c9f5a1be3f695
Author: VKing9 <vaibhavrathod2282@gmail.com>
Date:   Thu Jul 10 06:49:11 2025 +0200

    🌐 Add translations for: Hindi

    Currently translated at 100.0% (1857 of 1857 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/hi/

commit e702b556e2ae798e22cc966f6eff421cbc6fda81
Author: VKing9 <vaibhavrathod2282@gmail.com>
Date:   Thu Jul 10 06:42:32 2025 +0200

    🌐 Add translations for: Hindi

    Currently translated at 100.0% (1857 of 1857 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/hi/

commit f74f8f96e5af79900df3508ee5551d8f85e63558
Author: VKing9 <vaibhavrathod2282@gmail.com>
Date:   Thu Jul 10 06:40:51 2025 +0200

    🌐 Add translations for: Hindi

    Currently translated at 100.0% (1857 of 1857 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/hi/

commit f7db30ac4d1855b646e0ece454a2153aaaaeb309
Author: VKing9 <vaibhavrathod2282@gmail.com>
Date:   Thu Jul 10 06:33:44 2025 +0200

    🌐 Add translations for: Hindi

    Currently translated at 100.0% (1857 of 1857 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/hi/

commit 07fd2353f670b981601f5d51aca3f013483af9a6
Author: VKing9 <vaibhavrathod2282@gmail.com>
Date:   Wed Jul 9 09:29:04 2025 +0200

    🌐 Add translations for: Hindi

    Currently translated at 82.7% (1536 of 1857 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/hi/

commit a8b578cbaa69c6bd1c8319b43a96799267eae98d
Author: VKing9 <vaibhavrathod2282@gmail.com>
Date:   Wed Jul 9 09:25:49 2025 +0200

    🌐 Add translations for: Hindi

    Currently translated at 82.7% (1536 of 1857 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/hi/

commit 12a9927f7b5b257d2909be6c73af72a58ddfb8b6
Author: VKing9 <vaibhavrathod2282@gmail.com>
Date:   Wed Jul 9 09:24:52 2025 +0200

    🌐 Add translations for: Hindi

    Currently translated at 82.7% (1536 of 1857 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/hi/

commit 2314eab73fa7fcb7b479c16dfb0551a188a7c46e
Author: VKing9 <vaibhavrathod2282@gmail.com>
Date:   Wed Jul 9 09:23:25 2025 +0200

    🌐 Add translations for: Hindi

    Currently translated at 82.7% (1536 of 1857 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/hi/

commit 88b721c600ff72a2e8bdc4c301f0745a3174fbd5
Author: VKing9 <vaibhavrathod2282@gmail.com>
Date:   Wed Jul 9 09:17:17 2025 +0200

    🌐 Add translations for: Hindi

    Currently translated at 82.7% (1536 of 1857 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/hi/

commit 14b4124e4cdf4ced296d234b4dbd76afa5a6166c
Author: VKing9 <vaibhavrathod2282@gmail.com>
Date:   Wed Jul 9 09:12:41 2025 +0200

    🌐 Add translations for: Hindi

    Currently translated at 82.7% (1536 of 1857 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/hi/

commit ccaa8da28c65d0256027f2fbf3e556797ef901fb
Author: VKing9 <vaibhavrathod2282@gmail.com>
Date:   Wed Jul 9 08:16:45 2025 +0200

    🌐 Add translations for: Hindi

    Currently translated at 82.7% (1536 of 1857 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/hi/

commit e517e2f0152383549a46ac72b4ebc94752dbdbf3
Author: VKing9 <vaibhavrathod2282@gmail.com>
Date:   Wed Jul 9 08:12:19 2025 +0200

    🌐 Add translations for: Hindi

    Currently translated at 82.7% (1536 of 1857 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/hi/

commit cb359962bc2aff200c501d8466db1097e93d074e
Author: VKing9 <vaibhavrathod2282@gmail.com>
Date:   Wed Jul 9 08:03:00 2025 +0200

    🌐 Add translations for: Hindi

    Currently translated at 82.7% (1536 of 1857 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/hi/

commit 71205252a4f4aadeed2cf0b6da41722a6d2e38a8
Author: VKing9 <vaibhavrathod2282@gmail.com>
Date:   Wed Jul 9 07:51:41 2025 +0200

    🌐 Add translations for: Hindi

    Currently translated at 82.7% (1536 of 1857 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/hi/

commit fe56a9fdd177c4ca624b9dbb88bfa30dc31a92f4
Author: VKing9 <vaibhavrathod2282@gmail.com>
Date:   Wed Jul 9 07:48:33 2025 +0200

    🌐 Add translations for: Hindi

    Currently translated at 82.7% (1536 of 1857 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/hi/

commit 3f2d9bf68f466c21557e045fcce7aab76441d9da
Author: VKing9 <vaibhavrathod2282@gmail.com>
Date:   Wed Jul 9 07:22:29 2025 +0200

    🌐 Add translations for: Hindi

    Currently translated at 82.7% (1536 of 1857 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/hi/

commit e41af1831d5f749e341ce163f520ce2dff5fc7de
Author: VKing9 <vaibhavrathod2282@gmail.com>
Date:   Wed Jul 9 07:21:22 2025 +0200

    🌐 Add translations for: Hindi

    Currently translated at 82.7% (1536 of 1857 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/hi/

commit bb8c9129c9c3cff69ce59b7bfe86560bba977e09
Author: VKing9 <vaibhavrathod2282@gmail.com>
Date:   Wed Jul 9 07:20:40 2025 +0200

    🌐 Add translations for: Hindi

    Currently translated at 82.7% (1536 of 1857 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/hi/

commit efd5849fc1e6e76fdf91b21b0a69be2b7e89cbcf
Author: VKing9 <vaibhavrathod2282@gmail.com>
Date:   Wed Jul 9 07:18:52 2025 +0200

    🌐 Add translations for: Hindi

    Currently translated at 82.7% (1536 of 1857 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/hi/

commit 0b2403b8bd2682e4a2cfdfe879b34c83ed5a6913
Author: VKing9 <vaibhavrathod2282@gmail.com>
Date:   Wed Jul 9 07:13:43 2025 +0200

    🌐 Add translations for: Hindi

    Currently translated at 82.7% (1536 of 1857 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/hi/

commit 8412b71915047cf0d436279b89f93bc0c77f1c20
Author: VKing9 <vaibhavrathod2282@gmail.com>
Date:   Wed Jul 9 07:03:41 2025 +0200

    🌐 Add translations for: Hindi

    Currently translated at 82.7% (1536 of 1857 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/hi/

commit fe49d3ccd5697ef830bb71086557f8a249c3ed6e
Author: VKing9 <vaibhavrathod2282@gmail.com>
Date:   Wed Jul 9 07:02:20 2025 +0200

    🌐 Add translations for: Hindi

    Currently translated at 82.7% (1536 of 1857 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/hi/

commit 48f39509b7a93e501115c3d4cc5d8bb76361b197
Author: VKing9 <vaibhavrathod2282@gmail.com>
Date:   Wed Jul 9 07:00:51 2025 +0200

    🌐 Add translations for: Hindi

    Currently translated at 82.7% (1536 of 1857 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/hi/

commit 634df69814a209dc830ffebe471be4e821b849fa
Author: VKing9 <vaibhavrathod2282@gmail.com>
Date:   Wed Jul 9 06:57:19 2025 +0200

    🌐 Add translations for: Hindi

    Currently translated at 82.7% (1536 of 1857 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/hi/

commit f2ddf8266af3f4d56351883f5ad845327834fe8b
Author: VKing9 <vaibhavrathod2282@gmail.com>
Date:   Wed Jul 9 06:50:16 2025 +0200

    🌐 Add translations for: Hindi

    Currently translated at 82.7% (1536 of 1857 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/hi/

commit 27d24e6438d34ecfea68b87d0322d51b05cfdb68
Author: VKing9 <vaibhavrathod2282@gmail.com>
Date:   Tue Jul 8 09:49:01 2025 +0200

    🌐 Add translations for: Hindi

    Currently translated at 82.7% (1536 of 1857 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/hi/

commit bc0afe1b8053bb0258b7b18905714d3cc070c55f
Author: VKing9 <vaibhavrathod2282@gmail.com>
Date:   Tue Jul 8 09:40:07 2025 +0200

    🌐 Add translations for: Hindi

    Currently translated at 82.7% (1536 of 1857 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/hi/

commit 4f6e0bd6778e8105d248f298319b9771c99347a1
Author: VKing9 <vaibhavrathod2282@gmail.com>
Date:   Tue Jul 8 09:36:54 2025 +0200

    🌐 Add translations for: Hindi

    Currently translated at 82.7% (1536 of 1857 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/hi/

commit faae4f0c18ee77bd2330936448823f3caa7df881
Author: VKing9 <vaibhavrathod2282@gmail.com>
Date:   Tue Jul 8 09:35:38 2025 +0200

    🌐 Add translations for: Hindi

    Currently translated at 82.7% (1536 of 1857 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/hi/

commit 5e43671edccc5786f46afba4b1e5c32de39d05a6
Author: VKing9 <vaibhavrathod2282@gmail.com>
Date:   Tue Jul 8 09:29:10 2025 +0200

    🌐 Add translations for: Hindi

    Currently translated at 82.7% (1536 of 1857 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/hi/

commit 6aec58217b608f125e327d9b7048fa163984b8b3
Author: VKing9 <vaibhavrathod2282@gmail.com>
Date:   Tue Jul 8 09:24:10 2025 +0200

    🌐 Add translations for: Hindi

    Currently translated at 82.7% (1536 of 1857 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/hi/

commit a20b28bfe96618e507259b6294f6791bc30e1ed3
Author: VKing9 <vaibhavrathod2282@gmail.com>
Date:   Tue Jul 8 09:22:34 2025 +0200

    🌐 Add translations for: Hindi

    Currently translated at 82.7% (1536 of 1857 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/hi/

commit 59ee55aa262c7248b9f85f2fdd5b217132b71975
Author: VKing9 <vaibhavrathod2282@gmail.com>
Date:   Tue Jul 8 09:21:42 2025 +0200

    🌐 Add translations for: Hindi

    Currently translated at 82.7% (1536 of 1857 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/hi/

commit 3825a6a464c6015f383e90be9155c81da8a1f2c1
Author: VKing9 <vaibhavrathod2282@gmail.com>
Date:   Tue Jul 8 09:17:33 2025 +0200

    🌐 Add translations for: Hindi

    Currently translated at 82.7% (1536 of 1857 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/hi/

commit 7fe83a8f347a65e101ec1e01ef30d8791057718f
Author: VKing9 <vaibhavrathod2282@gmail.com>
Date:   Tue Jul 8 07:39:05 2025 +0200

    🌐 Add translations for: Hindi

    Currently translated at 52.2% (970 of 1857 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/hi/

commit 7eab18e15ec35f4e7a4eb33fbec17c8fd61c5a65
Author: VKing9 <vaibhavrathod2282@gmail.com>
Date:   Tue Jul 8 07:28:07 2025 +0200

    🌐 Add translations for: Hindi

    Currently translated at 52.2% (970 of 1857 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/hi/

commit 66a42acd37df0eecfa409fd460b279565b7c7292
Author: VKing9 <vaibhavrathod2282@gmail.com>
Date:   Tue Jul 8 07:23:43 2025 +0200

    🌐 Add translations for: Hindi

    Currently translated at 52.2% (970 of 1857 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/hi/

commit 9eb17f7172141e366eb338b128bf2229deeb1246
Author: VKing9 <vaibhavrathod2282@gmail.com>
Date:   Tue Jul 8 07:23:08 2025 +0200

    🌐 Add translations for: Hindi

    Currently translated at 52.2% (970 of 1857 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/hi/

commit 2626d45eb96da5e47a5b90c5ba4aa13362b8eea2
Author: VKing9 <vaibhavrathod2282@gmail.com>
Date:   Mon Jul 7 11:56:38 2025 +0200

    🌐 Add translations for: Hindi

    Currently translated at 52.2% (970 of 1857 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/hi/

commit f3719edaa121a9c880cf5f670ed18bb6f1806378
Author: VKing9 <vaibhavrathod2282@gmail.com>
Date:   Mon Jul 7 11:43:06 2025 +0200

    🌐 Add translations for: Hindi

    Currently translated at 52.2% (970 of 1857 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/hi/

commit 67001aafa71aa9dba8c5e1e927c9ce305e14070e
Author: Stephan Paternotte <stephan@paternottes.net>
Date:   Mon Jul 7 07:02:49 2025 +0200

    🌐 Add translations for: Dutch

    Currently translated at 99.9% (1856 of 1857 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/nl/

commit 4d4f5265c00c384a9ba7bb4bf49461279ca536fd
Author: VKing9 <vaibhavrathod2282@gmail.com>
Date:   Fri Jul 4 12:37:46 2025 +0200

    🌐 Add translations for: Hindi

    Currently translated at 40.3% (750 of 1857 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/hi/

commit f3cc8ae33cbb6941434cf71d7d4b4e037aa0a594
Author: VKing9 <vaibhavrathod2282@gmail.com>
Date:   Fri Jul 4 12:19:25 2025 +0200

    🌐 Add translations for: Hindi

    Currently translated at 40.3% (750 of 1857 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/hi/

commit 2d3c0e4a342e1a051d0bf07a580b99a53c12078a
Author: VKing9 <vaibhavrathod2282@gmail.com>
Date:   Fri Jul 4 12:09:45 2025 +0200

    🌐 Add translations for: Hindi

    Currently translated at 40.3% (750 of 1857 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/hi/

commit 4e394b39599e4854ff53374f2ea900d3ea0d49f7
Author: VKing9 <vaibhavrathod2282@gmail.com>
Date:   Fri Jul 4 09:27:07 2025 +0200

    🌐 Add translations for: Hindi

    Currently translated at 40.3% (750 of 1857 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/hi/

commit ebef981a652cba41d988e4f93f685c640ecd5efe
Author: VKing9 <vaibhavrathod2282@gmail.com>
Date:   Fri Jul 4 09:24:00 2025 +0200

    🌐 Add translations for: Hindi

    Currently translated at 40.3% (750 of 1857 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/hi/

commit 6ca42826654fec0fec38631252547323a2226b93
Author: VKing9 <vaibhavrathod2282@gmail.com>
Date:   Fri Jul 4 09:23:29 2025 +0200

    🌐 Add translations for: Hindi

    Currently translated at 40.3% (750 of 1857 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/hi/

commit 5bd8c711b63e967ef2657106e8f2e1498a2596e0
Author: VKing9 <vaibhavrathod2282@gmail.com>
Date:   Fri Jul 4 09:18:58 2025 +0200

    🌐 Add translations for: Hindi

    Currently translated at 40.3% (750 of 1857 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/hi/

commit 6356069174f83939690751f965b641709a7a708e
Author: VKing9 <vaibhavrathod2282@gmail.com>
Date:   Fri Jul 4 08:22:38 2025 +0200

    🌐 Add translations for: Hindi

    Currently translated at 40.3% (750 of 1857 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/hi/

commit a3107d059ec8cf8762cca2e258e09595651c7e4c
Author: VKing9 <vaibhavrathod2282@gmail.com>
Date:   Fri Jul 4 08:09:28 2025 +0200

    🌐 Add translations for: Hindi

    Currently translated at 40.3% (750 of 1857 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/hi/

commit c0f2f43b0669a38c05c1bae783359d70bb53957d
Author: VKing9 <vaibhavrathod2282@gmail.com>
Date:   Fri Jul 4 08:01:49 2025 +0200

    🌐 Add translations for: Hindi

    Currently translated at 27.3% (508 of 1857 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/hi/

commit d725f53e9ea0c22302485fccc3289e8546124570
Author: VKing9 <vaibhavrathod2282@gmail.com>
Date:   Fri Jul 4 07:54:46 2025 +0200

    🌐 Add translations for: Hindi

    Currently translated at 27.3% (508 of 1857 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/hi/

commit 6a50a0db429792a41861281f41b1bafd2bebd64d
Author: VKing9 <vaibhavrathod2282@gmail.com>
Date:   Fri Jul 4 07:53:55 2025 +0200

    🌐 Add translations for: Hindi

    Currently translated at 27.3% (508 of 1857 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/hi/

commit ee382c0d777c65240fdea46222e8249ae131c538
Author: VKing9 <vaibhavrathod2282@gmail.com>
Date:   Thu Jul 3 11:12:22 2025 +0200

    🌐 Add translations for: Hindi

    Currently translated at 27.3% (508 of 1857 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/hi/

commit 181d3083e1e03b7b640545479c666a629c3cdacb
Author: VKing9 <vaibhavrathod2282@gmail.com>
Date:   Thu Jul 3 11:10:31 2025 +0200

    🌐 Add translations for: Hindi

    Currently translated at 27.3% (508 of 1857 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/hi/

commit e898179de59525f259d5ccfae59f4f2fca309f3d
Author: VKing9 <vaibhavrathod2282@gmail.com>
Date:   Thu Jul 3 11:05:22 2025 +0200

    🌐 Add translations for: Hindi

    Currently translated at 27.3% (508 of 1857 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/hi/

commit b16596c7b9c3814478c0149e172329a3aa074dd1
Author: VKing9 <vaibhavrathod2282@gmail.com>
Date:   Thu Jul 3 10:47:59 2025 +0200

    🌐 Add translations for: Hindi

    Currently translated at 27.3% (508 of 1857 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/hi/

commit ae70f146dc1b187d53bcba575e4c365b9077d42a
Author: VKing9 <vaibhavrathod2282@gmail.com>
Date:   Thu Jul 3 09:40:00 2025 +0200

    🌐 Add translations for: Hindi

    Currently translated at 27.3% (508 of 1857 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/hi/

commit 4be87babf5605533eed83cee114cf9171c7985cb
Author: VKing9 <vaibhavrathod2282@gmail.com>
Date:   Thu Jul 3 09:39:23 2025 +0200

    🌐 Add translations for: Hindi

    Currently translated at 27.3% (508 of 1857 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/hi/

commit 1f4261a6e5686224cfedfebf385572d565b573c7
Author: VKing9 <vaibhavrathod2282@gmail.com>
Date:   Thu Jul 3 09:27:26 2025 +0200

    🌐 Add translations for: Hindi

    Currently translated at 27.3% (508 of 1857 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/hi/

commit 50db4f8bc8fbac02ef880add7e5e2330ab06dab0
Author: VKing9 <vaibhavrathod2282@gmail.com>
Date:   Thu Jul 3 09:17:03 2025 +0200

    🌐 Add translations for: Hindi

    Currently translated at 27.3% (508 of 1857 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/hi/

commit d2897327a2aeef26cfc4da4ca63291af7504921e
Author: VKing9 <vaibhavrathod2282@gmail.com>
Date:   Thu Jul 3 09:13:15 2025 +0200

    🌐 Add translations for: Hindi

    Currently translated at 27.3% (508 of 1857 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/hi/

commit 5c7f7e4179ab2e510a6fcabb86f66bd1b2827bd6
Author: VKing9 <vaibhavrathod2282@gmail.com>
Date:   Thu Jul 3 09:09:13 2025 +0200

    🌐 Add translations for: Hindi

    Currently translated at 27.3% (508 of 1857 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/hi/

commit b1d5bbcd0db8a96967cc067bb29f147b2174eb8a
Author: VKing9 <vaibhavrathod2282@gmail.com>
Date:   Thu Jul 3 09:06:52 2025 +0200

    🌐 Add translations for: Hindi

    Currently translated at 27.3% (508 of 1857 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/hi/

commit 2cea4705c972032fc7be9b4fbc047a5422846b13
Author: VKing9 <vaibhavrathod2282@gmail.com>
Date:   Thu Jul 3 09:03:41 2025 +0200

    🌐 Add translations for: Hindi

    Currently translated at 27.3% (508 of 1857 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/hi/

commit 44d01ba7054306027f006fcfca9afad18e1f08ac
Author: VKing9 <vaibhavrathod2282@gmail.com>
Date:   Thu Jul 3 08:59:32 2025 +0200

    🌐 Add translations for: Hindi

    Currently translated at 27.3% (508 of 1857 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/hi/

commit 50a2f98ac6573d47237578dd1bce6d848cc83c78
Author: VKing9 <vaibhavrathod2282@gmail.com>
Date:   Thu Jul 3 08:58:33 2025 +0200

    🌐 Add translations for: Hindi

    Currently translated at 27.3% (508 of 1857 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/hi/

commit cef20ab80a59ca5da6a14be2c6b3b6fc57ea4aab
Author: VKing9 <vaibhavrathod2282@gmail.com>
Date:   Thu Jul 3 08:58:15 2025 +0200

    🌐 Add translations for: Hindi

    Currently translated at 27.3% (508 of 1857 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/hi/

commit 214f9c2bb1e75fe99fe7407e77eb273d437782cd
Author: VKing9 <vaibhavrathod2282@gmail.com>
Date:   Thu Jul 3 08:54:59 2025 +0200

    🌐 Add translations for: Hindi

    Currently translated at 27.3% (508 of 1857 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/hi/

commit 4f9f7a38f811b1948fb9a34fc57f4e9d0ddf1c1b
Author: VKing9 <vaibhavrathod2282@gmail.com>
Date:   Thu Jul 3 08:46:36 2025 +0200

    🌐 Add translations for: Hindi

    Currently translated at 27.3% (508 of 1857 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/hi/

commit be7e929ae70344d6f4349eae569a3012bdfe2e2a
Author: VKing9 <vaibhavrathod2282@gmail.com>
Date:   Thu Jul 3 08:12:41 2025 +0200

    🌐 Add translations for: Hindi

    Currently translated at 27.3% (508 of 1857 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/hi/

commit 4db59803d86f78a35538b089f122291a2577716d
Author: VKing9 <vaibhavrathod2282@gmail.com>
Date:   Thu Jul 3 08:06:20 2025 +0200

    🌐 Add translations for: Hindi

    Currently translated at 27.3% (508 of 1857 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/hi/

commit 14aad9500e7c901573effbb5fdff2a8a0bcca036
Author: VKing9 <vaibhavrathod2282@gmail.com>
Date:   Thu Jul 3 08:05:29 2025 +0200

    🌐 Add translations for: Hindi

    Currently translated at 27.3% (508 of 1857 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/hi/

commit 85014b458caa951d798e45000b02f25b9fdad271
Author: VKing9 <vaibhavrathod2282@gmail.com>
Date:   Thu Jul 3 08:02:38 2025 +0200

    🌐 Add translations for: Hindi

    Currently translated at 27.3% (508 of 1857 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/hi/

commit 002a623606025367f33870c8074e2ea486315b5d
Author: VKing9 <vaibhavrathod2282@gmail.com>
Date:   Thu Jul 3 08:01:16 2025 +0200

    🌐 Add translations for: Hindi

    Currently translated at 27.3% (508 of 1857 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/hi/

commit b72efd33dfeadefcb9f63e68e59cb16fb6366483
Author: VKing9 <vaibhavrathod2282@gmail.com>
Date:   Thu Jul 3 07:57:48 2025 +0200

    🌐 Add translations for: Hindi

    Currently translated at 27.3% (508 of 1857 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/hi/

commit ab75e51c330561eb132eef8354908fcbd8b3ec09
Author: VKing9 <vaibhavrathod2282@gmail.com>
Date:   Thu Jul 3 07:57:18 2025 +0200

    🌐 Add translations for: Hindi

    Currently translated at 27.3% (508 of 1857 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/hi/

commit 2bae66951b930e872c06443b78c36c225c564438
Author: VKing9 <vaibhavrathod2282@gmail.com>
Date:   Thu Jul 3 07:45:41 2025 +0200

    🌐 Add translations for: Hindi

    Currently translated at 27.3% (508 of 1857 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/hi/

commit 1151123aeabfcad65410bd44d6e04685d21ba5ed
Author: VKing9 <vaibhavrathod2282@gmail.com>
Date:   Thu Jul 3 07:40:17 2025 +0200

    🌐 Add translations for: Hindi

    Currently translated at 27.3% (508 of 1857 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/hi/

commit 97a4f34e599d4f1ac6da3029cab3d993ee3ab4da
Author: VKing9 <vaibhavrathod2282@gmail.com>
Date:   Thu Jul 3 07:35:28 2025 +0200

    🌐 Add translations for: Hindi

    Currently translated at 27.3% (508 of 1857 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/hi/

commit a2e1ec123bce716ea0bcc2542809398ec3f65cb1
Author: VKing9 <vaibhavrathod2282@gmail.com>
Date:   Thu Jul 3 07:30:19 2025 +0200

    🌐 Add translations for: Hindi

    Currently translated at 27.3% (508 of 1857 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/hi/

commit 9e72ab6771857ec0814cd0fa22dac6bf1470901a
Author: VKing9 <vaibhavrathod2282@gmail.com>
Date:   Thu Jul 3 07:28:38 2025 +0200

    🌐 Add translations for: Hindi

    Currently translated at 27.3% (508 of 1857 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/hi/

commit 87849347286683544dba68e9a1cbdc9fc06b7ff3
Author: VKing9 <vaibhavrathod2282@gmail.com>
Date:   Thu Jul 3 07:22:13 2025 +0200

    🌐 Add translations for: Hindi

    Currently translated at 27.3% (508 of 1857 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/hi/

commit 1e359566b91bf23270a34ed398b058a635a7de7b
Author: Denys Kisil <ossenjoyer@proton.me>
Date:   Mon Jun 30 14:35:56 2025 +0200

    🌐 Add translations for: Ukrainian (ukr_UA)

    Currently translated at 99.9% (1856 of 1857 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/ukr_UA/

commit 312ee3f7036615fce7f88b880accce71605470dc
Author: Denys Kisil <ossenjoyer@proton.me>
Date:   Mon Jun 30 14:31:42 2025 +0200

    🌐 Add translations for: Ukrainian (ukr_UA)

    Currently translated at 99.9% (1856 of 1857 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/ukr_UA/

commit 7ca4e07d12e419e11b2d0079acb8133beac1315a
Author: Denys Kisil <ossenjoyer@proton.me>
Date:   Mon Jun 30 14:29:26 2025 +0200

    🌐 Add translations for: Ukrainian (ukr_UA)

    Currently translated at 99.9% (1856 of 1857 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/ukr_UA/

commit 3e1db432d2fef95542ea9d0d5e4c164ab2190e11
Author: Denys Kisil <ossenjoyer@proton.me>
Date:   Mon Jun 30 14:22:29 2025 +0200

    🌐 Add translations for: Ukrainian (ukr_UA)

    Currently translated at 99.9% (1856 of 1857 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/ukr_UA/

commit f6121a315de283a8a0b2e163aeaff48851a42a25
Author: Denys Kisil <ossenjoyer@proton.me>
Date:   Mon Jun 30 14:19:07 2025 +0200

    🌐 Add translations for: Ukrainian (ukr_UA)

    Currently translated at 99.9% (1856 of 1857 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/ukr_UA/

commit e1720aae76015fba1754575dc743a3021040e04a
Author: Denys Kisil <ossenjoyer@proton.me>
Date:   Mon Jun 30 14:15:08 2025 +0200

    🌐 Add translations for: Ukrainian (ukr_UA)

    Currently translated at 99.9% (1856 of 1857 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/ukr_UA/

commit a399deae487af3db9127adc89aa39bd813296ecf
Author: Corentin Noël <tintou@noel.tf>
Date:   Fri Jun 27 14:26:07 2025 +0200

    🌐 Add translations for: French

    Currently translated at 99.8% (1855 of 1857 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/fr/

commit 1c81b4c9b3bac3bc210b16ba9691cc5e2917c896
Author: Ingrid Pigueron <ingridp.uxr@gmail.com>
Date:   Thu Jun 26 11:31:04 2025 +0200

    🌐 Add translations for: French

    Currently translated at 99.8% (1854 of 1857 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/fr/

commit 0c756f50747fd9a0031e398d6bba4903d402519a
Author: Stas Haas <stas@girafic.de>
Date:   Sun Jun 22 11:35:49 2025 +0200

    🌐 Add translations for: German

    Currently translated at 92.6% (1720 of 1857 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/de/

commit eaa9d3e2bccf4f2fb9aa9f23fee530c7efe5e720
Author: al0cam <benjaminsikac@gmail.com>
Date:   Thu Jun 19 14:48:06 2025 +0200

    🌐 Add translations for: Croatian

    Currently translated at 87.4% (1624 of 1857 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/hr/

commit 8fc4f74bf8e8e754f780a155c2eb8f6d9c51f3b4
Author: Stas Haas <stas@girafic.de>
Date:   Tue Jun 17 09:06:30 2025 +0200

    🌐 Add translations for: German

    Currently translated at 91.9% (1708 of 1857 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/de/

commit 4d396ef7f7b1be2ec5f57d671717ae1dbb9419ab
Author: Denys Kisil <ossenjoyer@proton.me>
Date:   Mon Jun 16 21:34:47 2025 +0200

    🌐 Add translations for: Ukrainian (ukr_UA)

    Currently translated at 99.9% (1856 of 1857 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/ukr_UA/

commit 28dcfb52785fecca69a4bf22ac7222b330d29f9f
Author: al0cam <benjaminsikac@gmail.com>
Date:   Mon Jun 16 07:54:05 2025 +0200

    🌐 Add translations for: Croatian

    Currently translated at 87.2% (1620 of 1857 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/hr/

commit 680c9a1a0ebe3b323cf1bc7d3f92d7e0bda53c7a
Author: Yaron Shahrabani <sh.yaron@gmail.com>
Date:   Mon Jun 16 18:51:01 2025 +0200

    🌐 Add translations for: Hebrew

    Currently translated at 99.9% (1856 of 1857 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/he/

commit 6e3f6ed276b74df94a64af294ea4ca80ac1c43f6
Author: Ingrid Pigueron <ingridp.uxr@gmail.com>
Date:   Sat Jun 14 12:53:48 2025 +0200

    🌐 Add translations for: French

    Currently translated at 99.8% (1854 of 1857 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/fr/

commit feabe2414490e29db3fbabf20a00d890df9907d8
Author: Nicola Bortoletto <nicola.bortoletto@live.com>
Date:   Fri Jun 13 08:26:35 2025 +0200

    🌐 Add translations for: Italian

    Currently translated at 99.9% (1856 of 1857 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/it/

commit a3b49ee9510b53ae5b010bfbcfb5022a79f6fe1b
Author: Yaron Shahrabani <sh.yaron@gmail.com>
Date:   Thu Jun 12 08:17:05 2025 +0200

    🌐 Add translations for: Hebrew

    Currently translated at 97.0% (1803 of 1857 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/he/

commit c775173ec6f5d22964e9b79cc2a80e3cbd08fccb
Author: Stas Haas <stas@girafic.de>
Date:   Thu Jun 12 10:56:20 2025 +0200

    🌐 Add translations for: German

    Currently translated at 90.7% (1686 of 1857 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/de/

commit 249051c087fd679f7d5a5c604a65c1eb6fb377d0
Author: Yaron Shahrabani <sh.yaron@gmail.com>
Date:   Wed Jun 11 11:24:21 2025 +0200

    🌐 Add translations for: Hebrew

    Currently translated at 96.9% (1800 of 1857 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/he/

commit d33693bf9f8aa419b7688deed03a26926d7b5338
Author: Stas Haas <stas@girafic.de>
Date:   Tue Jun 10 15:05:19 2025 +0200

    🌐 Add translations for: German

    Currently translated at 90.4% (1680 of 1857 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/de/

commit c3d4852c7f61ac398aa505eb0f1b3e0a5e6a6f49
Author: Unreal Vision <unrealvisionyt@gmail.com>
Date:   Tue Jun 10 14:59:59 2025 +0200

    🌐 Add translations for: French

    Currently translated at 99.7% (1853 of 1857 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/fr/

commit 16e6fadb8dd1c2285c64fde7079d6b33c8a7f6a6
Author: Rudra Harsh <harshrudra020@gmail.com>
Date:   Mon Jun 9 15:46:43 2025 +0200

    🌐 Add translations for: Hindi

    Currently translated at 1.2% (23 of 1857 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/hi/

commit 7653bc6060bc0f6ad0664549cc46a15d7e72ccd7
Author: Stephan Paternotte <stephan@paternottes.net>
Date:   Tue Jun 10 05:46:17 2025 +0200

    🌐 Add translations for: Dutch

    Currently translated at 99.7% (1853 of 1857 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/nl/

commit 0f65e960b1de543b9133e6742a732e46967d1f83
Author: Edgars Andersons <Edgars+Weblate@gaitenis.id.lv>
Date:   Tue Jun 10 11:51:03 2025 +0200

    🌐 Add translations for: Latvian

    Currently translated at 99.9% (1856 of 1857 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/lv/

commit 05f12ae1bf59986cdc8f5e98ac14c33d6c0e79e2
Author: Nicola Bortoletto <nicola.bortoletto@live.com>
Date:   Mon Jun 9 23:14:58 2025 +0200

    🌐 Add translations for: Italian

    Currently translated at 99.9% (1856 of 1857 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/it/

commit 2e16f175f57b757a5de4f387caf58331ec5dc822
Author: Yaron Shahrabani <sh.yaron@gmail.com>
Date:   Mon Jun 9 19:01:14 2025 +0200

    🌐 Add translations for: Hebrew

    Currently translated at 96.6% (1794 of 1857 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/he/

commit a202b8b663c3a32af7e21f662907d8365fb587c5
Author: Stas Haas <stas@girafic.de>
Date:   Tue Jun 10 14:57:32 2025 +0200

    🌐 Add translations for: German

    Currently translated at 90.0% (1672 of 1857 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/de/

commit ffe9682df9a5a65dc1f582844e566cf3eff32a08
Author: Unreal Vision <unrealvisionyt@gmail.com>
Date:   Tue Jun 10 14:56:54 2025 +0200

    🌐 Add translations for: French

    Currently translated at 98.7% (1833 of 1857 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/fr/

commit f8f4abe8007491f5392bfb1ab5cbfba618e22700
Author: Ingrid Pigueron <ingridp.uxr@gmail.com>
Date:   Mon Jun 9 19:44:09 2025 +0200

    🌐 Add translations for: French

    Currently translated at 98.7% (1833 of 1857 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/fr/

commit bb6fee5a9ba86eb823c22fae22a49afdcc36c659
Author: Rudra Harsh <harshrudra020@gmail.com>
Date:   Mon Jun 9 15:21:41 2025 +0200

    🌐 Add translations for: Hindi

    Currently translated at 0.5% (11 of 1857 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/hi/

commit 55b4c5c07827d4b6eda2ffcc71caca81e6f36534
Author: Madalena Melo <madalena.melo@kaleidos.net>
Date:   Mon Jun 9 11:52:50 2025 +0200

    🌐  Added translation for: Hindi
2025-08-11 09:21:55 +02:00
Andrey Antukh
58bd7c6bd4 Import translations from weblate
commit 2239711f15f62c29cb7eb1981874ae81019d4b3e
Author: Stas Haas <stas@girafic.de>
Date:   Tue Jul 29 07:59:24 2025 +0200

    🌐 Add translations for: German

    Currently translated at 92.6% (1721 of 1857 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/de/

commit 836068ca8cbc3e72a96bfa4be1d239ad2d516d32
Author: VKing9 <vaibhavrathod2282@gmail.com>
Date:   Thu Jul 10 08:41:57 2025 +0200

    🌐 Add translations for: Hindi

    Currently translated at 100.0% (1857 of 1857 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/hi/

commit 1c2958825198a6194bf99db5cc50a3a386df98f6
Author: VKing9 <vaibhavrathod2282@gmail.com>
Date:   Thu Jul 10 07:58:53 2025 +0200

    🌐 Add translations for: Hindi

    Currently translated at 100.0% (1857 of 1857 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/hi/

commit c0f884b12350225c897e0f0843e09a02ea1c6639
Author: VKing9 <vaibhavrathod2282@gmail.com>
Date:   Thu Jul 10 07:56:18 2025 +0200

    🌐 Add translations for: Hindi

    Currently translated at 100.0% (1857 of 1857 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/hi/

commit 4692c0019c9d09a1019b6605d748d8f3144edf68
Author: VKing9 <vaibhavrathod2282@gmail.com>
Date:   Thu Jul 10 07:51:22 2025 +0200

    🌐 Add translations for: Hindi

    Currently translated at 100.0% (1857 of 1857 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/hi/

commit 6f74a30b90e39d1cb998dd7a37931d1a55a1bbfb
Author: VKing9 <vaibhavrathod2282@gmail.com>
Date:   Thu Jul 10 07:44:43 2025 +0200

    🌐 Add translations for: Hindi

    Currently translated at 100.0% (1857 of 1857 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/hi/

commit e657464742dc9f151313d4450025fd3ac57a6732
Author: VKing9 <vaibhavrathod2282@gmail.com>
Date:   Thu Jul 10 07:39:28 2025 +0200

    🌐 Add translations for: Hindi

    Currently translated at 100.0% (1857 of 1857 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/hi/

commit a41e8ed7865083123703710fbdacaa5ee9e506fa
Author: VKing9 <vaibhavrathod2282@gmail.com>
Date:   Thu Jul 10 07:34:59 2025 +0200

    🌐 Add translations for: Hindi

    Currently translated at 100.0% (1857 of 1857 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/hi/

commit 4d27f8cb303b27f9ddba30d2a2fbc2163c920694
Author: VKing9 <vaibhavrathod2282@gmail.com>
Date:   Thu Jul 10 07:27:34 2025 +0200

    🌐 Add translations for: Hindi

    Currently translated at 100.0% (1857 of 1857 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/hi/

commit b5369fa2380beaa190265df4847c81af713bf348
Author: VKing9 <vaibhavrathod2282@gmail.com>
Date:   Thu Jul 10 07:03:29 2025 +0200

    🌐 Add translations for: Hindi

    Currently translated at 100.0% (1857 of 1857 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/hi/

commit 4d639b62f29e469abce6f463208079e73f70b146
Author: VKing9 <vaibhavrathod2282@gmail.com>
Date:   Thu Jul 10 07:02:50 2025 +0200

    🌐 Add translations for: Hindi

    Currently translated at 100.0% (1857 of 1857 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/hi/

commit ddb5fe44ee8e12f6592b4cbf3f0c9f5a1be3f695
Author: VKing9 <vaibhavrathod2282@gmail.com>
Date:   Thu Jul 10 06:49:11 2025 +0200

    🌐 Add translations for: Hindi

    Currently translated at 100.0% (1857 of 1857 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/hi/

commit e702b556e2ae798e22cc966f6eff421cbc6fda81
Author: VKing9 <vaibhavrathod2282@gmail.com>
Date:   Thu Jul 10 06:42:32 2025 +0200

    🌐 Add translations for: Hindi

    Currently translated at 100.0% (1857 of 1857 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/hi/

commit f74f8f96e5af79900df3508ee5551d8f85e63558
Author: VKing9 <vaibhavrathod2282@gmail.com>
Date:   Thu Jul 10 06:40:51 2025 +0200

    🌐 Add translations for: Hindi

    Currently translated at 100.0% (1857 of 1857 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/hi/

commit f7db30ac4d1855b646e0ece454a2153aaaaeb309
Author: VKing9 <vaibhavrathod2282@gmail.com>
Date:   Thu Jul 10 06:33:44 2025 +0200

    🌐 Add translations for: Hindi

    Currently translated at 100.0% (1857 of 1857 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/hi/

commit 07fd2353f670b981601f5d51aca3f013483af9a6
Author: VKing9 <vaibhavrathod2282@gmail.com>
Date:   Wed Jul 9 09:29:04 2025 +0200

    🌐 Add translations for: Hindi

    Currently translated at 82.7% (1536 of 1857 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/hi/

commit a8b578cbaa69c6bd1c8319b43a96799267eae98d
Author: VKing9 <vaibhavrathod2282@gmail.com>
Date:   Wed Jul 9 09:25:49 2025 +0200

    🌐 Add translations for: Hindi

    Currently translated at 82.7% (1536 of 1857 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/hi/

commit 12a9927f7b5b257d2909be6c73af72a58ddfb8b6
Author: VKing9 <vaibhavrathod2282@gmail.com>
Date:   Wed Jul 9 09:24:52 2025 +0200

    🌐 Add translations for: Hindi

    Currently translated at 82.7% (1536 of 1857 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/hi/

commit 2314eab73fa7fcb7b479c16dfb0551a188a7c46e
Author: VKing9 <vaibhavrathod2282@gmail.com>
Date:   Wed Jul 9 09:23:25 2025 +0200

    🌐 Add translations for: Hindi

    Currently translated at 82.7% (1536 of 1857 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/hi/

commit 88b721c600ff72a2e8bdc4c301f0745a3174fbd5
Author: VKing9 <vaibhavrathod2282@gmail.com>
Date:   Wed Jul 9 09:17:17 2025 +0200

    🌐 Add translations for: Hindi

    Currently translated at 82.7% (1536 of 1857 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/hi/

commit 14b4124e4cdf4ced296d234b4dbd76afa5a6166c
Author: VKing9 <vaibhavrathod2282@gmail.com>
Date:   Wed Jul 9 09:12:41 2025 +0200

    🌐 Add translations for: Hindi

    Currently translated at 82.7% (1536 of 1857 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/hi/

commit ccaa8da28c65d0256027f2fbf3e556797ef901fb
Author: VKing9 <vaibhavrathod2282@gmail.com>
Date:   Wed Jul 9 08:16:45 2025 +0200

    🌐 Add translations for: Hindi

    Currently translated at 82.7% (1536 of 1857 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/hi/

commit e517e2f0152383549a46ac72b4ebc94752dbdbf3
Author: VKing9 <vaibhavrathod2282@gmail.com>
Date:   Wed Jul 9 08:12:19 2025 +0200

    🌐 Add translations for: Hindi

    Currently translated at 82.7% (1536 of 1857 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/hi/

commit cb359962bc2aff200c501d8466db1097e93d074e
Author: VKing9 <vaibhavrathod2282@gmail.com>
Date:   Wed Jul 9 08:03:00 2025 +0200

    🌐 Add translations for: Hindi

    Currently translated at 82.7% (1536 of 1857 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/hi/

commit 71205252a4f4aadeed2cf0b6da41722a6d2e38a8
Author: VKing9 <vaibhavrathod2282@gmail.com>
Date:   Wed Jul 9 07:51:41 2025 +0200

    🌐 Add translations for: Hindi

    Currently translated at 82.7% (1536 of 1857 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/hi/

commit fe56a9fdd177c4ca624b9dbb88bfa30dc31a92f4
Author: VKing9 <vaibhavrathod2282@gmail.com>
Date:   Wed Jul 9 07:48:33 2025 +0200

    🌐 Add translations for: Hindi

    Currently translated at 82.7% (1536 of 1857 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/hi/

commit 3f2d9bf68f466c21557e045fcce7aab76441d9da
Author: VKing9 <vaibhavrathod2282@gmail.com>
Date:   Wed Jul 9 07:22:29 2025 +0200

    🌐 Add translations for: Hindi

    Currently translated at 82.7% (1536 of 1857 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/hi/

commit e41af1831d5f749e341ce163f520ce2dff5fc7de
Author: VKing9 <vaibhavrathod2282@gmail.com>
Date:   Wed Jul 9 07:21:22 2025 +0200

    🌐 Add translations for: Hindi

    Currently translated at 82.7% (1536 of 1857 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/hi/

commit bb8c9129c9c3cff69ce59b7bfe86560bba977e09
Author: VKing9 <vaibhavrathod2282@gmail.com>
Date:   Wed Jul 9 07:20:40 2025 +0200

    🌐 Add translations for: Hindi

    Currently translated at 82.7% (1536 of 1857 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/hi/

commit efd5849fc1e6e76fdf91b21b0a69be2b7e89cbcf
Author: VKing9 <vaibhavrathod2282@gmail.com>
Date:   Wed Jul 9 07:18:52 2025 +0200

    🌐 Add translations for: Hindi

    Currently translated at 82.7% (1536 of 1857 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/hi/

commit 0b2403b8bd2682e4a2cfdfe879b34c83ed5a6913
Author: VKing9 <vaibhavrathod2282@gmail.com>
Date:   Wed Jul 9 07:13:43 2025 +0200

    🌐 Add translations for: Hindi

    Currently translated at 82.7% (1536 of 1857 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/hi/

commit 8412b71915047cf0d436279b89f93bc0c77f1c20
Author: VKing9 <vaibhavrathod2282@gmail.com>
Date:   Wed Jul 9 07:03:41 2025 +0200

    🌐 Add translations for: Hindi

    Currently translated at 82.7% (1536 of 1857 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/hi/

commit fe49d3ccd5697ef830bb71086557f8a249c3ed6e
Author: VKing9 <vaibhavrathod2282@gmail.com>
Date:   Wed Jul 9 07:02:20 2025 +0200

    🌐 Add translations for: Hindi

    Currently translated at 82.7% (1536 of 1857 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/hi/

commit 48f39509b7a93e501115c3d4cc5d8bb76361b197
Author: VKing9 <vaibhavrathod2282@gmail.com>
Date:   Wed Jul 9 07:00:51 2025 +0200

    🌐 Add translations for: Hindi

    Currently translated at 82.7% (1536 of 1857 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/hi/

commit 634df69814a209dc830ffebe471be4e821b849fa
Author: VKing9 <vaibhavrathod2282@gmail.com>
Date:   Wed Jul 9 06:57:19 2025 +0200

    🌐 Add translations for: Hindi

    Currently translated at 82.7% (1536 of 1857 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/hi/

commit f2ddf8266af3f4d56351883f5ad845327834fe8b
Author: VKing9 <vaibhavrathod2282@gmail.com>
Date:   Wed Jul 9 06:50:16 2025 +0200

    🌐 Add translations for: Hindi

    Currently translated at 82.7% (1536 of 1857 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/hi/

commit 27d24e6438d34ecfea68b87d0322d51b05cfdb68
Author: VKing9 <vaibhavrathod2282@gmail.com>
Date:   Tue Jul 8 09:49:01 2025 +0200

    🌐 Add translations for: Hindi

    Currently translated at 82.7% (1536 of 1857 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/hi/

commit bc0afe1b8053bb0258b7b18905714d3cc070c55f
Author: VKing9 <vaibhavrathod2282@gmail.com>
Date:   Tue Jul 8 09:40:07 2025 +0200

    🌐 Add translations for: Hindi

    Currently translated at 82.7% (1536 of 1857 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/hi/

commit 4f6e0bd6778e8105d248f298319b9771c99347a1
Author: VKing9 <vaibhavrathod2282@gmail.com>
Date:   Tue Jul 8 09:36:54 2025 +0200

    🌐 Add translations for: Hindi

    Currently translated at 82.7% (1536 of 1857 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/hi/

commit faae4f0c18ee77bd2330936448823f3caa7df881
Author: VKing9 <vaibhavrathod2282@gmail.com>
Date:   Tue Jul 8 09:35:38 2025 +0200

    🌐 Add translations for: Hindi

    Currently translated at 82.7% (1536 of 1857 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/hi/

commit 5e43671edccc5786f46afba4b1e5c32de39d05a6
Author: VKing9 <vaibhavrathod2282@gmail.com>
Date:   Tue Jul 8 09:29:10 2025 +0200

    🌐 Add translations for: Hindi

    Currently translated at 82.7% (1536 of 1857 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/hi/

commit 6aec58217b608f125e327d9b7048fa163984b8b3
Author: VKing9 <vaibhavrathod2282@gmail.com>
Date:   Tue Jul 8 09:24:10 2025 +0200

    🌐 Add translations for: Hindi

    Currently translated at 82.7% (1536 of 1857 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/hi/

commit a20b28bfe96618e507259b6294f6791bc30e1ed3
Author: VKing9 <vaibhavrathod2282@gmail.com>
Date:   Tue Jul 8 09:22:34 2025 +0200

    🌐 Add translations for: Hindi

    Currently translated at 82.7% (1536 of 1857 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/hi/

commit 59ee55aa262c7248b9f85f2fdd5b217132b71975
Author: VKing9 <vaibhavrathod2282@gmail.com>
Date:   Tue Jul 8 09:21:42 2025 +0200

    🌐 Add translations for: Hindi

    Currently translated at 82.7% (1536 of 1857 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/hi/

commit 3825a6a464c6015f383e90be9155c81da8a1f2c1
Author: VKing9 <vaibhavrathod2282@gmail.com>
Date:   Tue Jul 8 09:17:33 2025 +0200

    🌐 Add translations for: Hindi

    Currently translated at 82.7% (1536 of 1857 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/hi/

commit 7fe83a8f347a65e101ec1e01ef30d8791057718f
Author: VKing9 <vaibhavrathod2282@gmail.com>
Date:   Tue Jul 8 07:39:05 2025 +0200

    🌐 Add translations for: Hindi

    Currently translated at 52.2% (970 of 1857 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/hi/

commit 7eab18e15ec35f4e7a4eb33fbec17c8fd61c5a65
Author: VKing9 <vaibhavrathod2282@gmail.com>
Date:   Tue Jul 8 07:28:07 2025 +0200

    🌐 Add translations for: Hindi

    Currently translated at 52.2% (970 of 1857 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/hi/

commit 66a42acd37df0eecfa409fd460b279565b7c7292
Author: VKing9 <vaibhavrathod2282@gmail.com>
Date:   Tue Jul 8 07:23:43 2025 +0200

    🌐 Add translations for: Hindi

    Currently translated at 52.2% (970 of 1857 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/hi/

commit 9eb17f7172141e366eb338b128bf2229deeb1246
Author: VKing9 <vaibhavrathod2282@gmail.com>
Date:   Tue Jul 8 07:23:08 2025 +0200

    🌐 Add translations for: Hindi

    Currently translated at 52.2% (970 of 1857 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/hi/

commit 2626d45eb96da5e47a5b90c5ba4aa13362b8eea2
Author: VKing9 <vaibhavrathod2282@gmail.com>
Date:   Mon Jul 7 11:56:38 2025 +0200

    🌐 Add translations for: Hindi

    Currently translated at 52.2% (970 of 1857 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/hi/

commit f3719edaa121a9c880cf5f670ed18bb6f1806378
Author: VKing9 <vaibhavrathod2282@gmail.com>
Date:   Mon Jul 7 11:43:06 2025 +0200

    🌐 Add translations for: Hindi

    Currently translated at 52.2% (970 of 1857 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/hi/

commit 67001aafa71aa9dba8c5e1e927c9ce305e14070e
Author: Stephan Paternotte <stephan@paternottes.net>
Date:   Mon Jul 7 07:02:49 2025 +0200

    🌐 Add translations for: Dutch

    Currently translated at 99.9% (1856 of 1857 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/nl/

commit 4d4f5265c00c384a9ba7bb4bf49461279ca536fd
Author: VKing9 <vaibhavrathod2282@gmail.com>
Date:   Fri Jul 4 12:37:46 2025 +0200

    🌐 Add translations for: Hindi

    Currently translated at 40.3% (750 of 1857 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/hi/

commit f3cc8ae33cbb6941434cf71d7d4b4e037aa0a594
Author: VKing9 <vaibhavrathod2282@gmail.com>
Date:   Fri Jul 4 12:19:25 2025 +0200

    🌐 Add translations for: Hindi

    Currently translated at 40.3% (750 of 1857 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/hi/

commit 2d3c0e4a342e1a051d0bf07a580b99a53c12078a
Author: VKing9 <vaibhavrathod2282@gmail.com>
Date:   Fri Jul 4 12:09:45 2025 +0200

    🌐 Add translations for: Hindi

    Currently translated at 40.3% (750 of 1857 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/hi/

commit 4e394b39599e4854ff53374f2ea900d3ea0d49f7
Author: VKing9 <vaibhavrathod2282@gmail.com>
Date:   Fri Jul 4 09:27:07 2025 +0200

    🌐 Add translations for: Hindi

    Currently translated at 40.3% (750 of 1857 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/hi/

commit ebef981a652cba41d988e4f93f685c640ecd5efe
Author: VKing9 <vaibhavrathod2282@gmail.com>
Date:   Fri Jul 4 09:24:00 2025 +0200

    🌐 Add translations for: Hindi

    Currently translated at 40.3% (750 of 1857 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/hi/

commit 6ca42826654fec0fec38631252547323a2226b93
Author: VKing9 <vaibhavrathod2282@gmail.com>
Date:   Fri Jul 4 09:23:29 2025 +0200

    🌐 Add translations for: Hindi

    Currently translated at 40.3% (750 of 1857 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/hi/

commit 5bd8c711b63e967ef2657106e8f2e1498a2596e0
Author: VKing9 <vaibhavrathod2282@gmail.com>
Date:   Fri Jul 4 09:18:58 2025 +0200

    🌐 Add translations for: Hindi

    Currently translated at 40.3% (750 of 1857 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/hi/

commit 6356069174f83939690751f965b641709a7a708e
Author: VKing9 <vaibhavrathod2282@gmail.com>
Date:   Fri Jul 4 08:22:38 2025 +0200

    🌐 Add translations for: Hindi

    Currently translated at 40.3% (750 of 1857 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/hi/

commit a3107d059ec8cf8762cca2e258e09595651c7e4c
Author: VKing9 <vaibhavrathod2282@gmail.com>
Date:   Fri Jul 4 08:09:28 2025 +0200

    🌐 Add translations for: Hindi

    Currently translated at 40.3% (750 of 1857 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/hi/

commit c0f2f43b0669a38c05c1bae783359d70bb53957d
Author: VKing9 <vaibhavrathod2282@gmail.com>
Date:   Fri Jul 4 08:01:49 2025 +0200

    🌐 Add translations for: Hindi

    Currently translated at 27.3% (508 of 1857 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/hi/

commit d725f53e9ea0c22302485fccc3289e8546124570
Author: VKing9 <vaibhavrathod2282@gmail.com>
Date:   Fri Jul 4 07:54:46 2025 +0200

    🌐 Add translations for: Hindi

    Currently translated at 27.3% (508 of 1857 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/hi/

commit 6a50a0db429792a41861281f41b1bafd2bebd64d
Author: VKing9 <vaibhavrathod2282@gmail.com>
Date:   Fri Jul 4 07:53:55 2025 +0200

    🌐 Add translations for: Hindi

    Currently translated at 27.3% (508 of 1857 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/hi/

commit ee382c0d777c65240fdea46222e8249ae131c538
Author: VKing9 <vaibhavrathod2282@gmail.com>
Date:   Thu Jul 3 11:12:22 2025 +0200

    🌐 Add translations for: Hindi

    Currently translated at 27.3% (508 of 1857 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/hi/

commit 181d3083e1e03b7b640545479c666a629c3cdacb
Author: VKing9 <vaibhavrathod2282@gmail.com>
Date:   Thu Jul 3 11:10:31 2025 +0200

    🌐 Add translations for: Hindi

    Currently translated at 27.3% (508 of 1857 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/hi/

commit e898179de59525f259d5ccfae59f4f2fca309f3d
Author: VKing9 <vaibhavrathod2282@gmail.com>
Date:   Thu Jul 3 11:05:22 2025 +0200

    🌐 Add translations for: Hindi

    Currently translated at 27.3% (508 of 1857 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/hi/

commit b16596c7b9c3814478c0149e172329a3aa074dd1
Author: VKing9 <vaibhavrathod2282@gmail.com>
Date:   Thu Jul 3 10:47:59 2025 +0200

    🌐 Add translations for: Hindi

    Currently translated at 27.3% (508 of 1857 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/hi/

commit ae70f146dc1b187d53bcba575e4c365b9077d42a
Author: VKing9 <vaibhavrathod2282@gmail.com>
Date:   Thu Jul 3 09:40:00 2025 +0200

    🌐 Add translations for: Hindi

    Currently translated at 27.3% (508 of 1857 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/hi/

commit 4be87babf5605533eed83cee114cf9171c7985cb
Author: VKing9 <vaibhavrathod2282@gmail.com>
Date:   Thu Jul 3 09:39:23 2025 +0200

    🌐 Add translations for: Hindi

    Currently translated at 27.3% (508 of 1857 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/hi/

commit 1f4261a6e5686224cfedfebf385572d565b573c7
Author: VKing9 <vaibhavrathod2282@gmail.com>
Date:   Thu Jul 3 09:27:26 2025 +0200

    🌐 Add translations for: Hindi

    Currently translated at 27.3% (508 of 1857 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/hi/

commit 50db4f8bc8fbac02ef880add7e5e2330ab06dab0
Author: VKing9 <vaibhavrathod2282@gmail.com>
Date:   Thu Jul 3 09:17:03 2025 +0200

    🌐 Add translations for: Hindi

    Currently translated at 27.3% (508 of 1857 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/hi/

commit d2897327a2aeef26cfc4da4ca63291af7504921e
Author: VKing9 <vaibhavrathod2282@gmail.com>
Date:   Thu Jul 3 09:13:15 2025 +0200

    🌐 Add translations for: Hindi

    Currently translated at 27.3% (508 of 1857 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/hi/

commit 5c7f7e4179ab2e510a6fcabb86f66bd1b2827bd6
Author: VKing9 <vaibhavrathod2282@gmail.com>
Date:   Thu Jul 3 09:09:13 2025 +0200

    🌐 Add translations for: Hindi

    Currently translated at 27.3% (508 of 1857 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/hi/

commit b1d5bbcd0db8a96967cc067bb29f147b2174eb8a
Author: VKing9 <vaibhavrathod2282@gmail.com>
Date:   Thu Jul 3 09:06:52 2025 +0200

    🌐 Add translations for: Hindi

    Currently translated at 27.3% (508 of 1857 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/hi/

commit 2cea4705c972032fc7be9b4fbc047a5422846b13
Author: VKing9 <vaibhavrathod2282@gmail.com>
Date:   Thu Jul 3 09:03:41 2025 +0200

    🌐 Add translations for: Hindi

    Currently translated at 27.3% (508 of 1857 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/hi/

commit 44d01ba7054306027f006fcfca9afad18e1f08ac
Author: VKing9 <vaibhavrathod2282@gmail.com>
Date:   Thu Jul 3 08:59:32 2025 +0200

    🌐 Add translations for: Hindi

    Currently translated at 27.3% (508 of 1857 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/hi/

commit 50a2f98ac6573d47237578dd1bce6d848cc83c78
Author: VKing9 <vaibhavrathod2282@gmail.com>
Date:   Thu Jul 3 08:58:33 2025 +0200

    🌐 Add translations for: Hindi

    Currently translated at 27.3% (508 of 1857 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/hi/

commit cef20ab80a59ca5da6a14be2c6b3b6fc57ea4aab
Author: VKing9 <vaibhavrathod2282@gmail.com>
Date:   Thu Jul 3 08:58:15 2025 +0200

    🌐 Add translations for: Hindi

    Currently translated at 27.3% (508 of 1857 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/hi/

commit 214f9c2bb1e75fe99fe7407e77eb273d437782cd
Author: VKing9 <vaibhavrathod2282@gmail.com>
Date:   Thu Jul 3 08:54:59 2025 +0200

    🌐 Add translations for: Hindi

    Currently translated at 27.3% (508 of 1857 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/hi/

commit 4f9f7a38f811b1948fb9a34fc57f4e9d0ddf1c1b
Author: VKing9 <vaibhavrathod2282@gmail.com>
Date:   Thu Jul 3 08:46:36 2025 +0200

    🌐 Add translations for: Hindi

    Currently translated at 27.3% (508 of 1857 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/hi/

commit be7e929ae70344d6f4349eae569a3012bdfe2e2a
Author: VKing9 <vaibhavrathod2282@gmail.com>
Date:   Thu Jul 3 08:12:41 2025 +0200

    🌐 Add translations for: Hindi

    Currently translated at 27.3% (508 of 1857 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/hi/

commit 4db59803d86f78a35538b089f122291a2577716d
Author: VKing9 <vaibhavrathod2282@gmail.com>
Date:   Thu Jul 3 08:06:20 2025 +0200

    🌐 Add translations for: Hindi

    Currently translated at 27.3% (508 of 1857 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/hi/

commit 14aad9500e7c901573effbb5fdff2a8a0bcca036
Author: VKing9 <vaibhavrathod2282@gmail.com>
Date:   Thu Jul 3 08:05:29 2025 +0200

    🌐 Add translations for: Hindi

    Currently translated at 27.3% (508 of 1857 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/hi/

commit 85014b458caa951d798e45000b02f25b9fdad271
Author: VKing9 <vaibhavrathod2282@gmail.com>
Date:   Thu Jul 3 08:02:38 2025 +0200

    🌐 Add translations for: Hindi

    Currently translated at 27.3% (508 of 1857 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/hi/

commit 002a623606025367f33870c8074e2ea486315b5d
Author: VKing9 <vaibhavrathod2282@gmail.com>
Date:   Thu Jul 3 08:01:16 2025 +0200

    🌐 Add translations for: Hindi

    Currently translated at 27.3% (508 of 1857 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/hi/

commit b72efd33dfeadefcb9f63e68e59cb16fb6366483
Author: VKing9 <vaibhavrathod2282@gmail.com>
Date:   Thu Jul 3 07:57:48 2025 +0200

    🌐 Add translations for: Hindi

    Currently translated at 27.3% (508 of 1857 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/hi/

commit ab75e51c330561eb132eef8354908fcbd8b3ec09
Author: VKing9 <vaibhavrathod2282@gmail.com>
Date:   Thu Jul 3 07:57:18 2025 +0200

    🌐 Add translations for: Hindi

    Currently translated at 27.3% (508 of 1857 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/hi/

commit 2bae66951b930e872c06443b78c36c225c564438
Author: VKing9 <vaibhavrathod2282@gmail.com>
Date:   Thu Jul 3 07:45:41 2025 +0200

    🌐 Add translations for: Hindi

    Currently translated at 27.3% (508 of 1857 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/hi/

commit 1151123aeabfcad65410bd44d6e04685d21ba5ed
Author: VKing9 <vaibhavrathod2282@gmail.com>
Date:   Thu Jul 3 07:40:17 2025 +0200

    🌐 Add translations for: Hindi

    Currently translated at 27.3% (508 of 1857 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/hi/

commit 97a4f34e599d4f1ac6da3029cab3d993ee3ab4da
Author: VKing9 <vaibhavrathod2282@gmail.com>
Date:   Thu Jul 3 07:35:28 2025 +0200

    🌐 Add translations for: Hindi

    Currently translated at 27.3% (508 of 1857 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/hi/

commit a2e1ec123bce716ea0bcc2542809398ec3f65cb1
Author: VKing9 <vaibhavrathod2282@gmail.com>
Date:   Thu Jul 3 07:30:19 2025 +0200

    🌐 Add translations for: Hindi

    Currently translated at 27.3% (508 of 1857 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/hi/

commit 9e72ab6771857ec0814cd0fa22dac6bf1470901a
Author: VKing9 <vaibhavrathod2282@gmail.com>
Date:   Thu Jul 3 07:28:38 2025 +0200

    🌐 Add translations for: Hindi

    Currently translated at 27.3% (508 of 1857 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/hi/

commit 87849347286683544dba68e9a1cbdc9fc06b7ff3
Author: VKing9 <vaibhavrathod2282@gmail.com>
Date:   Thu Jul 3 07:22:13 2025 +0200

    🌐 Add translations for: Hindi

    Currently translated at 27.3% (508 of 1857 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/hi/

commit 1e359566b91bf23270a34ed398b058a635a7de7b
Author: Denys Kisil <ossenjoyer@proton.me>
Date:   Mon Jun 30 14:35:56 2025 +0200

    🌐 Add translations for: Ukrainian (ukr_UA)

    Currently translated at 99.9% (1856 of 1857 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/ukr_UA/

commit 312ee3f7036615fce7f88b880accce71605470dc
Author: Denys Kisil <ossenjoyer@proton.me>
Date:   Mon Jun 30 14:31:42 2025 +0200

    🌐 Add translations for: Ukrainian (ukr_UA)

    Currently translated at 99.9% (1856 of 1857 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/ukr_UA/

commit 7ca4e07d12e419e11b2d0079acb8133beac1315a
Author: Denys Kisil <ossenjoyer@proton.me>
Date:   Mon Jun 30 14:29:26 2025 +0200

    🌐 Add translations for: Ukrainian (ukr_UA)

    Currently translated at 99.9% (1856 of 1857 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/ukr_UA/

commit 3e1db432d2fef95542ea9d0d5e4c164ab2190e11
Author: Denys Kisil <ossenjoyer@proton.me>
Date:   Mon Jun 30 14:22:29 2025 +0200

    🌐 Add translations for: Ukrainian (ukr_UA)

    Currently translated at 99.9% (1856 of 1857 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/ukr_UA/

commit f6121a315de283a8a0b2e163aeaff48851a42a25
Author: Denys Kisil <ossenjoyer@proton.me>
Date:   Mon Jun 30 14:19:07 2025 +0200

    🌐 Add translations for: Ukrainian (ukr_UA)

    Currently translated at 99.9% (1856 of 1857 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/ukr_UA/

commit e1720aae76015fba1754575dc743a3021040e04a
Author: Denys Kisil <ossenjoyer@proton.me>
Date:   Mon Jun 30 14:15:08 2025 +0200

    🌐 Add translations for: Ukrainian (ukr_UA)

    Currently translated at 99.9% (1856 of 1857 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/ukr_UA/

commit a399deae487af3db9127adc89aa39bd813296ecf
Author: Corentin Noël <tintou@noel.tf>
Date:   Fri Jun 27 14:26:07 2025 +0200

    🌐 Add translations for: French

    Currently translated at 99.8% (1855 of 1857 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/fr/

commit 1c81b4c9b3bac3bc210b16ba9691cc5e2917c896
Author: Ingrid Pigueron <ingridp.uxr@gmail.com>
Date:   Thu Jun 26 11:31:04 2025 +0200

    🌐 Add translations for: French

    Currently translated at 99.8% (1854 of 1857 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/fr/

commit 0c756f50747fd9a0031e398d6bba4903d402519a
Author: Stas Haas <stas@girafic.de>
Date:   Sun Jun 22 11:35:49 2025 +0200

    🌐 Add translations for: German

    Currently translated at 92.6% (1720 of 1857 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/de/

commit eaa9d3e2bccf4f2fb9aa9f23fee530c7efe5e720
Author: al0cam <benjaminsikac@gmail.com>
Date:   Thu Jun 19 14:48:06 2025 +0200

    🌐 Add translations for: Croatian

    Currently translated at 87.4% (1624 of 1857 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/hr/

commit 8fc4f74bf8e8e754f780a155c2eb8f6d9c51f3b4
Author: Stas Haas <stas@girafic.de>
Date:   Tue Jun 17 09:06:30 2025 +0200

    🌐 Add translations for: German

    Currently translated at 91.9% (1708 of 1857 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/de/

commit 4d396ef7f7b1be2ec5f57d671717ae1dbb9419ab
Author: Denys Kisil <ossenjoyer@proton.me>
Date:   Mon Jun 16 21:34:47 2025 +0200

    🌐 Add translations for: Ukrainian (ukr_UA)

    Currently translated at 99.9% (1856 of 1857 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/ukr_UA/

commit 28dcfb52785fecca69a4bf22ac7222b330d29f9f
Author: al0cam <benjaminsikac@gmail.com>
Date:   Mon Jun 16 07:54:05 2025 +0200

    🌐 Add translations for: Croatian

    Currently translated at 87.2% (1620 of 1857 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/hr/

commit 680c9a1a0ebe3b323cf1bc7d3f92d7e0bda53c7a
Author: Yaron Shahrabani <sh.yaron@gmail.com>
Date:   Mon Jun 16 18:51:01 2025 +0200

    🌐 Add translations for: Hebrew

    Currently translated at 99.9% (1856 of 1857 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/he/

commit 6e3f6ed276b74df94a64af294ea4ca80ac1c43f6
Author: Ingrid Pigueron <ingridp.uxr@gmail.com>
Date:   Sat Jun 14 12:53:48 2025 +0200

    🌐 Add translations for: French

    Currently translated at 99.8% (1854 of 1857 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/fr/

commit feabe2414490e29db3fbabf20a00d890df9907d8
Author: Nicola Bortoletto <nicola.bortoletto@live.com>
Date:   Fri Jun 13 08:26:35 2025 +0200

    🌐 Add translations for: Italian

    Currently translated at 99.9% (1856 of 1857 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/it/

commit a3b49ee9510b53ae5b010bfbcfb5022a79f6fe1b
Author: Yaron Shahrabani <sh.yaron@gmail.com>
Date:   Thu Jun 12 08:17:05 2025 +0200

    🌐 Add translations for: Hebrew

    Currently translated at 97.0% (1803 of 1857 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/he/

commit c775173ec6f5d22964e9b79cc2a80e3cbd08fccb
Author: Stas Haas <stas@girafic.de>
Date:   Thu Jun 12 10:56:20 2025 +0200

    🌐 Add translations for: German

    Currently translated at 90.7% (1686 of 1857 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/de/

commit 249051c087fd679f7d5a5c604a65c1eb6fb377d0
Author: Yaron Shahrabani <sh.yaron@gmail.com>
Date:   Wed Jun 11 11:24:21 2025 +0200

    🌐 Add translations for: Hebrew

    Currently translated at 96.9% (1800 of 1857 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/he/

commit d33693bf9f8aa419b7688deed03a26926d7b5338
Author: Stas Haas <stas@girafic.de>
Date:   Tue Jun 10 15:05:19 2025 +0200

    🌐 Add translations for: German

    Currently translated at 90.4% (1680 of 1857 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/de/

commit c3d4852c7f61ac398aa505eb0f1b3e0a5e6a6f49
Author: Unreal Vision <unrealvisionyt@gmail.com>
Date:   Tue Jun 10 14:59:59 2025 +0200

    🌐 Add translations for: French

    Currently translated at 99.7% (1853 of 1857 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/fr/

commit 16e6fadb8dd1c2285c64fde7079d6b33c8a7f6a6
Author: Rudra Harsh <harshrudra020@gmail.com>
Date:   Mon Jun 9 15:46:43 2025 +0200

    🌐 Add translations for: Hindi

    Currently translated at 1.2% (23 of 1857 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/hi/

commit 7653bc6060bc0f6ad0664549cc46a15d7e72ccd7
Author: Stephan Paternotte <stephan@paternottes.net>
Date:   Tue Jun 10 05:46:17 2025 +0200

    🌐 Add translations for: Dutch

    Currently translated at 99.7% (1853 of 1857 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/nl/

commit 0f65e960b1de543b9133e6742a732e46967d1f83
Author: Edgars Andersons <Edgars+Weblate@gaitenis.id.lv>
Date:   Tue Jun 10 11:51:03 2025 +0200

    🌐 Add translations for: Latvian

    Currently translated at 99.9% (1856 of 1857 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/lv/

commit 05f12ae1bf59986cdc8f5e98ac14c33d6c0e79e2
Author: Nicola Bortoletto <nicola.bortoletto@live.com>
Date:   Mon Jun 9 23:14:58 2025 +0200

    🌐 Add translations for: Italian

    Currently translated at 99.9% (1856 of 1857 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/it/

commit 2e16f175f57b757a5de4f387caf58331ec5dc822
Author: Yaron Shahrabani <sh.yaron@gmail.com>
Date:   Mon Jun 9 19:01:14 2025 +0200

    🌐 Add translations for: Hebrew

    Currently translated at 96.6% (1794 of 1857 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/he/

commit a202b8b663c3a32af7e21f662907d8365fb587c5
Author: Stas Haas <stas@girafic.de>
Date:   Tue Jun 10 14:57:32 2025 +0200

    🌐 Add translations for: German

    Currently translated at 90.0% (1672 of 1857 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/de/

commit ffe9682df9a5a65dc1f582844e566cf3eff32a08
Author: Unreal Vision <unrealvisionyt@gmail.com>
Date:   Tue Jun 10 14:56:54 2025 +0200

    🌐 Add translations for: French

    Currently translated at 98.7% (1833 of 1857 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/fr/

commit f8f4abe8007491f5392bfb1ab5cbfba618e22700
Author: Ingrid Pigueron <ingridp.uxr@gmail.com>
Date:   Mon Jun 9 19:44:09 2025 +0200

    🌐 Add translations for: French

    Currently translated at 98.7% (1833 of 1857 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/fr/

commit bb6fee5a9ba86eb823c22fae22a49afdcc36c659
Author: Rudra Harsh <harshrudra020@gmail.com>
Date:   Mon Jun 9 15:21:41 2025 +0200

    🌐 Add translations for: Hindi

    Currently translated at 0.5% (11 of 1857 strings)

    Translation: Penpot/frontend
    Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/hi/

commit 55b4c5c07827d4b6eda2ffcc71caca81e6f36534
Author: Madalena Melo <madalena.melo@kaleidos.net>
Date:   Mon Jun 9 11:52:50 2025 +0200

    🌐  Added translation for: Hindi
2025-08-11 09:14:05 +02:00
Andrey Antukh
f02667e031 Merge remote-tracking branch 'origin/staging' into develop 2025-08-11 09:12:03 +02:00
Alejandro Alonso
8e0a6e4123 🐛 Fix auto height is fixed in the HTML inspect tab for text elements (#7078) 2025-08-11 09:07:43 +02:00
Marina López
0131cd6f8b Display the total price of the subscription and the cap amount (#7088) 2025-08-11 09:07:24 +02:00
Alejandro Alonso
99b40cecf2 Revert "🐛 Fix big blur rendering for wasm render"
This reverts commit c7a4c67d83.
2025-08-09 08:44:52 +02:00
Alejandro Alonso
c7a4c67d83 🐛 Fix big blur rendering for wasm render 2025-08-09 08:42:55 +02:00
Florian Schrödl
c29a8cb0c4 Implement font-weight token (#7089) 2025-08-08 11:11:18 +02:00
Andrey Antukh
288a7b21d6 Merge tag '2.9.0-RC8' 2025-08-08 09:47:42 +02:00
andrés gonzález
32bd08533d 💄 Remove slide about overrides in the release notes (#7086) 2025-08-08 09:46:40 +02:00
Yamila Moreno
c1aae12327 📎 Improve gh actions 2025-08-07 18:08:25 +02:00
Yamila Moreno
23a6f4b7c1 📎 Improve gh actions 2025-08-07 18:07:47 +02:00
Yamila Moreno
a9f4fe84fa 📎 Improve gh actions 2025-08-07 17:51:20 +02:00
Andrey Antukh
133e6e1e68 Merge tag '2.9.0-RC7' 2025-08-07 16:30:30 +02:00
Andrey Antukh
f7832585dc Add tests for snapshot locking (#7085) 2025-08-07 16:27:43 +02:00
Eva Marco
e34bfb50a8 🐛 Fix font variant names for source sans pro font (#7087) 2025-08-07 16:25:15 +02:00
Andrey Antukh
6abd045273 🐛 Add missing generator for token-set file change operation (#7080)
* 🐛 Add missing generator for token-set file change operation

* 🐛 Use ::sm/any instead of :any for on get-file-data-for-thumbnail rpc method

Mainly because :any will use a very generic generator that can generate
instances of Character that are not directly serializable to JSON
2025-08-07 12:36:14 +02:00
Florian Schrödl
0a106c2604 🐛 Fix import of borderWidth (#7084) 2025-08-07 12:16:18 +02:00
Andrey Antukh
8f5f88743b Normalize font variant naming for google fonts (#7083) 2025-08-07 11:14:40 +02:00
Florian Schrödl
9562d2f1f0 Allow font-families with surrounding quotation marks (#7081) 2025-08-07 11:13:04 +02:00
Andrey Antukh
ea482f16c8 💄 Add minor cosmetic changes to dashboard sidebar components (#7052)
* 💄 Change component decl style of sidebar-team-switch

* 💄 Change component decl style of sidebar-search

* 💄 Add general cosmetic changes to sidebar components
2025-08-07 10:57:46 +02:00
Alejandro Alonso
50634e1a4c 🐛 Fix selection lost when using keyboard 2025-08-07 09:28:17 +02:00
Andrey Antukh
56de96d25b Merge remote-tracking branch 'origin/staging' into develop 2025-08-07 08:04:40 +02:00
Luis de Dios
5d1c20c47c 🐛 Fix focus new added property (#7065) 2025-08-07 07:47:17 +02:00
Marina López
778a608854 🐛 Fix tooltip for icon plans from team dropdown (#7075) 2025-08-07 07:43:49 +02:00
andrés gonzález
7de8e10721 🐛 Fix changelog link (#7070) 2025-08-07 07:43:11 +02:00
andrés gonzález
80f41c4a69 🐛 Fix issue where Alt + arrow keys shortcut interferes with letter-spacing (#7071) 2025-08-07 07:42:33 +02:00
Luis de Dios
a3557a81e4 🐛 Fix add space between the name and the index of new properties (#7068) 2025-08-07 07:41:33 +02:00
Luis de Dios
0a02e526ee Treat empty names as a malformed formula (#7073) 2025-08-07 07:41:07 +02:00
Luis de Dios
db9349e764 💄 Style improvements in the swap panel (#7077) 2025-08-07 07:40:38 +02:00
Belén Albeza
60903f349f 🐛 Fix color picker not working with the new renderer 2025-08-06 18:00:48 +02:00
Florian Schrödl
b91e955486 Text decoration fixes (#7066)
*  Show text more options when apply text decoration token

* 🐛 Fix placeholder
2025-08-06 16:23:38 +02:00
Marina López
a76a9fae41 🐛 Fix an unused translation (#7074) 2025-08-06 13:28:02 +02:00
Andrey Antukh
f7cfbdd229 🐛 Comment the problematic migration 2025-08-05 22:05:52 +02:00
Andrey Antukh
e28d2842f6 🐛 Revert the revert of orientation detection on media
This reverts commit 515cbf7bef.
2025-08-05 22:03:09 +02:00
Andrey Antukh
ccc3ca0948 Disable virtual threads on http server 2025-08-05 20:34:47 +02:00
Andrey Antukh
515cbf7bef 🐛 Revert orientation detection on media 2025-08-05 19:30:01 +02:00
Andrey Antukh
c320cbc47b 🐛 Revert to semaphore based climit impl 2025-08-05 19:17:35 +02:00
Yamila Moreno
6166f45a7f Merge pull request #7069 from penpot/yms-update-k8s-documentation
📚 Update k8s documentation
2025-08-05 15:44:59 +02:00
Yamila Moreno
c103eb86db 📚 Update k8s documentation 2025-08-05 13:55:39 +02:00
Alejandro Alonso
61d93d69b1 Merge pull request #7048 from penpot/elenatorro-11704-fix-symbols-font
 Include symbols support
2025-08-05 13:40:16 +02:00
Belén Albeza
d5abf34538 🐛 Fix text style change not being applied (#7036)
* 🐛 Fix text styles not being applied to current cursor

* 🔧 Add text file for bug 11552

* 📚 Update changelog
2025-08-05 13:35:54 +02:00
Alejandro Alonso
7efc297cd9 Merge pull request #7053 from penpot/ladybenko-11678-compact-keep-ratio-flag
 Compact fill serialization (opacity + flags)
2025-08-05 13:29:49 +02:00
Alejandro Alonso
98522a390e 🐛 Fix frames extrect calculation 2025-08-05 13:25:25 +02:00
Andrey Antukh
46969585ed Disable native buffers usage on xnio
A temporal change for investigate native memory leak
2025-08-04 22:13:08 +02:00
Andrey Antukh
47882c5419 Add missing parameter on climit instance creation 2025-08-04 19:53:56 +02:00
andrés gonzález
019d5e083a 💄 Change copys at the 2.9 release slides (#7063) 2025-08-04 19:53:50 +02:00
Belén Albeza
6fc949844d Use 1 byte to store opacity in gradient fills 2025-08-04 14:13:40 +02:00
Andrey Antukh
97e8c9250a Merge remote-tracking branch 'origin/staging' into develop 2025-08-04 14:10:57 +02:00
Andrey Antukh
85f6cf32ae 🐛 Several bugfixes (#7062)
* 🐛 Fix incorrect status validation on subscription internal api

* 🐛 Make the shortcuts overwritting optional
2025-08-04 13:54:29 +02:00
Marina López
ded8e39e73 🐛 Fix hidden button in subscribe modal when there is a large number of teams (#7061) 2025-08-04 13:16:58 +02:00
Florian Schrödl
551313d3de Text case fixes (#7058)
*  Add placeholder

*  Remove status icon
2025-08-04 12:13:57 +02:00
Andrey Antukh
e730200873 🐛 Fix pinned project ordering on dashboard sidebar (#7060) 2025-08-04 12:07:19 +02:00
Andrey Antukh
433e61bc4e Merge remote-tracking branch 'origin/staging' into develop 2025-08-04 11:52:24 +02:00
Andrei Fëdorov
818b03d8f2 Add text decoration token (#7049) 2025-08-04 10:47:09 +02:00
Belén Albeza
ae3aef8dcc Use existing space for storing image fill flags 2025-08-04 10:42:56 +02:00
Luis de Dios
1b30325640 🐛 Fix adjust focus in select component (#7024) 2025-08-04 10:21:17 +02:00
Yamila Moreno
44d626d578 📎 Fix typo in documentation 2025-08-01 16:32:42 +02:00
Francis Santiago
4501d13961 📚 Clarify OpenShift requirements (#6937)
* 📚 Clarify OpenShift requirements

* 📚 Remove the click for expanding
2025-08-01 16:26:04 +02:00
Elena Torró
c8f5ec4698 ♻️ Refactor dropdown-menu and make dropdown visibility exclusive (#6956)
* 🐛 Fix having multiple dropdown menus opened on dashboard page

* ♻️ Refactor dropdown-menu

Make it follow new standards and make it external api more usable,
not depending on manually provided list of ids.

This also implements the autoclosing of "other" active/open
dropdown-menu (or other similar components).

* 📎 Add PR feedback changes

* 🐛 Fix incorrect event handling on project-menu

* 🐛 Fix unexpected exception

---------

Co-authored-by: Andrey Antukh <niwi@niwi.nz>
2025-08-01 16:14:15 +02:00
Pablo Alba
07b15819d4 🎉 Add the ability to create variants from a selection (#7045)
* 🎉 Add the ability to create variants from a selection

* 📎 Add PR feedback changes

* 💄 Add minor cosmetic changes

---------

Co-authored-by: Andrey Antukh <niwi@niwi.nz>
2025-08-01 15:39:46 +02:00
Elena Torró
f519c6ef46 Center team settings properly (#7021) 2025-08-01 15:17:32 +02:00
Juan de la Cruz
baa1cfb2f8 🎉 Add 2.9 release slides (#7019) 2025-08-01 14:59:11 +02:00
Eva Marco
905699d15a Add info to apply-token events (#7050) 2025-08-01 14:00:30 +02:00
Eva Marco
fe53869308 🐛 Fix small details on number token application (#7051) 2025-08-01 13:52:09 +02:00
Elena Torro
c69ee35e18 Include symbols support 2025-08-01 13:41:12 +02:00
Luis de Dios
8d5ee92f16 🐛 Fix show 'add new property' from menu when a variant is selected (#7042) 2025-08-01 13:21:19 +02:00
Andrey Antukh
e55d184d2b Merge remote-tracking branch 'origin/staging' into develop 2025-08-01 13:13:56 +02:00
Andrey Antukh
50076bac83 Merge remote-tracking branch 'origin/main' into staging 2025-08-01 13:10:52 +02:00
Eva Marco
e976714964 🐛 Fix error on inspect tab with texts (#7032) 2025-08-01 13:03:43 +02:00
Brandon Currell
44bc4b7fa4 🐳 Add missing package in the exporter Docker image (#7026)
penpot-exporter requires poppler-utils for exporting to a PDF, but it is missing.
Added the package to the Dockerfile in the RUN section where dependencies are
being installed.

Signed-off-by: Brandon Currell <brandon+git@currell.pw>
2025-08-01 13:00:51 +02:00
Brandon Currell
ce0d6ffda2 🐳 Add missing package in the exporter Docker image (#7026)
penpot-exporter requires poppler-utils for exporting to a PDF, but it is missing.
Added the package to the Dockerfile in the RUN section where dependencies are
being installed.

Signed-off-by: Brandon Currell <brandon+git@currell.pw>
2025-08-01 12:59:39 +02:00
Yamila Moreno
5c14f486d7 🐳 Update Imagemagick version 2025-08-01 12:49:11 +02:00
Andrey Antukh
0cbd980b68 🎉 Add imagemagick docker image build scripts (#6925)
* 🎉 Add imagemagick docker image build scripts

* 📎 Add PR feedback changes
2025-08-01 12:48:47 +02:00
Andrey Antukh
bc2308f2ce Merge pull request #7011 from penpot/lmcrean-lmcrean-milestones-version-lock
🎉 Add the ability to lock/unlock of file versions
2025-08-01 12:40:07 +02:00
Laurie Crean
0b47a366ab Implement version locking functionality for file snapshots
Signed-off-by: Laurie Crean <lmcrean@gmail.com>
2025-08-01 11:41:30 +02:00
Andrey Antukh
1892fa6782 Merge pull request #7043 from penpot/niwinz-develop-refactor-time-helpers
♻️ Refactor time related namespaces
2025-08-01 11:35:07 +02:00
Andrey Antukh
6f35b7db24 Add reader tag support for tokens related types 2025-08-01 11:20:01 +02:00
Andrey Antukh
4d9e070bcd Add reader tag support for types path data 2025-08-01 11:20:01 +02:00
Andrey Antukh
61fe8e8d8e Add reader tag support for geom matrix 2025-08-01 11:20:01 +02:00
Andrey Antukh
0934095e96 Add reader tag support for geom point 2025-08-01 11:20:01 +02:00
Andrey Antukh
eba2ff7d8d Add impl for Inst protocol for FileTime class 2025-08-01 11:20:01 +02:00
Andrey Antukh
283eb0419c ♻️ Refactor time related namespaces
Mainly removes the custom app.util.time namespace
from frontend and backend and normalize all to use
the app.common.time namespace
2025-08-01 11:20:01 +02:00
Elena Torro
9a0c36c442 🐛 Fix default color when neither fill nor background color is set 2025-07-31 16:17:13 +02:00
luisδμ
ff1d26294a 🐛 Fix create properties with a default value instead of an empty one (#7033) 2025-07-31 15:01:51 +02:00
Eva Marco
63bfbbb3c6 🐛 Fix typography token context menu (#7038) 2025-07-31 15:00:14 +02:00
Eva Marco
95dda2b1af 🐛 Fix stroke width token application (#7039) 2025-07-31 14:59:48 +02:00
Elena Torró
76d725559e Set default new text fill color depending on background color (#6998) 2025-07-31 12:31:54 +02:00
luisδμ
d7ec8ccbc0 🐛 Fix property name cannot be empty (#7030) 2025-07-31 12:27:10 +02:00
Juanfran
6def5e285b 🐛 Apply design review fixes for variant connection help (#11186) (#7016) 2025-07-31 12:26:04 +02:00
Andrey Antukh
5170872961 Merge pull request #7031 from penpot/eva-fix-export-button-width
🐛 Fix export button width on inspect tab
2025-07-31 12:25:03 +02:00
Andrey Antukh
b46e9ee065 Merge remote-tracking branch 'origin/staging' into develop 2025-07-31 12:22:14 +02:00
Andrey Antukh
871ca68e1e 📎 Allow revert commits on github commit checker 2025-07-31 12:14:29 +02:00
Andrey Antukh
0ab896fc76 Revert " Highlight first font in font selector search, apply on Enter/click"
This reverts commit e62567d09e.
2025-07-31 12:14:29 +02:00
Andrey Antukh
6a4b548457 Revert "🐛 Fix font selector highlight inconsistency (#6990)"
This reverts commit 708a40bff1.
2025-07-31 12:14:29 +02:00
Elena Torró
0457ca4fe5 Use 'desvincular' instead of 'desacoplar' (#7020) 2025-07-31 11:50:46 +02:00
Elena Torro
083be7df88 🐛 Fix focus editor check 2025-07-31 10:05:37 +02:00
Eva Marco
695a399941 🐛 Fix export button width on inspect tab 2025-07-31 09:30:46 +02:00
luisδμ
200b69fae2 📚 Improve documentation for combobox and select in the storybook (#7006) 2025-07-31 09:05:54 +02:00
Eva Marco
a32463fada 🐛 Fix tooltip position after several shows and hides (#7022) 2025-07-31 09:00:05 +02:00
luisδμ
3b04cd37ff 🐛 Fix empty values should not have dimmed text (#7015) 2025-07-30 18:06:39 +02:00
Eva Marco
5d44c88988 🐛 Fix token pill not showing position application on dimension token type (#7018) 2025-07-30 14:24:10 +02:00
luisδμ
4d688b1d55 🐛 Fix title for button when trying to remove last variant property (#7017) 2025-07-30 13:28:42 +02:00
Andrey Antukh
e43b6fb0b7 Merge pull request #6992 from penpot/niwinz-artboard-defaults
 Add defaults for artboard drawing
2025-07-30 13:27:54 +02:00
Andrey Antukh
7895f03447 💄 Add minor cosmetic changes 2025-07-30 13:11:28 +02:00
Marina López
1f42b2f72d Show preset name when an option is selected 2025-07-30 13:11:28 +02:00
Andrey Antukh
f4adfe56be Add defaults for artboard drawing 2025-07-30 13:11:28 +02:00
Alejandro Alonso
33a679fbc0 Merge pull request #6940 from penpot/niwinz-develop-inplace-import
🎉 Add support for in-place binfile import
2025-07-30 12:42:37 +02:00
Pablo Alba
9db67cc5e8 🐛 Fix bad swap slot after two swaps (#6962)
* 🐛 Fix bad swap slot after two swaps

*  MR changes
2025-07-30 12:35:27 +02:00
luisδμ
9834f0596b 🐛 Fix move empty variant values to the end when component is selected (#7009)
* 🐛 Move empty variant values to the end when component is selected

* 📎 PR changes
2025-07-30 12:29:51 +02:00
Andrey Antukh
ce87d797d1 Merge pull request #7014 from penpot/niwinz-staging-regression-3
🐛 Fix several issues related to font/text related tokens
2025-07-30 12:25:28 +02:00
Andrey Antukh
37cec8891f 🎉 Add inplace binfile import support 2025-07-30 12:23:40 +02:00
Andrey Antukh
fd62141c04 Disable pointer-map feature (temporary)
Because the upcoming refactor changes several aspects
of that feature and it not make sense to continue have
this active for now, until refactor is merged.
2025-07-30 12:06:41 +02:00
Andrey Antukh
4bdba6894d Add get-with-sql helper to db module 2025-07-30 12:06:41 +02:00
Andrey Antukh
6c7fef29a8 Improve file data type constructor 2025-07-30 12:06:41 +02:00
Andrey Antukh
a77edc5aa2 Add better uri constructor function 2025-07-30 12:06:41 +02:00
Andrey Antukh
7fde1436e1 🐛 Add missing styles to the empty node on editor-v1 2025-07-30 11:45:39 +02:00
Andrey Antukh
e1c5a32fcb 💄 Fix indentation style on generate-unapply-tokens 2025-07-30 11:45:19 +02:00
Andrey Antukh
b262e6a46f 🐛 Fix incorrect condition on checking text shape attrs 2025-07-30 11:44:07 +02:00
Yamila Moreno
31f37a20e3 Merge pull request #7013 from penpot/yms-simplify-gh-actions
 Simplify gh-actions workflows
2025-07-30 11:42:39 +02:00
alonso.torres
06b4ae5c96 🐛 Fix problem with layout update touching geometry 2025-07-30 11:27:15 +02:00
Alejandro Alonso
a3e24785d3 Merge pull request #7003 from penpot/alotor-fix-transform
🐛 Fix wasm transform issues
2025-07-30 11:10:54 +02:00
Yamila Moreno
78102210a5 Simplify gh-actions workflows 2025-07-30 10:45:01 +02:00
Pablo Alba
7553d68100 🐛 Fix corner case of chained switch and libraries (#7008) 2025-07-30 08:44:27 +02:00
Andrey Antukh
2e726b62c3 📎 Update changelog 2025-07-29 20:07:05 +02:00
Andrey Antukh
02acd81c2c 🐛 Add missing profile prop to access style component (#7007)
* 💄 Fix request-access component style

* 🐛 Add missing profile prop to access style component
2025-07-29 16:04:15 +02:00
Andrey Antukh
44daa1cf65 Merge remote-tracking branch 'origin/staging' into develop 2025-07-29 15:22:14 +02:00
Andrey Antukh
bae2de75ff Merge branch 'main' into staging 2025-07-29 15:21:58 +02:00
Andrey Antukh
b68c426cd1 🐛 Fix exception on fills menu when binary-fills flag is active
And multiple shapes are selected.
2025-07-29 15:10:32 +02:00
Andrey Antukh
5161ef15bf 🐛 Fix regression on show access request dialog (#7005) 2025-07-29 14:58:02 +02:00
Andrey Antukh
bdbaa6d597 Merge remote-tracking branch 'origin/staging' into develop 2025-07-29 14:34:35 +02:00
Eva Marco
36d3d94ec9 🐛 Fix X & Y position do not sincronize with tokens (#7004) 2025-07-29 14:32:06 +02:00
Andrey Antukh
0e675a725d 📎 Fix linter issues on frontend
Caused by the merge from staging to develop
2025-07-29 14:15:01 +02:00
Andrey Antukh
17447d7610 Remove restriction of duplicate bindings on mousetrap 2025-07-29 14:14:19 +02:00
Andrey Antukh
2a3046ba2e 📎 Fix linter issue on common 2025-07-29 14:10:49 +02:00
Andrey Antukh
54d76123d0 Merge remote-tracking branch 'origin/staging' into develop 2025-07-29 14:06:53 +02:00
Andrey Antukh
6ffbf08826 Merge pull request #6969 from penpot/andy-show-keyboard-distance
 Show distance between layers while moving them with the keyboard
2025-07-29 13:32:53 +02:00
andrés gonzález
708a40bff1 🐛 Fix font selector highlight inconsistency (#6990)
* 🐛 Fix font selector highlight inconsistency

*  Add minor performance enhancements

---------

Co-authored-by: Andrey Antukh <niwi@niwi.nz>
2025-07-29 13:12:54 +02:00
Andrey Antukh
d84ee8bb65 Optimize mousetrap binding setup 2025-07-29 13:12:28 +02:00
Elena Torró
a16f40cb73 Set page objects once on wasm render(#6994) 2025-07-29 13:00:40 +02:00
Andrey Antukh
02cff2740f Remove restriction of duplicate bindings on mousetrap 2025-07-29 12:51:39 +02:00
Andres Gonzalez
6049d97ed9 Display continously the distances between layers
When a user moves a layer with the keyboard.
2025-07-29 12:51:04 +02:00
Andrey Antukh
3f657a0c04 Merge pull request #6997 from penpot/alotor-fix-wasm-bugs
🐛 Fix wasm problems
2025-07-29 12:42:26 +02:00
Marina López
efaf6573bd 📎 Update monetization texts (#7002) 2025-07-29 12:42:11 +02:00
alonso.torres
4b020dcc1a 🐛 Fix problem when changing size with user input 2025-07-29 12:16:08 +02:00
alonso.torres
223a468bbf 🐛 Fix problem when moving layout with measure input 2025-07-29 12:15:53 +02:00
alonso.torres
ddd0e447f6 🐛 Fix problem when creating shapes after new page 2025-07-29 12:15:27 +02:00
alonso.torres
0c0c81e9a5 🐛 Fix problem with shape to path not working 2025-07-29 12:15:27 +02:00
Yamila Moreno
001bcbce59 Merge pull request #6995 from penpot/yms-update-imagemagick-version
🐳 Update Imagemagick version
2025-07-29 10:58:32 +02:00
Yamila Moreno
c195c07a3f 🐳 Update Imagemagick version 2025-07-29 10:37:11 +02:00
Alejandro Alonso
f5298f51e7 🐛 Fix the context menu always closes after any action (#6944) 2025-07-29 09:50:55 +02:00
Alejandro Alonso
46c440fef2 🐛 Fix remove color button in the gradient editor (#6993) 2025-07-28 17:48:05 +02:00
Aitor Moreno
e6ac2c1159 Merge pull request #6880 from penpot/elenatorro-fix-editor-crash-on-deleting-entire-selection-firefox
🐛 Handle empty paragraph on entire selected text deletion
2025-07-28 17:39:25 +02:00
Florian Schrödl
4c605b8151 Implement text case token (#6978) 2025-07-28 17:36:06 +02:00
Elena Torro
2913899aa5 🐛 Fix auto-format on font 2025-07-28 17:31:36 +02:00
Elena Torro
ecd3245612 🐛 Fix request render after pending calls have finished on set-objects 2025-07-28 17:31:36 +02:00
Xaviju
dadeda4476 🐛 Display stroke properties in inspect tab (#6955) 2025-07-28 16:17:54 +02:00
Elena Torró
d129557f77 Merge pull request #6988 from penpot/superalex-fix-render-wasm-visible-0-width-strokes
🐛 Fix visible 0 width strokes in wasm render
2025-07-28 14:36:07 +02:00
Alejandro Alonso
e77f8b572a Merge pull request #6953 from penpot/superalex-fix-component-changes-not-propagated
🐛 Fix component changes not propagated
2025-07-28 12:53:37 +02:00
Alejandro Alonso
ade5eecf80 🐛 Fix component changes not propagated 2025-07-28 12:38:09 +02:00
Elena Torró
ff7e34e308 Merge pull request #6984 from penpot/superalex-fix-switching-theme-form-wasm-render
🐛 Fix switching theme for wasm render
2025-07-28 11:30:41 +02:00
Yamila Moreno
88055294a2 Reuse github workflows (#6989) 2025-07-28 09:03:47 +02:00
Alejandro Alonso
e473f45048 🐛 Fix visible 0 width strokes in wasm render 2025-07-28 08:46:47 +02:00
Alejandro Alonso
bcee670ac6 🐛 Fix switching theme for wasm render 2025-07-28 07:44:56 +02:00
andrés gonzález
97fc7702b8 📚 Improve and clarify 'Hide and lock layers' section (#6975) 2025-07-25 14:53:32 +02:00
andrés gonzález
54fcd58531 📚 Add doc for resizing text (#6974)
* 📚 Add doc for resizing text

* 📚 Update docs for text resizing

Co-authored-by: Madalena Melo <madalena.melo@kaleidos.net>
Signed-off-by: andrés gonzález <andres.gonzalez79@gmail.com>

---------

Signed-off-by: andrés gonzález <andres.gonzalez79@gmail.com>
Co-authored-by: Madalena Melo <madalena.melo@kaleidos.net>
2025-07-25 13:20:52 +02:00
andrés gonzález
b7a8747f00 📚 Add doc for tokens zip file import option (#6973) 2025-07-25 13:20:39 +02:00
Elena Torró
b93e96a18d Merge pull request #6958 from penpot/superalex-fix-texts-bigger-than-selrects-in-multiple-tiles
🐛 Fix rendering texts bigger than their selrects in mutiple tiles
2025-07-25 13:14:29 +02:00
Alejandro Alonso
b70f6af2df 🐛 Fix rendering texts bigger than their selrects in mutiple tiles 2025-07-25 12:56:57 +02:00
Andrey Antukh
d00de7d5a4 Merge pull request #6960 from penpot/xaviju-remove-image-shape-type-fix
🐛 Remove image type from inspect tab panels
2025-07-25 12:49:57 +02:00
andrés gonzález
5ae4dde222 📚 Add font size token doc (#6972) 2025-07-25 12:30:56 +02:00
Elena Torro
0e20bb6271 🐛 Fix text width calculation 2025-07-25 12:27:26 +02:00
Xaviju
2fbd4b07e0 🐛 Remove image type from inspect tab panels 2025-07-25 12:08:01 +02:00
Elena Torró
bd15ef4618 Merge pull request #6854 from penpot/ladybenko-11522-fix-missing-font
🐛 Fix missing font when pasting text
2025-07-25 11:55:56 +02:00
Belén Albeza
af5b942e05 🐛 Fix copy/paste not working on follow up pastes 2025-07-25 09:53:48 +02:00
Belén Albeza
098fd9fb0f 🐛 Fix not picking up font style / variant in new renderer 2025-07-25 09:48:20 +02:00
Belén Albeza
a242962113 🐛 Fix missing font when pasting text (editor v1) 2025-07-25 09:48:20 +02:00
Elena Torro
2b95e6b7a9 🐛 Fix update canvas background color 2025-07-25 09:19:59 +02:00
Florian Schroedl
58a843ea23 Remove token when applying tyopgraphic asset style 2025-07-24 17:51:53 +02:00
Florian Schroedl
4189d01844 Remove token when applying tyopgraphic asset style 2025-07-24 17:14:04 +02:00
Andrés Moya
57330f53e2 🔧 Use id instead of name for tokens crud 2025-07-24 15:21:18 +02:00
Florian Schroedl
f6b97af148 🐛 Fix spacing menu not available in dimensions token 2025-07-24 15:20:10 +02:00
Florian Schroedl
1c79e726af 🐛 Fix spacing menu not available in dimensions token 2025-07-24 15:16:01 +02:00
Alejandro Alonso
76b7287bf1 Merge pull request #6864 from penpot/niwinz-staging-snapshot-migrations
 Add migrations handling on file snapshots
2025-07-24 11:41:17 +02:00
Andrey Antukh
019bc2f183 Add migrations handling on file snapshots 2025-07-24 11:40:54 +02:00
Florian Schroedl
8c96a617be Add test for spacing token application rules 2025-07-24 11:01:49 +02:00
Florian Schroedl
1f15e9b81e Fix spacing token for frame children 2025-07-24 11:01:49 +02:00
Alejandro Alonso
f7627e515a Merge pull request #6876 from penpot/niwinz-develop-minor-changes-logical-deletion
 Change default status filtering for logical deletion
2025-07-24 10:58:49 +02:00
Andrey Antukh
d08c94d5a6 Change default status filtering for logical deletion 2025-07-24 10:43:45 +02:00
Florian Schroedl
cccea3dc71 Add test for spacing token application rules 2025-07-24 10:42:08 +02:00
Florian Schroedl
c82c39caf3 Fix spacing token for frame children 2025-07-24 10:42:08 +02:00
Xaviju
01896501c1 🐛 Remove image type from inspect tab panels (#6959) 2025-07-24 09:37:38 +02:00
Andrey Antukh
33cf75e933 Merge remote-tracking branch 'origin/staging' into develop 2025-07-24 09:00:29 +02:00
Andrey Antukh
3f9a1525ca Merge pull request #6954 from penpot/alotor-fix-gradient-stroke
🐛 Fix opacity on stroke gradients
2025-07-24 08:59:02 +02:00
alonso.torres
52c1e227d5 🐛 Fix change from gradient to solid color 2025-07-24 08:58:48 +02:00
alonso.torres
955538b12a 🐛 Fix opacity on stroke gradients 2025-07-24 08:58:46 +02:00
Alonso Torres
dfc8a1da4a Fix problem with booleans selection (#6950) 2025-07-24 08:57:02 +02:00
Alonso Torres
8254af27cb 🐛 Fix problem when changing between flex/grid layout (#6949) 2025-07-24 08:54:07 +02:00
Pablo Alba
b477ca0508 🐛 Fix design review bugs on variants advanced retrieve (#6948) 2025-07-24 08:53:26 +02:00
Elena Torró
f76391ecbb 🐛 Enable switch to system theme on options menu (#6946) 2025-07-24 08:43:03 +02:00
Andrés Moya
c49e9fbf18 🐛 Fix last migration of token sets (#6957) 2025-07-24 08:42:16 +02:00
Marina López
122701ee7b 🐛 Fix modal submit button for unpaid or canceled subscriptions (#6947) 2025-07-24 08:41:39 +02:00
Andrés Moya
351362bb50 🐛 Fix migration from tokens lib version 1.2 2025-07-23 15:28:53 +02:00
Andrey Antukh
9a6989d2ca 📎 Fix linter issues introduced on merging staging into develop 2025-07-23 12:27:04 +02:00
Andrey Antukh
8aebe1a41e Merge remote-tracking branch 'origin/staging' into develop 2025-07-23 12:26:09 +02:00
Andrey Antukh
1acf78d57c Merge branch 'main' into staging 2025-07-23 12:09:37 +02:00
Andrey Antukh
523373dfa2 📎 Update .gitignore file 2025-07-23 12:09:15 +02:00
Andrés Moya
f55e7d8165 🐛 Keep shape level groups for token sync later 2025-07-23 12:04:31 +02:00
Andrés Moya
9fdc6be465 🐛 Fix bad touched attributes when applying tokens to text shapes 2025-07-23 12:04:31 +02:00
Alejandro Alonso
9390c1e7be 🐛 Fix "Copy as SVG" generates different code from the Inspect panel (#6945) 2025-07-23 11:46:58 +02:00
Florian Schroedl (aider)
d788a4d252 Implement new token-type :font-families 2025-07-23 11:26:28 +02:00
Eva Marco
b20b272eae 📚 Update changelog 2025-07-23 09:53:49 +02:00
Aitor Moreno
2cddc6fb5b Merge pull request #6583 from penpot/niwinz-fills-binary-type
🎉 Fills as binary type
2025-07-23 09:26:26 +02:00
Alejandro Alonso
d46b519524 🐛 Fix remove color button in the gradient editor (#6942) 2025-07-23 09:04:54 +02:00
Andrey Antukh
4effd375a9 Add several improvements to admin pannel 2025-07-23 08:33:33 +02:00
Andrey Antukh
4e753dc474 💄 Use resolved schemas instead of references
For several schemas on common types
2025-07-23 08:33:28 +02:00
Andrey Antukh
fbf63b98c3 Reuse file data checkers on file validate ns 2025-07-23 08:33:23 +02:00
Marina López
3df557b370 ♻️ Remove the workaround for updating the subscription after subscribing (#6938) 2025-07-23 08:10:20 +02:00
Aitor Moreno
cdb600b081 Remove unused code 2025-07-23 08:03:23 +02:00
Aitor Moreno
ffb688696b 🎉 Add keep-aspect-ratio integration 2025-07-23 08:03:23 +02:00
Andrey Antukh
8bb210e7b6 🎉 Add binary fills integration 2025-07-23 08:03:23 +02:00
Andrey Antukh
9ee488009f ♻️ Add substantial refactor on how types are organized
This mainly affects types related to colors, fills and texts, moving library
based operations from color namespace.
2025-07-23 08:03:23 +02:00
Andrey Antukh
96d9b102b6 Add type hints on config ns 2025-07-23 07:32:11 +02:00
Andrey Antukh
16fba49937 Expose flags for common submodule 2025-07-23 07:32:11 +02:00
Andrey Antukh
af99bd620c Use binary fills to write data to wasm memory 2025-07-23 07:32:11 +02:00
Andrey Antukh
8a58b9d459 Use new write-bool helper on fills metadata 2025-07-23 07:32:11 +02:00
Andrey Antukh
e3c62075b8 Write keep-aspect-ration on fill binary format 2025-07-23 07:32:11 +02:00
Andrey Antukh
22a70eb5b2 🎉 Add write-bool helper to buffer ns helpers 2025-07-23 07:32:11 +02:00
Andrey Antukh
4e2998a366 ♻️ Rename fill to fills namespace 2025-07-23 07:32:11 +02:00
Andrey Antukh
158f759cde Add binary fills initialization on workspace fetch 2025-07-23 07:32:11 +02:00
Aitor Moreno
3e3be95420 Merge pull request #6927 from penpot/elenatorro-test-fix-text-shadows
🐛 Fix text shadows apply text opacity
2025-07-23 06:59:28 +02:00
Elena Torró
b5808701ec Merge pull request #6873 from penpot/niwinz-develop-enhancements-1
 Add improvements for backend admin/debug page
2025-07-22 15:14:08 +02:00
Xaviju
35f3125fff 🐛 Fix null when copying shadow color on inspect tab (#6923)
Co-authored-by: Xavier Julian <xaviju@proton.me>
2025-07-22 14:49:36 +02:00
Elena Torro
5427d207cd 🐛 Fix text shadows apply text opacity 2025-07-22 14:34:10 +02:00
Xaviju
ee23d72d13 🐛 Fix null when copying shadow color on inspect tab (#6923)
Co-authored-by: Xavier Julian <xaviju@proton.me>
2025-07-22 14:06:06 +02:00
Francis Santiago
f22aa606ce 📚 Clarify OpenShift requirements (#6937)
* 📚 Clarify OpenShift requirements

* 📚 Remove the click for expanding
2025-07-22 14:05:02 +02:00
Andrey Antukh
d914314c1c Merge remote-tracking branch 'origin/staging' into develop 2025-07-22 13:04:57 +02:00
Pablo Alba
4aa9f1f62b 🐛 On component swap do not show secondary variants (#6928) 2025-07-22 12:33:37 +02:00
David Barragán Merino
9d288486d7 🐛 Subscription current period dates could be null (#6931)
`current-period-start` and `current-period-end` can be null if the invoice has not yet been created in stripe. This happens after the subscription is created, before the webhook is sent.
2025-07-22 12:32:42 +02:00
Pablo Alba
ea5521485a ♻️ Remove redundant flag on text overrides (#6933) 2025-07-22 12:32:24 +02:00
Marina López
f768ffbdad 🐛 Fix wrong behaviour for unpaid or canceled subscriptions (#6932) 2025-07-22 12:31:45 +02:00
Andrey Antukh
4f0d3660de 🎉 Add imagemagick docker image build scripts (#6925)
* 🎉 Add imagemagick docker image build scripts

* 📎 Add PR feedback changes
2025-07-22 11:51:13 +02:00
Andrey Antukh
fa72bb4adf Add several improvements to admin pannel 2025-07-22 10:06:29 +02:00
Andrey Antukh
ea0044f69a 💄 Use resolved schemas instead of references
For several schemas on common types
2025-07-22 10:06:29 +02:00
Andrey Antukh
7e493376a4 Reuse file data checkers on file validate ns 2025-07-22 10:06:29 +02:00
Andrey Antukh
8c5afe5ab3 📎 Add next release entries to the changelog 2025-07-21 21:20:46 +02:00
Andrey Antukh
7ccb742ef3 Merge remote-tracking branch 'origin/develop' into staging 2025-07-21 21:15:54 +02:00
Andrey Antukh
7bc29c22ed Merge remote-tracking branch 'origin/develop' into staging 2025-07-21 21:07:24 +02:00
Andrey Antukh
1d550eaa18 Merge remote-tracking branch 'origin/staging' into develop 2025-07-21 21:03:19 +02:00
Andrey Antukh
b71ec4bfe0 Simplify docker build script (#6924) 2025-07-21 20:45:03 +02:00
Andrey Antukh
827bbf6a7f Merge pull request #6926 from penpot/juanfran-close-libraries-modal-on-esc
🐛 Fix ESC key not closing Add/Manage Libraries modal
2025-07-21 15:48:40 +02:00
Juanfran
2db0cc0cbf 🐛 Fix ESC key not closing Add/Manage Libraries modal 2025-07-21 15:23:54 +02:00
Andrey Antukh
42ef01b339 Merge pull request #6871 from penpot/niwinz-develop-login-enhancements
 Allow login dialog on settings
2025-07-21 15:19:06 +02:00
Aitor Moreno
fdaef2be69 Merge pull request #6891 from penpot/elenatorro-test-style-decoration-blending
🔧 Add text decoration styles
2025-07-21 15:18:18 +02:00
Pablo Alba
ae3213f5d4 🐛 Fix text override corner case 2025-07-21 12:40:03 +02:00
Andrey Antukh
6dfd05fdd1 Merge remote-tracking branch 'origin/staging' into develop 2025-07-21 12:05:24 +02:00
Andrey Antukh
51107c3fc9 🐛 Fix incorrect event name on event constructor 2025-07-21 11:58:48 +02:00
Andrey Antukh
b6863efb3a Merge pull request #6874 from penpot/xaviju-11355-tokens-import-details-layout
 Improve legibility on import token notification details
2025-07-21 11:54:08 +02:00
Andrey Antukh
799bceb8b7 🐛 Check if profile is logged-in on subscriptions internal redirects 2025-07-21 11:40:31 +02:00
Andrey Antukh
9e573128c1 🐛 Fix incorrect event name on event constructor 2025-07-21 11:40:31 +02:00
Andrey Antukh
1f05511add Allow login dialog on settings 2025-07-21 11:40:30 +02:00
Elena Torro
eeee52a738 🐛 Ensure line height is properly handled on line breaks 2025-07-21 11:37:56 +02:00
Xavier Julian
7f53860296 📎 Add warning on feature flag temporary fix for font-size tokens 2025-07-21 11:23:27 +02:00
Andrey Antukh
16d0077393 Merge pull request #6920 from penpot/mdbenito-feature/wheel-scrolling-for-templates
 Enable wheel scrolling over templates-section in the dashboard
2025-07-21 11:22:47 +02:00
Andrey Antukh
622fed2f0d 💄 Add minor formating enhancements to dashboard templates ui code 2025-07-21 10:39:50 +02:00
Andrey Antukh
d22ade3289 Remove duplicated code 2025-07-21 10:38:18 +02:00
Miguel de Benito Delgado
7febf330ac Enable wheel scrolling over templates-section in the dashboard 2025-07-21 10:34:50 +02:00
Andrey Antukh
75a50ac1ac Merge pull request #6912 from penpot/andy-highlight-font-selector
 Highlight first font in font selector search, apply on Enter/click
2025-07-21 10:33:53 +02:00
Andres Gonzalez
e62567d09e Highlight first font in font selector search, apply on Enter/click
[Taiga #11579](https://tree.taiga.io/project/penpot/issue/11579)

 Highlight first font in font selector search, apply on Enter/click
2025-07-21 10:13:36 +02:00
Andrey Antukh
8d80eebeb1 Merge pull request #6906 from penpot/andy-enhance-text-auto-resize
 Switch auto-width to auto-height on horizontal resize on text shapes
2025-07-21 10:11:35 +02:00
Andres Gonzalez
ee9a42238d Switch auto-width to auto-height on horizontal resize on text shapes 2025-07-21 09:56:45 +02:00
Andrey Antukh
758c76d661 Merge pull request #6905 from penpot/andy-enhance-text-resize-behavior
 Allow double-click on text bounding box to set auto-width/auto-height
2025-07-21 09:55:18 +02:00
Andrey Antukh
1dec46cbfa Merge pull request #6903 from penpot/superalex-fix-page-duplication
🐛 Fix error on validating file referential integrity when duplicating a page
2025-07-21 09:46:12 +02:00
Andrey Antukh
ae25d704c1 📎 Add missing use-fn hook 2025-07-21 09:32:44 +02:00
Andres Gonzalez
e05f8c0329 Improve text layer resize behavior
Text layers now only switch to fixed grow-type on vertical resize, not on horizontal resize, for a more intuitive UX. See #4602.
2025-07-21 09:27:42 +02:00
Alejandro Alonso
ce62e11626 🐛 Fix error on validating file referential integrity when duplicating a page 2025-07-21 09:26:23 +02:00
Andrey Antukh
9f04c2fc1d Merge pull request #6901 from penpot/superalex-hide-bb-when-editing-effects
 Hide bounding box while editing visual effects
2025-07-21 09:23:18 +02:00
Andrey Antukh
05a405a82d Merge pull request #6893 from penpot/xaviju-11144-copy-color-attr
 Keep color data when copying from info tab into CSS
2025-07-21 09:22:57 +02:00
Andrey Antukh
3c8c21c378 Merge pull request #6899 from abedef/patch-1
📚 Fix broken link in self-hosting docs
2025-07-21 09:19:39 +02:00
Xavier Julian
2dbeb884a5 Keep color data when copying from info tab into CSS 2025-07-21 09:07:20 +02:00
Andrey Antukh
931d72b41f Merge pull request #6887 from dfelinto/fix-trackpad-swipe
🐛 Fix touchpad swipe back/forward #4246
2025-07-21 08:58:32 +02:00
Alejandro Alonso
2e3cdd872c Revert " Highlight first found font in font list when searching [Taiga #3204]"
This reverts commit 55a13c3139.
2025-07-17 13:01:24 +02:00
Andres Gonzalez
55a13c3139 Highlight first found font in font list when searching [Taiga #3204]
This enhancement highlights the first found font in the font list when searching, and allows pressing Enter to select it, for a more intuitive font selection experience.

See [Taiga #3204](https://tree.taiga.io/project/penpot/issue/3204).
2025-07-17 12:09:50 +02:00
Andrey Antukh
f63d1c87e3 Merge pull request #6904 from penpot/andy-fix-email-change-message
 Update email change confirmation message for clarity
2025-07-17 11:31:21 +02:00
Alejandro Alonso
abbfd44534 Hide bounding box while editing visual effects 2025-07-17 09:33:10 +02:00
Andres Gonzalez
f772724f9a Update email change confirmation message for clarity 2025-07-16 10:22:53 +02:00
Andrey Antukh
f3abd0f190 Merge pull request #6902 from penpot/andy-clarify-invite-member-message
 Clarify invite member message for existing team members
2025-07-15 15:48:45 +02:00
Andres Gonzalez
5d4042c861 Clarify invite member message for existing team members
Update the English message shown when inviting team members whose emails are already part of the team, as suggested in issue #6785.
2025-07-15 14:05:20 +02:00
Dalai Felinto
1fbcec98fb 🐛 Fix touchpad swipe back/forward #4246
This prevents the browser to take over the trackbad swipe gesture both
for the dashboard and the workspace.

At an early attempt I did get the code to work only for the workspace,
but it is too unreliable and I could every now and then get it to misbehave.

I believe it is better to be safe and always prevent the browser from
going back/forth, regardless of workspace/dashboard.

Signed-off-by: Dalai Felinto <dalai@blender.org>
2025-07-15 00:24:20 +02:00
Alejandro Alonso
abef9f3cf7 Merge pull request #6889 from penpot/niwinz-staging-bugfix
🐛 Fix unexpected exception on processing old texts
2025-07-14 07:08:31 +02:00
Abed Fayyad
6f1958f9f2 📚 Fix broken link in self-hosting docs
Replaced broken Markdown link to the unofficial self-hosting section.

Signed-off-by: Abed Fayyad <yo@abedef.ca>
2025-07-13 09:16:13 -04:00
Andrey Antukh
6b2ce86d5f Merge pull request #6896 from penpot/juanfran-issue-show-main-component-focus
🐛 Fix initialize-page namespace when showing main component
2025-07-11 18:31:37 +02:00
Pablo Alba
0cfd70da2e 🐛 Fix corner cases on variants text overrides 2025-07-11 15:28:55 +02:00
Xavier Julian
4167faf39d 📎 Add blend-mode in code editor feature to CHANGELOG 2025-07-11 15:14:29 +02:00
Pablo Alba
90e6e8c5eb 🐛 Fix double undo on text partial overrides 2025-07-11 15:05:30 +02:00
Andrey Antukh
e2c5a1378e Merge pull request #6724 from penpot/elenatorro-improve-create-profile-command
🔧 Add option to skip tutorial/walkthrough when creating a profile from the script
2025-07-11 14:15:49 +02:00
Xavier Julian
81f99458e5 📎 Add new font-size token type to CHANGELOG 2025-07-11 14:09:39 +02:00
Elena Torro
b40b1fa2e4 🔧 Refactor ParagraphBuilder and fix auto height 2025-07-11 13:29:22 +02:00
Juanfran
bb1ec109d8 🐛 Fix initialize-page namespace when showing main component 2025-07-11 13:09:20 +02:00
Florian Schroedl
9c5a13c4ac Enable font-size token 2025-07-11 10:37:17 +02:00
Elena Torro
4c21468850 🔧 Add text decoration styles 2025-07-10 14:26:41 +02:00
Xavier Julian
02ae934e25 📎 Add import tokens from zip file to CHANGELOG 2025-07-10 13:40:42 +02:00
Andrey Antukh
95cfb26b38 Merge pull request #6882 from penpot/xaviju-11283-info-tab-visibility-attrs-review
♻️ Fix tab info not updating and suggested code refactor
2025-07-10 11:56:38 +02:00
Andrey Antukh
935c22d124 Merge pull request #6885 from penpot/marina-change-text-capitalize
🐛 Fix title button from Title case to Capitalize
2025-07-10 11:55:50 +02:00
Marina López
ba6a02d1d9 🐛 Add fixes from subscription design review (#6870)
* 🐛 Fixes from subscription design review

* 🐛 Fix to consider professional plan the unpaid and canceled status

* 📎 Fixes PR feedback
2025-07-10 11:55:16 +02:00
Xavier Julian
0b681effe7 ♻️ Fix tab info not updating and suggested code refactor 2025-07-10 11:38:53 +02:00
Marina López
6826db8498 🐛 Fix title button from Title case to Capitalize 2025-07-10 11:29:48 +02:00
Andrey Antukh
66c5841d48 Merge pull request #6886 from penpot/alotor-fix-create-layout
🐛 Fix problem when creating a layout from an existing layout
2025-07-10 11:28:19 +02:00
Xavier Julian
af10705b4c ♻️ Review import message text 2025-07-10 10:18:59 +02:00
Andrey Antukh
40c300fa1a 🐛 Fix unexpected exception on processing old texts 2025-07-10 09:22:00 +02:00
Pablo Alba
41146ef71d 🐛 Fix text overrides when there are structure changes 2025-07-09 21:58:01 +02:00
Pablo Alba
abb6aee57d 🐛 On texts overrides, keep also vertical-align property 2025-07-09 21:58:01 +02:00
alonso.torres
aa01d3b707 🐛 Fix problem when creating a layout from an existing layout 2025-07-09 15:44:15 +02:00
alonso.torres
a003687256 🐛 Fix problem with grid assignments 2025-07-09 14:55:14 +02:00
Elena Torro
e2b55d814b 🐛 Fix select all deletion error on Firefox 2025-07-09 14:50:35 +02:00
Andrey Antukh
51a6d61be6 Merge pull request #6865 from penpot/xaviju-11283-info-tab-visibility-attrs
 Add visibility group and attributes to info tab
2025-07-09 12:18:10 +02:00
Xavier Julian
0daa8be0b5 Add visibility group and attributes to info tab 2025-07-09 11:19:30 +02:00
Andrey Antukh
00599f76d0 Merge pull request #6875 from penpot/ladybenko-fix-devenv-mac-ubuntu
🔧 Fix building and running devenv (Mac / Linux)
2025-07-09 08:28:49 +02:00
Belén Albeza
cb8aae4d5f 🔧 Drop the -R in chown (dockerfile mac) 2025-07-08 15:45:34 +02:00
Belén Albeza
927228fc8f 🔧 Remove COPY of apt.sources (linux issue) 2025-07-08 15:44:42 +02:00
Xavier Julian
77a47e4b2b Improve legibility on import token notification details 2025-07-08 15:09:50 +02:00
Andrés Moya
88bb9bfe52 🐛 Detach styles from assets when applying tokens 2025-07-08 13:15:45 +02:00
Andrey Antukh
e554b9fcb7 Merge remote-tracking branch 'origin/staging' into develop 2025-07-08 11:04:29 +02:00
Aitor Moreno
4548310235 Merge pull request #6867 from penpot/azazeln28-fix-missing-solid-color
🐛 Fix missing required SolidColor
2025-07-08 09:11:12 +02:00
Aitor Moreno
ea9261b0b2 🐛 Fix missing required SolidColor 2025-07-08 08:45:03 +02:00
Aitor Moreno
6ffcd58368 Merge pull request #6846 from penpot/alotor-wasm-refactor-mut-2
♻️ Refactor wasm shapes state management
2025-07-08 08:31:15 +02:00
alonso.torres
69135ef8c7 ♻️ Refactor wasm shapes state management 2025-07-08 08:30:40 +02:00
Aitor Moreno
747427daa4 Merge pull request #6841 from penpot/superalex-fix-frame-clipping
🐛 Fix frame clipping
2025-07-08 08:26:48 +02:00
Alejandro Alonso
5b704faf79 Merge pull request #6862 from penpot/niwinz-develop-minor-fixes
 Add several improvements
2025-07-07 15:40:20 +02:00
Andrey Antukh
d24eab7241 📎 Update changelog 2025-07-07 15:07:07 +02:00
Andrey Antukh
c8fef97598 Add missing field on get-teams rpc method 2025-07-07 13:36:00 +02:00
Andrey Antukh
44e3e4a641 🔥 Remove image shape inspect pannel
Image shapes are long ago deprecated not used
on penpot
2025-07-07 13:36:00 +02:00
Andrey Antukh
f3616c68a0 Improve decode empty string for path content 2025-07-07 13:36:00 +02:00
Andrey Antukh
9ea3f81bc4 🐛 Clean invalid library colors 2025-07-07 13:35:59 +02:00
Pablo Alba
cfec023585 ♻️ Rename flag :component-swap to :allow-altering-copies 2025-07-07 12:07:36 +02:00
Pablo Alba
469d47eaf3 🐛 Fix variants combobox and select to new options format 2025-07-07 11:46:50 +02:00
Alejandro Alonso
51bb6583d2 🐛 Fix frame clipping 2025-07-07 11:09:29 +02:00
Pablo Alba
a44c70ef69 Keep the swapped childs if the copies when doing a variant switch 2025-07-07 10:50:49 +02:00
Andrés Moya
4fddf34a73 🐛 Fix error when there exists a tokens lib with no sets 2025-07-07 10:02:49 +02:00
Xavier Julian
8f840daa91 Improve token import error copy 2025-07-07 09:59:57 +02:00
Juanfran
0a7d6d98e1 Integrate plugin runtime as npm library (#6852) 2025-07-07 09:46:07 +02:00
Álvaro Tejero-Cantero
bcb69b6227 🐛 Restore viewport and selection when exiting focus mode (#6827)
* 📚 Provide guidance on how to exit focus mode

* 🐛 Restore viewport & selection post focus mode

* 📎 Update changelog
2025-07-07 09:44:06 +02:00
Andrey Antukh
92d708d52c Merge remote-tracking branch 'origin/staging' into develop 2025-07-07 09:37:55 +02:00
Alonso Torres
accd5226d7 🐛 Fix sidebar width in localhost (#6732) 2025-07-07 09:28:52 +02:00
Andrey Antukh
16a1fd14e5 🐛 Fix media translation on text nodes on paste (#6845)
Fix incorrect media translation on paste text with fill images
2025-07-07 09:03:35 +02:00
Aitor Moreno
824bb19c7e Merge pull request #6848 from penpot/niwinz-staging-library-referer
 Add referer field to binfile v3
2025-07-07 09:02:13 +02:00
Aitor Moreno
d0f3e0f0b0 Merge pull request #6853 from penpot/niwinz-staging-path-bool-fixes
🐛 Fix exception on a corner case of creating bool shape
2025-07-07 09:00:57 +02:00
Andrey Antukh
43ba2b05e8 📎 Change current config values for error report explain 2025-07-04 14:51:08 +02:00
Andrey Antukh
d5ccb704b2 🐛 Fix unexpected exception on creating bool shapes 2025-07-04 14:42:09 +02:00
Andrey Antukh
0374e4f3eb Merge remote-tracking branch 'origin/staging' into develop 2025-07-04 12:02:12 +02:00
David Barragán Merino
6d21fcc9de 🔧 Fix condition for automatic events (#6849) 2025-07-04 11:57:57 +02:00
Andrey Antukh
77741b49a7 Add tracking for referer on the import-binfile 2025-07-04 11:02:36 +02:00
Andrey Antukh
a7e0cfc609 🎉 Bump 1.0.7 release of the penpot library
Includes the ability to pass referer
2025-07-04 11:02:36 +02:00
Andrey Antukh
50a6355537 🎉 Add options for creating library build context
With the ability to pass referer.
2025-07-04 11:02:36 +02:00
Alejandro Alonso
264aef277d Merge pull request #6847 from penpot/niwinz-staging-error-reports-2
 Add minor improvements to error report on calc bool content
2025-07-04 10:53:02 +02:00
Andrey Antukh
78d0e6d059 Add minor improvements to error report on calc bool content 2025-07-04 10:13:24 +02:00
Alonso Torres
6d41d36b3a 🐛 Fix problem when double click on hidden shapes (#6833) 2025-07-04 09:01:20 +02:00
David Barragán Merino
bb97df373e 🔧 Add Github Action to build and upload artifact (#6840)
Co-authored-by: Francis Santiago <francis.santiago@kaleidos.net>
2025-07-04 08:41:46 +02:00
David Barragán Merino
528c819323 🔧 Add Github Action to build and upload artifact (#6840)
Co-authored-by: Francis Santiago <francis.santiago@kaleidos.net>
2025-07-04 08:25:23 +02:00
Florian Schrödl
21746144b7 Add letter spacing token (#6814)
* 🐛 Fix merge schema not working with key generation

*  Add letter-spacing token

* ♻️ Remove comments

* ♻️ Inline line-height for now
2025-07-03 16:00:58 +02:00
Andrey Antukh
3165761bac Merge remote-tracking branch 'origin/staging' into develop 2025-07-03 15:32:30 +02:00
Andrés Moya
c09f72c3d5 🐛 Sanitize wrong ids in token themes (#6843) 2025-07-03 15:31:45 +02:00
Alejandro Alonso
a41af032cd Merge pull request #6844 from penpot/niwinz-staging-enhancements
 Improve error reporting
2025-07-03 15:31:20 +02:00
Andrey Antukh
86ee4f55c5 📚 Update docstring 2025-07-03 14:54:00 +02:00
Andrey Antukh
63cd3ae025 Add better error handling for bool creation 2025-07-03 14:54:00 +02:00
Andrey Antukh
cafb7abb53 🎉 Add better syntax facility for ex/try! macro 2025-07-03 14:54:00 +02:00
Andrey Antukh
e5b6c4a9e0 Add minor improvement to error reporter logger 2025-07-03 14:54:00 +02:00
Andrey Antukh
1d5bad5523 💄 Report file-id on file changes exception 2025-07-03 14:54:00 +02:00
Andrey Antukh
96d6868b45 🐛 Add missing fields on get-team-shared-files query 2025-07-03 14:54:00 +02:00
Andrey Antukh
b739d8bd0c 💄 Change default depth on params for error reports 2025-07-03 14:54:00 +02:00
Alejandro Alonso
dd803dc1de Merge pull request #6839 from penpot/niwinz-staging-fix-broken-path
🐛 Add migration for fix undecoded path content
2025-07-03 13:43:59 +02:00
Florian Schrödl
7dd61968b5 Implement object type specific tokens (#6816)
*  Allow token applying for supported shape types only

* 🐛 Remove x/y attribute keys from spacing token

*  Shape specific context-menu

*  Only apply tokens to supported shapes when doing multi selection apply

*  Handle groups not supported by tokens yet

* 🐛 Fix outdated tests

* ♻️ Commentary

*  Add helper functions for attribute applicability checks

* ♻️ Groups don't have own attributes

* ♻️ Remove unused function

* ♻️ Move attribute logic to common.types.token
2025-07-03 12:22:04 +02:00
Juanfran
669d6d9ae2 Merge pull request #6837 from penpot/juanfran-us-11186-rules-help
 Add in-app help to guide users about variant rules
2025-07-03 11:30:16 +02:00
Andrey Antukh
b627c10737 🔥 Remove duplicated check-fn 2025-07-03 10:50:09 +02:00
María Valderrama
95f4a9bd29 Add missing start-plugin event (#6809)
*  Add missing start-plugin event

* 📎 Correct event origin
2025-07-03 10:29:43 +02:00
Miguel de Benito Delgado
b931547300 🐳 Add "postgres" network alias to default docker network in devenv (#6823) 2025-07-03 10:28:53 +02:00
Andrey Antukh
a2b8f19ff3 🐛 Add migration for fix undecoded path content 2025-07-03 08:40:23 +02:00
Belén Albeza
30274c4f5c 🔧 Restore arm64 build of devenv (#6826) 2025-07-03 08:28:07 +02:00
Andrés Moya
0a71134652 🔧 Sanitize and check tokens when deserializing from db (#6838) 2025-07-02 17:01:10 +02:00
Juanfran
72b1919e29 Add in-app help to guide users about variant rules 2025-07-02 14:46:36 +02:00
Andrey Antukh
898182e3d5 Add minor events props normalization (#6836) 2025-07-02 14:41:48 +02:00
Xavier Julian
be43365909 🐛 Fix broken import file type drodown options 2025-07-02 14:35:01 +02:00
Andrey Antukh
41994703a9 ♻️ Refactor tab-switcher* component (#6815)
* 💄 Add minor style adjustments to workspace sidebar

* 💄 Add style enhacement to sitemap component

* ♻️ Refactor tab-switcher* component
2025-07-02 14:08:47 +02:00
Marina López
3d45080e3c 🐛 Fixes from subscription design review (#6812) 2025-07-02 10:49:16 +02:00
Miguel de Benito Delgado
28c055e3f9 📚 Fix and extend backend repl doc (#6819) 2025-07-02 10:38:35 +02:00
Prithvi Tharun
4f993bf4ae 💄 Replace 'Verify new email' label with 'Confirm new email' (#6831)
Improves clarity by using more accurate and familiar terminology.

Signed-off-by: Prithvi Tharun <ptrithu8@gmail.com>
2025-07-02 10:32:09 +02:00
Alejandro Alonso
3cb0e1b6ee 🐛 Fix exif rotation detection when auto-rotation isn't supported (#6818) 2025-07-02 10:31:05 +02:00
Miguel de Benito Delgado
e03c822b51 🐛 Fix internal error on missing theme setting in profile (#6822) 2025-07-02 10:17:22 +02:00
Andrey Antukh
1432b211a6 Merge remote-tracking branch 'origin/staging' into develop 2025-07-02 10:13:30 +02:00
Miguel de Benito Delgado
3e45e4fb25 🐛 Fix internal error on missing theme setting in profile (#6822) 2025-07-02 09:57:56 +02:00
Eva Marco
a3aabf3b7d 🐛 Fix tooltip position after click (#6830) 2025-07-02 09:56:14 +02:00
Andrés Moya
953287ea33 🐛 Avoid crash in combobox with empty options 2025-07-02 08:57:25 +02:00
Elena Torró
493831f110 Merge pull request #6821 from penpot/alotor-refactor-mutability
♻️ Refactor mutability modifiers in wasm
2025-07-01 13:52:39 +02:00
alonso.torres
3d374e8e97 ♻️ Refactor mutability modifiers in wasm 2025-07-01 12:47:31 +02:00
Andrés Moya
f0f01af55c 🔧 Make TokenSet an abstract data type 2025-06-30 16:59:00 +02:00
Xavier Julian
6de9de9e38 Add new metric for token update and provide token type 2025-06-30 13:21:49 +02:00
Kelp
b893a62e40 Add new typography icon to the DS (#6808)
Signed-off-by: Kelp <5446186+NatachaMenjibar@users.noreply.github.com>
2025-06-30 11:06:54 +02:00
alonso.torres
8dcb376b18 Add drop grid cells in wasm 2025-06-30 10:28:59 +02:00
alonso.torres
52a4fc6030 🐛 Fix drop index on flex layout wasm 2025-06-30 10:28:59 +02:00
Andrey Antukh
403d92838a ♻️ Add minor refactor to options dropdown options handling and validation (#6739)
* ♻️ Refactor options-dropdown* and related components

* 🐛 Fix props error

* 🐛 Fix test

* 📎 Update rumext

---------

Co-authored-by: Eva Marco <evamarcod@gmail.com>
2025-06-29 11:52:29 +02:00
Xavier Julian
6bd3253e5e ♻️ Restructure UI files for tokens editor 2025-06-27 13:23:42 +02:00
Pablo Alba
20b5b7f6e4 🐛 Fix variant switch in another page (#6802) 2025-06-27 12:23:54 +02:00
Andrés Moya
5c4fd97541 🐛 Allow importing file without any token but with themes or sets (#6796) 2025-06-27 11:32:14 +02:00
Pablo Alba
804146ae9a 🐛 Fix text partial change doesn't show up on another page (#6799) 2025-06-27 10:21:21 +02:00
Juanfran
24e78e6a10 🐛 Display error message on register form (#6797) 2025-06-27 10:01:54 +02:00
Pablo Alba
daca26e54f 🐛 On variants override use the component name instead of the copy name 2025-06-26 17:37:21 +02:00
Aitor Moreno
29016cef49 Merge pull request #6794 from penpot/alotor-wasm-fix-grid-fr
🐛 Fix problem with fr allocation
2025-06-26 14:39:42 +02:00
alonso.torres
fb07788e8f 🐛 Fix problem with fr allocation 2025-06-26 13:17:26 +02:00
Alejandro Alonso
3010abbf64 Merge pull request #6793 from penpot/alotor-fix-plugins-system-theme
🐛 Fix problem with plugins on system theme
2025-06-26 12:30:51 +02:00
alonso.torres
e6a7eed7a9 🐛 Fix problem with plugins on system theme 2025-06-26 12:15:06 +02:00
Andrey Antukh
c75a617d26 Merge remote-tracking branch 'origin/staging' into develop 2025-06-26 11:19:29 +02:00
Andrey Antukh
f2c4a1eb1f Merge pull request #6674 from penpot/niwinz-develop-enhacements-3
 Refactor fills-menu and related components
2025-06-26 11:09:30 +02:00
Marina López
62371fded0 🐛 Fix libraries position in dashboard sidebar (#6791) 2025-06-26 11:08:18 +02:00
Alejandro Alonso
daf3b5caa8 🐛 Fix slow color picker (#6780) 2025-06-26 11:07:35 +02:00
Andrey Antukh
e72d31a082 🔥 Remove unused and commented code 2025-06-26 10:50:38 +02:00
Andrey Antukh
6b4a85cd15 🐛 Fix issue on changing from gradient to solid color on colorpicker 2025-06-26 10:50:38 +02:00
Andrey Antukh
027a7a457d Add minor style improvements for reorder-handler component 2025-06-26 10:50:38 +02:00
Andrey Antukh
20d2d22f39 Add performance oriented refactor to fill-menu component 2025-06-26 10:50:36 +02:00
Andrey Antukh
34d65ed1c8 Merge pull request #6775 from penpot/superalex-fix-entering-long-project-name
🐛 Fix entering long project name
2025-06-26 10:48:54 +02:00
Andrey Antukh
a191fe63a1 Merge remote-tracking branch 'origin/staging' into develop 2025-06-26 09:18:23 +02:00
luisδμ
2de0c90fc7 🐛 Remove empty properties starting with the last one (#6757)
* 🐛 Remove empty properties starting with the last one

*  MR changes

---------

Co-authored-by: Pablo Alba <pablo.alba@kaleidos.net>
2025-06-26 09:16:59 +02:00
Alejandro Alonso
27c624ae0f Merge pull request #6787 from penpot/niwinz-staging-hotfix-4
🐛 Several fixes
2025-06-26 09:13:49 +02:00
Andrey Antukh
3831b3034e 🐛 Fix boolean shape migration that causes issues on import 2025-06-26 08:55:09 +02:00
Luis de Dios
7cd0e28c3b Allow variants with no properties 2025-06-26 08:42:34 +02:00
Andrey Antukh
00390a1349 🐛 Add correct is-text-node? predicate to text processing methods 2025-06-26 08:32:11 +02:00
Andrey Antukh
17bfed137c 📎 Add better defaults for text processing on old migrations 2025-06-26 08:32:11 +02:00
Andrey Antukh
77ef26b207 📎 Add srepl script for validate file schema 2025-06-26 08:32:11 +02:00
Andrey Antukh
26239a15f2 📎 Add missing changes on lost-colors fix script 2025-06-25 20:13:35 +02:00
Andrey Antukh
25ef1800d0 Merge remote-tracking branch 'origin/staging' into develop 2025-06-25 19:30:57 +02:00
Andrey Antukh
207974fe6c Add minor improvement to color cleaning migration 2025-06-25 19:26:43 +02:00
Andrey Antukh
b52e2fa681 🐛 Add missing version field on get-team-shared-files internal query 2025-06-25 19:24:18 +02:00
Andrey Antukh
bf719b587f Add better shadow cleaning migration 2025-06-25 19:17:58 +02:00
Alejandro Alonso
61109c91e3 Merge pull request #6784 from penpot/niwinz-staging-hotfix-3
🐛 Fix incorrect library color cleaning mechanism
2025-06-25 16:21:58 +02:00
Andrey Antukh
4915a97c2c 📎 Add script for restoring lost colors 2025-06-25 16:10:35 +02:00
Andrey Antukh
903aba5642 🐛 Fix incorrect library color cleaning mechanism 2025-06-25 14:36:33 +02:00
Andrey Antukh
9760911fce Merge remote-tracking branch 'origin/staging' into develop 2025-06-25 14:24:26 +02:00
Alejandro Alonso
82583f5079 🐛 Fix entering long project name 2025-06-25 14:21:52 +02:00
Alejandro Alonso
4561392791 🐛 Fix shortcut error pressing G+W from the View Mode (#6772) 2025-06-25 14:14:44 +02:00
Marina López
f81a973a4d 🐛 Fix text decoration line through value in inspect tab (#6778) 2025-06-25 14:11:58 +02:00
Alejandro Alonso
ca99671d3c 📚 Update CHANGES with support for exif rotated images (#6782) 2025-06-25 14:10:13 +02:00
Alejandro Alonso
8e8b2acddd Merge pull request #6781 from penpot/niwinz-staging-hotfix-2
🐛 Hot fixes
2025-06-25 13:53:58 +02:00
Marina López
1f42f032fc 🐛 Add fixes for subscription design review (#6751)
* 🐛 Fix from subscription design review

* 📎 Fixes PR feedback
2025-06-25 13:41:45 +02:00
Andrey Antukh
93cbd99932 🐛 Clear invalid keys from color libraries 2025-06-25 13:38:35 +02:00
Andrey Antukh
15c91a5de5 Make the bool-content normalize migration idempotent 2025-06-25 13:26:32 +02:00
Andrey Antukh
7f2e819789 🐛 Fix migration persistence ordering issue
When migrations are applied to old files
2025-06-25 13:26:25 +02:00
Alejandro Alonso
4947bf480b Merge pull request #6779 from penpot/niwinz-staging-hotfix-2
🐛 Fix regression on changing color type on fills
2025-06-25 12:27:34 +02:00
Marina López
67ca8ccb22 🐛 Fix copy font-size doesn't copy the unit (#6776) 2025-06-25 12:14:33 +02:00
Alejandro Alonso
c51ae35fc5 Merge pull request #6777 from penpot/niwinz-staging-hotfix-1
🐛 Remove qualified keyword keys from colors
2025-06-25 12:13:53 +02:00
Andrey Antukh
81564dbfa9 🐛 Fix regression on changing color type on fills 2025-06-25 12:12:04 +02:00
Andrey Antukh
56472a95de 🐛 Add missing file migration to get-team-shared-files rpc method 2025-06-25 11:56:11 +02:00
Andrey Antukh
9e5bc3675c 🐛 Remove cider nrepl handler from default nrepl server 2025-06-25 11:41:24 +02:00
Xavier Julian
ce59070fd1 ♻️ Restructure UI files for token sets 2025-06-25 11:27:13 +02:00
Andrey Antukh
787c066357 🐛 Remove qualified keyword keys from colors 2025-06-25 11:23:39 +02:00
Marina López
82bedda604 Add tokens library to dashboard carousel (#6769) 2025-06-25 10:22:19 +02:00
Marina López
e258030bc0 💄 Change 'save color' button (#6774) 2025-06-25 10:21:22 +02:00
Alejandro Alonso
8f00292f8f 🎉 Support for exim rotated images (#6767) 2025-06-25 10:20:37 +02:00
Alejandro Alonso
1b67be2f36 Merge pull request #6773 from penpot/niwinz-staging-paste-regression
🐛 Fix minor regression on paste shapes with fill-image
2025-06-25 10:02:36 +02:00
Andrey Antukh
1a8a9df2b7 🐛 Fix minor regression on paste shapes with fill-image 2025-06-25 09:40:17 +02:00
Alejandro Alonso
e1ce7ec787 Merge pull request #6752 from penpot/niwinz-staging-path-editor-fixes
🐛 Fix incorrect path tool handling on shapes not coerced to path
2025-06-25 07:25:13 +02:00
Andrey Antukh
546b7d5f60 🐛 Fix incorrect path tool handling on shapes not coerced to path 2025-06-24 19:09:38 +02:00
Florian Schroedl
fe91201431 Keep warning for unsupported token types when FF is disabled 2025-06-24 15:41:24 +02:00
Florian Schroedl
00c7411f92 🐛 Fix dtcg token type name 2025-06-24 15:41:24 +02:00
Xavier Julian
e585cbd673 ♻️ Restructure UI files for import/export and common files 2025-06-24 13:58:54 +02:00
Alejandro Alonso
bdc10ac173 Merge pull request #6754 from penpot/azazeln28-issue-11401-fix-wrong-aspect-ratio
🐛 Fix image aspect ratio rendering on oriented images
2025-06-24 13:23:35 +02:00
Elena Torró
9f5cb61a19 Merge pull request #6766 from penpot/elenatorro-fix-text-auto-height
🐛 Fix text auto height
2025-06-24 13:18:28 +02:00
Alejandro Alonso
fb6121bf92 Merge pull request #6765 from penpot/alotor-update-plugins-runtime
⬆️ Update plugins runtime
2025-06-24 13:14:53 +02:00
Alejandro Alonso
e442d8adad Add tests for exif rotated images 2025-06-24 13:08:18 +02:00
Elena Torro
925af4e1e9 🐛 Fix text auto height 2025-06-24 12:36:12 +02:00
alonso.torres
a45886c86c Small cosmetic change 2025-06-24 10:26:37 +02:00
alonso.torres
36b6f6323a ♻️ Refactor modifiers methods 2025-06-24 10:26:37 +02:00
alonso.torres
afec3b9bc1 🐛 Fix problem with margin in flex layout 2025-06-24 10:26:37 +02:00
alonso.torres
ac6a814026 🐛 Fix problem with flex layout in wasm 2025-06-24 10:26:37 +02:00
Alejandro Alonso
89fb802362 Merge pull request #6764 from penpot/alotor-fix-problem-lines
🐛 Fix wasm problem with horizontal/vertical lines
2025-06-24 09:43:11 +02:00
alonso.torres
8cdcfb70e2 ⬆️ Update plugins runtime 2025-06-24 09:25:12 +02:00
alonso.torres
b0d858df2b 🐛 Fix wasm problem with horizontal/vertical lines 2025-06-24 09:24:00 +02:00
Aitor Moreno
f54497194a Merge pull request #6762 from penpot/elenatorro-10901-add-text-vertical-alignment
🔧 Add vertical alignment for text shapes
2025-06-23 17:05:47 +02:00
Elena Torro
134fb1ab4c 🔧 Add vertical alignment for text shapes 2025-06-23 16:45:25 +02:00
andrés gonzález
8c2dc1f22d 📚 Add DT import/export options to the docs (#6753) 2025-06-23 15:37:57 +02:00
Aitor Moreno
833546d754 🐛 Fix wrong aspect ratio on oriented image 2025-06-23 15:30:01 +02:00
Elena Torró
0010d61ae2 Merge pull request #6758 from penpot/elenatorro-text-rendering-fixes-and-tests
🔧 Add tests to cover text styles
2025-06-23 14:06:19 +02:00
Elena Torro
747f72be47 🔧 Add tests to cover text styles 2025-06-23 13:43:09 +02:00
Alejandro Alonso
1882efe3f7 🐛 Fix paths rendered initially ony in tile 0 0 2025-06-23 12:23:49 +02:00
Florian Schrödl
580bb46a05 Implement font-size token type (#6708)
*  Implement font-size token type

*  Hide typography tokens behind FF

* 💄 Update icon

* 🔧 Add font-size to unapply check

* ♻️ Generalize status-icon logic and remove icon for font-size
2025-06-23 12:12:40 +02:00
Alejandro Alonso
9ea0875e65 Merge pull request #6742 from penpot/ladybenko-fix-wasm-debug-text-hi-dpr
 Fix size of 'wasm renderer' debug text on dpr > 1
2025-06-23 11:47:20 +02:00
Alejandro Alonso
43b19ba33e Merge pull request #6738 from penpot/ladybenko-11247-enable-dpr-when-render-wasm
🔧 Enable render-wasm-dpr by default
2025-06-23 11:46:24 +02:00
Andrey Fedorov
130cd52f79 Notify user if imported file or directory doesn't contain token files 2025-06-23 11:44:00 +02:00
Aitor Moreno
21fd56076c Merge pull request #6756 from penpot/superalex-fix-empty-fills
🐛 Fix empty fills
2025-06-23 11:31:34 +02:00
Alejandro Alonso
c97314ddb5 🐛 Fix empty fills 2025-06-23 11:14:58 +02:00
Andrey Antukh
34bbce5089 Merge remote-tracking branch 'origin/staging' into develop 2025-06-23 10:06:05 +02:00
ºelhombretecla
9a0538e5e3 Add visual indicator for new comments in the workspace (#6728)
* 🎉 Add comment notification to workspace

* 💄 Add info to changelog

*  Add minor efficiency improvements

---------

Co-authored-by: Andrey Antukh <niwi@niwi.nz>
2025-06-23 09:51:41 +02:00
ºelhombretecla
1b041d949c 💄 Add new content for 2.8 release slides (#6729)
* 💄 Add new content for 2.8 release slides

* 📎 Fix linter issues

---------

Co-authored-by: Andrey Antukh <niwi@niwi.nz>
2025-06-23 09:43:55 +02:00
Belén Albeza
56d96aaf07 🔧 Enable render-wasm-dpr by default 2025-06-20 12:48:49 +02:00
Eva Marco
1a8f36562b 🐛 Fix export button width on design tab (#6744) 2025-06-20 12:04:49 +02:00
luisδμ
70f3988046 Show warning when selecting a copy of conflicted variant (#6743) 2025-06-20 11:52:07 +02:00
Andrey Antukh
ec021d944d Merge remote-tracking branch 'origin/staging' into develop 2025-06-20 11:37:50 +02:00
Alejandro Alonso
3d0c3013e5 Merge pull request #6746 from penpot/niwinz-staging-path-editor-fixes
 Add missing fixes to the path edition mode
2025-06-20 11:31:17 +02:00
Elena Torró
f1a6b46165 Merge pull request #6745 from penpot/superalex-bug-fix-text-image-strokes
🐛 Fix image fill strokes are not rendered correctly for texts
2025-06-20 11:14:24 +02:00
Andrey Antukh
3274a74611 Add missing fixes to the path edition mode 2025-06-20 11:06:48 +02:00
Belén Albeza
2412402a23 Fix size of 'wasm renderer' debug text on dpr > 1 2025-06-20 10:55:33 +02:00
Alejandro Alonso
5375029497 🐛 Fix image fill strokes are not rendered correctly for texts 2025-06-20 10:52:26 +02:00
Alejandro Alonso
3a0ac577f8 Merge pull request #6720 from penpot/niwinz-staging-path-editor-fixes
 Fix path edition/drawing state on workspace
2025-06-20 10:34:19 +02:00
Andrés Moya
cf78e68787 🐛 Fix token unapply for text shapes 2025-06-20 10:15:49 +02:00
Aitor Moreno
8bfc314b17 Merge pull request #6700 from penpot/superalex-fix-async-content-rendering
🐛 Fix asynchronous content rendering
2025-06-20 10:11:28 +02:00
Elena Torró
38112e287a Merge pull request #6734 from penpot/ladybenko-11392-no-ui-in-tests
🔧 Make visual regression tests to hide the UI when taking a screenshot (render-wasm tests only)
2025-06-20 09:05:30 +02:00
Alejandro Alonso
43ba30c694 Merge pull request #6741 from penpot/niwinz-staging-join-nodes
🔥 Remove incorrect assert on path segment helper
2025-06-20 08:22:27 +02:00
Andrey Antukh
520ea0e094 🔥 Remove incorrect assert on path segment helper 2025-06-20 08:01:59 +02:00
Alejandro Alonso
5c7a4ce5b7 🐛 Fix fill images for text 2025-06-20 07:45:28 +02:00
Andrey Antukh
0c260c626b Make the path creation flow consistent 2025-06-20 07:41:06 +02:00
Andrey Antukh
db4721f692 Forward path edition state from vieweport to editor 2025-06-20 07:41:06 +02:00
Andrey Antukh
f8d63f5d9d 🐛 Fix incorrect path drawing/edition state management 2025-06-20 07:41:06 +02:00
Andrey Antukh
7e909dfbe8 Merge remote-tracking branch 'origin/staging' into develop 2025-06-19 15:35:19 +02:00
Alonso Torres
7f7f0893d0 🐛 Fix sidebar width in localhost (#6732) 2025-06-19 15:31:27 +02:00
Andrey Antukh
0f46efc117 Merge pull request #6733 from penpot/eva-bugfixing
🐛 Fix some bugs
2025-06-19 15:29:34 +02:00
María Valderrama
22fbc3fa5f 💄 Improve dashboard's sidebar (#6736) 2025-06-19 15:28:32 +02:00
Alejandro Alonso
d71fa659d5 🐛 Fix asynchronous content rendering 2025-06-19 14:03:40 +02:00
Alejandro Alonso
d0425cabda Merge pull request #6721 from penpot/ladybenko-11276-fix-modifiers-dpr
🐛 Fix panning and scroll when dpr > 1 (render wasm)
2025-06-19 14:01:47 +02:00
Eva Marco
909838c8c4 🐛 Fix snap nodes shortcut 2025-06-19 14:01:15 +02:00
Eva Marco
86e36061fb 🐛 Fix multiple values on text 2025-06-19 13:41:35 +02:00
Belén Albeza
9852d24b83 🔧 Make visual regression tests to hide the UI when taking a screenshot (render-wasm tests only) 2025-06-19 13:37:52 +02:00
Alejandro Alonso
2239482049 Merge pull request #6717 from penpot/alotor-grid-editor
 Support grid editor with wasm modifiers
2025-06-19 13:32:27 +02:00
Xavier Julian
4ea4a1e130 ♻️ Restructure UI files for token settings 2025-06-19 13:10:09 +02:00
alonso.torres
11467e26a2 🐛 Fix problem with flex wrap in wasm 2025-06-19 13:03:25 +02:00
alonso.torres
b997d5a320 🐛 Fix problem with grid layout wasm 2025-06-19 13:03:25 +02:00
alonso.torres
5b4cd9f4f1 🐛 Fix problem when moving masks, bools, groups with wasm 2025-06-19 13:03:25 +02:00
alonso.torres
58e5748b4f 🐛 Fix wasm layout problems 2025-06-19 13:03:25 +02:00
alonso.torres
b2647f30c2 Support grid editor with wasm modifiers 2025-06-19 13:03:25 +02:00
Eva Marco
fbdabcd913 🐛 Fix button width 2025-06-19 12:51:53 +02:00
luisδμ
72f2a409f9 Show warning when duplicated variant prop name and value (#6639)
*  Show warning when duplicated variant prop name and value

* 📎 PR changes
2025-06-19 12:34:28 +02:00
Alejandro Alonso
191ea3d02a Merge pull request #6637 from penpot/mavalroot-missing-events
 Add missing user experience events
2025-06-19 12:11:07 +02:00
Xavier Julian
62a6f2c2f1 ♻️ Restructure UI files for theme creation modal 2025-06-19 11:59:25 +02:00
Andrey Antukh
b747ccc382 🎉 Add shortcut helper for creating events 2025-06-19 11:38:08 +02:00
Andrey Antukh
892c9ab12c Add minor code consistency fixes 2025-06-19 11:38:08 +02:00
Eva Marco
b595d5abf8 🐛 Fix radio buttons gap 2025-06-19 11:23:32 +02:00
María Valderrama
cb46d643ac Add missing user experience events 2025-06-19 11:22:58 +02:00
Xavier Julian
105e0ba75f ♻️ Create themes folder and themes root file 2025-06-19 10:53:31 +02:00
Belén Albeza
4a9f6ea04e 🐛 Fix panning and scroll when dpr > 1 (render wasm) 2025-06-19 10:42:19 +02:00
Andrey Antukh
03a82c18cb Merge pull request #6726 from penpot/eva-fix-comment-icon
🐛 Fix comment icon fill
2025-06-19 09:43:02 +02:00
Andrey Antukh
a559547f97 Merge pull request #6727 from penpot/bameda-fix-typo
🐛 Fix a typo
2025-06-19 09:42:35 +02:00
David Barragán Merino
b91d703060 🐛 Fix a typo 2025-06-19 09:34:53 +02:00
luisδμ
e7e39a5521 Avoid duplicated property names adding a number (#6681)
*  Avoid repeated property names appending a number

* 📎 PR changes

* 🐛 Adjust rules for incrementing numbers in prop names
2025-06-19 09:11:41 +02:00
Belén Albeza
70a29c43ec 🔧 Fix race condition in colorpicket gradient tests (#6722) 2025-06-19 08:57:38 +02:00
Eva Marco
7bde3d0ec1 🐛 Fix comment icon fill 2025-06-19 08:51:29 +02:00
Andrey Antukh
386c729507 Merge remote-tracking branch 'origin/staging' into develop 2025-06-19 08:49:11 +02:00
Alejandro Alonso
219dca3ab8 Merge pull request #6723 from penpot/elenatorro-11385-fix-text-gradients
🐛 Fix text fill gradients and add visual regression test for text…
2025-06-19 07:03:19 +02:00
Elena Torro
5c120b601c 🐛 Fix text fill gradients and add visual regression test for text styles 2025-06-18 18:02:28 +02:00
Andrey Antukh
54643b79f6 🐛 Fix exception on changing hex color on colorpicker gradient editor (#6718) 2025-06-18 17:59:14 +02:00
Elena Torro
cf8006ce9c 🔧 Add option to skip tutorial/walkthrough when creating profiles for dev purposes 2025-06-18 17:00:46 +02:00
Kelp
71afccbeb5 Adds new font-size icon to the DS
Signed-off-by: Kelp <5446186+NatachaMenjibar@users.noreply.github.com>
2025-06-18 15:55:13 +02:00
Andrey Antukh
f0b82864dd Merge pull request #6719 from penpot/andy-changelog-update
📚 Update changelog
2025-06-18 15:04:28 +02:00
Andres Gonzalez
29244776f0 📚 Update changelog 2025-06-18 14:11:35 +02:00
Andrey Antukh
bbb9713f97 Merge remote-tracking branch 'origin/staging' into develop 2025-06-18 14:09:49 +02:00
Andrey Antukh
40c33c7dcc Merge pull request #6715 from penpot/alotor-bug-fix-workaround
🐛 Fix problem fetching images
2025-06-18 14:09:29 +02:00
Andrey Antukh
063c6e7771 Merge remote-tracking branch 'origin/staging' into develop 2025-06-18 13:34:47 +02:00
alonso.torres
1a6fcb5daf 🐛 Fix problem fetching images 2025-06-18 13:26:15 +02:00
Andrey Antukh
34febfc833 📎 Update indirect dependencies 2025-06-18 13:20:45 +02:00
Andrey Antukh
2c0abea254 📎 Add missing deps for build wasm tests 2025-06-18 12:45:25 +02:00
Andrey Antukh
4524782282 📎 Adapt backend test to devenv changes 2025-06-18 12:35:58 +02:00
Andrey Antukh
b8b56d5aa4 Merge remote-tracking branch 'origin/staging' into develop 2025-06-18 10:54:17 +02:00
Alejandro Alonso
2a5b087aa4 Merge pull request #6714 from penpot/niwinz-staging-fix-path-edition
🐛 Fix unexpected exception on selectiong node on non path shape
2025-06-18 10:45:36 +02:00
Andrey Antukh
402508a710 Merge remote-tracking branch 'origin/staging' into develop 2025-06-18 10:41:30 +02:00
Alejandro Alonso
1f034654a0 Merge pull request #6705 from penpot/niwinz-staging-docker-improvements
 Major improvement and update to docker images and devenv
2025-06-18 10:39:51 +02:00
Andrey Antukh
88ed08916e Merge remote-tracking branch 'origin/staging' into develop 2025-06-18 10:39:23 +02:00
Andrey Antukh
a9a0970001 Merge pull request #6679 from penpot/niwinz-develop-enhacements-4
 Add editors count to get-owned-teams rpc method response
2025-06-18 10:38:48 +02:00
Andrey Antukh
1576016999 Merge pull request #6711 from penpot/elenatorro-11212-fix-right-sidebar-overflow
🐛 Fix right-sidebar width overflow
2025-06-18 10:38:18 +02:00
Andrey Antukh
5ea515cc9f Merge pull request #6713 from mdbenito/doc/undo-ns
📚 Document app.main.data.workspace.undo
2025-06-18 10:37:42 +02:00
Andrey Antukh
e3cce104e1 🐛 Fix unexpected exception on selectiong node on non path shape 2025-06-18 10:12:24 +02:00
Alejandro Alonso
a24631ac66 Merge pull request #6710 from penpot/niwinz-staging-path-make-curve-point
🐛 Fix incorrect behavior of `make-curve-point` fn
2025-06-18 10:06:28 +02:00
Miguel de Benito Delgado
c0df527b3d 📚 Document app.main.data.workspace.undo 2025-06-18 09:52:15 +02:00
Andrey Antukh
fd81ea6a84 🔥 Remove commented code 2025-06-18 09:46:15 +02:00
Andrey Antukh
a3c7151157 ⬆️ Update indirect exporter module dependencies 2025-06-18 09:46:15 +02:00
Andrey Antukh
2d4fc3e05f ♻️ Refactor devenv build mechanism
This introduces multistage build process for devenv making
different dependencies build depend on its own (per example, when
jvm version is changed, only the jvm stage is rebuild)

This commit also introduces imagemagick 7.x custom build
in the same way as we have on public docker images, so on
devenv we use the same version.
2025-06-18 09:46:15 +02:00
Andrey Antukh
b01dea20d6 Add imagemagick custom build to backend docker image
This allows us be in control of the imagemagick version and not
depend on the version available on the distro repository, which
right now only ships the legacy 6.x version
2025-06-18 09:46:15 +02:00
Andrey Antukh
3f40a830fd Revisit exporter docker image dependencies
And remove cache for not include unnecessary files on
the docker image.
2025-06-18 09:46:15 +02:00
Andrey Antukh
50e9816526 Use custom jre for backend image
Mainly for reduce the size of the image and not include
not necessary modules. It also starts using multistage
dockerfiles for fetch and setup jdk and node and then
only copy the required files.
2025-06-18 09:46:15 +02:00
Andrey Antukh
4c0165da62 ⬆️ Update node dependency on devenv 2025-06-18 09:46:15 +02:00
Andrey Antukh
42d36bae0a Update several node based dependencies 2025-06-18 09:46:15 +02:00
Andrey Antukh
6dd0f4f164 🔥 Remove unused jvm options from backend start-dev script 2025-06-18 09:46:15 +02:00
Elena Torro
f7c4bd77be 🐛 Fix right-sidebar width overflow 2025-06-18 09:10:01 +02:00
Alejandro Alonso
5d72954611 Merge pull request #6707 from penpot/niwinz-staging-fix-path-join-nodes
🐛 Fix incorrect type handling on path join nodes operation
2025-06-18 07:37:58 +02:00
Alejandro Alonso
9930f54558 Merge pull request #6706 from penpot/niwinz-staging-opacity-fix
🐛 Fix incorrect handling of opacity change on gradient stop
2025-06-18 07:32:34 +02:00
Alejandro Alonso
667c9ddbb9 Merge pull request #6698 from penpot/niwinz-staging-fix-exporter
🐛 Fix incorrect params handling on exporter
2025-06-18 07:29:36 +02:00
Alejandro Alonso
4f09005586 Merge pull request #6694 from penpot/niwinz-staging-fix-profile-lang
🐛 Fix bad initial state on profile settings
2025-06-18 07:26:42 +02:00
Alejandro Alonso
cbc98a761f Merge pull request #6693 from penpot/niwinz-staging-register-regression
🐛 Fix regression on singup flow
2025-06-18 07:23:37 +02:00
Andrey Antukh
c3b306201d 🐛 Fix incorrect behavior of make-curve-point fn 2025-06-17 23:18:34 +02:00
Andrey Antukh
a772b442c8 🐛 Fix incorrect type handling on path join nodes operation 2025-06-17 17:34:37 +02:00
Alejandro Alonso
6a46110f80 Merge pull request #6672 from penpot/superalex-fix-focus-mode-wasm
🐛 Fix focus mode for wasm render
2025-06-17 16:55:47 +02:00
Alejandro Alonso
1c7aea4b84 🐛 Fix focus mode for wasm render 2025-06-17 16:42:45 +02:00
Andrey Antukh
90116c207f Merge remote-tracking branch 'origin/staging' into develop 2025-06-17 16:23:35 +02:00
Pablo Alba
46fe3a6239 📚 Add comments on convoluted variants code (#6704) 2025-06-17 16:17:56 +02:00
Andrey Antukh
332bbc71c3 🐛 Fix incorrect handling of opacity change on gradient stop 2025-06-17 16:14:10 +02:00
Andrey Antukh
c5b0206bf0 🐛 Add workaround for webkit issue on fileReader (#6697)
On reading blob as data uri
2025-06-17 15:25:58 +02:00
Elena Torró
01311225c7 Merge pull request #6695 from penpot/superalex-fix-allocate-0-bytes-path-attrs
🐛 Fix wasm render path issues
2025-06-17 14:44:15 +02:00
Elena Torró
717f3e1b32 Merge pull request #6703 from penpot/elenatorro-update-render-wasm-docs
📚 Add schemas and links to render-wasm README
2025-06-17 14:24:47 +02:00
Elena Torro
9a44bd0967 📚 Add schemas and links to render-wasm README 2025-06-17 14:06:46 +02:00
Belén Albeza
b92e108205 Are more visual regression tests for wasm (#6702) 2025-06-17 12:39:38 +02:00
Alejandro Alonso
8c6a80829f Merge pull request #6671 from penpot/azazeln28-refactor-minor-perf-issues
♻️ Refactor some minor perf issues
2025-06-17 11:30:43 +02:00
Elena Torró
039a544990 Merge pull request #6675 from penpot/alotor-grid-helpers
 Add grid helpers to wasm
2025-06-17 11:14:18 +02:00
Alejandro Alonso
60dbf02896 Merge pull request #6701 from penpot/elenatorro-fix-custom-font-load
🐛 Fix storing custom fonts
2025-06-17 10:06:02 +02:00
Elena Torro
d248dd09bc 🐛 Fix storing custom fonts 2025-06-17 09:38:17 +02:00
Alejandro Alonso
81d2b9a82e 🐛 Fix group fills propagation when fill is none 2025-06-17 09:17:54 +02:00
Alejandro Alonso
1bb6f2754c 🐛 Fix allocate 0 bytes for path attrs 2025-06-17 08:43:00 +02:00
Andrey Antukh
22ca1ab5f9 🐛 Fix incorrect params handling on exporter
that caused unexpected exception on multiple exports
2025-06-16 16:58:03 +02:00
Andrey Antukh
df84396fea Merge remote-tracking branch 'origin/staging' into develop 2025-06-16 16:51:14 +02:00
Andrey Antukh
acf0d02c5d Merge pull request #6696 from penpot/eva-add-export-metrics
🎉 Add token export event tag
2025-06-16 16:50:49 +02:00
Eva Marco
5ccf34fdae 🐛 Fix reposition on tooltip 2025-06-16 16:34:53 +02:00
Eva Marco
41c8bba1df ♻️ Remove anonym fn 2025-06-16 16:23:53 +02:00
Eva Marco
325a78a967 🎉 Add token export event tag 2025-06-16 16:20:14 +02:00
mirakernel
409ff31c30 🐛 Avoid crash on empty string in interaction prototype (#6687)
Fixes #6469

Using `uuid/parse` caused a crash when "Relative to" field was set to "auto",
producing an empty string. This change uses `uuid/parse*` instead, which safely
returns nil for invalid or empty inputs, preventing the crash.

Signed-off-by: Dmitriy Mikheev <mirakernel.disroot.org>
Co-authored-by: kira <kira@kira.kira>
2025-06-16 15:19:45 +02:00
mirakernel
a56822ad99 🐛 Avoid crash on empty string in interaction prototype (#6687)
Fixes #6469

Using `uuid/parse` caused a crash when "Relative to" field was set to "auto",
producing an empty string. This change uses `uuid/parse*` instead, which safely
returns nil for invalid or empty inputs, preventing the crash.

Signed-off-by: Dmitriy Mikheev <mirakernel.disroot.org>
Co-authored-by: kira <kira@kira.kira>
2025-06-16 15:18:59 +02:00
Andrey Antukh
8cb42a63e5 🐛 Fix bad initial state on profile settings 2025-06-16 15:05:29 +02:00
Andrey Antukh
2af1feafb6 Merge pull request #6667 from penpot/niwinz-develop-enhacements-2
 Add internal changes to tooltip* ds component
2025-06-16 15:03:42 +02:00
Eva Marco
691a67b595 🐛 Fix tooltip height on safari 2025-06-16 14:45:12 +02:00
Andrey Antukh
f7e94accc3 Add internal performance oriented changes to tooltip* 2025-06-16 14:45:12 +02:00
Andrey Antukh
fc655224af Add memorization to icon-button* ds component 2025-06-16 14:45:12 +02:00
Andrey Antukh
8b0ead6832 🐛 Fix regression on singup flow
Move all params handling to prepare-register, just for consistency
2025-06-16 14:31:30 +02:00
Alejandro Alonso
10ae4dd3f7 Merge pull request #6689 from penpot/niwinz-staging-add-sr-lang
 Add several fixes & enhancements
2025-06-16 13:43:24 +02:00
Andrey Antukh
34d6e86e42 🐛 Fix incorrect theem selection on export progress bar color 2025-06-16 13:42:43 +02:00
Andrey Antukh
481d1ec53a Normalize layout schemas 2025-06-16 13:42:43 +02:00
Andrey Antukh
c6f4ee1974 ⬆️ Update cuerdas dependency
Fixes a corner case with camel->kebab casing
2025-06-16 13:42:41 +02:00
Andrey Antukh
f20032199a 🎉 Add Serbian lang 2025-06-16 13:42:22 +02:00
Elena Torró
4869373a43 🔧 Add methods to render text as path (#6624)
* 🔧 Refactor text strokes drawing

* 🔧 Add text to path methods for future usage

* 📚 Add text as paths internal documentation
2025-06-16 13:37:29 +02:00
María Valderrama
d0aac65c76 🐛 Fix misalignments at create account (#6692) 2025-06-16 13:26:33 +02:00
Pablo Alba
2d36a1f3e0 🐛 Fix when retrieving a variant from several with same props, it get the last one 2025-06-16 12:23:40 +02:00
Alejandro Alonso
38941d4811 Merge pull request #6676 from penpot/elenatorro-fix-load-pending-single-attr
🐛 Fix parsing pending callback on setting single shape attr
2025-06-16 11:50:57 +02:00
María Valderrama
f21e546bc1 Add import error event (#6690) 2025-06-16 10:39:56 +02:00
alonso.torres
0be8a6e0e6 Add grid helpers to wasm 2025-06-16 09:55:35 +02:00
Marina López
3624a14141 Subscription tests (#6669)
*  Subscription tests

*  Subscription tests
2025-06-16 09:31:50 +02:00
Peter Kahoun
141431bb9e Update cs.po - inflection fixes (#6677)
Signed-off-by: Peter Kahoun <kahi.cz@gmail.com>
2025-06-16 09:29:47 +02:00
Alonso Torres
874a658369 Adds generateFontFaces method to the plugins api (#6682)
*  Adds generateFontFaces method to the plugins api

* ⬆️ Update plugin runtime
2025-06-16 09:28:04 +02:00
Alonso Torres
c254ebd7c3 🐛 Fix problem with import modal style (#6683) 2025-06-16 09:26:35 +02:00
Elena Torro
f58ee2c89f 🔧 Add visual regression tests for font load 2025-06-11 13:22:23 +02:00
Pablo Alba
925b6c02d6 🎉 Separate the content of the text of the rest of properties on variants 2025-06-11 11:22:43 +02:00
Pablo Alba
9761cba337 ♻️ Restore separate the content of the text of the rest of properties on components updates
This reverts commit b2aaa5f0df.
2025-06-11 11:21:54 +02:00
Florian Schrödl
267a3af1e5 💄 Fixes export dialog styling issues (#6673)
* 🐛 Fix text overflow in file list
* 💄 Set monospace font for code-block component
* 💄 Reduce padding
2025-06-11 10:43:02 +02:00
Andrey Antukh
71f5806e23 Add editors count to get-owned-teams rpc method response 2025-06-11 08:40:58 +02:00
Elena Torro
330bee7839 🐛 Fix parsing pending callback on setting single shape attr 2025-06-10 21:34:41 +02:00
Andrey Fedorov
d44e4e5275 Add zip file format import for tokens 2025-06-10 17:32:06 +02:00
Aitor Moreno
369e134bed ♻️ Refactor some minor perf issues 2025-06-10 16:00:10 +02:00
Andrey Antukh
b8ee7cad26 Merge pull request #6663 from penpot/alotor-plugins-bugfixes
 Plugins fixes and enhancements
2025-06-10 15:30:32 +02:00
alonso.torres
26efc9f0c8 📚 Add documentation for new plugin permission 2025-06-10 15:09:22 +02:00
alonso.torres
1d593e1287 ⬆️ Updates plugins runtime 2025-06-10 15:09:22 +02:00
alonso.torres
b34c161fc3 Adds local store proxy in plugins 2025-06-10 15:09:22 +02:00
alonso.torres
ed0c84a069 Exposes board clipContent and showInViewMode properties in plugins 2025-06-10 15:06:31 +02:00
alonso.torres
29466b47fe Adds skipChildren to export parameters 2025-06-10 15:06:30 +02:00
Elena Torró
f02dd9f8dc Merge pull request #6651 from penpot/superalex-path-fixes
🐛 Path fixes
2025-06-10 12:11:25 +02:00
David Barragán Merino
b385f055e0 🐳 Migrate from Redis to Valkey (#6666) 2025-06-10 10:08:10 +02:00
Alejandro Alonso
e91550cd9d Merge pull request #6646 from penpot/ladybenko-10904-playwright-wasm
🔧 Set up visual regression tests for wasm renderer
2025-06-10 09:24:59 +02:00
Alejandro Alonso
5faa619bc4 Merge pull request #6664 from penpot/niwinz-hotfix-1
🐛 Add better fix for path transformation
2025-06-10 08:51:51 +02:00
Alejandro Alonso
ed76b1b1ee 🎉 Support for webp images (#6665) 2025-06-10 08:40:30 +02:00
Belén Albeza
afdbb5cf2f 📚 Add documentation specific for wasm visual regression tests 2025-06-09 17:46:18 +02:00
Belén Albeza
971b92a75b 🔧 Make mockAsset to accept an array of asset ids too 2025-06-09 17:46:18 +02:00
Belén Albeza
479406b884 🔧 Add initial snapshots 2025-06-09 17:46:18 +02:00
Belén Albeza
1a10b7ebfd 🔧 Wait for first render using a custom event (visual regression tests) 2025-06-09 17:46:18 +02:00
Belén Albeza
59a4b51d2c 🔧 Set up playwright project for render wasm 2025-06-09 17:01:29 +02:00
Andrey Antukh
74430aad21 📎 Add missing emsd loading to devenv bashrc 2025-06-09 15:57:31 +02:00
Alejandro Alonso
78d6166bac 🐛 Fix caps for rounded paths 2025-06-09 14:40:54 +02:00
Alejandro Alonso
8db910baee 🐛 Fix rendering vertical and horizontal paths 2025-06-09 13:04:18 +02:00
Alejandro Alonso
a9702f104d 🐛 Fix shapes without fills contained in a group with fills 2025-06-09 13:04:18 +02:00
Andrey Antukh
01dda6dd6b 🐛 Add better fix for path transformation 2025-06-09 12:46:53 +02:00
Andrey Antukh
b2bc481672 Merge remote-tracking branch 'origin/develop' into staging 2025-06-09 12:21:09 +02:00
Andrey Antukh
8c337f508b Merge remote-tracking branch 'origin/staging' into develop 2025-06-09 12:20:55 +02:00
Andrey Antukh
f9f45dc612 🐛 Fix path rotation issue (#6662) 2025-06-09 12:14:09 +02:00
Anonymous
93542854c1 🌐 Add translations for: Swedish
Currently translated at 86.6% (1610 of 1857 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/sv/
2025-06-09 11:13:39 +02:00
Anonymous
858f94c6d2 🌐 Add translations for: Dutch
Currently translated at 96.5% (1793 of 1857 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/nl/
2025-06-09 11:13:38 +02:00
Anonymous
f932d663b0 🌐 Add translations for: Latvian
Currently translated at 96.5% (1793 of 1857 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/lv/
2025-06-09 11:13:38 +02:00
Anonymous
63631e60cd 🌐 Add translations for: Ukrainian (ukr_UA)
Currently translated at 96.5% (1793 of 1857 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/ukr_UA/
2025-06-09 11:13:38 +02:00
Anonymous
6018cd67c5 🌐 Add translations for: Croatian
Currently translated at 87.1% (1619 of 1857 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/hr/
2025-06-09 11:13:37 +02:00
Anonymous
4856d0e957 🌐 Add translations for: Portuguese (Portugal)
Currently translated at 85.7% (1592 of 1857 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/pt_PT/
2025-06-09 11:13:37 +02:00
Anonymous
995ca4d7d9 🌐 Add translations for: Czech
Currently translated at 87.1% (1618 of 1857 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/cs/
2025-06-09 11:13:37 +02:00
Anonymous
d5d254a7f3 🌐 Add translations for: Italian
Currently translated at 96.5% (1793 of 1857 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/it/
2025-06-09 11:13:36 +02:00
Anonymous
69f45dc811 🌐 Add translations for: Chinese (Traditional Han script)
Currently translated at 87.3% (1623 of 1857 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/zh_Hant/
2025-06-09 11:13:35 +02:00
Anonymous
7534ad283c 🌐 Add translations for: Hebrew
Currently translated at 96.5% (1793 of 1857 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/he/
2025-06-09 11:13:34 +02:00
Anonymous
3d6695171d 🌐 Add translations for: Indonesian
Currently translated at 92.7% (1722 of 1857 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/id/
2025-06-09 11:13:34 +02:00
Anonymous
8fa28ce176 🌐 Add translations for: German
Currently translated at 89.9% (1670 of 1857 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/de/
2025-06-09 11:13:34 +02:00
Anonymous
f03a0de665 🌐 Add translations for: French
Currently translated at 95.7% (1778 of 1857 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/fr/
2025-06-09 11:13:34 +02:00
Anonymous
555af2fa52 🌐 Add translations for: English
Currently translated at 99.7% (1852 of 1857 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/en/
2025-06-09 11:13:33 +02:00
Andrey Antukh
0683b20b25 🌐 Rehash and validate translation files 2025-06-09 11:01:08 +02:00
Hosted Weblate
163ae639ff 🌐 Update translation files
Updated by "Cleanup translation files" hook in Weblate.

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/
2025-06-09 10:57:51 +02:00
Andrey Antukh
354ba91aa6 Merge remote-tracking branch 'weblate/develop' into develop 2025-06-09 10:57:13 +02:00
Andrey Antukh
38d9a9d2d5 📎 Update changelog 2025-06-09 10:29:18 +02:00
Yamila Moreno
beb3d16693 📎 Fix minor typo (#6661) 2025-06-09 10:25:16 +02:00
Andrey Antukh
5770c0cb02 Merge pull request #6625 from penpot/niwinz-develop-enhacements-1
 Several enhacements
2025-06-09 10:24:44 +02:00
Eva Marco
46ce9500fc 🐛 Fix absolute position tooltip message (#6660) 2025-06-09 09:52:35 +02:00
Alejandro Alonso
d008ea9edd Merge pull request #6652 from penpot/elenatorro-fix-load-fonts
🐛 Fix fonts initialization
2025-06-09 09:31:00 +02:00
Eva Marco
eba8d02c18 📚 Update changelog 2025-06-06 15:48:39 +02:00
Florian Schrödl
bb9daf7c03 Add export tokens modal with multi-file export (#6649) 2025-06-06 15:37:10 +02:00
Andrey Antukh
f1232fc461 🐛 Fix issues with old profile theme data 2025-06-06 15:25:49 +02:00
Andrey Antukh
9584e1b02d 📎 Add missing playwright chromium install to devenv 2025-06-06 15:10:52 +02:00
Edgars Andersons
96ccac5085 🌐 Add translations for: Latvian
Currently translated at 99.9% (1807 of 1808 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/lv/
2025-06-06 13:03:07 +00:00
Ingrid Pigueron
2540d58096 🌐 Add translations for: French
Currently translated at 98.7% (1786 of 1808 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/fr/
2025-06-06 13:03:05 +00:00
Andrey Antukh
de2695682d Allow encode mailto and self target link in markdown
On translation files
2025-06-06 14:03:52 +02:00
Andrey Antukh
e464d8cf9c 📎 Add library tests to circle-ci config 2025-06-06 14:03:52 +02:00
Andrey Antukh
a8433bcef3 🐛 Fix incorrect decoding of library color 2025-06-06 14:03:52 +02:00
Andrey Antukh
644dd9ff44 🎉 Add support for progress reporting to library export method 2025-06-06 14:03:52 +02:00
Andrey Antukh
27d2724153 🐛 Fix incorrect shape filtering on bool creation on library 2025-06-06 14:03:52 +02:00
Andrey Antukh
c647d122d8 ⬆️ Update frontend dependencies 2025-06-06 14:03:52 +02:00
Andrey Antukh
e4a65f3a04 ⬆️ Update backend dependencies 2025-06-06 14:03:52 +02:00
Andrey Antukh
389f1d6502 ⬆️ Update common dependencies 2025-06-06 14:03:52 +02:00
Andrey Antukh
b91a670198 Replace redis with valkey on devenv compose file 2025-06-06 14:03:52 +02:00
Andrey Antukh
5650629b73 Add minimal wait to run-devenv when no compose is started 2025-06-06 14:01:10 +02:00
Andrey Antukh
a4310b4213 🔥 Remove usage of dm/assert on data.profile ns file 2025-06-06 14:01:10 +02:00
Elena Torro
a8d4b293dc 🐛 Fix loading same resources multiple times 2025-06-06 12:26:35 +02:00
Alejandro Alonso
fec7d5cff2 🐛 Fix detach stroke (#6655) 2025-06-06 12:24:18 +02:00
Alejandro Alonso
5e254ff3f6 Merge pull request #6643 from penpot/azazeln28-refactor-performance-improvements
♻️ Minor performance improvements
2025-06-06 11:38:53 +02:00
Elena Torro
8c20159fb0 🐛 Cache emoji font correctly 2025-06-06 11:28:50 +02:00
Elena Torro
79e1c29306 🐛 Fix emoji detection and load 2025-06-06 11:28:50 +02:00
Aitor Moreno
fcd3e5c34c ♻️ Refactor surface iteration 2025-06-06 10:21:31 +02:00
Eva Marco
8b9f15f414 🐛 Fix select color tooltip error (#6648) 2025-06-05 21:15:00 +02:00
Pablo Alba
b2aaa5f0df ♻️ Remove separate the content of the text of the rest of properties on components updates 2025-06-05 16:43:23 +02:00
Aitor Moreno
8922e7454f ♻️ Refactor some allocations 2025-06-05 15:37:03 +02:00
Alejandro Alonso
4f7d97a31e Merge pull request #6641 from penpot/ladybenko-fix-fills-wasm
🐛 Fix set-shape-fills serialization (wasm renderer)
2025-06-05 14:24:27 +02:00
Stas Haas
e32af5e71e 🌐 Add translations for: German
Currently translated at 92.4% (1672 of 1808 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/de/
2025-06-05 14:09:36 +02:00
Ingrid Pigueron
6cb5b812da 🌐 Add translations for: French
Currently translated at 98.0% (1772 of 1808 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/fr/
2025-06-05 14:09:36 +02:00
Belén Albeza
ca24e23775 🐛 Fix set-shape-fills serialization (wasm renderer) 2025-06-05 14:04:41 +02:00
Alejandro Alonso
28ed62fb2c Merge pull request #6640 from penpot/niwinz-develop-hotfix-1
🐛 Remove fills from paragraph-set nodes on text shapes
2025-06-05 14:03:18 +02:00
Andrey Antukh
9c4b60e95f 🐛 Fix incorrect opacity assignation on changing fill from solid to gradient 2025-06-05 13:34:13 +02:00
Andrey Antukh
6719902647 Add color checks and test of event creation for fills 2025-06-05 13:34:13 +02:00
Andrey Antukh
cf8307af8f 📎 Update changelog 2025-06-05 13:29:51 +02:00
Andrey Antukh
8c54cb764f 🐛 Remove fills from paragraph-set nodes on text shapes 2025-06-05 13:11:39 +02:00
Eva Marco
4a9fef12eb 🐛 Fix url params on invitation link (#6638) 2025-06-05 12:28:53 +02:00
Alejandro Alonso
ea4e69f381 Merge pull request #6633 from penpot/niwinz-develop-hotfix-1
🐛 Fix library color detach operation
2025-06-05 11:04:57 +02:00
Anderson Paulo
5fed12d807 🌐 Add translations for: Portuguese
Currently translated at 5.1% (93 of 1808 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/pt/
2025-06-05 11:01:50 +02:00
Edgars Andersons
a2f41a7a40 🌐 Add translations for: Latvian
Currently translated at 99.3% (1797 of 1808 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/lv/
2025-06-05 11:01:47 +02:00
Stas Haas
f4fd9fa13d 🌐 Add translations for: German
Currently translated at 92.3% (1669 of 1808 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/de/
2025-06-05 11:01:47 +02:00
Andrés Moya
8a0aa20789 🔧 Renames, privacy adjustments and other small enhancements 2025-06-05 10:58:23 +02:00
Andrés Moya
1b3a200010 🔧 Reorder code for more legibility 2025-06-05 10:58:23 +02:00
Andrés Moya
70263ba901 🔥 Remove unused code 2025-06-05 10:58:23 +02:00
Andrés Moya
5c8f6dd498 🔧 Add internal id to all token entities 2025-06-05 10:58:23 +02:00
Eva Marco
a2abaea637 ♻️ Update button-icon with tooltip component (#6539)
* 🐛 Add tooltip to base icon button

* 🎉 Update id prop

* 🐛 Fix test
2025-06-05 10:18:56 +02:00
Alejandro Alonso
55997a3d4a Merge pull request #6634 from penpot/ladybenko-fit-set-shape-fills
🐛 Fix wasm crash in set_shape_fills (wasm) when fill list is empty
2025-06-05 10:07:34 +02:00
Belén Albeza
a30ab17605 🐛 Fix wasm crash in set_shape_fills (wasm) when fill list is empty 2025-06-05 09:52:51 +02:00
Eva Marco
ab0219876e Add numeric token type (#6575)
*  Add numeric type token

* 🐛 Fix comments
2025-06-05 09:33:54 +02:00
Andrey Antukh
19961f440a 🐛 Fix library color detach operation 2025-06-05 09:33:06 +02:00
Alejandro Alonso
db84eb365b 🐛 Fix strokes migration (#6632) 2025-06-05 08:42:57 +02:00
Marina López
b7f97dbeea 🐛 Subscription review fixes (#6628) 2025-06-04 21:01:48 +02:00
Elenzakaleidos
4cbaef1451 💄 New video in the README.md (#6629)
I added a new video in the readme page cause the previous one had the wrong name

Signed-off-by: Elenzakaleidos <elena.scilinguo@kaleidos.net>
2025-06-04 21:00:49 +02:00
andrés gonzález
e1adbdfd9f 📚 Update changelog (#6616) 2025-06-04 15:12:33 +02:00
Alejandro Alonso
687e1e7b0b Merge pull request #6569 from penpot/niwinz-fills-cleanup
♻️ Clean and sanitize color types
2025-06-04 14:26:12 +02:00
Alejandro Alonso
055ee27be0 🐛 Add migrations to fix colors 2025-06-04 14:01:48 +02:00
Andrés Moya
47af278f5e 🐛 Remove unneeded check 2025-06-04 13:11:16 +02:00
Andrey Antukh
29ad99d685 🐛 Fix incorrect declaration of tokens lib schema decoder 2025-06-04 13:03:51 +02:00
Andrey Antukh
3a8b312f6d 🐛 Fix calculate hash on empty path data instance 2025-06-04 13:03:51 +02:00
Andrey Antukh
8f55269522 🐛 Remove unknown types from stroke style schema 2025-06-04 13:03:51 +02:00
Andrey Antukh
f86ce38f04 🎉 Add Fills binary data type 2025-06-04 13:03:51 +02:00
Andrey Antukh
b97a3f9783 Add tests for common buffers namespace to the cljs test runner 2025-06-04 12:46:49 +02:00
Andrey Antukh
91807151ba Add stricter validation for gradient stop offset
It should be from a number from 0 to 1 inclusive
2025-06-04 12:46:49 +02:00
Andrey Antukh
5c225a51ce Add the ability to retrieve a set of keys from map schemas 2025-06-04 12:46:49 +02:00
Andrey Antukh
3d61924162 ♻️ Change internal naming for PathData cljs impl
For make it more consistent with CLJ impl and move
the equals helper to buffers for make it reusable by
other binary types.
2025-06-04 12:46:49 +02:00
Andrey Antukh
580013bc3f ⬆️ Update shadow-cljs to 3.1.5 2025-06-04 12:46:49 +02:00
Andrey Antukh
9ec5467e2a 🐛 Fix incorrect neested data structure validation on components
This commit upgrades rumext where the issue is fixed. It also
adapts the swatch component for correct data passing.
2025-06-04 12:46:49 +02:00
Andrey Antukh
b113736321 📎 Disable shadow-cljs reload on storybook build 2025-06-04 12:46:49 +02:00
Andrey Antukh
22db773b2e 🔥 Remove unused code from worker import ns 2025-06-04 12:46:49 +02:00
Andrey Antukh
91636ffc41 🐛 Adapt inspect code to color type changes
Still contains broken code because it was already broken
2025-06-04 12:46:49 +02:00
Andrey Antukh
7160334cb9 ♻️ Add stricter validation for colors, fills and strokes 2025-06-04 12:46:49 +02:00
Andrey Antukh
d08d2f49ac Add better defaults for several number schema generators 2025-06-04 12:46:49 +02:00
Andrey Antukh
8f774a3611 Simplify media mime types structs 2025-06-04 12:46:49 +02:00
Andrey Antukh
d9d2cc7b4e Split byte buffer helpers from types path impl 2025-06-04 12:46:49 +02:00
Andrey Antukh
2e0fd6ec1b Merge pull request #6626 from penpot/niwinz-develop-fixes-4
🐛 Several bugfixes
2025-06-04 12:39:39 +02:00
Andrey Antukh
d2d39aad30 Make theme toggle skip "system" theme 2025-06-04 12:24:01 +02:00
Andrey Antukh
d6e0001ac4 🐛 Fix encoding and decoding issue with tokens lib type 2025-06-04 12:12:31 +02:00
Elena Torró
793c01a0a1 Merge pull request #6611 from penpot/elenatorro-add-new-render-texts-docs
📚 Add texts documentation
2025-06-04 10:11:31 +02:00
Elena Torró
bbac5d050e Merge pull request #6623 from penpot/ladybenko-11106-send-all-fills
 Send all fills of a shape in a single wasm call
2025-06-04 09:18:39 +02:00
Alejandro Alonso
5a7d9e3f18 Merge pull request #6609 from penpot/elenatorro-11213-fix-language-font-fallback
🎉 Implement font fallback to support multiple languages
2025-06-03 17:19:39 +02:00
Edgars Andersons
1a921c2750 🌐 Add translations for: Latvian
Currently translated at 99.1% (1792 of 1808 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/lv/
2025-06-03 14:04:12 +00:00
Yaron Shahrabani
39f145b8b1 🌐 Add translations for: Hebrew
Currently translated at 99.9% (1807 of 1808 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/he/
2025-06-03 14:04:10 +00:00
Stas Haas
6611769dc9 🌐 Add translations for: German
Currently translated at 92.2% (1667 of 1808 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/de/
2025-06-03 14:04:08 +00:00
Eva Marco
b3d230ba16 📚 Add copyright to docs files (#6618) 2025-06-03 15:49:24 +02:00
Eva Marco
ddae0026fe 🎉 Add metrics to new multi file import (#6610) 2025-06-03 15:48:22 +02:00
Belén Albeza
9fc3f4858a Send all fills of a shape in a single wasm call 2025-06-03 15:37:36 +02:00
andrés gonzález
1120c7c7fb 🐛 Fix copy in error message (#6615) 2025-06-03 12:28:49 +02:00
Andrey Antukh
e9bd44b819 Merge remote-tracking branch 'origin/staging' into develop 2025-06-03 10:44:11 +02:00
Andrey Antukh
2244bf6aa7 Merge remote-tracking branch 'origin/main' into staging 2025-06-03 10:43:39 +02:00
Andrey Antukh
f4ef4a705c Merge tag '2.7.2-RC1' 2025-06-03 10:43:14 +02:00
Elena Torro
c40de5fb87 🎉 Implement font fallback to support multiple languages 2025-06-03 08:21:59 +02:00
Elena Torro
9733c41ae4 🐛 Fix blend mode on merge fills 2025-06-03 08:21:59 +02:00
Alejandro Alonso
fe8d9fdd76 Merge pull request #6614 from penpot/niwinz-staging-backport-1
 Make the hash optional on binfile-v3
2025-06-03 08:13:42 +02:00
Alejandro Alonso
401fa823a0 Merge pull request #6612 from penpot/niwinz-develop-devenv
🐛 Fix build issues on devenv
2025-06-03 07:49:34 +02:00
Andrey Antukh
3da3281a56 🐛 Fix library compatibility issue on media encoding with penpot 2.7 (#6613) 2025-06-02 23:25:39 +02:00
Andrey Antukh
3131eec271 Make the hash optional on binfile-v3
Backport the change from develop
2025-06-02 23:24:35 +02:00
Andrey Antukh
1909189ce0 Use different approach for setup cargo home 2025-06-02 22:29:39 +02:00
Andrey Antukh
0ec0917b6d Add isolated-shell to manage.sh
Instead of attaching to an existing devenv, starts a new one.
2025-06-02 19:13:20 +02:00
Andrey Antukh
0e4c535edc 📎 Print current path on frontend scripts build script 2025-06-02 19:11:55 +02:00
Andrey Antukh
46f330fef3 Move several logic from init to entrypoint on devenv
For make commands consistent independently if they are executed
inside devenv or from manage.sh
2025-06-02 19:10:48 +02:00
Andrey Antukh
f067c86b02 🔥 Remove unnecesary env vars from bashrc (devenv) 2025-06-02 19:10:20 +02:00
Andrey Antukh
2b6a91819b Reduce verbosity of frontend build script 2025-06-02 18:05:11 +02:00
Andrey Antukh
1f652fe364 Remove arm64 build of devenv
Looks unused right now
2025-06-02 17:44:22 +02:00
Elena Torro
4c10aeefe6 📚 Add texts documentation 2025-06-02 16:36:25 +02:00
Andrey Antukh
e70da78a77 Merge remote-tracking branch 'origin/staging' into develop 2025-06-02 12:55:22 +02:00
Andrey Antukh
27ab910a64 📚 Update changelog 2025-06-02 12:36:47 +02:00
Alejandro Alonso
c1fa6be7c4 Merge pull request #6591 from penpot/azazeln28-refactor-render-iteration
♻️ Refactor render iteration
2025-06-02 12:33:19 +02:00
Andrey Antukh
2398c1fc2b Merge pull request #6604 from penpot/alotor-fix-sandbox-runtime
🐛 Add sandbox runtime
2025-06-02 12:30:51 +02:00
Alejandro Alonso
13859f90b9 Merge pull request #6601 from penpot/alotor-fix-move-guides
 Move guides and comments for wasm modifiers
2025-06-02 12:28:01 +02:00
Yamila Moreno
e2724d180b Merge pull request #6497 from penpot/yms-update-coc
📚 Update Code of conduct
2025-06-02 12:20:57 +02:00
Andrey Antukh
c6bccafd98 Merge pull request #6607 from penpot/andy-update-changelog
📚 Update changelog
2025-06-02 12:17:53 +02:00
Andrey Antukh
1357ab34eb 📚 Move library rework changes to its own changelog 2025-06-02 12:16:27 +02:00
Andres Gonzalez
6e9ee3d310 📚 Update changelog 2025-06-02 12:10:32 +02:00
Yamila Moreno
5816695246 📚 Update Code of Conduct 2025-06-02 12:09:20 +02:00
Yamila Moreno
0d9160506b 📚 Add direct link to the CoC 2025-06-02 12:09:20 +02:00
Yamila Moreno
c3c6628bf1 📚 Minor improvement in README / Getting started 2025-06-02 12:09:20 +02:00
Alejandro Alonso
8642ffba46 🐛 Fix frontend build (#6608) 2025-06-02 12:03:08 +02:00
Andrey Antukh
25372c3edf Persist ruler layout flag to local storage 2025-06-02 11:43:13 +02:00
Andrey Antukh
e13d1743da Merge pull request #6598 from penpot/superalex-deprecate-old-image-type
♻️ Migrations for deprecated types and attributes
2025-06-02 11:29:44 +02:00
luisδμ
02d1a1f0b1 Delete variant property when it has no value anywhere after editing a formula (#6586) 2025-06-02 09:50:27 +02:00
Alejandro Alonso
08aeb93710 Merge pull request #6606 from penpot/niwinz-develop-fixes-2
 Fix several issues on penpot library
2025-06-02 07:04:22 +02:00
Alejandro Alonso
04f0f77cd8 Merge pull request #6605 from penpot/niwinz-develop-fixes-1
🐛 Fix default theme setup
2025-06-02 07:02:59 +02:00
Andrey Antukh
15adf1bd06 📎 Set penpot library version to 1.0.2 2025-06-01 11:29:31 +02:00
Andrey Antukh
1080ffc6b8 Add correct library version on the metadata 2025-06-01 11:28:42 +02:00
Andrey Antukh
1450672341 Remove obsolete props from bool style attrs 2025-06-01 11:20:26 +02:00
Andrey Antukh
483e88d6a3 Add more descriptive names for playground samples 2025-06-01 11:20:26 +02:00
Andrey Antukh
9fee16f4a9 🐛 Fix compatibility issue with penpot 2.7 2025-06-01 11:20:26 +02:00
Andrey Antukh
89a09346a5 🐛 Fix incorrect boolean shapes generation on builder 2025-06-01 11:06:00 +02:00
Andrey Antukh
77fa235965 🐛 Fix incorrect boolean shape generation on file builder 2025-06-01 10:25:11 +02:00
Andrey Antukh
03e4ca12be ♻️ Move update-bool from common geom to types path 2025-06-01 10:24:09 +02:00
Andrey Antukh
229c9b8385 📎 Add minor changes to circleci cache management 2025-06-01 09:34:05 +02:00
Andrey Antukh
a4fab5c5bd 🐛 Fix default theme setup
broken on previous commits
2025-06-01 09:30:57 +02:00
Andrey Antukh
d8913ab18b Add minor changes to devenv for avoid repeated deps download (#6600)
*  Add minor changes to devenv for avoid repeated dependency download

*  Add minor changes to devenv for integrate payments service

*  Remove playwright deps install from circleci config

*  Move cargo_home to userspace on devenv start

*  Improve cache management on CI

*  Improve cargo installation

*  Add missing playwright install cmd on CI

*  Install cargo-watch on devenv

---------

Co-authored-by: David Barragán Merino <david.barragan@kaleidos.net>
2025-06-01 09:16:28 +02:00
Edgars Andersons
7ef2f4e67e 🌐 Add translations for: Latvian
Currently translated at 98.8% (1787 of 1808 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/lv/
2025-05-31 12:03:08 +02:00
Alejandro Alonso
1d065e68f4 🎉 Allow force render mode from get param (#6594) 2025-05-30 20:05:58 +02:00
Miguel de Benito Delgado
c9ceceb7e9 🔥 Remove old code for theme support (#6597) 2025-05-30 16:54:23 +02:00
luisδμ
ad26efaa5d Limit the length of property names and values to 60 chars (#6587) 2025-05-30 16:15:18 +02:00
alonso.torres
a3e17047a4 🐛 Add sandbox runtime 2025-05-30 15:40:36 +02:00
Alejandro Alonso
0552ef55cf Merge pull request #6603 from penpot/alotor-fix-duplicate-shapes
🐛 Fix problem in wasm when duplicate objects
2025-05-30 14:08:01 +02:00
Belén Albeza
d4c6063378 Avoid intercepting get-file-fragment in the playwright test 2025-05-30 13:53:00 +02:00
Belén Albeza
f23e460b2a Fix broken tokens test 2025-05-30 13:53:00 +02:00
Belén Albeza
35b29bb203 🐛 Fix font size input not displaying 'mixed' when needed 2025-05-30 13:53:00 +02:00
Alejandro Alonso
cd02905d1f ♻️ Migrate old fill text attributes 2025-05-30 13:51:05 +02:00
Alejandro Alonso
87d917bc2e ♻️ Deprecate old image type 2025-05-30 13:51:05 +02:00
alonso.torres
e8d1ea24d1 🐛 Fix problem in wasm when duplicate objects 2025-05-30 13:49:56 +02:00
Andrey Antukh
ad842872fb 🐛 Fix unexpected exception on get-team internal method
Because of invalid SQL
2025-05-30 13:49:05 +02:00
Alejandro Alonso
90744c182e Merge pull request #6602 from penpot/elenatorro-11214-use-text-decoration-from-leaf
🐛 Fix reading text-decoration and text-transform from leaf, and fallback to paragraph values
2025-05-30 13:33:58 +02:00
Alejandro Alonso
78aaf28532 Merge pull request #6498 from penpot/niwinz-develop-update-fonts
⬆️ Update google fonts
2025-05-30 13:28:08 +02:00
Elena Torro
4e2f905a26 🐛 Fix reading text-decoration and text-transform from leaf, and fallback to paragraph values 2025-05-30 13:22:39 +02:00
Andrey Antukh
d2cd99ed44 ⬆️ Update google fonts 2025-05-30 13:08:57 +02:00
Alejandro Alonso
885231e9a1 Merge pull request #6512 from penpot/niwinz-develop-custom-deletion-rules
♻️ Normalize logical deletion delay handling
2025-05-30 12:53:37 +02:00
Pablo Alba
baabfe2de8 🎉 Split text and its properties on components updates 2025-05-30 12:36:10 +02:00
alonso.torres
facb0227a0 Move guides and comments for wasm modifiers 2025-05-30 12:15:21 +02:00
Elena Torró
f6fe41af96 🔧 Add texts playground (#6599) 2025-05-30 12:10:34 +02:00
Edgars Andersons
f225fce9a1 🌐 Add translations for: Latvian
Currently translated at 98.4% (1780 of 1808 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/lv/
2025-05-30 11:01:47 +02:00
Yaron Shahrabani
3570d29575 🌐 Add translations for: Hebrew
Currently translated at 97.1% (1756 of 1808 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/he/
2025-05-30 11:01:45 +02:00
Andrey Antukh
f8489a521f Merge pull request #6590 from penpot/niwinz-develop-library-fixes
 Add minor enhancements to penpot library
2025-05-30 10:35:41 +02:00
Andrey Antukh
cc76a42088 Merge pull request #6561 from mdbenito/feature/5030-use-system-theme
 Use system theme
2025-05-30 10:34:46 +02:00
Andrey Antukh
50cc70201d Merge pull request #6578 from penpot/ladybenko-11105-cap-fills
🎉 Disable adding fills in UI when limit has been reached
2025-05-30 10:11:05 +02:00
Belén Albeza
e88b3bae5a 🔥 Remove gulp (#6592) 2025-05-30 10:03:22 +02:00
Aitor Moreno
2b2939b4b7 ♻️ Remove unnecesary sort operation 2025-05-30 09:56:58 +02:00
Miguel de Benito Delgado
6b25720155 🌐 Add missing translation 2025-05-29 20:11:11 +00:00
Miguel de Benito Delgado
96d099b71e Mock .matchMedia in global/window 2025-05-29 20:11:11 +00:00
Miguel de Benito Delgado
fab9e842e8 Support following system color scheme 2025-05-29 22:10:00 +02:00
Miguel de Benito Delgado
ee022e225c 🚧 UI to support switching to system theme 2025-05-29 22:10:00 +02:00
Andrey Antukh
1b3fcb0432 📎 Update circleci workflow 2025-05-29 13:50:39 +02:00
Andrey Antukh
37f88067b9 🔥 Remove library method addComponentInstance 2025-05-29 13:07:44 +02:00
Alejandro Alonso
2650eccd09 🐛 Fix set path attrs (#6589) 2025-05-29 12:27:08 +02:00
Andrey Antukh
969b171510 📎 Prepare for release 1.0.1 of the penpot library 2025-05-29 12:15:17 +02:00
Andrey Antukh
4b22a0ebfb 🐛 Make the library generate output compatible with penpot 2.7.x 2025-05-29 12:08:50 +02:00
Andrey Antukh
eafea7aec9 Merge pull request #6588 from penpot/niwinz-develop-fix-boolean
🐛 Fix incorrect bool shape creation
2025-05-29 11:38:47 +02:00
Belén Albeza
ce23fee292 Limit the amount of fills shown in the UI 2025-05-29 11:26:18 +02:00
Alejandro Alonso
f3d734357a Merge pull request #6409 from penpot/azazeln28-feat-compare-wasm
🎉 Add comparison tool to WASM playground
2025-05-29 11:20:54 +02:00
Andrey Antukh
d31f64796f 🐛 Fix incorrect bool shape creation issue 2025-05-29 11:16:12 +02:00
Andrey Antukh
3a27a5a542 Add minor naming change on process selected fn 2025-05-29 11:15:46 +02:00
Andrey Antukh
2a04f78337 Add common transducers section to common data ns 2025-05-29 11:14:53 +02:00
Aitor Moreno
aeee05c90d 🎉 Add comparison tool to WASM playground 2025-05-29 10:46:38 +02:00
Yamila Moreno
6fc63f14a0 Add configuration for air gapped installations (#6567) 2025-05-29 10:34:47 +02:00
Belén Albeza
f33c1fb530 Update binary fills flag name and add it to supported flags 2025-05-29 10:32:49 +02:00
Andrey Antukh
75170bb043 Merge pull request #6537 from penpot/niwinz-library-publish
 Add minor enhancements to penpot-library for publish it on npm
2025-05-29 09:49:51 +02:00
Belén Albeza
c0a98288d0 🔧 Gate cap with config flag 2025-05-29 09:45:31 +02:00
Belén Albeza
7d5739b663 Add playwright test for disabling adding fills 2025-05-29 09:45:31 +02:00
Elena Torró
fe60016124 Merge pull request #6573 from penpot/elenatorro-11021-text-fixes
🔧 Fix text parsing and transformation
2025-05-29 09:33:05 +02:00
Alejandro Alonso
5c58a04fc2 🐛 Fix inner strokes black background effect 2025-05-29 09:05:30 +02:00
Alejandro Alonso
04a1f8475d Merge pull request #6585 from penpot/alotor-scale-content
 Add scale content to render wasm
2025-05-29 07:32:47 +02:00
Belén Albeza
3c05f09fd1 🔧 Fix unnecessary playwright dependency in root dir (#6577) 2025-05-28 17:09:05 +02:00
María Valderrama
5eaea63ca8 🐛 Fix palette is over sidebar (#6581) 2025-05-28 17:08:23 +02:00
alonso.torres
bcfa9a82ea Add scale content to render wasm 2025-05-28 16:40:57 +02:00
Denys Kisil
d9649eaedd 🌐 Add translations for: Ukrainian (ukr_UA)
Currently translated at 99.7% (1803 of 1808 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/ukr_UA/
2025-05-28 16:01:45 +02:00
Belén Albeza
170d35dde2 Disable new fills in UI when the cap is reached 2025-05-28 14:01:26 +02:00
andrés gonzález
2943f80db5 📚 Change help links at the Help Center (#6582) 2025-05-28 13:22:42 +02:00
luisδμ
46b0e4f0e7 Manage empty property values in the combobox in design tab (#6574)
*  Manage empty property values in the combobox in design tab

* 📎 PR changes
2025-05-28 12:41:04 +02:00
Marina López
878952f7b5 Add subscription events (#6563)
*  Add subscription events

* 📎 Fixes PR feedback

* 📎 Fixes PR feedback
2025-05-28 10:50:36 +02:00
Marina López
f84ffc3562 Add history version days for subscriptions (#6571) 2025-05-28 10:49:53 +02:00
Aitor Moreno
e9edebbbb5 📚 Add tile rendering documentation (#6568) 2025-05-28 09:41:07 +02:00
Xavier Julian
14afd58eac 🐛 Display color swatch only on color type tokens 2025-05-28 09:29:26 +02:00
Belén Albeza
827d39a406 💄 Remove ununsed prop on fill-menu component 2025-05-27 15:30:16 +02:00
Belén Albeza
e4a1c373bb Only take N amount of fills 2025-05-27 15:30:11 +02:00
Pablo Alba
be13704934 🐛 Fix access to libs on migration during an import (#6572) 2025-05-27 14:54:17 +02:00
Elena Torro
88e77e3218 🔧 Fix text parsing and transformation 2025-05-27 14:04:27 +02:00
Pablo Alba
443cabe94e Add the ability to access libraries from file migrations 2025-05-27 13:12:34 +02:00
Alejandro Alonso
c7c8e91183 🐛 Fix keep aspect ratio support 2025-05-27 12:20:40 +02:00
Alejandro Alonso
327db5a1a3 🐛 Fix render of paths with empty selrects 2025-05-27 12:20:05 +02:00
Edgars Andersons
bcb74822d2 🌐 Add translations for: Latvian
Currently translated at 97.9% (1771 of 1808 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/lv/
2025-05-27 09:01:55 +00:00
Yaron Shahrabani
790d422100 🌐 Add translations for: Hebrew
Currently translated at 96.4% (1743 of 1808 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/he/
2025-05-27 09:01:54 +00:00
laurentiucotet
419a949816 🌐 Add translations for: Romanian
Currently translated at 71.7% (1298 of 1808 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/ro/
2025-05-27 09:01:53 +00:00
Ingrid Pigueron
1ad6ee6e38 🌐 Add translations for: French
Currently translated at 97.4% (1761 of 1808 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/fr/
2025-05-27 09:01:51 +00:00
Andrey Antukh
da10425800 📚 Add readme for library directory 2025-05-27 10:55:49 +02:00
Andrey Antukh
3e4c80fa27 Prepare library to be published on npm 2025-05-27 10:55:49 +02:00
Marina López
179a5654e7 🐛 Fix get current user for plugins api 2025-05-27 10:50:01 +02:00
Marina López
bc38bd6a9c 🐛 Fix team name dropdown menu from dashboard (#6562) 2025-05-27 10:05:19 +02:00
Alejandro Alonso
1c5d182a90 Merge pull request #6559 from penpot/alotor-perf-fixes
🐛 Fix some problems with modifiers
2025-05-27 09:46:37 +02:00
alonso.torres
a85a42d367 🐛 Fix some problems with modifiers 2025-05-27 09:33:33 +02:00
Alejandro Alonso
1a705cee24 Merge pull request #6555 from penpot/niwinz-develop-fix-path-bug-1
🐛 Fix path node type change operation
2025-05-27 09:04:11 +02:00
Eva Marco
a771ca91ab 🐛 Add token units flag to common/flags file (#6557) 2025-05-26 13:53:56 +02:00
Andrey Antukh
4326e2c5a4 Merge remote-tracking branch 'origin/staging' into develop 2025-05-26 13:25:05 +02:00
Andrés Moya
050ffa235c ⬆️ Update cuerdas library (#6556) 2025-05-26 13:22:30 +02:00
Eva Marco
3dfccdaf9b ♻️ Put token settings under config flag (#6551) 2025-05-26 12:57:32 +02:00
Marina López
e5bc369e56 Visual indicators subscription for teams and project settings (#6546)
*  Visual indicators subscription for teams and project settings

* 📎 Fixes PR feedback

---------

Co-authored-by: Andrey Antukh <niwi@niwi.nz>
2025-05-26 12:56:40 +02:00
Andrey Antukh
fdd6502671 📚 Update changelog 2025-05-26 12:41:34 +02:00
Andrey Antukh
e698fd7d35 🐛 Fix path node type change operation 2025-05-26 12:13:52 +02:00
Andrés Moya
5e8929e504 🔧 Refactor token json file import/export 2025-05-26 12:02:26 +02:00
Alejandro Alonso
3ee3ee2059 Merge pull request #6553 from penpot/alotor-bug-fix-grid-editor-problem
🐛 Fix problem with grid editing
2025-05-26 11:40:24 +02:00
alonso.torres
9eacde567d 🐛 Fix problem with grid editing 2025-05-26 11:20:09 +02:00
Alejandro Alonso
ac0b74e11a Merge pull request #6549 from penpot/niwinz-staging-hotfix-1
🐛 Fix incorrect relink operation for stroke image
2025-05-26 09:50:52 +02:00
Stephan Paternotte
24d4871b23 🌐 Add translations for: Dutch
Currently translated at 99.9% (1807 of 1808 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/nl/
2025-05-25 04:01:45 +00:00
Andrey Antukh
9638fd274f Merge pull request #6547 from penpot/eva-remove-deprecated-props
♻️ Update docs and remove deprecated props
2025-05-24 11:18:53 +02:00
Andrey Antukh
b5d96d312a 🐛 Fix incorrect relink operation for stroke image 2025-05-24 09:16:10 +02:00
Edgars Andersons
f88420efb5 🌐 Add translations for: Latvian
Currently translated at 96.7% (1750 of 1808 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/lv/
2025-05-23 20:01:44 +02:00
Nicola Bortoletto
c301d95f20 🌐 Add translations for: Italian
Currently translated at 99.7% (1804 of 1808 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/it/
2025-05-23 20:01:44 +02:00
Eva Marco
7c072abe28 📚 Update docs without props obj 2025-05-23 12:57:24 +02:00
Eva Marco
603e41bbfd ♻️ Remove mf/props obj from DS components 2025-05-23 12:57:02 +02:00
Pablo Alba
b561ad033c 🐛 Fix restore component when its original parent with layout is deleted 2025-05-23 12:11:35 +02:00
luisδμ
7373056037 Improve formula validating and parsing (#6527) 2025-05-23 12:08:50 +02:00
luisδμ
a9173f672d 🐛 Sanitize inputs for variant property names and values (#6532) 2025-05-23 12:08:39 +02:00
luisδμ
44829ff1ae Use different copies for different variant selection cases (#6544)
*  Use different copies for different variant selection cases

* 📎 PR changes
2025-05-23 12:08:24 +02:00
Andrey Antukh
927ee9e55e Add get-owned-teams rpc method 2025-05-23 11:20:35 +02:00
Xavier Julian
066b252522 Add composition and slots documentation to storybook 2025-05-23 10:12:20 +02:00
luisδμ
556a68a78f Select all variants with errors (#6533) 2025-05-23 09:21:57 +02:00
Belén Albeza
f9bbf2d524 Improve paths deserialization (wasm) (#6501)
* ♻️ Refactor path wasm code to its own wasm submodule

* ♻️ Use unified enum for RawSegmentData and transmute to deserialize

* ♻️ Move set_shape_path_attrs to wasm::paths module

* 💄 Unify repr declarations
2025-05-23 08:48:55 +02:00
alonso.torres
eaaca5629e 🐛 Fix problem with sidebar layout 2025-05-22 18:35:08 +02:00
Andrey Antukh
0df2a12814 Merge remote-tracking branch 'origin/staging' into develop 2025-05-22 13:34:46 +02:00
Andrey Antukh
df27db1996 Merge pull request #6531 from mdbenito/fix/choppy-closest-point
 Fix choppy behaviour of new node on path
2025-05-22 13:24:04 +02:00
Miguel de Benito Delgado
7fc0d15418 🐛 Fix cursor overlap query (#6530)
* 🐛 Fix cursor overlap query. Closes #4472

* 📎 Update CHANGES.md

---------

Signed-off-by: Miguel de Benito Delgado <m.debenito.d@gmail.com>
2025-05-22 13:22:52 +02:00
Eva Marco
99fb905070 🐛 Fix at icon (#6540) 2025-05-22 13:15:09 +02:00
Stephan Paternotte
e74cf1836f 🌐 Add translations for: Dutch
Currently translated at 99.9% (1807 of 1808 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/nl/
2025-05-22 13:06:02 +02:00
Edgars Andersons
dfdc1ac35b 🌐 Add translations for: Latvian
Currently translated at 96.4% (1743 of 1808 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/lv/
2025-05-22 13:06:01 +02:00
Yaron Shahrabani
97a5a93694 🌐 Add translations for: Hebrew
Currently translated at 96.2% (1740 of 1808 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/he/
2025-05-22 13:06:00 +02:00
Ingrid Pigueron
dd0b8f8f6e 🌐 Add translations for: French
Currently translated at 97.3% (1760 of 1808 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/fr/
2025-05-22 13:05:58 +02:00
Alejandro Alonso
413fc6de16 Merge pull request #6536 from penpot/niwinz-update-promesa
⬆️ Update dependencies
2025-05-22 12:49:00 +02:00
Aitor Moreno
d54a7d0401 Merge pull request #6526 from penpot/superalex-improve-zoom-performance-and-behaviour
🐛 Fix zoom performance and behaviour
2025-05-22 12:15:38 +02:00
Alejandro Alonso
ed53793d9d 🐛 Fix render shapes in multiple tiles with high dprs (#6538) 2025-05-22 12:10:51 +02:00
María Valderrama
faa68784af 💄 Add styles for external widgets on workspace (#6509)
* 💄 Add styles for Inkeep Chat at workspace

* 📎 Styles review
2025-05-22 11:56:45 +02:00
Aitor Moreno
58b1cf6b0c Merge pull request #6491 from penpot/alotor-perf-pixel-precision
 Pixel precision for new renderer
2025-05-22 11:37:11 +02:00
Andrey Antukh
f9c9e865b5 🐛 Remove unexpected modified-at on binfile-v3 import 2025-05-22 10:53:23 +02:00
Andrey Antukh
ebe321d9d3 ⬆️ Update dependencies on exporter 2025-05-22 10:53:23 +02:00
Andrey Antukh
0683fbd17c ⬆️ Update backend dependencies 2025-05-22 10:53:23 +02:00
Andrey Antukh
09a7ef3e45 ⬆️ Upgrade frontend dependendencies 2025-05-22 10:53:23 +02:00
Andrey Antukh
172b70d8a7 ⬆️ Upgrade promesa library to latest version
That fixes a workaround introduced in previous commits
2025-05-22 10:53:23 +02:00
Alejandro Alonso
3597e5bb54 🐛 Fix zoom performance and behaviour 2025-05-22 10:29:43 +02:00
Eva Marco
949b6d1205 🎉 Add missing translation (#6534) 2025-05-22 10:24:41 +02:00
Eva Marco
c0af77faf7 📚 Add css rules to the UI guide (#6521)
* 📚 Add css rules to UI guide

* 🐛 Solve comments on PR

* 🐛 Add missing class

* 🐛 Improve css modules improvement

* 🐛 Fix width

* 🐛 Fix note
2025-05-22 10:06:03 +02:00
Miguel de Benito Delgado
8f7a674000 🔥 Remove unused fn types.path.segment.path-closest-point 2025-05-21 21:32:18 +02:00
Miguel de Benito Delgado
e4f2dfaa11 Make precision closest point computation depend on zoom 2025-05-21 21:29:40 +02:00
Andrey Antukh
ec29c4f5fe Merge pull request #6528 from penpot/ladybenko-11076-fix-xywh-inputs
🐛 Fix misalignment in measure section (design tab)
2025-05-21 21:05:38 +02:00
Elena Torró
c21f5221bb Merge pull request #6453 from penpot/elenatorro-10900-add-text-fills
🎉 Add text fills
2025-05-21 18:46:04 +02:00
Elena Torro
42ef2f929a 🎉 Add text fills 2025-05-21 18:32:50 +02:00
Belén Albeza
2b21401368 🐛 Fix clip buttons size 2025-05-21 17:08:56 +02:00
Belén Albeza
a5c8063b2c 🐛 Fix presets menu alignment 2025-05-21 17:01:23 +02:00
Belén Albeza
2ad2af2aea 🐛 Fix measures inputs' alignment 2025-05-21 16:58:49 +02:00
Eva Marco
c2ce7c6cf6 🐛 Remove unnecesary icon (#6524) 2025-05-21 15:44:25 +02:00
María Valderrama
47490db4be 💄 Add styles for external widgets on workspace (#6509)
* 💄 Add styles for Inkeep Chat at workspace

* 📎 Styles review
2025-05-21 14:17:48 +02:00
andrés gonzález
a2ac2bc6c6 Change copy as SVG menu order (#6523) 2025-05-21 13:12:33 +02:00
Elena Torró
e80ca7e332 Merge pull request #6439 from penpot/elenatorro-11035-fix-overflow-x-scroll-on-sidebar
🐛 Fix default scroll visibility on layers sidebar
2025-05-21 11:51:32 +02:00
Elena Torro
e4644ff506 🔧 Use scroll only on layers and refactor layer element name 2025-05-21 11:36:24 +02:00
Andrey Antukh
662b926b4b 🌐 Rehash all translations 2025-05-21 11:20:36 +02:00
Miguel de Benito Delgado
6319ed78f9 🌐 Add missing translation strings for error messages (#6519)
* 🌐 Add i18n strings for some error messages

* 🌐 Add fr, de, es translations for some error messages
2025-05-21 11:17:53 +02:00
Eva Marco
3abc8774f6 ♻️ Change translation string from workspace.token to workspace.tokens (#6508)
* ♻️ Change string translation for tokens

* ♻️ Apply find-and-replace on translation files

---------

Co-authored-by: Andrey Antukh <niwi@niwi.nz>
2025-05-21 11:17:05 +02:00
Anonymous
af1c90c252 🌐 Add translations for: Swedish
Currently translated at 89.4% (1612 of 1803 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/sv/
2025-05-21 10:44:23 +02:00
Anonymous
8019ae7840 🌐 Add translations for: Dutch
Currently translated at 95.7% (1726 of 1803 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/nl/
2025-05-21 10:44:22 +02:00
Anonymous
6bd615ff8b 🌐 Add translations for: Latvian
Currently translated at 95.7% (1726 of 1803 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/lv/
2025-05-21 10:44:22 +02:00
Anonymous
c4a793d306 🌐 Add translations for: Ukrainian (ukr_UA)
Currently translated at 95.7% (1726 of 1803 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/ukr_UA/
2025-05-21 10:44:22 +02:00
Anonymous
631b3ac062 🌐 Add translations for: Croatian
Currently translated at 89.9% (1621 of 1803 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/hr/
2025-05-21 10:44:22 +02:00
Anonymous
48995850fa 🌐 Add translations for: Portuguese (Portugal)
Currently translated at 88.4% (1594 of 1803 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/pt_PT/
2025-05-21 10:44:21 +02:00
Anonymous
a5c7a2c97b 🌐 Add translations for: Czech
Currently translated at 89.8% (1620 of 1803 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/cs/
2025-05-21 10:44:20 +02:00
Anonymous
3a8285bc69 🌐 Add translations for: Italian
Currently translated at 95.6% (1724 of 1803 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/it/
2025-05-21 10:44:20 +02:00
Anonymous
02e3cc089e 🌐 Add translations for: Chinese (Traditional Han script)
Currently translated at 90.1% (1625 of 1803 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/zh_Hant/
2025-05-21 10:44:20 +02:00
Anonymous
17e19afcbd 🌐 Add translations for: Hebrew
Currently translated at 95.7% (1726 of 1803 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/he/
2025-05-21 10:44:19 +02:00
Anonymous
a2b52a6408 🌐 Add translations for: Indonesian
Currently translated at 95.7% (1726 of 1803 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/id/
2025-05-21 10:44:19 +02:00
Anonymous
8cc4b69291 🌐 Add translations for: German
Currently translated at 92.1% (1661 of 1803 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/de/
2025-05-21 10:44:19 +02:00
Anonymous
045ddf5829 🌐 Add translations for: Portuguese (Brazil)
Currently translated at 70.9% (1279 of 1803 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/pt_BR/
2025-05-21 10:44:18 +02:00
Anonymous
1d0335aba6 🌐 Add translations for: French
Currently translated at 95.7% (1727 of 1803 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/fr/
2025-05-21 10:44:18 +02:00
Anonymous
5412d72236 🌐 Add translations for: Spanish
Currently translated at 98.8% (1782 of 1803 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/es/
2025-05-21 10:44:17 +02:00
Anonymous
896ee43212 🌐 Add translations for: English
Currently translated at 99.8% (1800 of 1803 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/en/
2025-05-21 10:44:17 +02:00
alonso.torres
5d42b9793b 🐛 Fix some problems with layouts 2025-05-21 10:42:03 +02:00
alonso.torres
6cd2c712ab Pixel precision for new renderer 2025-05-21 10:42:03 +02:00
Elena Torro
a575410a29 🐛 Fix default scroll visibility on layers sidebar 2025-05-21 10:38:27 +02:00
Hosted Weblate
6b5703c1fe 🌐 Update translation files
Updated by "Cleanup translation files" hook in Weblate.

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/
2025-05-21 10:38:18 +02:00
Andrey Antukh
22c3d4d807 Merge remote-tracking branch 'weblate/develop' into develop 2025-05-21 10:37:42 +02:00
luisδμ
b0701f6bb4 Control malformed variant formulas (#6473)
*  Control malformed variant strings

* 📎 PR changes

* 📎 PR changes
2025-05-21 10:18:11 +02:00
Alejandro Alonso
0748ef7267 Merge pull request #6518 from penpot/niwinz-staging-tokenslib-json-encoding
🐛 Add json encoding for tokenslib type
2025-05-21 10:17:37 +02:00
Pablo Alba
9bad9b8e91 🐛 Fix restore component when its original parent is deleted (#6517) 2025-05-21 10:05:22 +02:00
Andrey Antukh
9ca4fa752c 🐛 Add json encoding for tokenslib type 2025-05-21 09:59:28 +02:00
Andrey Antukh
b6563f620b 📎 Allow merge commits on commit linter 2025-05-21 09:34:05 +02:00
Andrey Antukh
a63fa2944d Merge remote-tracking branch 'origin/staging' into develop 2025-05-21 09:23:15 +02:00
Miguel de Benito Delgado
fd89c9d82c Avoid double id lookup when calling lookup-page-objects (#6513) 2025-05-20 22:31:40 +02:00
Andrey Antukh
a706907b26 ♻️ Normalize logical deletion to future dates
Instead of managing the ...
2025-05-20 22:25:57 +02:00
Andrey Antukh
a3b4fc9545 🔥 Remove unused function from workspace.media ns 2025-05-20 22:25:57 +02:00
Miguel de Benito Delgado
71bb2556f9 ♻️ Move page setup out of the data.workspace ns (#6502)
* ♻️ Split history workspace.cljs to workspace/pages.cljs - rename file to target-name

* ♻️ Split history workspace.cljs to workspace/pages.cljs - rename source-file to git-split-temp

* ♻️ Split history workspace.cljs to workspace/pages.cljs - restore name of source-file

* ♻️ Cleanup after adding new ns, add exports

* ♻️ Move set-plugin-data to main.data.plugins

* 🐛 Possible bugfix, cherry-picked from commit 8f7c63d6e2 (conflict during refactor)

---------

Co-authored-by: Eva Marco <eva.marco@kaleidos.net>
2025-05-20 22:11:05 +02:00
Miguel de Benito Delgado
f36aa30525 Add copy-as-svg to contextual menu (#6510)
*  Add "copy as svg" to contextual menu

* 🌐 Add a few translations of the new string

* 📚 Document commit message format for translations

* 📎 Log SVG import errors to the console

* 📎 Update CHANGES.md (two PRs)

---------

Signed-off-by: Miguel de Benito Delgado <m.debenito.d@gmail.com>
2025-05-20 22:06:36 +02:00
Eva Marco
8f7c63d6e2 Add base font fallback (#6468)
*  Add base font fallback

* ♻️ Add asserts to change-builder

* 🐛 Change fn name
2025-05-20 17:27:04 +02:00
Andrey Antukh
965b22718f 📚 Update changelog 2025-05-20 15:46:56 +02:00
Miguel de Benito Delgado
48a3d38d82 Add the Shift+ctrl+drag to deselect (#6494)
*  Allow shape deselection using Ctrl+Shift+Drag

*  Allow point deselection using Ctrl+Shift+Drag

*  Properly remember previous selection during addition/removal of shapes

*  Preload point selection in path handle-area-selection

Also: prefer dm/get-in over get-in

*  Highlight path nodes in selection rectangle incrementally
2025-05-20 15:23:05 +02:00
Florian Schroedl
31f642ed25 ♻️ Use rx streams for style dictionary interface 2025-05-20 14:55:07 +02:00
andrés gonzález
9f414b6ecd 📚 Update changelog (#6511) 2025-05-20 14:14:17 +02:00
Alejandro Alonso
334d7833d5 Merge pull request #6490 from penpot/azazeln28-refactor-iteration-performance
♻️ Refactor tile iteration
2025-05-20 13:56:37 +02:00
Alejandro Alonso
ff9c8f5929 Merge pull request #6483 from penpot/niwinz-staging-bugfixes-error-report
🐛 Several bugfixes
2025-05-20 13:54:54 +02:00
Xavier Julian
f7311cbb6b ♻️ Ensure tokens feature integrates design system 2025-05-20 13:52:38 +02:00
Alejandro Alonso
e4c563f917 Merge pull request #6479 from penpot/niwinz-develop-json-encoding-fix
🐛 Fix exception on rendering openapi.json
2025-05-20 13:46:16 +02:00
Andrey Antukh
2d3ad5a88f 📎 Update changelog 2025-05-20 13:30:04 +02:00
Andrey Antukh
1334d733cd 🐛 Fix openapi json generation for :re schemas 2025-05-20 13:29:44 +02:00
Andrey Antukh
004a9f17d3 Add minor js-like type schema formatting improvements 2025-05-20 13:29:44 +02:00
Andrey Antukh
c87fa4f723 Make the rpc doc generation lazy 2025-05-20 13:29:44 +02:00
Andrey Antukh
9378a5786f Replace json library used for generate openapi json 2025-05-20 13:29:44 +02:00
Andrey Antukh
3224ba26f1 ♻️ Replace :any schema with own ::sm/any
That a more specific, json friendly generator
2025-05-20 13:29:44 +02:00
Andrey Antukh
d33a5e6df1 Backport from develop partial improvements to sm/register! helper 2025-05-20 13:29:44 +02:00
Alejandro Alonso
0d60e3d997 Merge pull request #6486 from penpot/niwinz-library-export
 Add .penpot export support for penpot library
2025-05-20 13:27:11 +02:00
Andrey Antukh
645c4a57db Add playground file with example of how to create a component
This also fixes several internal issues related to component
creaton.
2025-05-20 13:06:07 +02:00
Andrey Antukh
778de6adaf Add minimal testing structure 2025-05-20 13:06:07 +02:00
Andrey Antukh
29d23577d2 🎉 Add .penpot (binfile-v3) support for library 2025-05-20 13:06:07 +02:00
Andrey Antukh
1fea1e8f5b 🔥 Remove unused svg parsing code from common 2025-05-20 13:06:07 +02:00
Andrey Antukh
c8a211742a 🔥 Remove already broken and unused internal components-v2 migration code 2025-05-20 13:06:06 +02:00
Andrey Antukh
2da8747485 ♻️ Move library to its own directory 2025-05-20 13:05:52 +02:00
Andrey Antukh
6803c78e80 Change naming and schema registation on tokens lib 2025-05-20 13:05:52 +02:00
Andrey Antukh
d8daea72de ⬆️ Update promesa library 2025-05-20 13:05:52 +02:00
Andrey Antukh
36b162b4fa ♻️ Replace jszip usage with zip.js library 2025-05-20 13:05:52 +02:00
Andrey Antukh
4c487834f0 Add the ability to deref internal state on library file instance 2025-05-20 13:05:52 +02:00
Andrey Antukh
dc7e53881a 🔥 Remove legacy-zip exportation support 2025-05-20 13:05:52 +02:00
Alejandro Alonso
1a01c9ee4a Merge pull request #6500 from penpot/niwinz-develop-svg-fixes
🐛 Fix svg path parsing on uploading svg image
2025-05-20 12:58:48 +02:00
Yamila Moreno
b6be416c7b 📎 Add wasm envvar to manage script 2025-05-20 12:15:14 +02:00
Florian Schroedl
4a27e8d1dd 🐛 Prevent unkown tokens hint always showing 2025-05-20 10:53:04 +02:00
Aitor Moreno
1bc97f9ad0 Merge pull request #6505 from penpot/supearlex-fix-avoid-unncesary-clone-for-new-render
🐛 Avoid unnecesary clone call
2025-05-20 10:07:23 +02:00
Aitor Moreno
aaa57cb17f 🐛 Fix inline styles in code tab (#6428) 2025-05-20 10:05:35 +02:00
Alejandro Alonso
b2d6342422 🐛 Avoid unnecesary clone call 2025-05-20 09:45:19 +02:00
Andrés Moya
ba1e16b55b 🐛 Fix token directory import 2025-05-20 09:42:38 +02:00
Aitor Moreno
ef95e3ecb0 ♻️ Refactor tile iteration 2025-05-19 16:24:52 +02:00
Eva Marco
55d21761fc Add multi file import on tokens (#6444)
*  Implement token multi-file import

* ♻️ Refactor import modal UI

* 🐛 Fix comments

---------

Co-authored-by: Florian Schroedl <flo.schroedl@gmail.com>
2025-05-19 16:12:46 +02:00
Andrey Antukh
0b4a367e9e 🐛 Fix svg path parsing on uploading svg image 2025-05-19 15:35:58 +02:00
Andrey Antukh
8f2ca15ec0 Merge pull request #6495 from mdbenito/refactor/frontend-app-main-data-workspace-clipboard
♻️ Factor clipboard code out of frontend/src/app/main/data/workspace.cljs
2025-05-19 15:20:52 +02:00
Aitor Moreno
21041eb925 Merge pull request #6496 from penpot/superalex-fix-path-performance
🐛 Fix paths performance in new render
2025-05-19 13:57:20 +02:00
Pablo Alba
53cfc29a1f Merge pull request #6425 from penpot/palba-variants-overrides-same-name
 Manage layers with the same name on variants overrides
2025-05-19 13:51:16 +02:00
Alejandro Alonso
96d44e0631 🐛 Fix paths performance in new render 2025-05-19 12:22:42 +02:00
Belén Albeza
8afd217a80 🔧 Enable back clippy rules (#6492)
* 🔧 Fix lint script (rust)

* 🔧 Temporarily add clippy rules to ignore so lint script passes

* 💄 Fix clippy rule crate_in_macro_def

* 💄 Fix clippy rule redundant-static-lifetimes

* 💄 Fix clippy rule unnecessary_cast

* 💄 Fix clippy rule nonminimal_bool

* 💄 Fix clippy rule redundant_pattern_matching

* 💄 Fix clippy rule assign_op_pattern

* 💄 Fix clippy rule needless_lifetimes

* 💄 Fix clippy rule for_kv_map

* 💄 Fix clippy rule ptr_arg

* 💄 Fix clippy rule match_like_matches_macro

* 💄 Fix clippy rule macro_metavars_in_unsafe

* 💄 Fix clippy rule map_clone

* 💄 Fix clippy rule wrong_self_convention

* 💄 Fix clippy rule vec_box

* 💄 Fix clippy rule useless_format

* 💄 Fix clippy rule unwrap_or_default

* 💄 Fix clippy rule unused_unit

* 💄 Fix clippy rule unnecessary_to_owned

* 💄 Fix clippy rule too_many_arguments

* 💄 Fix clippy rule slow_vector_initialization

* 💄 Fix clippy rule single_match

* 💄 Fix clippy rule redundant_field_names

* 💄 Fix clippy rule rendudant_closure

* 💄 Fix clippy rule needless_return

* 💄 Fix clippy rule needless_range_loop

* 💄 Fix clippy rule needless_borrows_for_generic_args

* 💄 Fix clippy rule needless-borrow

* 💄 Fix clippy rule missing_transmute_annotations

* 💄 Fix clippy rule map_entry

* 💄 Fix clippy rule manual_map

* 💄 Fix clippy rule len_zero

* 💄 Fix clippy rule from_over_into

* 💄 Fix clippy rule field_reassign_with_default

* 💄 Fix clippy rule enum_variant_names

* 💄 Fix clippy rule derivable_impls

* 💄 Fix clippy rule clone_on_copy

* 💄 Fix clippy rule box_collection

* 🔧 Make lint script also check test config target

* 🔧 Remove cargo-watch as a lib dependency

* 💄 Fix clippy rule for join_bounds

* 🔧 Fix lint script return code

---------

Co-authored-by: alonso.torres <alonso.torres@kaleidos.net>
2025-05-19 11:14:55 +02:00
Miguel de Benito Delgado
330e49db56 ♻️ Cleanup after adding new ns, add exports 2025-05-18 18:49:59 +02:00
Miguel de Benito Delgado
aa39170d47 ♻️ Split history workspace.cljs to workspace/clipboard.cljs - restore name of source-file 2025-05-18 18:49:07 +02:00
Miguel de Benito Delgado
8fa7a69094 ♻️ Split history workspace.cljs to workspace/clipboard.cljs - resolve conflict and keep both files 2025-05-18 18:49:07 +02:00
Miguel de Benito Delgado
33d989feb2 ♻️ Split history workspace.cljs to workspace/clipboard.cljs - rename source-file to git-split-temp 2025-05-18 18:49:07 +02:00
Miguel de Benito Delgado
e309a57223 ♻️ Split history workspace.cljs to workspace/clipboard.cljs - rename file to target-name 2025-05-18 18:49:07 +02:00
Andrey Antukh
0b289153cb Add the ability to disable wasm on build script 2025-05-18 17:30:41 +02:00
Andrey Antukh
cf274099c4 Improve events/sse internal API
For make code cleaner and more evident for a quick view
2025-05-18 17:30:41 +02:00
Andrey Antukh
6524e75770 💄 Fix check-fn naming on types.container 2025-05-18 17:30:41 +02:00
Andrey Antukh
9b80f7c9b3 💄 Don't return unnecesary object from db query
the return value is already ignored
2025-05-18 17:30:41 +02:00
Andrey Antukh
bf76f328c8 Remove duplicate error logging on sse response 2025-05-18 17:30:41 +02:00
Xavier Julian
051c2a7e99 🐛 Fix sloppy behaviour on tokens value inputs 2025-05-16 15:42:25 +02:00
Xavier Julian
887fa6b77b Add slots feature to DS input component 2025-05-16 15:42:25 +02:00
Andrey Fedorov
d9f98008f4 Add unknown token type reporting 2025-05-16 15:09:36 +02:00
Alejandro Alonso
0cb6e0dee2 🐛 Fix new render zoom (#6488)
* 🐛 Fix new render zoom

* 🐛 Use scale instead of just zoom in get_tiles_for_viewbox

---------

Co-authored-by: Belén Albeza <belen@hey.com>
2025-05-16 10:49:03 +02:00
Andrey Antukh
ad87e9842d Merge pull request #6429 from penpot/yms-update-ubuntu-in-docker-images
🐳 Update docker images and dependencies
2025-05-16 10:38:56 +02:00
Miguel de Benito Delgado
e22a55334e 💄 Rename some namespace aliases for consistency (#6485) 2025-05-15 17:43:02 +02:00
Elena Torró
f5e81debbc Merge pull request #6478 from penpot/ladybenko-11030-fix-dpr-fills
🐛 Fix fills & strokes when dpr > 1
2025-05-15 16:04:30 +02:00
andrés gonzález
ddfd55261d :Books: Update design tokens doc (#6487) 2025-05-15 14:44:51 +02:00
Belén Albeza
300e24b403 🐛 Fix drawing shapes when dpr > 1 2025-05-15 11:01:14 +02:00
Andrey Antukh
a00e7c1061 Merge remote-tracking branch 'origin/staging' into develop 2025-05-15 09:52:31 +02:00
Alonso Torres
ba25ce3098 🐛 Fix share button being displayed with no permissions (#6476)
* 🐛 Fix share button being displayed with no permissions

*  Simplify impl by accessing perms from teams directly

---------

Co-authored-by: Andrey Antukh <niwi@niwi.nz>
2025-05-15 09:49:29 +02:00
Miguel de Benito Delgado
968ea56197 ♻️ Reorganize index management on worker code (#6477)
* ♻️ Factor index management out of app.worker.impl

* 💄 Fix silly spacing

* 💄 Lint
2025-05-15 09:46:49 +02:00
Miguel de Benito Delgado
2635873b9a 📚 Update CONTRIBUTING.md with formatting and linting (#6480) 2025-05-15 09:41:33 +02:00
Alejandro Alonso
f5f1316f0b Merge pull request #6474 from penpot/superalex-develop-paste-html-fix
🐛 Fix exception on paste invalid html
2025-05-14 16:16:53 +02:00
Andrey Antukh
79a164be6d 🐛 Fix exception on paste invalid html 2025-05-14 16:07:01 +02:00
alonso.torres
ecb85778bc 🐛 Fix problem with path edition of shapes 2025-05-14 14:45:29 +02:00
Elena Torró
676c4d2dfe Merge pull request #6472 from penpot/alotor-perf-selrect-modifiers
 Set selrect for new render modifiers
2025-05-14 14:19:38 +02:00
Andrés Moya
5b8d1c1ca6 Merge branch 'hiru-update-tech-guide' 2025-05-14 13:23:38 +02:00
Andrés Moya
24e2948407 📚 Update code samples 2025-05-14 13:22:49 +02:00
Andrés Moya
c569c71306 📚 Update Tech Guide about abstraction levels 2025-05-14 13:22:38 +02:00
Andrés Moya
2cdc241e68 Merge branch 'hiru-update-tech-guide' into staging 2025-05-14 12:00:03 +02:00
Andrés Moya
057bf9bf25 📚 Update code samples 2025-05-14 11:38:55 +02:00
Andrés Moya
2ddcd0ce15 📚 Update Tech Guide about abstraction levels 2025-05-14 11:37:28 +02:00
alonso.torres
fef08dfa18 Set selrect for new render modifiers 2025-05-14 11:21:43 +02:00
Andrey Antukh
831422feaf ⬆️ Update several npm dependencies on frontend module 2025-05-14 10:39:34 +02:00
Andrey Antukh
d01e3085f4 ⬆️ Update yarn to 4.9.1 2025-05-14 10:39:34 +02:00
Andrey Antukh
d9ca82dc15 ⬆️ Update dependencies 2025-05-14 10:39:34 +02:00
Yamila Moreno
1e7127d98a 🐳 Update frontend image to nginx:1.28.0 2025-05-14 10:39:34 +02:00
Yamila Moreno
002ae8b91a 🐳 Update docker images to ubuntu 24.04 2025-05-14 10:39:34 +02:00
Aitor Moreno
6831acb71d Merge pull request #6465 from penpot/superalex-fix-render-wasm-maks
🐛 Fix new render masks
2025-05-14 10:33:52 +02:00
Alejandro Alonso
1f44d53f6b 🐛 Fix new render masks 2025-05-13 15:41:41 +02:00
Alonso Torres
ca2891d441 🐛 Fix problem syncing library colors and typographies (#6467) 2025-05-13 13:28:16 +02:00
Belén Albeza
91fbe8f8ef 🎉 Cap stop amount in UI for wasm (#6438)
* 🎉 Cap in the colorpicker the amount of stops a gradient can have

* 🎉 Cap the stops amount in gradient handlers

* 🎉 Disable add stop in gradient handlers (viewport + colorpicker)

*  Add integration test for gradient limits

* 💄 Address PR suggestion
2025-05-13 10:37:05 +02:00
Miguel de Benito Delgado
69cc4fb4c2 📚 Add missing command to open a repl on frontend process (#6458)
* 📚 Add missing command to open a repl on frontend process

* 📚 Add further information on starting a REPL on the frontend process
2025-05-13 08:10:52 +02:00
Elenzakaleidos
37abb7b237 💄 Update video in readme page (#6461)
Signed-off-by: Elenzakaleidos <elena.scilinguo@kaleidos.net>
2025-05-13 08:10:19 +02:00
Ramiro Andres Sanchez Balo
5fc2208c16 📚 Improve metadata descriptions (#6457) 2025-05-13 08:09:59 +02:00
Alejandro Alonso
c2b67d7c67 Merge pull request #6459 from penpot/superalex-fix-wasm-playground-fills-size
🐛 Fix wasm playground fills size
2025-05-13 06:23:48 +02:00
Pablo Alba
294ce7bb1b 🐛 Fix variants override for nested components (#6421) 2025-05-12 15:50:06 +02:00
Andrey Antukh
a558bfdb2f Merge remote-tracking branch 'origin/staging' into develop 2025-05-12 15:16:19 +02:00
Andrey Antukh
86bcd1b681 🐛 Fix issue on shortcuts restore operation (#6462)
* 🐛 Fix issue on shortcuts restore operation

Happens when the order of shortcuts pop events is inconsistent with
push events. Using less strictly order policy for pop operations
allows relax this and make it eventually consistent.

* 💄 Add cosmetic changes on shortcuts hooks on colorpicker and    wport

* 📎 Update changelog

* 📎 Add PR feedback changes
2025-05-12 15:08:14 +02:00
Elena Torró
33c260c35b Merge pull request #6456 from penpot/alotor-perf-text-grow-2
 Reflow flex on grow text height
2025-05-12 14:16:29 +02:00
Andrey Antukh
94312bb35c Merge remote-tracking branch 'origin/staging' into develop 2025-05-12 13:44:24 +02:00
Andrey Antukh
70b1989f10 Merge tag '2.7.0-RC2' 2025-05-12 13:11:40 +02:00
Alejandro Alonso
eb76d16b3b 🐛 Fix wasm playground fills size 2025-05-12 12:05:10 +02:00
Xavier Julian
c0eaa75232 💄 Fix errors UI on input token for value 2025-05-12 12:03:23 +02:00
Alejandro Alonso
dbb9971482 Merge pull request #6351 from penpot/niwinz-develop-improve-cleaner
 Add cleaner to file-gc
2025-05-12 11:52:01 +02:00
Alejandro Alonso
0828994840 Merge pull request #6419 from penpot/niwinz-refactor-library
♻️ Refactor penpot library
2025-05-12 11:47:00 +02:00
ºelhombretecla
e6b5618bd3 🎉 Add 2.7 release slides (#6440) 2025-05-12 11:38:00 +02:00
Aitor Moreno
9c24d3a521 Merge pull request #6370 from penpot/superalex-improve-zoom-in-zoom-out-performance-2
🎉 Improve zoom in/out performance
2025-05-12 11:22:57 +02:00
Alejandro Alonso
480e0887e3 🎉 Improve zoom in/out performance 2025-05-12 11:10:21 +02:00
Alejandro Alonso
e0e381bdfc Merge pull request #6451 from penpot/niwinz-develop-features-binfile-v1
🐛 Apply migrations in correct order for binfile-v1
2025-05-12 11:08:10 +02:00
Alejandro Alonso
5199b306aa Merge pull request #6446 from penpot/niwinz-staging-bugfixes-2
🐛 Properly propagate export errors from worker to main thread
2025-05-12 10:47:46 +02:00
Alejandro Alonso
8febfaa21e Merge pull request #6447 from penpot/niwinz-staging-bugfixes
 Ensure read-only mode on non-workspace access to file
2025-05-12 10:43:02 +02:00
Aitor Moreno
69062f03ee Merge pull request #6449 from penpot/superalex-add-shapes-buffer
🎉 Add shapes buffer to improve memory allocation
2025-05-12 10:23:34 +02:00
alonso.torres
eb04fa19e1 Reflow flex on grow text height 2025-05-12 09:48:57 +02:00
Alejandro Alonso
03b4fe3558 🎉 Add shapes buffer to improve memory allocation 2025-05-09 15:00:02 +02:00
Andrey Antukh
b349d08155 🐛 Apply migrations in correct order for binfile-v1
The patch was already existed but only applied to binfile-v3,
with this commit, the fix is properly applied to all binfile
formats and for duplicate file operation.
2025-05-09 13:38:13 +02:00
Elena Torró
15e9d92094 Merge pull request #6445 from penpot/elenatorro-11044-fix-parsing-text-spaces
🐛 Fix parsing text spaces
2025-05-09 12:31:17 +02:00
andrés gonzález
5e675dbf0b 📚 Update changelog for 2.7 (#6448) 2025-05-09 12:20:39 +02:00
Elena Torro
a5660819de 🐛 Fix stroke paragraphs 2025-05-09 11:54:51 +02:00
luisδμ
d277fefc87 Improve combobox component (#6424) 2025-05-09 11:33:57 +02:00
Elena Torro
1383010826 🔧 Remove log 2025-05-09 11:23:06 +02:00
Elena Torro
59982c9056 🐛 Fix parsing text spaces 2025-05-09 11:23:00 +02:00
Alejandro Alonso
afcff84e38 Merge pull request #6443 from penpot/niwinz-develop-feaures-bugfix
🐛 Fix incorrect features asignation after file migration
2025-05-09 11:17:27 +02:00
Andrey Antukh
fc5d9659d6 🐛 Properly propagate export errors from worker to main thread 2025-05-09 11:15:04 +02:00
Andrey Antukh
8fa7fa8c4b 🐛 Fix incorrect features asignation after file migration 2025-05-09 10:53:16 +02:00
Elena Torró
23bde76192 Merge pull request #6437 from penpot/elenatorro-add-fill-text-strokes
🎉 Add text stroke fills
2025-05-09 10:41:12 +02:00
BDVGitHub
ca7a80fb83 📚 Update framework version
Fix Svelte version number
2025-05-09 08:46:33 +02:00
BDVGitHub
cf0d9a433d 📚 Chore: Update create-a-plugin.md
Add Svelte and change version to the updated version of in the examples on https://github.com/penpot/plugin-examples
2025-05-09 08:46:33 +02:00
Andrey Antukh
bc20598b3d Don't persist file on several read operations
after applying migrations
2025-05-08 19:15:28 +02:00
Andrey Antukh
9de8ebb52c Add read-only option for files/get-file 2025-05-08 19:12:50 +02:00
alonso.torres
568af52ebc Text grow width/height 2025-05-08 17:59:18 +02:00
Elena Torro
eddabc0d68 🎉 Add text stroke fills 2025-05-08 15:49:58 +02:00
Pablo Alba
6b300d516b 🐛 Fix restore totally deleted variant should add props as name 2025-05-08 15:01:29 +02:00
Andrey Antukh
e271caa32b Merge remote-tracking branch 'origin/staging' into develop 2025-05-08 13:41:11 +02:00
Alonso Torres
9be569c54c 🐛 Fix problem when duplicating grid layout (#6426) 2025-05-08 13:39:47 +02:00
Alonso Torres
7e6a621484 🐛 Restore component fix order inside flex (#6432) 2025-05-08 13:37:59 +02:00
Eva Marco
66b47f9444 🐛 Fix resize bar background (#6435) 2025-05-08 13:37:00 +02:00
Andrey Antukh
694a2084e2 Add file cleaner to file-gc process 2025-05-08 13:35:25 +02:00
Andrey Antukh
fef19a3c80 Add legacy flex dir cleaner 2025-05-08 13:35:25 +02:00
Andrey Antukh
3da8b945ca 📎 Don't send unnecesary features to worker 2025-05-08 13:35:24 +02:00
Andrey Antukh
8f27b82edd Extend cleaner to fix invalid root shapes 2025-05-08 13:34:48 +02:00
Andrés Moya
8b529d308c Merge pull request #6338 from penpot/hiru-rework-abstraction-levels
📚 Update Tech Guide about abstraction levels
2025-05-08 13:32:23 +02:00
Alejandro Alonso
71aa8e5a86 Merge pull request #6434 from penpot/niwinz-staging-webhook-audit
 Add webhook trigger to the audit events
2025-05-08 13:00:04 +02:00
Andrey Antukh
ab01f0b274 Merge remote-tracking branch 'origin/staging' into develop 2025-05-08 12:22:50 +02:00
Andrey Antukh
e203536506 Add webhook trigger to audit events 2025-05-08 11:56:06 +02:00
Eva Marco
b71b9edee7 🐛 Tooltip positioning tunning (#6418) 2025-05-08 11:09:58 +02:00
Elena Torró
bd514c0594 🔧 Fix linting warnings and errors (#6431) 2025-05-08 11:07:36 +02:00
Xavier Julian
36e1ad287c 💄 Fix design review for input component 2025-05-08 10:55:07 +02:00
Florian Schrödl
92f5b5f92b Allow importing token files with reference errors (#6374)
*  Allow importing token files with reference errors

*  Add test for missing references
2025-05-08 10:11:02 +02:00
Andrey Antukh
0b7b6e2c23 ♻️ Refactor penpot library 2025-05-08 09:51:25 +02:00
Elena Torró
46709fb02e Merge pull request #6379 from penpot/ladybenko-10753-fills-serialization
🎉 Serialize as bytes all fill kinds
2025-05-07 18:03:42 +02:00
Elena Torró
61eb2f4a19 🎉 Add text solid strokes (#6384)
* 🎉 Add text strokes

* 🔧 Minor refactor
2025-05-07 17:28:36 +02:00
Belén Albeza
3fe16bd8f9 🐛 Fix history panel shortcut (#6420)
*  Remove duplicate ID in file menu

* 🐛 Fix shortcut for Show Version History

*  Add regression test
2025-05-07 16:49:54 +02:00
Alejandro Alonso
a9725a1aac Merge pull request #6422 from penpot/superalex-add-even-to-power-up-link-from-workspace-menu
🐛 Add event to power up link from workspace menu
2025-05-07 15:13:31 +02:00
Belén Albeza
8f9298fac8 ♻️ Remove redundant calls to add_shape_fill 2025-05-07 14:55:54 +02:00
Alejandro Alonso
c3e76817cd 🐛 Add event to power up link from workspace menu 2025-05-07 13:45:57 +02:00
Andrey Antukh
8bdec66927 Remove the ILazySchema internal abstraction from schema ns 2025-05-07 12:17:24 +02:00
Andrey Antukh
66ee9edaf8 Add minor enhacements and naming fixes on schemas 2025-05-07 12:17:24 +02:00
Andrey Antukh
ffd7bc883d ⬆️ Update shadow-cljs to 3.0.3 on common and frontend 2025-05-07 12:17:23 +02:00
Andrey Antukh
1bcfa4b8dc 🎉 Add facility to define custom js class 2025-05-07 12:17:23 +02:00
Andrey Antukh
99e325acaf 🔥 Remove support from legacy-zip format 2025-05-07 12:14:52 +02:00
Andrey Antukh
8badd1f2eb 💄 Add cosmetic improvements to common scripts/repl
Make it consistent with backend scripts/repl
2025-05-07 12:14:51 +02:00
alonso.torres
44bf276c49 🐛 Remove print 2025-05-07 12:13:47 +02:00
Eva Marco
0f3a4db71e ♻️ Refactor modal/hide! function calls (#6415) 2025-05-07 09:53:07 +02:00
Pablo Alba
751bed4117 Manage overrides on variants switch 2025-05-07 09:29:41 +02:00
Alejandro Alonso
ea095a98ba Merge pull request #6367 from penpot/azazeln28-refactor-flush-and-submit
♻️ Flush and submit
2025-05-07 07:03:22 +02:00
Eva Marco
348a9c82bf Merge pull request #6413 from penpot/eva-fix-tooltip-display-prop
🐛 Fix tooltip display on hide
2025-05-06 19:36:29 +02:00
Eva Marco
e2918f4148 🎉 Create tooltip DS component (#6340)
*  Add new tooltip DS component

* 🎉 Add delay

* 🎉 Update docs and stories

* 🎉 Add configurable delay

* ♻️ Fix comments

* ♻️ Fix comments
2025-05-06 17:15:22 +02:00
Aitor Moreno
c45187eedd Merge pull request #6381 from penpot/alotor-perf-modifiers-refactor
 Apply modifiers changes into data
2025-05-06 15:52:57 +02:00
Elena Torró
eeea5f2cc8 Merge pull request #6411 from penpot/alotor-perf-fix-text-editor-v2-error
🐛 Fix problem with editor v2
2025-05-06 15:03:15 +02:00
alonso.torres
05b6aeef3e 🐛 Fix problem with editor v2 2025-05-06 14:50:10 +02:00
Belén Albeza
6323031b40 📚 Add serialization docs for fills 2025-05-06 14:41:40 +02:00
Andrey Antukh
6ccb6cafaa Merge pull request #6263 from penpot/niwinz-develop-path-data-optimizations-1
 Performance optimizations to path related functions
2025-05-06 13:53:56 +02:00
Andrey Antukh
be26985ca5 Make the fdata/path-data feature no-team-inheritable
And also add helpers for revert it to plain format
2025-05-06 13:39:17 +02:00
Andrey Antukh
2aa2525d0e Add db conn dynamic binding for srepl helpers 2025-05-06 13:39:17 +02:00
Andrey Antukh
7cb2f307d8 Move path-editor from selection handlers 2025-05-06 13:39:17 +02:00
Andrey Antukh
f1a557c372 Add minor performance enhacements to viewport top-bar 2025-05-06 13:39:17 +02:00
Andrey Antukh
202337b135 💄 Add cosmetic improvements for start-editing-selected event fn 2025-05-06 13:39:16 +02:00
Andrey Antukh
4e3abcbd45 🐛 Prevent NPE on get-points 2025-05-06 13:39:16 +02:00
Andrey Antukh
122e5a4b57 🐛 Fix path content json decoding mechanism 2025-05-06 13:39:16 +02:00
Andrey Antukh
1981946480 🐛 Fix incorrect path content handling on converting from shape 2025-05-06 13:39:16 +02:00
Andrey Antukh
7d327d23a2 Make consistent use of .toString with path content 2025-05-06 13:39:16 +02:00
Andrey Antukh
500c27859b 🐛 Fix geom/point zero? predicate to work correctly with mixed numeric types
Using numeric indpendent equality check: `==`
2025-05-06 13:39:16 +02:00
Andrey Antukh
c6f68e6ed1 ♻️ Use LITTLE_ENDIAN instead of BIG_ENDIAND for path encoding 2025-05-06 13:39:15 +02:00
Andrey Antukh
b48faf8fe0 Simplify impl with sharing more code
and use macros for abstract platform differences
2025-05-06 13:39:15 +02:00
Andrey Antukh
fa24ced3a3 🐛 Don't render path editor on editing grid on frame 2025-05-06 13:39:15 +02:00
Andrey Antukh
b9ea2425b9 🔥 Remove legacy path formating code 2025-05-06 13:39:15 +02:00
Andrey Antukh
1abaff9c52 Add minor improvements to curve drawing internal impl 2025-05-06 13:39:15 +02:00
Andrey Antukh
6f2ccabaa2 Coerce PathData float values to double
For avoid equality issues on JVM
2025-05-06 13:39:14 +02:00
Andrey Antukh
1c77126fe6 Implement get-handlers in term of internal reduce
That has an average performance improvement of 64% over
original impl and reduction of generation of object garbage
2025-05-06 13:39:14 +02:00
Andrey Antukh
7196be2a23 🎉 Add support for internal reduce on PathData type 2025-05-06 13:39:14 +02:00
Andrey Antukh
d509b840dc 🔥 Remove unused get-commands fn 2025-05-06 13:39:14 +02:00
Andrey Antukh
61c23877c1 Rename handler->point to get-handler-point 2025-05-06 13:39:14 +02:00
Andrey Antukh
0e61398d67 Optimize handler->point path segment helper fn
More or les x2 speed improvement and reduced the generation
of objects garbage.
2025-05-06 13:39:13 +02:00
Andrey Antukh
f12656463d Add a helper for perform internal lookup on path content 2025-05-06 13:39:13 +02:00
Andrey Antukh
ba9fc37226 🔥 Remove unused fn content->points
Replaced by get-points
2025-05-06 13:39:13 +02:00
Andrey Antukh
60f754f172 Add minor improvements to get-segments-with-points
And rename it from `get-segments`
2025-05-06 13:39:13 +02:00
Andrey Antukh
3a22545158 Replace cmd name usage with segment name
For fix naming inconsistency
2025-05-06 13:39:13 +02:00
Andrey Antukh
1d0020f6e6 Replace duplicate fn get-point with segment->point 2025-05-06 13:39:13 +02:00
Andrey Antukh
f3c3f3e2d8 🔥 Remove legacy-parser1
Unused
2025-05-06 13:39:12 +02:00
Andrey Antukh
9ba0ae5532 Replace command->point with segment->point helper 2025-05-06 13:39:12 +02:00
Andrey Antukh
db73c2eea0 Fix segment param naming on path type helpers 2025-05-06 13:39:12 +02:00
Andrey Antukh
753823c0b3 Reorganize path toString impl 2025-05-06 13:39:12 +02:00
Andrey Antukh
44e8eacb8d Add the ability to provide initial value on path -walk 2025-05-06 13:39:12 +02:00
Andrey Antukh
33bcbd89f1 Optimize calculate-extremities path helper
Heavily used on path edition
2025-05-06 13:39:11 +02:00
Andrey Antukh
b0cbe3cec8 Replace content->points with faster get-points 2025-05-06 13:39:11 +02:00
Andrey Antukh
3ca76c9ef7 ♻️ Refactor path-editor component 2025-05-06 13:39:11 +02:00
Andrey Antukh
93199e1a70 ♻️ Refactor path editor component: path-snap 2025-05-06 13:39:11 +02:00
Andrey Antukh
93a601a1e7 ♻️ Refactor path editor component: path-preview 2025-05-06 13:39:11 +02:00
Andrey Antukh
3d864c4ff1 ♻️ Refactor path editor components: path-handler and path-point 2025-05-06 13:39:11 +02:00
Andrey Antukh
da2f519805 Add get-points helper, a faster alternative to content->points 2025-05-06 13:39:10 +02:00
Andrey Antukh
230e330eb2 Add cache and faster way to iterate over PathData 2025-05-06 13:39:10 +02:00
Andrey Antukh
4f6dffabb4 ♻️ Use new call convention for path drawing components 2025-05-06 13:39:10 +02:00
Andrey Antukh
09c3490cae Add naming improvement to bool content update fn 2025-05-06 13:39:10 +02:00
Andrey Antukh
1fc0203c38 🎉 Add full integration with path data type feature 2025-05-06 13:39:10 +02:00
Andrey Antukh
f545d7b3ea ♻️ Refactor bool shape creation and modification events 2025-05-06 13:39:09 +02:00
Andrey Antukh
b242eb5b32 🔥 Remove unused components-v2 binding on fdata creation 2025-05-06 13:39:09 +02:00
Andrey Antukh
be9e3fa355 Add better error reporting for test check tests 2025-05-06 13:39:09 +02:00
Andrey Antukh
fac93e4ff8 Add serialization support for PathData
For transit and fressian
2025-05-06 13:39:09 +02:00
Belén Albeza
8609db2182 ♻️ Remove unused deserialization code 2025-05-06 13:00:25 +02:00
Belén Albeza
ec73bd640c Use mem::transmute to deserialize raw fill data 2025-05-06 12:38:30 +02:00
Belén Albeza
cba65972dd Use same wasm function to add all types of fills 2025-05-06 12:33:14 +02:00
luisδμ
e62231cfed ♻️ Rename, move and refactor the input-with-values component (#6387)
* 💄 Adapt behaviour when hovering

* ♻️ Rename, refactor and move component

* 📎 PR changes
2025-05-06 11:19:18 +02:00
Aitor Moreno
3249fb43c3 Merge pull request #6378 from penpot/elenatorro-10914-fix-children-render-order
🐛 Render children in the correct order
2025-05-06 09:59:59 +02:00
Pablo Alba
ee0ba15f9e ♻️ Refactor update attrs
* Extract token update from update-attrs

* Split update-attrs in smaller functions for legibility and reusability
2025-05-05 18:14:04 +02:00
Belén Albeza
784aecd1a1 🎉 Add a DTO that handles all fill types 2025-05-05 16:55:00 +02:00
Belén Albeza
173d6c23b0 Serialize image fills in binary 2025-05-05 15:51:21 +02:00
Aitor Moreno
abc1241402 ♻️ Refactor flush and submit 2025-05-05 15:10:20 +02:00
Belén Albeza
f30441626e ♻️ Refactor fills DTOs into separate submodules 2025-05-05 12:33:40 +02:00
Belén Albeza
5ae125db94 Serialize stroke solid fills as bytes (wasm) 2025-05-05 12:33:40 +02:00
Belén Albeza
093fa18839 Serialize solid fills as bytes (wasm) 2025-05-05 12:33:40 +02:00
Belén Albeza
81f18ad7f4 ♻️ Normalize opacity in fills to u8 2025-05-05 12:33:40 +02:00
Belén Albeza
875e019d4f ♻️ Refactor raw gradient data into wasm module 2025-05-05 12:33:40 +02:00
Belén Albeza
8e18a0880e ♻️ Use a single byte to store gradient stop count (wasm) 2025-05-05 12:33:39 +02:00
alonso.torres
36b78e5e21 🐛 Fix restore component restore layout 2025-05-05 11:50:08 +02:00
María Valderrama
86a498fc29 Optimize profile setup flow for better user experience (#6223)
*  Optimize profile setup flow for better user experience

* 📎 Remove extra onboarding step

* 📎 Code review

* 📎 Update changelog

---------

Co-authored-by: Andrey Antukh <niwi@niwi.nz>
2025-05-05 10:42:08 +02:00
Alejandro Alonso
aae81b8a04 🎉 Add wasm playground environment 2025-05-05 09:45:59 +02:00
Xaviju
486f036a11 ♻️ Redesign form input tokens (#6294)
* ♻️ Redesign form input tokens

* ♻️ Redesign form input tokens

---------

Co-authored-by: Xavier Julian <xaviju@proton.me>
2025-05-05 09:05:14 +02:00
Alonso Torres
a2c9d307df 🐛 Fix problem in viewer with the back button (#6385) 2025-05-05 08:54:05 +02:00
Andrés Moya
e52fd90963 💄 Add copyright header to all tokens source files (#6389) 2025-05-01 10:06:17 +02:00
Elena Torro
f8602810eb 🐛 Fix font id serialization 2025-04-30 11:48:07 +02:00
Pablo Alba
219ddfabaf Restore a deleted variant 2025-04-30 11:40:00 +02:00
alonso.torres
d8b3b216e9 🐛 Fix import modal style problem 2025-04-30 10:48:48 +02:00
alonso.torres
88e5209856 Apply modifiers changes into data 2025-04-30 09:34:13 +02:00
Andrey Antukh
c2b13a6d5d 📚 Update changelog 2025-04-29 14:46:15 +02:00
Elena Torro
9eefe13e8b 🐛 Render children in the correct order 2025-04-29 13:39:57 +02:00
Elena Torró
7eab6a2f1d Merge pull request #6372 from penpot/elenatorro-10892-load-emoji-font-lazily
 Load emoji font dynamically when initializing
2025-04-29 13:18:09 +02:00
Elena Torro
2306df5fb7 Load emoji font dynamically when initializing 2025-04-29 13:07:06 +02:00
Andrey Antukh
56ecacee21 Merge remote-tracking branch 'origin/staging' into develop 2025-04-29 11:30:16 +02:00
Andrey Antukh
a60b3d4b08 Merge pull request #6375 from penpot/hiru-move-tokens-staging
🔧 Reorganize tokens data functions
2025-04-29 10:43:13 +02:00
Andrés Moya
b14798b405 🔧 Make private function 2025-04-29 10:28:00 +02:00
Andrés Moya
8382a88efe 🔧 Move errors and warnings to workspace.data 2025-04-29 10:27:56 +02:00
Andrés Moya
53057c4bf2 🔧 Move token update to workspace.data and rename to propagation 2025-04-29 10:27:50 +02:00
Andrés Moya
3e0f38e8c3 🔧 Move token helpers to common.files 2025-04-29 10:27:46 +02:00
Andrés Moya
a5bbe765b9 🔧 Move style-dictionary and tinycolor to main.data 2025-04-29 10:27:42 +02:00
Andrés Moya
4455adc813 🔧 Move token lib edit to workspace.data and remove unused code 2025-04-29 10:27:38 +02:00
Andrés Moya
abca763aa5 🔧 Move token application to workspace.data 2025-04-29 10:27:20 +02:00
Andrés Moya
5c74349de0 🔧 Make private function 2025-04-29 10:11:40 +02:00
Andrés Moya
4a7b72dae1 🔧 Move errors and warnings to workspace.data 2025-04-29 10:11:40 +02:00
Andrés Moya
23e17d7f30 🔧 Move token update to workspace.data and rename to propagation 2025-04-29 10:11:40 +02:00
Andrés Moya
37cf829188 🔧 Move token helpers to common.files 2025-04-29 10:11:40 +02:00
Andrés Moya
f213ffabe1 🔧 Move style-dictionary and tinycolor to main.data 2025-04-29 10:11:40 +02:00
Andrés Moya
a1921bb767 🔧 Move token lib edit to workspace.data and remove unused code 2025-04-29 10:11:40 +02:00
Andrés Moya
213c04bc8a 🔧 Move token application to workspace.data 2025-04-29 10:11:40 +02:00
Pablo Alba
916eb530a0 Close swap panel after doing a swap 2025-04-28 11:23:42 +02:00
Andrey Antukh
1f0644ea91 Merge pull request #6314 from penpot/niwinz-subscriptions-internal-api
 Add prepl api for subscriptions
2025-04-28 10:34:29 +02:00
Andrey Antukh
b20147255a Add better approach for returning subscription on teams response 2025-04-28 10:23:02 +02:00
Andrey Antukh
38728eb342 Add the ability to known the subscription status on teams list 2025-04-28 10:23:02 +02:00
Andrey Antukh
18c7890f65 Add proper impl for retrieving num of editors 2025-04-28 10:23:02 +02:00
Andrey Antukh
1c224609b9 Add prototype for returning number of used slots on customer 2025-04-28 10:23:02 +02:00
Andrey Antukh
4b81468c9c Allow subscription to be nil 2025-04-28 10:23:02 +02:00
Andrey Antukh
cffac2a56a Change schema for subscription 2025-04-28 10:23:02 +02:00
Andrey Antukh
05c0f8d69f 🎉 Add update-customer-subscription prepl method 2025-04-28 10:23:02 +02:00
Andrey Antukh
5db5bc65de 🎉 Add get-customer-prfile prepl rpc method 2025-04-28 10:23:02 +02:00
Andrey Antukh
952ab032f9 🎉 Add authenticate prepl rpc method 2025-04-28 10:23:02 +02:00
Andrey Antukh
2df6f2b8b1 ♻️ Refactor prepl interface
Make prepl to be json message based protocol
instead of clojure expression. This facilitates
implementing internal RPC over socket server.
2025-04-28 10:23:02 +02:00
Andrey Antukh
62a12a64a3 Merge branch 'staging' into develop 2025-04-28 08:44:05 +02:00
Andrey Antukh
6935d54870 Merge branch 'main' into staging 2025-04-28 08:43:54 +02:00
Andrey Antukh
049427c6ca Merge branch 'main' into develop 2025-04-28 08:43:39 +02:00
Andrey Antukh
65e8526ee2 Merge tag '2.6.2-RC4' 2025-04-28 08:43:04 +02:00
alonso.torres
8ce71e792e Add dynamic properties modifiers to WASM 2025-04-25 15:03:24 +02:00
Andrés Moya
202762027f 🐛 Handle swapped nested instances when detaching 2025-04-25 10:00:14 +02:00
Andrés Moya
d95551e651 🔧 Add debug traces to detach copy operation 2025-04-25 10:00:14 +02:00
Elena Torro
44d68ad723 🐛 Calculate text-length in bytes correctly 2025-04-25 09:48:12 +02:00
Elena Torró
9e4c9d3101 Merge pull request #6353 from penpot/ladybenko-10867-comment-crash
🐛 Fix comment loading crash (new renderer viewport)
2025-04-25 08:41:51 +02:00
Andrey Antukh
050692952e Merge remote-tracking branch 'origin/staging' into develop 2025-04-24 15:11:12 +02:00
Xaviju
c96fbfdcd6 📚 Update tokens changelog for 2.6.2 (#6364)
Co-authored-by: Xavier Julian <xaviju@proton.me>
2025-04-24 13:29:56 +02:00
Belén Albeza
ab90d9d01c 🔧 Increase the cap for gradient stops 2025-04-24 12:20:34 +02:00
Belén Albeza
281c0068d9 Embed stop data into RawGradientData 2025-04-24 12:20:34 +02:00
Belén Albeza
e7b74939cb 💄 Change to more idiomatic code in main.rs functions 2025-04-24 12:20:34 +02:00
Elena Torró
c2ae58bf08 🎉 Add text shadows (#6335) 2025-04-24 12:19:41 +02:00
Elena Torró
14e8026e30 🐛 Fix take new lines into account when rendering text (#6337) 2025-04-24 12:16:21 +02:00
Xaviju
eb29a42209 📚 Update tokens changelog for 2.6.2 and 2.7 (#6363)
Co-authored-by: Xavier Julian <xaviju@proton.me>
2025-04-24 11:40:06 +02:00
Pablo Alba
6fdaad1bf4 🐛 Fix corner case when selecting component to switch (#6350) 2025-04-24 10:38:32 +02:00
Elena Torró
dfa6c502dc Improve left sidebar horizontal layers scroll (#6317) 2025-04-24 10:00:15 +02:00
Belén Albeza
b958dcb891 🐛 Fix positioning of comment thread draft (#6357)
* 🐛 Fix positioning of comment thread draft

* 📚 Update changelog
2025-04-24 09:53:07 +02:00
Alejandro Alonso
6e5d64d403 Merge pull request #6362 from penpot/niwinz-staging-bugfixes-2
🐛 Add migration for fix old broken root shapes (file migration)
2025-04-24 09:28:04 +02:00
Andrey Antukh
3e0c2bf1a1 🐛 Add migration for fix root shape 2025-04-24 09:17:33 +02:00
Andrey Antukh
9c4896d72b Merge remote-tracking branch 'origin/staging' into develop 2025-04-24 09:00:13 +02:00
Andrey Antukh
283cdee5d6 Ensure consistency on using d/update-vals on file migrations 2025-04-24 08:55:54 +02:00
Andrey Antukh
ab5e01e54a Ensure we don't leave :components with nil on file data
after aplying migrations
2025-04-24 08:53:30 +02:00
Alejandro Alonso
01fec1a0cf Merge pull request #6339 from penpot/azazeln28-refactor-rebuild-tiles
♻️ Refactor how rebuild_tiles works
2025-04-24 07:38:56 +02:00
Aitor Moreno
caf13eb774 ♻️ Refactor how rebuild_tiles works 2025-04-24 07:34:35 +02:00
Alejandro Alonso
373248e304 Merge pull request #6360 from penpot/niwinz-staging-bugfixes-2
🐛 Fix issues on file data migration handling
2025-04-24 07:30:50 +02:00
Marina López
fef342b489 🐛 Fixed team info settings alignment (#6354) 2025-04-23 22:59:07 +02:00
Pablo Alba
6e9adece1f 🐛 Fix problems cutting-paste a variant to another page or file (#6359) 2025-04-23 22:58:12 +02:00
Andrey Antukh
80308ceafa 🐛 Make http cache aware of missing file data migrations 2025-04-23 18:15:33 +02:00
Andrey Antukh
f65518f865 🐛 Fix incorrect migration application after binfile import 2025-04-23 18:10:52 +02:00
Andrés Moya
c0315e2c30 🔥 Remove redundant schemas (and add some tooling) 2025-04-23 12:27:01 +02:00
Andrés Moya
2f20ccf289 🔥 Remove unused functions 2025-04-23 12:27:01 +02:00
Belén Albeza
1a7d60bb88 🐛 Fix comment loading crash 2025-04-23 12:15:16 +02:00
Alejandro Alonso
90b1895f19 Merge pull request #6352 from penpot/alotor-update-scripts
🐛 Fix wasm scripts
2025-04-23 11:39:15 +02:00
alonso.torres
7945a95522 🐛 Fix wasm scripts 2025-04-23 11:21:24 +02:00
Andrey Antukh
40fe6369cb Merge remote-tracking branch 'origin/staging' into develop 2025-04-23 08:59:33 +02:00
Alejandro Alonso
f155042958 Merge pull request #6345 from penpot/niwinz-staging-add-interaction-cleaning
🐛 Add migration for decoding and cleaning shape interactions
2025-04-23 08:08:31 +02:00
Andrey Antukh
1dd23a3f47 🐛 Invalidate http cache on apply migrations to file on read operation 2025-04-23 07:57:56 +02:00
Alejandro Alonso
55da3ee275 Merge pull request #6349 from penpot/azazeln28-fix-rendering-order
🐛 Fix rendering order
2025-04-23 07:07:27 +02:00
Andrey Antukh
1194e40222 🐛 Properly dispose rx subscription on grid thumbnail component 2025-04-22 21:39:57 +02:00
Andrey Antukh
05fac41534 🐛 Remove feature checking from get-file-data-for-thumbnail rpc method
The prev code has feature resolution race condition and it
in reallity does not need that check.
2025-04-22 21:38:40 +02:00
Andrey Antukh
3f85e89f62 🐛 Send frontend version on worker http requests 2025-04-22 21:26:51 +02:00
Alonso Torres
ee0f8ad19a 🐛 Fix horizontal scroll in viewer (#6347) 2025-04-22 21:03:45 +02:00
Andrey Antukh
b7d7cf233a Fix shadow colors on import penpot files 2025-04-22 19:58:10 +02:00
Aitor Moreno
38a708e12b 🐛 Fix rendering order 2025-04-22 18:49:57 +02:00
Alonso Torres
53dcd94f0d Add support for self mentions (#6341) 2025-04-22 18:49:10 +02:00
Pablo Alba
a3ccc3dfef Select correct component to switch when changing variant property (#6346) 2025-04-22 18:48:18 +02:00
Alonso Torres
bd208c31e2 🐛 Fix update layout on component restore (#6348) 2025-04-22 18:46:21 +02:00
Andrey Antukh
151dc352c8 Don't register shadow schema
It is not really necessary, we can use the
schema var directly.
2025-04-22 17:21:52 +02:00
luisδμ
77d8504baf Selection of several components of a variant at the same time 2025-04-22 15:56:38 +02:00
Andrey Antukh
ccbf17106d 🐛 Add migration for decoding and cleaning shape interactions 2025-04-22 15:04:22 +02:00
Andrey Antukh
95c4d95fd3 📎 Use d/update-vals instead of update-vals on migrations 2025-04-22 15:01:33 +02:00
Aitor Moreno
484772e3b2 Merge pull request #6313 from penpot/superalex-improve-images-performance-wasm
🎉 Improve images performance
2025-04-22 11:36:24 +02:00
Alejandro Alonso
5c7a1fb407 🎉 Improve tile caching 2025-04-22 11:03:21 +02:00
Pablo Alba
064981ff3d Merge remote-tracking branch 'origin/staging' into develop 2025-04-22 10:44:29 +02:00
Pablo Alba
fe003d7496 Add removal of variant container when it becomes empty (#6311) 2025-04-22 09:22:18 +02:00
Pablo Alba
fae1df7f4b 🐛 Fix extract component variant from variant with path (#6303) 2025-04-22 09:18:31 +02:00
Andrey Antukh
a72c07b657 Merge pull request #6309 from penpot/niwinz-staging-bugfixes-2
🐛 Several bugfixes
2025-04-22 09:15:02 +02:00
Florian Schrödl
0bff76e5f1 Don't override user provided color format (#6231) 2025-04-22 09:10:07 +02:00
Elena Torró
c7b062f483 Merge pull request #6278 from penpot/elenatorro-send-leaf-attrs-uint-arr
🔧 Parse text leaves all at once
2025-04-21 14:27:26 +02:00
Elena Torro
83f72f3e41 🔧 Parse text leaves all at once 2025-04-21 13:24:39 +02:00
Aitor Moreno
d8b71d76dd Merge pull request #6225 from penpot/elenatorro-10710-render-text-while-typing
🎉 Render text while typing
2025-04-21 12:33:08 +02:00
Aitor Moreno
a6d2f385af Merge pull request #6266 from penpot/superalex-fix-path-unions
🐛 Fix unions for new render
2025-04-21 11:23:14 +02:00
Pablo Alba
db9e397531 🐛 Fix variant from a shared lib doesnt't show props 2025-04-21 09:25:00 +02:00
Elena Torró
18dea6c3a3 Merge pull request #6298 from penpot/ladybenko-10752-gradient-stops
 Send fill + Stops in a single wasm call
2025-04-21 09:17:26 +02:00
Alejandro Alonso
8ebaecc472 🐛 Fix unions for new render 2025-04-21 08:10:15 +02:00
Unreal Vision
58e0b26493 🌐 Add translations for: French
Currently translated at 100.0% (1730 of 1730 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/fr/
2025-04-17 15:01:43 +02:00
Corentin Noël
c75380e063 🌐 Add translations for: French
Currently translated at 100.0% (1730 of 1730 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/fr/
2025-04-17 15:01:42 +02:00
Andrey Antukh
708492afeb 💄 Add mainly cosmetic changes to dashboard placeholder components 2025-04-17 09:20:35 +02:00
Andrey Antukh
1305ab3cc6 🐛 Fix issue with empty placeholder on team change 2025-04-17 09:20:34 +02:00
Andrey Antukh
29cc6b4f9c Print the current seed on test.check fail 2025-04-17 09:20:34 +02:00
Andrey Antukh
cc7f0b145c 🐛 Make shape interaction properly decode on binfile import 2025-04-17 09:20:34 +02:00
Andrey Antukh
e69c0c3e27 Make schema uuid parsing fns private 2025-04-17 09:20:34 +02:00
Andrey Antukh
a209966427 🐛 Don't use schema uuid parsing function on websocket ns 2025-04-17 09:20:34 +02:00
Andrey Antukh
d5abbd4220 📎 Add missing entries on the changelog 2025-04-17 09:20:32 +02:00
Andrey Antukh
43a75b64b4 Merge pull request #6318 from penpot/ladybenko-10781-rust-devenv
🔧 Improve Rust dev env
2025-04-17 08:48:50 +02:00
Pablo Alba
70a23a14c4 🐛 Fix allow moving a main component into another 2025-04-16 22:54:30 +02:00
Marina López
93c81ea49c 🐛 Fix pricing CTA to be under a config flag (#6304) 2025-04-16 17:17:47 +02:00
Xaviju
3a741d1c14 🐛 Hide inactive warning if sets are empty (#6295)
* 🐛 Hide inactive warning if sets are empty

* 📎 Add simplified impl with proper comment

---------

Co-authored-by: Xavier Julian <xaviju@proton.me>
Co-authored-by: Andrey Antukh <niwi@niwi.nz>
2025-04-16 17:17:13 +02:00
Pablo Alba
ba442e1549 Allow copy-paste variants into another file (#6319) 2025-04-16 17:12:12 +02:00
Andrés Moya
8c15296d07 Merge branch 'tokens-studio-hyma/99-improve-token-error-messages' into develop 2025-04-16 16:31:53 +02:00
Florian Schroedl
d26464c810 Catch invalid name errors in json 2025-04-16 16:30:47 +02:00
Belén Albeza
8ee202e5a1 🔧 Fix emscripten version in devenv 2025-04-16 15:30:29 +02:00
Belén Albeza
689cddfd0c 🔧 Use cargo env variable for target and allow to override it as well as SKIA_BINARIES_URL 2025-04-16 15:05:31 +02:00
Elena Torró
25950bb5a5 Merge pull request #6312 from penpot/elenatorro-fix-children-removal-regression
🐛 Fix last shape removal
2025-04-16 15:03:26 +02:00
Belén Albeza
1da623e63f 💄 Change naming and args order of write-gradient-fill! 2025-04-16 14:09:24 +02:00
Belén Albeza
4bf9e24d43 ♻️ Avoid using get-prop when unneeded in serializers 2025-04-16 14:09:24 +02:00
Belén Albeza
b41a7b8547 💄 Remove no longer used functions in wasm serialization 2025-04-16 14:09:23 +02:00
Belén Albeza
f500a00d04 ♻️ Extract wasm-functions for fills and strokes out of main.rs 2025-04-16 14:09:19 +02:00
Belén Albeza
64a2a08d24 ♻️ Refactor gradient parsing from bytes 2025-04-16 14:08:38 +02:00
Belén Albeza
1f58f96e88 ♻️ Refactor serializing gradient fill 2025-04-16 14:07:35 +02:00
Belén Albeza
dc3d802d3d 🎉 Serialize radial fills in one go 2025-04-16 14:07:35 +02:00
Belén Albeza
5765d1c56c ♻️ Switch to a f32 offset for gradient stops 2025-04-16 14:07:35 +02:00
Belén Albeza
abcd050c69 ♻️ Adapt linear gradient type so it can be used for radial too (wasm) 2025-04-16 14:07:33 +02:00
Belén Albeza
f40ef26c69 ♻️ Move color and fill serializers to their own sub-namespaces 2025-04-16 14:06:22 +02:00
Belén Albeza
fccd1a5bd7 Send fill + stops data in one call for linear fills 2025-04-16 14:05:39 +02:00
Alejandro Alonso
16012a3881 Merge remote-tracking branch 'origin/staging' into develop 2025-04-16 13:15:18 +02:00
Alejandro Alonso
ddc41027ab Merge pull request #6316 from penpot/palba-fix-instanciate-component
🐛 Fix error while drag an drop a component to the canvas
2025-04-16 13:15:07 +02:00
Pablo Alba
4f931fbe6a 🐛 Fix error while drag an drop a component to the canvas 2025-04-16 13:05:56 +02:00
Marina López
7ada3692cf Design improvements to the Invitations page with an empty state 2025-04-16 12:38:47 +02:00
Elena Torro
1ab5d5027f 🐛 Fix last shape removal 2025-04-16 12:37:29 +02:00
Alejandro Alonso
1f16816fe4 Merge pull request #6310 from penpot/alotor-perf-reparent-modifiers
 Reparent modifiers
2025-04-16 12:21:20 +02:00
alonso.torres
daf048e258 Reparent modifiers 2025-04-16 11:27:51 +02:00
Alejandro Alonso
f3d13005b2 🐛 Fix avoid uncacheable tiles (#6281) 2025-04-16 10:59:24 +02:00
Elena Torró
25a44e1387 Merge pull request #6306 from penpot/ladybenko-fix-raf-macros
🐛 Fix broken test build for rust wasm
2025-04-16 07:15:27 +02:00
Belén Albeza
9e9612cf1f 🐛 Fix broken test build for rust wasm 2025-04-15 16:58:49 +02:00
Aitor Moreno
304c44048f ♻️ Refactor how rAF/cAF is handled (#6241) 2025-04-15 15:45:28 +02:00
Alejandro Alonso
99e64ad387 Merge pull request #6274 from penpot/alotor-perf-grid-layout-modifiers-3
 Modifiers grid multi-span
2025-04-15 13:39:45 +02:00
Marina López
0f0c45af8e Propagate sharing a prototype to editors and viewers (#6297) 2025-04-15 12:50:01 +02:00
Marina López
f2977cf938 Visual indicators for unlimited tier users (#6270)
*  Visual indicators for unlimited tier users

* ♻️ Refactor to organize properly subscription

* ♻️ Refactor with PR feedback

* 💄 Add minor cosmetic changes

---------

Co-authored-by: Andrey Antukh <niwi@niwi.nz>
2025-04-15 12:47:37 +02:00
Andrey Antukh
bb80da137d Merge remote-tracking branch 'origin/staging' into develop 2025-04-15 12:10:53 +02:00
Pablo Alba
f4b16a255c Copy values of same named properties moving a variant into another (#6288)
*  Copy values of same named properties moving a variant into another

*  Add MR changes
2025-04-15 12:06:58 +02:00
Andrey Antukh
b49a4734ff 🐛 Fix srepl helper for restore file snapshots 2025-04-15 11:03:50 +02:00
Marina López
ec8c30f060 Update board presets with newer devices (#6296) 2025-04-15 10:42:46 +02:00
Andrey Antukh
7990400c7a 🐛 Fix srepl helper for restore file snapshots (#6300) 2025-04-15 10:39:51 +02:00
Alejandro Alonso
2aaa2f3033 🐛 Fix template import (#6299) 2025-04-15 10:39:22 +02:00
Alejandro Alonso
202b9f3075 Merge pull request #6284 from penpot/niwinz-staging-several-bugfixes
🐛 Several bugfixes and enhacements
2025-04-15 10:33:59 +02:00
Eva Marco
eee5cf5fb4 Add duplicate sets feature (#6240)
*  Add duplicate sets feature

*  Add test to each module

* 🎉 Fix comments

* 🎉 Remove duplicate from groups

* 🎉 Remove create theme from test

* 🎉 Remove ' from names
2025-04-14 16:22:40 +02:00
Andrey Antukh
be0814cdac Improve internal error reporting 2025-04-14 13:26:12 +02:00
Xavier Julian
f5c699ab7a Improve copy on inactive set warning title 2025-04-14 10:30:48 +02:00
Andrey Antukh
80d719353c Make auth data available before request parsing
For properly report profile-id
2025-04-14 09:23:41 +02:00
Andrey Antukh
fa3fc12594 Sanitize uuid on the rest of code 2025-04-14 09:23:29 +02:00
Andrey Antukh
422a9db07b Sanitize uuid parsing on legacy zip import code 2025-04-14 09:13:35 +02:00
Andrey Antukh
a4145a30f5 🐛 Fix uuid encode/decode on schema 2025-04-14 09:13:34 +02:00
TheScientistPT
3d67c7930c 🌐 Add translations for: Portuguese (Portugal)
Currently translated at 92.3% (1598 of 1730 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/pt_PT/
2025-04-13 20:18:26 +02:00
TheScientistPT
b55ec38c35 🌐 Add translations for: Portuguese (Portugal)
Currently translated at 92.2% (1596 of 1730 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/pt_PT/
2025-04-11 23:02:00 +02:00
Stas Haas
02a1cfb457 🌐 Add translations for: German
Currently translated at 96.1% (1663 of 1730 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/de/
2025-04-11 23:01:59 +02:00
Corentin Noël
b2ba38b5de 🌐 Add translations for: French
Currently translated at 98.7% (1708 of 1730 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/fr/
2025-04-11 23:01:57 +02:00
Pablo Alba
dcf1a593f7 Add playwright tests for cut-copy-paste variants 2025-04-11 15:17:33 +02:00
Pablo Alba
785b61be2f Fix corner cases of duplicate/copy-paste/cut-paste variants 2025-04-11 15:17:33 +02:00
Elena Torró
39c7782019 Merge pull request #6264 from penpot/elenatorro-10681-update-component-color-preview
🐛 Update the component thumbnail on component change
2025-04-11 14:33:07 +02:00
Alejandro Alonso
1c5c51907a Merge remote-tracking branch 'origin/staging' into develop 2025-04-11 14:05:00 +02:00
andrés gonzález
e004671346 📚 Update Recommended storage info (#6275) 2025-04-11 14:02:35 +02:00
alonso.torres
a59014cad0 Modifiers grid multi-span 2025-04-11 13:35:16 +02:00
Andrey Antukh
38e5c161e7 Sanitize plugins uuid parsing 2025-04-11 13:21:26 +02:00
Aitor Moreno
87650de9bc 🐛 Fix color gradient on text positioned incorrectly (#6253) 2025-04-11 11:36:31 +02:00
Florian Schrödl
ee5596067e ⬆️ Upgrade style_dictionary dependency to v5-rc1 (#6283) 2025-04-11 11:31:28 +02:00
Eva Marco
870fec6bbd 🐛 Fix modal hint as context notification (#6276) 2025-04-11 11:27:30 +02:00
Alejandro Alonso
686ab14b43 Merge pull request #6282 from penpot/alotor-fix-bool-wasm
🐛 Fix problem with booleans in wasm
2025-04-11 11:06:31 +02:00
alonso.torres
fced0cf3b1 🐛 Fix problem with booleans in wasm 2025-04-11 10:56:08 +02:00
Andrey Antukh
25dd53290c 🐛 Fix component thumbnail refresh on change
Happens when a component is nested in an other top level frame
2025-04-11 10:40:56 +02:00
Andrey Antukh
a7c1f7ba69 🐛 Fix incorrect undo handling on path edition 2025-04-11 08:54:02 +02:00
Elena Torró
de8e27feb8 Merge pull request #6242 from penpot/ladybenko-10666-builtin-fonts
🎉 Load built-in font and its variants (wasm)
2025-04-11 08:48:31 +02:00
luisδμ
e7144142e5 Add, edit and delete variant properties from layer panel (#6257) 2025-04-10 21:15:23 +02:00
Xavier Julian
b6f2a434cf Display inactive set warning 2025-04-10 15:02:30 +02:00
Alonso Torres
caf558f8dd 🐛 Fix import error messages (#6265) 2025-04-10 14:46:50 +02:00
Florian Schrödl
6f2f1b7a76 ⬆️ Update style dictionary to 4.3.3 (#6260)
Co-authored-by: Andrey Fedorov <oran9e.red@gmail.com>
2025-04-10 14:42:24 +02:00
Elena Torró
744ef1958b Merge pull request #6269 from penpot/elenatorro-fix-render-wasm-tests
🔧 Return the test output
2025-04-10 14:19:02 +02:00
Elena Torro
08b44e1857 🔧 Return the test output 2025-04-10 14:10:05 +02:00
Eva Marco
580b60550c 🐛 Fix notification vertical alignment (#6272) 2025-04-10 13:53:20 +02:00
Florian Schroedl
e9755d437e 🐛 Fix sets and set groups with same name cannot be renamed 2025-04-10 13:27:49 +02:00
Elena Torró
20f695e8d7 Merge pull request #6271 from penpot/ladybenko-fix-test-run
🔧 Update test script to use the right architecture
2025-04-10 13:04:22 +02:00
Belén Albeza
1d7ff1f9e4 🔧 Fix requiring an emscripten macro in non-wasm architectures 2025-04-10 12:52:56 +02:00
Belén Albeza
5b18f1d76d 🔧 Update test script to use the right architecture 2025-04-10 12:50:22 +02:00
Aitor Moreno
d880307a9b 🎉 Add performance measuring functions (#6229) 2025-04-10 11:33:22 +02:00
Eva Marco
e5db66351e 🐛 Fix scroll on token themes modal (#6251)
* 🐛 Fix scroll on token themes modal

* 🐛 Fix collapse set group error
2025-04-10 10:25:08 +02:00
ºelhombretecla
89153eef23 🎉 Increase height presets dropdown (#6185)
* 🎉 Add new measures dropdown height

* 🎉 Add enhancement to CHANGES.md
2025-04-10 10:01:52 +02:00
Alejandro
97c24c8b9c 🐛 Fix merge path nodes with only one node selected (#6248) 2025-04-10 09:08:44 +02:00
Alejandro Alonso
43535ae573 Merge remote-tracking branch 'origin/staging' into develop 2025-04-10 08:40:29 +02:00
Alejandro
b7a8677036 Merge pull request #6262 from penpot/niwinz-staging-clean-data
🐛 Clean workspace state on exit or url change
2025-04-10 08:38:55 +02:00
Alejandro
61643f676c Merge pull request #6249 from penpot/elenatorro-10750-fix-path-nil-svg-attrs
🔧 Do not try to set svg path attrs if none
2025-04-10 06:51:50 +02:00
Alejandro
9b8c8c4971 Merge pull request #6258 from penpot/elenatorro-10756-delete-last-shape
🐛 Remove children correctly
2025-04-10 06:49:41 +02:00
Alejandro
033ca0d56b 🐛 Fix error when an external user tries to export a shape on viewer (#6252) 2025-04-09 16:48:49 +02:00
Alonso Torres
28a6797595 🐛 Fix problem with error detail in toast (#6259) 2025-04-09 16:36:11 +02:00
Andrey Antukh
9ff2160c77 🐛 Clean workspace state on exit or url change 2025-04-09 16:31:49 +02:00
Elena Torro
953db56a0d 🐛 Remove children correctly 2025-04-09 14:39:21 +02:00
Denys Kisil
68ce13368e 🌐 Add translations for: Ukrainian (ukr_UA)
Currently translated at 100.0% (1730 of 1730 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/ukr_UA/
2025-04-09 14:01:41 +02:00
Alejandro Alonso
82cf474863 Merge remote-tracking branch 'origin/staging' into develop 2025-04-09 13:52:54 +02:00
Alejandro
4c77b32171 Merge pull request #6256 from penpot/niwinz-staging-fix-backend-tests
📎 Fix backend tests
2025-04-09 13:52:30 +02:00
Andrey Antukh
34141ce9af 📎 Fix backend tests
Caused by update of image procesing libraries on the devenv docker
image update from debian to ubuntu
2025-04-09 13:37:52 +02:00
Andrey Antukh
edfcac3d5c 🐛 Restore uid assignation on devenv entrypoint 2025-04-09 13:11:12 +02:00
Alejandro Alonso
774e11c827 Merge remote-tracking branch 'origin/staging' into develop 2025-04-09 12:53:18 +02:00
Alejandro
58c867885c Merge pull request #6250 from penpot/alotor-bug-colorpicker
🐛 Fix colorpicker scroll when dropdown displayed
2025-04-09 12:51:17 +02:00
alonso.torres
ccb6e25914 🐛 Fix colorpicker scroll when dropdown displayed 2025-04-09 12:50:55 +02:00
Alejandro
965d2d4036 🐛 Fix webhooks not shown in list (#6254) 2025-04-09 12:46:00 +02:00
Yamila Moreno
9f8d7c9e41 🐳 Improve https documentation 2025-04-09 12:24:43 +02:00
Andrey Antukh
8d352c1f82 Merge branch 'main' into staging 2025-04-09 10:59:37 +02:00
Andrey Antukh
faead09174 Merge tag '2.6.0' 2025-04-09 10:58:39 +02:00
Elena Torro
43f77376b6 🔧 Do not try to set svg path attrs if none 2025-04-09 10:13:39 +02:00
Yamila Moreno
ae3ce1220b 🐳 Improve https documentation 2025-04-09 10:05:18 +02:00
Andrey Antukh
6e3673136a 📎 Update changelog 2025-04-09 09:19:05 +02:00
Belén Albeza
c0ba92f503 🎉 Add support for default font variants (wasm) 2025-04-08 16:45:27 +02:00
Belén Albeza
90cb0357c6 🎉 Swap default font for source sans (wasm) 2025-04-08 14:48:28 +02:00
Alejandro
d55e55ebcc Merge pull request #6237 from penpot/niwinz-upgrade-devenv
⬆️ Upgrade devenv (ubuntu, jvm, node)
2025-04-08 10:50:50 +02:00
Aitor Moreno
c2522329fd Merge pull request #6235 from penpot/alotor-perf-grid-layout-modifiers-2
 Grid layout modifiers
2025-04-08 09:47:42 +02:00
Alejandro
2470c1788e 🐛 Fix render wasm build (#6239) 2025-04-08 09:06:32 +02:00
Pablo Alba
230d259551 Merge pull request #6238 from penpot/luis-improve-input-with-values-doc
📚 Update documentation for input-with-values component
2025-04-07 23:31:40 +02:00
Denys Kisil
a55db1d52b 🌐 Add translations for: Ukrainian (ukr_UA)
Currently translated at 100.0% (1730 of 1730 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/ukr_UA/
2025-04-07 16:01:42 +00:00
Luis de Dios
cb533335c4 📚 Update documentation for input-with-values component 2025-04-07 17:18:21 +02:00
Andrés Moya
a8890e4b13 Merge branch 'tokens-studio-florian-70-sets-in-theme-create' into develop 2025-04-07 17:08:33 +02:00
Florian Schroedl
0281e0dba4 🚧 Explicit state handling 2025-04-07 16:42:43 +02:00
Florian Schroedl
1c209f49fc 🚧 Don't expose state 2025-04-07 16:36:02 +02:00
Yamila Moreno
28caa1d47d 🐛 Fix docker-compose.yaml (#6236) 2025-04-07 16:29:47 +02:00
Andrey Antukh
a4701866a4 ⬆️ Upgrade devenv (ubuntu, jvm, node) 2025-04-07 16:26:04 +02:00
Florian Schroedl
12f72c8ca9 🚧 Show back button only when coming from a modal view 2025-04-07 16:04:18 +02:00
Florian Schroedl
c1165bd12d 🚧 Convert rumext 2025-04-07 16:04:18 +02:00
Florian Schroedl
215fb53c52 🚧 Use use-fn 2025-04-07 16:04:18 +02:00
Florian Schroedl
8df780b237 Allow editing of sets in create theme dialog
♻️ theme-state -> current-theme
2025-04-07 16:04:18 +02:00
Andrés Moya
79679cbb16 Merge branch 'tokens-studio-andrei/91-single-set-import-refactoring' into develop 2025-04-07 15:56:22 +02:00
Andrey Fedorov
fb2db4b918 ♻️ Refactor single set import functionality 2025-04-07 15:48:27 +02:00
Andrey Antukh
05b66f1dcf Merge remote-tracking branch 'origin/develop' into develop 2025-04-07 14:45:29 +02:00
Andrey Antukh
0f1b2003be Merge branch 'staging' into develop 2025-04-07 14:45:08 +02:00
Andrey Antukh
ea6f0abf7c 🐛 Fix regresion on features calculate method on workspace load 2025-04-07 14:32:48 +02:00
Belén Albeza
6f91da9461 🔧 Fix Rust tests (#6208)
* 🔧 Fix test script (rust wasm)

* 🔧 Make code compile in test mode + using aarch64 as a target for tests
2025-04-07 14:08:41 +02:00
Andrey Antukh
45cdfff128 🐛 Fix backend notifications on dashboard 2025-04-07 14:00:26 +02:00
Marina López
8c38e41261 🎉 Consolidate first state of a project (#6150) 2025-04-07 13:15:32 +02:00
alonso.torres
63666fca48 Grid layout modifiers 2025-04-07 11:51:28 +02:00
Andrey Antukh
d279b6c232 📎 Fix linter issues 2025-04-07 11:40:19 +02:00
Andrey Antukh
17f7f920c4 Merge branch 'staging' into develop 2025-04-07 11:32:41 +02:00
Alejandro
3197dfddd9 Merge pull request #6234 from penpot/niwinz-staging-bugfixes-3
🐛 Several bugfixes and backports
2025-04-07 11:15:32 +02:00
Andrey Antukh
b55c86544b 📎 Fix linter issues 2025-04-07 10:52:07 +02:00
Pablo Alba
af1d5b86e1 Merge pull request #6214 from penpot/palba-cleanup-components-v2
♻️ Cleanup of componentsv2
 Add check to avoid open files with components v1
2025-04-07 10:18:53 +02:00
Andrey Antukh
d900516302 Merge branch 'main' into staging 2025-04-07 09:59:27 +02:00
Andrey Antukh
fa68a25bea Merge branch 'warrenjokinen-patch-1' 2025-04-07 09:59:08 +02:00
warrenjokinen
2cc2d34719 📚 Update shortcuts.njk (docs)
minor typo
2025-04-07 09:57:05 +02:00
Andrey Antukh
4640d043e3 ⬆️ Update yarn 2025-04-07 09:21:56 +02:00
Alonso Torres
137e8d042f 🐛 Fix problem with boolean edges (#6218) 2025-04-07 09:19:43 +02:00
Andrey Antukh
bc957893f4 Make feature resolved on team load
That simplifies features retrieval to simple get
2025-04-07 07:50:40 +02:00
Andrey Antukh
b8107ee497 Ensure workspace page loading and intialization process 2025-04-07 07:42:09 +02:00
Andrey Antukh
6b3a988526 Send version and build data to worker configuration 2025-04-07 07:10:40 +02:00
Andrey Antukh
5cb39874a2 Add better error hints on auth ns 2025-04-07 07:10:40 +02:00
Rick Benetti
ee96c5599c 🌐 Add translations for: Portuguese (Brazil)
Currently translated at 74.0% (1281 of 1730 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/pt_BR/
2025-04-05 14:07:11 +00:00
Elena Torro
4ceaedcbe8 🎉 Render text while typing 2025-04-04 14:02:02 +02:00
Pablo Alba
f375cc9a82 Add check to avoid open files with components v1 2025-04-04 11:08:30 +02:00
Marina López
9fc671cc17 🐛 Fix wrong path to list all icons in storybook 2025-04-04 10:36:51 +02:00
Elena Torró
5937ed57ce 🎉 Update font and variant on change (#6220) 2025-04-04 10:17:39 +02:00
Aitor Moreno
2e3ed0c23f Merge pull request #6230 from penpot/azazeln28-fix-mem-bytes-alloc-32
🐛 Fix bytes-alloc-32
2025-04-04 09:55:34 +02:00
Aitor Moreno
5d1d2ef289 🐛 Fix bytes-alloc-32 2025-04-04 09:43:48 +02:00
Elena Torró
480c224250 🐛 Fix long file names (#6216)
* 🔧 Add truncate str macro

* 🐛 Use truncate instead of prune to prevent title override

* 💄 Use text-overflow ellipsis on file names

* 📎 Add #10662 to 2.7 bugfixes
2025-04-03 16:06:02 +02:00
Aitor Moreno
cd731c3ad2 ♻️ Refactor heap usage (#6204) 2025-04-03 16:04:51 +02:00
Pablo Alba
3fb3b45fdc Merge pull request #6219 from penpot/niwinz-staging-bugfixes-2
🐛 Several bugfixes and enhancements
2025-04-03 15:49:09 +02:00
Andrey Antukh
9bc49e3381 Merge pull request #6209 from penpot/niwinz-features-enhancement
 Make feature resolved on team load
2025-04-03 15:43:12 +02:00
Andrey Antukh
0816adbaec Send ws messages in verbose format when on development build 2025-04-03 11:40:40 +02:00
Andrey Antukh
1d69941882 🐛 Fix backend notification dialogs 2025-04-03 11:40:40 +02:00
Pablo Alba
f961b75bba ♻️ Cleanup of componentsv2 2025-04-03 11:38:35 +02:00
Andrey Antukh
8f600f334f 🐛 Make accept and cancel handlers optional on actionable* 2025-04-03 11:21:02 +02:00
Andrey Antukh
cf55d12991 📚 Add better docstring for srepl.main/notify! helper 2025-04-03 11:21:02 +02:00
Andrey Antukh
78919df886 🐛 Fix incorrect topic sending on internal srepl notify helper 2025-04-03 10:58:10 +02:00
Marina López
1e16fb8ca2 🐛 Fix horizontal scroll from design tab (#6213) 2025-04-02 20:00:22 +02:00
Elena Torró
c332528185 🐛 Fix render object with pending status (#6215) 2025-04-02 19:58:03 +02:00
Pablo Alba
387c5e67f3 🐛 Fix flick on create variant (#6217) 2025-04-02 19:54:48 +02:00
Elena Torró
2ed780e14d Merge pull request #6205 from penpot/elenatorro-10528-fix-google-font-variant-styles
🐛 Fix Google Fonts load by parsing italic variant ids correctly
2025-04-02 17:16:51 +02:00
Pablo Alba
1b8714fe7f 🐛 Fix position problems cutting-pasting a component 2025-04-02 12:10:18 +02:00
Andrey Antukh
e28f8cae74 Merge remote-tracking branch 'origin/staging' into develop 2025-04-02 10:34:31 +02:00
Andrés Moya
5d600c6715 Change behavior of single set json file import to be coherent (#6211) 2025-04-02 09:41:12 +02:00
Andrey Antukh
ea031a2161 Merge pull request #6210 from penpot/niwinz-staging-bugfixes
🐛 Several bugfixes
2025-04-02 09:19:57 +02:00
Andrey Antukh
87ef98dad5 Consolidate layout/grid feature 2025-04-01 21:15:38 +02:00
Andrey Antukh
4d4a04e9aa Add minor enhacement for error reporting 2025-04-01 20:43:55 +02:00
Andrey Antukh
e6e71e9278 Add minor enhacement for error reporting 2025-04-01 20:24:07 +02:00
Andrey Antukh
02220d02ed ⬆️ Update svgo 2025-04-01 20:01:21 +02:00
Andrey Antukh
ff7b77bda7 ⬆️ Update yarn 2025-04-01 20:01:21 +02:00
Andrey Antukh
f8ffae75c4 Make feature resolved on team load
That simplifies features retrieval to simple get
2025-04-01 20:01:21 +02:00
Andrey Antukh
3ec797f56e 🐛 Validate and decode params on export-binfile 2025-04-01 19:16:35 +02:00
Andrey Antukh
cb350b26a1 Merge remote-tracking branch 'origin/develop' into develop 2025-04-01 18:27:02 +02:00
Andrey Antukh
dccebb0bea Merge remote-tracking branch 'origin/staging' into develop 2025-04-01 18:26:37 +02:00
Elena Torró
4cefbb52e1 Merge pull request #6206 from penpot/azazeln28-fix-not-enough-surfaces
🐛 Fix not enough surfaces
2025-04-01 15:47:59 +02:00
Elena Torro
d757009b48 🐛 Fix Google Fonts load by parsing italic variant ids correctly 2025-04-01 14:01:54 +02:00
Aitor Moreno
ca202711e1 🐛 Fix not enough surfaces 2025-04-01 13:41:33 +02:00
Eva Marco
74f11859e4 🐛 Fix max lenght on assets inputs (#6201) 2025-04-01 13:28:35 +02:00
Andrey Antukh
47f80cf3db 🐛 Make error middleware capture profile-id 2025-04-01 12:30:51 +02:00
Pablo Alba
f04229d8cb 🎉 Allow duplicate/copy-paste/cut-paste variants 2025-04-01 11:07:22 +02:00
Andrey Antukh
076d64df8f Merge remote-tracking branch 'origin/staging' into develop 2025-04-01 11:02:32 +02:00
Andrey Fedorov
a20dd3f955 Fix single set import 2025-04-01 10:57:17 +02:00
Andrey Antukh
982118c942 🐳 Update devenv corepack setup 2025-04-01 10:47:49 +02:00
Andrey Antukh
a51feb8638 📎 Update changelog 2025-04-01 10:47:13 +02:00
Elena Torró
3d7479f9aa 🐛 Fix stroke image rendering (#6189) 2025-04-01 09:55:19 +02:00
Yamila Moreno
9663964790 🐳 Make traefik example easier (#6198) 2025-04-01 09:34:46 +02:00
Elena Torró
76ffc2d268 🔧 Log error on process animation frame (#6182) 2025-04-01 09:01:49 +02:00
Elena Scilinguo
d0d118b31e 📚 Update README.md
Signed-off-by: Elena Scilinguo <elena.scilinguo@kaleidos.net >
2025-04-01 08:51:23 +02:00
Andrés Moya
2c0e18ce1c 🐛 Fix sync of margin and padding tokens in components 2025-03-31 16:19:45 +02:00
Eva Marco
89876ef96f 🐛 Fix UI with long named colors (#6193) 2025-03-31 15:33:30 +02:00
Elena Torró
895b5b2ee1 🐛 Fix new line parsing (#6180) 2025-03-31 14:59:34 +02:00
Rick Benetti
21702c090d 🌐 Add translations for: Portuguese (Brazil)
Currently translated at 73.9% (1280 of 1730 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/pt_BR/
2025-03-31 11:06:36 +00:00
Elena Torró
9fd0e9af66 Merge pull request #6178 from penpot/ladybenko-10528-google-fonts
🎉 Render text that uses a google font (wasm)
2025-03-31 11:55:57 +02:00
luisδμ
648a8f9237 Allow modifying property name when a variation is selected (#6174)
*  Change property name when a variation is selected

* 📎 PR changes
2025-03-31 09:12:43 +02:00
Edgars Andersons
c4254106e8 🌐 Add translations for: Latvian
Currently translated at 100.0% (1730 of 1730 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/lv/
2025-03-29 13:01:53 +01:00
Xavier Julian
c259b8ed46 🐛 Fix overflow on tokens sidebar 2025-03-28 23:45:01 +01:00
Xavier Julian
b1df0ac194 Add a default 256 maxlength value to all input fields 2025-03-28 23:45:01 +01:00
Aitor Moreno
4e1ae1bc1a Merge pull request #6181 from penpot/superalex-tada-avoid-full-tiles-rebuild-on-set-modifiers
🎉 Avoid full tiles rebuild on set modifiers
2025-03-28 16:27:30 +01:00
Aitor Moreno
b6ac1dea4d 🐛 Fix TileSurfaceCache not deref surfaces 2025-03-28 16:14:37 +01:00
Belén Albeza
219d9af885 ♻️ Simplify font ids 2025-03-28 15:21:42 +01:00
Belén Albeza
c6bba54573 ♻️ Refactor font-related wasm code into a sub-namespace 2025-03-28 15:17:13 +01:00
Belén Albeza
f53cae0faa 🎉 Render text that uses a Google Font 2025-03-28 15:17:12 +01:00
Eva Marco
c1853a71a9 🐛 Fix available resize area (#6186) 2025-03-28 13:15:35 +01:00
Edgars Andersons
981336ed5e 🌐 Add translations for: Latvian
Currently translated at 98.4% (1704 of 1730 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/lv/
2025-03-28 11:01:58 +00:00
Linerly
3864ce6855 🌐 Add translations for: Indonesian
Currently translated at 100.0% (1730 of 1730 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/id/
2025-03-28 11:01:57 +00:00
Alejandro Alonso
6953a57333 🎉 Avoid full tiles rebuild on set modifiers 2025-03-28 11:55:54 +01:00
Alejandro
a109f11926 Merge pull request #6187 from penpot/azazeln28-fix-surface-pool-missing-deallocation
🐛 Fix SurfacePool missing deallocation
2025-03-28 11:55:45 +01:00
Alejandro
45c9904e05 Merge pull request #6155 from penpot/azazeln28-feat-cache-extra-tiles
🎉 Cache extra tiles
2025-03-28 11:55:31 +01:00
Aitor Moreno
08fc32cdc6 🎉 Cache extra tiles 2025-03-28 11:34:18 +01:00
Aitor Moreno
6c10f1e364 🐛 Fix SurfacePool missing deallocation 2025-03-28 11:34:04 +01:00
Alejandro
e8549ffb79 Merge pull request #6177 from penpot/azazeln28-feat-sort-viewport-tiles
🎉 Sort viewport tiles by distance to center
2025-03-28 11:32:08 +01:00
Aitor Moreno
8a8d89dfc0 🎉 Sort viewport tiles by distance to center 2025-03-28 11:22:10 +01:00
Pablo Alba
b6c4376217 🐛 Fix bugs from varaints design review 2025-03-28 11:20:10 +01:00
Eva Marco
cbb3f6672f 🐛 Fix asset name on inspect tab (#6173)
Signed-off-by: Eva Marco <eva.marco@kaleidos.net>
2025-03-28 10:38:35 +01:00
Alejandro
bd5e47f5fc Merge pull request #6126 from penpot/elenatorro-10516-fix-stroke-shadows
🐛 Fix stroke shadows
2025-03-28 09:54:39 +01:00
Alejandro
2aa756af38 Merge pull request #6175 from penpot/niwinz-develop-binfile-path-fix
🐛 Fix binfile-v3 importation related to bool shape normalization
2025-03-28 09:46:16 +01:00
Andrey Antukh
78c2840b22 Merge remote-tracking branch 'origin/staging' into develop 2025-03-28 09:45:34 +01:00
Aitor Moreno
af0a516a79 🐛 Fix path editing with wrong selrect (#6168) 2025-03-28 09:43:46 +01:00
Alejandro
cc97a8ffcc Merge pull request #6158 from penpot/niwinz-staging-task-result
🐛 Fix incorrect task result handling
2025-03-28 09:43:11 +01:00
ºelhombretecla
535e8653a0 🎉 Add slides for version 2.6 (#6176) 2025-03-28 09:42:09 +01:00
Andrey Antukh
210e5b0023 🐛 Fix incorrect task result handling
That caused that many task rows in a table not properly marked
as completed and leaved just as scheduled.
2025-03-28 09:10:46 +01:00
Andrey Antukh
651beb4b9c 🐛 Fix binfile-v3 importation related to bool shape normalization 2025-03-28 08:57:47 +01:00
Elena Torro
f4d04a3dcb 🐛 Fix Stroke Shadows
- Move shadows surface responsibility
- Draw shadows directly into DropShadows and InnerShadows surfaces
- Draw stroke shadows directly into Strokes in order
- Clean up old shadow surfaces (Shadow & Overlay)
2025-03-28 08:56:37 +01:00
Elena Torró
d573da55b0 Merge pull request #6179 from penpot/elenatorro-10530-fix-paragraph
🐛 Revert offset change to fix paragraph rendering
2025-03-27 17:29:50 +01:00
Elena Torro
3c4be537d9 🐛 Revert offset change to fix paragraph rendering 2025-03-27 17:17:36 +01:00
Andrés Moya
6a87d5eea9 🐛 Rewrite active tokens calculation algorithm (#6165) 2025-03-27 15:53:17 +00:00
Elena Torró
9800331505 🎉 Improve performance reducing unnecessary calls to set-objects
🎉 Improve performance reducing unnecessary calls to set-objects
2025-03-27 16:19:36 +01:00
Alejandro Alonso
7728d5b317 🎉 Improve performance reducing unnecessary calls to set-objects 2025-03-27 15:47:03 +01:00
Aitor Moreno
8f47ed8b0a Merge pull request #6136 from penpot/superalex-disable-svg-viewport-texts-for-wasm-render
🐛 Disable svg viewport texts for wasm render
2025-03-27 14:46:38 +01:00
Alejandro
c137e682dc Merge pull request #6172 from penpot/elenatorro-10530-fix-text-drag-and-drop
 Render text properly while dragging and resizing the text Shape
2025-03-27 14:18:11 +01:00
Andrey Antukh
14c639a425 🐛 Fix bool type shape normalize migration 2025-03-27 14:15:13 +01:00
Elena Torró
06bfb1ad26 🎉 Add PathData data type
🎉 Add PathData data type
2025-03-27 13:39:54 +01:00
Elena Torro
33c3611345 Render text properly while dragging and resizing the text Shape 2025-03-27 13:04:45 +01:00
Alejandro Alonso
e012046f62 Merge remote-tracking branch 'origin/staging' into develop 2025-03-27 12:12:57 +01:00
Alejandro Alonso
237d9d067d Merge remote-tracking branch 'origin/main' into staging 2025-03-27 12:12:37 +01:00
Alejandro
6519db82d1 Merge pull request #6171 from penpot/mavalroot-install-plugin-bug
🐛 Fix plugin installation error by penpot hub
2025-03-27 12:12:19 +01:00
María Valderrama
0a60cbedb5 🐛 Fix plugin installation error by penpot hub 2025-03-27 11:57:23 +01:00
Andrey Antukh
ebf3730454 Normalize the content prop from bool type (#6162)
Make it the same as path shape, because they are essentially the
same data type
2025-03-27 11:15:48 +01:00
Edgars Andersons
ec0183ce94 🌐 Add translations for: Latvian
Currently translated at 97.6% (1690 of 1730 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/lv/
2025-03-27 11:01:53 +01:00
Aitor Moreno
3cf823ffb3 Merge pull request #6137 from penpot/superalex-rendering-wasm-performance
🎉 Avoid rendering too small shapes
2025-03-27 10:22:02 +01:00
Aitor Moreno
6231a9f931 Merge pull request #6130 from penpot/azazeln28-fix-tile-cache-exhaustion
🐛 Fix tile cache exhaustion
2025-03-27 09:51:16 +01:00
Elena Torró
dd30e939ae 📎 Add #9489 bug fix to CHANGELOG
📎 Add #9489 bug fix to CHANGELOG
2025-03-26 14:14:34 +01:00
Elena Torro
6f2e1d3794 📎 Add #9489 bug fix to CHANGELOG 2025-03-26 13:55:42 +01:00
Eva Marco
d7c709607d 🐛 Fix line height on token pills (#6164) 2025-03-26 13:46:55 +01:00
Elena Torró
2e41bd7607 🐛 Fix linecap SVG path property (#6163) 2025-03-26 13:46:35 +01:00
Andrey Antukh
bb7301fb63 Improve libraries loading on workspace (#6141)
*  Improve libraries loading on workspace

*  Add improvements to CSS

---------

Co-authored-by: Eva Marco <evamarcod@gmail.com>
2025-03-26 13:19:48 +01:00
Andrey Antukh
b9907ec401 🎉 Add PathData data type
That replaces the ad-hoc helpers for convert path content from
plain with encapsulated type that implements the appropriate
clojure protocols and interfaces that helps interacting with
binary encoded path data
2025-03-26 13:17:25 +01:00
Andrey Antukh
416e9e8e1d Merge remote-tracking branch 'origin/staging' into develop 2025-03-26 13:15:58 +01:00
Eva Marco
2918c57fb8 🐛 Show broken pills when all sets are disabled (#6161) 2025-03-26 13:13:45 +01:00
Eva Marco
f55e0bf6e3 🐛 Eva Fix context menu for viewer role (#6159) 2025-03-26 12:50:23 +01:00
Alonso Torres
83d41dba6f Serialization of grid layout data (#6148)
*  Add serializators for grid layout properties

*  Extract serializers for wasm api module
2025-03-26 12:10:31 +01:00
Pablo Alba
7284fb539f 🐛 Fix when editing a property name, the wrong property changes name (#6156) 2025-03-26 11:17:48 +01:00
andrés gonzález
3d16fa6f19 📚 Add Design Tokens documentation (#6026)
* 📚 Add Design Tokens documentation

* 📚 Update docs/user-guide/design-tokens/index.njk

Co-authored-by: Madalena Melo <madalena.melo@kaleidos.net>

* 📚 Update docs/user-guide/design-tokens/index.njk

Co-authored-by: Madalena Melo <madalena.melo@kaleidos.net>

* 📚 Update docs/user-guide/design-tokens/index.njk

Co-authored-by: Madalena Melo <madalena.melo@kaleidos.net>

* 📚 Update docs/user-guide/design-tokens/index.njk

Co-authored-by: Madalena Melo <madalena.melo@kaleidos.net>

* 📚 Update docs/user-guide/design-tokens/index.njk

Co-authored-by: Madalena Melo <madalena.melo@kaleidos.net>

* 📚 Changing several things after the PR review

---------

Co-authored-by: Madalena Melo <madalena.melo@kaleidos.net>
2025-03-26 10:51:17 +01:00
Yamila Moreno
c65c4270c3 Merge pull request #6128 from orhtej2/patch-1
📚 Add YunoHost as a self-hosting option
2025-03-26 10:17:51 +01:00
Andrey Antukh
0099c282b6 🐛 Fix tokens set reordering corner case 2025-03-26 09:06:54 +01:00
luisδμ
f932f3efb1 Filter variant by name on layers panel 2025-03-25 21:50:29 +01:00
Andrés Moya
9115e1a3a3 🐛 Fix resolved value when opening the token edit form 2025-03-25 17:12:04 +01:00
Aitor Moreno
60bc88a075 🐛 Fix tile cache exhaustion 2025-03-25 16:35:49 +01:00
ºelhombretecla
a7044c73ba 🐛 Fix libraries carrousel styles (#6140) 2025-03-25 15:51:34 +01:00
luisδμ
dc84ab3e41 🐛 Fix calculate zoom to avoid bubbles to get outside viewbox (#6138)
* 🐛 Fix calculate zoom to avoid bubbles to get outside vbox

* 📎 PR changes
2025-03-25 15:39:47 +01:00
Aitor Moreno
6eb686c06b ♻️ Refactor Custom Fonts allocations (#6146)
* ♻️ Refactor Custom Fonts allocations

* 💄 Remove commented code

---------

Co-authored-by: Belén Albeza <belen@hey.com>
2025-03-25 15:34:11 +01:00
Edgars Andersons
f587ed4ade 🌐 Add translations for: Latvian
Currently translated at 97.1% (1680 of 1730 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/lv/
2025-03-25 11:01:54 +00:00
Eva Marco
e81adb241b 🐛 Add underscore as posible name character (#6135) 2025-03-25 10:57:23 +01:00
Alejandro
065b50f5a2 🐛 Fix asynchronous content dependant rendering (#6142)
* 🐛 Fix custom fonts rendering

* 🐛 Fix asynchronous content dependant rendering

* 🎉 Renaming clear_cache to clear_drawing_cache
2025-03-25 09:49:47 +01:00
Marina López
a6133e9c48 🐛 Fix actions when workspace is visited first time (#6129)
* 🐛 Fix actions when workspace is visited first time

* 📎 Fix linter errors

* 🐛 Fix problem with integration test

* 📎 Fix linter errors

* 📎 Fix linter errors

---------

Co-authored-by: alonso.torres <alonso.torres@kaleidos.net>
2025-03-24 18:02:05 +01:00
Alejandro Alonso
85b24e1e8d 🎉 Disable antialias for small shapes 2025-03-24 16:27:43 +01:00
Eva Marco
7bc000517f 🐛 Fix modal position when colopicker is open (#6139) 2025-03-24 16:10:16 +01:00
Xavier Julian
95d9403790 Resize tokens panel on resize 2025-03-24 13:59:51 +01:00
Pablo Alba
9653e72e47 ♻️ Refactor variants
* ♻️ Refactor variants

*  Add MR changes
2025-03-24 13:15:02 +01:00
Alejandro Alonso
a80f114d66 🎉 Avoid rendering too small shapes 2025-03-24 11:49:38 +01:00
Alejandro Alonso
74ae4743d8 🐛 Disable svg viewport texts for wasm render 2025-03-24 11:06:14 +01:00
Andrey Antukh
d1d30e7eb5 Revert "📎 Add workaround for wasm production build failure"
This reverts commit f8a2291a55.
2025-03-24 10:48:22 +01:00
Andrey Antukh
e83be01475 Merge remote-tracking branch 'origin/staging' into develop 2025-03-24 10:42:14 +01:00
Alejandro
5d66eedcc7 Merge pull request #6134 from penpot/azazeln28-fix-render-wasm-build-env
🐛 Fix _build_env release EMCC_CFLAGS
2025-03-24 10:28:28 +01:00
Aitor Moreno
974d43cb08 🐛 Fix _build_env release EMCC_CFLAGS 2025-03-24 10:17:16 +01:00
Aitor Moreno
22efd6574d Merge pull request #6125 from penpot/alotor-perf-flex-layout-2
 Improvements on flex layout positioning
2025-03-24 09:53:30 +01:00
Nicola Bortoletto
bb5a103944 🌐 Add translations for: Italian
Currently translated at 99.8% (1728 of 1730 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/it/
2025-03-23 19:01:53 +00:00
Rick Benetti
34b3520fb2 🌐 Add translations for: Portuguese (Brazil)
Currently translated at 70.9% (1228 of 1730 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/pt_BR/
2025-03-23 19:01:52 +00:00
Stephan Paternotte
3217ba5a77 🌐 Add translations for: Dutch
Currently translated at 100.0% (1730 of 1730 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/nl/
2025-03-22 18:01:53 +01:00
Nicola Bortoletto
a91caded9e 🌐 Add translations for: Italian
Currently translated at 96.4% (1669 of 1730 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/it/
2025-03-22 18:01:52 +01:00
Stephan Paternotte
05ba1c3e64 🌐 Add translations for: Dutch
Currently translated at 99.0% (1714 of 1730 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/nl/
2025-03-21 15:02:01 +00:00
Edgars Andersons
77f025eb8d 🌐 Add translations for: Latvian
Currently translated at 96.0% (1662 of 1730 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/lv/
2025-03-21 15:02:00 +00:00
Yaron Shahrabani
aacec1809b 🌐 Add translations for: Hebrew
Currently translated at 100.0% (1730 of 1730 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/he/
2025-03-21 15:01:59 +00:00
Linerly
0435f560a4 🌐 Add translations for: Indonesian
Currently translated at 95.4% (1652 of 1730 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/id/
2025-03-21 15:01:58 +00:00
Stas Haas
766f034e5e 🌐 Add translations for: German
Currently translated at 94.1% (1628 of 1730 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/de/
2025-03-21 15:01:56 +00:00
Ally Tiago
8502d9d21b 🌐 Add translations for: Portuguese (Brazil)
Currently translated at 70.4% (1218 of 1730 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/pt_BR/
2025-03-21 15:01:55 +00:00
Rick Benetti
6c874b2bb7 🌐 Add translations for: Portuguese (Brazil)
Currently translated at 70.4% (1218 of 1730 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/pt_BR/
2025-03-21 15:01:55 +00:00
Andrey Antukh
f8a2291a55 📎 Add workaround for wasm production build failure 2025-03-21 14:07:02 +01:00
Andrey Antukh
8c302e314f Merge remote-tracking branch 'origin/staging' into develop 2025-03-21 11:17:26 +01:00
Eva Marco
752f74767e 🐛 Fix error copy (#6132) 2025-03-21 10:47:32 +01:00
Andrey Antukh
e5319e04c7 ♻️ Fix naming on token-set group move change operation 2025-03-21 10:23:27 +01:00
Andrey Antukh
e8e9037ef1 🐛 Fix inconsistencies on parsing tokens dtcg json 2025-03-21 10:23:27 +01:00
Andrey Antukh
c6bfae0d63 🐛 Normalize set names on importing themes dtcg json 2025-03-21 10:23:27 +01:00
alonso.torres
a830c27ceb Improvements on flex layout positioning 2025-03-21 10:18:34 +01:00
Andrey Antukh
93bf198073 🐛 Prevent theme replacement on ranaming 2025-03-21 09:22:16 +01:00
Alejandro
4c12af957c Merge pull request #6121 from penpot/superalex-tada-improve-tile-shapes-iteration-2
🎉 Improve tile shapes iteration
2025-03-21 07:30:52 +01:00
Alejandro Alonso
9ea3c54b92 🎉 Improve tile shapes iteration 2025-03-21 07:20:45 +01:00
orhtej2
4be8d77a79 📚 Update unofficial-options.md
Signed-off-by: Mateusz Szymański <2871798+orhtej2@users.noreply.github.com>
2025-03-20 23:59:30 +01:00
Aitor Moreno
4620764111 Merge pull request #6127 from penpot/superalex-fix-wasm-state-warning
🐛 Fix wasm state warning
2025-03-20 18:47:49 +01:00
Alejandro Alonso
ca86137d0f 🐛 Fix wasm state warning 2025-03-20 18:18:50 +01:00
Alejandro Alonso
b299a732c0 Merge remote-tracking branch 'origin/staging' into develop 2025-03-20 18:08:06 +01:00
Alejandro
9fb7456b38 Merge pull request #6111 from penpot/superalex-fix-pen-shortcut-multiple-times
🐛 Fix opening pen with shortcut multiple times breaks toolbar
2025-03-20 18:05:35 +01:00
Eva Marco
b3a3cca9fe 🐛 Fix stroke width validation (#6124) 2025-03-20 17:35:19 +01:00
andrés gonzález
f98009ec54 📚 Add Design Tokens to the Changelog (#6112) 2025-03-20 16:39:14 +01:00
Alejandro
7a4c9d9933 Merge pull request #6122 from penpot/elenatorro-10516-fix-inner-shadow-rendering
🐛 Fix Fill Inner Shadow rendering
2025-03-20 15:46:15 +01:00
Elena Torro
91d15ea221 🐛 Fix Fill Inner Shadows 2025-03-20 15:20:15 +01:00
Andrey Antukh
b043fec0d5 🌐 Validate and rehash translation files 2025-03-20 14:46:46 +01:00
Andrey Antukh
0bab46eb5c Merge remote-tracking branch 'weblate/develop' into develop 2025-03-20 14:45:42 +01:00
Andrey Antukh
82bff09373 🐛 Fix incorrect syntax on spanish translation file 2025-03-20 14:45:20 +01:00
Andrey Antukh
329b2d30d0 Revert "🌐 Sync, validate and rehash translations"
This reverts commit 37a8bf7bfc.
2025-03-20 14:44:57 +01:00
Anonymous
0d65b652d4 🌐 Add translations for: Swedish
Currently translated at 93.1% (1612 of 1730 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/sv/
2025-03-20 14:42:44 +01:00
Anonymous
9d3c19e86a 🌐 Add translations for: Yoruba
Currently translated at 69.1% (1196 of 1730 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/yo/
2025-03-20 14:42:43 +01:00
Anonymous
56a7800519 🌐 Add translations for: Hausa
Currently translated at 72.9% (1262 of 1730 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/ha/
2025-03-20 14:42:43 +01:00
Anonymous
ba0cebd713 🌐 Add translations for: Dutch
Currently translated at 94.0% (1627 of 1730 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/nl/
2025-03-20 14:42:43 +01:00
Anonymous
e28628d148 🌐 Add translations for: Latvian
Currently translated at 94.0% (1627 of 1730 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/lv/
2025-03-20 14:42:42 +01:00
Anonymous
40bc860dc6 🌐 Add translations for: Ukrainian (ukr_UA)
Currently translated at 93.9% (1626 of 1730 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/ukr_UA/
2025-03-20 14:42:42 +01:00
Anonymous
decf32fdd5 🌐 Add translations for: Croatian
Currently translated at 93.8% (1623 of 1730 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/hr/
2025-03-20 14:42:42 +01:00
Anonymous
d9d6ee9922 🌐 Add translations for: Portuguese (Portugal)
Currently translated at 88.9% (1539 of 1730 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/pt_PT/
2025-03-20 14:42:42 +01:00
Anonymous
903609a38f 🌐 Add translations for: Czech
Currently translated at 93.6% (1621 of 1730 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/cs/
2025-03-20 14:42:41 +01:00
Anonymous
4504903b4c 🌐 Add translations for: Italian
Currently translated at 93.9% (1626 of 1730 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/it/
2025-03-20 14:42:40 +01:00
Anonymous
4bf4972b6e 🌐 Add translations for: Chinese (Traditional Han script)
Currently translated at 93.9% (1626 of 1730 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/zh_Hant/
2025-03-20 14:42:40 +01:00
Anonymous
47e4b41dd2 🌐 Add translations for: Hebrew
Currently translated at 94.0% (1627 of 1730 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/he/
2025-03-20 14:42:39 +01:00
Anonymous
af413ff1c0 🌐 Add translations for: Indonesian
Currently translated at 94.0% (1627 of 1730 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/id/
2025-03-20 14:42:39 +01:00
Anonymous
5fcf0808c6 🌐 Add translations for: German
Currently translated at 94.0% (1627 of 1730 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/de/
2025-03-20 14:42:39 +01:00
Anonymous
fb956b3aa1 🌐 Add translations for: Chinese (Simplified Han script)
Currently translated at 79.3% (1373 of 1730 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/zh_Hans/
2025-03-20 14:42:38 +01:00
Anonymous
93986af181 🌐 Add translations for: Russian
Currently translated at 83.5% (1446 of 1730 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/ru/
2025-03-20 14:42:38 +01:00
Andrey Antukh
37a8bf7bfc 🌐 Sync, validate and rehash translations 2025-03-20 14:41:50 +01:00
Elena Torro
e60e36a0e2 🔧 Refactor RenderState scale calculation 2025-03-20 14:36:45 +01:00
Hosted Weblate
199e182399 🌐 Update translation files
Updated by "Cleanup translation files" hook in Weblate.

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/
2025-03-20 14:31:52 +01:00
Andrey Antukh
a9f4b29f32 Merge remote-tracking branch 'weblate/develop' into develop 2025-03-20 14:31:09 +01:00
Andrey Antukh
22cd43b8a2 Merge remote-tracking branch 'origin/staging' into develop 2025-03-20 14:27:37 +01:00
Andrey Antukh
669533cae6 Merge pull request #6115 from penpot/niwinz-staging-tokens-1
🐛 Fix incorrect absolute frame positioning with measures sidebar
2025-03-20 13:20:08 +01:00
Andrey Antukh
d6efd469e4 🎉 Make the design tokens feature enabled by default 2025-03-20 12:22:37 +01:00
Andrey Antukh
0d4a6fc75f 🐛 Clear selected token set on leave file on workspace 2025-03-20 12:22:37 +01:00
Andrey Antukh
e403194bba 💄 Remove incorrect use of rx/concat on update-shape-position 2025-03-20 12:22:37 +01:00
Andrey Antukh
b8c5a10551 💄 Add minor cosmetic changes to measures menu 2025-03-20 12:22:37 +01:00
Andrey Antukh
7fdb0873db 🐛 Fix incorrect absolute frame positioning with measures sidebar 2025-03-20 12:22:37 +01:00
Alejandro
2d61644b05 Merge pull request #5914 from penpot/azazeln28-feat-tile-rendering
🎉 Tile rendering
2025-03-20 11:25:58 +01:00
Aitor Moreno
084816fb9f 🎉 Tile rendering system 2025-03-20 11:14:14 +01:00
Xavier Julian
68a89556d6 🐛 Add tooltip to empty sets button on theme creation modal 2025-03-20 10:18:28 +01:00
william chen
b5ea90f740 🌐 Add translations for: Chinese (Traditional Han script)
Currently translated at 100.0% (1646 of 1646 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/zh_Hant/
2025-03-20 10:02:52 +01:00
Alejandro Alonso
1a77c1fe36 🐛 Fix opening pen with shortcut multiple times breaks toolbar 2025-03-20 09:19:27 +01:00
Aitor Moreno
4aa1bb7246 Merge pull request #6116 from penpot/alotor-fix-group-constraints
🐛 Fix problem with constraints when creating group
2025-03-19 16:43:54 +01:00
alonso.torres
3a80120bf6 🐛 Fix problem with constraints when creating group 2025-03-19 16:33:50 +01:00
Aitor Moreno
d01eccf912 Merge pull request #6114 from penpot/alotor-fix-plugins-shapows
🐛 Fix problem with default shadows in plugins
2025-03-19 16:15:41 +01:00
alonso.torres
25621f8deb 🐛 Fix problem with default shadows in plugins 2025-03-19 14:51:39 +01:00
Yamila Moreno
dc006bd7f2 Merge pull request #6108 from penpot/yms-improve-self-host-documentation
📚 Improve self host documentation
2025-03-19 14:05:22 +01:00
Eva Marco
629f09089b 🐛 Fix tooltip with only one set and no active (#6107) 2025-03-19 13:54:00 +01:00
Andrey Antukh
e6839e4983 Merge pull request #6106 from penpot/palba--variants-inspect-header
 Add subtitle to inspect tab for components
2025-03-19 13:42:57 +01:00
Andrey Antukh
344ec94a3f Merge pull request #6109 from penpot/superalex-fix-hovering-dashboard-templates
🐛 FIx hovering dashboard templates
2025-03-19 13:42:04 +01:00
Andrey Antukh
62e89258e4 Merge pull request #6101 from penpot/niwinz-develop-token-fixes-4
 Add several improvements to tokens (part 4)
2025-03-19 13:38:46 +01:00
Andrey Antukh
b6bb93f0b6 Improve code convetion related to changes protocol
Partial work, still pending to make changes to other related
changes definitions
2025-03-19 12:52:03 +01:00
Andrey Antukh
39a1d5cc89 🐛 Fix set unexpected deletion on reordering 2025-03-19 12:42:05 +01:00
Andrey Antukh
8fa24de3d4 Merge pull request #6096 from penpot/niwinz-develop-token-fixes-3
 Add several improvements and fixes to tokens (part 3)
2025-03-19 12:30:05 +01:00
Alejandro Alonso
1def5015fb 🐛 FIx hovering dashboard templates 2025-03-19 12:27:13 +01:00
Yamila Moreno
1dbc924d31 📚 Remove docker installation in favour of the official documentation 2025-03-19 12:19:07 +01:00
Yamila Moreno
95da007107 📚 Add a warning about technical knowledge 2025-03-19 12:18:04 +01:00
Pablo Alba
82d3e466be Add subtitle to inspect tab for components 2025-03-19 10:34:19 +01:00
Alejandro
b0dacf6b11 Merge pull request #6105 from penpot/superalex-add-changelog-for-2.7.0
📎 Update changelog (add entry for 2.7.0)
2025-03-19 10:02:49 +01:00
Alejandro Alonso
64d090839d 📎 Update changelog (add entry for 2.7.0) 2025-03-19 09:51:22 +01:00
Alejandro Alonso
633a7eac4e Merge remote-tracking branch 'origin/staging' into develop 2025-03-19 09:47:32 +01:00
Alejandro
357fba5d2b 🐛 Fix selected team not saved (#6104) 2025-03-19 09:46:08 +01:00
Alejandro
b727f2fe1f Merge pull request #6077 from penpot/elenatorro-10516-fix-shadow-rendering
🐛 Fix drop shadows viewport clipping
2025-03-19 08:48:03 +01:00
Andrey Antukh
4453eec687 Persist migrated files on srepl process-file helper 2025-03-18 17:57:52 +01:00
Andrey Antukh
c169eef161 ♻️ Remove tokens lib migrations from file migrations 2025-03-18 17:57:52 +01:00
Eva Marco
17af55d3c8 🐛 Fix lost resolved value on tooltip (#6102) 2025-03-18 17:13:45 +01:00
Andrey Antukh
8df12e5e9c Remove state assignation round-trip on update-dimensions event
Using the lower-level apply-modifiers event, introduced in previous
commit
2025-03-18 16:19:55 +01:00
Andrey Antukh
cd423f23c6 Remove get-hidden-theme from tokens lib protocol 2025-03-18 16:19:55 +01:00
Andrey Antukh
86c2c4cd41 ♻️ Add lower-level impl of apply-modifiers event 2025-03-18 16:19:55 +01:00
Andrey Antukh
d9c4fc3721 Calculate uuid lazily on creating token theme 2025-03-18 16:19:55 +01:00
Andrey Antukh
b91e72d8a1 🐛 Fix typo 2025-03-18 16:19:55 +01:00
Andrey Antukh
6cc96ef679 Add logging for tokens update event operation 2025-03-18 16:19:55 +01:00
Andrey Antukh
28fe951c40 ♻️ Replace usage of dm/assert on several namespaces
And remove the `!` from the name on check functions
2025-03-18 16:19:55 +01:00
Andrey Antukh
22f789e77c Don't put timeout on tokens changes transaction 2025-03-18 16:19:55 +01:00
Eva Marco
2e5138eddc 🐛 Fix error message on invalid json (#6099) 2025-03-18 16:19:17 +01:00
Elena Torro
731c21f082 🐛 Fix drop shadows viewport clipping 2025-03-18 15:56:43 +01:00
Xavier Julian
99d7672284 Validate token name while typing 2025-03-18 14:14:16 +01:00
Andrés Moya
567fdd9619 🐛 Fix initial value of color bullet in form 2025-03-18 12:04:24 +01:00
Yamila Moreno
6067e438a3 📚 Document auto file snapshot (#6085) 2025-03-18 11:40:58 +01:00
Eva Marco
fc17a1742a 🐛 Fix copy on input placeholder (#6097) 2025-03-18 11:30:40 +01:00
al0cam
12d3994f45 🌐 Add translations for: Croatian
Currently translated at 99.6% (1641 of 1646 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/hr/
2025-03-18 10:01:54 +00:00
Eva Marco
f7f1598e71 🐛 Fix select same set after rename (#6095) 2025-03-18 10:55:44 +01:00
Eva Marco
8caf559a1a 🐛 Fix resolved value on tooltip (#6084) 2025-03-18 10:54:43 +01:00
Elena Torró
e927161ec1 Merge pull request #6066 from penpot/elenatorro-10387-test-emoji-rendering
 Support emoji default font in text rendering
2025-03-18 10:50:20 +01:00
Elena Torro
ba387a892f Support emoji default font in text rendering 2025-03-18 10:33:27 +01:00
Alejandro Alonso
18015bde4f Merge remote-tracking branch 'origin/staging' into develop 2025-03-18 10:14:16 +01:00
Alejandro Alonso
8affefbbab 📎 Update changelog 2025-03-18 10:13:12 +01:00
jdo-odoo
0225919a45 📚 Fix typos in shortcut and insert image section
Signed-off-by: jdo-odoo <108932862+jdo-odoo@users.noreply.github.com>
2025-03-18 10:09:58 +01:00
Pablo Alba
0901807db8 Update inspect-title-bar and copy-button to the new components format 2025-03-18 09:52:32 +01:00
Pablo Alba
625cbfc50a 🎉 Add variants properties to inspect panel 2025-03-18 09:52:32 +01:00
Eva Marco
b2bc5aff68 🐛 Add lost spanish translation (#6089) 2025-03-18 09:25:35 +01:00
Eva Marco
337c61db2c 🐛 Fix not active sets on json import (#6087) 2025-03-18 09:14:30 +01:00
Andrey Antukh
5c2c96fc2e Merge pull request #6086 from penpot/niwinz-develop-token-fixes-2
 Several bugfixes related to tokens (part 2)
2025-03-17 15:50:33 +01:00
Andrey Antukh
04c77a8532 🔥 Remove unused double token resolve operation on sidebar 2025-03-17 14:56:55 +01:00
Andrey Antukh
ebcf5b3177 🐛 Avoid theme overwrite on creating a theme with existing name 2025-03-17 14:56:55 +01:00
Andrey Antukh
9d2117e2ac 📎 Replace use-callback with use-fn on token themes modal 2025-03-17 14:56:55 +01:00
Andrey Antukh
c1c22dc6c6 Merge pull request #6075 from penpot/niwinz-develop-token-fixes-1
 Add several fixes and improvements to tokens
2025-03-17 14:47:21 +01:00
Andrey Antukh
1e10e3818e 🔥 Remove not necessary API from tokens-lib: add-sets 2025-03-17 14:24:55 +01:00
Andrey Antukh
802c67ace4 🔥 Remove unused API from tokens-lib
Removes the protocol method: `get-set-prefixed-path-string`
2025-03-17 14:24:54 +01:00
Andrey Antukh
5c3709b5d8 🔥 Remove unused API from tokens-lib
Removes the protocol method: `get-tokens-tree`
2025-03-17 14:24:54 +01:00
Andrey Antukh
626c65df02 🔥 Remove unnecesary API from tokens lib
Removes the `get-dtcg-tokens-tree` protocol method
2025-03-17 14:24:54 +01:00
Andrey Antukh
f2f492bf3f 🔥 Remove commented code 2025-03-17 14:24:54 +01:00
Andrey Antukh
40f69d320e Show proper toast message on token-set rename error 2025-03-17 14:24:52 +01:00
Andrey Antukh
1893cd306a Improve translation strings for token set drop errors 2025-03-17 14:24:33 +01:00
Andrey Antukh
096b685e2c 🐛 Prevent token-set overwrite on creation and edition 2025-03-17 14:24:02 +01:00
Andrey Antukh
1965490bee 📎 Use proper catch matching on tokens drop operation 2025-03-17 14:24:02 +01:00
Andrey Antukh
559dcabf0e Normalize token name on creation 2025-03-17 14:24:02 +01:00
Andrey Antukh
a9e8d8f8f7 Make the calculate-move-token-set-or-set-group fn private 2025-03-17 14:24:02 +01:00
Alejandro Alonso
dba67eea91 Merge remote-tracking branch 'origin/staging' into develop 2025-03-17 12:52:56 +01:00
Andrey Antukh
70fe6fda83 🔥 Remove unused code 2025-03-17 12:27:20 +01:00
luisδμ
5155cf2b23 🐛 Fix clicking on a comment at the viewer's sidebar is not opening threads (#6083) 2025-03-17 12:25:23 +01:00
elhombretecla
5ca9b95cca 🎉 Adds tips to the file loading screen (#6063)
* 🎉 Add tips to the default loader component

* 📎 Use simplier approach for show tips

This commit also fixes other minor issues

* 📎 Extract to constants the loader path data

* 📎 Use properly tracked translations for loader tips

---------

Co-authored-by: Andrey Antukh <niwi@niwi.nz>
2025-03-17 12:24:44 +01:00
Alonso Torres
fa0da3a695 Flex layout modifiers wasm implementation
*  Flex layout modifiers wasm implementation

*  Flex auto modifiers propagation
2025-03-17 10:46:32 +01:00
Xavier Julian
fa9d8a9b15 Add a tooltip explanation on themes modal sets 2025-03-17 10:21:50 +01:00
Tummas Jóhan Sigvardsen
e3b6b24c5f 🌐 Add translations for: Faroese
Currently translated at 10.0% (165 of 1646 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/fo/
2025-03-17 00:01:53 +01:00
Louis Chance
1eb7205c12 🌐 Add translations for: French
Currently translated at 85.3% (1405 of 1646 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/fr/
2025-03-17 00:01:52 +01:00
al0cam
92f4bdae03 🌐 Add translations for: Croatian
Currently translated at 87.7% (1445 of 1646 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/hr/
2025-03-14 22:02:57 +01:00
Vin
bd63a460eb 🌐 Add translations for: Russian
Currently translated at 88.0% (1450 of 1646 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/ru/
2025-03-14 22:02:56 +01:00
Andrey Antukh
7403f60366 Merge pull request #6076 from penpot/alotor-fix-problem-inspect
🐛 Fix problem with readonly and inspect
2025-03-14 15:50:01 +01:00
Alejandro Alonso
66295b0adf Merge remote-tracking branch 'origin/staging' into develop 2025-03-14 12:55:44 +01:00
Belén Albeza
eb6d2fb0eb 🎉 Store custom fonts (ttfs) and use them to write texts (wasm) (#6050) 2025-03-14 12:45:15 +01:00
Alejandro
a8c34ccc1a Merge pull request #6070 from penpot/alotor-bugfix-grid-layout
🐛 Fix problem with grid component propagation
2025-03-14 12:39:54 +01:00
alonso.torres
8c501db2fa 🐛 Fix problem with readonly and inspect 2025-03-14 12:24:34 +01:00
alonso.torres
d2fbb9dfa7 🐛 Fix problem with grid component propagation 2025-03-14 11:50:55 +01:00
Andrey Antukh
e4c9b736f7 Merge remote-tracking branch 'origin/staging' into develop 2025-03-14 11:19:47 +01:00
Andrey Antukh
f02f446015 Merge pull request #6071 from penpot/xaviju-10527-tooltip-import-warning
 Add a warning tooltip over import tokens button
2025-03-14 10:00:18 +01:00
Andrey Antukh
05d6d2fcd4 🐛 Fix several corner cases that causes race conditions on workspace and dashboard loading
* 🐛 Fix several race conditions on workspace and dashboard code

It also fixes a corner case that happens when penpot workspace
is loaded in a background tab on firefox.

* 🐛 Add missing team-id prop to several file returning endpoints
2025-03-14 09:55:41 +01:00
Andrey Antukh
d5492442fb Merge pull request #6068 from penpot/alotor-fix-readonly
🐛 Fix problem with readonly and inspect
2025-03-14 09:34:30 +01:00
al0cam
02e975f594 🌐 Add translations for: Croatian
Currently translated at 77.8% (1282 of 1646 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/hr/
2025-03-13 17:02:00 +00:00
Andrey Antukh
61800d8945 Merge pull request #6074 from penpot/dfelinto-export-webp
🎉 Add support for WEBP format for shape export
2025-03-13 16:24:55 +01:00
Dalai Felinto
f450c9dbe3 🎉 Add support for WEBP format on shape export
It is very convenient to be able to export WEBP right from penpot.
Otherwise users have to first download to PNG then convert it locally.

---

Playwright only supports JPEG and PNG. So in order to support WEBP I had
to first generate a PNG and then convert it afterwards.

Signed-off-by: Dalai Felinto <dalai@blender.org>
2025-03-13 16:15:30 +01:00
Xavier Julian
b46574bef6 Add a warning tooltip over import tokens button 2025-03-13 13:26:41 +01:00
Andrey Antukh
e3b3fa3342 📎 Update changelog 2025-03-13 09:32:19 +01:00
Eva Marco
21b2c0c26a 🐛 Fix token unset when flex layout is applied 2025-03-12 20:03:50 +01:00
alonso.torres
dcbf54fae1 🐛 Fix problem with readonly and inspect 2025-03-12 16:39:31 +01:00
Eva Marco
2fe6fb28e4 🐛 Fix tooltip update when set changes (#6058) 2025-03-12 15:49:07 +01:00
luisδμ
86022a967c Replace overlapping bubbles with a bubble group (#6059) 2025-03-12 14:37:39 +01:00
Eva Marco
0efbebd94f 🎉 Avoid setting token to group shapes (#6055)
* 🎉 Avoid setting token to group shapes

* 📎 Fix on update shape when double click
2025-03-12 14:18:59 +01:00
Marina López
2aee2ea79e 📚 Add US in changes.md 2025-03-12 14:03:50 +01:00
elhombretecla
60a20b6984 Add new toggle and translations 2025-03-12 14:03:50 +01:00
elhombretecla
fd753fb262 💄 Add new css styles 2025-03-12 14:03:50 +01:00
elhombretecla
0ae57a017e Add new carrousel layout 2025-03-12 14:03:50 +01:00
Alejandro
88772a9ced Merge pull request #6061 from penpot/alotor-bug-fills
🐛 Fix problem adding fill
2025-03-12 12:31:43 +01:00
Alejandro Alonso
65647f4aae Merge remote-tracking branch 'origin/staging' into develop 2025-03-12 12:30:11 +01:00
Alejandro
fe04f3e45d Merge pull request #6065 from penpot/superalex-fix-sync-issues-components
🐛 Fix sync issues components
2025-03-12 12:27:25 +01:00
Alejandro Alonso
363c1d5b56 🐛 Fix sync libraries of components 2025-03-12 12:15:00 +01:00
alonso.torres
5e6ccc44fc 🐛 Fix problem adding fill 2025-03-12 10:22:04 +01:00
Andrei Fëdorov
b9df8ad038 ♻️ Simplifies RPC pattern for token themes (#6052)
* ♻️ Add set token theme method schema

* ♻️ Add `:set-token-theme` dispatcher for `process-change` multimenthod

* ♻️ Add `set-token-theme` to the changes builder

* ♻️ Use new method on the frontend

* ♻️ Remove unused token theme methods

* ♻️ Add tests

* ♻️ Add library data to changes

* ♻️ Add new test case

* ♻️ Remove unused binding
2025-03-12 09:29:03 +01:00
Yamila Moreno
3ee3df9b24 Merge pull request #6019 from penpot/yms-improve-troubleshooting-toc
📚 Improve TOC in Troubleshooting section
2025-03-11 16:30:03 +01:00
Yamila Moreno
332657bd1b 📎 Add minor improvements 2025-03-11 16:21:16 +01:00
Eva Marco
474cd1e55a 🐛 Fix migration keyword (#6057) 2025-03-11 16:19:51 +01:00
Andrei Fëdorov
b52e8bc87c ♻️ Simplifies RPC pattern for token sets (#6045)
* ♻️ Add set removal methods to tokens library

* ♻️ Add `set-token-set` method to changes

* ♻️ Add `set-token-set` to changes builder

* ♻️ Use new method in the token set creation

* ♻️ Use `set-token-set` in frontend events

* ♻️ Remove unused binding

* ♻️ Add tests

* ♻️ Remove old API methods

* ♻️ Remove unused parts of schema and multimethods

* ♻️ Make `:tokens` key optional in schema

* ♻️ Add `with-library-data` calls before `set-token-set`

* ♻️ Fix DOM properties error
2025-03-11 16:03:52 +01:00
Yamila Moreno
953f770fdd 📚 Improve TOC for self-hosting guide 2025-03-11 12:45:30 +01:00
Yamila Moreno
c83b9ea305 📚 Improve TOC in Troubleshooting section 2025-03-11 12:45:30 +01:00
Elena Torró
f35723e772 Merge pull request #6048 from penpot/elenatorro-10448-fix-clipping-over-groups
🐛 Fix children clip bounds inheritance
2025-03-11 12:06:40 +01:00
Pablo Alba
415d1a2668 Merge pull request #6032 from penpot/palba-variants-create-with-path
 Create variant from component with path
2025-03-11 11:40:31 +01:00
Alejandro Alonso
b3feb9bffd Merge remote-tracking branch 'origin/staging' into develop 2025-03-11 10:00:17 +01:00
Denys Kisil
fdeabc15ab 🌐 Add translations for: Ukrainian (ukr_UA)
Currently translated at 99.6% (1641 of 1646 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/ukr_UA/
2025-03-11 09:02:04 +01:00
Alejandro
dfbf0d34b6 Merge pull request #6036 from penpot/elenatorro-10427-update-rust-last-version
🔧 Upgrade rust to v1.85
2025-03-11 08:40:33 +01:00
Eva Marco
0c3fd8a6d9 🎉 Add id to token theme (#6044)
* 🎉 Add id to token theme

* 📎 Fix tests

* 📎 Fixes from review
2025-03-10 18:38:52 +01:00
elenatorro
5b9dd96e02 🐛 Fix children clip bounds inheritance 2025-03-10 15:55:43 +01:00
Xavier Julian
46c89a1bcf Fix stories and add default state to toast 2025-03-10 14:43:41 +01:00
Xavier Julian
721760d679 Add a default appearance to context notifications 2025-03-10 14:43:41 +01:00
elenatorro
2cdb874484 🔧 Upgrade rust to v1.85 2025-03-10 13:33:12 +01:00
Andrés Moya
e5bccc470b Validate if token values are too large 2025-03-10 13:32:16 +01:00
Andrey Fedorov
ba768f8744 🐛 Fix Ci tests for shape proxy in plugin runtime 2025-03-10 13:29:10 +01:00
Andrey Fedorov
a33828467f ♻️ Rename bindings 2025-03-10 13:29:10 +01:00
Andrey Fedorov
6fed0f3b58 ♻️ Remove unused bidings and requirements 2025-03-10 13:29:10 +01:00
Andrey Fedorov
5f3599eaa7 🐛 Fix token dimension application for all relatively positioned shapes 2025-03-10 13:29:10 +01:00
Andrey Fedorov
44ca01aa27 🐛 Fix relative position application for flex children 2025-03-10 13:29:10 +01:00
Xavier Julian
451306f719 Add a maxlenght to input CRUD tokens 2025-03-10 13:25:07 +01:00
Elena Torró
29518f3ba5 Merge pull request #6042 from penpot/elenatorro-10436-fix-rounded-corners-for-images
🐛 Fix rounded corners in image fill
2025-03-10 12:49:50 +01:00
Elena Torró
d74bfd834d Merge pull request #6035 from penpot/elenatorro-10314-allow-mutable-static-only-on-state
🔧 Use with_state and with_current_state macros allowing static…
2025-03-10 12:42:47 +01:00
elenatorro
ac8b5a7bcc 🐛 Fix rounded corners in image fill 2025-03-10 12:16:41 +01:00
Denys Kisil
8363cb7449 🌐 Add translations for: Ukrainian (ukr_UA)
Currently translated at 99.6% (1641 of 1646 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/ukr_UA/
2025-03-09 19:02:05 +01:00
Xavier Julian
390cf6b642 Recalculate token context-menu submenu position 2025-03-07 19:14:07 +01:00
elenatorro
0dbf00a767 🔧 Use with_state and with_current_state macros allowing static_mut_refs only on STATE 2025-03-07 15:24:04 +01:00
Elena Torró
a361e0b990 Merge pull request #5992 from penpot/elenatorro-10314-use-mutex-for-static-mut
🔧 Do not use global static mut variables when possible
2025-03-07 15:20:05 +01:00
elenatorro
3a8ba4cbee 🔧 Avoid using global static mut variables when possible 2025-03-07 15:07:31 +01:00
Elena Torró
d5c9e68a3e 🔧 Update pull request GitHub template (#6022) 2025-03-07 14:45:29 +01:00
Alejandro
253d94c176 Merge pull request #6031 from penpot/fix-problem-flex-reverse
🐛 Fix problem with reverse config in flex
2025-03-07 14:08:25 +01:00
Pablo Alba
fd941e4701 🎉 Update package.json files 2025-03-07 13:59:20 +01:00
Pablo Alba
a99198de48 Filter variants on asset panel 2025-03-07 13:43:04 +01:00
Eva Marco
e729e85c42 ♻️ Create hidden theme on token lib creation (#5991)
* ♻️ Create hidden theme on token lib creation

* 📎 Fix tests

* 🎉 Add migration

* 🎉 Remove comment

* ♻️ Remove unused changes

* 📎 Remove unused fn
2025-03-07 13:17:36 +01:00
Pablo Alba
7eb9325047 Create variant from component with path 2025-03-07 09:54:38 +01:00
alonso.torres
ba4554da79 🐛 Fix problem with reverse config in flex 2025-03-07 09:23:07 +01:00
Alejandro
97fb1e00c2 Merge pull request #6028 from penpot/palba-fix-toolbar-tooltips
🐛 Fix hidden toolbar click event still available
2025-03-07 08:08:06 +01:00
Pablo Alba
3eb332f3d0 🐛 Fix hidden toolbar click event still available 2025-03-07 07:57:04 +01:00
Alejandro Alonso
0d11bafb57 Merge remote-tracking branch 'origin/staging' into develop 2025-03-07 07:54:05 +01:00
alonso.torres
e01dfd76e8 Merge remote-tracking branch 'origin/staging' into develop 2025-03-06 16:05:12 +01:00
Alejandro
854145e435 Merge pull request #6024 from penpot/fix-resize-problem
🐛 Fix problem with new render resize
2025-03-06 12:33:09 +01:00
alonso.torres
707bfd4241 🐛 Fix problem with new render resize 2025-03-06 12:20:56 +01:00
Andrés Moya
02bc6e62e7 🔧 Use a more correct selector in one test 2025-03-06 10:36:10 +01:00
Andrés Moya
9fde4e2121 🐛 Unapply token when manually changing layout margin and padding 2025-03-06 10:07:59 +01:00
Elena Torró
66eb4fb5ad Merge pull request #6003 from penpot/superalex-update-rust-skia-version
 Update rust skia version to 0.81.0
2025-03-06 09:30:57 +01:00
Alejandro Alonso
e362f423c0 Merge remote-tracking branch 'origin/staging' into develop 2025-03-06 07:36:19 +01:00
Alejandro
dc08eb7899 Merge pull request #6014 from penpot/marina-plugins-list-lacks-scrolling
🐛 Add scroll to plugins menu list
2025-03-06 07:27:34 +01:00
Marina López
a1e307b4ce 🐛 Add scroll to plugins menu list 2025-03-06 07:26:36 +01:00
Alejandro
a0f16fc038 Merge pull request #6013 from penpot/palba-fix-duplicate-page
🐛 Fix duplicate page with component over frame
2025-03-06 07:25:54 +01:00
Pablo Alba
7c36c76b0d 🐛 Fix duplicate page with component over frame 2025-03-06 07:17:46 +01:00
Alejandro
8488be311e Merge pull request #6011 from penpot/palba-fix-cut-paste-copy
🐛 Fix cut and paste a copy inside its parent
2025-03-06 07:16:51 +01:00
Pablo Alba
2297862d81 🐛 Fix cut and paste a copy inside its parent 2025-03-06 07:08:37 +01:00
Alejandro
539fdfa016 Merge pull request #6010 from penpot/marina-dashboard-sidebar-horizontal-scroll
🐛 Hide horizontal scroll from dashboard sidebar
2025-03-06 07:07:58 +01:00
Marina López
a7f6797499 🐛 Hide horizontal scroll from dashboard sidebar 2025-03-06 07:00:14 +01:00
Alejandro
cc7f745a0a Merge pull request #5966 from penpot/alotor-bug-click-resize
🐛 Fix problem resizing on click
2025-03-06 06:56:45 +01:00
alonso.torres
265675795e 🐛 Fix problem resizing on click 2025-03-06 06:40:47 +01:00
Alejandro Alonso
2c789e48f3 Merge remote-tracking branch 'origin/staging' into develop 2025-03-05 17:07:23 +01:00
Xavier Julian
9da6c50cbe Display tokens contextual menu in body through portal 2025-03-05 11:53:37 +01:00
Alejandro Alonso
5c53de8e76 Merge remote-tracking branch 'origin/staging' into develop 2025-03-05 11:00:19 +01:00
Alejandro
3cdc826fca Merge pull request #6012 from penpot/hiru-integration-tests
📚 Add some more instructions on running integration tests
2025-03-05 10:48:21 +01:00
Andrés Moya
02292f99ab 📚 Add some more instructions on running integration tests 2025-03-05 10:30:39 +01:00
Xavier Julian
0279e75c4b 🐛 Fix unsetted custom property on notifications 2025-03-04 22:09:11 +01:00
Pablo Alba
44f1798dce 🐛 Fix add variant menu inside a variant 2025-03-04 17:34:04 +01:00
Alejandro Alonso
23468a9908 Update rust skia version to 0.81.0 2025-03-04 16:20:56 +01:00
Pablo Alba
8eb2aaa0a8 🎉 Create a new variant from an existing one 2025-03-04 13:52:40 +01:00
Belén Albeza
aa468e2153 🎉 Render plain text
* 🎉 Serialize text content (wasm)

* ♻️ Refactor functions in main to wasm module

* 🎉 Stub rendering of paragraph text (wasm)

* 📎 Clean up commented code
2025-03-04 11:54:52 +01:00
María Valderrama
9e5de82967 📚 Add mark all as read feature to CHANGES.md 2025-03-04 11:25:16 +01:00
Alonso Torres
856e2be1ca 🐛 Fix problem when creating layouts 2025-03-04 11:04:26 +01:00
elhombretecla
8d4b023d61 💄 Remove underline decoration 2025-03-03 17:12:19 +01:00
Nicola Bortoletto
da43a4d3b4 🌐 Add translations for: Italian
Currently translated at 99.6% (1641 of 1646 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/it/
2025-03-03 16:04:07 +01:00
Andrés Moya
f06f11ad7a 🐛 Avoid crash when applying a token with no active value 2025-03-03 11:25:00 +01:00
Alejandro Alonso
c807e37525 Merge remote-tracking branch 'origin/staging' into develop 2025-03-03 07:16:31 +01:00
Andrey Antukh
c9a8d2bd23 🚧 Tokens (part4) (#5952)
*  Use reduce-kv for creating tokens tree

Instead of reduce

*  Avoid double iteration on spliting text shapes from shapes

On processing color changes

* ♻️ Move the undo transaction out of transform-fill

The undo transaction is a high level construct and it should
be called from the first level events. Low level impl should
not handle transactions at all

*  Use low-level primitives for update-fill token event

* 📎 Add performance logging for style dictionary resolution

* 📎 Replace inline code with a helper

* ♻️ Refactor how fill and stroke color is applied on tokens

* 💄 Fix call convention for component-item-thumbnail component

*  Clean component thumbnail when frame change received

* 📎 Fix tests

---------

Co-authored-by: Eva Marco <evamarcod@gmail.com>
2025-02-28 09:47:13 +01:00
Florian Schrödl
65c6c821e7 🐛 Fix set with spaces not being rename-able via context menu (#5956) 2025-02-28 09:46:52 +01:00
Xavier Julian
6cccacaaab 💄 Improve context menu scanability 2025-02-27 22:45:06 +01:00
Elena Torró
7da97d69b0 🐛 Fix viewer style in fullscreen mode (#5964) 2025-02-27 17:57:05 +01:00
Belén Albeza
f7574009b5 🐛 Fix layout context menu width + position 2025-02-27 17:47:31 +01:00
Belén Albeza
0416e883ca 🐛 Fix rendering order of inner shadows when shape has no fills (wasm) 2025-02-27 17:45:39 +01:00
Alejandro Alonso
c0ccb86e3a Merge remote-tracking branch 'origin/staging' into develop 2025-02-27 15:34:39 +01:00
william chen
69d21e20c9 🌐 Add translations for: Chinese (Traditional Han script)
Currently translated at 100.0% (1646 of 1646 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/zh_Hant/
2025-02-27 04:02:34 +00:00
Alejandro Alonso
7885f413b8 Merge remote-tracking branch 'origin/staging' into develop 2025-02-26 18:00:51 +01:00
Eva Marco
dfd5c5b508 🐛 Fix height of combobox label (#5944) 2025-02-26 16:54:28 +01:00
Elena Torró
bffbccac50 Merge pull request #5968 from penpot/ladybenko-fix-sampling-options-merge
🐛 Fix messed up rebase re: sampling options
2025-02-26 15:32:26 +01:00
Belén Albeza
12c2d73846 🐛 Fix messed up rebase re: sampling options 2025-02-26 15:18:26 +01:00
Elena Torró
27d15763f8 🐛 Override default SamplingOptions for ImageFill and set FilterMode (#5961)
* 🐛 Override default SamplingOptions for ImageFill and set FilterMode and MipmapMode to 'Linear' instead of 'Nearest'

* 📎 Use sampling_options from render_state in ImageFill
2025-02-26 14:27:25 +01:00
Alejandro
0eaa43f36b Merge pull request #5930 from penpot/ladybenko-10321-split-fill-strokes
 Split rendering of fills and strokes in separate surfaces
2025-02-26 11:57:37 +01:00
Elena Torró
e30834bb2d Enable WEBGL_debug_renderer_info extension before initializing the render (#5959) 2025-02-26 11:32:27 +01:00
Juanfran
fefb946a25 Merge pull request #5951 from penpot/juanfran-expand-padding-margin-apply-token
🐛 Expand padding/margin values on apply token and show 'Mixed' placeholder
2025-02-26 11:15:33 +01:00
Juanfran
2d857ecf2f 🐛 Expand padding/margin values on apply token and show 'Mixed' placeholder 2025-02-26 10:57:51 +01:00
Belén Albeza
2cf179ccf6 ♻️ Add ShapeStrokes surface 2025-02-26 09:51:30 +01:00
Belén Albeza
5ebfc603e6 ♻️ Refactor surfaces (wasm) 2025-02-26 09:50:17 +01:00
william chen
a925d6710a 🌐 Add translations for: Chinese (Traditional Han script)
Currently translated at 88.2% (1453 of 1646 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/zh_Hant/
2025-02-26 03:05:58 +00:00
alonso.torres
80d5272248 Serialize layout data 2025-02-25 15:43:12 +01:00
Andrey Antukh
b4f6177be7 🐛 Move team srepl helpers back to main from helpers (#5955) 2025-02-25 14:56:58 +01:00
Andrés Moya
3907a1783a Include active sets and themes in exported tokens json file (#5806)
*  Add active sets to json decode

* 📎 Fix tests

* 📎 Add encode tests

* 📎 Add decode test

---------

Co-authored-by: Eva Marco <evamarcod@gmail.com>
2025-02-25 14:05:07 +01:00
Andrey Antukh
b676ea7127 Merge remote-tracking branch 'origin/staging' into develop 2025-02-25 12:56:05 +01:00
Xavier Julian
ca65f5ad9a 💄 Improve theme modal with UX enhancements 2025-02-25 12:52:12 +01:00
Elena Torró
3e89b73ca0 📚 Add developer docs about how to test feature flags by team (#5949) 2025-02-25 12:51:00 +01:00
Alejandro
17e9e836f6 Merge pull request #5950 from penpot/alotor-fix-gradient-strokes
🐛 Fix problem with gradient in strokes
2025-02-25 11:43:49 +01:00
alonso.torres
c48d862d0f 🐛 Fix problem with gradient in strokes 2025-02-25 11:29:57 +01:00
alonso.torres
052282cff9 🐛 Fix problem updating layout when duplicating component 2025-02-25 11:21:41 +01:00
Pablo Alba
6d40166de7 Remove menu options and shortcuts actions over variants 2025-02-25 10:11:14 +01:00
Elena Torró
ab7781b4fa Add dbg panel to enable a team feature flag (#5940)
*  Add dbg panel to enable and disable team feature flags

* 📎 Rename debug to skip-check and do not parse & cast the feature value
2025-02-25 10:09:43 +01:00
Andy Li
f5218e207b 🌐 Add translations for: Chinese (Traditional Han script)
Currently translated at 66.1% (1089 of 1646 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/zh_Hant/
2025-02-25 03:04:17 +01:00
william chen
7fb6a095c6 🌐 Add translations for: Chinese (Traditional Han script)
Currently translated at 66.1% (1089 of 1646 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/zh_Hant/
2025-02-25 03:04:16 +01:00
Eva Marco
88669d2e0f 🎉 Add translations to token errors (#5926) 2025-02-24 15:50:47 +01:00
Andrey Antukh
1187d64f69 Merge remote-tracking branch 'origin/staging' into develop 2025-02-24 12:49:04 +01:00
Andrey Antukh
3074fc9ab5 ♻️ Remove deprecated with-atomic and refactor tx-run! (#5915)
* ♻️ Remove deprecated with-atomic and refactor tx-run!

*  Do not hold open connection for the whole clone-template operation
2025-02-24 11:15:44 +01:00
Elena Torró
bcea19001e Improve readability of RGBA and HSLA values in inspect mode (#5918)
*  Improve readability of RGBA and HSLA values in inspect mode

* 📎 Remove reader conditionals for format common methods
2025-02-24 09:08:42 +01:00
Andrés Moya
1c98c53805 🔧 Add filtering to logs in component sync algorithm 2025-02-21 11:30:02 +01:00
Aitor Moreno
4799f6fe0a ♻️ Refactor rendering surfaces (#5921) 2025-02-21 11:04:12 +01:00
Alejandro
7470fb709f Merge pull request #5920 from penpot/alotor-test-apply-modifiers
 Modify shapes geometry instead of transformation matrix
2025-02-21 07:44:32 +01:00
alonso.torres
8c1e18b1cd 🐛 Fix problem with images 2025-02-20 17:57:36 +01:00
alonso.torres
9143187efd Modify shapes geometry instead of transformation matrix 2025-02-20 17:39:17 +01:00
Aitor Moreno
b661f39422 ♻️ Refactor render shape (#5916) 2025-02-20 16:33:18 +01:00
Aitor Moreno
3a764a9da6 Merge pull request #5919 from penpot/alotor-constraints-2
🐛 Fix problems with constraints resizing
2025-02-20 16:26:46 +01:00
alonso.torres
2341dfb95d 🐛 Fix problems with constraints resizing 2025-02-20 14:20:01 +01:00
Xavier Julian
ff121d2af5 💄 Differentiate empty and not empty token types 2025-02-20 14:12:51 +01:00
Xavier Julian
55d7bab0e6 💄 Spacing on token sets 2025-02-20 13:31:18 +01:00
Juanfran
4a3d951329 Merge pull request #5888 from penpot/juanfran-fix-flaky-add-new-test
 Add more integration tests for tokens
2025-02-20 10:10:00 +01:00
Pablo Alba
014c297458 🎉 Add drag components in or out a variant container 2025-02-20 10:05:01 +01:00
Juanfran
280da72e63 Add more integration tests for tokens 2025-02-20 09:57:31 +01:00
Alejandro Alonso
6277db8d45 🐛 Fix clip for frames with border radius (render wasm) 2025-02-20 09:24:55 +01:00
Andrey Antukh
60530a80d9 Merge remote-tracking branch 'origin/staging' into develop 2025-02-20 09:15:00 +01:00
Andrey Antukh
d79fac7729 Merge remote-tracking branch 'origin/staging' into develop 2025-02-19 17:17:54 +01:00
Pablo Alba
195127b099 Add text selection on focus of an input-with-values (#5909) 2025-02-19 16:51:49 +01:00
María Valderrama
a3e74c55f1 💄 Add cosmetic changes to notifications buttons (#5902) 2025-02-19 16:45:22 +01:00
Juanfran
e408bc9113 Merge pull request #5904 from penpot/juanfran-themes-dropdown-scrollbar-styles
🐛 Fix scrollbar styles in themes dropdown
2025-02-19 15:22:19 +01:00
Juanfran
89dc917cb9 🐛 Fix scrollbar styles in themes dropdown 2025-02-19 14:25:43 +01:00
Elena Torró
f83cdf2f5d 📎 Remove invalid aria label on div (#5898) 2025-02-19 11:42:44 +01:00
Elena Torró
f3040fc10d 🐛 Pass color format to css formatter (#5890)
* 🐛 Pass color format to css formatter

* 📎 Use get method to retrieve format

* 📎 Add UI test to check background color is correctly copied to clipboard when changing the format
2025-02-19 11:23:52 +01:00
Andrey Antukh
44acd79081 Merge remote-tracking branch 'origin/staging' into develop 2025-02-19 10:46:55 +01:00
Andrey Antukh
a3e4da0b3d 📎 Update changelog 2025-02-19 10:46:33 +01:00
Elena Torró
73a52e5395 🐛 Fix opacity in frame containers (#5858)
* 🐛 Fix opacity in frame containers

* 📎 Improve readability of frame containers by using class names
2025-02-19 10:44:24 +01:00
Alonso Torres
6cb1aa24cd Add constraints calculation on WASM (#5894)
*  Add constraints calculation on WASM

*  Fix after review
2025-02-19 10:40:04 +01:00
Andrey Antukh
f5c913d26e Merge remote-tracking branch 'origin/staging' into develop 2025-02-18 17:28:38 +01:00
Andrey Antukh
c86f14e75d 🐛 Fix color slider not updating the hue of the ramp (#5891)
* 🐛 Fix color slider not updating the hue

*  Add minor enhancements for ramp* component

---------

Co-authored-by: Andrey Fedorov <oran9e.red@gmail.com>
2025-02-18 16:42:11 +01:00
Pablo Alba
65a97167de 🐛 Fix bad value on combobox enter keydown (#5859) 2025-02-18 15:55:22 +01:00
Xavier Julian
0530c57d31 Add placeholder to themes modal 2025-02-18 14:51:33 +01:00
Andrey Antukh
adbe29e3d1 Merge remote-tracking branch 'origin/staging' into develop 2025-02-18 10:25:13 +01:00
Alejandro
5fae07af11 Merge pull request #5880 from penpot/alotor-render-wasm-cache
🐛 Fix problem with cache
2025-02-18 10:20:31 +01:00
alonso.torres
400e5f60f2 🐛 Fix problem with cache 2025-02-18 10:00:57 +01:00
Pablo Alba
3268225941 🎉 Add variations POC 2025-02-17 16:47:25 +01:00
Xaviju
91fa39705d ♻️ Switch contextual notification component (#5874) 2025-02-17 16:03:13 +01:00
Andrey Antukh
c41f86f0a4 Merge remote-tracking branch 'origin/staging' into develop 2025-02-17 15:20:33 +01:00
Eva Marco
81b741478a 🐛 Fix a little regression on sidebar resize (#5866) 2025-02-17 12:25:07 +01:00
Juanfran
f6fc2f8808 🐛 Prevent themes dropdown overflow hidden in set sidebar (#5850) 2025-02-17 09:51:10 +01:00
Edgars Andersons
6a0bb2f452 🌐 Add translations for: Latvian
Currently translated at 99.6% (1641 of 1646 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/lv/
2025-02-14 16:01:57 +01:00
Amerey.eu
d02f85315a 🌐 Add translations for: Czech
Currently translated at 99.3% (1635 of 1646 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/cs/
2025-02-14 16:01:56 +01:00
Andrey Fedorov
aa180e9f3f 🐛 Fix max- min- width height not being applied 2025-02-14 15:26:49 +01:00
Florian Schroedl
6b773d6b74 🐛 Dont allow hex values without # prefix 2025-02-14 13:52:54 +01:00
Belén Albeza
6cbaacf1e0 🎉 Implement inner shadows (wasm) (#5767)
* 🎉 Implement inner shadows (wasm)

* 🐛 Fix reset canvas problem

---------

Co-authored-by: alonso.torres <alonso.torres@kaleidos.net>
2025-02-14 13:46:30 +01:00
Eva Marco
2ffb77cb4d Merge pull request #5840 from penpot/niwinz-tokens-changes-3
♻️ Token changes (part 3)
2025-02-14 12:55:12 +01:00
María Valderrama
59a57d6c3f Mark all notifications as read from dashboard (#5805)
*  Mark all notifications as read from dashboard

* ♻️ Mark all notifications as read code review

* ♻️ Mark all notifications as read code review II
2025-02-14 11:48:24 +01:00
Xaviju
8a332c1402 Add placeholder to set edition (#5848) 2025-02-14 11:46:04 +01:00
Andrey Antukh
37855bfe7f Merge remote-tracking branch 'origin/staging' into develop 2025-02-14 10:35:29 +01:00
Andrey Antukh
f68b0117c4 ♻️ Simplify token creation mechanism 2025-02-14 08:49:31 +01:00
Andrey Antukh
aa867adbd3 ♻️ Add minor refactor on tokenlib object construction and validation 2025-02-14 08:49:30 +01:00
Andrey Antukh
3fd429c72a Merge remote-tracking branch 'origin/staging' into develop 2025-02-13 21:04:52 +01:00
Aitor Moreno
39bbb4c2bd Merge pull request #5827 from penpot/superalex-fix-wasm-glitches
🐛 Fix wasm glitches
2025-02-13 15:25:24 +01:00
Alejandro Alonso
64e6d0b1f8 🐛 Fix wasm glitches 2025-02-13 15:16:45 +01:00
Xavier Julian
26a2ef8fb7 ♻️ Create DS context notification component 2025-02-13 13:36:53 +01:00
Alejandro
a6c46ee55c Merge pull request #5819 from penpot/azazeln28-feat-masks
🎉 Feat masks
2025-02-13 13:26:21 +01:00
AzazelN28
f8d58cb74e 🎉 Feat masks 2025-02-13 12:54:18 +01:00
Andrey Antukh
3ea52a0198 Merge pull request #5784 from penpot/niwinz-tokens-changes-2
 Several performance oriented changes to tokens code (part 2)
2025-02-13 11:47:28 +01:00
Andrey Antukh
054efb3435 Merge pull request #5766 from penpot/niwinz-tokens-changes
 Several changes to tokens
2025-02-13 11:46:58 +01:00
Edgars Andersons
fbd5c404d2 🌐 Add translations for: Latvian
Currently translated at 98.1% (1616 of 1646 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/lv/
2025-02-13 11:02:06 +01:00
Nicola Bortoletto
32b65e8dbc 🌐 Add translations for: Italian
Currently translated at 99.6% (1641 of 1646 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/it/
2025-02-13 11:02:04 +01:00
Alejandro
773b4fe02e Merge pull request #5824 from penpot/alotor-propagate-modifiers
 Use skia matrix for internal data
2025-02-13 10:21:58 +01:00
Elena Torró
1a62e5e42d Merge pull request #5830 from penpot/elenatorro-10118-fix-action-button-size
🐛 Fix Action Buttons size and add example to Storybook
2025-02-12 17:30:43 +01:00
elenatorro
f812460158 🐛 Fix Action Buttons size and display, and add example to Storybook 2025-02-12 17:02:20 +01:00
Andrey Antukh
654c070976 Merge remote-tracking branch 'origin/staging' into develop 2025-02-12 14:37:20 +01:00
Florian Schrödl
e776ba1b33 Add margin to spacing token & context menu (#5807) 2025-02-12 14:27:26 +01:00
Andrey Antukh
7497371b32 🐛 Fix issue on renaming group 2025-02-12 10:47:39 +01:00
Andrey Antukh
50afc4c507 Remove selection workaround for undo
Always select the first one when no match is found
2025-02-12 10:47:39 +01:00
Andrey Antukh
064e51d24e 🐛 Clear token set edition state on rename 2025-02-12 10:47:38 +01:00
Andrey Antukh
a029ec18a6 🐛 Fix incorrect handling of selected token set 2025-02-12 10:47:36 +01:00
Andrey Antukh
b0a6e5c946 🐛 Fix regression: close context menu on edit token 2025-02-12 10:45:04 +01:00
Andrey Antukh
e8c85d13ff ♻️ Remove sets context abstraction 2025-02-12 10:45:02 +01:00
Andrey Antukh
b228438127 Refactor the rest fot token sets context menu components 2025-02-12 10:41:24 +01:00
Andrey Antukh
1fb48a1e8a Adapt call style convention for token sets context menu component 2025-02-12 10:41:24 +01:00
Andrey Antukh
91b6d498fe Add minor efficiency improvements to tokens import export 2025-02-12 10:41:24 +01:00
Andrey Antukh
efe204c346 Simplify access to can-edit? using react context 2025-02-12 10:41:24 +01:00
Andrey Antukh
4a4cd9492a ♻️ Refactor token set auto selection mechanism
This is a general purpose change that also allows perform
a best effort on selection sets when the name is changed
(per example by moving it into other group).
2025-02-12 10:41:23 +01:00
Andrey Antukh
5446464d7e 📎 Add fixme comment for confusing name 2025-02-12 10:40:36 +01:00
Andrey Antukh
baa5258a43 Declare transducer statically for path split function 2025-02-12 10:40:36 +01:00
Andrey Antukh
df6a679548 Remove duplicated operations from tokens sidebar 2025-02-12 10:40:36 +01:00
Andrey Antukh
3692f17e55 Adapt call style for set-lists component 2025-02-12 10:40:34 +01:00
Andrey Antukh
2bac94ad5c Use new call convention on all components of tokens sidebar 2025-02-12 10:24:48 +01:00
Andrey Antukh
d46d80bd5c Use value equals on selected shapes set 2025-02-12 10:24:48 +01:00
Andrey Antukh
f0e5196659 Add minor optimization to token-pill component 2025-02-12 10:24:48 +01:00
Andrey Antukh
05a459ea19 📎 Add missing license header 2025-02-12 10:24:48 +01:00
Andrey Antukh
8e85d5a02a Add performance oriented refactor to token sidebar and token-pill 2025-02-12 10:24:48 +01:00
Andrey Antukh
81036b9330 Improve handling open-status and tokens selection 2025-02-12 10:24:47 +01:00
Andrey Antukh
c91b7606a0 Add minor efficiency improvements using new call convention 2025-02-12 10:24:47 +01:00
Andrey Antukh
d6e7a331d5 ♻️ Move token-types to changes ns
And rename it to token-properties
2025-02-12 10:24:47 +01:00
Andrey Antukh
831b0baddd Improve efficiency of grouping and sorting token types 2025-02-12 10:24:47 +01:00
Andrey Antukh
e4bf2bd9ad 💄 Internal function rename on tokens sidebar 2025-02-12 10:24:47 +01:00
Andrey Antukh
7a4d8b824e 💄 Rename token-component* to token-group* 2025-02-12 10:24:47 +01:00
Andrey Antukh
ff34d1d5f9 Don't create an additional sequence on iterating for tokens 2025-02-12 10:24:47 +01:00
Andrey Antukh
c1ce24e5f0 Don't sort tokens on each rerender 2025-02-12 10:24:46 +01:00
Andrey Antukh
1f450c83ec Use new component definition convention for token-component 2025-02-12 10:24:46 +01:00
Andrey Antukh
769000da2d 💄 Add cosmetic changes to token-component component 2025-02-12 10:24:46 +01:00
Andrey Antukh
a53c37bc3c Don't create function references for token-pill callbacks 2025-02-12 10:24:46 +01:00
Andrey Antukh
333cc5996c 💄 Add mainly cosmetic changes to tokens pill
Simplify the component logic removing duplicate token prop handling
2025-02-12 10:24:46 +01:00
Andrey Antukh
bccc90f5a2 Don't create keys seq on each rerender on token-pill component 2025-02-12 10:24:45 +01:00
Andrey Antukh
5575a66b8d 📎 Add many FIXME comments on token-pill component 2025-02-12 10:24:45 +01:00
Andrey Antukh
0fee8143dd Don't use seq operations for string includes operation 2025-02-12 10:24:45 +01:00
Andrey Antukh
b6e26d15e1 💄 Add cosmetic changes to tokens sidebar component 2025-02-12 10:24:44 +01:00
Andrey Antukh
7e0b2702de 💄 Add minor cosmetic changes 2025-02-12 10:24:13 +01:00
Andrey Antukh
e46fb9dba7 📎 Add missing copyright header 2025-02-12 10:24:13 +01:00
Andrey Antukh
f4dee75a17 🔥 Remove unused workspace tokens common ns file 2025-02-12 10:24:13 +01:00
Andrey Antukh
6d1ff0cb49 🔥 Remove unused and incorrect ref passed to dropdown component 2025-02-12 10:24:12 +01:00
alonso.torres
3dcabc9502 Use skia matrix for internal data 2025-02-11 16:49:43 +01:00
Eva Marco
10174aa7bc 🐛 Fix uppercase text and copy (#5821) 2025-02-11 16:46:17 +01:00
Andrey Antukh
cd87cbe44e Merge remote-tracking branch 'origin/staging' into develop 2025-02-11 16:09:32 +01:00
Aitor Moreno
4594c7bf0a Merge pull request #5823 from penpot/superalex-render-wasm-cloning
🎉 Remove extra clonings from render wasm
2025-02-11 15:55:58 +01:00
Stas Haas
bf153eb96b 🌐 Add translations for: German
Currently translated at 99.6% (1641 of 1646 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/de/
2025-02-11 14:22:12 +01:00
Alejandro Alonso
d1a1dafcad 🎉 Remove unnecesary clone for cache image 2025-02-11 14:05:37 +01:00
Alejandro Alonso
246463a3ec 🎉 Remove shape cloning from render wasm 2025-02-11 14:05:37 +01:00
Alejandro
4b4541515c Merge pull request #5809 from penpot/perf-transform-wasm
 Add support for WASM transforms
2025-02-11 12:52:55 +01:00
alonso.torres
1bb337c3dd Add support for WASM transforms 2025-02-11 12:36:44 +01:00
Florian Schrödl
8b380a01e6 ♻️ Simplifies RPC pattern for tokens (#5765)
* ♻️ Refactor to RPC pattern

Co-authored-by: andrei <andrei@hyma.io>

* ♻️ Remove unused alias

* ♻️ Change function signature

---------

Co-authored-by: andrei <andrei@hyma.io>
Co-authored-by: Andrey Fedorov <oran9e.red@gmail.com>
2025-02-11 12:32:28 +01:00
Xaviju
5c32ec8cfa ♻️ Create shared notification utility component 2025-02-11 11:42:06 +01:00
Eva Marco
9660307f00 🐛 Fix opacity valid values (#5820) 2025-02-11 11:28:25 +01:00
Andrey Antukh
a3a757f842 Merge remote-tracking branch 'origin/staging' into develop 2025-02-11 11:25:40 +01:00
Eva Marco
a2727a110e Add resize in percentage option (#5816) 2025-02-11 11:25:11 +01:00
Juanfran
dd1aba0d05 Merge pull request #5812 from penpot/juanfran-create-edit-token-modal-enter-key
 Add missing enter key for button activation in edit/create tokens modal
2025-02-10 16:10:25 +01:00
Eva Marco
6692f8dce2 Add validation to token opacity (#5802) 2025-02-10 15:04:22 +01:00
Juanfran
372b3145ea Add missing Enter key for button activation in edit/create tokens modal 2025-02-10 15:02:46 +01:00
Alejandro
8b7a102927 Merge pull request #5804 from penpot/superalex-fix-wasm-frame-clipping
🐛 Fix wasm frame clipping
2025-02-10 14:05:46 +01:00
Juanfran
24e1cf0d7d Merge pull request #5811 from penpot/juanfran-spacing-token-sets
💄 Improve spacing in design token sets
2025-02-10 13:57:02 +01:00
Alejandro Alonso
2ce88283a2 🐛 Fix wasm render frame clipping 2025-02-10 13:54:27 +01:00
Juanfran
2ae2e23b57 💄 Improve spacing in design token sets 2025-02-10 13:37:24 +01:00
Pablo Alba
9c7bb96b1c Add new DS component: InputWithValues (#5777)
*  Add new DS component: InputWithValues

*  Fix MR

*  Fix MR 2
2025-02-10 13:17:30 +01:00
Andrey Antukh
0f49208040 Merge branch 'staging' into develop 2025-02-10 12:01:15 +01:00
Alejandro
8f11a925df 🎉 Non blocking render wasm (#5726) 2025-02-10 11:46:56 +01:00
Andrey Antukh
f65f7d68e6 Merge remote-tracking branch 'origin/staging' into develop 2025-02-10 10:57:04 +01:00
TheScientistPT
f16fcf25e2 🌐 Add translations for: Portuguese (Portugal)
Currently translated at 93.9% (1546 of 1646 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/pt_PT/
2025-02-09 21:02:46 +01:00
Linerly
0048f9725d 🌐 Add translations for: Indonesian
Currently translated at 100.0% (1646 of 1646 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/id/
2025-02-07 15:01:51 +01:00
Robson Cardoso dos Santos
4bb5592e75 🌐 Add translations for: Portuguese (Brazil)
Currently translated at 72.7% (1198 of 1646 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/pt_BR/
2025-02-07 15:01:51 +01:00
Juanfran
f5b18f953d Enable Enter key for button activation in tokens modal (#5792) 2025-02-07 14:26:09 +01:00
Eva Marco
73ff1b4fe5 🐛 Fix menu shadow color (#5793) 2025-02-06 15:56:45 +01:00
Renan Mayrinck
d7fbd3c3bc 🌐 Add translations for: Portuguese (Brazil)
Currently translated at 72.7% (1198 of 1646 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/pt_BR/
2025-02-06 14:41:03 +01:00
Robson Cardoso dos Santos
0b62bee90d 🌐 Add translations for: Portuguese (Brazil)
Currently translated at 72.7% (1198 of 1646 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/pt_BR/
2025-02-06 14:41:03 +01:00
Florian Schrödl
0c275cf490 🐛 Fix token set selection & rename (#5783)
* 🐛 Fix set selection

* 🐛 Fix set name not being updated

* ♻️ Add better list assertion & test set renaming
2025-02-06 14:16:03 +01:00
Andrey Antukh
8b466ef0a3 Merge remote-tracking branch 'origin/staging' into develop 2025-02-06 12:57:33 +01:00
Edgars Andersons
a4a88769af 🌐 Add translations for: Latvian
Currently translated at 97.5% (1605 of 1646 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/lv/
2025-02-06 12:02:04 +01:00
Denys Kisil
2dce8d09b8 🌐 Add translations for: Ukrainian (ukr_UA)
Currently translated at 99.6% (1641 of 1646 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/ukr_UA/
2025-02-06 12:02:03 +01:00
TheScientistPT
e6e6401702 🌐 Add translations for: Portuguese (Portugal)
Currently translated at 93.6% (1542 of 1646 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/pt_PT/
2025-02-06 12:02:01 +01:00
Robson Cardoso dos Santos
e83ece392c 🌐 Add translations for: Portuguese (Brazil)
Currently translated at 70.7% (1164 of 1646 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/pt_BR/
2025-02-06 12:02:00 +01:00
Andrey Antukh
33887711f7 Merge remote-tracking branch 'origin/staging' into develop 2025-02-06 09:38:47 +01:00
Juanfran
947bd547aa 💄 Improve alignment of design token sets (#5782) 2025-02-06 08:58:02 +01:00
Florian Schrödl
86e0f8ad34 🐛 Fix toggling set groups in theme modal not working (#5733) 2025-02-05 12:21:21 +01:00
Late Night Defender
bb161f9da8 🌐 Add translations for: Thai
Currently translated at 12.5% (206 of 1646 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/th/
2025-02-04 22:02:01 +01:00
Denys Kisil
07360efd17 🌐 Add translations for: Ukrainian (ukr_UA)
Currently translated at 99.6% (1641 of 1646 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/ukr_UA/
2025-02-04 22:01:59 +01:00
TheScientistPT
7c8eaaa4f9 🌐 Add translations for: Portuguese (Portugal)
Currently translated at 93.3% (1537 of 1646 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/pt_PT/
2025-02-04 22:01:58 +01:00
Andrey Antukh
48acc8715b Merge remote-tracking branch 'origin/staging' into develop 2025-02-04 16:01:14 +01:00
Andrei Fëdorov
9db76f9a15 🎉 Import legacy format tokens (#5695) 2025-02-04 12:50:39 +01:00
Andrey Antukh
df0909483e Merge remote-tracking branch 'origin/staging' into develop 2025-02-04 11:35:03 +01:00
Florian Schrödl
ec8109644b Create sets inside folders 2025-02-04 10:59:28 +01:00
Andrey Antukh
315b389a66 🐛 Fix name generation and handling on creating objects (files, tokens, ...) (#5745)
*  Update function implementation

*  Add tests for a new function implementation

*  Update function usages according to new signature

*  Update docstrings

*  Use simpler assertion

* 💄 Replace concat with cons on name-seq

* 🐛 Fix incorrect error handling on legacy workspace redirect

---------

Co-authored-by: Andrey Fedorov <oran9e.red@gmail.com>
2025-02-03 12:49:56 +01:00
Andrey Antukh
bce30eb522 Merge pull request #5738 from penpot/niwinz-merge-two-prs
 Apply token value changes to all shapes in all pages
2025-02-03 12:31:07 +01:00
Andrey Antukh
d05d1c6a48 📎 Update changelog (add entry for 2.6.0) 2025-02-03 11:03:35 +01:00
Andrés Moya
1803e32322 🐛 Regenerate text shapes after changing token values 2025-02-03 10:16:31 +01:00
Denys Kisil
01e04843bf 🌐 Add translations for: Ukrainian (ukr_UA)
Currently translated at 99.6% (1641 of 1646 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/ukr_UA/
2025-02-02 14:01:52 +01:00
Linerly
3907f39c29 🌐 Add translations for: Indonesian
Currently translated at 98.9% (1628 of 1646 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/id/
2025-02-01 02:01:53 +01:00
Eva Marco
24281b512e 🐛 Fix thumbnail regeration when changing sets of tokens 2025-01-31 16:35:30 +01:00
Andrés Moya
f4f0478975 Apply token value changes to shapes in all pages 2025-01-31 16:35:30 +01:00
Stephan Paternotte
c570c0929f 🌐 Add translations for: Dutch
Currently translated at 99.6% (1641 of 1646 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/nl/
2025-01-31 00:57:21 +01:00
Denys Kisil
f53473f9e9 🌐 Add translations for: Ukrainian (ukr_UA)
Currently translated at 99.6% (1641 of 1646 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/ukr_UA/
2025-01-31 00:57:20 +01:00
Nicola Bortoletto
39e6d28826 🌐 Add translations for: Italian
Currently translated at 99.6% (1641 of 1646 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/it/
2025-01-31 00:57:18 +01:00
Yaron Shahrabani
0b56d07a67 🌐 Add translations for: Hebrew
Currently translated at 99.6% (1641 of 1646 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/he/
2025-01-31 00:57:17 +01:00
1910 changed files with 320125 additions and 155024 deletions

View File

@@ -1,5 +1,53 @@
version: 2.1
jobs:
lint:
docker:
- image: penpotapp/devenv:latest
working_directory: ~/repo
resource_class: medium+
steps:
- checkout
- run:
name: "fmt check"
working_directory: "."
command: |
yarn install
yarn run fmt:clj:check
- run:
name: "lint clj common"
working_directory: "."
command: |
yarn run lint:clj:common
- run:
name: "lint clj frontend"
working_directory: "."
command: |
yarn run lint:clj:frontend
- run:
name: "lint clj backend"
working_directory: "."
command: |
yarn run lint:clj:backend
- run:
name: "lint clj exporter"
working_directory: "."
command: |
yarn run lint:clj:exporter
- run:
name: "lint clj library"
working_directory: "."
command: |
yarn run lint:clj:library
test-common:
docker:
- image: penpotapp/devenv:latest
@@ -17,15 +65,7 @@ jobs:
# Download and cache dependencies
- restore_cache:
keys:
- v1-dependencies-{{ checksum "common/deps.edn"}}
- run:
name: "fmt check & linter"
working_directory: "./common"
command: |
yarn install
yarn run fmt:clj:check
yarn run lint:clj
- v1-dependencies-{{ checksum "common/deps.edn"}}-{{ checksum "common/yarn.lock" }}
- run:
name: "JVM tests"
@@ -37,12 +77,16 @@ jobs:
name: "NODE tests"
working_directory: "./common"
command: |
yarn install
yarn run test
- save_cache:
paths:
- ~/.m2
key: v1-dependencies-{{ checksum "common/deps.edn"}}
- ~/.yarn
- ~/.gitlibs
- ~/.cache/ms-playwright
key: v1-dependencies-{{ checksum "common/deps.edn"}}-{{ checksum "common/yarn.lock" }}
test-frontend:
docker:
@@ -61,36 +105,68 @@ jobs:
# Download and cache dependencies
- restore_cache:
keys:
- v1-dependencies-{{ checksum "frontend/deps.edn"}}
- v1-dependencies-{{ checksum "frontend/deps.edn"}}-{{ checksum "frontend/yarn.lock" }}
- run:
name: "prepopulate linter cache"
working_directory: "./common"
name: "install dependencies"
working_directory: "./frontend"
# We install playwright here because the dependent tasks
# uses the same cache as this task so we prepopulate it
command: |
yarn install
yarn run lint:clj
yarn run playwright install chromium --with-deps
- run:
name: "fmt check & linter"
name: "lint scss on frontend"
working_directory: "./frontend"
command: |
yarn install
yarn run fmt:clj:check
yarn run fmt:js:check
yarn run lint:scss
yarn run lint:clj
- run:
name: "unit tests"
working_directory: "./frontend"
command: |
yarn install
yarn run test
- save_cache:
paths:
- ~/.m2
key: v1-dependencies-{{ checksum "frontend/deps.edn"}}
- ~/.yarn
- ~/.gitlibs
- ~/.cache/ms-playwright
key: v1-dependencies-{{ checksum "frontend/deps.edn"}}-{{ checksum "frontend/yarn.lock" }}
test-library:
docker:
- image: penpotapp/devenv:latest
working_directory: ~/repo
resource_class: medium+
environment:
JAVA_OPTS: -Xmx6g
NODE_OPTIONS: --max-old-space-size=4096
steps:
- checkout
# Download and cache dependencies
- restore_cache:
keys:
- v1-dependencies-{{ checksum "frontend/deps.edn"}}-{{ checksum "frontend/yarn.lock" }}
- run:
name: Install dependencies and build
working_directory: "./library"
command: |
yarn install
- run:
name: Build and Test
working_directory: "./library"
command: |
./scripts/build
yarn run test
test-components:
docker:
@@ -109,14 +185,14 @@ jobs:
# Download and cache dependencies
- restore_cache:
keys:
- v1-dependencies-{{ checksum "frontend/deps.edn"}}
- v1-dependencies-{{ checksum "frontend/deps.edn"}}-{{ checksum "frontend/yarn.lock" }}
- run:
name: Install dependencies
working_directory: "./frontend"
command: |
yarn
npx playwright install --with-deps
yarn install
yarn run playwright install chromium
- run:
name: Build Storybook
@@ -131,36 +207,6 @@ jobs:
"npx http-server storybook-static --port 6006 --silent" \
"npx wait-on tcp:6006 && yarn test:storybook"
test-integration:
docker:
- image: penpotapp/devenv:latest
working_directory: ~/repo
resource_class: large
environment:
JAVA_OPTS: -Xmx6g -Xms2g
NODE_OPTIONS: --max-old-space-size=4096
steps:
- checkout
# Download and cache dependencies
- restore_cache:
keys:
- v1-dependencies-{{ checksum "frontend/deps.edn"}}
- run:
name: "integration tests"
working_directory: "./frontend"
command: |
yarn install
yarn run build:app:assets
yarn run build:app
yarn run build:app:libs
yarn run playwright install --with-deps chromium
yarn run test:e2e -x --workers=4
test-backend:
docker:
- image: penpotapp/devenv:latest
@@ -185,21 +231,6 @@ jobs:
keys:
- v1-dependencies-{{ checksum "backend/deps.edn" }}
- run:
name: "prepopulate linter cache"
working_directory: "./common"
command: |
yarn install
yarn run lint:clj
- run:
name: "fmt check & linter"
working_directory: "./backend"
command: |
yarn install
yarn run fmt:clj:check
yarn run lint:clj
- run:
name: "tests"
working_directory: "./backend"
@@ -215,37 +246,9 @@ jobs:
- save_cache:
paths:
- ~/.m2
- ~/.gitlibs
key: v1-dependencies-{{ checksum "backend/deps.edn" }}
test-exporter:
docker:
- image: penpotapp/devenv:latest
working_directory: ~/repo
resource_class: medium+
environment:
JAVA_OPTS: -Xmx4g -Xms100m -XX:+UseSerialGC
NODE_OPTIONS: --max-old-space-size=4096
steps:
- checkout
- run:
name: "prepopulate linter cache"
working_directory: "./common"
command: |
yarn install
yarn run lint:clj
- run:
name: "fmt check & linter"
working_directory: "./exporter"
command: |
yarn install
yarn run fmt:clj:check
yarn run lint:clj
test-render-wasm:
docker:
- image: penpotapp/devenv:latest
@@ -263,6 +266,12 @@ jobs:
command: |
cargo fmt --check
- run:
name: "lint"
working_directory: "./render-wasm"
command: |
./lint
- run:
name: "cargo tests"
working_directory: "./render-wasm"
@@ -272,10 +281,25 @@ jobs:
workflows:
penpot:
jobs:
- test-frontend
- test-components
- test-integration
- test-backend
- test-common
- test-exporter
- test-frontend:
requires:
- lint: success
- test-library:
requires:
- lint: success
- test-components:
requires:
- lint: success
- test-backend:
requires:
- lint: success
- test-common:
requires:
- lint: success
- lint
- test-render-wasm

View File

@@ -45,10 +45,16 @@
:potok/reify-type
{:level :error}
:missing-protocol-method
{:level :off}
:unresolved-namespace
{:level :warning
:exclude [data_readers]}
:unused-value
{:level :off}
:single-key-in
{:level :warning}
@@ -64,6 +70,9 @@
:redundant-nested-call
{:level :off}
:redundant-str-call
{:level :off}
:earmuffed-var-not-dynamic
{:level :off}

View File

@@ -1,29 +1,20 @@
<!--
### Related Ticket
Some key notes before you open a PR:
<!-- Reference the related GitHub/Taiga ticket. -->
1. Select which branch should this PR be merged in? By default, you should always merge to the develop branch.
2. PR name follows [convention](http://karma-runner.github.io/4.0/dev/git-commit-msg.html)
3. All tests pass locally, UI and Unit tests
4. All business logic and validations must be on the server-side
5. Update necessary Documentation
6. Put `closes #XXXX` in your comment to auto-close the issue that your PR fixes
### Summary
### Steps to reproduce
Also, if you're new here
### Checklist
- Contribution Guide => https://github.com/uxbox/uxbox/blob/develop/CONTRIBUTING.md
- [ ] Choose the correct target branch; use `develop` by default.
- [ ] Provide a brief summary of the changes introduced.
- [ ] Add a detailed explanation of how to reproduce the issue and/or verify the fix, if applicable.
- [ ] Include screenshots or videos, if applicable.
- [ ] Add or modify existing integration tests in case of bugs or new features, if applicable.
- [ ] Refactor any modified SCSS files following the refactor guide.
- [ ] Check CI passes successfully.
- [ ] Update the `CHANGES.md` file, referencing the related GitHub issue, if applicable.
-->
> Please provide enough information so that others can review your pull request:
<!-- You can skip this if you're fixing a typo or updating existing documentation -->
> Explain the **details** for making this change. What existing problem does the pull request solve?
<!-- Example: When "Adding a function to do X", explain why it is necessary to have a way to do X. -->
> Screenshots/GIFs
<!-- Add images/recordings to better visualize the change: expected/current behviour -->
<!-- For more details, check the contribution guidelines: https://github.com/penpot/penpot/blob/develop/CONTRIBUTING.md -->

93
.github/workflows/build-bundle.yml vendored Normal file
View File

@@ -0,0 +1,93 @@
name: Bundles Builder
on:
# Create bundle from manual action
workflow_dispatch:
inputs:
gh_ref:
description: 'Name of the branch or ref'
type: string
required: true
default: 'develop'
build_wasm:
description: 'BUILD_WASM. Valid values: yes, no'
type: string
required: false
default: 'yes'
build_storybook:
description: 'BUILD_STORYBOOK. Valid values: yes, no'
type: string
required: false
default: 'yes'
workflow_call:
inputs:
gh_ref:
description: 'Name of the branch or ref'
type: string
required: true
default: 'develop'
build_wasm:
description: 'BUILD_WASM. Valid values: yes, no'
type: string
required: false
default: 'yes'
build_storybook:
description: 'BUILD_STORYBOOK. Valid values: yes, no'
type: string
required: false
default: 'yes'
jobs:
build-bundle:
name: Build and Upload Penpot Bundle
runs-on: ubuntu-24.04
env:
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
AWS_DEFAULT_REGION: ${{ secrets.AWS_REGION }}
steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
fetch-depth: 0
ref: ${{ inputs.gh_ref }}
- name: Extract some useful variables
id: vars
run: |
echo "gh_ref=${{ inputs.gh_ref || github.ref_name }}" >> $GITHUB_OUTPUT
echo "bundle_version=$(git describe --tags --always)" >> $GITHUB_OUTPUT
- name: Build bundle
env:
BUILD_WASM: ${{ inputs.build_wasm }}
BUILD_STORYBOOK: ${{ inputs.build_storybook }}
run: ./manage.sh build-bundle
- name: Prepare directories for zipping
run: |
mkdir zips
mv bundles penpot
- name: Create zip bundle
run: |
echo "📦 Packaging Penpot bundle..."
zip -r zips/penpot.zip penpot
- name: Upload Penpot bundle to S3
run: |
aws s3 cp zips/penpot.zip s3://${{ secrets.S3_BUCKET }}/penpot-${{ steps.vars.outputs.gh_ref }}.zip --metadata bundle-version=${{ steps.vars.outputs.bundle_version }}
- name: Notify Mattermost
if: failure()
uses: mattermost/action-mattermost-notify@master
with:
MATTERMOST_WEBHOOK_URL: ${{ secrets.MATTERMOST_WEBHOOK }}
MATTERMOST_CHANNEL: bot-alerts-cicd
TEXT: |
❌ 📦 *[PENPOT] Error building penpot bundles.*
📄 Triggered from ref: `${{ steps.vars.outputs.gh_ref }}`
Bundle version: `${{ steps.vars.outputs.bundle_version }}`
🔗 Run: https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}
@infra

21
.github/workflows/build-develop.yml vendored Normal file
View File

@@ -0,0 +1,21 @@
name: _DEVELOP
on:
schedule:
- cron: '16 5-20 * * 1-5'
jobs:
build-bundle:
uses: ./.github/workflows/build-bundle.yml
secrets: inherit
with:
gh_ref: "develop"
build_wasm: "yes"
build_storybook: "yes"
build-docker:
needs: build-bundle
uses: ./.github/workflows/build-docker.yml
secrets: inherit
with:
gh_ref: "develop"

View File

@@ -0,0 +1,36 @@
name: DevEnv Docker Image Builder
on:
workflow_dispatch:
jobs:
build-and-push:
name: Build and push DevEnv Docker image
environment: release-admins
runs-on: ubuntu-24.04
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Login to Docker Registry
uses: docker/login-action@v3
with:
username: ${{ secrets.PUB_DOCKER_USERNAME }}
password: ${{ secrets.PUB_DOCKER_PASSWORD }}
- name: Build and push DevEnv Docker image
uses: docker/build-push-action@v6
env:
DOCKER_IMAGE: 'penpotapp/devenv'
with:
context: ./docker/devenv/
file: ./docker/devenv/Dockerfile
platforms: linux/amd64,linux/arm64
push: true
tags: ${{ env.DOCKER_IMAGE }}:latest
cache-from: type=registry,ref=${{ env.DOCKER_IMAGE }}:buildcache
cache-to: type=registry,ref=${{ env.DOCKER_IMAGE }}:buildcache,mode=max

152
.github/workflows/build-docker.yml vendored Normal file
View File

@@ -0,0 +1,152 @@
name: Docker Images Builder
on:
workflow_dispatch:
inputs:
gh_ref:
description: 'Name of the branch or ref'
type: string
required: true
default: 'develop'
workflow_call:
inputs:
gh_ref:
description: 'Name of the branch or ref'
type: string
required: true
default: 'develop'
jobs:
build-and-push:
name: Build and Push Penpot Docker Images
runs-on: ubuntu-24.04-arm
steps:
- name: Checkout code
uses: actions/checkout@v4
with:
fetch-depth: 0
ref: ${{ inputs.gh_ref }}
- name: Extract some useful variables
id: vars
run: |
echo "gh_ref=${{ inputs.gh_ref || github.ref_name }}" >> $GITHUB_OUTPUT
- name: Download Penpot Bundles
id: bundles
env:
FILE_NAME: penpot-${{ steps.vars.outputs.gh_ref }}.zip
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
AWS_DEFAULT_REGION: ${{ secrets.AWS_REGION }}
run: |
tmp=$(aws s3api head-object \
--bucket ${{ secrets.S3_BUCKET }} \
--key "$FILE_NAME" \
--query 'Metadata."bundle-version"' \
--output text)
echo "bundle_version=$tmp" >> $GITHUB_OUTPUT
pushd docker/images
aws s3 cp s3://${{ secrets.S3_BUCKET }}/$FILE_NAME .
unzip $FILE_NAME > /dev/null
mv penpot/backend bundle-backend
mv penpot/frontend bundle-frontend
mv penpot/exporter bundle-exporter
mv penpot/storybook bundle-storybook
popd
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Login to Docker Registry
uses: docker/login-action@v3
with:
registry: ${{ secrets.DOCKER_REGISTRY }}
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}
- name: Extract metadata (tags, labels)
id: meta
uses: docker/metadata-action@v5
with:
images:
frontend
backend
exporter
storybook
labels: |
bundle_version=${{ steps.bundles.outputs.bundle_version }}
- name: Build and push Backend Docker image
uses: docker/build-push-action@v6
env:
DOCKER_IMAGE: 'backend'
BUNDLE_PATH: './bundle-backend'
with:
context: ./docker/images/
file: ./docker/images/Dockerfile.backend
platforms: linux/amd64,linux/arm64
push: true
tags: ${{ secrets.DOCKER_REGISTRY }}/${{ env.DOCKER_IMAGE }}:${{ steps.vars.outputs.gh_ref }}
labels: ${{ steps.meta.outputs.labels }}
cache-from: type=registry,ref=${{ secrets.DOCKER_REGISTRY }}/${{ env.DOCKER_IMAGE }}:buildcache
cache-to: type=registry,ref=${{ secrets.DOCKER_REGISTRY }}/${{ env.DOCKER_IMAGE }}:buildcache,mode=max
- name: Build and push Frontend Docker image
uses: docker/build-push-action@v6
env:
DOCKER_IMAGE: 'frontend'
BUNDLE_PATH: './bundle-frontend'
with:
context: ./docker/images/
file: ./docker/images/Dockerfile.frontend
platforms: linux/amd64,linux/arm64
push: true
tags: ${{ secrets.DOCKER_REGISTRY }}/${{ env.DOCKER_IMAGE }}:${{ steps.vars.outputs.gh_ref }}
labels: ${{ steps.meta.outputs.labels }}
cache-from: type=registry,ref=${{ secrets.DOCKER_REGISTRY }}/${{ env.DOCKER_IMAGE }}:buildcache
cache-to: type=registry,ref=${{ secrets.DOCKER_REGISTRY }}/${{ env.DOCKER_IMAGE }}:buildcache,mode=max
- name: Build and push Exporter Docker image
uses: docker/build-push-action@v6
env:
DOCKER_IMAGE: 'exporter'
BUNDLE_PATH: './bundle-exporter'
with:
context: ./docker/images/
file: ./docker/images/Dockerfile.exporter
platforms: linux/amd64,linux/arm64
push: true
tags: ${{ secrets.DOCKER_REGISTRY }}/${{ env.DOCKER_IMAGE }}:${{ steps.vars.outputs.gh_ref }}
labels: ${{ steps.meta.outputs.labels }}
cache-from: type=registry,ref=${{ secrets.DOCKER_REGISTRY }}/${{ env.DOCKER_IMAGE }}:buildcache
cache-to: type=registry,ref=${{ secrets.DOCKER_REGISTRY }}/${{ env.DOCKER_IMAGE }}:buildcache,mode=max
- name: Build and push Storybook Docker image
uses: docker/build-push-action@v6
env:
DOCKER_IMAGE: 'storybook'
BUNDLE_PATH: './bundle-storybook'
with:
context: ./docker/images/
file: ./docker/images/Dockerfile.storybook
platforms: linux/amd64,linux/arm64
push: true
tags: ${{ secrets.DOCKER_REGISTRY }}/${{ env.DOCKER_IMAGE }}:${{ steps.vars.outputs.gh_ref }}
labels: ${{ steps.meta.outputs.labels }}
cache-from: type=registry,ref=${{ secrets.DOCKER_REGISTRY }}/${{ env.DOCKER_IMAGE }}:buildcache
cache-to: type=registry,ref=${{ secrets.DOCKER_REGISTRY }}/${{ env.DOCKER_IMAGE }}:buildcache,mode=max
- name: Notify Mattermost
if: failure()
uses: mattermost/action-mattermost-notify@master
with:
MATTERMOST_WEBHOOK_URL: ${{ secrets.MATTERMOST_WEBHOOK }}
MATTERMOST_CHANNEL: bot-alerts-cicd
TEXT: |
❌ 🐳 *[PENPOT] Error building penpot docker images.*
📄 Triggered from ref: `${{ steps.vars.outputs.gh_ref }}`
📦 Bundle: `${{ steps.bundles.outputs.bundle_version }}`
🔗 Run: https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}
@infra

21
.github/workflows/build-staging.yml vendored Normal file
View File

@@ -0,0 +1,21 @@
name: _STAGING
on:
schedule:
- cron: '36 5-20 * * 1-5'
jobs:
build-bundle:
uses: ./.github/workflows/build-bundle.yml
secrets: inherit
with:
gh_ref: "staging"
build_wasm: "yes"
build_storybook: "yes"
build-docker:
needs: build-bundle
uses: ./.github/workflows/build-docker.yml
secrets: inherit
with:
gh_ref: "staging"

46
.github/workflows/build-tag.yml vendored Normal file
View File

@@ -0,0 +1,46 @@
name: _TAG
on:
push:
tags:
- '*'
jobs:
build-bundle:
uses: ./.github/workflows/build-bundle.yml
secrets: inherit
with:
gh_ref: ${{ github.ref_name }}
build_wasm: "yes"
build_storybook: "yes"
build-docker:
needs: build-bundle
uses: ./.github/workflows/build-docker.yml
secrets: inherit
with:
gh_ref: ${{ github.ref_name }}
notify:
name: Notifications
runs-on: ubuntu-24.04
needs: build-docker
steps:
- name: Notify Mattermost
uses: mattermost/action-mattermost-notify@master
with:
MATTERMOST_WEBHOOK_URL: ${{ secrets.MATTERMOST_WEBHOOK }}
MATTERMOST_CHANNEL: bot-alerts-cicd
TEXT: |
🐳 *[PENPOT] Docker image available.*
🔗 Run: https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}
@infra
publish-final-tag:
if: ${{ !contains(github.ref_name, '-RC') && !contains(github.ref_name, '-alpha') && !contains(github.ref_name, '-beta') && contains(github.ref_name, '.') }}
needs: build-docker
uses: ./.github/workflows/release.yml
secrets: inherit
with:
gh_ref: ${{ github.ref_name }}

View File

@@ -26,7 +26,7 @@ jobs:
- name: Check Commit Type
uses: gsactions/commit-message-checker@v2
with:
pattern: '^:(lipstick|globe_with_meridians|wrench|books|arrow_up|arrow_down|zap|ambulance|construction|boom|fire|whale|bug|sparkles|paperclip|tada|recycle):\s[A-Z].*[^.]$'
pattern: '^(((:(lipstick|globe_with_meridians|wrench|books|arrow_up|arrow_down|zap|ambulance|construction|boom|fire|whale|bug|sparkles|paperclip|tada|recycle|rewind|construction_worker):)\s[A-Z].*[^.])|(Merge|Revert).+[^.])$'
flags: 'gm'
error: 'Commit should match CONTRIBUTING.md guideline'
checkAllCommitMessages: 'true' # optional: this checks all commits associated with a pull request

114
.github/workflows/release.yml vendored Normal file
View File

@@ -0,0 +1,114 @@
name: Release Publisher
on:
workflow_dispatch:
inputs:
gh_ref:
description: 'Tag to release'
type: string
required: true
workflow_call:
inputs:
gh_ref:
description: 'Tag to release'
type: string
required: true
permissions:
contents: write
jobs:
release:
environment: release-admins
runs-on: ubuntu-24.04
outputs:
version: ${{ steps.vars.outputs.gh_ref }}
release_notes: ${{ steps.extract_release_notes.outputs.release_notes }}
steps:
- name: Extract some useful variables
id: vars
run: |
echo "gh_ref=${{ inputs.gh_ref || github.ref_name }}" >> $GITHUB_OUTPUT
- name: Checkout code
uses: actions/checkout@v4
with:
fetch-depth: 0
ref: ${{ steps.vars.outputs.gh_ref }}
# --- Publicly release the docker images ---
- name: Configure ECR credentials
uses: aws-actions/configure-aws-credentials@v4
with:
aws-access-key-id: ${{ secrets.DOCKER_USERNAME }}
aws-secret-access-key: ${{ secrets.DOCKER_PASSWORD }}
aws-region: ${{ secrets.AWS_REGION }}
- name: Install Skopeo
run: |
sudo apt-get update -y
sudo apt-get install -y skopeo
- name: Copy images from AWS ECR to Docker Hub
env:
AWS_REGION: ${{ secrets.AWS_REGION }}
DOCKER_REGISTRY: ${{ secrets.DOCKER_REGISTRY }}
PUB_DOCKER_USERNAME: ${{ secrets.PUB_DOCKER_USERNAME }}
PUB_DOCKER_PASSWORD: ${{ secrets.PUB_DOCKER_PASSWORD }}
TAG: ${{ steps.vars.outputs.gh_ref }}
run: |
aws ecr get-login-password --region $AWS_REGION | \
skopeo login --username AWS --password-stdin \
$DOCKER_REGISTRY
echo "$PUB_DOCKER_PASSWORD" | skopeo login --username "$PUB_DOCKER_USERNAME" --password-stdin docker.io
IMAGES=("frontend" "backend" "exporter" "storybook")
for image in "${IMAGES[@]}"; do
skopeo copy --all \
docker://$DOCKER_REGISTRY/$image:$TAG \
docker://docker.io/penpotapp/$image:$TAG
for alias in main latest; do
skopeo copy --all \
docker://$DOCKER_REGISTRY/$image:$TAG \
docker://docker.io/penpotapp/$image:$alias
done
done
# --- Release notes extraction ---
- name: Extract release notes from CHANGES.md
id: extract_release_notes
env:
TAG: ${{ steps.vars.outputs.gh_ref }}
run: |
RELEASE_NOTES=$(awk "/^## $TAG$/{flag=1; next} /^## /{flag=0} flag" CHANGES.md | awk '{$1=$1};1')
if [ -z "$RELEASE_NOTES" ]; then
RELEASE_NOTES="No changes for $TAG according to CHANGES.md"
fi
echo "release_notes<<EOF" >> $GITHUB_OUTPUT
echo "$RELEASE_NOTES" >> $GITHUB_OUTPUT
echo "EOF" >> $GITHUB_OUTPUT
# --- Create GitHub release ---
- name: Create GitHub release
uses: softprops/action-gh-release@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
tag_name: ${{ steps.vars.outputs.gh_ref }}
name: ${{ steps.vars.outputs.gh_ref }}
body: ${{ steps.extract_release_notes.outputs.release_notes }}
- name: Notify Mattermost
if: failure()
uses: mattermost/action-mattermost-notify@master
with:
MATTERMOST_WEBHOOK_URL: ${{ secrets.MATTERMOST_WEBHOOK }}
MATTERMOST_CHANNEL: bot-alerts-cicd
TEXT: |
❌ 🚀 *[PENPOT] Error releasing penpot.*
📄 Triggered from ref: `${{ steps.vars.outputs.gh_ref }}`
🔗 Run: https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}
@infra

298
.github/workflows/tests.yml vendored Normal file
View File

@@ -0,0 +1,298 @@
name: "CI"
defaults:
run:
shell: bash
on:
pull_request:
types:
- opened
- synchronize
push:
branches:
- develop
- staging
concurrency:
group: ${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: true
jobs:
lint:
name: "Linter"
runs-on: ubuntu-24.04
container: penpotapp/devenv:latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Check clojure code format
run: |
./scripts/lint
test-common:
name: "Common Tests"
runs-on: ubuntu-24.04
container: penpotapp/devenv:latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Run tests on JVM
working-directory: ./common
run: |
clojure -M:dev:test
- name: Run tests on NODE
working-directory: ./common
run: |
./scripts/test
test-frontend:
name: "Frontend Tests"
runs-on: ubuntu-24.04
container: penpotapp/devenv:latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Unit Tests
working-directory: ./frontend
run: |
./scripts/test
- name: Component Tests
working-directory: ./frontend
run: |
./scripts/test-components
test-render-wasm:
name: "Render WASM Tests"
runs-on: ubuntu-24.04
container: penpotapp/devenv:latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Format
working-directory: ./render-wasm
run: |
cargo fmt --check
- name: Lint
working-directory: ./render-wasm
run: |
./lint
- name: Test
working-directory: ./render-wasm
run: |
./test
test-backend:
name: "Backend Tests"
runs-on: ubuntu-24.04
container: penpotapp/devenv:latest
services:
postgres:
image: postgres:17
# Provide the password for postgres
env:
POSTGRES_USER: penpot_test
POSTGRES_PASSWORD: penpot_test
POSTGRES_DB: penpot_test
# Set health checks to wait until postgres has started
options: >-
--health-cmd pg_isready
--health-interval 10s
--health-timeout 5s
--health-retries 5
redis:
image: valkey/valkey:9
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Run tests
working-directory: ./backend
env:
PENPOT_TEST_DATABASE_URI: "postgresql://postgres/penpot_test"
PENPOT_TEST_DATABASE_USERNAME: penpot_test
PENPOT_TEST_DATABASE_PASSWORD: penpot_test
PENPOT_TEST_REDIS_URI: "redis://redis/1"
run: |
clojure -M:dev:test --reporter kaocha.report/documentation
test-library:
name: "Library Tests"
runs-on: ubuntu-24.04
container: penpotapp/devenv:latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Run tests
working-directory: ./library
run: |
./scripts/test
build-integration:
name: "Build Integration Bundle"
runs-on: ubuntu-24.04
container: penpotapp/devenv:latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Build Bundle
working-directory: ./frontend
run: |
corepack enable;
corepack install;
yarn install
yarn run build:app:assets
yarn run build:app
yarn run build:app:libs
- name: Build WASM
working-directory: "./render-wasm"
run: |
./build release
- name: Store Bundle Cache
uses: actions/cache@v4
with:
key: "integration-bundle-${{ github.sha }}"
path: frontend/resources/public
test-integration-1:
name: "Integration Tests 1/4"
runs-on: ubuntu-24.04
container: penpotapp/devenv:latest
needs: build-integration
steps:
- name: Checkout Repository
uses: actions/checkout@v4
- name: Restore Cache
uses: actions/cache/restore@v4
with:
key: "integration-bundle-${{ github.sha }}"
path: frontend/resources/public
- name: Run Tests
working-directory: ./frontend
run: |
./scripts/test-e2e --shard="1/4";
- name: Upload test result
uses: actions/upload-artifact@v4
if: always()
with:
name: integration-tests-result-1
path: frontend/test-results/
overwrite: true
retention-days: 3
test-integration-2:
name: "Integration Tests 2/4"
runs-on: ubuntu-24.04
container: penpotapp/devenv:latest
needs: build-integration
steps:
- name: Checkout Repository
uses: actions/checkout@v4
- name: Restore Cache
uses: actions/cache/restore@v4
with:
key: "integration-bundle-${{ github.sha }}"
path: frontend/resources/public
- name: Run Tests
working-directory: ./frontend
run: |
./scripts/test-e2e --shard="2/4";
- name: Upload test result
uses: actions/upload-artifact@v4
if: always()
with:
name: integration-tests-result-2
path: frontend/test-results/
overwrite: true
retention-days: 3
test-integration-3:
name: "Integration Tests 3/4"
runs-on: ubuntu-24.04
container: penpotapp/devenv:latest
needs: build-integration
steps:
- name: Checkout Repository
uses: actions/checkout@v4
- name: Restore Cache
uses: actions/cache/restore@v4
with:
key: "integration-bundle-${{ github.sha }}"
path: frontend/resources/public
- name: Run Tests
working-directory: ./frontend
run: |
./scripts/test-e2e --shard="3/4";
- name: Upload test result
uses: actions/upload-artifact@v4
if: always()
with:
name: integration-tests-result-3
path: frontend/test-results/
overwrite: true
retention-days: 3
test-integration-4:
name: "Integration Tests 4/4"
runs-on: ubuntu-24.04
container: penpotapp/devenv:latest
needs: build-integration
steps:
- name: Checkout Repository
uses: actions/checkout@v4
- name: Restore Cache
uses: actions/cache/restore@v4
with:
key: "integration-bundle-${{ github.sha }}"
path: frontend/resources/public
- name: Run Tests
working-directory: ./frontend
run: |
./scripts/test-e2e --shard="4/4";
- name: Upload test result
uses: actions/upload-artifact@v4
if: always()
with:
name: integration-tests-result-4
path: frontend/test-results/
overwrite: true
retention-days: 3

11
.gitignore vendored
View File

@@ -30,6 +30,8 @@
/*.zip
/.clj-kondo/.cache
/_dump
/notes
/playground/
/backend/*.md
/backend/*.sql
/backend/*.txt
@@ -40,6 +42,7 @@
/backend/resources/public/assets
/backend/resources/public/media
/backend/target/
/backend/experiments
/bundle*
/cd.md
/clj-profiler/
@@ -50,9 +53,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/
@@ -68,6 +68,10 @@
/vendor/**/target
/vendor/svgclean/bundle*.js
/web
/library/target/
/library/*.zip
/external
clj-profiler/
node_modules
/test-results/
@@ -76,3 +80,4 @@ node_modules
/playwright/.cache/
/render-wasm/target/
/**/.yarn/*
/.pnpm-store

2
.nvmrc
View File

@@ -1 +1 @@
v22.13.1
v22.19.0

View File

@@ -1,6 +1,257 @@
# CHANGELOG
## 2.5.2
## 2.12.0 (Unreleased)
### :boom: Breaking changes & Deprecations
#### Backend RPC API changes
The backend RPC API URLS are changed from `/api/rpc/command/<name>` to
`/api/main/methods/<name>`. The previous PATH is preserved for backward
compatibility; however, if you are a user of this API, it is strongly
recommended that you adapt your code to use the new PATH.
#### Updated SSO Callback URL
The OAuth / Single Sign-On (SSO) callback endpoint has changed to
align with the new OpenID Connect (OIDC) implementation.
Old callback URL:
```
https://<your_domain>/api/auth/oauth/<oauth_provider>/callback
```
New callback URL:
```
https://<your_domain>/api/auth/oidc/callback
```
**Action required:**
If you have SSO/Social-Auth configured on your on-premise instance,
the following actions are required before update:
Update your OAuth or SSO provider configuration (e.g., Okta, Google,
Azure AD, etc.) to use the new callback URL. Failure to update may
result in authentication failures after upgrading.
**Reason for change:**
This update standardizes all authentication flows under the single URL
and makis it more modular, enabling the ability to configure SSO auth
provider dinamically.
#### Changes on default docker compose
We have updated the `docker/images/docker-compose.yaml` with a small
change related to the `PENPOT_SECRET_KEY`. Since this version, this
environment variable is also required on exporter. So if you are using
penpot on-premise you will need to apply the same changes on your own
`docker-compose.yaml` file.
We have removed the Minio server from the `docker/images/docker-compose.yml`
example. It's still usable as before, we just removed the example.
### :rocket: Epics and highlights
### :heart: Community contributions (Thank you!)
- Ensure consistent snap behavior across all zoom levels [Github #7774](https://github.com/penpot/penpot/pull/7774) by [@Tokytome](https://github.com/Tokytome)
- Fix crash in token grid view due to tooltip validation (by @dfelinto) [Github #7887](https://github.com/penpot/penpot/pull/7887)
### :sparkles: New features & Enhancements
- Add the ability to select boards to export as PDF [Taiga #12320](https://tree.taiga.io/project/penpot/issue/12320)
- Add toggle for switching boolean property values [Taiga #12341](https://tree.taiga.io/project/penpot/us/12341)
- Make the file export process more reliable [Taiga #12555](https://tree.taiga.io/project/penpot/us/12555)
- Add auth flow changes [Taiga #12333](https://tree.taiga.io/project/penpot/us/12333)
- Add new shape validation mechanism for shapes [Github #7696](https://github.com/penpot/penpot/pull/7696)
- Apply color tokens from sidebar [Taiga #11353](https://tree.taiga.io/project/penpot/us/11353)
- Display tokens in the inspect tab [Taiga #9313](https://tree.taiga.io/project/penpot/us/9313)
- Refactor clipboard behavior to assess some minor inconsistencies and make pasting binary data faster. [Taiga #12571](https://tree.taiga.io/project/penpot/task/12571)
### :bug: Bugs fixed
- Fix text line-height values are wrong [Taiga #12252](https://tree.taiga.io/project/penpot/issue/12252)
- Fix an error translation [Taiga #12402](https://tree.taiga.io/project/penpot/issue/12402)
- Fix pan cursor not disabling viewport guides [Github #6985](https://github.com/penpot/penpot/issues/6985)
- Fix viewport resize on locked shapes [Taiga #11974](https://tree.taiga.io/project/penpot/issue/11974)
- Fix nested variant in a component doesn't keep inherited overrides [Taiga #12299](https://tree.taiga.io/project/penpot/issue/12299)
- Fix on copy instance inside a components chain touched are missing [Taiga #12371](https://tree.taiga.io/project/penpot/issue/12371)
- Fix problem with multiple selection and shadows [Github #7437](https://github.com/penpot/penpot/issues/7437)
- Fix search shortcut [Taiga #10265](https://tree.taiga.io/project/penpot/issue/10265)
- Fix shortcut conflict in text editor (increase/decrease font size vs word selection)
- Fix problem with plugins generating code for pages different than current one [Taiga #12312](https://tree.taiga.io/project/penpot/issue/12312)
- Fix input confirmation behavior is not uniform [Taiga #12294](https://tree.taiga.io/project/penpot/issue/12294)
- Fix copy/pasting application/transit+json [Taiga #12721](https://tree.taiga.io/project/penpot/issue/12721)
- Fix problem with plugins content attribute [Plugins #209](https://github.com/penpot/penpot-plugins/issues/209)
- Fix U and E icon displayed in project list [Taiga #12806](https://tree.taiga.io/project/penpot/issue/12806)
- Fix unpublish library modal not scrolling a long file list [Taiga #12285](https://tree.taiga.io/project/penpot/issue/12285)
- Fix incorrect interaction betwen hower and scroll on assets sidebar [Taiga #12389](https://tree.taiga.io/project/penpot/issue/12389)
- Fix switch variants with paths [Taiga #12841](https://tree.taiga.io/project/penpot/issue/12841)
- Fix referencing typography tokens on font-family tokens [Taiga #12492](https://tree.taiga.io/project/penpot/issue/12492)
## 2.11.1
- Fix WEBP shape export on docker images [Taiga #3838](https://tree.taiga.io/project/penpot/issue/3838)
## 2.11.0
### :boom: Breaking changes & Deprecations
- Deprecated configuration variables with the prefix `PENPOT_ASSETS_*`, and will be
removed in future versions:
- The `PENPOT_ASSETS_STORAGE_BACKEND` becomes `PENPOT_OBJECTS_STORAGE_BACKEND` and its
values passes from (`assets-fs` or `assets-s3`) to (`fs` or `s3`)
- The `PENPOT_STORAGE_ASSETS_FS_DIRECTORY` becomes `PENPOT_OBJECTS_STORAGE_FS_DIRECTORY`
- The `PENPOT_STORAGE_ASSETS_S3_BUCKET` becomes `PENPOT_OBJECTS_STORAGE_S3_BUCKET`
- The `PENPOT_STORAGE_ASSETS_S3_REGION` becomes `PENPOT_OBJECTS_STORAGE_S3_REGION`
- The `PENPOT_STORAGE_ASSETS_S3_ENDPOINT` becomes `PENPOT_OBJECTS_STORAGE_S3_ENDPOINT`
- The `PENPOT_STORAGE_ASSETS_S3_IO_THREADS` replaced (see below)
- Add `PENPOT_NETTY_IO_THREADS` and `PENPOT_EXECUTOR_THREADS` variables to provide the
control over concurrency of the shared resources used by netty. Penpot uses the netty IO
threads for AWS S3 SDK and Redis/Valkey communication, and the EXEC threads to perform
out of HTTP serving threads tasks such that cache invalidation, S3 response completion,
configuration reloading and many other auxiliar tasks. By default they use a half number
if available cpus with a minumum of 2 for both executors. You should not touch that
variables unless you are know what you are doing.
- Replace the `PENPOT_STORAGE_ASSETS_S3_IO_THREADS` with a more general configuration
`PENPOT_NETTY_IO_THREADS` used to configure a shared netty resources across different
services which use netty internally (redis connection, S3 SDK client). This
configuration is not very commonly used so don't expected real impact on any user.
### :sparkles: New features & Enhancements
- New composite token: Typography [Taiga #10200](https://tree.taiga.io/project/penpot/us/10200)
- Show current Penpot version [Taiga #11603](https://tree.taiga.io/project/penpot/us/11603)
- Switch several variant copies at the same time [Taiga #11411](https://tree.taiga.io/project/penpot/us/11411)
- Invitations management improvements [Taiga #3479](https://tree.taiga.io/project/penpot/us/3479)
- Alternative ways of creating variants - Button Viewport [Taiga #11931](https://tree.taiga.io/project/penpot/us/11931)
- Reorder properties for a component [Taiga #10225](https://tree.taiga.io/project/penpot/us/10225)
- File Data storage layout refactor [Github #7345](https://github.com/penpot/penpot/pull/7345)
- Make several queries optimization on comment threads [Github #7506](https://github.com/penpot/penpot/pull/7506)
### :bug: Bugs fixed
- Fix selection problems when devtools open [Taiga #11950](https://tree.taiga.io/project/penpot/issue/11950)
- Fix long font names overlap [Taiga #11844](https://tree.taiga.io/project/penpot/issue/11844)
- Fix paste behavior according to the selected element [Taiga #11979](https://tree.taiga.io/project/penpot/issue/11979)
- Fix problem with export size [Github #7160](https://github.com/penpot/penpot/issues/7160)
- Fix multi level library dependencies [Taiga #12155](https://tree.taiga.io/project/penpot/issue/12155)
- Fix component context menu options order in assets tab [Taiga #11941](https://tree.taiga.io/project/penpot/issue/11941)
- Fix error updating library [Taiga #12218](https://tree.taiga.io/project/penpot/issue/12218)
- Fix restoring a variant in another file makes it overlap the existing variant [Taiga #12049](https://tree.taiga.io/project/penpot/issue/12049)
- Fix auto-width changes to fixed when switching variants [Taiga #12172](https://tree.taiga.io/project/penpot/issue/12172)
- Fix component number has no singular translation string [Taiga #12106](https://tree.taiga.io/project/penpot/issue/12106)
- Fix adding/removing identical text fills [Taiga #12287](https://tree.taiga.io/project/penpot/issue/12287)
- Fix scroll on the inspect tab [Taiga #12293](https://tree.taiga.io/project/penpot/issue/12293)
- Fix lock proportion tooltip [Taiga #12326](https://tree.taiga.io/project/penpot/issue/12326)
- Fix internal Error when selecting a set by name in the token theme editor [Taiga #12310](https://tree.taiga.io/project/penpot/issue/12310)
- Fix drag & drop functionality is swapping instead or reordering [Taiga #12254](https://tree.taiga.io/project/penpot/issue/12254)
- Fix variants not syncronizing tokens on switch [Taiga #12290](https://tree.taiga.io/project/penpot/issue/12290)
- Fix incorrect behavior of Alt + Drag for variants [Taiga #12309](https://tree.taiga.io/project/penpot/issue/12309)
- Fix text override is lost after switch [Taiga #12269](https://tree.taiga.io/project/penpot/issue/12269)
- Fix exporting a board crashing the app [Taiga #12384](https://tree.taiga.io/project/penpot/issue/12384)
- Fix nested variant in a component doesn't keep inherited overrides [Taiga #12299](https://tree.taiga.io/project/penpot/issue/12299)
- Fix selected colors not showing colors from children shapes in multiple selection [Taiga #12384](https://tree.taiga.io/project/penpot/issue/12385)
- Fix scrollbar issue in design tab [Taiga #12367](https://tree.taiga.io/project/penpot/issue/12367)
- Fix library update notificacions showing when they should not [Taiga #12397](https://tree.taiga.io/project/penpot/issue/12397)
- Fix remove flex button doesnt work within variant [Taiga #12314](https://tree.taiga.io/project/penpot/issue/12314)
- Fix an error translation [Taiga #12402](https://tree.taiga.io/project/penpot/issue/12402)
- Fix problem with certain text input in some editable labels (pages, components, tokens...) being in conflict with the drag/drop functionality [Taiga #12316](https://tree.taiga.io/project/penpot/issue/12316)
- Fix not controlled theme renaming [Taiga #12411](https://tree.taiga.io/project/penpot/issue/12411)
- Fix paste without selection sends the new element in the back [Taiga #12382](https://tree.taiga.io/project/penpot/issue/12382)
- Fix options button does not work for comments created in the lower part of the screen [Taiga #12422](https://tree.taiga.io/project/penpot/issue/12422)
- Fix problem when checking usage with removed teams [Taiga #12442](https://tree.taiga.io/project/penpot/issue/12442)
- Fix focus mode persisting across page/file navigation [Taiga #12469](https://tree.taiga.io/project/penpot/issue/12469)
- Fix shadow color validation [Github #7705](https://github.com/penpot/penpot/pull/7705)
- Fix exception on selection blend-mode using keyboard [Github #7710](https://github.com/penpot/penpot/pull/7710)
- Fix crash when using decimal (floating-point) values for X/Y or width/height [Taiga #12543](https://tree.taiga.io/project/penpot/issue/12543)
## 2.10.1
### :sparkles: New features & Enhancements
- Improve workpace file loading [Github 7366](https://github.com/penpot/penpot/pull/7366)
### :bug: Bugs fixed
- Fix regression with text shapes creation with Plugins API [Taiga #12244](https://tree.taiga.io/project/penpot/issue/12244)
## 2.10.0
### :rocket: Epics and highlights
- Variants
### :boom: Breaking changes & Deprecations
### :heart: Community contributions (Thank you!)
### :sparkles: New features & Enhancements
- Add efficiency enhancements to right sidebar [Github #7182](https://github.com/penpot/penpot/pull/7182)
- Add defaults for artboard drawing [Taiga #494](https://tree.taiga.io/project/penpot/us/494?milestone=465047)
- Continuous display of distances between elements when moving a layer with the keyboard [Taiga #1780](https://tree.taiga.io/project/penpot/us/1780)
- New Number token - unitless values [Taiga #10936](https://tree.taiga.io/project/penpot/us/10936)
- New font-family token [Taiga #10937](https://tree.taiga.io/project/penpot/us/10937)
- New text case token [Taiga #10942](https://tree.taiga.io/project/penpot/us/10942)
- New text-decoration token [Taiga #10941](https://tree.taiga.io/project/penpot/us/10941)
- New letter spacing token [Taiga #10940](https://tree.taiga.io/project/penpot/us/10940)
- New font weight token [Taiga #10939](https://tree.taiga.io/project/penpot/us/10939)
- Upgrade Node to v22.18.0 [Github #7283](https://github.com/penpot/penpot/pull/7283)
- Upgrade the base docker image for penpot frontend to v1.29.1 [Github #7283](https://github.com/penpot/penpot/pull/7283)
- Create variant from an existing component [Taiga #2088](https://tree.taiga.io/project/penpot/us/2088)
- Create variant from an existing variant [Taiga #8282](https://tree.taiga.io/project/penpot/us/8282)
- Actions over a component with variants [Taiga #10503](https://tree.taiga.io/project/penpot/us/10503)
- Create a variant by dragging a component into a component with variants [Taiga #8134](https://tree.taiga.io/project/penpot/us/8134)
- Transform a variant into an individual component [Taiga #8141](https://tree.taiga.io/project/penpot/us/8141)
- Delete variant [Taiga #6890](https://tree.taiga.io/project/penpot/us/6890)
- Restore an orphaned copy of a variant [Taiga #10446](https://tree.taiga.io/project/penpot/us/10446)
- Add, Edit & Delete variant properties name and value [Taiga #6892](https://tree.taiga.io/project/penpot/us/6892)
- Retrieve variants [Taiga #6888](https://tree.taiga.io/project/penpot/us/6888)
- Retrieve variants with nested components [Taiga #10277](https://tree.taiga.io/project/penpot/us/10277)
- Create variants in bulk from existing components [Taiga #7926](https://tree.taiga.io/project/penpot/us/7926)
- Alternative ways of creating variants - Button Design Tab [Taiga #10316](https://tree.taiga.io/project/penpot/us/10316)
- Fix problem with component swapping panel [Taiga #12175](https://tree.taiga.io/project/penpot/issue/12175)
### :bug: Bugs fixed
- Display strokes information in inspect tab [Taiga #11154](https://tree.taiga.io/project/penpot/issue/11154)
- Fix problem with booleans selection [Taiga #11627](https://tree.taiga.io/project/penpot/issue/11627)
- Fix missing font when copy&paste a chunk of text [Taiga #11522](https://tree.taiga.io/project/penpot/issue/11522)
- Fix bad swap slot after two swaps [Taiga #11659](https://tree.taiga.io/project/penpot/issue/11659)
- Fix missing package for the `penpot_exporter` Docker image [GitHub #7205](https://github.com/penpot/penpot/issues/7025)
- Fix issue where multiple dropdown menus could be opened simultaneously on the dashboard page [Taiga #11500](https://tree.taiga.io/project/penpot/issue/11500)
- Fix font size/variant not updated when editing a text [Taiga #11552](https://tree.taiga.io/project/penpot/issue/11552)
- Fix issue where Alt + arrow keys shortcut interferes with letter-spacing when moving text layers [Taiga #11552](https://tree.taiga.io/project/penpot/issue/11771)
- Fix consistency issues on how font variants are visualized [Taiga #11499](https://tree.taiga.io/project/penpot/us/11499)
- Fix parsing rx and ry SVG values for rect radius [Taiga #11861](https://tree.taiga.io/project/penpot/issue/11861)
- Fix misleading affordance in saved versions [Taiga #11887](https://tree.taiga.io/project/penpot/issue/11887)
- Fix pasting RTF text crashes penpot [Taiga #11717](https://tree.taiga.io/project/penpot/issue/11717)
- Fix navigation arrows in Libraries & Templates carousel [Taiga #10609](https://tree.taiga.io/project/penpot/issue/10609)
- Fix applying tokens with zero value to size [Taiga #11618](https://tree.taiga.io/project/penpot/issue/11618)
- Fix typo [Taiga #11969](https://tree.taiga.io/project/penpot/issue/11969)
- Fix typo [Taiga #11970](https://tree.taiga.io/project/penpot/issue/11970)
- Fix typos [Taiga #11971](https://tree.taiga.io/project/penpot/issue/11971)
- Fix inconsistent naming for "Flatten" [Taiga #8371](https://tree.taiga.io/project/penpot/issue/8371)
- Layout item tokens should be unapplied when moving out of a layout [Taiga #11012](https://tree.taiga.io/project/penpot/issue/11012)
- Fix incorrect date displayed for support plan [Taiga #11986](https://tree.taiga.io/project/penpot/issue/11986)
- Fix can't import 'borderWidth' type token [#132](https://github.com/tokens-studio/penpot/issues/132)
- Fix moving elements up or down while pressing alt [Taiga Issue #11992](https://tree.taiga.io/project/penpot/issue/11992)
- Fix conflicting shortcuts (remove dec/inc line height and letter spacing) [Taiga #12102](https://tree.taiga.io/project/penpot/issue/12102)
- Fix conflicting shortcuts (remove text-align shortcuts) [Taiga #12047](https://tree.taiga.io/project/penpot/issue/12047)
- Fix export file with empty tokens library [Taiga #12137](https://tree.taiga.io/project/penpot/issue/12137)
- Fix context menu on spacing tokens [Taiga #12141](https://tree.taiga.io/project/penpot/issue/12141)
## 2.9.0
### :rocket: Epics and highlights
@@ -8,7 +259,306 @@
### :heart: Community contributions (Thank you!)
- Clarify message when inviting existing team members to make it more user-friendly and clear which invitations will be sent. [Taiga #11441](https://tree.taiga.io/project/penpot/issue/11441) by [@iprithvitharun](https://github.com/iprithvitharun)
- Update email change confirmation message for clarity and correct grammar. [GitHub #6786](https://github.com/penpot/penpot/issues/6786) by [@iprithvitharun](https://github.com/iprithvitharun)
### :sparkles: New features & Enhancements
- Add visual indicator for new comments in the workspace [Taiga #11328](https://tree.taiga.io/project/penpot/issue/11328)
- On components overrides, separate the content of the text from the rest of properties [Taiga #7434](https://tree.taiga.io/project/penpot/us/7434)
- Improve dashboard's sidebar [Taiga #10700](https://tree.taiga.io/project/penpot/us/10700)
- Change "Save color" button to primary button [Taiga #9410](https://tree.taiga.io/project/penpot/issue/9410)
- Support for exif rotated images [GitHub #6767](https://github.com/penpot/penpot/issues/6767)
- Display Blend Mode and Layer Opacity properties in the Inspect tab [Taiga #11283](https://tree.taiga.io/project/penpot/issue/11283)
- Provide CSS `mix-blend-mode` property in code editor when present on shape [Taiga #11282](https://tree.taiga.io/project/penpot/issue/11282)
- Add the option to import tokens in a .zip file. [Taiga #11378](https://tree.taiga.io/project/penpot/us/11378)
- New typography token type - font size token [Taiga #10938](https://tree.taiga.io/project/penpot/us/10938)
- Hide bounding box while editing visual effects [Taiga #11576](https://tree.taiga.io/project/penpot/issue/11576)
- Improved text layer resizing: Allow double-click on text bounding box to set auto-width/auto-height [Taiga #11577](https://tree.taiga.io/project/penpot/issue/11577)
- 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)
- 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)
- Add info to apply-token event [Taiga #11710](https://tree.taiga.io/project/penpot/task/11710)
- Fix double click on set name input [Taiga #11747](https://tree.taiga.io/project/penpot/issue/11747)
### :bug: Bugs fixed
- Copying font size does not copy the unit [Taiga #11143](https://tree.taiga.io/project/penpot/issue/11143)
- Fix text-decoration line-through that displays a wrong property value [Taiga #11145](https://tree.taiga.io/project/penpot/issue/11145)
- Fix display error message on register form [Taiga #11444](https://tree.taiga.io/project/penpot/issue/11444)
- Fix toggle focus mode did not restore viewport and selection upon exit [GitHub #6280](https://github.com/penpot/penpot/issues/6820)
- Fix problem when creating a layout from an existing layout [Taiga #11554](https://tree.taiga.io/project/penpot/issue/11554)
- Fix title button from Title Case to Capitalize [Taiga #11476](https://tree.taiga.io/project/penpot/issue/11476)
- Fix touchpad swipe leading to navigating back/forth [GitHub #4246](https://github.com/penpot/penpot/issues/4246)
- Keep color data when copying from info tab into CSS [Taiga #11144](https://tree.taiga.io/project/penpot/issue/11144)
- Update HSL values to modern syntax as defined in W3C CSS Color Module Level 4 [Taiga #11144](https://tree.taiga.io/project/penpot/issue/11144)
- Fix main component receives focus and is selected when using 'Show Main Component' [Taiga #11402](https://tree.taiga.io/project/penpot/issue/11402)
- Fix UI theme selection from main menu [Taiga #11567](https://tree.taiga.io/project/penpot/issue/11567)
- 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)
- Fix problem when changing between flex/grid layout [Taiga #11625](https://tree.taiga.io/project/penpot/issue/11625)
- Fix opacity on stroke gradients [Taiga #11646](https://tree.taiga.io/project/penpot/issue/11646)
- Fix change from gradient to solid color [Taiga #11648](https://tree.taiga.io/project/penpot/issue/11648)
- Fix the context menu always closes after any action [Taiga #11624](https://tree.taiga.io/project/penpot/issue/11624)
- Fix X & Y position do not sincronize with tokens [Taiga #11617](https://tree.taiga.io/project/penpot/issue/11617)
- Fix tooltip position after first time [Taiga #11688](https://tree.taiga.io/project/penpot/issue/11688)
- Fix inconsistent ordering of pinned projects on dashboard sidebar [Taiga #11674](https://tree.taiga.io/project/penpot/issue/11674)
- Fix export button width on inspect tab [Taiga #11394](https://tree.taiga.io/project/penpot/issue/11394)
- Fix stroke width token application [Taiga #11724](https://tree.taiga.io/project/penpot/issue/11724)
- Fix number token application on shape [Taiga #11331](https://tree.taiga.io/project/penpot/task/11331)
- Fix auto height is fixed in the HTML inspect tab for text elements [Taiga #11680](https://tree.taiga.io/project/penpot/task/11680)
## 2.8.1
### :bug: Bugs fixed
- Fix unexpected exception on processing old texts [Github #6889](https://github.com/penpot/penpot/pull/6889)
- Fix error on inspect tab when selecting multiple shapes [Taiga #11655](https://tree.taiga.io/project/penpot/issue/11655)
- Fix missing package for the penport_exporter Docker image [GitHub #7205](https://github.com/penpot/penpot/issues/7025)
## 2.8.0
### :rocket: Epics and highlights
### :boom: Breaking changes & Deprecations
**Penpot Library**
The initial prototype is completly reworked to provide a more consistent API
and to have proper validation and params decoding. All the details can be found
on [its own changelog](library/CHANGES.md)
**Penpot migrate from Redis to Valkey**
As [Valkey](https://valkey.io/) is an opne-souce fork of [Redis](https://redis.io/)
version 7.2.4, this version of Penpot will be compatible with Redis but may diverge
in future versions. Therefore, **migration from Redis to ValKey is recommended for all
on-premises instances** that want to keep up to date.
### :heart: Community contributions (Thank you!)
- Add Serbian language [GitHub #5002](https://github.com/penpot/penpot/issues/5002) by [crnobog69](https://github.com/crnobog69)
### :sparkles: New features & Enhancements
- Optimize profile setup flow for better user experience [Taiga #10028](https://tree.taiga.io/project/penpot/us/10028)
- Rewrite path shape data PathData encoding [Taiga #8542](https://tree.taiga.io/project/penpot/us/8542?milestone=441308)
- Update base image for Docker Backend and Exporter to Ubuntu 24.04
- Update base image for Docker Frontend to Nginx 1.28.0
- Allow multi file token import [Github #27](https://github.com/tokens-studio/penpot/issues/27)
- Create `input*` wrapper component, and `label*`, `input-field*` and `hint-message*` components [Taiga #10713](https://tree.taiga.io/project/penpot/us/10713)
- Deselect layers (and path nodes) with Ctrl+Shift+Drag [Github #2509](https://github.com/penpot/penpot/issues/2509)
- Copy to SVG from contextual menu [Github #838](https://github.com/penpot/penpot/issues/838)
- Add styles for Inkeep Chat at workspace [Taiga #10708](https://tree.taiga.io/project/penpot/us/10708)
- Add configuration for air gapped installations with Docker
- Support system color scheme [Github #5030](https://github.com/penpot/penpot/issues/5030)
- Persist ruler visibility across files and reloads [GitHub #4586](https://github.com/penpot/penpot/issues/4586)
- Update google fonts (at 2025/05/19) [Taiga 10792](https://tree.taiga.io/project/penpot/us/10792)
- Add tooltip component to DS [Taiga 9220](https://tree.taiga.io/project/penpot/us/9220)
- Allow multi file token export [Taiga #10144](https://tree.taiga.io/project/penpot/us/10144)
- Fix problem when double click on hidden shapes [Taiga #11314](https://tree.taiga.io/project/penpot/issue/11314)
### :bug: Bugs fixed
- Fix getCurrentUser for plugins api [Taiga #11057](https://tree.taiga.io/project/penpot/issue/11057)
- Fix spacing / sizes of different elements in the measurements section of the design tab [Taiga #11076](https://tree.taiga.io/project/penpot/issue/11076)
- Fix selection of short paths [Github #4472](https://github.com/penpot/penpot/issues/4472)
- Fix element positioning on the right side to adjust to grid [#11073](https://tree.taiga.io/project/penpot/issue/11073)
- Fix palette is over sidebar [#11160](https://tree.taiga.io/project/penpot/issue/11160)
- Fix font size input not displaying "mixed" when multiple texts are selected [Taiga #11177](https://tree.taiga.io/project/penpot/issue/11177)
- Misalignments at Create account [Taiga #11315](https://tree.taiga.io/project/penpot/issue/11315)
- Fix issue with importing files where flex/grid is used [Taiga #11334](https://tree.taiga.io/project/penpot/issue/11334)
- Fix wrong color in the export progress bar [Taiga #11299](https://tree.taiga.io/project/penpot/issue/11299)
- Fix right sidebar width overflow on long layer names [Taiga #11212](https://tree.taiga.io/project/penpot/issue/11212)
- Fix comment icon fill [Taiga #11388](https://tree.taiga.io/project/penpot/issue/11388)
- Fix gap on radio-buttons component [Taiga #11360](https://tree.taiga.io/project/penpot/issue/11360)
- Fix button width [Taiga #11394](https://tree.taiga.io/project/penpot/issue/11394)
- Fix mixed letter spacing and line height [Taiga #11178](https://tree.taiga.io/project/penpot/issue/11178)
- Fix snap nodes shortcut [Taiga #11054](https://tree.taiga.io/project/penpot/issue/11054)
- Fix changing a text property in a text layer does not unapply the previously applied token in the same property [Taiga #11337](https://tree.taiga.io/project/penpot/issue/11337)
- Fix shortcut error pressing G+W from the View Mode [Taiga #11061](https://tree.taiga.io/project/penpot/issue/11061)
- Fix entering long project name [Taiga #11417](https://tree.taiga.io/project/penpot/issue/11417)
- Fix slow color picker [Taiga #11019](https://tree.taiga.io/project/penpot/issue/11019)
- Fix tooltip position after click [Taiga #11405](https://tree.taiga.io/project/penpot/issue/11405)
- Fix incorrect media translation on paste text with fill images [Github #6845](https://github.com/penpot/penpot/pull/6845)
## 2.7.2
### :bug: Bugs fixed
- Update plugins runtime [Github #6604](https://github.com/penpot/penpot/pull/6604)
- Backport from develop a minor fix that enables import of files
generated by penpot library [Github #6614](https://github.com/penpot/penpot/pull/6614)
- Fix copy in error message [GitHub #6615](https://github.com/penpot/penpot/pull/6615)
- Fix url on invitation link [Taiga #11284](https://tree.taiga.io/project/penpot/issue/11284)
## 2.7.1
### :bug: Bugs fixed
- Fix incorrect handling of strokes with images on importing files
- Fix tokens disappearing after manual additions [Taiga #11063](https://tree.taiga.io/project/penpot/issue/11063)
## 2.7.0
### :rocket: Epics and highlights
### :boom: Breaking changes & Deprecations
### :heart: Community contributions (Thank you!)
- Design improvements to the Invitations page with an empty state [GitHub #2608](https://github.com/penpot/penpot/issues/2608) by [@iprithvitharun](https://github.com/iprithvitharun)
### :sparkles: New features
- Update board presets with a newer devices [Taiga #10610](https://tree.taiga.io/project/penpot/us/10610)
- Propagate "sharing a prototype" to editors and viewers [Taiga #8853](https://tree.taiga.io/project/penpot/us/8853)
- Design improvements to the Invitations page with an empty state [Taiga #4554](https://tree.taiga.io/project/penpot/us/4554)
- Duplicate token sets [Taiga #10694](https://tree.taiga.io/project/penpot/issue/10694)
- Add set selection in create Token themes flow [Taiga #10746](https://tree.taiga.io/project/penpot/issue/10746)
- Display indicator on not active sets [Taiga #10668](https://tree.taiga.io/project/penpot/issue/10668)
### :bug: Bugs fixed
- Fix "at" icon to match all icons on app [Taiga #11136](https://tree.taiga.io/project/penpot/issue/11136)
- Fix problem in viewer with the back button [Taiga #10907](https://tree.taiga.io/project/penpot/issue/10907)
- Fix resize bar background on tokens panel [Taiga #10811](https://tree.taiga.io/project/penpot/issue/10811)
- Fix shortcut for history version panel [Taiga #11006](https://tree.taiga.io/project/penpot/issue/11006)
- Fix positioning of comment drafts when near the right / bottom edges of viewport [Taiga #10534](https://tree.taiga.io/project/penpot/issue/10534)
- Fix path having a wrong selrect [Taiga #10257](https://tree.taiga.io/project/penpot/issue/10257)
- Fix SVG `stroke-linecap` property when importing SVGs [Taiga #9489](https://tree.taiga.io/project/penpot/issue/9489)
- Fix position problems cutting-pasting a component [Taiga #10677](https://tree.taiga.io/project/penpot/issue/10677)
- Fix design tab has a horizontal scroll [Taiga #10660](https://tree.taiga.io/project/penpot/issue/10660)
- Fix long file names being clipped when longer than allowed length [Taiga #10662](https://tree.taiga.io/project/penpot/issue/10662)
- Fix problem with error detail in toast [Taiga #10519](https://tree.taiga.io/project/penpot/issue/10519)
- Fix view mode error when an external user tries to export something from a prototype using a shared link [Taiga #10251](https://tree.taiga.io/project/penpot/issue/10251)
- Fix merge path nodes with only one node selected [Taiga #9626](https://tree.taiga.io/project/penpot/issue/9626)
- Fix problem with import errors [Taiga #10040](https://tree.taiga.io/project/penpot/issue/10040)
- Fix color gradient on texts [Taiga Issue #7488](https://tree.taiga.io/project/penpot/issue/7488)
- Add support for self mentions [Taiga #10809](https://tree.taiga.io/project/penpot/issue/10809)
- Fix team info settings alignment [Taiga #10869](https://tree.taiga.io/project/penpot/issue/10869)
- Fix left sidebar horizontal scroll on nested layers [Taiga #10791](https://tree.taiga.io/project/penpot/issue/10791)
- Improve error message details importing tokens [Taiga Issue #10772](https://tree.taiga.io/project/penpot/issue/10772)
- Fix no selected set after Drag & Drop [Github #71](https://github.com/tokens-studio/penpot/issues/71)
- Styledictionary v5 Update [Github #6283](https://github.com/penpot/penpot/pull/6283)
- Fix Rename a set throws an internal error [Github #78](https://github.com/tokens-studio/penpot/issues/78)
- Fix Out of Sync Token Value & Color Picker [Github #102](https://github.com/tokens-studio/penpot/issues/102)
- Fix Color should preserve color space [Github #69](https://github.com/tokens-studio/penpot/issues/69)
- Fix cannot rename Design Token Sets when group of same name exists [Taiga Issue #10773](https://tree.taiga.io/project/penpot/issue/10773)
- Fix problem when duplicating grid layout [Github #6391](https://github.com/penpot/penpot/issues/6391)
- Fix issue that makes workspace shortcuts stop working [Taiga #11062](https://tree.taiga.io/project/penpot/issue/11062)
- Fix problem while syncing library colors and typographies [Taiga #11068](https://tree.taiga.io/project/penpot/issue/11068)
- Fix problem with path edition of shapes [Taiga #9496](https://tree.taiga.io/project/penpot/issue/9496)
- Fix exception on paste invalid html [Taiga #11047](https://tree.taiga.io/project/penpot/issue/11047)
- Fix share button being displayed with no permissions [Taiga #11086](https://tree.taiga.io/project/penpot/issue/11086)
- Fix inline styles in code tab [Taiga Issue #7583](https://tree.taiga.io/project/penpot/issue/7583)
- Fix exception on returning openapi.json
- Fix json encoding of TokensLib [Taiga #10994](https://tree.taiga.io/project/penpot/issue/10994)
## 2.6.2
### :bug: Bugs fixed
- Increase the height of the right sidebar dropdowns [Taiga #10615](https://tree.taiga.io/project/penpot/issue/10615)
- Fix scroll on token themes modal [Taiga #10745](https://tree.taiga.io/project/penpot/issue/10745)
- Fix collapsing grouped sets in "edit Theme" closes the dialog [Taiga #10771](https://tree.taiga.io/project/penpot/issue/10771)
- Fix unexpected exception on path editor on merge segments when undo stack is empty
- Fix pricing CTA to be under a config flag [Taiga #10808](https://tree.taiga.io/project/penpot/issue/10808)
- Fix allow moving a main component into another [Taiga #10818](https://tree.taiga.io/project/penpot/issue/10818)
- Fix several issues with internal srepl helpers
- Fix unexpected exception on template import from libraries
- Fix incorrect uuid parsing from different parts of code
- Fix update layout on component restore [Taiga #10637](https://tree.taiga.io/project/penpot/issue/10637)
- Fix horizontal scroll in viewer [Github #6290](https://github.com/penpot/penpot/issues/6290)
- Fix detach component in a particular case [Taiga #10837](https://tree.taiga.io/project/penpot/issue/10837)
## 2.6.1
### :bug: Bugs fixed
- Fix webhooks not shown in list [Taiga #10763](https://tree.taiga.io/project/penpot/issue/10763)
- Fix colorpicker scroll when dropdown displayed [Taiga #10696](https://tree.taiga.io/project/penpot/issue/10696)
- Clean internal workspace state on exit or url changed [Taiga #10619](https://tree.taiga.io/project/penpot/issue/10619)
## 2.6.0
### :rocket: Epics and highlights
- Design Tokens
### :boom: Breaking changes & Deprecations
### :heart: Community contributions (Thank you!)
### :sparkles: New features
- [COMMENTS] "Mark All as Read" Functionality in Dashboard [Taiga #9235](https://tree.taiga.io/project/penpot/us/9235)
- [COMMENTS] Bubble Groups [Taiga #9236](https://tree.taiga.io/project/penpot/us/9236)
- Change templates carrousel [Taiga #9803](https://tree.taiga.io/project/penpot/us/9803)
- [DESIGN TOKENS] Tokens CRUD. Types added: Color, Opacity, Border radius, Dimension, Sizing, Spacing, Rotation and Stroke.
- [DESIGN TOKENS] Create references (alias) that point to other tokens.
- [DESIGN TOKENS] Math operations in token values.
- [DESIGN TOKENS] Sets CRUD, grouping and reordering.
- [DESIGN TOKENS] Multidimensional Themes and Sets management.
- [DESIGN TOKENS] Apply/Remove tokens to/from elements from the Tokens tab.
- [DESIGN TOKENS] Integration with components.
- [DESIGN TOKENS] Import and export tokens from a JSON file.
- [DESIGN TOKENS] Apply Themes and Sets at document level.
- Add more descriptive tooltip to boards for first time users [Taiga #9426](https://tree.taiga.io/project/penpot/us/9426)
- First State of a Project Changes Consolidation [Taia #10605](https://tree.taiga.io/project/penpot/us/10605)
### :bug: Bugs fixed
- Fix opacity in frame containers [Github #5858](https://github.com/penpot/penpot/pull/5858)
- Avoid resizing on click [Taiga #10213](https://tree.taiga.io/project/penpot/issue/10213)
- Hide horizontal scroll from dashboard sidebar [Taiga #10422](https://tree.taiga.io/project/penpot/issue/10422)
- Fix cut and paste a copy a cmponent inside its parent [Taiga #10365](https://tree.taiga.io/project/penpot/us/10365)
- Fix duplicate page with component over frame [Taiga #8151](https://tree.taiga.io/project/penpot/issue/8151) and [Taiga #9698](https://tree.taiga.io/project/penpot/issue/9698)
- The plugin list in the navigation menu lacks scrolling, some plugins are not visible when a large number are installed [Taiga #9360](https://tree.taiga.io/project/penpot/us/9360)
- Fix hidden toolbar click event still available [Taiga #10437](https://tree.taiga.io/project/penpot/us/10437)
- Fix hovering over templates [Taiga #10545](https://tree.taiga.io/project/penpot/issue/10545)
- Fix problem with default shadows value in plugins [Plugins #191](https://github.com/penpot/penpot-plugins/issues/191)
- Fix problem with constraints when creating group [Taiga #10455](https://tree.taiga.io/project/penpot/issue/10455)
- Fix opening pen with shortcut multiple times breaks toolbar [Taiga #10566](https://tree.taiga.io/project/penpot/issue/10566)
- Fix actions when workspace is visited first time [Taiga #10548](https://tree.taiga.io/project/penpot/issue/10548)
- Chat icon overlaps "Show" button in carrousel section [Taiga #10542](https://tree.taiga.io/project/penpot/issue/10542)
- Fix assets name on inspect tab [Taiga #10630](https://tree.taiga.io/project/penpot/issue/10630)
- Fix chat icon overlaps "Show" button in carrousel section [Taiga #10542](https://tree.taiga.io/project/penpot/issue/10542)
- Fix incorrect handling of background task result (now task rows are properly marked as completed)
- Fix available size of resize handler [Taiga #10639](https://tree.taiga.io/project/penpot/issue/10639)
- Internal error when install a plugin by penpothub - Try plugin [Taiga #10542](https://tree.taiga.io/project/penpot/issue/10542)
- Add character limitation to asset inputs [Taiga #10669](https://tree.taiga.io/project/penpot/issue/10669)
- Fix Storybook link 'list of all available icons' wrong path [Taiga #10705](https://tree.taiga.io/project/penpot/issue/10705)
## 2.5.4
### :heart: Community contributions (Thank you!)
- 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)
### :bug: Bugs fixed
- Fix feature loading on workspace when opening a file in a background
tab [Taiga #10377](https://tree.taiga.io/project/penpot/issue/10377)
- Fix minor inconsistencies on RPC `get-file-libraries` and `get-file`
methods (add missing team-id prop)
- Fix problem with viewer role and inspect mode [Taiga #9751](https://tree.taiga.io/project/penpot/issue/9751)
- Fix error when clicking on a comment at the viewer's sidebar [Taiga #10465](https://tree.taiga.io/project/penpot/issue/10465)
## 2.5.3
### :bug: Bugs fixed
- Component sync issues with multiple tabs [Taiga #10471](https://tree.taiga.io/project/penpot/issue/10471)
## 2.5.2
### :sparkles: New features
- When the workspace is empty, set default the board creation tool [Taiga #9425](https://tree.taiga.io/project/penpot/us/9425)
### :bug: Bugs fixed
@@ -20,25 +570,15 @@
## 2.5.1
### :rocket: Epics and highlights
### :boom: Breaking changes & Deprecations
### :heart: Community contributions (Thank you!)
### :sparkles: New features
- Improve Nginx entryponit to get the resolvers dinamically by default
### :bug: Bugs fixed
## 2.5.0
### :rocket: Epics and highlights
### :boom: Breaking changes & Deprecations
Although this is not a breaking change, we believe its important to highlight it in this
Although this is not a breaking change, we believe it's important to highlight it in this
section:
This release includes a fix for an internal bug in Penpot that caused incorrect handling
@@ -46,9 +586,9 @@ of media assets (e.g., fill images). The issue has been resolved since version 2
no new incorrect references will be generated. However, existing files may still contain
incorrect references.
To address this, weve provided a script to correct these references in existing files.
To address this, we've provided a script to correct these references in existing files.
While having incorrect references generally doesnt result in visible issues, there are
While having incorrect references generally doesn't result in visible issues, there are
rare cases where it can cause problems. For example, if a component library (containing
images) is deleted, and that library is being used in other files, running the FileGC task
(responsible for freeing up space and performing logical deletions) could leave those
@@ -64,9 +604,6 @@ If you have a big database and many cores available, you can reduce the time of
all files by increasing paralelizacion changing the `max-jobs` value from 1 to N (where N
is a number of cores)
### :heart: Community contributions (Thank you!)
### :sparkles: New features
- [GRADIENTS] New gradients UI with multi-stop support. [Taiga #3418](https://tree.taiga.io/project/penpot/epic/3418)
@@ -83,6 +620,7 @@ is a number of cores)
### :bug: Bugs fixed
- Fix menu shadow color [Taiga #10102](https://tree.taiga.io/project/penpot/issue/10102)
- Fix missing state refresh on notifications update [Taiga #10253](https://tree.taiga.io/project/penpot/issue/10253)
- Fix icon visualization on select component [Taiga #8889](https://tree.taiga.io/project/penpot/issue/8889)
- Fix typo on integration tests docs [Taiga #10112](https://tree.taiga.io/project/penpot/issue/10112)
@@ -125,7 +663,6 @@ is a number of cores)
- Fix missing methods reference on API Docs
- Fix memory usage issue on file-gc asynchronous task (related to snapshots feature)
## 2.4.1
### :bug: Bugs fixed
@@ -133,7 +670,6 @@ is a number of cores)
- Fix error when importing files with touched components [Taiga #9625](https://tree.taiga.io/project/penpot/issue/9625)
- Fix problem when changing color libraries [Plugins #184](https://github.com/penpot/penpot-plugins/issues/184)
## 2.4.0
### :rocket: Epics and highlights
@@ -187,7 +723,6 @@ is a number of cores)
- Add initial documentation for Kubernetes
## 2.3.1
### :bug: Bugs fixed
@@ -195,7 +730,6 @@ is a number of cores)
- Fix unexpected issue on interaction between plugins sandbox and
internal impl of promise
## 2.3.0
### :rocket: Epics and highlights
@@ -221,7 +755,6 @@ is a number of cores)
You can enable it with the `enable-feature-text-editor-v2` configuration flag.
### :bug: Bugs fixed
- Fix problem with constraints buttons [Taiga #8465](https://tree.taiga.io/project/penpot/issue/8465)
@@ -261,8 +794,8 @@ is a number of cores)
### :boom: Breaking changes & Deprecations
- Removed "merge assets" option when exporting ".svg + .json" files. After the components changes the option wasn't
working properly and we're planning to change the format soon. We think it's better to deprecate the option for the
time being.
working properly and we're planning to change the format soon. We think it's better to deprecate the option for the
time being.
### :heart: Community contributions (Thank you!)
@@ -278,7 +811,7 @@ time being.
freeing up space in the database. It can be enabled with the
`enable-enable-tiered-file-data-storage` flag.
*(On-Premise feature, EXPERIMENTAL).*
_(On-Premise feature, EXPERIMENTAL)._
- **JSON Interoperability for HTTP API** [Taiga #8372](https://tree.taiga.io/project/penpot/us/8372)
@@ -321,7 +854,7 @@ time being.
- **Design System**
We implemented and subbed in new components from our Design System: `loader*` ([Taiga #8355](https://tree.taiga.io/project/penpot/task/8355)) and `tab-switcher*` ([Taiga #8518](https://tree.taiga.io/project/penpot/task/8518)).
We implemented and subbed in new components from our Design System: `loader*` ([Taiga #8355](https://tree.taiga.io/project/penpot/task/8355)) and `tab-switcher*` ([Taiga #8518](https://tree.taiga.io/project/penpot/task/8518)).
- **Storybook** [Taiga #6329](https://tree.taiga.io/project/penpot/us/6329)
@@ -376,11 +909,11 @@ time being.
### :sparkles: New features
- Consolidate templates new order and naming [Taiga #8392](https://tree.taiga.io/project/penpot/task/8392)
- Consolidate templates new order and naming [Taiga #8392](https://tree.taiga.io/project/penpot/task/8392)
### :bug: Bugs fixed
- Fix the search label in translations [Taiga #8402](https://tree.taiga.io/project/penpot/issue/8402)
- Fix the "search" label in translations [Taiga #8402](https://tree.taiga.io/project/penpot/issue/8402)
- Fix pencil loader [Taiga #8348](https://tree.taiga.io/project/penpot/issue/8348)
- Fix several issues on the OIDC.
- Fix regression on the `email-verification` flag [Taiga #8398](https://tree.taiga.io/project/penpot/issue/8398)
@@ -460,22 +993,21 @@ time being.
- Fix color palette sorting [Taiga #7458](https://tree.taiga.io/project/penpot/issue/7458)
- Fix style scoping problem with imported SVG [Taiga #7671](https://tree.taiga.io/project/penpot/issue/7671)
## 2.0.1
### :bug: Bugs fixed
- Fix different issues related to components v2 migrations including [Github #4443](https://github.com/penpot/penpot/issues/4443)
## 2.0.0 - I Just Can't Get Enough
### :rocket: Epics and highlights
- Grid CSS layout [Taiga #4915](https://tree.taiga.io/project/penpot/epic/4915)
- UI redesign [Taiga #4958](https://tree.taiga.io/project/penpot/epic/4958)
- New components System [Taiga #2662](https://tree.taiga.io/project/penpot/epic/2662)
- Swap components [Taiga #1331](https://tree.taiga.io/project/penpot/us/1331)
- Images as fill [Taiga #2983](https://tree.taiga.io/project/penpot/us/2983)
- Images as fill [Taiga #2983](https://tree.taiga.io/project/penpot/us/2983)
- HTML code generation [Taiga #5277](https://tree.taiga.io/project/penpot/us/5277)
- Light and dark themes [Taiga #2287](https://tree.taiga.io/project/penpot/us/2287)
@@ -484,9 +1016,9 @@ time being.
- New strokes default to inside border [Taiga #6847](https://tree.taiga.io/project/penpot/issue/6847)
- Change default z ordering on layers in flex layout. The previous behavior was inconsistent with how HTML works and we changed it to be more consistent. Previous layers that overlapped could be hidden, the fastest way to fix this is changing the z-index property but a better way is to change the order of your layers.
### :heart: Community contributions (Thank you!)
- New Hausa, Yoruba and Igbo translations and update translation files (by All For Tech Empowerment Foundation) [Taiga #6950](https://tree.taiga.io/project/penpot/us/6950), [Taiga #6534](https://tree.taiga.io/project/penpot/us/6534)
- New Hausa, Yoruba and Igbo translations and update translation files (by All For Tech Empowerment Foundation) [Taiga #6950](https://tree.taiga.io/project/penpot/us/6950), [Taiga #6534](https://tree.taiga.io/project/penpot/us/6534)
- Hide bounding-box when editing shape (by @VasilevsVV) [#3930](https://github.com/penpot/penpot/pull/3930)
- CTRL + "+" to zoom into canvas instead of browser (by @audriu) [#3848](https://github.com/penpot/penpot/pull/3848)
- Add dev deps.edn in the project root (by @PEZ) [#3794](https://github.com/penpot/penpot/pull/3794)
@@ -495,6 +1027,7 @@ time being.
- Typo (by StephanEggermont) [#157](https://github.com/penpot/penpot-docs/pull/157)
### :sparkles: New features
- Send comments with Ctrl+Enter / Cmd + Enter [Taiga #6085](https://tree.taiga.io/project/penpot/issue/6085)
- Select through stroke only rectangle [Taiga #5484](https://tree.taiga.io/project/penpot/issue/5484)
- Stroke default position [Taiga #6847](https://tree.taiga.io/project/penpot/issue/6847)
@@ -562,6 +1095,7 @@ time being.
- [REDESIGN] Onboarding slides [Taiga #6678](https://tree.taiga.io/project/penpot/us/6678)
### :bug: Bugs fixed
- Fix pixelated thumbnails [Github #3681](https://github.com/penpot/penpot/issues/3681), [Github #3661](https://github.com/penpot/penpot/issues/3661)
- Fix problem with not applying colors to boards [Github #3941](https://github.com/penpot/penpot/issues/3941)
- Fix problem with path editor undoing changes [Github #3998](https://github.com/penpot/penpot/issues/3998)
@@ -570,7 +1104,7 @@ time being.
- Selecting from Color Palette does not work for board when there is no existing fill [Taiga #6464](https://tree.taiga.io/project/penpot/issue/6464)
- Color thumbnails are consistently rounded in the inspect code mode [Taiga #5886](https://tree.taiga.io/project/penpot/issue/5886)
- Adding vector path points before first point of existing open path not working [Taiga #6593](https://tree.taiga.io/project/penpot/issue/6593)
- Some image formats include the extension when importing [Taiga #5485](https://tree.taiga.io/project/penpot/issue/5485)
- Some image formats include the extension when importing [Taiga #5485](https://tree.taiga.io/project/penpot/issue/5485)
- Gradient color tool doesn't work properly with flipped items [Taiga #6485](https://tree.taiga.io/project/penpot/issue/6485)
- [TEXT] Align options are not shown when several text are selected [Taiga #5948](https://tree.taiga.io/project/penpot/issue/5948)
- [VIEW MODE] Comments not working properly on multiple pages [Taiga #6281](https://tree.taiga.io/project/penpot/issue/6281)
@@ -614,7 +1148,7 @@ time being.
### :sparkles: New features
- Improve selected colors [Taiga #5805]( https://tree.taiga.io/project/penpot/us/5805)
- Improve selected colors [Taiga #5805](https://tree.taiga.io/project/penpot/us/5805)
### :bug: Bugs fixed
@@ -649,7 +1183,6 @@ time being.
- Fix deleted pages comments shown in right sidebar [Taiga #5648](https://tree.taiga.io/project/penpot/us/5648)
- Fix tooltip on toggle visibility and toggle lock buttons [Taiga #5141](https://tree.taiga.io/project/penpot/issue/5141)
## 1.19.1
### :bug: Bugs fixed
@@ -763,7 +1296,6 @@ time being.
- Update google fonts catalog (at 2023/07/06) [Taiga #5592](https://tree.taiga.io/project/penpot/issue/5592)
### :heart: Community contributions by (Thank you!)
- Update Typography palette order (by @akshay-gupta7) [Github #3156](https://github.com/penpot/penpot/pull/3156)
@@ -917,12 +1449,14 @@ time being.
- Fix problem with opacity in imported SVG's [Taiga #4923](https://tree.taiga.io/project/penpot/issue/4923)
### :heart: Community contributions by (Thank you!)
- To @ondrejkonec: for contributing to the code with:
- Refactor CSS variables [Github #2948](https://github.com/penpot/penpot/pull/2948)
## 1.17.3
### :bug: Bugs fixed
- Fix copy and paste very nested inside itself [Taiga #4848](https://tree.taiga.io/project/penpot/issue/4848)
- Fix custom fonts not rendered correctly [Taiga #4874](https://tree.taiga.io/project/penpot/issue/4874)
- Fix problem with shadows and blur on multiple selection
@@ -955,6 +1489,7 @@ time being.
## 1.17.1
### :bug: Bugs fixed
- Fix components groups items show the component name in list mode [Taiga #4770](https://tree.taiga.io/project/penpot/issue/4770)
- Fix typing CMD+Z on MacOS turns the cursor into a Zoom cursor [Taiga #4778](https://tree.taiga.io/project/penpot/issue/4778)
- Fix white space on small screens [Taiga #4774](https://tree.taiga.io/project/penpot/issue/4774)
@@ -1069,7 +1604,7 @@ time being.
### :boom: Breaking changes & Deprecations
- Removed the support for v2 internal file data blob format. This
- Removed the support for v2 internal file data blob format. This
version has never been documented nor set as default value so
technically this is not a breaking change because we are removing
a "private API".
@@ -1174,7 +1709,6 @@ time being.
- Fix when ungrouping, the items previously grouped should ALWAYS remain selected [Taiga #4064](https://tree.taiga.io/project/penpot/issue/4064)
- Change shortcut for "Clear undo" [#2219](https://github.com/penpot/penpot/issues/2219)
## 1.15.2-beta
### :bug: Bugs fixed
@@ -1258,6 +1792,7 @@ time being.
- Fix bringing complete file data when launching the export dialog [Taiga #4006](https://tree.taiga.io/project/penpot/issue/4006)
### :arrow_up: Deps updates
### :heart: Community contributions by (Thank you!)
## 1.14.2-beta
@@ -1298,10 +1833,10 @@ time being.
- Prototype connection should be under the rules [Taiga #3384](https://tree.taiga.io/project/penpot/issue/3384)
- Fix problem with empty text boxes events [Taiga #3627](https://tree.taiga.io/project/penpot/issue/3627)
## 1.13.5-beta
### :bug: Bugs fixed
- Fix orientation artboard preset not working with differently sized artboards [Taiga #3548](https://tree.taiga.io/project/penpot/issue/3548)
- Fix background on export arboards [Taiga #1991](https://tree.taiga.io/project/penpot/issue/1991)
@@ -1445,6 +1980,7 @@ time being.
- Fix problem when resizing a group with texts with auto-width/height [#3171](https://tree.taiga.io/project/penpot/issue/3171)
### :arrow_up: Deps updates
### :heart: Community contributions by (Thank you!)
## 1.12.4-beta
@@ -1462,7 +1998,7 @@ time being.
### :bug: Bugs fixed
- Fix issue with shift+select to deselect shapes [Taiga #3154](https://tree.taiga.io/project/penpot/issue/3154)
- Fix issue with drag-select shapes [Taiga #3165](https://tree.taiga.io/project/penpot/issue/3165)
- Fix issue with drag-select shapes [Taiga #3165](https://tree.taiga.io/project/penpot/issue/3165)
- Fix issue on password persistence after registration process on private instances
## 1.12.2-beta
@@ -1480,7 +2016,6 @@ time being.
- Fix length of names in sidebar [Taiga #2962](https://tree.taiga.io/project/penpot/issue/2962)
- Fix issues on loki integration
## 1.12.0-beta
### :boom: Breaking changes

3
CODE_OF_CONDUCT.md Normal file
View File

@@ -0,0 +1,3 @@
# Penpot's Code of Conduct
Check it at: https://help.penpot.app/contributing-guide/coc/

View File

@@ -1,62 +1,59 @@
# Contributing Guide #
Thank you for your interest in contributing to Penpot. This is a
generic guide that details how to contribute to Penpot in a way that
is efficient for everyone. If you want a specific documentation for
different parts of the platform, please refer to `docs/` directory.
generic guide that details how to contribute to the project in a way that
is efficient for everyone. If you are looking for specific documentation on
different parts of the platform, please refer to the `docs/` directory,
or the rendered version at the [Help Center](https://help.penpot.app/).
## Reporting Bugs ##
We are using [GitHub Issues](https://github.com/penpot/penpot/issues)
for our public bugs. We keep a close eye on this and try to make it
for our public bugs. We keep a close eye on them and try to make it
clear when we have an internal fix in progress. Before filing a new
task, try to make sure your problem doesn't already exist.
If you found a bug, please report it, as far as possible with:
If you found a bug, please report it, as far as possible, with:
- a detailed explanation of steps to reproduce the error
- a browser and the browser version used
- a dev tools console exception stack trace (if it is available)
- the browser and browser version used
- a dev tools console exception stack trace (if available)
If you found a bug that you consider better discuss in private (for
example: security bugs), consider first send an email to
If you found a bug which you think is better to discuss in private (for
example, security bugs), consider first sending an email to
`support@penpot.app`.
**We don't have formal bug bounty program for security reports; this
is an open source application and your contribution will be recognized
**We don't have a formal bug bounty program for security reports; this
is an open source application, and your contribution will be recognized
in the changelog.**
## Pull requests ##
## Pull Requests ##
If you want propose a change or bug fix with the Pull-Request system
firstly you should carefully read the **DCO** section and format your
commits accordingly.
If you want to propose a change or bug fix via a pull request (PR),
you should first carefully read the section **Developer's Certificate of
Origin**. You must also format your code and commits according to the
instructions below.
If you intend to fix a bug it's fine to submit a pull request right
away but we still recommend to file an issue detailing what you're
If you intend to fix a bug, it's fine to submit a pull request right
away, but we still recommend filing an issue detailing what you're
fixing. This is helpful in case we don't accept that specific fix but
want to keep track of the issue.
If you want to implement or start working in a new feature, please
open a **question** / **discussion** issue for it. No pull-request
will be accepted without previous chat about the changes,
independently if it is a new feature, already planned feature or small
quick win.
If you want to implement or start working on a new feature, please
open a **question*- / **discussion*- issue for it. No PR
will be accepted without a prior discussion about the changes,
whether it is a new feature, an already planned one, or a quick win.
If is going to be your first pull request, You can learn how from this
free video series:
https://egghead.io/courses/how-to-contribute-to-an-open-source-project-on-github
We will use the `easy fix` mark for tag for indicate issues that are
easy for beginners.
If it is your first PR, you can learn how to proceed from
[this free video
series](https://egghead.io/courses/how-to-contribute-to-an-open-source-project-on-github)
We use the `easy fix` tag to indicate issues that are appropriate for beginners.
## Commit Guidelines ##
We have very precise rules over how our git commit messages can be formatted.
We have very precise rules on how our git commit messages must be formatted.
The commit message format is:
@@ -71,34 +68,37 @@ The commit message format is:
Where type is:
- :bug: `:bug:` a commit that fixes a bug
- :sparkles: `:sparkles:` a commit that an improvement
- :tada: `:tada:` a commit with new feature
- :sparkles: `:sparkles:` a commit that adds an improvement
- :tada: `:tada:` a commit with a new feature
- :recycle: `:recycle:` a commit that introduces a refactor
- :lipstick: `:lipstick:` a commit with cosmetic changes
- :ambulance: `:ambulance:` a commit that fixes critical bug
- :ambulance: `:ambulance:` a commit that fixes a critical bug
- :books: `:books:` a commit that improves or adds documentation
- :construction: `:construction:`: a wip commit
- :construction: `:construction:` a WIP commit
- :boom: `:boom:` a commit with breaking changes
- :wrench: `:wrench:` a commit for config updates
- :zap: `:zap:` a commit with performance improvements
- :whale: `:whale:` a commit for docker related stuff
- :paperclip: `:paperclip:` a commit with other not relevant changes
- :arrow_up: `:arrow_up:` a commit with dependencies updates
- :arrow_down: `:arrow_down:` a commit with dependencies downgrades
- :whale: `:whale:` a commit for Docker-related stuff
- :paperclip: `:paperclip:` a commit with other non-relevant changes
- :arrow_up: `:arrow_up:` a commit with dependency updates
- :arrow_down: `:arrow_down:` a commit with dependency downgrades
- :fire: `:fire:` a commit that removes files or code
- :globe_with_meridians: `:globe_with_meridians:` a commit that adds or updates
translations
More info:
- https://gist.github.com/parmentf/035de27d6ed1dce0b36a
- https://gist.github.com/rxaviers/7360908
Each commit should have:
- A concise subject using imperative mood.
- The subject should have capitalized the first letter, without period
at the end and no larger than 65 characters.
- A concise subject using the imperative mood.
- The subject should capitalize the first letter, omit the period
at the end, and be no longer than 65 characters.
- A blank line between the subject line and the body.
- An entry on the CHANGES.md file if applicable, referencing the
github or taiga issue/user-story using the these same rules.
- An entry in the CHANGES.md file if applicable, referencing the
GitHub or Taiga issue/user story using these same rules.
Examples of good commit messages:
@@ -111,8 +111,30 @@ Examples of good commit messages:
- `:ambulance: Fix critical bug on user registration process`
- `:tada: Add new approach for user registration`
## Formatting and Linting ##
## Code of conduct ##
You will want to make sure your code is formatted and linted before submitting
a PR. We use [cljfmt](https://github.com/weavejester/cljfmt) and
[clj-kondo](https://github.com/clj-kondo/clj-kondo) for this. After installing
them on your system, you can run them with:
```bash
# Check formatting
yarn fmt:clj:check
# Check and fix formatting
yarn fmt:clj
# Run the linter
yarn lint:clj
```
There are more choices in `package.json`.
Ideally, you should run these commands as git pre-commit hooks. A convenient way
of defining them is to use [Husky](https://typicode.github.io/husky/#/).
## Code of Conduct ##
As contributors and maintainers of this project, we pledge to respect
all people who contribute through reporting issues, posting feature
@@ -132,11 +154,11 @@ unprofessional conduct.
Project maintainers have the right and responsibility to remove, edit,
or reject comments, commits, code, wiki edits, issues, and other
contributions that are not aligned to this Code of Conduct. Project
contributions that are not aligned with this Code of Conduct. Project
maintainers who do not follow the Code of Conduct may be removed from
the project team.
This code of conduct applies both within project spaces and in public
This Code of Conduct applies both within project spaces and in public
spaces when an individual is representing the project or its
community.
@@ -145,12 +167,11 @@ may be reported by opening an issue or contacting one or more of the
project maintainers.
This Code of Conduct is adapted from the Contributor Covenant, version
1.1.0, available from http://contributor-covenant.org/version/1/1/0/
1.1.0, available from [http://contributor-covenant.org/version/1/1/0/](http://contributor-covenant.org/version/1/1/0/)
## Developer's Certificate of Origin (DCO)
## Developer's Certificate of Origin (DCO) ##
By submitting code you are agree and can certify the below:
By submitting code you agree to and can certify the following:
Developer's Certificate of Origin 1.1
@@ -178,13 +199,15 @@ By submitting code you are agree and can certify the below:
maintained indefinitely and may be redistributed consistent with
this project or the open source license(s) involved.
Then, all your code patches (**documentation are excluded**) should
Then, all your code patches (**documentation is excluded**) should
contain a sign-off at the end of the patch/commit description body. It
can be automatically added on adding `-s` parameter to `git commit`.
can be automatically added by adding the `-s` parameter to `git commit`.
This is an example of the aspect of the line:
This is an example of what the line should look like:
Signed-off-by: Andrey Antukh <niwi@niwi.nz>
```
Signed-off-by: Andrey Antukh <niwi@niwi.nz>
```
Please, use your real name (sorry, no pseudonyms or anonymous
contributions are allowed).

View File

@@ -16,36 +16,38 @@
</p>
<p align="center">
<a href="https://penpot.app/"><b>Website</b></a> •
<a href="https://help.penpot.app/technical-guide/getting-started/"><b>Getting Started</b></a> •
<a href="https://help.penpot.app/user-guide/"><b>User Guide</b></a> •
<a href="https://help.penpot.app/user-guide/introduction/info/"><b>Tutorials & Info</b></a> •
<a href="https://penpot.app/"><b>Website</b></a> •
<a href="https://help.penpot.app/user-guide/"><b>User Guide</b></a> •
<a href="https://penpot.app/learning-center"><b>Learning Center</b></a> •
<a href="https://community.penpot.app/"><b>Community</b></a>
</p>
<p align="center">
<a href="https://www.youtube.com/@Penpot"><b>Youtube</b></a> •
<a href="https://peertube.kaleidos.net/a/penpot_app/video-channels"><b>Peertube</b></a> •
<a href="https://www.linkedin.com/company/penpot/"><b>Linkedin</b></a> •
<a href="https://instagram.com/penpot.app"><b>Instagram</b></a> •
<a href="https://fosstodon.org/@penpot/"><b>Mastodon</b></a> •
<a href="https://www.youtube.com/@Penpot"><b>Youtube</b></a> •
<a href="https://peertube.kaleidos.net/a/penpot_app/video-channels"><b>Peertube</b></a> •
<a href="https://www.linkedin.com/company/penpot/"><b>Linkedin</b></a> •
<a href="https://instagram.com/penpot.app"><b>Instagram</b></a> •
<a href="https://fosstodon.org/@penpot/"><b>Mastodon</b></a> •
<a href="https://bsky.app/profile/penpot.app"><b>Bluesky</b></a> •
<a href="https://twitter.com/penpotapp"><b>X</b></a>
</p>
<br />
[Penpot video](https://github.com/penpot/penpot/assets/5446186/b8ad0764-585e-4ddc-b098-9b4090d337cc)
[Penpot video](https://github.com/user-attachments/assets/7c67fd7c-04d3-4c9b-88ec-b6f5e23f8332
)
<br />
Penpot is the first **open-source** design tool for design and code collaboration. Designers can create stunning designs, interactive prototypes, design systems at scale, while developers enjoy ready-to-use code and make their workflow easy and fast. And all of this with no handoff drama.
Penpot is available on browser and [self host](https://penpot.app/self-host). Its web-based and works with open standards (SVG, CSS and HTML). And last but not least, its free!
Available on browser or self-hosted, Penpot works with open standards like SVG, CSS, HTML and JSON, and its free!
Penpots latest [huge release 2.0](https://penpot.app/dev-diaries), takes the platform to a whole new level. This update introduces the ground-breaking [CSS Grid Layout feature](https://penpot.app/penpot-2.0), a complete UI redesign, a new Components system, and much more. Plus, it's faster and more accessible.
The latest updates take Penpot even further. Its the first design tool to integrate native [design tokens](https://penpot.dev/collaboration/design-tokens)—a single source of truth to improve efficiency and collaboration between product design and development.
With the [huge 2.0 release](https://penpot.app/dev-diaries), Penpot took the platform to a whole new level. This update introduces the ground-breaking [CSS Grid Layout feature](https://penpot.app/penpot-2.0), a complete UI redesign, a new Components system, and much more.
For organizations that need extra service for its teams, [get in touch](https://cal.com/team/penpot/talk-to-us)
🎇 **Penpot Fest** is our design, code & Open Source event. Check out the highlights from [Penpot Fest 2023 edition](https://www.youtube.com/watch?v=sOpLZaK5mDc)!
🎇 Design, code, and Open Source meet at [Penpot Fest](https://penpot.app/penpotfest)! Be part of the 2025 edition in Madrid, Spain, on October 9-10.
## Table of contents ##
@@ -61,7 +63,7 @@ Penpots latest [huge release 2.0](https://penpot.app/dev-diaries), takes the
Penpot expresses designs as code. Designers can do their best work and see it will be beautifully implemented by developers in a two-way collaboration.
### Plugin system ###
[Penpot plugins](https://penpot.app/penpothub/plugins) let you expand the platform's capabilities, give you the flexibility to integrate it with other apps, and design custom solutions.
[Penpot plugins](https://penpot.app/penpothub/plugins) let you expand the platform's capabilities, give you the flexibility to integrate it with other apps, and design custom solutions.
### Designed for developers ###
Penpot was built to serve both designers and developers and create a fluid design-code process. You have the choice to enjoy real-time collaboration or play "solo".
@@ -75,23 +77,23 @@ Provide your team or organization with a completely owned collaborative design t
### Integrations ###
Penpot offers integration into the development toolchain, thanks to its support for webhooks and an API accessible through access tokens.
### Whats great for design ###
With Penpot you can design libraries to share and reuse; turn design elements into components and tokens to allow reusability and scalability; and build realistic user flows and interactions.
### Building Design Systems: design tokens, components and variants ###
Penpot brings design systems to code-minded teams: a single source of truth with native Design Tokens, Components, and Variants for scalable, reusable, and consistent UI across projects and platforms.
<br />
<p align="center">
<img src="https://img.plasmic.app/img-optimizer/v1/img?src=https%3A%2F%2Fimg.plasmic.app%2Fimg-optimizer%2Fv1%2Fimg%2F9dd677c36afb477e9666ccd1d3f009ad.png" alt="Open Source" style="width: 65%;">
<img src="https://github.com/user-attachments/assets/cce75ad6-f783-473f-8803-da9eb8255fef">
</p>
<br />
## Getting started ##
### Install with Elestio ###
Penpot is the only design & prototype platform that is deployment agnostic. You can use it or deploy it anywhere.
Penpot is the only design & prototype platform that is deployment agnostic. You can use it in our [SAAS](https://design.penpot.app) or deploy it anywhere.
Learn how to install it with Elestio and Docker, or other options on [our website](https://penpot.app/self-host).
Learn how to install it with Docker, Kubernetes, Elestio or other options on [our website](https://penpot.app/self-host).
<br />
<p align="center">
@@ -123,15 +125,21 @@ You will find the following categories:
</p>
<br />
### Code of Conduct ###
Anyone who contributes to Penpot, whether through code, in the community, or at an event, must adhere to the
[code of conduct](https://help.penpot.app/contributing-guide/coc/) and foster a positive and safe environment.
## Contributing ##
Any contribution will make a difference to improve Penpot. How can you get involved?
Any contribution will make a difference to improve Penpot. How can you get involved?
Choose your way:
Choose your way:
- Create and [share Libraries & Templates](https://penpot.app/libraries-templates.html) that will be helpful for the community
- Invite your [team to join](https://design.penpot.app/#/auth/register)
- Star this repo and follow us on Social Media: [Mastodon](https://fosstodon.org/@penpot/), [Youtube](https://www.youtube.com/c/Penpot), [Instagram](https://instagram.com/penpot.app), [Linkedin](https://www.linkedin.com/company/penpotdesign), [Peertube](https://peertube.kaleidos.net/a/penpot_app) and [X](https://twitter.com/penpotapp).
- Give this repo a star and follow us on Social Media: [Mastodon](https://fosstodon.org/@penpot/), [Youtube](https://www.youtube.com/c/Penpot), [Instagram](https://instagram.com/penpot.app), [Linkedin](https://www.linkedin.com/company/penpotdesign), [Peertube](https://peertube.kaleidos.net/a/penpot_app), [X](https://twitter.com/penpotapp) and [BlueSky](https://bsky.app/profile/penpot.app)
- Participate in the [Community](https://community.penpot.app/) space by asking and answering questions; reacting to others articles; opening your own conversations and following along on decisions affecting the project.
- Report bugs with our easy [guide for bugs hunting](https://help.penpot.app/contributing-guide/reporting-bugs/) or [GitHub issues](https://github.com/penpot/penpot/issues)
- Become a [translator](https://help.penpot.app/contributing-guide/translations)

View File

@@ -3,10 +3,10 @@
:deps
{penpot/common {:local/root "../common"}
org.clojure/clojure {:mvn/version "1.12.0"}
org.clojure/clojure {:mvn/version "1.12.2"}
org.clojure/tools.namespace {:mvn/version "1.5.0"}
com.github.luben/zstd-jni {:mvn/version "1.5.6-9"}
com.github.luben/zstd-jni {:mvn/version "1.5.7-4"}
io.prometheus/simpleclient {:mvn/version "0.16.0"}
io.prometheus/simpleclient_hotspot {:mvn/version "0.16.0"}
@@ -17,34 +17,41 @@
io.prometheus/simpleclient_httpserver {:mvn/version "0.16.0"}
io.lettuce/lettuce-core {:mvn/version "6.5.2.RELEASE"}
io.lettuce/lettuce-core {:mvn/version "6.8.1.RELEASE"}
;; Minimal dependencies required by lettuce, we need to include them
;; explicitly because clojure dependency management does not support
;; yet the BOM format.
io.micrometer/micrometer-core {:mvn/version "1.14.2"}
io.micrometer/micrometer-observation {:mvn/version "1.14.2"}
java-http-clj/java-http-clj {:mvn/version "0.4.3"}
com.google.guava/guava {:mvn/version "33.4.8-jre"}
funcool/yetti
{:git/tag "v11.4"
:git/sha "ce50d42"
{:git/tag "v11.8"
:git/sha "1d1b33f"
:git/url "https://github.com/funcool/yetti.git"
:exclusions [org.slf4j/slf4j-api]}
com.github.seancorfield/next.jdbc
{:mvn/version "1.3.994"}
metosin/reitit-core {:mvn/version "0.7.2"}
nrepl/nrepl {:mvn/version "1.3.1"}
cider/cider-nrepl {:mvn/version "0.52.0"}
{:mvn/version "1.3.1070"}
org.postgresql/postgresql {:mvn/version "42.7.5"}
org.xerial/sqlite-jdbc {:mvn/version "3.48.0.0"}
metosin/reitit-core {:mvn/version "0.9.1"}
nrepl/nrepl {:mvn/version "1.4.0"}
com.zaxxer/HikariCP {:mvn/version "6.2.1"}
org.postgresql/postgresql {:mvn/version "42.7.7"}
org.xerial/sqlite-jdbc {:mvn/version "3.50.3.0"}
com.zaxxer/HikariCP {:mvn/version "7.0.2"}
io.whitfin/siphash {:mvn/version "2.0.0"}
buddy/buddy-hashers {:mvn/version "2.0.167"}
buddy/buddy-sign {:mvn/version "3.6.1-359"}
com.github.ben-manes.caffeine/caffeine {:mvn/version "3.2.0"}
com.github.ben-manes.caffeine/caffeine {:mvn/version "3.2.2"}
org.jsoup/jsoup {:mvn/version "1.18.3"}
org.jsoup/jsoup {:mvn/version "1.21.2"}
org.im4java/im4java
{:git/tag "1.4.0-penpot-2"
:git/sha "e2b3e16"
@@ -54,12 +61,12 @@
org.clojars.pntblnk/clj-ldap {:mvn/version "0.0.17"}
dawran6/emoji {:mvn/version "0.1.5"}
markdown-clj/markdown-clj {:mvn/version "1.12.2"}
dawran6/emoji {:mvn/version "0.2.0"}
markdown-clj/markdown-clj {:mvn/version "1.12.4"}
;; Pretty Print specs
pretty-spec/pretty-spec {:mvn/version "0.1.4"}
software.amazon.awssdk/s3 {:mvn/version "2.28.26"}}
software.amazon.awssdk/s3 {:mvn/version "2.33.10"}}
:paths ["src" "resources" "target/classes"]
:aliases
@@ -74,12 +81,14 @@
:build
{:extra-deps
{io.github.clojure/tools.build {:git/tag "v0.10.6" :git/sha "52cf7d6"}}
{io.github.clojure/tools.build {:mvn/version "0.10.10"}}
:ns-default build}
:test
{:main-opts ["-m" "kaocha.runner"]
:jvm-opts ["-Dlog4j2.configurationFile=log4j2-devenv-repl.xml"]
:jvm-opts ["-Dlog4j2.configurationFile=log4j2-devenv-repl.xml"
"--sun-misc-unsafe-memory-access=allow"
"--enable-native-access=ALL-UNNAMED"]
:extra-deps {lambdaisland/kaocha {:mvn/version "1.91.1392"}}}
:outdated

View File

@@ -6,12 +6,14 @@
(ns user
(:require
[app.binfile.common :as bfc]
[app.common.data :as d]
[app.common.debug :as debug]
[app.common.exceptions :as ex]
[app.common.files.helpers :as cfh]
[app.common.fressian :as fres]
[app.common.geom.matrix :as gmt]
[app.common.json :as json]
[app.common.logging :as l]
[app.common.perf :as perf]
[app.common.pprint :as pp]
@@ -19,20 +21,22 @@
[app.common.schema.desc-js-like :as smdj]
[app.common.schema.desc-native :as smdn]
[app.common.schema.generators :as sg]
[app.common.schema.openapi :as oapi]
[app.common.spec :as us]
[app.common.json :as json]
[app.common.time :as ct]
[app.common.transit :as t]
[app.common.types.file :as ctf]
[app.common.uuid :as uuid]
[app.common.uri :as u]
[app.config :as cf]
[app.db :as db]
[app.main :as main]
[app.srepl.helpers :as srepl.helpers]
[app.srepl.main :as srepl]
[app.srepl.helpers :as h]
[app.srepl.main :refer :all]
[app.util.blob :as blob]
[app.util.time :as dt]
[clj-async-profiler.core :as prof]
[clojure.contrib.humanize :as hum]
[clojure.datafy :refer [datafy]]
[clojure.java.io :as io]
[clojure.pprint :refer [pprint print-table]]
[clojure.repl :refer :all]

View File

@@ -4,7 +4,7 @@
"license": "MPL-2.0",
"author": "Kaleidos INC",
"private": true,
"packageManager": "yarn@4.6.0+sha512.5383cc12567a95f1d668fbe762dfe0075c595b4bfff433be478dbbe24e05251a8e8c3eb992a986667c1d53b6c3a9c85b8398c35a960587fbd9fa3a0915406728",
"packageManager": "yarn@4.9.2+sha512.1fc009bc09d13cfd0e19efa44cbfc2b9cf6ca61482725eb35bbc5e257e093ebf4130db6dfe15d604ff4b79efd8e1e8e99b25fa7d0a6197c9f9826358d4d65c3c",
"repository": {
"type": "git",
"url": "https://github.com/penpot/penpot"

View File

@@ -193,7 +193,7 @@
<td align="left" style="font-size:0px;padding:10px 25px;word-break:break-word;">
<div
style="font-family:Source Sans Pro, sans-serif;font-size:16px;line-height:150%;text-align:left;color:#000000;">
Click to the link below to confirm the change:</div>
Click the link below to confirm the change.</div>
</td>
</tr>
<tr>
@@ -217,8 +217,7 @@
<td align="left" style="font-size:0px;padding:10px 25px;word-break:break-word;">
<div
style="font-family:Source Sans Pro, sans-serif;font-size:16px;line-height:150%;text-align:left;color:#000000;">
If you received this email by mistake, please consider changing your password for security
reasons.</div>
If you did not request this change, consider changing your password for security reasons.</div>
</td>
</tr>
<tr>

View File

@@ -2,12 +2,11 @@ Hello {{name|abbreviate:25}}!
We received a request to change your current email to {{ pending-email }}.
Click to the link below to confirm the change:
Click the link below to confirm the change.
{{ public-uri }}/#/auth/verify-token?token={{token}}
If you received this email by mistake, please consider changing your password
for security reasons.
If you did not request this change, consider changing your password for security reasons.
Enjoy!
The Penpot team.

View File

@@ -8,38 +8,41 @@
<body>
<p>
<strong>Feedback from:</strong><br />
{% if profile %}
<span>
<span>Name: </span>
<span><code>{{profile.fullname|abbreviate:25}}</code></span>
</span>
<br />
<span>
<span>Email: </span>
<span>{{profile.email}}</span>
</span>
<br />
<span>
<span>ID: </span>
<span><code>{{profile.id}}</code></span>
</span>
{% else %}
<span>
<span>Email: </span>
<span>{{profile.email}}</span>
</span>
{% endif %}
<span>
<span>Name: </span>
<span><code>{{profile.fullname|abbreviate:25}}</code></span>
</span>
<br />
<span>
<span>Email: </span>
<span>{{profile.email}}</span>
</span>
<br />
<span>
<span>ID: </span>
<span><code>{{profile.id}}</code></span>
</span>
</p>
<p>
<strong>Subject:</strong><br />
<span>{{subject|abbreviate:300}}</span>
<span>{{feedback-subject|abbreviate:300}}</span>
</p>
<p>
<strong>Type:</strong><br />
<span>{{feedback-type|abbreviate:300}}</span>
</p>
{% if feedback-error-href %}
<p>
<strong>Error HREF:</strong><br />
<span>{{feedback-error-href|abbreviate:500}}</span>
</p>
{% endif %}
<p>
<strong>Message:</strong><br />
{{content|linebreaks-br|safe}}
{{feedback-content|linebreaks-br}}
</p>
</body>
</html>

View File

@@ -1 +1 @@
[PENPOT FEEDBACK]: {{subject}}
[PENPOT FEEDBACK]: {{feedback-subject}}

View File

@@ -1,9 +1,11 @@
{% if profile %}
Feedback profile: {{profile.fullname}} <{{profile.email}}> / {{profile.id}}
{% else %}
Feedback from: {{email}}
{% endif %}
From: {{profile.fullname}} <{{profile.email}}> / {{profile.id}}
Subject: {{feedback-subject}}
Type: {{feedback-type}}
Subject: {{subject}}
{% if feedback-error-href %}
HREF: {{feedback-error-href}}
{% endif -%}
{{content}}
Message:
{{feedback-content}}

View File

@@ -1 +1 @@
Invitation to join {{team}}
{{invited-by|abbreviate:25}} has invited you to join the team “{{ team|abbreviate:25 }}

View File

@@ -13,7 +13,7 @@ This will automatically include {{requested-by|abbreviate:25}} in the team, so t
Click the link below to provide team access:
{{ public-uri }}/#/dashboard/members?team-id{{team-id}}&invite-email={{requested-by-email|urlescape}}
{{ public-uri }}/#/dashboard/members?team-id={{team-id}}&invite-email={{requested-by-email|urlescape}}

View File

@@ -1,4 +1,10 @@
[{:id "wireframing-kit"
[{:id "tokens-starter-kit"
:name "Design tokens starter kit"
:file-uri "https://github.com/penpot/penpot-files/raw/refs/heads/main/Tokens%20starter%20kit.penpot"}
{:id "penpot-design-system"
:name "Penpot Design System | Pencil"
:file-uri "https://github.com/penpot/penpot-files/raw/refs/heads/main/Pencil-Penpot-Design-System.penpot"}
{:id "wireframing-kit"
:name "Wireframe library"
:file-uri "https://github.com/penpot/penpot-files/raw/refs/heads/main/Wireframing%20kit%20v1.1.penpot"}
{:id "prototype-examples"
@@ -7,9 +13,6 @@
{:id "plants-app"
:name "UI mockup example"
:file-uri "https://github.com/penpot/penpot-files/raw/main/Plants-app.penpot"}
{:id "penpot-design-system"
:name "Design system example"
:file-uri "https://github.com/penpot/penpot-files/raw/refs/heads/main/Penpot%20-%20Design%20System%20v2.1.penpot"}
{:id "tutorial-for-beginners"
:name "Tutorial for beginners"
:file-uri "https://github.com/penpot/penpot-files/raw/main/tutorial-for-beginners.penpot"}

View File

@@ -4,7 +4,7 @@
<meta charset="utf-8" />
<meta name="robots" content="noindex,nofollow">
<meta http-equiv="x-ua-compatible" content="ie=edge" />
<title>Builtin API Documentation - Penpot</title>
<title>{{label|upper}} API Documentation</title>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
@@ -19,7 +19,7 @@
<body>
<main>
<header>
<h1>Penpot API Documentation (v{{version}})</h1>
<h1>{{label|upper}}: API Documentation (v{{version}})</h1>
<small class="menu">
[
<nav>
@@ -31,9 +31,10 @@
</header>
<section class="doc-content">
<h2>INTRODUCTION</h2>
<p>This documentation is intended to be a general overview of the penpot RPC API.
If you prefer, you can use <a href="/api/openapi.json">OpenAPI</a>
and/or <a href="/api/openapi">SwaggerUI</a> as alternative.</p>
<p>This documentation is intended to be a general overview of
the {{label}} API. If you prefer, you can
use <a href="{{openapi}}">Swagger/OpenAPI</a> as
alternative.</p>
<h2>GENERAL NOTES</h2>
@@ -43,7 +44,7 @@
that starts with <b>get-</b> in the name, can use GET HTTP
method which in many cases benefits from the HTTP cache.</p>
{% block auth-section %}
<h3>Authentication</h3>
<p>The penpot backend right now offers two way for authenticate the request:
<b>cookies</b> (the same mechanism that we use ourselves on accessing the API from the
@@ -56,9 +57,10 @@
<p>The access token can be obtained on the appropriate section on profile settings
and it should be provided using <b>`Authorization`</b> header with <b>`Token
&lt;token-string&gt;`</b> value.</p>
{% endblock %}
<h3>Content Negotiation</h3>
<p>The penpot API by default operates indistinctly with: <b>`application/json`</b>
<p>This API operates indistinctly with: <b>`application/json`</b>
and <b>`application/transit+json`</b> content types. You should specify the
desired content-type on the <b>`Accept`</b> header, the transit encoding is used
by default.</p>
@@ -75,13 +77,16 @@
standard <a href="https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API">Fetch
API</a></p>
{% block limits-section %}
<h3>Limits</h3>
<p>The rate limit work per user basis (this means that different api keys share
the same rate limit). For now the limits are not documented because we are
studying and analyzing the data. As a general rule, it should not be abused, if an
abusive use is detected, we will proceed to block the user's access to the
API.</p>
{% endblock %}
{% block webhooks-section %}
<h3>Webhooks</h3>
<p>All methods that emit webhook events are marked with flag <b>WEBHOOK</b>, the
data structure defined on each method represents the <i>payload</i> of the
@@ -97,9 +102,11 @@
"profileId": "db601c95-045f-808b-8002-361312e63531"
}
</pre>
{% endblock %}
</section>
<section class="rpc-doc-content">
<h2>RPC METHODS REFERENCE:</h2>
<h2>METHODS REFERENCE:</h2>
<ul class="rpc-items">
{% for item in methods %}
{% include "app/templates/api-doc-entry.tmpl" with item=item %}

View File

@@ -17,38 +17,6 @@ Debug Main Page
<desc><a href="/dbg/error">CLICK HERE TO SEE THE ERROR REPORTS</a> </desc>
</fieldset>
<fieldset>
<legend>Download file data:</legend>
<desc>Given an FILE-ID, downloads the file data as file. The file data is encoded using transit.</desc>
<form method="get" action="/dbg/file/data">
<div class="row">
<input type="text" style="width:300px" name="file-id" placeholder="file-id" />
</div>
<div class="row">
<input type="submit" name="download" value="Download" />
<input type="submit" name="clone" value="Clone" />
</div>
</form>
</fieldset>
<fieldset>
<legend>Upload File Data:</legend>
<desc>Create a new file on your draft projects using the file downloaded from the previous section.</desc>
<form method="post" enctype="multipart/form-data" action="/dbg/file/data">
<div class="row">
<input type="file" name="file" value="" />
</div>
<div class="row">
<label>Import with same id?</label>
<input type="checkbox" name="reuseid" />
</div>
<div class="row">
<input type="submit" value="Upload" />
</div>
</form>
</fieldset>
<fieldset>
<legend>Profile Management</legend>
<form method="post" action="/dbg/actions/resend-email-verification">
@@ -77,10 +45,88 @@ Debug Main Page
</form>
</fieldset>
<fieldset>
<legend>VIRTUAL CLOCK</legend>
<desc>
<p>
CURRENT CLOCK: <b>{{current-clock}}</b>
<br />
CURRENT OFFSET: <b>{{current-offset}}</b>
<br />
CURRENT TIME: <b>{{current-time}}</b>
</p>
<p>Examples: 3h, -7h, 24h (allowed suffixes: h, s)</p>
</desc>
<form method="post" action="/dbg/actions/set-virtual-clock">
<div class="row">
<input type="text" name="offset" placeholder="3h" value="" />
</div>
<div class="row">
<label for="force-verify">Are you sure?</label>
<input id="force-verify" type="checkbox" name="force" />
<br />
<small>
This is a just a security double check for prevent non intentional submits.
</small>
</div>
<div class="row">
<input type="submit" name="submit" value="Submit" />
<input type="submit" name="reset" value="Reset" />
</div>
</form>
</fieldset>
</section>
<section class="widget">
<fieldset>
<legend>Download RAW file data:</legend>
<desc>Given an FILE-ID, downloads the file AS-IS (no validation
checks, just exports the file data and related objects in raw)
<br/>
<br/>
<b>WARNING: this operation does not performs any checks</b>
</desc>
<form method="get" action="/dbg/actions/file-raw-export-import">
<div class="row">
<input type="text" style="width:300px" name="file-id" placeholder="file-id" />
</div>
<div class="row">
<input type="submit" name="download" value="Download" />
<input type="submit" name="clone" value="Clone" />
</div>
</form>
</fieldset>
<fieldset>
<legend>Upload File Data:</legend>
<desc>Create a new file on your draft projects using the file downloaded from the previous section.
<br/>
<br/>
<b>WARNING: this operation does not performs any checks</b>
</desc>
<form method="post" enctype="multipart/form-data" action="/dbg/actions/file-raw-export-import">
<div class="row">
<input type="file" name="file" value="" />
</div>
<div class="row">
<label>Import with same id?</label>
<input type="checkbox" name="reuseid" />
</div>
<div class="row">
<input type="submit" value="Upload" />
</div>
</form>
</fieldset>
</section>
<section class="widget">
<fieldset>
<legend>Export binfile:</legend>
@@ -88,7 +134,7 @@ Debug Main Page
the related libraries in a single custom formatted binary
file.</desc>
<form method="get" action="/dbg/file/export">
<form method="get" action="/dbg/actions/file-export">
<div class="row set-of-inputs">
<input type="text" style="width:300px" name="file-ids" placeholder="file-id" />
<input type="text" style="width:300px" name="file-ids" placeholder="file-id" />
@@ -116,7 +162,7 @@ Debug Main Page
<legend>Import binfile:</legend>
<desc>Import penpot file in binary format.</desc>
<form method="post" enctype="multipart/form-data" action="/dbg/file/import">
<form method="post" enctype="multipart/form-data" action="/dbg/actions/file-import">
<div class="row">
<input type="file" name="file" value="" />
</div>
@@ -130,15 +176,36 @@ Debug Main Page
<section class="widget">
<fieldset>
<legend>Reset file version</legend>
<desc>Allows reset file data version to a specific number/</desc>
<form method="post" action="/dbg/actions/reset-file-version">
<legend>Feature Flags for Team</legend>
<desc>Add a feature flag to a team</desc>
<form method="post" action="/dbg/actions/handle-team-features">
<div class="row">
<input type="text" style="width:300px" name="file-id" placeholder="file-id" />
<input type="text" style="width:300px" name="team-id" placeholder="team-id" />
</div>
<div class="row">
<input type="number" style="width:100px" name="version" placeholder="version" value="32" />
<select type="text" style="width:100px" name="feature">
{% for feature in supported-features %}
<option value="{{feature}}">{{feature}}</option>
{% endfor %}
</select>
</div>
<div class="row">
<select style="width:100px" name="action">
<option value="">Action...</option>
<option value="show">Show</option>
<option value="enable">Enable</option>
<option value="disable">Disable</option>
</select>
</div>
<div class="row">
<label for="check-feature">Skip feature check</label>
<input id="check-feature" type="checkbox" name="skip-check" />
<br />
<small>
Do not check if the feature is supported
</small>
</div>
<div class="row">
@@ -150,7 +217,6 @@ Debug Main Page
</small>
</div>
<div class="row">
<input type="submit" value="Submit" />
</div>

View File

@@ -7,7 +7,9 @@ penpot - error list
{% block content %}
<nav>
<div class="title">
<h1>Error reports (last 200)</h1>
<h1>Error reports (last 200)
<a href="/dbg">[GO BACK]</a>
</h1>
</div>
</nav>
<main class="horizontal-list">

View File

@@ -0,0 +1 @@
{% extends "app/templates/api-doc.tmpl" %}

View File

@@ -0,0 +1,10 @@
{% extends "app/templates/api-doc.tmpl" %}
{% block auth-section %}
{% endblock %}
{% block limits-section %}
{% endblock %}
{% block webhooks-section %}
{% endblock %}

View File

@@ -7,7 +7,7 @@
name="description"
content="SwaggerUI"
/>
<title>PENPOT Swagger UI</title>
<title>{{label|upper}} API</title>
<style>{{swagger-css|safe}}</style>
</head>
<body>
@@ -16,7 +16,7 @@
<script>
window.onload = () => {
window.ui = SwaggerUIBundle({
url: '{{public-uri}}/api/openapi.json',
url: '{{uri}}',
dom_id: '#swagger-ui',
presets: [
SwaggerUIBundle.presets.apis,

View File

@@ -25,8 +25,7 @@
<Logger name="app.storage.tmp" level="info" />
<Logger name="app.worker" level="trace" />
<Logger name="app.msgbus" level="info" />
<Logger name="app.http.websocket" level="info" />
<Logger name="app.http.sse" level="info" />
<Logger name="app.http" level="info" />
<Logger name="app.util.websocket" level="info" />
<Logger name="app.redis" level="info" />
<Logger name="app.rpc.rlimit" level="info" />

View File

@@ -25,8 +25,7 @@
<Logger name="app.storage.tmp" level="info" />
<Logger name="app.worker" level="trace" />
<Logger name="app.msgbus" level="info" />
<Logger name="app.http.websocket" level="info" />
<Logger name="app.http.sse" level="info" />
<Logger name="app.http" level="info" />
<Logger name="app.util.websocket" level="info" />
<Logger name="app.redis" level="info" />
<Logger name="app.rpc.rlimit" level="info" />

84
backend/scripts/_env Normal file
View File

@@ -0,0 +1,84 @@
#!/usr/bin/env bash
export PENPOT_MANAGEMENT_API_KEY=super-secret-management-api-key
export PENPOT_SECRET_KEY=super-secret-devenv-key
export PENPOT_HOST=devenv
export PENPOT_PUBLIC_URI=https://localhost:3449
export PENPOT_FLAGS="\
$PENPOT_FLAGS \
enable-login-with-password
disable-login-with-ldap \
disable-login-with-oidc \
disable-login-with-google \
disable-login-with-github \
disable-login-with-gitlab \
enable-backend-worker \
enable-backend-asserts \
disable-feature-fdata-pointer-map \
enable-feature-fdata-objects-map \
enable-audit-log \
enable-transit-readable-response \
enable-demo-users \
enable-user-feedback \
disable-secure-session-cookies \
enable-smtp \
enable-prepl-server \
enable-urepl-server \
enable-rpc-climit \
enable-rpc-rlimit \
enable-quotes \
enable-soft-rpc-rlimit \
enable-auto-file-snapshot \
enable-webhooks \
enable-access-tokens \
disable-tiered-file-data-storage \
enable-file-validation \
enable-file-schema-validation \
enable-redis-cache \
enable-subscriptions";
# Default deletion delay for devenv
export PENPOT_DELETION_DELAY="24h"
# Setup default upload media file size to 100MiB
export PENPOT_MEDIA_MAX_FILE_SIZE=104857600
# Setup default multipart upload size to 300MiB
export PENPOT_HTTP_SERVER_MAX_MULTIPART_BODY_SIZE=314572800
export PENPOT_USER_FEEDBACK_DESTINATION="support@example.com"
export AWS_ACCESS_KEY_ID=penpot-devenv
export AWS_SECRET_ACCESS_KEY=penpot-devenv
export PENPOT_OBJECTS_STORAGE_BACKEND=s3
export PENPOT_OBJECTS_STORAGE_S3_ENDPOINT=http://minio:9000
export PENPOT_OBJECTS_STORAGE_S3_BUCKET=penpot
export JAVA_OPTS="\
-Djava.util.logging.manager=org.apache.logging.log4j.jul.LogManager \
-Djdk.attach.allowAttachSelf \
-Dlog4j2.configurationFile=log4j2-devenv.xml \
-Djdk.tracePinnedThreads=full \
-Dim4java.useV7=true \
-XX:+UnlockExperimentalVMOptions \
-XX:+UseShenandoahGC \
-XX:+UseCompactObjectHeaders \
-XX:ShenandoahGCMode=generational \
-XX:-OmitStackTraceInFastThrow \
--sun-misc-unsafe-memory-access=allow \
--enable-preview \
--enable-native-access=ALL-UNNAMED";
function setup_minio() {
# Initialize MINIO config
mc alias set penpot-s3/ http://minio:9000 minioadmin minioadmin -q
mc admin user add penpot-s3 penpot-devenv penpot-devenv -q
mc admin user info penpot-s3 penpot-devenv |grep -F -q "readwrite"
if [ "$?" = "1" ]; then
mc admin policy attach penpot-s3 readwrite --user=penpot-devenv -q
fi
mc mb penpot-s3/penpot -p -q
}

View File

@@ -35,40 +35,35 @@ def get_prepl_conninfo():
return host, port
def send_eval(expr):
def send(data):
host, port = get_prepl_conninfo()
with socket.create_connection((host, port)) as s:
f = s.makefile(mode="rw")
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
s.connect((host, port))
s.send(expr.encode("utf-8"))
s.send(b":repl/quit\n\n")
json.dump(data, f)
f.write("\n")
f.flush()
with s.makefile() as f:
while True:
line = f.readline()
result = json.loads(line)
tag = result.get("tag", None)
if tag == "ret":
return result.get("val", None), result.get("exception", None)
elif tag == "out":
print(result.get("val"), end="")
else:
raise RuntimeError("unexpected response from PREPL")
while True:
line = f.readline()
result = json.loads(line)
tag = result.get("tag", None)
def encode(val):
return json.dumps(json.dumps(val))
if tag == "ret":
return result.get("val", None), result.get("err", None)
elif tag == "out":
print(result.get("val"), end="")
else:
raise RuntimeError("unexpected response from PREPL")
def print_error(res):
for error in res["via"]:
print("ERR:", error["message"])
break
def print_error(error):
print("ERR:", error["hint"])
def run_cmd(params):
try:
expr = "(app.srepl.cli/exec {})".format(encode(params))
res, failed = send_eval(expr)
if failed:
print_error(res)
res, err = send(params)
if err:
print_error(err)
sys.exit(-1)
return res
@@ -76,19 +71,27 @@ def run_cmd(params):
print("EXC:", str(cause))
sys.exit(-2)
def create_profile(fullname, email, password):
def create_profile(fullname, email, password, skip_tutorial=False, skip_walkthrough=False):
props = {}
if skip_tutorial:
props["viewed-tutorial?"] = True
if skip_walkthrough:
props["viewed-walkthrough?"] = True
params = {
"cmd": "create-profile",
"params": {
"fullname": fullname,
"email": email,
"password": password
"password": password,
**props
}
}
res = run_cmd(params)
print(f"Created: {res['email']} / {res['id']}")
def update_profile(email, fullname, password, is_active):
params = {
"cmd": "update-profile",
@@ -96,7 +99,7 @@ def update_profile(email, fullname, password, is_active):
"email": email,
"fullname": fullname,
"password": password,
"is_active": is_active
"isActive": is_active
}
}
@@ -138,7 +141,7 @@ def derive_password(password):
params = {
"cmd": "derive-password",
"params": {
"password": password,
"password": password
}
}
@@ -175,6 +178,8 @@ parser.add_argument("-n", "--fullname", help="fullname", action="store")
parser.add_argument("-e", "--email", help="email", action="store")
parser.add_argument("-p", "--password", help="password", action="store")
parser.add_argument("-c", "--connect", help="connect to PREPL", action="store", default="tcp://localhost:6063")
parser.add_argument("--skip-tutorial", help="mark tutorial as viewed", action="store_true")
parser.add_argument("--skip-walkthrough", help="mark walkthrough as viewed", action="store_true")
args = parser.parse_args()

View File

@@ -1,109 +1,13 @@
#!/usr/bin/env bash
export PENPOT_SECRET_KEY=super-secret-devenv-key
export PENPOT_HOST=devenv
export PENPOT_FLAGS="\
$PENPOT_FLAGS \
enable-login-with-ldap \
enable-login-with-password
enable-login-with-oidc \
enable-login-with-google \
enable-login-with-github \
enable-login-with-gitlab \
enable-backend-worker \
enable-backend-asserts \
enable-feature-fdata-pointer-map \
enable-feature-fdata-objects-map \
enable-audit-log \
enable-transit-readable-response \
enable-demo-users \
disable-secure-session-cookies \
enable-smtp \
enable-prepl-server \
enable-urepl-server \
enable-rpc-climit \
enable-rpc-rlimit \
enable-quotes \
enable-soft-rpc-rlimit \
enable-auto-file-snapshot \
enable-webhooks \
enable-access-tokens \
enable-tiered-file-data-storage \
enable-file-validation \
enable-file-schema-validation";
# Default deletion delay for devenv
export PENPOT_DELETION_DELAY="24h"
# Setup default upload media file size to 100MiB
export PENPOT_MEDIA_MAX_FILE_SIZE=104857600
# Setup default multipart upload size to 300MiB
export PENPOT_HTTP_SERVER_MAX_MULTIPART_BODY_SIZE=314572800
# export PENPOT_DATABASE_URI="postgresql://172.17.0.1:5432/penpot"
# export PENPOT_DATABASE_USERNAME="penpot"
# export PENPOT_DATABASE_PASSWORD="penpot"
# export PENPOT_DATABASE_READONLY=true
# export PENPOT_DATABASE_URI="postgresql://172.17.0.1:5432/penpot_pre"
# export PENPOT_DATABASE_USERNAME="penpot_pre"
# export PENPOT_DATABASE_PASSWORD="penpot_pre"
# export PENPOT_LOGGERS_LOKI_URI="http://172.17.0.1:3100/loki/api/v1/push"
# export PENPOT_AUDIT_LOG_ARCHIVE_URI="http://localhost:6070/api/audit"
SCRIPT_DIR=$(dirname $0);
source $SCRIPT_DIR/_env;
# Initialize MINIO config
mc alias set penpot-s3/ http://minio:9000 minioadmin minioadmin -q
mc admin user add penpot-s3 penpot-devenv penpot-devenv -q
mc admin user info penpot-s3 penpot-devenv |grep -F -q "readwrite"
if [ "$?" = "1" ]; then
mc admin policy attach penpot-s3 readwrite --user=penpot-devenv -q
fi
mc mb penpot-s3/penpot -p -q
export AWS_ACCESS_KEY_ID=penpot-devenv
export AWS_SECRET_ACCESS_KEY=penpot-devenv
export PENPOT_OBJECTS_STORAGE_BACKEND=s3
export PENPOT_OBJECTS_STORAGE_S3_ENDPOINT=http://minio:9000
export PENPOT_OBJECTS_STORAGE_S3_BUCKET=penpot
export PENPOT_OBJECTS_STORAGE_FS_DIRECTORY="assets"
export JAVA_OPTS="--enable-preview \
-Djava.util.logging.manager=org.apache.logging.log4j.jul.LogManager \
-Djdk.attach.allowAttachSelf \
-Dlog4j2.configurationFile=log4j2-devenv-repl.xml \
-Djdk.tracePinnedThreads=full \
-XX:+EnableDynamicAgentLoading \
-XX:-OmitStackTraceInFastThrow \
-XX:+UnlockDiagnosticVMOptions \
-XX:+DebugNonSafepoints";
setup_minio;
export JAVA_OPTS="$JAVA_OPTS -Dlog4j2.configurationFile=log4j2-devenv-repl.xml"
export OPTIONS="-A:jmx-remote -A:dev"
# Setup HEAP
# export OPTIONS="$OPTIONS -J-Xms50m -J-Xmx1024m"
# export OPTIONS="$OPTIONS -J-Xms1100m -J-Xmx1100m -J-XX:+AlwaysPreTouch"
# Increase virtual thread pool size
# export OPTIONS="$OPTIONS -J-Djdk.virtualThreadScheduler.parallelism=16"
# Disable C2 Compiler
# export OPTIONS="$OPTIONS -J-XX:TieredStopAtLevel=1"
# Disable all compilers
# export OPTIONS="$OPTIONS -J-Xint"
# Setup GC
# export OPTIONS="$OPTIONS -J-XX:+UseG1GC"
# Setup GC
# export OPTIONS="$OPTIONS -J-XX:+UseZGC"
# Enable ImageMagick v7.x support
# export OPTIONS="-J-Dim4java.useV7=true $OPTIONS";
export OPTIONS_EVAL="nil"
# export OPTIONS_EVAL="(set! *warn-on-reflection* true)"

View File

@@ -1,48 +0,0 @@
#!/usr/bin/env bash
source /home/penpot/environ
export PENPOT_FLAGS="$PENPOT_FLAGS disable-backend-worker"
export OPTIONS="
-A:jmx-remote -A:dev \
-J-Djava.util.logging.manager=org.apache.logging.log4j.jul.LogManager \
-J-Djdk.attach.allowAttachSelf \
-J-Dlog4j2.configurationFile=log4j2-experiments.xml \
-J-XX:-OmitStackTraceInFastThrow \
-J-XX:+UnlockDiagnosticVMOptions \
-J-XX:+DebugNonSafepoints \
-J-Djdk.tracePinnedThreads=full \
-J-XX:+UseTransparentHugePages \
-J-XX:ReservedCodeCacheSize=1g \
-J-Dpolyglot.engine.WarnInterpreterOnly=false \
-J--enable-preview";
# Setup HEAP
export OPTIONS="$OPTIONS -J-Xms320g -J-Xmx320g -J-XX:+AlwaysPreTouch"
export PENPOT_HTTP_SERVER_IO_THREADS=2
export PENPOT_HTTP_SERVER_WORKER_THREADS=2
# Increase virtual thread pool size
# export OPTIONS="$OPTIONS -J-Djdk.virtualThreadScheduler.parallelism=16"
# Disable C2 Compiler
# export OPTIONS="$OPTIONS -J-XX:TieredStopAtLevel=1"
# Disable all compilers
# export OPTIONS="$OPTIONS -J-Xint"
# Setup GC
export OPTIONS="$OPTIONS -J-XX:+UseG1GC -J-Xlog:gc:logs/gc.log"
# Setup GC
#export OPTIONS="$OPTIONS -J-XX:+UseZGC -J-XX:+ZGenerational -J-Xlog:gc:logs/gc.log"
# Enable ImageMagick v7.x support
# export OPTIONS="-J-Dim4java.useV7=true $OPTIONS";
export OPTIONS_EVAL="nil"
# export OPTIONS_EVAL="(set! *warn-on-reflection* true)"
set -ex
exec clojure $OPTIONS -M -e "$OPTIONS_EVAL" -m rebel-readline.main

View File

@@ -1,44 +1,13 @@
#!/usr/bin/env bash
export PENPOT_SECRET_KEY=super-secret-devenv-key
export PENPOT_HOST=devenv
export PENPOT_FLAGS="\
$PENPOT_FLAGS \
enable-backend-asserts \
enable-feature-fdata-pointer-map \
enable-feature-fdata-objects-map \
enable-file-snapshot \
enable-tiered-file-data-storage";
SCRIPT_DIR=$(dirname $0);
export JAVA_OPTS="
-Djava.util.logging.manager=org.apache.logging.log4j.jul.LogManager \
-Djdk.attach.allowAttachSelf \
-Dlog4j2.configurationFile=log4j2-devenv.xml \
-XX:+EnableDynamicAgentLoading \
-XX:-OmitStackTraceInFastThrow \
-XX:+UnlockDiagnosticVMOptions \
-XX:+DebugNonSafepoints";
export CLOJURE_OPTIONS="-A:dev"
# Default deletion delay for devenv
export PENPOT_DELETION_DELAY="24h"
# Setup default upload media file size to 100MiB
export PENPOT_MEDIA_MAX_FILE_SIZE=104857600
# Setup default multipart upload size to 300MiB
export PENPOT_HTTP_SERVER_MAX_MULTIPART_BODY_SIZE=314572800
export AWS_ACCESS_KEY_ID=penpot-devenv
export AWS_SECRET_ACCESS_KEY=penpot-devenv
export PENPOT_OBJECTS_STORAGE_BACKEND=s3
export PENPOT_OBJECTS_STORAGE_S3_ENDPOINT=http://minio:9000
export PENPOT_OBJECTS_STORAGE_S3_BUCKET=penpot
source $SCRIPT_DIR/_env;
export OPTIONS="-A:dev"
entrypoint=${1:-app.main};
shift 1;
set -ex
clojure $CLOJURE_OPTIONS -A:dev -M -m $entrypoint "$@";
exec clojure $OPTIONS -A:dev -M -m $entrypoint "$@";

View File

@@ -18,9 +18,9 @@ if [ -f ./environ ]; then
source ./environ
fi
export JVM_OPTS="-Djava.util.logging.manager=org.apache.logging.log4j.jul.LogManager -Dlog4j2.configurationFile=log4j2.xml -XX:-OmitStackTraceInFastThrow --enable-preview $JVM_OPTS"
export JAVA_OPTS="-Dim4java.useV7=true -Djava.util.logging.manager=org.apache.logging.log4j.jul.LogManager -Dlog4j2.configurationFile=log4j2.xml -XX:-OmitStackTraceInFastThrow --sun-misc-unsafe-memory-access=allow --enable-native-access=ALL-UNNAMED --enable-preview $JVM_OPTS $JAVA_OPTS"
ENTRYPOINT=${1:-app.main};
set -ex
exec $JAVA_CMD $JVM_OPTS -jar penpot.jar -m $ENTRYPOINT
exec $JAVA_CMD $JAVA_OPTS -jar penpot.jar -m $ENTRYPOINT

View File

@@ -1,70 +1,11 @@
#!/usr/bin/env bash
export PENPOT_SECRET_KEY=super-secret-devenv-key
export PENPOT_HOST=devenv
export PENPOT_FLAGS="\
$PENPOT_FLAGS \
enable-prepl-server \
enable-urepl-server \
enable-nrepl-server \
enable-webhooks \
enable-backend-asserts \
enable-audit-log \
enable-login-with-ldap \
enable-transit-readable-response \
enable-demo-users \
enable-feature-fdata-pointer-map \
enable-feature-fdata-objects-map \
disable-secure-session-cookies \
enable-rpc-climit \
enable-smtp \
enable-quotes \
enable-file-snapshot \
enable-access-tokens \
enable-tiered-file-data-storage \
enable-file-validation \
enable-file-schema-validation";
export OPTIONS="
-A:jmx-remote -A:dev \
-J-Djava.util.logging.manager=org.apache.logging.log4j.jul.LogManager \
-J-Djdk.attach.allowAttachSelf \
-J-Dpolyglot.engine.WarnInterpreterOnly=false \
-J-Dlog4j2.configurationFile=log4j2-devenv.xml \
-J-XX:+EnableDynamicAgentLoading \
-J-XX:-OmitStackTraceInFastThrow \
-J-XX:+UnlockDiagnosticVMOptions \
-J-XX:+DebugNonSafepoints"
# Default deletion delay for devenv
export PENPOT_DELETION_DELAY="24h"
# Setup default upload media file size to 100MiB
export PENPOT_MEDIA_MAX_FILE_SIZE=104857600
# Setup default multipart upload size to 300MiB
export PENPOT_HTTP_SERVER_MAX_MULTIPART_BODY_SIZE=314572800
# Enable ImageMagick v7.x support
# export OPTIONS="-J-Dim4java.useV7=true $OPTIONS";
SCRIPT_DIR=$(dirname $0);
source $SCRIPT_DIR/_env;
# Initialize MINIO config
mc alias set penpot-s3/ http://minio:9000 minioadmin minioadmin -q
mc admin user add penpot-s3 penpot-devenv penpot-devenv -q
mc admin user info penpot-s3 penpot-devenv |grep -F -q "readwrite"
if [ "$?" = "1" ]; then
mc admin policy attach penpot-s3 readwrite --user=penpot-devenv -q
fi
mc mb penpot-s3/penpot -p -q
export AWS_ACCESS_KEY_ID=penpot-devenv
export AWS_SECRET_ACCESS_KEY=penpot-devenv
export PENPOT_OBJECTS_STORAGE_BACKEND=s3
export PENPOT_OBJECTS_STORAGE_S3_ENDPOINT=http://minio:9000
export PENPOT_OBJECTS_STORAGE_S3_BUCKET=penpot
entrypoint=${1:-app.main};
setup_minio;
shift 1;
set -ex
clojure $OPTIONS -A:dev -M -m $entrypoint;
exec clojure -A:jmx-remote -A:dev -M -m app.main "$@";

View File

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,131 @@
;; 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
(ns app.binfile.cleaner
"A collection of helpers for perform cleaning of artifacts; mainly
for recently imported shapes."
(:require
[app.common.data :as d]
[app.common.types.shape :as cts]
[app.common.uuid :as uuid]))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; PRE DECODE
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(defn- pre-clean-bool-content
[shape]
(if-let [content (get shape :bool-content)]
(-> shape
(assoc :content content)
(dissoc :bool-content))
shape))
(defn- pre-clean-shadow-color
[shape]
(d/update-when shape :shadow
(fn [shadows]
(mapv (fn [shadow]
(update shadow :color
(fn [color]
(let [ref-id (get color :id)
ref-file (get color :file-id)]
(-> (d/without-qualified color)
(select-keys [:opacity :color :gradient :image :ref-id :ref-file])
(cond-> ref-id
(assoc :ref-id ref-id))
(cond-> ref-file
(assoc :ref-file ref-file)))))))
shadows))))
(defn clean-shape-pre-decode
"Applies a pre-decode phase migration to the shape"
[shape]
(cond-> shape
(= "bool" (:type shape))
(pre-clean-bool-content)
(contains? shape :shadow)
(pre-clean-shadow-color)))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; POST DECODE
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(defn- fix-shape-shadow-color
"Some shapes can come with invalid `id` property on shadow colors
caused by incorrect uuid parsing bug that should be already fixed;
this function removes the invalid id from the data structure."
[shape]
(let [fix-color
(fn [{:keys [id] :as color}]
(if (uuid? id)
color
(if (and (string? id)
(re-matches uuid/regex id))
(assoc color :id (uuid/uuid id))
(dissoc color :id))))
fix-shadow
(fn [shadow]
(d/update-when shadow :color fix-color))
xform
(map fix-shadow)]
(d/update-when shape :shadow
(fn [shadows]
(into [] xform shadows)))))
(defn- fix-root-shape
"Ensure all root objects are well formed shapes"
[shape]
(if (= (:id shape) uuid/zero)
(-> shape
(assoc :parent-id uuid/zero)
(assoc :frame-id uuid/zero)
;; We explicitly dissoc them and let the shape-setup
;; to regenerate it with valid values.
(dissoc :selrect)
(dissoc :points)
(cts/setup-shape))
shape))
(defn- fix-legacy-flex-dir
"This operation is only relevant to old data and it is fixed just
for convenience."
[shape]
(d/update-when shape :layout-flex-dir
(fn [dir]
(case dir
:reverse-row :row-reverse
:reverse-column :column-reverse
dir))))
(defn clean-shape-post-decode
"A shape procesor that expected to be executed after schema decoding
process but before validation."
[shape]
(-> shape
(fix-shape-shadow-color)
(fix-root-shape)
(fix-legacy-flex-dir)))
(defn- fix-container
[container]
(-> container
;; Remove possible `nil` keys on objects
(d/update-when :objects dissoc nil)
(d/update-when :objects d/update-vals clean-shape-post-decode)))
(defn clean-file
[file & {:as _opts}]
(update file :data
(fn [data]
(-> data
(d/update-when :pages-index d/update-vals fix-container)
(d/update-when :components d/update-vals fix-container)
(d/without-nils)))))

View File

@@ -15,19 +15,21 @@
[app.common.files.migrations :as fmg]
[app.common.files.validate :as fval]
[app.common.logging :as l]
[app.common.schema :as sm]
[app.common.time :as ct]
[app.common.types.file :as ctf]
[app.common.uuid :as uuid]
[app.common.weak :as weak]
[app.config :as cf]
[app.db :as db]
[app.db.sql :as sql]
[app.features.fdata :as feat.fdata]
[app.features.file-migrations :as feat.fmigr]
[app.features.fdata :as fdata]
[app.features.file-migrations :as fmigr]
[app.loggers.audit :as-alias audit]
[app.loggers.webhooks :as-alias webhooks]
[app.storage :as sto]
[app.util.blob :as blob]
[app.util.pointer-map :as pmap]
[app.util.time :as dt]
[app.worker :as-alias wrk]
[clojure.set :as set]
[cuerdas.core :as str]
@@ -38,6 +40,7 @@
(def ^:dynamic *state* nil)
(def ^:dynamic *options* nil)
(def ^:dynamic *reference-file* nil)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; DEFAULTS
@@ -54,15 +57,11 @@
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(declare get-resolved-file-libraries)
(declare update-file!)
(def file-attrs
#{:id
:name
:migrations
:features
:project-id
:is-shared
:version
:data})
(sm/keys ctf/schema:file))
(defn parse-file-format
[template]
@@ -142,29 +141,176 @@
([index coll attr]
(reduce #(index-object %1 %2 attr) index coll)))
(defn decode-row
"A generic decode row helper"
[{:keys [data features] :as row}]
(cond-> row
features (assoc :features (db/decode-pgarray features #{}))
data (assoc :data (blob/decode data))))
(defn- decode-row-features
[{:keys [features] :as row}]
(when row
(cond-> row
(db/pgarray? features) (assoc :features (db/decode-pgarray features #{})))))
(defn decode-file
"A general purpose file decoding function that resolves all external
pointers, run migrations and return plain vanilla file map"
[cfg {:keys [id] :as file}]
(binding [pmap/*load-fn* (partial feat.fdata/load-pointer cfg id)]
(let [file (->> file
(feat.fmigr/resolve-applied-migrations cfg)
(feat.fdata/resolve-file-data cfg))]
(def sql:get-minimal-file
"SELECT f.id,
f.revn,
f.modified_at,
f.deleted_at
FROM file AS f
WHERE f.id = ?")
(-> file
(update :features db/decode-pgarray #{})
(update :data blob/decode)
(update :data feat.fdata/process-pointers deref)
(update :data feat.fdata/process-objects (partial into {}))
(update :data assoc :id id)
(fmg/migrate-file)))))
(defn get-minimal-file
[cfg id & {:as opts}]
(db/get-with-sql cfg [sql:get-minimal-file id] opts))
(def sql:files-with-data
"SELECT f.id,
f.project_id,
f.created_at,
f.modified_at,
f.deleted_at,
f.name,
f.is_shared,
f.has_media_trimmed,
f.revn,
f.data AS legacy_data,
f.ignore_sync_until,
f.comment_thread_seqn,
f.features,
f.version,
f.vern,
p.team_id,
coalesce(fd.backend, 'legacy-db') AS backend,
fd.metadata AS metadata,
fd.data AS data
FROM file AS f
LEFT JOIN file_data AS fd ON (fd.file_id = f.id AND fd.id = f.id)
INNER JOIN project AS p ON (p.id = f.project_id)")
(def sql:get-file
(str sql:files-with-data " WHERE f.id = ?"))
(def sql:get-file-without-data
(str "WITH files AS (" sql:files-with-data ")"
"SELECT f.id,
f.project_id,
f.created_at,
f.modified_at,
f.deleted_at,
f.name,
f.is_shared,
f.has_media_trimmed,
f.revn,
f.ignore_sync_until,
f.comment_thread_seqn,
f.features,
f.version,
f.vern,
f.team_id
FROM files AS f
WHERE f.id = ?"))
(defn- migrate-file
[{:keys [::db/conn] :as cfg} {:keys [read-only?]} {:keys [id] :as file}]
(binding [pmap/*load-fn* (partial fdata/load-pointer cfg id)
pmap/*tracked* (pmap/create-tracked)]
(let [libs (delay (get-resolved-file-libraries cfg file))
;; For avoid unnecesary overhead of creating multiple
;; pointers and handly internally with objects map in their
;; worst case (when probably all shapes and all pointers
;; will be readed in any case), we just realize/resolve them
;; before applying the migration to the file.
file (-> (fdata/realize cfg file)
(fmg/migrate-file libs))]
(if (or read-only? (db/read-only? conn))
file
(do ;; When file is migrated, we break the rule of no
;; perform mutations on get operations and update the
;; file with all migrations applied
(update-file! cfg file)
(fmigr/resolve-applied-migrations cfg file))))))
(defn- get-file*
[{:keys [::db/conn] :as cfg} id
{:keys [migrate?
realize?
decode?
skip-locked?
include-deleted?
load-data?
throw-if-not-exists?
lock-for-update?
lock-for-share?]
:or {lock-for-update? false
lock-for-share? false
load-data? true
migrate? true
decode? true
include-deleted? false
throw-if-not-exists? true
realize? false}
:as options}]
(assert (db/connection? conn) "expected cfg with valid connection")
(when (and (not load-data?)
(or lock-for-share? lock-for-share? skip-locked?))
(throw (IllegalArgumentException. "locking is incompatible when `load-data?` is false")))
(let [sql
(if load-data?
sql:get-file
sql:get-file-without-data)
sql
(cond
lock-for-update?
(str sql " FOR UPDATE of f")
lock-for-share?
(str sql " FOR SHARE of f")
:else
sql)
sql
(if skip-locked?
(str sql " SKIP LOCKED")
sql)
file
(db/get-with-sql conn [sql id]
{::db/throw-if-not-exists false
::db/remove-deleted (not include-deleted?)})
file
(-> file
(d/update-when :features db/decode-pgarray #{})
(d/update-when :metadata fdata/decode-metadata))]
(if file
(if load-data?
(let [file
(->> file
(fmigr/resolve-applied-migrations cfg)
(fdata/resolve-file-data cfg))
will-migrate?
(and migrate? (fmg/need-migration? file))]
(if decode?
(cond->> (fdata/decode-file-data cfg file)
(and realize? (not will-migrate?))
(fdata/realize cfg)
will-migrate?
(migrate-file cfg options))
file))
file)
(when-not (or skip-locked? (not throw-if-not-exists?))
(ex/raise :type :not-found
:code :object-not-found
:hint "database object not found"
:table :file
:file-id id)))))
(defn get-file
"Get file, resolve all features and apply migrations.
@@ -173,10 +319,7 @@
operations on file, because it removes the ovehead of lazy fetching
and decoding."
[cfg file-id & {:as opts}]
(db/run! cfg (fn [{:keys [::db/conn] :as cfg}]
(some->> (db/get* conn :file {:id file-id}
(assoc opts ::db/remove-deleted false))
(decode-file cfg)))))
(db/run! cfg get-file* file-id opts))
(defn clean-file-features
[file]
@@ -200,12 +343,12 @@
(let [conn (db/get-connection cfg)
ids (db/create-array conn "uuid" ids)]
(->> (db/exec! conn [sql:get-teams ids])
(map decode-row))))
(map decode-row-features))))
(defn get-team
[cfg team-id]
(-> (db/get cfg :team {:id team-id})
(decode-row)))
(decode-row-features)))
(defn get-fonts
[cfg team-id]
@@ -297,7 +440,6 @@
(do
(l/trc :hint "lookup index"
:file-id (str file-id)
:snap-id (str (:snapshot-id file))
:id (str id)
:result (str (get mobj :id)))
(get mobj :id))
@@ -314,7 +456,6 @@
(doseq [[old-id item] missing-index]
(l/dbg :hint "create missing references"
:file-id (str file-id)
:snap-id (str (:snapshot-id file))
:old-id (str old-id)
:id (str (:id item)))
(db/insert! conn :file-media-object item
@@ -325,12 +466,16 @@
(def sql:get-file-media
"SELECT * FROM file_media_object WHERE id = ANY(?)")
(defn get-file-media*
[{:keys [::db/conn] :as cfg} {:keys [data id] :as file}]
(let [used (cfh/collect-used-media data)
used (db/create-array conn "uuid" used)]
(->> (db/exec! conn [sql:get-file-media used])
(mapv (fn [row] (assoc row :file-id id))))))
(defn get-file-media
[cfg {:keys [data] :as file}]
(db/run! cfg (fn [{:keys [::db/conn]}]
(let [used (cfh/collect-used-media data)
used (db/create-array conn "uuid" used)]
(db/exec! conn [sql:get-file-media used])))))
[cfg file]
(db/run! cfg get-file-media* file))
(def ^:private sql:get-team-files-ids
"SELECT f.id FROM file AS f
@@ -405,7 +550,7 @@
[cfg data file-id]
(let [library-ids (get-libraries cfg [file-id])]
(reduce (fn [data library-id]
(if-let [library (get-file cfg library-id)]
(if-let [library (get-file cfg library-id :include-deleted? true)]
(ctf/absorb-assets data (:data library))
data))
data
@@ -417,94 +562,146 @@
(db/exec-one! conn ["SET LOCAL idle_in_transaction_session_timeout = 0"])
(db/exec-one! conn ["SET CONSTRAINTS ALL DEFERRED"])))
(defn process-file
[{:keys [id] :as file}]
(-> file
(update :data (fn [fdata]
(-> fdata
(assoc :id id)
(dissoc :recent-colors))))
(fmg/migrate-file)
(update :data (fn [fdata]
(-> fdata
(update :pages-index relink-shapes)
(update :components relink-shapes)
(update :media relink-media)
(update :colors relink-colors)
(d/without-nils))))))
(defn invalidate-thumbnails
[cfg file-id]
(let [storage (sto/resolve cfg)
(defn encode-file
[{:keys [::db/conn] :as cfg} {:keys [id] :as file}]
(let [file (if (contains? (:features file) "fdata/objects-map")
(feat.fdata/enable-objects-map file)
sql-1
(str "update file_tagged_object_thumbnail "
" set deleted_at = now() "
" where file_id=? returning media_id")
sql-2
(str "update file_thumbnail "
" set deleted_at = now() "
" where file_id=? returning media_id")]
(run! #(sto/touch-object! storage %)
(sequence
(keep :media-id)
(concat
(db/exec! cfg [sql-1 file-id])
(db/exec! cfg [sql-2 file-id]))))))
(defn process-file
[cfg {:keys [id] :as file}]
(let [libs (delay (get-resolved-file-libraries cfg file))]
(-> file
(update :data (fn [fdata]
(-> fdata
(assoc :id id)
(dissoc :recent-colors))))
(update :data (fn [fdata]
(-> fdata
(update :pages-index relink-shapes)
(update :components relink-shapes)
(update :media relink-media)
(update :colors relink-colors)
(d/without-nils))))
(fmg/migrate-file libs)
;; NOTE: this is necessary because when we just creating a new
;; file from imported artifact or cloned file there are no
;; migrations registered on the database, so we need to persist
;; all of them, not only the applied
(vary-meta dissoc ::fmg/migrated))))
(defn- encode-file
[cfg {:keys [id features] :as file}]
(let [file (if (and (contains? features "fdata/objects-map")
(:data file))
(fdata/enable-objects-map file)
file)
file (if (contains? (:features file) "fdata/pointer-map")
(binding [pmap/*tracked* (pmap/create-tracked)]
(let [file (feat.fdata/enable-pointer-map file)]
(feat.fdata/persist-pointers! cfg id)
file (if (and (contains? features "fdata/pointer-map")
(:data file))
(binding [pmap/*tracked* (pmap/create-tracked :inherit true)]
(let [file (fdata/enable-pointer-map file)]
(fdata/persist-pointers! cfg id)
file))
file)]
(-> file
(update :features db/encode-pgarray conn "text")
(update :data blob/encode))))
(d/update-when :features into-array)
(d/update-when :data blob/encode))))
(defn get-params-from-file
(defn- file->params
[file]
(let [params {:has-media-trimmed (:has-media-trimmed file)
:ignore-sync-until (:ignore-sync-until file)
:project-id (:project-id file)
:features (:features file)
:name (:name file)
:is-shared (:is-shared file)
:version (:version file)
:data (:data file)
:id (:id file)
:deleted-at (:deleted-at file)
:created-at (:created-at file)
:modified-at (:modified-at file)
:revn (:revn file)
:vern (:vern file)}]
(-> (select-keys file file-attrs)
(assoc :data nil)
(dissoc :team-id)
(dissoc :migrations)))
(-> (d/without-nils params)
(assoc :data-backend nil)
(assoc :data-ref-id nil))))
(defn- file->file-data-params
[{:keys [id] :as file} & {:as opts}]
(let [created-at (or (:created-at file) (ct/now))
modified-at (or (:modified-at file) created-at)]
(d/without-nils
{:id id
:type "main"
:file-id id
:data (:data file)
:metadata (:metadata file)
:created-at created-at
:modified-at modified-at})))
(defn insert-file!
"Insert a new file into the database table"
"Insert a new file into the database table. Expectes a not-encoded file.
Returns nil."
[{:keys [::db/conn] :as cfg} file & {:as opts}]
(feat.fmigr/upsert-migrations! conn file)
(let [params (-> (encode-file cfg file)
(get-params-from-file))]
(db/insert! conn :file params opts)))
(db/exec-one! conn ["SET CONSTRAINTS ALL DEFERRED"])
(when (:migrations file)
(fmigr/upsert-migrations! conn file))
(let [file (encode-file cfg file)]
(db/insert! conn :file
(file->params file)
(assoc opts ::db/return-keys false))
(->> (file->file-data-params file)
(fdata/upsert! cfg))
nil))
(defn update-file!
"Update an existing file on the database."
[{:keys [::db/conn ::sto/storage] :as cfg} {:keys [id] :as file} & {:as opts}]
(let [file (encode-file cfg file)
params (-> (get-params-from-file file)
(dissoc :id))]
"Update an existing file on the database. Expects not encoded file."
[{:keys [::db/conn] :as cfg} {:keys [id] :as file} & {:as opts}]
;; If file was already offloaded, we touch the underlying storage
;; object for properly trigger storage-gc-touched task
(when (feat.fdata/offloaded? file)
(some->> (:data-ref-id file) (sto/touch-object! storage)))
(if (::reset-migrations? opts false)
(fmigr/reset-migrations! conn file)
(fmigr/upsert-migrations! conn file))
(feat.fmigr/upsert-migrations! conn file)
(db/update! conn :file params {:id id} opts)))
(let [file
(encode-file cfg file)
file-params
(file->params (dissoc file :id))
file-data-params
(file->file-data-params file)]
(db/update! conn :file file-params
{:id id}
{::db/return-keys false})
(fdata/upsert! cfg file-data-params)
nil))
(defn save-file!
"Applies all the final validations and perist the file, binfile
specific, should not be used outside of binfile domain"
specific, should not be used outside of binfile domain.
Returns nil"
[{:keys [::timestamp] :as cfg} file & {:as opts}]
(assert (dt/instant? timestamp) "expected valid timestamp")
(assert (ct/inst? timestamp) "expected valid timestamp")
(let [file (-> file
(assoc :created-at timestamp)
(assoc :modified-at timestamp)
(assoc :ignore-sync-until (dt/plus timestamp (dt/duration {:seconds 5})))
(cond-> (not (::overwrite cfg))
(assoc :ignore-sync-until (ct/plus timestamp (ct/duration {:seconds 5}))))
(update :features
(fn [features]
(-> (::features cfg #{})
@@ -521,4 +718,62 @@
(when (ex/exception? result)
(l/error :hint "file schema validation error" :cause result))))
(insert-file! cfg file opts)))
(if (::overwrite cfg)
(update-file! cfg file (assoc opts ::reset-migrations? true))
(insert-file! cfg file opts))))
(def ^:private sql:get-file-libraries
"WITH RECURSIVE libs AS (
SELECT fl.*, flr.synced_at
FROM file AS fl
JOIN file_library_rel AS flr ON (flr.library_file_id = fl.id)
WHERE flr.file_id = ?::uuid
UNION
SELECT fl.*, flr.synced_at
FROM file AS fl
JOIN file_library_rel AS flr ON (flr.library_file_id = fl.id)
JOIN libs AS l ON (flr.file_id = l.id)
)
SELECT l.id,
l.features,
l.project_id,
p.team_id,
l.created_at,
l.modified_at,
l.deleted_at,
l.name,
l.revn,
l.vern,
l.synced_at,
l.is_shared,
l.version
FROM libs AS l
INNER JOIN project AS p ON (p.id = l.project_id)
WHERE l.deleted_at IS NULL;")
(defn get-file-libraries
[conn file-id]
(into []
(comp
;; FIXME: :is-indirect set to false to all rows looks
;; completly useless
(map #(assoc % :is-indirect false))
(map decode-row-features))
(db/exec! conn [sql:get-file-libraries file-id])))
(defn get-resolved-file-libraries
"Get all file libraries including itself. Returns an instance of
LoadableWeakValueMap that allows do not have strong references to
the loaded libraries and reduce possible memory pressure on having
all this libraries loaded at same time on processing file validation
or file migration.
This still requires at least one library at time to be loaded while
access to it is performed, but it improves considerable not having
the need of loading all the libraries at the same time."
[{:keys [::db/conn] :as cfg} {:keys [id] :as file}]
(let [library-ids (->> (get-file-libraries conn (:id file))
(map :id)
(cons (:id file)))
load-fn #(get-file cfg % :migrate? false)]
(weak/loadable-weak-value-map library-ids load-fn {id file})))

View File

@@ -10,7 +10,6 @@
[app.binfile.common :as bfc]
[app.common.exceptions :as ex]
[app.common.features :as cfeat]
[app.features.components-v2 :as feat.compv2]
[clojure.set :as set]
[cuerdas.core :as str]))
@@ -28,13 +27,11 @@
(defn apply-pending-migrations!
"Apply alredy registered pending migrations to files"
[cfg]
(doseq [[feature file-id] (-> bfc/*state* deref :pending-to-migrate)]
[_cfg]
(doseq [[feature _file-id] (-> bfc/*state* deref :pending-to-migrate)]
(case feature
"components/v2"
(feat.compv2/migrate-file! cfg file-id
:validate? (::validate cfg true)
:skip-on-graphic-error? true)
nil
"fdata/shape-data-type"
nil

View File

@@ -17,6 +17,7 @@
[app.common.fressian :as fres]
[app.common.logging :as l]
[app.common.spec :as us]
[app.common.time :as ct]
[app.common.types.file :as ctf]
[app.common.uuid :as uuid]
[app.config :as cf]
@@ -30,7 +31,6 @@
[app.storage.tmp :as tmp]
[app.tasks.file-gc]
[app.util.events :as events]
[app.util.time :as dt]
[app.worker :as-alias wrk]
[clojure.java.io :as jio]
[clojure.set :as set]
@@ -346,7 +346,7 @@
thumbnails (->> (bfc/get-file-object-thumbnails cfg file-id)
(mapv #(dissoc % :file-id)))
file (cond-> (bfc/get-file cfg file-id)
file (cond-> (bfc/get-file cfg file-id :realize? true)
detach?
(-> (ctf/detach-external-references file-id)
(dissoc :libraries))
@@ -434,7 +434,7 @@
(defn read-import!
"Do the importation of the specified resource in penpot custom binary
format."
[{:keys [::bfc/input ::bfc/timestamp] :or {timestamp (dt/now)} :as options}]
[{:keys [::bfc/input ::bfc/timestamp] :or {timestamp (ct/now)} :as options}]
(dm/assert!
"expected input stream"
@@ -442,7 +442,7 @@
(dm/assert!
"expected valid instant"
(dt/instant? timestamp))
(ct/inst? timestamp))
(let [version (read-header! input)]
(read-import (assoc options ::version version ::bfc/timestamp timestamp))))
@@ -551,8 +551,8 @@
(cond-> (and (= idx 0) (some? name))
(assoc :name name))
(assoc :project-id project-id)
(dissoc :thumbnails)
(bfc/process-file))]
(dissoc :thumbnails))
file (bfc/process-file system file)]
;; All features that are enabled and requires explicit migration are
;; added to the state for a posterior migration step.
@@ -682,7 +682,7 @@
(io/coercible? output))
(let [id (uuid/next)
tp (dt/tpoint)
tp (ct/tpoint)
ab (volatile! false)
cs (volatile! nil)]
(try
@@ -720,7 +720,7 @@
(satisfies? jio/IOFactory input))
(let [id (uuid/next)
tp (dt/tpoint)
tp (ct/tpoint)
cs (volatile! nil)]
(l/info :hint "import: started" :id (str id))
@@ -742,6 +742,6 @@
(finally
(l/info :hint "import: terminated"
:id (str id)
:elapsed (dt/format-duration (tp))
:elapsed (ct/format-duration (tp))
:error? (some? @cs))))))

View File

@@ -13,6 +13,7 @@
[app.common.data :as d]
[app.common.features :as cfeat]
[app.common.logging :as l]
[app.common.time :as ct]
[app.common.transit :as t]
[app.common.uuid :as uuid]
[app.config :as cf]
@@ -23,7 +24,6 @@
[app.storage :as sto]
[app.storage.tmp :as tmp]
[app.util.events :as events]
[app.util.time :as dt]
[app.worker :as-alias wrk]
[clojure.set :as set]
[cuerdas.core :as str]
@@ -153,7 +153,7 @@
(defn- write-file!
[cfg file-id]
(let [file (bfc/get-file cfg file-id)
(let [file (bfc/get-file cfg file-id :realize? true)
thumbs (bfc/get-file-object-thumbnails cfg file-id)
media (bfc/get-file-media cfg file)
rels (bfc/get-files-rels cfg #{file-id})]
@@ -281,8 +281,8 @@
(let [file (-> (read-obj cfg :file file-id)
(update :id bfc/lookup-index)
(update :project-id bfc/lookup-index)
(bfc/process-file))]
(update :project-id bfc/lookup-index))
file (bfc/process-file cfg file)]
(events/tap :progress
{:op :import
@@ -344,7 +344,7 @@
(defn export-team!
[cfg team-id]
(let [id (uuid/next)
tp (dt/tpoint)
tp (ct/tpoint)
cfg (create-database cfg)]
(l/inf :hint "start"
@@ -378,15 +378,15 @@
(l/inf :hint "end"
:operation "export"
:id (str id)
:elapsed (dt/format-duration elapsed)))))))
:elapsed (ct/format-duration elapsed)))))))
(defn import-team!
[cfg path]
(let [id (uuid/next)
tp (dt/tpoint)
tp (ct/tpoint)
cfg (-> (create-database cfg path)
(assoc ::bfc/timestamp (dt/now)))]
(assoc ::bfc/timestamp (ct/now)))]
(l/inf :hint "start"
:operation "import"
@@ -434,4 +434,4 @@
(l/inf :hint "end"
:operation "import"
:id (str id)
:elapsed (dt/format-duration elapsed)))))))
:elapsed (ct/format-duration elapsed)))))))

View File

@@ -8,23 +8,26 @@
"A ZIP based binary file exportation"
(:refer-clojure :exclude [read])
(:require
[app.binfile.cleaner :as bfl]
[app.binfile.common :as bfc]
[app.binfile.migrations :as bfm]
[app.common.data :as d]
[app.common.data.macros :as dm]
[app.common.exceptions :as ex]
[app.common.features :as cfeat]
[app.common.files.migrations :as-alias fmg]
[app.common.json :as json]
[app.common.logging :as l]
[app.common.media :as cmedia]
[app.common.schema :as sm]
[app.common.thumbnails :as cth]
[app.common.time :as ct]
[app.common.types.color :as ctcl]
[app.common.types.component :as ctc]
[app.common.types.file :as ctf]
[app.common.types.page :as ctp]
[app.common.types.plugins :as ctpg]
[app.common.types.shape :as cts]
[app.common.types.tokens-lib :as cto]
[app.common.types.tokens-lib :as ctob]
[app.common.types.typography :as cty]
[app.common.uuid :as uuid]
[app.config :as cf]
@@ -33,14 +36,15 @@
[app.storage :as sto]
[app.storage.impl :as sto.impl]
[app.util.events :as events]
[app.util.time :as dt]
[clojure.java.io :as jio]
[cuerdas.core :as str]
[datoteka.fs :as fs]
[datoteka.io :as io])
(:import
java.io.File
java.io.InputStream
java.io.OutputStreamWriter
java.lang.AutoCloseable
java.util.zip.ZipEntry
java.util.zip.ZipFile
java.util.zip.ZipOutputStream))
@@ -51,7 +55,7 @@
[:map {:title "Manifest"}
[:version ::sm/int]
[:type :string]
[:referer {:optional true} :string]
[:generated-by {:optional true} :string]
[:files
@@ -71,7 +75,7 @@
[:size ::sm/int]
[:content-type :string]
[:bucket [::sm/one-of {:format :string} sto/valid-buckets]]
[:hash :string]])
[:hash {:optional true} :string]])
(def ^:private schema:file-thumbnail
[:map {:title "FileThumbnail"}
@@ -86,34 +90,40 @@
ctf/schema:file
[:map [:options {:optional true} ctf/schema:options]]])
;; --- HELPERS
(defn- default-now
[o]
(or o (ct/now)))
;; --- ENCODERS
(def encode-file
(sm/encoder schema:file sm/json-transformer))
(def encode-page
(sm/encoder ::ctp/page sm/json-transformer))
(sm/encoder ctp/schema:page sm/json-transformer))
(def encode-shape
(sm/encoder ::cts/shape sm/json-transformer))
(sm/encoder cts/schema:shape sm/json-transformer))
(def encode-media
(sm/encoder ::ctf/media sm/json-transformer))
(sm/encoder ctf/schema:media sm/json-transformer))
(def encode-component
(sm/encoder ::ctc/component sm/json-transformer))
(sm/encoder ctc/schema:component sm/json-transformer))
(def encode-color
(sm/encoder ::ctcl/color sm/json-transformer))
(sm/encoder ctcl/schema:library-color sm/json-transformer))
(def encode-typography
(sm/encoder ::cty/typography sm/json-transformer))
(sm/encoder cty/schema:typography sm/json-transformer))
(def encode-tokens-lib
(sm/encoder ::cto/tokens-lib sm/json-transformer))
(sm/encoder ctob/schema:tokens-lib sm/json-transformer))
(def encode-plugin-data
(sm/encoder ::ctpg/plugin-data sm/json-transformer))
(sm/encoder ctpg/schema:plugin-data sm/json-transformer))
(def encode-storage-object
(sm/encoder schema:storage-object sm/json-transformer))
@@ -127,31 +137,31 @@
(sm/decoder schema:manifest sm/json-transformer))
(def decode-media
(sm/decoder ::ctf/media sm/json-transformer))
(sm/decoder ctf/schema:media sm/json-transformer))
(def decode-component
(sm/decoder ::ctc/component sm/json-transformer))
(sm/decoder ctc/schema:component sm/json-transformer))
(def decode-color
(sm/decoder ::ctcl/color sm/json-transformer))
(sm/decoder ctcl/schema:library-color sm/json-transformer))
(def decode-file
(sm/decoder schema:file sm/json-transformer))
(def decode-page
(sm/decoder ::ctp/page sm/json-transformer))
(sm/decoder ctp/schema:page sm/json-transformer))
(def decode-shape
(sm/decoder ::cts/shape sm/json-transformer))
(sm/decoder cts/schema:shape sm/json-transformer))
(def decode-typography
(sm/decoder ::cty/typography sm/json-transformer))
(sm/decoder cty/schema:typography sm/json-transformer))
(def decode-tokens-lib
(sm/decoder ::cto/tokens-lib sm/json-transformer))
(sm/decoder ctob/schema:tokens-lib sm/json-transformer))
(def decode-plugin-data
(sm/decoder ::ctpg/plugin-data sm/json-transformer))
(sm/decoder ctpg/schema:plugin-data sm/json-transformer))
(def decode-storage-object
(sm/decoder schema:storage-object sm/json-transformer))
@@ -165,31 +175,31 @@
(sm/check-fn schema:manifest))
(def validate-file
(sm/check-fn ::ctf/file))
(sm/check-fn ctf/schema:file))
(def validate-page
(sm/check-fn ::ctp/page))
(sm/check-fn ctp/schema:page))
(def validate-shape
(sm/check-fn ::cts/shape))
(sm/check-fn cts/schema:shape))
(def validate-media
(sm/check-fn ::ctf/media))
(sm/check-fn ctf/schema:media))
(def validate-color
(sm/check-fn ::ctcl/color))
(sm/check-fn ctcl/schema:library-color))
(def validate-component
(sm/check-fn ::ctc/component))
(sm/check-fn ctc/schema:component))
(def validate-typography
(sm/check-fn ::cty/typography))
(sm/check-fn cty/schema:typography))
(def validate-tokens-lib
(sm/check-fn ::cto/tokens-lib))
(sm/check-fn ctob/schema:tokens-lib))
(def validate-plugin-data
(sm/check-fn ::ctpg/plugin-data))
(sm/check-fn ctpg/schema:plugin-data))
(def validate-storage-object
(sm/check-fn schema:storage-object))
@@ -214,9 +224,12 @@
(throw (IllegalArgumentException.
"the `include-libraries` and `embed-assets` are mutally excluding options")))
(let [detach? (and (not embed-assets) (not include-libraries))]
(let [detach? (and (not embed-assets) (not include-libraries))]
(db/tx-run! cfg (fn [cfg]
(cond-> (bfc/get-file cfg file-id {::sql/for-update true})
(cond-> (bfc/get-file cfg file-id
{:realize? true
:include-deleted? true
:lock-for-update? true})
detach?
(-> (ctf/detach-external-references file-id)
(dissoc :libraries))
@@ -227,27 +240,13 @@
:always
(bfc/clean-file-features))))))
(defn- resolve-extension
[mtype]
(case mtype
"image/png" ".png"
"image/jpeg" ".jpg"
"image/gif" ".gif"
"image/svg+xml" ".svg"
"image/webp" ".webp"
"font/woff" ".woff"
"font/woff2" ".woff2"
"font/ttf" ".ttf"
"font/otf" ".otf"
"application/octet-stream" ".bin"))
(defn- export-storage-objects
[{:keys [::output] :as cfg}]
(let [storage (sto/resolve cfg)]
(doseq [id (-> bfc/*state* deref :storage-objects not-empty)]
(let [sobject (sto/get-object storage id)
smeta (meta sobject)
ext (resolve-extension (:content-type smeta))
ext (cmedia/mtype->extension (:content-type smeta))
path (str "objects/" id ".json")
params (-> (meta sobject)
(assoc :id (:id sobject))
@@ -256,10 +255,12 @@
(write-entry! output path params)
(events/tap :progress {:section :storage-object :id id})
(with-open [input (sto/get-object-data storage sobject)]
(.putNextEntry output (ZipEntry. (str "objects/" id ext)))
(.putNextEntry ^ZipOutputStream output (ZipEntry. (str "objects/" id ext)))
(io/copy input output :size (:size sobject))
(.closeEntry output))))))
(.closeEntry ^ZipOutputStream output))))))
(defn- export-file
[{:keys [::file-id ::output] :as cfg}]
@@ -280,6 +281,8 @@
thumbnails (bfc/get-file-object-thumbnails cfg file-id)]
(events/tap :progress {:section :file :id file-id})
(vswap! bfc/*state* update :files assoc file-id
{:id file-id
:name (:name file)
@@ -287,13 +290,13 @@
(let [file (cond-> (select-keys file bfc/file-attrs)
(:options data)
(assoc :options (:options data))
(assoc :options (:options data)))
:always
(dissoc :data)
file (-> file
(dissoc :data)
(dissoc :deleted-at)
(encode-file))
:always
(encode-file))
path (str "files/" file-id ".json")]
(write-entry! output path file))
@@ -351,7 +354,8 @@
typography (encode-typography object)]
(write-entry! output path typography)))
(when tokens-lib
(when (and tokens-lib
(not (ctob/empty-lib? tokens-lib)))
(let [path (str "files/" file-id "/tokens.json")
encoded-tokens (encode-tokens-lib tokens-lib)]
(write-entry! output path encoded-tokens)))))
@@ -378,6 +382,7 @@
params {:type "penpot/export-files"
:version 1
:generated-by (str "penpot/" (:full cf/version))
:refer "penpot"
:files (vec (vals files))
:relations rels}]
(write-entry! output "manifest.json" params))))
@@ -450,7 +455,7 @@
(defn- read-manifest
[^ZipFile input]
(let [entry (get-zip-entry input "manifest.json")]
(with-open [reader (zip-entry-reader input entry)]
(with-open [^AutoCloseable reader (zip-entry-reader input entry)]
(let [manifest (json/read reader :key-fn json/read-kebab-key)]
(decode-manifest manifest)))))
@@ -540,24 +545,27 @@
(defn- read-entry
[^ZipFile input entry]
(with-open [reader (zip-entry-reader input entry)]
(with-open [^AutoCloseable reader (zip-entry-reader input entry)]
(json/read reader :key-fn json/read-kebab-key)))
(defn- read-plain-entry
[^ZipFile input entry]
(with-open [reader (zip-entry-reader input entry)]
(with-open [^AutoCloseable reader (zip-entry-reader input entry)]
(json/read reader)))
(defn- read-file
[{:keys [::bfc/input ::file-id]}]
[{:keys [::bfc/input ::bfc/timestamp]} file-id]
(let [path (str "files/" file-id ".json")
entry (get-zip-entry input path)]
(-> (read-entry input entry)
(decode-file)
(update :revn d/nilv 1)
(update :created-at d/nilv timestamp)
(update :modified-at d/nilv timestamp)
(validate-file))))
(defn- read-file-plugin-data
[{:keys [::bfc/input ::file-id]}]
[{:keys [::bfc/input]} file-id]
(let [path (str "files/" file-id "/plugin-data.json")
entry (get-zip-entry* input path)]
(some->> entry
@@ -566,13 +574,19 @@
(validate-plugin-data))))
(defn- read-file-media
[{:keys [::bfc/input ::file-id ::entries]}]
[{:keys [::bfc/input ::entries]} file-id]
(->> (keep (match-media-entry-fn file-id) entries)
(reduce (fn [result {:keys [id entry]}]
(let [object (->> (read-entry input entry)
(decode-media)
(validate-media))
object (assoc object :file-id file-id)]
object (-> object
(assoc :file-id file-id)
(update :created-at default-now)
;; FIXME: this is set default to true for
;; setting a value, this prop is no longer
;; relevant;
(assoc :is-local true))]
(if (= id (:id object))
(conj result object)
result)))
@@ -580,7 +594,7 @@
(not-empty)))
(defn- read-file-colors
[{:keys [::bfc/input ::file-id ::entries]}]
[{:keys [::bfc/input ::entries]} file-id]
(->> (keep (match-color-entry-fn file-id) entries)
(reduce (fn [result {:keys [id entry]}]
(let [object (->> (read-entry input entry)
@@ -593,20 +607,38 @@
(not-empty)))
(defn- read-file-components
[{:keys [::bfc/input ::file-id ::entries]}]
(->> (keep (match-component-entry-fn file-id) entries)
(reduce (fn [result {:keys [id entry]}]
(let [object (->> (read-entry input entry)
(decode-component)
(validate-component))]
(if (= id (:id object))
(assoc result id object)
result)))
{})
(not-empty)))
[{:keys [::bfc/input ::entries]} file-id]
(let [clean-component-post-decode
(fn [component]
(d/update-when component :objects
(fn [objects]
(reduce-kv (fn [objects id shape]
(assoc objects id (bfl/clean-shape-post-decode shape)))
objects
objects))))
clean-component-pre-decode
(fn [component]
(d/update-when component :objects
(fn [objects]
(reduce-kv (fn [objects id shape]
(assoc objects id (bfl/clean-shape-pre-decode shape)))
objects
objects))))]
(->> (keep (match-component-entry-fn file-id) entries)
(reduce (fn [result {:keys [id entry]}]
(let [object (->> (read-entry input entry)
(clean-component-pre-decode)
(decode-component)
(clean-component-post-decode))]
(if (= id (:id object))
(assoc result id object)
result)))
{})
(not-empty))))
(defn- read-file-typographies
[{:keys [::bfc/input ::file-id ::entries]}]
[{:keys [::bfc/input ::entries]} file-id]
(->> (keep (match-typography-entry-fn file-id) entries)
(reduce (fn [result {:keys [id entry]}]
(let [object (->> (read-entry input entry)
@@ -619,19 +651,20 @@
(not-empty)))
(defn- read-file-tokens-lib
[{:keys [::bfc/input ::file-id ::entries]}]
[{:keys [::bfc/input ::entries]} file-id]
(when-let [entry (d/seek (match-tokens-lib-entry-fn file-id) entries)]
(->> (read-plain-entry input entry)
(decode-tokens-lib)
(validate-tokens-lib))))
(defn- read-file-shapes
[{:keys [::bfc/input ::file-id ::page-id ::entries] :as cfg}]
[{:keys [::bfc/input ::entries] :as cfg} file-id page-id]
(->> (keep (match-shape-entry-fn file-id page-id) entries)
(reduce (fn [result {:keys [id entry]}]
(let [object (->> (read-entry input entry)
(bfl/clean-shape-pre-decode)
(decode-shape)
(validate-shape))]
(bfl/clean-shape-post-decode))]
(if (= id (:id object))
(assoc result id object)
result)))
@@ -639,15 +672,14 @@
(not-empty)))
(defn- read-file-pages
[{:keys [::bfc/input ::file-id ::entries] :as cfg}]
[{:keys [::bfc/input ::entries] :as cfg} file-id]
(->> (keep (match-page-entry-fn file-id) entries)
(keep (fn [{:keys [id entry]}]
(let [page (->> (read-entry input entry)
(decode-page))
page (dissoc page :options)]
(when (= id (:id page))
(let [objects (-> (assoc cfg ::page-id id)
(read-file-shapes))]
(let [objects (read-file-shapes cfg file-id id)]
(assoc page :objects objects))))))
(sort-by :index)
(reduce (fn [result {:keys [id] :as page}]
@@ -655,7 +687,7 @@
(d/ordered-map))))
(defn- read-file-thumbnails
[{:keys [::bfc/input ::file-id ::entries] :as cfg}]
[{:keys [::bfc/input ::entries] :as cfg} file-id]
(->> (keep (match-thumbnail-entry-fn file-id) entries)
(reduce (fn [result {:keys [page-id frame-id tag entry]}]
(let [object (->> (read-entry input entry)
@@ -670,14 +702,13 @@
(not-empty)))
(defn- read-file-data
[cfg]
(let [colors (read-file-colors cfg)
typographies (read-file-typographies cfg)
tokens-lib (read-file-tokens-lib cfg)
components (read-file-components cfg)
plugin-data (read-file-plugin-data cfg)
pages (read-file-pages cfg)]
[cfg file-id]
(let [colors (read-file-colors cfg file-id)
typographies (read-file-typographies cfg file-id)
tokens-lib (read-file-tokens-lib cfg file-id)
components (read-file-components cfg file-id)
plugin-data (read-file-plugin-data cfg file-id)
pages (read-file-pages cfg file-id)]
{:pages (-> pages keys vec)
:pages-index (into {} pages)
:colors colors
@@ -687,11 +718,11 @@
:plugin-data plugin-data}))
(defn- import-file
[{:keys [::bfc/project-id ::file-id ::file-name] :as cfg}]
[{:keys [::db/conn ::bfc/project-id] :as cfg} {file-id :id file-name :name}]
(let [file-id' (bfc/lookup-index file-id)
file (read-file cfg)
media (read-file-media cfg)
thumbnails (read-file-thumbnails cfg)]
file (read-file cfg file-id)
media (read-file-media cfg file-id)
thumbnails (read-file-thumbnails cfg file-id)]
(l/dbg :hint "processing file"
:id (str file-id')
@@ -700,28 +731,50 @@
:version (:version file)
::l/sync? true)
(events/tap :progress {:section :file :name file-name})
(vswap! bfc/*state* update :index bfc/update-index media :id)
(when media
;; Update index with media
(l/dbg :hint "update media index"
:file-id (str file-id')
:total (count media)
::l/sync? true)
(events/tap :progress {:section :media :file-id file-id})
(vswap! bfc/*state* update :index bfc/update-index (map :id media))
(vswap! bfc/*state* update :media into media))
(doseq [item media]
(let [params (-> item
(update :id bfc/lookup-index)
(assoc :file-id file-id')
(d/update-when :media-id bfc/lookup-index)
(d/update-when :thumbnail-id bfc/lookup-index))]
(when thumbnails
(l/dbg :hint "update thumbnails index"
:file-id (str file-id')
:total (count thumbnails)
::l/sync? true)
(l/dbg :hint "inserting media object"
:file-id (str file-id')
:id (str (:id params))
:media-id (str (:media-id params))
:thumbnail-id (str (:thumbnail-id params))
:old-id (str (:id item))
::l/sync? true)
(vswap! bfc/*state* update :index bfc/update-index (map :media-id thumbnails))
(vswap! bfc/*state* update :thumbnails into thumbnails))
(db/insert! conn :file-media-object params
::db/on-conflict-do-nothing? (::bfc/overwrite cfg))))
(let [data (-> (read-file-data cfg)
(events/tap :progress {:section :thumbnails :file-id file-id})
(doseq [item thumbnails]
(let [media-id (bfc/lookup-index (:media-id item))
object-id (-> (assoc item :file-id file-id')
(cth/fmt-object-id))
params {:file-id file-id'
:object-id object-id
:tag (:tag item)
:media-id media-id}]
(l/dbg :hint "inserting object thumbnail"
:file-id (str file-id')
:media-id (str media-id)
::l/sync? true)
(db/insert! conn :file-tagged-object-thumbnail params
::db/on-conflict-do-nothing? true)))
(events/tap :progress {:section :file :file-id file-id})
(let [data (-> (read-file-data cfg file-id)
(d/without-nils)
(assoc :id file-id')
(cond-> (:options file)
@@ -732,12 +785,13 @@
(assoc :data data)
(assoc :name file-name)
(assoc :project-id project-id)
(dissoc :options)
(bfc/process-file))]
(dissoc :options))
file (bfc/process-file cfg file)
file (ctf/check-file file)]
(bfm/register-pending-migrations! cfg file)
(bfc/save-file! cfg file ::db/return-keys false)
(bfc/save-file! cfg file)
file-id')))
@@ -767,107 +821,113 @@
entries (keep (match-storage-entry-fn) entries)]
(doseq [{:keys [id entry]} entries]
(let [object (->> (read-entry input entry)
(decode-storage-object)
(validate-storage-object))]
(let [object (->> (read-entry input entry)
(decode-storage-object)
(validate-storage-object))
(when (not= id (:id object))
ext (cmedia/mtype->extension (:content-type object))
path (str "objects/" id ext)
content (->> path
(get-zip-entry input)
(zip-entry-storage-content input))]
(when (not= (:size object) (sto/get-size content))
(ex/raise :type :validation
:code :inconsistent-penpot-file
:hint "the penpot file seems corrupt, found unexpected uuid (storage-object-id)"
:expected-id (str id)
:found-id (str (:id object))))
:hint "found corrupted storage object: size does not match"
:path path
:expected-size (:size object)
:found-size (sto/get-size content)))
(let [ext (resolve-extension (:content-type object))
path (str "objects/" id ext)
content (->> path
(get-zip-entry input)
(zip-entry-storage-content input))]
(when (not= (:size object) (sto/get-size content))
(ex/raise :type :validation
:code :inconsistent-penpot-file
:hint "found corrupted storage object: size does not match"
:path path
:expected-size (:size object)
:found-size (sto/get-size content)))
(when (not= (:hash object) (sto/get-hash content))
(when-let [hash (get object :hash)]
(when (not= hash (sto/get-hash content))
(ex/raise :type :validation
:code :inconsistent-penpot-file
:hint "found corrupted storage object: hash does not match"
:path path
:expected-hash (:hash object)
:found-hash (sto/get-hash content)))
:found-hash (sto/get-hash content))))
(let [params (-> object
(dissoc :id :size)
(assoc ::sto/content content)
(assoc ::sto/deduplicate? true)
(assoc ::sto/touched-at timestamp))
sobject (sto/put-object! storage params)]
(let [params (-> object
(dissoc :id :size)
(assoc ::sto/content content)
(assoc ::sto/deduplicate? true)
(assoc ::sto/touched-at timestamp))
sobject (sto/put-object! storage params)]
(l/dbg :hint "persisted storage object"
:id (str (:id sobject))
:prev-id (str id)
:bucket (:bucket params)
::l/sync? true)
(l/dbg :hint "persisted storage object"
:id (str (:id sobject))
:prev-id (str id)
:bucket (:bucket params)
::l/sync? true)
(vswap! bfc/*state* update :index assoc id (:id sobject))))))))
(vswap! bfc/*state* update :index assoc id (:id sobject)))))))
(defn- import-file-media
[{:keys [::db/conn] :as cfg}]
(events/tap :progress {:section :media})
(defn- import-files*
[{:keys [::manifest] :as cfg}]
(bfc/disable-database-timeouts! cfg)
(doseq [item (:media @bfc/*state*)]
(let [params (-> item
(update :id bfc/lookup-index)
(update :file-id bfc/lookup-index)
(d/update-when :media-id bfc/lookup-index)
(d/update-when :thumbnail-id bfc/lookup-index))]
(vswap! bfc/*state* update :index bfc/update-index (:files manifest) :id)
(l/dbg :hint "inserting file media object"
:old-id (str (:id item))
:id (str (:id params))
:file-id (str (:file-id params))
::l/sync? true)
(import-storage-objects cfg)
(db/insert! conn :file-media-object params))))
(let [files (get manifest :files)
result (reduce (fn [result {:keys [id] :as file}]
(let [name' (get file :name)
name' (if (map? name)
(get name id)
name')
file (assoc file :name name')]
(conj result (import-file cfg file))))
[]
files)]
(defn- import-file-thumbnails
[{:keys [::db/conn] :as cfg}]
(events/tap :progress {:section :thumbnails})
(doseq [item (:thumbnails @bfc/*state*)]
(let [file-id (bfc/lookup-index (:file-id item))
media-id (bfc/lookup-index (:media-id item))
object-id (-> (assoc item :file-id file-id)
(cth/fmt-object-id))
params {:file-id file-id
:object-id object-id
:tag (:tag item)
:media-id media-id}]
(import-file-relations cfg)
(bfm/apply-pending-migrations! cfg)
(l/dbg :hint "inserting file object thumbnail"
:file-id (str file-id)
:media-id (str media-id)
::l/sync? true)
result))
(db/insert! conn :file-tagged-object-thumbnail params))))
(defn- import-file-and-overwrite*
[{:keys [::manifest ::bfc/file-id] :as cfg}]
(when (not= 1 (count (:files manifest)))
(ex/raise :type :validation
:code :invalid-condition
:hint "unable to perform in-place update with binfile containing more than 1 file"
:manifest manifest))
(bfc/disable-database-timeouts! cfg)
(let [ref-file (bfc/get-minimal-file cfg file-id ::db/for-update true)
file (first (get manifest :files))
cfg (assoc cfg ::bfc/overwrite true)]
(vswap! bfc/*state* update :index assoc (:id file) file-id)
(binding [bfc/*options* cfg
bfc/*reference-file* ref-file]
(import-storage-objects cfg)
(import-file cfg file)
(bfc/invalidate-thumbnails cfg file-id)
(bfm/apply-pending-migrations! cfg)
[file-id])))
(defn- import-files
[{:keys [::bfc/timestamp ::bfc/input ::bfc/name] :or {timestamp (dt/now)} :as cfg}]
[{:keys [::bfc/timestamp ::bfc/input] :or {timestamp (ct/now)} :as cfg}]
(dm/assert!
"expected zip file"
(instance? ZipFile input))
(dm/assert!
"expected valid instant"
(dt/instant? timestamp))
(assert (instance? ZipFile input) "expected zip file")
(assert (ct/inst? timestamp) "expected valid instant")
(let [manifest (-> (read-manifest input)
(validate-manifest))
entries (read-zip-entries input)]
entries (read-zip-entries input)
cfg (-> cfg
(assoc ::entries entries)
(assoc ::manifest manifest)
(assoc ::bfc/timestamp timestamp))]
(when-not (= "penpot/export-files" (:type manifest))
(ex/raise :type :validation
@@ -890,35 +950,10 @@
(events/tap :progress {:section :manifest})
(let [index (bfc/update-index (map :id (:files manifest)))
state {:media [] :index index}
cfg (-> cfg
(assoc ::entries entries)
(assoc ::manifest manifest)
(assoc ::bfc/timestamp timestamp))]
(binding [bfc/*state* (volatile! state)]
(db/tx-run! cfg (fn [cfg]
(bfc/disable-database-timeouts! cfg)
(let [ids (->> (:files manifest)
(reduce (fn [result {:keys [id] :as file}]
(let [name' (get file :name)
name' (if (map? name)
(get name id)
name')]
(conj result (-> cfg
(assoc ::file-id id)
(assoc ::file-name name')
(import-file)))))
[]))]
(import-file-relations cfg)
(import-storage-objects cfg)
(import-file-media cfg)
(import-file-thumbnails cfg)
(bfm/apply-pending-migrations! cfg)
ids)))))))
(binding [bfc/*state* (volatile! {:media [] :index {}})]
(if (::bfc/file-id cfg)
(db/tx-run! cfg import-file-and-overwrite*)
(db/tx-run! cfg import-files*)))))
;; --- PUBLIC API
@@ -935,24 +970,23 @@
[{:keys [::bfc/ids] :as cfg} output]
(dm/assert!
"expected a set of uuid's for `::bfc/ids` parameter"
(and (set? ids)
(every? uuid? ids)))
(assert
(and (set? ids) (every? uuid? ids))
"expected a set of uuid's for `::bfc/ids` parameter")
(dm/assert!
"expected instance of jio/IOFactory for `input`"
(satisfies? jio/IOFactory output))
(assert
(satisfies? jio/IOFactory output)
"expected instance of jio/IOFactory for `input`")
(let [id (uuid/next)
tp (dt/tpoint)
tp (ct/tpoint)
ab (volatile! false)
cs (volatile! nil)]
(try
(l/info :hint "start exportation" :export-id (str id))
(binding [bfc/*state* (volatile! (bfc/initial-state))]
(with-open [output (io/output-stream output)]
(with-open [output (ZipOutputStream. output)]
(with-open [^AutoCloseable output (io/output-stream output)]
(with-open [^AutoCloseable output (ZipOutputStream. output)]
(let [cfg (assoc cfg ::output output)]
(export-files cfg)
(export-storage-objects cfg)))))
@@ -981,22 +1015,22 @@
(defn import-files!
[{:keys [::bfc/input] :as cfg}]
(dm/assert!
"expected valid profile-id and project-id on `cfg`"
(assert
(and (uuid? (::bfc/profile-id cfg))
(uuid? (::bfc/project-id cfg))))
(uuid? (::bfc/project-id cfg)))
"expected valid profile-id and project-id on `cfg`")
(dm/assert!
"expected instance of jio/IOFactory for `input`"
(io/coercible? input))
(assert
(io/coercible? input)
"expected instance of jio/IOFactory for `input`")
(let [id (uuid/next)
tp (dt/tpoint)
tp (ct/tpoint)
cs (volatile! nil)]
(l/info :hint "import: started" :id (str id))
(try
(with-open [input (ZipFile. (fs/file input))]
(with-open [input (ZipFile. ^File (fs/file input))]
(import-files (assoc cfg ::bfc/input input)))
(catch Throwable cause
@@ -1006,5 +1040,11 @@
(finally
(l/info :hint "import: terminated"
:id (str id)
:elapsed (dt/format-duration (tp))
:elapsed (ct/format-duration (tp))
:error? (some? @cs))))))
(defn get-manifest
[path]
(with-open [^AutoCloseable input (ZipFile. ^File (fs/file path))]
(-> (read-manifest input)
(validate-manifest))))

View File

@@ -5,17 +5,16 @@
;; Copyright (c) KALEIDOS INC
(ns app.config
"A configuration management."
(:refer-clojure :exclude [get])
(:require
[app.common.data :as d]
[app.common.exceptions :as ex]
[app.common.flags :as flags]
[app.common.schema :as sm]
[app.common.time :as ct]
[app.common.uri :as u]
[app.common.version :as v]
[app.util.overrides]
[app.util.time :as dt]
[clojure.core :as c]
[clojure.java.io :as io]
[cuerdas.core :as str]
@@ -47,22 +46,27 @@
:auto-file-snapshot-timeout "3h"
:public-uri "http://localhost:3449"
:host "localhost"
:tenant "default"
:redis-uri "redis://redis/0"
:file-data-backend "legacy-db"
:objects-storage-backend "fs"
:objects-storage-fs-directory "assets"
:auth-token-cookie-name "auth-token"
:assets-path "/internal/assets/"
:smtp-default-reply-to "Penpot <no-reply@example.com>"
:smtp-default-from "Penpot <no-reply@example.com>"
:profile-complaint-max-age (dt/duration {:days 7})
:profile-complaint-max-age (ct/duration {:days 7})
:profile-complaint-threshold 2
:profile-bounce-max-age (dt/duration {:days 7})
:profile-bounce-max-age (ct/duration {:days 7})
:profile-bounce-threshold 10
:telemetry-uri "https://telemetry.penpot.app/"
@@ -88,7 +92,7 @@
[:secret-key {:optional true} :string]
[:tenant {:optional false} :string]
[:public-uri {:optional false} :string]
[:public-uri {:optional false} ::sm/uri]
[:host {:optional false} :string]
[:http-server-port {:optional true} ::sm/int]
@@ -96,16 +100,19 @@
[:http-server-max-body-size {:optional true} ::sm/int]
[:http-server-max-multipart-body-size {:optional true} ::sm/int]
[:http-server-io-threads {:optional true} ::sm/int]
[:http-server-worker-threads {:optional true} ::sm/int]
[:http-server-max-worker-threads {:optional true} ::sm/int]
[:management-api-key {:optional true} :string]
[:telemetry-uri {:optional true} :string]
[:telemetry-with-taiga {:optional true} ::sm/boolean] ;; DELETE
[:auto-file-snapshot-every {:optional true} ::sm/int]
[:auto-file-snapshot-timeout {:optional true} ::dt/duration]
[:auto-file-snapshot-timeout {:optional true} ::ct/duration]
[:media-max-file-size {:optional true} ::sm/int]
[:deletion-delay {:optional true} ::dt/duration] ;; REVIEW
[:deletion-delay {:optional true} ::ct/duration]
[:file-clean-delay {:optional true} ::ct/duration]
[:telemetry-enabled {:optional true} ::sm/boolean]
[:default-blob-version {:optional true} ::sm/int]
[:allow-demo-users {:optional true} ::sm/boolean]
@@ -146,12 +153,11 @@
[:quotes-team-access-requests-per-team {:optional true} ::sm/int]
[:quotes-team-access-requests-per-requester {:optional true} ::sm/int]
[:auth-data-cookie-domain {:optional true} :string]
[:auth-token-cookie-name {:optional true} :string]
[:auth-token-cookie-max-age {:optional true} ::dt/duration]
[:auth-token-cookie-max-age {:optional true} ::ct/duration]
[:registration-domain-whitelist {:optional true} [::sm/set :string]]
[:email-verify-threshold {:optional true} ::dt/duration]
[:email-verify-threshold {:optional true} ::ct/duration]
[:github-client-id {:optional true} :string]
[:github-client-secret {:optional true} :string]
@@ -161,7 +167,7 @@
[:google-client-id {:optional true} :string]
[:google-client-secret {:optional true} :string]
[:oidc-client-id {:optional true} :string]
[:oidc-user-info-source {:optional true} :keyword]
[:oidc-user-info-source {:optional true} [:enum "auto" "userinfo" "token"]]
[:oidc-client-secret {:optional true} :string]
[:oidc-base-uri {:optional true} :string]
[:oidc-token-uri {:optional true} :string]
@@ -186,9 +192,9 @@
[:ldap-starttls {:optional true} ::sm/boolean]
[:ldap-user-query {:optional true} :string]
[:profile-bounce-max-age {:optional true} ::dt/duration]
[:profile-bounce-max-age {:optional true} ::ct/duration]
[:profile-bounce-threshold {:optional true} ::sm/int]
[:profile-complaint-max-age {:optional true} ::dt/duration]
[:profile-complaint-max-age {:optional true} ::ct/duration]
[:profile-complaint-threshold {:optional true} ::sm/int]
[:redis-uri {:optional true} ::sm/uri]
@@ -210,24 +216,27 @@
[:prepl-host {:optional true} :string]
[:prepl-port {:optional true} ::sm/int]
[:file-data-backend {:optional true} [:enum "db" "legacy-db" "storage"]]
[:media-directory {:optional true} :string] ;; REVIEW
[:media-uri {:optional true} :string]
[:assets-path {:optional true} :string]
;; Legacy, will be removed in 2.5
[:netty-io-threads {:optional true} ::sm/int]
[:executor-threads {:optional true} ::sm/int]
;; DEPRECATED
[:assets-storage-backend {:optional true} :keyword]
[:storage-assets-fs-directory {:optional true} :string]
[:storage-assets-s3-bucket {:optional true} :string]
[:storage-assets-s3-region {:optional true} :keyword]
[:storage-assets-s3-endpoint {:optional true} ::sm/uri]
[:storage-assets-s3-io-threads {:optional true} ::sm/int]
[:objects-storage-backend {:optional true} :keyword]
[:objects-storage-fs-directory {:optional true} :string]
[:objects-storage-s3-bucket {:optional true} :string]
[:objects-storage-s3-region {:optional true} :keyword]
[:objects-storage-s3-endpoint {:optional true} ::sm/uri]
[:objects-storage-s3-io-threads {:optional true} ::sm/int]]))
[:objects-storage-s3-endpoint {:optional true} ::sm/uri]]))
(defn- parse-flags
[config]
@@ -298,7 +307,12 @@
(defn get-deletion-delay
[]
(or (c/get config :deletion-delay)
(dt/duration {:days 7})))
(ct/duration {:days 7})))
(defn get-file-clean-delay
[]
(or (c/get config :file-clean-delay)
(ct/duration {:days 2})))
(defn get
"A configuration getter. Helps code be more testable."
@@ -307,5 +321,9 @@
([key default]
(c/get config key default)))
(defn logging-context
[]
{:version/backend (:full version)})
;; Set value for all new threads bindings.
(alter-var-root #'*assert* (constantly (contains? flags :backend-asserts)))

View File

@@ -10,19 +10,21 @@
[app.common.data :as d]
[app.common.exceptions :as ex]
[app.common.geom.point :as gpt]
[app.common.json :as json]
[app.common.logging :as l]
[app.common.schema :as sm]
[app.common.time :as ct]
[app.common.transit :as t]
[app.common.uuid :as uuid]
[app.db.sql :as sql]
[app.metrics :as mtx]
[app.util.json :as json]
[app.util.time :as dt]
[clojure.java.io :as io]
[clojure.set :as set]
[integrant.core :as ig]
[next.jdbc :as jdbc]
[next.jdbc.date-time :as jdbc-dt])
[next.jdbc.date-time :as jdbc-dt]
[next.jdbc.prepare :as jdbc.prepare]
[next.jdbc.transaction])
(:import
com.zaxxer.hikari.HikariConfig
com.zaxxer.hikari.HikariDataSource
@@ -32,6 +34,7 @@
java.io.InputStream
java.io.OutputStream
java.sql.Connection
java.sql.PreparedStatement
java.sql.Savepoint
org.postgresql.PGConnection
org.postgresql.geometric.PGpoint
@@ -41,6 +44,8 @@
org.postgresql.util.PGInterval
org.postgresql.util.PGobject))
(def ^:dynamic *conn* nil)
(declare open)
(declare create-pool)
@@ -223,16 +228,6 @@
(let [^OutputStream os (.getOutputStream ^LargeObject lobj)]
(io/make-output-stream os opts))))
(defmacro with-atomic
[& args]
(if (symbol? (first args))
(let [cfgs (first args)
body (rest args)]
`(jdbc/with-transaction [conn# (::pool ~cfgs)]
(let [~cfgs (assoc ~cfgs ::conn conn#)]
~@body)))
`(jdbc/with-transaction ~@args)))
(defn open
[system-or-pool]
(if (pool? system-or-pool)
@@ -303,7 +298,7 @@
(defn insert!
"A helper that builds an insert sql statement and executes it. By
default returns the inserted row with all the field; you can delimit
the returned columns with the `::columns` option."
the returned columns with the `::sql/columns` option."
[ds table params & {:as opts}]
(let [conn (get-connectable ds)
sql (sql/insert table params opts)
@@ -384,9 +379,7 @@
(defn is-row-deleted?
[{:keys [deleted-at]}]
(and (dt/instant? deleted-at)
(< (inst-ms deleted-at)
(inst-ms (dt/now)))))
(some? deleted-at))
(defn get*
"Retrieve a single row from database that matches a simple filters. Do
@@ -411,6 +404,23 @@
:hint "database object not found"))
row))
(defn get-with-sql
[ds sql & {:as opts}]
(let [rows
(cond->> (exec! ds sql opts)
(::remove-deleted opts true)
(remove is-row-deleted?)
:always
(not-empty))]
(when (and (not rows) (::throw-if-not-exists opts true))
(ex/raise :type :not-found
:code :object-not-found
:hint "database object not found"))
(first rows)))
(def ^:private default-plan-opts
(-> default-opts
(assoc :fetch-size 1000)
@@ -535,52 +545,40 @@
(l/trc :hint "explicit rollback requested (savepoint)")
(.rollback conn sp))))
(defn transact!
"A lower-level function for executing function in a transaction"
([transactable f] (transact! transactable f {}))
([transactable f opts]
(binding [next.jdbc.transaction/*nested-tx* :ignore]
(jdbc/transact transactable f opts))))
(defn tx-run!
"Run a function in a transaction."
[system f & params]
(cond
(connection? system)
(if (connection? system)
(tx-run! {::conn system} f)
(pool? system)
(tx-run! {::pool system} f)
(::conn system)
(let [conn (::conn system)
sp (savepoint conn)]
(try
(let [system' (-> system
(assoc ::savepoint sp)
(dissoc ::rollback))
result (apply f system' params)]
(if (::rollback system)
(rollback! conn sp)
(release! conn sp))
result)
(catch Throwable cause
(.rollback ^Connection conn ^Savepoint sp)
(throw cause))))
(::pool system)
(with-atomic [conn (::pool system)]
(let [system' (-> system
(assoc ::conn conn)
(dissoc ::rollback))
result (apply f system' params)]
(when (::rollback system)
(rollback! conn))
result))
:else
(throw (IllegalArgumentException. "invalid system/cfg provided"))))
(if (pool? system)
(tx-run! {::pool system} f)
(if-let [conn (or (::conn system)
(::pool system))]
(transact! conn
(fn [conn]
(let [system' (-> system
(dissoc ::rollback)
(assoc ::conn conn))]
(apply f system' params)))
{:rollback-only (::rollback system)
:read-only (::read-only system)})
(throw (IllegalArgumentException. "invalid system/cfg provided"))))))
(defn run!
[system f & params]
(cond
(connection? system)
(run! {::conn system} f)
(apply run! {::conn system} f params)
(pool? system)
(run! {::pool system} f)
(apply run! {::pool system} f params)
(::conn system)
(apply f system params)
@@ -604,7 +602,7 @@
(string? o)
(pginterval o)
(dt/duration? o)
(ct/duration? o)
(interval (inst-ms o))
:else
@@ -618,7 +616,7 @@
val (.getValue o)]
(if (or (= typ "json")
(= typ "jsonb"))
(json/decode val)
(json/decode val :key-fn keyword)
val))))
(defn decode-transit-pgobject
@@ -659,7 +657,7 @@
(when data
(doto (org.postgresql.util.PGobject.)
(.setType "jsonb")
(.setValue (json/encode-str data)))))
(.setValue (json/encode data)))))
;; --- Locks
@@ -705,3 +703,14 @@
[cause]
(and (sql-exception? cause)
(= "40001" (.getSQLState ^java.sql.SQLException cause))))
(defn duplicate-key-error?
[cause]
(and (sql-exception? cause)
(= "23505" (.getSQLState ^java.sql.SQLException cause))))
(extend-protocol jdbc.prepare/SettableParameter
clojure.lang.Keyword
(set-parameter [^clojure.lang.Keyword v ^PreparedStatement s ^long i]
(.setObject s i ^String (d/name v))))

View File

@@ -53,8 +53,15 @@
opts (cond-> opts
(::order-by opts) (assoc :order-by (::order-by opts))
(::columns opts) (assoc :columns (::columns opts))
(::for-update opts) (assoc :suffix "FOR UPDATE")
(::for-share opts) (assoc :suffix "FOR SHARE"))]
(or (::db/for-update opts)
(::for-update opts))
(assoc :suffix "FOR UPDATE")
(or (::db/for-share opts)
(::for-share opts))
(assoc :suffix "FOR SHARE"))]
(sql/for-query table where-params opts))))
(defn update

View File

@@ -7,6 +7,7 @@
(ns app.email
"Main api for send emails."
(:require
[app.common.data :as d]
[app.common.data.macros :as dm]
[app.common.exceptions :as ex]
[app.common.logging :as l]
@@ -93,36 +94,44 @@
headers)))
(defn- assign-body
[^MimeMessage mmsg {:keys [body charset] :or {charset "utf-8"}}]
(let [mpart (MimeMultipart. "mixed")]
[^MimeMessage mmsg {:keys [body charset attachments] :or {charset "utf-8"}}]
(let [mixed-mpart (MimeMultipart. "mixed")]
(cond
(string? body)
(let [bpart (MimeBodyPart.)]
(.setContent bpart ^String body (str "text/plain; charset=" charset))
(.addBodyPart mpart bpart))
(vector? body)
(let [mmp (MimeMultipart. "alternative")
mbp (MimeBodyPart.)]
(.addBodyPart mpart mbp)
(.setContent mbp mmp)
(doseq [item body]
(let [mbp (MimeBodyPart.)]
(.setContent mbp
^String (:content item)
^String (str (:type item "text/plain") "; charset=" charset))
(.addBodyPart mmp mbp))))
(let [text-part (MimeBodyPart.)]
(.setText text-part ^String body ^String charset)
(.addBodyPart mixed-mpart text-part))
(map? body)
(let [bpart (MimeBodyPart.)]
(.setContent bpart
^String (:content body)
^String (str (:type body "text/plain") "; charset=" charset))
(.addBodyPart mpart bpart))
(let [content-part (MimeBodyPart.)
alternative-mpart (MimeMultipart. "alternative")]
(when-let [content (get body "text/plain")]
(let [text-part (MimeBodyPart.)]
(.setText text-part ^String content ^String charset)
(.addBodyPart alternative-mpart text-part)))
(when-let [content (get body "text/html")]
(let [html-part (MimeBodyPart.)]
(.setContent html-part ^String content
(str "text/html; charset=" charset))
(.addBodyPart alternative-mpart html-part)))
(.setContent content-part alternative-mpart)
(.addBodyPart mixed-mpart content-part))
:else
(throw (ex-info "Unsupported type" {:body body})))
(.setContent mmsg mpart)
(throw (IllegalArgumentException. "invalid email body provided")))
(doseq [[name content] attachments]
(prn "attachment" name)
(let [attachment-part (MimeBodyPart.)]
(.setFileName attachment-part ^String name)
(.setContent attachment-part ^String content (str "text/plain; charset=" charset))
(.addBodyPart mixed-mpart attachment-part)))
(.setContent mmsg mixed-mpart)
mmsg))
(defn- opts->props
@@ -210,24 +219,26 @@
(ex/raise :type :internal
:code :missing-email-templates))
{:subject subj
:body (into
[{:type "text/plain"
:content text}]
(when html
[{:type "text/html"
:content html}]))}))
:body (d/without-nils
{"text/plain" text
"text/html" html})}))
(def ^:private schema:context
[:map
(def ^:private schema:params
[:map {:title "Email Params"}
[:to [:or ::sm/email [::sm/vec ::sm/email]]]
[:reply-to {:optional true} ::sm/email]
[:from {:optional true} ::sm/email]
[:lang {:optional true} ::sm/text]
[:subject {:optional true} ::sm/text]
[:priority {:optional true} [:enum :high :low]]
[:extra-data {:optional true} ::sm/text]])
[:extra-data {:optional true} ::sm/text]
[:body {:optional true}
[:or :string [:map-of :string :string]]]
[:attachments {:optional true}
[:map-of :string :string]]])
(def ^:private check-context
(sm/check-fn schema:context))
(def ^:private check-params
(sm/check-fn schema:params))
(defn template-factory
[& {:keys [id schema]}]
@@ -235,9 +246,9 @@
(let [check-fn (if schema
(sm/check-fn schema)
(constantly nil))]
(fn [context]
(let [context (-> context check-context check-fn)
email (build-email-template id context)]
(fn [params]
(let [params (-> params check-params check-fn)
email (build-email-template id params)]
(when-not email
(ex/raise :type :internal
:code :email-template-does-not-exists
@@ -245,35 +256,40 @@
:template-id id))
(cond-> (assoc email :id (name id))
(:extra-data context)
(assoc :extra-data (:extra-data context))
(:extra-data params)
(assoc :extra-data (:extra-data params))
(:from context)
(assoc :from (:from context))
(seq (:attachments params))
(assoc :attachments (:attachments params))
(:reply-to context)
(assoc :reply-to (:reply-to context))
(:from params)
(assoc :from (:from params))
(:to context)
(assoc :to (:to context)))))))
(:reply-to params)
(assoc :reply-to (:reply-to params))
(:to params)
(assoc :to (:to params)))))))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; PUBLIC HIGH-LEVEL API
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(defn render
[email-factory context]
(email-factory context))
[email-factory params]
(email-factory params))
(defn send!
"Schedule an already defined email to be sent using asynchronously
using worker task."
[{:keys [::conn ::factory] :as context}]
[{:keys [::conn ::factory] :as params}]
(assert (db/connectable? conn) "expected a valid database connection or pool")
(let [email (if factory
(factory context)
(dissoc context ::conn))]
(factory params)
(-> params
(dissoc params)
(check-params)))]
(wrk/submit! {::wrk/task :sendmail
::wrk/delay 0
::wrk/max-retries 4
@@ -343,8 +359,10 @@
(def ^:private schema:feedback
[:map
[:subject ::sm/text]
[:content ::sm/text]])
[:feedback-subject ::sm/text]
[:feedback-type ::sm/text]
[:feedback-content ::sm/text]
[:profile :map]])
(def user-feedback
"A profile feedback email."

View File

File diff suppressed because it is too large Load Diff

View File

@@ -10,42 +10,21 @@
[app.common.data :as d]
[app.common.exceptions :as ex]
[app.common.logging :as l]
[app.common.schema :as sm]
[app.common.time :as ct]
[app.common.types.objects-map :as omap]
[app.config :as cf]
[app.db :as db]
[app.db.sql :as-alias sql]
[app.storage :as sto]
[app.util.blob :as blob]
[app.util.objects-map :as omap]
[app.util.objects-map :as omap.legacy]
[app.util.pointer-map :as pmap]))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; OFFLOAD
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(defn offloaded?
[file]
(= "objects-storage" (:data-backend file)))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; OBJECTS-MAP
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(defn enable-objects-map
[file]
(let [update-page
(fn [page]
(if (and (pmap/pointer-map? page)
(not (pmap/loaded? page)))
page
(update page :objects omap/wrap)))
update-data
(fn [fdata]
(update fdata :pages-index d/update-vals update-page))]
(-> file
(update :data update-data)
(update :features conj "fdata/objects-map"))))
(defn process-objects
"Apply a function to all objects-map on the file. Usualy used for convert
the objects-map instances to plain maps"
@@ -55,35 +34,237 @@
(fn [page]
(update page :objects
(fn [objects]
(if (omap/objects-map? objects)
(if (or (omap/objects-map? objects)
(omap.legacy/objects-map? objects))
(update-fn objects)
objects)))))
fdata))
(defn realize-objects
"Process a file and remove all instances of objects map realizing them
to a plain data. Used in operation where is more efficient have the
whole file loaded in memory or we going to persist it in an
alterantive storage."
[_cfg file]
(update file :data process-objects (partial into {})))
(defn enable-objects-map
[file & _opts]
(let [update-page
(fn [page]
(update page :objects omap/wrap))
update-data
(fn [fdata]
(update fdata :pages-index d/update-vals update-page))]
(-> file
(update :data update-data)
(update :features conj "fdata/objects-map"))))
(defn disable-objects-map
[file & _opts]
(let [update-page
(fn [page]
(update page :objects #(into {} %)))
update-data
(fn [fdata]
(update fdata :pages-index d/update-vals update-page))]
(-> file
(update :data update-data)
(update :features disj "fdata/objects-map"))))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; STORAGE
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(defmulti resolve-file-data
(fn [_cfg file] (get file :backend "legacy-db")))
(defmethod resolve-file-data "legacy-db"
[_cfg {:keys [legacy-data] :as file}]
(-> file
(assoc :data legacy-data)
(dissoc :legacy-data)))
(defmethod resolve-file-data "db"
[_cfg file]
(dissoc file :legacy-data))
(defmethod resolve-file-data "storage"
[cfg {:keys [metadata] :as file}]
(let [storage (sto/resolve cfg ::db/reuse-conn true)
ref-id (:storage-ref-id metadata)
data (->> (sto/get-object storage ref-id)
(sto/get-object-bytes storage))]
(-> file
(assoc :data data)
(dissoc :legacy-data))))
(defn decode-file-data
[_cfg {:keys [data] :as file}]
(cond-> file
(bytes? data)
(assoc :data (blob/decode data))))
(def ^:private sql:insert-file-data
"INSERT INTO file_data (file_id, id, created_at, modified_at, deleted_at,
type, backend, metadata, data)
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)")
(def ^:private sql:upsert-file-data
(str sql:insert-file-data
" ON CONFLICT (file_id, id)
DO UPDATE SET modified_at=?,
deleted_at=?,
backend=?,
metadata=?,
data=?"))
(defn- upsert-in-database
[cfg {:keys [id file-id created-at modified-at deleted-at type backend data metadata]}]
(let [created-at (or created-at (ct/now))
metadata (some-> metadata db/json)
modified-at (or modified-at created-at)]
(db/exec-one! cfg [sql:upsert-file-data
file-id id
created-at
modified-at
deleted-at
type
backend
metadata
data
modified-at
deleted-at
backend
metadata
data])))
(defn- handle-persistence
[cfg {:keys [type backend id file-id data] :as params}]
(cond
(= backend "storage")
(let [storage (sto/resolve cfg)
content (sto/content data)
sobject (sto/put-object! storage
{::sto/content content
::sto/touch true
:bucket "file-data"
:content-type "application/octet-stream"
:file-id file-id
:id id})
metadata {:storage-ref-id (:id sobject)}
params (-> params
(assoc :metadata metadata)
(assoc :data nil))]
(upsert-in-database cfg params))
(= backend "db")
(->> (dissoc params :metadata)
(upsert-in-database cfg))
(= backend "legacy-db")
(cond
(= type "main")
(do
(db/delete! cfg :file-data
{:id id :file-id file-id :type "main"}
{::db/return-keys false})
(db/update! cfg :file
{:data data}
{:id file-id}
{::db/return-keys false}))
(= type "snapshot")
(do
(db/delete! cfg :file-data
{:id id :file-id file-id :type "snapshot"}
{::db/return-keys false})
(db/update! cfg :file-change
{:data data}
{:file-id file-id :id id}
{::db/return-keys false}))
(= type "fragment")
(upsert-in-database cfg
(-> (dissoc params :metadata)
(assoc :backend "db")))
:else
(throw (RuntimeException. "not implemented")))
:else
(throw (IllegalArgumentException.
(str "backend '" backend "' not supported")))))
(defn process-metadata
[cfg metadata]
(when-let [storage-id (:storage-ref-id metadata)]
(let [storage (sto/resolve cfg ::db/reuse-conn true)]
(sto/touch-object! storage storage-id))))
(defn- default-backend
[backend]
(or backend (cf/get :file-data-backend)))
(def ^:private schema:metadata
[:map {:title "Metadata"}
[:storage-ref-id {:optional true} ::sm/uuid]])
(def decode-metadata-with-schema
(sm/decoder schema:metadata sm/json-transformer))
(defn decode-metadata
[metadata]
(some-> metadata
(db/decode-json-pgobject)
(decode-metadata-with-schema)))
(def ^:private schema:update-params
[:map {:closed true}
[:id ::sm/uuid]
[:type [:enum "main" "snapshot" "fragment"]]
[:file-id ::sm/uuid]
[:backend {:optional true} [:enum "db" "legacy-db" "storage"]]
[:metadata {:optional true} [:maybe schema:metadata]]
[:data {:optional true} bytes?]
[:created-at {:optional true} ::ct/inst]
[:modified-at {:optional true} [:maybe ::ct/inst]]
[:deleted-at {:optional true} [:maybe ::ct/inst]]])
(def ^:private check-update-params
(sm/check-fn schema:update-params :hint "invalid params received for update"))
(defn upsert!
"Create or update file data"
[cfg params & {:as opts}]
(let [params (-> (check-update-params params)
(update :backend default-backend))]
(some->> (:metadata params)
(process-metadata cfg))
(-> (handle-persistence cfg params)
(db/get-update-count)
(pos?))))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; POINTER-MAP
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(defn get-file-data
"Get file data given a file instance."
[system file]
(if (offloaded? file)
(let [storage (sto/resolve system ::db/reuse-conn true)]
(->> (sto/get-object storage (:data-ref-id file))
(sto/get-object-bytes storage)))
(:data file)))
(defn resolve-file-data
[system file]
(let [data (get-file-data system file)]
(assoc file :data data)))
(defn load-pointer
"A database loader pointer helper"
[system file-id id]
(let [fragment (db/get* system :file-data-fragment
{:id id :file-id file-id}
{::sql/columns [:data :data-backend :data-ref-id :id]})]
[cfg file-id id]
(let [fragment (some-> (db/get* cfg :file-data
{:id id :file-id file-id :type "fragment"}
{::sql/columns [:data :backend :id :metadata]})
(update :metadata decode-metadata))]
(l/trc :hint "load pointer"
:file-id (str file-id)
@@ -97,22 +278,21 @@
:file-id file-id
:fragment-id id))
(let [data (get-file-data system fragment)]
;; FIXME: conditional thread scheduling for decoding big objects
(blob/decode data))))
(-> (resolve-file-data cfg fragment)
(get :data)
(blob/decode))))
(defn persist-pointers!
"Persist all currently tracked pointer objects"
[system file-id]
(let [conn (db/get-connection system)]
(doseq [[id item] @pmap/*tracked*]
(when (pmap/modified? item)
(l/trc :hint "persist pointer" :file-id (str file-id) :id (str id))
(let [content (-> item deref blob/encode)]
(db/insert! conn :file-data-fragment
{:id id
:file-id file-id
:data content}))))))
[cfg file-id]
(doseq [[id item] @pmap/*tracked*]
(when (pmap/modified? item)
(l/trc :hint "persist pointer" :file-id (str file-id) :id (str id))
(let [content (-> item deref blob/encode)]
(upsert! cfg {:id id
:file-id file-id
:type "fragment"
:data content})))))
(defn process-pointers
"Apply a function to all pointers on the file. Usuly used for
@@ -126,6 +306,14 @@
(d/update-vals update-fn')
(update :pages-index d/update-vals update-fn'))))
(defn realize-pointers
"Process a file and remove all instances of pointers realizing them to
a plain data. Used in operation where is more efficient have the
whole file loaded in memory."
[cfg {:keys [id] :as file}]
(binding [pmap/*load-fn* (partial load-pointer cfg id)]
(update file :data process-pointers deref)))
(defn get-used-pointer-ids
"Given a file, return all pointer ids used in the data."
[fdata]
@@ -136,10 +324,21 @@
(defn enable-pointer-map
"Enable the fdata/pointer-map feature on the file."
[file]
[file & _opts]
(-> file
(update :data (fn [fdata]
(-> fdata
(update :pages-index d/update-vals pmap/wrap)
(d/update-when :components pmap/wrap))))
(update :features conj "fdata/pointer-map")))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; GENERAL PURPOSE HELPERS
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(defn realize
"A helper that combines realize-pointers and realize-objects"
[cfg file]
(->> file
(realize-pointers cfg)
(realize-objects cfg)))

View File

@@ -8,6 +8,7 @@
"Backend specific code for file migrations. Implemented as permanent feature of files."
(:require
[app.common.data :as d]
[app.common.exceptions :as ex]
[app.common.files.migrations :as fmg :refer [xf:map-name]]
[app.db :as db]
[app.db.sql :as-alias sql]))
@@ -26,14 +27,27 @@
(defn upsert-migrations!
"Persist or update file migrations. Return the updated/inserted number
of rows"
[conn {:keys [id] :as file}]
(let [migrations (or (-> file meta ::fmg/migrated)
(-> file :migrations not-empty)
fmg/available-migrations)
[cfg {:keys [id] :as file}]
(let [conn (db/get-connection cfg)
migrations (or (-> file meta ::fmg/migrated)
(-> file :migrations))
columns [:file-id :name]
rows (mapv (fn [name] [id name]) migrations)]
rows (->> migrations
(mapv (fn [name] [id name]))
(not-empty))]
(when-not rows
(ex/raise :type :internal
:code :missing-migrations
:hint "no migrations available on file"))
(-> (db/insert-many! conn :file-migration columns rows
{::db/return-keys false
::sql/on-conflict-do-nothing true})
(db/get-update-count))))
(defn reset-migrations!
"Replace file migrations"
[cfg {:keys [id] :as file}]
(db/delete! cfg :file-migration {:file-id id})
(upsert-migrations! cfg file))

View File

@@ -0,0 +1,446 @@
;; 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
(ns app.features.file-snapshots
(:require
[app.binfile.common :as bfc]
[app.common.data :as d]
[app.common.exceptions :as ex]
[app.common.features :as-alias cfeat]
[app.common.files.migrations :as fmg]
[app.common.logging :as l]
[app.common.schema :as sm]
[app.common.time :as ct]
[app.common.uuid :as uuid]
[app.config :as cf]
[app.db :as db]
[app.db.sql :as-alias sql]
[app.features.fdata :as fdata]
[app.storage :as sto]
[app.util.blob :as blob]
[app.worker :as wrk]
[cuerdas.core :as str]))
(def sql:snapshots
"SELECT c.id,
c.label,
c.created_at,
c.updated_at AS modified_at,
c.deleted_at,
c.profile_id,
c.created_by,
c.locked_by,
c.revn,
c.features,
c.migrations,
c.version,
c.file_id,
c.data AS legacy_data,
fd.data AS data,
coalesce(fd.backend, 'legacy-db') AS backend,
fd.metadata AS metadata
FROM file_change AS c
LEFT JOIN file_data AS fd ON (fd.file_id = c.file_id
AND fd.id = c.id
AND fd.type = 'snapshot')
WHERE c.label IS NOT NULL")
(defn- decode-snapshot
[snapshot]
(some-> snapshot
(-> (d/update-when :metadata fdata/decode-metadata)
(d/update-when :migrations db/decode-pgarray [])
(d/update-when :features db/decode-pgarray #{}))))
(def ^:private sql:get-minimal-file
"SELECT f.id,
f.revn,
f.modified_at,
f.deleted_at,
fd.backend AS backend,
fd.metadata AS metadata
FROM file AS f
LEFT JOIN file_data AS fd ON (fd.file_id = f.id AND fd.id = f.id)
WHERE f.id = ?")
(defn- get-minimal-file
[cfg id & {:as opts}]
(-> (db/get-with-sql cfg [sql:get-minimal-file id] opts)
(d/update-when :metadata fdata/decode-metadata)))
(def ^:private sql:get-snapshot-without-data
(str "WITH snapshots AS (" sql:snapshots ")"
"SELECT c.id,
c.label,
c.revn,
c.created_at,
c.modified_at,
c.deleted_at,
c.profile_id,
c.created_by,
c.locked_by,
c.features,
c.metadata,
c.migrations,
c.version,
c.file_id
FROM snapshots AS c
WHERE c.id = ?
AND CASE WHEN c.created_by = 'user'
THEN c.deleted_at IS NULL
WHEN c.created_by = 'system'
THEN c.deleted_at IS NULL OR c.deleted_at >= ?::timestamptz
END"))
(defn get-minimal-snapshot
[cfg snapshot-id]
(let [now (ct/now)]
(-> (db/get-with-sql cfg [sql:get-snapshot-without-data snapshot-id now]
{::db/remove-deleted false})
(decode-snapshot))))
(def ^:private sql:get-snapshot
(str sql:snapshots
" AND c.file_id = ?
AND c.id = ?
AND CASE WHEN c.created_by = 'user'
THEN (c.deleted_at IS NULL)
WHEN c.created_by = 'system'
THEN (c.deleted_at IS NULL OR c.deleted_at >= ?::timestamptz)
END"))
(defn- get-snapshot
"Get snapshot with decoded data"
[cfg file-id snapshot-id]
(let [now (ct/now)]
(->> (db/get-with-sql cfg [sql:get-snapshot file-id snapshot-id now]
{::db/remove-deleted false})
(decode-snapshot)
(fdata/resolve-file-data cfg)
(fdata/decode-file-data cfg))))
(def ^:private sql:get-visible-snapshots
(str "WITH "
"snapshots1 AS ( " sql:snapshots "),"
"snapshots2 AS (
SELECT c.id,
c.label,
c.revn,
c.version,
c.created_at,
c.modified_at,
c.created_by,
c.locked_by,
c.profile_id,
c.deleted_at
FROM snapshots1 AS c
WHERE c.file_id = ?
), snapshots3 AS (
(SELECT * FROM snapshots2
WHERE created_by = 'system'
AND (deleted_at IS NULL OR
deleted_at >= ?::timestamptz)
LIMIT 500)
UNION ALL
(SELECT * FROM snapshots2
WHERE created_by = 'user'
AND deleted_at IS NULL
LIMIT 500)
)
SELECT * FROM snapshots3
ORDER BY created_at DESC"))
(defn get-visible-snapshots
"Return a list of snapshots fecheable from the API, it has a limited
set of fields and applies big but safe limits over all available
snapshots. It return a ordered vector by the snapshot date of
creation."
[cfg file-id]
(let [now (ct/now)]
(->> (db/exec! cfg [sql:get-visible-snapshots file-id now])
(mapv decode-snapshot))))
(def ^:private schema:decoded-file
[:map {:title "DecodedFile"}
[:id ::sm/uuid]
[:revn :int]
[:vern :int]
[:data :map]
[:version :int]
[:features ::cfeat/features]
[:migrations [::sm/set :string]]])
(def ^:private schema:snapshot
[:map {:title "Snapshot"}
[:id ::sm/uuid]
[:revn [::sm/int {:min 0}]]
[:version [::sm/int {:min 0}]]
[:features ::cfeat/features]
[:migrations [::sm/set ::sm/text]]
[:profile-id {:optional true} ::sm/uuid]
[:label ::sm/text]
[:file-id ::sm/uuid]
[:created-by [:enum "system" "user" "admin"]]
[:deleted-at {:optional true} ::ct/inst]
[:modified-at ::ct/inst]
[:created-at ::ct/inst]])
(def ^:private check-snapshot
(sm/check-fn schema:snapshot))
(def ^:private check-decoded-file
(sm/check-fn schema:decoded-file))
(defn- generate-snapshot-label
[]
(let [ts (-> (ct/now)
(ct/format-inst)
(str/replace #"[T:\.]" "-")
(str/rtrim "Z"))]
(str "snapshot-" ts)))
(def ^:private schema:create-params
[:map {:title "SnapshotCreateParams"}
[:profile-id ::sm/uuid]
[:created-by {:optional true} [:enum "user" "system"]]
[:label {:optional true} ::sm/text]
[:session-id {:optional true} ::sm/uuid]
[:modified-at {:optional true} ::ct/inst]
[:deleted-at {:optional true} ::ct/inst]])
(def ^:private check-create-params
(sm/check-fn schema:create-params))
(defn create!
"Create a file snapshot; expects a non-encoded file"
[cfg file & {:as params}]
(let [{:keys [label created-by deleted-at profile-id session-id]}
(check-create-params params)
file
(check-decoded-file file)
created-by
(or created-by "system")
snapshot-id
(uuid/next)
created-at
(ct/now)
deleted-at
(or deleted-at
(if (= created-by "system")
(ct/in-future (cf/get-deletion-delay))
nil))
label
(or label (generate-snapshot-label))
snapshot
(cond-> {:id snapshot-id
:revn (:revn file)
:version (:version file)
:file-id (:id file)
:features (:features file)
:migrations (:migrations file)
:label label
:created-at created-at
:modified-at created-at
:created-by created-by}
deleted-at
(assoc :deleted-at deleted-at)
:always
(check-snapshot))]
(db/insert! cfg :file-change
(-> snapshot
(update :features into-array)
(update :migrations into-array)
(assoc :updated-at created-at)
(assoc :profile-id profile-id)
(assoc :session-id session-id)
(dissoc :modified-at))
{::db/return-keys false})
(fdata/upsert! cfg
{:id snapshot-id
:file-id (:id file)
:type "snapshot"
:data (blob/encode (:data file))
:created-at created-at
:deleted-at deleted-at})
snapshot))
(def ^:private schema:update-params
[:map {:title "SnapshotUpdateParams"}
[:id ::sm/uuid]
[:file-id ::sm/uuid]
[:label ::sm/text]
[:modified-at {:optional true} ::ct/inst]])
(def ^:private check-update-params
(sm/check-fn schema:update-params))
(defn update!
[cfg params]
(let [{:keys [id file-id label modified-at]}
(check-update-params params)
modified-at
(or modified-at (ct/now))]
(db/update! cfg :file-data
{:deleted-at nil
:modified-at modified-at}
{:file-id file-id
:id id
:type "snapshot"}
{::db/return-keys false})
(-> (db/update! cfg :file-change
{:label label
:created-by "user"
:updated-at modified-at
:deleted-at nil}
{:file-id file-id
:id id}
{::db/return-keys false})
(db/get-update-count)
(pos?))))
(defn restore!
[{:keys [::db/conn] :as cfg} file-id snapshot-id]
(let [file (get-minimal-file conn file-id {::db/for-update true})
vern (rand-int Integer/MAX_VALUE)
storage
(sto/resolve cfg {::db/reuse-conn true})
snapshot
(get-snapshot cfg file-id snapshot-id)]
(when-not snapshot
(ex/raise :type :not-found
:code :snapshot-not-found
:hint "unable to find snapshot with the provided label"
:snapshot-id snapshot-id
:file-id file-id))
(when-not (:data snapshot)
(ex/raise :type :internal
:code :snapshot-without-data
:hint "snapshot has no data"
:label (:label snapshot)
:file-id file-id))
(let [;; If the snapshot has applied migrations stored, we reuse
;; them, if not, we take a safest set of migrations as
;; starting point. This is because, at the time of
;; implementing snapshots, migrations were not taken into
;; account so we need to make this backward compatible in
;; some way.
migrations
(or (:migrations snapshot)
(fmg/generate-migrations-from-version 67))
file
(-> file
(update :revn inc)
(assoc :migrations migrations)
(assoc :data (:data snapshot))
(assoc :vern vern)
(assoc :version (:version snapshot))
(assoc :has-media-trimmed false)
(assoc :modified-at (:modified-at snapshot))
(assoc :features (:features snapshot)))]
(l/dbg :hint "restoring snapshot"
:file-id (str file-id)
:label (:label snapshot)
:snapshot-id (str (:id snapshot)))
;; In the same way, on reseting the file data, we need to restore
;; the applied migrations on the moment of taking the snapshot
(bfc/update-file! cfg file ::bfc/reset-migrations? true)
;; FIXME: this should be separated functions, we should not have
;; inline sql here.
;; clean object thumbnails
(let [sql (str "update file_tagged_object_thumbnail "
" set deleted_at = now() "
" where file_id=? returning media_id")
res (db/exec! conn [sql file-id])]
(doseq [media-id (into #{} (keep :media-id) res)]
(sto/touch-object! storage media-id)))
;; clean file thumbnails
(let [sql (str "update file_thumbnail "
" set deleted_at = now() "
" where file_id=? returning media_id")
res (db/exec! conn [sql file-id])]
(doseq [media-id (into #{} (keep :media-id) res)]
(sto/touch-object! storage media-id)))
vern)))
(defn delete!
[cfg & {:keys [id file-id deleted-at]}]
(assert (uuid? id) "missing id")
(assert (uuid? file-id) "missing file-id")
(assert (ct/inst? deleted-at) "missing deleted-at")
(wrk/submit! {::db/conn (db/get-connection cfg)
::wrk/task :delete-object
::wrk/params {:object :snapshot
:deleted-at deleted-at
:file-id file-id
:id id}})
(db/update! cfg :file-change
{:deleted-at deleted-at}
{:id id :file-id file-id}
{::db/return-keys false})
true)
(def ^:private sql:get-snapshots
(str sql:snapshots " AND c.file_id = ?"))
(defn lock-by!
[conn id profile-id]
(-> (db/update! conn :file-change
{:locked-by profile-id}
{:id id}
{::db/return-keys false})
(db/get-update-count)
(pos?)))
(defn unlock!
[conn id]
(-> (db/update! conn :file-change
{:locked-by nil}
{:id id}
{::db/return-keys false})
(db/get-update-count)
(pos?)))
(defn reduce-snapshots
"Process the file snapshots using efficient reduction; the file
reduction comes with all snapshots, including maked as deleted"
[cfg file-id xform f init]
(let [conn (db/get-connection cfg)
xform (comp
(map (partial fdata/resolve-file-data cfg))
(map (partial fdata/decode-file-data cfg))
xform)]
(->> (db/plan conn [sql:get-snapshots file-id] {:fetch-size 1})
(transduce xform f init))))

View File

@@ -0,0 +1,32 @@
;; 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
(ns app.features.logical-deletion
"A code related to handle logical deletion mechanism"
(:require
[app.common.time :as ct]
[app.config :as cf]))
(def ^:private canceled-status
#{"canceled" "unpaid"})
(defn get-deletion-delay
"Calculate the next deleted-at for a resource (file, team, etc) in function
of team settings"
[team]
(if-let [{:keys [type status]} (get team :subscription)]
(cond
(and (= "unlimited" type) (not (contains? canceled-status status)))
(ct/duration {:days 30})
(and (= "enterprise" type) (not (contains? canceled-status status)))
(ct/duration {:days 90})
:else
(cf/get-deletion-delay))
(cf/get-deletion-delay)))

View File

@@ -17,16 +17,16 @@
[app.http.awsns :as-alias awsns]
[app.http.debug :as-alias debug]
[app.http.errors :as errors]
[app.http.management :as mgmt]
[app.http.middleware :as mw]
[app.http.security :as sec]
[app.http.session :as session]
[app.http.websocket :as-alias ws]
[app.main :as-alias main]
[app.metrics :as mtx]
[app.rpc :as-alias rpc]
[app.rpc.doc :as-alias rpc.doc]
[app.setup :as-alias setup]
[integrant.core :as ig]
[promesa.exec :as px]
[reitit.core :as r]
[reitit.middleware :as rr]
[yetti.adapter :as yt]
@@ -53,6 +53,8 @@
[:map
[::port ::sm/int]
[::host ::sm/text]
[::io-threads {:optional true} ::sm/int]
[::max-worker-threads {:optional true} ::sm/int]
[::max-body-size {:optional true} ::sm/int]
[::max-multipart-body-size {:optional true} ::sm/int]
[::router {:optional true} [:fn r/router?]]
@@ -63,30 +65,41 @@
(assert (sm/check schema:server-params params)))
(defmethod ig/init-key ::server
[_ {:keys [::handler ::router ::host ::port] :as cfg}]
[_ {:keys [::handler ::router ::host ::port ::mtx/metrics] :as cfg}]
(l/info :hint "starting http server" :port port :host host)
(let [options {:http/port port
:http/host host
:http/max-body-size (::max-body-size cfg)
:http/max-multipart-body-size (::max-multipart-body-size cfg)
:xnio/io-threads (or (::io-threads cfg)
(max 3 (px/get-available-processors)))
:xnio/dispatch :virtual
:ring/compat :ring2
:socket/backlog 4069}
(let [on-dispatch
(fn [_ start-at-ns]
(let [timing (- (System/nanoTime) start-at-ns)
timing (int (/ timing 1000000))]
(mtx/run! metrics
:id :http-server-dispatch-timing
:val timing)))
handler (cond
(some? router)
(router-handler router)
options
{:http/port port
:http/host host
:http/max-body-size (::max-body-size cfg)
:http/max-multipart-body-size (::max-multipart-body-size cfg)
:xnio/direct-buffers false
:xnio/io-threads (::io-threads cfg)
:xnio/max-worker-threads (::max-worker-threads cfg)
:ring/compat :ring2
:events/on-dispatch on-dispatch
:socket/backlog 4069}
(some? handler)
handler
handler
(cond
(some? router)
(router-handler router)
:else
(throw (UnsupportedOperationException. "handler or router are required")))
(some? handler)
handler
options (d/without-nils options)
server (yt/server handler options)]
:else
(throw (UnsupportedOperationException. "handler or router are required")))
server
(yt/server handler (d/without-nils options))]
(assoc cfg ::server (yt/start! server))))
@@ -135,12 +148,12 @@
[:map
[::ws/routes schema:routes]
[::rpc/routes schema:routes]
[::rpc.doc/routes schema:routes]
[::oidc/routes schema:routes]
[::assets/routes schema:routes]
[::debug/routes schema:routes]
[::mtx/routes schema:routes]
[::awsns/routes schema:routes]
[::mgmt/routes schema:routes]
::session/manager
::setup/props
::db/pool])
@@ -153,12 +166,14 @@
[_ cfg]
(rr/router
[["" {:middleware [[mw/server-timing]
[sec/sec-fetch-metadata]
[mw/params]
[mw/format-response]
[mw/auth {:bearer (partial session/decode-token cfg)
:cookie (partial session/decode-token cfg)
:token (partial actoken/decode-token cfg)}]
[mw/parse-request]
[mw/errors errors/handle]
[session/soft-auth cfg]
[actoken/soft-auth cfg]
[mw/restrict-methods]]}
(::mtx/routes cfg)
@@ -168,9 +183,9 @@
["/webhooks"
(::awsns/routes cfg)]
(::ws/routes cfg)
["/management"
(::mgmt/routes cfg)]
["/api" {:middleware [[mw/cors]]}
(::oidc/routes cfg)
(::rpc.doc/routes cfg)
(::rpc/routes cfg)]]]))
(::ws/routes cfg)
(::oidc/routes cfg)
(::rpc/routes cfg)]]))

View File

@@ -9,23 +9,19 @@
[app.common.logging :as l]
[app.config :as cf]
[app.db :as db]
[app.http :as-alias http]
[app.main :as-alias main]
[app.setup :as-alias setup]
[app.tokens :as tokens]
[yetti.request :as yreq]))
[app.tokens :as tokens]))
(def header-re #"^Token\s+(.*)")
(defn- get-token
[request]
(some->> (yreq/get-header request "authorization")
(re-matches header-re)
(second)))
(defn- decode-token
[props token]
(when token
(tokens/verify props {:token token :iss "access-token"})))
(defn decode-token
[cfg token]
(try
(tokens/verify cfg {:token token :iss "access-token"})
(catch Throwable cause
(l/trc :hint "exception on decoding token"
:token token
:cause cause))))
(def sql:get-token-data
"SELECT perms, profile_id, expires_at
@@ -35,47 +31,28 @@
OR (expires_at > now()));")
(defn- get-token-data
[pool token-id]
[pool claims]
(when-not (db/read-only? pool)
(some-> (db/exec-one! pool [sql:get-token-data token-id])
(update :perms db/decode-pgarray #{}))))
(defn- wrap-soft-auth
"Soft Authentication, will be executed synchronously on the undertow
worker thread."
[handler {:keys [::setup/props]}]
(letfn [(handle-request [request]
(try
(let [token (get-token request)
claims (decode-token props token)]
(cond-> request
(map? claims)
(assoc ::id (:tid claims))))
(catch Throwable cause
(l/trace :hint "exception on decoding malformed token" :cause cause)
request)))]
(fn [request]
(handler (handle-request request)))))
(when-let [token-id (get claims :tid)]
(some-> (db/exec-one! pool [sql:get-token-data token-id])
(update :perms db/decode-pgarray #{})))))
(defn- wrap-authz
"Authorization middleware, will be executed synchronously on vthread."
[handler {:keys [::db/pool]}]
(fn [request]
(let [{:keys [perms profile-id expires-at]} (some->> (::id request) (get-token-data pool))]
(handler (cond-> request
(some? perms)
(assoc ::perms perms)
(some? profile-id)
(assoc ::profile-id profile-id)
(some? expires-at)
(assoc ::expires-at expires-at))))))
(let [{:keys [type claims]} (get request ::http/auth-data)]
(if (= :token type)
(let [{:keys [perms profile-id expires-at]} (some->> claims (get-token-data pool))]
;; FIXME: revisit this, this data looks unused
(handler (cond-> request
(some? perms)
(assoc ::perms perms)
(some? profile-id)
(assoc ::profile-id profile-id)
(some? expires-at)
(assoc ::expires-at expires-at))))
(def soft-auth
{:name ::soft-auth
:compile (fn [& _]
(when (contains? cf/flags :access-tokens)
wrap-soft-auth))})
(handler request)))))
(def authz
{:name ::authz

View File

@@ -9,18 +9,18 @@
(:require
[app.common.data :as d]
[app.common.exceptions :as ex]
[app.common.time :as ct]
[app.common.uri :as u]
[app.db :as db]
[app.storage :as sto]
[app.util.time :as dt]
[integrant.core :as ig]
[yetti.response :as-alias yres]))
(def ^:private cache-max-age
(dt/duration {:hours 24}))
(ct/duration {:hours 24}))
(def ^:private signature-max-age
(dt/duration {:hours 24 :minutes 15}))
(ct/duration {:hours 24 :minutes 15}))
(defn get-id
[{:keys [path-params]}]

View File

@@ -17,11 +17,9 @@
[app.main :as-alias main]
[app.setup :as-alias setup]
[app.tokens :as tokens]
[app.worker :as-alias wrk]
[clojure.data.json :as j]
[cuerdas.core :as str]
[integrant.core :as ig]
[promesa.exec :as px]
[yetti.request :as yreq]
[yetti.response :as-alias yres]))
@@ -40,8 +38,8 @@
[_ cfg]
(letfn [(handler [request]
(let [data (-> request yreq/body slurp)]
(px/run! :vthread (partial handle-request cfg data)))
{::yres/status 200})]
(handle-request cfg data)
{::yres/status 200}))]
["/sns" {:handler handler
:allowed-methods #{:post}}]))
@@ -109,7 +107,7 @@
[cfg headers]
(let [tdata (get headers "x-penpot-data")]
(when-not (str/empty? tdata)
(let [result (tokens/verify (::setup/props cfg) {:token tdata :iss :profile-identity})]
(let [result (tokens/verify cfg {:token tdata :iss :profile-identity})]
(:profile-id result)))))
(defn- parse-notification

View File

@@ -9,8 +9,7 @@
(:require
[app.common.schema :as sm]
[integrant.core :as ig]
[java-http-clj.core :as http]
[promesa.core :as p])
[java-http-clj.core :as http])
(:import
java.net.http.HttpClient))
@@ -29,14 +28,9 @@
(defn send!
([client req] (send! client req {}))
([client req {:keys [response-type sync?] :or {response-type :string sync? false}}]
([client req {:keys [response-type] :or {response-type :string}}]
(assert (client? client) "expected valid http client")
(if sync?
(http/send req {:client client :as response-type})
(try
(http/send-async req {:client client :as response-type})
(catch Throwable cause
(p/rejected cause))))))
(http/send req {:client client :as response-type})))
(defn- resolve-client
[params]
@@ -56,8 +50,8 @@
([cfg-or-client request]
(let [client (resolve-client cfg-or-client)
request (update request :uri str)]
(send! client request {:sync? true})))
(send! client request {})))
([cfg-or-client request options]
(let [client (resolve-client cfg-or-client)
request (update request :uri str)]
(send! client request (merge {:sync? true} options)))))
(send! client request options))))

View File

@@ -15,21 +15,24 @@
[app.common.features :as cfeat]
[app.common.logging :as l]
[app.common.pprint :as pp]
[app.common.time :as ct]
[app.common.transit :as t]
[app.common.uuid :as uuid]
[app.config :as cf]
[app.db :as db]
[app.features.file-migrations :as feat.fmig]
[app.http.session :as session]
[app.rpc.commands.auth :as auth]
[app.rpc.commands.files-create :refer [create-file]]
[app.rpc.commands.profile :as profile]
[app.rpc.commands.teams :as teams]
[app.setup :as-alias setup]
[app.srepl.helpers :as srepl]
[app.setup.clock :as clock]
[app.srepl.main :as srepl]
[app.storage :as-alias sto]
[app.storage.tmp :as tmp]
[app.util.blob :as blob]
[app.util.template :as tmpl]
[app.util.time :as dt]
[cuerdas.core :as str]
[datoteka.io :as io]
[emoji.core :as emj]
@@ -47,29 +50,35 @@
(defn index-handler
[_cfg _request]
{::yres/status 200
::yres/headers {"content-type" "text/html"}
::yres/body (-> (io/resource "app/templates/debug.tmpl")
(tmpl/render {:version (:full cf/version)}))})
(let [{:keys [clock offset]} @clock/current]
{::yres/status 200
::yres/headers {"content-type" "text/html"}
::yres/body (-> (io/resource "app/templates/debug.tmpl")
(tmpl/render {:version (:full cf/version)
:current-clock (str clock)
:current-offset (if offset
(ct/format-duration offset)
"NO OFFSET")
:current-time (ct/format-inst (ct/now) :http)
:supported-features cfeat/supported-features}))}))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; FILE CHANGES
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(defn prepare-response
[body]
(let [headers {"content-type" "application/transit+json"}]
{::yres/status 200
::yres/body body
::yres/headers headers}))
(defn- get-resolved-file
[cfg file-id]
(some-> (bfc/get-file cfg file-id :migrate? false)
(update :data blob/encode)))
(defn prepare-download-response
[body filename]
(let [headers {"content-disposition" (str "attachment; filename=" filename)
"content-type" "application/octet-stream"}]
{::yres/status 200
::yres/body body
::yres/headers headers}))
(defn prepare-download
[file filename]
{::yres/status 200
::yres/headers
{"content-disposition" (str "attachment; filename=" filename ".json")
"content-type" "application/octet-stream"}
::yres/body
(t/encode file {:type :json-verbose})})
(def sql:retrieve-range-of-changes
"select revn, changes from file_change where file_id=? and revn >= ? and revn <= ? order by revn")
@@ -77,45 +86,51 @@
(def sql:retrieve-single-change
"select revn, changes, data from file_change where file_id=? and revn = ?")
(defn- retrieve-file-data
[{:keys [::db/pool]} {:keys [params ::session/profile-id] :as request}]
(defn- download-file-data
[cfg {:keys [params ::session/profile-id] :as request}]
(let [file-id (some-> params :file-id parse-uuid)
revn (some-> params :revn parse-long)
filename (str file-id)]
(when-not file-id
(ex/raise :type :validation
:code :missing-arguments))
(let [data (if (integer? revn)
(some-> (db/exec-one! pool [sql:retrieve-single-change file-id revn]) :data)
(some-> (db/get-by-id pool :file file-id) :data))]
(when-not data
(ex/raise :type :not-found
:code :enpty-data
:hint "empty response"))
(if-let [file (get-resolved-file cfg file-id)]
(cond
(contains? params :download)
(prepare-download-response data filename)
(prepare-download file filename)
(contains? params :clone)
(let [profile (profile/get-profile pool profile-id)
project-id (:default-project-id profile)]
(db/tx-run! cfg
(fn [{:keys [::db/conn] :as cfg}]
(let [profile (profile/get-profile conn profile-id)
project-id (:default-project-id profile)
file (-> (create-file cfg {:id (uuid/next)
:name (str "Cloned: " (:name file))
:features (:features file)
:project-id project-id
:profile-id profile-id})
(assoc :data (:data file))
(assoc :migrations (:migrations file)))]
(db/run! pool (fn [{:keys [::db/conn] :as cfg}]
(create-file cfg {:id file-id
:name (str "Cloned file: " filename)
:project-id project-id
:profile-id profile-id})
(db/update! conn :file
{:data data}
{:id file-id})
{::yres/status 201
::yres/body "OK CREATED"})))
(feat.fmig/reset-migrations! conn file)
(db/update! conn :file
{:data (:data file)}
{:id (:id file)}
{::db/return-keys false})
{::yres/status 201
::yres/body "OK CLONED"})))
:else
(prepare-response (blob/decode data))))))
(ex/raise :type :validation
:code :invalid-params
:hint "invalid button"))
(ex/raise :type :not-found
:code :enpty-data
:hint "empty response"))))
(defn- is-file-exists?
[pool id]
@@ -123,81 +138,61 @@
(-> (db/exec-one! pool [sql id]) :exists)))
(defn- upload-file-data
[{:keys [::db/pool]} {:keys [::session/profile-id params] :as request}]
[{:keys [::db/pool] :as cfg} {:keys [::session/profile-id params] :as request}]
(let [profile (profile/get-profile pool profile-id)
project-id (:default-project-id profile)
data (some-> params :file :path io/read*)]
file (some-> params :file :path io/read* t/decode)]
(if (and data project-id)
(let [fname (str "Imported file *: " (dt/now))
(if (and file project-id)
(let [fname (str "Imported: " (:name file) "(" (ct/now) ")")
reuse-id? (contains? params :reuseid)
file-id (or (and reuse-id? (ex/ignoring (-> params :file :filename parse-uuid)))
(uuid/next))]
(if (and reuse-id? file-id
(is-file-exists? pool file-id))
(do
(db/update! pool :file
{:data data
:deleted-at nil}
{:id file-id})
{::yres/status 200
::yres/body "OK UPDATED"})
(db/tx-run! cfg
(fn [{:keys [::db/conn] :as cfg}]
(db/update! conn :file
{:data (:data file)
:features (into-array (:features file))
:deleted-at nil}
{:id file-id}
{::db/return-keys false})
(feat.fmig/reset-migrations! conn file)
{::yres/status 200
::yres/body "OK UPDATED"}))
(db/tx-run! cfg
(fn [{:keys [::db/conn] :as cfg}]
(let [file (-> (create-file cfg {:id file-id
:name fname
:features (:features file)
:project-id project-id
:profile-id profile-id})
(assoc :data (:data file))
(assoc :migrations (:migrations file)))]
(db/run! pool (fn [{:keys [::db/conn] :as cfg}]
(create-file cfg {:id file-id
:name fname
:project-id project-id
:profile-id profile-id})
(db/update! conn :file
{:data data}
{:id file-id})
{:data (:data file)}
{:id file-id}
{::db/return-keys false})
(feat.fmig/reset-migrations! conn file)
{::yres/status 201
::yres/body "OK CREATED"}))))
::yres/body "OK CREATED"})))))
{::yres/status 500
::yres/body "ERROR"})))
(ex/raise :type :validation
:code :invalid-params
:hint "invalid file uploaded"))))
(defn file-data-handler
(defn raw-export-import-handler
[cfg request]
(case (yreq/method request)
:get (retrieve-file-data cfg request)
:get (download-file-data cfg request)
:post (upload-file-data cfg request)
(ex/raise :type :http
:code :method-not-found)))
(defn file-changes-handler
[{:keys [::db/pool]} {:keys [params] :as request}]
(letfn [(retrieve-changes [file-id revn]
(if (str/includes? revn ":")
(let [[start end] (->> (str/split revn #":")
(map str/trim)
(map parse-long))]
(some->> (db/exec! pool [sql:retrieve-range-of-changes file-id start end])
(map :changes)
(map blob/decode)
(mapcat identity)
(vec)))
(if-let [revn (parse-long revn)]
(let [item (db/exec-one! pool [sql:retrieve-single-change file-id revn])]
(some-> item :changes blob/decode vec))
(ex/raise :type :validation :code :invalid-arguments))))]
(let [file-id (some-> params :id parse-uuid)
revn (or (some-> params :revn parse-long) "latest")
filename (str file-id)]
(when (or (not file-id) (not revn))
(ex/raise :type :validation
:code :invalid-arguments
:hint "missing arguments"))
(let [data (retrieve-changes file-id revn)]
(if (contains? params :download)
(prepare-download-response data filename)
(prepare-response data))))))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ERROR BROWSER
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
@@ -234,7 +229,7 @@
(-> (io/resource "app/templates/error-report.v3.tmpl")
(tmpl/render (-> content
(assoc :id id)
(assoc :created-at (dt/format-instant created-at :rfc1123))))))]
(assoc :created-at (ct/format-inst created-at :rfc1123))))))]
(if-let [report (get-report request)]
(let [result (case (:version report)
@@ -258,7 +253,7 @@
(defn error-list-handler
[{:keys [::db/pool]} _request]
(let [items (->> (db/exec! pool [sql:error-reports])
(map #(update % :created-at dt/format-instant :rfc1123)))]
(map #(update % :created-at ct/format-inst :rfc1123)))]
{::yres/status 200
::yres/body (-> (io/resource "app/templates/error-list.tmpl")
(tmpl/render {:items items}))
@@ -402,33 +397,67 @@
::yres/headers {"content-type" "text/plain"}
::yres/body (str/ffmt "PROFILE '%' ACTIVATED" (:email profile))}))))))
(defn- reset-file-version
(defn- handle-team-features
[cfg {:keys [params] :as request}]
(let [file-id (some-> params :file-id d/parse-uuid)
version (some-> params :version d/parse-integer)]
(let [team-id (some-> params :team-id d/parse-uuid)
feature (some-> params :feature str)
action (some-> params :action)
skip-check (contains? params :skip-check)]
(when-not (contains? params :force)
(when (nil? team-id)
(ex/raise :type :validation
:code :missing-force
:hint "missing force checkbox"))
:code :invalid-team-id
:hint "provided invalid team id"))
(when (nil? file-id)
(ex/raise :type :validation
:code :invalid-file-id
:hint "provided invalid file id"))
(if (= action "show")
(let [team (db/run! cfg teams/get-team-info {:id team-id})]
{::yres/status 200
::yres/headers {"content-type" "text/plain"}
::yres/body (apply str "Team features:\n"
(->> (:features team)
(map (fn [feature]
(str "- " feature "\n")))))})
(when (nil? version)
(ex/raise :type :validation
:code :invalid-version
:hint "provided invalid version"))
(do
(when-not (contains? params :force)
(ex/raise :type :validation
:code :missing-force
:hint "missing force checkbox"))
(db/tx-run! cfg srepl/process-file! file-id #(assoc % :version version))
(cond
(= action "enable")
(srepl/enable-team-feature! team-id feature :skip-check skip-check)
{::yres/status 200
::yres/headers {"content-type" "text/plain"}
::yres/body "OK"}))
(= action "disable")
(srepl/disable-team-feature! team-id feature :skip-check skip-check)
:else
(ex/raise :type :validation
:code :invalid-action
:hint (str "invalid action: " action)))
{::yres/status 200
::yres/headers {"content-type" "text/plain"}
::yres/body "OK"}))))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; VIRTUAL CLOCK
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(defn- set-virtual-clock
[_ {:keys [params] :as request}]
(let [offset (some-> params :offset str/trim not-empty ct/duration)
reset? (contains? params :reset)]
(if (= "production" (cf/get :tenant))
{::yres/status 501
::yres/body "OPERATION NOT ALLOWED"}
(do
(if (or reset? (zero? (inst-ms offset)))
(clock/set-offset! nil)
(clock/set-offset! offset))
{::yres/status 302
::yres/headers {"location" "/dbg"}}))))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; OTHER SMALL VIEWS/HANDLERS
@@ -481,6 +510,25 @@
(ex/raise :type :authentication
:code :only-admins-allowed)))))})
(def errors
(letfn [(handle-error [cause]
(when-let [data (ex-data cause)]
(when (= :validation (:type data))
(str "Error: " (or (:hint data) (ex-message cause)) "\n"))))]
{:name ::errors
:compile
(fn [& _params]
(fn [handler]
(fn [request]
(try
(handler request)
(catch Throwable cause
(let [body (or (handle-error cause)
(ex/format-throwable cause))]
{::yres/status 400
::yres/headers {"content-type" "text/plain"}
::yres/body body}))))))}))
(defmethod ig/assert-key ::routes
[_ params]
(assert (db/pool? (::db/pool params)) "expected a valid database pool")
@@ -496,11 +544,14 @@
["/changelog" {:handler (partial changelog-handler cfg)}]
["/error/:id" {:handler (partial error-handler cfg)}]
["/error" {:handler (partial error-list-handler cfg)}]
["/actions/resend-email-verification"
{:handler (partial resend-email-notification cfg)}]
["/actions/reset-file-version"
{:handler (partial reset-file-version cfg)}]
["/file/export" {:handler (partial export-handler cfg)}]
["/file/import" {:handler (partial import-handler cfg)}]
["/file/data" {:handler (partial file-data-handler cfg)}]
["/file/changes" {:handler (partial file-changes-handler cfg)}]]])
["/actions" {:middleware [[errors]]}
["/set-virtual-clock"
{:handler (partial set-virtual-clock cfg)}]
["/resend-email-verification"
{:handler (partial resend-email-notification cfg)}]
["/handle-team-features"
{:handler (partial handle-team-features cfg)}]
["/file-export" {:handler (partial export-handler cfg)}]
["/file-import" {:handler (partial import-handler cfg)}]
["/file-raw-export-import" {:handler (partial raw-export-import-handler cfg)}]]]])

View File

@@ -13,6 +13,7 @@
[app.config :as cf]
[app.http :as-alias http]
[app.http.access-token :as-alias actoken]
[app.http.auth :as-alias auth]
[app.http.session :as-alias session]
[app.util.inet :as inet]
[clojure.spec.alpha :as s]
@@ -22,19 +23,16 @@
(defn request->context
"Extracts error report relevant context data from request."
[request]
(let [claims (-> {}
(into (::session/token-claims request))
(into (::actoken/token-claims request)))]
{:request/path (:path request)
:request/method (:method request)
:request/params (:params request)
:request/user-agent (yreq/get-header request "user-agent")
:request/ip-addr (inet/parse-request request)
:request/profile-id (:uid claims)
:version/frontend (or (yreq/get-header request "x-frontend-version") "unknown")
:version/backend (:full cf/version)}))
(let [{:keys [claims] :as auth} (get request ::http/auth-data)]
(-> (cf/logging-context)
(assoc :request/path (:path request))
(assoc :request/method (:method request))
(assoc :request/params (:params request))
(assoc :request/user-agent (yreq/get-header request "user-agent"))
(assoc :request/ip-addr (inet/parse-request request))
(assoc :request/profile-id (get claims :uid))
(assoc :request/auth-data auth)
(assoc :version/frontend (or (yreq/get-header request "x-frontend-version") "unknown")))))
(defmulti handle-error
(fn [cause _ _]
@@ -62,7 +60,6 @@
::yres/body data}
(binding [l/*context* (request->context request)]
(l/err :hint "restriction error" :data data)
{::yres/status 400
::yres/body data}))))
@@ -102,7 +99,7 @@
(= code :invalid-image)
(binding [l/*context* (request->context request)]
(let [cause (or parent-cause err)]
(l/warn :hint "unexpected error on processing image" :cause cause)
(l/warn :hint "image process error" :cause cause)
{::yres/status 400 ::yres/body data}))
:else
@@ -177,7 +174,7 @@
(let [state (.getSQLState ^java.sql.SQLException error)
cause (or parent-cause error)]
(binding [l/*context* (request->context request)]
(l/error :hint "PSQL error"
(l/error :hint "postgresql error"
:cause cause)
(cond
(= state "57014")

View File

@@ -0,0 +1,240 @@
;; 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
(ns app.http.management
"Internal mangement HTTP API"
(:require
[app.common.logging :as l]
[app.common.schema :as sm]
[app.common.schema.generators :as sg]
[app.common.time :as ct]
[app.config :as cf]
[app.db :as db]
[app.http.middleware :as mw]
[app.main :as-alias main]
[app.rpc.commands.profile :as cmd.profile]
[app.setup :as-alias setup]
[app.tokens :as tokens]
[app.worker :as-alias wrk]
[integrant.core :as ig]
[yetti.response :as-alias yres]))
;; ---- ROUTES
(declare ^:private authenticate)
(declare ^:private get-customer)
(declare ^:private update-customer)
(defmethod ig/assert-key ::routes
[_ params]
(assert (db/pool? (::db/pool params)) "expect valid database pool"))
(def ^:private default-system
{:name ::default-system
:compile
(fn [_ _]
(fn [handler cfg]
(fn [request]
(handler cfg request))))})
(def ^:private transaction
{:name ::transaction
:compile
(fn [data _]
(when (:transaction data)
(fn [handler]
(fn [cfg request]
(db/tx-run! cfg handler request)))))})
(defmethod ig/init-key ::routes
[_ {:keys [::setup/props] :as cfg}]
(let [management-key (or (cf/get :management-api-key)
(get props :management-key))]
["" {:middleware [[mw/shared-key-auth management-key]
[default-system cfg]
[transaction]]}
["/authenticate"
{:handler authenticate
:allowed-methods #{:post}}]
["/get-customer"
{:handler get-customer
:transaction true
:allowed-methods #{:post}}]
["/update-customer"
{:handler update-customer
:allowed-methods #{:post}
:transaction true}]]))
;; ---- HELPERS
(defn- coercer
[schema & {:as opts}]
(let [decode-fn (sm/decoder schema sm/json-transformer)
check-fn (sm/check-fn schema opts)]
(fn [data]
(-> data decode-fn check-fn))))
;; ---- API: AUTHENTICATE
(defn- authenticate
[cfg request]
(let [token (-> request :params :token)
result (tokens/verify cfg {:token token :iss "authentication"})]
{::yres/status 200
::yres/body result}))
;; ---- API: GET-CUSTOMER
(def ^:private schema:get-customer
[:map [:id ::sm/uuid]])
(def ^:private coerce-get-customer-params
(coercer schema:get-customer
:type :validation
:hint "invalid data provided for `get-customer` rpc call"))
(def ^:private sql:get-customer-slots
"WITH teams AS (
SELECT tpr.team_id AS id,
tpr.profile_id AS profile_id
FROM team_profile_rel AS tpr
WHERE tpr.is_owner IS true
AND tpr.profile_id = ?
), teams_with_slots AS (
SELECT tpr.team_id AS id,
count(*) AS total
FROM team_profile_rel AS tpr
WHERE tpr.team_id IN (SELECT id FROM teams)
AND tpr.can_edit IS true
GROUP BY 1
ORDER BY 2
)
SELECT max(total) AS total FROM teams_with_slots;")
(defn- get-customer-slots
[cfg profile-id]
(let [result (db/exec-one! cfg [sql:get-customer-slots profile-id])]
(:total result)))
(defn- get-customer
[cfg request]
(let [profile-id (-> request :params coerce-get-customer-params :id)
profile (cmd.profile/get-profile cfg profile-id)
result {:id (get profile :id)
:name (get profile :fullname)
:email (get profile :email)
:num-editors (get-customer-slots cfg profile-id)
:subscription (-> profile :props :subscription)}]
{::yres/status 200
::yres/body result}))
;; ---- API: UPDATE-CUSTOMER
(def ^:private schema:timestamp
(sm/type-schema
{:type ::timestamp
:pred ct/inst?
:type-properties
{:title "inst"
:description "The same as :app.common.time/inst but encodes to epoch"
:error/message "should be an instant"
:gen/gen (->> (sg/small-int)
(sg/fmap (fn [v] (ct/inst v))))
:decode/string ct/inst
:encode/string inst-ms
:decode/json ct/inst
:encode/json inst-ms}}))
(def ^:private schema:subscription
[:map {:title "Subscription"}
[:id ::sm/text]
[:customer-id ::sm/text]
[:type [:enum
"unlimited"
"professional"
"enterprise"]]
[:status [:enum
"active"
"canceled"
"incomplete"
"incomplete_expired"
"past_due"
"paused"
"trialing"
"unpaid"]]
[:billing-period [:enum
"month"
"day"
"week"
"year"]]
[:quantity :int]
[:description [:maybe ::sm/text]]
[:created-at schema:timestamp]
[:start-date [:maybe schema:timestamp]]
[:ended-at [:maybe schema:timestamp]]
[:trial-end [:maybe schema:timestamp]]
[:trial-start [:maybe schema:timestamp]]
[:cancel-at [:maybe schema:timestamp]]
[:canceled-at [:maybe schema:timestamp]]
[:current-period-end [:maybe schema:timestamp]]
[:current-period-start [:maybe schema:timestamp]]
[:cancel-at-period-end :boolean]
[:cancellation-details
[:map {:title "CancellationDetails"}
[:comment [:maybe ::sm/text]]
[:reason [:maybe ::sm/text]]
[:feedback [:maybe
[:enum
"customer_service"
"low_quality"
"missing_feature"
"other"
"switched_service"
"too_complex"
"too_expensive"
"unused"]]]]]])
(def ^:private schema:update-customer
[:map
[:id ::sm/uuid]
[:subscription [:maybe schema:subscription]]])
(def ^:private coerce-update-customer-params
(coercer schema:update-customer
:type :validation
:hint "invalid data provided for `update-customer` rpc call"))
(defn- update-customer
[cfg request]
(let [{:keys [id subscription]}
(-> request :params coerce-update-customer-params)
{:keys [props] :as profile}
(cmd.profile/get-profile cfg id ::db/for-update true)
props
(assoc props :subscription subscription)]
(l/dbg :hint "update customer"
:profile-id (str id)
:subscription-type (get subscription :type)
:subscription-status (get subscription :status)
:subscription-quantity (get subscription :quantity))
(db/update! cfg :profile
{:props (db/tjson props)}
{:id id}
{::db/return-keys false})
{::yres/status 201
::yres/body nil}))

View File

@@ -12,8 +12,11 @@
[app.common.schema :as-alias sm]
[app.common.transit :as t]
[app.config :as cf]
[app.http :as-alias http]
[app.http.errors :as errors]
[app.tokens :as tokens]
[app.util.pointer-map :as pmap]
[buddy.core.codecs :as bc]
[cuerdas.core :as str]
[yetti.adapter :as yt]
[yetti.middleware :as ymw]
@@ -240,3 +243,77 @@
(if (contains? allowed method)
(handler request)
{::yres/status 405}))))))})
(defn- wrap-auth
[handler decoders]
(let [token-re
#"(?i)^(Token|Bearer)\s+(.*)"
get-token-from-authorization
(fn [request]
(when-let [[_ token-type token] (some->> (yreq/get-header request "authorization")
(re-matches token-re))]
(if (= "token" (str/lower token-type))
{:type :token
:token token}
{:type :bearer
:token token})))
get-token-from-cookie
(fn [request]
(let [cname (cf/get :auth-token-cookie-name)
token (some-> (yreq/get-cookie request cname) :value)]
(when-not (str/empty? token)
{:type :cookie
:token token})))
get-token
(some-fn get-token-from-cookie get-token-from-authorization)
process-request
(fn [request]
(if-let [{:keys [type token] :as auth} (get-token request)]
(let [decode-fn (get decoders type)]
(if (or (= type :cookie) (= type :bearer))
(let [metadata (tokens/decode-header token)]
;; NOTE: we only proceed to decode claims on new
;; cookie tokens. The old cookies dont need to be
;; decoded because they use the token string as ID
(if (and (= (:kid metadata) 1)
(= (:ver metadata) 1)
(some? decode-fn))
(assoc request ::http/auth-data (assoc auth
:claims (decode-fn token)
:metadata metadata))
(assoc request ::http/auth-data (assoc auth :metadata {:ver 0}))))
(if decode-fn
(assoc request ::http/auth-data (assoc auth :claims (decode-fn token)))
(assoc request ::http/auth-data auth))))
request))]
(fn [request]
(-> request process-request handler))))
(def auth
{:name ::auth
:compile (constantly wrap-auth)})
(defn- wrap-shared-key-auth
[handler shared-key]
(if shared-key
(let [shared-key (if (string? shared-key)
shared-key
(bc/bytes->b64-str shared-key true))]
(fn [request]
(let [key (yreq/get-header request "x-shared-key")]
(if (= key shared-key)
(handler request)
{::yres/status 403}))))
(fn [_ _]
{::yres/status 403})))
(def shared-key-auth
{:name ::shared-key-auth
:compile (constantly wrap-shared-key-auth)})

View File

@@ -0,0 +1,55 @@
;; 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
(ns app.http.security
"Additional security layer middlewares"
(:require
[app.config :as cf]
[yetti.request :as yreq]
[yetti.response :as yres]))
(def ^:private safe-methods
#{:get :head :options})
(defn- wrap-sec-fetch-metadata
"Sec-Fetch metadata security layer middleware"
[handler]
(fn [request]
(let [site (yreq/get-header request "sec-fetch-site")]
(cond
(= site "same-origin")
(handler request)
(or (= site "same-site")
(= site "cross-site"))
(if (contains? safe-methods (yreq/method request))
(handler request)
{::yres/status 403})
:else
(handler request)))))
(def sec-fetch-metadata
{:name ::sec-fetch-metadata
:compile (fn [_ _]
(when (contains? cf/flags :sec-fetch-metadata-middleware)
wrap-sec-fetch-metadata))})
(defn- wrap-client-header-check
"Check for a penpot custom header to be present as additional CSRF
protection"
[handler]
(fn [request]
(let [client (yreq/get-header request "x-client")]
(if (some? client)
(handler request)
{::yres/status 403}))))
(def client-header-check
{:name ::client-header-check
:compile (fn [_ _]
(when (contains? cf/flags :client-header-check-middleware)
wrap-client-header-check))})

View File

@@ -10,45 +10,40 @@
[app.common.data :as d]
[app.common.logging :as l]
[app.common.schema :as sm]
[app.common.uri :as u]
[app.common.time :as ct]
[app.common.uuid :as uuid]
[app.config :as cf]
[app.db :as db]
[app.db.sql :as sql]
[app.http :as-alias http]
[app.http.auth :as-alias http.auth]
[app.http.session.tasks :as-alias tasks]
[app.main :as-alias main]
[app.setup :as-alias setup]
[app.tokens :as tokens]
[app.util.time :as dt]
[cuerdas.core :as str]
[integrant.core :as ig]
[yetti.request :as yreq]))
[yetti.request :as yreq]
[yetti.response :as yres]))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; DEFAULTS
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; A default cookie name for storing the session.
(def default-auth-token-cookie-name "auth-token")
;; A cookie that we can use to check from other sites of the same
;; domain if a user is authenticated.
(def default-auth-data-cookie-name "auth-data")
;; Default value for cookie max-age
(def default-cookie-max-age (dt/duration {:days 7}))
(def default-cookie-max-age (ct/duration {:days 7}))
;; Default age for automatic session renewal
(def default-renewal-max-age (dt/duration {:hours 6}))
(def default-renewal-max-age (ct/duration {:hours 6}))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; PROTOCOLS
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(defprotocol ISessionManager
(read [_ key])
(write! [_ key data])
(update! [_ data])
(delete! [_ key]))
(read-session [_ id])
(create-session [_ params])
(update-session [_ session])
(delete-session [_ id]))
(defn manager?
[o]
@@ -63,67 +58,82 @@
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(def ^:private schema:params
[:map {:title "session-params"}
[:user-agent ::sm/text]
[:map {:title "SessionParams" :closed true}
[:profile-id ::sm/uuid]
[:created-at ::sm/inst]])
[:user-agent {:optional true} ::sm/text]
[:sso-provider-id {:optional true} ::sm/uuid]
[:sso-session-id {:optional true} :string]])
(def ^:private valid-params?
(sm/validator schema:params))
(defn- prepare-session-params
[key params]
(assert (string? key) "expected key to be a string")
(assert (not (str/blank? key)) "expected key to be not empty")
(assert (valid-params? params) "expected valid params")
{:user-agent (:user-agent params)
:profile-id (:profile-id params)
:created-at (:created-at params)
:updated-at (:created-at params)
:id key})
(defn- database-manager
[pool]
(reify ISessionManager
(read [_ token]
(db/exec-one! pool (sql/select :http-session {:id token})))
(read-session [_ id]
(if (string? id)
;; Backward compatibility
(let [session (db/exec-one! pool (sql/select :http-session {:id id}))]
(-> session
(assoc :modified-at (:updated-at session))
(dissoc :updated-at)))
(db/exec-one! pool (sql/select :http-session-v2 {:id id}))))
(write! [_ key params]
(let [params (prepare-session-params key params)]
(db/insert! pool :http-session params)
params))
(create-session [_ params]
(assert (valid-params? params) "expect valid session params")
(update! [_ params]
(let [updated-at (dt/now)]
(db/update! pool :http-session
{:updated-at updated-at}
{:id (:id params)})
(assoc params :updated-at updated-at)))
(let [now (ct/now)
params (-> params
(assoc :id (uuid/next))
(assoc :created-at now)
(assoc :modified-at now))]
(db/insert! pool :http-session-v2 params
{::db/return-keys true})))
(delete! [_ token]
(db/delete! pool :http-session {:id token})
(update-session [_ session]
(let [modified-at (ct/now)]
(if (string? (:id session))
(db/insert! pool :http-session-v2
(-> session
(assoc :id (uuid/next))
(assoc :created-at modified-at)
(assoc :modified-at modified-at)))
(db/update! pool :http-session-v2
{:modified-at modified-at}
{:id (:id session)}
{::db/return-keys true}))))
(delete-session [_ id]
(if (string? id)
(db/delete! pool :http-session {:id id} {::db/return-keys false})
(db/delete! pool :http-session-v2 {:id id} {::db/return-keys false}))
nil)))
(defn inmemory-manager
[]
(let [cache (atom {})]
(reify ISessionManager
(read [_ token]
(get @cache token))
(read-session [_ id]
(get @cache id))
(write! [_ key params]
(let [params (prepare-session-params key params)]
(swap! cache assoc key params)
params))
(create-session [_ params]
(assert (valid-params? params) "expect valid session params")
(update! [_ params]
(let [updated-at (dt/now)]
(swap! cache update (:id params) assoc :updated-at updated-at)
(assoc params :updated-at updated-at)))
(let [now (ct/now)
session (-> params
(assoc :id (uuid/next))
(assoc :created-at now)
(assoc :modified-at now))]
(swap! cache assoc (:id session) session)
session))
(delete! [_ token]
(swap! cache dissoc token)
(update-session [_ session]
(let [modified-at (ct/now)]
(swap! cache update (:id session) assoc :modified-at modified-at)
(assoc session :modified-at modified-at)))
(delete-session [_ id]
(swap! cache dissoc id)
nil))))
(defmethod ig/assert-key ::manager
@@ -143,109 +153,116 @@
;; MANAGER IMPL
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(declare ^:private assign-auth-token-cookie)
(declare ^:private assign-auth-data-cookie)
(declare ^:private clear-auth-token-cookie)
(declare ^:private clear-auth-data-cookie)
(declare ^:private gen-token)
(declare ^:private assign-session-cookie)
(declare ^:private clear-session-cookie)
(defn- assign-token
[cfg session]
(let [claims {:iss "authentication"
:aud "penpot"
:sid (:id session)
:iat (:modified-at session)
:uid (:profile-id session)
:sso-provider-id (:sso-provider-id session)
:sso-session-id (:sso-session-id session)}
header {:kid 1 :ver 1}
token (tokens/generate cfg claims header)]
(assoc session :token token)))
(defn create-fn
[{:keys [::manager ::setup/props]} profile-id]
[{:keys [::manager] :as cfg} {profile-id :id :as profile}
& {:keys [sso-provider-id sso-session-id]}]
(assert (manager? manager) "expected valid session manager")
(assert (uuid? profile-id) "expected valid uuid for profile-id")
(fn [request response]
(let [uagent (yreq/get-header request "user-agent")
params {:profile-id profile-id
:user-agent uagent
:created-at (dt/now)}
token (gen-token props params)
session (write! manager token params)]
(l/trace :hint "create" :profile-id (str profile-id))
(-> response
(assign-auth-token-cookie session)
(assign-auth-data-cookie session)))))
session (->> {:user-agent uagent
:profile-id profile-id
:sso-provider-id sso-provider-id
:sso-session-id sso-session-id}
(d/without-nils)
(create-session manager)
(assign-token cfg))]
(l/trc :hint "create" :id (str (:id session)) :profile-id (str profile-id))
(assign-session-cookie response session))))
(defn delete-fn
[{:keys [::manager]}]
(assert (manager? manager) "expected valid session manager")
(fn [request response]
(let [cname (cf/get :auth-token-cookie-name default-auth-token-cookie-name)
cookie (yreq/get-cookie request cname)]
(l/trace :hint "delete" :profile-id (:profile-id request))
(some->> (:value cookie) (delete! manager))
(-> response
(assoc :status 204)
(assoc :body nil)
(clear-auth-token-cookie)
(clear-auth-data-cookie)))))
(some->> (get request ::id) (delete-session manager))
(clear-session-cookie response)))
(defn- gen-token
[props {:keys [profile-id created-at]}]
(tokens/generate props {:iss "authentication"
:iat created-at
:uid profile-id}))
(defn- decode-token
[props token]
(when token
(tokens/verify props {:token token :iss "authentication"})))
(defn decode-token
[cfg token]
(try
(tokens/verify cfg {:token token :iss "authentication"})
(catch Throwable cause
(l/trc :hint "exception on decoding token"
:token token
:cause cause))))
(defn- get-token
(defn get-session
[request]
(let [cname (cf/get :auth-token-cookie-name default-auth-token-cookie-name)
cookie (some-> (yreq/get-cookie request cname) :value)]
(when-not (str/empty? cookie)
cookie)))
(get request ::session))
(defn- get-session
[manager token]
(some->> token (read manager)))
(defn invalidate-others
[cfg session]
(let [sql "delete from http_session_v2 where profile_id = ? and id != ?"]
(-> (db/exec-one! cfg [sql (:profile-id session) (:id session)])
(db/get-update-count))))
(defn- renew-session?
[{:keys [updated-at] :as session}]
(and (dt/instant? updated-at)
(let [elapsed (dt/diff updated-at (dt/now))]
(neg? (compare default-renewal-max-age elapsed)))))
(defn- wrap-soft-auth
[handler {:keys [::manager ::setup/props]}]
(assert (manager? manager) "expected valid session manager")
(letfn [(handle-request [request]
(try
(let [token (get-token request)
claims (decode-token props token)]
(cond-> request
(map? claims)
(-> (assoc ::token-claims claims)
(assoc ::token token))))
(catch Throwable cause
(l/trace :hint "exception on decoding malformed token" :cause cause)
request)))]
(fn [request]
(handler (handle-request request)))))
[{:keys [id modified-at] :as session}]
(or (string? id)
(and (ct/inst? modified-at)
(let [elapsed (ct/diff modified-at (ct/now))]
(neg? (compare default-renewal-max-age elapsed))))))
(defn- wrap-authz
[handler {:keys [::manager]}]
[handler {:keys [::manager] :as cfg}]
(assert (manager? manager) "expected valid session manager")
(fn [request]
(let [session (get-session manager (::token request))
request (cond-> request
(some? session)
(assoc ::profile-id (:profile-id session)
::id (:id session)))
response (handler request)]
(let [{:keys [type token claims metadata]} (get request ::http/auth-data)]
(cond
(= type :cookie)
(let [session (case (:ver metadata)
;; BACKWARD COMPATIBILITY WITH OLD TOKENS
0 (read-session manager token)
1 (some->> (:sid claims) (read-session manager))
nil)
(if (renew-session? session)
(let [session (update! manager session)]
(-> response
(assign-auth-token-cookie session)
(assign-auth-data-cookie session)))
response))))
request (cond-> request
(some? session)
(-> (assoc ::profile-id (:profile-id session))
(assoc ::session session)))
(def soft-auth
{:name ::soft-auth
:compile (constantly wrap-soft-auth)})
response (handler request)]
(if (and session (renew-session? session))
(let [session (->> session
(update-session manager)
(assign-token cfg))]
(assign-session-cookie response session))
response))
(= type :bearer)
(let [session (case (:ver metadata)
;; BACKWARD COMPATIBILITY WITH OLD TOKENS
0 (read-session manager token)
1 (some->> (:sid claims) (read-session manager))
nil)
request (cond-> request
(some? session)
(-> (assoc ::profile-id (:profile-id session))
(assoc ::session session)))]
(handler request))
:else
(handler request)))))
(def authz
{:name ::authz
@@ -253,17 +270,17 @@
;; --- IMPL
(defn- assign-auth-token-cookie
[response {token :id updated-at :updated-at}]
(defn- assign-session-cookie
[response {token :token modified-at :modified-at}]
(let [max-age (cf/get :auth-token-cookie-max-age default-cookie-max-age)
created-at (or updated-at (dt/now))
renewal (dt/plus created-at default-renewal-max-age)
expires (dt/plus created-at max-age)
created-at modified-at
renewal (ct/plus created-at default-renewal-max-age)
expires (ct/plus created-at max-age)
secure? (contains? cf/flags :secure-session-cookies)
strict? (contains? cf/flags :strict-session-cookies)
cors? (contains? cf/flags :cors)
name (cf/get :auth-token-cookie-name default-auth-token-cookie-name)
comment (str "Renewal at: " (dt/format-instant renewal :rfc1123))
name (cf/get :auth-token-cookie-name)
comment (str "Renewal at: " (ct/format-inst renewal :rfc1123))
cookie {:path "/"
:http-only true
:expires expires
@@ -271,59 +288,21 @@
:comment comment
:same-site (if cors? :none (if strict? :strict :lax))
:secure secure?}]
(update response :cookies assoc name cookie)))
(update response ::yres/cookies assoc name cookie)))
(defn- assign-auth-data-cookie
[response {profile-id :profile-id updated-at :updated-at}]
(let [max-age (cf/get :auth-token-cookie-max-age default-cookie-max-age)
domain (cf/get :auth-data-cookie-domain)
cname default-auth-data-cookie-name
created-at (or updated-at (dt/now))
renewal (dt/plus created-at default-renewal-max-age)
expires (dt/plus created-at max-age)
comment (str "Renewal at: " (dt/format-instant renewal :rfc1123))
secure? (contains? cf/flags :secure-session-cookies)
strict? (contains? cf/flags :strict-session-cookies)
cors? (contains? cf/flags :cors)
cookie {:domain domain
:expires expires
:path "/"
:comment comment
:value (u/map->query-string {:profile-id profile-id})
:same-site (if cors? :none (if strict? :strict :lax))
:secure secure?}]
(cond-> response
(string? domain)
(update :cookies assoc cname cookie))))
(defn- clear-auth-token-cookie
(defn- clear-session-cookie
[response]
(let [cname (cf/get :auth-token-cookie-name default-auth-token-cookie-name)]
(update response :cookies assoc cname {:path "/" :value "" :max-age 0})))
(defn- clear-auth-data-cookie
[response]
(let [cname default-auth-data-cookie-name
domain (cf/get :auth-data-cookie-domain)]
(cond-> response
(string? domain)
(update :cookies assoc cname {:domain domain :path "/" :value "" :max-age 0}))))
(let [cname (cf/get :auth-token-cookie-name)]
(update response ::yres/cookies assoc cname {:path "/" :value "" :max-age 0})))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; TASK: SESSION GC
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; FIXME: MOVE
(defmethod ig/assert-key ::tasks/gc
[_ params]
(assert (db/pool? (::db/pool params)) "expected valid database pool")
(assert (dt/duration? (::tasks/max-age params))))
(assert (ct/duration? (::tasks/max-age params))))
(defmethod ig/expand-key ::tasks/gc
[k v]
@@ -332,21 +311,23 @@
(def ^:private
sql:delete-expired
"delete from http_session
where updated_at < now() - ?::interval
"DELETE FROM http_session
WHERE updated_at < ?::timestamptz
or (updated_at is null and
created_at < now() - ?::interval)")
created_at < ?::timestamptz)")
(defn- collect-expired-tasks
[{:keys [::db/conn ::tasks/max-age]}]
(let [threshold (ct/minus (ct/now) max-age)
result (-> (db/exec-one! conn [sql:delete-expired threshold threshold])
(db/get-update-count))]
(l/dbg :task "gc"
:hint "clean http sessions"
:deleted result)
result))
(defmethod ig/init-key ::tasks/gc
[_ {:keys [::db/pool ::tasks/max-age] :as cfg}]
(l/debug :hint "initializing session gc task" :max-age max-age)
[_ {:keys [::tasks/max-age] :as cfg}]
(l/dbg :hint "initializing session gc task" :max-age max-age)
(fn [_]
(db/with-atomic [conn pool]
(let [interval (db/interval max-age)
result (db/exec-one! conn [sql:delete-expired interval interval])
result (:next.jdbc/update-count result)]
(l/debug :task "gc"
:hint "clean http sessions"
:deleted result)
result))))
(db/tx-run! cfg collect-expired-tasks)))

View File

@@ -9,7 +9,6 @@
(:refer-clojure :exclude [tap])
(:require
[app.common.data :as d]
[app.common.exceptions :as ex]
[app.common.logging :as l]
[app.common.transit :as t]
[app.http.errors :as errors]
@@ -34,7 +33,7 @@
(println "event:" (d/name name))
(println "data:" (t/encode-str data {:type :json-verbose}))
(println))]
(.getBytes data "UTF-8"))
(.getBytes ^String data "UTF-8"))
(catch Throwable cause
(l/err :hint "unexpected error on encoding value on sse stream"
:cause cause)
@@ -45,7 +44,8 @@
(def default-headers
{"Content-Type" "text/event-stream;charset=UTF-8"
"Cache-Control" "no-cache, no-store, max-age=0, must-revalidate"
"Pragma" "no-cache"})
"Pragma" "no-cache"
"X-Accel-Buffering" "no"})
(defn response
[handler & {:keys [buf] :or {buf 32} :as opts}]
@@ -54,18 +54,20 @@
::yres/status 200
::yres/body (yres/stream-body
(fn [_ output]
(binding [events/*channel* (sp/chan :buf buf :xf (keep encode))]
(let [listener (events/start-listener
(partial write! output)
(partial pu/close! output))]
(try
(let [channel (sp/chan :buf buf :xf (keep encode))
listener (events/spawn-listener
channel
(partial write! output)
(partial pu/close! output))]
(try
(binding [events/*channel* channel]
(let [result (handler)]
(events/tap :end result))
(catch Throwable cause
(events/tap :error (errors/handle' cause request))
(when-not (ex/instance? java.io.EOFException cause)
(binding [l/*context* (errors/request->context request)]
(l/err :hint "unexpected error on processing sse response" :cause cause))))
(finally
(sp/close! events/*channel*)
(px/await! listener)))))))}))
(events/tap :end result)))
(catch Throwable cause
(let [result (errors/handle' cause request)]
(events/tap channel :error result)))
(finally
(sp/close! channel)
(px/await! listener))))))}))

View File

@@ -11,12 +11,12 @@
[app.common.logging :as l]
[app.common.pprint :as pp]
[app.common.schema :as sm]
[app.common.time :as ct]
[app.common.uuid :as uuid]
[app.db :as db]
[app.http.session :as session]
[app.metrics :as mtx]
[app.msgbus :as mbus]
[app.util.time :as dt]
[app.util.websocket :as ws]
[integrant.core :as ig]
[promesa.exec.csp :as sp]
@@ -239,7 +239,7 @@
(defn- on-connect
[{:keys [::mtx/metrics]} {:keys [::ws/id] :as wsp}]
(let [created-at (dt/now)]
(let [created-at (ct/now)]
(l/trace :fn "on-connect" :conn-id id)
(swap! state assoc id wsp)
(mtx/run! metrics
@@ -253,7 +253,7 @@
(mtx/run! metrics :id :websocket-active-connections :dec 1)
(mtx/run! metrics
:id :websocket-session-timing
:val (/ (inst-ms (dt/diff created-at (dt/now))) 1000.0))))))
:val (/ (inst-ms (ct/diff created-at (ct/now))) 1000.0))))))
(defn- on-rcv-message
[{:keys [::mtx/metrics ::profile-id ::session-id]} message]
@@ -273,7 +273,7 @@
(defn- http-handler
[cfg {:keys [params ::session/profile-id] :as request}]
(let [session-id (some-> params :session-id sm/parse-uuid)]
(let [session-id (some-> params :session-id uuid/parse*)]
(when-not (uuid? session-id)
(ex/raise :type :validation
:code :missing-session-id

View File

@@ -11,6 +11,7 @@
[app.common.data.macros :as dm]
[app.common.logging :as l]
[app.common.schema :as sm]
[app.common.time :as ct]
[app.common.uuid :as uuid]
[app.config :as cf]
[app.db :as db]
@@ -23,9 +24,9 @@
[app.setup :as-alias setup]
[app.util.inet :as inet]
[app.util.services :as-alias sv]
[app.util.time :as dt]
[app.worker :as wrk]
[cuerdas.core :as str]))
[cuerdas.core :as str]
[yetti.request :as yreq]))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; HELPERS
@@ -78,17 +79,32 @@
(remove #(contains? reserved-props (key %))))
props))
(defn event-from-rpc-params
"Create a base event skeleton with pre-filled some important
data that can be extracted from RPC params object"
[params]
(let [context {:external-session-id (::rpc/external-session-id params)
:external-event-origin (::rpc/external-event-origin params)
:triggered-by (::rpc/handler-name params)}]
{::type "action"
::profile-id (::rpc/profile-id params)
::ip-addr (::rpc/ip-addr params)
::context (d/without-nils context)}))
(defn get-external-session-id
[request]
(when-let [session-id (yreq/get-header request "x-external-session-id")]
(when-not (or (> (count session-id) 256)
(= session-id "null")
(str/blank? session-id))
session-id)))
(defn- get-client-event-origin
[request]
(when-let [origin (yreq/get-header request "x-event-origin")]
(when-not (or (= origin "null")
(str/blank? origin))
(str/prune origin 200))))
(defn get-client-user-agent
[request]
(when-let [user-agent (yreq/get-header request "user-agent")]
(str/prune user-agent 500)))
(defn- get-client-version
[request]
(when-let [origin (yreq/get-header request "x-frontend-version")]
(when-not (or (= origin "null")
(str/blank? origin))
(str/prune origin 100))))
;; --- SPECS
@@ -108,41 +124,61 @@
[::ip-addr {:optional true} ::sm/text]
[::props {:optional true} [:map-of :keyword :any]]
[::context {:optional true} [:map-of :keyword :any]]
[::tracked-at {:optional true} ::ct/inst]
[::webhooks/event? {:optional true} ::sm/boolean]
[::webhooks/batch-timeout {:optional true} ::dt/duration]
[::webhooks/batch-timeout {:optional true} ::ct/duration]
[::webhooks/batch-key {:optional true}
[:or ::sm/fn ::sm/text :keyword]]])
(def ^:private check-event
(sm/check-fn schema:event))
(defn- prepare-context-from-request
[request]
(let [client-event-origin (get-client-event-origin request)
client-version (get-client-version request)
client-user-agent (get-client-user-agent request)
session-id (get-external-session-id request)
token-id (::actoken/id request)]
(d/without-nils
{:external-session-id session-id
:access-token-id (some-> token-id str)
:client-event-origin client-event-origin
:client-user-agent client-user-agent
:client-version client-version
:version (:full cf/version)})))
(defn event-from-rpc-params
"Create a base event skeleton with pre-filled some important
data that can be extracted from RPC params object"
[params]
(let [context (some-> params meta ::http/request prepare-context-from-request)
event {::type "action"
::profile-id (or (::rpc/profile-id params) uuid/zero)
::ip-addr (::rpc/ip-addr params)}]
(cond-> event
(some? context)
(assoc ::context context))))
(defn prepare-event
[cfg mdata params result]
(let [resultm (meta result)
request (-> params meta ::http/request)
profile-id (or (::profile-id resultm)
(:profile-id result)
(::rpc/profile-id params)
uuid/zero)
(let [resultm (meta result)
request (-> params meta ::http/request)
profile-id (or (::profile-id resultm)
(:profile-id result)
(::rpc/profile-id params)
uuid/zero)
session-id (get params ::rpc/external-session-id)
event-origin (get params ::rpc/external-event-origin)
props (-> (or (::replace-props resultm)
(-> params
(merge (::props resultm))
(dissoc :profile-id)
(dissoc :type)))
(clean-props))
token-id (::actoken/id request)
context (-> (::context resultm)
(assoc :external-session-id session-id)
(assoc :external-event-origin event-origin)
(assoc :access-token-id (some-> token-id str))
(d/without-nils))
ip-addr (inet/parse-request request)]
context (merge (::context resultm)
(prepare-context-from-request request))
ip-addr (inet/parse-request request)]
{::type (or (::type resultm)
(::rpc/type cfg))
@@ -198,7 +234,7 @@
(defn- handle-event!
[cfg event]
(let [params (event->params event)
tnow (dt/now)]
tnow (ct/now)]
(when (contains? cf/flags :audit-log)
;; NOTE: this operation may cause primary key conflicts on inserts
@@ -272,7 +308,7 @@
(let [event (-> (d/without-nils event)
(check-event))]
(db/run! cfg (fn [cfg]
(let [tnow (dt/now)
(let [tnow (ct/now)
params (-> (event->params event)
(assoc :created-at tnow)
(update :tracked-at #(or % tnow)))]

View File

@@ -16,7 +16,6 @@
[app.http.client :as http]
[app.setup :as-alias setup]
[app.tokens :as tokens]
[app.util.time :as dt]
[integrant.core :as ig]
[lambdaisland.uri :as u]
[promesa.exec :as px]))
@@ -53,13 +52,12 @@
(defn- send!
[{:keys [::uri] :as cfg} events]
(let [token (tokens/generate (::setup/props cfg)
(let [token (tokens/generate cfg
{:iss "authentication"
:iat (dt/now)
:uid uuid/zero})
body (t/encode {:events events})
headers {"content-type" "application/transit+json"
"origin" (cf/get :public-uri)
"origin" (str (cf/get :public-uri))
"cookie" (u/map->query-string {:auth-token token})}
params {:uri uri
:timeout 12000

View File

@@ -41,7 +41,7 @@
(if (or (instance? java.util.concurrent.CompletionException cause)
(instance? java.util.concurrent.ExecutionException cause))
(-> record
(assoc ::trace (ex/format-throwable cause :data? false :explain? false :header? false :summary? false))
(assoc ::trace (ex/format-throwable cause :data? true :explain? false :header? false :summary? false))
(assoc ::l/cause (ex-cause cause))
(record->report))
@@ -49,28 +49,33 @@
ctx (-> context
(assoc :tenant (cf/get :tenant))
(assoc :host (cf/get :host))
(assoc :public-uri (cf/get :public-uri))
(assoc :public-uri (str (cf/get :public-uri)))
(assoc :logger/name logger)
(assoc :logger/level level)
(dissoc :request/params :value :params :data))]
(merge
{:context (-> (into (sorted-map) ctx)
(pp/pprint-str :length 50))
:props (pp/pprint-str props :length 50)
:hint (or (ex-message cause) @message)
:hint (or (when-let [message (ex-message cause)]
(if-let [props-hint (:hint props)]
(str props-hint ": " message)
message))
@message)
:trace (or (::trace record)
(some-> cause (ex/format-throwable :data? false :explain? false :header? false :summary? false)))}
(some-> cause (ex/format-throwable :data? true :explain? false :header? false :summary? false)))}
(when-let [params (or (:request/params context) (:params context))]
{:params (pp/pprint-str params :length 30 :level 13)})
{:params (pp/pprint-str params :length 20 :level 20)})
(when-let [value (:value context)]
{:value (pp/pprint-str value :length 30 :level 12)})
{:value (pp/pprint-str value :length 30 :level 13)})
(when-let [data (some-> data (dissoc ::s/problems ::s/value ::s/spec ::sm/explain :hint))]
{:data (pp/pprint-str data :length 30 :level 12)})
{:data (pp/pprint-str data :length 30 :level 13)})
(when-let [explain (ex/explain data :length 30 :level 12)]
(when-let [explain (ex/explain data :length 30 :level 13)]
{:explain explain})))))
(defn error-record?

View File

@@ -10,12 +10,13 @@
[app.common.data :as d]
[app.common.data.macros :as dm]
[app.common.logging :as l]
[app.common.time :as ct]
[app.common.transit :as t]
[app.common.uri :as uri]
[app.config :as cf]
[app.db :as db]
[app.http.client :as http]
[app.util.time :as dt]
[app.loggers.audit :as audit]
[app.worker :as wrk]
[clojure.data.json :as json]
[cuerdas.core :as str]
@@ -67,18 +68,27 @@
(defmethod ig/init-key ::process-event-handler
[_ cfg]
(fn [{:keys [props] :as task}]
(l/dbg :hint "process webhook event" :name (:name props))
(when-let [items (lookup-webhooks cfg props)]
(l/trc :hint "webhooks found for event" :total (count items))
(db/tx-run! cfg (fn [cfg]
(doseq [item items]
(wrk/submit! (-> cfg
(assoc ::wrk/task :run-webhook)
(assoc ::wrk/queue :webhooks)
(assoc ::wrk/max-retries 3)
(assoc ::wrk/params {:event props
:config item})))))))))
(let [items (lookup-webhooks cfg props)
event {::audit/profile-id (:profile-id props)
::audit/name "webhook"
::audit/type "trigger"
::audit/props {:name (get props :name)
:event-id (get props :id)
:total-affected (count items)}}]
(audit/insert! cfg event)
(when items
(l/trc :hint "webhooks found for event" :total (count items))
(db/tx-run! cfg (fn [cfg]
(doseq [item items]
(wrk/submit! (-> cfg
(assoc ::wrk/task :run-webhook)
(assoc ::wrk/queue :webhooks)
(assoc ::wrk/max-retries 3)
(assoc ::wrk/params {:event props
:config item}))))))))))
;; --- RUN
(declare interpret-exception)
@@ -114,7 +124,7 @@
{:id (:id whook)})))
(db/update! pool :webhook
{:updated-at (dt/now)
{:updated-at (ct/now)
:error-code nil
:error-count 0}
{:id (:id whook)})))
@@ -122,7 +132,7 @@
(report-delivery! [whook req rsp err]
(db/insert! pool :webhook-delivery
{:webhook-id (:id whook)
:created-at (dt/now)
:created-at (ct/now)
:error-code err
:req-data (db/tjson req)
:rsp-data (db/tjson rsp)}))]
@@ -145,7 +155,7 @@
(let [req {:uri (:uri whook)
:headers {"content-type" (:mtype whook)
"user-agent" (str/ffmt "penpot/%" (:main cf/version))}
:timeout (dt/duration "4s")
:timeout (ct/duration "4s")
:method :post
:body body}]
(try

View File

@@ -11,6 +11,7 @@
[app.auth.oidc.providers :as-alias oidc.providers]
[app.common.exceptions :as ex]
[app.common.logging :as l]
[app.common.time :as ct]
[app.config :as cf]
[app.db :as-alias db]
[app.email :as-alias email]
@@ -19,7 +20,8 @@
[app.http.awsns :as http.awsns]
[app.http.client :as-alias http.client]
[app.http.debug :as-alias http.debug]
[app.http.session :as-alias session]
[app.http.management :as mgmt]
[app.http.session :as session]
[app.http.session.tasks :as-alias session.tasks]
[app.http.websocket :as http.ws]
[app.loggers.webhooks :as-alias webhooks]
@@ -29,7 +31,6 @@
[app.redis :as-alias rds]
[app.rpc :as-alias rpc]
[app.rpc.climit :as-alias climit]
[app.rpc.doc :as-alias rpc.doc]
[app.setup :as-alias setup]
[app.srepl :as-alias srepl]
[app.storage :as-alias sto]
@@ -38,9 +39,9 @@
[app.storage.gc-touched :as-alias sto.gc-touched]
[app.storage.s3 :as-alias sto.s3]
[app.svgo :as-alias svgo]
[app.util.time :as dt]
[app.util.cron]
[app.worker :as-alias wrk]
[cider.nrepl :refer [cider-nrepl-handler]]
[app.worker.executor]
[clojure.test :as test]
[clojure.tools.namespace.repl :as repl]
[cuerdas.core :as str]
@@ -147,23 +148,11 @@
::mdef/labels []
::mdef/type :histogram}
:executors-active-threads
{::mdef/name "penpot_executors_active_threads"
::mdef/help "Current number of threads available in the executor service."
::mdef/labels ["name"]
::mdef/type :gauge}
:executors-completed-tasks
{::mdef/name "penpot_executors_completed_tasks_total"
::mdef/help "Approximate number of completed tasks by the executor."
::mdef/labels ["name"]
::mdef/type :counter}
:executors-running-threads
{::mdef/name "penpot_executors_running_threads"
::mdef/help "Current number of threads with state RUNNING."
::mdef/labels ["name"]
::mdef/type :gauge}})
:http-server-dispatch-timing
{::mdef/name "penpot_http_server_dispatch_timing"
::mdef/help "Histogram of dispatch handler"
::mdef/labels []
::mdef/type :histogram}})
(def system-config
{::db/pool
@@ -175,14 +164,12 @@
::db/max-size (cf/get :database-max-pool-size 60)
::mtx/metrics (ig/ref ::mtx/metrics)}
;; Default thread pool for IO operations
::wrk/executor
{}
;; Default netty IO pool (shared between several services)
::wrk/netty-io-executor
{:threads (cf/get :netty-io-threads)}
::wrk/monitor
{::mtx/metrics (ig/ref ::mtx/metrics)
::wrk/executor (ig/ref ::wrk/executor)
::wrk/name "default"}
::wrk/netty-executor
{:threads (cf/get :executor-threads)}
:app.migrations/migrations
{::db/pool (ig/ref ::db/pool)}
@@ -193,17 +180,27 @@
::mtx/routes
{::mtx/metrics (ig/ref ::mtx/metrics)}
::rds/redis
{::rds/uri (cf/get :redis-uri)
::mtx/metrics (ig/ref ::mtx/metrics)
::wrk/executor (ig/ref ::wrk/executor)}
::rds/client
{::rds/uri
(cf/get :redis-uri)
::wrk/netty-executor
(ig/ref ::wrk/netty-executor)
::wrk/netty-io-executor
(ig/ref ::wrk/netty-io-executor)}
::rds/pool
{::rds/client (ig/ref ::rds/client)
::mtx/metrics (ig/ref ::mtx/metrics)}
::mbus/msgbus
{::wrk/executor (ig/ref ::wrk/executor)
::rds/redis (ig/ref ::rds/redis)}
{::wrk/executor (ig/ref ::wrk/netty-executor)
::rds/client (ig/ref ::rds/client)
::mtx/metrics (ig/ref ::mtx/metrics)}
:app.storage.tmp/cleaner
{::wrk/executor (ig/ref ::wrk/executor)}
{::wrk/executor (ig/ref ::wrk/netty-executor)}
::sto.gc-deleted/handler
{::db/pool (ig/ref ::db/pool)
@@ -231,8 +228,10 @@
::http/host (cf/get :http-server-host)
::http/router (ig/ref ::http/router)
::http/io-threads (cf/get :http-server-io-threads)
::http/max-worker-threads (cf/get :http-server-max-worker-threads)
::http/max-body-size (cf/get :http-server-max-body-size)
::http/max-multipart-body-size (cf/get :http-server-max-multipart-body-size)}
::http/max-multipart-body-size (cf/get :http-server-max-multipart-body-size)
::mtx/metrics (ig/ref ::mtx/metrics)}
::ldap/provider
{:host (cf/get :ldap-host)
@@ -260,26 +259,33 @@
::oidc.providers/generic
{::http.client/client (ig/ref ::http.client/client)}
::oidc/providers
[(ig/ref ::oidc.providers/google)
(ig/ref ::oidc.providers/github)
(ig/ref ::oidc.providers/gitlab)
(ig/ref ::oidc.providers/generic)]
::oidc/routes
{::http.client/client (ig/ref ::http.client/client)
::db/pool (ig/ref ::db/pool)
::setup/props (ig/ref ::setup/props)
::oidc/providers {:google (ig/ref ::oidc.providers/google)
:github (ig/ref ::oidc.providers/github)
:gitlab (ig/ref ::oidc.providers/gitlab)
:oidc (ig/ref ::oidc.providers/generic)}
::oidc/providers (ig/ref ::oidc/providers)
::session/manager (ig/ref ::session/manager)
::email/blacklist (ig/ref ::email/blacklist)
::email/whitelist (ig/ref ::email/whitelist)}
::mgmt/routes
{::db/pool (ig/ref ::db/pool)
::setup/props (ig/ref ::setup/props)}
:app.http/router
{::session/manager (ig/ref ::session/manager)
::db/pool (ig/ref ::db/pool)
::rpc/routes (ig/ref ::rpc/routes)
::rpc.doc/routes (ig/ref ::rpc.doc/routes)
::setup/props (ig/ref ::setup/props)
::mtx/routes (ig/ref ::mtx/routes)
::oidc/routes (ig/ref ::oidc/routes)
::mgmt/routes (ig/ref ::mgmt/routes)
::http.debug/routes (ig/ref ::http.debug/routes)
::http.assets/routes (ig/ref ::http.assets/routes)
::http.ws/routes (ig/ref ::http.ws/routes)
@@ -295,33 +301,35 @@
{::db/pool (ig/ref ::db/pool)
::mtx/metrics (ig/ref ::mtx/metrics)
::mbus/msgbus (ig/ref ::mbus/msgbus)
::setup/props (ig/ref ::setup/props)
::session/manager (ig/ref ::session/manager)}
:app.http.assets/routes
{::http.assets/path (cf/get :assets-path)
::http.assets/cache-max-age (dt/duration {:hours 24})
::http.assets/cache-max-agesignature-max-age (dt/duration {:hours 24 :minutes 5})
::http.assets/cache-max-age (ct/duration {:hours 24})
::http.assets/cache-max-agesignature-max-age (ct/duration {:hours 24 :minutes 5})
::sto/storage (ig/ref ::sto/storage)}
::rpc/climit
{::mtx/metrics (ig/ref ::mtx/metrics)
::wrk/executor (ig/ref ::wrk/executor)
::wrk/executor (ig/ref ::wrk/netty-executor)
::climit/config (cf/get :rpc-climit-config)
::climit/enabled (contains? cf/flags :rpc-climit)}
:app.rpc/rlimit
{::wrk/executor (ig/ref ::wrk/executor)}
{::wrk/executor (ig/ref ::wrk/netty-executor)}
:app.rpc/methods
{::http.client/client (ig/ref ::http.client/client)
::db/pool (ig/ref ::db/pool)
::wrk/executor (ig/ref ::wrk/executor)
::rds/pool (ig/ref ::rds/pool)
::wrk/executor (ig/ref ::wrk/netty-executor)
::session/manager (ig/ref ::session/manager)
::ldap/provider (ig/ref ::ldap/provider)
::sto/storage (ig/ref ::sto/storage)
::mtx/metrics (ig/ref ::mtx/metrics)
::mbus/msgbus (ig/ref ::mbus/msgbus)
::rds/redis (ig/ref ::rds/redis)
::rds/client (ig/ref ::rds/client)
::rpc/climit (ig/ref ::rpc/climit)
::rpc/rlimit (ig/ref ::rpc/rlimit)
@@ -331,14 +339,26 @@
::email/blacklist (ig/ref ::email/blacklist)
::email/whitelist (ig/ref ::email/whitelist)}
:app.rpc.doc/routes
{:app.rpc/methods (ig/ref :app.rpc/methods)}
:app.rpc/management-methods
{::http.client/client (ig/ref ::http.client/client)
::db/pool (ig/ref ::db/pool)
::rds/pool (ig/ref ::rds/pool)
::wrk/executor (ig/ref ::wrk/netty-executor)
::session/manager (ig/ref ::session/manager)
::sto/storage (ig/ref ::sto/storage)
::mtx/metrics (ig/ref ::mtx/metrics)
::mbus/msgbus (ig/ref ::mbus/msgbus)
::rds/client (ig/ref ::rds/client)
::setup/props (ig/ref ::setup/props)}
:app.rpc/routes
{::rpc/methods (ig/ref :app.rpc/methods)
::db/pool (ig/ref ::db/pool)
::session/manager (ig/ref ::session/manager)
::setup/props (ig/ref ::setup/props)}
::rpc/routes
{::rpc/methods (ig/ref :app.rpc/methods)
::rpc/management-methods (ig/ref :app.rpc/management-methods)
;; FIXME: revisit if db/pool is necessary here
::db/pool (ig/ref ::db/pool)
::session/manager (ig/ref ::session/manager)
::setup/props (ig/ref ::setup/props)}
::wrk/registry
{::mtx/metrics (ig/ref ::mtx/metrics)
@@ -426,6 +446,9 @@
;; module requires the migrations to run before initialize.
::migrations (ig/ref :app.migrations/migrations)}
::setup/clock
{}
:app.loggers.audit.archive-task/handler
{::setup/props (ig/ref ::setup/props)
::db/pool (ig/ref ::db/pool)
@@ -469,49 +492,50 @@
(cf/get :objects-storage-s3-bucket))
::sto.s3/io-threads (or (cf/get :storage-assets-s3-io-threads)
(cf/get :objects-storage-s3-io-threads))
::wrk/executor (ig/ref ::wrk/executor)}
::wrk/netty-io-executor
(ig/ref ::wrk/netty-io-executor)}
:app.storage.fs/backend
{::sto.fs/directory (or (cf/get :storage-assets-fs-directory)
(cf/get :objects-storage-fs-directory))}})
(def worker-config
{::wrk/cron
{::wrk/registry (ig/ref ::wrk/registry)
::db/pool (ig/ref ::db/pool)
::wrk/entries
[{:cron #app/cron "0 0 0 * * ?" ;; daily
[{:cron #penpot/cron "0 0 0 * * ?" ;; daily
:task :session-gc}
{:cron #app/cron "0 0 0 * * ?" ;; daily
{:cron #penpot/cron "0 0 0 * * ?" ;; daily
:task :objects-gc}
{:cron #app/cron "0 0 0 * * ?" ;; daily
{:cron #penpot/cron "0 0 0 * * ?" ;; daily
:task :storage-gc-deleted}
{:cron #app/cron "0 0 0 * * ?" ;; daily
{:cron #penpot/cron "0 0 0 * * ?" ;; daily
:task :storage-gc-touched}
{:cron #app/cron "0 0 0 * * ?" ;; daily
{:cron #penpot/cron "0 0 0 * * ?" ;; daily
:task :tasks-gc}
{:cron #app/cron "0 0 2 * * ?" ;; daily
{:cron #penpot/cron "0 0 2 * * ?" ;; daily
:task :file-gc-scheduler}
{:cron #app/cron "0 30 */3,23 * * ?"
{:cron #penpot/cron "0 30 */3,23 * * ?"
:task :telemetry}
(when (contains? cf/flags :audit-log-archive)
{:cron #app/cron "0 */5 * * * ?" ;; every 5m
{:cron #penpot/cron "0 */5 * * * ?" ;; every 5m
:task :audit-log-archive})
(when (contains? cf/flags :audit-log-gc)
{:cron #app/cron "30 */5 * * * ?" ;; every 5m
{:cron #penpot/cron "30 */5 * * * ?" ;; every 5m
:task :audit-log-gc})]}
::wrk/dispatcher
{::rds/redis (ig/ref ::rds/redis)
{::rds/client (ig/ref ::rds/client)
::mtx/metrics (ig/ref ::mtx/metrics)
::db/pool (ig/ref ::db/pool)
::wrk/tenant (cf/get :tenant)}
@@ -520,7 +544,7 @@
{::wrk/parallelism (cf/get ::worker-default-parallelism 1)
::wrk/queue :default
::wrk/tenant (cf/get :tenant)
::rds/redis (ig/ref ::rds/redis)
::rds/client (ig/ref ::rds/client)
::wrk/registry (ig/ref ::wrk/registry)
::mtx/metrics (ig/ref ::mtx/metrics)
::db/pool (ig/ref ::db/pool)}
@@ -529,7 +553,7 @@
{::wrk/parallelism (cf/get ::worker-webhook-parallelism 1)
::wrk/queue :webhooks
::wrk/tenant (cf/get :tenant)
::rds/redis (ig/ref ::rds/redis)
::rds/client (ig/ref ::rds/client)
::wrk/registry (ig/ref ::wrk/registry)
::mtx/metrics (ig/ref ::mtx/metrics)
::db/pool (ig/ref ::db/pool)}})
@@ -605,7 +629,7 @@
(let [p (promise)]
(when (contains? cf/flags :nrepl-server)
(l/inf :hint "start nrepl server" :port 6064)
(nrepl/start-server :bind "0.0.0.0" :port 6064 :handler cider-nrepl-handler))
(nrepl/start-server :bind "0.0.0.0" :port 6064))
(start)
(deref p))

View File

@@ -8,56 +8,58 @@
"Media & Font postprocessing."
(:require
[app.common.data :as d]
[app.common.data.macros :as dm]
[app.common.exceptions :as ex]
[app.common.logging :as l]
[app.common.media :as cm]
[app.common.schema :as sm]
[app.common.schema.openapi :as-alias oapi]
[app.common.spec :as us]
[app.common.svg :as csvg]
[app.common.time :as ct]
[app.config :as cf]
[app.db :as-alias db]
[app.http.client :as http]
[app.storage :as-alias sto]
[app.storage.tmp :as tmp]
[app.util.time :as dt]
[buddy.core.bytes :as bb]
[buddy.core.codecs :as bc]
[clojure.java.shell :as sh]
[clojure.spec.alpha :as s]
[clojure.string]
[clojure.xml :as xml]
[cuerdas.core :as str]
[datoteka.fs :as fs]
[datoteka.io :as io])
(:import
clojure.lang.XMLHandler
java.io.InputStream
javax.xml.XMLConstants
javax.xml.parsers.SAXParserFactory
org.apache.commons.io.IOUtils
org.im4java.core.ConvertCmd
org.im4java.core.IMOperation
org.im4java.core.Info))
(s/def ::path fs/path?)
(s/def ::filename string?)
(s/def ::size integer?)
(s/def ::headers (s/map-of string? string?))
(s/def ::mtype string?)
(def default-max-file-size
(* 1024 1024 10)) ; 10 MiB
(s/def ::upload
(s/keys :req-un [::filename ::size ::path]
:opt-un [::mtype ::headers]))
(def schema:upload
[:map {:title "Upload"}
[:filename :string]
[:size ::sm/int]
[:path ::fs/path]
[:mtype {:optional true} :string]
[:headers {:optional true}
[:map-of :string :string]]])
;; A subset of fields from the ::upload spec
(s/def ::input
(s/keys :req-un [::path]
:opt-un [::mtype]))
(def ^:private schema:input
[:map {:title "Input"}
[:path ::fs/path]
[:mtype {:optional true} ::sm/text]])
(sm/register!
^{::sm/type ::upload}
[:map {:title "Upload"}
[:filename :string]
[:size ::sm/int]
[:path ::fs/path]
[:mtype {:optional true} :string]
[:headers {:optional true}
[:map-of :string :string]]])
(def ^:private check-input
(sm/check-fn schema:input))
(defn validate-media-type!
([upload] (validate-media-type! upload cm/valid-image-types))
([upload] (validate-media-type! upload cm/image-types))
([upload allowed]
(when-not (contains? allowed (:mtype upload))
(ex/raise :type :validation
@@ -97,17 +99,44 @@
(catch Throwable e
(process-error e))))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; SVG PARSING
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(defn- secure-parser-factory
[^InputStream input ^XMLHandler handler]
(.. (doto (SAXParserFactory/newInstance)
(.setFeature XMLConstants/FEATURE_SECURE_PROCESSING true)
(.setFeature "http://apache.org/xml/features/disallow-doctype-decl" true))
(newSAXParser)
(parse input handler)))
(defn- strip-doctype
[data]
(cond-> data
(str/includes? data "<!DOCTYPE")
(str/replace #"<\!DOCTYPE[^>]*>" "")))
(defn- parse-svg
[text]
(let [text (strip-doctype text)]
(dm/with-open [istream (IOUtils/toInputStream ^String text "UTF-8")]
(xml/parse istream secure-parser-factory))))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; IMAGE THUMBNAILS
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(s/def ::width integer?)
(s/def ::height integer?)
(s/def ::format #{:jpeg :webp :png})
(s/def ::quality #(< 0 % 101))
(def ^:private schema:thumbnail-params
[:map {:title "ThumbnailParams"}
[:input schema:input]
[:format [:enum :jpeg :webp :png]]
[:quality [:int {:min 1 :max 100}]]
[:width :int]
[:height :int]])
(s/def ::thumbnail-params
(s/keys :req-un [::input ::format ::width ::height]))
(def ^:private check-thumbnail-params
(sm/check-fn schema:thumbnail-params))
;; Related info on how thumbnails generation
;; http://www.imagemagick.org/Usage/thumbnails/
@@ -129,30 +158,38 @@
:data tmp)))
(defmethod process :generic-thumbnail
[{:keys [quality width height] :as params}]
(us/assert ::thumbnail-params params)
(let [op (doto (IMOperation.)
(.addImage)
(.autoOrient)
(.strip)
(.thumbnail ^Integer (int width) ^Integer (int height) ">")
(.quality (double quality))
(.addImage))]
(generic-process (assoc params :operation op))))
[params]
(let [{:keys [quality width height] :as params}
(check-thumbnail-params params)
operation
(doto (IMOperation.)
(.addImage)
(.autoOrient)
(.strip)
(.thumbnail ^Integer (int width) ^Integer (int height) ">")
(.quality (double quality))
(.addImage))]
(generic-process (assoc params :operation operation))))
(defmethod process :profile-thumbnail
[{:keys [quality width height] :as params}]
(us/assert ::thumbnail-params params)
(let [op (doto (IMOperation.)
(.addImage)
(.autoOrient)
(.strip)
(.thumbnail ^Integer (int width) ^Integer (int height) "^")
(.gravity "center")
(.extent (int width) (int height))
(.quality (double quality))
(.addImage))]
(generic-process (assoc params :operation op))))
[params]
(let [{:keys [quality width height] :as params}
(check-thumbnail-params params)
operation
(doto (IMOperation.)
(.addImage)
(.autoOrient)
(.strip)
(.thumbnail ^Integer (int width) ^Integer (int height) "^")
(.gravity "center")
(.extent (int width) (int height))
(.quality (double quality))
(.addImage))]
(generic-process (assoc params :operation operation))))
(defn get-basic-info-from-svg
[{:keys [tag attrs] :as data}]
@@ -182,17 +219,33 @@
{:width (int width)
:height (int height)})))]))
(defn- get-dimensions-with-orientation [^String path]
;; Image magick doesn't give info about exif rotation so we use the identify command
;; If we are processing an animated gif we use the first frame with -scene 0
(let [dim-result (sh/sh "identify" "-format" "%w %h\n" path)
orient-result (sh/sh "identify" "-format" "%[EXIF:Orientation]\n" path)]
(if (and (= 0 (:exit dim-result))
(= 0 (:exit orient-result)))
(let [[w h] (-> (:out dim-result)
str/trim
(clojure.string/split #"\s+")
(->> (mapv #(Integer/parseInt %))))
orientation (-> orient-result :out str/trim)]
(case orientation
("6" "8") {:width h :height w} ; Rotated 90 or 270 degrees
{:width w :height h})) ; Normal or unknown orientation
nil)))
(defmethod process :info
[{:keys [input] :as params}]
(us/assert ::input input)
(let [{:keys [path mtype]} input]
(let [{:keys [path mtype] :as input} (check-input input)]
(if (= mtype "image/svg+xml")
(let [info (some-> path slurp csvg/parse get-basic-info-from-svg)]
(let [info (some-> path slurp parse-svg get-basic-info-from-svg)]
(when-not info
(ex/raise :type :validation
:code :invalid-svg-file
:hint "uploaded svg does not provides dimensions"))
(merge input info {:ts (dt/now)}))
(merge input info {:ts (ct/now) :size (fs/size path)}))
(let [instance (Info. (str path))
mtype' (.getProperty instance "Mime type")]
@@ -202,13 +255,18 @@
:code :media-type-mismatch
:hint (str "Seems like you are uploading a file whose content does not match the extension."
"Expected: " mtype ". Got: " mtype')))
;; For an animated GIF, getImageWidth/Height returns the delta size of one frame (if no frame given
;; it returns size of the last one), whereas getPageWidth/Height always return the full size of
;; any frame.
(assoc input
:width (.getPageWidth instance)
:height (.getPageHeight instance)
:ts (dt/now))))))
(let [{:keys [width height]}
(or (get-dimensions-with-orientation (str path))
(do
(l/warn "Failed to read image dimensions with orientation; falling back to im4java"
{:path path})
{:width (.getPageWidth instance)
:height (.getPageHeight instance)}))]
(assoc input
:width width
:height height
:size (fs/size path)
:ts (ct/now)))))))
(defmethod process-error org.im4java.core.InfoException
[error]
@@ -217,6 +275,54 @@
:hint "invalid image"
:cause error))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; IMAGE HELPERS
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(defn download-image
"Download an image from the provided URI and return the media input object"
[{:keys [::http/client]} uri]
(letfn [(parse-and-validate [{:keys [headers] :as response}]
(let [size (some-> (get headers "content-length") d/parse-integer)
mtype (get headers "content-type")
format (cm/mtype->format mtype)
max-size (cf/get :media-max-file-size default-max-file-size)]
(when-not size
(ex/raise :type :validation
:code :unknown-size
:hint "seems like the url points to resource with unknown size"))
(when (> size max-size)
(ex/raise :type :validation
:code :file-too-large
:hint (str/ffmt "the file size % is greater than the maximum %"
size
default-max-file-size)))
(when (nil? format)
(ex/raise :type :validation
:code :media-type-not-allowed
:hint "seems like the url points to an invalid media object"))
{:size size :mtype mtype :format format}))]
(let [{:keys [body] :as response} (http/req! client
{:method :get :uri uri}
{:response-type :input-stream})
{:keys [size mtype]} (parse-and-validate response)
path (tmp/tempfile :prefix "penpot.media.download.")
written (io/write* path body :size size)]
(when (not= written size)
(ex/raise :type :internal
:code :mismatch-write-size
:hint "unexpected state: unable to write to file"))
{;; :size size
:path path
:mtype mtype})))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; FONTS
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

View File

@@ -438,7 +438,25 @@
:fn (mg/resource "app/migrations/sql/0138-mod-file-data-fragment-table.sql")}
{:name "0139-mod-file-change-table.sql"
:fn (mg/resource "app/migrations/sql/0139-mod-file-change-table.sql")}])
:fn (mg/resource "app/migrations/sql/0139-mod-file-change-table.sql")}
{:name "0140-mod-file-change-table.sql"
:fn (mg/resource "app/migrations/sql/0140-mod-file-change-table.sql")}
{:name "0140-add-locked-by-column-to-file-change-table"
:fn (mg/resource "app/migrations/sql/0140-add-locked-by-column-to-file-change-table.sql")}
{:name "0141-add-idx-to-file-library-rel"
:fn (mg/resource "app/migrations/sql/0141-add-idx-to-file-library-rel.sql")}
{:name "0141-add-file-data-table.sql"
:fn (mg/resource "app/migrations/sql/0141-add-file-data-table.sql")}
{:name "0142-add-sso-provider-table"
:fn (mg/resource "app/migrations/sql/0142-add-sso-provider-table.sql")}
{:name "0143-http-session-v2-table"
:fn (mg/resource "app/migrations/sql/0143-add-http-session-v2-table.sql")}])
(defn apply-migrations!
[pool name migrations]

View File

@@ -10,8 +10,8 @@
[app.common.exceptions :as ex]
[app.common.logging :as l]
[app.common.pprint]
[app.srepl.fixes.media-refs :refer [process-file]]
[app.srepl.main :as srepl]
[app.srepl.procs.media-refs]
[clojure.edn :as edn]))
(def ^:private required-services
@@ -20,7 +20,10 @@
:app.storage/storage
:app.metrics/metrics
:app.db/pool
:app.worker/executor])
:app.worker/netty-io-executor])
(def default-options
{:rollback? false})
(defn -main
[& [options]]
@@ -28,22 +31,20 @@
(let [config-var (requiring-resolve 'app.main/system-config)
start-var (requiring-resolve 'app.main/start-custom)
stop-var (requiring-resolve 'app.main/stop)
config (select-keys @config-var required-services)]
config (select-keys @config-var required-services)
options (if (string? options)
(ex/ignoring (edn/read-string options))
{})
options (-> (merge default-options options)
(assoc :proc-fn #'app.srepl.procs.media-refs/fix-media-refs))]
(start-var config)
(let [options (if (string? options)
(ex/ignoring (edn/read-string options))
{})]
(l/inf :hint "executing media-refs migration" :options options)
(srepl/process-files! process-file options))
(l/inf :hint "executing media-refs migration" :options options)
(srepl/process! options)
(stop-var)
(System/exit 0))
(catch Throwable cause
(ex/print-throwable cause)
(flush)
(System/exit -1))))

View File

@@ -0,0 +1,11 @@
-- Add locked_by column to file_change table for version locking feature
-- This allows users to lock their own saved versions to prevent deletion by others
ALTER TABLE file_change
ADD COLUMN locked_by uuid NULL REFERENCES profile(id) ON DELETE SET NULL DEFERRABLE;
-- Create index for locked versions queries
CREATE INDEX file_change__locked_by__idx ON file_change (locked_by) WHERE locked_by IS NOT NULL;
-- Add comment for documentation
COMMENT ON COLUMN file_change.locked_by IS 'Profile ID of user who has locked this version. Only the creator can lock/unlock their own versions. Locked versions cannot be deleted by others.';

View File

@@ -0,0 +1,2 @@
ALTER TABLE file_change
ADD COLUMN migrations text[];

View File

@@ -0,0 +1,38 @@
CREATE TABLE file_data (
file_id uuid NOT NULL REFERENCES file(id) DEFERRABLE,
id uuid NOT NULL,
created_at timestamptz NOT NULL DEFAULT now(),
modified_at timestamptz NOT NULL DEFAULT now(),
deleted_at timestamptz NULL,
type text NOT NULL,
backend text NULL,
metadata jsonb NULL,
data bytea NULL,
PRIMARY KEY (file_id, id)
) PARTITION BY HASH (file_id);
CREATE TABLE file_data_00 PARTITION OF file_data FOR VALUES WITH (MODULUS 16, REMAINDER 0);
CREATE TABLE file_data_01 PARTITION OF file_data FOR VALUES WITH (MODULUS 16, REMAINDER 1);
CREATE TABLE file_data_02 PARTITION OF file_data FOR VALUES WITH (MODULUS 16, REMAINDER 2);
CREATE TABLE file_data_03 PARTITION OF file_data FOR VALUES WITH (MODULUS 16, REMAINDER 3);
CREATE TABLE file_data_04 PARTITION OF file_data FOR VALUES WITH (MODULUS 16, REMAINDER 4);
CREATE TABLE file_data_05 PARTITION OF file_data FOR VALUES WITH (MODULUS 16, REMAINDER 5);
CREATE TABLE file_data_06 PARTITION OF file_data FOR VALUES WITH (MODULUS 16, REMAINDER 6);
CREATE TABLE file_data_07 PARTITION OF file_data FOR VALUES WITH (MODULUS 16, REMAINDER 7);
CREATE TABLE file_data_08 PARTITION OF file_data FOR VALUES WITH (MODULUS 16, REMAINDER 8);
CREATE TABLE file_data_09 PARTITION OF file_data FOR VALUES WITH (MODULUS 16, REMAINDER 9);
CREATE TABLE file_data_10 PARTITION OF file_data FOR VALUES WITH (MODULUS 16, REMAINDER 10);
CREATE TABLE file_data_11 PARTITION OF file_data FOR VALUES WITH (MODULUS 16, REMAINDER 11);
CREATE TABLE file_data_12 PARTITION OF file_data FOR VALUES WITH (MODULUS 16, REMAINDER 12);
CREATE TABLE file_data_13 PARTITION OF file_data FOR VALUES WITH (MODULUS 16, REMAINDER 13);
CREATE TABLE file_data_14 PARTITION OF file_data FOR VALUES WITH (MODULUS 16, REMAINDER 14);
CREATE TABLE file_data_15 PARTITION OF file_data FOR VALUES WITH (MODULUS 16, REMAINDER 15);
CREATE INDEX file_data__deleted_at__idx
ON file_data (deleted_at, file_id, id)
WHERE deleted_at IS NOT NULL;

View File

@@ -0,0 +1,2 @@
CREATE INDEX IF NOT EXISTS file_library_rel__library_file_id__idx
ON file_library_rel (library_file_id);

View File

@@ -0,0 +1,33 @@
CREATE TABLE sso_provider (
id uuid PRIMARY KEY,
created_at timestamptz NOT NULL DEFAULT now(),
modified_at timestamptz NOT NULL DEFAULT now(),
is_enabled boolean NOT NULL DEFAULT true,
type text NOT NULL CHECK (type IN ('oidc')),
domain text NOT NULL,
client_id text NOT NULL,
client_secret text NOT NULL,
base_uri text NOT NULL,
token_uri text NULL,
auth_uri text NULL,
user_uri text NULL,
jwks_uri text NULL,
logout_uri text NULL,
roles_attr text NULL,
email_attr text NULL,
name_attr text NULL,
user_info_source text NOT NULL DEFAULT 'token'
CHECK (user_info_source IN ('token', 'userinfo', 'auto')),
scopes text[] NULL,
roles text[] NULL
);
CREATE UNIQUE INDEX sso_provider__domain__idx
ON sso_provider(domain);

View File

@@ -0,0 +1,23 @@
CREATE TABLE http_session_v2 (
id uuid PRIMARY KEY,
created_at timestamptz NOT NULL DEFAULT now(),
modified_at timestamptz NOT NULL DEFAULT now(),
profile_id uuid REFERENCES profile(id) ON DELETE CASCADE,
user_agent text NULL,
sso_provider_id uuid NULL REFERENCES sso_provider(id) ON DELETE CASCADE,
sso_session_id text NULL
);
CREATE INDEX http_session_v2__profile_id__idx
ON http_session_v2(profile_id);
CREATE INDEX http_session_v2__sso_provider_id__idx
ON http_session_v2(sso_provider_id)
WHERE sso_provider_id IS NOT NULL;
CREATE INDEX http_session_v2__sso_session_id__idx
ON http_session_v2(sso_session_id)
WHERE sso_session_id IS NOT NULL;

View File

@@ -10,13 +10,12 @@
[app.common.data :as d]
[app.common.logging :as l]
[app.common.schema :as sm]
[app.common.time :as ct]
[app.common.transit :as t]
[app.config :as cfg]
[app.redis :as rds]
[app.util.time :as dt]
[app.worker :as wrk]
[integrant.core :as ig]
[promesa.core :as p]
[promesa.exec :as px]
[promesa.exec.csp :as sp]))
@@ -56,17 +55,19 @@
[k v]
{k (-> (d/without-nils v)
(assoc ::buffer-size 128)
(assoc ::timeout (dt/duration {:seconds 30})))})
(assoc ::timeout (ct/duration {:seconds 30})))})
(def ^:private schema:params
[:map ::rds/redis ::wrk/executor])
[:map
::rds/client
::wrk/executor])
(defmethod ig/assert-key ::msgbus
[_ params]
(assert (sm/check schema:params params)))
(defmethod ig/init-key ::msgbus
[_ {:keys [::buffer-size ::wrk/executor ::timeout ::rds/redis] :as cfg}]
[_ {:keys [::buffer-size ::wrk/executor ::timeout] :as cfg}]
(l/info :hint "initialize msgbus" :buffer-size buffer-size)
(let [cmd-ch (sp/chan :buf buffer-size)
rcv-ch (sp/chan :buf (sp/dropping-buffer buffer-size))
@@ -74,8 +75,9 @@
:xf xform-prefix-topic)
state (agent {})
pconn (rds/connect redis :type :default :timeout timeout)
sconn (rds/connect redis :type :pubsub :timeout timeout)
;; Open persistent connections to redis
pconn (rds/connect cfg :timeout timeout)
sconn (rds/connect-pubsub cfg :timeout timeout)
_ (set-error-handler! state #(l/error :cause % :hint "unexpected error on agent" ::l/sync? true))
_ (set-error-mode! state :continue)
@@ -189,14 +191,13 @@
(defn- create-listener
[rcv-ch]
(rds/pubsub-listener
:on-message (fn [_ topic message]
{:on-message (fn [_ topic message]
;; There are no back pressure, so we use a slidding
;; buffer for cases when the pubsub broker sends
;; more messages that we can process.
(let [val {:topic topic :message (t/decode message)}]
(let [val {:topic topic :message (t/decode-str message)}]
(when-not (sp/offer! rcv-ch val)
(l/warn :msg "dropping message on subscription loop"))))))
(l/warn :msg "dropping message on subscription loop"))))})
(defn- process-input
[{:keys [::state ::wrk/executor] :as cfg} topic message]
@@ -216,8 +217,7 @@
(rds/add-listener sconn (create-listener rcv-ch))
(px/thread
{:name "penpot/msgbus/io-loop"
:virtual true}
{:name "penpot/msgbus"}
(try
(loop []
(let [timeout-ch (sp/timeout-chan 1000)
@@ -263,7 +263,7 @@
intended to be used in core.async go blocks."
[{:keys [::pconn] :as cfg} {:keys [topic message]}]
(try
(p/await! (rds/publish pconn topic (t/encode message)))
(rds/publish pconn topic (t/encode-str message))
(catch InterruptedException cause
(throw cause))
(catch Throwable cause

View File

@@ -6,23 +6,22 @@
(ns app.redis
"The msgbus abstraction implemented using redis as underlying backend."
(:refer-clojure :exclude [eval])
(:refer-clojure :exclude [eval get set run!])
(:require
[app.common.data :as d]
[app.common.exceptions :as ex]
[app.common.generic-pool :as gpool]
[app.common.logging :as l]
[app.common.schema :as sm]
[app.common.time :as ct]
[app.metrics :as mtx]
[app.redis.script :as-alias rscript]
[app.util.cache :as cache]
[app.util.time :as dt]
[app.worker :as-alias wrk]
[app.worker :as wrk]
[app.worker.executor]
[clojure.core :as c]
[clojure.java.io :as io]
[cuerdas.core :as str]
[integrant.core :as ig]
[promesa.core :as p]
[promesa.exec :as px])
[integrant.core :as ig])
(:import
clojure.lang.MapEntry
io.lettuce.core.KeyValue
@@ -32,12 +31,10 @@
io.lettuce.core.RedisException
io.lettuce.core.RedisURI
io.lettuce.core.ScriptOutputType
io.lettuce.core.api.StatefulConnection
io.lettuce.core.SetArgs
io.lettuce.core.api.StatefulRedisConnection
io.lettuce.core.api.async.RedisAsyncCommands
io.lettuce.core.api.async.RedisScriptingAsyncCommands
io.lettuce.core.api.sync.RedisCommands
io.lettuce.core.codec.ByteArrayCodec
io.lettuce.core.api.sync.RedisScriptingCommands
io.lettuce.core.codec.RedisCodec
io.lettuce.core.codec.StringCodec
io.lettuce.core.pubsub.RedisPubSubListener
@@ -45,244 +42,238 @@
io.lettuce.core.pubsub.api.sync.RedisPubSubCommands
io.lettuce.core.resource.ClientResources
io.lettuce.core.resource.DefaultClientResources
io.netty.channel.nio.NioEventLoopGroup
io.netty.util.HashedWheelTimer
io.netty.util.Timer
io.netty.util.concurrent.EventExecutorGroup
java.lang.AutoCloseable
java.time.Duration))
(set! *warn-on-reflection* true)
(declare ^:private initialize-resources)
(declare ^:private shutdown-resources)
(declare ^:private impl-eval)
(def ^:const MAX-EVAL-RETRIES 18)
(defprotocol IRedis
(-connect [_ options])
(-get-or-connect [_ key options]))
(def default-timeout
(ct/duration "10s"))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; IMPL & PRIVATE API
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(defprotocol IConnection
(publish [_ topic message])
(rpush [_ key payload])
(blpop [_ timeout keys])
(eval [_ script]))
(-set-timeout [_ timeout] "set connection timeout")
(-get-timeout [_] "get current timeout")
(-reset-timeout [_] "reset to default timeout"))
(defprotocol IDefaultConnection
"Public API of default redis connection"
(-publish [_ topic message])
(-rpush [_ key payload])
(-blpop [_ timeout keys])
(-eval [_ script])
(-get [_ key])
(-set [_ key val args])
(-del [_ key-or-keys])
(-ping [_]))
(defprotocol IPubSubConnection
(add-listener [_ listener])
(subscribe [_ topics])
(unsubscribe [_ topics]))
(-add-listener [_ listener])
(-subscribe [_ topics])
(-unsubscribe [_ topics]))
(def default-codec
(RedisCodec/of StringCodec/UTF8 ByteArrayCodec/INSTANCE))
(def string-codec
(def ^:private default-codec
(RedisCodec/of StringCodec/UTF8 StringCodec/UTF8))
(sm/register!
{:type ::connection
:pred #(satisfies? IConnection %)
:type-properties
{:title "connection"
:description "redis connection instance"}})
(defn- impl-eval
[cmd cache metrics script]
(let [keys (into-array String (map str (::rscript/keys script)))
vals (into-array String (map str (::rscript/vals script)))
sname (::rscript/name script)
(sm/register!
{:type ::pubsub-connection
:pred #(satisfies? IPubSubConnection %)
:type-properties
{:title "connection"
:description "redis connection instance"}})
read-script
(fn []
(-> script ::rscript/path io/resource slurp))
(defn redis?
[o]
(satisfies? IRedis o))
load-script
(fn []
(let [id (.scriptLoad ^RedisScriptingCommands cmd
^String (read-script))]
(swap! cache assoc sname id)
(l/trc :hint "load script" :name sname :id id)
(sm/register!
{:type ::redis
:pred redis?})
id))
(def ^:private schema:script
[:map {:title "script"}
[::rscript/name qualified-keyword?]
[::rscript/path ::sm/text]
[::rscript/keys {:optional true} [:vector :any]]
[::rscript/vals {:optional true} [:vector :any]]])
eval-script
(fn [id]
(try
(let [tpoint (ct/tpoint)
result (.evalsha ^RedisScriptingCommands cmd
^String id
^ScriptOutputType ScriptOutputType/MULTI
^"[Ljava.lang.String;" keys
^"[Ljava.lang.String;" vals)
elapsed (tpoint)]
(def valid-script?
(sm/lazy-validator schema:script))
(mtx/run! metrics {:id :redis-eval-timing
:labels [(name sname)]
:val (inst-ms elapsed)})
(defmethod ig/expand-key ::redis
[k v]
(let [cpus (px/get-available-processors)
threads (max 1 (int (* cpus 0.2)))]
{k (-> (d/without-nils v)
(assoc ::timeout (dt/duration "10s"))
(assoc ::io-threads (max 3 threads))
(assoc ::worker-threads (max 3 threads)))}))
(l/trc :hint "eval script"
:name (name sname)
:id id
:params (str/join "," (::rscript/vals script))
:elapsed (ct/format-duration elapsed))
(def ^:private schema:redis-params
[:map {:title "redis-params"}
::wrk/executor
::mtx/metrics
[::uri ::sm/uri]
[::worker-threads ::sm/int]
[::io-threads ::sm/int]
[::timeout ::dt/duration]])
result)
(defmethod ig/assert-key ::redis
[_ params]
(assert (sm/check schema:redis-params params)))
(catch io.lettuce.core.RedisNoScriptException _cause
::load)
(defmethod ig/init-key ::redis
[_ params]
(initialize-resources params))
(catch Throwable cause
(when-let [on-error (::rscript/on-error script)]
(on-error cause))
(throw cause))))
(defmethod ig/halt-key! ::redis
[_ instance]
(d/close! instance))
eval-script'
(fn [id]
(loop [id id
retries 0]
(if (> retries MAX-EVAL-RETRIES)
(ex/raise :type :internal
:code ::max-eval-retries-reached
:hint (str "unable to eval redis script " sname))
(let [result (eval-script id)]
(if (= result ::load)
(recur (load-script)
(inc retries))
result)))))]
(defn- initialize-resources
"Initialize redis connection resources"
[{:keys [::uri ::io-threads ::worker-threads ::wrk/executor ::mtx/metrics] :as params}]
(if-let [id (c/get @cache sname)]
(eval-script' id)
(-> (load-script)
(eval-script')))))
(l/inf :hint "initialize redis resources"
:uri (str uri)
:io-threads io-threads
:worker-threads worker-threads)
(deftype Connection [^StatefulRedisConnection conn
^RedisCommands cmd
^Duration timeout
cache metrics]
AutoCloseable
(close [_]
(ex/ignoring (.close conn)))
(let [timer (HashedWheelTimer.)
resources (.. (DefaultClientResources/builder)
(ioThreadPoolSize ^long io-threads)
(computationThreadPoolSize ^long worker-threads)
(timer ^Timer timer)
(build))
IConnection
(-set-timeout [_ timeout]
(.setTimeout conn ^Duration timeout))
redis-uri (RedisURI/create ^String (str uri))
(-reset-timeout [_]
(.setTimeout conn timeout))
shutdown (fn [client conn]
(ex/ignoring (.close ^StatefulConnection conn))
(ex/ignoring (.close ^RedisClient client))
(l/trc :hint "disconnect" :hid (hash client)))
(-get-timeout [_]
(.getTimeout conn))
on-remove (fn [key val cause]
(l/trace :hint "evict connection (cache)" :key key :reason cause)
(some-> val d/close!))
IDefaultConnection
(-publish [_ topic message]
(.publish cmd ^String topic ^String message))
cache (cache/create :executor executor
:on-remove on-remove
:keepalive "5m")]
(reify
java.lang.AutoCloseable
(close [_]
(ex/ignoring (cache/invalidate! cache))
(ex/ignoring (.shutdown ^ClientResources resources))
(ex/ignoring (.stop ^Timer timer)))
(-rpush [_ key elements]
(try
(let [vals (make-array String (count elements))]
(loop [i 0 xs (seq elements)]
(when xs
(aset ^"[[Ljava.lang.String;" vals i ^String (first xs))
(recur (inc i) (next xs))))
IRedis
(-get-or-connect [this key options]
(let [create (fn [_] (-connect this options))]
(cache/get cache key create)))
(.rpush cmd
^String key
^"[[Ljava.lang.String;" vals))
(-connect [_ options]
(let [timeout (or (:timeout options) (::timeout params))
codec (get options :codec default-codec)
type (get options :type :default)
client (RedisClient/create ^ClientResources resources
^RedisURI redis-uri)]
(catch RedisCommandInterruptedException cause
(throw (InterruptedException. (ex-message cause))))))
(l/trc :hint "connect" :hid (hash client))
(if (= type :pubsub)
(let [conn (.connectPubSub ^RedisClient client
^RedisCodec codec)]
(.setTimeout ^StatefulConnection conn
^Duration timeout)
(reify
IPubSubConnection
(add-listener [_ listener]
(assert (instance? RedisPubSubListener listener) "expected listener instance")
(.addListener ^StatefulRedisPubSubConnection conn
^RedisPubSubListener listener))
(-blpop [_ keys timeout]
(try
(let [keys (into-array String keys)]
(when-let [res (.blpop cmd
^double timeout
^"[Ljava.lang.String;" keys)]
(MapEntry/create
(.getKey ^KeyValue res)
(.getValue ^KeyValue res))))
(catch RedisCommandInterruptedException cause
(throw (InterruptedException. (ex-message cause))))))
(subscribe [_ topics]
(try
(let [topics (into-array String (map str topics))
cmd (.sync ^StatefulRedisPubSubConnection conn)]
(.subscribe ^RedisPubSubCommands cmd topics))
(catch RedisCommandInterruptedException cause
(throw (InterruptedException. (ex-message cause))))))
(-get [_ key]
(assert (string? key) "key expected to be string")
(.get cmd ^String key))
(unsubscribe [_ topics]
(try
(let [topics (into-array String (map str topics))
cmd (.sync ^StatefulRedisPubSubConnection conn)]
(.unsubscribe ^RedisPubSubCommands cmd topics))
(catch RedisCommandInterruptedException cause
(throw (InterruptedException. (ex-message cause))))))
(-set [_ key val args]
(.set cmd
^String key
^bytes val
^SetArgs args))
(-del [_ keys]
(let [keys (into-array String keys)]
(.del cmd ^String/1 keys)))
(-ping [_]
(.ping cmd))
(-eval [_ script]
(impl-eval cmd cache metrics script)))
AutoCloseable
(close [_] (shutdown client conn))))
(deftype SubscriptionConnection [^StatefulRedisPubSubConnection conn
^RedisPubSubCommands cmd
^Duration timeout]
AutoCloseable
(close [_]
(ex/ignoring (.close conn)))
(let [conn (.connect ^RedisClient client ^RedisCodec codec)]
(.setTimeout ^StatefulConnection conn ^Duration timeout)
(reify
IConnection
(publish [_ topic message]
(assert (string? topic) "expected topic to be string")
(assert (bytes? message) "expected message to be a byte array")
IConnection
(-set-timeout [_ timeout]
(.setTimeout conn ^Duration timeout))
(let [pcomm (.async ^StatefulRedisConnection conn)]
(.publish ^RedisAsyncCommands pcomm ^String topic ^bytes message)))
(-reset-timeout [_]
(.setTimeout conn timeout))
(rpush [_ key payload]
(assert (or (and (vector? payload)
(every? bytes? payload))
(bytes? payload)))
(try
(let [cmd (.sync ^StatefulRedisConnection conn)
data (if (vector? payload) payload [payload])
vals (make-array (. Class (forName "[B")) (count data))]
(-get-timeout [_]
(.getTimeout conn))
(loop [i 0 xs (seq data)]
(when xs
(aset ^"[[B" vals i ^bytes (first xs))
(recur (inc i) (next xs))))
IPubSubConnection
(-add-listener [_ listener]
(.addListener conn ^RedisPubSubListener listener))
(.rpush ^RedisCommands cmd
^String key
^"[[B" vals))
(-subscribe [_ topics]
(try
(let [topics (into-array String topics)]
(.subscribe cmd topics))
(catch RedisCommandInterruptedException cause
(throw (InterruptedException. (ex-message cause))))))
(catch RedisCommandInterruptedException cause
(throw (InterruptedException. (ex-message cause))))))
(-unsubscribe [_ topics]
(try
(let [topics (into-array String topics)]
(.unsubscribe cmd topics))
(catch RedisCommandInterruptedException cause
(throw (InterruptedException. (ex-message cause)))))))
(blpop [_ timeout keys]
(try
(let [keys (into-array Object (map str keys))
cmd (.sync ^StatefulRedisConnection conn)
timeout (/ (double (inst-ms timeout)) 1000.0)]
(when-let [res (.blpop ^RedisCommands cmd
^double timeout
^"[Ljava.lang.String;" keys)]
(MapEntry/create
(.getKey ^KeyValue res)
(.getValue ^KeyValue res))))
(catch RedisCommandInterruptedException cause
(throw (InterruptedException. (ex-message cause))))))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; PUBLIC API
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(eval [_ script]
(assert (valid-script? script) "expected valid script")
(impl-eval conn metrics script))
AutoCloseable
(close [_] (shutdown client conn))))))))))
(defn connect
[instance & {:as opts}]
(assert (satisfies? IRedis instance) "expected valid redis instance")
(-connect instance opts))
(defn get-or-connect
[instance key & {:as opts}]
(assert (satisfies? IRedis instance) "expected valid redis instance")
(-get-or-connect instance key opts))
(defn build-set-args
[options]
(reduce-kv (fn [^SetArgs args k v]
(case k
:ex (if (instance? Duration v)
(.ex args ^Duration v)
(.ex args (long v)))
:px (.px args (long v))
:nx (if v (.nx args) args)
:keep-ttl (if v (.keepttl args) args)))
(SetArgs.)
options))
(defn pubsub-listener
[& {:keys [on-message on-subscribe on-unsubscribe]}]
@@ -311,61 +302,172 @@
(when on-unsubscribe
(on-unsubscribe nil topic count)))))
(def ^:private scripts-cache (atom {}))
(defn connect
[cfg & {:as options}]
(assert (contains? cfg ::mtx/metrics) "missing ::mtx/metrics on provided system")
(assert (contains? cfg ::client) "missing ::rds/client on provided system")
(defn- impl-eval
[^StatefulRedisConnection connection metrics script]
(let [cmd (.async ^StatefulRedisConnection connection)
keys (into-array String (map str (::rscript/keys script)))
vals (into-array String (map str (::rscript/vals script)))
sname (::rscript/name script)]
(let [state (::client cfg)
(letfn [(on-error [cause]
(if (instance? io.lettuce.core.RedisNoScriptException cause)
(do
(l/error :hint "no script found" :name sname :cause cause)
(->> (load-script)
(p/mcat eval-script)))
(if-let [on-error (::rscript/on-error script)]
(on-error cause)
(p/rejected cause))))
cache (::cache state)
client (::client state)
timeout (or (some-> (:timeout options) ct/duration)
(::timeout state))
(eval-script [sha]
(let [tpoint (dt/tpoint)]
(->> (.evalsha ^RedisScriptingAsyncCommands cmd
^String sha
^ScriptOutputType ScriptOutputType/MULTI
^"[Ljava.lang.String;" keys
^"[Ljava.lang.String;" vals)
(p/fmap (fn [result]
(let [elapsed (tpoint)]
(mtx/run! metrics {:id :redis-eval-timing
:labels [(name sname)]
:val (inst-ms elapsed)})
(l/trace :hint "eval script"
:name (name sname)
:sha sha
:params (str/join "," (::rscript/vals script))
:elapsed (dt/format-duration elapsed))
result)))
(p/merr on-error))))
conn (.connect ^RedisClient client
^RedisCodec default-codec)
cmd (.sync ^StatefulRedisConnection conn)]
(read-script []
(-> script ::rscript/path io/resource slurp))
(.setTimeout ^StatefulRedisConnection conn ^Duration timeout)
(->Connection conn cmd timeout cache (::mtx/metrics cfg))))
(load-script []
(l/trace :hint "load script" :name sname)
(->> (.scriptLoad ^RedisScriptingAsyncCommands cmd
^String (read-script))
(p/fmap (fn [sha]
(swap! scripts-cache assoc sname sha)
sha))))]
(defn connect-pubsub
[cfg & {:as options}]
(let [state (::client cfg)
client (::client state)
(p/await!
(if-let [sha (get @scripts-cache sname)]
(eval-script sha)
(->> (load-script)
(p/mapcat eval-script)))))))
timeout (or (some-> (:timeout options) ct/duration)
(::timeout state))
conn (.connectPubSub ^RedisClient client
^RedisCodec default-codec)
cmd (.sync ^StatefulRedisPubSubConnection conn)]
(.setTimeout ^StatefulRedisPubSubConnection conn
^Duration timeout)
(->SubscriptionConnection conn cmd timeout)))
(defn get
[conn key]
(assert (string? key) "key must be string instance")
(try
(-get conn key)
(catch RedisCommandTimeoutException cause
(l/err :hint "timeout on get redis key" :key key :cause cause)
nil)))
(defn set
([conn key val]
(set conn key val nil))
([conn key val args]
(assert (string? key) "key must be string instance")
(assert (string? val) "val must be string instance")
(let [args (cond
(or (instance? SetArgs args)
(nil? args))
args
(map? args)
(build-set-args args)
:else
(throw (IllegalArgumentException. "invalid args")))]
(try
(-set conn key val args)
(catch RedisCommandTimeoutException cause
(l/err :hint "timeout on set redis key" :key key :cause cause)
nil)))))
(defn del
[conn key-or-keys]
(let [keys (if (vector? key-or-keys) key-or-keys [key-or-keys])]
(assert (every? string? keys) "only string keys allowed")
(try
(-del conn keys)
(catch RedisCommandTimeoutException cause
(l/err :hint "timeout on del redis key" :key key :cause cause)
nil))))
(defn ping
[conn]
(-ping conn))
(defn blpop
[conn key-or-keys timeout]
(let [keys (if (vector? key-or-keys) key-or-keys [key-or-keys])
timeout (cond
(ct/duration? timeout)
(/ (double (inst-ms timeout)) 1000.0)
(double? timeout)
timeout
(int? timeout)
(/ (double timeout) 1000.0)
:else
0)]
(assert (every? string? keys) "only string keys allowed")
(-blpop conn keys timeout)))
(defn rpush
[conn key elements]
(assert (string? key) "key must be string instance")
(assert (every? string? elements) "elements should be all strings")
(let [elements (vec elements)]
(-rpush conn key elements)))
(defn publish
[conn topic payload]
(assert (string? topic) "expected topic to be string")
(assert (string? payload) "expected message to be a byte array")
(-publish conn topic payload))
(def ^:private schema:script
[:map {:title "script"}
[::rscript/name qualified-keyword?]
[::rscript/path ::sm/text]
[::rscript/keys {:optional true} [:vector :any]]
[::rscript/vals {:optional true} [:vector :any]]])
(def ^:private valid-script?
(sm/lazy-validator schema:script))
(defn eval
[conn script]
(assert (valid-script? script) "expected valid script")
(-eval conn script))
(defn add-listener
[conn listener]
(let [listener (cond
(map? listener)
(pubsub-listener listener)
(instance? RedisPubSubListener listener)
listener
:else
(throw (IllegalArgumentException. "invalid listener provided")))]
(-add-listener conn listener)))
(defn subscribe
[conn topic-or-topics]
(let [topics (if (vector? topic-or-topics) topic-or-topics [topic-or-topics])]
(assert (every? string? topics))
(-subscribe conn topics)))
(defn unsubscribe
[conn topic-or-topics]
(let [topics (if (vector? topic-or-topics) topic-or-topics [topic-or-topics])]
(assert (every? string? topics))
(-unsubscribe conn topics)))
(defn set-timeout
[conn timeout]
(let [timeout (ct/duration timeout)]
(-set-timeout conn timeout)))
(defn get-timeout
[conn]
(-get-timeout conn))
(defn reset-timeout
[conn]
(-reset-timeout conn))
(defn timeout-exception?
[cause]
@@ -374,3 +476,121 @@
(defn exception?
[cause]
(instance? RedisException cause))
(defn get-pooled
[cfg]
(let [pool (::pool cfg)]
(gpool/get pool)))
(defn close
[o]
(.close ^AutoCloseable o))
(defn pool
[cfg & {:as options}]
(gpool/create :create-fn (partial connect cfg options)
:destroy-fn close
:dispose-fn -reset-timeout))
(defn run!
[cfg f & args]
(if (gpool/pool? cfg)
(apply f {::pool cfg} f args)
(let [pool (::pool cfg)]
(with-open [^AutoCloseable conn (gpool/get pool)]
(apply f (assoc cfg ::conn @conn) args)))))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; INITIALIZATION
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(defmethod ig/expand-key ::client
[k v]
{k (-> (d/without-nils v)
(assoc ::timeout (ct/duration "10s")))})
(def ^:private schema:client
[:map {:title "RedisClient"}
[::timer [:fn #(instance? HashedWheelTimer %)]]
[::cache ::sm/atom]
[::timeout ::ct/duration]
[::resources [:fn #(instance? DefaultClientResources %)]]])
(def check-client
(sm/check-fn schema:client))
(sm/register! ::client schema:client)
(sm/register!
{:type ::pool
:pred gpool/pool?})
(def ^:private schema:client-params
[:map {:title "redis-params"}
::wrk/netty-io-executor
::wrk/netty-executor
[::uri ::sm/uri]
[::timeout ::ct/duration]])
(def ^:private check-client-params
(sm/check-fn schema:client-params))
(defmethod ig/assert-key ::client
[_ params]
(check-client-params params))
(defmethod ig/init-key ::client
[_ {:keys [::uri ::wrk/netty-io-executor ::wrk/netty-executor] :as params}]
(l/inf :hint "initialize redis client" :uri (str uri))
(let [timer (HashedWheelTimer.)
cache (atom {})
resources (.. (DefaultClientResources/builder)
(eventExecutorGroup ^EventExecutorGroup netty-executor)
;; We provide lettuce with a shared event loop
;; group instance instead of letting lettuce to
;; create its own
(eventLoopGroupProvider
(reify io.lettuce.core.resource.EventLoopGroupProvider
(allocate [_ _] netty-io-executor)
(threadPoolSize [_]
(.executorCount ^NioEventLoopGroup netty-io-executor))
(release [_ _ _ _ _]
;; Do nothing
)
(shutdown [_ _ _ _]
;; Do nothing
)))
(timer ^Timer timer)
(build))
redis-uri (RedisURI/create ^String (str uri))
client (RedisClient/create ^ClientResources resources
^RedisURI redis-uri)]
{::client client
::cache cache
::timer timer
::timeout default-timeout
::resources resources}))
(defmethod ig/halt-key! ::client
[_ {:keys [::client ::timer ::resources]}]
(ex/ignoring (.shutdown ^RedisClient client))
(ex/ignoring (.shutdown ^ClientResources resources))
(ex/ignoring (.stop ^Timer timer)))
(defmethod ig/assert-key ::pool
[_ {:keys [::client]}]
(check-client client))
(defmethod ig/init-key ::pool
[_ cfg]
(pool cfg {:timeout (ct/duration 2000)}))
(defmethod ig/halt-key! ::pool
[_ instance]
(.close ^java.lang.AutoCloseable instance))

View File

@@ -12,18 +12,24 @@
[app.common.logging :as l]
[app.common.schema :as sm]
[app.common.spec :as us]
[app.common.time :as ct]
[app.common.uri :as u]
[app.config :as cf]
[app.db :as db]
[app.http :as-alias http]
[app.http.access-token :as actoken]
[app.http.client :as-alias http.client]
[app.http.middleware :as mw]
[app.http.security :as sec]
[app.http.session :as session]
[app.loggers.audit :as audit]
[app.main :as-alias main]
[app.metrics :as mtx]
[app.msgbus :as-alias mbus]
[app.redis :as rds]
[app.rpc.climit :as climit]
[app.rpc.cond :as cond]
[app.rpc.doc :as doc]
[app.rpc.helpers :as rph]
[app.rpc.retry :as retry]
[app.rpc.rlimit :as rlimit]
@@ -31,11 +37,9 @@
[app.storage :as-alias sto]
[app.util.inet :as inet]
[app.util.services :as sv]
[app.util.time :as dt]
[clojure.spec.alpha :as s]
[cuerdas.core :as str]
[integrant.core :as ig]
[promesa.core :as p]
[yetti.request :as yreq]
[yetti.response :as yres]))
@@ -43,7 +47,7 @@
(defn- default-handler
[_]
(p/rejected (ex/error :type :not-found)))
(ex/raise :type :not-found))
(defn- handle-response-transformation
[response request mdata]
@@ -63,74 +67,65 @@
(let [mdata (meta result)
response (if (fn? result)
(result request)
(let [result (rph/unwrap result)]
{::yres/status (::http/status mdata 200)
::yres/headers (::http/headers mdata {})
(let [result (rph/unwrap result)
status (or (::http/status mdata)
(if (nil? result)
204
200))
headers (cond-> (::http/headers mdata {})
(yres/stream-body? result)
(assoc "content-type" "application/octet-stream"))]
{::yres/status status
::yres/headers headers
::yres/body result}))]
(-> response
(handle-response-transformation request mdata)
(handle-before-comple-hook mdata))))
(defn get-external-session-id
[request]
(when-let [session-id (yreq/get-header request "x-external-session-id")]
(when-not (or (> (count session-id) 256)
(= session-id "null")
(str/blank? session-id))
session-id)))
(defn- get-external-event-origin
[request]
(when-let [origin (yreq/get-header request "x-event-origin")]
(when-not (or (> (count origin) 256)
(= origin "null")
(str/blank? origin))
origin)))
(defn- rpc-handler
(defn- make-rpc-handler
"Ring handler that dispatches cmd requests and convert between
internal async flow into ring async flow."
[methods {:keys [params path-params method] :as request}]
(let [handler-name (:type path-params)
etag (yreq/get-header request "if-none-match")
profile-id (or (::session/profile-id request)
(::actoken/profile-id request))
[methods]
(let [methods (update-vals methods peek)]
(fn [{:keys [params path-params method] :as request}]
(let [handler-name (:type path-params)
etag (yreq/get-header request "if-none-match")
profile-id (or (::session/profile-id request)
(::actoken/profile-id request))
ip-addr (inet/parse-request request)
ip-addr (inet/parse-request request)
session-id (get-external-session-id request)
event-origin (get-external-event-origin request)
data (-> params
(assoc ::handler-name handler-name)
(assoc ::ip-addr ip-addr)
(assoc ::request-at (ct/now))
(assoc ::cond/key etag)
(cond-> (uuid? profile-id)
(assoc ::profile-id profile-id)))
data (-> params
(assoc ::handler-name handler-name)
(assoc ::ip-addr ip-addr)
(assoc ::request-at (dt/now))
(assoc ::external-session-id session-id)
(assoc ::external-event-origin event-origin)
(assoc ::session/id (::session/id request))
(assoc ::cond/key etag)
(cond-> (uuid? profile-id)
(assoc ::profile-id profile-id)))
data (with-meta data
{::http/request request})
data (vary-meta data assoc ::http/request request)
handler-fn (get methods (keyword handler-name) default-handler)]
handler-fn (get methods (keyword handler-name) default-handler)]
(when (and (or (= method :get)
(= method :head))
(not (str/starts-with? handler-name "get-")))
(ex/raise :type :restriction
:code :method-not-allowed
:hint "method not allowed for this request"))
(when (and (or (= method :get)
(= method :head))
(not (str/starts-with? handler-name "get-")))
(ex/raise :type :restriction
:code :method-not-allowed
:hint "method not allowed for this request"))
(binding [cond/*enabled* true]
(let [response (handler-fn data)]
(handle-response request response)))))
;; FIXME: why we have this cond enabled here, we need to move it outside this handler
(binding [cond/*enabled* true]
(let [response (handler-fn data)]
(handle-response request response)))))))
(defn- wrap-metrics
"Wrap service method with metrics measurement."
[{:keys [::mtx/metrics ::metrics-id]} f mdata]
(let [labels (into-array String [(::sv/name mdata)])]
(fn [cfg params]
(let [tp (dt/tpoint)]
(let [tp (ct/tpoint)]
(try
(f cfg params)
(finally
@@ -200,7 +195,7 @@
::sm/explain (explain params)))))))
f))
(defn- wrap-all
(defn- wrap
[cfg f mdata]
(as-> f $
(wrap-db-transaction cfg $ mdata)
@@ -214,17 +209,30 @@
(wrap-params-validation cfg $ mdata)
(wrap-authentication cfg $ mdata)))
(defn- wrap
(defn- wrap-management
[cfg f mdata]
(l/trc :hint "register method" :name (::sv/name mdata))
(let [f (wrap-all cfg f mdata)]
(partial f cfg)))
(as-> f $
(wrap-db-transaction cfg $ mdata)
(retry/wrap-retry cfg $ mdata)
(climit/wrap cfg $ mdata)
(wrap-metrics cfg $ mdata)
(wrap-audit cfg $ mdata)
(wrap-spec-conform cfg $ mdata)
(wrap-params-validation cfg $ mdata)
(wrap-authentication cfg $ mdata)))
(defn- process-method
[cfg [vfn mdata]]
[(keyword (::sv/name mdata)) [mdata (wrap cfg vfn mdata)]])
[cfg module wrap-fn [f mdata]]
(l/trc :hint "add method" :module module :name (::sv/name mdata))
(let [f (wrap-fn cfg f mdata)
k (keyword (::sv/name mdata))]
[k [mdata (partial f cfg)]]))
(defn- resolve-command-methods
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; API METHODS
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(defn- resolve-methods
[cfg]
(let [cfg (assoc cfg ::type "command" ::metrics-id :rpc-command-timing)]
(->> (sv/scan-ns
@@ -239,7 +247,6 @@
'app.rpc.commands.files
'app.rpc.commands.files-create
'app.rpc.commands.files-share
'app.rpc.commands.files-temp
'app.rpc.commands.files-update
'app.rpc.commands.files-snapshot
'app.rpc.commands.files-thumbnails
@@ -254,7 +261,7 @@
'app.rpc.commands.verify-token
'app.rpc.commands.viewer
'app.rpc.commands.webhooks)
(map (partial process-method cfg))
(map (partial process-method cfg "rpc" wrap))
(into {}))))
(def ^:private schema:methods-params
@@ -262,6 +269,7 @@
::session/manager
::http.client/client
::db/pool
::rds/pool
::mbus/msgbus
::sto/storage
::mtx/metrics
@@ -277,7 +285,50 @@
(defmethod ig/init-key ::methods
[_ cfg]
(let [cfg (d/without-nils cfg)]
(resolve-command-methods cfg)))
(resolve-methods cfg)))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; MANAGEMENT METHODS
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(defn- resolve-management-methods
[cfg]
(let [cfg (assoc cfg ::type "management" ::metrics-id :rpc-management-timing)]
(->> (sv/scan-ns
'app.rpc.management.subscription
'app.rpc.management.exporter)
(map (partial process-method cfg "management" wrap-management))
(into {}))))
(def ^:private schema:management-methods-params
[:map {:title "management-methods-params"}
::session/manager
::http.client/client
::db/pool
::rds/pool
::mbus/msgbus
::sto/storage
::mtx/metrics
::setup/props])
(defmethod ig/assert-key ::management-methods
[_ params]
(assert (sm/check schema:management-methods-params params)))
(defmethod ig/init-key ::management-methods
[_ cfg]
(let [cfg (d/without-nils cfg)]
(resolve-management-methods cfg)))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ROUTES
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(defn- redirect
[href]
(fn [_]
{::yres/status 308
::yres/headers {"location" (str href)}}))
(def ^:private schema:methods
[:map-of :keyword [:tuple :map ::sm/fn]])
@@ -292,11 +343,50 @@
(assert (db/pool? (::db/pool params)) "expect valid database pool")
(assert (some? (::setup/props params)))
(assert (session/manager? (::session/manager params)) "expect valid session manager")
(assert (valid-methods? (::methods params)) "expect valid methods map"))
(assert (valid-methods? (::methods params)) "expect valid methods map")
(assert (valid-methods? (::management-methods params)) "expect valid methods map"))
(defmethod ig/init-key ::routes
[_ {:keys [::methods] :as cfg}]
(let [methods (update-vals methods peek)]
[["/rpc" {:middleware [[session/authz cfg]
[actoken/authz cfg]]}
["/command/:type" {:handler (partial rpc-handler methods)}]]]))
[_ {:keys [::methods ::management-methods ::setup/props] :as cfg}]
(let [public-uri (cf/get :public-uri)
management-key (or (cf/get :management-api-key)
(get props :management-key))]
["/api"
["/management"
["/methods/:type"
{:middleware [[mw/shared-key-auth management-key]
[session/authz cfg]]
:handler (make-rpc-handler management-methods)}]
(doc/routes :methods management-methods
:label "management"
:base-uri (u/join public-uri "/api/management")
:description "MANAGEMENT API")]
["/main"
["/methods/:type"
{:middleware [[mw/cors]
[sec/client-header-check]
[session/authz cfg]
[actoken/authz cfg]]
:handler (make-rpc-handler methods)}]
(doc/routes :methods methods
:label "main"
:base-uri (u/join public-uri "/api/main")
:description "MAIN API")]
;; BACKWARD COMPATIBILITY
["/_doc" {:handler (redirect (u/join public-uri "/api/main/doc"))}]
["/doc" {:handler (redirect (u/join public-uri "/api/main/doc"))}]
["/openapi" {:handler (redirect (u/join public-uri "/api/main/doc/openapi"))}]
["/openapi.join" {:handler (redirect (u/join public-uri "/api/main/doc/openapi.json"))}]
["/rpc/command/:type"
{:middleware [[mw/cors]
[sec/client-header-check]
[session/authz cfg]
[actoken/authz cfg]]
:handler (make-rpc-handler methods)}]]))

View File

@@ -11,17 +11,16 @@
[app.common.exceptions :as ex]
[app.common.logging :as l]
[app.common.schema :as sm]
[app.common.time :as ct]
[app.metrics :as mtx]
[app.rpc :as-alias rpc]
[app.util.cache :as cache]
[app.util.services :as-alias sv]
[app.util.time :as dt]
[app.worker :as-alias wrk]
[clojure.edn :as edn]
[clojure.set :as set]
[datoteka.fs :as fs]
[integrant.core :as ig]
[promesa.exec :as px]
[promesa.exec.bulkhead :as pbh])
(:import
clojure.lang.ExceptionInfo
@@ -154,7 +153,7 @@
:id limit-id
:label limit-label
:queue queue
:elapsed (some-> elapsed dt/format-duration)
:elapsed (some-> elapsed ct/format-duration)
:params @limit-params)))
(def ^:private idseq (AtomicLong. 0))
@@ -171,19 +170,19 @@
mlabels (into-array String [(id->str limit-id)])
limit-id (id->str limit-id limit-key)
limiter (cache/get cache limit-id (partial create-limiter config))
tpoint (dt/tpoint)
tpoint (ct/tpoint)
req-id (.incrementAndGet ^AtomicLong idseq)]
(try
(let [stats (pbh/get-stats limiter)]
(measure metrics mlabels stats nil)
(log "enqueued" req-id stats limit-id limit-label limit-params nil))
(px/invoke! limiter (fn []
(let [elapsed (tpoint)
stats (pbh/get-stats limiter)]
(measure metrics mlabels stats elapsed)
(log "acquired" req-id stats limit-id limit-label limit-params elapsed)
(handler))))
(pbh/invoke! limiter (fn []
(let [elapsed (tpoint)
stats (pbh/get-stats limiter)]
(measure metrics mlabels stats elapsed)
(log "acquired" req-id stats limit-id limit-label limit-params elapsed)
(handler))))
(catch ExceptionInfo cause
(let [{:keys [type code]} (ex-data cause)]
@@ -289,13 +288,9 @@
(get-limits cfg)))
(defn invoke!
"Run a function in context of climit.
Intended to be used in virtual threads."
[{:keys [::executor ::rpc/climit] :as cfg} f params]
"Run a function in context of climit."
[{:keys [::rpc/climit] :as cfg} f params]
(let [f (if climit
(let [f (if (some? executor)
(fn [cfg params] (px/await! (px/submit! executor (fn [] (f cfg params)))))
f)]
(build-exec-chain cfg f))
(build-exec-chain cfg f)
f)]
(f cfg params)))

View File

@@ -7,6 +7,7 @@
(ns app.rpc.commands.access-token
(:require
[app.common.schema :as sm]
[app.common.time :as ct]
[app.common.uuid :as uuid]
[app.db :as db]
[app.main :as-alias main]
@@ -15,22 +16,22 @@
[app.rpc.quotes :as quotes]
[app.setup :as-alias setup]
[app.tokens :as tokens]
[app.util.services :as sv]
[app.util.time :as dt]))
[app.util.services :as sv]))
(defn- decode-row
[row]
(dissoc row :perms))
(defn create-access-token
[{:keys [::db/conn ::setup/props]} profile-id name expiration]
(let [created-at (dt/now)
token-id (uuid/next)
token (tokens/generate props {:iss "access-token"
:tid token-id
:iat created-at})
[{:keys [::db/conn] :as cfg} profile-id name expiration]
(let [token-id (uuid/next)
expires-at (some-> expiration (ct/in-future))
created-at (ct/now)
token (tokens/generate cfg {:iss "access-token"
:uid profile-id
:iat created-at
:tid token-id})
expires-at (some-> expiration dt/in-future)
token (db/insert! conn :access-token
{:id token-id
:name name
@@ -43,18 +44,13 @@
(decode-row token)))
(defn repl:create-access-token
[{:keys [::db/pool] :as system} profile-id name expiration]
(db/with-atomic [conn pool]
(let [props (:app.setup/props system)]
(create-access-token {::db/conn conn ::setup/props props}
profile-id
name
expiration))))
[cfg profile-id name expiration]
(db/tx-run! cfg create-access-token profile-id name expiration))
(def ^:private schema:create-access-token
[:map {:title "create-access-token"}
[:name [:string {:max 250 :min 1}]]
[:expiration {:optional true} ::dt/duration]])
[:expiration {:optional true} ::ct/duration]])
(sv/defmethod ::create-access-token
{::doc/added "1.18"

View File

@@ -10,6 +10,7 @@
[app.common.data :as d]
[app.common.logging :as l]
[app.common.schema :as sm]
[app.common.time :as ct]
[app.common.uuid :as uuid]
[app.config :as cf]
[app.db :as db]
@@ -20,8 +21,7 @@
[app.rpc.doc :as-alias doc]
[app.rpc.helpers :as rph]
[app.util.inet :as inet]
[app.util.services :as sv]
[app.util.time :as dt]))
[app.util.services :as sv]))
(def ^:private event-columns
[:id
@@ -49,7 +49,7 @@
(defn- adjust-timestamp
[{:keys [timestamp created-at] :as event}]
(let [margin (inst-ms (dt/diff timestamp created-at))]
(let [margin (inst-ms (ct/diff timestamp created-at))]
(if (or (neg? margin)
(> margin 3600000))
;; If event is in future or lags more than 1 hour, we reasign
@@ -63,7 +63,7 @@
[{:keys [::db/pool]} {:keys [::rpc/profile-id events] :as params}]
(let [request (-> params meta ::http/request)
ip-addr (inet/parse-request request)
tnow (dt/now)
tnow (ct/now)
xform (comp
(map (fn [event]
(-> event
@@ -92,9 +92,9 @@
[:string {:max 250}]
[::sm/one-of {:format "string"} valid-event-types]]]
[:props
[:map-of :keyword :any]]
[:map-of :keyword ::sm/any]]
[:context {:optional true}
[:map-of :keyword :any]]])
[:map-of :keyword ::sm/any]]])
(def schema:push-audit-events
[:map {:title "push-audit-events"}

View File

@@ -6,20 +6,25 @@
(ns app.rpc.commands.auth
(:require
[app.auth :as auth]
[app.auth.oidc :as oidc]
[app.common.data :as d]
[app.common.data.macros :as dm]
[app.common.exceptions :as ex]
[app.common.features :as cfeat]
[app.common.logging :as l]
[app.common.schema :as sm]
[app.common.time :as ct]
[app.common.uri :as u]
[app.common.uuid :as uuid]
[app.config :as cf]
[app.db :as db]
[app.email :as eml]
[app.email.blacklist :as email.blacklist]
[app.email.whitelist :as email.whitelist]
[app.http :as-alias http]
[app.http.session :as session]
[app.loggers.audit :as audit]
[app.media :as media]
[app.rpc :as-alias rpc]
[app.rpc.climit :as-alias climit]
[app.rpc.commands.profile :as profile]
@@ -28,9 +33,9 @@
[app.rpc.helpers :as rph]
[app.setup :as-alias setup]
[app.setup.welcome-file :refer [create-welcome-file]]
[app.storage :as sto]
[app.tokens :as tokens]
[app.util.services :as sv]
[app.util.time :as dt]
[app.worker :as wrk]
[cuerdas.core :as str]))
@@ -42,7 +47,7 @@
(defn- elapsed-verify-threshold?
[profile]
(let [elapsed (dt/diff (:modified-at profile) (dt/now))
(let [elapsed (ct/diff (:modified-at profile) (ct/now))
verify-threshold (cf/get :email-verify-threshold)]
(pos? (compare elapsed verify-threshold))))
@@ -55,14 +60,14 @@
(contains? cf/flags :login-with-password))
(ex/raise :type :restriction
:code :login-disabled
:hint "login is disabled in this instance"))
:hint "login is disabled"))
(letfn [(check-password [cfg profile password]
(if (= (:password profile) "!")
(ex/raise :type :validation
:code :account-without-password
:hint "the current account does not have password")
(let [result (profile/verify-password cfg password (:password profile))]
(let [result (auth/verify-password password (:password profile))]
(when (:update result)
(l/trc :hint "updating profile password"
:id (str (:id profile))
@@ -79,12 +84,13 @@
:code :wrong-credentials))
(when (:is-blocked profile)
(ex/raise :type :restriction
:code :profile-blocked))
:code :profile-blocked
:hint "profile is marked as blocked"))
(when-not (check-password cfg profile password)
(ex/raise :type :validation
:code :wrong-credentials))
(when-let [deleted-at (:deleted-at profile)]
(when (dt/is-after? (dt/now) deleted-at)
(when (ct/is-after? (ct/now) deleted-at)
(ex/raise :type :validation
:code :wrong-credentials)))
@@ -97,7 +103,7 @@
(profile/strip-private-attrs))
invitation (when-let [token (:invitation-token params)]
(tokens/verify (::setup/props cfg) {:token token :iss :team-invitation}))
(tokens/verify cfg {:token token :iss :team-invitation}))
;; If invitation member-id does not matches the profile-id, we just proceed to ignore the
;; invitation because invitations matches exactly; and user can't login with other email and
@@ -107,7 +113,7 @@
(assoc profile :is-admin (let [admins (cf/get :admins)]
(contains? admins (:email profile)))))]
(-> response
(rph/with-transform (session/create-fn cfg (:id profile)))
(rph/with-transform (session/create-fn cfg profile))
(rph/with-meta {::audit/props (audit/profile->props profile)
::audit/profile-id (:id profile)}))))]
@@ -143,26 +149,43 @@
[cfg params]
(if (= (:profile-id params)
(::rpc/profile-id params))
(rph/with-transform {} (session/delete-fn cfg))
(let [{:keys [claims]}
(rph/get-auth-data params)
provider
(some->> (get claims :sso-provider-id)
(oidc/get-provider cfg))
response
(if (and provider (:logout-uri provider))
(let [params {"logout_hint" (get claims :sso-session-id)
"client_id" (get provider :client-id)
"post_logout_redirect_uri" (str (cf/get :public-uri))}
uri (-> (u/uri (:logout-uri provider))
(assoc :query (u/map->query-string params)))]
{:redirect-uri uri})
{})]
(rph/with-transform response (session/delete-fn cfg)))
{}))
;; ---- COMMAND: Recover Profile
(defn recover-profile
[{:keys [::db/pool] :as cfg} {:keys [token password]}]
[{:keys [::db/conn] :as cfg} {:keys [token password]}]
(letfn [(validate-token [token]
(let [tdata (tokens/verify (::setup/props cfg) {:token token :iss :password-recovery})]
(let [tdata (tokens/verify cfg {:token token :iss :password-recovery})]
(:profile-id tdata)))
(update-password [conn profile-id]
(let [pwd (profile/derive-password cfg password)]
(let [pwd (auth/derive-password password)]
(db/update! conn :profile {:password pwd :is-active true} {:id profile-id})
nil))]
(db/with-atomic [conn pool]
(->> (validate-token token)
(update-password conn))
nil)))
(->> (validate-token token)
(update-password conn))
nil))
(def schema:recover-profile
[:map {:title "recover-profile"}
@@ -173,7 +196,8 @@
{::rpc/auth false
::doc/added "1.15"
::sm/params schema:recover-profile
::climit/id :auth/global}
::climit/id :auth/global
::db/transaction true}
[cfg params]
(recover-profile cfg params))
@@ -182,14 +206,14 @@
(defn- validate-register-attempt!
[cfg params]
(when (or
(not (contains? cf/flags :registration))
(not (contains? cf/flags :login-with-password)))
(when (or (not (contains? cf/flags :registration))
(not (contains? cf/flags :login-with-password)))
(ex/raise :type :restriction
:code :registration-disabled))
:code :registration-disabled
:hint "registration disabled"))
(when (contains? params :invitation-token)
(let [invitation (tokens/verify (::setup/props cfg)
(let [invitation (tokens/verify cfg
{:token (:invitation-token params)
:iss :team-invitation})]
(when-not (= (:email params) (:member-email invitation))
@@ -200,12 +224,14 @@
(when (and (email.blacklist/enabled? cfg)
(email.blacklist/contains? cfg (:email params)))
(ex/raise :type :restriction
:code :email-domain-is-not-allowed))
:code :email-domain-is-not-allowed
:hint "email domain in blacklist"))
(when (and (email.whitelist/enabled? cfg)
(not (email.whitelist/contains? cfg (:email params))))
(ex/raise :type :restriction
:code :email-domain-is-not-allowed))
:code :email-domain-is-not-allowed
:hint "email domain not in whitelist"))
;; Perform a basic validation of email & password
(when (= (str/lower (:email params))
@@ -218,39 +244,43 @@
(ex/raise :type :restriction
:code :email-has-permanent-bounces
:email (:email params)
:hint "looks like the email has bounce reports"))
:hint "email has bounce reports"))
(when (eml/has-complaint-reports? cfg (:email params))
(ex/raise :type :restriction
:code :email-has-complaints
:email (:email params)
:hint "looks like the email has complaint reports")))
:hint "email has complaint reports")))
(defn prepare-register
[{:keys [::db/pool] :as cfg} {:keys [email] :as params}]
[{:keys [::db/pool] :as cfg} {:keys [fullname email accept-newsletter-updates] :as params}]
(validate-register-attempt! cfg params)
(let [email (profile/clean-email email)
profile (profile/get-profile-by-email pool email)
params {:email email
:fullname fullname
:password (:password params)
:invitation-token (:invitation-token params)
:backend "penpot"
:iss :prepared-register
:profile-id (:id profile)
:exp (dt/in-future {:days 7})}
:exp (ct/in-future {:days 7})
:props {:newsletter-updates (or accept-newsletter-updates false)}}
params (d/without-nils params)
token (tokens/generate (::setup/props cfg) params)]
token (tokens/generate cfg params)]
(with-meta {:token token}
{::audit/profile-id uuid/zero})))
(def schema:prepare-register-profile
[:map {:title "prepare-register-profile"}
[:fullname ::sm/text]
[:email ::sm/email]
[:password schema:password]
[:create-welcome-file {:optional true} :boolean]
[:invitation-token {:optional true} schema:token]])
(sv/defmethod ::prepare-register-profile
@@ -262,11 +292,29 @@
;; ---- COMMAND: Register Profile
(defn create-profile!
(defn import-profile-picture
[cfg uri]
(try
(let [storage (sto/resolve cfg)
input (media/download-image cfg uri)
input (media/run {:cmd :info :input input})
hash (sto/calculate-hash (:path input))
content (-> (sto/content (:path input) (:size input))
(sto/wrap-with-hash hash))
sobject (sto/put-object! storage {::sto/content content
::sto/deduplicate? true
:bucket "profile"
:content-type (:mtype input)})]
(:id sobject))
(catch Throwable cause
(l/err :hint "unable to import profile picture"
:cause cause)
nil)))
(defn create-profile
"Create the profile entry on the database with limited set of input
attrs (all the other attrs are filled with default values)."
[conn {:keys [email] :as params}]
(dm/assert! ::sm/email email)
[{:keys [::db/conn] :as cfg} {:keys [email] :as params}]
(let [id (or (:id params) (uuid/next))
props (-> (audit/extract-utm-params params)
(merge (:props params))
@@ -274,8 +322,7 @@
:viewed-walkthrough? false
:nudge {:big 10 :small 1}
:v2-info-shown true
:release-notes-viewed (:main cf/version)})
(db/tjson))
:release-notes-viewed (:main cf/version)}))
password (or (:password params) "!")
@@ -290,6 +337,12 @@
theme (:theme params nil)
email (str/lower email)
photo-id (some->> (or (:oidc/picture props)
(:google/picture props)
(:github/picture props)
(:gitlab/picture props))
(import-profile-picture cfg))
params {:id id
:fullname (:fullname params)
:email email
@@ -297,27 +350,26 @@
:lang locale
:password password
:deleted-at (:deleted-at params)
:props props
:props (db/tjson props)
:theme theme
:photo-id photo-id
:is-active is-active
:is-muted is-muted
:is-demo is-demo}]
(try
(-> (db/insert! conn :profile params)
(profile/decode-row))
(catch org.postgresql.util.PSQLException cause
(let [state (.getSQLState cause)]
(if (not= state "23505")
(throw cause)
(if (db/duplicate-key-error? cause)
(ex/raise :type :validation
:code :email-already-exists
:hint "email already exists"
:cause cause)
(throw cause))))))
(do
(l/error :hint "not an error" :cause cause)
(ex/raise :type :validation
:code :email-already-exists
:hint "email already exists"
:cause cause))))))))
(defn create-profile-rels!
(defn create-profile-rels
[conn {:keys [id] :as profile}]
(let [features (cfeat/get-enabled-features cf/flags)
team (teams/create-team conn
@@ -334,17 +386,17 @@
(defn send-email-verification!
[{:keys [::db/conn] :as cfg} profile]
(let [vtoken (tokens/generate (::setup/props cfg)
(let [vtoken (tokens/generate cfg
{:iss :verify-email
:exp (dt/in-future "72h")
:exp (ct/in-future "72h")
:profile-id (:id profile)
:email (:email profile)})
;; NOTE: this token is mainly used for possible complains
;; identification on the sns webhook
ptoken (tokens/generate (::setup/props cfg)
ptoken (tokens/generate cfg
{:iss :profile-identity
:profile-id (:id profile)
:exp (dt/in-future {:days 30})})]
:exp (ct/in-future {:days 30})})]
(eml/send! {::eml/conn conn
::eml/factory eml/register
:public-uri (cf/get :public-uri)
@@ -354,13 +406,9 @@
:extra-data ptoken})))
(defn register-profile
[{:keys [::db/conn ::wrk/executor] :as cfg} {:keys [token fullname theme] :as params}]
(let [theme (when (= theme "light") theme)
claims (tokens/verify (::setup/props cfg) {:token token :iss :prepared-register})
params (-> claims
(into params)
(assoc :fullname fullname)
(assoc :theme theme))
[{:keys [::db/conn ::wrk/executor] :as cfg} {:keys [token] :as params}]
(let [claims (tokens/verify cfg {:token token :iss :prepared-register})
params (into claims params)
profile (if-let [profile-id (:profile-id claims)]
(profile/get-profile conn profile-id)
@@ -371,18 +419,19 @@
;; to detect if the profile is already registered
(or (profile/get-profile-by-email conn (:email claims))
(let [is-active (or (boolean (:is-active claims))
(boolean (:email-verified claims))
(not (contains? cf/flags :email-verification)))
params (-> params
(assoc :is-active is-active)
(update :password #(profile/derive-password cfg %)))
profile (->> (create-profile! conn params)
(create-profile-rels! conn))]
(update :password auth/derive-password))
profile (->> (create-profile cfg params)
(create-profile-rels conn))]
(vary-meta profile assoc :created true))))
created? (-> profile meta :created true?)
invitation (when-let [token (:invitation-token params)]
(tokens/verify (::setup/props cfg) {:token token :iss :team-invitation}))
(tokens/verify cfg {:token token :iss :team-invitation}))
props (-> (audit/profile->props profile)
(assoc :from-invitation (some? invitation)))
@@ -414,10 +463,10 @@
(and (some? invitation)
(= (:email profile)
(:member-email invitation)))
(let [claims (assoc invitation :member-id (:id profile))
token (tokens/generate (::setup/props cfg) claims)]
(let [invitation (assoc invitation :member-id (:id profile))
token (tokens/generate cfg invitation)]
(-> {:invitation-token token}
(rph/with-transform (session/create-fn cfg (:id profile)))
(rph/with-transform (session/create-fn cfg profile claims))
(rph/with-meta {::audit/replace-props props
::audit/context {:action "accept-invitation"}
::audit/profile-id (:id profile)})))
@@ -428,7 +477,7 @@
created?
(if (:is-active profile)
(-> (profile/strip-private-attrs profile)
(rph/with-transform (session/create-fn cfg (:id profile)))
(rph/with-transform (session/create-fn cfg profile claims))
(rph/with-defer create-welcome-file-when-needed)
(rph/with-meta
{::audit/replace-props props
@@ -462,7 +511,7 @@
(when (= action "resend-email-verification")
(db/update! conn :profile
{:modified-at (dt/now)}
{:modified-at (ct/now)}
{:id (:id profile)})
(send-email-verification! cfg profile))
@@ -474,10 +523,7 @@
(def schema:register-profile
[:map {:title "register-profile"}
[:token schema:token]
[:fullname [::sm/word-string {:max 100}]]
[:theme {:optional true} [:string {:max 10}]]
[:create-welcome-file {:optional true} :boolean]])
[:token schema:token]])
(sv/defmethod ::register-profile
{::rpc/auth false
@@ -492,17 +538,17 @@
(defn- request-profile-recovery
[{:keys [::db/conn] :as cfg} {:keys [email] :as params}]
(letfn [(create-recovery-token [{:keys [id] :as profile}]
(let [token (tokens/generate (::setup/props cfg)
(let [token (tokens/generate cfg
{:iss :password-recovery
:exp (dt/in-future "15m")
:exp (ct/in-future "15m")
:profile-id id})]
(assoc profile :token token)))
(send-email-notification [conn profile]
(let [ptoken (tokens/generate (::setup/props cfg)
(let [ptoken (tokens/generate cfg
{:iss :profile-identity
:profile-id (:id profile)
:exp (dt/in-future {:days 30})})]
:exp (ct/in-future {:days 30})})]
(eml/send! {::eml/conn conn
::eml/factory eml/password-recovery
:public-uri (cf/get :public-uri)
@@ -543,7 +589,7 @@
:else
(do
(db/update! conn :profile
{:modified-at (dt/now)}
{:modified-at (ct/now)}
{:id (:id profile)})
(->> profile
(create-recovery-token)
@@ -560,4 +606,32 @@
[cfg params]
(db/tx-run! cfg request-profile-recovery params))
;; --- COMMAND: get-sso-config
(defn- extract-domain
"Extract the domain part from email"
[email]
(let [at (str/last-index-of email "@")]
(when (and (>= at 0)
(< at (dec (count email))))
(-> (subs email (inc at))
(str/trim)
(str/lower)))))
(def ^:private schema:get-sso-provider
[:map {:title "get-sso-config"}
[:email ::sm/email]])
(def ^:private schema:get-sso-provider-result
[:map {:title "SSOProvider"}
[:id ::sm/uuid]])
(sv/defmethod ::get-sso-provider
{::rpc/auth false
::doc/added "2.12"
::sm/params schema:get-sso-provider
::sm/result schema:get-sso-provider-result}
[cfg {:keys [email]}]
(when-let [domain (extract-domain email)]
(when-let [config (db/get* cfg :sso-provider {:domain domain})]
(select-keys config [:id]))))

View File

@@ -11,8 +11,9 @@
[app.binfile.v1 :as bf.v1]
[app.binfile.v3 :as bf.v3]
[app.common.features :as cfeat]
[app.common.logging :as l]
[app.common.schema :as sm]
[app.common.time :as ct]
[app.common.uri :as u]
[app.config :as cf]
[app.db :as db]
[app.http.sse :as sse]
@@ -24,12 +25,12 @@
[app.rpc.commands.projects :as projects]
[app.rpc.commands.teams :as teams]
[app.rpc.doc :as-alias doc]
[app.storage :as sto]
[app.storage.tmp :as tmp]
[app.tasks.file-gc]
[app.util.services :as sv]
[app.util.time :as dt]
[app.worker :as-alias wrk]
[promesa.exec :as px]
[yetti.response :as yres]))
[datoteka.fs :as fs]))
(set! *warn-on-reflection* true)
@@ -38,64 +39,48 @@
(def ^:private
schema:export-binfile
[:map {:title "export-binfile"}
[:name [:string {:max 250}]]
[:file-id ::sm/uuid]
[:version {:optional true} ::sm/int]
[:include-libraries ::sm/boolean]
[:embed-assets ::sm/boolean]])
(defn stream-export-v1
[cfg {:keys [file-id include-libraries embed-assets] :as params}]
(yres/stream-body
(fn [_ output-stream]
(try
(-> cfg
(assoc ::bfc/ids #{file-id})
(assoc ::bfc/embed-assets embed-assets)
(assoc ::bfc/include-libraries include-libraries)
(bf.v1/export-files! output-stream))
(catch Throwable cause
(l/err :hint "exception on exporting file"
:file-id (str file-id)
:cause cause))))))
(defn- export-binfile
[{:keys [::sto/storage] :as cfg} {:keys [file-id include-libraries embed-assets]}]
(let [output (tmp/tempfile*)]
(try
(-> cfg
(assoc ::bfc/ids #{file-id})
(assoc ::bfc/embed-assets embed-assets)
(assoc ::bfc/include-libraries include-libraries)
(bf.v3/export-files! output))
(defn stream-export-v3
[cfg {:keys [file-id include-libraries embed-assets] :as params}]
(yres/stream-body
(fn [_ output-stream]
(try
(-> cfg
(assoc ::bfc/ids #{file-id})
(assoc ::bfc/embed-assets embed-assets)
(assoc ::bfc/include-libraries include-libraries)
(bf.v3/export-files! output-stream))
(catch Throwable cause
(l/err :hint "exception on exporting file"
:file-id (str file-id)
:cause cause))))))
(let [data (sto/content output)
object (sto/put-object! storage
{::sto/content data
::sto/touched-at (ct/in-future {:minutes 60})
:content-type "application/zip"
:bucket "tempfile"})]
(-> (cf/get :public-uri)
(u/join "/assets/by-id/")
(u/join (str (:id object)))))
(finally
(fs/delete output)))))
(sv/defmethod ::export-binfile
"Export a penpot file in a binary format."
{::doc/added "1.15"
::doc/changes [["2.12" "Remove version parameter, only one version is supported"]]
::webhooks/event? true
::sm/result schema:export-binfile}
[{:keys [::db/pool] :as cfg} {:keys [::rpc/profile-id version file-id] :as params}]
::sm/params schema:export-binfile}
[{:keys [::db/pool] :as cfg} {:keys [::rpc/profile-id file-id] :as params}]
(files/check-read-permissions! pool profile-id file-id)
(fn [_]
(let [version (or version 1)
body (case (int version)
1 (stream-export-v1 cfg params)
2 (throw (ex-info "not-implemented" {}))
3 (stream-export-v3 cfg params))]
{::yres/status 200
::yres/headers {"content-type" "application/octet-stream"}
::yres/body body})))
(sse/response (partial export-binfile cfg params)))
;; --- Command: import-binfile
(defn- import-binfile
[{:keys [::db/pool ::wrk/executor] :as cfg} {:keys [profile-id project-id version name file]}]
[{:keys [::db/pool] :as cfg} {:keys [profile-id project-id version name file]}]
(let [team (teams/get-team pool
:profile-id profile-id
:project-id project-id)
@@ -106,17 +91,14 @@
(assoc ::bfc/name name)
(assoc ::bfc/input (:path file)))
;; NOTE: the importation process performs some operations that are
;; not very friendly with virtual threads, and for avoid
;; unexpected blocking of other concurrent operations we dispatch
;; that operation to a dedicated executor.
result (case (int version)
1 (px/invoke! executor (partial bf.v1/import-files! cfg))
3 (px/invoke! executor (partial bf.v3/import-files! cfg)))]
1 (bf.v1/import-files! cfg)
3 (bf.v3/import-files! cfg))]
(db/update! pool :project
{:modified-at (dt/now)}
{:id project-id})
{:modified-at (ct/now)}
{:id project-id}
{::db/return-keys false})
result))
@@ -125,20 +107,42 @@
[:name [:or [:string {:max 250}]
[:map-of ::sm/uuid [:string {:max 250}]]]]
[:project-id ::sm/uuid]
[:file-id {:optional true} ::sm/uuid]
[:version {:optional true} ::sm/int]
[:file ::media/upload]])
[:file media/schema:upload]])
(sv/defmethod ::import-binfile
"Import a penpot file in a binary format."
"Import a penpot file in a binary format. If `file-id` is provided,
an in-place import will be performed instead of creating a new file.
The in-place imports are only supported for binfile-v3 and when a
.penpot file only contains one penpot file.
"
{::doc/added "1.15"
::doc/changes ["1.20" "Add file-id param for in-place import"
"1.20" "Set default version to 3"]
::webhooks/event? true
::sse/stream? true
::sm/params schema:import-binfile}
[{:keys [::db/pool] :as cfg} {:keys [::rpc/profile-id project-id version] :as params}]
[{:keys [::db/pool] :as cfg} {:keys [::rpc/profile-id project-id version file-id file] :as params}]
(projects/check-edition-permissions! pool profile-id project-id)
(let [params (-> params
(assoc :profile-id profile-id)
(assoc :version (or version 1)))]
(let [version (or version 3)
params (-> params
(assoc :profile-id profile-id)
(assoc :version version))
cfg (cond-> cfg
(uuid? file-id)
(assoc ::bfc/file-id file-id))
manifest (case (int version)
1 nil
3 (bf.v3/get-manifest (:path file)))]
(with-meta
(sse/response (partial import-binfile cfg params))
{::audit/props {:file nil}})))
{::audit/props {:file nil
:file-id file-id
:generated-by (:generated-by manifest)
:referer (:referer manifest)}})))

View File

@@ -6,11 +6,13 @@
(ns app.rpc.commands.comments
(:require
[app.binfile.common :as bfc]
[app.common.data :as d]
[app.common.data.macros :as dm]
[app.common.exceptions :as ex]
[app.common.geom.point :as gpt]
[app.common.schema :as sm]
[app.common.time :as ct]
[app.common.uri :as uri]
[app.common.uuid :as uuid]
[app.config :as cf]
@@ -29,7 +31,6 @@
[app.rpc.retry :as rtry]
[app.util.pointer-map :as pmap]
[app.util.services :as sv]
[app.util.time :as dt]
[clojure.set :as set]
[cuerdas.core :as str]))
@@ -163,34 +164,16 @@
(def xf-decode-row
(map decode-row))
(def ^:private
sql:get-file
"SELECT f.id, f.modified_at, f.revn, f.features, f.name,
f.project_id, p.team_id, f.data,
f.data_ref_id, f.data_backend
FROM file as f
INNER JOIN project as p on (p.id = f.project_id)
WHERE f.id = ?
AND (f.deleted_at IS NULL OR f.deleted_at > now())")
(defn- get-file
"A specialized version of get-file for comments module."
[cfg file-id page-id]
(let [file (db/exec-one! cfg [sql:get-file file-id])]
(when-not file
(ex/raise :type :not-found
:code :object-not-found
:hint "file not found"))
(binding [pmap/*load-fn* (partial feat.fdata/load-pointer cfg file-id)]
(let [file (->> file
(files/decode-row)
(feat.fdata/resolve-file-data cfg))
data (get file :data)]
(-> file
(assoc :page-name (dm/get-in data [:pages-index page-id :name]))
(assoc :page-id page-id)
(dissoc :data))))))
(binding [pmap/*load-fn* (partial feat.fdata/load-pointer cfg file-id)]
(let [file (bfc/get-file cfg file-id)
data (get file :data)]
(-> file
(assoc :page-name (dm/get-in data [:pages-index page-id :name]))
(assoc :page-id page-id)
(dissoc :data)))))
;; FIXME: rename
(defn- get-comment-thread
@@ -222,7 +205,7 @@
(defn upsert-comment-thread-status!
([conn profile-id thread-id]
(upsert-comment-thread-status! conn profile-id thread-id (dt/in-future "1s")))
(upsert-comment-thread-status! conn profile-id thread-id (ct/in-future "1s")))
([conn profile-id thread-id mod-at]
(db/exec-one! conn [sql:upsert-comment-thread-status thread-id profile-id mod-at mod-at])))
@@ -251,34 +234,39 @@
(files/check-comment-permissions! conn profile-id file-id share-id)
(get-comment-threads conn profile-id file-id))))
(def ^:private sql:comment-threads
"SELECT DISTINCT ON (ct.id)
ct.*,
pf.fullname AS owner_fullname,
pf.email AS owner_email,
pf.photo_id AS owner_photo_id,
p.team_id AS team_id,
f.name AS file_name,
f.project_id AS project_id,
first_value(c.content) OVER w AS content,
(SELECT count(1)
FROM comment AS c
WHERE c.thread_id = ct.id) AS count_comments,
(SELECT count(1)
FROM comment AS c
WHERE c.thread_id = ct.id
AND c.created_at >= coalesce(cts.modified_at, ct.created_at)) AS count_unread_comments
FROM comment_thread AS ct
INNER JOIN comment AS c ON (c.thread_id = ct.id)
INNER JOIN file AS f ON (f.id = ct.file_id)
INNER JOIN project AS p ON (p.id = f.project_id)
LEFT JOIN comment_thread_status AS cts ON (cts.thread_id = ct.id AND cts.profile_id = ?)
LEFT JOIN profile AS pf ON (ct.owner_id = pf.id)
WINDOW w AS (PARTITION BY c.thread_id ORDER BY c.created_at ASC)")
(defn- get-comment-threads-sql
[where]
(str/ffmt
"SELECT DISTINCT ON (ct.id)
ct.*,
pf.fullname AS owner_fullname,
pf.email AS owner_email,
pf.photo_id AS owner_photo_id,
p.team_id AS team_id,
f.name AS file_name,
f.project_id AS project_id,
first_value(c.content) OVER w AS content,
(SELECT count(1)
FROM comment AS c
WHERE c.thread_id = ct.id) AS count_comments,
(SELECT count(1)
FROM comment AS c
WHERE c.thread_id = ct.id
AND c.created_at >= coalesce(cts.modified_at, ct.created_at)) AS count_unread_comments
FROM comment_thread AS ct
INNER JOIN comment AS c ON (c.thread_id = ct.id)
INNER JOIN file AS f ON (f.id = ct.file_id)
INNER JOIN project AS p ON (p.id = f.project_id)
LEFT JOIN comment_thread_status AS cts ON (cts.thread_id = ct.id AND cts.profile_id = ?)
LEFT JOIN profile AS pf ON (ct.owner_id = pf.id)
WHERE f.deleted_at IS NULL
AND p.deleted_at IS NULL
%1
WINDOW w AS (PARTITION BY c.thread_id ORDER BY c.created_at ASC)"
where))
(def ^:private sql:comment-threads-by-file-id
(str "WITH threads AS (" sql:comment-threads ")"
"SELECT * FROM threads WHERE file_id = ?"))
(get-comment-threads-sql "AND ct.file_id = ?"))
(defn- get-comment-threads
[conn profile-id file-id]
@@ -287,7 +275,30 @@
;; --- COMMAND: Get Unread Comment Threads
(declare ^:private get-unread-comment-threads)
(def ^:private sql:unread-all-comment-threads-by-team
(str "WITH threads AS ("
(get-comment-threads-sql "AND p.team_id = ?")
")"
"SELECT t.* FROM threads AS t
WHERE t.count_unread_comments > 0"))
(def ^:private sql:unread-partial-comment-threads-by-team
(str "WITH threads AS ("
(get-comment-threads-sql "AND p.team_id = ? AND (ct.owner_id = ? OR ? = ANY(ct.mentions))")
")"
"SELECT t.* FROM threads AS t
WHERE t.count_unread_comments > 0"))
(defn- get-unread-comment-threads
[cfg profile-id team-id]
(let [profile (-> (db/get cfg :profile {:id profile-id} ::db/remove-deleted false)
(profile/decode-row))
notify (or (-> profile :props :notifications :dashboard-comments) :all)
result (case notify
:all (db/exec! cfg [sql:unread-all-comment-threads-by-team profile-id team-id])
:partial (db/exec! cfg [sql:unread-partial-comment-threads-by-team profile-id team-id profile-id profile-id])
[])]
(into [] xf-decode-row result)))
(def ^:private
schema:get-unread-comment-threads
@@ -298,41 +309,8 @@
{::doc/added "1.15"
::sm/params schema:get-unread-comment-threads}
[cfg {:keys [::rpc/profile-id team-id] :as params}]
(db/run!
cfg
(fn [{:keys [::db/conn]}]
(teams/check-read-permissions! conn profile-id team-id)
(get-unread-comment-threads conn profile-id team-id))))
(def sql:unread-all-comment-threads-by-team
(str "WITH threads AS (" sql:comment-threads ")"
"SELECT * FROM threads WHERE count_unread_comments > 0 AND team_id = ?"))
;; The partial configuration will retrieve only comments created by the user and
;; threads that have a mention to the user.
(def sql:unread-partial-comment-threads-by-team
(str "WITH threads AS (" sql:comment-threads ")"
"SELECT * FROM threads
WHERE count_unread_comments > 0
AND team_id = ?
AND (owner_id = ? OR ? = ANY(mentions))"))
(defn- get-unread-comment-threads
[conn profile-id team-id]
(let [profile (-> (db/get conn :profile {:id profile-id})
(profile/decode-row))
notify (or (-> profile :props :notifications :dashboard-comments) :all)]
(case notify
:all
(->> (db/exec! conn [sql:unread-all-comment-threads-by-team profile-id team-id])
(into [] xf-decode-row))
:partial
(->> (db/exec! conn [sql:unread-partial-comment-threads-by-team profile-id team-id profile-id profile-id])
(into [] xf-decode-row))
[])))
(teams/check-read-permissions! cfg profile-id team-id)
(get-unread-comment-threads cfg profile-id team-id))
;; --- COMMAND: Get Single Comment Thread
@@ -343,16 +321,17 @@
[:id ::sm/uuid]
[:share-id {:optional true} [:maybe ::sm/uuid]]])
(def ^:private sql:get-comment-thread
(get-comment-threads-sql "AND ct.file_id = ? AND ct.id = ?"))
(sv/defmethod ::get-comment-thread
{::doc/added "1.15"
::sm/params schema:get-comment-thread}
[cfg {:keys [::rpc/profile-id file-id id share-id] :as params}]
(db/run! cfg (fn [{:keys [::db/conn]}]
(files/check-comment-permissions! conn profile-id file-id share-id)
(let [sql (str "WITH threads AS (" sql:comment-threads ")"
"SELECT * FROM threads WHERE id = ? AND file_id = ?")]
(-> (db/exec-one! conn [sql profile-id id file-id])
(decode-row))))))
(some-> (db/exec-one! conn [sql:get-comment-thread profile-id file-id id])
(decode-row)))))
;; --- COMMAND: Retrieve Comments
@@ -797,3 +776,18 @@
{:id id}
{::db/return-keys false})
nil))
(def ^:private
schema:mark-all-threads-as-read
[:map {:title "mark-all-threads-as-read"}
[:threads [:vector ::sm/uuid]]])
(sv/defmethod ::mark-all-threads-as-read
{::doc/added "1.15"
::sm/params schema:mark-all-threads-as-read}
[cfg {:keys [::rpc/profile-id threads] :as params}]
(db/tx-run!
cfg
(fn [{:keys [::db/conn]}]
(doseq [thread-id threads]
(upsert-comment-thread-status! conn profile-id thread-id)))))

View File

@@ -7,16 +7,16 @@
(ns app.rpc.commands.demo
"A demo specific mutations."
(:require
[app.auth :refer [derive-password]]
[app.common.exceptions :as ex]
[app.common.time :as ct]
[app.config :as cf]
[app.db :as db]
[app.loggers.audit :as audit]
[app.rpc :as-alias rpc]
[app.rpc.commands.auth :as auth]
[app.rpc.commands.profile :as profile]
[app.rpc.doc :as-alias doc]
[app.util.services :as sv]
[app.util.time :as dt]
[buddy.core.codecs :as bc]
[buddy.core.nonce :as bn]))
@@ -27,7 +27,7 @@
{::rpc/auth false
::doc/added "1.15"
::doc/changes ["1.15" "This method is migrated from mutations to commands."]}
[{:keys [::db/pool] :as cfg} _]
[cfg _]
(when-not (contains? cf/flags :demo-users)
(ex/raise :type :validation
@@ -39,19 +39,20 @@
fullname (str "Demo User " sem)
password (-> (bn/random-bytes 16)
(bc/bytes->b64u)
(bc/bytes->b64 true)
(bc/bytes->str))
params {:email email
:fullname fullname
:is-active true
:deleted-at (dt/in-future (cf/get-deletion-delay))
:password (profile/derive-password cfg password)
:props {}}]
:is-demo true
:deleted-at (ct/in-future (cf/get-deletion-delay))
:password (derive-password password)
:props {}}
profile (db/tx-run! cfg (fn [{:keys [::db/conn] :as cfg}]
(->> (auth/create-profile cfg params)
(auth/create-profile-rels conn))))]
(with-meta {:email email
:password password}
{::audit/profile-id (:id profile)})))
(db/with-atomic [conn pool]
(let [profile (->> (auth/create-profile! conn params)
(auth/create-profile-rels! conn))]
(with-meta {:email email
:password password}
{::audit/profile-id (:id profile)})))))

View File

@@ -7,6 +7,7 @@
(ns app.rpc.commands.feedback
"A general purpose feedback module."
(:require
[app.common.data :as d]
[app.common.exceptions :as ex]
[app.common.schema :as sm]
[app.config :as cf]
@@ -21,8 +22,11 @@
(def ^:private schema:send-user-feedback
[:map {:title "send-user-feedback"}
[:subject [:string {:max 400}]]
[:content [:string {:max 2500}]]])
[:subject [:string {:max 500}]]
[:content [:string {:max 2500}]]
[:type {:optional true} :string]
[:error-href {:optional true} [:string {:max 2500}]]
[:error-report {:optional true} :string]])
(sv/defmethod ::send-user-feedback
{::doc/added "1.18"
@@ -39,16 +43,26 @@
(defn- send-user-feedback!
[pool profile params]
(let [dest (or (cf/get :user-feedback-destination)
;; LEGACY
(cf/get :feedback-destination))]
(let [destination
(or (cf/get :user-feedback-destination)
;; LEGACY
(cf/get :feedback-destination))
attachments
(d/without-nils
{"error-report.txt" (:error-report params)})]
(eml/send! {::eml/conn pool
::eml/factory eml/user-feedback
:from dest
:to dest
:profile profile
:from (cf/get :smtp-default-from)
:to destination
:reply-to (:email profile)
:email (:email profile)
:subject (:subject params)
:content (:content params)})
:attachments attachments
:feedback-subject (:subject params)
:feedback-type (:type params "not-specified")
:feedback-content (:content params)
:feedback-error-href (:error-href params)
:profile profile})
nil))

View File

File diff suppressed because it is too large Load Diff

View File

@@ -7,9 +7,10 @@
(ns app.rpc.commands.files-create
(:require
[app.binfile.common :as bfc]
[app.common.data.macros :as dm]
[app.common.features :as cfeat]
[app.common.files.migrations :as fmg]
[app.common.schema :as sm]
[app.common.time :as ct]
[app.common.types.file :as ctf]
[app.config :as cf]
[app.db :as db]
@@ -23,13 +24,13 @@
[app.rpc.quotes :as quotes]
[app.util.pointer-map :as pmap]
[app.util.services :as sv]
[app.util.time :as dt]
[clojure.set :as set]))
(defn create-file-role!
[conn {:keys [file-id profile-id role]}]
(let [params {:file-id file-id
:profile-id profile-id}]
(->> (perms/assign-role-flags params role)
(db/insert! conn :file-profile-rel))))
@@ -41,34 +42,34 @@
:or {is-shared false revn 0 create-page true}
:as params}]
(dm/assert!
"expected a valid connection"
(db/connection? conn))
(assert (db/connection? conn) "expected a valid connection")
(binding [pmap/*tracked* (pmap/create-tracked)
cfeat/*current* features]
(let [file (ctf/make-file {:id id
:project-id project-id
:name name
:revn revn
:is-shared is-shared
:features features
:migrations fmg/available-migrations
:ignore-sync-until ignore-sync-until
:modified-at modified-at
:deleted-at deleted-at
:create-page create-page
:page-id page-id})
file (-> (bfc/insert-file! cfg file)
(bfc/decode-row))]
:created-at modified-at
:deleted-at deleted-at}
{:create-page create-page
:page-id page-id})]
(bfc/insert-file! cfg file)
(->> (assoc params :file-id (:id file) :role :owner)
(create-file-role! conn))
(db/update! conn :project
{:modified-at (dt/now)}
{:modified-at (ct/now)}
{:id project-id})
file)))
(bfc/get-file cfg (:id file)))))
(def ^:private schema:create-file
[:map {:title "create-file"}
@@ -91,9 +92,6 @@
:project-id project-id)
team-id (:id team)
;; When we create files, we only need to respect the team
;; features, because some features can be enabled
;; globally, but the team is still not migrated properly.
features (-> (cfeat/get-team-enabled-features cf/flags team)
(cfeat/check-client-features! (:features params)))
@@ -107,25 +105,29 @@
params (-> params
(assoc :profile-id profile-id)
(assoc :features (set/difference features cfeat/frontend-only-features)))]
(assoc :features features))]
(quotes/check! cfg {::quotes/id ::quotes/files-per-project
::quotes/team-id team-id
::quotes/profile-id profile-id
::quotes/project-id project-id})
;; FIXME: IMPORTANT: this code can have race
;; conditions, because we have no locks for updating
;; team so, creating two files concurrently can lead
;; to lost team features updating
;; FIXME: IMPORTANT: this code can have race conditions, because
;; we have no locks for updating team so, creating two files
;; concurrently can lead to lost team features updating
(when-let [features (-> features
(set/difference (:features team))
(set/difference cfeat/no-team-inheritable-features)
(not-empty))]
(let [features (-> features
(set/union (:features team))
(set/difference cfeat/no-team-inheritable-features)
(into-array))]
;; When newly computed features does not match exactly with
;; the features defined on team row, we update it.
(when (not= features (:features team))
(let [features (db/create-array conn "text" features)]
(db/update! conn :team
{:features features}
{:id team-id})))
{:id (:id team)}
{::db/return-keys false})))
(-> (create-file cfg params)
(vary-meta assoc ::audit/props {:team-id team-id}))))

Some files were not shown because too many files have changed in this diff Show More