13

Is there an simple way of turning a string from

Then go to http:/example.com/ and foo the bar!

into

Then go to <a href="http://example.com">example.com</a> and foo the bar!

in Javascript within an existing HTML page?

4 Answers 4

15

Yes. The simplest way is to use a regular expressions to substitute things that look like a link for their linked equivalents. Something like:

node.innerHTML = node.innerHTML.replace(/(http:\/\/[^\s]+)/g, "<a href='$1'>$1</a>")

(my RegEx is a little rusty, so you may need to play with the syntax). This is just a simple case. You need to be wary of script injection here (for example if I have http://"><script>doevil()</script>). One way to work around this is by using a link building function:

node.innerHTML = node.innerHTML.replace(/ ... /g, buildLink($1));

Where buildLink() can check to make sure the URL doesn't contain anything malicious.

However, the RegEx-innerHTML method will not perform very well on large bodies of text though, since it tears down and rebuilds the entire HTML content of the node. You can achieve this with DOM methods as well:

  • Find reference to the text node
  • In the content, find start and end indexes of a URL
  • Use splitText() method to split the node into 3: before, link, after
  • Create an <a> node with the href that's the same as the link
  • Use insertBefore() to insert this <a> node before the link
  • Use appendChild() to move the link into the <a> node
Sign up to request clarification or add additional context in comments.

Comments

4

First, "within an HTML page" is difficult because a "page" is actually a DOM tree (which is partially composed of text nodes and mostly composed of HTML elements).

The easiest way to approach this problem would be to target content-rich text nodes. For each text node, apply something like this:

// we'll assume this is the string of a content-rich text node
var textNode = document.getElementById('contentNode');
textNode.innerHTML = textNode.innerHTML.replace(/(\s)(http:\/\/[^\s]+)(\s)/g, '$1<a href="$2">$2</a>$3');

BTW: there are security implications here. If you generate links from unsterilized text, there is the possibility of XSS.

2 Comments

this is basically the same answer as levik's. He posted first.
Thanks for the XSS reminder. Any hints on how to unsterilized the Text?
4

To all people coming here after 2023: don't write regex for this. https://linkify.js.org/

Comments

3

I use a function utilizing regex (regular expressions) to make it easier to do this. Some docs and some regex cheatsheets are linked below.

function linkfun(text, https) {
    if(https == "both") { // both
      var urlRegex = /(https?:\/\/[^\s]+)/g; // regex for both http:// and https://
      return text.replace(urlRegex, function(url) {
          return '<a href="' + url + '">' + url + '</a>'; // return the replaced text
      })
    }

    if(https == true) {
      var urlRegex = /(https:\/\/[^\s]+)/g; // regex for only https:// (notice the missing "?")
      return text.replace(urlRegex, function(url) {
          return '<a href="' + url + '">' + url + '</a>'; // return the replaced text
      })
    } else {
      var urlRegex = /(http:\/\/[^\s]+)/g; // regex for only http:// (notice the missing "?")
      return text.replace(urlRegex, function(url) {
          return '<a href="' + url + '">' + url + '</a>'; // return the replaced text
      })
    }
    // or alternatively
    // return text.replace(urlRegex, '<a href="$1">$1</a>')
}
<p id="text">Hi!! https://example.org is my favourite website, but http://example.net is also good. http://stackoverflow.com and https://stackexchange.com are cool. https://www.firefox.com is a web browser.<br><br>If you want to use this function multiple times on the same text, use <code>linkfun(...innerText, ...)</code> instead of <code>linkfun(...innerHTML, ...)</code></p>
<button onclick="document.getElementById('text').innerHTML = linkfun(document.getElementById('text').innerHTML, true);">Change just HTTPS</button>

<button onclick="document.getElementById('text').innerHTML = linkfun(document.getElementById('text').innerHTML, false);">Change just HTTP</button>

<button onclick="document.getElementById('text').innerHTML = linkfun(document.getElementById('text').innerHTML, 'both');">Change both</button>

You can learn more about:

- regex at mdn devdocs caniuse cheatsheet (rexegg) cheatsheet (mdn)

- string:replace at mdn devdocs caniuse

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.