<commit_before>/**
 * Created by faisal on 3/16/15.
 */

import Ember from 'ember';
import BaseMod from 'tealeaves/components/vizmods/base-viz';
import tools from 'tealeaves/library/toolkit';
/* global d3 */

function generateChart(target_elem, legend_elem, topic_set, message_data) {
  var margin = {
      top: 40,
      right: 30,
      bottom: 30,
      left: 50
    },
    width = Ember.$(target_elem).width() - margin.left - margin.right,
    height = Ember.$(target_elem).height() - margin.top - margin.bottom;

  var parseDate = d3.time.format("%Y-%m-%dT%I:%M:%S").parse;
  var formatDate = d3.time.format("%m/%d");
  var formatCount = d3.format(",.0f");

  var x = d3.time.scale().range([0, width]);
  var y = d3.scale.linear().range([height, 0]);
  var color = d3.scale.category20();

  // fix the colors to the topic IDs so they're consistent between vis components
  color.domain(Object.keys(topic_set));

  var xAxis = d3.svg.axis().scale(x)
    .orient("bottom").tickFormat(formatDate);

  var yAxis = d3.svg.axis().scale(y)
    .orient("left").ticks(12);

  var stack = d3.layout.stack()
    .values(function(d) {
      return d.values;
    });

  // Create the SVG drawing area
  var svg = d3.select(target_elem)
    .append("g")
    .attr("transform", "translate(" + margin.left + "," + margin.top + ")");

  // Parse the date strings into javascript dates
  message_data.forEach(function(d) {
    d.received_on = parseDate(d.received_on);
  });

  // Determine the first and list dates in the data set
  var timeExtent = d3.extent(message_data, function(d) {
    return d.received_on;
  });

  // Create one bin per day, use an offset to include the first and last days(?)
  var dayBins = d3.time.days(d3.time.day.offset(timeExtent[0], -1),
    d3.time.day.offset(timeExtent[1], 0));

  // Use the histogram layout to create a function that will bin the data
  var binByDay = d3.layout.histogram()
    .value(function(d) {
      return d.received_on;
    })
    .bins(dayBins);

  // Use D3's nest function to group the data by borough
  var dataGroupedByBorough = d3.nest()
    .key(function(d) {
      return d.topics[0].topic_id;
    })
    .map(message_data, d3.map);

  // Apply the histogram binning function to the data and convert from
  // a map to an array so that the stack layout can consume it
  var histDataByBorough = [];
  dataGroupedByBorough.entries().map(function(o) {
    var key = o.key;
    var value = o.value;

    // Bin the data for each borough by day
    var histData = binByDay(value);
    histDataByBorough.push({
      topic_id: key,
      values: histData
    });
  });

  var stackedHistData = stack(histDataByBorough);

  // Scale the range of the data by setting the domain
  x.domain(d3.extent(dayBins));
  y.domain([0, d3.max(stackedHistData[stackedHistData.length - 1].values, function(d) {
    return d.y + d.y0;
  })]);

  // Define the div for the tooltip
  var div = d3.select("body").append("div")
    .attr("class", "topicstacked-tooltip")
    .style("opacity", 0);

  // Set up one group for each borough
  // Note that color doesn't have a domain set, so colors are assigned to boroughs
  // below on a first come, first serve basis
  var borough = svg.selectAll(".borough")
    .data(stackedHistData)
    .enter().append("g")
    .attr("class", "borough")
    .style("fill", function(d, i) {
      return color(d.topic_id);
    })
    .style("stroke", function(d, i) {
      return d3.rgb(color(d.topic_id)).darker();
    })
    .on("mouseover", function(d) {
      div.transition()
        .duration(200)
        .style("opacity", 0.9);
      div	.html(topic_set[d.topic_id])
        .style("left", (d3.event.pageX) + "px")
        .style("top", (d3.event.pageY - 28) + "px");
    })
    .on("mouseout", function(d) {
      div.transition()
        .duration(500)
        .style("opacity", 0);
    });

  // Months have slightly different lengths so calculate the width for each bin
  // Draw the rectangles, starting from the upper left corner and going down
  borough.selectAll(".bar")
    .data(function(d) {
      return d.values;
    })
    .enter().append("rect")
    .attr("class", "bar")
    .attr("x", function(d) {
      return x(d.x);
    })
    .attr("width", function(d) {
      return x(new Date(d.x.getTime() + d.dx)) - x(d.x) - 2;
    })
    .attr("y", function(d) {
      return y(d.y0 + d.y);
    })
    .attr("height", function(d) {
      return y(d.y0) - y(d.y0 + d.y);
    });

  // Add the X Axis
  svg.append("g")
    .attr("class", "x axis")
    .attr("transform", "translate(0," + height + ")")
    .call(xAxis);

  // Add the Y Axis and label
  svg.append("g")
    .attr("class", "y axis")
    .call(yAxis);
    /*
    .append("text")
    .attr("transform", "rotate(-90)")
    .attr("y", 6)
    .attr("dy", ".71em")
    .style("text-anchor", "end")
    .text("Number of Rat Sightings");
    */

  // Add the legend to the second box
  Ember.$.each(topic_set, function(k, v) {
    // colored box + label container
    var $topic_set = Ember.$("<div />")
      .css('margin', '3px')
      .css('margin-left', '50px')
      .css('display', 'flex');

    // colored box
    Ember.$("<div />")
      .css('width', '15px')
      .css('height', '15px')
      .css('margin-right', '3px')
      .css('background-color', color(k))
      .appendTo($topic_set);

    // label
    Ember.$("<div />")
      .text(v)
      .appendTo($topic_set);

    $topic_set.appendTo(legend_elem);
  });
}

export default BaseMod.extend({
  classNames: ['topic-stacked'],

  bind: function(start_date, end_date) {
    var _this = this;

    // display the spinner
    this.$(".loader").show();

    var $boxShell = this.$(".topicstacked-box");
    var $target = this.$(".topicstacked-box svg");
    var $legend_target = this.$(".topic-legend");

    // remove any elements in the SVG
    $target.empty();
    $legend_target.empty();

    $target.attr('viewBox', `0 0 ${$boxShell.width()} ${$boxShell.height()}`);
    $target.attr('width', $boxShell.width());
    $target.attr('height', $boxShell.height());

    // we have to query for two things:
    // 1) the set of topics for this user
    // 2) the mail messages with associated 'topics' field keyed to set of topics

    _this.get('eaf_api').query('topic', {})
      .then(function(data) {
        var topic_set = data.objects.reduce(function(acc, v) { acc[v.id] = v.shortname; return acc; }, {});
        // once we have the topics, we can query for the messages and build the rest of the graph
        _this.get('eaf_api').query('mail_message', { min_date: tools.apiTZDateTime(start_date), max_date: tools.apiTZDateTime(end_date), topics: 1 })
          .then(function(message_data) {
            var msg_topics = message_data.objects.map(function(v) {
              return {'received_on': v.received_on, 'topics': v.topics};
            }).filter(function(v) {
              return v.topics.length > 0;
            });

            generateChart($target.get(0), $legend_target.get(0), topic_set, msg_topics);

            // now we can generate the chart
            _this.$(".loader").hide();
          });
      });
  }
});
<commit_msg>Added support for alter filtering to topic-stack<commit_after>/**
 * Created by faisal on 3/16/15.
 */

import Ember from 'ember';
import BaseMod from 'tealeaves/components/vizmods/base-viz';
import tools from 'tealeaves/library/toolkit';
/* global d3 */

function generateChart(target_elem, legend_elem, topic_set, message_data) {
  var margin = {
      top: 40,
      right: 30,
      bottom: 30,
      left: 50
    },
    width = Ember.$(target_elem).width() - margin.left - margin.right,
    height = Ember.$(target_elem).height() - margin.top - margin.bottom;

  var parseDate = d3.time.format("%Y-%m-%dT%I:%M:%S").parse;
  var formatDate = d3.time.format("%m/%d");
  var formatCount = d3.format(",.0f");

  var x = d3.time.scale().range([0, width]);
  var y = d3.scale.linear().range([height, 0]);
  var color = d3.scale.category20();

  // fix the colors to the topic IDs so they're consistent between vis components
  color.domain(Object.keys(topic_set));

  var xAxis = d3.svg.axis().scale(x)
    .orient("bottom").tickFormat(formatDate);

  var yAxis = d3.svg.axis().scale(y)
    .orient("left").ticks(12);

  var stack = d3.layout.stack()
    .values(function(d) {
      return d.values;
    });

  // Create the SVG drawing area
  var svg = d3.select(target_elem)
    .append("g")
    .attr("transform", "translate(" + margin.left + "," + margin.top + ")");

  // Parse the date strings into javascript dates
  message_data.forEach(function(d) {
    d.received_on = parseDate(d.received_on);
  });

  // Determine the first and list dates in the data set
  var timeExtent = d3.extent(message_data, function(d) {
    return d.received_on;
  });

  // Create one bin per day, use an offset to include the first and last days(?)
  var dayBins = d3.time.days(d3.time.day.offset(timeExtent[0], -1),
    d3.time.day.offset(timeExtent[1], 0));

  // Use the histogram layout to create a function that will bin the data
  var binByDay = d3.layout.histogram()
    .value(function(d) {
      return d.received_on;
    })
    .bins(dayBins);

  // Use D3's nest function to group the data by borough
  var dataGroupedByBorough = d3.nest()
    .key(function(d) {
      return d.topics[0].topic_id;
    })
    .map(message_data, d3.map);

  // Apply the histogram binning function to the data and convert from
  // a map to an array so that the stack layout can consume it
  var histDataByBorough = [];
  dataGroupedByBorough.entries().map(function(o) {
    var key = o.key;
    var value = o.value;

    // Bin the data for each borough by day
    var histData = binByDay(value);
    histDataByBorough.push({
      topic_id: key,
      values: histData
    });
  });

  var stackedHistData = stack(histDataByBorough);

  // Scale the range of the data by setting the domain
  x.domain(d3.extent(dayBins));
  y.domain([0, d3.max(stackedHistData[stackedHistData.length - 1].values, function(d) {
    return d.y + d.y0;
  })]);

  // Define the div for the tooltip
  var div = d3.select("body").append("div")
    .attr("class", "topicstacked-tooltip")
    .style("opacity", 0);

  // Set up one group for each borough
  // Note that color doesn't have a domain set, so colors are assigned to boroughs
  // below on a first come, first serve basis
  var borough = svg.selectAll(".borough")
    .data(stackedHistData)
    .enter().append("g")
    .attr("class", "borough")
    .style("fill", function(d, i) {
      return color(d.topic_id);
    })
    .style("stroke", function(d, i) {
      return d3.rgb(color(d.topic_id)).darker();
    })
    .on("mouseover", function(d) {
      div.transition()
        .duration(200)
        .style("opacity", 0.9);
      div	.html(topic_set[d.topic_id])
        .style("left", (d3.event.pageX) + "px")
        .style("top", (d3.event.pageY - 28) + "px");
    })
    .on("mouseout", function(d) {
      div.transition()
        .duration(500)
        .style("opacity", 0);
    });

  // Months have slightly different lengths so calculate the width for each bin
  // Draw the rectangles, starting from the upper left corner and going down
  borough.selectAll(".bar")
    .data(function(d) {
      return d.values;
    })
    .enter().append("rect")
    .attr("class", "bar")
    .attr("x", function(d) {
      return x(d.x);
    })
    .attr("width", function(d) {
      return x(new Date(d.x.getTime() + d.dx)) - x(d.x) - 2;
    })
    .attr("y", function(d) {
      return y(d.y0 + d.y);
    })
    .attr("height", function(d) {
      return y(d.y0) - y(d.y0 + d.y);
    });

  // Add the X Axis
  svg.append("g")
    .attr("class", "x axis")
    .attr("transform", "translate(0," + height + ")")
    .call(xAxis);

  // Add the Y Axis and label
  svg.append("g")
    .attr("class", "y axis")
    .call(yAxis);
    /*
    .append("text")
    .attr("transform", "rotate(-90)")
    .attr("y", 6)
    .attr("dy", ".71em")
    .style("text-anchor", "end")
    .text("Number of Rat Sightings");
    */

  // Add the legend to the second box
  Ember.$.each(topic_set, function(k, v) {
    // colored box + label container
    var $topic_set = Ember.$("<div />")
      .css('margin', '3px')
      .css('margin-left', '50px')
      .css('display', 'flex');

    // colored box
    Ember.$("<div />")
      .css('width', '15px')
      .css('height', '15px')
      .css('margin-right', '3px')
      .css('background-color', color(k))
      .appendTo($topic_set);

    // label
    Ember.$("<div />")
      .text(v)
      .appendTo($topic_set);

    $topic_set.appendTo(legend_elem);
  });
}

