mirror of
https://github.com/penpot/penpot.git
synced 2026-08-01 19:06:18 +00:00
Merge remote-tracking branch 'origin/staging' into develop
This commit is contained in:
commit
fd8cb957d1
@ -38,7 +38,7 @@ Include concise sections covering:
|
|||||||
PR descriptions follow this structure:
|
PR descriptions follow this structure:
|
||||||
|
|
||||||
```markdown
|
```markdown
|
||||||
**Note:** This PR was created with AI assistance as part of the Penpot MCP self-improvement initiative.
|
**Note:** This PR was created with AI assistance.
|
||||||
|
|
||||||
## What
|
## What
|
||||||
|
|
||||||
|
|||||||
@ -197,10 +197,10 @@ services:
|
|||||||
- penpot
|
- penpot
|
||||||
|
|
||||||
environment:
|
environment:
|
||||||
<< : [*penpot-secret-key]
|
<< : [*penpot-secret-key, *penpot-public-uri]
|
||||||
# Don't touch it; this uses an internal docker network to
|
# Don't touch it; this uses an internal docker network to
|
||||||
# communicate with the frontend.
|
# communicate with the frontend.
|
||||||
PENPOT_PUBLIC_URI: http://penpot-frontend:8080
|
PENPOT_INTERNAL_URI: http://penpot-frontend:8080
|
||||||
|
|
||||||
## Valkey (or previously Redis) is used for the websockets notifications.
|
## Valkey (or previously Redis) is used for the websockets notifications.
|
||||||
PENPOT_REDIS_URI: redis://penpot-valkey/0
|
PENPOT_REDIS_URI: redis://penpot-valkey/0
|
||||||
|
|||||||
@ -651,6 +651,21 @@ PENPOT_EXPORTER_URI: http://your-penpot-exporter:6061
|
|||||||
|
|
||||||
These variables are used for generate correct nginx.conf file on container startup.
|
These variables are used for generate correct nginx.conf file on container startup.
|
||||||
|
|
||||||
|
### Exporter
|
||||||
|
|
||||||
|
The exporter uses this variable:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Exporter
|
||||||
|
PENPOT_INTERNAL_URI: http://penpot-frontend:8080
|
||||||
|
```
|
||||||
|
|
||||||
|
- `PENPOT_INTERNAL_URI`: The URI used by the exporter's headless browser to
|
||||||
|
communicate with the frontend (internal Docker network). Defaults to
|
||||||
|
`PENPOT_PUBLIC_URI` if not set. The default value
|
||||||
|
`http://penpot-frontend:8080` used in the docker-compose is a good default and
|
||||||
|
it is recommended to keep it unchanged.
|
||||||
|
|
||||||
## Other flags
|
## Other flags
|
||||||
|
|
||||||
There are other flags that are useful for a more customized Penpot experience. This section has the list of the flags meant
|
There are other flags that are useful for a more customized Penpot experience. This section has the list of the flags meant
|
||||||
|
|||||||
@ -22,6 +22,7 @@
|
|||||||
|
|
||||||
(def ^:private defaults
|
(def ^:private defaults
|
||||||
{:public-uri "http://localhost:3449"
|
{:public-uri "http://localhost:3449"
|
||||||
|
:internal-uri nil
|
||||||
:tenant "default"
|
:tenant "default"
|
||||||
:host "localhost"
|
:host "localhost"
|
||||||
:http-server-port 6061
|
:http-server-port 6061
|
||||||
@ -33,6 +34,7 @@
|
|||||||
[:map {:title "config"}
|
[:map {:title "config"}
|
||||||
[:secret-key :string]
|
[:secret-key :string]
|
||||||
[:public-uri {:optional true} ::sm/uri]
|
[:public-uri {:optional true} ::sm/uri]
|
||||||
|
[:internal-uri {:optional true} ::sm/uri]
|
||||||
[:exporter-shared-key {:optional true} :string]
|
[:exporter-shared-key {:optional true} :string]
|
||||||
[:host {:optional true} :string]
|
[:host {:optional true} :string]
|
||||||
[:tenant {:optional true} :string]
|
[:tenant {:optional true} :string]
|
||||||
@ -100,6 +102,12 @@
|
|||||||
([key default]
|
([key default]
|
||||||
(c/get config key default)))
|
(c/get config key default)))
|
||||||
|
|
||||||
|
(defn get-internal-uri
|
||||||
|
"Returns internal-uri if set, otherwise falls back to public-uri."
|
||||||
|
[]
|
||||||
|
(or (c/get config :internal-uri)
|
||||||
|
(c/get config :public-uri)))
|
||||||
|
|
||||||
(def management-key
|
(def management-key
|
||||||
(let [key (or (c/get config :exporter-shared-key)
|
(let [key (or (c/get config :exporter-shared-key)
|
||||||
(let [secret-key (c/get config :secret-key)
|
(let [secret-key (c/get config :secret-key)
|
||||||
|
|||||||
@ -21,6 +21,7 @@
|
|||||||
[& _]
|
[& _]
|
||||||
(l/info :msg "initializing"
|
(l/info :msg "initializing"
|
||||||
:public-uri (str (cf/get :public-uri))
|
:public-uri (str (cf/get :public-uri))
|
||||||
|
:internal-uri (str (cf/get-internal-uri))
|
||||||
:version (:full cf/version))
|
:version (:full cf/version))
|
||||||
(p/do!
|
(p/do!
|
||||||
(bwr/init)
|
(bwr/init)
|
||||||
|
|||||||
@ -79,7 +79,7 @@
|
|||||||
:method "POST"
|
:method "POST"
|
||||||
:body fdata
|
:body fdata
|
||||||
:dispatcher agent}
|
:dispatcher agent}
|
||||||
uri (-> (cf/get :public-uri)
|
uri (-> (cf/get-internal-uri)
|
||||||
(u/ensure-path-slash)
|
(u/ensure-path-slash)
|
||||||
(u/join "api/management/methods/upload-tempfile")
|
(u/join "api/management/methods/upload-tempfile")
|
||||||
(str))]
|
(str))]
|
||||||
|
|||||||
@ -62,7 +62,7 @@
|
|||||||
:skip-children skip-children
|
:skip-children skip-children
|
||||||
:wasm (when is-wasm "true")
|
:wasm (when is-wasm "true")
|
||||||
:scale scale}
|
:scale scale}
|
||||||
uri (-> (cf/get :public-uri)
|
uri (-> (cf/get-internal-uri)
|
||||||
(u/ensure-path-slash)
|
(u/ensure-path-slash)
|
||||||
(u/join "render.html")
|
(u/join "render.html")
|
||||||
(assoc :query (u/map->query-string params)))]
|
(assoc :query (u/map->query-string params)))]
|
||||||
|
|||||||
@ -77,7 +77,7 @@
|
|||||||
(on-object (assoc object :path path))
|
(on-object (assoc object :path path))
|
||||||
(p/recur (rest objects))))))]
|
(p/recur (rest objects))))))]
|
||||||
|
|
||||||
(let [base-uri (-> (cf/get :public-uri)
|
(let [base-uri (-> (cf/get-internal-uri)
|
||||||
(u/ensure-path-slash))]
|
(u/ensure-path-slash))]
|
||||||
(bw/exec! (prepare-options base-uri)
|
(bw/exec! (prepare-options base-uri)
|
||||||
(partial render base-uri)))))
|
(partial render base-uri)))))
|
||||||
|
|||||||
@ -108,6 +108,18 @@
|
|||||||
{:width width
|
{:width width
|
||||||
:height height}))
|
:height height}))
|
||||||
|
|
||||||
|
(defn- replace-internal-uris
|
||||||
|
"Replaces internal-uri references with public-uri in SVG output.
|
||||||
|
This ensures that font URLs and other resource references in the
|
||||||
|
exported SVG use the public-facing URI accessible to end users."
|
||||||
|
[svg-content]
|
||||||
|
(let [internal-uri (str (cf/get-internal-uri))
|
||||||
|
public-uri (str (cf/get :public-uri))]
|
||||||
|
(if (and (not= internal-uri public-uri)
|
||||||
|
(str/includes? svg-content internal-uri))
|
||||||
|
(str/replace svg-content internal-uri public-uri)
|
||||||
|
svg-content)))
|
||||||
|
|
||||||
(defn render
|
(defn render
|
||||||
[{:keys [page-id file-id share-id objects token scale type]} on-object]
|
[{:keys [page-id file-id share-id objects token scale type]} on-object]
|
||||||
(letfn [(convert-to-ppm [pngpath]
|
(letfn [(convert-to-ppm [pngpath]
|
||||||
@ -320,7 +332,9 @@
|
|||||||
|
|
||||||
result (if (contains? cf/flags :exporter-svgo)
|
result (if (contains? cf/flags :exporter-svgo)
|
||||||
(svgo/optimize result svgo/defaultOptions)
|
(svgo/optimize result svgo/defaultOptions)
|
||||||
result)]
|
result)
|
||||||
|
|
||||||
|
result (replace-internal-uris result)]
|
||||||
|
|
||||||
;; (println "------- ORIGIN:")
|
;; (println "------- ORIGIN:")
|
||||||
;; (cljs.pprint/pprint (xml->clj xmldata))
|
;; (cljs.pprint/pprint (xml->clj xmldata))
|
||||||
@ -349,7 +363,7 @@
|
|||||||
:render-embed true
|
:render-embed true
|
||||||
:object-id (mapv :id objects)
|
:object-id (mapv :id objects)
|
||||||
:route "objects"}
|
:route "objects"}
|
||||||
uri (-> (cf/get :public-uri)
|
uri (-> (cf/get-internal-uri)
|
||||||
(u/ensure-path-slash)
|
(u/ensure-path-slash)
|
||||||
(u/join "render.html")
|
(u/join "render.html")
|
||||||
(assoc :query (u/map->query-string params)))]
|
(assoc :query (u/map->query-string params)))]
|
||||||
|
|||||||
@ -150,7 +150,7 @@
|
|||||||
.separator {
|
.separator {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
block-size: $sz-12;
|
block-size: $sz-12;
|
||||||
border-block-start: $b-1 solid var(--color-background-primary);
|
border-block-start: $b-1 solid var(--color-background-quaternary);
|
||||||
}
|
}
|
||||||
|
|
||||||
&[data-direction="up"] {
|
&[data-direction="up"] {
|
||||||
|
|||||||
@ -171,12 +171,20 @@
|
|||||||
on-caps-start-change
|
on-caps-start-change
|
||||||
(mf/use-fn
|
(mf/use-fn
|
||||||
(mf/deps index on-stroke-cap-start-change)
|
(mf/deps index on-stroke-cap-start-change)
|
||||||
#(on-stroke-cap-start-change index (keyword %)))
|
(fn [cap]
|
||||||
|
(let [cap (if (= cap "none")
|
||||||
|
nil
|
||||||
|
(keyword cap))]
|
||||||
|
(on-stroke-cap-start-change index cap))))
|
||||||
|
|
||||||
on-caps-end-change
|
on-caps-end-change
|
||||||
(mf/use-fn
|
(mf/use-fn
|
||||||
(mf/deps index on-stroke-cap-end-change)
|
(mf/deps index on-stroke-cap-end-change)
|
||||||
#(on-stroke-cap-end-change index (keyword %)))
|
(fn [cap]
|
||||||
|
(let [cap (if (= cap "none")
|
||||||
|
nil
|
||||||
|
(keyword cap))]
|
||||||
|
(on-stroke-cap-end-change index cap))))
|
||||||
|
|
||||||
on-detach-token-color
|
on-detach-token-color
|
||||||
(mf/use-fn
|
(mf/use-fn
|
||||||
@ -191,16 +199,16 @@
|
|||||||
(on-detach-token token #{:stroke-width})))
|
(on-detach-token token #{:stroke-width})))
|
||||||
|
|
||||||
stroke-caps-options
|
stroke-caps-options
|
||||||
[{:value nil :label (tr "workspace.options.stroke-cap.none")}
|
[{:id "none" :value "none" :label (tr "workspace.options.stroke-cap.none")}
|
||||||
:separator
|
{:label "" :type :separator :id "separator"}
|
||||||
{:value :line-arrow :label (tr "workspace.options.stroke-cap.line-arrow-short") :icon :stroke-arrow}
|
{:id "line-arrow" :value :line-arrow :label (tr "workspace.options.stroke-cap.line-arrow-short") :icon i/stroke-arrow}
|
||||||
{:value :triangle-arrow :label (tr "workspace.options.stroke-cap.triangle-arrow-short") :icon :stroke-triangle}
|
{:id "triangle-arrow" :value :triangle-arrow :label (tr "workspace.options.stroke-cap.triangle-arrow-short") :icon i/stroke-triangle}
|
||||||
{:value :square-marker :label (tr "workspace.options.stroke-cap.square-marker-short") :icon :stroke-rectangle}
|
{:id "square-marker" :value :square-marker :label (tr "workspace.options.stroke-cap.square-marker-short") :icon i/stroke-rectangle}
|
||||||
{:value :circle-marker :label (tr "workspace.options.stroke-cap.circle-marker-short") :icon :stroke-circle}
|
{:id "circle-marker" :value :circle-marker :label (tr "workspace.options.stroke-cap.circle-marker-short") :icon i/stroke-circle}
|
||||||
{:value :diamond-marker :label (tr "workspace.options.stroke-cap.diamond-marker-short") :icon :stroke-diamond}
|
{:id "diamond-marker" :value :diamond-marker :label (tr "workspace.options.stroke-cap.diamond-marker-short") :icon i/stroke-diamond}
|
||||||
:separator
|
{:label "" :type :separator :id "separator"}
|
||||||
{:value :round :label (tr "workspace.options.stroke-cap.round") :icon :stroke-rounded}
|
{:id "round" :value :round :label (tr "workspace.options.stroke-cap.round") :icon i/stroke-rounded}
|
||||||
{:value :square :label (tr "workspace.options.stroke-cap.square") :icon :stroke-squared}]
|
{:id "square" :value :square :label (tr "workspace.options.stroke-cap.square") :icon i/stroke-squared}]
|
||||||
|
|
||||||
on-cap-switch
|
on-cap-switch
|
||||||
(mf/use-fn
|
(mf/use-fn
|
||||||
@ -340,16 +348,18 @@
|
|||||||
;; Stroke Caps
|
;; Stroke Caps
|
||||||
(when show-caps
|
(when show-caps
|
||||||
[:div {:class (stl/css :stroke-caps-options)}
|
[:div {:class (stl/css :stroke-caps-options)}
|
||||||
[:& select {:default-value (:stroke-cap-start stroke)
|
[:> select* {:default-selected (or (d/name (:stroke-cap-start stroke)) "none")
|
||||||
:options stroke-caps-options
|
:options stroke-caps-options
|
||||||
:disabled hidden?
|
:data-testid "stroke.cap-start"
|
||||||
:on-change on-caps-start-change}]
|
:disabled hidden?
|
||||||
|
:on-change on-caps-start-change}]
|
||||||
[:> icon-button* {:variant "secondary"
|
[:> icon-button* {:variant "secondary"
|
||||||
:aria-label (tr "labels.switch")
|
:aria-label (tr "labels.switch")
|
||||||
:disabled hidden?
|
:disabled hidden?
|
||||||
:on-click on-cap-switch
|
:on-click on-cap-switch
|
||||||
:icon i/switch}]
|
:icon i/switch}]
|
||||||
[:& select {:default-value (:stroke-cap-end stroke)
|
[:> select* {:default-selected (or (d/name (:stroke-cap-end stroke)) "none")
|
||||||
:options stroke-caps-options
|
:options stroke-caps-options
|
||||||
:disabled hidden?
|
:data-testid "stroke.cap-end"
|
||||||
:on-change on-caps-end-change}]])]))
|
:disabled hidden?
|
||||||
|
:on-change on-caps-end-change}]])]))
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user