<commit_before>import {BaseStore} from 'fluxible/addons';

class SlideEditStore extends BaseStore {
    constructor(dispatcher) {
        super(dispatcher);
        //this.dispatcher = dispatcher; // Provides access to waitFor and getStore methods
        this.id = '';
        this.slideId = '';
        this.title = '';
        this.LeftPanelTitleChange = false;
        this.content = '';
        this.markdown = '';
        this.speakernotes = '';
        this.scaleratio = 1; //default no scale ratio
        this.template = '';
        this.slideSize = '';
        this.slideSizeText = '';
        this.saveSlideClick = 'false';
        this.cancelClick = 'false';
        this.selector = '';
        this.undoClick = 'false';
        this.redoClick = 'false';
        this.addInputBox = 'false';
        this.uploadMediaClick = 'false';
        this.uploadVideoClick = 'false';
        this.tableClick = 'false';
        this.mathsClick = 'false';
        this.codeClick = 'false';
        this.removeBackgroundClick = 'false';
        this.embedClick = 'false';
        this.embedWidth = '';
        this.embedHeight = '';
        this.embedURL = '';
        this.embedCode = '';
        this.HTMLEditorClick = 'false';
    }
    updateContent(payload) {
        //console.log('test' + payload + payload.slide.content + ' title: ' +  payload.slide.title + ' id: ' + payload.slide.id);
        //console.log('test' + payload.slide.title + ' id: ' + payload.slide.id);
        this.id = payload.slide.id;
        this.slideId = payload.selector.sid;
        this.title = payload.slide.title || ' ';
        this.content = payload.slide.content || ' ';
        this.markdown = payload.slide.markdown || ' ';
        this.speakernotes = payload.slide.speakernotes || ' ';

        this.emitChange();
    }
    saveSlide() {
        this.emitChange();
    }
    addSlide() {
        this.emitChange();
    }
    changeTemplate(payload){
        this.template = payload.template;
        this.emitChange();
        this.template = '';
        this.emitChange();
    }
    changeSlideSize(payload){
        this.slideSize = payload.slideSize;
        this.emitChange();
        this.slideSize = '';
        this.emitChange();
    }
    handleSaveSlideClick(){
        this.saveSlideClick = 'true';
        this.emitChange();
        this.saveSlideClick = 'false';
        this.emitChange();
    }
    handleCancelClick(payload){
        this.selector = payload.selector;
        this.cancelClick = 'true';
        this.emitChange();
        this.cancelClick = 'false';
        this.emitChange();
    }
    handleUndoClick(){
        this.undoClick = 'true';
        this.emitChange();
        this.undoClick = 'false';
        this.emitChange();
    }
    handleRedoClick(){
        this.redoClick = 'true';
        this.emitChange();
        this.redoClick = 'false';
        this.emitChange();
    }
    handleAddInputBox(){
        this.addInputBox = 'true';
        this.emitChange();
        this.addInputBox = 'false';
        this.emitChange();
    }
    handleUploadMedia(){
        this.uploadMediaClick = 'true';
        this.emitChange();
        this.uploadMediaClick = 'false';
        this.emitChange();
    }
    handleuploadVideoClick(){
        this.uploadVideoClick = 'true';
        this.emitChange();
        this.uploadVideoClick = 'false';
        this.emitChange();
    }
    handleTableClick(){
        this.tableClick = 'true';
        this.emitChange();
        this.tableClick = 'false';
        this.emitChange();
    }
    handleMathsClick(){
        this.mathsClick = 'true';
        this.emitChange();
        this.mathsClick = 'false';
        this.emitChange();
    }
    handleCodeClick(){
        this.codeClick = 'true';
        this.emitChange();
        this.codeClick = 'false';
        this.emitChange();
    }
    handleRemoveBackgroundClick(){
        this.removeBackgroundClick = 'true';
        this.emitChange();
        this.removeBackgroundClick = 'false';
        this.emitChange();
    }
    handleEmbedClick(payload){
        this.embedClick = 'true';
        this.embedWidth = payload.embedWidth;
        this.embedHeight = payload.embedHeight;
        this.embedURL = payload.embedURL;
        this.embedCode = payload.embedCode;
        this.emitChange();
        this.embedClick = 'false';
        this.embedWidth = '';
        this.embedHeight = '';
        this.embedURL = '';
        this.embedCode = '';
        this.emitChange();
    }
    changeTitle(payload){
        this.title = payload.title;
        this.LeftPanelTitleChange = payload.LeftPanelTitleChange;
        this.emitChange();
        //this.title = '';
        //this.emitChange();
    }
    handleHTMLEditorClick(){
        this.HTMLEditorClick = 'true';
        this.emitChange();
        this.HTMLEditorClick = 'false';
        this.emitChange();
    }

    getState() {
        return {
            id: this.id,
            slideId: this.slideId,
            title: this.title,
            LeftPanelTitleChange: this.LeftPanelTitleChange,
            content: this.content,
            markdown: this.markdown,
            speakernotes: this.speakernotes,
            scaleratio: this.scaleratio,
            saveSlideClick: this.saveSlideClick,
            cancelClick: this.cancelClick,
            selector: this.selector,
            undoClick: this.undoClick,
            redoClick: this.redoClick,
            template: this.template,
            slideSize: this.slideSize,
            slideSizeText: this.slideSizeText,
            addInputBox: this.addInputBox,
            uploadMediaClick: this.uploadMediaClick,
            uploadVideoClick: this.uploadVideoClick,
            tableClick: this.tableClick,
            mathsClick: this.mathsClick,
            codeClick: this.codeClick,
            removeBackgroundClick: this.removeBackgroundClick,
            embedClick: this.embedClick,
            embedURL: this.embedURL,
            embedCode: this.embedCode,
            embedWidth: this.embedWidth,
            embedHeight: this.embedHeight,
            HTMLEditorClick: this.HTMLEditorClick
        };
    }
    dehydrate() {
        return this.getState();
    }
    rehydrate(state) {
        this.id = state.id;
        this.slideId = state.slideId;
        this.title = state.title;
        this.LeftPanelTitleChange = state.LeftPanelTitleChange;
        this.content = state.content;
        this.markdown = state.markdown;
        this.speakernotes = state.speakernotes;
        this.scaleratio = state.scaleratio;
        this.saveSlideClick = state.saveSlideClick;
        this.cancelClick = state.cancelClick;
        this.selector = state.selector;
        this.undoClick = state.undoClick;
        this.redoClick = state.redoClick;
        this.template = state.template;
        this.slideSize = state.slideSize;
        this.slideSizeText = state.slideSizeText;
        this.addInputBox = state.addInputBox;
        this.uploadMediaClick = state.uploadMediaClick;
        this.uploadVideoClick = state.uploadVideoClick;
        this.tableClick = state.tableClick;
        this.mathsClick = state.mathsClick;
        this.codeClick = state.codeClick;
        this.removeBackgroundClick = state.removeBackgroundClick;
        this.embedClick = state.embedClick;
        this.embedURL = state.embedURL;
        this.embedCode = state.embedCode;
        this.embedWidth = state.embedWidth;
        this.embedHeight = state.embedHeight;
        this.HTMLEditorClick = state.HTMLEditorClick;
    }
}

SlideEditStore.storeName = 'SlideEditStore';
SlideEditStore.handlers = {
    'LOAD_SLIDE_EDIT_SUCCESS': 'updateContent',
    'SAVE_SLIDE_EDIT_SUCCESS': 'saveSlide',
    'ADD_SLIDE_EDIT_SUCCESS': 'addSlide',
    'SAVE_SLIDE_CLICK': 'handleSaveSlideClick',
    'CANCEL_CLICK': 'handleCancelClick',
    'CHANGE_TEMPLATE': 'changeTemplate',
    'CHANGE_SLIDE_SIZE': 'changeSlideSize',
    'CHANGE_SLIDE_SIZE_TEXT': 'changeSlideSizeText',
    'ADD_INPUT_BOX': 'handleAddInputBox',
    'UPLOAD_MEDIA_CLICK': 'handleUploadMedia',
    'UPLOAD_VIDEO_CLICK': 'handleuploadVideoClick',
    'TABLE_CLICK': 'handleTableClick',
    'MATHS_CLICK': 'handleMathsClick',
    'CODE_CLICK': 'handleCodeClick',
    'REMOVE_BACKGROUND_CLICK': 'handleRemoveBackgroundClick',
    'EMBED_CLICK': 'handleEmbedClick',
    'CHANGE_TITLE': 'changeTitle',
    'HTML_EDITOR_CLICK': 'handleHTMLEditorClick',
    'UNDO_CLICK': 'handleUndoClick',
    'REDO_CLICK': 'handleRedoClick',
};

export default SlideEditStore;
<commit_msg>Fixed a bug with not displayed resolution.<commit_after>import {BaseStore} from 'fluxible/addons';

class SlideEditStore extends BaseStore {
    constructor(dispatcher) {
        super(dispatcher);
        //this.dispatcher = dispatcher; // Provides access to waitFor and getStore methods
        this.id = '';
        this.slideId = '';
        this.title = '';
        this.LeftPanelTitleChange = false;
        this.content = '';
        this.markdown = '';
        this.speakernotes = '';
        this.scaleratio = 1; //default no scale ratio
        this.template = '';
        this.slideSize = '';
        this.slideSizeText = '';
        this.saveSlideClick = 'false';
        this.cancelClick = 'false';
        this.selector = '';
        this.undoClick = 'false';
        this.redoClick = 'false';
        this.addInputBox = 'false';
        this.uploadMediaClick = 'false';
        this.uploadVideoClick = 'false';
        this.tableClick = 'false';
        this.mathsClick = 'false';
        this.codeClick = 'false';
        this.removeBackgroundClick = 'false';
        this.embedClick = 'false';
        this.embedWidth = '';
        this.embedHeight = '';
        this.embedURL = '';
        this.embedCode = '';
        this.HTMLEditorClick = 'false';
    }
    updateContent(payload) {
        //console.log('test' + payload + payload.slide.content + ' title: ' +  payload.slide.title + ' id: ' + payload.slide.id);
        //console.log('test' + payload.slide.title + ' id: ' + payload.slide.id);
        this.id = payload.slide.id;
        this.slideId = payload.selector.sid;
        this.title = payload.slide.title || ' ';
        this.content = payload.slide.content || ' ';
        this.markdown = payload.slide.markdown || ' ';
        this.speakernotes = payload.slide.speakernotes || ' ';

        this.emitChange();
    }
    saveSlide() {
        this.emitChange();
    }
    addSlide() {
        this.emitChange();
    }
    changeTemplate(payload){
        this.template = payload.template;
        this.emitChange();
        this.template = '';
        this.emitChange();
    }
    changeSlideSize(payload){
        this.slideSize = payload.slideSize;
        this.emitChange();
        this.slideSize = '';
        this.emitChange();
    }
    changeSlideSizeText(payload){
        this.slideSizeText = payload.slideSizeText;
        this.emitChange();
    }
    handleSaveSlideClick(){
        this.saveSlideClick = 'true';
        this.emitChange();
        this.saveSlideClick = 'false';
        this.emitChange();
    }
    handleCancelClick(payload){
        this.selector = payload.selector;
        this.cancelClick = 'true';
        this.emitChange();
        this.cancelClick = 'false';
        this.emitChange();
    }
    handleUndoClick(){
        this.undoClick = 'true';
        this.emitChange();
        this.undoClick = 'false';
        this.emitChange();
    }
    handleRedoClick(){
        this.redoClick = 'true';
        this.emitChange();
        this.redoClick = 'false';
        this.emitChange();
    }
    handleAddInputBox(){
        this.addInputBox = 'true';
        this.emitChange();
        this.addInputBox = 'false';
        this.emitChange();
    }
    handleUploadMedia(){
        this.uploadMediaClick = 'true';
        this.emitChange();
        this.uploadMediaClick = 'false';
        this.emitChange();
    }
    handleuploadVideoClick(){
        this.uploadVideoClick = 'true';
        this.emitChange();
        this.uploadVideoClick = 'false';
        this.emitChange();
    }
    handleTableClick(){
        this.tableClick = 'true';
        this.emitChange();
        this.tableClick = 'false';
        this.emitChange();
    }
    handleMathsClick(){
        this.mathsClick = 'true';
        this.emitChange();
        this.mathsClick = 'false';
        this.emitChange();
    }
    handleCodeClick(){
        this.codeClick = 'true';
        this.emitChange();
        this.codeClick = 'false';
        this.emitChange();
    }
    handleRemoveBackgroundClick(){
        this.removeBackgroundClick = 'true';
        this.emitChange();
        this.removeBackgroundClick = 'false';
        this.emitChange();
    }
    handleEmbedClick(payload){
        this.embedClick = 'true';
        this.embedWidth = payload.embedWidth;
        this.embedHeight = payload.embedHeight;
        this.embedURL = payload.embedURL;
        this.embedCode = payload.embedCode;
        this.emitChange();
        this.embedClick = 'false';
        this.embedWidth = '';
        this.embedHeight = '';
        this.embedURL = '';
        this.embedCode = '';
        this.emitChange();
    }
    changeTitle(payload){
        this.title = payload.title;
        this.LeftPanelTitleChange = payload.LeftPanelTitleChange;
        this.emitChange();
        //this.title = '';
        //this.emitChange();
    }
    handleHTMLEditorClick(){
        this.HTMLEditorClick = 'true';
        this.emitChange();
        this.HTMLEditorClick = 'false';
        this.emitChange();
    }

