Something went wrong. Try again.
A privacy-first, self-hosted, fully open source personal knowledge management software, written in typescript and golang. (PERSONAL FORK)
Something went wrong. Try again.
Go
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586// SiYuan - Refactor your thinking// Copyright (c) 2020-present, b3log.org//// This program is free software: you can redistribute it and/or modify// it under the terms of the GNU Affero General Public License as published by// the Free Software Foundation, either version 3 of the License, or// (at your option) any later version.//// This program is distributed in the hope that it will be useful,// but WITHOUT ANY WARRANTY; without even the implied warranty of// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the// GNU Affero General Public License for more details.//// You should have received a copy of the GNU Affero General Public License// along with this program. If not, see <https://www.gnu.org/licenses/>.
package api
import ( "fmt" "math" "net/http" "regexp" "strconv" "strings" "time"
"github.com/gin-gonic/gin" "github.com/siyuan-note/siyuan/kernel/model" "github.com/siyuan-note/siyuan/kernel/util")
type ColorScheme struct { Primary string Secondary string}
var colorSchemes = map[string]ColorScheme{ "red": {"#d13d51", "#ba2c3f"}, "blue": {"#3eb0ea", "#0097e6"}, "yellow": {"#eec468", "#d89b18"}, "green": {"#52E0B8", "#19b37a"}, "purple": {"#a36cda", "#8952d5"}, "pink": {"#f183aa", "#e05b8a"}, "orange": {"#f3865e", "#ef5e2a"}, "grey": {"#576574", "#374a60"},}
func getColorScheme(color string) ColorScheme { // 去除可能的空格 color = strings.TrimSpace(color)
// 检查是否是预定义的颜色 if scheme, ok := colorSchemes[strings.ToLower(color)]; ok { return scheme } // 支持自定义颜色 // 如果颜色值不以#开头,自动添加# if !strings.HasPrefix(color, "#") && len(color) > 0 { color = "#" + color }
// 检查是否是十六进制颜色值 hexColorPattern := `^#?([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$` if matched, _ := regexp.MatchString(hexColorPattern, color); matched { // 确保颜色值有#前缀 if !strings.HasPrefix(color, "#") { color = "#" + color }
// 如果是3位十六进制,转换为6位 if len(color) == 4 { r := string(color[1]) g := string(color[2]) b := string(color[3]) color = "#" + r + r + g + g + b + b }
// 生成次要颜色(将主色调变深) secondary := darkenColor(color, 0.1)
return ColorScheme{ Primary: color, Secondary: secondary, } }
// 如果既不是预定义颜色也不是有效的十六进制值,返回默认颜色 return colorSchemes["red"]}
func darkenColor(hexColor string, factor float64) string { // 去掉#号 hex := hexColor[1:]
// 将十六进制转换为RGB r, _ := strconv.ParseInt(hex[0:2], 16, 64) g, _ := strconv.ParseInt(hex[2:4], 16, 64) b, _ := strconv.ParseInt(hex[4:6], 16, 64)
// 使颜色变深 r = int64(float64(r) * (1 - factor)) g = int64(float64(g) * (1 - factor)) b = int64(float64(b) * (1 - factor))
// 确保值在0-255范围内 r = int64(math.Max(0, float64(r))) g = int64(math.Max(0, float64(g))) b = int64(math.Max(0, float64(b)))
// 转回十六进制 return fmt.Sprintf("#%02X%02X%02X", r, g, b)}
func getDynamicIcon(c *gin.Context) { // Add internal kernel API `/api/icon/getDynamicIcon` https://github.com/siyuan-note/siyuan/pull/12939
iconType := c.Query("type") if "" == iconType { iconType = "1" } color := c.Query("color") // 不要预设默认值,不然type6返回星期就没法自动设置周末颜色了 date := c.Query("date") lang := c.Query("lang") if "" == lang { lang = util.Lang } weekdayType := c.Query("weekdayType") // 设置星期几的格式,zh_CH {1:周日,2:周天, 3:星期日,4:星期天,}, en_US {1: Mon, 2: MON,3: Monday, 4. MONDAY,} if "" == weekdayType { weekdayType = "1" }
dateInfo := getDateInfo(date, lang, weekdayType) var svg string switch iconType { case "1": // Type 1: 显示年月日星期 svg = generateTypeOneSVG(color, lang, dateInfo) case "2": // Type 2: 显示年月日 svg = generateTypeTwoSVG(color, lang, dateInfo) case "3": // Type 3: 显示年月 svg = generateTypeThreeSVG(color, lang, dateInfo) case "4": // Type 4: 仅显示年 svg = generateTypeFourSVG(color, lang, dateInfo) case "5": // Type 5: 显示周数 svg = generateTypeFiveSVG(color, lang, dateInfo) case "6": // Type 6: 仅显示星期 svg = generateTypeSixSVG(color, lang, weekdayType, dateInfo) case "7": // Type 7: 倒数日 svg = generateTypeSevenSVG(color, lang, dateInfo) case "8": // Type 8: 文字图标 content := c.Query("content") id := c.Query("id") svg = generateTypeEightSVG(color, content, id) default: // 默认为Type 1 svg = generateTypeOneSVG(color, lang, dateInfo) }
if !model.Conf.Editor.AllowSVGScript { svg = util.SanitizeSVG(svg) }
c.Header("Content-Type", "image/svg+xml") c.Header("Cache-Control", "no-cache") c.Header("Pragma", "no-cache") c.String(http.StatusOK, svg)}
func getDateInfo(dateStr string, lang string, weekdayType string) map[string]interface{} { // 设置默认值 var date time.Time var err error if dateStr == "" { date = time.Now() } else { date, err = time.Parse("2006-01-02", dateStr) if err != nil { date = time.Now() } } // 获取年月日星期 year := date.Year() month := date.Format("Jan") day := date.Day() var weekdayStr string var weekdays []string
switch lang { case "zh_CN": month = date.Format("1月") switch weekdayType { case "1": weekdays = []string{"周日", "周一", "周二", "周三", "周四", "周五", "周六"} case "2": weekdays = []string{"周天", "周一", "周二", "周三", "周四", "周五", "周六"} case "3": weekdays = []string{"星期日", "星期一", "星期二", "星期三", "星期四", "星期五", "星期六"} case "4": weekdays = []string{"星期天", "星期一", "星期二", "星期三", "星期四", "星期五", "星期六"} default: weekdays = []string{"周日", "周一", "周二", "周三", "周四", "周五", "周六"} } weekdayStr = weekdays[date.Weekday()] case "zh_CHT": month = date.Format("1月") switch weekdayType { case "1": weekdays = []string{"週日", "週一", "週二", "週三", "週四", "週五", "週六"} case "2": weekdays = []string{"週天", "週一", "週二", "週三", "週四", "週五", "週六"} case "3": weekdays = []string{"星期日", "星期一", "星期二", "星期三", "星期四", "星期五", "星期六"} case "4": weekdays = []string{"星期天", "星期一", "星期二", "星期三", "星期四", "星期五", "星期六"} default: weekdays = []string{"週日", "週一", "週二", "週三", "週四", "週五", "週六"} } weekdayStr = weekdays[date.Weekday()]
default: // 其他语言 switch weekdayType { case "1": weekdayStr = date.Format("Mon") case "2": weekdayStr = date.Format("Mon") weekdayStr = strings.ToUpper(weekdayStr) case "3": weekdayStr = date.Format("Monday") case "4": weekdayStr = date.Format("Monday") weekdayStr = strings.ToUpper(weekdayStr) default: weekdayStr = date.Format("Mon") } } // Calculate week number and ISO year isoYear, weekNum := date.ISOWeek() weekNumStr := fmt.Sprintf("%dW", weekNum)
switch lang { case "zh_CN": weekNumStr = fmt.Sprintf("%d周", weekNum) case "zh_CHT": weekNumStr = fmt.Sprintf("%d週", weekNum) } // 判断是否是周末 isWeekend := date.Weekday() == time.Saturday || date.Weekday() == time.Sunday // Calculate days until today today := time.Now() today = time.Date(today.Year(), today.Month(), today.Day(), 0, 0, 0, 0, today.Location()) date = time.Date(date.Year(), date.Month(), date.Day(), 0, 0, 0, 0, date.Location()) // countDown := int(math.Floor(date.Sub(today).Hours() / 24)) // 注意最大返回106751天,go的时间戳最大值 countDown := daysBetween(today, date)
return map[string]interface{}{ "year": year, "isoYear": isoYear, "month": month, "day": day, "date": fmt.Sprintf("%02d-%02d", date.Month(), date.Day()), "weekday": weekdayStr, "week": weekNumStr, "countDown": countDown, "isWeekend": isWeekend, }}
func daysBetween(date1, date2 time.Time) int { // 将两个日期都调整到UTC时间的0点 date1 = time.Date(date1.Year(), date1.Month(), date1.Day(), 0, 0, 0, 0, time.UTC) date2 = time.Date(date2.Year(), date2.Month(), date2.Day(), 0, 0, 0, 0, time.UTC)
// 确保date1不晚于date2 swap := false if date1.After(date2) { date1, date2 = date2, date1 swap = true }
// 计算天数差 days := 0 for y := date1.Year(); y < date2.Year(); y++ { if isLeapYear(y) { days += 366 } else { days += 365 } }
// 加上最后一年的天数 days += int(date2.YearDay() - date1.YearDay())
// 如果原始的date1晚于date2,返回负值 if swap { return -days } return days}
// 判断是否为闰年func isLeapYear(year int) bool { return year%4 == 0 && (year%100 != 0 || year%400 == 0)}
// Type 1: 显示年月日星期func generateTypeOneSVG(color string, lang string, dateInfo map[string]interface{}) string { colorScheme := getColorScheme(color)
return fmt.Sprintf(` <svg id="dynamic_icon_type1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"> <path d="M512,447.5c0,32-25,57-57,57H57c-32,0-57-25-57-57V120.5c0-31,25-57,57-57h398c32,0,57,26,57,57v327Z" style="fill: #ecf2f7;"/> <path d="M39,0h434c21.52,0,39,17.48,39,39v146H0V39C0,17.48,17.48,0,39,0Z" style="fill: %s;"/> <text transform="translate(22 146.5)" style="fill: #fff; font-family: -apple-system, BlinkMacSystemFont, 'Noto Sans', 'Noto Sans CJK SC', 'Microsoft YaHei'; font-size: 100px;">%s</text> <text x="50%%" y="392.5" style="fill: #66757f; font-family: -apple-system, BlinkMacSystemFont, 'Noto Sans', 'Noto Sans CJK SC', 'Microsoft YaHei'; font-size: 240px; text-anchor: middle">%d</text> <text x="50%%" y="472.5" style="fill: #66757f; font-family: -apple-system, BlinkMacSystemFont, 'Noto Sans', 'Noto Sans CJK SC', 'Microsoft YaHei'; font-size: 64px; text-anchor: middle">%s</text> <text transform="translate(331.03 148.44)" style="fill: #fff; font-family: -apple-system, BlinkMacSystemFont, 'Noto Sans', 'Noto Sans CJK SC', 'Microsoft YaHei'; font-size: 71.18px;">%d</text> </svg> `, colorScheme.Primary, dateInfo["month"], dateInfo["day"], dateInfo["weekday"], dateInfo["year"])}
// Type 2: 显示年月日func generateTypeTwoSVG(color string, lang string, dateInfo map[string]interface{}) string { colorScheme := getColorScheme(color)
return fmt.Sprintf(` <svg id="dynamic_icon_type2" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"> <path d="M512,447.5c0,32-25,57-57,57H57c-32,0-57-25-57-57V120.5c0-31,25-57,57-57h398c32,0,57,26,57,57v327Z" style="fill: #ecf2f7;"/> <path d="M39,0h434c21.52,0,39,17.48,39,39v146H0V39C0,17.48,17.48,0,39,0Z" style="fill: %s;"/> <text transform="translate(22 146.5)" style="fill: #fff; font-family: -apple-system, BlinkMacSystemFont, 'Noto Sans', 'Noto Sans CJK SC', 'Microsoft YaHei'; font-size: 100px;">%s</text> <text x="50%%" y="420.5" style="fill: #66757f; font-family: -apple-system, BlinkMacSystemFont, 'Noto Sans', 'Noto Sans CJK SC', 'Microsoft YaHei'; font-size: 256px;text-anchor: middle">%d</text> <text transform="translate(331.03 148.44)" style="fill: #fff; font-family: -apple-system, BlinkMacSystemFont, 'Noto Sans', 'Noto Sans CJK SC', 'Microsoft YaHei'; font-size: 71.18px;">%d</text> </svg> `, colorScheme.Primary, dateInfo["month"], dateInfo["day"], dateInfo["year"])}
// Type 3: 显示年月func generateTypeThreeSVG(color string, lang string, dateInfo map[string]interface{}) string { colorScheme := getColorScheme(color)
return fmt.Sprintf(` <svg id="dynamic_icon_type3" xmlns="http://www.w3.org/2000/svg" version="1.1" viewBox="0 0 512 512"> <path class="cls-6" d="M512,447.5c0,32-25,57-57,57H57c-32,0-57-25-57-57V120.5c0-31,25-57,57-57h398c32,0,57,26,57,57v327Z" style="fill: #ecf2f7;"/> <path class="cls-1" d="M39,0h434c21.5,0,39,17.5,39,39v146H0V39C0,17.5,17.5,0,39,0Z" style="fill: %s;"/> <g style="fill: %s;"> <circle cx="468.5" cy="135" r="14"/> <circle cx="468.5" cy="93" r="14"/> <circle cx="425.5" cy="135" r="14"/> <circle cx="425.5" cy="93" r="14"/> <circle cx="382.5" cy="135" r="14"/> <circle cx="382.5" cy="93" r="14"/> </g> <text transform="translate(22 146.5)" style="fill: #fff;font-size: 120px; font-family: -apple-system, BlinkMacSystemFont, 'Noto Sans', 'Noto Sans CJK SC', 'Microsoft YaHei'; ">%d</text> <text x="50%%" y="410.5" style="fill: #66757f;font-size: 200px;text-anchor: middle;font-family: -apple-system, BlinkMacSystemFont, 'Noto Sans', 'Noto Sans CJK SC', 'Microsoft YaHei'; ">%s</text> </svg> `, colorScheme.Primary, colorScheme.Secondary, dateInfo["year"], dateInfo["month"])}
// Type 4: 仅显示年func generateTypeFourSVG(color string, lang string, dateInfo map[string]interface{}) string { colorScheme := getColorScheme(color)
return fmt.Sprintf(` <svg id="dynamic_icon_type4" xmlns="http://www.w3.org/2000/svg" version="1.1" viewBox="0 0 512 512"> <path class="cls-6" d="M512,447.5c0,32-25,57-57,57H57c-32,0-57-25-57-57V120.5c0-31,25-57,57-57h398c32,0,57,26,57,57v327Z" style="fill: #ecf2f7;"/> <path class="cls-1" d="M39,0h434c21.5,0,39,17.5,39,39v146H0V39C0,17.5,17.5,0,39,0Z" style="fill: %s;"/> <g style="fill: %s;"> <circle cx="468.5" cy="135" r="14"/> <circle cx="468.5" cy="93" r="14"/> <circle cx="425.5" cy="135" r="14"/> <circle cx="425.5" cy="93" r="14"/> <circle cx="382.5" cy="135" r="14"/> <circle cx="382.5" cy="93" r="14"/> </g> <text x="50%%" y="410.5" style="fill: #66757f;font-size: 200px;text-anchor: middle;font-family: -apple-system, BlinkMacSystemFont, 'Noto Sans', 'Noto Sans CJK SC', 'Microsoft YaHei'; ">%d</text> </svg> `, colorScheme.Primary, colorScheme.Secondary, dateInfo["year"])}
// Type 5:: 显示周数func generateTypeFiveSVG(color string, lang string, dateInfo map[string]interface{}) string { colorScheme := getColorScheme(color)
return fmt.Sprintf(` <svg id="dynamic_icon_type5" xmlns="http://www.w3.org/2000/svg" version="1.1" viewBox="0 0 512 512"> <path class="cls-6" d="M512,447.5c0,32-25,57-57,57H57c-32,0-57-25-57-57V120.5c0-31,25-57,57-57h398c32,0,57,26,57,57v327Z" style="fill: #ecf2f7;"/> <path class="cls-1" d="M39,0h434c21.5,0,39,17.5,39,39v146H0V39C0,17.5,17.5,0,39,0Z" style="fill: %s;"/> <g style="fill: %s;"> <circle cx="468.5" cy="135" r="14"/> <circle cx="468.5" cy="93" r="14"/> <circle cx="425.5" cy="135" r="14"/> <circle cx="425.5" cy="93" r="14"/> <circle cx="382.5" cy="135" r="14"/> <circle cx="382.5" cy="93" r="14"/> </g> <text transform="translate(22 146.5)" style="fill: #fff;font-size: 120px; font-family: -apple-system, BlinkMacSystemFont, 'Noto Sans', 'Noto Sans CJK SC', 'Microsoft YaHei'; ">%d</text> <text x="50%%" y="410.5" style="fill: #66757f;font-size: 200px;text-anchor: middle;font-family: -apple-system, BlinkMacSystemFont, 'Noto Sans', 'Noto Sans CJK SC', 'Microsoft YaHei'; ">%s</text> </svg> `, colorScheme.Primary, colorScheme.Secondary, dateInfo["isoYear"], dateInfo["week"])}
// Type 6: 仅显示星期func generateTypeSixSVG(color string, lang string, weekdayType string, dateInfo map[string]interface{}) string {
weekday := dateInfo["weekday"].(string) isWeekend := dateInfo["isWeekend"].(bool)
// 如果不设置颜色,周末默认使用蓝色,工作日默认使用红色 var colorScheme ColorScheme if color == "" { if isWeekend { colorScheme = colorSchemes["blue"] } else { colorScheme = colorSchemes["red"] } } else { colorScheme = getColorScheme(color) } // 动态变化字体大小 var fontSize float64 switch lang { case "zh_CN", "zh_CHT": fontSize = 460 / float64(len([]rune(weekday))) default: switch weekdayType { case "1": fontSize = 690 / float64(len([]rune(weekday))) case "2": fontSize = 600 / float64(len([]rune(weekday))) case "3": fontSize = 720 / float64(len([]rune(weekday))) case "4": fontSize = 630 / float64(len([]rune(weekday))) default: fontSize = 750 / float64(len([]rune(weekday))) } }
return fmt.Sprintf(` <svg id="dynamic_icon_type6" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"> <path id="center" d="M512,447.5c0,32-25,57-57,57H57c-32,0-57-25-57-57V120.5c0-31,25-57,57-57h398c32,0,57,26,57,57v327Z" style="fill: #ecf2f7;"/> <path id="top" d="M39,0h434c21.5,0,39,14,39,31.2v116.8H0V31.2C0,14,17.5,0,39,0Z" style="fill: %s;"/> <g id="cirle" style="fill: %s;"> <circle cx="468.5" cy="113.5" r="14"/> <circle cx="468.5" cy="71.5" r="14"/> <circle cx="425.5" cy="113.5" r="14"/> <circle cx="425.5" cy="71.5" r="14"/> <circle cx="382.5" cy="113.5" r="14"/> <circle cx="382.5" cy="71.5" r="14"/> </g> <text id="weekday" x="50%%" y="65%%" style="fill: %s; font-size: %.2fpx; text-anchor: middle; dominant-baseline:middle; font-family: -apple-system, BlinkMacSystemFont, 'Noto Sans', 'Noto Sans CJK SC', 'Microsoft YaHei';">%s</text> </svg>`, colorScheme.Primary, colorScheme.Secondary, colorScheme.Primary, fontSize, weekday)}
// Type7: 倒数日func generateTypeSevenSVG(color string, lang string, dateInfo map[string]interface{}) string { colorScheme := getColorScheme(color)
diffDays := dateInfo["countDown"].(int)
var tipText, diffDaysText string
// 设置输出字符 switch { case diffDays == 0: switch lang { case "zh_CN", "zh_CHT": tipText = "今天" default: tipText = "Today" } diffDaysText = "--" case diffDays > 0: switch lang { case "zh_CN": tipText = "还有" case "zh_CHT": tipText = "還有" default: tipText = "Left" } diffDaysText = fmt.Sprintf("%d", diffDays) default: switch lang { case "zh_CN": tipText = "已过" case "zh_CHT": tipText = "已過" default: tipText = "Past" } absDiffDays := -diffDays diffDaysText = fmt.Sprintf("%d", absDiffDays) }
var dayStr string switch lang { case "zh_CN", "zh_CHT": dayStr = "天" default: dayStr = "days" } // 动态变化字体大小 var fontSize float64 switch { case len(diffDaysText) <= 3: fontSize = 240 case len(diffDaysText) == 4: fontSize = 190 case len(diffDaysText) == 5: fontSize = 140 case len(diffDaysText) >= 6: fontSize = 780 / float64(len(diffDaysText)) }
return fmt.Sprintf(` <svg id="dynamic_icon_type7" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"> <path id="bottom" d="M512,447.5c0,32-25,57-57,57H57c-32,0-57-25-57-57V120.5c0-31,25-57,57-57h398c32,0,57,26,57,57v327Z" style="fill: #ecf2f7;"/> <path id="top" d="M39,0h434c21.52,0,39,17.48,39,39v146H0V39C0,17.48,17.48,0,39,0Z" style="fill: %s;"/> <text id="year" transform="translate(46.1 78.92)" style="fill: #fff; font-family: -apple-system, BlinkMacSystemFont, 'Noto Sans', 'Noto Sans CJK SC', 'Microsoft YaHei'; font-size: 60px;">%d</text> <text id="day" transform="translate(43.58 148.44)" style="fill: #fff; font-family: -apple-system, BlinkMacSystemFont, 'Noto Sans', 'Noto Sans CJK SC', 'Microsoft YaHei'; font-size: 60px;">%s</text> <text id="passStr" transform="translate(400 148.44)" style="fill: #fff; text-anchor: middle;font-family: -apple-system, BlinkMacSystemFont, 'Noto Sans', 'Noto Sans CJK SC', 'Microsoft YaHei'; font-size: 71.18px;">%s</text> <text id="diffDays" x="50%%" y="65%%" style="font-size: %.0fpx; fill: #66757f; text-anchor: middle; dominant-baseline:middle;font-family: -apple-system, BlinkMacSystemFont, 'Noto Sans', 'Noto Sans CJK SC', 'Microsoft YaHei'; ">%s</text> <text id="dayStr" x="50%%" y="472.5" style="font-size: 64px; text-anchor: middle; fill: #66757f; font-family: -apple-system, BlinkMacSystemFont, 'Noto Sans', 'Noto Sans CJK SC', 'Microsoft YaHei';">%s</text> </svg>`, colorScheme.Primary, dateInfo["year"], dateInfo["date"], tipText, fontSize, diffDaysText, dayStr)}
// Type 8: 文字图标func generateTypeEightSVG(color, content, id string) string { if strings.Contains(content, ".action{") { content = model.RenderDynamicIconContentTemplate(content, id) }
colorScheme := getColorScheme(color)
// 动态变化字体大小 isChinese := regexp.MustCompile(`[\p{Han}]`).MatchString(content) var fontSize float64 if isChinese { switch { case len([]rune(content)) == 1: fontSize = 320 default: fontSize = 480 / float64(len([]rune(content))) } } else { switch { case len([]rune(content)) == 1: fontSize = 480 case len([]rune(content)) == 2: fontSize = 300 case len([]rune(content)) == 3: fontSize = 240 default: fontSize = 750 / float64(len([]rune(content))) } } // 当内容为单个字符时,一些小写字母需要调整文字位置(暂时没法批量解决) dy := "0%" if len([]rune(content)) == 1 { switch content { case "g", "p", "y", "q": dy = "-10%" case "j": dy = "-5%" default: dy = "0%" } }
return fmt.Sprintf(` <svg id="dynamic_icon_type8" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"> <path d="M39,0h434c20.97,0,38,17.03,38,38v412c0,33.11-26.89,60-60,60H60c-32.56,0-59-26.44-59-59V38C1,17.03,18.03,0,39,0Z" style="fill: %s;"/> <text x="50%%" y="55%%" dy="%s" style="font-size: %.2fpx; fill: #fff; text-anchor: middle; dominant-baseline:middle;font-family: -apple-system, BlinkMacSystemFont, 'Noto Sans', 'Noto Sans CJK SC', 'Microsoft YaHei'; ">%s</text> </svg> `, colorScheme.Primary, dy, fontSize, content)}