<commit_before>(function (exports) {
catcorr.version = "0.1.0";

exports.catcorr = catcorr;
function catcorr(div_id, data) {
    var questions = data.questions;
    var responses = data.responses;

    // create the label2index lookup for quickly calculating the
    // x-coordinate on survey answers
    var label2index = {};
    questions.forEach(function (q, i) {
	label2index[q.number] = {};
	q.choices.forEach(function (choice, j) {
	    label2index[q.number][choice] = j;
	});
    });

    // re-cast non-numeric answers into the corresponding number in
    // label2index so that this whole crossfilter bizness works
    responses.forEach(function (r, i) {
	questions.forEach(function (q, j) {
	    r[q.number] = label2index[q.number][r[q.number]];
	});
    });

    // add the questions text
    questions.forEach(function (q, i) {
    	d3.select(div_id)
    	    .append("div")
    	    .attr("id", q.number+"-chart")
    	    .attr("class", "catcorr chart")
    	    .append("div")
    	    .attr("class", "title")
    	    .text(q.number+'. '+q.text);
    });

    // Various formatters.
    var formatNumber = d3.format(",d");

    // Create the crossfilter for the relevant dimensions and groups.
    var respondents = crossfilter(responses),
        all = respondents.groupAll();
    var dimensions = [];
    var groups = [];
    questions.forEach(function (q, i) {
    	dimensions.push(respondents.dimension(function(d){return d[q.number]}));
    	groups.push(dimensions[i].group());
    });

    // record the total number of respondents in each group. this is
    // used later to correctly figure out the proportionPath lines
    // below
    groups.forEach(function (g, i) {
    	g.__all__ = g.all().map(function (o) {return o.value});
    });

    // create a chart for each dimension
    var xscales = [], xscale, yscales = [], yscale;
    var charts = [], chart;
    var bar_width = 80,
    tick_label_width=bar_width,
    tick_label_height=20,
    first_pass;
    questions.forEach(function (q, i) {

    	// get the labels for this axis
    	var labels = {};
	q.choices.forEach(function (choice, c) {
	    labels[c] = choice;
	});

    	// create the scale
    	var a=0, b=q.choices.length-1;
    	xscale = d3.scale.linear()
            .domain([-0.5, b+0.5])
            .rangeRound([0, bar_width*((b-a)+1)])
    	xscale.labels = labels;
    	xscales.push(xscale);

    	// only scale the y-axis once
        yscale = d3.scale.linear()
    	    .range([100, 0])
    	    .domain([0, groups[i].top(1)[0].value]);
    	yscales.push(yscale);

    	// create the chart
    	chart = barChart(q).dimension(dimensions[i])
    	    .group(groups[i])
    	    .x(xscale);
    	charts.push(chart);

    });

    // Given our array of charts, which we assume are in the same order as the
    // .chart elements in the DOM, bind the charts to the DOM and render them.
    // We also listen to the chart's brush events to update the display.
    var chart = d3.selectAll(".catcorr.chart")
    	.data(charts)
    	.each(function(chart) {
    	    chart.on("brush", renderAll)
    		.on("brushend", renderAll);
    	});

    // add an  element that displays fraction of elements
    // currently selected
    d3.select(div_id)
	.append("aside")
	.attr("id", "totals")
        .attr("class", "catcorr")
	.html("you've selected
 - / -
 respondents.")

    // Render the total.
    d3.selectAll("aside.catcorr #total")
    	.text(formatNumber(respondents.size()));

    renderAll();

    // Renders the specified chart or list.
    function render(method) {
    	d3.select(this).call(method);
    }

    // Whenever the brush moves, re-rendering everything.
    function renderAll() {
    	chart.each(render);
    	d3.select("aside.catcorr #active").text(formatNumber(all.value()));
    }

    window.filter = function(filters) {
    	filters.forEach(function(d, i) { charts[i].filter(d); });
    	renderAll();
    };

    window.reset = function(i) {
    	charts[i].filter(null);
    	renderAll();
    };

    function barChart(question) {
    	if (!barChart.id) barChart.id = 0;

    	var margin = {top: 10, right: 10, bottom: 20, left: 10},
        x,
        y = yscales[barChart.id],
        id = barChart.id++,
        axis = d3.svg.axis().orient("bottom").tickSize(6,0,0),
        brush = d3.svg.brush(),
        brushDirty,
        dimension,
        group,
        round;

    	function chart(div) {
    	    var width = d3.max(x.range()),
            height = d3.max(y.range());

	    // create ticks at these particular values
    	    axis.tickValues(d3.range(0,d3.keys(x.labels).length));

    	// d3.entries(reverse_lookup).forEach(function (o) {
    	//     labels[o.value] = o.key;
    	// });
	// console.log(labels);

    	    // // don't rescale the y-axis. can always revert if it
    	    // // becomes too difficult to see actual numbers, but
    	    // // this is necessary in order to display bars for all
    	    // // people.
    	    // y.domain([0, group.top(1)[0].value]);

    	    div.each(function() {
    		var div = d3.select(this),
    		g = div.select("g");

    		// Create the skeletal chart.
    		if (g.empty()) {
    		    div.select(".title").append("a")
    			.attr("href", "javascript:reset(" + id + ")")
    			.attr("class", "catcorr reset")
    			.text("reset")
    			.style("display", "none");

    		    g = div.append("svg")
    			.attr("width", width + margin.left + margin.right)
    			.attr("height", height + margin.top + margin.bottom)
    			.append("g")
    			.attr("transform", "translate(" + margin.left + "," + margin.top + ")");

    		    g.append("clipPath")
    			.attr("id", "clip-" + id)
    			.append("rect")
    			.attr("width", width)
    			.attr("height", height);

    		    g.selectAll(".bar")
    			.data(["all_background", "background", "foreground",
    			      "all_proportion"])
    			.enter().append("path")
    			.attr("class", function(d, i) {
    			    if (i===0){
    				return "catcorr "+d+" all_bar "+question.type;
    			    }
    			    else if(i===3) {
    				return "catcorr "+d+" all_bar "+question.type;
    			    }
    			    return "catcorr "+d+" bar "+question.type;
    			})
    			.datum(group.all());

    		    g.selectAll(".foreground.bar")
    			.attr("clip-path", "url(#clip-" + id + ")");

    		    g.append("g")
    		    	.attr("class", "catcorr axis")
    		    	.attr("transform", "translate(0," + height + ")")
    		    	.call(axis);

    		    // manipulate the axis label text
    		    g.selectAll("g.axis text")
    		    	.text(function (d) {
    		    	    var n = 20;
    		    	    var s = x.labels[d];
    		    	    if (s===undefined) {
    		    		return '';
    		    	    }
    		    	    else if (s.length > n) {
    		    	    	var parts = s.substring(0,n-3).split(" ");
    		    	    	s = parts.slice(0,parts.length-1).join(" ");
    		    	    	s += "...";
    		    	    }
    		    	    return s;
    		    	})

    		    // Initialize the brush component with pretty
    		    // resize handles.
    		    var gBrush = g.append("g")
    			.attr("class", "catcorr brush")
    			.call(brush);
    		    gBrush.selectAll("rect")
    			.attr("height", height);
    		    gBrush.selectAll(".resize")
    			.append("path")
    			.attr("d", resizePath);
    		}

    		// Only redraw the brush if set externally.
    		if (brushDirty) {
    		    brushDirty = false;
    		    g.selectAll(".brush")
    			.call(brush);
    		    div.select(".title a")
    			.style("display", brush.empty() ? "none" : null);
    		    if (brush.empty()) {
    			g.selectAll("#clip-" + id + " rect")
    			    .attr("x", 0)
    			    .attr("width", width);
    		    } else {
    			var extent = brush.extent();
    			g.selectAll("#clip-" + id + " rect")
    			    .attr("x", x(extent[0]))
    			    .attr("width", x(extent[1]) - x(extent[0]));
    		    }
    		}

    		// this is what actually uses the group data to set
    		// the path. good.
    		g.selectAll(".bar").attr("d", barPath);

    		// only render the .all_bar data once at the beginning
    		g.selectAll(".all_background.all_bar")
		    .attr("d", function (groups, i) {
    		    var v = d3.select(this).attr("d");
    		    if (v===null) {
    			return barPath(groups, i);
    		    }
    		    return v;
    		});

    		// render the .all_proportion.all_bar to show the proportion of
    		g.selectAll(".all_proportion.all_bar")
    		    .attr("d", proportionPath);

    	    });

    	    function barPath(groups) {
    		var path = [],
    		i = -1,
    		n = groups.length,
    		d;
    		while (++i < n) {
    		    d = groups[i];
    		    path.push("M", x(i-0.5)+1, ",",
    			      height, "V", y(d.value), "h",bar_width-2,
    			      "V", height);
    		}
    		return path.join("");
    	    }

    	    function proportionPath(groups) {
    		var path = [],
    		i = -1,
    		n = groups.length,
    		g, p,
    		a = all.value();
    		while (++i < n) {
    		    g = groups[i];
    		    p = a/responses.length*group.__all__[i];
    		    path.push("M", x(i-0.5), ",", y(p), "h", bar_width);
    		}
    		return path.join("");
    	    }

    	    function resizePath(d) {
    		var e = +(d == "e"),
    		x = e ? 1 : -1,
    		y = height / 3;
    		return "M" + (.5 * x) + "," + y
    		    + "A6,6 0 0 " + e + " " + (6.5 * x) + "," + (y + 6)
    		    + "V" + (2 * y - 6)
    		    + "A6,6 0 0 " + e + " " + (.5 * x) + "," + (2 * y)
    		    + "Z"
    		    + "M" + (2.5 * x) + "," + (y + 8)
    		    + "V" + (2 * y - 8)
    		    + "M" + (4.5 * x) + "," + (y + 8)
    		    + "V" + (2 * y - 8);
    	    }
    	}

    	brush.on("brushstart.chart", function() {
    	    var div = d3.select(this.parentNode.parentNode.parentNode);
    	    div.select(".title a").style("display", null);
    	});

    	brush.on("brush.chart", function() {
    	    var g = d3.select(this.parentNode),
            extent = brush.extent();
    	    if (round) {
    		g.select(".brush")
    		    .call(brush.extent(extent = extent.map(round)))
    		    .selectAll(".resize")
    		    .style("display", null);
    	    }
    	    g.select("#clip-" + id + " rect")
    		.attr("x", x(extent[0]))
    		.attr("width", x(extent[1]) - x(extent[0]));

    	    dimension.filterRange(extent);
    	});

    	brush.on("brushend.chart", function() {
    	    if (brush.empty()) {
    		var div = d3.select(this.parentNode.parentNode.parentNode);
    		div.select(".title a").style("display", "none");
    		div.select("#clip-" + id + " rect")
    		    .attr("x", null)
    		    .attr("width", "100%");
    		dimension.filterAll();
    	    }
    	});

    	// jasondavies fanciness. binding methods to this function
    	chart.margin = function(_) {
    	    if (!arguments.length) return margin;
    	    margin = _;
    	    return chart;
    	};
    	chart.x = function(_) {
    	    if (!arguments.length) return x;
    	    x = _;
    	    axis.scale(x);
    	    brush.x(x);
    	    return chart;
    	};
    	chart.y = function(_) {
    	    if (!arguments.length) return y;
    	    y = _;
    	    return chart;
    	};
    	chart.dimension = function(_) {
    	    if (!arguments.length) return dimension;
    	    dimension = _;
    	    return chart;
    	};
    	chart.filter = function(_) {
    	    if (_) {
    		brush.extent(_);
    		dimension.filterRange(_);
    	    } else {
    		brush.clear();
    		dimension.filterAll();
    	    }
    	    brushDirty = true;
    	    return chart;
    	};
    	chart.group = function(_) {
    	    if (!arguments.length) return group;
    	    group = _;
    	    return chart;
    	};
    	chart.round = function(_) {
    	    if (!arguments.length) return round;
    	    round = _;
    	    return chart;
    	};

    	return d3.rebind(chart, brush, "on");
    }
};
})(this)<commit_msg>fix the bars now that the full axis is drawn<commit_after>(function (exports) {
catcorr.version = "0.1.0";

exports.catcorr = catcorr;
function catcorr(div_id, data) {
    var questions = data.questions;
    var responses = data.responses;

    // create the label2index lookup for quickly calculating the
    // x-coordinate on survey answers
    var label2index = {};
    questions.forEach(function (q, i) {
	label2index[q.number] = {};
	q.choices.forEach(function (choice, j) {
	    label2index[q.number][choice] = j;
	});
    });

    // re-cast non-numeric answers into the corresponding number in
    // label2index so that this whole crossfilter bizness works
    responses.forEach(function (r, i) {
	questions.forEach(function (q, j) {
	    r[q.number] = label2index[q.number][r[q.number]];
	});
    });

    // add the questions text
    questions.forEach(function (q, i) {
    	d3.select(div_id)
    	    .append("div")
    	    .attr("id", q.number+"-chart")
    	    .attr("class", "catcorr chart")
    	    .append("div")
    	    .attr("class", "title")
    	    .text(q.number+'. '+q.text);
    });

    // Various formatters.
    var formatNumber = d3.format(",d");

    // Create the crossfilter for the relevant dimensions and groups.
    var respondents = crossfilter(responses),
        all = respondents.groupAll();
    var dimensions = [];
    var groups = [];
    questions.forEach(function (q, i) {
    	dimensions.push(respondents.dimension(function(d){return d[q.number]}));
    	groups.push(dimensions[i].group());
    });

    // record the total number of respondents in each group. this is
    // used later to correctly figure out the proportionPath lines
    // below
    groups.forEach(function (g, i) {
    	g.__all__ = g.all().map(function (o) {return o.value});
    });

    // create a chart for each dimension
    var xscales = [], xscale, yscales = [], yscale;
    var charts = [], chart;
    var bar_width = 80,
    tick_label_width=bar_width,
    tick_label_height=20,
    first_pass;
    questions.forEach(function (q, i) {

    	// get the labels for this axis
    	var labels = {};
	q.choices.forEach(function (choice, c) {
	    labels[c] = choice;
	});

    	// create the scale
    	var a=0, b=q.choices.length-1;
    	xscale = d3.scale.linear()
            .domain([-0.5, b+0.5])
            .rangeRound([0, bar_width*((b-a)+1)])
    	xscale.labels = labels;
    	xscales.push(xscale);

    	// only scale the y-axis once
        yscale = d3.scale.linear()
    	    .range([100, 0])
    	    .domain([0, groups[i].top(1)[0].value]);
    	yscales.push(yscale);

    	// create the chart
    	chart = barChart(q).dimension(dimensions[i])
    	    .group(groups[i])
    	    .x(xscale);
    	charts.push(chart);

    });

    // Given our array of charts, which we assume are in the same order as the
    // .chart elements in the DOM, bind the charts to the DOM and render them.
    // We also listen to the chart's brush events to update the display.
    var chart = d3.selectAll(".catcorr.chart")
    	.data(charts)
    	.each(function(chart) {
    	    chart.on("brush", renderAll)
    		.on("brushend", renderAll);
    	});

    // add an  element that displays fraction of elements
    // currently selected
    d3.select(div_id)
	.append("aside")
	.attr("id", "totals")
        .attr("class", "catcorr")
	.html("you've selected
 - / -
 respondents.")

    // Render the total.
    d3.selectAll("aside.catcorr #total")
    	.text(formatNumber(respondents.size()));

    renderAll();

    // Renders the specified chart or list.
    function render(method) {
    	d3.select(this).call(method);
    }

    // Whenever the brush moves, re-rendering everything.
    function renderAll() {
    	chart.each(render);
    	d3.select("aside.catcorr #active").text(formatNumber(all.value()));
    }

    window.filter = function(filters) {
    	filters.forEach(function(d, i) { charts[i].filter(d); });
    	renderAll();
    };

    window.reset = function(i) {
    	charts[i].filter(null);
    	renderAll();
    };

    function barChart(question) {
    	if (!barChart.id) barChart.id = 0;

    	var margin = {top: 10, right: 10, bottom: 20, left: 10},
        x,
        y = yscales[barChart.id],
        id = barChart.id++,
        axis = d3.svg.axis().orient("bottom").tickSize(6,0,0),
        brush = d3.svg.brush(),
        brushDirty,
        dimension,
        group,
        round;

    	function chart(div) {
    	    var width = d3.max(x.range()),
            height = d3.max(y.range());

	    // create ticks at these particular values
    	    axis.tickValues(d3.range(0,d3.keys(x.labels).length));

    	    // // don't rescale the y-axis. can always revert if it
    	    // // becomes too difficult to see actual numbers, but
    	    // // this is necessary in order to display bars for all
    	    // // people.
    	    // y.domain([0, group.top(1)[0].value]);

    	    div.each(function() {
    		var div = d3.select(this),
    		g = div.select("g");

    		// Create the skeletal chart.
    		if (g.empty()) {
    		    div.select(".title").append("a")
    			.attr("href", "javascript:reset(" + id + ")")
    			.attr("class", "catcorr reset")
    			.text("reset")
    			.style("display", "none");

    		    g = div.append("svg")
    			.attr("width", width + margin.left + margin.right)
    			.attr("height", height + margin.top + margin.bottom)
    			.append("g")
    			.attr("transform", "translate(" + margin.left + "," + margin.top + ")");

    		    g.append("clipPath")
    			.attr("id", "clip-" + id)
    			.append("rect")
    			.attr("width", width)
    			.attr("height", height);

    		    g.selectAll(".bar")
    			.data(["all_background", "background", "foreground",
    			      "all_proportion"])
    			.enter().append("path")
    			.attr("class", function(d, i) {
    			    if (i===0){
    				return "catcorr "+d+" all_bar "+question.type;
    			    }
    			    else if(i===3) {
    				return "catcorr "+d+" all_bar "+question.type;
    			    }
    			    return "catcorr "+d+" bar "+question.type;
    			})
    			.datum(group.all());

    		    g.selectAll(".foreground.bar")
    			.attr("clip-path", "url(#clip-" + id + ")");

    		    g.append("g")
    		    	.attr("class", "catcorr axis")
    		    	.attr("transform", "translate(0," + height + ")")
    		    	.call(axis);

    		    // manipulate the axis label text
    		    g.selectAll("g.axis text")
    		    	.text(function (d) {
    		    	    var n = 20;
    		    	    var s = x.labels[d];
    		    	    if (s===undefined) {
    		    		return '';
    		    	    }
    		    	    else if (s.length > n) {
    		    	    	var parts = s.substring(0,n-3).split(" ");
    		    	    	s = parts.slice(0,parts.length-1).join(" ");
    		    	    	s += "...";
    		    	    }
    		    	    return s;
    		    	})

    		    // Initialize the brush component with pretty
    		    // resize handles.
    		    var gBrush = g.append("g")
    			.attr("class", "catcorr brush")
    			.call(brush);
    		    gBrush.selectAll("rect")
    			.attr("height", height);
    		    gBrush.selectAll(".resize")
    			.append("path")
    			.attr("d", resizePath);
    		}

    		// Only redraw the brush if set externally.
    		if (brushDirty) {
    		    brushDirty = false;
    		    g.selectAll(".brush")
    			.call(brush);
    		    div.select(".title a")
    			.style("display", brush.empty() ? "none" : null);
    		    if (brush.empty()) {
    			g.selectAll("#clip-" + id + " rect")
    			    .attr("x", 0)
    			    .attr("width", width);
    		    } else {
    			var extent = brush.extent();
    			g.selectAll("#clip-" + id + " rect")
    			    .attr("x", x(extent[0]))
    			    .attr("width", x(extent[1]) - x(extent[0]));
    		    }
    		}

    		// this is what actually uses the group data to set
    		// the path. good.
    		g.selectAll(".bar").attr("d", barPath);

    		// only render the .all_bar data once at the beginning
    		g.selectAll(".all_background.all_bar")
		    .attr("d", function (groups, i) {
    		    var v = d3.select(this).attr("d");
    		    if (v===null) {
    			return barPath(groups, i);
    		    }
    		    return v;
    		});

    		// render the .all_proportion.all_bar to show the proportion of
    		g.selectAll(".all_proportion.all_bar")
    		    .attr("d", proportionPath);

    	    });

    	    function barPath(groups) {
    		var path = [],
    		i = -1,
    		n = groups.length,
    		d;
    		while (++i < n) {
    		    d = groups[i];
    		    path.push("M", x(d.key-0.5)+1, ",",
    			      height, "V", y(d.value), "h",bar_width-2,
    			      "V", height);
    		}
    		return path.join("");
    	    }

    	    function proportionPath(groups) {
    		var path = [],
    		i = -1,
    		n = groups.length,
    		g, p,
    		a = all.value();
    		while (++i < n) {
    		    g = groups[i];
    		    p = a/responses.length*group.__all__[i];
    		    path.push("M", x(g.key-0.5), ",", y(p), "h", bar_width);
    		}
    		return path.join("");
    	    }

    	    function resizePath(d) {
    		var e = +(d == "e"),
    		x = e ? 1 : -1,
    		y = height / 3;
    		return "M" + (.5 * x) + "," + y
    		    + "A6,6 0 0 " + e + " " + (6.5 * x) + "," + (y + 6)
    		    + "V" + (2 * y - 6)
    		    + "A6,6 0 0 " + e + " " + (.5 * x) + "," + (2 * y)
    		    + "Z"
    		    + "M" + (2.5 * x) + "," + (y + 8)
    		    + "V" + (2 * y - 8)
    		    + "M" + (4.5 * x) + "," + (y + 8)
    		    + "V" + (2 * y - 8);
    	    }
    	}

    	brush.on("brushstart.chart", function() {
    	    var div = d3.select(this.parentNode.parentNode.parentNode);
    	    div.select(".title a").style("display", null);
    	});

    	brush.on("brush.chart", function() {
    	    var g = d3.select(this.parentNode),
            extent = brush.extent();
    	    if (round) {
    		g.select(".brush")
    		    .call(brush.extent(extent = extent.map(round)))
    		    .selectAll(".resize")
    		    .style("display", null);
    	    }
    	    g.select("#clip-" + id + " rect")
    		.attr("x", x(extent[0]))
    		.attr("width", x(extent[1]) - x(extent[0]));

    	    dimension.filterRange(extent);
    	});

    	brush.on("brushend.chart", function() {
    	    if (brush.empty()) {
    		var div = d3.select(this.parentNode.parentNode.parentNode);
    		div.select(".title a").style("display", "none");
    		div.select("#clip-" + id + " rect")
    		    .attr("x", null)
    		    .attr("width", "100%");
    		dimension.filterAll();
    	    }
    	});

    	// jasondavies fanciness. binding methods to this function
    	chart.margin = function(_) {
    	    if (!arguments.length) return margin;
    	    margin = _;
    	    return chart;
    	};
    	chart.x = function(_) {
    	    if (!arguments.length) return x;
    	    x = _;
    	    axis.scale(x);
    	    brush.x(x);
    	    return chart;
    	};
    	chart.y = function(_) {
    	    if (!arguments.length) return y;
    	    y = _;
    	    return chart;
    	};
    	chart.dimension = function(_) {
    	    if (!arguments.length) return dimension;
    	    dimension = _;
    	    return chart;
    	};
    	chart.filter = function(_) {
    	    if (_) {
    		brush.extent(_);
    		dimension.filterRange(_);
    	    } else {
    		brush.clear();
    		dimension.filterAll();
    	    }
    	    brushDirty = true;
    	    return chart;
    	};
    	chart.group = function(_) {
    	    if (!arguments.length) return group;
    	    group = _;
    	    return chart;
    	};
    	chart.round = function(_) {
    	    if (!arguments.length) return round;
    	    round = _;
    	    return chart;
    	};

    	return d3.rebind(chart, brush, "on");
    }
};
})(this)<|endoftext|>


<commit_before>/**
 *
 */

'use strict';

/**
 *
 * @param pageWalker
 * @constructor
 */
function ImageScraper(pageWalker, imageDirectory) {
	this.pageWalker = pageWalker;
	this.setImageDirectory(imageDirectory);
}

/**
 *
 * @param pageWalker
 */
ImageScraper.prototype.setPageWalker = function (pageWalker) {
	this.pageWalker = pageWalker;
}

ImageScraper.prototype.setImageDirectory = function(imageDirectory) {
	this.imageDirectory = (imageDirectory || '.').replace(/\/?$/, '/');
}

/**
 *
 * @param array queue
 * @param function onDone
 */
ImageScraper.prototype.processQueue = function (queue, onDone) {
	var self = this,
		prefix;
	this.pageWalker.processQueue(
		queue,
		function (item, context) {
			var i;
			// @todo handle file:///
			prefix = context.url.replace(/https?:\/\//g, '').replace(/[/\\:;*?!&()<>#|"`^]/g, '-');
			if (item.selectors.length > 0) {
				for (i = 0; i < item.selectors.length; i++) {
					self._createImage(context.client, item.selectors[i], prefix);
				}
			} else {
				self._createImage(context.client, '', prefix);
			}
		},
		undefined,
		function () {
			if (onDone) {
				onDone();
			}
		}
	);
}

ImageScraper.prototype._createImage = function (webpage, selector, prefix) {
	var clipRect = webpage.clipRect;
	if (selector) {
		webpage.clipRect = webpage.evaluate(function (selector) {
			return document.querySelector(selector).getBoundingClientRect();
		}, selector);
	}
	// @todo use meaningful name (build in calling function)
	webpage.render(this.imageDirectory + prefix + '-' + selector + '.png');
	webpage.clipRect = clipRect;
}

module.exports = ImageScraper;
<commit_msg>add build() method to ImageScraper<commit_after>/**
 *
 */

'use strict';

/**
 *
 * @param pageWalker
 * @constructor
 */
function ImageScraper(pageWalker, imageDirectory) {
	this.pageWalker = pageWalker;
	this.setImageDirectory(imageDirectory);
}

ImageScraper.build = function (webpage) {
	webpage = webpage || require('../webpage.js').create();
	var PageWalker = require('./pagewalker.js');

	return new ImageScraper(new PageWalker(webpage));
}

/**
 *
 * @param pageWalker
 */
ImageScraper.prototype.setPageWalker = function (pageWalker) {
	this.pageWalker = pageWalker;
}

ImageScraper.prototype.setImageDirectory = function(imageDirectory) {
	this.imageDirectory = (imageDirectory || '.').replace(/\/?$/, '/');
}

/**
 *
 * @param array queue
 * @param function onDone
 */
ImageScraper.prototype.processQueue = function (queue, onDone) {
	var self = this,
		prefix;
	this.pageWalker.processQueue(
		queue,
		function (item, context) {
			var i;
			// @todo handle file:///
			prefix = context.url.replace(/https?:\/\//g, '').replace(/[/\\:;*?!&()<>#|"`^]/g, '-');
			if (item.selectors.length > 0) {
				for (i = 0; i < item.selectors.length; i++) {
					self._createImage(context.client, item.selectors[i], prefix);
				}
			} else {
				self._createImage(context.client, '', prefix);
			}
		},
		undefined,
		function () {
			if (onDone) {
				onDone();
			}
		}
	);
}

ImageScraper.prototype._createImage = function (webpage, selector, prefix) {
	var clipRect = webpage.clipRect;
	if (selector) {
		webpage.clipRect = webpage.evaluate(function (selector) {
			return document.querySelector(selector).getBoundingClientRect();
		}, selector);
	}
	// @todo use meaningful name (build in calling function)
	webpage.render(this.imageDirectory + prefix + '-' + selector + '.png');
	webpage.clipRect = clipRect;
}

module.exports = ImageScraper;
<|endoftext|>


<commit_before>var utils = require('./imap.utilities');

exports.convStr = function(str, literals) {
  if (str[0] === '"')
    return str.substring(1, str.length-1);
  else if (str === 'NIL')
    return null;
  else if (/^\d+$/.test(str)) {
    // some IMAP extensions utilize large (64-bit) integers, which JavaScript
    // can't handle natively, so we'll just keep it as a string if it's too big
    var val = parseInt(str, 10);
    return (val.toString() === str ? val : str);
  } else if (literals && literals.lp < literals.length && /^\{\d+\}$/.test(str))
    return literals[literals.lp++];
  else
    return str;
};

exports.parseNamespaces = function(str, literals) {
  var result, vals;
  if (str.length === 3 && str.toUpperCase() === 'NIL')
    vals = null;
  else {
    result = exports.parseExpr(str, literals);
    vals = [];
    for (var i=0,len=result.length; i<len; ++i) {
      var val = {
        prefix: result[i][0],
        delimiter: result[i][1]
      };
      if (result[i].length > 2) {
        // extension data
        val.extensions = [];
        for (var j=2,len2=result[i].length; j<len2; j+=2) {
          val.extensions.push({
            name: result[i][j],
            flags: result[i][j+1]
          });
        }
      }
      vals.push(val);
    }
  }
  return vals;
};

exports.parseFetch = function(str, literals, fetchData) {
  literals.lp = 0;
  var result = exports.parseExpr(str, literals);
  for (var i=0,len=result.length; i<len; i+=2) {
    if (Array.isArray(result[i]))
      result[i] = 'BODY';
    result[i] = result[i].toUpperCase();
    if (result[i] === 'UID')
      fetchData.uid = parseInt(result[i+1], 10);
    else if (result[i] === 'INTERNALDATE')
      fetchData.date = result[i+1];
    else if (result[i] === 'FLAGS')
      fetchData.flags = result[i+1].filter(utils.isNotEmpty);
    else if (result[i] === 'BODYSTRUCTURE')
      fetchData.structure = exports.parseBodyStructure(result[i+1], literals);
    else if (typeof result[i] === 'string') // simple extensions
      fetchData[result[i].toLowerCase()] = result[i+1];
  }
};

exports.parseBodyStructure = function(cur, literals, prefix, partID) {
  var ret = [];
  if (prefix === undefined) {
    var result = (Array.isArray(cur) ? cur : exports.parseExpr(cur, literals));
    if (result.length)
      ret = exports.parseBodyStructure(result, literals, '', 1);
  } else {
    var part, partLen = cur.length, next;
    if (Array.isArray(cur[0])) { // multipart
      next = -1;
      while (Array.isArray(cur[++next])) {
        ret.push(exports.parseBodyStructure(cur[next], literals, prefix
                                                    + (prefix !== '' ? '.' : '')
                                                    + (partID++).toString(), 1));
      }
      part = { type: cur[next++].toLowerCase() };
      if (partLen > next) {
        if (Array.isArray(cur[next])) {
          part.params = {};
          for (var i=0,len=cur[next].length; i<len; i+=2)
            part.params[cur[next][i].toLowerCase()] = cur[next][i+1];
        } else
          part.params = cur[next];
        ++next;
      }
    } else { // single part
      next = 7;
      if (typeof cur[1] === 'string') {
        part = {
          // the path identifier for this part, useful for fetching specific
          // parts of a message
          partID: (prefix !== '' ? prefix : '1'),

          // required fields as per RFC 3501 -- null or otherwise
          type: cur[0].toLowerCase(), subtype: cur[1].toLowerCase(),
          params: null, id: cur[3], description: cur[4], encoding: cur[5],
          size: cur[6]
        };
      } else {
        // type information for malformed multipart body
        part = { type: cur[0].toLowerCase(), params: null };
        cur.splice(1, 0, null);
        ++partLen;
        next = 2;
      }
      if (Array.isArray(cur[2])) {
        part.params = {};
        for (var i=0,len=cur[2].length; i<len; i+=2)
          part.params[cur[2][i].toLowerCase()] = cur[2][i+1];
        if (cur[1] === null)
          ++next;
      }
      if (part.type === 'message' && part.subtype === 'rfc822') {
        // envelope
        if (partLen > next && Array.isArray(cur[next])) {
          part.envelope = {};
          for (var i=0,len=cur[next].length; i<len; ++i) {
            if (i === 0)
              part.envelope.date = cur[next][i];
            else if (i === 1)
              part.envelope.subject = cur[next][i];
            else if (i >= 2 && i <= 7) {
              var val = cur[next][i];
              if (Array.isArray(val)) {
                var addresses = [], inGroup = false, curGroup;
                for (var j=0,len2=val.length; j<len2; ++j) {
                  if (val[j][3] === null) { // start group addresses
                    inGroup = true;
                    curGroup = {
                      group: val[j][2],
                      addresses: []
                    };
                  } else if (val[j][2] === null) { // end of group addresses
                    inGroup = false;
                    addresses.push(curGroup);
                  } else { // regular user address
                    var info = {
                      name: val[j][0],
                      mailbox: val[j][2],
                      host: val[j][3]
                    };
                    if (inGroup)
                      curGroup.addresses.push(info);
                    else
                      addresses.push(info);
                  }
                }
                val = addresses;
              }
              if (i === 2)
                part.envelope.from = val;
              else if (i === 3)
                part.envelope.sender = val;
              else if (i === 4)
                part.envelope['reply-to'] = val;
              else if (i === 5)
                part.envelope.to = val;
              else if (i === 6)
                part.envelope.cc = val;
              else if (i === 7)
                part.envelope.bcc = val;
            } else if (i === 8)
              // message ID being replied to
              part.envelope['in-reply-to'] = cur[next][i];
            else if (i === 9)
              part.envelope['message-id'] = cur[next][i];
            else
              break;
          }
        } else
          part.envelope = null;
        ++next;

        // body
        if (partLen > next && Array.isArray(cur[next])) {
          part.body = exports.parseBodyStructure(cur[next], literals, prefix
                                                    + (prefix !== '' ? '.' : '')
                                                    + (partID++).toString(), 1);
        } else
          part.body = null;
        ++next;
      }
      if ((part.type === 'text'
           || (part.type === 'message' && part.subtype === 'rfc822'))
          && partLen > next)
        part.lines = cur[next++];
      if (typeof cur[1] === 'string' && partLen > next)
        part.md5 = cur[next++];
    }
    // add any extra fields that may or may not be omitted entirely
    exports.parseStructExtra(part, partLen, cur, next);
    ret.unshift(part);
  }
  return ret;
};

exports.parseStructExtra = function(part, partLen, cur, next) {
  if (partLen > next) {
    // disposition
    // null or a special k/v list with these kinds of values:
    // e.g.: ['Foo', null]
    //       ['Foo', ['Bar', 'Baz']]
    //       ['Foo', ['Bar', 'Baz', 'Bam', 'Pow']]
    var disposition = { type: null, params: null };
    if (Array.isArray(cur[next])) {
      disposition.type = cur[next][0];
      if (Array.isArray(cur[next][1])) {
        disposition.params = {};
        for (var i=0,len=cur[next][1].length; i<len; i+=2)
          disposition.params[cur[next][1][i].toLowerCase()] = cur[next][1][i+1];
      }
    } else if (cur[next] !== null)
      disposition.type = cur[next];

    if (disposition.type === null)
      part.disposition = null;
    else
      part.disposition = disposition;

    ++next;
  }
  if (partLen > next) {
    // language can be a string or a list of one or more strings, so let's
    // make this more consistent ...
    if (cur[next] !== null)
      part.language = (Array.isArray(cur[next]) ? cur[next] : [cur[next]]);
    else
      part.language = null;
    ++next;
  }
  if (partLen > next)
    part.location = cur[next++];
  if (partLen > next) {
    // extension stuff introduced by later RFCs
    // this can really be any value: a string, number, or (un)nested list
    // let's not parse it for now ...
    part.extensions = cur[next];
  }
};

/*function isAlpha(ch) {
  if (typeof ch === 'string')
    ch = ch.charCodeAt(0);
  return ((ch >= 65 && ch <= 90) || (ch >= 97 && ch <= 122));
}*/

exports.parseExpr = function(o, literals, result, start) {
  start = start || 0;
  var inQuote = false, lastPos = start - 1, isTop = false;
  if (!result)
    result = [];
  if (typeof o === 'string') {
    o = { str: o };
    isTop = true;
  }
  for (var i=start,len=o.str.length; i<len; ++i) {
    if (!inQuote) {
      if (o.str[i] === '"')
        inQuote = true;
      else if (o.str[i] === ' ' || o.str[i] === ')' || o.str[i] === ']') {
        if (i - (lastPos+1) > 0)
          result.push(exports.convStr(o.str.substring(lastPos+1, i), literals));
        if ((o.str[i] === ')' || o.str[i] === ']') && !isTop)
          return i;
        lastPos = i;
      } else if ((o.str[i] === '(' || o.str[i] === '[')
                 /*&& (i === 0 || !isAlpha(o.str.charCodeAt(i-1)))*/) {
        var innerResult = [];
        i = exports.parseExpr(o, literals, innerResult, i+1);
        lastPos = i;
        result.push(innerResult);
      }
    } else if (o.str[i] === '"' &&
               (o.str[i-1] &&
                (o.str[i-1] !== '\\' || (o.str[i-2] && o.str[i-2] === '\\'))))
      inQuote = false;
    if (i+1 === len && len - (lastPos+1) > 0)
      result.push(exports.convStr(o.str.substring(lastPos+1), literals));
  }
  return (isTop ? result : start);
};
<commit_msg>Remove unused function<commit_after>var utils = require('./imap.utilities');

exports.convStr = function(str, literals) {
  if (str[0] === '"')
    return str.substring(1, str.length-1);
  else if (str === 'NIL')
    return null;
  else if (/^\d+$/.test(str)) {
    // some IMAP extensions utilize large (64-bit) integers, which JavaScript
    // can't handle natively, so we'll just keep it as a string if it's too big
    var val = parseInt(str, 10);
    return (val.toString() === str ? val : str);
  } else if (literals && literals.lp < literals.length && /^\{\d+\}$/.test(str))
    return literals[literals.lp++];
  else
    return str;
};

exports.parseNamespaces = function(str, literals) {
  var result, vals;
  if (str.length === 3 && str.toUpperCase() === 'NIL')
    vals = null;
  else {
    result = exports.parseExpr(str, literals);
    vals = [];
    for (var i=0,len=result.length; i<len; ++i) {
      var val = {
        prefix: result[i][0],
        delimiter: result[i][1]
      };
      if (result[i].length > 2) {
        // extension data
        val.extensions = [];
        for (var j=2,len2=result[i].length; j<len2; j+=2) {
          val.extensions.push({
            name: result[i][j],
            flags: result[i][j+1]
          });
        }
      }
      vals.push(val);
    }
  }
  return vals;
};

exports.parseFetch = function(str, literals, fetchData) {
  literals.lp = 0;
  var result = exports.parseExpr(str, literals);
  for (var i=0,len=result.length; i<len; i+=2) {
    if (Array.isArray(result[i]))
      result[i] = 'BODY';
    result[i] = result[i].toUpperCase();
    if (result[i] === 'UID')
      fetchData.uid = parseInt(result[i+1], 10);
    else if (result[i] === 'INTERNALDATE')
      fetchData.date = result[i+1];
    else if (result[i] === 'FLAGS')
      fetchData.flags = result[i+1].filter(utils.isNotEmpty);
    else if (result[i] === 'BODYSTRUCTURE')
      fetchData.structure = exports.parseBodyStructure(result[i+1], literals);
    else if (typeof result[i] === 'string') // simple extensions
      fetchData[result[i].toLowerCase()] = result[i+1];
  }
};

exports.parseBodyStructure = function(cur, literals, prefix, partID) {
  var ret = [];
  if (prefix === undefined) {
    var result = (Array.isArray(cur) ? cur : exports.parseExpr(cur, literals));
    if (result.length)
      ret = exports.parseBodyStructure(result, literals, '', 1);
  } else {
    var part, partLen = cur.length, next;
    if (Array.isArray(cur[0])) { // multipart
      next = -1;
      while (Array.isArray(cur[++next])) {
        ret.push(exports.parseBodyStructure(cur[next], literals, prefix
                                                    + (prefix !== '' ? '.' : '')
                                                    + (partID++).toString(), 1));
      }
      part = { type: cur[next++].toLowerCase() };
      if (partLen > next) {
        if (Array.isArray(cur[next])) {
          part.params = {};
          for (var i=0,len=cur[next].length; i<len; i+=2)
            part.params[cur[next][i].toLowerCase()] = cur[next][i+1];
        } else
          part.params = cur[next];
        ++next;
      }
    } else { // single part
      next = 7;
      if (typeof cur[1] === 'string') {
        part = {
          // the path identifier for this part, useful for fetching specific
          // parts of a message
          partID: (prefix !== '' ? prefix : '1'),

          // required fields as per RFC 3501 -- null or otherwise
          type: cur[0].toLowerCase(), subtype: cur[1].toLowerCase(),
          params: null, id: cur[3], description: cur[4], encoding: cur[5],
          size: cur[6]
        };
      } else {
        // type information for malformed multipart body
        part = { type: cur[0].toLowerCase(), params: null };
        cur.splice(1, 0, null);
        ++partLen;
        next = 2;
      }
      if (Array.isArray(cur[2])) {
        part.params = {};
        for (var i=0,len=cur[2].length; i<len; i+=2)
          part.params[cur[2][i].toLowerCase()] = cur[2][i+1];
        if (cur[1] === null)
          ++next;
      }
      if (part.type === 'message' && part.subtype === 'rfc822') {
        // envelope
        if (partLen > next && Array.isArray(cur[next])) {
          part.envelope = {};
          for (var i=0,len=cur[next].length; i<len; ++i) {
            if (i === 0)
              part.envelope.date = cur[next][i];
            else if (i === 1)
              part.envelope.subject = cur[next][i];
            else if (i >= 2 && i <= 7) {
              var val = cur[next][i];
              if (Array.isArray(val)) {
                var addresses = [], inGroup = false, curGroup;
                for (var j=0,len2=val.length; j<len2; ++j) {
                  if (val[j][3] === null) { // start group addresses
                    inGroup = true;
                    curGroup = {
                      group: val[j][2],
                      addresses: []
                    };
                  } else if (val[j][2] === null) { // end of group addresses
                    inGroup = false;
                    addresses.push(curGroup);
                  } else { // regular user address
                    var info = {
                      name: val[j][0],
                      mailbox: val[j][2],
                      host: val[j][3]
                    };
                    if (inGroup)
                      curGroup.addresses.push(info);
                    else
                      addresses.push(info);
                  }
                }
                val = addresses;
              }
              if (i === 2)
                part.envelope.from = val;
              else if (i === 3)
                part.envelope.sender = val;
              else if (i === 4)
                part.envelope['reply-to'] = val;
              else if (i === 5)
                part.envelope.to = val;
              else if (i === 6)
                part.envelope.cc = val;
              else if (i === 7)
                part.envelope.bcc = val;
            } else if (i === 8)
              // message ID being replied to
              part.envelope['in-reply-to'] = cur[next][i];
            else if (i === 9)
              part.envelope['message-id'] = cur[next][i];
            else
              break;
          }
        } else
          part.envelope = null;
        ++next;

        // body
        if (partLen > next && Array.isArray(cur[next])) {
          part.body = exports.parseBodyStructure(cur[next], literals, prefix
                                                    + (prefix !== '' ? '.' : '')
                                                    + (partID++).toString(), 1);
        } else
          part.body = null;
        ++next;
      }
      if ((part.type === 'text'
           || (part.type === 'message' && part.subtype === 'rfc822'))
          && partLen > next)
        part.lines = cur[next++];
      if (typeof cur[1] === 'string' && partLen > next)
        part.md5 = cur[next++];
    }
    // add any extra fields that may or may not be omitted entirely
    exports.parseStructExtra(part, partLen, cur, next);
    ret.unshift(part);
  }
  return ret;
};

exports.parseStructExtra = function(part, partLen, cur, next) {
  if (partLen > next) {
    // disposition
    // null or a special k/v list with these kinds of values:
    // e.g.: ['Foo', null]
    //       ['Foo', ['Bar', 'Baz']]
    //       ['Foo', ['Bar', 'Baz', 'Bam', 'Pow']]
    var disposition = { type: null, params: null };
    if (Array.isArray(cur[next])) {
      disposition.type = cur[next][0];
      if (Array.isArray(cur[next][1])) {
        disposition.params = {};
        for (var i=0,len=cur[next][1].length; i<len; i+=2)
          disposition.params[cur[next][1][i].toLowerCase()] = cur[next][1][i+1];
      }
    } else if (cur[next] !== null)
      disposition.type = cur[next];

    if (disposition.type === null)
      part.disposition = null;
    else
      part.disposition = disposition;

    ++next;
  }
  if (partLen > next) {
    // language can be a string or a list of one or more strings, so let's
    // make this more consistent ...
    if (cur[next] !== null)
      part.language = (Array.isArray(cur[next]) ? cur[next] : [cur[next]]);
    else
      part.language = null;
    ++next;
  }
  if (partLen > next)
    part.location = cur[next++];
  if (partLen > next) {
    // extension stuff introduced by later RFCs
    // this can really be any value: a string, number, or (un)nested list
    // let's not parse it for now ...
    part.extensions = cur[next];
  }
};

exports.parseExpr = function(o, literals, result, start) {
  start = start || 0;
  var inQuote = false, lastPos = start - 1, isTop = false;
  if (!result)
    result = [];
  if (typeof o === 'string') {
    o = { str: o };
    isTop = true;
  }
  for (var i=start,len=o.str.length; i<len; ++i) {
    if (!inQuote) {
      if (o.str[i] === '"')
        inQuote = true;
      else if (o.str[i] === ' ' || o.str[i] === ')' || o.str[i] === ']') {
        if (i - (lastPos+1) > 0)
          result.push(exports.convStr(o.str.substring(lastPos+1, i), literals));
        if ((o.str[i] === ')' || o.str[i] === ']') && !isTop)
          return i;
        lastPos = i;
      } else if ((o.str[i] === '(' || o.str[i] === '[')
                 /*&& (i === 0 || !isAlpha(o.str.charCodeAt(i-1)))*/) {
        var innerResult = [];
        i = exports.parseExpr(o, literals, innerResult, i+1);
        lastPos = i;
        result.push(innerResult);
      }
    } else if (o.str[i] === '"' &&
               (o.str[i-1] &&
                (o.str[i-1] !== '\\' || (o.str[i-2] && o.str[i-2] === '\\'))))
      inQuote = false;
    if (i+1 === len && len - (lastPos+1) > 0)
      result.push(exports.convStr(o.str.substring(lastPos+1), literals));
  }
  return (isTop ? result : start);
};
<|endoftext|>


<commit_before>// @remove-on-eject-begin
/**
 * Copyright (c) 2015-present, Facebook, Inc.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 */
// @remove-on-eject-end
'use strict';

// Do this as the first thing so that any code reading it knows the right env.
process.env.BABEL_ENV = 'test';
process.env.NODE_ENV = 'test';
process.env.PUBLIC_URL = '';

// Makes the script crash on unhandled rejections instead of silently
// ignoring them. In the future, promise rejections that are not handled will
// terminate the Node.js process with a non-zero exit code.
process.on('unhandledRejection', err => {
  throw err;
});

// Ensure environment variables are read.
require('../config/env');
// @remove-on-eject-begin
// Do the preflight check (only happens before eject).
const verifyPackageTree = require('./utils/verifyPackageTree');
if (process.env.SKIP_PREFLIGHT_CHECK !== 'true') {
  verifyPackageTree();
}
// @remove-on-eject-end

const jest = require('jest');
const argv = process.argv.slice(2);

// Watch unless on CI or in coverage mode
if (!process.env.CI && argv.indexOf('--coverage') < 0) {
  argv.push('--watch');
}

// @remove-on-eject-begin
// This is not necessary after eject because we embed config into package.json.
const createJestConfig = require('./utils/createJestConfig');
const path = require('path');
const paths = require('../config/paths');
argv.push(
  '--config',
  JSON.stringify(
    createJestConfig(
      relativePath => path.resolve(__dirname, '..', relativePath),
      path.resolve(paths.appSrc, '..'),
      false
    )
  )
);
// @remove-on-eject-end
jest.run(argv);
<commit_msg>Support Jest --watchAll flag (#3804)<commit_after>// @remove-on-eject-begin
/**
 * Copyright (c) 2015-present, Facebook, Inc.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 */
// @remove-on-eject-end
'use strict';

// Do this as the first thing so that any code reading it knows the right env.
process.env.BABEL_ENV = 'test';
process.env.NODE_ENV = 'test';
process.env.PUBLIC_URL = '';

// Makes the script crash on unhandled rejections instead of silently
// ignoring them. In the future, promise rejections that are not handled will
// terminate the Node.js process with a non-zero exit code.
process.on('unhandledRejection', err => {
  throw err;
});

// Ensure environment variables are read.
require('../config/env');
// @remove-on-eject-begin
// Do the preflight check (only happens before eject).
const verifyPackageTree = require('./utils/verifyPackageTree');
if (process.env.SKIP_PREFLIGHT_CHECK !== 'true') {
  verifyPackageTree();
}
// @remove-on-eject-end

const jest = require('jest');
const argv = process.argv.slice(2);

// Watch unless on CI, in coverage mode, or explicitly running all tests
if (
  !process.env.CI &&
  argv.indexOf('--coverage') === -1 &&
  argv.indexOf('--watchAll') === -1
) {
  argv.push('--watch');
}

// @remove-on-eject-begin
// This is not necessary after eject because we embed config into package.json.
const createJestConfig = require('./utils/createJestConfig');
const path = require('path');
const paths = require('../config/paths');
argv.push(
  '--config',
  JSON.stringify(
    createJestConfig(
      relativePath => path.resolve(__dirname, '..', relativePath),
      path.resolve(paths.appSrc, '..'),
      false
    )
  )
);
// @remove-on-eject-end
jest.run(argv);
<|endoftext|>


<commit_before>var assert = require('assert')
var fs = require('fs')
var path = require('path')
var level = require('level')
var hyperdrive = require('hyperdrive')
var raf = require('random-access-file')
var encoding = require('dat-encoding')
var debug = require('debug')('dat-node')

module.exports = function (opts, cb) {
  assert.ok(opts, 'dat-node: lib/init-archive opts required')
  assert.ok(opts.dir, 'dat-node: lib/init-archive dir option required')
  assert.ok(typeof cb === 'function', 'dat-node: lib/init-archive callback function required')

  var archive
  var drive
  var db
  var dir = opts.dir
  var key = opts.key ? encoding.toStr(opts.key) : null
  var dbPath = opts.dbPath || path.join(dir, '.dat')
  var createIfMissing = opts.createIfMissing === false ? opts.createIfMissing : true
  var errorIfExists = opts.errorIfExists || false

  // opts.resume backwards compat. TODO: Remove in v2
  if (opts.resume) createIfMissing = false
  if (opts.resume === false) errorIfExists = true

  if (!opts.file) {
    // TODO: do we always want this set?
    opts.file = function (name, opts) {
      if (archive && archive.secretKey) opts = null
      return raf(path.join(dir, name), opts && typeof opts.length === 'number' && {length: opts.length})
    }
  }

  if (opts.db || opts.drive) {
    drive = opts.drive || hyperdrive(opts.db)
    db = opts.db ? opts.db : drive.core._db
    return checkDriveKeys()
  }

  if (createIfMissing !== false) return createDb()

  try {
    // check if existing dbPath
    if (!fs.statSync(dbPath).isDirectory()) throw new Error('.dat folder not a dir')
    return createDb()
  } catch (e) {
    return cb(new Error('No existing .dat folder'))
  }

  function createDb () {
    debug('Making/Reading archive database')
    level(dbPath, function (err, _db) {
      if (err) return cb(err)
      db = _db
      drive = hyperdrive(db)
      checkDriveKeys()
    })
  }

  function checkDriveKeys () {
    // Try to resume archives if there are keys in the drive
    debug('Reading existing keys in drive')
    drive.core.list(function (err, keys) {
      if (err) return cb(err)

      if (keys.length > 2 && !key) return cb(new Error('Drive has multiple archives. Must specify key.'))
      else if (errorIfExists && keys.length) {
        return db.close(function () {
          cb(new Error('Existing feeds in database.'))
        })
      }

      keys = keys.map(function (val) {
        return encoding.toStr(val)
      })
      debug(`Drive has ${keys.length} existing keys.`)
      if (keys.length) {
        debug('keys:', keys)
      }

      // Error if opts.key is used and doesn't match anything in database
      if (keys.length && key && keys.indexOf(key) === -1) {
        return db.close(function () {
          cb(new Error('Existing archive in database does not match key option.'))
        })
      }

      if (key) {
        debug('Using key option for archive', key)
        archive = drive.createArchive(key, opts)
        archive.resumed = (keys.length === 2) // resumed = true if existing archive
        return doneArchive(keys.length < 2 && key) // do not open if new drive and external key (e.g. downloading)
      } else if (!keys.length) {
        // create a new database + archive
        debug('No existing feeds in drive, creating new archive.')
        archive = drive.createArchive(null, opts)
        archive.resumed = false
        return doneArchive(false) // open archive - no external key so we are making new archive locally
      }
      // opts.key = null && keys.length === 2
      tryOpen()

      function tryOpen () {
        // Just in case: double check our logic here =)
        assert.ok(!key, 'dat-node: lib/init-archive tryOpen should be called if we opts.key is used')
        assert.ok(keys.length && keys.length <= 2, `dat-node: lib/init-archive tryOpen 1-2 values in database, db has ${keys.length}`)

        // Existing Keys, No key Option
        // Guess which key is metadata
        // If first key fails, use other key
        debug('Making archive with key', keys[keys.length - 1].toString('hex'))
        archive = drive.createArchive(keys[keys.length - 1], opts)
        var openTimeout = setTimeout(function () {
          debug('Timeout Open')
          tryOtherKey()
        }, 150)
        archive.open(function (err) {
          clearTimeout(openTimeout)
          if (!err) return doneArchive()
          var badKey = err && (err.message.indexOf('Unknown message type') > -1 || err.message.indexOf('Key not found in database') > -1)
          if (err & !badKey) return cb(err)
          tryOtherKey()
        })
      }

      function tryOtherKey () {
        debug('Bad Key. Trying other key.')
        archive = drive.createArchive(keys[0], opts)
        doneArchive()
      }
    })
  }

  function doneArchive (doNotOpen) {
    debug('Archive initialized')
    if (archive.key) debug('Archive key', archive.key.toString('hex'))
    // doNotOpen = true if no existing feeds in drive
    // Opening would have to wait for swarm connection
    if (doNotOpen) return cb(null, archive, db)

    if (archive.resumed !== false) archive.resumed = true

    if (archive.key) debug('Opening archive', archive.key.toString('hex'))
    else debug('Opening snapshot archive')
    archive.open(function (err) {
      if (err) return cb(err)
      debug('Archive opened')
      cb(null, archive, db)
    })
  }
}
<commit_msg>Revert "do not set length if we own it" (#96)<commit_after>var assert = require('assert')
var fs = require('fs')
var path = require('path')
var level = require('level')
var hyperdrive = require('hyperdrive')
var raf = require('random-access-file')
var encoding = require('dat-encoding')
var debug = require('debug')('dat-node')

module.exports = function (opts, cb) {
  assert.ok(opts, 'dat-node: lib/init-archive opts required')
  assert.ok(opts.dir, 'dat-node: lib/init-archive dir option required')
  assert.ok(typeof cb === 'function', 'dat-node: lib/init-archive callback function required')

  var archive
  var drive
  var db
  var dir = opts.dir
  var key = opts.key ? encoding.toStr(opts.key) : null
  var dbPath = opts.dbPath || path.join(dir, '.dat')
  var createIfMissing = opts.createIfMissing === false ? opts.createIfMissing : true
  var errorIfExists = opts.errorIfExists || false

  // opts.resume backwards compat. TODO: Remove in v2
  if (opts.resume) createIfMissing = false
  if (opts.resume === false) errorIfExists = true

  if (!opts.file) {
    // TODO: do we always want this set?
    opts.file = function (name, opts) {
      return raf(path.join(dir, name), opts && typeof opts.length === 'number' && {length: opts.length})
    }
  }

  if (opts.db || opts.drive) {
    drive = opts.drive || hyperdrive(opts.db)
    db = opts.db ? opts.db : drive.core._db
    return checkDriveKeys()
  }

  if (createIfMissing !== false) return createDb()

  try {
    // check if existing dbPath
    if (!fs.statSync(dbPath).isDirectory()) throw new Error('.dat folder not a dir')
    return createDb()
  } catch (e) {
    return cb(new Error('No existing .dat folder'))
  }

  function createDb () {
    debug('Making/Reading archive database')
    level(dbPath, function (err, _db) {
      if (err) return cb(err)
      db = _db
      drive = hyperdrive(db)
      checkDriveKeys()
    })
  }

  function checkDriveKeys () {
    // Try to resume archives if there are keys in the drive
    debug('Reading existing keys in drive')
    drive.core.list(function (err, keys) {
      if (err) return cb(err)

      if (keys.length > 2 && !key) return cb(new Error('Drive has multiple archives. Must specify key.'))
      else if (errorIfExists && keys.length) {
        return db.close(function () {
          cb(new Error('Existing feeds in database.'))
        })
      }

      keys = keys.map(function (val) {
        return encoding.toStr(val)
      })
      debug(`Drive has ${keys.length} existing keys.`)
      if (keys.length) {
        debug('keys:', keys)
      }

      // Error if opts.key is used and doesn't match anything in database
      if (keys.length && key && keys.indexOf(key) === -1) {
        return db.close(function () {
          cb(new Error('Existing archive in database does not match key option.'))
        })
      }

      if (key) {
        debug('Using key option for archive', key)
        archive = drive.createArchive(key, opts)
        archive.resumed = (keys.length === 2) // resumed = true if existing archive
        return doneArchive(keys.length < 2 && key) // do not open if new drive and external key (e.g. downloading)
      } else if (!keys.length) {
        // create a new database + archive
        debug('No existing feeds in drive, creating new archive.')
        archive = drive.createArchive(null, opts)
        archive.resumed = false
        return doneArchive(false) // open archive - no external key so we are making new archive locally
      }
      // opts.key = null && keys.length === 2
      tryOpen()

      function tryOpen () {
        // Just in case: double check our logic here =)
        assert.ok(!key, 'dat-node: lib/init-archive tryOpen should be called if we opts.key is used')
        assert.ok(keys.length && keys.length <= 2, `dat-node: lib/init-archive tryOpen 1-2 values in database, db has ${keys.length}`)

        // Existing Keys, No key Option
        // Guess which key is metadata
        // If first key fails, use other key
        debug('Making archive with key', keys[keys.length - 1].toString('hex'))
        archive = drive.createArchive(keys[keys.length - 1], opts)
        var openTimeout = setTimeout(function () {
          debug('Timeout Open')
          tryOtherKey()
        }, 150)
        archive.open(function (err) {
          clearTimeout(openTimeout)
          if (!err) return doneArchive()
          var badKey = err && (err.message.indexOf('Unknown message type') > -1 || err.message.indexOf('Key not found in database') > -1)
          if (err & !badKey) return cb(err)
          tryOtherKey()
        })
      }

      function tryOtherKey () {
        debug('Bad Key. Trying other key.')
        archive = drive.createArchive(keys[0], opts)
        doneArchive()
      }
    })
  }

  function doneArchive (doNotOpen) {
    debug('Archive initialized')
    if (archive.key) debug('Archive key', archive.key.toString('hex'))
    // doNotOpen = true if no existing feeds in drive
    // Opening would have to wait for swarm connection
    if (doNotOpen) return cb(null, archive, db)

    if (archive.resumed !== false) archive.resumed = true

    if (archive.key) debug('Opening archive', archive.key.toString('hex'))
    else debug('Opening snapshot archive')
    archive.open(function (err) {
      if (err) return cb(err)
      debug('Archive opened')
      cb(null, archive, db)
    })
  }
}
<|endoftext|>


<commit_before>/*
 * Flushes stats to Instrumental (https://instrumentalapp.com).
 *
 * To enable this backend, include 'statsd-instrumental-backend' in the
 * backends configuration array:
 *
 *   backends: ['statsd-instrumental-backend']
 *
 * The backend will read the configuration options from the following
 * 'instrumental' hash defined in the main statsd config file:
 *
 *  instrumental : {
 *    key : API Token for your application,
 *    host : Instrumental server address (default: "instrumentalapp.com")
 *    port : Instrumental server port (default: 8000)
 *    timeout : Connection and read timeout (default: 10000 [10s])
 *  }
 */

// TODO: Log some internal stats (error rate, reconnect, metrics sent)

var net  = require("net"),
    util = require("util");

var debug;
var error = false;

var key, host, port, timeout;

function build_payload(metrics, time_stamp) {
  var payload = [];

  // Iterators: key and value.
  var k, v;

  // increment item.count 200 121820381
  for(k in metrics.counters) {
    v = metrics.counters[k];

    // Skip any counters that would not change the value
    if(v !== 0) {
      payload.push("increment " + k + " " + v + " " + time_stamp);
    }
  }

  // gauge item.time 7292 121820381
  for(k in metrics.timers) {
    // Skip any timers that are currently empty (no new data).
    if(metrics.timers[k].length === 0) {
      continue;
    }

    for(v in metrics.timers[k]) {
      payload.push("gauge " + k + " " + metrics.timers[k][v] + " " + time_stamp);
    }
  }

  // gauge item.gauge 7292 121820381
  for(k in metrics.gauges) {
    payload.push("gauge " + k + " " + metrics.gauges[k] + " " + time_stamp);
  }

  // By this point in time we should have an array of commands to send to the
  // instrumental server. We'll convert that array into a string blob in the
  // appropriate protocol.
  return payload;
}

// Push data to instrumental
function instrumental_send(payload) {
  var state = "cold";

  var client = net.createConnection({ port: port, host: host });

  // All communication with the server is done in ASCII.
  client.setEncoding("ascii");

  client.on("connect", function() {
    // Connetion Established. Lets go shopping
    state = "connected";

    // Write the authentication header
    client.write(
      "hello version 1.0\n" +
      "authenticate " + key + "\n"
    );
  });

  // We need to handle the timeout. I think we should only care about read
  // timeouts. That is we write out data, if we don't hear back in timeout
  // seconds then the data probably hasn't reached the server.
  client.setTimeout(timeout, function() {
    // ZOMG FAILED WRITING WE ARE BAD AT COMPUTER SCIENCE
    if(state == "connected") {
      // We're waiting to hear back from the server and it has timed out. It's
      // unlikely that the server will suddenly wake up and send us our data so
      // lets disconnect and go shopping.
      client.end();
    }
  });

  // HOW WE HANDLE ERRORS. We should probably reconnect, maybe retry.
  client.addListener("error", function(exception){
    if(debug) {
      util.log(exception);
    }
  });

  // What do we do when instrumental talks to us
  //
  // You know, we're early in the development cycle. We will (at most) expect
  // to receive "ok\nok\n" back from the server (ACK our header). Such a small
  // amount of data shouldn't be split into multiple packets... though I guess
  // we will find out.
  client.on("data", function(buffer) {
    if(debug) {
      util.puts("Received:", buffer);
    }

    // Authorization success
    if(buffer == "ok\nok\n") {
      error = false;

      if(debug) {
        util.puts("Sending:", payload.join("\n"));
      }

      client.end(payload.join("\n") + "\n", function() {
        state = "sent";
      });

    // Authorization failure
    } else if(buffer == "ok\nfail\n") {
      // TODO: Actually do something with this
      error = true;
    }
  });
}

function instrumental_flush(time_stamp, metrics) {
  var payload = build_payload(metrics, time_stamp);

  // Right now payload is at a minimum "\n"
  if(payload.length > 0) {
    instrumental_send(payload);
  }
}

function instrumental_status() {
  return !error;
}

exports.init = function instrumental_init(startup_time, config, events) {
  debug = config.debug;

  if(config.instrumental) {
    key  = config.instrumental.key;
    host = config.instrumental.host || "instrumentalapp.com";
    port = Number(config.instrumental.port || 8000);

    // Default 10s timeout
    timeout = Number(config.instrumental.timeout || 10000);
  }

  // Check for credentials
  if(!key) {
    util.log("Missing instrumental.key from the config.");
    return false;
  }

  events.on("flush", instrumental_flush);
  events.on("status", instrumental_status);

  return true;
};
<commit_msg>New endpoint collector.instrumentalapp.com.<commit_after>/*
 * Flushes stats to Instrumental (https://instrumentalapp.com).
 *
 * To enable this backend, include 'statsd-instrumental-backend' in the
 * backends configuration array:
 *
 *   backends: ['statsd-instrumental-backend']
 *
 * The backend will read the configuration options from the following
 * 'instrumental' hash defined in the main statsd config file:
 *
 *  instrumental : {
 *    key : API Token for your application,
 *    host : Instrumental server address (default: "collector.instrumentalapp.com")
 *    port : Instrumental server port (default: 8000)
 *    timeout : Connection and read timeout (default: 10000 [10s])
 *  }
 */

// TODO: Log some internal stats (error rate, reconnect, metrics sent)

var net  = require("net"),
    util = require("util");

var debug;
var error = false;

var key, host, port, timeout;

function build_payload(metrics, time_stamp) {
  var payload = [];

  // Iterators: key and value.
  var k, v;

  // increment item.count 200 121820381
  for(k in metrics.counters) {
    v = metrics.counters[k];

    // Skip any counters that would not change the value
    if(v !== 0) {
      payload.push("increment " + k + " " + v + " " + time_stamp);
    }
  }

  // gauge item.time 7292 121820381
  for(k in metrics.timers) {
    // Skip any timers that are currently empty (no new data).
    if(metrics.timers[k].length === 0) {
      continue;
    }

    for(v in metrics.timers[k]) {
      payload.push("gauge " + k + " " + metrics.timers[k][v] + " " + time_stamp);
    }
  }

  // gauge item.gauge 7292 121820381
  for(k in metrics.gauges) {
    payload.push("gauge " + k + " " + metrics.gauges[k] + " " + time_stamp);
  }

  // By this point in time we should have an array of commands to send to the
  // instrumental server. We'll convert that array into a string blob in the
  // appropriate protocol.
  return payload;
}

// Push data to instrumental
function instrumental_send(payload) {
  var state = "cold";

  var client = net.createConnection({ port: port, host: host });

  // All communication with the server is done in ASCII.
  client.setEncoding("ascii");

  client.on("connect", function() {
    // Connetion Established. Lets go shopping
    state = "connected";

    // Write the authentication header
    client.write(
      "hello version 1.0\n" +
      "authenticate " + key + "\n"
    );
  });

  // We need to handle the timeout. I think we should only care about read
  // timeouts. That is we write out data, if we don't hear back in timeout
  // seconds then the data probably hasn't reached the server.
  client.setTimeout(timeout, function() {
    // ZOMG FAILED WRITING WE ARE BAD AT COMPUTER SCIENCE
    if(state == "connected") {
      // We're waiting to hear back from the server and it has timed out. It's
      // unlikely that the server will suddenly wake up and send us our data so
      // lets disconnect and go shopping.
      client.end();
    }
  });

  // HOW WE HANDLE ERRORS. We should probably reconnect, maybe retry.
  client.addListener("error", function(exception){
    if(debug) {
      util.log(exception);
    }
  });

  // What do we do when instrumental talks to us
  //
  // You know, we're early in the development cycle. We will (at most) expect
  // to receive "ok\nok\n" back from the server (ACK our header). Such a small
  // amount of data shouldn't be split into multiple packets... though I guess
  // we will find out.
  client.on("data", function(buffer) {
    if(debug) {
      util.puts("Received:", buffer);
    }

    // Authorization success
    if(buffer == "ok\nok\n") {
      error = false;

      if(debug) {
        util.puts("Sending:", payload.join("\n"));
      }

      client.end(payload.join("\n") + "\n", function() {
        state = "sent";
      });

    // Authorization failure
    } else if(buffer == "ok\nfail\n") {
      // TODO: Actually do something with this
      error = true;
    }
  });
}

function instrumental_flush(time_stamp, metrics) {
  var payload = build_payload(metrics, time_stamp);

  // Right now payload is at a minimum "\n"
  if(payload.length > 0) {
    instrumental_send(payload);
  }
}

function instrumental_status() {
  return !error;
}

exports.init = function instrumental_init(startup_time, config, events) {
  debug = config.debug;

  if(config.instrumental) {
    key  = config.instrumental.key;
    host = config.instrumental.host || "collector.instrumentalapp.com";
    port = Number(config.instrumental.port || 8000);

    // Default 10s timeout
    timeout = Number(config.instrumental.timeout || 10000);
  }

  // Check for credentials
  if(!key) {
    util.log("Missing instrumental.key from the config.");
    return false;
  }

  events.on("flush", instrumental_flush);
  events.on("status", instrumental_status);

  return true;
};
<|endoftext|>


<commit_before>/**
 * app.js
 *
 * This is the entry file for the application, only setup and boilerplate
 * code.
 */

/* eslint-disable */
// Retrieve remote and backend URLs.
const remoteURL = window.location.port === '4000' ? 'http://localhost:4000/admin' : process.env.REMOTE_URL || 'http://localhost:1337/admin';
const backendURL = process.env.BACKEND_URL || 'http://localhost:1337';

// Retrieve development URL to avoid to re-build.
const $body = document.getElementsByTagName('body')[0];
const devFrontURL = $body.getAttribute('front');
const devBackendURL = $body.getAttribute('back');

$body.removeAttribute('front');
$body.removeAttribute('back');

import './public-path';
import 'babel-polyfill';

// Import all the third party stuff
import { Provider } from 'react-redux';
import React from 'react';
import ReactDOM from 'react-dom';
import { ConnectedRouter } from 'react-router-redux';
import createHistory from 'history/createBrowserHistory';
import { merge, isFunction } from 'lodash';
import 'sanitize.css/sanitize.css';
import 'whatwg-fetch';

import LanguageProvider from 'containers/LanguageProvider';

import App from 'containers/App';
import { showNotification } from 'containers/NotificationProvider/actions';
import { pluginLoaded, updatePlugin, setHasUserPlugin } from 'containers/App/actions';
import auth from 'utils/auth';
import configureStore from './store';
import { translationMessages, languages } from './i18n';
import { findIndex } from 'lodash';
/* eslint-enable */

const plugins = (() => {
  try {
    return require('./config/plugins.json');
  } catch (e) {
    return [];
  }
})();

// Create redux store with history
const initialState = {};
const history = createHistory({
  basename: (devFrontURL || remoteURL).replace(window.location.origin, ''),
});
const store = configureStore(initialState, history);

const render = (translatedMessages) => {
  ReactDOM.render(
    <Provider store={store}>
      <LanguageProvider messages={translatedMessages}>
        <ConnectedRouter history={history}>
          <App />
        </ConnectedRouter>
      </LanguageProvider>
    </Provider>,
    document.getElementById('app')
  );
};

// Hot reloadable translation json files
if (module.hot) {
  // modules.hot.accept does not accept dynamic dependencies,
  // have to be constants at compile-time
  module.hot.accept('./i18n', () => {
    render(translationMessages);
  });
}

// Chunked polyfill for browsers without Intl support
window.onload = function onLoad() {
  if (!window.Intl) {
    Promise.all([
      System.import('intl'),
      System.import('intl/locale-data/jsonp/en.js'),
      System.import('intl/locale-data/jsonp/fr.js'),
    ]).then(() => render(translationMessages));
  } else {
    render(translationMessages);
  }
};

// Don't inject plugins in development mode.
if (window.location.port !== '4000') {
  fetch(`${devFrontURL || remoteURL}/config/plugins.json`)
    .then(response => {
      return response.json();
    })
    .then(plugins => {
      if (findIndex(plugins, ['id', 'users-permissions']) === -1) {
        store.dispatch(setHasUserPlugin());
      }

      (plugins || []).forEach(plugin => {
        const script = document.createElement('script');
        script.type = 'text/javascript';
        script.onerror = function (oError) {
          const source = new URL(oError.target.src);
          const url = new URL(`${devFrontURL || remoteURL}`);

          if (!source || !url) {
            throw new Error(`Impossible to load: ${oError.target.src}`);
          }

          // Remove tag.
          $body.removeChild(script);

          // New attempt with new src.
          const newScript = document.createElement('script');
          newScript.type = 'text/javascript';
          newScript.src = `${url.origin}${source.pathname}`;
          $body.appendChild(newScript);
        };

        script.src = plugin.source[process.env.NODE_ENV];
        $body.appendChild(script);
      });
    })
    .catch(err => {
      console.log(err);
    });
} else if (findIndex(plugins, ['id', 'users-permissions']) === -1) {
  store.dispatch(setHasUserPlugin());
}

// const isPluginAllowedToRegister = (plugin) => true;
const isPluginAllowedToRegister = (plugin) => plugin.id === 'users-permissions' || plugin.id === 'email' || auth.getToken();

/**
 * Register a plugin
 *
 * @param params
 */
const registerPlugin = (plugin) => {
  // Merge admin translation messages
  merge(translationMessages, plugin.translationMessages);

  plugin.leftMenuSections = plugin.leftMenuSections || [];
  const shouldAllowRegister = isPluginAllowedToRegister(plugin);

  switch (true) {
    // Execute bootstrap function and check if plugin can be rendered
    case isFunction(plugin.bootstrap) && isFunction(plugin.pluginRequirements) && shouldAllowRegister:
      plugin.pluginRequirements(plugin)
        .then(plugin => {
          return plugin.bootstrap(plugin);
        })
        .then(plugin => {
          store.dispatch(pluginLoaded(plugin));
        });
      break;
    // Check if plugin can be rendered
    case isFunction(plugin.pluginRequirements):
      plugin.pluginRequirements(plugin).then(plugin => {
        store.dispatch(pluginLoaded(plugin));
      });
      break;
    // Execute bootstrap function
    case isFunction(plugin.bootstrap) && shouldAllowRegister:
      plugin.bootstrap(plugin).then(plugin => {
        store.dispatch(pluginLoaded(plugin));
      });
      break;
    default:
      store.dispatch(pluginLoaded(plugin));
  }
};

const displayNotification = (message, status) => {
  store.dispatch(showNotification(message, status));
};

/**
 * Public Strapi object exposed to the `window` object
 */

window.strapi = Object.assign(window.strapi || {}, {
  remoteURL: devFrontURL || remoteURL,
  backendURL: devBackendURL || backendURL,
  registerPlugin,
  notification: {
    success: (message) => {
      displayNotification(message, 'success');
    },
    warning: (message) => {
      displayNotification(message, 'warning');
    },
    error: (message) => {
      displayNotification(message, 'error');
    },
    info: (message) => {
      displayNotification(message, 'info');
    },
  },
  refresh: (pluginId) => ({
    translationMessages: (translationMessagesUpdated) => {
      render(merge({}, translationMessages, translationMessagesUpdated));
    },
    leftMenuSections: (leftMenuSectionsUpdated) => {
      store.dispatch(updatePlugin(pluginId, 'leftMenuSections', leftMenuSectionsUpdated));
    },
  }),
  router: history,
  languages,
});

const dispatch = store.dispatch;
export {
  dispatch,
};
<commit_msg>Fix eslint<commit_after>/**
 * app.js
 *
 * This is the entry file for the application, only setup and boilerplate
 * code.
 */

/* eslint-disable */
// Retrieve remote and backend URLs.
const remoteURL = window.location.port === '4000' ? 'http://localhost:4000/admin' : process.env.REMOTE_URL || 'http://localhost:1337/admin';
const backendURL = process.env.BACKEND_URL || 'http://localhost:1337';

// Retrieve development URL to avoid to re-build.
const $body = document.getElementsByTagName('body')[0];
const devFrontURL = $body.getAttribute('front');
const devBackendURL = $body.getAttribute('back');

$body.removeAttribute('front');
$body.removeAttribute('back');

import './public-path';
import 'babel-polyfill';

// Import all the third party stuff
import { Provider } from 'react-redux';
import React from 'react';
import ReactDOM from 'react-dom';
import { ConnectedRouter } from 'react-router-redux';
import createHistory from 'history/createBrowserHistory';
import { merge, isFunction } from 'lodash';
import 'sanitize.css/sanitize.css';
import 'whatwg-fetch';

import LanguageProvider from 'containers/LanguageProvider';

import App from 'containers/App';
import { showNotification } from 'containers/NotificationProvider/actions';
import { pluginLoaded, updatePlugin, setHasUserPlugin } from 'containers/App/actions';
import auth from 'utils/auth';
import configureStore from './store';
import { translationMessages, languages } from './i18n';
import { findIndex } from 'lodash';

const plugins = (() => {
  try {
    return require('./config/plugins.json');
  } catch (e) {
    return [];
  }
})();
/* eslint-enable */

// Create redux store with history
const initialState = {};
const history = createHistory({
  basename: (devFrontURL || remoteURL).replace(window.location.origin, ''),
});
const store = configureStore(initialState, history);

const render = (translatedMessages) => {
  ReactDOM.render(
    <Provider store={store}>
      <LanguageProvider messages={translatedMessages}>
        <ConnectedRouter history={history}>
          <App />
        </ConnectedRouter>
      </LanguageProvider>
    </Provider>,
    document.getElementById('app')
  );
};

// Hot reloadable translation json files
if (module.hot) {
  // modules.hot.accept does not accept dynamic dependencies,
  // have to be constants at compile-time
  module.hot.accept('./i18n', () => {
    render(translationMessages);
  });
}

// Chunked polyfill for browsers without Intl support
window.onload = function onLoad() {
  if (!window.Intl) {
    Promise.all([
      System.import('intl'),
      System.import('intl/locale-data/jsonp/en.js'),
      System.import('intl/locale-data/jsonp/fr.js'),
    ]).then(() => render(translationMessages));
  } else {
    render(translationMessages);
  }
};

// Don't inject plugins in development mode.
if (window.location.port !== '4000') {
  fetch(`${devFrontURL || remoteURL}/config/plugins.json`)
    .then(response => {
      return response.json();
    })
    .then(plugins => {
      if (findIndex(plugins, ['id', 'users-permissions']) === -1) {
        store.dispatch(setHasUserPlugin());
      }

      (plugins || []).forEach(plugin => {
        const script = document.createElement('script');
        script.type = 'text/javascript';
        script.onerror = function (oError) {
          const source = new URL(oError.target.src);
          const url = new URL(`${devFrontURL || remoteURL}`);

          if (!source || !url) {
            throw new Error(`Impossible to load: ${oError.target.src}`);
          }

          // Remove tag.
          $body.removeChild(script);

          // New attempt with new src.
          const newScript = document.createElement('script');
          newScript.type = 'text/javascript';
          newScript.src = `${url.origin}${source.pathname}`;
          $body.appendChild(newScript);
        };

        script.src = plugin.source[process.env.NODE_ENV];
        $body.appendChild(script);
      });
    })
    .catch(err => {
      console.log(err);
    });
} else if (findIndex(plugins, ['id', 'users-permissions']) === -1) {
  store.dispatch(setHasUserPlugin());
}

// const isPluginAllowedToRegister = (plugin) => true;
const isPluginAllowedToRegister = (plugin) => plugin.id === 'users-permissions' || plugin.id === 'email' || auth.getToken();

/**
 * Register a plugin
 *
 * @param params
 */
const registerPlugin = (plugin) => {
  // Merge admin translation messages
  merge(translationMessages, plugin.translationMessages);

  plugin.leftMenuSections = plugin.leftMenuSections || [];
  const shouldAllowRegister = isPluginAllowedToRegister(plugin);

  switch (true) {
    // Execute bootstrap function and check if plugin can be rendered
    case isFunction(plugin.bootstrap) && isFunction(plugin.pluginRequirements) && shouldAllowRegister:
      plugin.pluginRequirements(plugin)
        .then(plugin => {
          return plugin.bootstrap(plugin);
        })
        .then(plugin => {
          store.dispatch(pluginLoaded(plugin));
        });
      break;
    // Check if plugin can be rendered
    case isFunction(plugin.pluginRequirements):
      plugin.pluginRequirements(plugin).then(plugin => {
        store.dispatch(pluginLoaded(plugin));
      });
      break;
    // Execute bootstrap function
    case isFunction(plugin.bootstrap) && shouldAllowRegister:
      plugin.bootstrap(plugin).then(plugin => {
        store.dispatch(pluginLoaded(plugin));
      });
      break;
    default:
      store.dispatch(pluginLoaded(plugin));
  }
};

const displayNotification = (message, status) => {
  store.dispatch(showNotification(message, status));
};

/**
 * Public Strapi object exposed to the `window` object
 */

window.strapi = Object.assign(window.strapi || {}, {
  remoteURL: devFrontURL || remoteURL,
  backendURL: devBackendURL || backendURL,
  registerPlugin,
  notification: {
    success: (message) => {
      displayNotification(message, 'success');
    },
    warning: (message) => {
      displayNotification(message, 'warning');
    },
    error: (message) => {
      displayNotification(message, 'error');
    },
    info: (message) => {
      displayNotification(message, 'info');
    },
  },
  refresh: (pluginId) => ({
    translationMessages: (translationMessagesUpdated) => {
      render(merge({}, translationMessages, translationMessagesUpdated));
    },
    leftMenuSections: (leftMenuSectionsUpdated) => {
      store.dispatch(updatePlugin(pluginId, 'leftMenuSections', leftMenuSectionsUpdated));
    },
  }),
  router: history,
  languages,
});

const dispatch = store.dispatch;
export {
  dispatch,
};
<|endoftext|>


<commit_before>"use strict";

const compiler = require("./caching-compiler.js");
const isObject = require("../lib/utils.js").isObject;
const path = require("path");
const runtime = require("../lib/runtime.js");
const utils = require("./utils.js");
const wrapper = require("./wrapper.js");

const Module = require("module");

const exts = Module._extensions;
const Mp = Module.prototype;

let compileOptions;

module.exports = exports = (options) => {
  if (compileOptions === void 0) {
    compileOptions = Object.assign({}, options);
  }
};

wrapper.add(exts, ".js", function(func, pkgInfo, module, filename) {
  const cachePath = pkgInfo.cachePath;
  if (cachePath === null) {
    return func.call(this, module, filename);
  }

  const isGzipped = path.extname(filename) === ".gz";
  const cache = pkgInfo.cache;
  const cacheKey = utils.mtime(filename);
  const cacheFilename = utils.getCacheFileName(filename, cacheKey, pkgInfo);

  let cacheValue = cache[cacheFilename];
  if (cacheValue === true) {
    const cacheFilepath = path.join(cachePath, cacheFilename);
    cacheValue = isGzipped
      ? utils.gunzip(utils.readFile(cacheFilepath), "utf8")
      : utils.readFile(cacheFilepath, "utf8");

  } else if (typeof cacheValue !== "string") {
    const options = {
      cacheFilename,
      cachePath,
      compileOptions,
      filename,
      parser: pkgInfo.config.parser
    };

    const content = isGzipped
      ? utils.gunzip(utils.readFile(filename), "utf8")
      : utils.readFile(filename, "utf8");

    cacheValue = compiler.compile(content, options);
  }

  cache[cacheFilename] = cacheValue;

  runtime.enable(module);
  module._compile(cacheValue, filename);
  module.runModuleSetters();
});

const extsJsMap = wrapper.getMap(exts, ".js");
const extsJsRaw = extsJsMap.raw;
const extJsWrapper = extsJsMap.wrappers[utils.getReifySemVer()];

[".gz", ".js.gz", ".mjs.gz", ".mjs"].forEach((key) => {
  if (typeof exts[key] !== "function") {
    // Mimic the built-in Node behavior of treating files with unrecognized
    // extensions as .js.
    exts[key] = extsJsRaw;
  }

  wrapper.add(exts, key, function(func, pkgInfo, param, filename) {
    return extJsWrapper.call(this, func, pkgInfo, param, filename);
  });
});
<commit_msg>Remove unused Module.prototype reference from compile-hook.<commit_after>"use strict";

const compiler = require("./caching-compiler.js");
const isObject = require("../lib/utils.js").isObject;
const path = require("path");
const runtime = require("../lib/runtime.js");
const utils = require("./utils.js");
const wrapper = require("./wrapper.js");

const Module = require("module");
const exts = Module._extensions;

let compileOptions;

module.exports = exports = (options) => {
  if (compileOptions === void 0) {
    compileOptions = Object.assign({}, options);
  }
};

wrapper.add(exts, ".js", function(func, pkgInfo, module, filename) {
  const cachePath = pkgInfo.cachePath;
  if (cachePath === null) {
    return func.call(this, module, filename);
  }

  const isGzipped = path.extname(filename) === ".gz";
  const cache = pkgInfo.cache;
  const cacheKey = utils.mtime(filename);
  const cacheFilename = utils.getCacheFileName(filename, cacheKey, pkgInfo);

  let cacheValue = cache[cacheFilename];
  if (cacheValue === true) {
    const cacheFilepath = path.join(cachePath, cacheFilename);
    cacheValue = isGzipped
      ? utils.gunzip(utils.readFile(cacheFilepath), "utf8")
      : utils.readFile(cacheFilepath, "utf8");

  } else if (typeof cacheValue !== "string") {
    const options = {
      cacheFilename,
      cachePath,
      compileOptions,
      filename,
      parser: pkgInfo.config.parser
    };

    const content = isGzipped
      ? utils.gunzip(utils.readFile(filename), "utf8")
      : utils.readFile(filename, "utf8");

    cacheValue = compiler.compile(content, options);
  }

  cache[cacheFilename] = cacheValue;

  runtime.enable(module);
  module._compile(cacheValue, filename);
  module.runModuleSetters();
});

const extsJsMap = wrapper.getMap(exts, ".js");
const extsJsRaw = extsJsMap.raw;
const extJsWrapper = extsJsMap.wrappers[utils.getReifySemVer()];

[".gz", ".js.gz", ".mjs.gz", ".mjs"].forEach((key) => {
  if (typeof exts[key] !== "function") {
    // Mimic the built-in Node behavior of treating files with unrecognized
    // extensions as .js.
    exts[key] = extsJsRaw;
  }

  wrapper.add(exts, key, function(func, pkgInfo, param, filename) {
    return extJsWrapper.call(this, func, pkgInfo, param, filename);
  });
});
<|endoftext|>


<commit_before>/* eslint-disable no-console */
/* eslint-disable max-len */
/* eslint-disable no-underscore-dangle */
/* eslint-disable func-names */

import core from '@spiral-toolkit/core';
// import moment from 'moment';
import flatpickr from 'flatpickr';

export const DateInput = function (sf, node, options) {
  this._construct(sf, node, options);
};

/**
 * @lends sf.Form.prototype
 */
DateInput.prototype = Object.create(core.core.BaseDOMConstructor.prototype);

/**
 * Name to register
 * @type {string}
 */
DateInput.prototype.name = 'date';

DateInput.prototype._construct = function (sf, node, options) {
  this.init(sf, node, options);
  this.input = node.querySelector('input');
  this.picker = flatpickr(this.input, {
    enableTime: !!this.options.enableTime,
    noCalendar: !!this.options.noCalendar,
    altInput: true,
    altFormat: this.options.displayFormat || 'Y-m-d',
    dateFormat: this.options.dateFormat || 'Z',
    onChange: () => {

    },
  });
  console.log(this.options);
};

/**
 * @override
 * @inheritDoc
 * @enum {string}
 */
DateInput.prototype.optionsToGrab = {
  enableTime: {
    value: false,
    domAttr: 'data-enable-time',
  },
  noCalendar: {
    value: false,
    domAttr: 'data-no-calendar',
  },
  dateFormat: {
    value: 'Z',
    domAttr: 'data-format',
  },
  displayFormat: {
    value: 'Y-m-d',
    domAttr: 'data-display-format',
  },
};

DateInput.prototype.die = function () {
  delete this;
};

export { DateInput as default };
<commit_msg>use same date format as everywhere<commit_after>/* eslint-disable no-console */
/* eslint-disable max-len */
/* eslint-disable no-underscore-dangle */
/* eslint-disable func-names */

import core from '@spiral-toolkit/core';
// import moment from 'moment';
import flatpickr from 'flatpickr';

const dateWithTS = 'yyyy-MM-dd\'T\'HH:mm:ssZZZ';

const { luxon } = core.helpers;

export const DateInput = function (sf, node, options) {
  this._construct(sf, node, options);
};

/**
 * @lends sf.Form.prototype
 */
DateInput.prototype = Object.create(core.core.BaseDOMConstructor.prototype);

/**
 * Name to register
 * @type {string}
 */
DateInput.prototype.name = 'date';

DateInput.prototype._construct = function (sf, node, options) {
  this.init(sf, node, options);
  this.input = node.querySelector('input');
  this.picker = flatpickr(this.input, {
    enableTime: !!this.options.enableTime,
    noCalendar: !!this.options.noCalendar,
    altInput: true,
    altFormat: this.options.displayFormat || 'yyyy LLL dd',
    dateFormat: this.options.dateFormat || dateWithTS,
    formatDate: (date, format) => {
      console.log(date, format);
      return luxon.DateTime.fromJSDate(date).toFormat(format);
    },
    parseDate: (str, format) => {
      console.log(str, format);
      return luxon.DateTime.fromFormat(str, format).toJSDate();
    },
  });
  console.log(this.options);
};

/**
 * @override
 * @inheritDoc
 * @enum {string}
 */
DateInput.prototype.optionsToGrab = {
  enableTime: {
    value: false,
    domAttr: 'data-enable-time',
  },
  noCalendar: {
    value: false,
    domAttr: 'data-no-calendar',
  },
  dateFormat: {
    value: dateWithTS,
    domAttr: 'data-format',
  },
  displayFormat: {
    value: 'yyyy LLL dd',
    domAttr: 'data-display-format',
  },
};

DateInput.prototype.die = function () {
  delete this;
};

export { DateInput as default };
<|endoftext|>


<commit_before>var exec= require('child_process').exec;
var tt = 0;
var cmd ='./nodejs_app/nodeon.sh & tt=$!' ;

var t=exec(cmd,function (error,stdout, stderr){
	tt=stdout.replace('\r\n','');
});

exec("./nodejs_app/nodeoff.sh");
if(tt=0)
return 1;
else return 0;
<commit_msg>Update testsA.js<commit_after>var exec= require('child_process').exec;
var tt = 0;
var cmd ='./nodejs_app/nodeon.sh & tt=$!' ;

var t=exec(cmd,function (error,stdout, stderr){
	tt=stdout.replace('\r\n','');
});

exec("./nodejs_app/nodeoff.sh");
console.log(tt);
if(tt=0)
return 1;
else return 0;
<|endoftext|>


<commit_before>'use strict';

const micromatch = require('micromatch');
const flatten = require('lodash/flatten');

const NUMBER_REGEX = /^\d+$/;
const RANGE_REGEX = /^(?<startGroup>\d+)-(?<endGroup>\d+)$/;
const LINE_NUMBERS_REGEX = /^(?:\d+(?:-\d+)?,?)+$/;
const DELIMITER = ':';

const distinctArray = array => [...new Set(array)];
const sortNumbersAscending = array => {
	const sorted = [...array];
	sorted.sort((a, b) => a - b);
	return sorted;
};

const parseNumber = string => Number.parseInt(string, 10);
const removeAllWhitespace = string => string.replace(/\s/g, '');
const range = (start, end) => new Array(end - start + 1).fill(start).map((element, index) => element + index);

const parseLineNumbers = suffix => sortNumbersAscending(distinctArray(flatten(
	suffix.split(',').map(part => {
		if (NUMBER_REGEX.test(part)) {
			return parseNumber(part);
		}

		const {groups: {startGroup, endGroup}} = RANGE_REGEX.exec(part);
		const start = parseNumber(startGroup);
		const end = parseNumber(endGroup);

		if (start > end) {
			return range(end, start);
		}

		return range(start, end);
	})
)));

function splitPatternAndLineNumbers(pattern) {
	const parts = pattern.split(DELIMITER);
	if (parts.length === 1) {
		return {pattern, lineNumbers: null};
	}

	const suffix = removeAllWhitespace(parts.pop());
	if (!LINE_NUMBERS_REGEX.test(suffix)) {
		return {pattern, lineNumbers: null};
	}

	return {pattern: parts.join(DELIMITER), lineNumbers: parseLineNumbers(suffix)};
}

exports.splitPatternAndLineNumbers = splitPatternAndLineNumbers;

function getApplicableLineNumbers(normalizedFilePath, filter) {
	return sortNumbersAscending(distinctArray(flatten(
		filter
			.filter(({pattern, lineNumbers}) => lineNumbers && micromatch.isMatch(normalizedFilePath, pattern))
			.map(({lineNumbers}) => lineNumbers)
	)));
}

exports.getApplicableLineNumbers = getApplicableLineNumbers;
<commit_msg>Correctly use picomatch dependency<commit_after>'use strict';

const picomatch = require('picomatch');
const flatten = require('lodash/flatten');

const NUMBER_REGEX = /^\d+$/;
const RANGE_REGEX = /^(?<startGroup>\d+)-(?<endGroup>\d+)$/;
const LINE_NUMBERS_REGEX = /^(?:\d+(?:-\d+)?,?)+$/;
const DELIMITER = ':';

const distinctArray = array => [...new Set(array)];
const sortNumbersAscending = array => {
	const sorted = [...array];
	sorted.sort((a, b) => a - b);
	return sorted;
};

const parseNumber = string => Number.parseInt(string, 10);
const removeAllWhitespace = string => string.replace(/\s/g, '');
const range = (start, end) => new Array(end - start + 1).fill(start).map((element, index) => element + index);

const parseLineNumbers = suffix => sortNumbersAscending(distinctArray(flatten(
	suffix.split(',').map(part => {
		if (NUMBER_REGEX.test(part)) {
			return parseNumber(part);
		}

		const {groups: {startGroup, endGroup}} = RANGE_REGEX.exec(part);
		const start = parseNumber(startGroup);
		const end = parseNumber(endGroup);

		if (start > end) {
			return range(end, start);
		}

		return range(start, end);
	})
)));

function splitPatternAndLineNumbers(pattern) {
	const parts = pattern.split(DELIMITER);
	if (parts.length === 1) {
		return {pattern, lineNumbers: null};
	}

	const suffix = removeAllWhitespace(parts.pop());
	if (!LINE_NUMBERS_REGEX.test(suffix)) {
		return {pattern, lineNumbers: null};
	}

	return {pattern: parts.join(DELIMITER), lineNumbers: parseLineNumbers(suffix)};
}

exports.splitPatternAndLineNumbers = splitPatternAndLineNumbers;

function getApplicableLineNumbers(normalizedFilePath, filter) {
	return sortNumbersAscending(distinctArray(flatten(
		filter
			.filter(({pattern, lineNumbers}) => lineNumbers && picomatch.isMatch(normalizedFilePath, pattern))
			.map(({lineNumbers}) => lineNumbers)
	)));
}

exports.getApplicableLineNumbers = getApplicableLineNumbers;
<|endoftext|>