<commit_before>import React, { Component } from 'react';
import PropTypes from 'prop-types';
import axios from 'axios'
import { withStyles } from 'material-ui/styles'
import Grid from 'material-ui/Grid'
import Typography from 'material-ui/Typography'
import Divider from 'material-ui/Divider';
import List, { ListItem, ListItemText, ListItemIcon } from 'material-ui/List';
import Slide from 'material-ui/transitions/Slide';
import Button from 'material-ui/Button';
import Avatar from 'material-ui/Avatar';
import AccountBalanceWalletIcon from 'material-ui-icons/AccountBalanceWallet';
import WorkIcon from 'material-ui-icons/Work';
import AppsIcon from 'material-ui-icons/Apps';

import AssignmentIcon from 'material-ui-icons/Assignment';
import GroupWorkIcon from 'material-ui-icons/GroupWork';
import ArchiveIcon from 'material-ui-icons/Archive';
import CardMembershipIcon from 'material-ui-icons/CardMembership';
import BugReportIcon from 'material-ui-icons/BugReport';
import SubscribeFrom from 'react-mailchimp-subscribe'

import { red, cyan, teal } from 'material-ui/colors';

import './mailchimp.css'

import HowItWorksPeople from './how-it-works-people';
import WhoSubscribes from './who-subscribes';
import Workflow from './workflow';
import HowItWorksCompany from './how-it-works-company';
import WhichCompanies from './which-companies';
import Consulting from './consulting';

const logo = require('../../images/gitpay-logo.png');
const logoCompleteGray = require('../../images/logo-complete-gray.png');
const logoSymbol = require('../../images/logo-symbol.png');
const logoGitlab = require('../../images/gitlab-logo.png');
const logoGithub = require('../../images/github-logo.png');
const logoBitbucket = require('../../images/bitbucket-logo.png');
const octodex = require('../../images/octodex.png');
const octodexMotherhubbertocat = require('../../images/octodex-motherhubbertocat.png');
const deal = require('../../images/deal.png');

import ReactGA from 'react-ga';
ReactGA.initialize('UA-114655639-1');
ReactGA.pageview(window.location.pathname + window.location.search);

const styles = theme => ({
  root: {
    flexGrow: 1,
    marginTop: 0,
  },
  img: {
    marginTop: -18,
    marginRight: 10
  },
  icon: {
    marginTop: -4,
    marginRight: 5
  },
  button: {
    margin: theme.spacing.unit,
    padding: [theme.spacing.unit*2, theme.spacing.unit*4],
    color: 'white'
  },
  altButton: {
    margin: [theme.spacing.unit],
    padding: [theme.spacing.unit/2, theme.spacing.unit*6],
    color: 'white',
    fontSize: 12
  },
  mainBlock: {
    textAlign: 'center',
    padding: 8,
    color: theme.palette.text.primary
  },
  secBlock: {
    textAlign: 'center',
    padding: 8,
    backgroundColor: '#f1f0ea'
  },
  divider: {
    textAlign: 'center',
    display: 'inline-block',
    marginLeft: '35%',
    marginBottom: '5%',
    marginTop: 40,
    fontSize: 18,
    paddingBottom: 10,
    borderBottom: '5px solid black',
    width: '30%',
  },
  mainlist: {
    textAlign: 'left',
    marginLeft: '20%'
  },
  seclist: {
    textAlign: 'left',
    width: '100%'
  },
  listIconTop: {
    alignItems: 'flex-start'
  },
  alignLeftPadding: {
    textAlign: 'left',
    padding: 80,
    paddingTop: 40,
  },
  spacedTop: {
    marginTop: 20
  },
  defaultCenterBlock: {
    textAlign: 'center',
    padding: 10,
    color: theme.palette.text.primary
  },
  intro: {
    padding: 20,
    margin: 0,
    textAlign: 'center',
    height: 55,
    backgroundColor: 'black',
    color: theme.palette.text.secondary,
  },
  logoSimple: {
    textAlign: 'left',
    overflow: 'hidden',
    paddingTop: 20
  },
  tagline: {
    fontSize: 45,
    color: 'black'
  },
  appBar: {
    height: '100%'
  }
});

const formProps = {
  action: '//truppie.us17.list-manage.com/subscribe/post?u=bb76ecd5ef5cbbc5e60701321&id=63cbedd527',
  messages: {
    inputPlaceholder: "Deixe seu email",
    btnLabel: "Cadastrar!",
    sending: "Registrando...",
    success: "Você foi registrado e irá receber em breve novas oportunidades!",
    error: "Não conseguimos registrar este e-mail, deixou vazio ou colocou algum já existente?"
  },
  styles: {
    sending: {
      fontSize: 14,
      color: cyan["500"]
    },
    success: {
      fontSize: 14,
      color: teal["500"]
    },
    error: {
      fontSize: 14,
      color: red["500"]
    }
  }
}

class Welcome extends Component {

  constructor(props) {
    super(props);
  }

  render() {

    const { classes } = this.props;

    return (

        <Grid container spacing={24}>
          <Grid item xs={12}>

          </Grid>
          <Grid item xs={12}>

              <Typography type="display2" className={classes.tagline} gutterBottom>
                Aqui seu trabalho ganha vida
              </Typography>
              <Typography type="headline" gutterBottom>
                para colocar novas idéias no ar
              </Typography>
              <Typography type="subheading" gutterBottom noWrap>

                com o Gitpay você trabalha de forma independente com projetos sob demanda

              </Typography>

                <SubscribeFrom className="subscribe-form-main"  {...formProps} />

          </Grid>
        </Grid>

          <Grid container spacing={24}>
            <Grid item xs={12} sm={6}>

                <Typography type="headline" gutterBottom>
                  Para freelancers
                </Typography>

                <List>
                  <ListItem className={classes.listIconTop}>
                    <ListItemIcon>
                      <Avatar>
                        <AppsIcon />
                      </Avatar>
                    </ListItemIcon>
                    <ListItemText primary="Trabalhe em projetos usando as melhores ferramentas de desenvolvimento"
                                  secondary="Com o Gitpay você utiliza os recursos do git e controle de versão para realizar entregas para os clientes"/>
                  </ListItem>
                  <ListItem className={classes.listIconTop}>
                    <ListItemIcon>
                      <Avatar>
                        <WorkIcon />
                      </Avatar>
                    </ListItemIcon>
                    <ListItemText primary="Colabore com empresas e trabalhe sob demanda"
                                  secondary="Trabalhe em diferentes projetos, colabore e aprenda com projetos reais que utilizam diferentes tecnologias"/>
                  </ListItem>
                  <ListItem className={classes.listIconTop}>
                    <ListItemIcon>
                      <Avatar>
                        <AccountBalanceWalletIcon />
                      </Avatar>
                    </ListItemIcon>
                    <ListItemText primary="Receba pelos trabalhos realizados"
                                  secondary="Receba o pagamento diretamente na sua conta pelas tarefas de desenvolvimento quando seu código for integrado"/>
                  </ListItem>
                </List>

            </Grid>
            <Grid item xs={12} sm={6}>

            </Grid>
          </Grid>

          <Grid container spacing={24}>
            <Grid item xs={12} sm={6}>

                <Typography type="headline" gutterBottom>
                  Para empresas
                </Typography>

                <List>
                  <ListItem className={classes.listIconTop}>
                    <ListItemIcon>
                      <Avatar>
                        <AssignmentIcon />
                      </Avatar>
                    </ListItemIcon>
                    <ListItemText primary="Gerencie o desenvolvimento da sua startup"
                                  secondary="Com o Gitpay as empresas podem gerir seu negócio utilizando ferramentas de desenvolvimento feitos sobe medida para você"/>
                  </ListItem>
                  <ListItem className={classes.listIconTop}>
                    <ListItemIcon>
                      <Avatar>
                        <GroupWorkIcon />
                      </Avatar>
                    </ListItemIcon>
                    <ListItemText
                      primary="Pague pelos trabalhos concluídos com processos inteligentes e automatizados"
                      secondary="Envolva diferentes tipos de freelancers, com experiências variadas que irão ajudar no desenvolvimento do projeto usando as ferramentas que eles conhecem e processos já consolidados"/>
                  </ListItem>
                  <ListItem className={classes.listIconTop}>
                    <ListItemIcon>
                      <Avatar>
                        <AccountBalanceWalletIcon />
                      </Avatar>
                    </ListItemIcon>
                    <ListItemText
                      primary="Desenvolva o seu negócio com ferramentas open source, e pagando por servicos sob demanda"
                      secondary="Empresas podem nascer e se manter com o Gitpay, desde o design até o desenvolvimento, pagando apenas pelas demandas concluídas e integradas com o projeto"/>
                  </ListItem>
                </List>

            </Grid>
            <Grid item xs={12} sm={6}>

            </Grid>
          </Grid>

          <Grid container spacing={24}>

              <Typography type="headline" gutterBottom>
                Como funciona
              </Typography>

            <Grid item xs={12} sm={6}>

            </Grid>
            <Grid item xs={12} sm={6}>

                <List>
                  <ListItem className={classes.listIconTop}>
                    <ListItemIcon>
                      <ArchiveIcon />
                    </ListItemIcon>
                    <ListItemText primary="Uma nova tarefa de um projeto é criada"
                                  secondary="Uma demanda, incidente, melhoria ou sugestão é lançada na plataforma, seja ela de código, SEO, conteúdo ou até infra estrutura e novas idéias"/>
                  </ListItem>
                  <Divider />
                  <ListItem className={classes.listIconTop}>
                    <ListItemIcon>
                      <BugReportIcon />
                    </ListItemIcon>
                    <ListItemText primary="A sua demanda é enviada para a comunidade"
                                  secondary="Diferentes grupos de freelancers se interessam por esta demanda por um valor fixo ou sugerido pelos interessados"/>
                  </ListItem>
                  <Divider />
                  <ListItem className={classes.listIconTop}>
                    <ListItemIcon>
                      <CardMembershipIcon />
                    </ListItemIcon>
                    <ListItemText primary="Solicitação de mudança e recompensa"
                                  secondary="É enviada uma solicitação no repositório do projeto para que seja integrado e o pagamento é realizado"/>
                  </ListItem>
                  <Divider />
                  <ListItem className={classes.listIconTop}>
                    <ListItemIcon>
                      <BugReportIcon />
                    </ListItemIcon>
                    <ListItemText primary="Processos ágeis entre negócios e desenvolvimento"
                                  secondary="Queremos facilitar as transações e facilitar os acordos entre empresas e freelancers utilizando ferramentas inteligentes, processos já usados em empresas ágeis e startups"/>
                  </ListItem>
                </List>

            </Grid>
          </Grid>

            <Grid container spacing={24}>
              <Grid item xs={12} sm={3}>
                <Typography type="subheading">
                  Para freelancers
                </Typography>
                <List component="nav">
                  <HowItWorksPeople classes={classes} />
                  <WhoSubscribes classes={classes} />
                  <Workflow classes={classes} />
                </List>
              </Grid>
              <Grid item xs={12} sm={3}>
                <Typography type="subheading">
                  Para empresas
                </Typography>
                <List component="nav">
                  <HowItWorksCompany classes={classes} />
                  <WhichCompanies classes={classes} />
                  <Consulting classes={classes} />
                </List>
              </Grid>
              <Grid item xs={12} sm={2}>
                <Typography type="subheading">
                  Parceiros
                </Typography>
                <Button label="Jooble" href="https://br.jooble.org/vagas-de-emprego-desenvolvedor">Jooble</Button>
              </Grid>
              <Grid item xs={12} sm={4}>
                <Typography type="subheading">
                  Tá na dúvida aí? Não se preocupe, deixe seu e-mail e fique sabendo de novos desafios!
                </Typography>

                  <SubscribeFrom  {...formProps} />

                <Typography type="caption">
                  worknenjoy, Inc.

                  Borgergade, 26 sal 4 lej 3

                  København, Hovedstaden 1300 DK
                </Typography>
              </Grid>
            </Grid>
            <Divider className={classes.spacedTop}/>
            <Grid container spacing={24}>
              <Grid item xs={12} sm={2}>

              </Grid>
            </Grid>

    );
  }
}

