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.

ShreevatsaR
  • 880
  • 6
  • 19
  • 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

1 Answers1

3

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
Tobias
  • 32,569
  • 1
  • 34
  • 75