    getState() {
        return {
            id: this.id,
            slideId: this.slideId,
            title: this.title,
            LeftPanelTitleChange: this.LeftPanelTitleChange,
            content: this.content,
            markdown: this.markdown,
            speakernotes: this.speakernotes,
            scaleratio: this.scaleratio,
            saveSlideClick: this.saveSlideClick,
            cancelClick: this.cancelClick,
            selector: this.selector,
            undoClick: this.undoClick,
            redoClick: this.redoClick,
            template: this.template,
            slideSize: this.slideSize,
            slideSizeText: this.slideSizeText,
            addInputBox: this.addInputBox,
            uploadMediaClick: this.uploadMediaClick,
            uploadVideoClick: this.uploadVideoClick,
            tableClick: this.tableClick,
            mathsClick: this.mathsClick,
            codeClick: this.codeClick,
            removeBackgroundClick: this.removeBackgroundClick,
            embedClick: this.embedClick,
            embedURL: this.embedURL,
            embedCode: this.embedCode,
            embedWidth: this.embedWidth,
            embedHeight: this.embedHeight,
            HTMLEditorClick: this.HTMLEditorClick
        };
    }
    dehydrate() {
        return this.getState();
    }
    rehydrate(state) {
        this.id = state.id;
        this.slideId = state.slideId;
        this.title = state.title;
        this.LeftPanelTitleChange = state.LeftPanelTitleChange;
        this.content = state.content;
        this.markdown = state.markdown;
        this.speakernotes = state.speakernotes;
        this.scaleratio = state.scaleratio;
        this.saveSlideClick = state.saveSlideClick;
        this.cancelClick = state.cancelClick;
        this.selector = state.selector;
        this.undoClick = state.undoClick;
        this.redoClick = state.redoClick;
        this.template = state.template;
        this.slideSize = state.slideSize;
        this.slideSizeText = state.slideSizeText;
        this.addInputBox = state.addInputBox;
        this.uploadMediaClick = state.uploadMediaClick;
        this.uploadVideoClick = state.uploadVideoClick;
        this.tableClick = state.tableClick;
        this.mathsClick = state.mathsClick;
        this.codeClick = state.codeClick;
        this.removeBackgroundClick = state.removeBackgroundClick;
        this.embedClick = state.embedClick;
        this.embedURL = state.embedURL;
        this.embedCode = state.embedCode;
        this.embedWidth = state.embedWidth;
        this.embedHeight = state.embedHeight;
        this.HTMLEditorClick = state.HTMLEditorClick;
    }
}

SlideEditStore.storeName = 'SlideEditStore';
SlideEditStore.handlers = {
    'LOAD_SLIDE_EDIT_SUCCESS': 'updateContent',
    'SAVE_SLIDE_EDIT_SUCCESS': 'saveSlide',
    'ADD_SLIDE_EDIT_SUCCESS': 'addSlide',
    'SAVE_SLIDE_CLICK': 'handleSaveSlideClick',
    'CANCEL_CLICK': 'handleCancelClick',
    'CHANGE_TEMPLATE': 'changeTemplate',
    'CHANGE_SLIDE_SIZE': 'changeSlideSize',
    'CHANGE_SLIDE_SIZE_TEXT': 'changeSlideSizeText',
    'ADD_INPUT_BOX': 'handleAddInputBox',
    'UPLOAD_MEDIA_CLICK': 'handleUploadMedia',
    'UPLOAD_VIDEO_CLICK': 'handleuploadVideoClick',
    'TABLE_CLICK': 'handleTableClick',
    'MATHS_CLICK': 'handleMathsClick',
    'CODE_CLICK': 'handleCodeClick',
    'REMOVE_BACKGROUND_CLICK': 'handleRemoveBackgroundClick',
    'EMBED_CLICK': 'handleEmbedClick',
    'CHANGE_TITLE': 'changeTitle',
    'HTML_EDITOR_CLICK': 'handleHTMLEditorClick',
    'UNDO_CLICK': 'handleUndoClick',
    'REDO_CLICK': 'handleRedoClick',
};

export default SlideEditStore;
<|endoftext|>


<commit_before>import React from 'react';
import Helmet from 'react-helmet';
import { connect } from 'react-redux';
import { withRouter } from 'react-router';
import { isEqual } from 'lodash/lang';
import citySuggestionFormatter from 'helpers/citySuggestionFormatter';
import getPetitionsPageTitle from 'helpers/getPetitionsPageTitle';
import { petitionsPath } from 'helpers/petitionUrls';
import {
  fetchPetitions,
  fetchAll,
  updateCurrentCity
} from 'actions/PetitionsActions';
import settings from 'settings';
import Petitions from 'components/Petitions';
import getPetitions from 'selectors/petitions';

const PetitionsContainer = withRouter(React.createClass({
  componentWillMount () {
    // If there are no petitions, or deep compare filter params;
    // if they have changed then we fetch petitions client-side
    if (!this.props.petitions.length ||
      !isEqual(this.props.params, this.props.routeParams)) {
      this.props.fetchPetitions(this.props);
    }

    // Fetch the city to popular autocomplete
    this.props.fetchCity(this.props);
  },

  componentWillReceiveProps (nextProps) {
    // Deep compare filter params, if they have changes
    // then we fetch petitions again client-side
    if (!isEqual(this.props.params, nextProps.params)) {
      this.props.fetchPetitions(nextProps);

      // If no city given in new props
      if (!nextProps.params.cityName) {
        // Force clear autocomplete
        this.props.updateCurrentCity({});
      }
    }
  },

  getAutocompleteProps: ({ router, updateCurrentCity, currentCity }) => ({
    name: 'city-filter',
    endpoint: 'cities',
    suggestionFormatter: citySuggestionFormatter,
    getFormValue: (suggestion) => suggestion,
    suggestionsLimit: 4,
    helper: {
      value: { data: currentCity },
      onChange (newValue) {
        updateCurrentCity(newValue);

        router.push(petitionsPath({
          city: (newValue.id ? newValue : '')
        }));
      },
      onBlur () {}
    },
    html: { placeholder: settings.petitionsPage.filters.city.placeholder }
  }),

  render () {
    return (

        <Helmet title={this.props.title} />
        <Petitions
          {...this.props}
          autocompleteProps={this.getAutocompleteProps(this.props)}
        />

    );
  }
}));

PetitionsContainer.fetchData = ({ store, location, params }) => {
  return store.dispatch(fetchAll(location, params));
};

PetitionsContainer.propTypes = {
  petitions: React.PropTypes.array,
  total: React.PropTypes.number,
  isLoading: React.PropTypes.bool,
  title: React.PropTypes.string,
  currentCity: React.PropTypes.object,
  fetchPetitions: React.PropTypes.func
};

export const mapStateToProps = ({ petitions }) => ({
  petitions: getPetitions(petitions.data || []),
  isLoading: petitions.isLoading,
  title: getPetitionsPageTitle(petitions.currentCity),
  currentCity: petitions.currentCity
});

export const mapDispatchToProps = (dispatch) => ({
  fetchPetitions: (options) => dispatch(fetchPetitions(options)),
  updateCurrentCity: (newValue) => dispatch(updateCurrentCity(newValue))
});

export default connect(
  mapStateToProps,
  mapDispatchToProps
)(PetitionsContainer);
<commit_msg>Whitespace<commit_after>import React from 'react';
import Helmet from 'react-helmet';
import { connect } from 'react-redux';
import { withRouter } from 'react-router';
import { isEqual } from 'lodash/lang';
import citySuggestionFormatter from 'helpers/citySuggestionFormatter';
import getPetitionsPageTitle from 'helpers/getPetitionsPageTitle';
import { petitionsPath } from 'helpers/petitionUrls';
import {
  fetchPetitions,
  fetchAll,
  updateCurrentCity
} from 'actions/PetitionsActions';
import settings from 'settings';
import Petitions from 'components/Petitions';
import getPetitions from 'selectors/petitions';

const PetitionsContainer = withRouter(React.createClass({
  componentWillMount () {
    // If there are no petitions, or deep compare filter params;
    // if they have changed then we fetch petitions client-side
    if (!this.props.petitions.length ||
      !isEqual(this.props.params, this.props.routeParams)) {
      this.props.fetchPetitions(this.props);
    }

    // Fetch the city to populate autocomplete
    this.props.fetchCity(this.props);
  },

  componentWillReceiveProps (nextProps) {
    // Deep compare filter params, if they have changes
    // then we fetch petitions again client-side
    if (!isEqual(this.props.params, nextProps.params)) {
      this.props.fetchPetitions(nextProps);

      // If no city given in new props
      if (!nextProps.params.cityName) {
        // Force clear autocomplete
        this.props.updateCurrentCity({});
      }
    }
  },

  getAutocompleteProps: ({ router, updateCurrentCity, currentCity }) => ({
    name: 'city-filter',
    endpoint: 'cities',
    suggestionFormatter: citySuggestionFormatter,
    getFormValue: (suggestion) => suggestion,
    suggestionsLimit: 4,
    helper: {
      value: { data: currentCity },
      onChange (newValue) {
        updateCurrentCity(newValue);

        router.push(petitionsPath({
          city: (newValue.id ? newValue : '')
        }));
      },
      onBlur () {}
    },
    html: { placeholder: settings.petitionsPage.filters.city.placeholder }
  }),

  render () {
    return (

        <Helmet title={this.props.title} />
        <Petitions
          {...this.props}
          autocompleteProps={this.getAutocompleteProps(this.props)}
        />

    );
  }
}));

PetitionsContainer.fetchData = ({ store, location, params }) => {
  return store.dispatch(fetchAll(location, params));
};

PetitionsContainer.propTypes = {
  petitions: React.PropTypes.array,
  total: React.PropTypes.number,
  isLoading: React.PropTypes.bool,
  title: React.PropTypes.string,
  currentCity: React.PropTypes.object,
  fetchPetitions: React.PropTypes.func
};

export const mapStateToProps = ({ petitions }) => ({
  petitions: getPetitions(petitions.data || []),
  isLoading: petitions.isLoading,
  title: getPetitionsPageTitle(petitions.currentCity),
  currentCity: petitions.currentCity
});

export const mapDispatchToProps = (dispatch) => ({
  fetchPetitions: (options) => dispatch(fetchPetitions(options)),
  updateCurrentCity: (newValue) => dispatch(updateCurrentCity(newValue))
});

export default connect(
  mapStateToProps,
  mapDispatchToProps
)(PetitionsContainer);
<|endoftext|>


<commit_before>const webpack = require("webpack");
const OfflinePlugin = require("offline-plugin");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const CleanWebpackPlugin = require("clean-webpack-plugin");
const CopyWebpackPlugin = require("copy-webpack-plugin");
const path = require("path");

module.exports = (env, argv) => ({
  entry: {
    main: ["./src/main.tsx", "./src/global.scss"],
  },
  output: {
    filename: "[name].[chunkhash].js",
    path: __dirname + "/dist",
    publicPath: "/",
  },
  resolve: {
    extensions: [".ts", ".tsx", ".js"],
    alias: {
      style: path.resolve(__dirname, "src/style"),
    },
  },
  plugins: [
    new webpack.DefinePlugin({
      __BUILD_DATE__: JSON.stringify(Date.now()),
      __MODE__: JSON.stringify(argv.mode),
    }),
    new OfflinePlugin({
      caches: {
        main: [":rest:"],
      },
      ServiceWorker: {
        output: "sw.js",
        publicPath: "/sw.js",
        cacheName: "anontown",
        minify: true,
      },
    }),
    new HtmlWebpackPlugin({
      inject: true,
      template: "index.html",
      filename: ".index.template.html",
    }),
    new CopyWebpackPlugin([
      {
        from: "public",
        to: "",
      },
      {
        from: path.join(
          path.dirname(require.resolve("@anontown/client-icon/package.json")),
          "dist",
        ),
        to: "",
      },
    ]),
    new CleanWebpackPlugin({ cleanStaleWebpackAssets: false }),
  ],
  module: {
    rules: [
      {
        test: /\.(graphql|gql)$/,
        exclude: /node_modules/,
        loader: "graphql-tag/loader",
      },
      {
        test: /\.tsx?$/,
        loader: "ts-loader",
      },
      {
        test: /\.html?$/,
        loader: "html-loader",
      },
      {
        test: /\.s?css$/,
        use: [
          {
            loader: "style-loader",
          },
          {
            loader: "css-loader?modules",
          },
          {
            loader: "sass-loader",
          },
        ],
      },
    ],
  },
  devtool: "source-map",
  optimization: {
    splitChunks: {
      name: "vendor",
      chunks: "initial",
    },
  },
});
<commit_msg>modeがdevelopmentでないときソースマップを生成しないようにした<commit_after>const webpack = require("webpack");
const OfflinePlugin = require("offline-plugin");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const CleanWebpackPlugin = require("clean-webpack-plugin");
const CopyWebpackPlugin = require("copy-webpack-plugin");
const path = require("path");

module.exports = (env, argv) => ({
  entry: {
    main: ["./src/main.tsx", "./src/global.scss"],
  },
  output: {
    filename: "[name].[chunkhash].js",
    path: __dirname + "/dist",
    publicPath: "/",
  },
  resolve: {
    extensions: [".ts", ".tsx", ".js"],
    alias: {
      style: path.resolve(__dirname, "src/style"),
    },
  },
  plugins: [
    new webpack.DefinePlugin({
      __BUILD_DATE__: JSON.stringify(Date.now()),
      __MODE__: JSON.stringify(argv.mode),
    }),
    new OfflinePlugin({
      caches: {
        main: [":rest:"],
      },
      ServiceWorker: {
        output: "sw.js",
        publicPath: "/sw.js",
        cacheName: "anontown",
        minify: true,
      },
    }),
    new HtmlWebpackPlugin({
      inject: true,
      template: "index.html",
      filename: ".index.template.html",
    }),
    new CopyWebpackPlugin([
      {
        from: "public",
        to: "",
      },
      {
        from: path.join(
          path.dirname(require.resolve("@anontown/client-icon/package.json")),
          "dist",
        ),
        to: "",
      },
    ]),
    new CleanWebpackPlugin({ cleanStaleWebpackAssets: false }),
  ],
  module: {
    rules: [
      {
        test: /\.(graphql|gql)$/,
        exclude: /node_modules/,
        loader: "graphql-tag/loader",
      },
      {
        test: /\.tsx?$/,
        loader: "ts-loader",
      },
      {
        test: /\.html?$/,
        loader: "html-loader",
      },
      {
        test: /\.s?css$/,
        use: [
          {
            loader: "style-loader",
          },
          {
            loader: "css-loader?modules",
          },
          {
            loader: "sass-loader",
          },
        ],
      },
    ],
  },
  devtool: argv.mode === "development" ? "source-map" : false,
  optimization: {
    splitChunks: {
      name: "vendor",
      chunks: "initial",
    },
  },
});
<|endoftext|>


<commit_before>'use strict';

/**
 * An oriented bounding box calculated from three points.
 */
function Formation( x0, y0, x1, y1, x2, y2 ) {
  this.x = x0;
  this.y = y0;

  // First edge (width).
  var dx = x1 - x0,
      dy = y1 - y0;

  this.angle = Math.atan2( -dy, dx );
  this.width = Math.sqrt( dx * dx + dy * dy );

  // Second edge (height).
  var point = this.toLocal( x2, y2 );
  this.height = point.y;

  Object.freeze( this );
}

Formation.prototype.applyTransform = function( ctx ) {
  ctx.translate( this.x, this.y );
  ctx.rotate( -this.angle );
};

Formation.prototype.draw = function( ctx ) {
  ctx.save();

  this.applyTransform( ctx );
  ctx.rect( 0, 0, this.width, this.height );

  ctx.restore();
};

Formation.prototype.toWorld = function( x, y ) {
  var cos, sin;
  var rx, ry;

  if ( this.angle ) {
    cos = Math.cos( -this.angle );
    sin = Math.sin( -this.angle );

    rx = cos * x - sin * y;
    ry = sin * x + cos * y;

    x = rx;
    y = ry;
  }

  return {
    x: x + this.x,
    y: y + this.y
  };
};

Formation.prototype.toLocal = function( x, y ) {
  x -= this.x;
  y -= this.y;

  var cos, sin;
  var rx, ry;

  if ( this.angle ) {
    cos = Math.cos( this.angle );
    sin = Math.sin( this.angle );

    rx = cos * x - sin * y;
    ry = sin * x + cos * y;

    x = rx;
    y = ry;
  }

  return {
    x: x,
    y: y
  };
};

Formation.prototype.getPositions = function( count, rankSpacing, fileSpacing ) {
  var xCount = Math.ceil( this.width / rankSpacing );

  // Flip fileSpacing if height is negative.
  fileSpacing *= this.height < 0 ? -1 : 1;

  var positions = [];
  var i = 0;
  while ( i < count ) {
    positions.push({
      x: ( i % xCount ) * rankSpacing,
      y: Math.floor( i / xCount ) * fileSpacing
    });

    i++;
  }

  return positions;
};

/**
 * Unlike getPositions() which takes a predetermined unit count,
 * getPositionsFilled() fills the entire formation box with units
 * separated by the given spacing parameters.
 */
Formation.prototype.getPositionsFilled = function( rankSpacing, fileSpacing ) {
  // Return empty array if zero-spacing (results in infinite unit count).
  if ( !rankSpacing || !fileSpacing ) {
    return [];
  }

  // Absolute value allow for positive yCounts if height is negative.
  var xCount = Math.ceil( this.width / rankSpacing ),
      yCount = Math.ceil( Math.abs( this.height ) / fileSpacing );

  return this.getPositions( xCount * yCount, rankSpacing, fileSpacing );
};
<commit_msg>strategy[maneuvers]: Add getters for Formation x1, y1, x2, and y2 coordinates.<commit_after>'use strict';

/**
 * An oriented bounding box calculated from three points.
 */
function Formation( x0, y0, x1, y1, x2, y2 ) {
  this.x = x0;
  this.y = y0;

  // First edge (width).
  var dx = x1 - x0,
      dy = y1 - y0;

  this.angle = Math.atan2( -dy, dx );
  this.width = Math.sqrt( dx * dx + dy * dy );

  // Second edge (height).
  var point = this.toLocal( x2, y2 );
  this.height = point.y;

  Object.freeze( this );
}

Formation.prototype.applyTransform = function( ctx ) {
  ctx.translate( this.x, this.y );
  ctx.rotate( -this.angle );
};

Formation.prototype.draw = function( ctx ) {
  ctx.save();

  this.applyTransform( ctx );
  ctx.rect( 0, 0, this.width, this.height );

  ctx.restore();
};

Formation.prototype.toWorld = function( x, y ) {
  var cos, sin;
  var rx, ry;

  if ( this.angle ) {
    cos = Math.cos( -this.angle );
    sin = Math.sin( -this.angle );

    rx = cos * x - sin * y;
    ry = sin * x + cos * y;

    x = rx;
    y = ry;
  }

  return {
    x: x + this.x,
    y: y + this.y
  };
};

Formation.prototype.toLocal = function( x, y ) {
  x -= this.x;
  y -= this.y;

  var cos, sin;
  var rx, ry;

  if ( this.angle ) {
    cos = Math.cos( this.angle );
    sin = Math.sin( this.angle );

    rx = cos * x - sin * y;
    ry = sin * x + cos * y;

    x = rx;
    y = ry;
  }

  return {
    x: x,
    y: y
  };
};

Formation.prototype.getPositions = function( count, rankSpacing, fileSpacing ) {
  var xCount = Math.ceil( this.width / rankSpacing );

  // Flip fileSpacing if height is negative.
  fileSpacing *= this.height < 0 ? -1 : 1;

  var positions = [];
  var i = 0;
  while ( i < count ) {
    positions.push({
      x: ( i % xCount ) * rankSpacing,
      y: Math.floor( i / xCount ) * fileSpacing
    });

    i++;
  }

  return positions;
};

/**
 * Unlike getPositions() which takes a predetermined unit count,
 * getPositionsFilled() fills the entire formation box with units
 * separated by the given spacing parameters.
 */
Formation.prototype.getPositionsFilled = function( rankSpacing, fileSpacing ) {
  // Return empty array if zero-spacing (results in infinite unit count).
  if ( !rankSpacing || !fileSpacing ) {
    return [];
  }

  // Absolute value allow for positive yCounts if height is negative.
  var xCount = Math.ceil( this.width / rankSpacing ),
      yCount = Math.ceil( Math.abs( this.height ) / fileSpacing );

  return this.getPositions( xCount * yCount, rankSpacing, fileSpacing );
};

// World space coordinate getters.
Object.defineProperty( Formation.prototype, 'x1', {
  get: function() {
    return this.toWorld( this.width, 0 ).x;
  }
});

Object.defineProperty( Formation.prototype, 'y1', {
  get: function() {
    return this.toWorld( this.width, 0 ).y;
  }
});

Object.defineProperty( Formation.prototype, 'x2', {
  get: function() {
    return this.toWorld( this.width, this.height ).x;
  }
});

Object.defineProperty( Formation.prototype, 'y2', {
  get: function() {
    return this.toWorld( this.width, this.height ).y;
  }
});
<|endoftext|>


<commit_before>/* @noflow */

import toFastProperties from "to-fast-properties";
import compact from "lodash/compact";
import loClone from "lodash/clone";
import each from "lodash/each";
import uniq from "lodash/uniq";

let t = exports;

/**
 * Registers `is[Type]` and `assert[Type]` generated functions for a given `type`.
 * Pass `skipAliasCheck` to force it to directly compare `node.type` with `type`.
 */

function registerType(type: string) {
  let is = t[`is${type}`] = function (node, opts) {
    return t.is(type, node, opts);
  };

  t[`assert${type}`] = function (node, opts) {
    opts = opts || {};
    if (!is(node, opts)) {
      throw new Error(`Expected type ${JSON.stringify(type)} with option ${JSON.stringify(opts)}`);
    }
  };
}

//

export * from "./constants";

import "./definitions/init";
import { VISITOR_KEYS, ALIAS_KEYS, NODE_FIELDS, BUILDER_KEYS, DEPRECATED_KEYS } from "./definitions";
export { VISITOR_KEYS, ALIAS_KEYS, NODE_FIELDS, BUILDER_KEYS, DEPRECATED_KEYS };

import * as _react from "./react";
export { _react as react };

/**
 * Registers `is[Type]` and `assert[Type]` for all types.
 */

for (let type in t.VISITOR_KEYS) {
  registerType(type);
}

/**
 * Flip `ALIAS_KEYS` for faster access in the reverse direction.
 */

t.FLIPPED_ALIAS_KEYS = {};

function addAlias(type, alias) {
  let types = t.FLIPPED_ALIAS_KEYS[alias] = t.FLIPPED_ALIAS_KEYS[alias] || [];
  types.push(type);
}

function registerAlias(type, alias) {
  const isNew = !t.FLIPPED_ALIAS_KEYS[alias];
  addAlias(type, alias);
  if (isNew) _registerAlias(t.FLIPPED_ALIAS_KEYS[alias], alias);
  TYPES.push(alias);
}

each(t.ALIAS_KEYS, function (aliases, type) {
  each(aliases, function(alias) { addAlias(type, alias) });
});

/**
 * Registers `is[Alias]` and `assert[Alias]` functions for all aliases.
 */

function _registerAlias(types, type) {
  t[type.toUpperCase() + "_TYPES"] = types;
  registerType(type);
}
each(t.FLIPPED_ALIAS_KEYS, _registerAlias);

export const TYPES = Object.keys(t.VISITOR_KEYS)
  .concat(Object.keys(t.FLIPPED_ALIAS_KEYS))
  .concat(Object.keys(t.DEPRECATED_KEYS));

import _defineType, {
  assertEach,
  assertOneOf,
  assertNodeType,
  assertNodeOrValueType,
  assertValueType,
  chain
} from "./definitions";

/**
 * Allows for plugins to add custom types.
 * TODO: lots of checks to make sure this doesn't go crazy
 * TODO: move data to an instance rather than at the root level
 *       OR, add namespacing
 */

export function defineType(type, opts) {
  _defineType(type, opts);

  TYPES.push(type);

  registerType(type);

  createBuilder(opts.builder, type);

  each(type.aliases || [], function (alias) {
    registerAlias(type, alias);
  });
}
defineType.assertEach = assertEach;
defineType.assertOneOf = assertOneOf;
defineType.assertNodeType = assertNodeType;
defineType.assertNodeOrValueType = assertNodeOrValueType;
defineType.assertValueType = assertValueType;
defineType.chain = chain;

/**
 * Returns whether `node` is of given `type`.
 *
 * For better performance, use this instead of `is[Type]` when `type` is unknown.
 * Optionally, pass `skipAliasCheck` to directly compare `node.type` with `type`.
 */

export function is(type: string, node: Object, opts?: Object): boolean {
  if (!node) return false;

  let matches = isType(node.type, type);
  if (!matches) return false;

  if (typeof opts === "undefined") {
    return true;
  } else {
    return t.shallowEqual(node, opts);
  }
}

/**
 * Test if a `nodeType` is a `targetType` or if `targetType` is an alias of `nodeType`.
 */

export function isType(nodeType: string, targetType: string): boolean {
  if (nodeType === targetType) return true;

  let aliases: ?Array<string> = t.FLIPPED_ALIAS_KEYS[targetType];
  if (aliases) {
    if (aliases[0] === nodeType) return true;

    for (let alias of aliases) {
      if (nodeType === alias) return true;
    }
  }

  return false;
}

/**
 * Description
 */

function createBuilder (keys, type) {
  function builder() {
    if (arguments.length > keys.length) {
      throw new Error(`t.${type}: Too many arguments passed. Received ${arguments.length} but can receive no more than ${keys.length}`);
    }

    let node = {};
    node.type = type;

    let i = 0;

    for (let key of (keys: Array<string>)) {
      let field = t.NODE_FIELDS[type][key];

      let arg = arguments[i++];
      if (arg === undefined) arg = loClone(field.default);

      node[key] = arg;
    }

    for (let key in node) {
      validate(node, key, node[key]);
    }

    return node;
  }

  t[type] = builder;
  t[type[0].toLowerCase() + type.slice(1)] = builder;
}

each(t.BUILDER_KEYS, createBuilder);

/**
 * Proxy deprecated node types to updated names
 */

  function proxy(fn, type, newType) {
    return function () {
      console.trace(`The node type ${type} has been renamed to ${newType}`);
      return fn.apply(this, arguments);
    };
  }

  for (let type in t.DEPRECATED_KEYS) {
    let newType = t.DEPRECATED_KEYS[type];

    t[type] = t[type[0].toLowerCase() + type.slice(1)] = proxy(t[newType]);
    t[`is${type}`] = proxy(t[`is${newType}`], type, newType);
    t[`assert${type}`] = proxy(t[`assert${newType}`], type, newType);
  }

/**
 * Description
 */

export function validate(node?: Object, key: string, val: any) {
  if (!node) return;

  let fields = t.NODE_FIELDS[node.type];
  if (!fields) return;

  let field = fields[key];
  if (!field || !field.validate) return;
  if (field.optional && val == null) return;

  field.validate(node, key, val);
}

/**
 * Test if an object is shallowly equal.
 */

export function shallowEqual(actual: Object, expected: Object): boolean {
  let keys = Object.keys(expected);

  for (let key of (keys: Array<string>)) {
    if (actual[key] !== expected[key]) {
      return false;
    }
  }

  return true;
}

/**
 * Append a node to a member expression.
 */

export function appendToMemberExpression(member: Object, append: Object, computed?: boolean): Object {
  member.object   = t.memberExpression(member.object, member.property, member.computed);
  member.property = append;
  member.computed = !!computed;
  return member;
}

/**
 * Prepend a node to a member expression.
 */

export function prependToMemberExpression(member: Object, prepend: Object): Object {
  member.object = t.memberExpression(prepend, member.object);
  return member;
}

/**
 * Ensure the `key` (defaults to "body") of a `node` is a block.
 * Casting it to a block if it is not.
 */

export function ensureBlock(node: Object, key: string = "body"): Object {
  return node[key] = t.toBlock(node[key], node);
}

/**
 * Create a shallow clone of a `node` excluding `_private` properties.
 */

export function clone(node: Object): Object {
  let newNode = {};
  for (let key in node) {
    if (key[0] === "_") continue;
    newNode[key] = node[key];
  }
  return newNode;
}

/**
 * Create a shallow clone of a `node` excluding `_private` and location properties.
 */

export function cloneWithoutLoc(node: Object): Object {
  let newNode = clone(node);
  delete newNode.loc;
  return newNode;
}

/**
 * Create a deep clone of a `node` and all of it's child nodes
 * exluding `_private` properties.
 */

export function cloneDeep(node: Object): Object {
  let newNode = {};

  for (let key in node) {
    if (key[0] === "_") continue;

    let val = node[key];

    if (val) {
      if (val.type) {
        val = t.cloneDeep(val);
      } else if (Array.isArray(val)) {
        val = val.map(t.cloneDeep);
      }
    }

    newNode[key] = val;
  }

  return newNode;
}

/**
 * Build a function that when called will return whether or not the
 * input `node` `MemberExpression` matches the input `match`.
 *
 * For example, given the match `React.createClass` it would match the
 * parsed nodes of `React.createClass` and `React["createClass"]`.
 */

export function buildMatchMemberExpression(match:string, allowPartial?: boolean): Function {
  let parts = match.split(".");

  return function (member) {
    // not a member expression
    if (!t.isMemberExpression(member)) return false;

    let search = [member];
    let i = 0;

    while (search.length) {
      let node = search.shift();

      if (allowPartial && i === parts.length) {
        return true;
      }

      if (t.isIdentifier(node)) {
        // this part doesn't match
        if (parts[i] !== node.name) return false;
      } else if (t.isStringLiteral(node)) {
        // this part doesn't match
        if (parts[i] !== node.value) return false;
      } else if (t.isMemberExpression(node)) {
        if (node.computed && !t.isStringLiteral(node.property)) {
          // we can't deal with this
          return false;
        } else {
          search.push(node.object);
          search.push(node.property);
          continue;
        }
      } else {
        // we can't deal with this
        return false;
      }

      // too many parts
      if (++i > parts.length) {
        return false;
      }
    }

    return true;
  };
}

/**
 * Remove comment properties from a node.
 */

export function removeComments(node: Object): Object {
  for (let key of t.COMMENT_KEYS) {
    delete node[key];
  }
  return node;
}

/**
 * Inherit all unique comments from `parent` node to `child` node.
 */

export function inheritsComments(child: Object, parent: Object): Object {
  inheritTrailingComments(child, parent);
  inheritLeadingComments(child, parent);
  inheritInnerComments(child, parent);
  return child;
}

export function inheritTrailingComments(child: Object, parent: Object) {
  _inheritComments("trailingComments", child, parent);
}

export function inheritLeadingComments(child: Object, parent: Object) {
  _inheritComments("leadingComments", child, parent);
}

export function inheritInnerComments(child: Object, parent: Object) {
  _inheritComments("innerComments", child, parent);
}

function _inheritComments(key, child, parent) {
  if (child && parent) {
    child[key] = uniq(compact([].concat(child[key], parent[key])));
  }
}

/**
 * Inherit all contextual properties from `parent` node to `child` node.
 */

export function inherits(child: Object, parent: Object): Object {
  if (!child || !parent) return child;

  // optionally inherit specific properties if not null
  for (let key of (t.INHERIT_KEYS.optional: Array<string>)) {
    if (child[key] == null) {
      child[key] = parent[key];
    }
  }

  // force inherit "private" properties
  for (let key in parent) {
    if (key[0] === "_") child[key] = parent[key];
  }

  // force inherit select properties
  for (let key of (t.INHERIT_KEYS.force: Array<string>)) {
    child[key] = parent[key];
  }

  t.inheritsComments(child, parent);

  return child;
}

/**
 * TODO
 */

export function assertNode(node?) {
  if (!isNode(node)) {
    throw new TypeError("Not a valid node " + (node && node.type));
  }
}

/**
 * TODO
 */

export function isNode(node?): boolean {
  return !!(node && VISITOR_KEYS[node.type]);
}

// Optimize property access.
toFastProperties(t);
toFastProperties(t.VISITOR_KEYS);

//
export * from "./retrievers";
export * from "./validators";
export * from "./converters";
export * from "./flow";
<commit_msg>fix(comal-types): properly register aliases of defined types<commit_after>/* @noflow */

import toFastProperties from "to-fast-properties";
import compact from "lodash/compact";
import loClone from "lodash/clone";
import each from "lodash/each";
import uniq from "lodash/uniq";

let t = exports;

/**
 * Registers `is[Type]` and `assert[Type]` generated functions for a given `type`.
 * Pass `skipAliasCheck` to force it to directly compare `node.type` with `type`.
 */

function registerType(type: string) {
  let is = t[`is${type}`] = function (node, opts) {
    return t.is(type, node, opts);
  };

  t[`assert${type}`] = function (node, opts) {
    opts = opts || {};
    if (!is(node, opts)) {
      throw new Error(`Expected type ${JSON.stringify(type)} with option ${JSON.stringify(opts)}`);
    }
  };
}

//

export * from "./constants";

import "./definitions/init";
import { VISITOR_KEYS, ALIAS_KEYS, NODE_FIELDS, BUILDER_KEYS, DEPRECATED_KEYS } from "./definitions";
export { VISITOR_KEYS, ALIAS_KEYS, NODE_FIELDS, BUILDER_KEYS, DEPRECATED_KEYS };

import * as _react from "./react";
export { _react as react };

/**
 * Registers `is[Type]` and `assert[Type]` for all types.
 */

for (let type in t.VISITOR_KEYS) {
  registerType(type);
}

/**
 * Flip `ALIAS_KEYS` for faster access in the reverse direction.
 */

t.FLIPPED_ALIAS_KEYS = {};

function addAlias(type, alias) {
  let types = t.FLIPPED_ALIAS_KEYS[alias] = t.FLIPPED_ALIAS_KEYS[alias] || [];
  types.push(type);
}

function registerAlias(type, alias) {
  const isNew = !t.FLIPPED_ALIAS_KEYS[alias];
  addAlias(type, alias);
  if (isNew) _registerAlias(t.FLIPPED_ALIAS_KEYS[alias], alias);
  TYPES.push(alias);
}

each(t.ALIAS_KEYS, function (aliases, type) {
  each(aliases, function(alias) { addAlias(type, alias) });
});

/**
 * Registers `is[Alias]` and `assert[Alias]` functions for all aliases.
 */

function _registerAlias(types, type) {
  t[type.toUpperCase() + "_TYPES"] = types;
  registerType(type);
}
each(t.FLIPPED_ALIAS_KEYS, _registerAlias);

export const TYPES = Object.keys(t.VISITOR_KEYS)
  .concat(Object.keys(t.FLIPPED_ALIAS_KEYS))
  .concat(Object.keys(t.DEPRECATED_KEYS));

import _defineType, {
  assertEach,
  assertOneOf,
  assertNodeType,
  assertNodeOrValueType,
  assertValueType,
  chain
} from "./definitions";

/**
 * Allows for plugins to add custom types.
 * TODO: lots of checks to make sure this doesn't go crazy
 * TODO: move data to an instance rather than at the root level
 *       OR, add namespacing
 */

