Source blocks

ox-hugo tries to generate Markdown with fenced code blocks if possible. It also supports exporting source blocks with line numbers and/or highlighting enabled for specific lines.

Code Fences #

By default, the HUGO_CODE_FENCE property is non-nil. So the code blocks will be exported with CommonMark code fences when possible.

For example, below Org source block:

#+begin_src emacs-lisp
(message "Hello")
#+end_src

will export to:

```emacs-lisp
(message "Hello")
```
Note
It is necessary to set the Hugo site config variable markup.highlight.codeFences to true (which is the default at least as of Hugo v0.60.0) for syntax highlighting to work for fenced code blocks.

Line numbers #

Line numbers can be enabled/configured using the Org -n / +n syntax. See Org Info: Literal Examples for more information.

Here are some examples fetched from the “Source blocks with line number annotation” test case in the all-posts.org.

Default new line number start #

Org source #

#+begin_src emacs-lisp -n
;; this will export with line number 1 (default)
(message "This is line 2")
#+end_src

Output #

1
2
;; this will export with line number 1 (default)
(message "This is line 2")

Specify new line number start #

Org source #

#+begin_src emacs-lisp -n 20
;; this will export with line number 20
(message "This is line 21")
#+end_src

Output #

20
21
;; this will export with line number 20
(message "This is line 21")

Default continued line numbers #

Org source #

#+begin_src emacs-lisp +n
;; This will be listed as line 22
(message "This is line 23")
#+end_src

Output #

22
23
;; This will be listed as line 22
(message "This is line 23")

Specify continued line numbers jump #

Org source #

#+begin_src emacs-lisp +n 10
;; This will be listed as line 33
(message "This is line 34")
#+end_src

Output #

33
34
;; This will be listed as line 33
(message "This is line 34")