export default BaseMod.extend({
  classNames: ['topic-stacked'],

  bind: function(start_date, end_date, filters) {
    var _this = this;

    // display the spinner
    this.$(".loader").show();

    var $boxShell = this.$(".topicstacked-box");
    var $target = this.$(".topicstacked-box svg");
    var $legend_target = this.$(".topic-legend");

    // remove any elements in the SVG
    $target.empty();
    $legend_target.empty();

    $target.attr('viewBox', `0 0 ${$boxShell.width()} ${$boxShell.height()}`);
    $target.attr('width', $boxShell.width());
    $target.attr('height', $boxShell.height());

    // we have to query for two things:
    // 1) the set of topics for this user
    // 2) the mail messages with associated 'topics' field keyed to set of topics

    _this.get('eaf_api').query('topic', {})
      .then(function(data) {
        var topic_set = data.objects.reduce(function(acc, v) { acc[v.id] = v.shortname; return acc; }, {});

        var params = {
          min_date: tools.apiTZDateTime(start_date),
          max_date: tools.apiTZDateTime(end_date),
          topics: 1
        };

        _this.applyAlterFilter(filters, params);

        // once we have the topics, we can query for the messages and build the rest of the graph
        _this.get('eaf_api').query('mail_message', params)
          .then(function(message_data) {
            var msg_topics = message_data.objects.map(function(v) {
              return {'received_on': v.received_on, 'topics': v.topics};
            }).filter(function(v) {
              return v.topics.length > 0;
            });

            generateChart($target.get(0), $legend_target.get(0), topic_set, msg_topics);

            // now we can generate the chart
            _this.$(".loader").hide();
          });
      });
  }
});
<|endoftext|>


<commit_before>import React, { Component } from "react";
import Select from "react-select";
import classNames from "classnames";
import manager from "../middleware/ChannelManager";
import * as TYPES from "../middleware/constants";

const helper = require("../middleware/helper");

export default class DataSearch extends Component {
	// Search results often contain duplicate results, so display only unique values
	removeDuplicates(myArr, prop) {
		return myArr.filter((obj, pos, arr) => arr.map(mapObj => mapObj[prop]).indexOf(obj[prop]) === pos);
	}

	constructor(props) {
		super(props);
		this.state = {
			items: [],
			currentValue: null,
			isLoading: false,
			options: [],
			rawData: {
				hits: {
					hits: []
				}
			}
		};
		this.type = "match_phrase";
		this.searchInputId = `internal-${this.props.componentId}`;
		this.channelId = null;
		this.channelListener = null;
		this.fieldType = typeof this.props.appbaseField;
		this.handleSearch = this.handleSearch.bind(this);
		this.handleInputChange = this.handleInputChange.bind(this);
		this.setValue = this.setValue.bind(this);
		this.defaultSearchQuery = this.defaultSearchQuery.bind(this);
		this.previousSelectedSensor = {};
	}

	// Get the items from Appbase when component is mounted
	componentDidMount() {
		this.setQueryInfo();
		this.createChannel();
		this.checkDefault();
	}

	componentWillUpdate() {
		this.checkDefault();
	}

	// stop streaming request and remove listener when component will unmount
	componentWillUnmount() {
		if (this.channelId) {
			manager.stopStream(this.channelId);
		}
		if (this.channelListener) {
			this.channelListener.remove();
		}
	}

	// set the query type and input data
	setQueryInfo() {
		const obj = {
			key: this.props.componentId,
			value: {
				queryType: this.type,
				inputData: this.props.appbaseField,
				customQuery: this.props.customQuery ? this.props.customQuery : this.defaultSearchQuery
			}
		};
		helper.selectedSensor.setSensorInfo(obj);
		const searchObj = {
			key: this.searchInputId,
			value: {
				queryType: "multi_match",
				inputData: this.props.appbaseField,
				customQuery: this.defaultSearchQuery
			}
		};
		helper.selectedSensor.setSensorInfo(searchObj);
	}

	// set value to search
	setValue(value) {
		const obj = {
			key: this.searchInputId,
			value
		};
		helper.selectedSensor.set(obj, true);
		if (value && value.trim() !== "") {
			this.setState({
				options: [{
					label: value,
					value
				}],
				isLoadingOptions: true,
				currentValue: value
			});
		} else {
			this.setState({
				options: [],
				isLoadingOptions: false,
				currentValue: value
			});
		}
	}

	// set data after get the result
	setData(data) {
		let options = [];
		let searchField = null;
		if (this.fieldType === "string") {
			searchField = `hit._source.${this.props.appbaseField}.trim()`;
		}
		data.hits.hits.map((hit) => {
			if (searchField) {
				options.push({ value: eval(searchField), label: eval(searchField) });
			} else if (this.fieldType === "object") {
				this.props.appbaseField.map((field) => {
					const tempField = `hit._source.${field}`;
					if (eval(tempField)) {
						options.push({ value: eval(tempField), label: eval(tempField) });
					}
				});
			}
		});
		if (this.state.currentValue && this.state.currentValue.trim() !== "") {
			options.unshift({
				label: this.state.currentValue,
				value: this.state.currentValue
			});
		}
		options = this.removeDuplicates(options, "label");
		this.setState({
			options,
			isLoadingOptions: false
		});
	}

	// default query
	defaultSearchQuery(value) {
		let finalQuery = null;
		if (value) {
			if (this.fieldType === "string") {
				return {
					match_phrase_prefix: {
						[this.props.appbaseField]: value
					}
				};
			}
			const query = [];
			this.props.appbaseField.map((field) => {
				query.push({
					match_phrase_prefix: {
						[field]: value
					}
				});
			});
			finalQuery = {
				bool: {
					should: query,
					minimum_should_match: 1
				}
			};
		}
		return finalQuery;
	}

	// Create a channel which passes the react and receive results whenever react changes
	createChannel() {
		const react = this.props.react ? this.props.react : {};
		if (react && react.and && typeof react.and === "string") {
			react.and = [react.and];
		} else {
			react.and = react.and ? react.and : [];
		}
		react.and.push(this.searchInputId);
		const channelObj = manager.create(this.context.appbaseRef, this.context.type, react);
		this.channelId = channelObj.channelId;
		this.channelListener = channelObj.emitter.addListener(channelObj.channelId, (res) => {
			const data = res.data;
			let rawData;
			if (res.mode === "streaming") {
				rawData = this.state.rawData;
				rawData.hits.hits.push(res.data);
			} else if (res.mode === "historic") {
				rawData = data;
			}
			this.setState({
				rawData
			});
			if (this.props.autocomplete) {
				this.setData(rawData);
			}
		});
	}

	checkDefault() {
		if (this.props.defaultSelected && this.defaultSelected !== this.props.defaultSelected) {
			this.defaultSelected = this.props.defaultSelected;
			setTimeout(this.setValue.bind(this, this.defaultSelected), 100);
			this.handleSearch({
				value: this.defaultSelected
			});
		}
	}

	// When user has selected a search value
	handleSearch(currentValue) {
		let value = currentValue ? currentValue.value : null;
		value = value === "null" ? null : value;
		const obj = {
			key: this.props.componentId,
			value
		};
		helper.selectedSensor.set(obj, true);
		this.setState({
			currentValue: value
		});
	}

	handleInputChange(event) {
		const inputVal = event.target.value;
		this.setState({
			currentValue: inputVal
		});
		const obj = {
			key: this.props.componentId,
			value: inputVal
		};
		if(this.props.onValueChange) {
			this.props.onValueChange(obj.value);
		}
		// pass the selected sensor value with componentId as key,
		const isExecuteQuery = true;
		helper.selectedSensor.set(obj, isExecuteQuery);
	}

	render() {
		let title = null;
		if (this.props.title) {
			title = (
{this.props.title}
);
		}
		const cx = classNames({
			"rbc-title-active": this.props.title,
			"rbc-title-inactive": !this.props.title,
			"rbc-placeholder-active": this.props.placeholder,
			"rbc-placeholder-inactive": !this.props.placeholder,
			"rbc-autocomplete-active": this.props.autocomplete,
			"rbc-autocomplete-inactive": !this.props.autocomplete
		});

		return (
			<div className={`rbc rbc-datasearch col s12 col-xs-12 card thumbnail ${cx}`}>
				{title}
				{
					this.props.autocomplete ?
						<Select
							isLoading={this.state.isLoadingOptions}
							value={this.state.currentValue}
							options={this.state.options}
							onInputChange={this.setValue}
							onChange={this.handleSearch}
							onBlurResetsInput={false}
							{...this.props}
						/> :

							<input
								type="text"
								className="rbc-input"
								placeholder={this.props.placeholder}
								value={this.state.currentValue ? this.state.currentValue : ""}
								onChange={this.handleInputChange}
							/>

				}

		);
	}
}

DataSearch.propTypes = {
	componentId: React.PropTypes.string.isRequired,
	appbaseField: React.PropTypes.oneOfType([
		React.PropTypes.string,
		React.PropTypes.arrayOf(React.PropTypes.string)
	]),
	title: React.PropTypes.oneOfType([
		React.PropTypes.string,
		React.PropTypes.element
	]),
	placeholder: React.PropTypes.string,
	autocomplete: React.PropTypes.bool,
	defaultSelected: React.PropTypes.string,
	customQuery: React.PropTypes.func,
	onValueChange: React.PropTypes.func,
	react: React.PropTypes.object
};

// Default props value
DataSearch.defaultProps = {
	placeholder: "Search",
	autocomplete: true
};

// context type
DataSearch.contextTypes = {
	appbaseRef: React.PropTypes.any.isRequired,
	type: React.PropTypes.any.isRequired
};

DataSearch.types = {
	componentId: TYPES.STRING,
	appbaseField: TYPES.STRING,
	appbaseFieldType: TYPES.STRING,
	react: TYPES.OBJECT,
	title: TYPES.STRING,
	placeholder: TYPES.STRING,
	autocomplete: TYPES.BOOLEAN,
	defaultSelected: TYPES.STRING,
	customQuery: TYPES.FUNCTION
};
<commit_msg>Fix DataSearch suggestion value behavior<commit_after>import React, { Component } from "react";
import Select from "react-select";
import classNames from "classnames";
import manager from "../middleware/ChannelManager";
import * as TYPES from "../middleware/constants";

const _ = require("lodash");
const helper = require("../middleware/helper");

export default class DataSearch extends Component {
	// Search results often contain duplicate results, so display only unique values
	removeDuplicates(myArr, prop) {
		return myArr.filter((obj, pos, arr) => arr.map(mapObj => mapObj[prop]).indexOf(obj[prop]) === pos);
	}

	constructor(props) {
		super(props);
		this.state = {
			items: [],
			currentValue: null,
			isLoading: false,
			options: [],
			rawData: {
				hits: {
					hits: []
				}
			}
		};
		this.type = "match_phrase";
		this.searchInputId = `internal-${this.props.componentId}`;
		this.channelId = null;
		this.channelListener = null;
		this.fieldType = typeof this.props.appbaseField;
		this.handleSearch = this.handleSearch.bind(this);
		this.handleInputChange = this.handleInputChange.bind(this);
		this.setValue = this.setValue.bind(this);
		this.defaultSearchQuery = this.defaultSearchQuery.bind(this);
		this.previousSelectedSensor = {};
	}

	// Get the items from Appbase when component is mounted
	componentDidMount() {
		this.setQueryInfo();
		this.createChannel();
		this.checkDefault();
	}

	componentWillUpdate() {
		this.checkDefault();
	}

	// stop streaming request and remove listener when component will unmount
	componentWillUnmount() {
		if (this.channelId) {
			manager.stopStream(this.channelId);
		}
		if (this.channelListener) {
			this.channelListener.remove();
		}
	}

	// set the query type and input data
	setQueryInfo() {
		const obj = {
			key: this.props.componentId,
			value: {
				queryType: this.type,
				inputData: this.props.appbaseField,
				customQuery: this.props.customQuery ? this.props.customQuery : this.defaultSearchQuery
			}
		};
		helper.selectedSensor.setSensorInfo(obj);
		const searchObj = {
			key: this.searchInputId,
			value: {
				queryType: "multi_match",
				inputData: this.props.appbaseField,
				customQuery: this.defaultSearchQuery
			}
		};
		helper.selectedSensor.setSensorInfo(searchObj);
	}

	// set value to search
	setValue(value) {
		const obj = {
			key: this.searchInputId,
			value
		};
		helper.selectedSensor.set(obj, true);
		if (value && value.trim() !== "") {
			this.setState({
				options: [{
					label: value,
					value
				}],
				isLoadingOptions: true,
				currentValue: value
			});
		} else {
			this.setState({
				options: [],
				isLoadingOptions: false,
				currentValue: value
			});
		}
	}

	getValue(field, hit) {
		let val;
		if(_.has(hit, field)) {
			val = hit[field];
		} else if(field.indexOf(".") > -1) {
			let prefix = "";
			const fieldSplit = field.split(".");
			fieldSplit.forEach((item, index) => {
				prefix += item;
				if(_.isArray(_.get(hit, prefix))) {
					prefix += "[0]";
				}
				if(fieldSplit.length-1 !== index) {
					prefix += ".";
				} else {
					val = _.get(hit, prefix);
				}
			});
		}
		return val;
	}

	// set data after get the result
	setData(data) {
		let options = [];
		data.hits.hits.map((hit) => {
			if (this.fieldType === "string") {
				const tempField = this.getValue(this.props.appbaseField.trim(), hit._source);
				options.push({ value: tempField, label: tempField });
			} else if (this.fieldType === "object") {
				this.props.appbaseField.map((field) => {
					const tempField = this.getValue(field, hit._source);
					if (tempField) {
						options.push({ value: tempField, label: tempField });
					}
				});
			}
		});
		if (this.state.currentValue && this.state.currentValue.trim() !== "") {
			options.unshift({
				label: this.state.currentValue,
				value: this.state.currentValue
			});
		}
		options = this.removeDuplicates(options, "label");
		this.setState({
			options,
			isLoadingOptions: false
		});
	}

	// default query
	defaultSearchQuery(value) {
		let finalQuery = null;
		if (value) {
			if (this.fieldType === "string") {
				return {
					match_phrase_prefix: {
						[this.props.appbaseField]: value
					}
				};
			}
			const query = [];
			this.props.appbaseField.map((field) => {
				query.push({
					match_phrase_prefix: {
						[field]: value
					}
				});
			});
			finalQuery = {
				bool: {
					should: query,
					minimum_should_match: 1
				}
			};
		}
		return finalQuery;
	}

	// Create a channel which passes the react and receive results whenever react changes
	createChannel() {
		const react = this.props.react ? this.props.react : {};
		if (react && react.and && typeof react.and === "string") {
			react.and = [react.and];
		} else {
			react.and = react.and ? react.and : [];
		}
		react.and.push(this.searchInputId);
		const channelObj = manager.create(this.context.appbaseRef, this.context.type, react);
		this.channelId = channelObj.channelId;
		this.channelListener = channelObj.emitter.addListener(channelObj.channelId, (res) => {
			const data = res.data;
			let rawData;
			if (res.mode === "streaming") {
				rawData = this.state.rawData;
				rawData.hits.hits.push(res.data);
			} else if (res.mode === "historic") {
				rawData = data;
			}
			this.setState({
				rawData
			});
			if (this.props.autocomplete) {
				this.setData(rawData);
			}
		});
	}

	checkDefault() {
		if (this.props.defaultSelected && this.defaultSelected !== this.props.defaultSelected) {
			this.defaultSelected = this.props.defaultSelected;
			setTimeout(this.setValue.bind(this, this.defaultSelected), 100);
			this.handleSearch({
				value: this.defaultSelected
			});
		}
	}

	// When user has selected a search value
	handleSearch(currentValue) {
		let value = currentValue ? currentValue.value : null;
		value = value === "null" ? null : value;
		const obj = {
			key: this.props.componentId,
			value
		};
		helper.selectedSensor.set(obj, true);
		this.setState({
			currentValue: value
		});
	}

	handleInputChange(event) {
		const inputVal = event.target.value;
		this.setState({
			currentValue: inputVal
		});
		const obj = {
			key: this.props.componentId,
			value: inputVal
		};
		if(this.props.onValueChange) {
			this.props.onValueChange(obj.value);
		}
		// pass the selected sensor value with componentId as key,
		const isExecuteQuery = true;
		helper.selectedSensor.set(obj, isExecuteQuery);
	}

	render() {
		let title = null;
		if (this.props.title) {
			title = (
{this.props.title}
);
		}
		const cx = classNames({
			"rbc-title-active": this.props.title,
			"rbc-title-inactive": !this.props.title,
			"rbc-placeholder-active": this.props.placeholder,
			"rbc-placeholder-inactive": !this.props.placeholder,
			"rbc-autocomplete-active": this.props.autocomplete,
			"rbc-autocomplete-inactive": !this.props.autocomplete
		});

		return (
			<div className={`rbc rbc-datasearch col s12 col-xs-12 card thumbnail ${cx}`}>
				{title}
				{
					this.props.autocomplete ?
						<Select
							isLoading={this.state.isLoadingOptions}
							value={this.state.currentValue}
							options={this.state.options}
							onInputChange={this.setValue}
							onChange={this.handleSearch}
							onBlurResetsInput={false}
							{...this.props}
						/> :

							<input
								type="text"
								className="rbc-input"
								placeholder={this.props.placeholder}
								value={this.state.currentValue ? this.state.currentValue : ""}
								onChange={this.handleInputChange}
							/>

				}

		);
	}
}

DataSearch.propTypes = {
	componentId: React.PropTypes.string.isRequired,
	appbaseField: React.PropTypes.oneOfType([
		React.PropTypes.string,
		React.PropTypes.arrayOf(React.PropTypes.string)
	]),
	title: React.PropTypes.oneOfType([
		React.PropTypes.string,
		React.PropTypes.element
	]),
	placeholder: React.PropTypes.string,
	autocomplete: React.PropTypes.bool,
	defaultSelected: React.PropTypes.string,
	customQuery: React.PropTypes.func,
	onValueChange: React.PropTypes.func,
	react: React.PropTypes.object
};

// Default props value
DataSearch.defaultProps = {
	placeholder: "Search",
	autocomplete: true
};

// context type
DataSearch.contextTypes = {
	appbaseRef: React.PropTypes.any.isRequired,
	type: React.PropTypes.any.isRequired
};

DataSearch.types = {
	componentId: TYPES.STRING,
	appbaseField: TYPES.STRING,
	appbaseFieldType: TYPES.STRING,
	react: TYPES.OBJECT,
	title: TYPES.STRING,
	placeholder: TYPES.STRING,
	autocomplete: TYPES.BOOLEAN,
	defaultSelected: TYPES.STRING,
	customQuery: TYPES.FUNCTION
};
<|endoftext|>


<commit_before>/*** @using { core.RAIIEventEmitter } **/
/*** @using { core.Text } **/
/*** @using { core.Image } **/

exports.capabilities = {}
var runtime = _globals.pure.runtime
var renderer = null
var rootItem = null

var Rect = runtime.Rect
var Element = runtime.Element

var Renderer = function(w, h) {
	this.width = w
	this.height = h
	log('creating renderer ' + w + 'x' + h)
}

var Image = function() { }
var Text = function() { }

exports.init = function(ctx) {
	log('backend initialization...')
	ctx._updatedItems = []
	renderer = new Renderer(480, 640) //fixme: pass in options?
	rootItem = ctx.element = new Element(ctx, ctx.getTag())
	ctx.width = renderer.width
	ctx.height = renderer.height
}

exports.run = function(ctx) {
	ctx._run()
}

exports.createElement = function(ctx, tag) {
	return new Element(ctx, tag)
}

exports.initImage = function(image) {
	var element = image.element
	element._image = new Image()
}

var ImageStatusNull			= 0
var ImageStatusLoaded		= 1
var ImageStatusUnloaded		= 2
var ImageStatusError		= 3

exports.loadImage = function(image) {
	log('loading image ' + image.source)
	var Image = _globals.core.Image
	var element = image.element
	image.status = Image.Loading
	element._image.load(image.source, function(status) {
		log('image ' + image.source + ' status: ' + status + ' ' + element._image.width + ' ' + element._image.height)
		image.paintedWidth = element._image.width
		image.paintedHeight = element._image.height
		if (!image.width)
			image.width = image.paintedWidth
		if (!image.height)
			image.height = image.paintedHeight
		switch(status) {
			case ImageStatusNull:	image.status = Image.Null; break
			case ImageStatusLoaded:	image.status = Image.Ready; break
			case ImageStatusError:	image.status = Image.Error; break
		}
		element.update()
	})
}

Element.prototype.setHtml = function(html) {
	this._text.text = html
	this.layoutText()
}

Element.prototype.layoutText = function() {
	var text = this._text, ui = this.ui, font = ui.font
	if (text.font !== font)
		text.font = font

	var w = text.width, h = text.height
	ui.paintedWidth = w
	ui.paintedHeight = h
	switch(this._styles['text-align']) {
		case 'right':
			this._offsetX = ui.width - w
			break
		case 'center':
			this._offsetX = Math.floor((ui.width - w) / 2)
			break
		default:
			this._offsetX = 0
			break
	}
	// for(var name in this._styles)
	// 	log('text style', name, this._styles[name])
	this.update()
}

var _paintText = function(renderer, rect) {
	renderer.paintText(rect.moved(this._offsetX, this._offsetY), this._text)
}

exports.initText = function(text) {
	var element = text.element
	element._offsetX = 0
	element._offsetY = 0
	element.ui = text
	element._text = new Text()
	element._text.text = text.text
	element._paint = _paintText
	element.update()
}

exports.layoutText = function(text) {
	text.element.layoutText()
}

exports.requestAnimationFrame = function(callback) {
	return setTimeout(callback, 0)
}

exports.cancelAnimationFrame = function (timer) {
	clearTimeout(timer)
}

var Renderer = function(w, h) {
	this.width = w
	this.height = h
	this.clip = this.getRect()
	this.rect = this.getRect()
	this.depth = 0
}

Renderer.prototype.prefix = function() {
	var d = this.depth, r = '' + d + ':'
	while(d-- > 0)
		r += '  '
	return r
}

Renderer.prototype.getRect = function() {
	return new Rect(0, 0, this.width, this.height)
}

Renderer.prototype.paintRectangle = function(rect, color) {
	if (!rect.valid())
		return
	log(this.prefix() + 'paint rect ' + rect + ' with color ' + color)
	_renderRect(rect.l, rect.t, rect.r, rect.b, r, g, b, a)
}

Renderer.prototype.paintText = function(rect, text) {
	if (!rect.valid())
		return
	log(this.prefix() + 'paint text ' + rect + ' ' + text)
	_renderText(rect.l, rect.t, rect.r, rect.b, text)
}

Renderer.prototype.paintImage = function(rect, image) {
	if (!rect.valid())
		return
	log(this.prefix() + 'paint image ' + rect + ' ' + image)
	_renderImage(rect.l, rect.t, rect.r, rect.b, image)
}
exports.Renderer = Renderer
<commit_msg>added setClip method<commit_after>/*** @using { core.RAIIEventEmitter } **/
/*** @using { core.Text } **/
/*** @using { core.Image } **/

exports.capabilities = {}
var runtime = _globals.pure.runtime
var renderer = null
var rootItem = null

var Rect = runtime.Rect
var Element = runtime.Element

var Image = function() { }
var Text = function() { }

exports.init = function(ctx) {
	log('backend initialization...')
	ctx._updatedItems = []
	renderer = new Renderer(480, 640) //fixme: pass in options?
	ctx.renderer = renderer
	rootItem = ctx.element = new Element(ctx, ctx.getTag())
	ctx.width = renderer.width
	ctx.height = renderer.height
}

exports.run = function(ctx) {
	ctx._run()
	runtime.renderFrame(ctx)
}

exports.createElement = function(ctx, tag) {
	return new Element(ctx, tag)
}

exports.initImage = function(image) {
	var element = image.element
	element._image = new Image()
}

var ImageStatusNull			= 0
var ImageStatusLoaded		= 1
var ImageStatusUnloaded		= 2
var ImageStatusError		= 3

exports.loadImage = function(image) {
	log('loading image ' + image.source)
	var Image = _globals.core.Image
	var element = image.element
	image.status = Image.Loading
	element._image.load(image.source, function(status) {
		log('image ' + image.source + ' status: ' + status + ' ' + element._image.width + ' ' + element._image.height)
		image.paintedWidth = element._image.width
		image.paintedHeight = element._image.height
		if (!image.width)
			image.width = image.paintedWidth
		if (!image.height)
			image.height = image.paintedHeight
		switch(status) {
			case ImageStatusNull:	image.status = Image.Null; break
			case ImageStatusLoaded:	image.status = Image.Ready; break
			case ImageStatusError:	image.status = Image.Error; break
		}
		element.update()
	})
}

Element.prototype.setHtml = function(html) {
	this._text.text = html
	this.layoutText()
}

Element.prototype.layoutText = function() {
	var text = this._text, ui = this.ui, font = ui.font
	if (text.font !== font)
		text.font = font

	var w = text.width, h = text.height
	ui.paintedWidth = w
	ui.paintedHeight = h
	switch(this._styles['text-align']) {
		case 'right':
			this._offsetX = ui.width - w
			break
		case 'center':
			this._offsetX = Math.floor((ui.width - w) / 2)
			break
		default:
			this._offsetX = 0
			break
	}
	// for(var name in this._styles)
	// 	log('text style', name, this._styles[name])
	this.update()
}

var _paintText = function(renderer, rect) {
	renderer.paintText(rect.moved(this._offsetX, this._offsetY), this._text)
}

exports.initText = function(text) {
	var element = text.element
	element._offsetX = 0
	element._offsetY = 0
	element.ui = text
	element._text = new Text()
	element._text.text = text.text
	element._paint = _paintText
	element.update()
}

exports.layoutText = function(text) {
	text.element.layoutText()
}

exports.requestAnimationFrame = function(callback) {
	return setTimeout(callback, 0)
}

exports.cancelAnimationFrame = function (timer) {
	clearTimeout(timer)
}

var Renderer = function(w, h) {
	this.width = w
	this.height = h
	this.clip = this.getRect()
	this.rect = this.getRect()
	this.depth = 0
}

Renderer.prototype.setClip = function(clip) {
	log('setting clip to ' + clip)
}

Renderer.prototype.prefix = function() {
	var d = this.depth, r = '' + d + ':'
	while(d-- > 0)
		r += '  '
	return r
}

Renderer.prototype.getRect = function() {
	return new Rect(0, 0, this.width, this.height)
}

Renderer.prototype.paintRectangle = function(rect, color) {
	if (!rect.valid())
		return
	log(this.prefix() + 'paint rect ' + rect + ' with color ' + color)
	_renderRect(rect.l, rect.t, rect.r, rect.b, r, g, b, a)
}

Renderer.prototype.paintText = function(rect, text) {
	if (!rect.valid())
		return
	log(this.prefix() + 'paint text ' + rect + ' ' + text)
	_renderText(rect.l, rect.t, rect.r, rect.b, text)
}

Renderer.prototype.paintImage = function(rect, image) {
	if (!rect.valid())
		return
	log(this.prefix() + 'paint image ' + rect + ' ' + image)
	_renderImage(rect.l, rect.t, rect.r, rect.b, image)
}
exports.Renderer = Renderer
<|endoftext|>


<commit_before>/**
 * @license
 * Copyright 2016 Google LLC
 * SPDX-License-Identifier: Apache-2.0
 */

/**
 * @fileoverview Class for a button in the flyout.
 * @author fenichel@google.com (Rachel Fenichel)
 */
'use strict';

goog.module('Blockly.FlyoutButton');
goog.module.declareLegacyNamespace();

goog.require('Blockly.browserEvents');
goog.require('Blockly.Css');
goog.require('Blockly.utils');
goog.require('Blockly.utils.Coordinate');
goog.require('Blockly.utils.dom');
goog.require('Blockly.utils.style');
goog.require('Blockly.utils.Svg');

goog.requireType('Blockly.utils.toolbox');
goog.requireType('Blockly.WorkspaceSvg');

/**
 * Class for a button in the flyout.
 * @param {!Blockly.WorkspaceSvg} workspace The workspace in which to place this
 *     button.
 * @param {!Blockly.WorkspaceSvg} targetWorkspace The flyout's target workspace.
 * @param {!Blockly.utils.toolbox.ButtonOrLabelInfo} json
 *    The JSON specifying the label/button.
 * @param {boolean} isLabel Whether this button should be styled as a label.
 * @constructor
 * @package
 */
const FlyoutButton = function(workspace, targetWorkspace, json, isLabel) {
  // Labels behave the same as buttons, but are styled differently.

  /**
   * @type {!Blockly.WorkspaceSvg}
   * @private
   */
  this.workspace_ = workspace;

  /**
   * @type {!Blockly.WorkspaceSvg}
   * @private
   */
  this.targetWorkspace_ = targetWorkspace;

  /**
   * @type {string}
   * @private
   */
  this.text_ = json['text'];

  /**
   * @type {!Blockly.utils.Coordinate}
   * @private
   */
  this.position_ = new Blockly.utils.Coordinate(0, 0);

  /**
   * Whether this button should be styled as a label.
   * @type {boolean}
   * @private
   */
  this.isLabel_ = isLabel;

  /**
   * The key to the function called when this button is clicked.
   * @type {string}
   * @private
   */
  this.callbackKey_ = json['callbackKey'] ||
  /* Check the lower case version too to satisfy IE */
                      json['callbackkey'];

  /**
   * If specified, a CSS class to add to this button.
   * @type {?string}
   * @private
   */
  this.cssClass_ = json['web-class'] || null;

  /**
   * Mouse up event data.
   * @type {?Blockly.browserEvents.Data}
   * @private
   */
  this.onMouseUpWrapper_ = null;

  /**
   * The JSON specifying the label / button.
   * @type {!Blockly.utils.toolbox.ButtonOrLabelInfo}
   */
  this.info = json;
};

/**
 * The horizontal margin around the text in the button.
 */
FlyoutButton.MARGIN_X = 5;

/**
 * The vertical margin around the text in the button.
 */
FlyoutButton.MARGIN_Y = 2;

/**
 * The width of the button's rect.
 * @type {number}
 */
FlyoutButton.prototype.width = 0;

/**
 * The height of the button's rect.
 * @type {number}
 */
FlyoutButton.prototype.height = 0;

/**
 * Create the button elements.
 * @return {!SVGElement} The button's SVG group.
 */
FlyoutButton.prototype.createDom = function() {
  let cssClass = this.isLabel_ ? 'blocklyFlyoutLabel' : 'blocklyFlyoutButton';
  if (this.cssClass_) {
    cssClass += ' ' + this.cssClass_;
  }

  this.svgGroup_ = Blockly.utils.dom.createSvgElement(
      Blockly.utils.Svg.G, {'class': cssClass},
      this.workspace_.getCanvas());

  let shadow;
  if (!this.isLabel_) {
    // Shadow rectangle (light source does not mirror in RTL).
    shadow = Blockly.utils.dom.createSvgElement(
        Blockly.utils.Svg.RECT,
        {
          'class': 'blocklyFlyoutButtonShadow',
          'rx': 4, 'ry': 4, 'x': 1, 'y': 1
        },
        this.svgGroup_);
  }
  // Background rectangle.
  const rect = Blockly.utils.dom.createSvgElement(
      Blockly.utils.Svg.RECT,
      {
        'class': this.isLabel_ ?
            'blocklyFlyoutLabelBackground' : 'blocklyFlyoutButtonBackground',
        'rx': 4, 'ry': 4
      },
      this.svgGroup_);

  const svgText = Blockly.utils.dom.createSvgElement(
      Blockly.utils.Svg.TEXT,
      {
        'class': this.isLabel_ ? 'blocklyFlyoutLabelText' : 'blocklyText',
        'x': 0,
        'y': 0,
        'text-anchor': 'middle'
      },
      this.svgGroup_);
  let text = Blockly.utils.replaceMessageReferences(this.text_);
  if (this.workspace_.RTL) {
    // Force text to be RTL by adding an RLM.
    text += '\u200F';
  }
  svgText.textContent = text;
  if (this.isLabel_) {
    this.svgText_ = svgText;
    this.workspace_.getThemeManager().subscribe(this.svgText_,
        'flyoutForegroundColour', 'fill');
  }

  const fontSize = Blockly.utils.style.getComputedStyle(svgText, 'fontSize');
  const fontWeight = Blockly.utils.style.getComputedStyle(svgText, 'fontWeight');
  const fontFamily = Blockly.utils.style.getComputedStyle(svgText, 'fontFamily');
  this.width = Blockly.utils.dom.getFastTextWidthWithSizeString(svgText,
      fontSize, fontWeight, fontFamily);
  const fontMetrics = Blockly.utils.dom.measureFontMetrics(text, fontSize,
      fontWeight, fontFamily);
  this.height = fontMetrics.height;

  if (!this.isLabel_) {
    this.width += 2 * FlyoutButton.MARGIN_X;
    this.height += 2 * FlyoutButton.MARGIN_Y;
    shadow.setAttribute('width', this.width);
    shadow.setAttribute('height', this.height);
  }
  rect.setAttribute('width', this.width);
  rect.setAttribute('height', this.height);

  svgText.setAttribute('x', this.width / 2);
  svgText.setAttribute('y', this.height / 2 - fontMetrics.height / 2 +
      fontMetrics.baseline);

  this.updateTransform_();

  this.onMouseUpWrapper_ = Blockly.browserEvents.conditionalBind(
      this.svgGroup_, 'mouseup', this, this.onMouseUp_);
  return this.svgGroup_;
};

/**
 * Correctly position the flyout button and make it visible.
 */
FlyoutButton.prototype.show = function() {
  this.updateTransform_();
  this.svgGroup_.setAttribute('display', 'block');
};

/**
 * Update SVG attributes to match internal state.
 * @private
 */
FlyoutButton.prototype.updateTransform_ = function() {
  this.svgGroup_.setAttribute('transform',
      'translate(' + this.position_.x + ',' + this.position_.y + ')');
};

/**
 * Move the button to the given x, y coordinates.
 * @param {number} x The new x coordinate.
 * @param {number} y The new y coordinate.
 */
FlyoutButton.prototype.moveTo = function(x, y) {
  this.position_.x = x;
  this.position_.y = y;
  this.updateTransform_();
};

/**
 * @return {boolean} Whether or not the button is a label.
 */
FlyoutButton.prototype.isLabel = function() {
  return this.isLabel_;
};

/**
 * Location of the button.
 * @return {!Blockly.utils.Coordinate} x, y coordinates.
 * @package
 */
FlyoutButton.prototype.getPosition = function() {
  return this.position_;
};

/**
 * @return {string} Text of the button.
 */
FlyoutButton.prototype.getButtonText = function() {
  return this.text_;
};

/**
 * Get the button's target workspace.
 * @return {!Blockly.WorkspaceSvg} The target workspace of the flyout where this
 *     button resides.
 */
FlyoutButton.prototype.getTargetWorkspace = function() {
  return this.targetWorkspace_;
};

/**
 * Dispose of this button.
 */
FlyoutButton.prototype.dispose = function() {
  if (this.onMouseUpWrapper_) {
    Blockly.browserEvents.unbind(this.onMouseUpWrapper_);
  }
  if (this.svgGroup_) {
    Blockly.utils.dom.removeNode(this.svgGroup_);
  }
  if (this.svgText_) {
    this.workspace_.getThemeManager().unsubscribe(this.svgText_);
  }
};

/**
 * Do something when the button is clicked.
 * @param {!Event} e Mouse up event.
 * @private
 */
FlyoutButton.prototype.onMouseUp_ = function(e) {
  const gesture = this.targetWorkspace_.getGesture(e);
  if (gesture) {
    gesture.cancel();
  }

  if (this.isLabel_ && this.callbackKey_) {
    console.warn('Labels should not have callbacks. Label text: ' + this.text_);
  } else if (!this.isLabel_ && !(this.callbackKey_ &&
      this.targetWorkspace_.getButtonCallback(this.callbackKey_))) {
    console.warn('Buttons should have callbacks. Button text: ' + this.text_);
  } else if (!this.isLabel_) {
    this.targetWorkspace_.getButtonCallback(this.callbackKey_)(this);
  }
};

/**
 * CSS for buttons and labels.  See css.js for use.
 */
Blockly.Css.register([
  /* eslint-disable indent */
  '.blocklyFlyoutButton {',
    'fill: #888;',
    'cursor: default;',
  '}',

  '.blocklyFlyoutButtonShadow {',
    'fill: #666;',
  '}',

  '.blocklyFlyoutButton:hover {',
    'fill: #aaa;',
  '}',

  '.blocklyFlyoutLabel {',
    'cursor: default;',
  '}',

  '.blocklyFlyoutLabelBackground {',
    'opacity: 0;',
  '}',
  /* eslint-enable indent */
]);

exports = FlyoutButton;
<commit_msg>Migrate core/flyout_button.js named requires<commit_after>/**
 * @license
 * Copyright 2016 Google LLC
 * SPDX-License-Identifier: Apache-2.0
 */

/**
 * @fileoverview Class for a button in the flyout.
 * @author fenichel@google.com (Rachel Fenichel)
 */
'use strict';

goog.module('Blockly.FlyoutButton');
goog.module.declareLegacyNamespace();

const Coordinate = goog.require('Blockly.utils.Coordinate');
const Css = goog.require('Blockly.Css');
const Svg = goog.require('Blockly.utils.Svg');
/* eslint-disable-next-line no-unused-vars */
const WorkspaceSvg = goog.requireType('Blockly.WorkspaceSvg');
const browserEvents = goog.require('Blockly.browserEvents');
const dom = goog.require('Blockly.utils.dom');
const style = goog.require('Blockly.utils.style');
/* eslint-disable-next-line no-unused-vars */
const toolbox = goog.requireType('Blockly.utils.toolbox');
const {replaceMessageReferences} = goog.require('Blockly.utils');

