🐛 Preserve OpenType variant name for custom fonts (#9193)

This commit is contained in:
Statxc 2026-04-30 15:29:04 +02:00 committed by GitHub
parent c14dbba7fd
commit 547750e8bf
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
8 changed files with 64 additions and 9 deletions

View File

@ -71,6 +71,7 @@
- Remove `corepack` from the MCP local launcher so it runs on Node.js 25+, where corepack is no longer bundled [Github #8877](https://github.com/penpot/penpot/issues/8877)
- Fix Copy as SVG: emit a single valid SVG document when multiple shapes are selected, and publish `image/svg+xml` to the clipboard so the paste target works in Inkscape and other SVG-native tools [Github #838](https://github.com/penpot/penpot/issues/838)
- Reset profile submenu state when the account menu closes (by @eureka0928) [Github #8947](https://github.com/penpot/penpot/issues/8947)
- Preserve OpenType variant name table for custom fonts in the dashboard [Github #8924](https://github.com/penpot/penpot/issues/8924)
- Add export panel to inspect styles tab [Taiga #13582](https://tree.taiga.io/project/penpot/issue/13582)
- Fix styles between grid layout inputs [Taiga #13526](https://tree.taiga.io/project/penpot/issue/13526)
- Fix id prop on switch component [Taiga #13534](https://tree.taiga.io/project/penpot/issue/13534)

View File

@ -475,7 +475,10 @@
:fn (mg/resource "app/migrations/sql/0147-mod-team-invitation-table.sql")}
{:name "0147-add-upload-session-table"
:fn (mg/resource "app/migrations/sql/0147-add-upload-session-table.sql")}])
:fn (mg/resource "app/migrations/sql/0147-add-upload-session-table.sql")}
{:name "0148-add-variant-name-team-font-variant"
:fn (mg/resource "app/migrations/sql/0148-add-variant-name-team-font-variant.sql")}])
(defn apply-migrations!
[pool name migrations]

View File

@ -0,0 +1,2 @@
ALTER TABLE team_font_variant
ADD COLUMN variant_name text NULL;

View File

@ -98,7 +98,8 @@
[:font-id ::sm/uuid]
[:font-family ::sm/text]
[:font-weight [::sm/one-of {:format "number"} valid-weight]]
[:font-style [::sm/one-of {:format "string"} valid-style]]])
[:font-style [::sm/one-of {:format "string"} valid-style]]
[:variant-name {:optional true} [:maybe ::sm/text]]])
;; FIXME: IMPORTANT: refactor this, we should not hold a whole db
;; connection around the font creation
@ -184,6 +185,7 @@
:font-family (:font-family params)
:font-weight (:font-weight params)
:font-style (:font-style params)
:variant-name (:variant-name params)
:woff1-file-id (:id woff1)
:woff2-file-id (:id woff2)
:otf-file-id (:id otf)

View File

@ -114,3 +114,15 @@
800 "Extra Bold"
900 "Black"
950 "Extra Black"))
(defn font-display-variant
[variant-name weight style]
(cond
(and (string? variant-name) (not (str/blank? variant-name)))
(str/trim variant-name)
:else
(let [base (font-weight->name weight)
italic? (= "italic" style)]
(cond-> base
italic? (str " Italic")))))

View File

@ -57,3 +57,38 @@
(t/testing "leaves filename intact when it has no extension"
(t/is (= (media/strip-image-extension "README") "README"))))
(t/deftest test-font-display-variant
(t/testing "preserves the foundry-supplied variant string verbatim"
(t/is (= "Thin" (media/font-display-variant "Thin" 100 "normal")))
(t/is (= "SemiBold" (media/font-display-variant "SemiBold" 600 "normal")))
(t/is (= "Medium Oblique" (media/font-display-variant "Medium Oblique" 500 "italic")))
(t/is (= "Ultra" (media/font-display-variant "Ultra" 900 "normal"))))
(t/testing "trims surrounding whitespace from upstream variant strings"
(t/is (= "Bold" (media/font-display-variant " Bold " 700 "normal"))))
(t/testing "ignores blank or nil variant strings"
(t/is (= "Hairline" (media/font-display-variant nil 100 "normal")))
(t/is (= "Regular" (media/font-display-variant "" 400 "normal")))
(t/is (= "Bold" (media/font-display-variant " " 700 "normal")))
(t/is (= "Bold Italic" (media/font-display-variant nil 700 "italic"))))
(t/testing "fallback covers every supported numeric weight"
(t/is (= "Hairline" (media/font-display-variant nil 100 "normal")))
(t/is (= "Extra Light" (media/font-display-variant nil 200 "normal")))
(t/is (= "Light" (media/font-display-variant nil 300 "normal")))
(t/is (= "Regular" (media/font-display-variant nil 400 "normal")))
(t/is (= "Medium" (media/font-display-variant nil 500 "normal")))
(t/is (= "Semi Bold" (media/font-display-variant nil 600 "normal")))
(t/is (= "Bold" (media/font-display-variant nil 700 "normal")))
(t/is (= "Extra Bold" (media/font-display-variant nil 800 "normal")))
(t/is (= "Black" (media/font-display-variant nil 900 "normal")))
(t/is (= "Extra Black" (media/font-display-variant nil 950 "normal"))))
(t/testing "italic suffix only applied via the fallback path"
(t/is (= "Italic" (media/font-display-variant "Italic" 400 "italic")))
(t/is (= "Regular Italic" (media/font-display-variant nil 400 "italic"))))
(t/testing "stored variant survives even when its derived weight disagrees"
(t/is (= "Ultra" (media/font-display-variant "Ultra" 400 "normal")))))

View File

@ -60,9 +60,9 @@
(prepare-font-variant [item]
{:id (str (:font-style item) "-" (:font-weight item))
:name (str (cm/font-weight->name (:font-weight item))
(when (not= "normal" (:font-style item))
(str " " (str/capital (:font-style item)))))
:name (cm/font-display-variant (:variant-name item)
(:font-weight item)
(:font-style item))
:style (:font-style item)
:weight (str (:font-weight item))
::fonts/woff1-file-id (:woff1-file-id item)
@ -140,6 +140,7 @@
:font-family (or family "")
:font-weight (cm/parse-font-weight variant)
:font-style (cm/parse-font-style variant)
:variant-name variant
:height-warning? height-warning?})
;; Font could not be parsed (woff2), extract metadata from filename
(let [base-name (str/replace name #"\.[^.]+$" "")

View File

@ -65,10 +65,9 @@
(mf/defc font-variant-display-name*
{::mf/private true}
[{:keys [variant]}]
[:*
[:span (cm/font-weight->name (:font-weight variant))]
(when (not= "normal" (:font-style variant))
[:span " " (str/capital (:font-style variant))])])
[:span (cm/font-display-variant (:variant-name variant)
(:font-weight variant)
(:font-style variant))])
(mf/defc uploaded-fonts*
{::mf/private true}