hugo

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

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

integration_test.go (12036B)

    1 // Copyright 2021 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 goldmark_test
   15 
   16 import (
   17 	"fmt"
   18 	"strings"
   19 	"testing"
   20 
   21 	qt "github.com/frankban/quicktest"
   22 
   23 	"github.com/gohugoio/hugo/hugolib"
   24 )
   25 
   26 // Issue 9463
   27 func TestAttributeExclusion(t *testing.T) {
   28 	t.Parallel()
   29 
   30 	files := `
   31 -- config.toml --
   32 [markup.goldmark.renderer]
   33 	unsafe = false
   34 [markup.goldmark.parser.attribute]
   35 	block = true
   36 	title = true
   37 -- content/p1.md --
   38 ---
   39 title: "p1"
   40 ---
   41 ## Heading {class="a" onclick="alert('heading')"}
   42 
   43 > Blockquote
   44 {class="b" ondblclick="alert('blockquote')"}
   45 
   46 ~~~bash {id="c" onmouseover="alert('code fence')" LINENOS=true}
   47 foo
   48 ~~~
   49 -- layouts/_default/single.html --
   50 {{ .Content }}
   51 `
   52 
   53 	b := hugolib.NewIntegrationTestBuilder(
   54 		hugolib.IntegrationTestConfig{
   55 			T:           t,
   56 			TxtarString: files,
   57 			NeedsOsFS:   false,
   58 		},
   59 	).Build()
   60 
   61 	b.AssertFileContent("public/p1/index.html", `
   62 		<h2 class="a" id="heading">
   63 		<blockquote class="b">
   64 		<div class="highlight" id="c">
   65 	`)
   66 }
   67 
   68 // Issue 9511
   69 func TestAttributeExclusionWithRenderHook(t *testing.T) {
   70 	t.Parallel()
   71 
   72 	files := `
   73 -- content/p1.md --
   74 ---
   75 title: "p1"
   76 ---
   77 ## Heading {onclick="alert('renderhook')" data-foo="bar"}
   78 -- layouts/_default/single.html --
   79 {{ .Content }}
   80 -- layouts/_default/_markup/render-heading.html --
   81 <h{{ .Level }}
   82   {{- range $k, $v := .Attributes -}}
   83     {{- printf " %s=%q" $k $v | safeHTMLAttr -}}
   84   {{- end -}}
   85 >{{ .Text | safeHTML }}</h{{ .Level }}>
   86 `
   87 
   88 	b := hugolib.NewIntegrationTestBuilder(
   89 		hugolib.IntegrationTestConfig{
   90 			T:           t,
   91 			TxtarString: files,
   92 			NeedsOsFS:   false,
   93 		},
   94 	).Build()
   95 
   96 	b.AssertFileContent("public/p1/index.html", `
   97 		<h2 data-foo="bar" id="heading">Heading</h2>
   98 	`)
   99 }
  100 
  101 func TestAttributesDefaultRenderer(t *testing.T) {
  102 	t.Parallel()
  103 
  104 	files := `
  105 -- content/p1.md --
  106 ---
  107 title: "p1"
  108 ---
  109 ## Heading Attribute Which Needs Escaping { class="a < b" }
  110 -- layouts/_default/single.html --
  111 {{ .Content }}
  112 `
  113 
  114 	b := hugolib.NewIntegrationTestBuilder(
  115 		hugolib.IntegrationTestConfig{
  116 			T:           t,
  117 			TxtarString: files,
  118 			NeedsOsFS:   false,
  119 		},
  120 	).Build()
  121 
  122 	b.AssertFileContent("public/p1/index.html", `
  123 class="a &lt; b"
  124 	`)
  125 }
  126 
  127 // Issue 9558.
  128 func TestAttributesHookNoEscape(t *testing.T) {
  129 	t.Parallel()
  130 
  131 	files := `
  132 -- content/p1.md --
  133 ---
  134 title: "p1"
  135 ---
  136 ## Heading Attribute Which Needs Escaping { class="Smith & Wesson" }
  137 -- layouts/_default/_markup/render-heading.html --
  138 plain: |{{- range $k, $v := .Attributes -}}{{ $k }}: {{ $v }}|{{ end }}|
  139 safeHTML: |{{- range $k, $v := .Attributes -}}{{ $k }}: {{ $v | safeHTML }}|{{ end }}|
  140 -- layouts/_default/single.html --
  141 {{ .Content }}
  142 `
  143 
  144 	b := hugolib.NewIntegrationTestBuilder(
  145 		hugolib.IntegrationTestConfig{
  146 			T:           t,
  147 			TxtarString: files,
  148 			NeedsOsFS:   false,
  149 		},
  150 	).Build()
  151 
  152 	b.AssertFileContent("public/p1/index.html", `
  153 plain: |class: Smith &amp; Wesson|id: heading-attribute-which-needs-escaping|
  154 safeHTML: |class: Smith & Wesson|id: heading-attribute-which-needs-escaping|
  155 	`)
  156 }
  157 
  158 // Issue 9504
  159 func TestLinkInTitle(t *testing.T) {
  160 	t.Parallel()
  161 
  162 	files := `
  163 -- config.toml --
  164 -- content/p1.md --
  165 ---
  166 title: "p1"
  167 ---
  168 ## Hello [Test](https://example.com)
  169 -- layouts/_default/single.html --
  170 {{ .Content }}
  171 -- layouts/_default/_markup/render-heading.html --
  172 <h{{ .Level }} id="{{ .Anchor | safeURL }}">
  173   {{ .Text | safeHTML }}
  174   <a class="anchor" href="#{{ .Anchor | safeURL }}">#</a>
  175 </h{{ .Level }}>
  176 -- layouts/_default/_markup/render-link.html --
  177 <a href="{{ .Destination | safeURL }}"{{ with .Title}} title="{{ . }}"{{ end }}>{{ .Text | safeHTML }}</a>
  178 
  179 `
  180 
  181 	b := hugolib.NewIntegrationTestBuilder(
  182 		hugolib.IntegrationTestConfig{
  183 			T:           t,
  184 			TxtarString: files,
  185 			NeedsOsFS:   false,
  186 		},
  187 	).Build()
  188 
  189 	b.AssertFileContent("public/p1/index.html",
  190 		"<h2 id=\"hello-testhttpsexamplecom\">\n  Hello <a href=\"https://example.com\">Test</a>\n\n  <a class=\"anchor\" href=\"#hello-testhttpsexamplecom\">#</a>\n</h2>",
  191 	)
  192 }
  193 
  194 func TestHighlight(t *testing.T) {
  195 	t.Parallel()
  196 
  197 	files := `
  198 -- config.toml --
  199 [markup]
  200 [markup.highlight]
  201 anchorLineNos = false
  202 codeFences = true
  203 guessSyntax = false
  204 hl_Lines = ''
  205 lineAnchors = ''
  206 lineNoStart = 1
  207 lineNos = false
  208 lineNumbersInTable = true
  209 noClasses = false
  210 style = 'monokai'
  211 tabWidth = 4
  212 -- layouts/_default/single.html --
  213 {{ .Content }}
  214 -- content/p1.md --
  215 ---
  216 title: "p1"
  217 ---
  218 
  219 ## Code Fences
  220 
  221 §§§bash
  222 LINE1
  223 §§§
  224 
  225 ## Code Fences No Lexer
  226 
  227 §§§moo
  228 LINE1
  229 §§§
  230 
  231 ## Code Fences Simple Attributes
  232 
  233 §§A§bash { .myclass id="myid" }
  234 LINE1
  235 §§A§
  236 
  237 ## Code Fences Line Numbers
  238 
  239 §§§bash {linenos=table,hl_lines=[8,"15-17"],linenostart=199}
  240 LINE1
  241 LINE2
  242 LINE3
  243 LINE4
  244 LINE5
  245 LINE6
  246 LINE7
  247 LINE8
  248 §§§
  249 
  250 
  251 
  252 
  253 `
  254 
  255 	b := hugolib.NewIntegrationTestBuilder(
  256 		hugolib.IntegrationTestConfig{
  257 			T:           t,
  258 			TxtarString: files,
  259 		},
  260 	).Build()
  261 
  262 	b.AssertFileContent("public/p1/index.html",
  263 		"<div class=\"highlight\"><pre tabindex=\"0\" class=\"chroma\"><code class=\"language-bash\" data-lang=\"bash\"><span class=\"line\"><span class=\"cl\">LINE1\n</span></span></code></pre></div>",
  264 		"Code Fences No Lexer</h2>\n<pre tabindex=\"0\"><code class=\"language-moo\" data-lang=\"moo\">LINE1\n</code></pre>",
  265 		"lnt",
  266 	)
  267 }
  268 
  269 func BenchmarkRenderHooks(b *testing.B) {
  270 	files := `
  271 -- config.toml --
  272 -- layouts/_default/_markup/render-heading.html --
  273 <h{{ .Level }} id="{{ .Anchor | safeURL }}">
  274 	{{ .Text | safeHTML }}
  275 	<a class="anchor" href="#{{ .Anchor | safeURL }}">#</a>
  276 </h{{ .Level }}>
  277 -- layouts/_default/_markup/render-link.html --
  278 <a href="{{ .Destination | safeURL }}"{{ with .Title}} title="{{ . }}"{{ end }}>{{ .Text | safeHTML }}</a>
  279 -- layouts/_default/single.html --
  280 {{ .Content }}
  281 `
  282 
  283 	content := `
  284 
  285 ## Hello1 [Test](https://example.com)
  286 
  287 A.
  288 
  289 ## Hello2 [Test](https://example.com)
  290 
  291 B.
  292 
  293 ## Hello3 [Test](https://example.com)
  294 
  295 C.
  296 
  297 ## Hello4 [Test](https://example.com)
  298 
  299 D.
  300 
  301 [Test](https://example.com)
  302 
  303 ## Hello5
  304 
  305 
  306 `
  307 
  308 	for i := 1; i < 100; i++ {
  309 		files += fmt.Sprintf("\n-- content/posts/p%d.md --\n"+content, i+1)
  310 	}
  311 
  312 	cfg := hugolib.IntegrationTestConfig{
  313 		T:           b,
  314 		TxtarString: files,
  315 	}
  316 	builders := make([]*hugolib.IntegrationTestBuilder, b.N)
  317 
  318 	for i := range builders {
  319 		builders[i] = hugolib.NewIntegrationTestBuilder(cfg)
  320 	}
  321 
  322 	b.ResetTimer()
  323 
  324 	for i := 0; i < b.N; i++ {
  325 		builders[i].Build()
  326 	}
  327 }
  328 
  329 func BenchmarkCodeblocks(b *testing.B) {
  330 	files := `
  331 -- config.toml --
  332 [markup]
  333   [markup.highlight]
  334     anchorLineNos = false
  335     codeFences = true
  336     guessSyntax = false
  337     hl_Lines = ''
  338     lineAnchors = ''
  339     lineNoStart = 1
  340     lineNos = false
  341     lineNumbersInTable = true
  342     noClasses = true
  343     style = 'monokai'
  344     tabWidth = 4
  345 -- layouts/_default/single.html --
  346 {{ .Content }}
  347 `
  348 
  349 	content := `
  350 
  351 FENCEgo
  352 package main
  353 import "fmt"
  354 func main() {
  355     fmt.Println("hello world")
  356 }
  357 FENCE
  358 
  359 FENCEbash
  360 #!/bin/bash
  361 # Usage: Hello World Bash Shell Script Using Variables
  362 # Author: Vivek Gite
  363 # -------------------------------------------------
  364  
  365 # Define bash shell variable called var 
  366 # Avoid spaces around the assignment operator (=)
  367 var="Hello World"
  368  
  369 # print it 
  370 echo "$var"
  371  
  372 # Another way of printing it
  373 printf "%s\n" "$var"
  374 FENCE
  375 `
  376 
  377 	content = strings.ReplaceAll(content, "FENCE", "```")
  378 
  379 	for i := 1; i < 100; i++ {
  380 		files += fmt.Sprintf("\n-- content/posts/p%d.md --\n"+content, i+1)
  381 	}
  382 
  383 	cfg := hugolib.IntegrationTestConfig{
  384 		T:           b,
  385 		TxtarString: files,
  386 	}
  387 	builders := make([]*hugolib.IntegrationTestBuilder, b.N)
  388 
  389 	for i := range builders {
  390 		builders[i] = hugolib.NewIntegrationTestBuilder(cfg)
  391 	}
  392 
  393 	b.ResetTimer()
  394 
  395 	for i := 0; i < b.N; i++ {
  396 		builders[i].Build()
  397 	}
  398 }
  399 
  400 // Iisse #8959
  401 func TestHookInfiniteRecursion(t *testing.T) {
  402 	t.Parallel()
  403 
  404 	for _, renderFunc := range []string{"markdownify", ".Page.RenderString"} {
  405 		t.Run(renderFunc, func(t *testing.T) {
  406 
  407 			files := `
  408 -- config.toml --
  409 -- layouts/_default/_markup/render-link.html --
  410 <a href="{{ .Destination | safeURL }}">{{ .Text | RENDERFUNC }}</a>	
  411 -- layouts/_default/single.html --
  412 {{ .Content }}
  413 -- content/p1.md --
  414 ---
  415 title: "p1"
  416 ---
  417 
  418 https://example.org
  419 
  420 a@b.com
  421 		
  422 			
  423 			`
  424 
  425 			files = strings.ReplaceAll(files, "RENDERFUNC", renderFunc)
  426 
  427 			b, err := hugolib.NewIntegrationTestBuilder(
  428 				hugolib.IntegrationTestConfig{
  429 					T:           t,
  430 					TxtarString: files,
  431 				},
  432 			).BuildE()
  433 
  434 			b.Assert(err, qt.IsNotNil)
  435 			b.Assert(err.Error(), qt.Contains, "text is already rendered, repeating it may cause infinite recursion")
  436 
  437 		})
  438 
  439 	}
  440 
  441 }
  442 
  443 // Issue 9594
  444 func TestQuotesInImgAltAttr(t *testing.T) {
  445 	t.Parallel()
  446 
  447 	files := `
  448 -- config.toml --
  449 [markup.goldmark.extensions]
  450   typographer = false
  451 -- content/p1.md --
  452 ---
  453 title: "p1"
  454 ---
  455 !["a"](b.jpg)
  456 -- layouts/_default/single.html --
  457 {{ .Content }}
  458 `
  459 
  460 	b := hugolib.NewIntegrationTestBuilder(
  461 		hugolib.IntegrationTestConfig{
  462 			T:           t,
  463 			TxtarString: files,
  464 		},
  465 	).Build()
  466 
  467 	b.AssertFileContent("public/p1/index.html", `
  468 		<img src="b.jpg" alt="&quot;a&quot;">
  469 	`)
  470 }
  471 
  472 func TestLinkifyProtocol(t *testing.T) {
  473 	t.Parallel()
  474 
  475 	runTest := func(protocol string, withHook bool) *hugolib.IntegrationTestBuilder {
  476 
  477 		files := `
  478 -- config.toml --
  479 [markup.goldmark]
  480 [markup.goldmark.extensions]
  481 linkify = true
  482 linkifyProtocol = "PROTOCOL"
  483 -- content/p1.md --
  484 ---
  485 title: "p1"
  486 ---
  487 Link no procol: www.example.org
  488 Link http procol: http://www.example.org
  489 Link https procol: https://www.example.org
  490 
  491 -- layouts/_default/single.html --
  492 {{ .Content }}
  493 `
  494 		files = strings.ReplaceAll(files, "PROTOCOL", protocol)
  495 
  496 		if withHook {
  497 			files += `-- layouts/_default/_markup/render-link.html --
  498 <a href="{{ .Destination | safeURL }}">{{ .Text | safeHTML }}</a>`
  499 		}
  500 
  501 		return hugolib.NewIntegrationTestBuilder(
  502 			hugolib.IntegrationTestConfig{
  503 				T:           t,
  504 				TxtarString: files,
  505 			},
  506 		).Build()
  507 
  508 	}
  509 
  510 	for _, withHook := range []bool{false, true} {
  511 
  512 		b := runTest("https", withHook)
  513 
  514 		b.AssertFileContent("public/p1/index.html",
  515 			"Link no procol: <a href=\"https://www.example.org\">www.example.org</a>",
  516 			"Link http procol: <a href=\"http://www.example.org\">http://www.example.org</a>",
  517 			"Link https procol: <a href=\"https://www.example.org\">https://www.example.org</a></p>",
  518 		)
  519 
  520 		b = runTest("http", withHook)
  521 
  522 		b.AssertFileContent("public/p1/index.html",
  523 			"Link no procol: <a href=\"http://www.example.org\">www.example.org</a>",
  524 			"Link http procol: <a href=\"http://www.example.org\">http://www.example.org</a>",
  525 			"Link https procol: <a href=\"https://www.example.org\">https://www.example.org</a></p>",
  526 		)
  527 
  528 		b = runTest("gopher", withHook)
  529 
  530 		b.AssertFileContent("public/p1/index.html",
  531 			"Link no procol: <a href=\"gopher://www.example.org\">www.example.org</a>",
  532 			"Link http procol: <a href=\"http://www.example.org\">http://www.example.org</a>",
  533 			"Link https procol: <a href=\"https://www.example.org\">https://www.example.org</a></p>",
  534 		)
  535 
  536 	}
  537 }
  538 
  539 func TestGoldmarkBugs(t *testing.T) {
  540 	t.Parallel()
  541 
  542 	files := `
  543 -- config.toml --
  544 [markup.goldmark.renderer]
  545 unsafe = true
  546 -- content/p1.md --
  547 ---
  548 title: "p1"
  549 ---
  550 
  551 ## Issue 9650
  552 
  553 a <!-- b --> c
  554 
  555 ## Issue 9658
  556 
  557 - This is a list item <!-- Comment: an innocent-looking comment -->
  558 
  559 
  560 -- layouts/_default/single.html --
  561 {{ .Content }}
  562 `
  563 
  564 	b := hugolib.NewIntegrationTestBuilder(
  565 		hugolib.IntegrationTestConfig{
  566 			T:           t,
  567 			TxtarString: files,
  568 		},
  569 	).Build()
  570 
  571 	b.AssertFileContentExact("public/p1/index.html",
  572 		// Issue 9650
  573 		"<p>a <!-- b --> c</p>",
  574 		// Issue 9658 (crash)
  575 		"<li>This is a list item <!-- Comment: an innocent-looking comment --></li>",
  576 	)
  577 }