123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181 |
- package gen
- import (
- "regexp"
- "strings"
- )
- type cssRule struct {
- typeOf string
- selector string
- block string
- ruleList cssRuleList
- }
- type cssRuleList []cssRule
- // Prepare the css for parsing
- func clean(css *string) {
- // remove spaces
- re := regexp.MustCompile(`\s+`)
- *css = re.ReplaceAllString(*css, " ")
- // remove newlines
- *css = strings.ReplaceAll(*css, "\n", "")
- // remove comments
- r := regexp.MustCompile(`/\*[\s\S]*?\*/`)
- *css = r.ReplaceAllString(*css, "")
- }
- // Parse the css into a ruleList
- func toRuleList(css string) cssRuleList {
- clean(&css)
- dep := 0
- sel := ""
- blk := ""
- var ruleList cssRuleList
- for i := 0; i < len(css); i++ {
- chr := string(css[i])
- if chr == "{" && dep == 0 {
- dep++
- continue
- }
- if chr == "{" {
- dep++
- }
- if chr == "}" {
- dep--
- }
- if chr == "}" && dep == 0 {
- sel = strings.TrimSpace(sel)
- if strings.Contains(sel, "@media") {
- typeOf := "media"
- mediaRuleList := toRuleList(blk)
- ruleList = append(ruleList, cssRule{typeOf, sel, "", mediaRuleList})
- } else {
- typeOf := "rule"
- ruleList = append(ruleList, cssRule{typeOf, sel, blk, cssRuleList{}})
- }
- sel = ""
- blk = ""
- continue
- }
- if dep == 0 {
- sel = sel + chr
- } else {
- blk = blk + chr
- }
- }
- return ruleList
- }
- // scope the rules by adding a css class to each selector
- func scopeSelectors(ruleList cssRuleList, className string) cssRuleList {
- newRuleList := cssRuleList{}
- for i := 0; i < len(ruleList); i++ {
- rule := &ruleList[i]
- if strings.Contains(rule.selector, ":root") {
- continue
- }
- if strings.Contains(rule.selector, ":global") {
- continue
- }
- if strings.Contains(rule.selector, "@font-face") {
- continue
- }
- if strings.Contains(rule.selector, "@import") {
- continue
- }
- if rule.typeOf == "media" {
- rule.ruleList = scopeSelectors(rule.ruleList, className)
- continue
- }
- //
- if strings.Contains(rule.selector, ":cascade") {
- newRule := cssRule{}
- newRule.selector = "." + className + " " + rule.selector
- //newRule.selector = strings.ReplaceAll(newRule.selector, ":cascade", "")
- newRule.block = rule.block
- newRuleList = append(newRuleList, newRule)
- rule.selector = "." + className + " " + rule.selector
- continue
- }
- rule.selector = strings.ReplaceAll(rule.selector, " ", "."+className+" ")
- rule.selector = rule.selector + "." + className
- }
- ruleList = append(ruleList, newRuleList...)
- return ruleList
- }
- func mergeMediaRules(ruleList cssRuleList) cssRuleList {
- mediaMap := make(map[string]cssRuleList)
- var newRuleList cssRuleList
- for i := 0; i < len(ruleList); i++ {
- rule := ruleList[i]
- if rule.typeOf != "media" {
- newRuleList = append(newRuleList, rule)
- continue
- }
- mediaMap[rule.selector] = append(mediaMap[rule.selector], rule.ruleList...)
- }
- for sel, rList := range mediaMap {
- newRuleList = append(newRuleList, cssRule{"media", sel, "", rList})
- }
- return newRuleList
- }
- // order the appRules correctly, stip the :cascade tag too
- func orderRules(ruleList cssRuleList) cssRuleList {
- var newRuleList cssRuleList
- for i := 0; i < len(ruleList); i++ {
- rule := ruleList[i]
- if rule.typeOf == "media" {
- rule.ruleList = orderRules(rule.ruleList)
- }
- if strings.Contains(rule.selector, ":cascade") {
- rule.selector = strings.ReplaceAll(rule.selector, ":cascade", "")
- newRuleList = append(cssRuleList{rule}, newRuleList...)
- continue
- }
- if strings.Contains(rule.selector, ":global") {
- rule.selector = strings.ReplaceAll(rule.selector, ":global", "")
- newRuleList = append(cssRuleList{rule}, newRuleList...)
- continue
- }
- newRuleList = append(newRuleList, rule)
- }
- return newRuleList
- }
- func rulesToCSSstr(ruleList cssRuleList) string {
- cssStr := ""
- for i := 0; i < len(ruleList); i++ {
- rule := ruleList[i]
- if rule.typeOf == "media" {
- rule.block = rulesToCSSstr(rule.ruleList)
- }
- cssStr += rule.selector + "{" + rule.block + "}"
- }
- return cssStr
- }
|