🎉 Initial commit

This commit is contained in:
2025-03-19 21:10:19 +08:00
commit 86c8755f79
70 changed files with 6915 additions and 0 deletions

142
cache/compress.go vendored Normal file
View File

@@ -0,0 +1,142 @@
package cache
import (
"bytes"
"compress/gzip"
"io"
"strings"
)
// CompressOptions 压缩选项
type CompressOptions struct {
Enabled bool // 是否启用压缩
Level int // 压缩级别 (1-9)1为最快压缩9为最佳压缩
MinSizeBytes int // 最小压缩大小,小于此大小的数据不进行压缩
Ratio float64 // 压缩比阈值,压缩后大小/原始大小,小于此值才保存压缩结果
}
// DefaultCompressOptions 默认压缩选项
var DefaultCompressOptions = CompressOptions{
Enabled: true,
Level: 6, // 默认压缩级别为6平衡压缩率和性能
MinSizeBytes: 100, // 默认最小压缩大小为100字节
Ratio: 0.9, // 默认压缩比阈值为0.9即至少要压缩到原始大小的90%以下才保存压缩结果
}
// CompressSVG 压缩SVG数据
// 返回压缩后的数据和是否进行了压缩
func CompressSVG(svg string, options CompressOptions) ([]byte, bool) {
if !options.Enabled || len(svg) < options.MinSizeBytes {
return []byte(svg), false
}
// 创建一个bytes.Buffer来存储压缩数据
var buf bytes.Buffer
// 创建一个gzip.Writer设置压缩级别
writer, err := gzip.NewWriterLevel(&buf, options.Level)
if err != nil {
return []byte(svg), false
}
// 写入SVG数据
_, err = writer.Write([]byte(svg))
if err != nil {
return []byte(svg), false
}
// 关闭writer确保所有数据都被写入
err = writer.Close()
if err != nil {
return []byte(svg), false
}
// 获取压缩后的数据
compressed := buf.Bytes()
// 计算压缩比
ratio := float64(len(compressed)) / float64(len(svg))
// 如果压缩比不理想,返回原始数据
if ratio >= options.Ratio {
return []byte(svg), false
}
return compressed, true
}
// DecompressSVG 解压缩SVG数据
func DecompressSVG(data []byte, isCompressed bool) (string, error) {
// 如果数据未压缩,直接返回字符串
if !isCompressed {
return string(data), nil
}
// 检查数据是否为gzip格式
if !isGzipped(data) {
return string(data), nil
}
// 创建一个gzip.Reader
reader, err := gzip.NewReader(bytes.NewReader(data))
if err != nil {
return string(data), err
}
defer reader.Close()
// 读取解压缩后的数据
decompressed, err := io.ReadAll(reader)
if err != nil {
return string(data), err
}
return string(decompressed), nil
}
// isGzipped 检查数据是否为gzip格式
func isGzipped(data []byte) bool {
// gzip文件的魔数是0x1f 0x8b
return len(data) > 2 && data[0] == 0x1f && data[1] == 0x8b
}
// OptimizeSVG 优化SVG字符串移除不必要的空白和注释
func OptimizeSVG(svg string) string {
// 移除XML注释
svg = removeXMLComments(svg)
// 移除多余的空白
svg = removeExtraWhitespace(svg)
return svg
}
// removeXMLComments 移除XML注释
func removeXMLComments(svg string) string {
for {
start := strings.Index(svg, "<!--")
if start == -1 {
break
}
end := strings.Index(svg[start:], "-->") + start
if end > start {
svg = svg[:start] + svg[end+3:]
} else {
break
}
}
return svg
}
// removeExtraWhitespace 移除多余的空白
func removeExtraWhitespace(svg string) string {
// 替换多个空白字符为单个空格
svg = strings.Join(strings.Fields(svg), " ")
// 优化常见的SVG标签周围的空白
svg = strings.ReplaceAll(svg, "> <", "><")
svg = strings.ReplaceAll(svg, " />", "/>")
svg = strings.ReplaceAll(svg, " =", "=")
svg = strings.ReplaceAll(svg, "= ", "=")
return svg
}