Repository: gohugoio/hugo (language: go)

Issue:
Use sass --embedded once it's released
Hi, the [dart-sass-embedded](https://github.com/sass/dart-sass-embedded) compiler has been merged into dart-sass. Please consider using `sass --embedded` instead of ``dart-sass-embedded`` for forwards compatibility.


Discussion / hints:
Can you point to the released version of this `sass` binary?
> The embedded compiler has been merged into [the primary Dart Sass repository](https://github.com/sass/dart-sass), and further releases will be included [as part of Dart Sass itself](https://github.com/sass/dart-sass#embedded-dart-sass).
>
> -- readme of sass/dart-sass-embedded

The new version of `sass` haven't been released yet
> > The embedded compiler has been merged into [the primary Dart Sass repository](https://github.com/sass/dart-sass), and further releases will be included [as part of Dart Sass itself](https://github.com/sass/dart-sass#embedded-dart-sass).
> > -- readme of sass/dart-sass-embedded
> 
> The new version of `sass` haven't been released yet

Apologies, I didn't look into this enough. I'll add a comment updating this issue when the next version of dart-sass is released.
Thanks, this is already on our radar, but need a Dart Sass release before we can implement this.
I'll add to the requirement, "once it's released, and performance is roughly equivalent to the current embedded implementation." It may already be there, but my early (and perhaps poorly implemented) testing was not encouraging.
@jmooring yea, well, this will all start out in

https://github.com/bep/godartsass

Which has some basic benchmarks which will hopefully give raise a red flag if the performance has taken a hit.

Note that they also plan a change in the wire format (I'm not sure if that's implemented) that needs some update in the godartsass library to work -- as I understood it, that was motivated by performance.

Here's the changes I mentioned above: https://github.com/sass/dart-sass/issues/1980
A new version of Dart Sass has released with the inclusion of ``sass --embedded``, please see [Dart Sass 1.63.0](https://github.com/sass/dart-sass/releases/tag/1.63.0) and [subsequent releases](https://github.com/sass/dart-sass/releases/)
I have upgraded the upstream library to v2 of the protocol, but I need to understand this issue

https://github.com/bep/godartsass/issues/19

Before I can pull it into Hugo.


Fix patch:
diff --git a/common/herrors/file_error.go b/common/herrors/file_error.go
index 30417897f6a..ae86a700cb5 100644
--- a/common/herrors/file_error.go
+++ b/common/herrors/file_error.go
@@ -15,11 +15,14 @@ package herrors
 
 import (
 	"encoding/json"
+
+	godartsassv1 "github.com/bep/godartsass"
+
 	"fmt"
 	"io"
 	"path/filepath"
 
-	"github.com/bep/godartsass"
+	"github.com/bep/godartsass/v2"
 	"github.com/bep/golibsass/libsass/libsasserrors"
 	"github.com/gohugoio/hugo/common/paths"
 	"github.com/gohugoio/hugo/common/text"
@@ -145,6 +148,8 @@ func (e *fileError) causeString() string {
 	// Avoid repeating the file info in the error message.
 	case godartsass.SassError:
 		return v.Message
+	case godartsassv1.SassError:
+		return v.Message
 	case libsasserrors.Error:
 		return v.Message
 	default:
@@ -385,6 +390,13 @@ func extractPosition(e error) (pos text.Position) {
 		pos.Filename = filename
 		pos.Offset = start.Offset
 		pos.ColumnNumber = start.Column
+	case godartsassv1.SassError:
+		span := v.Span
+		start := span.Start
+		filename, _ := paths.UrlToFilename(span.Url)
+		pos.Filename = filename
+		pos.Offset = start.Offset
+		pos.ColumnNumber = start.Column
 	case libsasserrors.Error:
 		pos.Filename = v.File
 		pos.LineNumber = v.Line
diff --git a/common/hugo/hugo.go b/common/hugo/hugo.go
index 4769852a096..c28dd0b5308 100644
--- a/common/hugo/hugo.go
+++ b/common/hugo/hugo.go
@@ -22,9 +22,13 @@ import (
 	"sort"
 	"strings"
 	"sync"
+
+	godartsassv1 "github.com/bep/godartsass"
+	"github.com/mitchellh/mapstructure"
+
 	"time"
 
-	"github.com/bep/godartsass"
+	"github.com/bep/godartsass/v2"
 	"github.com/gohugoio/hugo/common/hexec"
 	"github.com/gohugoio/hugo/hugofs/files"
 
@@ -238,7 +242,10 @@ func GetDependencyListNonGo() []string {
 	}
 
 	if dartSass := dartSassVersion(); dartSass.ProtocolVersion != "" {
-		const dartSassPath = "github.com/sass/dart-sass-embedded"
+		var dartSassPath = "github.com/sass/dart-sass-embedded"
+		if IsDartSassV2() {
+			dartSassPath = "github.com/sass/dart-sass"
+		}
 		deps = append(deps,
 			formatDep(dartSassPath+"/protocol", dartSass.ProtocolVersion),
 			formatDep(dartSassPath+"/compiler", dartSass.CompilerVersion),
@@ -283,11 +290,46 @@ type Dependency struct {
 }
 
 func dartSassVersion() godartsass.DartSassVersion {
-	// This is also duplicated in the dartsass package.
-	const dartSassEmbeddedBinaryName = "dart-sass-embedded"
-	if !hexec.InPath(dartSassEmbeddedBinaryName) {
+	if DartSassBinaryName == "" {
 		return godartsass.DartSassVersion{}
 	}
-	v, _ := godartsass.Version(dartSassEmbeddedBinaryName)
-	return v
+	if IsDartSassV2() {
+		v, _ := godartsass.Version(DartSassBinaryName)
+		return v
+	}
+
+	v, _ := godartsassv1.Version(DartSassBinaryName)
+	var vv godartsass.DartSassVersion
+	mapstructure.WeakDecode(v, &vv)
+	return vv
+}
+
+// DartSassBinaryName is the name of the Dart Sass binary to use.
+// TODO(beop) find a better place for this.
+var DartSassBinaryName string
+
+func init() {
+	DartSassBinaryName = os.Getenv("DART_SASS_BINARY")
+	if DartSassBinaryName == "" {
+		for _, name := range dartSassBinaryNamesV2 {
+			if hexec.InPath(name) {
+				DartSassBinaryName = name
+				break
+			}
+		}
+		if DartSassBinaryName == "" {
+			if hexec.InPath(dartSassBinaryNameV1) {
+				DartSassBinaryName = dartSassBinaryNameV1
+			}
+		}
+	}
+}
+
+var (
+	dartSassBinaryNameV1  = "dart-sass-embedded"
+	dartSassBinaryNamesV2 = []string{"dart-sass", "sass"}
+)
+
+func IsDartSassV2() bool {
+	return !strings.Contains(DartSassBinaryName, "embedded")
 }
diff --git a/config/security/securityConfig.go b/config/security/securityConfig.go
index f7d2beac8bf..8bd12af4b77 100644
--- a/config/security/securityConfig.go
+++ b/config/security/securityConfig.go
@@ -35,9 +35,9 @@ const securityConfigKey = "security"
 var DefaultConfig = Config{
 	Exec: Exec{
 		Allow: NewWhitelist(
-			"^dart-sass-embedded$",
-			"^go$",  // for Go Modules
-			"^npx$", // used by all Node tools (Babel, PostCSS).
+			"^(dart-)?sass(-embedded)?$", // sass, dart-sass, dart-sass-embedded.
+			"^go$",                       // for Go Modules
+			"^npx$",                      // used by all Node tools (Babel, PostCSS).
 			"^postcss$",
 		),
 		// These have been tested to work with Hugo's external programs
diff --git a/go.mod b/go.mod
index d19c1b0ba14..8531dcfe61b 100644
--- a/go.mod
+++ b/go.mod
@@ -10,7 +10,8 @@ require (
 	github.com/bep/debounce v1.2.0
 	github.com/bep/gitmap v1.1.2
 	github.com/bep/goat v0.5.0
-	github.com/bep/godartsass v0.16.0
+	github.com/bep/godartsass v1.2.0
+	github.com/bep/godartsass/v2 v2.0.0
 	github.com/bep/golibsass v1.1.1
 	github.com/bep/gowebp v0.2.0
 	github.com/bep/helpers v0.4.0
diff --git a/go.sum b/go.sum
index ec96735a685..f97bb7a747d 100644
--- a/go.sum
+++ b/go.sum
@@ -168,8 +168,10 @@ github.com/bep/gitmap v1.1.2 h1:zk04w1qc1COTZPPYWDQHvns3y1afOsdRfraFQ3qI840=
 github.com/bep/gitmap v1.1.2/go.mod h1:g9VRETxFUXNWzMiuxOwcudo6DfZkW9jOsOW0Ft4kYaY=
 github.com/bep/goat v0.5.0 h1:S8jLXHCVy/EHIoCY+btKkmcxcXFd34a0Q63/0D4TKeA=
 github.com/bep/goat v0.5.0/go.mod h1:Md9x7gRxiWKs85yHlVTvHQw9rg86Bm+Y4SuYE8CTH7c=
-github.com/bep/godartsass v0.16.0 h1:nTpenrZBQjVSjLkCw3AgnYmBB2czauTJa4BLLv448qg=
-github.com/bep/godartsass v0.16.0/go.mod h1:6LvK9RftsXMxGfsA0LDV12AGc4Jylnu6NgHL+Q5/pE8=
+github.com/bep/godartsass v1.2.0 h1:E2VvQrxAHAFwbjyOIExAMmogTItSKodoKuijNrGm5yU=
+github.com/bep/godartsass v1.2.0/go.mod h1:6LvK9RftsXMxGfsA0LDV12AGc4Jylnu6NgHL+Q5/pE8=
+github.com/bep/godartsass/v2 v2.0.0 h1:Ruht+BpBWkpmW+yAM2dkp7RSSeN0VLaTobyW0CiSP3Y=
+github.com/bep/godartsass/v2 v2.0.0/go.mod h1:AcP8QgC+OwOXEq6im0WgDRYK7scDsmZCEW62o1prQLo=
 github.com/bep/golibsass v1.1.1 h1:xkaet75ygImMYjM+FnHIT3xJn7H0xBA9UxSOJjk8Khw=
 github.com/bep/golibsass v1.1.1/go.mod h1:DL87K8Un/+pWUS75ggYv41bliGiolxzDKWJAq3eJ1MA=
 github.com/bep/gowebp v0.2.0 h1:ZVfK8i9PpZqKHEmthQSt3qCnnHycbLzBPEsVtk2ch2Q=
diff --git a/resources/resource_transformers/tocss/dartsass/client.go b/resources/resource_transformers/tocss/dartsass/client.go
index f358b93e5f2..9ae3178869d 100644
--- a/resources/resource_transformers/tocss/dartsass/client.go
+++ b/resources/resource_transformers/tocss/dartsass/client.go
@@ -20,7 +20,10 @@ import (
 	"io"
 	"strings"
 
+	godartsassv1 "github.com/bep/godartsass"
+	"github.com/bep/godartsass/v2"
 	"github.com/gohugoio/hugo/common/herrors"
+	"github.com/gohugoio/hugo/common/hugo"
 	"github.com/gohugoio/hugo/helpers"
 	"github.com/gohugoio/hugo/hugofs"
 	"github.com/gohugoio/hugo/hugolib/filesystems"
@@ -28,7 +31,6 @@ import (
 	"github.com/gohugoio/hugo/resources/resource"
 	"github.com/spf13/afero"
 
-	"github.com/bep/godartsass"
 	"github.com/mitchellh/mapstructure"
 )
 
@@ -44,27 +46,57 @@ func New(fs *filesystems.SourceFilesystem, rs *resources.Spec) (*Client, error)
 		return &Client{dartSassNotAvailable: true}, nil
 	}
 
-	if err := rs.ExecHelper.Sec().CheckAllowedExec(dartSassEmbeddedBinaryName); err != nil {
+	if hugo.DartSassBinaryName == "" {
+		return nil, fmt.Errorf("no Dart Sass binary found in $PATH")
+	}
+
+	if err := rs.ExecHelper.Sec().CheckAllowedExec(hugo.DartSassBinaryName); err != nil {
 		return nil, err
 	}
 
-	transpiler, err := godartsass.Start(godartsass.Options{
-		LogEventHandler: func(event godartsass.LogEvent) {
-			message := strings.ReplaceAll(event.Message, dartSassStdinPrefix, "")
-			switch event.Type {
-			case godartsass.LogEventTypeDebug:
-				// Log as Info for now, we may adjust this if it gets too chatty.
-				rs.Logger.Infof("Dart Sass: %s", message)
-			default:
-				// The rest are either deprecations or @warn statements.
-				rs.Logger.Warnf("Dart Sass: %s", message)
-			}
-		},
-	})
+	var (
+		transpiler   *godartsass.Transpiler
+		transpilerv1 *godartsassv1.Transpiler
+		err          error
+	)
+
+	if hugo.IsDartSassV2() {
+		transpiler, err = godartsass.Start(godartsass.Options{
+			DartSassEmbeddedFilename: hugo.DartSassBinaryName,
+			LogEventHandler: func(event godartsass.LogEvent) {
+				message := strings.ReplaceAll(event.Message, dartSassStdinPrefix, "")
+				switch event.Type {
+				case godartsass.LogEventTypeDebug:
+					// Log as Info for now, we may adjust this if it gets too chatty.
+					rs.Logger.Infof("Dart Sass: %s", message)
+				default:
+					// The rest are either deprecations or @warn statements.
+					rs.Logger.Warnf("Dart Sass: %s", message)
+				}
+			},
+		})
+
+	} else {
+		transpilerv1, err = godartsassv1.Start(godartsassv1.Options{
+			DartSassEmbeddedFilename: hugo.DartSassBinaryName,
+			LogEventHandler: func(event godartsassv1.LogEvent) {
+				message := strings.ReplaceAll(event.Message, dartSassStdinPrefix, "")
+				switch event.Type {
+				case godartsassv1.LogEventTypeDebug:
+					// Log as Info for now, we may adjust this if it gets too chatty.
+					rs.Logger.Infof("Dart Sass: %s", message)
+				default:
+					// The rest are either deprecations or @warn statements.
+					rs.Logger.Warnf("Dart Sass: %s", message)
+				}
+			},
+		})
+	}
+
 	if err != nil {
 		return nil, err
 	}
-	return &Client{sfs: fs, workFs: rs.BaseFs.Work, rs: rs, transpiler: transpiler}, nil
+	return &Client{sfs: fs, workFs: rs.BaseFs.Work, rs: rs, transpiler: transpiler, transpilerV1: transpilerv1}, nil
 }
 
 type Client struct {
@@ -72,7 +104,10 @@ type Client struct {
 	rs                   *resources.Spec
 	sfs                  *filesystems.SourceFilesystem
 	workFs               afero.Fs
-	transpiler           *godartsass.Transpiler
+
+	// One of these are non-nil.
+	transpiler   *godartsass.Transpiler
+	transpilerV1 *godartsassv1.Transpiler
 }
 
 func (c *Client) ToCSS(res resources.ResourceTransformer, args map[string]any) (resource.Resource, error) {
@@ -83,23 +118,44 @@ func (c *Client) ToCSS(res resources.ResourceTransformer, args map[string]any) (
 }
 
 func (c *Client) Close() error {
-	if c.transpiler == nil {
-		return nil
+	if c.transpilerV1 != nil {
+		return c.transpilerV1.Close()
+	}
+	if c.transpiler != nil {
+		return c.transpiler.Close()
 	}
-	return c.transpiler.Close()
+	return nil
 }
 
 func (c *Client) toCSS(args godartsass.Args, src io.Reader) (godartsass.Result, error) {
-	var res godartsass.Result
-
 	in := helpers.ReaderToString(src)
 
 	args.Source = in
 
-	res, err := c.transpiler.Execute(args)
+	var (
+		err error
+		res godartsass.Result
+	)
+
+	if c.transpilerV1 != nil {
+		var resv1 godartsassv1.Result
+		var argsv1 godartsassv1.Args
+		mapstructure.Decode(args, &argsv1)
+		if args.ImportResolver != nil {
+			argsv1.ImportResolver = importResolverV1{args.ImportResolver}
+		}
+		resv1, err = c.transpilerV1.Execute(argsv1)
+		if err == nil {
+			mapstructure.Decode(resv1, &res)
+		}
+	} else {
+		res, err = c.transpiler.Execute(args)
+
+	}
+
 	if err != nil {
 		if err.Error() == "unexpected EOF" {
-			return res, fmt.Errorf("got unexpected EOF when executing %q. The user running hugo must have read and execute permissions on this program. With execute permissions only, this error is thrown.", dartSassEmbeddedBinaryName)
+			return res, fmt.Errorf("got unexpected EOF when executing %q. The user running hugo must have read and execute permissions on this program. With execute permissions only, this error is thrown.", hugo.DartSassBinaryName)
 		}
 		return res, herrors.NewFileErrorFromFileInErr(err, hugofs.Os, herrors.OffsetMatcher)
 	}
diff --git a/resources/resource_transformers/tocss/dartsass/transform.go b/resources/resource_transformers/tocss/dartsass/transform.go
index 61ea54437ad..32855e1c553 100644
--- a/resources/resource_transformers/tocss/dartsass/transform.go
+++ b/resources/resource_transformers/tocss/dartsass/transform.go
@@ -20,7 +20,7 @@ import (
 	"path/filepath"
 	"strings"
 
-	"github.com/gohugoio/hugo/common/hexec"
+	"github.com/gohugoio/hugo/common/hugo"
 	"github.com/gohugoio/hugo/common/paths"
 	"github.com/gohugoio/hugo/htesting"
 	"github.com/gohugoio/hugo/media"
@@ -34,11 +34,8 @@ import (
 
 	"github.com/gohugoio/hugo/hugofs"
 
-	"github.com/bep/godartsass"
-)
-
-const (
-	dartSassEmbeddedBinaryName = "dart-sass-embedded"
+	godartsassv1 "github.com/bep/godartsass"
+	"github.com/bep/godartsass/v2"
 )
 
 // Supports returns whether dart-sass-embedded is found in $PATH.
@@ -46,7 +43,7 @@ func Supports() bool {
 	if htesting.SupportsAll() {
 		return true
 	}
-	return hexec.InPath(dartSassEmbeddedBinaryName)
+	return hugo.DartSassBinaryName != ""
 }
 
 type transform struct {
@@ -86,7 +83,7 @@ func (t *transform) Transform(ctx *resources.ResourceTransformationCtx) error {
 			baseDir: baseDir,
 			c:       t.c,
 
-			varsStylesheet: sass.CreateVarsStyleSheet(opts.Vars),
+			varsStylesheet: godartsass.Import{Content: sass.CreateVarsStyleSheet(opts.Vars)},
 		},
 		OutputStyle:             godartsass.ParseOutputStyle(opts.OutputStyle),
 		EnableSourceMap:         opts.EnableSourceMap,
@@ -132,7 +129,7 @@ type importResolver struct {
 	baseDir string
 	c       *Client
 
-	varsStylesheet string
+	varsStylesheet godartsass.Import
 }
 
 func (t importResolver) CanonicalizeURL(url string) (string, error) {
@@ -184,11 +181,29 @@ func (t importResolver) CanonicalizeURL(url string) (string, error) {
 	return "", nil
 }
 
-func (t importResolver) Load(url string) (string, error) {
+func (t importResolver) Load(url string) (godartsass.Import, error) {
 	if url == sass.HugoVarsNamespace {
 		return t.varsStylesheet, nil
 	}
 	filename, _ := paths.UrlToFilename(url)
 	b, err := afero.ReadFile(hugofs.Os, filename)
-	return string(b), err
+
+	sourceSyntax := godartsass.SourceSyntaxSCSS
+	if strings.HasSuffix(filename, ".sass") {
+		sourceSyntax = godartsass.SourceSyntaxSASS
+	} else if strings.HasSuffix(filename, ".css") {
+		sourceSyntax = godartsass.SourceSyntaxCSS
+	}
+
+	return godartsass.Import{Content: string(b), SourceSyntax: sourceSyntax}, err
+
+}
+
+type importResolverV1 struct {
+	godartsass.ImportResolver
+}
+
+func (t importResolverV1) Load(url string) (godartsassv1.Import, error) {
+	res, err := t.ImportResolver.Load(url)
+	return godartsassv1.Import{Content: res.Content, SourceSyntax: godartsassv1.SourceSyntax(res.SourceSyntax)}, err
 }


Test patch:
diff --git a/.github/workflows/test-dart-sass-v1.yml b/.github/workflows/test-dart-sass-v1.yml
new file mode 100644
index 00000000000..ff6f6a01baf
--- /dev/null
+++ b/.github/workflows/test-dart-sass-v1.yml
@@ -0,0 +1,73 @@
+on:
+  push:
+    branches: [ master ]
+  pull_request:
+name: TestDartSassV1
+env:
+    GOPROXY: https://proxy.golang.org
+    GO111MODULE: on
+    DART_SASS_VERSION: 1.62.1
+    DART_SASS_SHA_LINUX: 3574da75a7322a539034648b8ff84ff2cca162eb924d72b663d718cd3936f075
+permissions:
+  contents: read
+jobs:
+  test:
+    strategy:
+      matrix:
+        go-version: [1.20.x]
+        os: [ubuntu-latest]
+    runs-on: ${{ matrix.os }}
+    steps:
+    - name: Checkout code
+      uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab
+    - name: Install Go
+      uses: actions/setup-go@fac708d6674e30b6ba41289acaab6d4b75aa0753
+      with:
+        go-version: ${{ matrix.go-version }}
+        check-latest: true
+        cache: true
+        cache-dependency-path: |
+          **/go.sum
+          **/go.mod
+    - name: Install Ruby
+      uses: ruby/setup-ruby@ee2113536afb7f793eed4ce60e8d3b26db912da4
+      with:
+        ruby-version: '2.7' 
+        bundler-cache: true #
+    - name: Install Python
+      uses: actions/setup-python@3105fb18c05ddd93efea5f9e0bef7a03a6e9e7df
+      with:
+        python-version: '3.x'
+    - name: Install Mage
+      run: go install github.com/magefile/mage@v1.15.0
+    - name: Install asciidoctor
+      uses: reitzig/actions-asciidoctor@7570212ae20b63653481675fb1ff62d1073632b0
+    - name: Install docutils
+      run: |
+        pip install docutils
+        rst2html.py --version
+    - if: matrix.os == 'ubuntu-latest'
+      name: Install pandoc on Linux
+      run: |
+          sudo apt-get update -y
+          sudo apt-get install -y pandoc
+    - if: matrix.os == 'macos-latest'
+      run: |
+        brew install pandoc
+    - if: matrix.os == 'windows-latest'
+      run: |
+        Choco-Install -PackageName pandoc
+    - run: pandoc -v
+    - name: Install dart-sass-embedded Linux
+      run: |
+        echo "Install Dart Sass version ${DART_SASS_VERSION} ..."
+        curl -LJO "https://github.com/sass/dart-sass-embedded/releases/download/${DART_SASS_VERSION}/sass_embedded-${DART_SASS_VERSION}-linux-x64.tar.gz";
+        echo "${DART_SASS_SHA_LINUX}  sass_embedded-${DART_SASS_VERSION}-linux-x64.tar.gz" | sha256sum -c;
+        tar -xvf "sass_embedded-${DART_SASS_VERSION}-linux-x64.tar.gz";
+        echo "$GITHUB_WORKSPACE/sass_embedded/" >> $GITHUB_PATH
+    - name: Check
+      run: |
+        dart-sass-embedded --version
+        mage -v check;
+      env:
+        HUGO_BUILD_TAGS: extended
diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml
index f23dde8031e..fd3847e598a 100644
--- a/.github/workflows/test.yml
+++ b/.github/workflows/test.yml
@@ -6,17 +6,17 @@ name: Test
 env:
     GOPROXY: https://proxy.golang.org
     GO111MODULE: on
-    DART_SASS_VERSION: 1.56.2
-    DART_SASS_SHA_LINUX: 9e4f455f7b8619959d7878af2862383be58392eb963a14ff87cc512c03701e2a
-    DART_SASS_SHA_MACOS: 5992e979e2c30ec363f8e338822bb2b4443c74232b3340501a76180f5652cb09
-    DART_SASS_SHA_WINDOWS: 8d3d9117c54840e3e6a4919e43acf75ea52f28a64fc87a8e29d80ec72ee36cfb
+    SASS_VERSION: 1.63.2
+    DART_SASS_SHA_LINUX: 3ea33c95ad5c35fda6e9a0956199eef38a398f496cfb8750e02479d7d1dd42af
+    DART_SASS_SHA_MACOS: 11c70f259836b250b44a9cb57fed70e030f21f45069b467d371685855f1eb4f0
+    DART_SASS_SHA_WINDOWS: cd8cd36a619dd8e27f93d3186c52d70eb7d69472aa6c85f5094b29693e773f64
 permissions:
   contents: read
 jobs:
   test:
     strategy:
       matrix:
-        go-version: [1.19.x, 1.20.x]
+        go-version: [1.19.x,1.20.x]
         os: [ubuntu-latest, macos-latest, windows-latest]
     runs-on: ${{ matrix.os }}
     steps:
@@ -66,29 +66,31 @@ jobs:
     - if: matrix.os == 'ubuntu-latest'
       name: Install dart-sass-embedded Linux
       run: |
-        echo "Install Dart Sass version ${DART_SASS_VERSION} ..."
-        curl -LJO "https://github.com/sass/dart-sass-embedded/releases/download/${DART_SASS_VERSION}/sass_embedded-${DART_SASS_VERSION}-linux-x64.tar.gz";
-        echo "${DART_SASS_SHA_LINUX}  sass_embedded-${DART_SASS_VERSION}-linux-x64.tar.gz" | sha256sum -c;
-        tar -xvf "sass_embedded-${DART_SASS_VERSION}-linux-x64.tar.gz";
-        echo "$GITHUB_WORKSPACE/sass_embedded/" >> $GITHUB_PATH
+        echo "Install Dart Sass version ${SASS_VERSION} ..."
+        curl -LJO "https://github.com/sass/dart-sass/releases/download/${SASS_VERSION}/dart-sass-${SASS_VERSION}-linux-x64.tar.gz";
+        echo "${DART_SASS_SHA_LINUX}  dart-sass-${SASS_VERSION}-linux-x64.tar.gz" | sha256sum -c;
+        tar -xvf "dart-sass-${SASS_VERSION}-linux-x64.tar.gz";
+        echo "$GOBIN"
+        echo "$GITHUB_WORKSPACE/dart-sass/" >> $GITHUB_PATH
     - if: matrix.os == 'macos-latest'
       name: Install dart-sass-embedded MacOS
       run: |
-        echo "Install Dart Sass version ${DART_SASS_VERSION} ..."
-        curl -LJO "https://github.com/sass/dart-sass-embedded/releases/download/${DART_SASS_VERSION}/sass_embedded-${DART_SASS_VERSION}-macos-x64.tar.gz";
-        echo "${DART_SASS_SHA_MACOS}  sass_embedded-${DART_SASS_VERSION}-macos-x64.tar.gz" | shasum -a 256 -c;
-        tar -xvf "sass_embedded-${DART_SASS_VERSION}-macos-x64.tar.gz";
-        echo "$GITHUB_WORKSPACE/sass_embedded/" >> $GITHUB_PATH
+        echo "Install Dart Sass version ${SASS_VERSION} ..."
+        curl -LJO "https://github.com/sass/dart-sass/releases/download/${SASS_VERSION}/dart-sass-${SASS_VERSION}-macos-x64.tar.gz";
+        echo "${DART_SASS_SHA_MACOS}  dart-sass-${SASS_VERSION}-macos-x64.tar.gz" | shasum -a 256 -c;
+        tar -xvf "dart-sass-${SASS_VERSION}-macos-x64.tar.gz";
+        echo "$GITHUB_WORKSPACE/dart-sass/" >> $GITHUB_PATH
     - if: matrix.os == 'windows-latest'
       name: Install dart-sass-embedded Windows
       run: |
-        echo "Install Dart Sass version ${env:DART_SASS_VERSION} ..."
-        curl -LJO "https://github.com/sass/dart-sass-embedded/releases/download/${env:DART_SASS_VERSION}/sass_embedded-${env:DART_SASS_VERSION}-windows-x64.zip";
-        Expand-Archive -Path "sass_embedded-${env:DART_SASS_VERSION}-windows-x64.zip" -DestinationPath .;
-        echo  "$env:GITHUB_WORKSPACE/sass_embedded/" | Out-File -FilePath $Env:GITHUB_PATH -Encoding utf-8 -Append
+        echo "Install Dart Sass version ${env:SASS_VERSION} ..."
+        curl -LJO "https://github.com/sass/dart-sass/releases/download/${env:SASS_VERSION}/dart-sass-${env:SASS_VERSION}-windows-x64.zip";
+        Expand-Archive -Path "dart-sass-${env:SASS_VERSION}-windows-x64.zip" -DestinationPath .;
+        echo  "$env:GITHUB_WORKSPACE/dart-sass/" | Out-File -FilePath $Env:GITHUB_PATH -Encoding utf-8 -Append
     - if: matrix.os != 'windows-latest'
       name: Check
       run: |
+        sass --version;
         mage -v check;
       env:
         HUGO_BUILD_TAGS: extended
diff --git a/config/security/securityConfig_test.go b/config/security/securityConfig_test.go
index edc1737e34a..3bfd59ce33b 100644
--- a/config/security/securityConfig_test.go
+++ b/config/security/securityConfig_test.go
@@ -140,7 +140,7 @@ func TestToTOML(t *testing.T) {
 	got := DefaultConfig.ToTOML()
 
 	c.Assert(got, qt.Equals,
-		"[security]\n  enableInlineShortcodes = false\n\n  [security.exec]\n    allow = ['^dart-sass-embedded$', '^go$', '^npx$', '^postcss$']\n    osEnv = ['(?i)^((HTTPS?|NO)_PROXY|PATH(EXT)?|APPDATA|TE?MP|TERM|GO\\w+)$']\n\n  [security.funcs]\n    getenv = ['^HUGO_', '^CI$']\n\n  [security.http]\n    methods = ['(?i)GET|POST']\n    urls = ['.*']",
+		"[security]\n  enableInlineShortcodes = false\n\n  [security.exec]\n    allow = ['^(dart-)?sass(-embedded)?$', '^go$', '^npx$', '^postcss$']\n    osEnv = ['(?i)^((HTTPS?|NO)_PROXY|PATH(EXT)?|APPDATA|TE?MP|TERM|GO\\w+)$']\n\n  [security.funcs]\n    getenv = ['^HUGO_', '^CI$']\n\n  [security.http]\n    methods = ['(?i)GET|POST']\n    urls = ['.*']",
 	)
 }
 
diff --git a/hugolib/securitypolicies_test.go b/hugolib/securitypolicies_test.go
index 5b9267b591d..60ef9a7e27d 100644
--- a/hugolib/securitypolicies_test.go
+++ b/hugolib/securitypolicies_test.go
@@ -42,7 +42,6 @@ func TestSecurityPolicies(t *testing.T) {
 		} else {
 			b.Build(BuildCfg{})
 		}
-
 	}
 
 	httpTestVariant := func(c *qt.C, templ, expectErr string, withBuilder func(b *sitesBuilder)) {
@@ -145,7 +144,7 @@ allow="none"
 			`)
 			b.WithTemplatesAdded("index.html", `{{ $scss := "body { color: #333; }" | resources.FromString "foo.scss"  | resources.ToCSS (dict "transpiler" "dartsass") }}`)
 		}
-		testVariant(c, cb, `(?s).*"dart-sass-embedded" is not whitelisted in policy "security\.exec\.allow".*`)
+		testVariant(c, cb, `(?s).*sass(-embedded)?" is not whitelisted in policy "security\.exec\.allow".*`)
 	})
 
 	c.Run("resources.GetRemote, OK", func(c *qt.C) {
diff --git a/resources/resource_transformers/tocss/dartsass/integration_test.go b/resources/resource_transformers/tocss/dartsass/integration_test.go
index aa71101a04e..d765923360c 100644
--- a/resources/resource_transformers/tocss/dartsass/integration_test.go
+++ b/resources/resource_transformers/tocss/dartsass/integration_test.go
@@ -109,6 +109,38 @@ T1: {{ $r.Content | safeHTML }}
 		/* foo */`)
 }
 
+func TestTransformImportIndentedSASS(t *testing.T) {
+	t.Parallel()
+	if !dartsass.Supports() {
+		t.Skip()
+	}
+
+	files := `
+-- assets/scss/_moo.sass --
+#main
+	color: blue
+-- assets/scss/main.scss --
+@import "moo";
+
+/* foo */
+-- config.toml --
+-- layouts/index.html --
+{{ $r := resources.Get "scss/main.scss" |  toCSS (dict "transpiler" "dartsass")  }}
+T1: {{ $r.Content | safeHTML }}
+
+	`
+
+	b := hugolib.NewIntegrationTestBuilder(
+		hugolib.IntegrationTestConfig{
+			T:           t,
+			TxtarString: files,
+			NeedsOsFS:   true,
+		},
+	).Build()
+
+	b.AssertFileContent("public/index.html", "T1: #main {\n  color: blue;\n}\n\n/* foo */")
+}
+
 // Issue 10592
 func TestTransformImportMountedCSS(t *testing.T) {
 	t.Parallel()