Is there an simple way of turning a string from
Then go to http:/example.com/ and foo the bar!
into
Then go to example.com and foo the bar!
in Javascript within an existing HTML page?
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
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$2$3');
BTW: there are security implications here. If you generate links from unsterilized text, there is the possibility of XSS.
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 '' + url + ''; // 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 '' + url + ''; // return the replaced text
})
} else {
var urlRegex = /(http:\/\/[^\s]+)/g; // regex for only http:// (notice the missing "?")
return text.replace(urlRegex, function(url) {
return '' + url + ''; // return the replaced text
})
}
// or alternatively
// return text.replace(urlRegex, '$1')
}
<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
Related
I want to make to uppercase the contents of specific HTML tags with plain JavaScript in a React-Native application.
Note: This is a React-Native application. There is no JS document, available, nor jQuery. Likewise, CSS text-transform: uppercase cannot be used because it will not be displayed in a web browser.
Let's say, there is the following HTML text:
<p>This is an <mytag>simple Example</mytag></p>
The content of the Tag <mytag> shall be transformed to uppercase:
<p>This is an <mytag>SIMPLE EXAMPLE</mytag></p>
I tried this code:
let regEx = storyText.match(/<mytag>(.*?)<\/mytag>/g)
if(regEx) storyText = regEx.map(function(val){
return val.toUpperCase();
});
But the map() function returns only the matched content instead of the whole string variable with the transformed part of <mytag>.
Also, the match() method will return null, if the tag wasn't found. So a fluent programming style like storyText.match().doSomething isn't possible.
Since there are more tags to transform, an approach where I can pass variables to the regex-pattern would be appreciated.
Any hints to solve this?
(This code is used in a React-Native-App with the react-native-html-view Plugin which doesn't support text-transform out of the box.)
Since it seems that document and DOM manipulation (e.g., i.e., through jQuery and native JS document functions) are off limits, I guess you do have to use regex.
Then why not just create a function that does a job like the above: looping through each tag and replacing it via regex?
var storyText = "your HTML in a string";
function tagsToUppercase(tags) {
for(tag in tags) {
let regex = new RegExp("(<" + tags[tag] + ">)([^<]+)(<\/" + tags[tag] + ">)", "g");
storyText = storyText.replace(regex, function(match, g1, g2, g3) {
return g1 + g2.toUpperCase() + g3;
});
}
}
// uppercase all <div>, <p>, <span> for example
tagsToUppercase(["div", "p", "span"]);
See it working on JSFiddle.
Also, although it probably doesn't apply to this case, (#Bergi urged me to remind you to) try to avoid using regular expressions to manipulate the DOM.
Edit, Updated
The content of the Tag < mytag > shall be transformed to uppercase:
<p>This is an <mytag>SIMPLE EXAMPLE</mytag></p>
You can use String.prototype.replace() with RegExp /(<mytag>)(.*?)(<\/mytag>)/g to create three capture groups, call .toUpperCase() on second capture group
let storyText = "<p>This is an <mytag>simple Example</mytag></p>";
let regEx = storyText.replace(/(<mytag>)(.*?)(<\/mytag>)/g
, function(val, p1, p2, p3) {
return p1 + p2.toUpperCase() + p3
});
console.log(regEx);
In general you shouldn't be parsing html with javascript. With that in mind, if this is what you truly need to do, then try something like this:
let story = '<p>smallcaps</p><h1>heading</h1><div>div</div><p>stuff</p>';
console.log( story.replace(/<(p|span|div)>([^<]*)<\/(p|span|div)>/ig,
(fullmatch, startag,content,endtag) => `<${startag}>${content.toUpperCase()}</${endtag}>` )
)
Consider the cases where you might have nested values, p inside a div, or an a or strong or em inside your p. For those cases this doesn't work.
Why not this way ?
$("mytag").text($("mytag").text().toUpperCase())
https://jsfiddle.net/gub61haL/
I want to remove html tags from given string using javascript. I looked into current approaches but there are some unsolved problems occured with them.
Current solutions
(1) Using javascript, creating virtual div tag and get the text
function remove_tags(html)
{
var tmp = document.createElement("DIV");
tmp.innerHTML = html;
return tmp.textContent||tmp.innerText;
}
(2) Using regex
function remove_tags(html)
{
return html.replace(/<(?:.|\n)*?>/gm, '');
}
(3) Using JQuery
function remove_tags(html)
{
return jQuery(html).text();
}
These three solutions are working correctly, but if the string is like this
<div> hello <hi all !> </div>
stripped string is like
hello . But I need only remove html tags only. like hello <hi all !>
Edited: Background is, I want to remove all the user input html tags for a particular text area. But I want to allow users to enter <hi all> kind of text. In current approach, its remove any content which include within <>.
Using a regex might not be a problem if you consider a different approach. For instance, looking for all tags, and then checking to see if the tag name matches a list of defined, valid HTML tag names:
var protos = document.body.constructor === window.HTMLBodyElement;
validHTMLTags =/^(?:a|abbr|acronym|address|applet|area|article|aside|audio|b|base|basefont|bdi|bdo|bgsound|big|blink|blockquote|body|br|button|canvas|caption|center|cite|code|col|colgroup|data|datalist|dd|del|details|dfn|dir|div|dl|dt|em|embed|fieldset|figcaption|figure|font|footer|form|frame|frameset|h1|h2|h3|h4|h5|h6|head|header|hgroup|hr|html|i|iframe|img|input|ins|isindex|kbd|keygen|label|legend|li|link|listing|main|map|mark|marquee|menu|menuitem|meta|meter|nav|nobr|noframes|noscript|object|ol|optgroup|option|output|p|param|plaintext|pre|progress|q|rp|rt|ruby|s|samp|script|section|select|small|source|spacer|span|strike|strong|style|sub|summary|sup|table|tbody|td|textarea|tfoot|th|thead|time|title|tr|track|tt|u|ul|var|video|wbr|xmp)$/i;
function sanitize(txt) {
var // This regex normalises anything between quotes
normaliseQuotes = /=(["'])(?=[^\1]*[<>])[^\1]*\1/g,
normaliseFn = function ($0, q, sym) {
return $0.replace(/</g, '<').replace(/>/g, '>');
},
replaceInvalid = function ($0, tag, off, txt) {
var
// Is it a valid tag?
invalidTag = protos &&
document.createElement(tag) instanceof HTMLUnknownElement
|| !validHTMLTags.test(tag),
// Is the tag complete?
isComplete = txt.slice(off+1).search(/^[^<]+>/) > -1;
return invalidTag || !isComplete ? '<' + tag : $0;
};
txt = txt.replace(normaliseQuotes, normaliseFn)
.replace(/<(\w+)/g, replaceInvalid);
var tmp = document.createElement("DIV");
tmp.innerHTML = txt;
return "textContent" in tmp ? tmp.textContent : tmp.innerHTML;
}
Working Demo: http://jsfiddle.net/m9vZg/3/
This works because browsers parse '>' as text if it isn't part of a matching '<' opening tag. It doesn't suffer the same problems as trying to parse HTML tags using a regular expression, because you're only looking for the opening delimiter and the tag name, everything else is irrelevant.
It's also future proof: the WebIDL specification tells vendors how to implement prototypes for HTML elements, so we try and create a HTML element from the current matching tag. If the element is an instance of HTMLUnknownElement, we know that it's not a valid HTML tag. The validHTMLTags regular expression defines a list of HTML tags for older browsers, such as IE 6 and 7, that do not implement these prototypes.
If you want to keep invalid markup untouched, regular expressions is your best bet. Something like this might work:
text = html.replace(/<\/?(span|div|img|p...)\b[^<>]*>/g, "")
Expand (span|div|img|p...) into a list of all tags (or only those you want to remove). NB: the list must be sorted by length, longer tags first!
This may provide incorrect results in some edge cases (like attributes with <> characters), but the only real alternative would be to program a complete html parser by yourself. Not that it would be extremely complicated, but might be an overkill here. Let us know.
var StrippedString = OriginalString.replace(/(<([^>]+)>)/ig,"");
Here is my solution ,
function removeTags(){
var txt = document.getElementById('myString').value;
var rex = /(<([^>]+)>)/ig;
alert(txt.replace(rex , ""));
}
I use regular expression for preventing HTML tags in my textarea
Example
<form>
<textarea class="box"></textarea>
<button>Submit</button>
</form>
<script>
$(".box").focusout( function(e) {
var reg =/<(.|\n)*?>/g;
if (reg.test($('.box').val()) == true) {
alert('HTML Tag are not allowed');
}
e.preventDefault();
});
</script>
<script type="text/javascript">
function removeHTMLTags() {
var str="<html><p>I want to remove HTML tags</p></html>";
alert(str.replace(/<[^>]+>/g, ''));
}</script>
I am currently trying to code an input form where you can type and format a text for later use as XML entries. In order to make the HTML code XML-readable, I have to replace the code brackets with the corresponding symbol codes, i.e. < with < and > with >.
The formatted text gets transferred as HTML code with the variable inputtext, so we have for example the text
The <b>Genji</b> and the <b>Heike</b> waged a long and bloody war.
which needs to get converted into
The <b>Genji</b> and the <b>Heike</b> waged a long and bloody war.
I tried it with the .replace() function:
inputxml = inputxml.replace("<", "<");
inputxml = inputxml.replace(">", ">");
But this would just replace the first occurrence of the brackets. I'm pretty sure I need some sort of loop for this; I also tried using the each() function from jQuery (a friend recommended I looked at the jQuery package), but I'm still new to coding in general and I have troubles getting this to work.
How would you code a loop which would replace the code brackets within a variable as described above?
Additional information
You are, of course, right in the assumption that this is part of something larger. I am a graduate student in Japanese studies and currently, I am trying to visualize information about Japenese history in a more accessible way. For this, I am using the Simile Timeline API developed by MIT grad students. You can see a working test of a timeline on my homepage.
The Simile Timeline uses an API based on AJAX and Javascript. If you don't want to install the AJAX engine on your own server, you can implement the timeline API from the MIT. The data for the timeline is usually provided either by one or several XML files or JSON files. In my case, I use XML files; you can have a look at the XML structure in this example.
Within the timeline, there are so-called "events" on which you can click in order to reveal additional information within an info bubble popup. The text within those info bubbles originates from the XML source file. Now, if you want to do some HTML formatting within the info bubbles, you cannot use code bracket because those will just be displayed as plain text. It works if you use the symbol codes instead of the plain brackets, however.
The content for the timeline will be written by people absolutely and totally not accustomed to codified markup, i.e. historians, art historians, sociologists, among them several persons of age 50 and older. I have tried to explain to them how they have to format the XML file if they want to create a timeline, but they occasionally slip up and get frustrated when the timeline doesn't load because they forgot to close a bracket or to include an apostrophe.
In order to make it easier, I have tried making an easy-to-use input form where you can enter all the information and format the text WYSIWYG style and then have it converted into XML code which you just have to copy and paste into the XML source file. Most of it works, though I am still struggling with the conversion of the text markup in the main text field.
The conversion of the code brackets into symbol code is the last thing I needed to get working in order to have a working input form.
look here:
http://www.bradino.com/javascript/string-replace/
just use this regex to replace all:
str = str.replace(/\</g,"<") //for <
str = str.replace(/\>/g,">") //for >
To store an arbitrary string in XML, use the native XML capabilities of the browser. It will be a hell of a lot simpler that way, plus you will never have to think about the edge cases again (for example attribute values that contain quotes or pointy brackets).
A tip to think of when working with XML: Do never ever ever build XML from strings by concatenation if there is any way to avoid it. You will get yourself into trouble that way. There are APIs to handle XML, use them.
Going from your code, I would suggest the following:
$(function() {
$("#addbutton").click(function() {
var eventXml = XmlCreate("<event/>");
var $event = $(eventXml);
$event.attr("title", $("#titlefield").val());
$event.attr("start", [$("#bmonth").val(), $("#bday").val(), $("#byear").val()].join(" "));
if (parseInt($("#eyear").val()) > 0) {
$event.attr("end", [$("#emonth").val(), $("#eday").val(), $("#eyear").val()].join(" "));
$event.attr("isDuration", "true");
} else {
$event.attr("isDuration", "false");
}
$event.text( tinyMCE.activeEditor.getContent() );
$("#outputtext").val( XmlSerialize(eventXml) );
});
});
// helper function to create an XML DOM Document
function XmlCreate(xmlString) {
var x;
if (typeof DOMParser === "function") {
var p = new DOMParser();
x = p.parseFromString(xmlString,"text/xml");
} else {
x = new ActiveXObject("Microsoft.XMLDOM");
x.async = false;
x.loadXML(xmlString);
}
return x.documentElement;
}
// helper function to turn an XML DOM Document into a string
function XmlSerialize(xml) {
var s;
if (typeof XMLSerializer === "function") {
var x = new XMLSerializer();
s = x.serializeToString(xml);
} else {
s = xml.xml;
}
return s
}
https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/String/replace
You might use a regular expression with the "g" (global match) flag.
var entities = {'<': '<', '>': '>'};
'<inputtext><anotherinputext>'.replace(
/[<>]/g, function (s) {
return entities[s];
}
);
You could also surround your XML entries with the following:
<![CDATA[...]]>
See example:
<xml>
<tag><![CDATA[The <b>Genji</b> and the <b>Heike</b> waged a long and bloody war.]]></tag>
</xml>
Wikipedia Article:
http://en.wikipedia.org/wiki/CDATA
What you really need, as mentioned in comments, is to XML-encode the string. If you absolutely want to do this is Javascript, have a look at the PHP.js function htmlentities.
I created a simple JS function to replace Greater Than and Less Than characters
Here is an example dirty string: < noreply#email.com >
Here is an example cleaned string: [ noreply#email.com ]
function RemoveGLthanChar(notes) {
var regex = /<[^>](.*?)>/g;
var strBlocks = notes.match(regex);
strBlocks.forEach(function (dirtyBlock) {
let cleanBlock = dirtyBlock.replace("<", "[").replace(">", "]");
notes = notes.replace(dirtyBlock, cleanBlock);
});
return notes;
}
Call it using
$('#form1').submit(function (e) {
e.preventDefault();
var dirtyBlock = $("#comments").val();
var cleanedBlock = RemoveGLthanChar(dirtyBlock);
$("#comments").val(cleanedBlock);
this.submit();
});
While browsing I came across this blog post about using the Wikipedia API from JavaScript, to link a single search term to it's definition. At the end of the blog post the author mentions possible extensions including:
A plugin which auto links terms to Wikipedia articles.
This fits the bill perfectly for a project requirement I'm working on, but sadly I lack the programming skills to extend the original source code. What I'd like is to have a pure JavaScript snippet I can add to a webpage, that links all the terms on that webpage that have an article on an internal wiki to that wiki.
I know this might be asking for much, but the code looks like it's nearly there, and I'd be willing to add a bounty if anyone will do the remaining work for that virtual credit.. ;) I also suspect this might be of value to a few others, as I've seen similar requests but no working implementation (that's a mere JavaScript (and therefore portable) library/snippet include).
Here's a sample of the original source code, I hope anyone is able to add to this or point me to what I'd need to add if I were to implement this myself (in which case I'll share the code if I manage to put something together).
<script type="text/javascript"><!--
var spellcheck = function (data) {
var found = false; var url=''; var text = data [0];
if (text != document.getElementById ('spellcheckinput').value)
return;
for (i=0; i<data [1].length; i++) {
if (text.toLowerCase () == data [1] [i].toLowerCase ()) {
found = true;
url ='http://en.wikipedia.org/wiki/' + text;
document.getElementById ('spellcheckresult').innerHTML = '<b style="color:green">Correct</b> - <a target="_top" href="' + url + '">link</a>';
}
}
if (! found)
document.getElementById ('spellcheckresult').innerHTML = '<b style="color:red">Incorrect</b>';
};
var getjs = function (value) {
if (! value)
return;
url = 'http://en.wikipedia.org/w/api.php?action=opensearch&search='+value+'&format=json&callback=spellcheck';
document.getElementById ('spellcheckresult').innerHTML = 'Checking ...';
var elem = document.createElement ('script');
elem.setAttribute ('src', url);
elem.setAttribute ('type','text/javascript');
document.getElementsByTagName ('head') [0].appendChild (elem);
};--></script>
<form action="#" method="get" onsubmit="return false">
<p>Enter a word - <input id="spellcheckinput" onkeyup="getjs (this.value);" type="text"> <span id="spellcheckresult"></span></p></form>
Update
As pointed out in the comments, both the time it would take to link all words and how to handle multiple word spanning article names were concerns of mine as well..
I'd think starting with single word articles would already cover a large percentage of the use cases, with maybe some performance benefits gained when skipping the 500 most common words in the English language, but still I'm uncertain how feasible this approach will be..
On the upside however this would all be client side, and some delay in linking terms is fully acceptable.
Alternatively searching for terms the mouse is hovering over / selected might be acceptable as well, but I'm unsure if this would decrease or increase complexity..
Update 2
'Pointy' explained below that this functionality could be achieved by altering some fairly standard highlighting scripts, after having obtained a list of article topics from api.php?action=query&list=allpages.
To reinterate: we're using an internal wiki, so the list of articles is likely limited, non ambiguous and domain specific enough to overcome some of the expected problems in matching words.
Since we've had some good suggestions so far, and a few workable ideas, I'm starting a bounty to see if I can get a few answers on this..
Perhaps something like this might help:
Assuming very simple HTML/Text like so:
<div id="theText">Testing the auto link system here...</div>
And two very small scripts.
dictionary.js sets up your list of your terms. My thought was that this could be generated in php by querying the articles database if you wanted. It also can be loaded cross domain (as it sets window.termsRE). If you don't need to generate the list from the database, you could also manually put it with termlinker.js.
This code that generates the RegExp assumes that your terms array contains properly formatted strings to match using Regular Expressions, so be sure to use \\ to escape []\.?*+|(){}^&
// dictionary.js - define some terms
var terms = ['testing', 'auto link'];
window.termsRE = new RegExp("\\b("+terms.join("|")+")\\b",'gi');
termlinker.js is just a simple regexp search replace on the defined terms. It could be an inline <script> too. requires that the dictionary.js has been loaded before you run it.
// termlinker.js - add some tags
var element = document.getElementById("theText");
element.innerHTML = element.innerHTML.replace(termsRE, function(term) {
return "<a href='http://en.wikipedia.org/wiki/"+escape(term)+"'>"+term+"</a>";
});
This simply searches for any words in the terms array and replaces them with a link to the term. Of course, it will also match properties and values inside HTML tags, which could break your markup a little.
All thrown together you get this (jsbin preview)
Using the API
Based off of the "minimum case" from before, here is the code sample for using the API to receive the list of words directly and the jsbin preview
// Utility Function
RegExp.escape = function(text) {
if (!arguments.callee.sRE) {
var specials = [
'/', '.', '*', '+', '?', '|',
'(', ')', '[', ']', '{', '}', '\\'
];
arguments.callee.sRE = new RegExp(
'(\\' + specials.join('|\\') + ')', 'g'
);
}
return text.replace(arguments.callee.sRE, '\\$1');
};
// JSONP Callback for receiving the API
function receiveAPI(data) {
var terms = [];
if (!data || !data['query'] || !data['query']['allpages']) return false;
var pages = data.query.allpages
for (var x in pages) {
terms.push(RegExp.escape(pages[x].title));
}
window.termsRE = new RegExp("\\b("+terms.reverse().join("|")+")\\b",'gi');
linkterms();
}
function linkterms() {
var element = document.getElementById("theText");
element.innerHTML = element.innerHTML.replace(termsRE, function(term) {
return "<a href='http://en.wikipedia.org/wiki/"+escape(term)+"'>"+term+"</a>";
});
}
// the apfrom=testing can be removed, it is only there so that
// we can get some useful terms near "testing" to work with.
// we are limited to 500 terms for the purpose of this demo:
url = 'http://en.wikipedia.org/w/api.php?action=query&list=allpages&aplimit=500&format=json&callback=receiveAPI' + '&apfrom=testing';
var elem = document.createElement('script');
elem.setAttribute('src', url);
elem.setAttribute('type','text/javascript');
document.getElementsByTagName('head')[0].appendChild (elem);
This question already has answers here:
How to replace plain URLs with links?
(25 answers)
Closed 9 years ago.
Does anyone know of a script that can select all text references to URLs and automatically replace them with anchor tags pointing to those locations?
For example:
http://www.google.com
would automatically turn into
http://www.google.com
Note: I am wanting this because I don't want to go through all my content and wrap them with anchor tags.
NOTE: An updated and corrected version of this script is now available at https://github.com/maranomynet/linkify (GPL/MIT licence)
Hmm... to me this seems like the perfect task for jQuery.
...something like this came off the top of my mind:
// Define: Linkify plugin
(function($){
var url1 = /(^|<|\s)(www\..+?\..+?)(\s|>|$)/g,
url2 = /(^|<|\s)(((https?|ftp):\/\/|mailto:).+?)(\s|>|$)/g,
linkifyThis = function () {
var childNodes = this.childNodes,
i = childNodes.length;
while(i--)
{
var n = childNodes[i];
if (n.nodeType == 3) {
var html = $.trim(n.nodeValue);
if (html)
{
html = html.replace(/&/g, '&')
.replace(/</g, '<')
.replace(/>/g, '>')
.replace(url1, '$1$2$3')
.replace(url2, '$1$2$5');
$(n).after(html).remove();
}
}
else if (n.nodeType == 1 && !/^(a|button|textarea)$/i.test(n.tagName)) {
linkifyThis.call(n);
}
}
};
$.fn.linkify = function () {
return this.each(linkifyThis);
};
})(jQuery);
// Usage example:
jQuery('div.textbody').linkify();
It attempts to turn all occurrences of the following into links:
www.example.com/path
http://www.example.com/path
mailto:me#example.com
ftp://www.server.com/path
...all of the above wrapped in angle brackets (i.e. <...>)
Enjoy :-)
JQuery isn't going to help you a whole lot here as you're not really concerned with DOM traversal/manipulation (other than creating the anchor tag). If all your URLs were in <p class="url"> tags then perhaps.
A vanilla JavaScript solution is probably what you want, and as fate would have it, this guy should have you covered.
I have this function i call
textToLinks: function(text) {
var re = /(https?:\/\/(([-\w\.]+)+(:\d+)?(\/([\w/_\.]*(\?\S+)?)?)?))/g;
return text.replace(re, "$1");
}
I suggest you do this on your static pages before rendering to the browser, or you'll be pushing the burden of conversion computation onto your poor visitors. :) Here's how you might do it in Ruby (reading from stdin, writing to stdout):
while line = gets
puts line.gsub( /(^|[^"'])(http\S+)/, "\\1<a href='\\2'>\\2</a>" )
end
Obviously, you'll want to think about how to make this as robust as you desire. The above requires all URLs to start with http, and will check not to convert URLs that are in quotes (i.e. which may already be inside an <a href="...">). It will not catch ftp://, mailto:. It will happily convert material in places like <script> bodies, which you may not want to happen.
The most satisfactory solution is really to do the conversion by hand with your editor so you can eyeball and approve all substitutions. A good editor will let you do regexp substitution with group references (aka back references), so it shouldn't be a big deal.
Take a look at this JQuery plugin: https://code.google.com/p/jquery-linkifier/
Doing this server-side is not an option sometimes. Think of a client-side Twitter widget (that goes directly to Twitter API using jsonp), and you want to linkify all the URLs in the Tweets dynamically...
If you want a solution from another perspective... if you can run the pages through php and HTML Purifier, it can autoformat the output and linkify any urls.