github.com/linchen2chris/hugo@v0.0.0-20230307053224-cec209389705/resources/resource_transformers/tocss/internal/sass/helpers.go (about) 1 // Copyright 2023 The Hugo Authors. All rights reserved. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // http://www.apache.org/licenses/LICENSE-2.0 7 // 8 // Unless required by applicable law or agreed to in writing, software 9 // distributed under the License is distributed on an "AS IS" BASIS, 10 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 // See the License for the specific language governing permissions and 12 // limitations under the License. 13 14 package sass 15 16 import ( 17 "fmt" 18 "regexp" 19 "sort" 20 "strings" 21 22 "github.com/gohugoio/hugo/common/types/css" 23 ) 24 25 const ( 26 HugoVarsNamespace = "hugo:vars" 27 ) 28 29 func CreateVarsStyleSheet(vars map[string]any) string { 30 if vars == nil { 31 return "" 32 } 33 var varsStylesheet string 34 35 var varsSlice []string 36 for k, v := range vars { 37 var prefix string 38 if !strings.HasPrefix(k, "$") { 39 prefix = "$" 40 } 41 42 switch v.(type) { 43 case css.QuotedString: 44 // Marked by the user as a string that needs to be quoted. 45 varsSlice = append(varsSlice, fmt.Sprintf("%s%s: %q;", prefix, k, v)) 46 default: 47 if isTypedCSSValue(v) { 48 // E.g. 24px, 1.5rem, 10%, hsl(0, 0%, 100%), calc(24px + 36px), #fff, #ffffff. 49 varsSlice = append(varsSlice, fmt.Sprintf("%s%s: %v;", prefix, k, v)) 50 } else { 51 // unquote will preserve quotes around URLs etc. if needed. 52 varsSlice = append(varsSlice, fmt.Sprintf("%s%s: unquote(%q);", prefix, k, v)) 53 } 54 } 55 } 56 sort.Strings(varsSlice) 57 varsStylesheet = strings.Join(varsSlice, "\n") 58 return varsStylesheet 59 60 } 61 62 var ( 63 isCSSColor = regexp.MustCompile(`^#[0-9a-fA-F]{3,6}$`) 64 isCSSFunc = regexp.MustCompile(`^([a-zA-Z-]+)\(`) 65 isCSSUnit = regexp.MustCompile(`^([0-9]+)(\.[0-9]+)?([a-zA-Z-%]+)$`) 66 ) 67 68 // isTypedCSSValue returns true if the given string is a CSS value that 69 // we should preserve the type of, as in: Not wrap it in quotes. 70 func isTypedCSSValue(v any) bool { 71 switch s := v.(type) { 72 case int, int8, int16, int32, int64, uint, uint8, uint16, uint32, uint64, float32, float64, css.UnquotedString: 73 return true 74 case string: 75 if isCSSColor.MatchString(s) { 76 return true 77 } 78 if isCSSFunc.MatchString(s) { 79 return true 80 } 81 if isCSSUnit.MatchString(s) { 82 return true 83 } 84 85 } 86 87 return false 88 }