/**
 * Class for a button in the flyout.
 * @param {!WorkspaceSvg} workspace The workspace in which to place this
 *     button.
 * @param {!WorkspaceSvg} targetWorkspace The flyout's target workspace.
 * @param {!toolbox.ButtonOrLabelInfo} json
 *    The JSON specifying the label/button.
 * @param {boolean} isLabel Whether this button should be styled as a label.
 * @constructor
 * @package
 */
const FlyoutButton = function(workspace, targetWorkspace, json, isLabel) {
  // Labels behave the same as buttons, but are styled differently.

  /**
   * @type {!WorkspaceSvg}
   * @private
   */
  this.workspace_ = workspace;

  /**
   * @type {!WorkspaceSvg}
   * @private
   */
  this.targetWorkspace_ = targetWorkspace;

  /**
   * @type {string}
   * @private
   */
  this.text_ = json['text'];

  /**
   * @type {!Coordinate}
   * @private
   */
  this.position_ = new Coordinate(0, 0);

  /**
   * Whether this button should be styled as a label.
   * @type {boolean}
   * @private
   */
  this.isLabel_ = isLabel;

  /**
   * The key to the function called when this button is clicked.
   * @type {string}
   * @private
   */
  this.callbackKey_ = json['callbackKey'] ||
  /* Check the lower case version too to satisfy IE */
                      json['callbackkey'];

  /**
   * If specified, a CSS class to add to this button.
   * @type {?string}
   * @private
   */
  this.cssClass_ = json['web-class'] || null;

  /**
   * Mouse up event data.
   * @type {?browserEvents.Data}
   * @private
   */
  this.onMouseUpWrapper_ = null;

  /**
   * The JSON specifying the label / button.
   * @type {!toolbox.ButtonOrLabelInfo}
   */
  this.info = json;
};

/**
 * The horizontal margin around the text in the button.
 */
FlyoutButton.MARGIN_X = 5;

/**
 * The vertical margin around the text in the button.
 */
FlyoutButton.MARGIN_Y = 2;

/**
 * The width of the button's rect.
 * @type {number}
 */
FlyoutButton.prototype.width = 0;

/**
 * The height of the button's rect.
 * @type {number}
 */
FlyoutButton.prototype.height = 0;

/**
 * Create the button elements.
 * @return {!SVGElement} The button's SVG group.
 */
FlyoutButton.prototype.createDom = function() {
  let cssClass = this.isLabel_ ? 'blocklyFlyoutLabel' : 'blocklyFlyoutButton';
  if (this.cssClass_) {
    cssClass += ' ' + this.cssClass_;
  }

  this.svgGroup_ = dom.createSvgElement(
      Svg.G, {'class': cssClass},
      this.workspace_.getCanvas());

  let shadow;
  if (!this.isLabel_) {
    // Shadow rectangle (light source does not mirror in RTL).
    shadow = dom.createSvgElement(
        Svg.RECT,
        {
          'class': 'blocklyFlyoutButtonShadow',
          'rx': 4, 'ry': 4, 'x': 1, 'y': 1
        },
        this.svgGroup_);
  }
  // Background rectangle.
  const rect = dom.createSvgElement(
      Svg.RECT,
      {
        'class': this.isLabel_ ?
            'blocklyFlyoutLabelBackground' : 'blocklyFlyoutButtonBackground',
        'rx': 4, 'ry': 4
      },
      this.svgGroup_);

  const svgText = dom.createSvgElement(
      Svg.TEXT,
      {
        'class': this.isLabel_ ? 'blocklyFlyoutLabelText' : 'blocklyText',
        'x': 0,
        'y': 0,
        'text-anchor': 'middle'
      },
      this.svgGroup_);
  let text = replaceMessageReferences(this.text_);
  if (this.workspace_.RTL) {
    // Force text to be RTL by adding an RLM.
    text += '\u200F';
  }
  svgText.textContent = text;
  if (this.isLabel_) {
    this.svgText_ = svgText;
    this.workspace_.getThemeManager().subscribe(this.svgText_,
        'flyoutForegroundColour', 'fill');
  }

  const fontSize = style.getComputedStyle(svgText, 'fontSize');
  const fontWeight = style.getComputedStyle(svgText, 'fontWeight');
  const fontFamily = style.getComputedStyle(svgText, 'fontFamily');
  this.width = dom.getFastTextWidthWithSizeString(svgText,
      fontSize, fontWeight, fontFamily);
  const fontMetrics = dom.measureFontMetrics(text, fontSize,
      fontWeight, fontFamily);
  this.height = fontMetrics.height;

  if (!this.isLabel_) {
    this.width += 2 * FlyoutButton.MARGIN_X;
    this.height += 2 * FlyoutButton.MARGIN_Y;
    shadow.setAttribute('width', this.width);
    shadow.setAttribute('height', this.height);
  }
  rect.setAttribute('width', this.width);
  rect.setAttribute('height', this.height);

  svgText.setAttribute('x', this.width / 2);
  svgText.setAttribute('y', this.height / 2 - fontMetrics.height / 2 +
      fontMetrics.baseline);

  this.updateTransform_();

  this.onMouseUpWrapper_ = browserEvents.conditionalBind(
      this.svgGroup_, 'mouseup', this, this.onMouseUp_);
  return this.svgGroup_;
};

/**
 * Correctly position the flyout button and make it visible.
 */
FlyoutButton.prototype.show = function() {
  this.updateTransform_();
  this.svgGroup_.setAttribute('display', 'block');
};

/**
 * Update SVG attributes to match internal state.
 * @private
 */
FlyoutButton.prototype.updateTransform_ = function() {
  this.svgGroup_.setAttribute('transform',
      'translate(' + this.position_.x + ',' + this.position_.y + ')');
};

/**
 * Move the button to the given x, y coordinates.
 * @param {number} x The new x coordinate.
 * @param {number} y The new y coordinate.
 */
FlyoutButton.prototype.moveTo = function(x, y) {
  this.position_.x = x;
  this.position_.y = y;
  this.updateTransform_();
};

/**
 * @return {boolean} Whether or not the button is a label.
 */
FlyoutButton.prototype.isLabel = function() {
  return this.isLabel_;
};

/**
 * Location of the button.
 * @return {!Coordinate} x, y coordinates.
 * @package
 */
FlyoutButton.prototype.getPosition = function() {
  return this.position_;
};

/**
 * @return {string} Text of the button.
 */
FlyoutButton.prototype.getButtonText = function() {
  return this.text_;
};

/**
 * Get the button's target workspace.
 * @return {!WorkspaceSvg} The target workspace of the flyout where this
 *     button resides.
 */
FlyoutButton.prototype.getTargetWorkspace = function() {
  return this.targetWorkspace_;
};

/**
 * Dispose of this button.
 */
FlyoutButton.prototype.dispose = function() {
  if (this.onMouseUpWrapper_) {
    browserEvents.unbind(this.onMouseUpWrapper_);
  }
  if (this.svgGroup_) {
    dom.removeNode(this.svgGroup_);
  }
  if (this.svgText_) {
    this.workspace_.getThemeManager().unsubscribe(this.svgText_);
  }
};

/**
 * Do something when the button is clicked.
 * @param {!Event} e Mouse up event.
 * @private
 */
FlyoutButton.prototype.onMouseUp_ = function(e) {
  const gesture = this.targetWorkspace_.getGesture(e);
  if (gesture) {
    gesture.cancel();
  }

  if (this.isLabel_ && this.callbackKey_) {
    console.warn('Labels should not have callbacks. Label text: ' + this.text_);
  } else if (!this.isLabel_ && !(this.callbackKey_ &&
      this.targetWorkspace_.getButtonCallback(this.callbackKey_))) {
    console.warn('Buttons should have callbacks. Button text: ' + this.text_);
  } else if (!this.isLabel_) {
    this.targetWorkspace_.getButtonCallback(this.callbackKey_)(this);
  }
};

/**
 * CSS for buttons and labels.  See css.js for use.
 */
Css.register([
  /* eslint-disable indent */
  '.blocklyFlyoutButton {',
    'fill: #888;',
    'cursor: default;',
  '}',

  '.blocklyFlyoutButtonShadow {',
    'fill: #666;',
  '}',

  '.blocklyFlyoutButton:hover {',
    'fill: #aaa;',
  '}',

  '.blocklyFlyoutLabel {',
    'cursor: default;',
  '}',

  '.blocklyFlyoutLabelBackground {',
    'opacity: 0;',
  '}',
  /* eslint-enable indent */
]);

exports = FlyoutButton;
<|endoftext|>


<commit_before>/**
 * Conversion.js
 * version: 0.0.1
 * authors: Sean Dokko
 * License: MIT
 * dokko1230.github.io/conversion.js
 */
!(function (undefined) {
  'use strict';

  var conversion,
      VERSION = '0.0.1',
      hasModule = (typeof module !== 'undefined' && module.exports),
      conversions = [],
      helpers = {};

      conversions.push({ // TEMPERATURE based in celsius
        'celsius': 1.0,
        'fahrenheit': -17.7778,
        'kelvin': -273.15
      });
      conversions.push({ // LENGTH based in meter
        'kilometer': 1000.0,
        'meter': 1.0,
        'centimeter': 0.01,
        'millimeter': 0.001,
        'mile': 1609.34,
        'yard': 0.9144,
        'inch': 0.0254,
        'foot': 0.3048,
        'nautical-mile': 1852
      });
      conversions.push({  // MASS based in kilogram
        'metric-ton': 1000,
        'kilogram': 1,
        'gram': 0.001,
        'milligram': 0.000001,
        'mcg': 0.000000001,
        'long-ton': 1016.05,
        'short-ton': 907.185,
        'stone': 6.35029,
        'pound': 0.453592,
        'ounce': 0.0283495
      });
      conversions.push({ // SPEED based in meters/sec
        'mph': 0.44704,
        'fps': 0.3048,
        'mps': 1,
        'kph': 0.277778,
        'knot': 0.514444
      });

  var initialize = function() {
    buildLengthFunctions();
  };

  /**
   * Non-pseudoclassical instantiation of conversion
   * @param {[integer]} value  [the value that is being converted]
   * @param {[string]} suffix [the suffix that is attached to the value. eg. 'km']
   */
  conversion = function (value, suffix) {
    var config = {};
    config.value = value;
    config.suffix = helpers.normalize(suffix);

    return new Conversion(config);
  };

  function Conversion(configs) {
    for (var key in configs) {
      this[key] = configs[key];
    }
  }

  /**
   * Holy mother of function builders
   * @return {undefined}
   */
  var buildLengthFunctions = function() {
    var obj = {};
    var isSpeed;
    for(var i = 0; i < conversions.length; i++) {
      for(var item in conversions[i]) {
        if(i === 3) {
          isSpeed = true;
        } else {
          isSpeed = false;
        }
        var methodName = helpers.makeMethodName(item, isSpeed);
        Conversion.prototype[methodName] = function() {
          var name = item;
          var topicIndex = i;
          return function() {
            return this.value * conversions[topicIndex][this.suffix] / conversions[topicIndex][name];
          }
        }();
      }
    }
  };

  /**
   * Helpers
   */

   /**
    * Normalize the suffix
    * @param  {[string]} suffix [the suffix to be normalized]
    * @return {[string]}        [returns the LENGTH table compatible string]
    */
  helpers.normalize = function (suffix) {
    if(suffix.length < 4) {
      return suffix.toLowerCase();
    }
    return suffix.toLowerCase().replace(/s$/i, '');
  };

  /**
   * Most nouns can be made plural by adding an -s to the end of the word. However, there are times when you need to add -es instead. If the word ends in "s", "x", "ch", or "sh", then you must use -es in order to spell the word correctly.
   */
  helpers.makeMethodName = function (original, isSpeed) {
    var items = original.split('-');
    var name = 'to';
    var edgeCases = [['s', 'x'],['ch', 'sh']];
    items.forEach(function(value) {
      name += value[0].toUpperCase() + value.substring(1);
    });
    if (isSpeed) {
      return name;
    } else {
      if(~edgeCases[0].indexOf(name.slice(-1)) || ~edgeCases[1].indexOf(name.slice(-2))) {
        return name += 'es';
      } else {
        return name += 's';
      }
    }
  };

  initialize();

  // CommonJS module is defined
  if (hasModule) {
    module.exports = conversion;
  }
})();<commit_msg>handle unique cases<commit_after>/**
 * Conversion.js
 * version: 0.0.1
 * authors: Sean Dokko
 * License: MIT
 * dokko1230.github.io/conversion.js
 */
