Skip to content

Commit

Permalink
Merge pull request #106 from fcarreiro/master
Browse files Browse the repository at this point in the history
Added validate option (function) to be able to selectively filter tokens
  • Loading branch information
Nick Frasser committed Jan 22, 2016
2 parents 173e1b8 + f186859 commit e7ac584
Show file tree
Hide file tree
Showing 15 changed files with 130 additions and 19 deletions.
3 changes: 2 additions & 1 deletion src/linkify-element.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,9 @@ function tokensToNodes(tokens, opts, doc) {

for (let i = 0; i < tokens.length; i++) {
let token = tokens[i];
let validated = token.isLink && options.resolve(opts.validate, token.toString(), token.type);

if (token.isLink) {
if (token.isLink && validated) {

let
href = token.toHref(opts.defaultProtocol),
Expand Down
4 changes: 3 additions & 1 deletion src/linkify-html.js
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,8 @@ function linkifyChars(str, opts) {

for (var i = 0; i < tokens.length; i++) {
let token = tokens[i];
let validated = token.isLink && linkify.options.resolve(opts.validate, token.toString(), token.type);

if (token.type === 'nl' && opts.nl2br) {
result.push({
type: StartTag,
Expand All @@ -85,7 +87,7 @@ function linkifyChars(str, opts) {
selfClosing: true
});
continue;
} else if (!token.isLink) {
} else if (!token.isLink || !validated) {
result.push({type: Chars, chars: token.toString()});
continue;
}
Expand Down
1 change: 1 addition & 0 deletions src/linkify-jquery.js
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ function apply($, doc=null) {
tagName: data.linkifyTagname,
target: data.linkifyTarget,
linkClass: data.linkifyLinkclass,
validate: data.linkifyValidate,
};
let $target = target === 'this' ? $this : $this.find(target);
$target.linkify(options);
Expand Down
6 changes: 4 additions & 2 deletions src/linkify-string.js
Original file line number Diff line number Diff line change
Expand Up @@ -37,11 +37,14 @@ function linkifyStr(str, opts={}) {

for (let i = 0; i < tokens.length; i++) {
let token = tokens[i];
if (token.isLink) {
let validated = token.isLink && options.resolve(opts.validate, token.toString(), token.type);

if (token.isLink && validated) {

let
href = token.toHref(opts.defaultProtocol),
formatted = options.resolve(opts.format, token.toString(), token.type),

formattedHref = options.resolve(opts.formatHref, href, token.type),
attributesHash = options.resolve(opts.attributes, href, token.type),
tagName = options.resolve(opts.tagName, href, token.type),
Expand All @@ -59,7 +62,6 @@ function linkifyStr(str, opts={}) {

link += `>${escapeText(formatted)}</${tagName}>`;
result.push(link);

} else if (token.type === 'nl' && opts.nl2br) {
if (opts.newLine) {
result.push(opts.newLine);
Expand Down
5 changes: 5 additions & 0 deletions src/linkify/utils/options.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@ function noop(val) {
return val;
}

function yes(val) {
return true;
}

function typeToTarget(href, type) {
return type === 'url' ? '_blank' : null;
}
Expand All @@ -14,6 +18,7 @@ function normalize(opts) {
defaultProtocol: opts.defaultProtocol || 'http',
events: opts.events || null,
format: opts.format || noop,
validate: opts.validate || yes,
formatHref: opts.formatHref || noop,
newLine: opts.newLine || false, // deprecated
nl2br: !!newLine || opts.nl2br || false,
Expand Down
2 changes: 2 additions & 0 deletions test/qunit/test/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@ QUnit.test('returns in the hash of default options when given an empty object',
defaultProtocol: 'http',
events: null,
format: function () {},
validate: function () {},
formatHref: function () {},
newLine: false, // deprecated
nl2br: false,
Expand All @@ -107,6 +108,7 @@ QUnit.test('returns in the hash of default options when given an empty object',
linkClass: 'linkified'
});
assert.equal(typeof result.format, 'function');
assert.equal(typeof result.validate, 'function');
assert.equal(result.format('test'), 'test');
assert.equal(typeof result.formatHref, 'function');
assert.equal(result.formatHref('test'), 'test');
Expand Down
8 changes: 4 additions & 4 deletions test/spec/html/linkified-alt.html
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
Hello here are some links to <a href="ftp://awesome.com/?where=this" class="linkified" target="_blank" rel="nofollow">ftp://awesome.com/?where=this</a> and <a href="http://localhost:8080" class="linkified" target="_blank" rel="nofollow">localhost:8080</a>, pretty neat right? <p>Here's a nested <a href="http://github.com/SoapBox/linkifyjs" class="linkified" target="_blank" rel="nofollow">github.com/SoapBox/linkifyjs</a> paragraph</p>
Hello here are some links to <a rel="nofollow" target="_blank" class="linkified" href="ftp://awesome.com/?where=this">ftp://awesome.com/?where=this</a> and <a rel="nofollow" target="_blank" class="linkified" href="http://localhost:8080">localhost:8080</a>, pretty neat right? <p>Here's a nested <a rel="nofollow" target="_blank" class="linkified" href="http://github.com/SoapBox/linkifyjs">github.com/SoapBox/linkifyjs</a> paragraph</p>
Hello here are some links to <a class="linkified" href="ftp://awesome.com/?where=this" target="_blank" rel="nofollow">ftp://awesome.com/?where=this</a> and <a class="linkified" href="http://localhost:8080" target="_blank" rel="nofollow">localhost:8080</a>, pretty neat right? <p>Here's a nested <a class="linkified" href="http://github.com/SoapBox/linkifyjs" target="_blank" rel="nofollow">github.com/SoapBox/linkifyjs</a> paragraph</p>
Hello here are some links to <a class="linkified" href="ftp://awesome.com/?where=this" rel="nofollow" target="_blank">ftp://awesome.com/?where=this</a> and <a class="linkified" href="http://localhost:8080" rel="nofollow" target="_blank">localhost:8080</a>, pretty neat right? <p>Here's a nested <a class="linkified" href="http://github.com/SoapBox/linkifyjs" rel="nofollow" target="_blank">github.com/SoapBox/linkifyjs</a> paragraph</p>
Hello here are some links to <a href="ftp://awesome.com/?where=this" class="linkified" target="_blank" rel="nofollow">ftp://awesome.com/?where=this</a> and <a href="http://localhost:8080" class="linkified" target="_blank" rel="nofollow">localhost:8080</a>, pretty neat right? <p>Here's a nested <a href="http://github.com/SoapBox/linkifyjs" class="linkified" target="_blank" rel="nofollow">github.com/SoapBox/linkifyjs</a> paragraph</p> and another link to <a href="http://www.google.com" class="linkified" target="_blank" rel="nofollow">www.google.com</a>
Hello here are some links to <a rel="nofollow" target="_blank" class="linkified" href="ftp://awesome.com/?where=this">ftp://awesome.com/?where=this</a> and <a rel="nofollow" target="_blank" class="linkified" href="http://localhost:8080">localhost:8080</a>, pretty neat right? <p>Here's a nested <a rel="nofollow" target="_blank" class="linkified" href="http://github.com/SoapBox/linkifyjs">github.com/SoapBox/linkifyjs</a> paragraph</p> and another link to <a href="http://www.google.com" class="linkified" target="_blank" rel="nofollow">www.google.com</a>
Hello here are some links to <a class="linkified" href="ftp://awesome.com/?where=this" target="_blank" rel="nofollow">ftp://awesome.com/?where=this</a> and <a class="linkified" href="http://localhost:8080" target="_blank" rel="nofollow">localhost:8080</a>, pretty neat right? <p>Here's a nested <a class="linkified" href="http://github.com/SoapBox/linkifyjs" target="_blank" rel="nofollow">github.com/SoapBox/linkifyjs</a> paragraph</p> and another link to <a href="http://www.google.com" class="linkified" target="_blank" rel="nofollow">www.google.com</a>
Hello here are some links to <a class="linkified" href="ftp://awesome.com/?where=this" rel="nofollow" target="_blank">ftp://awesome.com/?where=this</a> and <a class="linkified" href="http://localhost:8080" rel="nofollow" target="_blank">localhost:8080</a>, pretty neat right? <p>Here's a nested <a class="linkified" href="http://github.com/SoapBox/linkifyjs" rel="nofollow" target="_blank">github.com/SoapBox/linkifyjs</a> paragraph</p> and another link to <a href="http://www.google.com" class="linkified" target="_blank" rel="nofollow">www.google.com</a>
3 changes: 3 additions & 0 deletions test/spec/html/linkified-validate.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
Hello here are some links to <a href="ftp://awesome.com/?where=this" class="linkified" target="_blank">ftp://awesome.com/?where=this</a> and localhost:8080, pretty neat right? <p>Here's a nested github.com/SoapBox/linkifyjs paragraph</p> and another link to <a href="http://www.google.com" class="linkified" target="_blank">www.google.com</a>
Hello here are some links to <a href="ftp://awesome.com/?where=this" class="linkified" target="_blank">ftp://awesome.com/?where=this</a> and localhost:8080, pretty neat right? <p>Here's a nested github.com/SoapBox/linkifyjs paragraph</p> and another link to <a href="http://www.google.com" class="linkified" target="_blank">www.google.com</a>
Hello here are some links to <a href="ftp://awesome.com/?where=this" class="linkified" target="_blank">ftp://awesome.com/?where=this</a> and localhost:8080, pretty neat right? <p>Here's a nested github.com/SoapBox/linkifyjs paragraph</p> and another link to <a href="http://www.google.com" class="linkified" target="_blank">www.google.com</a>
6 changes: 3 additions & 3 deletions test/spec/html/linkified.html
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
Hello here are some links to <a href="ftp://awesome.com/?where=this" class="linkified" target="_blank">ftp://awesome.com/?where=this</a> and <a href="http://localhost:8080" class="linkified" target="_blank">localhost:8080</a>, pretty neat right? <p>Here's a nested <a href="http://github.com/SoapBox/linkifyjs" class="linkified" target="_blank">github.com/SoapBox/linkifyjs</a> paragraph</p>
Hello here are some links to <a target="_blank" class="linkified" href="ftp://awesome.com/?where=this">ftp://awesome.com/?where=this</a> and <a target="_blank" class="linkified" href="http://localhost:8080">localhost:8080</a>, pretty neat right? <p>Here's a nested <a target="_blank" class="linkified" href="http://github.com/SoapBox/linkifyjs">github.com/SoapBox/linkifyjs</a> paragraph</p>
Hello here are some links to <a class="linkified" href="ftp://awesome.com/?where=this" target="_blank">ftp://awesome.com/?where=this</a> and <a class="linkified" href="http://localhost:8080" target="_blank">localhost:8080</a>, pretty neat right? <p>Here's a nested <a class="linkified" href="http://github.com/SoapBox/linkifyjs" target="_blank">github.com/SoapBox/linkifyjs</a> paragraph</p>
Hello here are some links to <a href="ftp://awesome.com/?where=this" class="linkified" target="_blank">ftp://awesome.com/?where=this</a> and <a href="http://localhost:8080" class="linkified" target="_blank">localhost:8080</a>, pretty neat right? <p>Here's a nested <a href="http://github.com/SoapBox/linkifyjs" class="linkified" target="_blank">github.com/SoapBox/linkifyjs</a> paragraph</p> and another link to <a href="http://www.google.com" class="linkified" target="_blank">www.google.com</a>
Hello here are some links to <a target="_blank" class="linkified" href="ftp://awesome.com/?where=this">ftp://awesome.com/?where=this</a> and <a target="_blank" class="linkified" href="http://localhost:8080">localhost:8080</a>, pretty neat right? <p>Here's a nested <a target="_blank" class="linkified" href="http://github.com/SoapBox/linkifyjs">github.com/SoapBox/linkifyjs</a> paragraph</p> and another link to <a href="http://www.google.com" class="linkified" target="_blank">www.google.com</a>
Hello here are some links to <a class="linkified" href="ftp://awesome.com/?where=this" target="_blank">ftp://awesome.com/?where=this</a> and <a class="linkified" href="http://localhost:8080" target="_blank">localhost:8080</a>, pretty neat right? <p>Here's a nested <a class="linkified" href="http://github.com/SoapBox/linkifyjs" target="_blank">github.com/SoapBox/linkifyjs</a> paragraph</p> and another link to <a href="http://www.google.com" class="linkified" target="_blank">www.google.com</a>
9 changes: 9 additions & 0 deletions test/spec/html/options.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@ module.exports = {
linkifiedAlt: fs.readFileSync(__dirname + '/linkified-alt.html', 'utf8')
.trim()
.split('\n'),
linkifiedValidate: fs.readFileSync(__dirname + '/linkified-validate.html', 'utf8')
.trim()
.split('\n'),

extra: fs.readFileSync(__dirname + '/extra.html', 'utf8').trim(), // for jQuery plugin tests
altOptions: {
Expand All @@ -27,5 +30,11 @@ module.exports = {
throw 'Hovered!';
}
}
},

validateOptions: {
validate: function (text, type) {
return type !== 'url' || /^(http|ftp)s?:\/\//.test(text) || text.slice(0,3) === 'www';
}
}
};
2 changes: 1 addition & 1 deletion test/spec/html/original.html
Original file line number Diff line number Diff line change
@@ -1 +1 @@
Hello here are some links to ftp://awesome.com/?where=this and localhost:8080, pretty neat right? <p>Here's a nested github.com/SoapBox/linkifyjs paragraph</p>
Hello here are some links to ftp://awesome.com/?where=this and localhost:8080, pretty neat right? <p>Here's a nested github.com/SoapBox/linkifyjs paragraph</p> and another link to www.google.com
9 changes: 8 additions & 1 deletion test/spec/linkify-element-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ describe('linkify-element', function () {
expect(htmlOptions.linkified).to.contain(testContainer.innerHTML);
});

it('Works with overriden options', function () {
it('Works with overriden options (general)', function () {
expect(testContainer).to.be.ok;
expect(testContainer).to.be.a('object');
var result = linkifyElement(testContainer, htmlOptions.altOptions, doc);
Expand All @@ -80,4 +80,11 @@ describe('linkify-element', function () {
*/
});

it('Works with overriden options (validate)', function () {
expect(testContainer).to.be.ok;
expect(testContainer).to.be.a('object');
var result = linkifyElement(testContainer, htmlOptions.validateOptions, doc);
expect(result).to.equal(testContainer); // should return the same element
expect(htmlOptions.linkifiedValidate).to.contain(testContainer.innerHTML);
});
});
36 changes: 35 additions & 1 deletion test/spec/linkify-html-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -58,12 +58,46 @@ describe('linkify-html', function () {
});
});

it('Works with overriden options', function () {
it('Works with overriden options (general)', function () {
tests.map(function (test) {
expect(linkifyHtml(test[0], options)).to.be.eql(test[2]);
});
});

it('Works with overriden options (validate)', function () {
var optionsValidate = {
validate: function (text, type) {
return type !== 'url' || /^(http|ftp)s?:\/\//.test(text) || text.slice(0,3) === 'www';
}
},

testsValidate = [
[
'1.Test with no links',
'1.Test with no links'
], [
'2.The URL is google.com and the email is <strong>test@example.com</strong>',
'2.The URL is google.com and the email is <strong><a href="mailto:test@example.com" class="linkified">test@example.com</a></strong>'
], [
'3.Super long maps URL https://www.google.ca/maps/@43.472082,-80.5426668,18z?hl=en, a #hash-tag, and an email: test."wut".yo@gmail.co.uk!',
'3.Super long maps URL <a href="https://www.google.ca/maps/@43.472082,-80.5426668,18z?hl=en" class="linkified" target="_blank">https://www.google.ca/maps/@43.472082,-80.5426668,18z?hl=en</a>, a #hash-tag, and an email: <a href="mailto:test.&quot;wut&quot;.yo@gmail.co.uk" class="linkified">test."wut".yo@gmail.co.uk</a>!'
], [
'4a.This link is already in an anchor tag <a href="#bro">google.com</a> LOL and this one <h1>isnt http://github.com</h1>',
'4a.This link is already in an anchor tag <a href="#bro">google.com</a> LOL and this one <h1>isnt <a href="http://github.com" class="linkified" target="_blank">http://github.com</a></h1>'
], [
'4b.This link is already in an anchor tag <a href="#bro">google.com</a> LOL and this one <h1>isnt github.com</h1>',
'4b.This link is already in an anchor tag <a href="#bro">google.com</a> LOL and this one <h1>isnt github.com</h1>'
], [
'5.Unterminated anchor tag <a href="http://google.com"> This <em>is a link google.com</em> and this works!! https://reddit.com/r/photography/',
'5.Unterminated anchor tag <a href="http://google.com"> This <em>is a link google.com</em> and this works!! https://reddit.com/r/photography/'
]
];

testsValidate.map(function (test) {
expect(linkifyHtml(test[0], optionsValidate)).to.be.eql(test[1]);
});
});

it('Works with HTML and default options', function () {
var linkified = linkifyHtml(htmlOptions.original);
expect(htmlOptions.linkified).to.contain(linkified);
Expand Down
13 changes: 11 additions & 2 deletions test/spec/linkify-jquery-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ describe('linkify-jquery', function () {
testContainer.innerHTML = htmlOptions.original;
});

// This works but is inconsisten across browsers
// This works but is inconsistent across browsers
xit('Works with the DOM Data API', function () {
expect($('header').first().html()).to.be.eql(
'Have a link to:<br><a href="https://github.com" class="linkified" target="_blank">github.com</a>!'
Expand All @@ -125,12 +125,21 @@ describe('linkify-jquery', function () {
expect(htmlOptions.linkified).to.contain($container.html());
});

it('Works with overriden options', function () {
it('Works with overriden options (general)', function () {
var $container = $('#linkify-jquery-test-container');
expect(($container.length)).to.be.eql(1);
var result = $container.linkify(htmlOptions.altOptions);
// `should` is not defined on jQuery objects
expect((result === $container)).to.be.ok; // should return the same element
expect(htmlOptions.linkifiedAlt).to.contain($container.html());
});

it('Works with overriden options (validate)', function () {
var $container = $('#linkify-jquery-test-container');
expect(($container.length)).to.be.eql(1);
var result = $container.linkify(htmlOptions.validateOptions);
// `should` is not defined on jQuery objects
expect((result === $container)).to.be.ok; // should return the same element
expect(htmlOptions.linkifiedValidate).to.contain($container.html());
});
});
42 changes: 39 additions & 3 deletions test/spec/linkify-string-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -53,11 +53,12 @@ describe('linkify-string', function () {
[
'Test with no links',
'Test with no links',
'Test with no links'
'Test with no links',
], [
'The URL is google.com and the email is test@example.com',
'The URL is <a href="http://google.com" class="linkified" target="_blank">google.com</a> and the email is <a href="mailto:test@example.com" class="linkified">test@example.com</a>',
'The URL is <span href="https://google.com" class="my-linkify-class" target="_parent" rel="nofollow" onclick="javascript:;">google.com</span> and the email is <span href="mailto:test@example.com?subject=Hello%20from%20Linkify" class="my-linkify-class" target="_parent" rel="nofollow" onclick="javascript:;">test@example.com</span>'
'The URL is <span href="https://google.com" class="my-linkify-class" target="_parent" rel="nofollow" onclick="javascript:;">google.com</span> and the email is <span href="mailto:test@example.com?subject=Hello%20from%20Linkify" class="my-linkify-class" target="_parent" rel="nofollow" onclick="javascript:;">test@example.com</span>',
'The URL is google.com and the email is test@example.com',
], [
'Super long maps URL https://www.google.ca/maps/@43.472082,-80.5426668,18z?hl=en, a #hash-tag, and an email: test."wut".yo@gmail.co.uk!\n',
'Super long maps URL <a href="https://www.google.ca/maps/@43.472082,-80.5426668,18z?hl=en" class="linkified" target="_blank">https://www.google.ca/maps/@43.472082,-80.5426668,18z?hl=en</a>, a #hash-tag, and an email: <a href="mailto:test.&quot;wut&quot;.yo@gmail.co.uk" class="linkified">test."wut".yo@gmail.co.uk</a>!\n',
Expand All @@ -71,9 +72,44 @@ describe('linkify-string', function () {
});
});

it('Works with overriden options', function () {
it('Works with overriden options (general)', function () {
tests.map(function (test) {
expect(linkifyStr(test[0], options)).to.be.eql(test[2]);
});
});

// Test specific options
it('Works with overriden options (validate)', function () {
var optionsValidate = {
validate: function (text, type) {
return type !== 'url' || /^(http|ftp)s?:\/\//.test(text) || text.slice(0,3) === 'www';
}
},

testsValidate = [
[
'1.Test with no links',
'1.Test with no links'
], [
'2.The URL is google.com and the email is test@example.com',
'2.The URL is google.com and the email is <a href="mailto:test@example.com" class="linkified">test@example.com</a>'
], [
'3.The URL is www.google.com',
'3.The URL is <a href="http://www.google.com" class="linkified" target="_blank">www.google.com</a>'
], [
'4.The URL is http://google.com',
'4.The URL is <a href="http://google.com" class="linkified" target="_blank">http://google.com</a>'
], [
'5.The URL is ftp://google.com',
'5.The URL is <a href="ftp://google.com" class="linkified" target="_blank">ftp://google.com</a>'
], [
'6.Test with no links.It is sloppy avoiding spaces after the dot',
'6.Test with no links.It is sloppy avoiding spaces after the dot'
]
];

testsValidate.map(function (test) {
expect(linkifyStr(test[0], optionsValidate)).to.be.eql(test[1]);
});
});
});

0 comments on commit e7ac584

Please # to comment.