<commit_before>function delegate (target, callback) {
    return function () { callback.apply (target, arguments); }
}

function Meerkat () {
    this.Initialize ();
}

Meerkat.prototype = {

    progress_listener: null,
    progress_start_ref: 0,
    progress_first_hide: false,

    menu_button_filled: false,

    Initialize: function () {
        this.progress_listener = new MeerkatProgressListener (this);
    },

    Dispose: function () {
        if (this.progress_listener) {
            if (this.progress_listener) {
                gBrowser.removeProgressListener (this.progress_listener);
            }

            this.progress_listener.Dispose ();
            this.progress_listener = null;
        }
    },

    OnBrowserLoad: function () {
        window.removeEventListener ("load", this.OnBrowserLoad, true);

        if (this.progress_listener) {
            gBrowser.addProgressListener (this.progress_listener,
                Components.interfaces.nsIWebProgress.NOTIFY_STATE_DOCUMENT);
        }

        this.HideStatus ();
        this.ConfigureToolbars ();
    },

    OnProgressStart: function () {
        this.ShowStatus ();
    },

    OnProgressStop: function () {
        this.HideStatus ();
    },

    WithStatusBar: function (closure) {
        var status_bar = document.getElementById ("status-bar");
        if (status_bar) {
            delegate (this, closure) (status_bar);
        }

        return false;
    },

    ShowStatus: function () {
        this.progress_start_ref++;
        if (this.progress_start_ref != 1) {
            return;
        }

        this.WithStatusBar (function (bar) bar.collapsed = false);
    },

    HideStatus: function () {
        if (this.progress_start_ref == 0 && this.progress_first_hide) {
            return;
        } else if (this.progress_start_ref > 0) {
            this.progress_start_ref--;
        }

        this.progress_first_hide = true;

        this.WithStatusBar (function (bar) bar.collapsed = true);
    },

    FillMenuButton: function (aParent) {
        if (this.menu_button_filled) {
            return;
        }

        var menu_bar = document.getElementById ("main-menubar");

        if (!menu_bar) {
            aParent.style.display = "none";
            return;
        }

        for (var i = 0; i < menu_bar.childNodes.length; i++) {
            aParent.appendChild (menu_bar.childNodes[i].cloneNode (true));
        }

        aParent.appendChild (document.createElement ("menuseparator"));

        var prefs_item = document.getElementById ("menu_preferences");
        if (prefs_item) {
            aParent.appendChild (prefs_item.cloneNode (true));
        }

        var quit_item = document.getElementById ("menu_FileQuitItem");
        if (quit_item) {
            aParent.appendChild (quit_item.cloneNode (true));
        }

        this.menu_button_filled = true;
    },

    ConfigureToolbars: function () {
        var add_menu_button = false;

        // Only hide the menu bar if it hasn't been customized
        try {
            var menubar = document.getElementById ("toolbar-menubar");
            if (menubar != null && menubar.currentSet == "menubar-items,spring,throbber-box") {
                menubar.collapsed = true;
                add_menu_button = true;
            }
        } catch (e) {
        }

        var navbar = document.getElementById ("nav-bar");
        if (navbar) {
            navbar.setAttribute ("iconsize", "small");
            navbar.collapsed = false;
            document.persist (navbar.id, "iconsize");

            var items = navbar.currentSet.split (",");
            this.InsertAfterItem (items, "urlbar-container", "downloads-button");
            this.InsertAfterItem (items, "downloads-button", "bookmarks-button");
            if (add_menu_button) {
                this.InsertAfterItem (items, "history-button", "meerkat-menu-button");
            }
            this.UpdateToolbar (navbar, items);
        }

        BrowserToolboxCustomizeDone (true);
    },

    InsertAfterItem: function (items, before, after) {
        var index = items.indexOf (before);
        if (items.indexOf (after) < 0) {
            if (index < 0) {
                items.push (after);
            } else {
                items.splice (index + 1, 0, after);
            }
        }
    },

    UpdateToolbar: function (toolbar, items) {
        if (!toolbar) {
            return;
        }

        var items_str = items.join (",");

        toolbar.setAttribute ("currentset", items_str);
        toolbar.currentSet = items_str;
        document.persist (toolbar.id, "currentset");
    }
};

var meerkat = new Meerkat;

window.addEventListener ("load",
    delegate (meerkat, meerkat.OnBrowserLoad), true);

<commit_msg>Ensure the menu button is always last on the toolbar<commit_after>function delegate (target, callback) {
    return function () { callback.apply (target, arguments); }
}

function Meerkat () {
    this.Initialize ();
}

Meerkat.prototype = {

    progress_listener: null,
    progress_start_ref: 0,
    progress_first_hide: false,

    menu_button_filled: false,

    Initialize: function () {
        this.progress_listener = new MeerkatProgressListener (this);
    },

    Dispose: function () {
        if (this.progress_listener) {
            if (this.progress_listener) {
                gBrowser.removeProgressListener (this.progress_listener);
            }

            this.progress_listener.Dispose ();
            this.progress_listener = null;
        }
    },

    OnBrowserLoad: function () {
        window.removeEventListener ("load", this.OnBrowserLoad, true);

        if (this.progress_listener) {
            gBrowser.addProgressListener (this.progress_listener,
                Components.interfaces.nsIWebProgress.NOTIFY_STATE_DOCUMENT);
        }

        this.HideStatus ();
        this.ConfigureToolbars ();
    },

    OnProgressStart: function () {
        this.ShowStatus ();
    },

    OnProgressStop: function () {
        this.HideStatus ();
    },

    WithStatusBar: function (closure) {
        var status_bar = document.getElementById ("status-bar");
        if (status_bar) {
            delegate (this, closure) (status_bar);
        }

        return false;
    },

    ShowStatus: function () {
        this.progress_start_ref++;
        if (this.progress_start_ref != 1) {
            return;
        }

        this.WithStatusBar (function (bar) bar.collapsed = false);
    },

    HideStatus: function () {
        if (this.progress_start_ref == 0 && this.progress_first_hide) {
            return;
        } else if (this.progress_start_ref > 0) {
            this.progress_start_ref--;
        }

        this.progress_first_hide = true;

        this.WithStatusBar (function (bar) bar.collapsed = true);
    },

    FillMenuButton: function (aParent) {
        if (this.menu_button_filled) {
            return;
        }

        var menu_bar = document.getElementById ("main-menubar");

        if (!menu_bar) {
            aParent.style.display = "none";
            return;
        }

        for (var i = 0; i < menu_bar.childNodes.length; i++) {
            aParent.appendChild (menu_bar.childNodes[i].cloneNode (true));
        }

        aParent.appendChild (document.createElement ("menuseparator"));

        var prefs_item = document.getElementById ("menu_preferences");
        if (prefs_item) {
            aParent.appendChild (prefs_item.cloneNode (true));
        }

        var quit_item = document.getElementById ("menu_FileQuitItem");
        if (quit_item) {
            aParent.appendChild (quit_item.cloneNode (true));
        }

        this.menu_button_filled = true;
    },

    ConfigureToolbars: function () {
        var add_menu_button = false;

        // Only hide the menu bar if it hasn't been customized
        try {
            var menubar = document.getElementById ("toolbar-menubar");
            if (menubar != null && menubar.currentSet == "menubar-items,spring,throbber-box") {
                menubar.collapsed = true;
                add_menu_button = true;
            }
        } catch (e) {
        }

        var navbar = document.getElementById ("nav-bar");
        if (navbar) {
            navbar.setAttribute ("iconsize", "small");
            navbar.collapsed = false;
            document.persist (navbar.id, "iconsize");

            var items = navbar.currentSet.split (",");
            this.InsertAfterItem (items, "urlbar-container", "downloads-button");
            this.InsertAfterItem (items, "downloads-button", "bookmarks-button");
            if (add_menu_button) {
                var index = items.indexOf ("meerkat-menu-button");
                if (index >= 0) {
                    items.splice (index, 1);
                }
                items.push ("meerkat-menu-button");
            }
            this.UpdateToolbar (navbar, items);
        }

        BrowserToolboxCustomizeDone (true);
    },

    InsertAfterItem: function (items, before, after) {
        var index = items.indexOf (before);
        if (items.indexOf (after) < 0) {
            if (index < 0) {
                items.push (after);
            } else {
                items.splice (index + 1, 0, after);
            }
        }
    },

    UpdateToolbar: function (toolbar, items) {
        if (!toolbar) {
            return;
        }

        var items_str = items.join (",");

        toolbar.setAttribute ("currentset", items_str);
        toolbar.currentSet = items_str;
        document.persist (toolbar.id, "currentset");
    }
};

var meerkat = new Meerkat;

window.addEventListener ("load",
    delegate (meerkat, meerkat.OnBrowserLoad), true);

<|endoftext|>


<commit_before>import primitive from 'brique/string_utils';

function data(el, namespace) {
  var options = {};
  var set = el.dataset;

  for (var key in set) {
    var k = key;
    if (namespace != null) {
      k = k.replace(new RegExp('^' + namespace), '');
      k = k.charAt(0).toLowerCase() + k.slice(1);
    }
    options[k] = primitive(set[key]);
  }

  return options;
}

export data;
<commit_msg>Call hasOwnProperty when iterating on dataset<commit_after>import primitive from 'brique/string_utils';

function data(el, namespace) {
  var options = {};
  var set = el.dataset;

  for (var key in set) {
    if (!set.hasOwnProperty(key)) { continue; }

    var k = key;
    if (namespace != null) {
      k = k.replace(new RegExp('^' + namespace), '');
      k = k.charAt(0).toLowerCase() + k.slice(1);
    }
    options[k] = primitive(set[key]);
  }

  return options;
}

export data;
<|endoftext|>


<commit_before>'use strict'

const {BrowserWindow, MenuItem, webContents} = require('electron')
const EventEmitter = require('events').EventEmitter
const v8Util = process.atomBinding('v8_util')
const bindings = process.atomBinding('menu')

// Automatically generated radio menu item's group id.
var nextGroupId = 0

// Search between separators to find a radio menu item and return its group id,
// otherwise generate a group id.
var generateGroupId = function (items, pos) {
  var i, item, j, k, ref1, ref2, ref3
  if (pos > 0) {
    for (i = j = ref1 = pos - 1; ref1 <= 0 ? j <= 0 : j >= 0; i = ref1 <= 0 ? ++j : --j) {
      item = items[i]
      if (item.type === 'radio') {
        return item.groupId
      }
      if (item.type === 'separator') {
        break
      }
    }
  } else if (pos < items.length) {
    for (i = k = ref2 = pos, ref3 = items.length - 1; ref2 <= ref3 ? k <= ref3 : k >= ref3; i = ref2 <= ref3 ? ++k : --k) {
      item = items[i]
      if (item.type === 'radio') {
        return item.groupId
      }
      if (item.type === 'separator') {
        break
      }
    }
  }
  return ++nextGroupId
}

// Returns the index of item according to |id|.
var indexOfItemById = function (items, id) {
  var i, item, j, len
  for (i = j = 0, len = items.length; j < len; i = ++j) {
    item = items[i]
    if (item.id === id) {
      return i
    }
  }
  return -1
}

