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

const chromeModule  = require("chrome"),
      classes       = chromeModule.Cc,
      interfaces    = chromeModule.Ci,
      utilities     = chromeModule.Cu,
      pageMod       = require("sdk/page-mod"),
      data          = require("sdk/self").data,
      simplePrefs   = require("sdk/simple-prefs"),
      spellchecker  = classes["@mozilla.org/spellchecker/engine;1"].getService(interfaces.mozISpellCheckingEngine),
      tabs          = require("sdk/tabs");

let parsedDictionaries,
    preferenceList,
    availableDictionaries,
    appLocale;

utilities.import("resource://gre/modules/Services.jsm");

// TODO: There should be a better way to get the app locale
appLocale = Services.locale.getApplicationLocale().getCategory("NSILOCALE_MESSAGES");

function LanguageElement(code, isPreferred)
{
    this.code        = code;
    this.isPreferred = isPreferred;
}

function getPreferences()
{
    // See https://developer.mozilla.org/en-US/Add-ons/SDK/High-Level_APIs/simple-prefs#prefs
    // See package.json
    // The preferences object has a property name for each language with the value set to the dialect
    // selected by the user, or a dash (-) if the user doesn't want to detect the language. Example object may be
    // { "en": "en-NZ", "de": "de-LU", "ar": "-" }
    return simplePrefs.prefs;
}

// this function will parse the available dictionaries and will categorise them on the basis of the language names.
function parseAvailableDictionaries()
{
    const userPreferences = getPreferences();
    const dictionaries = {};

    for(let i = 0; i < availableDictionaries.length; i++)
    {
        // This is the code of the dictionary as is returned from the Mozilla spell checking service. Example codes are:
        // en, fr-FR, ja, de-LU
        const dialect = availableDictionaries[i];

        // This is the language code only. If we have a dictionary code of -for example- de-LU, we split it and store the
        // language code de in this variable:
        let language,
            // The index of the dash character (-) in the language code (ex for en-US this will be 2)
            dashIndex;

        // This is the case when we have a generic language with no country code (dialect) specified. For example:
        // en, fr, js, etc.
        if((dashIndex = dialect.indexOf("-")) < 0)
            language = dialect;
        else
        {
            // This is the case when we have both language and country codes, such as en-GB, de-LU
            // We split the language code into the language variable
            language = dialect.substr(0, dashIndex);
        }

        if(!dictionaries[language])
            dictionaries[language] = [];

        dictionaries[language].push(new LanguageElement(dialect, userPreferences[language] == dialect));
    }

    return dictionaries;
}

function initializeDictPreference()
{
    const dictArrayContainer       = {},
          dictArrayLengthContainer = {};

    spellchecker.getDictionaryList(dictArrayContainer, dictArrayLengthContainer);

    availableDictionaries = dictArrayContainer.value;

    parsedDictionaries = parseAvailableDictionaries();
}

// This function will be responsible for setting up the dictionary
function changeDictionary(language)
{
    // Exit if the script failed to detect the language, or the user chose to not detect the language
    if(!language)
        return;

    const languageData = parsedDictionaries[language];

    // If the language detection library detected a language for which the user has no dictionary (because of a
    // fault of the library or because the user input some gibberish in some foreign language) we set spell checking
    // language to an empty string and let Firefox select the default dictionary
    let dictionary;
    if(!languageData)
        dictionary = "";
    else
    {
        const preferredDictionary = languageData.find(function (dict)
        {
            return dict.isPreferred;
        });

        // If we find a preferred dictionary (as per what the user configured) use it, otherwise, use the first
        // dictionary in the list for this language
        if(preferredDictionary)
            dictionary = preferredDictionary.code;
        else
            dictionary = languageData[0].code;  // TODO: we need a better default that works for most people
    }

    spellchecker.dictionary = dictionary;

    const feedbackData = {
        language: null,
        message: null,
        isWarning: false
    };

    // TODO: Use friendly languages names
    if(dictionary)
    {
        feedbackData.language = dictionary;
        feedbackData.message = "Detected " + dictionary;
    }
    else
    {
        feedbackData.language = language;
        feedbackData.message = "Detected " + language + " but didn't find suitable dictionary";
        feedbackData.isWarning = true;
    }

    // Inform the content script about our findings so that it shows the proper message to user
    this.emit("feedback", feedbackData);
}

function initialize(options)
{
    // add the script to all pages that will be responsible for detecting the language
    pageMod.PageMod({
        include: [
            "http://*",
            "https://*",
            "file://*"
        ],
        contentScriptWhen: "end",
        contentStyleFile: [
            data.url("ui/content.css")
        ],
        contentScriptFile: [
            data.url("js/franc-most.js"),
            data.url("js/iso6393.js"),
            data.url("js/contentScript.js")
        ],
        onAttach: function (worker)
        {
            // The changeDictionary message will be sent to the main script when the user interaction with a page
            // element triggers language detection which in turn requests setting the dictionary name
            worker.port.on("changeDictionary", changeDictionary);

            function refreshSettings()
            {
                // Send the user preferences to the content script. Read the comment about the subject in contentScript.js
                worker.port.emit("config", getPreferences());
            }

            refreshSettings();

            // Every time the settings are modified, send a fresh copy of them to the current content script, so
            // that settings are never stale and the user needn't refresh the page for them to be current.
            simplePrefs.on("", refreshSettings);

            // When the tab is closed, remove the previously added event handlers from the simplePrefs module's
            // list so that dead handlers are cleaned up
            worker.tab.on("close", function ()
            {
                simplePrefs.off("", refreshSettings);
            });
        }
    });

    initializeDictPreference();

    // Every time the user changes a configuration, re-read the configurations and refresh the parsedDictionaries
    // object with what the user chose
    simplePrefs.on("", function ()
    {
        const userPreferences = getPreferences();

        for(let i in userPreferences)
        {
            if(parsedDictionaries[i])
            {
                parsedDictionaries[i].forEach(function (dictElement)
                {
                    /// <param name="dictElement" type="LanguageElement"></param>
                    dictElement.isPreferred = dictElement.code == userPreferences[i];
                });
            }
        }
    });
}

exports.main = function (options, callbacks)
{
    // First run of the addon
    if(options.loadReason == "install")
    {
        // The index of the dash character (-) in the language code (ex for en-US this will be 2)
        const dashIndex = appLocale.indexOf("-");
        const appLanguage = dashIndex >= 0 ? appLocale.substr(0, dashIndex) : appLocale;

        // If the user's browser isn't running with one of the default languages we support, set
        // the language it uses as an additional language so it gets detected without
        // the user visiting configuration:
        var longCode;
        switch (appLanguage) {
            // TODO: support all but the first 20 languages from https://github.com/wooorm/franc/blob/master/Supported-Languages.md
            // How to use iso6393.js here?
            case "ur": longCode = "urd"; break;
            case "gu": longCode = "guj"; break;
            case "pl": longCode = "pol"; break;
            case "uk": longCode = "ukr"; break;
            case "ml": longCode = "mal"; break;
            case "nl": longCode = "nld"; break;
        }
        if (longCode) {
            simplePrefs.prefs["additionalLanguage1"] = longCode;
        }

        // if the user's browser is running in e.g. en-GB, we assume they
        // want en-GB as their language (and not e.g. en-US):
        if(simplePrefs.prefs[appLanguage])
            simplePrefs.prefs[appLanguage] = appLocale;
    }

    initialize(options);
};

// exported for tests:
exports.initializeDictPreference = initializeDictPreference;
exports.parseAvailableDictionaries = parseAvailableDictionaries;
<commit_msg>improve detection on focus after page load: with setTimeout it works better now, but still not 100% fixed<commit_after>//   Automatic Dictionary Switcher Add-on for Firefox
//   Copyright 2015 Daniel Naber
//
//   Licensed under the Apache License, Version 2.0 (the "License");
//   you may not use this file except in compliance with the License.
//   You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
//   Unless required by applicable law or agreed to in writing, software
//   distributed under the License is distributed on an "AS IS" BASIS,
//   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//   See the License for the specific language governing permissions and
//   limitations under the License.

const chromeModule  = require("chrome"),
      classes       = chromeModule.Cc,
      interfaces    = chromeModule.Ci,
      utilities     = chromeModule.Cu,
      pageMod       = require("sdk/page-mod"),
      data          = require("sdk/self").data,
      simplePrefs   = require("sdk/simple-prefs"),
      spellchecker  = classes["@mozilla.org/spellchecker/engine;1"].getService(interfaces.mozISpellCheckingEngine),
      tabs          = require("sdk/tabs");

let parsedDictionaries,
    preferenceList,
    availableDictionaries,
    appLocale;

utilities.import("resource://gre/modules/Services.jsm");

// TODO: There should be a better way to get the app locale
appLocale = Services.locale.getApplicationLocale().getCategory("NSILOCALE_MESSAGES");

function LanguageElement(code, isPreferred)
{
    this.code        = code;
    this.isPreferred = isPreferred;
}

function getPreferences()
{
    // See https://developer.mozilla.org/en-US/Add-ons/SDK/High-Level_APIs/simple-prefs#prefs
    // See package.json
    // The preferences object has a property name for each language with the value set to the dialect
    // selected by the user, or a dash (-) if the user doesn't want to detect the language. Example object may be
    // { "en": "en-NZ", "de": "de-LU", "ar": "-" }
    return simplePrefs.prefs;
}

// this function will parse the available dictionaries and will categorise them on the basis of the language names.
function parseAvailableDictionaries()
{
    const userPreferences = getPreferences();
    const dictionaries = {};

    for(let i = 0; i < availableDictionaries.length; i++)
    {
        // This is the code of the dictionary as is returned from the Mozilla spell checking service. Example codes are:
        // en, fr-FR, ja, de-LU
        const dialect = availableDictionaries[i];

        // This is the language code only. If we have a dictionary code of -for example- de-LU, we split it and store the
        // language code de in this variable:
        let language,
            // The index of the dash character (-) in the language code (ex for en-US this will be 2)
            dashIndex;

        // This is the case when we have a generic language with no country code (dialect) specified. For example:
        // en, fr, js, etc.
        if((dashIndex = dialect.indexOf("-")) < 0)
            language = dialect;
        else
        {
            // This is the case when we have both language and country codes, such as en-GB, de-LU
            // We split the language code into the language variable
            language = dialect.substr(0, dashIndex);
        }

        if(!dictionaries[language])
            dictionaries[language] = [];

        dictionaries[language].push(new LanguageElement(dialect, userPreferences[language] == dialect));
    }

    return dictionaries;
}

function initializeDictPreference()
{
    const dictArrayContainer       = {},
          dictArrayLengthContainer = {};

    spellchecker.getDictionaryList(dictArrayContainer, dictArrayLengthContainer);

    availableDictionaries = dictArrayContainer.value;

    parsedDictionaries = parseAvailableDictionaries();
}

