KillWxapkg/utils/transformCSS.go
2024-07-25 13:39:39 +08:00

169 lines
3.7 KiB
Go

package utils
import (
"bytes"
"fmt"
"strings"
"github.com/gorilla/css/scanner"
)
// 定义需要移除的供应商前缀
var removeTypes = []string{"webkit", "moz", "ms", "o"}
// Declaration 结构体用于存储 CSS 声明
type Declaration struct {
Property string
Value string
}
// TransformCSS 函数用于转换 CSS
func TransformCSS(style string) string {
s := scanner.New(style)
var sb strings.Builder
var currentSelector string
var currentDeclarations []Declaration
for {
token := s.Next()
if token.Type == scanner.TokenEOF {
if currentSelector != "" {
writeRuleset(&sb, currentSelector, currentDeclarations)
}
break
}
switch token.Type {
case scanner.TokenS:
// 忽略空白
continue
case scanner.TokenComment:
sb.WriteString(fmt.Sprintf("\n%s\n", token.Value))
case scanner.TokenIdent:
// 处理选择器或属性名
if currentSelector == "" {
// 选择器
currentSelector = strings.TrimSpace(token.Value)
if strings.HasPrefix(currentSelector, "wx-") {
currentSelector = currentSelector[3:]
} else if currentSelector == "body" {
currentSelector = "page"
}
} else {
// 属性名
currentDeclarations = append(currentDeclarations, readDeclaration(s, token.Value))
}
case scanner.TokenChar:
if token.Value == "{" {
// 忽略大括号
continue
} else if token.Value == "}" {
// 遇到右大括号,写入规则集
writeRuleset(&sb, currentSelector, currentDeclarations)
currentSelector = ""
currentDeclarations = nil
}
default:
panic("unhandled default case")
}
}
return beautifyCSS(sb.String())
}
// readDeclaration 函数读取一个声明
func readDeclaration(s *scanner.Scanner, property string) Declaration {
var value bytes.Buffer
foundColon := false
// 1: 遇到冒号,跳过冒号
// 2: 遇到冒号,不跳过冒号
count := 1
for {
token := s.Next()
if token.Type == scanner.TokenEOF || token.Value == "}" || token.Value == ";" {
break
}
if token.Value == ":" && count == 1 {
foundColon = true
count++
continue
}
if foundColon {
value.WriteString(token.Value)
}
}
prop := strings.TrimSpace(property)
val := strings.TrimSpace(value.String())
if shouldRemoveProperty(prop, val) {
return Declaration{}
}
return Declaration{
Property: prop,
Value: val,
}
}
// shouldRemoveProperty 函数判断是否应移除属性
func shouldRemoveProperty(prop, value string) bool {
// 移除包含 progid:DXImageTransform 的值
if strings.HasPrefix(value, "progid:DXImageTransform") {
return true
}
// 移除指定前缀的属性
for _, prefix := range removeTypes {
if strings.HasPrefix(prop, "-"+prefix+"-") {
return true
}
if strings.HasPrefix(value, "-"+prefix+"-") {
return true
}
}
return false
}
// writeRuleset 函数用于写入处理后的规则集
func writeRuleset(sb *strings.Builder, selector string, declarations []Declaration) {
sb.WriteString(selector + " {\n")
for _, decl := range declarations {
// 过滤空的声明
if decl.Property != "" && decl.Value != "" {
sb.WriteString(fmt.Sprintf(" %s: %s;\n", decl.Property, decl.Value))
}
}
sb.WriteString("}\n\n")
}
// beautifyCSS 函数用于美化 CSS
func beautifyCSS(css string) string {
var beautified strings.Builder
indent := 0
lines := strings.Split(css, "\n")
for _, line := range lines {
trimmedLine := strings.TrimSpace(line)
if trimmedLine == "" {
continue
}
if strings.HasPrefix(trimmedLine, "}") {
indent--
}
beautified.WriteString(strings.Repeat(" ", indent))
beautified.WriteString(trimmedLine)
beautified.WriteString("\n")
if strings.HasSuffix(trimmedLine, "{") {
indent++
}
}
return beautified.String()
}