diff --git a/.cspell.json b/.cspell.json
index baf59df869..c94adfffdd 100644
--- a/.cspell.json
+++ b/.cspell.json
@@ -145,6 +145,7 @@
"octocat",
"openapi",
"opensource",
+ "opentype",
"Pacman",
"picus",
"Pinia",
@@ -178,6 +179,7 @@
"secprofile",
"selfhosted",
"sess",
+ "sfnt",
"shellescape",
"sigstore",
"Sonatype",
diff --git a/docs/plugins/woodpecker-plugins/package.json b/docs/plugins/woodpecker-plugins/package.json
index e6ed05ad68..5ab25773ab 100644
--- a/docs/plugins/woodpecker-plugins/package.json
+++ b/docs/plugins/woodpecker-plugins/package.json
@@ -17,7 +17,7 @@
"@types/node": "^24.10.9",
"axios": "^1.13.4",
"concurrently": "^9.2.1",
- "isomorphic-dompurify": "^2.35.0",
+ "isomorphic-dompurify": "^3.0.0",
"marked": "^17.0.1",
"slugify": "^1.6.6",
"tslib": "^2.8.1",
diff --git a/docs/pnpm-lock.yaml b/docs/pnpm-lock.yaml
index fdcbe1ff30..a69e62ff0a 100644
--- a/docs/pnpm-lock.yaml
+++ b/docs/pnpm-lock.yaml
@@ -113,8 +113,8 @@ importers:
specifier: ^9.2.1
version: 9.2.1
isomorphic-dompurify:
- specifier: ^2.35.0
- version: 2.36.0
+ specifier: ^3.0.0
+ version: 3.0.0
marked:
specifier: ^17.0.1
version: 17.0.3
@@ -1635,24 +1635,28 @@ packages:
engines: {node: '>= 10'}
cpu: [arm64]
os: [linux]
+ libc: [glibc]
'@node-rs/jieba-linux-arm64-musl@1.10.4':
resolution: {integrity: sha512-Y/tiJ1+HeS5nnmLbZOE+66LbsPOHZ/PUckAYVeLlQfpygLEpLYdlh0aPpS5uiaWMjAXYZYdFkpZHhxDmSLpwpw==}
engines: {node: '>= 10'}
cpu: [arm64]
os: [linux]
+ libc: [musl]
'@node-rs/jieba-linux-x64-gnu@1.10.4':
resolution: {integrity: sha512-WZO8ykRJpWGE9MHuZpy1lu3nJluPoeB+fIJJn5CWZ9YTVhNDWoCF4i/7nxz1ntulINYGQ8VVuCU9LD86Mek97g==}
engines: {node: '>= 10'}
cpu: [x64]
os: [linux]
+ libc: [glibc]
'@node-rs/jieba-linux-x64-musl@1.10.4':
resolution: {integrity: sha512-uBBD4S1rGKcgCyAk6VCKatEVQb6EDD5I40v/DxODi5CuZVCANi9m5oee/MQbAoaX7RydA2f0OSCE9/tcwXEwUg==}
engines: {node: '>= 10'}
cpu: [x64]
os: [linux]
+ libc: [musl]
'@node-rs/jieba-wasm32-wasi@1.10.4':
resolution: {integrity: sha512-Y2umiKHjuIJy0uulNDz9SDYHdfq5Hmy7jY5nORO99B4pySKkcrMjpeVrmWXJLIsEKLJwcCXHxz8tjwU5/uhz0A==}
@@ -1766,21 +1770,25 @@ packages:
resolution: {integrity: sha512-eQfcsaxhFrv5FmtaA7+O1F9/2yFDNIoPZzV/ZvqvFz5bBXVc4FAm/1fVpBg8Po/kX1h0chBc7Xkpry3cabFW8w==}
cpu: [arm64]
os: [linux]
+ libc: [glibc]
'@rspack/binding-linux-arm64-musl@1.7.6':
resolution: {integrity: sha512-DfQXKiyPIl7i1yECHy4eAkSmlUzzsSAbOjgMuKn7pudsWf483jg0UUYutNgXSlBjc/QSUp7906Cg8oty9OfwPA==}
cpu: [arm64]
os: [linux]
+ libc: [musl]
'@rspack/binding-linux-x64-gnu@1.7.6':
resolution: {integrity: sha512-NdA+2X3lk2GGrMMnTGyYTzM3pn+zNjaqXqlgKmFBXvjfZqzSsKq3pdD1KHZCd5QHN+Fwvoszj0JFsquEVhE1og==}
cpu: [x64]
os: [linux]
+ libc: [glibc]
'@rspack/binding-linux-x64-musl@1.7.6':
resolution: {integrity: sha512-rEy6MHKob02t/77YNgr6dREyJ0e0tv1X6Xsg8Z5E7rPXead06zefUbfazj4RELYySWnM38ovZyJAkPx/gOn3VA==}
cpu: [x64]
os: [linux]
+ libc: [musl]
'@rspack/binding-wasm32-wasi@1.7.6':
resolution: {integrity: sha512-YupOrz0daSG+YBbCIgpDgzfMM38YpChv+afZpaxx5Ml7xPeAZIIdgWmLHnQ2rts73N2M1NspAiBwV00Xx0N4Vg==}
@@ -1946,24 +1954,28 @@ packages:
engines: {node: '>=10'}
cpu: [arm64]
os: [linux]
+ libc: [glibc]
'@swc/core-linux-arm64-musl@1.15.11':
resolution: {integrity: sha512-PYftgsTaGnfDK4m6/dty9ryK1FbLk+LosDJ/RJR2nkXGc8rd+WenXIlvHjWULiBVnS1RsjHHOXmTS4nDhe0v0w==}
engines: {node: '>=10'}
cpu: [arm64]
os: [linux]
+ libc: [musl]
'@swc/core-linux-x64-gnu@1.15.11':
resolution: {integrity: sha512-DKtnJKIHiZdARyTKiX7zdRjiDS1KihkQWatQiCHMv+zc2sfwb4Glrodx2VLOX4rsa92NLR0Sw8WLcPEMFY1szQ==}
engines: {node: '>=10'}
cpu: [x64]
os: [linux]
+ libc: [glibc]
'@swc/core-linux-x64-musl@1.15.11':
resolution: {integrity: sha512-mUjjntHj4+8WBaiDe5UwRNHuEzLjIWBTSGTw0JT9+C9/Yyuh4KQqlcEQ3ro6GkHmBGXBFpGIj/o5VMyRWfVfWw==}
engines: {node: '>=10'}
cpu: [x64]
os: [linux]
+ libc: [musl]
'@swc/core-win32-arm64-msvc@1.15.11':
resolution: {integrity: sha512-ZkNNG5zL49YpaFzfl6fskNOSxtcZ5uOYmWBkY4wVAvgbSAQzLRVBp+xArGWh2oXlY/WgL99zQSGTv7RI5E6nzA==}
@@ -2018,24 +2030,28 @@ packages:
engines: {node: '>=10'}
cpu: [arm64]
os: [linux]
+ libc: [glibc]
'@swc/html-linux-arm64-musl@1.15.11':
resolution: {integrity: sha512-aNACh2/HPy52VbKPqHieVRDeKzkO66DQdlhiVUi+fggdn8khvllni6Xr52INeAMjYFASrTTth/3vKXMv215t3A==}
engines: {node: '>=10'}
cpu: [arm64]
os: [linux]
+ libc: [musl]
'@swc/html-linux-x64-gnu@1.15.11':
resolution: {integrity: sha512-8YOar0XeRLBzA+UMMW5smGpsQamoZLtaQ5RKGfap21FxOUUXqkPhkDTRr+kBVCYb47yz3NokjTPaDGTWOYNyww==}
engines: {node: '>=10'}
cpu: [x64]
os: [linux]
+ libc: [glibc]
'@swc/html-linux-x64-musl@1.15.11':
resolution: {integrity: sha512-em2Ur0uGFA/nw2JbMclXu9mLuUC7q/1J06i8FZTRHqZzNGt9Q0UMdgH9T8HkGLT5e7dZ6ROJoq1H4st6B8N3uw==}
engines: {node: '>=10'}
cpu: [x64]
os: [linux]
+ libc: [musl]
'@swc/html-win32-arm64-msvc@1.15.11':
resolution: {integrity: sha512-Xf9Vd4UsYTs4ejBwS+j9zShkyp3KQ+qfn/ZKVMKDygWjuOjU6FFXWYm93/PdTmS5qD0c58FhmoqTv+uFEZ4nxQ==}
@@ -3854,9 +3870,9 @@ packages:
resolution: {integrity: sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==}
engines: {node: '>=0.10.0'}
- isomorphic-dompurify@2.36.0:
- resolution: {integrity: sha512-E8YkGyPY3a/U5s0WOoc8Ok+3SWL/33yn2IHCoxCFLBUUPVy9WGa++akJZFxQCcJIhI+UvYhbrbnTIFQkHKZbgA==}
- engines: {node: '>=20.19.5'}
+ isomorphic-dompurify@3.0.0:
+ resolution: {integrity: sha512-5K+MYP7Nrg74+Bi+QmQGzQ/FgEOyVHWsN8MuJy5wYQxxBRxPnWsD25Tjjt5FWYhan3OQ+vNLubyNJH9dfG03lQ==}
+ engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0}
jest-util@29.7.0:
resolution: {integrity: sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==}
@@ -3989,24 +4005,28 @@ packages:
engines: {node: '>= 12.0.0'}
cpu: [arm64]
os: [linux]
+ libc: [glibc]
lightningcss-linux-arm64-musl@1.31.1:
resolution: {integrity: sha512-mVZ7Pg2zIbe3XlNbZJdjs86YViQFoJSpc41CbVmKBPiGmC4YrfeOyz65ms2qpAobVd7WQsbW4PdsSJEMymyIMg==}
engines: {node: '>= 12.0.0'}
cpu: [arm64]
os: [linux]
+ libc: [musl]
lightningcss-linux-x64-gnu@1.31.1:
resolution: {integrity: sha512-xGlFWRMl+0KvUhgySdIaReQdB4FNudfUTARn7q0hh/V67PVGCs3ADFjw+6++kG1RNd0zdGRlEKa+T13/tQjPMA==}
engines: {node: '>= 12.0.0'}
cpu: [x64]
os: [linux]
+ libc: [glibc]
lightningcss-linux-x64-musl@1.31.1:
resolution: {integrity: sha512-eowF8PrKHw9LpoZii5tdZwnBcYDxRw2rRCyvAXLi34iyeYfqCQNA9rmUM0ce62NlPhCvof1+9ivRaTY6pSKDaA==}
engines: {node: '>= 12.0.0'}
cpu: [x64]
os: [linux]
+ libc: [musl]
lightningcss-win32-arm64-msvc@1.31.1:
resolution: {integrity: sha512-aJReEbSEQzx1uBlQizAOBSjcmr9dCdL3XuC/6HLXAxmtErsj2ICo5yYggg1qOODQMtnjNQv2UHb9NpOuFtYe4w==}
@@ -11002,7 +11022,7 @@ snapshots:
isobject@3.0.1: {}
- isomorphic-dompurify@2.36.0:
+ isomorphic-dompurify@3.0.0:
dependencies:
dompurify: 3.3.1
jsdom: 28.1.0
diff --git a/go.mod b/go.mod
index 930adaa00f..05445758dd 100644
--- a/go.mod
+++ b/go.mod
@@ -30,7 +30,6 @@ require (
github.com/go-sql-driver/mysql v1.9.3
github.com/go-viper/mapstructure/v2 v2.5.0
github.com/golang-jwt/jwt/v5 v5.3.1
- github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0
github.com/google/go-github/v83 v83.0.0
github.com/hashicorp/go-hclog v1.6.3
github.com/hashicorp/go-plugin v1.7.0
@@ -79,7 +78,7 @@ require (
)
require (
- filippo.io/edwards25519 v1.1.0 // indirect
+ filippo.io/edwards25519 v1.2.0 // indirect
github.com/42wim/httpsig v1.2.3 // indirect
github.com/Azure/go-ansiterm v0.0.0-20250102033503-faa5f7b0171c // indirect
github.com/KyleBanks/depth v1.2.1 // indirect
diff --git a/go.sum b/go.sum
index 6d01e49431..74614ed4d8 100644
--- a/go.sum
+++ b/go.sum
@@ -10,6 +10,8 @@ codeberg.org/mvdkleijn/forgejo-sdk/forgejo/v2 v2.2.0 h1:HTCWpzyWQOHDWt3LzI6/d2jv
codeberg.org/mvdkleijn/forgejo-sdk/forgejo/v2 v2.2.0/go.mod h1:ZglEEDj+qkxYUb+SQIeqGtFxQrbaMYqIOgahNKb7uxs=
filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA=
filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4=
+filippo.io/edwards25519 v1.2.0 h1:crnVqOiS4jqYleHd9vaKZ+HKtHfllngJIiOpNpoJsjo=
+filippo.io/edwards25519 v1.2.0/go.mod h1:xzAOLCNug/yB62zG1bQ8uziwrIqIuxhctzJT18Q77mc=
gitea.com/xorm/sqlfiddle v0.0.0-20180821085327-62ce714f951a h1:lSA0F4e9A2NcQSqGqTOXqu2aRi/XEQxDCBwM8yJtE6s=
gitea.com/xorm/sqlfiddle v0.0.0-20180821085327-62ce714f951a/go.mod h1:EXuID2Zs0pAQhH8yz+DNjUbjppKQzKFAn28TMYPB6IU=
gitee.com/travelliu/dm v1.8.11192/go.mod h1:DHTzyhCrM843x9VdKVbZ+GKXGRbKM2sJ4LxihRxShkE=
@@ -227,8 +229,6 @@ github.com/golang-sql/civil v0.0.0-20220223132316-b832511892a9 h1:au07oEsX2xN0kt
github.com/golang-sql/civil v0.0.0-20220223132316-b832511892a9/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0=
github.com/golang-sql/sqlexp v0.1.0 h1:ZCD6MBpcuOVfGVqsEmY5/4FtYiKz6tSyUv9LPEDei6A=
github.com/golang-sql/sqlexp v0.1.0/go.mod h1:J4ad9Vo8ZCWQ2GMrC4UCQy1JpCbwU9m3EOqtpKwwwHI=
-github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 h1:DACJavvAHhabrF08vX0COfcOBJRhZ8lUbR+ZWIs0Y5g=
-github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGwJL78qG/PmXZO1EjYhfJinVAhrmmHX6Z8B9k=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA=
diff --git a/server/badges/badges_test.go b/server/badges/badges_test.go
index b837556a76..d2f6d14121 100644
--- a/server/badges/badges_test.go
+++ b/server/badges/badges_test.go
@@ -28,10 +28,10 @@ import (
var (
badgeNone = ``
- badgeSuccess = ``
- badgeFailure = ``
- badgeError = ``
- badgeStarted = ``
+ badgeSuccess = ``
+ badgeFailure = ``
+ badgeError = ``
+ badgeStarted = ``
)
// Generate an SVG badge based on a pipeline.
@@ -82,7 +82,7 @@ func TestBadgeDrawerRender(t *testing.T) {
mutex: &sync.Mutex{},
}
- output := "XXX,YYY,#c0c0c0,14,26,38,26,52"
+ output := "XXX,YYY,#c0c0c0,15.5,29,41,26,55"
var buf bytes.Buffer
assert.NoError(t, d.Render("XXX", "YYY", "#c0c0c0", &buf))
@@ -105,7 +105,7 @@ func TestBadgeDrawerRenderBytes(t *testing.T) {
mutex: &sync.Mutex{},
}
- output := "XXX,YYY,#c0c0c0,14,26,38,26,52"
+ output := "XXX,YYY,#c0c0c0,15.5,29,41,26,55"
bytes, err := d.RenderBytes("XXX", "YYY", "#c0c0c0")
diff --git a/server/badges/drawer.go b/server/badges/drawer.go
index e4cef5b62a..616a69cfa0 100644
--- a/server/badges/drawer.go
+++ b/server/badges/drawer.go
@@ -11,8 +11,9 @@ import (
"io"
"sync"
- "github.com/golang/freetype/truetype"
"golang.org/x/image/font"
+ "golang.org/x/image/font/opentype"
+ "golang.org/x/image/font/sfnt"
"go.woodpecker-ci.org/woodpecker/v3/server/badges/fonts"
)
@@ -116,15 +117,21 @@ func initDrawer() (*badgeDrawer, error) {
}
func mustNewFontDrawer(size, dpi float64) (*font.Drawer, error) {
- ttf, err := truetype.Parse(fonts.DejaVuSans)
+ f, err := sfnt.Parse(fonts.DejaVuSans)
if err != nil {
return nil, err
}
+
+ face, err := opentype.NewFace(f, &opentype.FaceOptions{
+ Size: size,
+ DPI: dpi,
+ Hinting: font.HintingFull,
+ })
+ if err != nil {
+ return nil, err
+ }
+
return &font.Drawer{
- Face: truetype.NewFace(ttf, &truetype.Options{
- Size: size,
- DPI: dpi,
- Hinting: font.HintingFull,
- }),
+ Face: face,
}, nil
}