// Returns the index of where to insert the item according to |position|.
var indexToInsertByPosition = function (items, position) {
  var insertIndex
  if (!position) {
    return items.length
  }
  const [query, id] = position.split('=')
  insertIndex = indexOfItemById(items, id)
  if (insertIndex === -1 && query !== 'endof') {
    console.warn("Item with id '" + id + "' is not found")
    return items.length
  }
  switch (query) {
    case 'after':
      insertIndex++
      break
    case 'endof':

      // If the |id| doesn't exist, then create a new group with the |id|.
      if (insertIndex === -1) {
        items.push({
          id: id,
          type: 'separator'
        })
        insertIndex = items.length - 1
      }

      // Find the end of the group.
      insertIndex++
      while (insertIndex < items.length && items[insertIndex].type !== 'separator') {
        insertIndex++
      }
  }
  return insertIndex
}

const Menu = bindings.Menu

Object.setPrototypeOf(Menu.prototype, EventEmitter.prototype)

Menu.prototype._init = function () {
  this.commandsMap = {}
  this.groupsMap = {}
  this.items = []
  this.delegate = {
    isCommandIdChecked: (commandId) => {
      var command = this.commandsMap[commandId]
      return command != null ? command.checked : undefined
    },
    isCommandIdEnabled: (commandId) => {
      var command = this.commandsMap[commandId]
      return command != null ? command.enabled : undefined
    },
    isCommandIdVisible: (commandId) => {
      var command = this.commandsMap[commandId]
      return command != null ? command.visible : undefined
    },
    getAcceleratorForCommandId: (commandId, useDefaultAccelerator) => {
      const command = this.commandsMap[commandId]
      if (command == null) return
      if (command.accelerator != null) return command.accelerator
      if (useDefaultAccelerator) return command.getDefaultRoleAccelerator()
    },
    getIconForCommandId: (commandId) => {
      var command = this.commandsMap[commandId]
      return command != null ? command.icon : undefined
    },
    executeCommand: (event, commandId) => {
      const command = this.commandsMap[commandId]
      if (command == null) return
      command.click(event, BrowserWindow.getFocusedWindow(), webContents.getFocusedWebContents())
    },
    menuWillShow: () => {
      // Make sure radio groups have at least one menu item seleted.
      var checked, group, id, j, len, radioItem, ref1
      ref1 = this.groupsMap
      for (id in ref1) {
        group = ref1[id]
        checked = false
        for (j = 0, len = group.length; j < len; j++) {
          radioItem = group[j]
          if (!radioItem.checked) {
            continue
          }
          checked = true
          break
        }
        if (!checked) {
          v8Util.setHiddenValue(group[0], 'checked', true)
        }
      }
    }
  }
}

Menu.prototype.popup = function (window, x, y, positioningItem) {
  let asyncPopup

  // menu.popup(x, y, positioningItem)
  if (window != null && (typeof window !== 'object' || window.constructor !== BrowserWindow)) {
    // Shift.
    positioningItem = y
    y = x
    x = window
    window = null
  }

  // menu.popup(window, {})
  if (x != null && typeof x === 'object') {
    const options = x
    x = options.x
    y = options.y
    positioningItem = options.positioningItem
    asyncPopup = options.async
  }

  // Default to showing in focused window.
  if (window == null) window = BrowserWindow.getFocusedWindow()

  // Default to showing under mouse location.
  if (typeof x !== 'number') x = -1
  if (typeof y !== 'number') y = -1

  // Default to not highlighting any item.
  if (typeof positioningItem !== 'number') positioningItem = -1

  // Default to synchronous for backwards compatibility.
  if (typeof asyncPopup !== 'boolean') asyncPopup = false

  this.popupAt(window, x, y, positioningItem, asyncPopup)
}

Menu.prototype.closePopup = function (window) {
  if (window == null || window.constructor !== BrowserWindow) {
    window = BrowserWindow.getFocusedWindow()
  }
  if (window != null) {
    this.closePopupAt(window.id)
  }
}

Menu.prototype.getMenuItemById = function (id) {
  const items = this.items

  let found = items.find(item => item.id === id) || null
  for (let i = 0, length = items.length; !found && i < length; i++) {
    if (items[i].submenu) {
      found = items[i].submenu.getMenuItemById(id)
    }
  }
  return found
}

Menu.prototype.append = function (item) {
  return this.insert(this.getItemCount(), item)
}

Menu.prototype.insert = function (pos, item) {
  var base, name
  if ((item != null ? item.constructor : void 0) !== MenuItem) {
    throw new TypeError('Invalid item')
  }
  switch (item.type) {
    case 'normal':
      this.insertItem(pos, item.commandId, item.label)
      break
    case 'checkbox':
      this.insertCheckItem(pos, item.commandId, item.label)
      break
    case 'separator':
      this.insertSeparator(pos)
      break
    case 'submenu':
      this.insertSubMenu(pos, item.commandId, item.label, item.submenu)
      break
    case 'radio':
      // Grouping radio menu items.
      item.overrideReadOnlyProperty('groupId', generateGroupId(this.items, pos))
      if ((base = this.groupsMap)[name = item.groupId] == null) {
        base[name] = []
      }
      this.groupsMap[item.groupId].push(item)

      // Setting a radio menu item should flip other items in the group.
      v8Util.setHiddenValue(item, 'checked', item.checked)
      Object.defineProperty(item, 'checked', {
        enumerable: true,
        get: function () {
          return v8Util.getHiddenValue(item, 'checked')
        },
        set: () => {
          var j, len, otherItem, ref1
          ref1 = this.groupsMap[item.groupId]
          for (j = 0, len = ref1.length; j < len; j++) {
            otherItem = ref1[j]
            if (otherItem !== item) {
              v8Util.setHiddenValue(otherItem, 'checked', false)
            }
          }
          return v8Util.setHiddenValue(item, 'checked', true)
        }
      })
      this.insertRadioItem(pos, item.commandId, item.label, item.groupId)
  }
  if (item.sublabel != null) {
    this.setSublabel(pos, item.sublabel)
  }
  if (item.icon != null) {
    this.setIcon(pos, item.icon)
  }
  if (item.role != null) {
    this.setRole(pos, item.role)
  }

  // Make menu accessable to items.
  item.overrideReadOnlyProperty('menu', this)

  // Remember the items.
  this.items.splice(pos, 0, item)
  this.commandsMap[item.commandId] = item
}

// Force menuWillShow to be called
Menu.prototype._callMenuWillShow = function () {
  if (this.delegate != null) {
    this.delegate.menuWillShow()
  }
  this.items.forEach(function (item) {
    if (item.submenu != null) {
      item.submenu._callMenuWillShow()
    }
  })
}

var applicationMenu = null

Menu.setApplicationMenu = function (menu) {
  if (!(menu === null || menu.constructor === Menu)) {
    throw new TypeError('Invalid menu')
  }

  // Keep a reference.
  applicationMenu = menu
  if (process.platform === 'darwin') {
    if (menu === null) {
      return
    }
    menu._callMenuWillShow()
    bindings.setApplicationMenu(menu)
  } else {
    BrowserWindow.getAllWindows().forEach(function (window) {
      window.setMenu(menu)
    })
  }
}

Menu.getApplicationMenu = function () {
  return applicationMenu
}

Menu.sendActionToFirstResponder = bindings.sendActionToFirstResponder

Menu.buildFromTemplate = function (template) {
  var insertIndex, item, j, k, len, len1, menu, menuItem, positionedTemplate
  if (!Array.isArray(template)) {
    throw new TypeError('Invalid template for Menu')
  }
  positionedTemplate = []
  insertIndex = 0
  for (j = 0, len = template.length; j < len; j++) {
    item = template[j]
    if (item.position) {
      insertIndex = indexToInsertByPosition(positionedTemplate, item.position)
    } else {
      // If no |position| is specified, insert after last item.
      insertIndex++
    }
    positionedTemplate.splice(insertIndex, 0, item)
  }
  menu = new Menu()
  for (k = 0, len1 = positionedTemplate.length; k < len1; k++) {
    item = positionedTemplate[k]
    if (typeof item !== 'object') {
      throw new TypeError('Invalid template for MenuItem')
    }
    menuItem = new MenuItem(item)
    menu.append(menuItem)
  }
  return menu
}

module.exports = Menu
<commit_msg>refactor indexOfItemById<commit_after>'use strict'

const {BrowserWindow, MenuItem, webContents} = require('electron')
const EventEmitter = require('events').EventEmitter
const v8Util = process.atomBinding('v8_util')
const bindings = process.atomBinding('menu')

// Automatically generated radio menu item's group id.
var nextGroupId = 0

// Search between separators to find a radio menu item and return its group id,
// otherwise generate a group id.
function generateGroupId (items, pos) {
  var i, item, j, k, ref1, ref2, ref3
  if (pos > 0) {
    for (i = j = ref1 = pos - 1; ref1 <= 0 ? j <= 0 : j >= 0; i = ref1 <= 0 ? ++j : --j) {
      item = items[i]
      if (item.type === 'radio') {
        return item.groupId
      }
      if (item.type === 'separator') {
        break
      }
    }
  } else if (pos < items.length) {
    for (i = k = ref2 = pos, ref3 = items.length - 1; ref2 <= ref3 ? k <= ref3 : k >= ref3; i = ref2 <= ref3 ? ++k : --k) {
      item = items[i]
      if (item.type === 'radio') {
        return item.groupId
      }
      if (item.type === 'separator') {
        break
      }
    }
  }
  return ++nextGroupId
}

// Returns the index of item according to |id|.
function indexOfItemById (items, id) {
  for (let idx = 0; idx < items.length; idx += 1) {
    const item = items[idx]
    if (item.id === id) return idx
  }
  return -1
}

// Returns the index of where to insert the item according to |position|.
function indexToInsertByPosition (items, position) {
  var insertIndex
  if (!position) {
    return items.length
  }
  const [query, id] = position.split('=')
  insertIndex = indexOfItemById(items, id)
  if (insertIndex === -1 && query !== 'endof') {
    console.warn("Item with id '" + id + "' is not found")
    return items.length
  }
  switch (query) {
    case 'after':
      insertIndex++
      break
    case 'endof':

      // If the |id| doesn't exist, then create a new group with the |id|.
      if (insertIndex === -1) {
        items.push({
          id: id,
          type: 'separator'
        })
        insertIndex = items.length - 1
      }

      // Find the end of the group.
      insertIndex++
      while (insertIndex < items.length && items[insertIndex].type !== 'separator') {
        insertIndex++
      }
  }
  return insertIndex
}

const Menu = bindings.Menu

Object.setPrototypeOf(Menu.prototype, EventEmitter.prototype)

