menu: add internal link check #1002

This commit is contained in:
Sören Weber 2025-01-29 18:03:23 +01:00
parent ba7e3b9b27
commit 1205aa0448
No known key found for this signature in database
GPG key ID: BEC6D55545451B6D
10 changed files with 72 additions and 16 deletions

View file

@ -19,7 +19,7 @@ externalLinkTarget = '_self'
## Enabling Link and Image Link Warnings ## Enabling Link and Image Link Warnings
{{% badge style="cyan" icon="gears" title=" " %}}Option{{% /badge %}} {{% badge style="green" icon="fa-fw fab fa-markdown" title=" " %}}Front Matter{{% /badge %}} You can use `link.errorlevel` and `image.errorlevel` to control what should happen if a local link can not be resolved to a resource. {{% badge style="cyan" icon="gears" title=" " %}}Option{{% /badge %}} {{% badge style="green" icon="fa-fw fab fa-markdown" title=" " %}}Front Matter{{% /badge %}} You can use `link.errorlevel` and `image.errorlevel` to control what should happen if a local link can not be resolved to a page and/or a resource.
If not set or empty, any unresolved link is written as given into the resulting output. If set to `warning` the same happens and an additional warning is printed in the built console. If set to `error` an error message is printed and the build is aborted. If not set or empty, any unresolved link is written as given into the resulting output. If set to `warning` the same happens and an additional warning is printed in the built console. If set to `error` an error message is printed and the build is aborted.

View file