export function defineType(type, opts) {
  _defineType(type, opts);

  TYPES.push(type);

  registerType(type);

  createBuilder(opts.builder, type);

  each(opts.aliases || [], function (alias) {
    registerAlias(type, alias);
  });
}
defineType.assertEach = assertEach;
defineType.assertOneOf = assertOneOf;
defineType.assertNodeType = assertNodeType;
defineType.assertNodeOrValueType = assertNodeOrValueType;
defineType.assertValueType = assertValueType;
defineType.chain = chain;

/**
 * Returns whether `node` is of given `type`.
 *
 * For better performance, use this instead of `is[Type]` when `type` is unknown.
 * Optionally, pass `skipAliasCheck` to directly compare `node.type` with `type`.
 */

export function is(type: string, node: Object, opts?: Object): boolean {
  if (!node) return false;

  let matches = isType(node.type, type);
  if (!matches) return false;

  if (typeof opts === "undefined") {
    return true;
  } else {
    return t.shallowEqual(node, opts);
  }
}

/**
 * Test if a `nodeType` is a `targetType` or if `targetType` is an alias of `nodeType`.
 */

export function isType(nodeType: string, targetType: string): boolean {
  if (nodeType === targetType) return true;

  let aliases: ?Array<string> = t.FLIPPED_ALIAS_KEYS[targetType];
  if (aliases) {
    if (aliases[0] === nodeType) return true;

    for (let alias of aliases) {
      if (nodeType === alias) return true;
    }
  }

  return false;
}

/**
 * Description
 */

function createBuilder (keys, type) {
  function builder() {
    if (arguments.length > keys.length) {
      throw new Error(`t.${type}: Too many arguments passed. Received ${arguments.length} but can receive no more than ${keys.length}`);
    }

    let node = {};
    node.type = type;

    let i = 0;

    for (let key of (keys: Array<string>)) {
      let field = t.NODE_FIELDS[type][key];

      let arg = arguments[i++];
      if (arg === undefined) arg = loClone(field.default);

      node[key] = arg;
    }

    for (let key in node) {
      validate(node, key, node[key]);
    }

    return node;
  }

  t[type] = builder;
  t[type[0].toLowerCase() + type.slice(1)] = builder;
}

each(t.BUILDER_KEYS, createBuilder);

/**
 * Proxy deprecated node types to updated names
 */

  function proxy(fn, type, newType) {
    return function () {
      console.trace(`The node type ${type} has been renamed to ${newType}`);
      return fn.apply(this, arguments);
    };
  }

  for (let type in t.DEPRECATED_KEYS) {
    let newType = t.DEPRECATED_KEYS[type];

    t[type] = t[type[0].toLowerCase() + type.slice(1)] = proxy(t[newType]);
    t[`is${type}`] = proxy(t[`is${newType}`], type, newType);
    t[`assert${type}`] = proxy(t[`assert${newType}`], type, newType);
  }

/**
 * Description
 */

export function validate(node?: Object, key: string, val: any) {
  if (!node) return;

  let fields = t.NODE_FIELDS[node.type];
  if (!fields) return;

  let field = fields[key];
  if (!field || !field.validate) return;
  if (field.optional && val == null) return;

  field.validate(node, key, val);
}

/**
 * Test if an object is shallowly equal.
 */

export function shallowEqual(actual: Object, expected: Object): boolean {
  let keys = Object.keys(expected);

  for (let key of (keys: Array<string>)) {
    if (actual[key] !== expected[key]) {
      return false;
    }
  }

  return true;
}

/**
 * Append a node to a member expression.
 */

export function appendToMemberExpression(member: Object, append: Object, computed?: boolean): Object {
  member.object   = t.memberExpression(member.object, member.property, member.computed);
  member.property = append;
  member.computed = !!computed;
  return member;
}

/**
 * Prepend a node to a member expression.
 */

export function prependToMemberExpression(member: Object, prepend: Object): Object {
  member.object = t.memberExpression(prepend, member.object);
  return member;
}

/**
 * Ensure the `key` (defaults to "body") of a `node` is a block.
 * Casting it to a block if it is not.
 */

export function ensureBlock(node: Object, key: string = "body"): Object {
  return node[key] = t.toBlock(node[key], node);
}

/**
 * Create a shallow clone of a `node` excluding `_private` properties.
 */

export function clone(node: Object): Object {
  let newNode = {};
  for (let key in node) {
    if (key[0] === "_") continue;
    newNode[key] = node[key];
  }
  return newNode;
}

/**
 * Create a shallow clone of a `node` excluding `_private` and location properties.
 */

export function cloneWithoutLoc(node: Object): Object {
  let newNode = clone(node);
  delete newNode.loc;
  return newNode;
}

/**
 * Create a deep clone of a `node` and all of it's child nodes
 * exluding `_private` properties.
 */

export function cloneDeep(node: Object): Object {
  let newNode = {};

  for (let key in node) {
    if (key[0] === "_") continue;

    let val = node[key];

    if (val) {
      if (val.type) {
        val = t.cloneDeep(val);
      } else if (Array.isArray(val)) {
        val = val.map(t.cloneDeep);
      }
    }

    newNode[key] = val;
  }

  return newNode;
}

/**
 * Build a function that when called will return whether or not the
 * input `node` `MemberExpression` matches the input `match`.
 *
 * For example, given the match `React.createClass` it would match the
 * parsed nodes of `React.createClass` and `React["createClass"]`.
 */

export function buildMatchMemberExpression(match:string, allowPartial?: boolean): Function {
  let parts = match.split(".");

  return function (member) {
    // not a member expression
    if (!t.isMemberExpression(member)) return false;

    let search = [member];
    let i = 0;

    while (search.length) {
      let node = search.shift();

      if (allowPartial && i === parts.length) {
        return true;
      }

      if (t.isIdentifier(node)) {
        // this part doesn't match
        if (parts[i] !== node.name) return false;
      } else if (t.isStringLiteral(node)) {
        // this part doesn't match
        if (parts[i] !== node.value) return false;
      } else if (t.isMemberExpression(node)) {
        if (node.computed && !t.isStringLiteral(node.property)) {
          // we can't deal with this
          return false;
        } else {
          search.push(node.object);
          search.push(node.property);
          continue;
        }
      } else {
        // we can't deal with this
        return false;
      }

      // too many parts
      if (++i > parts.length) {
        return false;
      }
    }

    return true;
  };
}

/**
 * Remove comment properties from a node.
 */

export function removeComments(node: Object): Object {
  for (let key of t.COMMENT_KEYS) {
    delete node[key];
  }
  return node;
}

/**
 * Inherit all unique comments from `parent` node to `child` node.
 */

export function inheritsComments(child: Object, parent: Object): Object {
  inheritTrailingComments(child, parent);
  inheritLeadingComments(child, parent);
  inheritInnerComments(child, parent);
  return child;
}

export function inheritTrailingComments(child: Object, parent: Object) {
  _inheritComments("trailingComments", child, parent);
}

export function inheritLeadingComments(child: Object, parent: Object) {
  _inheritComments("leadingComments", child, parent);
}

export function inheritInnerComments(child: Object, parent: Object) {
  _inheritComments("innerComments", child, parent);
}

function _inheritComments(key, child, parent) {
  if (child && parent) {
    child[key] = uniq(compact([].concat(child[key], parent[key])));
  }
}

/**
 * Inherit all contextual properties from `parent` node to `child` node.
 */

export function inherits(child: Object, parent: Object): Object {
  if (!child || !parent) return child;

  // optionally inherit specific properties if not null
  for (let key of (t.INHERIT_KEYS.optional: Array<string>)) {
    if (child[key] == null) {
      child[key] = parent[key];
    }
  }

  // force inherit "private" properties
  for (let key in parent) {
    if (key[0] === "_") child[key] = parent[key];
  }

  // force inherit select properties
  for (let key of (t.INHERIT_KEYS.force: Array<string>)) {
    child[key] = parent[key];
  }

  t.inheritsComments(child, parent);

  return child;
}

/**
 * TODO
 */

export function assertNode(node?) {
  if (!isNode(node)) {
    throw new TypeError("Not a valid node " + (node && node.type));
  }
}

/**
 * TODO
 */

export function isNode(node?): boolean {
  return !!(node && VISITOR_KEYS[node.type]);
}

// Optimize property access.
toFastProperties(t);
toFastProperties(t.VISITOR_KEYS);

//
export * from "./retrievers";
export * from "./validators";
export * from "./converters";
export * from "./flow";
<|endoftext|>


<commit_before>/**
 * page_capture
 * Copyright (c) 2015 Yieldbot, Inc. - All rights reserved.
 */

/* globals chrome, draggable */

'use strict';

(function() {
  var manifest = chrome.runtime.getManifest();

  /**
   *
   * @param {string} imageBase64
   * @param {number} x
   * @param {number} y
   * @param {number} width
   * @param {number} height
   * @param {number} zoomFactor
   * @param {function} cb
   * @return {undefined}
   */
  var crop = function(imageBase64, x, y, width, height, zoomFactor, cb) {
    var img = new Image();
    img.onload = function() {
      var canvas = document.createElement('canvas');
      var canvasContext = canvas.getContext('2d');

      canvas.width = width;
      canvas.height = height;

      // update the properties if the zoom level is not 100%
      if (zoomFactor !== 1) {
        x = x * zoomFactor;
        y = y * zoomFactor;
        width = width * zoomFactor;
        height = height * zoomFactor;
      }

      canvasContext.drawImage(img, x, y, width, height, 0, 0, canvas.width, canvas.height);

      cb(canvas.toDataURL('image/jpeg', 1));
    };
    img.src = imageBase64;
  };

  /**
   *
   * @param {string} selectors
   * @param {function} callback
   * @return {undefined}
   */
  var screenCaptureHandler = function(selectors, callback) {
    var target = document.querySelector(selectors);

    if (!target) {
      callback(null);
    } else {

      var offset = target.getBoundingClientRect();
      //var waitFor = 0;
      //
      //if (offset.top < 0) {
      //  target.scrollIntoView();
      //  waitFor = 200;
      //}

      //setTimeout(function() {
      //offset = target.getBoundingClientRect();
      chrome.runtime.sendMessage({api: 'screenCapture'}, function(data) {
        crop(data.img, offset.left, offset.top, offset.width, offset.height, data.zoomFactor, callback);
      });
      //}, waitFor);
    }
  };

  var createControlPanel = function(){
    var panel = document.getElementById('pc-control-panel');
    if(!panel) {
      panel = document.createElement('div');
      panel.setAttribute('id', 'pc-control-panel');
      document.body.appendChild(panel);
    }
    panel.style.position = 'fixed';
    panel.style.top = '100px';
    panel.style.right = '10px';
    panel.style.width = '100px';
    panel.style.height = '100px';
    panel.style.background = 'linear-gradient(#ccc, #aaf)';
    panel.style.border = '2px solid #02aeef';
    panel.style.zIndex = '99999999';
    panel.style.borderRadius = '50%';
    panel.style.boxShadow = '0 0 30px 0 #02aeef';
    panel.style.lineHeight = '100px';
    panel.style.textAlign = 'center';
    panel.style.cursor = 'pointer';
    panel.style.fontWeight = 'bold';
    panel.innerHTML = 'capture';
    return panel;
  };

  // listen to messages from clients using the the public api's
  window.addEventListener('message', function(event) {
    var data = event.data || {};

    if (!data.__index || !data.ns || !data.api) {
      return;
    }

    var send = function(value) {
      var opt = {
        __key: data.__index,
        value: value
      };
      window.postMessage(opt, '*');
    };

    console.log('page_capture api', data.api);

    if (data.api === 'getVersion') {
      send(manifest.version);
    }

    else if (data.api === 'captureElement') {
      screenCaptureHandler(data.element, function(data) {
        send(data);
        return true;
      });
    }

    else if (data.api === 'capturePage') {
      chrome.runtime.sendMessage({api: 'screenCapture'}, function(data) {
        send(data.img);
        return true;
      });
    }

    else if (data.api === 'captureSection') {
      chrome.runtime.sendMessage({api: 'screenCapture'}, function(responseData) {
        crop(responseData.img, data.x, data.y, data.width, data.height, responseData.zoomFactor, send);
        return true;
      });
    }

    else if (data.api === 'captureUrl') {
      chrome.runtime.sendMessage(data, function(dataUrl) {
        send(dataUrl);
        return true;
      });
    }
  });

  // listens for messages from the background script
  chrome.extension.onMessage.addListener(function (message, sender, sendResponse) {
    if (message.option === 'addControls') {
      var panel = createControlPanel();

      if(message.imgUrl){
        var img = new Image();
        img.onload = function(){
          img.style.width = img.naturalWidth + 'px';
          img.style.height = img.naturalHeight + 'px';
          draggable(img);
        };
        img.src = message.imgUrl;
      }

      var onClick = function(e) {
        e.preventDefault();
        document.getElementById('pc-control-panel').style.display = 'none';
        var info = null;
        if(message.imgUrl) {
          info = {};
          if (!message.includeOverlay) {
            img.style.display = 'none';
            info.url = location.href;
            info.overlay = img.dataset;
            info.overlay.url = message.imgUrl;
            delete info.overlay.pcType;
          }
        }
        setTimeout(function() {
          chrome.runtime.sendMessage({api: 'screenCapture'}, function(responseData) {
            if(info){
              responseData.info = info;
              sendResponse(responseData);
            } else {
              sendResponse(responseData.img);
            }
            return true;
          });
        }, 500);
      };

      var isMobile = /iPhone|iPad|iPod|Android/i.test(navigator.userAgent);
      if (isMobile) {
        panel.addEventListener('touchend', onClick, false);
      } else {
        panel.addEventListener('click', onClick, false);
      }
    }
    // all for asynchronously response
    return true;
  });

  // inject the api script in the current page document
  var apiScript = document.createElement('script');
  apiScript.src = chrome.extension.getURL('public.api.js');
  apiScript.type = 'text/javascript';
  document.body.appendChild(apiScript);

  console.log();

})();
<commit_msg>delay a little before capturing element<commit_after>/**
 * page_capture
 * Copyright (c) 2015 Yieldbot, Inc. - All rights reserved.
 */

/* globals chrome, draggable */

'use strict';

(function() {
  var manifest = chrome.runtime.getManifest();

  /**
   *
   * @param {string} imageBase64
   * @param {number} x
   * @param {number} y
   * @param {number} width
   * @param {number} height
   * @param {number} zoomFactor
   * @param {function} cb
   * @return {undefined}
   */
  var crop = function(imageBase64, x, y, width, height, zoomFactor, cb) {
    var img = new Image();
    img.onload = function() {
      var canvas = document.createElement('canvas');
      var canvasContext = canvas.getContext('2d');

      canvas.width = width;
      canvas.height = height;

      // update the properties if the zoom level is not 100%
      if (zoomFactor !== 1) {
        x = x * zoomFactor;
        y = y * zoomFactor;
        width = width * zoomFactor;
        height = height * zoomFactor;
      }

      canvasContext.drawImage(img, x, y, width, height, 0, 0, canvas.width, canvas.height);

      cb(canvas.toDataURL('image/jpeg', 1));
    };
    img.src = imageBase64;
  };

  /**
   *
   * @param {string} selectors
   * @param {function} callback
   * @return {undefined}
   */
  var screenCaptureHandler = function(selectors, callback) {
    var target = document.querySelector(selectors);

    if (!target) {
      callback(null);
    } else {
      setTimeout(function() {
        var offset = target.getBoundingClientRect();
        chrome.runtime.sendMessage({api: 'screenCapture'}, function(data) {
          crop(data.img, offset.left, offset.top, offset.width, offset.height, data.zoomFactor, callback);
        });
      }, 400);
    }
  };

  var createControlPanel = function(){
    var panel = document.getElementById('pc-control-panel');
    if(!panel) {
      panel = document.createElement('div');
      panel.setAttribute('id', 'pc-control-panel');
      document.body.appendChild(panel);
    }
    panel.style.position = 'fixed';
    panel.style.top = '100px';
    panel.style.right = '10px';
    panel.style.width = '100px';
    panel.style.height = '100px';
    panel.style.background = 'linear-gradient(#ccc, #aaf)';
    panel.style.border = '2px solid #02aeef';
    panel.style.zIndex = '99999999';
    panel.style.borderRadius = '50%';
    panel.style.boxShadow = '0 0 30px 0 #02aeef';
    panel.style.lineHeight = '100px';
    panel.style.textAlign = 'center';
    panel.style.cursor = 'pointer';
    panel.style.fontWeight = 'bold';
    panel.innerHTML = 'capture';
    return panel;
  };

  // listen to messages from clients using the the public api's
  window.addEventListener('message', function(event) {
    var data = event.data || {};

    if (!data.__index || !data.ns || !data.api) {
      return;
    }

    var send = function(value) {
      var opt = {
        __key: data.__index,
        value: value
      };
      window.postMessage(opt, '*');
    };

    console.log('page_capture api', data.api);

    if (data.api === 'getVersion') {
      send(manifest.version);
    }

    else if (data.api === 'captureElement') {
      screenCaptureHandler(data.element, function(data) {
        send(data);
        return true;
      });
    }

    else if (data.api === 'capturePage') {
      chrome.runtime.sendMessage({api: 'screenCapture'}, function(data) {
        send(data.img);
        return true;
      });
    }

    else if (data.api === 'captureSection') {
      chrome.runtime.sendMessage({api: 'screenCapture'}, function(responseData) {
        crop(responseData.img, data.x, data.y, data.width, data.height, responseData.zoomFactor, send);
        return true;
      });
    }

    else if (data.api === 'captureUrl') {
      chrome.runtime.sendMessage(data, function(dataUrl) {
        send(dataUrl);
        return true;
      });
    }
  });

  // listens for messages from the background script
  chrome.extension.onMessage.addListener(function (message, sender, sendResponse) {
    if (message.option === 'addControls') {
      var panel = createControlPanel();

      if(message.imgUrl){
        var img = new Image();
        img.onload = function(){
          img.style.width = img.naturalWidth + 'px';
          img.style.height = img.naturalHeight + 'px';
          draggable(img);
        };
        img.src = message.imgUrl;
      }

      var onClick = function(e) {
        e.preventDefault();
        document.getElementById('pc-control-panel').style.display = 'none';
        var info = null;
        if(message.imgUrl) {
          info = {};
          if (!message.includeOverlay) {
            img.style.display = 'none';
            info.url = location.href;
            info.overlay = img.dataset;
            info.overlay.url = message.imgUrl;
            delete info.overlay.pcType;
          }
        }
        setTimeout(function() {
          chrome.runtime.sendMessage({api: 'screenCapture'}, function(responseData) {
            if(info){
              responseData.info = info;
              sendResponse(responseData);
            } else {
              sendResponse(responseData.img);
            }
            return true;
          });
        }, 500);
      };

      var isMobile = /iPhone|iPad|iPod|Android/i.test(navigator.userAgent);
      if (isMobile) {
        panel.addEventListener('touchend', onClick, false);
      } else {
        panel.addEventListener('click', onClick, false);
      }
    }
    // all for asynchronously response
    return true;
  });

  // inject the api script in the current page document
  var apiScript = document.createElement('script');
  apiScript.src = chrome.extension.getURL('public.api.js');
  apiScript.type = 'text/javascript';
  document.body.appendChild(apiScript);

  console.log();

})();
<|endoftext|>


<commit_before>const jsonStringify = require('@bugsnag/safe-json-stringify')
const filterPaths = [
  // report
  'events.[].app',
  'events.[].metaData',
  'events.[].user',
  'events.[].breadcrumbs',
  'events.[].request',
  'events.[].device',
  // session
  'device',
  'app',
  'user'
]

module.exports.report = (report, filterKeys) => {
  let payload = jsonStringify(report, null, null, { filterPaths, filterKeys })
  if (payload.length > 10e5) {
    delete report.events[0].metaData
    report.events[0].metaData = {
      notifier:
`WARNING!
Serialized payload was ${payload.length / 10e5}MB (limit = 1MB)
metaData was removed`
    }
    payload = jsonStringify(report, null, null, { filterPaths, filterKeys })
    if (payload.length > 10e5) throw new Error('payload exceeded 1MB limit')
  }
  return payload
}

module.exports.session = (report, filterKeys) => {
  return jsonStringify(report, null, null, { filterPaths, filterKeys })
}
<commit_msg>refactor: Split filter paths into separate vars and check for size in session payload<commit_after>const jsonStringify = require('@bugsnag/safe-json-stringify')
const REPORT_FILTER_PATHS = [
  'events.[].app',
  'events.[].metaData',
  'events.[].user',
  'events.[].breadcrumbs',
  'events.[].request',
  'events.[].device'
]
const SESSION_FILTER_PATHS = [
  'device',
  'app',
  'user'
]

module.exports.report = (report, filterKeys) => {
  let payload = jsonStringify(report, null, null, { filterPaths: REPORT_FILTER_PATHS, filterKeys })
  if (payload.length > 10e5) {
    delete report.events[0].metaData
    report.events[0].metaData = {
      notifier:
`WARNING!
Serialized payload was ${payload.length / 10e5}MB (limit = 1MB)
metaData was removed`
    }
    payload = jsonStringify(report, null, null, { filterPaths: REPORT_FILTER_PATHS, filterKeys })
    if (payload.length > 10e5) throw new Error('payload exceeded 1MB limit')
  }
  return payload
}

module.exports.session = (report, filterKeys) => {
  const payload = jsonStringify(report, null, null, { filterPaths: SESSION_FILTER_PATHS, filterKeys })
  if (payload.length > 10e5) throw new Error('payload exceeded 1MB limit')
  return payload
}
<|endoftext|>


<commit_before>//var logger = require("loggero").create("controllers/registry");
var inherit = require("../inherit");
var Module = require("../module");
var Controller = require("../controller");
var Repository = require("../repository");

function Registry(context) {
  Controller.call(this, context);
}

inherit.base(Registry).extends(Controller);

Registry.prototype.register = function(name, exports) {
  return this.setModule(new Module({
    id: name,
    name: name,
    exports: exports,
    state: Module.State.READY
  }));
};

Registry.prototype.hasModule = function(id) {
  return Repository.hasItem(this.context.cache, id);
};

Registry.prototype.findModules = function(criteria) {
  return Repository.findAll(this.context.cache, {
    module: criteria
  });
};

Registry.prototype.findModule = function(criteria) {
  var result = Repository.findFirst(this.context.cache, {
    module: criteria
  });

  return result;
};

Registry.prototype.getModule = function(id) {
  if (!this.hasModule(id)) {
    throw new Error("Module with id '" + id + "' not found");
  }

  return Repository.getItem(this.context.cache, id);
};

Registry.prototype.setModule = function(mod) {
  var id = mod.id;
  var state = mod.state;

  if (this.hasModule(id) && this.getModuleState(id) === state) {
    throw new Error("Module instance '" + (mod.name || mod.id) + "' already exists. State '" + state + "'");
  }

  Repository.setItem(this.context.cache, id, mod);
  return mod;
};

Registry.prototype.updateModule = function(mod) {
  var id = mod.id;

  if (!this.hasModule(id)) {
    throw new Error("Module instance '" + (mod.name || mod.id) + "' does not exist");
  }

  Repository.setItem(this.context.cache, id, mod);
  return mod;
};

Registry.prototype.deleteModule = function(id) {
  if (!this.hasModule(id)) {
    throw new Error("Unable to delete module with id '" + id + "'. Module not found.");
  }

  var mod = Repository.getItem(this.context.cache, id);
  Repository.deleteItem(this.context.cache, id);
  return mod;
};

Registry.prototype.getModuleState = function(id) {
  if (!this.hasModule(id)) {
    throw new Error("Module instance '" + id + "' not found");
  }

  return Repository.getItem(this.context.cache, id).state;
};

module.exports = Registry;
<commit_msg>added a clear method in the repository to make sure we have a way to clear the internal module cache<commit_after>//var logger = require("loggero").create("controllers/registry");
var inherit = require("../inherit");
var Module = require("../module");
var Controller = require("../controller");
var Repository = require("../repository");

function Registry(context) {
  Controller.call(this, context);
}

inherit.base(Registry).extends(Controller);

Registry.prototype.register = function(name, exports) {
  return this.setModule(new Module({
    id: name,
    name: name,
    exports: exports,
    state: Module.State.READY
  }));
};