/*
<Button raised color="primary" className={classes.button}>
  Começar agora!
</Button>

 <Grid item xs={12}>

 <Typography type="subheading" gutterBottom noWrap>
 Ou conecte com algumas dessas contas
 </Typography>
 <Button raised size="small" color="accent" className={classes.altButton}>
  Github
 </Button>
 <Button raised size="small" color="accent" className={classes.altButton}>
  Gitlab
 </Button>
 <Button raised size="small" color="accent" className={classes.altButton}>
  Bitbucket
 </Button>

 </Grid>
*/

Welcome.propTypes = {
  classes: PropTypes.object.isRequired,
};

export default withStyles(styles)(Welcome);
<commit_msg>adding integrations<commit_after>import React, { Component } from 'react';
import PropTypes from 'prop-types';
import axios from 'axios'
import { withStyles } from 'material-ui/styles'
import Grid from 'material-ui/Grid'
import Typography from 'material-ui/Typography'
import Divider from 'material-ui/Divider';
import List, { ListItem, ListItemText, ListItemIcon } from 'material-ui/List';
import Slide from 'material-ui/transitions/Slide';
import Button from 'material-ui/Button';
import Avatar from 'material-ui/Avatar';
import AccountBalanceWalletIcon from 'material-ui-icons/AccountBalanceWallet';
import WorkIcon from 'material-ui-icons/Work';
import AppsIcon from 'material-ui-icons/Apps';

import AssignmentIcon from 'material-ui-icons/Assignment';
import GroupWorkIcon from 'material-ui-icons/GroupWork';
import ArchiveIcon from 'material-ui-icons/Archive';
import CardMembershipIcon from 'material-ui-icons/CardMembership';
import BugReportIcon from 'material-ui-icons/BugReport';
import SubscribeFrom from 'react-mailchimp-subscribe'

import { red, cyan, teal } from 'material-ui/colors';

import './mailchimp.css'

import HowItWorksPeople from './how-it-works-people';
import WhoSubscribes from './who-subscribes';
import Workflow from './workflow';
import HowItWorksCompany from './how-it-works-company';
import WhichCompanies from './which-companies';
import Consulting from './consulting';

const logo = require('../../images/gitpay-logo.png');
const logoCompleteGray = require('../../images/logo-complete-gray.png');
const logoSymbol = require('../../images/logo-symbol.png');
const logoGitlab = require('../../images/gitlab-logo.png');
const logoGithub = require('../../images/github-logo.png');
const logoBitbucket = require('../../images/bitbucket-logo.png');
const octodex = require('../../images/octodex.png');
const octodexMotherhubbertocat = require('../../images/octodex-motherhubbertocat.png');
const deal = require('../../images/deal.png');

import ReactGA from 'react-ga';
ReactGA.initialize('UA-114655639-1');
ReactGA.pageview(window.location.pathname + window.location.search);

const styles = theme => ({
  root: {
    flexGrow: 1,
    marginTop: 0,
  },
  img: {
    marginTop: -18,
    marginRight: 10
  },
  icon: {
    marginTop: -4,
    marginRight: 5
  },
  button: {
    margin: theme.spacing.unit,
    padding: [theme.spacing.unit*2, theme.spacing.unit*4],
    color: 'white'
  },
  altButton: {
    margin: [theme.spacing.unit],
    padding: [theme.spacing.unit/2, theme.spacing.unit*6],
    color: 'white',
    fontSize: 12
  },
  mainBlock: {
    textAlign: 'center',
    padding: 8,
    color: theme.palette.text.primary
  },
  secBlock: {
    textAlign: 'center',
    padding: 8,
    backgroundColor: '#f1f0ea'
  },
  divider: {
    textAlign: 'center',
    display: 'inline-block',
    marginLeft: '35%',
    marginBottom: '5%',
    marginTop: 40,
    fontSize: 18,
    paddingBottom: 10,
    borderBottom: '5px solid black',
    width: '30%',
  },
  mainlist: {
    textAlign: 'left',
    marginLeft: '20%'
  },
  seclist: {
    textAlign: 'left',
    width: '100%'
  },
  listIconTop: {
    alignItems: 'flex-start'
  },
  alignLeftPadding: {
    textAlign: 'left',
    padding: 80,
    paddingTop: 40,
  },
  spacedTop: {
    marginTop: 20
  },
  defaultCenterBlock: {
    textAlign: 'center',
    padding: 10,
    color: theme.palette.text.primary
  },
  intro: {
    padding: 20,
    margin: 0,
    textAlign: 'center',
    height: 55,
    backgroundColor: 'black',
    color: theme.palette.text.secondary,
  },
  logoSimple: {
    textAlign: 'left',
    overflow: 'hidden',
    paddingTop: 20
  },
  tagline: {
    fontSize: 45,
    color: 'black'
  },
  appBar: {
    height: '100%'
  }
});

const formProps = {
  action: '//truppie.us17.list-manage.com/subscribe/post?u=bb76ecd5ef5cbbc5e60701321&id=63cbedd527',
  messages: {
    inputPlaceholder: "Deixe seu email",
    btnLabel: "Cadastrar!",
    sending: "Registrando...",
    success: "Você foi registrado e irá receber em breve novas oportunidades!",
    error: "Não conseguimos registrar este e-mail, deixou vazio ou colocou algum já existente?"
  },
  styles: {
    sending: {
      fontSize: 14,
      color: cyan["500"]
    },
    success: {
      fontSize: 14,
      color: teal["500"]
    },
    error: {
      fontSize: 14,
      color: red["500"]
    }
  }
}

class Welcome extends Component {

  constructor(props) {
    super(props);
  }

