1

With

#+CAPTION: my-caption
[[file:image.png]]

I get a caption (with a number) both in LaTeX and in HTML. The same with tables and src blocks (which become listings in LaTeX)

But with a theorem, definition, ... and all other mathematical environments I cannot get a title and a number.

#+ATTR_LATEX: :options [my-theorem]
#+BEGIN_theorem
....
#+END_theorem

works for LaTeX, but in HTML I don't get the caption (and most importantly the number).

This instead breaks also LaTeX because inserts a \caption macro inside the environment:

#+CAPTION: my-theorem
#+BEGIN_theorem
....
#+END_theorem

How can I create a new special block which takes care of numbering also for HTML (like for figures, tables and listings)?

For the caption the solution is very simple:

#+ATTR_LATEX: :options [my-theorem]
#+BEGIN_theorem
@@html:<span class="theorem-title">my-theorem</span>@@
....
#+END_theorem

so the difficult part is taking care of the numbering.

UPDATE
With org-special-block-extras I achieved this:

(defvar special-block-definition-counter 0)
(defblock definition (title nil) (label nil unnumbered nil)
  "Definition special block."
  (unless unnumbered (cl-incf special-block-definition-counter))
  (format
   (cond
    ((org-export-derived-backend-p org-export-current-backend 'latex)
     (concat "\\begin{definition" (when unnumbered "*") "}{%s}{%s}\n"
             "%s"
             "\\end{definition" (when unnumbered "*") "}"))
    ((org-export-derived-backend-p org-export-current-backend 'html)
     (concat "<p class=\"admonition-title definition\">Definizione" (unless unnumbered (format " %d" special-block-definition-counter)) (when title ": ") "%s</p>"
             "<div id=\"%s\" class=\"special-block definition\">%s</div>")))
   (or title "") (or label "") contents))

and

#+BEGIN_definition Definition title :label def:example
....
#+END_definition

To export correctly for ePub a patch is needed (for more info: https://github.com/alhassy/org-special-block-extras/issues/12):

(add-to-list 'org-export-filter-parse-tree-functions
             (lambda (tree backend info)
               (when (eq backend 'epub)
                 (org-element-map tree 'export-block
                   (lambda (el)
                     (when (string= (org-element-property :type el) "EPUB")
                       (org-element-put-property el :type "HTML")))))
               tree))

Now I have only to manage the internal links (label/reference).

2
  • 1
    My knee-jerk reaction would be to derive a new exporter from the HTML exporter with the only difference being the handling of special blocks (in particular, the theorem block). But I don't know enough about HTML/CSS to say definitively that you have to do it this way: it might be possible to do something outside of the exporter. If you do decide to go with a derived exporter, examples can be found in the Org mode sources. See Appendix A.4 of the manual (C-h i g(org)adding export TAB will get you there) and the doc on Worg that ...
    – NickD
    Aug 26, 2021 at 1:37
  • 1
    ... is referenced therein. However, you do need to know some elisp for that.
    – NickD
    Aug 26, 2021 at 1:38

1 Answer 1

0

I finally solved using org-special-block-extras:

  1. Define a macro to define a new theorem type (calls defblock) and its link. This also takes count in a list of all the labels to get numbers and links.
(defmacro special-block-labels-push (name label)
  (let ((labels (format "special-block-%s-labels" name))
        (labels-cdr (format "special-block-%s-labels-cdr" name)))
    `(let ((label (list (format "%s" ,label))))
       (setq ,(intern labels-cdr)
             (if ,(intern labels-cdr)
                 (setcdr ,(intern labels-cdr) label)
               (setq ,(intern labels) label))))))

(defmacro defspeciallink (name prefix)
  `(progn
     (defvar ,(intern (format "special-block-%s-labels" name)) '()) ; to store this theroem labels
     (defvar ,(intern (format "special-block-%s-labels-cdr" name)) nil)

     (defblock ,prefix (ref nil) ()
       ,(format "Reference a %s special block." name)
       (format
        (cond
         ((org-export-derived-backend-p org-export-current-backend 'latex)
          ,(format "\\ref{%s:%%s}" prefix)) ; use standard ref in LateX
         ((org-export-derived-backend-p org-export-current-backend 'html)
          ,(format "<a href=\"#%s:%%s\">%%d</a>" prefix))) ; in HTML the number has to be print manually, finding the position of the label in the list
        ref (1+ (cl-position (format "%s" ref) ,(intern (format "special-block-%s-labels" name)) :test 'equal)))))) ; sum one because lists are zero based

(defmacro deftheorem (name display-name prefix &optional tcb)
  "Defines a new theorem type called NAME (rendered as DISPLAY-NAME in HTML) which labels start with PREFIX. If TCB is not nil, in LaTeX the tcbtheorem syntax is used.
Usage:
,#+BEGIN_name Title :label lbl
....
,#+END_name
As can be seen in [[prefix:lbl]]
                "
  `(progn
     (defspeciallink ,name ,prefix)

     (defblock ,name (title nil) (label nil unnumbered nil)
       ,(format "Define %s special block." name)
       (unless unnumbered (special-block-labels-push ,name label)) ; add label to list
       (format
        (cond
         ((org-export-derived-backend-p org-export-current-backend 'latex)
          (concat ,(format "\\begin{%s" name) (when unnumbered "*") "}"
                  ,(if tcb "{%s}{%s}" (format "[%%s]\\label{%s:%%s}" prefix)) ; tcbtheorem or standard
                  "\n%s"
                  ,(format "\\end{%s" name) (when unnumbered "*") "}"))
         ((org-export-derived-backend-p org-export-current-backend 'html)
          (concat ,(format "<p class=\"admonition-title %s\">%s" name display-name)
                  (unless unnumbered (format " %d" (length ,(intern (format "special-block-%s-labels" name)))))
                  (when title ": ") "%s</p>"
                  ,(format "<div id=\"%s:%%s\" class=\"special-block %s\">%%s</div>" prefix name))))
        (or title "") (or label "") contents))))

It works both with standard LaTeX theorems and tcbtheorems (using the last parameter.

  1. Add new theorems using the previous macro:
(deftheorem definition "Definizione" def)
(deftheorem theorem "Teorema" thm)
(deftheorem postulate "Postulato" pos)
(deftheorem axiom "Assioma" axi)
(deftheorem proposition "Proposizione" pro)
(deftheorem corollary "Corollario" cor)
(deftheorem lemma "Lemma" lem)
(deftheorem principia "Principio" pri t)
(deftheorem alg "Algoritmo" alg t)
  1. (OPT) add new LatTeX theorems:
\newtcbtheorem[auto counter,number within=chapter]{principia}{Principio}{propstyle}{pri}
\newtcbtheorem[auto counter,number within=chapter]{alg}{Algoritmo}{algstyle}{alg}
  1. Add CSS style (I based on ReadTheOrg):
/* BLOCKS */
#content .special-block {
  padding: 12px;
  line-height: 24px;
  margin-bottom: 24px;
}
#content .special-block p:last-child {
  margin-bottom: 0;
}
#content .admonition-title {
  color: #fff;
  font-weight: bold;
  display: block;
  padding: 6px 12px;
  margin-bottom: 0px;
}
/* Definition: green */
#content .definition {background-color: #dbfaf4;}
#content p.admonition-title.definition {background-color: #1abc9c;}
/* Theorem: orange */
#content .theorem, 
#content .postulate, 
#content .axiom, 
#content .corollary, 
#content .lemma {background-color: #ffedcc;}
#content p.admonition-title.theorem,
#content p.admonition-title.postulate,
#content p.admonition-title.axiom,
#content p.admonition-title.corollary,
#content p.admonition-title.lemma {background-color: #f0b37e;}
/* Proposition: blue*/
#content .proposition,
#content .principia {background-color: #e7f2fa;}
#content p.admonition-title.proposition,
#content p.admonition-title.principia{background-color: #6ab0de;}
/* Algorithm: gray */
#content .alg {background-color: #ddd;}
#content p.admonition-title.alg {background-color: #333;}
  1. Use it in Org mode:
#+BEGIN_theorem My theorem :label test
....
#+END_theorem
...
As said in theorem [[thm:test]]
1
  • Didn't work for me, could you please clarify? I get error 'Unable to resolve link "thm:test"' while exporting to html. Here's what I did: (i) added macros and links defined in steps 1 and 2 to my emacs-config.org file, (ii) created style.css file and added the style from step 4, (iii) skipped step 3, (iv) added this line at the top of my org file: "#+HTML_HEAD: <link rel="stylesheet" type="text/css" href="style.css" />", and (v) in the body of my org file, I added the content from step 5. If I omit the last line from step 5, I get a html with theorem style but without caption and number.
    – vpk
    May 5, 2022 at 6:36

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

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