From 889308dd854b0907069d7bc6dd44ed760bc6e819 Mon Sep 17 00:00:00 2001 From: Joe Mooring Date: Fri, 18 Oct 2024 16:10:46 -0700 Subject: resources: Address Dart Sass deprecation of global built-in functions See https://github.com/sass/dart-sass/releases/tag/1.80.0 Fixes #12961 --- .../tocss/dartsass/transform.go | 4 +- .../tocss/internal/sass/helpers.go | 87 ------------------ .../tocss/internal/sass/helpers_test.go | 43 --------- .../resource_transformers/tocss/sass/helpers.go | 102 +++++++++++++++++++++ .../tocss/sass/helpers_test.go | 43 +++++++++ .../resource_transformers/tocss/scss/tocss.go | 4 +- 6 files changed, 149 insertions(+), 134 deletions(-) delete mode 100644 resources/resource_transformers/tocss/internal/sass/helpers.go delete mode 100644 resources/resource_transformers/tocss/internal/sass/helpers_test.go create mode 100644 resources/resource_transformers/tocss/sass/helpers.go create mode 100644 resources/resource_transformers/tocss/sass/helpers_test.go (limited to 'resources') diff --git a/resources/resource_transformers/tocss/dartsass/transform.go b/resources/resource_transformers/tocss/dartsass/transform.go index f0bd6634a..d8b6ae5b4 100644 --- a/resources/resource_transformers/tocss/dartsass/transform.go +++ b/resources/resource_transformers/tocss/dartsass/transform.go @@ -29,7 +29,7 @@ import ( "github.com/gohugoio/hugo/resources" "github.com/gohugoio/hugo/resources/internal" - "github.com/gohugoio/hugo/resources/resource_transformers/tocss/internal/sass" + "github.com/gohugoio/hugo/resources/resource_transformers/tocss/sass" "github.com/spf13/afero" @@ -85,7 +85,7 @@ func (t *transform) Transform(ctx *resources.ResourceTransformationCtx) error { c: t.c, dependencyManager: ctx.DependencyManager, - varsStylesheet: godartsass.Import{Content: sass.CreateVarsStyleSheet(opts.Vars)}, + varsStylesheet: godartsass.Import{Content: sass.CreateVarsStyleSheet(sass.TranspilerDart, opts.Vars)}, }, OutputStyle: godartsass.ParseOutputStyle(opts.OutputStyle), EnableSourceMap: opts.EnableSourceMap, diff --git a/resources/resource_transformers/tocss/internal/sass/helpers.go b/resources/resource_transformers/tocss/internal/sass/helpers.go deleted file mode 100644 index c1cef141e..000000000 --- a/resources/resource_transformers/tocss/internal/sass/helpers.go +++ /dev/null @@ -1,87 +0,0 @@ -// Copyright 2024 The Hugo Authors. All rights reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package sass - -import ( - "fmt" - "regexp" - "sort" - "strings" - - "github.com/gohugoio/hugo/common/types/css" -) - -const ( - HugoVarsNamespace = "hugo:vars" -) - -func CreateVarsStyleSheet(vars map[string]any) string { - if vars == nil { - return "" - } - var varsStylesheet string - - var varsSlice []string - for k, v := range vars { - var prefix string - if !strings.HasPrefix(k, "$") { - prefix = "$" - } - - switch v.(type) { - case css.QuotedString: - // Marked by the user as a string that needs to be quoted. - varsSlice = append(varsSlice, fmt.Sprintf("%s%s: %q;", prefix, k, v)) - default: - if isTypedCSSValue(v) { - // E.g. 24px, 1.5rem, 10%, hsl(0, 0%, 100%), calc(24px + 36px), #fff, #ffffff. - varsSlice = append(varsSlice, fmt.Sprintf("%s%s: %v;", prefix, k, v)) - } else { - // unquote will preserve quotes around URLs etc. if needed. - varsSlice = append(varsSlice, fmt.Sprintf("%s%s: unquote(%q);", prefix, k, v)) - } - } - } - sort.Strings(varsSlice) - varsStylesheet = strings.Join(varsSlice, "\n") - return varsStylesheet -} - -var ( - isCSSColor = regexp.MustCompile(`^#[0-9a-fA-F]{3,6}$`) - isCSSFunc = regexp.MustCompile(`^([a-zA-Z-]+)\(`) - isCSSUnit = regexp.MustCompile(`^([0-9]+)(\.[0-9]+)?([a-zA-Z-%]+)$`) -) - -// isTypedCSSValue returns true if the given string is a CSS value that -// we should preserve the type of, as in: Not wrap it in quotes. -func isTypedCSSValue(v any) bool { - switch s := v.(type) { - case int, int8, int16, int32, int64, uint, uint8, uint16, uint32, uint64, float32, float64, css.UnquotedString: - return true - case string: - if isCSSColor.MatchString(s) { - return true - } - if isCSSFunc.MatchString(s) { - return true - } - if isCSSUnit.MatchString(s) { - return true - } - - } - - return false -} diff --git a/resources/resource_transformers/tocss/internal/sass/helpers_test.go b/resources/resource_transformers/tocss/internal/sass/helpers_test.go deleted file mode 100644 index ef31fdd8f..000000000 --- a/resources/resource_transformers/tocss/internal/sass/helpers_test.go +++ /dev/null @@ -1,43 +0,0 @@ -// Copyright 2024 The Hugo Authors. All rights reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package sass - -import ( - "testing" - - qt "github.com/frankban/quicktest" -) - -func TestIsUnquotedCSSValue(t *testing.T) { - c := qt.New(t) - - for _, test := range []struct { - in any - out bool - }{ - {"24px", true}, - {"1.5rem", true}, - {"10%", true}, - {"hsl(0, 0%, 100%)", true}, - {"calc(24px + 36px)", true}, - {"24xxx", true}, // a false positive. - {123, true}, - {123.12, true}, - {"#fff", true}, - {"#ffffff", true}, - {"#ffffffff", false}, - } { - c.Assert(isTypedCSSValue(test.in), qt.Equals, test.out) - } -} diff --git a/resources/resource_transformers/tocss/sass/helpers.go b/resources/resource_transformers/tocss/sass/helpers.go new file mode 100644 index 000000000..d4091a39c --- /dev/null +++ b/resources/resource_transformers/tocss/sass/helpers.go @@ -0,0 +1,102 @@ +// Copyright 2024 The Hugo Authors. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package sass + +import ( + "fmt" + "regexp" + "sort" + "strings" + + "github.com/gohugoio/hugo/common/types/css" +) + +const ( + HugoVarsNamespace = "hugo:vars" + // Transpiler implementation can be controlled from the client by + // setting the 'transpiler' option. + // Default is currently 'libsass', but that may change. + TranspilerDart = "dartsass" + TranspilerLibSass = "libsass" +) + +func CreateVarsStyleSheet(transpiler string, vars map[string]any) string { + if vars == nil { + return "" + } + var varsStylesheet string + + var varsSlice []string + for k, v := range vars { + var prefix string + if !strings.HasPrefix(k, "$") { + prefix = "$" + } + + switch v.(type) { + case css.QuotedString: + // Marked by the user as a string that needs to be quoted. + varsSlice = append(varsSlice, fmt.Sprintf("%s%s: %q;", prefix, k, v)) + default: + if isTypedCSSValue(v) { + // E.g. 24px, 1.5rem, 10%, hsl(0, 0%, 100%), calc(24px + 36px), #fff, #ffffff. + varsSlice = append(varsSlice, fmt.Sprintf("%s%s: %v;", prefix, k, v)) + } else { + // unquote will preserve quotes around URLs etc. if needed. + if transpiler == TranspilerDart { + varsSlice = append(varsSlice, fmt.Sprintf("%s%s: string.unquote(%q);", prefix, k, v)) + } else { + varsSlice = append(varsSlice, fmt.Sprintf("%s%s: unquote(%q);", prefix, k, v)) + } + } + } + } + sort.Strings(varsSlice) + + if transpiler == TranspilerDart { + varsStylesheet = `@use "sass:string";` + "\n" + strings.Join(varsSlice, "\n") + } else { + varsStylesheet = strings.Join(varsSlice, "\n") + } + + return varsStylesheet +} + +var ( + isCSSColor = regexp.MustCompile(`^#[0-9a-fA-F]{3,6}$`) + isCSSFunc = regexp.MustCompile(`^([a-zA-Z-]+)\(`) + isCSSUnit = regexp.MustCompile(`^([0-9]+)(\.[0-9]+)?([a-zA-Z-%]+)$`) +) + +// isTypedCSSValue returns true if the given string is a CSS value that +// we should preserve the type of, as in: Not wrap it in quotes. +func isTypedCSSValue(v any) bool { + switch s := v.(type) { + case int, int8, int16, int32, int64, uint, uint8, uint16, uint32, uint64, float32, float64, css.UnquotedString: + return true + case string: + if isCSSColor.MatchString(s) { + return true + } + if isCSSFunc.MatchString(s) { + return true + } + if isCSSUnit.MatchString(s) { + return true + } + + } + + return false +} diff --git a/resources/resource_transformers/tocss/sass/helpers_test.go b/resources/resource_transformers/tocss/sass/helpers_test.go new file mode 100644 index 000000000..ef31fdd8f --- /dev/null +++ b/resources/resource_transformers/tocss/sass/helpers_test.go @@ -0,0 +1,43 @@ +// Copyright 2024 The Hugo Authors. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package sass + +import ( + "testing" + + qt "github.com/frankban/quicktest" +) + +func TestIsUnquotedCSSValue(t *testing.T) { + c := qt.New(t) + + for _, test := range []struct { + in any + out bool + }{ + {"24px", true}, + {"1.5rem", true}, + {"10%", true}, + {"hsl(0, 0%, 100%)", true}, + {"calc(24px + 36px)", true}, + {"24xxx", true}, // a false positive. + {123, true}, + {123.12, true}, + {"#fff", true}, + {"#ffffff", true}, + {"#ffffffff", false}, + } { + c.Assert(isTypedCSSValue(test.in), qt.Equals, test.out) + } +} diff --git a/resources/resource_transformers/tocss/scss/tocss.go b/resources/resource_transformers/tocss/scss/tocss.go index 36ef2a77d..4b9c51ce0 100644 --- a/resources/resource_transformers/tocss/scss/tocss.go +++ b/resources/resource_transformers/tocss/scss/tocss.go @@ -31,7 +31,7 @@ import ( "github.com/gohugoio/hugo/identity" "github.com/gohugoio/hugo/media" "github.com/gohugoio/hugo/resources" - "github.com/gohugoio/hugo/resources/resource_transformers/tocss/internal/sass" + "github.com/gohugoio/hugo/resources/resource_transformers/tocss/sass" ) // Used in tests. This feature requires Hugo to be built with the extended tag. @@ -64,7 +64,7 @@ func (t *toCSSTransformation) Transform(ctx *resources.ResourceTransformationCtx } } - varsStylesheet := sass.CreateVarsStyleSheet(options.from.Vars) + varsStylesheet := sass.CreateVarsStyleSheet(sass.TranspilerLibSass, options.from.Vars) // To allow for overrides of SCSS files anywhere in the project/theme hierarchy, we need // to help libsass revolve the filename by looking in the composite filesystem first. -- cgit v1.2.3