@peaceroad/markdown-it-figure-with-p-caption 0.14.2 → 0.15.1
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 +596 -579
- package/index.js +290 -167
- package/package.json +4 -4
package/index.js
CHANGED
|
@@ -2,7 +2,6 @@ import { setCaptionParagraph, markReg } from 'p7d-markdown-it-p-captions'
|
|
|
2
2
|
|
|
3
3
|
const htmlRegCache = new Map()
|
|
4
4
|
const cleanCaptionRegCache = new Map()
|
|
5
|
-
const classReg = /^f-(.+)$/
|
|
6
5
|
const blueskyEmbedReg = /^<blockquote class="bluesky-embed"[^]*?>[\s\S]*?$/
|
|
7
6
|
const videoIframeReg = /^<[^>]*? src="https:\/\/(?:www.youtube-nocookie.com|player.vimeo.com)\//i
|
|
8
7
|
const classNameReg = /^<[^>]*? class="(twitter-tweet|instagram-media|text-post-media|bluesky-embed|mastodon-embed)"/
|
|
@@ -26,6 +25,80 @@ const fallbackLabelDefaults = {
|
|
|
26
25
|
table: { en: 'Table', ja: '表' },
|
|
27
26
|
}
|
|
28
27
|
|
|
28
|
+
const escapeRegExp = (value) => value.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')
|
|
29
|
+
const buildClassPrefix = (value) => (value ? value + '-' : '')
|
|
30
|
+
const normalizeLabelPrefixMarkers = (value) => {
|
|
31
|
+
if (typeof value === 'string') {
|
|
32
|
+
return value ? [value] : []
|
|
33
|
+
}
|
|
34
|
+
if (Array.isArray(value)) {
|
|
35
|
+
const normalized = value.map(entry => String(entry)).filter(Boolean)
|
|
36
|
+
return normalized.length > 2 ? normalized.slice(0, 2) : normalized
|
|
37
|
+
}
|
|
38
|
+
return []
|
|
39
|
+
}
|
|
40
|
+
const buildLabelPrefixMarkerRegFromList = (markers) => {
|
|
41
|
+
if (!markers || markers.length === 0) return null
|
|
42
|
+
const pattern = markers.map(escapeRegExp).join('|')
|
|
43
|
+
return new RegExp('^(?:' + pattern + ')(?:[ \\t ]+)?')
|
|
44
|
+
}
|
|
45
|
+
const resolveLabelPrefixMarkerPair = (markers) => {
|
|
46
|
+
if (!markers || markers.length === 0) return { prev: [], next: [] }
|
|
47
|
+
if (markers.length === 1) {
|
|
48
|
+
return { prev: [markers[0]], next: [markers[0]] }
|
|
49
|
+
}
|
|
50
|
+
return { prev: [markers[0]], next: [markers[1]] }
|
|
51
|
+
}
|
|
52
|
+
const stripLeadingPrefix = (text, prefix) => {
|
|
53
|
+
if (typeof text !== 'string' || !text || !prefix) return text
|
|
54
|
+
if (text.startsWith(prefix)) return text.slice(prefix.length)
|
|
55
|
+
return text
|
|
56
|
+
}
|
|
57
|
+
const stripLabelPrefixMarkerFromInline = (inlineToken, markerText) => {
|
|
58
|
+
if (!inlineToken || !markerText) return
|
|
59
|
+
if (typeof inlineToken.content === 'string') {
|
|
60
|
+
inlineToken.content = stripLeadingPrefix(inlineToken.content, markerText)
|
|
61
|
+
}
|
|
62
|
+
if (inlineToken.children && inlineToken.children.length) {
|
|
63
|
+
for (let i = 0; i < inlineToken.children.length; i++) {
|
|
64
|
+
const child = inlineToken.children[i]
|
|
65
|
+
if (child && child.type === 'text' && typeof child.content === 'string') {
|
|
66
|
+
child.content = stripLeadingPrefix(child.content, markerText)
|
|
67
|
+
break
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
const getLabelPrefixMarkerMatch = (inlineToken, markerReg) => {
|
|
73
|
+
if (!markerReg || !inlineToken || inlineToken.type !== 'inline') return null
|
|
74
|
+
const content = typeof inlineToken.content === 'string' ? inlineToken.content : ''
|
|
75
|
+
if (!content) return null
|
|
76
|
+
const match = content.match(markerReg)
|
|
77
|
+
if (!match) return null
|
|
78
|
+
const remaining = content.slice(match[0].length)
|
|
79
|
+
if (!remaining || !remaining.trim()) return null
|
|
80
|
+
return match[0]
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
const parseImageAttrs = (raw) => {
|
|
84
|
+
if (raw === null || raw === undefined) return null
|
|
85
|
+
const attrs = []
|
|
86
|
+
const parts = raw.split(/ +/)
|
|
87
|
+
for (let i = 0; i < parts.length; i++) {
|
|
88
|
+
let entry = parts[i]
|
|
89
|
+
if (!entry) continue
|
|
90
|
+
if (classAttrReg.test(entry)) {
|
|
91
|
+
entry = entry.replace(classAttrReg, 'class=')
|
|
92
|
+
} else if (idAttrReg.test(entry)) {
|
|
93
|
+
entry = entry.replace(idAttrReg, 'id=')
|
|
94
|
+
}
|
|
95
|
+
const imageAttr = entry.match(attrParseReg)
|
|
96
|
+
if (!imageAttr || !imageAttr[1]) continue
|
|
97
|
+
attrs.push([imageAttr[1], imageAttr[2]])
|
|
98
|
+
}
|
|
99
|
+
return attrs
|
|
100
|
+
}
|
|
101
|
+
|
|
29
102
|
const normalizeAutoLabelNumberSets = (value) => {
|
|
30
103
|
const normalized = { img: false, table: false }
|
|
31
104
|
if (!value) return normalized
|
|
@@ -117,7 +190,12 @@ const getImageAltText = (token) => {
|
|
|
117
190
|
if (alt) return alt
|
|
118
191
|
if (typeof token.content === 'string' && token.content !== '') return token.content
|
|
119
192
|
if (token.children && token.children.length > 0) {
|
|
120
|
-
|
|
193
|
+
let combined = ''
|
|
194
|
+
for (let i = 0; i < token.children.length; i++) {
|
|
195
|
+
const child = token.children[i]
|
|
196
|
+
if (child && child.content) combined += child.content
|
|
197
|
+
}
|
|
198
|
+
return combined
|
|
121
199
|
}
|
|
122
200
|
return ''
|
|
123
201
|
}
|
|
@@ -207,6 +285,22 @@ const getCaptionInlineToken = (tokens, range, caption) => {
|
|
|
207
285
|
return null
|
|
208
286
|
}
|
|
209
287
|
|
|
288
|
+
const hasClassName = (classAttr, className) => {
|
|
289
|
+
const index = classAttr.indexOf(className)
|
|
290
|
+
if (index === -1) return false
|
|
291
|
+
const end = index + className.length
|
|
292
|
+
if (index > 0 && classAttr.charCodeAt(index - 1) > 0x20) return false
|
|
293
|
+
if (end < classAttr.length && classAttr.charCodeAt(end) > 0x20) return false
|
|
294
|
+
return true
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
const hasAnyClassName = (classAttr, classNames) => {
|
|
298
|
+
for (let i = 0; i < classNames.length; i++) {
|
|
299
|
+
if (hasClassName(classAttr, classNames[i])) return true
|
|
300
|
+
}
|
|
301
|
+
return false
|
|
302
|
+
}
|
|
303
|
+
|
|
210
304
|
const getInlineLabelTextToken = (inlineToken, type, opt) => {
|
|
211
305
|
if (!inlineToken || !inlineToken.children) return null
|
|
212
306
|
const children = inlineToken.children
|
|
@@ -216,9 +310,7 @@ const getInlineLabelTextToken = (inlineToken, type, opt) => {
|
|
|
216
310
|
if (!child || !child.attrs) continue
|
|
217
311
|
const classAttr = getTokenAttr(child, 'class')
|
|
218
312
|
if (!classAttr) continue
|
|
219
|
-
|
|
220
|
-
const matched = classNames.some(className => classes.includes(className))
|
|
221
|
-
if (!matched) continue
|
|
313
|
+
if (!hasAnyClassName(classAttr, classNames)) continue
|
|
222
314
|
const textToken = children[i + 1]
|
|
223
315
|
if (textToken && textToken.type === 'text') {
|
|
224
316
|
return textToken
|
|
@@ -246,30 +338,38 @@ const ensureAutoFigureNumbering = (tokens, range, caption, figureNumberState, op
|
|
|
246
338
|
if (!inlineToken) return
|
|
247
339
|
const labelTextToken = getInlineLabelTextToken(inlineToken, captionType, opt)
|
|
248
340
|
if (!labelTextToken || typeof labelTextToken.content !== 'string') return
|
|
249
|
-
const
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
341
|
+
const originalText = labelTextToken.content
|
|
342
|
+
let end = originalText.length - 1
|
|
343
|
+
while (end >= 0 && originalText.charCodeAt(end) === 0x20) end--
|
|
344
|
+
if (end >= 0) {
|
|
345
|
+
const code = originalText.charCodeAt(end)
|
|
346
|
+
if (code >= 0x30 && code <= 0x39) {
|
|
347
|
+
const existingMatch = originalText.match(trailingDigitsReg)
|
|
348
|
+
if (existingMatch && existingMatch[1]) {
|
|
349
|
+
const explicitValue = parseInt(existingMatch[1], 10)
|
|
350
|
+
if (!Number.isNaN(explicitValue) && explicitValue > (figureNumberState[captionType] || 0)) {
|
|
351
|
+
figureNumberState[captionType] = explicitValue
|
|
352
|
+
}
|
|
353
|
+
return
|
|
354
|
+
}
|
|
254
355
|
}
|
|
255
|
-
return
|
|
256
356
|
}
|
|
257
357
|
figureNumberState[captionType] = (figureNumberState[captionType] || 0) + 1
|
|
258
|
-
const baseLabel =
|
|
358
|
+
const baseLabel = originalText.trim()
|
|
259
359
|
if (!baseLabel) return
|
|
260
360
|
const joint = asciiLabelReg.test(baseLabel) ? ' ' : ''
|
|
261
361
|
const newLabelText = baseLabel + joint + figureNumberState[captionType]
|
|
262
|
-
const originalText = labelTextToken.content
|
|
263
362
|
labelTextToken.content = newLabelText
|
|
264
363
|
updateInlineTokenContent(inlineToken, originalText, newLabelText)
|
|
265
364
|
}
|
|
266
365
|
|
|
267
366
|
const getAutoCaptionFromImage = (imageToken, opt, fallbackLabelState) => {
|
|
268
367
|
if (!opt.autoCaptionDetection) return ''
|
|
368
|
+
if (!imgCaptionMarkReg && !opt.autoAltCaption && !opt.autoTitleCaption) return ''
|
|
269
369
|
const tryMatch = (text) => {
|
|
270
370
|
if (!text) return ''
|
|
271
371
|
const trimmed = text.trim()
|
|
272
|
-
if (trimmed && imgCaptionMarkReg &&
|
|
372
|
+
if (trimmed && imgCaptionMarkReg && imgCaptionMarkReg.test(trimmed)) {
|
|
273
373
|
return trimmed
|
|
274
374
|
}
|
|
275
375
|
return ''
|
|
@@ -314,76 +414,87 @@ const getHtmlReg = (tag) => {
|
|
|
314
414
|
return reg
|
|
315
415
|
}
|
|
316
416
|
|
|
317
|
-
const
|
|
318
|
-
if (!token.attrs) return ''
|
|
319
|
-
const attrs = token.attrs
|
|
320
|
-
for (let i = 0, len = attrs.length; i < len; i++) {
|
|
321
|
-
const attr = attrs[i]
|
|
322
|
-
if (attr[0] === 'class') {
|
|
323
|
-
const match = attr[1].match(classReg)
|
|
324
|
-
if (match) return match[1]
|
|
325
|
-
}
|
|
326
|
-
}
|
|
327
|
-
return ''
|
|
328
|
-
}
|
|
329
|
-
|
|
330
|
-
const checkPrevCaption = (tokens, n, caption, fNum, sp, opt, TokenConstructor) => {
|
|
417
|
+
const checkPrevCaption = (tokens, n, caption, fNum, sp, opt, captionState) => {
|
|
331
418
|
if(n < 3) return caption
|
|
332
419
|
const captionStartToken = tokens[n-3]
|
|
420
|
+
const captionInlineToken = tokens[n-2]
|
|
333
421
|
const captionEndToken = tokens[n-1]
|
|
334
422
|
if (captionStartToken === undefined || captionEndToken === undefined) return
|
|
335
423
|
if (captionStartToken.type !== 'paragraph_open' || captionEndToken.type !== 'paragraph_close') return
|
|
336
|
-
setCaptionParagraph(n-3,
|
|
337
|
-
const captionName =
|
|
338
|
-
if(!captionName)
|
|
424
|
+
setCaptionParagraph(n-3, captionState, caption, fNum, sp, opt)
|
|
425
|
+
const captionName = sp && sp.captionDecision ? sp.captionDecision.mark : ''
|
|
426
|
+
if(!captionName) {
|
|
427
|
+
if (opt.labelPrefixMarkerWithoutLabelPrevReg) {
|
|
428
|
+
const markerMatch = getLabelPrefixMarkerMatch(captionInlineToken, opt.labelPrefixMarkerWithoutLabelPrevReg)
|
|
429
|
+
if (markerMatch) {
|
|
430
|
+
stripLabelPrefixMarkerFromInline(captionInlineToken, markerMatch)
|
|
431
|
+
caption.isPrev = true
|
|
432
|
+
}
|
|
433
|
+
}
|
|
434
|
+
return
|
|
435
|
+
}
|
|
339
436
|
caption.name = captionName
|
|
340
437
|
caption.isPrev = true
|
|
341
438
|
return
|
|
342
439
|
}
|
|
343
440
|
|
|
344
|
-
const checkNextCaption = (tokens, en, caption, fNum, sp, opt,
|
|
441
|
+
const checkNextCaption = (tokens, en, caption, fNum, sp, opt, captionState) => {
|
|
345
442
|
if (en + 2 > tokens.length) return
|
|
346
443
|
const captionStartToken = tokens[en+1]
|
|
444
|
+
const captionInlineToken = tokens[en+2]
|
|
347
445
|
const captionEndToken = tokens[en+3]
|
|
348
446
|
if (captionStartToken === undefined || captionEndToken === undefined) return
|
|
349
447
|
if (captionStartToken.type !== 'paragraph_open' || captionEndToken.type !== 'paragraph_close') return
|
|
350
|
-
setCaptionParagraph(en+1,
|
|
351
|
-
const captionName =
|
|
352
|
-
if(!captionName)
|
|
448
|
+
setCaptionParagraph(en+1, captionState, caption, fNum, sp, opt)
|
|
449
|
+
const captionName = sp && sp.captionDecision ? sp.captionDecision.mark : ''
|
|
450
|
+
if(!captionName) {
|
|
451
|
+
if (opt.labelPrefixMarkerWithoutLabelNextReg) {
|
|
452
|
+
const markerMatch = getLabelPrefixMarkerMatch(captionInlineToken, opt.labelPrefixMarkerWithoutLabelNextReg)
|
|
453
|
+
if (markerMatch) {
|
|
454
|
+
stripLabelPrefixMarkerFromInline(captionInlineToken, markerMatch)
|
|
455
|
+
caption.isNext = true
|
|
456
|
+
}
|
|
457
|
+
}
|
|
458
|
+
return
|
|
459
|
+
}
|
|
353
460
|
caption.name = captionName
|
|
354
461
|
caption.isNext = true
|
|
355
462
|
return
|
|
356
463
|
}
|
|
357
464
|
|
|
358
|
-
const cleanCaptionTokenAttrs = (token, captionName) => {
|
|
359
|
-
if (!token.attrs) return
|
|
360
|
-
|
|
465
|
+
const cleanCaptionTokenAttrs = (token, captionName, opt) => {
|
|
466
|
+
if (!captionName || !token.attrs || !opt) return
|
|
467
|
+
const prefix = opt.captionClassPrefix || ''
|
|
468
|
+
const targetClass = prefix + captionName
|
|
469
|
+
if (!targetClass) return
|
|
470
|
+
let reg = cleanCaptionRegCache.get(targetClass)
|
|
361
471
|
if (!reg) {
|
|
362
|
-
reg = new RegExp('
|
|
363
|
-
cleanCaptionRegCache.set(
|
|
472
|
+
reg = new RegExp('(?:^|\\s)' + escapeRegExp(targetClass) + '(?=\\s|$)', 'g')
|
|
473
|
+
cleanCaptionRegCache.set(targetClass, reg)
|
|
364
474
|
}
|
|
365
475
|
for (let i = token.attrs.length - 1; i >= 0; i--) {
|
|
366
476
|
if (token.attrs[i][0] === 'class') {
|
|
367
|
-
|
|
368
|
-
if (
|
|
477
|
+
const classValue = token.attrs[i][1] || ''
|
|
478
|
+
if (!classValue || classValue.indexOf(targetClass) === -1) continue
|
|
479
|
+
const cleaned = classValue.replace(reg, '').replace(/\s+/g, ' ').trim()
|
|
480
|
+
if (cleaned) {
|
|
481
|
+
token.attrs[i][1] = cleaned
|
|
482
|
+
} else {
|
|
483
|
+
token.attrs.splice(i, 1)
|
|
484
|
+
}
|
|
369
485
|
}
|
|
370
486
|
}
|
|
371
487
|
}
|
|
372
488
|
|
|
373
|
-
const resolveFigureClassName = (checkTokenTagName,
|
|
374
|
-
|
|
489
|
+
const resolveFigureClassName = (checkTokenTagName, sp, opt) => {
|
|
490
|
+
const prefix = opt.figureClassPrefix || ''
|
|
491
|
+
let className = prefix + checkTokenTagName
|
|
375
492
|
if (opt.allIframeTypeFigureClassName === '') {
|
|
376
493
|
if (sp.isVideoIframe) {
|
|
377
|
-
className = '
|
|
494
|
+
className = prefix + 'video'
|
|
378
495
|
}
|
|
379
496
|
if (sp.isIframeTypeBlockquote) {
|
|
380
|
-
|
|
381
|
-
if ((caption.isPrev || caption.isNext) &&
|
|
382
|
-
figureClassThatWrapsIframeTypeBlockquote === 'f-img' &&
|
|
383
|
-
(caption.name === 'blockquote' || caption.name === 'img')) {
|
|
384
|
-
figureClassThatWrapsIframeTypeBlockquote = 'f-img'
|
|
385
|
-
}
|
|
386
|
-
className = figureClassThatWrapsIframeTypeBlockquote
|
|
497
|
+
className = opt.figureClassThatWrapsIframeTypeBlockquote
|
|
387
498
|
}
|
|
388
499
|
} else {
|
|
389
500
|
if (checkTokenTagName === 'iframe' || sp.isIframeTypeBlockquote) {
|
|
@@ -409,7 +520,7 @@ const changePrevCaptionPosition = (tokens, n, caption, opt) => {
|
|
|
409
520
|
const captionInlineToken = tokens[n-2]
|
|
410
521
|
const captionEndToken = tokens[n-1]
|
|
411
522
|
|
|
412
|
-
cleanCaptionTokenAttrs(captionStartToken, caption.name)
|
|
523
|
+
cleanCaptionTokenAttrs(captionStartToken, caption.name, opt)
|
|
413
524
|
captionStartToken.type = 'figcaption_open'
|
|
414
525
|
captionStartToken.tag = 'figcaption'
|
|
415
526
|
captionEndToken.type = 'figcaption_close'
|
|
@@ -423,7 +534,7 @@ const changeNextCaptionPosition = (tokens, en, caption, opt) => {
|
|
|
423
534
|
const captionStartToken = tokens[en+2] // +1: text node for figure.
|
|
424
535
|
const captionInlineToken = tokens[en+3]
|
|
425
536
|
const captionEndToken = tokens[en+4]
|
|
426
|
-
cleanCaptionTokenAttrs(captionStartToken, caption.name)
|
|
537
|
+
cleanCaptionTokenAttrs(captionStartToken, caption.name, opt)
|
|
427
538
|
captionStartToken.type = 'figcaption_open'
|
|
428
539
|
captionStartToken.tag = 'figcaption'
|
|
429
540
|
captionEndToken.type = 'figcaption_close'
|
|
@@ -437,23 +548,25 @@ const wrapWithFigure = (tokens, range, checkTokenTagName, caption, replaceInstea
|
|
|
437
548
|
let n = range.start
|
|
438
549
|
let en = range.end
|
|
439
550
|
const figureStartToken = new TokenConstructor('figure_open', 'figure', 1)
|
|
440
|
-
const figureClassName = sp.figureClassName || resolveFigureClassName(checkTokenTagName,
|
|
551
|
+
const figureClassName = sp.figureClassName || resolveFigureClassName(checkTokenTagName, sp, opt)
|
|
441
552
|
figureStartToken.attrSet('class', figureClassName)
|
|
442
553
|
|
|
443
|
-
if(
|
|
554
|
+
if (opt.roleDocExample && (checkTokenTagName === 'pre-code' || checkTokenTagName === 'pre-samp')) {
|
|
444
555
|
figureStartToken.attrSet('role', 'doc-example')
|
|
445
556
|
}
|
|
446
557
|
const figureEndToken = new TokenConstructor('figure_close', 'figure', -1)
|
|
447
558
|
const breakToken = new TokenConstructor('text', '', 0)
|
|
448
559
|
breakToken.content = '\n'
|
|
449
560
|
if (opt.styleProcess && caption.isNext && sp.attrs.length > 0) {
|
|
450
|
-
for (let
|
|
561
|
+
for (let i = 0; i < sp.attrs.length; i++) {
|
|
562
|
+
const attr = sp.attrs[i]
|
|
451
563
|
figureStartToken.attrJoin(attr[0], attr[1])
|
|
452
564
|
}
|
|
453
565
|
}
|
|
454
566
|
// For vsce
|
|
455
|
-
if(
|
|
456
|
-
for (let
|
|
567
|
+
if (caption.name === 'img' && tokens[n].attrs) {
|
|
568
|
+
for (let i = 0; i < tokens[n].attrs.length; i++) {
|
|
569
|
+
const attr = tokens[n].attrs[i]
|
|
457
570
|
figureStartToken.attrJoin(attr[0], attr[1])
|
|
458
571
|
}
|
|
459
572
|
}
|
|
@@ -471,22 +584,25 @@ const wrapWithFigure = (tokens, range, checkTokenTagName, caption, replaceInstea
|
|
|
471
584
|
return
|
|
472
585
|
}
|
|
473
586
|
|
|
474
|
-
const checkCaption = (tokens, n, en, caption, fNum, sp, opt,
|
|
475
|
-
checkPrevCaption(tokens, n, caption, fNum, sp, opt,
|
|
587
|
+
const checkCaption = (tokens, n, en, caption, fNum, sp, opt, captionState) => {
|
|
588
|
+
checkPrevCaption(tokens, n, caption, fNum, sp, opt, captionState)
|
|
476
589
|
if (caption.isPrev) return
|
|
477
|
-
checkNextCaption(tokens, en, caption, fNum, sp, opt,
|
|
590
|
+
checkNextCaption(tokens, en, caption, fNum, sp, opt, captionState)
|
|
478
591
|
return
|
|
479
592
|
}
|
|
480
593
|
|
|
481
|
-
const nestedContainers = ['blockquote', 'list_item', 'dd']
|
|
482
|
-
|
|
483
594
|
const getNestedContainerType = (token) => {
|
|
484
|
-
if (!token
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
595
|
+
if (!token) return null
|
|
596
|
+
switch (token.type) {
|
|
597
|
+
case 'blockquote_open':
|
|
598
|
+
return 'blockquote'
|
|
599
|
+
case 'list_item_open':
|
|
600
|
+
return 'list_item'
|
|
601
|
+
case 'dd_open':
|
|
602
|
+
return 'dd'
|
|
603
|
+
default:
|
|
604
|
+
return null
|
|
488
605
|
}
|
|
489
|
-
return null
|
|
490
606
|
}
|
|
491
607
|
|
|
492
608
|
const resetRangeState = (range, start) => {
|
|
@@ -495,7 +611,6 @@ const resetRangeState = (range, start) => {
|
|
|
495
611
|
}
|
|
496
612
|
|
|
497
613
|
const resetCaptionState = (caption) => {
|
|
498
|
-
caption.mark = ''
|
|
499
614
|
caption.name = ''
|
|
500
615
|
caption.nameSuffix = ''
|
|
501
616
|
caption.isPrev = false
|
|
@@ -506,18 +621,19 @@ const resetSpecialState = (sp) => {
|
|
|
506
621
|
sp.attrs.length = 0
|
|
507
622
|
sp.isVideoIframe = false
|
|
508
623
|
sp.isIframeTypeBlockquote = false
|
|
509
|
-
sp.hasImgCaption = false
|
|
510
624
|
sp.figureClassName = ''
|
|
511
625
|
sp.captionDecision = null
|
|
512
626
|
}
|
|
513
627
|
|
|
514
628
|
const findClosingTokenIndex = (tokens, startIndex, tag) => {
|
|
629
|
+
const openType = tag + '_open'
|
|
630
|
+
const closeType = tag + '_close'
|
|
515
631
|
let depth = 1
|
|
516
632
|
let i = startIndex + 1
|
|
517
633
|
while (i < tokens.length) {
|
|
518
|
-
const
|
|
519
|
-
if (
|
|
520
|
-
if (
|
|
634
|
+
const tokenType = tokens[i].type
|
|
635
|
+
if (tokenType === openType) depth++
|
|
636
|
+
if (tokenType === closeType) {
|
|
521
637
|
depth--
|
|
522
638
|
if (depth === 0) return i
|
|
523
639
|
}
|
|
@@ -526,17 +642,14 @@ const findClosingTokenIndex = (tokens, startIndex, tag) => {
|
|
|
526
642
|
return startIndex
|
|
527
643
|
}
|
|
528
644
|
|
|
529
|
-
const detectCheckTypeOpen = (tokens, token, n, caption) => {
|
|
530
|
-
if (!token) return null
|
|
531
|
-
const baseType = CHECK_TYPE_TOKEN_MAP[token.type]
|
|
532
|
-
if (!baseType) return null
|
|
645
|
+
const detectCheckTypeOpen = (tokens, token, n, caption, baseType) => {
|
|
646
|
+
if (!token || !baseType) return null
|
|
533
647
|
if (n > 1 && tokens[n - 2] && tokens[n - 2].type === 'figure_open') return null
|
|
534
648
|
let tagName = token.tag
|
|
535
649
|
caption.name = baseType
|
|
536
650
|
if (baseType === 'pre') {
|
|
537
|
-
if (tokens[n + 1] && tokens[n + 1].tag === 'code') caption.
|
|
538
|
-
if (tokens[n + 1] && tokens[n + 1].tag === 'samp') caption.
|
|
539
|
-
caption.name = caption.mark
|
|
651
|
+
if (tokens[n + 1] && tokens[n + 1].tag === 'code') caption.name = 'pre-code'
|
|
652
|
+
if (tokens[n + 1] && tokens[n + 1].tag === 'samp') caption.name = 'pre-samp'
|
|
540
653
|
}
|
|
541
654
|
const en = findClosingTokenIndex(tokens, n, tagName)
|
|
542
655
|
return {
|
|
@@ -569,14 +682,18 @@ const detectFenceToken = (token, n, caption) => {
|
|
|
569
682
|
|
|
570
683
|
const detectHtmlBlockToken = (tokens, token, n, caption, sp, opt) => {
|
|
571
684
|
if (!token || token.type !== 'html_block') return null
|
|
572
|
-
const
|
|
685
|
+
const content = token.content
|
|
686
|
+
const hasBlueskyHint = content.indexOf('bluesky-embed') !== -1
|
|
687
|
+
const hasBlueskyEmbed = hasBlueskyHint && blueskyEmbedReg.test(content)
|
|
573
688
|
let matchedTag = ''
|
|
574
689
|
for (let i = 0; i < HTML_TAG_CANDIDATES.length; i++) {
|
|
575
690
|
const candidate = HTML_TAG_CANDIDATES[i]
|
|
576
691
|
const treatDivAsIframe = candidate === 'div'
|
|
577
692
|
const lookupTag = treatDivAsIframe ? 'div' : candidate
|
|
578
|
-
const
|
|
579
|
-
|
|
693
|
+
const hasTagHint = content.indexOf('<' + lookupTag) !== -1
|
|
694
|
+
if (!hasTagHint && !(candidate === 'blockquote' && hasBlueskyEmbed)) continue
|
|
695
|
+
const hasTag = hasTagHint ? content.match(getHtmlReg(lookupTag)) : null
|
|
696
|
+
const isBlueskyBlockquote = !hasTag && hasBlueskyEmbed && candidate === 'blockquote'
|
|
580
697
|
if (!(hasTag || isBlueskyBlockquote)) continue
|
|
581
698
|
if (hasTag) {
|
|
582
699
|
if ((hasTag[2] && hasTag[3] !== '\n') || (hasTag[1] !== '\n' && hasTag[2] === undefined)) {
|
|
@@ -588,9 +705,8 @@ const detectHtmlBlockToken = (tokens, token, n, caption, sp, opt) => {
|
|
|
588
705
|
}
|
|
589
706
|
} else {
|
|
590
707
|
let addedCont = ''
|
|
591
|
-
const tokensLength = tokens.length
|
|
592
708
|
let j = n + 1
|
|
593
|
-
while (j <
|
|
709
|
+
while (j < tokens.length) {
|
|
594
710
|
const nextToken = tokens[j]
|
|
595
711
|
if (nextToken.type === 'inline' && endBlockquoteScriptReg.test(nextToken.content)) {
|
|
596
712
|
addedCont += nextToken.content + '\n'
|
|
@@ -598,9 +714,11 @@ const detectHtmlBlockToken = (tokens, token, n, caption, sp, opt) => {
|
|
|
598
714
|
tokens.splice(j + 1, 1)
|
|
599
715
|
}
|
|
600
716
|
nextToken.content = ''
|
|
601
|
-
nextToken.children
|
|
602
|
-
|
|
603
|
-
|
|
717
|
+
if (nextToken.children) {
|
|
718
|
+
for (let k = 0; k < nextToken.children.length; k++) {
|
|
719
|
+
nextToken.children[k].content = ''
|
|
720
|
+
}
|
|
721
|
+
}
|
|
604
722
|
break
|
|
605
723
|
}
|
|
606
724
|
if (nextToken.type === 'paragraph_open') {
|
|
@@ -617,8 +735,7 @@ const detectHtmlBlockToken = (tokens, token, n, caption, sp, opt) => {
|
|
|
617
735
|
}
|
|
618
736
|
if (!matchedTag) return null
|
|
619
737
|
if (matchedTag === 'blockquote') {
|
|
620
|
-
|
|
621
|
-
if (isIframeTypeBlockquote) {
|
|
738
|
+
if (classNameReg.test(token.content)) {
|
|
622
739
|
sp.isIframeTypeBlockquote = true
|
|
623
740
|
} else {
|
|
624
741
|
return null
|
|
@@ -665,17 +782,11 @@ const detectImageParagraph = (tokens, token, nextToken, n, caption, sp, opt) =>
|
|
|
665
782
|
if (childIndex === childrenLength - 1 && child.type === 'text') {
|
|
666
783
|
let imageAttrs = child.content && child.content.match(imageAttrsReg)
|
|
667
784
|
if (imageAttrs) {
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
}
|
|
673
|
-
if (idAttrReg.test(imageAttrs[i])) {
|
|
674
|
-
imageAttrs[i] = imageAttrs[i].replace(idAttrReg, 'id=')
|
|
785
|
+
const parsedAttrs = parseImageAttrs(imageAttrs[1])
|
|
786
|
+
if (parsedAttrs && parsedAttrs.length) {
|
|
787
|
+
for (let i = 0; i < parsedAttrs.length; i++) {
|
|
788
|
+
sp.attrs.push(parsedAttrs[i])
|
|
675
789
|
}
|
|
676
|
-
const imageAttr = imageAttrs[i].match(attrParseReg)
|
|
677
|
-
if (!imageAttr || !imageAttr[1]) continue
|
|
678
|
-
sp.attrs.push([imageAttr[1], imageAttr[2]])
|
|
679
790
|
}
|
|
680
791
|
break
|
|
681
792
|
}
|
|
@@ -715,7 +826,6 @@ const detectImageParagraph = (tokens, token, nextToken, n, caption, sp, opt) =>
|
|
|
715
826
|
}
|
|
716
827
|
}
|
|
717
828
|
}
|
|
718
|
-
nextToken.children[0].type = 'image'
|
|
719
829
|
const en = n + 2
|
|
720
830
|
let tagName = 'img'
|
|
721
831
|
if (caption.nameSuffix) tagName += caption.nameSuffix
|
|
@@ -746,25 +856,29 @@ const figureWithCaption = (state, opt) => {
|
|
|
746
856
|
table: null,
|
|
747
857
|
}
|
|
748
858
|
|
|
749
|
-
|
|
859
|
+
const captionState = { tokens: state.tokens, Token: state.Token }
|
|
860
|
+
figureWithCaptionCore(state.tokens, opt, fNum, figureNumberState, fallbackLabelState, state.Token, captionState, null, 0)
|
|
750
861
|
}
|
|
751
862
|
|
|
752
|
-
const figureWithCaptionCore = (tokens, opt, fNum, figureNumberState, fallbackLabelState, TokenConstructor, parentType = null, startIndex = 0) => {
|
|
863
|
+
const figureWithCaptionCore = (tokens, opt, fNum, figureNumberState, fallbackLabelState, TokenConstructor, captionState, parentType = null, startIndex = 0) => {
|
|
753
864
|
const rRange = { start: startIndex, end: startIndex }
|
|
754
865
|
const rCaption = {
|
|
755
|
-
|
|
866
|
+
name: '', nameSuffix: '', isPrev: false, isNext: false
|
|
756
867
|
}
|
|
757
868
|
const rSp = {
|
|
758
|
-
attrs: [],
|
|
869
|
+
attrs: [],
|
|
870
|
+
isVideoIframe: false,
|
|
871
|
+
isIframeTypeBlockquote: false,
|
|
872
|
+
figureClassName: '',
|
|
873
|
+
captionDecision: null
|
|
759
874
|
}
|
|
760
|
-
|
|
761
875
|
let n = startIndex
|
|
762
876
|
while (n < tokens.length) {
|
|
763
877
|
const token = tokens[n]
|
|
764
878
|
const containerType = getNestedContainerType(token)
|
|
765
879
|
|
|
766
880
|
if (containerType && containerType !== 'blockquote') {
|
|
767
|
-
const closeIndex = figureWithCaptionCore(tokens, opt, fNum, figureNumberState, fallbackLabelState, TokenConstructor, containerType, n + 1)
|
|
881
|
+
const closeIndex = figureWithCaptionCore(tokens, opt, fNum, figureNumberState, fallbackLabelState, TokenConstructor, captionState, containerType, n + 1)
|
|
768
882
|
n = (typeof closeIndex === 'number' ? closeIndex : n) + 1
|
|
769
883
|
continue
|
|
770
884
|
}
|
|
@@ -774,20 +888,35 @@ const figureWithCaptionCore = (tokens, opt, fNum, figureNumberState, fallbackLab
|
|
|
774
888
|
return n
|
|
775
889
|
}
|
|
776
890
|
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
891
|
+
let detection = null
|
|
892
|
+
const tokenType = token.type
|
|
893
|
+
const blockType = CHECK_TYPE_TOKEN_MAP[tokenType]
|
|
894
|
+
if (tokenType === 'paragraph_open') {
|
|
895
|
+
resetRangeState(rRange, n)
|
|
896
|
+
resetCaptionState(rCaption)
|
|
897
|
+
resetSpecialState(rSp)
|
|
898
|
+
const nextToken = tokens[n + 1]
|
|
899
|
+
detection = detectImageParagraph(tokens, token, nextToken, n, rCaption, rSp, opt)
|
|
900
|
+
} else if (tokenType === 'html_block') {
|
|
901
|
+
resetRangeState(rRange, n)
|
|
902
|
+
resetCaptionState(rCaption)
|
|
903
|
+
resetSpecialState(rSp)
|
|
904
|
+
detection = detectHtmlBlockToken(tokens, token, n, rCaption, rSp, opt)
|
|
905
|
+
} else if (tokenType === 'fence') {
|
|
906
|
+
resetRangeState(rRange, n)
|
|
907
|
+
resetCaptionState(rCaption)
|
|
908
|
+
resetSpecialState(rSp)
|
|
909
|
+
detection = detectFenceToken(token, n, rCaption)
|
|
910
|
+
} else if (blockType) {
|
|
911
|
+
resetRangeState(rRange, n)
|
|
912
|
+
resetCaptionState(rCaption)
|
|
913
|
+
resetSpecialState(rSp)
|
|
914
|
+
detection = detectCheckTypeOpen(tokens, token, n, rCaption, blockType)
|
|
915
|
+
}
|
|
787
916
|
|
|
788
917
|
if (!detection) {
|
|
789
918
|
if (containerType === 'blockquote') {
|
|
790
|
-
|
|
919
|
+
const closeIndex = figureWithCaptionCore(tokens, opt, fNum, figureNumberState, fallbackLabelState, TokenConstructor, captionState, containerType, n + 1)
|
|
791
920
|
n = (typeof closeIndex === 'number' ? closeIndex : n) + 1
|
|
792
921
|
} else {
|
|
793
922
|
n++
|
|
@@ -797,8 +926,8 @@ const figureWithCaptionCore = (tokens, opt, fNum, figureNumberState, fallbackLab
|
|
|
797
926
|
|
|
798
927
|
rRange.end = detection.en
|
|
799
928
|
|
|
800
|
-
rSp.figureClassName = resolveFigureClassName(detection.tagName,
|
|
801
|
-
checkCaption(tokens, rRange.start, rRange.end, rCaption, fNum, rSp, opt,
|
|
929
|
+
rSp.figureClassName = resolveFigureClassName(detection.tagName, rSp, opt)
|
|
930
|
+
checkCaption(tokens, rRange.start, rRange.end, rCaption, fNum, rSp, opt, captionState)
|
|
802
931
|
applyCaptionDrivenFigureClass(rCaption, rSp, opt)
|
|
803
932
|
|
|
804
933
|
let hasCaption = rCaption.isPrev || rCaption.isNext
|
|
@@ -813,7 +942,7 @@ const figureWithCaptionCore = (tokens, opt, fNum, figureNumberState, fallbackLab
|
|
|
813
942
|
if (detection.canWrap === false) {
|
|
814
943
|
let nextIndex = rRange.end + 1
|
|
815
944
|
if (containerType === 'blockquote') {
|
|
816
|
-
const closeIndex = figureWithCaptionCore(tokens, opt, fNum, figureNumberState, fallbackLabelState, TokenConstructor, containerType, rRange.start + 1)
|
|
945
|
+
const closeIndex = figureWithCaptionCore(tokens, opt, fNum, figureNumberState, fallbackLabelState, TokenConstructor, captionState, containerType, rRange.start + 1)
|
|
817
946
|
nextIndex = Math.max(nextIndex, (typeof closeIndex === 'number' ? closeIndex : rRange.end) + 1)
|
|
818
947
|
}
|
|
819
948
|
n = nextIndex
|
|
@@ -825,13 +954,8 @@ const figureWithCaptionCore = (tokens, opt, fNum, figureNumberState, fallbackLab
|
|
|
825
954
|
shouldWrap = detection.canWrap !== false && (hasCaption || detection.wrapWithoutCaption)
|
|
826
955
|
} else if (detection.type === 'image') {
|
|
827
956
|
shouldWrap = detection.canWrap !== false && (hasCaption || detection.wrapWithoutCaption)
|
|
828
|
-
if (
|
|
829
|
-
|
|
830
|
-
if (isInTightList) {
|
|
831
|
-
shouldWrap = false
|
|
832
|
-
} else if (!hasCaption && !opt.oneImageWithoutCaption) {
|
|
833
|
-
shouldWrap = false
|
|
834
|
-
}
|
|
957
|
+
if (token.hidden === true) {
|
|
958
|
+
shouldWrap = false
|
|
835
959
|
}
|
|
836
960
|
} else {
|
|
837
961
|
shouldWrap = detection.canWrap !== false && hasCaption
|
|
@@ -845,7 +969,7 @@ const figureWithCaptionCore = (tokens, opt, fNum, figureNumberState, fallbackLab
|
|
|
845
969
|
rRange.start += insertedLength
|
|
846
970
|
rRange.end += insertedLength
|
|
847
971
|
n += insertedLength
|
|
848
|
-
checkCaption(tokens, rRange.start, rRange.end, rCaption, fNum, rSp, opt,
|
|
972
|
+
checkCaption(tokens, rRange.start, rRange.end, rCaption, fNum, rSp, opt, captionState)
|
|
849
973
|
applyCaptionDrivenFigureClass(rCaption, rSp, opt)
|
|
850
974
|
}
|
|
851
975
|
ensureAutoFigureNumbering(tokens, rRange, rCaption, figureNumberState, opt)
|
|
@@ -853,15 +977,19 @@ const figureWithCaptionCore = (tokens, opt, fNum, figureNumberState, fallbackLab
|
|
|
853
977
|
}
|
|
854
978
|
|
|
855
979
|
let nextIndex
|
|
856
|
-
if (!rCaption.
|
|
857
|
-
|
|
980
|
+
if (!rCaption.isPrev && !rCaption.isNext) {
|
|
981
|
+
if (shouldWrap && detection.type === 'html') {
|
|
982
|
+
nextIndex = rRange.end + 1
|
|
983
|
+
} else {
|
|
984
|
+
nextIndex = n + 1
|
|
985
|
+
}
|
|
858
986
|
} else {
|
|
859
987
|
const en = rRange.end
|
|
860
988
|
if (rCaption.isPrev) {
|
|
861
989
|
changePrevCaptionPosition(tokens, rRange.start, rCaption, opt)
|
|
862
990
|
nextIndex = en + 1
|
|
863
991
|
} else if (rCaption.isNext) {
|
|
864
|
-
changeNextCaptionPosition(tokens, en, rCaption)
|
|
992
|
+
changeNextCaptionPosition(tokens, en, rCaption, opt)
|
|
865
993
|
nextIndex = en + 4
|
|
866
994
|
} else {
|
|
867
995
|
nextIndex = en + 1
|
|
@@ -869,7 +997,7 @@ const figureWithCaptionCore = (tokens, opt, fNum, figureNumberState, fallbackLab
|
|
|
869
997
|
}
|
|
870
998
|
|
|
871
999
|
if (containerType === 'blockquote') {
|
|
872
|
-
const closeIndex = figureWithCaptionCore(tokens, opt, fNum, figureNumberState, fallbackLabelState, TokenConstructor, containerType, rRange.start + 1)
|
|
1000
|
+
const closeIndex = figureWithCaptionCore(tokens, opt, fNum, figureNumberState, fallbackLabelState, TokenConstructor, captionState, containerType, rRange.start + 1)
|
|
873
1001
|
const fallbackIndex = rCaption.name ? rRange.end : n
|
|
874
1002
|
nextIndex = Math.max(nextIndex, (typeof closeIndex === 'number' ? closeIndex : fallbackIndex) + 1)
|
|
875
1003
|
}
|
|
@@ -879,42 +1007,12 @@ const figureWithCaptionCore = (tokens, opt, fNum, figureNumberState, fallbackLab
|
|
|
879
1007
|
return tokens.length
|
|
880
1008
|
}
|
|
881
1009
|
|
|
882
|
-
const isInListItem = (() => {
|
|
883
|
-
const cache = new WeakMap()
|
|
884
|
-
return (tokens, idx) => {
|
|
885
|
-
if (cache.has(tokens)) {
|
|
886
|
-
const cachedResult = cache.get(tokens)
|
|
887
|
-
if (cachedResult[idx] !== undefined) {
|
|
888
|
-
return cachedResult[idx]
|
|
889
|
-
}
|
|
890
|
-
} else {
|
|
891
|
-
cache.set(tokens, {})
|
|
892
|
-
}
|
|
893
|
-
|
|
894
|
-
const result = cache.get(tokens)
|
|
895
|
-
|
|
896
|
-
for (let i = idx - 1; i >= 0; i--) {
|
|
897
|
-
if (tokens[i].type === 'list_item_open') {
|
|
898
|
-
result[idx] = true
|
|
899
|
-
return true
|
|
900
|
-
}
|
|
901
|
-
if (tokens[i].type === 'list_item_close' || tokens[i].type === 'list_open') {
|
|
902
|
-
result[idx] = false
|
|
903
|
-
return false
|
|
904
|
-
}
|
|
905
|
-
}
|
|
906
|
-
|
|
907
|
-
result[idx] = false
|
|
908
|
-
return false
|
|
909
|
-
}
|
|
910
|
-
})()
|
|
911
|
-
|
|
912
1010
|
const mditFigureWithPCaption = (md, option) => {
|
|
913
1011
|
let opt = {
|
|
914
1012
|
// --- figure-wrapper behavior ---
|
|
915
1013
|
classPrefix: 'f',
|
|
916
|
-
figureClassThatWrapsIframeTypeBlockquote:
|
|
917
|
-
figureClassThatWrapsSlides:
|
|
1014
|
+
figureClassThatWrapsIframeTypeBlockquote: null,
|
|
1015
|
+
figureClassThatWrapsSlides: null,
|
|
918
1016
|
styleProcess : true,
|
|
919
1017
|
oneImageWithoutCaption: false,
|
|
920
1018
|
iframeWithoutCaption: false,
|
|
@@ -932,6 +1030,10 @@ const mditFigureWithPCaption = (md, option) => {
|
|
|
932
1030
|
autoAltCaption: false, // allow alt text (when matching markReg.img or fallback) to build captions automatically
|
|
933
1031
|
autoTitleCaption: false, // same as above but reads from the title attribute when alt isn't usable
|
|
934
1032
|
|
|
1033
|
+
// --- label prefix marker helpers ---
|
|
1034
|
+
labelPrefixMarker: null, // optional leading marker(s) before label, e.g. '*' or ['*', '>']
|
|
1035
|
+
allowLabelPrefixMarkerWithoutLabel: false, // when true, reuse labelPrefixMarker for marker-only captions (array uses [prev, next])
|
|
1036
|
+
|
|
935
1037
|
// --- numbering controls ---
|
|
936
1038
|
autoLabelNumber: false, // shorthand for enabling numbering for both img/table unless autoLabelNumberSets is provided explicitly
|
|
937
1039
|
autoLabelNumberSets: [], // preferred; supports ['img'], ['table'], or both
|
|
@@ -949,6 +1051,8 @@ const mditFigureWithPCaption = (md, option) => {
|
|
|
949
1051
|
wrapCaptionBody: false,
|
|
950
1052
|
}
|
|
951
1053
|
const hasExplicitAutoLabelNumberSets = option && Object.prototype.hasOwnProperty.call(option, 'autoLabelNumberSets')
|
|
1054
|
+
const hasExplicitFigureClassThatWrapsIframeTypeBlockquote = option && Object.prototype.hasOwnProperty.call(option, 'figureClassThatWrapsIframeTypeBlockquote')
|
|
1055
|
+
const hasExplicitFigureClassThatWrapsSlides = option && Object.prototype.hasOwnProperty.call(option, 'figureClassThatWrapsSlides')
|
|
952
1056
|
if (option) Object.assign(opt, option)
|
|
953
1057
|
// Normalize option shorthands now so downstream logic works with a consistent { img, table } shape.
|
|
954
1058
|
opt.autoLabelNumberSets = normalizeAutoLabelNumberSets(opt.autoLabelNumberSets)
|
|
@@ -956,8 +1060,27 @@ const mditFigureWithPCaption = (md, option) => {
|
|
|
956
1060
|
opt.autoLabelNumberSets.img = true
|
|
957
1061
|
opt.autoLabelNumberSets.table = true
|
|
958
1062
|
}
|
|
959
|
-
|
|
1063
|
+
const classPrefix = buildClassPrefix(opt.classPrefix)
|
|
1064
|
+
opt.figureClassPrefix = classPrefix
|
|
1065
|
+
opt.captionClassPrefix = classPrefix
|
|
1066
|
+
if (!hasExplicitFigureClassThatWrapsIframeTypeBlockquote) {
|
|
1067
|
+
opt.figureClassThatWrapsIframeTypeBlockquote = classPrefix + 'img'
|
|
1068
|
+
}
|
|
1069
|
+
if (!hasExplicitFigureClassThatWrapsSlides) {
|
|
1070
|
+
opt.figureClassThatWrapsSlides = classPrefix + 'slide'
|
|
1071
|
+
}
|
|
1072
|
+
// Precompute label-class permutations so numbering lookup doesn't rebuild arrays per caption.
|
|
960
1073
|
opt.labelClassLookup = buildLabelClassLookup(opt)
|
|
1074
|
+
const markerList = normalizeLabelPrefixMarkers(opt.labelPrefixMarker)
|
|
1075
|
+
opt.labelPrefixMarkerReg = buildLabelPrefixMarkerRegFromList(markerList)
|
|
1076
|
+
if (opt.allowLabelPrefixMarkerWithoutLabel === true) {
|
|
1077
|
+
const markerPair = resolveLabelPrefixMarkerPair(markerList)
|
|
1078
|
+
opt.labelPrefixMarkerWithoutLabelPrevReg = buildLabelPrefixMarkerRegFromList(markerPair.prev)
|
|
1079
|
+
opt.labelPrefixMarkerWithoutLabelNextReg = buildLabelPrefixMarkerRegFromList(markerPair.next)
|
|
1080
|
+
} else {
|
|
1081
|
+
opt.labelPrefixMarkerWithoutLabelPrevReg = null
|
|
1082
|
+
opt.labelPrefixMarkerWithoutLabelNextReg = null
|
|
1083
|
+
}
|
|
961
1084
|
|
|
962
1085
|
//If nextCaption has `{}` style and `f-img-multipleImages`, when upgraded to markdown-it-attrs@4.2.0, the existing script will have `{}` style on nextCaption. Therefore, since markdown-it-attrs is md.core.ruler.before('linkify'), figure_with_caption will be processed after it.
|
|
963
1086
|
md.core.ruler.before('replacements', 'figure_with_caption', (state) => {
|