<commit_before>import { assign, defaults, flatten, isFunction, partialRight, uniq, some } from "lodash";
import React from "react";
import Axis from "./axis";
import { Style, Transitions, Collection, Data, Domain, Events } from "victory-core";

export default {
  getData(props, childComponents) {
    if (props.data) {
      return Data.getData(props);
    }
    childComponents = childComponents || React.Children.toArray(props.children);
    return this.getDataFromChildren(childComponents);
  },

  getDefaultDomainPadding(props, axis, childComponents) {
    const horizontalChildren = childComponents.some((component) => {
      return component.props && component.props.horizontal;
    });
    const horizontal = props && props.horizontal || horizontalChildren;
    const groupComponent = childComponents.filter((child) => {
      return child.type && child.type.role && child.type.role === "group";
    });

    if (groupComponent.length < 1) {
      return undefined;
    }
    const { offset, children } = groupComponent[0].props;
    const defaultDomainPadding = horizontal ?
      { y: (offset * children.length) / 2 } :
      { x: (offset * children.length) / 2 };
    return defaultDomainPadding[axis];
  },

  getDomain(props, axis, childComponents) {
    childComponents = childComponents || React.Children.toArray(props.children);
    const propsDomain = Domain.getDomainFromProps(props, axis);
    if (propsDomain) {
      return propsDomain;
    }
    const dataset = (props.data || props.y) && Data.getData(props);
    const dataDomain = dataset ? Domain.getDomainFromData(props, axis, dataset) : [];
    const childDomain = this.getDomainFromChildren(props, axis, childComponents);
    const min = Collection.getMinValue([...dataDomain, ...childDomain]);
    const max = Collection.getMaxValue([...dataDomain, ...childDomain]);
    const domainPadding = props.polar ?
      0 : this.getDefaultDomainPadding(props, axis, childComponents);
    const paddedDomain = Domain.padDomain([min, max], assign({ domainPadding }, props), axis);
    return Domain.cleanDomain(paddedDomain, props, axis);
  },

  setAnimationState(props, nextProps) {
    if (!props.animate) {
      return;
    }
    if (props.animate.parentState) {
      const nodesWillExit = props.animate.parentState.nodesWillExit;
      const oldProps = nodesWillExit ? props : null;
      this.setState(defaults({ oldProps, nextProps }, props.animate.parentState));
    } else {
      const oldChildren = React.Children.toArray(props.children);
      const nextChildren = React.Children.toArray(nextProps.children);
      const isContinuous = (child) => {
        const check = (c) => c.type && c.type.continuous;
        return Array.isArray(child) ? some(child, check) : check(child);
      };

      const continuous = !props.polar && some(oldChildren, (child) => {
        return isContinuous(child) || child.props.children && isContinuous(child.props.children);
      });
      const {
        nodesWillExit,
        nodesWillEnter,
        childrenTransitions,
        nodesShouldEnter
      } = Transitions.getInitialTransitionState(oldChildren, nextChildren);

      this.setState({
        nodesWillExit,
        nodesWillEnter,
        nodesShouldEnter,
        childrenTransitions: Collection.isArrayOfArrays(childrenTransitions) ?
          childrenTransitions[0] : childrenTransitions,
        oldProps: nodesWillExit ? props : null,
        nextProps,
        continuous
      });
    }
  },

  getAllEvents(props) {
    const components = ["groupComponent", "containerComponent", "labelComponent"];
    this.componentEvents = Events.getComponentEvents(props, components);
    if (Array.isArray(this.componentEvents)) {
      return Array.isArray(props.events) ?
        this.componentEvents.concat(...props.events) : this.componentEvents;
    }
    return props.events;
  },

  getAnimationProps(props, child, index) {
    if (!props.animate) {
      return child.props.animate;
    }
    const getFilteredState = () => {
      let childrenTransitions = this.state && this.state.childrenTransitions;
      childrenTransitions = Collection.isArrayOfArrays(childrenTransitions) ?
        childrenTransitions[index] : childrenTransitions;
      return defaults({ childrenTransitions }, this.state);
    };

    let getTransitions = props.animate && props.animate.getTransitions;
    const state = getFilteredState();
    const parentState = props.animate && props.animate.parentState || state;
    if (!getTransitions) {
      const getTransitionProps = Transitions.getTransitionPropsFactory(
        props,
        state,
        (newState) => this.setState(newState)
      );
      getTransitions = partialRight(getTransitionProps, index);
    }
    return defaults({ getTransitions, parentState }, props.animate, child.props.animate);
  },

  getDomainFromChildren(props, axis, childComponents) { // eslint-disable-line max-statements, complexity, max-len
    const childDomains = [];
    let childDomainsLength = 0;

    const children = childComponents
      ? childComponents.slice(0)
      : React.Children.toArray(props.children);
    let childrenLength = children.length;

    const horizontalChildren = childComponents.some((component) => {
      return component.props && component.props.horizontal;
    });
    const horizontal = props && props.horizontal || horizontalChildren.length > 0;
    const currentAxis = Axis.getCurrentAxis(axis, horizontal);

    const parentData = props.data ? Data.getData(props, axis) : undefined;
    const { polar, startAngle, endAngle } = props;
    const parentProps = parentData ?
      { data: parentData, polar, startAngle, endAngle } : { polar, startAngle, endAngle };

    while (childrenLength > 0) {
      const child = children[--childrenLength];

      if (child.type && isFunction(child.type.getDomain)) {
        const sharedProps = assign({}, child.props, parentProps);
        const childDomain = child.props && child.type.getDomain(sharedProps, currentAxis);
        if (childDomain) {
          const childDomainLength = childDomain.length;
          for (let index = 0; index < childDomainLength; index++) {
            childDomains[childDomainsLength++] = childDomain[index];
          }
        }
      } else if (child.props && child.props.children) {
        const newChildren = React.Children.toArray(child.props.children);
        const newChildrenLength = newChildren.length;
        for (let index = 0; index < newChildrenLength; index++) {
          children[childrenLength++] = newChildren[index];
        }
      }
    }
    const min = Collection.getMinValue(childDomains);
    const max = Collection.getMaxValue(childDomains);
    return childDomains.length === 0 ?
      [0, 1] : [min, max];
  },

  getDataFromChildren(props, childComponents) { // eslint-disable-line max-statements
    const getData = (childProps) => {
      const data = Data.getData(childProps);
      return Array.isArray(data) && data.length > 0 ? data : undefined;
    };

    // Reverse the child array to maintain correct order when looping over
    // children starting from the end of the array.
    const children = childComponents
      ? childComponents.slice(0).reverse()
      : React.Children.toArray(props.children).reverse();

    let childrenLength = children.length;

    const dataArr = [];
    let dataArrLength = 0;
    while (childrenLength > 0) {
      const child = children[--childrenLength];
      if (child.type && child.type.role === "axis") {
        dataArrLength = dataArrLength;
      } else if (child.type && child.type.role !== "axis" && isFunction(child.type.getData)) {
        dataArr[dataArrLength++] = child.type.getData(child.props);
      } else if (child.props && child.props.children) {
        const newChildren = React.Children.toArray(child.props.children);
        const newChildrenLength = newChildren.length;
        for (let index = 0; index < newChildrenLength; index++) {
          children[childrenLength++] = newChildren[index];
        }
      } else {
        dataArr[dataArrLength++] = getData(child.props);
      }
    }

    return dataArr;
  },

  getStackedDomain(props, axis) {
    const propsDomain = Domain.getDomainFromProps(props, axis);
    if (propsDomain) {
      return propsDomain;
    }
    const { horizontal } = props;
    const ensureZero = (domain) => {
      const isDependent = (axis === "y" && !horizontal) || (axis === "x" && horizontal);
      return isDependent ?
        [Collection.getMinValue(domain, 0), Collection.getMaxValue(domain, 0)] : domain;
    };
    const datasets = this.getDataFromChildren(props);
    return ensureZero(Domain.getDomainFromGroupedData(props, axis, datasets));
  },

  getColor(calculatedProps, child, index) {
    // check for styles first
    const { style } = calculatedProps;
    let { colorScale, color } = calculatedProps;
    if (style && style.data && style.data.fill) {
      return style.data.fill;
    }
    colorScale = child.props && child.props.colorScale ? child.props.colorScale : colorScale;
    color = child.props && child.props.color ? child.props.color : color;
    if (!colorScale && !color) {
      return undefined;
    }
    const colors = Array.isArray(colorScale) ?
      colorScale : Style.getColorScale(colorScale);
    return color || colors[index % colors.length];
  },

  getWidth(props) {
    const { datasets, scale, horizontal } = props;
    const range = horizontal ? scale.y.range() : scale.x.range();
    const extent = Math.abs(range[1] - range[0]);
    const bars = datasets.length * (datasets[0].length || 1) + 2;
    const barRatio = 0.5;
    return { width: Math.round(barRatio * extent / bars) };
  },

  getChildStyle(child, index, calculatedProps) {
    const { style, role } = calculatedProps;
    const childRole = child.type && child.type.role;
    const defaultFill = childRole === "stack" ?
      undefined : this.getColor(calculatedProps, child, index);
    const defaultColor = childRole === "line" ?
      { fill: "none", stroke: defaultFill } : { fill: defaultFill };
    const childStyle = child.props.style || {};
    const dataWidth = role === "stack" ? {} : this.getWidth(calculatedProps);
    const dataStyle = defaults(
      {}, childStyle.data, assign({}, dataWidth, style.data, defaultColor)
    );
    const labelsStyle = defaults({}, childStyle.labels, style.labels);
    return {
      parent: style.parent,
      data: dataStyle,
      labels: labelsStyle
    };
  },

  getStringsFromCategories(childComponents, axis) { // eslint-disable-line max-statements
    const strings = [];
    let stringsLength = 0;

    const children = childComponents.slice(0).reverse();
    let childrenLength = children.length;

    while (childrenLength > 0) {
      const child = children[--childrenLength];

      if (child.props && child.props.categories) {
        const newStrings = Data.getStringsFromCategories(child.props, axis);
        const newStringsLength = newStrings.length;
        for (let index = 0; index < newStringsLength; index++) {
          strings[stringsLength++] = newStrings[index];
        }
      } else if (child.props && child.props.children) {
        const newChildren = React.Children.toArray(child.props.children);
        const newChildrenLength = newChildren.length;
        for (let index = 0; index < newChildrenLength; index++) {
          children[childrenLength++] = newChildren[index];
        }
      }
    }

    return strings;
  },

  getStringsFromData(childComponents, axis) { // eslint-disable-line max-statements
    const strings = [];
    let stringsLength = 0;

    const children = childComponents.slice(0).reverse();
    let childrenLength = children.length;

    while (childrenLength > 0) {
      const child = children[--childrenLength];

      if (child.props && child.props.data) {
        const newStrings = Data.getStringsFromData(child.props, axis);
        const newStringsLength = newStrings.length;
        for (let index = 0; index < newStringsLength; index++) {
          strings[stringsLength++] = newStrings[index];
        }
      } else if (child.type && isFunction(child.type.getData)) {
        const data = flatten(child.type.getData(child.props));
        const attr = axis === "x" ? "xName" : "yName";
        for (let index = 0; index < data.length; index++) {
          const datum = data[index];
          if (datum[attr]) {
            strings[stringsLength++] = datum[attr];
          }
        }
      } else if (child.props && child.props.children) {
        const newChildren = React.Children.toArray(child.props.children);
        const newChildrenLength = newChildren.length;
        for (let index = 0; index < newChildrenLength; index++) {
          children[childrenLength++] = newChildren[index];
        }
      }
    }

    return strings;
  },

  getStringsFromChildren(props, axis, childComponents) {
    childComponents = childComponents || React.Children.toArray(props.children);
    const axisComponent = Axis.getAxisComponent(childComponents, axis);
    const axisStrings = axisComponent ? Data.getStringsFromAxes(axisComponent.props, axis) : [];
    const categoryStrings = this.getStringsFromCategories(childComponents, axis);
    const dataStrings = this.getStringsFromData(childComponents, axis);
    return uniq(flatten([...categoryStrings, ...dataStrings, ...axisStrings]));
  },

  getCategories(props, axis) {
    const categories = Data.getCategories(props, axis) ||
      this.getStringsFromChildren(props, axis);
    return categories.length > 0 ? categories : undefined;
  },

  getY0(datum, index, calculatedProps) {
    if (datum.y0) {
      return datum.y0;
    }
    const { datasets } = calculatedProps;
    const y = datum._y;
    const previousDataSets = datasets.slice(0, index);
    const previousPoints = previousDataSets.reduce((prev, dataset) => {
      return prev.concat(dataset
        .filter((previousDatum) => datum._x instanceof Date
          ? previousDatum._x.getTime() === datum._x.getTime()
          : previousDatum._x === datum._x)
        .map((previousDatum) => previousDatum._y || 0)
      );
    }, []);
    const y0 = previousPoints.length && previousPoints.reduce((memo, value) => {
      const sameSign = (y < 0 && value < 0) || (y >= 0 && value >= 0);
      return sameSign ? +value + memo : memo;
    }, 0);
    return previousPoints.some((point) => point instanceof Date) ? new Date(y0) : y0;
  }
};
<commit_msg>pad explicit domains<commit_after>import { assign, defaults, flatten, isFunction, partialRight, uniq, some } from "lodash";
import React from "react";
import Axis from "./axis";
import { Style, Transitions, Collection, Data, Domain, Events } from "victory-core";

export default {
  getData(props, childComponents) {
    if (props.data) {
      return Data.getData(props);
    }
    childComponents = childComponents || React.Children.toArray(props.children);
    return this.getDataFromChildren(childComponents);
  },

  getDefaultDomainPadding(props, axis, childComponents) {
    const horizontalChildren = childComponents.some((component) => {
      return component.props && component.props.horizontal;
    });
    const horizontal = props && props.horizontal || horizontalChildren;
    const groupComponent = childComponents.filter((child) => {
      return child.type && child.type.role && child.type.role === "group";
    });

    if (groupComponent.length < 1) {
      return undefined;
    }
    const { offset, children } = groupComponent[0].props;
    const defaultDomainPadding = horizontal ?
      { y: (offset * children.length) / 2 } :
      { x: (offset * children.length) / 2 };
    return defaultDomainPadding[axis];
  },

  getDomain(props, axis, childComponents) {
    childComponents = childComponents || React.Children.toArray(props.children);
    const propsDomain = Domain.getDomainFromProps(props, axis);
    const domainPadding = props.polar ?
      0 : this.getDefaultDomainPadding(props, axis, childComponents);
    let domain;
    if (propsDomain) {
      domain = propsDomain;
    } else {
      const dataset = (props.data || props.y) && Data.getData(props);
      const dataDomain = dataset ? Domain.getDomainFromData(props, axis, dataset) : [];
      const childDomain = this.getDomainFromChildren(props, axis, childComponents);
      const min = Collection.getMinValue([...dataDomain, ...childDomain]);
      const max = Collection.getMaxValue([...dataDomain, ...childDomain]);
      domain = [min, max];
    }
    const paddedDomain = Domain.padDomain(domain, assign({ domainPadding }, props), axis);
    return Domain.cleanDomain(paddedDomain, props, axis);
  },

  setAnimationState(props, nextProps) {
    if (!props.animate) {
      return;
    }
    if (props.animate.parentState) {
      const nodesWillExit = props.animate.parentState.nodesWillExit;
      const oldProps = nodesWillExit ? props : null;
      this.setState(defaults({ oldProps, nextProps }, props.animate.parentState));
    } else {
      const oldChildren = React.Children.toArray(props.children);
      const nextChildren = React.Children.toArray(nextProps.children);
      const isContinuous = (child) => {
        const check = (c) => c.type && c.type.continuous;
        return Array.isArray(child) ? some(child, check) : check(child);
      };

      const continuous = !props.polar && some(oldChildren, (child) => {
        return isContinuous(child) || child.props.children && isContinuous(child.props.children);
      });
      const {
        nodesWillExit,
        nodesWillEnter,
        childrenTransitions,
        nodesShouldEnter
      } = Transitions.getInitialTransitionState(oldChildren, nextChildren);

      this.setState({
        nodesWillExit,
        nodesWillEnter,
        nodesShouldEnter,
        childrenTransitions: Collection.isArrayOfArrays(childrenTransitions) ?
          childrenTransitions[0] : childrenTransitions,
        oldProps: nodesWillExit ? props : null,
        nextProps,
        continuous
      });
    }
  },

  getAllEvents(props) {
    const components = ["groupComponent", "containerComponent", "labelComponent"];
    this.componentEvents = Events.getComponentEvents(props, components);
    if (Array.isArray(this.componentEvents)) {
      return Array.isArray(props.events) ?
        this.componentEvents.concat(...props.events) : this.componentEvents;
    }
    return props.events;
  },

  getAnimationProps(props, child, index) {
    if (!props.animate) {
      return child.props.animate;
    }
    const getFilteredState = () => {
      let childrenTransitions = this.state && this.state.childrenTransitions;
      childrenTransitions = Collection.isArrayOfArrays(childrenTransitions) ?
        childrenTransitions[index] : childrenTransitions;
      return defaults({ childrenTransitions }, this.state);
    };

    let getTransitions = props.animate && props.animate.getTransitions;
    const state = getFilteredState();
    const parentState = props.animate && props.animate.parentState || state;
    if (!getTransitions) {
      const getTransitionProps = Transitions.getTransitionPropsFactory(
        props,
        state,
        (newState) => this.setState(newState)
      );
      getTransitions = partialRight(getTransitionProps, index);
    }
    return defaults({ getTransitions, parentState }, props.animate, child.props.animate);
  },

  getDomainFromChildren(props, axis, childComponents) { // eslint-disable-line max-statements, complexity, max-len
    const childDomains = [];
    let childDomainsLength = 0;

    const children = childComponents
      ? childComponents.slice(0)
      : React.Children.toArray(props.children);
    let childrenLength = children.length;

    const horizontalChildren = childComponents.some((component) => {
      return component.props && component.props.horizontal;
    });
    const horizontal = props && props.horizontal || horizontalChildren.length > 0;
    const currentAxis = Axis.getCurrentAxis(axis, horizontal);

    const parentData = props.data ? Data.getData(props, axis) : undefined;
    const { polar, startAngle, endAngle } = props;
    const parentProps = parentData ?
      { data: parentData, polar, startAngle, endAngle } : { polar, startAngle, endAngle };

    while (childrenLength > 0) {
      const child = children[--childrenLength];

      if (child.type && isFunction(child.type.getDomain)) {
        const sharedProps = assign({}, child.props, parentProps);
        const childDomain = child.props && child.type.getDomain(sharedProps, currentAxis);
        if (childDomain) {
          const childDomainLength = childDomain.length;
          for (let index = 0; index < childDomainLength; index++) {
            childDomains[childDomainsLength++] = childDomain[index];
          }
        }
      } else if (child.props && child.props.children) {
        const newChildren = React.Children.toArray(child.props.children);
        const newChildrenLength = newChildren.length;
        for (let index = 0; index < newChildrenLength; index++) {
          children[childrenLength++] = newChildren[index];
        }
      }
    }
    const min = Collection.getMinValue(childDomains);
    const max = Collection.getMaxValue(childDomains);
    return childDomains.length === 0 ?
      [0, 1] : [min, max];
  },

  getDataFromChildren(props, childComponents) { // eslint-disable-line max-statements
    const getData = (childProps) => {
      const data = Data.getData(childProps);
      return Array.isArray(data) && data.length > 0 ? data : undefined;
    };

    // Reverse the child array to maintain correct order when looping over
    // children starting from the end of the array.
    const children = childComponents
      ? childComponents.slice(0).reverse()
      : React.Children.toArray(props.children).reverse();

    let childrenLength = children.length;

    const dataArr = [];
    let dataArrLength = 0;
    while (childrenLength > 0) {
      const child = children[--childrenLength];
      if (child.type && child.type.role === "axis") {
        dataArrLength = dataArrLength;
      } else if (child.type && child.type.role !== "axis" && isFunction(child.type.getData)) {
        dataArr[dataArrLength++] = child.type.getData(child.props);
      } else if (child.props && child.props.children) {
        const newChildren = React.Children.toArray(child.props.children);
        const newChildrenLength = newChildren.length;
        for (let index = 0; index < newChildrenLength; index++) {
          children[childrenLength++] = newChildren[index];
        }
      } else {
        dataArr[dataArrLength++] = getData(child.props);
      }
    }

    return dataArr;
  },

  getStackedDomain(props, axis) {
    const propsDomain = Domain.getDomainFromProps(props, axis);
    if (propsDomain) {
      return propsDomain;
    }
    const { horizontal } = props;
    const ensureZero = (domain) => {
      const isDependent = (axis === "y" && !horizontal) || (axis === "x" && horizontal);
      return isDependent ?
        [Collection.getMinValue(domain, 0), Collection.getMaxValue(domain, 0)] : domain;
    };
    const datasets = this.getDataFromChildren(props);
    return ensureZero(Domain.getDomainFromGroupedData(props, axis, datasets));
  },

  getColor(calculatedProps, child, index) {
    // check for styles first
    const { style } = calculatedProps;
    let { colorScale, color } = calculatedProps;
    if (style && style.data && style.data.fill) {
      return style.data.fill;
    }
    colorScale = child.props && child.props.colorScale ? child.props.colorScale : colorScale;
    color = child.props && child.props.color ? child.props.color : color;
    if (!colorScale && !color) {
      return undefined;
    }
    const colors = Array.isArray(colorScale) ?
      colorScale : Style.getColorScale(colorScale);
    return color || colors[index % colors.length];
  },

  getWidth(props) {
    const { datasets, scale, horizontal } = props;
    const range = horizontal ? scale.y.range() : scale.x.range();
    const extent = Math.abs(range[1] - range[0]);
    const bars = datasets.length * (datasets[0].length || 1) + 2;
    const barRatio = 0.5;
    return { width: Math.round(barRatio * extent / bars) };
  },

  getChildStyle(child, index, calculatedProps) {
    const { style, role } = calculatedProps;
    const childRole = child.type && child.type.role;
    const defaultFill = childRole === "stack" ?
      undefined : this.getColor(calculatedProps, child, index);
    const defaultColor = childRole === "line" ?
      { fill: "none", stroke: defaultFill } : { fill: defaultFill };
    const childStyle = child.props.style || {};
    const dataWidth = role === "stack" ? {} : this.getWidth(calculatedProps);
    const dataStyle = defaults(
      {}, childStyle.data, assign({}, dataWidth, style.data, defaultColor)
    );
    const labelsStyle = defaults({}, childStyle.labels, style.labels);
    return {
      parent: style.parent,
      data: dataStyle,
      labels: labelsStyle
    };
  },

  getStringsFromCategories(childComponents, axis) { // eslint-disable-line max-statements
    const strings = [];
    let stringsLength = 0;

    const children = childComponents.slice(0).reverse();
    let childrenLength = children.length;

    while (childrenLength > 0) {
      const child = children[--childrenLength];

      if (child.props && child.props.categories) {
        const newStrings = Data.getStringsFromCategories(child.props, axis);
        const newStringsLength = newStrings.length;
        for (let index = 0; index < newStringsLength; index++) {
          strings[stringsLength++] = newStrings[index];
        }
      } else if (child.props && child.props.children) {
        const newChildren = React.Children.toArray(child.props.children);
        const newChildrenLength = newChildren.length;
        for (let index = 0; index < newChildrenLength; index++) {
          children[childrenLength++] = newChildren[index];
        }
      }
    }

    return strings;
  },

  getStringsFromData(childComponents, axis) { // eslint-disable-line max-statements
    const strings = [];
    let stringsLength = 0;

    const children = childComponents.slice(0).reverse();
    let childrenLength = children.length;

    while (childrenLength > 0) {
      const child = children[--childrenLength];

      if (child.props && child.props.data) {
        const newStrings = Data.getStringsFromData(child.props, axis);
        const newStringsLength = newStrings.length;
        for (let index = 0; index < newStringsLength; index++) {
          strings[stringsLength++] = newStrings[index];
        }
      } else if (child.type && isFunction(child.type.getData)) {
        const data = flatten(child.type.getData(child.props));
        const attr = axis === "x" ? "xName" : "yName";
        for (let index = 0; index < data.length; index++) {
          const datum = data[index];
          if (datum[attr]) {
            strings[stringsLength++] = datum[attr];
          }
        }
      } else if (child.props && child.props.children) {
        const newChildren = React.Children.toArray(child.props.children);
        const newChildrenLength = newChildren.length;
        for (let index = 0; index < newChildrenLength; index++) {
          children[childrenLength++] = newChildren[index];
        }
      }
    }

    return strings;
  },

  getStringsFromChildren(props, axis, childComponents) {
    childComponents = childComponents || React.Children.toArray(props.children);
    const axisComponent = Axis.getAxisComponent(childComponents, axis);
    const axisStrings = axisComponent ? Data.getStringsFromAxes(axisComponent.props, axis) : [];
    const categoryStrings = this.getStringsFromCategories(childComponents, axis);
    const dataStrings = this.getStringsFromData(childComponents, axis);
    return uniq(flatten([...categoryStrings, ...dataStrings, ...axisStrings]));
  },

  getCategories(props, axis) {
    const categories = Data.getCategories(props, axis) ||
      this.getStringsFromChildren(props, axis);
    return categories.length > 0 ? categories : undefined;
  },

  getY0(datum, index, calculatedProps) {
    if (datum.y0) {
      return datum.y0;
    }
    const { datasets } = calculatedProps;
    const y = datum._y;
    const previousDataSets = datasets.slice(0, index);
    const previousPoints = previousDataSets.reduce((prev, dataset) => {
      return prev.concat(dataset
        .filter((previousDatum) => datum._x instanceof Date
          ? previousDatum._x.getTime() === datum._x.getTime()
          : previousDatum._x === datum._x)
        .map((previousDatum) => previousDatum._y || 0)
      );
    }, []);
    const y0 = previousPoints.length && previousPoints.reduce((memo, value) => {
      const sameSign = (y < 0 && value < 0) || (y >= 0 && value >= 0);
      return sameSign ? +value + memo : memo;
    }, 0);
    return previousPoints.some((point) => point instanceof Date) ? new Date(y0) : y0;
  }
};
<|endoftext|>


