From aaf0c707a2ee77896890c34b9d9990040aff448b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=B6ren=20Weber?= Date: Fri, 7 Feb 2025 14:28:26 +0100 Subject: [PATCH] link: introduce effects #850 #1008 - new link effects: target download - effects can now be strings besides bools (to allow for custom download attribute on links) - remove "no*" classes form image as they don't make sense for string effects and are cluttering the image class list for newly introduced effects - refactor attribute parsing for later reusage in menu generation, button topbar, etc. --- .../quickstart => assets/images}/magic.gif | Bin docs/content/authoring/markdown.en.md | 28 ++++++ .../customization/imageeffects.en.md | 12 +-- .../introduction/quickstart/_index.en.md | 2 +- .../introduction/releasenotes/7/4.en.md | 19 +++- .../partials/_relearn/imageAttributes.gotmpl | 71 ++++++++++++++ .../partials/_relearn/linkAttributes.gotmpl | 72 ++++++++++++++ layouts/partials/shortcodes/image.html | 92 +++++------------- layouts/partials/shortcodes/link.html | 25 +++-- layouts/partials/version.txt | 2 +- 10 files changed, 230 insertions(+), 93 deletions(-) rename docs/{content/introduction/quickstart => assets/images}/magic.gif (100%) create mode 100644 layouts/partials/_relearn/imageAttributes.gotmpl create mode 100644 layouts/partials/_relearn/linkAttributes.gotmpl diff --git a/docs/content/introduction/quickstart/magic.gif b/docs/assets/images/magic.gif similarity index 100% rename from docs/content/introduction/quickstart/magic.gif rename to docs/assets/images/magic.gif diff --git a/docs/content/authoring/markdown.en.md b/docs/content/authoring/markdown.en.md index e0d3aaf2fc..f3c8d490bc 100644 --- a/docs/content/authoring/markdown.en.md +++ b/docs/content/authoring/markdown.en.md @@ -681,6 +681,34 @@ That's some more text with a footnote.[^someid] Blue light glows blue. {{% /notice %}} +### Link Effects + +{{% badge color="#7dc903" icon="fa-fw fas fa-puzzle-piece" %}}Relearn{{% /badge %}} This theme allows additional non-standard formatting by setting query parameter at the end of the URL. See the [link effects docs](authoring/linkeffects) for a detailed example and how to configure it. + +#### Target + +Add query parameter `target=_self` or `target=_blank` to override [site-wide settings](authoring/frontmatter/linking#opening-links) of [the target behavior](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/a#target) individuallly for each link. + +````md +[Magic in new window](images/magic.gif?target=_blank) +```` + +{{% notice style="code" icon="eye" title="Result" %}} +[Magic in new window](images/magic.gif?target=_blank) +{{% /notice %}} + +#### Download + +Add query parameter `download` or `download=myfile.gif` to force your browser [to download the link target](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/a#download) instead of opening it. + +````md +[Magic as a download](images/magic.gif?download) +```` + +{{% notice style="code" icon="eye" title="Result" %}} +[Magic as a download](images/magic.gif?download) +{{% /notice %}} + ## Images ### Basic Images diff --git a/docs/content/configuration/customization/imageeffects.en.md b/docs/content/configuration/customization/imageeffects.en.md index 3f3bba39c4..8a92e0463f 100644 --- a/docs/content/configuration/customization/imageeffects.en.md +++ b/docs/content/configuration/customization/imageeffects.en.md @@ -56,27 +56,21 @@ With this configuration in effect, the following URL would result in ````html {title="HTML"} -Minion +Minion ```` ## Styling Effects -If the resulting effect value is - -- `true`: add a class with the effect's name -- `false`: add a class with the effect's name and a "no" prefix +If the resulting effect value is `true` a class with the effect's name will be added. Styles for default effects are contained in the theme. Add styles for your custom effects to `layouts/partials/content-header.html`. -For the above example you could add styles for both boolean cases: +For the above custom effect you could add the following style: ````html {title="layouts/partials/content-header.html"} ```` diff --git a/docs/content/introduction/quickstart/_index.en.md b/docs/content/introduction/quickstart/_index.en.md index ca938af756..d07f827efe 100644 --- a/docs/content/introduction/quickstart/_index.en.md +++ b/docs/content/introduction/quickstart/_index.en.md @@ -127,7 +127,7 @@ Open [http://localhost:1313](http://localhost:1313) in your web browser. You can keep the server running while you edit. The browser will update automatically when you save changes. -{{% figure src="magic.gif" link="https://gohugo.io" alt="Magic" caption="It's a kind of magic" %}} +{{% figure src="images/magic.gif" link="https://gohugo.io" alt="Magic" caption="It's a kind of magic" %}} ## Build and Deploy diff --git a/docs/content/introduction/releasenotes/7/4.en.md b/docs/content/introduction/releasenotes/7/4.en.md index 888ab1bdad..3cba5a2495 100644 --- a/docs/content/introduction/releasenotes/7/4.en.md +++ b/docs/content/introduction/releasenotes/7/4.en.md @@ -10,9 +10,24 @@ weight = -4 ### New -- {{% badge style="info" icon="plus-circle" title=" " %}}New{{% /badge %}} If [`link.errorlevel` is configured](authoring/frontmatter/linking/#enabling-link-and-image-link-warnings), now also the `pageRef` of a [Hugo menu item](https://gohugo.io/content-management/menus/) and the `menuPageRef` in a [page's front matter](configuration/sidebar/menus/#displaying-arbitrary-links-in-a-page-menu) will be checked for existence. +- {{% badge style="info" icon="plus-circle" title=" " %}}New{{% /badge %}} The theme now allows page references (given as `pageRef` of a [Hugo menu item](https://gohugo.io/content-management/menus/), `pageRef` parameter of a [`sidebarmenus` entry ](configuration/sidebar/menus#defining-sidebar-menus) and the `menuPageRef` in a [page's front matter](configuration/sidebar/menus/#displaying-arbitrary-links-in-a-page-menu)) to also be global resources from your `assets` directory. -- {{% badge style="info" icon="plus-circle" title=" " %}}New{{% /badge %}} You can now [configure an ignore list](authoring/frontmatter/linking/#ignoring-false-negatives) of addresses that should be ignored if an errorlevel test fails. This is configured by setting `errorignore=[]` in your `hugo.toml`. This helps to remove false negatives from the output while still benefitting from the check for all other addresses. +- {{% badge style="info" icon="plus-circle" title=" " %}}New{{% /badge %}} If [`link.errorlevel` is configured](authoring/frontmatter/linking/#enabling-link-and-image-link-warnings), now also page references will be checked for existence. + +- {{% badge style="info" icon="plus-circle" title=" " %}}New{{% /badge %}} It is now possible to add query parameter and an optional fragment part to all links. This is regardless whether it is a local or remote address and also applies to Hugo's internal path. + + By that you can now use it on Markdown links, image links, page references. + +- {{% badge style="info" icon="plus-circle" title=" " %}}New{{% /badge %}} This release introduces [link effects](authoring/markdown#link-effects) which work similar to [image effects](authoring/markdown#image-effects) and can be set as query parameter on any link. + + With that you currently can specify + + - a link target individually for each link + - that a link should result in a file download in your browser + +- {{% badge style="info" icon="plus-circle" title=" " %}}New{{% /badge %}} You can now [configure an ignore list](authoring/frontmatter/linking/#ignoring-false-negatives) of addresses that should be ignored if an errorlevel test fails. This is configured by setting `errorignore=[]` globally in your `hugo.toml` for all errorlevel checks. + + This helps to remove false negatives while still benefitting from the check for all other addresses. - {{% badge style="info" icon="plus-circle" title=" " %}}New{{% /badge %}} The theme supports the new [`source` output format](configuration/sitemanagement/outputformats/#source-support) which behaves similar in configuration as the `markdown` output format but allows the original Markdown source including the front matter of a page to be viewed. diff --git a/layouts/partials/_relearn/imageAttributes.gotmpl b/layouts/partials/_relearn/imageAttributes.gotmpl new file mode 100644 index 0000000000..6ad73f485e --- /dev/null +++ b/layouts/partials/_relearn/imageAttributes.gotmpl @@ -0,0 +1,71 @@ +{{- $attributes := dict }} +{{- $height := "auto" }} +{{- $width := "auto" }} +{{- $effects := dict "border" false "lazy" true "lightbox" true "shadow" false }} +{{- if .page.Site.Params.imageeffects }} + {{- $effects = merge $effects .page.Site.Params.imageeffects }} +{{- end }} +{{- if .page.Params.imageEffects }} + {{- $effects = merge $effects .page.Params.imageEffects }} +{{- end }} +{{- $u := urls.Parse .url }} +{{- if $u.RawQuery }} + {{- if $u.Query.Has "classes" }} + {{- $classes := slice | append (split ($u.Query.Get "classes") ",") }} + {{- range $classes }} + {{- $k := . }} + {{- $v := true }} + {{- if strings.HasPrefix $k "no" }} + {{- $k := strings.TrimPrefix "no" $k }} + {{- $v := false }} + {{- end }} + {{- $effects = merge $effects (dict $k $v) }} + {{- end }} + {{- end }} + {{- if $u.Query.Has "featherlight" }} + {{- $filepath := "[virtual file]" }}{{ with and .page .page.File .page.File.Filename }}{{ $filepath = . }}{{ end }} + {{- warnf "%q: DEPRECATED usage of 'featherlight' image CSS class found, use 'lightbox' instead; see https://mcshelby.github.io/hugo-theme-relearn/introduction/releasenotes/5/#5-11-0" $filepath }} + {{- $effects = merge $effects (dict "lightbox" (ne ($u.Query.Get "featherlight") "false")) }} + {{- end }} + {{- range $k, $v := $effects }} + {{- if $u.Query.Has $k }} + {{- $effects = merge $effects (dict $k (ne ($u.Query.Get $k) "false")) }} + {{- end }} + {{- end }} + {{- range $k, $v := $effects }} + {{- if $u.Query.Has $k }} + {{- $paramValue := $u.Query.Get $k }} + {{- $newValue := true }} + {{- if eq $paramValue "" }} + {{- $newValue = true }} + {{- else if eq $paramValue "true" }} + {{- $newValue = true }} + {{- else if eq $paramValue "false" }} + {{- $newValue = false }} + {{- else }} + {{- $newValue = $paramValue }} + {{- end }} + {{- $effects = merge $effects (dict $k $newValue) }} + {{- end }} + {{- end }} + {{- with $u.Query.Get "height" }} + {{- $height = . }} + {{- end }} + {{- with $u.Query.Get "width" }} + {{- $width = . }} + {{- end }} +{{- end }} +{{- $classes := slice }} +{{- range $k, $v := $effects }} + {{- if $v }} + {{- if eq (printf "%T" $v) "bool" }} + {{- $classes = $classes | append $k }} + {{- end }} + {{- end }} +{{- end }} +{{- if $attributes.class }}{{ $classes = $classes | append $attributes.class }}{{ end }} +{{- $attributes = merge $attributes (dict "class" (delimit $classes " ")) }} +{{- $attributes = merge $attributes (dict "src" .url) }} +{{- $attributes = merge $attributes (dict "style" (printf " height: %s; width: %s;%s" $height $width (index $attributes "style" | default ""))) }} +{{- if $effects.lazy }}{{ $attributes = merge $attributes (dict "loading" "lazy") }}{{ end }} +{{- return $attributes }} \ No newline at end of file diff --git a/layouts/partials/_relearn/linkAttributes.gotmpl b/layouts/partials/_relearn/linkAttributes.gotmpl new file mode 100644 index 0000000000..6827516620 --- /dev/null +++ b/layouts/partials/_relearn/linkAttributes.gotmpl @@ -0,0 +1,72 @@ +{{- $attributes := dict }} +{{- /* target will be boolean false if no user defined value was set and effect default should be applied */}} +{{- $target := false }} +{{- $u := urls.Parse .url }} +{{- if $u.IsAbs }} + {{- $attributes = merge $attributes (dict "rel" "external") }} + {{- $target = "_blank" }} + {{- if isset .page.Site.Params "externallinktarget" }} + {{- $target = .page.Site.Params.externalLinkTarget }} + {{- if in (slice "false" false 0) $target }} + {{- $target = "" }} + {{- end }} + {{- if in (slice "true" true 1) $target }} + {{- $target = "_blank" }} + {{- end }} + {{- end }} +{{- end }} +{{- $effects := dict "download" false "target" false }} +{{- if .page.Site.Params.linkeffects }} + {{- $effects = merge $effects .page.Site.Params.linkeffects }} +{{- end }} +{{- if .page.Params.linkeffects }} + {{- $effects = merge $effects .page.Params.linkeffects }} +{{- end }} +{{- $target := .target | default $target }} +{{- if ne (printf "%T" $target) "bool" }} + {{- $effects = merge $effects (dict "target" $target) }} +{{- end }} +{{- if $u.RawQuery }} + {{- if $u.Query.Has "classes" }} + {{- $classes := slice | append (split ($u.Query.Get "classes") ",") }} + {{- range $classes }} + {{- $k := . }} + {{- $v := true }} + {{- if strings.HasPrefix $k "no" }} + {{- $k := strings.TrimPrefix "no" $k }} + {{- $v := false }} + {{- end }} + {{- $effects = merge $effects (dict $k $v) }} + {{- end }} + {{- end }} + {{- range $k, $v := $effects }} + {{- if $u.Query.Has $k }} + {{- $paramValue := $u.Query.Get $k }} + {{- $newValue := true }} + {{- if eq $paramValue "" }} + {{- $newValue = true }} + {{- else if eq $paramValue "true" }} + {{- $newValue = true }} + {{- else if eq $paramValue "false" }} + {{- $newValue = false }} + {{- else }} + {{- $newValue = $paramValue }} + {{- end }} + {{- $effects = merge $effects (dict $k $newValue) }} + {{- end }} + {{- end }} +{{- end }} +{{- $classes := slice }} +{{- range $k, $v := $effects }} + {{- if $v }} + {{- if eq (printf "%T" $v) "bool" }} + {{- $classes = $classes | append $k }} + {{- end }} + {{- end }} +{{- end }} +{{- if $attributes.class }}{{ $classes = $classes | append $attributes.class }}{{ end }} +{{- $attributes = merge $attributes (dict "class" (delimit $classes " ")) }} +{{- $attributes = merge $attributes (dict "href" .url) }} +{{- $attributes = merge $attributes (dict "download" $effects.download) }} +{{- $attributes = merge $attributes (dict "target" $effects.target) }} +{{- return $attributes }} \ No newline at end of file diff --git a/layouts/partials/shortcodes/image.html b/layouts/partials/shortcodes/image.html index a147731996..3ca43f9c43 100644 --- a/layouts/partials/shortcodes/image.html +++ b/layouts/partials/shortcodes/image.html @@ -7,98 +7,56 @@ {{- end }} {{- $title := .title }} {{- $alt := .alt }} -{{- $effects := dict "border" false "lazy" true "lightbox" true "shadow" false }} -{{- if $page.Site.Params.imageeffects }} - {{- $effects = merge $effects $page.Site.Params.imageeffects }} -{{- end }} -{{- if $page.Params.imageEffects }} - {{- $effects = merge $effects $page.Params.imageEffects }} -{{- end }} -{{- $height := "auto" }} -{{- $width := "auto" }} {{- $attributes := .attributes | default dict }} {{- $u := urls.Parse .url }} {{- $src := $u.String }} {{- if $u.IsAbs }} {{- partialCached "_relearn/urlExists.gotmpl" (dict "url" .url "page" $page "type" "image") $u.String }} {{- else }} - {{- $path := strings.TrimPrefix "./" $u.Path }} - {{- with or - ($page.Resources.Get $path) - (resources.Get $path) - }} - {{- $src = .RelPermalink }} - {{- with $u.RawQuery }} - {{- $src = printf "%s?%s" $src . }} - {{- end }} - {{- with $u.Fragment }} - {{- $src = printf "%s#%s" $src . }} - {{- end }} + {{- $linkObject := partial "_relearn/linkObject.gotmpl" (dict "url" .url "page" $page "searchPage" false) }} + {{- if $linkObject }} + {{- $src = partial "_relearn/decoratedLink.gotmpl" (dict "url" .url "page" $page "linkObject" $linkObject "param" "image") }} {{- else }} {{- $filepath := "[virtual file]" }}{{ with and $page $page.File $page.File.Filename }}{{ $filepath = . }}{{ end }} {{- $msg := printf "%q: image '%s' is not a resource" $filepath .url }} {{- partial "_relearn/urlErrorReport.gotmpl" (dict "url" .url "page" $page "param" "image" "msg" $msg) }} {{- end }} {{- end }} -{{- if $u.RawQuery }} - {{- if $u.Query.Has "classes" }} - {{- $classes := slice | append (split ($u.Query.Get "classes") ",") }} - {{- range $classes }} - {{- $k := . }} - {{- $v := true }} - {{- if strings.HasPrefix $k "no" }} - {{- $k := strings.TrimPrefix "no" $k }} - {{- $v := false }} - {{- end }} - {{- $effects = merge $effects (dict $k $v) }} - {{- end }} - {{- end }} - {{- if $u.Query.Has "featherlight" }} - {{- $filepath := "[virtual file]" }}{{ with and $page $page.File $page.File.Filename }}{{ $filepath = . }}{{ end }} - {{- warnf "%q: DEPRECATED usage of 'featherlight' image CSS class found, use 'lightbox' instead; see https://mcshelby.github.io/hugo-theme-relearn/introduction/releasenotes/5/#5-11-0" $filepath }} - {{- $effects = merge $effects (dict "lightbox" (ne ($u.Query.Get "featherlight") "false")) }} - {{- end }} - {{- range $k, $v := $effects }} - {{- if $u.Query.Has $k }} - {{- $effects = merge $effects (dict $k (ne ($u.Query.Get $k) "false")) }} - {{- end }} - {{- end }} - {{- with $u.Query.Get "height" }} - {{- $height = . }} - {{- end }} - {{- with $u.Query.Get "width" }} - {{- $width = . }} - {{- end }} -{{- end }} -{{- $classes := slice }} -{{- range $k, $v := $effects }} - {{- $c := printf "%s%s" (cond $v "" "no") $k }} - {{- $classes = $classes | append $c }} -{{- end }} {{- $id := cond (or (eq .id nil) (eq .id "")) (partial "_relearn/makeRandomMd5.gotmpl" $page) .id }} -{{- $attributes = merge $attributes (dict "alt" $alt "src" $src "title" ($title | transform.HTMLEscape)) }} -{{- if $effects.lazy }} - {{- $attributes = merge $attributes (dict "loading" "lazy") }} -{{- end }} -{{- if $effects.lightbox -}} +{{- $attributes = merge $attributes (partial "_relearn/imageAttributes.gotmpl" (dict "url" $src "page" $page)) }} +{{- $attributes = merge $attributes (dict "alt" $alt "title" ($title | transform.HTMLEscape)) }} +{{- $classes := split $attributes.class " " }} +{{- $isLightbox := in $classes "lightbox" }} +{{- if $isLightbox -}} {{- end }} -{{- $attributes_figure := merge $attributes (dict "class" (delimit (append (index $attributes "class" | default slice) "figure-image" $classes) " ")) }} -{{- $attributes_figure = merge $attributes_figure (dict "style" (delimit (slice (index $attributes "style") (printf "height: %s; width: %s;" $height $width)) " ")) -}} +{{- $attributes_figure := $attributes }} +{{- $attributes_figure = merge $attributes_figure (dict "class" (delimit ((split $attributes_figure.class " ") | append "figure-image") " ")) }} +{{- $attributes_figure = merge $attributes_figure (dict "style" (index $attributes_figure "style")) -}} -{{- if $effects.lightbox -}} +{{- if $isLightbox -}} -{{- $attributes_lightbox := merge $attributes (dict "class" (delimit (append (index $attributes "class" | default slice) "lightbox-image" $classes) " ")) -}} +{{- $attributes_lightbox := $attributes }} +{{- $attributes_lightbox = merge $attributes_lightbox (dict "class" (delimit ((split $attributes_lightbox.class " ") | append "lightbox-image") " ")) }} +{{- $attributes_lightbox = merge $attributes_lightbox (dict "style" "") -}} {{- end }} \ No newline at end of file diff --git a/layouts/partials/shortcodes/link.html b/layouts/partials/shortcodes/link.html index 8c542bb7aa..e2a40b2ef4 100644 --- a/layouts/partials/shortcodes/link.html +++ b/layouts/partials/shortcodes/link.html @@ -12,33 +12,32 @@ {{- $attributes := .attributes | default dict }} {{- $title := .title | default "" }} {{- $title = trim $title " " }} -{{- $attributes = $attributes | merge (dict "title" ($title | transform.HTMLEscape)) }} +{{- $attributes = merge $attributes (dict "title" ($title | transform.HTMLEscape)) }} {{- $content := .content }} -{{- $target := .target | default "" }} +{{- /* target will be boolean false if no user defined value was set and effect default should be applied */}} +{{- $target := false }} {{- $u := urls.Parse .url }} {{- $href := $u.String }} {{- if $u.IsAbs }} {{- partialCached "_relearn/urlExists.gotmpl" (dict "url" .url "page" $page "type" "link") $u.String }} - {{- $attributes = merge $attributes (dict "rel" "external") }} - {{- $target = "_blank" }} - {{- if isset $page.Site.Params "externallinktarget" }} - {{- $target = $page.Site.Params.externalLinkTarget }} - {{- end }} - {{- $attributes = $attributes | merge (dict "target" $target) }} {{- else }} - {{- $linkObject := partial "_relearn/linkObject.gotmpl" (dict "url" $.url "page" $page) }} - {{- with $linkObject }} - {{- $href = partial "_relearn/decoratedLink.gotmpl" (dict "url" $.url "page" $page "linkObject" . "param" "link") }} + {{- $linkObject := partial "_relearn/linkObject.gotmpl" (dict "url" .url "page" $page) }} + {{- if $linkObject }} + {{- $href = partial "_relearn/decoratedLink.gotmpl" (dict "url" .url "page" $page "linkObject" $linkObject "param" "link") }} {{- else }} {{- $filepath := "[virtual file]" }}{{ with and $page $page.File $page.File.Filename }}{{ $filepath = . }}{{ end }} {{- $msg := printf "%q: link '%s' is not a page or a resource" $filepath .url }} {{- partial "_relearn/urlErrorReport.gotmpl" (dict "url" .url "page" $page "param" "link" "msg" $msg) }} {{- end }} {{- end }} -{{- $attributes = $attributes | merge (dict "href" $href) -}} +{{- $attributes = merge $attributes (partial "_relearn/linkAttributes.gotmpl" (dict "url" $href "page" $page "target" .target)) -}} {{ $content | safeHTML }} \ No newline at end of file diff --git a/layouts/partials/version.txt b/layouts/partials/version.txt index 7f2320e745..e5f82aff30 100644 --- a/layouts/partials/version.txt +++ b/layouts/partials/version.txt @@ -1 +1 @@ -7.3.2+14c19bb13cecd2d3e72f5f53ad2b03f71dfcef81 \ No newline at end of file +7.3.2+516e552ecefcdf2f67cb0c34869f225affe45f73 \ No newline at end of file