mirror of
https://github.com/gohugoio/hugo.git
synced 2024-11-21 20:46:30 -05:00
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
This commit is contained in:
parent
1687a9a585
commit
eddcd2bac6
7 changed files with 241 additions and 162 deletions
145
tpl/css/css.go
145
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
|
||||
}
|
||||
|
|
|
@ -51,6 +51,9 @@ type TemplateFuncsNamespace struct {
|
|||
// This is the method receiver.
|
||||
Context func(ctx context.Context, v ...any) (any, error)
|
||||
|
||||
// OnCreated is called when all the namespaces are ready.
|
||||
OnCreated func(namespaces map[string]any)
|
||||
|
||||
// Additional info, aliases and examples, per method name.
|
||||
MethodMappings map[string]TemplateFuncMethodMapping
|
||||
}
|
||||
|
|
|
@ -31,6 +31,11 @@ func init() {
|
|||
Context: func(cctx context.Context, args ...any) (any, error) { return ctx, nil },
|
||||
}
|
||||
|
||||
ns.AddMethodMapping(ctx.Babel,
|
||||
[]string{"babel"},
|
||||
[][2]string{},
|
||||
)
|
||||
|
||||
return ns
|
||||
}
|
||||
|
||||
|
|
30
tpl/js/js.go
30
tpl/js/js.go
|
@ -15,9 +15,12 @@
|
|||
package js
|
||||
|
||||
import (
|
||||
"errors"
|
||||
|
||||
"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/js"
|
||||
"github.com/gohugoio/hugo/tpl/internal/resourcehelpers"
|
||||
)
|
||||
|
@ -28,13 +31,15 @@ func New(deps *deps.Deps) *Namespace {
|
|||
return &Namespace{}
|
||||
}
|
||||
return &Namespace{
|
||||
client: js.New(deps.BaseFs.Assets, deps.ResourceSpec),
|
||||
client: js.New(deps.BaseFs.Assets, deps.ResourceSpec),
|
||||
babelClient: babel.New(deps.ResourceSpec),
|
||||
}
|
||||
}
|
||||
|
||||
// Namespace provides template functions for the "js" namespace.
|
||||
type Namespace struct {
|
||||
client *js.Client
|
||||
client *js.Client
|
||||
babelClient *babel.Client
|
||||
}
|
||||
|
||||
// Build processes the given Resource with ESBuild.
|
||||
|
@ -62,3 +67,24 @@ func (ns *Namespace) Build(args ...any) (resource.Resource, error) {
|
|||
|
||||
return ns.client.Process(r, m)
|
||||
}
|
||||
|
||||
// Babel processes the given Resource with Babel.
|
||||
func (ns *Namespace) Babel(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
|
||||
}
|
||||
var options babel.Options
|
||||
if m != nil {
|
||||
options, err = babel.DecodeOptions(m)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
return ns.babelClient.Process(r, options)
|
||||
}
|
||||
|
|
|
@ -17,7 +17,9 @@ import (
|
|||
"context"
|
||||
|
||||
"github.com/gohugoio/hugo/deps"
|
||||
"github.com/gohugoio/hugo/tpl/css"
|
||||
"github.com/gohugoio/hugo/tpl/internal"
|
||||
"github.com/gohugoio/hugo/tpl/js"
|
||||
)
|
||||
|
||||
const name = "resources"
|
||||
|
@ -33,6 +35,22 @@ func init() {
|
|||
ns := &internal.TemplateFuncsNamespace{
|
||||
Name: name,
|
||||
Context: func(cctx context.Context, args ...any) (any, error) { return ctx, nil },
|
||||
OnCreated: func(m map[string]any) {
|
||||
for _, v := range m {
|
||||
switch v := v.(type) {
|
||||
case *css.Namespace:
|
||||
ctx.cssNs = v
|
||||
case *js.Namespace:
|
||||
ctx.jsNs = v
|
||||
}
|
||||
}
|
||||
if ctx.cssNs == nil {
|
||||
panic("css namespace not found")
|
||||
}
|
||||
if ctx.jsNs == nil {
|
||||
panic("js namespace not found")
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
ns.AddMethodMapping(ctx.Get,
|
||||
|
@ -57,21 +75,6 @@ func init() {
|
|||
[][2]string{},
|
||||
)
|
||||
|
||||
ns.AddMethodMapping(ctx.ToCSS,
|
||||
[]string{"toCSS"},
|
||||
[][2]string{},
|
||||
)
|
||||
|
||||
ns.AddMethodMapping(ctx.PostCSS,
|
||||
[]string{"postCSS"},
|
||||
[][2]string{},
|
||||
)
|
||||
|
||||
ns.AddMethodMapping(ctx.Babel,
|
||||
[]string{"babel"},
|
||||
[][2]string{},
|
||||
)
|
||||
|
||||
return ns
|
||||
}
|
||||
|
||||
|
|
|
@ -18,12 +18,12 @@ import (
|
|||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"sync"
|
||||
|
||||
"github.com/gohugoio/hugo/common/hugo"
|
||||
"github.com/gohugoio/hugo/common/maps"
|
||||
"github.com/gohugoio/hugo/common/paths"
|
||||
|
||||
"github.com/gohugoio/hugo/tpl/internal/resourcehelpers"
|
||||
"github.com/gohugoio/hugo/tpl/css"
|
||||
"github.com/gohugoio/hugo/tpl/js"
|
||||
|
||||
"github.com/gohugoio/hugo/resources/postpub"
|
||||
|
||||
|
@ -33,13 +33,9 @@ import (
|
|||
|
||||
"github.com/gohugoio/hugo/resources/resource_factories/bundler"
|
||||
"github.com/gohugoio/hugo/resources/resource_factories/create"
|
||||
"github.com/gohugoio/hugo/resources/resource_transformers/babel"
|
||||
"github.com/gohugoio/hugo/resources/resource_transformers/integrity"
|
||||
"github.com/gohugoio/hugo/resources/resource_transformers/minifier"
|
||||
"github.com/gohugoio/hugo/resources/resource_transformers/postcss"
|
||||
"github.com/gohugoio/hugo/resources/resource_transformers/templates"
|
||||
"github.com/gohugoio/hugo/resources/resource_transformers/tocss/dartsass"
|
||||
"github.com/gohugoio/hugo/resources/resource_transformers/tocss/scss"
|
||||
|
||||
"github.com/spf13/cast"
|
||||
)
|
||||
|
@ -50,26 +46,18 @@ func New(deps *deps.Deps) (*Namespace, error) {
|
|||
return &Namespace{}, nil
|
||||
}
|
||||
|
||||
scssClient, err := scss.New(deps.BaseFs.Assets, deps.ResourceSpec)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
minifyClient, err := minifier.New(deps.ResourceSpec)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &Namespace{
|
||||
deps: deps,
|
||||
scssClientLibSass: scssClient,
|
||||
createClient: create.New(deps.ResourceSpec),
|
||||
bundlerClient: bundler.New(deps.ResourceSpec),
|
||||
integrityClient: integrity.New(deps.ResourceSpec),
|
||||
minifyClient: minifyClient,
|
||||
postcssClient: postcss.New(deps.ResourceSpec),
|
||||
templatesClient: templates.New(deps.ResourceSpec, deps),
|
||||
babelClient: babel.New(deps.ResourceSpec),
|
||||
deps: deps,
|
||||
createClient: create.New(deps.ResourceSpec),
|
||||
bundlerClient: bundler.New(deps.ResourceSpec),
|
||||
integrityClient: integrity.New(deps.ResourceSpec),
|
||||
minifyClient: minifyClient,
|
||||
templatesClient: templates.New(deps.ResourceSpec, deps),
|
||||
}, nil
|
||||
}
|
||||
|
||||
|
@ -79,33 +67,16 @@ var _ resource.ResourceFinder = (*Namespace)(nil)
|
|||
type Namespace struct {
|
||||
deps *deps.Deps
|
||||
|
||||
createClient *create.Client
|
||||
bundlerClient *bundler.Client
|
||||
scssClientLibSass *scss.Client
|
||||
integrityClient *integrity.Client
|
||||
minifyClient *minifier.Client
|
||||
postcssClient *postcss.Client
|
||||
babelClient *babel.Client
|
||||
templatesClient *templates.Client
|
||||
createClient *create.Client
|
||||
bundlerClient *bundler.Client
|
||||
integrityClient *integrity.Client
|
||||
minifyClient *minifier.Client
|
||||
templatesClient *templates.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
|
||||
}
|
||||
|
||||
func (ns *Namespace) getscssClientDartSass() (*dartsass.Client, error) {
|
||||
var err error
|
||||
ns.scssClientDartSassInit.Do(func() {
|
||||
ns.scssClientDartSass, err = dartsass.New(ns.deps.BaseFs.Assets, ns.deps.ResourceSpec)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
ns.deps.BuildClosers.Add(ns.scssClientDartSass)
|
||||
})
|
||||
|
||||
return ns.scssClientDartSass, err
|
||||
// We moved some CSS and JS related functions to the css and js package in Hugo 0.128.0.
|
||||
// Keep this here until the deprecation period is over.
|
||||
cssNs *css.Namespace
|
||||
jsNs *js.Namespace
|
||||
}
|
||||
|
||||
// Copy copies r to the new targetPath in s.
|
||||
|
@ -337,89 +308,17 @@ func (ns *Namespace) Minify(r resources.ResourceTransformer) (resource.Resource,
|
|||
// ToCSS converts the given Resource to CSS. You can optional provide an Options object
|
||||
// as second argument. As an option, you can e.g. specify e.g. the target path (string)
|
||||
// for the converted CSS resource.
|
||||
// Deprecated: Moved to the css namespace in Hugo 0.128.0.
|
||||
func (ns *Namespace) ToCSS(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)
|
||||
hugo.Deprecate("resources.ToCSS", "Use css.SASS.", "v0.128.0")
|
||||
return ns.cssNs.Sass(args...)
|
||||
}
|
||||
|
||||
// PostCSS processes the given Resource with PostCSS
|
||||
// PostCSS processes the given Resource with PostCSS.
|
||||
// Deprecated: Moved to the css namespace in Hugo 0.128.0.
|
||||
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)
|
||||
hugo.Deprecate("resources.PostCSS", "Use css.PostCSS.", "v0.128.0")
|
||||
return ns.cssNs.PostCSS(args...)
|
||||
}
|
||||
|
||||
// PostProcess processes r after the build.
|
||||
|
@ -428,22 +327,8 @@ func (ns *Namespace) PostProcess(r resource.Resource) (postpub.PostPublishedReso
|
|||
}
|
||||
|
||||
// Babel processes the given Resource with Babel.
|
||||
// Deprecated: Moved to the js namespace in Hugo 0.128.0.
|
||||
func (ns *Namespace) Babel(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
|
||||
}
|
||||
var options babel.Options
|
||||
if m != nil {
|
||||
options, err = babel.DecodeOptions(m)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
return ns.babelClient.Process(r, options)
|
||||
hugo.Deprecate("resources.Babel", "Use js.Babel.", "v0.128.0")
|
||||
return ns.jsNs.Babel(args...)
|
||||
}
|
||||
|
|
|
@ -252,6 +252,9 @@ func newTemplateExecuter(d *deps.Deps) (texttemplate.Executer, map[string]reflec
|
|||
func createFuncMap(d *deps.Deps) map[string]any {
|
||||
funcMap := template.FuncMap{}
|
||||
|
||||
nsMap := make(map[string]any)
|
||||
var onCreated []func(namespaces map[string]any)
|
||||
|
||||
// Merge the namespace funcs
|
||||
for _, nsf := range internal.TemplateFuncsNamespaceRegistry {
|
||||
ns := nsf(d)
|
||||
|
@ -259,6 +262,11 @@ func createFuncMap(d *deps.Deps) map[string]any {
|
|||
panic(ns.Name + " is a duplicate template func")
|
||||
}
|
||||
funcMap[ns.Name] = ns.Context
|
||||
contextV, err := ns.Context(context.Background())
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
nsMap[ns.Name] = contextV
|
||||
for _, mm := range ns.MethodMappings {
|
||||
for _, alias := range mm.Aliases {
|
||||
if _, exists := funcMap[alias]; exists {
|
||||
|
@ -267,6 +275,14 @@ func createFuncMap(d *deps.Deps) map[string]any {
|
|||
funcMap[alias] = mm.Method
|
||||
}
|
||||
}
|
||||
|
||||
if ns.OnCreated != nil {
|
||||
onCreated = append(onCreated, ns.OnCreated)
|
||||
}
|
||||
}
|
||||
|
||||
for _, f := range onCreated {
|
||||
f(nsMap)
|
||||
}
|
||||
|
||||
if d.OverloadedTemplateFuncs != nil {
|
||||
|
|
Loading…
Reference in a new issue