<commit_before>import React, { Component, PropTypes } from 'react';
import { Link } from 'react-router';
import { Badge } from 'reactstrap';

import './ProfileCard.scss';

export default class ProfileCard extends Component {

  static propTypes = {
    id: PropTypes.number,
    username: PropTypes.string,
    avatar: PropTypes.string,
  }

  render() {

    const {
      id,
      username,
      avatar,
      link_count,
      comment_count,
      karma
    } = this.props;

    return (

        { username } <Badge>{ karma }</Badge>

            <Link to={`/u/${id}/${username.toLowerCase()}/links`}>
              Links
              { link_count }
            </Link>

            <Link to={`/u/${id}/${username.toLowerCase()}/comments`}>
              Comments
              { comment_count }
            </Link>

    );
  }
}
<commit_msg>Added tooltip to karma badge<commit_after>import React, { Component, PropTypes } from 'react';
import { Link } from 'react-router';
import { Badge, Tooltip } from 'reactstrap';

import './ProfileCard.scss';

export default class ProfileCard extends Component {

  static propTypes = {
    id: PropTypes.number,
    username: PropTypes.string,
    avatar: PropTypes.string,
  }

  state = {
    tooltipOpen: false,
  }

  toggleTooltip(){
    this.setState({ tooltipOpen: !this.state.tooltipOpen});
  }

