diff --git a/backend/src/app/rpc/commands/files.clj b/backend/src/app/rpc/commands/files.clj
index 366ba96499..9b518ca9d6 100644
--- a/backend/src/app/rpc/commands/files.clj
+++ b/backend/src/app/rpc/commands/files.clj
@@ -241,6 +241,18 @@
(some-> (db/get cfg :file-data {:file-id file-id :id fragment-id :type "fragment"})
(update :data blob/decode)))
+(defn- check-fragment-scope!
+ "Checks that the fragment is reachable from the pages authorized by
+ the share-link. Raises a :not-found exception if the fragment is not reachable."
+ [cfg file-id fragment-id pages]
+ (let [fdata (-> (bfc/get-file cfg file-id :read-only? true)
+ (get :data)
+ (update :pages-index select-keys pages))]
+ (when-not (contains? (feat.fdata/get-used-pointer-ids fdata) fragment-id)
+ (ex/raise :type :not-found
+ :code :object-not-found
+ :hint "object not found"))))
+
(sv/defmethod ::get-file-fragment
"Retrieve a file fragment by its ID. Only authenticated users."
{::doc/added "1.17"
@@ -250,11 +262,9 @@
[cfg {:keys [::rpc/profile-id file-id fragment-id share-id]}]
(db/run! cfg (fn [cfg]
(let [perms (perms/get-file-read-permissions cfg profile-id file-id share-id)]
- (when (= :share-link (:type perms))
- (ex/raise :type :not-found
- :code :object-not-found
- :hint "object not found"))
(check-read-permissions! perms)
+ (when (= :share-link (:type perms))
+ (check-fragment-scope! cfg file-id fragment-id (:pages perms)))
(-> (get-file-fragment cfg file-id fragment-id)
(rph/with-http-cache long-cache-duration))))))
diff --git a/frontend/src/app/main/data/viewer.cljs b/frontend/src/app/main/data/viewer.cljs
index 5b92a20316..4ad40beade 100644
--- a/frontend/src/app/main/data/viewer.cljs
+++ b/frontend/src/app/main/data/viewer.cljs
@@ -326,11 +326,12 @@
(filter #(= page-id (:page-id %)))
(d/index-by :id)
(assoc state :comment-threads)))
- (on-error [{:keys [type] :as err}]
- (if (or (= :authentication type)
- (= :not-found type))
- (rx/empty)
- (rx/throw err)))]
+ (on-error [cause]
+ (let [{:keys [type]} (ex-data cause)]
+ (if (or (= :authentication type)
+ (= :not-found type))
+ (rx/empty)
+ (rx/throw cause))))]
(ptk/reify ::fetch-comment-threads
ptk/WatchEvent
diff --git a/frontend/src/app/main/ui/auth/register.cljs b/frontend/src/app/main/ui/auth/register.cljs
index 68a2ac22b1..e6cd8197f5 100644
--- a/frontend/src/app/main/ui/auth/register.cljs
+++ b/frontend/src/app/main/ui/auth/register.cljs
@@ -114,6 +114,7 @@
(str "
"))]
(st/emit! (ntf/show {:content (tr "errors.weak-password")
:detail detail
+ :is-html true
:type :toast
:level :error})))
diff --git a/frontend/src/app/main/ui/nitrate/nitrate_code_activation_modal.cljs b/frontend/src/app/main/ui/nitrate/nitrate_code_activation_modal.cljs
index 1ede96a4d6..5d8f51a51f 100644
--- a/frontend/src/app/main/ui/nitrate/nitrate_code_activation_modal.cljs
+++ b/frontend/src/app/main/ui/nitrate/nitrate_code_activation_modal.cljs
@@ -120,7 +120,7 @@
[:div
(tr "nitrate.code-activation.footer-after") " "
[:a {:class (stl/css :link)
- :href "mailto:sales@nitrate.com"}
- "sales@nitrate.com"]
+ :href "mailto:sales@penpot.app"}
+ "sales@penpot.app"]
" "
(tr "nitrate.code-activation.footer-before")]]]]]))
diff --git a/frontend/src/app/main/ui/nitrate/nitrate_form.cljs b/frontend/src/app/main/ui/nitrate/nitrate_form.cljs
index 93e3a61eda..489ba391b9 100644
--- a/frontend/src/app/main/ui/nitrate/nitrate_form.cljs
+++ b/frontend/src/app/main/ui/nitrate/nitrate_form.cljs
@@ -118,8 +118,8 @@
(tr "nitrate.form.contact-upgrade")
(tr "nitrate.form.contact-trial"))]
[:p {:class (stl/css :modal-text-large)}
- [:a {:class (stl/css :link) :href "mailto:sales@penpot.app"}
- "sales@penpot.app"]]
+ [:a {:class (stl/css :link) :href "mailto:sales@penpot.net"}
+ "sales@penpot.net"]]
[:div {:class (stl/css :activation-code)}
[:p {:class (stl/css :modal-text-large)}
[:a {:class (stl/css :link)
diff --git a/frontend/src/app/main/ui/settings/subscription.cljs b/frontend/src/app/main/ui/settings/subscription.cljs
index a8a7f3fed9..ff38ffb1c6 100644
--- a/frontend/src/app/main/ui/settings/subscription.cljs
+++ b/frontend/src/app/main/ui/settings/subscription.cljs
@@ -745,7 +745,6 @@
:cta-link (if (and (contains? cf/flags :admin-console) nitrate?) #(open-contact-sales-modal subscription-type "Unlimited") #(open-subscription-modal "unlimited" subscription))
:cta-text-with-icon (tr "subscription.settings.more-information")
:cta-link-with-icon go-to-pricing-page
- :recommended (= subscription-type "professional")
:show-button-cta (= subscription-type "professional")
:current-plan false}])
@@ -783,6 +782,7 @@
:cta-text-with-icon (tr "subscription.settings.more-information")
:cta-link-with-icon go-to-pricing-page
:code-action :activate
+ :recommended (= subscription-type "professional")
:show-button-cta (not nitrate-license)
:current-plan false
:inline-error nitrate-start-error-message}])]]]))
@@ -848,8 +848,8 @@
[:div {:class (stl/css :modal-text)}
(tr "nitrate.form.enterprise-intro" ".") " " (if nitrate-license (tr "nitrate.form.contact-us-upgrade") (tr "nitrate.form.contact-us-free-trial"))]
[:div {:class (stl/css :modal-text)}
- [:a {:class (stl/css :cta-button) :href "mailto:sales@penpot.app"}
- "sales@penpot.app"]]])]]))
+ [:a {:class (stl/css :cta-button) :href "mailto:sales@penpot.net"}
+ "sales@penpot.net"]]])]]))
(mf/defc nitrate-contact-sales-dialog
{::mf/register modal/components
@@ -898,7 +898,7 @@
:on-click handle-close-dialog} (tr "ds.confirm-cancel")]
[:> button* {:variant "primary"
:type "button"
- :on-click #(dom/open-new-window (dm/str "mailto:sales@penpot.app?subject=Switch%20to%20the%20" subscription-type "%20plan"))} (tr "nitrate.contact-sales.button")]]])]]]))
+ :on-click #(dom/open-new-window (dm/str "mailto:sales@penpot.net?subject=Switch%20to%20the%20" subscription-type "%20plan"))} (tr "nitrate.contact-sales.button")]]])]]]))
(mf/defc nitrate-cancel-contact-sales-dialog
{::mf/register modal/components
diff --git a/frontend/src/app/main/ui/workspace/sidebar/options/menus/typography.cljs b/frontend/src/app/main/ui/workspace/sidebar/options/menus/typography.cljs
index b73d9dab19..8a8e41354c 100644
--- a/frontend/src/app/main/ui/workspace/sidebar/options/menus/typography.cljs
+++ b/frontend/src/app/main/ui/workspace/sidebar/options/menus/typography.cljs
@@ -164,11 +164,13 @@
(defn- sample-container-style
"Inline style that applies the typography font to the (clipped, fixed-height)
- sample container."
+ sample container. Must be a real JS object (`#js`), not a ClojureScript map:
+ the `:style` value here is a runtime expression, not a literal recognized by
+ the hiccup macro, so it reaches React unconverted."
[typography]
- {:font-family (:font-family typography)
- :font-weight (:font-weight typography)
- :font-style (:font-style typography)})
+ #js {:fontFamily (:font-family typography)
+ :fontWeight (:font-weight typography)
+ :fontStyle (:font-style typography)})
(defn- sample-text-style
"Inline style that optically centers the sample glyphs. Must be applied to
@@ -177,7 +179,7 @@
would shift the whole box relative to the row instead of the glyphs inside it."
[em]
(when-not (zero? em)
- {:transform (dm/str "translateY(" em "em)")}))
+ #js {:transform (dm/str "translateY(" em "em)")}))
;; --- FONT SELECTOR --------------------------------------------------------
@@ -219,6 +221,7 @@
:role "img"
:aria-label (:name font)}
[:use {:href (dm/str "#" fonts/preview-sprite-prefix font-id)}]]
+<<<<<<< HEAD
[:span {:class (stl/css :font-item-label)
:style (cond-> {}
loaded?
@@ -226,6 +229,20 @@
(not (zero? label-offset))
(assoc :transform (dm/str "translateY(" label-offset "em)")))}
(:name font)])))
+=======
+ ;; The vertical correction goes on an INNER span, not on `.font-item-label`
+ ;; itself: that class carries its own `overflow: hidden` (from the
+ ;; text-ellipsis mixin, needed to truncate long font names), and a
+ ;; transform applied to a self-clipping element moves its clip region
+ ;; along with it — a no-op. The inner span has no overflow of its own, so
+ ;; the shift actually moves the ink within the outer's fixed clip area.
+ [:span {:class (stl/css :font-item-label)}
+ [:span {:style #js {:fontFamily (when loaded?
+ (dm/str "\"" (:family font) "\", sans-serif"))
+ :transform (when-not (zero? label-offset)
+ (dm/str "translateY(" label-offset "em)"))}}
+ (:name font)]])))
+>>>>>>> origin/staging
(mf/defc font-item*
{::mf/wrap [mf/memo]}
diff --git a/frontend/src/app/main/ui/workspace/sidebar/options/menus/typography.scss b/frontend/src/app/main/ui/workspace/sidebar/options/menus/typography.scss
index a8ad4b21ef..bbfa19734e 100644
--- a/frontend/src/app/main/ui/workspace/sidebar/options/menus/typography.scss
+++ b/frontend/src/app/main/ui/workspace/sidebar/options/menus/typography.scss
@@ -101,7 +101,7 @@ $font-preview-box-height: 28px;
box-sizing: border-box;
background-color: var(--font-name-wrapper-background-color);
margin-block-end: var(--sp-s);
- padding: var(--sp-s) 0 var(--sp-s) var(--sp-m);
+ padding-inline-start: var(--sp-m);
&:focus-within {
--font-name-wrapper-border-color: var(--color-accent-primary);