mirror of
https://github.com/gohugoio/hugo.git
synced 2024-05-14 13:31:58 +00:00
Compare commits
7 commits
afe67cc32c
...
c87000da6c
Author | SHA1 | Date | |
---|---|---|---|
c87000da6c | |||
509ab08c1b | |||
2d75f539e1 | |||
15a4b9b337 | |||
10a8448eee | |||
28434238db | |||
5a72de2600 |
48
docs/content/en/functions/bool.md
Normal file
48
docs/content/en/functions/bool.md
Normal file
|
@ -0,0 +1,48 @@
|
|||
---
|
||||
title: bool
|
||||
linktitle: bool
|
||||
description: Creates a `bool` from the argument passed into the function.
|
||||
date: 2023-01-28
|
||||
publishdate: 2023-01-28
|
||||
lastmod: 2023-01-28
|
||||
categories: [functions]
|
||||
menu:
|
||||
docs:
|
||||
parent: "functions"
|
||||
keywords: [strings,boolean,bool]
|
||||
signature: ["bool INPUT"]
|
||||
workson: []
|
||||
hugoversion:
|
||||
relatedfuncs: [truth]
|
||||
deprecated: false
|
||||
aliases: []
|
||||
---
|
||||
|
||||
Useful for turning ints, strings, and nil into booleans.
|
||||
|
||||
```
|
||||
{{ bool "true" }} → true
|
||||
{{ bool "false" }} → false
|
||||
|
||||
{{ bool "TRUE" }} → true
|
||||
{{ bool "FALSE" }} → false
|
||||
|
||||
{{ truth "t" }} → true
|
||||
{{ truth "f" }} → false
|
||||
|
||||
{{ truth "T" }} → true
|
||||
{{ truth "F" }} → false
|
||||
|
||||
{{ bool "1" }} → true
|
||||
{{ bool "0" }} → false
|
||||
|
||||
{{ bool 1 }} → true
|
||||
{{ bool 0 }} → false
|
||||
|
||||
{{ bool true }} → true
|
||||
{{ bool false }} → false
|
||||
|
||||
{{ bool nil }} → false
|
||||
```
|
||||
|
||||
This function will throw a type-casting error for most other types or strings. For less strict behavior, see [`truth`](/functions/truth).
|
51
docs/content/en/functions/truth.md
Normal file
51
docs/content/en/functions/truth.md
Normal file
|
@ -0,0 +1,51 @@
|
|||
---
|
||||
title: truth
|
||||
linktitle: truth
|
||||
description: Creates a `bool` from the truthyness of the argument passed into the function
|
||||
date: 2023-01-28
|
||||
publishdate: 2023-01-28
|
||||
lastmod: 2023-01-28
|
||||
categories: [functions]
|
||||
menu:
|
||||
docs:
|
||||
parent: "functions"
|
||||
keywords: [strings,boolean,bool,truthy,falsey]
|
||||
signature: ["truth INPUT"]
|
||||
workson: []
|
||||
hugoversion:
|
||||
relatedfuncs: [bool]
|
||||
deprecated: false
|
||||
aliases: []
|
||||
---
|
||||
|
||||
Useful for turning different types into booleans based on their [truthy-ness](https://developer.mozilla.org/en-US/docs/Glossary/Truthy).
|
||||
|
||||
```
|
||||
{{ truth "true" }} → true
|
||||
{{ truth "false" }} → true
|
||||
|
||||
{{ truth "TRUE" }} → true
|
||||
{{ truth "FALSE" }} → true
|
||||
|
||||
{{ truth "t" }} → true
|
||||
{{ truth "f" }} → true
|
||||
|
||||
{{ truth "T" }} → true
|
||||
{{ truth "F" }} → true
|
||||
|
||||
{{ truth "1" }} → true
|
||||
{{ truth "0" }} → true
|
||||
|
||||
{{ truth 1 }} → true
|
||||
{{ truth 0 }} → false
|
||||
|
||||
{{ truth true }} → true
|
||||
{{ truth false }} → false
|
||||
|
||||
{{ truth nil }} → false
|
||||
|
||||
{{ truth "cheese" }} → true
|
||||
{{ truth 1.67 }} → true
|
||||
```
|
||||
|
||||
This function will not throw an error. For more strict behavior, see [`bool`](/functions/bool).
|
|
@ -14,6 +14,7 @@
|
|||
package hugolib
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
@ -241,3 +242,52 @@ iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNkYPhfDwAChwGA60e6kgAA
|
|||
"p1|<p><a href=\"p2\">P2</a>", "<img src=\"pixel.png\" alt=\"Pixel\">")
|
||||
})
|
||||
}
|
||||
|
||||
func TestRenderHooksDefaultEscape(t *testing.T) {
|
||||
files := `
|
||||
-- hugo.toml --
|
||||
[markup.goldmark.renderHooks]
|
||||
[markup.goldmark.renderHooks.image]
|
||||
enableDefault = ENABLE
|
||||
[markup.goldmark.renderHooks.link]
|
||||
enableDefault = ENABLE
|
||||
[markup.goldmark.parser]
|
||||
wrapStandAloneImageWithinParagraph = false
|
||||
[markup.goldmark.parser.attribute]
|
||||
block = true
|
||||
title = true
|
||||
-- content/_index.md --
|
||||
---
|
||||
title: "Home"
|
||||
---
|
||||
Link: [text-"<>&](/destination-"<> 'title-"<>&')
|
||||
|
||||
Image: ![alt-"<>&](/destination-"<> 'title-"<>&')
|
||||
{class="><script>alert()</script>" id="baz"}
|
||||
|
||||
-- layouts/index.html --
|
||||
{{ .Content }}
|
||||
`
|
||||
|
||||
for _, enabled := range []bool{true, false} {
|
||||
enabled := enabled
|
||||
t.Run(fmt.Sprint(enabled), func(t *testing.T) {
|
||||
t.Parallel()
|
||||
b := Test(t, strings.ReplaceAll(files, "ENABLE", fmt.Sprint(enabled)))
|
||||
|
||||
// The escaping is slightly different between the two.
|
||||
if enabled {
|
||||
b.AssertFileContent("public/index.html",
|
||||
"Link: <a href=\"/destination-%22%3C%3E\" title=\"title-"<>&\">text-"<>&</a>",
|
||||
"img alt=\"alt-"<>&\" src=\"/destination-%22%3C%3E\" title=\"title-"<>&\">",
|
||||
"><script>",
|
||||
)
|
||||
} else {
|
||||
b.AssertFileContent("public/index.html",
|
||||
"Link: <a href=\"/destination-%22%3C%3E\" title=\"title-"<>&\">text-"<>&</a>",
|
||||
"Image: <img src=\"/destination-%22%3C%3E\" alt=\"alt-"<>&\" title=\"title-"<>&\">",
|
||||
)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -175,7 +175,7 @@ func (pco *pageContentOutput) RenderShortcodes(ctx context.Context) (template.HT
|
|||
// This content will be parsed and rendered by Goldmark.
|
||||
// Wrap it in a special Hugo markup to assign the correct Page from
|
||||
// the stack.
|
||||
c = hugocontext.Wrap(c, pco.po.p.pid)
|
||||
return template.HTML(hugocontext.Wrap(c, pco.po.p.pid)), nil
|
||||
}
|
||||
|
||||
return helpers.BytesToHTML(c), nil
|
||||
|
|
|
@ -34,7 +34,7 @@ func New() goldmark.Extender {
|
|||
|
||||
// Wrap wraps the given byte slice in a Hugo context that used to determine the correct Page
|
||||
// in .RenderShortcodes.
|
||||
func Wrap(b []byte, pid uint64) []byte {
|
||||
func Wrap(b []byte, pid uint64) string {
|
||||
buf := bufferpool.GetBuffer()
|
||||
defer bufferpool.PutBuffer(buf)
|
||||
buf.Write(prefix)
|
||||
|
@ -45,7 +45,7 @@ func Wrap(b []byte, pid uint64) []byte {
|
|||
buf.Write(b)
|
||||
buf.Write(prefix)
|
||||
buf.Write(closingDelimAndNewline)
|
||||
return buf.Bytes()
|
||||
return buf.String()
|
||||
}
|
||||
|
||||
var kindHugoContext = ast.NewNodeKind("HugoContext")
|
||||
|
|
|
@ -24,7 +24,7 @@ func TestWrap(t *testing.T) {
|
|||
|
||||
b := []byte("test")
|
||||
|
||||
c.Assert(string(Wrap(b, 42)), qt.Equals, "{{__hugo_ctx pid=42}}\ntest{{__hugo_ctx/}}\n")
|
||||
c.Assert(Wrap(b, 42), qt.Equals, "{{__hugo_ctx pid=42}}\ntest{{__hugo_ctx/}}\n")
|
||||
}
|
||||
|
||||
func BenchmarkWrap(b *testing.B) {
|
||||
|
|
|
@ -17,6 +17,7 @@ package cast
|
|||
import (
|
||||
"html/template"
|
||||
|
||||
"github.com/gohugoio/hugo/common/hreflect"
|
||||
_cast "github.com/spf13/cast"
|
||||
)
|
||||
|
||||
|
@ -45,6 +46,23 @@ func (ns *Namespace) ToFloat(v any) (float64, error) {
|
|||
return _cast.ToFloat64E(v)
|
||||
}
|
||||
|
||||
// ToBool converts v to a boolean.
|
||||
func (ns *Namespace) ToBool(v any) (bool, error) {
|
||||
v = convertTemplateToString(v)
|
||||
result, err := _cast.ToBoolE(v)
|
||||
if err != nil {
|
||||
return false, nil
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
|
||||
// ToTruth yields the same behavior as ToBool when possible.
|
||||
// If the cast is unsuccessful, ToTruth converts v to a boolean using the JavaScript [definition of truthy](https://developer.mozilla.org/en-US/docs/Glossary/Truthy).
|
||||
// Accordingly, it never yields an error, but maintains the signature of other cast methods for consistency.
|
||||
func (ns *Namespace) ToTruth(v any) (bool, error) {
|
||||
return hreflect.IsTruthful(v), nil
|
||||
}
|
||||
|
||||
func convertTemplateToString(v any) any {
|
||||
switch vv := v.(type) {
|
||||
case template.HTML:
|
||||
|
|
|
@ -117,3 +117,90 @@ func TestToFloat(t *testing.T) {
|
|||
c.Assert(result, qt.Equals, test.expect, errMsg)
|
||||
}
|
||||
}
|
||||
|
||||
func TestToBool(t *testing.T) {
|
||||
t.Parallel()
|
||||
c := qt.New(t)
|
||||
ns := New()
|
||||
|
||||
for i, test := range []struct {
|
||||
v any
|
||||
expect any
|
||||
error any
|
||||
}{
|
||||
{"true", true, nil},
|
||||
{"false", false, nil},
|
||||
{"TRUE", true, nil},
|
||||
{"FALSE", false, nil},
|
||||
{"t", true, nil},
|
||||
{"f", false, nil},
|
||||
{"T", true, nil},
|
||||
{"F", false, nil},
|
||||
{"1", true, nil},
|
||||
{"0", false, nil},
|
||||
{1, true, nil},
|
||||
{0, false, nil},
|
||||
{true, true, nil},
|
||||
{false, false, nil},
|
||||
{nil, false, nil},
|
||||
|
||||
{"cheese", false, nil},
|
||||
{"", false, nil},
|
||||
} {
|
||||
errMsg := qt.Commentf("[%d] %v", i, test.v)
|
||||
|
||||
result, err := ns.ToBool(test.v)
|
||||
|
||||
if b, ok := test.error.(bool); ok && !b {
|
||||
c.Assert(err, qt.Not(qt.IsNil), errMsg)
|
||||
continue
|
||||
}
|
||||
|
||||
c.Assert(err, qt.IsNil, errMsg)
|
||||
c.Assert(result, qt.Equals, test.expect, errMsg)
|
||||
}
|
||||
}
|
||||
|
||||
func TestToTruth(t *testing.T) {
|
||||
t.Parallel()
|
||||
c := qt.New(t)
|
||||
ns := New()
|
||||
|
||||
for i, test := range []struct {
|
||||
v any
|
||||
expect any
|
||||
}{
|
||||
{"true", true},
|
||||
{"false", true},
|
||||
{"TRUE", true},
|
||||
{"FALSE", true},
|
||||
{"t", true},
|
||||
{"f", true},
|
||||
{"T", true},
|
||||
{"F", true},
|
||||
{"1", true},
|
||||
{"0", true},
|
||||
{1, true},
|
||||
{0, false},
|
||||
{"cheese", true},
|
||||
{"", false},
|
||||
{1.67, true},
|
||||
{template.HTML("2"), true},
|
||||
{template.CSS("3"), true},
|
||||
{template.HTMLAttr("4"), true},
|
||||
{template.JS("-5.67"), true},
|
||||
{template.JSStr("6"), true},
|
||||
{t, true},
|
||||
{nil, false},
|
||||
{"null", true},
|
||||
{"undefined", true},
|
||||
{"NaN", true},
|
||||
} {
|
||||
errMsg := qt.Commentf("[%d] %v", i, test.v)
|
||||
|
||||
result, err := ns.ToTruth(test.v)
|
||||
|
||||
c.Assert(err, qt.IsNil, errMsg)
|
||||
c.Assert(result, qt.Equals, test.expect, errMsg)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -52,6 +52,24 @@ func init() {
|
|||
},
|
||||
)
|
||||
|
||||
ns.AddMethodMapping(ctx.ToBool,
|
||||
[]string{"bool"},
|
||||
[][2]string{
|
||||
{`{{ "0" | bool | printf "%T" }}`, `bool`},
|
||||
{`{{ "true" | bool }}`, `true`},
|
||||
{`{{ "false" | bool }}`, `false`},
|
||||
},
|
||||
)
|
||||
|
||||
ns.AddMethodMapping(ctx.ToTruth,
|
||||
[]string{"truth"},
|
||||
[][2]string{
|
||||
{`{{ "1234" | truth | printf "%T" }}`, `bool`},
|
||||
{`{{ "1234" | truth }}`, `true`},
|
||||
{`{{ "" | truth }}`, `false`},
|
||||
},
|
||||
)
|
||||
|
||||
return ns
|
||||
}
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
{{- $src = .RelPermalink -}}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
{{- $attributes := merge .Attributes (dict "alt" .Text "src" $src "title" .Title) -}}
|
||||
{{- $attributes := merge .Attributes (dict "alt" .Text "src" $src "title" (.Title | transform.HTMLEscape)) -}}
|
||||
<img
|
||||
{{- range $k, $v := $attributes -}}
|
||||
{{- if $v -}}
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
{{- end -}}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
{{- $attributes := dict "href" $href "title" .Title -}}
|
||||
{{- $attributes := dict "href" $href "title" (.Title | transform.HTMLEscape) -}}
|
||||
<a
|
||||
{{- range $k, $v := $attributes -}}
|
||||
{{- if $v -}}
|
||||
|
|
|
@ -48,7 +48,7 @@
|
|||
<title>{{ if eq .Title .Site.Title }}{{ .Site.Title }}{{ else }}{{ with .Title }}{{ . }} on {{ end }}{{ .Site.Title }}{{ end }}</title>
|
||||
<link>{{ .Permalink }}</link>
|
||||
<description>Recent content {{ if ne .Title .Site.Title }}{{ with .Title }}in {{ . }} {{ end }}{{ end }}on {{ .Site.Title }}</description>
|
||||
<generator>Hugo {{ hugo.Version }}</generator>
|
||||
<generator>Hugo</generator>
|
||||
<language>{{ site.Language.LanguageCode }}</language>{{ with $authorEmail }}
|
||||
<managingEditor>{{.}}{{ with $authorName }} ({{ . }}){{ end }}</managingEditor>{{ end }}{{ with $authorEmail }}
|
||||
<webMaster>{{ . }}{{ with $authorName }} ({{ . }}){{ end }}</webMaster>{{ end }}{{ with .Site.Copyright }}
|
||||
|
|
|
@ -8,10 +8,10 @@ Renders an embedded YouTube video.
|
|||
@param {int} [end] The time, measured in seconds from the start of the video, when the player should stop playing the video.
|
||||
@param {string} [id] The video id. Optional if the id is provided as first positional argument.
|
||||
@param {string} [loading=eager] The loading attribute of the iframe element.
|
||||
@param {bool} [loop=false] Whether to indefinitely repeat the video.
|
||||
@param {bool} [loop=false] Whether to indefinitely repeat the video. Ignores the start and end arguments after the first play.
|
||||
@param {bool} [mute=false] Whether to mute the video. Always true when autoplay is true.
|
||||
@param {int} [start] The time, measured in seconds from the start of the video, when the player should start playing the video.
|
||||
@param {string} [title] The title attribute of the iframe element. Defaults to the title returned by YouTube oEmbed API.
|
||||
@param {string} [title] The title attribute of the iframe element. Defaults to "YouTube video".
|
||||
|
||||
@returns {template.HTML}
|
||||
|
||||
|
@ -26,20 +26,6 @@ Renders an embedded YouTube video.
|
|||
{{- if not $pc.Disable }}
|
||||
{{- with $id := or (.Get "id") (.Get 0) }}
|
||||
|
||||
{{- /* Get data from the YouTube oEmbed API. */}}
|
||||
{{- $q := querify "url" (printf "https://www.youtube.com/watch?v=%s" $id) "format" "json" }}
|
||||
{{- $url := printf "https://www.youtube.com/oembed?%s" $q }}
|
||||
{{- $data := dict }}
|
||||
{{- with resources.GetRemote $url }}
|
||||
{{- with .Err }}
|
||||
{{- erroridf $remoteErrID "The %q shortcode was unable to get remote resource %q. %s. See %s" $.Name $url . $.Position }}
|
||||
{{- else }}
|
||||
{{- $data = .Content | transform.Unmarshal }}
|
||||
{{- end }}
|
||||
{{- else }}
|
||||
{{- erroridf $remoteErrID "The %q shortcode was unable to get remote resource %q. See %s" $.Name $url $.Position }}
|
||||
{{- end }}
|
||||
|
||||
{{/* Set defaults. */}}
|
||||
{{- $allowFullScreen := "allowfullscreen" }}
|
||||
{{- $autoplay := 0 }}
|
||||
|
@ -50,7 +36,7 @@ Renders an embedded YouTube video.
|
|||
{{- $loop := 0 }}
|
||||
{{- $mute := 0 }}
|
||||
{{- $start := 0 }}
|
||||
{{- $title := $data.title }}
|
||||
{{- $title := "YouTube video" }}
|
||||
|
||||
{{- /* Get arguments. */}}
|
||||
{{- if in (slice "false" false 0) ($.Get "allowFullScreen") }}
|
||||
|
|
Loading…
Reference in a new issue