hugo

Fork of github.com/gohugoio/hugo with reverse pagination support

git clone git://git.shimmy1996.com/hugo.git

site_output_test.go (17604B)

    1 // Copyright 2019 The Hugo Authors. All rights reserved.
    2 //
    3 // Licensed under the Apache License, Version 2.0 (the "License");
    4 // you may not use this file except in compliance with the License.
    5 // You may obtain a copy of the License at
    6 // http://www.apache.org/licenses/LICENSE-2.0
    7 //
    8 // Unless required by applicable law or agreed to in writing, software
    9 // distributed under the License is distributed on an "AS IS" BASIS,
   10 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   11 // See the License for the specific language governing permissions and
   12 // limitations under the License.
   13 
   14 package hugolib
   15 
   16 import (
   17 	"fmt"
   18 	"strings"
   19 	"testing"
   20 
   21 	qt "github.com/frankban/quicktest"
   22 	"github.com/gohugoio/hugo/config"
   23 	"github.com/gohugoio/hugo/resources/page"
   24 
   25 	"github.com/spf13/afero"
   26 
   27 	"github.com/gohugoio/hugo/helpers"
   28 	"github.com/gohugoio/hugo/output"
   29 )
   30 
   31 func TestSiteWithPageOutputs(t *testing.T) {
   32 	for _, outputs := range [][]string{{"html", "json", "calendar"}, {"json"}} {
   33 		outputs := outputs
   34 		t.Run(fmt.Sprintf("%v", outputs), func(t *testing.T) {
   35 			t.Parallel()
   36 			doTestSiteWithPageOutputs(t, outputs)
   37 		})
   38 	}
   39 }
   40 
   41 func doTestSiteWithPageOutputs(t *testing.T, outputs []string) {
   42 	outputsStr := strings.Replace(fmt.Sprintf("%q", outputs), " ", ", ", -1)
   43 
   44 	siteConfig := `
   45 baseURL = "http://example.com/blog"
   46 
   47 paginate = 1
   48 defaultContentLanguage = "en"
   49 
   50 disableKinds = ["section", "term", "taxonomy", "RSS", "sitemap", "robotsTXT", "404"]
   51 
   52 [Taxonomies]
   53 tag = "tags"
   54 category = "categories"
   55 
   56 defaultContentLanguage = "en"
   57 
   58 
   59 [languages]
   60 
   61 [languages.en]
   62 title = "Title in English"
   63 languageName = "English"
   64 weight = 1
   65 
   66 [languages.nn]
   67 languageName = "Nynorsk"
   68 weight = 2
   69 title = "Tittel på Nynorsk"
   70 
   71 `
   72 
   73 	pageTemplate := `---
   74 title: "%s"
   75 outputs: %s
   76 ---
   77 # Doc
   78 
   79 {{< myShort >}}
   80 
   81 {{< myOtherShort >}}
   82 
   83 `
   84 
   85 	b := newTestSitesBuilder(t).WithConfigFile("toml", siteConfig)
   86 	b.WithI18n("en.toml", `
   87 [elbow]
   88 other = "Elbow"
   89 `, "nn.toml", `
   90 [elbow]
   91 other = "Olboge"
   92 `)
   93 
   94 	b.WithTemplates(
   95 		// Case issue partials #3333
   96 		"layouts/partials/GoHugo.html", `Go Hugo Partial`,
   97 		"layouts/_default/baseof.json", `START JSON:{{block "main" .}}default content{{ end }}:END JSON`,
   98 		"layouts/_default/baseof.html", `START HTML:{{block "main" .}}default content{{ end }}:END HTML`,
   99 		"layouts/shortcodes/myOtherShort.html", `OtherShort: {{ "<h1>Hi!</h1>" | safeHTML }}`,
  100 		"layouts/shortcodes/myShort.html", `ShortHTML`,
  101 		"layouts/shortcodes/myShort.json", `ShortJSON`,
  102 
  103 		"layouts/_default/list.json", `{{ define "main" }}
  104 List JSON|{{ .Title }}|{{ .Content }}|Alt formats: {{ len .AlternativeOutputFormats -}}|
  105 {{- range .AlternativeOutputFormats -}}
  106 Alt Output: {{ .Name -}}|
  107 {{- end -}}|
  108 {{- range .OutputFormats -}}
  109 Output/Rel: {{ .Name -}}/{{ .Rel }}|{{ .MediaType }}
  110 {{- end -}}
  111  {{ with .OutputFormats.Get "JSON" }}
  112 <atom:link href={{ .Permalink }} rel="self" type="{{ .MediaType }}" />
  113 {{ end }}
  114 {{ .Site.Language.Lang }}: {{ T "elbow" -}}
  115 {{ end }}
  116 `,
  117 		"layouts/_default/list.html", `{{ define "main" }}
  118 List HTML|{{.Title }}|
  119 {{- with .OutputFormats.Get "HTML" -}}
  120 <atom:link href={{ .Permalink }} rel="self" type="{{ .MediaType }}" />
  121 {{- end -}}
  122 {{ .Site.Language.Lang }}: {{ T "elbow" -}}
  123 Partial Hugo 1: {{ partial "GoHugo.html" . }}
  124 Partial Hugo 2: {{ partial "GoHugo" . -}}
  125 Content: {{ .Content }}
  126 Len Pages: {{ .Kind }} {{ len .Site.RegularPages }} Page Number: {{ .Paginator.PageNumber }}
  127 {{ end }}
  128 `,
  129 		"layouts/_default/single.html", `{{ define "main" }}{{ .Content }}{{ end }}`,
  130 	)
  131 
  132 	b.WithContent("_index.md", fmt.Sprintf(pageTemplate, "JSON Home", outputsStr))
  133 	b.WithContent("_index.nn.md", fmt.Sprintf(pageTemplate, "JSON Nynorsk Heim", outputsStr))
  134 
  135 	for i := 1; i <= 10; i++ {
  136 		b.WithContent(fmt.Sprintf("p%d.md", i), fmt.Sprintf(pageTemplate, fmt.Sprintf("Page %d", i), outputsStr))
  137 	}
  138 
  139 	b.Build(BuildCfg{})
  140 
  141 	s := b.H.Sites[0]
  142 	b.Assert(s.language.Lang, qt.Equals, "en")
  143 
  144 	home := s.getPage(page.KindHome)
  145 
  146 	b.Assert(home, qt.Not(qt.IsNil))
  147 
  148 	lenOut := len(outputs)
  149 
  150 	b.Assert(len(home.OutputFormats()), qt.Equals, lenOut)
  151 
  152 	// There is currently always a JSON output to make it simpler ...
  153 	altFormats := lenOut - 1
  154 	hasHTML := helpers.InStringArray(outputs, "html")
  155 	b.AssertFileContent("public/index.json",
  156 		"List JSON",
  157 		fmt.Sprintf("Alt formats: %d", altFormats),
  158 	)
  159 
  160 	if hasHTML {
  161 		b.AssertFileContent("public/index.json",
  162 			"Alt Output: HTML",
  163 			"Output/Rel: JSON/alternate|",
  164 			"Output/Rel: HTML/canonical|",
  165 			"en: Elbow",
  166 			"ShortJSON",
  167 			"OtherShort: <h1>Hi!</h1>",
  168 		)
  169 
  170 		b.AssertFileContent("public/index.html",
  171 			// The HTML entity is a deliberate part of this test: The HTML templates are
  172 			// parsed with html/template.
  173 			`List HTML|JSON Home|<atom:link href=http://example.com/blog/ rel="self" type="text/html" />`,
  174 			"en: Elbow",
  175 			"ShortHTML",
  176 			"OtherShort: <h1>Hi!</h1>",
  177 			"Len Pages: home 10",
  178 		)
  179 		b.AssertFileContent("public/page/2/index.html", "Page Number: 2")
  180 		b.Assert(b.CheckExists("public/page/2/index.json"), qt.Equals, false)
  181 
  182 		b.AssertFileContent("public/nn/index.html",
  183 			"List HTML|JSON Nynorsk Heim|",
  184 			"nn: Olboge")
  185 	} else {
  186 		b.AssertFileContent("public/index.json",
  187 			"Output/Rel: JSON/canonical|",
  188 			// JSON is plain text, so no need to safeHTML this and that
  189 			`<atom:link href=http://example.com/blog/index.json rel="self" type="application/json" />`,
  190 			"ShortJSON",
  191 			"OtherShort: <h1>Hi!</h1>",
  192 		)
  193 		b.AssertFileContent("public/nn/index.json",
  194 			"List JSON|JSON Nynorsk Heim|",
  195 			"nn: Olboge",
  196 			"ShortJSON",
  197 		)
  198 	}
  199 
  200 	of := home.OutputFormats()
  201 
  202 	json := of.Get("JSON")
  203 	b.Assert(json, qt.Not(qt.IsNil))
  204 	b.Assert(json.RelPermalink(), qt.Equals, "/blog/index.json")
  205 	b.Assert(json.Permalink(), qt.Equals, "http://example.com/blog/index.json")
  206 
  207 	if helpers.InStringArray(outputs, "cal") {
  208 		cal := of.Get("calendar")
  209 		b.Assert(cal, qt.Not(qt.IsNil))
  210 		b.Assert(cal.RelPermalink(), qt.Equals, "/blog/index.ics")
  211 		b.Assert(cal.Permalink(), qt.Equals, "webcal://example.com/blog/index.ics")
  212 	}
  213 
  214 	b.Assert(home.HasShortcode("myShort"), qt.Equals, true)
  215 	b.Assert(home.HasShortcode("doesNotExist"), qt.Equals, false)
  216 }
  217 
  218 // Issue #3447
  219 func TestRedefineRSSOutputFormat(t *testing.T) {
  220 	siteConfig := `
  221 baseURL = "http://example.com/blog"
  222 
  223 paginate = 1
  224 defaultContentLanguage = "en"
  225 
  226 disableKinds = ["page", "section", "term", "taxonomy", "sitemap", "robotsTXT", "404"]
  227 
  228 [outputFormats]
  229 [outputFormats.RSS]
  230 mediatype = "application/rss"
  231 baseName = "feed"
  232 
  233 `
  234 
  235 	c := qt.New(t)
  236 
  237 	mf := afero.NewMemMapFs()
  238 	writeToFs(t, mf, "content/foo.html", `foo`)
  239 
  240 	th, h := newTestSitesFromConfig(t, mf, siteConfig)
  241 
  242 	err := h.Build(BuildCfg{})
  243 
  244 	c.Assert(err, qt.IsNil)
  245 
  246 	th.assertFileContent("public/feed.xml", "Recent content on")
  247 
  248 	s := h.Sites[0]
  249 
  250 	// Issue #3450
  251 	c.Assert(s.Info.RSSLink, qt.Equals, "http://example.com/blog/feed.xml")
  252 }
  253 
  254 // Issue #3614
  255 func TestDotLessOutputFormat(t *testing.T) {
  256 	siteConfig := `
  257 baseURL = "http://example.com/blog"
  258 
  259 paginate = 1
  260 defaultContentLanguage = "en"
  261 
  262 disableKinds = ["page", "section", "term", "taxonomy", "sitemap", "robotsTXT", "404"]
  263 
  264 [mediaTypes]
  265 [mediaTypes."text/nodot"]
  266 delimiter = ""
  267 [mediaTypes."text/defaultdelim"]
  268 suffixes = ["defd"]
  269 [mediaTypes."text/nosuffix"]
  270 [mediaTypes."text/customdelim"]
  271 suffixes = ["del"]
  272 delimiter = "_"
  273 
  274 [outputs]
  275 home = [ "DOTLESS", "DEF", "NOS", "CUS" ]
  276 
  277 [outputFormats]
  278 [outputFormats.DOTLESS]
  279 mediatype = "text/nodot"
  280 baseName = "_redirects" # This is how Netlify names their redirect files.
  281 [outputFormats.DEF]
  282 mediatype = "text/defaultdelim"
  283 baseName = "defaultdelimbase"
  284 [outputFormats.NOS]
  285 mediatype = "text/nosuffix"
  286 baseName = "nosuffixbase"
  287 [outputFormats.CUS]
  288 mediatype = "text/customdelim"
  289 baseName = "customdelimbase"
  290 
  291 `
  292 
  293 	c := qt.New(t)
  294 
  295 	mf := afero.NewMemMapFs()
  296 	writeToFs(t, mf, "content/foo.html", `foo`)
  297 	writeToFs(t, mf, "layouts/_default/list.dotless", `a dotless`)
  298 	writeToFs(t, mf, "layouts/_default/list.def.defd", `default delimim`)
  299 	writeToFs(t, mf, "layouts/_default/list.nos", `no suffix`)
  300 	writeToFs(t, mf, "layouts/_default/list.cus.del", `custom delim`)
  301 
  302 	th, h := newTestSitesFromConfig(t, mf, siteConfig)
  303 
  304 	err := h.Build(BuildCfg{})
  305 
  306 	c.Assert(err, qt.IsNil)
  307 
  308 	s := h.Sites[0]
  309 
  310 	th.assertFileContent("public/_redirects", "a dotless")
  311 	th.assertFileContent("public/defaultdelimbase.defd", "default delimim")
  312 	// This looks weird, but the user has chosen this definition.
  313 	th.assertFileContent("public/nosuffixbase", "no suffix")
  314 	th.assertFileContent("public/customdelimbase_del", "custom delim")
  315 
  316 	home := s.getPage(page.KindHome)
  317 	c.Assert(home, qt.Not(qt.IsNil))
  318 
  319 	outputs := home.OutputFormats()
  320 
  321 	c.Assert(outputs.Get("DOTLESS").RelPermalink(), qt.Equals, "/blog/_redirects")
  322 	c.Assert(outputs.Get("DEF").RelPermalink(), qt.Equals, "/blog/defaultdelimbase.defd")
  323 	c.Assert(outputs.Get("NOS").RelPermalink(), qt.Equals, "/blog/nosuffixbase")
  324 	c.Assert(outputs.Get("CUS").RelPermalink(), qt.Equals, "/blog/customdelimbase_del")
  325 }
  326 
  327 // Issue 8030
  328 func TestGetOutputFormatRel(t *testing.T) {
  329 	b := newTestSitesBuilder(t).
  330 		WithSimpleConfigFileAndSettings(map[string]any{
  331 			"outputFormats": map[string]any{
  332 				"humansTXT": map[string]any{
  333 					"name":        "HUMANS",
  334 					"mediaType":   "text/plain",
  335 					"baseName":    "humans",
  336 					"isPlainText": true,
  337 					"rel":         "author",
  338 				},
  339 			},
  340 		}).WithTemplates("index.html", `
  341 {{- with ($.Site.GetPage "humans").OutputFormats.Get "humans" -}}
  342 <link rel="{{ .Rel }}" type="{{ .MediaType.String }}" href="{{ .Permalink }}">
  343 {{- end -}}
  344 `).WithContent("humans.md", `---
  345 outputs:
  346 - HUMANS
  347 ---
  348 This is my content.
  349 `)
  350 
  351 	b.Build(BuildCfg{})
  352 	b.AssertFileContent("public/index.html", `
  353 <link rel="author" type="text/plain" href="/humans.txt">
  354 `)
  355 }
  356 
  357 func TestCreateSiteOutputFormats(t *testing.T) {
  358 	t.Run("Basic", func(t *testing.T) {
  359 		c := qt.New(t)
  360 
  361 		outputsConfig := map[string]any{
  362 			page.KindHome:    []string{"HTML", "JSON"},
  363 			page.KindSection: []string{"JSON"},
  364 		}
  365 
  366 		cfg := config.NewWithTestDefaults()
  367 		cfg.Set("outputs", outputsConfig)
  368 
  369 		outputs, err := createSiteOutputFormats(output.DefaultFormats, cfg.GetStringMap("outputs"), false)
  370 		c.Assert(err, qt.IsNil)
  371 		c.Assert(outputs[page.KindSection], deepEqualsOutputFormats, output.Formats{output.JSONFormat})
  372 		c.Assert(outputs[page.KindHome], deepEqualsOutputFormats, output.Formats{output.HTMLFormat, output.JSONFormat})
  373 
  374 		// Defaults
  375 		c.Assert(outputs[page.KindTerm], deepEqualsOutputFormats, output.Formats{output.HTMLFormat, output.RSSFormat})
  376 		c.Assert(outputs[page.KindTaxonomy], deepEqualsOutputFormats, output.Formats{output.HTMLFormat, output.RSSFormat})
  377 		c.Assert(outputs[page.KindPage], deepEqualsOutputFormats, output.Formats{output.HTMLFormat})
  378 
  379 		// These aren't (currently) in use when rendering in Hugo,
  380 		// but the pages needs to be assigned an output format,
  381 		// so these should also be correct/sensible.
  382 		c.Assert(outputs[kindRSS], deepEqualsOutputFormats, output.Formats{output.RSSFormat})
  383 		c.Assert(outputs[kindSitemap], deepEqualsOutputFormats, output.Formats{output.SitemapFormat})
  384 		c.Assert(outputs[kindRobotsTXT], deepEqualsOutputFormats, output.Formats{output.RobotsTxtFormat})
  385 		c.Assert(outputs[kind404], deepEqualsOutputFormats, output.Formats{output.HTMLFormat})
  386 	})
  387 
  388 	// Issue #4528
  389 	t.Run("Mixed case", func(t *testing.T) {
  390 		c := qt.New(t)
  391 		cfg := config.NewWithTestDefaults()
  392 
  393 		outputsConfig := map[string]any{
  394 			// Note that we in Hugo 0.53.0 renamed this Kind to "taxonomy",
  395 			// but keep this test to test the legacy mapping.
  396 			"taxonomyterm": []string{"JSON"},
  397 		}
  398 		cfg.Set("outputs", outputsConfig)
  399 
  400 		outputs, err := createSiteOutputFormats(output.DefaultFormats, cfg.GetStringMap("outputs"), false)
  401 		c.Assert(err, qt.IsNil)
  402 		c.Assert(outputs[page.KindTaxonomy], deepEqualsOutputFormats, output.Formats{output.JSONFormat})
  403 	})
  404 }
  405 
  406 func TestCreateSiteOutputFormatsInvalidConfig(t *testing.T) {
  407 	c := qt.New(t)
  408 
  409 	outputsConfig := map[string]any{
  410 		page.KindHome: []string{"FOO", "JSON"},
  411 	}
  412 
  413 	cfg := config.NewWithTestDefaults()
  414 	cfg.Set("outputs", outputsConfig)
  415 
  416 	_, err := createSiteOutputFormats(output.DefaultFormats, cfg.GetStringMap("outputs"), false)
  417 	c.Assert(err, qt.Not(qt.IsNil))
  418 }
  419 
  420 func TestCreateSiteOutputFormatsEmptyConfig(t *testing.T) {
  421 	c := qt.New(t)
  422 
  423 	outputsConfig := map[string]any{
  424 		page.KindHome: []string{},
  425 	}
  426 
  427 	cfg := config.NewWithTestDefaults()
  428 	cfg.Set("outputs", outputsConfig)
  429 
  430 	outputs, err := createSiteOutputFormats(output.DefaultFormats, cfg.GetStringMap("outputs"), false)
  431 	c.Assert(err, qt.IsNil)
  432 	c.Assert(outputs[page.KindHome], deepEqualsOutputFormats, output.Formats{output.HTMLFormat, output.RSSFormat})
  433 }
  434 
  435 func TestCreateSiteOutputFormatsCustomFormats(t *testing.T) {
  436 	c := qt.New(t)
  437 
  438 	outputsConfig := map[string]any{
  439 		page.KindHome: []string{},
  440 	}
  441 
  442 	cfg := config.NewWithTestDefaults()
  443 	cfg.Set("outputs", outputsConfig)
  444 
  445 	var (
  446 		customRSS  = output.Format{Name: "RSS", BaseName: "customRSS"}
  447 		customHTML = output.Format{Name: "HTML", BaseName: "customHTML"}
  448 	)
  449 
  450 	outputs, err := createSiteOutputFormats(output.Formats{customRSS, customHTML}, cfg.GetStringMap("outputs"), false)
  451 	c.Assert(err, qt.IsNil)
  452 	c.Assert(outputs[page.KindHome], deepEqualsOutputFormats, output.Formats{customHTML, customRSS})
  453 }
  454 
  455 // https://github.com/gohugoio/hugo/issues/5849
  456 func TestOutputFormatPermalinkable(t *testing.T) {
  457 	config := `
  458 baseURL = "https://example.com"
  459 
  460 
  461 
  462 # DAMP is similar to AMP, but not permalinkable.
  463 [outputFormats]
  464 [outputFormats.damp]
  465 mediaType = "text/html"
  466 path = "damp"
  467 [outputFormats.ramp]
  468 mediaType = "text/html"
  469 path = "ramp"
  470 permalinkable = true
  471 [outputFormats.base]
  472 mediaType = "text/html"
  473 isHTML = true
  474 baseName = "that"
  475 permalinkable = true
  476 [outputFormats.nobase]
  477 mediaType = "application/json"
  478 permalinkable = true
  479 
  480 `
  481 
  482 	b := newTestSitesBuilder(t).WithConfigFile("toml", config)
  483 	b.WithContent("_index.md", `
  484 ---
  485 Title: Home Sweet Home
  486 outputs: [ "html", "amp", "damp", "base" ]
  487 ---
  488 
  489 `)
  490 
  491 	b.WithContent("blog/html-amp.md", `
  492 ---
  493 Title: AMP and HTML
  494 outputs: [ "html", "amp" ]
  495 ---
  496 
  497 `)
  498 
  499 	b.WithContent("blog/html-damp.md", `
  500 ---
  501 Title: DAMP and HTML
  502 outputs: [ "html", "damp" ]
  503 ---
  504 
  505 `)
  506 
  507 	b.WithContent("blog/html-ramp.md", `
  508 ---
  509 Title: RAMP and HTML
  510 outputs: [ "html", "ramp" ]
  511 ---
  512 
  513 `)
  514 
  515 	b.WithContent("blog/html.md", `
  516 ---
  517 Title: HTML only
  518 outputs: [ "html" ]
  519 ---
  520 
  521 `)
  522 
  523 	b.WithContent("blog/amp.md", `
  524 ---
  525 Title: AMP only
  526 outputs: [ "amp" ]
  527 ---
  528 
  529 `)
  530 
  531 	b.WithContent("blog/html-base-nobase.md", `
  532 ---
  533 Title: HTML, Base and Nobase
  534 outputs: [ "html", "base", "nobase" ]
  535 ---
  536 
  537 `)
  538 
  539 	const commonTemplate = `
  540 This RelPermalink: {{ .RelPermalink }}
  541 Output Formats: {{ len .OutputFormats }};{{ range .OutputFormats }}{{ .Name }};{{ .RelPermalink }}|{{ end }}
  542 
  543 `
  544 
  545 	b.WithTemplatesAdded("index.html", commonTemplate)
  546 	b.WithTemplatesAdded("_default/single.html", commonTemplate)
  547 	b.WithTemplatesAdded("_default/single.json", commonTemplate)
  548 
  549 	b.Build(BuildCfg{})
  550 
  551 	b.AssertFileContent("public/index.html",
  552 		"This RelPermalink: /",
  553 		"Output Formats: 4;HTML;/|AMP;/amp/|damp;/damp/|base;/that.html|",
  554 	)
  555 
  556 	b.AssertFileContent("public/amp/index.html",
  557 		"This RelPermalink: /amp/",
  558 		"Output Formats: 4;HTML;/|AMP;/amp/|damp;/damp/|base;/that.html|",
  559 	)
  560 
  561 	b.AssertFileContent("public/blog/html-amp/index.html",
  562 		"Output Formats: 2;HTML;/blog/html-amp/|AMP;/amp/blog/html-amp/|",
  563 		"This RelPermalink: /blog/html-amp/")
  564 
  565 	b.AssertFileContent("public/amp/blog/html-amp/index.html",
  566 		"Output Formats: 2;HTML;/blog/html-amp/|AMP;/amp/blog/html-amp/|",
  567 		"This RelPermalink: /amp/blog/html-amp/")
  568 
  569 	// Damp is not permalinkable
  570 	b.AssertFileContent("public/damp/blog/html-damp/index.html",
  571 		"This RelPermalink: /blog/html-damp/",
  572 		"Output Formats: 2;HTML;/blog/html-damp/|damp;/damp/blog/html-damp/|")
  573 
  574 	b.AssertFileContent("public/blog/html-ramp/index.html",
  575 		"This RelPermalink: /blog/html-ramp/",
  576 		"Output Formats: 2;HTML;/blog/html-ramp/|ramp;/ramp/blog/html-ramp/|")
  577 
  578 	b.AssertFileContent("public/ramp/blog/html-ramp/index.html",
  579 		"This RelPermalink: /ramp/blog/html-ramp/",
  580 		"Output Formats: 2;HTML;/blog/html-ramp/|ramp;/ramp/blog/html-ramp/|")
  581 
  582 	// https://github.com/gohugoio/hugo/issues/5877
  583 	outputFormats := "Output Formats: 3;HTML;/blog/html-base-nobase/|base;/blog/html-base-nobase/that.html|nobase;/blog/html-base-nobase/index.json|"
  584 
  585 	b.AssertFileContent("public/blog/html-base-nobase/index.json",
  586 		"This RelPermalink: /blog/html-base-nobase/index.json",
  587 		outputFormats,
  588 	)
  589 
  590 	b.AssertFileContent("public/blog/html-base-nobase/that.html",
  591 		"This RelPermalink: /blog/html-base-nobase/that.html",
  592 		outputFormats,
  593 	)
  594 
  595 	b.AssertFileContent("public/blog/html-base-nobase/index.html",
  596 		"This RelPermalink: /blog/html-base-nobase/",
  597 		outputFormats,
  598 	)
  599 }
  600 
  601 func TestSiteWithPageNoOutputs(t *testing.T) {
  602 	t.Parallel()
  603 
  604 	b := newTestSitesBuilder(t)
  605 	b.WithConfigFile("toml", `
  606 baseURL = "https://example.com"
  607 
  608 [outputFormats.o1]
  609 mediaType = "text/html"
  610 
  611 
  612 
  613 `)
  614 	b.WithContent("outputs-empty.md", `---
  615 title: "Empty Outputs"
  616 outputs: []
  617 ---
  618 
  619 Word1. Word2.
  620 
  621 `,
  622 		"outputs-string.md", `---
  623 title: "Outputs String"
  624 outputs: "o1"
  625 ---
  626 
  627 Word1. Word2.
  628 
  629 `)
  630 
  631 	b.WithTemplates("index.html", `
  632 {{ range .Site.RegularPages }}
  633 WordCount: {{ .WordCount }}
  634 {{ end }}
  635 `)
  636 
  637 	b.WithTemplates("_default/single.html", `HTML: {{ .Content }}`)
  638 	b.WithTemplates("_default/single.o1.html", `O1: {{ .Content }}`)
  639 
  640 	b.Build(BuildCfg{})
  641 
  642 	b.AssertFileContent(
  643 		"public/index.html",
  644 		" WordCount: 2")
  645 
  646 	b.AssertFileContent("public/outputs-empty/index.html", "HTML:", "Word1. Word2.")
  647 	b.AssertFileContent("public/outputs-string/index.html", "O1:", "Word1. Word2.")
  648 }