Line number Style (linenos#

The value of linenos (Hugo’s default value or the site-global value set in its config.toml) can be overridden per source block using the :linenos parameter in that source block’s header.

Table 1: Possible values of :linenos
:linenos value Description
false Disable line numbers.
true Enable line numbers with Hugo’s default value of lineNumbersInTable.
inline Enable line numbers where the line numbers and code are rendered in HTML <div> and <span> tags.
table Enable line numbers where the line numbers and code are rendered in HTML tables.

Example usage: If a user has enabled the line numbers by default by adding this in their site’s config.toml:

[markup]
  [markup.highlight]
    lineNos = true

, they can disable line numbers for selected source blocks by adding :linenos false to their headers.

#+begin_src emacs-lisp :linenos false
(message "hello")
(message "bye")
#+end_src

The :linenos header arg works for example blocks too.

Line numbers in HTML table #

The source block or code block rendering is done by Hugo using the chroma syntax highlighter. When the line numbers are enabled, the line numbers and code blocks can be rendered either in HTML tables (lineNumbersInTable = true) or in the div and span tags (lineNumbersInTable = false). See Hugo’s default value of this config variable here.

To render the line numbers and code blocks in HTML tables regardless of Hugo’s default value, add this to your site’s config.toml:

[markup]
  [markup.highlight]
    lineNumbersInTable = true
Code Snippet 1: Render line numbers and code blocks in HTML tables

To override the rendering of line numbers and code blocks to happen in <div> and <span> tags, set lineNumbersInTable = false instead, but this is not recommended. With lineNumbersInTable = false, when the code blocks are copied in Firefox, extra blank lines get inserted after each line when pasted elsewhere. See Bugzilla # 1273836.

Highlight Lines #

Implementing this feature was interesting, because while Org doesn’t have a syntax to enable highlighting only specific lines, Hugo supports line highlighting using the hl_lines attribute for code fences (Hugo v0.60.0+) or its highlight shortcode.

So the challenge was to present that “lines to be highlighted” information in the Org source in a nice format and then translate that to the hl_lines attribute with the required format at the time of exporting.

It involved hacking the org-babel-exp-code. See this discussion on the emacs-orgmode thread if interested.

This feature is implemented by using a parameter called :hl_lines in the header of source blocks. This parameter is specific to ox-hugo, and that’s why implementing this needed that hack.

If a user wants to highlight lines 1, and then 3 to 5, they would add :hl_lines 1,3-5 to the source block header.

Highlighting without line numbers #

Org source #

#+begin_src emacs-lisp :hl_lines 1,3-5
(message "This is line 1")
(message "This is line 2")
(message "This is line 3")
(message "This is line 4")
(message "This is line 5")
(message "This is line 6")
#+end_src

Output #

(message "This is line 1")
(message "This is line 2")
(message "This is line 3")
(message "This is line 4")
(message "This is line 5")
(message "This is line 6")

Above highlighting might look weird as the highlighting spans the full page/container width. This could be either called a bug in Hugo, or the HTML limitation.

A workaround is below.. use line numbers too!.

Highlighting only 1 line #

Org source #
#+begin_src emacs-lisp :hl_lines 2
(message "This is line 1")
(message "This is line 2")
(message "This is line 3")
#+end_src
Output #
(message "This is line 1")
(message "This is line 2")
(message "This is line 3")

Highlighting with line numbers #

The Org source for the below is similar to the above, except that the -n switch is also added to enable the line numbers.

With line numbers enabled, the highlighting is limited to the width of the HTML table rows if the linenos option is set to table (default).

Note 1
When using both, switches (like -n), and header args (like :hl_lines), the switches have to come first.
Note 2
The line numbers in the value for :hl_lines parameter is always with the starting line number reference of 1. That has no relation with the value of the line numbers displayed using the -n or +n switches!

Org source #

#+begin_src emacs-lisp -n 7 :hl_lines 1,3-5
(message "This is line 7 in code, but line 1 for highlighting reference")
(message "This is line 8 in code, but line 2 for highlighting reference")
(message "This is line 9 in code, but line 3 for highlighting reference")
(message "This is line 10 in code, but line 4 for highlighting reference")
(message "This is line 11 in code, but line 5 for highlighting reference")
(message "This is line 12 in code, but line 6 for highlighting reference")
#+end_src

Output #

 7
 8
 9
10
11
12
(message "This is line 7 in code, but line 1 for highlighting reference")
(message "This is line 8 in code, but line 2 for highlighting reference")
(message "This is line 9 in code, but line 3 for highlighting reference")
(message "This is line 10 in code, but line 4 for highlighting reference")
(message "This is line 11 in code, but line 5 for highlighting reference")
(message "This is line 12 in code, but line 6 for highlighting reference")

Hiding source block caption numbers #

The “Code Snippet <number>:” part of the source block captions can be hidden by adding this to the CSS:

.src-block-number {
  display: none;
}

Code References #

ox-hugo generates code references hyperlinked to line numbers of source and example blocks when using the (ref:REF) syntax in the blocks as explained in Org Info: Literal Examples.

Org interprets strings like (ref:name) as labels, and use them as targets for special hyperlinks like [[(name)]] — i.e., the reference name enclosed in single parenthesis.

You can also add a -r switch which removes the labels from the source code.

One convenience feature added by ox-hugo is that the -n is always implied when code references are detected in the source or example blocks.

Note
It is the user’s responsibility to ensure that all code ref labels used within a single post are unique.

Code references exported with labels #

As an example, this in Org source:

#+begin_src emacs-lisp
(save-excursion                 (ref:sc)
   (goto-char (point-min))      (ref:jump)
#+end_src

In line [[(sc)]] we remember the current position. [[(jump)][Line (jump)]] jumps to
~point-min~.

exports to:

1
2
(save-excursion                 (sc)
   (goto-char (point-min))      (jump)

In line sc we remember the current position. Line jump jumps to point-min.

Code references exported without labels #

When the -r switch is used in the header, the code ref labels are removed from the exported code block, and the labels in code ref link descriptions are replaced with line numbers.

As an example, this in Org source:

#+begin_src emacs-lisp -r
(save-excursion                 (ref:sc1)
   (goto-char (point-min))      (ref:jump1)
#+end_src

In line [[(sc1)]] we remember the current position. [[(jump1)][Line (jump1)]] jumps to
~point-min~.

exports to:

1
2
(save-excursion
   (goto-char (point-min))

In line 1 we remember the current position. Line 2 jumps to point-min.

highlight shortcode #

By default, ox-hugo tries to avoid using this shortcode because it is buggy (#161), and also it’s better to export CommonMark supported code fences than Hugo-specific shortcodes.

The Hugo highlight shortcode is used instead of code fences if one of these is true:

Fork me on GitHub