<commit_before>var net = require('net'),
    EventEmitter = require('events').EventEmitter,
    tcpEventify = require('../../utils/tcpEventify'),
    find = require('../find.js');

/** Creates a point to point mapper that routes every event to the other side of the channel
 * @param {string} port - The port where the local side of the channel will be created
 * @returns {object} map - The local map created
 */
module.exports = function (port) {
    var map = {},
        channelConnected = false;
        emitter = new EventEmitter(),
        serverSocket = {},
        clientSocket = {};

    var server = net.createServer(function (socket) {
        if (!channelConnected) {
            channelConnected = true;
            var eventedSocket = tcpEventify(socket);
            serverSocket = eventedSocket;
            eventedSocket.on('event', function (event) {
                emitter.emit(event.name, event.message);
            });
        }
    }).listen(port, function () {
        // console.log('Distributed channel listening on port', port);
    });

    map.connect = function connectChannel(options, onConnect) {
        find.distributed.channel(options, function (socket) {
            var eventedSocket = tcpEventify(socket);
            clientSocket = eventedSocket;
            eventedSocket.on('event', function (event) {
                emitter.emit(event.name, event.message);
            });
            onConnect();
        });
    };
    map.emit = function (event, message) {
        if (clientSocket.send) {
            clientSocket.send(event, message);
        } else if (serverSocket.send) {
            serverSocket.send(event, message);
        }
    };
    map.on = function (event, callback) {
        emitter.on(event, callback);
    };

    return map;
};<commit_msg>Removed the call to #tcpEventify and process the target connection options.<commit_after>var net = require('net'),
    EventEmitter = require('events').EventEmitter,
    tcpEventify = require('../../utils/tcpEventify'),
    find = require('../find.js');

/** Creates a point to point mapper that routes every event to the other side of the channel
 * @param {string} port - The port where the local side of the channel will be created
 * @returns {object} map - The local map created
 */
module.exports = function (port) {
    var map = {},
        serverConnected = false,
        emitter = new EventEmitter(),
        serverSocket = {},
        clientSocket = {};

    var server = net.createServer(function (socket) {
        if (!serverConnected) {
            channelConnected = true;
            var eventedSocket = tcpEventify(socket);
            serverSocket = eventedSocket;
            eventedSocket.on('event', function (event) {
                emitter.emit(event.name, event.message);
            });
        }
    }).listen(port, function () {
        // console.log('Distributed channel listening on port', port);
    });

    map.connect = function connectChannel(target, onConnect) {
        var parts = target.split(':'),
        options = {
            host: parts[0],
            port: parts[1]
        };

        find.distributed.channel(options, function (socket) {
            clientSocket = socket;
            socket.on('event', function (event) {
                emitter.emit(event.name, event.message);
            });
            if (typeof onConnect === 'function') {
                onConnect();
            }
        });
    };
    map.emit = function (event, message) {
        if (clientSocket.send) {
            clientSocket.send(event, message);
        } else if (serverSocket.send) {
            serverSocket.send(event, message);
        }
    };
    map.on = function (event, callback) {
        emitter.on(event, callback);
    };

    return map;
};<|endoftext|>


<commit_before>import gulp from "gulp";
import browserify from "browserify";
import watchify from "watchify";
import babelify from "babelify";
import source from "vinyl-source-stream";
import buffer from "vinyl-buffer";
import gutil from "gulp-util";
import plumber from "gulp-plumber";
import notify from "gulp-notify";
import sourcemaps from "gulp-sourcemaps";
import rename from "gulp-rename";
import eslint from "gulp-eslint";
import uglify from "gulp-uglify";
import del from "del";

const errorHandler = notify.onError("Error: <%= error.message %>");

// Make browserify bundle
function bundle(file, options, cb) {
    var base, bundler, watcher, opts;

    opts = options || {};

    opts.entries = "./" + file;
    opts.debug = typeof opts.debug === "boolean" ? opts.debug : true;

    if (bundle.watch) {
        opts.cache = {};
        opts.packageCache = {};
        opts.fullPaths = true;
    }

    bundler = browserify(opts);

    base = file.split(/[\\/]/).pop();

    if (bundle.watch) {
        watcher = watchify(bundler);

        cb(
            watcher
            .on("update", () => {
                gutil.log(`Starting '${gutil.colors.yellow(file)}'...`);

                cb(
                    watcher.bundle()
                    .on("error", errorHandler)
                    .pipe(source(base))
                    .pipe(buffer())
                );
            })
            .on("time", time => gutil.log(`Finished '${gutil.colors.yellow(file)}' after ${gutil.colors.magenta(time + " ms")}`))
            .bundle()
            .pipe(source(base))
            .pipe(buffer())
        );
    } else {
        cb(
            bundler.bundle()
            .on("error", function(error) {
                errorHandler(error);

                // End the stream to prevent gulp from crashing
                this.end();
            })
            .pipe(source(base))
            .pipe(buffer())
        );
    }
}

gulp.task("lint", () =>
    gulp.src("src/**/*.js")
    .pipe(plumber({ errorHandler }))
    .pipe(eslint())
    .pipe(eslint.format())
    .pipe(eslint.failOnError())
);

gulp.task("bundle", () =>
    bundle("src/app.js", {
        transform: [ babelify ]
    }, bundled => bundled
        .pipe(plumber({ errorHandler }))
        .pipe(sourcemaps.init({ loadMaps: true }))
        .pipe(gutil.env.production ? uglify() : gutil.noop())
        .pipe(rename({ suffix: ".min" }))
        .pipe(sourcemaps.write("."))
        .pipe(gulp.dest("dist"))
    )
);

gulp.task("scripts", [ "bundle" ]);

gulp.task("scripts:watch", () => {
    bundle.watch = true;

    gulp.start("scripts");

    gulp.watch("src/js/**/*.js", [ "lint" ]);
});

// Clean up generated files
gulp.task("clean", () => del("dist/"));

gulp.task("watch", [ "scripts:watch" ]);

// Build files
gulp.task("build", [ "scripts" ]);

// Default Task
gulp.task("default", [ "lint", "clean" ], () => gulp.start("build"));

<commit_msg>Fix watch<commit_after>import gulp from "gulp";
import browserify from "browserify";
import watchify from "watchify";
import babelify from "babelify";
import source from "vinyl-source-stream";
import buffer from "vinyl-buffer";
import gutil from "gulp-util";
import plumber from "gulp-plumber";
import notify from "gulp-notify";
import sourcemaps from "gulp-sourcemaps";
import rename from "gulp-rename";
import eslint from "gulp-eslint";
import uglify from "gulp-uglify";
import del from "del";

const errorHandler = notify.onError("Error: <%= error.message %>");

// Make browserify bundle
function bundle(file, options, cb) {
    var base, bundler, watcher, opts;

    opts = options || {};

    opts.entries = "./" + file;
    opts.debug = typeof opts.debug === "boolean" ? opts.debug : true;

    if (bundle.watch) {
        opts.cache = {};
        opts.packageCache = {};
        opts.fullPaths = true;
    }

    bundler = browserify(opts);

    base = file.split(/[\\/]/).pop();

    if (bundle.watch) {
        watcher = watchify(bundler);

        cb(
            watcher
            .on("update", () => {
                gutil.log(`Starting '${gutil.colors.yellow(file)}'...`);

                cb(
                    watcher.bundle()
                    .on("error", errorHandler)
                    .pipe(source(base))
                    .pipe(buffer())
                );
            })
            .on("time", time => gutil.log(`Finished '${gutil.colors.yellow(file)}' after ${gutil.colors.magenta(time + " ms")}`))
            .bundle()
            .pipe(source(base))
            .pipe(buffer())
        );
    } else {
        cb(
            bundler.bundle()
            .on("error", function(error) {
                errorHandler(error);

                // End the stream to prevent gulp from crashing
                this.end();
            })
            .pipe(source(base))
            .pipe(buffer())
        );
    }
}

gulp.task("lint", () =>
    gulp.src("src/**/*.js")
    .pipe(plumber({ errorHandler }))
    .pipe(eslint())
    .pipe(eslint.format())
    .pipe(eslint.failOnError())
);

gulp.task("bundle", () =>
    bundle("src/app.js", {
        transform: [ babelify ]
    }, bundled => bundled
        .pipe(plumber({ errorHandler }))
        .pipe(sourcemaps.init({ loadMaps: true }))
        .pipe(gutil.env.production ? uglify() : gutil.noop())
        .pipe(rename({ suffix: ".min" }))
        .pipe(sourcemaps.write("."))
        .pipe(gulp.dest("dist"))
    )
);

gulp.task("scripts", [ "bundle" ]);

gulp.task("scripts:watch", () => {
    bundle.watch = true;

    gulp.start("scripts");

    gulp.watch("src/**/*.js", [ "lint" ]);
});

// Clean up generated files
gulp.task("clean", () => del("dist/"));

gulp.task("watch", [ "scripts:watch" ]);

// Build files
gulp.task("build", [ "scripts" ]);

// Default Task
gulp.task("default", [ "lint", "clean" ], () => gulp.start("build"));

<|endoftext|>


<commit_before>import $ from 'jquery';
import _ from 'lodash';
import Promise from 'bluebird';
import '../../lib/jquery.selection';
import '../../lib/jquery.esarea';
import Ui from './ui';

let ui = new Ui();
window.ui = ui; // for debug

// TODO できればグローバルで定義しないほうがよさそう
let storedPost = { title: '', body: '', cursorPosition: 0, saved: false };

const loadPost = function() {
  let defaultPost = { title: '', body: '', cursorPosition: 0, saved: false };
  chrome.storage.sync.get(defaultPost, function(post) {
    storedPost = post;

    // TODO: この辺の処理を ui.loadPost() にまとめたい
    ui.toggle('save-button', 'disabled', post.saved);

    ui.title(post.title);
    ui.body(post.body);
    if (ui.title() != '') {
      // Move cursor at previous position
      ui.moveFocus('body', post.cursorPosition);
    }
  });
};

const getConfig = function() {
  return new Promise(function(resolve, reject) {
    let defaultConfig = { teamName: '', token: '', teamIcon: '', postId: '' };
    chrome.storage.sync.get(defaultConfig, function(config) {
      if (!config.teamName || !config.token) {
        ui.toggle('option-link', 'show', true);
        ui.teamName('Configuration failed');

        reject('Please configure options (\\( ˘⊖˘)/)');
      } else {
        ui.toggle('option-link', 'show', false);

        if (config.postId != '') {
          let link = `https://${config.teamName}.esa.io/posts/${config.postId}`;
          ui.savedPostLink(link);
        }

        ui.teamName(config.teamName);
        ui.teamIcon(config.teamIcon);

        resolve(config);
      }
    });
  });
};

const searchPost = function(config) {
  return new Promise(function(resolve, reject) {
    let title = ui.title();
    let category = '';

    if (hasCategory(title)) {
      category = /(.+)\/.+/.exec(title)[1];
      title = /.+\/(.+)/.exec(title)[1];
    }

    let q = `name:${title}`;
    if (category.length != 0) {
      q = `${q} category:${category}`;
    }

    $.ajax({
      type: 'GET',
      url: `https://api.esa.io/v1/teams/${config.teamName}/posts`,
      data: {
        q: q,
        access_token: config.token,
      },
    }).then(function(response) {
      let hitPost;
      // カテゴリ無しだけを検索する方法がわからなかったので別途絞込している
      if (category.length == 0) {
        hitPost = _.find(response.posts, { name: title, category: null });
      } else {
        // 1つしかない想定
        hitPost = response.posts[0];
      }

      // 記事があった場合は更新するためIDを保存する
      if (hitPost) {
        config.postId = hitPost.number;
      } else {
        config.postId = undefined;
      }
      chrome.storage.sync.set(config, function() {
        resolve(config);
      });
    }, reject);
  });
};

const savePost = function(config) {
  return new Promise(function(resolve, reject) {
    let type;
    let url = `https://api.esa.io/v1/teams/${config.teamName}/posts`;
    let title = ui.title();
    let body = ui.body();

    let post = {
      name: title,
      category: '',
      body_md: body,
      message: 'from tsuibami',
    };

    if (hasCategory(title)) {
      post['category'] = /(.+)\/.+/.exec(title)[1];
      post['name'] = /.+\/(.+)/.exec(title)[1];
    }

    let postId = config.postId;
    if (postId) {
      type = 'PATCH';
      url = url + '/' + postId;
    } else {
      type = 'POST';
    }

    $.ajax({
      type: type,
      url: url,
      data: {
        post: post,
        access_token: config.token,
      },
    }).then(resolve, reject);
  });
};

const storePostAsSaved = function(response) {
  return new Promise(function(resolve, reject) {
    ui.toggle('save-button', 'disabled', true);

    let newPostId = response.number;
    chrome.storage.sync.set({ saved: true, postId: newPostId }, function() {
      storedPost.saved = true;
      resolve(response);
    });
  });
};

const updatePostTitleDisplay = function(response) {
  // 保存したタイトルによっては末尾に "(2)" などの表記がesaによってつけられている可能性があるため、再度表示し直す
  return new Promise(function(resolve, reject) {
    chrome.storage.sync.set({ title: response.name }, function() {
      ui.title(response.full_name);
      resolve(response);
    });
  });
};

const clearPost = function(response) {
  if (!ui.checkedclear()) {
    return new Promise(function(resolve, reject) {
      ui.moveFocus('body');
      resolve(response);
    });
  }
  return new Promise(function(resolve, reject) {
    ui.title('');
    ui.body('');

    ui.toggle('save-button', 'disabled', true);

    storedPost = { title: '', body: '', cursorPosition: 0, saved: true };
    chrome.storage.sync.set(storedPost, function() {
      if (chrome.runtime.lastError) {
        reject(response);
      } else {
        resolve(response);
      }
    });
  });
};

const notifySaved = function(response) {
  return new Promise(function(resolve, reject) {
    let message;

    ui.savedPostLink(response.url);
    // 最初の保存の時だけメッセージを変える
    if (response.revision_number == 1) {
      message = 'created!';
    } else {
      message = 'updated!';
    }
    resolve(message);
  });
};

const hasCategory = function(title) {
  return /.+\/.+/.test(title);
};

const notifySuccess = function(msg) {
  showMessage(msg + ' (\\( ⁰⊖⁰)/)', true);
};

const notifyError = function(msg) {
  console.log(msg);
  showMessage(msg);
};

const showMessage = function(message, succeeded) {
  if (succeeded) {
    ui.messageArea.showMessageOnSuccess(message);
  } else {
    ui.messageArea.showMessageOnFailure(message);
  }
};

const storeTitle = function() {
  let title = ui.title();

  if (title != storedPost.title) {
    storedPost.title = title;
    storedPost.saved = false;
    store({ title: title, saved: false });
    ui.toggle('save-button', 'disabled', false);
  }
};

const storeBody = function() {
  let body = ui.body();

  if (body != storedPost.body) {
    storedPost.body = body;
    storedPost.saved = false;
    ui.toggle('save-button', 'disabled', false);
  }

  let cursorPosition = $('.post__body')[0].selectionStart;
  if (cursorPosition != storedPost.cursorPosition) {
    storedPost.cursorPosition = cursorPosition;
  }
  store(storedPost);
};

const storeCursorPosition = function() {
  let cursorPosition = $('.post__body')[0].selectionStart;
  if (cursorPosition != storedPost.cursorPosition) {
    store({ cursorPosition: cursorPosition });
  }
};

const store = function(data) {
  chrome.storage.sync.set(data, function() {
    if (chrome.runtime.lastError) {
      showMessage('Error: ' + chrome.runtime.lastError.message, false);
    }
  });
};

const showSavedStatus = function(saving) {
  $('.esa__post-button').text(saving ? 'Saving...' : 'Save as WIP');
};

const runSaveProcess = function() {
  ui.toggle('save-button', 'disabled', true);
  showSavedStatus(true);
  getConfig()
    .then(searchPost)
    .then(savePost)
    .then(storePostAsSaved)
    .then(updatePostTitleDisplay)
    .then(clearPost)
    .then(notifySaved)
    .then(notifySuccess)
    .catch(notifyError)
    .finally(function() {
      showSavedStatus(false);
    });
};

const runSaveProcessByShortcut = function(event) {
  // Ctrl+s or Cmd+s
  if ((event.metaKey || event.ctrlKey) && event.keyCode == 83) {
    event.preventDefault();
    runSaveProcess();
  }
};

$(function() {
  loadPost();
  getConfig().catch(notifyError);

  $('.post__title').on('keyup', _.debounce(storeTitle, 200));
  $('.post__body').on('keyup', _.debounce(storeBody, 200));
  $('.post__body').on('mouseup', storeCursorPosition);

  $('.post__title').on('keydown', runSaveProcessByShortcut);
  $('.post__body').on('keydown', runSaveProcessByShortcut);

  $('.post__body').esarea();

  $('.esa__post-button').on('click', runSaveProcess);
});
<commit_msg>Remove needless Promise<commit_after>import $ from 'jquery';
import _ from 'lodash';
import Promise from 'bluebird';
import '../../lib/jquery.selection';
import '../../lib/jquery.esarea';
import Ui from './ui';

let ui = new Ui();
window.ui = ui; // for debug

// TODO できればグローバルで定義しないほうがよさそう
let storedPost = { title: '', body: '', cursorPosition: 0, saved: false };

const loadPost = function() {
  let defaultPost = { title: '', body: '', cursorPosition: 0, saved: false };
  chrome.storage.sync.get(defaultPost, function(post) {
    storedPost = post;

    // TODO: この辺の処理を ui.loadPost() にまとめたい
    ui.toggle('save-button', 'disabled', post.saved);

    ui.title(post.title);
    ui.body(post.body);
    if (ui.title() != '') {
      // Move cursor at previous position
      ui.moveFocus('body', post.cursorPosition);
    }
  });
};

const getConfig = function() {
  return new Promise(function(resolve, reject) {
    let defaultConfig = { teamName: '', token: '', teamIcon: '', postId: '' };
    chrome.storage.sync.get(defaultConfig, function(config) {
      if (!config.teamName || !config.token) {
        ui.toggle('option-link', 'show', true);
        ui.teamName('Configuration failed');

        reject('Please configure options (\\( ˘⊖˘)/)');
      } else {
        ui.toggle('option-link', 'show', false);

        if (config.postId != '') {
          let link = `https://${config.teamName}.esa.io/posts/${config.postId}`;
          ui.savedPostLink(link);
        }

        ui.teamName(config.teamName);
        ui.teamIcon(config.teamIcon);

        resolve(config);
      }
    });
  });
};

const searchPost = function(config) {
  return new Promise(function(resolve, reject) {
    let title = ui.title();
    let category = '';

    if (hasCategory(title)) {
      category = /(.+)\/.+/.exec(title)[1];
      title = /.+\/(.+)/.exec(title)[1];
    }

    let q = `name:${title}`;
    if (category.length != 0) {
      q = `${q} category:${category}`;
    }

    $.ajax({
      type: 'GET',
      url: `https://api.esa.io/v1/teams/${config.teamName}/posts`,
      data: {
        q: q,
        access_token: config.token,
      },
    }).then(function(response) {
      let hitPost;
      // カテゴリ無しだけを検索する方法がわからなかったので別途絞込している
      if (category.length == 0) {
        hitPost = _.find(response.posts, { name: title, category: null });
      } else {
        // 1つしかない想定
        hitPost = response.posts[0];
      }

      // 記事があった場合は更新するためIDを保存する
      if (hitPost) {
        config.postId = hitPost.number;
      } else {
        config.postId = undefined;
      }
      chrome.storage.sync.set(config, function() {
        resolve(config);
      });
    }, reject);
  });
};

const savePost = function(config) {
  return new Promise(function(resolve, reject) {
    let type;
    let url = `https://api.esa.io/v1/teams/${config.teamName}/posts`;
    let title = ui.title();
    let body = ui.body();

    let post = {
      name: title,
      category: '',
      body_md: body,
      message: 'from tsuibami',
    };

    if (hasCategory(title)) {
      post['category'] = /(.+)\/.+/.exec(title)[1];
      post['name'] = /.+\/(.+)/.exec(title)[1];
    }

    let postId = config.postId;
    if (postId) {
      type = 'PATCH';
      url = url + '/' + postId;
    } else {
      type = 'POST';
    }

    $.ajax({
      type: type,
      url: url,
      data: {
        post: post,
        access_token: config.token,
      },
    }).then(resolve, reject);
  });
};

const storePostAsSaved = function(response) {
  return new Promise(function(resolve, reject) {
    ui.toggle('save-button', 'disabled', true);

    let newPostId = response.number;
    chrome.storage.sync.set({ saved: true, postId: newPostId }, function() {
      storedPost.saved = true;
      resolve(response);
    });
  });
};

const updatePostTitleDisplay = function(response) {
  // 保存したタイトルによっては末尾に "(2)" などの表記がesaによってつけられている可能性があるため、再度表示し直す
  return new Promise(function(resolve, reject) {
    chrome.storage.sync.set({ title: response.name }, function() {
      ui.title(response.full_name);
      resolve(response);
    });
  });
};

const clearPost = function(response) {
  if (!ui.checkedclear()) {
    return new Promise(function(resolve, reject) {
      ui.moveFocus('body');
      resolve(response);
    });
  }
  return new Promise(function(resolve, reject) {
    ui.title('');
    ui.body('');

    ui.toggle('save-button', 'disabled', true);

    storedPost = { title: '', body: '', cursorPosition: 0, saved: true };
    chrome.storage.sync.set(storedPost, function() {
      if (chrome.runtime.lastError) {
        reject(response);
      } else {
        resolve(response);
      }
    });
  });
};

const notifySaved = function(response) {
  let message;

  ui.savedPostLink(response.url);
  // 最初の保存の時だけメッセージを変える
  if (response.revision_number == 1) {
    message = 'created!';
  } else {
    message = 'updated!';
  }
  notifySuccess(message);
};

const hasCategory = function(title) {
  return /.+\/.+/.test(title);
};

const notifySuccess = function(msg) {
  showMessage(msg + ' (\\( ⁰⊖⁰)/)', true);
};

const notifyError = function(msg) {
  console.log(msg);
  showMessage(msg);
};

const showMessage = function(message, succeeded) {
  if (succeeded) {
    ui.messageArea.showMessageOnSuccess(message);
  } else {
    ui.messageArea.showMessageOnFailure(message);
  }
};

const storeTitle = function() {
  let title = ui.title();

  if (title != storedPost.title) {
    storedPost.title = title;
    storedPost.saved = false;
    store({ title: title, saved: false });
    ui.toggle('save-button', 'disabled', false);
  }
};

const storeBody = function() {
  let body = ui.body();

  if (body != storedPost.body) {
    storedPost.body = body;
    storedPost.saved = false;
    ui.toggle('save-button', 'disabled', false);
  }

  let cursorPosition = $('.post__body')[0].selectionStart;
  if (cursorPosition != storedPost.cursorPosition) {
    storedPost.cursorPosition = cursorPosition;
  }
  store(storedPost);
};

const storeCursorPosition = function() {
  let cursorPosition = $('.post__body')[0].selectionStart;
  if (cursorPosition != storedPost.cursorPosition) {
    store({ cursorPosition: cursorPosition });
  }
};

const store = function(data) {
  chrome.storage.sync.set(data, function() {
    if (chrome.runtime.lastError) {
      showMessage('Error: ' + chrome.runtime.lastError.message, false);
    }
  });
};

const showSavedStatus = function(saving) {
  $('.esa__post-button').text(saving ? 'Saving...' : 'Save as WIP');
};

const runSaveProcess = function() {
  ui.toggle('save-button', 'disabled', true);
  showSavedStatus(true);
  getConfig()
    .then(searchPost)
    .then(savePost)
    .then(storePostAsSaved)
    .then(updatePostTitleDisplay)
    .then(clearPost)
    .then(notifySaved)
    .catch(notifyError)
    .finally(function() {
      showSavedStatus(false);
    });
};

const runSaveProcessByShortcut = function(event) {
  // Ctrl+s or Cmd+s
  if ((event.metaKey || event.ctrlKey) && event.keyCode == 83) {
    event.preventDefault();
    runSaveProcess();
  }
};

$(function() {
  loadPost();
  getConfig().catch(notifyError);

  $('.post__title').on('keyup', _.debounce(storeTitle, 200));
  $('.post__body').on('keyup', _.debounce(storeBody, 200));
  $('.post__body').on('mouseup', storeCursorPosition);

  $('.post__title').on('keydown', runSaveProcessByShortcut);
  $('.post__body').on('keydown', runSaveProcessByShortcut);

  $('.post__body').esarea();

  $('.esa__post-button').on('click', runSaveProcess);
});
<|endoftext|>


<commit_before>import babel from 'gulp-babel'
import gulp from 'gulp'
import sass from 'gulp-sass'
import rename from 'gulp-rename'
// import injectSvg from 'gulp-inject-svg'

gulp.task('build:js:main', () =>
  gulp.src('app/src/main/*.js')
    .pipe(babel())
    .pipe(gulp.dest('app/dist/main')))

gulp.task('build:js:renderer', () =>
  gulp.src('app/src/renderer/js/*.js')
    .pipe(babel())
    .pipe(gulp.dest('app/dist/renderer/js')))

gulp.task('build:scss:main', () =>
  gulp.src('app/src/renderer/styles/*.scss')
    .pipe(sass().on('error', sass.logError))
    .pipe(gulp.dest('app/dist/renderer/styles')))

gulp.task('build:scss:themes', () =>
  gulp.src('app/src/renderer/styles/theme-*/main.scss')
    .pipe(sass().on('error', sass.logError))
    .pipe(rename((path) => {
      path.basename = path.dirname
      path.dirname = ""
    }))
    .pipe(gulp.dest('app/dist/renderer/styles')))

gulp.task('build', ['build:js:main', 'build:js:renderer', 'build:scss:main', 'build:scss:themes'])

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

gulp.task('watch', ['build'], () => {
  gulp.watch('app/src/main/*.js', ['build:js:main'])
  gulp.watch('app/src/renderer/*.js', ['build:js:renderer'])
  gulp.watch('app/src/renderer/styles/*', ['build:scss:main'])
  gulp.watch('app/src/renderer/styles/theme-*/main.scss', ['build:scss:themes'])
})
<commit_msg>Goddamn singlequotes.<commit_after>import babel from 'gulp-babel'
import gulp from 'gulp'
import sass from 'gulp-sass'
import rename from 'gulp-rename'
// import injectSvg from 'gulp-inject-svg'

gulp.task('build:js:main', () =>
  gulp.src('app/src/main/*.js')
    .pipe(babel())
    .pipe(gulp.dest('app/dist/main')))

gulp.task('build:js:renderer', () =>
  gulp.src('app/src/renderer/js/*.js')
    .pipe(babel())
    .pipe(gulp.dest('app/dist/renderer/js')))

gulp.task('build:scss:main', () =>
  gulp.src('app/src/renderer/styles/*.scss')
    .pipe(sass().on('error', sass.logError))
    .pipe(gulp.dest('app/dist/renderer/styles')))

gulp.task('build:scss:themes', () =>
  gulp.src('app/src/renderer/styles/theme-*/main.scss')
    .pipe(sass().on('error', sass.logError))
    .pipe(rename((path) => {
      path.basename = path.dirname
      path.dirname = ''
    }))
    .pipe(gulp.dest('app/dist/renderer/styles')))

gulp.task('build', ['build:js:main', 'build:js:renderer', 'build:scss:main', 'build:scss:themes'])

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

gulp.task('watch', ['build'], () => {
  gulp.watch('app/src/main/*.js', ['build:js:main'])
  gulp.watch('app/src/renderer/*.js', ['build:js:renderer'])
  gulp.watch('app/src/renderer/styles/*', ['build:scss:main'])
  gulp.watch('app/src/renderer/styles/theme-*/main.scss', ['build:scss:themes'])
})
<|endoftext|>


<commit_before>/**
 *	Modal window
 *	@author
 *	@Contructor
 *	@return An interface object
 */

ui.Modal = function(conf){
	var that = ui.Floats(); // Inheritance

	// Global configuration
	conf.$trigger = $(conf.element);
	conf.closeButton = true;
	conf.align = 'center';
	conf.classes = 'box';

	conf.ajaxType = 'POST';
	conf.ajaxParams = [];
	conf.ajaxParams.push({'x':'x'});//TODO refactor con el header de ajax

	// Methods Privates
	var show = function(event){
		conf.content.data = conf.$trigger.attr('href') || conf.$trigger.parents('form').attr('action'); //Se pisaba esta variable porque tiene el mismo class pero content.data diferente. Ejmplo del Type param con contenido distintos pero la misma class (va a traer la del primero)
		if(conf.content.type.toLowerCase() === 'ajax' && conf.$trigger.attr('type') == 'submit') setAjaxConfig();
		dimmer.on();
		that.show(event, conf);
		$('.close').bind('click', hide);
	};

	var hide = function(event){
		dimmer.off();
		that.hide(event, conf);
	};

	var setAjaxConfig = function(){
		// Content from href/action
		if(conf.content.data == '') alert('UI: Modal ajax configuration error.'); //TODO mejorar la expresion de vacio
		conf.ajaxType = conf.$trigger.parents('form').attr('method') || 'POST';
		conf.ajaxParams = $.merge(conf.ajaxParams, conf.$trigger.parents('form').serializeArray());
	};

	// Dimmer
	var dimmer = {
		on:function(){
			$('<div>').bind('click', function(event){ hide(event) }).addClass('dimmer').css({height:$(window).height(), display:'block'}).hide().appendTo('body').fadeIn();
		},
		off:function(){
			$('div.dimmer').fadeOut('normal', function(){ $(this).remove(); });
		}
	};

	// Events
	conf.$trigger
		.css('cursor', 'pointer')
		.bind('click', function(event){ show(event) });

	return { show: function(){ show($.Event()) }, hide: function(){ hide($.Event()) } };
};<commit_msg>SDK modal fix<commit_after>/**
 *	Modal window
 *	@author
 *	@Contructor
 *	@return An interface object
 */

ui.Modal = function(conf){
	var that = ui.Floats(); // Inheritance

	// Global configuration
	conf.$trigger = $(conf.element);
	conf.closeButton = true;
	conf.align = 'center';
	conf.classes = 'box';

	conf.ajaxType = 'POST';
	//conf.ajaxParams = [];
	//conf.ajaxParams.push({'x':'x'});//TODO refactor con el header de ajax
	conf.ajaxParams = 'x=x';//TODO refactor con el header de ajax

	// Methods Privates
	var show = function(event){
		conf.content.data = conf.$trigger.attr('href') || conf.$trigger.parents('form').attr('action'); //Se pisaba esta variable porque tiene el mismo class pero content.data diferente. Ejmplo del Type param con contenido distintos pero la misma class (va a traer la del primero)
		if(conf.content.type.toLowerCase() === 'ajax' && conf.$trigger.attr('type') == 'submit') setAjaxConfig();
		dimmer.on();
		that.show(event, conf);
		$('.close').bind('click', hide);
	};

	var hide = function(event){
		dimmer.off();
		that.hide(event, conf);
	};

	var setAjaxConfig = function(){
		// Content from href/action
		if(conf.content.data == '') alert('UI: Modal ajax configuration error.'); //TODO mejorar la expresion de vacio
		conf.ajaxType = conf.$trigger.parents('form').attr('method') || 'POST';
		//conf.ajaxParams = $.merge(conf.ajaxParams, conf.$trigger.parents('form').serializeArray());
		var serialized = conf.$trigger.parents('form').serialize();
		conf.ajaxParams = conf.ajaxParams + ((serialized != '') ? '&' + serialized : '');
	};

	// Dimmer
	var dimmer = {
		on:function(){
			$('<div>').bind('click', function(event){ hide(event) }).addClass('dimmer').css({height:$(window).height(), display:'block'}).hide().appendTo('body').fadeIn();
		},
		off:function(){
			$('div.dimmer').fadeOut('normal', function(){ $(this).remove(); });
		}
	};

	// Events
	conf.$trigger
		.css('cursor', 'pointer')
		.bind('click', function(event){ show(event) });

	return { show: function(){ show($.Event()) }, hide: function(){ hide($.Event()) } };
};<|endoftext|>


<commit_before>let gulp = require('gulp');
let sourcemaps = require('gulp-sourcemaps');
let source = require('vinyl-source-stream');
let rename = require('gulp-rename');
let replace = require('gulp-replace');
let buffer = require('vinyl-buffer');
let browserify = require('browserify');
let watchify = require('watchify');
let babel = require('babelify');
let fs = require('fs');

let allProjects = ['2.5d', '3d-point-lines', 'bezier-curves', 'bigbang', 'collision-detect', 'earth-sun-gravitation', 'friction', 'gravitations', 'normal-distribution-meter', 'paint-splatter', 'particles', 'perlin-noise', 'planetario', 'spaceship', 'springs-1', 'springs-2', 'random-walker', 'uniform-distribution-meter'];
let projects = getParams() || allProjects;

gulp.task('default', compile);
gulp.task('build', buildAll);
gulp.task('watch', watchProject);

// Will build only one if '--project' is specified
function buildAll() {
    projects.forEach(function(project) {
        compile(project, false);
    });
}

function watchProject() {
  if (projects.length > 1) {
    console.error("Please use '-p <project>' to watch");
    return false;
  }

  compile(projects[0], true);
}

function compile(project, watch) {
  let bundler = browserify('./projects/'+ project +'/app.js', { debug: true });
  if (watch) {
      bundler = watchify(bundler);
  }

  bundler.transform(babel);

  function rebundle() {
    bundler.bundle()
    .on('error', function(err) { console.error(err); this.emit('end'); })
    .pipe(source('app.js'))
    .pipe(buffer())
    .pipe(sourcemaps.init({ loadMaps: true }))
    .pipe(sourcemaps.write('./'))
    .pipe(gulp.dest('./build/'+ project +'/'));
  }

  if (watch) {
    console.log(">> Watching project: ", project," <<");
    bundler.on('update', function() {
      console.log('-> bundling...');
      rebundle();
    });
  }

  copyfiles(project);
  rebundle();
}

function copyfiles(project) {
  let localCSS = '';
  let path = {
              project: './projects/'+ project,
              build: './build/'+ project
            };

  let dir = fs.existsSync(path.project + '/css') ? fs.readdirSync(path.project + '/css'):[];

  if (dir.length) {
    let pattern = /.+\.css$/;
    for (var i=0; i<dir.length; i++) {
      if (pattern.test(dir[i])) {
        localCSS += "<link rel='stylesheet' href='css/"+ dir[i] +"' />";
      }
    }
  }

  if (fs.existsSync('./projects/'+ project +'/index.html')){
  };
  // Copy common index file unless there is a local one
  if (!fs.existsSync('./projects/'+ project +'/index.html')){
    gulp.src('./src/default.html')
    //.pipe(replace(/%(.{3})%/g, '$1foo'))
    .pipe(replace('%title%', project.charAt(0).toUpperCase() + project.slice(1)))
    .pipe(replace('%local_css%', localCSS))
    .pipe(rename('index.html'))
    .pipe(gulp.dest('./build/'+ project +'/'));

  } else {

    gulp.src('./projects/'+ project +'/index.html')
    .pipe(gulp.dest('./build/'+ project +'/'));
  }

  // Copy common CSS and check if CSS dir exists
  gulp.src('./src/css/common.css')
  .pipe(gulp.dest('./build/'+ project +'/css'));

  // Copy resources and local stylesheets
  gulp.src('./projects/'+ project +'/**/*.{jpg,png,gif,svg,css}')
  .pipe(gulp.dest('./build/'+ project +'/'));
}

function getParams() {
    let i = process.argv.indexOf("-p");
    if(i>-1 && process.argv[i+1] !== undefined) {
        return [process.argv[i+1]];
    }
}
<commit_msg>Corrected typo for '3d-points-lines' project<commit_after>let gulp = require('gulp');
let sourcemaps = require('gulp-sourcemaps');
let source = require('vinyl-source-stream');
let rename = require('gulp-rename');
let replace = require('gulp-replace');
let buffer = require('vinyl-buffer');
let browserify = require('browserify');
let watchify = require('watchify');
let babel = require('babelify');
let fs = require('fs');

let allProjects = ['2.5d', '3d-points-lines', 'bezier-curves', 'bigbang', 'collision-detect', 'earth-sun-gravitation', 'friction', 'gravitations', 'normal-distribution-meter', 'paint-splatter', 'particles', 'perlin-noise', 'planetario', 'spaceship', 'springs-1', 'springs-2', 'random-walker', 'uniform-distribution-meter'];
let projects = getParams() || allProjects;

gulp.task('default', compile);
gulp.task('build', buildAll);
gulp.task('watch', watchProject);

// Will build only one if '--project' is specified
function buildAll() {
    projects.forEach(function(project) {
        compile(project, false);
    });
}

function watchProject() {
  if (projects.length > 1) {
    console.error("Please use '-p <project>' to watch");
    return false;
  }

  compile(projects[0], true);
}

function compile(project, watch) {
  let bundler = browserify('./projects/'+ project +'/app.js', { debug: true });
  if (watch) {
      bundler = watchify(bundler);
  }

  bundler.transform(babel);

  function rebundle() {
    bundler.bundle()
    .on('error', function(err) { console.error(err); this.emit('end'); })
    .pipe(source('app.js'))
    .pipe(buffer())
    .pipe(sourcemaps.init({ loadMaps: true }))
    .pipe(sourcemaps.write('./'))
    .pipe(gulp.dest('./build/'+ project +'/'));
  }

  if (watch) {
    console.log(">> Watching project: ", project," <<");
    bundler.on('update', function() {
      console.log('-> bundling...');
      rebundle();
    });
  }

  copyfiles(project);
  rebundle();
}

function copyfiles(project) {
  let localCSS = '';
  let path = {
              project: './projects/'+ project,
              build: './build/'+ project
            };

  let dir = fs.existsSync(path.project + '/css') ? fs.readdirSync(path.project + '/css'):[];

  if (dir.length) {
    let pattern = /.+\.css$/;
    for (var i=0; i<dir.length; i++) {
      if (pattern.test(dir[i])) {
        localCSS += "<link rel='stylesheet' href='css/"+ dir[i] +"' />";
      }
    }
  }

  if (fs.existsSync('./projects/'+ project +'/index.html')){
  };
  // Copy common index file unless there is a local one
  if (!fs.existsSync('./projects/'+ project +'/index.html')){
    gulp.src('./src/default.html')
    //.pipe(replace(/%(.{3})%/g, '$1foo'))
    .pipe(replace('%title%', project.charAt(0).toUpperCase() + project.slice(1)))
    .pipe(replace('%local_css%', localCSS))
    .pipe(rename('index.html'))
    .pipe(gulp.dest('./build/'+ project +'/'));

  } else {

    gulp.src('./projects/'+ project +'/index.html')
    .pipe(gulp.dest('./build/'+ project +'/'));
  }

  // Copy common CSS and check if CSS dir exists
  gulp.src('./src/css/common.css')
  .pipe(gulp.dest('./build/'+ project +'/css'));

  // Copy resources and local stylesheets
  gulp.src('./projects/'+ project +'/**/*.{jpg,png,gif,svg,css}')
  .pipe(gulp.dest('./build/'+ project +'/'));
}

function getParams() {
    let i = process.argv.indexOf("-p");
    if(i>-1 && process.argv[i+1] !== undefined) {
        return [process.argv[i+1]];
    }
}
<|endoftext|>


<commit_before>define([
    'backbone',
    'jquery',
    'text!js-whatever/templates/modal.html',
    'bootstrap'
], function(Backbone, $, modalHtml) {
    'use strict';

    var modalTemplate = _.template(modalHtml);

    return Backbone.View.extend({
        className: 'modal fade',

        events: {
            'hidden.bs.modal': 'remove',
            'click .modal-action-button': function() {
                this.actionButtonCallback();
            }
        },

        initialize: function(options) {
            // The title and actionButtonText are escaped but content is not
            this.actionButtonCallback = options.actionButtonCallback;
            this.actionButtonClass = options.actionButtonClass;
            this.actionButtonText = options.actionButtonText;
            this.content = options.content;
            this.contentView = options.contentView;
            this.title = options.title;
            this.secondaryButtonText = options.secondaryButtonText;

            this.showFooter = !_.isUndefined(options.showFooter) ? options.showFooter : true;

            this.render();

            this.listenTo(this.contentView, 'primary-button-disable', function() {
                this.$('.modal-footer .button-primary').addClass('not-clickable disabled');
            });

            this.listenTo(this.contentView, 'primary-button-enable', function() {
                this.$('.modal-footer .button-primary').removeClass('not-clickable disabled');
            });
        },

        render: function() {
            $(document.activeElement).blur();

            this.$el.html(modalTemplate({
                actionButtonClass: this.actionButtonClass,
                actionButtonText: this.actionButtonText,
                secondaryButtonText: this.secondaryButtonText,
                showFooter: this.showFooter,
                title: this.title
            })).modal();

            if (this.content) {
                this.$('.modal-body').html(this.content);
            } else if (this.contentView) {
                this.contentView.render();
                this.$('.modal-body').append(this.contentView.$el);
            }
        },

        hide: function() {
            this.$el.modal('hide');
        }
    });

});<commit_msg>Bugfix.<commit_after>define([
    'backbone',
    'underscore',
    'jquery',
    'text!js-whatever/templates/modal.html',
    'bootstrap'
], function(Backbone, _, $, modalHtml) {
    'use strict';

    var modalTemplate = _.template(modalHtml);

    return Backbone.View.extend({
        className: 'modal fade',

        events: {
            'hidden.bs.modal': 'remove',
            'click .modal-action-button': function() {
                this.actionButtonCallback();
            }
        },

        initialize: function(options) {
            // The title and actionButtonText are escaped but content is not
            this.actionButtonCallback = options.actionButtonCallback;
            this.actionButtonClass = options.actionButtonClass;
            this.actionButtonText = options.actionButtonText;
            this.content = options.content;
            this.contentView = options.contentView;
            this.title = options.title;
            this.secondaryButtonText = options.secondaryButtonText;

            this.showFooter = !_.isUndefined(options.showFooter) ? options.showFooter : true;

            this.render();

            this.listenTo(this.contentView, 'primary-button-disable', function() {
                this.$('.modal-footer .button-primary').addClass('not-clickable disabled');
            });

            this.listenTo(this.contentView, 'primary-button-enable', function() {
                this.$('.modal-footer .button-primary').removeClass('not-clickable disabled');
            });
        },

        render: function() {
            $(document.activeElement).blur();

            this.$el.html(modalTemplate({
                actionButtonClass: this.actionButtonClass,
                actionButtonText: this.actionButtonText,
                secondaryButtonText: this.secondaryButtonText,
                showFooter: this.showFooter,
                title: this.title
            })).modal();

            if (this.content) {
                this.$('.modal-body').html(this.content);
            } else if (this.contentView) {
                this.contentView.render();
                this.$('.modal-body').append(this.contentView.$el);
            }
        },

        hide: function() {
            this.$el.modal('hide');
        }
    });

});<|endoftext|>


<commit_before>/* global __dirname */

// we can use sync safely here because it's just the gulp file
// gulp tasks prefer unregulated arrow-body-style
/* eslint-disable no-sync, arrow-body-style */

import clean from 'gulp-rimraf';
import coffeelint from 'gulp-coffeelint';
import coveralls from 'gulp-coveralls';
import eslint from 'gulp-eslint';
import gulp from 'gulp';
import minimist from 'minimist';
import mocha from 'gulp-mocha';
import mochaSpawn from 'gulp-spawn-mocha';
import open from 'gulp-open';
import path from 'path';
import runSequence from 'run-sequence';
import util from 'gulp-util';

// this is required for mocha
require('coffee-script/register');

const args = minimist(process.argv);

const config = {
  verbose: args.verbose || false,
  quiet: args.quiet || false,
  dirs: {
    src: path.join(__dirname, 'src'),
    test: path.join(__dirname, 'test'),
    coverage: path.join(__dirname, 'coverage'),
  },
  test: {
    reporter: args.reporter || 'spec',
  },
};

function log(...items) {
  if (config.quiet === false) {
    // Reflect is not available in the gulp file
    // eslint-disable-next-line prefer-reflect
    util.log.apply(null, items);
  }
}

if (config.verbose) {
  log('Gulp Config:', JSON.stringify(config, null, 2));
}

// Default build task
gulp.task('default', [ 'test' ]);
// Default test task
gulp.task('test', [ 'mocha' ]);

// npm test task
gulp.task('test:npm', (done) => {
  runSequence('clean', 'lint', 'mocha:coverage', () => {
    runSequence('coveralls:upload', done);
  });
});

gulp.task('config', () => {
  util.log('Gulp Config:', JSON.stringify(config, null, 2));
});

