@@ -9,10 +9,10 @@ import type { _Lexer } from './Lexer.ts';
9
9
import type { Links , Tokens , Token } from './Tokens.ts' ;
10
10
import type { MarkedOptions } from './MarkedOptions.ts' ;
11
11
12
- function outputLink ( cap : string [ ] , link : Pick < Tokens . Link , 'href' | 'title' > , raw : string , lexer : _Lexer ) : Tokens . Link | Tokens . Image {
12
+ function outputLink ( cap : string [ ] , link : Pick < Tokens . Link , 'href' | 'title' > , raw : string , lexer : _Lexer , rules : Rules ) : Tokens . Link | Tokens . Image {
13
13
const href = link . href ;
14
14
const title = link . title || null ;
15
- const text = cap [ 1 ] . replace ( / \\ ( [ \[ \] ] ) / g , '$1' ) ;
15
+ const text = cap [ 1 ] . replace ( rules . other . outputLinkReplace , '$1' ) ;
16
16
17
17
if ( cap [ 0 ] . charAt ( 0 ) !== '!' ) {
18
18
lexer . state . inLink = true ;
@@ -36,8 +36,8 @@ function outputLink(cap: string[], link: Pick<Tokens.Link, 'href' | 'title'>, ra
36
36
} ;
37
37
}
38
38
39
- function indentCodeCompensation ( raw : string , text : string ) {
40
- const matchIndentToCode = raw . match ( / ^ ( \s + ) (?: ` ` ` ) / ) ;
39
+ function indentCodeCompensation ( raw : string , text : string , rules : Rules ) {
40
+ const matchIndentToCode = raw . match ( rules . other . indentCodeCompensation ) ;
41
41
42
42
if ( matchIndentToCode === null ) {
43
43
return text ;
@@ -48,7 +48,7 @@ function indentCodeCompensation(raw: string, text: string) {
48
48
return text
49
49
. split ( '\n' )
50
50
. map ( node => {
51
- const matchIndentInNode = node . match ( / ^ \s + / ) ;
51
+ const matchIndentInNode = node . match ( rules . other . beginningSpace ) ;
52
52
if ( matchIndentInNode === null ) {
53
53
return node ;
54
54
}
@@ -89,7 +89,7 @@ export class _Tokenizer {
89
89
code ( src : string ) : Tokens . Code | undefined {
90
90
const cap = this . rules . block . code . exec ( src ) ;
91
91
if ( cap ) {
92
- const text = cap [ 0 ] . replace ( / ^ (?: { 1 , 4 } | { 0 , 3 } \t ) / gm , '' ) ;
92
+ const text = cap [ 0 ] . replace ( this . rules . other . codeRemoveIndent , '' ) ;
93
93
return {
94
94
type : 'code' ,
95
95
raw : cap [ 0 ] ,
@@ -105,7 +105,7 @@ export class _Tokenizer {
105
105
const cap = this . rules . block . fences . exec ( src ) ;
106
106
if ( cap ) {
107
107
const raw = cap [ 0 ] ;
108
- const text = indentCodeCompensation ( raw , cap [ 3 ] || '' ) ;
108
+ const text = indentCodeCompensation ( raw , cap [ 3 ] || '' , this . rules ) ;
109
109
110
110
return {
111
111
type : 'code' ,
@@ -122,11 +122,11 @@ export class _Tokenizer {
122
122
let text = cap [ 2 ] . trim ( ) ;
123
123
124
124
// remove trailing #s
125
- if ( / # $ / . test ( text ) ) {
125
+ if ( this . rules . other . endingHash . test ( text ) ) {
126
126
const trimmed = rtrim ( text , '#' ) ;
127
127
if ( this . options . pedantic ) {
128
128
text = trimmed . trim ( ) ;
129
- } else if ( ! trimmed || / $ / . test ( trimmed ) ) {
129
+ } else if ( ! trimmed || this . rules . other . endingSpaceChar . test ( trimmed ) ) {
130
130
// CommonMark requires space before trailing #s
131
131
text = trimmed . trim ( ) ;
132
132
}
@@ -167,7 +167,7 @@ export class _Tokenizer {
167
167
let i ;
168
168
for ( i = 0 ; i < lines . length ; i ++ ) {
169
169
// get lines up to a continuation
170
- if ( / ^ { 0 , 3 } > / . test ( lines [ i ] ) ) {
170
+ if ( this . rules . other . blockquoteStart . test ( lines [ i ] ) ) {
171
171
currentLines . push ( lines [ i ] ) ;
172
172
inBlockquote = true ;
173
173
} else if ( ! inBlockquote ) {
@@ -181,8 +181,8 @@ export class _Tokenizer {
181
181
const currentRaw = currentLines . join ( '\n' ) ;
182
182
const currentText = currentRaw
183
183
// precede setext continuation with 4 spaces so it isn't a setext
184
- . replace ( / \n { 0 , 3 } ( (?: = + | - + ) * ) (? = \n | $ ) / g , '\n $1' )
185
- . replace ( / ^ { 0 , 3 } > [ \t ] ? / gm , '' ) ;
184
+ . replace ( this . rules . other . blockquoteSetextReplace , '\n $1' )
185
+ . replace ( this . rules . other . blockquoteSetextReplace2 , '' ) ;
186
186
raw = raw ? `${ raw } \n${ currentRaw } ` : currentRaw ;
187
187
text = text ? `${ text } \n${ currentText } ` : currentText ;
188
188
@@ -258,7 +258,7 @@ export class _Tokenizer {
258
258
}
259
259
260
260
// Get next list item
261
- const itemRegex = new RegExp ( `^( {0,3} ${ bull } )((?:[\t ][^\\n]*)?(?:\\n|$))` ) ;
261
+ const itemRegex = this . rules . other . listItemRegex ( bull ) ;
262
262
let endsWithBlankLine = false ;
263
263
// Check if current bullet point can start a new List Item
264
264
while ( src ) {
@@ -276,7 +276,7 @@ export class _Tokenizer {
276
276
raw = cap [ 0 ] ;
277
277
src = src . substring ( raw . length ) ;
278
278
279
- let line = cap [ 2 ] . split ( '\n' , 1 ) [ 0 ] . replace ( / ^ \t + / , ( t : string ) => ' ' . repeat ( 3 * t . length ) ) ;
279
+ let line = cap [ 2 ] . split ( '\n' , 1 ) [ 0 ] . replace ( this . rules . other . listReplaceTabs , ( t : string ) => ' ' . repeat ( 3 * t . length ) ) ;
280
280
let nextLine = src . split ( '\n' , 1 ) [ 0 ] ;
281
281
let blankLine = ! line . trim ( ) ;
282
282
@@ -287,24 +287,24 @@ export class _Tokenizer {
287
287
} else if ( blankLine ) {
288
288
indent = cap [ 1 ] . length + 1 ;
289
289
} else {
290
- indent = cap [ 2 ] . search ( / [ ^ ] / ) ; // Find first non-space char
290
+ indent = cap [ 2 ] . search ( this . rules . other . nonSpaceChar ) ; // Find first non-space char
291
291
indent = indent > 4 ? 1 : indent ; // Treat indented code blocks (> 4 spaces) as having only 1 indent
292
292
itemContents = line . slice ( indent ) ;
293
293
indent += cap [ 1 ] . length ;
294
294
}
295
295
296
- if ( blankLine && / ^ [ \t ] * $ / . test ( nextLine ) ) { // Items begin with at most one blank line
296
+ if ( blankLine && this . rules . other . blankLine . test ( nextLine ) ) { // Items begin with at most one blank line
297
297
raw += nextLine + '\n' ;
298
298
src = src . substring ( nextLine . length + 1 ) ;
299
299
endEarly = true ;
300
300
}
301
301
302
302
if ( ! endEarly ) {
303
- const nextBulletRegex = new RegExp ( `^ {0, ${ Math . min ( 3 , indent - 1 ) } }(?:[*+-]|\\d{1,9}[.)])((?:[ \t][^\\n]*)?(?:\\n|$))` ) ;
304
- const hrRegex = new RegExp ( `^ {0, ${ Math . min ( 3 , indent - 1 ) } }((?:- *){3,}|(?:_ *){3,}|(?:\\* *){3,})(?:\\n+|$)` ) ;
305
- const fencesBeginRegex = new RegExp ( `^ {0, ${ Math . min ( 3 , indent - 1 ) } }(?:\`\`\`|~~~)` ) ;
306
- const headingBeginRegex = new RegExp ( `^ {0, ${ Math . min ( 3 , indent - 1 ) } }#` ) ;
307
- const htmlBeginRegex = new RegExp ( `^ {0, ${ Math . min ( 3 , indent - 1 ) } }<(?:[a-z].*>|!--)` , 'i' ) ;
303
+ const nextBulletRegex = this . rules . other . nextBulletRegex ( indent ) ;
304
+ const hrRegex = this . rules . other . hrRegex ( indent ) ;
305
+ const fencesBeginRegex = this . rules . other . fencesBeginRegex ( indent ) ;
306
+ const headingBeginRegex = this . rules . other . headingBeginRegex ( indent ) ;
307
+ const htmlBeginRegex = this . rules . other . htmlBeginRegex ( indent ) ;
308
308
309
309
// Check if following lines should be included in List Item
310
310
while ( src ) {
@@ -314,10 +314,10 @@ export class _Tokenizer {
314
314
315
315
// Re-align to follow commonmark nesting rules
316
316
if ( this . options . pedantic ) {
317
- nextLine = nextLine . replace ( / ^ { 1 , 4 } (? = ( { 4 } ) * [ ^ ] ) / g , ' ' ) ;
317
+ nextLine = nextLine . replace ( this . rules . other . listReplaceNesting , ' ' ) ;
318
318
nextLineWithoutTabs = nextLine ;
319
319
} else {
320
- nextLineWithoutTabs = nextLine . replace ( / \t / g , ' ' ) ;
320
+ nextLineWithoutTabs = nextLine . replace ( this . rules . other . tabCharGlobal , ' ' ) ;
321
321
}
322
322
323
323
// End list item if found code fences
@@ -345,7 +345,7 @@ export class _Tokenizer {
345
345
break ;
346
346
}
347
347
348
- if ( nextLineWithoutTabs . search ( / [ ^ ] / ) >= indent || ! nextLine . trim ( ) ) { // Dedent if possible
348
+ if ( nextLineWithoutTabs . search ( this . rules . other . nonSpaceChar ) >= indent || ! nextLine . trim ( ) ) { // Dedent if possible
349
349
itemContents += '\n' + nextLineWithoutTabs . slice ( indent ) ;
350
350
} else {
351
351
// not enough indentation
@@ -354,7 +354,7 @@ export class _Tokenizer {
354
354
}
355
355
356
356
// paragraph continuation unless last line was a different block level element
357
- if ( line . replace ( / \t / g , ' ' ) . search ( / [ ^ ] / ) >= 4 ) { // indented code block
357
+ if ( line . replace ( this . rules . other . tabCharGlobal , ' ' ) . search ( this . rules . other . nonSpaceChar ) >= 4 ) { // indented code block
358
358
break ;
359
359
}
360
360
if ( fencesBeginRegex . test ( line ) ) {
@@ -384,7 +384,7 @@ export class _Tokenizer {
384
384
// If the previous item ended with a blank line, the list is loose
385
385
if ( endsWithBlankLine ) {
386
386
list . loose = true ;
387
- } else if ( / \n [ \t ] * \n [ \t ] * $ / . test ( raw ) ) {
387
+ } else if ( this . rules . other . doubleBlankLine . test ( raw ) ) {
388
388
endsWithBlankLine = true ;
389
389
}
390
390
}
@@ -393,10 +393,10 @@ export class _Tokenizer {
393
393
let ischecked : boolean | undefined ;
394
394
// Check for task list items
395
395
if ( this . options . gfm ) {
396
- istask = / ^ \[ [ x X ] \] / . exec ( itemContents ) ;
396
+ istask = this . rules . other . listIsTask . exec ( itemContents ) ;
397
397
if ( istask ) {
398
398
ischecked = istask [ 0 ] !== '[ ] ' ;
399
- itemContents = itemContents . replace ( / ^ \[ [ x X ] \] + / , '' ) ;
399
+ itemContents = itemContents . replace ( this . rules . other . listReplaceTask , '' ) ;
400
400
}
401
401
}
402
402
@@ -426,7 +426,7 @@ export class _Tokenizer {
426
426
if ( ! list . loose ) {
427
427
// Check if list should be loose
428
428
const spacers = list . items [ i ] . tokens . filter ( t => t . type === 'space' ) ;
429
- const hasMultipleLineBreaks = spacers . length > 0 && spacers . some ( t => / \n . * \n / . test ( t . raw ) ) ;
429
+ const hasMultipleLineBreaks = spacers . length > 0 && spacers . some ( t => this . rules . other . anyLine . test ( t . raw ) ) ;
430
430
431
431
list . loose = hasMultipleLineBreaks ;
432
432
}
@@ -460,8 +460,8 @@ export class _Tokenizer {
460
460
def ( src : string ) : Tokens . Def | undefined {
461
461
const cap = this . rules . block . def . exec ( src ) ;
462
462
if ( cap ) {
463
- const tag = cap [ 1 ] . toLowerCase ( ) . replace ( / \s + / g , ' ' ) ;
464
- const href = cap [ 2 ] ? cap [ 2 ] . replace ( / ^ < ( . * ) > $ / , '$1' ) . replace ( this . rules . inline . anyPunctuation , '$1' ) : '' ;
463
+ const tag = cap [ 1 ] . toLowerCase ( ) . replace ( this . rules . other . multipleSpaceGlobal , ' ' ) ;
464
+ const href = cap [ 2 ] ? cap [ 2 ] . replace ( this . rules . other . hrefBrackets , '$1' ) . replace ( this . rules . inline . anyPunctuation , '$1' ) : '' ;
465
465
const title = cap [ 3 ] ? cap [ 3 ] . substring ( 1 , cap [ 3 ] . length - 1 ) . replace ( this . rules . inline . anyPunctuation , '$1' ) : cap [ 3 ] ;
466
466
return {
467
467
type : 'def' ,
@@ -479,14 +479,14 @@ export class _Tokenizer {
479
479
return ;
480
480
}
481
481
482
- if ( ! / [: | ] / . test ( cap [ 2 ] ) ) {
482
+ if ( ! this . rules . other . tableDelimiter . test ( cap [ 2 ] ) ) {
483
483
// delimiter row must have a pipe (|) or colon (:) otherwise it is a setext heading
484
484
return ;
485
485
}
486
486
487
487
const headers = splitCells ( cap [ 1 ] ) ;
488
- const aligns = cap [ 2 ] . replace ( / ^ \| | \| * $ / g , '' ) . split ( '|' ) ;
489
- const rows = cap [ 3 ] && cap [ 3 ] . trim ( ) ? cap [ 3 ] . replace ( / \n [ \t ] * $ / , '' ) . split ( '\n' ) : [ ] ;
488
+ const aligns = cap [ 2 ] . replace ( this . rules . other . tableAlignChars , '' ) . split ( '|' ) ;
489
+ const rows = cap [ 3 ] && cap [ 3 ] . trim ( ) ? cap [ 3 ] . replace ( this . rules . other . tableRowBlankLine , '' ) . split ( '\n' ) : [ ] ;
490
490
491
491
const item : Tokens . Table = {
492
492
type : 'table' ,
@@ -502,11 +502,11 @@ export class _Tokenizer {
502
502
}
503
503
504
504
for ( const align of aligns ) {
505
- if ( / ^ * - + : * $ / . test ( align ) ) {
505
+ if ( this . rules . other . tableAlignRight . test ( align ) ) {
506
506
item . align . push ( 'right' ) ;
507
- } else if ( / ^ * : - + : * $ / . test ( align ) ) {
507
+ } else if ( this . rules . other . tableAlignCenter . test ( align ) ) {
508
508
item . align . push ( 'center' ) ;
509
- } else if ( / ^ * : - + * $ / . test ( align ) ) {
509
+ } else if ( this . rules . other . tableAlignLeft . test ( align ) ) {
510
510
item . align . push ( 'left' ) ;
511
511
} else {
512
512
item . align . push ( null ) ;
@@ -590,14 +590,14 @@ export class _Tokenizer {
590
590
tag ( src : string ) : Tokens . Tag | undefined {
591
591
const cap = this . rules . inline . tag . exec ( src ) ;
592
592
if ( cap ) {
593
- if ( ! this . lexer . state . inLink && / ^ < a / i . test ( cap [ 0 ] ) ) {
593
+ if ( ! this . lexer . state . inLink && this . rules . other . startATag . test ( cap [ 0 ] ) ) {
594
594
this . lexer . state . inLink = true ;
595
- } else if ( this . lexer . state . inLink && / ^ < \/ a > / i . test ( cap [ 0 ] ) ) {
595
+ } else if ( this . lexer . state . inLink && this . rules . other . endATag . test ( cap [ 0 ] ) ) {
596
596
this . lexer . state . inLink = false ;
597
597
}
598
- if ( ! this . lexer . state . inRawBlock && / ^ < ( p r e | c o d e | k b d | s c r i p t ) ( \s | > ) / i . test ( cap [ 0 ] ) ) {
598
+ if ( ! this . lexer . state . inRawBlock && this . rules . other . startPreScriptTag . test ( cap [ 0 ] ) ) {
599
599
this . lexer . state . inRawBlock = true ;
600
- } else if ( this . lexer . state . inRawBlock && / ^ < \/ ( p r e | c o d e | k b d | s c r i p t ) ( \s | > ) / i . test ( cap [ 0 ] ) ) {
600
+ } else if ( this . lexer . state . inRawBlock && this . rules . other . endPreScriptTag . test ( cap [ 0 ] ) ) {
601
601
this . lexer . state . inRawBlock = false ;
602
602
}
603
603
@@ -616,9 +616,9 @@ export class _Tokenizer {
616
616
const cap = this . rules . inline . link . exec ( src ) ;
617
617
if ( cap ) {
618
618
const trimmedUrl = cap [ 2 ] . trim ( ) ;
619
- if ( ! this . options . pedantic && / ^ < / . test ( trimmedUrl ) ) {
619
+ if ( ! this . options . pedantic && this . rules . other . startAngleBracket . test ( trimmedUrl ) ) {
620
620
// commonmark requires matching angle brackets
621
- if ( ! ( / > $ / . test ( trimmedUrl ) ) ) {
621
+ if ( ! ( this . rules . other . endAngleBracket . test ( trimmedUrl ) ) ) {
622
622
return ;
623
623
}
624
624
@@ -642,7 +642,7 @@ export class _Tokenizer {
642
642
let title = '' ;
643
643
if ( this . options . pedantic ) {
644
644
// split pedantic href and title
645
- const link = / ^ ( [ ^ ' " ] * [ ^ \s ] ) \s + ( [ ' " ] ) ( . * ) \2 / . exec ( href ) ;
645
+ const link = this . rules . other . pedanticHrefTitle . exec ( href ) ;
646
646
647
647
if ( link ) {
648
648
href = link [ 1 ] ;
@@ -653,8 +653,8 @@ export class _Tokenizer {
653
653
}
654
654
655
655
href = href . trim ( ) ;
656
- if ( / ^ < / . test ( href ) ) {
657
- if ( this . options . pedantic && ! ( / > $ / . test ( trimmedUrl ) ) ) {
656
+ if ( this . rules . other . startAngleBracket . test ( href ) ) {
657
+ if ( this . options . pedantic && ! ( this . rules . other . endAngleBracket . test ( trimmedUrl ) ) ) {
658
658
// pedantic allows starting angle bracket without ending angle bracket
659
659
href = href . slice ( 1 ) ;
660
660
} else {
@@ -664,15 +664,15 @@ export class _Tokenizer {
664
664
return outputLink ( cap , {
665
665
href : href ? href . replace ( this . rules . inline . anyPunctuation , '$1' ) : href ,
666
666
title : title ? title . replace ( this . rules . inline . anyPunctuation , '$1' ) : title ,
667
- } , cap [ 0 ] , this . lexer ) ;
667
+ } , cap [ 0 ] , this . lexer , this . rules ) ;
668
668
}
669
669
}
670
670
671
671
reflink ( src : string , links : Links ) : Tokens . Link | Tokens . Image | Tokens . Text | undefined {
672
672
let cap ;
673
673
if ( ( cap = this . rules . inline . reflink . exec ( src ) )
674
674
|| ( cap = this . rules . inline . nolink . exec ( src ) ) ) {
675
- const linkString = ( cap [ 2 ] || cap [ 1 ] ) . replace ( / \s + / g , ' ' ) ;
675
+ const linkString = ( cap [ 2 ] || cap [ 1 ] ) . replace ( this . rules . other . multipleSpaceGlobal , ' ' ) ;
676
676
const link = links [ linkString . toLowerCase ( ) ] ;
677
677
if ( ! link ) {
678
678
const text = cap [ 0 ] . charAt ( 0 ) ;
@@ -682,7 +682,7 @@ export class _Tokenizer {
682
682
text,
683
683
} ;
684
684
}
685
- return outputLink ( cap , link , cap [ 0 ] , this . lexer ) ;
685
+ return outputLink ( cap , link , cap [ 0 ] , this . lexer , this . rules ) ;
686
686
}
687
687
}
688
688
@@ -691,7 +691,7 @@ export class _Tokenizer {
691
691
if ( ! match ) return ;
692
692
693
693
// _ can't be between two alphanumerics. \p{L}\p{N} includes non-english alphabet/numbers as well
694
- if ( match [ 3 ] && prevChar . match ( / [ \p { L } \p { N } ] / u ) ) return ;
694
+ if ( match [ 3 ] && prevChar . match ( this . rules . other . unicodeAlphaNumeric ) ) return ;
695
695
696
696
const nextChar = match [ 1 ] || match [ 2 ] || '' ;
697
697
@@ -759,9 +759,9 @@ export class _Tokenizer {
759
759
codespan ( src : string ) : Tokens . Codespan | undefined {
760
760
const cap = this . rules . inline . code . exec ( src ) ;
761
761
if ( cap ) {
762
- let text = cap [ 2 ] . replace ( / \n / g , ' ' ) ;
763
- const hasNonSpaceChars = / [ ^ ] / . test ( text ) ;
764
- const hasSpaceCharsOnBothEnds = / ^ / . test ( text ) && / $ / . test ( text ) ;
762
+ let text = cap [ 2 ] . replace ( this . rules . other . newLineCharGlobal , ' ' ) ;
763
+ const hasNonSpaceChars = this . rules . other . nonSpaceChar . test ( text ) ;
764
+ const hasSpaceCharsOnBothEnds = this . rules . other . startingSpaceChar . test ( text ) && this . rules . other . endingSpaceChar . test ( text ) ;
765
765
if ( hasNonSpaceChars && hasSpaceCharsOnBothEnds ) {
766
766
text = text . substring ( 1 , text . length - 1 ) ;
767
767
}
0 commit comments