Repository: gohugoio/hugo (language: go)

Issue:
Dart Sass transpiler error in Hugo v0.123.0
### What version of Hugo are you using (`hugo version`)?

```
hugo v0.123.0-3c8a4713908e48e6523f058ca126710397aa4ed5+extended darwin/arm64 BuildDate=2024-02-19T16:32:38Z VendorInfo=brew
```
### Does this issue reproduce with the latest release?

Yes

### Context

When upgrading Hugo from `v0.122.0` to `v0.123.0` I get a Dart Sass transpiler error. Below the error logs (specific to the Hinode theme):

```bash
Start building sites … 
hugo v0.123.0-3c8a4713908e48e6523f058ca126710397aa4ed5+extended darwin/arm64 BuildDate=2024-02-19T16:32:38Z VendorInfo=brew

ERROR render of "page" failed: execute of template failed: template: partials/head/head.html:8:7: executing "head" at <partialCached "head/stylesheet-core.html" .>: error calling partialCached: "/Users/mark/Development/GitHub/gethinode/hinode/layouts/partials/head/stylesheet-core.html:3:3": execute of template failed: template: partials/head/stylesheet-core.html:3:3: executing "partials/head/stylesheet-core.html" at <partial "head/stylesheet.html">: error calling partial: "/Users/mark/Development/GitHub/gethinode/hinode/layouts/partials/head/stylesheet.html:60:12": execute of template failed: template: partials/head/stylesheet.html:60:12: executing "partials/head/stylesheet.html" at <partial "head/icons.html" (dict "css" $css)>: error calling partial: "/Users/mark/Development/GitHub/gethinode/hinode/layouts/partials/head/icons.html:22:54": execute of template failed: template: partials/head/icons.html:22:54: executing "partials/head/icons.html" at <$css.Content>: error calling Content: TOCSS-DART: failed to transform "css/main.css" (text/x-scss): "/Users/mark/Development/GitHub/gethinode/hinode/_vendor/github.com/gethinode/mod-bootstrap/assets/scss/modules/bootstrap/_mixins-dart.scss:9:8": Can't find stylesheet to import.
ERROR TOCSS-DART: failed to transform "css/main.css" (text/x-scss): "/Users/mark/Development/GitHub/gethinode/hinode/_vendor/github.com/gethinode/mod-bootstrap/assets/scss/modules/bootstrap/_mixins-dart.scss:9:8": Can't find stylesheet to import.
Built in 1035 ms
Error: error building site: TOCSS-DART: failed to transform "css/main.css" (text/x-scss): "/Users/mark/Development/GitHub/gethinode/hinode/_vendor/github.com/gethinode/mod-bootstrap/assets/scss/modules/bootstrap/_mixins-dart.scss:9:8": Can't find stylesheet to import.
```

The full environment:

```bash
hugo v0.123.0-3c8a4713908e48e6523f058ca126710397aa4ed5+extended darwin/arm64 BuildDate=2024-02-19T16:32:38Z VendorInfo=brew
GOOS="darwin"
GOARCH="arm64"
GOVERSION="go1.22.0"
github.com/sass/libsass="3.6.5"
github.com/webmproject/libwebp="v1.3.2"
github.com/sass/dart-sass/protocol="2.5.0"
github.com/sass/dart-sass/compiler="1.71.0"
github.com/sass/dart-sass/implementation="1.71.0"
```

The error does not occur when using `libsass`.

## To reproduce

```bash
git clone https://github.com/gethinode/hinode.git
cd hinode
hugo mod vendor
hugo server -s exampleSite
```

Switching to `libsass` in `exampleSite/config/_default/params.toml` solves the issue:

```
[main]
    [main.build]
        transpiler = "libsass"
```


Discussion / hints:
I had a similar error message yesterday: In my case it was caused by the fact that including a CSS file from a theme using a SCSS `import` as part of the site SCSS didn't resolve. I suspect that the search path of the site either doesn't include assets  from the theme anymore or that this now requires a explicit mount setup.
I solved it by just copying the CSS file fro the theme to the site.
@markdumay 

