la.captions

This extension lets you assign captions to document elements, and wraps them (as appropriate) in the HTML elements intended for this purpose: <figcaption> within <figure>, and/or <caption> within <table>.

Once so structured, these figures, tables and captions can be styled with CSS and numbered using la.labels.

To caption an element:

  1. Write the caption itself as an ordinary Markdown paragraph (or block quote) before the element you are captioning, with a paragraph break in between.

  2. Attach the -caption directive to the caption. (The attr_list extension will be loaded automatically for this purpose, but you can also use la.attr_prefix.)

1. Basic Example

Here’s how it works in simple cases:

import lamarkdown as la
la('la.captions')
la.css('''
    figure { border: 1px solid gray;
             padding: 1em; }
''')
Some ordinary document text.

A diagram for your
consideration.
{-caption}

![Important diagram](diagram1.svg)

Some more ordinary document text.
<p>Some ordinary document text.</p>
<figure>
<figcaption>A diagram for your
consideration.</figcaption>
<img alt="Important diagram" src="data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9Im5vIj8+CjwhRE9DVFlQRSBzdmcgUFVCTElDICItLy9XM0MvL0RURCBTVkcgMS4xLy9FTiIKImh0dHA6Ly93d3cudzMub3JnL0dyYXBoaWNzL1NWRy8xLjEvRFREL3N2ZzExLmR0ZCI+CjwhLS0gR2VuZXJhdGVkIGJ5IGdyYXBodml6IHZlcnNpb24gOS4wLjAgKDApCi0tPgo8IS0tIFRpdGxlOiBEaWFncmFtIFBhZ2VzOiAxIC0tPgo8c3ZnIHdpZHRoPSIxMzRwdCIgaGVpZ2h0PSIxMDZwdCIKdmlld0JveD0iMC4wMCAwLjAwIDEzNC4yMSAxMDYuNDEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiPgo8ZyBpZD0iZ3JhcGgwIiBjbGFzcz0iZ3JhcGgiIHRyYW5zZm9ybT0ic2NhbGUoMSAxKSByb3RhdGUoMCkgdHJhbnNsYXRlKDQgMTAyLjQxKSI+Cjx0aXRsZT5EaWFncmFtPC90aXRsZT4KPHBvbHlnb24gZmlsbD0id2hpdGUiIHN0cm9rZT0ibm9uZSIgcG9pbnRzPSItNCw0IC00LC0xMDIuNDEgMTMwLjIxLC0xMDIuNDEgMTMwLjIxLDQgLTQsNCIvPgo8IS0tIEEgLS0+CjxnIGlkPSJub2RlMSIgY2xhc3M9Im5vZGUiPgo8dGl0bGU+QTwvdGl0bGU+Cjxwb2x5Z29uIGZpbGw9InBpbmsiIHN0cm9rZT0iYmxhY2siIHBvaW50cz0iNTQsLTk3LjkzIDAsLTk3LjkzIDAsLTYxLjkzIDU0LC02MS45MyA1NCwtOTcuOTMiLz4KPHRleHQgdGV4dC1hbmNob3I9Im1pZGRsZSIgeD0iMjciIHk9Ii03NS4yNiIgZm9udC1mYW1pbHk9IlRpbWVzLHNlcmlmIiBmb250LXNpemU9IjE0LjAwIj5BPC90ZXh0Pgo8L2c+CjwhLS0gQiAtLT4KPGcgaWQ9Im5vZGUyIiBjbGFzcz0ibm9kZSI+Cjx0aXRsZT5CPC90aXRsZT4KPHBvbHlnb24gZmlsbD0ibGlnaHR5ZWxsb3ciIHN0cm9rZT0iYmxhY2siIHBvaW50cz0iMTI2LjIxLC05OC40MSA3Mi4yMSwtOTguNDEgNzIuMjEsLTYyLjQxIDEyNi4yMSwtNjIuNDEgMTI2LjIxLC05OC40MSIvPgo8dGV4dCB0ZXh0LWFuY2hvcj0ibWlkZGxlIiB4PSI5OS4yMSIgeT0iLTc1LjczIiBmb250LWZhbWlseT0iVGltZXMsc2VyaWYiIGZvbnQtc2l6ZT0iMTQuMDAiPkI8L3RleHQ+CjwvZz4KPCEtLSBBJiM0NTsmZ3Q7QiAtLT4KPGcgaWQ9ImVkZ2UxIiBjbGFzcz0iZWRnZSI+Cjx0aXRsZT5BJiM0NTsmZ3Q7QjwvdGl0bGU+CjxwYXRoIGZpbGw9Im5vbmUiIHN0cm9rZT0iYmxhY2siIGQ9Ik01NC4zLC04MC4xMUM1Ni4zNiwtODAuMTMgNTguNDcsLTgwLjE0IDYwLjU5LC04MC4xNSIvPgo8cG9seWdvbiBmaWxsPSJibGFjayIgc3Ryb2tlPSJibGFjayIgcG9pbnRzPSI2MC4zMywtODMuNjUgNzAuMzYsLTgwLjIyIDYwLjM4LC03Ni42NSA2MC4zMywtODMuNjUiLz4KPC9nPgo8IS0tIEMgLS0+CjxnIGlkPSJub2RlMyIgY2xhc3M9Im5vZGUiPgo8dGl0bGU+QzwvdGl0bGU+Cjxwb2x5Z29uIGZpbGw9ImxpZ2h0Ymx1ZSIgc3Ryb2tlPSJibGFjayIgcG9pbnRzPSI5MC41OSwtMzYgMzYuNTksLTM2IDM2LjU5LDAgOTAuNTksMCA5MC41OSwtMzYiLz4KPHRleHQgdGV4dC1hbmNob3I9Im1pZGRsZSIgeD0iNjMuNTkiIHk9Ii0xMy4zMiIgZm9udC1mYW1pbHk9IlRpbWVzLHNlcmlmIiBmb250LXNpemU9IjE0LjAwIj5DPC90ZXh0Pgo8L2c+CjwhLS0gQiYjNDU7Jmd0O0MgLS0+CjxnIGlkPSJlZGdlMiIgY2xhc3M9ImVkZ2UiPgo8dGl0bGU+QiYjNDU7Jmd0O0M8L3RpdGxlPgo8cGF0aCBmaWxsPSJub25lIiBzdHJva2U9ImJsYWNrIiBkPSJNODguNzEsLTYyLjAyQzg1LjkxLC01Ny4xMSA4Mi44MiwtNTEuNjkgNzkuNzksLTQ2LjM4Ii8+Cjxwb2x5Z29uIGZpbGw9ImJsYWNrIiBzdHJva2U9ImJsYWNrIiBwb2ludHM9IjgyLjg4LC00NC43NCA3NC44OCwtMzcuNzkgNzYuOCwtNDguMjEgODIuODgsLTQ0Ljc0Ii8+CjwvZz4KPCEtLSBDJiM0NTsmZ3Q7QSAtLT4KPGcgaWQ9ImVkZ2UzIiBjbGFzcz0iZWRnZSI+Cjx0aXRsZT5DJiM0NTsmZ3Q7QTwvdGl0bGU+CjxwYXRoIGZpbGw9Im5vbmUiIHN0cm9rZT0iYmxhY2siIGQ9Ik01Mi44MSwtMzYuMjVDNDkuOTMsLTQxLjEyIDQ2Ljc2LC00Ni41IDQzLjY0LC01MS43NyIvPgo8cG9seWdvbiBmaWxsPSJibGFjayIgc3Ryb2tlPSJibGFjayIgcG9pbnRzPSI0MC42NywtNDkuOTEgMzguNiwtNjAuMyA0Ni43LC01My40NyA0MC42NywtNDkuOTEiLz4KPC9nPgo8L2c+Cjwvc3ZnPg==">
</figure>
<p>Some more ordinary document text.</p>

