"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"
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,
+++ /dev/null
-// 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
-}
+++ /dev/null
-// 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)
- }
-}
--- /dev/null
+// 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
+}
--- /dev/null
+// 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)
+ }
+}
"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.
}
}
- 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.
"github.com/gohugoio/hugo/resources/resource_transformers/babel"
"github.com/gohugoio/hugo/resources/resource_transformers/cssjs"
"github.com/gohugoio/hugo/resources/resource_transformers/tocss/dartsass"
+ "github.com/gohugoio/hugo/resources/resource_transformers/tocss/sass"
"github.com/gohugoio/hugo/resources/resource_transformers/tocss/scss"
"github.com/gohugoio/hugo/tpl/internal"
"github.com/gohugoio/hugo/tpl/internal/resourcehelpers"
return nil, errors.New("must not provide more arguments than resource object and options")
}
- const (
- // 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"
- )
-
var (
r resources.ResourceTransformer
m map[string]any
targetPath string
err error
ok bool
- transpiler = transpilerLibSass
+ transpiler = sass.TranspilerLibSass
)
r, targetPath, ok = resourcehelpers.ResolveIfFirstArgIsString(args)
if m != nil {
if t, _, found := maps.LookupEqualFold(m, "transpiler"); found {
switch t {
- case transpilerDart, transpilerLibSass:
+ case sass.TranspilerDart, sass.TranspilerLibSass:
transpiler = cast.ToString(t)
default:
- return nil, fmt.Errorf("unsupported transpiler %q; valid values are %q or %q", t, transpilerLibSass, transpilerDart)
+ return nil, fmt.Errorf("unsupported transpiler %q; valid values are %q or %q", t, sass.TranspilerLibSass, sass.TranspilerDart)
}
}
}
- if transpiler == transpilerLibSass {
+ if transpiler == sass.TranspilerLibSass {
var options scss.Options
if targetPath != "" {
options.TargetPath = paths.ToSlashTrimLeading(targetPath)
qt "github.com/frankban/quicktest"
"github.com/gohugoio/hugo/hugolib"
+ "github.com/gohugoio/hugo/resources/resource_transformers/tocss/dartsass"
+ "github.com/gohugoio/hugo/resources/resource_transformers/tocss/scss"
)
func TestCopy(t *testing.T) {
b.AssertFileContent("public/files/b.txt", "I am b.txt")
b.AssertFileContent("public/files/C.txt", "I am C.txt")
}
+
+// Issue #12961
+func TestDartSassVars(t *testing.T) {
+ t.Parallel()
+
+ if !scss.Supports() || !dartsass.Supports() {
+ t.Skip()
+ }
+
+ files := `
+-- hugo.toml --
+disableKinds = ['page','section','rss','sitemap','taxonomy','term']
+-- layouts/index.html --
+{{ $opts := dict "transpiler" "dartsass" "outputStyle" "compressed" "vars" (dict "color" "red") }}
+{{ with resources.Get "dartsass.scss" | css.Sass $opts }}
+ {{ .Content }}
+{{ end }}
+
+{{ $opts := dict "transpiler" "libsass" "outputStyle" "compressed" "vars" (dict "color" "blue") }}
+{{ with resources.Get "libsass.scss" | css.Sass $opts }}
+ {{ .Content }}
+{{ end }}
+-- assets/dartsass.scss --
+@use "hugo:vars" as v;
+.dartsass {
+ color: v.$color;
+}
+-- assets/libsass.scss --
+@import "hugo:vars";
+.libsass {
+ color: $color;
+}
+`
+
+ b := hugolib.Test(t, files, hugolib.TestOptWarn())
+
+ b.AssertFileContent("public/index.html",
+ ".dartsass{color:red}",
+ ".libsass{color:blue}",
+ )
+ b.AssertLogContains("! WARN Dart Sass: hugo:vars")
+}