Registry.prototype.clear = function() {
  this.context.cache = {};
};

Registry.prototype.hasModule = function(id) {
  return Repository.hasItem(this.context.cache, id);
};

Registry.prototype.findModules = function(criteria) {
  return Repository.findAll(this.context.cache, {
    module: criteria
  });
};

Registry.prototype.findModule = function(criteria) {
  var result = Repository.findFirst(this.context.cache, {
    module: criteria
  });

  return result;
};

Registry.prototype.getModule = function(id) {
  if (!this.hasModule(id)) {
    throw new Error("Module with id '" + id + "' not found");
  }

  return Repository.getItem(this.context.cache, id);
};

Registry.prototype.setModule = function(mod) {
  var id = mod.id;
  var state = mod.state;

  if (this.hasModule(id) && this.getModuleState(id) === state) {
    throw new Error("Module instance '" + (mod.name || mod.id) + "' already exists. State '" + state + "'");
  }

  Repository.setItem(this.context.cache, id, mod);
  return mod;
};

Registry.prototype.updateModule = function(mod) {
  var id = mod.id;

  if (!this.hasModule(id)) {
    throw new Error("Module instance '" + (mod.name || mod.id) + "' does not exist");
  }

  Repository.setItem(this.context.cache, id, mod);
  return mod;
};

Registry.prototype.deleteModule = function(id) {
  if (!this.hasModule(id)) {
    throw new Error("Unable to delete module with id '" + id + "'. Module not found.");
  }

  var mod = Repository.getItem(this.context.cache, id);
  Repository.deleteItem(this.context.cache, id);
  return mod;
};

Registry.prototype.getModuleState = function(id) {
  if (!this.hasModule(id)) {
    throw new Error("Module instance '" + id + "' not found");
  }

  return Repository.getItem(this.context.cache, id).state;
};

module.exports = Registry;
<|endoftext|>


<commit_before>Package.describe({
  summary: "Meteor's client-side datastore: a port of MongoDB to Javascript",
  internal: true
});

Package.on_use(function (api) {
  api.export('GeoJSON');
  api.add_files(['geojson-utils.js']);
});

Package.on_test(function (api) {
  api.use('tinytest');
  api.add_files(['geojson-utils.js', 'geojson-utils.tests.js'], 'client');
});

<commit_msg>Fix package's description<commit_after>Package.describe({
  summary: 'GeoJSON utility functions',
  internal: true
});

Package.on_use(function (api) {
  api.export('GeoJSON');
  api.add_files(['geojson-utils.js']);
});

Package.on_test(function (api) {
  api.use('tinytest');
  api.add_files(['geojson-utils.js', 'geojson-utils.tests.js'], 'client');
});

<|endoftext|>


<commit_before>// Test harnesses
// ==============

// A test is defined with 'test', which returns a function.
// A group of tests is defined with `testGroup`, which also returns a function.
// Either one is executed by calling it with a "reporter".
// HTML and console reporters are provided.

// Setup.
import {spawn, timeout} from '../src/Asy';
import {makeStopwatch}  from '../src/Utl';
import {assignAdd}      from '../src/Obj';
import {parseBody}      from '../src/Fun';

var {assign, create, keys} = Object;

// Assertion libraries.
// --------------------
var {expect, should, assert} = chai;

assign(chai.config, {
  includeStack: true,
  showDiff: true
});

// `should` requires initialization.
should = should();

// Reporters
// ---------

var statusInfo = {
  pass: { color: 'green',  mark: '✓'},
  fail: { color: 'red',    mark: 'x'},
  skip: { color: 'orange', mark: '?'}
};

var statuses = keys(statusInfo);

// Base class for reporters.
// Options include a `hide` property with properties:
// `counts`, `time`, `pass`, `fail`, `skip`, `body`, `children`
class Reporter {
  constructor(options = {}) {
    this.options = assign({}, options);
    this.counts = {};
    this.time = 0;
  }

  startGroup()     { return new this.constructor(options); }

  endGroup({counts, time})  {
    assignAdd(this.counts, counts);
    this.time += time;
  }

  pass() { }
  fail() { }
  skip() { }

  report(result) {
    var {msg, status, time, code} = result;
    var {hide = {}} = this.options;

    if (!hide[status]) {
      if (!hide.time) { msg = `${msg} (${time}ms)`; }
      msg = statusInfo[status].mark + msg;
      this[status](msg, code, statusInfo[status].color);
    }

    this.counts[status] = (this.counts[status] || 0) + 1;
    this.time += time;
  }
}

// Console reporter, which reports results on the console.
class ConsoleReporter extends Reporter {
  constructor(options = {}) {
    super(options);
  }

  pass(msg, code, color) {
    console.log('%c' + msg, `color: ${color}`);
  }

  fail(msg) {
    console.error(msg);
  }

  skip(msg, code, color) {
    console.log('%c' + msg, `color: ${color}`);
  }

  startGroup(desc, options = {}) {
    var {hide = {}} = this.options;
    console[hide.cihldren ? 'groupCollapsed' : 'group'](desc);
    return new ConsoleReporter(assign(options, this.options));
  }

  endGroup(group) {
    var {counts, options: {hide = {}}, time} = group;
    console.groupEnd();
    super(group);
    if (!hide.counts) {
      let msg = keys(counts)
          .map(status => `${counts[status]} ${status}`)
          .join(', ');
      let color = counts.fail ? 'red' : 'green';
      if (!hide.time) { msg += ` (${time}ms)`; }
      console.log('%c' + msg, `color: ${color}`);
    }
    return this;
  }
}

// HTML reporter inserts output into the DOM.
class HtmlReporter extends Reporter {
  constructor(parent, options = {}) {
    this.parent = parent;
    super(options);
  }

  elt(tag)  { return document.createElement(tag); }
  append(c) { return this.parent.appendChild(c); }
  text(t)   { return document.createTextNode(t); }

  pass(msg, code, color) {
    var {hide = {}} = this.options;
    var t = this.text(msg);
    var e = this.elt('div');
    e.style.color = color;
    e.appendChild(t);
    if (!hide.code) {
      let codeElement = document.createElement('code');
      let codeText = document.createTextNode(` { ${code} }`);
      codeElement.appendChild(codeText);
      e.appendChild(codeElement);
    }
    this.append(e);
  }
  skip(msg, code, color) {
    var t = this.text(msg);
    var e = this.elt('div');
    e.style.color = color;
    e.appendChild(t);
    this.append(e);
  }
  fail(msg, code, color) {
    var t = this.text(msg);
    var e = this.elt('div');
    e.style.color = color;
    e.appendChild(t);
    this.append(e);
  }

  startGroup(desc) {
    var {hide = {}} = this.options;
    var details = this.elt('details');
    if (!hide.children) { details.setAttribute('open', true); }
    var summary = this.summaryElement = this.elt('summary');
    details.appendChild(summary);
    var desc = this.text(desc);
    summary.appendChild(desc);
    this.parent.appendChild(details);
    return new HtmlReporter(details, this.options);
  }

  endGroup(group) {
    var {counts, options: {hide = {}}, time} = group;
    super(group);
    if (!hide.counts) {
      let msg = keys(counts)
          .map(status => `${counts[status]} ${status}`)
          .join(', ');
      let color = counts.fail ? 'red' : 'green';
      if (!hide.time) { msg += ` (${time}ms)`; }
      this.summaryElement.textContent += ` [${msg}]`;
      this.summaryElement.style.color = color;
    }
    return this;
  }

}

// Test creators
// -------------

// To skip a test, or test group, or unskip it, call these.
function skipify  (test, s = true) { test._skip   = s; return test; }
function unskipify(test, s = true) { test._unskip = s; return test; }

// Return a function to run a group of tests.
function testGroup(desc, tests, options = {}) {
  var {skip, unskip} = options;

  function _testGroup(reporter, skipping) {
    return spawn(

      function *() {
        var group;
        yield group = reporter.startGroup(desc);
        for (var t of tests) {
          yield t(group, !t._unskip && (t._skip || skipping));
        }
        yield reporter.endGroup(group);
      }

    );
  }

  // Allow skipping/unskipping by chaining: `testGroup(...).skip()`.
  _testGroup.skip   = function(s) { return skipify  (this, s); };
  _testGroup.unskip = function(s) { return unskipify(this, s); };
  return _testGroup;
}

// Return a function to run a single test.
function test(desc, fn, options = {}) {
  var status, msg, time;
  var code = parseBody(fn);
  var stopwatch = makeStopwatch();
  var {unskip, skip} = options;

  return function _test(reporter, skipping) {
    if (skipping) {
      return Promise
        .resolve()
        .then(_ => reporter.report({status: 'skip', msg: desc, time: 0}))
      ;
    } else {
      return Promise
        .resolve()
        .then  (stopwatch.start)
        .then  (_ => fn(reporter))
        .then  (
          _ => { status = 'pass'; msg = desc; },
          e => { status = 'fail'; msg = desc + ": " + e; }
        )
        .then  (_ => {
          stopwatch.stop();
          time = stopwatch.time;
          reporter.report({status, msg, time, code});
        })
      ;
    }
  }

  // Allow skipping/unskipping by chaining: `test(...).skip()`.
  _test.skip   = function(s) { return skipify  (this, s); };
  _test.unskip = function(s) { return unskipify(this, s); };
  return _test;

}

// Exports
// -------
export {
  // Reporters.
  ConsoleReporter,
  HtmlReporter,

  // Test creators.
  test,
  testGroup,
  skipify,
  unskipify,

  // Assertion libraries.
  assert,
  should,
  expect
};
<commit_msg>Make summary line orange if all tests skipped.<commit_after>// Test harnesses
// ==============

// A test is defined with 'test', which returns a function.
// A group of tests is defined with `testGroup`, which also returns a function.
// Either one is executed by calling it with a "reporter".
// HTML and console reporters are provided.

// Setup.
import {spawn, timeout} from '../src/Asy';
import {makeStopwatch}  from '../src/Utl';
import {assignAdd}      from '../src/Obj';
import {parseBody}      from '../src/Fun';

var {assign, create, keys} = Object;

// Assertion libraries.
// --------------------
var {expect, should, assert} = chai;

assign(chai.config, {
  includeStack: true,
  showDiff: true
});

// `should` requires initialization.
should = should();

// Reporters
// ---------

var statusInfo = {
  pass: { color: 'green',  mark: '✓'},
  fail: { color: 'red',    mark: 'x'},
  skip: { color: 'orange', mark: '?'}
};

var statuses = keys(statusInfo);

// Base class for reporters.
// Options include a `hide` property with properties:
// `counts`, `time`, `pass`, `fail`, `skip`, `body`, `children`
class Reporter {
  constructor(options = {}) {
    this.options = assign({}, options);
    this.counts = {};
    this.time = 0;
  }

  startGroup()     { return new this.constructor(options); }

  endGroup({counts, time})  {
    assignAdd(this.counts, counts);
    this.time += time;
  }

  pass() { }
  fail() { }
  skip() { }

  report(result) {
    var {msg, status, time, code} = result;
    var {hide = {}} = this.options;

    if (!hide[status]) {
      if (!hide.time) { msg = `${msg} (${time}ms)`; }
      msg = statusInfo[status].mark + msg;
      this[status](msg, code, statusInfo[status].color);
    }

    this.counts[status] = (this.counts[status] || 0) + 1;
    this.time += time;
  }
}

// Console reporter, which reports results on the console.
class ConsoleReporter extends Reporter {
  constructor(options = {}) {
    super(options);
  }

  pass(msg, code, color) {
    console.log('%c' + msg, `color: ${color}`);
  }

  fail(msg) {
    console.error(msg);
  }

  skip(msg, code, color) {
    console.log('%c' + msg, `color: ${color}`);
  }

  startGroup(desc, options = {}) {
    var {hide = {}} = this.options;
    console[hide.cihldren ? 'groupCollapsed' : 'group'](desc);
    return new ConsoleReporter(assign(options, this.options));
  }

  endGroup(group) {
    var {counts, options: {hide = {}}, time} = group;
    console.groupEnd();
    super(group);
    if (!hide.counts) {
      let msg = keys(counts)
          .map(status => `${counts[status]} ${status}`)
          .join(', ');
      let color = counts.fail ? 'red' : 'green';
      if (!hide.time) { msg += ` (${time}ms)`; }
      console.log('%c' + msg, `color: ${color}`);
    }
    return this;
  }
}