Design Notes

An alternate (hypothetical) approach would be to write captions as values of the -caption directive itself, e.g.:

{-caption="A diagram for your consideration."}
![Important diagram](diagram1.svg)

<!-- Not actually how it works! -->

This alternate approach would be unnecessarily limiting, because no Markdown processing occurs within attribute values. Thus, a caption would be limited to a single paragraph of text devoid of formatting, links, or any other semantic structure. There seems no advantage to this.

Also, in the actual approach taken, captions must be written above (not below) their captioned elements, because:

  • This is consistent with the traditional placement of table captions.

  • Though figure captions traditionally appear underneath figures, this applies to formatted documents, where figures can be viewed as the pictures or diagrams they are intended to be. In Markdown, the code representing a figure usually won’t have any meaning on its own, at a glance.

  • We need a consistent rule. We can’t permit captions to appear either above or below, without creating ambiguity or additional complexity.

This only applies to the .md file itself. The HTML document can be styled so that captions appear anywhere you wish.

2. Tables

When captioning a table, the HTML structure will use the <table> and <caption> elements. (The default styling may show the caption protruding outside the physical table boundary, but it’s still logically part of the table.)

import lamarkdown as la
la('la.captions', 'tables')
la.css('''
    table  { border: 1px solid red; }
    td, th { border: 1px solid blue; }
''')
A table for your
consideration.
{-caption}