  render() {

    const {
      id,
      username,
      avatar,
      link_count,
      comment_count,
      karma
    } = this.props;

    return (

        { username } <Badge id="karma-tooltip">{ karma }</Badge>
        <Tooltip placement="top" isOpen={ this.state.tooltipOpen } target="karma-tooltip" toggle={this.toggleTooltip.bind(this)}>
          Karma
        </Tooltip>

            <Link to={`/u/${id}/${username.toLowerCase()}/links`}>
              Links
              { link_count }
            </Link>

            <Link to={`/u/${id}/${username.toLowerCase()}/comments`}>
              Comments
              { comment_count }
            </Link>

    );
  }
}
<|endoftext|>


<commit_before>'use strict';
/**
 * model
 */
export default class extends think.model.relation {
  /**
   * relation
   * @type {Object}
   */
  relation = {
    cate: {
      type: think.model.MANY_TO_MANY,
      field: 'id,name'
    },
    tag: {
      type: think.model.MANY_TO_MANY,
      field: 'id,name'
    },
    user: {
      type: think.model.BELONG_TO,
      field: 'id,name,display_name'
    }
  };
  /**
   * get where condition
   * @param  {[type]} where [description]
   * @return {[type]}       [description]
   */
  getWhereCondition(where){
    where = think.extend({}, where, {
      is_public: 1, //公开
      type: 0, //文章
      status: 3 //已经发布
    });
    if(!where.create_time){
      where.create_time = {
        '<=': think.datetime()
      };
    }
    return where;
  }
  /**
   * get post list
   * @param  {[type]} page  [description]
   * @param  {[type]} where [description]
   * @return {[type]}       [description]
   */
  async getPostList(page, options = {}){
    let field = options.field || 'id,title,pathname,create_time,summary,comment_num';
    if(options.tag || options.cate){
      let name = options.tag ? 'tag' : 'cate';
      let {id} = await this.model(name).field('id').setRelation(false).where({name: options.tag || options.cate}).find();
      if(think.isEmpty(id)){
        return false;
      }
      let where = this.getWhereCondition({[`${name}.${name}_id`]: id});
      return this.join({
        table: `post_${name}`,
        as: name,
        on: ['id', 'post_id']
      }).where(where).order('create_time DESC').countSelect();
    }

    let where = this.getWhereCondition(options.where);
    page = page | 0 || 1;
    //only cache first page post
    if(page === 1){
      return think.cache('post_1', () => {
        return this.field(field).page(page).setRelation(false).order('create_time DESC').where(where).countSelect();
      },{timeout:259200});
    }

    return this.field(field).page(page).setRelation(false).order('create_time DESC').where(where).countSelect();
  }

  /**
   * get post detail info
   * @param  {[type]} pathname [description]
   * @return {[type]}          [description]
   */
  async getPostDetail(pathname){
    let where = this.getWhereCondition({pathname: pathname});
    let detail = await this.where(where).fieldReverse('markdown_content,summary').find();
    if(think.isEmpty(detail)){
      return detail;
    }
    let createTime = think.datetime(detail.create_time);
    let prevWhere = this.getWhereCondition({
      create_time: ['<', createTime],
      id: ['!=', detail.id]
    });
    let prevPromise = this.field('title,pathname').setRelation(false).where(prevWhere).order('create_time DESC').find();
    let nextWhere = this.getWhereCondition({
      create_time: ['>', createTime],
      id: ['!=', detail.id]
    });
    let nextPromise = this.field('title,pathname').setRelation(false).where(nextWhere).order('create_time ASC').find();
    let [prev, next] = await Promise.all([prevPromise, nextPromise]);
    return {
      detail,
      prev,
      next
    }
  }
  async getPostRssList(){
    let field = 'id,title,pathname,create_time,content';
    let where = this.getWhereCondition();

    let data = await this.field(field).where(where).order('create_time DESC').setRelation(false).limit(10).select();

    return data;
  }

  async getPostSitemapList(){
    let field = 'pathname,update_time';
    let where = this.getWhereCondition();

    let data = await this.field(field).where(where).order('update_time DESC').setRelation(false).select();
    return data;
  }
  /**
   * get post archive
   * @return {[type]} [description]
   */
  async getPostArchive(){
    let where = this.getWhereCondition();
    let data = await this.field('id,title,pathname,create_time').order('create_time DESC').setRelation(false).where(where).select();
    let result = {};
    data.forEach(item => {
      let yearMonth = think.datetime(item.create_time, 'YYYY年MM月');
      if(!(yearMonth in result)){
        result[yearMonth] = [];
      }
      result[yearMonth].push(item);
    });
    return result;
  }
  /**
   * get post search result
   * @param  {[type]} keyword [description]
   * @param  {[type]} page    [description]
   * @return {[type]}         [description]
   */
  async getPostSearch(keyword, page){
    let where = {'title|content': ['LIKE', `%${keyword}%`]}
    where = this.getWhereCondition(where);
    return this.where(where).page(page).setRelation(false).field('title,pathname,summary,create_time').order('create_time DESC').countSelect();
  }
}
<commit_msg>fix conflict<commit_after>'use strict';
/**
 * model
 */
