Custom JavaScript with “parseScripts”

After successfully implementing and using literalHTML (discussed here) I decided to have a go at creating a reusable basis for adding new enhancements just like it; your own “language” if you will. The code itself relies on the fact that SCRIPT elements are only run as JavaScript if their type attribute is set appropriately (or, optionally, not set at all).

So, any arbitrary content can be held in a SCRIPT element assuming the browser does not recognize its type attribute; this has been demonstrated many times. For example, John Resig takes advantage of this in his “micro-templating” example and with his popular processing.js JavaScript port.

So, as evident from Resig’s work, you can do absolutely anything you want with content held within SCRIPT tags; even port/create your own programming language!

As mentioned, I’ve been working on a simple abstraction (called “parseScripts“) to simplify the process of enhancing JavaScript as you see fit. It’s somewhat experimental at the moment; I’ve only played with it for a short while and have yet to make any firm decisions as to the true usefulness of it but I’m blogging about it for your consideration.

The extent to which this is useful is entirely dependent on your imagination. Just as an example, I’ve implemented Alex‘s (from Dojo) recent Cramdas idea; usable in the following way:

<script type="application/javascript:cramdas">
var module = (#{
 
    var calc = #(n) {
        return n*n;
    };
 
    return #{
        // ... Other stuff
    };
 
})();
</script>

You should definitely have a read of Alex’s post but essentially the crux is that all occurrences of the word “function” should be replaced with a shorter syntax; he proposed what you can see above; i.e. replacing “function” with “#” (plus ‘#{}’ is equivalent to a literal function with no parameters). The usefulness of his idea is obviously debatable; I’m only using it as an example.

Notice the script type attribute (“application/javascript:cramdas”). The contents of this SCRIPT element will not be run as JavaScript by the browser so you’re free to do what you want with it.

parseScripts(/:cramdas$/, function(unparsed){
 
    var strings = [],
        sid = '_' + (+new Date());
 
    // Extract strings before #>function replacement.
    // Re-insert them at the end.
    // (So we don't replace '#' occurances within strings)
 
    return unparsed
        .replace(/("|')((?:\1|.)+?)1/g, function($0){
            strings[strings.length] = $0;
            return sid;
        })
        .replace(/#(s*{)?/g, function($0, $1){
            return 'function' + ($1 ? '(){' : '');
        })
        .replace(RegExp(sid,'g'), function(){
            return strings.shift();    
        });
});

The above code uses parseScripts (on Github) to implement the hash tag functions as per Alex’s musings.

You may think this adds an unacceptable overhead to script execution time but the speed is all down to the efficiency of your parser!

The parseScripts works by running the content of each chosen SCRIPT tag through the function (second parameter) and then “globally eval’ing” the returned JavaScript. It works on nested code (code within SCRIPT tags) and with locally hosted files (src="/file/my.js").

I hope someone besides me finds this interesting/exciting!

Thanks for reading! Please share your thoughts with me on Twitter. Have a great day!