@ -10,8 +10,10 @@ weight = -4
### New ### New
- {{% badge style="info" icon="plus-circle" title=" " %}}New{{% /badge %}} Table headers are sticky now. - {{% badge style="info" icon="plus-circle" title=" " %}}New{{% /badge %}} If `link.errorlevel` is configured, now also the `pageRef` of a [Hugo menu item](https://gohugo.io/content-management/menus/) and the `menuPageRef` in a page's front matter will be checked for existence.
- {{% 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. - {{% 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.
You can see this in action on the above linked page, accessible by clicking the topbar button. You can see this in action on the above linked page, accessible by clicking the topbar button.
- {{% badge style="info" icon="plus-circle" title=" " %}}New{{% /badge %}} Table headers are sticky now.

View file

@ -163,20 +163,34 @@
{{- $url := partial "permalink.gotmpl" (dict "to" .) }} {{- $url := partial "permalink.gotmpl" (dict "to" .) }}
{{- $isCrosslink := false }} {{- $isCrosslink := false }}
{{- $target := "" }} {{- $target := "" }}
{{- $errorlevel := or $currentNode.Params.link.errorlevel $currentNode.Site.Params.link.errorlevel }}
{{- if .Params.menuPageRef }} {{- if .Params.menuPageRef }}
{{- with site.Home.GetPage (.Params.menuPageRef) }} {{- with site.Home.GetPage (.Params.menuPageRef) }}
{{- $url = partial "permalink.gotmpl" (dict "to" .) }} {{- $url = partial "permalink.gotmpl" (dict "to" .) }}
{{- $isCrosslink = true }} {{- $isCrosslink = true }}
{{- else }}
{{- if eq $errorlevel "warning" }}
{{- warnf "%q: menu link '%s' is not a page but linked anyways" $currentNode.File.Filename .Params.menuPageRef }}
{{- else if eq $errorlevel "error" }}
{{- errorf "%q: menu link '%s' is not a page" $currentNode.File.Filename .Params.menuPageRef }}
{{- end }}
{{- end }} {{- end }}
{{- else if .Params.menuUrl }} {{- else if .Params.menuUrl }}
{{- $url = .Params.menuUrl }} {{- $url = .Params.menuUrl }}
{{- $isCrosslink = true }} {{- $isCrosslink = true }}
{{- $u := urls.Parse $url }} {{- $u := urls.Parse $url }}
{{- if $u.IsAbs }} {{- if $u.IsAbs }}
{{- partialCached "_relearn/urlExists.gotmpl" (dict "url" $url "page" $currentNode "type" "menu link") $u.String }}
{{- $target = "_blank" }} {{- $target = "_blank" }}
{{- if isset site.Params "externallinktarget" }} {{- if isset site.Params "externallinktarget" }}
{{- $target = site.Params.externalLinkTarget }} {{- $target = site.Params.externalLinkTarget }}
{{- end }} {{- end }}
{{- else }}
{{- if eq $errorlevel "warning" }}
{{- warnf "%q: local menu link '%s' was given by 'menuURL'; if it points to a page inside your Hugo site use 'menuPageRef' instead; link created anyways" $currentNode.File.Filename .Params.menuUrl }}
{{- else if eq $errorlevel "error" }}
{{- errorf "%q: local menu link '%s' was given by 'menuURL'; if it points to a page inside your Hugo site use 'menuPageRef' instead" $currentNode.File.Filename .Params.menuUrl }}
{{- end }}
{{- end }} {{- end }}
{{- end }} {{- end }}
{{- $pre := partial "menu-pre.html" . }} {{- $pre := partial "menu-pre.html" . }}
@ -225,7 +239,7 @@
{{- $entries := . }} {{- $entries := . }}
{{- if eq (len $entries) 1 }} {{- if eq (len $entries) 1 }}
{{- with index $entries 0 }} {{- with index $entries 0 }}
{{- if not (partial "menupermalink.gotmpl" .) }} {{- if not (partial "menupermalink.gotmpl" (dict "page" $currentNode "menu" .)) }}
{{- /* because in Hugo menus can not have parameter but menu entries can, {{- /* because in Hugo menus can not have parameter but menu entries can,
we can flag a single top level menu entry as a container; this container we can flag a single top level menu entry as a container; this container
entry carrys just meta information and parameter, uses its children entry carrys just meta information and parameter, uses its children
@ -264,7 +278,7 @@
{{- $isSubCollapsible := .Params.collapsibleMenu | default $root.Params.collapsibleMenu | default site.Params.collapsibleMenu }} {{- $isSubCollapsible := .Params.collapsibleMenu | default $root.Params.collapsibleMenu | default site.Params.collapsibleMenu }}
{{- if or $isSubSelf $isSubAncestor }} {{- if or $isSubSelf $isSubAncestor }}
{{- partial "partials/inline/menu-walker" (dict "menu" . "currentnode" $currentNode "showvisitedlinks" $showvisitedlinks "alwaysopen" $defaultAlwaysopen "isSelf" $isSubSelf "isAncestor" $isSubAncestor "isHidden" $isSubHidden "root" $root) }} {{- partial "partials/inline/menu-walker" (dict "menu" . "currentnode" $currentNode "showvisitedlinks" $showvisitedlinks "alwaysopen" $defaultAlwaysopen "isSelf" $isSubSelf "isAncestor" $isSubAncestor "isHidden" $isSubHidden "root" $root) }}
{{- else if and (not $isSubHidden) (or $isSubCollapsible (not (partial "menupermalink.gotmpl" $entry)) (and $entry (eq $entry.Page $currentNode)) (and $entry ($currentNode.HasMenuCurrent $entry.Menu $entry))) }} {{- else if and (not $isSubHidden) (or $isSubCollapsible (not (partial "menupermalink.gotmpl" (dict "page" $currentNode "menu" $entry))) (and $entry (eq $entry.Page $currentNode)) (and $entry ($currentNode.HasMenuCurrent $entry.Menu $entry))) }}
{{- $id := md5 (print .) }} {{- $id := md5 (print .) }}
{{- partialCached "partials/inline/menu-walker" (dict "menu" . "currentnode" $currentNode "showvisitedlinks" $showvisitedlinks "alwaysopen" $defaultAlwaysopen "isSelf" $isSubSelf "isAncestor" $isSubAncestor "isHidden" $isSubHidden "root" $root) $id }} {{- partialCached "partials/inline/menu-walker" (dict "menu" . "currentnode" $currentNode "showvisitedlinks" $showvisitedlinks "alwaysopen" $defaultAlwaysopen "isSelf" $isSubSelf "isAncestor" $isSubAncestor "isHidden" $isSubHidden "root" $root) $id }}
{{- end }} {{- end }}
@ -300,7 +314,7 @@
{{- end }} {{- end }}
{{- end }} {{- end }}
{{- $title := partial "menutitle.gotmpl" . }} {{- $title := partial "menutitle.gotmpl" . }}
{{- $url := partial "menupermalink.gotmpl" . }} {{- $url := partial "menupermalink.gotmpl" (dict "page" $currentNode "menu" .) }}
{{- $target := "" }} {{- $target := "" }}
{{- $u := urls.Parse $url }} {{- $u := urls.Parse $url }}
{{- if $u.IsAbs }} {{- if $u.IsAbs }}
@ -336,7 +350,7 @@
{{- $isSubCollapsible := .Params.collapsibleMenu | default $root.Params.collapsibleMenu | default site.Params.collapsibleMenu }} {{- $isSubCollapsible := .Params.collapsibleMenu | default $root.Params.collapsibleMenu | default site.Params.collapsibleMenu }}
{{- if or $isSubSelf $isSubAncestor }} {{- if or $isSubSelf $isSubAncestor }}
{{- partial "partials/inline/menu-walker" (dict "menu" . "currentnode" $currentNode "showvisitedlinks" $showvisitedlinks "alwaysopen" $defaultAlwaysopen "isSelf" $isSubSelf "isAncestor" $isSubAncestor "isHidden" $isSubHidden "root" $root) }} {{- partial "partials/inline/menu-walker" (dict "menu" . "currentnode" $currentNode "showvisitedlinks" $showvisitedlinks "alwaysopen" $defaultAlwaysopen "isSelf" $isSubSelf "isAncestor" $isSubAncestor "isHidden" $isSubHidden "root" $root) }}
{{- else if and (not $isSubHidden) (or $isSubCollapsible (not (partial "menupermalink.gotmpl" $entry)) (eq $entry.Page $currentNode) ($currentNode.HasMenuCurrent $entry.Menu $entry)) }} {{- else if and (not $isSubHidden) (or $isSubCollapsible (not (partial "menupermalink.gotmpl" (dict "page" $currentNode "menu" $entry))) (eq $entry.Page $currentNode) ($currentNode.HasMenuCurrent $entry.Menu $entry)) }}
{{- $id := md5 (print .) }} {{- $id := md5 (print .) }}
{{- partialCached "partials/inline/menu-walker" (dict "menu" . "currentnode" $currentNode "showvisitedlinks" $showvisitedlinks "alwaysopen" $defaultAlwaysopen "isSelf" $isSubSelf "isAncestor" $isSubAncestor "isHidden" $isSubHidden "root" $root) $id }} {{- partialCached "partials/inline/menu-walker" (dict "menu" . "currentnode" $currentNode "showvisitedlinks" $showvisitedlinks "alwaysopen" $defaultAlwaysopen "isSelf" $isSubSelf "isAncestor" $isSubAncestor "isHidden" $isSubHidden "root" $root) $id }}
{{- end }} {{- end }}

View file

@ -1,10 +1,30 @@
{{- $url := "" }} {{- $url := "" }}
{{- with . }} {{- with .menu }}
{{- with .URL }} {{- $errorlevel := or $.page.Params.link.errorlevel $.page.Site.Params.link.errorlevel }}
{{- $url = . | relLangURL }} {{- if .PageRef }}
{{- end }} {{- with .Page }}
{{- with .Page }} {{- $url = partial "permalink.gotmpl" (dict "to" .) }}
{{- $url = partial "permalink.gotmpl" (dict "to" .) }} {{- else }}
{{- if eq $errorlevel "warning" }}
{{- warnf "%q: menu link '%s' is not a page but linked anyways" $.page.File.Filename .PageRef }}
{{- else if eq $errorlevel "error" }}
{{- errorf "%q: menu link '%s' is not a page" $.page.File.Filename .PageRef }}
{{- end }}
{{- end }}
{{- else }}
{{- with .URL }}
{{- $url = . | relLangURL }}
{{- $u := urls.Parse $url }}
{{- if $u.IsAbs }}
{{- partialCached "_relearn/urlExists.gotmpl" (dict "url" $url "page" $.page "type" "menu link") $u.String }}
{{- else }}
{{- if eq $errorlevel "warning" }}
{{- warnf "%q: local menu link '%s' was given by 'URL'; if it points to a page inside your Hugo site use 'pageRef' instead; link created anyways" $.page.File.Filename . }}
{{- else if eq $errorlevel "error" }}
{{- errorf "%q: local menu link '%s' was given by 'URL'; if it points to a page inside your Hugo site use 'pageRef' instead" $.page.File.Filename . }}
{{- end }}
{{- end }}
{{- end }}
{{- end }} {{- end }}
{{- end }} {{- end }}
{{- return $url }} {{- return $url }}

View file

@ -15,14 +15,29 @@
<meta name="robots" content="noindex, nofollow, noarchive, noimageindex"> <meta name="robots" content="noindex, nofollow, noarchive, noimageindex">
{{- end }} {{- end }}
{{- $url := "" }} {{- $url := "" }}
{{- $errorlevel := or .Params.link.errorlevel .Site.Params.link.errorlevel }}
{{- if .Params.menuPageRef }} {{- if .Params.menuPageRef }}
{{- with site.Home.GetPage (.Params.menuPageRef) }} {{- with site.Home.GetPage (.Params.menuPageRef) }}
{{- $url = partial "permalink.gotmpl" (dict "to" .) }} {{- $url = partial "permalink.gotmpl" (dict "to" .) }}
{{- else }} {{- else }}
{{- warnf "%q: WARNING: page '%s' not found for 'menuPageRef' parameter" .File.Filename .Params.menuPageRef }} {{- if eq $errorlevel "warning" }}
{{- warnf "%q: menu link '%s' is not a page but linked anyways" .File.Filename .Params.menuPageRef }}
{{- else if eq $errorlevel "error" }}
{{- errorf "%q: menu link '%s' is not a page" .File.Filename .Params.menuPageRef }}
{{- end }}
{{- end }} {{- end }}
{{- else if .Params.menuUrl }} {{- else if .Params.menuUrl }}
{{- $url = .Params.menuUrl }} {{- $url = .Params.menuUrl }}
{{- $u := urls.Parse $url }}
{{- if $u.IsAbs }}
{{- partialCached "_relearn/urlExists.gotmpl" (dict "url" $url "page" . "type" "menu link") $u.String }}
{{- else }}
{{- if eq $errorlevel "warning" }}
{{- warnf "%q: local menu link '%s' was given by 'menuURL'; if it points to a page inside your Hugo site use 'menuPageRef' instead; link created anyways" .File.Filename .Params.menuUrl }}
{{- else if eq $errorlevel "error" }}
{{- errorf "%q: local menu link '%s' was given by 'menuURL'; if it points to a page inside your Hugo site use 'menuPageRef' instead" .File.Filename .Params.menuUrl }}
{{- end }}
{{- end }}
{{- end }} {{- end }}
{{- if $url }} {{- if $url }}
<meta http-equiv="refresh" content="0; url={{ $url }}"> <meta http-equiv="refresh" content="0; url={{ $url }}">

View file

@ -18,7 +18,9 @@
{{- $attributes := .attributes | default dict }} {{- $attributes := .attributes | default dict }}
{{- $u := urls.Parse .url }} {{- $u := urls.Parse .url }}
{{- $src := $u.String }} {{- $src := $u.String }}
{{- if not $u.IsAbs }} {{- if $u.IsAbs }}
{{- partialCached "_relearn/urlExists.gotmpl" (dict "url" .url "page" $page "type" "image") $u.String }}
{{- else }}
{{- $path := strings.TrimPrefix "./" $u.Path }} {{- $path := strings.TrimPrefix "./" $u.Path }}
{{- with or {{- with or
($page.Resources.Get $path) ($page.Resources.Get $path)

View file

@ -16,6 +16,7 @@
{{- $u := urls.Parse .url -}} {{- $u := urls.Parse .url -}}
{{- $href := $u.String }} {{- $href := $u.String }}
{{- if $u.IsAbs }} {{- if $u.IsAbs }}
{{- partialCached "_relearn/urlExists.gotmpl" (dict "url" .url "page" $page "type" "link") $u.String }}
{{- $attributes = merge $attributes (dict "rel" "external") }} {{- $attributes = merge $attributes (dict "rel" "external") }}
{{- $target = "_blank" }} {{- $target = "_blank" }}
{{- if isset $page.Site.Params "externallinktarget" }} {{- if isset $page.Site.Params "externallinktarget" }}

View file

@ -7,7 +7,9 @@
{{- $src := $u.String }} {{- $src := $u.String }}
{{- $spec := "" }} {{- $spec := "" }}
{{- $id := cond (or (eq .id nil) (eq .id "")) (partial "_relearn/makeRandomMd5.gotmpl" $page) .id }} {{- $id := cond (or (eq .id nil) (eq .id "")) (partial "_relearn/makeRandomMd5.gotmpl" $page) .id }}
{{- if not $u.IsAbs }} {{- if $u.IsAbs }}
{{- partialCached "_relearn/urlExists.gotmpl" (dict "url" .src "page" $page "type" "OpenAPI spec link") $u.String }}
{{- else }}
{{- $path := strings.TrimPrefix "./" $u.Path }} {{- $path := strings.TrimPrefix "./" $u.Path }}
{{- with or {{- with or
($page.Resources.Get $path) ($page.Resources.Get $path)

View file

@ -1 +1 @@
7.3.2+44f7ff47eebd1a552b906059400888958f2709ae 7.3.2+ba7e3b9b27ff1459815a786b6c6adb5686723b58