@peaceroad/markdown-it-figure-with-p-caption 0.18.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.
- package/README.md +259 -471
- package/caption-numbering/counter-series.js +62 -0
- package/caption-numbering/number-codec.js +101 -0
- package/caption-numbering/options.js +101 -0
- package/caption-numbering/scope.js +466 -0
- package/caption-numbering.js +12 -0
- package/docs/examples.md +571 -0
- package/docs/numbering.md +215 -0
- package/docs/reference.md +148 -0
- package/embeds/detect.js +94 -68
- package/embeds/providers.js +0 -1
- package/index.js +459 -385
- package/package.json +18 -10
package/index.js
CHANGED
|
@@ -1,27 +1,52 @@
|
|
|
1
1
|
import {
|
|
2
|
+
analyzeCaptionParagraph,
|
|
2
3
|
analyzeCaptionStart,
|
|
3
|
-
|
|
4
|
+
applyCaptionParagraph,
|
|
4
5
|
buildLabelPrefixMarkerRegFromMarkers,
|
|
6
|
+
canonicalizeCaptionNumberingMark,
|
|
7
|
+
createCaptionNumberingPolicy,
|
|
8
|
+
createCaptionNumberingRuntime,
|
|
5
9
|
getGeneratedLabelDefaults,
|
|
10
|
+
normalizeAutoLabelNumberSets,
|
|
6
11
|
normalizeLabelPrefixMarkers,
|
|
7
12
|
setCaptionParagraph,
|
|
8
13
|
getMarkRegStateForLanguages,
|
|
9
14
|
stripLabelPrefixMarker,
|
|
10
15
|
} from 'p7d-markdown-it-p-captions'
|
|
11
|
-
import { detectHtmlFigureCandidate } from './embeds/detect.js'
|
|
16
|
+
import { applyHtmlFigureTransform, detectHtmlFigureCandidate } from './embeds/detect.js'
|
|
17
|
+
import {
|
|
18
|
+
createFigureCaptionCounterKeyResolverFromMarkRegState,
|
|
19
|
+
} from './caption-numbering/counter-series.js'
|
|
20
|
+
import {
|
|
21
|
+
createUnscopedNumberingContext,
|
|
22
|
+
formatFigureCaptionGeneratedNumberUnchecked,
|
|
23
|
+
getCaptionNumberingContext,
|
|
24
|
+
parseFigureCaptionExplicitNumberUnchecked,
|
|
25
|
+
} from './caption-numbering/number-codec.js'
|
|
26
|
+
import {
|
|
27
|
+
getFigureCaptionNumberingPolicyState,
|
|
28
|
+
normalizeFigureCaptionNumberingPolicy,
|
|
29
|
+
} from './caption-numbering/options.js'
|
|
30
|
+
import {
|
|
31
|
+
createFigureCaptionScopeRuntime,
|
|
32
|
+
getFigureCaptionScopeNestedContainerType,
|
|
33
|
+
updateFigureCaptionScopeFromHeading,
|
|
34
|
+
} from './caption-numbering/scope.js'
|
|
12
35
|
|
|
13
36
|
const imageAttrsReg = /^ *\{(.*?)\} *$/
|
|
14
|
-
const classAttrReg = /^\./
|
|
15
|
-
const idAttrReg = /^#/
|
|
16
37
|
const sampLangReg = /^ *(?:samp|shell|console)(?:(?= )|$)/
|
|
17
38
|
const asciiLabelReg = /^[A-Za-z]/
|
|
18
39
|
const attrNameReg = /^[^\s=]+$/
|
|
19
|
-
const labelTrailingJointReg = /[.\u3002\uff0e
|
|
40
|
+
const labelTrailingJointReg = /[.\u3002\uff0e::\u3000]\s*$/
|
|
41
|
+
const installedKey = Symbol.for('p7d-markdown-it-figure-with-p-caption.installed')
|
|
20
42
|
const CHECK_TYPE_TOKEN_MAP = {
|
|
21
43
|
table_open: 'table',
|
|
22
44
|
pre_open: 'pre',
|
|
23
45
|
blockquote_open: 'blockquote',
|
|
24
46
|
}
|
|
47
|
+
const hasOwnOption = (option, name) => !!(
|
|
48
|
+
option && Object.prototype.hasOwnProperty.call(option, name)
|
|
49
|
+
)
|
|
25
50
|
const escapeRegExp = (value) => value.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')
|
|
26
51
|
const normalizeLanguageCode = (value) => {
|
|
27
52
|
if (value === null || value === undefined) return ''
|
|
@@ -31,11 +56,10 @@ const normalizeLanguageCode = (value) => {
|
|
|
31
56
|
return separatorIndex === -1 ? normalized : normalized.slice(0, separatorIndex)
|
|
32
57
|
}
|
|
33
58
|
const appendAvailableLanguage = (target, lang, availableLanguages) => {
|
|
34
|
-
if (!lang) return
|
|
35
|
-
if (availableLanguages.indexOf(lang) === -1) return
|
|
36
|
-
if (target.indexOf(lang) !== -1) return
|
|
59
|
+
if (!lang) return
|
|
60
|
+
if (availableLanguages.indexOf(lang) === -1) return
|
|
61
|
+
if (target.indexOf(lang) !== -1) return
|
|
37
62
|
target.push(lang)
|
|
38
|
-
return true
|
|
39
63
|
}
|
|
40
64
|
const normalizePreferredLanguages = (value, availableLanguages) => {
|
|
41
65
|
if (!Array.isArray(availableLanguages) || availableLanguages.length === 0) return []
|
|
@@ -100,31 +124,30 @@ const isHyphenFenceLine = (src, lineStart) => {
|
|
|
100
124
|
if (index >= src.length || src.charCodeAt(index) !== 0x0a) return 0
|
|
101
125
|
return hyphenCount
|
|
102
126
|
}
|
|
103
|
-
const
|
|
104
|
-
if (typeof src !== 'string' || isHyphenFenceLine(src, 0) === 0) return
|
|
127
|
+
const getBodyStartAfterLeadingFrontmatter = (src) => {
|
|
128
|
+
if (typeof src !== 'string' || isHyphenFenceLine(src, 0) === 0) return 0
|
|
105
129
|
let lineStart = src.indexOf('\n')
|
|
106
|
-
if (lineStart === -1) return
|
|
130
|
+
if (lineStart === -1) return 0
|
|
107
131
|
lineStart++
|
|
108
132
|
while (lineStart < src.length) {
|
|
109
133
|
if (isHyphenFenceLine(src, lineStart) > 0) {
|
|
110
134
|
const nextLineStart = src.indexOf('\n', lineStart)
|
|
111
|
-
|
|
112
|
-
return src.slice(nextLineStart + 1)
|
|
135
|
+
return nextLineStart === -1 ? src.length : nextLineStart + 1
|
|
113
136
|
}
|
|
114
137
|
const nextLineStart = src.indexOf('\n', lineStart)
|
|
115
138
|
if (nextLineStart === -1) break
|
|
116
139
|
lineStart = nextLineStart + 1
|
|
117
140
|
}
|
|
118
|
-
return
|
|
141
|
+
return 0
|
|
119
142
|
}
|
|
120
143
|
const detectDocumentPrimaryLanguage = (src, availableLanguages) => {
|
|
121
144
|
if (!src || availableLanguages.indexOf('ja') === -1) return ''
|
|
122
|
-
const
|
|
123
|
-
const limit = Math.min(
|
|
145
|
+
const bodyStart = getBodyStartAfterLeadingFrontmatter(src)
|
|
146
|
+
const limit = Math.min(src.length, bodyStart + 8192)
|
|
124
147
|
let japaneseCount = 0
|
|
125
148
|
let asciiAlphaCount = 0
|
|
126
|
-
for (let i =
|
|
127
|
-
const code =
|
|
149
|
+
for (let i = bodyStart; i < limit; i++) {
|
|
150
|
+
const code = src.charCodeAt(i)
|
|
128
151
|
if (isJapaneseCharCode(code)) {
|
|
129
152
|
japaneseCount++
|
|
130
153
|
continue
|
|
@@ -137,10 +160,6 @@ const detectDocumentPrimaryLanguage = (src, availableLanguages) => {
|
|
|
137
160
|
if (asciiAlphaCount === 0) return 'ja'
|
|
138
161
|
return japaneseCount * 2 >= asciiAlphaCount ? 'ja' : ''
|
|
139
162
|
}
|
|
140
|
-
const sourceMayNeedPreferredLanguages = (state) => {
|
|
141
|
-
const src = state && typeof state.src === 'string' ? state.src : ''
|
|
142
|
-
return src.indexOf('![') !== -1
|
|
143
|
-
}
|
|
144
163
|
const resolvePreferredLanguagesForState = (state, opt) => {
|
|
145
164
|
const availableLanguages = (
|
|
146
165
|
opt &&
|
|
@@ -149,10 +168,7 @@ const resolvePreferredLanguagesForState = (state, opt) => {
|
|
|
149
168
|
) ? opt.markRegState.languages : []
|
|
150
169
|
if (availableLanguages.length === 0) return []
|
|
151
170
|
|
|
152
|
-
const
|
|
153
|
-
? opt.normalizedOptionLanguages
|
|
154
|
-
: []
|
|
155
|
-
const baseLanguages = optionLanguages.length > 0 ? optionLanguages : availableLanguages
|
|
171
|
+
const baseLanguages = availableLanguages
|
|
156
172
|
const env = state && state.env ? state.env : null
|
|
157
173
|
|
|
158
174
|
const envLocale = normalizeLanguageCode(env && env.locale)
|
|
@@ -190,18 +206,15 @@ const resolvePreferredLanguagesForState = (state, opt) => {
|
|
|
190
206
|
}
|
|
191
207
|
const needsPreferredLanguagesResolution = (opt) => {
|
|
192
208
|
if (!opt || !opt.markRegState || !Array.isArray(opt.markRegState.languages)) return false
|
|
209
|
+
if (!opt.autoCaptionDetection) return false
|
|
193
210
|
if (opt.markRegState.languages.length <= 1) return false
|
|
194
211
|
return opt.autoAltCaption === true || opt.autoTitleCaption === true
|
|
195
212
|
}
|
|
196
213
|
const normalizeOptionalClassName = (value) => {
|
|
197
214
|
if (value === null || value === undefined) return ''
|
|
198
|
-
|
|
199
|
-
return normalized || ''
|
|
200
|
-
}
|
|
201
|
-
const buildClassPrefix = (value) => {
|
|
202
|
-
const normalized = normalizeOptionalClassName(value)
|
|
203
|
-
return normalized ? normalized + '-' : ''
|
|
215
|
+
return String(value).trim()
|
|
204
216
|
}
|
|
217
|
+
const buildClassPrefix = (normalized) => normalized ? normalized + '-' : ''
|
|
205
218
|
const normalizeClassOptionWithFallback = (value, fallbackValue) => {
|
|
206
219
|
const normalized = normalizeOptionalClassName(value)
|
|
207
220
|
return normalized || fallbackValue
|
|
@@ -283,10 +296,11 @@ const parseImageAttrs = (raw) => {
|
|
|
283
296
|
for (let i = 0; i < parts.length; i++) {
|
|
284
297
|
let entry = parts[i]
|
|
285
298
|
if (!entry) continue
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
299
|
+
const firstCode = entry.charCodeAt(0)
|
|
300
|
+
if (firstCode === 0x2e) {
|
|
301
|
+
entry = 'class=' + entry.slice(1)
|
|
302
|
+
} else if (firstCode === 0x23) {
|
|
303
|
+
entry = 'id=' + entry.slice(1)
|
|
290
304
|
}
|
|
291
305
|
const equalIndex = entry.indexOf('=')
|
|
292
306
|
if (equalIndex === -1) {
|
|
@@ -301,22 +315,50 @@ const parseImageAttrs = (raw) => {
|
|
|
301
315
|
return attrs
|
|
302
316
|
}
|
|
303
317
|
|
|
304
|
-
const
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
const
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
318
|
+
const getEnabledCaptionNumberingMarks = (sets, opt) => {
|
|
319
|
+
if (!Array.isArray(sets) || sets.length === 0) return []
|
|
320
|
+
const exceptMarks = opt && Array.isArray(opt.removeUnnumberedLabelExceptMarks)
|
|
321
|
+
? opt.removeUnnumberedLabelExceptMarks
|
|
322
|
+
: []
|
|
323
|
+
if (!opt || !opt.removeUnnumberedLabel) return sets
|
|
324
|
+
return sets.filter(mark => exceptMarks.indexOf(mark) !== -1)
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
const createFigureCaptionNumberingPolicy = (enabledMarks, advancedPolicy, markRegState) => {
|
|
328
|
+
if (enabledMarks.length === 0) return null
|
|
329
|
+
const resolveCounterKey = createFigureCaptionCounterKeyResolverFromMarkRegState(markRegState)
|
|
330
|
+
const getCounterKey = ({ captionDecision }) => resolveCounterKey(captionDecision)
|
|
331
|
+
if (!advancedPolicy) {
|
|
332
|
+
return createCaptionNumberingPolicy({
|
|
333
|
+
enabledMarks,
|
|
334
|
+
explicitCounter: 'max',
|
|
335
|
+
generatedNumberHasNumClass: false,
|
|
336
|
+
getCounterKey,
|
|
337
|
+
})
|
|
338
|
+
}
|
|
339
|
+
return createCaptionNumberingPolicy({
|
|
340
|
+
enabledMarks,
|
|
341
|
+
explicitCounter: 'max',
|
|
342
|
+
generatedNumberHasNumClass: false,
|
|
343
|
+
getCounterKey,
|
|
344
|
+
getSequenceKey({ captionContext }) {
|
|
345
|
+
return getCaptionNumberingContext(captionContext).sequenceKey
|
|
346
|
+
},
|
|
347
|
+
// p-captions resolves getSequenceKey first, so the following callbacks can
|
|
348
|
+
// reuse that already-branded context without a second WeakSet lookup.
|
|
349
|
+
parseExplicitNumber({ number, captionContext }) {
|
|
350
|
+
return parseFigureCaptionExplicitNumberUnchecked(
|
|
351
|
+
number,
|
|
352
|
+
captionContext && captionContext.numbering,
|
|
353
|
+
)
|
|
354
|
+
},
|
|
355
|
+
formatGeneratedNumber({ sequence, captionContext }) {
|
|
356
|
+
return formatFigureCaptionGeneratedNumberUnchecked(
|
|
357
|
+
sequence,
|
|
358
|
+
captionContext && captionContext.numbering,
|
|
359
|
+
)
|
|
360
|
+
},
|
|
361
|
+
})
|
|
320
362
|
}
|
|
321
363
|
|
|
322
364
|
const isOnlySpacesText = (token) => {
|
|
@@ -418,7 +460,24 @@ const buildCaptionWithFallback = (text, fallbackOption, mark, markRegState, pref
|
|
|
418
460
|
return label + getFallbackStringLabelJoint(label) + trimmedText
|
|
419
461
|
}
|
|
420
462
|
|
|
463
|
+
const resolveCaptionPreferredLanguages = (captionState, opt) => {
|
|
464
|
+
const renderState = captionState.preferredLanguageState
|
|
465
|
+
if (!renderState) return captionState.preferredLanguages
|
|
466
|
+
captionState.preferredLanguages = resolvePreferredLanguagesForState(renderState, opt)
|
|
467
|
+
captionState.preferredLanguageState = null
|
|
468
|
+
return captionState.preferredLanguages
|
|
469
|
+
}
|
|
470
|
+
|
|
421
471
|
const validateFallbackCaptionLabelOption = (optionName, fallbackOption, markRegState) => {
|
|
472
|
+
if (
|
|
473
|
+
fallbackOption !== undefined &&
|
|
474
|
+
fallbackOption !== null &&
|
|
475
|
+
fallbackOption !== false &&
|
|
476
|
+
fallbackOption !== true &&
|
|
477
|
+
typeof fallbackOption !== 'string'
|
|
478
|
+
) {
|
|
479
|
+
throw new TypeError(`${optionName} must be false, true, a string label, or null.`)
|
|
480
|
+
}
|
|
422
481
|
if (typeof fallbackOption !== 'string') return
|
|
423
482
|
const sampleCaption = buildCaptionWithFallback('caption', fallbackOption, 'img', markRegState, null)
|
|
424
483
|
const analysis = analyzeCaptionStart(sampleCaption, {
|
|
@@ -444,121 +503,6 @@ const createAutoCaptionParagraph = (captionText, TokenConstructor) => {
|
|
|
444
503
|
return [paragraphOpen, inlineToken, paragraphClose]
|
|
445
504
|
}
|
|
446
505
|
|
|
447
|
-
const getCaptionInlineToken = (tokens, range, caption) => {
|
|
448
|
-
if (caption.isPrev) {
|
|
449
|
-
const inlineIndex = range.start - 2
|
|
450
|
-
if (inlineIndex >= 0) return tokens[inlineIndex]
|
|
451
|
-
} else if (caption.isNext) {
|
|
452
|
-
return tokens[range.end + 2]
|
|
453
|
-
}
|
|
454
|
-
return null
|
|
455
|
-
}
|
|
456
|
-
|
|
457
|
-
const hasClassName = (classAttr, className) => {
|
|
458
|
-
if (!classAttr || !className) return false
|
|
459
|
-
let index = 0
|
|
460
|
-
while (index < classAttr.length) {
|
|
461
|
-
index = classAttr.indexOf(className, index)
|
|
462
|
-
if (index === -1) return false
|
|
463
|
-
const end = index + className.length
|
|
464
|
-
const beforeBoundary = index === 0 || classAttr.charCodeAt(index - 1) <= 0x20
|
|
465
|
-
const afterBoundary = end >= classAttr.length || classAttr.charCodeAt(end) <= 0x20
|
|
466
|
-
if (beforeBoundary && afterBoundary) return true
|
|
467
|
-
index = end
|
|
468
|
-
}
|
|
469
|
-
return false
|
|
470
|
-
}
|
|
471
|
-
|
|
472
|
-
const hasAnyClassName = (classAttr, classNames) => {
|
|
473
|
-
for (let i = 0; i < classNames.length; i++) {
|
|
474
|
-
if (hasClassName(classAttr, classNames[i])) return true
|
|
475
|
-
}
|
|
476
|
-
return false
|
|
477
|
-
}
|
|
478
|
-
|
|
479
|
-
const getInlineLabelTextToken = (inlineToken, type, opt) => {
|
|
480
|
-
if (!inlineToken || !inlineToken.children) return null
|
|
481
|
-
const children = inlineToken.children
|
|
482
|
-
const classNames = opt.labelClassLookup[type] || opt.labelClassLookup.default
|
|
483
|
-
for (let i = 0; i < children.length; i++) {
|
|
484
|
-
const child = children[i]
|
|
485
|
-
if (!child || !child.attrs) continue
|
|
486
|
-
const classAttr = getTokenAttr(child, 'class')
|
|
487
|
-
if (!classAttr) continue
|
|
488
|
-
if (!hasAnyClassName(classAttr, classNames)) continue
|
|
489
|
-
const textToken = children[i + 1]
|
|
490
|
-
if (textToken && textToken.type === 'text') {
|
|
491
|
-
return textToken
|
|
492
|
-
}
|
|
493
|
-
}
|
|
494
|
-
return null
|
|
495
|
-
}
|
|
496
|
-
|
|
497
|
-
const updateInlineTokenContent = (inlineToken, originalText, newText) => {
|
|
498
|
-
if (!inlineToken || typeof inlineToken.content !== 'string') return
|
|
499
|
-
if (!originalText) return
|
|
500
|
-
const index = inlineToken.content.indexOf(originalText)
|
|
501
|
-
if (index === -1) return
|
|
502
|
-
inlineToken.content =
|
|
503
|
-
inlineToken.content.slice(0, index) +
|
|
504
|
-
newText +
|
|
505
|
-
inlineToken.content.slice(index + originalText.length)
|
|
506
|
-
}
|
|
507
|
-
|
|
508
|
-
const parseTrailingPositiveInteger = (text) => {
|
|
509
|
-
if (typeof text !== 'string' || text.length === 0) return null
|
|
510
|
-
let end = text.length - 1
|
|
511
|
-
while (end >= 0 && text.charCodeAt(end) === 0x20) end--
|
|
512
|
-
if (end < 0) return null
|
|
513
|
-
const lastCode = text.charCodeAt(end)
|
|
514
|
-
if (lastCode < 0x30 || lastCode > 0x39) return null
|
|
515
|
-
let start = end
|
|
516
|
-
while (start >= 0) {
|
|
517
|
-
const code = text.charCodeAt(start)
|
|
518
|
-
if (code < 0x30 || code > 0x39) break
|
|
519
|
-
start--
|
|
520
|
-
}
|
|
521
|
-
let value = 0
|
|
522
|
-
let digitBase = 1
|
|
523
|
-
for (let i = end; i > start; i--) {
|
|
524
|
-
value += (text.charCodeAt(i) - 0x30) * digitBase
|
|
525
|
-
digitBase *= 10
|
|
526
|
-
}
|
|
527
|
-
return value
|
|
528
|
-
}
|
|
529
|
-
|
|
530
|
-
const ensureAutoFigureNumbering = (tokens, range, caption, figureNumberState, opt) => {
|
|
531
|
-
const captionType = caption.name === 'img' ? 'img' : (caption.name === 'table' ? 'table' : '')
|
|
532
|
-
if (!captionType) return
|
|
533
|
-
if (!shouldApplyLabelNumbering(captionType, opt)) return
|
|
534
|
-
const inlineToken = getCaptionInlineToken(tokens, range, caption)
|
|
535
|
-
if (!inlineToken) return
|
|
536
|
-
const labelTextToken = getInlineLabelTextToken(inlineToken, captionType, opt)
|
|
537
|
-
if (!labelTextToken || typeof labelTextToken.content !== 'string') return
|
|
538
|
-
const originalText = labelTextToken.content
|
|
539
|
-
let end = originalText.length - 1
|
|
540
|
-
while (end >= 0 && originalText.charCodeAt(end) === 0x20) end--
|
|
541
|
-
if (end >= 0) {
|
|
542
|
-
const code = originalText.charCodeAt(end)
|
|
543
|
-
if (code >= 0x30 && code <= 0x39) {
|
|
544
|
-
const explicitValue = parseTrailingPositiveInteger(originalText)
|
|
545
|
-
if (explicitValue !== null) {
|
|
546
|
-
if (explicitValue > (figureNumberState[captionType] || 0)) {
|
|
547
|
-
figureNumberState[captionType] = explicitValue
|
|
548
|
-
}
|
|
549
|
-
return
|
|
550
|
-
}
|
|
551
|
-
}
|
|
552
|
-
}
|
|
553
|
-
figureNumberState[captionType] = (figureNumberState[captionType] || 0) + 1
|
|
554
|
-
const baseLabel = originalText.trim()
|
|
555
|
-
if (!baseLabel) return
|
|
556
|
-
const joint = asciiLabelReg.test(baseLabel) ? ' ' : ''
|
|
557
|
-
const newLabelText = baseLabel + joint + figureNumberState[captionType]
|
|
558
|
-
labelTextToken.content = newLabelText
|
|
559
|
-
updateInlineTokenContent(inlineToken, originalText, newLabelText)
|
|
560
|
-
}
|
|
561
|
-
|
|
562
506
|
const matchAutoCaptionText = (text, opt, preferredMark = 'img') => {
|
|
563
507
|
if (!text || !opt || !opt.markRegState) return ''
|
|
564
508
|
const trimmed = text.trim()
|
|
@@ -571,89 +515,116 @@ const matchAutoCaptionText = (text, opt, preferredMark = 'img') => {
|
|
|
571
515
|
return ''
|
|
572
516
|
}
|
|
573
517
|
|
|
574
|
-
const getAutoCaptionFromImage = (imageToken, opt) => {
|
|
575
|
-
if (!opt.
|
|
576
|
-
if (!opt.autoAltCaption && !opt.autoTitleCaption && !(opt.markRegState && opt.markRegState.markReg && opt.markRegState.markReg.img)) return ''
|
|
518
|
+
const getAutoCaptionFromImage = (imageToken, opt, captionState) => {
|
|
519
|
+
if (!opt.autoAltCaption && !opt.autoTitleCaption && !(opt.markRegState && opt.markRegState.markReg && opt.markRegState.markReg.img)) return null
|
|
577
520
|
|
|
578
521
|
const altText = getImageAltText(imageToken)
|
|
579
522
|
let caption = matchAutoCaptionText(altText, opt)
|
|
580
523
|
if (caption) {
|
|
581
|
-
|
|
582
|
-
return caption
|
|
524
|
+
return { text: caption, source: 'alt' }
|
|
583
525
|
}
|
|
584
|
-
if (
|
|
585
|
-
const
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
}
|
|
590
|
-
caption = fallbackCaption
|
|
526
|
+
if (opt.autoAltCaption) {
|
|
527
|
+
const preferredLanguages = opt.autoAltCaption === true
|
|
528
|
+
? resolveCaptionPreferredLanguages(captionState, opt)
|
|
529
|
+
: captionState.preferredLanguages
|
|
530
|
+
caption = buildCaptionWithFallback(altText, opt.autoAltCaption, 'img', opt.markRegState, preferredLanguages)
|
|
591
531
|
}
|
|
592
|
-
if (caption) return caption
|
|
532
|
+
if (caption) return { text: caption, source: 'alt' }
|
|
593
533
|
|
|
594
534
|
const titleText = getImageTitleText(imageToken)
|
|
595
535
|
caption = matchAutoCaptionText(titleText, opt)
|
|
596
536
|
if (caption) {
|
|
597
|
-
|
|
598
|
-
return caption
|
|
537
|
+
return { text: caption, source: 'title' }
|
|
599
538
|
}
|
|
600
|
-
if (
|
|
601
|
-
const
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
539
|
+
if (opt.autoTitleCaption) {
|
|
540
|
+
const preferredLanguages = opt.autoTitleCaption === true
|
|
541
|
+
? resolveCaptionPreferredLanguages(captionState, opt)
|
|
542
|
+
: captionState.preferredLanguages
|
|
543
|
+
caption = buildCaptionWithFallback(titleText, opt.autoTitleCaption, 'img', opt.markRegState, preferredLanguages)
|
|
544
|
+
}
|
|
545
|
+
return caption ? { text: caption, source: 'title' } : null
|
|
546
|
+
}
|
|
547
|
+
|
|
548
|
+
const consumeAutoCaptionSource = (imageToken, autoCaption) => {
|
|
549
|
+
if (!imageToken || !autoCaption) return
|
|
550
|
+
if (autoCaption.source === 'alt') {
|
|
551
|
+
clearImageAltAttr(imageToken)
|
|
552
|
+
} else if (autoCaption.source === 'title') {
|
|
553
|
+
clearImageTitleAttr(imageToken)
|
|
607
554
|
}
|
|
608
|
-
|
|
555
|
+
}
|
|
556
|
+
|
|
557
|
+
const setFigureCaptionParagraph = (index, captionState, caption, sp, opt) => {
|
|
558
|
+
const needsCaptionDrivenClassBeforeApply = !!(
|
|
559
|
+
opt.labelClassFollowsFigure &&
|
|
560
|
+
caption.name === 'iframe' &&
|
|
561
|
+
!opt.allIframeTypeFigureClassName
|
|
562
|
+
)
|
|
563
|
+
if (!needsCaptionDrivenClassBeforeApply) {
|
|
564
|
+
return setCaptionParagraph(index, captionState, caption, captionState.numberingRuntime, sp, opt)
|
|
565
|
+
}
|
|
566
|
+
const decision = analyzeCaptionParagraph(index, captionState, {
|
|
567
|
+
captionName: caption.name,
|
|
568
|
+
isIframeTypeBlockquote: sp.isIframeTypeBlockquote,
|
|
569
|
+
isVideoIframe: sp.isVideoIframe,
|
|
570
|
+
}, opt)
|
|
571
|
+
if (!decision) return false
|
|
572
|
+
// Figure-following label classes need the final caption-driven wrapper class
|
|
573
|
+
// before p-captions constructs the label/body spans.
|
|
574
|
+
applyCaptionDrivenFigureClass(caption, sp, opt, decision)
|
|
575
|
+
return applyCaptionParagraph(
|
|
576
|
+
decision,
|
|
577
|
+
captionState,
|
|
578
|
+
sp,
|
|
579
|
+
captionState.numberingRuntime,
|
|
580
|
+
opt,
|
|
581
|
+
)
|
|
609
582
|
}
|
|
610
583
|
|
|
611
584
|
const checkPrevCaption = (tokens, n, caption, sp, opt, captionState) => {
|
|
612
|
-
if(n < 3) return
|
|
613
|
-
const captionStartToken = tokens[n-3]
|
|
614
|
-
const captionInlineToken = tokens[n-2]
|
|
615
|
-
const captionEndToken = tokens[n-1]
|
|
585
|
+
if (n < 3) return
|
|
586
|
+
const captionStartToken = tokens[n - 3]
|
|
587
|
+
const captionInlineToken = tokens[n - 2]
|
|
588
|
+
const captionEndToken = tokens[n - 1]
|
|
616
589
|
if (captionStartToken === undefined || captionEndToken === undefined) return
|
|
617
590
|
if (captionStartToken.type !== 'paragraph_open' || captionEndToken.type !== 'paragraph_close') return
|
|
618
|
-
|
|
591
|
+
setFigureCaptionParagraph(n - 3, captionState, caption, sp, opt)
|
|
619
592
|
const captionName = sp && sp.captionDecision ? sp.captionDecision.mark : ''
|
|
620
|
-
if(!captionName) {
|
|
593
|
+
if (!captionName) {
|
|
621
594
|
if (opt.labelPrefixMarkerWithoutLabelPrevReg) {
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
595
|
+
const markerMatch = getLabelPrefixMarkerMatch(captionInlineToken, opt.labelPrefixMarkerWithoutLabelPrevReg)
|
|
596
|
+
if (markerMatch) {
|
|
597
|
+
stripLabelPrefixMarker(captionInlineToken, markerMatch)
|
|
598
|
+
caption.isPrev = true
|
|
599
|
+
}
|
|
627
600
|
}
|
|
628
601
|
return
|
|
629
602
|
}
|
|
630
603
|
caption.name = captionName
|
|
631
604
|
caption.isPrev = true
|
|
632
|
-
return
|
|
633
605
|
}
|
|
634
606
|
|
|
635
607
|
const checkNextCaption = (tokens, en, caption, sp, opt, captionState) => {
|
|
636
|
-
if (en +
|
|
637
|
-
const captionStartToken = tokens[en+1]
|
|
638
|
-
const captionInlineToken = tokens[en+2]
|
|
639
|
-
const captionEndToken = tokens[en+3]
|
|
608
|
+
if (en + 3 >= tokens.length) return
|
|
609
|
+
const captionStartToken = tokens[en + 1]
|
|
610
|
+
const captionInlineToken = tokens[en + 2]
|
|
611
|
+
const captionEndToken = tokens[en + 3]
|
|
640
612
|
if (captionStartToken === undefined || captionEndToken === undefined) return
|
|
641
613
|
if (captionStartToken.type !== 'paragraph_open' || captionEndToken.type !== 'paragraph_close') return
|
|
642
|
-
|
|
614
|
+
setFigureCaptionParagraph(en + 1, captionState, caption, sp, opt)
|
|
643
615
|
const captionName = sp && sp.captionDecision ? sp.captionDecision.mark : ''
|
|
644
|
-
if(!captionName) {
|
|
616
|
+
if (!captionName) {
|
|
645
617
|
if (opt.labelPrefixMarkerWithoutLabelNextReg) {
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
618
|
+
const markerMatch = getLabelPrefixMarkerMatch(captionInlineToken, opt.labelPrefixMarkerWithoutLabelNextReg)
|
|
619
|
+
if (markerMatch) {
|
|
620
|
+
stripLabelPrefixMarker(captionInlineToken, markerMatch)
|
|
621
|
+
caption.isNext = true
|
|
622
|
+
}
|
|
651
623
|
}
|
|
652
624
|
return
|
|
653
625
|
}
|
|
654
626
|
caption.name = captionName
|
|
655
627
|
caption.isNext = true
|
|
656
|
-
return
|
|
657
628
|
}
|
|
658
629
|
|
|
659
630
|
const cleanCaptionTokenAttrs = (token, captionName, opt) => {
|
|
@@ -701,24 +672,26 @@ const resolveFigureClassName = (checkTokenTagName, sp, opt) => {
|
|
|
701
672
|
return className
|
|
702
673
|
}
|
|
703
674
|
|
|
704
|
-
const applyCaptionDrivenFigureClass = (caption, sp, opt) => {
|
|
675
|
+
const applyCaptionDrivenFigureClass = (caption, sp, opt, decision = sp && sp.captionDecision) => {
|
|
705
676
|
if (!sp) return
|
|
706
677
|
const figureClassForSlides = opt.figureClassThatWrapsSlides
|
|
707
678
|
if (!figureClassForSlides) return
|
|
708
|
-
const detectedMark = (
|
|
679
|
+
const detectedMark = (decision && decision.mark) || (caption && caption.name) || ''
|
|
709
680
|
if (detectedMark !== 'slide') return
|
|
710
681
|
if (opt.allIframeTypeFigureClassName && sp.figureClassName === opt.allIframeTypeFigureClassName) return
|
|
682
|
+
if (sp.figureClassName === figureClassForSlides) return
|
|
711
683
|
sp.figureClassName = figureClassForSlides
|
|
712
684
|
}
|
|
713
685
|
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
686
|
+
const convertCaptionTokens = (
|
|
687
|
+
captionStartToken,
|
|
688
|
+
captionInlineToken,
|
|
689
|
+
captionEndToken,
|
|
690
|
+
figureBaseLevel,
|
|
691
|
+
captionName,
|
|
692
|
+
opt,
|
|
693
|
+
) => {
|
|
694
|
+
cleanCaptionTokenAttrs(captionStartToken, captionName, opt)
|
|
722
695
|
captionStartToken.type = 'figcaption_open'
|
|
723
696
|
captionStartToken.tag = 'figcaption'
|
|
724
697
|
captionStartToken.block = true
|
|
@@ -728,33 +701,61 @@ const changePrevCaptionPosition = (tokens, n, caption, opt) => {
|
|
|
728
701
|
captionEndToken.tag = 'figcaption'
|
|
729
702
|
captionEndToken.block = true
|
|
730
703
|
captionEndToken.level = figureBaseLevel + 1
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
704
|
+
}
|
|
705
|
+
|
|
706
|
+
const changePrevCaptionPosition = (tokens, n, caption, opt) => {
|
|
707
|
+
const captionStartToken = tokens[n-3]
|
|
708
|
+
const captionInlineToken = tokens[n-2]
|
|
709
|
+
const captionEndToken = tokens[n-1]
|
|
710
|
+
const figureStartToken = tokens[n]
|
|
711
|
+
const figureStartPaddingToken = tokens[n+1]
|
|
712
|
+
convertCaptionTokens(
|
|
713
|
+
captionStartToken,
|
|
714
|
+
captionInlineToken,
|
|
715
|
+
captionEndToken,
|
|
716
|
+
getTokenLevel(tokens[n]),
|
|
717
|
+
caption.name,
|
|
718
|
+
opt,
|
|
719
|
+
)
|
|
720
|
+
tokens[n-3] = figureStartToken
|
|
721
|
+
tokens[n-2] = figureStartPaddingToken
|
|
722
|
+
tokens[n-1] = captionStartToken
|
|
723
|
+
tokens[n] = captionInlineToken
|
|
724
|
+
tokens[n+1] = captionEndToken
|
|
734
725
|
}
|
|
735
726
|
|
|
736
727
|
const changeNextCaptionPosition = (tokens, en, caption, opt) => {
|
|
728
|
+
const figureEndToken = tokens[en]
|
|
737
729
|
const captionStartToken = tokens[en+1]
|
|
738
730
|
const captionInlineToken = tokens[en+2]
|
|
739
731
|
const captionEndToken = tokens[en+3]
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
tokens
|
|
752
|
-
tokens.splice(en+4, 3)
|
|
753
|
-
return true
|
|
732
|
+
convertCaptionTokens(
|
|
733
|
+
captionStartToken,
|
|
734
|
+
captionInlineToken,
|
|
735
|
+
captionEndToken,
|
|
736
|
+
getTokenLevel(tokens[en]),
|
|
737
|
+
caption.name,
|
|
738
|
+
opt,
|
|
739
|
+
)
|
|
740
|
+
tokens[en] = captionStartToken
|
|
741
|
+
tokens[en+1] = captionInlineToken
|
|
742
|
+
tokens[en+2] = captionEndToken
|
|
743
|
+
tokens[en+3] = figureEndToken
|
|
754
744
|
}
|
|
755
745
|
|
|
756
746
|
const getTokenMap = (token) => {
|
|
757
|
-
|
|
747
|
+
if (!token || !Array.isArray(token.map) || token.map.length !== 2) return null
|
|
748
|
+
const startLine = token.map[0]
|
|
749
|
+
const endLine = token.map[1]
|
|
750
|
+
if (
|
|
751
|
+
!Number.isSafeInteger(startLine) ||
|
|
752
|
+
!Number.isSafeInteger(endLine) ||
|
|
753
|
+
startLine < 0 ||
|
|
754
|
+
endLine < startLine
|
|
755
|
+
) {
|
|
756
|
+
return null
|
|
757
|
+
}
|
|
758
|
+
return token.map
|
|
758
759
|
}
|
|
759
760
|
|
|
760
761
|
const findNearestMapInRange = (tokens, start, end, step) => {
|
|
@@ -773,9 +774,6 @@ const getRangeMap = (tokens, start, end) => {
|
|
|
773
774
|
const endMap = getTokenMap(tokens[end]) || findNearestMapInRange(tokens, end, start, -1) || startMap
|
|
774
775
|
const startLine = startMap[0]
|
|
775
776
|
const endLine = Math.max(startMap[1], endMap[1])
|
|
776
|
-
if (typeof startLine !== 'number' || typeof endLine !== 'number' || endLine < startLine) {
|
|
777
|
-
return [startMap[0], startMap[1]]
|
|
778
|
-
}
|
|
779
777
|
return [startLine, endLine]
|
|
780
778
|
}
|
|
781
779
|
|
|
@@ -793,14 +791,27 @@ const adjustTokenLevels = (tokens, start, end, delta) => {
|
|
|
793
791
|
}
|
|
794
792
|
}
|
|
795
793
|
|
|
794
|
+
const createTextToken = (TokenConstructor, content, level) => {
|
|
795
|
+
const token = new TokenConstructor('text', '', 0)
|
|
796
|
+
token.content = content
|
|
797
|
+
token.level = level
|
|
798
|
+
return token
|
|
799
|
+
}
|
|
800
|
+
|
|
801
|
+
const joinTokenAttrs = (token, attrs) => {
|
|
802
|
+
if (!attrs || attrs.length === 0) return
|
|
803
|
+
for (let i = 0; i < attrs.length; i++) {
|
|
804
|
+
token.attrJoin(attrs[i][0], attrs[i][1])
|
|
805
|
+
}
|
|
806
|
+
}
|
|
807
|
+
|
|
796
808
|
const wrapWithFigure = (tokens, range, checkTokenTagName, caption, replaceInsteadOfWrap, sp, opt, TokenConstructor) => {
|
|
797
809
|
let n = range.start
|
|
798
810
|
let en = range.end
|
|
799
811
|
const baseLevel = getTokenLevel(tokens[n])
|
|
800
812
|
const childLevel = baseLevel + 1
|
|
801
813
|
const figureStartToken = new TokenConstructor('figure_open', 'figure', 1)
|
|
802
|
-
|
|
803
|
-
figureStartToken.attrSet('class', figureClassName)
|
|
814
|
+
figureStartToken.attrSet('class', sp.figureClassName)
|
|
804
815
|
figureStartToken.block = true
|
|
805
816
|
figureStartToken.level = baseLevel
|
|
806
817
|
|
|
@@ -815,65 +826,50 @@ const wrapWithFigure = (tokens, range, checkTokenTagName, caption, replaceInstea
|
|
|
815
826
|
figureStartToken.map = [rangeMap[0], rangeMap[1]]
|
|
816
827
|
figureEndToken.map = [rangeMap[0], rangeMap[1]]
|
|
817
828
|
}
|
|
818
|
-
const createBreakToken = () => {
|
|
819
|
-
const breakToken = new TokenConstructor('text', '', 0)
|
|
820
|
-
breakToken.content = '\n'
|
|
821
|
-
breakToken.level = childLevel
|
|
822
|
-
return breakToken
|
|
823
|
-
}
|
|
824
|
-
const createEmptyTextToken = () => {
|
|
825
|
-
const emptyToken = new TokenConstructor('text', '', 0)
|
|
826
|
-
emptyToken.content = ''
|
|
827
|
-
emptyToken.level = childLevel
|
|
828
|
-
return emptyToken
|
|
829
|
-
}
|
|
830
829
|
if (caption.name === 'img') {
|
|
831
|
-
const joinAttrs = (attrs) => {
|
|
832
|
-
if (!attrs || attrs.length === 0) return
|
|
833
|
-
for (let i = 0; i < attrs.length; i++) {
|
|
834
|
-
const attr = attrs[i]
|
|
835
|
-
figureStartToken.attrJoin(attr[0], attr[1])
|
|
836
|
-
}
|
|
837
|
-
}
|
|
838
830
|
// `styleProcess` should keep working even when markdown-it-attrs is absent.
|
|
839
|
-
if (opt.styleProcess)
|
|
831
|
+
if (opt.styleProcess) joinTokenAttrs(figureStartToken, sp.attrs)
|
|
840
832
|
// Forward attrs already materialized by markdown-it-attrs on the image paragraph.
|
|
841
|
-
|
|
833
|
+
joinTokenAttrs(figureStartToken, tokens[n].attrs)
|
|
842
834
|
}
|
|
843
835
|
if (replaceInsteadOfWrap) {
|
|
844
|
-
tokens
|
|
845
|
-
tokens.splice(
|
|
836
|
+
const contentToken = tokens[n + 1]
|
|
837
|
+
tokens.splice(
|
|
838
|
+
n,
|
|
839
|
+
en - n + 1,
|
|
840
|
+
figureStartToken,
|
|
841
|
+
createTextToken(TokenConstructor, '', childLevel),
|
|
842
|
+
contentToken,
|
|
843
|
+
createTextToken(TokenConstructor, '\n', childLevel),
|
|
844
|
+
figureEndToken,
|
|
845
|
+
)
|
|
846
846
|
en = en + 2
|
|
847
|
+
} else if (n === en) {
|
|
848
|
+
const contentToken = tokens[n]
|
|
849
|
+
adjustTokenLevels(tokens, n, en, 1)
|
|
850
|
+
tokens.splice(
|
|
851
|
+
n,
|
|
852
|
+
1,
|
|
853
|
+
figureStartToken,
|
|
854
|
+
createTextToken(TokenConstructor, '', childLevel),
|
|
855
|
+
contentToken,
|
|
856
|
+
figureEndToken,
|
|
857
|
+
)
|
|
858
|
+
en = en + 3
|
|
847
859
|
} else {
|
|
848
860
|
adjustTokenLevels(tokens, n, en, 1)
|
|
849
861
|
tokens.splice(en+1, 0, figureEndToken)
|
|
850
|
-
tokens.splice(n, 0, figureStartToken,
|
|
862
|
+
tokens.splice(n, 0, figureStartToken, createTextToken(TokenConstructor, '', childLevel))
|
|
851
863
|
en = en + 3
|
|
852
864
|
}
|
|
853
865
|
range.start = n
|
|
854
866
|
range.end = en
|
|
855
|
-
return
|
|
856
867
|
}
|
|
857
868
|
|
|
858
869
|
const checkCaption = (tokens, n, en, caption, sp, opt, captionState) => {
|
|
859
870
|
checkPrevCaption(tokens, n, caption, sp, opt, captionState)
|
|
860
871
|
if (caption.isPrev) return
|
|
861
872
|
checkNextCaption(tokens, en, caption, sp, opt, captionState)
|
|
862
|
-
return
|
|
863
|
-
}
|
|
864
|
-
|
|
865
|
-
const getNestedContainerType = (token) => {
|
|
866
|
-
if (!token) return null
|
|
867
|
-
switch (token.type) {
|
|
868
|
-
case 'blockquote_open':
|
|
869
|
-
return 'blockquote'
|
|
870
|
-
case 'list_item_open':
|
|
871
|
-
return 'list_item'
|
|
872
|
-
case 'dd_open':
|
|
873
|
-
return 'dd'
|
|
874
|
-
default:
|
|
875
|
-
return null
|
|
876
|
-
}
|
|
877
873
|
}
|
|
878
874
|
|
|
879
875
|
const resetRangeState = (range, start) => {
|
|
@@ -894,6 +890,7 @@ const resetSpecialState = (sp) => {
|
|
|
894
890
|
sp.isIframeTypeBlockquote = false
|
|
895
891
|
sp.figureClassName = ''
|
|
896
892
|
sp.captionDecision = null
|
|
893
|
+
sp.numbering = null
|
|
897
894
|
}
|
|
898
895
|
|
|
899
896
|
const findClosingTokenIndex = (tokens, startIndex, tag) => {
|
|
@@ -910,19 +907,20 @@ const findClosingTokenIndex = (tokens, startIndex, tag) => {
|
|
|
910
907
|
}
|
|
911
908
|
i++
|
|
912
909
|
}
|
|
913
|
-
return
|
|
910
|
+
return -1
|
|
914
911
|
}
|
|
915
912
|
|
|
916
913
|
const detectCheckTypeOpen = (tokens, token, n, caption, baseType) => {
|
|
917
914
|
if (!token || !baseType) return null
|
|
918
915
|
if (n > 1 && tokens[n - 2] && tokens[n - 2].type === 'figure_open') return null
|
|
919
|
-
|
|
916
|
+
const tagName = token.tag
|
|
920
917
|
caption.name = baseType
|
|
921
918
|
if (baseType === 'pre') {
|
|
922
919
|
if (tokens[n + 1] && tokens[n + 1].tag === 'code') caption.name = 'pre-code'
|
|
923
920
|
if (tokens[n + 1] && tokens[n + 1].tag === 'samp') caption.name = 'pre-samp'
|
|
924
921
|
}
|
|
925
922
|
const en = findClosingTokenIndex(tokens, n, tagName)
|
|
923
|
+
if (en < 0) return null
|
|
926
924
|
return {
|
|
927
925
|
type: 'block',
|
|
928
926
|
tagName,
|
|
@@ -935,11 +933,8 @@ const detectCheckTypeOpen = (tokens, token, n, caption, baseType) => {
|
|
|
935
933
|
|
|
936
934
|
const detectFenceToken = (token, n, caption) => {
|
|
937
935
|
if (!token || token.type !== 'fence' || token.tag !== 'code' || !token.block) return null
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
token.tag = 'samp'
|
|
941
|
-
tagName = 'pre-samp'
|
|
942
|
-
}
|
|
936
|
+
const useSampTag = sampLangReg.test(token.info)
|
|
937
|
+
const tagName = useSampTag ? 'pre-samp' : 'pre-code'
|
|
943
938
|
caption.name = tagName
|
|
944
939
|
return {
|
|
945
940
|
type: 'fence',
|
|
@@ -948,6 +943,8 @@ const detectFenceToken = (token, n, caption) => {
|
|
|
948
943
|
replaceInsteadOfWrap: false,
|
|
949
944
|
wrapWithoutCaption: false,
|
|
950
945
|
canWrap: true,
|
|
946
|
+
token,
|
|
947
|
+
useSampTag,
|
|
951
948
|
}
|
|
952
949
|
}
|
|
953
950
|
|
|
@@ -971,6 +968,7 @@ const detectImageParagraph = (nextToken, n, caption, sp, opt) => {
|
|
|
971
968
|
let isMultipleImagesHorizontal = true
|
|
972
969
|
let isMultipleImagesVertical = true
|
|
973
970
|
let isValid = true
|
|
971
|
+
let trailingAttrToken = null
|
|
974
972
|
caption.name = 'img'
|
|
975
973
|
if (childrenLength === 1) {
|
|
976
974
|
return {
|
|
@@ -1006,7 +1004,7 @@ const detectImageParagraph = (nextToken, n, caption, sp, opt) => {
|
|
|
1006
1004
|
for (let i = 0; i < parsedAttrs.length; i++) {
|
|
1007
1005
|
sp.attrs.push(parsedAttrs[i])
|
|
1008
1006
|
}
|
|
1009
|
-
|
|
1007
|
+
trailingAttrToken = child
|
|
1010
1008
|
break
|
|
1011
1009
|
}
|
|
1012
1010
|
}
|
|
@@ -1044,12 +1042,6 @@ const detectImageParagraph = (nextToken, n, caption, sp, opt) => {
|
|
|
1044
1042
|
} else {
|
|
1045
1043
|
caption.nameSuffix = '-multiple'
|
|
1046
1044
|
}
|
|
1047
|
-
for (let i = 0; i < childrenLength; i++) {
|
|
1048
|
-
const child = children[i]
|
|
1049
|
-
if (isOnlySpacesText(child)) {
|
|
1050
|
-
child.content = ''
|
|
1051
|
-
}
|
|
1052
|
-
}
|
|
1053
1045
|
}
|
|
1054
1046
|
const en = n + 2
|
|
1055
1047
|
let tagName = 'img'
|
|
@@ -1062,28 +1054,56 @@ const detectImageParagraph = (nextToken, n, caption, sp, opt) => {
|
|
|
1062
1054
|
wrapWithoutCaption: isValid && allowImageParagraphWithoutCaption,
|
|
1063
1055
|
canWrap: isValid,
|
|
1064
1056
|
imageToken,
|
|
1057
|
+
inlineToken: nextToken,
|
|
1058
|
+
trailingAttrToken,
|
|
1065
1059
|
}
|
|
1066
1060
|
}
|
|
1067
1061
|
|
|
1068
|
-
const
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
|
|
1062
|
+
const applyImageParagraphTransform = (detection) => {
|
|
1063
|
+
if (!detection || detection.type !== 'image') return
|
|
1064
|
+
if (detection.trailingAttrToken) {
|
|
1065
|
+
detection.trailingAttrToken.content = ''
|
|
1072
1066
|
}
|
|
1067
|
+
if (!detection.inlineToken || detection.tagName === 'img') return
|
|
1068
|
+
const children = detection.inlineToken.children
|
|
1069
|
+
for (let i = 0; i < children.length; i++) {
|
|
1070
|
+
if (isOnlySpacesText(children[i])) {
|
|
1071
|
+
children[i].content = ''
|
|
1072
|
+
}
|
|
1073
|
+
}
|
|
1074
|
+
}
|
|
1073
1075
|
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
1076
|
+
const applyWrappedCandidateTransform = (detection) => {
|
|
1077
|
+
if (detection.type === 'image') {
|
|
1078
|
+
applyImageParagraphTransform(detection)
|
|
1079
|
+
} else if (detection.type === 'fence' && detection.useSampTag) {
|
|
1080
|
+
detection.token.tag = 'samp'
|
|
1081
|
+
}
|
|
1082
|
+
}
|
|
1083
|
+
|
|
1084
|
+
const figureWithCaption = (state, opt) => {
|
|
1085
|
+
const numberingRuntime = opt.captionNumberingPolicy
|
|
1086
|
+
? createCaptionNumberingRuntime(opt.captionNumberingPolicy, { env: state.env })
|
|
1087
|
+
: null
|
|
1088
|
+
const numberingScopeState = numberingRuntime
|
|
1089
|
+
? createFigureCaptionScopeRuntime(
|
|
1090
|
+
state,
|
|
1091
|
+
opt.normalizedAutoLabelNumberPolicy,
|
|
1092
|
+
opt.unscopedNumberingContext,
|
|
1093
|
+
)
|
|
1094
|
+
: null
|
|
1095
|
+
const captionState = {
|
|
1096
|
+
tokens: state.tokens,
|
|
1097
|
+
Token: state.Token,
|
|
1098
|
+
preferredLanguages: opt.preferredLanguages,
|
|
1099
|
+
numberingRuntime,
|
|
1100
|
+
numberingScopeState,
|
|
1082
1101
|
}
|
|
1083
|
-
|
|
1102
|
+
if (opt.shouldResolvePreferredLanguages) captionState.preferredLanguageState = state
|
|
1103
|
+
figureWithCaptionCore(state.tokens, opt, state.Token, captionState, null, 0)
|
|
1084
1104
|
}
|
|
1085
1105
|
|
|
1086
|
-
const figureWithCaptionCore = (tokens, opt,
|
|
1106
|
+
const figureWithCaptionCore = (tokens, opt, TokenConstructor, captionState, parentType = null, startIndex = 0) => {
|
|
1087
1107
|
const rRange = { start: startIndex, end: startIndex }
|
|
1088
1108
|
const rCaption = {
|
|
1089
1109
|
name: '', nameSuffix: '', isPrev: false, isNext: false
|
|
@@ -1093,21 +1113,31 @@ const figureWithCaptionCore = (tokens, opt, figureNumberState, TokenConstructor,
|
|
|
1093
1113
|
isVideoIframe: false,
|
|
1094
1114
|
isIframeTypeBlockquote: false,
|
|
1095
1115
|
figureClassName: '',
|
|
1096
|
-
captionDecision: null
|
|
1097
|
-
|
|
1116
|
+
captionDecision: null,
|
|
1117
|
+
numbering: null,
|
|
1118
|
+
}
|
|
1119
|
+
const numberingScopeState = parentType ? null : captionState.numberingScopeState
|
|
1120
|
+
const headingScopeState = numberingScopeState &&
|
|
1121
|
+
!numberingScopeState.fixed &&
|
|
1122
|
+
numberingScopeState.scopeConfig.usesHeading
|
|
1123
|
+
? numberingScopeState
|
|
1124
|
+
: null
|
|
1125
|
+
const parentCloseType = parentType ? parentType + '_close' : ''
|
|
1098
1126
|
let n = startIndex
|
|
1099
1127
|
while (n < tokens.length) {
|
|
1100
1128
|
const token = tokens[n]
|
|
1101
|
-
|
|
1129
|
+
if (headingScopeState && token.type === 'heading_open') {
|
|
1130
|
+
updateFigureCaptionScopeFromHeading(tokens, n, headingScopeState)
|
|
1131
|
+
}
|
|
1132
|
+
const containerType = getFigureCaptionScopeNestedContainerType(token)
|
|
1102
1133
|
|
|
1103
1134
|
if (containerType && containerType !== 'blockquote') {
|
|
1104
|
-
const closeIndex = figureWithCaptionCore(tokens, opt,
|
|
1105
|
-
n =
|
|
1135
|
+
const closeIndex = figureWithCaptionCore(tokens, opt, TokenConstructor, captionState, containerType, n + 1)
|
|
1136
|
+
n = closeIndex + 1
|
|
1106
1137
|
continue
|
|
1107
1138
|
}
|
|
1108
1139
|
|
|
1109
|
-
|
|
1110
|
-
if (parentType && token.type === `${parentType}_close`) {
|
|
1140
|
+
if (parentCloseType && token.type === parentCloseType) {
|
|
1111
1141
|
return n
|
|
1112
1142
|
}
|
|
1113
1143
|
|
|
@@ -1146,8 +1176,8 @@ const figureWithCaptionCore = (tokens, opt, figureNumberState, TokenConstructor,
|
|
|
1146
1176
|
|
|
1147
1177
|
if (!detection) {
|
|
1148
1178
|
if (containerType === 'blockquote') {
|
|
1149
|
-
const closeIndex = figureWithCaptionCore(tokens, opt,
|
|
1150
|
-
n =
|
|
1179
|
+
const closeIndex = figureWithCaptionCore(tokens, opt, TokenConstructor, captionState, containerType, n + 1)
|
|
1180
|
+
n = closeIndex + 1
|
|
1151
1181
|
} else {
|
|
1152
1182
|
n++
|
|
1153
1183
|
}
|
|
@@ -1156,63 +1186,77 @@ const figureWithCaptionCore = (tokens, opt, figureNumberState, TokenConstructor,
|
|
|
1156
1186
|
|
|
1157
1187
|
rRange.end = detection.en
|
|
1158
1188
|
|
|
1189
|
+
if (detection.canWrap === false || (detection.type === 'image' && token.hidden === true)) {
|
|
1190
|
+
let nextIndex = rRange.end + 1
|
|
1191
|
+
if (containerType === 'blockquote') {
|
|
1192
|
+
const closeIndex = figureWithCaptionCore(tokens, opt, TokenConstructor, captionState, containerType, rRange.start + 1)
|
|
1193
|
+
nextIndex = Math.max(nextIndex, closeIndex + 1)
|
|
1194
|
+
}
|
|
1195
|
+
n = nextIndex
|
|
1196
|
+
continue
|
|
1197
|
+
}
|
|
1198
|
+
|
|
1199
|
+
if (detection.type === 'html') {
|
|
1200
|
+
rRange.end = applyHtmlFigureTransform(tokens, detection)
|
|
1201
|
+
}
|
|
1202
|
+
|
|
1203
|
+
if (captionState.numberingRuntime) {
|
|
1204
|
+
rSp.numbering = captionState.numberingScopeState
|
|
1205
|
+
? captionState.numberingScopeState.currentContext
|
|
1206
|
+
: opt.unscopedNumberingContext
|
|
1207
|
+
}
|
|
1159
1208
|
rSp.figureClassName = resolveFigureClassName(detection.tagName, rSp, opt)
|
|
1160
1209
|
checkCaption(tokens, rRange.start, rRange.end, rCaption, rSp, opt, captionState)
|
|
1161
|
-
applyCaptionDrivenFigureClass(rCaption, rSp, opt)
|
|
1162
1210
|
|
|
1163
1211
|
let hasCaption = rCaption.isPrev || rCaption.isNext
|
|
1164
|
-
|
|
1212
|
+
if (hasCaption) applyCaptionDrivenFigureClass(rCaption, rSp, opt)
|
|
1213
|
+
let pendingAutoCaption = null
|
|
1165
1214
|
if (!hasCaption && detection.type === 'image' && opt.autoCaptionDetection) {
|
|
1166
|
-
pendingAutoCaption = getAutoCaptionFromImage(detection.imageToken, opt)
|
|
1215
|
+
pendingAutoCaption = getAutoCaptionFromImage(detection.imageToken, opt, captionState)
|
|
1167
1216
|
if (pendingAutoCaption) {
|
|
1168
1217
|
hasCaption = true
|
|
1169
1218
|
}
|
|
1170
1219
|
}
|
|
1171
1220
|
|
|
1172
|
-
|
|
1173
|
-
|
|
1174
|
-
|
|
1175
|
-
const closeIndex = figureWithCaptionCore(tokens, opt, figureNumberState, TokenConstructor, captionState, containerType, rRange.start + 1)
|
|
1176
|
-
nextIndex = Math.max(nextIndex, (typeof closeIndex === 'number' ? closeIndex : rRange.end) + 1)
|
|
1177
|
-
}
|
|
1178
|
-
n = nextIndex
|
|
1179
|
-
continue
|
|
1221
|
+
let shouldWrap = hasCaption
|
|
1222
|
+
if (detection.type === 'html' || detection.type === 'image') {
|
|
1223
|
+
shouldWrap = shouldWrap || detection.wrapWithoutCaption
|
|
1180
1224
|
}
|
|
1181
|
-
|
|
1182
|
-
|
|
1183
|
-
|
|
1184
|
-
|
|
1185
|
-
|
|
1186
|
-
|
|
1187
|
-
|
|
1188
|
-
|
|
1225
|
+
if (pendingAutoCaption) {
|
|
1226
|
+
const captionTokens = createAutoCaptionParagraph(pendingAutoCaption.text, TokenConstructor)
|
|
1227
|
+
const insertIndex = rRange.start
|
|
1228
|
+
const insertedLength = captionTokens.length
|
|
1229
|
+
tokens.splice(insertIndex, 0, ...captionTokens)
|
|
1230
|
+
rRange.start += insertedLength
|
|
1231
|
+
rRange.end += insertedLength
|
|
1232
|
+
n += insertedLength
|
|
1233
|
+
try {
|
|
1234
|
+
checkCaption(tokens, rRange.start, rRange.end, rCaption, rSp, opt, captionState)
|
|
1235
|
+
} catch (error) {
|
|
1236
|
+
tokens.splice(insertIndex, insertedLength)
|
|
1237
|
+
throw error
|
|
1238
|
+
}
|
|
1239
|
+
if (rCaption.isPrev || rCaption.isNext) {
|
|
1240
|
+
consumeAutoCaptionSource(detection.imageToken, pendingAutoCaption)
|
|
1241
|
+
applyCaptionDrivenFigureClass(rCaption, rSp, opt)
|
|
1242
|
+
} else {
|
|
1243
|
+
tokens.splice(insertIndex, insertedLength)
|
|
1244
|
+
rRange.start -= insertedLength
|
|
1245
|
+
rRange.end -= insertedLength
|
|
1246
|
+
n -= insertedLength
|
|
1247
|
+
shouldWrap = detection.wrapWithoutCaption
|
|
1189
1248
|
}
|
|
1190
|
-
} else {
|
|
1191
|
-
shouldWrap = detection.canWrap !== false && hasCaption
|
|
1192
1249
|
}
|
|
1193
|
-
|
|
1194
1250
|
if (shouldWrap) {
|
|
1195
|
-
if (
|
|
1196
|
-
|
|
1197
|
-
tokens.splice(rRange.start, 0, ...captionTokens)
|
|
1198
|
-
const insertedLength = captionTokens.length
|
|
1199
|
-
rRange.start += insertedLength
|
|
1200
|
-
rRange.end += insertedLength
|
|
1201
|
-
n += insertedLength
|
|
1202
|
-
checkCaption(tokens, rRange.start, rRange.end, rCaption, rSp, opt, captionState)
|
|
1203
|
-
applyCaptionDrivenFigureClass(rCaption, rSp, opt)
|
|
1251
|
+
if (detection.type !== 'html') {
|
|
1252
|
+
applyWrappedCandidateTransform(detection)
|
|
1204
1253
|
}
|
|
1205
|
-
ensureAutoFigureNumbering(tokens, rRange, rCaption, figureNumberState, opt)
|
|
1206
1254
|
wrapWithFigure(tokens, rRange, detection.tagName, rCaption, detection.replaceInsteadOfWrap, rSp, opt, TokenConstructor)
|
|
1207
1255
|
}
|
|
1208
1256
|
|
|
1209
1257
|
let nextIndex
|
|
1210
1258
|
if (!rCaption.isPrev && !rCaption.isNext) {
|
|
1211
|
-
|
|
1212
|
-
nextIndex = rRange.end + 1
|
|
1213
|
-
} else {
|
|
1214
|
-
nextIndex = n + 1
|
|
1215
|
-
}
|
|
1259
|
+
nextIndex = shouldWrap ? rRange.end + 1 : n + 1
|
|
1216
1260
|
} else {
|
|
1217
1261
|
const en = rRange.end
|
|
1218
1262
|
if (rCaption.isPrev) {
|
|
@@ -1221,15 +1265,20 @@ const figureWithCaptionCore = (tokens, opt, figureNumberState, TokenConstructor,
|
|
|
1221
1265
|
} else if (rCaption.isNext) {
|
|
1222
1266
|
changeNextCaptionPosition(tokens, en, rCaption, opt)
|
|
1223
1267
|
nextIndex = en + 4
|
|
1224
|
-
} else {
|
|
1225
|
-
nextIndex = en + 1
|
|
1226
1268
|
}
|
|
1227
1269
|
}
|
|
1228
1270
|
|
|
1229
1271
|
if (containerType === 'blockquote') {
|
|
1230
|
-
const
|
|
1231
|
-
const
|
|
1232
|
-
|
|
1272
|
+
const nestedContentStart = rRange.start + (shouldWrap ? 3 : 1)
|
|
1273
|
+
const closeIndex = figureWithCaptionCore(
|
|
1274
|
+
tokens,
|
|
1275
|
+
opt,
|
|
1276
|
+
TokenConstructor,
|
|
1277
|
+
captionState,
|
|
1278
|
+
containerType,
|
|
1279
|
+
nestedContentStart,
|
|
1280
|
+
)
|
|
1281
|
+
nextIndex = Math.max(nextIndex, closeIndex + 1)
|
|
1233
1282
|
}
|
|
1234
1283
|
|
|
1235
1284
|
n = nextIndex
|
|
@@ -1238,7 +1287,11 @@ const figureWithCaptionCore = (tokens, opt, figureNumberState, TokenConstructor,
|
|
|
1238
1287
|
}
|
|
1239
1288
|
|
|
1240
1289
|
const mditFigureWithPCaption = (md, option) => {
|
|
1241
|
-
|
|
1290
|
+
if (md[installedKey]) return
|
|
1291
|
+
if (hasOwnOption(option, 'setFigureNumber')) {
|
|
1292
|
+
throw new Error('setFigureNumber is not supported by figure-with-p-caption; use autoLabelNumber or autoLabelNumberSets')
|
|
1293
|
+
}
|
|
1294
|
+
const opt = {
|
|
1242
1295
|
// Caption languages delegated to p-captions.
|
|
1243
1296
|
languages: ['en', 'ja'],
|
|
1244
1297
|
preferredLanguages: null, // compatibility tie-break for generated fallback labels; prefer env.locale / env.preferredLocales per render
|
|
@@ -1271,7 +1324,8 @@ const mditFigureWithPCaption = (md, option) => {
|
|
|
1271
1324
|
|
|
1272
1325
|
// --- numbering controls ---
|
|
1273
1326
|
autoLabelNumber: false, // shorthand for enabling numbering for both img/table unless autoLabelNumberSets is provided explicitly
|
|
1274
|
-
autoLabelNumberSets: [], // preferred; supports
|
|
1327
|
+
autoLabelNumberSets: [], // preferred; supports img/table/code/samp/video marks
|
|
1328
|
+
autoLabelNumberPolicy: undefined, // omitted: automatic Chapter/Appendix scope; explicit null: document-wide numbering
|
|
1275
1329
|
|
|
1276
1330
|
// --- caption text formatting (delegated to p7d-markdown-it-p-captions) ---
|
|
1277
1331
|
hasNumClass: false,
|
|
@@ -1287,16 +1341,20 @@ const mditFigureWithPCaption = (md, option) => {
|
|
|
1287
1341
|
labelClassFollowsFigure: false,
|
|
1288
1342
|
figureToLabelClassMap: null,
|
|
1289
1343
|
}
|
|
1290
|
-
const hasExplicitAutoLabelNumberSets =
|
|
1291
|
-
const hasExplicitImageOnlyParagraphWithoutCaption =
|
|
1292
|
-
const hasExplicitFigureClassThatWrapsIframeTypeBlockquote =
|
|
1293
|
-
const hasExplicitFigureClassThatWrapsSlides =
|
|
1294
|
-
const hasExplicitLabelClassFollowsFigure =
|
|
1344
|
+
const hasExplicitAutoLabelNumberSets = hasOwnOption(option, 'autoLabelNumberSets')
|
|
1345
|
+
const hasExplicitImageOnlyParagraphWithoutCaption = hasOwnOption(option, 'imageOnlyParagraphWithoutCaption')
|
|
1346
|
+
const hasExplicitFigureClassThatWrapsIframeTypeBlockquote = hasOwnOption(option, 'figureClassThatWrapsIframeTypeBlockquote')
|
|
1347
|
+
const hasExplicitFigureClassThatWrapsSlides = hasOwnOption(option, 'figureClassThatWrapsSlides')
|
|
1348
|
+
const hasExplicitLabelClassFollowsFigure = hasOwnOption(option, 'labelClassFollowsFigure')
|
|
1295
1349
|
if (option) Object.assign(opt, option)
|
|
1350
|
+
if (Array.isArray(opt.removeUnnumberedLabelExceptMarks)) {
|
|
1351
|
+
opt.removeUnnumberedLabelExceptMarks = opt.removeUnnumberedLabelExceptMarks.map(
|
|
1352
|
+
canonicalizeCaptionNumberingMark,
|
|
1353
|
+
)
|
|
1354
|
+
}
|
|
1296
1355
|
opt.imageOnlyParagraphWithoutCaption = hasExplicitImageOnlyParagraphWithoutCaption
|
|
1297
1356
|
? !!opt.imageOnlyParagraphWithoutCaption
|
|
1298
1357
|
: !!opt.oneImageWithoutCaption
|
|
1299
|
-
opt.oneImageWithoutCaption = !!opt.oneImageWithoutCaption
|
|
1300
1358
|
if (!hasExplicitLabelClassFollowsFigure && opt.figureToLabelClassMap) {
|
|
1301
1359
|
opt.labelClassFollowsFigure = true
|
|
1302
1360
|
}
|
|
@@ -1305,7 +1363,6 @@ const mditFigureWithPCaption = (md, option) => {
|
|
|
1305
1363
|
opt.markRegState = getMarkRegStateForLanguages(opt.languages)
|
|
1306
1364
|
opt.preferredLanguages = normalizePreferredLanguages(opt.preferredLanguages, opt.markRegState.languages)
|
|
1307
1365
|
if (opt.preferredLanguages.length === 0) opt.preferredLanguages = null
|
|
1308
|
-
opt.normalizedOptionLanguages = normalizePreferredLanguages(opt.languages, opt.markRegState.languages)
|
|
1309
1366
|
opt.shouldResolvePreferredLanguages = needsPreferredLanguagesResolution(opt)
|
|
1310
1367
|
validateFallbackCaptionLabelOption('autoAltCaption', opt.autoAltCaption, opt.markRegState)
|
|
1311
1368
|
validateFallbackCaptionLabelOption('autoTitleCaption', opt.autoTitleCaption, opt.markRegState)
|
|
@@ -1315,12 +1372,27 @@ const mditFigureWithPCaption = (md, option) => {
|
|
|
1315
1372
|
audio: !!opt.audioWithoutCaption,
|
|
1316
1373
|
iframeTypeBlockquote: !!opt.iframeTypeBlockquoteWithoutCaption,
|
|
1317
1374
|
}
|
|
1318
|
-
|
|
1319
|
-
|
|
1320
|
-
|
|
1321
|
-
|
|
1322
|
-
|
|
1323
|
-
|
|
1375
|
+
const requestedAutoLabelNumberSets = hasExplicitAutoLabelNumberSets
|
|
1376
|
+
? option.autoLabelNumberSets
|
|
1377
|
+
: opt.autoLabelNumber
|
|
1378
|
+
? ['img', 'table']
|
|
1379
|
+
: []
|
|
1380
|
+
opt.autoLabelNumberSets = normalizeAutoLabelNumberSets(requestedAutoLabelNumberSets)
|
|
1381
|
+
const enabledNumberingMarks = getEnabledCaptionNumberingMarks(opt.autoLabelNumberSets, opt)
|
|
1382
|
+
opt.normalizedAutoLabelNumberPolicy = enabledNumberingMarks.length === 0 &&
|
|
1383
|
+
opt.autoLabelNumberPolicy === undefined
|
|
1384
|
+
? null
|
|
1385
|
+
: normalizeFigureCaptionNumberingPolicy(opt.autoLabelNumberPolicy)
|
|
1386
|
+
opt.captionNumberingPolicy = createFigureCaptionNumberingPolicy(
|
|
1387
|
+
enabledNumberingMarks,
|
|
1388
|
+
opt.normalizedAutoLabelNumberPolicy,
|
|
1389
|
+
opt.markRegState,
|
|
1390
|
+
)
|
|
1391
|
+
opt.unscopedNumberingContext = opt.captionNumberingPolicy && opt.normalizedAutoLabelNumberPolicy
|
|
1392
|
+
? createUnscopedNumberingContext(
|
|
1393
|
+
getFigureCaptionNumberingPolicyState(opt.normalizedAutoLabelNumberPolicy).separator,
|
|
1394
|
+
)
|
|
1395
|
+
: null
|
|
1324
1396
|
const classPrefix = buildClassPrefix(opt.classPrefix)
|
|
1325
1397
|
opt.figureClassPrefix = classPrefix
|
|
1326
1398
|
opt.captionClassPrefix = classPrefix
|
|
@@ -1342,8 +1414,6 @@ const mditFigureWithPCaption = (md, option) => {
|
|
|
1342
1414
|
defaultSlideFigureClass,
|
|
1343
1415
|
)
|
|
1344
1416
|
}
|
|
1345
|
-
// Precompute label-class permutations so numbering lookup doesn't rebuild arrays per caption.
|
|
1346
|
-
opt.labelClassLookup = buildLabelClassLookup(opt)
|
|
1347
1417
|
const markerList = normalizeLabelPrefixMarkers(opt.labelPrefixMarker)
|
|
1348
1418
|
opt.labelPrefixMarkerReg = buildLabelPrefixMarkerRegFromMarkers(markerList)
|
|
1349
1419
|
opt.cleanCaptionRegCache = new Map()
|
|
@@ -1356,10 +1426,14 @@ const mditFigureWithPCaption = (md, option) => {
|
|
|
1356
1426
|
opt.labelPrefixMarkerWithoutLabelNextReg = null
|
|
1357
1427
|
}
|
|
1358
1428
|
|
|
1359
|
-
//
|
|
1429
|
+
// Run after markdown-it-attrs has attached paragraph attrs, but before text replacements.
|
|
1360
1430
|
md.core.ruler.before('replacements', 'figure_with_caption', (state) => {
|
|
1361
1431
|
figureWithCaption(state, opt)
|
|
1362
1432
|
})
|
|
1433
|
+
Object.defineProperty(md, installedKey, {
|
|
1434
|
+
value: true,
|
|
1435
|
+
configurable: true,
|
|
1436
|
+
})
|
|
1363
1437
|
}
|
|
1364
1438
|
|
|
1365
1439
|
export default mditFigureWithPCaption
|