  render() {

    const { classes } = this.props;

    return (

        <Grid container spacing={24}>
          <Grid item xs={12}>

          </Grid>
          <Grid item xs={12}>

              <Typography type="display2" className={classes.tagline} gutterBottom>
                Aqui seu trabalho ganha vida
              </Typography>
              <Typography type="headline" gutterBottom>
                para colocar novas idéias no ar
              </Typography>
              <Typography type="subheading" gutterBottom noWrap>

                com o Gitpay você trabalha de forma independente com projetos sob demanda

              </Typography>

                <SubscribeFrom className="subscribe-form-main"  {...formProps} />

          </Grid>
        </Grid>
        <Grid item xs={12}>

            <Typography type="subheading" gutterBottom noWrap>
              Ou conecte com algumas dessas contas
            </Typography>
            <Button variant="raised" size="small" color="secondary" className={classes.altButton}>
               Github
            </Button>
            <Button variant="raised" size="small" color="secondary" className={classes.altButton}>
               Gitlab
            </Button>
            <Button href="/authorize/bitbucket" variant="raised" size="small" color="secondary" className={classes.altButton}>
               Bitbucket
            </Button>

        </Grid>

          <Grid container spacing={24}>
            <Grid item xs={12} sm={6}>

                <Typography type="headline" gutterBottom>
                  Para freelancers
                </Typography>

                <List>
                  <ListItem className={classes.listIconTop}>
                    <ListItemIcon>
                      <Avatar>
                        <AppsIcon />
                      </Avatar>
                    </ListItemIcon>
                    <ListItemText primary="Trabalhe em projetos usando as melhores ferramentas de desenvolvimento"
                                  secondary="Com o Gitpay você utiliza os recursos do git e controle de versão para realizar entregas para os clientes"/>
                  </ListItem>
                  <ListItem className={classes.listIconTop}>
                    <ListItemIcon>
                      <Avatar>
                        <WorkIcon />
                      </Avatar>
                    </ListItemIcon>
                    <ListItemText primary="Colabore com empresas e trabalhe sob demanda"
                                  secondary="Trabalhe em diferentes projetos, colabore e aprenda com projetos reais que utilizam diferentes tecnologias"/>
                  </ListItem>
                  <ListItem className={classes.listIconTop}>
                    <ListItemIcon>
                      <Avatar>
                        <AccountBalanceWalletIcon />
                      </Avatar>
                    </ListItemIcon>
                    <ListItemText primary="Receba pelos trabalhos realizados"
                                  secondary="Receba o pagamento diretamente na sua conta pelas tarefas de desenvolvimento quando seu código for integrado"/>
                  </ListItem>
                </List>

            </Grid>
            <Grid item xs={12} sm={6}>

            </Grid>
          </Grid>

          <Grid container spacing={24}>
            <Grid item xs={12} sm={6}>

                <Typography type="headline" gutterBottom>
                  Para empresas
                </Typography>

                <List>
                  <ListItem className={classes.listIconTop}>
                    <ListItemIcon>
                      <Avatar>
                        <AssignmentIcon />
                      </Avatar>
                    </ListItemIcon>
                    <ListItemText primary="Gerencie o desenvolvimento da sua startup"
                                  secondary="Com o Gitpay as empresas podem gerir seu negócio utilizando ferramentas de desenvolvimento feitos sobe medida para você"/>
                  </ListItem>
                  <ListItem className={classes.listIconTop}>
                    <ListItemIcon>
                      <Avatar>
                        <GroupWorkIcon />
                      </Avatar>
                    </ListItemIcon>
                    <ListItemText
                      primary="Pague pelos trabalhos concluídos com processos inteligentes e automatizados"
                      secondary="Envolva diferentes tipos de freelancers, com experiências variadas que irão ajudar no desenvolvimento do projeto usando as ferramentas que eles conhecem e processos já consolidados"/>
                  </ListItem>
                  <ListItem className={classes.listIconTop}>
                    <ListItemIcon>
                      <Avatar>
                        <AccountBalanceWalletIcon />
                      </Avatar>
                    </ListItemIcon>
                    <ListItemText
                      primary="Desenvolva o seu negócio com ferramentas open source, e pagando por servicos sob demanda"
                      secondary="Empresas podem nascer e se manter com o Gitpay, desde o design até o desenvolvimento, pagando apenas pelas demandas concluídas e integradas com o projeto"/>
                  </ListItem>
                </List>

            </Grid>
            <Grid item xs={12} sm={6}>

            </Grid>
          </Grid>

          <Grid container spacing={24}>

              <Typography type="headline" gutterBottom>
                Como funciona
              </Typography>

            <Grid item xs={12} sm={6}>

            </Grid>
            <Grid item xs={12} sm={6}>

                <List>
                  <ListItem className={classes.listIconTop}>
                    <ListItemIcon>
                      <ArchiveIcon />
                    </ListItemIcon>
                    <ListItemText primary="Uma nova tarefa de um projeto é criada"
                                  secondary="Uma demanda, incidente, melhoria ou sugestão é lançada na plataforma, seja ela de código, SEO, conteúdo ou até infra estrutura e novas idéias"/>
                  </ListItem>
                  <Divider />
                  <ListItem className={classes.listIconTop}>
                    <ListItemIcon>
                      <BugReportIcon />
                    </ListItemIcon>
                    <ListItemText primary="A sua demanda é enviada para a comunidade"
                                  secondary="Diferentes grupos de freelancers se interessam por esta demanda por um valor fixo ou sugerido pelos interessados"/>
                  </ListItem>
                  <Divider />
                  <ListItem className={classes.listIconTop}>
                    <ListItemIcon>
                      <CardMembershipIcon />
                    </ListItemIcon>
                    <ListItemText primary="Solicitação de mudança e recompensa"
                                  secondary="É enviada uma solicitação no repositório do projeto para que seja integrado e o pagamento é realizado"/>
                  </ListItem>
                  <Divider />
                  <ListItem className={classes.listIconTop}>
                    <ListItemIcon>
                      <BugReportIcon />
                    </ListItemIcon>
                    <ListItemText primary="Processos ágeis entre negócios e desenvolvimento"
                                  secondary="Queremos facilitar as transações e facilitar os acordos entre empresas e freelancers utilizando ferramentas inteligentes, processos já usados em empresas ágeis e startups"/>
                  </ListItem>
                </List>

            </Grid>
          </Grid>

            <Grid container spacing={24}>
              <Grid item xs={12} sm={3}>
                <Typography type="subheading">
                  Para freelancers
                </Typography>
                <List component="nav">
                  <HowItWorksPeople classes={classes} />
                  <WhoSubscribes classes={classes} />
                  <Workflow classes={classes} />
                </List>
              </Grid>
              <Grid item xs={12} sm={3}>
                <Typography type="subheading">
                  Para empresas
                </Typography>
                <List component="nav">
                  <HowItWorksCompany classes={classes} />
                  <WhichCompanies classes={classes} />
                  <Consulting classes={classes} />
                </List>
              </Grid>
              <Grid item xs={12} sm={2}>
                <Typography type="subheading">
                  Parceiros
                </Typography>
                <Button label="Jooble" href="https://br.jooble.org/vagas-de-emprego-desenvolvedor">Jooble</Button>
              </Grid>
              <Grid item xs={12} sm={4}>
                <Typography type="subheading">
                  Tá na dúvida aí? Não se preocupe, deixe seu e-mail e fique sabendo de novos desafios!
                </Typography>

                  <SubscribeFrom  {...formProps} />

                <Typography type="caption">
                  worknenjoy, Inc.

                  Borgergade, 26 sal 4 lej 3

                  København, Hovedstaden 1300 DK
                </Typography>
              </Grid>
            </Grid>
            <Divider className={classes.spacedTop}/>
            <Grid container spacing={24}>
              <Grid item xs={12} sm={2}>

              </Grid>
            </Grid>

    );
  }
}

/*
<Button raised color="primary" className={classes.button}>
  Começar agora!
</Button>

 <Grid item xs={12}>

 <Typography type="subheading" gutterBottom noWrap>
 Ou conecte com algumas dessas contas
 </Typography>
 <Button raised size="small" color="accent" className={classes.altButton}>
  Github
 </Button>
 <Button raised size="small" color="accent" className={classes.altButton}>
  Gitlab
 </Button>
 <Button raised size="small" color="accent" className={classes.altButton}>
  Bitbucket
 </Button>

 </Grid>
*/

Welcome.propTypes = {
  classes: PropTypes.object.isRequired,
};

export default withStyles(styles)(Welcome);
<|endoftext|>


<commit_before>$(document).ready(function(){
    $(".toggler").click(function(e){
        e.preventDefault();
        $('.round'+$(this).attr('data-betwit-matchid')).toggle(1000);
        $('html, body').animate({ scrollTop: $("#"+$(this).attr('data-betwit-matchid')).offset().top}, 1000);
    });
});

<commit_msg>[FIX] display bet detail for a match : define an offset on srolltop<commit_after>$(document).ready(function(){
    $(".toggler").click(function(e){
        e.preventDefault();
        $('.round'+$(this).attr('data-betwit-matchid')).toggle(1000);
        $('html, body').animate({ scrollTop: $("#"+$(this).attr('data-betwit-matchid')).offset().top-51}, 1000);
    });
});

<|endoftext|>


<commit_before>//
// nntpchan.js -- frontend ui niceness
//

// insert a backlink for a post given its short hash
function nntpchan_backlink(shorthash)
{
  var elem = document.getElementById("postform_message");
  if ( elem )
  {
    elem.value += ">>" + shorthash + "\n";
  }
}
<commit_msg>ammend nnptchan.js to use old style shorthashes<commit_after>//
// nntpchan.js -- frontend ui niceness
//

// insert a backlink for a post given its short hash
function nntpchan_backlink(shorthash)
{
  var elem = document.getElementById("postform_message");
  if ( elem )
  {
    elem.value += ">>" + shorthash.substr(2,10) + "\n";
  }
}
<|endoftext|>


<commit_before>/**
 * @file TreeSelect component
 * @author liangxiaojun(liangxiaojun@derbysoft.com)
 */

import React, {Component} from 'react';
import PropTypes from 'prop-types';
import classNames from 'classnames';

import Dropdown from '../Dropdown';
import Tree from '../Tree';
import Theme from '../Theme';
import Tip from '../Tip';

import SelectMode from '../_statics/SelectMode';

import Util from '../_vendors/Util';
import Event from '../_vendors/Event';
import TreeCalculation from '../_vendors/TreeCalculation';

class TreeSelect extends Component {

    static SelectMode = SelectMode;
    static Theme = Theme;
    static Position = Dropdown.Position;

