<commit_before>module.exports = function (grunt)
{
    'use strict';

    // Load all Grunt tasks.
    require('load-grunt-tasks')(grunt);

    grunt.initConfig({
        pkg: grunt.file.readJSON('package.json'),

        // Set up paths.
        paths: {
            src: {
                sass: 'src/assets/sass/',
                js: 'src/assets/js/'
            },
            tmp: {
                css: 'tmp/assets/css/',
                js: 'tmp/assets/js/'
            },
            dest: {
                css: 'public/assets/css/',
                js: 'public/assets/js/'
            }
        },

        // Set up timestamp.
        opt : {
            timestamp: '<%= new Date().getTime() %>'
        },

        // Use 'config.rb' file to configure Compass.
        compass: {
            dev: {
                options: {
                    config: 'config.rb',
                    force: true
                }
            }
        },

        // Combine any matching media queries.
        cmq: {
            css: {
                files: {
                    'tmp/assets/css': [
                        '<%= paths.tmp.css %>*.css',
                        // Ignore these non-concatenated files.
                        '!<%= paths.tmp.css %>style.css',
                        '!<%= paths.tmp.css %>jquery-ui.css'
                    ]
                }
            }
        },

        // Concatenate CSS files prior to matching media queries.
        concat: {
            css: {
                src: [
                    '<%= paths.tmp.css %>style.css',
                    '<%= paths.tmp.css %>jquery-ui.css',
                    'node_modules/flowplayer/dist/skin/minimalist.css'
                ],
                dest: '<%= paths.tmp.css %>main.css'
            }
        },

        copy: {
            // Copy files from various sources.
            js: {
                files: [
                    {expand: true, cwd: 'src/', src: ['*'], dest: 'public/', filter: 'isFile'},
                    {expand: true, cwd: '<%= paths.src.js %>libs/', src: ['**'], dest: '<%= paths.dest.js %>'},
                    {expand: true, cwd: 'node_modules/flowplayer/dist/', src: ['**'], dest: '<%= paths.dest.js %>flowplayer/'}
                ]
            },

            // Copy Flowplayer images and fonts to CSS folder (because Flowplayer's CSS expects relative path to these).
            css: {
                files: [
                    {expand: true, cwd: 'node_modules/flowplayer/dist/skin/img/', src: ['**'], dest: '<%= paths.dest.css %>img/'},
                    {expand: true, cwd: 'node_modules/flowplayer/dist/skin/fonts/', src: ['**'], dest: '<%= paths.dest.css %>fonts/'}
                ]
            }
        },

        // Dissect and provide example file of critical above-the-fold CSS.
        // Usage info: https://github.com/addyosmani/critical
        critical: {
            test: {
                options: {
                    base: './',
                    css: [
                        '<%= paths.tmp.css %>main.css'
                    ],
                    width: 1280,
                    height: 900,
                    minify: false
                },
                src: 'public/index.html',
                dest: '<%= paths.dest.css %>critical.css'
            }
        },

        // Minify and copy CSS files to `public/assets/css/`.
        cssmin: {
            main: {
                files: {
                    '<%= paths.dest.css %>main.css': ['<%= paths.tmp.css %>main.css'],
                    '<%= paths.dest.css %>ie8.css': ['<%= paths.tmp.css %>ie8.css'],
                    '<%= paths.dest.css %>design-patterns.css': ['<%= paths.tmp.css %>design-patterns.css']
                }
            }
        },

        // Check code quality of Gruntfile.js and site-specific JavaScript using JSHint.
        jshint: {
            files: ['Gruntfile.js', '<%= paths.src.js %>*.js'],
            options: {
                bitwise: true,
                camelcase: true,
                curly: true,
                eqeqeq: true,
                es3: true,
                forin: true,
                immed: true,
                indent: 4,
                latedef: true,
                noarg: true,
                noempty: true,
                nonew: true,
                quotmark: 'single',
                undef: true,
                unused: true,
                strict: true,
                trailing: true,
                browser: true,
                globals: {
                    jQuery: true,
                    Zepto: true,
                    define: true,
                    module: true,
                    require: true,
                    requirejs: true,
                    autosize: true,
                    responsiveNav: true,
                    prettyPrint: true
                }
            }
        },

        // Generate filename timestamps within template/mockup files.
        replace: {
            theme: {
                options: {
                    patterns: [{
                            match: 'timestamp',
                            replacement: '<%= opt.timestamp %>'
                    }]
                },
                files: [
                    {expand: true, cwd: 'src/templates/', src: ['**'], dest: 'public/templates/'},
                    {src: ['<%= paths.src.js %>main.js'], dest: '<%= paths.tmp.js %>main.js'}
                ]
            }
        },

        // Validate Sass files via sass-lint.
        sasslint: {
            options: {
                configFile: '.sass-lint.yml'
            },
            target: ['<%= paths.src.sass %>**/*.scss']
        },

        // Uglify and copy JavaScript files from `bower_components`, and also `main.js`, to `public/assets/js/`.
        uglify: {
            dist: {
                // Preserve all comments that start with a bang (!) or include a closure compiler style.
                options: {
                    preserveComments: 'some'
                },
                files: [
                    {
                        '<%= paths.dest.js %>main.js': ['<%= paths.tmp.js %>main.js'],
                        '<%= paths.dest.js %>autosize.js': ['node_modules/autosize/dist/autosize.js'],
                        '<%= paths.dest.js %>cookie.js': ['bower_components/jquery.cookie/jquery.cookie.js'],
                        //'<%= paths.dest.js %>cookie.js': ['bower_components/js-cookie/src/js.cookie.js'], // TODO: migrate to JS Cookie v2
                        '<%= paths.dest.js %>details.js': ['bower_components/jquery-details/jquery.details.js'],
                        '<%= paths.dest.js %>picturefill.js': ['node_modules/picturefill/dist/picturefill.js'],
                        '<%= paths.dest.js %>prettify.js': ['bower_components/google-code-prettify/src/prettify.js'],
                        '<%= paths.dest.js %>require.js': ['node_modules/requirejs/require.js'],
                        '<%= paths.dest.js %>responsivenav.js': ['bower_components/responsive-nav/responsive-nav.js'],
                        '<%= paths.dest.js %>responsiveslides.js': ['bower_components/ResponsiveSlides.js/responsiveslides.js']
                    },
                    {
                        expand: true,
                        cwd: 'bower_components/google-code-prettify/src/',
                        src: 'lang-*.js',
                        dest: '<%= paths.dest.js %>'
                    }
                ]
            }
        },

        // Directories watched and tasks performed by invoking `grunt watch`.
        watch: {
            sass: {
                files: '<%= paths.src.sass %>**',
                tasks: ['sass']
            },

            js: {
                files: '<%= paths.src.js %>*.js',
                tasks: ['jshint', 'copy:js', 'uglify']
            }
        }

    });

    // Register tasks.
    grunt.registerTask('build', ['jshint', 'sass', 'copy:js', 'replace', 'uglify']);
    grunt.registerTask('criticalcss', ['sass', 'critical']);
    grunt.registerTask('default', ['watch']);
    grunt.registerTask('sass', ['sasslint', 'compass', 'concat', 'cmq', 'cssmin', 'copy:css']);
    grunt.registerTask('test', ['jshint']);
    grunt.registerTask('travis', ['jshint', 'compass']);
};
<commit_msg>Simplify<commit_after>module.exports = function (grunt)
{
    'use strict';

    // Load all Grunt tasks.
    require('load-grunt-tasks')(grunt);

    grunt.initConfig({
        pkg: grunt.file.readJSON('package.json'),

        // Set up paths.
        paths: {
            src: {
                sass: 'src/assets/sass/',
                js: 'src/assets/js/'
            },
            tmp: {
                css: 'tmp/assets/css/',
                js: 'tmp/assets/js/'
            },
            dest: {
                css: 'public/assets/css/',
                js: 'public/assets/js/'
            }
        },

        // Set up timestamp.
        opt : {
            timestamp: '<%= new Date().getTime() %>'
        },

        // Use 'config.rb' file to configure Compass.
        compass: {
            dev: {
                options: {
                    config: 'config.rb',
                    force: true
                }
            }
        },

        // Combine any matching media queries.
        cmq: {
            css: {
                files: {
                    'tmp/assets/css': [
                        '<%= paths.tmp.css %>*.css',
                        // Ignore these non-concatenated files.
                        '!<%= paths.tmp.css %>style.css',
                        '!<%= paths.tmp.css %>jquery-ui.css'
                    ]
                }
            }
        },

        // Concatenate CSS files prior to matching media queries.
        concat: {
            css: {
                src: [
                    '<%= paths.tmp.css %>style.css',
                    '<%= paths.tmp.css %>jquery-ui.css',
                    'node_modules/flowplayer/dist/skin/minimalist.css'
                ],
                dest: '<%= paths.tmp.css %>main.css'
            }
        },

        copy: {
            // Copy files from various sources.
            js: {
                files: [
                    {expand: true, cwd: 'src/', src: ['*'], dest: 'public/', filter: 'isFile'},
                    {expand: true, cwd: '<%= paths.src.js %>libs/', src: ['**'], dest: '<%= paths.dest.js %>'},
                    {expand: true, cwd: 'node_modules/flowplayer/dist/', src: ['**'], dest: '<%= paths.dest.js %>flowplayer/'}
                ]
            },

            // Copy Flowplayer images and fonts to CSS folder (because Flowplayer's CSS expects relative path to these).
            css: {
                files: [
                    {expand: true, cwd: 'node_modules/flowplayer/dist/skin/img/', src: ['**'], dest: '<%= paths.dest.css %>img/'},
                    {expand: true, cwd: 'node_modules/flowplayer/dist/skin/fonts/', src: ['**'], dest: '<%= paths.dest.css %>fonts/'}
                ]
            }
        },

        // Dissect and provide example file of critical above-the-fold CSS.
        // Usage info: https://github.com/addyosmani/critical
        critical: {
            test: {
                options: {
                    base: './',
                    css: [
                        '<%= paths.tmp.css %>main.css'
                    ],
                    width: 1280,
                    height: 900,
                    minify: false
                },
                src: 'public/index.html',
                dest: '<%= paths.dest.css %>critical.css'
            }
        },

        // Minify and copy CSS files to `public/assets/css/`.
        cssmin: {
            main: {
                files: {
                    '<%= paths.dest.css %>main.css': '<%= paths.tmp.css %>main.css',
                    '<%= paths.dest.css %>ie8.css': '<%= paths.tmp.css %>ie8.css',
                    '<%= paths.dest.css %>design-patterns.css': '<%= paths.tmp.css %>design-patterns.css'
                }
            }
        },

        // Check code quality of Gruntfile.js and site-specific JavaScript using JSHint.
        jshint: {
            files: ['Gruntfile.js', '<%= paths.src.js %>*.js'],
            options: {
                bitwise: true,
                camelcase: true,
                curly: true,
                eqeqeq: true,
                es3: true,
                forin: true,
                immed: true,
                indent: 4,
                latedef: true,
                noarg: true,
                noempty: true,
                nonew: true,
                quotmark: 'single',
                undef: true,
                unused: true,
                strict: true,
                trailing: true,
                browser: true,
                globals: {
                    jQuery: true,
                    Zepto: true,
                    define: true,
                    module: true,
                    require: true,
                    requirejs: true,
                    autosize: true,
                    responsiveNav: true,
                    prettyPrint: true
                }
            }
        },

        // Generate filename timestamps within template/mockup files.
        replace: {
            theme: {
                options: {
                    patterns: [{
                            match: 'timestamp',
                            replacement: '<%= opt.timestamp %>'
                    }]
                },
                files: [
                    {expand: true, cwd: 'src/templates/', src: ['**'], dest: 'public/templates/'},
                    {src: ['<%= paths.src.js %>main.js'], dest: '<%= paths.tmp.js %>main.js'}
                ]
            }
        },

        // Validate Sass files via sass-lint.
        sasslint: {
            options: {
                configFile: '.sass-lint.yml'
            },
            target: ['<%= paths.src.sass %>**/*.scss']
        },

        // Uglify and copy JavaScript files from `bower_components`, and also `main.js`, to `public/assets/js/`.
        uglify: {
            dist: {
                // Preserve all comments that start with a bang (!) or include a closure compiler style.
                options: {
                    preserveComments: 'some'
                },
                files: [
                    {
                        '<%= paths.dest.js %>main.js': ['<%= paths.tmp.js %>main.js'],
                        '<%= paths.dest.js %>autosize.js': ['node_modules/autosize/dist/autosize.js'],
                        '<%= paths.dest.js %>cookie.js': ['bower_components/jquery.cookie/jquery.cookie.js'],
                        //'<%= paths.dest.js %>cookie.js': ['bower_components/js-cookie/src/js.cookie.js'], // TODO: migrate to JS Cookie v2
                        '<%= paths.dest.js %>details.js': ['bower_components/jquery-details/jquery.details.js'],
                        '<%= paths.dest.js %>picturefill.js': ['node_modules/picturefill/dist/picturefill.js'],
                        '<%= paths.dest.js %>prettify.js': ['bower_components/google-code-prettify/src/prettify.js'],
                        '<%= paths.dest.js %>require.js': ['node_modules/requirejs/require.js'],
                        '<%= paths.dest.js %>responsivenav.js': ['bower_components/responsive-nav/responsive-nav.js'],
                        '<%= paths.dest.js %>responsiveslides.js': ['bower_components/ResponsiveSlides.js/responsiveslides.js']
                    },
                    {
                        expand: true,
                        cwd: 'bower_components/google-code-prettify/src/',
                        src: 'lang-*.js',
                        dest: '<%= paths.dest.js %>'
                    }
                ]
            }
        },

        // Directories watched and tasks performed by invoking `grunt watch`.
        watch: {
            sass: {
                files: '<%= paths.src.sass %>**',
                tasks: ['sass']
            },

            js: {
                files: '<%= paths.src.js %>*.js',
                tasks: ['jshint', 'copy:js', 'uglify']
            }
        }

    });

    // Register tasks.
    grunt.registerTask('build', ['jshint', 'sass', 'copy:js', 'replace', 'uglify']);
    grunt.registerTask('criticalcss', ['sass', 'critical']);
    grunt.registerTask('default', ['watch']);
    grunt.registerTask('sass', ['sasslint', 'compass', 'concat', 'cmq', 'cssmin', 'copy:css']);
    grunt.registerTask('test', ['jshint']);
    grunt.registerTask('travis', ['jshint', 'compass']);
};
<|endoftext|>


<commit_before>var gulp = require('gulp');
var sass = require('gulp-sass');
var pleeease = require('gulp-pleeease');
var concat = require('gulp-concat');
var uglify = require('gulp-uglify');
var imagemin = require('gulp-imagemin');
var browserSync = require('browser-sync');
var reload      = browserSync.reload;

// Sass

gulp.task('sass', function () {
    gulp.src('sass/**/*.scss')
        .pipe(sass({errLogToConsole: true})) // Keep running gulp even though occurred compile error
        .pipe(pleeease({
            autoprefixer: {
                browsers: ['last 2 versions']
            }
        }))
        .pipe(gulp.dest('build/css'))
        .pipe(reload({stream:true}));
});

// Js-concat-uglify

gulp.task('js', function() {
    gulp.src(['js/*.js'])
        .pipe(concat('scripts.js'))
        .pipe(uglify({preserveComments: 'some'})) // Keep some comments
        .pipe(gulp.dest('build/js'))
        .pipe(reload({stream:true}));
});

// Imagemin

gulp.task('imagemin', function() {
    gulp.src(['images/**/*.{png,jpg,gif,svg}'])
        .pipe(imagemin({optimizationLevel: 8}))
        .pipe(gulp.dest('build/images'));
});

// Static server

gulp.task('browser-sync', function() {
    browserSync({
        server: {
            baseDir: "./"
        }
    });
});

// Reload all browsers

gulp.task('bs-reload', function () {
    browserSync.reload();
});

// Task for `gulp` command

gulp.task('default',['browser-sync'], function() {
    gulp.watch('sass/**/*.scss',['sass']);
    gulp.watch('js/*.js',['js']);
    gulp.watch("*.html", ['bs-reload']);
});<commit_msg>gulpfile.js<commit_after><|endoftext|>


<commit_before>/*! React Starter Kit | MIT License | http://www.reactstarterkit.com/ */

import 'babel/polyfill';
import React from 'react';
import FastClick from 'fastclick';
import App from './components/App';
import Dispatcher from './core/Dispatcher';
import AppActions from './actions/AppActions';
import ActionTypes from './constants/ActionTypes';

let path = decodeURI(window.location.pathname);
let onSetMeta = (name, content) => {
  // Remove and create a new <meta /> tag in order to make it work
  // with bookmarks in Safari
  let elements = document.getElementsByTagName('meta');
  [].slice.call(elements).forEach((element) => {
    if (element.getAttribute('name') === name) {
      element.parentNode.removeChild(element);
    }
  });
  let meta = document.createElement('meta');
  meta.setAttribute('name', name);
  meta.setAttribute('content', content);
  document.getElementsByTagName('head')[0].appendChild(meta);
};

function run() {
  // Render the top-level React component
  let props = {
    path: path,
    context: {
      onSetTitle: value => document.title = value,
      onSetMeta
    }
  };
  let element = React.createElement(App, props);
  React.render(element, document.getElementById('app'), () => {
    let css = document.getElementById('css');
    css.parentNode.removeChild(css);
  });

  // Update `Application.path` prop when `window.location` is changed
  Dispatcher.register((action) => {
    if (action.type === ActionTypes.CHANGE_LOCATION) {
      element = React.cloneElement(element, {path: action.path});
      React.render(element, document.getElementById('app'));
    }
  });
}

// Run the application when both DOM is ready
// and page content is loaded
Promise.all([
  new Promise((resolve) => {
    if (window.addEventListener) {
      window.addEventListener('DOMContentLoaded', resolve);
    } else {
      window.attachEvent('onload', resolve);
    }
  }).then(() => FastClick.attach(document.body)),
  new Promise((resolve) => AppActions.loadPage(path, resolve))
]).then(run);
<commit_msg>Replaces app with super simple React component<commit_after>let React = require('react');

class AvatarApp extends React.Component {
  render() {
    return
Hello, World
;
  }
}

React.render(<AvatarApp />, document.getElementById('app'));
<|endoftext|>


<commit_before>var UI = require('ui');
var ajax = require('ajax');
var Vector2 = require('vector2');

var parseFeed = function(data, quantity) {
  var items = [];
  for(var i = 0; i < quantity; i++) {
    // Always upper case the description string
    var title = data.list[i].weather[0].main;
    title = title.charAt(0).toUpperCase() + title.substring(1);

    // Get date/time substring
    var time = data.list[i].dt_txt;
    time = time.substring(time.indexOf('-') + 1, time.indexOf(':') + 3);

    // Add to menu items array
    items.push({
      title:title,
      subtitle:time
    });
  }

  // Finally return whole array
  return items;
};

// Show splash screen while waiting for data
var splashWindow = new UI.Window();

// Text element to inform user
var text = new UI.Text({
  position: new Vector2(0, 0),
  size: new Vector2(144, 168),
  text:'Downloading weather data...',
  font:'GOTHIC_28_BOLD',
  color:'black',
  textOverflow:'wrap',
  textAlign:'center',
	backgroundColor:'white'
});

// Add to splashWindow and show
splashWindow.add(text);
splashWindow.show();

// Make request to openweathermap.org
ajax(
  {
    url:'http://api.openweathermap.org/data/2.5/forecast?q=London',
    type:'json'
  },
  function(data) {
    // Create an array of Menu items
    var menuItems = parseFeed(data, 10);

    // Construct Menu to show to user
    var resultsMenu = new UI.Menu({
      sections: [{
        title: 'Current Forecast',
        items: menuItems
      }]
    });

    // Show the Menu, hide the splash
    resultsMenu.show();
    splashWindow.hide();
  },
  function(error) {
    console.log('Download failed: ' + error);
  }
);
<commit_msg>Working Prototype<commit_after>var UI = require('ui');
var ajax = require('ajax');
var Vector2 = require('vector2');

var parseFeed = function(data) {
  var items = [];

  for(var i = 0; i < data.prediction.predictionUnit.length; i++) {
    var title = data.prediction.predictionUnit[i].route;
    var time = data.prediction.predictionUnit[i].time;

      console.log(title);
      console.log(time);
    // Add to menu items array
    items.push({
      title:title,
      subtitle:time
    });
  }

  // Finally return whole array
  return items;
};

// Show splash screen while waiting for data
var splashWindow = new UI.Window();

// Text element to inform user
var text = new UI.Text({
  position: new Vector2(0, 0),
  size: new Vector2(144, 168),
  text:'LOADING',
  font:'GOTHIC_28_BOLD',
  color:'black',
  textOverflow:'wrap',
  textAlign:'center',
	backgroundColor:'white'
});

// Add to splashWindow and show
splashWindow.add(text);
splashWindow.show();

// Make request to openweathermap.org
ajax(
  {
    url:'http://theloganwalker.com/info/dev.php',
    type:'json'
  },
  function(data) {
    // Create an array of Menu items
    var menuItems = parseFeed(data);

    // Construct Menu to show to user
    var resultsMenu = new UI.Menu({
      sections: [{
        title: 'Current Busses',
        items: menuItems
      }]
    });

    // Show the Menu, hide the splash
    resultsMenu.show();
    splashWindow.hide();
  },
  function(error) {
    console.log('Download failed: ' + error);
  }
);
<|endoftext|>


<commit_before>// @flow
import React, {PureComponent} from 'react';
import * as Immutable from 'immutable';
import clipboard from 'clipboard-js';
import generate from 'babel-generator';

import type {ASTNode, ASTPath} from './types';
import {ArrayExpression, ObjectExpression} from './components/collections';
import Keymap from './components/keymap';
import {BooleanLiteral, NumericLiteral, StringLiteral} from './components/literals';
import {
  isBooleanLiteral, isNumericLiteral, isArrayExpression, isObjectExpression, isEditable
} from './checks';
import example from '../package.json';
import navigate from './navigate';
import parse from './parse';
import renderTypeElement, {injectTypeElements} from './render-type-element';

const {List, Map} = Immutable;

const MAX_HISTORY_LENGTH = 100;

injectTypeElements({
  BooleanLiteral,
  NumericLiteral,
  StringLiteral,
  ArrayExpression,
  ObjectExpression
});

const BooleanNode = new Map({type: 'BooleanLiteral', value: true});
const NumericNode = new Map({type: 'NumericLiteral', value: '0'});
const StringNode = new Map({type: 'StringLiteral', value: ''});
const ArrayNode = Immutable.fromJS({type: 'ArrayExpression', elements: []});
const ObjectNode = Immutable.fromJS({type: 'ObjectExpression', properties: []});

const links = [
  ['Reasoning', 'https://medium.com/@grgtwt/code-is-not-just-text-1082981ae27f'],
  ['Roadmap', 'https://github.com/Gregoor/syntactor#roadmap'],
  ['GitHub', 'https://github.com/gregoor/syntactor'],
  ['Issues', 'https://github.com/Gregoor/syntactor/issues']
];

const cardStyle = {
  padding: 20,
  background: 'white',
  boxShadow: '0 2px 2px 0 rgba(0,0,0,.14), 0 3px 1px -2px rgba(0,0,0,.2), 0 1px 5px 0 rgba(0,0,0,.12)'
};

export default class App extends PureComponent {

  state = {
    future: new List(),
    history: new List([
      new Map({
        inputMode: false,
        root: parse(example),
        selected: new List()
      })
    ])
  };

  getSelectedNode() {
    const editorState = this.state.history.first();
    return editorState.get('root').getIn(editorState.get('selected'));
  }

  getClosestCollectionPath(root: ASTNode, selected: ASTPath) {
    const selectedNode = root.getIn(selected);

    if (selectedNode) {
      if (isObjectExpression(selectedNode)) {
        return selected.push('properties');
      } else if (isArrayExpression(selectedNode)) {
        return selected.push('elements');
      }
    }

    const index = selected.findLastIndex((key) => ['elements', 'properties'].includes(key));
    return selected.slice(0, index + 1);
  }

  getDirection(key: string) {
    switch (key) {

      case 'k':
      case 'ArrowUp':
        return 'UP';

      case 'j':
      case 'ArrowDown':
        return 'DOWN';

      case 'h':
      case 'ArrowLeft':
        return 'LEFT';

      case 'l':
      case 'ArrowRight':
        return 'RIGHT';

      default:
        return;

    }
  }

  addToHistory(updateFn: (root: ASTNode, selected: ASTPath) => any) {
    this.setState(({history}) => {
      const editorState = history.first();
      const root = editorState.get('root');
      const selected = editorState.get('selected');
      const inputMode = editorState.get('inputMode');
      return {
        future: new List(),
        history: history.unshift(new Map({
          inputMode, root, selected,
          ...updateFn(root, selected, inputMode)
        })).slice(0, MAX_HISTORY_LENGTH)
      };
    });
  }

  updateValue(updateFn: (any) => any) {
    this.addToHistory((root, selected) => ({
      root: root.updateIn(selected.push('value'), updateFn)
    }));
  }

  insert = (node: ASTNode) => this.addToHistory((root, selected) => {
    const collectionPath = this.getClosestCollectionPath(root, selected);
    const itemIndex = selected.get(collectionPath.size) + 1 || 0;

    const isArray = isArrayExpression(root.getIn(collectionPath.slice(0, -1)));

    const newRoot = root.updateIn(collectionPath, (list) => list.insert(
      itemIndex,
      isArray
        ? node
        : new Map({type: 'ObjectProperty', key: StringNode, value: node})
    ));
    const newSelected = isArray
      ? collectionPath.push(itemIndex)
      : collectionPath.push(itemIndex, 'key');
    return {
      inputMode: !isArray || isEditable(newRoot.getIn(newSelected)),
      root: newRoot,
      selected: newSelected
    };
  });

  goToEditable(direction: 'LEFT' | 'RIGHT') {
    return this.addToHistory((root, selected) => {
      let visitedPaths = new List();
      let lastEditablePath = selected;
      let newSelectedNode;
      let newlySelectedIsEditable;
      do {
        selected = navigate(direction, root, selected);
        if (visitedPaths.includes(selected)) {
          return {selected: lastEditablePath};
        }
        visitedPaths = visitedPaths.push(selected);
        newSelectedNode = root.getIn(selected);
        newlySelectedIsEditable = newSelectedNode && isEditable(newSelectedNode);
        if (newlySelectedIsEditable) {
          lastEditablePath = selected;
        }
      } while (!newlySelectedIsEditable);
      return {selected: lastEditablePath};
    });
  }

  handleKeyDown = (event: any) => {
    const {ctrlKey, key} = event;

    const direction = this.getDirection(key);

    const editorState = this.state.history.first();
    if (!editorState.get('inputMode')) {

      if (direction) {
        return this.addToHistory((root, selected) => ({
          selected: navigate(direction, root, selected)
        }));
      }

      const selectedNode = this.getSelectedNode();

      switch (key) {

        case 's':
        case '\'':
          return this.insert(StringNode);

        case 'n':
          return this.insert(NumericNode);

        case 'b':
          return this.insert(BooleanNode);

        case 'a':
        case '[':
          return this.insert(ArrayNode);

        case 'o':
        case '{':
          return this.insert(ObjectNode);

        case '+':
        case '-':
          return isNumericLiteral(selectedNode) && this.updateValue(
            (value) => value + (key === '+' ? 1 : -1)
          );

        case 't':
        case 'f':
          return isBooleanLiteral(selectedNode) && this.updateValue(
            () => Boolean(key === 't')
          );

        case 'd':
        case 'Delete':
          return this.addToHistory((root, selected) => ({
            root: root.deleteIn(
              selected.slice(0, 1 + selected.findLastIndex((value) => typeof value === 'number'))
            ),
            selected: selected.last() === 'end' ? new List() : navigate('UP', root, selected)
          }));

        case 'i':
        case 'Enter':
          return isEditable(selectedNode) && this.addToHistory(() => ({inputMode: true}));

        default:

      }

      if (ctrlKey && key === 'c') {
        event.preventDefault();
        return clipboard.copy(
          generate(editorState.get('root').getIn(editorState.get('selected')).toJS()).code
        );
      }
    }

    if (ctrlKey && key.toLowerCase() === 'z') {
      event.preventDefault();
      return this.setState(({future, history}) => key === 'z'
        ? {
          future: future.unshift(history.first()),
          history: history.shift()
        }
        : {
          future: future.shift(),
          history: future.isEmpty() ? history : history.unshift(future.first())
        }
      );
    }

    if (['Enter', 'Escape'].includes(key)) {
      this.addToHistory((root, selected) => ({
        inputMode: false,
        root: root.getIn(selected.push('type')) === 'NumericLiteral'
          ? root.updateIn(selected.push('value'), (value) => parseFloat(value))
          : root
      }));
    }

    if (key === 'Tab') {
      event.preventDefault();
      return this.goToEditable(event.shiftKey ? 'LEFT' : 'RIGHT');
    }
  };

  handleChange = ({target: {value}}: any) => {
    this.addToHistory((root, selected, inputMode) => inputMode ? {
      root: root.setIn(selected.push('value'), value)
    } : {});
  };

  render() {
    const {history} = this.state;
    const editorState = history.first();
    const inputMode = editorState.get('inputMode');
    const selected = editorState.get('selected');
    const isInArray = (selected.last() === 'end' ? selected.slice(0, -2) : selected)
        .findLast((key) => ['elements', 'properties'].includes(key)) === 'elements';
    return (

 div && !inputMode && div.focus()}
           tabIndex="0" onKeyDown={this.handleKeyDown}>

Syntactor

              |
              {links.map(([label, link], i) => [
                {label},
                '|'
              ])}

              An editor with two basic goals:

Manage syntax and code style (no syntax errors, no bikeshedding)

At least as fast at making changes as regular editors

              For now, it's only a JSON editor.

            <form onChange={this.handleChange} style={{height: '100%', width: '100%', ...cardStyle}}>
              {renderTypeElement(editorState.get('root'), {inputMode, level: 0, selected})}
            </form>

              <Keymap {...{inputMode, isInArray}} selectedNode={this.getSelectedNode()}/>

    );
  }

}<commit_msg>fix copy when collection end selected<commit_after>// @flow
import React, {PureComponent} from 'react';
import * as Immutable from 'immutable';
import clipboard from 'clipboard-js';
import generate from 'babel-generator';

import type {ASTNode, ASTPath} from './types';
import {ArrayExpression, ObjectExpression} from './components/collections';
import Keymap from './components/keymap';
import {BooleanLiteral, NumericLiteral, StringLiteral} from './components/literals';
import {
  isBooleanLiteral, isNumericLiteral, isArrayExpression, isObjectExpression, isEditable
} from './checks';
import example from '../package.json';
import navigate from './navigate';
import parse from './parse';
import renderTypeElement, {injectTypeElements} from './render-type-element';

const {List, Map} = Immutable;

const MAX_HISTORY_LENGTH = 100;

injectTypeElements({
  BooleanLiteral,
  NumericLiteral,
  StringLiteral,
  ArrayExpression,
  ObjectExpression
});

const BooleanNode = new Map({type: 'BooleanLiteral', value: true});
const NumericNode = new Map({type: 'NumericLiteral', value: '0'});
const StringNode = new Map({type: 'StringLiteral', value: ''});
const ArrayNode = Immutable.fromJS({type: 'ArrayExpression', elements: []});
const ObjectNode = Immutable.fromJS({type: 'ObjectExpression', properties: []});

const links = [
  ['Reasoning', 'https://medium.com/@grgtwt/code-is-not-just-text-1082981ae27f'],
  ['Roadmap', 'https://github.com/Gregoor/syntactor#roadmap'],
  ['GitHub', 'https://github.com/gregoor/syntactor'],
  ['Issues', 'https://github.com/Gregoor/syntactor/issues']
];

const cardStyle = {
  padding: 20,
  background: 'white',
  boxShadow: '0 2px 2px 0 rgba(0,0,0,.14), 0 3px 1px -2px rgba(0,0,0,.2), 0 1px 5px 0 rgba(0,0,0,.12)'
};

export default class App extends PureComponent {

  state = {
    future: new List(),
    history: new List([
      new Map({
        inputMode: false,
        root: parse(example),
        selected: new List()
      })
    ])
  };

  getSelectedNode() {
    const editorState = this.state.history.first();
    return editorState.get('root').getIn(editorState.get('selected'));
  }

  getClosestCollectionPath(root: ASTNode, selected: ASTPath) {
    const selectedNode = root.getIn(selected);

    if (selectedNode) {
      if (isObjectExpression(selectedNode)) {
        return selected.push('properties');
      } else if (isArrayExpression(selectedNode)) {
        return selected.push('elements');
      }
    }

    const index = selected.findLastIndex((key) => ['elements', 'properties'].includes(key));
    return selected.slice(0, index + 1);
  }

  getDirection(key: string) {
    switch (key) {

      case 'k':
      case 'ArrowUp':
        return 'UP';

      case 'j':
      case 'ArrowDown':
        return 'DOWN';

      case 'h':
      case 'ArrowLeft':
        return 'LEFT';

      case 'l':
      case 'ArrowRight':
        return 'RIGHT';

      default:
        return;

    }
  }

  addToHistory(updateFn: (root: ASTNode, selected: ASTPath) => any) {
    this.setState(({history}) => {
      const editorState = history.first();
      const root = editorState.get('root');
      const selected = editorState.get('selected');
      const inputMode = editorState.get('inputMode');
      return {
        future: new List(),
        history: history.unshift(new Map({
          inputMode, root, selected,
          ...updateFn(root, selected, inputMode)
        })).slice(0, MAX_HISTORY_LENGTH)
      };
    });
  }

  updateValue(updateFn: (any) => any) {
    this.addToHistory((root, selected) => ({
      root: root.updateIn(selected.push('value'), updateFn)
    }));
  }

  insert = (node: ASTNode) => this.addToHistory((root, selected) => {
    const collectionPath = this.getClosestCollectionPath(root, selected);
    const itemIndex = selected.get(collectionPath.size) + 1 || 0;

    const isArray = isArrayExpression(root.getIn(collectionPath.slice(0, -1)));

    const newRoot = root.updateIn(collectionPath, (list) => list.insert(
      itemIndex,
      isArray
        ? node
        : new Map({type: 'ObjectProperty', key: StringNode, value: node})
    ));
    const newSelected = isArray
      ? collectionPath.push(itemIndex)
      : collectionPath.push(itemIndex, 'key');
    return {
      inputMode: !isArray || isEditable(newRoot.getIn(newSelected)),
      root: newRoot,
      selected: newSelected
    };
  });

  goToEditable(direction: 'LEFT' | 'RIGHT') {
    return this.addToHistory((root, selected) => {
      let visitedPaths = new List();
      let lastEditablePath = selected;
      let newSelectedNode;
      let newlySelectedIsEditable;
      do {
        selected = navigate(direction, root, selected);
        if (visitedPaths.includes(selected)) {
          return {selected: lastEditablePath};
        }
        visitedPaths = visitedPaths.push(selected);
        newSelectedNode = root.getIn(selected);
        newlySelectedIsEditable = newSelectedNode && isEditable(newSelectedNode);
        if (newlySelectedIsEditable) {
          lastEditablePath = selected;
        }
      } while (!newlySelectedIsEditable);
      return {selected: lastEditablePath};
    });
  }

  handleKeyDown = (event: any) => {
    const {ctrlKey, key} = event;

    const direction = this.getDirection(key);

    const editorState = this.state.history.first();
    if (!editorState.get('inputMode')) {

      if (direction) {
        return this.addToHistory((root, selected) => ({
          selected: navigate(direction, root, selected)
        }));
      }

      const selectedNode = this.getSelectedNode();

      switch (key) {

        case 's':
        case '\'':
          return this.insert(StringNode);

        case 'n':
          return this.insert(NumericNode);

        case 'b':
          return this.insert(BooleanNode);

        case 'a':
        case '[':
          return this.insert(ArrayNode);

        case 'o':
        case '{':
          return this.insert(ObjectNode);

        case '+':
        case '-':
          return isNumericLiteral(selectedNode) && this.updateValue(
            (value) => value + (key === '+' ? 1 : -1)
          );

        case 't':
        case 'f':
          return isBooleanLiteral(selectedNode) && this.updateValue(
            () => Boolean(key === 't')
          );

        case 'd':
        case 'Delete':
          return this.addToHistory((root, selected) => ({
            root: root.deleteIn(
              selected.slice(0, 1 + selected.findLastIndex((value) => typeof value === 'number'))
            ),
            selected: selected.last() === 'end' ? new List() : navigate('UP', root, selected)
          }));

        case 'i':
        case 'Enter':
          return isEditable(selectedNode) && this.addToHistory(() => ({inputMode: true}));

        default:

      }

      if (ctrlKey && key === 'c') {
        event.preventDefault();
        let selected = editorState.get('selected');
        if (selected.last() === 'end') {
          selected = selected.slice(0, -2);
        }
        console.log(selected.toJS());
        return clipboard.copy(
          generate(editorState.get('root').getIn(selected).toJS()).code
        );
      }
    }

    if (ctrlKey && key.toLowerCase() === 'z') {
      event.preventDefault();
      return this.setState(({future, history}) => key === 'z'
        ? {
          future: future.unshift(history.first()),
          history: history.shift()
        }
        : {
          future: future.shift(),
          history: future.isEmpty() ? history : history.unshift(future.first())
        }
      );
    }

    if (['Enter', 'Escape'].includes(key)) {
      this.addToHistory((root, selected) => ({
        inputMode: false,
        root: root.getIn(selected.push('type')) === 'NumericLiteral'
          ? root.updateIn(selected.push('value'), (value) => parseFloat(value))
          : root
      }));
    }

    if (key === 'Tab') {
      event.preventDefault();
      return this.goToEditable(event.shiftKey ? 'LEFT' : 'RIGHT');
    }
  };

  handleChange = ({target: {value}}: any) => {
    this.addToHistory((root, selected, inputMode) => inputMode ? {
      root: root.setIn(selected.push('value'), value)
    } : {});
  };

  render() {
    const {history} = this.state;
    const editorState = history.first();
    const inputMode = editorState.get('inputMode');
    const selected = editorState.get('selected');
    const isInArray = (selected.last() === 'end' ? selected.slice(0, -2) : selected)
        .findLast((key) => ['elements', 'properties'].includes(key)) === 'elements';
    return (

 div && !inputMode && div.focus()}
           tabIndex="0" onKeyDown={this.handleKeyDown}>

Syntactor

              |
              {links.map(([label, link], i) => [
                {label},
                '|'
              ])}

              An editor with two basic goals:

Manage syntax and code style (no syntax errors, no bikeshedding)

At least as fast at making changes as regular editors

              For now, it's only a JSON editor.

            <form onChange={this.handleChange} style={{height: '100%', width: '100%', ...cardStyle}}>
              {renderTypeElement(editorState.get('root'), {inputMode, level: 0, selected})}
            </form>

              <Keymap {...{inputMode, isInArray}} selectedNode={this.getSelectedNode()}/>

    );
  }

}<|endoftext|>


<commit_before>module.exports = function (grunt) {
    // Do grunt-related things in here
    grunt.initConfig({
        pkg : grunt.file.readJSON('package.json'),
        meta : {
            project : '<%= pkg.name %>',
            version : '<%= pkg.version %>',
            banner  : '/*! <%= meta.project %> - v<%= meta.version %> - \n' +
            ' * Copyright (c) Hassan Khan <%= grunt.template.today("yyyy") %>\n' +
            ' */'
        },
        jshint : {
            files        : ['emojify.js']
        },
        uglify : {
            options : {
                banner : '<%= meta.banner %>'
            },
            production : {
                files : {
                    'emojify.min.js' : 'emojify.js'
                }
            }
        }
    });

    grunt.loadNpmTasks('grunt-contrib-jshint');
    grunt.loadNpmTasks('grunt-contrib-uglify');

    grunt.registerTask(
        'default',
        [
            'jshint',
            'uglify'
        ]
    );
};
<commit_msg>Implement buildCSS task, builds emoji.css with all images base64 encoded as styles<commit_after>module.exports = function (grunt) {
    // Do grunt-related things in here
    grunt.initConfig({
        pkg : grunt.file.readJSON('package.json'),
        meta : {
            project : '<%= pkg.name %>',
            version : '<%= pkg.version %>',
            banner  : '/*! <%= meta.project %> - v<%= meta.version %> - \n' +
            ' * Copyright (c) Hassan Khan <%= grunt.template.today("yyyy") %>\n' +
            ' */'
        },
        jshint : {
            files        : ['emojify.js']
        },
        uglify : {
            options : {
                banner : '<%= meta.banner %>'
            },
            production : {
                files : {
                    'emojify.min.js' : 'emojify.js'
                }
            }
        }
    });

    grunt.loadNpmTasks('grunt-contrib-jshint');
    grunt.loadNpmTasks('grunt-contrib-uglify');

    grunt.registerTask(
        'default',
        [
            'jshint',
            'uglify'
        ]
    );

    grunt.registerTask('buildCSS', 'Generate CSS for emojis in /images', function() {
        var fs = require('fs'),
            path = require('path'),
            util = require('util'),
            done = this.async(),
            emojiPath = './images/emoji/',
            emojiCSS = fs.createWriteStream('emojify.css', {'flags': 'w'}),
            buildSelector = function(imageName, encodedImage) {
                return util.format('.emjoi-%s {\n  background:\n    url(data:image/png;base64,%s)\n    no-repeat\n    left-center;\n}\n',
                                   imageName, encodedImage);
            };

        fs.readdir(emojiPath, function (err, files) {
            files.map(function(file) {
                fs.readFile(path.join(emojiPath, file), function(err, data){
                    var base64Image = new Buffer(data, 'binary').toString('base64');
                    emojiCSS.write(buildSelector(file.slice(0, -4), base64Image));
                });
            });
        });
    });
};
<|endoftext|>


<commit_before>/* global module:false */
module.exports = function(grunt) {
	var port = grunt.option('port') || 8000;
	// Project configuration
	grunt.initConfig({
		pkg: grunt.file.readJSON('package.json'),
		meta: {
			banner:
				'/*!\n' +
				' * reveal.js <%= pkg.version %> (<%= grunt.template.today("yyyy-mm-dd, HH:MM") %>)\n' +
				' * http://lab.hakim.se/reveal-js\n' +
				' * MIT licensed\n' +
				' *\n' +
				' * Copyright (C) 2015 Hakim El Hattab, http://hakim.se\n' +
				' */'
		},

		qunit: {
			files: [ 'test/*.html' ]
		},

		uglify: {
			options: {
				banner: '<%= meta.banner %>\n'
			},
			build: {
				src: 'js/reveal.js',
				dest: 'js/reveal.min.js'
			}
		},

		sass: {
			core: {
				files: {
					'css/reveal.css': 'css/reveal.scss',
				}
			},
			themes: {
				files: {
					'css/theme/black.css': 'css/theme/source/black.scss',
					'css/theme/white.css': 'css/theme/source/white.scss',
					'css/theme/league.css': 'css/theme/source/league.scss',
					'css/theme/beige.css': 'css/theme/source/beige.scss',
					'css/theme/night.css': 'css/theme/source/night.scss',
					'css/theme/serif.css': 'css/theme/source/serif.scss',
					'css/theme/simple.css': 'css/theme/source/simple.scss',
					'css/theme/sky.css': 'css/theme/source/sky.scss',
					'css/theme/moon.css': 'css/theme/source/moon.scss',
					'css/theme/solarized.css': 'css/theme/source/solarized.scss',
					'css/theme/blood.css': 'css/theme/source/blood.scss'
				}
			}
		},

		autoprefixer: {
			dist: {
				src: 'css/reveal.css'
			}
		},

		cssmin: {
			compress: {
				files: {
					'css/reveal.min.css': [ 'css/reveal.css' ]
				}
			}
		},

		jshint: {
			options: {
				curly: false,
				eqeqeq: true,
				immed: true,
				latedef: true,
				newcap: true,
				noarg: true,
				sub: true,
				undef: true,
				eqnull: true,
				browser: true,
				expr: true,
				globals: {
					head: false,
					module: false,
					console: false,
					unescape: false,
					define: false,
					exports: false
				}
			},
			files: [ 'Gruntfile.js', 'js/reveal.js' ]
		},

		connect: {
			server: {
				options: {
					port: port,
					base: '.',
                    livereload: true,
                    open: true
				}
			}
		},

		zip: {
			'reveal-js-presentation.zip': [
				'index.html',
				'css/**',
				'js/**',
				'lib/**',
				'images/**',
				'plugin/**'
			]
		},

		watch: {
            options: {
                livereload: true
            },
			js: {
				files: [ 'Gruntfile.js', 'js/reveal.js' ],
				tasks: 'js'
			},
			theme: {
				files: [ 'css/theme/source/*.scss', 'css/theme/template/*.scss' ],
				tasks: 'css-themes'
			},
			css: {
				files: [ 'css/reveal.scss' ],
				tasks: 'css-core'
			},
            html: {
                files: [ 'index.html']
            }
		}

	});

	// Dependencies
	grunt.loadNpmTasks( 'grunt-contrib-qunit' );
	grunt.loadNpmTasks( 'grunt-contrib-jshint' );
	grunt.loadNpmTasks( 'grunt-contrib-cssmin' );
	grunt.loadNpmTasks( 'grunt-contrib-uglify' );
	grunt.loadNpmTasks( 'grunt-contrib-watch' );
	grunt.loadNpmTasks( 'grunt-sass' );
	grunt.loadNpmTasks( 'grunt-contrib-connect' );
	grunt.loadNpmTasks( 'grunt-autoprefixer' );
	grunt.loadNpmTasks( 'grunt-zip' );

	// Default task
	grunt.registerTask( 'default', [ 'css', 'js' ] );

	// JS task
	grunt.registerTask( 'js', [ 'jshint', 'uglify', 'qunit' ] );

	// Theme CSS
	grunt.registerTask( 'css-themes', [ 'sass:themes' ] );

	// Core framework CSS
	grunt.registerTask( 'css-core', [ 'sass:core', 'autoprefixer', 'cssmin' ] );

	// All CSS
	grunt.registerTask( 'css', [ 'sass', 'autoprefixer', 'cssmin' ] );

	// Package presentation to archive
	grunt.registerTask( 'package', [ 'default', 'zip' ] );

	// Serve presentation locally
	grunt.registerTask( 'serve', [ 'connect', 'watch' ] );

	// Run tests
	grunt.registerTask( 'test', [ 'jshint', 'qunit' ] );

};
<commit_msg>adding to the grunt compilation list, according to the readme. next, try compiling with grunt css-themes.<commit_after>/* global module:false */
module.exports = function(grunt) {
	var port = grunt.option('port') || 8000;
	// Project configuration
	grunt.initConfig({
		pkg: grunt.file.readJSON('package.json'),
		meta: {
			banner:
				'/*!\n' +
				' * reveal.js <%= pkg.version %> (<%= grunt.template.today("yyyy-mm-dd, HH:MM") %>)\n' +
				' * http://lab.hakim.se/reveal-js\n' +
				' * MIT licensed\n' +
				' *\n' +
				' * Copyright (C) 2015 Hakim El Hattab, http://hakim.se\n' +
				' */'
		},

		qunit: {
			files: [ 'test/*.html' ]
		},

		uglify: {
			options: {
				banner: '<%= meta.banner %>\n'
			},
			build: {
				src: 'js/reveal.js',
				dest: 'js/reveal.min.js'
			}
		},

		sass: {
			core: {
				files: {
					'css/reveal.css': 'css/reveal.scss',
				}
			},
			themes: {
				files: {
					'css/theme/black.css': 'css/theme/source/black.scss',
					'css/theme/white.css': 'css/theme/source/white.scss',
					'css/theme/league.css': 'css/theme/source/league.scss',
					'css/theme/beige.css': 'css/theme/source/beige.scss',
					'css/theme/night.css': 'css/theme/source/night.scss',
					'css/theme/serif.css': 'css/theme/source/serif.scss',
					'css/theme/simple.css': 'css/theme/source/simple.scss',
					'css/theme/sky.css': 'css/theme/source/sky.scss',
					'css/theme/moon.css': 'css/theme/source/moon.scss',
					'css/theme/solarized.css': 'css/theme/source/solarized.scss',
					'css/theme/blood.css': 'css/theme/source/blood.scss'
					'css/theme/midcamp.css': 'css/theme/source/midcamp.scss'
				}
			}
		},

		autoprefixer: {
			dist: {
				src: 'css/reveal.css'
			}
		},

		cssmin: {
			compress: {
				files: {
					'css/reveal.min.css': [ 'css/reveal.css' ]
				}
			}
		},

		jshint: {
			options: {
				curly: false,
				eqeqeq: true,
				immed: true,
				latedef: true,
				newcap: true,
				noarg: true,
				sub: true,
				undef: true,
				eqnull: true,
				browser: true,
				expr: true,
				globals: {
					head: false,
					module: false,
					console: false,
					unescape: false,
					define: false,
					exports: false
				}
			},
			files: [ 'Gruntfile.js', 'js/reveal.js' ]
		},

		connect: {
			server: {
				options: {
					port: port,
					base: '.',
                    livereload: true,
                    open: true
				}
			}
		},

		zip: {
			'reveal-js-presentation.zip': [
				'index.html',
				'css/**',
				'js/**',
				'lib/**',
				'images/**',
				'plugin/**'
			]
		},

		watch: {
            options: {
                livereload: true
            },
			js: {
				files: [ 'Gruntfile.js', 'js/reveal.js' ],
				tasks: 'js'
			},
			theme: {
				files: [ 'css/theme/source/*.scss', 'css/theme/template/*.scss' ],
				tasks: 'css-themes'
			},
			css: {
				files: [ 'css/reveal.scss' ],
				tasks: 'css-core'
			},
            html: {
                files: [ 'index.html']
            }
		}

	});

	// Dependencies
	grunt.loadNpmTasks( 'grunt-contrib-qunit' );
	grunt.loadNpmTasks( 'grunt-contrib-jshint' );
	grunt.loadNpmTasks( 'grunt-contrib-cssmin' );
	grunt.loadNpmTasks( 'grunt-contrib-uglify' );
	grunt.loadNpmTasks( 'grunt-contrib-watch' );
	grunt.loadNpmTasks( 'grunt-sass' );
	grunt.loadNpmTasks( 'grunt-contrib-connect' );
	grunt.loadNpmTasks( 'grunt-autoprefixer' );
	grunt.loadNpmTasks( 'grunt-zip' );

	// Default task
	grunt.registerTask( 'default', [ 'css', 'js' ] );

	// JS task
	grunt.registerTask( 'js', [ 'jshint', 'uglify', 'qunit' ] );

	// Theme CSS
	grunt.registerTask( 'css-themes', [ 'sass:themes' ] );

	// Core framework CSS
	grunt.registerTask( 'css-core', [ 'sass:core', 'autoprefixer', 'cssmin' ] );

	// All CSS
	grunt.registerTask( 'css', [ 'sass', 'autoprefixer', 'cssmin' ] );

	// Package presentation to archive
	grunt.registerTask( 'package', [ 'default', 'zip' ] );

	// Serve presentation locally
	grunt.registerTask( 'serve', [ 'connect', 'watch' ] );

	// Run tests
	grunt.registerTask( 'test', [ 'jshint', 'qunit' ] );

};
<|endoftext|>


