Support for acronyms

The Markdown Extra syntax allows defining acronyms as shown below:

The HTML specification
is maintained by the W3C.

*[HTML]: Hyper Text Markup Language
*[W3C]:  World Wide Web Consortium

How do I use this in Hugo?

You cannot. You will need to create a shortcode.

Hugo converts markdown to HTML using the Goldmark markdown renderer. Goldmark adheres to the CommonMark specification, with the addition of several extensions to provide GFM compatibility.

Thanks for the clarification. I have an implementation idea using page.Store which I’ll run down here at the forum for suggestions.

I just implemented this on my site. The solution seems complex so feedback would be highly appreciated.

The way it is implemented is, I define the acronyms in the frontmatter like this:

---
title: Some Post
acronyms:
  - short: WWW
    long: World Wide Web
---

Then, I wrote a string injector which replaces all string occurrences from paragraphs only, excluding code blocks and heading.

layouts/partials/single/inject-acronyms.html

{{ $delimiters := dict
  "\n```" "\n```"
  "\n#" ""
  "\n>" ""
}}
{{ $suffixPattern := slice }}
{{ range $k, $v := $delimiters }}
  {{ $suffixPattern = $suffixPattern | append $k }}
{{ end }}
{{ $suffixPattern = delimit $suffixPattern "|" }}

{{ $charPattern := `\pL\pS\pZ\pP\pN\pM\pC` }}
{{ $pattern := printf `^([%s\n]*?)((?:%s))` $charPattern $suffixPattern }}

{{ $content := . }}
{{ $output := "" }}
{{ range . | countwords | seq }}
  {{ if not $content }}
    {{ break }}
  {{ end }}

  {{/* Walk down the markup and extract a paragraph */}}
  {{ $matches := index (findRESubmatch $pattern $content 1) 0 }}
  {{ $paragraph := index $matches 1 }}
  {{ $suffix := index $matches 2 }}

  {{/* No elements remain, so parse the entire markup at once */}}
  {{ if eq $paragraph nil }}
    {{ $paragraph = $content }}
  {{ end }}

  {{ $content = substr $content (strings.RuneCount $paragraph) }}

  {{/* Process the paragraph */}}
  {{ range page.Params.acronyms }}
    {{ $pattern := printf `([\[\s])\b%s\b([,.!:';\s\]])` .short }}
    {{ $replacement := printf `$1<abbr title="%s">%s</abbr>$2` .long .short }}
    {{ $paragraph = $paragraph | replaceRE $pattern $replacement }}
  {{ end }}

  {{ $output = print $output $paragraph }}

  {{/* Consume an element */}}
  {{ if $suffix }}
    {{ $end := index $delimiters $suffix }}
    {{ $pattern := printf `^(%s[%s\n]*?%s)\n` $suffix $charPattern $end }}
    {{ if not $end }}
      {{ $pattern = printf `^(%s[%s]*?)\n` $suffix $charPattern }}
    {{ end }}

    {{ $matches := index (findRESubmatch $pattern $content 1) 0 }}
    {{ $element := index $matches 1 }}

    {{ if $element }}
      {{ $content = substr $content (strings.RuneCount $element) }}
    {{ end }}

    {{ $output = print $output $element }}
  {{ end }}
{{ end }}

{{ return $output }}

And then we just call this for all our single pages instead of {{ .Content }}:

      {{ partialCached "single/inject-acronyms" .RawContent . | .RenderString | emojify }}

With this setup, all of my acronyms in the document are surrounded with <abbr> and it looks something like this:

I did go for a shortcode initially, but the syntax was too unfriendly, having to call the shortcode for each occurrence was painful.

1 Like

Minor point, but your examples are not acronyms, they’re initialisms.

Secondaly, if you need define each one in frontmatter what is the benefit over just writing <abbr title="World Wide Web">WWW</abbr> ? Genuine question.

3 Likes

Thanks about the initialisms info. Regarding the tag, with the partial, you only define it once in the front matter and all occurrences are automatically expanded in the markup.

This means I don’t have to use the abbr tag for each occurrence.

By the way, I just posted a blog about the way I implemented a shortcode version of this. It’s pretty simple, but I think it would work quite well for technical writers on docs with lots of acronyms. Instead of just simplifying the syntax of an abbr, it assumes the reader has a data store of acronyms somewhere and conditionally formats them based on whether they appeared before.

But that data store could be in the page params and use an ephemeral inline shortcode.

Sorry, I would have posted in the original thread (linked upthread), but I seemed to have locked it when I selected the solution. Also thanks again, @nternetinspired , changing the phrasing to abbreviations did indeed make the naming more correct and less awkward.

1 Like

How about using links instead ?

{{- $destination := .Destination -}}
{{- if eq $destination "DFN" -}}<dfn {{with .Title}}alt="{{.}}"{{end}}>{{- .Text -}}</dfn>
{{- else if eq $destination "ABBR" -}}<abbr alt="{{.Title}}">{{.Text}}</abbr>
{{else}}
     {{- $isRemote := or (strings.Contains $destination "://") (strings.HasPrefix $destination "www") }}
     {{- if $isRemote -}}
     blablablablabla....

Unless your word is written a hundred times (in that case an inline definition in bold characters would seem more appropriate), with this you would only need to define the word once with an external reference (or however they’re called):

[taurodontes]: DFN "Taurodontism describes an anatomic variation in human tooth in which the tooth's body expands to the detriment of roots."

then it costs only one pair of bracket each time you want your <abbr> or whatever else.
Not entirely automatic but I think much better than bothering with shortcodes.

2 Likes

Thanks, this is a clever and ingenious approach. It also has more control on the abbreviations, so I think I’ll go with something like this.

This topic was automatically closed 2 days after the last reply. New replies are no longer allowed.