mirror of
https://github.com/penpot/penpot.git
synced 2026-07-22 05:57:56 +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:
|
||||
|
||||
```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
|
||||
|
||||
|
||||
@ -197,10 +197,10 @@ services:
|
||||
- penpot
|
||||
|
||||
environment:
|
||||
<< : [*penpot-secret-key]
|
||||
<< : [*penpot-secret-key, *penpot-public-uri]
|
||||
# Don't touch it; this uses an internal docker network to
|
||||
# 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.
|
||||
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.
|
||||
|
||||
### 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
|
||||
|
||||
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
|
||||
{:public-uri "http://localhost:3449"
|
||||
:internal-uri nil
|
||||
:tenant "default"
|
||||
:host "localhost"
|
||||
:http-server-port 6061
|
||||
@ -33,6 +34,7 @@
|
||||
[:map {:title "config"}
|
||||
[:secret-key :string]
|
||||
[:public-uri {:optional true} ::sm/uri]
|
||||
[:internal-uri {:optional true} ::sm/uri]
|
||||
[:exporter-shared-key {:optional true} :string]
|
||||
[:host {:optional true} :string]
|
||||
[:tenant {:optional true} :string]
|
||||
@ -100,6 +102,12 @@
|
||||
([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
|
||||
(let [key (or (c/get config :exporter-shared-key)
|
||||
(let [secret-key (c/get config :secret-key)
|
||||
|
||||
@ -21,6 +21,7 @@
|
||||
[& _]
|
||||
(l/info :msg "initializing"
|
||||
:public-uri (str (cf/get :public-uri))
|
||||
:internal-uri (str (cf/get-internal-uri))
|
||||
:version (:full cf/version))
|
||||
(p/do!
|
||||
(bwr/init)
|
||||
|
||||
@ -79,7 +79,7 @@
|
||||
:method "POST"
|
||||
:body fdata
|
||||
:dispatcher agent}
|
||||
uri (-> (cf/get :public-uri)
|
||||
uri (-> (cf/get-internal-uri)
|
||||
(u/ensure-path-slash)
|
||||
(u/join "api/management/methods/upload-tempfile")
|
||||
(str))]
|
||||
|
||||
@ -62,7 +62,7 @@
|
||||
:skip-children skip-children
|
||||
:wasm (when is-wasm "true")
|
||||
:scale scale}
|
||||
uri (-> (cf/get :public-uri)
|
||||
uri (-> (cf/get-internal-uri)
|
||||
(u/ensure-path-slash)
|
||||
(u/join "render.html")
|
||||
(assoc :query (u/map->query-string params)))]
|
||||
|
||||
@ -77,7 +77,7 @@
|
||||
(on-object (assoc object :path path))
|
||||
(p/recur (rest objects))))))]
|
||||
|
||||
(let [base-uri (-> (cf/get :public-uri)
|
||||
(let [base-uri (-> (cf/get-internal-uri)
|
||||
(u/ensure-path-slash))]
|
||||
(bw/exec! (prepare-options base-uri)
|
||||
(partial render base-uri)))))
|
||||
|
||||
@ -108,6 +108,18 @@
|
||||
{:width width
|
||||
: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
|
||||
[{:keys [page-id file-id share-id objects token scale type]} on-object]
|
||||
(letfn [(convert-to-ppm [pngpath]
|
||||
@ -320,7 +332,9 @@
|
||||
|
||||
result (if (contains? cf/flags :exporter-svgo)
|
||||
(svgo/optimize result svgo/defaultOptions)
|
||||
result)]
|
||||
result)
|
||||
|
||||
result (replace-internal-uris result)]
|
||||
|
||||
;; (println "------- ORIGIN:")
|
||||
;; (cljs.pprint/pprint (xml->clj xmldata))
|
||||
@ -349,7 +363,7 @@
|
||||
:render-embed true
|
||||
:object-id (mapv :id objects)
|
||||
:route "objects"}
|
||||
uri (-> (cf/get :public-uri)
|
||||
uri (-> (cf/get-internal-uri)
|
||||
(u/ensure-path-slash)
|
||||
(u/join "render.html")
|
||||
(assoc :query (u/map->query-string params)))]
|
||||
|
||||
@ -150,7 +150,7 @@
|
||||
.separator {
|
||||
margin: 0;
|
||||
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"] {
|
||||
|
||||
@ -171,12 +171,20 @@
|
||||
on-caps-start-change
|
||||
(mf/use-fn
|
||||
(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
|
||||
(mf/use-fn
|
||||
(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
|
||||
(mf/use-fn
|
||||
@ -191,16 +199,16 @@
|
||||
(on-detach-token token #{:stroke-width})))
|
||||
|
||||
stroke-caps-options
|
||||
[{:value nil :label (tr "workspace.options.stroke-cap.none")}
|
||||
:separator
|
||||
{:value :line-arrow :label (tr "workspace.options.stroke-cap.line-arrow-short") :icon :stroke-arrow}
|
||||
{:value :triangle-arrow :label (tr "workspace.options.stroke-cap.triangle-arrow-short") :icon :stroke-triangle}
|
||||
{:value :square-marker :label (tr "workspace.options.stroke-cap.square-marker-short") :icon :stroke-rectangle}
|
||||
{:value :circle-marker :label (tr "workspace.options.stroke-cap.circle-marker-short") :icon :stroke-circle}
|
||||
{:value :diamond-marker :label (tr "workspace.options.stroke-cap.diamond-marker-short") :icon :stroke-diamond}
|
||||
:separator
|
||||
{:value :round :label (tr "workspace.options.stroke-cap.round") :icon :stroke-rounded}
|
||||
{:value :square :label (tr "workspace.options.stroke-cap.square") :icon :stroke-squared}]
|
||||
[{:id "none" :value "none" :label (tr "workspace.options.stroke-cap.none")}
|
||||
{:label "" :type :separator :id "separator"}
|
||||
{:id "line-arrow" :value :line-arrow :label (tr "workspace.options.stroke-cap.line-arrow-short") :icon i/stroke-arrow}
|
||||
{:id "triangle-arrow" :value :triangle-arrow :label (tr "workspace.options.stroke-cap.triangle-arrow-short") :icon i/stroke-triangle}
|
||||
{:id "square-marker" :value :square-marker :label (tr "workspace.options.stroke-cap.square-marker-short") :icon i/stroke-rectangle}
|
||||
{:id "circle-marker" :value :circle-marker :label (tr "workspace.options.stroke-cap.circle-marker-short") :icon i/stroke-circle}
|
||||
{:id "diamond-marker" :value :diamond-marker :label (tr "workspace.options.stroke-cap.diamond-marker-short") :icon i/stroke-diamond}
|
||||
{:label "" :type :separator :id "separator"}
|
||||
{:id "round" :value :round :label (tr "workspace.options.stroke-cap.round") :icon i/stroke-rounded}
|
||||
{:id "square" :value :square :label (tr "workspace.options.stroke-cap.square") :icon i/stroke-squared}]
|
||||
|
||||
on-cap-switch
|
||||
(mf/use-fn
|
||||
@ -340,16 +348,18 @@
|
||||
;; Stroke Caps
|
||||
(when show-caps
|
||||
[:div {:class (stl/css :stroke-caps-options)}
|
||||
[:& select {:default-value (:stroke-cap-start stroke)
|
||||
:options stroke-caps-options
|
||||
:disabled hidden?
|
||||
:on-change on-caps-start-change}]
|
||||
[:> select* {:default-selected (or (d/name (:stroke-cap-start stroke)) "none")
|
||||
:options stroke-caps-options
|
||||
:data-testid "stroke.cap-start"
|
||||
:disabled hidden?
|
||||
:on-change on-caps-start-change}]
|
||||
[:> icon-button* {:variant "secondary"
|
||||
:aria-label (tr "labels.switch")
|
||||
:disabled hidden?
|
||||
:on-click on-cap-switch
|
||||
:icon i/switch}]
|
||||
[:& select {:default-value (:stroke-cap-end stroke)
|
||||
:options stroke-caps-options
|
||||
:disabled hidden?
|
||||
:on-change on-caps-end-change}]])]))
|
||||
[:> select* {:default-selected (or (d/name (:stroke-cap-end stroke)) "none")
|
||||
:options stroke-caps-options
|
||||
:data-testid "stroke.cap-end"
|
||||
:disabled hidden?
|
||||
:on-change on-caps-end-change}]])]))
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user