t.Parallel()
files := `
--- config.toml --
+-- hugo.toml --
defaultContentLanguage = 'it'
-- layouts/home.html --
{{ $dates := slice
--- /dev/null
+// Copyright 2025 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 hugolib
+
+import (
+ "strings"
+ "testing"
+)
+
+func TestLegacyConfigDotToml(t *testing.T) {
+ const filesTemplate = `
+-- config.toml --
+title = "My Site"
+-- layouts/home.html --
+Site: {{ .Site.Title }}
+
+ `
+ t.Run("In root", func(t *testing.T) {
+ t.Parallel()
+ files := filesTemplate
+ b := Test(t, files)
+ b.AssertFileContent("public/index.html", "Site: My Site")
+ })
+
+ t.Run("In config dir", func(t *testing.T) {
+ t.Parallel()
+ files := strings.Replace(filesTemplate, "-- config.toml --", "-- config/_default/config.toml --", 1)
+ b := Test(t, files)
+ b.AssertFileContent("public/index.html", "Site: My Site")
+ })
+}
-// Copyright 2025-present The Hugo Authors. All rights reserved.
+// Copyright 2025 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.
t.Parallel()
files := `
--- config.toml --
+-- hugo.toml --
[markup]
defaultMarkdownHandler = 'blackfriday'
-- content/_index.md --
c := qt.New(t)
files := `
--- config.toml --
+-- hugo.toml --
title = "Integration Test"
disableKinds=["page", "section", "taxonomy", "term", "sitemap", "robotsTXT", "RSS"]
-- layouts/home.html --
t.Parallel()
files := `
--- config.toml --
+-- hugo.toml --
timeZone = "America/Los_Angeles"
-- content/_index.md --
---
t.Parallel()
files := `
--- config.toml --
+-- hugo.toml --
baseURL="https://example.org"
[module]
rnd := rand.New(rand.NewSource(32))
files := `
--- config.toml --
+-- hugo.toml --
baseURL = "https://example.com"
defaultContentLanguage = 'en'
t.Parallel()
files := `
--- config.toml --
+-- hugo.toml --
baseURL = 'https://example.org/'
title = 'Issue-9073'
defaultContentLanguageInSubdir = true
t.Parallel()
files := `
--- config.toml --
+-- hugo.toml --
titleCaseStyle = 'none'
-- content/books/book-1.md --
---
t.Parallel()
files := `
--- config.toml --
+-- hugo.toml --
baseURL = 'https://example.org/'
languageCode = 'en-us'
title = 'Hugo Forum Topic #37225'
t.Parallel()
files := `
--- config.toml --
+-- hugo.toml --
disableKinds = ['RSS','sitemap','taxonomy','term']
[[menu.main]]
name = 'Home'
func TestPageHashString(t *testing.T) {
files := `
--- config.toml --
+-- hugo.toml --
baseURL = "https://example.org"
[languages]
[languages.en]
t.Parallel()
files := `
--- config.toml --
+-- hugo.toml --
baseURL = "https://example.com/"
-- content/p1.md --
-- content/p2.md --
t.Parallel()
filesTemplate := `
--- config.toml --
+-- hugo.toml --
title = "Hugo Rocks!"
enableInlineShortcodes = true
-- content/p1/index.md --
t.Parallel()
files := `
--- config.toml --
+-- hugo.toml --
-- layouts/_shortcodes/myshort.html --
Page Kind: {{ .Page.Kind }}
-- layouts/home.html --
t.Parallel()
files := `
--- config.toml --
+-- hugo.toml --
timeout = '300ms'
-- content/p1.md --
---
t.Parallel()
files := `
--- config.toml --
+-- hugo.toml --
disableKinds = ['RSS','sitemap','taxonomy','term']
[params]
mainSections=["a", "b"]
t.Parallel()
files := `
--- config.toml --
+-- hugo.toml --
disableKinds = ['RSS','sitemap','taxonomy','term']
mainSections=["a", "b"]
[params]
t.Parallel()
files := `
--- config.toml --
+-- hugo.toml --
disableKinds = ['RSS','sitemap','taxonomy','term']
-- content/mysect/page1.md --
-- layouts/home.html --
t.Parallel()
files := `
--- config.toml --
+-- hugo.toml --
[module]
[[module.imports]]
path = "mytheme"
t.Parallel()
files := `
--- config.toml --
+-- hugo.toml --
-- content/_index.md --
---
title: "Home"
t.Parallel()
files := `
--- config.toml --
+-- hugo.toml --
disableKinds = ['RSS','sitemap','taxonomy','term','page','section']
defaultContentLanguage = 'es'
defaultContentLanguageInSubdir = true
t.Parallel()
files := `
--- config.toml --
+-- hugo.toml --
-- i18n/en.toml --
[description]
other = 'This is a description from i18n.'
t.Parallel()
files := `
--- config.toml --
+-- hugo.toml --
[markup]
[markup.highlight]
anchorLineNos = false
t.Parallel()
files := `
--- config.toml --
+-- hugo.toml --
[markup]
[markup.highlight]
anchorLineNos = false
t.Parallel()
files := `
--- config.toml --
+-- hugo.toml --
-- layouts/_markup/render-codeblock.html --
{{ .Position | safeHTML }}
-- layouts/single.html --
t.Parallel()
files := `
--- config.toml --
+-- hugo.toml --
-- content/p1.md --
---
title: "p1"
t.Parallel()
files := `
--- config.toml --
+-- hugo.toml --
-- content/p1.md --
---
title: "p1"
t.Parallel()
files := `
--- config.toml --
+-- hugo.toml --
-- content/p1.md --
---
title: "p1"
t.Parallel()
files := `
--- config.toml --
+-- hugo.toml --
-- content/p1.md --
---
title: "p1"
func TestPanics(t *testing.T) {
files := `
--- config.toml --
+-- hugo.toml --
[markup]
[markup.goldmark]
[markup.goldmark.parser]
t.Parallel()
files := `
--- config.toml --
+-- hugo.toml --
[markup.goldmark.renderer]
unsafe = false
[markup.goldmark.parser.attribute]
t.Parallel()
files := `
--- config.toml --
+-- hugo.toml --
-- content/p1.md --
---
title: "p1"
t.Parallel()
files := `
--- config.toml --
+-- hugo.toml --
[markup]
[markup.highlight]
anchorLineNos = false
func BenchmarkRenderHooks(b *testing.B) {
files := `
--- config.toml --
+-- hugo.toml --
-- layouts/_markup/render-heading.html --
<h{{ .Level }} id="{{ .Anchor | safeURL }}">
{{ .Text }}
func BenchmarkCodeblocks(b *testing.B) {
filesTemplate := `
--- config.toml --
+-- hugo.toml --
[markup]
[markup.highlight]
anchorLineNos = false
for _, renderFunc := range []string{"markdownify", ".Page.RenderString"} {
t.Run(renderFunc, func(t *testing.T) {
files := `
--- config.toml --
+-- hugo.toml --
-- layouts/_markup/render-link.html --
<a href="{{ .Destination | safeURL }}">{{ .Text | RENDERFUNC }}</a>
-- layouts/single.html --
t.Parallel()
files := `
--- config.toml --
+-- hugo.toml --
[markup.goldmark.extensions]
typographer = false
-- content/p1.md --
runTest := func(protocol string, withHook bool) *hugolib.IntegrationTestBuilder {
files := `
--- config.toml --
+-- hugo.toml --
[markup.goldmark]
[markup.goldmark.extensions]
linkify = true
t.Parallel()
files := `
--- config.toml --
+-- hugo.toml --
[markup.goldmark.renderer]
unsafe = true
-- content/p1.md --
t.Parallel()
files := `
--- config.toml --
+-- hugo.toml --
enableEmoji = true
-- content/p1.md --
---
t.Parallel()
files := `
--- config.toml --
+-- hugo.toml --
enableEmoji = false
-- content/p1.md --
---
t.Parallel()
files := `
--- config.toml --
+-- hugo.toml --
[minify]
minifyOutput = true
[minify.tdewolff.html]
t.Parallel()
files := `
--- config.toml --
+-- hugo.toml --
[markup.goldmark.extensions.passthrough]
enable = true
[markup.goldmark.extensions.passthrough.delimiters]
t.Parallel()
files := `
--- config.toml --
+-- hugo.toml --
[markup.goldmark.extensions.passthrough]
enable = true
[markup.goldmark.extensions.passthrough.delimiters]
t.Parallel()
files := `
--- config.toml --
+-- hugo.toml --
[markup.goldmark.extensions.passthrough]
enable = true
[markup.goldmark.extensions.passthrough.delimiters]
t.Parallel()
filesTemplate := `
--- config.toml --
+-- hugo.toml --
[markup.goldmark.renderer]
unsafe = false
[markup.goldmark.parser]
t.Parallel()
files := `
--- config.toml --
+-- hugo.toml --
[markup.goldmark.extensions.passthrough]
enable = true
[markup.goldmark.extensions.passthrough.delimiters]
t.Parallel()
files := `
--- config.toml --
+-- hugo.toml --
[markup]
[markup.highlight]
codeFences = true
t.Parallel()
files := `
--- config.toml --
+-- hugo.toml --
[markup.highlight]
noClasses = false
-- content/_index.md --
t.Parallel()
files := `
--- config.toml --
+-- hugo.toml --
[markup.highlight]
noClasses = false
wrapperClass = "highlight no-prose"
func BenchmarkRelatedSite(b *testing.B) {
files := `
--- config.toml --
+-- hugo.toml --
baseURL = "http://example.com/"
disableKinds = ["taxonomy", "term", "RSS", "sitemap", "robotsTXT"]
[related]
func TestGroupByLocalizedDate(t *testing.T) {
files := `
--- config.toml --
+-- hugo.toml --
defaultContentLanguage = 'en'
defaultContentLanguageInSubdir = true
[languages]
func TestPagesSortCollation(t *testing.T) {
files := `
--- config.toml --
+-- hugo.toml --
defaultContentLanguage = 'en'
defaultContentLanguageInSubdir = true
[languages]
func TestGetRemoteHead(t *testing.T) {
files := `
--- config.toml --
+-- hugo.toml --
[security]
[security.http]
methods = ['(?i)GET|POST|HEAD']
func TestGetRemoteResponseHeaders(t *testing.T) {
files := `
--- config.toml --
+-- hugo.toml --
[security]
[security.http]
methods = ['(?i)GET|POST|HEAD']
module.exports = {
presets: ["@babel/preset-env"],
};
--- config.toml --
+-- hugo.toml --
disablekinds = ['taxonomy', 'term', 'page']
[security]
[security.exec]
@apply text-2xl font-bold;
}
--- config.toml --
+-- hugo.toml --
disablekinds = ['taxonomy', 'term', 'page']
baseURL = "https://example.com"
[build]
c := qt.New(t)
mainWithImport := `
--- config.toml --
+-- hugo.toml --
disableKinds=["page", "section", "taxonomy", "term", "sitemap", "robotsTXT"]
disableLiveReload = true
-- assets/js/main.js --
c := qt.New(t)
files := `
--- config.toml --
+-- hugo.toml --
baseURL = "https://example.org"
disableKinds=["page", "section", "taxonomy", "term", "sitemap", "robotsTXT"]
[module]
}
let user = [0, 1, 2];
document.body.textContent = greeter(user);
--- config.toml --
+-- hugo.toml --
disablekinds = ['taxonomy', 'term', 'page']
-- content/p1.md --
Content.
c := qt.New(t)
filesTemplate := `
--- config.toml --
+-- hugo.toml --
disableKinds=["page", "section", "taxonomy", "term", "sitemap", "robotsTXT"]
-- assets/js/main.js --
// A comment.
files := `
-- assets/js/test.js --
new Date(2002, 04, 11)
--- config.toml --
+-- hugo.toml --
-- layouts/home.html --
{{ $js := resources.Get "js/test.js" | minify }}
<script>
t.Parallel()
files := `
--- config.toml --
+-- hugo.toml --
baseURL = "http://example.com/blog"
defaultContentLanguage = "fr"
defaultContentLanguageInSubdir = true
moo {
color: $moolor;
}
--- config.toml --
+-- hugo.toml --
-- layouts/home.html --
{{ $cssOpts := (dict "includePaths" (slice "node_modules/foo") "transpiler" "dartsass" ) }}
{{ $r := resources.Get "scss/main.scss" | toCSS $cssOpts | minify }}
/* foo */
-- assets/scss/regular.css --
--- config.toml --
+-- hugo.toml --
-- layouts/home.html --
{{ $r := resources.Get "scss/main.scss" | toCSS (dict "transpiler" "dartsass") }}
T1: {{ $r.Content | safeHTML }}
@import "moo";
/* foo */
--- config.toml --
+-- hugo.toml --
-- layouts/home.html --
{{ $r := resources.Get "scss/main.scss" | toCSS (dict "transpiler" "dartsass") }}
T1: {{ $r.Content | safeHTML }}
-- layouts/home.html --
{{- $opts := dict "transpiler" "dartsass" }}
{{- with resources.Get "main.scss" | toCSS $opts }}{{ .Content | safeHTML }}{{ end }}
--- config.toml --
+-- hugo.toml --
disableKinds = ['RSS','sitemap','taxonomy','term','page','section']
[[module.mounts]]
moo {
color: $moolor;
}
--- config.toml --
+-- hugo.toml --
theme = 'mytheme'
-- layouts/home.html --
{{ $cssOpts := (dict "includePaths" (slice "node_modules/foo" ) "transpiler" "dartsass" ) }}
@warn "foo";
@debug "bar";
--- config.toml --
+-- hugo.toml --
disableKinds = ["term", "taxonomy", "section", "page"]
-- layouts/home.html --
{{ $cssOpts := (dict "transpiler" "dartsass" ) }}
c := qt.New(t)
const filesTemplate = `
--- config.toml --
+-- hugo.toml --
-- assets/scss/components/_foo.scss --
/* comment line 1 */
$foocolor: #ccc;
}
files := `
--- config.toml --
+-- hugo.toml --
[params]
[params.sassvars]
color1 = "blue"
}
files := `
--- config.toml --
+-- hugo.toml --
disableKinds = ["term", "taxonomy", "section", "page"]
[params]
moo {
color: $moolor;
}
--- config.toml --
+-- hugo.toml --
-- layouts/home.html --
{{ $cssOpts := (dict "includePaths" (slice "node_modules/foo") "transpiler" "dartsass" ) }}
{{ $r := resources.Get "scss/main.scss" | toCSS $cssOpts | minify }}
moo {
color: $moolor;
}
--- config.toml --
+-- hugo.toml --
-- layouts/home.html --
{{ $cssOpts := (dict "includePaths" (slice "node_modules/foo") ) }}
{{ $r := resources.Get "scss/main.scss" | toCSS $cssOpts | minify }}
/* foo */
-- assets/scss/regular.css --
--- config.toml --
+-- hugo.toml --
-- layouts/home.html --
{{ $r := resources.Get "scss/main.scss" | toCSS }}
T1: {{ $r.Content | safeHTML }}
moo {
color: $moolor;
}
--- config.toml --
+-- hugo.toml --
theme = 'mytheme'
-- layouts/home.html --
{{ $cssOpts := (dict "includePaths" (slice "node_modules/foo" ) ) }}
c := qt.New(t)
const filesTemplate = `
--- config.toml --
+-- hugo.toml --
theme = 'mytheme'
-- assets/scss/components/_foo.scss --
/* comment line 1 */
t.Parallel()
files := `
--- config.toml --
+-- hugo.toml --
disableLiveReload = true
baseURL = "https://example.org"
-- content/mybundle/index.md --
t.Parallel()
files := `
--- config.toml --
+-- hugo.toml --
-- assets/circle.svg --
<svg height="100" width="100"><circle cx="50" cy="50" r="40" stroke="black" stroke-width="3" fill="red" /></svg>
-- layouts/home.html --
t.Parallel()
files := `
--- config.toml --
+-- hugo.toml --
disableKinds = ['section','rss','sitemap','taxonomy','term']
-- layouts/home.html --
{{- range site.RegularPages.GroupByParamDate "eventDate" "2006-01" }}
t.Parallel()
files := `
--- config.toml --
+-- hugo.toml --
baseURL = 'http://example.com/'
-- layouts/home.html --
{{ apply (seq 3) "partial" "foo.html"}}
t.Parallel()
files := `
--- config.toml --
+-- hugo.toml --
-- layouts/home.html --
{{ $values := slice (dict "a" 1 "b" 2) (dict "a" 3 "b" 1) (dict "a" 2 "b" 0) (dict "a" 1 "b" 0) (dict "a" 3 "b" 1) (dict "a" 2 "b" 2) (dict "a" 2 "b" 1) (dict "a" 0 "b" 3) (dict "a" 3 "b" 3) (dict "a" 0 "b" 0) (dict "a" 0 "b" 0) (dict "a" 2 "b" 0) (dict "a" 1 "b" 2) (dict "a" 1 "b" 1) (dict "a" 3 "b" 0) (dict "a" 2 "b" 0) (dict "a" 3 "b" 0) (dict "a" 3 "b" 0) (dict "a" 3 "b" 0) (dict "a" 3 "b" 1) }}
Asc: {{ sort (sort $values "b" "asc") "a" "asc" }}
t.Parallel()
files := `
--- config.toml --
+-- hugo.toml --
baseURL = 'http://example.com/'
-- layouts/home.html --
Home: {{ range where site.RegularPages "WordCount" "gt" 50 }}{{ .Title }}|{{ end }}
t.Parallel()
files := `
--- config.toml --
+-- hugo.toml --
disableKinds = ['rss','sitemap', 'taxonomy', 'term', 'page']
-- layouts/home.html --
{{ $a := resources.Match "*a*" }}
t.Parallel()
files := `
--- config.toml --
+-- hugo.toml --
theme = "mytheme"
-- myproject.txt --
Hello project!
).Build()
b.AssertFileContent("public/index.html", `
-START:|config.toml|myproject.txt|:END:
+START:|hugo.toml|myproject.txt|:END:
`)
}
t.Parallel()
files := `
--- config.toml --
+-- hugo.toml --
-- layouts/home.html --
{{ $fi := (readFile "doesnotexist") }}
{{ if $fi }}Failed{{ else }}OK{{ end }}
t.Parallel()
filesTemplate := `
--- config.toml --
+-- hugo.toml --
baseURL = 'http://example.com/'
disableKinds = ["taxonomy", "term"]
enableInlineShortcodes = true
t.Parallel()
files := `
--- config.toml --
+-- hugo.toml --
baseURL = 'http://example.com/'
disableKinds = ["taxonomy", "term"]
-- content/p1.md --
t.Parallel()
files := `
--- config.toml --
+-- hugo.toml --
baseURL = 'http://example.com/'
-- layouts/home.html --
partial: {{ partials.Include "foo.html" . }}
t.Parallel()
files := `
--- config.toml --
+-- hugo.toml --
baseURL = 'http://example.com/'
-- layouts/home.html --
partialCached: {{ partials.IncludeCached "foo.html" . }}
t.Parallel()
files := `
--- config.toml --
+-- hugo.toml --
baseURL = 'http://example.com/'
-- layouts/home.html --
{{ partials.IncludeCached "p1.html" . }}
t.Parallel()
files := `
--- config.toml --
+-- hugo.toml --
baseURL = 'http://example.com/'
-- content/_index.md --
---
t.Parallel()
files := `
--- config.toml --
+-- hugo.toml --
baseURL = 'http://example.com/'
templateMetrics=true
templateMetricsHints=true
// gobench --package ./tpl/partials
func BenchmarkIncludeCached(b *testing.B) {
files := `
--- config.toml --
+-- hugo.toml --
baseURL = 'http://example.com/'
-- layouts/home.html --
-- layouts/single.html --
t.Parallel()
files := `
--- config.toml --
+-- hugo.toml --
baseURL = 'http://example.com/'
-- layouts/home.html --
{{ partials.Include "foo.html" . }}
t.Parallel()
files := `
--- config.toml --
+-- hugo.toml --
baseURL = 'http://example.com/'
timeout = '200ms'
-- layouts/home.html --
t.Parallel()
files := `
--- config.toml --
+-- hugo.toml --
baseURL = 'http://example.com/'
timeout = '200ms'
-- layouts/home.html --
t.Parallel()
files := `
--- config.toml --
+-- hugo.toml --
baseURL = 'http://example.com/'
-- layouts/home.html --
{{ $r := partial "foo" }}
t.Parallel()
files := `
--- config.toml --
+-- hugo.toml --
baseURL = "http://example.com/blog"
-- assets/images/pixel.png --
iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNkYPhfDwAChwGA60e6kgAAAABJRU5ErkJggg==
t.Parallel()
files := `
--- config.toml --
+-- hugo.toml --
-- layouts/home.html --
{{/* This is currently not supported. */}}
{{ $copy := .Copy "copy.md" }}
t.Parallel()
files := `
--- config.toml --
+-- hugo.toml --
baseURL = "http://example.com/blog"
-- assets/images/pixel.png --
iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNkYPhfDwAChwGA60e6kgAAAABJRU5ErkJggg==
t.Parallel()
files := `
--- config.toml --
+-- hugo.toml --
baseURL = "http://example.com/"
-- assets/401K Prospectus.txt --
Prospectus.
t.Parallel()
files := `
--- config.toml --
+-- hugo.toml --
baseURL = 'http://example.com/'
-- layouts/home.html --
home.html: {{ templates.Exists "home.html" }}
t.Parallel()
files := `
--- config.toml --
+-- hugo.toml --
baseURL = 'http://example.com/'
-- layouts/baseof.html --
{{ block "main" . }}{{ end }}
t.Parallel()
files := `
--- config.toml --
+-- hugo.toml --
baseURL = 'http://example.com/'
-- layouts/home.html --
Home: {{ page.IsHome }}
t.Parallel()
files := `
--- config.toml --
+-- hugo.toml --
baseURL = 'http://example.com/'
-- layouts/home.html --
Home.
t.Parallel()
files := `
--- config.toml --
+-- hugo.toml --
baseURL = 'https://example.org/dir/'
disableKinds = ['home','rss','section','sitemap','taxonomy','term']
[markup.goldmark.extensions.typographer]
t.Parallel()
files := `
--- config.toml --
+-- hugo.toml --
baseURL = 'http://example.com/'
printUnusedTemplates=true
-- content/p1.md --
t.Parallel()
files := `
--- config.toml --
+-- hugo.toml --
baseURL = 'http://example.com/'
disableKinds = ["section", "home", "rss", "taxonomy", "term", "rss"]
-- content/p1.md --
t.Parallel()
files := `
--- config.toml --
+-- hugo.toml --
baseURL = 'http://example.com/'
-- content/s1/p1.md --
---
t.Parallel()
files := `
--- config.toml --
+-- hugo.toml --
-- layouts/home.html --
{{ $m := dict "key" "value" }}
{{ $k := "" }}
func TestSecurityAllowActionJSTmpl(t *testing.T) {
filesTemplate := `
--- config.toml --
+-- hugo.toml --
SECURITYCONFIG
-- layouts/home.html --
<script>
t.Parallel()
files := `
--- config.toml --
+-- hugo.toml --
disableKinds = ['home','section','rss','sitemap','taxonomy','term']
[markup.goldmark.parser.attribute]
title = true
t.Parallel()
files := `
--- config.toml --
+-- hugo.toml --
disableKinds = ['section','sitemap','taxonomy','term']
-- content/p1.md --
---