/*
This code may be used internally to Travelocity without limitation,
exclusion, or restriction.  If this code is used externally the
following comment must be included everywhere this code is used.
*/

/***********************************************************************
This is written by Austin Cheney on 7 May 2009.  Anybody may use this
code without permission so long as this comment exists verbatim in each
instance of its use.

http://www.travelocity.com/
http://mailmarkup.org/
***********************************************************************/

/*
This is a minification application for markup languages.  Its only
requirement is that the modified jsmin.js be included prior to the
inclusion of this code.
http://mailmarkup.org/prettydiff/jsmin.js

Minification is acheived according to this pattern:

   1) It looks for syntax characters inside tags.  Whitespace is
      tokenized inside tags and removes all whitespace directly next to
      a syntax character except quotes that do not occur directly next
      or one space away from an equal sign. Numbers, hypens (dash,
      minus), underscores, alpha characters, and ampersands were not
      considered in this logic.
   3) It takes the contents of script and style tags, runs jsmin against
      this content, removes the original content, and then returns the
      code minified with jsmin.
   4) It removes all comments.
   5) Then at the end it removes even more spaces, using the replace
      method, to tokenize additional spaces introduced by the prior
      logic except spaces between tags and content.

markupmin is composed of these child objects:
   - it: This self initiating function performs a single pass through
   the data looking for markup tags, script blocks, style blocks, and
   comments.  
   - markupspace: This function is executed by the it function when a
   tag is encountered that is not a comment, style block, or script
   block.  This function serves to remove all spaces around syntax
   characters inside tags except double and single quotes.
   - markupcomment: This function removes opening comment characters and
   every character after until the closing comment is found.
   - markupscript: This function is fired if a script or style tag is
   found.  It checks if jsmin exists as a named object, or otherwise
   immediately exits.  This function finds the opening tag, and records
   it.  Then it takes all the characters inside the concerned tag and
   passes them to jsmin.  The opening tag and output of jsmin is
   returned only after the original opening tag and tag content are
   removed.

   At the end all other white space is tokenized and spaces around the
   opening and closing of tags, except those adjacent to content, is
   removed.
*/
"use strict";
var markupmin = function (x, slop, comments) {
    var i, a, b, c, white = new RegExp(/\s/),

    //This closure performs checks for excessive whitespace inside
    //markup tags.  Whitespace around certain syntax characters is
    //collapsed and all remaining whitespace is tokenized.
    markupspace = function () {
        var d = '';
        for (a = i; a < x.length; a += 1) {
            if (x[a] === ">") {
                break;
            } else {
                d = d + x[a];
                x[a] = '';
            }
        }
        d = d.replace(/\s+/g, " ").replace(/\s*,\s+/g, ", ").replace(/\s*;\s*/g, ";").replace(/\s*\/\s*/g, "/").replace(/\s*\.\s*/g, ".").replace(/\s*=\s*/g, "=").replace(/\s*:\s*/g, ":").replace(/\=" /g, '="').replace(/\=' /g, "='").replace(/ \="/g, '="').replace(/ \='/g, "='") + ">";
        i = a;
        x[i] = d;
    },

    //This function looks for markup comments and removes all
    //contained characters until the comment is properly closed.  If
    //a comment is not properly close then all remaining characters
    //will be removed, which is fine because they would not be
    //parsed by a browser anyways.
    markupcomment = function () {
        c = '';
        for (b = i; b < x.length; b += 1) {
            if (x[b] === "-" && x[b + 1] === "-" && x[b + 2] === ">") {
                x[b] = "";
                x[b + 1] = "";
                x[b + 2] = "";
                break;
            } else if (comments !== "comments") {
                x[b] = "";
            } else {
                c = c + x[b];
                x[b] = "";
            }
        }
        if (comments === "comments") {
            c = " " + c + "-->";
            x[i] = c;
        }
    },

    //This function passes the content of script and style blocks
    //off to jsmin.
    markupscript = function (y) {
        if (jsmin === undefined) {
            return;
        }
        var e = [],
        f,
        h = '',
        j = y.split(''),
        m;
        j.splice(5, y.length);
        j = "</" + j.join('');
        for (c = i; c < x.length; c += 1) {
            if ((x[c] + x[c + 1] + x[c + 2] + x[c + 3] + x[c + 4] + x[c + 5] + x[c + 6]).toLowerCase() === j) {
                f = c;
                break;
            }
        }
        for (c = i; c < f; c += 1) {
            if (x[c - 1] !== ">") {
                e.push(x[c]);
                x[c] = "";
            } else {
                break;
            }
        }
        m = e[0];
        e.splice(0, 1);
        if (white.test(e[0]) === true) {
            e.splice(0, 1);
        }
        for (; f < x.length; f += 1) {
            if (x[f] !== ">") {
                h = h + x[f];
                x[f] = '';
            } else {
                break;
            }
        }
        h = h + ">";
        i = f;
        if (e.join('') === "") {
            x[i] = m + h;
            return;
        }
        e = e.join('');
        if (slop !== 'none') {
            if (y === "style") {
                e = jsmin('', e, 3, 'css', slop);
            } else {
                e = jsmin('', e, 3, 'js', slop);
            }
        }
        for (c = 0; c < e.length; c += 1) {
            if (white.test(e.charAt(c)) === true) {
                e = e.substr(c + 1);
            } else {
                break;
            }
        }
        x[i] = m + e + h;
    },

    preserve = function (end) {
        b = '';
        for (c = i; c < x.length; c += 1) {
            if (x[c - 1] + x[c] === end) {
                break;
            }
        }
        for (a = i; a < c; a += 1) {
            b += x[a];
            x[a] = '';
        }
        x[i] = b;
        i = c;
    },

    content = function () {
        b = '';
        for (a = i; a < x.length; a += 1) {
            if (x[a] === "<") {
                break;
            } else {
                b = b + x[a];
                x[a] = '';
            }
        }
        i = a - 1;
        x[i] = b.replace(/\s+/g, " ");
    },

    //This self invocating function is the action piece of
    //markupmin.  It is a single loop that execute the closures
    //described above when comments, tags, style blocks, and/or
    //script blocks are encountered.  No logic is performed on
    //content, aside from whitespace tokenization.
    it = (function () {
        x = x.split('');
        for (i = 0; i < x.length; i += 1) {
            if ((x[i] + x[i + 1] + x[i + 2] + x[i + 3] + x[i + 4] + x[i + 5] + x[i + 6]).toLowerCase() === "<script") {
                markupspace();
                markupscript("script");
            } else if ((x[i] + x[i + 1] + x[i + 2] + x[i + 3] + x[i + 4] + x[i + 5]).toLowerCase() === "<style") {
                markupspace();
                markupscript("style");
                continue;
            } else if (x[i] + x[i + 1] + x[i + 2] + x[i + 3] === "<!--" && x[i + 4] !== "#") {
                markupcomment();
            } else if (x[i] + x[i + 1] + x[i + 2] + x[i + 3] + x[i + 4] === "<?php") {
                preserve("?>");
            } else if (x[i] + x[i + 1] === "<%") {
                preserve("%>");
            } else if ((x[i] === "<" && x[i + 1] !== "!") || (x[i] === "<" && x[i + 1] === "!" && x[i + 2] !== "-")) {
                markupspace();
            } else if (x[i] === undefined) {
                x[i] = "";
            } else if (x[i - 1] !== undefined && x[i - 1].charAt(x[i - 1].length - 1) === ">") {
                content();
            }
        }
    }());
    x = x.join('').replace(/-->\s+/g, '-->').replace(/\s+<\?php/g, ' <?php').replace(/\s+<%/g, ' <%').replace(/>\s+/g, '> ').replace(/\s+</g, ' <').replace(/ >/g, '>').replace(/< /g, '<').replace(/ \/>/g, '/>').replace(/> <\//g, '></');
    return x;
};