gulp.task('help', () => {
  /* eslint-disable max-len */
  util.log(`*** Gulp Help ***

Command Line Overrides:
  ${ util.colors.cyan('--verbose') }          : print webpack module details and stats after bundling (${ util.colors.magenta(config.verbose) })
  ${ util.colors.cyan('--quiet') }            : do not print any extra build details (${ util.colors.magenta(config.quiet) })
  ${ util.colors.cyan('--reporter') }  ${ util.colors.yellow('<name>') } : mocha test reporter (${ util.colors.magenta(config.test.reporter) })
    reporter options : ${ [ 'spec', 'list', 'progress', 'dot', 'min' ].map((x) => util.colors.magenta(x)).join(', ') }

Tasks:
  ${ util.colors.cyan('gulp') } is an alias for ${ util.colors.cyan('gulp test') }
  ${ util.colors.cyan('gulp test') } will build a ${ util.colors.yellow('test') } bundle and run mocha against the tests (alias for ${ util.colors.cyan('gulp mocha') })

  ${ util.colors.cyan('gulp help') } will print this help text
  ${ util.colors.cyan('gulp config') } will print the gulp build configuration

  ${ util.colors.cyan('gulp clean') } will delete all files in ${ util.colors.magenta(config.dirs.coverage) }
       ${ [ 'coverage' ].map((x) => util.colors.cyan(`clean:${ x }`)).join(', ') }

  ${ util.colors.cyan('gulp lint') } will lint the source files with ${ util.colors.yellow('eslint') } and ${ util.colors.yellow('coffeelint') }
       ${ [ 'es', 'coffee' ].map((x) => util.colors.cyan(`lint:${ x }`)).join(', ') }

  ${ util.colors.cyan('gulp mocha') } will run mocha against the specs in ${ util.colors.magenta(config.dirs.test) }

  ${ util.colors.cyan('gulp watch') } will start webpack in ${ util.colors.magenta('watch') } mode, and run all tests after any detected change
       ${ [ 'lint', 'mocha' ].map((x) => util.colors.cyan(`watch:${ x }`)).join(', ') }

  ${ util.colors.cyan('gulp coveralls') } will upload test coverage results to coveralls.io

  ${ util.colors.cyan('gulp browser') } will open a browser window to test coverage results
       ${ [ 'coverage' ].map((x) => util.colors.cyan(`browser:${ x }`)).join(', ') }
`);
  /* eslint-enable max-len */
});

// clean Tasks

gulp.task('clean', [ 'clean:coverage' ]);

gulp.task('clean:coverage', () => {
  log('Cleaning', util.colors.magenta(config.dirs.coverage));

  return gulp
    .src(config.dirs.coverage, { read: false })
    .pipe(clean());
});

// lint Tasks

gulp.task('lint', [ 'lint:es', 'lint:coffee' ]);

gulp.task('lint:es', () => {
  log('Linting with ESLint');

  return gulp
    .src([
      path.join(__dirname, '*.js'),
    ])
    .pipe(eslint())
    .pipe(eslint.format())
    .pipe(eslint.failAfterError());
});

gulp.task('lint:coffee', () => {
  log('Linting with CoffeeLint');

  return gulp
    .src([
      path.join(config.dirs.src, '**', '*.coffee'),
      path.join(config.dirs.test, '**', '*.coffee'),
      path.join(__dirname, '*.coffee'),
    ])
    .pipe(coffeelint())
    .pipe(coffeelint.reporter('coffeelint-stylish'))
    .pipe(coffeelint.reporter('fail'));
});

// mocha Tasks

gulp.task('mocha', () => {
  log('Testing with Mocha', util.colors.magenta(config.dirs.test));

  return gulp
    .src([
      path.join(config.dirs.test, '**', '*.spec.coffee'),
    ])
    .pipe(mocha({
      reporter: args.reporter || (config.quiet ? 'dot' : config.test.reporter),
    }));
});

gulp.task('mocha:coverage', () => {
  log('Covering tests with Mocha and Istanbul', util.colors.magenta(config.dirs.test));

  return gulp
    .src([
      path.join(config.dirs.test, '**', '*.spec.coffee'),
    ], { read: false })
    .pipe(mochaSpawn({
      recursive: true,
      compilers: 'coffee:coffee-script/register',
      require: path.join(config.dirs.test, 'setup.js'),
      istanbul: true,
    }));
});

// watch Tasks

gulp.task('watch', [ 'watch:mocha' ]);

gulp.task('watch:mocha', () => {
  runSequence('mocha', () => null);

  return gulp
    .watch([
      path.join(config.dirs.src, '**', '*.coffee'),
      path.join(config.dirs.test, '**', '*.spec.coffee'),
    ], () => {
      runSequence('mocha', () => null);
    });
});

gulp.task('watch:lint', () => {
  runSequence('lint', () => null);

  return gulp
    .watch([
      path.join(config.dirs.src, '**', '*.coffee'),
      path.join(config.dirs.test, '**', '*.coffee'),
      path.join(__dirname, '*.coffee'),
      path.join(__dirname, '*.js'),
    ], () => {
      runSequence('lint', () => null);
    });
});

// coveralls Tasks

gulp.task('coveralls', (done) => {
  runSequence('mocha:coverage', 'coveralls:upload', done);
});

gulp.task('coveralls:upload', () => {
  return gulp
    .src(path.join(config.dirs.coverage, '**', 'lcov.info'))
    .pipe(coveralls());
});

// browser Tasks

gulp.task('browser', [ 'browser:coverage' ]);

gulp.task('browser:coverage', [ 'mocha:coverage' ], () => {
  return gulp
    .src('')
    .pipe(open({ uri: path.join(config.dirs.coverage, 'lcov-report', 'index.html') }));
});
<commit_msg>enabling dotenv for gulp<commit_after>/* global __dirname */

// we can use sync safely here because it's just the gulp file
// gulp tasks prefer unregulated arrow-body-style
/* eslint-disable no-sync, arrow-body-style */

// load environment variables
require('dotenv').config();

import clean from 'gulp-rimraf';
import coffeelint from 'gulp-coffeelint';
import coveralls from 'gulp-coveralls';
import eslint from 'gulp-eslint';
import gulp from 'gulp';
import minimist from 'minimist';
import mocha from 'gulp-mocha';
import mochaSpawn from 'gulp-spawn-mocha';
import open from 'gulp-open';
import path from 'path';
import runSequence from 'run-sequence';
import util from 'gulp-util';

// this is required for mocha
require('coffee-script/register');

const args = minimist(process.argv);

const config = {
  verbose: args.verbose || false,
  quiet: args.quiet || false,
  dirs: {
    src: path.join(__dirname, 'src'),
    test: path.join(__dirname, 'test'),
    coverage: path.join(__dirname, 'coverage'),
  },
  test: {
    reporter: args.reporter || 'spec',
  },
};

function log(...items) {
  if (config.quiet === false) {
    // Reflect is not available in the gulp file
    // eslint-disable-next-line prefer-reflect
    util.log.apply(null, items);
  }
}

if (config.verbose) {
  log('Gulp Config:', JSON.stringify(config, null, 2));
}

// Default build task
gulp.task('default', [ 'test' ]);
// Default test task
gulp.task('test', [ 'mocha' ]);

// npm test task
gulp.task('test:npm', (done) => {
  runSequence('clean', 'lint', 'mocha:coverage', () => {
    runSequence('coveralls:upload', done);
  });
});

gulp.task('config', () => {
  util.log('Gulp Config:', JSON.stringify(config, null, 2));
});

gulp.task('help', () => {
  /* eslint-disable max-len */
  util.log(`*** Gulp Help ***

Command Line Overrides:
  ${ util.colors.cyan('--verbose') }          : print webpack module details and stats after bundling (${ util.colors.magenta(config.verbose) })
  ${ util.colors.cyan('--quiet') }            : do not print any extra build details (${ util.colors.magenta(config.quiet) })
  ${ util.colors.cyan('--reporter') }  ${ util.colors.yellow('<name>') } : mocha test reporter (${ util.colors.magenta(config.test.reporter) })
    reporter options : ${ [ 'spec', 'list', 'progress', 'dot', 'min' ].map((x) => util.colors.magenta(x)).join(', ') }

Tasks:
  ${ util.colors.cyan('gulp') } is an alias for ${ util.colors.cyan('gulp test') }
  ${ util.colors.cyan('gulp test') } will build a ${ util.colors.yellow('test') } bundle and run mocha against the tests (alias for ${ util.colors.cyan('gulp mocha') })

  ${ util.colors.cyan('gulp help') } will print this help text
  ${ util.colors.cyan('gulp config') } will print the gulp build configuration

  ${ util.colors.cyan('gulp clean') } will delete all files in ${ util.colors.magenta(config.dirs.coverage) }
       ${ [ 'coverage' ].map((x) => util.colors.cyan(`clean:${ x }`)).join(', ') }

  ${ util.colors.cyan('gulp lint') } will lint the source files with ${ util.colors.yellow('eslint') } and ${ util.colors.yellow('coffeelint') }
       ${ [ 'es', 'coffee' ].map((x) => util.colors.cyan(`lint:${ x }`)).join(', ') }

  ${ util.colors.cyan('gulp mocha') } will run mocha against the specs in ${ util.colors.magenta(config.dirs.test) }

  ${ util.colors.cyan('gulp watch') } will start webpack in ${ util.colors.magenta('watch') } mode, and run all tests after any detected change
       ${ [ 'lint', 'mocha' ].map((x) => util.colors.cyan(`watch:${ x }`)).join(', ') }

  ${ util.colors.cyan('gulp coveralls') } will upload test coverage results to coveralls.io

  ${ util.colors.cyan('gulp browser') } will open a browser window to test coverage results
       ${ [ 'coverage' ].map((x) => util.colors.cyan(`browser:${ x }`)).join(', ') }
`);
  /* eslint-enable max-len */
});

// clean Tasks

gulp.task('clean', [ 'clean:coverage' ]);

gulp.task('clean:coverage', () => {
  log('Cleaning', util.colors.magenta(config.dirs.coverage));

  return gulp
    .src(config.dirs.coverage, { read: false })
    .pipe(clean());
});

// lint Tasks

gulp.task('lint', [ 'lint:es', 'lint:coffee' ]);

gulp.task('lint:es', () => {
  log('Linting with ESLint');

  return gulp
    .src([
      path.join(__dirname, '*.js'),
    ])
    .pipe(eslint())
    .pipe(eslint.format())
    .pipe(eslint.failAfterError());
});

gulp.task('lint:coffee', () => {
  log('Linting with CoffeeLint');

  return gulp
    .src([
      path.join(config.dirs.src, '**', '*.coffee'),
      path.join(config.dirs.test, '**', '*.coffee'),
      path.join(__dirname, '*.coffee'),
    ])
    .pipe(coffeelint())
    .pipe(coffeelint.reporter('coffeelint-stylish'))
    .pipe(coffeelint.reporter('fail'));
});

// mocha Tasks

gulp.task('mocha', () => {
  log('Testing with Mocha', util.colors.magenta(config.dirs.test));

  return gulp
    .src([
      path.join(config.dirs.test, '**', '*.spec.coffee'),
    ])
    .pipe(mocha({
      reporter: args.reporter || (config.quiet ? 'dot' : config.test.reporter),
    }));
});

gulp.task('mocha:coverage', () => {
  log('Covering tests with Mocha and Istanbul', util.colors.magenta(config.dirs.test));

  return gulp
    .src([
      path.join(config.dirs.test, '**', '*.spec.coffee'),
    ], { read: false })
    .pipe(mochaSpawn({
      recursive: true,
      compilers: 'coffee:coffee-script/register',
      require: path.join(config.dirs.test, 'setup.js'),
      istanbul: true,
    }));
});

// watch Tasks

gulp.task('watch', [ 'watch:mocha' ]);

gulp.task('watch:mocha', () => {
  runSequence('mocha', () => null);

  return gulp
    .watch([
      path.join(config.dirs.src, '**', '*.coffee'),
      path.join(config.dirs.test, '**', '*.spec.coffee'),
    ], () => {
      runSequence('mocha', () => null);
    });
});

gulp.task('watch:lint', () => {
  runSequence('lint', () => null);

  return gulp
    .watch([
      path.join(config.dirs.src, '**', '*.coffee'),
      path.join(config.dirs.test, '**', '*.coffee'),
      path.join(__dirname, '*.coffee'),
      path.join(__dirname, '*.js'),
    ], () => {
      runSequence('lint', () => null);
    });
});

// coveralls Tasks

gulp.task('coveralls', (done) => {
  runSequence('mocha:coverage', 'coveralls:upload', done);
});

