aboutsummaryrefslogtreecommitdiffstats
path: root/build/js/Packer.js
diff options
context:
space:
mode:
Diffstat (limited to 'build/js/Packer.js')
-rw-r--r--build/js/Packer.js205
1 files changed, 205 insertions, 0 deletions
diff --git a/build/js/Packer.js b/build/js/Packer.js
new file mode 100644
index 000000000..4e907cfb1
--- /dev/null
+++ b/build/js/Packer.js
@@ -0,0 +1,205 @@
+/*
+ Packer version 3.0 (beta 5) - copyright 2004-2007, Dean Edwards
+ http://www.opensource.org/licenses/mit-license
+*/
+
+eval(base2.namespace);
+
+var IGNORE = RegGrp.IGNORE;
+var REMOVE = "";
+var SPACE = " ";
+var WORDS = /\w+/g;
+
+var Packer = Base.extend({
+ minify: function(script) {
+ script = script.replace(Packer.CONTINUE, "");
+ script = Packer.clean.exec(script);
+ script = Packer.whitespace.exec(script);
+ script = Packer.clean.exec(script); // seem to grab a few more bytes on the second pass
+ return script;
+ },
+
+ pack: function(script, base62, shrink) {
+ script = this.minify(script);
+ if (shrink) script = this._shrinkVariables(script);
+ if (base62) script = this._base62Encode(script);
+ return script;
+ },
+
+ _base62Encode: function(script) {
+ var words = new Words(script);
+ var encode = function(word) {
+ return words.fetch(word).encoded;
+ };
+
+ /* build the packed script */
+
+ var p = this._escape(script.replace(WORDS, encode));
+ var a = Math.min(Math.max(words.count(), 2), 62);
+ var c = words.count();
+ var k = words;
+ var e = Packer["ENCODE" + (a > 10 ? a > 36 ? 62 : 36 : 10)];
+ var r = a > 10 ? "e(c)" : "c";
+
+ // the whole thing
+ return format(Packer.UNPACK, p,a,c,k,e,r);
+ },
+
+ _escape: function(script) {
+ // single quotes wrap the final string so escape them
+ // also escape new lines required by conditional comments
+ return script.replace(/([\\'])/g, "\\$1").replace(/[\r\n]+/g, "\\n");
+ },
+
+ _shrinkVariables: function(script) {
+ // Windows Scripting Host cannot do regexp.test() on global regexps.
+ var global = function(regexp) {
+ // This function creates a global version of the passed regexp.
+ return new RegExp(regexp.source, "g");
+ };
+
+ var data = []; // encoded strings and regular expressions
+ var store = function(string) {
+ var replacement = "#" + data.length;
+ data.push(string);
+ return replacement;
+ };
+
+ // Base52 encoding (a-Z)
+ var encode52 = function(c) {
+ return (c < 52 ? '' : arguments.callee(parseInt(c / 52))) +
+ ((c = c % 52) > 25 ? String.fromCharCode(c + 39) : String.fromCharCode(c + 97));
+ };
+
+ // identify blocks, particularly identify function blocks (which define scope)
+ var BLOCK = /(function\s*[\w$]*\s*\(\s*([^\)]*)\s*\)\s*)?(\{([^{}]*)\})/;
+ var VAR_ = /var\s+/g;
+ var VAR_NAME = /var\s+[\w$]{2,}/g; // > 1 char
+ var COMMA = /\s*,\s*/;
+ var blocks = []; // store program blocks (anything between braces {})
+ // encoder for program blocks
+ var encode = function(block, func, args) {
+ if (func) { // the block is a function block
+
+ // decode the function block (THIS IS THE IMPORTANT BIT)
+ // We are retrieving all sub-blocks and will re-parse them in light
+ // of newly shrunk variables
+ block = decode(block);
+
+ // create the list of variable and argument names
+ var vars = match(block, VAR_NAME).join(",").replace(VAR_, "");
+ var ids = Array2.combine(args.split(COMMA).concat(vars.split(COMMA)));
+
+ // process each identifier
+ var count = 0, shortId;
+ forEach (ids, function(id) {
+ id = rescape(trim(id));
+ if (id) {
+ // find the next free short name (check everything in the current scope)
+ do shortId = encode52(count++);
+ while (new RegExp("[^\\w$.]" + shortId + "[^\\w$:]").test(block));
+ // replace the long name with the short name
+ var reg = new RegExp("([^\\w$.])" + id + "([^\\w$:])");
+ while (reg.test(block)) block = block.replace(global(reg), "$1" + shortId + "$2");
+ var reg = new RegExp("([^{,])" + id + ":", "g");
+ block = block.replace(reg, "$1" + shortId + ":");
+ }
+ });
+ }
+ var replacement = "~" + blocks.length;
+ blocks.push(block);
+ return replacement;
+ };
+
+ // decoder for program blocks
+ var ENCODED = /~(\d+)/;
+ var decode = function(script) {
+ while (ENCODED.test(script)) {
+ script = script.replace(global(ENCODED), function(match, index) {
+ return blocks[index];
+ });
+ }
+ return script;
+ };
+
+ // encode strings and regular expressions
+ script = Packer.data.exec(script, store);
+
+ // remove closures (this is for base2 namespaces only)
+ script = script.replace(/new function\(_\)\s*\{/g, "{;#;");
+
+ // encode blocks, as we encode we replace variable and argument names
+ while (BLOCK.test(script)) {
+ script = script.replace(global(BLOCK), encode);
+ }
+
+ // put the blocks back
+ script = decode(script);
+
+ // put back the closure (for base2 namespaces only)
+ script = script.replace(/\{;#;/g, "new function(_){");
+
+ // put strings and regular expressions back
+ script = script.replace(/#(\d+)/g, function(match, index) {
+ return data[index];
+ });
+
+ return script;
+ }
+}, {
+ CONTINUE: /\\\r?\n/g,
+
+ ENCODE10: "String",
+ ENCODE36: "function(c){return c.toString(a)}",
+ ENCODE62: "function(c){return(c<a?'':e(parseInt(c/a)))+((c=c%a)>35?String.fromCharCode(c+29):c.toString(36))}",
+
+ UNPACK: "eval(function(p,a,c,k,e,r){e=%5;if(!''.replace(/^/,String)){while(c--)r[%6]=k[c]" +
+ "||%6;k=[function(e){return r[e]}];e=function(){return'\\\\w+'};c=1};while(c--)if(k[c])p=p." +
+ "replace(new RegExp('\\\\b'+e(c)+'\\\\b','g'),k[c]);return p}('%1',%2,%3,'%4'.split('|'),0,{}))",
+
+ init: function() {
+ this.data = reduce(this.data, new RegGrp, function(data, replacement, expression) {
+ data.store(this.javascript.exec(expression), replacement);
+ return data;
+ }, this);
+ this.clean = this.data.union(this.clean);
+ this.whitespace = this.data.union(this.whitespace);
+ },
+
+ clean: {
+ ";;;[^\\n]*": REMOVE, // triple semi-colons treated like line comments
+ "\\(\\s*;\\s*;\\s*\\)": "(;;)", // for (;;) loops
+ "throw[^};]+[};]": IGNORE, // a safari 1.3 bug
+ ";+\\s*([};])": "$1"
+ },
+
+ data: {
+ // strings
+ "STRING1": IGNORE,
+ 'STRING2': IGNORE,
+ "CONDITIONAL": IGNORE, // conditional comments
+ "(COMMENT1)\\n\\s*(REGEXP)?": "\n$2",
+ "(COMMENT2)\\s*(REGEXP)?": " $3",
+ "COMMENT1$": REMOVE,
+ "([\\[(\\^=,{}:;&|!*?])\\s*(REGEXP)": "$1$2"
+ },
+
+ javascript: new RegGrp({
+ COMMENT1: /\/\/[^\n]*/.source,
+ COMMENT2: /\/\*[^*]*\*+([^\/][^*]*\*+)*\//.source,
+ CONDITIONAL: /\/\*@|@\*\/|\/\/@[^\n]*\n/.source,
+ REGEXP: /\/(\\\/|[^*\/])(\\.|[^\/\n\\])*\//.source,
+ STRING1: /'(\\.|[^'\\])*'/.source,
+ STRING2: /"(\\.|[^"\\])*"/.source
+ }),
+
+ whitespace: {
+ "(\\d)\\s+(\\.\\s*[a-z\\$_\\[(])": "$1 $2", // http://dean.edwards.name/weblog/2007/04/packer3/#comment84066
+ "([+-])\\s+([+-])": "$1 $2", // c = a++ +b;
+ "\\b\\s+\\$\\s+\\b": " $ ", // var $ in
+ "\\$\\s+\\b": "$ ", // object$ in
+ "\\b\\s+\\$": " $", // return $object
+ "\\b\\s+\\b": SPACE,
+ "\\s+": REMOVE
+ }
+});