// This function will be responsible for setting up the dictionary
function changeDictionary(language)
{
    // Exit if the script failed to detect the language, or the user chose to not detect the language
    if(!language)
        return;

    const languageData = parsedDictionaries[language];

    // If the language detection library detected a language for which the user has no dictionary (because of a
    // fault of the library or because the user input some gibberish in some foreign language) we set spell checking
    // language to an empty string and let Firefox select the default dictionary
    let dictionary;
    if(!languageData)
        dictionary = "";
    else
    {
        const preferredDictionary = languageData.find(function (dict)
        {
            return dict.isPreferred;
        });

        // If we find a preferred dictionary (as per what the user configured) use it, otherwise, use the first
        // dictionary in the list for this language
        if(preferredDictionary)
            dictionary = preferredDictionary.code;
        else
            dictionary = languageData[0].code;  // TODO: we need a better default that works for most people
    }

    // focus into textarea after page load sometimes doesn't set the spell dictionary
    // properly (even though detection works), this helps but doesn't fix it completely (issue #7):
    var { setTimeout } = require("sdk/timers");
    setTimeout(function() {spellchecker.dictionary = dictionary;}, 10);

    const feedbackData = {
        language: null,
        message: null,
        isWarning: false
    };

    // TODO: Use friendly languages names
    if(dictionary)
    {
        feedbackData.language = dictionary;
        feedbackData.message = "Detected " + dictionary;
    }
    else
    {
        feedbackData.language = language;
        feedbackData.message = "Detected " + language + " but didn't find suitable dictionary";
        feedbackData.isWarning = true;
    }

    // Inform the content script about our findings so that it shows the proper message to user
    this.emit("feedback", feedbackData);
}

function initialize(options)
{
    // add the script to all pages that will be responsible for detecting the language
    pageMod.PageMod({
        include: [
            "http://*",
            "https://*",
            "file://*"
        ],
        contentScriptWhen: "end",
        contentStyleFile: [
            data.url("ui/content.css")
        ],
        contentScriptFile: [
            data.url("js/franc-most.js"),
            data.url("js/iso6393.js"),
            data.url("js/contentScript.js")
        ],
        onAttach: function (worker)
        {
            // The changeDictionary message will be sent to the main script when the user interaction with a page
            // element triggers language detection which in turn requests setting the dictionary name
            worker.port.on("changeDictionary", changeDictionary);

            function refreshSettings()
            {
                // Send the user preferences to the content script. Read the comment about the subject in contentScript.js
                worker.port.emit("config", getPreferences());
            }

            refreshSettings();

            // Every time the settings are modified, send a fresh copy of them to the current content script, so
            // that settings are never stale and the user needn't refresh the page for them to be current.
            simplePrefs.on("", refreshSettings);

            // When the tab is closed, remove the previously added event handlers from the simplePrefs module's
            // list so that dead handlers are cleaned up
            worker.tab.on("close", function ()
            {
                simplePrefs.off("", refreshSettings);
            });
        }
    });

    initializeDictPreference();

    // Every time the user changes a configuration, re-read the configurations and refresh the parsedDictionaries
    // object with what the user chose
    simplePrefs.on("", function ()
    {
        const userPreferences = getPreferences();

        for(let i in userPreferences)
        {
            if(parsedDictionaries[i])
            {
                parsedDictionaries[i].forEach(function (dictElement)
                {
                    /// <param name="dictElement" type="LanguageElement"></param>
                    dictElement.isPreferred = dictElement.code == userPreferences[i];
                });
            }
        }
    });
}

exports.main = function (options, callbacks)
{
    // First run of the addon
    if(options.loadReason == "install")
    {
        // The index of the dash character (-) in the language code (ex for en-US this will be 2)
        const dashIndex = appLocale.indexOf("-");
        const appLanguage = dashIndex >= 0 ? appLocale.substr(0, dashIndex) : appLocale;

        // If the user's browser isn't running with one of the default languages we support, set
        // the language it uses as an additional language so it gets detected without
        // the user visiting configuration:
        var longCode;
        switch (appLanguage) {
            // TODO: support all but the first 20 languages from https://github.com/wooorm/franc/blob/master/Supported-Languages.md
            // How to use iso6393.js here?
            case "ur": longCode = "urd"; break;
            case "gu": longCode = "guj"; break;
            case "pl": longCode = "pol"; break;
            case "uk": longCode = "ukr"; break;
            case "ml": longCode = "mal"; break;
            case "nl": longCode = "nld"; break;
        }
        if (longCode) {
            simplePrefs.prefs["additionalLanguage1"] = longCode;
        }

        // if the user's browser is running in e.g. en-GB, we assume they
        // want en-GB as their language (and not e.g. en-US):
        if(simplePrefs.prefs[appLanguage])
            simplePrefs.prefs[appLanguage] = appLocale;
    }

    initialize(options);
};

// exported for tests:
exports.initializeDictPreference = initializeDictPreference;
exports.parseAvailableDictionaries = parseAvailableDictionaries;
<|endoftext|>


<commit_before>const fs = require('fs')
const path = require('path')
const imagemin = require('imagemin')
const imageminMozjpeg = require('imagemin-mozjpeg')
const imageminPngquant = require('imagemin-pngquant')

// dom elements

const $fileList = document.querySelector('.file-list')
const $queue = document.querySelector('.js-queue')
const $totalImagesOptimized = document.querySelector('.js-total-images-optimized')
const $totalSavings = document.querySelector('.js-total-savings')
const $openSettingsButton = document.querySelector('.open-settings-button')
const $settings = document.querySelector('.settings')
const $settingsCloseButton = document.querySelector('.settings-close-button')
const $settingsInputDestination = document.querySelector('.settings-input-destination')
const $settingsInputQuality = document.querySelector('.settings-input-quality')
const $settingsLabelQuality = document.querySelector('.settings-label-quality')
const $settingsInputConcurrentOptimizations = document.querySelector('.settings-input-concurrent-optimizations')
const $settingsLabelConcurrentOptimizations = document.querySelector('.settings-label-concurrent-optimizations')

let options = {
  dest: '',
  maxConcurrentOptimizations: 20,
  quality: 75
}
let fileQueue = []
let activeOptimizations = 0
let totalImagesOptimized = 0
let totalSavings = 0

// add handlers to dom elements

document.addEventListener('dragenter', handleDragEnter)
document.addEventListener('dragleave', handleDragLeave)
document.addEventListener('dragover', handleDragOver)
document.addEventListener('drop', handleDrop)
document.addEventListener('drop', showFileList)
$settingsCloseButton.addEventListener('click', closeSettings)
$openSettingsButton.addEventListener('click', openSettings)
$settingsCloseButton.addEventListener('click', closeSettings)
$openSettingsButton.addEventListener('click', openSettings)
$settingsInputDestination.addEventListener('change', handleDestinationChange)
$settingsInputQuality.addEventListener('change', handleQualityChange)
$settingsInputConcurrentOptimizations.addEventListener('change', handleConcurrentOptimizationsChange)

// optimize images in the queue on a set interval
setInterval(function() {

  // if queue is not empty
  // and max concurrent optimizations have not been reached
  // optimize the next image in the queue
  if (fileQueue.length !== 0 && activeOptimizations < options.maxConcurrentOptimizations) {
    optimizeImage(fileQueue.shift(), options.dest)

    // update footer notes
    $queue.textContent = fileQueue.length
    $totalImagesOptimized.textContent = totalImagesOptimized
    $totalSavings.textContent = displaySize(totalSavings)
  }

}, 300)

function optimizeImage(img, dest) {

  let row = document.getElementById(img.id)
  let originalSize = img.size

  row.querySelector('.js-status').innerHTML = '👷 Working'

  activeOptimizations ++

  // if no destination specified, overwrite same file
  if (!dest) {
      dest = path.dirname(img.path)
  }

  imagemin([img.path], dest, {
    plugins: [
      imageminMozjpeg({
        quality: img.size > 150000 ? options.quality : 95
      })
    ]
  }).then(files => {
    let optimizedFile = files[0]

    fs.stat(optimizedFile.path, function updateFileListItem(err, stats) {
      if (err) throw err

      let savings = originalSize - stats.size

      row.querySelector('.js-status').innerHTML = '✔ Optimized'
      row.querySelector('.js-optimized').innerHTML = displaySize(stats.size)
      row.querySelector('.js-savings').innerHTML = ( savings / originalSize * 100 ).toFixed(1) + '%'

      totalSavings += savings
      totalImagesOptimized ++
      activeOptimizations --
    })

  })

}

// handlers for drag and drop events

function handleDragEnter(e) {
  e.preventDefault()
  e.stopPropagation()
  document.body.classList.add('is-drag-over')
  return false
}

function handleDragLeave(e) {
  e.preventDefault()
  e.stopPropagation()
  document.body.classList.remove('is-drag-over')
  return false
}

function handleDragOver(e) {
  e.preventDefault()
  e.stopPropagation()
  document.body.classList.add('is-drag-over')
  return false
}

function handleDrop(e) {
  e.preventDefault()
  e.stopPropagation()

  const droppedFiles = e.dataTransfer.files

  document.body.classList.remove('is-drag-over')

  for (let i = 0; i < droppedFiles.length; i++) {

    let file = droppedFiles[i]

    // check if file dropped is jpg
    if (path.extname(file.name).toLowerCase() === '.jpg') {

      file.id = generateId()

      insertRow(file.id, file.path, file.name, displaySize(file.size), $fileList)

      fileQueue.push(file)

    }

    else if(file.type === '') {

      findImagesInDir(file.path)

    }
  }

  return false
}

function showFileList() {
  $fileList.classList.remove('is-transparent')
  document.removeEventListener('drop', showFileList)
}

function findImagesInDir(dirPath) {

  // find all files in directory
  fs.readdir(dirPath, (err, files) => {
    if (err) throw err

    // for each file
    files.forEach(file => {

      // check if file is file or another directory
      fs.stat(path.join(dirPath, file), (err, stats) => {
        if (err) throw err

        // if it's a jpeg file, add it to the file queue to optimize
        if (stats.isFile()) {

          if (path.extname(file).toLowerCase() === '.jpg') {

            // create an img object with all the data needed for optimizing
            let img = {
              id: generateId(),
              path: path.join(dirPath, file),
              size: stats.size
            }

            // insert a row in the file list
            insertRow(img.id, img.path, file, displaySize(img.size), $fileList)

            // add the image to the queue for optimizing
            fileQueue.push(img)
          }
        }
        // if it's a directory, recursively find files in it
        else if (stats.isDirectory()) {

          findImagesInDir(path.join(dirPath, file))

        }
      })

    })
  })
}

function insertRow(fileId, filePath, fileName, fileSize, fileList) {

  let row = document.createElement('tr')

  row.id = fileId
  row.className = 'file-item'
  row.innerHTML =
   `
      ${fileName}

    ⏳ Pending
    ${fileSize}

    	`

  $fileList.insertBefore(row, null)
}

// handlers for settings menu actions

function openSettings() {
  $settings.showModal()
  $settings.classList.add('is-open')
}

function closeSettings() {
  $settings.close()
  $settings.classList.remove('is-open')
}

function handleDestinationChange(e) {
  if (e.target.files[0]) {
    options.dest = e.target.files[0].path
  }
  else {
    options.dest = ''
  }
}

function handleQualityChange(e) {
  let value = e.target.value
  $settingsLabelQuality.textContent = value
  options.quality = value
}

function handleConcurrentOptimizationsChange(e) {
  let value = e.target.value
  $settingsLabelConcurrentOptimizations.textContent = e.target.value
  options.maxConcurrentOptimizations = value
}

// utils

