<commit_before>import React, { Component } from 'react'
import {Icon} from '@conveyal/woonerf'
import { Button, Alert, Checkbox, ButtonToolbar, FormGroup, Form, FormControl, ControlLabel } from 'react-bootstrap'
import { sentence as toSentenceCase } from 'change-case'
import Rcslider from 'rc-slider'

import { polyline as getPolyline } from '../../../scenario-editor/utils/valhalla'
import { CLICK_OPTIONS } from '../../util'

export default class EditShapePanel extends Component {
  async drawPatternFromStops (pattern, stops) {
    let newShape = await getPolyline(stops)
    console.log(newShape)
    this.props.updateActiveEntity(pattern, 'trippattern', {shape: {type: 'LineString', coordinates: newShape}})
    this.props.saveActiveEntity('trippattern')
    return true
  }
  renderEditSettings (isEditing) {
    return isEditing
      ? <FormGroup className='col-xs-12'>
        <ControlLabel style={{marginTop: '5px'}}>Edit settings</ControlLabel>
        <Checkbox style={{marginTop: '0px'}} checked={this.props.editSettings.followStreets} onChange={() => this.props.updateEditSetting('followStreets', !this.props.editSettings.followStreets)}>
          Snap to streets
        </Checkbox>
        <Checkbox checked={this.props.editSettings.snapToStops} onChange={() => this.props.updateEditSetting('snapToStops', !this.props.editSettings.snapToStops)}>
          Snap to stops
        </Checkbox>
        <Checkbox checked={!this.props.editSettings.hideStops} onChange={() => this.props.updateEditSetting('hideStops', !this.props.editSettings.hideStops)}>
          Show stops
        </Checkbox>
        <ControlLabel>Editing mode</ControlLabel>
        <FormControl
          componentClass='select'
          value={this.props.editSettings.onMapClick}
          onChange={(evt) => this.props.updateEditSetting('onMapClick', evt.target.value)}
        >
          {CLICK_OPTIONS.map(v => {
            return <option key={v} value={v}>{toSentenceCase(v.replace('_', ' '))}</option>
          })}
        </FormControl>
        {this.props.editSettings.onMapClick === 'ADD_STOPS_AT_INTERVAL'
          ?

            <Rcslider
              min={100}
              max={2000}
              defaultValue={this.props.editSettings.stopInterval}
              onAfterChange={(value) => this.props.updateEditSetting('stopInterval', value)}
              step={25}
              marks={{
                100: '100m',
                400: 400m,
                800: '800m',
                1600: '1600m'
              }}
              tipFormatter={(value) => {
                return `${value}m (${Math.round(value * 0.000621371 * 100) / 100}mi)`
              }}
            />

          : this.props.editSettings.onMapClick === 'ADD_STOPS_AT_INTERSECTIONS'
          ? <Form inline>
            {/* distance from intersection */}
            <FormControl
              type='number' step={5} min={0} max={100}
              value={this.props.editSettings.distanceFromIntersection}
              onChange={(evt) => this.props.updateEditSetting('distanceFromIntersection', +evt.target.value)}
              style={{width: '60px', marginTop: '10px'}}
            />
             meters
            {/* before/after intersection */}
            <FormControl
              componentClass='select'
              value={this.props.editSettings.afterIntersection}
              onChange={(evt) => this.props.updateEditSetting('afterIntersection', +evt.target.value)}
              style={{width: '80px', marginTop: '10px'}}
            >
              <option value={1}>after</option>
              <option value={0}>before</option>
            </FormControl>
             every
            {/* every n intersections */}
            <FormControl
              type='number' step={1} max={10} min={1}
              value={this.props.editSettings.intersectionStep}
              onChange={(evt) => this.props.updateEditSetting('intersectionStep', +evt.target.value)}
              style={{width: '55px', marginTop: '10px'}}
            />
             intersections
          </Form>
          : null
        }
        {this.props.editSettings.onMapClick.includes('ADD_')
          ? <Alert bsStyle='warning' style={{marginTop: '30px'}}>
            Warning! This editing mode creates new stops. Unless no existing stops are nearby, this mode is not recommended.
          </Alert>
          : null
        }
      </FormGroup>
      : null
  }
  renderEditButtons (isEditing, activePattern) {
    const buttons = []
    if (isEditing) {
      buttons.push(<Button
        style={{marginBottom: '5px'}}
        key='save'
        disabled={this.props.editSettings.coordinatesHistory.length === 0}
        bsStyle='primary'
        onClick={() => {
          this.props.saveActiveEntity('trippattern')
          .then(() => {
            this.props.updateEditSetting('editGeometry', !this.props.editSettings.editGeometry, activePattern)
          })
        }}
      >
        <Icon type='check' /> Save
      </Button>)
      buttons.push(<Button
        style={{marginBottom: '5px'}}
        key='undo'
        disabled={this.props.editSettings.actions.length === 0}
        bsStyle='default'
        onClick={() => {
          this.props.undoActiveTripPatternEdits()
        }}
      >
        <Icon type='undo' /> Undo
      </Button>)
      buttons.push(<Button
        style={{marginBottom: '5px'}}
        key='cancel'
        bsStyle='default'
        onClick={() => {
          this.props.resetActiveEntity(activePattern, 'trippattern')
          this.props.updateEditSetting('editGeometry', !this.props.editSettings.editGeometry, activePattern)
        }}
      >
        <Icon type='times' /> Cancel
      </Button>)
    } else {
      buttons.push(<Button
        style={{marginBottom: '5px'}}
        key='edit'
        bsStyle={'warning'}
        onClick={() => {
          this.props.updateEditSetting('editGeometry', !this.props.editSettings.editGeometry, activePattern)
        }}
      >
        <Icon type='pencil' /> Edit
      </Button>)
      buttons.push(<Button
        style={{marginBottom: '5px'}}
        key='delete'
        bsStyle='danger'
        onClick={() => {
          this.props.showConfirmModal({
            title: `Delete shape for trip pattern?`,
            body: `Are you sure you want to delete this trip pattern shape?`,
            onConfirm: () => {
              this.props.updateActiveEntity(activePattern, 'trippattern', {shape: null})
              this.props.saveActiveEntity('trippattern')
            }
          })
        }}
      >
        <Icon type='trash' /> Delete
      </Button>)
      buttons.push(<Button
        style={{marginBottom: '5px'}}
        key='create'
        bsStyle='success'
        onClick={() => {
          this.props.showConfirmModal({
            title: `Create pattern shape from stops?`,
            body: `Are you sure you want to overwrite this trip pattern?`,
            onConfirm: () => {
              let stopLocations = this.props.stops && activePattern.patternStops && activePattern.patternStops.length
                ? activePattern.patternStops.map((s, index) => {
                  let stop = this.props.stops.find(st => st.id === s.stopId)
                  return {lng: stop.stop_lon, lat: stop.stop_lat}
                })
                : []
              return this.drawPatternFromStops(activePattern, stopLocations)
            }
          })
        }}
      >
        <Icon type='map-marker' /> Create
      </Button>)
    }
    return buttons
  }
  render () {
    const { activePattern } = this.props
    return (

          Pattern Shape

        <ButtonToolbar>
          {this.renderEditButtons(this.props.editSettings.editGeometry, activePattern)}
          {this.renderEditSettings(this.props.editSettings.editGeometry)}
        </ButtonToolbar>

    )
  }
}
<commit_msg>catch error if pattern drawing fails<commit_after>import React, { Component } from 'react'
import {Icon} from '@conveyal/woonerf'
import { Button, Alert, Checkbox, ButtonToolbar, FormGroup, Form, FormControl, ControlLabel } from 'react-bootstrap'
import { sentence as toSentenceCase } from 'change-case'
import Rcslider from 'rc-slider'

import { polyline as getPolyline } from '../../../scenario-editor/utils/valhalla'
import { CLICK_OPTIONS } from '../../util'

export default class EditShapePanel extends Component {
  async drawPatternFromStops (pattern, stops) {
    let newShape = await getPolyline(stops)
    if (newShape) {
      this.props.updateActiveEntity(pattern, 'trippattern', {shape: {type: 'LineString', coordinates: newShape}})
      this.props.saveActiveEntity('trippattern')
      return true
    } else {
      this.props.setErrorMessage('Error drawing pattern from stops! Some stops may be unreachable by streets.')
      return false
    }
  }
  renderEditSettings (isEditing) {
    return isEditing
      ? <FormGroup className='col-xs-12'>
        <ControlLabel style={{marginTop: '5px'}}>Edit settings</ControlLabel>
        <Checkbox style={{marginTop: '0px'}} checked={this.props.editSettings.followStreets} onChange={() => this.props.updateEditSetting('followStreets', !this.props.editSettings.followStreets)}>
          Snap to streets
        </Checkbox>
        <Checkbox checked={this.props.editSettings.snapToStops} onChange={() => this.props.updateEditSetting('snapToStops', !this.props.editSettings.snapToStops)}>
          Snap to stops
        </Checkbox>
        <Checkbox checked={!this.props.editSettings.hideStops} onChange={() => this.props.updateEditSetting('hideStops', !this.props.editSettings.hideStops)}>
          Show stops
        </Checkbox>
        <ControlLabel>Editing mode</ControlLabel>
        <FormControl
          componentClass='select'
          value={this.props.editSettings.onMapClick}
          onChange={(evt) => this.props.updateEditSetting('onMapClick', evt.target.value)}
        >
          {CLICK_OPTIONS.map(v => {
            return <option key={v} value={v}>{toSentenceCase(v.replace('_', ' '))}</option>
          })}
        </FormControl>
        {this.props.editSettings.onMapClick === 'ADD_STOPS_AT_INTERVAL'
          ?

            <Rcslider
              min={100}
              max={2000}
              defaultValue={this.props.editSettings.stopInterval}
              onAfterChange={(value) => this.props.updateEditSetting('stopInterval', value)}
              step={25}
              marks={{
                100: '100m',
                400: 400m,
                800: '800m',
                1600: '1600m'
              }}
              tipFormatter={(value) => {
                return `${value}m (${Math.round(value * 0.000621371 * 100) / 100}mi)`
              }}
            />

          : this.props.editSettings.onMapClick === 'ADD_STOPS_AT_INTERSECTIONS'
          ? <Form inline>
            {/* distance from intersection */}
            <FormControl
              type='number' step={5} min={0} max={100}
              value={this.props.editSettings.distanceFromIntersection}
              onChange={(evt) => this.props.updateEditSetting('distanceFromIntersection', +evt.target.value)}
              style={{width: '60px', marginTop: '10px'}}
            />
             meters
            {/* before/after intersection */}
            <FormControl
              componentClass='select'
              value={this.props.editSettings.afterIntersection}
              onChange={(evt) => this.props.updateEditSetting('afterIntersection', +evt.target.value)}
              style={{width: '80px', marginTop: '10px'}}
            >
              <option value={1}>after</option>
              <option value={0}>before</option>
            </FormControl>
             every
            {/* every n intersections */}
            <FormControl
              type='number' step={1} max={10} min={1}
              value={this.props.editSettings.intersectionStep}
              onChange={(evt) => this.props.updateEditSetting('intersectionStep', +evt.target.value)}
              style={{width: '55px', marginTop: '10px'}}
            />
             intersections
          </Form>
          : null
        }
        {this.props.editSettings.onMapClick.includes('ADD_')
          ? <Alert bsStyle='warning' style={{marginTop: '30px'}}>
            Warning! This editing mode creates new stops. Unless no existing stops are nearby, this mode is not recommended.
          </Alert>
          : null
        }
      </FormGroup>
      : null
  }
  renderEditButtons (isEditing, activePattern) {
    const buttons = []
    if (isEditing) {
      buttons.push(<Button
        style={{marginBottom: '5px'}}
        key='save'
        disabled={this.props.editSettings.coordinatesHistory.length === 0}
        bsStyle='primary'
        onClick={() => {
          this.props.saveActiveEntity('trippattern')
          .then(() => {
            this.props.updateEditSetting('editGeometry', !this.props.editSettings.editGeometry, activePattern)
          })
        }}
      >
        <Icon type='check' /> Save
      </Button>)
      buttons.push(<Button
        style={{marginBottom: '5px'}}
        key='undo'
        disabled={this.props.editSettings.actions.length === 0}
        bsStyle='default'
        onClick={() => {
          this.props.undoActiveTripPatternEdits()
        }}
      >
        <Icon type='undo' /> Undo
      </Button>)
      buttons.push(<Button
        style={{marginBottom: '5px'}}
        key='cancel'
        bsStyle='default'
        onClick={() => {
          this.props.resetActiveEntity(activePattern, 'trippattern')
          this.props.updateEditSetting('editGeometry', !this.props.editSettings.editGeometry, activePattern)
        }}
      >
        <Icon type='times' /> Cancel
      </Button>)
    } else {
      buttons.push(<Button
        style={{marginBottom: '5px'}}
        key='edit'
        bsStyle={'warning'}
        onClick={() => {
          this.props.updateEditSetting('editGeometry', !this.props.editSettings.editGeometry, activePattern)
        }}
      >
        <Icon type='pencil' /> Edit
      </Button>)
      buttons.push(<Button
        style={{marginBottom: '5px'}}
        key='delete'
        bsStyle='danger'
        onClick={() => {
          this.props.showConfirmModal({
            title: `Delete shape for trip pattern?`,
            body: `Are you sure you want to delete this trip pattern shape?`,
            onConfirm: () => {
              this.props.updateActiveEntity(activePattern, 'trippattern', {shape: null})
              this.props.saveActiveEntity('trippattern')
            }
          })
        }}
      >
        <Icon type='trash' /> Delete
      </Button>)
      buttons.push(<Button
        style={{marginBottom: '5px'}}
        key='create'
        bsStyle='success'
        onClick={() => {
          this.props.showConfirmModal({
            title: `Create pattern shape from stops?`,
            body: `Are you sure you want to overwrite this trip pattern?`,
            onConfirm: () => {
              let stopLocations = this.props.stops && activePattern.patternStops && activePattern.patternStops.length
                ? activePattern.patternStops.map((s, index) => {
                  let stop = this.props.stops.find(st => st.id === s.stopId)
                  return {lng: stop.stop_lon, lat: stop.stop_lat}
                })
                : []
              return this.drawPatternFromStops(activePattern, stopLocations)
            }
          })
        }}
      >
        <Icon type='map-marker' /> Create
      </Button>)
    }
    return buttons
  }
  render () {
    const { activePattern } = this.props
    return (

          Pattern Shape

        <ButtonToolbar>
          {this.renderEditButtons(this.props.editSettings.editGeometry, activePattern)}
          {this.renderEditSettings(this.props.editSettings.editGeometry)}
        </ButtonToolbar>

    )
  }
}
<|endoftext|>


<commit_before>const Gulp = require('gulp');
const Plugins = require('gulp-load-plugins')();
const Fs = require('fs');
const Del = require('del');
const RunSequence = require('run-sequence');

const PackageJSON = JSON.parse(Fs.readFileSync('./package.json'));

const BANNER = `/*!
 * ${PackageJSON.config.packageName} v${PackageJSON.version} (${PackageJSON.website})
 * Copyright ${PackageJSON.config.projectStartYear} ${PackageJSON.author}
 * Licensed under ${PackageJSON.license} (${PackageJSON.config.licenseUrl})
 */`;

Gulp.task('default', () => {
});

Gulp.task('js:clean', () => {
  return Del(['dist/js/**/*']);
});

Gulp.task('js:copy', ['js:clean'],() => {
  return Gulp.src(['bootstrap/dist/js/**/*.js'], { cwd: 'node_modules' })
    .pipe(Gulp.dest('dist/js'));
});

Gulp.task('css:clean', () => {
  return Del(['dist/css/**/*']);
});

Gulp.task('css:lint', () => {
  return Gulp.src(['scss/**/*.scss'])
    .pipe(Plugins.stylelint({
      failAfterError: true,
      reporters: [
        { formatter: 'verbose', console: true },
      ],
    }));
});

Gulp.task('css:build', () => {
  return Gulp.src(['scss/**/*.scss'])
    .pipe(Plugins.plumber({
      errorHandler(err) {
        console.error(err.message);
        this.emit('end');
      },
    }))
    .pipe(Plugins.sass({
      includePaths: [
        'node_modules/',
      ],
      outputStyle: 'expanded',
      sourceMap: true,
      sourceMapContents: true,
      lineFeed: 'lf',
      precision: 6,
    }))
    .pipe(Plugins.plumber.stop())
    .pipe(Plugins.postcss({
      noMap: true,
      use: 'autoprefixer',
      config: '../build/postcss.config.js',
      replace: 'dist/css/bootstrap.css',
    }))
    .pipe(Gulp.dest('dist/css'));
});

Gulp.task('css:banner', () => {
  return Gulp.src(['dist/css/*.css'])
    .pipe(Plugins.replace('/*!', `@charset "UTF-8";\n${BANNER}\n/*!`))
    .pipe(Gulp.dest('dist/css'));
});

Gulp.task('css:minify', () => {
  return Gulp.src(['dist/css/*.css', '!dist/css/*.min.css'])
    .pipe(Plugins.cleanCss({
      level: 1,
    }))
    .pipe(Plugins.rename({
      extname: '.min.css',
    }))
    .pipe(Gulp.dest('dist/css'));
});

Gulp.task('clean', (resolve) => {
  return RunSequence(['css:clean'], () => { resolve(); });
});

Gulp.task('css', (resolve) => {
  return RunSequence('clean', 'css:build', 'css:minify', 'css:banner', () => { resolve(); });
});
<commit_msg>:tropical_drink: Update integrated gulp task<commit_after>const Gulp = require('gulp');
const Plugins = require('gulp-load-plugins')();
const Fs = require('fs');
const Del = require('del');
const RunSequence = require('run-sequence');

const PackageJSON = JSON.parse(Fs.readFileSync('./package.json'));

const BANNER = `/*!
 * ${PackageJSON.config.packageName} v${PackageJSON.version} (${PackageJSON.website})
 * Copyright ${PackageJSON.config.projectStartYear} ${PackageJSON.author}
 * Licensed under ${PackageJSON.license} (${PackageJSON.config.licenseUrl})
 */`;

Gulp.task('default', () => {
});

Gulp.task('js:clean', () => {
  return Del(['dist/js/**/*']);
});

Gulp.task('js:copy', ['js:clean'],() => {
  return Gulp.src(['bootstrap/dist/js/**/*.js'], { cwd: 'node_modules' })
    .pipe(Gulp.dest('dist/js'));
});

Gulp.task('css:clean', () => {
  return Del(['dist/css/**/*']);
});

Gulp.task('css:lint', () => {
  return Gulp.src(['scss/**/*.scss'])
    .pipe(Plugins.stylelint({
      failAfterError: true,
      reporters: [
        { formatter: 'verbose', console: true },
      ],
    }));
});

Gulp.task('css:build', () => {
  return Gulp.src(['scss/**/*.scss'])
    .pipe(Plugins.plumber({
      errorHandler(err) {
        console.error(err.message);
        this.emit('end');
      },
    }))
    .pipe(Plugins.sass({
      includePaths: [
        'node_modules/',
      ],
      outputStyle: 'expanded',
      sourceMap: true,
      sourceMapContents: true,
      lineFeed: 'lf',
      precision: 6,
    }))
    .pipe(Plugins.plumber.stop())
    .pipe(Plugins.postcss({
      noMap: true,
      use: 'autoprefixer',
      config: '../build/postcss.config.js',
      replace: 'dist/css/bootstrap.css',
    }))
    .pipe(Gulp.dest('dist/css'));
});

Gulp.task('css:banner', () => {
  return Gulp.src(['dist/css/*.css'])
    .pipe(Plugins.replace('/*!', `@charset "UTF-8";\n${BANNER}\n/*!`))
    .pipe(Gulp.dest('dist/css'));
});

Gulp.task('css:minify', () => {
  return Gulp.src(['dist/css/*.css', '!dist/css/*.min.css'])
    .pipe(Plugins.cleanCss({
      level: 1,
    }))
    .pipe(Plugins.rename({
      extname: '.min.css',
    }))
    .pipe(Gulp.dest('dist/css'));
});

Gulp.task('clean', (resolve) => {
  return RunSequence(['css:clean', 'js:clean'], () => { resolve(); });
});

Gulp.task('css', (resolve) => {
  return RunSequence('css:clean', 'css:build', 'css:minify', 'css:banner', () => { resolve(); });
});

Gulp.task('js', (resolve) => {
  return RunSequence('js:clean', 'js:copy', () => { resolve(); });
});
<|endoftext|>


<commit_before>var fs = require('fs');
var io = require('io');
var f1 = require('f1');
var find = require('dom-select');
var $ = require('jquery');
var PIXI = require('pixi');
var framework = require('../../framework/index');
var Model = require('../../model/model');
var states = require('./states');
module.exports = Section;
var SERVERNAME = window.location.origin;

function socketSetup(){
    var curSession = window.location.href;
    curSession = curSession.split('/');
    var end = curSession.length -1;
    var curSessionId = curSession[end];
    curSession = '/'+curSession[end - 1] +'/'+ curSession[end];

    var socket = io.connect(SERVERNAME);
    socket.emit('validate',curSessionId);
    socket.on('fullorinvalid',function(){
      framework.go('/home');
      done();
    });
    socket = io.connect(SERVERNAME +curSession);
    socket.emit('joinSession','testname',curSessionId);
    socket.on('userCount',function(msg){
       var Usertab =  find('.cd-tabs-content li[data-content=Users]');
       var countElement;
       countElement = document.getElementById('userCount');
       if(countElement){
        countElement.innerHTML = msg;
       }else{
        countElement = document.createElement('div');
        countElement.id = 'userCount';
        countElement.innerHTML = msg;
        Usertab.appendChild(countElement);
       }

    });
    socket.on('userJoining',function(msg,userCount){
      //update user list clientside
      //update chat tab with msg
       var Chattab =  find('.cd-tabs-content li[data-content=Chat]');

       var div =document.createElement('div');
       div.innerHTML = msg;
       Chattab.appendChild(div);
      //adjust all users priority
      //send edited user list to db
    });
    socket.on('userLeaving',function(msg,userCount){
      //update user list clientside
      //update chat tab with msg
       var Chattab =  find('.cd-tabs-content li[data-content=Chat]');

       var div =document.createElement('div');
       div.innerHTML = msg;
       Chattab.appendChild(div);
      //adjust all users priority
      //send edited user list to db
    });

    console.log(curSession);
    return socket;
  }

function Section() {}

Section.prototype = {

  init: function(req, done) {

    var socket = socketSetup();
    var body = find('body');
    var content = find('#content');
    this.section = document.createElement('div');
    this.section.innerHTML = fs.readFileSync(__dirname + '/index.hbs', 'utf8');
    content.appendChild(this.section);

    createTabs();

    // find('#tabs').style.width = body.offsetWidth * 0.25 + 'px';

    states.init.whiteboard.position[0] = body.offsetWidth * 1.5;

    // Strap html to application
    var canvas = find('#whiteboard-container');
    console.log("width", canvas.style.width);
    var renderer = new PIXI.WebGLRenderer(body.offsetWidth * 0.75, body.offsetHeight - 60);
    canvas.appendChild(renderer.view);

    var stage = new PIXI.Container();

    this.animate = new f1().states(states)
                           .transitions(require('./transitions'))
                           .targets({ whiteboard: find('#whiteboard')})
                           .parsers(require('f1-dom'))
                           .init('init');

    done();
  },

  resize: function(w, h) {
  },

  animateIn: function(req, done) {
    this.animate.go('idle', function() {
      done();
    }.bind(this));
  },

  animateOut: function(req, done) {
    this.animate.go('out', function() {
      done();
    }.bind(this));
  },

  destroy: function(req, done) {
    console.log("Destroy!");
    this.section.parentNode.removeChild(this.section);
    done();
  }
};

function createTabs() {
  $(document).ready(function($){
    var toolItems = $('#flyout_menu li a');

    toolItems.on('click', function(event) {
      var selectedItem = $(this);

      if(!selectedItem.hasClass('menuSelected')) {
        toolItems.removeClass('menuSelected');
        selectedItem.addClass('menuSelected');
      }
      else {
        toolItems.removeClass('menuSelected');
      }
    });

    var tabItems = $('.cd-tabs-navigation a'),
    tabContentWrapper = $('.cd-tabs-content');

    tabItems.on('click', function(event){
      event.preventDefault();
      var selectedItem = $(this);
      if( !selectedItem.hasClass('selected') ) {
        var selectedTab = selectedItem.data('content'),
        selectedContent = tabContentWrapper.find('li[data-content="'+selectedTab+'"]'),
        slectedContentHeight = selectedContent.innerHeight();

        tabItems.removeClass('selected');
        selectedItem.addClass('selected');
        selectedContent.addClass('selected').siblings('li').removeClass('selected');
        //animate tabContentWrapper height when content changes
        tabContentWrapper.animate({
          'height': slectedContentHeight
        }, 200);
      }
    });

  //hide the .cd-tabs::after element when tabbed navigation has scrolled to the end (mobile version)
  checkScrolling($('.cd-tabs nav'));
  $(window).on('resize', function(){
    checkScrolling($('.cd-tabs nav'));
    tabContentWrapper.css('height', 'auto');
  });
  $('.cd-tabs nav').on('scroll', function(){
    checkScrolling($(this));
  });

  function checkScrolling(tabs){
    var totalTabWidth = parseInt(tabs.children('.cd-tabs-navigation').width()),
    tabsViewport = parseInt(tabs.width());
    if( tabs.scrollLeft() >= totalTabWidth - tabsViewport) {
      tabs.parent('.cd-tabs').addClass('is-ended');
    } else {
      tabs.parent('.cd-tabs').removeClass('is-ended');
    }
  }
});
}
<commit_msg>merging<commit_after>var fs = require('fs');
var io = require('io');
var f1 = require('f1');
var find = require('dom-select');
var $ = require('jquery');
var PIXI = require('pixi');
var framework = require('../../framework/index');
var Model = require('../../model/model');
var states = require('./states');
var SERVERNAME = 'http://localhost:3000';
var createTabs = require('./ui/tabs');

module.exports = Section;

function Section() {}

Section.prototype = {

  init: function(req, done) {
    var curSession = window.location.href;
    curSession = curSession.split('/');
    var end = curSession.length -1;
    var curSessionId = curSession[end];
    curSession = '/'+curSession[end - 1] +'/'+ curSession[end];
    var socket = io.connect(SERVERNAME);
    socket.emit('validate',curSessionId);
    socket.on('notFound',function(){
      framework.go('/home');
      done();
    });
    socket = io.connect(SERVERNAME + curSession);
    socket.emit('joinSession','testname',curSessionId);

    var content = find('#content');
    this.section = document.createElement('div');
    this.section.innerHTML = fs.readFileSync(__dirname + '/index.hbs', 'utf8');
    content.appendChild(this.section);

    createTabs();

    states.init.whiteboard.position[0] = document.body.offsetWidth * 1.5;

    // Strap html to application
    var canvas = find('#whiteboard-container');
    var renderer = new PIXI.autoDetectRenderer(document.body.offsetWidth * 0.75, document.body.offsetHeight - 60);
    renderer.backgroundColor = 0x123feb;
    canvas.appendChild(renderer.view);

    var stage = new PIXI.Container();

    // This creates a texture from a 'bunny.png' image.
    var bunnyTexture = PIXI.Texture.fromImage('images/pencil-icon.png');
    var bunny = new PIXI.Sprite(bunnyTexture);

    // Setup the position and scale of the bunny
    bunny.position.x = 400;
    bunny.position.y = 300;

    bunny.scale.x = 2;
    bunny.scale.y = 2;

    // Add the bunny to the scene we are building.
    stage.addChild(bunny);

    // kick off the animation loop (defined below)
    animate();

    function animate() {
        // start the timer for the next animation loop
        requestAnimationFrame(animate);

        // each frame we spin the bunny around a bit
        bunny.rotation += 0.01;

        // this is the main render call that makes pixi draw your container and its children.
        renderer.render(stage);
    }

    socket.on('news', function (data) {
      console.log(data);
      socket.emit('my other event', { my: 'data' });
    });

    this.animate = new f1().states(states)
                           .transitions(require('./transitions'))
                           .targets({ whiteboard: find('#whiteboard')})
                           .parsers(require('f1-dom'))
                           .init('init');

    done();
  },

  resize: function(w, h) {
  },

  animateIn: function(req, done) {
    this.animate.go('idle', function() {
      done();
    }.bind(this));
  },

  animateOut: function(req, done) {
    this.animate.go('out', function() {
      done();
    }.bind(this));
  },

  destroy: function(req, done) {
    console.log("Destroy!");
    this.section.parentNode.removeChild(this.section);
    done();
  }
};<|endoftext|>


<commit_before>var rollup = require('rollup');
var traverseTree = require('./arithmetic').traverseTree;
var getConditionModule = require('./trace').getConditionModule;
var extend = require('./utils').extend;
var getAlias = require('./utils').getAlias;
var pluginBundleHook = require('./compile').pluginBundleHook;

exports.rollupTree = function(loader, tree, entryPoints, traceOpts, compileOpts, outputOpts) {
  /*
   * 1. Determine the tree entry points and optimization points
   *
   * eg for the tree:
   *
   * A -> B -> C
   * D -> C
   *
   * A and D are the entry points.
   * Optimization points are ES module entry points to be optimized
   *
   */

  entryPoints = entryPoints.concat([]);

  var optimizationPoints = [];

  var entryMap = {};

  function isESM(moduleName) {
    return tree[moduleName] && tree[moduleName].metadata && tree[moduleName].metadata.format == 'esm' && !tree[moduleName].metadata.originalSource;
  }

  // for each module in the tree, we traverse the whole tree
  // we then relate each module in the tree to the first traced entry point
  Object.keys(tree).forEach(function(entryPoint) {
    traverseTree(tree, entryPoint, function(depName, parentName) {
      // esm from a non-esm parent means this is an optimization entry point from the linking alogorithm perspective
      if (parentName && isESM(depName) && !isESM(parentName) && optimizationPoints.indexOf(depName) == -1)
        optimizationPoints.push(depName);

      // if we have a entryMap for the given module, then stop
      if (entryMap[depName])
        return false;

      if (parentName)
        entryMap[depName] = entryPoint;
    }, traceOpts);
  });

  // the entry points are then the modules not represented in entryMap
  Object.keys(tree).forEach(function(entryPoint) {
    if (!entryMap[entryPoint] && tree[entryPoint] && entryPoints.indexOf(entryPoint) == -1)
      entryPoints.push(entryPoint);
  });

  // if all the entry points are ES modules,
  // then we can create a single dummy entry point
  // that represents the tree
  var esmEntryPoints = 0;
  entryPoints.forEach(function(entryPoint) {
    if (tree[entryPoint].metadata && tree[entryPoint].metadata.format == 'esm')
      esmEntryPoints ++;
  });

  if (esmEntryPoints > 1 && esmEntryPoints == entryPoints.length) {
    var dummySource = 'export * from "' + entryPoints[0] + '";\n';
    var dummyDepMap = {};

    entryPoints.forEach(function(entryPoint) {
      dummyDepMap[entryPoint] = entryPoint;

      dummySource += 'import "' + entryPoint + '";';
    });

    tree['@dummy-entry-point'] = {
      name: '@dummy-entry-point',
      path: null,
      metadata: { format: 'esm' },
      deps: entryPoints,
      depMap: dummyDepMap,
      source: dummySource
    };
    entryPoints = ['@dummy-entry-point'];
  }

  // optimization points are then es module entry points
  entryPoints.forEach(function(entryPoint) {
    if (isESM(entryPoint) && optimizationPoints.indexOf(entryPoint) == -1)
      optimizationPoints.push(entryPoint);
  });

  /*
   * 2. Determine unoptimizable modules, splitting them out into their own optimization points
   *
   * eg for the tree:
   *   A -> B -> C -> D
   *   E -> C -> D
   *
   * A, E are top-level entry points detected by the previous step
   *   (and hence optimization points if they are es modules)
   * C is not optimizable because it has two unique parent entry points
   *   (which is what this step looks for)
   * So C becomes its own optimization point
   * Leading to D inlining into C and B inlining into A
   *
   */

  // for each module in the tree, we track its parent optimization point
  // as soon as a module has two parent entry points, it is not optimizable
  // and we set it to undefined here. It then becomes its own optimizationPoint.
  var optimizationParentMap = {};

  // build up the parent entry point map as above
  // we use for over forEach because this list will grow as we go
  for (var i = 0; i < optimizationPoints.length; i++) {
    var entryPoint = optimizationPoints[i];
    traverseTree(tree, entryPoint, function(depName, parentName) {

      // we only traverse ES module tree subgraphs
      if (!isESM(depName))
        return false;

      if (depName == entryPoint)
        return;

      // dont traverse through other entry points
      if (optimizationPoints.indexOf(depName) != -1)
        return false;

      if (!optimizationParentMap[depName]) {
        optimizationParentMap[depName] = entryPoint;
        return;
      }

      // module in two separate entry point graphs -> it becomes its own optimization entry point
      if (optimizationParentMap[depName] != entryPoint) {
        optimizationParentMap[depName] = undefined;

        // this new optimization point will then be traversed in turn as part of this loop later
        optimizationPoints.push(depName);
      }
    }, traceOpts);
  }

  /*
   * 3. Given complete optimization points, populate subgraph externals
   *
   * eg for the graph
   *    A -> B -> C
   *
   * Where A is the optimization point, and C is not ESM, another optimization point,
   * or not contained in our build tree, then we mark 'C' as an external.
   *
   * That is, optimizationGraphExternals[A] = [C]
   *
   * This externals input is used in the Rollup API.
   * This way we just optimize B into A, retaining an explicit dependency on C.
   */

  var inlinedModules = [];
  var optimizationGraphExternals = {};

  optimizationPoints.forEach(function(entryPoint) {
    // the subgraph object is the list of modules in the subgraph
    // and the list of modules that are "external" boundaries of the subgraph
    var externals = [];

    // this traversal is a bit odd, since we need to traverse the full
    // dependency graph to detect externals, not just the direct build graph
    traverseTree(tree, entryPoint, function(depName, parentName) {
      if (!isESM(depName) || (depName != entryPoint && optimizationPoints.indexOf(depName) != -1))
        return false;

      var depLoad = tree[depName];
      depLoad.deps && depLoad.deps.forEach(function(depName) {
        depName = depLoad.depMap[depName];
        if (depName == entryPoint)
          return;

        // anything not ESM, not in the tree, or an optimization point, is external
        if (!isESM(depName) || optimizationPoints.indexOf(depName) != -1) {
          if (externals.indexOf(depName) == -1)
            externals.push(depName);
        }
        else {
          if (inlinedModules.indexOf(depName) == -1)
            inlinedModules.push(depName);
        }
      }, traceOpts);
    });

    optimizationGraphExternals[entryPoint] = externals;
  });

  // finally we rollup each optimization graph
  var rolledUpTree = {};
  Object.keys(tree).forEach(function(moduleName) {
    if (inlinedModules.indexOf(moduleName) == -1)
      rolledUpTree[moduleName] = tree[moduleName];
  });

  // compute the inlineMap
  var inlineMap = {};
  inlinedModules.forEach(function(moduleName) {
    var optimizationParent = optimizationParentMap[moduleName];
    (inlineMap[optimizationParent] = inlineMap[optimizationParent] || []).push(moduleName);
  });

  // if every module in the tree is rolled-up, then we can do a full tree rollup
  var fullTreeRollup = entryPoints.length == 1 && optimizationPoints.length == 1 && Object.keys(optimizationGraphExternals).length == 1;

  return Promise.all(Object.keys(optimizationGraphExternals).map(function(entryPoint) {
    var externals = optimizationGraphExternals[entryPoint];
    var loadList = [];

    // if all externals are outside the tree then this really is a full tree rollup
    // also @node/x requires mean we do need sfx core (pending a better output of these)
    if (fullTreeRollup)
      externals.forEach(function(external) {
        if (external.substr(0, 5) == '@node' || tree[external])
          fullTreeRollup = false;
      });

    var aliasedExternals = externals.map(function(external) {
      var alias = getAlias(loader, external) || externals;
      if (alias.indexOf('#:') != -1)
        alias = alias.replace('#:', '/');
      return alias;
    });

    return rollup.rollup({
      entry: entryPoint,
      external: aliasedExternals,
      plugins: [{
        resolveId: function(id, importer, options) {
          var resolved = importer ? tree[importer].depMap[id] : id;
          var externalIndex = externals.indexOf(resolved);
          if (externalIndex != -1)
            return aliasedExternals[externalIndex];
          return resolved;
        },
        load: function(id, options) {
          if (loadList.indexOf(tree[id]) == -1)
            loadList.push(tree[id]);
          loadList.push(tree[id]);
          return {
            code: tree[id].metadata.originalSource || tree[id].source,
            map: tree[id].metadata.sourceMap
          };
        }
      }],
      onwarn: function(message) {}
    })
    .then(function(bundle) {
      var entryPointLoad = tree[entryPoint];

      var defaultExport = compileOpts.defaultExport;
      if (entryPointLoad.metadata.format != 'esm' && entryPointLoad.metadata.format != 'system' && entryPointLoad.metadata.format != 'register')
        defaultExport = true;

      var generateOptions = {
        sourceMap: !!compileOpts.sourceMaps,
        exports: defaultExport ? 'default' : 'named',
        dest: 'output.js' // workaround for rollup/rollup#1015
      };

      // for a full tree rollup, we pass all the output options into rollup itself
      if (fullTreeRollup) {
        generateOptions.format = compileOpts.format;
        if (generateOptions.format == 'global')
          generateOptions.format = 'iife';
        if (generateOptions.format == 'esm')
          generateOptions.format = 'es6';

        if ((generateOptions.format == 'iife' || generateOptions.format == 'umd') &&
            !compileOpts.globalName)
          throw new Error('The globalName option must be set for full-tree rollup global and UMD builds.');

        if (compileOpts.globalName)
          generateOptions.moduleName = compileOpts.globalName;

        if (compileOpts.globalDeps)
          generateOptions.globals = compileOpts.globalDeps;
      }

      var output = bundle.generate(generateOptions);

      // convert sources list into paths
      if (output.map) {
        output.map.sources = output.map.sources.map(function(name) {
          name = loader.getCanonicalName(loader.decanonicalize(name));
          return tree[name] && tree[name].path || loader.decanonicalize(name);
        });
      }

      if (fullTreeRollup)
        return {
          source: output.code,
          sourceMap: output.map
        };

      // replace the entry point module itself with the inlined subgraph module
      var curInlined = inlineMap[entryPoint] || [];

      // the process of running rollup will itself normalize all dependencies
      // the depMap then just becomes the identity map for non-externals
      var inlinedDepMap = {};
      aliasedExternals.forEach(function(dep, index) {
        inlinedDepMap[dep] = externals[index];
      });

      rolledUpTree[entryPoint] = extend(extend({}, entryPointLoad), {
        deps: aliasedExternals,
        depMap: inlinedDepMap,
        metadata: extend(extend({}, entryPointLoad.metadata), {
          originalSource: undefined,
          sourceMap: output.map
        }),
        source: output.code,
        compactedLoads: loadList
      });
    });
  }))
  .then(function(outputs) {
    if (fullTreeRollup) {
      // for the full tree rollup case, we need to run the plugin bundle hook as we skip compile entirely
      return pluginBundleHook(loader, Object.keys(tree).map(function(name) {
          return tree[name];
        }).filter(function(load) {
          return load;
        }), compileOpts, outputOpts)
      .then(function(pluginResult) {
        return {
          outputs: outputs.concat(pluginResult.outputs),
          assetList: pluginResult.assetList
        };
      });
    }

    return {
      tree: rolledUpTree,
      inlineMap: inlineMap
    };
  });
};
<commit_msg>add error for format = 'register' in rollup<commit_after>var rollup = require('rollup');
var traverseTree = require('./arithmetic').traverseTree;
var getConditionModule = require('./trace').getConditionModule;
var extend = require('./utils').extend;
var getAlias = require('./utils').getAlias;
var pluginBundleHook = require('./compile').pluginBundleHook;

exports.rollupTree = function(loader, tree, entryPoints, traceOpts, compileOpts, outputOpts) {
  /*
   * 1. Determine the tree entry points and optimization points
   *
   * eg for the tree:
   *
   * A -> B -> C
   * D -> C
   *
   * A and D are the entry points.
   * Optimization points are ES module entry points to be optimized
   *
   */

  entryPoints = entryPoints.concat([]);

  var optimizationPoints = [];

  var entryMap = {};

  function isESM(moduleName) {
    return tree[moduleName] && tree[moduleName].metadata && tree[moduleName].metadata.format == 'esm' && !tree[moduleName].metadata.originalSource;
  }

  // for each module in the tree, we traverse the whole tree
  // we then relate each module in the tree to the first traced entry point
  Object.keys(tree).forEach(function(entryPoint) {
    traverseTree(tree, entryPoint, function(depName, parentName) {
      // esm from a non-esm parent means this is an optimization entry point from the linking alogorithm perspective
      if (parentName && isESM(depName) && !isESM(parentName) && optimizationPoints.indexOf(depName) == -1)
        optimizationPoints.push(depName);

      // if we have a entryMap for the given module, then stop
      if (entryMap[depName])
        return false;

      if (parentName)
        entryMap[depName] = entryPoint;
    }, traceOpts);
  });

  // the entry points are then the modules not represented in entryMap
  Object.keys(tree).forEach(function(entryPoint) {
    if (!entryMap[entryPoint] && tree[entryPoint] && entryPoints.indexOf(entryPoint) == -1)
      entryPoints.push(entryPoint);
  });

  // if all the entry points are ES modules,
  // then we can create a single dummy entry point
  // that represents the tree
  var esmEntryPoints = 0;
  entryPoints.forEach(function(entryPoint) {
    if (tree[entryPoint].metadata && tree[entryPoint].metadata.format == 'esm')
      esmEntryPoints ++;
  });

  if (esmEntryPoints > 1 && esmEntryPoints == entryPoints.length) {
    var dummySource = 'export * from "' + entryPoints[0] + '";\n';
    var dummyDepMap = {};

    entryPoints.forEach(function(entryPoint) {
      dummyDepMap[entryPoint] = entryPoint;

      dummySource += 'import "' + entryPoint + '";';
    });

    tree['@dummy-entry-point'] = {
      name: '@dummy-entry-point',
      path: null,
      metadata: { format: 'esm' },
      deps: entryPoints,
      depMap: dummyDepMap,
      source: dummySource
    };
    entryPoints = ['@dummy-entry-point'];
  }

  // optimization points are then es module entry points
  entryPoints.forEach(function(entryPoint) {
    if (isESM(entryPoint) && optimizationPoints.indexOf(entryPoint) == -1)
      optimizationPoints.push(entryPoint);
  });

  /*
   * 2. Determine unoptimizable modules, splitting them out into their own optimization points
   *
   * eg for the tree:
   *   A -> B -> C -> D
   *   E -> C -> D
   *
   * A, E are top-level entry points detected by the previous step
   *   (and hence optimization points if they are es modules)
   * C is not optimizable because it has two unique parent entry points
   *   (which is what this step looks for)
   * So C becomes its own optimization point
   * Leading to D inlining into C and B inlining into A
   *
   */

  // for each module in the tree, we track its parent optimization point
  // as soon as a module has two parent entry points, it is not optimizable
  // and we set it to undefined here. It then becomes its own optimizationPoint.
  var optimizationParentMap = {};

  // build up the parent entry point map as above
  // we use for over forEach because this list will grow as we go
  for (var i = 0; i < optimizationPoints.length; i++) {
    var entryPoint = optimizationPoints[i];
    traverseTree(tree, entryPoint, function(depName, parentName) {

      // we only traverse ES module tree subgraphs
      if (!isESM(depName))
        return false;

      if (depName == entryPoint)
        return;

      // dont traverse through other entry points
      if (optimizationPoints.indexOf(depName) != -1)
        return false;

      if (!optimizationParentMap[depName]) {
        optimizationParentMap[depName] = entryPoint;
        return;
      }

      // module in two separate entry point graphs -> it becomes its own optimization entry point
      if (optimizationParentMap[depName] != entryPoint) {
        optimizationParentMap[depName] = undefined;

        // this new optimization point will then be traversed in turn as part of this loop later
        optimizationPoints.push(depName);
      }
    }, traceOpts);
  }

  /*
   * 3. Given complete optimization points, populate subgraph externals
   *
   * eg for the graph
   *    A -> B -> C
   *
   * Where A is the optimization point, and C is not ESM, another optimization point,
   * or not contained in our build tree, then we mark 'C' as an external.
   *
   * That is, optimizationGraphExternals[A] = [C]
   *
   * This externals input is used in the Rollup API.
   * This way we just optimize B into A, retaining an explicit dependency on C.
   */

  var inlinedModules = [];
  var optimizationGraphExternals = {};

  optimizationPoints.forEach(function(entryPoint) {
    // the subgraph object is the list of modules in the subgraph
    // and the list of modules that are "external" boundaries of the subgraph
    var externals = [];

    // this traversal is a bit odd, since we need to traverse the full
    // dependency graph to detect externals, not just the direct build graph
    traverseTree(tree, entryPoint, function(depName, parentName) {
      if (!isESM(depName) || (depName != entryPoint && optimizationPoints.indexOf(depName) != -1))
        return false;

      var depLoad = tree[depName];
      depLoad.deps && depLoad.deps.forEach(function(depName) {
        depName = depLoad.depMap[depName];
        if (depName == entryPoint)
          return;

        // anything not ESM, not in the tree, or an optimization point, is external
        if (!isESM(depName) || optimizationPoints.indexOf(depName) != -1) {
          if (externals.indexOf(depName) == -1)
            externals.push(depName);
        }
        else {
          if (inlinedModules.indexOf(depName) == -1)
            inlinedModules.push(depName);
        }
      }, traceOpts);
    });

    optimizationGraphExternals[entryPoint] = externals;
  });

  // finally we rollup each optimization graph
  var rolledUpTree = {};
  Object.keys(tree).forEach(function(moduleName) {
    if (inlinedModules.indexOf(moduleName) == -1)
      rolledUpTree[moduleName] = tree[moduleName];
  });

  // compute the inlineMap
  var inlineMap = {};
  inlinedModules.forEach(function(moduleName) {
    var optimizationParent = optimizationParentMap[moduleName];
    (inlineMap[optimizationParent] = inlineMap[optimizationParent] || []).push(moduleName);
  });

  // if every module in the tree is rolled-up, then we can do a full tree rollup
  var fullTreeRollup = entryPoints.length == 1 && optimizationPoints.length == 1 && Object.keys(optimizationGraphExternals).length == 1;

  return Promise.all(Object.keys(optimizationGraphExternals).map(function(entryPoint) {
    var externals = optimizationGraphExternals[entryPoint];
    var loadList = [];

    // if all externals are outside the tree then this really is a full tree rollup
    // also @node/x requires mean we do need sfx core (pending a better output of these)
    if (fullTreeRollup)
      externals.forEach(function(external) {
        if (external.substr(0, 5) == '@node' || tree[external])
          fullTreeRollup = false;
      });

    var aliasedExternals = externals.map(function(external) {
      var alias = getAlias(loader, external) || externals;
      if (alias.indexOf('#:') != -1)
        alias = alias.replace('#:', '/');
      return alias;
    });

    return rollup.rollup({
      entry: entryPoint,
      external: aliasedExternals,
      plugins: [{
        resolveId: function(id, importer, options) {
          var resolved = importer ? tree[importer].depMap[id] : id;
          var externalIndex = externals.indexOf(resolved);
          if (externalIndex != -1)
            return aliasedExternals[externalIndex];
          return resolved;
        },
        load: function(id, options) {
          if (loadList.indexOf(tree[id]) == -1)
            loadList.push(tree[id]);
          loadList.push(tree[id]);
          return {
            code: tree[id].metadata.originalSource || tree[id].source,
            map: tree[id].metadata.sourceMap
          };
        }
      }],
      onwarn: function(message) {}
    })
    .then(function(bundle) {
      var entryPointLoad = tree[entryPoint];

      var defaultExport = compileOpts.defaultExport;
      if (entryPointLoad.metadata.format == 'register')
        throw new Error('format = \'register\' is no longer valid, please use format = \'system\'');

      if (entryPointLoad.metadata.format != 'esm' && entryPointLoad.metadata.format != 'system')
        defaultExport = true;

      var generateOptions = {
        sourceMap: !!compileOpts.sourceMaps,
        exports: defaultExport ? 'default' : 'named',
        dest: 'output.js' // workaround for rollup/rollup#1015
      };

      // for a full tree rollup, we pass all the output options into rollup itself
      if (fullTreeRollup) {
        generateOptions.format = compileOpts.format;
        if (generateOptions.format == 'global')
          generateOptions.format = 'iife';
        if (generateOptions.format == 'esm')
          generateOptions.format = 'es6';

        if ((generateOptions.format == 'iife' || generateOptions.format == 'umd') &&
            !compileOpts.globalName)
          throw new Error('The globalName option must be set for full-tree rollup global and UMD builds.');

        if (compileOpts.globalName)
          generateOptions.moduleName = compileOpts.globalName;

        if (compileOpts.globalDeps)
          generateOptions.globals = compileOpts.globalDeps;
      }

      var output = bundle.generate(generateOptions);

      // convert sources list into paths
      if (output.map) {
        output.map.sources = output.map.sources.map(function(name) {
          name = loader.getCanonicalName(loader.decanonicalize(name));
          return tree[name] && tree[name].path || loader.decanonicalize(name);
        });
      }

      if (fullTreeRollup)
        return {
          source: output.code,
          sourceMap: output.map
        };

      // replace the entry point module itself with the inlined subgraph module
      var curInlined = inlineMap[entryPoint] || [];

      // the process of running rollup will itself normalize all dependencies
      // the depMap then just becomes the identity map for non-externals
      var inlinedDepMap = {};
      aliasedExternals.forEach(function(dep, index) {
        inlinedDepMap[dep] = externals[index];
      });

      rolledUpTree[entryPoint] = extend(extend({}, entryPointLoad), {
        deps: aliasedExternals,
        depMap: inlinedDepMap,
        metadata: extend(extend({}, entryPointLoad.metadata), {
          originalSource: undefined,
          sourceMap: output.map
        }),
        source: output.code,
        compactedLoads: loadList
      });
    });
  }))
  .then(function(outputs) {
    if (fullTreeRollup) {
      // for the full tree rollup case, we need to run the plugin bundle hook as we skip compile entirely
      return pluginBundleHook(loader, Object.keys(tree).map(function(name) {
          return tree[name];
        }).filter(function(load) {
          return load;
        }), compileOpts, outputOpts)
      .then(function(pluginResult) {
        return {
          outputs: outputs.concat(pluginResult.outputs),
          assetList: pluginResult.assetList
        };
      });
    }

    return {
      tree: rolledUpTree,
      inlineMap: inlineMap
    };
  });
};
<|endoftext|>


<commit_before>'use strict';

require('jshint-stylish');

var gulp = require('gulp'),
    uglify = require('gulp-uglify'),
    sourcemaps = require('gulp-sourcemaps'),
    jshint = require('gulp-jshint'),
    header = require('gulp-header'),
    browserify = require('browserify'),
    webserver = require('gulp-webserver'),
    rename = require('gulp-rename'),
    pkg = require('./package.json'),
    source = require('vinyl-source-stream'),
    buffer = require('vinyl-buffer'),
    babelify = require('babelify'),
    IW = {};

IW.banner = [
  '/**',
  ' ** <%= pkg.name %> - <%= pkg.description %>',
  ' ** @author <%= pkg.author %>',
  ' ** @version v<%= pkg.version %>',
  ' **/',
  ''
].join('\n');

IW._paths = {
    main: './src/index.js',
    js: './src/**/*.js',
    demo: './demo',
    demoJS: './demo/js'
};
IW.minifiedName = 'ironwing.min.js';

gulp.task('build', ['lint'], function() {
  var b = browserify({
    entries: IW._paths.main,
    debug: true
  }).transform(babelify);

  return b.bundle()
         .pipe(source('app.min.js'))
         .pipe(buffer())
         .pipe(uglify({
          mangle: false
         }))
        .pipe(header(IW.banner, { pkg: pkg }))
        .pipe(rename('ironwing.min.js'))
        .pipe(gulp.dest('dist'));
});

gulp.task('scripts', ['lint'], function() {
  var b = browserify({
    entries: IW._paths.main,
    debug: true
  }).transform(babelify);

  return b.bundle()
         .pipe(source('app.min.js'))
         .pipe(buffer())
        .pipe(sourcemaps.init({loadMaps: true, debug: true}))
        // .pipe(uglify())
        .pipe(header(IW.banner, { pkg: pkg }))
        .pipe(sourcemaps.write('./'))
        .pipe(gulp.dest(IW._paths.demoJS));
});

gulp.task('lint', function() {
    return gulp.src(IW._paths.js)
        .pipe(jshint())
        .pipe(jshint.reporter('jshint-stylish'))
        .pipe(jshint.reporter('fail'));
});

gulp.task('webserver', function() {
  gulp.src(IW._paths.demo)
    .pipe(webserver({
      open: true
    }));
});

gulp.task('default', ['webserver'], function() {
    gulp.watch(IW._paths.js, ['scripts']);
});
<commit_msg>Removed old gulpfile<commit_after><|endoftext|>


<commit_before>'use strict';
const gulp = require('gulp'),
    gulpJsdoc2md = require('gulp-jsdoc-to-markdown'),
    rename = require('gulp-rename'),
    istanbul = require('gulp-istanbul'),
    istanbulHarmony = require('istanbul-harmony'),
    mocha = require('gulp-mocha'),
    eslint = require('gulp-eslint'),
    git = require('gulp-git');

const sockFiles = ['*.js', '!./gulpfile.js', '**/plugins/**/*.js', '!node_modules/**'],
    sockExterns = ['**/external/**/*.js'],
    sockDocs = ['README.md', 'docs/**/*.md'],
    sockTests = ['test/**/*.js'];
let docgenFiles = [];

const JobNumber = process.env.TRAVIS_JOB_NUMBER,
    CommitRange = process.env.TRAVIS_COMMIT_RANGE,
    runDocs = !JobNumber || /[.]1$/.test(JobNumber);

/**
 * Pull git branch locally (solves detached head issue in CI)
 */
gulp.task('gitBranch', (done) => {
    let complete = false;
    const branch = process.env.TRAVIS_BRANCH;
    // Abort(successfully) early if not running in CI
    if (!(JobNumber && runDocs && branch)) {
        return done();
    }
    git.checkout(branch, () => {
        // Make sure we have full log history.
        git.pull('origin', branch, {}, () => {
            if (!complete) {
                done();
            }
            complete = true;
        });
    });
});

/**
 * Construct the array of file globs for gulpJsdoc2md
 */
gulp.task('docList', ['gitBranch'], function (done) {
    if (CommitRange) {
        git.exec({
            args: 'show --pretty="format:" --name-only ' + CommitRange
        }, (err, stdout) => {
            if (err) {
                console.log('Error fetching files in commit range\n' + err);
                return;
            }
            stdout.split(/\r?\n/).foreach((file) => {
                if (file && file.length > 3 && file.endsWith('.js')){
                    docgenFiles.push('./' + file);
                }
            });
            if (docgenFiles.length === 0) {
                docgenFiles.push('*.*');
            }
            done();
        });
    } else {
        docgenFiles.push('*.*');
        done();
    }
});

/**
 * Generate API documentation for all js files, place markup in the correct folder for readthedocs.org
 */
gulp.task('docs', ['gitBranch', 'lintExterns', 'docList'], function (done) {
    // Abort(successfully) early if running in CI and not job #1
    if (!runDocs) {
        return done();
    }
    gulp.src(sockFiles.concat(sockExterns))
        .filter(docgenFiles)
        .pipe(gulpJsdoc2md({}))
        .on('error', done)
        .pipe(rename((path) => {
            path.extname = '.md';
        }))
        .pipe(gulp.dest('docs/api'))
        .on('finish', done);
});

/**
 * Run all js files through eslint and report status.
 */
gulp.task('lintCore', (done) => {
    return gulp.src(sockFiles)
        .pipe(eslint())
        .pipe(eslint.format())
        .pipe(eslint.failAfterError());
});
/**
 * Run all js files through eslint and report status.
 */
gulp.task('lintExterns', (done) => {
    return gulp.src(sockExterns)
        .pipe(eslint())
        .pipe(eslint.format())
        .pipe(eslint.failAfterError());
});

/**
 * Run all tests through eslint and report status.
 */
gulp.task('lintTests', (done) => {
    return gulp.src(sockTests)
        .pipe(eslint())
        .pipe(eslint.format())
        .pipe(eslint.failAfterError());
});

/**
 * Set git username/email to CI user
 */
gulp.task('gitConfig', (done) => {
    // Abort(successfully) early if not running in CI
    if (!JobNumber) {
        return done();
    }
    git.exec({
        args: 'config user.name "Travis-CI"'
    }, () => {
        git.exec({
            args: 'config user.email "Travis-CI@servercooties.com"'
        }, () => {
            done();
        });
    });
});

/**
 * Commit generated documentation to be picked up by readthedocs.org
 *
 * Add CI tag to commit to prevent CI jobs from being created by checking in docs
 */
gulp.task('commitDocs', ['gitConfig'], (done) => {
    gulp.src(sockDocs)
        .pipe(git.add())
        .pipe(git.commit('Automatically push updated documentation [ci skip]'))
        .on('error', () => 0)
        .on('finish', done);
});

/**
 * Commit and push docs to github to be picked up by readthedocs.org
 */
gulp.task('pushDocs', ['gitConfig', 'commitDocs'], (done) => {
    //Abort(successfully) early if running in CI and not job #1
    if (!runDocs) {
        return done();
    }
    git.addRemote('github', 'https://github.com/SockDrawer/SockBot.git', (e) => {
        if (e) {
            done();
        } else {
            git.push('github', 'HEAD', {
                args: ['-q']
            }, () => {
                done();
            });
        }
    });
});

/**
 * Run code coverage instrumented tests
 */
gulp.task('test', ['lintCore', 'lintTests'], (done) => {
    gulp.src(sockFiles)
        // Instrument code files with istanbulHarmony
        .pipe(istanbul({
            instrumenter: istanbulHarmony.Instrumenter
        }))
        // hook require function for complete code coverage
        .pipe(istanbul.hookRequire())
        .on('finish', () => {
            // Run all tests
            gulp.src(sockTests)
                .pipe(mocha({
                    reporter: 'dot'
                }))
                .on('error', done)
                // Write code coverage reports
                .pipe(istanbul.writeReports())
                .on('finish', done);
        });
});

// Meta tasks
gulp.task('buildDocs', ['docs'], () => 0);
gulp.task('preBuild', ['buildDocs'], () => 0);
gulp.task('postBuild', ['pushDocs'], () => 0);
gulp.task('default', ['lint'], () => 0);
gulp.task('lint', ['lintCore', 'lintTests', 'lintExterns'], () => 0);<commit_msg>Fixed the match-all globs<commit_after>'use strict';
const gulp = require('gulp'),
    gulpJsdoc2md = require('gulp-jsdoc-to-markdown'),
    rename = require('gulp-rename'),
    istanbul = require('gulp-istanbul'),
    istanbulHarmony = require('istanbul-harmony'),
    mocha = require('gulp-mocha'),
    eslint = require('gulp-eslint'),
    git = require('gulp-git');

const sockFiles = ['*.js', '!./gulpfile.js', '**/plugins/**/*.js', '!node_modules/**'],
    sockExterns = ['**/external/**/*.js'],
    sockDocs = ['README.md', 'docs/**/*.md'],
    sockTests = ['test/**/*.js'];
let docgenFiles = [];

const JobNumber = process.env.TRAVIS_JOB_NUMBER,
    CommitRange = process.env.TRAVIS_COMMIT_RANGE,
    runDocs = !JobNumber || /[.]1$/.test(JobNumber);

/**
 * Pull git branch locally (solves detached head issue in CI)
 */
gulp.task('gitBranch', (done) => {
    let complete = false;
    const branch = process.env.TRAVIS_BRANCH;
    // Abort(successfully) early if not running in CI
    if (!(JobNumber && runDocs && branch)) {
        return done();
    }
    git.checkout(branch, () => {
        // Make sure we have full log history.
        git.pull('origin', branch, {}, () => {
            if (!complete) {
                done();
            }
            complete = true;
        });
    });
});

/**
 * Construct the array of file globs for gulpJsdoc2md
 */
gulp.task('docList', ['gitBranch'], function (done) {
    if (CommitRange) {
        git.exec({
            args: 'show --pretty="format:" --name-only ' + CommitRange
        }, (err, stdout) => {
            if (err) {
                console.log('Error fetching files in commit range\n' + err);
                return;
            }
            stdout.split(/\r?\n/).foreach((file) => {
                if (file && file.length > 3 && file.endsWith('.js')){
                    docgenFiles.push('./' + file);
                }
            });
            if (docgenFiles.length === 0) {
                docgenFiles.push('**');
            }
            done();
        });
    } else {
        docgenFiles.push('**');
        done();
    }
});

/**
 * Generate API documentation for all js files, place markup in the correct folder for readthedocs.org
 */
gulp.task('docs', ['gitBranch', 'lintExterns', 'docList'], function (done) {
    // Abort(successfully) early if running in CI and not job #1
    if (!runDocs) {
        return done();
    }
    gulp.src(sockFiles.concat(sockExterns))
        .filter(docgenFiles)
        .pipe(gulpJsdoc2md({}))
        .on('error', done)
        .pipe(rename((path) => {
            path.extname = '.md';
        }))
        .pipe(gulp.dest('docs/api'))
        .on('finish', done);
});

/**
 * Run all js files through eslint and report status.
 */
gulp.task('lintCore', (done) => {
    return gulp.src(sockFiles)
        .pipe(eslint())
        .pipe(eslint.format())
        .pipe(eslint.failAfterError());
});
/**
 * Run all js files through eslint and report status.
 */
gulp.task('lintExterns', (done) => {
    return gulp.src(sockExterns)
        .pipe(eslint())
        .pipe(eslint.format())
        .pipe(eslint.failAfterError());
});

/**
 * Run all tests through eslint and report status.
 */
gulp.task('lintTests', (done) => {
    return gulp.src(sockTests)
        .pipe(eslint())
        .pipe(eslint.format())
        .pipe(eslint.failAfterError());
});

/**
 * Set git username/email to CI user
 */
gulp.task('gitConfig', (done) => {
    // Abort(successfully) early if not running in CI
    if (!JobNumber) {
        return done();
    }
    git.exec({
        args: 'config user.name "Travis-CI"'
    }, () => {
        git.exec({
            args: 'config user.email "Travis-CI@servercooties.com"'
        }, () => {
            done();
        });
    });
});

/**
 * Commit generated documentation to be picked up by readthedocs.org
 *
 * Add CI tag to commit to prevent CI jobs from being created by checking in docs
 */
gulp.task('commitDocs', ['gitConfig'], (done) => {
    gulp.src(sockDocs)
        .pipe(git.add())
        .pipe(git.commit('Automatically push updated documentation [ci skip]'))
        .on('error', () => 0)
        .on('finish', done);
});

/**
 * Commit and push docs to github to be picked up by readthedocs.org
 */
gulp.task('pushDocs', ['gitConfig', 'commitDocs'], (done) => {
    //Abort(successfully) early if running in CI and not job #1
    if (!runDocs) {
        return done();
    }
    git.addRemote('github', 'https://github.com/SockDrawer/SockBot.git', (e) => {
        if (e) {
            done();
        } else {
            git.push('github', 'HEAD', {
                args: ['-q']
            }, () => {
                done();
            });
        }
    });
});

/**
 * Run code coverage instrumented tests
 */
gulp.task('test', ['lintCore', 'lintTests'], (done) => {
    gulp.src(sockFiles)
        // Instrument code files with istanbulHarmony
        .pipe(istanbul({
            instrumenter: istanbulHarmony.Instrumenter
        }))
        // hook require function for complete code coverage
        .pipe(istanbul.hookRequire())
        .on('finish', () => {
            // Run all tests
            gulp.src(sockTests)
                .pipe(mocha({
                    reporter: 'dot'
                }))
                .on('error', done)
                // Write code coverage reports
                .pipe(istanbul.writeReports())
                .on('finish', done);
        });
});

// Meta tasks
gulp.task('buildDocs', ['docs'], () => 0);
gulp.task('preBuild', ['buildDocs'], () => 0);
gulp.task('postBuild', ['pushDocs'], () => 0);
gulp.task('default', ['lint'], () => 0);
gulp.task('lint', ['lintCore', 'lintTests', 'lintExterns'], () => 0);<|endoftext|>


