Skip to content

Instantly share code, notes, and snippets.

@erikhazzard
Last active August 29, 2015 14:18
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save erikhazzard/2e2415f79c517311dbdc to your computer and use it in GitHub Desktop.
Save erikhazzard/2e2415f79c517311dbdc to your computer and use it in GitHub Desktop.
Replace all links in a string with <a> tags
Examples:
"Hello there google.com" becomes "Hello there <a href='http://google.com' target='_blank'>google.com</a>"
"Hello there http://google.com" becomes "Hello there <a href='http://google.com' target='_blank'>http://google.com</a>"
"Hello there http://google.com?q=test" becomes "Hello there <a href='http://google.com?q=test' target='_blank'>http://google.com?q=test</a>"
/* =========================================================================
*
* get-links-from-string
* Tests getting links from a string
*
* ========================================================================= */
var _ = require('lodash');
var logger = require('bragi-browser');
var transformString = require('../../util/transform-string-with-links');
// util for tests
function getWrappedLink(original){
var fqdn = original;
if(!original.match(/^https?:\/\//)){ fqdn = 'http://' + original; }
fqdn = fqdn.replace(/^(https?):\/\/\/\//, "$1://");
return "<a href='" + fqdn + "' target='_blank'>" + original + "</a>";
}
// ====================================
//
// Tests
//
// ====================================
describe('Get Links from String', function (){
describe('no links', function(){
it('should not generate link for a bunch of strings', function(){
_.each([
'string', 'just a test message haha', 'simple test',
'simple string hello world it\'s a little long'
], function(string){
transformString(string).should.equal(string);
});
});
it('should test periods', function(){
_.each([
'test.....test', 'test....test', 'test...test', 'test..test',
'.com', '.net', '.x', '.xyzxyz', 'a..com'
], function(string){
transformString(string).should.equal(string);
});
});
});
describe('link tests', function(){
it('should test no http links', function(){
transformString('google.com').should.equal("<a href='http://google.com' target='_blank'>google.com</a>");
transformString('google.co').should.equal("<a href='http://google.co' target='_blank'>google.co</a>");
transformString('google.net').should.equal("<a href='http://google.net' target='_blank'>google.net</a>");
transformString('imgur.com').should.equal("<a href='http://imgur.com' target='_blank'>imgur.com</a>");
});
it('should test with ports', function(){
transformString('imgur.com:80').should.equal("<a href='http://imgur.com:80' target='_blank'>imgur.com:80</a>");
transformString('imgur.com:8080').should.equal("<a href='http://imgur.com:8080' target='_blank'>imgur.com:8080</a>");
transformString('imgur.com:8080/').should.equal("<a href='http://imgur.com:8080/' target='_blank'>imgur.com:8080/</a>");
});
it('should test with commas', function(){
var string = 'imgur.com/aVsTm60,QBizuWp,CEvBkMb,G0U1rGC';
transformString(string).should.equal(getWrappedLink(string));
string = 'http://imgur.com/aVsTm60,QBizuWp,CEvBkMb,G0U1rGC';
transformString(string).should.equal(getWrappedLink(string));
// ports
string = 'imgur.com:80/aVsTm60,QBizuWp,CEvBkMb,G0U1rGC';
transformString(string).should.equal(getWrappedLink(string));
string = 'http://imgur.com:80/aVsTm60,QBizuWp,CEvBkMb,G0U1rGC';
transformString(string).should.equal(getWrappedLink(string));
string = 'http://imgur.com:1337/aVsTm60,QBizuWp,CEvBkMb,G0U1rGC';
transformString(string).should.equal(getWrappedLink(string));
});
it('should add links for a bunch of links', function(){
_.each([
'http://www.reddit.com/r/fiveapp/comments/320wzu/live_chat_nils_is_da_bauf',
'http://reddit.com',
'http://www.reddit.com/r/fiveapp/comments/320wzu/live_chat_nils_is_da_bauf/',
'http://www.reddit.com/message/moderator/',
'http://imgur.com/hzrGykL',
'http://www.reddit.com/r/pics/comments/320m7t/this_is_the_moment_i_knew_that_i_had_finally_made/',
'http://www.reddit.com/r/pics/comments/320m7t/this_is_the_moment_i_knew_that_i_had_finally_made',
'https://reddit.com',
], function( string ){
transformString(string).should.equal(getWrappedLink(string));
});
});
it('should test subdomains', function(){
_.each([
'http://www.reddit.com', 'http://www.test.reddit.com',
'http://dev.test.reddit.com', 'http://inner.dev.test.reddit.com',
'http://inner.inner.dev.test.reddit.com',
'http://inner.inner.inner.dev.test.reddit.com',
'http://reallylonginnersubdomainname.reddit.com',
'http://inner.inner.inner.inner.dev.test.reddit.com',
'http://inner.inner.inner.inner.inner.dev.test.reddit.com',
], function( string ){
transformString(string).should.equal(getWrappedLink(string));
});
});
it('should test ur with query', function(){
_.each([
'google.com?q=test', 'google.com?q=testgoogle.com?q=test',
'google.com:8080?q=test', 'inner.google.com:8080?q=test',
'inner.inner.google.com:8080?q=test',
'innerreaaaaaaaaaaaaaaaaaaalylong.inner.google.com:8080?q=test',
'innerreaaaaaaaaaaaaaaaaaaalylong.inner.google.com:8080?q=test/test',
'http://google.com?q=test', 'http://google.com?q=test&z=24',
'http://google.com?q=test&z=24,x=521'
], function( string ){
transformString(string).should.equal(getWrappedLink(string));
});
});
it('should test other formats of URLs', function(){
_.each([
'//i.imgur.com/Pu3I8av.png',
'//cdnjs.cloudflare.com/test/libs/1140/2.0/1140.css',
], function(string){
transformString(string).should.equal(getWrappedLink(string));
});
});
});
describe('should test MULTIPLE links in string', function(){
it('should test multiple simple (non http) links in string', function(){
transformString('google.com hey check it out test.com').should
.equal(getWrappedLink('google.com') + ' hey check it out ' + getWrappedLink('test.com'));
transformString('google.com reddit.com test.com').should
.equal(getWrappedLink('google.com') + ' ' +
getWrappedLink('reddit.com') + ' ' +
getWrappedLink('test.com'));
transformString('google.comreddit.com test.com').should
.equal(getWrappedLink('google.comreddit.com') + ' ' +
getWrappedLink('test.com'));
transformString('check it out reddit.com').should.equal('check it out ' +
getWrappedLink('reddit.com'));
transformString('pasting imgur.com/zwbZO,mn5C5HZ,LpeTpza will not break it')
.should.equal('pasting ' +
getWrappedLink('imgur.com/zwbZO,mn5C5HZ,LpeTpza') +
' will not break it');
});
it('should test multiple non simple links', function(){
transformString('http://i.imgur.com/Pu3I8av.png - https://i.imgur.com/NA.png')
.should.equal(
getWrappedLink('http://i.imgur.com/Pu3I8av.png') + ' - ' + getWrappedLink('https://i.imgur.com/NA.png'));
transformString('i.imgur.com/Pu3I8av.png - https://i.imgur.com/NA.png')
.should.equal(
getWrappedLink('i.imgur.com/Pu3I8av.png') + ' - ' + getWrappedLink('https://i.imgur.com/NA.png'));
transformString('//i.imgur.com/Pu3I8av.png //i.imgur.com/NA.png')
.should.equal(
getWrappedLink('//i.imgur.com/Pu3I8av.png') + ' ' + getWrappedLink('//i.imgur.com/NA.png'));
transformString('//i.imgur.com/Pu3I8av.png some space //i.imgur.com/NA.png')
.should.equal(
getWrappedLink('//i.imgur.com/Pu3I8av.png') + ' some space ' + getWrappedLink('//i.imgur.com/NA.png'));
});
it('should test a mixture of links', function(){
transformString('//i.imgur.com/Pu3I8av.png - https://i.imgur.com/NA.png :: i.imgur.com/NA.png?test=42 https://i.imgur-test.com/NA.png')
.should.equal(
getWrappedLink('//i.imgur.com/Pu3I8av.png') + ' - ' +
getWrappedLink('https://i.imgur.com/NA.png') + ' :: ' +
getWrappedLink('i.imgur.com/NA.png?test=42') + ' ' +
getWrappedLink('https://i.imgur-test.com/NA.png')
);
// trailing space
transformString('//i.imgur.com/Pu3I8av.png - https://i.imgur.com/NA.png :: i.imgur.com/NA.png?test=42 https://i.imgur-test.com/NA.png ')
.should.equal(
getWrappedLink('//i.imgur.com/Pu3I8av.png') + ' - ' +
getWrappedLink('https://i.imgur.com/NA.png') + ' :: ' +
getWrappedLink('i.imgur.com/NA.png?test=42') + ' ' +
getWrappedLink('https://i.imgur-test.com/NA.png') + ' '
);
});
});
});
var _ = require('lodash');
// simple, but probably more prone to error
var LINK_REGEX = /(https?:\/\/|\/\/)?([^ .]+\.)+[^ .]+ /gi;
// more complex, but more explicit
var LINK_REGEX = /(https?:\/\/|\/\/)?([-a-zA-Z0-9@:%_\+~]+\.[a-z]{2,6}){1,100}((:[0-9]{1,6})?((\/|\?)?([-a-zA-Z0-9@:%_\+.,~#?&//=]*)?)?)? /gi;
function transformString( string ){
string += ' '; // add trailing space (for regex)
var urls = string.match(LINK_REGEX);
if(urls){
_.each(urls, function(originalUrlMatch){
// LINK REPLACEMENT
var replacementUrl = originalUrlMatch.replace(/ $/,'');
// ensure there's some preceeding text
if(!(replacementUrl.match(/^https?:\/\//))){
replacementUrl = 'http://' + replacementUrl.replace(/^\/\//,'');
}
string = string.replace(
//new RegExp(originalUrlMatch),
originalUrlMatch,
"<a href='" + replacementUrl + "' target='_blank'>" +
originalUrlMatch.replace(/ $/,'') + "</a> "
);
});
}
// remove trailing space
string = string.substring(0, string.length-1);
return string;
}
module.exports = transformString;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment