mirror of
https://github.com/gohugoio/hugo.git
synced 2026-09-01 19:22:38 +00:00
Compare commits
171 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| a3574f6f70 | |||
| 989454a52d | |||
| 1e91e46520 | |||
| 8a57d0f15f | |||
| b76c50ac18 | |||
| 1cdd17882c | |||
| e2fb0b0e80 | |||
| 88aea56683 | |||
| f4c11571bb | |||
| 54075acc29 | |||
| 8b52303e31 | |||
| 3d45d30a41 | |||
| 095157cd65 | |||
| 29cf87444f | |||
| 1b4dd436dd | |||
| 4414ef73f3 | |||
| a133393eda | |||
| 9197debbfe | |||
| c29897fac0 | |||
| c70ab27ceb | |||
| 510d98b778 | |||
| 7fd6762c16 | |||
| 584f052f39 | |||
| b76d71761e | |||
| c5dca3bdee | |||
| ec463c0977 | |||
| 4d2743e4c8 | |||
| c20f70d9a3 | |||
| 1b556216a8 | |||
| 106c8e6de6 | |||
| 03b33ecb5e | |||
| 9928122eb8 | |||
| 105d3bc32f | |||
| 3e46ba5ce2 | |||
| 4d1303512b | |||
| 9943c1bef0 | |||
| 766757310a | |||
| d71c07cf3c | |||
| b462980ac2 | |||
| 47678d8cbd | |||
| 18b9b6488b | |||
| ce44a8e835 | |||
| 64f40731f1 | |||
| 1140314be1 | |||
| 404fd9e512 | |||
| b1b0cdee3a | |||
| 3eea082903 | |||
| 0f18cbe990 | |||
| 3f5473b7d4 | |||
| d1f6a1dc59 | |||
| 747cf4ad65 | |||
| d8774d7fc3 | |||
| 3b8947d821 | |||
| 321a66ef19 | |||
| 57a784e027 | |||
| 25c0f2408a | |||
| 4f2d2b2cc4 | |||
| b8eb45c9df | |||
| 1d90afff1b | |||
| e751afa9bd | |||
| a09b8a60eb | |||
| 0071b47b8b | |||
| 70d62993ee | |||
| 66240338f1 | |||
| 84b5123912 | |||
| 2912415955 | |||
| bb4e66cd7c | |||
| 45ec2f88bb | |||
| 1ba80874e4 | |||
| 84dd495f2b | |||
| 327bbc613f | |||
| 2447138f1d | |||
| 61ec7a20a5 | |||
| c289fcaaaa | |||
| cfc38ecfed | |||
| 22e579e050 | |||
| b886615d1b | |||
| ecdef2be70 | |||
| ff3ae62933 | |||
| bfa7453792 | |||
| 12ace3ad5c | |||
| c14fdddada | |||
| 186934feb4 | |||
| 13b43e6117 | |||
| bff4dddb12 | |||
| 885cd299b7 | |||
| 80e973ea5c | |||
| debf3c559a | |||
| 01b0eda96c | |||
| 87e100e61f | |||
| 1649f3126f | |||
| ccd6a4b71e | |||
| 6dc1a1752b | |||
| 806d4848c3 | |||
| 348aae91e8 | |||
| 61482cfab6 | |||
| 04ee1b9784 | |||
| 7a86fe9905 | |||
| 5fdcc09062 | |||
| f5245a7d5f | |||
| 5029676aca | |||
| 2216028620 | |||
| ecc3dd1f53 | |||
| de4a7f1e04 | |||
| 3aa22b0942 | |||
| 40c3d8233d | |||
| 7ff5ec734c | |||
| 3937ab24d0 | |||
| 9c57af1351 | |||
| d240a705d6 | |||
| bbcc2a7973 | |||
| 98ba786f2f | |||
| 6f42cfbc9b | |||
| a84beee429 | |||
| 65893efd8d | |||
| c0d9bebacc | |||
| 3e2f1cdfdb | |||
| 0a5b870281 | |||
| bba6996e15 | |||
| 94e2c276a8 | |||
| 90d397b142 | |||
| 61e6c730dd | |||
| e4f6b9eef8 | |||
| bb147f91ee | |||
| 266d46dccc | |||
| e77b2ad8fd | |||
| 9487acf6ab | |||
| 84b31721bf | |||
| b8ba33ca95 | |||
| f967212b72 | |||
| 1b4c423667 | |||
| 1e9a0b93e3 | |||
| cfc8d315b4 | |||
| dd6e2c8724 | |||
| 762417617c | |||
| 29bdbde19c | |||
| 6a4a3ab8f8 | |||
| 36f6f987a9 | |||
| 18a9ca7d7a | |||
| b6c8dfa9dc | |||
| 621ea42f3c | |||
| 4ef5720141 | |||
| 34e83789f7 | |||
| 4d3ebe4d21 | |||
| b5c0383bda | |||
| 4217fee4b0 | |||
| fad57964aa | |||
| 10da2bd765 | |||
| 01241d5dc9 | |||
| 8e61f1fe12 | |||
| f37412a575 | |||
| 21a4a9acd7 | |||
| 7a4a4790e5 | |||
| 54065b7ef8 | |||
| e333836f49 | |||
| cc7bfeea32 | |||
| 32eb1a8ad4 | |||
| 32af02cd3e | |||
| 189453612e | |||
| 5273a884d4 | |||
| 6334948515 | |||
| 75259636c8 | |||
| 0df9f3510f | |||
| 302e6a726b | |||
| 202fe0d45c | |||
| 843ffeb48d | |||
| bff5d19121 | |||
| da370d30de | |||
| 6bd328c584 | |||
| 766a2e7868 | |||
| 13e1617557 |
@@ -4,7 +4,7 @@ parameters:
|
||||
defaults: &defaults
|
||||
resource_class: large
|
||||
docker:
|
||||
- image: bepsays/ci-hugoreleaser:1.22400.20000
|
||||
- image: bepsays/ci-hugoreleaser:1.22500.20300
|
||||
environment: &buildenv
|
||||
GOMODCACHE: /root/project/gomodcache
|
||||
version: 2
|
||||
@@ -58,7 +58,7 @@ jobs:
|
||||
environment:
|
||||
<<: [*buildenv]
|
||||
docker:
|
||||
- image: bepsays/ci-hugoreleaser-linux-arm64:1.22400.20000
|
||||
- image: bepsays/ci-hugoreleaser-linux-arm64:1.22500.20300
|
||||
steps:
|
||||
- *restore-cache
|
||||
- &attach-workspace
|
||||
|
||||
@@ -16,7 +16,7 @@ jobs:
|
||||
test:
|
||||
strategy:
|
||||
matrix:
|
||||
go-version: [1.23.x, 1.24.x]
|
||||
go-version: [1.24.x, 1.25.x]
|
||||
os: [ubuntu-latest, windows-latest] # macos disabled for now because of disk space issues.
|
||||
runs-on: ${{ matrix.os }}
|
||||
steps:
|
||||
@@ -45,7 +45,7 @@ jobs:
|
||||
**/go.sum
|
||||
**/go.mod
|
||||
- name: Install Ruby
|
||||
uses: ruby/setup-ruby@a6e6f86333f0a2523ece813039b8b4be04560854 # v1.190.0
|
||||
uses: ruby/setup-ruby@44511735964dcb71245e7e55f72539531f7bc0eb # v1.257.0
|
||||
with:
|
||||
ruby-version: "2.7"
|
||||
bundler-cache: true #
|
||||
|
||||
+4
-4
@@ -2,8 +2,8 @@
|
||||
# Twitter: https://twitter.com/gohugoio
|
||||
# Website: https://gohugo.io/
|
||||
|
||||
ARG GO_VERSION="1.23.2"
|
||||
ARG ALPINE_VERSION="3.20"
|
||||
ARG GO_VERSION="1.25"
|
||||
ARG ALPINE_VERSION="3.22"
|
||||
ARG DART_SASS_VERSION="1.79.3"
|
||||
|
||||
FROM --platform=$BUILDPLATFORM tonistiigi/xx:1.5.0 AS xx
|
||||
@@ -19,7 +19,7 @@ RUN apk add clang lld
|
||||
COPY --from=xx / /
|
||||
|
||||
ARG TARGETPLATFORM
|
||||
RUN xx-apk add musl-dev gcc g++
|
||||
RUN xx-apk add musl-dev gcc g++
|
||||
|
||||
# Optionally set HUGO_BUILD_TAGS to "none" or "withdeploy" when building like so:
|
||||
# docker build --build-arg HUGO_BUILD_TAGS=withdeploy .
|
||||
@@ -72,7 +72,7 @@ RUN mkdir -p /var/hugo/bin /cache && \
|
||||
adduser -Sg hugo -u 1000 -h /var/hugo hugo && \
|
||||
chown -R hugo: /var/hugo /cache && \
|
||||
# For the Hugo's Git integration to work.
|
||||
runuser -u hugo -- git config --global --add safe.directory /project && \
|
||||
runuser -u hugo -- git config --global --add safe.directory /project && \
|
||||
# See https://github.com/gohugoio/hugo/issues/9810
|
||||
runuser -u hugo -- git config --global core.quotepath false
|
||||
|
||||
|
||||
@@ -69,7 +69,7 @@ See the [features] section of the documentation for a comprehensive summary of H
|
||||
|
||||
<a href="https://www.jetbrains.com/go/?utm_source=OSS&utm_medium=referral&utm_campaign=hugo" target="_blank"><img src="https://raw.githubusercontent.com/gohugoio/hugoDocs/master/assets/images/sponsors/goland.svg" width="200" alt="The complete IDE crafted for professional Go developers."></a>
|
||||
|
||||
<a href="https://pinme.eth.limo/?s=hugo" target="_blank"><img src="https://raw.githubusercontent.com/gohugoio/hugoDocs/master/assets/images/sponsors/logo-pinme.svg" width="200" alt="PinMe."></a>
|
||||
<a href="https://cloudcannon.com/hugo-cms/?utm_campaign=HugoSponsorship&utm_source=sponsor&utm_content=gohugo" target="_blank"><img src="https://raw.githubusercontent.com/gohugoio/hugoDocs/master/assets/images/sponsors/cloudcannon-cms-logo.svg" width="200" alt="CloudCannon"></a>
|
||||
</p>
|
||||
|
||||
## Editions
|
||||
@@ -102,9 +102,9 @@ Install Hugo from a [prebuilt binary], package manager, or package repository. P
|
||||
|
||||
Prerequisites to build Hugo from source:
|
||||
|
||||
- Standard edition: Go 1.23.0 or later
|
||||
- Extended edition: Go 1.23.0 or later, and GCC
|
||||
- Extended/deploy edition: Go 1.23.0 or later, and GCC
|
||||
- Standard edition: Go 1.24.0 or later
|
||||
- Extended edition: Go 1.24.0 or later, and GCC
|
||||
- Extended/deploy edition: Go 1.24.0 or later, and GCC
|
||||
|
||||
Build the standard edition:
|
||||
|
||||
|
||||
Vendored
+13
-2
@@ -25,6 +25,8 @@ import (
|
||||
|
||||
// DefaultConfig holds the default configuration for the HTTP cache.
|
||||
var DefaultConfig = Config{
|
||||
RespectCacheControlNoStoreInRequest: true,
|
||||
RespectCacheControlNoStoreInResponse: false,
|
||||
Cache: Cache{
|
||||
For: GlobMatcher{
|
||||
Excludes: []string{"**"},
|
||||
@@ -42,7 +44,13 @@ var DefaultConfig = Config{
|
||||
|
||||
// Config holds the configuration for the HTTP cache.
|
||||
type Config struct {
|
||||
// Configures the HTTP cache behavior (RFC 9111).
|
||||
// When enabled and there's a Cache-Control: no-store directive in the request, response will never be stored in disk cache.
|
||||
RespectCacheControlNoStoreInRequest bool
|
||||
|
||||
// When enabled and there's a Cache-Control: no-store directive in the response, response will never be stored in disk cache.
|
||||
RespectCacheControlNoStoreInResponse bool
|
||||
|
||||
// Enables HTTP cache behavior (RFC 9111) for these resources.
|
||||
// When this is not enabled for a resource, Hugo will go straight to the file cache.
|
||||
Cache Cache
|
||||
|
||||
@@ -57,7 +65,9 @@ type Cache struct {
|
||||
}
|
||||
|
||||
func (c *Config) Compile() (ConfigCompiled, error) {
|
||||
var cc ConfigCompiled
|
||||
cc := ConfigCompiled{
|
||||
Base: *c,
|
||||
}
|
||||
|
||||
p, err := c.Cache.For.CompilePredicate()
|
||||
if err != nil {
|
||||
@@ -127,6 +137,7 @@ func (gm GlobMatcher) IsZero() bool {
|
||||
}
|
||||
|
||||
type ConfigCompiled struct {
|
||||
Base Config
|
||||
For predicate.P[string]
|
||||
PollConfigs []PollConfigCompiled
|
||||
}
|
||||
|
||||
+10
-5
@@ -51,6 +51,7 @@ func newGenCommand() *genCommand {
|
||||
lineNumbersInlineStyle string
|
||||
lineNumbersTableStyle string
|
||||
omitEmpty bool
|
||||
omitClassComments bool
|
||||
)
|
||||
|
||||
newChromaStyles := func() simplecobra.Commander {
|
||||
@@ -81,12 +82,14 @@ See https://xyproto.github.io/splash/docs/all.html for a preview of the availabl
|
||||
return err
|
||||
}
|
||||
|
||||
var formatter *html.Formatter
|
||||
if omitEmpty {
|
||||
formatter = html.New(html.WithClasses(true))
|
||||
} else {
|
||||
formatter = html.New(html.WithAllClasses(true))
|
||||
// See https://github.com/alecthomas/chroma/commit/5b2a4c5a26c503c79bc86ba3c4ae5b330028bd3d
|
||||
hugo.Deprecate("--omitEmpty", "Flag is no longer needed, empty classes are now always omitted.", "v0.149.0")
|
||||
}
|
||||
options := []html.Option{
|
||||
html.WithCSSComments(!omitClassComments),
|
||||
}
|
||||
formatter := html.New(options...)
|
||||
|
||||
w := os.Stdout
|
||||
fmt.Fprintf(w, "/* Generated using: hugo %s */\n\n", strings.Join(os.Args[1:], " "))
|
||||
@@ -103,8 +106,10 @@ See https://xyproto.github.io/splash/docs/all.html for a preview of the availabl
|
||||
_ = cmd.RegisterFlagCompletionFunc("lineNumbersInlineStyle", cobra.NoFileCompletions)
|
||||
cmd.PersistentFlags().StringVar(&lineNumbersTableStyle, "lineNumbersTableStyle", "", `foreground and background colors for table line numbers, e.g. --lineNumbersTableStyle "#fff000 bg:#000fff"`)
|
||||
_ = cmd.RegisterFlagCompletionFunc("lineNumbersTableStyle", cobra.NoFileCompletions)
|
||||
cmd.PersistentFlags().BoolVar(&omitEmpty, "omitEmpty", false, `omit empty CSS rules`)
|
||||
cmd.PersistentFlags().BoolVar(&omitEmpty, "omitEmpty", false, `omit empty CSS rules (deprecated, no longer needed)`)
|
||||
_ = cmd.RegisterFlagCompletionFunc("omitEmpty", cobra.NoFileCompletions)
|
||||
cmd.PersistentFlags().BoolVar(&omitClassComments, "omitClassComments", false, `omit CSS class comment prefixes in the generated CSS`)
|
||||
_ = cmd.RegisterFlagCompletionFunc("omitClassComments", cobra.NoFileCompletions)
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -76,7 +76,7 @@ func flagsToCfgWithAdditionalConfigBase(cd *simplecobra.Commandeer, cfg config.P
|
||||
|
||||
// Flags with a different name in the config.
|
||||
keyMap := map[string]string{
|
||||
"minify": "minifyOutput",
|
||||
"minify": "minify.minifyOutput",
|
||||
"destination": "publishDir",
|
||||
"editor": "newContentEditor",
|
||||
}
|
||||
|
||||
+21
-1
@@ -27,6 +27,7 @@ import (
|
||||
"sync/atomic"
|
||||
"time"
|
||||
|
||||
"github.com/bep/debounce"
|
||||
"github.com/bep/simplecobra"
|
||||
"github.com/fsnotify/fsnotify"
|
||||
"github.com/gohugoio/hugo/common/herrors"
|
||||
@@ -515,6 +516,14 @@ func (c *hugoBuilder) doWithPublishDirs(f func(sourceFs *filesystems.SourceFiles
|
||||
return langCount, nil
|
||||
}
|
||||
|
||||
func (c *hugoBuilder) progressIntermediate() {
|
||||
terminal.ReportProgress(c.r.StdOut, terminal.ProgressIntermediate, 0)
|
||||
}
|
||||
|
||||
func (c *hugoBuilder) progressHidden() {
|
||||
terminal.ReportProgress(c.r.StdOut, terminal.ProgressHidden, 0)
|
||||
}
|
||||
|
||||
func (c *hugoBuilder) fullBuild(noBuildLock bool) error {
|
||||
var (
|
||||
g errgroup.Group
|
||||
@@ -962,7 +971,7 @@ func (c *hugoBuilder) handleEvents(watcher *watcher.Batcher,
|
||||
lrl.Logf("no page to navigate to, force refresh")
|
||||
livereload.ForceRefresh()
|
||||
}
|
||||
} else if len(otherChanges) > 0 {
|
||||
} else if len(otherChanges) > 0 || len(cssChanges) > 0 {
|
||||
if len(otherChanges) == 1 {
|
||||
// Allow single changes to be refreshed without a full page reload.
|
||||
pathToRefresh := h.PathSpec.RelURL(paths.ToSlashTrimLeading(otherChanges[0]), false)
|
||||
@@ -1027,6 +1036,17 @@ func (c *hugoBuilder) hugoTry() *hugolib.HugoSites {
|
||||
}
|
||||
|
||||
func (c *hugoBuilder) loadConfig(cd *simplecobra.Commandeer, running bool) error {
|
||||
if terminal.PrintANSIColors(os.Stdout) {
|
||||
defer c.progressHidden()
|
||||
// If the configuration takes a while to load, we want to show some progress.
|
||||
// This is typically loading of external modules.
|
||||
d := debounce.New(500 * time.Millisecond)
|
||||
d(func() {
|
||||
c.progressIntermediate()
|
||||
})
|
||||
defer d(func() {})
|
||||
}
|
||||
|
||||
cfg := config.New()
|
||||
cfg.Set("renderToMemory", c.r.renderToMemory)
|
||||
watch := c.r.buildWatch || (c.s != nil && c.s.serverWatch)
|
||||
|
||||
+3
-1
@@ -53,7 +53,9 @@ Ensure you run this within the root directory of your site.`,
|
||||
if len(args) < 1 {
|
||||
return newUserError("path needs to be provided")
|
||||
}
|
||||
h, err := r.Hugo(flagsToCfg(cd, nil))
|
||||
cfg := flagsToCfg(cd, nil)
|
||||
cfg.Set("BuildFuture", true)
|
||||
h, err := r.Hugo(cfg)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -15,6 +15,7 @@ package collections
|
||||
|
||||
import (
|
||||
"html/template"
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
qt "github.com/frankban/quicktest"
|
||||
@@ -77,6 +78,7 @@ func TestAppend(t *testing.T) {
|
||||
{[]string{"a", "b"}, []any{nil}, []any{"a", "b", nil}},
|
||||
{[]string{"a", "b"}, []any{nil, "d", nil}, []any{"a", "b", nil, "d", nil}},
|
||||
{[]any{"a", nil, "c"}, []any{"d", nil, "f"}, []any{"a", nil, "c", "d", nil, "f"}},
|
||||
{[]string{"a", "b"}, []any{}, []string{"a", "b"}},
|
||||
} {
|
||||
|
||||
result, err := Append(test.start, test.addend...)
|
||||
@@ -146,3 +148,66 @@ func TestAppendShouldMakeACopyOfTheInputSlice(t *testing.T) {
|
||||
c.Assert(result, qt.DeepEquals, []string{"a", "b", "c"})
|
||||
c.Assert(slice, qt.DeepEquals, []string{"d", "b"})
|
||||
}
|
||||
|
||||
func TestIndirect(t *testing.T) {
|
||||
t.Parallel()
|
||||
c := qt.New(t)
|
||||
|
||||
type testStruct struct {
|
||||
Field string
|
||||
}
|
||||
|
||||
var (
|
||||
nilPtr *testStruct
|
||||
nilIface interface{} = nil
|
||||
nonNilIface interface{} = &testStruct{Field: "hello"}
|
||||
)
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
input any
|
||||
wantKind reflect.Kind
|
||||
wantNil bool
|
||||
}{
|
||||
{
|
||||
name: "nil pointer",
|
||||
input: nilPtr,
|
||||
wantKind: reflect.Ptr,
|
||||
wantNil: true,
|
||||
},
|
||||
{
|
||||
name: "nil interface",
|
||||
input: nilIface,
|
||||
wantKind: reflect.Invalid,
|
||||
wantNil: false,
|
||||
},
|
||||
{
|
||||
name: "non-nil pointer to struct",
|
||||
input: &testStruct{Field: "abc"},
|
||||
wantKind: reflect.Struct,
|
||||
wantNil: false,
|
||||
},
|
||||
{
|
||||
name: "non-nil interface holding pointer",
|
||||
input: nonNilIface,
|
||||
wantKind: reflect.Struct,
|
||||
wantNil: false,
|
||||
},
|
||||
{
|
||||
name: "plain value",
|
||||
input: testStruct{Field: "xyz"},
|
||||
wantKind: reflect.Struct,
|
||||
wantNil: false,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
v := reflect.ValueOf(tt.input)
|
||||
got, isNil := indirect(v)
|
||||
|
||||
c.Assert(got.Kind(), qt.Equals, tt.wantKind)
|
||||
c.Assert(isNil, qt.Equals, tt.wantNil)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -136,3 +136,37 @@ func TestSortedStringSlice(t *testing.T) {
|
||||
c.Assert(s.Count("z"), qt.Equals, 0)
|
||||
c.Assert(s.Count("a"), qt.Equals, 1)
|
||||
}
|
||||
|
||||
func TestStringSliceToInterfaceSlice(t *testing.T) {
|
||||
t.Parallel()
|
||||
c := qt.New(t)
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
in []string
|
||||
want []any
|
||||
}{
|
||||
{
|
||||
name: "empty slice",
|
||||
in: []string{},
|
||||
want: []any{},
|
||||
},
|
||||
{
|
||||
name: "single element",
|
||||
in: []string{"hello"},
|
||||
want: []any{"hello"},
|
||||
},
|
||||
{
|
||||
name: "multiple elements",
|
||||
in: []string{"a", "b", "c"},
|
||||
want: []any{"a", "b", "c"},
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
got := StringSliceToInterfaceSlice(tt.in)
|
||||
c.Assert(got, qt.DeepEquals, tt.want)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,77 @@
|
||||
package collections
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
qt "github.com/frankban/quicktest"
|
||||
)
|
||||
|
||||
func TestNewStack(t *testing.T) {
|
||||
t.Parallel()
|
||||
c := qt.New(t)
|
||||
|
||||
s := NewStack[int]()
|
||||
|
||||
c.Assert(s, qt.IsNotNil)
|
||||
}
|
||||
|
||||
func TestStackBasic(t *testing.T) {
|
||||
t.Parallel()
|
||||
c := qt.New(t)
|
||||
|
||||
s := NewStack[int]()
|
||||
|
||||
c.Assert(s.Len(), qt.Equals, 0)
|
||||
|
||||
s.Push(1)
|
||||
s.Push(2)
|
||||
s.Push(3)
|
||||
|
||||
c.Assert(s.Len(), qt.Equals, 3)
|
||||
|
||||
top, ok := s.Peek()
|
||||
c.Assert(ok, qt.Equals, true)
|
||||
c.Assert(top, qt.Equals, 3)
|
||||
|
||||
popped, ok := s.Pop()
|
||||
c.Assert(ok, qt.Equals, true)
|
||||
c.Assert(popped, qt.Equals, 3)
|
||||
|
||||
c.Assert(s.Len(), qt.Equals, 2)
|
||||
|
||||
_, _ = s.Pop()
|
||||
_, _ = s.Pop()
|
||||
_, ok = s.Pop()
|
||||
|
||||
c.Assert(ok, qt.Equals, false)
|
||||
}
|
||||
|
||||
func TestStackDrain(t *testing.T) {
|
||||
t.Parallel()
|
||||
c := qt.New(t)
|
||||
|
||||
s := NewStack[string]()
|
||||
s.Push("a")
|
||||
s.Push("b")
|
||||
|
||||
got := s.Drain()
|
||||
|
||||
c.Assert(got, qt.DeepEquals, []string{"a", "b"})
|
||||
c.Assert(s.Len(), qt.Equals, 0)
|
||||
}
|
||||
|
||||
func TestStackDrainMatching(t *testing.T) {
|
||||
t.Parallel()
|
||||
c := qt.New(t)
|
||||
|
||||
s := NewStack[int]()
|
||||
s.Push(1)
|
||||
s.Push(2)
|
||||
s.Push(3)
|
||||
s.Push(4)
|
||||
|
||||
got := s.DrainMatching(func(v int) bool { return v%2 == 0 })
|
||||
|
||||
c.Assert(got, qt.DeepEquals, []int{4, 2})
|
||||
c.Assert(s.Drain(), qt.DeepEquals, []int{1, 3})
|
||||
}
|
||||
@@ -24,6 +24,7 @@ const (
|
||||
WarnRenderShortcodesInHTML = "warning-rendershortcodes-in-html"
|
||||
WarnGoldmarkRawHTML = "warning-goldmark-raw-html"
|
||||
WarnPartialSuperfluousPrefix = "warning-partial-superfluous-prefix"
|
||||
WarnHomePageIsLeafBundle = "warning-home-page-is-leaf-bundle"
|
||||
)
|
||||
|
||||
// Field/method names with special meaning.
|
||||
|
||||
@@ -1,46 +0,0 @@
|
||||
// Copyright 2024 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.
|
||||
// You may obtain a copy of the License at
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package hcontext
|
||||
|
||||
import "context"
|
||||
|
||||
// ContextDispatcher is a generic interface for setting and getting values from a context.
|
||||
type ContextDispatcher[T any] interface {
|
||||
Set(ctx context.Context, value T) context.Context
|
||||
Get(ctx context.Context) T
|
||||
}
|
||||
|
||||
// NewContextDispatcher creates a new ContextDispatcher with the given key.
|
||||
func NewContextDispatcher[T any, R comparable](key R) ContextDispatcher[T] {
|
||||
return keyInContext[T, R]{
|
||||
id: key,
|
||||
}
|
||||
}
|
||||
|
||||
type keyInContext[T any, R comparable] struct {
|
||||
zero T
|
||||
id R
|
||||
}
|
||||
|
||||
func (f keyInContext[T, R]) Get(ctx context.Context) T {
|
||||
v := ctx.Value(f.id)
|
||||
if v == nil {
|
||||
return f.zero
|
||||
}
|
||||
return v.(T)
|
||||
}
|
||||
|
||||
func (f keyInContext[T, R]) Set(ctx context.Context, value T) context.Context {
|
||||
return context.WithValue(ctx, f.id, value)
|
||||
}
|
||||
@@ -86,6 +86,18 @@ func IsSlice(v any) bool {
|
||||
|
||||
var zeroType = reflect.TypeOf((*types.Zeroer)(nil)).Elem()
|
||||
|
||||
var isZeroCache sync.Map
|
||||
|
||||
func implementsIsZero(tp reflect.Type) bool {
|
||||
v, ok := isZeroCache.Load(tp)
|
||||
if ok {
|
||||
return v.(bool)
|
||||
}
|
||||
implements := tp.Implements(zeroType)
|
||||
isZeroCache.Store(tp, implements)
|
||||
return implements
|
||||
}
|
||||
|
||||
// IsTruthfulValue returns whether the given value has a meaningful truth value.
|
||||
// This is based on template.IsTrue in Go's stdlib, but also considers
|
||||
// IsZero and any interface value will be unwrapped before it's considered
|
||||
@@ -101,7 +113,11 @@ func IsTruthfulValue(val reflect.Value) (truth bool) {
|
||||
return
|
||||
}
|
||||
|
||||
if val.Type().Implements(zeroType) {
|
||||
if val.Kind() == reflect.Pointer && val.IsNil() {
|
||||
return
|
||||
}
|
||||
|
||||
if implementsIsZero(val.Type()) {
|
||||
return !val.Interface().(types.Zeroer).IsZero()
|
||||
}
|
||||
|
||||
|
||||
@@ -22,13 +22,29 @@ import (
|
||||
qt "github.com/frankban/quicktest"
|
||||
)
|
||||
|
||||
type zeroStruct struct {
|
||||
zero bool
|
||||
}
|
||||
|
||||
func (z zeroStruct) IsZero() bool {
|
||||
return z.zero
|
||||
}
|
||||
|
||||
func TestIsTruthful(t *testing.T) {
|
||||
c := qt.New(t)
|
||||
|
||||
var nilpointerZero *zeroStruct
|
||||
|
||||
c.Assert(IsTruthful(true), qt.Equals, true)
|
||||
c.Assert(IsTruthful(false), qt.Equals, false)
|
||||
c.Assert(IsTruthful(time.Now()), qt.Equals, true)
|
||||
c.Assert(IsTruthful(time.Time{}), qt.Equals, false)
|
||||
c.Assert(IsTruthful(&zeroStruct{zero: false}), qt.Equals, true)
|
||||
c.Assert(IsTruthful(&zeroStruct{zero: true}), qt.Equals, false)
|
||||
c.Assert(IsTruthful(zeroStruct{zero: false}), qt.Equals, true)
|
||||
c.Assert(IsTruthful(zeroStruct{zero: true}), qt.Equals, false)
|
||||
c.Assert(IsTruthful(nil), qt.Equals, false)
|
||||
c.Assert(IsTruthful(nilpointerZero), qt.Equals, false)
|
||||
}
|
||||
|
||||
func TestGetMethodByName(t *testing.T) {
|
||||
@@ -90,14 +106,26 @@ func BenchmarkIsContextType(b *testing.B) {
|
||||
})
|
||||
}
|
||||
|
||||
func BenchmarkIsTruthFul(b *testing.B) {
|
||||
v := reflect.ValueOf("Hugo")
|
||||
func BenchmarkIsTruthFulValue(b *testing.B) {
|
||||
var (
|
||||
stringHugo = reflect.ValueOf("Hugo")
|
||||
stringEmpty = reflect.ValueOf("")
|
||||
zero = reflect.ValueOf(time.Time{})
|
||||
timeNow = reflect.ValueOf(time.Now())
|
||||
boolTrue = reflect.ValueOf(true)
|
||||
boolFalse = reflect.ValueOf(false)
|
||||
nilPointer = reflect.ValueOf((*zeroStruct)(nil))
|
||||
)
|
||||
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
if !IsTruthfulValue(v) {
|
||||
b.Fatal("not truthful")
|
||||
}
|
||||
IsTruthfulValue(stringHugo)
|
||||
IsTruthfulValue(stringEmpty)
|
||||
IsTruthfulValue(zero)
|
||||
IsTruthfulValue(timeNow)
|
||||
IsTruthfulValue(boolTrue)
|
||||
IsTruthfulValue(boolFalse)
|
||||
IsTruthfulValue(nilPointer)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+3
-2
@@ -28,12 +28,13 @@ import (
|
||||
"github.com/bep/logg"
|
||||
|
||||
"github.com/bep/godartsass/v2"
|
||||
"github.com/gohugoio/hugo/common/hcontext"
|
||||
|
||||
"github.com/gohugoio/hugo/common/hexec"
|
||||
"github.com/gohugoio/hugo/common/loggers"
|
||||
"github.com/gohugoio/hugo/common/maps"
|
||||
"github.com/gohugoio/hugo/hugofs/files"
|
||||
|
||||
"github.com/bep/helpers/contexthelpers"
|
||||
"github.com/spf13/afero"
|
||||
|
||||
iofs "io/fs"
|
||||
@@ -145,7 +146,7 @@ const (
|
||||
contextKeyMarkupScope contextKey = iota
|
||||
)
|
||||
|
||||
var markupScope = hcontext.NewContextDispatcher[string](contextKeyMarkupScope)
|
||||
var markupScope = contexthelpers.NewContextDispatcher[string](contextKeyMarkupScope)
|
||||
|
||||
type Context struct{}
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@ package hugo
|
||||
// This should be the only one.
|
||||
var CurrentVersion = Version{
|
||||
Major: 0,
|
||||
Minor: 148,
|
||||
PatchLevel: 0,
|
||||
Suffix: "-DEV",
|
||||
Minor: 151,
|
||||
PatchLevel: 2,
|
||||
Suffix: "",
|
||||
}
|
||||
|
||||
+25
-2
@@ -20,13 +20,27 @@ import (
|
||||
// Cache is a simple thread safe cache backed by a map.
|
||||
type Cache[K comparable, T any] struct {
|
||||
m map[K]T
|
||||
opts CacheOptions
|
||||
hasBeenInitialized bool
|
||||
sync.RWMutex
|
||||
}
|
||||
|
||||
// NewCache creates a new Cache.
|
||||
// CacheOptions are the options for the Cache.
|
||||
type CacheOptions struct {
|
||||
// If set, the cache will not grow beyond this size.
|
||||
Size uint64
|
||||
}
|
||||
|
||||
var defaultCacheOptions = CacheOptions{}
|
||||
|
||||
// NewCache creates a new Cache with default options.
|
||||
func NewCache[K comparable, T any]() *Cache[K, T] {
|
||||
return &Cache[K, T]{m: make(map[K]T)}
|
||||
return &Cache[K, T]{m: make(map[K]T), opts: defaultCacheOptions}
|
||||
}
|
||||
|
||||
// NewCacheWithOptions creates a new Cache with the given options.
|
||||
func NewCacheWithOptions[K comparable, T any](opts CacheOptions) *Cache[K, T] {
|
||||
return &Cache[K, T]{m: make(map[K]T), opts: opts}
|
||||
}
|
||||
|
||||
// Delete deletes the given key from the cache.
|
||||
@@ -65,6 +79,7 @@ func (c *Cache[K, T]) GetOrCreate(key K, create func() (T, error)) (T, error) {
|
||||
if err != nil {
|
||||
return v, err
|
||||
}
|
||||
c.clearIfNeeded()
|
||||
c.m[key] = v
|
||||
return v, nil
|
||||
}
|
||||
@@ -127,7 +142,15 @@ func (c *Cache[K, T]) SetIfAbsent(key K, value T) {
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Cache[K, T]) clearIfNeeded() {
|
||||
if c.opts.Size > 0 && uint64(len(c.m)) >= c.opts.Size {
|
||||
// clear the map
|
||||
clear(c.m)
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Cache[K, T]) set(key K, value T) {
|
||||
c.clearIfNeeded()
|
||||
c.m[key] = value
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,57 @@
|
||||
// Copyright 2024 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.
|
||||
// You may obtain a copy of the License at
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package maps
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
qt "github.com/frankban/quicktest"
|
||||
)
|
||||
|
||||
func TestCacheSize(t *testing.T) {
|
||||
c := qt.New(t)
|
||||
|
||||
cache := NewCacheWithOptions[string, string](CacheOptions{Size: 10})
|
||||
|
||||
for i := 0; i < 30; i++ {
|
||||
cache.Set(string(rune('a'+i)), "value")
|
||||
}
|
||||
|
||||
c.Assert(len(cache.m), qt.Equals, 10)
|
||||
|
||||
for i := 20; i < 50; i++ {
|
||||
cache.GetOrCreate(string(rune('a'+i)), func() (string, error) {
|
||||
return "value", nil
|
||||
})
|
||||
}
|
||||
|
||||
c.Assert(len(cache.m), qt.Equals, 10)
|
||||
|
||||
for i := 100; i < 200; i++ {
|
||||
cache.SetIfAbsent(string(rune('a'+i)), "value")
|
||||
}
|
||||
|
||||
c.Assert(len(cache.m), qt.Equals, 10)
|
||||
|
||||
cache.InitAndGet("foo", func(
|
||||
get func(key string) (string, bool), set func(key string, value string),
|
||||
) error {
|
||||
for i := 50; i < 100; i++ {
|
||||
set(string(rune('a'+i)), "value")
|
||||
}
|
||||
return nil
|
||||
})
|
||||
|
||||
c.Assert(len(cache.m), qt.Equals, 10)
|
||||
}
|
||||
+16
-11
@@ -120,7 +120,7 @@ func (pp *PathParser) parse(component, s string) (*Path, error) {
|
||||
return p, nil
|
||||
}
|
||||
|
||||
func (pp *PathParser) parseIdentifier(component, s string, p *Path, i, lastDot, numDots int) {
|
||||
func (pp *PathParser) parseIdentifier(component, s string, p *Path, i, lastDot, numDots int, isLast bool) {
|
||||
if p.posContainerHigh != -1 {
|
||||
return
|
||||
}
|
||||
@@ -128,7 +128,12 @@ func (pp *PathParser) parseIdentifier(component, s string, p *Path, i, lastDot,
|
||||
mayHaveLang = mayHaveLang && (component == files.ComponentFolderContent || component == files.ComponentFolderLayouts)
|
||||
mayHaveOutputFormat := component == files.ComponentFolderLayouts
|
||||
mayHaveKind := p.posIdentifierKind == -1 && mayHaveOutputFormat
|
||||
mayHaveLayout := component == files.ComponentFolderLayouts
|
||||
var mayHaveLayout bool
|
||||
if p.pathType == TypeShortcode {
|
||||
mayHaveLayout = !isLast && component == files.ComponentFolderLayouts
|
||||
} else {
|
||||
mayHaveLayout = component == files.ComponentFolderLayouts
|
||||
}
|
||||
|
||||
var found bool
|
||||
var high int
|
||||
@@ -235,19 +240,22 @@ func (pp *PathParser) doParse(component, s string, p *Path) (*Path, error) {
|
||||
lastDot := 0
|
||||
lastSlashIdx := strings.LastIndex(s, "/")
|
||||
numDots := strings.Count(s[lastSlashIdx+1:], ".")
|
||||
if strings.Contains(s, "/_shortcodes/") {
|
||||
p.pathType = TypeShortcode
|
||||
}
|
||||
|
||||
for i := len(s) - 1; i >= 0; i-- {
|
||||
c := s[i]
|
||||
|
||||
switch c {
|
||||
case '.':
|
||||
pp.parseIdentifier(component, s, p, i, lastDot, numDots)
|
||||
pp.parseIdentifier(component, s, p, i, lastDot, numDots, false)
|
||||
lastDot = i
|
||||
case '/':
|
||||
slashCount++
|
||||
if p.posContainerHigh == -1 {
|
||||
if lastDot > 0 {
|
||||
pp.parseIdentifier(component, s, p, i, lastDot, numDots)
|
||||
pp.parseIdentifier(component, s, p, i, lastDot, numDots, true)
|
||||
}
|
||||
p.posContainerHigh = i + 1
|
||||
} else if p.posContainerLow == -1 {
|
||||
@@ -283,10 +291,9 @@ func (pp *PathParser) doParse(component, s string, p *Path) (*Path, error) {
|
||||
p.pathType = TypeContentData
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if component == files.ComponentFolderLayouts {
|
||||
if p.pathType < TypeMarkup && component == files.ComponentFolderLayouts {
|
||||
if p.posIdentifierBaseof != -1 {
|
||||
p.pathType = TypeBaseof
|
||||
} else {
|
||||
@@ -302,12 +309,10 @@ func (pp *PathParser) doParse(component, s string, p *Path) (*Path, error) {
|
||||
}
|
||||
|
||||
if p.pathType == TypeShortcode && p.posIdentifierLayout != -1 {
|
||||
// myshortcode or myshortcode.html, no layout.
|
||||
if len(p.identifiersKnown) <= 2 {
|
||||
id := p.identifiersKnown[p.posIdentifierLayout]
|
||||
if id.Low == p.posContainerHigh {
|
||||
// First identifier is shortcode name.
|
||||
p.posIdentifierLayout = -1
|
||||
} else {
|
||||
// First is always the name.
|
||||
p.posIdentifierLayout--
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -434,12 +434,12 @@ func TestParseLayouts(t *testing.T) {
|
||||
},
|
||||
{
|
||||
"Layout multiple",
|
||||
"/maylayout.list.section.no.html",
|
||||
"/mylayout.list.section.no.html",
|
||||
func(c *qt.C, p *Path) {
|
||||
c.Assert(p.Layout(), qt.Equals, "maylayout")
|
||||
c.Assert(p.Identifiers(), qt.DeepEquals, []string{"html", "no", "section", "list", "maylayout"})
|
||||
c.Assert(p.Layout(), qt.Equals, "mylayout")
|
||||
c.Assert(p.Identifiers(), qt.DeepEquals, []string{"html", "no", "section", "list", "mylayout"})
|
||||
c.Assert(p.IdentifiersUnknown(), qt.DeepEquals, []string{})
|
||||
c.Assert(p.Base(), qt.Equals, "/maylayout.html")
|
||||
c.Assert(p.Base(), qt.Equals, "/mylayout.html")
|
||||
c.Assert(p.Lang(), qt.Equals, "no")
|
||||
},
|
||||
},
|
||||
@@ -487,7 +487,8 @@ func TestParseLayouts(t *testing.T) {
|
||||
func(c *qt.C, p *Path) {
|
||||
c.Assert(p.Base(), qt.Equals, "/_shortcodes/myshortcode.html")
|
||||
c.Assert(p.Type(), qt.Equals, TypeShortcode)
|
||||
c.Assert(p.Identifiers(), qt.DeepEquals, []string{"html", "list", "myshortcode"})
|
||||
c.Assert(p.Identifiers(), qt.DeepEquals, []string{"html", "list"})
|
||||
c.Assert(p.Layout(), qt.Equals, "list")
|
||||
c.Assert(p.PathNoIdentifier(), qt.Equals, "/_shortcodes/myshortcode")
|
||||
c.Assert(p.PathBeforeLangAndOutputFormatAndExt(), qt.Equals, "/_shortcodes/myshortcode.list")
|
||||
c.Assert(p.Lang(), qt.Equals, "")
|
||||
@@ -572,11 +573,21 @@ func TestParseLayouts(t *testing.T) {
|
||||
c.Assert(p.NameNoIdentifier(), qt.Equals, "no")
|
||||
},
|
||||
},
|
||||
{
|
||||
"Shortcode lang layout",
|
||||
"/_shortcodes/myshortcode.no.html",
|
||||
func(c *qt.C, p *Path) {
|
||||
c.Assert(p.Type(), qt.Equals, TypeShortcode)
|
||||
c.Assert(p.Lang(), qt.Equals, "no")
|
||||
c.Assert(p.Layout(), qt.Equals, "")
|
||||
c.Assert(p.NameNoIdentifier(), qt.Equals, "myshortcode")
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
c.Run(test.name, func(c *qt.C) {
|
||||
if test.name != "Shortcode lang in root" {
|
||||
if test.name != "Shortcode lang layout" {
|
||||
// return
|
||||
}
|
||||
test.assert(c, testParser.Parse(files.ComponentFolderLayouts, test.path))
|
||||
|
||||
@@ -16,8 +16,8 @@ package terminal
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"runtime"
|
||||
"strings"
|
||||
|
||||
isatty "github.com/mattn/go-isatty"
|
||||
@@ -41,10 +41,6 @@ func PrintANSIColors(f *os.File) bool {
|
||||
// IsTerminal return true if the file descriptor is terminal and the TERM
|
||||
// environment variable isn't a dumb one.
|
||||
func IsTerminal(f *os.File) bool {
|
||||
if runtime.GOOS == "windows" {
|
||||
return false
|
||||
}
|
||||
|
||||
fd := f.Fd()
|
||||
return os.Getenv("TERM") != "dumb" && (isatty.IsTerminal(fd) || isatty.IsCygwinTerminal(fd))
|
||||
}
|
||||
@@ -77,3 +73,27 @@ func doublePercent(str string) string {
|
||||
func singlePercent(str string) string {
|
||||
return strings.Replace(str, "%%", "%", -1)
|
||||
}
|
||||
|
||||
type ProgressState int
|
||||
|
||||
const (
|
||||
ProgressHidden ProgressState = iota
|
||||
ProgressNormal
|
||||
ProgressError
|
||||
ProgressIntermediate
|
||||
ProgressWarning
|
||||
)
|
||||
|
||||
// ReportProgress writes OSC 9;4 sequence to w.
|
||||
func ReportProgress(w io.Writer, state ProgressState, progress float64) {
|
||||
if progress < 0 {
|
||||
progress = 0.0
|
||||
}
|
||||
if progress > 1 {
|
||||
progress = 1.0
|
||||
}
|
||||
|
||||
pi := int(progress * 100)
|
||||
|
||||
fmt.Fprintf(w, "\033]9;4;%d;%d\007", state, pi)
|
||||
}
|
||||
|
||||
@@ -20,6 +20,7 @@ import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
"regexp"
|
||||
"slices"
|
||||
"sort"
|
||||
"strconv"
|
||||
"strings"
|
||||
@@ -32,7 +33,6 @@ import (
|
||||
"github.com/gohugoio/hugo/common/loggers"
|
||||
"github.com/gohugoio/hugo/common/maps"
|
||||
"github.com/gohugoio/hugo/common/paths"
|
||||
"github.com/gohugoio/hugo/common/types"
|
||||
"github.com/gohugoio/hugo/common/urls"
|
||||
"github.com/gohugoio/hugo/config"
|
||||
"github.com/gohugoio/hugo/config/privacy"
|
||||
@@ -42,6 +42,7 @@ import (
|
||||
"github.com/gohugoio/hugo/helpers"
|
||||
"github.com/gohugoio/hugo/hugolib/segments"
|
||||
"github.com/gohugoio/hugo/langs"
|
||||
gc "github.com/gohugoio/hugo/markup/goldmark/goldmark_config"
|
||||
"github.com/gohugoio/hugo/markup/markup_config"
|
||||
"github.com/gohugoio/hugo/media"
|
||||
"github.com/gohugoio/hugo/minifiers"
|
||||
@@ -399,7 +400,6 @@ func (c *Config) CompileConfig(logger loggers.Logger) error {
|
||||
hugo.DeprecateWithLogger("site config key paginate", "Use pagination.pagerSize instead.", "v0.128.0", logger.Logger())
|
||||
c.Pagination.PagerSize = c.Paginate
|
||||
}
|
||||
|
||||
if c.PaginatePath != "" {
|
||||
hugo.DeprecateWithLogger("site config key paginatePath", "Use pagination.path instead.", "v0.128.0", logger.Logger())
|
||||
c.Pagination.Path = c.PaginatePath
|
||||
@@ -410,12 +410,10 @@ func (c *Config) CompileConfig(logger loggers.Logger) error {
|
||||
hugo.DeprecateWithLogger("site config key privacy.twitter.disable", "Use privacy.x.disable instead.", "v0.141.0", logger.Logger())
|
||||
c.Privacy.X.Disable = c.Privacy.Twitter.Disable
|
||||
}
|
||||
|
||||
if c.Privacy.Twitter.EnableDNT {
|
||||
hugo.DeprecateWithLogger("site config key privacy.twitter.enableDNT", "Use privacy.x.enableDNT instead.", "v0.141.0", logger.Logger())
|
||||
c.Privacy.X.EnableDNT = c.Privacy.Twitter.EnableDNT
|
||||
}
|
||||
|
||||
if c.Privacy.Twitter.Simple {
|
||||
hugo.DeprecateWithLogger("site config key privacy.twitter.simple", "Use privacy.x.simple instead.", "v0.141.0", logger.Logger())
|
||||
c.Privacy.X.Simple = c.Privacy.Twitter.Simple
|
||||
@@ -436,6 +434,45 @@ func (c *Config) CompileConfig(logger loggers.Logger) error {
|
||||
hugo.DeprecateWithLogger("the \":slugorfilename\" permalink token", "Use \":slugorcontentbasename\" instead.", "0.144.0", logger.Logger())
|
||||
}
|
||||
|
||||
// Legacy render hook values.
|
||||
alternativeDetails := fmt.Sprintf(
|
||||
"Set to %q if previous value was false, or set to %q if previous value was true.",
|
||||
gc.RenderHookUseEmbeddedNever,
|
||||
gc.RenderHookUseEmbeddedFallback,
|
||||
)
|
||||
if c.Markup.Goldmark.RenderHooks.Image.EnableDefault != nil {
|
||||
alternative := "Use markup.goldmark.renderHooks.image.useEmbedded instead." + " " + alternativeDetails
|
||||
hugo.DeprecateWithLogger("site config key markup.goldmark.renderHooks.image.enableDefault", alternative, "0.148.0", logger.Logger())
|
||||
if *c.Markup.Goldmark.RenderHooks.Image.EnableDefault {
|
||||
c.Markup.Goldmark.RenderHooks.Image.UseEmbedded = gc.RenderHookUseEmbeddedFallback
|
||||
} else {
|
||||
c.Markup.Goldmark.RenderHooks.Image.UseEmbedded = gc.RenderHookUseEmbeddedNever
|
||||
}
|
||||
}
|
||||
if c.Markup.Goldmark.RenderHooks.Link.EnableDefault != nil {
|
||||
alternative := "Use markup.goldmark.renderHooks.link.useEmbedded instead." + " " + alternativeDetails
|
||||
hugo.DeprecateWithLogger("site config key markup.goldmark.renderHooks.link.enableDefault", alternative, "0.148.0", logger.Logger())
|
||||
if *c.Markup.Goldmark.RenderHooks.Link.EnableDefault {
|
||||
c.Markup.Goldmark.RenderHooks.Link.UseEmbedded = gc.RenderHookUseEmbeddedFallback
|
||||
} else {
|
||||
c.Markup.Goldmark.RenderHooks.Link.UseEmbedded = gc.RenderHookUseEmbeddedNever
|
||||
}
|
||||
}
|
||||
|
||||
// Validate render hook configuration.
|
||||
renderHookUseEmbeddedModes := []string{
|
||||
gc.RenderHookUseEmbeddedAlways,
|
||||
gc.RenderHookUseEmbeddedAuto,
|
||||
gc.RenderHookUseEmbeddedFallback,
|
||||
gc.RenderHookUseEmbeddedNever,
|
||||
}
|
||||
if !slices.Contains(renderHookUseEmbeddedModes, c.Markup.Goldmark.RenderHooks.Image.UseEmbedded) {
|
||||
return fmt.Errorf("site config markup.goldmark.renderHooks.image must be one of %s", helpers.StringSliceToList(renderHookUseEmbeddedModes, "or"))
|
||||
}
|
||||
if !slices.Contains(renderHookUseEmbeddedModes, c.Markup.Goldmark.RenderHooks.Link.UseEmbedded) {
|
||||
return fmt.Errorf("site config markup.goldmark.renderHooks.link must be one of %s", helpers.StringSliceToList(renderHookUseEmbeddedModes, "or"))
|
||||
}
|
||||
|
||||
c.C = &ConfigCompiled{
|
||||
Timeout: timeout,
|
||||
BaseURL: baseURL,
|
||||
@@ -1082,13 +1119,11 @@ func fromLoadConfigResult(fs afero.Fs, logger loggers.Logger, res config.LoadCon
|
||||
|
||||
// Adjust Goldmark config defaults for multilingual, single-host sites.
|
||||
if len(languagesConfig) > 1 && !isMultihost && !clone.Markup.Goldmark.DuplicateResourceFiles {
|
||||
if !clone.Markup.Goldmark.DuplicateResourceFiles {
|
||||
if clone.Markup.Goldmark.RenderHooks.Link.EnableDefault == nil {
|
||||
clone.Markup.Goldmark.RenderHooks.Link.EnableDefault = types.NewBool(true)
|
||||
}
|
||||
if clone.Markup.Goldmark.RenderHooks.Image.EnableDefault == nil {
|
||||
clone.Markup.Goldmark.RenderHooks.Image.EnableDefault = types.NewBool(true)
|
||||
}
|
||||
if clone.Markup.Goldmark.RenderHooks.Image.UseEmbedded == gc.RenderHookUseEmbeddedAuto {
|
||||
clone.Markup.Goldmark.RenderHooks.Image.UseEmbedded = gc.RenderHookUseEmbeddedFallback
|
||||
}
|
||||
if clone.Markup.Goldmark.RenderHooks.Link.UseEmbedded == gc.RenderHookUseEmbeddedAuto {
|
||||
clone.Markup.Goldmark.RenderHooks.Link.UseEmbedded = gc.RenderHookUseEmbeddedFallback
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -2,12 +2,14 @@ package allconfig_test
|
||||
|
||||
import (
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
qt "github.com/frankban/quicktest"
|
||||
"github.com/gohugoio/hugo/common/hugo"
|
||||
"github.com/gohugoio/hugo/config/allconfig"
|
||||
"github.com/gohugoio/hugo/hugolib"
|
||||
gc "github.com/gohugoio/hugo/markup/goldmark/goldmark_config"
|
||||
"github.com/gohugoio/hugo/media"
|
||||
)
|
||||
|
||||
@@ -379,3 +381,28 @@ weight = 3
|
||||
|
||||
b.Assert(len(b.H.Sites), qt.Equals, 1)
|
||||
}
|
||||
|
||||
// Issue 13535
|
||||
// We changed enablement of the embedded link and image render hooks from
|
||||
// booleans to enums in v0.148.0.
|
||||
func TestLegacyEmbeddedRenderHookEnablement(t *testing.T) {
|
||||
files := `
|
||||
-- hugo.toml --
|
||||
[markup.goldmark.renderHooks.image]
|
||||
#KEY_VALUE
|
||||
|
||||
[markup.goldmark.renderHooks.link]
|
||||
#KEY_VALUE
|
||||
`
|
||||
f := strings.ReplaceAll(files, "#KEY_VALUE", "enableDefault = false")
|
||||
b := hugolib.Test(t, f)
|
||||
c := b.H.Configs.Base.Markup.Goldmark.RenderHooks
|
||||
b.Assert(c.Link.UseEmbedded, qt.Equals, gc.RenderHookUseEmbeddedNever)
|
||||
b.Assert(c.Image.UseEmbedded, qt.Equals, gc.RenderHookUseEmbeddedNever)
|
||||
|
||||
f = strings.ReplaceAll(files, "#KEY_VALUE", "enableDefault = true")
|
||||
b = hugolib.Test(t, f)
|
||||
c = b.H.Configs.Base.Markup.Goldmark.RenderHooks
|
||||
b.Assert(c.Link.UseEmbedded, qt.Equals, gc.RenderHookUseEmbeddedFallback)
|
||||
b.Assert(c.Image.UseEmbedded, qt.Equals, gc.RenderHookUseEmbeddedFallback)
|
||||
}
|
||||
|
||||
@@ -170,10 +170,16 @@ func (l configLoader) applyDefaultConfig() error {
|
||||
}
|
||||
|
||||
func (l configLoader) normalizeCfg(cfg config.Provider) error {
|
||||
if b, ok := cfg.Get("minifyOutput").(bool); ok && b {
|
||||
cfg.Set("minify.minifyOutput", true)
|
||||
} else if b, ok := cfg.Get("minify").(bool); ok && b {
|
||||
cfg.Set("minify", maps.Params{"minifyOutput": true})
|
||||
if b, ok := cfg.Get("minifyOutput").(bool); ok {
|
||||
hugo.Deprecate("site config minifyOutput", "Use minify.minifyOutput instead.", "v0.150.0")
|
||||
if b {
|
||||
cfg.Set("minify.minifyOutput", true)
|
||||
}
|
||||
} else if b, ok := cfg.Get("minify").(bool); ok {
|
||||
hugo.Deprecate("site config minify", "Use minify.minifyOutput instead.", "v0.150.0")
|
||||
if b {
|
||||
cfg.Set("minify", maps.Params{"minifyOutput": true})
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
@@ -280,7 +286,14 @@ func (l *configLoader) envValToVal(k string, v any) any {
|
||||
|
||||
func (l *configLoader) envStringToVal(k, v string) any {
|
||||
switch k {
|
||||
case "disablekinds", "disablelanguages":
|
||||
case "disablekinds", "disablelanguages", "ignorefiles", "ignorelogs":
|
||||
v = strings.TrimSpace(v)
|
||||
if strings.HasPrefix(v, "[") && strings.HasSuffix(v, "]") {
|
||||
if parsed, err := metadecoders.Default.UnmarshalStringTo(v, []any{}); err == nil {
|
||||
return parsed
|
||||
}
|
||||
}
|
||||
|
||||
if strings.Contains(v, ",") {
|
||||
return strings.Split(v, ",")
|
||||
} else {
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
package config
|
||||
|
||||
import (
|
||||
"regexp"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
@@ -32,3 +33,13 @@ func TestIsValidConfigFileName(t *testing.T) {
|
||||
c.Assert(IsValidConfigFilename(""), qt.Equals, false)
|
||||
c.Assert(IsValidConfigFilename("config.toml.swp"), qt.Equals, false)
|
||||
}
|
||||
|
||||
func TestFromTOMLConfigString(t *testing.T) {
|
||||
c := qt.New(t)
|
||||
|
||||
c.Assert(
|
||||
func() { FromTOMLConfigString("cfg") },
|
||||
qt.PanicMatches,
|
||||
regexp.MustCompile("_stream.toml:.*"),
|
||||
)
|
||||
}
|
||||
|
||||
@@ -17,6 +17,7 @@ import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"slices"
|
||||
"strconv"
|
||||
"strings"
|
||||
"testing"
|
||||
@@ -353,6 +354,90 @@ func TestDefaultConfigProvider(t *testing.T) {
|
||||
|
||||
c.Assert(r.Wait(), qt.IsNil)
|
||||
})
|
||||
|
||||
c.Run("GetBool", func(c *qt.C) {
|
||||
cfg := New()
|
||||
|
||||
var k string
|
||||
var v bool
|
||||
|
||||
k, v = "foo", true
|
||||
|
||||
cfg.Set(k, v)
|
||||
c.Assert(cfg.Get(k), qt.Equals, v)
|
||||
c.Assert(cfg.GetBool(k), qt.Equals, v)
|
||||
})
|
||||
|
||||
c.Run("GetParams", func(c *qt.C) {
|
||||
cfg := New()
|
||||
k := "foo"
|
||||
|
||||
cfg.Set(k, maps.Params{k: true})
|
||||
c.Assert(cfg.GetParams(k), qt.DeepEquals, maps.Params{
|
||||
k: true,
|
||||
})
|
||||
|
||||
c.Assert(cfg.GetParams("bar"), qt.IsNil)
|
||||
})
|
||||
|
||||
c.Run("Keys", func(c *qt.C) {
|
||||
cfg := New()
|
||||
k := "foo"
|
||||
k2 := "bar"
|
||||
|
||||
cfg.Set(k, maps.Params{k: struct{}{}})
|
||||
cfg.Set(k2, maps.Params{k2: struct{}{}})
|
||||
|
||||
c.Assert(len(cfg.Keys()), qt.Equals, 2)
|
||||
|
||||
got := cfg.Keys()
|
||||
slices.Sort(got)
|
||||
|
||||
want := []string{k, k2}
|
||||
slices.Sort(want)
|
||||
|
||||
c.Assert(got, qt.DeepEquals, want)
|
||||
})
|
||||
|
||||
c.Run("WalkParams", func(c *qt.C) {
|
||||
cfg := New()
|
||||
|
||||
cfg.Set("x", maps.Params{})
|
||||
cfg.Set("y", maps.Params{})
|
||||
|
||||
var got []string
|
||||
cfg.WalkParams(func(params ...maps.KeyParams) bool {
|
||||
got = append(got, params[len(params)-1].Key)
|
||||
return false
|
||||
})
|
||||
|
||||
want := []string{"", "x", "y"}
|
||||
slices.Sort(got)
|
||||
slices.Sort(want)
|
||||
|
||||
c.Assert(got, qt.DeepEquals, want)
|
||||
|
||||
cfg = New()
|
||||
cfg.WalkParams(func(params ...maps.KeyParams) bool {
|
||||
return true
|
||||
})
|
||||
|
||||
got = []string{""}
|
||||
want = []string{""}
|
||||
c.Assert(got, qt.DeepEquals, want)
|
||||
})
|
||||
|
||||
c.Run("SetDefaults", func(c *qt.C) {
|
||||
cfg := New()
|
||||
|
||||
cfg.SetDefaults(maps.Params{
|
||||
"foo": "bar",
|
||||
"bar": "baz",
|
||||
})
|
||||
|
||||
c.Assert(cfg.Get("foo"), qt.Equals, "bar")
|
||||
c.Assert(cfg.Get("bar"), qt.Equals, "baz")
|
||||
})
|
||||
}
|
||||
|
||||
func BenchmarkDefaultConfigProvider(b *testing.B) {
|
||||
|
||||
@@ -44,7 +44,7 @@ var DefaultConfig = Config{
|
||||
),
|
||||
// These have been tested to work with Hugo's external programs
|
||||
// on Windows, Linux and MacOS.
|
||||
OsEnv: MustNewWhitelist(`(?i)^((HTTPS?|NO)_PROXY|PATH(EXT)?|APPDATA|TE?MP|TERM|GO\w+|(XDG_CONFIG_)?HOME|USERPROFILE|SSH_AUTH_SOCK|DISPLAY|LANG|SYSTEMDRIVE)$`),
|
||||
OsEnv: MustNewWhitelist(`(?i)^((HTTPS?|NO)_PROXY|PATH(EXT)?|APPDATA|TE?MP|TERM|GO\w+|(XDG_CONFIG_)?HOME|USERPROFILE|SSH_AUTH_SOCK|DISPLAY|LANG|SYSTEMDRIVE|PROGRAMDATA)$`),
|
||||
},
|
||||
Funcs: Funcs{
|
||||
Getenv: MustNewWhitelist("^HUGO_", "^CI$"),
|
||||
|
||||
@@ -135,7 +135,7 @@ func TestToTOML(t *testing.T) {
|
||||
got := DefaultConfig.ToTOML()
|
||||
|
||||
c.Assert(got, qt.Equals,
|
||||
"[security]\n enableInlineShortcodes = false\n\n [security.exec]\n allow = ['^(dart-)?sass(-embedded)?$', '^go$', '^git$', '^npx$', '^postcss$', '^tailwindcss$']\n osEnv = ['(?i)^((HTTPS?|NO)_PROXY|PATH(EXT)?|APPDATA|TE?MP|TERM|GO\\w+|(XDG_CONFIG_)?HOME|USERPROFILE|SSH_AUTH_SOCK|DISPLAY|LANG|SYSTEMDRIVE)$']\n\n [security.funcs]\n getenv = ['^HUGO_', '^CI$']\n\n [security.http]\n methods = ['(?i)GET|POST']\n urls = ['.*']",
|
||||
"[security]\n enableInlineShortcodes = false\n\n [security.exec]\n allow = ['^(dart-)?sass(-embedded)?$', '^go$', '^git$', '^npx$', '^postcss$', '^tailwindcss$']\n osEnv = ['(?i)^((HTTPS?|NO)_PROXY|PATH(EXT)?|APPDATA|TE?MP|TERM|GO\\w+|(XDG_CONFIG_)?HOME|USERPROFILE|SSH_AUTH_SOCK|DISPLAY|LANG|SYSTEMDRIVE|PROGRAMDATA)$']\n\n [security.funcs]\n getenv = ['^HUGO_', '^CI$']\n\n [security.http]\n methods = ['(?i)GET|POST']\n urls = ['.*']",
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
{{ define "main" }}
|
||||
{{ .Content }}
|
||||
{{ range site.RegularPages }}
|
||||
<h2><a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a></h2>
|
||||
{{ .Summary }}
|
||||
<section>
|
||||
<h2><a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a></h2>
|
||||
{{ .Summary }}
|
||||
</section>
|
||||
{{ end }}
|
||||
{{ end }}
|
||||
|
||||
@@ -2,7 +2,9 @@
|
||||
<h1>{{ .Title }}</h1>
|
||||
{{ .Content }}
|
||||
{{ range .Pages }}
|
||||
<h2><a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a></h2>
|
||||
{{ .Summary }}
|
||||
<section>
|
||||
<h2><a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a></h2>
|
||||
{{ .Summary }}
|
||||
</section>
|
||||
{{ end }}
|
||||
{{ end }}
|
||||
|
||||
+49
-34
@@ -36,6 +36,7 @@ import (
|
||||
"github.com/dustin/go-humanize"
|
||||
"github.com/gobwas/glob"
|
||||
"github.com/gohugoio/hugo/common/loggers"
|
||||
"github.com/gohugoio/hugo/common/para"
|
||||
"github.com/gohugoio/hugo/config"
|
||||
"github.com/gohugoio/hugo/deploy/deployconfig"
|
||||
"github.com/gohugoio/hugo/media"
|
||||
@@ -487,7 +488,12 @@ 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, mappath func(string) string) (map[string]*localFile, error) {
|
||||
retval := map[string]*localFile{}
|
||||
retval := make(map[string]*localFile)
|
||||
var mu sync.Mutex
|
||||
|
||||
workers := para.New(d.cfg.Workers)
|
||||
g, _ := workers.Start(context.Background())
|
||||
|
||||
err := afero.Walk(fs, "", func(path string, info os.FileInfo, err error) error {
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -508,45 +514,54 @@ func (d *Deployer) walkLocal(fs afero.Fs, matchers []*deployconfig.Matcher, incl
|
||||
return nil
|
||||
}
|
||||
|
||||
// When a file system is HFS+, its filepath is in NFD form.
|
||||
if runtime.GOOS == "darwin" {
|
||||
path = norm.NFC.String(path)
|
||||
}
|
||||
|
||||
// Check include/exclude matchers.
|
||||
slashpath := filepath.ToSlash(path)
|
||||
if include != nil && !include.Match(slashpath) {
|
||||
d.logger.Infof(" dropping %q due to include\n", slashpath)
|
||||
return nil
|
||||
}
|
||||
if exclude != nil && exclude.Match(slashpath) {
|
||||
d.logger.Infof(" dropping %q due to exclude\n", slashpath)
|
||||
return nil
|
||||
}
|
||||
|
||||
// Find the first matching matcher (if any).
|
||||
var m *deployconfig.Matcher
|
||||
for _, cur := range matchers {
|
||||
if cur.Matches(slashpath) {
|
||||
m = cur
|
||||
break
|
||||
// Process each file in a worker
|
||||
g.Run(func() error {
|
||||
// When a file system is HFS+, its filepath is in NFD form.
|
||||
if runtime.GOOS == "darwin" {
|
||||
path = norm.NFC.String(path)
|
||||
}
|
||||
}
|
||||
// Apply any additional modifications to the local path, to map it to
|
||||
// the remote path.
|
||||
if mappath != nil {
|
||||
slashpath = mappath(slashpath)
|
||||
}
|
||||
lf, err := newLocalFile(fs, path, slashpath, m, mediaTypes)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
retval[lf.SlashPath] = lf
|
||||
|
||||
// Check include/exclude matchers.
|
||||
slashpath := filepath.ToSlash(path)
|
||||
if include != nil && !include.Match(slashpath) {
|
||||
d.logger.Infof(" dropping %q due to include\n", slashpath)
|
||||
return nil
|
||||
}
|
||||
if exclude != nil && exclude.Match(slashpath) {
|
||||
d.logger.Infof(" dropping %q due to exclude\n", slashpath)
|
||||
return nil
|
||||
}
|
||||
|
||||
// Find the first matching matcher (if any).
|
||||
var m *deployconfig.Matcher
|
||||
for _, cur := range matchers {
|
||||
if cur.Matches(slashpath) {
|
||||
m = cur
|
||||
break
|
||||
}
|
||||
}
|
||||
// Apply any additional modifications to the local path, to map it to
|
||||
// the remote path.
|
||||
if mappath != nil {
|
||||
slashpath = mappath(slashpath)
|
||||
}
|
||||
lf, err := newLocalFile(fs, path, slashpath, m, mediaTypes)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
mu.Lock()
|
||||
retval[lf.SlashPath] = lf
|
||||
mu.Unlock()
|
||||
return nil
|
||||
})
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := g.Wait(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return retval, nil
|
||||
}
|
||||
|
||||
|
||||
@@ -623,7 +623,7 @@ func TestEndToEndSync(t *testing.T) {
|
||||
localFs: test.fs,
|
||||
bucket: test.bucket,
|
||||
mediaTypes: media.DefaultTypes,
|
||||
cfg: deployconfig.DeployConfig{MaxDeletes: -1},
|
||||
cfg: deployconfig.DeployConfig{Workers: 2, MaxDeletes: -1},
|
||||
}
|
||||
|
||||
// Initial deployment should sync remote with local.
|
||||
@@ -706,7 +706,7 @@ func TestMaxDeletes(t *testing.T) {
|
||||
localFs: test.fs,
|
||||
bucket: test.bucket,
|
||||
mediaTypes: media.DefaultTypes,
|
||||
cfg: deployconfig.DeployConfig{MaxDeletes: -1},
|
||||
cfg: deployconfig.DeployConfig{Workers: 2, MaxDeletes: -1},
|
||||
}
|
||||
|
||||
// Sync remote with local.
|
||||
@@ -836,7 +836,7 @@ func TestIncludeExclude(t *testing.T) {
|
||||
}
|
||||
deployer := &Deployer{
|
||||
localFs: fsTest.fs,
|
||||
cfg: deployconfig.DeployConfig{MaxDeletes: -1}, bucket: fsTest.bucket,
|
||||
cfg: deployconfig.DeployConfig{Workers: 2, MaxDeletes: -1}, bucket: fsTest.bucket,
|
||||
target: tgt,
|
||||
mediaTypes: media.DefaultTypes,
|
||||
}
|
||||
@@ -893,7 +893,7 @@ func TestIncludeExcludeRemoteDelete(t *testing.T) {
|
||||
}
|
||||
deployer := &Deployer{
|
||||
localFs: fsTest.fs,
|
||||
cfg: deployconfig.DeployConfig{MaxDeletes: -1}, bucket: fsTest.bucket,
|
||||
cfg: deployconfig.DeployConfig{Workers: 2, MaxDeletes: -1}, bucket: fsTest.bucket,
|
||||
mediaTypes: media.DefaultTypes,
|
||||
}
|
||||
|
||||
@@ -945,7 +945,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.DeployConfig{Workers: 2, MaxDeletes: -1, Matchers: []*deployconfig.Matcher{{Pattern: ".*", Gzip: true, Re: regexp.MustCompile(".*")}}},
|
||||
mediaTypes: media.DefaultTypes,
|
||||
}
|
||||
|
||||
@@ -1000,7 +1000,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.DeployConfig{Workers: 2, MaxDeletes: -1, Matchers: []*deployconfig.Matcher{{Pattern: "^subdir/aaa$", Force: true, Re: regexp.MustCompile("^subdir/aaa$")}}},
|
||||
mediaTypes: media.DefaultTypes,
|
||||
}
|
||||
|
||||
@@ -1097,5 +1097,6 @@ func verifyRemote(ctx context.Context, bucket *blob.Bucket, local []*fileData) (
|
||||
func newDeployer() *Deployer {
|
||||
return &Deployer{
|
||||
logger: loggers.NewDefault(),
|
||||
cfg: deployconfig.DeployConfig{Workers: 2},
|
||||
}
|
||||
}
|
||||
|
||||
+2
-2
@@ -4,10 +4,10 @@
|
||||
[codespell]
|
||||
|
||||
# Comma separated list of dirs to be skipped.
|
||||
skip = _vendor,.cspell.json,chroma.css,chroma_dark.css
|
||||
skip = *.ai,chroma.css,chroma_dark.css,.cspell.json
|
||||
|
||||
# Comma separated list of words to be ignored. Words must be lowercased.
|
||||
ignore-words-list = abl,edn,te,ue,trys,januar,womens,crossreferences
|
||||
ignore-words-list = abl,edn,januar,te,trys,ue,womens
|
||||
|
||||
# Check file names as well.
|
||||
check-filenames = true
|
||||
|
||||
+14
-2
@@ -1,8 +1,15 @@
|
||||
{
|
||||
"version": "0.2",
|
||||
"allowCompoundWords": true,
|
||||
"files": [
|
||||
"**/*.md"
|
||||
"overrides": [
|
||||
{
|
||||
"filename": "**/*",
|
||||
"enabled": false
|
||||
},
|
||||
{
|
||||
"filename": "**/*.md",
|
||||
"enabled": true
|
||||
}
|
||||
],
|
||||
"flagWords": [
|
||||
"alot",
|
||||
@@ -64,12 +71,14 @@
|
||||
"templating",
|
||||
"transpile",
|
||||
"unmarshal",
|
||||
"unmarshaled",
|
||||
"unmarshaling",
|
||||
"unmarshals",
|
||||
"# ----------------------------------------------------------------------",
|
||||
"# cspell: ignore hugo terminology",
|
||||
"# ----------------------------------------------------------------------",
|
||||
"alignx",
|
||||
"aligny",
|
||||
"attrlink",
|
||||
"canonify",
|
||||
"codeowners",
|
||||
@@ -99,6 +108,8 @@
|
||||
"descripción",
|
||||
"dokumentation",
|
||||
"erklärungen",
|
||||
"español",
|
||||
"français",
|
||||
"libros",
|
||||
"mercredi",
|
||||
"miesiąc",
|
||||
@@ -146,6 +157,7 @@
|
||||
"dpkg",
|
||||
"doas",
|
||||
"eopkg",
|
||||
"forgejo",
|
||||
"gitee",
|
||||
"goldmark",
|
||||
"katex",
|
||||
|
||||
Vendored
-22
@@ -1,22 +0,0 @@
|
||||
# Number of days of inactivity before an issue becomes stale
|
||||
daysUntilStale: 120
|
||||
# Number of days of inactivity before a stale issue is closed
|
||||
daysUntilClose: 30
|
||||
# Issues with these labels will never be considered stale
|
||||
exemptLabels:
|
||||
- Keep
|
||||
- Security
|
||||
- UndocumentedFeature
|
||||
# Label to use when marking an issue as stale
|
||||
staleLabel: Stale
|
||||
# Comment to post when marking an issue as stale. Set to `false` to disable
|
||||
markComment: >
|
||||
This issue has been automatically marked as stale because it has not had
|
||||
recent activity. The resources of the Hugo team are limited, and so we are asking for your help.
|
||||
|
||||
If you still think this is important, please tell us why.
|
||||
|
||||
This issue will automatically be closed in the near future if no further activity occurs. Thank you for all your contributions.
|
||||
|
||||
# Comment to post when closing a stale issue. Set to `false` to disable
|
||||
closeComment: false
|
||||
+1
-1
@@ -15,7 +15,7 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v5
|
||||
|
||||
- name: Initialize CodeQL
|
||||
uses: github/codeql-action/init@v3
|
||||
|
||||
+15
@@ -0,0 +1,15 @@
|
||||
name: Lint markdown
|
||||
on:
|
||||
workflow_dispatch:
|
||||
pull_request:
|
||||
jobs:
|
||||
lint:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v5
|
||||
- name: Run Markdown linter
|
||||
uses: DavidAnson/markdownlint-cli2-action@v20
|
||||
with:
|
||||
globs: # set to null to override default of *.{md,markdown}
|
||||
continue-on-error: false
|
||||
+5
-7
@@ -12,16 +12,14 @@ jobs:
|
||||
spellcheck:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: streetsidesoftware/cspell-action@v5
|
||||
- uses: actions/checkout@v5
|
||||
- uses: streetsidesoftware/cspell-action@v7
|
||||
with:
|
||||
check_dot_files: false
|
||||
files: content/**/*.md
|
||||
incremental_files_only: true
|
||||
inline: warning
|
||||
strict: false
|
||||
strict: true
|
||||
# cspell uses the .cspell.json configuration file
|
||||
- uses: codespell-project/actions-codespell@v2
|
||||
with:
|
||||
check_filenames: true
|
||||
check_hidden: true
|
||||
# by default, codespell uses configuration from the .codespellrc
|
||||
# codespell uses the .codespellrc file
|
||||
|
||||
Vendored
+32
@@ -0,0 +1,32 @@
|
||||
name: Close stale issues and pull requests
|
||||
on:
|
||||
workflow_dispatch:
|
||||
schedule:
|
||||
- cron: "30 1 * * *"
|
||||
permissions:
|
||||
contents: read
|
||||
jobs:
|
||||
stale:
|
||||
permissions:
|
||||
contents: read
|
||||
issues: write
|
||||
pull-requests: write
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/stale@v9
|
||||
with:
|
||||
days-before-stale: 90 # default is 60
|
||||
days-before-close: 14 # default is 7
|
||||
exempt-all-assignees: true
|
||||
exempt-draft-pr: true
|
||||
exempt-issue-labels: Keep, InProgress, NeedsTriage
|
||||
exempt-pr-labels: Keep
|
||||
operations-per-run: 100
|
||||
stale-issue-message: >
|
||||
This issue has been marked as stale because there hasn't been any
|
||||
recent activity. It will be closed soon if there are no further
|
||||
updates.
|
||||
stale-pr-message: >
|
||||
This pull request has been marked as stale because there hasn't
|
||||
been any recent activity. It will be closed soon if there are no
|
||||
further updates.
|
||||
-41
@@ -1,41 +0,0 @@
|
||||
name: Super Linter
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
contents: read # to fetch code (actions/checkout)
|
||||
|
||||
jobs:
|
||||
build:
|
||||
permissions:
|
||||
contents: read # to fetch code (actions/checkout)
|
||||
statuses: write # to mark status of each linter run (github/super-linter/slim)
|
||||
|
||||
name: Lint Code Base
|
||||
runs-on: ubuntu-latest
|
||||
if: ${{ github.actor != 'dependabot[bot]' }}
|
||||
|
||||
steps:
|
||||
- name: Checkout Code
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Lint Code Base
|
||||
uses: super-linter/super-linter/slim@v6
|
||||
env:
|
||||
DEFAULT_BRANCH: master
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
IGNORE_GITIGNORED_FILES: true
|
||||
LINTER_RULES_PATH: /
|
||||
LOG_LEVEL: NOTICE
|
||||
MARKDOWN_CONFIG_FILE: .markdownlint.yaml
|
||||
SUPPRESS_POSSUM: true
|
||||
VALIDATE_CSS: false
|
||||
VALIDATE_EDITORCONFIG: false
|
||||
VALIDATE_GITLEAKS: false
|
||||
VALIDATE_HTML: false
|
||||
VALIDATE_JAVASCRIPT_STANDARD: false
|
||||
VALIDATE_JSCPD: false
|
||||
VALIDATE_NATURAL_LANGUAGE: false
|
||||
VALIDATE_SHELL_SHFMT: false
|
||||
VALIDATE_XML: false
|
||||
@@ -0,0 +1,91 @@
|
||||
# Glob patterns to include
|
||||
globs:
|
||||
- "content/**/*.md"
|
||||
|
||||
# Glob patterns to exclude
|
||||
ignores:
|
||||
- "content/**/commands/**"
|
||||
- "content/en/about/license.md"
|
||||
- "content/LICENSE.md"
|
||||
|
||||
# Markdownlint rules and configuration
|
||||
# https://github.com/DavidAnson/markdownlint?tab=readme-ov-file#rules--aliases
|
||||
config:
|
||||
MD001: true
|
||||
# MD002 deprecated
|
||||
MD003:
|
||||
style: atx
|
||||
MD004:
|
||||
style: dash
|
||||
MD005: true
|
||||
# MD006 deprecated
|
||||
MD007: false # if enabled, throws errors when definition descriptions contain list items
|
||||
# MD008 deprecated
|
||||
MD009: true
|
||||
MD010: true
|
||||
MD011: true
|
||||
MD012: true
|
||||
MD013: false
|
||||
MD014: true
|
||||
# MD015 deprecated
|
||||
# MD016 deprecated
|
||||
# MD017 deprecated
|
||||
MD018: true
|
||||
MD019: true
|
||||
MD020: true
|
||||
MD021: true
|
||||
MD022: true
|
||||
MD023: true
|
||||
MD024: true
|
||||
MD025: true
|
||||
MD026: true
|
||||
MD027: true
|
||||
MD028: false
|
||||
MD029:
|
||||
style: one
|
||||
MD030: true
|
||||
MD031: true
|
||||
MD032: true
|
||||
MD033: true
|
||||
MD034: false
|
||||
MD035:
|
||||
style: ---
|
||||
MD036: true
|
||||
MD037: true
|
||||
MD038: true
|
||||
MD039: true
|
||||
MD040: true
|
||||
MD041: false
|
||||
MD042: true
|
||||
MD043: false
|
||||
MD044: false
|
||||
MD045: true
|
||||
MD046: false
|
||||
MD047: true
|
||||
MD048:
|
||||
style: backtick
|
||||
MD049:
|
||||
style: underscore
|
||||
MD050:
|
||||
style: asterisk
|
||||
MD051: false
|
||||
MD052: true
|
||||
MD053: true
|
||||
MD054:
|
||||
autolink: true
|
||||
collapsed: true
|
||||
full: true
|
||||
inline: true
|
||||
shortcut: true
|
||||
url_inline: true
|
||||
MD055:
|
||||
style: consistent
|
||||
MD056: true
|
||||
# MD057 deprecated
|
||||
MD058: true
|
||||
MD059:
|
||||
prohibited_texts:
|
||||
- click here
|
||||
- here
|
||||
- link
|
||||
- more
|
||||
@@ -1,27 +0,0 @@
|
||||
# https://github.com/DavidAnson/markdownlint/blob/main/doc/Rules.md
|
||||
|
||||
MD001: false
|
||||
MD002: false
|
||||
MD003: false
|
||||
MD004: false
|
||||
MD007: false
|
||||
MD012:
|
||||
maximum: 2
|
||||
MD013: false
|
||||
MD014: false
|
||||
MD022: false
|
||||
MD024: false
|
||||
MD031: false
|
||||
MD032: false
|
||||
MD033: false
|
||||
MD034: false
|
||||
MD036: false
|
||||
MD037: false
|
||||
MD038: false
|
||||
MD041: false
|
||||
MD046: false
|
||||
MD049: false
|
||||
MD050: false
|
||||
MD051: false
|
||||
MD053: false
|
||||
MD055: false
|
||||
@@ -1,6 +0,0 @@
|
||||
**/commands/**
|
||||
**/functions/**
|
||||
**/news/**
|
||||
**/showcase/**
|
||||
**/zh/**
|
||||
**/license.md
|
||||
@@ -2,16 +2,16 @@
|
||||
**/icons.html
|
||||
|
||||
# These are whitespace sensitive.
|
||||
layouts/_default/_markup/render-code*
|
||||
layouts/_default/_markup/render-table*
|
||||
layouts/shortcodes/glossary-term.html
|
||||
layouts/shortcodes/glossary.html
|
||||
layouts/shortcodes/highlighting-styles.html
|
||||
layouts/shortcodes/list-pages-in-section.html
|
||||
layouts/shortcodes/quick-reference.html
|
||||
layouts/_markup/render-code*
|
||||
layouts/_markup/render-table*
|
||||
layouts/_shortcodes/glossary-term.html
|
||||
layouts/_shortcodes/glossary.html
|
||||
layouts/_shortcodes/highlighting-styles.html
|
||||
layouts/_shortcodes/list-pages-in-section.html
|
||||
layouts/_shortcodes/quick-reference.html
|
||||
|
||||
# No root node.
|
||||
layouts/partials/layouts/head/head.html
|
||||
layouts/_partials/layouts/head/head.html
|
||||
|
||||
# Auto generated.
|
||||
assets/css/components/chroma*.css
|
||||
|
||||
@@ -0,0 +1,100 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 24.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.1" id="图层_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
viewBox="0 0 299 118" height="100%" width="100%" style="enable-background:new 0 0 299 118;" xml:space="preserve">
|
||||
<style type="text/css">
|
||||
.st0{clip-path:url(#SVGID_2_);}
|
||||
.st1{fill:#414141;}
|
||||
.st2{fill:#3D4DF4;}
|
||||
</style>
|
||||
<g>
|
||||
<defs>
|
||||
<rect id="SVGID_1_" x="0.4" y="0" width="66.5" height="67.8"/>
|
||||
</defs>
|
||||
<clipPath id="SVGID_2_">
|
||||
<use xlink:href="#SVGID_1_" style="overflow:visible;"/>
|
||||
</clipPath>
|
||||
<g class="st0">
|
||||
<path class="st1" d="M34.2,28l31.4,18.3c0.9,0.5,1.1,1.6,0.6,2.4c-0.2,0.3-0.4,0.5-0.6,0.6L35.6,66.9c-1.4,0.8-3.1,0.8-4.5,0
|
||||
L1.3,49.6c-0.9-0.5-1.1-1.6-0.6-2.4c0.2-0.3,0.4-0.5,0.6-0.6l23-13.4l7.9,13.6c0.5,0.8,1.5,1.1,2.4,0.7l0.1,0l0.1,0
|
||||
c0.6-0.4,0.9-1.2,0.7-2l-5-15.7l2.5-1.5C33.3,27.8,33.8,27.8,34.2,28z M36,58.6c-1.4-0.8-3.9-0.7-5.5,0.3l-3,1.7l7,4.1l2-1.2
|
||||
l-2-1.1l1-0.6C37.1,60.9,37.3,59.4,36,58.6z M32.1,59.9c0.6-0.3,1.4-0.4,1.8-0.1c0.5,0.3,0.4,0.7-0.2,1.1l-1,0.6l-1.7-1L32.1,59.9
|
||||
z M36.2,55.6l-2,1.2l7,4.1l2-1.2L36.2,55.6z M42.6,51.9l-2,1.2l2.9,1.7l-4.5-0.8L37,55.1l7,4.1l2-1.2L43,56.3l4.5,0.8l2.1-1.2
|
||||
L42.6,51.9z M56.3,43.8l-6,3.5l2.5,1.4l-3.7-0.7L47,49.3l2.9,1.7l-4.5-0.8l-2.1,1.2l7,4.1l2-1.2l-2.9-1.7l4.5,0.8l2.1-1.2
|
||||
l-2.9-1.7l4,0.7l0.2,0.1l2-1.2l4-2.3l-1.7-1l-4,2.3l-1-0.6l4-2.3l-1.7-1l-4,2.3L54,47.1l4-2.3L56.3,43.8z"/>
|
||||
<path class="st2" d="M41.7,0c0.1,0,0.2,0,0.3,0c1,0.2,1.6,1.1,1.5,2.1l-2.3,13.5c3.9,2.5,6.5,6.9,6.5,11.9v0.7l-10.3,0l-2,17.9
|
||||
c-0.1,0.8-0.7,1.4-1.5,1.5l-0.1,0c-1,0.1-1.9-0.6-2-1.5l-2-17.9H19.6v-0.7c0-5,2.6-9.4,6.5-11.9L23.8,2.1c0-0.1,0-0.2,0-0.3
|
||||
c0-1,0.8-1.8,1.8-1.8H41.7z"/>
|
||||
</g>
|
||||
</g>
|
||||
<path class="st1" d="M277.4,61c-3.7,0-7.1-0.8-10-2.4c-2.8-1.6-5.1-3.9-6.7-6.8c-1.6-2.9-2.4-6.4-2.4-10.3v-0.9
|
||||
c0-4,0.8-7.4,2.4-10.3c1.6-2.9,3.8-5.2,6.6-6.8c2.8-1.6,6.1-2.4,9.9-2.4c3.7,0,6.9,0.8,9.7,2.5c2.7,1.6,4.9,3.9,6.4,6.8
|
||||
c1.5,2.9,2.3,6.3,2.3,10.1v3.3h-27.4c0.1,2.6,1.1,4.7,2.9,6.3c1.8,1.6,4.1,2.4,6.7,2.4c2.7,0,4.7-0.6,5.9-1.7
|
||||
c1.3-1.2,2.2-2.5,2.9-3.9l7.8,4.1c-0.7,1.3-1.7,2.8-3.1,4.3c-1.3,1.5-3.1,2.8-5.3,4C283.6,60.5,280.8,61,277.4,61z M268.2,36.8h17.6
|
||||
c-0.2-2.2-1.1-3.9-2.7-5.2c-1.5-1.3-3.5-2-6-2c-2.6,0-4.6,0.7-6.2,2C269.5,32.9,268.5,34.6,268.2,36.8z"/>
|
||||
<path class="st1" d="M192.9,60V6.8h18.6l9.2,46.4h1.4l9.2-46.4h18.6V60h-9.7V14.1h-1.4L229.6,60h-16.6L204,14.1h-1.4V60H192.9z"/>
|
||||
<path class="st1" d="M146.3,60V22.3h9.4v4.9h1.4c0.6-1.3,1.7-2.6,3.4-3.7c1.7-1.2,4.2-1.8,7.6-1.8c2.9,0,5.5,0.7,7.7,2.1
|
||||
c2.2,1.3,4,3.2,5.2,5.5c1.2,2.3,1.8,5.1,1.8,8.2V60h-9.6V38.2c0-2.8-0.7-5-2.1-6.4c-1.4-1.4-3.3-2.1-5.9-2.1c-2.9,0-5.2,1-6.8,3
|
||||
c-1.6,1.9-2.4,4.6-2.4,8.1V60H146.3z"/>
|
||||
<path class="st1" d="M126.1,60V22.3h9.6V60H126.1z M130.9,17.9c-1.7,0-3.2-0.6-4.4-1.7c-1.2-1.1-1.7-2.6-1.7-4.4
|
||||
c0-1.8,0.6-3.3,1.7-4.4c1.2-1.1,2.7-1.7,4.4-1.7c1.8,0,3.2,0.6,4.4,1.7c1.2,1.1,1.7,2.6,1.7,4.4c0,1.8-0.6,3.3-1.7,4.4
|
||||
C134.2,17.3,132.7,17.9,130.9,17.9z"/>
|
||||
<path class="st1" d="M79.9,60V6.8h21.9c3.3,0,6.3,0.7,8.8,2.1c2.6,1.3,4.6,3.2,6,5.6c1.5,2.4,2.2,5.3,2.2,8.7v1.1
|
||||
c0,3.3-0.8,6.2-2.3,8.7c-1.5,2.4-3.5,4.3-6.1,5.7c-2.5,1.3-5.4,2-8.7,2H89.9V60H79.9z M89.9,31.4h10.9c2.4,0,4.3-0.7,5.8-2
|
||||
c1.5-1.3,2.2-3.1,2.2-5.4v-0.8c0-2.3-0.7-4.1-2.2-5.4c-1.5-1.3-3.4-2-5.8-2H89.9V31.4z"/>
|
||||
<path class="st2" d="M285.3,112V91h13.5v3.6h-9.5v5h8.7v3.6h-8.7v5.2h9.7v3.6H285.3z"/>
|
||||
<path class="st2" d="M268.7,112V91h13.5v3.6h-9.5v5h8.7v3.6h-8.7v5.2h9.7v3.6H268.7z"/>
|
||||
<path class="st2" d="M249.7,112V91h9.1c1.3,0,2.5,0.2,3.4,0.7c1,0.5,1.7,1.1,2.3,1.9c0.5,0.8,0.8,1.8,0.8,3v0.4
|
||||
c0,1.3-0.3,2.3-0.9,3.1c-0.6,0.8-1.3,1.4-2.2,1.7v0.5c0.8,0,1.4,0.3,1.9,0.8c0.4,0.5,0.7,1.2,0.7,2v6.9h-4v-6.3
|
||||
c0-0.5-0.1-0.9-0.4-1.2c-0.2-0.3-0.6-0.4-1.2-0.4h-5.5v7.9H249.7z M253.7,100.4h4.7c0.9,0,1.7-0.2,2.2-0.8c0.5-0.5,0.8-1.2,0.8-2
|
||||
v-0.3c0-0.8-0.3-1.5-0.8-2c-0.5-0.5-1.3-0.8-2.2-0.8h-4.7V100.4z"/>
|
||||
<path class="st2" d="M233.7,112V91h13.2v3.6h-9.2v5.1h8.5v3.6h-8.5v8.7H233.7z"/>
|
||||
<path class="st1" d="M214.3,112V97.1h3.7v1.7h0.5c0.2-0.6,0.6-1,1.1-1.3c0.5-0.3,1.1-0.4,1.8-0.4h1.8v3.4h-1.9c-1,0-1.8,0.3-2.4,0.8
|
||||
c-0.6,0.5-0.9,1.3-0.9,2.3v8.5H214.3z"/>
|
||||
<path class="st1" d="M203,112.4c-1.5,0-2.8-0.3-4-0.9c-1.2-0.6-2.1-1.5-2.8-2.6c-0.7-1.1-1-2.5-1-4.1v-0.5c0-1.6,0.3-3,1-4.1
|
||||
c0.7-1.1,1.6-2,2.8-2.6c1.2-0.6,2.5-0.9,4-0.9c1.5,0,2.8,0.3,4,0.9c1.2,0.6,2.1,1.5,2.8,2.6c0.7,1.1,1,2.5,1,4.1v0.5
|
||||
c0,1.6-0.3,3-1,4.1c-0.7,1.1-1.6,2-2.8,2.6C205.8,112.1,204.5,112.4,203,112.4z M203,109c1.2,0,2.1-0.4,2.9-1.1
|
||||
c0.8-0.8,1.1-1.8,1.1-3.2v-0.3c0-1.4-0.4-2.5-1.1-3.2c-0.7-0.8-1.7-1.1-2.9-1.1c-1.2,0-2.1,0.4-2.9,1.1c-0.8,0.7-1.1,1.8-1.1,3.2
|
||||
v0.3c0,1.4,0.4,2.5,1.1,3.2C200.9,108.7,201.8,109,203,109z"/>
|
||||
<path class="st1" d="M185.8,112v-11.8H182v-3.1h3.8v-2.8c0-1,0.3-1.8,0.9-2.4c0.6-0.6,1.4-0.9,2.4-0.9h3.9v3.1h-2.6
|
||||
c-0.6,0-0.8,0.3-0.8,0.9v2.1h3.9v3.1h-3.9V112H185.8z"/>
|
||||
<path class="st1" d="M155.9,104.6v-0.5c0-1.6,0.3-2.9,0.9-4c0.6-1.1,1.4-2,2.5-2.5c1-0.6,2.2-0.9,3.4-0.9c1.4,0,2.4,0.2,3.1,0.7
|
||||
c0.7,0.5,1.2,1,1.5,1.5h0.5v-1.8h3.7v17.5c0,1-0.3,1.8-0.9,2.4c-0.6,0.6-1.4,0.9-2.4,0.9h-10v-3.3h8.6c0.6,0,0.8-0.3,0.8-0.9v-3.9
|
||||
h-0.5c-0.2,0.3-0.5,0.7-0.8,1c-0.4,0.3-0.8,0.6-1.4,0.8c-0.6,0.2-1.4,0.3-2.3,0.3c-1.2,0-2.3-0.3-3.4-0.9c-1-0.6-1.8-1.4-2.5-2.6
|
||||
C156.2,107.5,155.9,106.1,155.9,104.6z M163.7,108.7c1.2,0,2.1-0.4,2.9-1.1s1.2-1.8,1.2-3.1v-0.3c0-1.4-0.4-2.4-1.2-3.1
|
||||
c-0.8-0.7-1.7-1.1-2.9-1.1c-1.2,0-2.1,0.4-2.9,1.1c-0.8,0.7-1.2,1.8-1.2,3.1v0.3c0,1.3,0.4,2.4,1.2,3.1S162.6,108.7,163.7,108.7z"/>
|
||||
<path class="st1" d="M145.3,112.4c-1.5,0-2.8-0.3-4-0.9c-1.2-0.6-2.1-1.5-2.8-2.6s-1-2.5-1-4.1v-0.5c0-1.6,0.3-3,1-4.1
|
||||
c0.7-1.1,1.6-2,2.8-2.6c1.2-0.6,2.5-0.9,4-0.9s2.8,0.3,4,0.9c1.2,0.6,2.1,1.5,2.8,2.6c0.7,1.1,1,2.5,1,4.1v0.5c0,1.6-0.3,3-1,4.1
|
||||
c-0.7,1.1-1.6,2-2.8,2.6C148.1,112.1,146.8,112.4,145.3,112.4z M145.3,109c1.2,0,2.1-0.4,2.9-1.1c0.8-0.8,1.1-1.8,1.1-3.2v-0.3
|
||||
c0-1.4-0.4-2.5-1.1-3.2c-0.7-0.8-1.7-1.1-2.9-1.1c-1.2,0-2.1,0.4-2.9,1.1c-0.8,0.7-1.1,1.8-1.1,3.2v0.3c0,1.4,0.4,2.5,1.1,3.2
|
||||
C143.2,108.7,144.1,109,145.3,109z"/>
|
||||
<path class="st1" d="M130.3,112V91h3.8v21H130.3z"/>
|
||||
<path class="st1" d="M109.6,112v-3.5h2.8v-14h-2.8V91h10.8c1.3,0,2.4,0.2,3.3,0.7c1,0.4,1.7,1,2.2,1.8c0.5,0.8,0.8,1.7,0.8,2.8v0.3
|
||||
c0,1-0.2,1.8-0.5,2.4c-0.4,0.6-0.8,1.1-1.3,1.4c-0.5,0.3-0.9,0.6-1.4,0.7v0.5c0.4,0.1,0.9,0.3,1.4,0.7c0.5,0.3,1,0.8,1.3,1.4
|
||||
c0.4,0.6,0.6,1.4,0.6,2.4v0.3c0,1.2-0.3,2.2-0.8,3c-0.5,0.8-1.3,1.4-2.2,1.9c-0.9,0.4-2,0.7-3.3,0.7H109.6z M116.3,108.4h3.7
|
||||
c0.9,0,1.6-0.2,2.1-0.6c0.5-0.4,0.8-1,0.8-1.8v-0.3c0-0.8-0.3-1.4-0.8-1.8c-0.5-0.4-1.2-0.6-2.1-0.6h-3.7V108.4z M116.3,99.6h3.7
|
||||
c0.8,0,1.5-0.2,2-0.6c0.5-0.4,0.8-1,0.8-1.7v-0.3c0-0.8-0.3-1.3-0.8-1.7c-0.5-0.4-1.2-0.6-2-0.6h-3.7V99.6z"/>
|
||||
<path class="st1" d="M85.9,118v-3.3H94c0.6,0,0.8-0.3,0.8-0.9V110h-0.5c-0.2,0.3-0.4,0.7-0.8,1c-0.3,0.3-0.8,0.6-1.4,0.8
|
||||
c-0.6,0.2-1.3,0.3-2.2,0.3c-1.2,0-2.2-0.3-3.1-0.8c-0.9-0.5-1.5-1.3-2-2.2c-0.5-0.9-0.7-2-0.7-3.2v-8.9h3.8v8.6c0,1.1,0.3,2,0.8,2.5
|
||||
c0.6,0.6,1.4,0.8,2.4,0.8c1.2,0,2.1-0.4,2.7-1.1c0.6-0.8,1-1.9,1-3.2v-7.6h3.8v17.5c0,1-0.3,1.8-0.9,2.4c-0.6,0.6-1.4,0.9-2.4,0.9
|
||||
H85.9z"/>
|
||||
<path class="st1" d="M72.9,112.4c-1.5,0-2.8-0.3-4-0.9s-2.1-1.5-2.8-2.6s-1-2.5-1-4.1v-0.5c0-1.6,0.3-3,1-4.1c0.7-1.1,1.6-2,2.8-2.6
|
||||
s2.5-0.9,4-0.9c1.5,0,2.8,0.3,4,0.9s2.1,1.5,2.8,2.6c0.7,1.1,1,2.5,1,4.1v0.5c0,1.6-0.3,3-1,4.1s-1.6,2-2.8,2.6
|
||||
S74.4,112.4,72.9,112.4z M72.9,109c1.2,0,2.1-0.4,2.9-1.1c0.8-0.8,1.1-1.8,1.1-3.2v-0.3c0-1.4-0.4-2.5-1.1-3.2
|
||||
c-0.7-0.8-1.7-1.1-2.9-1.1c-1.2,0-2.1,0.4-2.9,1.1c-0.8,0.7-1.1,1.8-1.1,3.2v0.3c0,1.4,0.4,2.5,1.1,3.2
|
||||
C70.8,108.7,71.8,109,72.9,109z"/>
|
||||
<path class="st1" d="M57.9,112V91h3.8v21H57.9z"/>
|
||||
<path class="st1" d="M38.8,118V97.1h3.7v1.8H43c0.3-0.6,0.9-1.1,1.6-1.5c0.7-0.5,1.8-0.7,3.1-0.7c1.2,0,2.3,0.3,3.3,0.9
|
||||
c1,0.6,1.8,1.4,2.5,2.6c0.6,1.1,0.9,2.5,0.9,4.1v0.5c0,1.6-0.3,3-0.9,4.1c-0.6,1.1-1.4,2-2.5,2.6c-1,0.6-2.1,0.9-3.3,0.9
|
||||
c-0.9,0-1.7-0.1-2.3-0.3c-0.6-0.2-1.1-0.5-1.5-0.8c-0.4-0.3-0.7-0.7-0.9-1h-0.5v7.7H38.8z M46.6,109.1c1.2,0,2.1-0.4,2.9-1.1
|
||||
c0.8-0.8,1.2-1.9,1.2-3.3v-0.3c0-1.4-0.4-2.5-1.2-3.3c-0.8-0.8-1.8-1.1-2.9-1.1s-2.1,0.4-2.9,1.1c-0.8,0.7-1.2,1.8-1.2,3.3v0.3
|
||||
c0,1.4,0.4,2.5,1.2,3.3C44.4,108.7,45.4,109.1,46.6,109.1z"/>
|
||||
<path class="st1" d="M28.2,112.4c-1.5,0-2.8-0.3-3.9-0.9c-1.1-0.6-2-1.5-2.6-2.7c-0.6-1.2-0.9-2.5-0.9-4.1v-0.4
|
||||
c0-1.6,0.3-2.9,0.9-4.1c0.6-1.2,1.5-2,2.6-2.7c1.1-0.6,2.4-1,3.9-1c1.5,0,2.7,0.3,3.8,1c1.1,0.6,1.9,1.5,2.5,2.7
|
||||
c0.6,1.1,0.9,2.5,0.9,4v1.3H24.6c0,1,0.4,1.8,1.1,2.5c0.7,0.6,1.6,1,2.6,1c1.1,0,1.8-0.2,2.3-0.7s0.9-1,1.1-1.5l3.1,1.6
|
||||
c-0.3,0.5-0.7,1.1-1.2,1.7c-0.5,0.6-1.2,1.1-2.1,1.6C30.7,112.2,29.6,112.4,28.2,112.4z M24.6,102.8h7c-0.1-0.9-0.4-1.6-1-2.1
|
||||
c-0.6-0.5-1.4-0.8-2.4-0.8c-1,0-1.8,0.3-2.4,0.8C25.1,101.3,24.7,102,24.6,102.8z"/>
|
||||
<path class="st1" d="M0.8,112v-3.5h2.8v-14H0.8V91h8.6c2.8,0,5,0.7,6.4,2.2c1.5,1.4,2.2,3.5,2.2,6.4v4c0,2.8-0.7,4.9-2.2,6.4
|
||||
c-1.5,1.4-3.6,2.1-6.4,2.1H0.8z M7.5,108.4h2c1.6,0,2.8-0.4,3.5-1.3c0.7-0.8,1.1-2,1.1-3.5v-4.2c0-1.5-0.4-2.7-1.1-3.5
|
||||
c-0.7-0.8-1.9-1.3-3.5-1.3h-2V108.4z"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 8.8 KiB |
@@ -8,6 +8,7 @@ params
|
||||
```go-html-template
|
||||
{{ $js := resources.Get "js/main.js" | js.Build (dict "params" (dict "api" "https://example.org/api")) }}
|
||||
```
|
||||
|
||||
And then in your JS file:
|
||||
|
||||
```js
|
||||
@@ -21,10 +22,10 @@ minify
|
||||
|
||||
loaders
|
||||
: {{< new-in 0.140.0 />}}
|
||||
: (`map`) Configuring a loader for a given file type lets you load that file type with an `import` statement or a `require` call. For example, configuring the `.png` file extension to use the data URL loader means importing a `.png` file gives you a data URL containing the contents of that image. Loaders available are `none`, `base64`, `binary`, `copy`, `css`, `dataurl`, `default`, `empty`, `file`, `global-css`, `js`, `json`, `jsx`, `local-css`, `text`, `ts`, `tsx`. See https://esbuild.github.io/api/#loader.
|
||||
: (`map`) Configuring a loader for a given file type lets you load that file type with an `import` statement or a `require` call. For example, configuring the `.png` file extension to use the data URL loader means importing a `.png` file gives you a data URL containing the contents of that image. Loaders available are `none`, `base64`, `binary`, `copy`, `css`, `dataurl`, `default`, `empty`, `file`, `global-css`, `js`, `json`, `jsx`, `local-css`, `text`, `ts`, `tsx`. See <https://esbuild.github.io/api/#loader>.
|
||||
|
||||
inject
|
||||
: (`slice`) This option allows you to automatically replace a global variable with an import from another file. The path names must be relative to `assets`. See https://esbuild.github.io/api/#inject.
|
||||
: (`slice`) This option allows you to automatically replace a global variable with an import from another file. The path names must be relative to `assets`. See <https://esbuild.github.io/api/#inject>.
|
||||
|
||||
shims
|
||||
: (`map`) This option allows swapping out a component with another. A common use case is to load dependencies like React from a CDN (with _shims_) when in production, but running with the full bundled `node_modules` dependency during development:
|
||||
@@ -58,10 +59,10 @@ target
|
||||
|
||||
platform
|
||||
: {{< new-in 0.140.0 />}}
|
||||
: (`string`) One of `browser`, `node`, `neutral`. Default is `browser`. See https://esbuild.github.io/api/#platform.
|
||||
: (`string`) One of `browser`, `node`, `neutral`. Default is `browser`. See <https://esbuild.github.io/api/#platform>.
|
||||
|
||||
externals
|
||||
: (`slice`) External dependencies. Use this to trim dependencies you know will never be executed. See https://esbuild.github.io/api/#external.
|
||||
: (`slice`) External dependencies. Use this to trim dependencies you know will never be executed. See <https://esbuild.github.io/api/#external>.
|
||||
|
||||
defines
|
||||
: (`map`) This option allows you to define a set of string replacements to be performed when building. It must be a map where each key will be replaced by its value.
|
||||
@@ -73,7 +74,7 @@ defines
|
||||
drop
|
||||
: {{< new-in 0.144.0 />}}
|
||||
: (`string`) Edit your source code before building to drop certain constructs: One of `debugger` or `console`.
|
||||
: See https://esbuild.github.io/api/#drop
|
||||
: See <https://esbuild.github.io/api/#drop>
|
||||
|
||||
sourceMap
|
||||
: (`string`) Whether to generate `inline`, `linked`, or `external` source maps from esbuild. Linked and external source maps will be written to the target with the output file name + ".map". When `linked` a `sourceMappingURL` will also be written to the output file. By default, source maps are not created. Note that the `linked` option was added in Hugo 0.140.0.
|
||||
@@ -84,11 +85,11 @@ sourcesContent
|
||||
|
||||
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.
|
||||
: (`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.
|
||||
: (`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.:
|
||||
|
||||
|
||||
@@ -6,6 +6,7 @@ _comment: Do not remove front matter.
|
||||
> You need [Go] version 1.18 or later and [Git] to use Hugo Modules. For older sites hosted on Netlify, please ensure the `GO_VERSION` environment variable is set to `1.18` or higher.
|
||||
>
|
||||
> Go Modules resources:
|
||||
>
|
||||
> - [go.dev/wiki/Modules](https://go.dev/wiki/Modules)
|
||||
> - [blog.golang.org/using-go-modules](https://go.dev/blog/using-go-modules)
|
||||
|
||||
|
||||
@@ -15,9 +15,3 @@ Prebuilt binaries are available for a variety of operating systems and architect
|
||||
Please consult your operating system documentation if you need help setting file permissions or modifying your PATH environment variable.
|
||||
|
||||
If you do not see a prebuilt binary for the desired edition, operating system, and architecture, install Hugo using one of the methods described below.
|
||||
|
||||
[commit information]: /methods/page/gitinfo/
|
||||
[Git]: https://git-scm.com/
|
||||
[Go]: https://go.dev/
|
||||
[Hugo Modules]: /hugo-modules/
|
||||
[latest release]: https://github.com/gohugoio/hugo/releases/latest
|
||||
|
||||
@@ -32,13 +32,13 @@ content/
|
||||
|
||||
And these templates:
|
||||
|
||||
```go-html-template {file="layouts/_default/list.html"}
|
||||
```go-html-template {file="layouts/section.html"}
|
||||
{{ range .Pages.ByWeight }}
|
||||
<h2><a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a></h2>
|
||||
{{ end }}
|
||||
```
|
||||
|
||||
```go-html-template {file="layouts/_default/single.html"}
|
||||
```go-html-template {file="layouts/page.html"}
|
||||
{{ with .Prev }}
|
||||
<a href="{{ .RelPermalink }}">Previous</a>
|
||||
{{ end }}
|
||||
|
||||
@@ -32,13 +32,13 @@ content/
|
||||
|
||||
And these templates:
|
||||
|
||||
```go-html-template {file="layouts/_default/list.html"}
|
||||
```go-html-template {file="layouts/section.html"}
|
||||
{{ range .Pages.ByWeight }}
|
||||
<h2><a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a></h2>
|
||||
{{ end }}
|
||||
```
|
||||
|
||||
```go-html-template {file="layouts/_default/single.html"}
|
||||
```go-html-template {file="layouts/page.html"}
|
||||
{{ with .PrevInSection }}
|
||||
<a href="{{ .RelPermalink }}">Previous</a>
|
||||
{{ end }}
|
||||
|
||||
@@ -32,13 +32,13 @@ content/
|
||||
|
||||
And these templates:
|
||||
|
||||
```go-html-template {file="layouts/_default/list.html"}
|
||||
```go-html-template {file="layouts/section.html"}
|
||||
{{ range .Pages.ByWeight }}
|
||||
<h2><a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a></h2>
|
||||
{{ end }}
|
||||
```
|
||||
|
||||
```go-html-template {file="layouts/_default/single.html"}
|
||||
```go-html-template {file="layouts/page.html"}
|
||||
{{ $pages := .CurrentSection.Pages.ByWeight }}
|
||||
|
||||
{{ with $pages.Prev . }}
|
||||
@@ -57,7 +57,7 @@ When you visit page-2:
|
||||
|
||||
To reverse the meaning of _next_ and _previous_ you can chain the [`Reverse`] method to the page collection definition:
|
||||
|
||||
```go-html-template {file="layouts/_default/single.html"}
|
||||
```go-html-template {file="layouts/page.html"}
|
||||
{{ $pages := .CurrentSection.Pages.ByWeight.Reverse }}
|
||||
|
||||
{{ with $pages.Prev . }}
|
||||
|
||||
@@ -32,9 +32,9 @@ To capture the "genres" `Taxonomy` object from within any template, use the [`Ta
|
||||
{{ $taxonomyObject := .Site.Taxonomies.genres }}
|
||||
```
|
||||
|
||||
To capture the "genres" `Taxonomy` object when rendering its page with a taxonomy template, use the [`Terms`] method on the page's [`Data`] object:
|
||||
To capture the "genres" `Taxonomy` object when rendering its page with a _taxonomy_ template, use the [`Terms`] method on the page's [`Data`] object:
|
||||
|
||||
```go-html-template {file="layouts/_default/taxonomy.html"}
|
||||
```go-html-template {file="layouts/taxonomy.html"}
|
||||
{{ $taxonomyObject := .Data.Terms }}
|
||||
```
|
||||
|
||||
|
||||
@@ -26,9 +26,15 @@ _comment: Do not remove front matter.
|
||||
`:section`
|
||||
: The content's section.
|
||||
|
||||
`:sectionslug`
|
||||
: The content's section using slugified section name. The slugified section name is the `slug` as defined in front matter, else the `title` as defined in front matter, else the automatic title.
|
||||
|
||||
`:sections`
|
||||
: The content's sections hierarchy. You can use a selection of the sections using _slice syntax_: `:sections[1:]` includes all but the first, `:sections[:last]` includes all but the last, `:sections[last]` includes only the last, `:sections[1:2]` includes section 2 and 3. Note that this slice access will not throw any out-of-bounds errors, so you don't have to be exact.
|
||||
|
||||
`:sectionslugs`
|
||||
: The content's sections hierarchy using slugified section names. The slugified section name is the `slug` as defined in front matter, else the `title` as defined in front matter, else the automatic title. You can use a selection of the sections using _slice syntax_: `:sectionslugs[1:]` includes all but the first, `:sectionslugs[:last]` includes all but the last, `:sectionslugs[last]` includes only the last, `:sectionslugs[1:2]` includes section 2 and 3. Note that this slice access will not throw any out-of-bounds errors, so you don't have to be exact.
|
||||
|
||||
`:title`
|
||||
: The `title` as defined in front matter, else the automatic title. Hugo generates titles automatically for section, taxonomy, and term pages that are not backed by a file.
|
||||
|
||||
@@ -67,5 +73,3 @@ For time-related values, you can also use the layout string components defined i
|
||||
permalinks:
|
||||
posts: /:06/:1/:2/:title/
|
||||
{{< /code-toggle >}}
|
||||
|
||||
[content base name]: /methods/page/file/#contentbasename
|
||||
|
||||
@@ -8,7 +8,7 @@ _comment: Do not remove front matter.
|
||||
|
||||
The primary use case for `PageInner` is to resolve links and [page resources](g) relative to an included `Page`. For example, create an "include" shortcode to compose a page from multiple content files, while preserving a global context for footnotes and the table of contents:
|
||||
|
||||
```go-html-template {file="layouts/shortcodes/include.html" copy=true}
|
||||
```go-html-template {file="layouts/_shortcodes/include.html" copy=true}
|
||||
{{ with .Get 0 }}
|
||||
{{ with $.Page.GetPage . }}
|
||||
{{- .RenderShortcodes }}
|
||||
@@ -22,14 +22,14 @@ The primary use case for `PageInner` is to resolve links and [page resources](g)
|
||||
|
||||
Then call the shortcode in your Markdown:
|
||||
|
||||
```text {file="content/posts/p1.md"}
|
||||
{{%/* include "/posts/p2" */%}}
|
||||
```text {file="content/posts/post-1.md"}
|
||||
{{%/* include "/posts/post-2" */%}}
|
||||
```
|
||||
|
||||
Any render hook triggered while rendering `/posts/p2` will get:
|
||||
Any render hook triggered while rendering `/posts/post-2` will get:
|
||||
|
||||
- `/posts/p1` when calling `Page`
|
||||
- `/posts/p2` when calling `PageInner`
|
||||
- `/posts/post-1` when calling `Page`
|
||||
- `/posts/post-2` when calling `PageInner`
|
||||
|
||||
`PageInner` falls back to the value of `Page` if not relevant, and always returns a value.
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@ The method or function used to create a scratch pad determines its scope. For ex
|
||||
Scope|Method or function
|
||||
:--|:--
|
||||
page|[`PAGE.Store`]
|
||||
site|[`SITE.Store`]
|
||||
site|[`SITE.Store`]
|
||||
global|[`hugo.Store`]
|
||||
local|[`collections.NewScratch`]
|
||||
shortcode|[`SHORTCODE.Store`]
|
||||
|
||||
@@ -28,6 +28,7 @@ lineNoStart
|
||||
|
||||
lineNos
|
||||
: (`any`) Controls line number display. Default is `false`.
|
||||
|
||||
- `true`: Enable line numbers, controlled by `lineNumbersInTable`.
|
||||
- `false`: Disable line numbers.
|
||||
- `inline`: Enable inline line numbers (sets `lineNumbersInTable` to `false`).
|
||||
|
||||
@@ -92,7 +92,7 @@ weight: 20
|
||||
## Performance
|
||||
|
||||
[Caching]
|
||||
: Reduce build time and cost by rendering a partial template once then cache the result, either globally or within a given context. For example, cache the result of an asset pipeline to prevent reprocessing on every rendered page.
|
||||
: Reduce build time and cost by rendering a _partial_ template once then cache the result, either globally or within a given context. For example, cache the result of an asset pipeline to prevent reprocessing on every rendered page.
|
||||
|
||||
[Segmentation]
|
||||
: Reduce build time and cost by partitioning your sites into segments. For example, render the home page and the "news section" every hour, and render the entire site once a week.
|
||||
|
||||
@@ -84,7 +84,7 @@ disableKinds
|
||||
: (`[]string`) A slice of page [kinds](g) to disable during the build process, any of `404`, `home`, `page`, `robotstxt`, `rss`, `section`, `sitemap`, `taxonomy`, or `term`.
|
||||
|
||||
disableLanguages
|
||||
: (`[]string]`) A slice of language keys representing the languages to disable during the build process. Although this is functional, consider using the [`disabled`] key under each language instead.
|
||||
: (`[]string`) A slice of language keys representing the languages to disable during the build process. Although this is functional, consider using the [`disabled`] key under each language instead.
|
||||
|
||||
disableLiveReload
|
||||
: (`bool`) Whether to disable automatic live reloading of the browser window. Default is `false`.
|
||||
@@ -123,7 +123,7 @@ ignoreCache
|
||||
: (`bool`) Whether to ignore the cache directory. Default is `false`.
|
||||
|
||||
ignoreFiles
|
||||
: (`[]string]`) A slice of [regular expressions](g) used to exclude specific files from a build. These expressions are matched against the absolute file path and apply to files within the `content`, `data`, and `i18n` directories. For more advanced file exclusion options, see the section on [module mounts].
|
||||
: (`[]string`) A slice of [regular expressions](g) used to exclude specific files from a build. These expressions are matched against the absolute file path and apply to files within the `content`, `data`, and `i18n` directories. For more advanced file exclusion options, see the section on [module mounts].
|
||||
|
||||
ignoreLogs
|
||||
: (`[]string`) A slice of message identifiers corresponding to warnings and errors you wish to suppress. See [`erroridf`] and [`warnidf`].
|
||||
@@ -280,7 +280,7 @@ themesDir
|
||||
: (`string`) The designated directory for themes. Default is `themes`.
|
||||
|
||||
timeout
|
||||
: (`string`) The timeout for generating page content, either as a [duration] or in seconds. This timeout is used to prevent infinite recursion during content generation. You may need to increase this value if your pages take a long time to generate, for example, due to extensive image processing or reliance on remote content. Default is `30s`.
|
||||
: (`string`) The timeout for generating page content, either as a [duration] or in seconds. This timeout is used to prevent infinite recursion during content generation. You may need to increase this value if your pages take a long time to generate, for example, due to extensive image processing or reliance on remote content. Default is `60s`.
|
||||
|
||||
timeZone
|
||||
: (`string`) The time zone used to parse dates without time zone offsets, including front matter date fields and values passed to the [`time.AsTime`] and [`time.Format`] template functions. The list of valid values may be system dependent, but should include `UTC`, `Local`, and any location in the [IANA Time Zone Database]. For example, `America/Los_Angeles` and `Europe/Oslo` are valid time zones.
|
||||
@@ -339,7 +339,6 @@ Some configuration settings, such as menus and custom parameters, can be defined
|
||||
[`MainSections`]: /methods/site/mainsections/
|
||||
[`segments`]: /configuration/segments/
|
||||
[`strings.Title`]: /functions/strings/title/
|
||||
[`strings.Title`]: /functions/strings/title
|
||||
[`Summary`]: /methods/page/summary/
|
||||
[`time.AsTime`]: /functions/time/astime/
|
||||
[`time.Format`]: /functions/time/format/
|
||||
|
||||
@@ -27,6 +27,7 @@ useResourceCacheWhen
|
||||
|
||||
The `build.cachebusters` configuration option was added to support development using Tailwind 3.x's JIT compiler where a `build` configuration may look like this:
|
||||
|
||||
<!-- markdownlint-disable MD049 -->
|
||||
{{< code-toggle file=hugo >}}
|
||||
[build]
|
||||
[build.buildStats]
|
||||
@@ -44,6 +45,7 @@ The `build.cachebusters` configuration option was added to support development u
|
||||
source = "assets/.*\\.(.*)$"
|
||||
target = "$1"
|
||||
{{< /code-toggle >}}
|
||||
<!-- markdownlint-enable MD049 -->
|
||||
|
||||
When `buildStats` is enabled, Hugo writes a `hugo_stats.json` file on each build with HTML classes etc. that's used in the rendered output. Changes to this file will trigger a rebuild of the `styles.css` file. You also need to add `hugo_stats.json` to Hugo's server watcher. See [Hugo Starter Tailwind Basic](https://github.com/bep/hugo-starter-tailwind-basic) for a running example.
|
||||
|
||||
|
||||
@@ -44,7 +44,7 @@ environment
|
||||
: (`string`) A [glob](g) pattern matching the build [environment](g). For example: `{staging,production}`.
|
||||
|
||||
kind
|
||||
: (`string`) A [glob](g) pattern matching the [page kind](g). For example: ` {taxonomy,term}`.
|
||||
: (`string`) A [glob](g) pattern matching the [page kind](g). For example: `{taxonomy,term}`.
|
||||
|
||||
lang
|
||||
: (`string`) A [glob](g) pattern matching the [page language]. For example: `{en,de}`.
|
||||
|
||||
@@ -60,25 +60,32 @@ The default front matter configuration includes these aliases.
|
||||
|
||||
## Tokens
|
||||
|
||||
Hugo provides several [tokens](g) to assist with front matter configuration.
|
||||
Hugo provides the following [tokens](g) to help you configure your front matter:
|
||||
|
||||
Token|Description
|
||||
:--|:--
|
||||
`:default`|The default ordered sequence of date fields.
|
||||
`:fileModTime`|The file's last modification timestamp.
|
||||
`:filename`|The date from the file name, if present.
|
||||
`:git`|The Git author date for the file's last revision.
|
||||
`:default`
|
||||
: The default ordered sequence of date fields.
|
||||
|
||||
When Hugo extracts a date from a file name, it uses the rest of the file name to generate the page's [`slug`], but only if a slug isn't already specified in the page's front matter. For example, given the name `2025-02-01-article.md`, Hugo will set the `date` to `2025-02-01` and the `slug` to `article`.
|
||||
`:fileModTime`
|
||||
: The file's last modification timestamp.
|
||||
|
||||
[`slug`]: /content-management/front-matter/#slug
|
||||
`:filename`
|
||||
: Extracts the date from the file name, provided the file name begins with a date in one of the following formats:
|
||||
|
||||
To enable access to the Git author date, set [`enableGitInfo`] to `true`, or use\
|
||||
the `--enableGitInfo` flag when building your site.
|
||||
- `YYYY-MM-DD`
|
||||
- `YYYY-MM-DD-HH-MM-SS` {{< new-in 0.148.0 />}}
|
||||
|
||||
[`enableGitInfo`]: /configuration/all/#enablegitinfo
|
||||
Within the `YYYY-MM-DD-HH-MM-SS` format, the date and time values may be separated by any character including a space (e.g., `2025-02-01T14-30-00`).
|
||||
|
||||
Consider this example:
|
||||
Hugo resolves the extracted date to the [`timeZone`] defined in your site configuration, falling back to the system time zone. After extracting the date, Hugo uses the remaining part of the file name to generate the page's [`slug`], but only if you haven't already specified a slug in the page's front matter.
|
||||
|
||||
For example, if you name your file `2025-02-01-article.md`, Hugo will set the date to `2025-02-01` and the slug to `article`.
|
||||
|
||||
`:git`
|
||||
: The Git author date for the file's last revision. To enable access to the Git author date, set [`enableGitInfo`] to `true`, or use the `--enableGitInfo` flag when building your site.
|
||||
|
||||
## Example
|
||||
|
||||
Consider this site configuration:
|
||||
|
||||
{{< code-toggle file=hugo >}}
|
||||
[frontmatter]
|
||||
@@ -89,3 +96,7 @@ lastmod = ['lastmod', ':fileModTime']
|
||||
To determine `date`, Hugo tries to extract the date from the file name, falling back to the default ordered sequence of date fields.
|
||||
|
||||
To determine `lastmod`, Hugo looks for a `lastmod` field in front matter, falling back to the file's last modification timestamp.
|
||||
|
||||
[`enableGitInfo`]: /configuration/all/#enablegitinfo
|
||||
[`slug`]: /content-management/front-matter/#slug
|
||||
[`timeZone`]: /configuration/all/#timezone
|
||||
|
||||
@@ -79,6 +79,11 @@ my-project/
|
||||
|
||||
The root configuration keys are {{< root-configuration-keys >}}.
|
||||
|
||||
> [!note]
|
||||
> You must define `cascade` tables in the root configuration file. You cannot define `cascade` tables in a dedicated file. See issue [#12899] for details.
|
||||
|
||||
[#12899]: https://github.com/gohugoio/hugo/issues/12899
|
||||
|
||||
### Omit the root key
|
||||
|
||||
When splitting the configuration by root key, omit the root key in the component file. For example, these are equivalent:
|
||||
|
||||
@@ -47,10 +47,10 @@ Extension|Documentation|Enabled
|
||||
:--|:--|:-:
|
||||
`cjk`|[Goldmark Extensions: CJK]|:heavy_check_mark:
|
||||
`definitionList`|[PHP Markdown Extra: Definition lists]|:heavy_check_mark:
|
||||
`extras`|[Hugo Goldmark Extensions: Extras]||
|
||||
`extras`|[Hugo Goldmark Extensions: Extras]|
|
||||
`footnote`|[PHP Markdown Extra: Footnotes]|:heavy_check_mark:
|
||||
`linkify`|[GitHub Flavored Markdown: Autolinks]|:heavy_check_mark:
|
||||
`passthrough`|[Hugo Goldmark Extensions: Passthrough]||
|
||||
`passthrough`|[Hugo Goldmark Extensions: Passthrough]|
|
||||
`strikethrough`|[GitHub Flavored Markdown: Strikethrough]|:heavy_check_mark:
|
||||
`table`|[GitHub Flavored Markdown: Tables]|:heavy_check_mark:
|
||||
`taskList`|[GitHub Flavored Markdown: Task list items]|:heavy_check_mark:
|
||||
@@ -70,12 +70,19 @@ Mark text|`==baz==`|`<mark>baz</mark>`
|
||||
Subscript|`H~2~O`|`H<sub>2</sub>O`
|
||||
Superscript|`1^st^`|`1<sup>st</sup>`
|
||||
|
||||
To avoid a conflict when enabling the "subscript" feature of the Extras extension, if you want to render subscript and strikethrough text concurrently you must:
|
||||
To avoid a conflict[^1], if you enable the "subscript" feature of the Extras extension, you must disable the Strikethrough extension:
|
||||
|
||||
1. Disable the Strikethrough extension
|
||||
1. Enable the "deleted text" feature of the Extras extension
|
||||
[^1]: See [details](https://github.com/gohugoio/hugo-goldmark-extensions/commit/4d4fcd022fe45a9b51483df001c9e5f4e632d5a9).
|
||||
|
||||
For example:
|
||||
{{< code-toggle file=hugo >}}
|
||||
[markup.goldmark.extensions]
|
||||
strikethrough = false
|
||||
|
||||
[markup.goldmark.extensions.extras.subscript]
|
||||
enable = true
|
||||
{{< /code-toggle >}}
|
||||
|
||||
If you still need to show deleted text after disabling the Strikethrough extension, enable the "deleted text" feature of the Extras extension:
|
||||
|
||||
{{< code-toggle file=hugo >}}
|
||||
[markup.goldmark.extensions]
|
||||
@@ -83,11 +90,10 @@ strikethrough = false
|
||||
|
||||
[markup.goldmark.extensions.extras.delete]
|
||||
enable = true
|
||||
|
||||
[markup.goldmark.extensions.extras.subscript]
|
||||
enable = true
|
||||
{{< /code-toggle >}}
|
||||
|
||||
With this configuration, to format text as deleted, wrap it with double-tildes.
|
||||
|
||||
#### Passthrough
|
||||
|
||||
{{< new-in 0.122.0 />}}
|
||||
@@ -111,7 +117,7 @@ Markdown|Replaced by|Description
|
||||
`”`|`”`|right double quote
|
||||
`’`|`’`|right single quote
|
||||
|
||||
### Settings explained
|
||||
### Goldmark settings explained
|
||||
|
||||
Most of the Goldmark settings above are self-explanatory, but some require explanation.
|
||||
|
||||
@@ -133,13 +139,13 @@ parser.autoHeadingID
|
||||
: (`bool`) Whether to automatically add `id` attributes to headings (i.e., `h1`, `h2`, `h3`, `h4`, `h5`, and `h6` elements).
|
||||
|
||||
parser.autoIDType
|
||||
: (`string`) The strategy used to automatically generate `id` attributes, one of `github`, `github-ascii` or `blackfriday`.
|
||||
: (`string`) The strategy used to automatically generate `id` attributes, one of `github`, `github-ascii` or `blackfriday`. Default is `github`.
|
||||
|
||||
- `github` produces GitHub-compatible `id` attributes
|
||||
- `github-ascii` drops any non-ASCII characters after accent normalization
|
||||
- `blackfriday` produces `id` attributes compatible with the Blackfriday Markdown renderer
|
||||
- `github`: Generate GitHub-compatible `id` attributes
|
||||
- `github-ascii`: Drop any non-ASCII characters after accent normalization
|
||||
- `blackfriday`: Generate `id` attributes compatible with the Blackfriday Markdown renderer
|
||||
|
||||
This is also the strategy used by the [anchorize](/functions/urls/anchorize) template function. Default is `github`.
|
||||
This is also the strategy used by the [anchorize] template function.
|
||||
|
||||
parser.attribute.block
|
||||
: (`bool`) Whether to enable [Markdown attributes] for block elements. Default is `false`.
|
||||
@@ -147,19 +153,33 @@ parser.attribute.block
|
||||
parser.attribute.title
|
||||
: (`bool`) Whether to enable [Markdown attributes] for headings. Default is `true`.
|
||||
|
||||
<!-- TODO: delete this on or after July 1, 2027. -->
|
||||
renderHooks.image.enableDefault
|
||||
: {{< new-in 0.123.0 />}}
|
||||
: (`bool`) Whether to enable the [embedded image render hook]. Default is `false`.
|
||||
: Deprecated in v0.148.0. Use `renderHooks.image.useEmbedded` instead.
|
||||
|
||||
> [!note]
|
||||
> The embedded image render hook is automatically enabled for multilingual single-host sites if [duplication of shared page resources] is disabled. This is the default configuration for multilingual single-host sites.
|
||||
renderHooks.image.useEmbedded
|
||||
: {{< new-in 0.148.0 />}}
|
||||
: (`string`) When to use the [embedded image render hook]. One of `auto`, `never`, `always`, or `fallback`. Default is `auto`.
|
||||
|
||||
- `auto`: Automatically use the embedded image render hook for multilingual single-host sites, specifically when the [duplication of shared page resources] feature is disabled. This is the default behavior for such sites. If custom image render hooks are defined by your project, modules, or themes, these will be used instead.
|
||||
- `never`: Never use the embedded image render hook. If custom image render hooks are defined by your project, modules, or themes, these will be used instead.
|
||||
- `always`: Always use the embedded image render hook, even if custom image render hooks are provided by your project, modules, or themes. In this case, the embedded hook takes precedence.
|
||||
- `fallback`: Use the embedded image render hook only if custom image render hooks are not provided by your project, modules, or themes. If custom image render hooks exist, these will be used instead.
|
||||
|
||||
<!-- TODO: delete this on or after July 1, 2027. -->
|
||||
renderHooks.link.enableDefault
|
||||
: {{< new-in 0.123.0 />}}
|
||||
: (`bool`) Whether to enable the [embedded link render hook]. Default is `false`.
|
||||
: Deprecated in v0.148.0. Use `renderHooks.link.useEmbedded` instead.
|
||||
|
||||
> [!note]
|
||||
> The embedded link render hook is automatically enabled for multilingual single-host sites if [duplication of shared page resources] is disabled. This is the default configuration for multilingual single-host sites.
|
||||
renderHooks.link.useEmbedded
|
||||
: {{< new-in 0.148.0 />}}
|
||||
: (`string`) When to use the [embedded link render hook]. One of `auto`, `never`, `always`, or `fallback`. Default is `auto`.
|
||||
|
||||
- `auto`: Automatically use the embedded link render hook for multilingual single-host sites, specifically when the [duplication of shared page resources] feature is disabled. This is the default behavior for such sites. If custom link render hooks are defined by your project, modules, or themes, these will be used instead.
|
||||
- `never`: Never use the embedded link render hook. If custom link render hooks are defined by your project, modules, or themes, these will be used instead.
|
||||
- `always`: Always use the embedded link render hook, even if custom link render hooks are provided by your project, modules, or themes. In this case, the embedded hook takes precedence.
|
||||
- `fallback`: Use the embedded link render hook only if custom link render hooks are not provided by your project, modules, or themes. If custom link render hooks exist, these will be used instead.
|
||||
|
||||
renderer.hardWraps
|
||||
: (`bool`) Whether to replace newline characters within a paragraph with `br` elements. Default is `false`.
|
||||
@@ -173,7 +193,7 @@ This is the default configuration for the AsciiDoc renderer:
|
||||
|
||||
{{< code-toggle config=markup.asciidocExt />}}
|
||||
|
||||
### Settings explained
|
||||
### AsciiDoc settings explained
|
||||
|
||||
attributes
|
||||
: (`map`) A map of key-value pairs, each a document attribute. See Asciidoctor's [attributes].
|
||||
@@ -226,49 +246,47 @@ workingFolderCurrent
|
||||
|
||||
Follow the steps below to enable syntax highlighting.
|
||||
|
||||
#### Step 1
|
||||
Step 1
|
||||
: Set the `source-highlighter` attribute in your site configuration. For example:
|
||||
|
||||
Set the `source-highlighter` attribute in your site configuration. For example:
|
||||
{{< code-toggle file=hugo >}}
|
||||
[markup.asciidocExt.attributes]
|
||||
source-highlighter = 'rouge'
|
||||
{{< /code-toggle >}}
|
||||
|
||||
{{< code-toggle file=hugo >}}
|
||||
[markup.asciidocExt.attributes]
|
||||
source-highlighter = 'rouge'
|
||||
{{< /code-toggle >}}
|
||||
Step 2
|
||||
: Generate the highlighter CSS. For example:
|
||||
|
||||
#### Step 2
|
||||
```text
|
||||
rougify style monokai.sublime > assets/css/syntax.css
|
||||
```
|
||||
|
||||
Generate the highlighter CSS. For example:
|
||||
Step 3
|
||||
: In your base template add a link to the CSS file:
|
||||
|
||||
```text
|
||||
rougify style monokai.sublime > assets/css/syntax.css
|
||||
```
|
||||
```go-html-template {file="layouts/baseof.html"}
|
||||
<head>
|
||||
...
|
||||
{{ with resources.Get "css/syntax.css" }}
|
||||
<link rel="stylesheet" href="{{ .RelPermalink }}" integrity="{{ .Data.Integrity }}" crossorigin="anonymous">
|
||||
{{ end }}
|
||||
...
|
||||
</head>
|
||||
```
|
||||
|
||||
#### Step 3
|
||||
Step 4
|
||||
: Add the code to be highlighted to your markup:
|
||||
|
||||
In your base template add a link to the CSS file:
|
||||
```text
|
||||
[#hello,ruby]
|
||||
----
|
||||
require 'sinatra'
|
||||
|
||||
```go-html-template {file="layouts/_default/baseof.html"}
|
||||
<head>
|
||||
...
|
||||
{{ with resources.Get "css/syntax.css" }}
|
||||
<link rel="stylesheet" href="{{ .RelPermalink }}" integrity="{{ .Data.Integrity }}" crossorigin="anonymous">
|
||||
{{ end }}
|
||||
...
|
||||
</head>
|
||||
```
|
||||
|
||||
Then add the code to be highlighted to your markup:
|
||||
|
||||
```text
|
||||
[#hello,ruby]
|
||||
----
|
||||
require 'sinatra'
|
||||
|
||||
get '/hi' do
|
||||
"Hello World!"
|
||||
end
|
||||
----
|
||||
```
|
||||
get '/hi' do
|
||||
"Hello World!"
|
||||
end
|
||||
----
|
||||
```
|
||||
|
||||
### Troubleshooting
|
||||
|
||||
@@ -303,24 +321,24 @@ ordered
|
||||
|
||||
[`Fragments.Identifiers`]: /methods/page/fragments/#identifiers
|
||||
[`TableOfContents`]: /methods/page/tableofcontents/
|
||||
[anchorize]: /functions/urls/anchorize
|
||||
[AsciiDoc]: https://asciidoc.org/
|
||||
[asciidoctor-diagram]: https://asciidoctor.org/docs/asciidoctor-diagram/
|
||||
[attributes]: https://asciidoctor.org/docs/asciidoc-syntax-quick-reference/#attributes-and-substitutions
|
||||
[CommonMark]: https://spec.commonmark.org/current/
|
||||
[deleted text]: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/del
|
||||
[duplication of shared page resources]: /configuration/markup/#duplicateresourcefiles
|
||||
[duplication of shared page resources]: /configuration/markup/#duplicateresourcefiles
|
||||
[embedded image render hook]: /render-hooks/images/#default
|
||||
[embedded image render hook]: /render-hooks/images/#default
|
||||
[embedded link render hook]: /render-hooks/links/#default
|
||||
[embedded link render hook]: /render-hooks/links/#default
|
||||
[GitHub Flavored Markdown]: https://github.github.com/gfm/
|
||||
[Emacs Org Mode]: https://orgmode.org/
|
||||
[embedded image render hook]: /render-hooks/images/#embedded
|
||||
[embedded link render hook]: /render-hooks/links/#embedded
|
||||
[GitHub Flavored Markdown: Autolinks]: https://github.github.com/gfm/#autolinks-extension-
|
||||
[GitHub Flavored Markdown: Strikethrough]: https://github.github.com/gfm/#strikethrough-extension-
|
||||
[GitHub Flavored Markdown: Tables]: https://github.github.com/gfm/#tables-extension-
|
||||
[GitHub Flavored Markdown: Task list items]: https://github.github.com/gfm/#task-list-items-extension-
|
||||
[Goldmark]: https://github.com/yuin/goldmark/
|
||||
[GitHub Flavored Markdown]: https://github.github.com/gfm/
|
||||
[Goldmark Extensions: CJK]: https://github.com/yuin/goldmark?tab=readme-ov-file#cjk-extension
|
||||
[Goldmark Extensions: Typographer]: https://github.com/yuin/goldmark?tab=readme-ov-file#typographer-extension
|
||||
[Goldmark]: https://github.com/yuin/goldmark/
|
||||
[Hugo Goldmark Extensions: Extras]: https://github.com/gohugoio/hugo-goldmark-extensions?tab=readme-ov-file#extras-extension
|
||||
[Hugo Goldmark Extensions: Passthrough]: https://github.com/gohugoio/hugo-goldmark-extensions?tab=readme-ov-file#passthrough-extension
|
||||
[image render hook]: /render-hooks/images/
|
||||
@@ -330,12 +348,10 @@ ordered
|
||||
[Markdown attributes]: /content-management/markdown-attributes/
|
||||
[mathematics in Markdown]: content-management/mathematics/
|
||||
[multilingual page resources]: /content-management/page-resources/#multilingual
|
||||
[Pandoc]: https://pandoc.org/
|
||||
[PHP Markdown Extra: Definition lists]: https://michelf.ca/projects/php-markdown/extra/#def-list
|
||||
[PHP Markdown Extra: Footnotes]: https://michelf.ca/projects/php-markdown/extra/#footnotes
|
||||
[reStructuredText]: https://docutils.sourceforge.io/rst.html
|
||||
[security policy]: /configuration/security/
|
||||
[subscript]: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/sub
|
||||
[superscript]: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/sup
|
||||
[AsciiDoc]: https://asciidoc.org/
|
||||
[Emacs Org Mode]: https://orgmode.org/
|
||||
[Pandoc]: https://www.pandoc.org/
|
||||
[reStructuredText]: https://docutils.sourceforge.io/rst.html
|
||||
|
||||
@@ -96,6 +96,7 @@ url
|
||||
|
||||
This nested menu demonstrates some of the available properties:
|
||||
|
||||
<!-- markdownlint-disable MD033 -->
|
||||
{{< code-toggle file=hugo >}}
|
||||
[[menus.main]]
|
||||
name = 'Products'
|
||||
@@ -127,6 +128,7 @@ weight = 30
|
||||
[menus.main.params]
|
||||
rel = 'external'
|
||||
{{< /code-toggle >}}
|
||||
<!-- markdownlint-enable MD033 -->
|
||||
|
||||
[`Menus`]: /methods/site/menus/
|
||||
[Automatically]: /content-management/menus/#define-automatically
|
||||
|
||||
@@ -11,6 +11,7 @@ aliases: [/hugo-modules/configuration/]
|
||||
|
||||
This is the default configuration:
|
||||
|
||||
<!-- markdownlint-disable MD049 -->
|
||||
{{< code-toggle file=hugo >}}
|
||||
[module]
|
||||
noProxy = 'none'
|
||||
@@ -20,6 +21,7 @@ proxy = 'direct'
|
||||
vendorClosest = false
|
||||
workspace = 'off'
|
||||
{{< /code-toggle >}}
|
||||
<!-- markdownlint-enable MD049 -->
|
||||
|
||||
auth
|
||||
: {{< new-in 0.144.0 />}}
|
||||
@@ -75,12 +77,10 @@ extended
|
||||
: (`bool`) Whether the extended edition of Hugo is required, satisfied by installing either the extended or extended/deploy edition.
|
||||
|
||||
max
|
||||
: (`string`) The maximum Hugo version supported, for example `0.143.0`.
|
||||
: (`string`) The maximum Hugo version supported, for example `0.148.0`.
|
||||
|
||||
min
|
||||
: (`string`) The minimum Hugo version supported, for example `0.123.0`.
|
||||
|
||||
[`themesDir`]: /configuration/all/#themesdir
|
||||
: (`string`) The minimum Hugo version supported, for example `0.102.0`.
|
||||
|
||||
## Imports
|
||||
|
||||
@@ -112,8 +112,6 @@ noVendor
|
||||
path
|
||||
: (`string`) The module path, either a valid Go module path (e.g., `github.com/gohugoio/myShortcodes`) or the directory name if stored in the [`themesDir`].
|
||||
|
||||
[`themesDir`]: /configuration/all#themesDir
|
||||
|
||||
{{% include "/_common/gomodules-info.md" %}}
|
||||
|
||||
## Mounts
|
||||
@@ -177,3 +175,5 @@ excludeFiles
|
||||
source="assets"
|
||||
target="assets"
|
||||
{{< /code-toggle >}}
|
||||
|
||||
[`themesDir`]: /configuration/all/#themesdir
|
||||
|
||||
@@ -44,25 +44,25 @@ isHTML
|
||||
: (`bool`) Whether to classify the output format as HTML. Hugo uses this value to determine when to create alias redirects and when to inject the LiveReload script. Default is `false`.
|
||||
|
||||
isPlainText
|
||||
: (`bool`) Whether to parse templates for this output format with Go's [text/template] package instead of the [html/template] package. Default is `false`.
|
||||
: (`bool`) Whether to parse templates for this output format with Go's [text/template][] package instead of the [html/template][] package. Default is `false`.
|
||||
|
||||
mediaType
|
||||
: (`string`) The [media type](g) of the published file. This must match one of the [configured media types].
|
||||
: (`string`) The [media type](g) of the published file. This must match one of the [configured media types][].
|
||||
|
||||
notAlternative
|
||||
: (`bool`) Whether to exclude this output format from the values returned by the [`AlternativeOutputFormats`] method on a `Page` object. Default is `false`.
|
||||
: (`bool`) Whether to exclude this output format from the values returned by the [`AlternativeOutputFormats`][] method on a `Page` object. Default is `false`.
|
||||
|
||||
noUgly
|
||||
: (`bool`) Whether to disable ugly URLs for this output format when [`uglyURLs`] are enabled in your site configuration. Default is `false`.
|
||||
: (`bool`) Whether to disable ugly URLs for this output format when [`uglyURLs`][] are enabled in your site configuration. Default is `false`.
|
||||
|
||||
path
|
||||
: (`string`) The published file's directory path, relative to the root of the publish directory. If not specified, the file will be published using its content path.
|
||||
: (`string`) The first segment of the publication path for this output format. This path segment is relative to the root of your [`publishDir`][]. If omitted, Hugo will use the file's original content path for publishing.
|
||||
|
||||
permalinkable
|
||||
: (`bool`) Whether to return the rendering output format rather than main output format when invoking the [`Permalink`] and [`RelPermalink`] methods on a `Page` object. See [details](#link-to-output-formats). Enabled by default for the `html` and `amp` output formats. Default is `false`.
|
||||
: (`bool`) Whether to return the rendering output format rather than main output format when invoking the [`Permalink`][] and [`RelPermalink`][] methods on a `Page` object. See [details](#link-to-output-formats). Enabled by default for the `html` and `amp` output formats. Default is `false`.
|
||||
|
||||
protocol
|
||||
: (`string`) The protocol (scheme) of the URL for this output format. For example, `https://` or `webcal://`. Default is the scheme of the [`baseURL`] parameter in your site configuration, typically `https://`.
|
||||
: (`string`) The protocol (scheme) of the URL for this output format. For example, `https://` or `webcal://`. Default is the scheme of the [`baseURL`][] parameter in your site configuration, typically `https://`.
|
||||
|
||||
rel
|
||||
: (`string`) If provided, you can assign this value to `rel` attributes in `link` elements when iterating over output formats in your templates. Default is `alternate`.
|
||||
@@ -93,56 +93,52 @@ The example above shows that when you modify a default content format, you only
|
||||
|
||||
You can create new output formats as needed. For example, you may wish to create an output format to support Atom feeds.
|
||||
|
||||
### Step 1
|
||||
Step 1
|
||||
: Output formats require a specified media type. Because Atom feeds use `application/atom+xml`, which is not one of the [default media types][], you must create it first.
|
||||
|
||||
Output formats require a specified media type. Because Atom feeds use `application/atom+xml`, which is not one of the [default media types], you must create it first.
|
||||
{{< code-toggle file=hugo >}}
|
||||
[mediaTypes.'application/atom+xml']
|
||||
suffixes = ['atom']
|
||||
{{< /code-toggle >}}
|
||||
|
||||
{{< code-toggle file=hugo >}}
|
||||
[mediaTypes.'application/atom+xml']
|
||||
suffixes = ['atom']
|
||||
{{< /code-toggle >}}
|
||||
See [configure media types][] for more information.
|
||||
|
||||
See [configure media types] for more information.
|
||||
Step 2
|
||||
: Create a new output format:
|
||||
|
||||
### Step 2
|
||||
{{< code-toggle file=hugo >}}
|
||||
[outputFormats.atom]
|
||||
mediaType = 'application/atom+xml'
|
||||
noUgly = true
|
||||
{{< /code-toggle >}}
|
||||
|
||||
Create a new output format:
|
||||
Note that we use the default settings for all other output format properties.
|
||||
|
||||
{{< code-toggle file=hugo >}}
|
||||
[outputFormats.atom]
|
||||
mediaType = 'application/atom+xml'
|
||||
noUgly = true
|
||||
{{< /code-toggle >}}
|
||||
Step 3
|
||||
: Specify the page [kinds](g) for which to render this output format:
|
||||
|
||||
Note that we use the default settings for all other output format properties.
|
||||
{{< code-toggle file=hugo >}}
|
||||
[outputs]
|
||||
home = ['html', 'rss', 'atom']
|
||||
section = ['html', 'rss', 'atom']
|
||||
taxonomy = ['html', 'rss', 'atom']
|
||||
term = ['html', 'rss', 'atom']
|
||||
{{< /code-toggle >}}
|
||||
|
||||
### Step 3
|
||||
See [configure outputs][] for more information.
|
||||
|
||||
Specify the page [kinds](g) for which to render this output format:
|
||||
Step 4
|
||||
: Create a template to render the output format. Since Atom feeds are lists, you need to create a list template. Consult the [template lookup order] to find the correct template path:
|
||||
|
||||
{{< code-toggle file=hugo >}}
|
||||
[outputs]
|
||||
home = ['html', 'rss', 'atom']
|
||||
section = ['html', 'rss', 'atom']
|
||||
taxonomy = ['html', 'rss', 'atom']
|
||||
term = ['html', 'rss', 'atom']
|
||||
{{< /code-toggle >}}
|
||||
```text
|
||||
layouts/list.atom.atom
|
||||
```
|
||||
|
||||
See [configure outputs] for more information.
|
||||
|
||||
### Step 4
|
||||
|
||||
Create a template to render the output format. Since Atom feeds are lists, you need to create a list template. Consult the [template lookup order] to find the correct template path:
|
||||
|
||||
```text
|
||||
layouts/_default/list.atom.atom
|
||||
```
|
||||
|
||||
We leave writing the template code as an exercise for you. Aim for a result similar to the [embedded RSS template].
|
||||
We leave writing the template code as an exercise for you. Aim for a result similar to the [embedded RSS template][].
|
||||
|
||||
## List output formats
|
||||
|
||||
To access output formats, each `Page` object provides two methods: [`OutputFormats`] (for all formats, including the current one) and [`AlternativeOutputFormats`]. Use `AlternativeOutputFormats` to create a link `rel` list within your site's `head` element, as shown below:
|
||||
To access output formats, each `Page` object provides two methods: [`OutputFormats`][] (for all formats, including the current one) and [`AlternativeOutputFormats`][]. Use `AlternativeOutputFormats` to create a link `rel` list within your site's `head` element, as shown below:
|
||||
|
||||
```go-html-template
|
||||
{{ range .AlternativeOutputFormats }}
|
||||
@@ -152,9 +148,9 @@ To access output formats, each `Page` object provides two methods: [`OutputForma
|
||||
|
||||
## Link to output formats
|
||||
|
||||
By default, a `Page` object's [`Permalink`] and [`RelPermalink`] methods return the URL of the [primary output format](g), typically `html`. This behavior remains consistent regardless of the template used.
|
||||
By default, a `Page` object's [`Permalink`][] and [`RelPermalink`][] methods return the URL of the [primary output format](g), typically `html`. This behavior remains consistent regardless of the template used.
|
||||
|
||||
For example, in `single.json.json`, you'll see:
|
||||
For example, in `page.json.json`, you'll see:
|
||||
|
||||
```go-html-template
|
||||
{{ .RelPermalink }} → /that-page/
|
||||
@@ -163,9 +159,9 @@ For example, in `single.json.json`, you'll see:
|
||||
{{ end }}
|
||||
```
|
||||
|
||||
To make these methods return the URL of the _current_ template's output format, you must set the [`permalinkable`] setting to `true` for that format.
|
||||
To make these methods return the URL of the _current_ template's output format, you must set the [`permalinkable`][] setting to `true` for that format.
|
||||
|
||||
With `permalinkable` set to true for `json` in the same `single.json.json` template:
|
||||
With `permalinkable` set to true for `json` in the same `page.json.json` template:
|
||||
|
||||
```go-html-template
|
||||
{{ .RelPermalink }} → /that-page/index.json
|
||||
@@ -176,7 +172,7 @@ With `permalinkable` set to true for `json` in the same `single.json.json` templ
|
||||
|
||||
## Template lookup order
|
||||
|
||||
Each output format requires a template conforming to the [template lookup order].
|
||||
Each output format requires a template conforming to the [template lookup order][].
|
||||
|
||||
For the highest specificity in the template lookup order, include the page kind, output format, and suffix in the file name:
|
||||
|
||||
@@ -188,22 +184,23 @@ For example, for section pages:
|
||||
|
||||
Output format|Template path
|
||||
:--|:--
|
||||
`html`|`layouts/_default/section.html.html`
|
||||
`json`|`layouts/_default/section.json.json`
|
||||
`rss`|`layouts/_default/section.rss.xml`
|
||||
`html`|`layouts/section.html.html`
|
||||
`json`|`layouts/section.json.json`
|
||||
`rss`|`layouts/section.rss.xml`
|
||||
|
||||
[`AlternativeOutputFormats`]: /methods/page/alternativeoutputformats/
|
||||
[`baseURL`]: /configuration/all/#baseurl
|
||||
[`OutputFormats`]: /methods/page/outputformats/
|
||||
[`Permalink`]: /methods/page/permalink/
|
||||
[`RelPermalink`]: /methods/page/relpermalink/
|
||||
[`baseURL`]: /configuration/all/#baseurl
|
||||
[`permalinkable`]: #permalinkable
|
||||
[`publishDir`]: /configuration/all/#publishdir
|
||||
[`RelPermalink`]: /methods/page/relpermalink/
|
||||
[`uglyURLs`]: /configuration/ugly-urls/
|
||||
[configure media types]: /configuration/media-types/
|
||||
[configure outputs]: /configuration/outputs/
|
||||
[configured media types]: /configuration/media-types/
|
||||
[default media types]: /configuration/media-types/
|
||||
[embedded RSS template]: {{% eturl rss %}}
|
||||
[embedded RSS template]: <{{% eturl rss %}}>
|
||||
[html/template]: https://pkg.go.dev/html/template
|
||||
[template lookup order]: /templates/lookup-order/
|
||||
[text/template]: https://pkg.go.dev/text/template
|
||||
|
||||
@@ -95,9 +95,9 @@ weight = 1
|
||||
|
||||
We've configured the `authors` index with a weight of `2` and the `genres` index with a weight of `1`. This means Hugo prioritizes shared `authors` as twice as significant as shared `genres`.
|
||||
|
||||
Then render a list of 5 related reviews with a partial template like this:
|
||||
Then render a list of 5 related reviews with a _partial_ template like this:
|
||||
|
||||
```go-html-template {file="layouts/partials/related.html" copy=true}
|
||||
```go-html-template {file="layouts/_partials/related.html" copy=true}
|
||||
{{ with site.RegularPages.Related . | first 5 }}
|
||||
<p>Related content:</p>
|
||||
<ul>
|
||||
|
||||
@@ -6,7 +6,7 @@ categories: []
|
||||
keywords: []
|
||||
---
|
||||
|
||||
Hugo's built-in security policy, which restricts access to `os/exec`, remote communication, and similar operations, is configured via allow lists. By default, access is restricted. If a build attempts to use a feature not included in the allow list, it will fail, providing a detailed message.
|
||||
Hugo's built-in security policy, which restricts access to `os/exec`, remote communication, and similar operations, is configured via allowlists. By default, access is restricted. If a build attempts to use a feature not included in the allowlist, it will fail, providing a detailed message.
|
||||
|
||||
This is the default security configuration:
|
||||
|
||||
@@ -34,7 +34,7 @@ http.urls
|
||||
: (`[]string`) A slice of [regular expressions](g) matching the URLs that the `resources.GetRemote` function is allowed to access.
|
||||
|
||||
> [!note]
|
||||
> Setting an allow list to the string `none` will completely disable the associated feature.
|
||||
> Setting an allowlist to the string `none` will completely disable the associated feature.
|
||||
|
||||
You can also override the site configuration with environment variables. For example, to block `resources.GetRemote` from accessing any URL:
|
||||
|
||||
|
||||
@@ -31,7 +31,7 @@ Each segment is defined by include and exclude filters:
|
||||
Available fields for filtering:
|
||||
|
||||
kind
|
||||
: (`string`) A [glob](g) pattern matching the [page kind](g). For example: ` {taxonomy,term}`.
|
||||
: (`string`) A [glob](g) pattern matching the [page kind](g). For example: `{taxonomy,term}`.
|
||||
|
||||
lang
|
||||
: (`string`) A [glob](g) pattern matching the [page language]. For example: `{en,de}`.
|
||||
|
||||
@@ -47,7 +47,7 @@ to
|
||||
|
||||
## Headers
|
||||
|
||||
Include headers in every server response to facilitate testing, particularly for features like Content Security Policies.
|
||||
Include headers in every server response to facilitate testing, particularly for features like [Content Security Policies].
|
||||
|
||||
[Content Security Policies]: https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP
|
||||
|
||||
|
||||
@@ -17,8 +17,8 @@ When creating a taxonomy:
|
||||
|
||||
Then use the value as the key in front matter:
|
||||
|
||||
<!-- markdownlint-disable MD007 MD032 -->
|
||||
{{< code-toggle file=content/example.md fm=true >}}
|
||||
---
|
||||
title: Example
|
||||
categories:
|
||||
- vegetarian
|
||||
@@ -27,7 +27,7 @@ tags:
|
||||
- appetizer
|
||||
- main course
|
||||
{{< /code-toggle >}}
|
||||
|
||||
<!-- markdownlint-enable MD007 MD032 -->
|
||||
If you do not expect to assign more than one [term](g) from a given taxonomy to a content page, you may use the singular form for both key and value:
|
||||
|
||||
{{< code-toggle file=hugo >}}
|
||||
@@ -37,12 +37,13 @@ taxonomies:
|
||||
|
||||
Then in front matter:
|
||||
|
||||
<!-- markdownlint-disable MD007 MD032 -->
|
||||
{{< code-toggle file=content/example.md fm=true >}}
|
||||
---
|
||||
title: Example
|
||||
author:
|
||||
- Robert Smith
|
||||
{{< /code-toggle >}}
|
||||
<!-- markdownlint-enable MD007 MD032 -->
|
||||
|
||||
The example above illustrates that even with a single term, the value is still provided as an array.
|
||||
|
||||
@@ -58,7 +59,7 @@ taxonomies:
|
||||
To disable the taxonomy system, use the [`disableKinds`] setting in the root of your site configuration to disable the `taxonomy` and `term` page [kinds](g).
|
||||
|
||||
{{< code-toggle file=hugo >}}
|
||||
disableKinds = ['categories','tags']
|
||||
disableKinds = ['taxonomy','term']
|
||||
{{< /code-toggle >}}
|
||||
|
||||
[`disableKinds`]: /configuration/all/#disablekinds
|
||||
|
||||
@@ -13,6 +13,7 @@ https://example.org/section/article.html
|
||||
```
|
||||
|
||||
In its default configuration, Hugo generates [pretty URLs](g). For example:
|
||||
|
||||
```text
|
||||
https://example.org/section/article/
|
||||
```
|
||||
|
||||
@@ -69,7 +69,7 @@ title = 'Headless page'
|
||||
|
||||
To include the content and images on the home page:
|
||||
|
||||
```go-html-template {file="layouts/_default/home.html"}
|
||||
```go-html-template {file="layouts/home.html"}
|
||||
{{ with .Site.GetPage "/headless" }}
|
||||
{{ .Content }}
|
||||
{{ range .Resources.ByType "image" }}
|
||||
@@ -127,7 +127,7 @@ In the front matter above, note that we have set `list` to `local` to include th
|
||||
|
||||
To include the content and images on the home page:
|
||||
|
||||
```go-html-template {file="layouts/_default/home.html"}
|
||||
```go-html-template {file="layouts/home.html"}
|
||||
{{ with .Site.GetPage "/headless" }}
|
||||
{{ range .Pages }}
|
||||
{{ .Content }}
|
||||
@@ -186,7 +186,7 @@ render = 'always'
|
||||
|
||||
To render the glossary:
|
||||
|
||||
```go-html-template {file="layouts/glossary/list.html"}
|
||||
```go-html-template {file="layouts/glossary/section.html"}
|
||||
<dl>
|
||||
{{ range .Pages }}
|
||||
<dt>{{ .Title }}</dt>
|
||||
|
||||
@@ -34,7 +34,7 @@ For many websites, this is enough configuration. However, you also have the opti
|
||||
Disqus has its own [internal template](/templates/embedded/#disqus) available, to render it add the following code where you want comments to appear:
|
||||
|
||||
```go-html-template
|
||||
{{ template "_internal/disqus.html" . }}
|
||||
{{ partial "disqus.html" . }}
|
||||
```
|
||||
|
||||
## Alternatives
|
||||
@@ -64,9 +64,4 @@ Open-source commenting systems:
|
||||
[configuration]: /configuration/
|
||||
[disquspartial]: /templates/embedded/#disqus
|
||||
[disqussetup]: https://disqus.com/profile/signup/
|
||||
[forum]: https://discourse.gohugo.io
|
||||
[front matter]: /content-management/front-matter/
|
||||
[kaijuissue]: https://github.com/spf13/kaiju/issues/new
|
||||
[issotutorial]: https://stiobhart.net/2017-02-24-isso-comments/
|
||||
[partials]: /templates/partial/
|
||||
[MongoDB]: https://www.mongodb.com/
|
||||
|
||||
@@ -27,7 +27,7 @@ content/
|
||||
└── _index.md
|
||||
```
|
||||
|
||||
Each content adapter is named _content.gotmpl and uses the same [syntax] as templates in the `layouts` directory. You can use any of the [template functions] within a content adapter, as well as the methods described below.
|
||||
Each content adapter is named `_content.gotmpl` and uses the same [syntax] as templates in the `layouts` directory. You can use any of the [template functions] within a content adapter, as well as the methods described below.
|
||||
|
||||
## Methods
|
||||
|
||||
@@ -71,7 +71,7 @@ Adds a page resource to the site.
|
||||
|
||||
Then retrieve the new page resource with something like:
|
||||
|
||||
```go-html-template {file="layouts/_default/single.html"}
|
||||
```go-html-template {file="layouts/page.html"}
|
||||
{{ with .Resources.Get "cover.jpg" }}
|
||||
<img src="{{ .RelPermalink }}" width="{{ .Width }}" height="{{ .Height }}" alt="">
|
||||
{{ end }}
|
||||
@@ -90,7 +90,7 @@ Returns the `Site` to which the pages will be added.
|
||||
|
||||
### Store
|
||||
|
||||
Returns a persistent “scratch pad” to store and manipulate data. The main use case for this is to transfer values between executions when [EnableAllLanguages](#enablealllanguages) is set. See [examples](/methods/page/store/).
|
||||
Returns a persistent "scratch pad" to store and manipulate data. The main use case for this is to transfer values between executions when [EnableAllLanguages](#enablealllanguages) is set. See [examples](/methods/page/store/).
|
||||
|
||||
```go-html-template {file="content/books/_content.gotmpl"}
|
||||
{{ .Store.Set "key" "value" }}
|
||||
@@ -99,7 +99,7 @@ Returns a persistent “scratch pad” to store and manipulate data. The main us
|
||||
|
||||
### EnableAllLanguages
|
||||
|
||||
By default, Hugo executes the content adapter for the language defined by the _content.gotmpl file. Use this method to activate the content adapter for all languages.
|
||||
By default, Hugo executes the content adapter for the language defined by the `_content.gotmpl` file. Use this method to activate the content adapter for all languages.
|
||||
|
||||
```go-html-template {file="content/books/_content.gotmpl"}
|
||||
{{ .EnableAllLanguages }}
|
||||
@@ -153,7 +153,7 @@ Key|Description|Required
|
||||
`title`|The resource title.|
|
||||
|
||||
> [!note]
|
||||
> If the `content.value` is a string Hugo creates a new resource. If the `content.value` is a resource, Hugo obtains the value from the existing resource.
|
||||
> When `content.value` is a string, Hugo generates a new resource with a publication path relative to the page. However, if `content.value` is already a resource, Hugo directly uses its value and publishes it relative to the site root. This latter method is more efficient.
|
||||
>
|
||||
> When setting the `path`, Hugo transforms the given string to a logical path. For example, setting `path` to `A B C/cover.jpg` produces a logical path of `/section/a-b-c/cover.jpg`.
|
||||
|
||||
@@ -161,112 +161,109 @@ Key|Description|Required
|
||||
|
||||
Create pages from remote data, where each page represents a book review.
|
||||
|
||||
### Step 1
|
||||
Step 1
|
||||
: Create the content structure.
|
||||
|
||||
Create the content structure.
|
||||
```text
|
||||
content/
|
||||
└── books/
|
||||
├── _content.gotmpl <-- content adapter
|
||||
└── _index.md
|
||||
```
|
||||
|
||||
```text
|
||||
content/
|
||||
└── books/
|
||||
├── _content.gotmpl <-- content adapter
|
||||
└── _index.md
|
||||
```
|
||||
Step 2
|
||||
: Inspect the remote data to determine how to map key-value pairs to front matter fields.\
|
||||
<https://gohugo.io/shared/examples/data/books.json>
|
||||
|
||||
### Step 2
|
||||
Inspect the remote data to determine how to map key-value pairs to front matter fields.\
|
||||
<https://gohugo.io/shared/examples/data/books.json>
|
||||
Step 3
|
||||
: Create the content adapter.
|
||||
|
||||
### Step 3
|
||||
|
||||
Create the content adapter.
|
||||
|
||||
```go-html-template {file="content/books/_content.gotmpl" copy=true}
|
||||
{{/* Get remote data. */}}
|
||||
{{ $data := dict }}
|
||||
{{ $url := "https://gohugo.io/shared/examples/data/books.json" }}
|
||||
{{ with try (resources.GetRemote $url) }}
|
||||
{{ with .Err }}
|
||||
{{ errorf "Unable to get remote resource %s: %s" $url . }}
|
||||
{{ else with .Value }}
|
||||
{{ $data = . | transform.Unmarshal }}
|
||||
{{ else }}
|
||||
{{ errorf "Unable to get remote resource %s" $url }}
|
||||
{{ end }}
|
||||
{{ end }}
|
||||
|
||||
{{/* Add pages and page resources. */}}
|
||||
{{ range $data }}
|
||||
|
||||
{{/* Add page. */}}
|
||||
{{ $content := dict "mediaType" "text/markdown" "value" .summary }}
|
||||
{{ $dates := dict "date" (time.AsTime .date) }}
|
||||
{{ $params := dict "author" .author "isbn" .isbn "rating" .rating "tags" .tags }}
|
||||
{{ $page := dict
|
||||
"content" $content
|
||||
"dates" $dates
|
||||
"kind" "page"
|
||||
"params" $params
|
||||
"path" .title
|
||||
"title" .title
|
||||
}}
|
||||
{{ $.AddPage $page }}
|
||||
|
||||
{{/* Add page resource. */}}
|
||||
{{ $item := . }}
|
||||
{{ with $url := $item.cover }}
|
||||
{{ with try (resources.GetRemote $url) }}
|
||||
{{ with .Err }}
|
||||
{{ errorf "Unable to get remote resource %s: %s" $url . }}
|
||||
{{ else with .Value }}
|
||||
{{ $content := dict "mediaType" .MediaType.Type "value" .Content }}
|
||||
{{ $params := dict "alt" $item.title }}
|
||||
{{ $resource := dict
|
||||
"content" $content
|
||||
"params" $params
|
||||
"path" (printf "%s/cover.%s" $item.title .MediaType.SubType)
|
||||
}}
|
||||
{{ $.AddResource $resource }}
|
||||
{{ else }}
|
||||
{{ errorf "Unable to get remote resource %s" $url }}
|
||||
{{ end }}
|
||||
```go-html-template {file="content/books/_content.gotmpl" copy=true}
|
||||
{{/* Get remote data. */}}
|
||||
{{ $data := dict }}
|
||||
{{ $url := "https://gohugo.io/shared/examples/data/books.json" }}
|
||||
{{ with try (resources.GetRemote $url) }}
|
||||
{{ with .Err }}
|
||||
{{ errorf "Unable to get remote resource %s: %s" $url . }}
|
||||
{{ else with .Value }}
|
||||
{{ $data = . | transform.Unmarshal }}
|
||||
{{ else }}
|
||||
{{ errorf "Unable to get remote resource %s" $url }}
|
||||
{{ end }}
|
||||
{{ end }}
|
||||
|
||||
{{ end }}
|
||||
```
|
||||
{{/* Add pages and page resources. */}}
|
||||
{{ range $data }}
|
||||
|
||||
### Step 4
|
||||
{{/* Add page. */}}
|
||||
{{ $content := dict "mediaType" "text/markdown" "value" .summary }}
|
||||
{{ $dates := dict "date" (time.AsTime .date) }}
|
||||
{{ $params := dict "author" .author "isbn" .isbn "rating" .rating "tags" .tags }}
|
||||
{{ $page := dict
|
||||
"content" $content
|
||||
"dates" $dates
|
||||
"kind" "page"
|
||||
"params" $params
|
||||
"path" .title
|
||||
"title" .title
|
||||
}}
|
||||
{{ $.AddPage $page }}
|
||||
|
||||
Create a single template to render each book review.
|
||||
|
||||
```go-html-template {file="layouts/books/single.html" copy=true}
|
||||
{{ define "main" }}
|
||||
<h1>{{ .Title }}</h1>
|
||||
|
||||
{{ with .Resources.GetMatch "cover.*" }}
|
||||
<img src="{{ .RelPermalink }}" width="{{ .Width }}" height="{{ .Height }}" alt="{{ .Params.alt }}">
|
||||
{{ end }}
|
||||
|
||||
<p>Author: {{ .Params.author }}</p>
|
||||
|
||||
<p>
|
||||
ISBN: {{ .Params.isbn }}<br>
|
||||
Rating: {{ .Params.rating }}<br>
|
||||
Review date: {{ .Date | time.Format ":date_long" }}
|
||||
</p>
|
||||
|
||||
{{ with .GetTerms "tags" }}
|
||||
<p>Tags:</p>
|
||||
<ul>
|
||||
{{ range . }}
|
||||
<li><a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a></li>
|
||||
{{/* Add page resource. */}}
|
||||
{{ $item := . }}
|
||||
{{ with $url := $item.cover }}
|
||||
{{ with try (resources.GetRemote $url) }}
|
||||
{{ with .Err }}
|
||||
{{ errorf "Unable to get remote resource %s: %s" $url . }}
|
||||
{{ else with .Value }}
|
||||
{{ $content := dict "mediaType" .MediaType.Type "value" .Content }}
|
||||
{{ $params := dict "alt" $item.title }}
|
||||
{{ $resource := dict
|
||||
"content" $content
|
||||
"params" $params
|
||||
"path" (printf "%s/cover.%s" $item.title .MediaType.SubType)
|
||||
}}
|
||||
{{ $.AddResource $resource }}
|
||||
{{ else }}
|
||||
{{ errorf "Unable to get remote resource %s" $url }}
|
||||
{{ end }}
|
||||
{{ end }}
|
||||
</ul>
|
||||
{{ end }}
|
||||
{{ end }}
|
||||
|
||||
{{ .Content }}
|
||||
{{ end }}
|
||||
```
|
||||
{{ end }}
|
||||
```
|
||||
|
||||
Step 4
|
||||
: Create a _page_ template to render each book review.
|
||||
|
||||
```go-html-template {file="layouts/books/page.html" copy=true}
|
||||
{{ define "main" }}
|
||||
<h1>{{ .Title }}</h1>
|
||||
|
||||
{{ with .Resources.GetMatch "cover.*" }}
|
||||
<img src="{{ .RelPermalink }}" width="{{ .Width }}" height="{{ .Height }}" alt="{{ .Params.alt }}">
|
||||
{{ end }}
|
||||
|
||||
<p>Author: {{ .Params.author }}</p>
|
||||
|
||||
<p>
|
||||
ISBN: {{ .Params.isbn }}<br>
|
||||
Rating: {{ .Params.rating }}<br>
|
||||
Review date: {{ .Date | time.Format ":date_long" }}
|
||||
</p>
|
||||
|
||||
{{ with .GetTerms "tags" }}
|
||||
<p>Tags:</p>
|
||||
<ul>
|
||||
{{ range . }}
|
||||
<li><a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a></li>
|
||||
{{ end }}
|
||||
</ul>
|
||||
{{ end }}
|
||||
|
||||
{{ .Content }}
|
||||
{{ end }}
|
||||
```
|
||||
|
||||
## Multilingual sites
|
||||
|
||||
@@ -338,7 +335,7 @@ content/
|
||||
└── the-hunchback-of-notre-dame.md
|
||||
```
|
||||
|
||||
If the content adapter also creates books/the-hunchback-of-notre-dame, the content of the published page is indeterminate. You can not define the processing order.
|
||||
If the content adapter also creates `books/the-hunchback-of-notre-dame`, the content of the published page is indeterminate. You can not define the processing order.
|
||||
|
||||
To detect page collisions, use the `--printPathWarnings` flag when building your site.
|
||||
|
||||
|
||||
@@ -65,7 +65,7 @@ Use data sources to augment existing content. For example, create a shortcode to
|
||||
{{</* csv-to-table "pets.csv" */>}}
|
||||
```
|
||||
|
||||
```go-html-template {file="layouts/shortcodes/csv-to-table.html"}
|
||||
```go-html-template {file="layouts/_shortcodes/csv-to-table.html"}
|
||||
{{ with $file := .Get 0 }}
|
||||
{{ with resources.Get $file }}
|
||||
{{ with . | transform.Unmarshal }}
|
||||
|
||||
@@ -39,7 +39,7 @@ Will be rendered as:
|
||||
|
||||
Hugo does not provide a built-in template for Mermaid diagrams. Create your own using a [code block render hook]:
|
||||
|
||||
```go-html-template {file="layouts/_default/_markup/render-codeblock-mermaid.html" copy=true}
|
||||
```go-html-template {file="layouts/_markup/render-codeblock-mermaid.html" copy=true}
|
||||
<pre class="mermaid">
|
||||
{{ .Inner | htmlEscape | safeHTML }}
|
||||
</pre>
|
||||
@@ -48,7 +48,7 @@ Hugo does not provide a built-in template for Mermaid diagrams. Create your own
|
||||
|
||||
Then include this snippet at the _bottom_ of your base template, before the closing `body` tag:
|
||||
|
||||
```go-html-template {file="layouts/_default/baseof.html" copy=true}
|
||||
```go-html-template {file="layouts/baseof.html" copy=true}
|
||||
{{ if .Store.Get "hasMermaid" }}
|
||||
<script type="module">
|
||||
import mermaid from 'https://cdn.jsdelivr.net/npm/mermaid/dist/mermaid.esm.min.mjs';
|
||||
|
||||
@@ -75,7 +75,7 @@ Create your content in the [Emacs Org Mode] format preceded by front matter. You
|
||||
|
||||
### AsciiDoc
|
||||
|
||||
Create your content in the [AsciiDoc] format preceded by front matter. Hugo renders AsciiDoc content to HTML using the Asciidoctor executable. You must install Asciidoctor and its dependencies (Ruby) to use the AsciiDoc content format.
|
||||
Create your content in the [AsciiDoc] format preceded by front matter. Hugo renders AsciiDoc content to HTML using the Asciidoctor executable. You must install Asciidoctor and its dependencies (Ruby) to render the AsciiDoc content format.
|
||||
|
||||
You can configure the AsciiDoc renderer in your [site configuration][configure asciidoc].
|
||||
|
||||
@@ -92,12 +92,13 @@ hugo --logLevel info
|
||||
```
|
||||
|
||||
[AsciiDoc]: https://asciidoc.org/
|
||||
[configure the AsciiDoc renderer]: /configuration/markup/#asciidoc
|
||||
[configure asciidoc]: /configuration/markup/#asciidoc
|
||||
|
||||
### Pandoc
|
||||
|
||||
Create your content in the [Pandoc] format preceded by front matter. Hugo renders Pandoc content to HTML using the Pandoc executable. You must install Pandoc to use the Pandoc content format.
|
||||
Create your content in the [Pandoc] format[^1] preceded by front matter. Hugo renders Pandoc content to HTML using the Pandoc executable. You must install Pandoc to render the Pandoc content format.
|
||||
|
||||
[^1]: This is a derivation of the Markdown format as described by the CommonMark specification.
|
||||
|
||||
Hugo passes these CLI flags when calling the Pandoc executable:
|
||||
|
||||
@@ -105,11 +106,11 @@ Hugo passes these CLI flags when calling the Pandoc executable:
|
||||
--mathjax
|
||||
```
|
||||
|
||||
[Pandoc]: https://pandoc.org/
|
||||
[Pandoc]: https://pandoc.org/MANUAL.html#pandocs-markdown
|
||||
|
||||
### reStructuredText
|
||||
|
||||
Create your content in the [reStructuredText] format preceded by front matter. Hugo renders reStructuredText content to HTML using [Docutils], specifically rst2html. You must install Docutils and its dependencies (Python) to use the reStructuredText content format.
|
||||
Create your content in the [reStructuredText] format preceded by front matter. Hugo renders reStructuredText content to HTML using [Docutils], specifically rst2html. You must install Docutils and its dependencies (Python) to render the reStructuredText content format.
|
||||
|
||||
Hugo passes these CLI flags when calling the rst2html executable:
|
||||
|
||||
|
||||
@@ -18,10 +18,6 @@ The front matter at the top of each content file is metadata that:
|
||||
|
||||
Provide front matter using a serialization format, one of [JSON], [TOML], or [YAML]. Hugo determines the front matter format by examining the delimiters that separate the front matter from the page content.
|
||||
|
||||
[json]: https://www.json.org/
|
||||
[toml]: https://toml.io/
|
||||
[yaml]: https://yaml.org/
|
||||
|
||||
See examples of front matter delimiters by toggling between the serialization formats below.
|
||||
|
||||
{{< code-toggle file=content/example.md fm=true >}}
|
||||
@@ -115,7 +111,7 @@ sitemap
|
||||
: (`map`) A map of sitemap options. See the [sitemap templates] page for details. Access these values from a template using the [`Sitemap`] method on a `Page` object.
|
||||
|
||||
slug
|
||||
: (`string`) Overrides the last segment of the URL path. Not applicable to section pages. See the [URL management] page for details. Access this value from a template using the [`Slug`] method on a `Page` object.
|
||||
: (`string`) Overrides the last segment of the URL path. Not applicable to `home`, `section`, `taxonomy`, or `term` pages. See the [URL management] page for details. Access this value from a template using the [`Slug`] method on a `Page` object.
|
||||
|
||||
summary
|
||||
: (`string`) Conceptually different than the page `description`, the summary either summarizes the content or serves as a teaser to encourage readers to visit the page. Access this value from a template using the [`Summary`] method on a `Page` object.
|
||||
@@ -138,42 +134,6 @@ url
|
||||
weight
|
||||
: (`int`) The page [weight](g), used to order the page within a [page collection](g). Access this value from a template using the [`Weight`] method on a `Page` object.
|
||||
|
||||
[URL management]: /content-management/urls/#slug
|
||||
[`Summary`]: /methods/page/summary/
|
||||
[`aliases`]: /methods/page/aliases/
|
||||
[`date`]: /methods/page/date/
|
||||
[`description`]: /methods/page/description/
|
||||
[`draft`]: /methods/page/draft/
|
||||
[`expirydate`]: /methods/page/expirydate/
|
||||
[`fuzzywordcount`]: /methods/page/wordcount/
|
||||
[`keywords`]: /methods/page/keywords/
|
||||
[`lastmod`]: /methods/page/date/
|
||||
[`layout`]: /methods/page/layout/
|
||||
[`linktitle`]: /methods/page/linktitle/
|
||||
[`publishdate`]: /methods/page/publishdate/
|
||||
[`readingtime`]: /methods/page/readingtime/
|
||||
[`sitemap`]: /methods/page/sitemap/
|
||||
[`slug`]: /methods/page/slug/
|
||||
[`summary`]: /methods/page/summary/
|
||||
[`title`]: /methods/page/title/
|
||||
[`translationkey`]: /methods/page/translationkey/
|
||||
[`type`]: /methods/page/type/
|
||||
[`weight`]: /methods/page/weight/
|
||||
[`wordcount`]: /methods/page/wordcount/
|
||||
[aliases]: /content-management/urls/#aliases
|
||||
[build options]: /content-management/build-options/
|
||||
[cascade]: #cascade-1
|
||||
[configure outputs]: /configuration/outputs/#outputs-per-page
|
||||
[content formats]: /content-management/formats/#classification
|
||||
[leaf bundles]: /content-management/page-bundles/#leaf-bundles
|
||||
[menus]: /content-management/menus/#define-in-front-matter
|
||||
[output formats]: /configuration/output-formats/
|
||||
[page parameters]: #parameters
|
||||
[page resources]: /content-management/page-resources/#metadata
|
||||
[sitemap templates]: /templates/sitemap/
|
||||
[target a specific template]: /templates/lookup-order/#target-a-template
|
||||
[template lookup order]: /templates/lookup-order/
|
||||
|
||||
## Parameters
|
||||
|
||||
{{< new-in 0.123.0 />}}
|
||||
@@ -191,9 +151,6 @@ author = 'John Smith'
|
||||
|
||||
Access these values from a template using the [`Params`] or [`Param`] method on a `Page` object.
|
||||
|
||||
[`param`]: /methods/page/param/
|
||||
[`params`]: /methods/page/params/
|
||||
|
||||
Hugo provides [embedded templates] to optionally insert meta data within the `head` element of your rendered pages. These embedded templates expect the following front matter parameters:
|
||||
|
||||
Parameter|Data type|Used by these embedded templates
|
||||
@@ -237,7 +194,7 @@ You can add taxonomy terms to the front matter of any these [page kinds](g):
|
||||
|
||||
Access taxonomy terms from a template using the [`Params`] or [`GetTerms`] method on a `Page` object. For example:
|
||||
|
||||
```go-html-template {file="layouts/_default/single.html"}
|
||||
```go-html-template {file="layouts/page.html"}
|
||||
{{ with .GetTerms "tags" }}
|
||||
<p>Tags</p>
|
||||
<ul>
|
||||
@@ -248,7 +205,6 @@ Access taxonomy terms from a template using the [`Params`] or [`GetTerms`] metho
|
||||
{{ end }}
|
||||
```
|
||||
|
||||
[`Params`]: /methods/page/params/
|
||||
[`GetTerms`]: /methods/page/getterms/
|
||||
|
||||
## Cascade
|
||||
@@ -289,7 +245,7 @@ environment
|
||||
: (`string`) A [glob](g) pattern matching the build [environment](g). For example: `{staging,production}`.
|
||||
|
||||
kind
|
||||
: (`string`) A [glob](g) pattern matching the [page kind](g). For example: ` {taxonomy,term}`.
|
||||
: (`string`) A [glob](g) pattern matching the [page kind](g). For example: `{taxonomy,term}`.
|
||||
|
||||
path
|
||||
: (`string`) A [glob](g) pattern matching the page's [logical path](g). For example: `{/books,/books/**}`.
|
||||
@@ -356,7 +312,46 @@ To override the default time zone, set the [`timeZone`](/configuration/all/#time
|
||||
1. The time zone specified in your site configuration
|
||||
1. The `Etc/UTC` time zone
|
||||
|
||||
[`aliases`]: /methods/page/aliases/
|
||||
[`date`]: /methods/page/date/
|
||||
[`description`]: /methods/page/description/
|
||||
[`draft`]: /methods/page/draft/
|
||||
[`expirydate`]: /methods/page/expirydate/
|
||||
[`fuzzywordcount`]: /methods/page/wordcount/
|
||||
[`keywords`]: /methods/page/keywords/
|
||||
[`lastmod`]: /methods/page/date/
|
||||
[`layout`]: /methods/page/layout/
|
||||
[`linktitle`]: /methods/page/linktitle/
|
||||
[`opengraph.html`]: {{% eturl opengraph %}}
|
||||
[`Param`]: /methods/page/param/
|
||||
[`Params`]: /methods/page/params/
|
||||
[`publishdate`]: /methods/page/publishdate/
|
||||
[`readingtime`]: /methods/page/readingtime/
|
||||
[`schema.html`]: {{% eturl schema %}}
|
||||
[`sitemap`]: /methods/page/sitemap/
|
||||
[`slug`]: /methods/page/slug/
|
||||
[`Summary`]: /methods/page/summary/
|
||||
[`title`]: /methods/page/title/
|
||||
[`translationkey`]: /methods/page/translationkey/
|
||||
[`twitter_cards.html`]: {{% eturl twitter_cards %}}
|
||||
[`type`]: /methods/page/type/
|
||||
[`weight`]: /methods/page/weight/
|
||||
[`wordcount`]: /methods/page/wordcount/
|
||||
[aliases]: /content-management/urls/#aliases
|
||||
[build options]: /content-management/build-options/
|
||||
[cascade]: #cascade-1
|
||||
[configure outputs]: /configuration/outputs/#outputs-per-page
|
||||
[content formats]: /content-management/formats/#classification
|
||||
[embedded templates]: /templates/embedded/
|
||||
[json]: https://www.json.org/
|
||||
[leaf bundles]: /content-management/page-bundles/#leaf-bundles
|
||||
[menus]: /content-management/menus/#define-in-front-matter
|
||||
[output formats]: /configuration/output-formats/
|
||||
[page parameters]: #parameters
|
||||
[page resources]: /content-management/page-resources/#metadata
|
||||
[sitemap templates]: /templates/sitemap/
|
||||
[target a specific template]: /templates/lookup-order/#target-a-template
|
||||
[template lookup order]: /templates/lookup-order/
|
||||
[toml]: https://toml.io/
|
||||
[URL management]: /content-management/urls/#slug
|
||||
[yaml]: https://yaml.org/
|
||||
|
||||
@@ -45,126 +45,123 @@ Whether an equation or expression appears inline, or as a block, depends on the
|
||||
|
||||
Follow these instructions to include mathematical equations and expressions in your Markdown using LaTeX markup.
|
||||
|
||||
### Step 1
|
||||
Step 1
|
||||
: Enable and configure the Goldmark [passthrough extension] in your site configuration. The passthrough extension preserves raw Markdown within delimited snippets of text, including the delimiters themselves.
|
||||
|
||||
Enable and configure the Goldmark [passthrough extension] in your site configuration. The passthrough extension preserves raw Markdown within delimited snippets of text, including the delimiters themselves.
|
||||
{{< code-toggle file=hugo copy=true >}}
|
||||
[markup.goldmark.extensions.passthrough]
|
||||
enable = true
|
||||
|
||||
{{< code-toggle file=hugo copy=true >}}
|
||||
[markup.goldmark.extensions.passthrough]
|
||||
enable = true
|
||||
[markup.goldmark.extensions.passthrough.delimiters]
|
||||
block = [['\[', '\]'], ['$$', '$$']]
|
||||
inline = [['\(', '\)']]
|
||||
|
||||
[markup.goldmark.extensions.passthrough.delimiters]
|
||||
block = [['\[', '\]'], ['$$', '$$']]
|
||||
inline = [['\(', '\)']]
|
||||
[params]
|
||||
math = true
|
||||
{{< /code-toggle >}}
|
||||
|
||||
[params]
|
||||
math = true
|
||||
{{< /code-toggle >}}
|
||||
The configuration above enables mathematical rendering on every page unless you set the `math` parameter to `false` in front matter. To enable mathematical rendering as needed, set the `math` parameter to `false` in your site configuration, and set the `math` parameter to `true` in front matter. Use this parameter in your base template as shown in [Step 3](#step-3).
|
||||
|
||||
The configuration above enables mathematical rendering on every page unless you set the `math` parameter to `false` in front matter. To enable mathematical rendering as needed, set the `math` parameter to `false` in your site configuration, and set the `math` parameter to `true` in front matter. Use this parameter in your base template as shown in [Step 3].
|
||||
> [!note]
|
||||
> The configuration above precludes the use of the `$...$` delimiter pair for inline equations. Although you can add this delimiter pair to the configuration and JavaScript, you must double-escape the `$` symbol when used outside of math contexts to avoid unintended formatting.
|
||||
>
|
||||
> See the [inline delimiters](#inline-delimiters) section for details.
|
||||
|
||||
> [!note]
|
||||
> The configuration above precludes the use of the `$...$` delimiter pair for inline equations. Although you can add this delimiter pair to the configuration and JavaScript, you will need to double-escape the `$` symbol when used outside of math contexts to avoid unintended formatting.
|
||||
>
|
||||
> See the [inline delimiters](#inline-delimiters) section for details.
|
||||
To disable passthrough of inline snippets, omit the `inline` key from the configuration:
|
||||
|
||||
To disable passthrough of inline snippets, omit the `inline` key from the configuration:
|
||||
{{< code-toggle file=hugo >}}
|
||||
[markup.goldmark.extensions.passthrough.delimiters]
|
||||
block = [['\[', '\]'], ['$$', '$$']]
|
||||
{{< /code-toggle >}}
|
||||
|
||||
{{< code-toggle file=hugo >}}
|
||||
[markup.goldmark.extensions.passthrough.delimiters]
|
||||
block = [['\[', '\]'], ['$$', '$$']]
|
||||
{{< /code-toggle >}}
|
||||
You can define your own opening and closing delimiters, provided they match the delimiters that you set in [Step 2].
|
||||
|
||||
You can define your own opening and closing delimiters, provided they match the delimiters that you set in [Step 2].
|
||||
{{< code-toggle file=hugo >}}
|
||||
[markup.goldmark.extensions.passthrough.delimiters]
|
||||
block = [['@@', '@@']]
|
||||
inline = [['@', '@']]
|
||||
{{< /code-toggle >}}
|
||||
|
||||
{{< code-toggle file=hugo >}}
|
||||
[markup.goldmark.extensions.passthrough.delimiters]
|
||||
block = [['@@', '@@']]
|
||||
inline = [['@', '@']]
|
||||
{{< /code-toggle >}}
|
||||
Step 2
|
||||
: Create a _partial_ template to load MathJax or KaTeX. The example below loads MathJax, or you can use KaTeX as described in the [engines](#engines) section.
|
||||
|
||||
### Step 2
|
||||
```go-html-template {file="layouts/_partials/math.html" copy=true}
|
||||
<script id="MathJax-script" async src="https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-chtml.js"></script>
|
||||
<script>
|
||||
MathJax = {
|
||||
tex: {
|
||||
displayMath: [['\\[', '\\]'], ['$$', '$$']], // block
|
||||
inlineMath: [['\\(', '\\)']] // inline
|
||||
},
|
||||
loader:{
|
||||
load: ['ui/safe']
|
||||
},
|
||||
};
|
||||
</script>
|
||||
```
|
||||
|
||||
Create a partial template to load MathJax or KaTeX. The example below loads MathJax, or you can use KaTeX as described in the [engines](#engines) section.
|
||||
The delimiters above must match the delimiters in your site configuration.
|
||||
|
||||
```go-html-template {file="layouts/partials/math.html" copy=true}
|
||||
<script id="MathJax-script" async src="https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-chtml.js"></script>
|
||||
<script>
|
||||
MathJax = {
|
||||
tex: {
|
||||
displayMath: [['\\[', '\\]'], ['$$', '$$']], // block
|
||||
inlineMath: [['\\(', '\\)']] // inline
|
||||
},
|
||||
loader:{
|
||||
load: ['ui/safe']
|
||||
},
|
||||
};
|
||||
</script>
|
||||
```
|
||||
Step 3
|
||||
: Conditionally call the _partial_ template from the base template.
|
||||
|
||||
The delimiters above must match the delimiters in your site configuration.
|
||||
```go-html-template {file="layouts/baseof.html"}
|
||||
<head>
|
||||
...
|
||||
{{ if .Param "math" }}
|
||||
{{ partialCached "math.html" . }}
|
||||
{{ end }}
|
||||
...
|
||||
</head>
|
||||
```
|
||||
|
||||
### Step 3
|
||||
The example above loads the _partial_ template if you have set the `math` parameter in front matter to `true`. If you have not set the `math` parameter in front matter, the conditional statement falls back to the `math` parameter in your site configuration.
|
||||
|
||||
Conditionally call the partial template from the base template.
|
||||
Step 4
|
||||
: If you set the `math` parameter to `false` in your site configuration, you must set the `math` parameter to `true` in front matter. For example:
|
||||
|
||||
```go-html-template {file="layouts/_default/baseof.html"}
|
||||
<head>
|
||||
...
|
||||
{{ if .Param "math" }}
|
||||
{{ partialCached "math.html" . }}
|
||||
{{ end }}
|
||||
...
|
||||
</head>
|
||||
```
|
||||
{{< code-toggle file=content/math-examples.md fm=true >}}
|
||||
title = 'Math examples'
|
||||
date = 2024-01-24T18:09:49-08:00
|
||||
[params]
|
||||
math = true
|
||||
{{< /code-toggle >}}
|
||||
|
||||
The example above loads the partial template if you have set the `math` parameter in front matter to `true`. If you have not set the `math` parameter in front matter, the conditional statement falls back to the `math` parameter in your site configuration.
|
||||
Step 5
|
||||
: Include mathematical equations and expressions in Markdown using LaTeX markup.
|
||||
|
||||
### Step 4
|
||||
```text {file="content/math-examples.md" copy=true}
|
||||
This is an inline \(a^*=x-b^*\) equation.
|
||||
|
||||
Include mathematical equations and expressions in Markdown using LaTeX markup.
|
||||
These are block equations:
|
||||
|
||||
```text {file="content/math-examples.md" copy=true}
|
||||
This is an inline \(a^*=x-b^*\) equation.
|
||||
\[a^*=x-b^*\]
|
||||
|
||||
These are block equations:
|
||||
\[ a^*=x-b^* \]
|
||||
|
||||
\[a^*=x-b^*\]
|
||||
\[
|
||||
a^*=x-b^*
|
||||
\]
|
||||
|
||||
\[ a^*=x-b^* \]
|
||||
These are also block equations:
|
||||
|
||||
\[
|
||||
a^*=x-b^*
|
||||
\]
|
||||
$$a^*=x-b^*$$
|
||||
|
||||
These are also block equations:
|
||||
$$ a^*=x-b^* $$
|
||||
|
||||
$$a^*=x-b^*$$
|
||||
|
||||
$$ a^*=x-b^* $$
|
||||
|
||||
$$
|
||||
a^*=x-b^*
|
||||
$$
|
||||
```
|
||||
|
||||
If you set the `math` parameter to `false` in your site configuration, you must set the `math` parameter to `true` in front matter. For example:
|
||||
|
||||
{{< code-toggle file=content/math-examples.md fm=true >}}
|
||||
title = 'Math examples'
|
||||
date = 2024-01-24T18:09:49-08:00
|
||||
[params]
|
||||
math = true
|
||||
{{< /code-toggle >}}
|
||||
$$
|
||||
a^*=x-b^*
|
||||
$$
|
||||
```
|
||||
|
||||
## Inline delimiters
|
||||
|
||||
The configuration, JavaScript, and examples above use the `\(...\)` delimiter pair for inline equations. The `$...$` delimiter pair is a common alternative, but using it may result in unintended formatting if you use the `$` symbol outside of math contexts.
|
||||
|
||||
If you add the `$...$` delimiter pair to your configuration and JavaScript, you must double-escape the `$` when outside of math contexts, regardless of whether mathematical rendering is enabled on the page. For example:
|
||||
If you add the `$...$` delimiter pair to your configuration and JavaScript, you must double-escape the `$` symbol when used outside of math contexts to avoid unintended formatting. For example:
|
||||
|
||||
```text
|
||||
A \\$5 bill _saved_ is a \\$5 bill _earned_.
|
||||
I will give you \\$2 if you can solve $y = x^2$.
|
||||
```
|
||||
|
||||
> [!note]
|
||||
@@ -179,9 +176,9 @@ MathJax and KaTeX are open-source JavaScript display engines. Both engines are f
|
||||
>
|
||||
>See the [inline delimiters](#inline-delimiters) section for details.
|
||||
|
||||
To use KaTeX instead of MathJax, replace the partial template from [Step 2] with this:
|
||||
To use KaTeX instead of MathJax, replace the _partial_ template from [Step 2] with this:
|
||||
|
||||
```go-html-template {file="layouts/partials/math.html" copy=true}
|
||||
```go-html-template {file="layouts/_partials/math.html" copy=true}
|
||||
<link
|
||||
rel="stylesheet"
|
||||
href="https://cdn.jsdelivr.net/npm/katex@0.16.21/dist/katex.min.css"
|
||||
@@ -227,12 +224,10 @@ $$C_p[\ce{H2O(l)}] = \pu{75.3 J // mol K}$$
|
||||
|
||||
$$C_p[\ce{H2O(l)}] = \pu{75.3 J // mol K}$$
|
||||
|
||||
As shown in [Step 2] above, MathJax supports chemical equations without additional configuration. To add chemistry support to KaTeX, enable the mhchem extension as described in the KaTeX [documentation](https://katex.org/docs/libs).
|
||||
As shown in [Step 2](#step-2) above, MathJax supports chemical equations without additional configuration. To add chemistry support to KaTeX, enable the mhchem extension as described in the KaTeX [documentation](https://katex.org/docs/libs).
|
||||
|
||||
[`transform.ToMath`]: /functions/transform/tomath/
|
||||
[KaTeX]: https://katex.org/
|
||||
[LaTeX]: https://www.latex-project.org/
|
||||
[MathJax]: https://www.mathjax.org/
|
||||
[passthrough extension]: /configuration/markup/#passthrough
|
||||
[Step 2]: #step-2
|
||||
[Step 3]: #step-3
|
||||
|
||||
@@ -68,6 +68,7 @@ Use these properties when defining menu entries in front matter:
|
||||
|
||||
This front matter menu entry demonstrates some of the available properties:
|
||||
|
||||
<!-- markdownlint-disable MD033 -->
|
||||
{{< code-toggle file=content/products/software.md fm=true >}}
|
||||
title = 'Software'
|
||||
[menus.main]
|
||||
@@ -77,6 +78,7 @@ pre = '<i class="fa-solid fa-code"></i>'
|
||||
[menus.main.params]
|
||||
class = 'center'
|
||||
{{< /code-toggle >}}
|
||||
<!-- markdownlint-enable MD033 -->
|
||||
|
||||
Access the entry with `site.Menus.main` in your templates. See [menu templates] for details.
|
||||
|
||||
|
||||
@@ -25,9 +25,9 @@ Considering the following example:
|
||||
The first file is assigned the English language and is linked to the second.
|
||||
The second file is assigned the French language and is linked to the first.
|
||||
|
||||
Their language is __assigned__ according to the language code added as a __suffix to the file name__.
|
||||
Their language is assigned according to the language code added as a suffix to the file name.
|
||||
|
||||
By having the same **path and base file name**, the content pieces are __linked__ together as translated pages.
|
||||
By having the same path and base file name, the content pieces are linked together as translated pages.
|
||||
|
||||
> [!note]
|
||||
> If a file has no language code, it will be assigned the default language.
|
||||
@@ -58,9 +58,9 @@ Considering the following example in conjunction with the configuration above:
|
||||
The first file is assigned the English language and is linked to the second.
|
||||
The second file is assigned the French language and is linked to the first.
|
||||
|
||||
Their language is __assigned__ according to the `content` directory they are __placed__ in.
|
||||
Their language is assigned according to the `content` directory they are placed in.
|
||||
|
||||
By having the same **path and basename** (relative to their language `content` directory), the content pieces are __linked__ together as translated pages.
|
||||
By having the same path and basename (relative to their language `content` directory), the content pieces are linked together as translated pages.
|
||||
|
||||
### Bypassing default linking
|
||||
|
||||
@@ -76,7 +76,7 @@ Considering the following example:
|
||||
translationKey: "about"
|
||||
{{< /code-toggle >}}
|
||||
|
||||
By setting the `translationKey` front matter parameter to `about` in all three pages, they will be __linked__ as translated pages.
|
||||
By setting the `translationKey` front matter parameter to `about` in all three pages, they will be linked as translated pages.
|
||||
|
||||
### Localizing permalinks
|
||||
|
||||
@@ -114,7 +114,7 @@ If, across the linked bundles, two or more files share the same basename, only o
|
||||
|
||||
To create a list of links to translated content, use a template similar to the following:
|
||||
|
||||
```go-html-template {file="layouts/partials/i18nlist.html"}
|
||||
```go-html-template {file="layouts/_partials/i18nlist.html"}
|
||||
{{ if .IsTranslated }}
|
||||
<h4>{{ i18n "translations" }}</h4>
|
||||
<ul>
|
||||
@@ -127,7 +127,7 @@ To create a list of links to translated content, use a template similar to the f
|
||||
{{ end }}
|
||||
```
|
||||
|
||||
The above can be put in a `partial` (i.e., inside `layouts/partials/`) and included in any template. It will not print anything if there are no translations for a given page.
|
||||
The above can be put in a _partial_ template then included in any template. It will not print anything if there are no translations for a given page.
|
||||
|
||||
The above also uses the [`i18n` function][i18func] described in the next section.
|
||||
|
||||
@@ -135,7 +135,7 @@ The above also uses the [`i18n` function][i18func] described in the next section
|
||||
|
||||
`.AllTranslations` on a `Page` can be used to list all translations, including the page itself. On the home page it can be used to build a language navigator:
|
||||
|
||||
```go-html-template {file="layouts/partials/allLanguages.html"}
|
||||
```go-html-template {file="layouts/_partials/allLanguages.html"}
|
||||
<ul>
|
||||
{{ range $.Site.Home.AllTranslations }}
|
||||
<li><a href="{{ .RelPermalink }}">{{ .Language.LanguageName }}</a></li>
|
||||
|
||||
@@ -99,7 +99,7 @@ The [sections] can be nested as deeply as you want. The important thing to under
|
||||
|
||||
### Single pages in sections
|
||||
|
||||
Single content files in each of your sections will be rendered by a [single template]. Here is an example of a single `post` within `posts`:
|
||||
Single content files in each of your sections will be rendered by a [page template]. Here is an example of a single `post` within `posts`:
|
||||
|
||||
```txt
|
||||
path ("posts/my-first-hugo-post.md")
|
||||
@@ -128,7 +128,7 @@ The following concepts provide more insight into the relationship between your p
|
||||
|
||||
### `section`
|
||||
|
||||
A default content type is determined by the section in which a content item is stored. `section` is determined by the location within the project's `content` directory. `section` *cannot* be specified or overridden in front matter.
|
||||
A default content type is determined by the section in which a content item is stored. `section` is determined by the location within the project's `content` directory. `section` cannot be specified or overridden in front matter.
|
||||
|
||||
### `slug`
|
||||
|
||||
@@ -148,4 +148,4 @@ The `url` is the entire URL path, defined by the file path and optionally overri
|
||||
[config]: /configuration/
|
||||
[pretty]: /content-management/urls/#appearance
|
||||
[sections]: /content-management/sections/
|
||||
[single template]: /templates/types/#single
|
||||
[page template]: /templates/types/#page
|
||||
|
||||
@@ -38,10 +38,10 @@ Page bundle characteristics vary by bundle type.
|
||||
|
||||
| | Leaf bundle | Branch bundle |
|
||||
|---------------------|---------------------------------------------------------|---------------------------------------------------------|
|
||||
| Index file | `index.md` | `_index.md` |
|
||||
| Example | `content/about/index.md` | `content/posts/_index.md ` |
|
||||
| Index file | `index.md` | `_index.md` |
|
||||
| Example | `content/about/index.md` | `content/posts/_index.md` |
|
||||
| [Page kinds](g) | `page` | `home`, `section`, `taxonomy`, or `term` |
|
||||
| Template types | [single] | [home], [section], [taxonomy], or [term] |
|
||||
| Template types | [single] | [home], [section], [taxonomy], or [term] |
|
||||
| Descendant pages | None | Zero or more |
|
||||
| Resource location | Adjacent to the index file or in a nested subdirectory | Same as a leaf bundles, but excludes descendant bundles |
|
||||
| [Resource types](g) | `page`, `image`, `video`, etc. | all but `page` |
|
||||
|
||||
@@ -35,10 +35,10 @@ content
|
||||
|
||||
Use any of these methods on a `Page` object to capture page resources:
|
||||
|
||||
- [`Resources.ByType`]
|
||||
- [`Resources.Get`]
|
||||
- [`Resources.GetMatch`]
|
||||
- [`Resources.Match`]
|
||||
- [`Resources.ByType`]
|
||||
- [`Resources.Get`]
|
||||
- [`Resources.GetMatch`]
|
||||
- [`Resources.Match`]
|
||||
|
||||
Once you have captured a resource, use any of the applicable [`Resource`] methods to return a value or perform an action.
|
||||
|
||||
@@ -125,30 +125,32 @@ params
|
||||
|
||||
### Resources metadata example
|
||||
|
||||
<!-- markdownlint-disable MD007 MD032 -->
|
||||
{{< code-toggle file=content/example.md fm=true >}}
|
||||
title: Application
|
||||
date : 2018-01-25
|
||||
resources :
|
||||
- src : "images/sunset.jpg"
|
||||
name : "header"
|
||||
- src : "documents/photo_specs.pdf"
|
||||
title : "Photo Specifications"
|
||||
params:
|
||||
icon : "photo"
|
||||
- src : "documents/guide.pdf"
|
||||
title : "Instruction Guide"
|
||||
- src : "documents/checklist.pdf"
|
||||
title : "Document Checklist"
|
||||
- src : "documents/payment.docx"
|
||||
title : "Proof of Payment"
|
||||
- src : "**.pdf"
|
||||
name : "pdf-file-:counter"
|
||||
params :
|
||||
icon : "pdf"
|
||||
- src : "**.docx"
|
||||
params :
|
||||
icon : "word"
|
||||
date: 2018-01-25
|
||||
resources:
|
||||
- src: images/sunset.jpg
|
||||
name: header
|
||||
- src: documents/photo_specs.pdf
|
||||
title: Photo Specifications
|
||||
params:
|
||||
icon: photo
|
||||
- src: documents/guide.pdf
|
||||
title: Instruction Guide
|
||||
- src: documents/checklist.pdf
|
||||
title: Document Checklist
|
||||
- src: documents/payment.docx
|
||||
title: Proof of Payment
|
||||
- src: "**.pdf"
|
||||
name: pdf-file-:counter
|
||||
params:
|
||||
icon: pdf
|
||||
- src: "**.docx"
|
||||
params:
|
||||
icon: word
|
||||
{{</ code-toggle >}}
|
||||
<!-- markdownlint-enable MD007 MD032 -->
|
||||
|
||||
From the example above:
|
||||
|
||||
@@ -271,12 +273,12 @@ public/
|
||||
|
||||
This approach reduces build times, storage requirements, bandwidth consumption, and deployment times, ultimately reducing cost.
|
||||
|
||||
> [!note]
|
||||
> [!important]
|
||||
> To resolve Markdown link and image destinations to the correct location, you must use link and image render hooks that capture the page resource with the [`Resources.Get`] method, and then invoke its [`RelPermalink`] method.
|
||||
>
|
||||
> By default, with multilingual single-host sites, Hugo enables its [embedded link render hook] and [embedded image render hook] to resolve Markdown link and image destinations.
|
||||
> In its default configuration, Hugo automatically uses the [embedded link render hook] and the [embedded image render hook] for multilingual single-host sites, specifically when the [duplication of shared page resources] feature is disabled. This is the default behavior for such sites. If custom link or image render hooks are defined by your project, modules, or themes, these will be used instead.
|
||||
>
|
||||
> You may override the embedded render hooks as needed, provided they capture the resource as described above.
|
||||
> You can also configure Hugo to `always` use the embedded link or image render hook, use it only as a `fallback`, or `never` use it. See [details](/configuration/markup/#renderhookslinkuseembedded).
|
||||
|
||||
Although duplicating shared page resources is inefficient, you can enable this feature in your site configuration if desired:
|
||||
|
||||
@@ -288,10 +290,10 @@ duplicateResourceFiles = true
|
||||
[`RelPermalink`]: /methods/resource/relpermalink/
|
||||
[`Resource`]: /methods/resource
|
||||
[`Resources.ByType`]: /methods/page/resources#bytype
|
||||
[`Resources.Get`]: /methods/page/resources#get
|
||||
[`Resources.Get`]: /methods/page/resources/#get
|
||||
[`Resources.GetMatch`]: /methods/page/resources#getmatch
|
||||
[`Resources.Match`]: /methods/page/resources#match
|
||||
[content formats]: /content-management/formats/
|
||||
[embedded image render hook]: /render-hooks/images/#default
|
||||
[embedded link render hook]: /render-hooks/links/#default
|
||||
[duplication of shared page resources]: /configuration/markup/#duplicateresourcefiles
|
||||
[embedded image render hook]: /render-hooks/images/#embedded
|
||||
[embedded link render hook]: /render-hooks/links/#embedded
|
||||
|
||||
@@ -12,7 +12,7 @@ Hugo uses a set of factors to identify a page's related content based on front m
|
||||
|
||||
To list up to 5 related pages (which share the same _date_ or _keyword_ parameters) is as simple as including something similar to this partial in your template:
|
||||
|
||||
```go-html-template {file="layouts/partials/related.html" copy=true}
|
||||
```go-html-template {file="layouts/_partials/related.html" copy=true}
|
||||
{{ with site.RegularPages.Related . | first 5 }}
|
||||
<p>Related content:</p>
|
||||
<ul>
|
||||
|
||||
@@ -53,7 +53,7 @@ The example above has two top-level sections: articles and products. None of the
|
||||
|
||||
Sections and non-sections behave differently.
|
||||
|
||||
||Sections|Non-sections
|
||||
|Sections|Non-sections
|
||||
:--|:-:|:-:
|
||||
Directory names become URL segments|:heavy_check_mark:|:heavy_check_mark:
|
||||
Have logical ancestors and descendants|:heavy_check_mark:|:x:
|
||||
@@ -63,7 +63,7 @@ With the file structure from the [example above](#overview):
|
||||
|
||||
1. The list page for the articles section includes all articles, regardless of directory structure; none of the subdirectories are sections.
|
||||
1. The articles/2022 and articles/2023 directories do not have list pages; they are not sections.
|
||||
1. The list page for the products section, by default, includes product-1 and product-2, but not their descendant pages. To include descendant pages, use the `RegularPagesRecursive` method instead of the `Pages` method in the list template.
|
||||
1. The list page for the products section, by default, includes product-1 and product-2, but not their descendant pages. To include descendant pages, use the `RegularPagesRecursive` method instead of the `Pages` method in the _section_ template.
|
||||
1. All directories in the products section have list pages; each directory is a section.
|
||||
|
||||
## Template selection
|
||||
@@ -74,15 +74,15 @@ With the file structure from the [example above](#overview):
|
||||
|
||||
Content directory|Section template
|
||||
:--|:--
|
||||
`content/products`|`layouts/products/list.html`
|
||||
`content/products/product-1`|`layouts/products/list.html`
|
||||
`content/products/product-1/benefits`|`layouts/products/list.html`
|
||||
`content/products`|`layouts/products/section.html`
|
||||
`content/products/product-1`|`layouts/products/section.html`
|
||||
`content/products/product-1/benefits`|`layouts/products/section.html`
|
||||
|
||||
Content directory|Single template
|
||||
Content directory|Page template
|
||||
:--|:--
|
||||
`content/products`|`layouts/products/single.html`
|
||||
`content/products/product-1`|`layouts/products/single.html`
|
||||
`content/products/product-1/benefits`|`layouts/products/single.html`
|
||||
`content/products`|`layouts/products/page.html`
|
||||
`content/products/product-1`|`layouts/products/page.html`
|
||||
`content/products/product-1/benefits`|`layouts/products/page.html`
|
||||
|
||||
If you need to use a different template for a subsection, specify `type` and/or `layout` in front matter.
|
||||
|
||||
@@ -98,7 +98,7 @@ The content file (benefit-1.md) has four ancestors: benefits, product-1, product
|
||||
|
||||
For example, use the `.Ancestors` method to render breadcrumb navigation.
|
||||
|
||||
```go-html-template {file="layouts/partials/breadcrumb.html"}
|
||||
```go-html-template {file="layouts/_partials/breadcrumb.html"}
|
||||
<nav aria-label="breadcrumb" class="breadcrumb">
|
||||
<ol>
|
||||
{{ range .Ancestors.Reverse }}
|
||||
|
||||
@@ -20,9 +20,9 @@ Hugo's embedded shortcodes are pre-defined templates within the application. Ref
|
||||
|
||||
## Custom
|
||||
|
||||
Create custom shortcodes to simplify and standardize content creation. For example, the following shortcode template generates an audio player using a [global resource](g):
|
||||
Create custom shortcodes to simplify and standardize content creation. For example, the following _shortcode_ template generates an audio player using a [global resource](g):
|
||||
|
||||
```go-html-template {file="layouts/shortcodes/audio.html"}
|
||||
```go-html-template {file="layouts/_shortcodes/audio.html"}
|
||||
{{ with resources.Get (.Get "src") }}
|
||||
<audio controls preload="auto" src="{{ .RelPermalink }}"></audio>
|
||||
{{ end }}
|
||||
@@ -38,11 +38,11 @@ Learn more about creating shortcodes in the [shortcode templates] section.
|
||||
|
||||
## Inline
|
||||
|
||||
An inline shortcode is a shortcode template defined within content.
|
||||
An inline shortcode is a _shortcode_ template defined within content.
|
||||
|
||||
Hugo's security model is based on the premise that template and configuration authors are trusted, but content authors are not. This model enables generation of HTML output safe against code injection.
|
||||
|
||||
To conform with this security model, creating shortcode templates within content is disabled by default. If you trust your content authors, you can enable this functionality in your site's configuration:
|
||||
To conform with this security model, creating _shortcode_ templates within content is disabled by default. If you trust your content authors, you can enable this functionality in your site's configuration:
|
||||
|
||||
{{< code-toggle file=hugo >}}
|
||||
[security]
|
||||
@@ -69,7 +69,7 @@ In the example above, the inline shortcode is executed twice: once upon definiti
|
||||
<p>Today is Thursday, January 30, 2025</p>
|
||||
```
|
||||
|
||||
Inline shortcodes process their inner content within the same context as regular shortcode templates, allowing you to use any available [shortcode method].
|
||||
Inline shortcodes process their inner content within the same context as regular _shortcode_ templates, allowing you to use any available [shortcode method].
|
||||
|
||||
> [!note]
|
||||
> You cannot [nest](#nesting) inline shortcodes.
|
||||
@@ -179,9 +179,9 @@ Hugo processes the shortcode before the page content is rendered by the Markdown
|
||||
|
||||
With standard notation, Hugo processes the shortcode separately, merging the output into the page content after Markdown rendering. This means, for instance, that Markdown headings inside a standard-notation shortcode will be excluded when invoking the `TableOfContents` method on the `Page` object.
|
||||
|
||||
By way of example, with this shortcode template:
|
||||
By way of example, with this _shortcode_ template:
|
||||
|
||||
```go-html-template {file="layouts/shortcodes/foo.html"}
|
||||
```go-html-template {file="layouts/_shortcodes/foo.html"}
|
||||
{{ .Inner }}
|
||||
```
|
||||
|
||||
|
||||
@@ -32,7 +32,7 @@ Let's assume you are making a website about movies. You may want to include the
|
||||
- Year
|
||||
- Awards
|
||||
|
||||
Then, in each of the movies, you would specify terms for each of these taxonomies (i.e., in the [front matter] of each of your movie content files). From these terms, Hugo would automatically create pages for each Actor, Director, Studio, Genre, Year, and Award, with each listing all of the Movies that matched that specific Actor, Director, Studio, Genre, Year, and Award.
|
||||
Then, in each of the movies, you would specify terms for each of these taxonomies (i.e., in the front matter of each of your movie content files). From these terms, Hugo would automatically create pages for each Actor, Director, Studio, Genre, Year, and Award, with each listing all of the Movies that matched that specific Actor, Director, Studio, Genre, Year, and Award.
|
||||
|
||||
### Movie taxonomy organization
|
||||
|
||||
@@ -71,10 +71,10 @@ Moonrise Kingdom <- Value
|
||||
|
||||
### Default destinations
|
||||
|
||||
When taxonomies are used---and [taxonomy templates] are provided---Hugo will automatically create both a page listing all the taxonomy's terms and individual pages with lists of content associated with each term. For example, a `categories` taxonomy declared in your configuration and used in your content front matter will create the following pages:
|
||||
When taxonomies are used Hugo will automatically create both a page listing all the taxonomy's terms and individual pages with lists of content associated with each term. For example, a `categories` taxonomy declared in your configuration and used in your content front matter will create the following pages:
|
||||
|
||||
- A single page at `example.com/categories/` that lists all the terms within the taxonomy
|
||||
- [Individual taxonomy list pages][taxonomy templates] (e.g., `/categories/development/`) for each of the terms that shows a listing of all pages marked as part of that taxonomy within any content file's [front matter]
|
||||
- Individual taxonomy list pages (e.g., `/categories/development/`) for each of the terms that shows a listing of all pages marked as part of that taxonomy within any content file's front matter
|
||||
|
||||
## Configuration
|
||||
|
||||
@@ -92,7 +92,7 @@ categories = ['Category A','Category B']
|
||||
|
||||
## Order taxonomies
|
||||
|
||||
A content file can assign weight for each of its associate taxonomies. Taxonomic weight can be used for sorting or ordering content in [taxonomy templates] and is declared in a content file's [front matter]. The convention for declaring taxonomic weight is `taxonomyname_weight`.
|
||||
A content file can assign weight for each of its associate taxonomies. Taxonomic weight can be used for sorting or ordering content in taxonomy templates and is declared in a content file's front matter. The convention for declaring taxonomic weight is `taxonomyname_weight`.
|
||||
|
||||
The following show a piece of content that has a weight of 22, which can be used for ordering purposes when rendering the pages assigned to the "a", "b" and "c" values of the `tags` taxonomy. It has also been assigned the weight of 44 when rendering the "d" category page.
|
||||
|
||||
@@ -108,18 +108,73 @@ categories_weight = 44
|
||||
|
||||
By using taxonomic weight, the same piece of content can appear in different positions in different taxonomies.
|
||||
|
||||
## Add custom metadata to a taxonomy or term
|
||||
## Metadata
|
||||
|
||||
If you need to add custom metadata to your taxonomy terms, you will need to create a page for that term at `/content/<TAXONOMY>/<TERM>/_index.md` and add your metadata in its front matter. Continuing with our 'Actors' example, let's say you want to add a Wikipedia page link to each actor. Your terms pages would be something like this:
|
||||
Display metadata about each term by creating a corresponding branch bundle in the `content` directory.
|
||||
|
||||
{{< code-toggle file=content/actors/bruce-willis/_index.md fm=true >}}
|
||||
title: "Bruce Willis"
|
||||
wikipedia: "https://en.wikipedia.org/wiki/Bruce_Willis"
|
||||
For example, create an "authors" taxonomy:
|
||||
|
||||
{{< code-toggle file=hugo >}}
|
||||
[taxonomies]
|
||||
author = 'authors'
|
||||
{{< /code-toggle >}}
|
||||
|
||||
[content section]: /content-management/sections/
|
||||
[content type]: /content-management/types/
|
||||
[documentation on archetypes]: /content-management/archetypes/
|
||||
[front matter]: /content-management/front-matter/
|
||||
[taxonomy templates]: /templates/types/#taxonomy
|
||||
[site configuration]: /configuration/
|
||||
Then create content with one [branch bundle](g) for each term:
|
||||
|
||||
```text
|
||||
content/
|
||||
└── authors/
|
||||
├── jsmith/
|
||||
│ ├── _index.md
|
||||
│ └── portrait.jpg
|
||||
└── rjones/
|
||||
├── _index.md
|
||||
└── portrait.jpg
|
||||
```
|
||||
|
||||
Then add front matter to each term page:
|
||||
|
||||
{{< code-toggle file=content/authors/jsmith/_index.md fm=true >}}
|
||||
title = "John Smith"
|
||||
affiliation = "University of Chicago"
|
||||
{{< /code-toggle >}}
|
||||
|
||||
Then create a _taxonomy_ template specific to the "authors" taxonomy:
|
||||
|
||||
```go-html-template {file="layouts/authors/taxonomy.html"}
|
||||
{{ define "main" }}
|
||||
<h1>{{ .Title }}</h1>
|
||||
{{ .Content }}
|
||||
{{ range .Data.Terms.Alphabetical }}
|
||||
<h2><a href="{{ .Page.RelPermalink }}">{{ .Page.LinkTitle }}</a></h2>
|
||||
<p>Affiliation: {{ .Page.Params.Affiliation }}</p>
|
||||
{{ with .Page.Resources.Get "portrait.jpg" }}
|
||||
{{ with .Fill "100x100" }}
|
||||
<img src="{{ .RelPermalink }}" width="{{ .Width }}" height="{{ .Height }}" alt="portrait">
|
||||
{{ end }}
|
||||
{{ end }}
|
||||
{{ end }}
|
||||
{{ end }}
|
||||
```
|
||||
|
||||
In the example above we list each author including their affiliation and portrait.
|
||||
|
||||
Or create a _term_ template specific to the "authors" taxonomy:
|
||||
|
||||
```go-html-template {file="layouts/authors/term.html"}
|
||||
{{ define "main" }}
|
||||
<h1>{{ .Title }}</h1>
|
||||
<p>Affiliation: {{ .Params.affiliation }}</p>
|
||||
{{ with .Resources.Get "portrait.jpg" }}
|
||||
{{ with .Fill "100x100" }}
|
||||
<img src="{{ .RelPermalink }}" width="{{ .Width }}" height="{{ .Height }}" alt="portrait">
|
||||
{{ end }}
|
||||
{{ end }}
|
||||
{{ .Content }}
|
||||
{{ range .Pages }}
|
||||
<h2><a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a></h2>
|
||||
{{ end }}
|
||||
{{ end }}
|
||||
```
|
||||
|
||||
In the example above we display the author including their affiliation and portrait, then a list of associated content.
|
||||
|
||||
@@ -1,14 +0,0 @@
|
||||
---
|
||||
title: Content types
|
||||
description: Hugo is built around content organized in sections.
|
||||
categories: []
|
||||
keywords: []
|
||||
aliases: [/content/types]
|
||||
---
|
||||
|
||||
A **content type** is a way to organize your content. Hugo resolves the content type from either the `type` in front matter or, if not set, the first directory in the file path. E.g. `content/blog/my-first-event.md` will be of type `blog` if no `type` is set.
|
||||
|
||||
A content type is used to
|
||||
|
||||
- Determine how the content is rendered. See [Template Lookup Order](/templates/lookup-order/) and [Content Views](/templates/content-view) for more.
|
||||
- Determine which [archetype](/content-management/archetypes/) template to use for new content.
|
||||
@@ -20,7 +20,7 @@ You can change the structure and appearance of URLs with front matter values and
|
||||
|
||||
### `slug`
|
||||
|
||||
Set the `slug` in front matter to override the last segment of the path. The `slug` value does not affect section pages.
|
||||
Set the `slug` in front matter to override the last segment of the path. This front matter field is not applicable to `home`, `section`, `taxonomy`, or `term` pages.
|
||||
|
||||
{{< code-toggle file=content/posts/post-1.md fm=true >}}
|
||||
title = 'My First Post'
|
||||
@@ -39,6 +39,7 @@ Set the `url` in front matter to override the entire path. Use this with either
|
||||
|
||||
> [!note]
|
||||
> Hugo does not sanitize the `url` front matter field, allowing you to generate:
|
||||
>
|
||||
> - File paths that contain characters reserved by the operating system. For example, file paths on Windows may not contain any of these [reserved characters]. Hugo throws an error if a file path includes a character reserved by the current operating system.
|
||||
> - URLs that contain disallowed characters. For example, the less than sign (`<`) is not allowed in a URL.
|
||||
|
||||
@@ -108,7 +109,7 @@ multilingual|`about`|`https://example.org/de/about/`
|
||||
|
||||
{{< new-in 0.131.0 />}}
|
||||
|
||||
You can also usetokens when setting the `url` value. This is typically used in `cascade` sections:
|
||||
You can also use tokens when setting the `url` value. This is typically used in `cascade` sections:
|
||||
|
||||
{{< code-toggle file=content/foo/bar/_index.md fm=true >}}
|
||||
title ="Bar"
|
||||
|
||||
@@ -46,99 +46,89 @@ To build the extended or extended/deploy edition from source you must:
|
||||
|
||||
Use this workflow to create and submit pull requests.
|
||||
|
||||
### Step 1
|
||||
Step 1
|
||||
: Fork the [project repository].
|
||||
|
||||
Fork the [project repository].
|
||||
Step 2
|
||||
: Clone your fork.
|
||||
|
||||
### Step 2
|
||||
Step 3
|
||||
: Create a new branch with a descriptive name that includes the corresponding issue number.
|
||||
|
||||
Clone your fork.
|
||||
For a new feature:
|
||||
|
||||
### Step 3
|
||||
```sh
|
||||
git checkout -b feat/implement-some-feature-99999
|
||||
```
|
||||
|
||||
Create a new branch with a descriptive name that includes the corresponding issue number.
|
||||
For a bug fix:
|
||||
|
||||
For a new feature:
|
||||
```sh
|
||||
git checkout -b fix/fix-some-bug-99999
|
||||
```
|
||||
|
||||
```sh
|
||||
git checkout -b feat/implement-some-feature-99999
|
||||
```
|
||||
Step 4
|
||||
: Make changes.
|
||||
|
||||
For a bug fix:
|
||||
Step 5
|
||||
: Compile and install.
|
||||
|
||||
```sh
|
||||
git checkout -b fix/fix-some-bug-99999
|
||||
```
|
||||
To compile and install the standard edition:
|
||||
|
||||
### Step 4
|
||||
```text
|
||||
go install
|
||||
```
|
||||
|
||||
Make changes.
|
||||
To compile and install the extended edition:
|
||||
|
||||
### Step 5
|
||||
```text
|
||||
CGO_ENABLED=1 go install -tags extended
|
||||
```
|
||||
|
||||
Compile and install.
|
||||
To compile and install the extended/deploy edition:
|
||||
|
||||
To compile and install the standard edition:
|
||||
```text
|
||||
CGO_ENABLED=1 go install -tags extended,withdeploy
|
||||
```
|
||||
|
||||
```text
|
||||
go install
|
||||
```
|
||||
Step 6
|
||||
: Test your changes:
|
||||
|
||||
To compile and install the extended edition:
|
||||
```text
|
||||
go test ./...
|
||||
```
|
||||
|
||||
```text
|
||||
CGO_ENABLED=1 go install -tags extended
|
||||
```
|
||||
Step 7
|
||||
: Commit your changes with a descriptive commit message:
|
||||
|
||||
To compile and install the extended/deploy edition:
|
||||
- Provide a summary on the first line, typically 50 characters or less, followed by a blank line.
|
||||
- Begin the summary with one of content, theme, config, all, or misc, followed by a colon, a space, and a brief description of the change beginning with a capital letter
|
||||
- Use imperative present tense
|
||||
- See the [commit message guidelines] for requirements
|
||||
- Optionally, provide a detailed description where each line is 72 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.
|
||||
|
||||
```text
|
||||
CGO_ENABLED=1 go install -tags extended,withdeploy
|
||||
```
|
||||
For example:
|
||||
|
||||
### Step 6
|
||||
```sh
|
||||
git commit -m "tpl/strings: Create wrap function
|
||||
|
||||
Test your changes:
|
||||
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.
|
||||
|
||||
```text
|
||||
go test ./...
|
||||
```
|
||||
Fixes #99998
|
||||
Closes #99999"
|
||||
```
|
||||
|
||||
### Step 7
|
||||
Step 8
|
||||
: Push the new branch to your fork of the documentation repository.
|
||||
|
||||
Commit your changes with a descriptive commit message:
|
||||
Step 9
|
||||
: Visit the [project repository] and create a pull request (PR).
|
||||
|
||||
- Provide a summary on the first line, typically 50 characters or less, followed by a blank line.
|
||||
- Begin the summary with one of content, theme, config, all, or misc, followed by a colon, a space, and a brief description of the change beginning with a capital letter
|
||||
- Use imperative present tense
|
||||
- See the [commit message guidelines] for requirements
|
||||
- Optionally, provide a detailed description where each line is 72 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.
|
||||
|
||||
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"
|
||||
```
|
||||
|
||||
### 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.
|
||||
Step 10
|
||||
: A project maintainer will review your PR and may request changes. You may delete your branch after the maintainer merges your PR.
|
||||
|
||||
## Building from source
|
||||
|
||||
@@ -153,7 +143,7 @@ CGO_ENABLED=1 go install -tags extended github.com/gohugoio/hugo@latest
|
||||
To build and install a specific release:
|
||||
|
||||
```sh
|
||||
CGO_ENABLED=1 go install -tags extended github.com/gohugoio/hugo@v0.144.2
|
||||
CGO_ENABLED=1 go install -tags extended github.com/gohugoio/hugo@v0.148.0
|
||||
```
|
||||
|
||||
To build and install at the latest commit on the master branch:
|
||||
@@ -165,7 +155,7 @@ CGO_ENABLED=1 go install -tags extended github.com/gohugoio/hugo@master
|
||||
To build and install at a specific commit:
|
||||
|
||||
```sh
|
||||
CGO_ENABLED=1 go install -tags extended github.com/gohugoio/hugo@0851c17
|
||||
CGO_ENABLED=1 go install -tags extended github.com/gohugoio/hugo@c0d9beb
|
||||
```
|
||||
|
||||
[bugs]: https://github.com/gohugoio/hugo/issues?q=is%3Aopen+is%3Aissue+label%3ABug
|
||||
|
||||
@@ -70,6 +70,22 @@ Link to the [glossary] as needed and use terms consistently. Pay particular atte
|
||||
- "Markdown" (capitalized)
|
||||
- "open-source" (hyphenated adjective)
|
||||
|
||||
### Template types
|
||||
|
||||
When you refer to a template type, italicize it:
|
||||
|
||||
```text
|
||||
When creating a _taxonomy_ template, do this...
|
||||
```
|
||||
|
||||
However, if the template type is also a link, do not italicize it to avoid distracting formatting:
|
||||
|
||||
```text
|
||||
When creating a [taxonomy] template, do this...
|
||||
```
|
||||
|
||||
Do not italicize the template type in a title, heading, or front matter description.
|
||||
|
||||
### Titles and headings
|
||||
|
||||
- Use sentence-style capitalization.
|
||||
@@ -152,26 +168,27 @@ This example demonstrates the minimum required front matter fields.
|
||||
|
||||
If quotation marks are required, prefer single quotes to double quotes when possible.
|
||||
|
||||
Seq|Field|Description|Required
|
||||
--:|:--|:--|:--
|
||||
1|`title`|The page title|:heavy_check_mark:|
|
||||
2|`linkTitle`|A short version of the page title||
|
||||
3|`description`|A complete sentence describing the page|:heavy_check_mark:|
|
||||
4|`categories`|An array of terms in the categories taxonomy|:heavy_check_mark: [^1]|
|
||||
5|`keywords`|An array of keywords used to identify related content|:heavy_check_mark: [^1]|
|
||||
6|`publishDate`|Applicable to news items: the publication date||
|
||||
7|`params.altTitle`|An alternate title: used in the "see also" panel if provided||
|
||||
8|`params.functions_and_methods.aliases`|Applicable to function and method pages: an array of alias names||
|
||||
9|`params.functions_and_methods.returnType`|Applicable to function and method pages: the data type returned||
|
||||
10|`params.functions_and_methods.signatures`|Applicable to function and method pages: an array of signatures||
|
||||
11|`params.hide_in_this_section`|Whether to hide the "in this section" panel||
|
||||
12|`params.minversion`|Applicable to the quick start page: the minimum Hugo version required||
|
||||
13|`params.permalink`|Reserved for use by the news content adapter||
|
||||
14|`params.reference (used in glossary term)`|Applicable to glossary entries: a URL for additional information||
|
||||
15|`params.show_publish_date`|Whether to show the `publishDate` when rendering the page||
|
||||
16|`weight`|The page weight||
|
||||
17|`aliases`|Previous URLs used to access this page||
|
||||
18|`expirydate`|The expiration date||
|
||||
Field|Description|Required
|
||||
:--|:--|:--
|
||||
`title`|The page title|:heavy_check_mark:
|
||||
`linkTitle`|A short version of the page title|
|
||||
`description`|A complete sentence describing the page|:heavy_check_mark:
|
||||
`categories`|An array of terms in the categories taxonomy|:heavy_check_mark: [^1]
|
||||
`keywords`|An array of keywords used to identify related content|:heavy_check_mark: [^1]
|
||||
`publishDate`|Applicable to news items: the publication date|
|
||||
`params.alt_title`|An alternate title: used in the "see also" panel if provided|
|
||||
`params.functions_and_methods.aliases`|Applicable to function and method pages: an array of alias names|
|
||||
`params.functions_and_methods.returnType`|Applicable to function and method pages: the data type returned|
|
||||
`params.functions_and_methods.signatures`|Applicable to function and method pages: an array of signatures|
|
||||
`params.hide_in_this_section`|Whether to hide the "in this section" panel|
|
||||
`params.minversion`|Applicable to the quick start page: the minimum Hugo version required|
|
||||
`params.permalink`|Reserved for use by the news content adapter|
|
||||
`params.reference (used in glossary term)`|Applicable to glossary entries: a URL for additional information|
|
||||
`params.searchable`|Whether to add the content of this page to the search index. The default value is cascaded down from the site configuration; `true` if the page kind is `page`, and `false` if the page kind is one of `home`, `section`, `taxonomy`, or `term`. Add this field to override the default value.|
|
||||
`params.show_publish_date`|Whether to show the `publishDate` when rendering the page|
|
||||
`weight`|The page weight|
|
||||
`aliases`|Previous URLs used to access this page|
|
||||
`expirydate`|The expiration date|
|
||||
|
||||
[^1]: The field is required, but its data is not.
|
||||
|
||||
@@ -185,13 +202,13 @@ If the title in the "See also" sidebar is ambiguous or the same as another page,
|
||||
title = "Long descriptive title"
|
||||
linkTitle = "Short title"
|
||||
[params]
|
||||
altTitle = "Whatever you want"
|
||||
alt_title = "Whatever you want"
|
||||
{{< /code-toggle >}}
|
||||
|
||||
Use of the alternate title is limited to the "See also" sidebar.
|
||||
|
||||
> [!note]
|
||||
> Think carefully before setting the `altTitle`. Use it only when absolutely necessary.
|
||||
> Think carefully before setting the `alt_title`. Use it only when absolutely necessary.
|
||||
|
||||
## Code examples
|
||||
|
||||
@@ -223,10 +240,10 @@ erroneous lexing/highlighting of shortcode calls.
|
||||
```
|
||||
````
|
||||
|
||||
To include a filename header and copy-to-clipboard button:
|
||||
To include a file name header and copy-to-clipboard button:
|
||||
|
||||
````text
|
||||
```go-html-template {file="layouts/partials/foo.html" copy=true}
|
||||
```go-html-template {file="layouts/_partials/foo.html" copy=true}
|
||||
{{ if eq $foo "bar" }}
|
||||
{{ print "foo is bar" }}
|
||||
{{ end }}
|
||||
@@ -236,7 +253,7 @@ To include a filename header and copy-to-clipboard button:
|
||||
To wrap the code block within an initially-opened `details` element using a non-default summary:
|
||||
|
||||
````text
|
||||
```go-html-template {details=true open=true summary="layouts/partials/foo.html" copy=true}
|
||||
```go-html-template {details=true open=true summary="layouts/_partials/foo.html" copy=true}
|
||||
{{ if eq $foo "bar" }}
|
||||
{{ print "foo is bar" }}
|
||||
{{ end }}
|
||||
@@ -328,8 +345,6 @@ Limiting the number of callout types helps us to use them consistently.
|
||||
> [!important]
|
||||
> Key information users need to know to achieve their goal.
|
||||
|
||||
|
||||
|
||||
## Shortcodes
|
||||
|
||||
These shortcodes are commonly used throughout the documentation. Other shortcodes are available for specialized use.
|
||||
@@ -427,7 +442,7 @@ Use the [new-in shortcode](#new-in) to indicate a new feature:
|
||||
{{</* new-in 0.144.0 */>}}
|
||||
```
|
||||
|
||||
The "new in" label will be hidden if the specified version is older than a predefined threshold, based on differences in major and minor versions. See [details](https://github.com/gohugoio/hugoDocs/blob/master/_vendor/github.com/gohugoio/gohugoioTheme/layouts/shortcodes/new-in.html).
|
||||
The "new in" label will be hidden if the specified version is older than a predefined threshold, based on differences in major and minor versions. See [details](https://github.com/gohugoio/hugoDocs/blob/master/_vendor/github.com/gohugoio/gohugoioTheme/layouts/_shortcodes/new-in.html).
|
||||
|
||||
## Deprecated features
|
||||
|
||||
@@ -456,75 +471,65 @@ Set the `expiryDate` to two years from the date of deprecation, and add a brief
|
||||
|
||||
Use this workflow to create and submit pull requests.
|
||||
|
||||
### Step 1
|
||||
Step 1
|
||||
: Fork the [documentation repository].
|
||||
|
||||
Fork the [documentation repository].
|
||||
Step 2
|
||||
: Clone your fork.
|
||||
|
||||
### Step 2
|
||||
Step 3
|
||||
: Create a new branch with a descriptive name that includes the corresponding issue number, if any:
|
||||
|
||||
Clone your fork.
|
||||
```sh
|
||||
git checkout -b restructure-foo-page-99999
|
||||
```
|
||||
|
||||
### Step 3
|
||||
Step 4
|
||||
: Make changes.
|
||||
|
||||
Create a new branch with a descriptive name that includes the corresponding issue number, if any:
|
||||
Step 5
|
||||
: Build the site locally to preview your changes.
|
||||
|
||||
```sh
|
||||
git checkout -b restructure-foo-page-99999
|
||||
```
|
||||
Step 6
|
||||
: Commit your changes with a descriptive commit message:
|
||||
|
||||
### Step 4
|
||||
- Provide a summary on the first line, typically 50 characters or less, followed by a blank line.
|
||||
- Begin the summary with one of `content`, `theme`, `config`, `all`, or `misc`, followed by a colon, a space, and a brief description of the change beginning with a capital letter
|
||||
- Use imperative present tense
|
||||
- Optionally, provide a detailed description where each line is 72 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.
|
||||
|
||||
Make changes.
|
||||
For example:
|
||||
|
||||
### Step 5
|
||||
```text
|
||||
git commit -m "content: Restructure the taxonomy page
|
||||
|
||||
Build the site locally to preview your changes.
|
||||
This restructures the taxonomy page by splitting topics into logical
|
||||
sections, each with one or more examples.
|
||||
|
||||
### Step 6
|
||||
Fixes #9999
|
||||
Closes #9998"
|
||||
```
|
||||
|
||||
Commit your changes with a descriptive commit message:
|
||||
Step 7
|
||||
: Push the new branch to your fork of the documentation repository.
|
||||
|
||||
- Provide a summary on the first line, typically 50 characters or less, followed by a blank line.
|
||||
- Begin the summary with one of `content`, `theme`, `config`, `all`, or `misc`, followed by a colon, a space, and a brief description of the change beginning with a capital letter
|
||||
- Use imperative present tense
|
||||
- Optionally, provide a detailed description where each line is 72 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.
|
||||
Step 8
|
||||
: Visit the [documentation repository] and create a pull request (PR).
|
||||
|
||||
For example:
|
||||
Step 9
|
||||
: A project maintainer will review your PR and may request changes. You may delete your branch after the maintainer merges your PR.
|
||||
|
||||
```text
|
||||
git commit -m "content: Restructure the taxonomy page
|
||||
|
||||
This restructures the taxonomy page by splitting topics into logical
|
||||
sections, each with one or more examples.
|
||||
|
||||
Fixes #9999
|
||||
Closes #9998"
|
||||
```
|
||||
|
||||
### Step 7
|
||||
|
||||
Push the new branch to your fork of the documentation repository.
|
||||
|
||||
### Step 8
|
||||
|
||||
Visit the [documentation repository] and create a pull request (PR).
|
||||
|
||||
### Step 9
|
||||
|
||||
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
|
||||
[basic english]: https://simple.wikipedia.org/wiki/Basic_English
|
||||
[ATX]: https://spec.commonmark.org/current/#atx-headings
|
||||
[basic english]: https://simple.wikipedia.org/wiki/Basic_English
|
||||
[developer documentation style guide]: https://developers.google.com/style
|
||||
[documentation repository]: https://github.com/gohugoio/hugoDocs/
|
||||
[fenced code blocks]: https://spec.commonmark.org/0.30/#fenced-code-blocks
|
||||
[fenced code blocks]: https://spec.commonmark.org/current/#fenced-code-blocks
|
||||
[glossary]: /quick-reference/glossary/
|
||||
[indented code blocks]: https://spec.commonmark.org/0.30/#indented-code-blocks
|
||||
[indented code blocks]: https://spec.commonmark.org/current/#indented-code-blocks
|
||||
[issues]: https://github.com/gohugoio/hugoDocs/issues
|
||||
[list items]: https://spec.commonmark.org/0.30/#list-items
|
||||
[list items]: https://spec.commonmark.org/current/#list-items
|
||||
[project repository]: https://github.com/gohugoio/hugo
|
||||
[raw HTML]: https://spec.commonmark.org/0.30/#raw-html
|
||||
[raw HTML]: https://spec.commonmark.org/current/#raw-html
|
||||
[related content]: /content-management/related-content/
|
||||
[setext]: https://spec.commonmark.org/0.30/#setext-heading
|
||||
[setext]: https://spec.commonmark.org/current/#setext-heading
|
||||
|
||||
@@ -3,6 +3,8 @@ title: Hugo Documentation
|
||||
linkTitle: Docs
|
||||
description: Hugo is the world's fastest static website engine. It's written in Go (aka Golang) and developed by bep, spf13 and friends.
|
||||
layout: list
|
||||
params:
|
||||
searchable: false
|
||||
---
|
||||
|
||||
<!--
|
||||
|
||||
@@ -12,8 +12,18 @@ aliases: [/functions/shuffle]
|
||||
---
|
||||
|
||||
```go-html-template
|
||||
{{ shuffle (seq 1 2 3) }} → [3 1 2]
|
||||
{{ shuffle (slice "a" "b" "c") }} → [b a c]
|
||||
{{ collections.Shuffle (slice "a" "b" "c") }} → [b a c]
|
||||
```
|
||||
|
||||
The result will vary from one build to the next.
|
||||
|
||||
To render an unordered list of 5 random pages from a page collection:
|
||||
|
||||
```go-html-template
|
||||
<ul>
|
||||
{{ $p := site.RegularPages }}
|
||||
{{ range $p | collections.Shuffle | first 5 }}
|
||||
<li><a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a></li>
|
||||
{{ end }}
|
||||
</ul>
|
||||
```
|
||||
|
||||
@@ -22,46 +22,41 @@ params:
|
||||
|
||||
Follow the steps below to transform CSS using any of the available [PostCSS plugins].
|
||||
|
||||
### Step 1
|
||||
Step 1
|
||||
: Install [Node.js].
|
||||
|
||||
Install [Node.js].
|
||||
Step 2
|
||||
: Install the required Node.js packages in the root of your project. For example, to add vendor prefixes to your CSS rules:
|
||||
|
||||
### Step 2
|
||||
```sh
|
||||
npm i -D postcss postcss-cli autoprefixer
|
||||
```
|
||||
|
||||
Install the required Node.js packages in the root of your project. For example, to add vendor prefixes to your CSS rules:
|
||||
Step 3
|
||||
: Create a PostCSS configuration file in the root of your project.
|
||||
|
||||
```sh
|
||||
npm i -D postcss postcss-cli autoprefixer
|
||||
```
|
||||
```js {file="postcss.config.js"}
|
||||
module.exports = {
|
||||
plugins: [
|
||||
require('autoprefixer')
|
||||
]
|
||||
};
|
||||
```
|
||||
|
||||
### Step 3
|
||||
> [!note]
|
||||
> If you are a Windows user, and the path to your project contains a space, you must place the PostCSS configuration within the package.json file. See [this example] and issue [#7333].
|
||||
|
||||
Create a PostCSS configuration file in the root of your project.
|
||||
Step 4
|
||||
: Place your CSS file within the `assets/css` directory.
|
||||
|
||||
```js {file="postcss.config.js"}
|
||||
module.exports = {
|
||||
plugins: [
|
||||
require('autoprefixer')
|
||||
]
|
||||
};
|
||||
```
|
||||
Step 5
|
||||
: Process the resource with PostCSS:
|
||||
|
||||
> [!note]
|
||||
> If you are a Windows user, and the path to your project contains a space, you must place the PostCSS configuration within the package.json file. See [this example] and issue [#7333].
|
||||
|
||||
### Step 4
|
||||
|
||||
Place your CSS file within the `assets/css` directory.
|
||||
|
||||
### Step 5
|
||||
|
||||
Process the resource with PostCSS:
|
||||
|
||||
```go-html-template
|
||||
{{ with resources.Get "css/main.css" | postCSS }}
|
||||
<link rel="stylesheet" href="{{ .RelPermalink }}">
|
||||
{{ end }}
|
||||
```
|
||||
```go-html-template
|
||||
{{ with resources.Get "css/main.css" | postCSS }}
|
||||
<link rel="stylesheet" href="{{ .RelPermalink }}">
|
||||
{{ end }}
|
||||
```
|
||||
|
||||
## Options
|
||||
|
||||
|
||||
@@ -66,20 +66,20 @@ vars
|
||||
```go-html-template {copy=true}
|
||||
{{ with resources.Get "sass/main.scss" }}
|
||||
{{ $opts := dict
|
||||
"enableSourceMap" (not hugo.IsProduction)
|
||||
"outputStyle" (cond hugo.IsProduction "compressed" "expanded")
|
||||
"enableSourceMap" hugo.IsDevelopment
|
||||
"outputStyle" (cond hugo.IsDevelopment "expanded" "compressed")
|
||||
"targetPath" "css/main.css"
|
||||
"transpiler" "dartsass"
|
||||
"vars" site.Params.styles
|
||||
"includePaths" (slice "node_modules/bootstrap/scss")
|
||||
}}
|
||||
{{ with . | toCSS $opts }}
|
||||
{{ if hugo.IsProduction }}
|
||||
{{ if hugo.IsDevelopment }}
|
||||
<link rel="stylesheet" href="{{ .RelPermalink }}">
|
||||
{{ else }}
|
||||
{{ with . | fingerprint }}
|
||||
<link rel="stylesheet" href="{{ .RelPermalink }}" integrity="{{ .Data.Integrity }}" crossorigin="anonymous">
|
||||
{{ end }}
|
||||
{{ else }}
|
||||
<link rel="stylesheet" href="{{ .RelPermalink }}">
|
||||
{{ end }}
|
||||
{{ end }}
|
||||
{{ end }}
|
||||
@@ -113,7 +113,7 @@ macOS|Homebrew|[brew.sh]|`brew install sass/sass/sass`
|
||||
Windows|Chocolatey|[chocolatey.org]|`choco install sass`
|
||||
Windows|Scoop|[scoop.sh]|`scoop install sass`
|
||||
|
||||
You may also install [prebuilt binaries] for Linux, macOS, and Windows.
|
||||
You may also install [prebuilt binaries] for Linux, macOS, and Windows. You must install the prebuilt binary outside of your project directory and ensure its path is included in your system's PATH environment variable.
|
||||
|
||||
Run `hugo env` to list the active transpilers.
|
||||
|
||||
@@ -122,83 +122,31 @@ Run `hugo env` to list the active transpilers.
|
||||
|
||||
### Installing in a production environment
|
||||
|
||||
For [CI/CD](g) deployments (e.g., GitHub Pages, GitLab Pages, Netlify, etc.) you must edit the workflow to install Dart Sass before Hugo builds the site[^2]. Some providers allow you to use one of the package managers above, or you can download and extract one of the prebuilt binaries.
|
||||
To use Dart Sass with Hugo on a CI/CD platform like GitHub Pages, GitLab Pages, or Netlify, you typically must modify your build workflow to install Dart Sass before the Hugo site build begins. This is because these platforms don't have Dart Sass pre-installed, and Hugo needs it to process your Sass files.
|
||||
|
||||
[^2]: You do not have to do this if (a) you have not modified the assets cache location, and (b) you have not set `useResourceCacheWhen` to `never` in your [site configuration], and (c) you add and commit your `resources` directory to your repository.
|
||||
There's one key exception where you can skip this step: you have committed your `resources` directory to your repository. This is only possible if:
|
||||
|
||||
#### GitHub Pages
|
||||
- You have not changed Hugo's default asset cache location.
|
||||
- You have not set [`useResourceCacheWhen`] to never in your sites configuration.
|
||||
|
||||
To install Dart Sass for your builds on GitHub Pages, add this step to the GitHub Pages workflow file:
|
||||
By committing the `resources` directory, you're providing the pre-built CSS files directly to your CI/CD service, so it doesn't need to run the Sass compilation itself.
|
||||
|
||||
```yaml
|
||||
- name: Install Dart Sass
|
||||
run: sudo snap install dart-sass
|
||||
```
|
||||
For examples of how to install Dart Sass in a production environment, see the following workflow files:
|
||||
|
||||
#### GitLab Pages
|
||||
|
||||
To install Dart Sass for your builds on GitLab Pages, the `.gitlab-ci.yml` file should look something like this:
|
||||
|
||||
```yaml
|
||||
variables:
|
||||
HUGO_VERSION: 0.144.2
|
||||
DART_SASS_VERSION: 1.85.0
|
||||
GIT_DEPTH: 0
|
||||
GIT_STRATEGY: clone
|
||||
GIT_SUBMODULE_STRATEGY: recursive
|
||||
TZ: America/Los_Angeles
|
||||
image:
|
||||
name: golang:1.20-buster
|
||||
pages:
|
||||
script:
|
||||
# Install Dart Sass
|
||||
- curl -LJO https://github.com/sass/dart-sass/releases/download/${DART_SASS_VERSION}/dart-sass-${DART_SASS_VERSION}-linux-x64.tar.gz
|
||||
- tar -xf dart-sass-${DART_SASS_VERSION}-linux-x64.tar.gz
|
||||
- cp -r dart-sass/* /usr/local/bin
|
||||
- rm -rf dart-sass*
|
||||
# Install Hugo
|
||||
- curl -LJO https://github.com/gohugoio/hugo/releases/download/v${HUGO_VERSION}/hugo_extended_${HUGO_VERSION}_linux-amd64.deb
|
||||
- apt install -y ./hugo_extended_${HUGO_VERSION}_linux-amd64.deb
|
||||
- rm hugo_extended_${HUGO_VERSION}_linux-amd64.deb
|
||||
# Build
|
||||
- hugo --gc --minify
|
||||
artifacts:
|
||||
paths:
|
||||
- public
|
||||
rules:
|
||||
- if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
|
||||
```
|
||||
|
||||
#### Netlify
|
||||
|
||||
To install Dart Sass for your builds on Netlify, the `netlify.toml` file should look something like this:
|
||||
|
||||
```toml
|
||||
[build.environment]
|
||||
HUGO_VERSION = "0.144.2"
|
||||
DART_SASS_VERSION = "1.85.0"
|
||||
NODE_VERSION = "22"
|
||||
TZ = "America/Los_Angeles"
|
||||
|
||||
[build]
|
||||
publish = "public"
|
||||
command = """\
|
||||
curl -LJO https://github.com/sass/dart-sass/releases/download/${DART_SASS_VERSION}/dart-sass-${DART_SASS_VERSION}-linux-x64.tar.gz && \
|
||||
tar -xf dart-sass-${DART_SASS_VERSION}-linux-x64.tar.gz && \
|
||||
rm dart-sass-${DART_SASS_VERSION}-linux-x64.tar.gz && \
|
||||
export PATH=/opt/build/repo/dart-sass:$PATH && \
|
||||
hugo --gc --minify \
|
||||
"""
|
||||
```
|
||||
- [GitHub Pages]
|
||||
- [GitLab Pages]
|
||||
- [Netlify]
|
||||
|
||||
[`publishDir`]: /configuration/all/#publishdir
|
||||
[`useResourceCacheWhen`]: /configuration/build/#useresourcecachewhen
|
||||
[brew.sh]: https://brew.sh/
|
||||
[chocolatey.org]: https://community.chocolatey.org/packages/sass
|
||||
[dart sass]: https://sass-lang.com/dart-sass
|
||||
[GitHub Pages]: /host-and-deploy/host-on-github-pages/#step-7
|
||||
[GitLab Pages]: /host-and-deploy/host-on-gitlab-pages/#configure-gitlab-cicd
|
||||
[libsass]: https://sass-lang.com/libsass
|
||||
[Netlify]: /host-and-deploy/host-on-netlify/#configuration-file
|
||||
[prebuilt binaries]: https://github.com/sass/dart-sass/releases/latest
|
||||
[scoop.sh]: https://scoop.sh/#/apps?q=sass
|
||||
[site configuration]: /configuration/build/
|
||||
[snap package]: /installation/linux/#snap
|
||||
[snapcraft.io]: https://snapcraft.io/dart-sass
|
||||
[starter workflow]: https://github.com/actions/starter-workflows/blob/main/pages/hugo.yml
|
||||
[`publishDir`]: /configuration/all/#publishdir
|
||||
|
||||
@@ -18,110 +18,87 @@ Use the `css.TailwindCSS` function to process your Tailwind CSS files. This func
|
||||
1. Compile those utility classes into standard CSS.
|
||||
1. Generate an optimized CSS output file.
|
||||
|
||||
> [!caution]
|
||||
> Tailwind CSS v4.0 and later requires a relatively [modern browser](https://tailwindcss.com/docs/compatibility#browser-support) to render correctly.
|
||||
> [!note]
|
||||
> Use this function with Tailwind CSS v4.0 and later, which require a relatively [modern browser] to render correctly.
|
||||
|
||||
[modern browser]: https://tailwindcss.com/docs/compatibility#browser-support
|
||||
|
||||
## Setup
|
||||
|
||||
### Step 1
|
||||
Step 1
|
||||
: Install the Tailwind CSS CLI v4.0 or later:
|
||||
|
||||
Install the Tailwind CSS CLI v4.0 or later:
|
||||
```sh {copy=true}
|
||||
npm install --save-dev tailwindcss @tailwindcss/cli
|
||||
```
|
||||
|
||||
```sh
|
||||
npm install --save-dev tailwindcss @tailwindcss/cli
|
||||
```
|
||||
The Tailwind CSS CLI is also available as a [standalone executable]. You must install it outside of your project directory and ensure its path is included in your system's `PATH` environment variable.
|
||||
|
||||
The TailwindCSS CLI is also available as a [standalone executable] if you want to use it without installing Node.js.
|
||||
[standalone executable]: https://github.com/tailwindlabs/tailwindcss/releases/latest
|
||||
|
||||
[standalone executable]: https://github.com/tailwindlabs/tailwindcss/releases/latest
|
||||
Step 2
|
||||
: Add this to your site configuration:
|
||||
|
||||
### Step 2
|
||||
{{< code-toggle file=hugo copy=true >}}
|
||||
[build]
|
||||
[build.buildStats]
|
||||
enable = true
|
||||
[[build.cachebusters]]
|
||||
source = 'assets/notwatching/hugo_stats\.json'
|
||||
target = 'css'
|
||||
[[build.cachebusters]]
|
||||
source = '(postcss|tailwind)\.config\.js'
|
||||
target = 'css'
|
||||
[module]
|
||||
[[module.mounts]]
|
||||
source = 'assets'
|
||||
target = 'assets'
|
||||
[[module.mounts]]
|
||||
disableWatch = true
|
||||
source = 'hugo_stats.json'
|
||||
target = 'assets/notwatching/hugo_stats.json'
|
||||
{{< /code-toggle >}}
|
||||
|
||||
Add this to your site configuration:
|
||||
Step 3
|
||||
: Create a CSS entry file:
|
||||
|
||||
{{< code-toggle file=hugo copy=true >}}
|
||||
[[module.mounts]]
|
||||
source = "assets"
|
||||
target = "assets"
|
||||
[[module.mounts]]
|
||||
source = "hugo_stats.json"
|
||||
target = "assets/notwatching/hugo_stats.json"
|
||||
disableWatch = true
|
||||
[build.buildStats]
|
||||
enable = true
|
||||
[[build.cachebusters]]
|
||||
source = "assets/notwatching/hugo_stats\\.json"
|
||||
target = "css"
|
||||
[[build.cachebusters]]
|
||||
source = "(postcss|tailwind)\\.config\\.js"
|
||||
target = "css"
|
||||
{{< /code-toggle >}}
|
||||
```css {file="assets/css/main.css" copy=true}
|
||||
@import "tailwindcss";
|
||||
@source "hugo_stats.json";
|
||||
```
|
||||
|
||||
### Step 3
|
||||
Tailwind CSS respects `.gitignore` files. This means that if `hugo_stats.json` is listed in your `.gitignore` file, Tailwind CSS will ignore it. To make `hugo_stats.json` available to Tailwind CSS you must explicitly source it as shown in the example above.
|
||||
|
||||
Create a CSS entry file:
|
||||
Step 4
|
||||
: Create a _partial_ template to process the CSS with the Tailwind CSS CLI:
|
||||
|
||||
```css {file="assets/css/main.css" copy=true}
|
||||
@import "tailwindcss";
|
||||
@source "hugo_stats.json";
|
||||
```
|
||||
|
||||
Tailwind CSS respects `.gitignore` files. This means that if `hugo_stats.json` is listed in your `.gitignore` file, Tailwind CSS will ignore it. To make `hugo_stats.json` available to Tailwind CSS you must explicitly source it as shown in the example above.
|
||||
|
||||
### Step 4
|
||||
|
||||
Create a partial template to process the CSS with the Tailwind CSS CLI:
|
||||
|
||||
```go-html-template {file="layouts/partials/css.html" copy=true}
|
||||
{{ with (templates.Defer (dict "key" "global")) }}
|
||||
```go-html-template {file="layouts/_partials/css.html" copy=true}
|
||||
{{ with resources.Get "css/main.css" }}
|
||||
{{ $opts := dict
|
||||
"minify" hugo.IsProduction
|
||||
"inlineImports" true
|
||||
}}
|
||||
{{ $opts := dict "minify" (not hugo.IsDevelopment) }}
|
||||
{{ with . | css.TailwindCSS $opts }}
|
||||
{{ if hugo.IsProduction }}
|
||||
{{ if hugo.IsDevelopment }}
|
||||
<link rel="stylesheet" href="{{ .RelPermalink }}">
|
||||
{{ else }}
|
||||
{{ with . | fingerprint }}
|
||||
<link rel="stylesheet" href="{{ .RelPermalink }}" integrity="{{ .Data.Integrity }}" crossorigin="anonymous">
|
||||
{{ end }}
|
||||
{{ else }}
|
||||
<link rel="stylesheet" href="{{ .RelPermalink }}">
|
||||
{{ end }}
|
||||
{{ end }}
|
||||
{{ end }}
|
||||
{{ end }}
|
||||
```
|
||||
```
|
||||
|
||||
### Step 5
|
||||
Step 5
|
||||
: Call the _partial_ template from your base template, deferring template execution until after all sites and output formats have been rendered:
|
||||
|
||||
Call the partial template from your base template:
|
||||
|
||||
```go-html-template {file="layouts/_default/baseof.html"}
|
||||
<head>
|
||||
...
|
||||
{{ partialCached "css.html" . }}
|
||||
...
|
||||
<head>
|
||||
```
|
||||
|
||||
### Step 6
|
||||
|
||||
Optionally create a `tailwind.config.js` file in the root of your project as shown below. This is necessary if you use the [Tailwind CSS IntelliSense
|
||||
extension] for Visual Studio Code.
|
||||
|
||||
[Tailwind CSS IntelliSense
|
||||
extension]: https://marketplace.visualstudio.com/items?itemName=bradlc.vscode-tailwindcss
|
||||
|
||||
```js {file="tailwind.config.js" copy=true}
|
||||
/*
|
||||
This file is present to satisfy a requirement of the Tailwind CSS IntelliSense
|
||||
extension for Visual Studio Code.
|
||||
|
||||
https://marketplace.visualstudio.com/items?itemName=bradlc.vscode-tailwindcss
|
||||
|
||||
The rest of this file is intentionally empty.
|
||||
*/
|
||||
```
|
||||
```go-html-template {file="layouts/baseof.html" copy=true}
|
||||
<head>
|
||||
...
|
||||
{{ with (templates.Defer (dict "key" "global")) }}
|
||||
{{ partial "css.html" . }}
|
||||
{{ end }}
|
||||
...
|
||||
</head>
|
||||
```
|
||||
|
||||
## Options
|
||||
|
||||
@@ -131,8 +108,9 @@ minify
|
||||
optimize
|
||||
: (`bool`) Whether to optimize the output without minifying. Default is `false`.
|
||||
|
||||
inlineImports
|
||||
: (`bool`) Whether to enable inlining of `@import` statements. Inlining is performed recursively, but currently once only per file. It is not possible to import the same file in different scopes (root, media query, etc.). Note that this import routine does not care about the CSS specification, so you can have `@import` statements anywhere in the file. Default is `false`.
|
||||
disableInlineImports
|
||||
: {{< new-in 0.147.4 />}}
|
||||
: (`bool`) Whether to disable inlining of `@import` statements. Inlining is performed recursively, but currently once only per file. It is not possible to import the same file in different scopes (root, media query, etc.). Note that this import routine does not care about the CSS specification, so you can have `@import` statements anywhere in the file. Default is `false`.
|
||||
|
||||
skipInlineImportsNotFound
|
||||
: (`bool`) Whether to allow the build process to continue despite unresolved import statements, preserving the original import declarations. It is important to note that the inline importer does not process URL-based imports or those with media queries, and these will remain unaltered even when this option is disabled. Default is `false`.
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user