Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[pull] master from gohugoio:master #1464

Merged
merged 6 commits into from
Jan 16, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion common/paths/url.go
Original file line number Diff line number Diff line change
Expand Up @@ -228,7 +228,7 @@ func UrlFromFilename(filename string) (*url.URL, error) {
}, nil
}

// UrlToFilename converts the URL s to a filename.
// UrlStringToFilename converts the URL s to a filename.
// If ParseRequestURI fails, the input is just converted to OS specific slashes and returned.
func UrlStringToFilename(s string) (string, bool) {
u, err := url.ParseRequestURI(s)
Expand Down
22 changes: 22 additions & 0 deletions config/allconfig/allconfig.go
Original file line number Diff line number Diff line change
Expand Up @@ -402,6 +402,28 @@ func (c *Config) CompileConfig(logger loggers.Logger) error {
c.Pagination.Path = c.PaginatePath
}

// Legacy privacy values.
if c.Privacy.Twitter.Disable {
hugo.Deprecate("site config key privacy.twitter.disable", "Use privacy.x.disable instead.", "v0.141.0")
c.Privacy.X.Disable = c.Privacy.Twitter.Disable
}

if c.Privacy.Twitter.EnableDNT {
hugo.Deprecate("site config key privacy.twitter.enableDNT", "Use privacy.x.enableDNT instead.", "v0.141.0")
c.Privacy.X.EnableDNT = c.Privacy.Twitter.EnableDNT
}

if c.Privacy.Twitter.Simple {
hugo.Deprecate("site config key privacy.twitter.simple", "Use privacy.x.simple instead.", "v0.141.0")
c.Privacy.X.Simple = c.Privacy.Twitter.Simple
}

// Legacy services values.
if c.Services.Twitter.DisableInlineCSS {
hugo.Deprecate("site config key services.twitter.disableInlineCSS", "Use services.x.disableInlineCSS instead.", "v0.141.0")
c.Services.X.DisableInlineCSS = c.Services.Twitter.DisableInlineCSS
}

c.C = &ConfigCompiled{
Timeout: timeout,
BaseURL: baseURL,
Expand Down
24 changes: 20 additions & 4 deletions config/privacy/privacyConfig.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,10 @@ type Config struct {
Disqus Disqus
GoogleAnalytics GoogleAnalytics
Instagram Instagram
Twitter Twitter
Twitter Twitter // deprecated in favor of X in v0.141.0
Vimeo Vimeo
YouTube YouTube
X X
}

// Disqus holds the privacy configuration settings related to the Disqus template.
Expand All @@ -58,7 +59,8 @@ type Instagram struct {
Simple bool
}

// Twitter holds the privacy configuration settingsrelated to the Twitter shortcode.
// Twitter holds the privacy configuration settings related to the Twitter shortcode.
// Deprecated in favor of X in v0.141.0.
type Twitter struct {
Service `mapstructure:",squash"`

Expand All @@ -70,7 +72,7 @@ type Twitter struct {
Simple bool
}

// Vimeo holds the privacy configuration settingsrelated to the Vimeo shortcode.
// Vimeo holds the privacy configuration settings related to the Vimeo shortcode.
type Vimeo struct {
Service `mapstructure:",squash"`

Expand All @@ -84,7 +86,7 @@ type Vimeo struct {
Simple bool
}

// YouTube holds the privacy configuration settingsrelated to the YouTube shortcode.
// YouTube holds the privacy configuration settings related to the YouTube shortcode.
type YouTube struct {
Service `mapstructure:",squash"`

Expand All @@ -94,6 +96,20 @@ type YouTube struct {
PrivacyEnhanced bool
}

// X holds the privacy configuration settings related to the X shortcode.
type X struct {
Service `mapstructure:",squash"`

// When set to true, the X post and its embedded page on your site are not
// used for purposes that include personalized suggestions and personalized
// ads.
EnableDNT bool

// If simple mode is enabled, a static and no-JS version of the X post will
// be built.
Simple bool
}

// DecodeConfig creates a privacy Config from a given Hugo configuration.
func DecodeConfig(cfg config.Provider) (pc Config, err error) {
if !cfg.IsSet(privacyConfigKey) {
Expand Down
7 changes: 6 additions & 1 deletion config/privacy/privacyConfig_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,10 @@ simple = true
disable = true
enableDNT = true
simple = true
[privacy.x]
disable = true
enableDNT = true
simple = true
[privacy.vimeo]
disable = true
enableDNT = true
Expand All @@ -61,7 +65,8 @@ simple = true
pc.GoogleAnalytics.RespectDoNotTrack, pc.Instagram.Disable,
pc.Instagram.Simple, pc.Twitter.Disable, pc.Twitter.EnableDNT,
pc.Twitter.Simple, pc.Vimeo.Disable, pc.Vimeo.EnableDNT, pc.Vimeo.Simple,
pc.YouTube.PrivacyEnhanced, pc.YouTube.Disable,
pc.YouTube.PrivacyEnhanced, pc.YouTube.Disable, pc.X.Disable, pc.X.EnableDNT,
pc.X.Simple,
}

c.Assert(got, qt.All(qt.Equals), true)
Expand Down
12 changes: 11 additions & 1 deletion config/services/servicesConfig.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,8 @@ type Config struct {
Disqus Disqus
GoogleAnalytics GoogleAnalytics
Instagram Instagram
Twitter Twitter
Twitter Twitter // deprecated in favor of X in v0.141.0
X X
RSS RSS
}

Expand Down Expand Up @@ -61,13 +62,22 @@ type Instagram struct {
}

// Twitter holds the functional configuration settings related to the Twitter shortcodes.
// Deprecated in favor of X in v0.141.0.
type Twitter struct {
// The Simple variant of Twitter is decorated with a basic set of inline styles.
// This means that if you want to provide your own CSS, you want
// to disable the inline CSS provided by Hugo.
DisableInlineCSS bool
}

// X holds the functional configuration settings related to the X shortcodes.
type X struct {
// The Simple variant of X is decorated with a basic set of inline styles.
// This means that if you want to provide your own CSS, you want
// to disable the inline CSS provided by Hugo.
DisableInlineCSS bool
}

// RSS holds the functional configuration settings related to the RSS feeds.
type RSS struct {
// Limit the number of pages.
Expand Down
2 changes: 2 additions & 0 deletions config/services/servicesConfig_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@ id = "ga_id"
disableInlineCSS = true
[services.twitter]
disableInlineCSS = true
[services.x]
disableInlineCSS = true
`
cfg, err := config.FromConfigString(tomlConfig, "toml")
c.Assert(err, qt.IsNil)
Expand Down
1 change: 1 addition & 0 deletions docs/content/en/commands/hugo_config.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ hugo config [command] [flags]
--format string preferred file format (toml, yaml or json) (default "toml")
-h, --help help for config
--lang string the language to display config for. Defaults to the first language defined.
--printZero include config options with zero values (e.g. false, 0, "") in the output
--renderSegments strings named segments to render (configured in the segments config)
-t, --theme strings themes to use (located in /themes/THEMENAME/)
```
Expand Down
4 changes: 2 additions & 2 deletions docs/content/en/render-hooks/headings.md
Original file line number Diff line number Diff line change
Expand Up @@ -64,15 +64,15 @@ In its default configuration, Hugo renders Markdown headings according to the [C
[CommonMark specification]: https://spec.commonmark.org/current/

{{< code file=layouts/_default/_markup/render-heading.html copy=true >}}
<h{{ .Level }} id="{{ .Anchor }}">
<h{{ .Level }} id="{{ .Anchor }}" {{- with .Attributes.class }} class="{{ . }}" {{- end }}>
{{- .Text -}}
</h{{ .Level }}>
{{< /code >}}

To add an anchor link to the right of each heading:

{{< code file=layouts/_default/_markup/render-heading.html copy=true >}}
<h{{ .Level }} id="{{ .Anchor }}">
<h{{ .Level }} id="{{ .Anchor }}" {{- with .Attributes.class }} class="{{ . }}" {{- end }}>
{{ .Text }}
<a href="#{{ .Anchor }}">#</a>
</h{{ .Level }}>
Expand Down
6 changes: 3 additions & 3 deletions docs/content/en/render-hooks/images.md
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ In its default configuration, Hugo renders Markdown images according to the [Com

{{< code file=layouts/_default/_markup/render-image.html copy=true >}}
<img src="{{ .Destination | safeURL }}"
{{- with .Text }} alt="{{ . }}"{{ end -}}
{{- with .PlainText }} alt="{{ . }}"{{ end -}}
{{- with .Title }} title="{{ . }}"{{ end -}}
>
{{- /* chomp trailing newline */ -}}
Expand All @@ -103,13 +103,13 @@ To render standalone images within `figure` elements:
{{- if .IsBlock -}}
<figure>
<img src="{{ .Destination | safeURL }}"
{{- with .Text }} alt="{{ . }}"{{ end -}}
{{- with .PlainText }} alt="{{ . }}"{{ end -}}
>
{{- with .Title }}<figcaption>{{ . }}</figcaption>{{ end -}}
</figure>
{{- else -}}
<img src="{{ .Destination | safeURL }}"
{{- with .Text }} alt="{{ . }}"{{ end -}}
{{- with .PlainText }} alt="{{ . }}"{{ end -}}
{{- with .Title }} title="{{ . }}"{{ end -}}
>
{{- end -}}
Expand Down
26 changes: 26 additions & 0 deletions htesting/hqt/checkers.go
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,32 @@ func normalizeString(s string) string {
return strings.Join(lines, "\n")
}

// IsAllElementsEqual asserts that all elements in the slice are equal.
var IsAllElementsEqual qt.Checker = &sliceAllElementsEqualChecker{
argNames: []string{"got"},
}

type sliceAllElementsEqualChecker struct {
argNames
}

func (c *sliceAllElementsEqualChecker) Check(got any, args []any, note func(key string, value any)) (err error) {
gotSlice := reflect.ValueOf(got)
numElements := gotSlice.Len()
if numElements < 2 {
return nil
}
first := gotSlice.Index(0).Interface()
// Check that the others are equal to the first.
for i := 1; i < numElements; i++ {
if diff := cmp.Diff(first, gotSlice.Index(i).Interface()); diff != "" {
return fmt.Errorf("element %d is not equal to the first element:\n%s", i, diff)
}
}

return nil
}

// DeepAllowUnexported creates an option to allow compare of unexported types
// in the given list of types.
// see https://github.com/google/go-cmp/issues/40#issuecomment-328615283
Expand Down
2 changes: 2 additions & 0 deletions hugolib/testhelpers_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -262,6 +262,8 @@ respectDoNotTrack = true
simple = true
[privacy.twitter]
enableDNT = true
[privacy.x]
enableDNT = true
[privacy.vimeo]
disable = false
[privacy.youtube]
Expand Down
1 change: 1 addition & 0 deletions tpl/tplimpl/embedded/templates/shortcodes/twitter.html
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
{{- warnf "The \"twitter\", \"tweet\", and \"twitter_simple\" shortcodes were deprecated in v0.142.0 and will be removed in a future release. Please use the \"x\" shortcode instead." }}
{{- $pc := .Page.Site.Config.Privacy.Twitter -}}
{{- if not $pc.Disable -}}
{{- if $pc.Simple -}}
Expand Down
19 changes: 11 additions & 8 deletions tpl/tplimpl/embedded/templates/shortcodes/twitter_simple.html
Original file line number Diff line number Diff line change
@@ -1,34 +1,37 @@
{{- $pc := .Page.Site.Config.Privacy.Twitter -}}
{{- $sc := .Page.Site.Config.Services.Twitter -}}
{{- if not $pc.Disable -}}
{{- warnf "The \"twitter\", \"tweet\", and \"twitter_simple\" shortcodes were deprecated in v0.142.0 and will be removed in a future release. Please use the \"x\" shortcode instead." }}
{{- if not site.Config.Privacy.Twitter.Disable -}}
{{- $id := or (.Get "id") "" -}}
{{- $user := or (.Get "user") "" -}}
{{- if and $id $user -}}
{{- template "render-simple-tweet" (dict "id" $id "user" $user "dnt" $pc.EnableDNT "name" .Name "position" .Position) -}}
{{- template "render-simple-tweet" (dict "id" $id "user" $user "ctx" .) -}}
{{- else -}}
{{- errorf "The %q shortcode requires two named parameters: user and id. See %s" .Name .Position -}}
{{- end -}}
{{- end -}}

{{- define "render-simple-tweet" -}}
{{- $dnt := site.Config.Privacy.Twitter.EnableDNT }}
{{- $url := printf "https://twitter.com/%v/status/%v" .user .id -}}
{{- $query := querify "url" $url "dnt" .dnt "omit_script" true -}}
{{- $query := querify "url" $url "dnt" $dnt "omit_script" true -}}
{{- $request := printf "https://publish.twitter.com/oembed?%s" $query -}}
{{- with try (resources.GetRemote $request) -}}
{{- with .Err -}}
{{- errorf "%s" . -}}
{{- else with .Value -}}
{{- if not site.Config.Services.Twitter.DisableInlineCSS }}
{{- template "__h_simple_twitter_css" (dict "ctx" $.ctx) }}
{{- end }}
{{- (. | transform.Unmarshal).html | safeHTML -}}
{{- else -}}
{{- warnidf "shortcode-twitter-simple-getremote" "The %q shortcode was unable to retrieve the remote data. See %s" .name .position -}}
{{- warnidf "shortcode-twitter-simple-getremote" "The %q shortcode was unable to retrieve the remote data. See %s" .ctx.Name .ctx.Position -}}
{{- end -}}
{{- end -}}
{{- end -}}

{{- define "__h_simple_twitter_css" -}}
{{- if not (.Page.Scratch.Get "__h_simple_twitter_css") -}}
{{- if not (.ctx.Page.Store.Get "__h_simple_twitter_css") -}}
{{/* Only include once */}}
{{- .Page.Scratch.Set "__h_simple_twitter_css" true -}}
{{- .ctx.Page.Store.Set "__h_simple_twitter_css" true -}}
<style type="text/css">
.twitter-tweet {
font:
Expand Down
29 changes: 29 additions & 0 deletions tpl/tplimpl/embedded/templates/shortcodes/x.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
{{- $pc := .Page.Site.Config.Privacy.X -}}
{{- if not $pc.Disable -}}
{{- if $pc.Simple -}}
{{- template "_internal/shortcodes/x_simple.html" . -}}
{{- else -}}
{{- $id := or (.Get "id") "" -}}
{{- $user := or (.Get "user") "" -}}
{{- if and $id $user -}}
{{- template "render-x" (dict "id" $id "user" $user "dnt" $pc.EnableDNT "name" .Name "position" .Position) -}}
{{- else -}}
{{- errorf "The %q shortcode requires two named parameters: user and id. See %s" .Name .Position -}}
{{- end -}}
{{- end -}}
{{- end -}}

{{- define "render-x" -}}
{{- $url := printf "https://x.com/%v/status/%v" .user .id -}}
{{- $query := querify "url" $url "dnt" .dnt -}}
{{- $request := printf "https://publish.x.com/oembed?%s" $query -}}
{{- with try (resources.GetRemote $request) -}}
{{- with .Err -}}
{{- errorf "%s" . -}}
{{- else with .Value -}}
{{- (. | transform.Unmarshal).html | safeHTML -}}
{{- else -}}
{{- warnidf "shortcode-x-getremote" "The %q shortcode was unable to retrieve the remote data. See %s" .name .position -}}
{{- end -}}
{{- end -}}
{{- end -}}
60 changes: 60 additions & 0 deletions tpl/tplimpl/embedded/templates/shortcodes/x_simple.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
{{- if not site.Config.Privacy.X.Disable -}}
{{- $id := or (.Get "id") "" -}}
{{- $user := or (.Get "user") "" -}}
{{- if and $id $user -}}
{{- template "render-simple-x" (dict "id" $id "user" $user "ctx" .) -}}
{{- else -}}
{{- errorf "The %q shortcode requires two named parameters: user and id. See %s" .Name .Position -}}
{{- end -}}
{{- end -}}

{{- define "render-simple-x" -}}
{{- $dnt := site.Config.Privacy.X.EnableDNT }}
{{- $url := printf "https://x.com/%v/status/%v" .user .id -}}
{{- $query := querify "url" $url "dnt" $dnt "omit_script" true -}}
{{- $request := printf "https://publish.x.com/oembed?%s" $query -}}
{{- with try (resources.GetRemote $request) -}}
{{- with .Err -}}
{{- errorf "%s" . -}}
{{- else with .Value -}}
{{- if not site.Config.Services.X.DisableInlineCSS }}
{{- template "__h_simple_x_css" (dict "ctx" $.ctx) }}
{{- end }}
{{- (. | transform.Unmarshal).html | safeHTML -}}
{{- else -}}
{{- warnidf "shortcode-x-simple-getremote" "The %q shortcode was unable to retrieve the remote data. See %s" .ctx.Name .ctx.Position -}}
{{- end -}}
{{- end -}}
{{- end -}}

{{- define "__h_simple_x_css" -}}
{{- if not (.ctx.Page.Store.Get "__h_simple_x_css") -}}
{{/* Only include once */}}
{{- .ctx.Page.Store.Set "__h_simple_x_css" true -}}
<style type="text/css">
.twitter-tweet {
font:
14px/1.45 -apple-system,
BlinkMacSystemFont,
"Segoe UI",
Roboto,
Oxygen-Sans,
Ubuntu,
Cantarell,
"Helvetica Neue",
sans-serif;
border-left: 4px solid #2b7bb9;
padding-left: 1.5em;
color: #555;
}
.twitter-tweet a {
color: #2b7bb9;
text-decoration: none;
}
blockquote.twitter-tweet a:hover,
blockquote.twitter-tweet a:focus {
text-decoration: underline;
}
</style>
{{- end -}}
{{- end -}}
Loading
Loading