    constructor(props, ...restArgs) {

        super(props, ...restArgs);

        this.state = {
            value: props.value,
            popupVisible: false,
            path: props.selectMode === SelectMode.SINGLE_SELECT ?
                TreeCalculation.calPath(props.value, props.data, props) : undefined
        };

    }

    closePopup = () => {
        this.refs.dropdown && this.refs.dropdown.closePopup();
    };

    getTriggerValue = (props = this.props) => {

        const {data, selectMode, placeholder, triggerRenderer, renderer, displayField, valueField} = props,
            {value, path} = this.state,
            isMultiSelect = selectMode === SelectMode.MULTI_SELECT;

        if (triggerRenderer) {
            return typeof triggerRenderer === 'function' ? triggerRenderer(value, path) : triggerRenderer;
        }

        if (!value) {
            return placeholder;
        }

        if (isMultiSelect) {
            return value.length > 0 ?
                value.length + ' selected'
                :
                placeholder;
        }

        let result = [];

        function addNode(node, i) {
            result.push(
                renderer ?

                        {renderer(node, path && path.slice(0, i + 1))}

                    :
                    Util.getTextByDisplayField(node, displayField, valueField)
            );
        }

        addNode(data, -1);

        if (path) {
            for (let i = 0, len = path.length; i < len; i++) {

                result.push(

                );

                addNode(path[i].node, i);

            }
        }

        return result;

    };

    nodeSelectHandler = (value, path) => {

        if (this.props.selectMode !== SelectMode.SINGLE_SELECT) {
            return;
        }

        this.setState({
            path
        });

    };

    changeHandler = value => {

        const {autoClose} = this.props;
        if (autoClose) {
            this.closePopup();
        }

        this.setState({
            value
        }, () => {
            const {onChange} = this.props;
            onChange && onChange(value);
        });

    };

    popupClosedHandler = e => {
        this.setState({
            popupVisible: false
        }, () => {
            const {onClosePopup} = this.props;
            onClosePopup && onClosePopup(e);
        });
    };

    componentWillReceiveProps(nextProps) {
        if (nextProps.value !== this.props.value) {
            this.setState({
                value: nextProps.value
            });
        }
    }

    render() {

        const {

                className, triggerClassName, popupClassName, style, name, popupTheme, data, renderer,
                selectMode, valueField, displayField, descriptionField, triggerRenderer,
                isSelectRecursive, allowCollapse, onNodeClick, popupChildren,
                collapsedIconCls, expandedIconCls, radioUncheckedIconCls, radioCheckedIconCls,
                checkboxUncheckedIconCls, checkboxCheckedIconCls, checkboxIndeterminateIconCls,

                ...restProps

            } = this.props,
            {value, popupVisible} = this.state,

            wrapperClassName = classNames('tree-select', {
                [className]: className
            }),

            selectTriggerClassName = classNames({
                activated: popupVisible,
                empty: !triggerRenderer && !value,
                [triggerClassName]: triggerClassName
            }),
            selectPopupClassName = classNames('tree-select-popup', {
                [popupClassName]: popupClassName
            });

        return (

                {
                    name ?
                        <input type="hidden"
                               name={name}
                               value={Util.getValueByValueField(value, valueField, displayField)}/>
                        :
                        null
                }

                <Dropdown {...restProps}
                          ref="dropdown"
                          triggerClassName={selectTriggerClassName}
                          popupClassName={selectPopupClassName}
                          popupTheme={popupTheme}
                          triggerValue={this.getTriggerValue()}
                          onClosePopup={this.popupClosedHandler}>

 Event.wheelHandler(e, this.props)}>

                        <Tree className="tree-select-list"
                              theme={popupTheme}
                              selectMode={selectMode}
                              data={data}
                              value={value}
                              valueField={valueField}
                              displayField={displayField}
                              descriptionField={descriptionField}
                              isSelectRecursive={isSelectRecursive}
                              allowCollapse={allowCollapse}
                              collapsedIconCls={collapsedIconCls}
                              expandedIconCls={expandedIconCls}
                              radioUncheckedIconCls={radioUncheckedIconCls}
                              radioCheckedIconCls={radioCheckedIconCls}
                              checkboxUncheckedIconCls={checkboxUncheckedIconCls}
                              checkboxCheckedIconCls={checkboxCheckedIconCls}
                              checkboxIndeterminateIconCls={checkboxIndeterminateIconCls}
                              renderer={renderer}
                              onNodeClick={onNodeClick}
                              onNodeSelect={this.nodeSelectHandler}
                              onChange={this.changeHandler}/>

                    {popupChildren}

                </Dropdown>

        );

    }
}

TreeSelect.propTypes = {

    /**
     * The CSS class name of the root element.
     */
    className: PropTypes.string,

    /**
     * The CSS class name of the trigger element.
     */
    triggerClassName: PropTypes.string,

    /**
     * The class name of the popup element.
     */
    popupClassName: PropTypes.string,

    /**
     * Override the styles of the root element.
     */
    style: PropTypes.object,

    /**
     * Override the styles of the popup element.
     */
    popupStyle: PropTypes.object,

    /**
     * The theme.
     */
    theme: PropTypes.oneOf(Util.enumerateValue(Theme)),

    /**
     * The theme.
     */
    popupTheme: PropTypes.oneOf(Util.enumerateValue(Theme)),

    position: PropTypes.oneOf(Util.enumerateValue(Dropdown.Position)),

    /**
     * The name of the dropDownSelect.
     */
    name: PropTypes.string,

    /**
     * The value of the dropDownSelect.
     */
    value: PropTypes.any,

    /**
     * The placeholder of the dropDownSelect.
     */
    placeholder: PropTypes.string,

    triggerValue: PropTypes.string,

    rightIconCls: PropTypes.string,

    /**
     * The options data.
     */
    data: PropTypes.shape({

        /**
         * The CSS class name of the tree node.
         */
        className: PropTypes.string,

        /**
         * Override the styles of the tree node.
         */
        style: PropTypes.object,

        /**
         * The theme of the tree button.
         */
        theme: PropTypes.oneOf(Util.enumerateValue(Theme)),

        /**
         * The text value of the tree button.Type can be string or number.
         */
        value: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),

        /**
         * The tree node's display text. Type can be string, number or bool.
         */
        text: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),

        /**
         * The desc value of the tree node. Type can be string or number.
         */
        desc: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),

        /**
         * If true,the tree node will be disabled.
         */
        disabled: PropTypes.bool,

        /**
         * If true,the button will be have loading effect.
         */
        isLoading: PropTypes.bool,

        /**
         * Use this property to display an icon. It will display on the left.
         */
        iconCls: PropTypes.string,

        /**
         * Use this property to display an icon. It will display on the right.
         */
        rightIconCls: PropTypes.string,

        /**
         * The message of tip.
         */
        title: PropTypes.string,

        children: PropTypes.array,

        /**
         * You can create a complicated renderer callback instead of value and desc prop.
         */
        itemRenderer: PropTypes.func,

        /**
         * Callback function fired when a tree node touch-tapped.
         */
        onClick: PropTypes.func

    }),

    /**
     * The invalid message of dropDownSelect.
     */
    invalidMsg: PropTypes.string,

    /**
     * If true,the dropDownSelect will be disabled.
     */
    disabled: PropTypes.bool,

    /**
     * The select mode of listItem.Can be normal,checkbox.
     */
    selectMode: PropTypes.oneOf(Util.enumerateValue(SelectMode)),

    /**
     * The value field name in data. (default: "value")
     */
    valueField: PropTypes.string,

    /**
     * The display field name in data. (default: "text")
     */
    displayField: PropTypes.string,

    /**
     * The description field name in data. (default: "desc")
     */
    descriptionField: PropTypes.string,

    /**
     * The message of the dropDownSelect.
     */
    infoMsg: PropTypes.string,

    /**
     * Use this function to format the options's text.
     */
    textFormat: PropTypes.func,

    /**
     * If true,the drop-down box automatically closed after selection.
     */
    autoClose: PropTypes.bool,

    shouldPreventContainerScroll: PropTypes.bool,
    isSelectRecursive: PropTypes.bool,
    allowCollapse: PropTypes.bool,
    collapsedIconCls: PropTypes.string,
    expandedIconCls: PropTypes.string,
    radioUncheckedIconCls: PropTypes.string,
    radioCheckedIconCls: PropTypes.string,
    checkboxUncheckedIconCls: PropTypes.string,
    checkboxCheckedIconCls: PropTypes.string,
    checkboxIndeterminateIconCls: PropTypes.string,

    popupChildren: PropTypes.any,

    renderer: PropTypes.func,

    triggerRenderer: PropTypes.oneOfType([PropTypes.number, PropTypes.string, PropTypes.func]),

    /**
     * Callback function fired when the button is touch-tapped.
     */
    onNodeClick: PropTypes.func,

    /**
     * Callback function fired when the popup is closed.
     */
    onClosePopup: PropTypes.func,

    /**
     * Callback function fired when a menu item is selected.
     */
    onChange: PropTypes.func,

    onWheel: PropTypes.func,
    onFocus: PropTypes.func,
    onBlur: PropTypes.func,
    onMouseOver: PropTypes.func,
    onMouseOut: PropTypes.func

};

TreeSelect.defaultProps = {

    theme: Theme.DEFAULT,
    popupTheme: Theme.DEFAULT,

    position: Dropdown.Position.LEFT,
    placeholder: 'Please select ...',
    rightIconCls: 'fas fa-angle-down',
    disabled: false,
    selectMode: SelectMode.SINGLE_SELECT,

    valueField: 'value',
    displayField: 'text',
    descriptionField: 'desc',

    autoClose: true,

    shouldPreventContainerScroll: true,
    isSelectRecursive: false,
    allowCollapse: true

};

