Skip to content

Commit 212c413

Browse files
committed
feat: 移除 CGO 依赖并嵌入静态文件
- 将 go-sqlite3 替换为 modernc.org/sqlite (纯 Go 实现) - 将 gorm.io/driver/sqlite 替换为 github.com/glebarez/sqlite - 使用 go:embed 将 themes 目录嵌入二进制文件 - 支持从嵌入文件系统加载静态资源(优先文件系统,回退嵌入) - 现在可以使用 CGO_ENABLED=0 进行交叉编译 - 二进制文件可独立运行,无需单独分发 themes 目录 🤖 Generated with [Qoder][https://qoder.com]
1 parent abd8a91 commit 212c413

10 files changed

Lines changed: 175 additions & 25 deletions

File tree

embed.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
package main
2+
3+
import "embed"
4+
5+
//go:embed all:themes
6+
var EmbeddedThemes embed.FS

go.mod

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,8 @@ require (
1111
github.com/aws/aws-sdk-go-v2/service/s3 v1.58.3
1212
github.com/gin-contrib/cors v1.6.0
1313
github.com/gin-gonic/gin v1.9.1
14+
github.com/glebarez/sqlite v1.11.0
1415
github.com/golang-jwt/jwt/v4 v4.5.2
15-
github.com/mattn/go-sqlite3 v1.14.32
1616
github.com/robfig/cron/v3 v3.0.1
1717
github.com/sirupsen/logrus v1.9.3
1818
github.com/spf13/cobra v1.9.0
@@ -27,8 +27,8 @@ require (
2727
gopkg.in/yaml.v3 v3.0.1
2828
gorm.io/driver/mysql v1.5.7
2929
gorm.io/driver/postgres v1.4.7
30-
gorm.io/driver/sqlite v1.5.7
3130
gorm.io/gorm v1.25.10
31+
modernc.org/sqlite v1.35.0
3232
)
3333

3434
require (
@@ -51,8 +51,10 @@ require (
5151
github.com/bytedance/sonic v1.11.2 // indirect
5252
github.com/chenzhuoyu/base64x v0.0.0-20230717121745-296ad89f973d // indirect
5353
github.com/chenzhuoyu/iasm v0.9.1 // indirect
54+
github.com/dustin/go-humanize v1.0.1 // indirect
5455
github.com/gabriel-vasile/mimetype v1.4.3 // indirect
5556
github.com/gin-contrib/sse v1.1.0 // indirect
57+
github.com/glebarez/go-sqlite v1.21.2 // indirect
5658
github.com/go-openapi/jsonpointer v0.22.0 // indirect
5759
github.com/go-openapi/jsonreference v0.21.1 // indirect
5860
github.com/go-openapi/spec v0.21.0 // indirect
@@ -73,6 +75,7 @@ require (
7375
github.com/go-playground/validator/v10 v10.19.0 // indirect
7476
github.com/go-sql-driver/mysql v1.8.1 // indirect
7577
github.com/goccy/go-json v0.10.5 // indirect
78+
github.com/google/uuid v1.6.0 // indirect
7679
github.com/inconshreveable/mousetrap v1.1.0 // indirect
7780
github.com/jackc/pgpassfile v1.0.0 // indirect
7881
github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 // indirect
@@ -88,14 +91,20 @@ require (
8891
github.com/mattn/go-isatty v0.0.20 // indirect
8992
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
9093
github.com/modern-go/reflect2 v1.0.2 // indirect
94+
github.com/ncruces/go-strftime v0.1.9 // indirect
9195
github.com/pelletier/go-toml/v2 v2.2.4 // indirect
96+
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect
9297
github.com/spf13/pflag v1.0.6 // indirect
9398
github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
9499
github.com/ugorji/go/codec v1.3.0 // indirect
95100
golang.org/x/arch v0.7.0 // indirect
101+
golang.org/x/exp v0.0.0-20230315142452-642cacee5cc0 // indirect
96102
golang.org/x/net v0.47.0 // indirect
97103
golang.org/x/sync v0.18.0 // indirect
98104
golang.org/x/text v0.31.0 // indirect
99105
golang.org/x/tools v0.38.0 // indirect
100106
google.golang.org/protobuf v1.36.8 // indirect
107+
modernc.org/libc v1.61.13 // indirect
108+
modernc.org/mathutil v1.7.1 // indirect
109+
modernc.org/memory v1.8.2 // indirect
101110
)

go.sum

Lines changed: 40 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,8 @@ github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ3
5959
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
6060
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
6161
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
62+
github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY=
63+
github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto=
6264
github.com/gabriel-vasile/mimetype v1.4.3 h1:in2uUcidCuFcDKtdcBxlR0rJ1+fsokWf+uqxgUFjbI0=
6365
github.com/gabriel-vasile/mimetype v1.4.3/go.mod h1:d8uq/6HKRL6CGdk+aubisF/M5GcPfT7nKyLpA0lbSSk=
6466
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
@@ -72,6 +74,10 @@ github.com/gin-contrib/sse v1.1.0/go.mod h1:hxRZ5gVpWMT7Z0B0gSNYqqsSCNIJMjzvm6fq
7274
github.com/gin-gonic/gin v1.8.1/go.mod h1:ji8BvRH1azfM+SYow9zQ6SZMvR8qOMZHmsCuWR9tTTk=
7375
github.com/gin-gonic/gin v1.9.1 h1:4idEAncQnU5cB7BeOkPtxjfCSye0AAm1R0RVIqJ+Jmg=
7476
github.com/gin-gonic/gin v1.9.1/go.mod h1:hPrL7YrpYKXt5YId3A/Tnip5kqbEAP+KLuI3SUcPTeU=
77+
github.com/glebarez/go-sqlite v1.21.2 h1:3a6LFC4sKahUunAmynQKLZceZCOzUthkRkEAl9gAXWo=
78+
github.com/glebarez/go-sqlite v1.21.2/go.mod h1:sfxdZyhQjTM2Wry3gVYWaW072Ri1WMdWJi0k6+3382k=
79+
github.com/glebarez/sqlite v1.11.0 h1:wSG0irqzP6VurnMEpFGer5Li19RpIRi2qvQz++w0GMw=
80+
github.com/glebarez/sqlite v1.11.0/go.mod h1:h8/o8j5wiAsqSPoWELDUdJXhjAhsVliSn7bWZjOhrgQ=
7581
github.com/go-openapi/jsonpointer v0.19.3/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg=
7682
github.com/go-openapi/jsonpointer v0.19.5/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg=
7783
github.com/go-openapi/jsonpointer v0.22.0 h1:TmMhghgNef9YXxTu1tOopo+0BGEytxA+okbry0HjZsM=
@@ -133,6 +139,10 @@ github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/
133139
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
134140
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
135141
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
142+
github.com/google/pprof v0.0.0-20240409012703-83162a5b38cd h1:gbpYu9NMq8jhDVbvlGkMFWCjLFlqqEZjEmObmhUy6Vo=
143+
github.com/google/pprof v0.0.0-20240409012703-83162a5b38cd/go.mod h1:kf6iHlnVGwgKolg33glAes7Yg/8iWP8ukqeldJSO7jw=
144+
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
145+
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
136146
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
137147
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
138148
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
@@ -182,13 +192,13 @@ github.com/mailru/easyjson v0.9.0/go.mod h1:1+xMtQp2MRNVL/V1bOzuP3aP8VNwRW55fQUt
182192
github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=
183193
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
184194
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
185-
github.com/mattn/go-sqlite3 v1.14.32 h1:JD12Ag3oLy1zQA+BNn74xRgaBbdhbNIDYvQUEuuErjs=
186-
github.com/mattn/go-sqlite3 v1.14.32/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y=
187195
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
188196
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
189197
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
190198
github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
191199
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
200+
github.com/ncruces/go-strftime v0.1.9 h1:bY0MQC28UADQmHmaF5dgpLmImcShSi2kHU9XLdhx/f4=
201+
github.com/ncruces/go-strftime v0.1.9/go.mod h1:Fwc5htZGVVkseilnfgOVb9mKy6w1naJmn9CehxcKcls=
192202
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
193203
github.com/otiai10/copy v1.7.0/go.mod h1:rmRl6QPdJj6EiUqXQ/4Nn2lLXoNQjFCQbbNrxgc/t3U=
194204
github.com/otiai10/curr v0.0.0-20150429015615-9b4961190c95/go.mod h1:9qAhocn7zKJG+0mI8eUu6xqkFDYS2kb2saOteoSB3cE=
@@ -201,6 +211,8 @@ github.com/pelletier/go-toml/v2 v2.2.4/go.mod h1:2gIqNv+qfxSVS7cM2xJQKtLSTLUE9V8
201211
github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA=
202212
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
203213
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
214+
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE=
215+
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
204216
github.com/robfig/cron/v3 v3.0.1 h1:WdRxkvbJztn8LMz/QEvLN5sBU+xKpSqwwUO1Pjr4qDs=
205217
github.com/robfig/cron/v3 v3.0.1/go.mod h1:eQICP3HwyT7UooqI/z+Ov+PtYAWygg1TEWWzGIFLtro=
206218
github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc=
@@ -261,6 +273,8 @@ golang.org/x/crypto v0.0.0-20220829220503-c86fa9a7ed90/go.mod h1:IxCIyHEi3zRg3s0
261273
golang.org/x/crypto v0.4.0/go.mod h1:3quD/ATkf6oY+rnes5c3ExXTbLc8mueNue5/DoinL80=
262274
golang.org/x/crypto v0.45.0 h1:jMBrvKuj23MTlT0bQEOBcAE0mjg8mK9RXFhRH6nyF3Q=
263275
golang.org/x/crypto v0.45.0/go.mod h1:XTGrrkGJve7CYK7J8PEww4aY7gM3qMCElcJQ8n8JdX4=
276+
golang.org/x/exp v0.0.0-20230315142452-642cacee5cc0 h1:pVgRXcIictcr+lBQIFeiwuwtDIs4eL21OuM9nyAADmo=
277+
golang.org/x/exp v0.0.0-20230315142452-642cacee5cc0/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc=
264278
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
265279
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
266280
golang.org/x/mod v0.29.0 h1:HV8lRxZC4l2cr3Zq1LvtOsi/ThTgWnUk/y64QSs8GwA=
@@ -353,11 +367,33 @@ gorm.io/driver/mysql v1.5.7 h1:MndhOPYOfEp2rHKgkZIhJ16eVUIRf2HmzgoPmh7FCWo=
353367
gorm.io/driver/mysql v1.5.7/go.mod h1:sEtPWMiqiN1N1cMXoXmBbd8C6/l+TESwriotuRRpkDM=
354368
gorm.io/driver/postgres v1.4.7 h1:J06jXZCNq7Pdf7LIPn8tZn9LsWjd81BRSKveKNr0ZfA=
355369
gorm.io/driver/postgres v1.4.7/go.mod h1:UJChCNLFKeBqQRE+HrkFUbKbq9idPXmTOk2u4Wok8S4=
356-
gorm.io/driver/sqlite v1.5.7 h1:8NvsrhP0ifM7LX9G4zPB97NwovUakUxc+2V2uuf3Z1I=
357-
gorm.io/driver/sqlite v1.5.7/go.mod h1:U+J8craQU6Fzkcvu8oLeAQmi50TkwPEhHDEjQZXDah4=
358370
gorm.io/gorm v1.24.2/go.mod h1:DVrVomtaYTbqs7gB/x2uVvqnXzv0nqjB396B8cG4dBA=
359371
gorm.io/gorm v1.25.7/go.mod h1:hbnx/Oo0ChWMn1BIhpy1oYozzpM15i4YPuHDmfYtwg8=
360372
gorm.io/gorm v1.25.10 h1:dQpO+33KalOA+aFYGlK+EfxcI5MbO7EP2yYygwh9h+s=
361373
gorm.io/gorm v1.25.10/go.mod h1:hbnx/Oo0ChWMn1BIhpy1oYozzpM15i4YPuHDmfYtwg8=
374+
modernc.org/cc/v4 v4.24.4 h1:TFkx1s6dCkQpd6dKurBNmpo+G8Zl4Sq/ztJ+2+DEsh0=
375+
modernc.org/cc/v4 v4.24.4/go.mod h1:uVtb5OGqUKpoLWhqwNQo/8LwvoiEBLvZXIQ/SmO6mL0=
376+
modernc.org/ccgo/v4 v4.23.16 h1:Z2N+kk38b7SfySC1ZkpGLN2vthNJP1+ZzGZIlH7uBxo=
377+
modernc.org/ccgo/v4 v4.23.16/go.mod h1:nNma8goMTY7aQZQNTyN9AIoJfxav4nvTnvKThAeMDdo=
378+
modernc.org/fileutil v1.3.0 h1:gQ5SIzK3H9kdfai/5x41oQiKValumqNTDXMvKo62HvE=
379+
modernc.org/fileutil v1.3.0/go.mod h1:XatxS8fZi3pS8/hKG2GH/ArUogfxjpEKs3Ku3aK4JyQ=
380+
modernc.org/gc/v2 v2.6.3 h1:aJVhcqAte49LF+mGveZ5KPlsp4tdGdAOT4sipJXADjw=
381+
modernc.org/gc/v2 v2.6.3/go.mod h1:YgIahr1ypgfe7chRuJi2gD7DBQiKSLMPgBQe9oIiito=
382+
modernc.org/libc v1.61.13 h1:3LRd6ZO1ezsFiX1y+bHd1ipyEHIJKvuprv0sLTBwLW8=
383+
modernc.org/libc v1.61.13/go.mod h1:8F/uJWL/3nNil0Lgt1Dpz+GgkApWh04N3el3hxJcA6E=
384+
modernc.org/mathutil v1.7.1 h1:GCZVGXdaN8gTqB1Mf/usp1Y/hSqgI2vAGGP4jZMCxOU=
385+
modernc.org/mathutil v1.7.1/go.mod h1:4p5IwJITfppl0G4sUEDtCr4DthTaT47/N3aT6MhfgJg=
386+
modernc.org/memory v1.8.2 h1:cL9L4bcoAObu4NkxOlKWBWtNHIsnnACGF/TbqQ6sbcI=
387+
modernc.org/memory v1.8.2/go.mod h1:ZbjSvMO5NQ1A2i3bWeDiVMxIorXwdClKE/0SZ+BMotU=
388+
modernc.org/opt v0.1.4 h1:2kNGMRiUjrp4LcaPuLY2PzUfqM/w9N23quVwhKt5Qm8=
389+
modernc.org/opt v0.1.4/go.mod h1:03fq9lsNfvkYSfxrfUhZCWPk1lm4cq4N+Bh//bEtgns=
390+
modernc.org/sortutil v1.2.1 h1:+xyoGf15mM3NMlPDnFqrteY07klSFxLElE2PVuWIJ7w=
391+
modernc.org/sortutil v1.2.1/go.mod h1:7ZI3a3REbai7gzCLcotuw9AC4VZVpYMjDzETGsSMqJE=
392+
modernc.org/sqlite v1.35.0 h1:yQps4fegMnZFdphtzlfQTCNBWtS0CZv48pRpW3RFHRw=
393+
modernc.org/sqlite v1.35.0/go.mod h1:9cr2sicr7jIaWTBKQmAxQLfBv9LL0su4ZTEV+utt3ic=
394+
modernc.org/strutil v1.2.1 h1:UneZBkQA+DX2Rp35KcM69cSsNES9ly8mQWD71HKlOA0=
395+
modernc.org/strutil v1.2.1/go.mod h1:EHkiggD70koQxjVdSBM3JKM7k6L0FbGE5eymy9i3B9A=
396+
modernc.org/token v1.1.0 h1:Xl7Ap9dKaEs5kLoOQeQmPWevfnk/DM5qcLcYlA8ys6Y=
397+
modernc.org/token v1.1.0/go.mod h1:UGzOrNV1mAFSEB63lOFHIpNRUVMvYTc6yu1SMY/XTDM=
362398
nullprogram.com/x/optparse v1.0.0/go.mod h1:KdyPE+Igbe0jQUrVfMqDMeJQIJZEuyV7pjYmp6pbG50=
363399
rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4=

internal/database/database.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import (
1010

1111
"gorm.io/driver/mysql"
1212
"gorm.io/driver/postgres"
13-
"gorm.io/driver/sqlite"
13+
"github.com/glebarez/sqlite"
1414
"gorm.io/gorm"
1515
"gorm.io/gorm/logger"
1616
)

internal/routes/admin.go

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -57,12 +57,7 @@ func SetupAdminRoutes(
5757
return func(c *gin.Context) {
5858
rel := c.Param("filepath")
5959
joined := append(parts, rel)
60-
path, err := static.ResolveThemeFile(cfg, joined...)
61-
if err != nil {
62-
c.Status(404)
63-
return
64-
}
65-
c.File(path)
60+
static.ServeThemeFile(c, cfg, joined...)
6661
}
6762
}
6863

internal/services/admin/admin_test_helpers_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import (
99
"github.com/zy84338719/filecodebox/internal/repository"
1010
admin "github.com/zy84338719/filecodebox/internal/services/admin"
1111
"github.com/zy84338719/filecodebox/internal/storage"
12-
"gorm.io/driver/sqlite"
12+
"github.com/glebarez/sqlite"
1313
"gorm.io/gorm"
1414
)
1515

internal/static/assets.go

Lines changed: 107 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
package static
22

33
import (
4+
"embed"
45
"fmt"
56
"html"
7+
"io/fs"
68
"net/http"
79
"os"
810
"path/filepath"
@@ -14,6 +16,24 @@ import (
1416

1517
const defaultThemeDir = "themes/2025"
1618

19+
// embeddedFS holds the embedded themes filesystem, set via SetEmbeddedFS
20+
var embeddedFS embed.FS
21+
var embeddedFSSet bool
22+
23+
// SetEmbeddedFS sets the embedded filesystem for static assets
24+
func SetEmbeddedFS(efs embed.FS) {
25+
embeddedFS = efs
26+
embeddedFSSet = true
27+
}
28+
29+
// getEmbeddedSubFS returns a sub-filesystem for the themes directory
30+
func getEmbeddedSubFS() (fs.FS, error) {
31+
if !embeddedFSSet {
32+
return nil, fs.ErrNotExist
33+
}
34+
return fs.Sub(embeddedFS, "themes/2025")
35+
}
36+
1737
func themeCandidates(cfg *config.ConfigManager) []string {
1838
var candidates []string
1939
seen := make(map[string]struct{})
@@ -79,18 +99,76 @@ func resolveThemeFilePath(cfg *config.ConfigManager, parts ...string) (string, e
7999
}
80100

81101
func loadThemeFile(cfg *config.ConfigManager, parts ...string) ([]byte, error) {
102+
// First try filesystem
82103
path, err := resolveThemeFilePath(cfg, parts...)
83-
if err != nil {
84-
return nil, err
104+
if err == nil {
105+
return os.ReadFile(path)
85106
}
86-
return os.ReadFile(path)
107+
// Fallback to embedded FS
108+
if embeddedFSSet {
109+
embeddedPath := filepath.Join(parts...)
110+
data, embErr := fs.ReadFile(embeddedFS, "themes/2025/"+embeddedPath)
111+
if embErr == nil {
112+
return data, nil
113+
}
114+
}
115+
return nil, err
87116
}
88117

89118
// ResolveThemeFile returns the concrete filesystem path for a theme file, applying fallbacks.
90119
func ResolveThemeFile(cfg *config.ConfigManager, parts ...string) (string, error) {
91120
return resolveThemeFilePath(cfg, parts...)
92121
}
93122

123+
// ServeThemeFile serves a theme file, falling back to embedded FS if filesystem path not found
124+
func ServeThemeFile(c *gin.Context, cfg *config.ConfigManager, parts ...string) {
125+
// First try filesystem
126+
path, err := resolveThemeFilePath(cfg, parts...)
127+
if err == nil {
128+
c.File(path)
129+
return
130+
}
131+
// Fallback to embedded FS
132+
if embeddedFSSet {
133+
embeddedPath := "themes/2025/" + filepath.Join(parts...)
134+
data, embErr := fs.ReadFile(embeddedFS, embeddedPath)
135+
if embErr == nil {
136+
// Detect content type
137+
contentType := "application/octet-stream"
138+
ext := filepath.Ext(embeddedPath)
139+
switch ext {
140+
case ".html":
141+
contentType = "text/html; charset=utf-8"
142+
case ".css":
143+
contentType = "text/css; charset=utf-8"
144+
case ".js":
145+
contentType = "application/javascript; charset=utf-8"
146+
case ".json":
147+
contentType = "application/json; charset=utf-8"
148+
case ".svg":
149+
contentType = "image/svg+xml"
150+
case ".png":
151+
contentType = "image/png"
152+
case ".jpg", ".jpeg":
153+
contentType = "image/jpeg"
154+
case ".gif":
155+
contentType = "image/gif"
156+
case ".ico":
157+
contentType = "image/x-icon"
158+
case ".woff":
159+
contentType = "font/woff"
160+
case ".woff2":
161+
contentType = "font/woff2"
162+
case ".ttf":
163+
contentType = "font/ttf"
164+
}
165+
c.Data(http.StatusOK, contentType, data)
166+
return
167+
}
168+
}
169+
c.Status(http.StatusNotFound)
170+
}
171+
94172
// ThemePath returns the resolved theme directory joined with optional relative parts.
95173
func ThemePath(cfg *config.ConfigManager, parts ...string) string {
96174
root := firstExistingThemeDir(cfg)
@@ -104,10 +182,32 @@ func ThemePath(cfg *config.ConfigManager, parts ...string) string {
104182
// RegisterStaticRoutes registers public-facing static routes (assets, css, js, components)
105183
func RegisterStaticRoutes(router *gin.Engine, cfg *config.ConfigManager) {
106184
themeDir := firstExistingThemeDir(cfg)
107-
router.Static("/assets", filepath.Join(themeDir, "assets"))
108-
router.Static("/css", filepath.Join(themeDir, "css"))
109-
router.Static("/js", filepath.Join(themeDir, "js"))
110-
router.Static("/components", filepath.Join(themeDir, "components"))
185+
186+
// Check if filesystem theme exists
187+
if themeDirExists(themeDir) {
188+
router.Static("/assets", filepath.Join(themeDir, "assets"))
189+
router.Static("/css", filepath.Join(themeDir, "css"))
190+
router.Static("/js", filepath.Join(themeDir, "js"))
191+
router.Static("/components", filepath.Join(themeDir, "components"))
192+
return
193+
}
194+
195+
// Fallback to embedded FS
196+
if embeddedFSSet {
197+
registerEmbeddedStatic(router, "/assets", "themes/2025/assets")
198+
registerEmbeddedStatic(router, "/css", "themes/2025/css")
199+
registerEmbeddedStatic(router, "/js", "themes/2025/js")
200+
registerEmbeddedStatic(router, "/components", "themes/2025/components")
201+
}
202+
}
203+
204+
// registerEmbeddedStatic registers a static route from embedded FS
205+
func registerEmbeddedStatic(router *gin.Engine, urlPath, fsPath string) {
206+
subFS, err := fs.Sub(embeddedFS, fsPath)
207+
if err != nil {
208+
return
209+
}
210+
router.StaticFS(urlPath, http.FS(subFS))
111211
}
112212

113213
// Note: admin static routes are intentionally not registered here.

main.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ import (
3838
"github.com/zy84338719/filecodebox/internal/repository"
3939
"github.com/zy84338719/filecodebox/internal/routes"
4040
"github.com/zy84338719/filecodebox/internal/services"
41+
"github.com/zy84338719/filecodebox/internal/static"
4142
"github.com/zy84338719/filecodebox/internal/storage"
4243
"github.com/zy84338719/filecodebox/internal/tasks"
4344

@@ -48,6 +49,9 @@ import (
4849
)
4950

5051
func main() {
52+
// 初始化嵌入的静态文件
53+
static.SetEmbeddedFS(EmbeddedThemes)
54+
5155
// 如果有子命令参数,切换到 CLI 模式(使用 Cobra)
5256
if len(os.Args) > 1 {
5357
// delay import of CLI to avoid cycles

scripts/export_config_from_db.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import (
77
"log"
88
"os"
99

10-
_ "github.com/mattn/go-sqlite3"
10+
_ "modernc.org/sqlite"
1111
"gopkg.in/yaml.v3"
1212
)
1313

@@ -20,7 +20,7 @@ func main() {
2020
log.Fatalf("db not found: %v", err)
2121
}
2222

23-
db, err := sql.Open("sqlite3", *dbPath)
23+
db, err := sql.Open("sqlite", *dbPath)
2424
if err != nil {
2525
log.Fatalf("open db: %v", err)
2626
}

0 commit comments

Comments
 (0)