!(function (undefined) {
  'use strict';

  var conversion,
      VERSION = '0.0.1',
      hasModule = (typeof module !== 'undefined' && module.exports),
      conversions = [],
      helpers = {};

      conversions.push({ // TEMPERATURE based in celsius
        'celsius': 1.0,
        'fahrenheit': -17.7778,
        'kelvin': -273.15
      });
      conversions.push({ // LENGTH based in meter
        'kilometer': 1000.0,
        'meter': 1.0,
        'centimeter': 0.01,
        'millimeter': 0.001,
        'mile': 1609.34,
        'yard': 0.9144,
        'inch': 0.0254,
        'foot': 0.3048,
        'feet': 0.3048,
        'nautical-mile': 1852
      });
      conversions.push({  // MASS based in kilogram
        'metric-ton': 1000,
        'kilogram': 1,
        'gram': 0.001,
        'milligram': 0.000001,
        'mcg': 0.000000001,
        'long-ton': 1016.05,
        'short-ton': 907.185,
        'stone': 6.35029,
        'pound': 0.453592,
        'ounce': 0.0283495
      });
      conversions.push({ // SPEED based in meters/sec
        'mph': 0.44704,
        'fps': 0.3048,
        'mps': 1,
        'kph': 0.277778,
        'knot': 0.514444
      });

  var initialize = function() {
    buildLengthFunctions();
  };

  /**
   * Non-pseudoclassical instantiation of conversion
   * @param {[integer]} value  [the value that is being converted]
   * @param {[string]} suffix [the suffix that is attached to the value. eg. 'km']
   */
  conversion = function (value, suffix) {
    var config = {};
    config.value = value;
    config.suffix = helpers.normalize(suffix);

    return new Conversion(config);
  };

  function Conversion(configs) {
    for (var key in configs) {
      this[key] = configs[key];
    }
  }

  /**
   * Holy mother of function builders
   * @return {undefined}
   */
  var buildLengthFunctions = function() {
    var obj = {};
    var isSpeed;
    for(var i = 0; i < conversions.length; i++) {
      for(var item in conversions[i]) {
        if(i === 3) {
          isSpeed = true;
        } else {
          isSpeed = false;
        }
        var methodName = helpers.makeMethodName(item, isSpeed);
        Conversion.prototype[methodName] = function() {
          var name = item;
          var topicIndex = i;
          return function() {
            return Number((this.value * conversions[topicIndex][this.suffix] / conversions[topicIndex][name]).toFixed(4));
          }
        }();
      }
    }
  };

  /**
   * Helpers
   */

   /**
    * Normalize the suffix
    * @param  {[string]} suffix [the suffix to be normalized]
    * @return {[string]}        [returns the LENGTH table compatible string]
    */
  helpers.normalize = function (suffix) {
    if(suffix.length < 4) {
      return suffix.toLowerCase();
    }
    return suffix.toLowerCase().replace(/s$/i, '');
  };

  helpers.handleUnique = function(original) {
    if(original === 'foot') {
      return 'toFeet';
    } else {
      return false;
    }
  }

  /**
   * Most nouns can be made plural by adding an -s to the end of the word. However, there are times when you need to add -es instead. If the word ends in "s", "x", "ch", or "sh", then you must use -es in order to spell the word correctly.
   */
  helpers.makeMethodName = function (original, isSpeed) {
    var items = original.split('-');
    var name = 'to';
    var edgeCases = [['s', 'x'],['ch', 'sh']];

    var isUnique = helpers.handleUnique(original);
    if(isUnique) {
      return isUnique;
    }

    items.forEach(function(value) {
      name += value[0].toUpperCase() + value.substring(1);
    });

    //TODO: Foot to Feet
    if (isSpeed) {
      return name;
    } else {
      if(~edgeCases[0].indexOf(name.slice(-1)) || ~edgeCases[1].indexOf(name.slice(-2))) {
        return name += 'es';
      } else {
        return name += 's';
      }
    }
  };

  initialize();

  // CommonJS module is defined
  if (hasModule) {
    module.exports = conversion;
  } else {
    this.convert = convert;
  }
})();<|endoftext|>


<commit_before>import React from 'react';
import styled from 'styled-components';
import {Link} from 'react-router';
import ContentBlock from 'components/ContentBlock';
import { FormattedMessage, injectIntl } from 'react-intl';
import LanguageThemeProvider from 'components/LanguageThemeProvider';
import Timestamp from 'react-timestamp';
import messages from './messages';
import { twitterFollow } from 'utils/social';

const ItemContainer = styled.li`
  list-style: none;
  border-top: 2px solid;
  padding: 15px 0;
`;
const Viewport = styled.div`
position: relative`;

const Source = styled(Link)`
  font-weight: 800;
  text-transform: uppercase;
  display: block;
  color: black;
  text-decoration: none;
`;
const Handle = styled(Link)`
  text-decoration: none;
  display: block;
  color: gray;
  &::before { content: '@'; }
`;

const Image = styled.img`
  float: ${props=>props.lang === 'ar' ? 'right' : 'left' };
  ${props=>props.lang === 'ar' ? 'margin-left' : 'margin-right' }: 5px;
  width: 40px;
`;
const Content = styled.span`
margin-top: 15px;
display: inline-block;
`;
const CallToAction = styled.div`
color: gray;
display: block;
margin: 5px 0;
text-align: right !important;

  button {
    color: gray;
    text-transform: uppercase;
    font-weight: bold;
    text-decoration: underline;
    cursor: pointer;
  }
`;

const TweetTimestamp = styled(Timestamp)`
  display: block;
  font-size: 12px;
  margin: 2px 0;
  color: gray;
`;

function NewsFeedItem(props) {

  return (
    <LanguageThemeProvider>
      <ItemContainer>
        <Viewport>
          <ContentBlock>
            <Image src={props.image_http} lang={props.intl.locale}/>
            <Source to={props.user_link} target='_blank'>{props.user_name}</Source>
            <Handle to={props.user_link} target='_blank'>{props.user_handle}</Handle>
            <Content dangerouslySetInnerHTML={{__html: props.content_html}}></Content>
          </ContentBlock>
          <TweetTimestamp time={props.timestamp / 1000} format='full' />
          <CallToAction>
            <ContentBlock>
              <button onClick={()=>twitterFollow(props.user_handle)}><FormattedMessage {...messages.follow} /></button>
            </ContentBlock>
          </CallToAction>
        </Viewport>
      </ItemContainer>
    </LanguageThemeProvider>
  )
}

export default injectIntl(NewsFeedItem);
<commit_msg>Newsfeed fix<commit_after>import React from 'react';
import styled from 'styled-components';
import {Link} from 'react-router';
import ContentBlock from 'components/ContentBlock';
import { FormattedMessage, injectIntl } from 'react-intl';
import LanguageThemeProvider from 'components/LanguageThemeProvider';
import Timestamp from 'react-timestamp';
import messages from './messages';
import { twitterFollow } from 'utils/social';

const ItemContainer = styled.li`
  list-style: none;
  border-top: 2px solid;
  padding: 15px 0;
`;
const Viewport = styled.div`
position: relative`;

const Source = styled(Link)`
  font-weight: 800;
  text-transform: uppercase;
  display: block;
  color: black;
  text-decoration: none;
`;
const Handle = styled(Link)`
  text-decoration: none;
  display: block;
  color: gray;
  &::before { content: '@'; }
`;

const Image = styled.img`
  float: ${props=>props.lang === 'ar' ? 'right' : 'left' };
  ${props=>props.lang === 'ar' ? 'margin-left' : 'margin-right' }: 5px;
  width: 40px;
`;
const Content = styled.span`
margin-top: 15px;
display: inline-block;
`;
const CallToAction = styled.div`
color: gray;
display: block;
margin: 5px 0;
text-align: ${p=>p.theme.isArabic ? 'left': 'right'} !important;

  button {
    color: gray;
    text-transform: uppercase;
    font-weight: bold;
    text-decoration: underline;
    cursor: pointer;
  }
`;

const TweetTimestamp = styled(Timestamp)`
  display: block;
  font-size: 12px;
  margin: 2px 0;
  color: gray;
`;

function NewsFeedItem(props) {

  return (
    <LanguageThemeProvider>
      <ItemContainer>
        <Viewport>
          <ContentBlock>
            <Image src={props.image_http} lang={props.intl.locale}/>
            <Source to={props.user_link} target='_blank'>{props.user_name}</Source>
            <Handle to={props.user_link} target='_blank'>{props.user_handle}</Handle>
            <Content dangerouslySetInnerHTML={{__html: props.content_html}}></Content>
          </ContentBlock>
          <TweetTimestamp time={props.timestamp / 1000} format='full' />
          <CallToAction>
            <button onClick={()=>twitterFollow(props.user_handle)}><FormattedMessage {...messages.follow} /></button>
          </CallToAction>
        </Viewport>
      </ItemContainer>
    </LanguageThemeProvider>
  )
}

export default injectIntl(NewsFeedItem);
<|endoftext|>


<commit_before>import estraverse from 'estraverse';
import ImportDefaultSpecifier from './../syntax/import-default-specifier.js';
import ImportDeclaration from './../syntax/import-declaration.js';
import _ from 'lodash';

export default
  function (ast, callback) {

    unidentifiedIdentifier = [];

    estraverse.traverse(ast, {
      enter: importDetector
    });

    estraverse.traverse(ast, {
      enter: identifierDetector
    });

    importGenerator(ast);

    if(callback){
      callback();
    }
  }

var unidentifiedIdentifier = [],
  identifiedIdentifier = ['Object', 'console'],
  defaultImportSource = {
    '$' : 'jQuery'
  };

function importDetector(node) {

  if(node.type ==='ImportDeclaration') {

    let specifiers = node.specifiers;

    for(let i=0; i<specifiers.length; i++) {
      let specifier = specifiers[i];
      if(specifier.id.type === 'Identifier') {
        identifiedIdentifier.push(specifier.id.name);
      }
    }

  }

}

function identifierDetector(node) {

  if(node.type === 'CallExpression' && node.callee.type === 'MemberExpression' && !calledByThis(node.callee)) {

    let calleeObjectName = getCalleeObject(node.callee.object);
    if(calleeObjectName && _.indexOf(identifiedIdentifier, calleeObjectName) === -1 && _.indexOf(unidentifiedIdentifier, calleeObjectName) === -1) {
      unidentifiedIdentifier.push(calleeObjectName);
    }

  }

}

function importGenerator(ast) {

  for(let i=0; i<unidentifiedIdentifier.length; i++) {

    let name = unidentifiedIdentifier[i];
    let source = defaultImportSource[name] || name;

    let specifier = new ImportDefaultSpecifier();
    specifier.setIdentifierName(name);

    let importDeclaration = new ImportDeclaration();
    importDeclaration.addSpecifier(specifier);
    importDeclaration.setLiteral(source);

    ast.body.unshift(importDeclaration);
  }

}

function getCalleeObject(callee) {

  if(callee.type === 'MemberExpression') {
    return getCalleeObject(callee.object);
  }else if(callee.type === 'Identifier'){
    return callee.name;
  }

  return false;

}

function calledByThis(callee) {

  let _calledByThis = false;

  estraverse.traverse(callee, {
    enter: function (node) {
      if(node.type === 'ThisExpression') {
        _calledByThis = true;
        this.break();
      }
    }
  });

  return _calledByThis;
}<commit_msg>add JSON and console as identified Object<commit_after>import estraverse from 'estraverse';
import ImportDefaultSpecifier from './../syntax/import-default-specifier.js';
import ImportDeclaration from './../syntax/import-declaration.js';
import _ from 'lodash';

export default
  function (ast, callback) {

    unidentifiedIdentifier = [];

    estraverse.traverse(ast, {
      enter: importDetector
    });

    estraverse.traverse(ast, {
      enter: identifierDetector
    });

    importGenerator(ast);

    if(callback){
      callback();
    }
  }

var unidentifiedIdentifier = [],
  identifiedIdentifier = ['Object', 'console', 'JSON'],
  defaultImportSource = {
    '$' : 'jQuery'
  };

function importDetector(node) {

  if(node.type ==='ImportDeclaration') {

    let specifiers = node.specifiers;

    for(let i=0; i<specifiers.length; i++) {
      let specifier = specifiers[i];
      if(specifier.id.type === 'Identifier') {
        identifiedIdentifier.push(specifier.id.name);
      }
    }

  }

}

function identifierDetector(node) {

  if(node.type === 'CallExpression' && node.callee.type === 'MemberExpression' && !calledByThis(node.callee)) {

    let calleeObjectName = getCalleeObject(node.callee.object);
    if(calleeObjectName && _.indexOf(identifiedIdentifier, calleeObjectName) === -1 && _.indexOf(unidentifiedIdentifier, calleeObjectName) === -1) {
      unidentifiedIdentifier.push(calleeObjectName);
    }

  }

}

