Skip to content

Commit

Permalink
Fix to not autolink URLs inside a <!DOCTYPE> tag
Browse files Browse the repository at this point in the history
  • Loading branch information
gregjacobs committed Sep 7, 2014
1 parent 609fbd6 commit deef0e3
Show file tree
Hide file tree
Showing 5 changed files with 51 additions and 13 deletions.
16 changes: 10 additions & 6 deletions dist/Autolinker.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/*!
* Autolinker.js
* 0.11.0
* 0.11.2
*
* Copyright(c) 2014 Gregory Jacobs <greg@greg-jacobs.com>
* MIT Licensed. http://www.opensource.org/licenses/mit-license.php
Expand Down Expand Up @@ -237,22 +237,26 @@
htmlRegex : (function() {
var tagNameRegex = /[0-9a-zA-Z:]+/,
attrNameRegex = /[^\s\0"'>\/=\x01-\x1F\x7F]+/, // the unicode range accounts for excluding control chars, and the delete char
attrValueRegex = /(?:".*?"|'.*?'|[^'"=<>`\s]+)/; // double quoted, single quoted, or unquoted attribute values
attrValueRegex = /(?:".*?"|'.*?'|[^'"=<>`\s]+)/, // double quoted, single quoted, or unquoted attribute values
nameEqualsValueRegex = attrNameRegex.source + '(?:\\s*=\\s*' + attrValueRegex.source + ')?'; // optional '=[value]'

return new RegExp( [
'<(/)?', // Beginning of a tag. Either '<' for a start tag, or '</' for an end tag. The slash or an empty string is Capturing Group 1.
'<(?:!|(/))?', // Beginning of a tag. Either '<' for a start tag, '</' for an end tag, or <! for the <!DOCTYPE ...> tag. The slash or an empty string is Capturing Group 1.

// The tag name (Capturing Group 2)
'(' + tagNameRegex.source + ')',

// Zero or more attributes following the tag name
'(?:',
'\\s+', // one or more whitespace chars before an attribute
attrNameRegex.source,
'(?:\\s*=\\s*' + attrValueRegex.source + ')?', // optional '=[value]'

// Either:
// A. tag="value", or
// B. "value" alone (for <!DOCTYPE> tag. Ex: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">)
'(?:', nameEqualsValueRegex, '|', attrValueRegex.source + ')',
')*',

'\\s*', // any trailing spaces before the closing '>'
'\\s*/?', // any trailing spaces and optional '/' before the closing '>'
'>'
].join( "" ), 'g' );
} )(),
Expand Down
4 changes: 2 additions & 2 deletions dist/Autolinker.min.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "autolinker",
"version": "0.11.0",
"version": "0.11.2",
"description": "Simple utility to automatically link the URLs, email addresses, and Twitter handles in a given block of text/HTML",
"main": "dist/Autolinker.js",
"directories": {
Expand Down
12 changes: 8 additions & 4 deletions src/Autolinker.js
Original file line number Diff line number Diff line change
Expand Up @@ -228,19 +228,23 @@
htmlRegex : (function() {
var tagNameRegex = /[0-9a-zA-Z:]+/,
attrNameRegex = /[^\s\0"'>\/=\x01-\x1F\x7F]+/, // the unicode range accounts for excluding control chars, and the delete char
attrValueRegex = /(?:".*?"|'.*?'|[^'"=<>`\s]+)/; // double quoted, single quoted, or unquoted attribute values
attrValueRegex = /(?:".*?"|'.*?'|[^'"=<>`\s]+)/, // double quoted, single quoted, or unquoted attribute values
nameEqualsValueRegex = attrNameRegex.source + '(?:\\s*=\\s*' + attrValueRegex.source + ')?'; // optional '=[value]'

return new RegExp( [
'<(/)?', // Beginning of a tag. Either '<' for a start tag, or '</' for an end tag. The slash or an empty string is Capturing Group 1.
'<(?:!|(/))?', // Beginning of a tag. Either '<' for a start tag, '</' for an end tag, or <! for the <!DOCTYPE ...> tag. The slash or an empty string is Capturing Group 1.

// The tag name (Capturing Group 2)
'(' + tagNameRegex.source + ')',

// Zero or more attributes following the tag name
'(?:',
'\\s+', // one or more whitespace chars before an attribute
attrNameRegex.source,
'(?:\\s*=\\s*' + attrValueRegex.source + ')?', // optional '=[value]'

// Either:
// A. tag="value", or
// B. "value" alone (for <!DOCTYPE> tag. Ex: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">)
'(?:', nameEqualsValueRegex, '|', attrValueRegex.source + ')',
')*',

'\\s*/?', // any trailing spaces and optional '/' before the closing '>'
Expand Down
30 changes: 30 additions & 0 deletions tests/AutolinkerSpec.js
Original file line number Diff line number Diff line change
Expand Up @@ -581,6 +581,36 @@ describe( "Autolinker", function() {
} );


it( "should NOT automatically link anything in a !DOCTYPE tag (Issue #53)", function() {
var input = '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">';

var result = autolinker.link( input );
expect( result ).toBe( input );
} );


it( "should automatically link tags after a !DOCTYPE tag", function() {
var input = [
'<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">',
'<html>',
'<body>',
'Welcome to mysite.com',
'</body>',
'</html>'
].join( "" );

var result = autolinker.link( input );
expect( result ).toBe( [
'<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">',
'<html>',
'<body>',
'Welcome to <a href="http://mysite.com">mysite.com</a>',
'</body>',
'</html>'
].join( "" ) );
} );


it( "should allow the full range of HTML attribute name characters as specified in the W3C HTML syntax document (http://www.w3.org/TR/html-markup/syntax.html)", function() {
// Note: We aren't actually expecting the HTML to be modified by this test
var inAndOutHtml = '<ns:p>Foo <a data-qux-="" href="http://www.example.com">Bar<\/a> Baz<\/ns:p>';
Expand Down

0 comments on commit deef0e3

Please sign in to comment.