<commit_before>/**
 * Copyright 2015 Kitware Inc.
 *
 * 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 path = require('path');
const process = require('process');

const _ = require('underscore');
const extendify = require('extendify');
const webpack = require('webpack');
const ExtractTextPlugin = require('extract-text-webpack-plugin');
const GoogleFontsPlugin = require('google-fonts-webpack-plugin');
const UglifyJsPlugin = require('uglifyjs-webpack-plugin');
const GitRevisionPlugin = require('git-revision-webpack-plugin');
const CopyWebpackPlugin = require('copy-webpack-plugin');

const webpackPlugins = require('./webpack.plugins.js');
const pkg = require('../package.json');

const isTrue = (str) => !!str && !['false', 'off', '0'].includes(str.toString().toLowerCase());

module.exports = function (grunt) {
    // Get and validate options
    const progress = !isTrue(grunt.option('no-progress'));
    const isWatch = isTrue(grunt.option('watch'));
    const pollingWatch = isTrue(process.env.WATCH_USEPOLLING);
    const isDev = grunt.config.get('environment') === 'dev' || isWatch;

    function injectIstanbulCoverage(config) {
        if (!isDev) {
            return;
        }
        const istanbulPlugin = require.resolve('babel-plugin-istanbul');
        _.each(config.module.rules, (rule) => {
            _.each(_.where(rule.use, {loader: 'babel-loader'}), (useEntry) => {
                useEntry.options.plugins = [
                    [istanbulPlugin, {
                        exclude: ['**/*.pug', '**/*.jade']
                    }]
                ];
            });
        });
    }

    // Set some environment variables
    if (!process.env.NODE_ENV) {
        // This is not explicitly used for anything in Girder, but some Npm packages may respect it.
        // Babel will also fall back to using this if BABEL_ENV is not defined.
        process.env.NODE_ENV = isDev ? 'development' : 'production';
    }

    // nyc will only instrument files whose *real* path is inside the working directory.  Because we
    // want to instrument files that could be symlinked into node_modules from outside the girder
    // web_client directory, we just set this to the system root.  There do not seem to be any
    // consequences to this beyond the path lookup performed in nyc.
    process.env.NYC_CWD = '/';

    // Load the global webpack config
    const webpackConfig = require('./webpack.config.js');
    const updateWebpackConfig = _.partial(
        extendify({
            inPlace: true,
            isDeep: false,
            arrays: 'concat'
        }),
        webpackConfig
    );
    const plugins = grunt.config.get('pkg.girder.plugins') || [];

    // Extend the global webpack config options with environment-specific changes
    if (isDev) {
        updateWebpackConfig({
            devtool: 'source-map',
            cache: true,
            plugins: [
                new webpack.LoaderOptionsPlugin({
                    minimize: false,
                    debug: true
                })
            ]
        });

        if (isWatch) {
            updateWebpackConfig({
                watch: true
                // When "watch" is enabled for webpack, grunt-webpack will intelligently set its own
                // options for "keepalive" and "failOnError"
            });
            if (pollingWatch) {
                updateWebpackConfig({
                    watchOptions: {
                        // For Girder's current number of files, 500ms is a reasonable polling
                        // interval to keep CPU utilization from going too high, particularly in a
                        // VM (where this option is most likely to be used)
                        poll: 500
                    }
                });
                // Chokidar is used internally for almost all file polling, so enable it globally
                // for other packages to potentially benefit too
                process.env.CHOKIDAR_USEPOLLING = 'TRUE';
                process.env.CHOKIDAR_INTERVAL = '500';
            }
        }
    } else {
        updateWebpackConfig({
            // "devtool" is off by default
            cache: false,
            plugins: [
                // https://github.com/webpack/webpack/issues/283
                // https://github.com/webpack/webpack/issues/2061#issuecomment-228932941
                // https://gist.github.com/sokra/27b24881210b56bbaff7#loader-options--minimize
                // but unclear and confusing as to how far it has been implemented
                new webpack.LoaderOptionsPlugin({
                    minimize: true,
                    debug: false
                }),
                new UglifyJsPlugin({
                    uglifyOptions: {
                        ecma: 6
                    }
                })
            ]
        });
    }

    const gitRevision = new GitRevisionPlugin();
    let versionInfo = {
        git: false,
        SHA: null,
        shortSHA: null,
        date: new Date().toISOString(),
        apiVersion: pkg.version
    };
    try {
        // inject git revision information if possible
        const gitHash = gitRevision.commithash();
        Object.assign(versionInfo, {
            git: true,
            SHA: gitHash,
            shortSHA: gitHash.slice(0, 8)
        });
    } catch (err) {
        // The above writes a fatal error line when not inside a git repo
        // Let the user know this is not a problem for production/non-dev installs.
        grunt.log.oklns(
            'You are not running in a git repository.  This is normal for non-development builds of girder.'
        );
    }

    // TODO: Eventually we should refactor the setup.py to use setuptools scm and avoid
    // this hackery, but for now, we generate a version file when building the web client.
    grunt.config.merge({
        'file-creator': {
            'python-version': {
                [path.resolve('..', 'girder-version.json')]: function (fs, fd, done) {
                    fs.writeSync(fd, JSON.stringify(versionInfo, null, 4) + '\n');
                    done();
                }
            }
        },
        default: {
            'file-creator:python-version': {}
        }
    });

    // Define global constants
    updateWebpackConfig({
        plugins: [
            new webpack.DefinePlugin({
                'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV),
                'GIRDER_VERSION': JSON.stringify(versionInfo)
            })
        ]
    });

    // Add extra config options for grunt-webpack
    updateWebpackConfig({
        progress: progress
    });

    const paths = require('./webpack.paths.js');

    // add coverage to all babel loader rules when in dev mode
    injectIstanbulCoverage(webpackConfig);

    grunt.config.merge({
        webpack: {
            options: webpackConfig,
            core_lib: {
                entry: {
                    girder_lib: [paths.web_src]
                },
                output: {
                    library: '[name]',
                    path: grunt.config.get('builtPath')
                },
                plugins: [
                    // Remove this if it turns out we don't want to use it for every bundle target.
                    new webpack.DllPlugin({
                        path: path.join(grunt.config.get('builtPath'), '[name]-manifest.json'),
                        name: '[name]'
                    }),
                    new ExtractTextPlugin({
                        filename: '[name].min.css',
                        allChunks: true
                    }),
                    new GoogleFontsPlugin({
                        filename: 'googlefonts.css',
                        fonts: [{
                            family: 'Open Sans',
                            variants: ['regular', '700', 'italic', '700italic']
                        }]
                    })
                ]
            },
            core_app: {
                entry: {
                    girder_app: [path.join(paths.web_src, 'main.js')]
                },
                output: {
                    path: grunt.config.get('builtPath')
                },
                plugins: [
                    new webpack.DllReferencePlugin({
                        context: '.',
                        manifest: path.join(grunt.config.get('builtPath'), 'girder_lib-manifest.json')
                    }),
                    new ExtractTextPlugin({
                        filename: '[name].min.css',
                        allChunks: true
                    }),
                    new CopyWebpackPlugin([{
                        from: 'static/img/Girder_Favicon.png',
                        to: grunt.config.get('builtPath'),
                        toType: 'dir'
                    }])
                ]
            }
        },
        default: {
            build: {}
        }
    });

    // Get a list of entry points for each installed plugin.
    plugins.forEach(function (plugin) {
        const pluginDef = require(path.join(plugin, 'package.json'))['girderPlugin'];
        const name = pluginDef.name;
        const babelRule = {
            resource: {
                test: /\.js$/,
                include: [path.resolve(`node_modules/${plugin}`)],
                exclude: new RegExp(`node_modules/${plugin}/node_modules`)
            },
            use: [{
                loader: 'babel-loader',
                options: {
                    presets: [require.resolve('babel-preset-env')],
                    cacheDirectory: true
                }
            }]
        };
        let pluginWebpackConfig = {
            entry: {
                [`plugins/${name}/plugin`]: [`${plugin}/main.js`]
            },
            output: {
                path: path.resolve(grunt.config.get('builtPath'), 'plugins', name),
                filename: 'plugin.min.js',
                library: `girder_plugin_${name}`
            },
            module: {
                rules: [babelRule]
            },
            plugins: [
                new webpack.DllPlugin({
                    path: path.join(grunt.config.get('builtPath'), 'plugins', name, 'plugin-manifest.json'),
                    name: `girder_plugin_${name}`
                }),
                // DllBootstrapPlugin allows the same plugin bundle to also
                // execute an entry point at load time instead of just exposing symbols
                // as a library.
                new webpackPlugins.DllBootstrapPlugin({
                    [`plugins/${name}/plugin`]: `${plugin}/main.js`
                }),
                // This plugin allows this bundle to dynamically link against girder's
                // core library bundle.
                new webpack.DllReferencePlugin({
                    context: '.',
                    manifest: path.join(grunt.config.get('builtPath'), 'girder_lib-manifest.json')
                }),
                // This plugin pulls the CSS out of the bundle and into a separate file.
                new ExtractTextPlugin({
                    filename: 'plugin.min.css',
                    allChunks: true
                })
            ].concat(_.map(pluginDef.dependencies || [], (dep) => {
                return new webpack.DllReferencePlugin({
                    context: '.',
                    manifest: path.join(grunt.config.get('builtPath'), 'plugins', dep, 'plugin-manifest.json')
                });
            }))
        };
        injectIstanbulCoverage(pluginWebpackConfig);

        // allow the plugin to mutate its own webpack config
        if (pluginDef.webpack) {
            pluginWebpackConfig = require(path.join(plugin, pluginDef.webpack))(pluginWebpackConfig);
        }
        grunt.config.set(`webpack.plugin_${name}`, pluginWebpackConfig);

        // Make dependent plugins build before this one to create the DLL manifest.
        grunt.config.set(`default.webpack:plugin_${name}`, {
            dependencies: _.map(pluginDef.dependencies, (dep) => `webpack:plugin_${dep}`)
        });
    });

    // Need an alias that can be used as a dependency (for testing). It will then trigger dev or
    // prod based on options passed
    grunt.registerTask('build', 'Build the web client.', [
        'webpack:core_lib',
        'webpack:core_app'
    ]);
};
<commit_msg>Copy "extra" assets from plugins to the static root<commit_after>/**
 * Copyright 2015 Kitware Inc.
 *
 * 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 path = require('path');
const process = require('process');

const _ = require('underscore');
const extendify = require('extendify');
const webpack = require('webpack');
const ExtractTextPlugin = require('extract-text-webpack-plugin');
const GoogleFontsPlugin = require('google-fonts-webpack-plugin');
const UglifyJsPlugin = require('uglifyjs-webpack-plugin');
const GitRevisionPlugin = require('git-revision-webpack-plugin');
const CopyWebpackPlugin = require('copy-webpack-plugin');

const webpackPlugins = require('./webpack.plugins.js');
const pkg = require('../package.json');

const isTrue = (str) => !!str && !['false', 'off', '0'].includes(str.toString().toLowerCase());

module.exports = function (grunt) {
    // Get and validate options
    const progress = !isTrue(grunt.option('no-progress'));
    const isWatch = isTrue(grunt.option('watch'));
    const pollingWatch = isTrue(process.env.WATCH_USEPOLLING);
    const isDev = grunt.config.get('environment') === 'dev' || isWatch;

    function injectIstanbulCoverage(config) {
        if (!isDev) {
            return;
        }
        const istanbulPlugin = require.resolve('babel-plugin-istanbul');
        _.each(config.module.rules, (rule) => {
            _.each(_.where(rule.use, {loader: 'babel-loader'}), (useEntry) => {
                useEntry.options.plugins = [
                    [istanbulPlugin, {
                        exclude: ['**/*.pug', '**/*.jade']
                    }]
                ];
            });
        });
    }

    // Set some environment variables
    if (!process.env.NODE_ENV) {
        // This is not explicitly used for anything in Girder, but some Npm packages may respect it.
        // Babel will also fall back to using this if BABEL_ENV is not defined.
        process.env.NODE_ENV = isDev ? 'development' : 'production';
    }

    // nyc will only instrument files whose *real* path is inside the working directory.  Because we
    // want to instrument files that could be symlinked into node_modules from outside the girder
    // web_client directory, we just set this to the system root.  There do not seem to be any
    // consequences to this beyond the path lookup performed in nyc.
    process.env.NYC_CWD = '/';

    // Load the global webpack config
    const webpackConfig = require('./webpack.config.js');
    const updateWebpackConfig = _.partial(
        extendify({
            inPlace: true,
            isDeep: false,
            arrays: 'concat'
        }),
        webpackConfig
    );
    const plugins = grunt.config.get('pkg.girder.plugins') || [];

    // Extend the global webpack config options with environment-specific changes
    if (isDev) {
        updateWebpackConfig({
            devtool: 'source-map',
            cache: true,
            plugins: [
                new webpack.LoaderOptionsPlugin({
                    minimize: false,
                    debug: true
                })
            ]
        });

        if (isWatch) {
            updateWebpackConfig({
                watch: true
                // When "watch" is enabled for webpack, grunt-webpack will intelligently set its own
                // options for "keepalive" and "failOnError"
            });
            if (pollingWatch) {
                updateWebpackConfig({
                    watchOptions: {
                        // For Girder's current number of files, 500ms is a reasonable polling
                        // interval to keep CPU utilization from going too high, particularly in a
                        // VM (where this option is most likely to be used)
                        poll: 500
                    }
                });
                // Chokidar is used internally for almost all file polling, so enable it globally
                // for other packages to potentially benefit too
                process.env.CHOKIDAR_USEPOLLING = 'TRUE';
                process.env.CHOKIDAR_INTERVAL = '500';
            }
        }
    } else {
        updateWebpackConfig({
            // "devtool" is off by default
            cache: false,
            plugins: [
                // https://github.com/webpack/webpack/issues/283
                // https://github.com/webpack/webpack/issues/2061#issuecomment-228932941
                // https://gist.github.com/sokra/27b24881210b56bbaff7#loader-options--minimize
                // but unclear and confusing as to how far it has been implemented
                new webpack.LoaderOptionsPlugin({
                    minimize: true,
                    debug: false
                }),
                new UglifyJsPlugin({
                    uglifyOptions: {
                        ecma: 6
                    }
                })
            ]
        });
    }

    const gitRevision = new GitRevisionPlugin();
    let versionInfo = {
        git: false,
        SHA: null,
        shortSHA: null,
        date: new Date().toISOString(),
        apiVersion: pkg.version
    };
    try {
        // inject git revision information if possible
        const gitHash = gitRevision.commithash();
        Object.assign(versionInfo, {
            git: true,
            SHA: gitHash,
            shortSHA: gitHash.slice(0, 8)
        });
    } catch (err) {
        // The above writes a fatal error line when not inside a git repo
        // Let the user know this is not a problem for production/non-dev installs.
        grunt.log.oklns(
            'You are not running in a git repository.  This is normal for non-development builds of girder.'
        );
    }

    // TODO: Eventually we should refactor the setup.py to use setuptools scm and avoid
    // this hackery, but for now, we generate a version file when building the web client.
    grunt.config.merge({
        'file-creator': {
            'python-version': {
                [path.resolve('..', 'girder-version.json')]: function (fs, fd, done) {
                    fs.writeSync(fd, JSON.stringify(versionInfo, null, 4) + '\n');
                    done();
                }
            }
        },
        default: {
            'file-creator:python-version': {}
        }
    });

    // Define global constants
    updateWebpackConfig({
        plugins: [
            new webpack.DefinePlugin({
                'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV),
                'GIRDER_VERSION': JSON.stringify(versionInfo)
            })
        ]
    });

    // Add extra config options for grunt-webpack
    updateWebpackConfig({
        progress: progress
    });

    const paths = require('./webpack.paths.js');

    // add coverage to all babel loader rules when in dev mode
    injectIstanbulCoverage(webpackConfig);

    grunt.config.merge({
        webpack: {
            options: webpackConfig,
            core_lib: {
                entry: {
                    girder_lib: [paths.web_src]
                },
                output: {
                    library: '[name]',
                    path: grunt.config.get('builtPath')
                },
                plugins: [
                    // Remove this if it turns out we don't want to use it for every bundle target.
                    new webpack.DllPlugin({
                        path: path.join(grunt.config.get('builtPath'), '[name]-manifest.json'),
                        name: '[name]'
                    }),
                    new ExtractTextPlugin({
                        filename: '[name].min.css',
                        allChunks: true
                    }),
                    new GoogleFontsPlugin({
                        filename: 'googlefonts.css',
                        fonts: [{
                            family: 'Open Sans',
                            variants: ['regular', '700', 'italic', '700italic']
                        }]
                    })
                ]
            },
            core_app: {
                entry: {
                    girder_app: [path.join(paths.web_src, 'main.js')]
                },
                output: {
                    path: grunt.config.get('builtPath')
                },
                plugins: [
                    new webpack.DllReferencePlugin({
                        context: '.',
                        manifest: path.join(grunt.config.get('builtPath'), 'girder_lib-manifest.json')
                    }),
                    new ExtractTextPlugin({
                        filename: '[name].min.css',
                        allChunks: true
                    }),
                    new CopyWebpackPlugin([{
                        from: 'static/img/Girder_Favicon.png',
                        to: grunt.config.get('builtPath'),
                        toType: 'dir'
                    }])
                ]
            }
        },
        default: {
            build: {}
        }
    });

    // Get a list of entry points for each installed plugin.
    plugins.forEach(function (plugin) {
        const pluginDef = require(path.join(plugin, 'package.json'))['girderPlugin'];
        const name = pluginDef.name;
        const babelRule = {
            resource: {
                test: /\.js$/,
                include: [path.resolve(`node_modules/${plugin}`)],
                exclude: new RegExp(`node_modules/${plugin}/node_modules`)
            },
            use: [{
                loader: 'babel-loader',
                options: {
                    presets: [require.resolve('babel-preset-env')],
                    cacheDirectory: true
                }
            }]
        };
        let pluginWebpackConfig = {
            entry: {
                [`plugins/${name}/plugin`]: [`${plugin}/main.js`]
            },
            output: {
                path: path.resolve(grunt.config.get('builtPath'), 'plugins', name),
                filename: 'plugin.min.js',
                library: `girder_plugin_${name}`
            },
            module: {
                rules: [babelRule]
            },
            plugins: [
                new webpack.DllPlugin({
                    path: path.join(grunt.config.get('builtPath'), 'plugins', name, 'plugin-manifest.json'),
                    name: `girder_plugin_${name}`
                }),
                // DllBootstrapPlugin allows the same plugin bundle to also
                // execute an entry point at load time instead of just exposing symbols
                // as a library.
                new webpackPlugins.DllBootstrapPlugin({
                    [`plugins/${name}/plugin`]: `${plugin}/main.js`
                }),
                // This plugin allows this bundle to dynamically link against girder's
                // core library bundle.
                new webpack.DllReferencePlugin({
                    context: '.',
                    manifest: path.join(grunt.config.get('builtPath'), 'girder_lib-manifest.json')
                }),
                // This plugin pulls the CSS out of the bundle and into a separate file.
                new ExtractTextPlugin({
                    filename: 'plugin.min.css',
                    allChunks: true
                }),
                // Copy assets from the "extras" directory.
                new CopyWebpackPlugin([{
                    context: path.resolve(`node_modules/${plugin}/extra`),
                    from: '**',
                    to: path.join(grunt.config.get('builtPath'), 'plugins', name, 'extra'),
                    toType: 'dir'
                }])
            ].concat(_.map(pluginDef.dependencies || [], (dep) => {
                return new webpack.DllReferencePlugin({
                    context: '.',
                    manifest: path.join(grunt.config.get('builtPath'), 'plugins', dep, 'plugin-manifest.json')
                });
            }))
        };
        injectIstanbulCoverage(pluginWebpackConfig);

        // allow the plugin to mutate its own webpack config
        if (pluginDef.webpack) {
            pluginWebpackConfig = require(path.join(plugin, pluginDef.webpack))(pluginWebpackConfig);
        }
        grunt.config.set(`webpack.plugin_${name}`, pluginWebpackConfig);

        // Make dependent plugins build before this one to create the DLL manifest.
        grunt.config.set(`default.webpack:plugin_${name}`, {
            dependencies: _.map(pluginDef.dependencies, (dep) => `webpack:plugin_${dep}`)
        });
    });

    // Need an alias that can be used as a dependency (for testing). It will then trigger dev or
    // prod based on options passed
    grunt.registerTask('build', 'Build the web client.', [
        'webpack:core_lib',
        'webpack:core_app'
    ]);
};
<|endoftext|>


<commit_before>var mysql  = require('mysql');
var connectionParams = require('../../config/connectionParams');
function getConnection() {
  var connection = mysql.createConnection(connectionParams);
  return connection;
}

function Fossil(databaseRow) {
  // Fossil Number
  // Fossil Name
  // Fossil Strat Unit
  // Fossil Max
  // Fossil Min
  // Fossil Position
  // Fossil Reference
}

function Calibration(databaseRow) {
  // Properties to fill
  this.nodeName = databaseRow['NodeName'];
  this.nodeMinAge = databaseRow['MinAge'];
  this.nodeMaxAge = databaseRow['MaxAge'];
  this.calibrationReference = databaseRow['FullReference'];
  var calibrationId = databaseRow['']
  this.fossils = [];
  // fossils
  // TODO: make fossil objects

  this.tipPairs = [];
  // tip_pairs
    // Tip 1 Name
    // Tip 2 Name
    // “Distance” of root from tip(s)?
}

function Calibrations() {
  function query(queryString, queryParams, callback) {
    var connection = getConnection();
    connection.connect();
    connection.query(queryString, queryParams, callback);
    connection.end()
  }

  var TABLE_NAME = 'View_Calibrations';
  this.findById = function(calibration_id, callback) {
    // callback is (calibration, err)
    // query the calibrations by id
    var queryString = 'SELECT * FROM ' + TABLE_NAME + ' WHERE CalibrationID = ?';
    // TODO: write a method that takes a calibration Id and makes a calibration
    // populating its fossils too
    query(queryString, [calibration_id], function(err, results) {
        if(err) {
          callback(null,err);
        } else {
          var calibrationResult = new Calibration(results[0]);
          callback(calibrationResult);
        }
      });
    };
  this.findByFilter = function(params, callback) {
    var queryString = 'SELECT * FROM ' + TABLE_NAME + ' WHERE minAge > ? AND maxAge < ?';
    query(queryString, [params.min, params.max], function(err, results) {
      if(err) {
        callback(null,err);
      } else {
        var calibrationResults = results.map(function(result) { return new Calibration(result)});
        callback(calibrationResults);
      }
    });
  };
}

module.exports = new Calibrations();<commit_msg>Comments<commit_after>var mysql  = require('mysql');
var connectionParams = require('../../config/connectionParams');
function getConnection() {
  var connection = mysql.createConnection(connectionParams);
  return connection;
}

/*
  Creates a Fossil object from a database row
 */

