A while ago I posted a snippet of linky, and explaining how "changing the current highlighted text into a link" (heuristically figuring out if text to be made clickable or the URL itself) made more sense to me (for use on the backend of my blog) than either markdown-like approaches or dialogs with two input boxes.
But with my work flow, sometimes it was annoying to have to highlight the link in order to linkify it, and I realized a better UX would be "if I click "linky" and there is no text selected, change every https:// starting URL looking thing into a link."
This stackoverflow was a good start, but assumed any URL wasn't already in a link - like if you ran it twice (or there were links elsewhere) you'd get <a href="<a href=" crap.
But the regular expression to do it properly was tough. I got some help and ended up with (with a few tester function to start... and pardon the bad pre code ;-) )
function testLinkify(){
console.log('starting test');
test(`https://foo.com`, `<a href="https://foo.com"></a>`);
test(`\nhttps://foo.com`,`\n<a href="https://foo.com"></a>`);
test(`<a href="https://foo.com"></a>`,`<a href="https://foo.com"></a>`);
test(`<a href="https://foo.com"></a> https://bar.com`,`<a href="https://foo.com"></a> <a href="https://bar.com"></a>`);
test(`https://foo.com\nhttps://bar.com <a href="https://baz.com">BAZ</a>`,`<a href="https://foo.com"></a>\n<a href="https://bar.com"></a> <a href="https://baz.com">BAZ</a>`);
}
function test(input,expect){
const testFunction = linkifyBareHttp;
const output = testFunction(input);
console.log (output === expect ? 'PASS':'FAIL');
console.log(` INPUT: ${input}`);
if(output !== expect) {
console.log(`EXPECT: ${expect}`);
console.log(`OUTPUT: ${output}`)
}
}
function linkifyBareHttp(inputText){
//URLs starting with http://, https://, or ftp://
const replacePattern1 = /\b(?<!(\'|\"))(((https?|ftp):\/\/[-A-Z0-9+&@#\/%?=~_|!:,.;]*[-A-Z0-9+&@#\/%=~_|]))/gim;
return inputText.replace(replacePattern1, '<a href="$2"></a>');
}
testLinkify();
You can play with that at a codepen
(UPDATE: it was funny playing with my admittedly idiosyncratic UI, starting to use it for real. Turns out I had a workflow that expected to be able to click "linky" before typing anything and just get a place holder "<a href>". Also in theory I might hit linky before any textarea has the focus (it uses the rule of "less touched textarea is the 'current' one") so I special cased a few in the offchance I had started focusing yet... anyway...)