<commit_before>/* gulpfile.js - https://github.com/wearefractal/gulp */

var gulp = require('gulp');
var gutil = require('gulp-util');
var coffee = require('gulp-coffee');

var path = require('path');
var fs = require('fs');

var srcCoffeeDir = './coffee/';
var destDir = './src/';

// Emulate coffee -b -w -c -o ./src/ ./coffee
var gulpCoffee = function(coffeeFile) {

    // Mirror srcCoffeeDir dir structure to destDir
    //
    // From: srcCoffeeDir/[intermediate_dirs]/coffeeFile
    // To: destDir/[intermediate_dirs]/coffeeFile

    // __dirname/srcCoffeeDir/
    var normSrc = path.normalize(__dirname + '/' + srcCoffeeDir + '/');

    // __dirname/srcCoffeeDir/[intermediate_dirs]/coffeeFile
    var intermediate_dirs = path.relative(normSrc, path.dirname(coffeeFile));

    var normDestPath = path.normalize(destDir + '/' + intermediate_dirs + '/');
    var finalDestFilePath;

    gulp.src(coffeeFile)
        .pipe(coffee({bare: true}))
            .on('error', gutil.log)
            // Trigger system bell
            .on('error', gutil.beep)

        // Note: gulp.dest uses mkdirp.
        .pipe(gulp.dest(normDestPath))
            .on('data', function(file) {
                finalDestFilePath = path.normalize(normDestPath + '/' + path.basename(file.path));
            })
            .on('end', function() {

                var from = path.relative(__dirname, coffeeFile);
                var to = path.relative(__dirname, finalDestFilePath);

                gutil.log("Compiled '" + from + "' to '" + to + "'");

            });
    return;

}

// The default task (called when you run `gulp`)
gulp.task('default', function() {

    var target = path.normalize(srcCoffeeDir + '/**/*.coffee');

    // Process all coffee files.
    gulp.src(target)
        .on('data', function(file) {
            gulpCoffee(file.path);
        });

    // Watch coffeescript files and compile them if they change
    gulp.watch(target, function(event) {
        gulpCoffee(event.path);
    });

});

gulp.task('build', function() {

    // Future...
});

gulp.task('requirejs', function() {

    // Future...
});
<commit_msg>gulp crashes when you rename file(s) during watch task<commit_after>/* gulpfile.js - https://github.com/wearefractal/gulp */

var gulp = require('gulp');
var gutil = require('gulp-util');
var coffee = require('gulp-coffee');

var path = require('path');
var fs = require('fs');

var srcCoffeeDir = './coffee/';
var destDir = './src/';

// Emulate coffee -b -w -c -o ./src/ ./coffee
var gulpCoffee = function(coffeeFile) {

    // Mirror srcCoffeeDir dir structure to destDir
    //
    // From: srcCoffeeDir/[intermediate_dirs]/coffeeFile
    // To: destDir/[intermediate_dirs]/coffeeFile

    // __dirname/srcCoffeeDir/
    var normSrc = path.normalize(__dirname + '/' + srcCoffeeDir + '/');

    // __dirname/srcCoffeeDir/[intermediate_dirs]/coffeeFile
    var intermediate_dirs = path.relative(normSrc, path.dirname(coffeeFile));

    var normDestPath = path.normalize(destDir + '/' + intermediate_dirs + '/');
    var finalDestFilePath;

    gulp.src(coffeeFile)
        .pipe(coffee({bare: true}))
            .on('error', gutil.log)
            // Trigger system bell
            .on('error', gutil.beep)

        // Note: gulp.dest uses mkdirp.
        .pipe(gulp.dest(normDestPath))
            .on('data', function(file) {
                finalDestFilePath = path.normalize(normDestPath + '/' + path.basename(file.path));
            })
            .on('end', function() {

                var from = path.relative(__dirname, coffeeFile);
                var to = finalDestFilePath && path.relative(__dirname, finalDestFilePath);

                gutil.log("Compiled '" + from + "' to '" + to + "'");

            });
    return;

}

// The default task (called when you run `gulp`)
gulp.task('default', function() {

    var target = path.normalize(srcCoffeeDir + '/**/*.coffee');

    // Process all coffee files.
    gulp.src(target)
        .on('data', function(file) {
            gulpCoffee(file.path);
        });

    // Watch coffeescript files and compile them if they change
    gulp.watch(target, function(event) {
        gulpCoffee(event.path);
    });

});

gulp.task('build', function() {

    // Future...
});

gulp.task('requirejs', function() {

    // Future...
});
<|endoftext|>


<commit_before>var push = [].push

function Delta (callback) {
    if (!(this instanceof Delta)) {
        return new Delta(callback)
    }
    this._callback = callback
    this._results = []
    this._waiting = 0
    this._listeners = []
    this._completed = false
    this._canceled = 0
    this._instance = INSTANCE++
}

Delta.prototype.ee = function (ee) {
    return new Constructor(this, ee)
}

Delta.prototype._unlisten = function () {
    this._listeners.forEach(function (listener) {
        unlisten(listener, this)
    }, this)
    this._listeners.length = 0
}

Delta.prototype.off = function (ee, name, f) {
    var listeners = this._listeners, i = 0, I = listeners.length, listener
    while (i < I) {
        listener = listeners[i]
        if (
            ee === listener.ee &&
            (!name || name == listener.name) &&
            (!f || f === listener.f)
        ) {
            if (listener.action === get && !--this._waiting) {
                this._done()
                break
            }
            unlisten(listener, this)
            listeners.splice(i, 1)
            I--
        } else {
            i++
        }
    }
}

Delta.prototype.cancel = function (vargs) {
    if (!this._completed) {
        this._completed = true
        this._canceled++
        this._unlisten()
        this._callback.apply(null, vargs)
    }
}

function unlisten (listener, delta) {
    listener.f = null
    listener.ee.removeListener(listener.name, listener.listener)
//    listener.heap.push(listener)
}

Delta.prototype._rescue = function (error, ee) {
    error.ee = ee
    this._unlisten()
    this._callback.call(null, error)
}

Delta.prototype._done = function () {
    var vargs = []
    for (var i = 0, I = this._results.length; i < I; i++) {
        push.apply(vargs, this._results[i])
    }
    if (vargs.length) {
        vargs.unshift(null)
    }
    this._unlisten()
    this._callback.apply(null, vargs)
    this._completed = true
}

var INSTANCE = 0

function Constructor (delta, ee) {
    var rescuer = {
        instance: delta._instance,
        delta: delta,
        ee: ee,
        name: 'error',
        listener: function (error) {
            rescuer.delta._rescue(error, rescuer.ee)
        }
    }

    delta._listeners.push(rescuer)

    ee.on('error', rescuer.listener)

    this._delta = delta
    this._ee = ee
}

function gather (vargs) {
    push.apply(this.delta._results[this.index][0], vargs)
}

function get (vargs) {
    push.apply(this.delta._results[this.index], vargs)
    this.delta.off(this.ee, this.name)
}

function invoke (vargs) {
    try {
        this.f.apply(null, vargs)
    } catch (error) {
        this.delta._rescue(error)
    }
}

Constructor.prototype.on = function (name, object) {
    var listener = {
        instance: this._delta._instance,
        delta: this._delta,
        ee: this._ee,
        name: name,
        action: null,
        listening: true,
        index: 0,
        f: null,
        listener: function () {
            var vargs = new Array
            for (var i = 0, I = arguments.length; i < I; i++) {
                vargs[i] = arguments[i]
            }
            listener.action(vargs)
        }
    }

    if (Array.isArray(object)) {
        this._delta._results.push([[]])
        listener.index = this._delta._results.length - 1
        listener.action = gather
    } else if (typeof object == 'function') {
        listener.action = invoke
        listener.f = object
    } else {
        this._delta._results.push([])
        this._delta._waiting++
        listener.index = this._delta._results.length - 1
        listener.action = get
    }

    this._delta._listeners.push(listener)
    this._ee.on(name, listener.listener)

    return this
}

