github.com/neohugo/neohugo@v0.123.8/resources/resource_transformers/tocss/internal/sass/helpers.go (about) 1 // Copyright 2024 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/neohugo/neohugo/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 var ( 62 isCSSColor = regexp.MustCompile(`^#[0-9a-fA-F]{3,6}$`) 63 isCSSFunc = regexp.MustCompile(`^([a-zA-Z-]+)\(`) 64 isCSSUnit = regexp.MustCompile(`^([0-9]+)(\.[0-9]+)?([a-zA-Z-%]+)$`) 65 ) 66 67 // isTypedCSSValue returns true if the given string is a CSS value that 68 // we should preserve the type of, as in: Not wrap it in quotes. 69 func isTypedCSSValue(v any) bool { 70 switch s := v.(type) { 71 case int, int8, int16, int32, int64, uint, uint8, uint16, uint32, uint64, float32, float64, css.UnquotedString: 72 return true 73 case string: 74 if isCSSColor.MatchString(s) { 75 return true 76 } 77 if isCSSFunc.MatchString(s) { 78 return true 79 } 80 if isCSSUnit.MatchString(s) { 81 return true 82 } 83 84 } 85 86 return false 87 }