@peaceroad/markdown-it-figure-with-p-caption 0.19.0 → 0.20.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,571 @@
1
+ # Complete conversion and option examples
2
+
3
+ This document contains the exhaustive input/output and option examples for
4
+ `@peaceroad/markdown-it-figure-with-p-caption`. For installation and
5
+ representative examples, start with the [project README](../README.md). For
6
+ behavioral contracts, see the [behavior and options reference](reference.md).
7
+ Numbering-specific examples and contracts are documented in
8
+ [Automatic numbering and integration API](numbering.md).
9
+
10
+ Complete pairs whose fence info includes `{test id="..."}` are rendered and
11
+ compared exactly by `npm run test:docs`. A Markdown fence may also select one
12
+ of the test runner's fixed, non-evaluated `setup` names. Abbreviated examples
13
+ containing `...` remain illustrative and intentionally omit the test metadata.
14
+
15
+ ## Contents
16
+
17
+ - [Conversion examples](#conversion-examples)
18
+ - [Default before/after caption detection](#default-beforeafter-caption-paragraph-detection)
19
+ - [Auto alt/title detection](#auto-alttitle-detection)
20
+ - [Multiple images](#multiple-images)
21
+ - [Option examples](#option-examples)
22
+ - [Styles](#styles)
23
+ - [Automatic detection fallbacks](#automatic-detection-fallbacks)
24
+ - [Role helpers](#role-helpers)
25
+ - [Captionless conversion toggles](#captionless-conversion-toggles)
26
+ - [Current social embed structures](#current-social-embed-structures)
27
+ - [Iframe-type blockquote class override](#iframe-type-blockquote-class-override)
28
+ - [All iframe/embed class override](#all-iframeembed-class-override)
29
+ - [Caption markers](#caption-markers)
30
+
31
+ ## Conversion Examples
32
+
33
+ ### Default before/after caption paragraph detection
34
+
35
+ ~~~
36
+ [Markdown]
37
+ ![A single cat](figure.jpg)
38
+
39
+ [HTML]
40
+ <p><img src="figure.jpg" alt="A single cat"></p>
41
+
42
+ <!-- Above: If imageOnlyParagraphWithoutCaption (or its legacy alias oneImageWithoutCaption) is true, this img element has wrapped into figure element without caption. -->
43
+
44
+
45
+ [Markdown]
46
+ Figure. A Caption.
47
+
48
+ ![A single cat](figure.jpg)
49
+ [HTML]
50
+ <figure class="f-img">
51
+ <figcaption><span class="f-img-label">Figure<span class="f-img-label-joint">.</span></span> A Caption.</figcaption>
52
+ <img src="figure.jpg" alt="A single cat">
53
+ </figure>
54
+
55
+
56
+ [Markdown]
57
+ ![A single cat](figure.jpg)
58
+
59
+ Figure. A Caption.
60
+ [HTML]
61
+ <figure class="f-img">
62
+ <img src="figure.jpg" alt="A single cat">
63
+ <figcaption><span class="f-img-label">Figure<span class="f-img-label-joint">.</span></span> A Caption.</figcaption>
64
+ </figure>
65
+
66
+
67
+ [Markdown]
68
+ Table. A Caption.
69
+
70
+ | Tokyo | Osaka |
71
+ | ----- | ----- |
72
+ | Sushi | Takoyaki |
73
+
74
+ [HTML]
75
+ <figure class="f-table">
76
+ <figcaption><span class="f-table-label">Table<span class="f-table-label-joint">.</span></span> A Caption.</figcaption>
77
+ <table>
78
+ <thead>
79
+ <tr>
80
+ <th>Tokyo</th>
81
+ <th>Osaka</th>
82
+ </tr>
83
+ </thead>
84
+ <tbody>
85
+ <tr>
86
+ <td>Sushi</td>
87
+ <td>Takoyaki</td>
88
+ </tr>
89
+ </tbody>
90
+ </table>
91
+ </figure>
92
+
93
+
94
+ [Markdown]
95
+ Code. A Caption.
96
+
97
+ ```js
98
+ console.log('Hello World!');
99
+ ```
100
+
101
+ [HTML]
102
+ <figure class="f-pre-code">
103
+ <figcaption><span class="f-pre-code-label">Code<span class="f-pre-code-label-joint">.</span></span> A Caption.</figcaption>
104
+ <pre><code class="language-js">console.log('Hello World!');
105
+ </code></pre>
106
+ </figure>
107
+
108
+ <!-- Above: class attribute of code element is generated by markdown-it option. -->
109
+
110
+
111
+ [Markdown]
112
+ Source. A Caption.
113
+
114
+ > A quoted paragraph.
115
+
116
+ [HTML]
117
+ <figure class="f-blockquote">
118
+ <figcaption><span class="f-blockquote-label">Source<span class="f-blockquote-label-joint">.</span></span> A Caption.</figcaption>
119
+ <blockquote>
120
+ <p>A quoted paragraph.</p>
121
+ </blockquote>
122
+ </figure>
123
+
124
+
125
+ [Markdown]
126
+ Terminal. A Caption.
127
+
128
+ ```samp
129
+ $ pwd
130
+ /home/user
131
+ ```
132
+
133
+ [HTML]
134
+ <figure class="f-pre-samp">
135
+ <figcaption><span class="f-pre-samp-label">Terminal<span class="f-pre-samp-label-joint">.</span></span> A Caption.</figcaption>
136
+ <pre><samp>$ pwd
137
+ /home/user
138
+ </samp></pre>
139
+ </figure>
140
+
141
+ <!-- Above: When @peaceroad/markdown-it-renderer-fence is used, a samp element is generated automatically for `samp` fences. -->
142
+
143
+ [Markdown]
144
+ Video. An MP4 video.
145
+
146
+ <video controls width="400" height="300">
147
+ <source src="example.mp4" type="video/mp4">
148
+ </video>
149
+
150
+ [HTML]
151
+ <figure class="f-video">
152
+ <figcaption><span class="f-video-label">Video<span class="f-video-label-joint">.</span></span> An MP4 video.</figcaption>
153
+ <video controls width="400" height="300">
154
+ <source src="example.mp4" type="video/mp4">
155
+ </video>
156
+ </figure>
157
+
158
+
159
+ [Markdown]
160
+ Audio. A narration.
161
+
162
+ <audio controls>
163
+ <source src="example.mp3" type="audio/mpeg">
164
+ </audio>
165
+
166
+ [HTML]
167
+ <figure class="f-audio">
168
+ <figcaption><span class="f-audio-label">Audio<span class="f-audio-label-joint">.</span></span> A narration.</figcaption>
169
+ <audio controls>
170
+ <source src="example.mp3" type="audio/mpeg">
171
+ </audio>
172
+ </figure>
173
+
174
+
175
+ [Markdown]
176
+ Video. A YouTube video.
177
+
178
+ <iframe width="560" height="315" src="https://www.youtube-nocookie.com/embed/XXXXXXXXXXX" ...></iframe>
179
+
180
+ [HTML]
181
+ <figure class="f-video">
182
+ <figcaption><span class="f-video-label">Video<span class="f-video-label-joint">.</span></span> A YouTube video.</figcaption>
183
+ <iframe width="560" height="315" src="https://www.youtube-nocookie.com/embed/XXXXXXXXXXX" ...></iframe>
184
+ </figure>
185
+
186
+
187
+ [Markdown]
188
+ Figure. Mastodon post.
189
+
190
+ <blockquote class="mastodon-embed" ...> ...... </blockquote><script async src="https://example.com/embed.js"></script>
191
+
192
+ [HTML]
193
+ <figure class="f-img">
194
+ <figcaption><span class="f-img-label">Figure<span class="f-img-label-joint">.</span></span> Mastodon post.</figcaption>
195
+ <blockquote class="mastodon-embed" ...> ...... </blockquote><script async src="https://example.com/embed.js"></script>
196
+ </figure>
197
+
198
+
199
+ [Markdown]
200
+ Quote. Mastodon post.
201
+
202
+ <blockquote class="mastodon-embed" ...> ...... </blockquote><script async src="https://example.com/embed.js"></script>
203
+
204
+ [HTML]
205
+ <figure class="f-img">
206
+ <figcaption><span class="f-blockquote-label">Quote<span class="f-blockquote-label-joint">.</span></span> Mastodon post.</figcaption>
207
+ <blockquote class="mastodon-embed" ...> ...... </blockquote><script async src="https://example.com/embed.js"></script>
208
+ </figure>
209
+
210
+
211
+ [Markdown]
212
+ Slide. A Speaker Deck.
213
+
214
+ <iframe src="https://speakerdeck.com/player/XXXXXXXXXXX" width="640" height="360" frameborder="0" allowfullscreen></iframe>
215
+
216
+ [HTML]
217
+ <figure class="f-slide">
218
+ <figcaption><span class="f-slide-label">Slide<span class="f-slide-label-joint">.</span></span> A Speaker Deck.</figcaption>
219
+ <iframe src="https://speakerdeck.com/player/XXXXXXXXXXX" width="640" height="360" frameborder="0" allowfullscreen></iframe>
220
+ </figure>
221
+ ~~~
222
+
223
+ ### Auto alt/title detection
224
+
225
+ The consumed `alt` or `title` value is cleared only after the image paragraph is confirmed to be wrappable. Tight-list images and image paragraphs with trailing non-image text keep their original accessibility attributes and baseline rendering.
226
+
227
+ ```md {test id="docs-auto-caption-alt"}
228
+ ![Figure. A cat.](cat.jpg)
229
+ ```
230
+
231
+ ```html {test id="docs-auto-caption-alt"}
232
+ <figure class="f-img">
233
+ <figcaption><span class="f-img-label">Figure<span class="f-img-label-joint">.</span></span> A cat.</figcaption>
234
+ <img src="cat.jpg" alt="">
235
+ </figure>
236
+ ```
237
+
238
+ ```md {test id="docs-auto-caption-title"}
239
+ ![A white cat eats fish.](cat.jpg "Figure. A cat.")
240
+ ```
241
+
242
+ ```html {test id="docs-auto-caption-title"}
243
+ <figure class="f-img">
244
+ <figcaption><span class="f-img-label">Figure<span class="f-img-label-joint">.</span></span> A cat.</figcaption>
245
+ <img src="cat.jpg" alt="A white cat eats fish.">
246
+ </figure>
247
+ ```
248
+
249
+ ### Multiple images
250
+
251
+ ```md {test id="docs-multiple-images-horizontal"}
252
+ A paragraph. multipleImages: true. horizontal images only.
253
+
254
+ ![Sitting cat](cat1.jpg) ![Standing cat](cat2.jpg)
255
+
256
+ Figure. Cats.
257
+
258
+ A paragraph.
259
+ ```
260
+
261
+ ```html {test id="docs-multiple-images-horizontal"}
262
+ <p>A paragraph. multipleImages: true. horizontal images only.</p>
263
+ <figure class="f-img-horizontal">
264
+ <img src="cat1.jpg" alt="Sitting cat"><img src="cat2.jpg" alt="Standing cat">
265
+ <figcaption><span class="f-img-label">Figure<span class="f-img-label-joint">.</span></span> Cats.</figcaption>
266
+ </figure>
267
+ <p>A paragraph.</p>
268
+ ```
269
+
270
+ ```md {test id="docs-multiple-images-vertical"}
271
+ A paragraph. multipleImages: true. vertical images only.
272
+
273
+ Figure. Cats.
274
+
275
+ ![Sitting cat](cat1.jpg)
276
+ ![Standing cat](cat2.jpg)
277
+
278
+ A paragraph.
279
+ ```
280
+
281
+ ```html {test id="docs-multiple-images-vertical"}
282
+ <p>A paragraph. multipleImages: true. vertical images only.</p>
283
+ <figure class="f-img-vertical">
284
+ <figcaption><span class="f-img-label">Figure<span class="f-img-label-joint">.</span></span> Cats.</figcaption>
285
+ <img src="cat1.jpg" alt="Sitting cat">
286
+ <img src="cat2.jpg" alt="Standing cat">
287
+ </figure>
288
+ <p>A paragraph.</p>
289
+ ```
290
+
291
+ ```md {test id="docs-multiple-images-mixed"}
292
+ A paragraph. multipleImages: true.
293
+
294
+ Figure. Cats.
295
+
296
+ ![Sitting cat](cat1.jpg) ![Standing cat](cat2.jpg)
297
+ ![Sleeping cat](cat3.jpg)
298
+
299
+ A paragraph.
300
+ ```
301
+
302
+ ```html {test id="docs-multiple-images-mixed"}
303
+ <p>A paragraph. multipleImages: true.</p>
304
+ <figure class="f-img-multiple">
305
+ <figcaption><span class="f-img-label">Figure<span class="f-img-label-joint">.</span></span> Cats.</figcaption>
306
+ <img src="cat1.jpg" alt="Sitting cat"><img src="cat2.jpg" alt="Standing cat">
307
+ <img src="cat3.jpg" alt="Sleeping cat">
308
+ </figure>
309
+ <p>A paragraph.</p>
310
+ ```
311
+
312
+ ## Option Examples
313
+
314
+ ### Styles
315
+
316
+ This example uses `classPrefix: 'custom'` and leaves `styleProcess: true` so a trailing `{.notice}` block moves onto the `<figure>` wrapper. This fallback only handles the final trailing attrs block on an image-only paragraph; it supports quoted values with spaces, but for broader attrs syntax support, keep using `markdown-it-attrs`.
317
+
318
+ ```md {test id="docs-custom-style" setup="custom-style"}
319
+ Figure. Highlighted cat.
320
+
321
+ ![Highlighted cat](cat.jpg) {.notice}
322
+ ```
323
+
324
+ ```html {test id="docs-custom-style"}
325
+ <figure class="custom-img notice">
326
+ <figcaption><span class="custom-img-label">Figure<span class="custom-img-label-joint">.</span></span> Highlighted cat.</figcaption>
327
+ <img src="cat.jpg" alt="Highlighted cat">
328
+ </figure>
329
+ ```
330
+
331
+ ### Automatic detection fallbacks
332
+
333
+ `autoCaptionDetection` combined with `autoAltCaption` / `autoTitleCaption` can still generate caption text even when the original alt/title lacks labels, as long as the alt/title body is non-empty. The corresponding attributes are cleared after conversion so the figcaption becomes the canonical source. When these fallbacks are `true`, the generated label text and punctuation come from `p7d-markdown-it-p-captions` locale metadata rather than a local hardcoded map. When these fallbacks are strings, the string must be a label stem recognized as an image caption label by `p7d-markdown-it-p-captions`; invalid strings fail during plugin setup instead of producing a stray paragraph.
334
+
335
+ The first example assumes `autoAltCaption: true`; the second assumes
336
+ `autoTitleCaption: true`.
337
+
338
+ ```md {test id="docs-auto-alt-fallback" setup="auto-alt"}
339
+ ![Alt fallback example](bird.jpg)
340
+ ```
341
+
342
+ ```html {test id="docs-auto-alt-fallback"}
343
+ <figure class="f-img">
344
+ <figcaption><span class="f-img-label">Figure<span class="f-img-label-joint">.</span></span> Alt fallback example</figcaption>
345
+ <img src="bird.jpg" alt="">
346
+ </figure>
347
+ ```
348
+
349
+ ```md {test id="docs-auto-title-fallback" setup="auto-title"}
350
+ ![No caption](fish.jpg "Plain title text")
351
+ ```
352
+
353
+ ```html {test id="docs-auto-title-fallback"}
354
+ <figure class="f-img">
355
+ <figcaption><span class="f-img-label">Figure<span class="f-img-label-joint">.</span></span> Plain title text</figcaption>
356
+ <img src="fish.jpg" alt="No caption">
357
+ </figure>
358
+ ```
359
+
360
+ ### Role helpers
361
+
362
+ Set `roleDocExample: true` to add `role="doc-example"` to code/samp figures.
363
+ This option decorates an eligible figure; it does not wrap a captionless fence
364
+ by itself.
365
+
366
+ ~~~md {test id="docs-role-doc-example" setup="role-doc-example"}
367
+ Terminal. Current directory.
368
+
369
+ ```samp
370
+ $ pwd
371
+ /home/user
372
+ ```
373
+ ~~~
374
+
375
+ ```html {test id="docs-role-doc-example"}
376
+ <figure class="f-pre-samp" role="doc-example">
377
+ <figcaption><span class="f-pre-samp-label">Terminal<span class="f-pre-samp-label-joint">.</span></span> Current directory.</figcaption>
378
+ <pre><samp>$ pwd
379
+ /home/user
380
+ </samp></pre>
381
+ </figure>
382
+ ```
383
+
384
+ ### Captionless conversion toggles
385
+
386
+ If `imageOnlyParagraphWithoutCaption` (or the legacy alias `oneImageWithoutCaption`) is enabled, a single image paragraph will be wrapped with `<figure class="f-img">` even without a caption. Multi-image image-only paragraphs can also be wrapped, in which case the normal layout classes such as `f-img-horizontal`, `f-img-vertical`, or `f-img-multiple` are used.
387
+
388
+ ```md {test id="docs-captionless-image" setup="captionless-image"}
389
+ ![A single cat](cat.jpg)
390
+ ```
391
+
392
+ ```html {test id="docs-captionless-image"}
393
+ <figure class="f-img">
394
+ <img src="cat.jpg" alt="A single cat">
395
+ </figure>
396
+ ```
397
+
398
+ If `videoWithoutCaption` is enabled, `<video>` elements and iframes pointing to known video hosts (such as `www.youtube.com`, `youtube.com`, `www.youtube-nocookie.com`, or Vimeo) will be wrapped with `<figure class="f-video">`.
399
+
400
+ ```md {test id="docs-captionless-video-iframe" setup="captionless-video"}
401
+ <iframe width="560" height="315" src="https://www.youtube-nocookie.com/embed/XXXXXXXXXXX"></iframe>
402
+ ```
403
+
404
+ ```html {test id="docs-captionless-video-iframe"}
405
+ <figure class="f-video">
406
+ <iframe width="560" height="315" src="https://www.youtube-nocookie.com/embed/XXXXXXXXXXX"></iframe>
407
+ </figure>
408
+ ```
409
+
410
+ ```md {test id="docs-captionless-video" setup="captionless-video"}
411
+ <video controls width="400" height="300">
412
+ <source src="example.mp4" type="video/mp4">
413
+ </video>
414
+ ```
415
+
416
+ ```html {test id="docs-captionless-video"}
417
+ <figure class="f-video">
418
+ <video controls width="400" height="300">
419
+ <source src="example.mp4" type="video/mp4">
420
+ </video>
421
+ </figure>
422
+ ```
423
+
424
+ When `iframeWithoutCaption` is enabled, generic iframe HTML blocks are wrapped
425
+ with `<figure class="f-iframe">`. It also permits captionless wrapping of known
426
+ video iframes, which retain `<figure class="f-video">`. `videoWithoutCaption`
427
+ permits captionless `<video>` blocks and known video iframes without enabling
428
+ generic iframes. If `iframeTypeBlockquoteWithoutCaption` is enabled, recognized
429
+ blockquote-based embeds (for example, X) are wrapped with
430
+ `<figure class="f-img">` or another configured class.
431
+
432
+ ```md {test id="docs-captionless-iframe" setup="captionless-iframe"}
433
+ <iframe src="https://example.com/embed"></iframe>
434
+ ```
435
+
436
+ ```html {test id="docs-captionless-iframe"}
437
+ <figure class="f-iframe">
438
+ <iframe src="https://example.com/embed"></iframe>
439
+ </figure>
440
+ ```
441
+
442
+ #### Current social embed structures
443
+
444
+ Social embed detection uses the exact class token on the opening `blockquote`.
445
+ Additional `data-*` attributes, inline styles, SVG content, and current script
446
+ hosts are preserved. The following compact examples exercise the same
447
+ structures as the longer provider-generated snippets.
448
+
449
+ ```md {test id="docs-modern-mastodon" setup="captionless-social"}
450
+ <blockquote class="mastodon-embed" data-embed-url="https://mastodon.social/@Mastodon/1/embed" style="background: #FCF8FF"><a href="https://mastodon.social/@Mastodon/1"><svg viewBox="0 0 79 75"><path d="M0 0"/></svg><span>View on Mastodon</span></a></blockquote> <script data-allowed-prefixes="https://mastodon.social/" async src="https://mastodon.social/embed.js"></script>
451
+ ```
452
+
453
+ ```html {test id="docs-modern-mastodon"}
454
+ <figure class="f-img">
455
+ <blockquote class="mastodon-embed" data-embed-url="https://mastodon.social/@Mastodon/1/embed" style="background: #FCF8FF"><a href="https://mastodon.social/@Mastodon/1"><svg viewBox="0 0 79 75"><path d="M0 0"/></svg><span>View on Mastodon</span></a></blockquote> <script data-allowed-prefixes="https://mastodon.social/" async src="https://mastodon.social/embed.js"></script>
456
+ </figure>
457
+ ```
458
+
459
+ ```md {test id="docs-modern-threads" setup="captionless-social"}
460
+ <blockquote class="text-post-media" data-text-post-permalink="https://www.threads.com/@threads/post/1" data-text-post-version="0" id="ig-tp-1"><a href="https://www.threads.com/@threads/post/1"><svg aria-label="Threads" viewBox="0 0 192 192"><path d="M0 0"/></svg><span>Threadsで見る</span></a></blockquote>
461
+ <script async src="https://www.threads.com/embed.js"></script>
462
+ ```
463
+
464
+ ```html {test id="docs-modern-threads"}
465
+ <figure class="f-img">
466
+ <blockquote class="text-post-media" data-text-post-permalink="https://www.threads.com/@threads/post/1" data-text-post-version="0" id="ig-tp-1"><a href="https://www.threads.com/@threads/post/1"><svg aria-label="Threads" viewBox="0 0 192 192"><path d="M0 0"/></svg><span>Threadsで見る</span></a></blockquote>
467
+ <script async src="https://www.threads.com/embed.js"></script>
468
+ </figure>
469
+ ```
470
+
471
+ ```md {test id="docs-modern-x" setup="captionless-social"}
472
+ <blockquote class="twitter-tweet" data-dnt="true"><p lang="en" dir="ltr">A post</p>&mdash; X (@X)</blockquote> <script async src="https://platform.x.com/widgets.js" charset="utf-8"></script>
473
+ ```
474
+
475
+ ```html {test id="docs-modern-x"}
476
+ <figure class="f-img">
477
+ <blockquote class="twitter-tweet" data-dnt="true"><p lang="en" dir="ltr">A post</p>&mdash; X (@X)</blockquote> <script async src="https://platform.x.com/widgets.js" charset="utf-8"></script>
478
+ </figure>
479
+ ```
480
+
481
+ ```md {test id="docs-modern-bluesky" setup="captionless-social"}
482
+ <blockquote class="bluesky-embed" data-bluesky-uri="at://did:plc:example/app.bsky.feed.post/1" data-bluesky-cid="cid" data-bluesky-embed-color-mode="system"><p lang="en">First line
483
+
484
+ Second line</p>&mdash; Bluesky</blockquote><script async src="https://embed.bsky.app/static/embed.js" charset="utf-8"></script>
485
+ ```
486
+
487
+ ```html {test id="docs-modern-bluesky"}
488
+ <figure class="f-img">
489
+ <blockquote class="bluesky-embed" data-bluesky-uri="at://did:plc:example/app.bsky.feed.post/1" data-bluesky-cid="cid" data-bluesky-embed-color-mode="system"><p lang="en">First line
490
+
491
+ Second line</p>&mdash; Bluesky</blockquote><script async src="https://embed.bsky.app/static/embed.js" charset="utf-8"></script>
492
+ </figure>
493
+ ```
494
+
495
+ ### Iframe-type blockquote class override
496
+
497
+ Set `figureClassThatWrapsIframeTypeBlockquote: 'f-social'` (or any class you prefer) to wrap blockquote-based embeds (for example, X, Mastodon, Bluesky) with that class.
498
+
499
+ ```md {test id="docs-social-class" setup="social-class"}
500
+ Figure. Twitter embed.
501
+
502
+ <blockquote class="twitter-tweet"><p>Embed content</p></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
503
+ ```
504
+
505
+ ```html {test id="docs-social-class"}
506
+ <figure class="f-social">
507
+ <figcaption><span class="f-img-label">Figure<span class="f-img-label-joint">.</span></span> Twitter embed.</figcaption>
508
+ <blockquote class="twitter-tweet"><p>Embed content</p></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
509
+ </figure>
510
+ ```
511
+
512
+ ### All iframe/embed class override
513
+
514
+ Set `allIframeTypeFigureClassName: 'f-embed'` (or any class you prefer) to consolidate iframe-like embeds under one class.
515
+
516
+ ```md {test id="docs-all-iframe-class" setup="all-iframe-class"}
517
+ Video. Custom embed.
518
+
519
+ <iframe width="560" height="315" src="https://example.com/embed/123" title="Custom embed" frameborder="0" allowfullscreen></iframe>
520
+ ```
521
+
522
+ ```html {test id="docs-all-iframe-class"}
523
+ <figure class="f-embed">
524
+ <figcaption><span class="f-video-label">Video<span class="f-video-label-joint">.</span></span> Custom embed.</figcaption>
525
+ <iframe width="560" height="315" src="https://example.com/embed/123" title="Custom embed" frameborder="0" allowfullscreen></iframe>
526
+ </figure>
527
+ ```
528
+
529
+ Need matching caption classes too? Use `labelClassFollowsFigure` (and optionally `figureToLabelClassMap`) so the `figcaption` spans inherit the embed class you just applied (e.g., `f-embed-label`, `f-embed-label-joint`). If `figureToLabelClassMap` is provided, figure-following mode is enabled automatically unless `labelClassFollowsFigure` is set explicitly.
530
+
531
+
532
+ ### Caption markers
533
+
534
+ - `allowLabelPrefixMarkerWithoutLabel`: when `true`, marker-only paragraphs (e.g., `▼Caption`) are treated as captions without labels. If `labelPrefixMarker` is an array, the first entry is used for the previous caption and the second for the next caption. The marker is stripped from output.
535
+
536
+ ```js
537
+ const figureOption = {
538
+ labelPrefixMarker: ['▼', '▲'],
539
+ allowLabelPrefixMarkerWithoutLabel: true,
540
+ }
541
+
542
+ const md = mdit({ html: true }).use(mditFigureWithPCaption, figureOption)
543
+ ```
544
+
545
+ The first marker applies to captions before the figure, the second to captions after it.
546
+
547
+ ```md {test id="docs-caption-marker-before" setup="caption-markers"}
548
+ ▼Caption
549
+
550
+ ![Cat](cat.jpg)
551
+ ```
552
+
553
+ ```html {test id="docs-caption-marker-before"}
554
+ <figure class="f-img">
555
+ <figcaption>Caption</figcaption>
556
+ <img src="cat.jpg" alt="Cat">
557
+ </figure>
558
+ ```
559
+
560
+ ```md {test id="docs-caption-marker-after" setup="caption-markers"}
561
+ ![Cat](cat.jpg)
562
+
563
+ ▲Caption
564
+ ```
565
+
566
+ ```html {test id="docs-caption-marker-after"}
567
+ <figure class="f-img">
568
+ <img src="cat.jpg" alt="Cat">
569
+ <figcaption>Caption</figcaption>
570
+ </figure>
571
+ ```