<commit_before>import React, { Component } from 'react';
import ReactDOM from 'react-dom';
import {
  TitleBar,
  PushButton,
  TextField,
  Toolbar,
  Box,
  SegmentedControl,
  IndeterminateCircularProgressIndicator,
  Form,
  Label,
  Window
} from '../src/Main';

import WindowWindows from '../src/Window/Window.windows';
import TitleBarWindows from '../src/TitleBar/TitleBar.windows';

document.title = 'React Desktop Playground';
document.body.style.padding = '30px 40px';
document.body.style.background = 'white';
document.body.style.display = 'flex';
document.body.style.flexDirection = 'column';
document.body.style.alignItems = 'center';

document.body.innerHTML = `

`;

class Window1 extends Component {
  render() {
    return (
      <WindowWindows chrome style={{marginBottom: '60px'}}>
        <TitleBarWindows
          title="Store"
          controls
        />
      </WindowWindows>
    );
  }
}

/*class Window1 extends Component {
 render() {
 return (
 <Window chrome style={{marginBottom: '60px'}}>
 <TitleBar
 title="TitleBar"
 controls
 onClosePress={() => { alert('close'); }}
 onMinimizePress={() => { alert('minimize'); }}
 onResizePress={() => { alert('resize'); }}
 />
 </Window>
 <WindowWindows chrome style={{marginBottom: '60px'}}>
 </WindowWindows>
 );
 }
 }

*/

 class Window2 extends Component {
  constructor() {
    super();
    this.state = { selectedTab: 'login' };
  }

  render() {
    return (
      <Window chrome>
        <TitleBar title="TitleBar with Toolbar" controls>
          <Toolbar/>
        </TitleBar>

        <Box className="box">
          <SegmentedControl>
            <SegmentedControl.Item
              title="Selected"
              selected={this.state.selectedTab === 'login'}
              onPress={() => { this.setState({ selectedTab: 'login' }) }}
              className="form"
            >
              <Form onSubmit={() => { alert('form submitted'); }}>

                  There was an error submitting this form.

                <Form.Row>
                  Label:
                  <TextField defaultValue="" placeholder="TextField" style={{width: '200px'}}/>
                </Form.Row>

                <Form.Row>
                  Longer label:
                  <TextField defaultValue="" placeholder="TextField" style={{width: '200px'}}/>
                </Form.Row>

                <Form.Row>
                  <PushButton>PushButton</PushButton>
                  <PushButton onPress="submit" color="blue">PushButton Blue</PushButton>

                  <IndeterminateCircularProgressIndicator absolute/>
                </Form.Row>
              </Form>
            </SegmentedControl.Item>

            <SegmentedControl.Item
              title="Segmented"
              selected={this.state.selectedTab === 'segmented'}
              onPress={() => { this.setState({ selectedTab: 'segmented' }) }}
            >
              Hello World
            </SegmentedControl.Item>

            <SegmentedControl.Item
              title="Control"
              selected={this.state.selectedTab === 'control'}
              onPress={() => { this.setState({ selectedTab: 'control' }) }}
            >
              Goodbye World
            </SegmentedControl.Item>
          </SegmentedControl>
        </Box>
      </Window>
    );
  }
}

ReactDOM.render(<Window1/>, document.getElementById('window1'));
//ReactDOM.render(<Window2/>, document.getElementById('window2'));
<commit_msg>Added a windows window in the playground<commit_after>import React, { Component } from 'react';
import ReactDOM from 'react-dom';
import {
  TitleBar,
  PushButton,
  TextField,
  Toolbar,
  Box,
  SegmentedControl,
  IndeterminateCircularProgressIndicator,
  Form,
  Label,
  Windows,
  Window,
  Desktop
} from '../src/Main';

document.title = 'React Desktop Playground';
document.body.style.padding = '30px 40px';
document.body.style.background = 'white';
document.body.style.display = 'flex';
document.body.style.flexDirection = 'column';
document.body.style.alignItems = 'center';

document.body.innerHTML = `

`;

class Window1 extends Component {
  constructor() {
    super();
  }

  render() {
    return (
      <Windows.Window chrome style={{marginBottom: '60px'}}>
        <Windows.TitleBar
          title="TitleBar"
          controls
          onClosePress={() => { alert('close'); }}
          onMinimizePress={() => { alert('minimize'); }}
          onMaximizePress={() => { alert('mazimize'); }}
        />
      </Windows.Window>
    );
  }
}

class Window2 extends Component {
  constructor() {
    super();
    this.state = {selectedTab: 'login'};
  }

  render() {
    return (
      <Window chrome>
        <TitleBar title="TitleBar with Toolbar" controls>
          <Toolbar/>
        </TitleBar>

        <Box className="box">
          <SegmentedControl>
            <SegmentedControl.Item
              title="Selected"
              selected={this.state.selectedTab === 'login'}
              onPress={() => { this.setState({ selectedTab: 'login' }) }}
              className="form"
            >
              <Form onSubmit={() => { alert('form submitted'); }}>

                  There was an error submitting this form.

                <Form.Row>
                  Label:
                  <TextField defaultValue="" placeholder="TextField" style={{width: '200px'}}/>
                </Form.Row>

                <Form.Row>
                  Longer label:
                  <TextField defaultValue="" placeholder="TextField" style={{width: '200px'}}/>
                </Form.Row>

                <Form.Row>
                  <PushButton>PushButton</PushButton>
                  <PushButton onPress="submit" color="blue">PushButton Blue</PushButton>

                  <IndeterminateCircularProgressIndicator absolute/>
                </Form.Row>
              </Form>
            </SegmentedControl.Item>

            <SegmentedControl.Item
              title="Segmented"
              selected={this.state.selectedTab === 'segmented'}
              onPress={() => { this.setState({ selectedTab: 'segmented' }) }}
            >
              Hello World
            </SegmentedControl.Item>

            <SegmentedControl.Item
              title="Control"
              selected={this.state.selectedTab === 'control'}
              onPress={() => { this.setState({ selectedTab: 'control' }) }}
            >
              Goodbye World
            </SegmentedControl.Item>
          </SegmentedControl>
        </Box>
      </Window>
    );
  }
}

ReactDOM.render(<Window1/>, document.getElementById('window1'));
ReactDOM.render(<Window2/>, document.getElementById('window2'));
<|endoftext|>


