Repository: gohugoio/hugo (language: go)

Issue:
dartsass: Support @debug, @warn etc. 
See https://github.com/bep/godartsass/issues/6


Discussion / hints:
Please include `@error` in this. I think it would be useful to stop processing at that point and dartsass would do that. If you think devs should not be able to "break out" of the stylesheet creation (I wouldn't understand what is going on under the hood there) then maybe "catch" an `@error` and output something along the lines of "`@error` encountered but ignored". 

A good use case for these features is in my opinion the opportunity for me as theme developer to let the user know that his selection of colors for instance is ok, but might result in bad contrasts. Or tell them that a variable is not set that could make their life better and what defaults are used. Makes sense somehow.
@error is already handled (it fails the build). This particular issue is about _logging_, and the scope is very narrow.

Fix patch:
diff --git a/go.mod b/go.mod
index 9a5e1179e1e..b797586be71 100644
--- a/go.mod
+++ b/go.mod
@@ -9,7 +9,7 @@ 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.12.0
+	github.com/bep/godartsass v0.14.0
 	github.com/bep/golibsass v1.0.0
 	github.com/bep/gowebp v0.1.0
 	github.com/bep/tmc v0.5.1
diff --git a/go.sum b/go.sum
index 1027742c15f..545ba108559 100644
--- a/go.sum
+++ b/go.sum
@@ -140,8 +140,8 @@ 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.12.0 h1:VvGLA4XpXUjKvp53SI05YFLhRFJ78G+Ybnlaz6Oul7E=
-github.com/bep/godartsass v0.12.0/go.mod h1:nXQlHHk4H1ghUk6n/JkYKG5RD43yJfcfp5aHRqT/pc4=
+github.com/bep/godartsass v0.14.0 h1:pPb6XkpyDEppS+wK0veh7OXDQc4xzOJI9Qcjb743UeQ=
+github.com/bep/godartsass v0.14.0/go.mod h1:6LvK9RftsXMxGfsA0LDV12AGc4Jylnu6NgHL+Q5/pE8=
 github.com/bep/golibsass v1.0.0 h1:gNguBMSDi5yZEZzVZP70YpuFQE3qogJIGUlrVILTmOw=
 github.com/bep/golibsass v1.0.0/go.mod h1:DL87K8Un/+pWUS75ggYv41bliGiolxzDKWJAq3eJ1MA=
 github.com/bep/gowebp v0.1.0 h1:4/iQpfnxHyXs3x/aTxMMdOpLEQQhFmF6G7EieWPTQyo=
@@ -219,7 +219,6 @@ github.com/fortytw2/leaktest v1.3.0 h1:u8491cBMTQ8ft8aeV+adlcytMZylmA5nnwwkRZjI8
 github.com/fortytw2/leaktest v1.3.0/go.mod h1:jDsjWgpAGjm2CA7WthBh/CdZYEPF31XHquHwclZch5g=
 github.com/frankban/quicktest v1.4.1/go.mod h1:36zfPVQyHxymz4cH7wlDmVwDrJuljRB60qkgn7rorfQ=
 github.com/frankban/quicktest v1.7.2/go.mod h1:jaStnuzAqU1AJdCO0l53JDCJrVDKcS03DbaAcR7Ks/o=
-github.com/frankban/quicktest v1.11.2/go.mod h1:K+q6oSqb0W0Ininfk863uOk1lMy69l/P6txr3mVT54s=
 github.com/frankban/quicktest v1.13.0/go.mod h1:qLE0fzW0VuyUAJgPU19zByoIr0HtCHN/r/VLSOOIySU=
 github.com/frankban/quicktest v1.14.2 h1:SPb1KFFmM+ybpEjPUhCCkZOM5xlovT5UbrMvWnXyBns=
 github.com/frankban/quicktest v1.14.2/go.mod h1:mgiwOwqx65TmIk1wJ6Q7wvnVMocbUorkibMOrVTHZps=
diff --git a/resources/resource_transformers/tocss/dartsass/client.go b/resources/resource_transformers/tocss/dartsass/client.go
index b5d05b30b41..647cf86aa01 100644
--- a/resources/resource_transformers/tocss/dartsass/client.go
+++ b/resources/resource_transformers/tocss/dartsass/client.go
@@ -18,6 +18,7 @@ package dartsass
 import (
 	"fmt"
 	"io"
+	"strings"
 
 	"github.com/gohugoio/hugo/helpers"
 	"github.com/gohugoio/hugo/hugolib/filesystems"
@@ -41,7 +42,19 @@ func New(fs *filesystems.SourceFilesystem, rs *resources.Spec) (*Client, error)
 		return nil, err
 	}
 
-	transpiler, err := godartsass.Start(godartsass.Options{})
+	transpiler, err := godartsass.Start(godartsass.Options{
+		LogEventHandler: func(event godartsass.LogEvent) {
+			message := strings.ReplaceAll(event.Message, stdinPrefix, "")
+			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)
+			}
+		},
+	})
 	if err != nil {
 		return nil, err
 	}