gulp.task('coveralls:upload', () => {
  return gulp
    .src(path.join(config.dirs.coverage, '**', 'lcov.info'))
    .pipe(coveralls());
});

// browser Tasks

gulp.task('browser', [ 'browser:coverage' ]);

gulp.task('browser:coverage', [ 'mocha:coverage' ], () => {
  return gulp
    .src('')
    .pipe(open({ uri: path.join(config.dirs.coverage, 'lcov-report', 'index.html') }));
});
<|endoftext|>


<commit_before>"use strict";

import gulp from 'gulp';
import del     from    'del';

import jshint   from   'gulp-jshint';
import mocha    from  'gulp-mocha';
import istanbul from    'gulp-istanbul';
import bs from 'browser-sync';
import nodemon  from  'gulp-nodemon';
import sourcemaps from 'gulp-sourcemaps';
import through  from   'through2';
import yargs from  'yargs';
import exit    from    'gulp-exit';
import babel from 'gulp-babel';

const args = yargs.argv;

const isprod = (args.env === 'prod');

//call gulp -env value -frontendpath value
console.log("args.env is: " + args.env);
console.log("args.frontendpath is: " + args.frontendpath);

const noop = function () {
  return through.obj();
};

const dev = function (task) {
  return isprod ? noop() : task;
};

const prod = function (task) {
  return isprod ? task : noop();
};

// ***************************************************
// *                   FILE PATHS                    *
// ***************************************************

const filePaths = ['src/**/*.js', './app.js'];
const testHintJs = ['src/**/*.js', './app.js'];
const testPaths = [
  'test-server-unit/util.spec.js',
  'test-server-integration/**/*.spec.js',
  'test-server-unit/3dparty-passport.spec.js',
  'test-server-unit/auth-experimental-collapse-db.spec.js',
  'test-server-unit/auth-util.spec.js',
  'test-server-unit/passport.spec.js',
  'test-server-unit/users.spec.js'
];
const sourcemapPaths = ['src/**/*.js'];

// ***************************************************
// *                     JSHINT                      *
// ***************************************************

export function hint() {
  return gulp.src(testHintJs /*, {since: gulp.lastRun('hint')}*/)
    .pipe(jshint())
    .pipe(jshint.reporter('default'))
    .pipe(jshint.reporter('fail'));
}

// ***************************************************
// *                      TEST                       *
// ***************************************************

gulp.task('pre-test', function pretestInternal() {
  return gulp.src(sourcemapPaths)
  // optionally load existing source maps
    .pipe(sourcemaps.init())
    // Covering files
    .pipe(istanbul())
    // Force `require` to return covered files
    .pipe(istanbul.hookRequire());
});

function handleError(err) {
  console.log(err.toString());
  // this.emit('end');
}

gulp.task('test',
  gulp.series('pre-test', function testInternal() {
    return gulp.src(testPaths)
      .pipe(mocha({
        timeout: 10000,
        useColors: true
      }))
      // .pipe(mocha().on("error", handleError))
      // // Creating the reports after tests ran
      .pipe(istanbul.writeReports({
        dir: './coverage',
        reporters: ['lcov', 'json', 'text', 'text-summary'],
        reportOpts: {dir: './coverage'},
      }))
      .pipe(exit());
    // Enforce a coverage of at least 90% otherwise throw an error
    // FIXME this throws an error. I don't known why. Probabily it's a gulp's bug
    // .pipe(istanbul.enforceThresholds({ thresholds: { global: 80,  each: 85 } }));
    // .once('end', function () {
    //   process.exit();
    // });
  }));

// ***************************************************
// *                    LOCAL ENV                    *
// ***************************************************

gulp.task('nodemon', function nodemonInternal(cb) {
  var started = false;
  return nodemon({
    script: 'bin/www',
    // watch core server file(s) that require server restart on change
    //watch: ['app.js']
    // ext: 'js html',
    env: {'NODE_ENV': process.env.NODE_ENV}
  })
    .on('start', function nodemonStartInternal() {
      bs.reload;
      if (!started) {
        cb();
        started = true;
      }

    })
    .on('error', function nodemonErrInternal(err) {
      // Make sure failure causes gulp to exit
      throw err;
    });
});

gulp.task('server',
  gulp.series('nodemon', function bSyncInternal() {

    // for more browser-sync config options: http://www.browsersync.io/docs/options/
    bs.init({

      // informs browser-sync to proxy our expressjs app which would run at the following location
      proxy: 'http://localhost:3000',

      // informs browser-sync to use the following port for the proxied app
      // notice that the default port is 3000, which would clash with our expressjs
      port: 3001,

      // open the proxied app in chrome
      browser: ["google chrome"]
    });
  })
);

gulp.task('default',
  gulp.series(/*hint,*/ 'server', function watcher(done) {
    gulp.watch(filePaths, bs.reload);
  })
);
<commit_msg>impl of gulpfile in es2015 #65<commit_after>"use strict";

import gulp         from 'gulp';
import del          from 'del';
import jshint       from 'gulp-jshint';
import mocha        from 'gulp-mocha';
import istanbul     from 'gulp-istanbul';
import bs           from 'browser-sync';
import nodemon      from 'gulp-nodemon';
import sourcemaps   from 'gulp-sourcemaps';
import through      from 'through2';
import yargs        from 'yargs';
import exit         from 'gulp-exit';
import babel        from 'gulp-babel';

const args = yargs.argv;
const isprod = (args.env === 'prod');

//call gulp -env value -frontendpath value
console.log("args.env is: " + args.env);
console.log("args.frontendpath is: " + args.frontendpath);

const noop = () => through.obj();
const dev = task => isprod ? noop() : task;
const prod = task => isprod ? task : noop();

// ***************************************************
// *                   FILE PATHS                    *
// ***************************************************
const filePaths = ['src/**/*.js', './app.js'];
const testHintJs = ['src/**/*.js', './app.js'];
const testPaths = [
  'test-server-unit/util.spec.js',
  'test-server-integration/**/*.spec.js',
  'test-server-unit/3dparty-passport.spec.js',
  'test-server-unit/auth-experimental-collapse-db.spec.js',
  'test-server-unit/auth-util.spec.js',
  'test-server-unit/passport.spec.js',
  'test-server-unit/users.spec.js'
];
const sourcemapPaths = ['src/**/*.js'];

// ***************************************************
// *                     JSHINT                      *
// ***************************************************
export function hint() {
  return gulp.src(testHintJs /*, {since: gulp.lastRun('hint')}*/)
    .pipe(jshint())
    .pipe(jshint.reporter('default'))
    .pipe(jshint.reporter('fail'));
}

// ***************************************************
// *                      TEST                       *
// ***************************************************

function preTest() {
  return gulp.src(sourcemapPaths)
  // optionally load existing source maps
    .pipe(sourcemaps.init())
    // Covering files
    .pipe(istanbul())
    // Force `require` to return covered files
    .pipe(istanbul.hookRequire());
}

function handleError(err) {
  console.log(err.toString());
  // this.emit('end');
}

function testInternal() {
  return gulp.src(testPaths)
    .pipe(mocha({
      timeout: 10000,
      useColors: true
    }))
    // .pipe(mocha().on("error", handleError))
    // // Creating the reports after tests ran
    .pipe(istanbul.writeReports({
      dir: './coverage',
      reporters: ['lcov', 'json', 'text', 'text-summary'],
      reportOpts: {dir: './coverage'},
    }))
    .pipe(exit());
  // Enforce a coverage of at least 90% otherwise throw an error
  // FIXME this throws an error. I don't known why. Probabily it's a gulp's bug
  // .pipe(istanbul.enforceThresholds({ thresholds: { global: 80,  each: 85 } }));
  // .once('end', function () {
  //   process.exit();
  // });
}

const test = gulp.series(preTest, testInternal);
export { test };

// ***************************************************
// *                    LOCAL ENV                    *
// ***************************************************
export function nodemontask(cb) {
  var started = false;
  return nodemon({
    script: 'bin/www',
    // watch core server file(s) that require server restart on change
    //watch: ['app.js']
    // ext: 'js html',
    env: {'NODE_ENV': process.env.NODE_ENV}
  })
    .on('start', function nodemonStartInternal() {
      bs.reload;
      if (!started) {
        cb();
        started = true;
      }

    })
    .on('error', function nodemonErrInternal(err) {
      // Make sure failure causes gulp to exit
      throw err;
    });
}

function bSyncInternal() {

  // for more browser-sync config options: http://www.browsersync.io/docs/options/
  bs.init({

    // informs browser-sync to proxy our expressjs app which would run at the following location
    proxy: 'http://localhost:3000',

    // informs browser-sync to use the following port for the proxied app
    // notice that the default port is 3000, which would clash with our expressjs
    port: 3001,

    // open the proxied app in chrome
    browser: ["google chrome"]
  });
}

const server = gulp.series(nodemontask, bSyncInternal);
export { server };

function watcher() {
  gulp.watch(filePaths, bs.reload);
}

const buildDefault = gulp.series(hint, server, watcher);
export { buildDefault };

/*
 * Export a default task
 */
export default buildDefault;<|endoftext|>


<commit_before>/*
** file: js/main.js
** description: javascript code for "html/main.html" page
*/

var syncRules;

function init_main() {
    //get the current enabled state and rule list
    chrome.storage.sync.get('status', function (data) {
        if (typeof data.status === "undefined") {
            //this is first use; enable by default and save
            chrome.storage.sync.set({
                "status": 1
            });
            var isEnabled = 1;
        }
        else {
            var isEnabled = parseInt(data.status);
        }

        //make the switch reflect our current state
        if (isEnabled) {
            $("#status").prop("checked", true);
        }
        else {
            $("#status").prop("checked", false);
        }
    });

    //init our switch
    $('#status').bootstrapSwitch();

    //build options link
    $("#optLink").attr("href", chrome.extension.getURL("html/options.html"));

    //show the menu
    $('html').hide().fadeIn('slow');
}

//bind events to dom elements
document.addEventListener('DOMContentLoaded', init_main);

//handle enabling or disabling or the extension
$('#status').change(function () {
    if ($("#status").prop("checked")) {
        chrome.storage.sync.set({
            "status": 1
        });
    }
    else {
        chrome.storage.sync.set({
            "status": 0
        });
    }
});<commit_msg>remove bootstrap switch init<commit_after>/*
** file: js/main.js
** description: javascript code for "html/main.html" page
*/

var syncRules;

function init_main() {
    //get the current enabled state and rule list
    chrome.storage.sync.get('status', function (data) {
        if (typeof data.status === "undefined") {
            //this is first use; enable by default and save
            chrome.storage.sync.set({
                "status": 1
            });
            var isEnabled = 1;
        }
        else {
            var isEnabled = parseInt(data.status);
        }

        //make the switch reflect our current state
        if (isEnabled) {
            $("#status").prop("checked", true);
        }
        else {
            $("#status").prop("checked", false);
        }
    });

    //build options link
    $("#optLink").attr("href", chrome.extension.getURL("html/options.html"));

    //show the menu
    $('html').hide().fadeIn('slow');
}

//bind events to dom elements
document.addEventListener('DOMContentLoaded', init_main);

//handle enabling or disabling or the extension
$('#status').change(function () {
    if ($("#status").prop("checked")) {
        chrome.storage.sync.set({
            "status": 1
        });
    }
    else {
        chrome.storage.sync.set({
            "status": 0
        });
    }
});<|endoftext|>


<commit_before>import gulp from 'gulp'
import loadPlugins from 'gulp-load-plugins'
import {Instrumenter} from 'isparta'
import del from 'del'
import seq from 'run-sequence'
import spawn from 'cross-spawn-promise'

const COVERAGE_THRESHOLDS = {global: 100}