function displaySize(bytes) {

  var kilobytes = bytes / 1024
  var megabytes = kilobytes / 1024
  var displaySize = ''

  if (megabytes > 1) {
    displaySize = megabytes.toFixed(2) + ' MB'
  } else {
    displaySize = kilobytes.toFixed(2) + ' KB'
  }

  return displaySize
}

function generateId() {
  return 'f-'+ Math.random().toString().substring(2, 9)
}<commit_msg>fix footer note updates<commit_after>const fs = require('fs')
const path = require('path')
const imagemin = require('imagemin')
const imageminMozjpeg = require('imagemin-mozjpeg')
const imageminPngquant = require('imagemin-pngquant')

// dom elements

const $fileList = document.querySelector('.file-list')
const $queue = document.querySelector('.js-queue')
const $totalImagesOptimized = document.querySelector('.js-total-images-optimized')
const $totalSavings = document.querySelector('.js-total-savings')
const $openSettingsButton = document.querySelector('.open-settings-button')
const $settings = document.querySelector('.settings')
const $settingsCloseButton = document.querySelector('.settings-close-button')
const $settingsInputDestination = document.querySelector('.settings-input-destination')
const $settingsInputQuality = document.querySelector('.settings-input-quality')
const $settingsLabelQuality = document.querySelector('.settings-label-quality')
const $settingsInputConcurrentOptimizations = document.querySelector('.settings-input-concurrent-optimizations')
const $settingsLabelConcurrentOptimizations = document.querySelector('.settings-label-concurrent-optimizations')

let options = {
  dest: '',
  maxConcurrentOptimizations: 20,
  quality: 75
}
let fileQueue = []
let activeOptimizations = 0
let totalImagesOptimized = 0
let totalSavings = 0

// add handlers to dom elements

document.addEventListener('dragenter', handleDragEnter)
document.addEventListener('dragleave', handleDragLeave)
document.addEventListener('dragover', handleDragOver)
document.addEventListener('drop', handleDrop)
document.addEventListener('drop', showFileList)
$settingsCloseButton.addEventListener('click', closeSettings)
$openSettingsButton.addEventListener('click', openSettings)
$settingsCloseButton.addEventListener('click', closeSettings)
$openSettingsButton.addEventListener('click', openSettings)
$settingsInputDestination.addEventListener('change', handleDestinationChange)
$settingsInputQuality.addEventListener('change', handleQualityChange)
$settingsInputConcurrentOptimizations.addEventListener('change', handleConcurrentOptimizationsChange)

// optimize images in the queue on a set interval
setInterval(function() {

  // if queue is not empty
  // and max concurrent optimizations have not been reached
  // optimize the next image in the queue
  if (fileQueue.length !== 0 && activeOptimizations < options.maxConcurrentOptimizations) {
    optimizeImage(fileQueue.shift(), options.dest)
  }

  // update footer notes
  $queue.textContent = fileQueue.length
  $totalImagesOptimized.textContent = totalImagesOptimized
  $totalSavings.textContent = displaySize(totalSavings)

}, 300)

function optimizeImage(img, dest) {

  let row = document.getElementById(img.id)
  let originalSize = img.size

  row.querySelector('.js-status').innerHTML = '👷 Working'

  activeOptimizations ++

  // if no destination specified, overwrite same file
  if (!dest) {
      dest = path.dirname(img.path)
  }

  imagemin([img.path], dest, {
    plugins: [
      imageminMozjpeg({
        quality: img.size > 150000 ? options.quality : 95
      })
    ]
  }).then(files => {
    let optimizedFile = files[0]

    fs.stat(optimizedFile.path, function updateFileListItem(err, stats) {
      if (err) throw err

      let savings = originalSize - stats.size

      row.querySelector('.js-status').innerHTML = '✔ Optimized'
      row.querySelector('.js-optimized').innerHTML = displaySize(stats.size)
      row.querySelector('.js-savings').innerHTML = ( savings / originalSize * 100 ).toFixed(1) + '%'

      totalSavings += savings
      totalImagesOptimized ++
      activeOptimizations --
    })

  })

}

// handlers for drag and drop events

function handleDragEnter(e) {
  e.preventDefault()
  e.stopPropagation()
  document.body.classList.add('is-drag-over')
  return false
}

function handleDragLeave(e) {
  e.preventDefault()
  e.stopPropagation()
  document.body.classList.remove('is-drag-over')
  return false
}

function handleDragOver(e) {
  e.preventDefault()
  e.stopPropagation()
  document.body.classList.add('is-drag-over')
  return false
}

function handleDrop(e) {
  e.preventDefault()
  e.stopPropagation()

  const droppedFiles = e.dataTransfer.files

  document.body.classList.remove('is-drag-over')

  for (let i = 0; i < droppedFiles.length; i++) {

    let file = droppedFiles[i]

    // check if file dropped is jpg
    if (path.extname(file.name).toLowerCase() === '.jpg') {

      file.id = generateId()

      insertRow(file.id, file.path, file.name, displaySize(file.size), $fileList)

      fileQueue.push(file)

    }

    else if(file.type === '') {

      findImagesInDir(file.path)

    }
  }

  return false
}

function showFileList() {
  $fileList.classList.remove('is-transparent')
  document.removeEventListener('drop', showFileList)
}

function findImagesInDir(dirPath) {

  // find all files in directory
  fs.readdir(dirPath, (err, files) => {
    if (err) throw err

    // for each file
    files.forEach(file => {

      // check if file is file or another directory
      fs.stat(path.join(dirPath, file), (err, stats) => {
        if (err) throw err

        // if it's a jpeg file, add it to the file queue to optimize
        if (stats.isFile()) {

          if (path.extname(file).toLowerCase() === '.jpg') {

            // create an img object with all the data needed for optimizing
            let img = {
              id: generateId(),
              path: path.join(dirPath, file),
              size: stats.size
            }

            // insert a row in the file list
            insertRow(img.id, img.path, file, displaySize(img.size), $fileList)

            // add the image to the queue for optimizing
            fileQueue.push(img)
          }
        }
        // if it's a directory, recursively find files in it
        else if (stats.isDirectory()) {

          findImagesInDir(path.join(dirPath, file))

        }
      })

    })
  })
}

function insertRow(fileId, filePath, fileName, fileSize, fileList) {

  let row = document.createElement('tr')

  row.id = fileId
  row.className = 'file-item'
  row.innerHTML =
   `
      ${fileName}

    ⏳ Pending
    ${fileSize}

    	`

  $fileList.insertBefore(row, null)
}

// handlers for settings menu actions

function openSettings() {
  $settings.showModal()
  $settings.classList.add('is-open')
}

function closeSettings() {
  $settings.close()
  $settings.classList.remove('is-open')
}

function handleDestinationChange(e) {
  if (e.target.files[0]) {
    options.dest = e.target.files[0].path
  }
  else {
    options.dest = ''
  }
}

function handleQualityChange(e) {
  let value = e.target.value
  $settingsLabelQuality.textContent = value
  options.quality = value
}

function handleConcurrentOptimizationsChange(e) {
  let value = e.target.value
  $settingsLabelConcurrentOptimizations.textContent = e.target.value
  options.maxConcurrentOptimizations = value
}

// utils

function displaySize(bytes) {

  var kilobytes = bytes / 1024
  var megabytes = kilobytes / 1024
  var displaySize = ''

  if (megabytes > 1) {
    displaySize = megabytes.toFixed(2) + ' MB'
  } else {
    displaySize = kilobytes.toFixed(2) + ' KB'
  }

  return displaySize
}

function generateId() {
  return 'f-'+ Math.random().toString().substring(2, 9)
}<|endoftext|>


<commit_before>const EncodingListView = require('./encoding-list-view')
const EncodingStatusView = require('./encoding-status-view')

const encodings = {
  utf8: {
    list: 'UTF-8',
    status: 'UTF-8'
  },
  utf16le: {
    list: 'UTF-16 LE',
    status: 'UTF-16 LE'
  },
  utf16be: {
    list: 'UTF-16 BE',
    status: 'UTF-16 BE'
  },
  windows1252: {
    list: 'Western (Windows 1252)',
    status: 'Windows 1252'
  },
  iso88591: {
    list: 'Western (ISO 8859-1)',
    status: 'ISO 8859-1'
  },
  iso88593: {
    list: 'Western (ISO 8859-3)',
    status: 'ISO 8859-3'
  },
  iso885915: {
    list: 'Western (ISO 8859-15)',
    status: 'ISO 8859-15'
  },
  macroman: {
    list: 'Western (Mac Roman)',
    status: 'Mac Roman'
  },
  cp437: {
    list: 'DOS (CP 437)',
    status: 'CP437'
  },
  cp850: {
    list: 'DOS (CP 850)',
    status: 'CP850'
  },
  windows1256: {
    list: 'Arabic (Windows 1256)',
    status: 'Windows 1256'
  },
  iso88596: {
    list: 'Arabic (ISO 8859-6)',
    status: 'ISO 8859-6'
  },
  windows1257: {
    list: 'Baltic (Windows 1257)',
    status: 'Windows 1257'
  },
  iso88594: {
    list: 'Baltic (ISO 8859-4)',
    status: 'ISO 8859-4'
  },
  iso885914: {
    list: 'Celtic (ISO 8859-14)',
    status: 'ISO 8859-14'
  },
  windows1250: {
    list: 'Central European (Windows 1250)',
    status: 'Windows 1250'
  },
  iso88592: {
    list: 'Central European (ISO 8859-2)',
    status: 'ISO 8859-2'
  },
  windows1251: {
    list: 'Cyrillic (Windows 1251)',
    status: 'Windows 1251'
  },
  cp866: {
    list: 'Cyrillic (CP 866)',
    status: 'CP 866'
  },
  iso88595: {
    list: 'Cyrillic (ISO 8859-5)',
    status: 'ISO 8859-5'
  },
  koi8r: {
    list: 'Cyrillic (KOI8-R)',
    status: 'KOI8-R'
  },
  koi8u: {
    list: 'Cyrillic (KOI8-U)',
    status: 'KOI8-U'
  },
  iso885913: {
    list: 'Estonian (ISO 8859-13)',
    status: 'ISO 8859-13'
  },
  windows1253: {
    list: 'Greek (Windows 1253)',
    status: 'Windows 1253'
  },
  iso88597: {
    list: 'Greek (ISO 8859-7)',
    status: 'ISO 8859-7'
  },
  windows1255: {
    list: 'Hebrew (Windows 1255)',
    status: 'Windows 1255'
  },
  iso88598: {
    list: 'Hebrew (ISO 8859-8)',
    status: 'ISO 8859-8'
  },
  iso885910: {
    list: 'Nordic (ISO 8859-10)',
    status: 'ISO 8859-10'
  },
  iso885916: {
    list: 'Romanian (ISO 8859-16)',
    status: 'ISO 8859-16'
  },
  windows1254: {
    list: 'Turkish (Windows 1254)',
    status: 'Windows 1254'
  },
  iso88599: {
    list: 'Turkish (ISO 8859-9)',
    status: 'ISO 8859-9'
  },
  windows1258: {
    list: 'Vietnamese (Windows 1254)',
    status: 'Windows 1254'
  },
  gbk: {
    list: 'Chinese (GBK)',
    status: 'GBK'
  },
  gb18030: {
    list: 'Chinese (GB18030)',
    status: 'GB18030'
  },
  cp950: {
    list: 'Traditional Chinese (Big5)',
    status: 'Big5'
  },
  big5hkscs: {
    list: 'Traditional Chinese (Big5-HKSCS)',
    status: 'Big5-HKSCS'
  },
  shiftjis: {
    list: 'Japanese (Shift JIS)',
    status: 'Shift JIS'
  },
  cp932: {
    list: 'Japanese (CP 932)',
    status: 'CP 932'
  },
  eucjp: {
    list: 'Japanese (EUC-JP)',
    status: 'EUC-JP'
  },
  euckr: {
    list: 'Korean (EUC-KR)',
    status: 'EUC-KR'
  }
}