// HTML reporter inserts output into the DOM.
class HtmlReporter extends Reporter {
  constructor(parent, options = {}) {
    this.parent = parent;
    super(options);
  }

  elt(tag)  { return document.createElement(tag); }
  append(c) { return this.parent.appendChild(c); }
  text(t)   { return document.createTextNode(t); }

  pass(msg, code, color) {
    var {hide = {}} = this.options;
    var t = this.text(msg);
    var e = this.elt('div');
    e.style.color = color;
    e.appendChild(t);
    if (!hide.code) {
      let codeElement = document.createElement('code');
      let codeText = document.createTextNode(` { ${code} }`);
      codeElement.appendChild(codeText);
      e.appendChild(codeElement);
    }
    this.append(e);
  }
  skip(msg, code, color) {
    var t = this.text(msg);
    var e = this.elt('div');
    e.style.color = color;
    e.appendChild(t);
    this.append(e);
  }
  fail(msg, code, color) {
    var t = this.text(msg);
    var e = this.elt('div');
    e.style.color = color;
    e.appendChild(t);
    this.append(e);
  }

  startGroup(desc) {
    var {hide = {}} = this.options;
    var details = this.elt('details');
    if (!hide.children) { details.setAttribute('open', true); }
    var summary = this.summaryElement = this.elt('summary');
    details.appendChild(summary);
    var desc = this.text(desc);
    summary.appendChild(desc);
    this.parent.appendChild(details);
    return new HtmlReporter(details, this.options);
  }

  endGroup(group) {
    var {counts, options: {hide = {}}, time} = group;
    super(group);
    if (!hide.counts) {
      let msg = keys(counts)
          .map(status => `${counts[status]} ${status}`)
          .join(', ');
      let allSkip = counts.skip && !keys(counts).some(k => k !== 'skip' && counts[k]);
      let color = allSkip ? 'orange' : counts.fail ? 'red' : 'green';
      if (!hide.time) { msg += ` (${time}ms)`; }
      this.summaryElement.textContent += ` [${msg}]`;
      this.summaryElement.style.color = color;
    }
    return this;
  }

}

// Test creators
// -------------

// To skip a test, or test group, or unskip it, call these.
function skipify  (test, s = true) { test._skip   = s; return test; }
function unskipify(test, s = true) { test._unskip = s; return test; }

// Return a function to run a group of tests.
function testGroup(desc, tests, options = {}) {
  var {skip, unskip} = options;

  function _testGroup(reporter, skipping) {
    return spawn(

      function *() {
        var group;
        yield group = reporter.startGroup(desc);
        for (var t of tests) {
          yield t(group, !t._unskip && (t._skip || skipping));
        }
        yield reporter.endGroup(group);
      }

    );
  }

  // Allow skipping/unskipping by chaining: `testGroup(...).skip()`.
  _testGroup.skip   = function(s) { return skipify  (this, s); };
  _testGroup.unskip = function(s) { return unskipify(this, s); };
  return _testGroup;
}

// Return a function to run a single test.
function test(desc, fn, options = {}) {
  var status, msg, time;
  var code = parseBody(fn);
  var stopwatch = makeStopwatch();
  var {unskip, skip} = options;

  return function _test(reporter, skipping) {
    if (skipping) {
      return Promise
        .resolve()
        .then(_ => reporter.report({status: 'skip', msg: desc, time: 0}))
      ;
    } else {
      return Promise
        .resolve()
        .then  (stopwatch.start)
        .then  (_ => fn(reporter))
        .then  (
          _ => { status = 'pass'; msg = desc; },
          e => { status = 'fail'; msg = desc + ": " + e; }
        )
        .then  (_ => {
          stopwatch.stop();
          time = stopwatch.time;
          reporter.report({status, msg, time, code});
        })
      ;
    }
  }

  // Allow skipping/unskipping by chaining: `test(...).skip()`.
  _test.skip   = function(s) { return skipify  (this, s); };
  _test.unskip = function(s) { return unskipify(this, s); };
  return _test;

}

// Exports
// -------
export {
  // Reporters.
  ConsoleReporter,
  HtmlReporter,

  // Test creators.
  test,
  testGroup,
  skipify,
  unskipify,

  // Assertion libraries.
  assert,
  should,
  expect
};
<|endoftext|>


<commit_before>/**
 * Copyright (c) 2014-present, Facebook, Inc. All rights reserved.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 *
 * @flow
 */

import type {GlobalConfig} from 'types/Config';
import type {
  OnTestFailure,
  OnTestStart,
  OnTestSuccess,
  Test,
  TestRunnerOptions,
  TestWatcher,
} from 'types/TestRunner';

import typeof {worker} from './test_worker';

import runTest from './run_test';
import throat from 'throat';
import Worker from 'jest-worker';

const TEST_WORKER_PATH = require.resolve('./test_worker');

type WorkerInterface = Worker & {worker: worker};

class TestRunner {
  _globalConfig: GlobalConfig;

  constructor(globalConfig: GlobalConfig) {
    this._globalConfig = globalConfig;
  }

  async runTests(
    tests: Array<Test>,
    watcher: TestWatcher,
    onStart: OnTestStart,
    onResult: OnTestSuccess,
    onFailure: OnTestFailure,
    options: TestRunnerOptions,
  ): Promise<void> {
    return await (options.serial
      ? this._createInBandTestRun(tests, watcher, onStart, onResult, onFailure)
      : this._createParallelTestRun(
          tests,
          watcher,
          onStart,
          onResult,
          onFailure,
        ));
  }

  async _createInBandTestRun(
    tests: Array<Test>,
    watcher: TestWatcher,
    onStart: OnTestStart,
    onResult: OnTestSuccess,
    onFailure: OnTestFailure,
  ) {
    const mutex = throat(1);
    return tests.reduce(
      (promise, test) =>
        mutex(() =>
          promise
            .then(async () => {
              if (watcher.isInterrupted()) {
                throw new CancelRun();
              }

              await onStart(test);
              return runTest(
                test.path,
                this._globalConfig,
                test.context.config,
                test.context.resolver,
              );
            })
            .then(result => onResult(test, result))
            .catch(err => onFailure(test, err)),
        ),
      Promise.resolve(),
    );
  }

  async _createParallelTestRun(
    tests: Array<Test>,
    watcher: TestWatcher,
    onStart: OnTestStart,
    onResult: OnTestSuccess,
    onFailure: OnTestFailure,
  ) {
    // $FlowFixMe: class object is augmented with worker when instantiating.
    const worker: WorkerInterface = new Worker(TEST_WORKER_PATH, {
      exposedMethods: ['worker'],
      maxRetries: 3,
      numWorkers: this._globalConfig.maxWorkers,
    });

    const mutex = throat(this._globalConfig.maxWorkers);

    // Send test suites to workers continuously instead of all at once to track
    // the start time of individual tests.
    const runTestInWorker = test =>
      mutex(async () => {
        if (watcher.isInterrupted()) {
          return Promise.reject();
        }

        await onStart(test);

        return worker.worker({
          config: test.context.config,
          globalConfig: this._globalConfig,
          path: test.path,
          rawModuleMap: watcher.isWatchMode()
            ? test.context.moduleMap.getRawModuleMap()
            : null,
        });
      });

    const onError = async (err, test) => {
      await onFailure(test, err);
      if (err.type === 'ProcessTerminatedError') {
        console.error(
          'A worker process has quit unexpectedly! ' +
            'Most likely this is an initialization error.',
        );
        process.exit(1);
      }
    };

    const onInterrupt = new Promise((_, reject) => {
      watcher.on('change', state => {
        if (state.interrupted) {
          reject(new CancelRun());
        }
      });
    });

    const runAllTests = Promise.all(
      tests.map(test =>
        runTestInWorker(test)
          .then(testResult => onResult(test, testResult))
          .catch(error => onError(error, test)),
      ),
    );

    const cleanup = () => worker.end();
    return Promise.race([runAllTests, onInterrupt]).then(cleanup, cleanup);
  }
}

class CancelRun extends Error {
  constructor(message: ?string) {
    super(message);
    this.name = 'CancelRun';
  }
}

module.exports = TestRunner;
<commit_msg>Inherit stdio for jest-runner (#4933)<commit_after>/**
 * Copyright (c) 2014-present, Facebook, Inc. All rights reserved.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 *
 * @flow
 */

import type {GlobalConfig} from 'types/Config';
import type {
  OnTestFailure,
  OnTestStart,
  OnTestSuccess,
  Test,
  TestRunnerOptions,
  TestWatcher,
} from 'types/TestRunner';

import typeof {worker} from './test_worker';

import runTest from './run_test';
import throat from 'throat';
import Worker from 'jest-worker';

const TEST_WORKER_PATH = require.resolve('./test_worker');

type WorkerInterface = Worker & {worker: worker};

class TestRunner {
  _globalConfig: GlobalConfig;

  constructor(globalConfig: GlobalConfig) {
    this._globalConfig = globalConfig;
  }

  async runTests(
    tests: Array<Test>,
    watcher: TestWatcher,
    onStart: OnTestStart,
    onResult: OnTestSuccess,
    onFailure: OnTestFailure,
    options: TestRunnerOptions,
  ): Promise<void> {
    return await (options.serial
      ? this._createInBandTestRun(tests, watcher, onStart, onResult, onFailure)
      : this._createParallelTestRun(
          tests,
          watcher,
          onStart,
          onResult,
          onFailure,
        ));
  }

  async _createInBandTestRun(
    tests: Array<Test>,
    watcher: TestWatcher,
    onStart: OnTestStart,
    onResult: OnTestSuccess,
    onFailure: OnTestFailure,
  ) {
    const mutex = throat(1);
    return tests.reduce(
      (promise, test) =>
        mutex(() =>
          promise
            .then(async () => {
              if (watcher.isInterrupted()) {
                throw new CancelRun();
              }

              await onStart(test);
              return runTest(
                test.path,
                this._globalConfig,
                test.context.config,
                test.context.resolver,
              );
            })
            .then(result => onResult(test, result))
            .catch(err => onFailure(test, err)),
        ),
      Promise.resolve(),
    );
  }

  async _createParallelTestRun(
    tests: Array<Test>,
    watcher: TestWatcher,
    onStart: OnTestStart,
    onResult: OnTestSuccess,
    onFailure: OnTestFailure,
  ) {
    // $FlowFixMe: class object is augmented with worker when instantiating.
    const worker: WorkerInterface = new Worker(TEST_WORKER_PATH, {
      exposedMethods: ['worker'],
      forkOptions: {stdio: 'inherit'},
      maxRetries: 3,
      numWorkers: this._globalConfig.maxWorkers,
    });

    const mutex = throat(this._globalConfig.maxWorkers);

    // Send test suites to workers continuously instead of all at once to track
    // the start time of individual tests.
    const runTestInWorker = test =>
      mutex(async () => {
        if (watcher.isInterrupted()) {
          return Promise.reject();
        }

        await onStart(test);

        return worker.worker({
          config: test.context.config,
          globalConfig: this._globalConfig,
          path: test.path,
          rawModuleMap: watcher.isWatchMode()
            ? test.context.moduleMap.getRawModuleMap()
            : null,
        });
      });

    const onError = async (err, test) => {
      await onFailure(test, err);
      if (err.type === 'ProcessTerminatedError') {
        console.error(
          'A worker process has quit unexpectedly! ' +
            'Most likely this is an initialization error.',
        );
        process.exit(1);
      }
    };

    const onInterrupt = new Promise((_, reject) => {
      watcher.on('change', state => {
        if (state.interrupted) {
          reject(new CancelRun());
        }
      });
    });

    const runAllTests = Promise.all(
      tests.map(test =>
        runTestInWorker(test)
          .then(testResult => onResult(test, testResult))
          .catch(error => onError(error, test)),
      ),
    );

    const cleanup = () => worker.end();
    return Promise.race([runAllTests, onInterrupt]).then(cleanup, cleanup);
  }
}

class CancelRun extends Error {
  constructor(message: ?string) {
    super(message);
    this.name = 'CancelRun';
  }
}

module.exports = TestRunner;
<|endoftext|>