@@ -554,68 +554,9 @@ inline.normal = merge({}, inline);
554
554
inline . pedantic = merge ( { } , inline . normal , {
555
555
strong : / ^ _ _ (? = \S ) ( [ \s \S ] * ?\S ) _ _ (? ! _ ) | ^ \* \* (? = \S ) ( [ \s \S ] * ?\S ) \* \* (? ! \* ) / ,
556
556
em : / ^ _ (? = \S ) ( [ \s \S ] * ?\S ) _ (? ! _ ) | ^ \* (? = \S ) ( [ \s \S ] * ?\S ) \* (? ! \* ) / ,
557
- /* Original link re: /^!?\[(label)\]\(\s*<?([\s\S]*?)>?(?:\s+(['"][\s\S]*?['"]))?\s*\)/
558
- * This captures the spec reasonably well but is vulnerable to REDOS.
559
- * Instead we use a custom parser that follows the RegExp.exec semantics. */
560
- link : {
561
- exec : function ( s ) {
562
- // [TEXT](DESTINATION)
563
- var generalLinkRe = edit ( / ^ ! ? \[ ( l a b e l ) \] \( ( .* ?) \) / )
564
- . replace ( 'label' , inline . _label )
565
- . getRegex ( ) ;
566
-
567
- // destination: DESTINATION from generalLinkRe
568
- // returns [destination, title]: no angle-brackets on destination, no quotes on title
569
- function splitIntoDestinationAndTitle ( destination ) {
570
- function unwrapAngleBrackets ( str ) {
571
- if ( str . match ( / ^ < .* > $ / ) ) {
572
- str = str . slice ( 1 , - 1 ) ;
573
- }
574
- return str ;
575
- }
576
-
577
- // Valid DESTINATIONs, in decreasing specificity.
578
- var destinationAndTitleRe = / ^ ( [ ^ ' " ( ] * [ ^ \s ] ) \s + ( [ ' " ( ] .* [ ' " ) ] ) / ;
579
- var destinationRe = / ^ ( < ? [ \s \S ] * > ? ) / ;
580
- var parsingRegexes = [ destinationAndTitleRe , destinationRe ] ;
581
-
582
- var match = false ;
583
- for ( var i = 0 ; i < parsingRegexes . length ; i ++ ) {
584
- match = parsingRegexes [ i ] . exec ( destination ) ;
585
- if ( match ) {
586
- break ;
587
- }
588
- }
589
-
590
- if ( ! match ) {
591
- return null ;
592
- }
593
-
594
- var dest = match [ 1 ] ;
595
- var title = match [ 2 ] || '' ; // Not all parsingRegexes have 2 groups.
596
-
597
- // Format dest.
598
- dest = dest . trim ( ) ;
599
- dest = unwrapAngleBrackets ( dest ) ;
600
-
601
- return [ dest , title ] ;
602
- }
603
-
604
- var fullMatch = generalLinkRe . exec ( s ) ;
605
- if ( ! fullMatch ) {
606
- return null ;
607
- }
608
-
609
- var text = fullMatch [ 1 ] ;
610
- var destination = fullMatch [ 2 ] ;
611
-
612
- var destinationAndTitle = splitIntoDestinationAndTitle ( destination ) ;
613
- if ( ! destinationAndTitle ) {
614
- return null ;
615
- }
616
- return [ fullMatch [ 0 ] , text , destinationAndTitle [ 0 ] , destinationAndTitle [ 1 ] ] ;
617
- }
618
- } ,
557
+ link : edit ( / ^ ! ? \[ ( l a b e l ) \] \( ( .* ?) \) / )
558
+ . replace ( 'label' , inline . _label )
559
+ . getRegex ( ) ,
619
560
reflink : edit ( / ^ ! ? \[ ( l a b e l ) \] \s * \[ ( [ ^ \] ] * ) \] / )
620
561
. replace ( 'label' , inline . _label )
621
562
. getRegex ( )
@@ -762,8 +703,19 @@ InlineLexer.prototype.output = function(src) {
762
703
src = src . substring ( cap [ 0 ] . length ) ;
763
704
this . inLink = true ;
764
705
href = cap [ 2 ] ;
765
- href = href [ 0 ] === '<' ? href . substring ( 1 , href . length - 1 ) : href ;
766
- title = cap [ 3 ] ? cap [ 3 ] . substring ( 1 , cap [ 3 ] . length - 1 ) : cap [ 3 ] ;
706
+ if ( this . options . pedantic ) {
707
+ link = / ^ ( [ ^ ' " ] * [ ^ \s ] ) \s + ( [ ' " ] ) ( .* ) \2/ . exec ( href ) ;
708
+
709
+ if ( link ) {
710
+ href = link [ 1 ] ;
711
+ title = link [ 3 ] ;
712
+ } else {
713
+ title = '' ;
714
+ }
715
+ } else {
716
+ title = cap [ 3 ] ? cap [ 3 ] . slice ( 1 , - 1 ) : '' ;
717
+ }
718
+ href = href . trim ( ) . replace ( / ^ < ( [ \s \S ] * ) > $ / , '$1' ) ;
767
719
out += this . outputLink ( cap , {
768
720
href : InlineLexer . escapes ( href ) ,
769
721
title : InlineLexer . escapes ( title )
0 commit comments