function Fossil(databaseRow) {
  this.fossilNumber = databaseRow['']
  // Fossil Number
  // Fossil Name
  // Fossil Strat Unit
  // Fossil Max
  // Fossil Min
  // Fossil Position
  // Fossil Reference
}
/*
  Creates a calibration object from a database row
 */
function Calibration(databaseRow) {
  // Properties to fill
  this.nodeName = databaseRow['NodeName'];
  this.nodeMinAge = databaseRow['MinAge'];
  this.nodeMaxAge = databaseRow['MaxAge'];
  this.calibrationReference = databaseRow['FullReference'];
  var calibrationId = databaseRow['']
  this.fossils = [];
  // fossils
  // TODO: make fossil objects

  this.tipPairs = [];
  // tip_pairs
    // Tip 1 Name
    // Tip 2 Name
    // “Distance” of root from tip(s)?
}

function Calibrations() {
  function query(queryString, queryParams, callback) {
    var connection = getConnection();
    connection.connect();
    connection.query(queryString, queryParams, callback);
    connection.end()
  }

  var TABLE_NAME = 'View_Calibrations';
  this.findById = function(calibration_id, callback) {
    // callback is (calibration, err)
    // query the calibrations by id
    var queryString = 'SELECT * FROM ' + TABLE_NAME + ' WHERE CalibrationID = ?';
    // TODO: write a method that takes a calibration Id and makes a calibration
    // populating its fossils too
    query(queryString, [calibration_id], function(err, results) {
        if(err) {
          callback(null,err);
        } else {
          var calibrationResult = new Calibration(results[0]);
          callback(calibrationResult);
        }
      });
    };
  this.findByFilter = function(params, callback) {
    var queryString = 'SELECT * FROM ' + TABLE_NAME + ' WHERE minAge > ? AND maxAge < ?';
    query(queryString, [params.min, params.max], function(err, results) {
      if(err) {
        callback(null,err);
      } else {
        var calibrationResults = results.map(function(result) { return new Calibration(result)});
        callback(calibrationResults);
      }
    });
  };
}

module.exports = new Calibrations();<|endoftext|>