@peaceroad/markdown-it-strong-ja 0.5.3 → 0.5.5

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.
Files changed (2) hide show
  1. package/index.js +301 -185
  2. package/package.json +6 -4
package/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import Token from 'markdown-it/lib/token.mjs'
2
2
  import { parseLinkDestination, parseLinkTitle } from 'markdown-it/lib/helpers/index.mjs'
3
- import { isSpace } from 'markdown-it/lib/common/utils.mjs'
3
+ import { isSpace, isWhiteSpace } from 'markdown-it/lib/common/utils.mjs'
4
4
 
5
5
  const CHAR_ASTERISK = 0x2A // *
6
6
  //const CHAR_UNDERSCORE = 0x5F // _
@@ -20,15 +20,19 @@ const CHAR_TAB = 0x09 // tab
20
20
  //const CHAR_OPEN_CURLY = 0x7B // {
21
21
  const CHAR_CLOSE_CURLY = 0x7D // }
22
22
 
23
- const REG_ASTERISKS = /^\*+$/
24
23
  const REG_ATTRS = /{[^{}\n!@#%^&*()]+?}$/
25
- const REG_PUNCTUATION = /[!-/:-@[-`{-~ ]/
24
+ const REG_ASCII_PUNCT = /[!-/:-@[-`{-~]/g
26
25
  const REG_JAPANESE = /\p{Script=Hiragana}|\p{Script=Katakana}|\p{Script=Han}|\p{General_Category=Punctuation}|\p{General_Category=Symbol}|\p{General_Category=Format}|\p{Emoji}/u // ひらがな|カタカナ|漢字|句読点|記号|フォーマット文字|絵文字
27
26
 
28
27
  const REG_MARKDOWN_HTML = /^\[[^\[\]]+\]\([^)]+\)$|^<([a-zA-Z][a-zA-Z0-9]*)[^>]*>([^<]+<\/\1>)$|^`[^`]+`$|^\$[^$]+\$$/ // for mixed-language context detection
29
28
 
30
29
  const hasBackslash = (state, start) => {
31
30
  if (start <= 0) return false
31
+ if (state.__strongJaHasBackslash === false) return false
32
+ if (state.__strongJaHasBackslash === undefined) {
33
+ state.__strongJaHasBackslash = state.src.indexOf('\\') !== -1
34
+ if (!state.__strongJaHasBackslash) return false
35
+ }
32
36
  const cache = state.__strongJaBackslashCache
33
37
  if (cache && cache.has(start)) {
34
38
  return cache.get(start)
@@ -173,12 +177,11 @@ const computeReferenceRanges = (state, start, max) => {
173
177
  ? referenceCount > 0
174
178
  : Object.keys(references).length > 0)
175
179
  if (!hasReferences) return []
176
- const firstBracket = src.indexOf('[', start)
177
- if (firstBracket === -1 || firstBracket >= max) return []
180
+ let pos = src.indexOf('[', start)
181
+ if (pos === -1 || pos >= max) return []
178
182
  const ranges = []
179
- let pos = start
180
- while (pos < max) {
181
- if (src.charCodeAt(pos) === CHAR_OPEN_BRACKET && !hasBackslash(state, pos)) {
183
+ while (pos !== -1 && pos < max) {
184
+ if (!hasBackslash(state, pos)) {
182
185
  const labelClose = findMatchingBracket(state, pos, max, CHAR_OPEN_BRACKET, CHAR_CLOSE_BRACKET)
183
186
  if (labelClose !== -1) {
184
187
  const nextPos = labelClose + 1
@@ -199,16 +202,13 @@ const computeReferenceRanges = (state, start, max) => {
199
202
  ranges.push({ start: pos, end: labelClose, hasReference: true })
200
203
  ranges.push({ start: nextPos, end: refClose, hasReference: true })
201
204
  }
202
- pos = refClose
205
+ pos = src.indexOf('[', refClose + 1)
203
206
  continue
204
207
  }
205
208
  }
206
209
  }
207
210
  }
208
- pos++
209
- }
210
- if (ranges.length) {
211
- ranges.__cache = new Map()
211
+ pos = src.indexOf('[', pos + 1)
212
212
  }
213
213
  return ranges
214
214
  }
@@ -217,10 +217,11 @@ const computeInlineLinkRanges = (state, start, max) => {
217
217
  const src = state.src
218
218
  const ranges = []
219
219
  const labelRanges = []
220
- let pos = start
220
+ let pos = src.indexOf('[', start)
221
+ if (pos === -1 || pos >= max) return []
221
222
  let rangeId = 0
222
- while (pos < max) {
223
- if (src.charCodeAt(pos) === CHAR_OPEN_BRACKET && !hasBackslash(state, pos)) {
223
+ while (pos !== -1 && pos < max) {
224
+ if (!hasBackslash(state, pos)) {
224
225
  const labelClose = findMatchingBracket(state, pos, max, CHAR_OPEN_BRACKET, CHAR_CLOSE_BRACKET)
225
226
  if (labelClose === -1) break
226
227
  let destStart = labelClose + 1
@@ -237,14 +238,14 @@ const computeInlineLinkRanges = (state, start, max) => {
237
238
  labelRanges.push(labelRange)
238
239
  ranges.push({ start: destStart, end: destClose, kind: 'dest', id: rangeId })
239
240
  rangeId++
240
- pos = destClose + 1
241
+ pos = src.indexOf('[', destClose + 1)
241
242
  continue
242
243
  }
243
244
  }
244
- pos = labelClose + 1
245
+ pos = src.indexOf('[', labelClose + 1)
245
246
  continue
246
247
  }
247
- pos++
248
+ pos = src.indexOf('[', pos + 1)
248
249
  }
249
250
  if (ranges.length && labelRanges.length) {
250
251
  ranges.__labelRanges = labelRanges
@@ -264,7 +265,8 @@ const getInlineRangeCacheMap = (ranges, kind, create) => {
264
265
 
265
266
  const findInlineLinkRange = (pos, ranges, kind) => {
266
267
  if (!ranges || ranges.length === 0) return null
267
- const cache = getInlineRangeCacheMap(ranges, kind, false)
268
+ const useCache = ranges.length > 32
269
+ const cache = useCache ? getInlineRangeCacheMap(ranges, kind, false) : null
268
270
  if (cache && cache.has(pos)) return cache.get(pos)
269
271
  let left = 0
270
272
  let right = ranges.length - 1
@@ -283,8 +285,10 @@ const findInlineLinkRange = (pos, ranges, kind) => {
283
285
  break
284
286
  }
285
287
  }
286
- const storeCache = getInlineRangeCacheMap(ranges, kind, true)
287
- storeCache.set(pos, found)
288
+ if (useCache) {
289
+ const storeCache = getInlineRangeCacheMap(ranges, kind, true)
290
+ storeCache.set(pos, found)
291
+ }
288
292
  return found
289
293
  }
290
294
 
@@ -318,24 +322,64 @@ const registerPostProcessTarget = (state) => {
318
322
  targets.push(state.tokens)
319
323
  }
320
324
 
321
- const setToken = (state, inlines, opt) => {
325
+ const hasMditAttrs = (state) => {
326
+ if (state.__strongJaHasAttrs !== undefined) return state.__strongJaHasAttrs
327
+ const rules = state.md && state.md.core && state.md.core.ruler && state.md.core.ruler.__rules__
328
+ if (!rules || !Array.isArray(rules)) {
329
+ state.__strongJaHasAttrs = false
330
+ return false
331
+ }
332
+ for (let i = 0; i < rules.length; i++) {
333
+ if (rules[i].name === 'curly_attributes') {
334
+ state.__strongJaHasAttrs = true
335
+ return true
336
+ }
337
+ }
338
+ state.__strongJaHasAttrs = false
339
+ return false
340
+ }
341
+
342
+ const isAllAsterisks = (content) => {
343
+ for (let i = 0; i < content.length; i++) {
344
+ if (content.charCodeAt(i) !== CHAR_ASTERISK) return false
345
+ }
346
+ return true
347
+ }
348
+
349
+ function isPlainTextContent(content) {
350
+ for (let idx = 0; idx < content.length; idx++) {
351
+ const code = content.charCodeAt(idx)
352
+ if (code === CHAR_BACKSLASH || code === CHAR_NEWLINE || code === CHAR_TAB) {
353
+ return false
354
+ }
355
+ if (code < 128 && isAsciiPunctuationCode(code)) return false
356
+ }
357
+ return true
358
+ }
359
+
360
+ const setToken = (state, inlines, opt, attrsEnabled) => {
322
361
  const src = state.src
323
362
  let i = 0
324
- let attrsIsText = {
325
- val: false,
326
- tag: '',
327
- }
363
+ let attrsIsText = false
364
+ let attrsIsTextTag = ''
328
365
  while (i < inlines.length) {
329
366
  let type = inlines[i].type
330
- const tag = type.replace(/(?:_open|_close)$/, '')
331
-
332
- if (/_open$/.test(type)) {
367
+ let tag = ''
368
+ let isOpen = false
369
+ let isClose = false
370
+ if (type.length > 5 && type.endsWith('_open')) {
371
+ isOpen = true
372
+ tag = type.slice(0, -5)
373
+ } else if (type.length > 6 && type.endsWith('_close')) {
374
+ isClose = true
375
+ tag = type.slice(0, -6)
376
+ }
377
+
378
+ if (isOpen) {
333
379
  const startToken = state.push(type, tag, 1)
334
380
  startToken.markup = tag === 'strong' ? '**' : '*'
335
- attrsIsText = {
336
- val: true,
337
- tag: tag,
338
- }
381
+ attrsIsText = true
382
+ attrsIsTextTag = tag
339
383
  }
340
384
 
341
385
  if (type === 'html_inline') {
@@ -343,18 +387,23 @@ const setToken = (state, inlines, opt) => {
343
387
  }
344
388
  if (type === 'text') {
345
389
  let content = src.slice(inlines[i].s, inlines[i].e + 1)
346
- if (REG_ASTERISKS.test(content)) {
347
- const asteriskToken = state.push(type, '', 0)
348
- asteriskToken.content = content
349
- i++
350
- continue
390
+ if (content.length > 0 && content.charCodeAt(0) === CHAR_ASTERISK) {
391
+ if (isAllAsterisks(content)) {
392
+ const asteriskToken = state.push(type, '', 0)
393
+ asteriskToken.content = content
394
+ i++
395
+ continue
396
+ }
351
397
  }
352
- if (opt.mditAttrs && attrsIsText.val && i + 1 < inlines.length) {
353
- const hasImmediatelyAfterAsteriskClose = inlines[i+1].type === attrsIsText.tag + '_close'
354
- if (hasImmediatelyAfterAsteriskClose && REG_ATTRS.test(content)) {
398
+ if (attrsEnabled && attrsIsText && i + 1 < inlines.length) {
399
+ const hasImmediatelyAfterAsteriskClose = inlines[i+1].type === attrsIsTextTag + '_close'
400
+ const maybeAttrs = content.length > 0 && content.charCodeAt(content.length - 1) === CHAR_CLOSE_CURLY
401
+ if (hasImmediatelyAfterAsteriskClose && maybeAttrs && REG_ATTRS.test(content)) {
355
402
  const attrsToken = state.push(type, '', 0)
356
-
357
- const hasBackslashBeforeCurlyAttribute = content.match(/(\\+){/)
403
+ let hasBackslashBeforeCurlyAttribute = null
404
+ if (content.indexOf('\\') !== -1) {
405
+ hasBackslashBeforeCurlyAttribute = content.match(/(\\+){/)
406
+ }
358
407
  if (hasBackslashBeforeCurlyAttribute) {
359
408
  if (hasBackslashBeforeCurlyAttribute[1].length === 1) {
360
409
  attrsToken.content = content.replace(/\\{/, '{')
@@ -371,11 +420,18 @@ const setToken = (state, inlines, opt) => {
371
420
  } else {
372
421
  attrsToken.content = content
373
422
  }
374
- attrsIsText.val = false
423
+ attrsIsText = false
424
+ attrsIsTextTag = ''
375
425
  i++
376
426
  continue
377
427
  }
378
428
  }
429
+ if (isPlainTextContent(content)) {
430
+ const textToken = state.push(type, '', 0)
431
+ textToken.content = content
432
+ i++
433
+ continue
434
+ }
379
435
 
380
436
  const childTokens = state.md.parseInline(content, state.env)
381
437
  if (childTokens[0] && childTokens[0].children) {
@@ -387,7 +443,7 @@ const setToken = (state, inlines, opt) => {
387
443
  t.tag = ''
388
444
  t.content = '\n'
389
445
  }
390
- if (!opt.mditAttrs && t.tag === 'br') {
446
+ if (!attrsEnabled && t.tag === 'br') {
391
447
  t.tag = ''
392
448
  t.content = '\n'
393
449
  }
@@ -398,13 +454,11 @@ const setToken = (state, inlines, opt) => {
398
454
  }
399
455
  }
400
456
 
401
- if (/_close$/.test(type)) {
457
+ if (isClose) {
402
458
  const closeToken = state.push(type, tag, -1)
403
459
  closeToken.markup = tag === 'strong' ? '**' : '*'
404
- attrsIsText = {
405
- val: false,
406
- tag: '',
407
- }
460
+ attrsIsText = false
461
+ attrsIsTextTag = ''
408
462
  }
409
463
 
410
464
  i++
@@ -425,71 +479,81 @@ const pushInlines = (inlines, s, e, len, type, tag, tagType) => {
425
479
  inlines.push(inline)
426
480
  }
427
481
 
428
- const findNextSymbolPos = (state, n, max, symbol) => {
482
+ const isAsciiPunctuationCode = (code) => {
483
+ return (code >= 33 && code <= 47) || (code >= 58 && code <= 64) ||
484
+ (code >= 91 && code <= 96) || (code >= 123 && code <= 126)
485
+ }
486
+
487
+ const findNextAsciiPunctuation = (src, start, max) => {
488
+ REG_ASCII_PUNCT.lastIndex = start
489
+ const match = REG_ASCII_PUNCT.exec(src)
490
+ if (!match || match.index >= max) return -1
491
+ return match.index
492
+ }
493
+
494
+ const findNextSymbolPos = (state, n, max, symbol, symbolChar) => {
429
495
  const src = state.src
430
496
  if (src.charCodeAt(n) !== symbol || hasBackslash(state, n)) return -1
431
- for (let i = n + 1; i < max; i++) {
432
- if (src.charCodeAt(i) === symbol && !hasBackslash(state, i)) {
433
- return i
434
- }
497
+ let i = src.indexOf(symbolChar, n + 1)
498
+ while (i !== -1 && i < max) {
499
+ if (!hasBackslash(state, i)) return i
500
+ i = src.indexOf(symbolChar, i + 1)
435
501
  }
436
502
  return -1
437
503
  }
438
504
 
439
- const processSymbolPair = (state, n, srcLen, symbol, noMark, textStart, pushInlines) => {
440
- const nextSymbolPos = findNextSymbolPos(state, n, srcLen, symbol)
505
+ const processSymbolPair = (state, n, srcLen, symbol, symbolChar, hasText, textStart, pushInlines) => {
506
+ const nextSymbolPos = findNextSymbolPos(state, n, srcLen, symbol, symbolChar)
441
507
  if (nextSymbolPos === -1) {
442
- return { shouldBreak: false, shouldContinue: false, newN: n, newNoMark: noMark }
508
+ return { shouldBreak: false, shouldContinue: false, newN: n, hasText: hasText }
443
509
  }
444
- const src = state.src
445
- const innerText = src.slice(n + 1, nextSymbolPos)
446
- const markup = src.slice(n, nextSymbolPos + 1)
447
- const newNoMark = noMark + innerText + markup
448
510
  if (nextSymbolPos === srcLen - 1) {
449
511
  pushInlines(textStart, nextSymbolPos, nextSymbolPos - textStart + 1, 'text')
450
- return { shouldBreak: true, newN: nextSymbolPos + 1, newNoMark }
512
+ return { shouldBreak: true, newN: nextSymbolPos + 1, hasText: true }
451
513
  }
452
- return { shouldBreak: false, shouldContinue: true, newN: nextSymbolPos + 1, newNoMark }
514
+ return { shouldBreak: false, shouldContinue: true, newN: nextSymbolPos + 1, hasText: true }
453
515
  }
454
516
 
455
- const processTextSegment = (inlines, textStart, n, noMark) => {
456
- if (n !== 0 && noMark.length !== 0) {
517
+ const processTextSegment = (inlines, textStart, n, hasText) => {
518
+ if (n !== 0 && hasText) {
457
519
  pushInlines(inlines, textStart, n - 1, n - textStart, 'text')
458
- return ''
520
+ return false
459
521
  }
460
- return noMark
522
+ return hasText
461
523
  }
462
524
 
463
525
  const createInlines = (state, start, max, opt) => {
464
526
  const src = state.src
465
527
  const srcLen = max
466
528
  const htmlEnabled = state.md.options.html
529
+ const dollarMath = opt.dollarMath
467
530
  let n = start
468
531
  let inlines = []
469
- let noMark = ''
532
+ let hasText = false
470
533
  let textStart = n
471
534
 
472
- // Infinite loop prevention
473
- const maxIterations = srcLen * 2 // Safe upper bound
474
- let iterations = 0
475
-
476
535
  while (n < srcLen) {
477
- // Prevent infinite loops
478
- iterations++
479
- if (iterations > maxIterations) {
480
- // Add remaining text as-is and exit safely
481
- if (textStart < srcLen) {
482
- pushInlines(inlines, textStart, srcLen - 1, srcLen - textStart, 'text')
536
+ let currentChar = src.charCodeAt(n)
537
+
538
+ if (!isAsciiPunctuationCode(currentChar)) {
539
+ const nextPunc = findNextAsciiPunctuation(src, n, srcLen)
540
+ if (nextPunc === -1) {
541
+ if (textStart < srcLen) {
542
+ pushInlines(inlines, textStart, srcLen - 1, srcLen - textStart, 'text')
543
+ }
544
+ break
545
+ }
546
+ if (nextPunc > n) {
547
+ hasText = true
548
+ n = nextPunc
549
+ currentChar = src.charCodeAt(n)
483
550
  }
484
- break
485
551
  }
486
552
 
487
- const currentChar = src.charCodeAt(n)
488
-
489
553
  // Unified escape check
490
554
  let isEscaped = false
491
555
  if (currentChar === CHAR_ASTERISK || currentChar === CHAR_BACKTICK ||
492
- (opt.dollarMath && currentChar === CHAR_DOLLAR) ||
556
+ (dollarMath && currentChar === CHAR_DOLLAR) ||
493
557
  (htmlEnabled && currentChar === CHAR_LT)) {
494
558
  isEscaped = hasBackslash(state, n)
495
559
  }
@@ -497,7 +561,7 @@ const createInlines = (state, start, max, opt) => {
497
561
  // Asterisk handling
498
562
  if (currentChar === CHAR_ASTERISK) {
499
563
  if (!isEscaped) {
500
- noMark = processTextSegment(inlines, textStart, n, noMark)
564
+ hasText = processTextSegment(inlines, textStart, n, hasText)
501
565
  if (n === srcLen - 1) {
502
566
  pushInlines(inlines, n, n, 1, '')
503
567
  break
@@ -511,6 +575,7 @@ const createInlines = (state, start, max, opt) => {
511
575
  } else {
512
576
  pushInlines(inlines, n, i - 1, i - n, '')
513
577
  textStart = i
578
+ hasText = false
514
579
  }
515
580
  n = i
516
581
  continue
@@ -520,30 +585,30 @@ const createInlines = (state, start, max, opt) => {
520
585
  // Inline code (backticks)
521
586
  if (currentChar === CHAR_BACKTICK) {
522
587
  if (!isEscaped) {
523
- const result = processSymbolPair(state, n, srcLen, CHAR_BACKTICK, noMark, textStart,
588
+ const result = processSymbolPair(state, n, srcLen, CHAR_BACKTICK, '`', hasText, textStart,
524
589
  (start, end, len, type) => pushInlines(inlines, start, end, len, type))
525
590
  if (result.shouldBreak) break
526
591
  if (result.shouldContinue) {
527
592
  n = result.newN
528
- noMark = result.newNoMark
593
+ hasText = result.hasText
529
594
  continue
530
595
  }
531
- noMark = result.newNoMark
596
+ hasText = result.hasText
532
597
  }
