@@ -32,7 +32,11 @@ Autolinker.htmlParser.HtmlParser = Autolinker.Util.extend( Object, {
3232 tagNameRegex = / [ 0 - 9 a - z A - Z ] [ 0 - 9 a - z A - Z : ] * / ,
3333 attrNameRegex = / [ ^ \s " ' > \/ = \x00 - \x1F \x7F ] + / , // the unicode range accounts for excluding control chars, and the delete char
3434 attrValueRegex = / (?: " [ ^ " ] * ?" | ' [ ^ ' ] * ?' | [ ^ ' " = < > ` \s ] + ) / , // double quoted, single quoted, or unquoted attribute values
35- nameEqualsValueRegex = attrNameRegex . source + '(?:\\s*=\\s*' + attrValueRegex . source + ')?' ; // optional '=[value]'
35+ optionalAttrValueRegex = '(?:\\s*?=\\s*?' + attrValueRegex . source + ')?' ; // optional '=[value]'
36+
37+ var getNameEqualsValueRegex = function ( group ) {
38+ return '(?=(' + attrNameRegex . source + '))\\' + group + optionalAttrValueRegex ;
39+ } ;
3640
3741 return new RegExp ( [
3842 // for <!DOCTYPE> tag. Ex: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">)
@@ -46,7 +50,8 @@ Autolinker.htmlParser.HtmlParser = Autolinker.Util.extend( Object, {
4650 // Either:
4751 // A. attr="value", or
4852 // B. "value" alone (To cover example doctype tag: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">)
49- '(?:' , nameEqualsValueRegex , '|' , attrValueRegex . source + ')' ,
53+ // *** Capturing Group 2 - Pseudo-atomic group for attrNameRegex
54+ '(?:' , getNameEqualsValueRegex ( 2 ) , '|' , attrValueRegex . source + ')' ,
5055 ')*' ,
5156 '>' ,
5257 ')' ,
@@ -56,10 +61,10 @@ Autolinker.htmlParser.HtmlParser = Autolinker.Util.extend( Object, {
5661 // All other HTML tags (i.e. tags that are not <!DOCTYPE>)
5762 '(?:' ,
5863 '<(/)?' , // Beginning of a tag or comment. Either '<' for a start tag, or '</' for an end tag.
59- // *** Capturing Group 2 : The slash or an empty string. Slash ('/') for end tag, empty string for start or self-closing tag.
64+ // *** Capturing Group 3 : The slash or an empty string. Slash ('/') for end tag, empty string for start or self-closing tag.
6065
6166 '(?:' ,
62- commentTagRegex . source , // *** Capturing Group 3 - A Comment Tag's Text
67+ commentTagRegex . source , // *** Capturing Group 4 - A Comment Tag's Text
6368
6469 '|' ,
6570
@@ -68,7 +73,7 @@ Autolinker.htmlParser.HtmlParser = Autolinker.Util.extend( Object, {
6873 // to fix a regex time complexity issue seen with the
6974 // example in https://github.com/gregjacobs/Autolinker.js/issues/172
7075 '(?:' ,
71- // *** Capturing Group 4 - The tag name for a tag without attributes
76+ // *** Capturing Group 5 - The tag name for a tag without attributes
7277 '(' + tagNameRegex . source + ')' ,
7378
7479 '\\s*/?' , // any trailing spaces and optional '/' before the closing '>'
@@ -81,15 +86,16 @@ Autolinker.htmlParser.HtmlParser = Autolinker.Util.extend( Object, {
8186 // to fix a regex time complexity issue seen with the
8287 // example in https://github.com/gregjacobs/Autolinker.js/issues/172
8388 '(?:' ,
84- // *** Capturing Group 5 - The tag name for a tag with attributes
89+ // *** Capturing Group 6 - The tag name for a tag with attributes
8590 '(' + tagNameRegex . source + ')' ,
8691
8792 '\\s+' , // must have at least one space after the tag name to prevent ReDoS issue (issue #172)
8893
8994 // Zero or more attributes following the tag name
9095 '(?:' ,
9196 '(?:\\s+|\\b)' , // any number of whitespace chars before an attribute. NOTE: Using \s* here throws Chrome into an infinite loop for some reason, so using \s+|\b instead
92- nameEqualsValueRegex , // attr="value" (with optional ="value" part)
97+ // *** Capturing Group 7 - Pseudo-atomic group for attrNameRegex
98+ getNameEqualsValueRegex ( 7 ) , // attr="value" (with optional ="value" part)
9399 ')*' ,
94100
95101 '\\s*/?' , // any trailing spaces and optional '/' before the closing '>'
@@ -127,9 +133,9 @@ Autolinker.htmlParser.HtmlParser = Autolinker.Util.extend( Object, {
127133
128134 while ( ( currentResult = htmlRegex . exec ( html ) ) !== null ) {
129135 var tagText = currentResult [ 0 ] ,
130- commentText = currentResult [ 3 ] , // if we've matched a comment
131- tagName = currentResult [ 1 ] || currentResult [ 4 ] || currentResult [ 5 ] , // The <!DOCTYPE> tag (ex: "!DOCTYPE"), or another tag (ex: "a" or "img")
132- isClosingTag = ! ! currentResult [ 2 ] ,
136+ commentText = currentResult [ 4 ] , // if we've matched a comment
137+ tagName = currentResult [ 1 ] || currentResult [ 5 ] || currentResult [ 6 ] , // The <!DOCTYPE> tag (ex: "!DOCTYPE"), or another tag (ex: "a" or "img")
138+ isClosingTag = ! ! currentResult [ 3 ] ,
133139 offset = currentResult . index ,
134140 inBetweenTagsText = html . substring ( lastIndex , offset ) ;
135141
0 commit comments