Constructor.prototype.ee = function (ee) {
    return new Constructor(this._delta, ee)
}

Constructor.prototype.cancel = function (vargs) {
    this._delta.cancel(vargs)
}

module.exports = Delta
<commit_msg>Remove unused property.<commit_after>var push = [].push

function Delta (callback) {
    if (!(this instanceof Delta)) {
        return new Delta(callback)
    }
    this._callback = callback
    this._results = []
    this._waiting = 0
    this._listeners = []
    this._completed = false
    this._canceled = 0
    this._instance = INSTANCE++
}

Delta.prototype.ee = function (ee) {
    return new Constructor(this, ee)
}

Delta.prototype._unlisten = function () {
    this._listeners.forEach(function (listener) {
        unlisten(listener, this)
    }, this)
    this._listeners.length = 0
}

Delta.prototype.off = function (ee, name, f) {
    var listeners = this._listeners, i = 0, I = listeners.length, listener
    while (i < I) {
        listener = listeners[i]
        if (
            ee === listener.ee &&
            (!name || name == listener.name) &&
            (!f || f === listener.f)
        ) {
            if (listener.action === get && !--this._waiting) {
                this._done()
                break
            }
            unlisten(listener, this)
            listeners.splice(i, 1)
            I--
        } else {
            i++
        }
    }
}

Delta.prototype.cancel = function (vargs) {
    if (!this._completed) {
        this._completed = true
        this._canceled++
        this._unlisten()
        this._callback.apply(null, vargs)
    }
}

function unlisten (listener, delta) {
    listener.f = null
    listener.ee.removeListener(listener.name, listener.listener)
}

Delta.prototype._rescue = function (error, ee) {
    error.ee = ee
    this._unlisten()
    this._callback.call(null, error)
}

Delta.prototype._done = function () {
    var vargs = []
    for (var i = 0, I = this._results.length; i < I; i++) {
        push.apply(vargs, this._results[i])
    }
    if (vargs.length) {
        vargs.unshift(null)
    }
    this._unlisten()
    this._callback.apply(null, vargs)
    this._completed = true
}

var INSTANCE = 0

function Constructor (delta, ee) {
    var rescuer = {
        instance: delta._instance,
        delta: delta,
        ee: ee,
        name: 'error',
        listener: function (error) {
            rescuer.delta._rescue(error, rescuer.ee)
        }
    }

    delta._listeners.push(rescuer)

    ee.on('error', rescuer.listener)

    this._delta = delta
    this._ee = ee
}

function gather (vargs) {
    push.apply(this.delta._results[this.index][0], vargs)
}

function get (vargs) {
    push.apply(this.delta._results[this.index], vargs)
    this.delta.off(this.ee, this.name)
}

function invoke (vargs) {
    try {
        this.f.apply(null, vargs)
    } catch (error) {
        this.delta._rescue(error)
    }
}

Constructor.prototype.on = function (name, object) {
    var listener = {
        instance: this._delta._instance,
        delta: this._delta,
        ee: this._ee,
        name: name,
        action: null,
        index: 0,
        f: null,
        listener: function () {
            var vargs = new Array
            for (var i = 0, I = arguments.length; i < I; i++) {
                vargs[i] = arguments[i]
            }
            listener.action(vargs)
        }
    }

    if (Array.isArray(object)) {
        this._delta._results.push([[]])
        listener.index = this._delta._results.length - 1
        listener.action = gather
    } else if (typeof object == 'function') {
        listener.action = invoke
        listener.f = object
    } else {
        this._delta._results.push([])
        this._delta._waiting++
        listener.index = this._delta._results.length - 1
        listener.action = get
    }

    this._delta._listeners.push(listener)
    this._ee.on(name, listener.listener)

    return this
}

Constructor.prototype.ee = function (ee) {
    return new Constructor(this._delta, ee)
}

Constructor.prototype.cancel = function (vargs) {
    this._delta.cancel(vargs)
}

module.exports = Delta
<|endoftext|>


