How can I add rel=nofollow or target=blank or rel=external or other similar attributes to specific links in my posts (in markdown)?


I was wondering if there’s any easy way to set the rel attribute of the anchor tag from within my post’s content (in markdown).

I went through this:

I suppose one way would be to include a shortcode (it would be great if you give attach the sample code :sweat_smile: ).

Or is there any way to get this working with something like conditional Markdown Hooks. Something like this?

What’s the condition? Is there a pattern? For example, all links to should have a rel attribute?

Nope. I was looking for a solution that would work for any random link (plug-and-play like shortcodes). e.g. If I add an external link in my post I should be able to add rel=“external” attribute to the along with the href while other links in the same post don’t get the same attribute.

I was actually able to get this working with the following shortcode:

{{ $link := .Get 0}}
{{ $rel := .Get 1}}
{{ $text := .Get 2}}
<a href="{{$link}}" rel="{{$rel}}">{{$text}}</a>

So, {{< link "" "external" "external link" >}} renders the correct a tag for this specific link.

Is there any other way to achieve the same thing without cluttering the post content too much?

And if I have to stick with this, is there any way to shorten this thing? Like may be declare a variable in the beginning of the content and then just enter that in the actual content?

Would you consider something like this?

[Hugo Forum]( "The Hugo Forum {rel='nofollow'}")

Or, if your link doesn’t have a title:

[Hugo Forum]( "{rel='nofollow'}")

If this format works, we can use a render hook to handle your links.

1 Like

This should do. How do I setup the render hook? :slight_smile:


{{- $parsedTitle := dict -}}
{{- with .Title -}}
  {{- $parsedTitle = partial "functions/parse-title-attribute.html" . -}}
{{- end -}}

<a href="{{ .Destination | safeURL }}"
  {{- with $parsedTitle.title }} title="{{ . }}"{{- end -}}
  {{- with $parsedTitle.attributes -}}
    {{- range $k, $v := . -}}
      {{- printf " %s=%q" $k $v | safeHTMLAttr -}}
    {{- end -}}
  {{- end -}}
  >{{ .Text | safeHTML }}</a>

{{- /* Strip trailing space. */ -}}


{{/* Split .Title into two parts, title and attributes. */}}
{{- $parts := split . "{" -}}
{{- $parts = apply $parts "trim" "." " " -}}
{{- $parts = apply $parts "trim" "." "}" -}}

{{/* Extract title into a string. */}}
{{- $title := index $parts 0 -}}

{{/* Extract attributes into a dictionary. */}}
{{- $temp := index $parts 1 -}}
{{- $temp = split $temp "'" -}}
{{- $temp = first (sub (len $temp) 1) $temp -}}
{{- $temp = apply $temp "replace" "." "=" "" -}}
{{- $temp = apply $temp "trim" "." " " -}}
{{- $attributes := dict -}}
{{- if $temp -}}
  {{- range (seq 0 2 (sub (len $temp) 1)) -}}
    {{- $attributes = merge $attributes (dict (index $temp . ) (index $temp (add 1 .))) -}}
  {{- end -}}
{{- end -}}

{{- $parsedTitle := dict "title" $title "attributes" $attributes -}}
{{- return $parsedTitle -}}

This works with all of these:

[Hugo Forum]( "The Hugo Forum {rel='nofollow' foo='bar'}")
[Hugo Forum]( "The Hugo Forum {rel='nofollow'}")
[Hugo Forum]( "{rel='nofollow'}")
[Hugo Forum]( "Hello World")
[Hugo Forum]( " ")
[Hugo Forum]( "")
[Hugo Forum](

Whoa! That’s a lot of code :astonished:

Thanks A Lot Joe!! I couldn’t have possibly figured it all out :sweat_smile:

It works flawlessly!

However, why doesn’t Hugo provide this support built-in? It is a pretty common scenario for someone like a blogger, right?

Because I am abusing an HTML attribute, overloading it with stuff it shouldn’t contain. Ideally we would be able to add attributes to links and images in the same way that we can attributes to headings, code fences, and blocks.

When we did this, the implementation was limited to headings. Doing the same thing for image and links is complicated. This is somewhat related:

1 Like

I didn’t get this. rel and target are valid attributes of the anchor tag, right?

I undestand that this is no way near to the standard Markdown Syntax.

Because I am abusing an HTML attribute

You are right. My statement is incorrect. I am abusing markdown by overloading what would normally become the anchor element’s title attribute.

The CommonMark specification states that this:

[text](href "title"]

should render to this:

<a href="href" title="title">text</a>

But I’m abusing markdown to make this:

[text](href "title {foo='bar'}"]

render to this:

<a href="href" title="title" foo="bar">text</a>

instead of this:

<a href="href" title="title {foo='bar'}">text</a>
1 Like

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