const $ = loadPlugins()

const plumb = () => $.if(!process.env.CI, $.plumber({
  errorHandler: $.notify.onError('<%= error.message %>')
}))

gulp.task('clean', () => del('lib'))

gulp.task('transpile', () => {
  return gulp.src('src/**/*.js')
    .pipe(plumb())
    .pipe($.sourcemaps.init())
    .pipe($.babel())
    .pipe($.sourcemaps.write())
    .pipe(gulp.dest('lib'))
})

gulp.task('lint', () => {
  return gulp.src('src/**/*.js')
    .pipe(plumb())
    .pipe($.standard())
    .pipe($.standard.reporter('default', {breakOnError: false}))
})

gulp.task('pre-coverage', () => {
  return gulp.src('src/**/*.js')
    .pipe($.istanbul({instrumenter: Instrumenter}))
    .pipe($.istanbul.hookRequire())
})

gulp.task('coverage', ['pre-coverage'], () => {
  return gulp.src(['test/lib/setup.js', 'test/{unit,integration}/**/*.js', '!**/_*.js'], {read: false})
    .pipe(plumb())
    .pipe($.mocha({reporter: 'spec'}))
    .pipe($.istanbul.writeReports())
    .pipe($.istanbul.enforceThresholds({thresholds: COVERAGE_THRESHOLDS}))
})

gulp.task('coveralls', () => {
  if (!process.env.COVERALLS) {
    return
  }
  return gulp.src('coverage/lcov.info')
    .pipe($.coveralls())
})

gulp.task('test', (cb) => seq('lint', 'coverage', 'coveralls', cb))

gulp.task('build', (cb) => seq('test', 'clean', 'transpile', cb))

gulp.task('watch', () => gulp.watch('{src,test}/**/*', ['build']))

gulp.task('clean-doc', () => del('doc'))

gulp.task('doc', ['clean-doc'], () => {
  const cmd = 'node_modules/.bin/jsdoc'
  const args = ['-c', 'jsdoc.json']
  return spawn(cmd, args, {cwd: __dirname, stdio: 'inherit'})
})

gulp.task('default', ['build'], () => gulp.start('watch'))
<commit_msg>Also lint tests<commit_after>import gulp from 'gulp'
import loadPlugins from 'gulp-load-plugins'
import {Instrumenter} from 'isparta'
import del from 'del'
import seq from 'run-sequence'
import spawn from 'cross-spawn-promise'

const COVERAGE_THRESHOLDS = {global: 100}

const $ = loadPlugins()

const plumb = () => $.if(!process.env.CI, $.plumber({
  errorHandler: $.notify.onError('<%= error.message %>')
}))

gulp.task('clean', () => del('lib'))

gulp.task('transpile', () => {
  return gulp.src('src/**/*.js')
    .pipe(plumb())
    .pipe($.sourcemaps.init())
    .pipe($.babel())
    .pipe($.sourcemaps.write())
    .pipe(gulp.dest('lib'))
})

gulp.task('lint', () => {
  return gulp.src('{src,test}/**/*.js')
    .pipe(plumb())
    .pipe($.standard())
    .pipe($.standard.reporter('default', {breakOnError: false}))
})

gulp.task('pre-coverage', () => {
  return gulp.src('src/**/*.js')
    .pipe($.istanbul({instrumenter: Instrumenter}))
    .pipe($.istanbul.hookRequire())
})

gulp.task('coverage', ['pre-coverage'], () => {
  return gulp.src(['test/lib/setup.js', 'test/{unit,integration}/**/*.js', '!**/_*.js'], {read: false})
    .pipe(plumb())
    .pipe($.mocha({reporter: 'spec'}))
    .pipe($.istanbul.writeReports())
    .pipe($.istanbul.enforceThresholds({thresholds: COVERAGE_THRESHOLDS}))
})

gulp.task('coveralls', () => {
  if (!process.env.COVERALLS) {
    return
  }
  return gulp.src('coverage/lcov.info')
    .pipe($.coveralls())
})

gulp.task('test', (cb) => seq('lint', 'coverage', 'coveralls', cb))

gulp.task('build', (cb) => seq('test', 'clean', 'transpile', cb))

gulp.task('watch', () => gulp.watch('{src,test}/**/*', ['build']))

gulp.task('clean-doc', () => del('doc'))

gulp.task('doc', ['clean-doc'], () => {
  const cmd = 'node_modules/.bin/jsdoc'
  const args = ['-c', 'jsdoc.json']
  return spawn(cmd, args, {cwd: __dirname, stdio: 'inherit'})
})

gulp.task('default', ['build'], () => gulp.start('watch'))
<|endoftext|>


<commit_before>var rangy = (function() {
    var api = {

    };

    return api;
})();<commit_msg>Added log4javascript and some code copied from timdown.co.uk<commit_after>var rangy = (function() {
    var getSelection, getSelectionInfo, insertRangeBoundaryMarker, setRangeBoundary, removeMarkerElement;
    var createRange, selectRange, createSelectionInfo, testSelection, testRange, testNode;

    var win = window, doc = document;

    var api = {

    };

    /*----------------------------------------------------------------------------------------------------------------*/

    // Pair of functions taken from Peter Michaux's article:
    // http://peter.michaux.ca/articles/feature-detection-state-of-the-art-browser-scripting
    function isHostMethod(object, property) {
        var t = typeof object[property];
        return t === "function" || (!!(t === "object" && object[property])) || t === "unknown";
    }

    function isHostObject(object, property) {
        return !!(typeof(object[property]) === "object" && object[property]);
    }

    // Next pair of functions are a convenience to save verbose repeated calls to previous two functions
    function areHostMethods(object, properties) {
        for (var i = properties.length; i--; ) {
            if (!isHostMethod(object, properties[i])) {
                return false;
            }
        }
        return true;
    }

    function areHostObjects(object, properties) {
        for (var i = properties.length; i--; ) {
            if (!isHostObject(object, properties[i])) {
                return false;
            }
        }
        return true;
    }

    // Test for the Range/TextRange and Selection features required
    // Test for ability to retrieve selection
    if (isHostMethod(win, "getSelection")) {
        getSelection = function() { return win.getSelection(); };
    } else if (isHostObject(doc, "selection")) {
        getSelection = function() { return doc.selection; };
    }

    if (getSelection) {
        api.getSelection = getSelection;

        // Test creation of ranges
        if ( isHostMethod(doc, "createRange") ) {
            createRange = function() { return doc.createRange(); };
        } else if ( isHostMethod(doc.body, "createTextRange") ) {
            createRange = function() { return doc.body.createTextRange(); };
        }

        if (createRange) {
            api.createRange = createRange;

            // Test for ability to create a range from a selection
            createSelectionInfo = function(range, isDomRange) {
                return {
                    range: range,
                    isDomRange: isDomRange
                };
            };

            testSelection = getSelection();
            testRange = createRange();

            if ( isHostMethod(testSelection, "getRangeAt") ) {
                getSelectionInfo = function(selection) {
                    var range = (selection.rangeCount === 0) ? null : selection.getRangeAt(0);
                    return createSelectionInfo(range, true);
                };
            } else if ( isHostMethod(testSelection, "createRange") ) {
                getSelectionInfo = function(selection) {
                    var textRange = selection.createRange();
                    return createSelectionInfo(textRange, false);
                };
            } else if ( areHostObjects(testSelection,
                    ["anchorNode", "focusNode", "anchorOffset", "focusOffset", "isCollapsed"])
                    && createRange && isHostObject(createRange(), "collapsed") ) {

                // Old WebKit
                getSelectionInfo = function(selection) {
                    var range = doc.createRange();
                    range.setStart(selection.anchorNode, selection.anchorOffset);
                    range.setEnd(selection.focusNode, selection.focusOffset);

                    // Handle the case when the selection was selected backwards (from the end to the start in the
                    // document)
                    if (range.collapsed !== selection.isCollapsed) {
                        range.setStart(selection.focusNode, selection.focusOffset);
                        range.setEnd(selection.anchorNode, selection.anchorOffset);
                    }

                    return createSelectionInfo(range, true);
                };
            }

            if (getSelectionInfo) {
                api.getSelectionInfo = getSelectionInfo;
            }

            // Test selection of ranges
            if ( areHostMethods(testSelection, ["removeAllRanges", "addRange"]) ) {
                selectRange = function(selection, range) {
                    selection.removeAllRanges();
                    selection.addRange(range);
                };
            } else if ( isHostMethod(testSelection, ["empty"]) && isHostMethod(testRange, ["select"]) ) {
                selectRange = function(selection, range) {
                    selection.empty();
                    range.select();
                };
            }

            if (selectRange) {
                api.selectRange = selectRange;

                // Create the save and restore API

                // Test document for DOM methods
                if ( areHostMethods(doc, ["getElementById", "createElement", "createTextNode"]) ) {
                    testNode = doc.createElement("span");

                    // Test DOM node for required methods
                    if ( areHostMethods(testNode, ["appendChild", "removeChild"]) ) {

                        // Test Range/TextRange has required methods
                        if ( areHostMethods(testRange, ["collapse", "insertNode", "setStartAfter", "setEndBefore", "cloneRange", "detach"])
                                || areHostMethods(testRange, ["collapse", "pasteHTML", "setEndPoint", "moveToElementText", "duplicate"]) ) {

                            insertRangeBoundaryMarker = function(selectionInfo, atStart) {
                                var markerId = "selectionBoundary_" + new Date().getTime() + "_" + Math.random().toString().substr(2);
                                var range, markerEl;

                                if (selectionInfo.isDomRange) {
                                    // Clone the Range and collapse to the appropriate boundary point
                                    range = selectionInfo.range.cloneRange();
                                    range.collapse(atStart);

                                    // Create the marker element containing a single invisible character using DOM methods and insert it
                                    markerEl = doc.createElement("span");
                                    markerEl.id = markerId;
                                    markerEl.appendChild( doc.createTextNode(markerTextChar) );
                                    range.insertNode(markerEl);

                                    // Make sure the current range boundary is preserved
                                    selectionInfo.range[atStart ? "setStartAfter" : "setEndBefore"](markerEl);

                                    range.detach();
                                } else {
                                    // Clone the TextRange and collapse to the appropriate boundary point
                                    range = selectionInfo.range.duplicate();
                                    range.collapse(atStart);

                                    // Create the marker element containing a single invisible character by creating literal HTML and insert it
                                    range.pasteHTML('' + markerTextCharEntity + '');
                                    markerEl = doc.getElementById(markerId);

                                    // Make sure the current range boundary is preserved
                                    range.moveToElementText(markerEl);
                                    selectionInfo.range.setEndPoint(atStart ? "StartToEnd" : "EndToStart", range);
                                }

                                return markerId;
                            };

                            setRangeBoundary = function(range, markerId, isDomRange, atStart) {
                                var markerEl = doc.getElementById(markerId);
                                var tempRange;

                                if (isDomRange) {
                                    range[atStart ? "setStartAfter" : "setEndBefore"](markerEl);
                                } else {
                                    tempRange = range.duplicate();
                                    tempRange.moveToElementText(markerEl);
                                    range.setEndPoint(atStart ? "StartToEnd" : "EndToStart", tempRange);
                                }

                                // Remove the marker element
                                markerEl.parentNode.removeChild(markerEl);
                            };

                            api.removeMarkerElement = function(markerId) {
                                var markerEl = doc.getElementById(markerId);
                                markerEl.parentNode.removeChild(markerEl);
                            };

                            api.saveSelection = function() {
                                var selectionInfo = getSelectionInfo( getSelection() );
                                var savedSelection = {
                                    startMarkerId: insertRangeBoundaryMarker(selectionInfo, true),
                                    endMarkerId: insertRangeBoundaryMarker(selectionInfo, false),
                                    isDomRange: selectionInfo.isDomRange
                                };

                                // Ensure current selection is unaffected
                                selectRange( getSelection(), selectionInfo.range );

                                return savedSelection;
                            };

                            api.restoreSelection = function(savedSelection) {
                                var range = createRange();
                                setRangeBoundary(range, savedSelection.startMarkerId, savedSelection.isDomRange, true);
                                setRangeBoundary(range, savedSelection.endMarkerId, savedSelection.isDomRange, false);

                                // Select the range
                                selectRange( getSelection(), range );
                            };

                            api.removeMarkers = function(savedSelection) {
                                removeMarkerElement(savedSelection.startMarkerId);
                                removeMarkerElement(savedSelection.endMarkerId);
                            };

                            api.saveRestoreSupported = true;
                        }
                    }
                }
            }
        }
    }

    return api;
})();<|endoftext|>