<commit_before>module.exports = function(grunt) {

  // Update this variable if you don't want or can't serve on localhost
  var hostname = 'localhost';

  var PORT = {
    PROD : 9001,
    DEV : 9901,
    TEST : 9991
  };

  // create a version based on the build timestamp
  var dateFormat = require('dateformat');
  var version = '-' + dateFormat(new Date(), "yyyy-mm-dd-hh-MM");

  /**
   * Helper to prefix all strings in provided array with the provided path
   */
  var prefixPaths = function (paths, prefix) {
    return paths.map(function (path) {
      return prefix + path;
    });
  };

  // get the list of scripts paths to include
  var scriptPaths = require('./src/piskel-script-list.js').scripts;
  var piskelScripts = prefixPaths(scriptPaths, "src/").filter(function (path) {
    return path.indexOf('devtools') === -1;
  });

  // get the list of styles paths to include
  var stylePaths = require('./src/piskel-style-list.js').styles;
  var piskelStyles = prefixPaths(stylePaths, "src/");

  var casperTestPaths = require('./test/casperjs/TestSuite.js').tests;
  var casperTests = prefixPaths(casperTestPaths, "test/casperjs/");

  var getConnectConfig = function (base, port, host) {
    if (typeof base === 'string') {
      base = [base];
    }

    return {
      options: {
        port: port,
        hostname : host,
        base: base
      }
    };
  };

  // load all grunt tasks
  require('load-grunt-tasks')(grunt);

  grunt.initConfig({
    clean: {
      all: ['dest', 'src/img/icons.png', 'src/css/icons.css'],
      prod: ['dest/prod', 'dest/tmp'],
      desktop: ['dest/desktop', 'dest/tmp'],
      dev: ['dest/dev', 'dest/tmp']
    },

    /**
     * STYLE CHECKS
     */

    leadingIndent : {
      options: {
        indentation : "spaces"
      },
      css : ['src/css/**/*.css']
    },

    jscs : {
      options : {
        "config": ".jscsrc",
        "maximumLineLength": 120,
        "requireCamelCaseOrUpperCaseIdentifiers": "ignoreProperties",
        "validateQuoteMarks": { "mark": "'", "escape": true },
        "disallowMultipleVarDecl": "exceptUndefined",
        "disallowSpacesInAnonymousFunctionExpression": null
      },
      js : [ 'src/js/**/*.js' , '!src/js/**/lib/**/*.js' ]
    },

    jshint: {
      options: {
        undef : true,
        latedef : true,
        browser : true,
        trailing : true,
        curly : true,
        globals : {'$':true, 'jQuery' : true, 'pskl':true, 'Events':true, 'Constants':true, 'console' : true, 'module':true, 'require':true, 'Q':true}
      },
      files: [
        'Gruntfile.js',
        'package.json',
        'src/js/**/*.js',
        '!src/js/**/lib/**/*.js' // Exclude lib folder (note the leading !)
      ]
    },

    /**
     * SERVERS, BROWSER LAUNCHERS
     */

    connect: {
      prod: getConnectConfig('dest/prod', PORT.PROD, hostname),
      test: getConnectConfig(['dest/dev', 'test'], PORT.TEST, hostname),
      dev: getConnectConfig(['dest/dev', 'test'], PORT.DEV, hostname)
    },

    open : {
      prod : {
        path : 'http://' + hostname + ':' + PORT.PROD + '/'
      },
      dev : {
        path : 'http://' + hostname + ':' + PORT.DEV + '/?debug'
      }
    },

    watch: {
      prod: {
        files: ['src/**/*.*'],
        tasks: ['build'],
        options: {
          spawn: false
        }
      },
      dev: {
        files: ['src/**/*.*'],
        tasks: ['build-dev'],
        options: {
          spawn: false
        }
      }
    },

    /**
     * BUILD STEPS
     */

    sprite:{
      all : {
        src: 'src/img/icons/**/*.png',
        retinaSrcFilter: 'src/img/icons/**/*@2x.png',
        dest: 'src/img/icons.png',
        retinaDest: 'src/img/icons@2x.png',
        destCss: 'src/css/icons.css'
      }
    },

    concat : {
      js : {
        options : {
          separator : ';'
        },
        src : piskelScripts,
        dest : 'dest/prod/js/piskel-packaged' + version + '.js'
      },
      css : {
        src : piskelStyles,
        dest : 'dest/prod/css/piskel-style-packaged' + version + '.css'
      }
    },

    uglify : {
      options : {
        mangle : true
      },
      js : {
        files : {
          'dest/tmp/js/piskel-packaged-min.js' : ['dest/prod/js/piskel-packaged' + version + '.js']
        }
      }
    },

    includereplace: {
      all: {
        src: 'src/index.html',
        dest: 'dest/tmp/index.html',
        options : {
          globals : {
            'version' : version
          }
        }
      }
    },

    replace: {
      // main-partial.html is used when embedded in piskelapp.com
      mainPartial: {
        options: {
          patterns: [{
              match: /^(.|[\r\n])*<!--body-main-start-->/,
              replacement: "{% raw %}",
              description : "Remove everything before body-main-start comment"
            },{
              match: /<!--body-main-end-->(.|[\r\n])*$/,
              replacement: "{% endraw %}",
              description : "Remove everything after body-main-end comment"
            },{
              match: /([\r\n])  /g,
              replacement: "$1",
              description : "Decrease indentation by one"
            }
          ]
        },
        files: [
          // src/index.html should already have been moved by the includereplace task
          {src: ['dest/tmp/index.html'], dest: 'dest/prod/piskelapp-partials/main-partial.html'}
        ]
      },
      // remove the fake header from the desktop build
      desktop: {
        options: {
          patterns: [{
              match: /<!--standalone-start-->(?:.|[\r\n])*<!--standalone-end-->/,
              replacement: "",
              description : "Remove everything between standalone-start & standalone-end"
            }
          ]
        },
        files: [
          {src: ['dest/prod/index.html'], dest: 'dest/prod/index.html'}
        ]
      }
    },

    copy: {
      prod: {
        files: [
          // dest/js/piskel-packaged-min.js should have been created by the uglify task
          {src: ['dest/tmp/js/piskel-packaged-min.js'], dest: 'dest/prod/js/piskel-packaged-min' + version + '.js'},
          {src: ['dest/tmp/index.html'], dest: 'dest/prod/index.html'},
          {src: ['src/logo.png'], dest: 'dest/prod/logo.png'},
          {src: ['src/js/lib/gif/gif.ie.worker.js'], dest: 'dest/prod/js/lib/gif/gif.ie.worker.js'},
          {expand: true, src: ['img/**'], cwd: 'src/', dest: 'dest/prod/', filter: 'isFile'},
          {expand: true, src: ['css/fonts/**'], cwd: 'src/', dest: 'dest/prod/', filter: 'isFile'}
        ]
      },
      dev: {
        files: [
          // in dev copy everything to dest/dev
          {src: ['dest/tmp/index.html'], dest: 'dest/dev/index.html'},
          {src: ['src/piskel-script-list.js'], dest: 'dest/dev/piskel-script-list.js'},
          {src: ['src/piskel-style-list.js'], dest: 'dest/dev/piskel-style-list.js'},
          {expand: true, src: ['js/**'], cwd: 'src/', dest: 'dest/dev/', filter: 'isFile'},
          {expand: true, src: ['css/**'], cwd: 'src/', dest: 'dest/dev/', filter: 'isFile'},
          {expand: true, src: ['img/**'], cwd: 'src/', dest: 'dest/dev/', filter: 'isFile'},
        ]
      }
    },

    /**
     * TESTING
     */

    karma: {
      unit: {
        configFile: 'karma.conf.js'
      }
    },

    casperjs : {
      files : {
        src: casperTests
      },
      options : {
        casperjsOptions: [
          '--baseUrl=http://' + hostname + ':' + PORT.TEST,
          '--mode=?debug',
          '--verbose=false',
          '--log-level=info',
          '--print-command=false',
          '--print-file-paths=true',
        ]
      },
    },

    /**
     * DESKTOP BUILDS
     */

    nwjs: {
      windows : {
        options: {
          version : "0.15.4",
          build_dir: './dest/desktop/', // destination folder of releases.
          win: true,
          linux32: true,
          linux64: true
        },
        src: ['./dest/prod/**/*', "./package.json", "!./dest/desktop/"]
      },
      macos : {
        options: {
          osx64: true,
          version : "0.15.4",
          build_dir: './dest/desktop/'
        },
        src: ['./dest/prod/**/*', "./package.json", "!./dest/desktop/"]
      }
    }
  });

  // TEST TASKS
  // Run linting
  grunt.registerTask('lint', ['jscs:js', 'leadingIndent:css', 'jshint']);
  // Run unit-tests
  grunt.registerTask('unit-test', ['karma']);
  // Run linting, unit tests and drawing tests
  grunt.registerTask('test', ['lint', 'unit-test', 'build-dev', 'connect:test', 'casperjs']);

  // Run the tests, even if the linting fails
  grunt.registerTask('test-nolint', ['unit-test', 'build-dev', 'connect:test', 'casperjs']);
  // Used by optional precommit hook
  grunt.registerTask('precommit', ['test']);

  // BUILD TASKS
  grunt.registerTask('build-index.html', ['includereplace']);
  grunt.registerTask('merge-statics', ['concat:js', 'concat:css', 'uglify']);
  grunt.registerTask('build',  ['clean:prod', 'sprite', 'merge-statics', 'build-index.html', 'replace:mainPartial', 'copy:prod']);
  grunt.registerTask('build-dev',  ['clean:dev', 'sprite', 'build-index.html', 'copy:dev']);
  grunt.registerTask('desktop', ['clean:desktop', 'default', 'replace:desktop', 'nwjs:windows']);
  grunt.registerTask('desktop-mac', ['clean:desktop', 'default', 'replace:desktop', 'nwjs:macos']);

  // SERVER TASKS
  // Start webserver and watch for changes
  grunt.registerTask('serve', ['build', 'connect:prod', 'open:prod', 'watch:prod']);
  // Start webserver on src folder, in debug mode
  grunt.registerTask('play', ['build-dev', 'connect:dev', 'open:dev', 'watch:dev']);

  // ALIASES, kept for backward compatibility
  grunt.registerTask('serve-debug', ['play']);
  grunt.registerTask('serve-dev', ['play']);
  grunt.registerTask('test-travis', ['test']);
  grunt.registerTask('test-local', ['test']);

  // Default task
  grunt.registerTask('default', ['lint', 'build']);
};
<commit_msg>chore: update nwjs to 0.18.8<commit_after>module.exports = function(grunt) {

  // Update this variable if you don't want or can't serve on localhost
  var hostname = 'localhost';

  var PORT = {
    PROD : 9001,
    DEV : 9901,
    TEST : 9991
  };

  // create a version based on the build timestamp
  var dateFormat = require('dateformat');
  var version = '-' + dateFormat(new Date(), "yyyy-mm-dd-hh-MM");

  /**
   * Helper to prefix all strings in provided array with the provided path
   */
  var prefixPaths = function (paths, prefix) {
    return paths.map(function (path) {
      return prefix + path;
    });
  };

  // get the list of scripts paths to include
  var scriptPaths = require('./src/piskel-script-list.js').scripts;
  var piskelScripts = prefixPaths(scriptPaths, "src/").filter(function (path) {
    return path.indexOf('devtools') === -1;
  });

  // get the list of styles paths to include
  var stylePaths = require('./src/piskel-style-list.js').styles;
  var piskelStyles = prefixPaths(stylePaths, "src/");

  var casperTestPaths = require('./test/casperjs/TestSuite.js').tests;
  var casperTests = prefixPaths(casperTestPaths, "test/casperjs/");

  var getConnectConfig = function (base, port, host) {
    if (typeof base === 'string') {
      base = [base];
    }

    return {
      options: {
        port: port,
        hostname : host,
        base: base
      }
    };
  };

  // load all grunt tasks
  require('load-grunt-tasks')(grunt);

  grunt.initConfig({
    clean: {
      all: ['dest', 'src/img/icons.png', 'src/css/icons.css'],
      prod: ['dest/prod', 'dest/tmp'],
      desktop: ['dest/desktop', 'dest/tmp'],
      dev: ['dest/dev', 'dest/tmp']
    },

    /**
     * STYLE CHECKS
     */

    leadingIndent : {
      options: {
        indentation : "spaces"
      },
      css : ['src/css/**/*.css']
    },

    jscs : {
      options : {
        "config": ".jscsrc",
        "maximumLineLength": 120,
        "requireCamelCaseOrUpperCaseIdentifiers": "ignoreProperties",
        "validateQuoteMarks": { "mark": "'", "escape": true },
        "disallowMultipleVarDecl": "exceptUndefined",
        "disallowSpacesInAnonymousFunctionExpression": null
      },
      js : [ 'src/js/**/*.js' , '!src/js/**/lib/**/*.js' ]
    },

    jshint: {
      options: {
        undef : true,
        latedef : true,
        browser : true,
        trailing : true,
        curly : true,
        globals : {'$':true, 'jQuery' : true, 'pskl':true, 'Events':true, 'Constants':true, 'console' : true, 'module':true, 'require':true, 'Q':true}
      },
      files: [
        'Gruntfile.js',
        'package.json',
        'src/js/**/*.js',
        '!src/js/**/lib/**/*.js' // Exclude lib folder (note the leading !)
      ]
    },

    /**
     * SERVERS, BROWSER LAUNCHERS
     */

    connect: {
      prod: getConnectConfig('dest/prod', PORT.PROD, hostname),
      test: getConnectConfig(['dest/dev', 'test'], PORT.TEST, hostname),
      dev: getConnectConfig(['dest/dev', 'test'], PORT.DEV, hostname)
    },

    open : {
      prod : {
        path : 'http://' + hostname + ':' + PORT.PROD + '/'
      },
      dev : {
        path : 'http://' + hostname + ':' + PORT.DEV + '/?debug'
      }
    },

    watch: {
      prod: {
        files: ['src/**/*.*'],
        tasks: ['build'],
        options: {
          spawn: false
        }
      },
      dev: {
        files: ['src/**/*.*'],
        tasks: ['build-dev'],
        options: {
          spawn: false
        }
      }
    },

    /**
     * BUILD STEPS
     */

    sprite:{
      all : {
        src: 'src/img/icons/**/*.png',
        retinaSrcFilter: 'src/img/icons/**/*@2x.png',
        dest: 'src/img/icons.png',
        retinaDest: 'src/img/icons@2x.png',
        destCss: 'src/css/icons.css'
      }
    },

    concat : {
      js : {
        options : {
          separator : ';'
        },
        src : piskelScripts,
        dest : 'dest/prod/js/piskel-packaged' + version + '.js'
      },
      css : {
        src : piskelStyles,
        dest : 'dest/prod/css/piskel-style-packaged' + version + '.css'
      }
    },

    uglify : {
      options : {
        mangle : true
      },
      js : {
        files : {
          'dest/tmp/js/piskel-packaged-min.js' : ['dest/prod/js/piskel-packaged' + version + '.js']
        }
      }
    },

    includereplace: {
      all: {
        src: 'src/index.html',
        dest: 'dest/tmp/index.html',
        options : {
          globals : {
            'version' : version
          }
        }
      }
    },

    replace: {
      // main-partial.html is used when embedded in piskelapp.com
      mainPartial: {
        options: {
          patterns: [{
              match: /^(.|[\r\n])*<!--body-main-start-->/,
              replacement: "{% raw %}",
              description : "Remove everything before body-main-start comment"
            },{
              match: /<!--body-main-end-->(.|[\r\n])*$/,
              replacement: "{% endraw %}",
              description : "Remove everything after body-main-end comment"
            },{
              match: /([\r\n])  /g,
              replacement: "$1",
              description : "Decrease indentation by one"
            }
          ]
        },
        files: [
          // src/index.html should already have been moved by the includereplace task
          {src: ['dest/tmp/index.html'], dest: 'dest/prod/piskelapp-partials/main-partial.html'}
        ]
      },
      // remove the fake header from the desktop build
      desktop: {
        options: {
          patterns: [{
              match: /<!--standalone-start-->(?:.|[\r\n])*<!--standalone-end-->/,
              replacement: "",
              description : "Remove everything between standalone-start & standalone-end"
            }
          ]
        },
        files: [
          {src: ['dest/prod/index.html'], dest: 'dest/prod/index.html'}
        ]
      }
    },

    copy: {
      prod: {
        files: [
          // dest/js/piskel-packaged-min.js should have been created by the uglify task
          {src: ['dest/tmp/js/piskel-packaged-min.js'], dest: 'dest/prod/js/piskel-packaged-min' + version + '.js'},
          {src: ['dest/tmp/index.html'], dest: 'dest/prod/index.html'},
          {src: ['src/logo.png'], dest: 'dest/prod/logo.png'},
          {src: ['src/js/lib/gif/gif.ie.worker.js'], dest: 'dest/prod/js/lib/gif/gif.ie.worker.js'},
          {expand: true, src: ['img/**'], cwd: 'src/', dest: 'dest/prod/', filter: 'isFile'},
          {expand: true, src: ['css/fonts/**'], cwd: 'src/', dest: 'dest/prod/', filter: 'isFile'}
        ]
      },
      dev: {
        files: [
          // in dev copy everything to dest/dev
          {src: ['dest/tmp/index.html'], dest: 'dest/dev/index.html'},
          {src: ['src/piskel-script-list.js'], dest: 'dest/dev/piskel-script-list.js'},
          {src: ['src/piskel-style-list.js'], dest: 'dest/dev/piskel-style-list.js'},
          {expand: true, src: ['js/**'], cwd: 'src/', dest: 'dest/dev/', filter: 'isFile'},
          {expand: true, src: ['css/**'], cwd: 'src/', dest: 'dest/dev/', filter: 'isFile'},
          {expand: true, src: ['img/**'], cwd: 'src/', dest: 'dest/dev/', filter: 'isFile'},
        ]
      }
    },

    /**
     * TESTING
     */

    karma: {
      unit: {
        configFile: 'karma.conf.js'
      }
    },

    casperjs : {
      files : {
        src: casperTests
      },
      options : {
        casperjsOptions: [
          '--baseUrl=http://' + hostname + ':' + PORT.TEST,
          '--mode=?debug',
          '--verbose=false',
          '--log-level=info',
          '--print-command=false',
          '--print-file-paths=true',
        ]
      },
    },

    /**
     * DESKTOP BUILDS
     */

    nwjs: {
      windows : {
        options: {
          version : "0.18.8",
          build_dir: './dest/desktop/', // destination folder of releases.
          win: true,
          linux32: true,
          linux64: true
        },
        src: ['./dest/prod/**/*', "./package.json", "!./dest/desktop/"]
      },
      macos : {
        options: {
          osx64: true,
          version : "0.18.8",
          build_dir: './dest/desktop/'
        },
        src: ['./dest/prod/**/*', "./package.json", "!./dest/desktop/"]
      }
    }
  });

  // TEST TASKS
  // Run linting
  grunt.registerTask('lint', ['jscs:js', 'leadingIndent:css', 'jshint']);
  // Run unit-tests
  grunt.registerTask('unit-test', ['karma']);
  // Run linting, unit tests and drawing tests
  grunt.registerTask('test', ['lint', 'unit-test', 'build-dev', 'connect:test', 'casperjs']);

  // Run the tests, even if the linting fails
  grunt.registerTask('test-nolint', ['unit-test', 'build-dev', 'connect:test', 'casperjs']);
  // Used by optional precommit hook
  grunt.registerTask('precommit', ['test']);

  // BUILD TASKS
  grunt.registerTask('build-index.html', ['includereplace']);
  grunt.registerTask('merge-statics', ['concat:js', 'concat:css', 'uglify']);
  grunt.registerTask('build',  ['clean:prod', 'sprite', 'merge-statics', 'build-index.html', 'replace:mainPartial', 'copy:prod']);
  grunt.registerTask('build-dev',  ['clean:dev', 'sprite', 'build-index.html', 'copy:dev']);
  grunt.registerTask('desktop', ['clean:desktop', 'default', 'replace:desktop', 'nwjs:windows']);
  grunt.registerTask('desktop-mac', ['clean:desktop', 'default', 'replace:desktop', 'nwjs:macos']);

  // SERVER TASKS
  // Start webserver and watch for changes
  grunt.registerTask('serve', ['build', 'connect:prod', 'open:prod', 'watch:prod']);
  // Start webserver on src folder, in debug mode
  grunt.registerTask('play', ['build-dev', 'connect:dev', 'open:dev', 'watch:dev']);

  // ALIASES, kept for backward compatibility
  grunt.registerTask('serve-debug', ['play']);
  grunt.registerTask('serve-dev', ['play']);
  grunt.registerTask('test-travis', ['test']);
  grunt.registerTask('test-local', ['test']);

  // Default task
  grunt.registerTask('default', ['lint', 'build']);
};
<|endoftext|>