Menu.prototype._init = function () {
  this.commandsMap = {}
  this.groupsMap = {}
  this.items = []
  this.delegate = {
    isCommandIdChecked: (commandId) => {
      var command = this.commandsMap[commandId]
      return command != null ? command.checked : undefined
    },
    isCommandIdEnabled: (commandId) => {
      var command = this.commandsMap[commandId]
      return command != null ? command.enabled : undefined
    },
    isCommandIdVisible: (commandId) => {
      var command = this.commandsMap[commandId]
      return command != null ? command.visible : undefined
    },
    getAcceleratorForCommandId: (commandId, useDefaultAccelerator) => {
      const command = this.commandsMap[commandId]
      if (command == null) return
      if (command.accelerator != null) return command.accelerator
      if (useDefaultAccelerator) return command.getDefaultRoleAccelerator()
    },
    getIconForCommandId: (commandId) => {
      var command = this.commandsMap[commandId]
      return command != null ? command.icon : undefined
    },
    executeCommand: (event, commandId) => {
      const command = this.commandsMap[commandId]
      if (command == null) return
      command.click(event, BrowserWindow.getFocusedWindow(), webContents.getFocusedWebContents())
    },
    menuWillShow: () => {
      // Make sure radio groups have at least one menu item seleted.
      var checked, group, id, j, len, radioItem, ref1
      ref1 = this.groupsMap
      for (id in ref1) {
        group = ref1[id]
        checked = false
        for (j = 0, len = group.length; j < len; j++) {
          radioItem = group[j]
          if (!radioItem.checked) {
            continue
          }
          checked = true
          break
        }
        if (!checked) {
          v8Util.setHiddenValue(group[0], 'checked', true)
        }
      }
    }
  }
}

Menu.prototype.popup = function (window, x, y, positioningItem) {
  let asyncPopup

  // menu.popup(x, y, positioningItem)
  if (window != null && (typeof window !== 'object' || window.constructor !== BrowserWindow)) {
    // Shift.
    positioningItem = y
    y = x
    x = window
    window = null
  }

  // menu.popup(window, {})
  if (x != null && typeof x === 'object') {
    const options = x
    x = options.x
    y = options.y
    positioningItem = options.positioningItem
    asyncPopup = options.async
  }

  // Default to showing in focused window.
  if (window == null) window = BrowserWindow.getFocusedWindow()

  // Default to showing under mouse location.
  if (typeof x !== 'number') x = -1
  if (typeof y !== 'number') y = -1

  // Default to not highlighting any item.
  if (typeof positioningItem !== 'number') positioningItem = -1

  // Default to synchronous for backwards compatibility.
  if (typeof asyncPopup !== 'boolean') asyncPopup = false

  this.popupAt(window, x, y, positioningItem, asyncPopup)
}

Menu.prototype.closePopup = function (window) {
  if (window == null || window.constructor !== BrowserWindow) {
    window = BrowserWindow.getFocusedWindow()
  }
  if (window != null) {
    this.closePopupAt(window.id)
  }
}

Menu.prototype.getMenuItemById = function (id) {
  const items = this.items

  let found = items.find(item => item.id === id) || null
  for (let i = 0, length = items.length; !found && i < length; i++) {
    if (items[i].submenu) {
      found = items[i].submenu.getMenuItemById(id)
    }
  }
  return found
}

Menu.prototype.append = function (item) {
  return this.insert(this.getItemCount(), item)
}

Menu.prototype.insert = function (pos, item) {
  var base, name
  if ((item != null ? item.constructor : void 0) !== MenuItem) {
    throw new TypeError('Invalid item')
  }
  switch (item.type) {
    case 'normal':
      this.insertItem(pos, item.commandId, item.label)
      break
    case 'checkbox':
      this.insertCheckItem(pos, item.commandId, item.label)
      break
    case 'separator':
      this.insertSeparator(pos)
      break
    case 'submenu':
      this.insertSubMenu(pos, item.commandId, item.label, item.submenu)
      break
    case 'radio':
      // Grouping radio menu items.
      item.overrideReadOnlyProperty('groupId', generateGroupId(this.items, pos))
      if ((base = this.groupsMap)[name = item.groupId] == null) {
        base[name] = []
      }
      this.groupsMap[item.groupId].push(item)

      // Setting a radio menu item should flip other items in the group.
      v8Util.setHiddenValue(item, 'checked', item.checked)
      Object.defineProperty(item, 'checked', {
        enumerable: true,
        get: function () {
          return v8Util.getHiddenValue(item, 'checked')
        },
        set: () => {
          var j, len, otherItem, ref1
          ref1 = this.groupsMap[item.groupId]
          for (j = 0, len = ref1.length; j < len; j++) {
            otherItem = ref1[j]
            if (otherItem !== item) {
              v8Util.setHiddenValue(otherItem, 'checked', false)
            }
          }
          return v8Util.setHiddenValue(item, 'checked', true)
        }
      })
      this.insertRadioItem(pos, item.commandId, item.label, item.groupId)
  }
  if (item.sublabel != null) {
    this.setSublabel(pos, item.sublabel)
  }
  if (item.icon != null) {
    this.setIcon(pos, item.icon)
  }
  if (item.role != null) {
    this.setRole(pos, item.role)
  }

  // Make menu accessable to items.
  item.overrideReadOnlyProperty('menu', this)

  // Remember the items.
  this.items.splice(pos, 0, item)
  this.commandsMap[item.commandId] = item
}

// Force menuWillShow to be called
Menu.prototype._callMenuWillShow = function () {
  if (this.delegate != null) {
    this.delegate.menuWillShow()
  }
  this.items.forEach(function (item) {
    if (item.submenu != null) {
      item.submenu._callMenuWillShow()
    }
  })
}

var applicationMenu = null

Menu.setApplicationMenu = function (menu) {
  if (!(menu === null || menu.constructor === Menu)) {
    throw new TypeError('Invalid menu')
  }

  // Keep a reference.
  applicationMenu = menu
  if (process.platform === 'darwin') {
    if (menu === null) {
      return
    }
    menu._callMenuWillShow()
    bindings.setApplicationMenu(menu)
  } else {
    BrowserWindow.getAllWindows().forEach(function (window) {
      window.setMenu(menu)
    })
  }
}

Menu.getApplicationMenu = function () {
  return applicationMenu
}

Menu.sendActionToFirstResponder = bindings.sendActionToFirstResponder

Menu.buildFromTemplate = function (template) {
  var insertIndex, item, j, k, len, len1, menu, menuItem, positionedTemplate
  if (!Array.isArray(template)) {
    throw new TypeError('Invalid template for Menu')
  }
  positionedTemplate = []
  insertIndex = 0
  for (j = 0, len = template.length; j < len; j++) {
    item = template[j]
    if (item.position) {
      insertIndex = indexToInsertByPosition(positionedTemplate, item.position)
    } else {
      // If no |position| is specified, insert after last item.
      insertIndex++
    }
    positionedTemplate.splice(insertIndex, 0, item)
  }
  menu = new Menu()
  for (k = 0, len1 = positionedTemplate.length; k < len1; k++) {
    item = positionedTemplate[k]
    if (typeof item !== 'object') {
      throw new TypeError('Invalid template for MenuItem')
    }
    menuItem = new MenuItem(item)
    menu.append(menuItem)
  }
  return menu
}

module.exports = Menu
<|endoftext|>


<commit_before>import { isArray } from './../common/util/check'
import { remAttr, getAttr, getOuterHTML, createDOMPlaceholder, createFrag } from './../common/util/dom'
import { defineProperty, each } from './../common/util/misc'
import { tmpl } from 'riot-tmpl'
import Tag from './tag'

import {
  T_STRING,
  T_OBJECT,
  __TAG_IMPL,
  RE_SPECIAL_TAGS,
  FIREFOX
} from './../common/global-variables'

import {
  moveChildTag,
  getTag,
  getTagName,
  arrayishAdd,
  arrayishRemove,
  makeVirtual,
  moveVirtual
} from './../common/util/tags'

const MOVE = 'MOVE'
const INSERT = 'INSERT'
const UPDATE = 'UPDATE'

/**
 * Convert the item looped into an object used to extend the child tag properties
 * @param   { Object } expr - object containing the keys used to extend the children tags
 * @param   { * } key - value to assign to the new object returned
 * @param   { * } val - value containing the position of the item in the array
 * @param   { Object } base - prototype object for the new item
 * @returns { Object } - new object containing the values of the original item
 *
 * The variables 'key' and 'val' are arbitrary.
 * They depend on the collection type looped (Array, Object)
 * and on the expression used on the each tag
 *
 */
function mkitem(expr, key, val, base) {
  var item = base ? Object.create(base) : {}
  item[expr.key] = key
  if (expr.pos) item[expr.pos] = val
  return item
}

/**
 * Unmount the redundant tags
 * @param   { Array } items - array containing the current items to loop
 * @param   { Array } tags - array containing all the children tags
 * @param   { String } tagName - key used to identify the type of tag
 * @param   { Object } parent - parent tag to remove the child from
 */
function unmountRedundant(items, tags, tagName, parent) {

  var i = tags.length,
    j = items.length,
    t

  while (i > j) {
    t = tags[--i]
    tags.splice(i, 1)
    t.unmount()
    arrayishRemove(parent.tags, tagName, t, true)
  }
}

/**
 * Move the nested custom tags in non custom loop tags
 * @param   { Object } child - non custom loop tag
 * @param   { Number } i - current position of the loop tag
 */
function moveNestedTags(child, i) {
  each(Object.keys(child.tags), function(tagName) {
    var tag = child.tags[tagName]
    if (isArray(tag))
      each(tag, function (t) {
        moveChildTag(t, tagName, i)
      })
    else
      moveChildTag(tag, tagName, i)
  })
}

/**
 * Move a child tag
 * @param { Object } patch - all the data needed to handle the move
 */
function move(patch) {
  var { i, tags, isVirtual, tag, root, prevBase, item } = patch

  // update the tag...
  tag.update(item)

  // and move it
  if (isVirtual)
    moveVirtual(tag, root, tags[i])
  else if (tags[i].root.parentNode)
    root.insertBefore(tag.root, root.childNodes[prevBase + i])
}

/**
 * Insert and mount a child tag
 * @param { Object } patch - all the data needed to handle the insertion
 */
function insert(patch) {
  var { i, tags, isVirtual, tag, frag, root, mustAppend, prevBase } = patch,
    dom

  // mount the tag
  tag.mount()
  dom = tag.root

  if (isVirtual)
    makeVirtual(tag, frag, mustAppend ? null : tags[i])
  else
    if (mustAppend)
      frag.appendChild(dom)
    else
      root.insertBefore(dom, root.childNodes[prevBase + i])
}

/**
 * Update option nodes that seem to be buggy on Firefox see also #1374
 * @param   { Object } root - <select> tag
 */
function updateSelect(root) {
  for (var n = 0; n < root.length; n++) {
    if (root[n].__riot1374) {
      root.selectedIndex = n  // clear other options
      delete root[n].__riot1374
      break
    }
  }
}

/**
 * Manage tags having the 'each'
 * @param   { Object } dom - DOM node we need to loop
 * @param   { Tag } parent - parent tag instance where the dom node is contained
 * @param   { String } expr - string contained in the 'each' attribute
 * @returns { Object } expression object for this each loop
 */
