Making highlight.js work with org-export
Org-mode can export to HTML, PDF and LaTeX, but its HTML export doesn’t highlight code blocks, which makes code hard to read. highlight.js fixes that. It’s a JavaScript syntax highlighter that works on almost any markup, doesn’t depend on other frameworks, and detects the language on its own.
This post assumes you’ve already set up org-publish-project-alist to export your .org files to .html. We’ll change that variable to load highlight.js.
Modifying org-publish-project-alist
Your org-publish-project-alist probably looks something like this:
(setq org-publish-project-alist
(list
(list "celibistrial-website"
:recursive t
:auto-sitemap t
:base-directory "~/org/celibistrial-website/content"
:publishing-function 'org-html-publish-to-html
:publishing-directory "~/org/celibistrial-website/public"
:with-author nil
:footnote-section-p t
:html-footnotes-section t
:html-doctype "<!doctype html>"
:time-stamp-file nil)))
To load highlight.js, add these two options:
:html-preamble "
<link rel=\"stylesheet\" href=\"https://unpkg.com/highlightjs@9.16.2/styles/obsidian.css\">
<script src=\"https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.7.0/highlight.min.js\"></script>
"
:html-postamble "
<script>hljs.highlightAll();</script>
"
:html-preamble adds HTML to the top of every page. The first line loads the highlight.js stylesheet and the second loads the script. :html-postamble adds HTML to the bottom of the page, where we call hljs.highlightAll();.
Modifying org-html-src-block
If you stop here, your code blocks still won’t be highlighted. highlight.js looks for code inside a <code> tag within a <pre>, like this:
<pre>
<code>
Code goes here
</code>
</pre>
Org’s HTML export writes a plain <pre class="src src-lang"> with no <code> tag, so highlight.js skips it. This snippet rewrites the output into the format highlight.js wants. I didn’t write it. I found it in a Stack Overflow post but can’t find the link anymore.
;; I did not write this , i found it from a stackoverflow post but i am unable to find a link to it
(defun my/org-html-src-block (html)
"Modify the output of org-html-src-block for highlight.js"
(replace-regexp-in-string
"</pre>" "</code></pre>"
(replace-regexp-in-string
"<pre class=\"src src-\\(.*\\)\">"
"<pre><code class=\"\\1\">"
html)))
(advice-add 'org-html-src-block :filter-return #'my/org-html-src-block)
advice-add runs my/org-html-src-block on the output of org-html-src-block every time org exports a source block.