diff options
author | Bjørn Erik Pedersen <[email protected]> | 2024-06-23 12:10:35 +0200 |
---|---|---|
committer | Bjørn Erik Pedersen <[email protected]> | 2024-06-25 15:48:02 +0200 |
commit | eddcd2bac6bfd3cc0ac1a3b38bf8c4ae452ea23b (patch) | |
tree | 10116d4362d0a9dae56539cc8f9d852c2a4a66ce /tpl/css | |
parent | 1687a9a5852e83a1c52e647e92882d9e6bfc109a (diff) | |
download | hugo-eddcd2bac6bfd3cc0ac1a3b38bf8c4ae452ea23b.tar.gz hugo-eddcd2bac6bfd3cc0ac1a3b38bf8c4ae452ea23b.zip |
Clean up the css related template funcs package structure
Deprecate and move:
* resources.ToCSS => css.SASS
* resources.PostProcess => css.PostProcess
* resources.Babel => js.Babel
Updates #12618
Diffstat (limited to 'tpl/css')
-rw-r--r-- | tpl/css/css.go | 145 |
1 files changed, 143 insertions, 2 deletions
diff --git a/tpl/css/css.go b/tpl/css/css.go index 51fa1d518..145cb3aad 100644 --- a/tpl/css/css.go +++ b/tpl/css/css.go @@ -2,17 +2,40 @@ package css import ( "context" + "errors" + "fmt" + "sync" + "github.com/gohugoio/hugo/common/maps" + "github.com/gohugoio/hugo/common/paths" "github.com/gohugoio/hugo/common/types/css" "github.com/gohugoio/hugo/deps" + "github.com/gohugoio/hugo/resources" + "github.com/gohugoio/hugo/resources/resource" + "github.com/gohugoio/hugo/resources/resource_transformers/babel" + "github.com/gohugoio/hugo/resources/resource_transformers/postcss" + "github.com/gohugoio/hugo/resources/resource_transformers/tocss/dartsass" + "github.com/gohugoio/hugo/resources/resource_transformers/tocss/scss" "github.com/gohugoio/hugo/tpl/internal" + "github.com/gohugoio/hugo/tpl/internal/resourcehelpers" "github.com/spf13/cast" ) const name = "css" // Namespace provides template functions for the "css" namespace. -type Namespace struct{} +type Namespace struct { + d *deps.Deps + scssClientLibSass *scss.Client + postcssClient *postcss.Client + babelClient *babel.Client + + // The Dart Client requires a os/exec process, so only + // create it if we really need it. + // This is mostly to avoid creating one per site build test. + scssClientDartSassInit sync.Once + scssClientDartSass *dartsass.Client +} // Quoted returns a string that needs to be quoted in CSS. func (ns *Namespace) Quoted(v any) css.QuotedString { @@ -26,17 +49,135 @@ func (ns *Namespace) Unquoted(v any) css.UnquotedString { return css.UnquotedString(s) } +// PostCSS processes the given Resource with PostCSS. +func (ns *Namespace) PostCSS(args ...any) (resource.Resource, error) { + if len(args) > 2 { + return nil, errors.New("must not provide more arguments than resource object and options") + } + + r, m, err := resourcehelpers.ResolveArgs(args) + if err != nil { + return nil, err + } + + return ns.postcssClient.Process(r, m) +} + +// Sass processes the given Resource with Sass. +func (ns *Namespace) Sass(args ...any) (resource.Resource, error) { + if len(args) > 2 { + 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 + ) + + r, targetPath, ok = resourcehelpers.ResolveIfFirstArgIsString(args) + + if !ok { + r, m, err = resourcehelpers.ResolveArgs(args) + if err != nil { + return nil, err + } + } + + if m != nil { + if t, _, found := maps.LookupEqualFold(m, "transpiler"); found { + switch t { + case transpilerDart, transpilerLibSass: + transpiler = cast.ToString(t) + default: + return nil, fmt.Errorf("unsupported transpiler %q; valid values are %q or %q", t, transpilerLibSass, transpilerDart) + } + } + } + + if transpiler == transpilerLibSass { + var options scss.Options + if targetPath != "" { + options.TargetPath = paths.ToSlashTrimLeading(targetPath) + } else if m != nil { + options, err = scss.DecodeOptions(m) + if err != nil { + return nil, err + } + } + + return ns.scssClientLibSass.ToCSS(r, options) + } + + if m == nil { + m = make(map[string]any) + } + if targetPath != "" { + m["targetPath"] = targetPath + } + + client, err := ns.getscssClientDartSass() + if err != nil { + return nil, err + } + + return client.ToCSS(r, m) +} + func init() { f := func(d *deps.Deps) *internal.TemplateFuncsNamespace { - ctx := &Namespace{} + scssClient, err := scss.New(d.BaseFs.Assets, d.ResourceSpec) + if err != nil { + panic(err) + } + ctx := &Namespace{ + d: d, + scssClientLibSass: scssClient, + postcssClient: postcss.New(d.ResourceSpec), + babelClient: babel.New(d.ResourceSpec), + } ns := &internal.TemplateFuncsNamespace{ Name: name, Context: func(cctx context.Context, args ...any) (any, error) { return ctx, nil }, } + ns.AddMethodMapping(ctx.Sass, + []string{"toCSS"}, + [][2]string{}, + ) + + ns.AddMethodMapping(ctx.PostCSS, + []string{"postCSS"}, + [][2]string{}, + ) + return ns } internal.AddTemplateFuncsNamespace(f) } + +func (ns *Namespace) getscssClientDartSass() (*dartsass.Client, error) { + var err error + ns.scssClientDartSassInit.Do(func() { + ns.scssClientDartSass, err = dartsass.New(ns.d.BaseFs.Assets, ns.d.ResourceSpec) + if err != nil { + return + } + ns.d.BuildClosers.Add(ns.scssClientDartSass) + }) + + return ns.scssClientDartSass, err +} |