2

I want to style some HTML source block exports differently than others.

Say I want the "Hi" block to have a green background and "Bye" to be red:

#+COMMENT: -*- org-html-htmlize-output-type: css -*-

#+begin_src python
print("Hi")
#+end_src

#+begin_src python
print("Bye")
#+end_src

The relevent HTML export is,

<div id="content">
<div class="org-src-container">
<pre class="src src-python"><span class="org-keyword">print</span>(<span class="org-string">"Hi"</span>)
</pre>
</div>

<div class="org-src-container">
<pre class="src src-python"><span class="org-keyword">print</span>(<span class="org-string">"Bye"</span>)
</pre>
</div>
</div>

Each block corresponds to a org-src-container or src src-python and there is no way to differentiate them individually via CSS (unless I'm mistaken).

My thought is to assign a class or id tag to an individual block's div or pre. It seems like #+ATTR_HTML might work but the following produces the same output:

#+COMMENT: -*- org-html-htmlize-output-type: css -*-

#+ATTR_HTML: :class myclass :id myid
#+begin_src python
print("Hi")
#+end_src

#+begin_src python
print("Bye")
#+end_src

How can I add a class or id selector to specific block exports?

EDIT

From looking at the Org docs more, it appears that #+ATTR_HTML is only for tables and links when used with a source block. Frustratingly, it works exactly how I would like it to for example blocks: Org mode - change code block background color I suppose I could use that, except syntax highlighting doesn't seem to apply to example block exports.

I tried advising the org-html-src-block to include the desired tags (based off of Generate different markup for not-tangled code blocks in org-mode). Unfortunately, I couldn't find a way to pass information to the function (e.g. such as through a new key-value pair within the #+begin_src line). The info parameter only contains meta-data.

Finally, I tried applying a filter (i.e. regexp replace). This worked for single lines, but I couldn't get it to apply generally, such for multiple lines or to have a generic form. Using the regexp-builder, I could capture the code portion, the CSS tag, and the value with

"\\(?1:[^\n]+\\)#\s+\\(?2:[A-Za-z-]+\\):\s+\\(?3:.+\\)"

This would correspond to the print("Hi"), background-color, and rgb(255, 0, 0) in

#+begin_src python
print("Hi")  # background-color: rgb(255, 0, 0)
#+end_src

This was inspired by: https://emacs.stackexchange.com/questions/20417/org-mode-highlight-lines-i$|org-export-derived-backend-p

2

You can do this with the advice method. It's not the info parameter you need, but src-block. Use the org-export-read-attribute to extract the #ATTR_HTML contents.

The following advice checks for the :class and :id keywords in a #attr_html line and constructs a div around the source block accordingly.

(defun my-org-html-src-block-advice (oldfun src-block contents info)
  "Add class or id CSS tags to html source block output.

Allows class or id tags to be added to a source block using
#attr_html:

    #+ATTR_HTML: :class myclass :id myid
    #+begin_src python
    print(\"Hi\")
    #+end_src
"
  (let* ((old-ret (funcall oldfun src-block contents info))
         (class-tag (org-export-read-attribute :attr_html src-block :class))
         (id-tag (org-export-read-attribute :attr_html src-block :id)))
    (if (or class-tag id-tag)
        (concat
         "<div "
         (if class-tag (format "class=\"%s\" " class-tag))
         (if id-tag (format "id=\"%s\" " id-tag))
         ">"
         old-ret
         "</div>")
      old-ret)))

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

When applied to the sample Org file, it produces the output:

<div class="myclass" id="myid" ><div class="org-src-container">
<pre class="src src-python"><span class="org-keyword">print</span>(<span class="org-string">"Hi"</span>)
</pre>
</div></div>

<div class="org-src-container">
<pre class="src src-python"><span class="org-keyword">print</span>(<span class="org-string">"Bye"</span>)
</pre>
</div>

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.