When I do this:

```text
git clone https://github.com/gethinode/hinode.git
cd hinode
hugo mod vendor
hugo server -s exampleSite
```

I get this:

<details>
<summary>console log</summary>

```text
Start building sites … 
hugo v0.123.0-e8cc785a589bb18c9336880d662a659f29bb57f3+extended linux/amd64 BuildDate=2024-02-19T17:59:28Z

ERROR render of "page" failed: execute of template failed: template: partials/head/head.html:8:7: executing "head" at <partialCached "head/stylesheet-core.html" .>: error calling partialCached: "/home/jmooring/temp/hinode/layouts/partials/head/stylesheet-core.html:3:3": execute of template failed: template: partials/head/stylesheet-core.html:3:3: executing "partials/head/stylesheet-core.html" at <partial "head/stylesheet.html">: error calling partial: "/home/jmooring/temp/hinode/layouts/partials/head/stylesheet.html:60:12": execute of template failed: template: partials/head/stylesheet.html:60:12: executing "partials/head/stylesheet.html" at <partial "head/icons.html" (dict "css" $css)>: error calling partial: "/home/jmooring/temp/hinode/layouts/partials/head/icons.html:22:54": execute of template failed: template: partials/head/icons.html:22:54: executing "partials/head/icons.html" at <$css.Content>: error calling Content: TOCSS-DART: failed to transform "css/main.css" (text/x-scss): "/home/jmooring/temp/hinode/_vendor/github.com/gethinode/mod-bootstrap/assets/scss/modules/bootstrap/_mixins-dart.scss:9:8": Can't find stylesheet to import.
ERROR render of "section" failed: execute of template failed: template: partials/head/head.html:8:7: executing "head" at <partialCached "head/stylesheet-core.html" .>: error calling partialCached: "/home/jmooring/temp/hinode/layouts/partials/head/stylesheet-core.html:3:3": execute of template failed: template: partials/head/stylesheet-core.html:3:3: executing "partials/head/stylesheet-core.html" at <partial "head/stylesheet.html">: error calling partial: "/home/jmooring/temp/hinode/layouts/partials/head/stylesheet.html:60:12": execute of template failed: template: partials/head/stylesheet.html:60:12: executing "partials/head/stylesheet.html" at <partial "head/icons.html" (dict "css" $css)>: error calling partial: "/home/jmooring/temp/hinode/layouts/partials/head/icons.html:22:54": execute of template failed: template: partials/head/icons.html:22:54: executing "partials/head/icons.html" at <$css.Content>: error calling Content: TOCSS-DART: failed to transform "css/main.css" (text/x-scss): "/home/jmooring/temp/hinode/_vendor/github.com/gethinode/mod-bootstrap/assets/scss/modules/bootstrap/_mixins-dart.scss:9:8": Can't find stylesheet to import.
ERROR TOCSS-DART: failed to transform "css/main.css" (text/x-scss): "/home/jmooring/temp/hinode/_vendor/github.com/gethinode/mod-bootstrap/assets/scss/modules/bootstrap/_mixins-dart.scss:9:8": Can't find stylesheet to import.
Built in 33402 ms
Error: error building site: TOCSS-DART: failed to transform "css/main.css" (text/x-scss): "/home/jmooring/temp/hinode/_vendor/github.com/gethinode/mod-bootstrap/assets/scss/modules/bootstrap/_mixins-dart.scss:9:8": Can't find stylesheet to import.

```
</details>
<br>

And `main.build.transpiler` is already set to `libsass`, so I think transpiler selection is a red herring.
Disregard previous comment. I changed the value in the root, not in the example site.
See also https://discourse.gohugo.io/t/unable-to-import-scss-by-relative-path-when-using-v0-123-0/48360
@cmahnke to be helpful, you could provide a simple test case not link to another complex setup.
OK; I have found the cause of this, I just need to create a failing test for it. I will push a patch release later tonight (Norway time).
Great @bep, thanks a lot for your quick response!

