Hugo Attachment shortcode

Hugo Attachment shortcode

Shortcode which allows users to download page resource files, the files can be any extension or size. The user can download the files or open them in a new tab.

.html files cannot be part of page resources since Hugo will pick them up as an actual HTML page. In such case i add them as .html.txt files.

This article was written for Hugo 0.74.

For the tooltips the tooltips CSS library is used.

Usage

option   effect   optionaldefault
titlesets the title of the attachmentsyesAttachments
captionsets additional information for the attachmentsyes
folderspecifies the folder to useyesfiles
patterna regular expressions, used to filter the files in the folder.

The pattern parameter value must be regular expressions
  • To match a file suffix of ‘jpg’, use .*jpg.
  • To match file names ending in ‘jpg’ or ‘png’, use `.*(jpg
png)`yes

Attachments must be located in the page’s resources, i would strongly advice to use a leaf bundle for you content and add dedicated folders for downloadable resources. This also keeps your posts well organized.

  1. If your page is a markdown file, attachments must be placed in a folder named like your page and ending with .files (or specified folder name).

    • content
      • _index.md
      • page.files
        • attachment.pdf
      • page.md
  2. If your page is a folder (leaf bundle), attachments must be placed in a nested ‘files’ folder (or specified folder name).

    • content
      • _index.md
      • page
        • index.md
        • files
          • attachment.pdf

Be aware that if you use a multilingual website, you will need to have as many folders as languages.

Example

{{< attachments folder="attachments" caption="example" >}}
{{< attachments folder="attachments" pattern="(attachments.scss)" caption="single file example" >}}

Code

The shortcode will look for the specified folder and add all files to a list with their permalink so Hugo knows the files need to be included on the site. In addition it also shows the size of the file.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
<section class="attachments">
	<label>{{- (.Get "title") | default "Attachments" -}}{{ with (.Get "caption") }}  ({{- . -}}){{ end }}{{ partial "inline-svg" "paperclip" }}</label>
	<div class="attachments-files">
		{{- $folderName := default "files" (.Get "folder") -}}
		{{- $hasPattern := false -}}
		{{- if .Get "pattern" -}}{{- $hasPattern = true -}}{{- end -}}
		{{- $folder := path.Join "content" (path.Join .Page.File.Dir $folderName) -}}
		<ul>
			{{- range readDir $folder -}}
			{{- $include := not $hasPattern -}}
			{{- if $hasPattern -}}{{- $include = findRE ($.Get "pattern") .Name -}}{{- end -}}
			{{- if $include -}}
			<li>
				<a class="tooltipped tooltipped-n" aria-label="Download" href="{{ ($.Page.Resources.GetMatch (path.Join $folderName .Name)).RelPermalink }}" download>{{- .Name | markdownify -}}</a>
				<a class="new-tab tooltipped tooltipped-n" aria-label="Open in new tab" href="{{ ($.Page.Resources.GetMatch (path.Join $folderName .Name)).RelPermalink }}" target="_blank">{{ partial "inline-svg" "external-link" }}</a>
				<div class="attachment-size">({{- if le .Size 1024 -}}{{- .Size -}} b{{- else -}}{{- div .Size 1024 -}}kb{{- end -}})</div>
			</li>
			{{- end -}}
			{{- end -}}
		</ul>
	</div>
</section>

The accompanying SCSS

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
section.attachments {
  margin: 1.5rem 0;
  position: relative;

  label {
    font-weight: 300;
    margin: 0;
  }

  .attachments-files {
    display: block;
    font-size: 1rem;
    margin: 0;

    ul {
      margin-top: 0;
    }

    .attachment-size {
      display: inline-block;
      color: var(--font-color-muted);
    }
  }

  .new-tab {
    padding-left: 0.1em;
    padding-right: 0.1em;
  }
}
Noticed an error in this post? Corrections are appreciated.

© Nelis Oostens