533
598
  }
534
599
 
535
600
  // Inline math ($...$)
536
- if (opt.dollarMath && currentChar === CHAR_DOLLAR) {
601
+ if (dollarMath && currentChar === CHAR_DOLLAR) {
537
602
  if (!isEscaped) {
538
- const result = processSymbolPair(state, n, srcLen, CHAR_DOLLAR, noMark, textStart,
603
+ const result = processSymbolPair(state, n, srcLen, CHAR_DOLLAR, '$', hasText, textStart,
539
604
  (start, end, len, type) => pushInlines(inlines, start, end, len, type))
540
605
  if (result.shouldBreak) break
541
606
  if (result.shouldContinue) {
542
607
  n = result.newN
543
- noMark = result.newNoMark
608
+ hasText = result.hasText
544
609
  continue
545
610
  }
546
- noMark = result.newNoMark
611
+ hasText = result.hasText
547
612
  }
548
613
  }
549
614
 
@@ -551,9 +616,12 @@ const createInlines = (state, start, max, opt) => {
551
616
  if (htmlEnabled && currentChar === CHAR_LT) {
552
617
  if (!isEscaped) {
553
618
  let foundClosingTag = false
554
- for (let i = n + 1; i < srcLen; i++) {
555
- if (src.charCodeAt(i) === CHAR_GT && !hasBackslash(state, i)) {
556
- noMark = processTextSegment(inlines, textStart, n, noMark)
619
+ let i = n + 1
620
+ while (i < srcLen) {
621
+ i = src.indexOf('>', i)
622
+ if (i === -1 || i >= srcLen) break
623
+ if (!hasBackslash(state, i)) {
624
+ hasText = processTextSegment(inlines, textStart, n, hasText)
557
625
  let tag = src.slice(n + 1, i)
558
626
  let tagType
559
627
  if (tag.charCodeAt(0) === CHAR_SLASH) {
@@ -564,10 +632,12 @@ const createInlines = (state, start, max, opt) => {
564
632
  }
565
633
  pushInlines(inlines, n, i, i - n + 1, 'html_inline', tag, tagType)
566
634
  textStart = i + 1
635
+ hasText = false
567
636
  n = i + 1
568
637
  foundClosingTag = true
569
638
  break
570
639
  }
640
+ i += 1
571
641
  }
572
642
  if (foundClosingTag) {
573
643
  continue
@@ -577,7 +647,7 @@ const createInlines = (state, start, max, opt) => {
577
647
  }
578
648
 
579
649
  // Regular character
580
- noMark += src[n]
650
+ hasText = true
581
651
  if (n === srcLen - 1) {
582
652
  pushInlines(inlines, textStart, n, n - textStart + 1, 'text')
583
653
  break
@@ -597,6 +667,10 @@ const pushMark = (marks, opts) => {
597
667
  oLen: opts.oLen,
598
668
  type: opts.type
599
669
  }
670
+ if (marks.length === 0 || marks[marks.length - 1].s <= newMark.s) {
671
+ marks.push(newMark)
672
+ return
673
+ }
600
674
  // Binary search for insertion point to maintain sorted order
601
675
  let left = 0
602
676
  let right = marks.length
@@ -613,16 +687,17 @@ const pushMark = (marks, opts) => {
613
687
  }
614
688
 
615
689
  const setStrong = (state, inlines, marks, n, memo, opt, nestTracker, refRanges, inlineLinkRanges) => {
690
+ const hasInlineLinkRanges = inlineLinkRanges && inlineLinkRanges.length > 0
691
+ const hasRefRanges = refRanges && refRanges.length > 0
692
+ const inlinesLength = inlines.length
616
693
  if (opt.disallowMixed === true) {
617
694
  let i = n + 1
618
- const inlinesLength = inlines.length
619
695
  while (i < inlinesLength) {
620
696
  if (inlines[i].len === 0 || inlines[i].check) { i++; continue }
621
697
  if (inlines[i].type !== '') { i++; continue }
622
698
 
623
699
  if (inlines[i].len > 1) {
624
- const mixedCheck = checkMixedLanguagePattern(state, inlines, n, i, opt)
625
- if (mixedCheck.shouldBlock) {
700
+ if (shouldBlockMixedLanguage(state, inlines, n, i)) {
626
701
  return [n, 0]
627
702
  }
628
703
  break
@@ -631,33 +706,25 @@ const setStrong = (state, inlines, marks, n, memo, opt, nestTracker, refRanges,
631
706
  }
632
707
  }
633
708
 
634
- const strongOpenRange = findRefRangeIndex(inlines[n].s, refRanges)
635
- const openLinkRange = findInlineLinkRange(inlines[n].s, inlineLinkRanges)
709
+ const strongOpenRange = hasRefRanges ? findRefRangeIndex(inlines[n].s, refRanges) : -1
710
+ const openLinkRange = hasInlineLinkRanges ? findInlineLinkRange(inlines[n].s, inlineLinkRanges) : null
636
711
  let i = n + 1
637
712
  let j = 0
638
713
  let nest = 0
639
- let insideTagsIsClose = 1
640
- const inlinesLength = inlines.length
641
714
  while (i < inlinesLength) {
642
715
  if (inlines[i].type !== '') { i++; continue }
643
716
  if (inlines[i].len === 0 || inlines[i].check) { i++; continue }
644
- if (inlines[i].type === 'html_inline') {
645
- inlines[i].check = true
646
- insideTagsIsClose = checkInsideTags(inlines, i, memo)
647
- if (insideTagsIsClose === -1) return [n, nest]
648
- if (insideTagsIsClose === 0) { i++; continue }
649
- }
650
717
 
651
- if (inlineLinkRanges && inlineLinkRanges.length > 0 &&
718
+ if (hasInlineLinkRanges &&
652
719
  hasInlineLinkLabelCrossing(inlineLinkRanges, inlines[n].ep + 1, inlines[i].sp)) {
653
720
  i++
654
721
  continue
655
722
  }
656
723
 
657
- const closeRange = findRefRangeIndex(inlines[i].s, refRanges)
724
+ const closeRange = hasRefRanges ? findRefRangeIndex(inlines[i].s, refRanges) : -1
658
725
  if (strongOpenRange !== closeRange) { i++; continue }
659
726
 
660
- const closeLinkRange = findInlineLinkRange(inlines[i].s, inlineLinkRanges)
727
+ const closeLinkRange = hasInlineLinkRanges ? findInlineLinkRange(inlines[i].s, inlineLinkRanges) : null
661
728
  if (openLinkRange || closeLinkRange) {
662
729
  if (!openLinkRange || !closeLinkRange || openLinkRange.id !== closeLinkRange.id || openLinkRange.kind !== closeLinkRange.kind) {
663
730
  i++
@@ -689,16 +756,14 @@ const setStrong = (state, inlines, marks, n, memo, opt, nestTracker, refRanges,
689
756
  inlines[n].ep -= 1
690
757
  inlines[i].len -= 1
691
758
  if (inlines[i].len > 0) inlines[i].sp += 1
692
- if (insideTagsIsClose === 1) {
693
- const [newN, newNest] = setEm(state, inlines, marks, n, memo, opt, null, nestTracker, refRanges, inlineLinkRanges)
694
- n = newN
695
- nest = newNest
696
- }
759
+ const [newN, newNest] = setEm(state, inlines, marks, n, memo, opt, null, nestTracker, refRanges, inlineLinkRanges)
760
+ n = newN
761
+ nest = newNest
697
762
  }
698
763
  let strongNum = Math.trunc(Math.min(inlines[n].len, inlines[i].len) / 2)
699
764
 
700
765
  if (inlines[i].len > 1) {
701
- if (hasPunctuationOrNonJapanese(state, inlines, n, i, opt, refRanges)) {
766
+ if (hasPunctuationOrNonJapanese(state, inlines, n, i, opt, refRanges, hasRefRanges)) {
702
767
  if (memo.inlineMarkEnd) {
703
768
  marks.push(...createMarks(state, inlines, i, inlinesLength - 1, memo, opt, refRanges, inlineLinkRanges))
704
769
  if (inlines[i].len === 0) { i++; continue }
@@ -756,21 +821,19 @@ const checkInsideTags = (inlines, i, memo) => {
756
821
  if (memo.htmlTags[tagName] === undefined) {
757
822
  memo.htmlTags[tagName] = 0
758
823
  }
759
- if (inlines[i].tag[1] === 'open') {
824
+ const tagType = inlines[i].tag[1]
825
+ if (tagType === 'open') {
760
826
  memo.htmlTags[tagName] += 1
827
+ memo.htmlTagDepth += 1
761
828
  }
762
- if (inlines[i].tag[1] === 'close') {
829
+ if (tagType === 'close') {
763
830
  memo.htmlTags[tagName] -= 1
831
+ memo.htmlTagDepth -= 1
764
832
  }
765
- if (memo.htmlTags[tagName] < 0) {
833
+ if (memo.htmlTags[tagName] < 0 || memo.htmlTagDepth < 0) {
766
834
  return -1
767
835
  }
768
-
769
- // Direct check instead of Object.values().every()
770
- for (const count of Object.values(memo.htmlTags)) {
771
- if (count !== 0) return 0
772
- }
773
- return 1
836
+ return memo.htmlTagDepth === 0 ? 1 : 0
774
837
  }
775
838
 
776
839
  // Check if character is ASCII punctuation or space
@@ -799,7 +862,7 @@ const isJapanese = (ch) => {
799
862
  }
800
863
 
801
864
  // Check if character is English (letters, numbers) or other non-Japanese characters
802
- // Uses REG_JAPANESE and REG_PUNCTUATION to exclude Japanese and punctuation characters
865
+ // Uses REG_JAPANESE to exclude Japanese characters
803
866
  const isEnglish = (ch) => {
804
867
  if (!ch) return false
805
868
  const code = ch.charCodeAt(0)
@@ -809,10 +872,10 @@ const isEnglish = (ch) => {
809
872
  if (code < 128) {
810
873
  return code === CHAR_SPACE || (code > 126)
811
874
  }
812
- return !REG_JAPANESE.test(ch) && !REG_PUNCTUATION.test(ch)
875
+ return !REG_JAPANESE.test(ch)
813
876
  }
814
877
 
815
- const checkMixedLanguagePattern = (state, inlines, n, i, opt) => {
878
+ const shouldBlockMixedLanguage = (state, inlines, n, i) => {
816
879
  const src = state.src
817
880
  const openPrevChar = src[inlines[n].s - 1] || ''
818
881
  const closeNextChar = src[inlines[i].e + 1] || ''
@@ -820,25 +883,17 @@ const checkMixedLanguagePattern = (state, inlines, n, i, opt) => {
820
883
  const isEnglishPrefix = isEnglish(openPrevChar)
821
884
  const isEnglishSuffix = isEnglish(closeNextChar)
822
885
  if (!isEnglishPrefix && !isEnglishSuffix) {
823
- return { hasEnglishContext: false, hasMarkdownOrHtml: false, shouldBlock: false }
824
- }
825
-
826
- const contentBetween = src.slice(inlines[n].e + 1, inlines[i].s)
827
- const hasMarkdownOrHtml = REG_MARKDOWN_HTML.test(contentBetween)
828
-
829
- return {
830
- hasEnglishContext: true,
831
- hasMarkdownOrHtml,
832
- shouldBlock: hasMarkdownOrHtml
886
+ return false
833
887
  }
888
+ return hasMarkdownHtmlPattern(src, inlines[n].e + 1, inlines[i].s)
834
889
  }
835
890
 
836
- const hasPunctuationOrNonJapanese = (state, inlines, n, i, opt, refRanges) => {
891
+ const hasPunctuationOrNonJapanese = (state, inlines, n, i, opt, refRanges, hasRefRanges) => {
837
892
  const src = state.src
838
893
  const openPrevChar = src[inlines[n].s - 1] || ''
839
894
  const openNextChar = src[inlines[n].e + 1] || ''
840
895
  let checkOpenNextChar = isPunctuation(openNextChar)
841
- if (checkOpenNextChar && (openNextChar === '[' || openNextChar === ']')) {
896
+ if (hasRefRanges && checkOpenNextChar && (openNextChar === '[' || openNextChar === ']')) {
842
897
  const openNextRange = findRefRangeIndex(inlines[n].e + 1, refRanges)
843
898
  if (openNextRange !== -1) {
844
899
  checkOpenNextChar = false
@@ -846,19 +901,19 @@ const hasPunctuationOrNonJapanese = (state, inlines, n, i, opt, refRanges) => {
846
901
  }
847
902
  const closePrevChar = src[inlines[i].s - 1] || ''
848
903
  let checkClosePrevChar = isPunctuation(closePrevChar)
849
- if (checkClosePrevChar && (closePrevChar === '[' || closePrevChar === ']')) {
904
+ if (hasRefRanges && checkClosePrevChar && (closePrevChar === '[' || closePrevChar === ']')) {
850
905
  const closePrevRange = findRefRangeIndex(inlines[i].s - 1, refRanges)
851
906
  if (closePrevRange !== -1) {
852
907
  checkClosePrevChar = false
853
908
  }
854
909
  }
855
910
  const closeNextChar = src[inlines[i].e + 1] || ''
856
- const checkCloseNextChar = (isPunctuation(closeNextChar) || i === inlines.length - 1)
911
+ const isLastInline = i === inlines.length - 1
912
+ const checkCloseNextChar = isLastInline || isPunctuation(closeNextChar) || closeNextChar === '\n'
857
913
 
858
914
  if (opt.disallowMixed === false) {
859
915
  if (isEnglish(openPrevChar) || isEnglish(closeNextChar)) {
860
- const contentBetween = src.slice(inlines[n].e + 1, inlines[i].s)
861
- if (REG_MARKDOWN_HTML.test(contentBetween)) {
916
+ if (hasMarkdownHtmlPattern(src, inlines[n].e + 1, inlines[i].s)) {
862
917
  return false
863
918
  }
864
919
  }
@@ -869,18 +924,19 @@ const hasPunctuationOrNonJapanese = (state, inlines, n, i, opt, refRanges) => {
869
924
  }
870
925
 
871
926
  const setEm = (state, inlines, marks, n, memo, opt, sNest, nestTracker, refRanges, inlineLinkRanges) => {
872
- const emOpenRange = findRefRangeIndex(inlines[n].s, refRanges)
873
- const openLinkRange = findInlineLinkRange(inlines[n].s, inlineLinkRanges)
927
+ const hasInlineLinkRanges = inlineLinkRanges && inlineLinkRanges.length > 0
928
+ const hasRefRanges = refRanges && refRanges.length > 0
929
+ const inlinesLength = inlines.length
930
+ const emOpenRange = hasRefRanges ? findRefRangeIndex(inlines[n].s, refRanges) : -1
931
+ const openLinkRange = hasInlineLinkRanges ? findInlineLinkRange(inlines[n].s, inlineLinkRanges) : null
874
932
  if (opt.disallowMixed === true && !sNest) {
875
933
  let i = n + 1
876
- const inlinesLength = inlines.length
877
934
  while (i < inlinesLength) {
878
935
  if (inlines[i].len === 0 || inlines[i].check) { i++; continue }
879
936
  if (inlines[i].type !== '') { i++; continue }
880
937
 
881
938
  if (inlines[i].len > 0) {
882
- const mixedCheck = checkMixedLanguagePattern(state, inlines, n, i, opt)
883
- if (mixedCheck.shouldBlock) {
939
+ if (shouldBlockMixedLanguage(state, inlines, n, i)) {
884
940
  return [n, 0]
885
941
  }
886
942
  break
@@ -893,7 +949,6 @@ const setEm = (state, inlines, marks, n, memo, opt, sNest, nestTracker, refRange
893
949
  let nest = 0
894
950
  let strongPNum = 0
895
951
  let insideTagsIsClose = 1
896
- const inlinesLength = inlines.length
897
952
  while (i < inlinesLength) {
898
953
  if (inlines[i].len === 0 || inlines[i].check) { i++; continue }
899
954
  if (!sNest && inlines[i].type === 'html_inline') {
@@ -904,19 +959,19 @@ const setEm = (state, inlines, marks, n, memo, opt, sNest, nestTracker, refRange
904
959
  }
905
960
  if (inlines[i].type !== '') { i++; continue }
906
961
 
907
- if (inlineLinkRanges && inlineLinkRanges.length > 0 &&
962
+ if (hasInlineLinkRanges &&
908
963
  hasInlineLinkLabelCrossing(inlineLinkRanges, inlines[n].ep + 1, inlines[i].sp)) {
909
964
  i++
910
965
  continue
911
966
  }
912
967
 
913
- const closeRange = findRefRangeIndex(inlines[i].s, refRanges)
968
+ const closeRange = hasRefRanges ? findRefRangeIndex(inlines[i].s, refRanges) : -1
914
969
  if (emOpenRange !== closeRange) {
915
970
  i++
916
971
  continue
917
972
  }
918
973
 
919
- const closeLinkRange = findInlineLinkRange(inlines[i].s, inlineLinkRanges)
974
+ const closeLinkRange = hasInlineLinkRanges ? findInlineLinkRange(inlines[i].s, inlineLinkRanges) : null
920
975
  if (openLinkRange || closeLinkRange) {
921
976
  if (!openLinkRange || !closeLinkRange || openLinkRange.id !== closeLinkRange.id || openLinkRange.kind !== closeLinkRange.kind) {
922
977
  i++
@@ -928,15 +983,10 @@ const setEm = (state, inlines, marks, n, memo, opt, sNest, nestTracker, refRange
928
983
 
929
984
  if (!sNest && emNum !== 1) return [n, sNest, memo]
930
985
 
931
- const hasMarkersAtStartAndEnd = (i) => {
932
- let flag = memo.inlineMarkStart
933
- if (!flag) return false
934
- inlinesLength - 1 === i ? flag = true : flag = false
935
- if (!flag) return false
936
- inlines[i].len > 1 ? flag = true : flag = false
937
- return flag
938
- }
939
- if (!sNest && inlines[i].len === 2 && !hasMarkersAtStartAndEnd(i)) {
986
+ const isMarkerAtStartAndEnd = memo.inlineMarkStart &&
987
+ i === inlinesLength - 1 &&
988
+ inlines[i].len > 1
989
+ if (!sNest && inlines[i].len === 2 && !isMarkerAtStartAndEnd) {
940
990
  strongPNum++
941
991
  i++
942
992
  continue
@@ -950,7 +1000,7 @@ const setEm = (state, inlines, marks, n, memo, opt, sNest, nestTracker, refRange
950
1000
  if (nest === -1) return [n, nest]
951
1001
 
952
1002
  if (emNum === 1) {
953
- if (hasPunctuationOrNonJapanese(state, inlines, n, i, opt, refRanges)) {
1003
+ if (hasPunctuationOrNonJapanese(state, inlines, n, i, opt, refRanges, hasRefRanges)) {
954
1004
  if (memo.inlineMarkEnd) {
955
1005
  marks.push(...createMarks(state, inlines, i, inlinesLength - 1, memo, opt, refRanges, inlineLinkRanges))
956
1006
 
@@ -1102,7 +1152,33 @@ const mergeInlinesAndMarks = (inlines, marks) => {
1102
1152
  return merged
1103
1153
  }
1104
1154
 
1105
- const isWhitespaceToken = (token) => token && token.type === 'text' && token.content.trim() === ''
1155
+ const isWhitespaceToken = (token) => {
1156
+ if (!token || token.type !== 'text') return false
1157
+ const content = token.content
1158
+ if (!content) return true
1159
+ for (let i = 0; i < content.length; i++) {
1160
+ if (!isWhiteSpace(content.charCodeAt(i))) return false
1161
+ }
1162
+ return true
1163
+ }
1164
+
1165
+ const hasMarkdownHtmlPattern = (src, start, end) => {
1166
+ if (start >= end) return false
1167
+ const first = src.charCodeAt(start)
1168
+ const last = src.charCodeAt(end - 1)
1169
+ if (first === CHAR_OPEN_BRACKET) {
1170
+ if (last !== CHAR_CLOSE_PAREN) return false
1171
+ } else if (first === CHAR_LT) {
1172
+ if (last !== CHAR_GT) return false
1173
+ } else if (first === CHAR_BACKTICK) {
1174
+ if (last !== CHAR_BACKTICK) return false
1175
+ } else if (first === CHAR_DOLLAR) {
1176
+ if (last !== CHAR_DOLLAR) return false
1177
+ } else {
1178
+ return false
1179
+ }
1180
+ return REG_MARKDOWN_HTML.test(src.slice(start, end))
1181
+ }
1106
1182
 
1107
1183
  const strongJa = (state, silent, opt) => {
1108
1184
  if (silent) return false
@@ -1115,13 +1191,16 @@ const strongJa = (state, silent, opt) => {
1115
1191
  if (src.charCodeAt(start) !== CHAR_ASTERISK) return false
1116
1192
  if (hasBackslash(state, start)) return false
1117
1193
 
1194
+ const attrsEnabled = opt.mditAttrs && hasMditAttrs(state)
1195
+
1118
1196
  if (start === 0) {
1119
1197
  state.__strongJaRefRangeCache = null
1120
1198
  state.__strongJaInlineLinkRangeCache = null
1121
1199
  state.__strongJaBackslashCache = undefined
1200
+ state.__strongJaHasBackslash = undefined
1122
1201
  }
1123
1202
 
1124
- if (opt.mditAttrs) {
1203
+ if (attrsEnabled) {
1125
1204
  let attrCandidate = false
1126
1205
  let probe = originalMax - 1
1127
1206
  while (probe >= start) {
@@ -1158,7 +1237,8 @@ const strongJa = (state, silent, opt) => {
1158
1237
  }
1159
1238
 
1160
1239
  if (state.__strongJaHasCollapsedRefs === undefined) {
1161
- state.__strongJaHasCollapsedRefs = /\[[^\]]*\]\s*\[[^\]]*\]/.test(state.src)
1240
+ state.__strongJaHasCollapsedRefs = src.indexOf('[') !== -1 &&
1241
+ /\[[^\]]*\]\s*\[[^\]]*\]/.test(src)
1162
1242
  }
1163
1243
 
1164
1244
  if (state.__strongJaReferenceCount === undefined) {
@@ -1201,6 +1281,7 @@ const strongJa = (state, silent, opt) => {
1201
1281
  const memo = {
1202
1282
  html: state.md.options.html,
1203
1283
  htmlTags: {},
1284
+ htmlTagDepth: 0,
1204
1285
  inlineMarkStart: src.charCodeAt(0) === CHAR_ASTERISK,
1205
1286
  inlineMarkEnd: src.charCodeAt(max - 1) === CHAR_ASTERISK,
1206
1287
  }
@@ -1209,7 +1290,7 @@ const strongJa = (state, silent, opt) => {
1209
1290
 
1210
1291
  inlines = mergeInlinesAndMarks(inlines, marks)
1211
1292
 
1212
- setToken(state, inlines, opt)
1293
+ setToken(state, inlines, opt, attrsEnabled)
1213
1294
 
1214
1295
  if (inlineLinkRanges && inlineLinkRanges.length > 0) {
1215
1296
  const labelSources = []
@@ -1231,7 +1312,7 @@ const strongJa = (state, silent, opt) => {
1231
1312
  state.__strongJaPostProcessRegistered = true
1232
1313
  }
1233
1314
 
1234
- if (opt.mditAttrs && max !== state.posMax) {
1315
+ if (attrsEnabled && max !== state.posMax) {
1235
1316
  if (!attributesSrc) {
1236
1317
  state.pos = max
1237
1318
  return true
@@ -1244,9 +1325,12 @@ const strongJa = (state, silent, opt) => {
1244
1325
  }
1245
1326
 
1246
1327
  // Collapsed reference helpers
1247
- const buildReferenceLabel = (tokens) => {
1328
+ const buildReferenceLabelRange = (tokens, startIdx, endIdx) => {
1329
+ if (startIdx > endIdx) return ''
1248
1330
  let label = ''
1249
- for (const token of tokens) {
1331
+ for (let idx = startIdx; idx <= endIdx; idx++) {
1332
+ const token = tokens[idx]
1333
+ if (!token) continue
1250
1334
  if (token.type === 'text' || token.type === 'code_inline') {
1251
1335
  label += token.content
1252
1336
  } else if (token.type === 'softbreak' || token.type === 'hardbreak') {
@@ -1261,11 +1345,12 @@ const buildReferenceLabel = (tokens) => {
1261
1345
  }
1262
1346
 
1263
1347
  const cleanLabelText = (label) => {
1348
+ if (label.indexOf('*') === -1 && label.indexOf('_') === -1) return label
1264
1349
  return label.replace(/^[*_]+/, '').replace(/[*_]+$/, '')
1265
1350
  }
1266
1351
 
1267
1352
  const normalizeReferenceCandidate = (state, text, { useClean = false } = {}) => {
1268
- const source = useClean ? cleanLabelText(text) : text.replace(/\s+/g, ' ').trim()
1353
+ const source = useClean ? cleanLabelText(text) : text
1269
1354
  return normalizeRefKey(state, source)
1270
1355
  }
1271
1356
 
@@ -1325,7 +1410,9 @@ const splitBracketToken = (tokens, index, options) => {
1325
1410
  let buffer = ''
1326
1411
  let pos = 0
1327
1412
  while (pos < content.length) {
1328
- if (!splitEmptyPair && content.startsWith('[]', pos)) {
1413
+ if (!splitEmptyPair &&
1414
+ content.charCodeAt(pos) === CHAR_OPEN_BRACKET &&
1415
+ content.charCodeAt(pos + 1) === CHAR_CLOSE_BRACKET) {
1329
1416
  if (buffer) {
1330
1417
  segments.push(buffer)
1331
1418
  buffer = ''
@@ -1556,11 +1643,13 @@ const parseInlineLinkTail = (content, md) => {
1556
1643
 
1557
1644
  const INLINE_LINK_BRACKET_SPLIT_OPTIONS = { splitEmptyPair: true }
1558
1645
 
1559
- const removeGhostLabelText = (tokens, linkCloseToken, labelText) => {
1646
+ const removeGhostLabelText = (tokens, linkCloseIndex, labelText) => {
1560
1647
  if (!labelText) return
1561
- const closeIdx = tokens.indexOf(linkCloseToken)
1562
- if (closeIdx === -1) return
1563
- let idx = closeIdx + 1
1648
+ if (linkCloseIndex === null || linkCloseIndex === undefined) return
1649
+ if (linkCloseIndex < 0 || linkCloseIndex >= tokens.length) return
1650
+ const closeToken = tokens[linkCloseIndex]
1651
+ if (!closeToken || closeToken.type !== 'link_close') return
1652
+ let idx = linkCloseIndex + 1
1564
1653
  while (idx < tokens.length) {
1565
1654
  const token = tokens[idx]
1566
1655
  if (!token) {
@@ -1627,6 +1716,7 @@ const convertInlineLinks = (tokens, state) => {
1627
1716
  let tailIdx = closeIdx + 1
1628
1717
  let tailContent = ''
1629
1718
  let parsedTail = null
1719
+ let tailHasCloseParen = false
1630
1720
  while (tailIdx < tokens.length) {
1631
1721
  if (splitBracketToken(tokens, tailIdx, INLINE_LINK_BRACKET_SPLIT_OPTIONS)) {
1632
1722
  continue
@@ -1636,6 +1726,13 @@ const convertInlineLinks = (tokens, state) => {
1636
1726
  break
1637
1727
  }
1638
1728
  tailContent += tailToken.content
1729
+ if (!tailHasCloseParen) {
1730
+ if (tailToken.content.indexOf(')') === -1) {
1731
+ tailIdx++
1732
+ continue
1733
+ }
1734
+ tailHasCloseParen = true
1735
+ }
1639
1736
  parsedTail = parseInlineLinkTail(tailContent, state.md)
1640
1737
  if (parsedTail) break
1641
1738
  tailIdx++
@@ -1669,7 +1766,7 @@ const convertInlineLinks = (tokens, state) => {
1669
1766
  continue
1670
1767
  }
1671
1768
  if (needsPlaceholder && currentLabelSource) {
1672
- removeGhostLabelText(tokens, linkCloseToken, currentLabelSource)
1769
+ removeGhostLabelText(tokens, nextIndex - 1, currentLabelSource)
1673
1770
  }
1674
1771
 
1675
1772
  if (labelSources && labelSources.length > 0) {
@@ -1724,8 +1821,10 @@ const convertCollapsedReferenceLinks = (tokens, state) => {
1724
1821
  continue
1725
1822
  }
1726
1823
 
1727
- const labelTokens = tokens.slice(i + 1, closeIdx)
1728
- const labelText = buildReferenceLabel(labelTokens)
1824
+ const labelStart = i + 1
1825
+ const labelEnd = closeIdx - 1
1826
+ const labelLength = closeIdx - i - 1
1827
+ const labelText = buildReferenceLabelRange(tokens, labelStart, labelEnd)
1729
1828
  const cleanedLabel = cleanLabelText(labelText)
1730
1829
  const whitespaceStart = closeIdx + 1
1731
1830
  let refRemoveStart = whitespaceStart
@@ -1753,11 +1852,12 @@ const convertCollapsedReferenceLinks = (tokens, state) => {
1753
1852
  i++
1754
1853
  continue
1755
1854
  }
1756
- const refTokens = tokens.slice(refRemoveStart + 1, refCloseIdx)
1757
- if (refTokens.length === 0) {
1855
+ const refStart = refRemoveStart + 1
1856
+ const refEnd = refCloseIdx - 1
1857
+ if (refStart > refEnd) {
1758
1858
  refKey = normalizeReferenceCandidate(state, cleanedLabel)
1759
1859
  } else {
1760
- const refLabelText = buildReferenceLabel(refTokens)
1860
+ const refLabelText = buildReferenceLabelRange(tokens, refStart, refEnd)
1761
1861
  refKey = normalizeReferenceCandidate(state, refLabelText)
1762
1862
  }
1763
1863
  refRemoveCount = refCloseIdx - refRemoveStart + 1
@@ -1815,7 +1915,7 @@ const convertCollapsedReferenceLinks = (tokens, state) => {
1815
1915
  tokens.splice(closeIdx, 1)
1816
1916
  tokens.splice(i, 1)
1817
1917
 
1818
- const nextIndex = wrapLabelTokensWithLink(tokens, i, i + labelTokens.length - 1, linkOpenToken, linkCloseToken)
1918
+ const nextIndex = wrapLabelTokensWithLink(tokens, i, i + labelLength - 1, linkOpenToken, linkCloseToken)
1819
1919
  i = nextIndex
1820
1920
  }
1821
1921
  }
@@ -1889,6 +1989,22 @@ const mditStrongJa = (md, option) => {
1889
1989
  if (!targets || targets.length === 0) return
1890
1990
  for (const tokens of targets) {
1891
1991
  if (!tokens || !tokens.length) continue
1992
+ let hasBracketText = false
1993
+ for (let i = 0; i < tokens.length; i++) {
1994
+ const token = tokens[i]
1995
+ if (!token || token.type !== 'text') continue
1996
+ const content = token.content
1997
+ if (!content) continue
1998
+ if (content.indexOf('[') !== -1 || content.indexOf(']') !== -1) {
1999
+ hasBracketText = true
2000
+ break
2001
+ }
2002
+ }
2003
+ if (!hasBracketText) {
2004
+ delete tokens.__strongJaInlineLabelSources
2005
+ delete tokens.__strongJaInlineLabelIndex
2006
+ continue
2007
+ }
1892
2008
  convertInlineLinks(tokens, state)
1893
2009
  convertCollapsedReferenceLinks(tokens, state)
1894
2010
  mergeBrokenMarksAroundLinks(tokens)
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@peaceroad/markdown-it-strong-ja",
3
3
  "description": "This is a plugin for markdown-it. It is an alternative to the standard `**` (strong) and `*` (em) processing. It also processes strings that cannot be converted by the standard.",
4
- "version": "0.5.3",
4
+ "version": "0.5.5",
5
5
  "main": "index.js",
6
6
  "type": "module",
7
7
  "files": [
@@ -19,8 +19,10 @@
19
19
  "markdown-it": "^14.1.0"
20
20
  },
21
21
  "devDependencies": {
22
- "@peaceroad/markdown-it-hr-sandwiched-semantic-container": "^0.7.0",
23
- "@sup39/markdown-it-cjk-breaks": "^1.2.0",
24
- "markdown-it-attrs": "^4.2.0"
22
+ "@peaceroad/markdown-it-cjk-breaks-mod": "^0.1.1",
23
+ "@peaceroad/markdown-it-hr-sandwiched-semantic-container": "^0.8.0",
24
+ "markdown-it-attrs": "^4.3.1",
25
+ "markdown-it-sub": "^2.0.0",
26
+ "markdown-it-sup": "^2.0.0"
25
27
  }
26
28
  }