<commit_before>/**
 * impress.js
 *
 * impress.js is a presentation tool based on the power of CSS3 transforms and transitions
 * in modern browsers and inspired by the idea behind prezi.com.
 *
 *
 * Copyright 2011-2012 Bartek Szopka (@bartaz)
 *
 * Released under the MIT and GPL Licenses.
 *
 * ------------------------------------------------
 *  author:  Bartek Szopka
 *  version: 0.4pre (in development)
 *  url:     http://bartaz.github.com/impress.js/
 *  source:  http://github.com/bartaz/impress.js/
 */

(function ( document, window ) {
    'use strict';

    // HELPER FUNCTIONS

    var pfx = (function () {

        var style = document.createElement('dummy').style,
            prefixes = 'Webkit Moz O ms Khtml'.split(' '),
            memory = {};

        return function ( prop ) {
            if ( typeof memory[ prop ] === "undefined" ) {

                var ucProp  = prop.charAt(0).toUpperCase() + prop.substr(1),
                    props   = (prop + ' ' + prefixes.join(ucProp + ' ') + ucProp).split(' ');

                memory[ prop ] = null;
                for ( var i in props ) {
                    if ( style[ props[i] ] !== undefined ) {
                        memory[ prop ] = props[i];
                        break;
                    }
                }

            }

            return memory[ prop ];
        }

    })();

    var arrayify = function ( a ) {
        return [].slice.call( a );
    };

    var css = function ( el, props ) {
        var key, pkey;
        for ( key in props ) {
            if ( props.hasOwnProperty(key) ) {
                pkey = pfx(key);
                if ( pkey != null ) {
                    el.style[pkey] = props[key];
                }
            }
        }
        return el;
    }

    var byId = function ( id ) {
        return document.getElementById(id);
    }

    var $ = function ( selector, context ) {
        context = context || document;
        return context.querySelector(selector);
    };

    var $$ = function ( selector, context ) {
        context = context || document;
        return arrayify( context.querySelectorAll(selector) );
    };

    var translate = function ( t ) {
        return " translate3d(" + t.x + "px," + t.y + "px," + t.z + "px) ";
    };

    var rotate = function ( r, revert ) {
        var rX = " rotateX(" + r.x + "deg) ",
            rY = " rotateY(" + r.y + "deg) ",
            rZ = " rotateZ(" + r.z + "deg) ";

        return revert ? rZ+rY+rX : rX+rY+rZ;
    };

    var scale = function ( s ) {
        return " scale(" + s + ") ";
    };

    var perspective = function ( p ) {
        return " perspective(" + p + "px) ";
    };

    var getElementFromUrl = function () {
        // get id from url # by removing `#` or `#/` from the beginning,
        // so both `#slide-id` and "legacy" `#/slide-id` will work
        return byId( window.location.hash.replace(/^#\/?/,"") );
    };

    // CHECK SUPPORT

    var ua = navigator.userAgent.toLowerCase();
    var impressSupported = ( pfx("perspective") != null ) &&
                           ( document.body.classList ) &&
                           ( document.body.dataset ) &&
                           ( ua.search(/(iphone)|(ipod)|(android)/) == -1 );

    var roots = {};

    var impress = window.impress = function ( rootId ) {

        rootId = rootId || "impress";

        // if already initialized just return the API
        if (roots["impress-root-" + rootId]) {
            return roots["impress-root-" + rootId];
        }

        // DOM ELEMENTS

        var root = byId( rootId );

        if (!impressSupported) {
            root.className = "impress-not-supported";
            return;
        } else {
            root.className = "";
        }

        // viewport updates for iPad
        var meta = $("meta[name='viewport']") || document.createElement("meta");
        // hardcoding these values looks pretty bad, as they kind of depend on the content
        // so they should be at least configurable
        meta.content = "width=device-width, minimum-scale=1, maximum-scale=1, user-scalable=no";
        if (meta.parentNode != document.head) {
            meta.name = 'viewport';
            document.head.appendChild(meta);
        }

        // configuration object
        // probably will get extended (and configurable) later
        var config = {
            width: 1024,
            height: 768,
            maxScale: 1,
            minScale: 0
        }

        var canvas = document.createElement("div");
        canvas.className = "canvas";

        arrayify( root.childNodes ).forEach(function ( el ) {
            canvas.appendChild( el );
        });
        root.appendChild(canvas);

        var steps = $$(".step", root);

        // SETUP
        // set initial values and defaults

        document.documentElement.style.height = "100%";

        css(document.body, {
            height: "100%",
            overflow: "hidden"
        });

        var props = {
            position: "absolute",
            transformOrigin: "top left",
            transition: "all 0s ease-in-out",
            transformStyle: "preserve-3d"
        }

        css(root, props);
        css(root, {
            top: "50%",
            left: "50%",
            transform: perspective(1000)
        });
        css(canvas, props);

        var current = {
            translate: { x: 0, y: 0, z: 0 },
            rotate:    { x: 0, y: 0, z: 0 },
            scale:     1
        };

        var stepData = {};

        var isStep = function ( el ) {
            return !!(el && el.id && stepData["impress-" + el.id]);
        };

        var computeWindowScale = function () {
            var hScale = window.innerHeight / config.height,
                wScale = window.innerWidth / config.width,
                scale = hScale > wScale ? wScale : hScale;

            if (config.maxScale && scale > config.maxScale) {
                scale = config.maxScale;
            }

            if (config.minScale && scale < config.minScale) {
                scale = config.minScale;
            }

            return scale;
        };

        steps.forEach(function ( el, idx ) {
            var data = el.dataset,
                step = {
                    translate: {
                        x: data.x || 0,
                        y: data.y || 0,
                        z: data.z || 0
                    },
                    rotate: {
                        x: data.rotateX || 0,
                        y: data.rotateY || 0,
                        z: data.rotateZ || data.rotate || 0
                    },
                    scale: data.scale || 1,
                    el: el
                };

            if ( !el.id ) {
                el.id = "step-" + (idx + 1);
            }

            stepData["impress-" + el.id] = step;

            css(el, {
                position: "absolute",
                transform: "translate(-50%,-50%)" +
                           translate(step.translate) +
                           rotate(step.rotate) +
                           scale(step.scale),
                transformStyle: "preserve-3d"
            });

        });

        // making given step active

        var active = null;
        var hashTimeout = null;

        var windowScale = computeWindowScale();

        var goto = function ( el, force ) {
            if ( !isStep(el) || (el == active && !force) ) {
                // selected element is not defined as step or is already active
                return false;
            }

            // Sometimes it's possible to trigger focus on first link with some keyboard action.
            // Browser in such a case tries to scroll the page to make this element visible
            // (even that body overflow is set to hidden) and it breaks our careful positioning.
            //
            // So, as a lousy (and lazy) workaround we will make the page scroll back to the top
            // whenever slide is selected
            //
            // If you are reading this and know any better way to handle it, I'll be glad to hear about it!
            window.scrollTo(0, 0);

            var step = stepData["impress-" + el.id];

            if ( active ) {
                active.classList.remove("active");
            }
            el.classList.add("active");

            root.className = "step-" + el.id;

            // Setting fragment URL with `history.pushState`
            // and it has to be set after animation finishes, because in Chrome it
            // causes transtion being laggy
            // BUG: http://code.google.com/p/chromium/issues/detail?id=62820
            window.clearTimeout( hashTimeout );
            hashTimeout = window.setTimeout(function () {
                window.location.hash = "#/" + el.id;
            }, 1000);

            var target = {
                rotate: {
                    x: -parseInt(step.rotate.x, 10),
                    y: -parseInt(step.rotate.y, 10),
                    z: -parseInt(step.rotate.z, 10)
                },
                translate: {
                    x: -step.translate.x,
                    y: -step.translate.y,
                    z: -step.translate.z
                },
                scale: 1 / parseFloat(step.scale)
            };

            // check if the transition is zooming in or not
            var zoomin = target.scale >= current.scale;

            // if presentation starts (nothing is active yet)
            // don't animate (set duration to 0)
            var duration = (active) ? "1s" : "0";

            if (force) {
                windowScale = computeWindowScale();
            }

            css(root, {
                // to keep the perspective look similar for different scales
                // we need to 'scale' the perspective, too
                transform: perspective( 1000 / (target.scale * windowScale) ) + scale(target.scale * windowScale),
                transitionDuration: duration,
                transitionDelay: (zoomin ? "500ms" : "0ms")
            });

            css(canvas, {
                transform: rotate(target.rotate, true) + translate(target.translate),
                transitionDuration: duration,
                transitionDelay: (zoomin ? "0ms" : "500ms")
            });

            current = target;
            active = el;

            return el;
        };

        var prev = function () {
            var prev = steps.indexOf( active ) - 1;
            prev = prev >= 0 ? steps[ prev ] : steps[ steps.length-1 ];

            return goto(prev);
        };

        var next = function () {
            var next = steps.indexOf( active ) + 1;
            next = next < steps.length ? steps[ next ] : steps[ 0 ];

            return goto(next);
        };

        window.addEventListener("hashchange", function () {
            goto( getElementFromUrl() );
        }, false);

        window.addEventListener("orientationchange", function () {
            window.scrollTo(0, 0);
        }, false);

        // START
        // by selecting step defined in url or first step of the presentation
        goto(getElementFromUrl() || steps[0]);

        return (roots[ "impress-root-" + rootId ] = {
            goto: goto,
            next: next,
            prev: prev
        });

    }
})(document, window);

// EVENTS

(function ( document, window ) {
    'use strict';

    // throttling function calls, by Remy Sharp
    // http://remysharp.com/2010/07/21/throttling-function-calls/
    var throttle = function (fn, delay) {
        var timer = null;
        return function () {
            var context = this, args = arguments;
            clearTimeout(timer);
            timer = setTimeout(function () {
                fn.apply(context, args);
            }, delay);
        };
    };

    // keyboard navigation handlers

    // prevent default keydown action when one of supported key is pressed
    document.addEventListener("keydown", function ( event ) {
        if ( event.keyCode == 9 || ( event.keyCode >= 32 && event.keyCode <= 34 ) || (event.keyCode >= 37 && event.keyCode <= 40) ) {
            event.preventDefault();
        }
    }, false);

    // trigger impress action on keyup
    document.addEventListener("keyup", function ( event ) {
        if ( event.keyCode == 9 || ( event.keyCode >= 32 && event.keyCode <= 34 ) || (event.keyCode >= 37 && event.keyCode <= 40) ) {
            switch( event.keyCode ) {
                case 33: ; // pg up
                case 37: ; // left
                case 38:   // up
                         impress().prev();
                         break;
                case 9:  ; // tab
                case 32: ; // space
                case 34: ; // pg down
                case 39: ; // right
                case 40:   // down
                         impress().next();
                         break;
            }

            event.preventDefault();
        }
    }, false);

    // delegated handler for clicking on the links to presentation steps
    document.addEventListener("click", function ( event ) {
        // event delegation with "bubbling"
        // check if event target (or any of its parents is a link)
        var target = event.target;
        while ( (target.tagName != "A") &&
                (target != document.documentElement) ) {
            target = target.parentNode;
        }

        if ( target.tagName == "A" ) {
            var href = target.getAttribute("href");

            // if it's a link to presentation step, target this step
            if ( href && href[0] == '#' ) {
                target = document.getElementById( href.slice(1) );
            }
        }

        if ( impress().goto(target) ) {
            event.stopImmediatePropagation();
            event.preventDefault();
        }
    }, false);

    // delegated handler for clicking on step elements
    document.addEventListener("click", function ( event ) {
        var target = event.target;
        // find closest step element
        while ( !target.classList.contains("step") &&
                (target != document.documentElement) ) {
            target = target.parentNode;
        }

        if ( impress().goto(target) ) {
            event.preventDefault();
        }
    }, false);

    // touch handler to detect taps on the left and right side of the screen
    document.addEventListener("touchstart", function ( event ) {
        if (event.touches.length === 1) {
            var x = event.touches[0].clientX,
                width = window.innerWidth * 0.3,
                result = null;

            if ( x < width ) {
                result = impress().prev();
            } else if ( x > window.innerWidth - width ) {
                result = impress().next();
            }

            if (result) {
                event.preventDefault();
            }
        }
    }, false);

    // rescale presentation when window is resized
    window.addEventListener("resize", throttle(function (event) {
        // force going to active step again, to trigger rescaling
        impress().goto( document.querySelector(".active"), true );
    }, 250), false);
})(document, window);

<commit_msg>added number validation and impress.js config<commit_after>/**
 * impress.js
 *
 * impress.js is a presentation tool based on the power of CSS3 transforms and transitions
 * in modern browsers and inspired by the idea behind prezi.com.
 *
 *
 * Copyright 2011-2012 Bartek Szopka (@bartaz)
 *
 * Released under the MIT and GPL Licenses.
 *
 * ------------------------------------------------
 *  author:  Bartek Szopka
 *  version: 0.4pre (in development)
 *  url:     http://bartaz.github.com/impress.js/
 *  source:  http://github.com/bartaz/impress.js/
 */

(function ( document, window ) {
    'use strict';

    // HELPER FUNCTIONS

    var pfx = (function () {

        var style = document.createElement('dummy').style,
            prefixes = 'Webkit Moz O ms Khtml'.split(' '),
            memory = {};

        return function ( prop ) {
            if ( typeof memory[ prop ] === "undefined" ) {

                var ucProp  = prop.charAt(0).toUpperCase() + prop.substr(1),
                    props   = (prop + ' ' + prefixes.join(ucProp + ' ') + ucProp).split(' ');

                memory[ prop ] = null;
                for ( var i in props ) {
                    if ( style[ props[i] ] !== undefined ) {
                        memory[ prop ] = props[i];
                        break;
                    }
                }

            }

            return memory[ prop ];
        }

    })();

    var arrayify = function ( a ) {
        return [].slice.call( a );
    };

    var css = function ( el, props ) {
        var key, pkey;
        for ( key in props ) {
            if ( props.hasOwnProperty(key) ) {
                pkey = pfx(key);
                if ( pkey != null ) {
                    el.style[pkey] = props[key];
                }
            }
        }
        return el;
    }

    var toNumber = function (numeric, fallback) {
        return isNaN(numeric) ? (fallback || 0) : Number(numeric);
    };

    var byId = function ( id ) {
        return document.getElementById(id);
    }

    var $ = function ( selector, context ) {
        context = context || document;
        return context.querySelector(selector);
    };

    var $$ = function ( selector, context ) {
        context = context || document;
        return arrayify( context.querySelectorAll(selector) );
    };

    var translate = function ( t ) {
        return " translate3d(" + t.x + "px," + t.y + "px," + t.z + "px) ";
    };

    var rotate = function ( r, revert ) {
        var rX = " rotateX(" + r.x + "deg) ",
            rY = " rotateY(" + r.y + "deg) ",
            rZ = " rotateZ(" + r.z + "deg) ";

        return revert ? rZ+rY+rX : rX+rY+rZ;
    };

    var scale = function ( s ) {
        return " scale(" + s + ") ";
    };

    var perspective = function ( p ) {
        return " perspective(" + p + "px) ";
    };

    var getElementFromUrl = function () {
        // get id from url # by removing `#` or `#/` from the beginning,
        // so both `#slide-id` and "legacy" `#/slide-id` will work
        return byId( window.location.hash.replace(/^#\/?/,"") );
    };

    // CHECK SUPPORT

    var ua = navigator.userAgent.toLowerCase();
    var impressSupported = ( pfx("perspective") != null ) &&
                           ( document.body.classList ) &&
                           ( document.body.dataset ) &&
                           ( ua.search(/(iphone)|(ipod)|(android)/) == -1 );

    var roots = {};

    var defaults = {
        width: 1024,
        height: 768,
        maxScale: 1,
        minScale: 0
    };

    var impress = window.impress = function ( rootId ) {

        rootId = rootId || "impress";

        // if already initialized just return the API
        if (roots["impress-root-" + rootId]) {
            return roots["impress-root-" + rootId];
        }

        // DOM ELEMENTS

        var root = byId( rootId );

        if (!impressSupported) {
            root.className = "impress-not-supported";
            return;
        } else {
            root.className = "";
        }

        // viewport updates for iPad
        var meta = $("meta[name='viewport']") || document.createElement("meta");
        // hardcoding these values looks pretty bad, as they kind of depend on the content
        // so they should be at least configurable
        meta.content = "width=device-width, minimum-scale=1, maximum-scale=1, user-scalable=no";
        if (meta.parentNode != document.head) {
            meta.name = 'viewport';
            document.head.appendChild(meta);
        }

        // initialize configuration object
        var rootData = root.dataset;
        var config = {
            width: toNumber(rootData.width,    defaults.width),
            height: toNumber(rootData.height,   defaults.height),
            maxScale: toNumber(rootData.maxScale, defaults.maxScale),
            minScale: toNumber(rootData.minScale, defaults.minScale)
        }

        var canvas = document.createElement("div");
        canvas.className = "canvas";

        arrayify( root.childNodes ).forEach(function ( el ) {
            canvas.appendChild( el );
        });
        root.appendChild(canvas);

        var steps = $$(".step", root);

        // SETUP
        // set initial values and defaults

        document.documentElement.style.height = "100%";

        css(document.body, {
            height: "100%",
            overflow: "hidden"
        });

        var props = {
            position: "absolute",
            transformOrigin: "top left",
            transition: "all 0s ease-in-out",
            transformStyle: "preserve-3d"
        }

        css(root, props);
        css(root, {
            top: "50%",
            left: "50%",
            transform: perspective(1000)
        });
        css(canvas, props);

        var current = {
            translate: { x: 0, y: 0, z: 0 },
            rotate:    { x: 0, y: 0, z: 0 },
            scale:     1
        };

        var stepData = {};

        var isStep = function ( el ) {
            return !!(el && el.id && stepData["impress-" + el.id]);
        };

        var computeWindowScale = function () {
            var hScale = window.innerHeight / config.height,
                wScale = window.innerWidth / config.width,
                scale = hScale > wScale ? wScale : hScale;

            if (config.maxScale && scale > config.maxScale) {
                scale = config.maxScale;
            }

            if (config.minScale && scale < config.minScale) {
                scale = config.minScale;
            }

            return scale;
        };

        steps.forEach(function ( el, idx ) {
            var data = el.dataset,
                step = {
                    translate: {
                        x: toNumber(data.x),
                        y: toNumber(data.y),
                        z: toNumber(data.z)
                    },
                    rotate: {
                        x: toNumber(data.rotateX),
                        y: toNumber(data.rotateY),
                        z: toNumber(data.rotateZ || data.rotate)
                    },
                    scale: toNumber(data.scale, 1),
                    el: el
                };

            if ( !el.id ) {
                el.id = "step-" + (idx + 1);
            }

            stepData["impress-" + el.id] = step;

            css(el, {
                position: "absolute",
                transform: "translate(-50%,-50%)" +
                           translate(step.translate) +
                           rotate(step.rotate) +
                           scale(step.scale),
                transformStyle: "preserve-3d"
            });

        });

        // making given step active

        var active = null;
        var hashTimeout = null;

        var windowScale = computeWindowScale();

        var goto = function ( el, force ) {
            if ( !isStep(el) || (el == active && !force) ) {
                // selected element is not defined as step or is already active
                return false;
            }

            // Sometimes it's possible to trigger focus on first link with some keyboard action.
            // Browser in such a case tries to scroll the page to make this element visible
            // (even that body overflow is set to hidden) and it breaks our careful positioning.
            //
            // So, as a lousy (and lazy) workaround we will make the page scroll back to the top
            // whenever slide is selected
            //
            // If you are reading this and know any better way to handle it, I'll be glad to hear about it!
            window.scrollTo(0, 0);

            var step = stepData["impress-" + el.id];

            if ( active ) {
                active.classList.remove("active");
            }
            el.classList.add("active");

            root.className = "step-" + el.id;

            // Setting fragment URL with `history.pushState`
            // and it has to be set after animation finishes, because in Chrome it
            // causes transtion being laggy
            // BUG: http://code.google.com/p/chromium/issues/detail?id=62820
            window.clearTimeout( hashTimeout );
            hashTimeout = window.setTimeout(function () {
                window.location.hash = "#/" + el.id;
            }, 1000);

            var target = {
                rotate: {
                    x: -step.rotate.x,
                    y: -step.rotate.y,
                    z: -step.rotate.z,
                },
                translate: {
                    x: -step.translate.x,
                    y: -step.translate.y,
                    z: -step.translate.z
                },
                scale: 1 / step.scale
            };

            // check if the transition is zooming in or not
            var zoomin = target.scale >= current.scale;

            // if presentation starts (nothing is active yet)
            // don't animate (set duration to 0)
            var duration = (active) ? "1s" : "0";

            if (force) {
                windowScale = computeWindowScale();
            }

            css(root, {
                // to keep the perspective look similar for different scales
                // we need to 'scale' the perspective, too
                transform: perspective( 1000 / (target.scale * windowScale) ) + scale(target.scale * windowScale),
                transitionDuration: duration,
                transitionDelay: (zoomin ? "500ms" : "0ms")
            });

            css(canvas, {
                transform: rotate(target.rotate, true) + translate(target.translate),
                transitionDuration: duration,
                transitionDelay: (zoomin ? "0ms" : "500ms")
            });

            current = target;
            active = el;

            return el;
        };

        var prev = function () {
            var prev = steps.indexOf( active ) - 1;
            prev = prev >= 0 ? steps[ prev ] : steps[ steps.length-1 ];

            return goto(prev);
        };

        var next = function () {
            var next = steps.indexOf( active ) + 1;
            next = next < steps.length ? steps[ next ] : steps[ 0 ];

            return goto(next);
        };

        window.addEventListener("hashchange", function () {
            goto( getElementFromUrl() );
        }, false);

        window.addEventListener("orientationchange", function () {
            window.scrollTo(0, 0);
        }, false);

        // START
        // by selecting step defined in url or first step of the presentation
        goto(getElementFromUrl() || steps[0]);

        return (roots[ "impress-root-" + rootId ] = {
            goto: goto,
            next: next,
            prev: prev
        });

    }
})(document, window);

// EVENTS

(function ( document, window ) {
    'use strict';

    // throttling function calls, by Remy Sharp
    // http://remysharp.com/2010/07/21/throttling-function-calls/
    var throttle = function (fn, delay) {
        var timer = null;
        return function () {
            var context = this, args = arguments;
            clearTimeout(timer);
            timer = setTimeout(function () {
                fn.apply(context, args);
            }, delay);
        };
    };

    // keyboard navigation handlers

    // prevent default keydown action when one of supported key is pressed
    document.addEventListener("keydown", function ( event ) {
        if ( event.keyCode == 9 || ( event.keyCode >= 32 && event.keyCode <= 34 ) || (event.keyCode >= 37 && event.keyCode <= 40) ) {
            event.preventDefault();
        }
    }, false);

    // trigger impress action on keyup
    document.addEventListener("keyup", function ( event ) {
        if ( event.keyCode == 9 || ( event.keyCode >= 32 && event.keyCode <= 34 ) || (event.keyCode >= 37 && event.keyCode <= 40) ) {
            switch( event.keyCode ) {
                case 33: ; // pg up
                case 37: ; // left
                case 38:   // up
                         impress().prev();
                         break;
                case 9:  ; // tab
                case 32: ; // space
                case 34: ; // pg down
                case 39: ; // right
                case 40:   // down
                         impress().next();
                         break;
            }

            event.preventDefault();
        }
    }, false);

    // delegated handler for clicking on the links to presentation steps
    document.addEventListener("click", function ( event ) {
        // event delegation with "bubbling"
        // check if event target (or any of its parents is a link)
        var target = event.target;
        while ( (target.tagName != "A") &&
                (target != document.documentElement) ) {
            target = target.parentNode;
        }

        if ( target.tagName == "A" ) {
            var href = target.getAttribute("href");

            // if it's a link to presentation step, target this step
            if ( href && href[0] == '#' ) {
                target = document.getElementById( href.slice(1) );
            }
        }

        if ( impress().goto(target) ) {
            event.stopImmediatePropagation();
            event.preventDefault();
        }
    }, false);

    // delegated handler for clicking on step elements
    document.addEventListener("click", function ( event ) {
        var target = event.target;
        // find closest step element
        while ( !target.classList.contains("step") &&
                (target != document.documentElement) ) {
            target = target.parentNode;
        }

        if ( impress().goto(target) ) {
            event.preventDefault();
        }
    }, false);

    // touch handler to detect taps on the left and right side of the screen
    document.addEventListener("touchstart", function ( event ) {
        if (event.touches.length === 1) {
            var x = event.touches[0].clientX,
                width = window.innerWidth * 0.3,
                result = null;

            if ( x < width ) {
                result = impress().prev();
            } else if ( x > window.innerWidth - width ) {
                result = impress().next();
            }

            if (result) {
                event.preventDefault();
            }
        }
    }, false);

    // rescale presentation when window is resized
    window.addEventListener("resize", throttle(function (event) {
        // force going to active step again, to trigger rescaling
        impress().goto( document.querySelector(".active"), true );
    }, 250), false);
})(document, window);

<|endoftext|>


<commit_before>import * as url from "url";

export function getBlob(node) {
  var data = node.value.data || "";
  if (typeof data === "object") data = JSON.stringify(data);
  var buf = new Buffer(data, node.value.encoding || "utf8");
  var blob = new Blob([buf], { type: node.value.type });
  return blob;
}

export function getPromiseForRequest(node) {
  if (node.value.src) {
    var src = url.resolve(node.base || "", node.value.src);
    return Promise.resolve({ url: src });
  }

  return new Promise(function (resolve) {
    var blob = getBlob(node);
    var fileReader = new FileReader();

    fileReader.onloadend = function (evt) {
      resolve({ url: evt.target.result });
    };

    fileReader.readAsDataURL(blob);
  });
}
<commit_msg>Preserve Base URI for Data Content<commit_after>import * as url from "url";

export function getBlob(node) {
  var data = node.value.data || "";

  if (typeof data === "object") {
    if (node.value.type.indexOf("application/lynx+json") > -1) {
      data.base = data.base || node.base;
    }

    data = JSON.stringify(data);
  }

  var buf = new Buffer(data, node.value.encoding || "utf8");
  var blob = new Blob([buf], { type: node.value.type });

  return blob;
}

export function getPromiseForRequest(node) {
  if (node.value.src) {
    var src = url.resolve(node.base || "", node.value.src);
    return Promise.resolve({ url: src });
  }

  return new Promise(function (resolve) {
    var blob = getBlob(node);
    var fileReader = new FileReader();

    fileReader.onloadend = function (evt) {
      resolve({ url: evt.target.result });
    };

    fileReader.readAsDataURL(blob);
  });
}
<|endoftext|>


<commit_before>import { socketClient } from '../store';

import {
    IO_EMIT_SETUP,
    IO_EMIT_SUCCESS,
    IO_EMIT_FAILURE,
    IO_ON_SETUP,
    IO_ON_SUCCESS,
    IO_ON_FAILURE,

    SRV_CONNECT_RECEIVED,
    SRV_DISCONNECT_RECEIVED,
    SRV_INFO_RECEIVED,
} from './actionTypes';

export function srvConnect(){
    return (dispatch)=>{
        return socketClient.connect()
            .then(()=>{
                dispatch(waitforDisconnectReception(dispatch));
                dispatch(srvConnectionReceived());
                dispatch(srvGetServerInfo());
            });
    }
}

function tryReconnect(){
    return (dispatch)=>{
        setTimeout(()=>{
            return socketClient.reconnect()
                .then(()=>{
                    dispatch(srvConnectionReceived());
                })
                .catch(()=>dispatch(tryReconnect()));
        }, 500);
    }
}

function waitforDisconnectReception(dispatch){
    return {
        type: 'socket',
        types: [IO_ON_SETUP, IO_ON_SUCCESS, IO_ON_FAILURE],
        promise: (socket) => {
            return socket.on('disconnect', ()=>{
                dispatch(srvDisconnectReceived());
                dispatch(tryReconnect());
            });
        }
    }
}

function srvConnectionReceived(){
    return {
        type: SRV_CONNECT_RECEIVED
    }
}

function srvDisconnectReceived(){
    return {
        type: SRV_DISCONNECT_RECEIVED
    }
}

export function srvGetServerInfo(){
    return (dispatch)=>{
        dispatch(waitforInfoReception(dispatch));
        dispatch(emitInfoRequest());
    }
}

function waitforInfoReception(dispatch){
    return {
        type: 'socket',
        types: [IO_ON_SETUP, IO_ON_SUCCESS, IO_ON_FAILURE],
        promise: (socket) => {
            socket.off('server.info.ready');
            return socket.on('server.info.ready', (recd)=>{
                dispatch(srvInfoReceived(recd));
            });
        }
    }
}

function emitInfoRequest(){
    return {
        type: 'socket',
        types: [IO_EMIT_SETUP, IO_EMIT_SUCCESS, IO_EMIT_FAILURE],
        promise: (socket) => {
            return socket.emit('server.info.request');
        }
    }
}

function srvInfoReceived(serverInfo){
    return {
        type: SRV_INFO_RECEIVED,
        serverInfo
    }
}<commit_msg>Changed the reconnection to check every 200 ms.<commit_after>import { socketClient } from '../store';

import {
    IO_EMIT_SETUP,
    IO_EMIT_SUCCESS,
    IO_EMIT_FAILURE,
    IO_ON_SETUP,
    IO_ON_SUCCESS,
    IO_ON_FAILURE,

    SRV_CONNECT_RECEIVED,
    SRV_DISCONNECT_RECEIVED,
    SRV_INFO_RECEIVED,
} from './actionTypes';

export function srvConnect(){
    return (dispatch)=>{
        return socketClient.connect()
            .then(()=>{
                dispatch(waitforDisconnectReception(dispatch));
                dispatch(srvConnectionReceived());
                dispatch(srvGetServerInfo());
            });
    }
}

function tryReconnect(){
    return (dispatch)=>{
        setTimeout(()=>{
            return socketClient.reconnect()
                .then(()=>{
                    dispatch(srvConnectionReceived());
                })
                .catch(()=>dispatch(tryReconnect()));
        }, 200);
    }
}

function waitforDisconnectReception(dispatch){
    return {
        type: 'socket',
        types: [IO_ON_SETUP, IO_ON_SUCCESS, IO_ON_FAILURE],
        promise: (socket) => {
            return socket.on('disconnect', ()=>{
                dispatch(srvDisconnectReceived());
                dispatch(tryReconnect());
            });
        }
    }
}

function srvConnectionReceived(){
    return {
        type: SRV_CONNECT_RECEIVED
    }
}

function srvDisconnectReceived(){
    return {
        type: SRV_DISCONNECT_RECEIVED
    }
}

export function srvGetServerInfo(){
    return (dispatch)=>{
        dispatch(waitforInfoReception(dispatch));
        dispatch(emitInfoRequest());
    }
}

function waitforInfoReception(dispatch){
    return {
        type: 'socket',
        types: [IO_ON_SETUP, IO_ON_SUCCESS, IO_ON_FAILURE],
        promise: (socket) => {
            socket.off('server.info.ready');
            return socket.on('server.info.ready', (recd)=>{
                dispatch(srvInfoReceived(recd));
            });
        }
    }
}

function emitInfoRequest(){
    return {
        type: 'socket',
        types: [IO_EMIT_SETUP, IO_EMIT_SUCCESS, IO_EMIT_FAILURE],
        promise: (socket) => {
            return socket.emit('server.info.request');
        }
    }
}

function srvInfoReceived(serverInfo){
    return {
        type: SRV_INFO_RECEIVED,
        serverInfo
    }
}<|endoftext|>


<commit_before>let EventEmitter = require('events');
//module.exports = function() {
console.log('module was called')
let i18next = require('i18next'),
  _ = require('lodash');

const ERROR_LEVEL_FATAL = 'fatal',
  ERROR_LEVEL_ERROR = 'error',
  ERROR_LEVEL_WARN = 'warn',
  ERROR_LEVEL_INFO = 'info',
  ERROR_LEVEL_DEBUG = 'debug',
  ERROR_LEVEL_TRACE = 'trace';

const DEFAULT_ERROR_MESSAGE = "Internal server error!",
  DEFAULT_ERROR_LOCALE = "server.500.generic";

i18next.init({
  lng: "en-US",
  nsSeparator: false,
  //keySeparator: false,
  //load:['en-US', 'fr', 'es'],
  //fallbackLng: 'en-US',
  //backend: {
  //  loadPath: '/language/static/{{lng}}/{{ns}}.json'
  //},
  resources: {
    en: {
      translation: { // did a lot of searching, still unsure how this works
        // probably have to load JSON file here
        "server" : {
          "400" : {
            "notFound" : "this is how it's done",
            "forbidden" : "this one works too"
          }
        }
        // keySeparator must be set to false else 'server.400' is not recognized with '.'
      }
    }
  }
}//, (err, t) => {
  //const hw = i18next.t('key'); // hw = 'hello world'
//}
)

console.log(i18next.t('server.400.forbidden'))
console.log(i18next.t('server.400.notFound'))

class RichError{
  constructor(err, options, locale) {
    //initialize logger
    // move constants here
    console.log('RE constructor was called')
    this.build(err, options, locale)
  };

  build(err, options = {}, locale) {
    console.log('build was called') //temp
    let self = this;
    if(err === undefined) {
      if (options.internalMessage !== undefined) {
        console.log(options.internalMessage)
        return 3 // TODO find out what happens as a result of returning 3
      };
      return undefined
    } else {
      if (err instanceof RichError) {
        self.set(err.toObject());
      } else {
        if (err instanceof Error) {
          self.set(this.buildFromSystemError(err, options));
        } else if(typeof err === 'string' || err instanceof String) {
          if (i18next && i18next.exists(err)) {
            self.set(this.buildFromLocale(locale, options));// sent err before but buildFromLocale had locale as parameter
          } else {
            self.set(this.buildFromString(err, options));
          }
        } else {
          self.set(err);
        }
      }
    }
    return this;
  };
  buildFromSystemError(err = new Error(DEFAULT_ERROR_MESSAGE), options = {}) { // 'Internal server error!'
    console.log('buildFromSystemError was called') //temp
    let richErrorObject = {};
    richErrorObject.error = err;
    richErrorObject.error.code = (err.code) ? err.code.toLowerCase() : undefined;
    richErrorObject.internalOnly = (options.internalOnly === true) ? true : false;
    richErrorObject.internalMessage = options.internalMessage || undefined;
    richErrorObject.level = options.level || ERROR_LEVEL_ERROR; // 'error'
    richErrorObject.messageData = options.messageData || undefined;
    richErrorObject.options = options;
    richErrorObject.referenceData = options.referenceData || undefined;
    richErrorObject.statusCode = options.statusCode || 500;
    return richErrorObject;
  };

  buildFromLocale(locale = DEFAULT_ERROR_LOCALE, options = {}) { // 'server.500.generic'
    console.log('buildFromLocale was called') //temp
    let richErrorObject = {};
    richErrorObject.error = new Error(i18next.t(locale, options.i18next));
    richErrorObject.error.code = locale.toLowerCase();
    richErrorObject.internalOnly = (options.internalOnly === true) ? true : false;
    richErrorObject.internalMessage = options.internalMessage || undefined;
    richErrorObject.level = options.level || ERROR_LEVEL_ERROR; // 'error'
    richErrorObject.messageData = options.i18next;
    richErrorObject.options = options;
    richErrorObject.referenceData = options.referenceData || undefined;
    richErrorObject.statusCode = options.statusCode || this.guessStatusCodeOfLocale(locale);
    return richErrorObject;
  };

  buildFromString(errorString = DEFAULT_ERROR_MESSAGE, options = {}) { // 'Internal server error!'
    console.log('buildFromString was called') //temp
    let richErrorObject = {};
    richErrorObject.error = new Error(errorString);
    richErrorObject.error.code = (options.code) ? options.code.toLowerCase() : undefined;
    richErrorObject.internalOnly = (options.internalOnly === true) ? true : false;
    richErrorObject.internalMessage = options.internalMessage || undefined;
    richErrorObject.level = options.level || ERROR_LEVEL_ERROR; // 'error'
    richErrorObject.messageData = options.messageData || undefined;
    richErrorObject.options = options;
    richErrorObject.referenceData = options.referenceData || undefined;
    richErrorObject.statusCode = options.statusCode || 500;
    return richErrorObject;
  };

  get(key) {
    switch (key) {
      case "code":
      case "stack":
        return (this.error) ? this.error[key] : undefined;
      default:
        return this[key];
    }
  };

  guessStatusCodeOfLocale(locale) {
    console.log("guessStatusCodeOfLocale") //temp
    switch (locale) {
    //case "server.400.badRequest":
      //  return 400;
      case "server.400.forbidden":
        return 403;
      case "server.400.notFound":
        return 404;
      case "server.400.unauthorized":
        return 401;
      default:
        let categories = locale.split(".");
        if (categories.length != 0) {
          if (categories[0] == "server") {
            return Number(categories[1]);
          }
        }

        return 500;
    }
  };

  set(richErrorObject) {
    console.log('set was called') //temp
    // Node.js error object.  Contains two important child attributes "code" and "stack".
    if(richErrorObject.error instanceof Error) {
      this.error = richErrorObject.error;
    } else if(richErrorObject.error !== null && typeof richErrorObject.error === 'object') {
      this.error = new Error(richErrorObject.error.message);
      this.error.code = richErrorObject.error.code;
      this.error.stack = richErrorObject.error.stack;
    }

    // When true, the error should not be shown to an external client.
    this.internalOnly = richErrorObject.internalOnly;

    // An additional message to be displayed internally only.
    this.internalMessage = richErrorObject.internalMessage;

    // The error level, e.g. fatal, error, warn, info, debug, trace.
    this.level = richErrorObject.level;

    // Data that was used to create the error message, usually by i18next.
    this.messageData = richErrorObject.messageData;

    // The options used to create the Rich Error.
    this.options = richErrorObject.options;

    // Data that may have caused or is related to the error.
    this.referenceData = richErrorObject.referenceData;

    // HTTP status code associated with the error.
    this.statusCode = richErrorObject.statusCode;

    return this;
  };
}
//  return RichError
//};
module.exports = RichError

var inherits = require('util').inherits;  <commit_msg>moved toObject<commit_after>let EventEmitter = require('events');
//module.exports = function() {
console.log('module was called')
let i18next = require('i18next'),
  _ = require('lodash');

const ERROR_LEVEL_FATAL = 'fatal',
  ERROR_LEVEL_ERROR = 'error',
  ERROR_LEVEL_WARN = 'warn',
  ERROR_LEVEL_INFO = 'info',
  ERROR_LEVEL_DEBUG = 'debug',
  ERROR_LEVEL_TRACE = 'trace';

const DEFAULT_ERROR_MESSAGE = "Internal server error!",
  DEFAULT_ERROR_LOCALE = "server.500.generic";

i18next.init({
  lng: "en-US",
  nsSeparator: false,
  //keySeparator: false,
  //load:['en-US', 'fr', 'es'],
  //fallbackLng: 'en-US',
  //backend: {
  //  loadPath: '/language/static/{{lng}}/{{ns}}.json'
  //},
  resources: {
    en: {
      translation: { // did a lot of searching, still unsure how this works
        // probably have to load JSON file here
        "server" : {
          "400" : {
            "notFound" : "this is how it's done",
            "forbidden" : "this one works too"
          }
        }
        // keySeparator must be set to false else 'server.400' is not recognized with '.'
      }
    }
  }
}//, (err, t) => {
  //const hw = i18next.t('key'); // hw = 'hello world'
//}
)

//console.log(i18next.t('server.400.forbidden'))
//console.log(i18next.t('server.400.notFound'))

class RichError{
  constructor(err, options, locale) {
    let i18next = require('i18next')
    //initialize logger
    // move constants here
    console.log('RE constructor was called')
    this.build(err, options, locale)
  };

  build(err, options = {}, locale) {
    console.log('build was called') //temp
    let self = this;
    if(err === undefined) {
      if (options.internalMessage !== undefined) {
        console.log(options.internalMessage)
        return 3 // TODO find out what happens as a result of returning 3
      };
      return undefined
    } else {
      if (err instanceof RichError) {
        self.set(err.toObject(err));
      } else {
        if (err instanceof Error) {
          self.set(this.buildFromSystemError(err, options));
        } else if(typeof err === 'string' || err instanceof String) {
          if (i18next && i18next.exists(err)) {
            self.set(this.buildFromLocale(locale, options));// sent err before but buildFromLocale had locale as parameter
          } else {
            self.set(this.buildFromString(err, options));
          }
        } else {
          self.set(err);
        }
      }
    }
    return this;
  };
  buildFromSystemError(err = new Error(DEFAULT_ERROR_MESSAGE), options = {}) { // 'Internal server error!'
    console.log('buildFromSystemError was called') //temp
    let richErrorObject = {};
    richErrorObject.error = err;
    richErrorObject.error.code = (err.code) ? err.code.toLowerCase() : undefined;
    richErrorObject.internalOnly = (options.internalOnly === true) ? true : false;
    richErrorObject.internalMessage = options.internalMessage || undefined;
    richErrorObject.level = options.level || ERROR_LEVEL_ERROR; // 'error'
    richErrorObject.messageData = options.messageData || undefined;
    richErrorObject.options = options;
    richErrorObject.referenceData = options.referenceData || undefined;
    richErrorObject.statusCode = options.statusCode || 500;
    return richErrorObject;
  };

  buildFromLocale(locale = DEFAULT_ERROR_LOCALE, options = {}) { // 'server.500.generic'
    console.log('buildFromLocale was called') //temp
    let richErrorObject = {};
    richErrorObject.error = new Error(i18next.t(locale, options.i18next));
    richErrorObject.error.code = locale.toLowerCase();
    richErrorObject.internalOnly = (options.internalOnly === true) ? true : false;
    richErrorObject.internalMessage = options.internalMessage || undefined;
    richErrorObject.level = options.level || ERROR_LEVEL_ERROR; // 'error'
    richErrorObject.messageData = options.i18next;
    richErrorObject.options = options;
    richErrorObject.referenceData = options.referenceData || undefined;
    richErrorObject.statusCode = options.statusCode || this.guessStatusCodeOfLocale(locale);
    return richErrorObject;
  };

  buildFromString(errorString = DEFAULT_ERROR_MESSAGE, options = {}) { // 'Internal server error!'
    console.log('buildFromString was called') //temp
    let richErrorObject = {};
    richErrorObject.error = new Error(errorString);
    richErrorObject.error.code = (options.code) ? options.code.toLowerCase() : undefined;
    richErrorObject.internalOnly = (options.internalOnly === true) ? true : false;
    richErrorObject.internalMessage = options.internalMessage || undefined;
    richErrorObject.level = options.level || ERROR_LEVEL_ERROR; // 'error'
    richErrorObject.messageData = options.messageData || undefined;
    richErrorObject.options = options;
    richErrorObject.referenceData = options.referenceData || undefined;
    richErrorObject.statusCode = options.statusCode || 500;
    return richErrorObject;
  };

  get(key) {
    switch (key) {
      case "code":
      case "stack":
        return (this.error) ? this.error[key] : undefined;
      default:
        return this[key];
    }
  };

  guessStatusCodeOfLocale(locale) {
    console.log("guessStatusCodeOfLocale") //temp
    switch (locale) {
    //case "server.400.badRequest":
      //  return 400;
      case "server.400.forbidden":
        return 403;
      case "server.400.notFound":
        return 404;
      case "server.400.unauthorized":
        return 401;
      case undefined:
        return 500; //find out what happens as a result of this
      default:
        let categories = locale.split(".");
        if (categories.length != 0) {
          if (categories[0] == "server") {
            return Number(categories[1]);
          }
        }

        return 500;
    }
  };

  set(richErrorObject) {
    console.log('set was called') //temp
    // Node.js error object.  Contains two important child attributes "code" and "stack".
    if(richErrorObject.error instanceof Error) {
      this.error = richErrorObject.error;
    } else if(richErrorObject.error !== null && typeof richErrorObject.error === 'object') {
      this.error = new Error(richErrorObject.error.message);
      this.error.code = richErrorObject.error.code;
      this.error.stack = richErrorObject.error.stack;
    }

    // When true, the error should not be shown to an external client.
    this.internalOnly = richErrorObject.internalOnly;

    // An additional message to be displayed internally only.
    this.internalMessage = richErrorObject.internalMessage;

    // The error level, e.g. fatal, error, warn, info, debug, trace.
    this.level = richErrorObject.level;

    // Data that was used to create the error message, usually by i18next.
    this.messageData = richErrorObject.messageData;

    // The options used to create the Rich Error.
    this.options = richErrorObject.options;

    // Data that may have caused or is related to the error.
    this.referenceData = richErrorObject.referenceData;

    // HTTP status code associated with the error.
    this.statusCode = richErrorObject.statusCode;

    return this;
  };

  toObject(remie) {
    console.log('toObject was called') // temp
    let self = remie
    return { //possibly need to restructure to work when one or more values is not given
      error: {
        code: self.error.code,
        message: self.error.message,
        stack: self.error.stack
      },
      internalOnly: self.internalOnly,
      internalMessage: self.internalMessage,
      level: self.level,
      messageData: self.messageData,
      options: self.options,
      referenceData: self.referenceData,
      statusCode: self.statusCode
    };
  };
};
//  return RichError
//};
module.exports = RichError

var inherits = require('util').inherits;  <|endoftext|>


<commit_before>let EventEmitter = require('events');
//module.exports = function() {
console.log('module was called')
let i18next = require('i18next'),
  _ = require('lodash');

  const ERROR_LEVEL_FATAL = 'fatal',
    ERROR_LEVEL_ERROR = 'error',
    ERROR_LEVEL_WARN = 'warn',
    ERROR_LEVEL_INFO = 'info',
    ERROR_LEVEL_DEBUG = 'debug',
    ERROR_LEVEL_TRACE = 'trace';

  const DEFAULT_ERROR_MESSAGE = "Internal server error!",
    DEFAULT_ERROR_LOCALE = "server.500.generic";

class RichError{
  constructor(err, options, i18next, locale) {
    console.log('RE constructor was called')
    this.build(err, options, locale)
  };

  build(err, options = {}, locale) {
    console.log('build was called') //temp
    let self = this;
    if(err === undefined) {
      if (options.internalMessage !== undefined) {
        console.log(options.internalMessage)
      };
      return undefined
    } else {
      if (err instanceof RichError) {
        self.set(err.toObject());
      } else {
        if (err instanceof Error) {
          self.set(this.buildFromSystemError(err, options));
        } else if(typeof err === 'string' || err instanceof String) {
          if (i18next && i18next.exists(err)) {
            self.set(this.buildFromLocale(locale, options));// sent err before but buildFromLocale had locale as parameter
          } else {
            self.set(this.buildFromString(err, options));
          }
        } else {
          self.set(err);
        }
      }
    }
    console.log(this)
    return this;
  };
  buildFromSystemError(err = new Error(DEFAULT_ERROR_MESSAGE), options = {}) { // 'Internal server error!'
    console.log('buildFromSystemError was called') //temp
    let richErrorObject = {};
    richErrorObject.error = err;
    richErrorObject.error.code = (err.code) ? err.code.toLowerCase() : undefined;
    richErrorObject.internalOnly = (options.internalOnly === true) ? true : false;
    richErrorObject.internalMessage = options.internalMessage || undefined;
    richErrorObject.level = options.level || ERROR_LEVEL_ERROR; // 'error'
    richErrorObject.messageData = options.messageData || undefined;
    richErrorObject.options = options;
    richErrorObject.referenceData = options.referenceData || undefined;
    richErrorObject.statusCode = options.statusCode || 500;
    return richErrorObject;
  };

  buildFromLocale(locale = DEFAULT_ERROR_LOCALE, options = {}) { // 'server.500.generic'
    console.log('buildFromLocale was called') //temp
    let richErrorObject = {};
    richErrorObject.error = new Error(i18next.t(locale, options.i18next));
    richErrorObject.error.code = locale.toLowerCase();
    richErrorObject.internalOnly = (options.internalOnly === true) ? true : false;
    richErrorObject.internalMessage = options.internalMessage || undefined;
    richErrorObject.level = options.level || ERROR_LEVEL_ERROR; // 'error'
    richErrorObject.messageData = options.i18next;
    richErrorObject.options = options;
    richErrorObject.referenceData = options.referenceData || undefined;
    richErrorObject.statusCode = options.statusCode || this.guessStatusCodeOfLocale(locale);
    return richErrorObject;
  };

  buildFromString(errorString = DEFAULT_ERROR_MESSAGE, options = {}) { // 'Internal server error!'
    console.log('buildFromString was called') //temp
    let richErrorObject = {};
    richErrorObject.error = new Error(errorString);
    richErrorObject.error.code = (options.code) ? options.code.toLowerCase() : undefined;
    richErrorObject.internalOnly = (options.internalOnly === true) ? true : false;
    richErrorObject.internalMessage = options.internalMessage || undefined;
    richErrorObject.level = options.level || ERROR_LEVEL_ERROR; // 'error'
    richErrorObject.messageData = options.messageData || undefined;
    richErrorObject.options = options;
    richErrorObject.referenceData = options.referenceData || undefined;
    richErrorObject.statusCode = options.statusCode || 500;
    return richErrorObject;
  };

  get(key) {
    switch (key) {
      case "code":
      case "stack":
        return (this.error) ? this.error[key] : undefined;
      default:
        return this[key];
    }
  };

  guessStatusCodeOfLocale(locale) {
    console.log("guessStatusCodeOfLocale") //temp
    switch (locale) {
    //case "server.400.badRequest":
      //  return 400;
      case "server.400.forbidden":
        return 403;
      case "server.400.notFound":
        return 404;
      case "server.400.unauthorized":
        return 401;
      default:
        let categories = locale.split(".");
        if (categories.length != 0) {
          if (categories[0] == "server") {
            return Number(categories[1]);
          }
        }

        return 500;
    }
  };

  set(richErrorObject) {
    console.log('set was called') //temp
    // Node.js error object.  Contains two important child attributes "code" and "stack".
    if(richErrorObject.error instanceof Error) {
      this.error = richErrorObject.error;
    } else if(richErrorObject.error !== null && typeof richErrorObject.error === 'object') {
      this.error = new Error(richErrorObject.error.message);
      this.error.code = richErrorObject.error.code;
      this.error.stack = richErrorObject.error.stack;
    }
    console.log(this.error)

    // When true, the error should not be shown to an external client.
    this.internalOnly = richErrorObject.internalOnly;

    // An additional message to be displayed internally only.
    this.internalMessage = richErrorObject.internalMessage;

    // The error level, e.g. fatal, error, warn, info, debug, trace.
    this.level = richErrorObject.level;

    // Data that was used to create the error message, usually by i18next.
    this.messageData = richErrorObject.messageData;

    // The options used to create the Rich Error.
    this.options = richErrorObject.options;

    // Data that may have caused or is related to the error.
    this.referenceData = richErrorObject.referenceData;

    // HTTP status code associated with the error.
    this.statusCode = richErrorObject.statusCode;

    return this;
  };
}
//  return RichError
//};
module.exports = RichError

var inherits = require('util').inherits;  <commit_msg>removed unnecessary console.log<commit_after>let EventEmitter = require('events');
//module.exports = function() {
console.log('module was called')
let i18next = require('i18next'),
  _ = require('lodash');

  const ERROR_LEVEL_FATAL = 'fatal',
    ERROR_LEVEL_ERROR = 'error',
    ERROR_LEVEL_WARN = 'warn',
    ERROR_LEVEL_INFO = 'info',
    ERROR_LEVEL_DEBUG = 'debug',
    ERROR_LEVEL_TRACE = 'trace';

  const DEFAULT_ERROR_MESSAGE = "Internal server error!",
    DEFAULT_ERROR_LOCALE = "server.500.generic";

class RichError{
  constructor(err, options, locale) {
    console.log('RE constructor was called')
    this.build(err, options, locale)
  };

  build(err, options = {}, locale) {
    console.log('build was called') //temp
    let self = this;
    if(err === undefined) {
      if (options.internalMessage !== undefined) {
        console.log(options.internalMessage)
      };
      return undefined
    } else {
      if (err instanceof RichError) {
        self.set(err.toObject());
      } else {
        if (err instanceof Error) {
          self.set(this.buildFromSystemError(err, options));
        } else if(typeof err === 'string' || err instanceof String) {
          if (i18next && i18next.exists(err)) {
            self.set(this.buildFromLocale(locale, options));// sent err before but buildFromLocale had locale as parameter
          } else {
            self.set(this.buildFromString(err, options));
          }
        } else {
          self.set(err);
        }
      }
    }
    return this;
  };
  buildFromSystemError(err = new Error(DEFAULT_ERROR_MESSAGE), options = {}) { // 'Internal server error!'
    console.log('buildFromSystemError was called') //temp
    let richErrorObject = {};
    richErrorObject.error = err;
    richErrorObject.error.code = (err.code) ? err.code.toLowerCase() : undefined;
    richErrorObject.internalOnly = (options.internalOnly === true) ? true : false;
    richErrorObject.internalMessage = options.internalMessage || undefined;
    richErrorObject.level = options.level || ERROR_LEVEL_ERROR; // 'error'
    richErrorObject.messageData = options.messageData || undefined;
    richErrorObject.options = options;
    richErrorObject.referenceData = options.referenceData || undefined;
    richErrorObject.statusCode = options.statusCode || 500;
    return richErrorObject;
  };

  buildFromLocale(locale = DEFAULT_ERROR_LOCALE, options = {}) { // 'server.500.generic'
    console.log('buildFromLocale was called') //temp
    let richErrorObject = {};
    richErrorObject.error = new Error(i18next.t(locale, options.i18next));
    richErrorObject.error.code = locale.toLowerCase();
    richErrorObject.internalOnly = (options.internalOnly === true) ? true : false;
    richErrorObject.internalMessage = options.internalMessage || undefined;
    richErrorObject.level = options.level || ERROR_LEVEL_ERROR; // 'error'
    richErrorObject.messageData = options.i18next;
    richErrorObject.options = options;
    richErrorObject.referenceData = options.referenceData || undefined;
    richErrorObject.statusCode = options.statusCode || this.guessStatusCodeOfLocale(locale);
    return richErrorObject;
  };

  buildFromString(errorString = DEFAULT_ERROR_MESSAGE, options = {}) { // 'Internal server error!'
    console.log('buildFromString was called') //temp
    let richErrorObject = {};
    richErrorObject.error = new Error(errorString);
    richErrorObject.error.code = (options.code) ? options.code.toLowerCase() : undefined;
    richErrorObject.internalOnly = (options.internalOnly === true) ? true : false;
    richErrorObject.internalMessage = options.internalMessage || undefined;
    richErrorObject.level = options.level || ERROR_LEVEL_ERROR; // 'error'
    richErrorObject.messageData = options.messageData || undefined;
    richErrorObject.options = options;
    richErrorObject.referenceData = options.referenceData || undefined;
    richErrorObject.statusCode = options.statusCode || 500;
    return richErrorObject;
  };

  get(key) {
    switch (key) {
      case "code":
      case "stack":
        return (this.error) ? this.error[key] : undefined;
      default:
        return this[key];
    }
  };

  guessStatusCodeOfLocale(locale) {
    console.log("guessStatusCodeOfLocale") //temp
    switch (locale) {
    //case "server.400.badRequest":
      //  return 400;
      case "server.400.forbidden":
        return 403;
      case "server.400.notFound":
        return 404;
      case "server.400.unauthorized":
        return 401;
      default:
        let categories = locale.split(".");
        if (categories.length != 0) {
          if (categories[0] == "server") {
            return Number(categories[1]);
          }
        }

        return 500;
    }
  };

  set(richErrorObject) {
    console.log('set was called') //temp
    // Node.js error object.  Contains two important child attributes "code" and "stack".
    if(richErrorObject.error instanceof Error) {
      this.error = richErrorObject.error;
    } else if(richErrorObject.error !== null && typeof richErrorObject.error === 'object') {
      this.error = new Error(richErrorObject.error.message);
      this.error.code = richErrorObject.error.code;
      this.error.stack = richErrorObject.error.stack;
    }

    // When true, the error should not be shown to an external client.
    this.internalOnly = richErrorObject.internalOnly;

    // An additional message to be displayed internally only.
    this.internalMessage = richErrorObject.internalMessage;

    // The error level, e.g. fatal, error, warn, info, debug, trace.
    this.level = richErrorObject.level;

    // Data that was used to create the error message, usually by i18next.
    this.messageData = richErrorObject.messageData;

    // The options used to create the Rich Error.
    this.options = richErrorObject.options;

    // Data that may have caused or is related to the error.
    this.referenceData = richErrorObject.referenceData;

    // HTTP status code associated with the error.
    this.statusCode = richErrorObject.statusCode;

    return this;
  };
}
//  return RichError
//};
module.exports = RichError

var inherits = require('util').inherits;  <|endoftext|>


<commit_before>#!/usr/bin/env node

/*
  The MIT License (MIT)

  Copyright (c) 2007-2013 Einar Lielmanis and contributors.

  Permission is hereby granted, free of charge, to any person
  obtaining a copy of this software and associated documentation files
  (the "Software"), to deal in the Software without restriction,
  including without limitation the rights to use, copy, modify, merge,
  publish, distribute, sublicense, and/or sell copies of the Software,
  and to permit persons to whom the Software is furnished to do so,
  subject to the following conditions:

  The above copyright notice and this permission notice shall be
  included in all copies or substantial portions of the Software.

  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
  BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
  ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
  CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  SOFTWARE.

  Js-Beautify Command-line for node.js
  -------------------------------------

  Written by Daniel Stockman (daniel.stockman@gmail.com)

*/

var debug = process.env.DEBUG_JSBEAUTIFY || process.env.JSBEAUTIFY_DEBUG
    ? function () { console.error.apply(console, arguments); }
    : function () {};

var fs = require('fs'),
    cc = require('config-chain'),
    beautify = require('../index'),
    nopt = require('nopt'),
    path = require('path'),
    knownOpts = {
        // Beautifier
        "indent_size": Number,
        "indent_char": String,
        "indent_level": Number,
        "indent_with_tabs": Boolean,
        "preserve_newlines": Boolean,
        "max_preserve_newlines": Number,
        "jslint_happy": Boolean,
        "brace_style": ["collapse", "expand", "end-expand", "expand-strict"],
        "break_chained_methods": Boolean,
        "keep_array_indentation": Boolean,
        "unescape_strings": Boolean,
        "wrap_line_length": Number,
        // HTML-only
        "max_char": Number,
        "unformatted": [String, Array],
        "indent_scripts": ["keep", "separate", "normal"],
        // CLI
        "version": Boolean,
        "help": Boolean,
        "files": [path, Array],
        "outfile": path,
        "replace": Boolean,
        "quiet": Boolean,
        "type": ["js", "css", "html"],
        "config": path
    },
    // dasherizeShorthands provides { "indent-size": ["--indent_size"] }
    // translation, allowing more convenient dashes in CLI arguments
    shortHands = dasherizeShorthands({
        // Beautifier
        "s": ["--indent_size"],
        "c": ["--indent_char"],
        "l": ["--indent_level"],
        "t": ["--indent_with_tabs"],
        "p": ["--preserve_newlines"],
        "m": ["--max_preserve_newlines"],
        "j": ["--jslint_happy"],
        "b": ["--brace_style"],
        "B": ["--break_chained_methods"],
        "k": ["--keep_array_indentation"],
        "x": ["--unescape_strings"],
        "w": ["--wrap_line_length"],
        // HTML-only
        "W": ["--max_char"],
        "U": ["--unformatted"],
        "S": ["--indent_scripts"],
        // non-dasherized hybrid shortcuts
        "good-stuff": [
            "--keep_array_indentation",
            "--keep_function_indentation",
            "--jslint_happy"
        ],
        "js"  : ["--type", "js"],
        "css" : ["--type", "css"],
        "html": ["--type", "html"],
        // CLI
        "v": ["--version"],
        "h": ["--help"],
        "f": ["--files"],
        "o": ["--outfile"],
        "r": ["--replace"],
        "q": ["--quiet"]
        // no shorthand for "config"
    });

// var cli = require('js-beautify/cli'); cli.interpret();
var interpret = exports.interpret = function (argv, slice) {
    var parsed = nopt(knownOpts, shortHands, argv, slice);

    if (parsed.version) {
        console.log(require(__dirname + '/../../package.json').version);
        process.exit(0);
    }
    else if (parsed.help) {
        usage();
        process.exit(0);
    }

    var cfg = cc(
        parsed,
        cleanOptions(cc.env('jsbeautify_'), knownOpts),
        parsed.config,
        cc.find('.jsbeautifyrc'),
        cc.find(path.join(process.env.HOME, ".jsbeautifyrc")),
        __dirname + '/../config/defaults.json'
    ).snapshot;

    try {
        // Verify arguments
        checkType(cfg);
        checkFiles(cfg);
        checkIndent(cfg);
        debug(cfg);

        // Process files synchronously to avoid EMFILE error
        cfg.files.forEach(processInputSync, { cfg: cfg });
    }
    catch (ex) {
        debug(cfg);
        // usage(ex);
        console.error(ex);
        console.error('Run `' + getScriptName() + ' -h` for help.');
        process.exit(1);
    }
};

// interpret args immediately when called as executable
if (require.main === module) {
    interpret();
}

function usage(err) {
    var scriptName = getScriptName();
    var msg = [
        scriptName + '@' + require('./package.json').version,
        '',
        'CLI Options:',
        '  -f, --file       Input file(s) (Pass \'-\' for stdin)',
        '  -r, --replace    Write output in-place, replacing input',
        '  -o, --outfile    Write output to file (default stdout)',
        '  --config         Path to config file',
        '  --type           [js|css|html] ["js"]',
        '  -q, --quiet      Suppress logging to stdout',
        '  -h, --help       Show this help',
        '  -v, --version    Show the version',
        '',
        'Beautifier Options:',
        '  -s, --indent-size             Indentation size [4]',
        '  -c, --indent-char             Indentation character [" "]'
    ];

    switch (scriptName.split('-').shift()) {
    case "js":
        msg.push('  -l, --indent-level            Initial indentation level [0]');
        msg.push('  -t, --indent-with-tabs        Indent with tabs, overrides -s and -c');
        msg.push('  -p, --preserve-newlines       Preserve line-breaks (--no-preserve-newlines disables)');
        msg.push('  -m, --max-preserve-newlines   Number of line-breaks to be preserved in one chunk [10]');
        msg.push('  -j, --jslint-happy            Enable jslint-stricter mode');
        msg.push('  -b, --brace-style             [collapse|expand|end-expand|expand-strict] ["collapse"]');
        msg.push('  -B, --break-chained-methods   Break chained method calls across subsequent lines');
        msg.push('  -k, --keep-array-indentation  Preserve array indentation');
        msg.push('  -x, --unescape-strings        Decode printable characters encoded in xNN notation');
        msg.push('  -w, --wrap-line-length        Wrap lines at next opportunity after N characters [0]');
        msg.push('  --good-stuff                  Warm the cockles of Crockford\'s heart');
        break;
    case "html":
        msg.push('  -b, --brace-style             [collapse|expand|end-expand] ["collapse"]');
        msg.push('  -S, --indent-scripts          [keep|separate|normal] ["normal"]');
        msg.push('  -W, --max-char                Maximum characters per line (0 disables) [250]');
        msg.push('  -U, --unformatted             List of tags (defaults to inline) that should not be reformatted');
        break;
    }

    if (err) {
        msg.push(err);
        msg.push('');
        console.error(msg.join('\n'));
    } else {
        console.log(msg.join('\n'));
    }
}

// main iterator, {cfg} passed as thisArg of forEach call
function processInputSync(filepath) {
    var data = '',
        config = this.cfg,
        outfile = config.outfile,
        input;

    // -o passed with no value overwrites
    if (outfile === true || config.replace) {
        outfile = filepath;
    }

    if (filepath === '-') {
        input = process.stdin;
        input.resume();
        input.setEncoding('utf8');

        input.on('data', function (chunk) {
            data += chunk;
        });

        input.on('end', function () {
            makePretty(data, config, outfile, writePretty);
        });
    }
    else {
        data = fs.readFileSync(filepath, 'utf8');
        makePretty(data, config, outfile, writePretty);
    }
}

function makePretty(code, config, outfile, callback) {
    try {
        var fileType = getOutputType(outfile, config.type);
        var pretty = beautify[fileType](code, config);

        // ensure newline at end of beautified output
        pretty += '\n';

        callback(null, pretty, outfile, config);
    }
    catch (ex) {
        callback(ex);
    }
}

function writePretty(err, pretty, outfile, config) {
    if (err) {
        console.error(err);
        process.exit(1);
    }

    if (outfile) {
        try {
            fs.writeFileSync(outfile, pretty, 'utf8');
            logToStdout('beautified ' + path.relative(process.cwd(), outfile), config);
        }
        catch (ex) {
            onOutputError(ex);
        }
    }
    else {
        process.stdout.write(pretty);
    }
}

// workaround the fact that nopt.clean doesn't return the object passed in :P
function cleanOptions(data, types) {
    nopt.clean(data, types);
    return data;
}

// error handler for output stream that swallows errors silently,
// allowing the loop to continue over unwritable files.
function onOutputError(err) {
    if (err.code === 'EACCES') {
        console.error(err.path + " is not writable. Skipping!");
    }
    else {
        console.error(err);
        process.exit(0);
    }
}

// turn "--foo_bar" into "foo-bar"
function dasherizeFlag(str) {
    return str.replace(/^\-+/, '').replace(/_/g, '-');
}

// translate weird python underscored keys into dashed argv,
// avoiding single character aliases.
function dasherizeShorthands(hash) {
    // operate in-place
    Object.keys(hash).forEach(function (key) {
        // each key value is an array
        var val = hash[key][0];
        // only dasherize one-character shorthands
        if (key.length === 1 && val.indexOf('_') > -1) {
            hash[dasherizeFlag(val)] = val;
        }
    });

    return hash;
}

function getOutputType(outfile, configType) {
    if (outfile && /\.(js|css|html)$/.test(outfile)) {
        return outfile.split('.').pop();
    }
    return configType;
}

function getScriptName() {
    return path.basename(process.argv[1]);
}

function checkType(parsed) {
    var scriptType = getScriptName().split('-').shift();
    debug("executable type:", scriptType);

    var parsedType = parsed.type;
    debug("parsed type:", parsedType);

    if (!parsedType) {
        debug("type defaulted:", scriptType);
        parsed.type = scriptType;
    }
}

function checkIndent(parsed) {
    if (parsed["indent_with_tabs"]) {
        parsed["indent_size"] = 1;
        parsed["indent_char"] = "\t";
    }

    return parsed;
}

function checkFiles(parsed) {
    var argv = parsed.argv;

    if (!parsed.files) {
        parsed.files = [];
    }
    else {
        if (argv.cooked.indexOf('-') > -1) {
            // strip stdin path eagerly added by nopt in '-f -' case
            parsed.files.some(removeDashedPath);
        }
    }

    if (argv.remain.length) {
        // assume any remaining args are files
        argv.remain.forEach(function (f) {
            parsed.files.push(path.resolve(f));
        });
    }

    if ('string' === typeof parsed.outfile && !parsed.files.length) {
        // use outfile as input when no other files passed in args
        parsed.files.push(parsed.outfile);
        // operation is now an implicit overwrite
        parsed.replace = true;
    }

    if (argv.original.indexOf('-') > -1) {
        // ensure '-' without '-f' still consumes stdin
        parsed.files.push('-');
    }

    if (!parsed.files.length) {
        throw 'Must define at least one file.';
    }
    debug('files.length ' + parsed.files.length);

    parsed.files.forEach(testFilePath);

    return parsed;
}

function removeDashedPath(filepath, i, arr) {
    var found = filepath.lastIndexOf('-') === (filepath.length - 1);
    if (found) {
        arr.splice(i, 1);
    }
    return found;
}

function testFilePath(filepath) {
    try {
        if (filepath !== "-") {
            fs.statSync(filepath);
        }
    }
    catch (err) {
        throw 'Unable to open path "' + filepath + '"';
    }
}

function logToStdout(str, config) {
    if (typeof config.quiet === "undefined" || !config.quiet) {
        console.log(str);
    }
}
<commit_msg>bugfix: -h option did not work due to path of package.json not updated in cli.js<commit_after>#!/usr/bin/env node

/*
  The MIT License (MIT)

  Copyright (c) 2007-2013 Einar Lielmanis and contributors.

  Permission is hereby granted, free of charge, to any person
  obtaining a copy of this software and associated documentation files
  (the "Software"), to deal in the Software without restriction,
  including without limitation the rights to use, copy, modify, merge,
  publish, distribute, sublicense, and/or sell copies of the Software,
  and to permit persons to whom the Software is furnished to do so,
  subject to the following conditions:

  The above copyright notice and this permission notice shall be
  included in all copies or substantial portions of the Software.

  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
  BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
  ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
  CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  SOFTWARE.

  Js-Beautify Command-line for node.js
  -------------------------------------

  Written by Daniel Stockman (daniel.stockman@gmail.com)

*/

var debug = process.env.DEBUG_JSBEAUTIFY || process.env.JSBEAUTIFY_DEBUG
    ? function () { console.error.apply(console, arguments); }
    : function () {};

var fs = require('fs'),
    cc = require('config-chain'),
    beautify = require('../index'),
    nopt = require('nopt'),
    path = require('path'),
    knownOpts = {
        // Beautifier
        "indent_size": Number,
        "indent_char": String,
        "indent_level": Number,
        "indent_with_tabs": Boolean,
        "preserve_newlines": Boolean,
        "max_preserve_newlines": Number,
        "jslint_happy": Boolean,
        "brace_style": ["collapse", "expand", "end-expand", "expand-strict"],
        "break_chained_methods": Boolean,
        "keep_array_indentation": Boolean,
        "unescape_strings": Boolean,
        "wrap_line_length": Number,
        // HTML-only
        "max_char": Number,
        "unformatted": [String, Array],
        "indent_scripts": ["keep", "separate", "normal"],
        // CLI
        "version": Boolean,
        "help": Boolean,
        "files": [path, Array],
        "outfile": path,
        "replace": Boolean,
        "quiet": Boolean,
        "type": ["js", "css", "html"],
        "config": path
    },
    // dasherizeShorthands provides { "indent-size": ["--indent_size"] }
    // translation, allowing more convenient dashes in CLI arguments
    shortHands = dasherizeShorthands({
        // Beautifier
        "s": ["--indent_size"],
        "c": ["--indent_char"],
        "l": ["--indent_level"],
        "t": ["--indent_with_tabs"],
        "p": ["--preserve_newlines"],
        "m": ["--max_preserve_newlines"],
        "j": ["--jslint_happy"],
        "b": ["--brace_style"],
        "B": ["--break_chained_methods"],
        "k": ["--keep_array_indentation"],
        "x": ["--unescape_strings"],
        "w": ["--wrap_line_length"],
        // HTML-only
        "W": ["--max_char"],
        "U": ["--unformatted"],
        "S": ["--indent_scripts"],
        // non-dasherized hybrid shortcuts
        "good-stuff": [
            "--keep_array_indentation",
            "--keep_function_indentation",
            "--jslint_happy"
        ],
        "js"  : ["--type", "js"],
        "css" : ["--type", "css"],
        "html": ["--type", "html"],
        // CLI
        "v": ["--version"],
        "h": ["--help"],
        "f": ["--files"],
        "o": ["--outfile"],
        "r": ["--replace"],
        "q": ["--quiet"]
        // no shorthand for "config"
    });

// var cli = require('js-beautify/cli'); cli.interpret();
var interpret = exports.interpret = function (argv, slice) {
    var parsed = nopt(knownOpts, shortHands, argv, slice);

    if (parsed.version) {
        console.log(require(__dirname + '/../../package.json').version);
        process.exit(0);
    }
    else if (parsed.help) {
        usage();
        process.exit(0);
    }

    var cfg = cc(
        parsed,
        cleanOptions(cc.env('jsbeautify_'), knownOpts),
        parsed.config,
        cc.find('.jsbeautifyrc'),
        cc.find(path.join(process.env.HOME, ".jsbeautifyrc")),
        __dirname + '/../config/defaults.json'
    ).snapshot;

    try {
        // Verify arguments
        checkType(cfg);
        checkFiles(cfg);
        checkIndent(cfg);
        debug(cfg);

        // Process files synchronously to avoid EMFILE error
        cfg.files.forEach(processInputSync, { cfg: cfg });
    }
    catch (ex) {
        debug(cfg);
        // usage(ex);
        console.error(ex);
        console.error('Run `' + getScriptName() + ' -h` for help.');
        process.exit(1);
    }
};

// interpret args immediately when called as executable
if (require.main === module) {
    interpret();
}

function usage(err) {
    var scriptName = getScriptName();
    var msg = [
        scriptName + '@' + require(__dirname + '/../../package.json').version,
        '',
        'CLI Options:',
        '  -f, --file       Input file(s) (Pass \'-\' for stdin)',
        '  -r, --replace    Write output in-place, replacing input',
        '  -o, --outfile    Write output to file (default stdout)',
        '  --config         Path to config file',
        '  --type           [js|css|html] ["js"]',
        '  -q, --quiet      Suppress logging to stdout',
        '  -h, --help       Show this help',
        '  -v, --version    Show the version',
        '',
        'Beautifier Options:',
        '  -s, --indent-size             Indentation size [4]',
        '  -c, --indent-char             Indentation character [" "]'
    ];

    switch (scriptName.split('-').shift()) {
    case "js":
        msg.push('  -l, --indent-level            Initial indentation level [0]');
        msg.push('  -t, --indent-with-tabs        Indent with tabs, overrides -s and -c');
        msg.push('  -p, --preserve-newlines       Preserve line-breaks (--no-preserve-newlines disables)');
        msg.push('  -m, --max-preserve-newlines   Number of line-breaks to be preserved in one chunk [10]');
        msg.push('  -j, --jslint-happy            Enable jslint-stricter mode');
        msg.push('  -b, --brace-style             [collapse|expand|end-expand|expand-strict] ["collapse"]');
        msg.push('  -B, --break-chained-methods   Break chained method calls across subsequent lines');
        msg.push('  -k, --keep-array-indentation  Preserve array indentation');
        msg.push('  -x, --unescape-strings        Decode printable characters encoded in xNN notation');
        msg.push('  -w, --wrap-line-length        Wrap lines at next opportunity after N characters [0]');
        msg.push('  --good-stuff                  Warm the cockles of Crockford\'s heart');
        break;
    case "html":
        msg.push('  -b, --brace-style             [collapse|expand|end-expand] ["collapse"]');
        msg.push('  -S, --indent-scripts          [keep|separate|normal] ["normal"]');
        msg.push('  -W, --max-char                Maximum characters per line (0 disables) [250]');
        msg.push('  -U, --unformatted             List of tags (defaults to inline) that should not be reformatted');
        break;
    }

    if (err) {
        msg.push(err);
        msg.push('');
        console.error(msg.join('\n'));
    } else {
        console.log(msg.join('\n'));
    }
}

// main iterator, {cfg} passed as thisArg of forEach call
function processInputSync(filepath) {
    var data = '',
        config = this.cfg,
        outfile = config.outfile,
        input;

    // -o passed with no value overwrites
    if (outfile === true || config.replace) {
        outfile = filepath;
    }

    if (filepath === '-') {
        input = process.stdin;
        input.resume();
        input.setEncoding('utf8');

        input.on('data', function (chunk) {
            data += chunk;
        });

        input.on('end', function () {
            makePretty(data, config, outfile, writePretty);
        });
    }
    else {
        data = fs.readFileSync(filepath, 'utf8');
        makePretty(data, config, outfile, writePretty);
    }
}

function makePretty(code, config, outfile, callback) {
    try {
        var fileType = getOutputType(outfile, config.type);
        var pretty = beautify[fileType](code, config);

        // ensure newline at end of beautified output
        pretty += '\n';

        callback(null, pretty, outfile, config);
    }
    catch (ex) {
        callback(ex);
    }
}

function writePretty(err, pretty, outfile, config) {
    if (err) {
        console.error(err);
        process.exit(1);
    }

    if (outfile) {
        try {
            fs.writeFileSync(outfile, pretty, 'utf8');
            logToStdout('beautified ' + path.relative(process.cwd(), outfile), config);
        }
        catch (ex) {
            onOutputError(ex);
        }
    }
    else {
        process.stdout.write(pretty);
    }
}

// workaround the fact that nopt.clean doesn't return the object passed in :P
function cleanOptions(data, types) {
    nopt.clean(data, types);
    return data;
}

// error handler for output stream that swallows errors silently,
// allowing the loop to continue over unwritable files.
function onOutputError(err) {
    if (err.code === 'EACCES') {
        console.error(err.path + " is not writable. Skipping!");
    }
    else {
        console.error(err);
        process.exit(0);
    }
}

// turn "--foo_bar" into "foo-bar"
function dasherizeFlag(str) {
    return str.replace(/^\-+/, '').replace(/_/g, '-');
}

// translate weird python underscored keys into dashed argv,
// avoiding single character aliases.
function dasherizeShorthands(hash) {
    // operate in-place
    Object.keys(hash).forEach(function (key) {
        // each key value is an array
        var val = hash[key][0];
        // only dasherize one-character shorthands
        if (key.length === 1 && val.indexOf('_') > -1) {
            hash[dasherizeFlag(val)] = val;
        }
    });

    return hash;
}

function getOutputType(outfile, configType) {
    if (outfile && /\.(js|css|html)$/.test(outfile)) {
        return outfile.split('.').pop();
    }
    return configType;
}

function getScriptName() {
    return path.basename(process.argv[1]);
}

function checkType(parsed) {
    var scriptType = getScriptName().split('-').shift();
    debug("executable type:", scriptType);

    var parsedType = parsed.type;
    debug("parsed type:", parsedType);

    if (!parsedType) {
        debug("type defaulted:", scriptType);
        parsed.type = scriptType;
    }
}

function checkIndent(parsed) {
    if (parsed["indent_with_tabs"]) {
        parsed["indent_size"] = 1;
        parsed["indent_char"] = "\t";
    }

    return parsed;
}

function checkFiles(parsed) {
    var argv = parsed.argv;

    if (!parsed.files) {
        parsed.files = [];
    }
    else {
        if (argv.cooked.indexOf('-') > -1) {
            // strip stdin path eagerly added by nopt in '-f -' case
            parsed.files.some(removeDashedPath);
        }
    }

    if (argv.remain.length) {
        // assume any remaining args are files
        argv.remain.forEach(function (f) {
            parsed.files.push(path.resolve(f));
        });
    }

    if ('string' === typeof parsed.outfile && !parsed.files.length) {
        // use outfile as input when no other files passed in args
        parsed.files.push(parsed.outfile);
        // operation is now an implicit overwrite
        parsed.replace = true;
    }

    if (argv.original.indexOf('-') > -1) {
        // ensure '-' without '-f' still consumes stdin
        parsed.files.push('-');
    }

    if (!parsed.files.length) {
        throw 'Must define at least one file.';
    }
    debug('files.length ' + parsed.files.length);

    parsed.files.forEach(testFilePath);

    return parsed;
}

function removeDashedPath(filepath, i, arr) {
    var found = filepath.lastIndexOf('-') === (filepath.length - 1);
    if (found) {
        arr.splice(i, 1);
    }
    return found;
}

function testFilePath(filepath) {
    try {
        if (filepath !== "-") {
            fs.statSync(filepath);
        }
    }
    catch (err) {
        throw 'Unable to open path "' + filepath + '"';
    }
}

function logToStdout(str, config) {
    if (typeof config.quiet === "undefined" || !config.quiet) {
        console.log(str);
    }
}
<|endoftext|>