export default class extends think.model.relation {
  /**
   * relation
   * @type {Object}
   */
  relation = {
    cate: {
      type: think.model.MANY_TO_MANY,
      field: 'id,name'
    },
    tag: {
      type: think.model.MANY_TO_MANY,
      field: 'id,name'
    },
    user: {
      type: think.model.BELONG_TO,
      field: 'id,name,display_name'
    }
  };
  /**
   * get where condition
   * @param  {[type]} where [description]
   * @return {[type]}       [description]
   */
  getWhereCondition(where){
    where = think.extend({}, where, {
      is_public: 1, //公开
      type: 0, //文章
      status: 3 //已经发布
    });
    if(!where.create_time){
      where.create_time = {
        '<=': think.datetime()
      };
    }
    return where;
  }
  /**
   * get post list
   * @param  {[type]} page  [description]
   * @param  {[type]} where [description]
   * @return {[type]}       [description]
   */
  async getPostList(page, options = {}){
    let field = options.field || 'id,title,pathname,create_time,summary,comment_num';
    if(options.tag || options.cate){
      let name = options.tag ? 'tag' : 'cate';
      let {id} = await this.model(name).field('id').setRelation(false).where({name: options.tag || options.cate}).find();
      if(think.isEmpty(id)){
        return false;
      }
      let where = this.getWhereCondition({[`${name}.${name}_id`]: id});
      return this.join({
        table: `post_${name}`,
        as: name,
        on: ['id', 'post_id']
      }).where(where).order('create_time DESC').countSelect();
    }

    let where = this.getWhereCondition(options.where);
    page = page | 0 || 1;
    //only cache first page post
    if(page === 1){
      return think.cache('post_1', () => {
        return this.field(field).page(page).setRelation(false).order('create_time DESC').where(where).countSelect();
      },{timeout:259200});
    }

    return this.field(field).page(page).setRelation(false).order('create_time DESC').where(where).countSelect();
  }

  /**
   * get post detail info
   * @param  {[type]} pathname [description]
   * @return {[type]}          [description]
   */
  async getPostDetail(pathname){
    let where = this.getWhereCondition({pathname: pathname});
    let detail = await this.where(where).fieldReverse('markdown_content,summary').find();
    if(think.isEmpty(detail)){
      return detail;
    }
    let createTime = think.datetime(detail.create_time);
    let prevWhere = this.getWhereCondition({
      create_time: ['<', createTime],
      id: ['!=', detail.id]
    });
    let prevPromise = this.field('title,pathname').setRelation(false).where(prevWhere).order('create_time DESC').find();
    let nextWhere = this.getWhereCondition({
      create_time: ['>', createTime],
      id: ['!=', detail.id]
    });
    let nextPromise = this.field('title,pathname').setRelation(false).where(nextWhere).order('create_time ASC').find();
    let [prev, next] = await Promise.all([prevPromise, nextPromise]);
    return {
      detail,
      prev,
      next
    }
  }
  async getPostRssList(){
    let field = 'id,title,pathname,content,create_time';
    let where = this.getWhereCondition();

    let data = await this.field(field).where(where).order('create_time DESC').setRelation(false).limit(10).select();

    return data;
  }

  async getPostSitemapList(){
    let field = 'pathname,update_time';
    let where = this.getWhereCondition();

    let data = await this.field(field).where(where).order('update_time DESC').setRelation(false).select();
    return data;
  }
  /**
   * get post archive
   * @return {[type]} [description]
   */
  async getPostArchive(){
    let where = this.getWhereCondition();
    let data = await this.field('id,title,pathname,create_time').order('create_time DESC').setRelation(false).where(where).select();
    let result = {};
    data.forEach(item => {
      let yearMonth = think.datetime(item.create_time, 'YYYY年MM月');
      if(!(yearMonth in result)){
        result[yearMonth] = [];
      }
      result[yearMonth].push(item);
    });
    return result;
  }
  /**
   * get post search result
   * @param  {[type]} keyword [description]
   * @param  {[type]} page    [description]
   * @return {[type]}         [description]
   */
  async getPostSearch(keyword, page){
    let where = {'title|content': ['LIKE', `%${keyword}%`]}
    where = this.getWhereCondition(where);
    return this.where(where).page(page).setRelation(false).field('title,pathname,summary,create_time').order('create_time DESC').countSelect();
  }
}
<|endoftext|>


<commit_before>// Extensions
(function( undefined ){
	shoestring.fn.closest = function( sel ){
		var ret = [];
		if( !sel ){
			return shoestring( ret );
		}

		this.each(function(){
			var self = this,
				generations = 0;

			shoestring( sel ).each(function(){
				if( self === this && !ret.length ){
					ret.push( self );
				}
			});

			if( !ret.length ){
				shoestring( sel ).each(function(){
					var i = 0;
					while( self.parentElement && ( !generations || i < generations ) ){
						i++;
						if( self.parentElement === this ){
							ret.push( self.parentElement );
							generations = i;
						}
						else{
							self = self.parentElement;
						}
					}
				});
			}

		});
		return shoestring( ret );
	};
}());<commit_msg>Fix for .closest (would give no results on multiple uses).<commit_after>// Extensions
(function( undefined ){
	shoestring.fn.closest = function( sel ){
		var ret = [];
		if( !sel ){
			return shoestring( ret );
		}

		this.each(function(){
			var self = this,
				generations = 0;

			shoestring( sel ).each(function(){
				if( self === this && !ret.length ){
					ret.push( self );
				}
			});

			if( !ret.length ){
				shoestring( sel ).each(function(){
					var i = 0,
						otherSelf = self;

					while( otherSelf.parentElement && ( !generations || i < generations ) ){
						i++;
						if( otherSelf.parentElement === this ){
							ret.push( otherSelf.parentElement );
							generations = i;
						}
						else{
							otherSelf = otherSelf.parentElement;
						}
					}
				});
			}

		});
		return shoestring( ret );
	};
}());<|endoftext|>


<commit_before>// @flow
import React from 'react';

import DrawLineLayer from './DrawLineLayer';

export type ActiveActionLayer = 'drawLine' | 'eraser';

export default function ActionLayer(props: {
  activeActionLayer: ActiveActionLayer,
}) {
  switch (props.activeActionLayer) {
    case 'drawLine':
      return <DrawLineLayer {...props} />;
    default:
      throw new Error('Could not find ActionLayer.');
  }
}
<commit_msg>props.activeActionLayer は使わないので削除する。<commit_after>// @flow
import React from 'react';

import DrawLineLayer from './DrawLineLayer';

export type ActiveActionLayer = 'drawLine' | 'eraser';

export default function ActionLayer(props: {
  activeActionLayer: ActiveActionLayer,
}) {
  const useProps = Object.assign({}, props);
  delete useProps.activeActionLayer;
  switch (props.activeActionLayer) {
    case 'drawLine':
      return <DrawLineLayer {...useProps} />;
    default:
      throw new Error('Could not find ActionLayer.');
  }
}
<|endoftext|>


<commit_before>var path = require('path'),
    vow = require('vow'),
    mockFs = require('mock-fs'),
    TestNode = require('enb/lib/test/mocks/test-node'),
    Tech = require('../../techs/merge-deps');

