Compare commits

..

1 Commits

Author SHA1 Message Date
Bjørn Erik Pedersen b1163db2c8 commands: Make the server flag --renderToDisk into --renderToMemory (note)
Fixes #11987
2024-02-05 10:16:23 +01:00
205 changed files with 1671 additions and 3729 deletions
+2 -2
View File
@@ -4,7 +4,7 @@ parameters:
defaults: &defaults
resource_class: large
docker:
- image: bepsays/ci-hugoreleaser:1.22200.20000
- image: bepsays/ci-hugoreleaser:1.22100.20600
environment: &buildenv
GOMODCACHE: /root/project/gomodcache
version: 2
@@ -60,7 +60,7 @@ jobs:
environment:
<<: [*buildenv]
docker:
- image: bepsays/ci-hugoreleaser-linux-arm64:1.22200.20000
- image: bepsays/ci-hugoreleaser-linux-arm64:1.22100.20600
steps:
- *restore-cache
- &attach-workspace
+1 -1
View File
@@ -14,7 +14,7 @@ jobs:
test:
strategy:
matrix:
go-version: [1.22.x]
go-version: [1.21.x]
os: [ubuntu-latest]
runs-on: ${{ matrix.os }}
steps:
+1 -1
View File
@@ -16,7 +16,7 @@ jobs:
test:
strategy:
matrix:
go-version: [1.21.x,1.22.x]
go-version: [1.20.x,1.21.x]
os: [ubuntu-latest, macos-latest, windows-latest]
runs-on: ${{ matrix.os }}
steps:
-2
View File
@@ -295,8 +295,6 @@ func (c *Cache) start() func() {
select {
case <-ticker.C:
c.adjustCurrentMaxSize()
// Reset the ticker to avoid drift.
ticker.Reset(c.opts.CheckInterval)
case <-quit:
ticker.Stop()
return
+2 -1
View File
@@ -339,10 +339,11 @@ func (r *rootCommand) Run(ctx context.Context, cd *simplecobra.Commandeer, args
if r.buildWatch {
defer r.timeTrack(time.Now(), "Built")
}
err := b.build()
close, err := b.build()
if err != nil {
return err
}
close()
return nil
}()
if err != nil {
+4 -6
View File
@@ -32,10 +32,8 @@ package commands
import (
"context"
"github.com/gohugoio/hugo/deploy"
"github.com/gohugoio/hugo/deploy/deployconfig"
"github.com/bep/simplecobra"
"github.com/gohugoio/hugo/deploy"
"github.com/spf13/cobra"
)
@@ -64,9 +62,9 @@ documentation.
cmd.Flags().Bool("confirm", false, "ask for confirmation before making changes to the target")
cmd.Flags().Bool("dryRun", false, "dry run")
cmd.Flags().Bool("force", false, "force upload of all files")
cmd.Flags().Bool("invalidateCDN", deployconfig.DefaultConfig.InvalidateCDN, "invalidate the CDN cache listed in the deployment target")
cmd.Flags().Int("maxDeletes", deployconfig.DefaultConfig.MaxDeletes, "maximum # of files to delete, or -1 to disable")
cmd.Flags().Int("workers", deployconfig.DefaultConfig.Workers, "number of workers to transfer files. defaults to 10")
cmd.Flags().Bool("invalidateCDN", deploy.DefaultConfig.InvalidateCDN, "invalidate the CDN cache listed in the deployment target")
cmd.Flags().Int("maxDeletes", deploy.DefaultConfig.MaxDeletes, "maximum # of files to delete, or -1 to disable")
cmd.Flags().Int("workers", deploy.DefaultConfig.Workers, "number of workers to transfer files. defaults to 10")
},
}
}
+9 -11
View File
@@ -361,34 +361,32 @@ func (c *hugoBuilder) newWatcher(pollIntervalStr string, dirList ...string) (*wa
return watcher, nil
}
func (c *hugoBuilder) build() error {
func (c *hugoBuilder) build() (func(), error) {
stopProfiling, err := c.initProfiling()
if err != nil {
return err
return nil, err
}
defer func() {
if stopProfiling != nil {
stopProfiling()
}
}()
if err := c.fullBuild(false); err != nil {
return err
return nil, err
}
if !c.r.quiet {
c.r.Println()
h, err := c.hugo()
if err != nil {
return err
return nil, err
}
h.PrintProcessingStats(os.Stdout)
c.r.Println()
}
return nil
return func() {
if stopProfiling != nil {
stopProfiling()
}
}, nil
}
func (c *hugoBuilder) buildSites(noBuildLock bool) (err error) {
+2 -1
View File
@@ -23,6 +23,7 @@ import (
"time"
"github.com/bep/simplecobra"
"github.com/gohugoio/hugo/config"
"github.com/gohugoio/hugo/hugolib"
"github.com/gohugoio/hugo/resources/page"
"github.com/gohugoio/hugo/resources/resource"
@@ -45,7 +46,7 @@ func newListCommand() *listCommand {
list := func(cd *simplecobra.Commandeer, r *rootCommand, shouldInclude func(page.Page) bool, opts ...any) error {
bcfg := hugolib.BuildCfg{SkipRender: true}
cfg := flagsToCfg(cd, nil)
cfg := config.New()
for i := 0; i < len(opts); i += 2 {
cfg.Set(opts[i].(string), opts[i+1])
}
+10 -2
View File
@@ -495,14 +495,19 @@ func (c *serverCommand) Run(ctx context.Context, cd *simplecobra.Commandeer, arg
}
var close func()
err := func() error {
defer c.r.timeTrack(time.Now(), "Built")
return c.build()
var err error
close, err = c.build()
return err
}()
if err != nil {
return err
}
defer close()
return c.serve()
}
@@ -538,6 +543,9 @@ of a second, you will be able to save and see your changes nearly instantly.`
cmd.Flags().BoolVar(&c.disableFastRender, "disableFastRender", false, "enables full re-renders on changes")
cmd.Flags().BoolVar(&c.disableBrowserError, "disableBrowserError", false, "do not show build errors in the browser")
cmd.Flags().String("memstats", "", "log memory usage to this file")
cmd.Flags().String("meminterval", "100ms", "interval to poll memory usage (requires --memstats), valid time units are \"ns\", \"us\" (or \"µs\"), \"ms\", \"s\", \"m\", \"h\".")
cmd.Flags().SetAnnotation("tlsCertFile", cobra.BashCompSubdirsInDir, []string{})
cmd.Flags().SetAnnotation("tlsKeyFile", cobra.BashCompSubdirsInDir, []string{})
@@ -1087,7 +1095,7 @@ func (s *staticSyncer) syncsStaticEvents(staticEvents []fsnotify.Event) error {
fromPath := ev.Name
relPath, found := sourceFs.MakePathRelative(fromPath, true)
relPath, found := sourceFs.MakePathRelative(fromPath)
if !found {
// Not member of this virtual host.
+1 -1
View File
@@ -17,7 +17,7 @@ package hugo
// This should be the only one.
var CurrentVersion = Version{
Major: 0,
Minor: 124,
Minor: 123,
PatchLevel: 0,
Suffix: "-DEV",
}
+14 -80
View File
@@ -18,11 +18,9 @@ import (
"path/filepath"
"runtime"
"strings"
"sync"
"github.com/gohugoio/hugo/common/types"
"github.com/gohugoio/hugo/hugofs/files"
"github.com/gohugoio/hugo/identity"
)
var defaultPathParser PathParser
@@ -52,54 +50,19 @@ func NormalizePathStringBasic(s string) string {
return s
}
// ParseIdentity parses component c with path s into a StringIdentity.
func (pp *PathParser) ParseIdentity(c, s string) identity.StringIdentity {
p := pp.parsePooled(c, s)
defer putPath(p)
return identity.StringIdentity(p.IdentifierBase())
}
// ParseBaseAndBaseNameNoIdentifier parses component c with path s into a base and a base name without any identifier.
func (pp *PathParser) ParseBaseAndBaseNameNoIdentifier(c, s string) (string, string) {
p := pp.parsePooled(c, s)
defer putPath(p)
return p.Base(), p.BaseNameNoIdentifier()
}
func (pp *PathParser) parsePooled(c, s string) *Path {
s = NormalizePathStringBasic(s)
p := getPath()
p.component = c
p, err := pp.doParse(c, s, p)
if err != nil {
panic(err)
}
return p
}
// Parse parses component c with path s into Path using Hugo's content path rules.
func (pp *PathParser) Parse(c, s string) *Path {
p, err := pp.parse(c, s)
func (parser PathParser) Parse(c, s string) *Path {
p, err := parser.parse(c, s)
if err != nil {
panic(err)
}
return p
}
func (pp *PathParser) newPath(component string) *Path {
return &Path{
component: component,
posContainerLow: -1,
posContainerHigh: -1,
posSectionHigh: -1,
posIdentifierLanguage: -1,
}
}
func (pp *PathParser) parse(component, s string) (*Path, error) {
ss := NormalizePathStringBasic(s)
p, err := pp.doParse(component, ss, pp.newPath(component))
p, err := pp.doParse(component, ss)
if err != nil {
return nil, err
}
@@ -107,7 +70,7 @@ func (pp *PathParser) parse(component, s string) (*Path, error) {
if s != ss {
var err error
// Preserve the original case for titles etc.
p.unnormalized, err = pp.doParse(component, s, pp.newPath(component))
p.unnormalized, err = pp.doParse(component, s)
if err != nil {
return nil, err
@@ -119,7 +82,15 @@ func (pp *PathParser) parse(component, s string) (*Path, error) {
return p, nil
}
func (pp *PathParser) doParse(component, s string, p *Path) (*Path, error) {
func (pp *PathParser) doParse(component, s string) (*Path, error) {
p := &Path{
component: component,
posContainerLow: -1,
posContainerHigh: -1,
posSectionHigh: -1,
posIdentifierLanguage: -1,
}
hasLang := pp.LanguageIndex != nil
hasLang = hasLang && (component == files.ComponentFolderContent || component == files.ComponentFolderLayouts)
@@ -249,7 +220,6 @@ const (
)
type Path struct {
// Note: Any additions to this struct should also be added to the pathPool.
s string
posContainerLow int
@@ -269,37 +239,6 @@ type Path struct {
unnormalized *Path
}
var pathPool = &sync.Pool{
New: func() any {
p := &Path{}
p.reset()
return p
},
}
func getPath() *Path {
return pathPool.Get().(*Path)
}
func putPath(p *Path) {
p.reset()
pathPool.Put(p)
}
func (p *Path) reset() {
p.s = ""
p.posContainerLow = -1
p.posContainerHigh = -1
p.posSectionHigh = -1
p.component = ""
p.bundleType = 0
p.identifiers = p.identifiers[:0]
p.posIdentifierLanguage = -1
p.disabled = false
p.trimLeadingSlash = false
p.unnormalized = nil
}
// TrimLeadingSlash returns a copy of the Path with the leading slash removed.
func (p Path) TrimLeadingSlash() *Path {
p.trimLeadingSlash = true
@@ -315,7 +254,7 @@ func (p *Path) norm(s string) string {
// IdentifierBase satifies identity.Identity.
func (p *Path) IdentifierBase() string {
return p.Base()
return p.Base()[1:]
}
// Component returns the component for this path (e.g. "content").
@@ -541,11 +480,6 @@ func (p *Path) IsLeafBundle() bool {
return p.bundleType == PathTypeLeaf
}
func (p Path) ForBundleType(t PathType) *Path {
p.bundleType = t
return &p
}
func (p *Path) identifierAsString(i int) string {
i = p.identifierIndex(i)
if i == -1 {
-6
View File
@@ -349,9 +349,3 @@ func TestHasExt(t *testing.T) {
c.Assert(HasExt("/a/b/c"), qt.IsFalse)
c.Assert(HasExt("/a/b.c/d"), qt.IsFalse)
}
func BenchmarkParseIdentity(b *testing.B) {
for i := 0; i < b.N; i++ {
testParser.ParseIdentity(files.ComponentFolderAssets, "/a/b.css")
}
}
+6 -16
View File
@@ -37,7 +37,7 @@ import (
"github.com/gohugoio/hugo/config/privacy"
"github.com/gohugoio/hugo/config/security"
"github.com/gohugoio/hugo/config/services"
"github.com/gohugoio/hugo/deploy/deployconfig"
"github.com/gohugoio/hugo/deploy"
"github.com/gohugoio/hugo/helpers"
"github.com/gohugoio/hugo/langs"
"github.com/gohugoio/hugo/markup/markup_config"
@@ -141,8 +141,8 @@ type Config struct {
// <docsmeta>{"refs": ["config:languages:menus"] }</docsmeta>
Menus *config.ConfigNamespace[map[string]navigation.MenuConfig, navigation.Menus] `mapstructure:"-"`
// The deployment configuration section contains for hugo deployconfig.
Deployment deployconfig.DeployConfig `mapstructure:"-"`
// The deployment configuration section contains for hugo deploy.
Deployment deploy.DeployConfig `mapstructure:"-"`
// Module configuration.
Module modules.Config `mapstructure:"-"`
@@ -538,9 +538,6 @@ type RootConfig struct {
// Note that this currently only works for English, but you can provide your own title in the content file's front matter.
PluralizeListTitles bool
// Whether to capitalize automatic page titles, applicable to section, taxonomy, and term pages.
CapitalizeListTitles bool
// Make all relative URLs absolute using the baseURL.
// <docsmeta>{"identifiers": ["baseURL"] }</docsmeta>
CanonifyURLs bool
@@ -666,18 +663,11 @@ type Configs struct {
// All below is set in Init.
Languages langs.Languages
LanguagesDefaultFirst langs.Languages
ContentPathParser *paths.PathParser
ContentPathParser paths.PathParser
configLangs []config.AllProvider
}
func (c *Configs) Validate(logger loggers.Logger) error {
for p := range c.Base.Cascade.Config {
page.CheckCascadePattern(logger, p)
}
return nil
}
// transientErr returns the last transient error found during config compilation.
func (c *Configs) transientErr() error {
for _, l := range c.LanguageConfigSlice {
@@ -745,7 +735,7 @@ func (c *Configs) Init() error {
c.Languages = languages
c.LanguagesDefaultFirst = languagesDefaultFirst
c.ContentPathParser = &paths.PathParser{LanguageIndex: languagesDefaultFirst.AsIndexSet(), IsLangDisabled: c.Base.IsLangDisabled}
c.ContentPathParser = paths.PathParser{LanguageIndex: languagesDefaultFirst.AsIndexSet(), IsLangDisabled: c.Base.IsLangDisabled}
c.configLangs = make([]config.AllProvider, len(c.Languages))
for i, l := range c.LanguagesDefaultFirst {
@@ -976,7 +966,7 @@ func decodeConfigFromParams(fs afero.Fs, logger loggers.Logger, bcfg config.Base
})
for _, v := range decoderSetups {
p := decodeConfig{p: p, c: target, fs: fs, bcfg: bcfg}
p := decodeConfig{p: p, c: target, fs: fs, logger: logger, bcfg: bcfg}
if err := v.decode(v, p); err != nil {
return fmt.Errorf("failed to decode %q: %w", v.key, err)
}
+9 -7
View File
@@ -18,13 +18,14 @@ import (
"strings"
"github.com/gohugoio/hugo/cache/filecache"
"github.com/gohugoio/hugo/common/loggers"
"github.com/gohugoio/hugo/common/maps"
"github.com/gohugoio/hugo/common/types"
"github.com/gohugoio/hugo/config"
"github.com/gohugoio/hugo/config/privacy"
"github.com/gohugoio/hugo/config/security"
"github.com/gohugoio/hugo/config/services"
"github.com/gohugoio/hugo/deploy/deployconfig"
"github.com/gohugoio/hugo/deploy"
"github.com/gohugoio/hugo/langs"
"github.com/gohugoio/hugo/markup/markup_config"
"github.com/gohugoio/hugo/media"
@@ -42,10 +43,11 @@ import (
)
type decodeConfig struct {
p config.Provider
c *Config
fs afero.Fs
bcfg config.BaseConfig
p config.Provider
c *Config
fs afero.Fs
logger loggers.Logger
bcfg config.BaseConfig
}
type decodeWeight struct {
@@ -291,7 +293,7 @@ var allDecoderSetups = map[string]decodeWeight{
key: "cascade",
decode: func(d decodeWeight, p decodeConfig) error {
var err error
p.c.Cascade, err = page.DecodeCascadeConfig(nil, p.p.Get(d.key))
p.c.Cascade, err = page.DecodeCascadeConfig(p.logger, p.p.Get(d.key))
return err
},
},
@@ -331,7 +333,7 @@ var allDecoderSetups = map[string]decodeWeight{
key: "deployment",
decode: func(d decodeWeight, p decodeConfig) error {
var err error
p.c.Deployment, err = deployconfig.DecodeConfig(p.p)
p.c.Deployment, err = deploy.DecodeConfig(p.p)
return err
},
},
+1 -9
View File
@@ -19,7 +19,6 @@ import (
"github.com/gohugoio/hugo/common/paths"
"github.com/gohugoio/hugo/common/urls"
"github.com/gohugoio/hugo/config"
"github.com/gohugoio/hugo/identity"
"github.com/gohugoio/hugo/langs"
)
@@ -43,7 +42,7 @@ func (c ConfigLanguage) LanguagesDefaultFirst() langs.Languages {
return c.m.LanguagesDefaultFirst
}
func (c ConfigLanguage) PathParser() *paths.PathParser {
func (c ConfigLanguage) PathParser() paths.PathParser {
return c.m.ContentPathParser
}
@@ -134,13 +133,6 @@ func (c ConfigLanguage) Watching() bool {
return c.m.Base.Internal.Watch
}
func (c ConfigLanguage) NewIdentityManager(name string) identity.Manager {
if !c.Watching() {
return identity.NopManager
}
return identity.NewManager(name)
}
// GetConfigSection is mostly used in tests. The switch statement isn't complete, but what's in use.
func (c ConfigLanguage) GetConfigSection(s string) any {
switch s {
-1
View File
@@ -189,7 +189,6 @@ func (l configLoader) applyDefaultConfig() error {
"menus": maps.Params{},
"disableLiveReload": false,
"pluralizeListTitles": true,
"capitalizeListTitles": true,
"forceSyncStatic": false,
"footnoteAnchorPrefix": "",
"footnoteReturnLinkContents": "",
+1 -3
View File
@@ -20,7 +20,6 @@ import (
"github.com/gohugoio/hugo/common/paths"
"github.com/gohugoio/hugo/common/types"
"github.com/gohugoio/hugo/common/urls"
"github.com/gohugoio/hugo/identity"
"github.com/gohugoio/hugo/langs"
)
@@ -32,7 +31,7 @@ type AllProvider interface {
LanguagePrefix() string
BaseURL() urls.BaseURL
BaseURLLiveReload() urls.BaseURL
PathParser() *paths.PathParser
PathParser() paths.PathParser
Environment() string
IsMultihost() bool
IsMultiLingual() bool
@@ -58,7 +57,6 @@ type AllProvider interface {
BuildDrafts() bool
Running() bool
Watching() bool
NewIdentityManager(name string) identity.Manager
FastRenderMode() bool
PrintUnusedTemplates() bool
EnableMissingTranslationPlaceholders() bool
+1 -2
View File
@@ -24,7 +24,6 @@ import (
"github.com/aws/aws-sdk-go-v2/aws"
"github.com/aws/aws-sdk-go-v2/service/cloudfront"
"github.com/aws/aws-sdk-go-v2/service/cloudfront/types"
"github.com/gohugoio/hugo/deploy/deployconfig"
gcaws "gocloud.dev/aws"
)
@@ -39,7 +38,7 @@ var v2ConfigValidParams = map[string]bool{
// InvalidateCloudFront invalidates the CloudFront cache for distributionID.
// Uses AWS credentials config from the bucket URL.
func InvalidateCloudFront(ctx context.Context, target *deployconfig.Target) error {
func InvalidateCloudFront(ctx context.Context, target *Target) error {
u, err := url.Parse(target.URL)
if err != nil {
return err
+10 -11
View File
@@ -38,7 +38,6 @@ import (
"github.com/gobwas/glob"
"github.com/gohugoio/hugo/common/loggers"
"github.com/gohugoio/hugo/config"
"github.com/gohugoio/hugo/deploy/deployconfig"
"github.com/gohugoio/hugo/media"
"github.com/spf13/afero"
"golang.org/x/text/unicode/norm"
@@ -58,10 +57,10 @@ type Deployer struct {
mediaTypes media.Types // Hugo's MediaType to guess ContentType
quiet bool // true reduces STDOUT // TODO(bep) remove, this is a global feature.
cfg deployconfig.DeployConfig
cfg DeployConfig
logger loggers.Logger
target *deployconfig.Target // the target to deploy to
target *Target // the target to deploy to
// For tests...
summary deploySummary // summary of latest Deploy results
@@ -75,7 +74,7 @@ const metaMD5Hash = "md5chksum" // the meta key to store md5hash in
// New constructs a new *Deployer.
func New(cfg config.AllProvider, logger loggers.Logger, localFs afero.Fs) (*Deployer, error) {
dcfg := cfg.GetConfigSection(deployconfig.DeploymentConfigKey).(deployconfig.DeployConfig)
dcfg := cfg.GetConfigSection(deploymentConfigKey).(DeployConfig)
targetName := dcfg.Target
if len(dcfg.Targets) == 0 {
@@ -84,7 +83,7 @@ func New(cfg config.AllProvider, logger loggers.Logger, localFs afero.Fs) (*Depl
mediaTypes := cfg.GetConfigSection("mediaTypes").(media.Types)
// Find the target to deploy to.
var tgt *deployconfig.Target
var tgt *Target
if targetName == "" {
// Default to the first target.
tgt = dcfg.Targets[0]
@@ -134,7 +133,7 @@ func (d *Deployer) Deploy(ctx context.Context) error {
// Load local files from the source directory.
var include, exclude glob.Glob
if d.target != nil {
include, exclude = d.target.IncludeGlob, d.target.ExcludeGlob
include, exclude = d.target.includeGlob, d.target.excludeGlob
}
local, err := d.walkLocal(d.localFs, d.cfg.Matchers, include, exclude, d.mediaTypes)
if err != nil {
@@ -179,7 +178,7 @@ func (d *Deployer) Deploy(ctx context.Context) error {
// Order the uploads. They are organized in groups; all uploads in a group
// must be complete before moving on to the next group.
uploadGroups := applyOrdering(d.cfg.Ordering, uploads)
uploadGroups := applyOrdering(d.cfg.ordering, uploads)
nParallel := d.cfg.Workers
var errs []error
@@ -344,14 +343,14 @@ type localFile struct {
UploadSize int64
fs afero.Fs
matcher *deployconfig.Matcher
matcher *Matcher
md5 []byte // cache
gzipped bytes.Buffer // cached of gzipped contents if gzipping
mediaTypes media.Types
}
// newLocalFile initializes a *localFile.
func newLocalFile(fs afero.Fs, nativePath, slashpath string, m *deployconfig.Matcher, mt media.Types) (*localFile, error) {
func newLocalFile(fs afero.Fs, nativePath, slashpath string, m *Matcher, mt media.Types) (*localFile, error) {
f, err := fs.Open(nativePath)
if err != nil {
return nil, err
@@ -483,7 +482,7 @@ func knownHiddenDirectory(name string) bool {
// walkLocal walks the source directory and returns a flat list of files,
// using localFile.SlashPath as the map keys.
func (d *Deployer) walkLocal(fs afero.Fs, matchers []*deployconfig.Matcher, include, exclude glob.Glob, mediaTypes media.Types) (map[string]*localFile, error) {
func (d *Deployer) walkLocal(fs afero.Fs, matchers []*Matcher, include, exclude glob.Glob, mediaTypes media.Types) (map[string]*localFile, error) {
retval := map[string]*localFile{}
err := afero.Walk(fs, "", func(path string, info os.FileInfo, err error) error {
if err != nil {
@@ -522,7 +521,7 @@ func (d *Deployer) walkLocal(fs afero.Fs, matchers []*deployconfig.Matcher, incl
}
// Find the first matching matcher (if any).
var m *deployconfig.Matcher
var m *Matcher
for _, cur := range matchers {
if cur.Matches(slashpath) {
m = cur
@@ -1,4 +1,4 @@
// Copyright 2024 The Hugo Authors. All rights reserved.
// Copyright 2019 The Hugo Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -11,7 +11,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
package deployconfig
package deploy
import (
"errors"
@@ -24,7 +24,7 @@ import (
"github.com/mitchellh/mapstructure"
)
const DeploymentConfigKey = "deployment"
const deploymentConfigKey = "deployment"
// DeployConfig is the complete configuration for deployment.
type DeployConfig struct {
@@ -48,7 +48,7 @@ type DeployConfig struct {
// Number of concurrent workers to use when uploading files.
Workers int
Ordering []*regexp.Regexp `json:"-"` // compiled Order
ordering []*regexp.Regexp // compiled Order
}
type Target struct {
@@ -67,20 +67,20 @@ type Target struct {
Exclude string
// Parsed versions of Include/Exclude.
IncludeGlob glob.Glob `json:"-"`
ExcludeGlob glob.Glob `json:"-"`
includeGlob glob.Glob
excludeGlob glob.Glob
}
func (tgt *Target) ParseIncludeExclude() error {
func (tgt *Target) parseIncludeExclude() error {
var err error
if tgt.Include != "" {
tgt.IncludeGlob, err = hglob.GetGlob(tgt.Include)
tgt.includeGlob, err = hglob.GetGlob(tgt.Include)
if err != nil {
return fmt.Errorf("invalid deployment.target.include %q: %v", tgt.Include, err)
}
}
if tgt.Exclude != "" {
tgt.ExcludeGlob, err = hglob.GetGlob(tgt.Exclude)
tgt.excludeGlob, err = hglob.GetGlob(tgt.Exclude)
if err != nil {
return fmt.Errorf("invalid deployment.target.exclude %q: %v", tgt.Exclude, err)
}
@@ -115,12 +115,12 @@ type Matcher struct {
// other route-determined metadata (e.g., ContentType) has changed.
Force bool
// Re is Pattern compiled.
Re *regexp.Regexp `json:"-"`
// re is Pattern compiled.
re *regexp.Regexp
}
func (m *Matcher) Matches(path string) bool {
return m.Re.MatchString(path)
return m.re.MatchString(path)
}
var DefaultConfig = DeployConfig{
@@ -133,10 +133,10 @@ var DefaultConfig = DeployConfig{
func DecodeConfig(cfg config.Provider) (DeployConfig, error) {
dcfg := DefaultConfig
if !cfg.IsSet(DeploymentConfigKey) {
if !cfg.IsSet(deploymentConfigKey) {
return dcfg, nil
}
if err := mapstructure.WeakDecode(cfg.GetStringMap(DeploymentConfigKey), &dcfg); err != nil {
if err := mapstructure.WeakDecode(cfg.GetStringMap(deploymentConfigKey), &dcfg); err != nil {
return dcfg, err
}
@@ -148,7 +148,7 @@ func DecodeConfig(cfg config.Provider) (DeployConfig, error) {
if *tgt == (Target{}) {
return dcfg, errors.New("empty deployment target")
}
if err := tgt.ParseIncludeExclude(); err != nil {
if err := tgt.parseIncludeExclude(); err != nil {
return dcfg, err
}
}
@@ -157,7 +157,7 @@ func DecodeConfig(cfg config.Provider) (DeployConfig, error) {
if *m == (Matcher{}) {
return dcfg, errors.New("empty deployment matcher")
}
m.Re, err = regexp.Compile(m.Pattern)
m.re, err = regexp.Compile(m.Pattern)
if err != nil {
return dcfg, fmt.Errorf("invalid deployment.matchers.pattern: %v", err)
}
@@ -167,7 +167,7 @@ func DecodeConfig(cfg config.Provider) (DeployConfig, error) {
if err != nil {
return dcfg, fmt.Errorf("invalid deployment.orderings.pattern: %v", err)
}
dcfg.Ordering = append(dcfg.Ordering, re)
dcfg.ordering = append(dcfg.ordering, re)
}
return dcfg, nil
@@ -1,4 +1,4 @@
// Copyright 2024 The Hugo Authors. All rights reserved.
// Copyright 2019 The Hugo Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -14,7 +14,7 @@
//go:build !nodeploy
// +build !nodeploy
package deployconfig
package deploy
import (
"fmt"
@@ -91,7 +91,7 @@ force = true
c.Assert(len(dcfg.Order), qt.Equals, 2)
c.Assert(dcfg.Order[0], qt.Equals, "o1")
c.Assert(dcfg.Order[1], qt.Equals, "o2")
c.Assert(len(dcfg.Ordering), qt.Equals, 2)
c.Assert(len(dcfg.ordering), qt.Equals, 2)
// Targets.
c.Assert(len(dcfg.Targets), qt.Equals, 3)
@@ -104,11 +104,11 @@ force = true
c.Assert(tgt.CloudFrontDistributionID, qt.Equals, fmt.Sprintf("cdn%d", i))
c.Assert(tgt.Include, qt.Equals, wantInclude[i])
if wantInclude[i] != "" {
c.Assert(tgt.IncludeGlob, qt.Not(qt.IsNil))
c.Assert(tgt.includeGlob, qt.Not(qt.IsNil))
}
c.Assert(tgt.Exclude, qt.Equals, wantExclude[i])
if wantExclude[i] != "" {
c.Assert(tgt.ExcludeGlob, qt.Not(qt.IsNil))
c.Assert(tgt.excludeGlob, qt.Not(qt.IsNil))
}
}
@@ -117,7 +117,7 @@ force = true
for i := 0; i < 3; i++ {
m := dcfg.Matchers[i]
c.Assert(m.Pattern, qt.Equals, fmt.Sprintf("^pattern%d$", i))
c.Assert(m.Re, qt.Not(qt.IsNil))
c.Assert(m.re, qt.Not(qt.IsNil))
c.Assert(m.CacheControl, qt.Equals, fmt.Sprintf("cachecontrol%d", i))
c.Assert(m.ContentEncoding, qt.Equals, fmt.Sprintf("contentencoding%d", i))
c.Assert(m.ContentType, qt.Equals, fmt.Sprintf("contenttype%d", i))
+17 -18
View File
@@ -31,7 +31,6 @@ import (
"testing"
"github.com/gohugoio/hugo/common/loggers"
"github.com/gohugoio/hugo/deploy/deployconfig"
"github.com/gohugoio/hugo/hugofs"
"github.com/gohugoio/hugo/media"
"github.com/google/go-cmp/cmp"
@@ -111,7 +110,7 @@ func TestFindDiffs(t *testing.T) {
{
Description: "local == remote with route.Force true -> diffs",
Local: []*localFile{
{NativePath: "aaa", SlashPath: "aaa", UploadSize: 1, matcher: &deployconfig.Matcher{Force: true}, md5: hash1},
{NativePath: "aaa", SlashPath: "aaa", UploadSize: 1, matcher: &Matcher{Force: true}, md5: hash1},
makeLocal("bbb", 2, hash1),
},
Remote: []*blob.ListObject{
@@ -294,7 +293,7 @@ func TestLocalFile(t *testing.T) {
tests := []struct {
Description string
Path string
Matcher *deployconfig.Matcher
Matcher *Matcher
MediaTypesConfig map[string]any
WantContent []byte
WantSize int64
@@ -320,7 +319,7 @@ func TestLocalFile(t *testing.T) {
{
Description: "CacheControl from matcher",
Path: "foo.txt",
Matcher: &deployconfig.Matcher{CacheControl: "max-age=630720000"},
Matcher: &Matcher{CacheControl: "max-age=630720000"},
WantContent: contentBytes,
WantSize: contentLen,
WantMD5: contentMD5[:],
@@ -329,7 +328,7 @@ func TestLocalFile(t *testing.T) {
{
Description: "ContentEncoding from matcher",
Path: "foo.txt",
Matcher: &deployconfig.Matcher{ContentEncoding: "foobar"},
Matcher: &Matcher{ContentEncoding: "foobar"},
WantContent: contentBytes,
WantSize: contentLen,
WantMD5: contentMD5[:],
@@ -338,7 +337,7 @@ func TestLocalFile(t *testing.T) {
{
Description: "ContentType from matcher",
Path: "foo.txt",
Matcher: &deployconfig.Matcher{ContentType: "foo/bar"},
Matcher: &Matcher{ContentType: "foo/bar"},
WantContent: contentBytes,
WantSize: contentLen,
WantMD5: contentMD5[:],
@@ -347,7 +346,7 @@ func TestLocalFile(t *testing.T) {
{
Description: "gzipped content",
Path: "foo.txt",
Matcher: &deployconfig.Matcher{Gzip: true},
Matcher: &Matcher{Gzip: true},
WantContent: gzBytes,
WantSize: gzLen,
WantMD5: gzMD5[:],
@@ -561,7 +560,7 @@ func TestEndToEndSync(t *testing.T) {
localFs: test.fs,
bucket: test.bucket,
mediaTypes: media.DefaultTypes,
cfg: deployconfig.DeployConfig{MaxDeletes: -1},
cfg: DeployConfig{MaxDeletes: -1},
}
// Initial deployment should sync remote with local.
@@ -644,7 +643,7 @@ func TestMaxDeletes(t *testing.T) {
localFs: test.fs,
bucket: test.bucket,
mediaTypes: media.DefaultTypes,
cfg: deployconfig.DeployConfig{MaxDeletes: -1},
cfg: DeployConfig{MaxDeletes: -1},
}
// Sync remote with local.
@@ -765,16 +764,16 @@ func TestIncludeExclude(t *testing.T) {
if err != nil {
t.Fatal(err)
}
tgt := &deployconfig.Target{
tgt := &Target{
Include: test.Include,
Exclude: test.Exclude,
}
if err := tgt.ParseIncludeExclude(); err != nil {
if err := tgt.parseIncludeExclude(); err != nil {
t.Error(err)
}
deployer := &Deployer{
localFs: fsTest.fs,
cfg: deployconfig.DeployConfig{MaxDeletes: -1}, bucket: fsTest.bucket,
cfg: DeployConfig{MaxDeletes: -1}, bucket: fsTest.bucket,
target: tgt,
mediaTypes: media.DefaultTypes,
}
@@ -831,7 +830,7 @@ func TestIncludeExcludeRemoteDelete(t *testing.T) {
}
deployer := &Deployer{
localFs: fsTest.fs,
cfg: deployconfig.DeployConfig{MaxDeletes: -1}, bucket: fsTest.bucket,
cfg: DeployConfig{MaxDeletes: -1}, bucket: fsTest.bucket,
mediaTypes: media.DefaultTypes,
}
@@ -849,11 +848,11 @@ func TestIncludeExcludeRemoteDelete(t *testing.T) {
}
// Second sync
tgt := &deployconfig.Target{
tgt := &Target{
Include: test.Include,
Exclude: test.Exclude,
}
if err := tgt.ParseIncludeExclude(); err != nil {
if err := tgt.parseIncludeExclude(); err != nil {
t.Error(err)
}
deployer.target = tgt
@@ -883,7 +882,7 @@ func TestCompression(t *testing.T) {
deployer := &Deployer{
localFs: test.fs,
bucket: test.bucket,
cfg: deployconfig.DeployConfig{MaxDeletes: -1, Matchers: []*deployconfig.Matcher{{Pattern: ".*", Gzip: true, Re: regexp.MustCompile(".*")}}},
cfg: DeployConfig{MaxDeletes: -1, Matchers: []*Matcher{{Pattern: ".*", Gzip: true, re: regexp.MustCompile(".*")}}},
mediaTypes: media.DefaultTypes,
}
@@ -938,7 +937,7 @@ func TestMatching(t *testing.T) {
deployer := &Deployer{
localFs: test.fs,
bucket: test.bucket,
cfg: deployconfig.DeployConfig{MaxDeletes: -1, Matchers: []*deployconfig.Matcher{{Pattern: "^subdir/aaa$", Force: true, Re: regexp.MustCompile("^subdir/aaa$")}}},
cfg: DeployConfig{MaxDeletes: -1, Matchers: []*Matcher{{Pattern: "^subdir/aaa$", Force: true, re: regexp.MustCompile("^subdir/aaa$")}}},
mediaTypes: media.DefaultTypes,
}
@@ -963,7 +962,7 @@ func TestMatching(t *testing.T) {
}
// Repeat with a matcher that should now match 3 files.
deployer.cfg.Matchers = []*deployconfig.Matcher{{Pattern: "aaa", Force: true, Re: regexp.MustCompile("aaa")}}
deployer.cfg.Matchers = []*Matcher{{Pattern: "aaa", Force: true, re: regexp.MustCompile("aaa")}}
if err := deployer.Deploy(ctx); err != nil {
t.Errorf("no-op deploy with triple force matcher: %v", err)
}
-1
View File
@@ -105,7 +105,6 @@
"doas",
"eopkg",
"gitee",
"gohugoio",
"goldmark",
"KaTeX",
"kubuntu",
+2 -2
View File
@@ -18,9 +18,9 @@ jobs:
uses: actions/checkout@v4
- name: Initialize CodeQL
uses: github/codeql-action/init@v3
uses: github/codeql-action/init@v2
with:
languages: "javascript"
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v3
uses: github/codeql-action/analyze@v2
+1 -1
View File
@@ -21,7 +21,7 @@ jobs:
uses: actions/checkout@v4
- name: Lint Code Base
uses: super-linter/super-linter/slim@v6
uses: super-linter/super-linter/slim@v5
env:
DEFAULT_BRANCH: master
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+49 -13
View File
@@ -1,20 +1,56 @@
<a href="https://gohugo.io/"><img src="https://raw.githubusercontent.com/gohugoio/gohugoioTheme/master/static/images/hugo-logo-wide.svg?sanitize=true" alt="Hugo" width="565"></a>
A fast and flexible static site generator built with love by [bep], [spf13], and [friends] in [Go].
---
[![Netlify Status](https://api.netlify.com/api/v1/badges/e0dbbfc7-34f1-4393-a679-c16e80162705/deploy-status)](https://app.netlify.com/sites/gohugoio/deploys)
[![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg?style=flat-square)](https://gohugo.io/contribute/documentation/)
This is the repository for the [Hugo](https://github.com/gohugoio/hugo) documentation site.
# Hugo Docs
Please see the [contributing] section for guidelines, examples, and process.
Documentation site for [Hugo](https://github.com/gohugoio/hugo), the very fast and flexible static site generator built with love in Go.
## Contributing
We welcome contributions to Hugo of any kind including documentation, suggestions, bug reports, pull requests etc. Also check out our [contribution guide](https://gohugo.io/contribute/documentation/). We would love to hear from you.
[bep]: https://github.com/bep
[spf13]: https://github.com/spf13
[friends]: https://github.com/gohugoio/hugo/graphs/contributors
[go]: https://go.dev/
[contributing]: https://gohugo.io/contribute/documentation
Note that this repository contains solely the documentation for Hugo. For contributions that aren't documentation-related please refer to the [hugo](https://github.com/gohugoio/hugo) repository.
*Pull requests shall **only** contain changes to the actual documentation. However, changes on the codebase of Hugo **and** the documentation shall be a single, atomic pull request in the [hugo](https://github.com/gohugoio/hugo) repository.*
Spelling fixes are most welcomed, and if you want to contribute longer sections to the documentation, it would be great if you had the following criteria in mind when writing:
* Short is good. People go to the library to read novels. If there is more than one way to _do a thing_ in Hugo, describe the current _best practice_ (avoid "… but you can also do …" and "… in older versions of Hugo you had to …".
* For example, try to find short snippets that teaches people about the concept. If the example is also useful as-is (copy and paste), then great. Don't list long and similar examples just so people can use them on their sites.
* Hugo has users from all over the world, so easy to understand and [simple English](https://simple.wikipedia.org/wiki/Basic_English) is good.
## Edit the theme
If you want to do docs-related theme changes, the simplest way is to have both `hugoDocs` and `gohugoioTheme` cloned as sibling directories, and then run:
```sh
HUGO_MODULE_WORKSPACE=hugo.work hugo server --ignoreVendorPaths "**"
```
## Branches
* The `master` branch is where the site is automatically built from, and is the place to put changes relevant to the current Hugo version.
* The `next` branch is where we store changes that are related to the next Hugo release. This can be previewed here: https://next--gohugoio.netlify.com/
## Build
To view the documentation site locally, you need to clone this repository:
```sh
git clone https://github.com/gohugoio/hugoDocs.git
```
Also note that the documentation version for a given version of Hugo can also be found in the `/docs` sub-folder of the [Hugo source repository](https://github.com/gohugoio/hugo).
Then to view the docs in your browser, run Hugo and open up the link:
```sh
▶ hugo server
Started building sites ...
.
.
Serving pages from memory
Web Server is available at http://localhost:1313/ (bind address 127.0.0.1)
Press Ctrl+C to stop
```
@@ -1,4 +1,4 @@
<!doctype html>
<!DOCTYPE html>
<html
class="no-js"
lang="{{ with $.Site.LanguageCode }}
@@ -98,8 +98,7 @@
{{ partial "gtag.html" . }}
{{ end }}
{{ $hasMath := .Param "math" }}
{{ if $hasMath }}
{{ if .Param "math" }}
{{ partialCached "math.html" . }}
{{ end }}
@@ -108,7 +107,7 @@
<body
class="ma0 sans-serif bg-primary-color-light{{ with getenv "HUGO_ENV" }}
{{ . }}
{{ end }} {{ if $hasMath }}{{ print " dn" }}{{ end }}">
{{ end }}">
{{ partial "hooks/after-body-start.html" . }}
{{ block "nav" . }}{{ partial "site-nav.html" . }}{{ end }}
{{ block "header" . }}{{ end }}
@@ -1,42 +1,32 @@
{{ $author := .context.Params.author }}
{{ if $author }}
<aside class="mw5 center bg-white br3 pa3 pa4-ns mv3 ba b--black-10 nested-links">
{{ $data := "" }}
{{ $url := urls.JoinPath "https://api.github.com/users" $author }}
{{ with resources.GetRemote $url }}
{{ with .Err }}
{{ errorf "%s" . }}
{{ else }}
{{ $data = . | transform.Unmarshal }}
{{ end }}
{{ else }}
{{ errorf "Unable to get remote resource %q" $url }}
{{ end }}
{{ $urlPre := "https://api.github.com" }}
{{ $user_json := getJSON $urlPre "/users/" $author }}
<div class="tc">
{{ with $data }}
{{ with .avatar_url }}
<a href="{{ . }}" class="link hover-bg-light-gray pa1 br-100">
<img src="{{ . }}&size={{ $.size }}" alt="" class="br-100 ba b--light-gray">
</a>
{{ end }}
{{ with .name }}
<h3 class="f4">
<a href="{{ $data.html_url }}" class="link dim">
{{ . | htmlEscape }}
</a>
</h3>
<hr class="mw3 bb bw1 b--black-10">
{{ end }}
{{ with .bio }}
<p class="lh-copy measure center f6 black-70">
{{ . | htmlEscape }}
</p>
{{ end }}
{{ if $user_json.avatar_url }}
<a href="{{ $user_json.html_url }}" class="link hover-bg-light-gray pa1 br-100">
<img src="{{ $user_json.avatar_url }}&size={{ .size }}" alt="" class="br-100 ba b--light-gray">
</a>
{{ end }}
{{ if $user_json.name }}
<h3 class="f4">
<a href="{{ $user_json.html_url }}" class="link dim">
{{ $user_json.name }}
</a>
</h3>
<hr class="mw3 bb bw1 b--black-10">
{{ end }}
{{ if $user_json.bio }}
<p class="lh-copy measure center f6 black-70">
{{ $user_json.bio }}
</p>
{{ end }}
</div>
</aside>
@@ -1,36 +1,21 @@
{{ $author := .context.Params.author }}
{{ if $author }}
<aside class="mw5 br3 mv3 nested-links">
{{ $data := "" }}
{{ $url := urls.JoinPath "https://api.github.com/users" $author }}
{{ with resources.GetRemote $url }}
{{ with .Err }}
{{ errorf "%s" . }}
{{ else }}
{{ $data = . | transform.Unmarshal }}
{{ end }}
{{ else }}
{{ errorf "Unable to get remote resource %q" $url }}
{{ end }}
{{ with $data }}
{{ with .name }}
{{ $urlPre := "https://api.github.com" }}
{{ $user_json := getJSON $urlPre "/users/" $author }}
{{ if $user_json.name }}
<h3 class="f4 dib">
{{ . | htmlEscape }}
{{ $user_json.name | htmlEscape }}
</h3>
{{ end }}
{{ with .bio }}
{{ if $user_json.bio }}
<p class="lh-copy measure center mt0 f6 black-60">
{{ . | htmlEscape }}
{{ $user_json.bio | htmlEscape }}
</p>
{{ end }}
{{ with .html_url }}
<a href="{{ . }}" class="link dim v-mid dib">
{{ partial "svg/github-squared.svg" (dict "fill" "gray" "width" "16" "height" "18") }}
</a>
{{ end }}
{{ end }}
<a href="{{ $user_json.html_url }}" class="link dim v-mid dib">
{{ partial "svg/github-squared.svg" (dict "fill" "gray" "width" "16" "height" "18") }}
</a>
</aside>
{{ end }}
@@ -14,11 +14,11 @@
<a href="{{ .Permalink }}">{{ .Title }}</a>
</td>
<td class="pv2 ph3">
<a href="{{ .Site.Params.ghrepo }}blob/master/content/{{ .Language.Lang }}/{{ .File.Path }}">
<a href="{{.Site.Params.ghrepo}}blob/master/content/{{.Lang }}/{{.File.Path}}">
{{ with .GitInfo }}{{ .Subject }}{{ else }}Source{{ end }}
</a>
</td>
</tr>
{{ end }}
</tbody>
</table>
</table>
@@ -2,15 +2,8 @@
<script>
MathJax = {
tex: {
inlineMath: [['$', '$'], ['\\(', '\\)']], // inline
displayMath: [['$$', '$$'], ['\\[', '\\]']] // block
},
startup: {
pageReady: () => {
return MathJax.startup.defaultPageReady().then(() => {
document.body.classList.remove("dn");
});
}
displayMath: [['\\[', '\\]'], ['$$', '$$']], // block
inlineMath: [['\\(', '\\)']] // inline
}
};
</script>
@@ -1,3 +1,3 @@
<a href="{{.Site.Params.ghrepo }}edit/master/content/{{ .Language.Lang }}/{{ .File.Path }}" class="
<a href="{{.Site.Params.ghrepo}}edit/master/content/{{ .Lang }}/{{.File.Path}}" class="
f6 ph3 pv1 br2 dib tc ttu mv3 bg-primary-color white hover-bg-green link
">Improve this page</a>
+1 -1
View File
@@ -1 +1 @@
# github.com/gohugoio/gohugoioTheme v0.0.0-20240201183016-8e648a3b5342
# github.com/gohugoio/gohugoioTheme v0.0.0-20240126181647-31e47d550511
+1 -1
View File
@@ -56,7 +56,7 @@ hugo [flags]
--printPathWarnings print warnings on duplicate target paths etc.
--printUnusedTemplates print warnings on unused templates.
--quiet build in quiet mode
--renderToMemory render to memory (mostly useful when running the server)
--renderToMemory render to memory (only useful for benchmark testing)
-s, --source string filesystem path to read files relative from
--templateMetrics display metrics about template executions
--templateMetricsHints calculate some improvement hints when combined with --templateMetrics
@@ -31,7 +31,6 @@ See each sub-command's help for details on how to use the generated script.
--ignoreVendorPaths string ignores any _vendor for module paths matching the given Glob pattern
--logLevel string log level (debug|info|warn|error)
--quiet build in quiet mode
--renderToMemory render to memory (mostly useful when running the server)
-s, --source string filesystem path to read files relative from
--themesDir string filesystem path to themes directory
-v, --verbose verbose output
@@ -54,7 +54,6 @@ hugo completion bash
--ignoreVendorPaths string ignores any _vendor for module paths matching the given Glob pattern
--logLevel string log level (debug|info|warn|error)
--quiet build in quiet mode
--renderToMemory render to memory (mostly useful when running the server)
-s, --source string filesystem path to read files relative from
--themesDir string filesystem path to themes directory
-v, --verbose verbose output
@@ -45,7 +45,6 @@ hugo completion fish [flags]
--ignoreVendorPaths string ignores any _vendor for module paths matching the given Glob pattern
--logLevel string log level (debug|info|warn|error)
--quiet build in quiet mode
--renderToMemory render to memory (mostly useful when running the server)
-s, --source string filesystem path to read files relative from
--themesDir string filesystem path to themes directory
-v, --verbose verbose output
@@ -42,7 +42,6 @@ hugo completion powershell [flags]
--ignoreVendorPaths string ignores any _vendor for module paths matching the given Glob pattern
--logLevel string log level (debug|info|warn|error)
--quiet build in quiet mode
--renderToMemory render to memory (mostly useful when running the server)
-s, --source string filesystem path to read files relative from
--themesDir string filesystem path to themes directory
-v, --verbose verbose output
@@ -56,7 +56,6 @@ hugo completion zsh [flags]
--ignoreVendorPaths string ignores any _vendor for module paths matching the given Glob pattern
--logLevel string log level (debug|info|warn|error)
--quiet build in quiet mode
--renderToMemory render to memory (mostly useful when running the server)
-s, --source string filesystem path to read files relative from
--themesDir string filesystem path to themes directory
-v, --verbose verbose output
-1
View File
@@ -39,7 +39,6 @@ hugo config [command] [flags]
--ignoreVendorPaths string ignores any _vendor for module paths matching the given Glob pattern
--logLevel string log level (debug|info|warn|error)
--quiet build in quiet mode
--renderToMemory render to memory (mostly useful when running the server)
-s, --source string filesystem path to read files relative from
--themesDir string filesystem path to themes directory
-v, --verbose verbose output
@@ -33,7 +33,6 @@ hugo config mounts [flags] [args]
--ignoreVendorPaths string ignores any _vendor for module paths matching the given Glob pattern
--logLevel string log level (debug|info|warn|error)
--quiet build in quiet mode
--renderToMemory render to memory (mostly useful when running the server)
-s, --source string filesystem path to read files relative from
--themesDir string filesystem path to themes directory
-v, --verbose verbose output
-1
View File
@@ -33,7 +33,6 @@ See convert's subcommands toJSON, toTOML and toYAML for more information.
--ignoreVendorPaths string ignores any _vendor for module paths matching the given Glob pattern
--logLevel string log level (debug|info|warn|error)
--quiet build in quiet mode
--renderToMemory render to memory (mostly useful when running the server)
-s, --source string filesystem path to read files relative from
--themesDir string filesystem path to themes directory
-v, --verbose verbose output
@@ -35,7 +35,6 @@ hugo convert toJSON [flags] [args]
--logLevel string log level (debug|info|warn|error)
-o, --output string filesystem path to write files to
--quiet build in quiet mode
--renderToMemory render to memory (mostly useful when running the server)
-s, --source string filesystem path to read files relative from
--themesDir string filesystem path to themes directory
--unsafe enable less safe operations, please backup first
@@ -35,7 +35,6 @@ hugo convert toTOML [flags] [args]
--logLevel string log level (debug|info|warn|error)
-o, --output string filesystem path to write files to
--quiet build in quiet mode
--renderToMemory render to memory (mostly useful when running the server)
-s, --source string filesystem path to read files relative from
--themesDir string filesystem path to themes directory
--unsafe enable less safe operations, please backup first
@@ -35,7 +35,6 @@ hugo convert toYAML [flags] [args]
--logLevel string log level (debug|info|warn|error)
-o, --output string filesystem path to write files to
--quiet build in quiet mode
--renderToMemory render to memory (mostly useful when running the server)
-s, --source string filesystem path to read files relative from
--themesDir string filesystem path to themes directory
--unsafe enable less safe operations, please backup first
-1
View File
@@ -44,7 +44,6 @@ hugo deploy [flags] [args]
--ignoreVendorPaths string ignores any _vendor for module paths matching the given Glob pattern
--logLevel string log level (debug|info|warn|error)
--quiet build in quiet mode
--renderToMemory render to memory (mostly useful when running the server)
-s, --source string filesystem path to read files relative from
--themesDir string filesystem path to themes directory
-v, --verbose verbose output
-1
View File
@@ -33,7 +33,6 @@ hugo env [flags] [args]
--ignoreVendorPaths string ignores any _vendor for module paths matching the given Glob pattern
--logLevel string log level (debug|info|warn|error)
--quiet build in quiet mode
--renderToMemory render to memory (mostly useful when running the server)
-s, --source string filesystem path to read files relative from
--themesDir string filesystem path to themes directory
-v, --verbose verbose output
-1
View File
@@ -25,7 +25,6 @@ A collection of several useful generators.
--ignoreVendorPaths string ignores any _vendor for module paths matching the given Glob pattern
--logLevel string log level (debug|info|warn|error)
--quiet build in quiet mode
--renderToMemory render to memory (mostly useful when running the server)
-s, --source string filesystem path to read files relative from
--themesDir string filesystem path to themes directory
-v, --verbose verbose output
@@ -38,7 +38,6 @@ hugo gen chromastyles [flags] [args]
--ignoreVendorPaths string ignores any _vendor for module paths matching the given Glob pattern
--logLevel string log level (debug|info|warn|error)
--quiet build in quiet mode
--renderToMemory render to memory (mostly useful when running the server)
-s, --source string filesystem path to read files relative from
--themesDir string filesystem path to themes directory
-v, --verbose verbose output
-1
View File
@@ -39,7 +39,6 @@ hugo gen doc [flags] [args]
--ignoreVendorPaths string ignores any _vendor for module paths matching the given Glob pattern
--logLevel string log level (debug|info|warn|error)
--quiet build in quiet mode
--renderToMemory render to memory (mostly useful when running the server)
-s, --source string filesystem path to read files relative from
--themesDir string filesystem path to themes directory
-v, --verbose verbose output
-1
View File
@@ -36,7 +36,6 @@ hugo gen man [flags] [args]
--ignoreVendorPaths string ignores any _vendor for module paths matching the given Glob pattern
--logLevel string log level (debug|info|warn|error)
--quiet build in quiet mode
--renderToMemory render to memory (mostly useful when running the server)
-s, --source string filesystem path to read files relative from
--themesDir string filesystem path to themes directory
-v, --verbose verbose output
-1
View File
@@ -31,7 +31,6 @@ Import requires a subcommand, e.g. `hugo import jekyll jekyll_root_path target_p
--ignoreVendorPaths string ignores any _vendor for module paths matching the given Glob pattern
--logLevel string log level (debug|info|warn|error)
--quiet build in quiet mode
--renderToMemory render to memory (mostly useful when running the server)
-s, --source string filesystem path to read files relative from
--themesDir string filesystem path to themes directory
-v, --verbose verbose output
@@ -36,7 +36,6 @@ hugo import jekyll [flags] [args]
--ignoreVendorPaths string ignores any _vendor for module paths matching the given Glob pattern
--logLevel string log level (debug|info|warn|error)
--quiet build in quiet mode
--renderToMemory render to memory (mostly useful when running the server)
-s, --source string filesystem path to read files relative from
--themesDir string filesystem path to themes directory
-v, --verbose verbose output
-1
View File
@@ -31,7 +31,6 @@ List requires a subcommand, e.g. hugo list drafts
--ignoreVendorPaths string ignores any _vendor for module paths matching the given Glob pattern
--logLevel string log level (debug|info|warn|error)
--quiet build in quiet mode
--renderToMemory render to memory (mostly useful when running the server)
-s, --source string filesystem path to read files relative from
--themesDir string filesystem path to themes directory
-v, --verbose verbose output
@@ -33,7 +33,6 @@ hugo list all [flags] [args]
--ignoreVendorPaths string ignores any _vendor for module paths matching the given Glob pattern
--logLevel string log level (debug|info|warn|error)
--quiet build in quiet mode
--renderToMemory render to memory (mostly useful when running the server)
-s, --source string filesystem path to read files relative from
--themesDir string filesystem path to themes directory
-v, --verbose verbose output
@@ -33,7 +33,6 @@ hugo list drafts [flags] [args]
--ignoreVendorPaths string ignores any _vendor for module paths matching the given Glob pattern
--logLevel string log level (debug|info|warn|error)
--quiet build in quiet mode
--renderToMemory render to memory (mostly useful when running the server)
-s, --source string filesystem path to read files relative from
--themesDir string filesystem path to themes directory
-v, --verbose verbose output
@@ -33,7 +33,6 @@ hugo list expired [flags] [args]
--ignoreVendorPaths string ignores any _vendor for module paths matching the given Glob pattern
--logLevel string log level (debug|info|warn|error)
--quiet build in quiet mode
--renderToMemory render to memory (mostly useful when running the server)
-s, --source string filesystem path to read files relative from
--themesDir string filesystem path to themes directory
-v, --verbose verbose output
@@ -33,7 +33,6 @@ hugo list future [flags] [args]
--ignoreVendorPaths string ignores any _vendor for module paths matching the given Glob pattern
--logLevel string log level (debug|info|warn|error)
--quiet build in quiet mode
--renderToMemory render to memory (mostly useful when running the server)
-s, --source string filesystem path to read files relative from
--themesDir string filesystem path to themes directory
-v, --verbose verbose output
-1
View File
@@ -40,7 +40,6 @@ See https://gohugo.io/hugo-modules/ for more information.
--ignoreVendorPaths string ignores any _vendor for module paths matching the given Glob pattern
--logLevel string log level (debug|info|warn|error)
--quiet build in quiet mode
--renderToMemory render to memory (mostly useful when running the server)
-s, --source string filesystem path to read files relative from
--themesDir string filesystem path to themes directory
-v, --verbose verbose output
@@ -39,7 +39,6 @@ hugo mod clean [flags] [args]
--ignoreVendorPaths string ignores any _vendor for module paths matching the given Glob pattern
--logLevel string log level (debug|info|warn|error)
--quiet build in quiet mode
--renderToMemory render to memory (mostly useful when running the server)
-s, --source string filesystem path to read files relative from
--themesDir string filesystem path to themes directory
-v, --verbose verbose output
-1
View File
@@ -64,7 +64,6 @@ hugo mod get [flags] [args]
--ignoreVendorPaths string ignores any _vendor for module paths matching the given Glob pattern
--logLevel string log level (debug|info|warn|error)
--quiet build in quiet mode
--renderToMemory render to memory (mostly useful when running the server)
-s, --source string filesystem path to read files relative from
--themesDir string filesystem path to themes directory
-v, --verbose verbose output
@@ -40,7 +40,6 @@ hugo mod graph [flags] [args]
--ignoreVendorPaths string ignores any _vendor for module paths matching the given Glob pattern
--logLevel string log level (debug|info|warn|error)
--quiet build in quiet mode
--renderToMemory render to memory (mostly useful when running the server)
-s, --source string filesystem path to read files relative from
--themesDir string filesystem path to themes directory
-v, --verbose verbose output
@@ -44,7 +44,6 @@ hugo mod init [flags] [args]
--ignoreVendorPaths string ignores any _vendor for module paths matching the given Glob pattern
--logLevel string log level (debug|info|warn|error)
--quiet build in quiet mode
--renderToMemory render to memory (mostly useful when running the server)
-s, --source string filesystem path to read files relative from
--themesDir string filesystem path to themes directory
-v, --verbose verbose output
-1
View File
@@ -33,7 +33,6 @@ hugo mod npm [command] [flags]
--ignoreVendorPaths string ignores any _vendor for module paths matching the given Glob pattern
--logLevel string log level (debug|info|warn|error)
--quiet build in quiet mode
--renderToMemory render to memory (mostly useful when running the server)
-s, --source string filesystem path to read files relative from
--themesDir string filesystem path to themes directory
-v, --verbose verbose output
@@ -47,7 +47,6 @@ hugo mod npm pack [flags] [args]
--ignoreVendorPaths string ignores any _vendor for module paths matching the given Glob pattern
--logLevel string log level (debug|info|warn|error)
--quiet build in quiet mode
--renderToMemory render to memory (mostly useful when running the server)
-s, --source string filesystem path to read files relative from
--themesDir string filesystem path to themes directory
-v, --verbose verbose output
@@ -33,7 +33,6 @@ hugo mod tidy [flags] [args]
--ignoreVendorPaths string ignores any _vendor for module paths matching the given Glob pattern
--logLevel string log level (debug|info|warn|error)
--quiet build in quiet mode
--renderToMemory render to memory (mostly useful when running the server)
-s, --source string filesystem path to read files relative from
--themesDir string filesystem path to themes directory
-v, --verbose verbose output
@@ -39,7 +39,6 @@ hugo mod vendor [flags] [args]
--ignoreVendorPaths string ignores any _vendor for module paths matching the given Glob pattern
--logLevel string log level (debug|info|warn|error)
--quiet build in quiet mode
--renderToMemory render to memory (mostly useful when running the server)
-s, --source string filesystem path to read files relative from
--themesDir string filesystem path to themes directory
-v, --verbose verbose output
@@ -38,7 +38,6 @@ hugo mod verify [flags] [args]
--ignoreVendorPaths string ignores any _vendor for module paths matching the given Glob pattern
--logLevel string log level (debug|info|warn|error)
--quiet build in quiet mode
--renderToMemory render to memory (mostly useful when running the server)
-s, --source string filesystem path to read files relative from
--themesDir string filesystem path to themes directory
-v, --verbose verbose output
-1
View File
@@ -36,7 +36,6 @@ Ensure you run this within the root directory of your site.
--ignoreVendorPaths string ignores any _vendor for module paths matching the given Glob pattern
--logLevel string log level (debug|info|warn|error)
--quiet build in quiet mode
--renderToMemory render to memory (mostly useful when running the server)
-s, --source string filesystem path to read files relative from
--themesDir string filesystem path to themes directory
-v, --verbose verbose output
@@ -47,7 +47,6 @@ hugo new content [path] [flags]
--ignoreVendorPaths string ignores any _vendor for module paths matching the given Glob pattern
--logLevel string log level (debug|info|warn|error)
--quiet build in quiet mode
--renderToMemory render to memory (mostly useful when running the server)
-s, --source string filesystem path to read files relative from
--themesDir string filesystem path to themes directory
-v, --verbose verbose output
@@ -37,7 +37,6 @@ hugo new site [path] [flags]
--ignoreVendorPaths string ignores any _vendor for module paths matching the given Glob pattern
--logLevel string log level (debug|info|warn|error)
--quiet build in quiet mode
--renderToMemory render to memory (mostly useful when running the server)
-s, --source string filesystem path to read files relative from
--themesDir string filesystem path to themes directory
-v, --verbose verbose output
@@ -36,7 +36,6 @@ hugo new theme [name] [flags]
--ignoreVendorPaths string ignores any _vendor for module paths matching the given Glob pattern
--logLevel string log level (debug|info|warn|error)
--quiet build in quiet mode
--renderToMemory render to memory (mostly useful when running the server)
-s, --source string filesystem path to read files relative from
--themesDir string filesystem path to themes directory
-v, --verbose verbose output
+5 -5
View File
@@ -12,9 +12,8 @@ A high performance webserver
Hugo provides its own webserver which builds and serves the site.
While hugo server is high performance, it is a webserver with limited options.
'hugo server' will by default write and server files from disk, but you can
render to memory by using the '--renderToMemory' flag. This can be faster
in some cases, but it will consume more memory.
'hugo server' will avoid writing the rendered and served content to disk,
preferring to store it in memory.
By default hugo will also watch your files for any changes you make and
automatically rebuild the site. It will then live reload any open browser pages
@@ -48,6 +47,8 @@ hugo server [command] [flags]
--ignoreCache ignores the cache directory
-l, --layoutDir string filesystem path to layout directory
--liveReloadPort int port for live reloading (i.e. 443 in HTTPS proxy situations) (default -1)
--meminterval string interval to poll memory usage (requires --memstats), valid time units are "ns", "us" (or "µs"), "ms", "s", "m", "h". (default "100ms")
--memstats string log memory usage to this file
--minify minify any supported output format (HTML, XML etc.)
--navigateToChanged navigate to changed content file on live browser reload
--noBuildLock don't create .hugo_build.lock file
@@ -57,12 +58,12 @@ hugo server [command] [flags]
--panicOnWarning panic on first WARNING log
--poll string set this to a poll interval, e.g --poll 700ms, to use a poll based approach to watch for file system changes
-p, --port int port on which the server will listen (default 1313)
--pprof enable the pprof server (port 8080)
--printI18nWarnings print missing translations
--printMemoryUsage print memory usage to screen at intervals
--printPathWarnings print warnings on duplicate target paths etc.
--printUnusedTemplates print warnings on unused templates.
--renderStaticToDisk serve static files from disk and dynamic files from memory
--renderToDisk serve all files from disk (default is from memory)
--templateMetrics display metrics about template executions
--templateMetricsHints calculate some improvement hints when combined with --templateMetrics
-t, --theme strings themes to use (located in /themes/THEMENAME/)
@@ -85,7 +86,6 @@ hugo server [command] [flags]
--ignoreVendorPaths string ignores any _vendor for module paths matching the given Glob pattern
--logLevel string log level (debug|info|warn|error)
--quiet build in quiet mode
--renderToMemory render to memory (mostly useful when running the server)
-s, --source string filesystem path to read files relative from
--themesDir string filesystem path to themes directory
-v, --verbose verbose output
@@ -30,7 +30,6 @@ hugo server trust [flags] [args]
--ignoreVendorPaths string ignores any _vendor for module paths matching the given Glob pattern
--logLevel string log level (debug|info|warn|error)
--quiet build in quiet mode
--renderToMemory render to memory (mostly useful when running the server)
-s, --source string filesystem path to read files relative from
--themesDir string filesystem path to themes directory
-v, --verbose verbose output
-1
View File
@@ -33,7 +33,6 @@ hugo version [flags] [args]
--ignoreVendorPaths string ignores any _vendor for module paths matching the given Glob pattern
--logLevel string log level (debug|info|warn|error)
--quiet build in quiet mode
--renderToMemory render to memory (mostly useful when running the server)
-s, --source string filesystem path to read files relative from
--themesDir string filesystem path to themes directory
-v, --verbose verbose output
@@ -50,7 +50,7 @@ render
: Always render the page to disk. This is the default value.
- `link`
: Do not render the page to disk, but assign `Permalink` and `RelPermalink` values.
: Do not render the page to disk, but include it in all page collections.
- `never`
: Never render the page to disk, and exclude it from all page collections.
@@ -245,7 +245,7 @@ content/
Set the build options in front matter:
{{< code-toggle file=content/books/_index.md fm=true >}}
{{< code-toggle file=content/books/_index.md >}}
title = 'Books'
[_build]
render = 'never'
@@ -131,6 +131,9 @@ videos
weight
: used for [ordering your content in lists][ordering]. Lower weight gets higher precedence. So content with lower weight will come first. If set, weights should be non-zero, as 0 is interpreted as an *unset* weight.
taxonomies
: Field name of the *plural* form of the index. See `tags` and `categories` in the above front matter examples. *Note that the plural form of user-defined taxonomies cannot be the same as any of the predefined front matter variables.*
{{% note %}}
If neither `slug` nor `url` is present and [permalinks are not configured otherwise in your site configuration file](/content-management/urls/#permalinks), Hugo will use the file name of your content to create the output URL. See [Content Organization](/content-management/organization) for an explanation of paths in Hugo and [URL Management](/content-management/urls/) for ways to customize Hugo's default behaviors.
{{% /note %}}
@@ -187,7 +190,7 @@ Any of the above can be omitted.
{{% note %}}
When making a site that supports multiple languages, defining a `[[cascade]]` is recommended to be done in [Site Config](../../getting-started/configuration/#cascade) to prevent duplication.
If you instead define a `[[cascade]]` in front matter for multiple languages, an `content/XX/foo/_index.md` file needs to be made on a per-language basis, with `XX` the glob pattern matching the Page's language. In this case, the **lang** keyword is ignored.
If you instea define a `[[cascade]]` in front matter for multiple languages, an `content/XX/foo/_index.md` file needs to be made on a per-language basis, with `XX` the glob pattern matching the Page's language. In this case, the **lang** keyword is ignored.
{{% /note %}}
### Example
@@ -1,9 +1,9 @@
---
title: Mathematics in markdown
linkTitle: Mathematics
description: Include mathematical equations and expressions in your markdown using LaTeX or TeX typesetting syntax.
description: Include mathematical equations and expressions in your markdown using LaTeX or TeX typsetting syntax.
categories: [content management]
keywords: [chemical,chemistry,latex,math,mathjax,tex,typesetting]
keywords: [chemical,chemistry,latex,math,mathjax,tex,typsetting]
menu:
docs:
parent: content-management
@@ -45,7 +45,7 @@ The approach described below avoids reliance on platform-specific features like
## Setup
Follow these instructions to include mathematical equations and expressions in your markdown using LaTeX or TeX typesetting syntax.
Follow these instructions to include mathematical equations and expressions in your markdown using LaTeX or TeX typsetting syntax.
###### Step 1
@@ -122,7 +122,7 @@ The example above loads the partial template if you have set the `math` paramete
###### Step 4
Include mathematical equations and expressions in your markdown using LaTeX or TeX typesetting syntax.
Include mathematical equations and expressions in your markdown using LaTeX or TeX typsetting syntax.
{{< code file=content/math-examples.md copy=true >}}
This is an inline \(a^*=x-b^*\) equation.
+388 -106
View File
@@ -11,138 +11,420 @@ weight: 20
toc: true
---
## Introduction
You can contribute to the Hugo project by:
Hugo is an open-source project and lives by the work of its [contributors]. There are plenty of [open issues][issues], and we need your help to make Hugo even more awesome. You don't need to be a Go guru to contribute to the project's development.
- Answering questions on the [forum]
- Improving the [documentation]
- Monitoring the [issue queue]
- Creating or improving [themes]
- Squashing [bugs]
## Assumptions
Please submit documentation issues and pull requests to the [documentation repository].
This contribution guide takes a step-by-step approach in hopes of helping newcomers. Therefore, we only assume the following:
If you have an idea for an enhancement or new feature, create a new topic on the [forum] in the "Feature" category. This will help you to:
- Determine if the capability already exists
- Measure interest
- Refine the concept
If there is sufficient interest, [create a proposal]. Do not submit a pull request until the project lead accepts the proposal.
For a complete guide to contributing to Hugo, see the [Contribution Guide].
[bugs]: https://github.com/gohugoio/hugo/issues?q=is%3Aopen+is%3Aissue+label%3ABug
[contributing]: CONTRIBUTING.md
[create a proposal]: https://github.com/gohugoio/hugo/issues/new?labels=Proposal%2C+NeedsTriage&template=feature_request.md
[documentation repository]: https://github.com/gohugoio/hugoDocs
[documentation]: https://gohugo.io/documentation
[forum]: https://discourse.gohugo.io
[issue queue]: https://github.com/gohugoio/hugo/issues
[themes]: https://themes.gohugo.io/
[contribution guide]: https://github.com/gohugoio/hugo/blob/master/CONTRIBUTING.md
## Prerequisites
To build the extended edition of Hugo from source you must:
1. Install [Git]
1. Install [Go] version 1.20 or later
1. Install a C compiler, either [GCC] or [Clang]
1. Update your `PATH` environment variable as described in the [Go documentation]
[Clang]: https://clang.llvm.org/
[GCC]: https://gcc.gnu.org/
[Git]: https://git-scm.com/book/en/v2/Getting-Started-Installing-Git
[Go documentation]: https://go.dev/doc/code#Command
[Go]: https://go.dev/doc/install
* You are new to Git or open-source projects in general
* You are a fan of Hugo and enthusiastic about contributing to the project
{{% note %}}
See these [detailed instructions](https://discourse.gohugo.io/t/41370) to install GCC on Windows.
If you're struggling at any point in this contribution guide, reach out to the Hugo community in [Hugo's Discussion forum](https://discourse.gohugo.io).
{{% /note %}}
## GitHub workflow
## Install Go
The installation of Go should take only a few minutes. You have more than one option to get Go up and running on your machine.
If you are having trouble following the installation guides for Go, check out [Go Bootcamp, which contains setups for every platform][gobootcamp] or reach out to the Hugo community in the [Hugo Discussion Forums][forums].
### Install Go from source
[Download the latest stable version of Go][godl] and follow the official [Go installation guide][goinstall].
Once you're finished installing Go, let's confirm everything is working correctly. Open a terminal---or command line under Windows--and type the following:
```txt
go version
```
You should see something similar to the following written to the console. Note that the version here reflects the most recent version of Go as of the last update for this page:
```txt
go version go1.12 darwin/amd64
```
Next, make sure that you set up your `GOPATH` [as described in the installation guide][setupgopath].
You can print the `GOPATH` with `echo $GOPATH`. You should see a non-empty string containing a valid path to your Go workspace; for example:
```txt
/Users/<yourusername>/Code/go
```
### Install Go with Homebrew
If you are a macOS user and have [Homebrew](https://brew.sh/) installed on your machine, installing Go is as simple as the following command:
{{< code file=install-go.sh >}}
brew install go
{{< /code >}}
### Install Go via GVM
More experienced users can use the [Go Version Manager][gvm] (GVM). GVM allows you to switch between different Go versions *on the same machine*. If you're a beginner, you probably don't need this feature. However, GVM makes it easy to upgrade to a new released Go version with just a few commands.
GVM comes in especially handy if you follow the development of Hugo over a longer period of time. Future versions of Hugo will usually be compiled with the latest version of Go. Sooner or later, you will have to upgrade if you want to keep up.
## Create a GitHub account
If you're going to contribute code, you'll need to have an account on GitHub. Go to [www.github.com/join](https://github.com/join) and set up a personal account.
## Install Git on your system
You will need to have Git installed on your computer to contribute to Hugo development. Teaching Git is outside the scope of the Hugo docs, but if you're looking for an excellent reference to learn the basics of Git, we recommend the [Git book][gitbook] if you are not sure where to begin. We will include short explanations of the Git commands in this document.
Git is a [version control system](https://en.wikipedia.org/wiki/Version_control) to track the changes of source code. Hugo depends on smaller third-party packages that are used to extend the functionality. We use them because we don't want to reinvent the wheel.
Go ships with a sub-command called `get` that will download these packages for us when we set up our working environment. The source code of the packages is tracked with Git. `get` will interact with the Git servers of the package hosters in order to fetch all dependencies.
Move back to the terminal and check if Git is already installed. Type in `git version` and press enter. You can skip the rest of this section if the command returned a version number. Otherwise [download](https://git-scm.com/downloads) the latest version of Git and follow this [installation guide](https://git-scm.com/book/en/v2/Getting-Started-Installing-Git).
Finally, check again with `git version` if Git was installed successfully.
### Git graphical front ends
There are several [GUI clients](https://git-scm.com/downloads/guis) that help you to operate Git. Not all are available for all operating systems and maybe differ in their usage. Because of this we will document how to use the command-line, since the commands are the same everywhere.
### Install Hub on your system (optional)
Hub is a great tool for working with GitHub. The main site for it is [hub.github.com](https://hub.github.com/). Feel free to install this little Git wrapper.
On a Mac, you can install [Hub](https://github.com/github/hub) using [Homebrew](https://brew.sh):
```txt
brew install hub
```
Now we'll create an [alias in Bash](https://tldp.org/LDP/abs/html/aliases.html) so that typing `git` actually runs `Hub`:
```txt
echo "alias git='hub'" >> ~/.bash_profile
```
Confirm the installation:
```txt
git version 2.21.0
hub version 2.10.0
```
## Set up your working copy
You set up the working copy of the repository locally on your computer. Your local copy of the files is what you'll edit, compile, and end up pushing back to GitHub. The main steps are cloning the repository and creating your fork as a remote.
### Clone the repository
We assume that you've set up your `GOPATH` (see the section above if you're unsure about this). You should now copy the Hugo repository down to your computer. You'll hear this called "clone the repo". GitHub's [help pages](https://help.github.com/articles/cloning-a-repository/) give us a short explanation:
{{% note %}}
This section assumes that you have a working knowledge of Go, Git and GitHub, and are comfortable working on the command line.
When you create a repository on GitHub, it exists as a remote repository. You can create a local clone of your repository on your computer and sync between the two locations.
{{% /note %}}
Use this workflow to create and submit pull requests.
We're going to clone the [master Hugo repository](https://github.com/gohugoio/hugo). That seems counter-intuitive, since you won't have commit rights on it. But it's required for the Go workflow. You'll work on a copy of the master and push your changes to your own repository on GitHub.
Step 1
: Fork the [project repository].
So, let's make a new directory and clone that master repository:
[project repository]: https://github.com/gohugoio/hugo/
Step 2
: Clone your fork.
Step 3
: Create a new branch with a descriptive name that includes the corresponding issue number.
For a new feature:
```sh
git checkout -b feat/implement-some-feature-99999
```txt
mkdir $HOME/src
cd $HOME/src
git clone https://github.com/gohugoio/hugo.git
```
For a bug fix:
Since Hugo 0.48, Hugo uses the Go Modules support built into Go 1.11 to build. The easiest is to clone Hugo in a directory outside of GOPATH
```sh
git checkout -b fix/fix-some-bug-99999
And then, install dependencies of Hugo by running the following in the cloned directory:
```txt
cd $HOME/src/hugo
go install
```
Step 4
: Make changes.
Hugo relies on [mage](https://github.com/magefile/mage) for some convenient build and test targets. If you don't already have it, get it:
Step 5
: Compile and install:
```text
CGO_ENABLED=1 go install -tags extended
```txt
go install github.com/magefile/mage@latest
```
Step 6
: Test your changes:
### Fork the repository
```text
go test ./...
If you're not familiar with this term, GitHub's [help pages](https://help.github.com/articles/fork-a-repo/) provide again a simple explanation:
{{% note %}}
A fork is a copy of a repository. Forking a repository allows you to freely experiment with changes without affecting the original project.
{{% /note %}}
#### Fork by hand
Open the [Hugo repository](https://github.com/gohugoio/hugo) on GitHub and click on the "Fork" button in the top right.
![Fork button](/images/contribute/development/forking-a-repository.png)
Now open your fork repository on GitHub and copy the remote URL of your fork. You can choose between HTTPS and SSH as protocol that Git should use for the following operations. HTTPS works always [if you're not sure](https://help.github.com/articles/which-remote-url-should-i-use/).
![Copy remote url](/images/contribute/development/copy-remote-url.png)
Switch back to the terminal and move into the directory of the cloned master repository from the last step.
```txt
cd $HOME/src/hugo
```
Step 7
: Commit your changes with a descriptive commit message:
Now Git needs to know that our fork exists by adding the copied remote url:
- Provide a summary on the first line, typically 50 characters or less, followed by a blank line.
- Optionally, provide a detailed description where each line is 80 characters or less, followed by a blank line.
- Add one or more "Fixes" or "Closes" keywords, each on its own line, referencing the [issues] addressed by this change.
```txt
git remote add <YOUR-GITHUB-USERNAME> <COPIED REMOTE-URL>
```
#### Fork with Hub
Alternatively, you can use the Git wrapper Hub. Hub makes forking a repository easy:
```txt
git fork
```
That command will log in to GitHub using your account, create a fork of the repository that you're currently working in, and add it as a remote to your working copy.
#### Trust, but verify
Let's check if everything went right by listing all known remotes:
```txt
git remote -v
```
The output should look similar:
```txt
digitalcraftsman git@github.com:digitalcraftsman/hugo.git (fetch)
digitalcraftsman git@github.com:digitalcraftsman/hugo.git (push)
origin https://github.com/gohugoio/hugo (fetch)
origin https://github.com/gohugoio/hugo (push)
```
## The Hugo Git contribution workflow
### Create a new branch
You should never develop against the "master" branch. The development team will not accept a pull request against that branch. Instead, create a descriptive named branch and work on it.
First, you should always pull the latest changes from the master repository:
```txt
git checkout master
git pull
```
Now we can create a new branch for your additions:
```txt
git checkout -b <BRANCH-NAME>
```
You can check on which branch you are with `git branch`. You should see a list of all local branches. The current branch is indicated with a little asterisk.
### Contribute to documentation
Perhaps you want to start contributing to the Hugo docs. If so, you can ignore most of the following steps and focus on the `/docs` directory within your newly cloned repository. You can change directories into the Hugo docs using `cd docs`.
You can start Hugo's built-in server via `hugo server`. Browse the documentation by entering [http://localhost:1313](http://localhost:1313) in the address bar of your browser. The server automatically updates the page whenever you change content.
We have developed a [separate Hugo documentation contribution guide][docscontrib] for more information on how the Hugo docs are built, organized, and improved by the generosity of people like you.
### Build Hugo
While making changes in the codebase it's a good idea to build the binary to test them:
```txt
mage hugo
```
This command generates the binary file at the root of the repository.
If you want to install the binary in `$GOPATH/bin`, run
```txt
mage install
```
### Test
Sometimes changes on the codebase can cause unintended side effects. Or they don't work as expected. Most functions have their own test cases. You can find them in files ending with `_test.go`.
Make sure the commands
```txt
mage -v check
```
passes.
### Formatting
The Go code style guide maybe is opinionated but it ensures that the codebase looks the same, regardless who wrote the code. Go comes with its own formatting tool. Let's apply the style guide to our additions:
```txt
mage fmt
```
Once you made your additions commit your changes. Make sure that you follow our [code contribution guidelines](https://github.com/gohugoio/hugo/blob/master/CONTRIBUTING.md):
```txt
# Add all changed files
git add --all
git commit --message "YOUR COMMIT MESSAGE"
```
The commit message should describe what the commit does (e.g. add feature XYZ), not how it is done.
### Modify commits
You noticed some commit messages don't fulfill the code contribution guidelines or you just forget something to add some files? No problem. Git provides the necessary tools to fix such problems. The next two methods cover all common cases.
If you are unsure what a command does leave the commit as it is. We can fix your commits later in the pull request.
#### Modify the last commit
Let's say you want to modify the last commit message. Run the following command and replace the current message:
```txt
git commit --amend -m"YOUR NEW COMMIT MESSAGE"
```
Take a look at the commit log to see the change:
```txt
git log
# Exit with q
```
After making the last commit you may have forgotten something. There is no need to create a new commit. Just add the latest changes and merge them into the intended commit:
```txt
git add --all
git commit --amend
```
#### Modify multiple commits
{{% note %}}
Modifications such as those described in this section can have serious unintended consequences. Skip this section if you're not sure!
{{% /note %}}
This is a bit more advanced. Git allows you to [rebase](https://git-scm.com/docs/git-rebase) commits interactively. In other words: it allows you to rewrite the commit history.
```txt
git rebase --interactive @~6
```
The `6` at the end of the command represents the number of commits that should be modified. An editor should open and present a list of last six commit messages:
```txt
pick 80d02a1 tpl: Add hasPrefix to template function smoke test"
pick aaee038 tpl: Sort the smoke tests
pick f0dbf2c tpl: Add the other test case for hasPrefix
pick 911c35b Add "How to contribute to Hugo" tutorial
pick 33c8973 Begin workflow
pick 3502f2e Refactoring and typo fixes
```
In the case above we should merge the last two commits in the commit of this tutorial (`Add "How to contribute to Hugo" tutorial`). You can "squash" commits, i.e. merge two or more commits into a single one.
All operations are written before the commit message. Replace "pick" with an operation. In this case `squash` or `s` for short:
```txt
pick 80d02a1 tpl: Add hasPrefix to template function smoke test"
pick aaee038 tpl: Sort the smoke tests
pick f0dbf2c tpl: Add the other test case for hasPrefix
pick 911c35b Add "How to contribute to Hugo" tutorial
squash 33c8973 Begin workflow
squash 3502f2e Refactoring and typo fixes
```
We also want to rewrite the commits message of the third last commit. We forgot "docs:" as prefix according to the code contribution guidelines. The operation to rewrite a commit is called `reword` (or `r` as shortcut).
You should end up with a similar setup:
```txt
pick 80d02a1 tpl: Add hasPrefix to template function smoke test"
pick aaee038 tpl: Sort the smoke tests
pick f0dbf2c tpl: Add the other test case for hasPrefix
reword 911c35b Add "How to contribute to Hugo" tutorial
squash 33c8973 Begin workflow
squash 3502f2e Refactoring and typo fixes
```
Close the editor. It should open again with a new tab. A text is instructing you to define a new commit message for the last two commits that should be merged (aka "squashed"). Save the file with <kbd>CTRL</kbd>+<kbd>S</kbd> and close the editor again.
A last time a new tab opens. Enter a new commit message and save again. Your terminal should contain a status message. Hopefully this one:
```txt
Successfully rebased and updated refs/heads/<BRANCHNAME>.
```
Check the commit log if everything looks as expected. Should an error occur you can abort this rebase with `git rebase --abort`.
### Push commits
To push our commits to the fork on GitHub we need to specify a destination. A destination is defined by the remote and a branch name. Earlier, the defined that the remote URL of our fork is the same as our GitHub handle, in my case `digitalcraftsman`. The branch should have the same as our local one. This makes it easy to identify corresponding branches.
```txt
git push --set-upstream <YOUR-GITHUB-USERNAME> <BRANCHNAME>
```
Now Git knows the destination. Next time when you to push commits you just need to enter `git push`.
If you modified your commit history in the last step GitHub will reject your try to push. This is a safety-feature because the commit history isn't the same and new commits can't be appended as usual. You can enforce this push explicitly with `git push --force`.
## Open a pull request
We made a lot of progress. Good work. In this step we finally open a pull request to submit our additions. Open the [Hugo master repository](https://github.com/gohugoio/hugo/) on GitHub in your browser.
You should find a green button labeled with "New pull request". But GitHub is clever and probably suggests you a pull request like in the beige box below:
![Open a pull request](/images/contribute/development/open-pull-request.png)
The new page summaries the most important information of your pull request. Scroll down and you find the additions of all your commits. Make sure everything looks as expected and click on "Create pull request".
### Accept the contributor license agreement
Last but not least you should accept the contributor license agreement (CLA). A new comment should be added automatically to your pull request. Click on the yellow badge, accept the agreement and authenticate yourself with your GitHub account. It just takes a few clicks and only needs to be done once.
![Accept the CLA](/images/contribute/development/accept-cla.png)
### Automatic builds
We use a GitHub Actions workflow to build and test. This is a matrix build across combinations of operating system (macOS, Windows, and Ubuntu) and Go versions. The workflow is triggered by the submission of a pull request. If you are a first-time contributor, the workflow requires approval from a project maintainer.
## Where to start?
Thank you for reading through this contribution guide. Hopefully, we will see you again soon on GitHub. There are plenty of [open issues][issues] for you to help with.
Feel free to [open an issue][newissue] if you think you found a bug or you have a new idea to improve Hugo. We are happy to hear from you.
## Additional references for learning Git and Go
* [Codecademy's Free "Learn Git" Course][codecademy] (Free)
* [Code School and GitHub's "Try Git" Tutorial][trygit] (Free)
* [The Git Book][gitbook] (Free)
* [Go Bootcamp][gobootcamp]
[codecademy]: https://www.codecademy.com/learn/learn-git
[contributors]: https://github.com/gohugoio/hugo/graphs/contributors
[docscontrib]: /contribute/documentation/
[forums]: https://discourse.gohugo.io
[gitbook]: https://git-scm.com/
[gobootcamp]: https://www.golang-book.com/guides/machine_setup
[godl]: https://go.dev/dl/
[goinstall]: https://go.dev/doc/install
[gvm]: https://github.com/moovweb/gvm
[issues]: https://github.com/gohugoio/hugo/issues
For example:
```sh
git commit -m "tpl/strings: Create wrap function
The strings.Wrap function wraps a string into one or more lines,
splitting the string after the given number of characters, but not
splitting in the middle of a word.
Fixes #99998
Closes #99999"
```
See the [commit message guidelines] for details.
[commit message guidelines]: https://github.com/gohugoio/hugo/blob/master/CONTRIBUTING.md#git-commit-message-guidelines
Step 8
: Push the new branch to your fork of the documentation repository.
Step 9
: Visit the [project repository] and create a pull request (PR).
Step 10
: A project maintainer will review your PR and may request changes. You may delete your branch after the maintainer merges your PR.
[newissue]: https://github.com/gohugoio/hugo/issues/new
[releases]: /getting-started/
[setupgopath]: https://go.dev/doc/code#Workspaces
[trygit]: https://try.github.io/levels/1/challenges/1
+9 -21
View File
@@ -325,44 +325,32 @@ Step 2
: Clone your fork.
Step 3
: Create a new branch with a descriptive name that includes the corresponding issue number, if any:
: Create a new branch with a descriptive name.
```sh
git checkout -b restructure-foo-page-99999
git checkout -b fix/typos-shortcode-templates
```
Step 4
: Make changes.
Step 5
: Build the site locally to preview your changes.
Step 6
: Commit your changes with a descriptive commit message:
- Provide a summary on the first line, typically 50 characters or less, followed by a blank line.
- Optionally, provide a detailed description where each line is 80 characters or less, followed by a blank line.
- Optionally, add one or more "Fixes" or "Closes" keywords, each on its own line, referencing the [issues] addressed by this change.
For example:
: Commit your changes with a descriptive commit message, typically 50 characters or less. Add the "Closes" keyword if your change addresses one or more open [issues].
```sh
git commit -m "Restructure the taxonomy page
git commit -m "Fix typos on the shortcode templates page
This restructures the taxonomy page by splitting topics into logical
sections, each with one or more examples.
Fixes #9999
Closes #9998"
Closes #1234
Closes #5678"
```
Step 7
Step 6
: Push the new branch to your fork of the documentation repository.
Step 8
Step 7
: Visit the [documentation repository] and create a pull request (PR).
Step 9
Step 8
: A project maintainer will review your PR and may request changes. You may delete your branch after the maintainer merges your PR.
[ATX]: https://spec.commonmark.org/0.30/#atx-headings
+2 -2
View File
@@ -8,7 +8,7 @@ action:
- functions/cast/ToFloat
- functions/cast/ToString
returnType: int
signatures: [cast.ToInt INPUT]
signatures: [cast/ToInt INPUT]
aliases: [/functions/int]
---
@@ -49,5 +49,5 @@ With a hexadecimal (base 16) input:
{{% note %}}
Values with a leading zero are octal (base 8). When casting a string representation of a decimal (base 10) number, remove leading zeros:
`{{ strings.TrimLeft "0" "0011" | int }} → 11`
`{{ strings/TrimLeft "0" "0011" | int }} → 11`
{{% /note %}}
@@ -15,8 +15,6 @@ action:
aliases: [/functions/crypto.fnv32a]
---
{{< new-in 0.98.0 >}}
This function calculates the 32-bit [FNV1a hash](https://en.wikipedia.org/wiki/Fowler%E2%80%93Noll%E2%80%93Vo_hash_function#FNV-1a_hash) of a given string according to the [specification](https://datatracker.ietf.org/doc/html/draft-eastlake-fnv-12):
```go-html-template
-160
View File
@@ -1,160 +0,0 @@
---
title: images.Dither
description: Returns an image filter that dithers an image.
categories: []
keywords: []
action:
aliases: []
related:
- functions/images/Filter
- functions/images/Process
- methods/resource/Colors
- methods/resource/Filter
returnType: images.filter
signatures: ['images.Dither [OPTIONS]']
toc: true
---
## Options
colors
: (`string array`) A slice of two or more colors that make up the dithering palette, each expressed as an RGB or RGBA [hexadecimal] value, with or without a leading hash mark. The default values are opaque black (`000000ff`) and opaque white (`ffffffff`).
[hexadecimal]: https://developer.mozilla.org/en-US/docs/Web/CSS/hex-color
method
: (`string`) The dithering method. See the [dithering methods](#dithering-methods) section below for a list of the available methods. Default is `FloydSteinberg`.
serpentine
: (`bool`) Applicable to error diffusion dithering methods, serpentine controls whether the error diffusion matrix is applied in a serpentine manner, meaning that it goes right-to-left every other line. This greatly reduces line-type artifacts. Default is `true`.
strength
: (`float`) The strength at which to apply the dithering matrix, typically a value in the range [0, 1]. A value of `1.0` applies the dithering matrix at 100% strength (no modifification of the dither matrix). The `strength` is inversely proportional to contrast; reducing the strength increases the contrast. Setting `strength` to a value such as `0.8` can be useful to reduce noise in the dithered image. Default is `1.0`.
## Usage
Create the options map:
```go-html-template
{{ $opts := dict
"colors" (slice "222222" "808080" "dddddd")
"method" "ClusteredDot4x4"
"strength" 0.85
}}
```
Create the filter:
```go-html-template
{{ $filter := images.Dither $opts }}
```
Or create the filter using the default settings:
```go-html-template
{{ $filter := images.Dither }}
```
{{% include "functions/images/_common/apply-image-filter.md" %}}
## Dithering methods
See the [Go documentation] for descriptions of each of the dithering methods below.
[Go documentation]: https://pkg.go.dev/github.com/makeworld-the-better-one/dither/v2#pkg-variables
Error diffusion dithering methods:
- Atkinson
- Burkes
- FalseFloydSteinberg
- FloydSteinberg
- JarvisJudiceNinke
- Sierra
- Sierra2
- Sierra2_4A
- Sierra3
- SierraLite
- Simple2D
- StevenPigeon
- Stucki
- TwoRowSierra
Ordered dithering methods:
- ClusteredDot4x4
- ClusteredDot6x6
- ClusteredDot6x6_2
- ClusteredDot6x6_3
- ClusteredDot8x8
- ClusteredDotDiagonal16x16
- ClusteredDotDiagonal6x6
- ClusteredDotDiagonal8x8
- ClusteredDotDiagonal8x8_2
- ClusteredDotDiagonal8x8_3
- ClusteredDotHorizontalLine
- ClusteredDotSpiral5x5
- ClusteredDotVerticalLine
- Horizontal3x5
- Vertical5x3
## Example
This example uses the default dithering options.
{{< img
src="images/examples/zion-national-park.jpg"
alt="Zion National Park"
filter="Dither"
filterArgs=""
example=true
>}}
## Recommendations
Regardless of dithering method, do both of the following to obtain the best results:
1. Scale the image _before_ dithering
2. Output the image to a lossless format such as GIF or PNG
The example below does both of these, and it sets the dithering palette to the three most dominant colors in the image.
```go-html-template
{{ with resources.Get "original.jpg" }}
{{ $opts := dict
"method" "ClusteredDotSpiral5x5"
"colors" (first 3 .Colors)
}}
{{ $filters := slice
(images.Process "resize 800x")
(images.Dither $opts)
(images.Process "png")
}}
{{ with . | images.Filter $filters }}
<img src="{{ .RelPermalink }}" width="{{ .Width }}" height="{{ .Height }}" alt="">
{{ end }}
{{ end }}
```
For best results, if the dithering palette is grayscale, convert the image to grayscale before dithering.
```go-html-template
{{ $opts := dict "colors" (slice "222" "808080" "ddd") }}
{{ $filters := slice
(images.Process "resize 800x")
(images.Grayscale)
(images.Dither $opts)
(images.Process "png")
}}
{{ with images.Filter $filters . }}
<img src="{{ .RelPermalink }}" width="{{ .Width }}" height="{{ .Height }}" alt="">
{{ end }}
```
The example above:
1. Resizes the image to be 800 px wide
2. Converts the image to grayscale
3. Dithers the image using the default (`FloydSteinberg`) dithering method with a grayscale palette
4. Converts the image to the PNG format
-23
View File
@@ -111,29 +111,6 @@ format
sourceMap
: (`string`) Whether to generate `inline` or `external` source maps from esbuild. External source maps will be written to the target with the output file name + ".map". Input source maps can be read from js.Build and node modules and combined into the output source maps. By default, source maps are not created.
JSX {{< new-in 0.124.0 >}}
: (`string`) How to handle/transform JSX syntax. One of: `transform`, `preserve`, `automatic`. Default is `transform`. Notably, the `automatic` transform was introduced in React 17+ and will cause the necessary JSX helper functions to be imported automatically. See https://esbuild.github.io/api/#jsx
JSXImportSource {{< new-in 0.124.0 >}}
: (`string`) Which library to use to automatically import its JSX helper functions from. This only works if `JSX` is set to `automatic`. The specified library needs to be installed through NPM and expose certain exports. See https://esbuild.github.io/api/#jsx-import-source
The combination of `JSX` and `JSXImportSource` is helpful if you want to use a non-React JSX library like Preact, e.g.:
```go-html-template
{{ $js := resources.Get "js/main.jsx" | js.Build (dict "JSX" "automatic" "JSXImportSource" "preact") }}
```
With the above, you can use Preact components and JSX without having to manually import `h` and `Fragment` every time:
```jsx
import { render } from 'preact';
const App = () => <>Hello world!</>;
const container = document.getElementById('app');
if (container) render(<App />, container);
```
### Import JS code from /assets
`js.Build` has full support for the virtual union file system in [Hugo Modules](/hugo-modules/). You can see some simple examples in this [test project](https://github.com/gohugoio/hugoTestProjectJSModImports), but in short this means that you can do this:
+19 -139
View File
@@ -8,18 +8,17 @@ action:
related: []
returnType: string
signatures: ['lang.Translate KEY [CONTEXT]']
toc: true
aliases: [/functions/i18n]
---
The `lang.Translate` function returns the value associated with given key as defined in the translation table for the current language.
The `lang.Translate` function returns the value associated with given key as defined in the translation table for the current language.
If the key is not found in the translation table for the current language, the `lang.Translate` function falls back to the translation table for the [`defaultContentLanguage`].
[`defaultContentLanguage`]: /getting-started/configuration/#defaultcontentlanguage
If the key is not found in the translation table for the current language, the `lang.Translate` function falls back to the translation table for the [`defaultContentLanguage`].
If the key is not found in the translation table for the `defaultContentLanguage`, the `lang.Translate` function returns an empty string.
[`defaultContentLanguage`]: /getting-started/configuration/#defaultcontentlanguage
{{% note %}}
To list missing and fallback translations, use the `--printI18nWarnings` flag when building your site.
@@ -29,31 +28,6 @@ To render placeholders for missing and fallback translations, set
[`enableMissingTranslationPlaceholders`]: /getting-started/configuration/#enablemissingtranslationplaceholders
{{% /note %}}
## Translation tables
Create translation tables in the i18n directory, naming each file according to [RFC 5646]. Translation tables may be JSON, TOML, or YAML. For example:
```text
i18n/en.toml
i18n/en-US.toml
```
The base name must match the language key as defined in your site configuration.
Artificial languages with private use subtags as defined in [RFC 5646 § 2.2.7] are also supported. You may omit the `art-x-` prefix for brevity. For example:
```text
i18n/art-x-hugolang.toml
i18n/hugolang.toml
```
Private use subtags must not exceed 8 alphanumeric characters.
[RFC 5646]: https://datatracker.ietf.org/doc/html/rfc5646
[RFC 5646 § 2.2.7]: https://datatracker.ietf.org/doc/html/rfc5646#section-2.2.7
## Simple translations
Let's say your multilingual site supports two languages, English and Polish. Create a translation table for each language in the `i18n` directory.
```text
@@ -62,47 +36,10 @@ i18n/
└── pl.toml
```
The English translation table:
The translation tables can contain both:
{{< code-toggle file=i18n/en >}}
privacy = 'privacy'
security = 'security'
{{< /code-toggle >}}
The Polish translation table:
{{< code-toggle file=i18n/pl >}}
privacy = 'prywatność'
security = 'bezpieczeństwo'
{{< /code-toggle >}}
{{% note %}}
The examples below use the `T` alias for brevity.
{{% /note %}}
When viewing the English language site:
```go-html-template
{{ T "privacy" }} → privacy
{{ T "security" }} → security
````
When viewing the Polish language site:
```go-html-template
{{ T "privacy" }} → prywatność
{{ T "security" }} → bezpieczeństwo
```
## Translations with pluralization
Let's say your multilingual site supports two languages, English and Polish. Create a translation table for each language in the `i18n` directory.
```text
i18n/
├── en.toml
└── pl.toml
```
- Simple translations
- Translations with pluralization
The Unicode [CLDR Plural Rules chart] describes the pluralization categories for each language.
@@ -111,6 +48,9 @@ The Unicode [CLDR Plural Rules chart] describes the pluralization categories for
The English translation table:
{{< code-toggle file=i18n/en >}}
privacy = 'privacy'
security = 'security'
[day]
one = 'day'
other = 'days'
@@ -123,6 +63,9 @@ other = '{{ . }} days'
The Polish translation table:
{{< code-toggle file=i18n/pl >}}
privacy = 'prywatność'
security = 'bezpieczeństwo'
[day]
one = 'miesiąc'
few = 'miesiące'
@@ -143,6 +86,9 @@ The examples below use the `T` alias for brevity.
When viewing the English language site:
```go-html-template
{{ T "privacy" }} → privacy
{{ T "security" }} → security
{{ T "day" 0 }} → days
{{ T "day" 1 }} → day
{{ T "day" 2 }} → days
@@ -157,6 +103,9 @@ When viewing the English language site:
When viewing the Polish language site:
```go-html-template
{{ T "privacy" }} → prywatność
{{ T "security" }} → bezpieczeństwo
{{ T "day" 0 }} → miesięcy
{{ T "day" 1 }} → miesiąc
{{ T "day" 2 }} → miesiące
@@ -184,72 +133,3 @@ Template code:
{{ T "age" (dict "name" "Will" "count" 1) }} → Will is 1 year old.
{{ T "age" (dict "name" "John" "count" 3) }} → John is 3 years old.
```
{{% note %}}
Translation tables may contain both simple translations and translations with pluralization.
{{% /note %}}
## Reserved keys
Hugo uses the [go-i18n] package to look up values in translation tables. This package reserves the following keys for internal use:
[go-i18n]: https://github.com/nicksnyder/go-i18n
id
: (`string`) Uniquely identifies the message.
description
: (`string`) Describes the message to give additional context to translators that may be relevant for translation.
hash
: (`string`) Uniquely identifies the content of the message that this message was translated from.
leftdelim
: (`string`) The left Go template delimiter.
rightdelim
: (`string`) The right Go template delimiter.
zero
: (`string`) The content of the message for the [CLDR] plural form "zero".
one
: (`string`) The content of the message for the [CLDR] plural form "one".
two
: (`string`) The content of the message for the [CLDR] plural form "two".
few
: (`string`) The content of the message for the [CLDR] plural form "few".
many
: (`string`) The content of the message for the [CLDR] plural form "many".
other
: (`string`) The content of the message for the [CLDR] plural form "other".
[CLDR]: https://www.unicode.org/cldr/charts/43/supplemental/language_plural_rules.html
If you need to provide a translation for one of the reserved keys, you can prepend the word with an underscore. For example:
{{< code-toggle file=i18n/es >}}
_description = 'descripción'
_few = 'pocos'
_many = 'muchos'
_one = 'uno'
_other = 'otro'
_two = 'dos'
_zero = 'cero'
{{< /code-toggle >}}
Then in your templates:
```go-html-template
{{ T "_description" }} → descripción
{{ T "_few" }} → pocos
{{ T "_many" }} → muchos
{{ T "_one" }} → uno
{{ T "_two" }} → dos
{{ T "_zero" }} → cero
{{ T "_other" }} → otro
```
-6
View File
@@ -22,9 +22,3 @@ If one of the numbers is a [`float`], the result is a `float`.
```
[`float`]: /getting-started/glossary/#float
You can also use the `add` function to concatenate strings.
```go-html-template
{{ add "hu" "go" }} → hugo
```
+2
View File
@@ -47,3 +47,5 @@ news → true
Note that `os.ReadDir` is not recursive.
Details of the `FileInfo` structure are available in the [Go documentation](https://pkg.go.dev/io/fs#FileInfo).
For more information on using `readDir` and `readFile` in your templates, see [Local File Templates](/templates/files).
+2
View File
@@ -36,3 +36,5 @@ This is **bold** text.
```
Note that `os.ReadFile` returns raw (uninterpreted) content.
For more information on using `readDir` and `readFile` in your templates, see [Local File Templates](/templates/files).
@@ -171,45 +171,7 @@ Override the cache key by setting a `key` in the options map. Use this approach
```go-html-template
{{ $url := "https://example.org/images/a.jpg" }}
{{ $cacheKey := print $url (now.Format "2006-01-02") }}
{{ $resource := resources.GetRemote $url (dict "key" $cacheKey) }}
{{ $resource := resource.GetRemote $url (dict "key" $cacheKey) }}
```
[configure file caches]: /getting-started/configuration/#configure-file-caches
## Security
To protect against malicious intent, the `resources.GetRemote` function inspects the server response including:
- The [Content-Type] in the response header
- The file extension, if any
- The content itself
If Hugo is unable to resolve the media type to an entry in its [allowlist], the function throws an error:
```text
ERROR error calling resources.GetRemote: failed to resolve media type...
```
For example, you will see the error above if you attempt to download an executable.
Although the allowlist contains entries for common media types, you may encounter situations where Hugo is unable to resolve the media type of a file that you know to be safe. In these situations, edit your site configuration to add the media type to the allowlist. For example:
```text
[security.http]
mediaTypes=['application/vnd\.api\+json']
```
Note that the entry above is:
- An _addition_ to the allowlist; it does not _replace_ the allowlist
- An array of regular expressions
For example, to add two entries to the allowlist:
```text
[security.http]
mediaTypes=['application/vnd\.api\+json','image/avif']
```
[allowlist]: https://en.wikipedia.org/wiki/Whitelist
[Content-Type]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Type
@@ -11,26 +11,6 @@ weight: 60
# Use level 6 headings for each term in the glossary.
---
[A](#action)
[B](#bool)
[C](#cache)
[D](#default-sort-order)
[E](#environment)
[F](#field)
[G](#global-resource)
[I](#identifier)
[K](#kind)
[L](#layout)
[M](#map)
[O](#object)
[P](#page-bundle)
[R](#regular-page)
[S](#scalar)
[T](#taxonomic-weight)
[U](#unmarshal)
[V](#variable)
[W](#walk)
###### action
See [template action](#template-action).
-23
View File
@@ -95,29 +95,6 @@ format
sourceMap
: (`string`) Whether to generate `inline` or `external` source maps from esbuild. External source maps will be written to the target with the output file name + ".map". Input source maps can be read from js.Build and node modules and combined into the output source maps. By default, source maps are not created.
JSX {{< new-in 0.124.0 >}}
: (`string`) How to handle/transform JSX syntax. One of: `transform`, `preserve`, `automatic`. Default is `transform`. Notably, the `automatic` transform was introduced in React 17+ and will cause the necessary JSX helper functions to be imported automatically. See https://esbuild.github.io/api/#jsx
JSXImportSource {{< new-in 0.124.0 >}}
: (`string`) Which library to use to automatically import its JSX helper functions from. This only works if `JSX` is set to `automatic`. The specified library needs to be installed through NPM and expose certain exports. See https://esbuild.github.io/api/#jsx-import-source
The combination of `JSX` and `JSXImportSource` is helpful if you want to use a non-React JSX library like Preact, e.g.:
```go-html-template
{{ $js := resources.Get "js/main.jsx" | js.Build (dict "JSX" "automatic" "JSXImportSource" "preact") }}
```
With the above, you can use Preact components and JSX without having to manually import `h` and `Fragment` every time:
```jsx
import { render } from 'preact';
const App = () => <>Hello world!</>;
const container = document.getElementById('app');
if (container) render(<App />, container);
```
### Import JS code from /assets
`js.Build` has full support for the virtual union file system in [Hugo Modules](/hugo-modules/). You can see some simple examples in this [test project](https://github.com/gohugoio/hugoTestProjectJSModImports), but in short this means that you can do this:
+1 -1
View File
@@ -18,7 +18,7 @@ With this front matter:
title = 'Annual conference'
date = 2023-10-17T15:11:37-07:00
display_related = true
[author]
[params.author]
email = 'jsmith@example.org'
name = 'John Smith'
{{< /code-toggle >}}
+1 -1
View File
@@ -6,7 +6,7 @@ keywords: []
action:
related:
- methods/time/Before
- methods/time/Equal
- methods/time/After
- functions/time/AsTime
returnType: bool
signatures: [TIME1.After TIME2]
+1 -1
View File
@@ -127,7 +127,7 @@ Achievements:
You can use the following code to render the `Short Description` in your layout:
```go-html-template
<div>Short Description of {{ .Site.Data.user0123.Name }}: <p>{{ index .Site.Data.user0123 "Short Description" | markdownify }}</p></div>
<div>Short Description of {{ .Site.Data.User0123.Name }}: <p>{{ index .Site.Data.User0123 "Short Description" | markdownify }}</p></div>
```
Note the use of the [`markdownify`] function. This will send the description through the Markdown rendering engine.
+56
View File
@@ -0,0 +1,56 @@
---
title: Local file templates
description: Hugo's `readDir` and `readFile` functions make it easy to traverse your project's directory structure and write file contents to your templates.
categories: [templates]
keywords: [files,directories]
menu:
docs:
parent: templates
weight: 180
weight: 180
toc: true
aliases: [/extras/localfiles/,/templates/local-files/]
---
## Traverse local files
With Hugo's [`readDir`] and [`readFile`] template functions, you can traverse your website's files on your server.
## Use `readDir`
The [`readDir`] function returns an array of [`os.FileInfo`] structures. It takes the file's `path` as a single string argument. This path can be to any directory of your website (i.e., as found on your server's file system).
Whether the path is absolute or relative does not matter because---at least for `readDir`---the root of your website (typically `./public/`) in effect becomes both:
1. The file system root
2. The current working directory
## Use `readFile`
The [`readfile`] function reads a file from disk and converts it into a string to be manipulated by other Hugo functions or added as-is. `readFile` takes the file, including path, as an argument passed to the function.
To use the `readFile` function in your templates, make sure the path is relative to your *Hugo project's root directory*:
```go-html-template
{{ readFile "/content/templates/local-file-templates" }}
```
### `readFile` Example: Add a Project File to Content
As `readFile` is a function, it is only available to you in your templates and not your content. However, we can create a simple [shortcode template][sct] that calls `readFile`, passes the first argument through the function, and then allows an optional second argument to send the file through the Markdown processor. The pattern for adding this shortcode to your content will be as follows:
```go-html-template
{{</* readfile file="/path/to/local/file.txt" markdown="true" */>}}
```
{{% note %}}
If you are going to create [custom shortcodes](/templates/shortcode-templates/) with `readFile` for a theme, note that usage of the shortcode will refer to the project root and *not* your `themes` directory.
{{% /note %}}
[called directly in the Hugo docs]: https://github.com/gohugoio/hugoDocs/blob/master/content/en/templates/files.md
[`os.FileInfo`]: https://pkg.go.dev/io/fs#FileInfo
[`readDir`]: /functions/os/readdir
[`readFile`]: /functions/os/readfile
[sc]: /content-management/shortcodes/
[sct]: /templates/shortcode-templates/
[readfilesource]: https://github.com/gohugoio/hugoDocs/blob/master/layouts/shortcodes/readfile.html
@@ -85,6 +85,9 @@ The above example is fictional, but if used for the homepage on a site with `bas
The following is the full list of configuration options for output formats and their default values:
name
: the output format identifier. This is used to define what output format(s) you want for your pages.
mediaType
: this must match the `Type` of a defined media type.
+1 -1
View File
@@ -31,7 +31,7 @@ Setting `paginate` to a positive value will split the list pages for the homepag
## List paginator pages
{{% note %}}
Paginate a page collection in list templates for these page kinds: `home`, `section`, `taxonomy`, or `term`. You cannot paginate a page collection in a template for the `page` page kind.
`.Paginator` is provided to help you build a pager menu. This feature is currently only supported on homepage and list pages (i.e., taxonomies and section lists).
{{% /note %}}
There are two ways to configure and use a `.Paginator`:
+2 -2
View File
@@ -18,8 +18,8 @@ aliases: [/templates/partial/,/layout/chrome/,/extras/analytics/]
Partial templates---like [single page templates][singletemps] and [list page templates][listtemps]---have a specific [lookup order]. However, partials are simpler in that Hugo will only check in two places:
1. `layouts/partials/<PARTIALNAME>.html`
2. `themes/<THEME>/layouts/partials/<PARTIALNAME>.html`
1. `layouts/partials/*<PARTIALNAME>.html`
2. `themes/<THEME>/layouts/partials/*<PARTIALNAME>.html`
This allows a theme's end user to copy a partial's contents into a file of the same name for [further customization][customize].
+1 -1
View File
@@ -128,7 +128,7 @@ Here is a code example for how the render-image.html template could look:
Given this template file
{{< code file=layouts/_default/_markup/render-heading.html >}}
<h{{ .Level }} id="{{ .Anchor }}">{{ .Text | safeHTML }} <a href="#{{ .Anchor | safeURL }}">¶</a></h{{ .Level }}>
<h{{ .Level }} id="{{ .Anchor | safeURL }}">{{ .Text | safeHTML }} <a href="#{{ .Anchor | safeURL }}">¶</a></h{{ .Level }}>
{{< /code >}}
And this markdown
+3 -8
View File
@@ -1596,7 +1596,7 @@ config:
- ^npx$
- ^postcss$
osEnv:
- (?i)^((HTTPS?|NO)_PROXY|PATH(EXT)?|APPDATA|TE?MP|TERM|GO\w+|(XDG_CONFIG_)?HOME|USERPROFILE|SSH_AUTH_SOCK|DISPLAY|LANG|SYSTEMDRIVE)$
- (?i)^((HTTPS?|NO)_PROXY|PATH(EXT)?|APPDATA|TE?MP|TERM|GO\w+|(XDG_CONFIG_)?HOME|USERPROFILE|SSH_AUTH_SOCK|DISPLAY|LANG)$
funcs:
getenv:
- ^HUGO_
@@ -2506,7 +2506,7 @@ tpl:
- shuffle
Args:
- l
Description: Shuffle returns list l in a randomized order.
Description: Shuffle returns list l in a randomised order.
Examples: []
Slice:
Aliases:
@@ -2898,7 +2898,7 @@ tpl:
- format
- args
Description: Printf returns string representation of args formatted with the
layout in format.
layouut in format.
Examples:
- - '{{ printf "%s!" "works" }}'
- works!
@@ -3020,11 +3020,6 @@ tpl:
Args: null
Description: ""
Examples: null
Dither:
Aliases: null
Args: null
Description: ""
Examples: null
Filter:
Aliases: null
Args: null

Some files were not shown because too many files have changed in this diff Show More