mirror of
https://github.com/selfhst/icons.git
synced 2026-04-30 13:26:18 -04:00
v3.2.0 (Primary colors, remote URLs)
This commit is contained in:
13
CHANGELOG.md
13
CHANGELOG.md
@@ -1,3 +1,12 @@
|
|||||||
|
# v3.2.0
|
||||||
|
|
||||||
|
## What's Changed
|
||||||
|
|
||||||
|
* [Feature] Added PRIMARY_COLOR variable to easily apply a single custom color to all icons (see Wiki for additional details)
|
||||||
|
* [Feature] Added REMOTE_URL to allow users to serve icons from their own remote sources (see Wiki for additional details) ([#690](https://github.com/selfhst/icons/issues/690))
|
||||||
|
* Reduced remote icon load time by removing redundant existence checks
|
||||||
|
* Updated Go version to [v1.26](https://go.dev/doc/go1.26)
|
||||||
|
|
||||||
# v3.1.1
|
# v3.1.1
|
||||||
|
|
||||||
## What's Changed
|
## What's Changed
|
||||||
@@ -19,7 +28,7 @@ The legacy custom color URL ```domain.com/icon.svg?color=000000``` is no longer
|
|||||||
|
|
||||||
## What's Changed
|
## What's Changed
|
||||||
|
|
||||||
* Added support for the new AVIF and ICO formats
|
* [Feature] Added support for the new AVIF and ICO formats
|
||||||
* Updated Go version to [v1.25](https://go.dev/doc/go1.25)
|
* Updated Go version to [v1.25](https://go.dev/doc/go1.25)
|
||||||
* Removed unmaintained [gorilla/mux](https://github.com/gorilla/mux) external dependency in favor of [net/http enhancements introduced in Go 1.22](https://go.dev/blog/routing-enhancements)
|
* Removed unmaintained [gorilla/mux](https://github.com/gorilla/mux) external dependency in favor of [net/http enhancements introduced in Go 1.22](https://go.dev/blog/routing-enhancements)
|
||||||
|
|
||||||
@@ -33,7 +42,7 @@ The legacy custom color URL ```domain.com/icon.svg?color=000000``` is no longer
|
|||||||
|
|
||||||
## What's Changed
|
## What's Changed
|
||||||
|
|
||||||
* Added optional volume for custom (non-selfh.st) icons ([#495](https://github.com/selfhst/icons/issues/495))
|
* [Feature] Added optional volume for custom (non-selfh.st) icons ([#495](https://github.com/selfhst/icons/issues/495))
|
||||||
|
|
||||||
# v2.0.0
|
# v2.0.0
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
FROM golang:1.25-alpine AS builder
|
FROM golang:1.26-alpine AS builder
|
||||||
|
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
|
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
3.1.1
|
3.2.0
|
||||||
@@ -1,3 +1,3 @@
|
|||||||
module selfhst-icons
|
module selfhst-icons
|
||||||
|
|
||||||
go 1.25
|
go 1.26
|
||||||
@@ -17,9 +17,10 @@ import (
|
|||||||
type Config struct {
|
type Config struct {
|
||||||
Port string
|
Port string
|
||||||
IconSource string
|
IconSource string
|
||||||
JSDelivrURL string
|
RemoteURL string
|
||||||
LocalPath string
|
LocalPath string
|
||||||
StandardIconFormat string
|
StandardIconFormat string
|
||||||
|
PrimaryColor string
|
||||||
CacheTTL time.Duration
|
CacheTTL time.Duration
|
||||||
CacheSize int
|
CacheSize int
|
||||||
}
|
}
|
||||||
@@ -110,12 +111,20 @@ func loadConfig() *Config {
|
|||||||
standardFormat = "svg"
|
standardFormat = "svg"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
remoteURL := os.Getenv("REMOTE_URL")
|
||||||
|
if remoteURL == "" {
|
||||||
|
remoteURL = "https://cdn.jsdelivr.net/gh/selfhst/icons@main"
|
||||||
|
}
|
||||||
|
|
||||||
|
primaryColor := strings.TrimPrefix(os.Getenv("PRIMARY_COLOR"), "#")
|
||||||
|
|
||||||
return &Config{
|
return &Config{
|
||||||
Port: port,
|
Port: port,
|
||||||
IconSource: iconSource,
|
IconSource: iconSource,
|
||||||
JSDelivrURL: "https://cdn.jsdelivr.net/gh/selfhst/icons@main",
|
RemoteURL: remoteURL,
|
||||||
LocalPath: "/app/icons",
|
LocalPath: "/app/icons",
|
||||||
StandardIconFormat: standardFormat,
|
StandardIconFormat: standardFormat,
|
||||||
|
PrimaryColor: primaryColor,
|
||||||
CacheTTL: time.Hour,
|
CacheTTL: time.Hour,
|
||||||
CacheSize: 500,
|
CacheSize: 500,
|
||||||
}
|
}
|
||||||
@@ -131,14 +140,6 @@ func fileExists(path string) bool {
|
|||||||
return err == nil
|
return err == nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func urlExists(url string) bool {
|
|
||||||
resp, err := http.Head(url)
|
|
||||||
if err != nil {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
defer resp.Body.Close()
|
|
||||||
return resp.StatusCode == http.StatusOK
|
|
||||||
}
|
|
||||||
|
|
||||||
func readLocalFile(path string) (string, error) {
|
func readLocalFile(path string) (string, error) {
|
||||||
data, err := os.ReadFile(path)
|
data, err := os.ReadFile(path)
|
||||||
@@ -225,6 +226,14 @@ func handleIcon(w http.ResponseWriter, r *http.Request) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
primaryFallback := false
|
||||||
|
if colorCode == "primary" {
|
||||||
|
if config.PrimaryColor == "" {
|
||||||
|
primaryFallback = true
|
||||||
|
}
|
||||||
|
colorCode = config.PrimaryColor
|
||||||
|
}
|
||||||
|
|
||||||
if colorCode != "" && !isValidHexColor(colorCode) {
|
if colorCode != "" && !isValidHexColor(colorCode) {
|
||||||
log.Printf("[ERROR] Invalid color code for icon \"%s\": %s", iconName, colorCode)
|
log.Printf("[ERROR] Invalid color code for icon \"%s\": %s", iconName, colorCode)
|
||||||
http.Error(w, "Invalid color code. Use 6-digit hex without #", http.StatusBadRequest)
|
http.Error(w, "Invalid color code. Use 6-digit hex without #", http.StatusBadRequest)
|
||||||
@@ -288,28 +297,31 @@ func handleIcon(w http.ResponseWriter, r *http.Request) {
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if colorCode != "" {
|
if colorCode != "" {
|
||||||
lightURL := config.JSDelivrURL + "/svg/" + iconName + "-light.svg"
|
lightURL := config.RemoteURL + "/svg/" + iconName + "-light.svg"
|
||||||
if urlExists(lightURL) {
|
iconContent, err = fetchRemoteFile(lightURL)
|
||||||
iconContent, err = fetchRemoteFile(lightURL)
|
if err == nil {
|
||||||
if err == nil {
|
iconContent = applySVGColor(iconContent, colorCode)
|
||||||
iconContent = applySVGColor(iconContent, colorCode)
|
} else {
|
||||||
}
|
iconContent = ""
|
||||||
|
err = nil
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
var standardURL string
|
var standardURL string
|
||||||
if formatToServe == "svg" {
|
if formatToServe == "svg" {
|
||||||
standardURL = config.JSDelivrURL + "/svg/" + iconName + ".svg"
|
standardURL = config.RemoteURL + "/svg/" + iconName + ".svg"
|
||||||
} else {
|
} else {
|
||||||
standardURL = config.JSDelivrURL + "/" + formatToServe + "/" + iconName + "." + formatToServe
|
standardURL = config.RemoteURL + "/" + formatToServe + "/" + iconName + "." + formatToServe
|
||||||
}
|
}
|
||||||
|
|
||||||
if urlExists(standardURL) {
|
iconContent, err = fetchRemoteFile(standardURL)
|
||||||
iconContent, err = fetchRemoteFile(standardURL)
|
if err != nil {
|
||||||
|
iconContent = ""
|
||||||
|
err = nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if iconContent == "" {
|
if iconContent == "" {
|
||||||
svgURL := config.JSDelivrURL + "/svg/" + iconName + ".svg"
|
svgURL := config.RemoteURL + "/svg/" + iconName + ".svg"
|
||||||
iconContent, err = fetchRemoteFile(svgURL)
|
iconContent, err = fetchRemoteFile(svgURL)
|
||||||
contentType = "image/svg+xml"
|
contentType = "image/svg+xml"
|
||||||
formatToServe = "svg"
|
formatToServe = "svg"
|
||||||
@@ -326,8 +338,14 @@ func handleIcon(w http.ResponseWriter, r *http.Request) {
|
|||||||
|
|
||||||
cache.Set(cacheKey, iconContent)
|
cache.Set(cacheKey, iconContent)
|
||||||
|
|
||||||
log.Printf("[SUCCESS] Serving icon: \"%s\"%s (%s, source: %s)", iconName,
|
log.Printf("[%s] Serving icon: \"%s\"%s (%s, source: %s)",
|
||||||
func() string { if colorCode != "" { return " with color " + colorCode } else { return "" } }(),
|
func() string { if primaryFallback { return "WARN" } else { return "SUCCESS" } }(),
|
||||||
|
iconName,
|
||||||
|
func() string {
|
||||||
|
if colorCode != "" { return " with color " + colorCode }
|
||||||
|
if primaryFallback { return " (PRIMARY_COLOR not set, using standard format)" }
|
||||||
|
return ""
|
||||||
|
}(),
|
||||||
formatToServe, config.IconSource)
|
formatToServe, config.IconSource)
|
||||||
|
|
||||||
w.Header().Set("Content-Type", contentType)
|
w.Header().Set("Content-Type", contentType)
|
||||||
@@ -412,7 +430,7 @@ func handleRoot(w http.ResponseWriter, r *http.Request) {
|
|||||||
if config.IconSource == "local" {
|
if config.IconSource == "local" {
|
||||||
return config.LocalPath
|
return config.LocalPath
|
||||||
}
|
}
|
||||||
return config.JSDelivrURL
|
return config.RemoteURL
|
||||||
}(),
|
}(),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@@ -444,7 +462,7 @@ func main() {
|
|||||||
if config.IconSource == "local" {
|
if config.IconSource == "local" {
|
||||||
return "Local volume"
|
return "Local volume"
|
||||||
}
|
}
|
||||||
return "Remote CDN"
|
return "Remote: " + config.RemoteURL
|
||||||
}())
|
}())
|
||||||
log.Printf("Cache settings: TTL %ds, Max %d items", int(config.CacheTTL.Seconds()), config.CacheSize)
|
log.Printf("Cache settings: TTL %ds, Max %d items", int(config.CacheTTL.Seconds()), config.CacheSize)
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user