export default function _each(dom, parent, expr) {

  // remove the each property from the original tag
  remAttr(dom, 'each')

  var mustReorder = typeof getAttr(dom, 'no-reorder') !== T_STRING || remAttr(dom, 'no-reorder'),
    tagName = getTagName(dom),
    impl = __TAG_IMPL[tagName] || { tmpl: getOuterHTML(dom) },
    useRoot = RE_SPECIAL_TAGS.test(tagName),
    root = dom.parentNode,
    prevBase = [].indexOf.call(root.childNodes, dom.previousSibling) + 1,
    ref = createDOMPlaceholder(),
    child = getTag(dom),
    ifExpr = getAttr(dom, 'if'),
    isOption = tagName.toLowerCase() === 'option', // the option tags must be treated differently
    tags = [],
    oldItems = [],
    hasKeys,
    isVirtual = dom.tagName == 'VIRTUAL'

  // parse the each expression
  expr = tmpl.loopKeys(expr)
  expr.isLoop = true

  if (ifExpr) remAttr(dom, 'if')

  // insert a marked where the loop tags will be injected
  root.insertBefore(ref, dom)
  root.removeChild(dom)

  expr.update = function updateEach() {
    // get the new items collection
    var items = tmpl(expr.val, parent),
      patches = [],
      // create a fragment to hold the new DOM nodes to inject in the parent tag
      frag = createFrag()

    root = ref.parentNode

    // object loop. any changes cause full redraw
    if (!isArray(items)) {
      hasKeys = items || false
      items = hasKeys ?
        Object.keys(items).map(function (key) {
          return mkitem(expr, key, items[key])
        }) : []
    }

    if (ifExpr) {
      items = items.filter(function(item, i) {
        var context = mkitem(expr, item, i, parent)
        return !!tmpl(ifExpr, context)
      })
    }

    // loop all the new items
    each(items, function(item, i) {
      // reorder only if the items are objects
      var
        _mustReorder = mustReorder && typeof item == T_OBJECT && !hasKeys,
        oldPos = oldItems.indexOf(item),
        pos = ~oldPos && _mustReorder ? oldPos : i,
        // does a tag exist in this position?
        tag = tags[pos]

      item = !hasKeys && expr.key ? mkitem(expr, item, i) : item

      // new tag
      if (
        !_mustReorder && !tag // with no-reorder we just update the old tags
        ||
        _mustReorder && !~oldPos || !tag // by default we always try to reorder the DOM elements
      ) {

        tag = new Tag(impl, {
          parent,
          isLoop: true,
          anonymous: !__TAG_IMPL[tagName],
          root: useRoot ? root : dom.cloneNode(),
          item
        }, dom.innerHTML)

        patches.push({
          type: INSERT,
          mustAppend: i == tags.length,
          root, i, tags, isVirtual, tag, frag, prevBase
        })

        if (i != tags.length) oldItems.splice(i, 0, item)
        tags.splice(i, 0, tag)
        if (child) arrayishAdd(parent.tags, tagName, tag, true)
        pos = i // handled here so no move
      } else patches.push({ tag, item, type: UPDATE })

      // reorder the tag if it's not located in its previous position
      if (pos !== i && _mustReorder) {
        patches.push({
          type: MOVE,
          item, i, tags, isVirtual, tag, dom, frag, root, prevBase
        })

        // update the position attribute if it exists
        if (expr.pos) tag[expr.pos] = i
        // move the old tag instance
        tags.splice(i, 0, tags.splice(pos, 1)[0])
        // move the old item
        oldItems.splice(i, 0, oldItems.splice(pos, 1)[0])
        // if the loop tags are not custom
        // we need to move all their custom tags into the right position
        if (!child && tag.tags) moveNestedTags(tag, i)
      }

      // cache the original item to use it in the events bound to this node
      // and its children
      tag._item = item
      // cache the real parent tag internally
      defineProperty(tag, '_parent', parent)
    })

    // update the DOM
    each(patches, (patch) => {
      switch (patch.type) {
      case INSERT:
        insert(patch)
        break
      case MOVE:
        move(patch)
        break
      default:
        // just update (patch.type === UPDATE)
        patch.tag.update(patch.item)
      }
    })

    // remove the redundant tags
    unmountRedundant(items, tags, tagName, parent)

    // insert the new nodes
    if (frag.childNodes) root.insertBefore(frag, ref)

    // #1374 FireFox bug in <option selected={expression}>
    if (isOption && FIREFOX && !root.multiple) updateSelect(root)

    // clone the items array
    oldItems = items.slice()
  }

  expr.unmount = function() {
    each(tags, function(t) { t.unmount() })
  }

  return expr
}
<commit_msg>tags out of sync for virtual<commit_after>import { isArray } from './../common/util/check'
import { remAttr, getAttr, getOuterHTML, createDOMPlaceholder, createFrag } from './../common/util/dom'
import { defineProperty, each } from './../common/util/misc'
import { tmpl } from 'riot-tmpl'
import Tag from './tag'

import {
  T_STRING,
  T_OBJECT,
  __TAG_IMPL,
  RE_SPECIAL_TAGS,
  FIREFOX
} from './../common/global-variables'

import {
  moveChildTag,
  getTag,
  getTagName,
  arrayishAdd,
  arrayishRemove,
  makeVirtual,
  moveVirtual
} from './../common/util/tags'

const MOVE = 'MOVE'
const INSERT = 'INSERT'
const UPDATE = 'UPDATE'

/**
 * Convert the item looped into an object used to extend the child tag properties
 * @param   { Object } expr - object containing the keys used to extend the children tags
 * @param   { * } key - value to assign to the new object returned
 * @param   { * } val - value containing the position of the item in the array
 * @param   { Object } base - prototype object for the new item
 * @returns { Object } - new object containing the values of the original item
 *
 * The variables 'key' and 'val' are arbitrary.
 * They depend on the collection type looped (Array, Object)
 * and on the expression used on the each tag
 *
 */
function mkitem(expr, key, val, base) {
  var item = base ? Object.create(base) : {}
  item[expr.key] = key
  if (expr.pos) item[expr.pos] = val
  return item
}

/**
 * Unmount the redundant tags
 * @param   { Array } items - array containing the current items to loop
 * @param   { Array } tags - array containing all the children tags
 * @param   { String } tagName - key used to identify the type of tag
 * @param   { Object } parent - parent tag to remove the child from
 */
function unmountRedundant(items, tags, tagName, parent) {

  var i = tags.length,
    j = items.length,
    t

  while (i > j) {
    t = tags[--i]
    tags.splice(i, 1)
    t.unmount()
    arrayishRemove(parent.tags, tagName, t, true)
  }
}

/**
 * Move the nested custom tags in non custom loop tags
 * @param   { Object } child - non custom loop tag
 * @param   { Number } i - current position of the loop tag
 */
function moveNestedTags(child, i) {
  each(Object.keys(child.tags), function(tagName) {
    var tag = child.tags[tagName]
    if (isArray(tag))
      each(tag, function (t) {
        moveChildTag(t, tagName, i)
      })
    else
      moveChildTag(tag, tagName, i)
  })
}

/**
 * Move a child tag
 * @param { Object } patch - all the data needed to handle the move
 */
function move(patch) {
  var { i, tags, isVirtual, tag, root, prevBase, item } = patch

  // update the tag...
  tag.update(item)

  // and move it
  if (isVirtual)
    moveVirtual(tag, root, tags[i])
  else if (tags[i].root.parentNode)
    root.insertBefore(tag.root, root.childNodes[prevBase + i])
}

/**
 * Insert and mount a child tag
 * @param { Object } patch - all the data needed to handle the insertion
 */
function insert(patch) {
  var { i, tags, isVirtual, tag, frag, root, mustAppend, prevBase } = patch,
    dom

  // mount the tag
  tag.mount()
  dom = tag.root

  if (isVirtual) {
    if (mustAppend)
      makeVirtual(tag, frag)
    else
      makeVirtual(tag, root, tags[i])
    tags.splice(i, 0, tag)
  }
  else
    if (mustAppend)
      frag.appendChild(dom)
    else
      root.insertBefore(dom, root.childNodes[prevBase + i])
}

/**
 * Update option nodes that seem to be buggy on Firefox see also #1374
 * @param   { Object } root - <select> tag
 */
function updateSelect(root) {
  for (var n = 0; n < root.length; n++) {
    if (root[n].__riot1374) {
      root.selectedIndex = n  // clear other options
      delete root[n].__riot1374
      break
    }
  }
}

/**
 * Manage tags having the 'each'
 * @param   { Object } dom - DOM node we need to loop
 * @param   { Tag } parent - parent tag instance where the dom node is contained
 * @param   { String } expr - string contained in the 'each' attribute
 * @returns { Object } expression object for this each loop
 */
export default function _each(dom, parent, expr) {

  // remove the each property from the original tag
  remAttr(dom, 'each')

  var mustReorder = typeof getAttr(dom, 'no-reorder') !== T_STRING || remAttr(dom, 'no-reorder'),
    tagName = getTagName(dom),
    impl = __TAG_IMPL[tagName] || { tmpl: getOuterHTML(dom) },
    useRoot = RE_SPECIAL_TAGS.test(tagName),
    root = dom.parentNode,
    prevBase = [].indexOf.call(root.childNodes, dom.previousSibling) + 1,
    ref = createDOMPlaceholder(),
    child = getTag(dom),
    ifExpr = getAttr(dom, 'if'),
    isOption = tagName.toLowerCase() === 'option', // the option tags must be treated differently
    tags = [],
    oldItems = [],
    hasKeys,
    isVirtual = dom.tagName == 'VIRTUAL'

  // parse the each expression
  expr = tmpl.loopKeys(expr)
  expr.isLoop = true

  if (ifExpr) remAttr(dom, 'if')

  // insert a marked where the loop tags will be injected
  root.insertBefore(ref, dom)
  root.removeChild(dom)

  expr.update = function updateEach() {
    // get the new items collection
    var items = tmpl(expr.val, parent),
      patches = [],
      // create a fragment to hold the new DOM nodes to inject in the parent tag
      frag = createFrag()

    root = ref.parentNode

    // object loop. any changes cause full redraw
    if (!isArray(items)) {
      hasKeys = items || false
      items = hasKeys ?
        Object.keys(items).map(function (key) {
          return mkitem(expr, key, items[key])
        }) : []
    }

    if (ifExpr) {
      items = items.filter(function(item, i) {
        var context = mkitem(expr, item, i, parent)
        return !!tmpl(ifExpr, context)
      })
    }

    // loop all the new items
    each(items, function(item, i) {
      // reorder only if the items are objects
      var
        _mustReorder = mustReorder && typeof item == T_OBJECT && !hasKeys,
        oldPos = oldItems.indexOf(item),
        pos = ~oldPos && _mustReorder ? oldPos : i,
        // does a tag exist in this position?
        tag = tags[pos]

      item = !hasKeys && expr.key ? mkitem(expr, item, i) : item

      // new tag
      if (
        !_mustReorder && !tag // with no-reorder we just update the old tags
        ||
        _mustReorder && !~oldPos || !tag // by default we always try to reorder the DOM elements
      ) {

        tag = new Tag(impl, {
          parent,
          isLoop: true,
          anonymous: !__TAG_IMPL[tagName],
          root: useRoot ? root : dom.cloneNode(),
          item
        }, dom.innerHTML)

        patches.push({
          type: INSERT,
          mustAppend: i == tags.length,
          root, i, tags, isVirtual, tag, frag, prevBase
        })

        if (i != tags.length) oldItems.splice(i, 0, item)
        if (!isVirtual) tags.splice(i, 0, tag)
        if (child) arrayishAdd(parent.tags, tagName, tag, true)
        pos = i // handled here so no move
      } else patches.push({ tag, item, type: UPDATE })

      // reorder the tag if it's not located in its previous position
      if (pos !== i && _mustReorder) {
        patches.push({
          type: MOVE,
          item, i, tags, isVirtual, tag, dom, frag, root, prevBase
        })

        // update the position attribute if it exists
        if (expr.pos) tag[expr.pos] = i
        // move the old tag instance
        tags.splice(i, 0, tags.splice(pos, 1)[0])
        // move the old item
        oldItems.splice(i, 0, oldItems.splice(pos, 1)[0])
        // if the loop tags are not custom
        // we need to move all their custom tags into the right position
        if (!child && tag.tags) moveNestedTags(tag, i)
      }

      // cache the original item to use it in the events bound to this node
      // and its children
      tag._item = item
      // cache the real parent tag internally
      defineProperty(tag, '_parent', parent)
    })

    // update the DOM
    each(patches, (patch) => {
      switch (patch.type) {
      case INSERT:
        insert(patch)
        break
      case MOVE:
        move(patch)
        break
      default:
        // just update (patch.type === UPDATE)
        patch.tag.update(patch.item)
      }
    })

    // remove the redundant tags
    unmountRedundant(items, tags, tagName, parent)

    // insert the new nodes
    if (frag.childNodes) root.insertBefore(frag, ref)

    // #1374 FireFox bug in <option selected={expression}>
    if (isOption && FIREFOX && !root.multiple) updateSelect(root)

    // clone the items array
    oldItems = items.slice()
  }

  expr.unmount = function() {
    each(tags, function(t) { t.unmount() })
  }

  return expr
}
<|endoftext|>


<commit_before>'use strict';

var request = require('request');
var _ = require('lodash');

const defaultOptions = (options) => {
  const defaults = {
    timeout: 30000,
    headers: {
      'Content-Type': 'application/json'
    }
  };
  if(!options) {
    options = defaults;
  } else {
    options = _.assign(defaults, options);
  }

  return options;
};

class CartoDBMapClient {
  constructor(user, apiKey) {
    this.user = user;
  	this.apiKey = apiKey;
    this.baseURL = 'https://' + this.user + '.carto.com/';
  }

  createNamedMap(options) {
    this.existsNamedMap(options.name).then(() => {

    });
  }

  existsNamedMap(name, options) {
    var $this = this;
    options = defaultOptions(options);
    const promise = new Promise((resolve, reject) => {
      request(_.assign(options, {
        method: 'GET',
        uri: $this.baseURL + 'tiles/template/' + name,
        qs: {
          'api_key': $this.apiKey,
        },
        json: {}
      }), (error, response, body) => {
        if(error) {
          reject(error);
          return;
        }
        resolve({
          exists: response.statusCode !== 404,
          data: body
        });
      });
    });
    return promise;
  }

  searchDatasets(text, page, size, options) {
    var $this = this;
    page = page || 1;
    size = size || 20;
    options = defaultOptions(options);
    const promise = new Promise((resolve, reject) => {
      request(_.assign(options, {
        method: 'GET',
        uri: $this.baseURL + 'api/v1/viz/',
        qs: {
          'api_key': $this.apiKey,
          deepInsights: false,
          'exclude_shared': false,
          types: 'table,remote',
          shared: 'yes',
          q: text,
          page,
          'per_page': size
        },
        json: {}
      }), (error, response, body) => {
        if(error) {
          reject(error);
          return;
        }
        resolve(body);
      });
    });
    return promise;
  }

  searchMaps(text, page, size, options) {
    var $this = this;
    page = page || 1;
    size = size || 20;
    options = defaultOptions(options);
    const promise = new Promise((resolve, reject) => {
      request(_.assign(options, {
        method: 'GET',
        uri: $this.baseURL + 'api/v1/viz/',
        qs: {
          'api_key': $this.apiKey,
          deepInsights: false,
          'exclude_shared': false,
          types: 'derived',
          shared: 'yes',
          q: text,
          page,
          'per_page': size
        },
        json: {}
      }), (error, response, body) => {
        if(error) {
          reject(error);
          return;
        }
        resolve(body);
      });
    });
    return promise;
  }

  getGroupID(name, options) {
    var $this = this;
    options = defaultOptions(options);

    const promise = new Promise((resolve, reject) => {
      request(_.assign(options, {
        method: 'POST',
        uri: $this.baseURL + 'tiles/template/' + name,
        qs: {
          'api_key': $this.apiKey,
        },
        json: {}
      }), (error, response, body) => {
        if(error) {
          reject(error);
          return;
        }
        resolve(body);
      });
    });
    return promise;
  }

  get(suffixUrl, params, options) {
    var $this = this;
    if(!params) {
      params = {};
    }
    options = defaultOptions(options);
    // jshint camelcase: false
    params.api_key = this.apiKey;
    const promise = new Promise((resolve, reject) => {
      request(_.assign(options, {
        method: 'GET',
        uri: $this.baseURL + suffixUrl,
        qs: params,
        json: {}
      }), (error, response, body) => {
        if(error) {
          reject(error);
          return;
        }
        resolve(body);
      });
    });
    return promise;
  }

  post(suffixUrl, params, body, options) {
    var $this = this;
    if(!params) {
      params = {};
    }
    if(!body) {
      body = {};
    }
    options = defaultOptions(options);
    // jshint camelcase: false
    params.api_key = this.apiKey;
    const promise = new Promise((resolve, reject) => {
      request(_.assign(options, {
        method: 'POST',
        uri: $this.baseURL + suffixUrl,
        qs: params,
        json: body
      }), (error, response, body) => {
        if(error) {
          reject(error);
          return;
        }
        resolve(body);
      });
    });
    return promise;
  }

  put(suffixUrl, params, body, options) {
    var $this = this;
    if(!params) {
      params = {};
    }
    if(!body) {
      body = {};
    }
    options = defaultOptions(options);
    // jshint camelcase: false
    params.api_key = this.apiKey;
    const promise = new Promise((resolve, reject) => {
      request(_.assign(options, {
        method: 'PUT',
        uri: $this.baseURL + suffixUrl,
        qs: params,
        json: body
      }), (error, response, body) => {
        if(error) {
          reject(error);
          return;
        }
        resolve(body);
      });
    });
    return promise;
  }
}

module.exports = CartoDBMapClient;
<commit_msg>add delete method<commit_after>'use strict';

var request = require('request');
var _ = require('lodash');

const defaultOptions = (options) => {
  const defaults = {
    timeout: 30000,
    headers: {
      'Content-Type': 'application/json'
    }
  };
  if(!options) {
    options = defaults;
  } else {
    options = _.assign(defaults, options);
  }

  return options;
};

class CartoDBMapClient {
  constructor(user, apiKey) {
    this.user = user;
  	this.apiKey = apiKey;
    this.baseURL = 'https://' + this.user + '.carto.com/';
  }

  createNamedMap(options) {
    this.existsNamedMap(options.name).then(() => {

    });
  }

  existsNamedMap(name, options) {
    var $this = this;
    options = defaultOptions(options);
    const promise = new Promise((resolve, reject) => {
      request(_.assign(options, {
        method: 'GET',
        uri: $this.baseURL + 'tiles/template/' + name,
        qs: {
          'api_key': $this.apiKey,
        },
        json: {}
      }), (error, response, body) => {
        if(error) {
          reject(error);
          return;
        }
        resolve({
          exists: response.statusCode !== 404,
          data: body
        });
      });
    });
    return promise;
  }

  searchDatasets(text, page, size, options) {
    var $this = this;
    page = page || 1;
    size = size || 20;
    options = defaultOptions(options);
    const promise = new Promise((resolve, reject) => {
      request(_.assign(options, {
        method: 'GET',
        uri: $this.baseURL + 'api/v1/viz/',
        qs: {
          'api_key': $this.apiKey,
          deepInsights: false,
          'exclude_shared': false,
          types: 'table,remote',
          shared: 'yes',
          q: text,
          page,
          'per_page': size
        },
        json: {}
      }), (error, response, body) => {
        if(error) {
          reject(error);
          return;
        }
        resolve(body);
      });
    });
    return promise;
  }

  searchMaps(text, page, size, options) {
    var $this = this;
    page = page || 1;
    size = size || 20;
    options = defaultOptions(options);
    const promise = new Promise((resolve, reject) => {
      request(_.assign(options, {
        method: 'GET',
        uri: $this.baseURL + 'api/v1/viz/',
        qs: {
          'api_key': $this.apiKey,
          deepInsights: false,
          'exclude_shared': false,
          types: 'derived',
          shared: 'yes',
          q: text,
          page,
          'per_page': size
        },
        json: {}
      }), (error, response, body) => {
        if(error) {
          reject(error);
          return;
        }
        resolve(body);
      });
    });
    return promise;
  }

  getGroupID(name, options) {
    var $this = this;
    options = defaultOptions(options);

    const promise = new Promise((resolve, reject) => {
      request(_.assign(options, {
        method: 'POST',
        uri: $this.baseURL + 'tiles/template/' + name,
        qs: {
          'api_key': $this.apiKey,
        },
        json: {}
      }), (error, response, body) => {
        if(error) {
          reject(error);
          return;
        }
        resolve(body);
      });
    });
    return promise;
  }

  get(suffixUrl, params, options) {
    var $this = this;
    if(!params) {
      params = {};
    }
    options = defaultOptions(options);
    // jshint camelcase: false
    params.api_key = this.apiKey;
    const promise = new Promise((resolve, reject) => {
      request(_.assign(options, {
        method: 'GET',
        uri: $this.baseURL + suffixUrl,
        qs: params,
        json: {}
      }), (error, response, body) => {
        if(error) {
          reject(error);
          return;
        }
        resolve(body);
      });
    });
    return promise;
  }

  post(suffixUrl, params, body, options) {
    var $this = this;
    if(!params) {
      params = {};
    }
    if(!body) {
      body = {};
    }
    options = defaultOptions(options);
    // jshint camelcase: false
    params.api_key = this.apiKey;
    const promise = new Promise((resolve, reject) => {
      request(_.assign(options, {
        method: 'POST',
        uri: $this.baseURL + suffixUrl,
        qs: params,
        json: body
      }), (error, response, body) => {
        if(error) {
          reject(error);
          return;
        }
        resolve(body);
      });
    });
    return promise;
  }

  put(suffixUrl, params, body, options) {
    var $this = this;
    if(!params) {
      params = {};
    }
    if(!body) {
      body = {};
    }
    options = defaultOptions(options);
    // jshint camelcase: false
    params.api_key = this.apiKey;
    const promise = new Promise((resolve, reject) => {
      request(_.assign(options, {
        method: 'PUT',
        uri: $this.baseURL + suffixUrl,
        qs: params,
        json: body
      }), (error, response, body) => {
        if(error) {
          reject(error);
          return;
        }
        resolve(body);
      });
    });
    return promise;
  }

  delete(suffixUrl, params, body, options) {
    var $this = this;
    if(!params) {
      params = {};
    }
    if(!body) {
      body = {};
    }
    options = defaultOptions(options);
    // jshint camelcase: false
    params.api_key = this.apiKey;
    const promise = new Promise((resolve, reject) => {
      request(_.assign(options, {
        method: 'DELETE',
        uri: $this.baseURL + suffixUrl,
        qs: params,
        json: body
      }), (error, response, body) => {
        if(error) {
          reject(error);
          return;
        }
        resolve(body);
      });
    });
    return promise;
  }
}

module.exports = CartoDBMapClient;
<|endoftext|>


<commit_before><commit_msg>debugging firefox xslt transformations<commit_after><|endoftext|>


<commit_before><commit_msg>error has been changed from string to Error object<commit_after><|endoftext|>


<commit_before>var _ = require('../util').lodash,
    Property = require('./property').Property,
    Script = require('./script').Script,

    Event;

_.inherit((
    /**
     * A Postman event definition that refers to an event to be listened to and a script reference or definition to be
     * executed.
     * @constructor
     * @extends {Property}
     *
     * @param {Object} options Pass the initial definition of the event (name, id, listener name, etc) as the
     * options parameter.
     * @param {String=} [listen] - optional parameter to override the event name to be listened to (handy when creating
     * an event from an array map iterator.)
     */
    Event = function PostmanEvent (options) {
        // this constructor is intended to inherit and as such the super constructor is required to be excuted
        Event.super_.call(this, options);
        if (!options) { return; } // in case definition object is missing, there is no point moving forward

        // @todo: error if no name?
        _.merge(this, /** @lends Event.prototype */ {
            /**
             * Name of the event that this instance is intended to listen to.
             * @type {String}
             */
            listen: _.isString(options.listen) ? options.listen.toLowerCase() : undefined,
            /**
             * The script that is to be executed when this event is triggered.
             * @type {Script}
             */
            script: _.isString(options.script) ? options.script : new Script(options.script),
            /**
             * A flag for events that can be disabled when put within a list
             * @type {Boolean}
             */
            disabled: (options && _.has(options, 'disabled')) ? !!options.disabled : undefined
        });
    }), Property);

_.extend(Event, /** @lends Event */ {

    /**
     * Defines the name of this property for internal use.
     * @private
     * @readOnly
     * @type {String}
     */
    _postman_propertyName: 'Event'
});

module.exports = {
    Event: Event
};
<commit_msg>Removed the duplicate "disabled" processing of Event and elaborated the documentation<commit_after>var _ = require('../util').lodash,
    Property = require('./property').Property,
    Script = require('./script').Script,

    Event;

/**
 * @typedef Event~definition
 * @property {String} listen
 * @property {Script} script
 */
_.inherit((
    /**
     * A Postman event definition that refers to an event to be listened to and a script reference or definition to be
     * executed.
     * @constructor
     * @extends {Property}
     *
     * @param {Event~definition} definition Pass the initial definition of the event (name, id, listener name, etc) as
     * the options parameter.
     */
    Event = function PostmanEvent (definition) {
        // this constructor is intended to inherit and as such the super constructor is required to be excuted
        Event.super_.call(this, definition);
        // set initial values of this event
        definition && this.update(definition);
    }), Property);

_.extend(Event.prototype, /** @lends Event.prototype */ {
    /**
     * Update an event
     * @param {Event~definition} options
     */
    update: function (definition) {
        if (!definition) {
            return;
        }

        _.merge(this, /** @lends Event.prototype */ {
            /**
             * Name of the event that this instance is intended to listen to.
             * @type {String}
             */
            listen: _.isString(definition.listen) ? definition.listen.toLowerCase() : undefined,
            /**
             * The script that is to be executed when this event is triggered.
             * @type {Script}
             */
            script: _.isString(definition.script) ? definition.script : new Script(definition.script)
        });
    }
});

_.extend(Event, /** @lends Event */ {

    /**
     * Defines the name of this property for internal use.
     * @private
     * @readOnly
     * @type {String}
     */
    _postman_propertyName: 'Event'
});

module.exports = {
    Event: Event
};
<|endoftext|>


<commit_before>import androidHelpers from '../android-helpers';
import temp from 'temp';
import { fs, mkdirp } from 'appium-support';
import AdmZip from 'adm-zip';
import path from 'path';
import log from '../logger';

const swipeStepsPerSec = 28;
const dragStepsPerSec = 40;

let commands = {}, helpers = {}, extensions = {};

commands.keyevent = async function (keycode, metastate = null) {
  // TODO deprecate keyevent; currently wd only implements keyevent
  log.warn("keyevent will be deprecated use pressKeyCode");
  return await this.pressKeyCode(keycode, metastate);
};

commands.pressKeyCode = async function (keycode, metastate = null) {
  return await this.bootstrap.sendAction("pressKeyCode", {keycode, metastate});
};

commands.longPressKeyCode = async function (keycode, metastate = null) {
  return await this.bootstrap.sendAction("longPressKeyCode", {keycode, metastate});
};

commands.getOrientation = async function () {
  let orientation = await this.bootstrap.sendAction("orientation", {});
  return orientation.toUpperCase();
};

commands.setOrientation = async function (orientation) {
  orientation = orientation.toUpperCase();
  return await this.bootstrap.sendAction("orientation", {orientation});
};

commands.fakeFlick = async function (xSpeed, ySpeed) {
  return await this.bootstrap.sendAction('flick', {xSpeed, ySpeed});
};

commands.fakeFlickElement = async function (elementId, xoffset, yoffset, speed) {
  let params = {xoffset, yoffset, speed, elementId};
  return await this.bootstrap.sendAction('element:flick', params);
};

commands.swipe = async function (startX, startY, endX, endY, duration, touchCount, elId) {
  if (startX === 'null') {
    startX = 0.5;
  }
  if (startY === 'null') {
    startY = 0.5;
  }
  let swipeOpts = {startX, startY, endX, endY,
                   steps: Math.round(duration * swipeStepsPerSec)};
  // going the long way and checking for undefined and null since
  // we can't be assured `elId` is a string and not an int
  if (typeof elId !== "undefined" && elId !== null) {
    swipeOpts.elementId = elId;
    return await this.bootstrap.sendAction("element:swipe", swipeOpts);
  } else {
    return await this.bootstrap.sendAction("swipe", swipeOpts);
  }
};

commands.pinchClose = async function (startX, startY, endX, endY, duration, percent, steps, elId) {
  let pinchOpts = {
    direction: 'in',
    elementId: elId,
    percent,
    steps
  };
  return await this.bootstrap.sendAction("element:pinch", pinchOpts);
};

commands.pinchOpen = async function (startX, startY, endX, endY, duration, percent, steps, elId) {
  let pinchOpts = {direction: 'out', elementId: elId, percent, steps};
  return await this.bootstrap.sendAction("element:pinch", pinchOpts);
};

commands.flick = async function (element, xSpeed, ySpeed, xOffset, yOffset, speed) {
  if (element) {
    await this.fakeFlickElement(element, xOffset, yOffset, speed);
  } else {
    await this.fakeFlick(xSpeed, ySpeed);
  }
};

commands.drag = async function (startX, startY, endX, endY, duration, touchCount, elementId, destElId) {
  let dragOpts = {elementId, destElId, startX, startY, endX, endY,
                  steps: Math.round(duration * dragStepsPerSec)};
  if (elementId) {
    return await this.bootstrap.sendAction("element:drag", dragOpts);
  } else {
    return await this.bootstrap.sendAction("drag", dragOpts);
  }
};

commands.lock = async function () {
  return await this.adb.lock();
};

commands.isLocked = async function () {
  return await this.adb.isScreenLocked();
};

commands.unlock = async function () {
  return await androidHelpers.unlock(this.adb);
};

commands.openNotifications = async function () {
  return await this.bootstrap.sendAction("openNotification");
};

commands.setLocation = async function (latitude, longitude) {
  return await this.adb.sendTelnetCommand(`geo fix ${longitude} ${latitude}`);
};

commands.pullFile = async function (remotePath) {
  let localFile = temp.path({prefix: 'appium', suffix: '.tmp'});
  await this.adb.pull(remotePath, localFile);
  let data = await fs.readFile(localFile);
  let b64data = new Buffer(data).toString('base64');
  if (await fs.exists(localFile)) {
    await fs.unlink(localFile);
  }
  return b64data;
};

commands.pushFile = async function (remotePath, base64Data) {
  let localFile = temp.path({prefix: 'appium', suffix: '.tmp'});
  await mkdirp(path.dirname(localFile));
  let content = new Buffer(base64Data, 'base64');
  let fd = await fs.open(localFile, 'w');
  await fs.write(fd, content, 0, content.length, 0);
  await fs.close(fd);

  // adb push creates folders and overwrites existing files.
  await this.adb.push(localFile, remotePath);
  if (await fs.exists(localFile)) {
    await fs.unlink(localFile);
  }
};

commands.pullFolder = async function (remotePath) {
  let localFolder = temp.path({prefix: 'appium'});
  await this.adb.pull(remotePath, localFolder);
  // TODO: find a better alternative to the AdmZip module
  let zip = new AdmZip();
  zip.addLocalFolder(localFolder);
  return new Promise((resolve, reject) => {
    zip.toBuffer((buffer) => {
      log.debug('Converting in-memory zip file to base64 encoded string');
      resolve(buffer.toString('base64'));
    }, (err) => {
      reject(err);
    });
  });
};

commands.getScreenshot = async function () {
  let localFile = temp.path({prefix: 'appium', suffix: '.png'});
  const png = '/data/local/tmp/screenshot.png';
  let cmd =  ['/system/bin/rm', `${png};`, '/system/bin/screencap', '-p', png];
  await this.adb.shell(cmd);
  if (await fs.exists(localFile)) {
    await fs.unlink(localFile);
  }
  await this.adb.pull(png, localFile);
  let data = await fs.readFile(localFile);
  let b64data = new Buffer(data).toString('base64');
  await fs.unlink(localFile);
  return b64data;
};

Object.assign(extensions, commands, helpers);
export { commands, helpers };
export default extensions;
<commit_msg>Refactored drag and swipe<commit_after>import androidHelpers from '../android-helpers';
import temp from 'temp';
import { fs, mkdirp, util } from 'appium-support';
import AdmZip from 'adm-zip';
import path from 'path';
import log from '../logger';

const swipeStepsPerSec = 28;
const dragStepsPerSec = 40;

let commands = {}, helpers = {}, extensions = {};

commands.keyevent = async function (keycode, metastate = null) {
  // TODO deprecate keyevent; currently wd only implements keyevent
  log.warn("keyevent will be deprecated use pressKeyCode");
  return await this.pressKeyCode(keycode, metastate);
};

commands.pressKeyCode = async function (keycode, metastate = null) {
  return await this.bootstrap.sendAction("pressKeyCode", {keycode, metastate});
};

commands.longPressKeyCode = async function (keycode, metastate = null) {
  return await this.bootstrap.sendAction("longPressKeyCode", {keycode, metastate});
};

commands.getOrientation = async function () {
  let orientation = await this.bootstrap.sendAction("orientation", {});
  return orientation.toUpperCase();
};

commands.setOrientation = async function (orientation) {
  orientation = orientation.toUpperCase();
  return await this.bootstrap.sendAction("orientation", {orientation});
};

commands.fakeFlick = async function (xSpeed, ySpeed) {
  return await this.bootstrap.sendAction('flick', {xSpeed, ySpeed});
};

commands.fakeFlickElement = async function (elementId, xoffset, yoffset, speed) {
  let params = {xoffset, yoffset, speed, elementId};
  return await this.bootstrap.sendAction('element:flick', params);
};

commands.swipe = async function (startX, startY, endX, endY, duration, touchCount, elId) {
  if (startX === 'null') {
    startX = 0.5;
  }
  if (startY === 'null') {
    startY = 0.5;
  }
  let swipeOpts = {startX, startY, endX, endY,
                   steps: Math.round(duration * swipeStepsPerSec)};
  // going the long way and checking for undefined and null since
  // we can't be assured `elId` is a string and not an int
  if (util.hasValue(elId)) {
    swipeOpts.elementId = elId;
  }
  return await this.doSwipe(swipeOpts);
};

commands.doSwipe = async function(swipeOpts) {
  if (util.hasValue(swipeOpts.elementId)) {
    return await this.bootstrap.sendAction("element:swipe", swipeOpts);
  } else {
    return await this.bootstrap.sendAction("swipe", swipeOpts);
  }
};

commands.pinchClose = async function (startX, startY, endX, endY, duration, percent, steps, elId) {
  let pinchOpts = {
    direction: 'in',
    elementId: elId,
    percent,
    steps
  };
  return await this.bootstrap.sendAction("element:pinch", pinchOpts);
};

commands.pinchOpen = async function (startX, startY, endX, endY, duration, percent, steps, elId) {
  let pinchOpts = {direction: 'out', elementId: elId, percent, steps};
  return await this.bootstrap.sendAction("element:pinch", pinchOpts);
};

commands.flick = async function (element, xSpeed, ySpeed, xOffset, yOffset, speed) {
  if (element) {
    await this.fakeFlickElement(element, xOffset, yOffset, speed);
  } else {
    await this.fakeFlick(xSpeed, ySpeed);
  }
};

commands.drag = async function (startX, startY, endX, endY, duration, touchCount, elementId, destElId) {
  let dragOpts = {
    elementId, destElId, startX, startY, endX, endY,
    steps: Math.round(duration * dragStepsPerSec)
  };
  return await this.doDrag(dragOpts);

};

commands.doDrag = async function (dragOpts) {
  if (util.hasValue(dragOpts.elementId)) {
    return await this.bootstrap.sendAction("element:drag", dragOpts);
  } else {
    return await this.bootstrap.sendAction("drag", dragOpts);
  }
};

commands.lock = async function () {
  return await this.adb.lock();
};

commands.isLocked = async function () {
  return await this.adb.isScreenLocked();
};

commands.unlock = async function () {
  return await androidHelpers.unlock(this.adb);
};

commands.openNotifications = async function () {
  return await this.bootstrap.sendAction("openNotification");
};

commands.setLocation = async function (latitude, longitude) {
  return await this.adb.sendTelnetCommand(`geo fix ${longitude} ${latitude}`);
};

commands.pullFile = async function (remotePath) {
  let localFile = temp.path({prefix: 'appium', suffix: '.tmp'});
  await this.adb.pull(remotePath, localFile);
  let data = await fs.readFile(localFile);
  let b64data = new Buffer(data).toString('base64');
  if (await fs.exists(localFile)) {
    await fs.unlink(localFile);
  }
  return b64data;
};

commands.pushFile = async function (remotePath, base64Data) {
  let localFile = temp.path({prefix: 'appium', suffix: '.tmp'});
  await mkdirp(path.dirname(localFile));
  let content = new Buffer(base64Data, 'base64');
  let fd = await fs.open(localFile, 'w');
  await fs.write(fd, content, 0, content.length, 0);
  await fs.close(fd);

  // adb push creates folders and overwrites existing files.
  await this.adb.push(localFile, remotePath);
  if (await fs.exists(localFile)) {
    await fs.unlink(localFile);
  }
};

commands.pullFolder = async function (remotePath) {
  let localFolder = temp.path({prefix: 'appium'});
  await this.adb.pull(remotePath, localFolder);
  // TODO: find a better alternative to the AdmZip module
  let zip = new AdmZip();
  zip.addLocalFolder(localFolder);
  return new Promise((resolve, reject) => {
    zip.toBuffer((buffer) => {
      log.debug('Converting in-memory zip file to base64 encoded string');
      resolve(buffer.toString('base64'));
    }, (err) => {
      reject(err);
    });
  });
};

commands.getScreenshot = async function () {
  let localFile = temp.path({prefix: 'appium', suffix: '.png'});
  const png = '/data/local/tmp/screenshot.png';
  let cmd =  ['/system/bin/rm', `${png};`, '/system/bin/screencap', '-p', png];
  await this.adb.shell(cmd);
  if (await fs.exists(localFile)) {
    await fs.unlink(localFile);
  }
  await this.adb.pull(png, localFile);
  let data = await fs.readFile(localFile);
  let b64data = new Buffer(data).toString('base64');
  await fs.unlink(localFile);
  return b64data;
};

Object.assign(extensions, commands, helpers);
export { commands, helpers };
export default extensions;
<|endoftext|>


<commit_before>var logger = require('npmlog');
var semver = require('semver');
var mkdirp = require('mkdirp');
var difftool = require('diff');

var path = require('path');

var file = require('../utils/file');
var md5sum = require('../utils/md5sum');
var request = require('../utils/request');

var dataDir = path.resolve(__dirname, '../../data');

var cwd = process.cwd();
var baseDir = (process.env.HOME || '/tmp/');
var cacheDir = path.resolve(baseDir, '.mauer/cache');
var modulesDir = path.resolve(cwd, '.mauer');

var config = {
  'dependencyDir': 'public/vendor',
  'patchesDir': 'patches'
};

mkdirp.sync(cacheDir);
mkdirp.sync(modulesDir);

function installPackage (package) {

  var tokens = package.split('@');

  // allow only valid package names
  if (tokens.length > 2) {
    logger.error('', 'Invalid package "%s"', package);
    return;
  }

  var name = tokens[0];
  var packageFile = path.join(dataDir, name + '.json');
  if (!file.exists(packageFile)) {
    logger.error('', 'Unrecognised package "%s"', package);
    return;
  }

  var version = latestVersion(name, tokens[1]);
  if (version) {
    logger.verbose('installing', name, version);
    getPackage(name, version, function (err, cache) {
      if (err) {
        throw err;
      }
      setupPackage(name, version, cache);
      logger.info('done', name);
    });
  }
}

function latestVersion (name, version) {

  if (version && version !== 'latest') {
    var parsed = semver.parse(version);
    if (parsed) {
      version = parsed.splice(1,3).join('.');
    } else {
      logger.error('', 'Unsupported "%s@%s"', name, version);
      return;
    }
  }

  var packageFile = path.join(dataDir, name + '.json');
  var packageInfo = require(packageFile);
  var versions = Object.keys(packageInfo.versions);

  // If no version is passed, fallback to the latest version
  if (!version || version === 'latest') {
    version = versions.sort(semver.rcompare)[0];
  } else if (versions.indexOf(version) < 0) {
    logger.error('', 'Unsupported "%s@%s"', name, version);
    return;
  }

  return version;
}

function getPackage (name, version, callback) {
  var packageFile = path.join(dataDir, name + '.json');
  var packageInfo = require(packageFile);
  var versionData = packageInfo.versions[version];

  var expectedSum = versionData.md5sum;
  var urls = versionData.urls;

  // create the cache directory, if it doesn't exist
  var cachedFile = path.join(cacheDir, name, version);
  mkdirp.sync(path.join(cacheDir, name));

  // if the cached file exists
  // and if the md5 sum of the cached file matches
  if (file.exists(cachedFile) && md5sum(cachedFile, expectedSum)) {
    logger.verbose('using', 'cached file for %s@%s', name, version);
    callback(null, cachedFile);
  }
  // otherwise download the file again
  else {
    logger.verbose('downloading', '%s@%s', name, version);
    urls = urls.split(/[\r\n]/g);

    // TODO: try a random url every time
    var url = urls[0];
    downloadPackage(url, cachedFile, expectedSum, callback);
  }
}

function downloadPackage (url, cachedFile, expectedSum, callback) {
  request(url, function (err, data) {
    logger.verbose('downloaded', url);
    file.write(cachedFile, data);
    var md5 = md5sum(cachedFile);
    if (md5 === expectedSum) {
      logger.verbose('checksum verfied', md5);
      callback(null, cachedFile);
    } else {
      logger.error('checksum failed', 'expected %s, got %s',
        expectedSum, md5);
      file.delete(cachedFile);
      callback(new Error('checksum failed'));
    }
  });
}

function setupPackage (name, version, cache) {
  var destDir = path.resolve(modulesDir, name);
  mkdirp.sync(destDir);

  // copy over the cached file
  var source = path.join(destDir, 'source');
  logger.verbose('setting up', name);
  file.copy(cache, source);

  // patch, if needed
  patchPackage(name, version);

  // finalize
  deployPackage(name, version);
}

function patchPackage (name, version) {
  var destDir = path.resolve(modulesDir, name);
  var original = file.read(path.join(destDir, 'source'));
  var patchName = [name, version].join('@');
  var patchFile = path.resolve(cwd, config.patchesDir, patchName);

  var content = original;
  if (file.exists(patchFile)) {
    logger.verbose('patching', patchName);
    var patch = file.read(patchFile);
    content = difftool.applyPatch(original, patch);
    if (content === false) {
      logger.error('\nfailed to patch', patchName);
      process.exit(-1);
    }
  }

  var dest = path.join(destDir, 'patched');
  file.write(dest, content);
}

function deployPackage (name, version) {
  var destDir = path.resolve(modulesDir, name);
  logger.verbose('linking', name, version);

  // delete current copy & move over the patched version
  var patched = path.join(destDir, 'patched');
  // TODO: use mauer.json for the path mappings to symlink the files
  var lib = path.resolve(cwd, config.dependencyDir, name + '.js');
  if (file.exists(lib)) {
    file.delete(lib);
  }
  file.link(patched, lib);
}

function installAll (mauerFile) {
  // TODO: handle malformed config
  var mauerConfig = require(mauerFile);
  var dependencies = mauerConfig.dependencies;

  config.patchesDir = mauerConfig.patchesDir || 'patches';
  config.dependencyDir = mauerConfig.dependencyDir;

  // ensure that the destination directory exists
  mkdirp.sync(config.dependencyDir);

  var name, version;
  for (name in dependencies) {
    version = dependencies[name];
    installPackage([name, version].join('@'));
  }
}

function install () {
  var packages = [].slice.call(arguments);

  // if specific package installation was asked for
  if (packages.length > 0) {
    packages.forEach(installPackage);
  }
  // otherwise install everything on mauer.json
  else {
    var mauerFile = path.join(cwd, 'mauer.json');
    if (!file.exists(mauerFile)) {
      logger.error('config', 'mauer.json not found');
      return;
    } else {
      installAll (mauerFile);
    }
  }
}

module.exports = install;
<commit_msg>fix installer<commit_after>var logger = require('npmlog');
var semver = require('semver');
var mkdirp = require('mkdirp');
var difftool = require('diff');

var path = require('path');

var file = require('../utils/file');
var md5sum = require('../utils/md5sum');
var request = require('../utils/request');

var dataDir = path.resolve(__dirname, '../../data');

var cwd = process.cwd();
var baseDir = (process.env.HOME || '/tmp/');
var cacheDir = path.resolve(baseDir, '.mauer/cache');
var modulesDir = path.resolve(cwd, '.mauer');

var config = {
  'dependencyDir': 'public/vendor',
  'patchesDir': 'patches'
};

mkdirp.sync(cacheDir);
mkdirp.sync(modulesDir);

function installPackage (package) {

  var tokens = package.split('@');

  // allow only valid package names
  if (tokens.length > 2) {
    logger.error('', 'Invalid package "%s"', package);
    return;
  }

  var name = tokens[0];
  var packageFile = path.join(dataDir, name + '.json');
  if (!file.exists(packageFile)) {
    logger.error('', 'Unrecognised package "%s"', package);
    return;
  }

  var version = latestVersion(name, tokens[1]);
  if (version) {
    logger.verbose('installing', name, version);
    getPackage(name, version, function (err, cache) {
      if (err) {
        throw err;
      }
      setupPackage(name, version, cache);
      console.log('%s@%s', name, version);
    });
  }
}

function latestVersion (name, version) {

  if (version && version !== 'latest') {
    var parsed = semver.parse(version);
    if (parsed) {
      version = parsed.splice(1,3).join('.');
    } else {
      logger.error('', 'Unsupported "%s@%s"', name, version);
      return;
    }
  }

  var packageFile = path.join(dataDir, name + '.json');
  var packageInfo = require(packageFile);
  var versions = Object.keys(packageInfo.versions);

  // If no version is passed, fallback to the latest version
  if (!version || version === 'latest') {
    version = versions.sort(semver.rcompare)[0];
  } else if (versions.indexOf(version) < 0) {
    logger.error('', 'Unsupported "%s@%s"', name, version);
    return;
  }

  return version;
}

function getPackage (name, version, callback) {
  var packageFile = path.join(dataDir, name + '.json');
  var packageInfo = require(packageFile);
  var versionData = packageInfo.versions[version];

  var expectedSum = versionData.md5sum;
  var urls = versionData.urls;

  // create the cache directory, if it doesn't exist
  var cachedFile = path.join(cacheDir, name, version);
  mkdirp.sync(path.join(cacheDir, name));

  // if the cached file exists
  // and if the md5 sum of the cached file matches
  if (file.exists(cachedFile) && md5sum(cachedFile, expectedSum)) {
    logger.verbose('using', 'cached file for %s@%s', name, version);
    callback(null, cachedFile);
  }
  // otherwise download the file again
  else {
    logger.verbose('downloading', '%s@%s', name, version);
    var url = urls[Math.floor(Math.random() * urls.length)];
    downloadPackage(url, cachedFile, expectedSum, callback);
  }
}

function downloadPackage (url, cachedFile, expectedSum, callback) {
  request(url, function (err, data) {
    logger.verbose('downloaded', url);
    file.write(cachedFile, data);
    var md5 = md5sum(cachedFile);
    if (md5 === expectedSum) {
      logger.verbose('checksum verfied', md5);
      callback(null, cachedFile);
    } else {
      logger.error('checksum failed', 'expected %s, got %s',
        expectedSum, md5);
      file.delete(cachedFile);
      callback(new Error('checksum failed'));
    }
  });
}

function setupPackage (name, version, cache) {
  var destDir = path.resolve(modulesDir, name);
  mkdirp.sync(destDir);

  // copy over the cached file
  var source = path.join(destDir, 'source');
  logger.verbose('setting up', name);
  file.copy(cache, source);

  // patch, if needed
  patchPackage(name, version);

  // finalize
  deployPackage(name, version);
}

function patchPackage (name, version) {
  var destDir = path.resolve(modulesDir, name);
  var original = file.read(path.join(destDir, 'source'));
  var patchName = [name, version].join('@');
  var patchFile = path.resolve(cwd, config.patchesDir, patchName);

  var content = original;
  if (file.exists(patchFile)) {
    logger.verbose('patching', patchName);
    var patch = file.read(patchFile);
    content = difftool.applyPatch(original, patch);
    if (content === false) {
      logger.error('\nfailed to patch', patchName);
      process.exit(-1);
    }
  }

  var dest = path.join(destDir, 'patched');
  file.write(dest, content);
}

function deployPackage (name, version) {
  var destDir = path.resolve(modulesDir, name);
  logger.verbose('linking', name, version);

  // delete current copy & move over the patched version
  var patched = path.join(destDir, 'patched');
  // TODO: use mauer.json for the path mappings to symlink the files
  var lib = path.resolve(cwd, config.dependencyDir, name + '.js');
  if (file.exists(lib)) {
    file.delete(lib);
  }
  file.link(patched, lib);
}

function installAll (mauerFile) {
  // TODO: handle malformed config
  var mauerConfig = require(mauerFile);
  var dependencies = mauerConfig.dependencies;

  config.patchesDir = mauerConfig.patchesDir || 'patches';
  config.dependencyDir = mauerConfig.dependencyDir;

  // ensure that the destination directory exists
  mkdirp.sync(config.dependencyDir);

  var name, version;
  for (name in dependencies) {
    version = dependencies[name];
    installPackage([name, version].join('@'));
  }
}

function install () {
  var packages = [].slice.call(arguments);

  // if specific package installation was asked for
  if (packages.length > 0) {
    packages.forEach(installPackage);
  }
  // otherwise install everything on mauer.json
  else {
    var mauerFile = path.join(cwd, 'mauer.json');
    if (!file.exists(mauerFile)) {
      logger.error('config', 'mauer.json not found');
      return;
    } else {
      installAll (mauerFile);
    }
  }
}

module.exports = install;
<|endoftext|>


<commit_before>// Copyright (c) 2016, Matt Godbolt & Rubén Rincón
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
//     * Redistributions of source code must retain the above copyright notice,
//       this list of conditions and the following disclaimer.
//     * Redistributions in binary form must reproduce the above copyright
//       notice, this list of conditions and the following disclaimer in the
//       documentation and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.

const BaseCompiler = require('../base-compiler'),
    _ = require('underscore'),
    utils = require('../utils');

class GolangCompiler extends BaseCompiler {
    convertNewGoL(code) {
        const re = /^\s+(0[xX]?[0-9A-Za-z]+)?\s?[0-9]+\s*\(([^:]+):([0-9]+)\)\s*([A-Z]+)(.*)/;
        const reUnknown = /^\s+(0[xX]?[0-9A-Za-z]+)?\s?[0-9]+\s*\(<unknown line number>\)\s*([A-Z]+)(.*)/;
        let prevLine = null;
        let file = null;
        let fileCount = 0;
        return _.compact(code.map(obj => {
            const line = obj.text;
            let match = line.match(re);
            if (match) {
                let res = "";
                if (file !== match[2]) {
                    fileCount++;
                    res += "\t.file " + fileCount + ' "' + match[2] + '"\n';
                    file = match[2];
                }
                if (prevLine !== match[3]) {
                    res += "\t.loc " + fileCount + " " + match[3] + " 0\n";
                    prevLine = match[3];
                }
                return res + "\t" + match[4].toLowerCase() + match[5];
            } else {
                match = line.match(reUnknown);
                if (match) {
                    return "\t" + match[2].toLowerCase() + match[3];
                } else {
                    return null;
                }
            }

        })).join("\n");
    }

    extractLogging(stdout) {
        const reLogging = /^\/(.*):([0-9]*):([0-9]*):\s(.*)/i;
        return stdout.filter(obj => obj.text.match(reLogging)).
            map(obj => obj.text).
            join('\n');
    }

    postProcess(result) {
        const logging = this.extractLogging(result.stdout);
        result.asm = this.convertNewGoL(result.stdout);
        result.stdout = utils.parseOutput(logging, result.inputFilename);
        return Promise.resolve(result);
    }

    optionsForFilter(filters, outputFilename) {
        // If we're dealing with an older version...
        if (this.compiler.id === '6g141') {
            return ['tool', '6g', '-g', '-o', outputFilename, '-S'];
        }
        return ['tool', 'compile', '-o', outputFilename, '-S'];
    }

    getDefaultExecOptions() {
        const execOptions = super.getDefaultExecOptions();
        const goroot = this.compilerProps("compiler." + this.compiler.id + ".goroot");
        if (goroot) {
            execOptions.env.GOROOT = goroot;
        }
        return execOptions;
    }
}

module.exports = GolangCompiler;
<commit_msg>source<commit_after>// Copyright (c) 2016, Matt Godbolt & Rubén Rincón
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
//     * Redistributions of source code must retain the above copyright notice,
//       this list of conditions and the following disclaimer.
//     * Redistributions in binary form must reproduce the above copyright
//       notice, this list of conditions and the following disclaimer in the
//       documentation and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.

const BaseCompiler = require('../base-compiler'),
    _ = require('underscore'),
    utils = require('../utils');

class GolangCompiler extends BaseCompiler {
    convertNewGoL(code) {
        const re = /^\s+(0[xX]?[0-9A-Za-z]+)?\s?[0-9]+\s*\(([^:]+):([0-9]+)\)\s*([A-Z]+)(.*)/;
        const reUnknown = /^\s+(0[xX]?[0-9A-Za-z]+)?\s?[0-9]+\s*\(<unknown line number>\)\s*([A-Z]+)(.*)/;
        let prevLine = null;
        let file = null;
        let fileCount = 0;
        return _.compact(code.map(obj => {
            const line = obj.text;
            let match = line.match(re);
            if (match) {
                let res = "";
                if (file !== match[2]) {
                    fileCount++;
                    res += "\t.file " + fileCount + ' "' + match[2] + '"\n';
                    file = match[2];
                }
                if (prevLine !== match[3]) {
                    res += "\t.loc " + fileCount + " " + match[3] + " 0\n";
                    prevLine = match[3];
                }
                return res + "\t" + match[4].toLowerCase() + match[5];
            } else {
                match = line.match(reUnknown);
                if (match) {
                    return "\t" + match[2].toLowerCase() + match[3];
                } else {
                    return null;
                }
            }

        })).join("\n");
    }

    extractLogging(stdout) {
        const reLogging = /^<source>:([0-9]*):([0-9]*):\s(.*)/i;
        return stdout.filter(obj => obj.text.match(reLogging)).
            map(obj => obj.text).
            join('\n');
    }

    postProcess(result) {
        const logging = this.extractLogging(result.stdout);
        result.asm = this.convertNewGoL(result.stdout);
        result.stdout = utils.parseOutput(logging, result.inputFilename);
        return Promise.resolve(result);
    }

    optionsForFilter(filters, outputFilename) {
        // If we're dealing with an older version...
        if (this.compiler.id === '6g141') {
            return ['tool', '6g', '-g', '-o', outputFilename, '-S'];
        }
        return ['tool', 'compile', '-o', outputFilename, '-S'];
    }

    getDefaultExecOptions() {
        const execOptions = super.getDefaultExecOptions();
        const goroot = this.compilerProps("compiler." + this.compiler.id + ".goroot");
        if (goroot) {
            execOptions.env.GOROOT = goroot;
        }
        return execOptions;
    }
}

module.exports = GolangCompiler;
<|endoftext|>