JavaScript function to highlight URLs

September 3rd, 2012

Sometimes you want to show the user a URL that is nicely visually structured. This happens especially in cases where it is important to focus on e.g. query parameters of an URL. I had this need and so I created urlhighlight, a very little (151 loc) JavaScript function that takes a URL as a parameter and returns HTML that wraps components of that URL. These components can be then styled in CSS.

Let me jump directly to an example that shows urlhighlight() in action.



Example

urlhiglight({ url: 'http://www.example.com?foo=5&bar=baz#top' }) produces this HTML snippet:

<span class="url-protocol">http:</span>
<span class="url-protocol-delimiter">//</span>
<span class="url-host">www.example.com</span>
<span class="url-query-delimiter">?</span>
<span class="url-query-param-name">bar</span>
<span class="url-query-param-assign">=</span>
<span class="url-query-param-value">baz</span>
<span class="url-query-param-delimiter">&</span>
<span class="url-query-param-name">foo</span>
<span class="url-query-param-assign">=</span>
<span class="url-query-param-value">5</span>
<span class="url-hash-delimiter">#</span>
<span class="url-hash">top</span>
    
which is then styled in the included CSS stylesheet.

Implementation

Parsing URLs is not that straighforward as it might look at the first glance. For the curious ones, RFC 1738 document defines BNF grammar for URL syntax. Fortunately, we can take advantage of the URL parser implemented in browsers. urlhighlight uses this smart URL parsing DOM technique shown by James Padolsey with a slight modification to support data URLs:



    var a = document.createElement('a');

    function parse(url) {
         
        a.href = url;

        var parsedUrl = {

            source: url,
            protocol: a.protocol,
            host: a.hostname,
            port: a.port,
            query: a.search,
            params: (function() {
                
                var queryParams = {},
                    segments = a.search.replace(/^\?/,'').split('&'),
                    idx = segments.length;
                    
                while (idx--) {
                    if (segments[idx]) {
                        var nameValue = segments[idx].split('=');
                        queryParams[nameValue[0]] = nameValue[1];
                    }
                }
                return queryParams;
            })(),
            
            file: (a.pathname.match(/\/([^\/?#]+)$/i) || [,''])[1],
            hash: a.hash.replace('#',''),
            path: a.pathname.replace(/^([^\/])/,'/$1'),
            relative: (a.href.match(/tps?:\/\/[^\/]+(.+)/) || [,''])[1],
            segments: a.pathname.replace(/^\//,'').split('/')
        };

        if (parsedUrl.protocol === 'data-uri:') {
            
            parsedUrl.mimeType = a.pathname.replace(/,.*$/, '');
            parsedUrl.encoding = a.pathname.replace(/(^.*,)(.*)(;.*$)/, '$2');
            parsedUrl.data = a.pathname.replace(/(^.*,)(.*)(;.*$)/, '$3').substring(1);
        }
        
        return parsedUrl;
    }

Advanced usage

urlhighlight also supports custom templates. This means that the default <span> elements that are used to produce the resulting HTML snippet can be replaced with whatever string you defined. An example call with different template for the protocol component could look something like:



urlhighlight({ 
    url: 'http://www.example.com', 
    protocol: '<div class="myprotocol">{{protocol}}</div>' 
})

    

This is the complete list of all the template names that can be changed:

Following list of all the CSS classes that are used in the default templates:

data-uri specific: