la.labels
This extension assigns counter-based (or fixed) labels to headings, lists, figures and tables, and lets you use those labels in links to labelled elements.
You can specify where and how labels should appear by:
- Adding the
-label=...
directive to headings, lists, figures and tables; or - Specifying the
labels
configuration option.
In both cases, you provide a label template.
Note
Remember that, while the following examples all use the -label
directive, you can just as easily write templates using the labels
configuration option. In the latter case, you may not need to modify the .md
file at all in order to produce the labelling systems you want.
1. Label Templates
A label template has several parts.
1.1. Counter Types
A counter type is a system for counting integers. Given -label="1"
, the 1
is a counter type representing base-10 Arabic numerals. You can also provide A
or a
for upper/lower-case alphabetic numbering, I
or i
for upper/lower-case Roman numerals, or one of various longer-form names corresponding to CSS counter styles (e.g., simp-chinese-informal
, lower-greek
, lower-hexadecimal
, etc.).
## Heading {-label="i "}
## Heading
{-label="simp-chinese-formal "}
1. List item
2. List item
Design Notes
The available counter types are essentially the same as the values supported by the list-style-type
CSS property, except for:
- Bullet-points like
disc
,circle
,square
,disclosure-open
anddisclosure-closed
(which would simply duplicate literal Unicode characters); - Global CSS values like
inherit
,initial
, etc.; - The value
none
; - Custom counter styles.
The use of CSS belies some internal complexity. Lists are numbered by generating CSS code that itself produces the labels (because this seems the conventional approach to HTML/CSS lists). However, headings (and figures and tables) are labelled at compile time, the labels becoming part of the HTML document content.
This is partly because the toc
extension will read heading text (at compile time, of course), and reproduce it inside the table-of-contents, and we’d ideally like the table-of-contents to contain the same heading labels that the headings themselves do.
To support compile-time labelling, la.labels
must implement much of the same counter logic as browsers do to support CSS’s @counter-style
construct.
A future version of Lamarkdown may:
- Provide a configuration option to determine which implementation approach to use for which type of element; and/or
- Provide a way to define custom counter types, similar to
@counter-style
.
1.2. Literals
Literal strings can appear as the prefix and suffix of a label. In -label="(1) "
, the (
is a prefix, and )
is a suffix. Literals may contain any number of characters, including zero: e.g.:
{-label="@@@ A @@@"}
1. List item
2. List item
3. List item
Literals can consist of:
-
Spaces and all printable symbols other than ASCII digits, letters, quotation marks,
,
,-
and*
. -
-
, when not between alphanumeric characters (where it is considered part of a counter type). -
*
, when not the final character following,
(where it has a special meaning, explained below). -
Characters within an additional pair of quotation marks. There will already be a pair of quotation marks around the entire template (whether
-label='...'
orlabel="..."
), so the inner quotation marks must be different. For instance:{-label="'Table' 1."} Column A | Column B -------- | -------- One | Two Three | Four Column C | Column D -------- | -------- Five | Six Seven | Eight
-
Quotation marks, when doubled-up within other quotation marks; e.g.,
-label="''''1''''"
produces a base-10 arabic number inside a single set of quotation marks:'1'
,'2'
, etc.Note: the attribute syntax (the general form
attr="value"
) has its own separate way of escaping characters with\
, but this is invisible to the template syntax, so cannot be used to designate literal characters.
A label may consist of just a literal string, with no counter type, which can be useful in unordered lists:
{-label="{-⦿-} "}
* List item
* List item
* List item
1.3. Hierarchical Labels
A parent indicator (if present) is used to make hierarchical labels. It acts as a placeholder for a higher-level label, which then forms part of the lower-level label, preceeding the lower-level counter. (The higher-level label’s own prefix and suffix are removed.)
A template with a parent indicator has a form similar to -label="(L.1) "
, where L
is the parent indicator, and .
is a separator literal (which can be any valid literal). L
specifically refers to the label of the next higher list, if one exists.
For instance:
{-label="L.1. "}
1. Item
2. Item
{-label="[L.A] "}
1. Item
2. Item
{-label="_L_i_ "}
1. Item
2. Item
3. Item
3. Item
In the first label template above, the L.
part will be ignored, because there is no higher list level.
Similarly, the parent indicator H
refers to the label of the next higher heading (if one exists):
{-label="H.1. "}
## Heading
## Heading
{-label="[H.A] "}
### Heading
### Heading
{-label="_H_i_ "}
#### Heading
#### Heading
### Heading
## Heading
Meanwhile, X
refers to the next label label of any kind. For example, here are some <h3>
headings, within an <ol>
list, underneath another <h2>
heading, where the labels are arranged hierarchically:
{-label="1. "}
## Heading
## Heading
{-label="[X.A] "}
1. List item
2. List item
{-label="_X_i_ "}
### Heading
### Heading
1.4. Inner Templates
An inner template is the part of a template after the first (non-quoted) ,
. A full label template consists of a ,
-separated sequence of components (each of which is as described above), optionally ending in ,*
.
Inner label templates let you set up several levels of labelling in one place. They apply to nested elements of the same type. For instance, -label="1. ,(a) ,(i) "
assigns labels 1.
, 2.
, etc. to the current level, (a)
, (b)
to singly-nested elements, and (i)
, (ii)
to doubly-nested elements (all of the same type).
{-label="1. ,(a), (i) "}
1. List item
1. List item
1. List item
2. List item
2. List item
2. List item
{-label="♠ ,♥, ♣, ♦ "}
* List item
* List item
* List item
* List item
* List item
* List item
When ,*
occurs after the final template component, it applies that template to all more-deeply nested elements indefinitely (until otherwise overridden).
Together with parent indicators, this lets you produce a typical multilevel decimal numbering system with little overhead:
{-label="H.1. ,*"}
## Heading
### Heading
#### Heading
#### Heading
### Heading
## Heading
2. Cross References
Once elements are labelled, you can create links to them (or parts of them) that include those labels in the link text. Specifically, you must:
- Assign an ID to the target of a link, e.g., by writing
{#myid}
before or after it. The ID does not need to be on precisely the element that actually has the label; it may also be on any element inside it. - Create a link to that ID, where the link text contains
##
.
For instance:
Some references to headings [##](#secX) and
[##](#secY), and to [list item ##](#itemU) and
[list item ##](#itemV).
{-label="1. "}
## Heading {#secX}
## Heading {#secY}
{-label="(a) "}
1. List item
{#itemU}
2. List item
{#itemV}
You can be more specific about what kind of label you want to refer to, by appending a parent indicator to the ##
; e.g., ##H
or ##L
. You can also have multiple such placeholders for a single link.
A reference to [list item ##L in section ##H](#item).
{-label="1. "}
## Heading
## Heading
{-label="(a) "}
1. List item
2. List item
{#item}
Design Notes
The use of ##
has the advantage that:
- It is concise, without being too likely to require routine escaping (as a single
#
may); - It appears to reflect a number;
- It also seems visually-related to the element IDs syntax (
#myid
), while not being exactly the same; and - Since it only applies inside link text, it does not conflict with heading syntax.
One might compare the approach to LaTeX, which uses \label
and \ref
:
A reference to Section \ref{xyz}.
\section{First}
...
\section{Second}
\label{xyz}
...
Markdown and HTML have element IDs in place of \label
. They do not have an exact equivalent of \ref
(which just grabs a label). But rather than trying to recreate \ref
exactly, we accept the preeminence of hyperlinks in Markdown and HTML, and work within them.
One theoretical weakness of the la.labels
approach is that you cannot make a label reference outside of a hyperlink. There seems little practical drawback to this, though.
la.labels
does not replace or directly alter the Markdown link-parsing logic, but rather looks for the text inside <a>
(anchor) elements once they’ve already been parsed.
3. Suppressing Labels: -no-label
The -no-label
directive will suppress a label in places where one would otherwise occur. The counter will be paused, and carry on at the next applicable element.
## Heading {-label="(i) "}
## Heading {-no-label}
## Heading
{-label="(i) "}
1. List item
2. List item
{-no-label}
3. List item
4. Changing Labels
The label format may be changed part-way through a sequence of elements, simply by assigning a new -label
template to one of the elements. For instance:
## Heading {-label="(i) "}
## Heading
## Heading {-label="[A] "}
## Heading
{-label="(i) "}
1. List item
2. List item
3. List item
{-label="[A] "}
4. List item
5. Options
The labels
option is the one key option for influencing document-wide labelling conventions. The remainder of the options below concern the technical implementation details.
Option | Description | |
---|---|---|
css_fn |
A function taking a single string parameter, which the extension will call to deliver CSS code, under the assumption that it will be applied to the output document. The extension needs this capability in order to implement CSS-based labels, particularly for ordered/unordered lists. By default, and if it’s available, this will be If |
|
css_rendering |
A set containing element types that will receive CSS-based label rendering, if it’s available, rather than hard-coded labels. It’s not currently recommended to change this, because the underlying implementation only currently supports CSS-based rendering for list labels. | |
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. |
|
label_processors |
A list of LabelProcessor objects responsible for orchestrating the labelling of different kinds of HTML elements. It’s not currently recommended to change this. |
|
labels |
A dictionary specifying label templates to use in the absence of The dictionary keys are The dictionary values are label templates. Just as for the By default, |
|
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. |
- |