let encodingListView = null
let encodingStatusView = null
let commandSubscription = null

module.exports = {
  activate () {
    commandSubscription = atom.commands.add('atom-text-editor', 'encoding-selector:show', () => {
      if (!encodingListView) encodingListView = new EncodingListView(encodings)
      encodingListView.toggle()
    })
  },

  deactivate () {
    if (commandSubscription) commandSubscription.dispose()
    commandSubscription = null

    if (encodingStatusView) encodingStatusView.destroy()
    encodingStatusView = null

    if (encodingListView) encodingListView.destroy()
    encodingListView = null
  },

  consumeStatusBar (statusBar) {
    encodingStatusView = new EncodingStatusView(statusBar, encodings)
    encodingStatusView.attach()
  }
}
<commit_msg>On windows, exclude encodings that don't work<commit_after>const EncodingListView = require('./encoding-list-view')
const EncodingStatusView = require('./encoding-status-view')

const encodings = {
  utf8: {
    list: 'UTF-8',
    status: 'UTF-8'
  },
  utf16le: {
    list: 'UTF-16 LE',
    status: 'UTF-16 LE'
  },
  utf16be: {
    list: 'UTF-16 BE',
    status: 'UTF-16 BE'
  },
  windows1252: {
    list: 'Western (Windows 1252)',
    status: 'Windows 1252'
  },
  iso88591: {
    list: 'Western (ISO 8859-1)',
    status: 'ISO 8859-1'
  },
  iso88593: {
    list: 'Western (ISO 8859-3)',
    status: 'ISO 8859-3'
  },
  iso885915: {
    list: 'Western (ISO 8859-15)',
    status: 'ISO 8859-15'
  },
  macroman: {
    list: 'Western (Mac Roman)',
    status: 'Mac Roman'
  },
  cp437: {
    list: 'DOS (CP 437)',
    status: 'CP437'
  },
  cp850: {
    list: 'DOS (CP 850)',
    status: 'CP850'
  },
  windows1256: {
    list: 'Arabic (Windows 1256)',
    status: 'Windows 1256'
  },
  iso88596: {
    list: 'Arabic (ISO 8859-6)',
    status: 'ISO 8859-6'
  },
  windows1257: {
    list: 'Baltic (Windows 1257)',
    status: 'Windows 1257'
  },
  iso88594: {
    list: 'Baltic (ISO 8859-4)',
    status: 'ISO 8859-4'
  },
  windows1250: {
    list: 'Central European (Windows 1250)',
    status: 'Windows 1250'
  },
  iso88592: {
    list: 'Central European (ISO 8859-2)',
    status: 'ISO 8859-2'
  },
  windows1251: {
    list: 'Cyrillic (Windows 1251)',
    status: 'Windows 1251'
  },
  cp866: {
    list: 'Cyrillic (CP 866)',
    status: 'CP 866'
  },
  iso88595: {
    list: 'Cyrillic (ISO 8859-5)',
    status: 'ISO 8859-5'
  },
  koi8r: {
    list: 'Cyrillic (KOI8-R)',
    status: 'KOI8-R'
  },
  koi8u: {
    list: 'Cyrillic (KOI8-U)',
    status: 'KOI8-U'
  },
  iso885913: {
    list: 'Estonian (ISO 8859-13)',
    status: 'ISO 8859-13'
  },
  windows1253: {
    list: 'Greek (Windows 1253)',
    status: 'Windows 1253'
  },
  iso88597: {
    list: 'Greek (ISO 8859-7)',
    status: 'ISO 8859-7'
  },
  windows1255: {
    list: 'Hebrew (Windows 1255)',
    status: 'Windows 1255'
  },
  iso88598: {
    list: 'Hebrew (ISO 8859-8)',
    status: 'ISO 8859-8'
  },
  iso885916: {
    list: 'Romanian (ISO 8859-16)',
    status: 'ISO 8859-16'
  },
  windows1254: {
    list: 'Turkish (Windows 1254)',
    status: 'Windows 1254'
  },
  iso88599: {
    list: 'Turkish (ISO 8859-9)',
    status: 'ISO 8859-9'
  },
  windows1258: {
    list: 'Vietnamese (Windows 1254)',
    status: 'Windows 1254'
  },
  gbk: {
    list: 'Chinese (GBK)',
    status: 'GBK'
  },
  gb18030: {
    list: 'Chinese (GB18030)',
    status: 'GB18030'
  },
  cp950: {
    list: 'Traditional Chinese (Big5)',
    status: 'Big5'
  },
  big5hkscs: {
    list: 'Traditional Chinese (Big5-HKSCS)',
    status: 'Big5-HKSCS'
  },
  shiftjis: {
    list: 'Japanese (Shift JIS)',
    status: 'Shift JIS'
  },
  cp932: {
    list: 'Japanese (CP 932)',
    status: 'CP 932'
  },
  eucjp: {
    list: 'Japanese (EUC-JP)',
    status: 'EUC-JP'
  },
  euckr: {
    list: 'Korean (EUC-KR)',
    status: 'EUC-KR'
  }
}

const posixOnlyEncodings = {
  iso885914: {
    list: 'Celtic (ISO 8859-14)',
    status: 'ISO 8859-14'
  },
  iso885910: {
    list: 'Nordic (ISO 8859-10)',
    status: 'ISO 8859-10'
  }
}

let encodingListView = null
let encodingStatusView = null
let commandSubscription = null

module.exports = {
  activate () {
    if (process.platform !== 'win32') {
      Object.assign(encodings, posixOnlyEncodings)
    }

    commandSubscription = atom.commands.add('atom-text-editor', 'encoding-selector:show', () => {
      if (!encodingListView) encodingListView = new EncodingListView(encodings)
      encodingListView.toggle()
    })
  },

  deactivate () {
    if (commandSubscription) commandSubscription.dispose()
    commandSubscription = null

    if (encodingStatusView) encodingStatusView.destroy()
    encodingStatusView = null

    if (encodingListView) encodingListView.destroy()
    encodingListView = null
  },

  consumeStatusBar (statusBar) {
    encodingStatusView = new EncodingStatusView(statusBar, encodings)
    encodingStatusView.attach()
  }
}
<|endoftext|>


<commit_before>'use strict'

import React, { Component } from 'react'
import QrReader from 'react-qr-reader'
import QRCode from 'qrcode.react'
import { Layout, Header, Content } from 'react-mdl'

class App extends Component {
  constructor (props) {
    super(props)
    this.state = {
      showCamera: true,
      showSuccess: false,
      result: null
    }
  }
  handleScan (data) {
    this.setState({
      result: this.generateQRCode()
    }, () => {
      this.setState({ showCamera: false })
      this.setState({ showSuccess: true })
    })
  }
  handleError (err) {
    console.log(err)
  }
  generateQRCode () {
    let identifier = Math.floor((Math.random() * 1000) + 1)
    return `${identifier};342432432;Bepantol Derma;30%;2017-01-31T18:46:19-0300;1318630`
  }
  render () {
    const previewStyle = {
      height: '460px',
      width: '100%'
    }
    return (
      <Layout fixedHeader >

        <Content>

          {this.state.showCamera &&
            <Content className='reader'>

                Olá,

                  Waldo Sousa

                Aproxime a câmera para realizar a leitura do QRCode

              <QrReader
                previewStyle={previewStyle}
                handleError={this.handleError}
                handleScan={this.handleScan.bind(this)} />
            </Content>
          }
          {this.state.showSuccess &&
            <Content className='success-box'>

                  Waldo Sousa

                Parabéns, Vá até a farmácia mais próxima e apresente este QRCode para ganhar seu desconto de 20%

              <QRCode size={256} value={this.state.result} />
            </Content>
        }
        </Content>
      </Layout>
    )
  }
}

export default App
<commit_msg>Forçando camera traseira, tentativa 2<commit_after>'use strict'

import React, { Component } from 'react'
import QrReader from 'react-qr-reader'
import QRCode from 'qrcode.react'
import { Layout, Header, Content } from 'react-mdl'

class App extends Component {
  constructor (props) {
    super(props)
    this.state = {
      showCamera: true,
      showSuccess: false,
      result: null
    }
  }
  handleScan (data) {
    this.setState({
      result: this.generateQRCode()
    }, () => {
      this.setState({ showCamera: false })
      this.setState({ showSuccess: true })
    })
  }
  handleError (err) {
    console.log(err)
  }
  generateQRCode () {
    let identifier = Math.floor((Math.random() * 1000) + 1)
    return `${identifier};342432432;Bepantol Derma;30%;2017-01-31T18:46:19-0300;1318630`
  }
  render () {
    const previewStyle = {
      height: '460px',
      width: '100%'
    }
    return (
      <Layout fixedHeader >

        <Content>

          {this.state.showCamera &&
            <Content className='reader'>

                Olá,

                  Waldo Sousa

                Aproxime a câmera para realizar a leitura do QRCode

              <QrReader
                previewStyle={previewStyle}
                handleError={this.handleError}
                handleScan={this.handleScan.bind(this)}
                facingMode={'rear'} />
            </Content>
          }
          {this.state.showSuccess &&
            <Content className='success-box'>

                  Waldo Sousa

                Parabéns, Vá até a farmácia mais próxima e apresente este QRCode para ganhar seu desconto de 20%

              <QRCode size={256} value={this.state.result} />
            </Content>
        }
        </Content>
      </Layout>
    )
  }
}

export default App
<|endoftext|>


<commit_before>// vim: set ts=2 sw=2:
"use strict";

let the_physics = new Physics();
let the_longcat = new LongCat(document.getElementById('the_longcat'), the_physics);

let backgrounds = [];
document.querySelectorAll('.background').forEach((background, i) => {
  backgrounds[i] = new Background(background, the_physics);
});

window.requestAnimationFrame = window.requestAnimationFrame
                            || window.mozRequestAnimationFrame
                            || window.webkitRequestAnimationFrame
                            || window.msRequestAnimationFrame
                            || function(cb) { window.setTimeout(cb, 1000/60); };

// Rather use window.performance if it's available.
// It has sub-millisecond precision, while Date.now only has milliseconds.
let rtc = window.performance || Date;
let t0 = rtc.now();

function mainloop() {
  let t = rtc.now();
  let dt = 0.001*(t - t0);  // from milliseconds to seconds

  // When the tab gets hidden, this animate loop is not called, which is good
  // as it pauses the game. But when the tab gets visible again, the dt is huge:
  // as large as the tab was hidden. We don't want this, as it undoes the pause.
  // so we only update on small dt.
  if (dt < 0.5) {
    the_physics.update(dt);
    the_longcat.update(dt);

    backgrounds.forEach(background => {
      background.update(dt);
    });
  }

  // For the next timestep.
  t0 = t;
  window.requestAnimationFrame(mainloop);
}
window.requestAnimationFrame(mainloop);

function raise_longcat(ev) {
  // Avoid stuff like drag/drop selection etc.
  ev.preventDefault();

  the_physics.speedup();
}

// A click raises the longcat!
window.addEventListener('mousedown', raise_longcat);
window.addEventListener('touchstart', raise_longcat);
<commit_msg>Add up/down arrow for easy debugging.<commit_after>// vim: set ts=2 sw=2:
"use strict";

let the_physics = new Physics();
let the_longcat = new LongCat(document.getElementById('the_longcat'), the_physics);

let backgrounds = [];
document.querySelectorAll('.background').forEach((background, i) => {
  backgrounds[i] = new Background(background, the_physics);
});

window.requestAnimationFrame = window.requestAnimationFrame
                            || window.mozRequestAnimationFrame
                            || window.webkitRequestAnimationFrame
                            || window.msRequestAnimationFrame
                            || function(cb) { window.setTimeout(cb, 1000/60); };

// Rather use window.performance if it's available.
// It has sub-millisecond precision, while Date.now only has milliseconds.
let rtc = window.performance || Date;
let t0 = rtc.now();

function mainloop() {
  let t = rtc.now();
  let dt = 0.001*(t - t0);  // from milliseconds to seconds

  // When the tab gets hidden, this animate loop is not called, which is good
  // as it pauses the game. But when the tab gets visible again, the dt is huge:
  // as large as the tab was hidden. We don't want this, as it undoes the pause.
  // so we only update on small dt.
  if (dt < 0.5) {
    the_physics.update(dt);
    the_longcat.update(dt);

    backgrounds.forEach(background => {
      background.update(dt);
    });
  }

  // For the next timestep.
  t0 = t;
  window.requestAnimationFrame(mainloop);
}
window.requestAnimationFrame(mainloop);

function raise_longcat(ev) {
  // Avoid stuff like drag/drop selection etc.
  ev.preventDefault();

  the_physics.speedup();
}

// A click raises the longcat!
window.addEventListener('mousedown', raise_longcat);
window.addEventListener('touchstart', raise_longcat);

// Some cheats for testing
window.addEventListener('keyup', (ev) => {
  ev.preventDefault();
  if (ev.key == 'ArrowUp') {
    the_physics.g = 0;
    the_physics.vy += 0.01;
  } else if (ev.key == 'ArrowDown') {
    the_physics.g = 0;
    the_physics.vy -= 0.01;
  }
  console.log(ev.key)
})
<|endoftext|>


<commit_before>'use strict';
const fs = require('fs');

function parse(raw, strip=true){
	if(!raw) return {};
	raw = CSVToArray(raw);
	let obj = {};
	let location;
	raw.map((row) => {
		if(row.length === 1){
			location = row[0].match(/\[(.*?)\]/)[1];
			return obj[location] = {};
		}
		if(strip) row = row.map((v) => { return v.trim(); });
		obj[location][row[0]] = row[1];

	});
	return obj;
}