export default TreeSelect;<commit_msg>update TreeSelect<commit_after>/**
 * @file TreeSelect component
 * @author liangxiaojun(liangxiaojun@derbysoft.com)
 */

import React, {Component} from 'react';
import PropTypes from 'prop-types';
import classNames from 'classnames';

import Dropdown from '../Dropdown';
import Tree from '../Tree';
import Theme from '../Theme';
import Tip from '../Tip';

import SelectMode from '../_statics/SelectMode';

import Util from '../_vendors/Util';
import Event from '../_vendors/Event';
import TreeCalculation from '../_vendors/TreeCalculation';
import ComponentUtil from '../_vendors/ComponentUtil';

class TreeSelect extends Component {

    static SelectMode = SelectMode;
    static Theme = Theme;
    static Position = Dropdown.Position;

    constructor(props, ...restArgs) {

        super(props, ...restArgs);

        this.state = {
            value: props.value,
            popupVisible: false,
            path: props.selectMode === SelectMode.SINGLE_SELECT ?
                TreeCalculation.calPath(props.value, props.data, props) : undefined
        };

    }

    closePopup = () => {
        this.refs.dropdown && this.refs.dropdown.closePopup();
    };

    getTriggerValue = (props = this.props) => {

        const {data, selectMode, placeholder, triggerRenderer, renderer, displayField, valueField} = props,
            {value, path} = this.state,
            isMultiSelect = selectMode === SelectMode.MULTI_SELECT;

        if (triggerRenderer) {
            return typeof triggerRenderer === 'function' ? triggerRenderer(value, path) : triggerRenderer;
        }

        if (!value) {
            return placeholder;
        }

        if (isMultiSelect) {
            return value.length > 0 ?
                value.length + ' selected'
                :
                placeholder;
        }

        let result = [];

        function addNode(node, i) {
            result.push(
                renderer ?

                        {renderer(node, path && path.slice(0, i + 1))}

                    :
                    Util.getTextByDisplayField(node, displayField, valueField)
            );
        }

        addNode(data, -1);

        if (path) {
            for (let i = 0, len = path.length; i < len; i++) {

                result.push(

                );

                addNode(path[i].node, i);

            }
        }

        return result;

    };

    nodeSelectHandler = (value, path) => {

        if (this.props.selectMode !== SelectMode.SINGLE_SELECT) {
            return;
        }

        this.setState({
            path
        });

    };

    changeHandler = value => {

        const {autoClose} = this.props;
        if (autoClose) {
            this.closePopup();
        }

        this.setState({
            value
        }, () => {
            const {onChange} = this.props;
            onChange && onChange(value);
        });

    };

    popupClosedHandler = e => {
        this.setState({
            popupVisible: false
        }, () => {
            const {onClosePopup} = this.props;
            onClosePopup && onClosePopup(e);
        });
    };

    static getDerivedStateFromProps(props, state) {
        return {
            prevProps: props,
            value: ComponentUtil.getDerivedState(props, state, 'value')
        };
    }

    render() {

        const {

                className, triggerClassName, popupClassName, style, name, popupTheme, data, renderer,
                selectMode, valueField, displayField, descriptionField, triggerRenderer,
                isSelectRecursive, allowCollapse, onNodeClick, popupChildren,
                collapsedIconCls, expandedIconCls, radioUncheckedIconCls, radioCheckedIconCls,
                checkboxUncheckedIconCls, checkboxCheckedIconCls, checkboxIndeterminateIconCls,

                ...restProps

            } = this.props,
            {value, popupVisible} = this.state,

            wrapperClassName = classNames('tree-select', {
                [className]: className
            }),

            selectTriggerClassName = classNames({
                activated: popupVisible,
                empty: !triggerRenderer && !value,
                [triggerClassName]: triggerClassName
            }),
            selectPopupClassName = classNames('tree-select-popup', {
                [popupClassName]: popupClassName
            });

        return (

                {
                    name ?
                        <input type="hidden"
                               name={name}
                               value={Util.getValueByValueField(value, valueField, displayField)}/>
                        :
                        null
                }

                <Dropdown {...restProps}
                          ref="dropdown"
                          triggerClassName={selectTriggerClassName}
                          popupClassName={selectPopupClassName}
                          popupTheme={popupTheme}
                          triggerValue={this.getTriggerValue()}
                          onClosePopup={this.popupClosedHandler}>

 Event.wheelHandler(e, this.props)}>

                        <Tree className="tree-select-list"
                              theme={popupTheme}
                              selectMode={selectMode}
                              data={data}
                              value={value}
                              valueField={valueField}
                              displayField={displayField}
                              descriptionField={descriptionField}
                              isSelectRecursive={isSelectRecursive}
                              allowCollapse={allowCollapse}
                              collapsedIconCls={collapsedIconCls}
                              expandedIconCls={expandedIconCls}
                              radioUncheckedIconCls={radioUncheckedIconCls}
                              radioCheckedIconCls={radioCheckedIconCls}
                              checkboxUncheckedIconCls={checkboxUncheckedIconCls}
                              checkboxCheckedIconCls={checkboxCheckedIconCls}
                              checkboxIndeterminateIconCls={checkboxIndeterminateIconCls}
                              renderer={renderer}
                              onNodeClick={onNodeClick}
                              onNodeSelect={this.nodeSelectHandler}
                              onChange={this.changeHandler}/>

                    {popupChildren}

                </Dropdown>

        );

    }
}

TreeSelect.propTypes = {

    /**
     * The CSS class name of the root element.
     */
    className: PropTypes.string,

    /**
     * The CSS class name of the trigger element.
     */
    triggerClassName: PropTypes.string,

    /**
     * The class name of the popup element.
     */
    popupClassName: PropTypes.string,

    /**
     * Override the styles of the root element.
     */
    style: PropTypes.object,

    /**
     * Override the styles of the popup element.
     */
    popupStyle: PropTypes.object,

    /**
     * The theme.
     */
    theme: PropTypes.oneOf(Util.enumerateValue(Theme)),

    /**
     * The theme.
     */
    popupTheme: PropTypes.oneOf(Util.enumerateValue(Theme)),

    position: PropTypes.oneOf(Util.enumerateValue(Dropdown.Position)),

    /**
     * The name of the dropDownSelect.
     */
    name: PropTypes.string,

    /**
     * The value of the dropDownSelect.
     */
    value: PropTypes.any,

    /**
     * The placeholder of the dropDownSelect.
     */
    placeholder: PropTypes.string,

    triggerValue: PropTypes.string,

    rightIconCls: PropTypes.string,

    /**
     * The options data.
     */
    data: PropTypes.shape({

        /**
         * The CSS class name of the tree node.
         */
        className: PropTypes.string,

        /**
         * Override the styles of the tree node.
         */
        style: PropTypes.object,

        /**
         * The theme of the tree button.
         */
        theme: PropTypes.oneOf(Util.enumerateValue(Theme)),

        /**
         * The text value of the tree button.Type can be string or number.
         */
        value: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),

        /**
         * The tree node's display text. Type can be string, number or bool.
         */
        text: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),

        /**
         * The desc value of the tree node. Type can be string or number.
         */
        desc: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),

        /**
         * If true,the tree node will be disabled.
         */
        disabled: PropTypes.bool,

        /**
         * If true,the button will be have loading effect.
         */
        isLoading: PropTypes.bool,

        /**
         * Use this property to display an icon. It will display on the left.
         */
        iconCls: PropTypes.string,

        /**
         * Use this property to display an icon. It will display on the right.
         */
        rightIconCls: PropTypes.string,

        /**
         * The message of tip.
         */
        title: PropTypes.string,

        children: PropTypes.array,

        /**
         * You can create a complicated renderer callback instead of value and desc prop.
         */
        itemRenderer: PropTypes.func,

        /**
         * Callback function fired when a tree node touch-tapped.
         */
        onClick: PropTypes.func

    }),

    /**
     * The invalid message of dropDownSelect.
     */
    invalidMsg: PropTypes.string,

    /**
     * If true,the dropDownSelect will be disabled.
     */
    disabled: PropTypes.bool,

    /**
     * The select mode of listItem.Can be normal,checkbox.
     */
    selectMode: PropTypes.oneOf(Util.enumerateValue(SelectMode)),

    /**
     * The value field name in data. (default: "value")
     */
    valueField: PropTypes.string,

    /**
     * The display field name in data. (default: "text")
     */
    displayField: PropTypes.string,

    /**
     * The description field name in data. (default: "desc")
     */
    descriptionField: PropTypes.string,

    /**
     * The message of the dropDownSelect.
     */
    infoMsg: PropTypes.string,

    /**
     * Use this function to format the options's text.
     */
    textFormat: PropTypes.func,

    /**
     * If true,the drop-down box automatically closed after selection.
     */
    autoClose: PropTypes.bool,

    shouldPreventContainerScroll: PropTypes.bool,
    isSelectRecursive: PropTypes.bool,
    allowCollapse: PropTypes.bool,
    collapsedIconCls: PropTypes.string,
    expandedIconCls: PropTypes.string,
    radioUncheckedIconCls: PropTypes.string,
    radioCheckedIconCls: PropTypes.string,
    checkboxUncheckedIconCls: PropTypes.string,
    checkboxCheckedIconCls: PropTypes.string,
    checkboxIndeterminateIconCls: PropTypes.string,

    popupChildren: PropTypes.any,

    renderer: PropTypes.func,

    triggerRenderer: PropTypes.oneOfType([PropTypes.number, PropTypes.string, PropTypes.func]),

    /**
     * Callback function fired when the button is touch-tapped.
     */
    onNodeClick: PropTypes.func,

    /**
     * Callback function fired when the popup is closed.
     */
    onClosePopup: PropTypes.func,

    /**
     * Callback function fired when a menu item is selected.
     */
    onChange: PropTypes.func,

    onWheel: PropTypes.func,
    onFocus: PropTypes.func,
    onBlur: PropTypes.func,
    onMouseOver: PropTypes.func,
    onMouseOut: PropTypes.func

};

TreeSelect.defaultProps = {

    theme: Theme.DEFAULT,
    popupTheme: Theme.DEFAULT,

    position: Dropdown.Position.LEFT,
    placeholder: 'Please select ...',
    rightIconCls: 'fas fa-angle-down',
    disabled: false,
    selectMode: SelectMode.SINGLE_SELECT,

    valueField: 'value',
    displayField: 'text',
    descriptionField: 'desc',

    autoClose: true,

    shouldPreventContainerScroll: true,
    isSelectRecursive: false,
    allowCollapse: true

};

export default TreeSelect;<|endoftext|>


<commit_before>#!/usr/bin/env node
//#############################################################################
// @author: Facundo Victor
// @licence: MIT
// @description: Script that allows to do a backup of your jsFiddles to disk.
//#############################################################################

var commander = require('commander');
var chalk = require('chalk');
var https = require('https');
var Promise = require('bluebird');
var cheerio = require('cheerio');
var url_parser = require('url');
var fs = require('fs');
Promise.promisifyAll(fs);

//#############################################################################

commander
	.version('0.0.1')
	.option('-u, --user <user>', 'Save all the users fiddles')
	.option('-l, --link <url>', 'Url of the fiddle to save')
	.option('-o, --output <path>', 'Target path to download the data')
	.option('-c, --compressed', 'Compress the spaces of the HTML output')
	.option('-v, --verbose', 'Verbose output')
	.parse(process.argv);

//#############################################################################
// Print helpers

function logIfVerbose(str, error){
	if (commander.verbose){
		if (error){
			console.error(str);
		}else{
			console.log(chalk.bgGreen(str));
		}
	}
}

function printError(str){
	console.error(chalk.red(str));
}

//#############################################################################

function mkdirp (path) {
	Promise.bind(this)
		.then( function(){
			fs.mkdir(path)
		}).then( function(){
			logIfVerbose('Dir '+path+' created.');
		}).catch( function(error){
			if ( error.code != 'EEXIST' ) throw error;
		});
}

function isCommand(str){
	return /^show$|^embed$/.test(str);
}

//#############################################################################
// HTTPS Requests

function getListOfFiddles(user){
	return new Promise(function (resolve, reject){
		var complete_path = "/api/user/"+user+
     "/demo/list.json?callback=Api&sort=framework&start=0&limit=50000";

		var options = {
			hostname: 'jsfiddle.net',
			port: 443,
			method: 'GET',
			path: complete_path
		};

		var request = https.request(options, function (res){
			res.setEncoding('utf8');
			body = '';
			res.on('data', function (chunk) {
				logIfVerbose('Retreive chunk');
				body += chunk;
			});
			res.on('end', function () {
				logIfVerbose('End request');
				var jsonSource = body.substring(4,body.length - 3);
				var data = JSON.parse(jsonSource);
				if (data.status == 'ok'){
					logIfVerbose('Parsed response..');
					resolve(data.list);
				} else {
					logIfVerbose('JSFiddle API error..',true);
					reject(data);
				}
			});
		});

		request.on('error', function(error){
			logIfVerbose(error, true);
			reject(error);
		});
		request.write('');
		request.end();
	});
}

function getCompletePath(fiddle_code, user){
	var complete_path = '/';
	if (user != null){
		complete_path += user +'/';
	}
	if (fiddle_code != null){
		complete_path += fiddle_code +'/show/light/';
	}
	return complete_path;
}

function makeHttpRequest(fiddle_code, user){
	return new Promise(function (resolve, reject){
		var complete_path = getCompletePath(fiddle_code, user);
		var options = {
			hostname: 'jsfiddle.net',
			port: 443,
			method: 'GET',
			path: complete_path,
			headers: {
				'Referer': 'https://jsfiddle.net' + complete_path
			}
		};

		var request = https.request(options, function (res){
			res.setEncoding('utf8');
			body = '';
			res.on('data', function (chunk) {
				logIfVerbose('Retreive chunk');
				body += chunk;
			});
			res.on('end', function () {
				logIfVerbose('End request');
				resolve(body);
			});
		});

		request.on('error', function(error){
			logIfVerbose(error, true);
			reject(error);
		});
		request.write('');
		request.end();
	});
}

//#############################################################################

function insertDescription(html_raw, fiddle_data){
	return new Promise(function (resolve, reject){
		if (html_raw.length > 0){
			config = {
				normalizeWhitespace: commander.compressed
			};
			$ = cheerio.load(html_raw, config);

			if (fiddle_data){
				$('head').append("<!-- Title: "+fiddle_data.title+" -->");
				$('head').append("<!-- Author: "+fiddle_data.author+" -->");
				$('head').append("<!-- Description: "+fiddle_data.description+" -->");
				$('head').append("<!-- Framework: "+fiddle_data.framework+" -->");
				$('head').append("<!-- Version: "+fiddle_data.veresion+" -->");
				$('head').append("<!-- Latest_version: "+fiddle_data.latest_version+" -->");
				$('head').append("<!-- Url: "+fiddle_data.url+" -->");
				$('head').append("<!-- Created date: "+fiddle_data.created+" -->");
			}
			resolve($.html());
		} else {
			reject(new Error('Empty html'));
		}
	});
}

function loadDataFromUrl(url){
	return new Promise(function (resolve, reject){
		if (typeof url == 'string' && (url.indexOf('/') > 0)){
			var data = {};
			url_parts = url_parser.parse(url);
			path_parts = url_parts.path.split('/');

			if (path_parts.length > 1){
				amount_of_parts = path_parts.length - 1; // Minus the first slash

				if (amount_of_parts == 1){
					// Only one argument (fiddle_id)
					data.fiddle_code = path_parts[1];
					logIfVerbose(	'Detected single fiddle url..')
				} else {
					// Could bee user/fiddle_id or fiddle_id/command
					if (isCommand(path_parts[2])){
						data.fiddle_code = path_parts[1];
						logIfVerbose(	'Detected fiddle and command url..')
					} else {
						data.user = path_parts[1];
						data.fiddle_code = path_parts[2];
						logIfVerbose(	'Detected user and fiddle url..')
					}
				}
				process.stdout.write('Detected fiddle code = '+chalk.green(data.fiddle_code));
				if (data.user != null){
					process.stdout.write(', from user = '+chalk.green(data.user));
				}
				process.stdout.write('\n');
				resolve(data);
			}else{
				reject(new Error('Invalid url'));
			}
		}else{
			reject(new Error('Invalid url'));
		}
	});
}

function recoverSingleFiddle(url, output, fiddle_data){
	Promise.bind(this)
		.then(function(){
			return loadDataFromUrl(url);
		}).then( function(data){
			output = output || global.cwd+'/'+data.fiddle_code+'.html'
			logIfVerbose('Output file = '+output);
			return makeHttpRequest(data.fiddle_code, data.user);
		}).then( function(fiddle) {
			return insertDescription(fiddle, fiddle_data);
		}).then( function(fiddle) {
			fs.writeFile(output, fiddle);
		}).catch( function (error) {
			printError(error);
			process.exit(1);
		});
}

function saveFiddles(list, output){
	global.cwd = process.cwd();
	var amount = list.length;
	var promises = [];
	for (var i=0; i < amount; i++) {
		var fiddle = list[i];
		var url = fiddle.url.substring(2, fiddle.url.length);
		logIfVerbose('Processing fiddle = '+url);
		promises.push(recoverSingleFiddle(url, null, fiddle));
	}
	return Promise.all(promises);
}

function recoverAllFiddles(user, output){
	var current_dir = process.cwd();
	Promise.bind(this)
		.then(function(){
			mkdirp(output);
		}).then(function(){
			return getListOfFiddles(user);
		}).then(function(list){
			process.chdir(output);
			return saveFiddles(list, output);
		}).then(function(result){
			console.log(chalk.green('Download terminated'));
		}).catch( function (error) {
			printError(error);
			process.exit(1);
		});
}

//#############################################################################

(function main (){
	global.cwd = process.cwd();
  if (commander.user){
		recoverAllFiddles(commander.user, commander.output || 'output_dir');
	} else if (commander.link) {
		recoverSingleFiddle(commander.link, commander.output);
	} else {
		commander.help();
	}
})();
<commit_msg>Fix bug on alraedy existent directory<commit_after>#!/usr/bin/env node
//#############################################################################
// @author: Facundo Victor
// @licence: MIT
// @description: Script that allows to do a backup of your jsFiddles to disk.
//#############################################################################

var commander = require('commander');
var chalk = require('chalk');
var https = require('https');
var Promise = require('bluebird');
var cheerio = require('cheerio');
var url_parser = require('url');
var fs = Promise.promisifyAll(require("fs"));

//#############################################################################