describe('techs', function () {
    describe('merge-deps', function () {
        afterEach(function () {
            mockFs.restore();
        });

        it('must provide result from data', function (done) {
            var sources = [[{ block: 'block' }]],
                deps = [{ block: 'block' }];

            assert(sources, deps, done);
        });

        it('must provide result from cache', function (done) {
            mockFs({
                bundle: {
                    'bundle.deps.js': 'exports.deps = ' + JSON.stringify([
                        { block: 'other-block' }
                    ]) + ';',
                    'bundle-1.deps.js': 'exports.deps = ' + JSON.stringify([{ block: 'block-1' }]) + ';',
                    'bundle-2.deps.js': 'exports.deps = ' + JSON.stringify([{ block: 'block-2' }]) + ';'
                }
            });

            var bundle = new TestNode('bundle'),
                cache = bundle.getNodeCache('bundle.deps.js');

            cache.cacheFileInfo('deps-file', path.resolve('bundle/bundle.deps.js'));
            cache.cacheFileList('source-file-list', [
                path.resolve('bundle/bundle-1.deps.js'),
                path.resolve('bundle/bundle-2.deps.js')
            ]);

            return bundle.runTech(Tech, { sources: ['bundle-1.deps.js', 'bundle-2.deps.js'] })
                .then(function (target) {
                    target.deps.must.eql([{ block: 'other-block' }]);
                })
                .then(done, done);
        });

        it('must support BEMDECL', function (done) {
            var decl1 = [{ name: 'block-1' }],
                decl2 = [{ name: 'block-2' }],
                expected = [
                    { block: 'block-1' },
                    { block: 'block-2' }
                ];

            assert([decl1, decl2], expected, done);
        });

        it('must merge block with mod of block', function (done) {
            var decl1 = [{ block: 'block' }],
                decl2 = [{ block: 'block', mod: 'mod-name', val: 'mod-val' }],
                expected = [
                    { block: 'block' },
                    { block: 'block', mod: 'mod-name', val: 'mod-val' }
                ];

            assert([decl1, decl2], expected, done);
        });

        it('must merge block with elem', function (done) {
            var decl1 = [{ block: 'block' }],
                decl2 = [{ block: 'block', elem: 'elem' }],
                expected = [
                    { block: 'block' },
                    { block: 'block', elem: 'elem' }
                ];

            assert([decl1, decl2], expected, done);
        });

        it('must merge elem with mod of elem', function (done) {
            var decl1 = [{ block: 'block', elem: 'elem' }],
                decl2 = [{ block: 'block', elem: 'elem', mod: 'mod-name', val: 'mod-val' }],
                expected = [
                    { block: 'block', elem: 'elem' },
                    { block: 'block', elem: 'elem', mod: 'mod-name', val: 'mod-val' }
                ];

            assert([decl1, decl2], expected, done);
        });

        it('must merge elems of block', function (done) {
            var decl1 = [{ block: 'block', elem: 'elem-1' }],
                decl2 = [{ block: 'block', elem: 'elem-2' }],
                expected = [
                    { block: 'block', elem: 'elem-1' },
                    { block: 'block', elem: 'elem-2' }
                ];

            assert([decl1, decl2], expected, done);
        });

        it('must merge set with empty set', function (done) {
            var decl1 = [],
                decl2 = [{ block: '1' }, { block: '2' }, { block: '3' }],
                expected = [{ block: '1' }, { block: '2' }, { block: '3' }];

            assert([decl1, decl2], expected, done);
        });

        it('must merge intersecting sets', function (done) {
            var decl1 = [{ block: '1' }, { block: '2' }, { block: '3' }],
                decl2 = [{ block: '2' }],
                expected = [{ block: '1' }, { block: '2' }, { block: '3' }];

            assert([decl1, decl2], expected, done);
        });

        it('must merge disjoint sets', function (done) {
            var decl1 = [{ block: '1' }, { block: '2' }, { block: '3' }],
                decl2 = [{ block: 'O_o' }],
                expected = [{ block: '1' }, { block: '2' }, { block: '3' }, { block: 'O_o' }];

            assert([decl1, decl2], expected, done);
        });
    });
});

function assert(sources, expected, done) {
    var dataBundle = new TestNode('data-bundle'),
        fsBundle,
        dir = {},
        options = { sources: [] },
        dataOptions = { sources: [] };

    mockFs({ 'data-bundle': {} });

    sources.forEach(function (deps, i) {
        var target = i + '.deps.js',
            dataTarget = 'data-' + target,
            isBemdecl = !!deps && deps.length && deps[0].name;

        dir[target] = isBemdecl ? 'exports.blocks = ' + JSON.stringify(deps) + ';' :
            'exports.deps = ' + JSON.stringify(deps) + ';';
        options.sources.push(target);

        dataBundle.provideTechData(dataTarget, isBemdecl ? { blocks: deps } : { deps: deps });
        dataOptions.sources.push(dataTarget);
    });

    mockFs({ 'fs-bundle': dir, 'data-bundle': {} });

    fsBundle = (new TestNode('fs-bundle'));

    return vow.all([
            fsBundle.runTechAndGetResults(Tech, options),
            fsBundle.runTechAndRequire(Tech, options),
            dataBundle.runTechAndGetResults(Tech, dataOptions),
            dataBundle.runTechAndRequire(Tech, dataOptions)
        ])
        .spread(function (data1, target1, data2, target2) {
            data1['fs-bundle.deps.js'].deps.must.eql(expected);
            target1[0].deps.must.eql(expected);
            data2['data-bundle.deps.js'].deps.must.eql(expected);
            target2[0].deps.must.eql(expected);
        })
        .then(done, done);
}
<commit_msg>Fixed test for `merge-deps` tech<commit_after>var path = require('path'),
    vow = require('vow'),
    mockFs = require('mock-fs'),
    fileList = require('enb/lib/file-list'),
    TestNode = require('enb/lib/test/mocks/test-node'),
    Tech = require('../../techs/merge-deps');

describe('techs', function () {
    describe('merge-deps', function () {
        afterEach(function () {
            mockFs.restore();
        });

        it('must provide result from data', function (done) {
            var sources = [[{ block: 'block' }]],
                deps = [{ block: 'block' }];

            assert(sources, deps, done);
        });

        it('must provide result from cache', function (done) {
            mockFs({
                bundle: {
                    'bundle.deps.js': 'exports.deps = ' + JSON.stringify([
                        { block: 'other-block' }
                    ]) + ';',
                    'bundle-1.deps.js': 'exports.deps = ' + JSON.stringify([{ block: 'block-1' }]) + ';',
                    'bundle-2.deps.js': 'exports.deps = ' + JSON.stringify([{ block: 'block-2' }]) + ';'
                }
            });

            var bundle = new TestNode('bundle'),
                cache = bundle.getNodeCache('bundle.deps.js');

            cache.cacheFileInfo('deps-file', path.resolve('bundle', 'bundle.deps.js'));
            cache.cacheFileList('source-file-list', [
                path.resolve('bundle', 'bundle-1.deps.js'),
                path.resolve('bundle', 'bundle-2.deps.js')
            ].map(function (filename) {
                return fileList.getFileInfo(filename);
            }));

            return bundle.runTech(Tech, { sources: ['bundle-1.deps.js', 'bundle-2.deps.js'] })
                .then(function (target) {
                    target.deps.must.eql([{ block: 'other-block' }]);
                })
                .then(done, done);
        });

        it('must support BEMDECL', function (done) {
            var decl1 = [{ name: 'block-1' }],
                decl2 = [{ name: 'block-2' }],
                expected = [
                    { block: 'block-1' },
                    { block: 'block-2' }
                ];

            assert([decl1, decl2], expected, done);
        });

        it('must merge block with mod of block', function (done) {
            var decl1 = [{ block: 'block' }],
                decl2 = [{ block: 'block', mod: 'mod-name', val: 'mod-val' }],
                expected = [
                    { block: 'block' },
                    { block: 'block', mod: 'mod-name', val: 'mod-val' }
                ];

            assert([decl1, decl2], expected, done);
        });

        it('must merge block with elem', function (done) {
            var decl1 = [{ block: 'block' }],
                decl2 = [{ block: 'block', elem: 'elem' }],
                expected = [
                    { block: 'block' },
                    { block: 'block', elem: 'elem' }
                ];

            assert([decl1, decl2], expected, done);
        });

        it('must merge elem with mod of elem', function (done) {
            var decl1 = [{ block: 'block', elem: 'elem' }],
                decl2 = [{ block: 'block', elem: 'elem', mod: 'mod-name', val: 'mod-val' }],
                expected = [
                    { block: 'block', elem: 'elem' },
                    { block: 'block', elem: 'elem', mod: 'mod-name', val: 'mod-val' }
                ];

            assert([decl1, decl2], expected, done);
        });

        it('must merge elems of block', function (done) {
            var decl1 = [{ block: 'block', elem: 'elem-1' }],
                decl2 = [{ block: 'block', elem: 'elem-2' }],
                expected = [
                    { block: 'block', elem: 'elem-1' },
                    { block: 'block', elem: 'elem-2' }
                ];

            assert([decl1, decl2], expected, done);
        });

        it('must merge set with empty set', function (done) {
            var decl1 = [],
                decl2 = [{ block: '1' }, { block: '2' }, { block: '3' }],
                expected = [{ block: '1' }, { block: '2' }, { block: '3' }];

            assert([decl1, decl2], expected, done);
        });

        it('must merge intersecting sets', function (done) {
            var decl1 = [{ block: '1' }, { block: '2' }, { block: '3' }],
                decl2 = [{ block: '2' }],
                expected = [{ block: '1' }, { block: '2' }, { block: '3' }];

            assert([decl1, decl2], expected, done);
        });

        it('must merge disjoint sets', function (done) {
            var decl1 = [{ block: '1' }, { block: '2' }, { block: '3' }],
                decl2 = [{ block: 'O_o' }],
                expected = [{ block: '1' }, { block: '2' }, { block: '3' }, { block: 'O_o' }];

            assert([decl1, decl2], expected, done);
        });
    });
});