diff --git a/resources/resource_transformers/tocss/dartsass/transform.go b/resources/resource_transformers/tocss/dartsass/transform.go
index 57d9feadbee..aaf9d4bf813 100644
--- a/resources/resource_transformers/tocss/dartsass/transform.go
+++ b/resources/resource_transformers/tocss/dartsass/transform.go
@@ -39,7 +39,8 @@ import (
 
 const (
 	// See https://github.com/sass/dart-sass-embedded/issues/24
-	stdinPlaceholder           = "HUGOSTDIN"
+	// Note: This prefix must be all lower case.
+	stdinPrefix                = "hugostdin:"
 	dartSassEmbeddedBinaryName = "dart-sass-embedded"
 )
 
@@ -75,9 +76,14 @@ func (t *transform) Transform(ctx *resources.ResourceTransformationCtx) error {
 	}
 
 	baseDir := path.Dir(ctx.SourcePath)
+	filename := stdinPrefix
+
+	if ctx.SourcePath != "" {
+		filename += t.c.sfs.RealFilename(ctx.SourcePath)
+	}
 
 	args := godartsass.Args{
-		URL:          stdinPlaceholder,
+		URL:          filename,
 		IncludePaths: t.c.sfs.RealDirs(baseDir),
 		ImportResolver: importResolver{
 			baseDir: baseDir,
@@ -106,11 +112,8 @@ func (t *transform) Transform(ctx *resources.ResourceTransformationCtx) error {
 			start := sassErr.Span.Start
 			context := strings.TrimSpace(sassErr.Span.Context)
 			filename, _ := urlToFilename(sassErr.Span.Url)
-			if filename == stdinPlaceholder {
-				if ctx.SourcePath == "" {
-					return sassErr
-				}
-				filename = t.c.sfs.RealFilename(ctx.SourcePath)
+			if strings.HasPrefix(filename, stdinPrefix) {
+				filename = filename[len(stdinPrefix):]
 			}
 
 			offsetMatcher := func(m herrors.LineMatcher) bool {


Test patch:
diff --git a/hugolib/integrationtest_builder.go b/hugolib/integrationtest_builder.go
index 1bfa194bdc9..d49e29763c0 100644
--- a/hugolib/integrationtest_builder.go
+++ b/hugolib/integrationtest_builder.go
@@ -6,6 +6,7 @@ import (
 	"io"
 	"os"
 	"path/filepath"
+	"regexp"
 	"strings"
 	"sync"
 	"testing"
@@ -98,6 +99,12 @@ func (s *IntegrationTestBuilder) AssertLogContains(text string) {
 	s.Assert(s.logBuff.String(), qt.Contains, text)
 }
 
+func (s *IntegrationTestBuilder) AssertLogMatches(expression string) {
+	s.Helper()
+	re := regexp.MustCompile(expression)
+	s.Assert(re.MatchString(s.logBuff.String()), qt.IsTrue, qt.Commentf(s.logBuff.String()))
+}
+
 func (s *IntegrationTestBuilder) AssertBuildCountData(count int) {
 	s.Helper()
 	s.Assert(s.H.init.data.InitCount(), qt.Equals, count)
diff --git a/resources/resource_transformers/tocss/dartsass/integration_test.go b/resources/resource_transformers/tocss/dartsass/integration_test.go
index 9434b1d5233..a1ac1d59f13 100644
--- a/resources/resource_transformers/tocss/dartsass/integration_test.go
+++ b/resources/resource_transformers/tocss/dartsass/integration_test.go
@@ -18,6 +18,7 @@ import (
 
 	"github.com/gohugoio/hugo/hugolib"
 	"github.com/gohugoio/hugo/resources/resource_transformers/tocss/dartsass"
+	jww "github.com/spf13/jwalterweatherman"
 )
 
 func TestTransformIncludePaths(t *testing.T) {
@@ -164,3 +165,34 @@ zoo {
 
 	b.AssertFileContent("public/index.html", `T1: moo{color:#ccc}boo{color:green}zoo{color:pink}`)
 }
+
+func TestTransformLogging(t *testing.T) {
+	if !dartsass.Supports() {
+		t.Skip()
+	}
+
+	files := `
+-- assets/scss/main.scss --
+@warn "foo";
+@debug "bar";
+
+-- config.toml --
+disableKinds = ["term", "taxonomy", "section", "page"]
+-- layouts/index.html --
+{{ $cssOpts := (dict  "transpiler" "dartsass" ) }}
+{{ $r := resources.Get "scss/main.scss" |  toCSS $cssOpts   }}
+T1: {{ $r.Content }}
+	`
+
+	b := hugolib.NewIntegrationTestBuilder(
+		hugolib.IntegrationTestConfig{
+			T:           t,
+			TxtarString: files,
+			NeedsOsFS:   true,
+			LogLevel:    jww.LevelInfo,
+		}).Build()
+
+	b.AssertLogMatches(`WARN.*Dart Sass: foo`)
+	b.AssertLogMatches(`INFO.*Dart Sass: .*assets.*main.scss:1:0: bar`)
+
+}