commander
	.version('0.0.1')
	.option('-u, --user <user>', 'Save all the users fiddles')
	.option('-l, --link <url>', 'Url of the fiddle to save')
	.option('-o, --output <path>', 'Target path to download the data')
	.option('-c, --compressed', 'Compress the spaces of the HTML output')
	.option('-v, --verbose', 'Verbose output')
	.parse(process.argv);

//#############################################################################
// Print helpers

function logIfVerbose(str, error){
	if (commander.verbose){
		if (error){
			console.error(str);
		}else{
			console.log(chalk.bgGreen(str));
		}
	}
}

function printError(str){
	console.error(chalk.red(str));
}

//#############################################################################

function mkdirp (path) {
	Promise.bind(this)
		.then( function(){
			return Promise.promisify(fs.mkdir)(path);
		}).then( function(){
			logIfVerbose('Dir '+path+' created.');
		}).catch( function(error){
			if ( error.code != 'EEXIST' ) throw error;
		});
}

function isCommand(str){
	return /^show$|^embed$/.test(str);
}

//#############################################################################
// HTTPS Requests

function getListOfFiddles(user){
	return new Promise(function (resolve, reject){
		var complete_path = "/api/user/"+user+
     "/demo/list.json?callback=Api&sort=framework&start=0&limit=50000";

		var options = {
			hostname: 'jsfiddle.net',
			port: 443,
			method: 'GET',
			path: complete_path
		};

		var request = https.request(options, function (res){
			res.setEncoding('utf8');
			body = '';
			res.on('data', function (chunk) {
				logIfVerbose('Retreive chunk');
				body += chunk;
			});
			res.on('end', function () {
				logIfVerbose('End request');
				var jsonSource = body.substring(4,body.length - 3);
				var data = JSON.parse(jsonSource);
				if (data.status == 'ok'){
					logIfVerbose('Parsed response..');
					resolve(data.list);
				} else {
					logIfVerbose('JSFiddle API error..',true);
					reject(data);
				}
			});
		});

		request.on('error', function(error){
			logIfVerbose(error, true);
			reject(error);
		});
		request.write('');
		request.end();
	});
}

function getCompletePath(fiddle_code, user){
	var complete_path = '/';
	if (user != null){
		complete_path += user +'/';
	}
	if (fiddle_code != null){
		complete_path += fiddle_code +'/show/light/';
	}
	return complete_path;
}

function makeHttpRequest(fiddle_code, user){
	return new Promise(function (resolve, reject){
		var complete_path = getCompletePath(fiddle_code, user);
		var options = {
			hostname: 'jsfiddle.net',
			port: 443,
			method: 'GET',
			path: complete_path,
			headers: {
				'Referer': 'https://jsfiddle.net' + complete_path
			}
		};

		var request = https.request(options, function (res){
			res.setEncoding('utf8');
			body = '';
			res.on('data', function (chunk) {
				logIfVerbose('Retreive chunk');
				body += chunk;
			});
			res.on('end', function () {
				logIfVerbose('End request');
				resolve(body);
			});
		});

		request.on('error', function(error){
			logIfVerbose(error, true);
			reject(error);
		});
		request.write('');
		request.end();
	});
}

//#############################################################################

function insertDescription(html_raw, fiddle_data){
	return new Promise(function (resolve, reject){
		if (html_raw.length > 0){
			config = {
				normalizeWhitespace: commander.compressed
			};
			$ = cheerio.load(html_raw, config);

			if (fiddle_data){
				$('head').append("<!-- Title: "+fiddle_data.title+" -->");
				$('head').append("<!-- Author: "+fiddle_data.author+" -->");
				$('head').append("<!-- Description: "+fiddle_data.description+" -->");
				$('head').append("<!-- Framework: "+fiddle_data.framework+" -->");
				$('head').append("<!-- Version: "+fiddle_data.veresion+" -->");
				$('head').append("<!-- Latest_version: "+fiddle_data.latest_version+" -->");
				$('head').append("<!-- Url: "+fiddle_data.url+" -->");
				$('head').append("<!-- Created date: "+fiddle_data.created+" -->");
			}
			resolve($.html());
		} else {
			reject(new Error('Empty html'));
		}
	});
}

function loadDataFromUrl(url){
	return new Promise(function (resolve, reject){
		if (typeof url == 'string' && (url.indexOf('/') > 0)){
			var data = {};
			url_parts = url_parser.parse(url);
			path_parts = url_parts.path.split('/');

			if (path_parts.length > 1){
				amount_of_parts = path_parts.length - 1; // Minus the first slash

				if (amount_of_parts == 1){
					// Only one argument (fiddle_id)
					data.fiddle_code = path_parts[1];
					logIfVerbose(	'Detected single fiddle url..')
				} else {
					// Could bee user/fiddle_id or fiddle_id/command
					if (isCommand(path_parts[2])){
						data.fiddle_code = path_parts[1];
						logIfVerbose(	'Detected fiddle and command url..')
					} else {
						data.user = path_parts[1];
						data.fiddle_code = path_parts[2];
						logIfVerbose(	'Detected user and fiddle url..')
					}
				}
				process.stdout.write('Detected fiddle code = '+chalk.green(data.fiddle_code));
				if (data.user != null){
					process.stdout.write(', from user = '+chalk.green(data.user));
				}
				process.stdout.write('\n');
				resolve(data);
			}else{
				reject(new Error('Invalid url'));
			}
		}else{
			reject(new Error('Invalid url'));
		}
	});
}

function recoverSingleFiddle(url, output, fiddle_data){
	Promise.bind(this)
		.then(function(){
			return loadDataFromUrl(url);
		}).then( function(data){
			output = output || global.cwd+'/'+data.fiddle_code+'.html'
			logIfVerbose('Output file = '+output);
			return makeHttpRequest(data.fiddle_code, data.user);
		}).then( function(fiddle) {
			return insertDescription(fiddle, fiddle_data);
		}).then( function(fiddle) {
			fs.writeFile(output, fiddle);
		}).catch( function (error) {
			printError(error);
			process.exit(1);
		});
}

function saveFiddles(list, output){
	global.cwd = process.cwd();
	var amount = list.length;
	var promises = [];
	for (var i=0; i < amount; i++) {
		var fiddle = list[i];
		var url = fiddle.url.substring(2, fiddle.url.length);
		logIfVerbose('Processing fiddle = '+url);
		promises.push(recoverSingleFiddle(url, null, fiddle));
	}
	return Promise.all(promises);
}

function recoverAllFiddles(user, output){
	var current_dir = process.cwd();
	Promise.bind(this)
		.then(function(){
			mkdirp(output);
		}).then(function(){
			return getListOfFiddles(user);
		}).then(function(list){
			process.chdir(output);
			return saveFiddles(list, output);
		}).then(function(result){
			console.log(chalk.green('Download terminated'));
		}).catch( function (error) {
			printError(error);
			process.exit(1);
		});
}

//#############################################################################

(function main (){
	global.cwd = process.cwd();
  if (commander.user){
		recoverAllFiddles(commander.user, commander.output || 'output_dir');
	} else if (commander.link) {
		recoverSingleFiddle(commander.link, commander.output);
	} else {
		commander.help();
	}
})();
<|endoftext|>


<commit_before>const APP_VERSION = require("./package.json").version;
const PROFILE = process.env.PROFILE || 'dev';
const profileConfig = require('./webpack-profiles.config')[PROFILE];

const path = require('path');
const webpack = require('webpack');
const merge = require('webpack-merge');

const CommonsChunkPlugin = require('webpack/lib/optimize/CommonsChunkPlugin');
const ChunkHashPlugin = require('webpack-chunk-hash');
const ExtractTextPlugin = require('extract-text-webpack-plugin');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const CopyWebpackPlugin = require('copy-webpack-plugin');
const CleanWebpackPlugin = require('clean-webpack-plugin');

const { AotPlugin } = require('@ngtools/webpack');

const PATHS = { };
PATHS.root         = path.join(__dirname, './');
PATHS.dist         = path.join(PATHS.root, `dist/${PROFILE}`);
PATHS.node_modules = path.join(PATHS.root, 'node_modules');
PATHS.app          = path.join(PATHS.root, 'app');

const baseOutputName = `[name]-${APP_VERSION}-[chunkhash:12]`;
const extractCSS = new ExtractTextPlugin({
   filename: `${baseOutputName}.css`
});

const isInPath = (module, p, ignores) => {
   let inPath = false;
   if (module.userRequest) {
      inPath = (module.userRequest.indexOf(p) === 0);

      // Vérification des ignores
      if (inPath && ignores) {
         let hasIgnore = ignores.some((ignore) => {
            return (module.userRequest.indexOf(path.join(p, ignore)) === 0);
         });

         inPath = (hasIgnore ? false : inPath);
      }
   }

   return inPath;
};

