tpl/css: Fix external source maps

Fixes #14620
This commit is contained in:
Bjørn Erik Pedersen
2026-03-13 16:30:06 +01:00
parent a7cbcf15f0
commit e431f90bc6
4 changed files with 58 additions and 28 deletions
+6 -1
View File
@@ -225,7 +225,12 @@ func (c *BuildClient) Build(opts Options) (api.BuildResult, error) {
}
return ss
}
return ""
if strings.HasPrefix(s, opts.OutDir) {
// This is an output file, not a source file.
return ""
}
// s is already the absolute filename set by the Hugo resolve plugin.
return s
}
return s
}); err != nil {
+21 -15
View File
@@ -46,7 +46,27 @@ func fixSourceMap(s []byte, resolve func(string) string) ([]byte, error) {
return nil, err
}
sm.Sources = fixSourceMapSources(sm.Sources, resolve)
hasSourcesContent := len(sm.SourcesContent) == len(sm.Sources)
var sources []string
var sourcesContent []string
for i, src := range sm.Sources {
if resolved := resolve(src); resolved != "" {
// Absolute filenames works fine on U*ix (tested in Chrome on MacOs), but works very poorly on Windows (again Chrome).
// So, convert it to a URL.
if u, err := paths.UrlFromFilename(resolved); err == nil {
sources = append(sources, u.String())
if hasSourcesContent {
sourcesContent = append(sourcesContent, sm.SourcesContent[i])
}
}
}
}
sm.Sources = sources
if hasSourcesContent {
sm.SourcesContent = sourcesContent
}
b, err := json.Marshal(sm)
if err != nil {
@@ -56,20 +76,6 @@ func fixSourceMap(s []byte, resolve func(string) string) ([]byte, error) {
return b, nil
}
func fixSourceMapSources(s []string, resolve func(string) string) []string {
var result []string
for _, src := range s {
if s := resolve(src); s != "" {
// Absolute filenames works fine on U*ix (tested in Chrome on MacOs), but works very poorly on Windows (again Chrome).
// So, convert it to a URL.
if u, err := paths.UrlFromFilename(s); err == nil {
result = append(result, u.String())
}
}
}
return result
}
// Used in tests.
func SourcesFromSourceMap(s string) []string {
var sm sourceMap
@@ -228,7 +228,7 @@ TS2: {{ template "print" $ts2 }}
}
}
checkMap("public/js/main.js.map", 4)
checkMap("public/js/main.js.map", 5)
}
func TestBuildError(t *testing.T) {
+30 -11
View File
@@ -17,8 +17,10 @@ import (
"strings"
"testing"
qt "github.com/frankban/quicktest"
"github.com/gohugoio/hugo/htesting"
"github.com/gohugoio/hugo/hugolib"
"github.com/gohugoio/hugo/internal/js/esbuild"
)
func TestCSSBuild(t *testing.T) {
@@ -165,30 +167,45 @@ span { background: green; }
article { background: yellow; }
-- layouts/home.html --
{{ with resources.Get "css/main.css" }}
{{ $opts := (dict "minify" false "sourceMap" "SOURCE_MAP" "sourcesContent" SOURCES_CONTENT "loaders" (dict ".png" "dataurl"))}}
{{ $opts := (dict "minify" MINIFY "sourceMap" "SOURCE_MAP" "sourcesContent" SOURCES_CONTENT "loaders" (dict ".png" "dataurl"))}}
{{ with . | css.Build $opts }}
<link rel="stylesheet" href="{{ .RelPermalink }}" />
{{ end }}
{{ end }}
`
r := strings.NewReplacer(
"SOURCE_MAP", "linked",
"SOURCES_CONTENT", "true",
var (
r *strings.Replacer
files string
b *hugolib.IntegrationTestBuilder
)
files := r.Replace(filesTemplate)
for _, minify := range []string{"true", "false"} {
b := hugolib.Test(t, files, hugolib.TestOptOsFs())
b.AssertFileContent("public/css/main.css", "/*# sourceMappingURL=main.css.map */")
b.AssertFileContent("public/css/main.css.map",
`"sourcesContent":["p { background: red; }"`,
"AAAA;AAAI,cAAY;AAAK",
)
r = strings.NewReplacer(
"SOURCE_MAP", "linked",
"SOURCES_CONTENT", "true",
"MINIFY", minify,
)
files = r.Replace(filesTemplate)
b = hugolib.Test(t, files, hugolib.TestOptOsFs())
b.AssertFileContent("public/css/main.css", "/*# sourceMappingURL=main.css.map */")
b.AssertFileContent("public/css/main.css.map",
`"sourcesContent":["`,
`"mappings":"`,
)
sources := esbuild.SourcesFromSourceMap(b.FileContent("public/css/main.css.map"))
// main.css + foo.css + bar.css + baz.css = 4 sources.
b.Assert(len(sources), qt.Equals, 4)
}
r = strings.NewReplacer(
"SOURCE_MAP", "external",
"SOURCES_CONTENT", "true",
"MINIFY", "false",
)
files = r.Replace(filesTemplate)
@@ -203,6 +220,7 @@ article { background: yellow; }
r = strings.NewReplacer(
"SOURCE_MAP", "external",
"SOURCES_CONTENT", "false",
"MINIFY", "false",
)
files = r.Replace(filesTemplate)
@@ -216,6 +234,7 @@ article { background: yellow; }
r = strings.NewReplacer(
"SOURCE_MAP", "inline",
"SOURCES_CONTENT", "false",
"MINIFY", "false",
)
files = r.Replace(filesTemplate)