function importGenerator(ast) {

  for(let i=0; i<unidentifiedIdentifier.length; i++) {

    let name = unidentifiedIdentifier[i];
    let source = defaultImportSource[name] || name;

    let specifier = new ImportDefaultSpecifier();
    specifier.setIdentifierName(name);

    let importDeclaration = new ImportDeclaration();
    importDeclaration.addSpecifier(specifier);
    importDeclaration.setLiteral(source);

    ast.body.unshift(importDeclaration);
  }

}

function getCalleeObject(callee) {

  if(callee.type === 'MemberExpression') {
    return getCalleeObject(callee.object);
  }else if(callee.type === 'Identifier'){
    return callee.name;
  }

  return false;

}

function calledByThis(callee) {

  let _calledByThis = false;

  estraverse.traverse(callee, {
    enter: function (node) {
      if(node.type === 'ThisExpression') {
        _calledByThis = true;
        this.break();
      }
    }
  });

  return _calledByThis;
}<|endoftext|>


<commit_before>'use strict';

const escape = require('js-string-escape');

function render(errors) {
  return errors.map(error => `${error.line}:${error.column} - ${error.message} (${error.ruleId})`).join('\n');
}

function qunit(relativePath, errors, results) {
  const passed = !results.errorCount || results.errorCount.length === 0;

  let messages = relativePath + ' should pass ESLint';

  if (results.messages) {
    messages += '\n\n' + render(results.messages);
  }

  return `QUnit.module('ESLint | ${escape(relativePath)}');\n` +
    `QUnit.test('should pass ESLint', function(assert) {\n` +
    `  assert.expect(1);\n` +
    `  assert.ok(${passed}, '${escape(messages)}');\n` +
    `});\n`;
}

function mocha(relativePath, errors, results) {
  const passed = !results.errorCount || results.errorCount.length === 0;

  let messages = `${relativePath} should pass ESLint`;

  if (results.messages) {
    messages += `\n\n${render(results.messages)}`;
  }

  let output =
    `describe('ESLint | ${escape(relativePath)}', function() {\n` +
    `  it('should pass ESLint', function() {\n`;

  if (passed) {
    output +=
      `    // ESLint passed\n`;
  } else {
    output +=
      `    // ESLint failed\n` +
      `    var error = new chai.AssertionError('${escape(messages)}');\n` +
      `    error.stack = undefined;\n` +
      `    throw error;\n`;
  }

  output +=
    `  });\n` +
    `});\n`;

  return output;
}

module.exports = { qunit, mocha };
<commit_msg>test-generators: Extract helper functions<commit_after>'use strict';

const escape = require('js-string-escape');

function render(errors) {
  return errors.map(error => `${error.line}:${error.column} - ${error.message} (${error.ruleId})`).join('\n');
}

function qunit(relativePath, errors, results) {
  let passed = hasPassed(results);
  let message = createAssertionMessage(relativePath, results);

  return `QUnit.module('ESLint | ${escape(relativePath)}');\n` +
    `QUnit.test('should pass ESLint', function(assert) {\n` +
    `  assert.expect(1);\n` +
    `  assert.ok(${passed}, '${escape(message)}');\n` +
    `});\n`;
}

function mocha(relativePath, errors, results) {
  let passed = hasPassed(results);
  let message = createAssertionMessage(relativePath, results);

  let output =
    `describe('ESLint | ${escape(relativePath)}', function() {\n` +
    `  it('should pass ESLint', function() {\n`;

  if (passed) {
    output +=
      `    // ESLint passed\n`;
  } else {
    output +=
      `    // ESLint failed\n` +
      `    var error = new chai.AssertionError('${escape(message)}');\n` +
      `    error.stack = undefined;\n` +
      `    throw error;\n`;
  }

  output +=
    `  });\n` +
    `});\n`;

  return output;
}

function hasPassed(results) {
  return !results.errorCount || results.errorCount.length === 0;
}

function createAssertionMessage(relativePath, results) {
  let message = `${relativePath} should pass ESLint`;

  if (results.messages) {
    message += `\n\n${render(results.messages)}`;
  }

  return message;
}

module.exports = { qunit, mocha };
<|endoftext|>


<commit_before>/**
*
* ToolTypeAllFull
*
*/

import React from 'react';
import styled from 'styled-components';
import Isvg from 'react-inlinesvg';

import {Link} from 'react-router';
import { injectIntl } from 'react-intl';

import TranslatableStaticText from 'containers/TranslatableStaticText';

import Container from 'components/ToolTypeAllFull/Container';
import Desc from 'components/ToolTypeAllFull/Desc';
import Head from 'components/ToolTypeAllFull/Head';
import Row from 'components/ToolTypeAllFull/Row';
import ToolType from 'components/ToolTypeAllFull/ToolType';

import MethodologyIcon from 'assets/images/type/methodologies-option.svg';
import PrincipleIcon from 'assets/images/type/principles-option.svg';
import StoryIcon from 'assets/images/type/stories-option.svg';
import TacticIcon from 'assets/images/type/tactics-option.svg';
import TheoryIcon from 'assets/images/type/theories-option.svg';

import messages from '../ToolTypeArea/messages';
import staticText from './staticText';

function ToolTypeAllFull(props) {
  const lang = props.intl.locale;
  return (
    <Container {...props} lang={lang} showLine={props.showLine}>

        <Row>
            <ToolType to={'/type/story'} lang={lang}>

                <TranslatableStaticText {...staticText.stories} />

              <Isvg src={StoryIcon} />
            </ToolType>

            <ToolType to={'/type/story'} style={{paddingTop: 35}} lang={lang}>
              <Desc ar={lang==='ar'}>
                <TranslatableStaticText {...staticText.shortDefinitionStory} />
              </Desc>
            </ToolType>
        </Row>

        <Row>
            <ToolType to={'/type/tactic'} lang={lang}>

                <TranslatableStaticText {...staticText.tactics} />

              <Isvg src={TacticIcon} />
            </ToolType>

            <ToolType to={'/type/tactic'} style={{paddingTop: 35}} lang={lang}>
              <Desc ar={lang==='ar'}>
                <TranslatableStaticText {...staticText.shortDefinitionTactic} />
              </Desc>
            </ToolType>
        </Row>

        <Row>
            <ToolType to={'/type/principle'} lang={lang}>

                <TranslatableStaticText {...staticText.principles} />

              <Isvg src={PrincipleIcon} />
            </ToolType>

            <ToolType to={'/type/principle'} style={{paddingTop: 35}} lang={lang}>
              <Desc ar={lang==='ar'}>
                <TranslatableStaticText {...staticText.shortDefinitionPrinciple} />
              </Desc>
            </ToolType>
        </Row>

        <Row>
            <ToolType to={'/type/theory'} lang={lang}>

                <TranslatableStaticText {...staticText.theories} />

              <Isvg src={TheoryIcon} />
            </ToolType>

            <ToolType to={'/type/theory'} style={{paddingTop: 35}} lang={lang}>
              <Desc ar={lang==='ar'}>
                <TranslatableStaticText {...staticText.shortDefinitionTheory} />
              </Desc>
            </ToolType>
        </Row>
        <Row>
            <ToolType to={'/type/methodology'} lang={lang}>

                <TranslatableStaticText {...staticText.methodologies} />

              <Isvg src={MethodologyIcon} />
            </ToolType>

            <ToolType to={'/type/methodology'} style={{paddingTop: 35}} lang={lang}>
              <Desc ar={lang==='ar'}>
                <TranslatableStaticText {...staticText.shortDefinitionMethodology} />
              </Desc>
            </ToolType>
        </Row>
        <Row>
            <ToolType to={'/type/story'} lang={lang}>

                <TranslatableStaticText {...staticText.stories} />

              <Isvg src={StoryIcon} />
            </ToolType>

            <ToolType to={'/type/story'} style={{paddingTop: 35}} lang={lang}>
              <Desc ar={lang==='ar'}>
                <TranslatableStaticText {...staticText.shortDefinitionStory} />
              </Desc>
            </ToolType>
        </Row>

    </Container>
  );
}

/**
<Row>
  <ToolType to={'/type/tactic'} lang={lang}>

      <TranslatableStaticText {...staticText.tactics} />

    <Isvg src={TacticIcon} />
    <Desc ar={lang==='ar'}>
      <TranslatableStaticText {...staticText.shortDefinitionTactic} />
    </Desc>
  </ToolType>

  <ToolType to={'/type/principle'} lang={lang}>

      <TranslatableStaticText {...staticText.principles} />

    <Isvg src={PrincipleIcon} />
    <Desc ar={lang==='ar'}>
      <TranslatableStaticText {...staticText.shortDefinitionPrinciple} />
    </Desc>
  </ToolType>

  <ToolType to={'/type/theory'} lang={lang}>

      <TranslatableStaticText {...staticText.theories} />

    <Isvg src={TheoryIcon} />
    <Desc ar={lang==='ar'}>
      <TranslatableStaticText {...staticText.shortDefinitionTheory} />
    </Desc>
  </ToolType>

  <ToolType to={'/type/methodology'} lang={lang}>

      <TranslatableStaticText {...staticText.methodologies} />

    <Isvg src={MethodologyIcon} />
    <Desc ar={lang==='ar'}>
      <TranslatableStaticText {...staticText.shortDefinitionMethodology} />
    </Desc>
  </ToolType>
</Row>*/

ToolTypeAllFull.propTypes = {

};

export default injectIntl(ToolTypeAllFull);
<commit_msg>Remove booboo<commit_after>/**
*
* ToolTypeAllFull
*
*/

import React from 'react';
import styled from 'styled-components';
import Isvg from 'react-inlinesvg';

import {Link} from 'react-router';
import { injectIntl } from 'react-intl';

import TranslatableStaticText from 'containers/TranslatableStaticText';

import Container from 'components/ToolTypeAllFull/Container';
import Desc from 'components/ToolTypeAllFull/Desc';
import Head from 'components/ToolTypeAllFull/Head';
import Row from 'components/ToolTypeAllFull/Row';
import ToolType from 'components/ToolTypeAllFull/ToolType';

import MethodologyIcon from 'assets/images/type/methodologies-option.svg';
import PrincipleIcon from 'assets/images/type/principles-option.svg';
import StoryIcon from 'assets/images/type/stories-option.svg';
import TacticIcon from 'assets/images/type/tactics-option.svg';
import TheoryIcon from 'assets/images/type/theories-option.svg';

import messages from '../ToolTypeArea/messages';
import staticText from './staticText';

function ToolTypeAllFull(props) {
  const lang = props.intl.locale;
  return (
    <Container {...props} lang={lang} showLine={props.showLine}>

        <Row>
            <ToolType to={'/type/story'} lang={lang}>

                <TranslatableStaticText {...staticText.stories} />

              <Isvg src={StoryIcon} />
            </ToolType>

            <ToolType to={'/type/story'} style={{paddingTop: 35}} lang={lang}>
              <Desc ar={lang==='ar'}>
                <TranslatableStaticText {...staticText.shortDefinitionStory} />
              </Desc>
            </ToolType>
        </Row>

        <Row>
            <ToolType to={'/type/tactic'} lang={lang}>

                <TranslatableStaticText {...staticText.tactics} />

              <Isvg src={TacticIcon} />
            </ToolType>

            <ToolType to={'/type/tactic'} style={{paddingTop: 35}} lang={lang}>
              <Desc ar={lang==='ar'}>
                <TranslatableStaticText {...staticText.shortDefinitionTactic} />
              </Desc>
            </ToolType>
        </Row>

        <Row>
            <ToolType to={'/type/principle'} lang={lang}>

                <TranslatableStaticText {...staticText.principles} />

              <Isvg src={PrincipleIcon} />
            </ToolType>

            <ToolType to={'/type/principle'} style={{paddingTop: 35}} lang={lang}>
              <Desc ar={lang==='ar'}>
                <TranslatableStaticText {...staticText.shortDefinitionPrinciple} />
              </Desc>
            </ToolType>
        </Row>

        <Row>
            <ToolType to={'/type/theory'} lang={lang}>

                <TranslatableStaticText {...staticText.theories} />

              <Isvg src={TheoryIcon} />
            </ToolType>

            <ToolType to={'/type/theory'} style={{paddingTop: 35}} lang={lang}>
              <Desc ar={lang==='ar'}>
                <TranslatableStaticText {...staticText.shortDefinitionTheory} />
              </Desc>
            </ToolType>
        </Row>
        <Row>
            <ToolType to={'/type/methodology'} lang={lang}>

                <TranslatableStaticText {...staticText.methodologies} />

              <Isvg src={MethodologyIcon} />
            </ToolType>

            <ToolType to={'/type/methodology'} style={{paddingTop: 35}} lang={lang}>
              <Desc ar={lang==='ar'}>
                <TranslatableStaticText {...staticText.shortDefinitionMethodology} />
              </Desc>
            </ToolType>
        </Row>

    </Container>
  );
}