Heading A | Heading B
--------- | ---------
One       | Two
Three     | Four
<table>
<caption>A table for your
consideration.</caption>
<thead>
<tr>
<th>Heading A</th>
<th>Heading B</th>
</tr>
</thead>
<tbody>
<tr>
<td>One</td>
<td>Two</td>
</tr>
<tr>
<td>Three</td>
<td>Four</td>
</tr>
</tbody>
</table>

3. Complex Captions

If a caption requires more than one paragraph and/or other block elements, then:

  1. You can represent it using the Markdown “block quote” syntax (prefixing lines with >), but also
  2. You will need to use la.attr_prefix in order to attach the -caption directive above the block quote. (You can do this regardless, even in simpler cases, if you wish.)
import lamarkdown as la
la('la.captions', 'la.attr_prefix')
la.css('figure { border: 1px solid gray; '
       '         padding: 1em; }')
{-caption}
> A diagram for your
> consideration.
>
> It requires some complex explanation:
>
> * First, here's a list item.
> * Second, there's another.

![Important diagram](diagram1.svg)
<figure>
<figcaption>
<p>A diagram for your
consideration.</p>
<p>It requires some complex explanation:</p>
<ul>
<li>First, here's a list item.</li>
<li>Second, there's another.</li>
</ul></figcaption>
<img alt="Important diagram" src="data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9Im5vIj8+CjwhRE9DVFlQRSBzdmcgUFVCTElDICItLy9XM0MvL0RURCBTVkcgMS4xLy9FTiIKImh0dHA6Ly93d3cudzMub3JnL0dyYXBoaWNzL1NWRy8xLjEvRFREL3N2ZzExLmR0ZCI+CjwhLS0gR2VuZXJhdGVkIGJ5IGdyYXBodml6IHZlcnNpb24gOS4wLjAgKDApCi0tPgo8IS0tIFRpdGxlOiBEaWFncmFtIFBhZ2VzOiAxIC0tPgo8c3ZnIHdpZHRoPSIxMzRwdCIgaGVpZ2h0PSIxMDZwdCIKdmlld0JveD0iMC4wMCAwLjAwIDEzNC4yMSAxMDYuNDEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiPgo8ZyBpZD0iZ3JhcGgwIiBjbGFzcz0iZ3JhcGgiIHRyYW5zZm9ybT0ic2NhbGUoMSAxKSByb3RhdGUoMCkgdHJhbnNsYXRlKDQgMTAyLjQxKSI+Cjx0aXRsZT5EaWFncmFtPC90aXRsZT4KPHBvbHlnb24gZmlsbD0id2hpdGUiIHN0cm9rZT0ibm9uZSIgcG9pbnRzPSItNCw0IC00LC0xMDIuNDEgMTMwLjIxLC0xMDIuNDEgMTMwLjIxLDQgLTQsNCIvPgo8IS0tIEEgLS0+CjxnIGlkPSJub2RlMSIgY2xhc3M9Im5vZGUiPgo8dGl0bGU+QTwvdGl0bGU+Cjxwb2x5Z29uIGZpbGw9InBpbmsiIHN0cm9rZT0iYmxhY2siIHBvaW50cz0iNTQsLTk3LjkzIDAsLTk3LjkzIDAsLTYxLjkzIDU0LC02MS45MyA1NCwtOTcuOTMiLz4KPHRleHQgdGV4dC1hbmNob3I9Im1pZGRsZSIgeD0iMjciIHk9Ii03NS4yNiIgZm9udC1mYW1pbHk9IlRpbWVzLHNlcmlmIiBmb250LXNpemU9IjE0LjAwIj5BPC90ZXh0Pgo8L2c+CjwhLS0gQiAtLT4KPGcgaWQ9Im5vZGUyIiBjbGFzcz0ibm9kZSI+Cjx0aXRsZT5CPC90aXRsZT4KPHBvbHlnb24gZmlsbD0ibGlnaHR5ZWxsb3ciIHN0cm9rZT0iYmxhY2siIHBvaW50cz0iMTI2LjIxLC05OC40MSA3Mi4yMSwtOTguNDEgNzIuMjEsLTYyLjQxIDEyNi4yMSwtNjIuNDEgMTI2LjIxLC05OC40MSIvPgo8dGV4dCB0ZXh0LWFuY2hvcj0ibWlkZGxlIiB4PSI5OS4yMSIgeT0iLTc1LjczIiBmb250LWZhbWlseT0iVGltZXMsc2VyaWYiIGZvbnQtc2l6ZT0iMTQuMDAiPkI8L3RleHQ+CjwvZz4KPCEtLSBBJiM0NTsmZ3Q7QiAtLT4KPGcgaWQ9ImVkZ2UxIiBjbGFzcz0iZWRnZSI+Cjx0aXRsZT5BJiM0NTsmZ3Q7QjwvdGl0bGU+CjxwYXRoIGZpbGw9Im5vbmUiIHN0cm9rZT0iYmxhY2siIGQ9Ik01NC4zLC04MC4xMUM1Ni4zNiwtODAuMTMgNTguNDcsLTgwLjE0IDYwLjU5LC04MC4xNSIvPgo8cG9seWdvbiBmaWxsPSJibGFjayIgc3Ryb2tlPSJibGFjayIgcG9pbnRzPSI2MC4zMywtODMuNjUgNzAuMzYsLTgwLjIyIDYwLjM4LC03Ni42NSA2MC4zMywtODMuNjUiLz4KPC9nPgo8IS0tIEMgLS0+CjxnIGlkPSJub2RlMyIgY2xhc3M9Im5vZGUiPgo8dGl0bGU+QzwvdGl0bGU+Cjxwb2x5Z29uIGZpbGw9ImxpZ2h0Ymx1ZSIgc3Ryb2tlPSJibGFjayIgcG9pbnRzPSI5MC41OSwtMzYgMzYuNTksLTM2IDM2LjU5LDAgOTAuNTksMCA5MC41OSwtMzYiLz4KPHRleHQgdGV4dC1hbmNob3I9Im1pZGRsZSIgeD0iNjMuNTkiIHk9Ii0xMy4zMiIgZm9udC1mYW1pbHk9IlRpbWVzLHNlcmlmIiBmb250LXNpemU9IjE0LjAwIj5DPC90ZXh0Pgo8L2c+CjwhLS0gQiYjNDU7Jmd0O0MgLS0+CjxnIGlkPSJlZGdlMiIgY2xhc3M9ImVkZ2UiPgo8dGl0bGU+QiYjNDU7Jmd0O0M8L3RpdGxlPgo8cGF0aCBmaWxsPSJub25lIiBzdHJva2U9ImJsYWNrIiBkPSJNODguNzEsLTYyLjAyQzg1LjkxLC01Ny4xMSA4Mi44MiwtNTEuNjkgNzkuNzksLTQ2LjM4Ii8+Cjxwb2x5Z29uIGZpbGw9ImJsYWNrIiBzdHJva2U9ImJsYWNrIiBwb2ludHM9IjgyLjg4LC00NC43NCA3NC44OCwtMzcuNzkgNzYuOCwtNDguMjEgODIuODgsLTQ0Ljc0Ii8+CjwvZz4KPCEtLSBDJiM0NTsmZ3Q7QSAtLT4KPGcgaWQ9ImVkZ2UzIiBjbGFzcz0iZWRnZSI+Cjx0aXRsZT5DJiM0NTsmZ3Q7QTwvdGl0bGU+CjxwYXRoIGZpbGw9Im5vbmUiIHN0cm9rZT0iYmxhY2siIGQ9Ik01Mi44MSwtMzYuMjVDNDkuOTMsLTQxLjEyIDQ2Ljc2LC00Ni41IDQzLjY0LC01MS43NyIvPgo8cG9seWdvbiBmaWxsPSJibGFjayIgc3Ryb2tlPSJibGFjayIgcG9pbnRzPSI0MC42NywtNDkuOTEgMzguNiwtNjAuMyA0Ni43LC01My40NyA0MC42NywtNDkuOTEiLz4KPC9nPgo8L2c+Cjwvc3ZnPg==">
</figure>

4. Options

Option Description
directives An object for retrieving directives from HTML tree elements. This should be an instance of lamarkdown.lib.directives.Directives, and the extension will reuse Lamarkdown’s “current” instance by default, if available.
progress An object accepting error, warning and progress messages. This should be an instance of lamarkdown.lib.Progress, and the extension will reuse Lamarkdown’s “current” instance by default, if available.
autowrap_listings False by default. If True, wrap all code listings (<pre> elements containing a <code> element) in a <figure> element, even where no caption is provided. The theory is that listings are often less in need of a caption than ordinary figures or tables, but it may still be desirable to have them automatically numbered with the la.labels extension (which would otherwise ignore them).
autowrap_maths False by default. If True, wrap all block-style MathML (<math>) elements in a <figure> element, even when no caption is provided. The same reasoning applies as for autowrap_listings.