github.com/kovansky/hugo@v0.92.3-0.20220224232819-63076e4ff19f/markup/goldmark/integration_test.go (about) 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 "github.com/gohugoio/hugo/hugolib" 22 ) 23 24 // Issue 9463 25 func TestAttributeExclusion(t *testing.T) { 26 t.Parallel() 27 28 files := ` 29 -- config.toml -- 30 [markup.goldmark.renderer] 31 unsafe = false 32 [markup.goldmark.parser.attribute] 33 block = true 34 title = true 35 -- content/p1.md -- 36 --- 37 title: "p1" 38 --- 39 ## Heading {class="a" onclick="alert('heading')"} 40 41 > Blockquote 42 {class="b" ondblclick="alert('blockquote')"} 43 44 ~~~bash {id="c" onmouseover="alert('code fence')" LINENOS=true} 45 foo 46 ~~~ 47 -- layouts/_default/single.html -- 48 {{ .Content }} 49 ` 50 51 b := hugolib.NewIntegrationTestBuilder( 52 hugolib.IntegrationTestConfig{ 53 T: t, 54 TxtarString: files, 55 NeedsOsFS: false, 56 }, 57 ).Build() 58 59 b.AssertFileContent("public/p1/index.html", ` 60 <h2 class="a" id="heading"> 61 <blockquote class="b"> 62 <div class="highlight" id="c"> 63 `) 64 } 65 66 // Issue 9511 67 func TestAttributeExclusionWithRenderHook(t *testing.T) { 68 t.Parallel() 69 70 files := ` 71 -- content/p1.md -- 72 --- 73 title: "p1" 74 --- 75 ## Heading {onclick="alert('renderhook')" data-foo="bar"} 76 -- layouts/_default/single.html -- 77 {{ .Content }} 78 -- layouts/_default/_markup/render-heading.html -- 79 <h{{ .Level }} 80 {{- range $k, $v := .Attributes -}} 81 {{- printf " %s=%q" $k $v | safeHTMLAttr -}} 82 {{- end -}} 83 >{{ .Text | safeHTML }}</h{{ .Level }}> 84 ` 85 86 b := hugolib.NewIntegrationTestBuilder( 87 hugolib.IntegrationTestConfig{ 88 T: t, 89 TxtarString: files, 90 NeedsOsFS: false, 91 }, 92 ).Build() 93 94 b.AssertFileContent("public/p1/index.html", ` 95 <h2 data-foo="bar" id="heading">Heading</h2> 96 `) 97 } 98 99 func TestAttributesDefaultRenderer(t *testing.T) { 100 t.Parallel() 101 102 files := ` 103 -- content/p1.md -- 104 --- 105 title: "p1" 106 --- 107 ## Heading Attribute Which Needs Escaping { class="a < b" } 108 -- layouts/_default/single.html -- 109 {{ .Content }} 110 ` 111 112 b := hugolib.NewIntegrationTestBuilder( 113 hugolib.IntegrationTestConfig{ 114 T: t, 115 TxtarString: files, 116 NeedsOsFS: false, 117 }, 118 ).Build() 119 120 b.AssertFileContent("public/p1/index.html", ` 121 class="a < b" 122 `) 123 } 124 125 // Issue 9558. 126 func TestAttributesHookNoEscape(t *testing.T) { 127 t.Parallel() 128 129 files := ` 130 -- content/p1.md -- 131 --- 132 title: "p1" 133 --- 134 ## Heading Attribute Which Needs Escaping { class="Smith & Wesson" } 135 -- layouts/_default/_markup/render-heading.html -- 136 plain: |{{- range $k, $v := .Attributes -}}{{ $k }}: {{ $v }}|{{ end }}| 137 safeHTML: |{{- range $k, $v := .Attributes -}}{{ $k }}: {{ $v | safeHTML }}|{{ end }}| 138 -- layouts/_default/single.html -- 139 {{ .Content }} 140 ` 141 142 b := hugolib.NewIntegrationTestBuilder( 143 hugolib.IntegrationTestConfig{ 144 T: t, 145 TxtarString: files, 146 NeedsOsFS: false, 147 }, 148 ).Build() 149 150 b.AssertFileContent("public/p1/index.html", ` 151 plain: |class: Smith & Wesson|id: heading-attribute-which-needs-escaping| 152 safeHTML: |class: Smith & Wesson|id: heading-attribute-which-needs-escaping| 153 `) 154 } 155 156 // Issue 9504 157 func TestLinkInTitle(t *testing.T) { 158 t.Parallel() 159 160 files := ` 161 -- config.toml -- 162 -- content/p1.md -- 163 --- 164 title: "p1" 165 --- 166 ## Hello [Test](https://example.com) 167 -- layouts/_default/single.html -- 168 {{ .Content }} 169 -- layouts/_default/_markup/render-heading.html -- 170 <h{{ .Level }} id="{{ .Anchor | safeURL }}"> 171 {{ .Text | safeHTML }} 172 <a class="anchor" href="#{{ .Anchor | safeURL }}">#</a> 173 </h{{ .Level }}> 174 -- layouts/_default/_markup/render-link.html -- 175 <a href="{{ .Destination | safeURL }}"{{ with .Title}} title="{{ . }}"{{ end }}>{{ .Text | safeHTML }}</a> 176 177 ` 178 179 b := hugolib.NewIntegrationTestBuilder( 180 hugolib.IntegrationTestConfig{ 181 T: t, 182 TxtarString: files, 183 NeedsOsFS: false, 184 }, 185 ).Build() 186 187 b.AssertFileContent("public/p1/index.html", 188 "<h2 id=\"hello-testhttpsexamplecom\">\n Hello <a href=\"https://example.com\">Test</a>\n\n <a class=\"anchor\" href=\"#hello-testhttpsexamplecom\">#</a>\n</h2>", 189 ) 190 } 191 192 func TestHighlight(t *testing.T) { 193 t.Parallel() 194 195 files := ` 196 -- config.toml -- 197 [markup] 198 [markup.highlight] 199 anchorLineNos = false 200 codeFences = true 201 guessSyntax = false 202 hl_Lines = '' 203 lineAnchors = '' 204 lineNoStart = 1 205 lineNos = false 206 lineNumbersInTable = true 207 noClasses = false 208 style = 'monokai' 209 tabWidth = 4 210 -- layouts/_default/single.html -- 211 {{ .Content }} 212 -- content/p1.md -- 213 --- 214 title: "p1" 215 --- 216 217 ## Code Fences 218 219 §§§bash 220 LINE1 221 §§§ 222 223 ## Code Fences No Lexer 224 225 §§§moo 226 LINE1 227 §§§ 228 229 ## Code Fences Simple Attributes 230 231 §§A§bash { .myclass id="myid" } 232 LINE1 233 §§A§ 234 235 ## Code Fences Line Numbers 236 237 §§§bash {linenos=table,hl_lines=[8,"15-17"],linenostart=199} 238 LINE1 239 LINE2 240 LINE3 241 LINE4 242 LINE5 243 LINE6 244 LINE7 245 LINE8 246 §§§ 247 248 249 250 251 ` 252 253 // Code fences 254 files = strings.ReplaceAll(files, "§§§", "```") 255 256 b := hugolib.NewIntegrationTestBuilder( 257 hugolib.IntegrationTestConfig{ 258 T: t, 259 TxtarString: files, 260 }, 261 ).Build() 262 263 b.AssertFileContent("public/p1/index.html", 264 "<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>", 265 "Code Fences No Lexer</h2>\n<pre tabindex=\"0\"><code class=\"language-moo\" data-lang=\"moo\">LINE1\n</code></pre>", 266 "lnt", 267 ) 268 } 269 270 func BenchmarkRenderHooks(b *testing.B) { 271 files := ` 272 -- config.toml -- 273 -- layouts/_default/_markup/render-heading.html -- 274 <h{{ .Level }} id="{{ .Anchor | safeURL }}"> 275 {{ .Text | safeHTML }} 276 <a class="anchor" href="#{{ .Anchor | safeURL }}">#</a> 277 </h{{ .Level }}> 278 -- layouts/_default/_markup/render-link.html -- 279 <a href="{{ .Destination | safeURL }}"{{ with .Title}} title="{{ . }}"{{ end }}>{{ .Text | safeHTML }}</a> 280 -- layouts/_default/single.html -- 281 {{ .Content }} 282 ` 283 284 content := ` 285 286 ## Hello1 [Test](https://example.com) 287 288 A. 289 290 ## Hello2 [Test](https://example.com) 291 292 B. 293 294 ## Hello3 [Test](https://example.com) 295 296 C. 297 298 ## Hello4 [Test](https://example.com) 299 300 D. 301 302 [Test](https://example.com) 303 304 ## Hello5 305 306 307 ` 308 309 for i := 1; i < 100; i++ { 310 files += fmt.Sprintf("\n-- content/posts/p%d.md --\n"+content, i+1) 311 } 312 313 cfg := hugolib.IntegrationTestConfig{ 314 T: b, 315 TxtarString: files, 316 } 317 builders := make([]*hugolib.IntegrationTestBuilder, b.N) 318 319 for i := range builders { 320 builders[i] = hugolib.NewIntegrationTestBuilder(cfg) 321 } 322 323 b.ResetTimer() 324 325 for i := 0; i < b.N; i++ { 326 builders[i].Build() 327 } 328 } 329 330 func BenchmarkCodeblocks(b *testing.B) { 331 files := ` 332 -- config.toml -- 333 [markup] 334 [markup.highlight] 335 anchorLineNos = false 336 codeFences = true 337 guessSyntax = false 338 hl_Lines = '' 339 lineAnchors = '' 340 lineNoStart = 1 341 lineNos = false 342 lineNumbersInTable = true 343 noClasses = true 344 style = 'monokai' 345 tabWidth = 4 346 -- layouts/_default/single.html -- 347 {{ .Content }} 348 ` 349 350 content := ` 351 352 FENCEgo 353 package main 354 import "fmt" 355 func main() { 356 fmt.Println("hello world") 357 } 358 FENCE 359 360 FENCEbash 361 #!/bin/bash 362 # Usage: Hello World Bash Shell Script Using Variables 363 # Author: Vivek Gite 364 # ------------------------------------------------- 365 366 # Define bash shell variable called var 367 # Avoid spaces around the assignment operator (=) 368 var="Hello World" 369 370 # print it 371 echo "$var" 372 373 # Another way of printing it 374 printf "%s\n" "$var" 375 FENCE 376 ` 377 378 content = strings.ReplaceAll(content, "FENCE", "```") 379 380 for i := 1; i < 100; i++ { 381 files += fmt.Sprintf("\n-- content/posts/p%d.md --\n"+content, i+1) 382 } 383 384 cfg := hugolib.IntegrationTestConfig{ 385 T: b, 386 TxtarString: files, 387 } 388 builders := make([]*hugolib.IntegrationTestBuilder, b.N) 389 390 for i := range builders { 391 builders[i] = hugolib.NewIntegrationTestBuilder(cfg) 392 } 393 394 b.ResetTimer() 395 396 for i := 0; i < b.N; i++ { 397 builders[i].Build() 398 } 399 }