Skip to content

Extend caption syntax to images and block quotes - #373

Open
dereuromark wants to merge 2 commits into
jgm:mainfrom
dereuromark:caption-images-blockquotes
Open

Extend caption syntax to images and block quotes#373
dereuromark wants to merge 2 commits into
jgm:mainfrom
dereuromark:caption-images-blockquotes

Conversation

@dereuromark

@dereuromark dereuromark commented Feb 5, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Extends the existing ^ caption syntax (currently tables only) to also support images and block quotes
  • Extracts caption rules into a dedicated "Caption" section in the spec for clarity
  • Image + caption: wraps in <figure> with <figcaption>
  • Block quote + caption: wraps in <figure> with <figcaption>, useful for attributions
  • Table caption behavior is unchanged (<caption> element)
  • Multi-line caption example included

This is a natural extension of the table caption syntax that already exists in the spec, using the same ^ marker consistently across elements.

Examples:

![Sunset over the ocean](sunset.jpg)
^ A beautiful sunset captured at the beach

> To be or not to be, that is the question.
^ William Shakespeare, Hamlet

Addresses #28 and #31.

A reference implementation already exists in djot-php:

closing the gap between upstream spec and downstream implementations.

Generalize the existing table caption syntax (^ caption text) to
also support images and block quotes:

- Image + caption: wraps in <figure> with <figcaption>
- Block quote + caption: wraps in <figure> with <figcaption>,
  useful for attributions
- Table caption behavior is unchanged (<caption> element)

Extract the caption rules into a dedicated "Caption" section in the
spec for clarity, replacing the table-specific caption paragraph.

Addresses jgm#28 and jgm#31.
dereuromark added a commit to dereuromark/djot.js that referenced this pull request Feb 5, 2026
Extend the existing table caption syntax (^ caption text) to also
work with images and block quotes, wrapping them in <figure> and
<figcaption> HTML elements.

- Add Figure and Figcaption AST node types
- Modify the -caption handler in parse.ts to detect image paragraphs
  and block quotes, wrapping them in figure/figcaption nodes
- Add figure/figcaption rendering in the HTML renderer
- Add test cases for image captions, block quote captions, formatted
  captions, and non-captionable element handling

Companion spec PR: jgm/djot#373
Comment thread doc/syntax.md Outdated
@dereuromark

Copy link
Copy Markdown
Contributor Author

Omikhleia raises a fair point about HTML-dependency in the spec. A possible approach: lead with semantic description, then mention HTML as an example output.

For instance, instead of:

A table caption produces a <caption> element inside the table

Consider:

A caption provides a title or description for the preceding element. For tables, the caption is associated with the table itself. When rendered to HTML, this becomes a <caption> element.

This keeps the spec useful for HTML users while being output-agnostic in principle. The semantic meaning ("provides a title/description", "is associated with") comes first; the HTML rendering is presented as one possible output, not the definition.

Same pattern could apply to figures:

An image with a caption becomes a figure - a self-contained unit with its caption. When rendered to HTML, this uses <figure> and <figcaption> elements.

This way non-technical readers understand what it does, and technical readers know how it renders.

Lead with semantic descriptions ('provides a title or description',
'is associated with', 'becomes a figure'), then mention HTML rendering
as an example output. This addresses the concern about HTML-dependency
in the spec.
@Omikhleia

Omikhleia commented Feb 6, 2026

Copy link
Copy Markdown

This being said, I personally like the proposal. So it has two reference implementations

  • As stated here, in djot-php
  • Also in my modified version of the djot-lua for SILE (which does more than images and blockquotes, see question below)

A third independent implementation would be nice -- typically, for instance, the djot-hs parser (unless mistaken) used by Pandoc, i.e. with respect to the intermediary AST used in that software.

On that topic, regarding:

![Sunset over the ocean](sunset.jpg)
^ A beautiful sunset captured at the beach

It seems to me that the most logical way would to use a Figure element (as generated e.g. when the implicit_figure extension is enabled in Pandoc-style markdown). I am less sure for the blockquote case, but it's probably applicable too (?)

Extra question: why on images and block quotes only, and not generalized to code blocks and divs?

@dereuromark

Copy link
Copy Markdown
Contributor Author

Extra question: why on images and block quotes only, and not generalized to code blocks and divs?

95% use case I would say. You gotto stop somewhere.
Code blocks could maybe still be somewhat relevant, but generic divs as a whole seem out of scope (too generic).

@dereuromark

Copy link
Copy Markdown
Contributor Author

@jgm This is an important addition to fulfill the gap closing on captions.

@dereuromark

Copy link
Copy Markdown
Contributor Author

In hindsight I would actually rather propose footer syntax here for blockquotes.
A figure is a numbered thing. A quotation is not. Making a captioned quote a figure means
the quote enters the figure counter and the cross-reference table.

Cleaner might be:

> To be or not to be.
^ William Shakespeare, Hamlet
<blockquote>
  <p>To be or not to be.</p>
  <footer>William Shakespeare, Hamlet</footer>
</blockquote>

Both spellings are valid HTML; <figure> may legally wrap a quotation and <footer> inside
<blockquote> is the attribution idiom. The argument is about the model: figure was
doing two jobs, the generic AST wrapper for any captioned block and the semantic notion
"figure", and the second job is wrong for a quote.

If a document genuinely wants a quotation numbered as a figure, it says so explicitly once a
::: div is a captionable host:

::: figure
> To be or not to be.
:::
^ Figure #: A pull quote

Carve implementation going this way now I think directly.
The other elements, incl images, are all fine as figure IMO.

@clarfonthey

clarfonthey commented Aug 14, 2026

Copy link
Copy Markdown

A figure is a numbered thing. A quotation is not.

This is not how HTML <figure> is defined. The HTML standard itself even directly includes an example on the page for <blockquote> on using a <figure> for captioning it: https://html.spec.whatwg.org/multipage/grouping-content.html#the-blockquote-element

Note that in the context of numbered figures, the caption is what provides that. Otherwise, figures are just a generic way to caption content.

@dereuromark

Copy link
Copy Markdown
Contributor Author

OK fair, then the current proposal as above and as implemented in the PHP version stands as is.
Would be nice if this would be getting some traction, so the consistency of having them working across all relevant types is there. Right now it's a bit chaotic and not so nice for users (outside of the PHP library^^)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants