<commit_before>Polymer({
    publish: {
        bezier: [],
    },

    svg: null,
    bezierBinding: '',
    selectCurves: [],
    typeIndex: 0,
    move: false,
    _previewProgress: 0,
    _stopPreview: false,

    curves: [
        {
            name: 'Linear',
            items: [
                {
                    name: 'Default',
                    value: [0.5,0.5,0.5,0.5],
                },
            ],
        },
        {
            name: 'Ease In',
            items: [
                {
                    name: 'Cubic',
                    value: [0.4,0,0.5,0.5],
                },
                {
                    name: 'Quad',
                    value: [0.55,0.08,0.68,0.53],
                },
                {
                    name: 'Quart',
                    value: [0.89,0.03,0.68,0.21],
                },
                {
                    name: 'Quint',
                    value: [0.75,0.05,0.85,0.06],
                },
                {
                    name: 'Sine',
                    value: [0.48,0,0.73,0.71],
                },
                {
                    name: 'Expo',
                    value: [0.95,0.04,0.79,0.03],
                },
                {
                    name: 'Circ',
                    value: [0.6,0.04,0.98,0.33],
                },
            ],
        },

        {
            name: 'Ease Out',
            items: [
                {
                    name: 'Cubic',
                    value: [0.06,0.12,0.58,1],
                },
                {
                    name: 'Quad',
                    value: [0.25,0.46,0.45,0.95],
                },
                {
                    name: 'Quart',
                    value: [0.16,0.84,0.43,1],
                },
                {
                    name: 'Quint',
                    value: [0.22,1,0.31,1],
                },
                {
                    name: 'Sine',
                    value: [0.39,0.59,0.56,1],
                },
                {
                    name: 'Expo',
                    value: [0.18,1,0.22,1],
                },
                {
                    name: 'Circ',
                    value: [0.08,0.82,0.01,1],
                },
            ],
        },
        {
            name: 'Ease in out',
            items: [
                {
                    name: 'Cubic',
                    value: [0.42,0,0.58,1],
                },
                {
                    name: 'Quad',
                    value: [0.48,0.04,0.52,0.96],
                },
                {
                    name: 'Quart',
                    value: [0.83,0,0.17,1],
                },
                {
                    name: 'Quint',
                    value: [0.94,0,0.06,1],
                },
                {
                    name: 'Sine',
                    value: [0.46,0.05,0.54,0.95],
                },
                {
                    name: 'Expo',
                    value: [1,0,0,1],
                },
                {
                    name: 'Circ',
                    value: [0.86,0.14,0.14,0.86],
                },
            ],
        },
        {
            name: 'Back',
            items: [
                {
                    name: 'Forward',
                    value: [0.18,0.89,0.31,1.21],
                },
                {
                    name: 'Reverse',
                    value: [0.6,-0.27,0.73,0.04],
                },
            ],
        },
    ],

    domReady: function () {
        this.svg = this.$.svg;
        this.distance = this.$.curve.getBoundingClientRect().width - 1;
        this.ofX = this.$.curve.offsetLeft;
        this.ofY = this.$.curve.offsetTop;
        if ( this.bezier.length === 0) {
            this.selectCurves = this.curves[0].items[0].value;
            this.changeBezierType(0);
        }else {
            this.loadCustomBezier();
            this.drawBezier();
        }
        this.playPreview();
    },

    changeBezier: function(event) {
        var ele = event.target;
        for (var i = 0; i < ele.parentElement.children.length; i++) {
            ele.parentElement.children[i].removeAttribute('active');
            if (ele === ele.parentElement.children[i]) {
                this.bezier = this.curves[this.typeIndex].items[i].value.slice(0);
                ele.parentElement.children[i].setAttribute('active','');
                this.drawBezier();
            }
        }
    },

    changeBezierType: function (index) {
        this.typeIndex = index;
        if (!index) {
            this.selectCurves = this.curves[0].items.slice(0);
            return;
        }
        this.selectCurves = this.curves[index].items.slice(0);
    },

    curveTypeClickAction: function (event) {
        var ele = event.target;
        for (var i = 0; i < ele.parentElement.children.length; i++) {
            ele.parentElement.children[i].removeAttribute('select');
            if (ele === ele.parentElement.children[i]) {
                this.changeBezierType(i-1);
                this.typeIndex = i-1;
                ele.setAttribute('select','');
            }
        }
    },

    drawBezier: function () {
        if (this.bezier === []) {
            return;
        }
        this.$.svg.innerHTML = '';
        var realBezier = this.realCoord(this.bezier);

        var svgns = "http://www.w3.org/2000/svg";
        var slash = this.drawLine(this.distance + this.ofX,this.ofY,'#3e3e3e',true);
        var path = document.createElementNS(svgns,"path");
        var d = this.getPath(realBezier);

        path.setAttribute("d", d);
        path.setAttribute("fill", "none");
        path.setAttribute("stroke", "#e2e2e2");
        this.$.svg.appendChild(path);

        var line1 = this.drawLine(realBezier[0],realBezier[1],'#2c7dfd',true);
        var line2 = this.drawLine(realBezier[2],realBezier[3],'#2c7dfd',false);

        var spoint = this.drawRect(this.ofX,this.ofY + this.distance);
        var epoint = this.drawRect(this.ofX + this.distance,this.ofY);

        var c1point = this.drawPoint(realBezier[0],realBezier[1]);

        var c2point = this.drawPoint(realBezier[2],realBezier[3]);

        c1point.onmousedown = function () {
            this.move = true;
            this.onmousemove = function (event) {
                if (this.move) {
                    this.$.svg.style.cursor = 'all-scroll';
                    var x = event.clientX - this.$.curve.getBoundingClientRect().left + this.ofX;
                    var y = event.clientY - this.$.curve.getBoundingClientRect().top + this.ofY;
                    c1point.setAttribute("cx",x);
                    c1point.setAttribute("cy",y);
                    line1.setAttribute('x2',x);
                    line1.setAttribute('y2',y);
                    realBezier[0] = x;
                    this.bezier[0] = (x - this.ofX) / this.distance;
                    realBezier[1] = y;
                    this.bezier[1] = 1 - ((y - this.ofY) / this.distance);
                    path.setAttribute("d", this.getPath(realBezier));
                    this.updateValue();
                }
            };
            this.onmouseup = function () {
                this.$.svg.style.cursor = 'default';
                this.move = false;
            };
        }.bind(this);

        c2point.onmousedown = function () {
            this.move = true;
            this.onmousemove = function (event) {
                if (this.move) {
                    this.$.svg.style.cursor = 'all-scroll';
                    var x = event.clientX - this.$.curve.getBoundingClientRect().left + this.ofX;
                    var y = event.clientY - this.$.curve.getBoundingClientRect().top + this.ofY;
                    c2point.setAttribute("cx",x);
                    c2point.setAttribute("cy",y);
                    line2.setAttribute('x2',x);
                    line2.setAttribute('y2',y);
                    realBezier[2] = x;
                    this.bezier[2] = (x - this.ofX) / this.distance;
                    realBezier[3] = y;
                    this.bezier[3] = 1 - ( (y - this.ofY) / this.distance);
                    path.setAttribute("d", this.getPath(realBezier));
                    this.updateValue();
                }
            };

            this.onmouseup = function () {
                this.$.svg.style.cursor = 'default';
                this.move = false;
            };
        }.bind(this);
        this.updateValue();
    },

    realCoord: function (bezier) {
        var realCoord = [
            bezier[0] * this.distance + this.ofX,
            (1 - bezier[1]) * this.distance + this.ofY,
            bezier[2] * this.distance + this.ofX,
            (1 - bezier[3]) * this.distance + this.ofY,
        ];
        return realCoord;
    },

    getPath: function (points)　{
        var dstart = "M"+ this.ofX + ',' + (this.ofY + this.distance) + ' ';
        var controlPoint = "C" + points[0] +
            ',' + points[1] +
            ',' + points[2] +
            ',' + points[3] +
            ',' + (this.ofX + this.distance) + ',' + (this.ofY) + ' ';
        var p = dstart + controlPoint;
        return p;
    },

    drawPoint: function (cx,cy) {
        var svgns = "http://www.w3.org/2000/svg";
        var point = document.createElementNS(svgns,"circle");
        point.setAttribute("cx",cx);
        point.setAttribute("cy",cy);
        point.setAttribute("r","3");
        point.setAttribute("fill","#454544");
        point.setAttribute("stroke","white");
        point.setAttribute("class","point");
        this.svg.appendChild(point);
        return point;
    },

    drawRect: function (x,y) {
        var svgns = "http://www.w3.org/2000/svg";
        var rect = document.createElementNS(svgns,"rect");
        rect.setAttribute("x",x - 2.5);
        rect.setAttribute("y",y - 2.5);
        rect.setAttribute("width","5");
        rect.setAttribute("height","5");
        rect.setAttribute("stroke","#2f8bf5");
        rect.setAttribute("fill","white");
        this.svg.appendChild(rect);
        return rect;
    },

    drawLine: function (x,y,color,first)　{
        var svgns = "http://www.w3.org/2000/svg";
        var line = document.createElementNS(svgns,"line");
        if (first) {
            line.setAttribute("x1",this.ofX);
            line.setAttribute("y1",this.ofY + this.distance);
        }
        else {
            line.setAttribute("x1",this.ofX + this.distance);
            line.setAttribute("y1",this.ofY);
        }

        line.setAttribute("x2",x);
        line.setAttribute("y2",y);
        line.setAttribute("stroke",color);
        line.setAttribute("fill","transparent");
        line.setAttribute("stroke-width","1");
        this.svg.appendChild(line);
        return line;
    },

    updateValue: function () {
        this.bezierBinding = [
            this.bezier[0].toFixed(2),
            this.bezier[1].toFixed(2),
            this.bezier[2].toFixed(2),
            this.bezier[3].toFixed(2),
        ];
    },

    selectCurvesChanged: function () {
        this.$.btnGrp.innerHTML = '';
        for (var item in this.selectCurves) {
            var btns = document.createElement('div');
            btns.className = 'btn_item';
            if (item === '0' ) {
                btns.setAttribute('active','');
            }
            btns.addEventListener('click',function(event) {
                this.changeBezier(event);
            }.bind(this));
            btns.innerHTML = this.selectCurves[item].name;
            this.$.btnGrp.appendChild(btns);
        }
        this.$.beziers.children[this.typeIndex + 1].setAttribute('select','');
        this.bezier = this.curves[this.typeIndex].items[0].value.slice(0);
        this.drawBezier();
    },

    loadCustomBezier: function () {
        this.$.btnGrp.innerHTML = '';
        var btns = document.createElement('div');
        btns.className = 'btn_item';
        btns.setAttribute('active','');
        btns.innerHTML = 'Custom';
        this.$.btnGrp.appendChild(btns);
    },

    setBezier: function (bezier) {
        this.loadCustomBezier();
        this.bezier = bezier.slice(0);
        this.drawBezier();
    },

    updateAnimate: function () {
        if (this._stopPreview) {
            this.$.animate1.style.bottom = -1;
            this.$.animate2.style.left = -1;
            this._previewProgress = 0;
            return;
        }

        window.requestAnimationFrame(function() {
            if (this._previewProgress >= 1) {
                this._previewProgress = 0;
            }

            var coord = this.bezierToCoord(this.bezier,this._previewProgress);
            this.$.animate1.style.bottom = coord.y * this.distance;
            this.$.animate2.style.left = coord.x * this.distance;
            this._previewProgress += 0.008;
            this.updateAnimate();
        }.bind(this));
    },

    playPreview: function() {
        this._stopPreview = false;
        this.updateAnimate();
    },

    stopPreview: function () {
        this._stopPreview = true;
    },

    bezierToCoord: function (cp,t) {
        function Point2D(x,y){
            this.x=x||0.0;
            this.y=y||0.0;
        }

        var ax, bx, cx;
        var ay, by, cy;
        var tSquared, tCubed;

        cx = 3.0 * cp[0];
        bx = 3.0 * (cp[2] - cp[0]) - cx;
        ax = 1 - cx - bx;

        cy = 3.0 * (cp[1]);
        by = 3.0 * (cp[3] - cp[1]) - cy;
        ay = 1 - cy - by;

        var x = (ax * Math.pow(t,2) * t) + (bx * Math.pow(t,2)) + (cx * t) + 0,
            y = (ay * Math.pow(t,2) * t) + (by * Math.pow(t,2)) + (cy * t) + 0;

        return new Point2D(x,y);
    }

});
<commit_msg>fixed https://github.com/fireball-x/dev/issues/703#issuecomment-106164352<commit_after>Polymer({
    publish: {
        bezier: [],
    },

    svg: null,
    bezierBinding: '',
    selectCurves: [],
    typeIndex: 0,
    move: false,
    _previewProgress: 0,
    _stopPreview: false,

    curves: [
        {
            name: 'Linear',
            items: [
                {
                    name: 'Default',
                    value: [0.5,0.5,0.5,0.5],
                },
            ],
        },
        {
            name: 'Ease In',
            items: [
                {
                    name: 'Cubic',
                    value: [0.4,0,0.5,0.5],
                },
                {
                    name: 'Quad',
                    value: [0.55,0.08,0.68,0.53],
                },
                {
                    name: 'Quart',
                    value: [0.89,0.03,0.68,0.21],
                },
                {
                    name: 'Quint',
                    value: [0.75,0.05,0.85,0.06],
                },
                {
                    name: 'Sine',
                    value: [0.48,0,0.73,0.71],
                },
                {
                    name: 'Expo',
                    value: [0.95,0.04,0.79,0.03],
                },
                {
                    name: 'Circ',
                    value: [0.6,0.04,0.98,0.33],
                },
            ],
        },

        {
            name: 'Ease Out',
            items: [
                {
                    name: 'Cubic',
                    value: [0.06,0.12,0.58,1],
                },
                {
                    name: 'Quad',
                    value: [0.25,0.46,0.45,0.95],
                },
                {
                    name: 'Quart',
                    value: [0.16,0.84,0.43,1],
                },
                {
                    name: 'Quint',
                    value: [0.22,1,0.31,1],
                },
                {
                    name: 'Sine',
                    value: [0.39,0.59,0.56,1],
                },
                {
                    name: 'Expo',
                    value: [0.18,1,0.22,1],
                },
                {
                    name: 'Circ',
                    value: [0.08,0.82,0.01,1],
                },
            ],
        },
        {
            name: 'Ease in out',
            items: [
                {
                    name: 'Cubic',
                    value: [0.42,0,0.58,1],
                },
                {
                    name: 'Quad',
                    value: [0.48,0.04,0.52,0.96],
                },
                {
                    name: 'Quart',
                    value: [0.83,0,0.17,1],
                },
                {
                    name: 'Quint',
                    value: [0.94,0,0.06,1],
                },
                {
                    name: 'Sine',
                    value: [0.46,0.05,0.54,0.95],
                },
                {
                    name: 'Expo',
                    value: [1,0,0,1],
                },
                {
                    name: 'Circ',
                    value: [0.86,0.14,0.14,0.86],
                },
            ],
        },
        {
            name: 'Back',
            items: [
                {
                    name: 'Forward',
                    value: [0.18,0.89,0.31,1.21],
                },
                {
                    name: 'Reverse',
                    value: [0.6,-0.27,0.73,0.04],
                },
            ],
        },
    ],

    domReady: function () {
        this.svg = this.$.svg;
        this.distance = this.$.curve.getBoundingClientRect().width - 1;
        this.ofX = this.$.curve.offsetLeft;
        this.ofY = this.$.curve.offsetTop;
        if ( this.bezier.length === 0) {
            this.selectCurves = this.curves[0].items[0].value;
            this.changeBezierType(0);
        }else {
            this.loadCustomBezier();
            this.drawBezier();
        }
        this.playPreview();
    },

    changeBezier: function(event) {
        var ele = event.target;
        for (var i = 0; i < ele.parentElement.children.length; i++) {
            ele.parentElement.children[i].removeAttribute('active');
            if (ele === ele.parentElement.children[i]) {
                this.bezier = this.curves[this.typeIndex].items[i].value.slice(0);
                ele.parentElement.children[i].setAttribute('active','');
                this.drawBezier();
            }
        }
    },

    changeBezierType: function (index) {
        this.typeIndex = index;
        if (!index) {
            this.selectCurves = this.curves[0].items.slice(0);
            return;
        }
        this.selectCurves = this.curves[index].items.slice(0);
    },

    curveTypeClickAction: function (event) {
        var ele = event.target;
        for (var i = 0; i < ele.parentElement.children.length; i++) {
            ele.parentElement.children[i].removeAttribute('select');
            if (ele === ele.parentElement.children[i]) {
                this.changeBezierType(i-1);
                this.typeIndex = i-1;
                ele.setAttribute('select','');
            }
        }
    },

    drawBezier: function () {
        if (this.bezier === []) {
            return;
        }
        this.$.svg.innerHTML = '';
        var realBezier = this.realCoord(this.bezier);

        var svgns = "http://www.w3.org/2000/svg";
        var slash = this.drawLine(this.distance + this.ofX,this.ofY,'#3e3e3e',true);
        var path = document.createElementNS(svgns,"path");
        var d = this.getPath(realBezier);

        path.setAttribute("d", d);
        path.setAttribute("fill", "none");
        path.setAttribute("stroke", "#e2e2e2");
        this.$.svg.appendChild(path);

        var line1 = this.drawLine(realBezier[0],realBezier[1],'#2c7dfd',true);
        var line2 = this.drawLine(realBezier[2],realBezier[3],'#2c7dfd',false);

        var spoint = this.drawRect(this.ofX,this.ofY + this.distance);
        var epoint = this.drawRect(this.ofX + this.distance,this.ofY);

        var c1point = this.drawPoint(realBezier[0],realBezier[1]);

        var c2point = this.drawPoint(realBezier[2],realBezier[3]);

        c1point.onmousedown = function () {
            this.move = true;
            this.onmousemove = function (event) {
                if (this.move) {
                    this.$.svg.style.cursor = 'all-scroll';
                    var x = event.clientX - this.$.curve.getBoundingClientRect().left + this.ofX;
                    var y = event.clientY - this.$.curve.getBoundingClientRect().top + this.ofY;
                    c1point.setAttribute("cx",x);
                    c1point.setAttribute("cy",y);
                    line1.setAttribute('x2',x);
                    line1.setAttribute('y2',y);
                    realBezier[0] = x;
                    this.bezier[0] = (x - this.ofX) / this.distance;
                    realBezier[1] = y;
                    this.bezier[1] = 1 - ((y - this.ofY) / this.distance);
                    path.setAttribute("d", this.getPath(realBezier));
                    this.updateValue();
                }
            };
            this.onmouseup = function () {
                this.$.svg.style.cursor = 'default';
                this.move = false;
            };
        }.bind(this);

        c2point.onmousedown = function () {
            this.move = true;
            this.onmousemove = function (event) {
                if (this.move) {
                    this.$.svg.style.cursor = 'all-scroll';
                    var x = event.clientX - this.$.curve.getBoundingClientRect().left + this.ofX;
                    var y = event.clientY - this.$.curve.getBoundingClientRect().top + this.ofY;
                    c2point.setAttribute("cx",x);
                    c2point.setAttribute("cy",y);
                    line2.setAttribute('x2',x);
                    line2.setAttribute('y2',y);
                    realBezier[2] = x;
                    this.bezier[2] = (x - this.ofX) / this.distance;
                    realBezier[3] = y;
                    this.bezier[3] = 1 - ( (y - this.ofY) / this.distance);
                    path.setAttribute("d", this.getPath(realBezier));
                    this.updateValue();
                }
            };

            this.onmouseup = function () {
                this.$.svg.style.cursor = 'default';
                this.move = false;
            };
        }.bind(this);
        this.updateValue();
    },

    realCoord: function (bezier) {
        var realCoord = [
            bezier[0] * this.distance + this.ofX,
            (1 - bezier[1]) * this.distance + this.ofY,
            bezier[2] * this.distance + this.ofX,
            (1 - bezier[3]) * this.distance + this.ofY,
        ];
        return realCoord;
    },

    getPath: function (points)　{
        var dstart = "M"+ this.ofX + ',' + (this.ofY + this.distance) + ' ';
        var controlPoint = "C" + points[0] +
            ',' + points[1] +
            ',' + points[2] +
            ',' + points[3] +
            ',' + (this.ofX + this.distance) + ',' + (this.ofY) + ' ';
        var p = dstart + controlPoint;
        return p;
    },

    drawPoint: function (cx,cy) {
        var svgns = "http://www.w3.org/2000/svg";
        var point = document.createElementNS(svgns,"circle");
        point.setAttribute("cx",cx);
        point.setAttribute("cy",cy);
        point.setAttribute("r","3");
        point.setAttribute("fill","#454544");
        point.setAttribute("stroke","white");
        point.setAttribute("class","point");
        this.svg.appendChild(point);
        return point;
    },

    drawRect: function (x,y) {
        var svgns = "http://www.w3.org/2000/svg";
        var rect = document.createElementNS(svgns,"rect");
        rect.setAttribute("x",x - 2.5);
        rect.setAttribute("y",y - 2.5);
        rect.setAttribute("width","5");
        rect.setAttribute("height","5");
        rect.setAttribute("stroke","#2f8bf5");
        rect.setAttribute("fill","white");
        this.svg.appendChild(rect);
        return rect;
    },

    drawLine: function (x,y,color,first)　{
        var svgns = "http://www.w3.org/2000/svg";
        var line = document.createElementNS(svgns,"line");
        if (first) {
            line.setAttribute("x1",this.ofX);
            line.setAttribute("y1",this.ofY + this.distance);
        }
        else {
            line.setAttribute("x1",this.ofX + this.distance);
            line.setAttribute("y1",this.ofY);
        }

        line.setAttribute("x2",x);
        line.setAttribute("y2",y);
        line.setAttribute("stroke",color);
        line.setAttribute("fill","transparent");
        line.setAttribute("stroke-width","1");
        this.svg.appendChild(line);
        return line;
    },

    updateValue: function () {
        this.bezierBinding = [
            this.bezier[0].toFixed(2),
            this.bezier[1].toFixed(2),
            this.bezier[2].toFixed(2),
            this.bezier[3].toFixed(2),
        ];
    },

    selectCurvesChanged: function () {
        this.$.btnGrp.innerHTML = '';
        for (var item in this.selectCurves) {
            var btns = document.createElement('div');
            btns.className = 'btn_item';
            if (item === '0' ) {
                btns.setAttribute('active','');
            }
            btns.addEventListener('click',function(event) {
                this.changeBezier(event);
            }.bind(this));
            btns.innerHTML = this.selectCurves[item].name;
            this.$.btnGrp.appendChild(btns);
        }
        this.$.beziers.children[this.typeIndex + 1].setAttribute('select','');
        this.bezier = this.curves[this.typeIndex].items[0].value.slice(0);
        this.drawBezier();
    },

    loadCustomBezier: function () {
        this.$.btnGrp.innerHTML = '';
        var btns = document.createElement('div');
        btns.className = 'btn_item';
        btns.setAttribute('active','');
        btns.innerHTML = 'Custom';
        this.$.btnGrp.appendChild(btns);
    },

    setBezier: function (bezier) {
        this.loadCustomBezier();
        this.bezier = bezier.slice(0);
        this.drawBezier();
    },

    updateAnimate: function () {
        if (this._stopPreview) {
            this.$.animate1.style.bottom = -1;
            this.$.animate2.style.left = -1;
            this._previewProgress = 0;
            return;
        }

        window.requestAnimationFrame(function() {
            if (this._previewProgress >= 1) {
                this._previewProgress = 0;
            }
            var y = Fire._bezier(this.bezier,this._previewProgress);
            this.$.animate1.style.bottom = y * this.distance;
            this.$.animate2.style.left = this._previewProgress * this.distance;
            this._previewProgress += 0.005;
            this.updateAnimate();
        }.bind(this));
    },

    playPreview: function() {
        this._stopPreview = false;
        this.updateAnimate();
    },

    stopPreview: function () {
        this._stopPreview = true;
    },

});
<|endoftext|>


<commit_before>// used when nak is run from a script
exports.run = function(options) {
  if (!options) {
    options = process.argv;
    options.splice(0, 2);

    // from a script
    if (options[0] === "--json") {
      options = JSON.parse(options[1]);
    }
    // from the bin
    else {
      options = require("../lib/options").parseArgs(options);
      options.path = options.args.pop();

      if (options.args.length == 1)
        options.query = options.args.pop();
      else if (options.args.length == 2) {
        options.replacement = options.args.pop();
        options.query = options.args.pop();
      }
    }
  }
  main(options);
};

function main(options) {
var fs = require('fs'),
    path = require('path'),
    walkdir = require('../lib/walkdir').walkdir,
    PathFilter = require('../lib/path-filter');

// arguments
var fpath = path.resolve(options.path),
    replacement = options.replacement,
    query = options.query,
    textColor = "",
    matches = 0,
    filecount = 0;

if (process.platform == "win32" && options.path[0] == "/" || options.path[0] == "\\")
  fpath = options.path.replace(/\\/g, "/");

if (options.startPaths) {
  if (typeof options.startPaths == "string")
    options.startPaths = [options.startPaths];
  options.startPaths = options.startPaths.map(function(p) {
    if (p[0] == "/" && fpath.slice(-1) == "/")
      p = p.substring(1);
    if (p.slice(-1) === "/")
      p = p.slice(0, - 1);
    var fullPath = path.normalize(fpath + p);
    var base = fpath;
    if (process.platform == "win32") {
      fullPath = fullPath.replace(/\\/g, "/");
      base = base.replace(/\\/g, "/");
    }
    if (fullPath.lastIndexOf(base, 0) === 0) {
      return p;
    }
  }).filter(Boolean);
}

if (process.platform == "win32" && fpath[0] == "/")
  fpath = fpath.substr(1);

if (options.color) {
  var colors = require('colors'),
  queryString = String(options.query),
  textColor = queryString.substring(1, queryString.length - 1);
}

setInclusions();
setExclusions(fpath);
// console.log(options)

// set the query up, and present a final summary; also, pump out results as they come.
// "streaming" output like this is slower (because console.log blocks)
// but serves a purpose when finding text
if (typeof callback != "undefined") {
  var Stream = require('stream').Stream;
  var stream = new Stream();
  stream.readable = true;

  callback(null, {stream: stream});

  if (query) {
    makeQuery(query, replacement);
    var output = "";

    walkdir(fpath, options, function(file, lines, _matches) {
      stream.emit("data", file + "\n" + lines);
      matches += _matches;
      filecount++;
    }, function() {
      if (!options.ackmate)
        stream.emit("data", "Found " + matches + (matches == 1 ? " match" : " matches") + " in " + filecount + (filecount == 1 ? " file " : " files "));

      stream.emit("end", {count : matches, filecount: filecount});
    });
  }
  // if we're listing, callback at the very end
  else if (options.list) {
    walkdir(fpath, options, function(lines) {
        stream.emit("data", lines);
        stream.emit("end");
    });
  }
}
// if we're listing, callback at the very end
else if (options.list || !query) {
  walkdir(fpath, options, function(lines) {
    console.log(lines);
  });
}
else if (query) {
  makeQuery(query, replacement);

  walkdir(fpath, options, function(file, lines, _matches) {
    if (!options.color) {
      console.log(file);
      console.log(lines);
    }
    else {
      console.log(file.cyan);
      lines = lines.grey;
      lines = lines.replace(options.query, textColor.yellowBG);
      console.log(lines);
    }

    matches += _matches;
    filecount++;
  }, function() {
    if (!options.ackmate)
      console.log("Found " + matches + (matches == 1 ? " match" : " matches") + " in " + filecount + (filecount == 1 ? " file " : " files "));
  });
}

function setInclusions() {
  options.inclusions = [];
  var paths = (options.pathInclude || '').split(',');
  var i = paths.length;
  while (i--)
    options.inclusions.push(paths[i].trim());
}

function setExclusions(fpath) {
  var referencedExclusions = "",
      nakExclusions = "",
      gitExclusions = "";

  // if these ignore files don't exist, don't worry about them
  if (options.pathToNakignore) {
    try {
        referencedExclusions = fs.readFileSync(options.pathToNakignore, "utf-8");
      } catch (e) { }
  }

  try {
    nakExclusions = fs.readFileSync(fpath + path.sep + ".nakignore", "utf8");
  } catch (e) { /* console.log(e) */ }

  if (options.addVCSIgnores) {
    try {
      gitExclusions = fs.readFileSync(fpath + path.sep + ".gitignore", "utf8");
    } catch (e) { /* console.log(e) */ }
  }

  var combinedExclusions = referencedExclusions + "\n" +
                           nakExclusions + "\n" +
                           gitExclusions + "\n" +
                           (options.ignore || "").replace(/,/g, "\n");

  if (combinedExclusions.length) {
    options.exclusions = combinedExclusions.split(/\r?\n/);
  }
}

function makeQuery(query, replacement) {
  var flags = "g";
  if (options.literal)
    query = PathFilter.escapeRegExp(query);
  if (options.ignoreCase)
    flags += "i";

  if (options.wordRegexp)
    query = "\\b(?:" + query + ")\\b";

  options.query = new RegExp(query, flags);

  options.queryClean = new RegExp(query, flags.substr(1));

  if (typeof replacement == "string") {
    options.replacement = replacement;
  }
}

}

var simplefunc = require("simplefunc");

exports.serialize = function(fn) {
  return simplefunc.toJson(fn);
};

exports.deserialize = function(fn) {
  return simplefunc.fromJson(fn);
};
<commit_msg>fix logging %%<commit_after>// used when nak is run from a script
exports.run = function(options) {
  if (!options) {
    options = process.argv;
    options.splice(0, 2);

    // from a script
    if (options[0] === "--json") {
      options = JSON.parse(options[1]);
    }
    // from the bin
    else {
      options = require("../lib/options").parseArgs(options);
      options.path = options.args.pop();

      if (options.args.length == 1)
        options.query = options.args.pop();
      else if (options.args.length == 2) {
        options.replacement = options.args.pop();
        options.query = options.args.pop();
      }
    }
  }
  main(options);
};

function main(options) {
var fs = require('fs'),
    path = require('path'),
    walkdir = require('../lib/walkdir').walkdir,
    PathFilter = require('../lib/path-filter');

// arguments
var fpath = path.resolve(options.path),
    replacement = options.replacement,
    query = options.query,
    textColor = "",
    matches = 0,
    filecount = 0;

if (process.platform == "win32" && options.path[0] == "/" || options.path[0] == "\\")
  fpath = options.path.replace(/\\/g, "/");

if (options.startPaths) {
  if (typeof options.startPaths == "string")
    options.startPaths = [options.startPaths];
  options.startPaths = options.startPaths.map(function(p) {
    if (p[0] == "/" && fpath.slice(-1) == "/")
      p = p.substring(1);
    if (p.slice(-1) === "/")
      p = p.slice(0, - 1);
    var fullPath = path.normalize(fpath + p);
    var base = fpath;
    if (process.platform == "win32") {
      fullPath = fullPath.replace(/\\/g, "/");
      base = base.replace(/\\/g, "/");
    }
    if (fullPath.lastIndexOf(base, 0) === 0) {
      return p;
    }
  }).filter(Boolean);
}

if (process.platform == "win32" && fpath[0] == "/")
  fpath = fpath.substr(1);

if (options.color) {
  var colors = require('colors'),
  queryString = String(options.query),
  textColor = queryString.substring(1, queryString.length - 1);
}

setInclusions();
setExclusions(fpath);
// console.log(options)
function log(text) {
  process.stdout.write(text + "\n");
}
// set the query up, and present a final summary; also, pump out results as they come.
// "streaming" output like this is slower (because log blocks)
// but serves a purpose when finding text
if (typeof callback != "undefined") {
  var Stream = require('stream').Stream;
  var stream = new Stream();
  stream.readable = true;

  callback(null, {stream: stream});

  if (query) {
    makeQuery(query, replacement);
    var output = "";

    walkdir(fpath, options, function(file, lines, _matches) {
      stream.emit("data", file + "\n" + lines);
      matches += _matches;
      filecount++;
    }, function() {
      if (!options.ackmate)
        stream.emit("data", "Found " + matches + (matches == 1 ? " match" : " matches") + " in " + filecount + (filecount == 1 ? " file " : " files "));

      stream.emit("end", {count : matches, filecount: filecount});
    });
  }
  // if we're listing, callback at the very end
  else if (options.list) {
    walkdir(fpath, options, function(lines) {
        stream.emit("data", lines);
        stream.emit("end");
    });
  }
}
// if we're listing, callback at the very end
else if (options.list || !query) {
  walkdir(fpath, options, function(lines) {
    log(lines);
  });
}
else if (query) {
  makeQuery(query, replacement);

  walkdir(fpath, options, function(file, lines, _matches) {
    if (!options.color) {
      log(file);
      log(lines);
    }
    else {
      log(file.cyan);
      lines = lines.grey;
      lines = lines.replace(options.query, textColor.yellowBG);
      log(lines);
    }

    matches += _matches;
    filecount++;
  }, function() {
    if (!options.ackmate)
      log("Found " + matches + (matches == 1 ? " match" : " matches") + " in " + filecount + (filecount == 1 ? " file " : " files "));
  });
}

function setInclusions() {
  options.inclusions = [];
  var paths = (options.pathInclude || '').split(',');
  var i = paths.length;
  while (i--)
    options.inclusions.push(paths[i].trim());
}

function setExclusions(fpath) {
  var referencedExclusions = "",
      nakExclusions = "",
      gitExclusions = "";

  // if these ignore files don't exist, don't worry about them
  if (options.pathToNakignore) {
    try {
        referencedExclusions = fs.readFileSync(options.pathToNakignore, "utf-8");
      } catch (e) { }
  }

  try {
    nakExclusions = fs.readFileSync(fpath + path.sep + ".nakignore", "utf8");
  } catch (e) { /* console.log(e) */ }

  if (options.addVCSIgnores) {
    try {
      gitExclusions = fs.readFileSync(fpath + path.sep + ".gitignore", "utf8");
    } catch (e) { /* console.log(e) */ }
  }

  var combinedExclusions = referencedExclusions + "\n" +
                           nakExclusions + "\n" +
                           gitExclusions + "\n" +
                           (options.ignore || "").replace(/,/g, "\n");

  if (combinedExclusions.length) {
    options.exclusions = combinedExclusions.split(/\r?\n/);
  }
}

function makeQuery(query, replacement) {
  var flags = "g";
  if (options.literal)
    query = PathFilter.escapeRegExp(query);
  if (options.ignoreCase)
    flags += "i";

  if (options.wordRegexp)
    query = "\\b(?:" + query + ")\\b";

  options.query = new RegExp(query, flags);

  options.queryClean = new RegExp(query, flags.substr(1));

  if (typeof replacement == "string") {
    options.replacement = replacement;
  }
}

}

var simplefunc = require("simplefunc");

exports.serialize = function(fn) {
  return simplefunc.toJson(fn);
};

exports.deserialize = function(fn) {
  return simplefunc.fromJson(fn);
};
<|endoftext|>


<commit_before>exports.config = {
    //
    // ====================
    // Runner Configuration
    // ====================
    //
    // WebdriverIO allows it to run your tests in arbitrary locations (e.g. locally or
    // on a remote machine).
    runner: 'local',
    //
    // =================
    // Service Providers
    // =================
    // WebdriverIO supports Sauce Labs, Browserstack, Testing Bot and LambdaTest (other cloud providers
    // should work too though). These services define specific user and key (or access key)
    // values you need to put in here in order to connect to these services.
    //
    user: process.env.SAUCE_USERNAME,
    key: process.env.SAUCE_ACCESS_KEY,
    //
    // If you run your tests on Sauce Labs you can specify the region you want to run your tests
    // in via the `region` property. Available short handles for regions are `us` (default) and `eu`.
    // These regions are used for the Sauce Labs VM cloud and the Sauce Labs Real Device Cloud.
    // If you don't provide the region it will default for the `us`
    region: 'us',
    //
    // ==================
    // Specify Test Files
    // ==================
    // Define which test specs should run. The pattern is relative to the directory
    // from which `wdio` was called. Notice that, if you are calling `wdio` from an
    // NPM script (see https://docs.npmjs.com/cli/run-script) then the current working
    // directory is where your package.json resides, so `wdio` will be called from there.
    //
    specs: ['./test/wdio/**/*.js'],
    // Patterns to exclude.
    exclude: [
        // 'path/to/excluded/files'
    ],
    //
    // ============
    // Capabilities
    // ============
    // Define your capabilities here. WebdriverIO can run multiple capabilities at the same
    // time. Depending on the number of capabilities, WebdriverIO launches several test
    // sessions. Within your capabilities you can overwrite the spec and exclude options in
    // order to group specific specs to a specific capability.
    //
    // First, you can define how many instances should be started at the same time. Let's
    // say you have 3 different capabilities (Chrome, Firefox, and Safari) and you have
    // set maxInstances to 1; wdio will spawn 3 processes. Therefore, if you have 10 spec
    // files and you set maxInstances to 10, all spec files will get tested at the same time
    // and 30 processes will get spawned. The property handles how many capabilities
    // from the same test should run tests.
    //
    maxInstances: 10,
    //
    // If you have trouble getting all important capabilities together, check out the
    // Sauce Labs platform configurator - a great tool to configure your capabilities:
    // https://docs.saucelabs.com/reference/platforms-configurator
    //
    capabilities: [
        {
            browserName: 'chrome',
            browserVersion: 'latest',
            platformName: 'Windows 10',
            'sauce:options': {
                public: 'public',
                recordScreenshots: false,
            },
        } /*,
        {
            browserName: 'chrome',
            platformName: 'Windows 10',
            browserVersion: '72.0',
            'sauce:options': {
                public: 'public',
            },
        },
        {
            browserName: 'chrome',
            platformName: 'Windows 10',
            browserVersion: '48.0',
            'sauce:options': {
                public: 'public',
            },
        },
        {
            browserName: 'MicrosoftEdge',
            platformName: 'Windows 10',
            browserVersion: '18.17763',
            'sauce:options': {
                public: 'public',
            },
        },
        {
            browserName: 'MicrosoftEdge',
            platformName: 'Windows 10',
            browserVersion: '17.17134',
            'sauce:options': {
                public: 'public',
            },
        },
        {
            browserName: 'MicrosoftEdge',
            platformName: 'Windows 10',
            browserVersion: '16.16299',
            'sauce:options': {
                public: 'public',
            },
        },
        {
            browserName: 'MicrosoftEdge',
            platformName: 'Windows 10',
            browserVersion: 'latest',
            'sauce:options': {
                public: 'public',
            },
        },
        {
            browserName: 'firefox',
            platformName: 'Windows 10',
            browserVersion: '65.0',
            'sauce:options': {
                public: 'public',
            },
        },
        {
            browserName: 'firefox',
            platformName: 'Windows 10',
            browserVersion: '62.0',
            'sauce:options': {
                public: 'public',
            },
        },
        {
            browserName: 'firefox',
            platformName: 'Windows 10',
            browserVersion: 'latest',
            'sauce:options': {
                public: 'public',
            },
        },
        {
            browserName: 'safari',
            platformName: 'macOS 10.15',
            browserVersion: 'latest',
            'sauce:options': {
                public: 'public',
            },
        },*/,
    ],
    //
    // ===================
    // Test Configurations
    // ===================
    // Define all options that are relevant for the WebdriverIO instance here
    //
    // Level of logging verbosity: trace | debug | info | warn | error | silent
    logLevel: 'info',
    //
    // Set specific log levels per logger
    // loggers:
    // - webdriver, webdriverio
    // - @wdio/applitools-service, @wdio/browserstack-service, @wdio/devtools-service, @wdio/sauce-service
    // - @wdio/mocha-framework, @wdio/jasmine-framework
    // - @wdio/local-runner
    // - @wdio/sumologic-reporter
    // - @wdio/cli, @wdio/config, @wdio/sync, @wdio/utils
    // Level of logging verbosity: trace | debug | info | warn | error | silent
    // logLevels: {
    //     webdriver: 'info',
    //     '@wdio/applitools-service': 'info'
    // },
    //
    // If you only want to run your tests until a specific amount of tests have failed use
    // bail (default is 0 - don't bail, run all tests).
    bail: 0,
    //
    // Set a base URL in order to shorten url command calls. If your `url` parameter starts
    // with `/`, the base url gets prepended, not including the path portion of your baseUrl.
    // If your `url` parameter starts without a scheme or `/` (like `some/path`), the base url
    // gets prepended directly.
    baseUrl: 'http://localhost:4000',
    //
    // Default timeout for all waitFor* commands.
    waitforTimeout: 10000,
    //
    // Default timeout in milliseconds for request
    // if browser driver or grid doesn't send response
    connectionRetryTimeout: 120000,
    //
    // Default request retries count
    connectionRetryCount: 3,
    //
    // Test runner services
    // Services take over a specific job you don't want to take care of. They enhance
    // your test setup with almost no effort. Unlike plugins, they don't add new
    // commands. Instead, they hook themselves up into the test process.
    services: [
        [
            'sauce',
            {
                sauceConnect: true,
            },
        ],
    ],

    // Framework you want to run your specs with.
    // The following are supported: Mocha, Jasmine, and Cucumber
    // see also: https://webdriver.io/docs/frameworks.html
    //
    // Make sure you have the wdio adapter package for the specific framework installed
    // before running any tests.
    framework: 'mocha',
    //
    // The number of times to retry the entire specfile when it fails as a whole
    // specFileRetries: 1,
    //
    // Delay in seconds between the spec file retry attempts
    // specFileRetriesDelay: 0,
    //
    // Whether or not retried specfiles should be retried immediately or deferred to the end of the queue
    // specFileRetriesDeferred: false,
    //
    // Test reporter for stdout.
    // The only one supported by default is 'dot'
    // see also: https://webdriver.io/docs/dot-reporter.html
    reporters: ['spec'],

    //
    // Options to be passed to Mocha.
    // See the full list at http://mochajs.org/
    mochaOpts: {
        ui: 'bdd',
        timeout: 60000,
    },
    //
    // =====
    // Hooks
    // =====
    // WebdriverIO provides several hooks you can use to interfere with the test process in order to enhance
    // it and to build services around it. You can either apply a single function or an array of
    // methods to it. If one of them returns with a promise, WebdriverIO will wait until that promise got
    // resolved to continue.
    /**
     * Gets executed once before all workers get launched.
     * @param {Object} config wdio configuration object
     * @param {Array.<Object>} capabilities list of capabilities details
     */
    // onPrepare: function (config, capabilities) {
    // },
    /**
     * Gets executed before a worker process is spawned and can be used to initialise specific service
     * for that worker as well as modify runtime environments in an async fashion.
     * @param  {String} cid      capability id (e.g 0-0)
     * @param  {[type]} caps     object containing capabilities for session that will be spawn in the worker
     * @param  {[type]} specs    specs to be run in the worker process
     * @param  {[type]} args     object that will be merged with the main configuration once worker is initialised
     * @param  {[type]} execArgv list of string arguments passed to the worker process
     */
    // onWorkerStart: function (cid, caps, specs, args, execArgv) {
    // },
    /**
     * Gets executed just before initialising the webdriver session and test framework. It allows you
     * to manipulate configurations depending on the capability or spec.
     * @param {Object} config wdio configuration object
     * @param {Array.<Object>} capabilities list of capabilities details
     * @param {Array.<String>} specs List of spec file paths that are to be run
     */
    // beforeSession: function (config, capabilities, specs) {
    // },
    /**
     * Gets executed before test execution begins. At this point you can access to all global
     * variables like `browser`. It is the perfect place to define custom commands.
     * @param {Array.<Object>} capabilities list of capabilities details
     * @param {Array.<String>} specs List of spec file paths that are to be run
     */
    // before: function (capabilities, specs) {
    // },
    /**
     * Runs before a WebdriverIO command gets executed.
     * @param {String} commandName hook command name
     * @param {Array} args arguments that command would receive
     */
    // beforeCommand: function (commandName, args) {
    // },
    /**
     * Hook that gets executed before the suite starts
     * @param {Object} suite suite details
     */
    // beforeSuite: function (suite) {
    // },
    /**
     * Function to be executed before a test (in Mocha/Jasmine) starts.
     */
    // beforeTest: function (test, context) {
    // },
    /**
     * Hook that gets executed _before_ a hook within the suite starts (e.g. runs before calling
     * beforeEach in Mocha)
     */
    // beforeHook: function (test, context) {
    // },
    /**
     * Hook that gets executed _after_ a hook within the suite starts (e.g. runs after calling
     * afterEach in Mocha)
     */
    // afterHook: function (test, context, { error, result, duration, passed, retries }) {
    // },
    /**
     * Function to be executed after a test (in Mocha/Jasmine).
     */
    // afterTest: function(test, context, { error, result, duration, passed, retries }) {
    // },

    /**
     * Hook that gets executed after the suite has ended
     * @param {Object} suite suite details
     */
    // afterSuite: function (suite) {
    // },
    /**
     * Runs after a WebdriverIO command gets executed
     * @param {String} commandName hook command name
     * @param {Array} args arguments that command would receive
     * @param {Number} result 0 - command success, 1 - command error
     * @param {Object} error error object if any
     */
    // afterCommand: function (commandName, args, result, error) {
    // },
    /**
     * Gets executed after all tests are done. You still have access to all global variables from
     * the test.
     * @param {Number} result 0 - test pass, 1 - test fail
     * @param {Array.<Object>} capabilities list of capabilities details
     * @param {Array.<String>} specs List of spec file paths that ran
     */
    // after: function (result, capabilities, specs) {
    // },
    /**
     * Gets executed right after terminating the webdriver session.
     * @param {Object} config wdio configuration object
     * @param {Array.<Object>} capabilities list of capabilities details
     * @param {Array.<String>} specs List of spec file paths that ran
     */
    // afterSession: function (config, capabilities, specs) {
    // },
    /**
     * Gets executed after all workers got shut down and the process is about to exit. An error
     * thrown in the onComplete hook will result in the test run failing.
     * @param {Object} exitCode 0 - success, 1 - fail
     * @param {Object} config wdio configuration object
     * @param {Array.<Object>} capabilities list of capabilities details
     * @param {<Object>} results object containing test results
     */
    // onComplete: function(exitCode, config, capabilities, results) {
    // },
    /**
     * Gets executed when a refresh happens.
     * @param {String} oldSessionId session ID of the old session
     * @param {String} newSessionId session ID of the new session
     */
    //onReload: function(oldSessionId, newSessionId) {
    //}
};
<commit_msg>feat(tool): update badges<commit_after>exports.config = {
    //
    // ====================
    // Runner Configuration
    // ====================
    //
    // WebdriverIO allows it to run your tests in arbitrary locations (e.g. locally or
    // on a remote machine).
    runner: 'local',
    //
    // =================
    // Service Providers
    // =================
    // WebdriverIO supports Sauce Labs, Browserstack, Testing Bot and LambdaTest (other cloud providers
    // should work too though). These services define specific user and key (or access key)
    // values you need to put in here in order to connect to these services.
    //
    user: process.env.SAUCE_USERNAME,
    key: process.env.SAUCE_ACCESS_KEY,
    //
    // If you run your tests on Sauce Labs you can specify the region you want to run your tests
    // in via the `region` property. Available short handles for regions are `us` (default) and `eu`.
    // These regions are used for the Sauce Labs VM cloud and the Sauce Labs Real Device Cloud.
    // If you don't provide the region it will default for the `us`
    region: 'us',
    //
    // ==================
    // Specify Test Files
    // ==================
    // Define which test specs should run. The pattern is relative to the directory
    // from which `wdio` was called. Notice that, if you are calling `wdio` from an
    // NPM script (see https://docs.npmjs.com/cli/run-script) then the current working
    // directory is where your package.json resides, so `wdio` will be called from there.
    //
    specs: ['./test/wdio/**/*.js'],
    // Patterns to exclude.
    exclude: [
        // 'path/to/excluded/files'
    ],
    //
    // ============
    // Capabilities
    // ============
    // Define your capabilities here. WebdriverIO can run multiple capabilities at the same
    // time. Depending on the number of capabilities, WebdriverIO launches several test
    // sessions. Within your capabilities you can overwrite the spec and exclude options in
    // order to group specific specs to a specific capability.
    //
    // First, you can define how many instances should be started at the same time. Let's
    // say you have 3 different capabilities (Chrome, Firefox, and Safari) and you have
    // set maxInstances to 1; wdio will spawn 3 processes. Therefore, if you have 10 spec
    // files and you set maxInstances to 10, all spec files will get tested at the same time
    // and 30 processes will get spawned. The property handles how many capabilities
    // from the same test should run tests.
    //
    maxInstances: 10,
    //
    // If you have trouble getting all important capabilities together, check out the
    // Sauce Labs platform configurator - a great tool to configure your capabilities:
    // https://docs.saucelabs.com/reference/platforms-configurator
    //
    capabilities: [
        { browserName: 'chrome', platform: 'Windows 10', version: 'latest' },
        { browserName: 'chrome', platform: 'Windows 10', version: '72.0' },
        { browserName: 'chrome', platform: 'Windows 10', version: '48.0' },
        { browserName: 'MicrosoftEdge', platform: 'Windows 10', version: '18.17763' },
        { browserName: 'MicrosoftEdge', platform: 'Windows 10', version: '17.17134' },
        { browserName: 'MicrosoftEdge', platform: 'Windows 10', version: '16.16299' },
        { browserName: 'MicrosoftEdge', platform: 'Windows 10', version: 'latest' },
        { browserName: 'firefox', platform: 'Windows 10', version: '65.0' },
        { browserName: 'firefox', platform: 'Windows 10', version: '62.0' },
        { browserName: 'firefox', platform: 'Windows 10', version: 'latest' },
        { browserName: 'safari', platform: 'macOS 10.15', version: 'latest' },
    ],
    //
    // ===================
    // Test Configurations
    // ===================
    // Define all options that are relevant for the WebdriverIO instance here
    //
    // Level of logging verbosity: trace | debug | info | warn | error | silent
    logLevel: 'info',
    //
    // Set specific log levels per logger
    // loggers:
    // - webdriver, webdriverio
    // - @wdio/applitools-service, @wdio/browserstack-service, @wdio/devtools-service, @wdio/sauce-service
    // - @wdio/mocha-framework, @wdio/jasmine-framework
    // - @wdio/local-runner
    // - @wdio/sumologic-reporter
    // - @wdio/cli, @wdio/config, @wdio/sync, @wdio/utils
    // Level of logging verbosity: trace | debug | info | warn | error | silent
    // logLevels: {
    //     webdriver: 'info',
    //     '@wdio/applitools-service': 'info'
    // },
    //
    // If you only want to run your tests until a specific amount of tests have failed use
    // bail (default is 0 - don't bail, run all tests).
    bail: 0,
    //
    // Set a base URL in order to shorten url command calls. If your `url` parameter starts
    // with `/`, the base url gets prepended, not including the path portion of your baseUrl.
    // If your `url` parameter starts without a scheme or `/` (like `some/path`), the base url
    // gets prepended directly.
    baseUrl: 'http://localhost:4000',
    //
    // Default timeout for all waitFor* commands.
    waitforTimeout: 10000,
    //
    // Default timeout in milliseconds for request
    // if browser driver or grid doesn't send response
    connectionRetryTimeout: 120000,
    //
    // Default request retries count
    connectionRetryCount: 3,
    //
    // Test runner services
    // Services take over a specific job you don't want to take care of. They enhance
    // your test setup with almost no effort. Unlike plugins, they don't add new
    // commands. Instead, they hook themselves up into the test process.
    services: [
        [
            'sauce',
            {
                sauceConnect: true,
            },
        ],
    ],

    // Framework you want to run your specs with.
    // The following are supported: Mocha, Jasmine, and Cucumber
    // see also: https://webdriver.io/docs/frameworks.html
    //
    // Make sure you have the wdio adapter package for the specific framework installed
    // before running any tests.
    framework: 'mocha',
    //
    // The number of times to retry the entire specfile when it fails as a whole
    // specFileRetries: 1,
    //
    // Delay in seconds between the spec file retry attempts
    // specFileRetriesDelay: 0,
    //
    // Whether or not retried specfiles should be retried immediately or deferred to the end of the queue
    // specFileRetriesDeferred: false,
    //
    // Test reporter for stdout.
    // The only one supported by default is 'dot'
    // see also: https://webdriver.io/docs/dot-reporter.html
    reporters: ['spec'],

    //
    // Options to be passed to Mocha.
    // See the full list at http://mochajs.org/
    mochaOpts: {
        ui: 'bdd',
        timeout: 60000,
    },
    //
    // =====
    // Hooks
    // =====
    // WebdriverIO provides several hooks you can use to interfere with the test process in order to enhance
    // it and to build services around it. You can either apply a single function or an array of
    // methods to it. If one of them returns with a promise, WebdriverIO will wait until that promise got
    // resolved to continue.
    /**
     * Gets executed once before all workers get launched.
     * @param {Object} config wdio configuration object
     * @param {Array.<Object>} capabilities list of capabilities details
     */
    // onPrepare: function (config, capabilities) {
    // },
    /**
     * Gets executed before a worker process is spawned and can be used to initialise specific service
     * for that worker as well as modify runtime environments in an async fashion.
     * @param  {String} cid      capability id (e.g 0-0)
     * @param  {[type]} caps     object containing capabilities for session that will be spawn in the worker
     * @param  {[type]} specs    specs to be run in the worker process
     * @param  {[type]} args     object that will be merged with the main configuration once worker is initialised
     * @param  {[type]} execArgv list of string arguments passed to the worker process
     */
    // onWorkerStart: function (cid, caps, specs, args, execArgv) {
    // },
    /**
     * Gets executed just before initialising the webdriver session and test framework. It allows you
     * to manipulate configurations depending on the capability or spec.
     * @param {Object} config wdio configuration object
     * @param {Array.<Object>} capabilities list of capabilities details
     * @param {Array.<String>} specs List of spec file paths that are to be run
     */
    // beforeSession: function (config, capabilities, specs) {
    // },
    /**
     * Gets executed before test execution begins. At this point you can access to all global
     * variables like `browser`. It is the perfect place to define custom commands.
     * @param {Array.<Object>} capabilities list of capabilities details
     * @param {Array.<String>} specs List of spec file paths that are to be run
     */
    // before: function (capabilities, specs) {
    // },
    /**
     * Runs before a WebdriverIO command gets executed.
     * @param {String} commandName hook command name
     * @param {Array} args arguments that command would receive
     */
    // beforeCommand: function (commandName, args) {
    // },
    /**
     * Hook that gets executed before the suite starts
     * @param {Object} suite suite details
     */
    // beforeSuite: function (suite) {
    // },
    /**
     * Function to be executed before a test (in Mocha/Jasmine) starts.
     */
    // beforeTest: function (test, context) {
    // },
    /**
     * Hook that gets executed _before_ a hook within the suite starts (e.g. runs before calling
     * beforeEach in Mocha)
     */
    // beforeHook: function (test, context) {
    // },
    /**
     * Hook that gets executed _after_ a hook within the suite starts (e.g. runs after calling
     * afterEach in Mocha)
     */
    // afterHook: function (test, context, { error, result, duration, passed, retries }) {
    // },
    /**
     * Function to be executed after a test (in Mocha/Jasmine).
     */
    // afterTest: function(test, context, { error, result, duration, passed, retries }) {
    // },

    /**
     * Hook that gets executed after the suite has ended
     * @param {Object} suite suite details
     */
    // afterSuite: function (suite) {
    // },
    /**
     * Runs after a WebdriverIO command gets executed
     * @param {String} commandName hook command name
     * @param {Array} args arguments that command would receive
     * @param {Number} result 0 - command success, 1 - command error
     * @param {Object} error error object if any
     */
    // afterCommand: function (commandName, args, result, error) {
    // },
    /**
     * Gets executed after all tests are done. You still have access to all global variables from
     * the test.
     * @param {Number} result 0 - test pass, 1 - test fail
     * @param {Array.<Object>} capabilities list of capabilities details
     * @param {Array.<String>} specs List of spec file paths that ran
     */
    // after: function (result, capabilities, specs) {
    // },
    /**
     * Gets executed right after terminating the webdriver session.
     * @param {Object} config wdio configuration object
     * @param {Array.<Object>} capabilities list of capabilities details
     * @param {Array.<String>} specs List of spec file paths that ran
     */
    // afterSession: function (config, capabilities, specs) {
    // },
    /**
     * Gets executed after all workers got shut down and the process is about to exit. An error
     * thrown in the onComplete hook will result in the test run failing.
     * @param {Object} exitCode 0 - success, 1 - fail
     * @param {Object} config wdio configuration object
     * @param {Array.<Object>} capabilities list of capabilities details
     * @param {<Object>} results object containing test results
     */
    // onComplete: function(exitCode, config, capabilities, results) {
    // },
    /**
     * Gets executed when a refresh happens.
     * @param {String} oldSessionId session ID of the old session
     * @param {String} newSessionId session ID of the new session
     */
    //onReload: function(oldSessionId, newSessionId) {
    //}
};
<|endoftext|>


