Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added validate option (function) to be able to selectively filter tokens #106

Merged
merged 2 commits into from
Jan 22, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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]);
});
});
});