2

Is there a way in org-mode's HTML export to make it so that code blocks that have :tangle no will appear differently? Even adding a different HTML class will do, as one can then probably add some CSS to alter their appearance (e.g. grey background or whatever).


Longer version / context:

I'm using org-mode (and its org-babel) to keep code and documentation together in a single file. Specifically, as in this question, I have

(require 'org)
(org-babel-load-file (expand-file-name "~/emacs/config/init.org"))

so that init.org can generate both an init.el file (for consumption by Emacs), and an init.html file (for consumption by me, when I want to make sense of my config again). In this file, I have some sections that I don't want to be part of init.el (e.g. either I decided against them, or they're simplified versions given first for understanding, before the “real” code, etc). For them, instead of something like

#+BEGIN_SRC emacs-lisp
(require 'cc-mode)
#+END_SRC

I have:

#+BEGIN_SRC emacs-lisp :tangle no
(require 'cc-mode)
#END_SRC

and everything works fine: the code no longer runs on startup, as it's no longer part of the generated init.el. However, the code still shows up in init.html (as I want it to) when I export from the org file, but unfortunately there's no longer any indication that this section is not going be tangled.

I imagine that in the HTML file, instead of

<div class="org-src-container">
  <pre class="src src-emacs-lisp">
    ...
  </pre>
</div>

if I could persuade org-mode / org-babel export to add another class, then I'd know how to solve the rest.

  • Looks like one would have to edit org-html-src-block (in ox-html.el). Not sure how to tell it that something is a :tangle no block... maybe it's already present in src-block, or can be passed in info (wherever this function is called... not sure of that either). – ShreevatsaR Aug 24 '18 at 19:25
3
+100

You can use an :around advice for org-html-src-block to wrap the code block generated by org-html-src-block with your own html block, e.g.: <div style="background-color:lightgray">.

But there is a little subtlety. The argument src-block of org-html-src-block is not really the parse tree of the original buffer. In the process of copying, parsing and reprinting that precedes the export the function org-babel-exp-src-block removes by default the source block argument :tangle no. To avoid that you need to add %tangle to the format fields of org-babel-exp-code-template.

There follows a minimal example code:

(defun my-org-html-src-block-no-tangle (oldfun src-block contents info)
  "Wrap source blocks with :tangle==no with colored background."
  (let* ((old-ret (funcall oldfun src-block contents info))
     (pars (org-babel-parse-header-arguments (org-element-property :parameters src-block)))
     (tangle (cdr (assoc :tangle pars))))
    (if (assoc-string tangle '(no))
    (concat
     "<div style=\"background-color:lightgray;\">"
     old-ret
     "</div>")
      old-ret)))

(advice-add 'org-html-src-block :around #'my-org-html-src-block-no-tangle)

(setq org-babel-exp-code-template "#+BEGIN_SRC %lang :tangle "no"
%body
#+END_SRC")

Tested with:

GNU Emacs 26.1 (build 1, x86_64-unknown-cygwin, GTK+ Version 3.22.28) of 2018-05-28

and the following org fragment:

There follows a minimal example code:

#+BEGIN_SRC emacs-lisp :tangle no :export both
(defun my-org-html-src-block-no-tangle (oldfun src-block contents info)
  "Wrap source blocks with :tangle==no with colored background."
  (let* ((old-ret (funcall oldfun src-block contents info))
     (pars (org-babel-parse-header-arguments (org-element-property :parameters src-block)))
     (tangle (cdr (assoc :tangle pars))))
    (if (assoc-string tangle '(no))
    (concat
     "<div style=\"background-color:lightgray;\">"
     old-ret
     "</div>")
      old-ret)))

(advice-add 'org-html-src-block :around #'my-org-html-src-block-no-tangle)

(setq org-babel-exp-code-template "#+BEGIN_SRC %lang%switches%flags :tangle %tangle
%body
,#+END_SRC")

#+END_SRC

#+BEGIN_SRC emacs-lisp :tangle t
(message "Hurrah!")
#+END_SRC

Test result:

Render source blocks with :tangle no different from that ones with :tangle t

Notes:

  • An alternative (maybe better) approach would be to derive a new exporter with org-export-define-derived-backend from 'html. The only function you would overwrite would be org-html-export-src-block and you could use the original version there.
  • You could also set org-babel-exp-code-template buffer-locally in your settings.org.
  • You don't need to add :tangle yes to each of the source blocks you want to tangle. You can just add the following line to the top of your settings.org:
    #+PROPERTY: header-args :tangle yes
  • 1
    @ShreevatsaR Note my last comment (at the bottom) about header-args. – Tobias Sep 5 '18 at 10:28
  • 1
    That works, thanks again... Nice work! – ShreevatsaR Sep 5 '18 at 20:01

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.