function assert(sources, expected, done) {
    var bundle,
        dir = {},
        options = { sources: [] };

    sources.forEach(function (deps, i) {
        var target = i + '.deps.js',

            isBemdecl = !!deps && deps.length && deps[0].name;

        dir[target] = isBemdecl ? 'exports.blocks = ' + JSON.stringify(deps) + ';' :
            'exports.deps = ' + JSON.stringify(deps) + ';';
        options.sources.push(target);
    });

    mockFs({ bundle: dir });
    bundle = (new TestNode('bundle'));

    return vow.all([
            bundle.runTechAndGetResults(Tech, options),
            bundle.runTechAndRequire(Tech, options)
        ])
        .spread(function (target1, target2) {
            target1['bundle.deps.js'].deps.must.eql(expected);
            target2[0].deps.must.eql(expected);
        })
        .then(done, done);
}
<|endoftext|>


<commit_before>// @flow
const fs = require(`fs`)
const traverse = require(`babel-traverse`).default
const get = require(`lodash/get`)
const { babelParseToAst } = require(`../utils/babel-parse-to-ast`)
const report = require(`gatsby-cli/lib/reporter`)

/**
 * Given a `require.resolve()` compatible path pointing to a JS module,
 * return an array listing the names of the module's exports.
 *
 * Returns [] for invalid paths and modules without exports.
 *
 * @param {string} modulePath
 * @param {function} resolver
 */