/**
<Row>
  <ToolType to={'/type/tactic'} lang={lang}>

      <TranslatableStaticText {...staticText.tactics} />

    <Isvg src={TacticIcon} />
    <Desc ar={lang==='ar'}>
      <TranslatableStaticText {...staticText.shortDefinitionTactic} />
    </Desc>
  </ToolType>

  <ToolType to={'/type/principle'} lang={lang}>

      <TranslatableStaticText {...staticText.principles} />

    <Isvg src={PrincipleIcon} />
    <Desc ar={lang==='ar'}>
      <TranslatableStaticText {...staticText.shortDefinitionPrinciple} />
    </Desc>
  </ToolType>

  <ToolType to={'/type/theory'} lang={lang}>

      <TranslatableStaticText {...staticText.theories} />

    <Isvg src={TheoryIcon} />
    <Desc ar={lang==='ar'}>
      <TranslatableStaticText {...staticText.shortDefinitionTheory} />
    </Desc>
  </ToolType>

  <ToolType to={'/type/methodology'} lang={lang}>

      <TranslatableStaticText {...staticText.methodologies} />

    <Isvg src={MethodologyIcon} />
    <Desc ar={lang==='ar'}>
      <TranslatableStaticText {...staticText.shortDefinitionMethodology} />
    </Desc>
  </ToolType>
</Row>*/

ToolTypeAllFull.propTypes = {

};

export default injectIntl(ToolTypeAllFull);
<|endoftext|>


<commit_before>const fs = require("fs");

const ohm = require("ohm-js");

const parserContents = fs.readFileSync("JCaml.ohm");

const JCamlGrammar = ohm.grammar(parserContents);
const Type = require("./ast/type");

const Program = require("./ast/program");
const Block = require("./ast/block");
const StatementIfElse = require("./ast/statementIfElse");
const Decl = require("./ast/decl");
const Print = require("./ast/print");
const Return = require("./ast/return");
const Addop = require("./ast/addop");
const Relop = require("./ast/relop");
const Mullop = require("./ast/mullop");
const Expop = require("./ast/expop");
const Binop = require("./ast/binop");
const FuncDec = require("./ast/FuncDec");
const FuncCall = require("./ast/funcCall");
const Args = require("./ast/args");
const Arg = require("./ast/arg");
const Params = require("./ast/params");
const Param = require("./ast/param");
const Body = require("./ast/body");
const ExpBinary = require("./ast/exp_binary");
const ExpTernary = require("./ast/exp_ternary");
const BinExp = require("./ast/binExp");
const MatchExp = require("./ast/matchExp");
const AddExp = require("./ast/addExp");
const MullExp = require("./ast/mullExp");
const ParenExp = require("./ast/parenExp");
const Matches = require("./ast/matches");
const Tuplit = require("./ast/tuplit");
const Numlit = require("./ast/numLit");
const Charlit = require("./ast/charLit");
const Stringlit = require("./ast/stringLit");
const ExpoExp = require("./ast/expoExp");
const PrefixExp = require("./ast/prefix_Exp");
const List = require("./ast/list");
const Stmt = require("./ast/stmt");

/* eslint-disable no-unused-vars */
const semantics = JCamlGrammar.createSemantics().addOperation("tree", {
    Program(block) { return new Program(block.tree()); },
    Block(stmt) { return new Block(stmt.tree()); },
    Stmt_if(_1, exp, block, _2, elseIfExprs, elseIfBlocks, _3, finalBlock) {
        return new StatementIfElse(exp.tree(), block.tree(), elseIfExprs.tree(), finalBlock.tree());
    },
    Decl_decl(_1, type, id, _2, exp) { return new Decl(type.tree(), id.sourceString, exp.tree()); },
    Print_print(_1, _2, binexp, _3) { return new Print(binexp.tree()); },
    Return(_1, arg) { return new Return(arg.tree()); },
    addop(op) { return new Addop(this.sourceString); },
    relop(op) { return new Relop(this.sourceString); },
    mullop(op) { return new Mullop(this.sourceString); },
    expop(op) { return new Expop(this.sourceString); },
    binop(op) { return new Binop(this.sourceString); },
    FuncDec(_1, id, _2, params, _3, type, body) {
      return new FuncDec(id.sourceString, params.tree(), type.tree(), body.tree());
    },
    FuncCall(id, _1, args, _2) { return new FuncCall(id.sourceString, args.tree()); },
    Args(arg) { return new Args(arg.tree()); },
    Arg(id) { return new Arg(id.sourceString); },
    Params(_1, params, _2) {
      return new Params(params.sourceString);
    },
    Param(id) { return new Param(id.sourceString); },
    Type(type) { return new Type(type.sourceString); },
    Body(_1, block, _2) { return new Body(block.tree()); },
    Exp_binary(exp, op, matchexp) { return new ExpBinary(op.tree(), exp.tree(), matchexp.tree()); },
    Exp_ternary(matchexp, _1, matchexp2, _2, matchexp3) {
      return new ExpTernary(matchexp.tree(), matchexp2.tree(), matchexp3.tree());
    },
    BinExp_binary(binexp, op, addexp) {
        return new BinExp(op.tree(), binexp.tree(), addexp.tree());
    },
    MatchExp_matchexp(_1, id, _2, matches) {
        return new MatchExp(id.sourceString, matches.tree());
    },
    AddExp_binary(addexp, op, mullexp) {
      return new AddExp(op.tree(), addexp.tree(), mullexp.tree());
    },
    MullExp_binary(mullexp, op, prefixexp) {
      return new MullExp(op.tree(), mullexp.tree(), prefixexp.tree());
    },
    PrefixExp_binary(op, expoexp) { return new PrefixExp(op.tree(), expoexp.tree()); },
    ExpoExp_binary(parenexp, op, expoexp) {
      return new ExpoExp(op.tree(), parenexp.tree(), expoexp.tree());
    },
    ParenExp_parens(_1, addexp, _2) { return new ParenExp(addexp.tree()); },
    Matches(_1, exp1, _2, exp2) { return new Matches(exp1.tree(), exp2.tree()); },
    Tuplit(_1, exp1, _2, exp2, _3) { return new Tuplit(exp1.tree(), exp2.tree()); },
    List_list(_1, _2, _3, _4, args) { return new List(this.sourceString); },
    List(_1) { return new List(this.sourceString); },
    numlit(value) { return new Numlit(this.sourceString); },
    charlit(_1, value, _2) { return new Charlit(this.sourceString); },
    stringlit(_1, value, _2) { return new Stringlit(this.sourceString); },
});
/* eslint-enable no-unused-vars */

function parse(text) {
    const match = JCamlGrammar.match(text);
    if (match.succeeded()) {
        return semantics(match).tree();
    }
    throw new Error(match.message);
}

module.exports = { parse, Program, Block, Stmt, Return, Arg, Param, Stringlit, FuncCall, FuncDec };
<commit_msg>Fixed arity problem.<commit_after>const fs = require("fs");

const ohm = require("ohm-js");

const parserContents = fs.readFileSync("JCaml.ohm");

const JCamlGrammar = ohm.grammar(parserContents);
const Type = require("./ast/type");

const Program = require("./ast/program");
const Block = require("./ast/block");
const StatementIfElse = require("./ast/statementIfElse");
const Decl = require("./ast/decl");
const Print = require("./ast/print");
const Return = require("./ast/return");
const Addop = require("./ast/addop");
const Relop = require("./ast/relop");
const Mullop = require("./ast/mullop");
const Expop = require("./ast/expop");
const Binop = require("./ast/binop");
const FuncDec = require("./ast/FuncDec");
const FuncCall = require("./ast/funcCall");
const Args = require("./ast/args");
const Arg = require("./ast/arg");
const Params = require("./ast/params");
const Param = require("./ast/param");
const Body = require("./ast/body");
const ExpBinary = require("./ast/exp_binary");
const ExpTernary = require("./ast/exp_ternary");
const BinExp = require("./ast/binExp");
const MatchExp = require("./ast/matchExp");
const AddExp = require("./ast/addExp");
const MullExp = require("./ast/mullExp");
const ParenExp = require("./ast/parenExp");
const Matches = require("./ast/matches");
const Tuplit = require("./ast/tuplit");
const Numlit = require("./ast/numLit");
const Charlit = require("./ast/charLit");
const Stringlit = require("./ast/stringLit");
const ExpoExp = require("./ast/expoExp");
const PrefixExp = require("./ast/prefix_Exp");
const List = require("./ast/list");
const Stmt = require("./ast/stmt");

/* eslint-disable no-unused-vars */
const semantics = JCamlGrammar.createSemantics().addOperation("tree", {
    Program(block) { return new Program(block.tree()); },
    Block(stmt) { return new Block(stmt.tree()); },
    Stmt_if(_1, exp, block, _2, elseIfExprs, elseIfBlocks, _3, finalBlock) {
        return new StatementIfElse(exp.tree(), block.tree(), elseIfExprs.tree(), finalBlock.tree());
    },
    Decl_decl(_1, type, id, _2, exp) { return new Decl(type.tree(), id.sourceString, exp.tree()); },
    Print_print(_1, _2, binexp, _3) { return new Print(binexp.tree()); },
    Return(_1, arg) { return new Return(arg.tree()); },
    addop(op) { return new Addop(this.sourceString); },
    relop(op) { return new Relop(this.sourceString); },
    mullop(op) { return new Mullop(this.sourceString); },
    expop(op) { return new Expop(this.sourceString); },
    binop(op) { return new Binop(this.sourceString); },
    FuncDec(_1, id, _2, params, _3, type, body) {
      return new FuncDec(id.sourceString, params.tree(), type.tree(), body.tree());
    },
    FuncCall(id, _1, args, _2) { return new FuncCall(id.sourceString, args.tree()); },
    Args(arg) { return new Args(arg.tree()); },
    Arg(id) { return new Arg(id.sourceString); },
    Params(params) {
      return new Params(params.sourceString);
    },
    Param(id) { return new Param(id.sourceString); },
    Type(type) { return new Type(type.sourceString); },
    Body(_1, block, _2) { return new Body(block.tree()); },
    Exp_binary(exp, op, matchexp) { return new ExpBinary(op.tree(), exp.tree(), matchexp.tree()); },
    Exp_ternary(matchexp, _1, matchexp2, _2, matchexp3) {
      return new ExpTernary(matchexp.tree(), matchexp2.tree(), matchexp3.tree());
    },
    BinExp_binary(binexp, op, addexp) {
        return new BinExp(op.tree(), binexp.tree(), addexp.tree());
    },
    MatchExp_matchexp(_1, id, _2, matches) {
        return new MatchExp(id.sourceString, matches.tree());
    },
    AddExp_binary(addexp, op, mullexp) {
      return new AddExp(op.tree(), addexp.tree(), mullexp.tree());
    },
    MullExp_binary(mullexp, op, prefixexp) {
      return new MullExp(op.tree(), mullexp.tree(), prefixexp.tree());
    },
    PrefixExp_binary(op, expoexp) { return new PrefixExp(op.tree(), expoexp.tree()); },
    ExpoExp_binary(parenexp, op, expoexp) {
      return new ExpoExp(op.tree(), parenexp.tree(), expoexp.tree());
    },
    ParenExp_parens(_1, addexp, _2) { return new ParenExp(addexp.tree()); },
    Matches(_1, exp1, _2, exp2) { return new Matches(exp1.tree(), exp2.tree()); },
    Tuplit(_1, exp1, _2, exp2, _3) { return new Tuplit(exp1.tree(), exp2.tree()); },
    List_list(_1, _2, _3, _4, args) { return new List(this.sourceString); },
    List(_1) { return new List(this.sourceString); },
    numlit(value) { return new Numlit(this.sourceString); },
    charlit(_1, value, _2) { return new Charlit(this.sourceString); },
    stringlit(_1, value, _2) { return new Stringlit(this.sourceString); },
});
/* eslint-enable no-unused-vars */

function parse(text) {
    const match = JCamlGrammar.match(text);
    if (match.succeeded()) {
        return semantics(match).tree();
    }
    throw new Error(match.message);
}

module.exports = { parse, Program, Block, Stmt, Return, Arg, Param, Stringlit, FuncCall, FuncDec };
<|endoftext|>


<commit_before>import test from 'tape';

test('patchSchema works correctly', assert => {

});
<commit_msg>skip patchSchema test<commit_after>import test from 'tape';

test('patchSchema works correctly', { skip: true }, assert => {

});
<|endoftext|>