mirror of
https://github.com/gohugoio/hugo.git
synced 2026-09-01 03:02:38 +00:00
Compare commits
98 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| da2a8e6402 | |||
| a4892a07b4 | |||
| cb98e9061b | |||
| 5fa97ee964 | |||
| 4d38f47250 | |||
| 80f793c38d | |||
| a9079d7a63 | |||
| 4914b7f18c | |||
| 9e06fd3394 | |||
| 9c2b2414d2 | |||
| ab21433689 | |||
| 23fcfb7f74 | |||
| 47bf2fcbe2 | |||
| 16fb2cae88 | |||
| 2bedcf3d18 | |||
| 935999e2fa | |||
| 20c3bae2c4 | |||
| 29b6e133a8 | |||
| 7f8ab74681 | |||
| 59bcc098cf | |||
| e26ba752d2 | |||
| bcf07fa639 | |||
| b6a7568131 | |||
| acf01bfb78 | |||
| 27b22cd87e | |||
| a2488b1c95 | |||
| 8f60c0c1ec | |||
| 9dc608084b | |||
| a349aafb7f | |||
| b8fbd4a578 | |||
| e2b2092ce6 | |||
| f4df7b88b3 | |||
| 3d9bd404ee | |||
| 5f5e55aa8d | |||
| 0baa4f9837 | |||
| aaaf1c8df5 | |||
| d3d4ab41a9 | |||
| 28d844642a | |||
| eb5fd3127f | |||
| 3ed28e4bfe | |||
| db14238ba3 | |||
| 3f64b5a3de | |||
| 66904097e0 | |||
| e54139c85b | |||
| 3710a5ec7e | |||
| 705e3cd5f5 | |||
| 8c61fd2541 | |||
| d3145e4e5d | |||
| 743a1da3ef | |||
| 123901b741 | |||
| 71fd79a3f4 | |||
| c4a530f104 | |||
| 272484f8bf | |||
| de4e466036 | |||
| c23a0c4a0f | |||
| a95670b981 | |||
| 46bdc03885 | |||
| 5160c7efa5 | |||
| e2dd4cd05f | |||
| e509cac533 | |||
| fd38171810 | |||
| 2eca1b3cc1 | |||
| 625162674d | |||
| a692278bc6 | |||
| d4016dd5cd | |||
| 4910312ee7 | |||
| 1b5f78b6b7 | |||
| d5d0f420d8 | |||
| 5993afa4c5 | |||
| d1b4458536 | |||
| 274852bcf2 | |||
| 37a2d5eb4e | |||
| 4c95389c25 | |||
| 3af8bded26 | |||
| 46da0b7aaa | |||
| 75f56b4ce6 | |||
| d234a963eb | |||
| b84644c008 | |||
| a9d19dbdd6 | |||
| 12d713176f | |||
| 6b65b2fae6 | |||
| 1768684d8b | |||
| 9aec42c545 | |||
| eb0ed33dfd | |||
| 6a246d1152 | |||
| ef0e7149d6 | |||
| c32094ace1 | |||
| a262fd4ddb | |||
| f0d32455d2 | |||
| e8bc8e6d02 | |||
| f9b3c0f486 | |||
| 11fcda971c | |||
| f31375d4cc | |||
| 6415b599be | |||
| 1e9b87f760 | |||
| 275c0acbf6 | |||
| f9163155d3 | |||
| 79a17d9e55 |
@@ -4,7 +4,7 @@ parameters:
|
||||
defaults: &defaults
|
||||
resource_class: large
|
||||
docker:
|
||||
- image: bepsays/ci-hugoreleaser:1.22000.20100
|
||||
- image: bepsays/ci-hugoreleaser:1.22100.20100
|
||||
environment: &buildenv
|
||||
GOMODCACHE: /root/project/gomodcache
|
||||
version: 2
|
||||
@@ -60,7 +60,7 @@ jobs:
|
||||
environment:
|
||||
<<: [*buildenv]
|
||||
docker:
|
||||
- image: bepsays/ci-hugoreleaser-linux-arm64:1.22000.20100
|
||||
- image: bepsays/ci-hugoreleaser-linux-arm64:1.22100.20100
|
||||
steps:
|
||||
- *restore-cache
|
||||
- &attach-workspace
|
||||
|
||||
@@ -122,8 +122,6 @@ cd hugo
|
||||
go install
|
||||
```
|
||||
|
||||
>Note: Some Go tools may not be fully updated to support Go Modules yet. One example would be LiteIDE. Follow [this workaround](https://github.com/visualfc/liteide/issues/986#issuecomment-428117702) for how to continue to work with Hugo below `GOPATH`.
|
||||
|
||||
For some convenient build and test targets, you also will want to install Mage:
|
||||
|
||||
```bash
|
||||
|
||||
@@ -33,7 +33,7 @@ A fast and flexible static site generator built with love by [bep], [spf13], and
|
||||
[](https://github.com/gohugoio/hugo/actions?query=workflow%3ATest)
|
||||
[](https://goreportcard.com/report/github.com/gohugoio/hugo)
|
||||
|
||||
[Website] | [Installation] | [Documentation] | [Support] | [Contributing] | [Twitter]
|
||||
[Website] | [Installation] | [Documentation] | [Support] | [Contributing] | <a rel="me" href="https://fosstodon.org/@gohugoio">Mastodon</a>
|
||||
|
||||
## Overview
|
||||
|
||||
|
||||
+11
-18
@@ -38,6 +38,7 @@ import (
|
||||
|
||||
"github.com/gohugoio/hugo/common/hstrings"
|
||||
"github.com/gohugoio/hugo/common/htime"
|
||||
"github.com/gohugoio/hugo/common/hugo"
|
||||
"github.com/gohugoio/hugo/common/loggers"
|
||||
"github.com/gohugoio/hugo/common/paths"
|
||||
"github.com/gohugoio/hugo/config"
|
||||
@@ -50,9 +51,7 @@ import (
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
var (
|
||||
errHelp = errors.New("help requested")
|
||||
)
|
||||
var errHelp = errors.New("help requested")
|
||||
|
||||
// Execute executes a command.
|
||||
func Execute(args []string) error {
|
||||
@@ -182,11 +181,9 @@ func (r *rootCommand) ConfigFromConfig(key int32, oldConf *commonConfig) (*commo
|
||||
cfg: oldConf.cfg,
|
||||
fs: fs,
|
||||
}, nil
|
||||
|
||||
})
|
||||
|
||||
return cc, err
|
||||
|
||||
}
|
||||
|
||||
func (r *rootCommand) ConfigFromProvider(key int32, cfg config.Provider) (*commonConfig, error) {
|
||||
@@ -211,7 +208,7 @@ func (r *rootCommand) ConfigFromProvider(key int32, cfg config.Provider) (*commo
|
||||
if !cfg.IsSet("workingDir") {
|
||||
cfg.Set("workingDir", dir)
|
||||
} else {
|
||||
if err := os.MkdirAll(cfg.GetString("workingDir"), 0777); err != nil {
|
||||
if err := os.MkdirAll(cfg.GetString("workingDir"), 0o777); err != nil {
|
||||
return nil, fmt.Errorf("failed to create workingDir: %w", err)
|
||||
}
|
||||
}
|
||||
@@ -303,7 +300,6 @@ func (r *rootCommand) ConfigFromProvider(key int32, cfg config.Provider) (*commo
|
||||
})
|
||||
|
||||
return cc, err
|
||||
|
||||
}
|
||||
|
||||
func (r *rootCommand) HugFromConfig(conf *commonConfig) (*hugolib.HugoSites, error) {
|
||||
@@ -348,7 +344,6 @@ func (r *rootCommand) Run(ctx context.Context, cd *simplecobra.Commandeer, args
|
||||
err := b.build()
|
||||
return err
|
||||
}()
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -434,26 +429,26 @@ func (r *rootCommand) createLogger(running bool) (loggers.Logger, error) {
|
||||
}
|
||||
} else {
|
||||
if r.verbose {
|
||||
helpers.Deprecated("--verbose", "use --logLevel info", false)
|
||||
hugo.Deprecate("--verbose", "use --logLevel info", "v0.114.0")
|
||||
hugo.Deprecate("--verbose", "use --logLevel info", "v0.114.0")
|
||||
level = logg.LevelInfo
|
||||
}
|
||||
|
||||
if r.debug {
|
||||
helpers.Deprecated("--debug", "use --logLevel debug", false)
|
||||
hugo.Deprecate("--debug", "use --logLevel debug", "v0.114.0")
|
||||
level = logg.LevelDebug
|
||||
}
|
||||
}
|
||||
|
||||
optsLogger := loggers.Options{
|
||||
Distinct: true,
|
||||
Level: level,
|
||||
Stdout: r.Out,
|
||||
Stderr: r.Out,
|
||||
StoreErrors: running,
|
||||
DistinctLevel: logg.LevelWarn,
|
||||
Level: level,
|
||||
Stdout: r.Out,
|
||||
Stderr: r.Out,
|
||||
StoreErrors: running,
|
||||
}
|
||||
|
||||
return loggers.New(optsLogger), nil
|
||||
|
||||
}
|
||||
|
||||
func (r *rootCommand) Reset() {
|
||||
@@ -519,7 +514,6 @@ func applyLocalFlagsBuildConfig(cmd *cobra.Command, r *rootCommand) {
|
||||
_ = cmd.Flags().SetAnnotation("cacheDir", cobra.BashCompSubdirsInDir, []string{})
|
||||
cmd.Flags().StringP("contentDir", "c", "", "filesystem path to content directory")
|
||||
_ = cmd.Flags().SetAnnotation("theme", cobra.BashCompSubdirsInDir, []string{"themes"})
|
||||
|
||||
}
|
||||
|
||||
// Flags needed to do a build (used by hugo and hugo server commands)
|
||||
@@ -558,7 +552,6 @@ func applyLocalFlagsBuild(cmd *cobra.Command, r *rootCommand) {
|
||||
cmd.Flags().StringSlice("disableKinds", []string{}, "disable different kind of pages (home, RSS etc.)")
|
||||
cmd.Flags().Bool("minify", false, "minify any supported output format (HTML, XML etc.)")
|
||||
_ = cmd.Flags().SetAnnotation("destination", cobra.BashCompSubdirsInDir, []string{})
|
||||
|
||||
}
|
||||
|
||||
func (r *rootCommand) timeTrack(start time.Time, name string) {
|
||||
|
||||
@@ -25,9 +25,9 @@ func init() {
|
||||
// This message to show to Windows users if Hugo is opened from explorer.exe
|
||||
cobra.MousetrapHelpText = `
|
||||
|
||||
Hugo is a command-line tool for generating static website.
|
||||
Hugo is a command-line tool for generating static websites.
|
||||
|
||||
You need to open PowerShell and run Hugo from there.
|
||||
|
||||
You need to open cmd.exe and run Hugo from there.
|
||||
|
||||
Visit https://gohugo.io/ for more information.`
|
||||
}
|
||||
|
||||
+7
-3
@@ -211,7 +211,12 @@ Install a specific version:
|
||||
|
||||
hugo mod get github.com/gohugoio/testshortcodes@v0.3.0
|
||||
|
||||
Install the latest versions of all module dependencies:
|
||||
Install the latest versions of all direct module dependencies:
|
||||
|
||||
hugo mod get
|
||||
hugo mod get ./... (recursive)
|
||||
|
||||
Install the latest versions of all module dependencies (direct and indirect):
|
||||
|
||||
hugo mod get -u
|
||||
hugo mod get -u ./... (recursive)
|
||||
@@ -281,7 +286,6 @@ Run "go help get" for more information. All flags available for "go get" is also
|
||||
npmCommand,
|
||||
},
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
type modCommands struct {
|
||||
@@ -303,7 +307,7 @@ func (c *modCommands) Run(ctx context.Context, cd *simplecobra.Commandeer, args
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
//config := conf.configs.Base
|
||||
// config := conf.configs.Base
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -63,7 +63,6 @@ Ensure you run this within the root directory of your site.`,
|
||||
cmd.Flags().StringVarP(&contentType, "kind", "k", "", "content type to create")
|
||||
cmd.Flags().String("editor", "", "edit new content with this editor, if provided")
|
||||
cmd.Flags().BoolVarP(&force, "force", "f", false, "overwrite file if it already exists")
|
||||
cmd.Flags().StringVar(&format, "format", "toml", "preferred file format (toml, yaml or json)")
|
||||
applyLocalFlagsBuildConfig(cmd, r)
|
||||
|
||||
},
|
||||
|
||||
+1
-1
@@ -927,7 +927,7 @@ func (c *serverCommand) serve() error {
|
||||
|
||||
for i := range baseURLs {
|
||||
mu, listener, serverURL, endpoint, err := srv.createEndpoint(i)
|
||||
var srv *http.Server
|
||||
var srv *http.Server
|
||||
if c.tlsCertFile != "" && c.tlsKeyFile != "" {
|
||||
srv = &http.Server{
|
||||
Addr: endpoint,
|
||||
|
||||
@@ -16,9 +16,6 @@ package constants
|
||||
// Error IDs.
|
||||
// Do not change these values.
|
||||
const (
|
||||
ErrIDAmbigousDisableKindTaxonomy = "error-disable-taxonomy"
|
||||
ErrIDAmbigousOutputKindTaxonomy = "error-output-taxonomy"
|
||||
|
||||
// IDs for remote errors in tpl/data.
|
||||
ErrRemoteGetJSON = "error-remote-getjson"
|
||||
ErrRemoteGetCSV = "error-remote-getcsv"
|
||||
|
||||
@@ -99,3 +99,26 @@ var reCache = regexpCache{re: make(map[string]*regexp.Regexp)}
|
||||
func GetOrCompileRegexp(pattern string) (re *regexp.Regexp, err error) {
|
||||
return reCache.getOrCompileRegexp(pattern)
|
||||
}
|
||||
|
||||
// InSlice checks if a string is an element of a slice of strings
|
||||
// and returns a boolean value.
|
||||
func InSlice(arr []string, el string) bool {
|
||||
for _, v := range arr {
|
||||
if v == el {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// InSlicEqualFold checks if a string is an element of a slice of strings
|
||||
// and returns a boolean value.
|
||||
// It uses strings.EqualFold to compare.
|
||||
func InSlicEqualFold(arr []string, el string) bool {
|
||||
for _, v := range arr {
|
||||
if strings.EqualFold(v, el) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
+63
-6
@@ -22,14 +22,15 @@ import (
|
||||
"sort"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
godartsassv1 "github.com/bep/godartsass"
|
||||
"github.com/bep/logg"
|
||||
"github.com/mitchellh/mapstructure"
|
||||
|
||||
"time"
|
||||
|
||||
"github.com/bep/godartsass/v2"
|
||||
"github.com/gohugoio/hugo/common/hexec"
|
||||
"github.com/gohugoio/hugo/common/loggers"
|
||||
"github.com/gohugoio/hugo/hugofs/files"
|
||||
|
||||
"github.com/spf13/afero"
|
||||
@@ -78,10 +79,22 @@ func (i HugoInfo) Generator() template.HTML {
|
||||
return template.HTML(fmt.Sprintf(`<meta name="generator" content="Hugo %s">`, CurrentVersion.String()))
|
||||
}
|
||||
|
||||
// IsDevelopment reports whether the current running environment is "development".
|
||||
func (i HugoInfo) IsDevelopment() bool {
|
||||
return i.Environment == EnvironmentDevelopment
|
||||
}
|
||||
|
||||
// IsProduction reports whether the current running environment is "production".
|
||||
func (i HugoInfo) IsProduction() bool {
|
||||
return i.Environment == EnvironmentProduction
|
||||
}
|
||||
|
||||
// IsServer reports whether the built-in server is running.
|
||||
func (i HugoInfo) IsServer() bool {
|
||||
return i.conf.Running()
|
||||
}
|
||||
|
||||
// IsExtended reports whether the Hugo binary is the extended version.
|
||||
func (i HugoInfo) IsExtended() bool {
|
||||
return IsExtended
|
||||
}
|
||||
@@ -99,6 +112,7 @@ func (i HugoInfo) Deps() []*Dependency {
|
||||
// ConfigProvider represents the config options that are relevant for HugoInfo.
|
||||
type ConfigProvider interface {
|
||||
Environment() string
|
||||
Running() bool
|
||||
WorkingDir() string
|
||||
}
|
||||
|
||||
@@ -170,8 +184,10 @@ type buildInfo struct {
|
||||
*debug.BuildInfo
|
||||
}
|
||||
|
||||
var bInfo *buildInfo
|
||||
var bInfoInit sync.Once
|
||||
var (
|
||||
bInfo *buildInfo
|
||||
bInfoInit sync.Once
|
||||
)
|
||||
|
||||
func getBuildInfo() *buildInfo {
|
||||
bInfoInit.Do(func() {
|
||||
@@ -198,7 +214,6 @@ func getBuildInfo() *buildInfo {
|
||||
bInfo.GoArch = s.Value
|
||||
}
|
||||
}
|
||||
|
||||
})
|
||||
|
||||
return bInfo
|
||||
@@ -242,7 +257,7 @@ func GetDependencyListNonGo() []string {
|
||||
}
|
||||
|
||||
if dartSass := dartSassVersion(); dartSass.ProtocolVersion != "" {
|
||||
var dartSassPath = "github.com/sass/dart-sass-embedded"
|
||||
dartSassPath := "github.com/sass/dart-sass-embedded"
|
||||
if IsDartSassV2() {
|
||||
dartSassPath = "github.com/sass/dart-sass"
|
||||
}
|
||||
@@ -333,3 +348,45 @@ var (
|
||||
func IsDartSassV2() bool {
|
||||
return !strings.Contains(DartSassBinaryName, "embedded")
|
||||
}
|
||||
|
||||
// Deprecate informs about a deprecation starting at the given version.
|
||||
//
|
||||
// A deprecation typically needs a simple change in the template, but doing so will make the template incompatible with older versions.
|
||||
// Theme maintainers generally want
|
||||
// 1. No warnings or errors in the console when building a Hugo site.
|
||||
// 2. Their theme to work for at least the last few Hugo versions.
|
||||
func Deprecate(item, alternative string, version string) {
|
||||
level := deprecationLogLevelFromVersion(version)
|
||||
DeprecateLevel(item, alternative, version, level)
|
||||
}
|
||||
|
||||
// DeprecateLevel informs about a deprecation logging at the given level.
|
||||
func DeprecateLevel(item, alternative, version string, level logg.Level) {
|
||||
var msg string
|
||||
if level == logg.LevelError {
|
||||
msg = fmt.Sprintf("%s was deprecated in Hugo %s and will be removed in Hugo %s. %s", item, version, CurrentVersion.Next().ReleaseVersion(), alternative)
|
||||
} else {
|
||||
msg = fmt.Sprintf("%s was deprecated in Hugo %s and will be removed in a future release. %s", item, version, alternative)
|
||||
}
|
||||
|
||||
loggers.Log().Logger().WithLevel(level).WithField(loggers.FieldNameCmd, "deprecated").Logf(msg)
|
||||
}
|
||||
|
||||
// We ususally do about one minor version a month.
|
||||
// We want people to run at least the current and previous version without any warnings.
|
||||
// We want people who don't update Hugo that often to see the warnings and errors before we remove the feature.
|
||||
func deprecationLogLevelFromVersion(ver string) logg.Level {
|
||||
from := MustParseVersion(ver)
|
||||
to := CurrentVersion
|
||||
minorDiff := to.Minor - from.Minor
|
||||
switch {
|
||||
case minorDiff >= 12:
|
||||
// Start failing the build after about a year.
|
||||
return logg.LevelError
|
||||
case minorDiff >= 6:
|
||||
// Start printing warnings after about six months.
|
||||
return logg.LevelWarn
|
||||
default:
|
||||
return logg.LevelInfo
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,13 +17,14 @@ import (
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"github.com/bep/logg"
|
||||
qt "github.com/frankban/quicktest"
|
||||
)
|
||||
|
||||
func TestHugoInfo(t *testing.T) {
|
||||
c := qt.New(t)
|
||||
|
||||
conf := testConfig{environment: "production", workingDir: "/mywork"}
|
||||
conf := testConfig{environment: "production", workingDir: "/mywork", running: false}
|
||||
hugoInfo := NewInfo(conf, nil)
|
||||
|
||||
c.Assert(hugoInfo.Version(), qt.Equals, CurrentVersion.Version())
|
||||
@@ -38,15 +39,34 @@ func TestHugoInfo(t *testing.T) {
|
||||
}
|
||||
c.Assert(hugoInfo.Environment, qt.Equals, "production")
|
||||
c.Assert(string(hugoInfo.Generator()), qt.Contains, fmt.Sprintf("Hugo %s", hugoInfo.Version()))
|
||||
c.Assert(hugoInfo.IsDevelopment(), qt.Equals, false)
|
||||
c.Assert(hugoInfo.IsProduction(), qt.Equals, true)
|
||||
c.Assert(hugoInfo.IsExtended(), qt.Equals, IsExtended)
|
||||
c.Assert(hugoInfo.IsServer(), qt.Equals, false)
|
||||
|
||||
devHugoInfo := NewInfo(testConfig{environment: "development"}, nil)
|
||||
devHugoInfo := NewInfo(testConfig{environment: "development", running: true}, nil)
|
||||
c.Assert(devHugoInfo.IsDevelopment(), qt.Equals, true)
|
||||
c.Assert(devHugoInfo.IsProduction(), qt.Equals, false)
|
||||
c.Assert(devHugoInfo.IsServer(), qt.Equals, true)
|
||||
}
|
||||
|
||||
func TestDeprecationLogLevelFromVersion(t *testing.T) {
|
||||
c := qt.New(t)
|
||||
|
||||
c.Assert(deprecationLogLevelFromVersion("0.55.0"), qt.Equals, logg.LevelError)
|
||||
ver := CurrentVersion
|
||||
c.Assert(deprecationLogLevelFromVersion(ver.String()), qt.Equals, logg.LevelInfo)
|
||||
ver.Minor -= 1
|
||||
c.Assert(deprecationLogLevelFromVersion(ver.String()), qt.Equals, logg.LevelInfo)
|
||||
ver.Minor -= 6
|
||||
c.Assert(deprecationLogLevelFromVersion(ver.String()), qt.Equals, logg.LevelWarn)
|
||||
ver.Minor -= 6
|
||||
c.Assert(deprecationLogLevelFromVersion(ver.String()), qt.Equals, logg.LevelError)
|
||||
}
|
||||
|
||||
type testConfig struct {
|
||||
environment string
|
||||
running bool
|
||||
workingDir string
|
||||
}
|
||||
|
||||
@@ -54,6 +74,10 @@ func (c testConfig) Environment() string {
|
||||
return c.environment
|
||||
}
|
||||
|
||||
func (c testConfig) Running() bool {
|
||||
return c.running
|
||||
}
|
||||
|
||||
func (c testConfig) WorkingDir() string {
|
||||
return c.workingDir
|
||||
}
|
||||
|
||||
@@ -67,8 +67,11 @@ func (h VersionString) String() string {
|
||||
|
||||
// Compare implements the compare.Comparer interface.
|
||||
func (h VersionString) Compare(other any) int {
|
||||
v := MustParseVersion(h.String())
|
||||
return compareVersions(v, other)
|
||||
return compareVersions(h.Version(), other)
|
||||
}
|
||||
|
||||
func (h VersionString) Version() Version {
|
||||
return MustParseVersion(h.String())
|
||||
}
|
||||
|
||||
// Eq implements the compare.Eqer interface.
|
||||
@@ -264,7 +267,6 @@ func compareFloatWithVersion(v1 float64, v2 Version) int {
|
||||
|
||||
if v1maj > v2.Major {
|
||||
return 1
|
||||
|
||||
}
|
||||
|
||||
if v1maj < v2.Major {
|
||||
@@ -276,7 +278,6 @@ func compareFloatWithVersion(v1 float64, v2 Version) int {
|
||||
}
|
||||
|
||||
return -1
|
||||
|
||||
}
|
||||
|
||||
func GoMinorVersion() int {
|
||||
|
||||
@@ -17,7 +17,7 @@ package hugo
|
||||
// This should be the only one.
|
||||
var CurrentVersion = Version{
|
||||
Major: 0,
|
||||
Minor: 119,
|
||||
Minor: 121,
|
||||
PatchLevel: 0,
|
||||
Suffix: "-DEV",
|
||||
}
|
||||
|
||||
@@ -40,7 +40,7 @@ type Options struct {
|
||||
Level logg.Level
|
||||
Stdout io.Writer
|
||||
Stderr io.Writer
|
||||
Distinct bool
|
||||
DistinctLevel logg.Level
|
||||
StoreErrors bool
|
||||
HandlerPost func(e *logg.Entry) error
|
||||
SuppressStatements map[string]bool
|
||||
@@ -92,8 +92,8 @@ func New(opts Options) Logger {
|
||||
logHandler = multi.New(handlers...)
|
||||
|
||||
var logOnce *logOnceHandler
|
||||
if opts.Distinct {
|
||||
logOnce = newLogOnceHandler(logg.LevelWarn)
|
||||
if opts.DistinctLevel != 0 {
|
||||
logOnce = newLogOnceHandler(opts.DistinctLevel)
|
||||
logHandler = newStopHandler(logOnce, logHandler)
|
||||
}
|
||||
|
||||
@@ -137,10 +137,10 @@ func New(opts Options) Logger {
|
||||
// NewDefault creates a new logger with the default options.
|
||||
func NewDefault() Logger {
|
||||
opts := Options{
|
||||
Distinct: true,
|
||||
Level: logg.LevelWarn,
|
||||
Stdout: os.Stdout,
|
||||
Stderr: os.Stdout,
|
||||
DistinctLevel: logg.LevelWarn,
|
||||
Level: logg.LevelWarn,
|
||||
Stdout: os.Stdout,
|
||||
Stderr: os.Stdout,
|
||||
}
|
||||
return New(opts)
|
||||
}
|
||||
|
||||
@@ -29,10 +29,10 @@ func TestLogDistinct(t *testing.T) {
|
||||
c := qt.New(t)
|
||||
|
||||
opts := loggers.Options{
|
||||
Distinct: true,
|
||||
StoreErrors: true,
|
||||
Stdout: io.Discard,
|
||||
Stderr: io.Discard,
|
||||
DistinctLevel: logg.LevelWarn,
|
||||
StoreErrors: true,
|
||||
Stdout: io.Discard,
|
||||
Stderr: io.Discard,
|
||||
}
|
||||
|
||||
l := loggers.New(opts)
|
||||
@@ -85,7 +85,6 @@ func TestOptionStoreErrors(t *testing.T) {
|
||||
|
||||
c.Assert(sb.String(), qt.Contains, "error 1")
|
||||
c.Assert(sb.String(), qt.Contains, "ERROR")
|
||||
|
||||
}
|
||||
|
||||
func TestLogCount(t *testing.T) {
|
||||
@@ -124,17 +123,16 @@ func TestSuppressStatements(t *testing.T) {
|
||||
c.Assert(errorsStr, qt.Not(qt.Contains), "error 1")
|
||||
c.Assert(errorsStr, qt.Contains, "error 2")
|
||||
c.Assert(l.LoggCount(logg.LevelError), qt.Equals, 1)
|
||||
|
||||
}
|
||||
|
||||
func TestReset(t *testing.T) {
|
||||
c := qt.New(t)
|
||||
|
||||
opts := loggers.Options{
|
||||
StoreErrors: true,
|
||||
Distinct: true,
|
||||
Stdout: io.Discard,
|
||||
Stderr: io.Discard,
|
||||
StoreErrors: true,
|
||||
DistinctLevel: logg.LevelWarn,
|
||||
Stdout: io.Discard,
|
||||
Stderr: io.Discard,
|
||||
}
|
||||
|
||||
l := loggers.New(opts)
|
||||
|
||||
@@ -21,7 +21,7 @@ import (
|
||||
"github.com/bep/logg"
|
||||
)
|
||||
|
||||
func InitGlobalLogger(panicOnWarnings bool) {
|
||||
func InitGlobalLogger(level logg.Level, panicOnWarnings bool) {
|
||||
logMu.Lock()
|
||||
defer logMu.Unlock()
|
||||
var logHookLast func(e *logg.Entry) error
|
||||
@@ -31,8 +31,9 @@ func InitGlobalLogger(panicOnWarnings bool) {
|
||||
|
||||
log = New(
|
||||
Options{
|
||||
Distinct: true,
|
||||
HandlerPost: logHookLast,
|
||||
Level: level,
|
||||
DistinctLevel: logg.LevelInfo,
|
||||
HandlerPost: logHookLast,
|
||||
},
|
||||
)
|
||||
}
|
||||
@@ -49,5 +50,5 @@ func Log() Logger {
|
||||
var log Logger
|
||||
|
||||
func init() {
|
||||
InitGlobalLogger(false)
|
||||
InitGlobalLogger(logg.LevelWarn, false)
|
||||
}
|
||||
|
||||
+12
-9
@@ -51,9 +51,10 @@ var pb pathBridge
|
||||
|
||||
// MakePermalink combines base URL with content path to create full URL paths.
|
||||
// Example
|
||||
// base: http://spf13.com/
|
||||
// path: post/how-i-blog
|
||||
// result: http://spf13.com/post/how-i-blog
|
||||
//
|
||||
// base: http://spf13.com/
|
||||
// path: post/how-i-blog
|
||||
// result: http://spf13.com/post/how-i-blog
|
||||
func MakePermalink(host, plink string) *url.URL {
|
||||
base, err := url.Parse(host)
|
||||
if err != nil {
|
||||
@@ -117,17 +118,19 @@ func PrettifyURL(in string) string {
|
||||
|
||||
// PrettifyURLPath takes a URL path to a content and converts it
|
||||
// to enable pretty URLs.
|
||||
// /section/name.html becomes /section/name/index.html
|
||||
// /section/name/ becomes /section/name/index.html
|
||||
// /section/name/index.html becomes /section/name/index.html
|
||||
//
|
||||
// /section/name.html becomes /section/name/index.html
|
||||
// /section/name/ becomes /section/name/index.html
|
||||
// /section/name/index.html becomes /section/name/index.html
|
||||
func PrettifyURLPath(in string) string {
|
||||
return prettifyPath(in, pb)
|
||||
}
|
||||
|
||||
// Uglify does the opposite of PrettifyURLPath().
|
||||
// /section/name/index.html becomes /section/name.html
|
||||
// /section/name/ becomes /section/name.html
|
||||
// /section/name.html becomes /section/name.html
|
||||
//
|
||||
// /section/name/index.html becomes /section/name.html
|
||||
// /section/name/ becomes /section/name.html
|
||||
// /section/name.html becomes /section/name.html
|
||||
func Uglify(in string) string {
|
||||
if path.Ext(in) == "" {
|
||||
if len(in) < 2 {
|
||||
|
||||
@@ -27,6 +27,7 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/gohugoio/hugo/cache/filecache"
|
||||
"github.com/gohugoio/hugo/common/hugo"
|
||||
"github.com/gohugoio/hugo/common/loggers"
|
||||
"github.com/gohugoio/hugo/common/maps"
|
||||
"github.com/gohugoio/hugo/common/urls"
|
||||
@@ -784,7 +785,7 @@ func fromLoadConfigResult(fs afero.Fs, logger loggers.Logger, res config.LoadCon
|
||||
// We accidentally allowed it in the past, so we need to support it a little longer,
|
||||
// But log a warning.
|
||||
if _, found := params[kk]; !found {
|
||||
helpers.Deprecated(fmt.Sprintf("config: languages.%s.%s: custom params on the language top level", k, kk), fmt.Sprintf("Put the value below [languages.%s.params]. See https://gohugo.io/content-management/multilingual/#changes-in-hugo-01120", k), false)
|
||||
hugo.Deprecate(fmt.Sprintf("config: languages.%s.%s: custom params on the language top level", k, kk), fmt.Sprintf("Put the value below [languages.%s.params]. See https://gohugo.io/content-management/multilingual/#changes-in-hugo-01120", k), "v0.112.0")
|
||||
params[kk] = vv
|
||||
}
|
||||
}
|
||||
|
||||
@@ -228,3 +228,7 @@ func (c ConfigLanguage) PaginatePath() string {
|
||||
func (c ConfigLanguage) StaticDirs() []string {
|
||||
return c.config.staticDirs()
|
||||
}
|
||||
|
||||
func (c ConfigLanguage) EnableEmoji() bool {
|
||||
return c.config.EnableEmoji
|
||||
}
|
||||
|
||||
@@ -93,10 +93,10 @@ func LoadConfig(d ConfigSourceDescriptor) (*Configs, error) {
|
||||
|
||||
// This is unfortunate, but these are global settings.
|
||||
tpl.SetSecurityAllowActionJSTmpl(configs.Base.Security.GoTemplates.AllowActionJSTmpl)
|
||||
loggers.InitGlobalLogger(configs.Base.PanicOnWarning)
|
||||
|
||||
loggers.InitGlobalLogger(d.Logger.Level(), configs.Base.PanicOnWarning)
|
||||
|
||||
return configs, nil
|
||||
|
||||
}
|
||||
|
||||
// ConfigSourceDescriptor describes where to find the config (e.g. config.toml etc.).
|
||||
@@ -330,7 +330,6 @@ func (l *configLoader) envStringToVal(k, v string) any {
|
||||
default:
|
||||
return v
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func (l *configLoader) loadConfigMain(d ConfigSourceDescriptor) (config.LoadConfigResult, modules.ModulesConfig, error) {
|
||||
|
||||
@@ -66,6 +66,7 @@ type AllProvider interface {
|
||||
StaticDirs() []string
|
||||
IgnoredErrors() map[string]bool
|
||||
WorkingDir() string
|
||||
EnableEmoji() bool
|
||||
}
|
||||
|
||||
// Provider provides the configuration settings for Hugo.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0">
|
||||
<meta name="viewport" content="width=device-width">
|
||||
<title>{{ if .IsHome }}{{ site.Title }}{{ else }}{{ printf "%s | %s" .Title site.Title }}{{ end }}</title>
|
||||
{{ partialCached "head/css.html" . }}
|
||||
{{ partialCached "head/js.html" . }}
|
||||
|
||||
@@ -27,6 +27,12 @@ Renders a menu for the given menu ID.
|
||||
{{- else if $page.HasMenuCurrent .Menu .}}
|
||||
{{- $attrs = merge $attrs (dict "class" "ancestor" "aria-current" "true") }}
|
||||
{{- end }}
|
||||
{{- $name := .Name }}
|
||||
{{- with .Identifier }}
|
||||
{{- with T . }}
|
||||
{{- $name = . }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
<li>
|
||||
<a
|
||||
{{- range $k, $v := $attrs }}
|
||||
@@ -34,7 +40,7 @@ Renders a menu for the given menu ID.
|
||||
{{- printf " %s=%q" $k $v | safeHTMLAttr }}
|
||||
{{- end }}
|
||||
{{- end -}}
|
||||
>{{ or (T .Identifier) .Name | safeHTML }}</a>
|
||||
>{{ $name }}</a>
|
||||
{{- with .Children }}
|
||||
<ul>
|
||||
{{- partial "inline/menu/walk.html" (dict "page" $page "menuEntries" .) }}
|
||||
|
||||
Vendored
+7
-2
@@ -33,7 +33,6 @@ import (
|
||||
// There will be normally only one instance of deps in play
|
||||
// at a given time, i.e. one per Site built.
|
||||
type Deps struct {
|
||||
|
||||
// The logger to use.
|
||||
Log loggers.Logger `json:"-"`
|
||||
|
||||
@@ -77,6 +76,9 @@ type Deps struct {
|
||||
// BuildStartListeners will be notified before a build starts.
|
||||
BuildStartListeners *Listeners
|
||||
|
||||
// BuildEndListeners will be notified after a build finishes.
|
||||
BuildEndListeners *Listeners
|
||||
|
||||
// Resources that gets closed when the build is done or the server shuts down.
|
||||
BuildClosers *Closers
|
||||
|
||||
@@ -97,7 +99,6 @@ func (d Deps) Clone(s page.Site, conf config.AllProvider) (*Deps, error) {
|
||||
}
|
||||
|
||||
return &d, nil
|
||||
|
||||
}
|
||||
|
||||
func (d *Deps) SetTempl(t *tpl.TemplateHandlers) {
|
||||
@@ -132,6 +133,10 @@ func (d *Deps) Init() error {
|
||||
d.BuildStartListeners = &Listeners{}
|
||||
}
|
||||
|
||||
if d.BuildEndListeners == nil {
|
||||
d.BuildEndListeners = &Listeners{}
|
||||
}
|
||||
|
||||
if d.BuildClosers == nil {
|
||||
d.BuildClosers = &Closers{}
|
||||
}
|
||||
|
||||
+33
-4
@@ -1,5 +1,8 @@
|
||||
.facebook, .twitter, .instagram, .youtube {
|
||||
fill: #BABABA;
|
||||
.facebook,
|
||||
.twitter,
|
||||
.instagram,
|
||||
.youtube {
|
||||
fill: #bababa;
|
||||
}
|
||||
.facebook:hover {
|
||||
fill: #3b5998;
|
||||
@@ -10,10 +13,9 @@
|
||||
}
|
||||
|
||||
.twitter:hover {
|
||||
fill: #BABABA;
|
||||
fill: #bababa;
|
||||
}
|
||||
|
||||
|
||||
.instagram:hover {
|
||||
fill: #e95950;
|
||||
}
|
||||
@@ -21,3 +23,30 @@
|
||||
.youtube:hover {
|
||||
fill: #bb0000;
|
||||
}
|
||||
|
||||
.mstdn {
|
||||
display: inline-block;
|
||||
background-color: #282c37;
|
||||
color: #d9e1e8;
|
||||
text-decoration: none;
|
||||
padding: 4px 10px 4px 30px;
|
||||
border-radius: 4px;
|
||||
font-size: 16px;
|
||||
background-image: url("data:image/svg+xml;charset=utf8,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%2261.076954mm%22%20height%3D%2265.47831mm%22%20viewBox%3D%220%200%20216.4144%20232.00976%22%3E%3Cpath%20d%3D%22M211.80734%20139.0875c-3.18125%2016.36625-28.4925%2034.2775-57.5625%2037.74875-15.15875%201.80875-30.08375%203.47125-45.99875%202.74125-26.0275-1.1925-46.565-6.2125-46.565-6.2125%200%202.53375.15625%204.94625.46875%207.2025%203.38375%2025.68625%2025.47%2027.225%2046.39125%2027.9425%2021.11625.7225%2039.91875-5.20625%2039.91875-5.20625l.8675%2019.09s-14.77%207.93125-41.08125%209.39c-14.50875.7975-32.52375-.365-53.50625-5.91875C9.23234%20213.82%201.40609%20165.31125.20859%20116.09125c-.365-14.61375-.14-28.39375-.14-39.91875%200-50.33%2032.97625-65.0825%2032.97625-65.0825C49.67234%203.45375%2078.20359.2425%20107.86484%200h.72875c29.66125.2425%2058.21125%203.45375%2074.8375%2011.09%200%200%2032.975%2014.7525%2032.975%2065.0825%200%200%20.41375%2037.13375-4.59875%2062.915%22%20fill%3D%22%233088d4%22%2F%3E%3Cpath%20d%3D%22M177.50984%2080.077v60.94125h-24.14375v-59.15c0-12.46875-5.24625-18.7975-15.74-18.7975-11.6025%200-17.4175%207.5075-17.4175%2022.3525v32.37625H96.20734V85.42325c0-14.845-5.81625-22.3525-17.41875-22.3525-10.49375%200-15.74%206.32875-15.74%2018.7975v59.15H38.90484V80.077c0-12.455%203.17125-22.3525%209.54125-29.675%206.56875-7.3225%2015.17125-11.07625%2025.85-11.07625%2012.355%200%2021.71125%204.74875%2027.8975%2014.2475l6.01375%2010.08125%206.015-10.08125c6.185-9.49875%2015.54125-14.2475%2027.8975-14.2475%2010.6775%200%2019.28%203.75375%2025.85%2011.07625%206.36875%207.3225%209.54%2017.22%209.54%2029.675%22%20fill%3D%22%23fff%22%2F%3E%3C%2Fsvg%3E");
|
||||
background-size: 16px;
|
||||
background-repeat: no-repeat;
|
||||
background-position: top 50% left 8px;
|
||||
transition: all 0.5s;
|
||||
}
|
||||
.mstdn:hover {
|
||||
background-color: #484c56;
|
||||
}
|
||||
|
||||
.mstdn > span {
|
||||
color: #9baec8;
|
||||
font-size: 12px;
|
||||
padding-left: 3px;
|
||||
}
|
||||
.mstdn > span:before {
|
||||
content: "@";
|
||||
}
|
||||
|
||||
+40
-30
@@ -804,8 +804,6 @@ img { max-width: 100%; }
|
||||
.b--washed-red { border-color: #ffdfdf; }
|
||||
.b--transparent { border-color: transparent; }
|
||||
.b--inherit { border-color: inherit; }
|
||||
.b--initial { border-color: currentColor; border-color: initial; }
|
||||
.b--unset { border-color: unset; }
|
||||
/*
|
||||
|
||||
BORDER RADIUS
|
||||
@@ -854,9 +852,6 @@ img { max-width: 100%; }
|
||||
border-top-right-radius: 0;
|
||||
border-bottom-right-radius: 0;
|
||||
}
|
||||
.br-inherit { border-radius: inherit; }
|
||||
.br-initial { border-radius: 0; border-radius: initial; }
|
||||
.br-unset { border-radius: unset; }
|
||||
@media screen and (min-width: 30em) {
|
||||
.br0-ns { border-radius: 0; }
|
||||
.br1-ns { border-radius: .125rem; }
|
||||
@@ -881,9 +876,6 @@ img { max-width: 100%; }
|
||||
border-top-right-radius: 0;
|
||||
border-bottom-right-radius: 0;
|
||||
}
|
||||
.br-inherit-ns { border-radius: inherit; }
|
||||
.br-initial-ns { border-radius: 0; border-radius: initial; }
|
||||
.br-unset-ns { border-radius: unset; }
|
||||
}
|
||||
@media screen and (min-width: 30em) and (max-width: 60em) {
|
||||
.br0-m { border-radius: 0; }
|
||||
@@ -909,9 +901,6 @@ img { max-width: 100%; }
|
||||
border-top-right-radius: 0;
|
||||
border-bottom-right-radius: 0;
|
||||
}
|
||||
.br-inherit-m { border-radius: inherit; }
|
||||
.br-initial-m { border-radius: 0; border-radius: initial; }
|
||||
.br-unset-m { border-radius: unset; }
|
||||
}
|
||||
@media screen and (min-width: 60em) {
|
||||
.br0-l { border-radius: 0; }
|
||||
@@ -937,9 +926,6 @@ img { max-width: 100%; }
|
||||
border-top-right-radius: 0;
|
||||
border-bottom-right-radius: 0;
|
||||
}
|
||||
.br-inherit-l { border-radius: inherit; }
|
||||
.br-initial-l { border-radius: 0; border-radius: initial; }
|
||||
.br-unset-l { border-radius: unset; }
|
||||
}
|
||||
/*
|
||||
|
||||
@@ -2381,7 +2367,6 @@ img { max-width: 100%; }
|
||||
.washed-yellow { color: #fffceb; }
|
||||
.washed-red { color: #ffdfdf; }
|
||||
.color-inherit { color: inherit; }
|
||||
/* Background colors */
|
||||
.bg-black-90 { background-color: rgba(0, 0, 0, .9); }
|
||||
.bg-black-80 { background-color: rgba(0, 0, 0, .8); }
|
||||
.bg-black-70 { background-color: rgba(0, 0, 0, .7); }
|
||||
@@ -2401,6 +2386,7 @@ img { max-width: 100%; }
|
||||
.bg-white-30 { background-color: rgba(255, 255, 255, .3); }
|
||||
.bg-white-20 { background-color: rgba(255, 255, 255, .2); }
|
||||
.bg-white-10 { background-color: rgba(255, 255, 255, .1); }
|
||||
/* Background colors */
|
||||
.bg-black { background-color: #000; }
|
||||
.bg-near-black { background-color: #111; }
|
||||
.bg-dark-gray { background-color: #333; }
|
||||
@@ -4685,7 +4671,6 @@ h6:hover .header-link {
|
||||
.searchbox__input::-webkit-input-placeholder{color:#aaa}
|
||||
.searchbox__input:-ms-input-placeholder{color:#aaa}
|
||||
.searchbox__input::-ms-input-placeholder{color:#aaa}
|
||||
.searchbox__input::-moz-placeholder{color:#aaa}
|
||||
.searchbox__input::placeholder{color:#aaa}
|
||||
.searchbox__submit{position:absolute;top:0;margin:0;border:0;border-radius:16px 0 0 16px;background-color:rgba(69, 142, 225, 0);padding:0;width:32px;height:100%;vertical-align:middle;text-align:center;font-size:inherit;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;right:inherit;left:0}
|
||||
.searchbox__submit:before{display:inline-block;margin-right:-4px;height:100%;vertical-align:middle;content:""}
|
||||
@@ -4919,14 +4904,14 @@ pre {
|
||||
text-decoration: none;
|
||||
|
||||
}
|
||||
.column-count-2 {-webkit-column-count: 1;-moz-column-count: 1;column-count: 1}
|
||||
.column-gap-1 {-webkit-column-gap: 0;-moz-column-gap: 0;column-gap: 0}
|
||||
.break-inside-avoid {-webkit-column-break-inside: auto;page-break-inside: auto;break-inside: auto}
|
||||
.column-count-2 {-webkit-column-count: 1;column-count: 1}
|
||||
.column-gap-1 {-webkit-column-gap: 0;column-gap: 0}
|
||||
.break-inside-avoid {-webkit-column-break-inside: auto;break-inside: auto}
|
||||
@media screen and (min-width: 60em) {
|
||||
.column-count-3-l {-webkit-column-count: 3;-moz-column-count: 3;column-count: 3}
|
||||
.column-count-2-l {-webkit-column-count: 2;-moz-column-count: 2;column-count: 2}
|
||||
.column-gap-1-l {-webkit-column-gap: 1;-moz-column-gap: 1;column-gap: 1}
|
||||
.break-inside-avoid-l {-webkit-column-break-inside: avoid;page-break-inside: avoid;break-inside: avoid}
|
||||
.column-count-3-l {-webkit-column-count: 3;column-count: 3}
|
||||
.column-count-2-l {-webkit-column-count: 2;column-count: 2}
|
||||
.column-gap-1-l {-webkit-column-gap: 1;column-gap: 1}
|
||||
.break-inside-avoid-l {-webkit-column-break-inside: avoid;break-inside: avoid}
|
||||
}
|
||||
.prose ul, .prose ol {
|
||||
margin-bottom: 2em;
|
||||
@@ -4937,10 +4922,6 @@ pre {
|
||||
.prose li:hover {
|
||||
background-color: #eee
|
||||
}
|
||||
.prose ::-moz-selection {
|
||||
background: #0594CB; /* WebKit/Blink Browsers */
|
||||
color: white;
|
||||
}
|
||||
.prose ::selection {
|
||||
background: #0594CB; /* WebKit/Blink Browsers */
|
||||
color: white;
|
||||
@@ -5132,8 +5113,11 @@ code, .code, pre code, .highlight pre {
|
||||
-webkit-transition: opacity .15s ease-in;
|
||||
transition: opacity .15s ease-in;
|
||||
}
|
||||
.facebook, .twitter, .instagram, .youtube {
|
||||
fill: #BABABA;
|
||||
.facebook,
|
||||
.twitter,
|
||||
.instagram,
|
||||
.youtube {
|
||||
fill: #bababa;
|
||||
}
|
||||
.facebook:hover {
|
||||
fill: #3b5998;
|
||||
@@ -5142,7 +5126,7 @@ code, .code, pre code, .highlight pre {
|
||||
fill: #55acee;
|
||||
}
|
||||
.twitter:hover {
|
||||
fill: #BABABA;
|
||||
fill: #bababa;
|
||||
}
|
||||
.instagram:hover {
|
||||
fill: #e95950;
|
||||
@@ -5150,6 +5134,32 @@ code, .code, pre code, .highlight pre {
|
||||
.youtube:hover {
|
||||
fill: #bb0000;
|
||||
}
|
||||
.mstdn {
|
||||
display: inline-block;
|
||||
background-color: #282c37;
|
||||
color: #d9e1e8;
|
||||
text-decoration: none;
|
||||
padding: 4px 10px 4px 30px;
|
||||
border-radius: 4px;
|
||||
font-size: 16px;
|
||||
background-image: url("data:image/svg+xml;charset=utf8,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%2261.076954mm%22%20height%3D%2265.47831mm%22%20viewBox%3D%220%200%20216.4144%20232.00976%22%3E%3Cpath%20d%3D%22M211.80734%20139.0875c-3.18125%2016.36625-28.4925%2034.2775-57.5625%2037.74875-15.15875%201.80875-30.08375%203.47125-45.99875%202.74125-26.0275-1.1925-46.565-6.2125-46.565-6.2125%200%202.53375.15625%204.94625.46875%207.2025%203.38375%2025.68625%2025.47%2027.225%2046.39125%2027.9425%2021.11625.7225%2039.91875-5.20625%2039.91875-5.20625l.8675%2019.09s-14.77%207.93125-41.08125%209.39c-14.50875.7975-32.52375-.365-53.50625-5.91875C9.23234%20213.82%201.40609%20165.31125.20859%20116.09125c-.365-14.61375-.14-28.39375-.14-39.91875%200-50.33%2032.97625-65.0825%2032.97625-65.0825C49.67234%203.45375%2078.20359.2425%20107.86484%200h.72875c29.66125.2425%2058.21125%203.45375%2074.8375%2011.09%200%200%2032.975%2014.7525%2032.975%2065.0825%200%200%20.41375%2037.13375-4.59875%2062.915%22%20fill%3D%22%233088d4%22%2F%3E%3Cpath%20d%3D%22M177.50984%2080.077v60.94125h-24.14375v-59.15c0-12.46875-5.24625-18.7975-15.74-18.7975-11.6025%200-17.4175%207.5075-17.4175%2022.3525v32.37625H96.20734V85.42325c0-14.845-5.81625-22.3525-17.41875-22.3525-10.49375%200-15.74%206.32875-15.74%2018.7975v59.15H38.90484V80.077c0-12.455%203.17125-22.3525%209.54125-29.675%206.56875-7.3225%2015.17125-11.07625%2025.85-11.07625%2012.355%200%2021.71125%204.74875%2027.8975%2014.2475l6.01375%2010.08125%206.015-10.08125c6.185-9.49875%2015.54125-14.2475%2027.8975-14.2475%2010.6775%200%2019.28%203.75375%2025.85%2011.07625%206.36875%207.3225%209.54%2017.22%209.54%2029.675%22%20fill%3D%22%23fff%22%2F%3E%3C%2Fsvg%3E");
|
||||
background-size: 16px;
|
||||
background-repeat: no-repeat;
|
||||
background-position: top 50% left 8px;
|
||||
-webkit-transition: all 0.5s;
|
||||
transition: all 0.5s;
|
||||
}
|
||||
.mstdn:hover {
|
||||
background-color: #484c56;
|
||||
}
|
||||
.mstdn > span {
|
||||
color: #9baec8;
|
||||
font-size: 12px;
|
||||
padding-left: 3px;
|
||||
}
|
||||
.mstdn > span:before {
|
||||
content: "@";
|
||||
}
|
||||
@media (min-width: 75em) {
|
||||
|
||||
[data-scrolldir="down"] .sticky {
|
||||
|
||||
File diff suppressed because one or more lines are too long
+2
-2
@@ -30,9 +30,9 @@
|
||||
{{- partial "site-search.html" . -}}
|
||||
</div>
|
||||
|
||||
<span class="absolute mt1 mt2-l pr3 right-0 top-0">
|
||||
<div class="absolute mt1 mt2-l pr3 right-0 top-0 flex items-start">
|
||||
{{- partialCached "social-follow.html" . -}}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
+6
-4
@@ -1,7 +1,9 @@
|
||||
<!-- TODO: Add follow intents where available TODO: Revisit color and hover color -->
|
||||
{{ with .Site.Social.twitter }}
|
||||
{{/*
|
||||
Disable Twitter for now as we lost access to the account.
|
||||
with .Site.Social.twitter }}
|
||||
<a href="https://twitter.com/intent/follow?screen_name={{ . }}" title="Follow on Twitter" class="link-transition twitter link dib z-999 pt3 pt0-l mr2">
|
||||
{{ partial "svg/twitter.svg" (dict "size" "32px") }}
|
||||
</a>
|
||||
{{ end }}
|
||||
<a class="github-button needs-js link primary-color-dark" href="https://github.com/gohugoio/hugo" data-size="large" data-show-count="false" aria-label="Star gohugoio/hugo on GitHub">Star</a>
|
||||
{{ end */}}
|
||||
<a rel="me" class="mstdn mr3" href="https://fosstodon.org/@gohugoio" target="_blank">gohugoio</a>
|
||||
<a class="github-button needs-js link primary-color-dark" href="https://github.com/gohugoio/hugo" data-size="large" data-show-count="false" aria-label="Star gohugoio/hugo on GitHub">Star</a>
|
||||
|
||||
@@ -1 +1 @@
|
||||
# github.com/gohugoio/gohugoioTheme v0.0.0-20230812102551-06f8256e7ee5
|
||||
# github.com/gohugoio/gohugoioTheme v0.0.0-20230927165800-342e2c850f18
|
||||
|
||||
@@ -1,11 +1,14 @@
|
||||
---
|
||||
title: {{ replace .Name "-" " " | title }}
|
||||
description: ""
|
||||
signature: []
|
||||
title: {{ replace .File.ContentBaseName "-" " " | title }}
|
||||
description:
|
||||
categories: [functions]
|
||||
keywords: []
|
||||
menu:
|
||||
docs:
|
||||
parent: functions
|
||||
relatedfuncs: []
|
||||
function:
|
||||
aliases: []
|
||||
returnType:
|
||||
signatures: []
|
||||
relatedFunctions: []
|
||||
---
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
---
|
||||
title: "{{ replace .Name "-" " " | title }}"
|
||||
description: ""
|
||||
title: {{ replace .File.ContentBaseName "-" " " | title }}
|
||||
description:
|
||||
date: {{ .Date }}
|
||||
---
|
||||
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
---
|
||||
|
||||
title: {{ replace .Name "-" " " | title }}
|
||||
title: {{ replace .File.ContentBaseName "-" " " | title }}
|
||||
date: {{ now.Format "2006-01-02" }}
|
||||
|
||||
description: "A short description of this page."
|
||||
description: A short description of this page.
|
||||
|
||||
# The URL to the site on the internet.
|
||||
siteURL: https://gohugo.io/
|
||||
@@ -34,4 +34,3 @@ bio.md
|
||||
|
||||
featured.png
|
||||
: A reasonably sized screenshot of your website. It can be named anything, but the name must start with "featured". The sample image is `1500x750` (2:1 aspect ratio).
|
||||
|
||||
|
||||
@@ -19,3 +19,6 @@ images = ["images/gohugoio-card.png"]
|
||||
flex_box_interior_classes = "flex-auto w-100 w-40-l mr3 mb3 bg-white ba b--moon-gray nested-copy-line-height"
|
||||
|
||||
#sidebar_direction = "sidebar_left"
|
||||
|
||||
[social]
|
||||
twitter = "GoHugoIO"
|
||||
|
||||
@@ -131,4 +131,4 @@ enableDNT
|
||||
: Enabling this for the vimeo shortcode, the Vimeo player will be blocked from tracking any session data, including all cookies and stats.
|
||||
|
||||
simple
|
||||
: If simple mode is enabled, the video thumbnail is fetched from Vimeo's servers and it is overlayed with a play button. If the user clicks to play the video, it will open in a new tab directly on Vimeo's website.
|
||||
: If simple mode is enabled, the video thumbnail is fetched from Vimeo's servers and it is overlaid with a play button. If the user clicks to play the video, it will open in a new tab directly on Vimeo's website.
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 83 KiB |
@@ -36,13 +36,13 @@ Hugo is for people building a blog, a company site, a portfolio site, documentat
|
||||
[@spf13]: https://twitter.com/spf13
|
||||
[Amazon S3]: https://aws.amazon.com/s3/
|
||||
[Azure]: https://docs.microsoft.com/en-us/azure/storage/blobs/storage-blob-static-website
|
||||
[CloudFront]: https://aws.amazon.com/cloudfront/ "Amazon CloudFront"
|
||||
[CloudFront]: https://aws.amazon.com/cloudfront/
|
||||
[DreamHost]: https://www.dreamhost.com/
|
||||
[Firebase]: https://firebase.google.com/docs/hosting/ "Firebase static hosting"
|
||||
[Firebase]: https://firebase.google.com/docs/hosting/
|
||||
[GitHub Pages]: https://pages.github.com/
|
||||
[GitLab Pages]: https://about.gitlab.com/features/pages/
|
||||
[Go language]: https://go.dev/
|
||||
[GoDaddy]: https://www.godaddy.com/ "GoDaddy.com Hosting"
|
||||
[GoDaddy]: https://www.godaddy.com/
|
||||
[Google Cloud Storage]: https://cloud.google.com/storage/
|
||||
[Heroku]: https://www.heroku.com/
|
||||
[Jekyll]: https://jekyllrb.com/
|
||||
|
||||
@@ -21,7 +21,7 @@ hugo gen chromastyles [flags] [args]
|
||||
|
||||
```
|
||||
-h, --help help for chromastyles
|
||||
--highlightStyle string style used for highlighting lines (see https://github.com/alecthomas/chroma) (default "bg:#ffffcc")
|
||||
--highlightStyle string style used for highlighting lines (see https://github.com/alecthomas/chroma)
|
||||
--linesStyle string style used for line numbers (see https://github.com/alecthomas/chroma)
|
||||
--style string highlighter style (see https://xyproto.github.io/splash/docs/) (default "friendly")
|
||||
```
|
||||
|
||||
@@ -12,7 +12,7 @@ Generate Markdown documentation for the Hugo CLI.
|
||||
Generate Markdown documentation for the Hugo CLI.
|
||||
This command is, mostly, used to create up-to-date documentation
|
||||
of Hugo's command-line interface for https://gohugo.io/.
|
||||
|
||||
|
||||
It creates one Markdown file per command with front matter suitable
|
||||
for rendering in Hugo.
|
||||
|
||||
|
||||
@@ -22,7 +22,12 @@ Install a specific version:
|
||||
|
||||
hugo mod get github.com/gohugoio/testshortcodes@v0.3.0
|
||||
|
||||
Install the latest versions of all module dependencies:
|
||||
Install the latest versions of all direct module dependencies:
|
||||
|
||||
hugo mod get
|
||||
hugo mod get ./... (recursive)
|
||||
|
||||
Install the latest versions of all module dependencies (direct and indirect):
|
||||
|
||||
hugo mod get -u
|
||||
hugo mod get -u ./... (recursive)
|
||||
|
||||
@@ -30,7 +30,6 @@ hugo new content [path] [flags]
|
||||
-c, --contentDir string filesystem path to content directory
|
||||
--editor string edit new content with this editor, if provided
|
||||
-f, --force overwrite file if it already exists
|
||||
--format string preferred file format (toml, yaml or json) (default "toml")
|
||||
-h, --help help for content
|
||||
-k, --kind string content type to create
|
||||
-t, --theme strings themes to use (located in /themes/THEMENAME/)
|
||||
|
||||
@@ -68,7 +68,7 @@ If none of these exists, Hugo uses a built-in default archetype.
|
||||
|
||||
## Functions and context
|
||||
|
||||
You can use any [template function] within an archetype. As shown above, the default archetype uses the [`replace`](/functions/replace/) function to replace hyphens with spaces when populating the title in front matter.
|
||||
You can use any [template function] within an archetype. As shown above, the default archetype uses the [`replace`](/functions/strings/replace) function to replace hyphens with spaces when populating the title in front matter.
|
||||
|
||||
Archetypes receive the following objects and values in [context]:
|
||||
|
||||
|
||||
@@ -24,8 +24,9 @@ Hugo comes with all the code you need to load Disqus into your templates. Before
|
||||
|
||||
Disqus comments require you set a single value in your [site's configuration file][configuration] like so:
|
||||
|
||||
{{< code-toggle copy=false >}}
|
||||
disqusShortname = "yourDisqusShortname"
|
||||
{{< code-toggle file="hugo" >}}
|
||||
[services.disqus]
|
||||
shortname = 'your-disqus-shortname'
|
||||
{{</ code-toggle >}}
|
||||
|
||||
For many websites, this is enough configuration. However, you also have the option to set the following in the [front matter] of a single content file:
|
||||
@@ -48,6 +49,7 @@ These are some alternatives to Disqus:
|
||||
|
||||
* [Cactus Comments](https://cactus.chat/docs/integrations/hugo/) (Open Source, Matrix appservice, Docker install)
|
||||
* [Commento](https://commento.io/) (Open Source, available as a service, local install, or docker image)
|
||||
* [Giscus](https://giscus.app/) (Open source, comments system powered by GitHub Discussions)
|
||||
* [Graph Comment](https://graphcomment.com/)
|
||||
* [Hyvor Talk](https://talk.hyvor.com/) (Available as a service)
|
||||
* [IntenseDebate](https://intensedebate.com/)
|
||||
|
||||
@@ -49,7 +49,7 @@ Hugo passes reasonable default arguments to these external helpers by default:
|
||||
Because additional formats are external commands, generation performance will rely heavily on the performance of the external tool you are using. As this feature is still in its infancy, feedback is welcome.
|
||||
{{% /note %}}
|
||||
|
||||
### External helper Asciidoctor
|
||||
### Asciidoctor
|
||||
|
||||
The Asciidoctor community offers a wide set of tools for the AsciiDoc format that can be installed additionally to Hugo.
|
||||
[See the Asciidoctor docs for installation instructions](https://asciidoctor.org/docs/install-toolchain/). Make sure that also all
|
||||
@@ -59,52 +59,9 @@ optional extensions like `asciidoctor-diagram` or `asciidoctor-html5s` are insta
|
||||
External `asciidoctor` command requires Hugo rendering to _disk_ to a specific destination directory. It is required to run Hugo with the command option `--destination`.
|
||||
{{% /note %}}
|
||||
|
||||
Some [Asciidoctor](https://asciidoctor.org/man/asciidoctor/) parameters can be customized in Hugo:
|
||||
Some Asciidoctor parameters can be customized in Hugo. See [details].
|
||||
|
||||
Parameter | Comment
|
||||
--- | ---
|
||||
backend | Don't change this unless you know what you are doing.
|
||||
doctype | Currently, the only document type supported in Hugo is `article`.
|
||||
extensions | Possible extensions are `asciidoctor-html5s`, `asciidoctor-bibtex`, `asciidoctor-diagram`, `asciidoctor-interdoc-reftext`, `asciidoctor-katex`, `asciidoctor-latex`, `asciidoctor-mathematical`, `asciidoctor-question`.
|
||||
attributes | Variables to be referenced in your AsciiDoc file. This is a list of variable name/value maps. See [Asciidoctor's attributes](https://asciidoctor.org/docs/asciidoc-syntax-quick-reference/#attributes-and-substitutions).
|
||||
noHeaderOrFooter | Output an embeddable document, which excludes the header, the footer, and everything outside the body of the document. Don't change this unless you know what you are doing.
|
||||
safeMode | Safe mode level `unsafe`, `safe`, `server` or `secure`. Don't change this unless you know what you are doing.
|
||||
sectionNumbers | Auto-number section titles.
|
||||
verbose | Verbosely print processing information and configuration file checks to stderr.
|
||||
trace | Include backtrace information on errors.
|
||||
failureLevel | The minimum logging level that triggers a non-zero exit code (failure).
|
||||
|
||||
Hugo provides additional settings that don't map directly to Asciidoctor's CLI options:
|
||||
|
||||
workingFolderCurrent
|
||||
: Sets the working directory to be the same as that of the AsciiDoc file being processed, so that [include](https://asciidoctor.org/docs/asciidoc-syntax-quick-reference/#include-files) will work with relative paths. This setting uses the `asciidoctor` cli parameter `--base-dir` and attribute `outdir=`. For rendering diagrams with [asciidoctor-diagram](https://asciidoctor.org/docs/asciidoctor-diagram/), `workingFolderCurrent` must be set to `true`.
|
||||
|
||||
preserveTOC
|
||||
: By default, Hugo removes the table of contents generated by Asciidoctor and provides it through the built-in variable [`.TableOfContents`](/content-management/toc/) to enable further customization and better integration with the various Hugo themes. This option can be set to `true` to preserve Asciidoctor's TOC in the generated page.
|
||||
|
||||
Below are all the AsciiDoc related settings in Hugo with their default values:
|
||||
|
||||
{{< code-toggle config="markup.asciidocExt" />}}
|
||||
|
||||
Notice that for security concerns only extensions that do not have path separators (either `\`, `/` or `.`) are allowed. That means that extensions can only be invoked if they are in one's ruby's `$LOAD_PATH` (ie. most likely, the extension has been installed by the user). Any extension declared relative to the website's path will not be accepted.
|
||||
|
||||
Example of how to set extensions and attributes:
|
||||
|
||||
```yml
|
||||
[markup.asciidocExt]
|
||||
extensions = ["asciidoctor-html5s", "asciidoctor-diagram"]
|
||||
workingFolderCurrent = true
|
||||
[markup.asciidocExt.attributes]
|
||||
my-base-url = "https://example.com/"
|
||||
my-attribute-name = "my value"
|
||||
```
|
||||
|
||||
In a complex Asciidoctor environment it is sometimes helpful to debug the exact call to your external helper with all
|
||||
parameters. Run Hugo with `-v`. You will get an output like
|
||||
|
||||
```txt
|
||||
INFO 2019/12/22 09:08:48 Rendering book-as-pdf.adoc with C:\Ruby26-x64\bin\asciidoctor.bat using asciidoc args [--no-header-footer -r asciidoctor-html5s -b html5s -r asciidoctor-diagram --base-dir D:\prototypes\hugo_asciidoc_ddd\docs -a outdir=D:\prototypes\hugo_asciidoc_ddd\build -] ...
|
||||
```
|
||||
[details]: /getting-started/configuration-markup/#asciidoc
|
||||
|
||||
## Learn markdown
|
||||
|
||||
@@ -115,7 +72,6 @@ Markdown syntax is simple enough to learn in a single sitting. The following are
|
||||
* [Markdown Tutorial (Interactive), Garen Torikian][mdtutorial]
|
||||
* [The Markdown Guide, Matt Cone][mdguide]
|
||||
|
||||
[`emojify` function]: /functions/emojify/
|
||||
[ascii]: https://asciidoctor.org/
|
||||
[config]: /getting-started/configuration/
|
||||
[developer tools]: /tools/
|
||||
|
||||
@@ -101,12 +101,45 @@ Example 4: Skips rendering if there's problem accessing a remote resource.
|
||||
|
||||
## Image processing methods
|
||||
|
||||
The `image` resource implements the [`Resize`], [`Fit`], [`Fill`], [`Crop`], [`Filter`], [`Colors`] and [`Exif`] methods.
|
||||
The `image` resource implements the [`Process`], [`Resize`], [`Fit`], [`Fill`], [`Crop`], [`Filter`], [`Colors`] and [`Exif`] methods.
|
||||
|
||||
{{% note %}}
|
||||
Metadata (EXIF, IPTC, XMP, etc.) is not preserved during image transformation. Use the [`Exif`] method with the _original_ image to extract EXIF metadata from JPEG or TIFF images.
|
||||
{{% /note %}}
|
||||
|
||||
### Process
|
||||
|
||||
{{< new-in "0.119.0" >}}
|
||||
|
||||
{{% note %}}
|
||||
The `Process` method is also available as a filter, which is more effective if need to apply multiple filters to an image. See [Process filter](/functions/images/#process).
|
||||
{{% /note %}}
|
||||
|
||||
Process processes the image with the given specification. The specification can contain an optional action, one of `resize`, `crop`, `fit` or `fill`. This means that you can use this method instead of [`Resize`], [`Fit`], [`Fill`], or [`Crop`].
|
||||
|
||||
See [Options](#image-processing-options) for available options.
|
||||
|
||||
You can also use this method apply image processing that does not need any scaling, e.g. format conversions:
|
||||
|
||||
```go-html-template
|
||||
{{/* Convert the image from JPG to PNG. */}}
|
||||
{{ $png := $jpg.Process "png" }}
|
||||
```
|
||||
|
||||
Some more examples:
|
||||
|
||||
```go-html-template
|
||||
{{/* Rotate the image 90 degrees counter-clockwise. */}}
|
||||
{{ $image := $image.Process "r90" }}
|
||||
|
||||
{{/* Scaling actions. */}}
|
||||
{{ $image := $image.Process "resize 600x" }}
|
||||
{{ $image := $image.Process "crop 600x400" }}
|
||||
{{ $image := $image.Process "fit 600x400" }}
|
||||
{{ $image := $image.Process "fill 600x400" }}
|
||||
```
|
||||
|
||||
|
||||
### Resize
|
||||
|
||||
Resize an image to the specified width and/or height.
|
||||
@@ -272,7 +305,7 @@ In the example above, on the second line, we have reversed width and height to r
|
||||
|
||||
### Anchor
|
||||
|
||||
When using the [`Crop`] or [`Fill`] method, the _anchor_ determines the placement of the crop box. You may specify `TopLeft`, `Top`, `TopRight`, `Left`, `Center`,`Right`, `BottomLeft`, `Bottom`, `BottomRight`, or `Smart`.
|
||||
When using the [`Crop`] or [`Fill`] method, the _anchor_ determines the placement of the crop box. You may specify `TopLeft`, `Top`, `TopRight`, `Left`, `Center`, `Right`, `BottomLeft`, `Bottom`, `BottomRight`, or `Smart`.
|
||||
|
||||
The default value is `Smart`, which uses [Smartcrop] image analysis to determine the optimal placement of the crop box. You may override the default value in the [site configuration].
|
||||
|
||||
@@ -468,15 +501,16 @@ If you change image processing methods or options, or if you rename or remove im
|
||||
hugo --gc
|
||||
```
|
||||
|
||||
[time.Format]: /functions/dateformat
|
||||
[time.Format]: /functions/time/format
|
||||
[`anchor`]: /content-management/image-processing#anchor
|
||||
[mounted]: /hugo-modules/configuration#module-configuration-mounts
|
||||
[page bundle]: /content-management/page-bundles
|
||||
[`lang.FormatNumber`]: /functions/lang
|
||||
[`lang.FormatNumber`]: /functions/lang/formatnumber
|
||||
[filters]: /functions/images
|
||||
[github.com/disintegration/imaging]: <https://github.com/disintegration/imaging#image-resizing>
|
||||
[Smartcrop]: <https://github.com/muesli/smartcrop#smartcrop>
|
||||
[Exif]: <https://en.wikipedia.org/wiki/Exif>
|
||||
[`Process`]: #process
|
||||
[`Colors`]: #colors
|
||||
[`Crop`]: #crop
|
||||
[`Exif`]: #exif
|
||||
@@ -485,4 +519,4 @@ hugo --gc
|
||||
[`Fit`]: #fit
|
||||
[`Resize`]: #resize
|
||||
[site configuration]: #processing-options
|
||||
[`with`]: /functions/with/
|
||||
[`with`]: /functions/go-template/with/
|
||||
|
||||
@@ -468,7 +468,7 @@ English|Wednesday, November 3, 2021
|
||||
Français|mercredi 3 novembre 2021
|
||||
Deutsch|Mittwoch, 3. November 2021
|
||||
|
||||
See [time.Format] for details.
|
||||
See [`time.Format`] for details.
|
||||
|
||||
### Currency
|
||||
|
||||
@@ -526,11 +526,86 @@ See [lang.FormatPercent] for details.
|
||||
|
||||
## Menus
|
||||
|
||||
Localization of menu entries depends on the how you define them:
|
||||
Localization of menu entries depends on how you define them:
|
||||
|
||||
- When you define menu entries [automatically] using the section pages menu, you must use translation tables to localize each entry.
|
||||
- When you define menu entries [in front matter], they are already localized based on the front matter itself. If the front matter values are insufficient, use translation tables to localize each entry.
|
||||
- When you define menu entries [in site configuration], you can (a) use translation tables, or (b) create language-specific menu entries under each language key.
|
||||
- When you define menu entries [in site configuration], you must create language-specific menu entries under each language key. If the names of the menu entries are insufficent, use translation tables to localize each entry.
|
||||
|
||||
### Create language-specific menu entries
|
||||
|
||||
#### Method 1 -- Use a single configuration file
|
||||
|
||||
For a simple menu with a small number of entries, use a single configuration file. For example:
|
||||
|
||||
{{< code-toggle file="hugo" copy=false >}}
|
||||
[languages.de]
|
||||
languageCode = 'de-DE'
|
||||
languageName = 'Deutsch'
|
||||
weight = 1
|
||||
|
||||
[[languages.de.menu.main]]
|
||||
name = 'Produkte'
|
||||
pageRef = '/products'
|
||||
weight = 10
|
||||
|
||||
[[languages.de.menu.main]]
|
||||
name = 'Leistungen'
|
||||
pageRef = '/services'
|
||||
weight = 20
|
||||
|
||||
[languages.en]
|
||||
languageCode = 'en-US'
|
||||
languageName = 'English'
|
||||
weight = 2
|
||||
|
||||
[[languages.en.menu.main]]
|
||||
name = 'Products'
|
||||
pageRef = '/products'
|
||||
weight = 10
|
||||
|
||||
[[languages.en.menu.main]]
|
||||
name = 'Services'
|
||||
pageRef = '/services'
|
||||
weight = 20
|
||||
{{< /code-toggle >}}
|
||||
|
||||
#### Method 2 -- Use a configuration directory
|
||||
|
||||
With a more complex menu structure, create a [configuration directory] and split the menu entries into multiple files, one file per language. For example:
|
||||
|
||||
```text
|
||||
config/
|
||||
└── _default/
|
||||
├── menus/
|
||||
│ ├── menu.de.toml
|
||||
│ └── menu.en.toml
|
||||
└── hugo.toml
|
||||
```
|
||||
|
||||
{{< code-toggle file="config/_default/menus/menu.de" copy=false >}}
|
||||
[[main]]
|
||||
name = 'Produkte'
|
||||
pageRef = '/products'
|
||||
weight = 10
|
||||
[[main]]
|
||||
name = 'Leistungen'
|
||||
pageRef = '/services'
|
||||
weight = 20
|
||||
{{< /code-toggle >}}
|
||||
|
||||
{{< code-toggle file="config/_default/menus/menu.en" copy=false >}}
|
||||
[[main]]
|
||||
name = 'Products'
|
||||
pageRef = '/products'
|
||||
weight = 10
|
||||
[[main]]
|
||||
name = 'Services'
|
||||
pageRef = '/services'
|
||||
weight = 20
|
||||
{{< /code-toggle >}}
|
||||
|
||||
[configuration directory]: /getting-started/configuration/#configuration-directory
|
||||
|
||||
### Use translation tables
|
||||
|
||||
@@ -574,44 +649,6 @@ services = 'Leistungen'
|
||||
[in front matter]: /content-management/menus/#define-in-front-matter
|
||||
[in site configuration]: /content-management/menus/#define-in-site-configuration
|
||||
|
||||
### Create language-specific menu entries
|
||||
|
||||
For example:
|
||||
|
||||
{{< code-toggle file="hugo" copy=false >}}
|
||||
[languages.de]
|
||||
languageCode = 'de-DE'
|
||||
languageName = 'Deutsch'
|
||||
weight = 1
|
||||
|
||||
[[languages.de.menu.main]]
|
||||
name = 'Produkte'
|
||||
pageRef = '/products'
|
||||
weight = 10
|
||||
|
||||
[[languages.de.menu.main]]
|
||||
name = 'Leistungen'
|
||||
pageRef = '/services'
|
||||
weight = 20
|
||||
|
||||
[languages.en]
|
||||
languageCode = 'en-US'
|
||||
languageName = 'English'
|
||||
weight = 2
|
||||
|
||||
[[languages.en.menu.main]]
|
||||
name = 'Products'
|
||||
pageRef = '/products'
|
||||
weight = 10
|
||||
|
||||
[[languages.en.menu.main]]
|
||||
name = 'Services'
|
||||
pageRef = '/services'
|
||||
weight = 20
|
||||
{{< /code-toggle >}}
|
||||
|
||||
For a simple menu with two languages, these menu entries are easy to create and maintain. For a larger menu, or with more than two languages, using translation tables as described above is preferable.
|
||||
|
||||
## Missing translations
|
||||
|
||||
If a string does not have a translation for the current language, Hugo will use the value from the default language. If no default value is set, an empty string will be shown.
|
||||
@@ -636,7 +673,7 @@ i18n|MISSING_TRANSLATION|en|wordCount
|
||||
To support Multilingual mode in your themes, some considerations must be taken for the URLs in the templates. If there is more than one language, URLs must meet the following criteria:
|
||||
|
||||
* Come from the built-in `.Permalink` or `.RelPermalink`
|
||||
* Be constructed with the [`relLangURL` template function][rellangurl] or the [`absLangURL` template function][abslangurl] **OR** be prefixed with `{{ .LanguagePrefix }}`
|
||||
* Be constructed with the [`relLangURL`] or [`absLangURL`] template function, or be prefixed with `{{ .LanguagePrefix }}`
|
||||
|
||||
If there is more than one language defined, the `LanguagePrefix` variable will equal `/en` (or whatever your `CurrentLanguage` is). If not enabled, it will be an empty string (and is therefore harmless for single-language Hugo websites).
|
||||
|
||||
@@ -657,23 +694,23 @@ hugo new content content/en/post/test.md
|
||||
hugo new content content/de/post/test.md
|
||||
```
|
||||
|
||||
[abslangurl]: /functions/abslangurl
|
||||
[`abslangurl`]: /functions/urls/abslangurl
|
||||
[config]: /getting-started/configuration/
|
||||
[contenttemplate]: /templates/single-page-templates/
|
||||
[go-i18n-source]: https://github.com/nicksnyder/go-i18n
|
||||
[go-i18n]: https://github.com/nicksnyder/go-i18n
|
||||
[homepage]: /templates/homepage/
|
||||
[Hugo Multilingual Part 1: Content translation]: https://regisphilibert.com/blog/2018/08/hugo-multilingual-part-1-managing-content-translation/
|
||||
[i18func]: /functions/i18n/
|
||||
[lang.FormatAccounting]: /functions/lang
|
||||
[lang.FormatCurrency]: /functions/lang
|
||||
[lang.FormatNumber]: /functions/lang
|
||||
[lang.FormatNumberCustom]: /functions/lang
|
||||
[lang.FormatPercent]: /functions/lang
|
||||
[lang.Merge]: /functions/lang.merge/
|
||||
[i18func]: /functions/lang/translate
|
||||
[lang.FormatAccounting]: /functions/lang/formataccounting
|
||||
[lang.FormatCurrency]: /functions/lang/formatcurrency
|
||||
[lang.FormatNumber]: /functions/lang/formatnumber
|
||||
[lang.FormatNumberCustom]: /functions/lang/formatnumbercustom
|
||||
[lang.FormatPercent]: /functions/lang/formatpercent
|
||||
[lang.Merge]: /functions/lang/merge/
|
||||
[menus]: /content-management/menus/
|
||||
[OS environment]: /getting-started/configuration/#configure-with-environment-variables
|
||||
[rellangurl]: /functions/rellangurl
|
||||
[`rellangurl`]: /functions/urls/rellangurl
|
||||
[RFC 5646]: https://tools.ietf.org/html/rfc5646
|
||||
[single page templates]: /templates/single-page-templates/
|
||||
[time.Format]: /functions/dateformat
|
||||
[`time.Format`]: /functions/time/format
|
||||
|
||||
@@ -187,7 +187,7 @@ Rendered:
|
||||
|
||||
To specify one or more [highlighting options], include a quotation-encapsulated, comma-separated list:
|
||||
|
||||
[highlighting options]: /functions/highlight/
|
||||
[highlighting options]: /functions/transform/highlight/
|
||||
|
||||
```text
|
||||
{{</* highlight go-html-template "lineNos=inline, lineNoStart=42" */>}}
|
||||
@@ -391,7 +391,7 @@ To learn more about creating custom shortcodes, see the [shortcode template docu
|
||||
[`figure` shortcode]: #figure
|
||||
[contentmanagementsection]: /content-management/formats/
|
||||
[examplegist]: https://gist.github.com/spf13/7896402
|
||||
[figureelement]: https://html5doctor.com/the-figure-figcaption-elements/ "An article from HTML5 doctor discussing the fig and figcaption elements."
|
||||
[figureelement]: https://html5doctor.com/the-figure-figcaption-elements/
|
||||
[Hugo and the GDPR]: /about/hugo-and-gdpr/
|
||||
[Instagram]: https://www.instagram.com/
|
||||
[pagevariables]: /variables/page/
|
||||
|
||||
@@ -92,7 +92,7 @@ Gives this:
|
||||
|
||||
## Highlight template function
|
||||
|
||||
See [Highlight](/functions/highlight/).
|
||||
See [Highlight](/functions/transform/highlight/).
|
||||
|
||||
## Highlighting in code fences
|
||||
|
||||
|
||||
@@ -191,12 +191,11 @@ title: "Bruce Willis"
|
||||
wikipedia: "https://en.wikipedia.org/wiki/Bruce_Willis"
|
||||
{{< /code-toggle >}}
|
||||
|
||||
[`urlize` template function]: /functions/urlize/
|
||||
[content section]: /content-management/sections/
|
||||
[content type]: /content-management/types/
|
||||
[documentation on archetypes]: /content-management/archetypes/
|
||||
[front matter]: /content-management/front-matter/
|
||||
[taxonomy list templates]: /templates/taxonomy-templates/#taxonomy-list-templates
|
||||
[taxonomy templates]: /templates/taxonomy-templates/
|
||||
[terms within the taxonomy]: /templates/taxonomy-templates/#taxonomy-terms-templates "See how to order terms associated with a taxonomy"
|
||||
[configuration]: /getting-started/configuration/
|
||||
[terms within the taxonomy]: /templates/taxonomy-templates/#taxonomy-terms-templates
|
||||
[site configuration]: /getting-started/configuration/
|
||||
|
||||
@@ -102,11 +102,11 @@ With this content structure:
|
||||
```text
|
||||
content/
|
||||
├── posts/
|
||||
│ ├── bash-in-slow-motion.md
|
||||
│ └── tls-in-a-nutshell.md
|
||||
│ ├── bash-in-slow-motion.md
|
||||
│ └── tls-in-a-nutshell.md
|
||||
├── tutorials/
|
||||
│ ├── git-for-beginners.md
|
||||
│ └── javascript-bundling-with-hugo.md
|
||||
│ ├── git-for-beginners.md
|
||||
│ └── javascript-bundling-with-hugo.md
|
||||
└── _index.md
|
||||
```
|
||||
|
||||
@@ -165,15 +165,15 @@ With this content structure:
|
||||
|
||||
```text
|
||||
content/
|
||||
├── de/
|
||||
│ ├── books/
|
||||
│ │ ├── les-miserables.md
|
||||
│ │ └── the-hunchback-of-notre-dame.md
|
||||
│ └── _index.md
|
||||
└── en/
|
||||
├── en/
|
||||
│ ├── books/
|
||||
│ │ ├── les-miserables.md
|
||||
│ │ └── the-hunchback-of-notre-dame.md
|
||||
│ └── _index.md
|
||||
└── es/
|
||||
├── books/
|
||||
│ ├── les-miserables.md
|
||||
│ └── the-hunchback-of-notre-dame.md
|
||||
│ ├── les-miserables.md
|
||||
│ └── the-hunchback-of-notre-dame.md
|
||||
└── _index.md
|
||||
```
|
||||
|
||||
@@ -197,7 +197,7 @@ books = "/books/:slug/"
|
||||
books = "/books/"
|
||||
|
||||
[languages.es]
|
||||
contentDir = 'content/de'
|
||||
contentDir = 'content/es'
|
||||
languageCode = 'es-ES'
|
||||
languageDirection = 'ltr'
|
||||
languageName = 'Español'
|
||||
@@ -215,21 +215,21 @@ The structure of the published site will be:
|
||||
```text
|
||||
public/
|
||||
├── en/
|
||||
│ ├── books/
|
||||
│ │ ├── les-miserables/
|
||||
│ │ │ └── index.html
|
||||
│ │ ├── the-hunchback-of-notre-dame/
|
||||
│ │ │ └── index.html
|
||||
│ │ └── index.html
|
||||
│ └── index.html
|
||||
│ ├── books/
|
||||
│ │ ├── les-miserables/
|
||||
│ │ │ └── index.html
|
||||
│ │ ├── the-hunchback-of-notre-dame/
|
||||
│ │ │ └── index.html
|
||||
│ │ └── index.html
|
||||
│ └── index.html
|
||||
├── es/
|
||||
│ ├── libros/
|
||||
│ │ ├── les-miserables/
|
||||
│ │ │ └── index.html
|
||||
│ │ ├── the-hunchback-of-notre-dame/
|
||||
│ │ │ └── index.html
|
||||
│ │ └── index.html
|
||||
│ └── index.html
|
||||
│ ├── libros/
|
||||
│ │ ├── les-miserables/
|
||||
│ │ │ └── index.html
|
||||
│ │ ├── the-hunchback-of-notre-dame/
|
||||
│ │ │ └── index.html
|
||||
│ │ └── index.html
|
||||
│ └── index.html
|
||||
└── index.html
|
||||
````
|
||||
|
||||
|
||||
@@ -2,12 +2,15 @@
|
||||
title: .AddDate
|
||||
description: Returns the time corresponding to adding the given number of years, months, and days to the given time.Time value.
|
||||
categories: [functions]
|
||||
keywords: []
|
||||
menu:
|
||||
docs:
|
||||
parent: functions
|
||||
keywords: [dates,time]
|
||||
signature: [".AddDate YEARS MONTHS DAYS"]
|
||||
relatedfuncs: [now]
|
||||
function:
|
||||
aliases: []
|
||||
returnType: time.Time
|
||||
signatures: [.AddDate YEARS MONTHS DAYS]
|
||||
relatedFunctions: []
|
||||
---
|
||||
|
||||
```go-html-template
|
||||
@@ -0,0 +1,90 @@
|
||||
---
|
||||
title: .Format
|
||||
description: Returns a formatted time.Time value.
|
||||
categories: [functions]
|
||||
keywords: []
|
||||
menu:
|
||||
docs:
|
||||
parent: functions
|
||||
function:
|
||||
aliases: []
|
||||
returnType: string
|
||||
signatures: [.Format LAYOUT]
|
||||
relatedFunctions: []
|
||||
toc: true
|
||||
---
|
||||
|
||||
```go-template
|
||||
{{ $t := "2023-01-27T23:44:58-08:00" }}
|
||||
{{ $t = time.AsTime $t }}
|
||||
{{ $format := "2 Jan 2006" }}
|
||||
|
||||
{{ $t.Format $format }} → 27 Jan 2023
|
||||
```
|
||||
|
||||
{{% note %}}
|
||||
To return a formatted and localized `time.Time` value, use the [`time.Format`] function instead.
|
||||
|
||||
[`time.Format`]: /functions/time/format
|
||||
{{% /note %}}
|
||||
|
||||
Use the `.Format` method with any `time.Time` value, including the four predefined front matter dates:
|
||||
|
||||
```go-html-template
|
||||
{{ $format := "2 Jan 2006" }}
|
||||
|
||||
{{ .Date.Format $format }}
|
||||
{{ .PublishDate.Format $format }}
|
||||
{{ .ExpiryDate.Format $format }}
|
||||
{{ .Lastmod.Format $format }}
|
||||
```
|
||||
|
||||
## Layout string
|
||||
|
||||
{{% readfile file="/functions/_common/time-layout-string.md" %}}
|
||||
|
||||
## Examples
|
||||
|
||||
Given this front matter:
|
||||
|
||||
{{< code-toggle fm=true copy=false >}}
|
||||
title = "About time"
|
||||
date = 2023-01-27T23:44:58-08:00
|
||||
{{< /code-toggle >}}
|
||||
|
||||
The examples below were rendered in the `America/Los_Angeles` time zone:
|
||||
|
||||
Format string|Result
|
||||
:--|:--
|
||||
`Monday, January 2, 2006`|`Friday, January 27, 2023`
|
||||
`Mon Jan 2 2006`|`Fri Jan 27 2023`
|
||||
`January 2006`|`January 2023`
|
||||
`2006-01-02`|`2023-01-27`
|
||||
`Monday`|`Friday`
|
||||
`02 Jan 06 15:04 MST`|`27 Jan 23 23:44 PST`
|
||||
`Mon, 02 Jan 2006 15:04:05 MST`|`Fri, 27 Jan 2023 23:44:58 PST`
|
||||
`Mon, 02 Jan 2006 15:04:05 -0700`|`Fri, 27 Jan 2023 23:44:58 -0800`
|
||||
|
||||
## UTC and local time
|
||||
|
||||
Convert and format any `time.Time` value to either Coordinated Universal Time (UTC) or local time.
|
||||
|
||||
```go-html-template
|
||||
{{ $t := "2023-01-27T23:44:58-08:00" }}
|
||||
{{ $t = time.AsTime $t }}
|
||||
{{ $format := "2 Jan 2006 3:04:05 PM MST" }}
|
||||
|
||||
{{ $t.UTC.Format $format }} → 28 Jan 2023 7:44:58 AM UTC
|
||||
{{ $t.Local.Format $format }} → 27 Jan 2023 11:44:58 PM PST
|
||||
```
|
||||
|
||||
## Ordinal representation
|
||||
|
||||
Use the [`humanize`](/functions/inflect/humanize) function to render the day of the month as an ordinal number:
|
||||
|
||||
```go-html-template
|
||||
{{ $t := "2023-01-27T23:44:58-08:00" }}
|
||||
{{ $t = time.AsTime $t }}
|
||||
|
||||
{{ humanize $t.Day }} of {{ $t.Format "January 2006" }} → 27th of January 2023
|
||||
```
|
||||
@@ -2,12 +2,17 @@
|
||||
title: .Get
|
||||
description: Accesses positional and ordered parameters in shortcode declaration.
|
||||
categories: [functions]
|
||||
keywords: []
|
||||
menu:
|
||||
docs:
|
||||
parent: functions
|
||||
keywords: [shortcodes]
|
||||
signature: [".Get INDEX", ".Get KEY"]
|
||||
relatedfuncs: []
|
||||
function:
|
||||
aliases: []
|
||||
returnType: any
|
||||
signatures:
|
||||
- .Get INDEX
|
||||
- .Get KEY
|
||||
relatedFunctions: []
|
||||
---
|
||||
|
||||
`.Get` is specifically used when creating your own [shortcode template][sc], to access the [positional and named](/templates/shortcode-templates/#positional-vs-named-parameters) parameters passed to it. When used with a numeric INDEX, it queries positional parameters (starting with 0). With a string KEY, it queries named parameters.
|
||||
@@ -1,13 +1,16 @@
|
||||
---
|
||||
title: .GetPage
|
||||
description: "Gets a `Page` of a given `path`."
|
||||
description: Gets a `Page` of a given `path`.
|
||||
categories: [functions]
|
||||
keywords: []
|
||||
menu:
|
||||
docs:
|
||||
parent: functions
|
||||
keywords: [sections,lists,indexes]
|
||||
signature: [".GetPage PATH"]
|
||||
relatedfuncs: []
|
||||
function:
|
||||
aliases: []
|
||||
returnType:
|
||||
signatures: [.GetPage PATH]
|
||||
relatedFunctions: []
|
||||
---
|
||||
|
||||
`.GetPage` returns a page of a given `path`. Both `Site` and `Page` implements this method. The `Page` variant will, if given a relative path -- i.e. a path without a leading `/` -- try look for the page relative to the current page.
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
---
|
||||
title: .HasMenuCurrent
|
||||
description: Reports whether the given page object matches the page object associated with one of the child menu entries under the given menu entry in the given menu.
|
||||
categories: [functions]
|
||||
keywords: []
|
||||
menu:
|
||||
docs:
|
||||
parent: functions
|
||||
function:
|
||||
aliases: []
|
||||
returnType: bool
|
||||
signatures: [PAGE.HasMenuCurrent MENU MENUENTRY]
|
||||
relatedFunctions:
|
||||
- .HasMenuCurrent
|
||||
- .IsMenuCurrent
|
||||
---
|
||||
|
||||
If the page object associated with the menu entry is a section, this method also returns `true` for any descendant of that section.
|
||||
|
||||
```go-html-template
|
||||
{{ $currentPage := . }}
|
||||
{{ range site.Menus.main }}
|
||||
{{ if $currentPage.IsMenuCurrent .Menu . }}
|
||||
<a class="active" aria-current="page" href="{{ .URL }}">{{ .Name }}</a>
|
||||
{{ else if $currentPage.HasMenuCurrent .Menu . }}
|
||||
<a class="ancestor" aria-current="true" href="{{ .URL }}">{{ .Name }}</a>
|
||||
{{ else }}
|
||||
<a href="{{ .URL }}">{{ .Name }}</a>
|
||||
{{ end }}
|
||||
{{ end }}
|
||||
```
|
||||
|
||||
See [menu templates] for a complete example.
|
||||
|
||||
[menu templates]: /templates/menu-templates/#example
|
||||
@@ -0,0 +1,33 @@
|
||||
---
|
||||
title: .IsMenuCurrent
|
||||
description: Reports whether the given page object matches the page object associated with the given menu entry in the given menu.
|
||||
categories: [functions]
|
||||
keywords: []
|
||||
menu:
|
||||
docs:
|
||||
parent: functions
|
||||
function:
|
||||
aliases: []
|
||||
returnType: bool
|
||||
signatures: [PAGE.IsMenuCurrent MENU MENUENTRY]
|
||||
relatedFunctions:
|
||||
- .HasMenuCurrent
|
||||
- .IsMenuCurrent
|
||||
---
|
||||
|
||||
```go-html-template
|
||||
{{ $currentPage := . }}
|
||||
{{ range site.Menus.main }}
|
||||
{{ if $currentPage.IsMenuCurrent .Menu . }}
|
||||
<a class="active" aria-current="page" href="{{ .URL }}">{{ .Name }}</a>
|
||||
{{ else if $currentPage.HasMenuCurrent .Menu . }}
|
||||
<a class="ancestor" aria-current="true" href="{{ .URL }}">{{ .Name }}</a>
|
||||
{{ else }}
|
||||
<a href="{{ .URL }}">{{ .Name }}</a>
|
||||
{{ end }}
|
||||
{{ end }}
|
||||
```
|
||||
|
||||
See [menu templates] for a complete example.
|
||||
|
||||
[menu templates]: /templates/menu-templates/#example
|
||||
@@ -1,12 +1,16 @@
|
||||
---
|
||||
title: .Param
|
||||
description: Returns a page parameter, falling back to a site parameter if present.
|
||||
signature: ['.Param KEY']
|
||||
categories: [functions]
|
||||
keywords: ['front matter', 'params']
|
||||
keywords: []
|
||||
menu:
|
||||
docs:
|
||||
parent: functions
|
||||
function:
|
||||
aliases: []
|
||||
returnType: any
|
||||
signatures: [.Param KEY]
|
||||
relatedFunctions: []
|
||||
---
|
||||
|
||||
The `.Param` method on `.Page` looks for the given `KEY` in page parameters, and returns the corresponding value. If it cannot find the `KEY` in page parameters, it looks for the `KEY` in site parameters. If it cannot find the `KEY` in either location, the `.Param` method returns `nil`.
|
||||
@@ -2,12 +2,15 @@
|
||||
title: .Render
|
||||
description: Takes a view to apply when rendering content.
|
||||
categories: [functions]
|
||||
keywords: []
|
||||
menu:
|
||||
docs:
|
||||
parent: functions
|
||||
keywords: [views]
|
||||
signature: [".Render LAYOUT"]
|
||||
relatedfuncs: []
|
||||
function:
|
||||
aliases: []
|
||||
returnType: template.HTML
|
||||
signatures: [.Render LAYOUT]
|
||||
relatedFunctions: []
|
||||
---
|
||||
|
||||
The view is an alternative layout and should be a file name that points to a template in one of the locations specified in the documentation for [Content Views](/templates/views).
|
||||
@@ -1,12 +1,15 @@
|
||||
---
|
||||
title: .RenderString
|
||||
description: "Renders markup to HTML."
|
||||
description: Renders markup to HTML.
|
||||
categories: [functions]
|
||||
keywords: []
|
||||
menu:
|
||||
docs:
|
||||
parent: functions
|
||||
keywords: [markdown,goldmark,render]
|
||||
signature: [".RenderString MARKUP"]
|
||||
function:
|
||||
aliases: []
|
||||
returnType: template.HTML
|
||||
signatures: ['.RenderString MARKUP [OPTIONS]']
|
||||
---
|
||||
|
||||
`.RenderString` is a method on `Page` that renders some markup to HTML using the content renderer defined for that page (if not set in the options).
|
||||
@@ -29,4 +32,4 @@ Some examples:
|
||||
{{ "/italic org mode/" | $p.RenderString $optOrg }}
|
||||
```
|
||||
|
||||
{{< new-in "0.93.0" >}} **Note**: [markdownify](/functions/markdownify/) uses this function in order to support [Render Hooks](/getting-started/configuration-markup/#markdown-render-hooks).
|
||||
{{< new-in "0.93.0" >}} **Note**: [markdownify](/functions/transform/markdownify) uses this function in order to support [Render Hooks](/getting-started/configuration-markup/#markdown-render-hooks).
|
||||
|
||||
@@ -1,14 +1,18 @@
|
||||
---
|
||||
title: .Scratch
|
||||
description: Acts as a "scratchpad" to store and manipulate data.
|
||||
keywords: [iteration]
|
||||
categories: [functions]
|
||||
keywords: []
|
||||
menu:
|
||||
docs:
|
||||
parent: functions
|
||||
toc:
|
||||
signature: []
|
||||
relatedfuncs: []
|
||||
function:
|
||||
aliases: []
|
||||
returnType:
|
||||
signatures: []
|
||||
relatedFunctions:
|
||||
- .Store
|
||||
- .Scratch
|
||||
aliases: [/extras/scratch/,/doc/scratch/]
|
||||
---
|
||||
|
||||
@@ -72,7 +76,7 @@ Get the value of a given key.
|
||||
|
||||
Add a given value to existing value(s) of the given key.
|
||||
|
||||
For single values, `Add` accepts values that support Go's `+` operator. If the first `Add` for a key is an array or slice, the following adds will be [appended](/functions/append/) to that list.
|
||||
For single values, `Add` accepts values that support Go's `+` operator. If the first `Add` for a key is an array or slice, the following adds will be [appended](/functions/collections/append/) to that list.
|
||||
|
||||
```go-html-template
|
||||
{{ $scratch.Add "greetings" "Hello" }}
|
||||
@@ -2,11 +2,17 @@
|
||||
title: .Store
|
||||
description: Returns a Scratch that is not reset on server rebuilds.
|
||||
categories: [functions]
|
||||
keywords: []
|
||||
menu:
|
||||
docs:
|
||||
parent: functions
|
||||
keywords: [scratch]
|
||||
signature: []
|
||||
function:
|
||||
aliases: []
|
||||
returnType:
|
||||
signatures: []
|
||||
relatedFunctions:
|
||||
- .Store
|
||||
- .Scratch
|
||||
---
|
||||
|
||||
The `.Store` method on `.Page` returns a [Scratch] to store and manipulate data. In contrast to the `.Scratch` method, this Scratch is not reset on server rebuilds.
|
||||
@@ -0,0 +1,36 @@
|
||||
---
|
||||
title: .Unix
|
||||
description: Converts a time.Time value to the number of seconds elapsed since the Unix epoch, excluding leap seconds. The Unix epoch is 00:00:00 UTC on 1 January 1970.
|
||||
categories: [functions]
|
||||
menu:
|
||||
docs:
|
||||
parent: functions
|
||||
function:
|
||||
aliases: []
|
||||
returnType: int64
|
||||
signatures:
|
||||
- .Unix
|
||||
- .UnixMilli
|
||||
- .UnixMicro
|
||||
- .UnixNano
|
||||
relatedFunctions: []
|
||||
---
|
||||
|
||||
The `Milli`, `Micro`, and `Nano` variants return the number of milliseconds, microseconds, and nanoseconds (respectively) elapsed since the Unix epoch.
|
||||
|
||||
```go-html-template
|
||||
.Date.Unix → 1637259694
|
||||
.ExpiryDate.Unix → 1672559999
|
||||
.Lastmod.Unix → 1637361786
|
||||
.PublishDate.Unix → 1637421261
|
||||
|
||||
("1970-01-01T00:00:00-00:00" | time.AsTime).Unix → 0
|
||||
("1970-01-01T00:00:42-00:00" | time.AsTime).Unix → 42
|
||||
("1970-04-11T01:48:29-08:00" | time.AsTime).Unix → 8675309
|
||||
("2026-05-02T20:09:31-07:00" | time.AsTime).Unix → 1777777771
|
||||
|
||||
now.Unix → 1637447841
|
||||
now.UnixMilli → 1637447841347
|
||||
now.UnixMicro → 1637447841347378
|
||||
now.UnixNano → 1637447841347378799
|
||||
```
|
||||
@@ -0,0 +1,3 @@
|
||||
See Go's [text/template] documentation for more details.
|
||||
|
||||
[text/template]: https://pkg.go.dev/text/template
|
||||
@@ -0,0 +1,3 @@
|
||||
Localization of dates, currencies, numbers, and percentages is performed by the [gohugoio/locales] package. The language tag of the current site must match one of the listed locales.
|
||||
|
||||
[gohugoio/locales]: https://github.com/gohugoio/locales
|
||||
@@ -0,0 +1,42 @@
|
||||
Format a `time.Time` value based on [Go's reference time]:
|
||||
|
||||
[Go's reference time]: https://pkg.go.dev/time#pkg-constants
|
||||
|
||||
```text {copy=false}
|
||||
Mon Jan 2 15:04:05 MST 2006
|
||||
```
|
||||
|
||||
Create a format string using these components:
|
||||
|
||||
Description|Valid components
|
||||
:--|:--
|
||||
Year|`"2006" "06"`
|
||||
Month|`"Jan" "January" "01" "1"`
|
||||
Day of the week|`"Mon" "Monday"`
|
||||
Day of the month|`"2" "_2" "02"`
|
||||
Day of the year|`"__2" "002"`
|
||||
Hour|`"15" "3" "03"`
|
||||
Minute|`"4" "04"`
|
||||
Second|`"5" "05"`
|
||||
AM/PM mark|`"PM"`
|
||||
Time zone offsets|`"-0700" "-07:00" "-07" "-070000" "-07:00:00"`
|
||||
|
||||
Replace the sign in the format string with a Z to print Z instead of an offset for the UTC zone.
|
||||
|
||||
Description|Valid components
|
||||
:--|:--
|
||||
Time zone offsets|`"Z0700" "Z07:00" "Z07" "Z070000" "Z07:00:00"`
|
||||
|
||||
```go-html-template
|
||||
{{ $t := "2023-01-27T23:44:58-08:00" }}
|
||||
{{ $t = time.AsTime $t }}
|
||||
{{ $t = $t.Format "Jan 02, 2006 3:04 PM Z07:00" }}
|
||||
|
||||
{{ $t }} → Jan 27, 2023 11:44 PM -08:00
|
||||
```
|
||||
|
||||
Strings such as `PST` and `CET` are not time zones. They are time zone _abbreviations_.
|
||||
|
||||
Strings such as `-07:00` and `+01:00` are not time zones. They are time zone _offsets_.
|
||||
|
||||
A time zone is a geographic area with the same local time. For example, the time zone abbreviated by `PST` and `PDT` (depending on Daylight Savings Time) is `America/Los_Angeles`.
|
||||
@@ -1,105 +0,0 @@
|
||||
---
|
||||
title: apply
|
||||
description: Given an array or slice, `apply` returns a new slice with a function applied over it.
|
||||
categories: [functions]
|
||||
menu:
|
||||
docs:
|
||||
parent: functions
|
||||
keywords: [advanced]
|
||||
signature: ["apply COLLECTION FUNCTION [PARAM...]"]
|
||||
relatedfuncs: []
|
||||
---
|
||||
|
||||
`apply` expects at least three arguments, depending on the function being applied.
|
||||
|
||||
1. The first argument is the sequence to operate on.
|
||||
2. The second argument is the name of the function as a string, which must be the name of a valid [Hugo function][functions].
|
||||
3. After that, the arguments to the applied function are provided, with the string `"."` standing in for each element of the sequence the function is to be applied against.
|
||||
|
||||
Here is an example of a content file with `names:` as a front matter field:
|
||||
|
||||
{{< code-toggle file="content/example.md" fm=true copy=false >}}
|
||||
title: Example
|
||||
names: [ "Derek Perkins", "Joe Bergevin", "Tanner Linsley" ]
|
||||
{{< /code-toggle >}}
|
||||
|
||||
You can then use `apply` as follows:
|
||||
|
||||
```go-html-template
|
||||
{{ apply .Params.names "urlize" "." }}
|
||||
```
|
||||
|
||||
Which will result in the following:
|
||||
|
||||
```
|
||||
"derek-perkins", "joe-bergevin", "tanner-linsley"
|
||||
```
|
||||
|
||||
This is *roughly* equivalent to using the following with [range]:
|
||||
|
||||
```go-html-template
|
||||
{{ range .Params.names }}{{ . | urlize }}{{ end }}
|
||||
```
|
||||
|
||||
However, it is not possible to provide the output of a range to the [`delimit` function][delimit], so you need to `apply` it.
|
||||
|
||||
If you have `post-tag-list.html` and `post-tag-link.html` as [partials], you *could* use the following snippets, respectively:
|
||||
|
||||
{{< code file="layouts/partials/post-tag-list.html" copy=false >}}
|
||||
{{ with .Params.tags }}
|
||||
<div class="tags-list">
|
||||
Tags:
|
||||
{{ $len := len . }}
|
||||
{{ if eq $len 1 }}
|
||||
{{ partial "post-tag-link.html" (index . 0) }}
|
||||
{{ else }}
|
||||
{{ $last := sub $len 1 }}
|
||||
{{ range first $last . }}
|
||||
{{ partial "post-tag-link.html" . }},
|
||||
{{ end }}
|
||||
{{ partial "post-tag-link.html" (index . $last) }}
|
||||
{{ end }}
|
||||
</div>
|
||||
{{ end }}
|
||||
{{< /code >}}
|
||||
|
||||
{{< code file="layouts/partials/post-tag-link.html" copy=false >}}
|
||||
<a class="post-tag post-tag-{{ . | urlize }}" href="/tags/{{ . | urlize }}">{{ . }}</a>
|
||||
{{< /code >}}
|
||||
|
||||
This works, but the complexity of `post-tag-list.html` is fairly high. The Hugo template needs to perform special behavior for the case where there’s only one tag, and it has to treat the last tag as special. Additionally, the tag list will be rendered something like `Tags: tag1 , tag2 , tag3` because of the way that the HTML is generated and then interpreted by a browser.
|
||||
|
||||
This first version of `layouts/partials/post-tag-list.html` separates all of the operations for ease of reading. The combined and DRYer version is shown next:
|
||||
|
||||
```go-html-template
|
||||
{{ with .Params.tags }}
|
||||
<div class="tags-list">
|
||||
Tags:
|
||||
{{ $sort := sort . }}
|
||||
{{ $links := apply $sort "partial" "post-tag-link.html" "." }}
|
||||
{{ $clean := apply $links "chomp" "." }}
|
||||
{{ delimit $clean ", " }}
|
||||
</div>
|
||||
{{ end }}
|
||||
```
|
||||
|
||||
Now in the completed version, you can sort the tags, convert the tags to links with `layouts/partials/post-tag-link.html`, [chomp] off stray newlines, and join the tags together in a delimited list for presentation. Here is an even DRYer version of the preceding example:
|
||||
|
||||
{{< code file="layouts/partials/post-tag-list.html" >}}
|
||||
{{ with .Params.tags }}
|
||||
<div class="tags-list">
|
||||
Tags:
|
||||
{{ delimit (apply (apply (sort .) "partial" "post-tag-link.html" ".") "chomp" ".") ", " }}
|
||||
</div>
|
||||
{{ end }}
|
||||
{{< /code >}}
|
||||
|
||||
{{% note %}}
|
||||
`apply` does not work when receiving the sequence as an argument through a pipeline.
|
||||
{{% /note %}}
|
||||
|
||||
[chomp]: /functions/chomp/ "See documentation for the chomp function"
|
||||
[delimit]: /functions/delimit/ "See documentation for the delimit function"
|
||||
[functions]: /functions/ "See the full list of Hugo functions to see what can be passed as an argument to the apply function."
|
||||
[partials]: /templates/partials/
|
||||
[range]: /functions/range/ "Learn the importance of the range function, a fundamental keyword in both Hugo templates and the Go programming language."
|
||||
@@ -1,28 +0,0 @@
|
||||
---
|
||||
title: base64
|
||||
description: "`base64Encode` and `base64Decode` let you easily decode content with a base64 encoding and vice versa through pipes."
|
||||
categories: [functions]
|
||||
menu:
|
||||
docs:
|
||||
parent: functions
|
||||
keywords: []
|
||||
relatedfuncs: []
|
||||
signature: ["base64Decode INPUT", "base64Encode INPUT"]
|
||||
---
|
||||
|
||||
```go-html-template
|
||||
{{ "Hugo" | base64Encode }} → "SHVnbw=="
|
||||
{{ "SHVnbw==" | base64Decode }} → "Hugo"
|
||||
```
|
||||
|
||||
## `base64` with APIs
|
||||
|
||||
Using base64 to decode and encode becomes really powerful if we have to handle
|
||||
responses from APIs.
|
||||
|
||||
```go-html-template
|
||||
{{ $resp := getJSON "https://api.github.com/repos/gohugoio/hugo/readme" }}
|
||||
{{ $resp.content | base64Decode | markdownify }}
|
||||
```
|
||||
|
||||
The response of the GitHub API contains the base64-encoded version of the [README.md](https://github.com/gohugoio/hugo/blob/master/README.md) in the Hugo repository. Now we can decode it and parse the Markdown. The final output will look similar to the rendered version on GitHub.
|
||||
@@ -1,13 +1,21 @@
|
||||
---
|
||||
title: float
|
||||
title: cast.ToFloat
|
||||
linkTitle: float
|
||||
description: Casts a value to a decimal (base 10) floating point value.
|
||||
categories: [functions]
|
||||
keywords: []
|
||||
menu:
|
||||
docs:
|
||||
parent: functions
|
||||
keywords: [cast,strings,floats]
|
||||
signature: ["float INPUT"]
|
||||
relatedfuncs: []
|
||||
function:
|
||||
aliases: [float]
|
||||
returnType: float64
|
||||
signatures: [cast.ToFloat INPUT]
|
||||
relatedFunctions:
|
||||
- cast.ToFloat
|
||||
- cast.ToInt
|
||||
- cast.ToString
|
||||
aliases: [/functions/float]
|
||||
---
|
||||
|
||||
With a decimal (base 10) input:
|
||||
@@ -1,13 +1,21 @@
|
||||
---
|
||||
title: int
|
||||
title: cast.ToInt
|
||||
linkTitle: int
|
||||
description: Casts a value to a decimal (base 10) integer.
|
||||
categories: [functions]
|
||||
keywords: []
|
||||
menu:
|
||||
docs:
|
||||
parent: functions
|
||||
keywords: [cast,strings,integers]
|
||||
signature: ["int INPUT"]
|
||||
relatedfuncs: []
|
||||
function:
|
||||
aliases: [int]
|
||||
returnType: int
|
||||
signatures: [cast.ToInt INPUT]
|
||||
relatedFunctions:
|
||||
- cast.ToFloat
|
||||
- cast.ToInt
|
||||
- cast.ToString
|
||||
aliases: [/functions/int]
|
||||
---
|
||||
|
||||
With a decimal (base 10) input:
|
||||
@@ -1,13 +1,21 @@
|
||||
---
|
||||
title: string
|
||||
title: cast.ToString
|
||||
linkTitle: string
|
||||
description: Cast a value to a string.
|
||||
categories: [functions]
|
||||
keywords: []
|
||||
menu:
|
||||
docs:
|
||||
parent: functions
|
||||
keywords: [cast,strings]
|
||||
signature: ["string INPUT"]
|
||||
relatedfuncs: []
|
||||
function:
|
||||
aliases: [string]
|
||||
returnType: string
|
||||
signatures: [cast.ToString INPUT]
|
||||
relatedFunctions:
|
||||
- cast.ToFloat
|
||||
- cast.ToInt
|
||||
- cast.ToString
|
||||
aliases: [/functions/string]
|
||||
---
|
||||
|
||||
With a decimal (base 10) input:
|
||||
@@ -1,20 +0,0 @@
|
||||
---
|
||||
title: chomp
|
||||
toc: true
|
||||
description: Removes any trailing newline characters.
|
||||
categories: [functions]
|
||||
menu:
|
||||
docs:
|
||||
parent: functions
|
||||
keywords: [trim]
|
||||
signature:
|
||||
- "chomp INPUT"
|
||||
- "strings.Chomp INPUT"
|
||||
relatedfuncs: [truncate]
|
||||
---
|
||||
|
||||
Useful in a pipeline to remove newlines added by other processing (e.g., [`markdownify`](/functions/markdownify/)).
|
||||
|
||||
```go-html-template
|
||||
{{ chomp "<p>Blockhead</p>\n" }} → "<p>Blockhead</p>"
|
||||
```
|
||||
+18
-10
@@ -1,16 +1,24 @@
|
||||
---
|
||||
title: after
|
||||
description: "`after` slices an array to only the items after the <em>N</em>th item."
|
||||
title: collections.After
|
||||
linkTitle: after
|
||||
description: Slices an array to the items after the Nth item.
|
||||
categories: [functions]
|
||||
keywords: []
|
||||
menu:
|
||||
docs:
|
||||
parent: functions
|
||||
keywords: [iteration]
|
||||
signature: ["after INDEX COLLECTION"]
|
||||
relatedfuncs: [last,first,seq]
|
||||
function:
|
||||
aliases: [after]
|
||||
returnType: any
|
||||
signatures: [collections.After INDEX COLLECTION]
|
||||
relatedFunctions:
|
||||
- collections.After
|
||||
- collections.First
|
||||
- collections.Last
|
||||
aliases: [/functions/after]
|
||||
---
|
||||
|
||||
The following shows `after` being used in conjunction with the [`slice` function][slice]:
|
||||
The following shows `after` being used in conjunction with the [`slice`]function:
|
||||
|
||||
```go-html-template
|
||||
{{ $data := slice "one" "two" "three" "four" }}
|
||||
@@ -22,7 +30,7 @@ The following shows `after` being used in conjunction with the [`slice` function
|
||||
|
||||
## Example of `after` with `first`: 2nd–4th most recent articles
|
||||
|
||||
You can use `after` in combination with the [`first` function] and Hugo's [powerful sorting methods][lists]. Let's assume you have a list page at `example.com/articles`. You have 10 articles, but you want your templating for the [list/section page] to show only two rows:
|
||||
You can use `after` in combination with the [`first`] function and Hugo's [powerful sorting methods][lists]. Let's assume you have a list page at `example.com/articles`. You have 10 articles, but you want your templating for the [list/section page] to show only two rows:
|
||||
|
||||
1. The top row is titled "Featured" and shows only the most recently published article (i.e. by `publishdate` in the content files' front matter).
|
||||
2. The second row is titled "Recent Articles" and shows only the 2nd- to 4th-most recently published articles.
|
||||
@@ -52,7 +60,7 @@ You can use `after` in combination with the [`first` function] and Hugo's [power
|
||||
{{ end }}
|
||||
{{< /code >}}
|
||||
|
||||
[`first` function]: /functions/first/
|
||||
[list/section page]: /templates/section-templates/
|
||||
[`first`]: /functions/collections/first
|
||||
[list/section page]: /templates/section-templates
|
||||
[lists]: /templates/lists/#order-content
|
||||
[slice]: /functions/slice/
|
||||
[`slice`]: /functions/collections/slice/
|
||||
+14
-6
@@ -1,13 +1,23 @@
|
||||
---
|
||||
title: append
|
||||
title: collections.Append
|
||||
linkTitle: append
|
||||
description: Appends one or more elements to a slice and returns the resulting slice.
|
||||
categories: [functions]
|
||||
keywords: []
|
||||
menu:
|
||||
docs:
|
||||
parent: functions
|
||||
keywords: [collections]
|
||||
signature: ["COLLECTION | append ELEMENT [ELEMENT]...", "COLLECTION | append COLLECTION"]
|
||||
relatedfuncs: [last,first,where,slice]
|
||||
function:
|
||||
aliases: [append]
|
||||
returnType: any
|
||||
signatures:
|
||||
- COLLECTION | collections.Append ELEMENT [ELEMENT]...
|
||||
- COLLECTION | collections.Append COLLECTION
|
||||
relatedFunctions:
|
||||
- collections.Append
|
||||
- collections.Merge
|
||||
- collections.Slice
|
||||
aliases: [/functions/append]
|
||||
---
|
||||
|
||||
This function appends all elements, excluding the last, to the last element. This allows [pipe](/getting-started/glossary/#pipeline) constructs as shown below.
|
||||
@@ -81,8 +91,6 @@ To create a slice of slices, starting with an empty slice:
|
||||
{{ $s }} → [[a b] [c d]]
|
||||
```
|
||||
|
||||
|
||||
|
||||
Although the elements in the examples above are strings, you can use the `append` function with any data type, including Pages. For example, on the home page of a corporate site, to display links to the two most recent press releases followed by links to the four most recent articles:
|
||||
|
||||
```go-html-template
|
||||
@@ -0,0 +1,37 @@
|
||||
---
|
||||
title: collections.Apply
|
||||
linkTitle: apply
|
||||
description: Returns a new collection with each element transformed by the given function.
|
||||
categories: [functions]
|
||||
keywords: []
|
||||
menu:
|
||||
docs:
|
||||
parent: functions
|
||||
function:
|
||||
aliases: [apply]
|
||||
returnType: '[]any'
|
||||
signatures: [collections.Apply COLLECTION FUNCTION PARAM...]
|
||||
relatedFunctions:
|
||||
- collections.Apply
|
||||
- collections.Delimit
|
||||
- collections.In
|
||||
- collections.Reverse
|
||||
- collections.Seq
|
||||
- collections.Slice
|
||||
aliases: [/functions/apply]
|
||||
---
|
||||
|
||||
The `apply` function takes three or more arguments, depending on the function being applied to the collection elements.
|
||||
|
||||
The first argument is the collection itself, the second argument is the function name, and the remaining arguments are passed to the function, with the string `"."` representing the collection element.
|
||||
|
||||
|
||||
```go-html-template
|
||||
{{ $s := slice "hello" "world" }}
|
||||
|
||||
{{ $s = apply $s "strings.FirstUpper" "." }}
|
||||
{{ $s }} → [Hello World]
|
||||
|
||||
{{ $s = apply $s "strings.Replace" "." "l" "_" }}
|
||||
{{ $s }} → [He__o Wor_d]
|
||||
```
|
||||
+14
-7
@@ -1,15 +1,22 @@
|
||||
---
|
||||
title: complement
|
||||
title: collections.Complement
|
||||
linkTitle: complement
|
||||
description: Returns the elements of the last collection that are not in any of the others.
|
||||
categories: [functions]
|
||||
keywords: []
|
||||
menu:
|
||||
docs:
|
||||
parent: functions
|
||||
keywords: [collections]
|
||||
signature:
|
||||
- "complement COLLECTION [COLLECTION]..."
|
||||
- "collections.Complement COLLECTION [COLLECTION]..."
|
||||
relatedfuncs: [intersect,symdiff,union]
|
||||
function:
|
||||
aliases: [complement]
|
||||
returnType: any
|
||||
signatures: ['collections.Complement COLLECTION [COLLECTION]...']
|
||||
relatedFunctions:
|
||||
- collections.Complement
|
||||
- collections.Intersect
|
||||
- collections.SymDiff
|
||||
- collections.Union
|
||||
aliases: [/functions/complement]
|
||||
---
|
||||
|
||||
To find the elements within `$c3` that do not exist in `$c1` or `$c2`:
|
||||
@@ -57,7 +64,7 @@ To list everything except blog articles (`blog`) and frequently asked questions
|
||||
{{% note %}}
|
||||
Although the example above demonstrates the `complement` function, you could use the [`where`] function as well:
|
||||
|
||||
[`where`]: /functions/where/
|
||||
[`where`]: /functions/collections/where
|
||||
{{% /note %}}
|
||||
|
||||
```go-html-template
|
||||
+16
-4
@@ -1,13 +1,25 @@
|
||||
---
|
||||
title: delimit
|
||||
title: collections.Delimit
|
||||
linkTitle: delimit
|
||||
description: Loops through any array, slice, or map and returns a string of all the values separated by a delimiter.
|
||||
categories: [functions]
|
||||
keywords: []
|
||||
menu:
|
||||
docs:
|
||||
parent: functions
|
||||
keywords: [iteration]
|
||||
signature: ["delimit COLLECTION DELIMITER [LAST]"]
|
||||
relatedfuncs: []
|
||||
function:
|
||||
aliases: [delimit]
|
||||
returnType: template.HTML
|
||||
signatures: ['collections.Delimit COLLECTION DELIMITER [LAST]']
|
||||
relatedFunctions:
|
||||
- collections.Apply
|
||||
- collections.Delimit
|
||||
- collections.In
|
||||
- collections.Reverse
|
||||
- collections.Seq
|
||||
- collections.Slice
|
||||
- strings.Split
|
||||
aliases: [/functions/delimit]
|
||||
---
|
||||
|
||||
Delimit a slice:
|
||||
+14
-4
@@ -1,13 +1,23 @@
|
||||
---
|
||||
title: dict
|
||||
title: collections.Dictionary
|
||||
linkTitle: dict
|
||||
description: Creates a map from a list of key and value pairs.
|
||||
categories: [functions]
|
||||
keywords: []
|
||||
menu:
|
||||
docs:
|
||||
parent: functions
|
||||
keywords: [collections]
|
||||
signature: ["dict KEY VALUE [KEY VALUE]..."]
|
||||
relatedfuncs: []
|
||||
function:
|
||||
aliases: [dict]
|
||||
returnType: mapany
|
||||
signatures: ['collections.Dictionary KEY VALUE [KEY VALUE]...']
|
||||
relatedFunctions:
|
||||
- collections.Dictionary
|
||||
- collections.Group
|
||||
- collections.Index
|
||||
- collections.IsSet
|
||||
- collections.Where
|
||||
aliases: [/functions/dict]
|
||||
---
|
||||
|
||||
`dict` is especially useful for passing more than one value to a partial template.
|
||||
@@ -0,0 +1,40 @@
|
||||
---
|
||||
title: collections.EchoParam
|
||||
linkTitle: echoParam
|
||||
description: Prints a parameter if it is set.
|
||||
categories: [functions]
|
||||
keywords: []
|
||||
menu:
|
||||
docs:
|
||||
parent: functions
|
||||
function:
|
||||
aliases: [echoParam]
|
||||
returnType: any
|
||||
signatures: [collections.EchoParam COLLECTION KEY]
|
||||
relatedFunctions: []
|
||||
aliases: [/functions/echoparam]
|
||||
---
|
||||
|
||||
For example, consider this site configuration:
|
||||
|
||||
{{< code-toggle file=hugo copy=false >}}
|
||||
[params.footer]
|
||||
poweredBy = 'Hugo'
|
||||
{{< /code-toggle >}}
|
||||
|
||||
To print the value of `poweredBy`:
|
||||
|
||||
```go-html-template
|
||||
{{ echoParam site.Params.footer "poweredby" }} → Hugo
|
||||
```
|
||||
|
||||
{{% note %}}
|
||||
When using the `echoParam` function you must reference the key using lower case. See the previous example.
|
||||
|
||||
The `echoParam` function will be deprecated in a future release. Instead, use either of the constructs below.
|
||||
{{% /note %}}
|
||||
|
||||
```go-html-template
|
||||
{{ site.Params.footer.poweredBy }} → Hugo
|
||||
{{ index site.Params.footer "poweredBy" }} → Hugo
|
||||
```
|
||||
+18
-10
@@ -1,13 +1,21 @@
|
||||
---
|
||||
title: first
|
||||
description: "Slices an array to only the first _N_ elements."
|
||||
title: collections.First
|
||||
linkTitle: first
|
||||
description: Slices an array to the first N elements.
|
||||
categories: [functions]
|
||||
keywords: []
|
||||
menu:
|
||||
docs:
|
||||
parent: functions
|
||||
keywords: [iteration]
|
||||
signature: ["first LIMIT COLLECTION"]
|
||||
relatedfuncs: [after,last]
|
||||
function:
|
||||
aliases: [first]
|
||||
returnType: any
|
||||
signatures: [collections.First LIMIT COLLECTION]
|
||||
relatedFunctions:
|
||||
- collections.After
|
||||
- collections.First
|
||||
- collections.Last
|
||||
aliases: [/functions/first]
|
||||
---
|
||||
|
||||
`first` works in a similar manner to the [`limit` keyword in
|
||||
@@ -28,9 +36,9 @@ elements. It takes the array and number of elements as input.
|
||||
|
||||
## `first` and `where` Together
|
||||
|
||||
Using `first` and [`where`][wherefunction] together can be very
|
||||
powerful. Below snippet gets a list of posts only from [**main
|
||||
sections**][mainsections], sorts it by the `title` parameter, and then
|
||||
Using `first` and [`where`] together can be very
|
||||
powerful. Below snippet gets a list of posts only from [main
|
||||
sections], sorts it by the `title` parameter, and then
|
||||
ranges through only the first 5 posts in that list:
|
||||
|
||||
{{< code file="first-and-where-together.html" >}}
|
||||
@@ -41,5 +49,5 @@ ranges through only the first 5 posts in that list:
|
||||
|
||||
|
||||
[limitkeyword]: https://www.techonthenet.com/sql/select_limit.php
|
||||
[wherefunction]: /functions/where/
|
||||
[mainsections]: /functions/where/#mainsections
|
||||
[`where`]: /functions/collections/where
|
||||
[main sections]: /functions/collections/where#mainsections
|
||||
@@ -0,0 +1,40 @@
|
||||
---
|
||||
title: collections.Group
|
||||
linkTitle: group
|
||||
description: Groups a list of pages.
|
||||
categories: [functions]
|
||||
keywords: []
|
||||
menu:
|
||||
docs:
|
||||
parent: functions
|
||||
function:
|
||||
aliases: [group]
|
||||
returnType: any
|
||||
signatures: [PAGES | collections.Group KEY]
|
||||
relatedFunctions:
|
||||
- collections.Dictionary
|
||||
- collections.Group
|
||||
- collections.Index
|
||||
- collections.IsSet
|
||||
- collections.Where
|
||||
aliases: [/functions/group]
|
||||
---
|
||||
|
||||
{{< code file="layouts/partials/groups.html" >}}
|
||||
{{ $new := .Site.RegularPages | first 10 | group "New" }}
|
||||
{{ $old := .Site.RegularPages | last 10 | group "Old" }}
|
||||
{{ $groups := slice $new $old }}
|
||||
{{ range $groups }}
|
||||
<h3>{{ .Key }}{{/* Prints "New", "Old" */}}</h3>
|
||||
<ul>
|
||||
{{ range .Pages }}
|
||||
<li>
|
||||
<a href="{{ .Permalink }}">{{ .Title }}</a>
|
||||
<div class="meta">{{ .Date.Format "Mon, Jan 2, 2006" }}</div>
|
||||
</li>
|
||||
{{ end }}
|
||||
</ul>
|
||||
{{ end }}
|
||||
{{< /code >}}
|
||||
|
||||
The page group you get from `group` is of the same type you get from the built-in [group methods](/templates/lists#group-content) in Hugo. The above example can be [paginated](/templates/pagination/#list-paginator-pages).
|
||||
@@ -0,0 +1,38 @@
|
||||
---
|
||||
title: collections.In
|
||||
linkTitle: in
|
||||
description: Reports whether an element is in an array or slice, or if a substring is in a string.
|
||||
keywords: []
|
||||
menu:
|
||||
docs:
|
||||
parent: functions
|
||||
function:
|
||||
aliases: [in]
|
||||
returnType: bool
|
||||
signatures: [collections.In SET ITEM]
|
||||
relatedFunctions:
|
||||
- collections.Slice
|
||||
aliases: [/functions/in]
|
||||
---
|
||||
|
||||
|
||||
|
||||
```go-html-template
|
||||
{{ $s := slice "a" "b" "c" }}
|
||||
{{ in $s "b" }} → true
|
||||
```
|
||||
|
||||
```go-html-template
|
||||
{{ $s := slice 1 2 3 }}
|
||||
{{ in $s 2 }} → true
|
||||
```
|
||||
|
||||
```go-html-template
|
||||
{{ $s := slice 1.11 2.22 3.33 }}
|
||||
{{ in $s 2.22 }} → true
|
||||
```
|
||||
|
||||
```go-html-template
|
||||
{{ $s := "abc" }}
|
||||
{{ in $s "b" }} → true
|
||||
```
|
||||
+17
-5
@@ -1,14 +1,26 @@
|
||||
---
|
||||
title: index
|
||||
title: collections.Index
|
||||
linkTitle: index
|
||||
description: Looks up the index(es) or key(s) of the data structure passed into it.
|
||||
categories: [functions]
|
||||
keywords: []
|
||||
menu:
|
||||
docs:
|
||||
parent: functions
|
||||
keywords: []
|
||||
signature: ["index COLLECTION INDEXES", "index COLLECTION KEYS"]
|
||||
relatedfuncs: []
|
||||
aliases: [/functions/index/]
|
||||
function:
|
||||
aliases: [index]
|
||||
returnType: any
|
||||
signatures:
|
||||
- collections.Index COLLECTION INDEXES
|
||||
- collections.Index COLLECTION KEYS
|
||||
relatedFunctions:
|
||||
- collections.Dictionary
|
||||
- collections.EchoParam
|
||||
- collections.Group
|
||||
- collections.Index
|
||||
- collections.IsSet
|
||||
- collections.Where
|
||||
aliases: [/functions/index,/functions/index-function]
|
||||
---
|
||||
|
||||
The `index` functions returns the result of indexing its first argument by the following arguments. Each indexed item must be a map or a slice, e.g.:
|
||||
+14
-5
@@ -1,13 +1,22 @@
|
||||
---
|
||||
title: intersect
|
||||
title: collections.Intersect
|
||||
linkTitle: intersect
|
||||
description: Returns the common elements of two arrays or slices, in the same order as the first array.
|
||||
categories: [functions]
|
||||
keywords: []
|
||||
menu:
|
||||
docs:
|
||||
parent: functions
|
||||
keywords: [collections,intersect,union,complement,symdiff]
|
||||
signature: ["intersect SET1 SET2"]
|
||||
relatedfuncs: []
|
||||
function:
|
||||
aliases: [intersect]
|
||||
returnType: any
|
||||
signatures: [collections.Intersect SET1 SET2]
|
||||
relatedFunctions:
|
||||
- collections.Complement
|
||||
- collections.Intersect
|
||||
- collections.SymDiff
|
||||
- collections.Union
|
||||
aliases: [/functions/intersect]
|
||||
---
|
||||
A useful example is to use it as `AND` filters when combined with where:
|
||||
|
||||
@@ -21,7 +30,7 @@ A useful example is to use it as `AND` filters when combined with where:
|
||||
|
||||
The above fetches regular pages not of `page` or `about` type unless they are pinned. And finally, we exclude all pages with no `images` set in Page parameters.
|
||||
|
||||
See [union](/functions/union) for `OR`.
|
||||
See [union](/functions/collections/union) for `OR`.
|
||||
|
||||
|
||||
[partials]: /templates/partials/
|
||||
@@ -0,0 +1,52 @@
|
||||
---
|
||||
title: collections.IsSet
|
||||
linkTitle: isset
|
||||
description: Reports whether the key exists within the collection.
|
||||
categories: [functions]
|
||||
keywords: []
|
||||
menu:
|
||||
docs:
|
||||
parent: functions
|
||||
function:
|
||||
aliases: [isset]
|
||||
returnType: bool
|
||||
signatures: [collections.IsSet COLLECTION KEY]
|
||||
relatedFunctions:
|
||||
- collections.Dictionary
|
||||
- collections.Group
|
||||
- collections.Index
|
||||
- collections.IsSet
|
||||
- collections.Where
|
||||
aliases: [/functions/isset]
|
||||
---
|
||||
|
||||
For example, consider this site configuration:
|
||||
|
||||
{{< code-toggle file=hugo copy=false >}}
|
||||
[params]
|
||||
showHeroImage = false
|
||||
{{< /code-toggle >}}
|
||||
|
||||
It the value of `showHeroImage` is `true`, we can detect that it exists using either `if` or `with`:
|
||||
|
||||
```go-html-template
|
||||
{{ if site.Params.showHeroImage }}
|
||||
{{ site.Params.showHeroImage }} → true
|
||||
{{ end }}
|
||||
|
||||
{{ with site.Params.showHeroImage }}
|
||||
{{ . }} → true
|
||||
{{ end }}
|
||||
```
|
||||
|
||||
But if the value of `showHeroImage` is `false`, we can't use either `if` or `with` to detect its existence. In this case, you must use the `isset` function:
|
||||
|
||||
```go-html-template
|
||||
{{ if isset site.Params "showheroimage" }}
|
||||
<p>The showHeroImage parameter is set to {{ site.Params.showHeroImage }}.<p>
|
||||
{{ end }}
|
||||
```
|
||||
|
||||
{{% note %}}
|
||||
When using the `isset` function you must reference the key using lower case. See the previous example.
|
||||
{{% /note %}}
|
||||
@@ -0,0 +1,45 @@
|
||||
---
|
||||
title: collections.KeyVals
|
||||
linkTitle: keyVals
|
||||
description: Returns a KeyVals struct.
|
||||
categories: [functions]
|
||||
keywords: []
|
||||
menu:
|
||||
docs:
|
||||
parent: functions
|
||||
function:
|
||||
aliases: [keyVals]
|
||||
returnType: KeyValues
|
||||
signatures: [collections.KeyVals KEY VALUES...]
|
||||
relatedFunctions: []
|
||||
aliases: [/functions/keyvals]
|
||||
---
|
||||
|
||||
The primary application for this function is the definition of the `namedSlices` parameter in the options map passed to the `.Related` method on the `Page` object.
|
||||
|
||||
See [related content](/content-management/related).
|
||||
|
||||
```go-html-template
|
||||
{{ $kv := keyVals "foo" "a" "b" "c" }}
|
||||
```
|
||||
|
||||
The resulting data structure is:
|
||||
|
||||
```json
|
||||
{
|
||||
"Key": "foo",
|
||||
"Values": [
|
||||
"a",
|
||||
"b",
|
||||
"c"
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
To extract the key and values:
|
||||
|
||||
```go-html-template
|
||||
|
||||
{{ $kv.Key }} → foo
|
||||
{{ $kv.Values }} → [a b c]
|
||||
```
|
||||
@@ -0,0 +1,25 @@
|
||||
---
|
||||
title: collections.Last
|
||||
linkTitle: last
|
||||
description: Slices an array to the last N elements.
|
||||
categories: [functions]
|
||||
keywords: []
|
||||
menu:
|
||||
docs:
|
||||
parent: functions
|
||||
function:
|
||||
aliases: [last]
|
||||
returnType: any
|
||||
signatures: [collections.Last INDEX COLLECTION]
|
||||
relatedFunctions:
|
||||
- collections.After
|
||||
- collections.First
|
||||
- collections.Last
|
||||
aliases: [/functions/last]
|
||||
---
|
||||
|
||||
```go-html-template
|
||||
{{ range last 10 .Pages }}
|
||||
{{ .Render "summary" }}
|
||||
{{ end }}
|
||||
```
|
||||
+13
-6
@@ -1,13 +1,20 @@
|
||||
---
|
||||
title: merge
|
||||
description: "Returns the result of merging two or more maps."
|
||||
title: collections.Merge
|
||||
linkTitle: merge
|
||||
description: Returns the result of merging two or more maps.
|
||||
categories: [functions]
|
||||
keywords: []
|
||||
menu:
|
||||
docs:
|
||||
parent: functions
|
||||
keywords: [collections]
|
||||
signature: ["collections.Merge MAP MAP...", "merge MAP MAP..."]
|
||||
relatedfuncs: [dict, append, reflect.IsMap, reflect.IsSlice]
|
||||
function:
|
||||
aliases: [merge]
|
||||
returnType: any
|
||||
signatures: [collections.Merge MAP MAP...]
|
||||
relatedFunctions:
|
||||
- collections.Append
|
||||
- collections.Merge
|
||||
aliases: [/functions/merge]
|
||||
---
|
||||
|
||||
Returns the result of merging two or more maps from left to right. If a key already exists, `merge` updates its value. If a key is absent, `merge` inserts the value under the new key.
|
||||
@@ -63,5 +70,5 @@ Example 4
|
||||
```
|
||||
|
||||
{{% note %}}
|
||||
Regardless of depth, merging only applies to maps. For slices, use [append](/functions/append).
|
||||
Regardless of depth, merging only applies to maps. For slices, use [append](/functions/collections/append).
|
||||
{{% /note %}}
|
||||
@@ -0,0 +1,22 @@
|
||||
---
|
||||
title: collections.NewScratch
|
||||
linkTitle: newScratch
|
||||
description: Creates a new Scratch which can be used to store values in a thread safe way.
|
||||
categories: [functions]
|
||||
keywords: []
|
||||
menu:
|
||||
docs:
|
||||
parent: functions
|
||||
function:
|
||||
aliases: [newScratch]
|
||||
returnType: Scratch
|
||||
signatures: [collections.NewScratch ]
|
||||
relatedFunctions: []
|
||||
---
|
||||
|
||||
```go-html-template
|
||||
{{ $scratch := newScratch }}
|
||||
{{ $scratch.Add "b" 2 }}
|
||||
{{ $scratch.Add "b" 2 }}
|
||||
{{ $scratch.Get "b" }} → 4
|
||||
```
|
||||
+13
-4
@@ -1,13 +1,22 @@
|
||||
---
|
||||
title: querify
|
||||
title: collections.Querify
|
||||
linkTitle: querify
|
||||
description: Takes a set or slice of key-value pairs and returns a query string to be appended to URLs.
|
||||
categories: [functions]
|
||||
keywords: []
|
||||
menu:
|
||||
docs:
|
||||
parent: functions
|
||||
keywords: [urls]
|
||||
signature: ["querify KEY VALUE [KEY VALUE]...", "querify COLLECTION"]
|
||||
relatedfuncs: []
|
||||
function:
|
||||
aliases: [querify]
|
||||
returnType: string
|
||||
signatures:
|
||||
- collections.Querify KEY VALUE [KEY VALUE]...
|
||||
- collections.Querify COLLECTION
|
||||
relatedFunctions:
|
||||
- collections.Querify
|
||||
- urlquery
|
||||
aliases: [/functions/querify]
|
||||
---
|
||||
|
||||
`querify` takes a set or slice of key-value pairs and returns a [query string](https://en.wikipedia.org/wiki/Query_string) that can be appended to a URL.
|
||||
@@ -0,0 +1,26 @@
|
||||
---
|
||||
title: collections.Reverse
|
||||
description: Reverses the order of a collection.
|
||||
categories: [functions]
|
||||
keywords: []
|
||||
menu:
|
||||
docs:
|
||||
parent: functions
|
||||
function:
|
||||
aliases: []
|
||||
returnType: any
|
||||
signatures: [collections.Reverse COLLECTION]
|
||||
relatedFunctions:
|
||||
- collections.Apply
|
||||
- collections.Delimit
|
||||
- collections.In
|
||||
- collections.Reverse
|
||||
- collections.Seq
|
||||
- collections.Slice
|
||||
aliases: [/functions/collections.reverse]
|
||||
---
|
||||
|
||||
|
||||
```go-html-template
|
||||
{{ slice 2 1 3 | collections.Reverse }} → [3 1 2]
|
||||
```
|
||||
@@ -1,13 +1,27 @@
|
||||
---
|
||||
title: seq
|
||||
title: collections.Seq
|
||||
linkTitle: seq
|
||||
description: Returns a slice of integers.
|
||||
categories: [functions]
|
||||
keywords: []
|
||||
menu:
|
||||
docs:
|
||||
parent: functions
|
||||
keywords: []
|
||||
signature: ["seq LAST", "seq FIRST LAST", "seq FIRST INCREMENT LAST"]
|
||||
relatedfuncs: []
|
||||
function:
|
||||
aliases: [seq]
|
||||
returnType: '[]int'
|
||||
signatures:
|
||||
- collections.Seq LAST
|
||||
- collections.Seq FIRST LAST
|
||||
- collections.Seq FIRST INCREMENT LAST
|
||||
relatedFunctions:
|
||||
- collections.Apply
|
||||
- collections.Delimit
|
||||
- collections.In
|
||||
- collections.Reverse
|
||||
- collections.Seq
|
||||
- collections.Slice
|
||||
aliases: [/functions/seq]
|
||||
---
|
||||
|
||||
```go-html-template
|
||||
+13
-4
@@ -1,16 +1,25 @@
|
||||
---
|
||||
title: shuffle
|
||||
title: collections.Shuffle
|
||||
linkTitle: shuffle
|
||||
description: Returns a random permutation of a given array or slice.
|
||||
keywords: [ordering]
|
||||
categories: [functions]
|
||||
keywords: []
|
||||
menu:
|
||||
docs:
|
||||
parent: functions
|
||||
signature: ["shuffle COLLECTION"]
|
||||
relatedfuncs: [seq]
|
||||
function:
|
||||
aliases: [shuffle]
|
||||
returnType: any
|
||||
signatures: [collections.Shuffle COLLECTION]
|
||||
relatedFunctions:
|
||||
- collections.Reverse
|
||||
- collections.Shuffle
|
||||
- collections.Sort
|
||||
- collections.Uniq
|
||||
aliases: [/functions/shuffle]
|
||||
---
|
||||
|
||||
|
||||
```go-html-template
|
||||
{{ shuffle (seq 1 2 3) }} → [3 1 2]
|
||||
{{ shuffle (slice "a" "b" "c") }} → [b a c]
|
||||
@@ -0,0 +1,30 @@
|
||||
---
|
||||
title: collections.Slice
|
||||
linkTitle: slice
|
||||
description: Creates a slice (array) of all passed arguments.
|
||||
categories: [functions]
|
||||
keywords: []
|
||||
menu:
|
||||
docs:
|
||||
parent: functions
|
||||
function:
|
||||
aliases: [slice]
|
||||
returnType: any
|
||||
signatures: [collections.Slice ITEM...]
|
||||
relatedFunctions:
|
||||
- collections.Append
|
||||
- collections.Apply
|
||||
- collections.Delimit
|
||||
- collections.In
|
||||
- collections.Reverse
|
||||
- collections.Seq
|
||||
- collections.Slice
|
||||
aliases: [/functions/slice]
|
||||
---
|
||||
|
||||
One use case is the concatenation of elements in combination with the [`delimit` function]:
|
||||
|
||||
```go-html-template
|
||||
{{ $s := slice "a" "b" "c" }}
|
||||
{{ $s }} → [a b c]
|
||||
```
|
||||
@@ -1,13 +1,22 @@
|
||||
---
|
||||
title: sort
|
||||
title: collections.Sort
|
||||
linkTitle: sort
|
||||
description: Sorts slices, maps, and page collections.
|
||||
categories: [functions]
|
||||
signature: ["sort COLLECTION [KEY] [ORDER]"]
|
||||
keywords: []
|
||||
menu:
|
||||
docs:
|
||||
parent: functions
|
||||
keywords: [ordering,sorting,lists]
|
||||
toc: true
|
||||
function:
|
||||
aliases: [sort]
|
||||
returnType: any
|
||||
signatures: ['collections.Sort COLLECTION [KEY] [ORDER]']
|
||||
relatedFunctions:
|
||||
- collections.Reverse
|
||||
- collections.Shuffle
|
||||
- collections.Sort
|
||||
- collections.Uniq
|
||||
aliases: [/functions/sort]
|
||||
---
|
||||
|
||||
The `KEY` is optional when sorting slices in ascending order, otherwise it is required. When sorting slices, use the literal `value` in place of the `KEY`. See examples below.
|
||||
@@ -0,0 +1,28 @@
|
||||
---
|
||||
title: collections.SymDiff
|
||||
linkTitle: symdiff
|
||||
description: Returns the symmetric difference of two collections.
|
||||
categories: [functions]
|
||||
keywords: []
|
||||
menu:
|
||||
docs:
|
||||
parent: functions
|
||||
function:
|
||||
aliases: [symdiff]
|
||||
returnType: any
|
||||
signatures: [COLLECTION | collections.SymDiff COLLECTION]
|
||||
relatedFunctions:
|
||||
- collections.Complement
|
||||
- collections.Intersect
|
||||
- collections.SymDiff
|
||||
- collections.Union
|
||||
aliases: [/functions/symdiff]
|
||||
---
|
||||
|
||||
Example:
|
||||
|
||||
```go-html-template
|
||||
{{ slice 1 2 3 | symdiff (slice 3 4) }} → [1 2 4]
|
||||
```
|
||||
|
||||
Also see https://en.wikipedia.org/wiki/Symmetric_difference
|
||||
+14
-5
@@ -1,13 +1,22 @@
|
||||
---
|
||||
title: union
|
||||
title: collections.Union
|
||||
linkTitle: union
|
||||
description: Given two arrays or slices, returns a new array that contains the elements or objects that belong to either or both arrays/slices.
|
||||
categories: [functions]
|
||||
keywords: []
|
||||
menu:
|
||||
docs:
|
||||
parent: functions
|
||||
keywords: [collections,intersect,union,complement]
|
||||
signature: ["union SET1 SET2"]
|
||||
relatedfuncs: [intersect,where]
|
||||
function:
|
||||
aliases: [union]
|
||||
returnType: any
|
||||
signatures: [collections.Union SET1 SET2]
|
||||
relatedFunctions:
|
||||
- collections.Complement
|
||||
- collections.Intersect
|
||||
- collections.SymDiff
|
||||
- collections.Union
|
||||
aliases: [/functions/union]
|
||||
---
|
||||
|
||||
Given two arrays (or slices) A and B, this function will return a new array that contains the elements or objects that belong to either A or to B or to both. The elements supported are strings, integers, and floats (only float64).
|
||||
@@ -38,4 +47,4 @@ This is also very useful to use as `OR` filters when combined with where:
|
||||
|
||||
The above fetches regular pages not of `page` or `about` type unless they are pinned. And finally, we exclude all pages with no `images` set in Page parameters.
|
||||
|
||||
See [intersect](/functions/intersect) for `AND`.
|
||||
See [intersect](/functions/collections/intersect) for `AND`.
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user