let config = {
   devtool: false,

   entry: {
      'polyfills': path.join(PATHS.app, 'polyfills.ts'),
      'main': path.join(PATHS.app, 'main.ts')
   },

   output: {
      path: PATHS.dist,
      publicPath: '',
      filename: `${baseOutputName}.js`
   },

   resolve: {
      modules: ['node_modules'],
      extensions: ['.ts', '.js'],
      alias: {
         'app': PATHS.app
      }
   },

   module: {
      rules: [
         {
            test: /\.ts$/,
            loaders: ['@ngtools/webpack'],
            exclude: [/\.(spec|e2e)\.ts$/]
         },

         {
            test: /\.s?css$/,
            loader: extractCSS.extract({
               fallback: 'style-loader',
               use: ['css-loader', 'sass-loader']
            }),
            exclude: [/\.component\.s?css$/]
         },

         {
            test: /\.s?css$/,
            loaders: ['to-string-loader', 'css-loader', 'sass-loader'],
            include: [/\.component\.s?css$/]
         },

         { test: /\.json/, loader: 'json-loader' },
         { test: /\.html$/, loader: 'html-loader' },

         {
            test: /\.(png|jpe?g|gif|svg|woff2?|eot|ttf|otf)(\?.*)?$/,
            loader: 'file-loader',
            query: {
               name: `[path][name].[ext]`
            }
         }
      ]
   },

   plugins: [
      new webpack.NoEmitOnErrorsPlugin(),
      new ChunkHashPlugin(),

      new webpack.DefinePlugin({
         PROFILE_CONFIG: JSON.stringify(profileConfig)
      }),

      // Plugin AOT pour Angular
      new AotPlugin({
         tsConfigPath: './tsconfig.json',
         mainPath: "app/main.ts",
         skipCodeGeneration: (!profileConfig.production) // AOT really happens here (false = enabled)
      }),

      // Permet de séparer le code applicatif des librairies externes
      new CommonsChunkPlugin({
         name: 'vendor-modules',
         chunks: ['main'],
         minChunks: (module) => isInPath(module, PATHS.node_modules, ['@angular'])
      }),

      // Sortir Angular hors du vendor-modules
      new CommonsChunkPlugin({
         name: 'vendor-angular',
         chunks: ['vendor-modules', 'main'],
         minChunks: (module) => isInPath(module, path.join(PATHS.node_modules, '@angular'))
      }),

      // Faire un fichier pour les polyfills et un dernier pour la partie "webpack" (manifest)
      new CommonsChunkPlugin({
         names: ['polyfills', 'manifest']
      }),

      extractCSS,

      // Recopier tout sauf ce qui est déjà pris en compte
      new CopyWebpackPlugin([
         // Copie de la config avec un search-replace
         {
            from: 'app/resources/config/*.json',
            to: '',
            transform: (content) => {
               // Regex permettant de remplacer tous les @{xxx} par ce qui se trouve dans le profileConfig
               return content.toString().replace(/@\{(\w*?)}/g, (match, p1) => profileConfig[p1]);
            }
         },

         {
            from: 'app',
            to: 'app',
            ignore: ['*.ts', '*.scss', '*.css', '*.html']
         }
      ]),

      new HtmlWebpackPlugin({
         filename: 'index.html',
         template: 'app/index.html',
         favicon: 'app/favicon.png',
         inject: true,
         minify: false
      })
   ],

   stats: {
      colors: true,
      hash: false,
      version: false,
      assets: true,
      cached: false,
      modules: false,
      children: false,
      chunks: false,
      chunkModules: false,
      chunkOrigins: false,
      reasons: false,
      source: false,
      maxModules: 0
   }

};

if ('dev' === PROFILE) {
   config = merge(config, {
      devtool: 'cheap-module-eval-source-map',

      devServer: {
         port: 3000,
         inline: false,
         hot: false,
         stats: config.stats
      }
   });
}

else {
   config = merge(config, {
      plugins: [
         new webpack.optimize.UglifyJsPlugin({
            comments: false,
            beautify: false,
            sourceMap: false,
            mangle: {
               screw_ie8: true,
               keep_fnames: true
            },
            compress: {
               screw_ie8: true,
               warnings: false
            }
         }),

         new CleanWebpackPlugin([PATHS.dist])
      ]
   });
}

module.exports = config;
<commit_msg>AOT Configuration ! :-)<commit_after>const APP_VERSION = require("./package.json").version;
const PROFILE = process.env.PROFILE || 'dev';
const profileConfig = require('./webpack-profiles.config')[PROFILE];

const path = require('path');
const webpack = require('webpack');
const merge = require('webpack-merge');

const CommonsChunkPlugin = require('webpack/lib/optimize/CommonsChunkPlugin');
const ChunkHashPlugin = require('webpack-chunk-hash');
const ExtractTextPlugin = require('extract-text-webpack-plugin');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const CopyWebpackPlugin = require('copy-webpack-plugin');
const CleanWebpackPlugin = require('clean-webpack-plugin');

const { AotPlugin } = require('@ngtools/webpack');
const ENABLE_AOT = profileConfig.production;

const PATHS = { };
PATHS.root         = path.join(__dirname, './');
PATHS.dist         = path.join(PATHS.root, `dist/${PROFILE}`);
PATHS.node_modules = path.join(PATHS.root, 'node_modules');
PATHS.app          = path.join(PATHS.root, 'app');

const baseOutputName = `[name]-${APP_VERSION}-[chunkhash:12]`;
const extractCSS = new ExtractTextPlugin({
   filename: `${baseOutputName}.css`
});

const isInPath = (module, p, ignores) => {
   let inPath = false;
   if (module.userRequest) {
      inPath = (module.userRequest.indexOf(p) === 0);

      // Vérification des ignores
      if (inPath && ignores) {
         let hasIgnore = ignores.some((ignore) => {
            return (module.userRequest.indexOf(path.join(p, ignore)) === 0);
         });

         inPath = (hasIgnore ? false : inPath);
      }
   }

   return inPath;
};

let config = {
   devtool: false,

   entry: {
      'polyfills': path.join(PATHS.app, 'polyfills.ts'),
      'main': path.join(PATHS.app, 'main.ts')
   },

   output: {
      path: PATHS.dist,
      publicPath: '',
      filename: `${baseOutputName}.js`
   },

   resolve: {
      modules: ['node_modules'],
      extensions: ['.ts', '.js'],
      alias: {
         'app': PATHS.app
      }
   },

   module: {
      rules: [
         {
            test: /\.ts$/,
            loaders: ['@ngtools/webpack'],
            exclude: [/\.(spec|e2e)\.ts$/]
         },

         {
            test: /\.s?css$/,
            loader: extractCSS.extract({
               fallback: 'style-loader',
               use: ['css-loader', 'sass-loader']
            }),
            exclude: [/\.component\.s?css$/]
         },

         {
            test: /\.s?css$/,
            loaders: ['to-string-loader', 'css-loader', 'sass-loader'],
            include: [/\.component\.s?css$/]
         },

         { test: /\.json/, loader: 'json-loader' },
         { test: /\.html$/, loader: 'html-loader' },

         {
            test: /\.(png|jpe?g|gif|svg|woff2?|eot|ttf|otf)(\?.*)?$/,
            loader: 'file-loader',
            query: {
               name: `[path][name].[ext]`
            }
         }
      ]
   },

   plugins: [
      new webpack.NoEmitOnErrorsPlugin(),
      new ChunkHashPlugin(),

      new webpack.DefinePlugin({
         PROFILE_CONFIG: JSON.stringify(profileConfig)
      }),

      // Plugin AOT pour Angular
      new AotPlugin({
         tsConfigPath: './tsconfig.json',
         mainPath: "app/main.ts",
         skipCodeGeneration: !ENABLE_AOT // AOT really happens here (false = enabled)
      }),

      // Permet de séparer le code applicatif des librairies externes
      new CommonsChunkPlugin({
         name: 'vendor-modules',
         chunks: ['main'],
         minChunks: (module) => isInPath(module, PATHS.node_modules, ['@angular'])
      }),

      // Sortir Angular hors du vendor-modules
      new CommonsChunkPlugin({
         name: 'vendor-angular',
         chunks: ['vendor-modules', 'main'],
         minChunks: (module) => isInPath(module, path.join(PATHS.node_modules, '@angular'))
      }),

      // Faire un fichier pour les polyfills et un dernier pour la partie "webpack" (manifest)
      new CommonsChunkPlugin({
         names: ['polyfills', 'manifest']
      }),

      extractCSS,

      // Recopier tout sauf ce qui est déjà pris en compte
      new CopyWebpackPlugin([
         // Copie de la config avec un search-replace
         {
            from: 'app/resources/config/*.json',
            to: '',
            transform: (content) => {
               // Regex permettant de remplacer tous les @{xxx} par ce qui se trouve dans le profileConfig
               return content.toString().replace(/@\{(\w*?)}/g, (match, p1) => profileConfig[p1]);
            }
         },

         {
            from: 'app',
            to: 'app',
            ignore: ['*.ts', '*.scss', '*.css', '*.html']
         }
      ]),

      new HtmlWebpackPlugin({
         filename: 'index.html',
         template: 'app/index.html',
         favicon: 'app/favicon.png',
         inject: true,
         minify: false
      })
   ],

   stats: {
      colors: true,
      hash: false,
      version: false,
      assets: true,
      cached: false,
      modules: false,
      children: false,
      chunks: false,
      chunkModules: false,
      chunkOrigins: false,
      reasons: false,
      source: false,
      maxModules: 0
   }

};

if ('dev' === PROFILE) {
   config = merge(config, {
      devtool: 'cheap-module-eval-source-map',

      devServer: {
         port: 3000,
         inline: false,
         hot: false,
         stats: config.stats
      }
   });
}

else {
   config = merge(config, {
      plugins: [
         new webpack.optimize.UglifyJsPlugin({
            comments: false,
            beautify: false,
            sourceMap: false,
            mangle: {
               screw_ie8: true,
               keep_fnames: true
            },
            compress: {
               screw_ie8: true,
               warnings: false
            }
         }),

         new CleanWebpackPlugin([PATHS.dist])
      ]
   });
}

module.exports = config;
<|endoftext|>