function CSVToArray(strData, delim = ',') {
	let objPattern = new RegExp((
	// Delimiters.
	'(\\' + delim + '|\\r?\\n|\\r|^)' +
	// Quoted fields.
	'(?:\"([^\"]*(?:\"\"[^\"]*)*)\"|' +
	// Standard fields.
	'([^\"\\' + delim + '\\r\\n]*))'), 'gi');

	let arrData = [[]];
	let match = null;
	while (match = objPattern.exec(strData)) {
		let matchDelim = match[1];
		if(matchDelim === '\n' && !match[3]) continue;
		if (matchDelim.length && (matchDelim !== delim)) {
			arrData.push([]);
		}
		let strMatchedValue = match[2] ?
			match[2].replace(/\"\"/, '\"') : match[3];
		arrData[arrData.length - 1].push(strMatchedValue);
	}
	return arrData;
}

module.exports = {
	parse: parse,
	_csvtoarray: CSVToArray
};
<commit_msg>changed module exports based on testing status<commit_after>'use strict';
const fs = require('fs');

function parse(raw, strip=true){
	if(!raw) return {};
	raw = CSVToArray(raw);
	let obj = {};
	let location;
	raw.map((row) => {
		if(row.length === 1){
			location = row[0].match(/\[(.*?)\]/)[1];
			return obj[location] = {};
		}
		if(strip) row = row.map((v) => { return v.trim(); });
		obj[location][row[0]] = row[1];

	});
	return obj;
}

function CSVToArray(strData, delim = ',') {
	let objPattern = new RegExp((
	// Delimiters.
	'(\\' + delim + '|\\r?\\n|\\r|^)' +
	// Quoted fields.
	'(?:\"([^\"]*(?:\"\"[^\"]*)*)\"|' +
	// Standard fields.
	'([^\"\\' + delim + '\\r\\n]*))'), 'gi');

	let arrData = [[]];
	let match = null;
	while (match = objPattern.exec(strData)) {
		let matchDelim = match[1];
		if(matchDelim === '\n' && !match[3]) continue;
		if (matchDelim.length && (matchDelim !== delim)) {
			arrData.push([]);
		}
		let strMatchedValue = match[2] ?
			match[2].replace(/\"\"/, '\"') : match[3];
		arrData[arrData.length - 1].push(strMatchedValue);
	}
	return arrData;
}

module.exports = parse;

//expose private functions for testing
if(process.env.npm_config_expose){
	module.exports = {
		parse: parse,
		_csvtoarray: CSVToArray
	};
}
<|endoftext|>


<commit_before>"use strict";

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

function setup_response_handler(req, callback) {
  if (typeof callback !== "function") {
    //console.log("missing callback");
    return;
  }
  req.on('response',
    function(res) {
      var response = '';
      res.setEncoding('utf8');
      res.on('data',
        function(chunk) {
          response += chunk;
        });
      res.on('end',
        function() {
          var err = null;
          try {
            response = JSON.parse(response);
            if (200 != res.statusCode && 201 != res.statusCode) {
              err = new Error(response.error.message);
              err.name = response.error.type;
              err.code = response.error.code;
              err.param = response.error.param;
              response = null;
            }
          } catch (e) {
            err = new Error("Invalid JSON response");
            response = null;
          }
          callback(err, response);
        });
    });
  req.on('error', function(error) {
    callback(error);
  });
}

module.exports = function(api_key) {
  var auth = 'Basic ' + new Buffer(api_key + ":").toString('base64');

  function _request(method, path, data, callback) {
    var request_data = JSON.stringify(data);

    var request_options = {
      host: 'api.blockscore.com',
      port: '443',
      path: path,
      method: method,
      headers: {
        'Authorization': auth,
        'Accept': 'application/vnd.blockscore+json;version=3',
        'User-Agent': 'blockscore-node/3.0.0 (https://github.com/BlockScore/blockscore-node)',
        'Content-Type': 'application/json',
        'Content-Length': request_data.length
      },
      agent: false
    };

    var req = https.request(request_options);
    setup_response_handler(req, callback);
    req.write(request_data);
    req.end();
  }

  function post(path, data, callback) {
    _request('POST', path, data, callback);
  }

  function get(path, data, callback) {
    _request('GET', path, data, callback);
  }

  function del(path, data, callback) {
    _request('DELETE', path, data, callback);
  }

  function normalizeArguments() {
    var args = arguments[0];
    if (typeof args[0] == 'object' && typeof args[1] == 'function' && !args[2])
      return {
        count: args[0].count,
        offset: args[0].offset,
        cb: args[1]
      };
    else
      return {
        count: args[0],
        offset: args[1],
        cb: args[2]
      };
  }

  return {
    verifications: {
      create: function(data, cb) {
        post("/verifications", data, cb);
      },
      retrieve: function(verification_id, cb) {
        if (!(verification_id && typeof verification_id === 'string')) {
          return cb(new Error("verification_id required"));
        }
        get("/verifications/" + encodeURIComponent(verification_id), {}, cb);
      },
      list: function(count, offset, cb) {
        var nArgs = normalizeArguments(arguments);
        get("/verifications", {
          count: nArgs.count,
          offset: nArgs.offset
        }, nArgs.cb);
      }
    },
    questions: {
      create: function(verification_id, cb) {
        if (!(verification_id && typeof verification_id === 'string')) {
          return cb(new Error("verification_id required"));
        }
        var data = { verification_id: verification_id };
        post("/questions", data, cb);
      },
      score: function(data, cb) {
        post("/questions/score", data, cb);
      },
      retrieve: function(question_set_id, cb) {
        if (!(question_set_id && typeof question_set_id === 'string')) {
          return cb(new Error("question_set_id required"));
        }
        get("/questions/" + encodeURIComponent(question_set_id), {}, cb);
      }
    },
    watchlist_candidates: {
      create: function(data, cb) {
        post("/watchlist_candidates", data, cb);
      },
      retrieve: function(watchlist_candidate_id, cb) {
        if (!(watchlist_candidate_id && typeof watchlist_candidate_id === 'string')) {
          return cb(new Error("watchlist_candidate_id required"));
        }
        get("/watchlist_candidates/" + encodeURIComponent(watchlist_candidate_id), {}, cb);
      },
      list: function(count, offset, cb) {
        var nArgs = normalizeArguments(arguments);
        get("/watchlist_candidates/", {
          count: nArgs.count,
          offset: nArgs.offset
        }, nArgs.cb);
      }
    }

  };
};
<commit_msg>implemented watchlist_candidates functionality for node wrapper; still need to write tests for & document it<commit_after>"use strict";

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

function setup_response_handler(req, callback) {
  if (typeof callback !== "function") {
    //console.log("missing callback");
    return;
  }
  req.on('response',
    function(res) {
      var response = '';
      res.setEncoding('utf8');
      res.on('data',
        function(chunk) {
          response += chunk;
        });
      res.on('end',
        function() {
          var err = null;
          try {
            response = JSON.parse(response);
            if (200 != res.statusCode && 201 != res.statusCode) {
              err = new Error(response.error.message);
              err.name = response.error.type;
              err.code = response.error.code;
              err.param = response.error.param;
              response = null;
            }
          } catch (e) {
            err = new Error("Invalid JSON response");
            response = null;
          }
          callback(err, response);
        });
    });
  req.on('error', function(error) {
    callback(error);
  });
}

module.exports = function(api_key) {
  var auth = 'Basic ' + new Buffer(api_key + ":").toString('base64');

  function _request(method, path, data, callback) {
    var request_data = JSON.stringify(data);

    var request_options = {
      host: 'api.blockscore.com',
      port: '443',
      path: path,
      method: method,
      headers: {
        'Authorization': auth,
        'Accept': 'application/vnd.blockscore+json;version=3',
        'User-Agent': 'blockscore-node/3.0.0 (https://github.com/BlockScore/blockscore-node)',
        'Content-Type': 'application/json',
        'Content-Length': request_data.length
      },
      agent: false
    };

    var req = https.request(request_options);
    setup_response_handler(req, callback);
    req.write(request_data);
    req.end();
  }

  function post(path, data, callback) {
    _request('POST', path, data, callback);
  }

  function get(path, data, callback) {
    _request('GET', path, data, callback);
  }

  function del(path, data, callback) {
    _request('DELETE', path, data, callback);
  }

  function normalizeArguments() {
    var args = arguments[0];
    if (typeof args[0] == 'object' && typeof args[1] == 'function' && !args[2])
      return {
        count: args[0].count,
        offset: args[0].offset,
        cb: args[1]
      };
    else
      return {
        count: args[0],
        offset: args[1],
        cb: args[2]
      };
  }

  return {
    verifications: {
      create: function(data, cb) {
        post("/verifications", data, cb);
      },
      retrieve: function(verification_id, cb) {
        if (!(verification_id && typeof verification_id === 'string')) {
          return cb(new Error("verification_id required"));
        }
        get("/verifications/" + encodeURIComponent(verification_id), {}, cb);
      },
      list: function(count, offset, cb) {
        var nArgs = normalizeArguments(arguments);
        get("/verifications", {
          count: nArgs.count,
          offset: nArgs.offset
        }, nArgs.cb);
      }
    },
    questions: {
      create: function(verification_id, cb) {
        if (!(verification_id && typeof verification_id === 'string')) {
          return cb(new Error("verification_id required"));
        }
        var data = { verification_id: verification_id };
        post("/questions", data, cb);
      },
      score: function(data, cb) {
        post("/questions/score", data, cb);
      },
      retrieve: function(question_set_id, cb) {
        if (!(question_set_id && typeof question_set_id === 'string')) {
          return cb(new Error("question_set_id required"));
        }
        get("/questions/" + encodeURIComponent(question_set_id), {}, cb);
      }
    },
    watchlist_candidates: {
      create: function(data, cb) {
        post("/watchlist_candidates", data, cb);
      },
      retrieve: function(watchlist_candidate_id, cb) {
        if (!(watchlist_candidate_id && typeof watchlist_candidate_id === 'string')) {
          return cb(new Error("watchlist_candidate_id required"));
        }
        get("/watchlist_candidates/" + encodeURIComponent(watchlist_candidate_id), {}, cb);
      },
      // // TODO get del fn to actually work
      // del: function(watchlist_candidate_id, cb) {
      //   del('/watchlist_candidates/' + encodeURIComponent(watchlist_candidate_id), {}, cb);
      // },
      list: function(count, offset, cb) {
        var nArgs = normalizeArguments(arguments);
        get("/watchlist_candidates/", {
          count: nArgs.count,
          offset: nArgs.offset
        }, nArgs.cb);
      }
    }

  };
};
<|endoftext|>


<commit_before>go.app = function() {
    var vumigo = require('vumigo_v02');
    var _ = require('lodash');
    var App = vumigo.App;
    var EndState = vumigo.states.EndState;
    var FreeText = vumigo.states.FreeText;

    var GoApp = App.extend(function(self) {
        App.call(self, 'states:start');
        var $ = self.$;

        self.init = function() {
            return self.im.contacts
                .for_user()
                .then(function(user_contact) {
                   self.contact = user_contact;
                });
        };

        // S1
        self.states.add('states:start', function(name, opts) {
            var valid = ['1', '2'];

            var error = $('Sorry, your choice was not valid. In order to continue receiving survey questions please Text 1 for Yes and 2 for No');

            var question;
            if (!opts.retry) {
                question = $('In order to continue receiving survey questions please Text 1 for Yes and 2 for No');
            } else {
                question = error;
            }

            return new FreeText(name, {
                question: question,

                check: function(content) {
                    if (!_.contains(valid, content.trim())) {
                        return error;
                    }
                },

                next: function(content) {
                    return {
                        '1': 'states:language',
                        '2': 'states:end_no_consent'
                    } [content.trim()];
                }
            });
        });

        // S2
        self.states.add('states:language', function(name, opts) {
            var valid = ['1', '2', '3'];

            var error = $('Sorry, your choice was not valid. What is your preferred language? Text 1 for English, 2 for Amharic and 3 for ኣማርኛ');

            var question;
            if (!opts.retry) {
                question = $('What is your preferred language? Text 1 for English, 2 for Amharic and 3 for ኣማርኛ');
            } else {
                question = error;
            }

            return new FreeText(name, {
                question: question,

                check: function(content) {
                    if (!_.contains(valid, content.trim())) {
                        return error;
                    }
                },

                next: function(content) {
                    return self.im.user.set_lang(content)
                        .then(function() {
                            return 'states:age';
                        });
                }
            });
        });

        // S3
        self.states.add('states:age', function(name, opts) {
            var valid = ['1', '2'];

            var error = $('Sorry, your choice was not valid. Are you older than 18 years? Text 1 for Yes and 2 for No');

            var question;
            if (!opts.retry) {
                question = $('Are you older than 18 years? Text 1 for Yes and 2 for No');
            } else {
                question = error;
            }

            return new FreeText(name, {
                question: question,

                check: function(content) {
                    if (!_.contains(valid, content.trim())) {
                        return error;
                    }
                },

                next: function(content) {
                    return 'states:gender';
                }
            });
        });

        // S4
        self.states.add('states:gender', function(name, opts) {
            var valid = ['1', '2'];

            var error = $('Sorry, your choice was not valid. What is your gender? Text 1 for Male and 2 for Female');

            var question;
            if (!opts.retry) {
                question = $('What is your gender? Text 1 for Male and 2 for Female');
            } else {
                question = error;
            }

            return new FreeText(name, {
                question: question,

                check: function(content) {
                    if (!_.contains(valid, content.trim())) {
                        return error;
                    }
                },

                next: function(content) {
                    return 'states:group_id';
                }
            });
        });

        // S5
        self.states.add('states:group_id', function(name, opts) {
            var num_listener_groups = _.size(self.im.config.group_id); // better than hardcoding, but can fall over if a group is deleted
            var valid = [];

            for (var i = 1; i <= num_listener_groups; i++) {
                valid.push(i.toString());
            }

            var error = $('Sorry, your choice was not valid. Please enter your Listener Group Name');

            var question;
            if (!opts.retry) {
                question = $('Please enter your Listener Group Name');
            } else {
                question = error;
            }

            return new FreeText(name, {
                question: question,

                check: function(content) {
                    if (!_.contains(valid, content.trim())) {
                        return error;
                    }
                },

                next: function(content) {
                    // set answers against contact extras
                    self.contact.extra.user_language = self.im.user.answers['states:language'];
                    self.contact.extra.user_age = self.im.user.answers['states:age'];
                    self.contact.extra.user_gender = self.im.user.answers['states:gender'];
                    self.contact.extra.group_id = self.im.user.answers['states:group_id'];

                    // look up group info and set against contact extras
                    self.contact.extra.group_type = self.im.config.group_id[content].group_type;
                    self.contact.extra.group_name = self.im.config.group_id[content].group_name;
                    self.contact.extra.urban_rural = self.im.config.group_id[content].urban_rural;

                    return self.im.contacts.save(self.contact)
                        .then(function() {
                            return self.im.groups.get(self.contact.extra.group_type, {create: true})
                                .then(function(group) {
                                    if(_.isUndefined(group.users)) {
                                        group.users = [];
                                    }
                                    var users = group.users;
                                    users.push(self.contact.msisdn);
                                    group.users = users;
                                    console.log('11111111111111111');
                                    console.log(group);
                                    console.log('22222222222222222');
                                    console.log(self.im.api.groups.store);
                                    return self.im.groups.save(group) // this doesn't seem to do anything, perhaps crappy groupstore setup?
                                    // for debugging
                                        .then(function() {
                                            self.im.groups.get('mixed')
                                            .then(function(blah) {
                                                console.log('3333333333333333');
                                                console.log(blah);
                                                console.log('4444444444444444');
                                                console.log(self.im.api.groups.store);
                                            });
                                        });
                                    // end debugging
                                });
                        })
                        .then(function() {
                            return self.im.groups.get('registered', {create: true})
                                .then(function(group) {
                                    if(_.isUndefined(group.users)) {
                                        group.users = [];
                                    }
                                    var users = group.users;
                                    users.push(self.contact.msisdn);
                                    group.users = users;
                                    return self.im.groups.save(group); // this doesn't seem to do anything!!
                                });
                        })
                        .then(function() {
                            return 'states:end_registered';
                        });
                }
            });
        });

        // End State 1 - no consent
        self.states.add('states:end_no_consent', function(name) {
            return new EndState(name, {
                text: $('Thank you for reaching out to Yegna Listener Group Registration Survey'),
                next: 'states:start'
            });
        });

        // End State 2 - successful registration
        self.states.add('states:end_registered', function(name) {
            return new EndState(name, {
                text: $('Thank you! You are now registered as a member of the Yegna Listener Group. Please share your feedback with us every week. Your input is very important to us.'),
                next: 'states:start'
            });
        });
    });

    return {
        GoApp: GoApp
    };
}();
<commit_msg>Try to simplfy groups addition<commit_after>go.app = function() {
    var vumigo = require('vumigo_v02');
    var _ = require('lodash');
    var App = vumigo.App;
    var EndState = vumigo.states.EndState;
    var FreeText = vumigo.states.FreeText;

    var GoApp = App.extend(function(self) {
        App.call(self, 'states:start');
        var $ = self.$;

        self.init = function() {
            return self.im.contacts
                .for_user()
                .then(function(user_contact) {
                   self.contact = user_contact;
                });
        };

        // S1
        self.states.add('states:start', function(name, opts) {
            var valid = ['1', '2'];

            var error = $('Sorry, your choice was not valid. In order to continue receiving survey questions please Text 1 for Yes and 2 for No');

            var question;
            if (!opts.retry) {
                question = $('In order to continue receiving survey questions please Text 1 for Yes and 2 for No');
            } else {
                question = error;
            }

            return new FreeText(name, {
                question: question,

                check: function(content) {
                    if (!_.contains(valid, content.trim())) {
                        return error;
                    }
                },

                next: function(content) {
                    return {
                        '1': 'states:language',
                        '2': 'states:end_no_consent'
                    } [content.trim()];
                }
            });
        });

        // S2
        self.states.add('states:language', function(name, opts) {
            var valid = ['1', '2', '3'];

            var error = $('Sorry, your choice was not valid. What is your preferred language? Text 1 for English, 2 for Amharic and 3 for ኣማርኛ');

            var question;
            if (!opts.retry) {
                question = $('What is your preferred language? Text 1 for English, 2 for Amharic and 3 for ኣማርኛ');
            } else {
                question = error;
            }

            return new FreeText(name, {
                question: question,

                check: function(content) {
                    if (!_.contains(valid, content.trim())) {
                        return error;
                    }
                },

                next: function(content) {
                    return self.im.user.set_lang(content)
                        .then(function() {
                            return 'states:age';
                        });
                }
            });
        });

        // S3
        self.states.add('states:age', function(name, opts) {
            var valid = ['1', '2'];

            var error = $('Sorry, your choice was not valid. Are you older than 18 years? Text 1 for Yes and 2 for No');

            var question;
            if (!opts.retry) {
                question = $('Are you older than 18 years? Text 1 for Yes and 2 for No');
            } else {
                question = error;
            }

            return new FreeText(name, {
                question: question,

                check: function(content) {
                    if (!_.contains(valid, content.trim())) {
                        return error;
                    }
                },

                next: function(content) {
                    return 'states:gender';
                }
            });
        });

        // S4
        self.states.add('states:gender', function(name, opts) {
            var valid = ['1', '2'];

            var error = $('Sorry, your choice was not valid. What is your gender? Text 1 for Male and 2 for Female');

            var question;
            if (!opts.retry) {
                question = $('What is your gender? Text 1 for Male and 2 for Female');
            } else {
                question = error;
            }

            return new FreeText(name, {
                question: question,

                check: function(content) {
                    if (!_.contains(valid, content.trim())) {
                        return error;
                    }
                },

                next: function(content) {
                    return 'states:group_id';
                }
            });
        });

        // S5
        self.states.add('states:group_id', function(name, opts) {
            var num_listener_groups = _.size(self.im.config.group_id); // better than hardcoding, but can fall over if a group is deleted
            var valid = [];

            for (var i = 1; i <= num_listener_groups; i++) {
                valid.push(i.toString());
            }

            var error = $('Sorry, your choice was not valid. Please enter your Listener Group Name');

            var question;
            if (!opts.retry) {
                question = $('Please enter your Listener Group Name');
            } else {
                question = error;
            }

            return new FreeText(name, {
                question: question,

                check: function(content) {
                    if (!_.contains(valid, content.trim())) {
                        return error;
                    }
                },

                next: function(content) {
                    // set answers against contact extras
                    self.contact.extra.user_language = self.im.user.answers['states:language'];
                    self.contact.extra.user_age = self.im.user.answers['states:age'];
                    self.contact.extra.user_gender = self.im.user.answers['states:gender'];
                    self.contact.extra.group_id = self.im.user.answers['states:group_id'];

                    // look up group info and set against contact extras
                    self.contact.extra.group_type = self.im.config.group_id[content].group_type;
                    self.contact.extra.group_name = self.im.config.group_id[content].group_name;
                    self.contact.extra.urban_rural = self.im.config.group_id[content].urban_rural;

                    return self.im.groups.get(self.contact.extra.group_type)
                        .then(function(group) {
                            self.contact.groups.push(group.key);
                            return self.im.groups.get("Registered")
                                .then(function(reg_group){
                                    self.contact.groups.push(reg_group.key);
                                    return self.im.contacts.save(self.contact)
                                        .then(function() {
                                            return 'states:end_registered';
                                        });
                                });
                        });
                }
            });
        });

        // End State 1 - no consent
        self.states.add('states:end_no_consent', function(name) {
            return new EndState(name, {
                text: $('Thank you for reaching out to Yegna Listener Group Registration Survey'),
                next: 'states:start'
            });
        });

        // End State 2 - successful registration
        self.states.add('states:end_registered', function(name) {
            return new EndState(name, {
                text: $('Thank you! You are now registered as a member of the Yegna Listener Group. Please share your feedback with us every week. Your input is very important to us.'),
                next: 'states:start'
            });
        });
    });

    return {
        GoApp: GoApp
    };
}();
<|endoftext|>


<commit_before>'use babel';

import path from 'path';
import React from 'react';
import uuid from 'uuid';
import _ from 'lodash';
import {CompositeDisposable} from 'atom';
import Dispatcher from './dispatcher';
import NotebookEditor from './notebook-editor';
import NotebookEditorView from './notebook-editor-view';``

export default {

  activate(state) {
    console.log('Activated.');
    this.openerDisposable = atom.workspace.addOpener(openURI);
    this.commands = atom.commands.add('.notebook-cell atom-text-editor', 'jupyter-notebook-atom:run', this.run);
    atom.views.addViewProvider({
      modelConstructor: NotebookEditor,
      createView: model => {
        let el = document.createElement('div');
        el.classList.add('notebook-wrapper');
        let viewComponent = React.render(
          <NotebookEditorView store={model} />,
          el);
        return el;
      }
    });
  },

  deactivate() {
    Dispatcher.dispatch({
      actionType: Dispatcher.actions.destroy
    });
    this.openerDisposable.dispose();
    this.commands.dispose();
  },

  toggle() {
    console.log('JupyterNotebookAtom was toggled!');
    if (this.modalPanel.isVisible()) {
      return this.modalPanel.hide();
    } else {
      return this.modalPanel.show();
    }
  },

  run() {
    // console.log('Run cell');
    Dispatcher.dispatch({
      actionType: Dispatcher.actions.run_active_cell
      // cellID: this.props.data.get('id')
    });
  }

};

function openURI(uriToOpen) {
  const notebookExtensions = ['.ipynb'];
  let uriExtension = path.extname(uriToOpen).toLowerCase();
  if (_.include(notebookExtensions, uriExtension)) return new NotebookEditor(uriToOpen);
}
<commit_msg>Fix process.env.PATH to spawn child processes<commit_after>'use babel';

import path from 'path';
import React from 'react';
import uuid from 'uuid';
import _ from 'lodash';
import {CompositeDisposable} from 'atom';
import Dispatcher from './dispatcher';
import NotebookEditor from './notebook-editor';
import NotebookEditorView from './notebook-editor-view';``

export default {

  activate(state) {
    // console.log('Activated');
    fixPath();
    this.openerDisposable = atom.workspace.addOpener(openURI);
    this.commands = atom.commands.add('.notebook-cell atom-text-editor', 'jupyter-notebook-atom:run', this.run);
    atom.views.addViewProvider({
      modelConstructor: NotebookEditor,
      createView: model => {
        let el = document.createElement('div');
        el.classList.add('notebook-wrapper');
        let viewComponent = React.render(
          <NotebookEditorView store={model} />,
          el);
        return el;
      }
    });
  },

  deactivate() {
    Dispatcher.dispatch({
      actionType: Dispatcher.actions.destroy
    });
    this.openerDisposable.dispose();
    this.commands.dispose();
  },

  toggle() {
    console.log('JupyterNotebookAtom was toggled!');
    if (this.modalPanel.isVisible()) {
      return this.modalPanel.hide();
    } else {
      return this.modalPanel.show();
    }
  },

  run() {
    // console.log('Run cell');
    Dispatcher.dispatch({
      actionType: Dispatcher.actions.run_active_cell
      // cellID: this.props.data.get('id')
    });
  }

};

function fixPath() {
  process.env.PATH = _.union([
    '/usr/local/bin',
    '/usr/bin',
    '/bin'
  ], process.env.PATH.split(':')).join(':');
}

function openURI(uriToOpen) {
  const notebookExtensions = ['.ipynb'];
  let uriExtension = path.extname(uriToOpen).toLowerCase();
  if (_.include(notebookExtensions, uriExtension)) return new NotebookEditor(uriToOpen);
}
<|endoftext|>


<commit_before>/**
 * @author  Hamza Waqas <hamzawaqas@live.com>
 * @since   1/14/14
 */

(function() {

    var _ = require('lodash');

    var Main = function(apiUrl, apiKey) {
        var _services = ['name', 'search', 'thumbnail']
            , Inherits = require('./inherits')
            , self = this;

        // Make some configuration;
        this.options = {
            api_url: apiUrl,
            apiKey: apiKey
        };

        _.forEach(_services, function(service) {
            module.exports[service] = require(__dirname + '/services/' + service)(Inherits, self.options);
        });

        return module.exports;
    }.bind(this);

    module.exports = Main;
}).call(this);
<commit_msg>Update main.js<commit_after>/**
 * @author  Hamza Waqas <hamzawaqas@live.com>
 * @since   1/14/14
 */

(function() {

    var _ = require('lodash');

    var Main = function(apiKey, apiUrl) {
        var _services = ['name', 'search', 'thumbnail']
            , Inherits = require('./inherits')
            , self = this;

        // Make some configuration;
        this.options = {
            api_url: apiUrl || 'http://api.pipl.com/search/v4/',
            apiKey: apiKey
        };

        _services.forEach(function(service) {
            module.exports[service] = require(__dirname + '/services/' + service)(Inherits, self.options);
        });

        return module.exports;
    }.bind(this);

    module.exports = Main;
}).call(this);
<|endoftext|>


<commit_before>var Application = require("substance-application");
var Component = Application.Component;
var $$ = Application.$$;
var _ = require("underscore");

// The main composer
var Composer = require("./composer");

// The Composer Application
// -------------------
//
// TODO: maybe we can get rid of this boilerplate
//
// would maybe be nicer to start a new app generically, like this:
//
// var app = new Application({
//   rootComponent: Composer,
//   data: null,
//   // state: state,
//   el: document.body
// });

var ComposerApp = function(options) {
  Application.call(this, options);

  this.el = document.body; // use options.el
  this.rootElement = $$(Composer);
};

ComposerApp.Prototype = function() {

};

ComposerApp.Prototype.prototype = Application.prototype;
ComposerApp.prototype = new ComposerApp.Prototype();

module.exports = ComposerApp;
<commit_msg>Preliminary component registry configuration.<commit_after>var Application = require("substance-application");
var Component = Application.Component;
var $$ = Application.$$;
var _ = require("underscore");

// The main composer
var Composer = require("./composer");
var WriterNodes = require('substance-writer').Nodes

// The Composer Application
// -------------------
//
// TODO: maybe we can get rid of this boilerplate
//
// would maybe be nicer to start a new app generically, like this:
//
// var app = new Application({
//   rootComponent: Composer,
//   data: null,
//   // state: state,
//   el: document.body
// });

var ComposerApp = function(options) {
  // TODO: discuss how to configure a component registry
  // Note: having this allows to lookup and create components
  // by name, such as components for custom nodes
  options.components = _.extend(WriterNodes, options.components);

  Application.call(this, options);

  this.el = document.body; // use options.el
  this.rootElement = $$(Composer);
};

ComposerApp.Prototype = function() {

};

ComposerApp.Prototype.prototype = Application.prototype;
ComposerApp.prototype = new ComposerApp.Prototype();

module.exports = ComposerApp;
<|endoftext|>


<commit_before>var path = require('path');
var express = require('express');
var compression = require('compression');
var favicon = require('serve-favicon');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');
var mongoose = require('mongoose');

var dbURL = process.envMONGOLAB_URI || "mongodb://localhost/DomoMaker";

var db = mongoose.connect(dbURL, function (err) {
  if (err) {
    console.log("Could not connect to database");
    throw err;
  }
});

//pull in our routes
var router = require('./router.js');

var port = process.env.PORT || process.env.NODE_PORT || 3000;

var app = express();
app.use('/assets', express.static(path.resolve(__dirname+'/../client/')));
app.use(compression());
app.use(bodyParser.urlencoded({
  extended: true
}));
app.set('view engine', 'jade');
app.set('views', __dirname + '/views');
app.use(cookieParser());

router(app);

app.listen(port, function (err) {
  if (err) {
    throw err;
  }
  console.log('Listening on port ' + port);
});
<commit_msg>fixed a typo in app.js<commit_after>var path = require('path');
var express = require('express');
var compression = require('compression');
var favicon = require('serve-favicon');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');
var mongoose = require('mongoose');

var dbURL = process.env.MONGOLAB_URI || "mongodb://localhost/DomoMaker";

var db = mongoose.connect(dbURL, function (err) {
  if (err) {
    console.log("Could not connect to database");
    throw err;
  }
});

//pull in our routes
var router = require('./router.js');

var port = process.env.PORT || process.env.NODE_PORT || 3000;

var app = express();
app.use('/assets', express.static(path.resolve(__dirname+'/../client/')));
app.use(compression());
app.use(bodyParser.urlencoded({
  extended: true
}));
app.set('view engine', 'jade');
app.set('views', __dirname + '/views');
app.use(cookieParser());

router(app);

app.listen(port, function (err) {
  if (err) {
    throw err;
  }
  console.log('Listening on port ' + port);
});
<|endoftext|>


<commit_before>'use babel';

import path from 'path';
import CSON from 'season';

export default {
  activate() {
    this.pkgName = 'levels-language-ruby';
    const pkgDirPath = atom.packages.resolvePackagePath(this.pkgName);
    this.pkgLanguageDirPath = path.join(pkgDirPath, 'language');

    var pkgSubscription = atom.packages.onDidActivatePackage(pkg => {
      if (pkg.name === this.pkgName) {
        if (this.consumedLevels) {
          this.startUsingLevels();
        }

        pkgSubscription.dispose();
        this.activated = true;
      }
    });
  },

  deactivate() {
    this.stopUsingLevels();
    this.consumedLevels = false;
    this.activated = false;
  },

  consumeLevels({languageRegistry}) {
    this.languageRegistry = languageRegistry;
    if (this.activated) {
      this.startUsingLevels();
    }
    this.consumedLevels = true;
  },

  startUsingLevels() {
    if (!this.usingLevels) {
      try {
        if (!this.language) {
          const configFilePath = CSON.resolve(path.join(this.pkgLanguageDirPath, 'config'));
          const executable = process.platform === 'win32' ? 'run.exe' : 'run';
          const executablePath = path.join(this.pkgLanguageDirPath, 'executables', process.platform, executable);
          const dummyGrammarPath = CSON.resolve(path.join(this.pkgLanguageDirPath, 'grammars', 'dummy'));
          this.dummyGrammar = atom.grammars.readGrammarSync(dummyGrammarPath);
          this.language = this.languageRegistry.readLanguageSync(configFilePath, executablePath);
          this.dummyGrammar.name = this.language.getGrammarName();
          this.dummyGrammar.scopeName = this.language.getScopeName();
          this.dummyGrammar.fileTypes = this.language.getLevelCodeFileTypes();
          this.language.setDummyGrammar(this.dummyGrammar);
        }

        atom.grammars.addGrammar(this.dummyGrammar);
        this.languageRegistry.addLanguage(this.language);

        this.usingLevels = true;
        this.setUpConfigManagement();
        process.env.LRB_WHITELIST_PATH = path.join(this.pkgLanguageDirPath, 'whitelist');
      } catch (error) {
        atom.notifications.addFatalError(`Failed to load the language from the ${this.pkgName} package`, {
          detail: error.message,
          stack: error.stack,
          dismissable: true
        });
      }
    }
  },

  stopUsingLevels() {
    if (this.usingLevels) {
      atom.grammars.removeGrammar(this.dummyGrammar);
      this.languageRegistry.removeLanguage(this.language);
      this.usingLevels = false;
      this.configSubscription.dispose();
      delete process.env.LRB_WHITELIST_PATH;
    }
  },

  config: {
    rubyInterpreterDirectoryPath: {
      title: 'Ruby Interpreter Directory Path',
      description: `The path to the directory that contains the Ruby interpreter
        (a file named \`ruby\` on macOS or Linux and \`ruby.exe\` on Windows, respectively).
        If no path is given, the \`PATH\` environment variable will be checked automatically.`,
      type: 'string',
      default: ''
    }
  },

  setExecutionCommandPatterns(directory) {
    const rubyInterpreterPath = path.join(directory.trim(), 'ruby');
    this.language.setExecutionCommandPatterns([`${rubyInterpreterPath} <filePath>`]);
  },

  setUpConfigManagement() {
    const configKeyPath = `${this.pkgName}.rubyInterpreterDirectoryPath`;
    this.setExecutionCommandPatterns(atom.config.get(configKeyPath));
    this.configSubscription = atom.config.onDidChange(configKeyPath, ({newValue}) => {
      this.setExecutionCommandPatterns(newValue);
    });
  }
};<commit_msg>Replaced var keyword with const<commit_after>'use babel';

import path from 'path';
import CSON from 'season';

export default {
  activate() {
    this.pkgName = 'levels-language-ruby';
    const pkgDirPath = atom.packages.resolvePackagePath(this.pkgName);
    this.pkgLanguageDirPath = path.join(pkgDirPath, 'language');

    const pkgSubscription = atom.packages.onDidActivatePackage(pkg => {
      if (pkg.name === this.pkgName) {
        if (this.consumedLevels) {
          this.startUsingLevels();
        }

        pkgSubscription.dispose();
        this.activated = true;
      }
    });
  },

  deactivate() {
    this.stopUsingLevels();
    this.consumedLevels = false;
    this.activated = false;
  },

  consumeLevels({languageRegistry}) {
    this.languageRegistry = languageRegistry;
    if (this.activated) {
      this.startUsingLevels();
    }
    this.consumedLevels = true;
  },

  startUsingLevels() {
    if (!this.usingLevels) {
      try {
        if (!this.language) {
          const configFilePath = CSON.resolve(path.join(this.pkgLanguageDirPath, 'config'));
          const executable = process.platform === 'win32' ? 'run.exe' : 'run';
          const executablePath = path.join(this.pkgLanguageDirPath, 'executables', process.platform, executable);
          const dummyGrammarPath = CSON.resolve(path.join(this.pkgLanguageDirPath, 'grammars', 'dummy'));
          this.dummyGrammar = atom.grammars.readGrammarSync(dummyGrammarPath);
          this.language = this.languageRegistry.readLanguageSync(configFilePath, executablePath);
          this.dummyGrammar.name = this.language.getGrammarName();
          this.dummyGrammar.scopeName = this.language.getScopeName();
          this.dummyGrammar.fileTypes = this.language.getLevelCodeFileTypes();
          this.language.setDummyGrammar(this.dummyGrammar);
        }

        atom.grammars.addGrammar(this.dummyGrammar);
        this.languageRegistry.addLanguage(this.language);

        this.usingLevels = true;
        this.setUpConfigManagement();
        process.env.LRB_WHITELIST_PATH = path.join(this.pkgLanguageDirPath, 'whitelist');
      } catch (error) {
        atom.notifications.addFatalError(`Failed to load the language from the ${this.pkgName} package`, {
          detail: error.message,
          stack: error.stack,
          dismissable: true
        });
      }
    }
  },

  stopUsingLevels() {
    if (this.usingLevels) {
      atom.grammars.removeGrammar(this.dummyGrammar);
      this.languageRegistry.removeLanguage(this.language);
      this.usingLevels = false;
      this.configSubscription.dispose();
      delete process.env.LRB_WHITELIST_PATH;
    }
  },

  config: {
    rubyInterpreterDirectoryPath: {
      title: 'Ruby Interpreter Directory Path',
      description: `The path to the directory that contains the Ruby interpreter
        (a file named \`ruby\` on macOS or Linux and \`ruby.exe\` on Windows, respectively).
        If no path is given, the \`PATH\` environment variable will be checked automatically.`,
      type: 'string',
      default: ''
    }
  },

  setExecutionCommandPatterns(directory) {
    const rubyInterpreterPath = path.join(directory.trim(), 'ruby');
    this.language.setExecutionCommandPatterns([`${rubyInterpreterPath} <filePath>`]);
  },

  setUpConfigManagement() {
    const configKeyPath = `${this.pkgName}.rubyInterpreterDirectoryPath`;
    this.setExecutionCommandPatterns(atom.config.get(configKeyPath));
    this.configSubscription = atom.config.onDidChange(configKeyPath, ({newValue}) => {
      this.setExecutionCommandPatterns(newValue);
    });
  }
};<|endoftext|>


<commit_before>var fs = require('fs'),
    WritableStream = require('readable-stream').Writable,
    inherits = require('util').inherits;

var utils = require('./utils');

function Busboy(opts) {
  if (!(this instanceof Busboy))
    return new Busboy(opts);
  if (opts.highWaterMark !== undefined)
    WritableStream.call(this, { highWaterMark: opts.highWaterMark });
  else
    WritableStream.call(this);

  var self = this;
  this._parser = undefined;

  if (opts.headers && typeof opts.headers['content-type'] === 'string')
    this.parseHeaders(opts.headers);
  this.limits = opts.limits;
  this.once('finish', function() {
    self._parser.end();
  });
}
inherits(Busboy, WritableStream);

Busboy.prototype.parseHeaders = function(headers) {
  this._parser = undefined;
  if (headers['content-type']) {
    var parsed = utils.parseParams(headers['content-type']),
        matched, type;
    for (var i = 0; i < TYPES_LEN; ++i) {
      type = TYPES[i];
      if (typeof type.detect === 'function')
        matched = type.detect(parsed);
      else
        matched = type.detect.test(parsed[0]);
      if (matched)
        break;
    }
    if (matched) {
      this._parser = new type(this, this.limits, headers, parsed);
      return;
    }
  }
  throw new Error('Unsupported content type: ' + headers['content-type']);
};

Busboy.prototype._write = function(chunk, encoding, cb) {
  this._parser.write(chunk);
  cb();
};

var TYPES = [], TYPES_LEN = 0;
fs.readdirSync(__dirname + '/types').forEach(function(type) {
  var typemod = require(__dirname + '/types/' + type);
  if (typemod.detect) {
    TYPES.push(typemod);
    ++TYPES_LEN;
  }
});

module.exports = Busboy;
<commit_msg>main: prefer native streams2 over readable-stream module<commit_after>var fs = require('fs'),
    WritableStream = require('stream').Writable
                     || require('readable-stream').Writable,
    inherits = require('util').inherits;

var utils = require('./utils');

function Busboy(opts) {
  if (!(this instanceof Busboy))
    return new Busboy(opts);
  if (opts.highWaterMark !== undefined)
    WritableStream.call(this, { highWaterMark: opts.highWaterMark });
  else
    WritableStream.call(this);

  var self = this;
  this._parser = undefined;

  if (opts.headers && typeof opts.headers['content-type'] === 'string')
    this.parseHeaders(opts.headers);
  this.limits = opts.limits;
  this.once('finish', function() {
    self._parser && self._parser.end();
  });
}
inherits(Busboy, WritableStream);

Busboy.prototype.parseHeaders = function(headers) {
  this._parser = undefined;
  if (headers['content-type']) {
    var parsed = utils.parseParams(headers['content-type']),
        matched, type;
    for (var i = 0; i < TYPES_LEN; ++i) {
      type = TYPES[i];
      if (typeof type.detect === 'function')
        matched = type.detect(parsed);
      else
        matched = type.detect.test(parsed[0]);
      if (matched)
        break;
    }
    if (matched) {
      this._parser = new type(this, this.limits, headers, parsed);
      return;
    }
  }
  throw new Error('Unsupported content type: ' + headers['content-type']);
};

Busboy.prototype._write = function(chunk, encoding, cb) {
  this._parser.write(chunk);
  cb();
};

var TYPES = [], TYPES_LEN = 0;
fs.readdirSync(__dirname + '/types').forEach(function(type) {
  var typemod = require(__dirname + '/types/' + type);
  if (typemod.detect) {
    TYPES.push(typemod);
    ++TYPES_LEN;
  }
});

module.exports = Busboy;
<|endoftext|>