<commit_before>var gulp = require('gulp');
var clean = require('gulp-clean');
var ts = require('gulp-typescript');
var sourcemaps = require('gulp-sourcemaps');
var merge = require('merge2');
var replace = require('gulp-replace');
var path = require('path');
var webpack = require('webpack');
var webpackStream = require('webpack-stream');

var tsProject = ts.createProject('tsconfig.json');

gulp.task('default', ['build']);

gulp.task('clean', cleanTask);
gulp.task('cleanBundles', cleanBundlesTask);

gulp.task('tsc', ['clean'], tscTask);
gulp.task('tscDev', ['clean'], tscDevTask);

gulp.task('build', ['tsc'], barrelTask);
gulp.task('buildDev', ['tscDev'], barrelTask);

gulp.task('webpack', webpackTask.bind(null, false));
gulp.task('webpack-min', webpackTask.bind(null, true));

function cleanTask() {
    return merge([
        gulp.src('dist/index.*', { read: false }).pipe(clean()),
        gulp.src('dist/src', { read: false }).pipe(clean())
    ]);
}

function cleanBundlesTask() {
    return gulp.src('dist/bundles', { read: false }).pipe(clean());
}

function tscTask() {
    var tsResult = gulp.src("src/**/*.ts")
        .pipe(tsProject());

    return merge([ // Merge the two output streams, so this task is finished when the IO of both operations is done.
        tsResult.dts.pipe(gulp.dest('dist/src')),
        tsResult.js.pipe(gulp.dest('dist/src'))
    ]);
};

function tscDevTask() {
    var tsResult = gulp.src("src/**/*.ts")
        .pipe(sourcemaps.init())
        .pipe(tsProject());

    return merge([ // Merge the two output streams, so this task is finished when the IO of both operations is done.
        tsResult.dts.pipe(gulp.dest('dist/src')),
        tsResult.js
            // .pipe(sourcemaps.write('.'))
            .pipe(sourcemaps.write()) // inlined maps
            .pipe(gulp.dest('dist/src'))
    ]);
};

function barrelTask() {
    return gulp.src(['dist/src/index.d.ts', 'dist/src/index.js'])
    .pipe(replace('./ra-ng', './src/ra-ng'))
    .pipe(gulp.dest(function(file){ return 'dist/'}));
}

function webpackTask(minify) {

    var plugins = [];
    plugins.push(new webpack.IgnorePlugin(/@angular/));
    plugins.push(new webpack.IgnorePlugin(/cachefactory/));
    plugins.push(new webpack.IgnorePlugin(/crypto-js/));
    plugins.push(new webpack.IgnorePlugin(/lodash/));
    plugins.push(new webpack.IgnorePlugin(/log4javascript/));
    plugins.push(new webpack.IgnorePlugin(/ng2-translate/));
    plugins.push(new webpack.IgnorePlugin(/primeng/));
    plugins.push(new webpack.IgnorePlugin(/rxjs/));

    if (minify) {
        plugins.push(new webpack.optimize.UglifyJsPlugin({compress: {warnings: false}}));
    }

    var mainFile = './dist/index.js';

    var fileName = 'ra-ng.umd';
    fileName += minify ? '.min' : '';
    fileName += '.js';

    return gulp.src('src/entry.js')
        .pipe(webpackStream({
            entry: {
                main: mainFile
            },
            output: {
                path: path.join(__dirname, "dist/bundles"),
                filename: fileName,
                library: ["raNG"],
                libraryTarget: "umd"
            },
            //devtool: 'inline-source-map',
            plugins: plugins
        }))
        .pipe(gulp.dest('./dist/bundles/'));
}<commit_msg>External dependencies are defined using the "externals" configuration property<commit_after>var gulp = require('gulp');
var clean = require('gulp-clean');
var ts = require('gulp-typescript');
var sourcemaps = require('gulp-sourcemaps');
var merge = require('merge2');
var replace = require('gulp-replace');
var path = require('path');
var webpack = require('webpack');
var webpackStream = require('webpack-stream');

var tsProject = ts.createProject('tsconfig.json');

gulp.task('default', ['build']);

gulp.task('clean', cleanTask);
gulp.task('cleanBundles', cleanBundlesTask);

gulp.task('tsc', ['clean'], tscTask);
gulp.task('tscDev', ['clean'], tscDevTask);

gulp.task('build', ['tsc'], barrelTask);
gulp.task('buildDev', ['tscDev'], barrelTask);

gulp.task('webpack', webpackTask.bind(null, false));
gulp.task('webpack-min', webpackTask.bind(null, true));

function cleanTask() {
    return merge([
        gulp.src('dist/index.*', { read: false }).pipe(clean()),
        gulp.src('dist/src', { read: false }).pipe(clean())
    ]);
}

function cleanBundlesTask() {
    return gulp.src('dist/bundles', { read: false }).pipe(clean());
}

function tscTask() {
    var tsResult = gulp.src("src/**/*.ts")
        .pipe(tsProject());

    return merge([ // Merge the two output streams, so this task is finished when the IO of both operations is done.
        tsResult.dts.pipe(gulp.dest('dist/src')),
        tsResult.js.pipe(gulp.dest('dist/src'))
    ]);
};

function tscDevTask() {
    var tsResult = gulp.src("src/**/*.ts")
        .pipe(sourcemaps.init())
        .pipe(tsProject());

    return merge([ // Merge the two output streams, so this task is finished when the IO of both operations is done.
        tsResult.dts.pipe(gulp.dest('dist/src')),
        tsResult.js
            // .pipe(sourcemaps.write('.'))
            .pipe(sourcemaps.write()) // inlined maps
            .pipe(gulp.dest('dist/src'))
    ]);
};

function barrelTask() {
    return gulp.src(['dist/src/index.d.ts', 'dist/src/index.js'])
    .pipe(replace('./ra-ng', './src/ra-ng'))
    .pipe(gulp.dest(function(file){ return 'dist/'}));
}

function webpackTask(minify) {

    var plugins = [];
    if (minify) {
        plugins.push(new webpack.optimize.UglifyJsPlugin({compress: {warnings: false}}));
    }

    var mainFile = './dist/index.js';

    var fileName = 'ra-ng.umd';
    fileName += minify ? '.min' : '';
    fileName += '.js';

    return gulp.src('src/entry.js')
        .pipe(webpackStream({
            entry: {
                main: mainFile
            },
            output: {
                path: path.join(__dirname, "dist/bundles"),
                filename: fileName,
                library: ["raNG"],
                libraryTarget: "umd"
            },
            externals: [
                "@angular/common", "@angular/compiler", "@angular/core", "@angular/forms",
                "@angular/http", "@angular/platform-browser", "@angular/platform-browser-dynamic",
                "@angular/router",
                "cachefactory", "crypto-js", "lodash", "log4javascript", "ng2-translate/ng2-translate",
                "primeng/primeng", "rxjs/Rx"
            ],
            //devtool: 'inline-source-map',
            plugins: plugins
        }))
        .pipe(gulp.dest('./dist/bundles/'));
}<|endoftext|>


<commit_before>var vm = new Vue({
    el: '#app',
    data: {
        config: []
    },
    created: function () {
        // 注册 serviceWorker
        if (navigator.serviceWorker) {
            navigator.serviceWorker.register('/MOJOY_FEATURE/service-worker.js', {
                scope: '/'
            }).then(function (registration) {
                if (registration.installing) {
                    console.log('Service worker installing');
                } else if (registration.waiting) {
                    console.log('Service worker installed');
                } else if (registration.active) {
                    console.log('Service worker active');
                }
                // console.log('service worker 注册成功');
            }).catch(function (err) {
                console.log('servcie worker 注册失败', err)
            });
        }
        // 获取配置文件
        this.$http.get('./static/config/config.json').then((response) => {
            vm.config = response.body
            console.log(vm.config)
        }, (response) => {
            alert('魔借出了点小问题')
        });
    },
    methods: {
        toProPage: function (id, name) {
            if (!id && !name) return

            var u = navigator.userAgent;
            var isAndroid = u.indexOf('Android') > -1 || u.indexOf('Adr') > -1;
            var isiOS = !!u.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/);
            if (isAndroid && !isiOS) {
                alert('test：Android:' + (id ? ('物品 id：' + id) : '') + (name ? (',物品名称：' + name) : name))
                Android.search(name);
            } else if (isiOS && !isAndroid) {
                alert('test：ios:' + (id ? ('物品 id：' + id) : '') + (name ? (',物品名称：' + name) : name))
                if (id) {
                    window.NativeBridge('fetchMessage', {
                        'type': 1,
                        'id': id
                    });
                } else if (name) {
                    window.NativeBridge('fetchMessage', {
                        'type': 2,
                        'key': name
                    });
                } else {
                    console.log('Some Error')
                }
            } else {
                console.log('Some Error:Not Android or Ios')
            }
        }
    }
})<commit_msg>scope<commit_after>var vm = new Vue({
    el: '#app',
    data: {
        config: []
    },
    created: function () {
        // 注册 serviceWorker
        if (navigator.serviceWorker) {
            navigator.serviceWorker.register('/MOJOY_FEATURE/service-worker.js', {
                scope: '/MOJOY_FEATURE/'
            }).then(function (registration) {
                if (registration.installing) {
                    console.log('Service worker installing');
                } else if (registration.waiting) {
                    console.log('Service worker installed');
                } else if (registration.active) {
                    console.log('Service worker active');
                }
                // console.log('service worker 注册成功');
            }).catch(function (err) {
                console.log('servcie worker 注册失败', err)
            });
        }
        // 获取配置文件
        this.$http.get('./static/config/config.json').then((response) => {
            vm.config = response.body
            console.log(vm.config)
        }, (response) => {
            alert('魔借出了点小问题')
        });
    },
    methods: {
        toProPage: function (id, name) {
            if (!id && !name) return

            var u = navigator.userAgent;
            var isAndroid = u.indexOf('Android') > -1 || u.indexOf('Adr') > -1;
            var isiOS = !!u.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/);
            if (isAndroid && !isiOS) {
                alert('test：Android:' + (id ? ('物品 id：' + id) : '') + (name ? (',物品名称：' + name) : name))
                Android.search(name);
            } else if (isiOS && !isAndroid) {
                alert('test：ios:' + (id ? ('物品 id：' + id) : '') + (name ? (',物品名称：' + name) : name))
                if (id) {
                    window.NativeBridge('fetchMessage', {
                        'type': 1,
                        'id': id
                    });
                } else if (name) {
                    window.NativeBridge('fetchMessage', {
                        'type': 2,
                        'key': name
                    });
                } else {
                    console.log('Some Error')
                }
            } else {
                console.log('Some Error:Not Android or Ios')
            }
        }
    }
})<|endoftext|>