<commit_before>define(['marionette',
        'utils/xhrimage',
        'tpl!templates/imaging/imagehistory.html',
        'tpl!templates/imaging/imagehistorymin.html'
    ], function(Marionette, XHRImage, template, templatemin) {

    var ThumbView = Marionette.ItemView.extend({
        tagName: 'figure',
        template: _.template('<a href="/containers/cid/<%=CONTAINERID%>/iid/<%=CONTAINERINSPECTIONID%>/sid/<%=BLSAMPLEID%>">
+<%=DELTA%>d
'),

        events: {
            'mouseover': 'hover',
        },

        hover: function(e) {
            console.log('hover')
            this.model.set({isSelected: true});
            this.model.collection.trigger('selected:change', this.model)
        },

        initialize: function(options) {
            this.model.on('change:isSelected', this.onSelectedChanged.bind(this))

            var self = this
            this.img = new XHRImage()
            this.img.onload = function() {
                self.$el.find('img').attr('src', self.img.src)
            }
            this.img.load(this.model.urlFor())

        },

        onSelectedChanged: function() {
            this.model.get('isSelected') ? this.$el.addClass('selected') : this.$el.removeClass('selected')
        },

        onRender: function() {
            if (this.model.get('isSelected')) this.$el.addClass('selected')
        },

    })

    var ThumbsView = Marionette.CollectionView.extend({
        childView: ThumbView,
    })

    return Marionette.LayoutView.extend({
        // template: template,
        getTemplate: function() {
            return this.getOption('embed') ? templatemin : template
        },

        className: function() {
            return 'img_history' + (this.getOption('embed') ? ' embed' : '')
        },

        regions: {
            thm: '.columns',
        },

        // setSampleId: function(id) {
        //     this.blsampleid = id
        //     if (id) this.images.fetch()
        // },

        // getSampleId: function() {
        //     return this.blsampleid
        // },

        initialize: function(options) {
            this.caching = true
            this.images = options.historyimages
            this.listenTo(this.images, 'sync', this.preCache.bind(this,1))
            //this.images.fetch()

        },

        onRender: function() {
            this.thm.show(new ThumbsView({ collection: this.images }))
        },

        preCache: function(n) {
            clearTimeout(this.cachethread)

            var self = this
            var i = this.images.at(n)
            if (this.caching && i) {
                var xhr =  new XHRImage()
                console.log('caching history', i.urlFor('hd'))
                xhr.load(i.urlFor('full'), function() {
                    self.cachethread = setTimeout(function() {
                        self.preCache(++n)
                    }, 500)
                })
            }

        },

        onDestroy: function() {
            clearTimeout(this.cachethread)
            this.caching = false
        },

    })

})<commit_msg>dont precache image history, dont autoload all images<commit_after>define(['marionette',
        'utils/xhrimage',
        'tpl!templates/imaging/imagehistory.html',
        'tpl!templates/imaging/imagehistorymin.html'
    ], function(Marionette, XHRImage, template, templatemin) {

    var ThumbView = Marionette.ItemView.extend({
        tagName: 'figure',
        template: _.template('<a href="/containers/cid/<%=CONTAINERID%>/iid/<%=CONTAINERINSPECTIONID%>/sid/<%=BLSAMPLEID%>">
+<%=DELTA%>d
'),

        events: {
            'mouseover': 'hover',
        },

        hover: function(e) {
            console.log('hover')
            this.model.set({isSelected: true});
            this.model.collection.trigger('selected:change', this.model)
        },

        initialize: function(options) {
            this.model.on('change:isSelected', this.onSelectedChanged.bind(this))

            var self = this
            this.img = new XHRImage()
            this.img.onload = function() {
                self.$el.find('img').attr('src', self.img.src)
            }

            if (this.getOption('autoLoad')) {
                this.loadImage()
            }
        },

        loadImage: function() {
            var idx = this.model.collection.indexOf(this.model)
            var last = this.model.collection.length == idx+1
            setTimeout(this.doLoadImage.bind(this), last ? 0 : idx*500)
        },

        doLoadImage: function() {
            this.img.load(this.model.urlFor())
        },

        onSelectedChanged: function() {
            this.model.get('isSelected') ? this.$el.addClass('selected') : this.$el.removeClass('selected')
        },

        onRender: function() {
            if (this.model.get('isSelected')) this.$el.addClass('selected')
        },

    })

    var ThumbsView = Marionette.CollectionView.extend({
        childView: ThumbView,

        childViewOptions: function() {
            return {
                autoLoad: this.getOption('autoLoad')
            }
        },

        load: function() {
            this.children.each(function(v) {
                v.loadImage()
            })
        }
    })

    return Marionette.LayoutView.extend({
        // template: template,
        getTemplate: function() {
            return this.getOption('embed') ? templatemin : template
        },

        className: function() {
            return 'img_history' + (this.getOption('embed') ? ' embed' : '')
        },

        regions: {
            thm: '.columns',
        },

        // setSampleId: function(id) {
        //     this.blsampleid = id
        //     if (id) this.images.fetch()
        // },

        // getSampleId: function() {
        //     return this.blsampleid
        // },

        initialize: function(options) {
            this.caching = true
            this.images = options.historyimages
            // this.listenTo(this.images, 'sync', this.preCache.bind(this,1))
            //this.images.fetch()
            //
            this.autoLoad = options && options.embed

        },

        onRender: function() {
            this.thumbs = new ThumbsView({ collection: this.images, autoLoad: this.getOption('autoLoad') })
            this.thm.show(this.thumbs)
        },

        load: function() {
            this.thumbs.load()
        },

        preCache: function(n) {
            clearTimeout(this.cachethread)

            var self = this
            var i = this.images.at(n)
            if (this.caching && i) {
                var xhr =  new XHRImage()
                console.log('caching history', i.urlFor('hd'))
                xhr.load(i.urlFor('full'), function() {
                    self.cachethread = setTimeout(function() {
                        self.preCache(++n)
                    }, 500)
                })
            }

        },

        onDestroy: function() {
            clearTimeout(this.cachethread)
            this.caching = false
        },

    })

})<|endoftext|>


<commit_before>import adWMGAnalyticsAdapter from 'modules/adWMGAnalyticsAdapter.js';
import { expect } from 'chai';
const sinon = require('sinon');
let adapterManager = require('src/adapterManager').default;
let events = require('src/events');
let constants = require('src/constants.json');

describe('adWMG Analytics', function () {
  let xhr = sinon.useFakeXMLHttpRequest();
  let requests = [];

  let timestamp = new Date() - 256;
  let auctionId = '5018eb39-f900-4370-b71e-3bb5b48d324f';
  let timeout = 1500;

  let bidTimeoutArgs = [
    {
      bidId: '2baa51527bd015',
      bidder: 'bidderA',
      adUnitCode: '/19968336/header-bid-tag-0',
      auctionId: '66529d4c-8998-47c2-ab3e-5b953490b98f'
    },
    {
      bidId: '6fe3b4c2c23092',
      bidder: 'bidderB',
      adUnitCode: '/19968336/header-bid-tag-0',
      auctionId: '66529d4c-8998-47c2-ab3e-5b953490b98f'
    }
  ];

  const bidResponse = {
    bidderCode: 'bidderA',
    adId: '208750227436c1',
    mediaTypes: ['banner'],
    cpm: 0.015,
    auctionId: auctionId,
    responseTimestamp: 1509369418832,
    requestTimestamp: 1509369418389,
    bidder: 'bidderA',
    timeToRespond: 443,
    size: '300x250',
    width: 300,
    height: 250,
  };

  let wonRequest = {
    'adId': '4587fec4900b81',
    'mediaType': 'banner',
    'requestId': '4587fec4900b81',
    'cpm': 1.962,
    'creativeId': 2126,
    'currency': 'USD',
    'netRevenue': true,
    'ttl': 302,
    'auctionId': '914bedad-b145-4e46-ba58-51365faea6cb',
    'statusMessage': 'Bid available',
    'responseTimestamp': 1530628534437,
    'requestTimestamp': 1530628534219,
    'bidder': 'bidderB',
    'adUnitCode': 'div-gpt-ad-1438287399331-0',
    'sizes': [[300, 250]],
    'size': [300, 250],
  };

  let expectedBidWonData = {
    publisher_id: '5abd0543ba45723db49d97ea',
    site: 'test.com',
    ad_unit_size: ['300,250'],
    ad_unit_type: ['banner'],
    c_timeout: 1500,
    events: [
      {
        status: 'bidWon',
        bids: [
          {
            bidder: 'bidderB',
            auction_id: '914bedad-b145-4e46-ba58-51365faea6cb',
            ad_unit_code: 'div-gpt-ad-1438287399331-0',
            transaction_id: '',
            bid_size: ['300,250'],
            bid_type: ['banner'],
            time_ms: 256,
            cur: 'USD',
            price: '1.96',
            cur_native: '',
            price_native: ''
          }
        ]
      }
    ]
  }

  let adUnits = [{
    code: 'ad-slot-1',
    sizes: [[300, 250]],
    mediaTypes: {
      banner: {
        sizes: [[300, 250]]
      }
    },
    bids: [
      {
        bidder: 'bidderA',
        params: {
          placement: '1000'
        }
      },
      {
        bidder: 'bidderB',
        params: {
          placement: '56656'
        }
      }
    ]
  }];

  before(function () {
    xhr.onCreate = function (request) {
      requests.push(request);
    };
  });

  after(function () {
    xhr.restore();
    adWMGAnalyticsAdapter.disableAnalytics();
  });

  describe('main test flow', function () {
    beforeEach(function () {
      global.XMLHttpRequest = sinon.useFakeXMLHttpRequest();
      sinon.stub(events, 'getEvents').returns([]);
    });

    afterEach(function () {
      events.getEvents.restore();
    });

    it('should catch all events', function () {
      sinon.spy(adWMGAnalyticsAdapter, 'track');

      adapterManager.registerAnalyticsAdapter({
        code: 'adWMG',
        adapter: adWMGAnalyticsAdapter
      });

      adapterManager.enableAnalytics({
        provider: 'adWMG',
        options: {
          site: 'test.com',
          publisher_id: '5abd0543ba45723db49d97ea'
        }
      });

      events.emit(constants.EVENTS.AUCTION_INIT, {timestamp, auctionId, timeout, adUnits});
      events.emit(constants.EVENTS.BID_REQUESTED, {});
      events.emit(constants.EVENTS.BID_RESPONSE, bidResponse);
      events.emit(constants.EVENTS.NO_BID, {});
      events.emit(constants.EVENTS.BID_TIMEOUT, bidTimeoutArgs);
      events.emit(constants.EVENTS.AUCTION_END, {});
      events.emit(constants.EVENTS.BID_WON, wonRequest);
      sinon.assert.callCount(adWMGAnalyticsAdapter.track, 7);
    });

    it('should be two xhr requests', function () {
      expect(requests.length).to.equal(2);
    });

    it('second request should be bidWon', function () {
      expect(JSON.parse(requests[1].requestBody).events[0].status).to.equal(expectedBidWonData.events[0].status);
    });

    it('check bidWon data', function () {
      let realBidWonData = JSON.parse(requests[1].requestBody);
      expect(realBidWonData.publisher_id).to.equal(expectedBidWonData.publisher_id);
      expect(realBidWonData.site).to.equal(expectedBidWonData.site);
      expect(realBidWonData.ad_unit_type[0]).to.equal(expectedBidWonData.ad_unit_type[0]);
      expect(realBidWonData.ad_unit_size[0]).to.equal(expectedBidWonData.ad_unit_size[0]);
      expect(realBidWonData.events[0].bids[0].bidder).to.equal(expectedBidWonData.events[0].bids[0].bidder);
    });
  });
});
<commit_msg>adWMGAnalytics - refactor unit tests (#5310)<commit_after>import adWMGAnalyticsAdapter from 'modules/adWMGAnalyticsAdapter.js';
import { expect } from 'chai';
import { server } from 'test/mocks/xhr.js';
let adapterManager = require('src/adapterManager').default;
let events = require('src/events');
let constants = require('src/constants.json');

describe('adWMG Analytics', function () {
  let timestamp = new Date() - 256;
  let auctionId = '5018eb39-f900-4370-b71e-3bb5b48d324f';
  let timeout = 1500;

  let bidTimeoutArgs = [
    {
      bidId: '2baa51527bd015',
      bidder: 'bidderA',
      adUnitCode: '/19968336/header-bid-tag-0',
      auctionId: '66529d4c-8998-47c2-ab3e-5b953490b98f'
    },
    {
      bidId: '6fe3b4c2c23092',
      bidder: 'bidderB',
      adUnitCode: '/19968336/header-bid-tag-0',
      auctionId: '66529d4c-8998-47c2-ab3e-5b953490b98f'
    }
  ];

  const bidResponse = {
    bidderCode: 'bidderA',
    adId: '208750227436c1',
    mediaTypes: ['banner'],
    cpm: 0.015,
    auctionId: auctionId,
    responseTimestamp: 1509369418832,
    requestTimestamp: 1509369418389,
    bidder: 'bidderA',
    timeToRespond: 443,
    size: '300x250',
    width: 300,
    height: 250,
  };

  let wonRequest = {
    'adId': '4587fec4900b81',
    'mediaType': 'banner',
    'requestId': '4587fec4900b81',
    'cpm': 1.962,
    'creativeId': 2126,
    'currency': 'USD',
    'netRevenue': true,
    'ttl': 302,
    'auctionId': '914bedad-b145-4e46-ba58-51365faea6cb',
    'statusMessage': 'Bid available',
    'responseTimestamp': 1530628534437,
    'requestTimestamp': 1530628534219,
    'bidder': 'bidderB',
    'adUnitCode': 'div-gpt-ad-1438287399331-0',
    'sizes': [[300, 250]],
    'size': [300, 250],
  };

  let expectedBidWonData = {
    publisher_id: '5abd0543ba45723db49d97ea',
    site: 'test.com',
    ad_unit_size: ['300,250'],
    ad_unit_type: ['banner'],
    c_timeout: 1500,
    events: [
      {
        status: 'bidWon',
        bids: [
          {
            bidder: 'bidderB',
            auction_id: '914bedad-b145-4e46-ba58-51365faea6cb',
            ad_unit_code: 'div-gpt-ad-1438287399331-0',
            transaction_id: '',
            bid_size: ['300,250'],
            bid_type: ['banner'],
            time_ms: 256,
            cur: 'USD',
            price: '1.96',
            cur_native: '',
            price_native: ''
          }
        ]
      }
    ]
  }

  let adUnits = [{
    code: 'ad-slot-1',
    sizes: [[300, 250]],
    mediaTypes: {
      banner: {
        sizes: [[300, 250]]
      }
    },
    bids: [
      {
        bidder: 'bidderA',
        params: {
          placement: '1000'
        }
      },
      {
        bidder: 'bidderB',
        params: {
          placement: '56656'
        }
      }
    ]
  }];

  after(function () {
    adWMGAnalyticsAdapter.disableAnalytics();
  });

  describe('main test flow', function () {
    beforeEach(function () {
      sinon.stub(events, 'getEvents').returns([]);
    });

    afterEach(function () {
      events.getEvents.restore();
    });

    it('should catch all events', function () {
      sinon.spy(adWMGAnalyticsAdapter, 'track');

      adapterManager.registerAnalyticsAdapter({
        code: 'adWMG',
        adapter: adWMGAnalyticsAdapter
      });

      adapterManager.enableAnalytics({
        provider: 'adWMG',
        options: {
          site: 'test.com',
          publisher_id: '5abd0543ba45723db49d97ea'
        }
      });

      events.emit(constants.EVENTS.AUCTION_INIT, {timestamp, auctionId, timeout, adUnits});
      events.emit(constants.EVENTS.BID_REQUESTED, {});
      events.emit(constants.EVENTS.BID_RESPONSE, bidResponse);
      events.emit(constants.EVENTS.NO_BID, {});
      events.emit(constants.EVENTS.BID_TIMEOUT, bidTimeoutArgs);
      events.emit(constants.EVENTS.AUCTION_END, {});
      events.emit(constants.EVENTS.BID_WON, wonRequest);
      sinon.assert.callCount(adWMGAnalyticsAdapter.track, 7);
    });

    it('should be two xhr requests', function () {
      events.emit(constants.EVENTS.AUCTION_END, {});
      events.emit(constants.EVENTS.BID_WON, wonRequest);
      expect(server.requests.length).to.equal(2);
    });

    it('second request should be bidWon', function () {
      events.emit(constants.EVENTS.AUCTION_END, {});
      events.emit(constants.EVENTS.BID_WON, wonRequest);
      expect(JSON.parse(server.requests[1].requestBody).events[0].status).to.equal(expectedBidWonData.events[0].status);
    });

    it('check bidWon data', function () {
      events.emit(constants.EVENTS.AUCTION_END, {});
      events.emit(constants.EVENTS.BID_WON, wonRequest);
      let realBidWonData = JSON.parse(server.requests[1].requestBody);
      expect(realBidWonData.publisher_id).to.equal(expectedBidWonData.publisher_id);
      expect(realBidWonData.site).to.equal(expectedBidWonData.site);
      expect(realBidWonData.ad_unit_type[0]).to.equal(expectedBidWonData.ad_unit_type[0]);
      expect(realBidWonData.ad_unit_size[0]).to.equal(expectedBidWonData.ad_unit_size[0]);
      expect(realBidWonData.events[0].bids[0].bidder).to.equal(expectedBidWonData.events[0].bids[0].bidder);
    });
  });
});
<|endoftext|>


<commit_before>import commander from 'commander';
import { exists, readdir, readFile, writeFile } from 'mz/fs';
import path from 'path';

import downloadFile from './downloadFile';
import run from './run';

export default function cli() {
  let project = null;
  commander
    .arguments('<project>')
    .description('Run decaffeinate on one of the sample projects.')
    .action(projectArg => project = projectArg)
    .option('--publish',
      `Push the resulting repository to the decaffeinate fork. The
           current git user must have permissions to do so.`)
    .parse(process.argv);

  runCli(project, commander.publish);
}

async function runCli(project, shouldPublish) {
  try {
    if (project === 'all') {
      await testAllProjects(shouldPublish);
    } else {
      await testProject(project, shouldPublish);
    }
  } catch (e) {
    console.error(`ERROR: ${e.message}`);
    process.exitCode = 1;
  }
}

async function testAllProjects(shouldPublish) {
  let projectNames = await readdir('./examples');
  console.log(`Processing all projects: ${projectNames.join(', ')}`);
  for (let project of projectNames) {
    console.log(`Processing project ${project}...`);
    await testProject(project, shouldPublish);
  }
  console.log(`Successfully processed all projects: ${projectNames.join(', ')}`);
}

async function testProject(project, shouldPublish) {
  let originalCwd = process.cwd();
  let exampleDir = path.resolve(`./examples/${project}`);
  if (!await exists(exampleDir)) {
    throw new Error(`Unknown project: ${project}`);
  }

  let config = require(`../examples/${project}/config`).default;

  let suffix = Math.floor(Math.random() * 1000000000000);
  let repoDir = `./tmp-projects/${project}-${suffix}`;
  await run(`mkdir ${repoDir}`);

  let cloneSuffix = config.branch ? `--branch ${config.branch}` : '';
  await run(`git clone ${config.cloneUrl} ${repoDir} ${cloneSuffix}`);

  if (config.useDefaultConfig) {
    await run(`cp -R ./default-config/. ${repoDir}`);
  }
  if (await exists(`${exampleDir}/bulk-decaffeinate.config.js`)) {
    await run(`cp ${exampleDir}/bulk-decaffeinate.config.js ${repoDir}`);
  }
  if (await exists(`${exampleDir}/.eslintrc.js`)) {
    await run(`cp ${exampleDir}/.eslintrc.js ${repoDir}`);
  }
  if (await exists(`${exampleDir}/babelrc`)) {
    await run(`cp ${exampleDir}/babelrc ${repoDir}/.babelrc`);
  }
  if (await exists(`${exampleDir}/package.json`)) {
    await run(`cp ${exampleDir}/package.json ${repoDir}`);
  }

  process.chdir(repoDir);

  if (shouldPublish) {
    await run(`git remote add fork ${config.forkUrl}`);
    await run('git fetch fork');
    // If we're using a custom branch/ref, it may not be valid to push to it, so
    // skip this step. (Currently this fits all use cases, but it can be made
    // more flexible later if necessary.)
    if (!config.branch) {
      await run('git push fork');
    }
  }

  if (await exists(`${exampleDir}/.gitignore_extension`)) {
    await run(`cat ${exampleDir}/.gitignore_extension >> .gitignore`);
  }

  await run('npm install');
  let dependencies = getDependencies(config);
  if (dependencies.length > 0) {
    await run(`npm install --save-dev ${dependencies.join(' ')}`);
  }
  await run('git add -A');
  await run('git commit -m "Add dependencies and config to prepare for decaffeinate"');

  let conversionResult = await checkConversion(config);
  if (!conversionResult.passed) {
    await run('git add -A');
    await run('git commit -m "Save decaffeinate error details"');

    await run('bulk-decaffeinate convert -p decaffeinate-successful-files.txt');
  } else {
    await run('bulk-decaffeinate convert');
  }

  await run('bulk-decaffeinate clean');
  // Make the patch its own commit after everything else so it's easier to
  // iterate on.
  if (await exists(`${exampleDir}/decaffeinate.patch`)) {
    await run(`git apply ${exampleDir}/decaffeinate.patch`);
    await run('git add -A');
    await run('git commit -m "Modify the build to work with JavaScript"');
  }
  let testResult = await runTests(config);

  await downloadFile(getConversionResultBadgeUrl(conversionResult), './conversion-status.svg');
  await downloadFile(getTestResultBadgeUrl(testResult), './test-status.svg');
  await writeFile('./README.md', getReadme(project, conversionResult, testResult));
  await run('git add -A');
  await run('git commit -m "Update README and badges with decaffeinate results"');

  if (shouldPublish) {
    await run('git push fork HEAD:decaffeinate -f');

    await run('git checkout --orphan gh-pages');
    await run('git rm --cached -r .');
    await run('git add conversion-status.svg');
    await run('git add test-status.svg');
    await run('git commit -m "Add status SVGs to gh-pages branch"');
    await run('git push fork HEAD:gh-pages -f');
  }

  process.chdir(originalCwd);
}

const DEFAULT_PACKAGES = [
  'babel-cli',
  'babel-polyfill',
  'babel-preset-env',
  'babel-register',
  'eslint',
  'eslint-config-airbnb-base',
  'eslint-plugin-import',
];

function getDependencies(config) {
  let dependencies = [];
  if (config.useDefaultConfig) {
    dependencies.push(...DEFAULT_PACKAGES);
  }
  if (config.extraDependencies) {
    dependencies.push(...config.extraDependencies);
  }
  return dependencies;
}

async function checkConversion(config) {
  await run('bulk-decaffeinate check');
  let hasErrorFile = await exists('./decaffeinate-errors.log');
  if (hasErrorFile) {
    let results = JSON.parse((await readFile('decaffeinate-results.json')).toString());
    let numErrors = results.filter(result => result.error).length;
    let numTotal = results.length;
    if (config.expectConversionSuccess) {
      process.exitCode = 1;
    }
    return {
      passed: false,
      numErrors,
      numTotal,
    };
  }
  return {
    passed: true,
  };
}

async function runTests(config) {
  if (config.skipTests) {
    console.log('Skipping tests for this project.');
    return 'SKIPPED';
  }
  try {
    if (config.testCommand) {
      await run(config.testCommand);
    } else {
      await run('npm test');
    }
    return 'PASSED';
  } catch (e) {
    if (config.expectTestSuccess) {
      process.exitCode = 1;
    }
    return 'FAILED';
  }
}

function getReadme(project, conversionResult, testResult) {
  let jobId = process.env.TRAVIS_JOB_ID;
  let jobMessage = jobId ?
    `[Travis logs](https://travis-ci.org/decaffeinate/decaffeinate-example-builder/jobs/${jobId})` :
    '';
  return `\
# decaffeinate fork of ${project}

![Conversion Status](https://decaffeinate-examples.github.io/${project}/conversion-status.svg)
![Test Status](https://decaffeinate-examples.github.io/${project}/test-status.svg)

${jobMessage}

## Conversion results

${getConversionResultDescription(conversionResult)}

## Test results

${getTestResultDescription(testResult)}

## About this repository

This repository was generated automatically by the [decaffeinate-examples]
project using the [decaffeinate] tool.

[decaffeinate-examples]: https://github.com/decaffeinate/decaffeinate-examples
[decaffeinate]: https://github.com/decaffeinate/decaffeinate
`;
}

function getConversionResultBadgeUrl(conversionResult) {
  if (conversionResult.passed) {
    return getBadgeUrl('decaffeinate conversion', 'success', 'brightgreen');
  } else {
    return getBadgeUrl(
      'decaffeinate conversion',
      `${conversionResult.numErrors}/${conversionResult.numTotal} failed`,
      'red'
    );
  }
}

function getTestResultBadgeUrl(testResult) {
  if (testResult === 'PASSED') {
    return getBadgeUrl('tests', 'passed', 'brightgreen');
  } else if (testResult === 'FAILED') {
    return getBadgeUrl('tests', 'failed', 'red');
  } else {
    return getBadgeUrl('tests', 'skipped', 'lightgrey');
  }
}

function getBadgeUrl(subject, status, color) {
  return `https://img.shields.io/badge/${encodeURI(subject)}-${encodeURI(status)}-${color}.svg`;
}

function getConversionResultDescription(conversionResult) {
  if (conversionResult.passed) {
    return 'All files were successfully converted to JavaScript.';
  } else {
    return `
There were ${conversionResult.numErrors} errors out of
${conversionResult.numTotal} total files.

For more details on the errors, view the [error logs](./decaffeinate-errors.log)
`;
  }
}

function getTestResultDescription(testResult) {
  if (testResult === 'PASSED') {
    return 'All tests passed.';
  } else if (testResult === 'FAILED') {
    return 'Some tests failed.';
  } else {
    return 'Post-decaffeinate tests have not yet been set up for this project.';
  }
}
<commit_msg>Save exact versions when saving to package.json (#48)<commit_after>import commander from 'commander';
import { exists, readdir, readFile, writeFile } from 'mz/fs';
import path from 'path';

import downloadFile from './downloadFile';
import run from './run';

export default function cli() {
  let project = null;
  commander
    .arguments('<project>')
    .description('Run decaffeinate on one of the sample projects.')
    .action(projectArg => project = projectArg)
    .option('--publish',
      `Push the resulting repository to the decaffeinate fork. The
           current git user must have permissions to do so.`)
    .parse(process.argv);

  runCli(project, commander.publish);
}

async function runCli(project, shouldPublish) {
  try {
    if (project === 'all') {
      await testAllProjects(shouldPublish);
    } else {
      await testProject(project, shouldPublish);
    }
  } catch (e) {
    console.error(`ERROR: ${e.message}`);
    process.exitCode = 1;
  }
}

async function testAllProjects(shouldPublish) {
  let projectNames = await readdir('./examples');
  console.log(`Processing all projects: ${projectNames.join(', ')}`);
  for (let project of projectNames) {
    console.log(`Processing project ${project}...`);
    await testProject(project, shouldPublish);
  }
  console.log(`Successfully processed all projects: ${projectNames.join(', ')}`);
}

async function testProject(project, shouldPublish) {
  let originalCwd = process.cwd();
  let exampleDir = path.resolve(`./examples/${project}`);
  if (!await exists(exampleDir)) {
    throw new Error(`Unknown project: ${project}`);
  }

  let config = require(`../examples/${project}/config`).default;

  let suffix = Math.floor(Math.random() * 1000000000000);
  let repoDir = `./tmp-projects/${project}-${suffix}`;
  await run(`mkdir ${repoDir}`);

  let cloneSuffix = config.branch ? `--branch ${config.branch}` : '';
  await run(`git clone ${config.cloneUrl} ${repoDir} ${cloneSuffix}`);

  if (config.useDefaultConfig) {
    await run(`cp -R ./default-config/. ${repoDir}`);
  }
  if (await exists(`${exampleDir}/bulk-decaffeinate.config.js`)) {
    await run(`cp ${exampleDir}/bulk-decaffeinate.config.js ${repoDir}`);
  }
  if (await exists(`${exampleDir}/.eslintrc.js`)) {
    await run(`cp ${exampleDir}/.eslintrc.js ${repoDir}`);
  }
  if (await exists(`${exampleDir}/babelrc`)) {
    await run(`cp ${exampleDir}/babelrc ${repoDir}/.babelrc`);
  }
  if (await exists(`${exampleDir}/package.json`)) {
    await run(`cp ${exampleDir}/package.json ${repoDir}`);
  }

  process.chdir(repoDir);

  if (shouldPublish) {
    await run(`git remote add fork ${config.forkUrl}`);
    await run('git fetch fork');
    // If we're using a custom branch/ref, it may not be valid to push to it, so
    // skip this step. (Currently this fits all use cases, but it can be made
    // more flexible later if necessary.)
    if (!config.branch) {
      await run('git push fork');
    }
  }

  if (await exists(`${exampleDir}/.gitignore_extension`)) {
    await run(`cat ${exampleDir}/.gitignore_extension >> .gitignore`);
  }

  await run('npm install');
  let dependencies = getDependencies(config);
  if (dependencies.length > 0) {
    await run(`npm install --save-dev --save-exact ${dependencies.join(' ')}`);
  }
  await run('git add -A');
  await run('git commit -m "Add dependencies and config to prepare for decaffeinate"');

  let conversionResult = await checkConversion(config);
  if (!conversionResult.passed) {
    await run('git add -A');
    await run('git commit -m "Save decaffeinate error details"');

    await run('bulk-decaffeinate convert -p decaffeinate-successful-files.txt');
  } else {
    await run('bulk-decaffeinate convert');
  }

  await run('bulk-decaffeinate clean');
  // Make the patch its own commit after everything else so it's easier to
  // iterate on.
  if (await exists(`${exampleDir}/decaffeinate.patch`)) {
    await run(`git apply ${exampleDir}/decaffeinate.patch`);
    await run('git add -A');
    await run('git commit -m "Modify the build to work with JavaScript"');
  }
  let testResult = await runTests(config);

  await downloadFile(getConversionResultBadgeUrl(conversionResult), './conversion-status.svg');
  await downloadFile(getTestResultBadgeUrl(testResult), './test-status.svg');
  await writeFile('./README.md', getReadme(project, conversionResult, testResult));
  await run('git add -A');
  await run('git commit -m "Update README and badges with decaffeinate results"');

  if (shouldPublish) {
    await run('git push fork HEAD:decaffeinate -f');

    await run('git checkout --orphan gh-pages');
    await run('git rm --cached -r .');
    await run('git add conversion-status.svg');
    await run('git add test-status.svg');
    await run('git commit -m "Add status SVGs to gh-pages branch"');
    await run('git push fork HEAD:gh-pages -f');
  }

  process.chdir(originalCwd);
}

const DEFAULT_PACKAGES = [
  'babel-cli',
  'babel-polyfill',
  'babel-preset-env',
  'babel-register',
  'eslint',
  'eslint-config-airbnb-base',
  'eslint-plugin-import',
];

function getDependencies(config) {
  let dependencies = [];
  if (config.useDefaultConfig) {
    dependencies.push(...DEFAULT_PACKAGES);
  }
  if (config.extraDependencies) {
    dependencies.push(...config.extraDependencies);
  }
  return dependencies;
}

async function checkConversion(config) {
  await run('bulk-decaffeinate check');
  let hasErrorFile = await exists('./decaffeinate-errors.log');
  if (hasErrorFile) {
    let results = JSON.parse((await readFile('decaffeinate-results.json')).toString());
    let numErrors = results.filter(result => result.error).length;
    let numTotal = results.length;
    if (config.expectConversionSuccess) {
      process.exitCode = 1;
    }
    return {
      passed: false,
      numErrors,
      numTotal,
    };
  }
  return {
    passed: true,
  };
}

async function runTests(config) {
  if (config.skipTests) {
    console.log('Skipping tests for this project.');
    return 'SKIPPED';
  }
  try {
    if (config.testCommand) {
      await run(config.testCommand);
    } else {
      await run('npm test');
    }
    return 'PASSED';
  } catch (e) {
    if (config.expectTestSuccess) {
      process.exitCode = 1;
    }
    return 'FAILED';
  }
}

function getReadme(project, conversionResult, testResult) {
  let jobId = process.env.TRAVIS_JOB_ID;
  let jobMessage = jobId ?
    `[Travis logs](https://travis-ci.org/decaffeinate/decaffeinate-example-builder/jobs/${jobId})` :
    '';
  return `\
# decaffeinate fork of ${project}

![Conversion Status](https://decaffeinate-examples.github.io/${project}/conversion-status.svg)
![Test Status](https://decaffeinate-examples.github.io/${project}/test-status.svg)

${jobMessage}

## Conversion results

${getConversionResultDescription(conversionResult)}

## Test results

${getTestResultDescription(testResult)}

## About this repository

This repository was generated automatically by the [decaffeinate-examples]
project using the [decaffeinate] tool.

[decaffeinate-examples]: https://github.com/decaffeinate/decaffeinate-examples
[decaffeinate]: https://github.com/decaffeinate/decaffeinate
`;
}

function getConversionResultBadgeUrl(conversionResult) {
  if (conversionResult.passed) {
    return getBadgeUrl('decaffeinate conversion', 'success', 'brightgreen');
  } else {
    return getBadgeUrl(
      'decaffeinate conversion',
      `${conversionResult.numErrors}/${conversionResult.numTotal} failed`,
      'red'
    );
  }
}

function getTestResultBadgeUrl(testResult) {
  if (testResult === 'PASSED') {
    return getBadgeUrl('tests', 'passed', 'brightgreen');
  } else if (testResult === 'FAILED') {
    return getBadgeUrl('tests', 'failed', 'red');
  } else {
    return getBadgeUrl('tests', 'skipped', 'lightgrey');
  }
}

function getBadgeUrl(subject, status, color) {
  return `https://img.shields.io/badge/${encodeURI(subject)}-${encodeURI(status)}-${color}.svg`;
}

function getConversionResultDescription(conversionResult) {
  if (conversionResult.passed) {
    return 'All files were successfully converted to JavaScript.';
  } else {
    return `
There were ${conversionResult.numErrors} errors out of
${conversionResult.numTotal} total files.

For more details on the errors, view the [error logs](./decaffeinate-errors.log)
`;
  }
}

function getTestResultDescription(testResult) {
  if (testResult === 'PASSED') {
    return 'All tests passed.';
  } else if (testResult === 'FAILED') {
    return 'Some tests failed.';
  } else {
    return 'Post-decaffeinate tests have not yet been set up for this project.';
  }
}
<|endoftext|>


<commit_before>'use strict'; // eslint-disable-line

const path = require('path');
const webpack = require('webpack');
const merge = require('webpack-merge');
const CleanPlugin = require('clean-webpack-plugin');
const ExtractTextPlugin = require('extract-text-webpack-plugin');
const CopyGlobsPlugin = require('copy-globs-webpack-plugin');
const FriendlyErrorsWebpackPlugin = require('friendly-errors-webpack-plugin');
const { BundleAnalyzerPlugin } = require('webpack-bundle-analyzer');

const config = require('./config');

const assetsFilenames = (config.enabled.cacheBusting) ? config.cacheBusting : '[name]';

let webpackConfig = {
  context: config.paths.assets,
  entry: config.entry,
  devtool: (config.enabled.sourceMaps ? '#source-map' : undefined),
  output: {
    path: config.paths.dist,
    publicPath: config.publicPath,
    filename: `scripts/${assetsFilenames}.js`,
  },
  stats: {
    hash: false,
    version: false,
    timings: false,
    children: false,
    errors: false,
    errorDetails: false,
    warnings: false,
    chunks: false,
    modules: false,
    reasons: false,
    source: false,
    publicPath: false,
  },
  module: {
    rules: [
      {
        enforce: 'pre',
        exclude: /node_modules/,
        test: /\.js$/,
        include: config.paths.assets,
        use: 'eslint',
      },
      {
        enforce: 'pre',
        test: /\.(js|s?[ca]ss)$/,
        include: config.paths.assets,
        loader: 'import-glob',
      },
      {
        test: /\.js$/,
        exclude: /node_modules/,
        use: [
          { loader: 'cache' },
          { loader: 'thread' },
          { loader: 'babel' },
        ],
      },
      {
        test: /\.css$/,
        include: config.paths.assets,
        use: ExtractTextPlugin.extract({
          fallback: 'style',
          use: [
            { loader: 'cache' },
            { loader: 'thread' },
            { loader: 'css', options: { sourceMap: config.enabled.sourceMaps } },
            {
              loader: 'postcss', options: {
                config: { path: __dirname, ctx: config },
                sourceMap: config.enabled.sourceMaps,
              },
            },
          ],
        }),
      },
      {
        test: /\.(sass|scss)$/,
        include: config.paths.assets,
        use: ExtractTextPlugin.extract({
          fallback: 'style',
          use: [
            { loader: 'cache' },
            { loader: 'thread' },
            { loader: 'css', options: { sourceMap: config.enabled.sourceMaps } },
            {
              loader: 'postcss', options: {
                config: { path: __dirname, ctx: config },
                sourceMap: config.enabled.sourceMaps,
              },
            },
            { loader: 'resolve-url', options: { sourceMap: config.enabled.sourceMaps } },
            { loader: 'sass', options: { sourceMap: config.enabled.sourceMaps } },
          ],
        }),
      },
      {
        test: /\.vue$/,
        loader: 'vue',
      },
      {
        test: /\.(ttf|eot|woff2?|png|jpe?g|gif|svg|ico)$/,
        include: config.paths.assets,
        loader: 'url',
        options: {
          limit: 1024,
          name: `[path]${assetsFilenames}.[ext]`,
        },
      },
      {
        test: /\.(ttf|eot|woff2?|png|jpe?g|gif|svg|ico)$/,
        include: /node_modules|bower_components/,
        loader: 'url',
        options: {
          limit: 1024,
          outputPath: 'vendor/',
          name: `${config.cacheBusting}.[ext]`,
        },
      },
    ],
  },
  resolve: {
    alias: {
      'vue$': 'vue/dist/vue.esm.js',
      '@scripts': path.resolve(__dirname, '../scripts'),
      '@components': path.resolve(__dirname, '../components'),
    },
    modules: [
      config.paths.assets,
      'node_modules',
    ],
    enforceExtension: false,
  },
  resolveLoader: {
    moduleExtensions: ['-loader'],
  },
  plugins: [
    new webpack.ProvidePlugin({
      axios: 'axios',
      Vue: ['vue/dist/vue.esm.js', 'default'],
      NProgress: 'nprogress/nprogress.js',
    }),
    new CleanPlugin([config.paths.dist], {
      root: config.paths.root,
      verbose: false,
    }),
    new CopyGlobsPlugin({
      pattern: config.copy,
      output: `[path]${assetsFilenames}.[ext]`,
      manifest: config.manifest,
    }),
    new ExtractTextPlugin({
      filename: `styles/${assetsFilenames}.css`,
      allChunks: true,
    }),
    new webpack.DefinePlugin({
      WEBPACK_PUBLIC_PATH: false,
    }),
    new webpack.LoaderOptionsPlugin({
      minimize: config.enabled.optimize,
      stats: { colors: true },
    }),
    new webpack.LoaderOptionsPlugin({
      test: /\.s?css$/,
      options: {
        output: { path: config.paths.dist },
        context: config.paths.assets,
      },
    }),
    new webpack.LoaderOptionsPlugin({
      test: /\.js$/,
      options: {
        eslint: { failOnWarning: false, failOnError: true },
      },
    }),
    new FriendlyErrorsWebpackPlugin(),
  ],
};

/* eslint-disable global-require */ /** Let's only load dependencies as needed */

if (config.enabled.optimize) {
  webpackConfig = merge(webpackConfig, require('./webpack.config.optimize'));
}

if (config.env.production) {
  webpackConfig.plugins.push(new webpack.NoEmitOnErrorsPlugin());
  webpackConfig.plugins.push(new webpack.optimize.ModuleConcatenationPlugin());
  webpackConfig.plugins.push(new webpack.optimize.AggressiveMergingPlugin());
  webpackConfig.plugins.push(new BundleAnalyzerPlugin({
    analyzerMode: 'static',
    reportFilename: path.resolve(__dirname, '../../.report/bundle-analyzer.html'),
    openAnalyzer: false,
  }));
}

if (config.enabled.cacheBusting) {
  const WebpackAssetsManifest = require('webpack-assets-manifest');

  webpackConfig.plugins.push(
    new WebpackAssetsManifest({
      output: 'assets.json',
      space: 2,
      writeToDisk: false,
      assets: config.manifest,
      replacer: require('./util/assetManifestsFormatter'),
    })
  );
}

module.exports = webpackConfig;
<commit_msg>add: resolve extensions<commit_after>'use strict'; // eslint-disable-line

const path = require('path');
const webpack = require('webpack');
const merge = require('webpack-merge');
const CleanPlugin = require('clean-webpack-plugin');
const ExtractTextPlugin = require('extract-text-webpack-plugin');
const CopyGlobsPlugin = require('copy-globs-webpack-plugin');
const FriendlyErrorsWebpackPlugin = require('friendly-errors-webpack-plugin');
const { BundleAnalyzerPlugin } = require('webpack-bundle-analyzer');

const config = require('./config');

const assetsFilenames = (config.enabled.cacheBusting) ? config.cacheBusting : '[name]';

let webpackConfig = {
  context: config.paths.assets,
  entry: config.entry,
  devtool: (config.enabled.sourceMaps ? '#source-map' : undefined),
  output: {
    path: config.paths.dist,
    publicPath: config.publicPath,
    filename: `scripts/${assetsFilenames}.js`,
  },
  stats: {
    hash: false,
    version: false,
    timings: false,
    children: false,
    errors: false,
    errorDetails: false,
    warnings: false,
    chunks: false,
    modules: false,
    reasons: false,
    source: false,
    publicPath: false,
  },
  module: {
    rules: [
      {
        enforce: 'pre',
        exclude: /node_modules/,
        test: /\.js$/,
        include: config.paths.assets,
        use: 'eslint',
      },
      {
        enforce: 'pre',
        test: /\.(js|s?[ca]ss)$/,
        include: config.paths.assets,
        loader: 'import-glob',
      },
      {
        test: /\.js$/,
        exclude: /node_modules/,
        use: [
          { loader: 'cache' },
          { loader: 'thread' },
          { loader: 'babel' },
        ],
      },
      {
        test: /\.css$/,
        include: config.paths.assets,
        use: ExtractTextPlugin.extract({
          fallback: 'style',
          use: [
            { loader: 'cache' },
            { loader: 'thread' },
            { loader: 'css', options: { sourceMap: config.enabled.sourceMaps } },
            {
              loader: 'postcss', options: {
                config: { path: __dirname, ctx: config },
                sourceMap: config.enabled.sourceMaps,
              },
            },
          ],
        }),
      },
      {
        test: /\.(sass|scss)$/,
        include: config.paths.assets,
        use: ExtractTextPlugin.extract({
          fallback: 'style',
          use: [
            { loader: 'cache' },
            { loader: 'thread' },
            { loader: 'css', options: { sourceMap: config.enabled.sourceMaps } },
            {
              loader: 'postcss', options: {
                config: { path: __dirname, ctx: config },
                sourceMap: config.enabled.sourceMaps,
              },
            },
            { loader: 'resolve-url', options: { sourceMap: config.enabled.sourceMaps } },
            { loader: 'sass', options: { sourceMap: config.enabled.sourceMaps } },
          ],
        }),
      },
      {
        test: /\.vue$/,
        loader: 'vue',
      },
      {
        test: /\.(ttf|eot|woff2?|png|jpe?g|gif|svg|ico)$/,
        include: config.paths.assets,
        loader: 'url',
        options: {
          limit: 1024,
          name: `[path]${assetsFilenames}.[ext]`,
        },
      },
      {
        test: /\.(ttf|eot|woff2?|png|jpe?g|gif|svg|ico)$/,
        include: /node_modules|bower_components/,
        loader: 'url',
        options: {
          limit: 1024,
          outputPath: 'vendor/',
          name: `${config.cacheBusting}.[ext]`,
        },
      },
    ],
  },
  resolve: {
    extensions: ['.js', '.vue', '.json'],
    alias: {
      'vue$': 'vue/dist/vue.esm.js',
      '@scripts': path.resolve(__dirname, '../scripts'),
      '@components': path.resolve(__dirname, '../components'),
    },
    modules: [
      config.paths.assets,
      'node_modules',
    ],
    enforceExtension: false,
  },
  resolveLoader: {
    moduleExtensions: ['-loader'],
  },
  plugins: [
    new webpack.ProvidePlugin({
      axios: 'axios',
      Vue: ['vue/dist/vue.esm.js', 'default'],
      NProgress: 'nprogress/nprogress.js',
    }),
    new CleanPlugin([config.paths.dist], {
      root: config.paths.root,
      verbose: false,
    }),
    new CopyGlobsPlugin({
      pattern: config.copy,
      output: `[path]${assetsFilenames}.[ext]`,
      manifest: config.manifest,
    }),
    new ExtractTextPlugin({
      filename: `styles/${assetsFilenames}.css`,
      allChunks: true,
    }),
    new webpack.DefinePlugin({
      WEBPACK_PUBLIC_PATH: false,
    }),
    new webpack.LoaderOptionsPlugin({
      minimize: config.enabled.optimize,
      stats: { colors: true },
    }),
    new webpack.LoaderOptionsPlugin({
      test: /\.s?css$/,
      options: {
        output: { path: config.paths.dist },
        context: config.paths.assets,
      },
    }),
    new webpack.LoaderOptionsPlugin({
      test: /\.js$/,
      options: {
        eslint: { failOnWarning: false, failOnError: true },
      },
    }),
    new FriendlyErrorsWebpackPlugin(),
  ],
};

/* eslint-disable global-require */ /** Let's only load dependencies as needed */

if (config.enabled.optimize) {
  webpackConfig = merge(webpackConfig, require('./webpack.config.optimize'));
}

if (config.env.production) {
  webpackConfig.plugins.push(new webpack.NoEmitOnErrorsPlugin());
  webpackConfig.plugins.push(new webpack.optimize.ModuleConcatenationPlugin());
  webpackConfig.plugins.push(new webpack.optimize.AggressiveMergingPlugin());
  webpackConfig.plugins.push(new BundleAnalyzerPlugin({
    analyzerMode: 'static',
    reportFilename: path.resolve(__dirname, '../../.report/bundle-analyzer.html'),
    openAnalyzer: false,
  }));
}

if (config.enabled.cacheBusting) {
  const WebpackAssetsManifest = require('webpack-assets-manifest');

  webpackConfig.plugins.push(
    new WebpackAssetsManifest({
      output: 'assets.json',
      space: 2,
      writeToDisk: false,
      assets: config.manifest,
      replacer: require('./util/assetManifestsFormatter'),
    })
  );
}

module.exports = webpackConfig;
<|endoftext|>


<commit_before>#!/usr/bin/env node

import fs from 'fs'
import _ from 'lodash'
import path from 'path'
import postcss from 'postcss'
import defaultConfig from './defaultConfig'
import program from 'commander'
import tailwind from '..'

let splitFileName = filename => {
  return filename.split('.')
}

let buildTailwind = config => {
  console.log('Building Tailwind!')

  fs.readFile(inputFile, (err, css) => {
    postcss([tailwind(config)])
      .process(css)
      .then(result => {
        fs.writeFileSync(outputFile, result.css)
      })
      .catch(error => console.log(error))
  })

  console.log('Finished building Tailwind!')
}

let getConfig = (customConfig, merge) => {
  if (merge) {
    return customConfig
  } else {
    return _.merge(defaultConfig, customConfig)
  }
}

program
  .version('0.1.0')
  .usage('[options] <file ...>')
  .option('-c, --config [path]', 'set config path')
  .option(
    '-r, --replace',
    'replace the built-in configuration with the provided config file'
  )
  .parse(process.argv)

let inputFile = program.args[0]

if (!inputFile) {
  console.error('No input file given!')
  process.exit(1)
}

let outputFile =
  program.args[1] || `${splitFileName(program.args[0])[0]}-output.css`

if (program.config !== undefined) {
  fs.exists(program.config, exists => {
    if (!exists) {
      console.error(`Config file [${program.config}] does not exist.`)
      process.exit(1)
    }

    fs.readFile(program.config, (err, config) => {
      if (err) {
        console.error(
          `There was a problem reading config file [${program.config}].`
        )
        process.exit(1)
      }

      const customConfig = JSON.parse(config.toString())

      let finalConfig = getConfig(customConfig, program.replace)

      buildTailwind(finalConfig)
    })
  })
} else {
  buildTailwind(defaultConfig)
}
<commit_msg>Change merge parameter to replace in CLI<commit_after>#!/usr/bin/env node

import fs from 'fs'
import _ from 'lodash'
import path from 'path'
import postcss from 'postcss'
import defaultConfig from './defaultConfig'
import program from 'commander'
import tailwind from '..'

let splitFileName = filename => {
  return filename.split('.')
}

let buildTailwind = config => {
  console.log('Building Tailwind!')

  fs.readFile(inputFile, (err, css) => {
    postcss([tailwind(config)])
      .process(css)
      .then(result => {
        fs.writeFileSync(outputFile, result.css)
      })
      .catch(error => console.log(error))
  })

  console.log('Finished building Tailwind!')
}

let getConfig = (customConfig, replace) => {
  if (replace) {
    return customConfig
  } else {
    return _.merge(defaultConfig, customConfig)
  }
}

program
  .version('0.1.0')
  .usage('[options] <file ...>')
  .option('-c, --config [path]', 'set config path')
  .option(
    '-r, --replace',
    'replace the built-in configuration with the provided config file'
  )
  .parse(process.argv)

let inputFile = program.args[0]

if (!inputFile) {
  console.error('No input file given!')
  process.exit(1)
}

let outputFile =
  program.args[1] || `${splitFileName(program.args[0])[0]}-output.css`

if (program.config !== undefined) {
  fs.exists(program.config, exists => {
    if (!exists) {
      console.error(`Config file [${program.config}] does not exist.`)
      process.exit(1)
    }

    fs.readFile(program.config, (err, config) => {
      if (err) {
        console.error(
          `There was a problem reading config file [${program.config}].`
        )
        process.exit(1)
      }

      const customConfig = JSON.parse(config.toString())

      let finalConfig = getConfig(customConfig, program.replace)

      buildTailwind(finalConfig)
    })
  })
} else {
  buildTailwind(defaultConfig)
}
<|endoftext|>


<commit_before>var $ = require('jquery');
var cdb = require('cartodb.js');
var trackJsErrors = require('new_common/track_js_errors');
var HeaderView = require('new_common/views/dashboard_header_view');
var SupportView = require('new_common/support_view');
var HeaderViewModel = require('new_keys/header_view_model');
var LocalStorage = require('new_common/local_storage');
var urls = require('new_common/urls_fn');
var RegenerateKeysDialog = require('new_keys/regenerate_keys_dialog_view');

if (window.trackJs) {
  trackJsErrors(window.trackJs, window.user_data.username);
}

/**
 * Entry point for the new keys, bootstraps all dependency models and application.
 */
$(function() {
  cdb.init(function() {
    cdb.templates.namespace = 'cartodb/';

    cdb.config.set(window.config); // import config
    if (cdb.config.isOrganizationUrl()) {
      cdb.config.set('url_prefix', cdb.config.organizationUrl());
    }

    $(document.body).bind('click', function () {
      cdb.god.trigger('closeDialogs');
    });

    var currentUser = new cdb.admin.User(window.user_data);

    var headerView = new HeaderView({
      el:             $('#header'), //pre-rendered in DOM by Rails app
      model:          currentUser,
      currentUserUrl: urls(window.config.account_host).userUrl(currentUser),
      viewModel:      new HeaderViewModel(),
      localStorage:   new LocalStorage()
    });
    headerView.render();

    var supportView = new SupportView({
      el: $('#support-banner'),
      user: currentUser
    });
    supportView.render();

    $('.js-submit').bind('click', function(ev) {
      if (ev) ev.preventDefault();
      var type = $(this).val();
      var dlg = new RegenerateKeysDialog({
        type: type || 'api'
      });

      dlg.bind('done', function() {
        $(this).closest('form').submit()
      }, this)
      dlg.bind('hide', function(){
        this.clean();
      });

      dlg.appendToBody();
    });

    $('.js-copy-value').each(function() {
      // Copy
      $(this).zclip({
        path: cdb.config.get('assets_url') + "/flash/ZeroClipboard.swf",
        copy: function(){
          return $(this).parent().find(".js-input").val();
        }
      });

      // Tooltip
      var tooltip = new cdb.common.TipsyTooltip({
        el: $(this),
        title: function() {
          return $(this).data('title');
        }
      });
    });
  });

});
<commit_msg>Fix trackJS for API keys entry bundle<commit_after>var $ = require('jquery');
var cdb = require('cartodb.js');
var HeaderView = require('new_common/views/dashboard_header_view');
var SupportView = require('new_common/support_view');
var HeaderViewModel = require('new_keys/header_view_model');
var LocalStorage = require('new_common/local_storage');
var urls = require('new_common/urls_fn');
var RegenerateKeysDialog = require('new_keys/regenerate_keys_dialog_view');

if (window.trackJs) {
  window.trackJs.configure({
    userId: window.user_data.username
  });
}

/**
 * Entry point for the new keys, bootstraps all dependency models and application.
 */
$(function() {
  cdb.init(function() {
    cdb.templates.namespace = 'cartodb/';

    cdb.config.set(window.config); // import config
    if (cdb.config.isOrganizationUrl()) {
      cdb.config.set('url_prefix', cdb.config.organizationUrl());
    }

    $(document.body).bind('click', function () {
      cdb.god.trigger('closeDialogs');
    });

    var currentUser = new cdb.admin.User(window.user_data);

    var headerView = new HeaderView({
      el:             $('#header'), //pre-rendered in DOM by Rails app
      model:          currentUser,
      currentUserUrl: urls(window.config.account_host).userUrl(currentUser),
      viewModel:      new HeaderViewModel(),
      localStorage:   new LocalStorage()
    });
    headerView.render();

    var supportView = new SupportView({
      el: $('#support-banner'),
      user: currentUser
    });
    supportView.render();

    $('.js-submit').bind('click', function(ev) {
      if (ev) ev.preventDefault();
      var type = $(this).val();
      var dlg = new RegenerateKeysDialog({
        type: type || 'api'
      });

      dlg.bind('done', function() {
        $(this).closest('form').submit()
      }, this)
      dlg.bind('hide', function(){
        this.clean();
      });

      dlg.appendToBody();
    });

    $('.js-copy-value').each(function() {
      // Copy
      $(this).zclip({
        path: cdb.config.get('assets_url') + "/flash/ZeroClipboard.swf",
        copy: function(){
          return $(this).parent().find(".js-input").val();
        }
      });

      // Tooltip
      var tooltip = new cdb.common.TipsyTooltip({
        el: $(this),
        title: function() {
          return $(this).data('title');
        }
      });
    });
  });

});
<|endoftext|>


<commit_before>/* ***** BEGIN LICENSE BLOCK *****
 *
 * Copyright (c) 2009 Aptana, Inc.
 *
 * Permission is hereby granted, free of charge, to any person
 * obtaining a copy of this software and associated documentation
 * files (the "Software"), to deal in the Software without
 * restriction, including without limitation the rights to use,
 * copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following
 * conditions:
 *
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 * OTHER DEALINGS IN THE SOFTWARE.
 *
 * ***** END LICENSE BLOCK ***** */

/**
 * Adapter for Jaxer configured with SQLite
 * @alias ActiveRecord.Adapters.JaxerSQLite
 * @property {ActiveRecord.Adapter}
 */
Adapters.JaxerSQLite = function(){
    ActiveSupport.extend(this,Adapters.SQLite);
    ActiveSupport.extend(this,{
        log: function log()
        {
            if (!ActiveRecord.logging)
            {
                return;
            }
            if (arguments[0])
            {
                arguments[0] = '  ' + arguments[0];
            }
            return AcitveSupport.log.apply(AcitveSupport,arguments || {});
        },
        executeSQL: function executeSQL(sql)
        {
            ActiveRecord.connection.log("Adapters.JaxerSQLite.executeSQL: " + sql + " [" + ActiveSupport.arrayFrom(arguments).slice(1).join(',') + "]");
            var response = Jaxer.DB.execute.apply(Jaxer.DB.connection, arguments);
            return response;
        },
        getLastInsertedRowId: function getLastInsertedRowId()
        {
            return Jaxer.DB.lastInsertId;
        },
        iterableFromResultSet: function iterableFromResultSet(result)
        {
            result.iterate = function iterate(iterator)
            {
                if (typeof(iterator) == 'number')
                {
                    if (this.rows[iterator])
                    {
                        return ActiveSupport.clone(this.rows[iterator]);
                    }
                    else
                    {
                        return false;
                    }
                }
                else
                {
                    for (var i = 0; i < this.rows.length; ++i)
                    {
                        var row = ActiveSupport.clone(this.rows[i]);
                        delete row['$values'];
                        iterator(row);
                    }
                }
            };
            return result;
        },
        transaction: function transaction(proceed)
        {
            try
            {
                ActiveRecord.connection.executeSQL('BEGIN');
                proceed();
                ActiveRecord.connection.executeSQL('COMMIT');
            }
            catch(e)
            {
                ActiveRecord.connection.executeSQL('ROLLBACK');
                throw e;
            }
        }
    });
};
Adapters.JaxerSQLite.connect = function connect(path)
{
    Jaxer.DB.connection = new Jaxer.DB.SQLite.createDB({
        PATH: Jaxer.Dir.resolve(path || 'ActiveRecord.sqlite')
    });
    return new Adapters.JaxerSQLite();
};<commit_msg>fixed misspelling of ActiveSupport<commit_after>/* ***** BEGIN LICENSE BLOCK *****
 *
 * Copyright (c) 2009 Aptana, Inc.
 *
 * Permission is hereby granted, free of charge, to any person
 * obtaining a copy of this software and associated documentation
 * files (the "Software"), to deal in the Software without
 * restriction, including without limitation the rights to use,
 * copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following
 * conditions:
 *
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 * OTHER DEALINGS IN THE SOFTWARE.
 *
 * ***** END LICENSE BLOCK ***** */

/**
 * Adapter for Jaxer configured with SQLite
 * @alias ActiveRecord.Adapters.JaxerSQLite
 * @property {ActiveRecord.Adapter}
 */
Adapters.JaxerSQLite = function(){
    ActiveSupport.extend(this,Adapters.SQLite);
    ActiveSupport.extend(this,{
        log: function log()
        {
            if (!ActiveRecord.logging)
            {
                return;
            }
            if (arguments[0])
            {
                arguments[0] = '  ' + arguments[0];
            }
            return ActiveSupport.log.apply(ActiveSupport,arguments || {});
        },
        executeSQL: function executeSQL(sql)
        {
            ActiveRecord.connection.log("Adapters.JaxerSQLite.executeSQL: " + sql + " [" + ActiveSupport.arrayFrom(arguments).slice(1).join(',') + "]");
            var response = Jaxer.DB.execute.apply(Jaxer.DB.connection, arguments);
            return response;
        },
        getLastInsertedRowId: function getLastInsertedRowId()
        {
            return Jaxer.DB.lastInsertId;
        },
        iterableFromResultSet: function iterableFromResultSet(result)
        {
            result.iterate = function iterate(iterator)
            {
                if (typeof(iterator) == 'number')
                {
                    if (this.rows[iterator])
                    {
                        return ActiveSupport.clone(this.rows[iterator]);
                    }
                    else
                    {
                        return false;
                    }
                }
                else
                {
                    for (var i = 0; i < this.rows.length; ++i)
                    {
                        var row = ActiveSupport.clone(this.rows[i]);
                        delete row['$values'];
                        iterator(row);
                    }
                }
            };
            return result;
        },
        transaction: function transaction(proceed)
        {
            try
            {
                ActiveRecord.connection.executeSQL('BEGIN');
                proceed();
                ActiveRecord.connection.executeSQL('COMMIT');
            }
            catch(e)
            {
                ActiveRecord.connection.executeSQL('ROLLBACK');
                throw e;
            }
        }
    });
};
Adapters.JaxerSQLite.connect = function connect(path)
{
    Jaxer.DB.connection = new Jaxer.DB.SQLite.createDB({
        PATH: Jaxer.Dir.resolve(path || 'ActiveRecord.sqlite')
    });
    return new Adapters.JaxerSQLite();
};<|endoftext|>


<commit_before>/**
 * @license
 * Copyright The Closure Library Authors.
 * SPDX-License-Identifier: Apache-2.0
 */

/**
 * @fileoverview A single module to define user-agent specific environment
 * details.
 *
 */

goog.module('goog.labs.net.webChannel.environment');

goog.module.declareLegacyNamespace();

const googURL = goog.require('goog.url');
const labsUABrowser = goog.require('goog.labs.userAgent.browser');
var userAgent = goog.require('goog.userAgent');

/**
 * The default polling interval in millis for Edge.
 *
 * Currently on edge, new-chunk events may be not be fired (at all) if a new
 * chunk arrives within 50ms following the previous chunk. This may be fixed
 * in future, which requires changes to the whatwg spec too.
 *
 * @private @const {number}
 */
var EDGE_POLLING_INTERVAL_ = 125;

/**
 * History:
 *
 * IE11 is still using Trident, the traditional engine for IE.
 * Edge is using EdgeHTML, a fork of Trident. We are seeing the same issue
 * on IE-11 (reported in 2017), so treat IE the same as Edge for now.
 *
 * We used to do polling for Opera (only) with an 250ms interval, because Opera
 * only fires readyState == INTERACTIVE once. Opera switched to WebKit in 2013,
 * and then to Blink (chrome).
 *
 * TODO(user): check the raw UA string to keep polling for old, mobile operas
 * that may still be affected. For old Opera, double the polling interval
 * to 250ms.
 *
 * @return {boolean} True if polling is required with XHR.
 */
exports.isPollingRequired = function() {
  return userAgent.EDGE_OR_IE;
};

/**
 * How often to poll (in MS) for changes to responseText in browsers that don't
 * fire onreadystatechange during incremental loading of the response body.
 *
 * @return {number|undefined} The polling interval (MS) for the current U-A;
 * or undefined if polling is not supposed to be enabled.
 */
exports.getPollingInterval = function() {
  if (userAgent.EDGE_OR_IE) {
    return EDGE_POLLING_INTERVAL_;
  }

  return undefined;
};

/**
 * Origin trial token for google.com
 *
 * https://developers.chrome.com/origintrials/#/trials
 *
 * http://googlechrome.github.io/OriginTrials/check-token.html
 * Origin: https://google.com:443
 * Matches Subdomains? Yes
 * Matches Third-party? Yes
 * Feature: FetchUploadStreaming
 * Expires: 7/14/2021, 8:59:59 AM
 *
 * Token for googleapis.com will be registered after google.com's is deployed.
 *
 */
const OT_TOKEN_GOOGLE_COM =
    "A70X6iKIlnS3U/OFBWYlZCJ6rRlXum75MZ6pvi68FKsnyeL+XPCA7KWBMeW75d2+xNHMEeFOWjfqMS+34jdvrw4AAAB/eyJvcmlnaW4iOiJodHRwczovL2dvb2dsZS5jb206NDQzIiwiZmVhdHVyZSI6IkZldGNoVXBsb2FkU3RyZWFtaW5nIiwiZXhwaXJ5IjoxNjI2MjIwNzk5LCJpc1N1YmRvbWFpbiI6dHJ1ZSwiaXNUaGlyZFBhcnR5Ijp0cnVlfQ==";
/**
 * Creates ReadableStream to upload
 * @return {!ReadableStream} ReadableStream to upload
 */
function createStream() {
  const encoder = new goog.global.TextEncoder();
  return new goog.global.ReadableStream({
    start: controller => {
      for (const obj of ['test\r\n', 'test\r\n']) {
        controller.enqueue(encoder.encode(obj));
      }
      controller.close();
    }
  });
}

/**
 * For Fetch/upload OT, make three requests against the server endpoint.
 * POST requests contain only dummy payload.
 *
 * https://developers.chrome.com/origintrials/#/view_trial/3524066708417413121
 *
 * This function is expected to be called from background during the handshake.
 * Exceptions will be logged by the caller.
 *
 * No stats or logs are collected on the client-side. To be disabled once the
 * OT is expired.
 *
 * @param {string} path The base URL path for the requests
 */
exports.startOriginTrials = function(path) {
  // NE: may need check if path has already contains query params?

  // Accept only Chrome.
  if (!labsUABrowser.isChrome()) {
    return;
  }
  // Accept M90 or later due to service worker support.
  if (!labsUABrowser.isVersionOrHigher(90)) {
    return;
  }
  // Accept only only google.com and subdoamins.
  const pathOrigin = googURL.resolveUrl(path).origin;
  if(!pathOrigin.endsWith("google.com")) {
    return;
  }
  // Since 3P OT is not supported yet, we should check the current page matches
  // the path (absolute one?) to disable this OT for cross-origin calls
  const urlOrigin = googURL.resolveUrl(window.document.URL).origin;
  if(!urlOrigin.endsWith("google.com")) {
    return;
  }

  // Enable origin trial by injecting OT <meta> tag
  const tokenElement =
    /** @type {! HTMLMetaElement} */ (document.createElement('meta'));
  tokenElement.httpEquiv = 'origin-trial';
  tokenElement.content = OT_TOKEN_GOOGLE_COM;
  // appendChild() synchronously enables OT.
  document.head.appendChild(tokenElement);

  // Check if fetch upload stream is actually enabled.
  // By the spec, Streaming request doesn't has the Content-Type header:
  // https://fetch.spec.whatwg.org/#concept-bodyinit-extract
  // If Chrome doesn't support Streaming, the body stream is converted to a
  // string "[object ReadableStream]" for fallback then it has "Content-Type:
  // text/plain;charset=UTF-8".
  const supportsRequestStreams = !new Request('', {
    body: new ReadableStream(),
    method: 'POST',
  }).headers.has('Content-Type');
  if (!supportsRequestStreams) {
    return;
  }

  // 1st req:  path?ot=1
  // non-streaming upload request
  goog.global.fetch(`${path}?ot=1`, {method: 'POST', body: 'test\r\n'});

  // 2nd req:  path?ot=2
  // h2-only streaming upload request
  goog.global.fetch(`${path}?ot=2`, {
    method: 'POST',
    body: createStream(),
    allowHTTP1ForStreamingUpload: false,
  });

  // 3rd req:  path?ot=3
  // h1-allowed streaming upload request
  goog.global.fetch(`${path}?ot=3`, {
    method: 'POST',
    body: createStream(),
    allowHTTP1ForStreamingUpload: true,
  });

  // Example calling a Chrome API:
  // goog.global.chrome.loadTimes().wasFetchedViaSpdy
};
<commit_msg>Automated rollback of commit d6c8205342a6d5a427aefeee27b81f3b94266a25.<commit_after>/**
 * @license
 * Copyright The Closure Library Authors.
 * SPDX-License-Identifier: Apache-2.0
 */

/**
 * @fileoverview A single module to define user-agent specific environment
 * details.
 *
 */

goog.module('goog.labs.net.webChannel.environment');

goog.module.declareLegacyNamespace();

var userAgent = goog.require('goog.userAgent');

/**
 * The default polling interval in millis for Edge.
 *
 * Currently on edge, new-chunk events may be not be fired (at all) if a new
 * chunk arrives within 50ms following the previous chunk. This may be fixed
 * in future, which requires changes to the whatwg spec too.
 *
 * @private @const {number}
 */
var EDGE_POLLING_INTERVAL_ = 125;

/**
 * History:
 *
 * IE11 is still using Trident, the traditional engine for IE.
 * Edge is using EdgeHTML, a fork of Trident. We are seeing the same issue
 * on IE-11 (reported in 2017), so treat IE the same as Edge for now.
 *
 * We used to do polling for Opera (only) with an 250ms interval, because Opera
 * only fires readyState == INTERACTIVE once. Opera switched to WebKit in 2013,
 * and then to Blink (chrome).
 *
 * TODO(user): check the raw UA string to keep polling for old, mobile operas
 * that may still be affected. For old Opera, double the polling interval
 * to 250ms.
 *
 * @return {boolean} True if polling is required with XHR.
 */
exports.isPollingRequired = function() {
  return userAgent.EDGE_OR_IE;
};

/**
 * How often to poll (in MS) for changes to responseText in browsers that don't
 * fire onreadystatechange during incremental loading of the response body.
 *
 * @return {number|undefined} The polling interval (MS) for the current U-A;
 * or undefined if polling is not supposed to be enabled.
 */
exports.getPollingInterval = function() {
  if (userAgent.EDGE_OR_IE) {
    return EDGE_POLLING_INTERVAL_;
  }

  return undefined;
};

/**
 * For Fetch/upload OT, make three requests against the server endpoint.
 * POST requests contain only dummy payload.
 *
 * https://developers.chrome.com/origintrials/#/view_trial/3524066708417413121
 *
 * 1) google.com token
 *
 * A329ozYiTjUmNz0Eh5wffNLiRjiVtFBptKBulP7UYXxKSuMVVhP3pVnlHnbrBg2ALEPd63boPZArHXg3+WlmagkAAAB/eyJvcmlnaW4iOiJodHRwczovL2dvb2dsZS5jb206NDQzIiwiZmVhdHVyZSI6IkZldGNoVXBsb2FkU3RyZWFtaW5nIiwiZXhwaXJ5IjoxNjA4OTIzMjA4LCJpc1N1YmRvbWFpbiI6dHJ1ZSwiaXNUaGlyZFBhcnR5Ijp0cnVlfQ==
 *
 * 2) googleapis.com token
 *
 * To be registered after 1) is deployed.
 *
 * https://developers.chrome.com/origintrials/#/trials
 *
 * This function is expected to be called from background during the handshake.
 * Exceptions will be logged by the caller.
 *
 * No stats or logs are collected on the client-side. To be disabled once the
 * OT is expired.
 *
 * @param {string} path The base URL path for the requests
 */
exports.startOriginTrials = function(path) {
  // NE: may need check if path has already contains query params?

  // 1st req:  path?ot=1
  // non-streaming upload request

  // 2nd req:  path?ot=2
  // h2-only streaming upload request

  // 3rd req:  path?ot=3
  // h1-allowed streaming upload request

  // Example calling a Chrome API:
  // goog.global.chrome.loadTimes().wasFetchedViaSpdy
};<|endoftext|>


<commit_before>var popchart = function(selector, data_url)
{
  // Following code copied then adapted from http://bl.ocks.org/mbostock/3884955

  // Setup
  var margin = {top: 20, right: 120, bottom: 30, left: 50},
      width = 960 - margin.left - margin.right,
      height = 500 - margin.top - margin.bottom;

  var parseDate = d3.time.format("%Y%m%d").parse;
  var capitalize = function(s) { return s[0].toUpperCase() + s.slice(1); }

  var x = d3.time.scale()
      .range([0, width]);

  var y = d3.scale.linear()
      .range([height, 0]);

  var color = d3.scale.category10();

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

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

  var line = d3.svg.line()
      .interpolate("linear")
      .x(function(d) { return x(d.date); })
      .y(function(d) { return y(d.count); });

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

  // Loading indicator
  svg.append("text")
    .attr("x", width / 2)
    .attr("y", height / 2)
    .attr("class", "removeme")
    .style("font-size", "100%")
    .text("Loading...")

  d3.json(data_url, function (error, data) {
    // Remove loading text
    svg.select(".removeme").remove();

    color.domain(d3.keys(data))

    // Re-structure and parse values
    var servers = color.domain().map(function(name) {
      return {
        name: name,
        values: data[name].map(function(count) {
          return { date: parseDate(count.date), count: +count.count };
        })
      };
    });

    // Find the min and max values for the scales
    // TODO: Consider a more efficient way to do this
    var xvals = [],
        yvals = [];

    servers.forEach(function(server) {
      var dates = server.values.map(function(data) {
        return data.date
      });

      var counts = server.values.map(function(data) {
        return data.count
      });

      xvals = xvals.concat(dates);
      yvals = yvals.concat(counts);
    });

    x.domain(d3.extent(xvals));
    y.domain([0, d3.max(yvals) * 1.25]);

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

    svg.append("g")
        .attr("class", "y axis")
        .call(yAxis)
      .append("text")
        .attr("transform", "rotate(-90)")
        .attr("y", 6)
        .attr("dy", ".71em")
        .style("text-anchor", "end")
        .text("Players");

    var server = svg.selectAll(".server")
        .data(servers)
      .enter().append("g")
        .attr("class", "servers");

    server.append("path")
        .attr("class", "line")
        .attr("d", function(d) { return line(d.values); })
        .style("stroke", function(d) { return color(d.name); });

    server.append("text")
        .datum(function(d) { return {name: d.name, value: d.values[d.values.length - 1]}; })
        .attr("transform", function(d) { return "translate(" + x(d.value.date) + "," + y(d.value.count) + ")"; })
        .attr("x", 3)
        .attr("dy", ".35em")
        .attr("class", "label")
        .text(function(d) { return capitalize(d.name) + ": " + Math.round(d.value.count)})
        .style("fill", function(d) { return color(d.name); });
  });
}
<commit_msg>Prettify popchart.js<commit_after>var popchart = function (selector, data_url) {
  // Following code copied then adapted from http://bl.ocks.org/mbostock/3884955

  // Setup
  var margin = { top: 20, right: 120, bottom: 30, left: 50 },
    width = 960 - margin.left - margin.right,
    height = 500 - margin.top - margin.bottom;

  var parseDate = d3.time.format("%Y%m%d").parse;
  var capitalize = function (s) { return s[0].toUpperCase() + s.slice(1); }

  var x = d3.time.scale()
    .range([0, width]);

  var y = d3.scale.linear()
    .range([height, 0]);

  var color = d3.scale.category10();

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

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

  var line = d3.svg.line()
    .interpolate("linear")
    .x(function (d) { return x(d.date); })
    .y(function (d) { return y(d.count); });

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

  // Loading indicator
  svg.append("text")
    .attr("x", width / 2)
    .attr("y", height / 2)
    .attr("class", "removeme")
    .style("font-size", "100%")
    .text("Loading...")

  d3.json(data_url, function (error, data) {
    // Remove loading text
    svg.select(".removeme").remove();

    color.domain(d3.keys(data))

    // Re-structure and parse values
    var servers = color.domain().map(function (name) {
      return {
        name: name,
        values: data[name].map(function (count) {
          return { date: parseDate(count.date), count: +count.count };
        })
      };
    });

    // Find the min and max values for the scales
    // TODO: Consider a more efficient way to do this
    var xvals = [],
      yvals = [];

    servers.forEach(function (server) {
      var dates = server.values.map(function (data) {
        return data.date
      });

      var counts = server.values.map(function (data) {
        return data.count
      });

      xvals = xvals.concat(dates);
      yvals = yvals.concat(counts);
    });

    x.domain(d3.extent(xvals));
    y.domain([0, d3.max(yvals) * 1.25]);

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

    svg.append("g")
      .attr("class", "y axis")
      .call(yAxis)
      .append("text")
      .attr("transform", "rotate(-90)")
      .attr("y", 6)
      .attr("dy", ".71em")
      .style("text-anchor", "end")
      .text("Players");

    var server = svg.selectAll(".server")
      .data(servers)
      .enter().append("g")
      .attr("class", "servers");

    server.append("path")
      .attr("class", "line")
      .attr("d", function (d) { return line(d.values); })
      .style("stroke", function (d) { return color(d.name); });

    server.append("text")
      .datum(function (d) { return { name: d.name, value: d.values[d.values.length - 1] }; })
      .attr("transform", function (d) { return "translate(" + x(d.value.date) + "," + y(d.value.count) + ")"; })
      .attr("x", 3)
      .attr("dy", ".35em")
      .attr("class", "label")
      .text(function (d) { return capitalize(d.name) + ": " + Math.round(d.value.count) })
      .style("fill", function (d) { return color(d.name); });
  });
}
<|endoftext|>


<commit_before>#! /usr/bin/env node

import { writeFileSync } from 'fs'
import program from 'commander'
import potFormatter from './json2po/potFormatter'
import messageReader from './json2po/jsonMessageReader'

program
  .command('json2pot <src> <dest>', 'converts react-intl extracted json to po/pot')
  .option('-p, --pattern', 'glob pattern used to find the src files')
  .option('-d, --use-default', 'use defaultMessage as msgstr')
  .action((src, dest, { pattern, useDefault }) => {
    writeFileSync(dest,
      potFormatter(messageReader({ cwd: src, messagesPattern: pattern }), useDefault),
    )
  })

program.parse(process.argv)
<commit_msg>cli: implement po2json command<commit_after>#! /usr/bin/env node

import { writeFileSync } from 'fs'
import program from 'commander'
import potFormatter from './json2po/potFormatter'
import messageReader from './json2po/jsonMessageReader'
import poMessageReader from './po2json/poMessageReader'

program
  .command('json2pot <src> <dest>', 'converts react-intl extracted json to po/pot')
  .option('-p, --pattern', 'glob pattern used to find the src files')
  .option('-d, --use-default', 'use defaultMessage as msgstr')
  .action((src, dest, { pattern, useDefault }) => {
    writeFileSync(
      dest,
      potFormatter(messageReader({ cwd: src, messagesPattern: pattern }), useDefault),
    )
  })
  .command('po2json <src> <dest>', 'converts po files to json')
  .option('-p, --pattern', 'glob pattern used to find the src files')
  .option('--pretty', 'preety print json')
  .action((src, dest, { pattern, pretty }) => {
    writeFileSync(
      dest,
      JSON.stringify(poMessageReader({
        cwd: src,
        messagesPattern: pattern,
      }), null, pretty ? '\t' : undefined)
    )
  })

program.parse(process.argv)
<|endoftext|>


<commit_before>// Server-side renderer filter.
//

'use strict';

var _      = require('lodash');
var render = require('../../../../system/render/common');

////////////////////////////////////////////////////////////////////////////////

module.exports = function (N) {

  // Filter middleware that renders view and required layout and sets
  //
  N.wire.after('responder:http', { priority: 10 }, function http_render(env) {

    // Don't render page on an error.
    if (env.err) {
      return;
    }

    // Don't render on JSON requests, just setup headers
    //
    var headers = env.origin.req.headers || {};

    if (headers['x-requested-with'] === 'XMLHttpRequest') {
      env.headers['Content-Type'] = 'application/json';
      env.body =  ('HEAD' === env.origin.req.method) ? null : JSON.stringify(env.res);
      return;
    }

    // Continue with standard http rendering

    var res = env.res
      , view = env.method;

    env.headers['Content-Type'] = 'text/html; charset=UTF-8';

    // If HEAD is requested, it's no need for real rendering.
    if ('HEAD' === env.origin.req.method) {
      env.body = null;
      return;
    }

    // Expose necessary environment/configuration values.
    res.enabled_locales = N.config.locales.enabled;

    // Start rendering.
    env.extras.puncher.start('rendering');

    try {
      env.body = render(N, view, res, _.extend({
        runtime: env.runtime
      , apiPath: env.method
      }, env.helpers));

      if (env.res.layout) {
        env.runtime.layout = env.res.layout;
        env.body = render(N, env.res.layout, res, _.extend({
          runtime: env.runtime
        , apiPath: env.method
        , content: env.body
        }, env.helpers));
      }
    } catch (err) {
      env.err = err;
    }

    env.extras.puncher.stop();
  });
};
<commit_msg>Return JSON instead of error, when method has no template<commit_after>// Server-side renderer filter.
//

'use strict';

var _      = require('lodash');
var render = require('../../../../system/render/common');

////////////////////////////////////////////////////////////////////////////////

module.exports = function (N) {

  // Filter middleware that renders view and required layout and sets
  //
  N.wire.after('responder:http', { priority: 10 }, function http_render(env) {

    // Don't render page on an error.
    if (env.err) {
      return;
    }

    var res = env.res
      , view = env.method
      , headers = env.origin.req.headers || {};

    // if no template found - force reply as for json request
    if (!_.has(N.views, view)) {
      headers['x-requested-with'] = 'XMLHttpRequest';
    }

    // Don't render on JSON requests, just setup headers
    if (headers['x-requested-with'] === 'XMLHttpRequest') {
      env.headers['Content-Type'] = 'application/json';
      env.body =  ('HEAD' === env.origin.req.method) ? null : JSON.stringify(env.res);
      return;
    }

    // Continue with standard http rendering

    env.headers['Content-Type'] = 'text/html; charset=UTF-8';

    // If HEAD is requested, it's no need for real rendering.
    if ('HEAD' === env.origin.req.method) {
      env.body = null;
      return;
    }

    // Expose necessary environment/configuration values.
    res.enabled_locales = N.config.locales.enabled;

    // Start rendering.
    env.extras.puncher.start('rendering');

    try {
      env.body = render(N, view, res, _.extend({
        runtime: env.runtime
      , apiPath: env.method
      }, env.helpers));

      if (env.res.layout) {
        env.runtime.layout = env.res.layout;
        env.body = render(N, env.res.layout, res, _.extend({
          runtime: env.runtime
        , apiPath: env.method
        , content: env.body
        }, env.helpers));
      }
    } catch (err) {
      env.err = err;
    }

    env.extras.puncher.stop();
  });
};
<|endoftext|>


<commit_before>/*
 * Copyright 2017 Teppo Kurki <teppo.kurki@iki.fi>
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0

 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
*/

const debug = require('debug')('signalk:interfaces:webapps')
const fs = require('fs')
const path = require('path')
const express = require('express')
const modulesWithKeyword = require('../modules').modulesWithKeyword

module.exports = function(app) {
  return {
    start: function() {
      mountWebapps(app)
      mountApi(app)
    },
    // tslint:disable-next-line: no-empty
    stop: function() {}
  }
}

function mountWebapps(app) {
  debug('MountWebApps')
  modulesWithKeyword(app, 'signalk-webapp').forEach(moduleData => {
    let webappPath = path.join(moduleData.location, moduleData.module)
    if (fs.existsSync(webappPath + '/public/')) {
      webappPath += '/public/'
    }
    debug('Mounting webapp /' + moduleData.module + ':' + webappPath)
    app.use('/' + moduleData.module, express.static(webappPath))
    app.webapps.push(moduleData.metadata)
  })
}

function mountApi(app) {
  app.get('/webapps', function(req, res, next) {
    res.json(app.webapps)
  })
}
<commit_msg>feature: add custom logo (#1043)<commit_after>/*
 * Copyright 2017 Teppo Kurki <teppo.kurki@iki.fi>
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0

 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
*/

const debug = require('debug')('signalk:interfaces:webapps')
const fs = require('fs')
const path = require('path')
const express = require('express')
const modulesWithKeyword = require('../modules').modulesWithKeyword

module.exports = function(app) {
  return {
    start: function() {
      mountWebapps(app)
      mountApi(app)
    },
    // tslint:disable-next-line: no-empty
    stop: function() {}
  }
}

function mountWebapps(app) {
  debug('MountWebApps')
  const logopath = path.resolve(app.config.configPath, 'logo.svg')
  if(fs.existsSync(logopath)) {
    debug(`Found custom logo at ${logopath}, adding route for it`)
    app.use('/admin/fonts/signal-k-logo-image-text.*', (req, res) => res.sendFile(logopath))
  }
  modulesWithKeyword(app, 'signalk-webapp').forEach(moduleData => {
    let webappPath = path.join(moduleData.location, moduleData.module)
    if (fs.existsSync(webappPath + '/public/')) {
      webappPath += '/public/'
    }
    debug('Mounting webapp /' + moduleData.module + ':' + webappPath)
    app.use('/' + moduleData.module, express.static(webappPath))
    app.webapps.push(moduleData.metadata)
  })
}

function mountApi(app) {
  app.get('/webapps', function(req, res, next) {
    res.json(app.webapps)
  })
}
<|endoftext|>