@peaceroad/markdown-it-figure-with-p-caption 0.12.0 → 0.14.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.
package/README.md CHANGED
@@ -1,84 +1,204 @@
1
1
  # p7d-markdown-it-figure-with-p-caption
2
2
 
3
- This is a markdown-it plugin.
3
+ This markdown-it plugin converts paragraphs representing captions before or after image/table/code/video/audio/iframe into `figcaption` element, and wraps them in `figure` element. Caption parsing (labels, filenames, spacing rules) is delegated to [`p7d-markdown-it-p-captions`](https://www.npmjs.com/package/p7d-markdown-it-p-captions), so this plugin focuses on detecting the surrounding structure. Optionally, you have the option to wrap it in a `figure` element, even if there is no caption paragraph.
4
4
 
5
- For a paragraph with one image/images only, a table or code block or a blockquote or a iframe, and by writing a caption paragraph immediately before or after, they are converted into the figure element with the figcaption element.
5
+ For images, even if they don't have a caption paragraph, they can be treated as captions if they have a caption string in the image's `alt`/`title` text (there is also an option to promote them to captions even if they don't have that string).
6
6
 
7
- 1. Check that the element: one image only paragraph, table, code(samp) block, blockquote, and video, iframe.
8
- 2. Check if this element has a caption paragraph immediately before or after it
9
- 3. If there is the caption paragraph, convert them to figure and figcaption element.
7
+ Optionally, you can auto-number image and table caption paragraphs starting from the beginning of the document if they only have label names.
10
8
 
11
- The figcaption behavior of this plugin depends on [p7d-markdown-it-p-captions](https://www.npmjs.com/package/p7d-markdown-it-p-captions).
9
+ **Note.** If you want to adjust the image `width`/`height`, please also use [`@peaceroad/markdown-it-renderer-image`](https://www.npmjs.com/package/@peaceroad/markdown-it-renderer-image). Also, if you want to use the `samp` element when displaying terminal output, please also use [`@peaceroad/markdown-it-renderer-fence`](https://www.npmjs.com/package/@peaceroad/markdown-it-renderer-fence). This document shows output using the latter option.
12
10
 
13
- **Notice.** Starting with version 0.7, the process changing from code to samp tag has been migrated to [@peaceroad/markdown-it-renderer-fence](https://www.npmjs.com/package/@peaceroad/markdown-it-renderer-fence). If you want to continue processing as before, please use this plugin at the same time.
14
- (The tests for this plugin and this Readme output used the plugins together.)
11
+ ## Behavior
15
12
 
16
- **Notice.** You can also use `markdown-it-attrs` at the same time. However, if there is `{.style}` at the end of a paragraph with only an image, and the next paragraph is a caption, `markdown-it-attrs` alone does not handle it well, so this plugin takes care of that. (This processing is optional `{styleProcess: true}` and can be turned off.) [0.5.0]
13
+ ### Image
17
14
 
18
- Use it as follows.
15
+ - Pure image paragraphs (`![...](...)`) become `<figure class="f-img">` blocks as soon as a caption paragraph (previous or next) or an auto-detected caption exists.
16
+ - Auto detection runs per image paragraph when `autoCaptionDetection` is `true` (default). The priority is:
17
+ 1. Caption paragraphs immediately before or after the image (standard syntax).
18
+ 2. Image `alt` text that already matches p7d-markdown-it-p-captions label formats (`Figure. `, `Figure 1. `, `図 `,`図1 `, etc.).
19
+ 3. Image `title` attribute that matches the same labels.
20
+ 4. Optional fallbacks (`autoAltCaption`, `autoTitleCaption`) that inject the label when the alt/title lacks one.
21
+ - `autoAltCaption`: `false` (default), `true`, or a string label. `true` inspects the first sentence of the caption text and picks `Figure` / `図` based on detected language; a string uses that label verbatim.
22
+ - `autoTitleCaption`: same behavior but sourced from the image `title`. It stays off by default so other plugins can keep using the `title` attribute for metadata.
23
+ - Set `autoCaptionDetection: false` to disable the auto-caption workflow entirely.
24
+ - Multi-image paragraphs are still wrapped as one figure when `multipleImages: true` (default). Layout-specific classes help with styling:
25
+ - `f-img-horizontal` when images sit on the same line (space-delimited).
26
+ - `f-img-vertical` when separated only by soft breaks.
27
+ - `f-img-multiple` for mixed layouts.
28
+ - Automatic detection inspects only the first image in the paragraph. If it yields a caption, the entire figure reuses that caption while later images keep their own `alt`/`title`.
29
+ - Paragraphs that contain only images also convert when they appear inside loose lists (leave blank lines between items), blockquotes, or description lists.
30
+
31
+ ### Table
32
+
33
+ - Markdown tables (including those produced by `markdown-it-multimd-table` or similar) convert into `<figure class="f-table">` blocks.
34
+ - Caption paragraphs immediately before/after the table become `<figcaption>` element ahead of the `<table>`.
35
+
36
+ ### Code block
37
+
38
+ - Captions labeled `Code. `, `Terminal. `, etc. wrap the fence in `<figure class="f-pre-code">` / `<figure class="f-pre-samp">`.
39
+ - If `roleDocExample: true`, these figures add `role="doc-example"`.
40
+
41
+ ### Blockquote
42
+
43
+ - Captioned blockquotes (e.g., “Source. A paragraph. Ewritten immediately before or after `> ...`) become `<figure class="f-blockquote">` while keeping the original blockquote intact.
44
+
45
+ ### Video & Audio
46
+
47
+ - Inline HTML `<video>` and `<audio>` tags are detected as media figures (`<figure class="f-video">` and `<figure class="f-audio">`).
48
+ - A caption paragraph labeled `Video. ` / `Audio. ` (or any registered label) is promoted to `<figcaption>` before/after the media so controls remain unobstructed.
49
+
50
+ ### Embedded content by iframe
51
+
52
+ - Inline HTML `<iframe>` elements become `<figure class="f-video">` when they point to known video hosts (YouTube `youtube.com` / `youtube-nocookie.com`, Vimeo `player.vimeo.com`).
53
+ - Blockquote-based social embeds (Twitter/X `twitter-tweet`, Mastodon `mastodon-embed`, Bluesky `bluesky-embed`, Instagram `instagram-media`, Tumblr `text-post-media`) are treated like iframe-type embeds when their `class` matches those providers. By default they become `<figure class="f-img">` so the caption label behaves like an image label (Labels can also use quote labels). You can override that figure class with `figureClassThatWrapsIframeTypeBlockquote` or the global `allIframeTypeFigureClassName`.
54
+ - `p7d-markdown-it-p-captions` ships with a `Slide.` label. When you use it (for example with Speaker Deck or SlideShare iframes), the `<figure>` wrapper automatically switches to `f-slide` (or whatever you set via `figureClassThatWrapsSlides`) so slides can get their own layout. If `allIframeTypeFigureClassName` is also configured, that class takes precedence even for slides, so you get a uniform embed wrapper without touching the slide option.
55
+ - All other iframes fall back to `<figure class="f-iframe">` unless you override the class via `allIframeTypeFigureClassName`.
56
+
57
+ ### label span class name
58
+
59
+ - The label inside the figcaption (the `span` element used for the label) is generated by `p7d-markdown-it-p-captions`, not by this plugin. By default the class name is formed by combining `classPrefix` with the mark name, producing names such as `f-img-label`, `f-video-label`, `f-blockquote-label`, and `f-slide-label`.
60
+ - With `markdown-it-attrs`, any attribute block (`{ .foo #bar }`) attached to the caption paragraph is moved to the generated `<figure>` by default (`styleProcess: true`). This keeps per-figure classes/IDs on the wrapper instead of the original paragraph; disable the option only if you explicitly want the attributes to stay on the paragraph.
61
+
62
+ ## Behavior Customization
63
+
64
+ ### Styles
65
+
66
+ - Set `allIframeTypeFigureClassName: 'f-embed'` (recommended) to force a single CSS class across `<iframe>` and social-embed figures so they can share styles, ensuring every embed wrapper shares the same predictable class name.
67
+ - `figureClassThatWrapsIframeTypeBlockquote`: override the class used when blockquote-based embeds (Twitter, Mastodon, Bluesky) are wrapped.
68
+ - `figureClassThatWrapsSlides`: override the class assigned when a caption paragraph uses the `Slide.` label.
69
+ - `classPrefix` (default `f`) controls the CSS namespace for every figure (`f-img`, `f-table`, etc.) so you can align with existing styles.
70
+
71
+ ### Wrapping without captions
72
+
73
+ - `oneImageWithoutCaption`: turn single-image paragraphs into `<figure>` elements even when no caption paragraph/auto caption is present. This is independent of automatic detection.
74
+ - `videoWithoutCaption`, `audioWithoutCaption`, `iframeWithoutCaption`, `iframeTypeBlockquoteWithoutCaption`: wrap the respective media blocks without caption.
75
+
76
+ ### Caption text helpers (delegated to `p7d-markdown-it-p-captions`)
77
+
78
+ Every option below is forwarded verbatim to `p7d-markdown-it-p-captions`, which owns the actual figcaption rendering:
79
+
80
+ - `strongFilename` / `dquoteFilename`: pull out filenames from captions using `**filename**` or `"filename"` syntax and wrap them in `<strong class="f-*-filename">`.
81
+ - `jointSpaceUseHalfWidth`: replace full-width space between Japanese labels and caption body with half-width space.
82
+ - `bLabel` / `strongLabel`: emphasize the label span itself.
83
+ - `removeUnnumberedLabel`: drop the leading “Figure. Etext entirely when no label number is present. Use `removeUnnumberedLabelExceptMarks` to keep specific labels (e.g., `['blockquote']` keeps `Quote. `).
84
+ - `removeMarkNameInCaptionClass`: replace `.f-img-label` / `.f-table-label` with the generic `.f-label`.
85
+ - `wrapCaptionBody`: wrap the non-label caption text in a span element.
86
+ - `hasNumClass`: add a class attribute to label span element if it has a label number.
87
+ - `labelClassFollowsFigure`: mirror the resolved `<figure>` class onto the `figcaption` spans (`f-embed-label`, `f-embed-label-joint`, `f-embed-body`, etc.) when you want captions styled alongside the wrapper.
88
+ - `figureToLabelClassMap`: extend `labelClassFollowsFigure` by mapping specific figure classes (e.g., `f-embed`) to custom caption label classes such as `caption-embed caption-social` for fine-grained control.
89
+
90
+ ### Automatic numbering
91
+
92
+ - `setLabelNumbers`: enable numbering per media type. Pass an array such as `['img']`, `['table']`, or `['img', 'table']`.
93
+ - `autoLabelNumber`: shorthand for turning numbering on for both images and tables without passing the array yourself. Provide `setLabelNumbers` explicitly (e.g., `['img']`) when you need finer control—the explicit array always wins.
94
+ - Counters start at `1` near the top of the document and increment sequentially per media type. Figures and tables keep independent counters even when mixed together.
95
+ - The counter only advances when a real caption exists (paragraph, auto-detected alt/title, or fallback text). Figures emitted solely because of `oneImageWithoutCaption` stay unnumbered.
96
+ - Manual numbers inside the caption text (e.g., `Figure 5.`) always win. The plugin updates its internal counter so the next automatic number becomes `6`. This applies to captions sourced from paragraphs, auto detection, and fallback captions.
97
+
98
+ ## Basic Usage
19
99
 
20
100
  ```js
21
101
  import mdit from 'markdown-it'
22
102
  import mditFigureWithPCaption from '@peaceroad/markdown-it-figure-with-p-caption'
23
- import mditRendererFence from '@peaceroad/markdown-it-renderer-fence' /* to processing code -> smap tag etc. process.*/
103
+ import mditRendererFence from '@peaceroad/markdown-it-renderer-fence' // optional but keeps fences aligned with samples
24
104
 
25
- const md = mdit()
26
- md.use(mditFigureWithPCaption)
105
+ const md = mdit({ html: true, langPrefix: 'language-', })
106
+ .use(mditFigureWithPCaption)
107
+ .use(mditRendererFence)
27
108
 
28
- console.log(md.render('Figure. A Cat.\n\n![Figure](cat.jpg)'))
109
+ console.log(md.render('Figure. A Cat.\n\n![A cat](cat.jpg)'))
29
110
  // <figure class="f-img">
30
111
  // <figcaption><span class="f-img-label">Figure<span class="f-img-label-joint">.</span></span> A Cat.</figcaption>
31
- // <img src="cat.jpg" alt="Figure">
112
+ // <img src="cat.jpg" alt="A cat">
32
113
  // </figure>
33
114
  ```
34
115
 
35
- Also, It is recommended to set the width and height attributes of the images at the same time. See: [@peaceroad/markdown-it-renderer-image](https://www.npmjs.com/package/@peaceroad/markdown-it-renderer-image).
116
+ ### Basic Recommended Options
117
+
118
+ Auto label numbering for images and tables.
119
+
120
+ ```js
121
+ const figureOption = {
122
+ // Opinionated defaults
123
+ oneImageWithoutCaption: true,
124
+ videoWithoutCaption: true,
125
+ audioWithoutCaption: true,
126
+ iframeWithoutCaption: true,
127
+ iframeTypeBlockquoteWithoutCaption: true,
128
+ removeUnnumberedLabelExceptMarks: ['blockquote'], // keep “Quote. Elabels even when unnumbered
129
+ allIframeTypeFigureClassName: 'f-embed', // apply a uniform class to every iframe-style embed
130
+ autoLabelNumber: true,
131
+
132
+ // If you want to enable auto alt/title captioning fallbacks without caption label.
133
+ //autoAltCaption: true,
134
+ //autoTitleCaption: true,
135
+ }
136
+ ```
137
+
138
+ If there is no label number, the label will also be deleted.
139
+
140
+ ```js
141
+ const figureOption = {
142
+ oneImageWithoutCaption: true,
143
+ videoWithoutCaption: true,
144
+ audioWithoutCaption: true,
145
+ iframeWithoutCaption: true,
146
+ iframeTypeBlockquoteWithoutCaption: true,
147
+ removeUnnumberedLabelExceptMarks: ['blockquote'],
148
+ allIframeTypeFigureClassName: 'f-embed',
149
+ removeUnnumberedLabel: true,
150
+ }
151
+ ```
152
+
153
+ These options can be used as follows:
36
154
 
37
- It could be applied to table, codeblock(pre > code, pre > samp), video as well.
155
+ ```
156
+ const md = mdit({ html: true }).use(mditFigureWithPCaption, figureOption)
157
+ ```
38
158
 
159
+ ## Conversion Examples
39
160
 
40
- ## Example
161
+ ### Default before/after caption paragraph detection
41
162
 
42
163
  ~~~
43
164
  [Markdown]
44
- ![Figure](figure.jpg)
165
+ ![A single cat](figure.jpg)
45
166
 
46
167
  [HTML]
47
- <p><img src="figure.jpg" alt="Figure"></p>
168
+ <p><img src="figure.jpg" alt="A single cat"></p>
169
+
170
+ <!-- Above: If oneImageWithoutCaption is true, this img element has wrapped into figure element without caption. -->
48
171
 
49
172
 
50
173
  [Markdown]
51
174
  Figure. A Caption.
52
175
 
53
- ![Figure](figure.jpg)
176
+ ![A single cat](figure.jpg)
54
177
  [HTML]
55
178
  <figure class="f-img">
56
179
  <figcaption><span class="f-img-label">Figure<span class="f-img-label-joint">.</span></span> A Caption.</figcaption>
57
- <img src="figure.jpg" alt="Figure">
180
+ <img src="figure.jpg" alt="A single cat">
58
181
  </figure>
59
182
 
60
183
 
61
184
  [Markdown]
62
- ![Figure](figure.jpg)
185
+ ![A single cat](figure.jpg)
63
186
 
64
187
  Figure. A Caption.
65
188
  [HTML]
66
189
  <figure class="f-img">
67
- <img src="figure.jpg" alt="Figure">
190
+ <img src="figure.jpg" alt="A single cat">
68
191
  <figcaption><span class="f-img-label">Figure<span class="f-img-label-joint">.</span></span> A Caption.</figcaption>
69
192
  </figure>
70
193
 
71
194
 
72
195
  [Markdown]
73
- A paragraph.
74
-
75
196
  Table. A Caption.
76
197
 
77
198
  | Tokyo | Osaka |
78
199
  | ----- | ----- |
79
200
  | Sushi | Takoyaki |
80
201
 
81
- A paragraph.
82
202
  [HTML]
83
203
  <p>A paragraph.</p>
84
204
  <figure class="f-table">
@@ -98,53 +218,40 @@ A paragraph.
98
218
  </tbody>
99
219
  </table>
100
220
  </figure>
101
- <p>A paragraph.</p>
102
221
 
103
222
 
104
223
  [Markdown]
105
- A paragraph.
106
-
107
224
  Code. A Caption.
108
225
 
109
226
  ```js
110
227
  console.log('Hello World!');
111
228
  ```
112
229
 
113
- A paragraph.
114
-
115
230
  [HTML]
116
- <p>A paragraph.</p>
117
231
  <figure class="f-pre-code">
118
232
  <figcaption><span class="f-pre-code-label">Code<span class="f-pre-code-label-joint">.</span></span> A Caption.</figcaption>
119
233
  <pre><code class="language-js">console.log('Hello World!');
120
234
  </code></pre>
121
235
  </figure>
122
- <p>A paragraph.</p>
123
236
 
237
+ <!-- Above: class attribute of code element is generated by markdown-it option. -->
124
238
 
125
- [Markdown]
126
- A paragraph.
127
239
 
240
+ [Markdown]
128
241
  Source. A Caption.
129
242
 
130
243
  > A quoted paragraph.
131
244
 
132
- A paragraph.
133
-
134
245
  [HTML]
135
- <p>A paragraph.</p>
136
246
  <figure class="f-blockquote">
137
247
  <figcaption><span class="f-blockquote-label">Source<span class="f-blockquote-label-joint">.</span></span> A Caption.</figcaption>
138
248
  <blockquote>
139
249
  <p>A quoted paragraph.</p>
140
250
  </blockquote>
141
251
  </figure>
142
- <p>A paragraph.</p>
143
252
 
144
253
 
145
254
  [Markdown]
146
- A paragraph.
147
-
148
255
  Terminal. A Caption.
149
256
 
150
257
  ```samp
@@ -152,108 +259,126 @@ $ pwd
152
259
  /home/user
153
260
  ```
154
261
 
155
- A paragraph.
156
-
157
262
  [HTML]
158
- <p>A paragraph.</p>
159
263
  <figure class="f-pre-samp">
160
264
  <figcaption><span class="f-pre-samp-label">Terminal<span class="f-pre-samp-label-joint">.</span></span> A Caption.</figcaption>
161
265
  <pre><samp>$ pwd
162
266
  /home/user
163
267
  </samp></pre>
164
268
  </figure>
165
- <p>A paragraph.</p>
166
269
 
270
+ <!-- Above: When @peaceroad/markdown-it-renderer-fence is used, samp element are generated automatically for `samp` fences. -->
167
271
 
168
272
  [Markdown]
169
- A paragraph.
170
-
171
273
  Video. A mp4.
172
274
 
173
275
  <video controls width="400" height="300">
174
276
  <source src="example.mp4" type="video/mp4">
175
277
  </video>
176
278
 
177
- A paragraph.
178
279
  [HTML]
179
- <p>A paragraph.</p>
180
280
  <figure class="f-video">
181
281
  <figcaption><span class="f-video-label">Video<span class="f-video-label-joint">.</span></span> A mp4.</figcaption>
182
282
  <video controls width="400" height="300">
183
283
  <source src="example.mp4" type="video/mp4">
184
284
  </video>
185
285
  </figure>
186
- <p>A paragraph.</p>
187
286
 
188
287
 
189
288
  [Markdown]
190
- A paragraph.
191
-
192
- Video. A youtube.
289
+ Audio. A narration.
193
290
 
194
- <iframe width="560" height="315" src="https://www.youtube-nocookie.com/embed/XXXXXXXXXXX" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
291
+ <audio controls>
292
+ <source src="example.mp3" type="audio/mpeg">
293
+ </audio>
195
294
 
196
- A paragraph.
197
295
  [HTML]
198
- <p>A paragraph.</p>
199
- <figure class="f-video">
200
- <figcaption><span class="f-video-label">Video<span class="f-video-label-joint">.</span></span> A youtube.</figcaption>
201
- <iframe width="560" height="315" src="https://www.youtube-nocookie.com/embed/XXXXXXXXXXX" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
296
+ <figure class="f-audio">
297
+ <figcaption><span class="f-audio-label">Audio<span class="f-audio-label-joint">.</span></span> A narration.</figcaption>
298
+ <audio controls>
299
+ <source src="example.mp3" type="audio/mpeg">
300
+ </audio>
202
301
  </figure>
203
- <p>A paragraph.</p>
204
302
 
205
303
 
206
304
  [Markdown]
207
- A paragraph.
208
-
209
- Video. A youtube.
305
+ Video. A YouTube video.
210
306
 
211
- <iframe width="560" height="315" src="https://www.youtube-nocookie.com/embed/XXXXXXXXXXX" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
307
+ <iframe width="560" height="315" src="https://www.youtube-nocookie.com/embed/XXXXXXXXXXX" ...></iframe>
212
308
 
213
- A paragraph.
214
309
  [HTML]
215
- <p>A paragraph.</p>
216
310
  <figure class="f-video">
217
- <figcaption><span class="f-video-label">Video<span class="f-video-label-joint">.</span></span> A youtube.</figcaption>
218
- <iframe width="560" height="315" src="https://www.youtube-nocookie.com/embed/XXXXXXXXXXX" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
311
+ <figcaption><span class="f-video-label">Video<span class="f-video-label-joint">.</span></span> A YouTube video.</figcaption>
312
+ <iframe width="560" height="315" src="https://www.youtube-nocookie.com/embed/XXXXXXXXXXX" ...></iframe>
219
313
  </figure>
220
- <p>A paragraph.</p>
221
314
 
222
315
 
223
316
  [Markdown]
224
- A paragraph.
317
+ Figure. Mastodon post.
318
+
319
+ <blockquote class="mastodon-embed" ...> ...... </blockquote><script async src="https://example.com/embed.js"></script>
320
+
321
+ [HTML]
322
+ <figure class="f-img">
323
+ <figcaption><span class="f-img-label">Figure<span class="f-img-label-joint">.</span></span> Mastodon post.</figcaption>
324
+ <blockquote class="mastodon-embed" ...> ...... </blockquote><script async src="https://example.com/embed.js"></script>
325
+ </figure>
225
326
 
226
- Figure. Twitter Post.
227
327
 
228
- <blockquote class="twitter-tweet"><p lang="ja" dir="ltr">XXXXX <a href="https://t.co/XXXXX">https://t.co/XXXXX</a></p>&mdash; UserName (@account) <a href="https://twitter.com/account/status/XXXXX">August 4, 2022</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
328
+ [Markdown]
329
+ Quote. Mastodon post.
330
+
331
+ <blockquote class="mastodon-embed" ...> ...... </blockquote><script async src="https://example.com/embed.js"></script>
229
332
 
230
- A paragraph.
231
333
  [HTML]
232
- <p>A paragraph.</p>
233
334
  <figure class="f-img">
234
- <figcaption><span class="f-img-label">Figure<span class="f-img-label-joint">.</span></span> Twitter Post.</figcaption>
235
- <blockquote class="twitter-tweet"><p lang="ja" dir="ltr">XXXXX <a href="https://t.co/XXXXX">https://t.co/XXXXX</a></p>&mdash; User (@twitter) <a href="https://twitter.com/UserID/status/XXXXX">August 4, 2022</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
335
+ <figcaption><span class="f-blockquote-label">Quote<span class="f-blockquote-label-joint">.</span></span> X post.</figcaption>
336
+ <blockquote class="mastodon-embed" ...> ...... </blockquote><script async src="https://example.com/embed.js"></script>
236
337
  </figure>
237
- <p>A paragraph.</p>
238
338
 
339
+
340
+ [Markdown]
341
+ Slide. A Speaker Deck.
342
+
343
+ <iframe src="https://speakerdeck.com/player/XXXXXXXXXXX" width="640" height="360" frameborder="0" allowfullscreen></iframe>
344
+
345
+ [HTML]
346
+ <figure class="f-slide">
347
+ <figcaption><span class="f-slide-label">Slide<span class="f-slide-label-joint">.</span></span> A Speaker Deck.</figcaption>
348
+ <iframe src="https://speakerdeck.com/player/XXXXXXXXXXX" width="640" height="360" frameborder="0" allowfullscreen></iframe>
349
+ </figure>
239
350
  ~~~
240
351
 
241
- Note: External embedding supports Youtube and Twitter. Twitter embedding uses blockquote instead of iframe. Therefore, the caption identifier should use "Quote", but "Figure" is also acceptable.
352
+ ### Auto alt/title detection
242
353
 
354
+ ```
355
+ [Markdown]
356
+ ![Figure. A cat.](cat.jpg)
243
357
 
244
- From version 0.5.0, it supports cases where a paragraph contains only multiple images. Instead of `f-img` as the figure class name, use the following class name. (This class name is unstable, but I probably won't change it.)
358
+ [HTML]
359
+ <figure class="f-img">
360
+ <figcaption><span class="f-img-label">Figure<span class="f-img-label-joint">.</span></span> A cat.</figcaption>
361
+ <img src="cat.jpg" alt="">
362
+ </figure>
245
363
 
246
- - `f-img-horizontal` if the image is written in one line on Markdown
247
- - `f-img-vertical` if images are written only vertically, one per line
248
- - `f-img-multiple` in other cases
249
364
 
250
- Notice. This process can be turned off by specifying `{multipleImages: false}`.
365
+ [Markdown]
366
+ ![A white cat eats fishs.](cat.jpg "Figure. A cat.")
251
367
 
368
+ [HTML]
369
+ <figure class="f-img">
370
+ <figcaption><span class="f-img-label">Figure<span class="f-img-label-joint">.</span></span> A cat.</figcaption>
371
+ <img src="cat.jpg" alt="A white cat eats fishs.">
372
+ </figure>
252
373
  ```
374
+
375
+ ### Multiple images
376
+
377
+ ~~~
253
378
  [Markdown]
254
379
  A paragraph. multipleImages: true. horizontal images only.
255
380
 
256
- ![One cat](cat1.jpg) ![Two cat](cat2.jpg)
381
+ ![Sitting cat](cat1.jpg) ![Standing cat](cat2.jpg)
257
382
 
258
383
  Figure. Cats.
259
384
 
@@ -261,7 +386,7 @@ A paragraph.
261
386
  [HTML]
262
387
  <p>A paragraph. multipleImages: true. horizontal images only</p>
263
388
  <figure class="f-img-horizontal">
264
- <img src="cat1.jpg" alt="One cat"><img src="cat2.jpg" alt="Two cat">
389
+ <img src="cat1.jpg" alt="Sitting cat"><img src="cat2.jpg" alt="Standing cat">
265
390
  <figcaption><span class="f-img-label">Figure<span class="f-img-label-joint">.</span></span> Cats.</figcaption>
266
391
  </figure>
267
392
  <p>A paragraph.</p>
@@ -271,16 +396,16 @@ A paragraph. multipleImages: true. vertical images only.
271
396
 
272
397
  Figure. Cats.
273
398
 
274
- ![One cat](cat1.jpg)
275
- ![Two cat](cat2.jpg)
399
+ ![Sitting cat](cat1.jpg)
400
+ ![Standing cat](cat2.jpg)
276
401
 
277
402
  A paragraph.
278
403
  [HTML]
279
404
  <p>A paragraph. multipleImages: true. vertical images only.</p>
280
405
  <figure class="f-img-vertical">
281
406
  <figcaption><span class="f-img-label">Figure<span class="f-img-label-joint">.</span></span> Cats.</figcaption>
282
- <img src="cat1.jpg" alt="One cat">
283
- <img src="cat2.jpg" alt="Two cat">
407
+ <img src="cat1.jpg" alt="Sitting cat">
408
+ <img src="cat2.jpg" alt="Standing cat">
284
409
  </figure>
285
410
  <p>A paragraph.</p>
286
411
 
@@ -289,271 +414,166 @@ A paragraph. multipleImages: true.
289
414
 
290
415
  Figure. Cats.
291
416
 
292
- ![One cat](cat1.jpg) ![Two cat](cat2.jpg)
293
- ![Three cat](cat3.jpg)
417
+ ![Sitting cat](cat1.jpg) ![Standing cat](cat2.jpg)
418
+ ![Sleeping cat](cat3.jpg)
294
419
 
295
420
  A paragraph.
296
421
  [HTML]
297
422
  <p>A paragraph. multipleImages: true.</p>
298
423
  <figure class="f-img-multiple">
299
424
  <figcaption><span class="f-img-label">Figure<span class="f-img-label-joint">.</span></span> Cats.</figcaption>
300
- <img src="cat1.jpg" alt="One cat"><img src="cat2.jpg" alt="Two cat">
301
- <img src="cat3.jpg" alt="Three cat">
425
+ <img src="cat1.jpg" alt="Sitting cat"><img src="cat2.jpg" alt="Standing cat">
426
+ <img src="cat3.jpg" alt="Sleeping cat">
302
427
  </figure>
303
428
  <p>A paragraph.</p>
304
- ```
305
-
306
- ## Option: Specify file name
429
+ ~~~
307
430
 
308
- Specify the file name before writing the caption.
309
- Note that a space is required between the file name and caption.
431
+ ## Option Examples
310
432
 
311
- ### Use double quote
433
+ ### Styles
312
434
 
313
- ```js
435
+ This example uses `classPrefix: 'custom'` and leaves `styleProcess: true` so a trailing `{.notice}` block moves onto the `<figure>` wrapper.
314
436
 
315
- md.use(mditFigureWithPCaption, {dquoteFilename: true});
316
437
  ```
317
-
318
- ~~~
319
438
  [Markdown]
320
- A paragraph.
321
-
322
- Code. "filename.js" Call a cat.
323
-
324
- ```js
325
- console.log('Nyaan!');
326
- ```
327
-
328
- A paragraph.
439
+ Figure. Highlighted cat. {.notice}
329
440
 
441
+ ![Highlighted cat](cat.jpg)
330
442
  [HTML]
331
- <p>A paragraph.</p>
332
- <figure class="f-pre-code">
333
- <figcaption><span class="f-pre-code-label">Code<span class="f-pre-code-label-joint">.</span></span> <strong class="f-pre-code-filename">filename.js</strong> Call a cat.</figcaption>
334
- <pre><code class="language-js">console.log('Nyaan!');
335
- </code></pre>
443
+ <figure class="custom-img notice">
444
+ <figcaption><span class="custom-img-label">Figure<span class="custom-img-label-joint">.</span></span> Highlighted cat.</figcaption>
445
+ <img src="cat.jpg" alt="Highlighted cat">
336
446
  </figure>
337
- <p>A paragraph.</p>
338
- ~~~
339
-
340
- ### Use strong mark
341
-
342
- ```js
343
- md.use(mditFigureWithPCaption, {strongFilename: true});
344
447
  ```
345
448
 
346
- ~~~
449
+ ### Automatic detection fallbacks
347
450
 
348
- [Markdown]
349
- A paragraph.
451
+ `autoCaptionDetection` combined with `autoAltCaption` / `autoTitleCaption` can still generate caption text even when the original alt/title lacks labels. The corresponding attributes are cleared after conversion so the figcaption becomes the canonical source.
350
452
 
351
- Code. **filename.js** Call a cat.
352
-
353
- ```js
354
- console.log('Nyaan!');
355
453
  ```
356
-
357
- A paragraph.
454
+ [Markdown]
455
+ ![Alt fallback example](bird.jpg)
358
456
 
359
457
  [HTML]
360
- <p>A paragraph.</p>
361
- <figure class="f-pre-code">
362
- <figcaption><span class="f-pre-code-label">Code<span class="f-pre-code-label-joint">.</span></span> <strong class="f-pre-code-filename">filename.js</strong> Call a cat.</figcaption>
363
- <pre><code class="language-js">console.log('Nyaan!');
364
- </code></pre>
458
+ <figure class="f-img">
459
+ <figcaption><span class="f-img-label">Figure<span class="f-img-label-joint">.</span></span> Alt fallback example</figcaption>
460
+ <img src="bird.jpg" alt="">
365
461
  </figure>
366
- <p>A paragraph.</p>
367
- ~~~
368
-
369
- ## Option
370
-
371
- ### Convert one image paragraph without caption
372
462
 
373
- Convert one image paragraph without a caption paragraph to figure element.
374
463
 
375
- ```js
376
- md.use(mditFigureWithPCaption, {oneImageWithoutCaption: true});
377
- ```
378
-
379
- ~~~
380
464
  [Markdown]
381
- A paragraph.
382
-
383
- ![Figure](cat.jpg)
384
-
385
- A paragraph.
465
+ ![No caption](fish.jpg "Plain title text")
386
466
 
387
467
  [HTML]
388
- <p>A paragraph.</p>
389
468
  <figure class="f-img">
390
- <img src="cat.jpg" alt="Figure">
469
+ <figcaption><span class="f-img-label">Figure<span class="f-img-label-joint">.</span></span> Plain title text</figcaption>
470
+ <img src="fish.jpg" alt="No caption">
391
471
  </figure>
392
- <p>A paragraph.</p>
393
- ~~~
394
-
395
- ### Convert one video element without caption
396
-
397
- Convert one video element without a caption paragraph to figure element.
398
-
399
- ```js
400
- md.use(mditFigureWithPCaption, {videoWithoutCaption: true});
401
472
  ```
402
473
 
403
- #### Convert one iframe without caption
474
+ ### Role helpers
404
475
 
405
- Convert one iframe without a caption paragraph to iframe element. (adn twitter blockquote embed eelment.)
406
-
407
- ```js
408
- md.use(mditFigureWithPCaption, {iframeWithoutCaption: true});
409
- ```
476
+ Set `roleDocExample: true` to add `role="doc-example"` to code/samp figures.
410
477
 
411
478
  ~~~
412
479
  [Markdown]
413
- <iframe src="https://example.com/embed" class="mastodon-embed" style="max-width: 100%; border: 0" width="400" allowfullscreen="allowfullscreen"></iframe><script src="https://exapmle.com/embed.js" async="async"></script>
480
+ ```samp
481
+ $ pwd
482
+ /home/user
483
+ ```
484
+
414
485
  [HTML]
415
- <figure class="f-iframe">
416
- <iframe src="https://example.com/embed" class="mastodon-embed" style="max-width: 100%; border: 0" width="400" allowfullscreen="allowfullscreen"></iframe><script src="https://exapmle.com/embed.js" async="async"></script>
486
+ <figure class="f-pre-samp" role="doc-example">
487
+ ...
417
488
  </figure>
489
+ ~~~
418
490
 
419
- [Markdown]
420
- A paragraph.
421
-
422
- <iframe width="560" height="315" src="https://www.youtube-nocookie.com/embed/XXXXXXXXXXX" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
491
+ ### Captionless conversion toggles
423
492
 
424
- A paragraph.
425
- [HTML]
426
- <p>A paragraph.</p>
427
- <figure class="f-video">
428
- <iframe width="560" height="315" src="https://www.youtube-nocookie.com/embed/XXXXXXXXXXX" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
429
- </figure>
430
- <p>A paragraph.</p>
493
+ If `oneImageWithoutCaption` is enabled, a single image paragraph will be wrapped with `<figure class="f-img">` even without a caption.
431
494
 
495
+ ```
432
496
  [Markdown]
433
- <iframe src="https://player.vimeo.com/video/xxxxxxxxxxxxxxx" width="640" height="360" frameborder="0" allow="autoplay; fullscreen; picture-in-picture" allowfullscreen></iframe>
497
+ ![A single cat](cat.jpg)
498
+
434
499
  [HTML]
435
- <figure class="f-video">
436
- <iframe src="https://player.vimeo.com/video/xxxxxxxxxxxxxxx" width="640" height="360" frameborder="0" allow="autoplay; fullscreen; picture-in-picture" allowfullscreen></iframe>
500
+ <figure class="f-img">
501
+ <img src="cat.jpg" alt="A single cat">
437
502
  </figure>
503
+ ```
438
504
 
439
- [Markdown]
440
- A paragraph. iframeWithoutCaption: true.
505
+ If `videoWithoutCaption` is enabled, an `iframe` pointing to a known video host (such as YouTube or video elements) will be wrapped with `<figure class="f-video">`.
441
506
 
442
- <blockquote class="twitter-tweet"><p lang="ja" dir="ltr">XXXXX <a href="https://t.co/XXXXX">https://t.co/XXXXX</a></p>&mdash; User (@twitter) <a href="https://twitter.com/UserID/status/XXXXX">August 4, 2022</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
507
+ ```
508
+ [Markdown]
509
+ <iframe width="560" height="315" src="https://www.youtube-nocookie.com/embed/XXXXXXXXXXX" ...></iframe>
443
510
 
444
- A paragraph.
445
511
  [HTML]
446
- <p>A paragraph. iframeWithoutCaption: true.</p>
447
- <figure class="f-iframe">
448
- <blockquote class="twitter-tweet"><p lang="ja" dir="ltr">XXXXX <a href="https://t.co/XXXXX">https://t.co/XXXXX</a></p>&mdash; User (@twitter) <a href="https://twitter.com/UserID/status/XXXXX">August 4, 2022</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
512
+ <figure class="f-video">
513
+ <iframe width="560" height="315" src="https://www.youtube-nocookie.com/embed/XXXXXXXXXXX" ...></iframe>
449
514
  </figure>
450
- <p>A paragraph.</p>
451
515
 
452
- [Markdown]
453
- <iframe src="https://example.com/embed" class="mastodon-embed" style="max-width: 100%; border: 0" width="400" allowfullscreen="allowfullscreen"></iframe><script src="https://exapmle.com/embed.js" async="async"></script>
454
- [HTML]
455
- <figure class="f-iframe">
456
- <iframe src="https://example.com/embed" class="mastodon-embed" style="max-width: 100%; border: 0" width="400" allowfullscreen="allowfullscreen"></iframe><script src="https://exapmle.com/embed.js" async="async"></script>
457
- </figure>
458
516
 
459
517
  [Markdown]
460
- <iframe class="speakerdeck-iframe" style="border: 0px none; background: rgba(0, 0, 0, 0.1) padding-box; margin: 0px; padding: 0px; border-radius: 6px; box-shadow: rgba(0, 0, 0, 0.2) 0px 5px 40px; width: 100%; height: auto; aspect-ratio: 560 / 314;" src="https://speakerdeck.com/player/xxxxxxxxxxxxxx" title="xxxxxxxxxxx" allowfullscreen="true" data-ratio="1.78343949044586" frameborder="0"></iframe>
518
+ <video controls width="400" height="300">
519
+ <source src="example.mp4" type="video/mp4">
520
+ </video>
461
521
  [HTML]
462
- <figure class="f-iframe">
463
- <iframe class="speakerdeck-iframe" style="border: 0px none; background: rgba(0, 0, 0, 0.1) padding-box; margin: 0px; padding: 0px; border-radius: 6px; box-shadow: rgba(0, 0, 0, 0.2) 0px 5px 40px; width: 100%; height: auto; aspect-ratio: 560 / 314;" src="https://speakerdeck.com/player/xxxxxxxxxxxxxx" title="xxxxxxxxxxx" allowfullscreen="true" data-ratio="1.78343949044586" frameborder="0"></iframe>
522
+ <figure class="f-video">
523
+ <video controls width="400" height="300">
524
+ <source src="example.mp4" type="video/mp4">
525
+ </video>
464
526
  </figure>
465
- ~~~
466
-
467
- ### Option: imgAltCaption
468
-
469
- In Markdown documents, captions are often written in the alt attribute of images. If you follow the syntax of this plugin, the commit log will be cluttered. Therefore, as an option, the alt attribute is treated as a caption.
470
- Note that you cannot use this plugin's syntax and this option's syntax at the same time.
471
-
472
- The img alt attribute have an empty value.
473
-
474
- ```js
475
- const mdImgAltCaption = mdit({html: true}).use(mditFigureWithPCaption, {imgAltCaption: 'Figure'})
476
527
  ```
477
528
 
529
+ When `iframeWithoutCaption` is enabled, iframe elements will be wrapped with `<figure class="f-iframe">`. And if `iframeTypeBlockquoteWithoutCaption` is enabled, blockquote-based embeds (for example, X) will be wrapped with `<figure class="f-img">` (or another configured class).
530
+
478
531
  ```
479
532
  [Markdown]
480
- ![Figure. A caption.](cat.jpg)
533
+ <iframe>
534
+ ...
535
+ </iframe>
481
536
 
482
537
  [HTML]
483
- <figure class="f-img">
484
- <figcaption><span class="f-img-label">Figure<span class="f-img-label-joint">.</span></span> A caption.</figcaption>
485
- <img src="cat.jpg" alt="">
538
+ <figure class="f-iframe">
539
+ <iframe>
540
+ ...
541
+ </iframe>
486
542
  </figure>
487
543
  ```
488
544
 
489
- ### Option: imgTitleCaption
490
-
491
- The title attribute of the Markdown img element is used as the caption.
492
- Note that you cannot use this plugin's standard syntax and this option's syntax at the same time.
493
-
494
- The img alt attribute is not specially modified during conversion; the Markdown alt attribute is used as is.
545
+ ### Iframe-type blockquote class override
495
546
 
496
- ```js
497
- const mdImgAltCaption = mdit({html: true}).use(mditFigureWithPCaption, {imgTitleCaption: 'Figure'})
498
- ```
547
+ Set `figureClassThatWrapsIframeTypeBlockquote: 'f-social'` (or any class you prefer) to wrap blockquote-based embeds (for example, X, Mastodon, Bluesky) with that class.
499
548
 
500
549
  ```
501
550
  [Markdown]
502
- ![A alt text.](cat.jpg "Figure. A caption.")
551
+ Figure. Twitter embed.
552
+
553
+ <blockquote class="twitter-tweet"><p>Embed content</p></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
503
554
 
504
555
  [HTML]
505
- <figure class="f-img">
506
- <figcaption><span class="f-img-label">Figure<span class="f-img-label-joint">.</span></span> A caption.</figcaption>
507
- <img src="cat.jpg" alt="A alt text.">
556
+ <figure class="f-social">
557
+ <figcaption><span class="f-img-label">Figure<span class="f-img-label-joint">.</span></span> Twitter embed.</figcaption>
558
+ <blockquote class="twitter-tweet"><p>Embed content</p></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
508
559
  </figure>
509
560
  ```
510
561
 
511
- ### Option: roleDocExample
562
+ ### All iframe/embed class override
512
563
 
513
- From version 0.8, role="doc-example" is not included as standard in figure.f-pre-code and figure.f-pre-samp. If necessary, set `roleDocExample: true.`
514
-
515
- ```js
516
- const mdImgAltCaption = mdit({html: true}).use(mditFigureWithPCaption, {roleDocExample: true})
517
- ```
518
-
519
- ### Option: allIframeTypeFigureClassName
520
-
521
- From version 0.16.0, unify the figure element that wraps the iframe or blockquote tag in the embed code to figure.f-embed (this may become the default in the future).
522
-
523
- ```js
524
- const mdAllIframeTypeFigureClassName = mdit({html: true}).use(mdFigureWithPCaption, {
525
- allIframeTypeFigureClassName: 'f-embed',
526
- videoWithoutCaption = true,
527
- iframeWithoutCaption = true,
528
- iframeTypeBlockquoteWithoutCaption = true,
529
- }).use(mditAttrs).use(mditRndererFence);
530
- ```
564
+ Set `allIframeTypeFigureClassName: 'f-embed'` (or any class you prefer) to consolidate iframe-like embeds under one class.
531
565
 
532
566
  ```
533
567
  [Markdown]
534
- <iframe width="560" height="315" src="https://www.youtube-nocookie.com/embed/XXXXXXXXXXX" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
535
- [HTML]
536
- <figure class="f-embed">
537
- <iframe width="560" height="315" src="https://www.youtube-nocookie.com/embed/XXXXXXXXXXX" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
538
- </figure>
539
-
568
+ Video. Custom embed.
540
569
 
541
- [Markdown]
542
- Video. A youtube.
570
+ <iframe width="560" height="315" src="https://example.com/embed/123" title="Custom embed" frameborder="0" allowfullscreen></iframe>
543
571
 
544
- <iframe width="560" height="315" src="https://www.youtube-nocookie.com/embed/XXXXXXXXXXX" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
545
572
  [HTML]
546
573
  <figure class="f-embed">
547
- <figcaption><span class="f-video-label">Video<span class="f-video-label-joint">.</span></span> A youtube.</figcaption>
548
- <iframe width="560" height="315" src="https://www.youtube-nocookie.com/embed/XXXXXXXXXXX" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
574
+ <figcaption><span class="f-video-label">Video<span class="f-video-label-joint">.</span></span> Custom embed.</figcaption>
575
+ <iframe width="560" height="315" src="https://example.com/embed/123" title="Custom embed" frameborder="0" allowfullscreen></iframe>
549
576
  </figure>
577
+ ```
550
578
 
551
-
552
- [Markdown]
553
- <blockquote class="mastodon-embed" data-embed-url="https://mastodon.social/@xxxx/xxxx/embed" ...>xxxxxxxxxxxxxxxx</blockquote> <script data-allowed-prefixes="https://mastodon.social/" async src="https://mastodon.social/embed.js"></script>
554
-
555
- [HTML]
556
- <figure class="f-embed">
557
- <blockquote class="mastodon-embed" data-embed-url="https://mastodon.social/@xxxx/xxxx/embed" ...>xxxxxxxxxxxxxxxx</blockquote> <script data-allowed-prefixes="https://mastodon.social/" async src="https://mastodon.social/embed.js"></script>
558
- </figure>
559
- ```
579
+ Need matching caption classes too? Combine this option with `labelClassFollowsFigure` (and optionally `figureToLabelClassMap`) so the `figcaption` spans inherit the embed class you just applied (e.g., `f-embed-label`, `f-embed-label-joint`).