169 lines
3.7 KiB
Go
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()
|
|
}
|