module.exports = (modulePath, resolver = require.resolve) => {
  let absPath
  const exportNames = []

  try {
    absPath = resolver(modulePath)
  } catch (err) {
    return exportNames // doesn't exist
  }
  const code = fs.readFileSync(absPath, `utf8`) // get file contents

  const ast = babelParseToAst(code, absPath)

  let isCommonJS = false
  let isES6 = false

  // extract names of exports from file
  traverse(ast, {
    // Check if the file is using ES6 imports
    ImportDeclaration: function ImportDeclaration(astPath) {
      isES6 = true
    },

    // get foo from `export const foo = bar`
    ExportNamedDeclaration: function ExportNamedDeclaration(astPath) {
      const exportName = get(
        astPath,
        `node.declaration.declarations[0].id.name`
      )
      isES6 = true
      if (exportName) exportNames.push(exportName)
    },
    AssignmentExpression: function AssignmentExpression(astPath) {
      const nodeLeft = astPath.node.left

      if (nodeLeft.type !== `MemberExpression`) return

      // get foo from `exports.foo = bar`
      if (get(nodeLeft, `object.name`) === `exports`) {
        isCommonJS = true
        exportNames.push(nodeLeft.property.name)
      }

      // get foo from `module.exports.foo = bar`
      if (
        get(nodeLeft, `object.object.name`) === `module` &&
        get(nodeLeft, `object.property.name`) === `exports`
      ) {
        isCommonJS = true
        exportNames.push(nodeLeft.property.name)
      }
    },
  })

  if (isES6 && isCommonJS && process.env.NODE_ENV !== `test`) {
    report.panic(
      `This plugin file is using both CommonJS and ES6 module systems together which we don't support.
You'll need to edit the file to use just one or the other.

plugin: ${modulePath}.js

This didn't cause a problem in Gatsby v1 so you might want to review the migration doc for this:
https://next.gatsbyjs.org/docs/migrating-from-v1-to-v2/#convert-to-either-pure-commonjs-or-pure-es6
      `
    )
  }
  return exportNames
}
<commit_msg>switch to a neater URL (#7324)<commit_after>// @flow
const fs = require(`fs`)
const traverse = require(`babel-traverse`).default
const get = require(`lodash/get`)
const { babelParseToAst } = require(`../utils/babel-parse-to-ast`)
const report = require(`gatsby-cli/lib/reporter`)

/**
 * Given a `require.resolve()` compatible path pointing to a JS module,
 * return an array listing the names of the module's exports.
 *
 * Returns [] for invalid paths and modules without exports.
 *
 * @param {string} modulePath
 * @param {function} resolver
 */
module.exports = (modulePath, resolver = require.resolve) => {
  let absPath
  const exportNames = []

  try {
    absPath = resolver(modulePath)
  } catch (err) {
    return exportNames // doesn't exist
  }
  const code = fs.readFileSync(absPath, `utf8`) // get file contents

  const ast = babelParseToAst(code, absPath)

  let isCommonJS = false
  let isES6 = false

  // extract names of exports from file
  traverse(ast, {
    // Check if the file is using ES6 imports
    ImportDeclaration: function ImportDeclaration(astPath) {
      isES6 = true
    },

    // get foo from `export const foo = bar`
    ExportNamedDeclaration: function ExportNamedDeclaration(astPath) {
      const exportName = get(
        astPath,
        `node.declaration.declarations[0].id.name`
      )
      isES6 = true
      if (exportName) exportNames.push(exportName)
    },
    AssignmentExpression: function AssignmentExpression(astPath) {
      const nodeLeft = astPath.node.left

      if (nodeLeft.type !== `MemberExpression`) return

      // get foo from `exports.foo = bar`
      if (get(nodeLeft, `object.name`) === `exports`) {
        isCommonJS = true
        exportNames.push(nodeLeft.property.name)
      }

      // get foo from `module.exports.foo = bar`
      if (
        get(nodeLeft, `object.object.name`) === `module` &&
        get(nodeLeft, `object.property.name`) === `exports`
      ) {
        isCommonJS = true
        exportNames.push(nodeLeft.property.name)
      }
    },
  })

  if (isES6 && isCommonJS && process.env.NODE_ENV !== `test`) {
    report.panic(
      `This plugin file is using both CommonJS and ES6 module systems together which we don't support.
You'll need to edit the file to use just one or the other.

plugin: ${modulePath}.js

This didn't cause a problem in Gatsby v1 so you might want to review the migration doc for this:
https://gatsby.app/no-mixed-modules
      `
    )
  }
  return exportNames
}
<|endoftext|>


<commit_before>/*!
 * Copyright 2013 Apereo Foundation (AF) Licensed under the
 * Educational Community License, Version 2.0 (the "License"); you may
 * not use this file except in compliance with the License. You may
 * obtain a copy of the License at
 *
 *     http://opensource.org/licenses/ECL-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an "AS IS"
 * BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
 * or implied. See the License for the specific language governing
 * permissions and limitations under the License.
 */

define(['require', 'jquery', 'oae.core'], function(require, $, oae) {

    return function(uid, showSettings, widgetData) {

        // Cache the widget container
        var $rootel = $('#' + uid);

        /////////////////////
        // DEFAULT PREVIEW //
        /////////////////////

        // Variable that will keep track of the interval used to check for a finished content preview generation
        var contentPreviewInterval = false;

        /**
         * Render the default preview for all files that don't have a particular in-line preview
         */
        var renderDefault = function() {
            // If the preview status is pending, we show a "Generating" message and
            // re-check every minute whether or not the preview has finished generating.
            // If so, we show the generated preview
            if (widgetData.previews && widgetData.previews.status === 'pending') {
                oae.api.util.template().render($('#filepreview-default-pending-template', $rootel), {'content': widgetData}, $('#filepreview-container', $rootel));
                contentPreviewInterval = setInterval(checkContentPreview, 60000);
            } else {
                oae.api.util.template().render($('#filepreview-default-template', $rootel), {'content': widgetData}, $('#filepreview-container', $rootel));
            }
        };

        /**
         * Check whether or not the content preview status has changed from 'pending' to finished.
         * Once preview processing has finished, we trigger an event that will cause the content
         * profile to refresh.
         */
        var checkContentPreview = function() {
            oae.api.content.getContent(widgetData.id, function(err, contentObj) {
                if (err) {
                    clearInterval(contentPreviewInterval);
                } else if (contentObj.previews && contentObj.previews.status !== 'pending') {
                    clearInterval(contentPreviewInterval);
                    $(document).trigger('oae.content.update', contentObj);
                }
            });
        };

        /////////////////////
        // IMAGE PREVIEW //
        /////////////////////

        /**
         * Render an image preview by embedding the image into the document
         */
        var renderImagePreview = function() {
            oae.api.util.template().render($('#filepreview-image-template', $rootel), {'content': widgetData}, $('#filepreview-container', $rootel));
        };

        //////////////////////
        // DOCUMENT PREVIEW //
        //////////////////////

        /**
         * Render a PDF or Office Document
         */
        var renderDocumentPreview = function() {
            // Only load the documentviewer when we are looking at an actual document
            require(['../lib/document-viewer/assets/viewer.js'], function(DV) {
                // Prepare the container
                oae.api.util.template().render($('#filepreview-document-template', $rootel), null, $('#filepreview-container', $rootel));

                // Initialize the document viewer
                var doc = {
                    'id': widgetData.id,
                    'title': widgetData.displayName,
                    'pages': widgetData.previews.pageCount,
                    'resources': {
                        'pdf': '/api/content/' + widgetData.id + '/download',
                        'page': {
                            'image': '/api/content/' + widgetData.id + '/revisions/' + widgetData.latestRevisionId + '/previews/page.{page}.{size}.png?signature=' + widgetData.signature.signature + '&expires=' + widgetData.signature.expires + '&lastmodified=' + widgetData.signature.lastModified
                        }
                    }
                };
                DV.load(doc, {
                    'container': '#' + uid + ' #filepreview-document',
                    'width': '100%',
                    'height': 700,
                    'sidebar': false,
                    'text': false
                });
            });
        };

        /////////////////////////
        // VIDEO/SOUND PREVIEW //
        /////////////////////////

        /**
         * Render a video preview using Flowplayer
         */
        var renderVideoPreview = function() {
            // Only load the flowplayer when we are looking at an actual video
            require(['flowplayer'], function() {
                oae.api.util.template().render($('#filepreview-video-template', $rootel), {'content': widgetData}, $('#filepreview-container', $rootel));
                $('#filepreview-video', $rootel).flowplayer();
            });
        };

        ////////////////////
        // INITIALISATION //
        ////////////////////

        /**
         * Render the file's preview based on its type
         */
        var initFilePreview = function() {
            // Image preview
            if (widgetData.mime.substring(0, 6) === 'image/') {
                renderImagePreview();
            // Display PDFs, Office files, ..
            } else if (widgetData.previews && widgetData.previews.pageCount) {
                renderDocumentPreview();
            // Video preview
            } else if (widgetData.mime.substring(0, 6) === 'video/') {
                renderVideoPreview();
            // Default preview
            } else {
                renderDefault();
            }
        };

        initFilePreview();

    };
});
<commit_msg>add mediacore player<commit_after>/*!
 * Copyright 2013 Apereo Foundation (AF) Licensed under the
 * Educational Community License, Version 2.0 (the "License"); you may
 * not use this file except in compliance with the License. You may
 * obtain a copy of the License at
 *
 *     http://opensource.org/licenses/ECL-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an "AS IS"
 * BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
 * or implied. See the License for the specific language governing
 * permissions and limitations under the License.
 */

define(['require', 'jquery', 'oae.core'], function(require, $, oae) {

    return function(uid, showSettings, widgetData) {

        // Cache the widget container
        var $rootel = $('#' + uid);

        /////////////////////
        // DEFAULT PREVIEW //
        /////////////////////

        // Variable that will keep track of the interval used to check for a finished content preview generation
        var contentPreviewInterval = false;

        /**
         * Render the default preview for all files that don't have a particular in-line preview
         */
        var renderDefault = function() {
            // If the preview status is pending, we show a "Generating" message and
            // re-check every minute whether or not the preview has finished generating.
            // If so, we show the generated preview
            if (widgetData.previews && widgetData.previews.status === 'pending') {
                oae.api.util.template().render($('#filepreview-default-pending-template', $rootel), {'content': widgetData}, $('#filepreview-container', $rootel));
                contentPreviewInterval = setInterval(checkContentPreview, 60000);
            } else {
                oae.api.util.template().render($('#filepreview-default-template', $rootel), {'content': widgetData}, $('#filepreview-container', $rootel));
            }
        };

        /**
         * Check whether or not the content preview status has changed from 'pending' to finished.
         * Once preview processing has finished, we trigger an event that will cause the content
         * profile to refresh.
         */
        var checkContentPreview = function() {
            oae.api.content.getContent(widgetData.id, function(err, contentObj) {
                if (err) {
                    clearInterval(contentPreviewInterval);
                } else if (contentObj.previews && contentObj.previews.status !== 'pending') {
                    clearInterval(contentPreviewInterval);
                    $(document).trigger('oae.content.update', contentObj);
                }
            });
        };

        /////////////////////
        // IMAGE PREVIEW //
        /////////////////////

        /**
         * Render an image preview by embedding the image into the document
         */
        var renderImagePreview = function() {
            oae.api.util.template().render($('#filepreview-image-template', $rootel), {'content': widgetData}, $('#filepreview-container', $rootel));
        };

        //////////////////////
        // DOCUMENT PREVIEW //
        //////////////////////

        /**
         * Render a PDF or Office Document
         */
        var renderDocumentPreview = function() {
            // Only load the documentviewer when we are looking at an actual document
            require(['../lib/document-viewer/assets/viewer.js'], function(DV) {
                // Prepare the container
                oae.api.util.template().render($('#filepreview-document-template', $rootel), null, $('#filepreview-container', $rootel));

                // Initialize the document viewer
                var doc = {
                    'id': widgetData.id,
                    'title': widgetData.displayName,
                    'pages': widgetData.previews.pageCount,
                    'resources': {
                        'pdf': '/api/content/' + widgetData.id + '/download',
                        'page': {
                            'image': '/api/content/' + widgetData.id + '/revisions/' + widgetData.latestRevisionId + '/previews/page.{page}.{size}.png?signature=' + widgetData.signature.signature + '&expires=' + widgetData.signature.expires + '&lastmodified=' + widgetData.signature.lastModified
                        }
                    }
                };
                DV.load(doc, {
                    'container': '#' + uid + ' #filepreview-document',
                    'width': '100%',
                    'height': 700,
                    'sidebar': false,
                    'text': false
                });
            });
        };

        /////////////////////////
        // VIDEO/SOUND PREVIEW //
        /////////////////////////

        /**
         * Render a video preview using Flowplayer
         */
        var renderVideoPreview = function() {
            // Only load the flowplayer when we are looking at an actual video
            require(['flowplayer'], function() {
                oae.api.util.template().render($('#filepreview-video-template', $rootel), {'content': widgetData}, $('#filepreview-container', $rootel));
                $('#filepreview-video', $rootel).flowplayer();
            });
        };

        ///////////////////////
        // MEDIACORE PREVIEW //
        ///////////////////////
        var renderMediaCorePreview = function() {
            $.ajax({
                'url': '/api/mediacore/embed/' + widgetData.id,
                'success': function(data) {
                    $('#filepreview-container', $rootel).html('
' + data.html + '
');
                }
            });
        };

        ////////////////////
        // INITIALISATION //
        ////////////////////

        /**
         * Render the file's preview based on its type
         */
        var initFilePreview = function() {
            // Image preview
            if (widgetData.mime.substring(0, 6) === 'image/') {
                renderImagePreview();
            // Display PDFs, Office files, ..
            } else if (widgetData.previews && widgetData.previews.pageCount) {
                renderDocumentPreview();
            // MediaCore preview
            } else if (widgetData.previews.mediacoreId) {
                renderMediaCorePreview();
            // Video preview
            } else if (widgetData.mime.substring(0, 6) === 'video/') {
                renderVideoPreview();
            // Default preview
            } else {
                renderDefault();
            }
        };

        initFilePreview();

    };
});
<|endoftext|>