<commit_before>/*
 * net.js: Wrapper around node.js core `net` module for observing relevant events
 *
 * (C) 2011 Nodejitsu Inc.
 *
 */

var net = require('net'),
    carapace = require('./carapace');

module.exports = function overrideNet() {
  //
  // Helper function from Node code to parse port arguments
  // passed to net.prototype.Server.listen
  //
  function toPort(x) {
    return (x = Number(x)) >= 0 ? x : false;
  }

  //
  // ### function nextPort (port)
  // #### @port {Number} Port to increment from.
  // Gets the next port in sequence from the
  // specified `port`.
  //
  function nextPort(port) {
    if (!port) {
      return 8000;
    }

    //
    // Find the next port that we are not supposed to ignore or cause errors on
    //
    var unavailable = carapace.ports.ignore.concat(carapace.ports.throw);
    do {
      port = port + 1;
    } while (unavailable.indexOf(port) !== -1);

    return port;
  }

  //
  // Internal mapping of server instances to
  // ports that have been mapped via `.listen()`.
  //
  carapace.servers = {};

  var _listen2 = net.Server.prototype._listen2;
  net.Server.prototype._listen2 = function ourListen(address, port, addressType, desired) {
    var self = this;

    port = toPort(port);
    desired || (desired = port);

    //
    // Always throw if our desired port was one that should always throw
    //
    if (carapace.ports.throw.indexOf(port) !== -1) {
      self.close();
      //
      // Build fake error
      //
      err = new Error('EADDRINUSE, Address already in use');
      err.code = 'EADDRINUSE';
      err.syscall = 'bind';
      err.errno = 100;
      return self.emit('error', err);
    }
    //
    // Since desired is not on a throwing port
    // we want to skip ports in both throw and ignore
    //
    port || (port = nextPort(port));

    //
    // We rely on `error` event to check if address it taken/available, however
    // user may want to hook up to `error` in his application as well (and
    // usually exit when it's emitted). This messes things up. Here we store
    // `error` event listeners and remove them. They will be restored after we
    // start listening or get an error which is not `EADDRINUSE`.
    //
    var errorListeners = self.listeners('error');
    self.removeAllListeners('error');

    function restoreErrorListeners() {
      errorListeners.forEach(function (listener) {
        self.on('error', listener);
      });
    }

    //
    // Problem with `listening` events is a bit different. We want to ensure
    // that we first emit `carapace::port` and *then* the proper `listening`
    // event (which can be consumed by user's app).
    //
    // (Also, not doing so breaks `net/net-multiple-servers-test` test.)
    //
    var listeningListeners = self.listeners('listening');
    self.removeAllListeners('listening');

    function restoreListeningListeners() {
      listeningListeners.forEach(function (listener) {
        self.on('listening', listener);
      });
    }

    function onListen() {
      //
      // Yay, we made it! Lets restore `error` listeners and tell the world
      // that we totally owned this port.
      //

      self.removeListener('error', onError);

      restoreErrorListeners();
      restoreListeningListeners();

      //
      // Store the server that has listened on the `desired` port
      // on the carapace itself, indexed by port.
      //
      carapace.servers[desired] = self;

      carapace.emit('carapace::port', {
        id: carapace.id,
        addr: address,
        port: port,
        desired: desired
      });

      process.nextTick(function () {
        self.emit('listening');
      });
    }

    function onError(err) {
      //
      // We failed to listen. Unless it's not EADDRINUSE lets try doing the
      // same thing, just with next port.
      //

      self.removeListener('listening', onListen);

      //
      // We can safely restore these listeners here. We're going to call
      // `ourFunction`, so they will be removed again anyway.
      //
      restoreErrorListeners();
      restoreListeningListeners();

      if (err.code !== 'EADDRINUSE') {
        self.close();
        return self.emit('error', err);
      }

      ourListen.call(self, address, nextPort(port), addressType, desired);
    }

    self.once('listening', onListen);
    self.once('error', onError);

    //
    // Call original _listen2 function.
    //
    process.nextTick(function () {
      _listen2.call(self, address, port, addressType);
    });
  };
};

<commit_msg>[refactor api] Emit `port` instead of `carapace::port`<commit_after>/*
 * net.js: Wrapper around node.js core `net` module for observing relevant events
 *
 * (C) 2011 Nodejitsu Inc.
 *
 */

var net = require('net'),
    carapace = require('./carapace');

module.exports = function overrideNet() {
  //
  // Helper function from Node code to parse port arguments
  // passed to net.prototype.Server.listen
  //
  function toPort(x) {
    return (x = Number(x)) >= 0 ? x : false;
  }

  //
  // ### function nextPort (port)
  // #### @port {Number} Port to increment from.
  // Gets the next port in sequence from the
  // specified `port`.
  //
  function nextPort(port) {
    if (!port) {
      return 8000;
    }

    //
    // Find the next port that we are not supposed to ignore or cause errors on
    //
    var unavailable = carapace.ports.ignore.concat(carapace.ports.throw);
    do {
      port = port + 1;
    } while (unavailable.indexOf(port) !== -1);

    return port;
  }

  //
  // Internal mapping of server instances to
  // ports that have been mapped via `.listen()`.
  //
  carapace.servers = {};

  var _listen2 = net.Server.prototype._listen2;
  net.Server.prototype._listen2 = function ourListen(address, port, addressType, desired) {
    var self = this;

    port = toPort(port);
    desired || (desired = port);

    //
    // Always throw if our desired port was one that should always throw
    //
    if (carapace.ports.throw.indexOf(port) !== -1) {
      self.close();
      //
      // Build fake error
      //
      err = new Error('EADDRINUSE, Address already in use');
      err.code = 'EADDRINUSE';
      err.syscall = 'bind';
      err.errno = 100;
      return self.emit('error', err);
    }
    //
    // Since desired is not on a throwing port
    // we want to skip ports in both throw and ignore
    //
    port || (port = nextPort(port));

    //
    // We rely on `error` event to check if address it taken/available, however
    // user may want to hook up to `error` in his application as well (and
    // usually exit when it's emitted). This messes things up. Here we store
    // `error` event listeners and remove them. They will be restored after we
    // start listening or get an error which is not `EADDRINUSE`.
    //
    var errorListeners = self.listeners('error');
    self.removeAllListeners('error');

    function restoreErrorListeners() {
      errorListeners.forEach(function (listener) {
        self.on('error', listener);
      });
    }

    //
    // Problem with `listening` events is a bit different. We want to ensure
    // that we first emit `carapace::port` and *then* the proper `listening`
    // event (which can be consumed by user's app).
    //
    // (Also, not doing so breaks `net/net-multiple-servers-test` test.)
    //
    var listeningListeners = self.listeners('listening');
    self.removeAllListeners('listening');

    function restoreListeningListeners() {
      listeningListeners.forEach(function (listener) {
        self.on('listening', listener);
      });
    }

    function onListen() {
      //
      // Yay, we made it! Lets restore `error` listeners and tell the world
      // that we totally owned this port.
      //

      self.removeListener('error', onError);

      restoreErrorListeners();
      restoreListeningListeners();

      //
      // Store the server that has listened on the `desired` port
      // on the carapace itself, indexed by port.
      //
      carapace.servers[desired] = self;

      carapace.emit('port', {
        id: carapace.id,
        addr: address,
        port: port,
        desired: desired
      });

      process.nextTick(function () {
        self.emit('listening');
      });
    }

    function onError(err) {
      //
      // We failed to listen. Unless it's not EADDRINUSE lets try doing the
      // same thing, just with next port.
      //

      self.removeListener('listening', onListen);

      //
      // We can safely restore these listeners here. We're going to call
      // `ourFunction`, so they will be removed again anyway.
      //
      restoreErrorListeners();
      restoreListeningListeners();

      if (err.code !== 'EADDRINUSE') {
        self.close();
        return self.emit('error', err);
      }

      ourListen.call(self, address, nextPort(port), addressType, desired);
    }

    self.once('listening', onListen);
    self.once('error', onError);

    //
    // Call original _listen2 function.
    //
    process.nextTick(function () {
      _listen2.call(self, address, port, addressType);
    });
  };
};

<|endoftext|>


<commit_before>const url = require('url')
const {HTTP} = require('http-call')
const config = require('./config')
const redis = require('./redis')
const warn = require('./warn')
const {cacheKey} = require('./cache')

function getAuthHeader () {
  if (config.npm.basic) {
    return `Basic ${config.npm.basic}`
  } else if (config.npm.token) {
    return `Bearer ${config.npm.token}`
  }
}

async function isEtagFresh (name, etag) {
  try {
    let cache = await redis.get(`${cacheKey(name)}/etag`)
    return etag === cache
  } catch (err) {
    warn(err, {pkg: name})
  }
}

async function updateEtag (name, etag) {
  try {
    await redis.setex(`${cacheKey(name)}/etag`, config.cache.packageTTL, etag)
  } catch (err) {
    warn(err, {pkg: name})
  }
}

async function fetchFromCache (name) {
  try {
    let pkg = await redis.zget(cacheKey(name))
    if (pkg) {
      console.log(`${name} found in redis`)
      return JSON.parse(pkg)
    }
  } catch (err) {
    warn(err, {pkg: name})
  }
}

async function updateCache (pkg) {
  if (!redis) return
  try {
    await redis.zsetex(cacheKey(pkg.name), config.cache.packageTTL, JSON.stringify(pkg))
  } catch (err) {
    warn(err, {pkg: pkg.name})
  }
}

function getRequestOpts (etag, headers = {}) {
  let opts = {timeout: config.timeout, headers}
  if (etag) opts.headers['if-none-match'] = etag
  let authHeader = getAuthHeader()
  if (authHeader) opts.headers['Authorization'] = authHeader
  return opts
}

async function get (name, etag) {
  try {
    if (etag && redis && (await isEtagFresh(name, etag))) return 304
    let pkg = redis ? await fetchFromCache(name) : null
    if (pkg) return pkg
    let req = await HTTP.request(url.resolve(config.uplink.href, '/' + name.replace(/\//, '%2F')), getRequestOpts(etag))
    pkg = req.body
    if (!pkg.versions) return 404
    pkg.etag = req.response.headers.etag
    updateCache(pkg)
    return pkg
  } catch (err) {
    switch (err.statusCode) {
      case 304:
        if (redis) updateEtag(name, etag)
        return 304
      case 404:
        return 404
      default:
        warn(err, {pkg: name})
        return 404
    }
  }
}

async function post (path, body) {
  const opts = Object.assign({body}, getRequestOpts())
  const req = await HTTP.post(url.resolve(config.uplink.href, path), opts)
  return req.body
}

function getTarball (name, filename) {
  return HTTP.stream(`${config.uplink.href}${name}/-/${filename}`, getRequestOpts())
}

async function getLatest (name) {
  let pkg = await get(name)
  let v = pkg['dist-tags'].latest
  return pkg.versions[v]
}

module.exports = {
  get,
  post,
  getTarball,
  getLatest
}
<commit_msg>Fix/129 - Packages 404 (#130)<commit_after>const url = require('url')
const {HTTP} = require('http-call')
const config = require('./config')
const redis = require('./redis')
const warn = require('./warn')
const {cacheKey} = require('./cache')

function getAuthHeader () {
  if (config.npm.basic) {
    return `Basic ${config.npm.basic}`
  } else if (config.npm.token) {
    return `Bearer ${config.npm.token}`
  }
}

async function isEtagFresh (name, etag) {
  try {
    let cache = await redis.get(`${cacheKey(name)}/etag`)
    return etag === cache
  } catch (err) {
    warn(err, {pkg: name})
  }
}

async function updateEtag (name, etag) {
  try {
    await redis.setex(`${cacheKey(name)}/etag`, config.cache.packageTTL, etag)
  } catch (err) {
    warn(err, {pkg: name})
  }
}

async function fetchFromCache (name) {
  try {
    let pkg = await redis.zget(cacheKey(name))
    if (pkg) {
      console.log(`${name} found in redis`)
      return JSON.parse(pkg)
    }
  } catch (err) {
    warn(err, {pkg: name})
  }
}

async function updateCache (pkg) {
  if (!redis) return
  try {
    await redis.zsetex(cacheKey(pkg.name), config.cache.packageTTL, JSON.stringify(pkg))
  } catch (err) {
    warn(err, {pkg: pkg.name})
  }
}

function getRequestOpts (etag, headers = {}) {
  let opts = {timeout: config.timeout, headers}
  if (etag) opts.headers['if-none-match'] = etag
  let authHeader = getAuthHeader()
  if (authHeader) opts.headers['Authorization'] = authHeader
  return opts
}

async function get (name, etag) {
  try {
    if (etag && redis && (await isEtagFresh(name, etag))) return 304
    let pkg = redis ? await fetchFromCache(name) : null
    if (pkg) return pkg
    let req = await HTTP.request(url.resolve(config.uplink.href, '/' + name.replace(/\//, '%2F')), getRequestOpts(etag))
    pkg = typeof req.body === 'string' ? JSON.parse(req.body) : req.body
    if (!pkg.versions) return 404
    pkg.etag = req.response.headers.etag
    updateCache(pkg)
    return pkg
  } catch (err) {
    switch (err.statusCode) {
      case 304:
        if (redis) updateEtag(name, etag)
        return 304
      case 404:
        return 404
      default:
        warn(err, {pkg: name})
        return 404
    }
  }
}

async function post (path, body) {
  const opts = Object.assign({body}, getRequestOpts())
  const req = await HTTP.post(url.resolve(config.uplink.href, path), opts)
  return req.body
}

function getTarball (name, filename) {
  return HTTP.stream(`${config.uplink.href}${name}/-/${filename}`, getRequestOpts())
}

async function getLatest (name) {
  let pkg = await get(name)
  let v = pkg['dist-tags'].latest
  return pkg.versions[v]
}

module.exports = {
  get,
  post,
  getTarball,
  getLatest
}
<|endoftext|>


<commit_before>(function (JSUS) {

	function OBJ(){};

    OBJ.equals = function (o1, o2) {

        if (!o1 || !o2) return false;

    	// Check whether arguments are not objects
    	if ( typeof o1 in {number:'',string:''}) {
    		if ( typeof o2 in {number:'',string:''}) {
        		return (o1 === o2);
        	}
    		return false;
    	}
    	else if ( typeof o2 in {number:'',string:''}) {
    		return false;
    	}

      for (var p in o1) {
          if (o1.hasOwnProperty(p)) {

        	  if ('undefined' === typeof o2[p] && 'undefined' !== typeof o1[p]) return false;

        	  switch (typeof o1[p]) {
                  case 'object':
                      if (!OBJ.equals(o1[p],o2[p])) return false;

                  case 'function':
                      if (o1[p].toString() !== o2[p].toString()) return false;

                  default:
                      if (o1[p] !== o2[p]) return false;
              }
          }
      }

      // Check whether o2 has extra properties
      // TODO: improve, some properties have already been checked!
      for (p in o2) {
    	  if (o2.hasOwnProperty(p)) {
    		  if ('undefined' === typeof o1[p] && 'undefined' !== typeof o2[p])
    			  return false;
    	  }
      }

      return true;
    };

	OBJ.getListSize = function (list) {
		var n = 0;
		for (var key in list) {
		    if (list.hasOwnProperty(key)) {
		    	n++;
		    }
		}

		//console.log('Calculated list length ' + n);

		return n;
	};

	OBJ._obj2Array = function(obj, keyed) {
	    var result = [];
	    for (var key in obj) {
	       if (obj.hasOwnProperty(key)) {
	    	   if ( 'object' === typeof obj[key] ) {
					result = result.concat(OBJ._obj2Array(obj[key],keyed));
				}
				else {
					if (keyed) result.push(key);
			        result.push(obj[key]);
				}

	       }
	    }

	    return result;
	};

	OBJ.obj2Array = function (obj) {
	    return OBJ._obj2Array(obj);
	};

	/**
	 * Creates an array containing all keys and values of the obj.
	 */
	OBJ.obj2KeyedArray = function (obj) {
	    return OBJ._obj2Array(obj,true);
	};

	OBJ.objGetAllKeys = function (obj) {
		var result = [];
	    for (var key in obj) {
	       if (obj.hasOwnProperty(key)) {
	    	   result.push(key);
	    	   if ('object' === typeof obj[key]) {
	    		   result = result.concat(OBJ.objGetAllKeys(obj[key]));
	    	   }
	       }
	    }
	    return result;
	};

	/**
	 * Creates an array of key:value objects.
	 *
	 */
	OBJ.implodeObj = function (obj) {
		//console.log(obj);
	    var result = [];
	    for (var key in obj) {
	       if (obj.hasOwnProperty(key)) {
	    	   var o = {};
	    	   o[key] = obj[key];
	           result.push(o);
	           //console.log(o);
	       }
	    }
	    return result;
	};

	/**
	 * Creates a perfect copy of the obj
	 */
	OBJ.clone = function (obj) {
		var clone = {};
		for (var i in obj) {
			if (obj.hasOwnProperty(i)) {
				if ( 'object' === typeof obj[i] ) {
					clone[i] = OBJ.clone(obj[i]);
				}
				else {
					clone[i] = obj[i];
				}
			}
		}
		return clone;
	};

	/**
	 * Performs a left join on the keys of two objects. In case keys overlaps
	 *  the values from obj2 are taken.
	 */
	OBJ.join = function (obj1, obj2) {
		var clone = OBJ.clone(obj1);
		if (!obj2) return clone;
		for (var i in clone) {
			if (clone.hasOwnProperty(i)) {
				if ('undefined' !== typeof obj2[i]) {
					if ( 'object' === typeof obj2[i] ) {
						clone[i] = OBJ.join(clone[i], obj2[i]);
					}
					else {
						clone[i] = obj2[i];
					}
				}
			}
		}
		return clone;
	};

	/**
	 * Merges two objects in one. In case keys overlaps the values from
	 * obj2 are taken.
	 */
	OBJ.merge = function (obj1, obj2) {
		var clone = OBJ.clone(obj1);
//		console.log('CLONE');
//		console.log(clone);
		if (!obj2) return clone;
		for (var i in obj2) {
			if (obj2.hasOwnProperty(i)) {
				//console.log(i);
				if ( 'object' === typeof obj2[i] ) {
					clone[i] = OBJ.merge(obj1[i],obj2[i]);
				}
				else {
					clone[i] = obj2[i];
				}
			}
		}
		return clone;
	};

	/**
	 * Set the.
	 */
	OBJ.mergeOnKey = function (obj1, obj2, key) {
		var clone = OBJ.clone(obj1);
		if (!obj2 || !key) return clone;
		for (var i in obj2) {
			if (obj2.hasOwnProperty(i)) {
				if ( 'object' === typeof obj1[i] ) {
					clone[i][key] = obj2[i];
				}
			}
		}
		return clone;
	};

	OBJ.subobj = function (o, select) {
		if (!o) return false;
		var out = {};
		if (!select) return out;
		for (var i=0; i<select.length;i++) {
			var key = select[i];
			//console.log(key);
			if ('undefined' !== o[key]) {
				out[key] = o[key];
			}
		}
		return out;
	};

	OBJ.mergeOnValue = function (obj1, obj2) {
		return OBJ.mergeOnKey(obj1, obj2, 'value');
	};

	OBJ.setNestedValue = function (str, value, obj) {
		var obj = obj || {};
		var keys = str.split('.');
		if (keys.length === 1) {
			obj[str] = value;
			return obj;
		}
		var k = keys.shift();
		obj[k] = OBJ.setNestedValue(keys.join('.'), value, obj[k]);
		return obj;
	};

	OBJ.getNestedValue = function (str, obj) {
		if (!obj) return;
		var keys = str.split('.');
		if (keys.length === 1) {
			return obj[str];
		}
		var k = keys.shift();
		return OBJ.getNestedValue(keys.join('.'), obj[k]);
	};

	JSUS.extend(OBJ);

})('undefined' !== typeof JSUS ? JSUS : module.parent.exports.JSUS);<commit_msg>Fixed bug with GameDB and NDDB.create. Only two arguments for GameDB now<commit_after>(function (JSUS) {

	function OBJ(){};

    OBJ.equals = function (o1, o2) {

        if (!o1 || !o2) return false;

    	// Check whether arguments are not objects
    	if ( typeof o1 in {number:'',string:''}) {
    		if ( typeof o2 in {number:'',string:''}) {
        		return (o1 === o2);
        	}
    		return false;
    	}
    	else if ( typeof o2 in {number:'',string:''}) {
    		return false;
    	}

      for (var p in o1) {
          if (o1.hasOwnProperty(p)) {

        	  if ('undefined' === typeof o2[p] && 'undefined' !== typeof o1[p]) return false;

        	  switch (typeof o1[p]) {
                  case 'object':
                      if (!OBJ.equals(o1[p],o2[p])) return false;

                  case 'function':
                      if (o1[p].toString() !== o2[p].toString()) return false;

                  default:
                      if (o1[p] !== o2[p]) return false;
              }
          }
      }

      // Check whether o2 has extra properties
      // TODO: improve, some properties have already been checked!
      for (p in o2) {
    	  if (o2.hasOwnProperty(p)) {
    		  if ('undefined' === typeof o1[p] && 'undefined' !== typeof o2[p])
    			  return false;
    	  }
      }

      return true;
    };

	OBJ.getListSize = function (list) {
		var n = 0;
		for (var key in list) {
		    if (list.hasOwnProperty(key)) {
		    	n++;
		    }
		}

		//console.log('Calculated list length ' + n);

		return n;
	};

	OBJ._obj2Array = function(obj, keyed) {
	    var result = [];
	    for (var key in obj) {
	       if (obj.hasOwnProperty(key)) {
	    	   if ( 'object' === typeof obj[key] ) {
					result = result.concat(OBJ._obj2Array(obj[key],keyed));
				}
				else {
					if (keyed) result.push(key);
			        result.push(obj[key]);
				}

	       }
	    }

	    return result;
	};

	OBJ.obj2Array = function (obj) {
	    return OBJ._obj2Array(obj);
	};

	/**
	 * Creates an array containing all keys and values of the obj.
	 */
	OBJ.obj2KeyedArray = function (obj) {
	    return OBJ._obj2Array(obj,true);
	};

	OBJ.objGetAllKeys = function (obj) {
		var result = [];
	    for (var key in obj) {
	       if (obj.hasOwnProperty(key)) {
	    	   result.push(key);
	    	   if ('object' === typeof obj[key]) {
	    		   result = result.concat(OBJ.objGetAllKeys(obj[key]));
	    	   }
	       }
	    }
	    return result;
	};

	/**
	 * Creates an array of key:value objects.
	 *
	 */
	OBJ.implodeObj = function (obj) {
		//console.log(obj);
	    var result = [];
	    for (var key in obj) {
	       if (obj.hasOwnProperty(key)) {
	    	   var o = {};
	    	   o[key] = obj[key];
	           result.push(o);
	           //console.log(o);
	       }
	    }
	    return result;
	};

	/**
	 * Creates a perfect copy of the obj
	 */
	OBJ.clone = function (obj) {
		if (!obj) return;
		var clone = {};
		for (var i in obj) {
			if (obj.hasOwnProperty(i)) {
				if ( 'object' === typeof obj[i] ) {
					clone[i] = OBJ.clone(obj[i]);
				}
				else {
					clone[i] = obj[i];
				}
			}
		}
		return clone;
	};

	/**
	 * Performs a left join on the keys of two objects. In case keys overlaps
	 *  the values from obj2 are taken.
	 */
	OBJ.join = function (obj1, obj2) {
		var clone = OBJ.clone(obj1);
		if (!obj2) return clone;
		for (var i in clone) {
			if (clone.hasOwnProperty(i)) {
				if ('undefined' !== typeof obj2[i]) {
					if ( 'object' === typeof obj2[i] ) {
						clone[i] = OBJ.join(clone[i], obj2[i]);
					}
					else {
						clone[i] = obj2[i];
					}
				}
			}
		}
		return clone;
	};

	/**
	 * Merges two objects in one. In case keys overlaps the values from
	 * obj2 are taken.
	 */
	OBJ.merge = function (obj1, obj2) {
		var clone = OBJ.clone(obj1);
//		console.log('CLONE');
//		console.log(clone);
		if (!obj2) return clone;
		for (var i in obj2) {
			if (obj2.hasOwnProperty(i)) {
				//console.log(i);
				if ( 'object' === typeof obj2[i] ) {
					clone[i] = OBJ.merge(obj1[i],obj2[i]);
				}
				else {
					clone[i] = obj2[i];
				}
			}
		}
		return clone;
	};

	/**
	 * Set the.
	 */
	OBJ.mergeOnKey = function (obj1, obj2, key) {
		var clone = OBJ.clone(obj1);
		if (!obj2 || !key) return clone;
		for (var i in obj2) {
			if (obj2.hasOwnProperty(i)) {
				if ( 'object' === typeof obj1[i] ) {
					clone[i][key] = obj2[i];
				}
			}
		}
		return clone;
	};

	OBJ.subobj = function (o, select) {
		if (!o) return false;
		var out = {};
		if (!select) return out;
		for (var i=0; i<select.length;i++) {
			var key = select[i];
			//console.log(key);
			if ('undefined' !== o[key]) {
				out[key] = o[key];
			}
		}
		return out;
	};

	OBJ.mergeOnValue = function (obj1, obj2) {
		return OBJ.mergeOnKey(obj1, obj2, 'value');
	};

	OBJ.setNestedValue = function (str, value, obj) {
		var obj = obj || {};
		var keys = str.split('.');
		if (keys.length === 1) {
			obj[str] = value;
			return obj;
		}
		var k = keys.shift();
		obj[k] = OBJ.setNestedValue(keys.join('.'), value, obj[k]);
		return obj;
	};

	OBJ.getNestedValue = function (str, obj) {
		if (!obj) return;
		var keys = str.split('.');
		if (keys.length === 1) {
			return obj[str];
		}
		var k = keys.shift();
		return OBJ.getNestedValue(keys.join('.'), obj[k]);
	};

	JSUS.extend(OBJ);

})('undefined' !== typeof JSUS ? JSUS : module.parent.exports.JSUS);<|endoftext|>