Fix patch:
diff --git a/commands/server.go b/commands/server.go
index 78155521f34..d08bc527793 100644
--- a/commands/server.go
+++ b/commands/server.go
@@ -1087,7 +1087,7 @@ func (s *staticSyncer) syncsStaticEvents(staticEvents []fsnotify.Event) error {
 
 			fromPath := ev.Name
 
-			relPath, found := sourceFs.MakePathRelative(fromPath)
+			relPath, found := sourceFs.MakePathRelative(fromPath, true)
 
 			if !found {
 				// Not member of this virtual host.
diff --git a/hugolib/filesystems/basefs.go b/hugolib/filesystems/basefs.go
index b37fb8cb40c..25c58d516b9 100644
--- a/hugolib/filesystems/basefs.go
+++ b/hugolib/filesystems/basefs.go
@@ -336,7 +336,7 @@ func (s *SourceFilesystems) ResolvePaths(filename string, checkExists bool) []hu
 // It will return an empty string if the filename is not a member of a static filesystem.
 func (s SourceFilesystems) MakeStaticPathRelative(filename string) string {
 	for _, staticFs := range s.Static {
-		rel, _ := staticFs.MakePathRelative(filename)
+		rel, _ := staticFs.MakePathRelative(filename, true)
 		if rel != "" {
 			return rel
 		}
@@ -345,8 +345,8 @@ func (s SourceFilesystems) MakeStaticPathRelative(filename string) string {
 }
 
 // MakePathRelative creates a relative path from the given filename.
-func (d *SourceFilesystem) MakePathRelative(filename string) (string, bool) {
-	cps, err := d.ReverseLookup(filename)
+func (d *SourceFilesystem) MakePathRelative(filename string, checkExists bool) (string, bool) {
+	cps, err := d.ReverseLookup(filename, checkExists)
 	if err != nil {
 		panic(err)
 	}
@@ -358,11 +358,11 @@ func (d *SourceFilesystem) MakePathRelative(filename string) (string, bool) {
 }
 
 // ReverseLookup returns the component paths for the given filename.
-func (d *SourceFilesystem) ReverseLookup(filename string) ([]hugofs.ComponentPath, error) {
+func (d *SourceFilesystem) ReverseLookup(filename string, checkExists bool) ([]hugofs.ComponentPath, error) {
 	var cps []hugofs.ComponentPath
 	hugofs.WalkFilesystems(d.Fs, func(fs afero.Fs) bool {
 		if rfs, ok := fs.(hugofs.ReverseLookupProvder); ok {
-			if c, err := rfs.ReverseLookup(filename, true); err == nil {
+			if c, err := rfs.ReverseLookup(filename, checkExists); err == nil {
 				cps = append(cps, c...)
 			}
 		}
diff --git a/hugolib/pagecollections.go b/hugolib/pagecollections.go
index 505b10bd772..58c646334b4 100644
--- a/hugolib/pagecollections.go
+++ b/hugolib/pagecollections.go
@@ -243,7 +243,7 @@ func (c *pageFinder) getContentNodeFromRefReverseLookup(ref string, fi hugofs.Fi
 
 	realFilename := filepath.Join(dir, ref)
 
-	pcs, err := s.BaseFs.Content.ReverseLookup(realFilename)
+	pcs, err := s.BaseFs.Content.ReverseLookup(realFilename, true)
 	if err != nil {
 		return nil, err
 	}
diff --git a/resources/resource_transformers/js/options.go b/resources/resource_transformers/js/options.go
index df32e701298..1c29ad67cf9 100644
--- a/resources/resource_transformers/js/options.go
+++ b/resources/resource_transformers/js/options.go
@@ -218,7 +218,7 @@ func createBuildPlugins(depsManager identity.Manager, c *Client, opts Options) (
 		isStdin := args.Importer == stdinImporter
 		var relDir string
 		if !isStdin {
-			rel, found := fs.MakePathRelative(args.Importer)
+			rel, found := fs.MakePathRelative(args.Importer, true)
 			if !found {
 				// Not in any of the /assets folders.
 				// This is an import from a node_modules, let
diff --git a/resources/resource_transformers/tocss/dartsass/transform.go b/resources/resource_transformers/tocss/dartsass/transform.go
index 73eca6a5384..a9600f380ad 100644
--- a/resources/resource_transformers/tocss/dartsass/transform.go
+++ b/resources/resource_transformers/tocss/dartsass/transform.go
@@ -138,12 +138,13 @@ func (t importResolver) CanonicalizeURL(url string) (string, error) {
 	if url == sass.HugoVarsNamespace {
 		return url, nil
 	}
+
 	filePath, isURL := paths.UrlToFilename(url)
 	var prevDir string
 	var pathDir string
 	if isURL {
 		var found bool
-		prevDir, found = t.c.sfs.MakePathRelative(filepath.Dir(filePath))
+		prevDir, found = t.c.sfs.MakePathRelative(filepath.Dir(filePath), false)
 
 		if !found {
 			// Not a member of this filesystem, let Dart Sass handle it.
diff --git a/resources/resource_transformers/tocss/scss/tocss.go b/resources/resource_transformers/tocss/scss/tocss.go
index a4c4e6d8ecc..a3f2a5289a7 100644
--- a/resources/resource_transformers/tocss/scss/tocss.go
+++ b/resources/resource_transformers/tocss/scss/tocss.go
@@ -86,7 +86,7 @@ func (t *toCSSTransformation) Transform(ctx *resources.ResourceTransformationCtx
 		if prev == "stdin" {
 			prevDir = baseDir
 		} else {
-			prevDir, _ = t.c.sfs.MakePathRelative(filepath.Dir(prev))
+			prevDir, _ = t.c.sfs.MakePathRelative(filepath.Dir(prev), false)
 
 			if prevDir == "" {
 				// Not a member of this filesystem. Let LibSASS handle it.


Test patch:
diff --git a/hugolib/filesystems/basefs_test.go b/hugolib/filesystems/basefs_test.go
index 5398055ed84..ebbb378d317 100644
--- a/hugolib/filesystems/basefs_test.go
+++ b/hugolib/filesystems/basefs_test.go
@@ -380,11 +380,11 @@ Main.
 `
 	b := hugolib.Test(t, files)
 
-	rel, found := b.H.BaseFs.Assets.MakePathRelative(filepath.FromSlash("/themes/t1/src/main.js"))
+	rel, found := b.H.BaseFs.Assets.MakePathRelative(filepath.FromSlash("/themes/t1/src/main.js"), true)
 	b.Assert(found, qt.Equals, true)
 	b.Assert(rel, qt.Equals, filepath.FromSlash("foo/bar/main.js"))
 
-	rel, found = b.H.BaseFs.Assets.MakePathRelative(filepath.FromSlash("/bar.txt"))
+	rel, found = b.H.BaseFs.Assets.MakePathRelative(filepath.FromSlash("/bar.txt"), true)
 	b.Assert(found, qt.Equals, true)
 	b.Assert(rel, qt.Equals, filepath.FromSlash("foo/baz.txt"))
 }
@@ -460,7 +460,7 @@ Home.
 	b.AssertFileContent("public/index.html", "Home.")
 
 	stat := func(path string) hugofs.FileMetaInfo {
-		ps, err := b.H.BaseFs.Content.ReverseLookup(filepath.FromSlash(path))
+		ps, err := b.H.BaseFs.Content.ReverseLookup(filepath.FromSlash(path), true)
 		b.Assert(err, qt.IsNil)
 		b.Assert(ps, qt.HasLen, 1)
 		first := ps[0]