<commit_before>const electron = require('electron');
var ipcRenderer = require('electron').ipcRenderer;
var remote = require("remote");

var _ = require('lodash');
var expandHomeDir = require('expand-home-dir')
var fs = require('fs-extra');
var gm = require('gm'); // GraphicsMagick
var path = require('path');
var wrench = require('wrench');

var config = require('../config.json');
var logger = require('../lib/logger');

// read in the configuration details to get the base paths
var ssDir = expandHomeDir(config.slideshowDirectory),
	sdMP = expandHomeDir(config.sdCardMountPoint);

// figure out the SD card's name
var sdCardName = getSDCardName(),
	sdCardPath;
if (!sdCardName) {
	console.log("No SD card present at " + sdMP);
	ipcRenderer.send('close-import-window');
}
sdCardPath = path.join(config.sdCardMountPoint, sdCardName).replace(/(["\s'$`\\])/g, '\\$1');

var message = document.getElementById('message');

document.getElementById('cancel').addEventListener('click', function (e) {
	ipcRenderer.send('close-import-window');
});

document.getElementById('ok').addEventListener('click', function (e) {
	fs.ensureDirSync(ssDir);
	var photoPath, photosToCopy = [];
	try {
		// see if there's a DCIM path
		if (fs.existsSync(path.join(sdMP, 'DCIM'))) {
			console.log('DCIM directory present, adding it to the base path');
			photoPath = path.join(sdMP, 'DCIM');
		}
	} catch (err) {
		// either sdCardMountPoint doesn't exist (but we tested for that in index.js)
		// or we don't have read access to it
		console.log(err);
		photoPath = sdMP;
	}
	console.log('Our source path is: ' + photoPath);
	_.each(wrench.readdirSyncRecursive(photoPath), function (file) {
		// build the list of files to copy
		var f = file.toLowerCase(),
			fqname = path.join(photoPath, file);
		if ((path.extname(f) === '.jpg' || path.extname(f) === '.jpg') && path.basename(f).charAt(0) !== '.') {
			// copy only JPG files but not those that begin with '.' (hidden/special files)
			console.log('Will copy: ' + fqname);
			photosToCopy.push(fqname);
		}
	});
	if (photosToCopy.length > 0) {
		// now, actually copy them
		_.each(photosToCopy, function (fileToCopy) {
			console.log('Copying: ' + fileToCopy);
			fs.copySync(fileToCopy, ssDir, {
				clobber: false
			});
		});

		alert("Copied " + photosToCopy.length + " photos to " + config.slideshowDirectory);
		ipcRenderer.send('close-import-window');
	} else {
		alert("No photos found to copy.");
	}

});

document.addEventListener("keydown", function (e) {
	if (e.keyCode === 123) { // F12
		var window = remote.getCurrentWindow();
		window.toggleDevTools();
	}
});

function getSDCardName() {
	if (config.cameraCardName && fs.existsSync(path.join(config.sdCardMountPoint, config.cameraCardName))) {
		// if user has defined a camera card name and it exists, return it
		return config.cameraCardName;
	}
	var possibleSDCards = fs.readdirSync(config.sdCardMountPoint);
	if (!possibleSDCards || possibleSDCards.length === 0) {
		alert('No SD card inserted');
		return false;
	} else if (possibleSDCards.length > 1) {
		alert('Only one camera card can be inserted at a time.');
		return false;
	} else {
		return possibleSDCards[0];
	}
}<commit_msg>fixes<commit_after>const electron = require('electron');
var ipcRenderer = require('electron').ipcRenderer;
var remote = require("remote");

var _ = require('lodash');
var expandHomeDir = require('expand-home-dir')
var fs = require('fs-extra');
var gm = require('gm'); // GraphicsMagick
var path = require('path');
var wrench = require('wrench');

var config = require('../config.json');
var logger = require('../lib/logger');

// read in the configuration details to get the base paths
var ssDir = expandHomeDir(config.slideshowDirectory),
	sdMP = expandHomeDir(config.sdCardMountPoint);

console.log('ssDir: ' + ssDir + ' exists: ' + fs.existsSync(ssDir));
console.log('sdMP: ' + sdMP + ' exists: ' + fs.existsSync(sdMP));

// figure out the SD card's name
var sdCardName = getSDCardName(),
	sdCardPath;
if (!sdCardName) {
	console.log("No SD card present at " + sdMP);
	ipcRenderer.send('close-import-window');
}
sdCardPath = path.join(sdMP, sdCardName).replace(/(["\s'$`\\])/g, '\\$1');

var message = document.getElementById('message');

document.getElementById('cancel').addEventListener('click', function (e) {
	ipcRenderer.send('close-import-window');
});

document.getElementById('ok').addEventListener('click', function (e) {
	fs.ensureDirSync(ssDir);
	var photoPath, photosToCopy = [];
	try {
		// see if there's a DCIM path
		if (fs.existsSync(path.join(sdCardPath, 'DCIM'))) {
			console.log('DCIM directory present, adding it to the base path');
			photoPath = path.join(sdCardPath, 'DCIM');
		}
	} catch (err) {
		// either sdCardMountPoint doesn't exist (but we tested for that in index.js)
		// or we don't have read access to it
		console.log(err);
		photoPath = sdCardPath;
	}
	console.log('Our source path is: ' + photoPath);
	_.each(wrench.readdirSyncRecursive(photoPath), function (file) {
		// build the list of files to copy
		var f = file.toLowerCase(),
			fqname = path.join(photoPath, file);
		if ((path.extname(f) === '.jpg' || path.extname(f) === '.jpg') && path.basename(f).charAt(0) !== '.') {
			// copy only JPG files but not those that begin with '.' (hidden/special files)
			console.log('Will copy: ' + fqname);
			photosToCopy.push(fqname);
		}
	});
	if (photosToCopy.length > 0) {
		// now, actually copy them
		_.each(photosToCopy, function (fileToCopy) {
			console.log('Copying: ' + fileToCopy);
			fs.copySync(fileToCopy, ssDir, {
				clobber: false
			});
		});

		alert("Copied " + photosToCopy.length + " photos to " + config.slideshowDirectory);
		ipcRenderer.send('close-import-window');
	} else {
		alert("No photos found to copy.");
	}

});

document.addEventListener("keydown", function (e) {
	if (e.keyCode === 123) { // F12
		var window = remote.getCurrentWindow();
		window.toggleDevTools();
	}
});

function getSDCardName() {
	if (config.cameraCardName && fs.existsSync(path.join(config.sdCardMountPoint, config.cameraCardName))) {
		// if user has defined a camera card name and it exists, return it
		return config.cameraCardName;
	}
	var possibleSDCards = fs.readdirSync(config.sdCardMountPoint);
	if (!possibleSDCards || possibleSDCards.length === 0) {
		alert('No SD card inserted');
		return false;
	} else if (possibleSDCards.length > 1) {
		alert('Only one camera card can be inserted at a time.');
		return false;
	} else {
		return possibleSDCards[0];
	}
}<|endoftext|>


<commit_before>/**
 * Copyright 2017 Red Hat Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may
 * not use this file except in compliance with the License. You may obtain
 * a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations
 * under the License.
 */

import { applyMiddleware, createStore } from 'redux';
import cookie from 'react-cookie';
import { fromJS } from 'immutable';
import thunkMiddleware from 'redux-thunk';
import { createLogger } from 'redux-logger';
import logger, { predicate } from './services/logging/LoggingService';

import { AppConfig } from './immutableRecords/appConfig';
import appReducer from './reducers/appReducer';
import { InitialPlanState } from './immutableRecords/plans';
import { InitialLoginState } from './immutableRecords/login';
import { getIntl } from './selectors/i18n';

const hydrateStore = () => {
  // VERSION and GITSHA are populated by webpack
  window.tripleOUiConfig.version = VERSION;
  window.tripleOUiConfig.gitSha = GITSHA;

  return {
    appConfig: new AppConfig(window && fromJS(window.tripleOUiConfig)),
    plans: new InitialPlanState({
      currentPlanName: getStoredPlanName()
    }),
    login: new InitialLoginState({
      tokenId: cookie.load('keystoneAuthTokenId')
    })
  };
};

function getStoredPlanName() {
  if (window && window.localStorage) {
    return window.localStorage.getItem('currentPlanName');
  }
}

const loggerMiddleware = createLogger({
  collapsed: true,
  predicate: predicate,
  logger: logger,
  // We're turning off all colors here because the formatting chars obscure the
  // content server-side.
  colors: false
});

const store = createStore(
  appReducer,
  hydrateStore(),
  applyMiddleware(
    thunkMiddleware.withExtraArgument({ getIntl }),
    loggerMiddleware
  )
);

logger.setReduxDispatch(store.dispatch);

export default store;
<commit_msg>Integrate redux-devtools Chrome extension<commit_after>/**
 * Copyright 2017 Red Hat Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may
 * not use this file except in compliance with the License. You may obtain
 * a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations
 * under the License.
 */

import { applyMiddleware, createStore, compose } from 'redux';
import cookie from 'react-cookie';
import { fromJS } from 'immutable';
import thunkMiddleware from 'redux-thunk';
import { createLogger } from 'redux-logger';
import logger, { predicate } from './services/logging/LoggingService';

import { AppConfig } from './immutableRecords/appConfig';
import appReducer from './reducers/appReducer';
import { InitialPlanState } from './immutableRecords/plans';
import { InitialLoginState } from './immutableRecords/login';
import { getIntl } from './selectors/i18n';

const hydrateStore = () => {
  // VERSION and GITSHA are populated by webpack
  window.tripleOUiConfig.version = VERSION;
  window.tripleOUiConfig.gitSha = GITSHA;

  return {
    appConfig: new AppConfig(window && fromJS(window.tripleOUiConfig)),
    plans: new InitialPlanState({
      currentPlanName: getStoredPlanName()
    }),
    login: new InitialLoginState({
      tokenId: cookie.load('keystoneAuthTokenId')
    })
  };
};

function getStoredPlanName() {
  if (window && window.localStorage) {
    return window.localStorage.getItem('currentPlanName');
  }
}

const loggerMiddleware = createLogger({
  collapsed: true,
  predicate: predicate,
  logger: logger,
  // We're turning off all colors here because the formatting chars obscure the
  // content server-side.
  colors: false
});

// Integrate redux-devtools Chrome extension
const composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose;

const store = createStore(
  appReducer,
  hydrateStore(),
  composeEnhancers(
    applyMiddleware(
      thunkMiddleware.withExtraArgument({ getIntl }),
      loggerMiddleware
    )
  )
);

logger.setReduxDispatch(store.dispatch);

export default store;
<|endoftext|>