<commit_before>'use strict';
var app = angular.module('sirAccordion', [
  'sir-accordion'
  ]);

app.run([function() {
  if ('addEventListener' in document) {
    document.addEventListener('DOMContentLoaded', function() {
      FastClick.attach(document.body);
    }, false);
  }
}]);

app.controller('Principal',['$scope','$compile','$timeout',function($scope,$compile,$timeout){
  $scope.activeArray = 1;
  $scope.coord = '';

  var accordionConfig = {
    id: '',
    debug: false,
    animDur: 0,
    expandFirst: false,
    autoCollapse: true,
    headerClass: '',
    beforeHeader: '',
    afterHeader: '

',
    topContentClass: '',
    beforeTopContent: '',
    afterTopContent: '

I repeat through all accordion

',
    bottomContentClass: '',
    beforeBottomContent: '',
    afterBottomContent: '',
    watchInternalChanges: true
  };

  var accordionCollection = [
    {"title":"Level 1","topContent":"This is the top content attr","bottomContent":null,"subCollection":[
        { "title": "This is a Level 2 Header!", "topContent":"This is some nice text right here and a button with 'ng-click' <button class=\"btn btn-primary\" ng-click=\"clickMe()\">Click me!</button>","bottomContent":null},
      {"title":"Level 2","topContent":"
And you can ad Html code directly to the content too
","bottomContent":null},
      {"title":"This Level 2 Header has another subCollection","topContent":null,"bottomContent":"
You can choose to put text after the subcollection if you prefer (or both before and after)
","subCollection":[
        {"title":"And You got to the Level 3","topContent":"Awesome text or HTML Content Here"},
        {"title":"Level 3","topContent":"You can also add AngularJS expressions","subCollection":[
          {"title":"And another Level, Level 4","topContent":"
Awesome text or HTML Content Here
"},
          {"title":"Level 4","topContent":"
Adding HTML

"}
        ]},
        {"title":"Level 3","topContent":"
Awesome text or HTML Content Here
"}
      ]},
      {"title":"Level 2","topContent":"
You can keep adding Levels
","bottomContent":null, "subCollection":[
        {"title":"Level 3","topContent":"
You can keep adding Levels
","bottomContent":null, "subCollection":[
          {"title":"Level 4","topContent":"
You can keep adding Levels
","bottomContent":null}
        ]}
      ]}
    ]},
    {"title":"Level 1","topContent":null,"bottomContent":null,"subCollection":[
      {"title":"Level 2","topContent":"
You Can set a Content, a subCollection of items, or combine them; making an element expand to a collection of items with text on the top, bottom or both!.
\n
Check the next items for examples
","bottomContent":null},
      {"title":"Level 2","topContent":"This is a top content","bottomContent":"This text should be the content after the Items","subCollection":[
        {"title":"Level 3 item","topContent":"Awesome text"},
        {"title":"Level 3 item","topContent":"Awesome text"}
      ]},
      {"title":"Level 2","topContent":"
sir-accordion is also perfect for responsive Design!
\nThe content uses VelocityJS, and you can resize the window and it will adapt pretty well\n
You can try it out by using the content provided or adding your own content and resizing your desktop window, it's awesome
","bottomContent":null}
    ]},
    {"title":"Level 1","topContent":"This one only goes to Level 1 and the content in it and this is the topContent","bottomContent":"this is the bottom content"},
    {"title":"Level 1","topContent":"This is the topContent field on this element and it also has an array of items (subCollection array field in the JSON object)","bottomContent":null,"subCollection":[
      {"title":"Level 2","topContent":"Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmodtempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam,quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodoconsequat. Duis aute irure dolor in reprehenderit in voluptate velit essecillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat nonproident, sunt in culpa qui officia deserunt mollit anim id est laborum.","bottomContent":null},
      {"title":"Level 2","topContent":"Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmodtempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam,quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodoconsequat. Duis aute irure dolor in reprehenderit in voluptate velit essecillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat nonproident, sunt in culpa qui officia deserunt mollit anim id est laborum.","bottomContent":null},
      {"title":"Level 2","topContent":"Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmodtempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam,quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodoconsequat. Duis aute irure dolor in reprehenderit in voluptate velit essecillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat nonproident, sunt in culpa qui officia deserunt mollit anim id est laborum.","bottomContent":null}
    ]},
    {"title":"Level 1","topContent":null,"bottomContent":null,"subCollection":[
      {"title":"Level 2","topContent":"Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmodtempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam,quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodoconsequat. Duis aute irure dolor in reprehenderit in voluptate velit essecillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat nonproident, sunt in culpa qui officia deserunt mollit anim id est laborum.","bottomContent":null},
      {"title":"Level 2","topContent":"Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmodtempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam,quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodoconsequat. Duis aute irure dolor in reprehenderit in voluptate velit essecillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat nonproident, sunt in culpa qui officia deserunt mollit anim id est laborum.","bottomContent":null},
      {"title":"Level 2","topContent":"Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmodtempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam,quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodoconsequat. Duis aute irure dolor in reprehenderit in voluptate velit essecillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat nonproident, sunt in culpa qui officia deserunt mollit anim id est laborum.","bottomContent":null}
    ]},
    {"title":"Level 1","topContent":null,"bottomContent":null,"subCollection":[
      {"title":"Level 2","topContent":"Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmodtempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam,quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodoconsequat. Duis aute irure dolor in reprehenderit in voluptate velit essecillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat nonproident, sunt in culpa qui officia deserunt mollit anim id est laborum.","bottomContent":null},
      {"title":"Level 2","topContent":"Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmodtempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam,quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodoconsequat. Duis aute irure dolor in reprehenderit in voluptate velit essecillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat nonproident, sunt in culpa qui officia deserunt mollit anim id est laborum.","bottomContent":null},
      {"title":"Level 2","topContent":"Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmodtempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam,quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodoconsequat. Duis aute irure dolor in reprehenderit in voluptate velit essecillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat nonproident, sunt in culpa qui officia deserunt mollit anim id est laborum.","bottomContent":null}
    ]},
    {"title":"Level 1","topContent":null,"bottomContent":null,"subCollection":[
      {"title":"Level 2","topContent":"Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmodtempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam,quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodoconsequat. Duis aute irure dolor in reprehenderit in voluptate velit essecillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat nonproident, sunt in culpa qui officia deserunt mollit anim id est laborum.","bottomContent":null},
      {"title":"Level 2","topContent":"Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmodtempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam,quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodoconsequat. Duis aute irure dolor in reprehenderit in voluptate velit essecillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat nonproident, sunt in culpa qui officia deserunt mollit anim id est laborum.","bottomContent":null},
      {"title":"Level 2","topContent":"Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmodtempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam,quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodoconsequat. Duis aute irure dolor in reprehenderit in voluptate velit essecillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat nonproident, sunt in culpa qui officia deserunt mollit anim id est laborum.","bottomContent":null}
    ]}
  ];

  $scope.sirAccordion = {
    collection: accordionCollection,
    config: accordionConfig
  };

  /* $timeout(function() {
    $scope.sirAccordion.collection[0].subCollection[0].title = 'hola';
  }, 2000);

  $timeout(function () {
    $scope.sirAccordion.collection[0] = {
      title: 'hola', topContent: 'hola'
    };
  }, 4000);

  $timeout(function () {
    $scope.sirAccordion.collection = [{
      title: 'hola', topContent: 'hola'
    }];
  }, 6000);

  $timeout(function () {
    $scope.sirAccordion.collection = [{
      title: 'chao', topContent: 'chao'
    }];
  }, 8000); */

  $scope.clickMe = function(){
    console.log('Hi I\'m Jeff');
    alert('Hi!');
  };

  $scope.toggleAutoCollapse = function(){
    $scope.$broadcast('sacCollapseAll');
    $scope.sirAccordion.config.autoCollapse = !$scope.sirAccordion.config.autoCollapse;
  };

  $scope.toggleAnimation = function() {
    if ($scope.sirAccordion.config.animDur){
      $scope.sirAccordion.config.animDur = 0;
      return;
    }
    $scope.sirAccordion.config.animDur = 300;
  };

  $scope.expandByCoord = function(){
    $scope.$broadcast('sacExpandContentById', $scope.coord);
  };

  $scope.collapseByCoord = function(){
    $scope.$broadcast('sacCollapseContentById', $scope.coord);
  };

  $scope.expandAll = function(){
    $scope.$broadcast('sacExpandAll');
  };

  $scope.collapseAll = function(){
    $scope.$broadcast('sacCollapseAll');
  };

  $scope.$on('sacExpandStart', function(data){
    console.log('sacExpandStart');
  });

  $scope.$on('sacExpandEnd', function (data) {
    console.log('sacExpandEnd');
  });

}]);<commit_msg>set animDur to 300 again in example app<commit_after>'use strict';
var app = angular.module('sirAccordion', [
  'sir-accordion'
  ]);

app.run([function() {
  if ('addEventListener' in document) {
    document.addEventListener('DOMContentLoaded', function() {
      FastClick.attach(document.body);
    }, false);
  }
}]);

app.controller('Principal',['$scope','$compile','$timeout',function($scope,$compile,$timeout){
  $scope.activeArray = 1;
  $scope.coord = '';

  var accordionConfig = {
    id: '',
    debug: false,
    animDur: 300,
    expandFirst: false,
    autoCollapse: true,
    headerClass: '',
    beforeHeader: '',
    afterHeader: '

',
    topContentClass: '',
    beforeTopContent: '',
    afterTopContent: '

I repeat through all accordion

',
    bottomContentClass: '',
    beforeBottomContent: '',
    afterBottomContent: '',
    watchInternalChanges: true
  };

  var accordionCollection = [
    {"title":"Level 1","topContent":"This is the top content attr","bottomContent":null,"subCollection":[
        { "title": "This is a Level 2 Header!", "topContent":"This is some nice text right here and a button with 'ng-click' <button class=\"btn btn-primary\" ng-click=\"clickMe()\">Click me!</button>","bottomContent":null},
      {"title":"Level 2","topContent":"
And you can ad Html code directly to the content too
","bottomContent":null},
      {"title":"This Level 2 Header has another subCollection","topContent":null,"bottomContent":"
You can choose to put text after the subcollection if you prefer (or both before and after)
","subCollection":[
        {"title":"And You got to the Level 3","topContent":"Awesome text or HTML Content Here"},
        {"title":"Level 3","topContent":"You can also add AngularJS expressions","subCollection":[
          {"title":"And another Level, Level 4","topContent":"
Awesome text or HTML Content Here
"},
          {"title":"Level 4","topContent":"
Adding HTML

"}
        ]},
        {"title":"Level 3","topContent":"
Awesome text or HTML Content Here
"}
      ]},
      {"title":"Level 2","topContent":"
You can keep adding Levels
","bottomContent":null, "subCollection":[
        {"title":"Level 3","topContent":"
You can keep adding Levels
","bottomContent":null, "subCollection":[
          {"title":"Level 4","topContent":"
You can keep adding Levels
","bottomContent":null}
        ]}
      ]}
    ]},
    {"title":"Level 1","topContent":null,"bottomContent":null,"subCollection":[
      {"title":"Level 2","topContent":"
You Can set a Content, a subCollection of items, or combine them; making an element expand to a collection of items with text on the top, bottom or both!.
\n
Check the next items for examples
","bottomContent":null},
      {"title":"Level 2","topContent":"This is a top content","bottomContent":"This text should be the content after the Items","subCollection":[
        {"title":"Level 3 item","topContent":"Awesome text"},
        {"title":"Level 3 item","topContent":"Awesome text"}
      ]},
      {"title":"Level 2","topContent":"
sir-accordion is also perfect for responsive Design!
\nThe content uses VelocityJS, and you can resize the window and it will adapt pretty well\n
You can try it out by using the content provided or adding your own content and resizing your desktop window, it's awesome
","bottomContent":null}
    ]},
    {"title":"Level 1","topContent":"This one only goes to Level 1 and the content in it and this is the topContent","bottomContent":"this is the bottom content"},
    {"title":"Level 1","topContent":"This is the topContent field on this element and it also has an array of items (subCollection array field in the JSON object)","bottomContent":null,"subCollection":[
      {"title":"Level 2","topContent":"Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmodtempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam,quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodoconsequat. Duis aute irure dolor in reprehenderit in voluptate velit essecillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat nonproident, sunt in culpa qui officia deserunt mollit anim id est laborum.","bottomContent":null},
      {"title":"Level 2","topContent":"Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmodtempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam,quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodoconsequat. Duis aute irure dolor in reprehenderit in voluptate velit essecillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat nonproident, sunt in culpa qui officia deserunt mollit anim id est laborum.","bottomContent":null},
      {"title":"Level 2","topContent":"Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmodtempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam,quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodoconsequat. Duis aute irure dolor in reprehenderit in voluptate velit essecillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat nonproident, sunt in culpa qui officia deserunt mollit anim id est laborum.","bottomContent":null}
    ]},
    {"title":"Level 1","topContent":null,"bottomContent":null,"subCollection":[
      {"title":"Level 2","topContent":"Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmodtempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam,quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodoconsequat. Duis aute irure dolor in reprehenderit in voluptate velit essecillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat nonproident, sunt in culpa qui officia deserunt mollit anim id est laborum.","bottomContent":null},
      {"title":"Level 2","topContent":"Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmodtempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam,quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodoconsequat. Duis aute irure dolor in reprehenderit in voluptate velit essecillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat nonproident, sunt in culpa qui officia deserunt mollit anim id est laborum.","bottomContent":null},
      {"title":"Level 2","topContent":"Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmodtempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam,quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodoconsequat. Duis aute irure dolor in reprehenderit in voluptate velit essecillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat nonproident, sunt in culpa qui officia deserunt mollit anim id est laborum.","bottomContent":null}
    ]},
    {"title":"Level 1","topContent":null,"bottomContent":null,"subCollection":[
      {"title":"Level 2","topContent":"Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmodtempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam,quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodoconsequat. Duis aute irure dolor in reprehenderit in voluptate velit essecillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat nonproident, sunt in culpa qui officia deserunt mollit anim id est laborum.","bottomContent":null},
      {"title":"Level 2","topContent":"Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmodtempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam,quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodoconsequat. Duis aute irure dolor in reprehenderit in voluptate velit essecillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat nonproident, sunt in culpa qui officia deserunt mollit anim id est laborum.","bottomContent":null},
      {"title":"Level 2","topContent":"Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmodtempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam,quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodoconsequat. Duis aute irure dolor in reprehenderit in voluptate velit essecillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat nonproident, sunt in culpa qui officia deserunt mollit anim id est laborum.","bottomContent":null}
    ]},
    {"title":"Level 1","topContent":null,"bottomContent":null,"subCollection":[
      {"title":"Level 2","topContent":"Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmodtempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam,quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodoconsequat. Duis aute irure dolor in reprehenderit in voluptate velit essecillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat nonproident, sunt in culpa qui officia deserunt mollit anim id est laborum.","bottomContent":null},
      {"title":"Level 2","topContent":"Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmodtempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam,quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodoconsequat. Duis aute irure dolor in reprehenderit in voluptate velit essecillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat nonproident, sunt in culpa qui officia deserunt mollit anim id est laborum.","bottomContent":null},
      {"title":"Level 2","topContent":"Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmodtempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam,quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodoconsequat. Duis aute irure dolor in reprehenderit in voluptate velit essecillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat nonproident, sunt in culpa qui officia deserunt mollit anim id est laborum.","bottomContent":null}
    ]}
  ];

  $scope.sirAccordion = {
    collection: accordionCollection,
    config: accordionConfig
  };

  /* $timeout(function() {
    $scope.sirAccordion.collection[0].subCollection[0].title = 'hola';
  }, 2000);

  $timeout(function () {
    $scope.sirAccordion.collection[0] = {
      title: 'hola', topContent: 'hola'
    };
  }, 4000);

  $timeout(function () {
    $scope.sirAccordion.collection = [{
      title: 'hola', topContent: 'hola'
    }];
  }, 6000);

  $timeout(function () {
    $scope.sirAccordion.collection = [{
      title: 'chao', topContent: 'chao'
    }];
  }, 8000); */

  $scope.clickMe = function(){
    console.log('Hi I\'m Jeff');
    alert('Hi!');
  };

  $scope.toggleAutoCollapse = function(){
    $scope.$broadcast('sacCollapseAll');
    $scope.sirAccordion.config.autoCollapse = !$scope.sirAccordion.config.autoCollapse;
  };

  $scope.toggleAnimation = function() {
    if ($scope.sirAccordion.config.animDur){
      $scope.sirAccordion.config.animDur = 0;
      return;
    }
    $scope.sirAccordion.config.animDur = 300;
  };

  $scope.expandByCoord = function(){
    $scope.$broadcast('sacExpandContentById', $scope.coord);
  };

  $scope.collapseByCoord = function(){
    $scope.$broadcast('sacCollapseContentById', $scope.coord);
  };

  $scope.expandAll = function(){
    $scope.$broadcast('sacExpandAll');
  };

  $scope.collapseAll = function(){
    $scope.$broadcast('sacCollapseAll');
  };

  $scope.$on('sacExpandStart', function(data){
    console.log('sacExpandStart');
  });

  $scope.$on('sacExpandEnd', function (data) {
    console.log('sacExpandEnd');
  });

}]);<|endoftext|>


<commit_before>const windowStateKeeper = require('electron-window-state');
const {app, BrowserWindow, Menu, MenuItem, shell, ipcMain} = require('electron');
const path = require('path');

var mainWindow = null;

require('electron-context-menu')({
    showInspectElement: false
});

app.commandLine.appendSwitch('force-color-profile', 'srgb');

// Quit when all windows are closed.
app.on('window-all-closed', function() {
    if (process.platform != 'darwin') {
        app.quit();
    }
});

// This method will be called when Electron has finished
// initialization and is ready to create browser windows.
app.on('ready', function() {
    // Set default dimensions if a previous state isn't available
    let mainWindowState = windowStateKeeper({
        defaultWidth: 1280,
        defaultHeight: 768
    });

    // Create the browser window.
    mainWindow = new BrowserWindow(
        {
            "x": mainWindowState.x,
            "y": mainWindowState.y,
            "width": mainWindowState.width,
            "height": mainWindowState.height,
            backgroundColor: '#3F51B5',
            icon: path.join(__dirname, 'img/logo.png'),
            "webPreferences": {
                "allowDisplayingInsecureContent": true, // TODO: make it configurable
                "preload": path.join(__dirname, 'browser.js'),
                "nodeIntegration": false,
                "sandbox": true
            }
        }
    );
    mainWindowState.manage(mainWindow);

    // and load the index.html of the app.
    mainWindow.loadURL('file://' + __dirname + '/index.html');

    //mainWindow.openDevTools();

    mainWindow.setMenuBarVisibility(false);

    // Emitted when the window is closed.
    mainWindow.on('closed', function() {
        mainWindow = null;
    });

    app.on('activate', function(event) {
         mainWindow.show();
    });

    /*
    mainWindow.on('blur', function() {
        console.log('blur');
        mainWindow.blurWebView();
    });

    mainWindow.on('focus', function() {
        console.log('focus');
        mainWindow.focusOnWebView();
    });*/

    /*
    var appIcon = new Tray(__dirname + '/img/logo_tray.png');
    appIcon.setToolTip('Movim - Kickass Social Network');

    appIcon.on('clicked', function() {
        //if(mainWindow.isVisible()) {
        //    mainWindow.hide();
        //else {
            mainWindow.show();
        //}
    });*/

    mainWindow.webContents.on('new-window', function(e, url) {
        e.preventDefault();
        if(url.search('/?visio/') > -1) {
            var win = new BrowserWindow(
                {
                    "webPreferences": {
                        "allowDisplayingInsecureContent": true, // TODO: make it configurable
                        "preload": path.join(__dirname, 'browser.js'),
                        "nodeIntegration": false,
                        "sandbox": true
                    }
                }
            );
            win.setMenuBarVisibility(false);
            win.loadURL(url);
            win.on('closed', function() {
                win = null;
            });
        } else if (url.search('/?popuptest') == -1) {
            shell.openExternal(url);
        }
    });

    ipcMain.on('open-external', function(event, url) {
        shell.openExternal(url);
    });

    ipcMain.on('notification',  function(event, counter) {
        app.setBadgeCount(counter);
        if(counter > 0) {
            if(app.dock) {
                app.dock.bounce();
            }
            //appIcon.setImage(__dirname + '/img/logo_tray_notifs.png');
        } else {
            //appIcon.setImage(__dirname + '/img/logo_tray.png');
        }
    });

});
<commit_msg>Fix Movim's popup blocking detection<commit_after>const windowStateKeeper = require('electron-window-state');
const {app, BrowserWindow, Menu, MenuItem, shell, ipcMain} = require('electron');
const path = require('path');

var mainWindow = null;

require('electron-context-menu')({
    showInspectElement: false
});

app.commandLine.appendSwitch('force-color-profile', 'srgb');

// Quit when all windows are closed.
app.on('window-all-closed', function() {
    if (process.platform != 'darwin') {
        app.quit();
    }
});

// This method will be called when Electron has finished
// initialization and is ready to create browser windows.
app.on('ready', function() {
    // Set default dimensions if a previous state isn't available
    let mainWindowState = windowStateKeeper({
        defaultWidth: 1280,
        defaultHeight: 768
    });

    // Create the browser window.
    mainWindow = new BrowserWindow(
        {
            "x": mainWindowState.x,
            "y": mainWindowState.y,
            "width": mainWindowState.width,
            "height": mainWindowState.height,
            backgroundColor: '#3F51B5',
            icon: path.join(__dirname, 'img/logo.png'),
            "webPreferences": {
                "allowDisplayingInsecureContent": true, // TODO: make it configurable
                "preload": path.join(__dirname, 'browser.js'),
                "nodeIntegration": false,
                "sandbox": true
            }
        }
    );
    mainWindowState.manage(mainWindow);

    // and load the index.html of the app.
    mainWindow.loadURL('file://' + __dirname + '/index.html');

    //mainWindow.openDevTools();

    mainWindow.setMenuBarVisibility(false);

    // Emitted when the window is closed.
    mainWindow.on('closed', function() {
        mainWindow = null;
    });

    app.on('activate', function(event) {
         mainWindow.show();
    });

    /*
    mainWindow.on('blur', function() {
        console.log('blur');
        mainWindow.blurWebView();
    });

    mainWindow.on('focus', function() {
        console.log('focus');
        mainWindow.focusOnWebView();
    });*/

    /*
    var appIcon = new Tray(__dirname + '/img/logo_tray.png');
    appIcon.setToolTip('Movim - Kickass Social Network');

    appIcon.on('clicked', function() {
        //if(mainWindow.isVisible()) {
        //    mainWindow.hide();
        //else {
            mainWindow.show();
        //}
    });*/

    mainWindow.webContents.on('new-window', function(e, url) {
        e.preventDefault();
        if((url.search('/?visio/') > -1) || (url.search('/?popuptest') > -1)) {
            var win = new BrowserWindow(
                {
                    "webPreferences": {
                        "allowDisplayingInsecureContent": true, // TODO: make it configurable
                        "preload": path.join(__dirname, 'browser.js'),
                        "nodeIntegration": false
                    }
                }
            );
            win.setMenuBarVisibility(false);
            win.loadURL(url);
            win.on('closed', function() {
                win = null;
            });
        } else {
            shell.openExternal(url);
        }
    });

    ipcMain.on('open-external', function(event, url) {
        shell.openExternal(url);
    });

    ipcMain.on('notification',  function(event, counter) {
        app.setBadgeCount(counter);
        if(counter > 0) {
            if(app.dock) {
                app.dock.bounce();
            }
            //appIcon.setImage(__dirname + '/img/logo_tray_notifs.png');
        } else {
            //appIcon.setImage(__dirname + '/img/logo_tray.png');
        }
    });

});
<|endoftext|>


<commit_before>$(document).ready(function(){
    // Simple shim to mark the current page as active
    (function(){
        var pageUrl = location.href, linkFound = false;
        // Attempt 1 - Check the top level page URLS
        $('ul.nav > li').each(function(idx, li){
            if(linkFound) return;
            var linkHref = $(li).find('a').attr('href').replace('../', '');
            if(pageUrl.indexOf(linkHref) >= 0) {
                $(li).addClass('active');
                linkFound = true;
            }
        });

        // Attempt 2 - Check child pages
        if(!linkFound) {
            pageUrl = location.pathname;
            $('ul.nav > li').each(function(idx, li){
                if(linkFound) return;
                var linkHref = $(li).find('a').attr('href').replace('../', '');
                var baseUrl = linkHref.substring(0, linkHref.lastIndexOf('/') + 1);
                if(pageUrl.indexOf(baseUrl) >= 0) {
                    $(li).addClass('active');
                    linkFound = true;
                }
            });
        }
    }());
});<commit_msg>Added highlighting support for drop downs<commit_after>$(document).ready(function(){
    // Simple shim to mark the current page as active
    (function(){
        var pageUrl = location.href, linkFound = false;
        // Attempt 1 - Check the top level page URLS
        $('ul.nav > li').each(function(idx, li){
            if(linkFound) return;
            var linkHref = $(li).find('a').attr('href').replace('../', '');
            if(pageUrl.indexOf(linkHref) >= 0) { $(li).addClass('active'); linkFound = true; }
        });

        // Attempt 2 - Check child pages
        if(!linkFound) {
            pageUrl = location.pathname;
            $('ul.nav > li').each(function(idx, li){
                if(linkFound) return;
                var linkHref = $(li).find('a').attr('href').replace('../', '');
                var baseUrl = linkHref.substring(0, linkHref.lastIndexOf('/') + 1);
                if(baseUrl.length > 0 && pageUrl.indexOf(baseUrl) >= 0) { $(li).addClass('active'); linkFound = true; }
            });
        }

        // Attempt 3 - Check drop downs
        if(!linkFound) {
            $('ul.nav > li > ul > li').each(function(idx, li){
                if(linkFound) return;
                var linkHref = $(li).find('a').attr('href').replace('../', '');
                var baseUrl = linkHref.substring(0, linkHref.lastIndexOf('/') + 1);
                if(pageUrl.indexOf(baseUrl) >= 0) { $(li).parent().parent().addClass('active');}
                if(pageUrl.indexOf(linkHref) >= 0){ $(li).addClass('active'); linkFound = true; }
            });
        }
    }());
});<|endoftext|>


<commit_before>/* @flow */

const _ = require(`lodash`)
const slash = require(`slash`)
const fs = require(`fs-extra`)
const md5File = require(`md5-file/promise`)
const crypto = require(`crypto`)
const del = require(`del`)
const path = require(`path`)
const convertHrtime = require(`convert-hrtime`)
const Promise = require(`bluebird`)

const apiRunnerNode = require(`../utils/api-runner-node`)
const mergeGatsbyConfig = require(`../utils/merge-gatsby-config`)
const { graphql } = require(`graphql`)
const { store, emitter } = require(`../redux`)
const loadPlugins = require(`./load-plugins`)
const report = require(`gatsby-cli/lib/reporter`)
const getConfigFile = require(`./get-config-file`)
const tracer = require(`opentracing`).globalTracer()
const preferDefault = require(`./prefer-default`)

// Show stack trace on unhandled promises.
process.on(`unhandledRejection`, (reason, p) => {
  report.panic(reason)
})

const {
  extractQueries,
} = require(`../internal-plugins/query-runner/query-watcher`)
const {
  runInitialQueries,
} = require(`../internal-plugins/query-runner/page-query-runner`)
const queryQueue = require(`../internal-plugins/query-runner/query-queue`)
const { writePages } = require(`../internal-plugins/query-runner/pages-writer`)
const {
  writeRedirects,
} = require(`../internal-plugins/query-runner/redirects-writer`)

// Override console.log to add the source file + line number.
// Useful for debugging if you lose a console.log somewhere.
// Otherwise leave commented out.
// require(`./log-line-function`)

type BootstrapArgs = {
  directory: string,
  prefixPaths?: boolean,
  parentSpan: Object,
}

module.exports = async (args: BootstrapArgs) => {
  const spanArgs = args.parentSpan ? { childOf: args.parentSpan } : {}
  const bootstrapSpan = tracer.startSpan(`bootstrap`, spanArgs)

  const program = {
    ...args,
    // Fix program directory path for windows env.
    directory: slash(args.directory),
  }

  store.dispatch({
    type: `SET_PROGRAM`,
    payload: program,
  })

  // Try opening the site's gatsby-config.js file.
  let activity = report.activityTimer(`open and validate gatsby-configs`, {
    parentSpan: bootstrapSpan,
  })
  activity.start()
  let config = await preferDefault(
    getConfigFile(program.directory, `gatsby-config`)
  )

  // theme gatsby configs can be functions or objects
  if (config.__experimentalThemes) {
    const themesConfig = await Promise.mapSeries(
      config.__experimentalThemes,
      async ([themeName, themeConfig]) => {
        const theme = await preferDefault(
          getConfigFile(themeName, `gatsby-config`)
        )
        // if theme is a function, call it with the themeConfig
        let themeConfigObj = theme
        if (_.isFunction(theme)) {
          themeConfigObj = theme(themeConfig)
        }
        // themes function as plugins too (gatsby-node, etc)
        return {
          ...themeConfigObj,
          plugins: [
            ...(themeConfigObj.plugins || []),
            // theme plugin is last so it's gatsby-node, etc can override it's declared plugins, like a normal site.
            { resolve: themeName, options: themeConfig },
          ],
        }
      }
    ).reduce(mergeGatsbyConfig, {})

    config = mergeGatsbyConfig(themesConfig, config)
  }

  if (config && config.polyfill) {
    report.warn(
      `Support for custom Promise polyfills has been removed in Gatsby v2. We only support Babel 7's new automatic polyfilling behavior.`
    )
  }

  store.dispatch({
    type: `SET_SITE_CONFIG`,
    payload: config,
  })

  activity.end()

  activity = report.activityTimer(`load plugins`)
  activity.start()
  const flattenedPlugins = await loadPlugins(config)
  activity.end()

  // onPreInit
  activity = report.activityTimer(`onPreInit`, {
    parentSpan: bootstrapSpan,
  })
  activity.start()
  await apiRunnerNode(`onPreInit`, { parentSpan: activity.span })
  activity.end()

  // Delete html and css files from the public directory as we don't want
  // deleted pages and styles from previous builds to stick around.
  activity = report.activityTimer(
    `delete html and css files from previous builds`,
    {
      parentSpan: bootstrapSpan,
    }
  )
  activity.start()
  await del([
    `public/*.{html,css}`,
    `public/**/*.{html,css}`,
    `!public/static`,
    `!public/static/**/*.{html,css}`,
  ])
  activity.end()

  activity = report.activityTimer(`initialize cache`)
  activity.start()
  // Check if any plugins have been updated since our last run. If so
  // we delete the cache is there's likely been changes
  // since the previous run.
  //
  // We do this by creating a hash of all the version numbers of installed
  // plugins, the site's package.json, gatsby-config.js, and gatsby-node.js.
  // The last, gatsby-node.js, is important as many gatsby sites put important
  // logic in there e.g. generating slugs for custom pages.
  const pluginVersions = flattenedPlugins.map(p => p.version)
  const hashes = await Promise.all([
    md5File(`package.json`),
    Promise.resolve(
      md5File(`${program.directory}/gatsby-config.js`).catch(() => {})
    ), // ignore as this file isn't required),
    Promise.resolve(
      md5File(`${program.directory}/gatsby-node.js`).catch(() => {})
    ), // ignore as this file isn't required),
  ])
  const pluginsHash = crypto
    .createHash(`md5`)
    .update(JSON.stringify(pluginVersions.concat(hashes)))
    .digest(`hex`)
  let state = store.getState()
  const oldPluginsHash = state && state.status ? state.status.PLUGINS_HASH : ``

  // Check if anything has changed. If it has, delete the site's .cache
  // directory and tell reducers to empty themselves.
  //
  // Also if the hash isn't there, then delete things just in case something
  // is weird.
  if (oldPluginsHash && pluginsHash !== oldPluginsHash) {
    report.info(report.stripIndent`
      One or more of your plugins have changed since the last time you ran Gatsby. As
      a precaution, we're deleting your site's cache to ensure there's not any stale
      data
    `)
  }

  if (!oldPluginsHash || pluginsHash !== oldPluginsHash) {
    try {
      await fs.remove(`${program.directory}/.cache`)
    } catch (e) {
      report.error(`Failed to remove .cache files.`, e)
    }
    // Tell reducers to delete their data (the store will already have
    // been loaded from the file system cache).
    store.dispatch({
      type: `DELETE_CACHE`,
    })
  }

  // Update the store with the new plugins hash.
  store.dispatch({
    type: `UPDATE_PLUGINS_HASH`,
    payload: pluginsHash,
  })

  // Now that we know the .cache directory is safe, initialize the cache
  // directory.
  await fs.ensureDir(`${program.directory}/.cache`)

  // Ensure the public/static directory
  await fs.ensureDir(`${program.directory}/public/static`)

  activity.end()

  // Copy our site files to the root of the site.
  activity = report.activityTimer(`copy gatsby files`, {
    parentSpan: bootstrapSpan,
  })
  activity.start()
  const srcDir = `${__dirname}/../../cache-dir`
  const siteDir = `${program.directory}/.cache`
  const tryRequire = `${__dirname}/../utils/test-require-error.js`
  try {
    await fs.copy(srcDir, siteDir, {
      clobber: true,
    })
    await fs.copy(tryRequire, `${siteDir}/test-require-error.js`, {
      clobber: true,
    })
    await fs.ensureDirSync(`${program.directory}/.cache/json`)

    // Ensure .cache/fragments exists and is empty. We want fragments to be
    // added on every run in response to data as fragments can only be added if
    // the data used to create the schema they're dependent on is available.
    await fs.emptyDir(`${program.directory}/.cache/fragments`)
  } catch (err) {
    report.panic(`Unable to copy site files to .cache`, err)
  }

  // Find plugins which implement gatsby-browser and gatsby-ssr and write
  // out api-runners for them.
  const hasAPIFile = (env, plugin) => {
    // The plugin loader has disabled SSR APIs for this plugin. Usually due to
    // multiple implementations of an API that can only be implemented once
    if (env === `ssr` && plugin.skipSSR === true) return undefined

    const envAPIs = plugin[`${env}APIs`]

    // Always include the site's gatsby-browser.js if it exists as it's
    // a handy place to include global styles and other global imports.
    try {
      if (env === `browser` && plugin.name === `default-site-plugin`) {
        return slash(
          require.resolve(path.join(plugin.resolve, `gatsby-${env}`))
        )
      }
    } catch (e) {
      // ignore
    }

    if (envAPIs && Array.isArray(envAPIs) && envAPIs.length > 0) {
      return slash(path.join(plugin.resolve, `gatsby-${env}`))
    }
    return undefined
  }

  const ssrPlugins = _.filter(
    flattenedPlugins.map(plugin => {
      return {
        resolve: hasAPIFile(`ssr`, plugin),
        options: plugin.pluginOptions,
      }
    }),
    plugin => plugin.resolve
  )

  const browserPlugins = _.filter(
    flattenedPlugins.map(plugin => {
      return {
        resolve: hasAPIFile(`browser`, plugin),
        options: plugin.pluginOptions,
      }
    }),
    plugin => plugin.resolve
  )

  const browserPluginsRequires = browserPlugins
    .map(
      plugin =>
        `{
      plugin: require('${plugin.resolve}'),
      options: ${JSON.stringify(plugin.options)},
    }`
    )
    .join(`,`)

  const browserAPIRunner = `module.exports = [${browserPluginsRequires}]\n`

  let sSRAPIRunner = ``

  try {
    sSRAPIRunner = fs.readFileSync(`${siteDir}/api-runner-ssr.js`, `utf-8`)
  } catch (err) {
    report.panic(`Failed to read ${siteDir}/api-runner-ssr.js`, err)
  }

  const ssrPluginsRequires = ssrPlugins
    .map(
      plugin =>
        `{
      plugin: require('${plugin.resolve}'),
      options: ${JSON.stringify(plugin.options)},
    }`
    )
    .join(`,`)
  sSRAPIRunner = `var plugins = [${ssrPluginsRequires}]\n${sSRAPIRunner}`

  fs.writeFileSync(
    `${siteDir}/api-runner-browser-plugins.js`,
    browserAPIRunner,
    `utf-8`
  )
  fs.writeFileSync(`${siteDir}/api-runner-ssr.js`, sSRAPIRunner, `utf-8`)

  activity.end()
  /**
   * Start the main bootstrap processes.
   */

  // onPreBootstrap
  activity = report.activityTimer(`onPreBootstrap`)
  activity.start()
  await apiRunnerNode(`onPreBootstrap`)
  activity.end()

  // Source nodes
  activity = report.activityTimer(`source and transform nodes`, {
    parentSpan: bootstrapSpan,
  })
  activity.start()
  await require(`../utils/source-nodes`)({ parentSpan: activity.span })
  activity.end()

  // Create Schema.
  activity = report.activityTimer(`building schema`, {
    parentSpan: bootstrapSpan,
  })
  activity.start()
  await require(`../schema`)({ parentSpan: activity.span })
  activity.end()

  // Collect resolvable extensions and attach to program.
  const extensions = [`.mjs`, `.js`, `.jsx`, `.wasm`, `.json`]
  // Change to this being an action and plugins implement `onPreBootstrap`
  // for adding extensions.
  const apiResults = await apiRunnerNode(`resolvableExtensions`, {
    traceId: `initial-resolvableExtensions`,
    parentSpan: bootstrapSpan,
  })

  store.dispatch({
    type: `SET_PROGRAM_EXTENSIONS`,
    payload: _.flattenDeep([extensions, apiResults]),
  })

  const graphqlRunner = (query, context = {}) => {
    const schema = store.getState().schema
    return graphql(schema, query, context, context, context)
  }

  // Collect pages.
  activity = report.activityTimer(`createPages`, {
    parentSpan: bootstrapSpan,
  })
  activity.start()
  await apiRunnerNode(`createPages`, {
    graphql: graphqlRunner,
    traceId: `initial-createPages`,
    waitForCascadingActions: true,
    parentSpan: activity.span,
  })
  activity.end()

  // A variant on createPages for plugins that want to
  // have full control over adding/removing pages. The normal
  // "createPages" API is called every time (during development)
  // that data changes.
  activity = report.activityTimer(`createPagesStatefully`, {
    parentSpan: bootstrapSpan,
  })
  activity.start()
  await apiRunnerNode(`createPagesStatefully`, {
    graphql: graphqlRunner,
    traceId: `initial-createPagesStatefully`,
    waitForCascadingActions: true,
    parentSpan: activity.span,
  })
  activity.end()

  activity = report.activityTimer(`onPreExtractQueries`, {
    parentSpan: bootstrapSpan,
  })
  activity.start()
  await apiRunnerNode(`onPreExtractQueries`, { parentSpan: activity.span })
  activity.end()

  // Update Schema for SitePage.
  activity = report.activityTimer(`update schema`, {
    parentSpan: bootstrapSpan,
  })
  activity.start()
  await require(`../schema`)({ parentSpan: activity.span })
  activity.end()

  require(`../schema/type-conflict-reporter`).printConflicts()

  // Extract queries
  activity = report.activityTimer(`extract queries from components`, {
    parentSpan: bootstrapSpan,
  })
  activity.start()
  await extractQueries()
  activity.end()

  // Start the createPages hot reloader.
  if (process.env.NODE_ENV !== `production`) {
    require(`./page-hot-reloader`)(graphqlRunner)
  }

  // Run queries
  activity = report.activityTimer(`run graphql queries`, {
    parentSpan: bootstrapSpan,
  })
  activity.start()
  const startQueries = process.hrtime()
  queryQueue.on(`task_finish`, () => {
    const stats = queryQueue.getStats()
    activity.setStatus(
      `${stats.total}/${stats.peak} ${(
        stats.total / convertHrtime(process.hrtime(startQueries)).seconds
      ).toFixed(2)} queries/second`
    )
  })
  await runInitialQueries(activity)
  activity.end()

  // Write out files.
  activity = report.activityTimer(`write out page data`, {
    parentSpan: bootstrapSpan,
  })
  activity.start()
  try {
    await writePages()
  } catch (err) {
    report.panic(`Failed to write out page data`, err)
  }
  activity.end()

  // Write out redirects.
  activity = report.activityTimer(`write out redirect data`, {
    parentSpan: bootstrapSpan,
  })
  activity.start()
  await writeRedirects()
  activity.end()

  const checkJobsDone = _.debounce(resolve => {
    const state = store.getState()
    if (state.jobs.active.length === 0) {
      report.log(``)
      report.info(`bootstrap finished - ${process.uptime()} s`)
      report.log(``)

      // onPostBootstrap
      activity = report.activityTimer(`onPostBootstrap`, {
        parentSpan: bootstrapSpan,
      })
      activity.start()
      apiRunnerNode(`onPostBootstrap`, { parentSpan: activity.span }).then(
        () => {
          activity.end()
          bootstrapSpan.finish()
          resolve({ graphqlRunner })
        }
      )
    }
  }, 100)

  if (store.getState().jobs.active.length === 0) {
    // onPostBootstrap
    activity = report.activityTimer(`onPostBootstrap`, {
      parentSpan: bootstrapSpan,
    })
    activity.start()
    await apiRunnerNode(`onPostBootstrap`, { parentSpan: activity.span })
    activity.end()

    bootstrapSpan.finish()

    report.log(``)
    report.info(`bootstrap finished - ${process.uptime()} s`)
    report.log(``)
    emitter.emit(`BOOTSTRAP_FINISHED`)
    return {
      graphqlRunner,
    }
  } else {
    return new Promise(resolve => {
      // Wait until all side effect jobs are finished.
      emitter.on(`END_JOB`, () => checkJobsDone(resolve))
    })
  }
}
<commit_msg>fix: fix builds without gatsby-config #8917 (#9256)<commit_after>/* @flow */

const _ = require(`lodash`)
const slash = require(`slash`)
const fs = require(`fs-extra`)
const md5File = require(`md5-file/promise`)
const crypto = require(`crypto`)
const del = require(`del`)
const path = require(`path`)
const convertHrtime = require(`convert-hrtime`)
const Promise = require(`bluebird`)

const apiRunnerNode = require(`../utils/api-runner-node`)
const mergeGatsbyConfig = require(`../utils/merge-gatsby-config`)
const { graphql } = require(`graphql`)
const { store, emitter } = require(`../redux`)
const loadPlugins = require(`./load-plugins`)
const report = require(`gatsby-cli/lib/reporter`)
const getConfigFile = require(`./get-config-file`)
const tracer = require(`opentracing`).globalTracer()
const preferDefault = require(`./prefer-default`)

// Show stack trace on unhandled promises.
process.on(`unhandledRejection`, (reason, p) => {
  report.panic(reason)
})

const {
  extractQueries,
} = require(`../internal-plugins/query-runner/query-watcher`)
const {
  runInitialQueries,
} = require(`../internal-plugins/query-runner/page-query-runner`)
const queryQueue = require(`../internal-plugins/query-runner/query-queue`)
const { writePages } = require(`../internal-plugins/query-runner/pages-writer`)
const {
  writeRedirects,
} = require(`../internal-plugins/query-runner/redirects-writer`)

// Override console.log to add the source file + line number.
// Useful for debugging if you lose a console.log somewhere.
// Otherwise leave commented out.
// require(`./log-line-function`)

type BootstrapArgs = {
  directory: string,
  prefixPaths?: boolean,
  parentSpan: Object,
}

module.exports = async (args: BootstrapArgs) => {
  const spanArgs = args.parentSpan ? { childOf: args.parentSpan } : {}
  const bootstrapSpan = tracer.startSpan(`bootstrap`, spanArgs)

  const program = {
    ...args,
    // Fix program directory path for windows env.
    directory: slash(args.directory),
  }

  store.dispatch({
    type: `SET_PROGRAM`,
    payload: program,
  })

  // Try opening the site's gatsby-config.js file.
  let activity = report.activityTimer(`open and validate gatsby-configs`, {
    parentSpan: bootstrapSpan,
  })
  activity.start()
  let config = await preferDefault(
    getConfigFile(program.directory, `gatsby-config`)
  )

  // theme gatsby configs can be functions or objects
  if (config && config.__experimentalThemes) {
    const themesConfig = await Promise.mapSeries(
      config.__experimentalThemes,
      async ([themeName, themeConfig]) => {
        const theme = await preferDefault(
          getConfigFile(themeName, `gatsby-config`)
        )
        // if theme is a function, call it with the themeConfig
        let themeConfigObj = theme
        if (_.isFunction(theme)) {
          themeConfigObj = theme(themeConfig)
        }
        // themes function as plugins too (gatsby-node, etc)
        return {
          ...themeConfigObj,
          plugins: [
            ...(themeConfigObj.plugins || []),
            // theme plugin is last so it's gatsby-node, etc can override it's declared plugins, like a normal site.
            { resolve: themeName, options: themeConfig },
          ],
        }
      }
    ).reduce(mergeGatsbyConfig, {})

    config = mergeGatsbyConfig(themesConfig, config)
  }

  if (config && config.polyfill) {
    report.warn(
      `Support for custom Promise polyfills has been removed in Gatsby v2. We only support Babel 7's new automatic polyfilling behavior.`
    )
  }

  store.dispatch({
    type: `SET_SITE_CONFIG`,
    payload: config,
  })

  activity.end()

  activity = report.activityTimer(`load plugins`)
  activity.start()
  const flattenedPlugins = await loadPlugins(config)
  activity.end()

  // onPreInit
  activity = report.activityTimer(`onPreInit`, {
    parentSpan: bootstrapSpan,
  })
  activity.start()
  await apiRunnerNode(`onPreInit`, { parentSpan: activity.span })
  activity.end()

  // Delete html and css files from the public directory as we don't want
  // deleted pages and styles from previous builds to stick around.
  activity = report.activityTimer(
    `delete html and css files from previous builds`,
    {
      parentSpan: bootstrapSpan,
    }
  )
  activity.start()
  await del([
    `public/*.{html,css}`,
    `public/**/*.{html,css}`,
    `!public/static`,
    `!public/static/**/*.{html,css}`,
  ])
  activity.end()

  activity = report.activityTimer(`initialize cache`)
  activity.start()
  // Check if any plugins have been updated since our last run. If so
  // we delete the cache is there's likely been changes
  // since the previous run.
  //
  // We do this by creating a hash of all the version numbers of installed
  // plugins, the site's package.json, gatsby-config.js, and gatsby-node.js.
  // The last, gatsby-node.js, is important as many gatsby sites put important
  // logic in there e.g. generating slugs for custom pages.
  const pluginVersions = flattenedPlugins.map(p => p.version)
  const hashes = await Promise.all([
    md5File(`package.json`),
    Promise.resolve(
      md5File(`${program.directory}/gatsby-config.js`).catch(() => {})
    ), // ignore as this file isn't required),
    Promise.resolve(
      md5File(`${program.directory}/gatsby-node.js`).catch(() => {})
    ), // ignore as this file isn't required),
  ])
  const pluginsHash = crypto
    .createHash(`md5`)
    .update(JSON.stringify(pluginVersions.concat(hashes)))
    .digest(`hex`)
  let state = store.getState()
  const oldPluginsHash = state && state.status ? state.status.PLUGINS_HASH : ``

  // Check if anything has changed. If it has, delete the site's .cache
  // directory and tell reducers to empty themselves.
  //
  // Also if the hash isn't there, then delete things just in case something
  // is weird.
  if (oldPluginsHash && pluginsHash !== oldPluginsHash) {
    report.info(report.stripIndent`
      One or more of your plugins have changed since the last time you ran Gatsby. As
      a precaution, we're deleting your site's cache to ensure there's not any stale
      data
    `)
  }

  if (!oldPluginsHash || pluginsHash !== oldPluginsHash) {
    try {
      await fs.remove(`${program.directory}/.cache`)
    } catch (e) {
      report.error(`Failed to remove .cache files.`, e)
    }
    // Tell reducers to delete their data (the store will already have
    // been loaded from the file system cache).
    store.dispatch({
      type: `DELETE_CACHE`,
    })
  }

  // Update the store with the new plugins hash.
  store.dispatch({
    type: `UPDATE_PLUGINS_HASH`,
    payload: pluginsHash,
  })

  // Now that we know the .cache directory is safe, initialize the cache
  // directory.
  await fs.ensureDir(`${program.directory}/.cache`)

  // Ensure the public/static directory
  await fs.ensureDir(`${program.directory}/public/static`)

  activity.end()

  // Copy our site files to the root of the site.
  activity = report.activityTimer(`copy gatsby files`, {
    parentSpan: bootstrapSpan,
  })
  activity.start()
  const srcDir = `${__dirname}/../../cache-dir`
  const siteDir = `${program.directory}/.cache`
  const tryRequire = `${__dirname}/../utils/test-require-error.js`
  try {
    await fs.copy(srcDir, siteDir, {
      clobber: true,
    })
    await fs.copy(tryRequire, `${siteDir}/test-require-error.js`, {
      clobber: true,
    })
    await fs.ensureDirSync(`${program.directory}/.cache/json`)

    // Ensure .cache/fragments exists and is empty. We want fragments to be
    // added on every run in response to data as fragments can only be added if
    // the data used to create the schema they're dependent on is available.
    await fs.emptyDir(`${program.directory}/.cache/fragments`)
  } catch (err) {
    report.panic(`Unable to copy site files to .cache`, err)
  }

  // Find plugins which implement gatsby-browser and gatsby-ssr and write
  // out api-runners for them.
  const hasAPIFile = (env, plugin) => {
    // The plugin loader has disabled SSR APIs for this plugin. Usually due to
    // multiple implementations of an API that can only be implemented once
    if (env === `ssr` && plugin.skipSSR === true) return undefined

    const envAPIs = plugin[`${env}APIs`]

    // Always include the site's gatsby-browser.js if it exists as it's
    // a handy place to include global styles and other global imports.
    try {
      if (env === `browser` && plugin.name === `default-site-plugin`) {
        return slash(
          require.resolve(path.join(plugin.resolve, `gatsby-${env}`))
        )
      }
    } catch (e) {
      // ignore
    }

    if (envAPIs && Array.isArray(envAPIs) && envAPIs.length > 0) {
      return slash(path.join(plugin.resolve, `gatsby-${env}`))
    }
    return undefined
  }

  const ssrPlugins = _.filter(
    flattenedPlugins.map(plugin => {
      return {
        resolve: hasAPIFile(`ssr`, plugin),
        options: plugin.pluginOptions,
      }
    }),
    plugin => plugin.resolve
  )

  const browserPlugins = _.filter(
    flattenedPlugins.map(plugin => {
      return {
        resolve: hasAPIFile(`browser`, plugin),
        options: plugin.pluginOptions,
      }
    }),
    plugin => plugin.resolve
  )

  const browserPluginsRequires = browserPlugins
    .map(
      plugin =>
        `{
      plugin: require('${plugin.resolve}'),
      options: ${JSON.stringify(plugin.options)},
    }`
    )
    .join(`,`)

  const browserAPIRunner = `module.exports = [${browserPluginsRequires}]\n`

  let sSRAPIRunner = ``

  try {
    sSRAPIRunner = fs.readFileSync(`${siteDir}/api-runner-ssr.js`, `utf-8`)
  } catch (err) {
    report.panic(`Failed to read ${siteDir}/api-runner-ssr.js`, err)
  }

  const ssrPluginsRequires = ssrPlugins
    .map(
      plugin =>
        `{
      plugin: require('${plugin.resolve}'),
      options: ${JSON.stringify(plugin.options)},
    }`
    )
    .join(`,`)
  sSRAPIRunner = `var plugins = [${ssrPluginsRequires}]\n${sSRAPIRunner}`

  fs.writeFileSync(
    `${siteDir}/api-runner-browser-plugins.js`,
    browserAPIRunner,
    `utf-8`
  )
  fs.writeFileSync(`${siteDir}/api-runner-ssr.js`, sSRAPIRunner, `utf-8`)

  activity.end()
  /**
   * Start the main bootstrap processes.
   */

  // onPreBootstrap
  activity = report.activityTimer(`onPreBootstrap`)
  activity.start()
  await apiRunnerNode(`onPreBootstrap`)
  activity.end()

  // Source nodes
  activity = report.activityTimer(`source and transform nodes`, {
    parentSpan: bootstrapSpan,
  })
  activity.start()
  await require(`../utils/source-nodes`)({ parentSpan: activity.span })
  activity.end()

  // Create Schema.
  activity = report.activityTimer(`building schema`, {
    parentSpan: bootstrapSpan,
  })
  activity.start()
  await require(`../schema`)({ parentSpan: activity.span })
  activity.end()

  // Collect resolvable extensions and attach to program.
  const extensions = [`.mjs`, `.js`, `.jsx`, `.wasm`, `.json`]
  // Change to this being an action and plugins implement `onPreBootstrap`
  // for adding extensions.
  const apiResults = await apiRunnerNode(`resolvableExtensions`, {
    traceId: `initial-resolvableExtensions`,
    parentSpan: bootstrapSpan,
  })

  store.dispatch({
    type: `SET_PROGRAM_EXTENSIONS`,
    payload: _.flattenDeep([extensions, apiResults]),
  })

  const graphqlRunner = (query, context = {}) => {
    const schema = store.getState().schema
    return graphql(schema, query, context, context, context)
  }

  // Collect pages.
  activity = report.activityTimer(`createPages`, {
    parentSpan: bootstrapSpan,
  })
  activity.start()
  await apiRunnerNode(`createPages`, {
    graphql: graphqlRunner,
    traceId: `initial-createPages`,
    waitForCascadingActions: true,
    parentSpan: activity.span,
  })
  activity.end()

  // A variant on createPages for plugins that want to
  // have full control over adding/removing pages. The normal
  // "createPages" API is called every time (during development)
  // that data changes.
  activity = report.activityTimer(`createPagesStatefully`, {
    parentSpan: bootstrapSpan,
  })
  activity.start()
  await apiRunnerNode(`createPagesStatefully`, {
    graphql: graphqlRunner,
    traceId: `initial-createPagesStatefully`,
    waitForCascadingActions: true,
    parentSpan: activity.span,
  })
  activity.end()

  activity = report.activityTimer(`onPreExtractQueries`, {
    parentSpan: bootstrapSpan,
  })
  activity.start()
  await apiRunnerNode(`onPreExtractQueries`, { parentSpan: activity.span })
  activity.end()

  // Update Schema for SitePage.
  activity = report.activityTimer(`update schema`, {
    parentSpan: bootstrapSpan,
  })
  activity.start()
  await require(`../schema`)({ parentSpan: activity.span })
  activity.end()

  require(`../schema/type-conflict-reporter`).printConflicts()

  // Extract queries
  activity = report.activityTimer(`extract queries from components`, {
    parentSpan: bootstrapSpan,
  })
  activity.start()
  await extractQueries()
  activity.end()

  // Start the createPages hot reloader.
  if (process.env.NODE_ENV !== `production`) {
    require(`./page-hot-reloader`)(graphqlRunner)
  }

  // Run queries
  activity = report.activityTimer(`run graphql queries`, {
    parentSpan: bootstrapSpan,
  })
  activity.start()
  const startQueries = process.hrtime()
  queryQueue.on(`task_finish`, () => {
    const stats = queryQueue.getStats()
    activity.setStatus(
      `${stats.total}/${stats.peak} ${(
        stats.total / convertHrtime(process.hrtime(startQueries)).seconds
      ).toFixed(2)} queries/second`
    )
  })
  await runInitialQueries(activity)
  activity.end()

  // Write out files.
  activity = report.activityTimer(`write out page data`, {
    parentSpan: bootstrapSpan,
  })
  activity.start()
  try {
    await writePages()
  } catch (err) {
    report.panic(`Failed to write out page data`, err)
  }
  activity.end()

  // Write out redirects.
  activity = report.activityTimer(`write out redirect data`, {
    parentSpan: bootstrapSpan,
  })
  activity.start()
  await writeRedirects()
  activity.end()

  const checkJobsDone = _.debounce(resolve => {
    const state = store.getState()
    if (state.jobs.active.length === 0) {
      report.log(``)
      report.info(`bootstrap finished - ${process.uptime()} s`)
      report.log(``)

      // onPostBootstrap
      activity = report.activityTimer(`onPostBootstrap`, {
        parentSpan: bootstrapSpan,
      })
      activity.start()
      apiRunnerNode(`onPostBootstrap`, { parentSpan: activity.span }).then(
        () => {
          activity.end()
          bootstrapSpan.finish()
          resolve({ graphqlRunner })
        }
      )
    }
  }, 100)

  if (store.getState().jobs.active.length === 0) {
    // onPostBootstrap
    activity = report.activityTimer(`onPostBootstrap`, {
      parentSpan: bootstrapSpan,
    })
    activity.start()
    await apiRunnerNode(`onPostBootstrap`, { parentSpan: activity.span })
    activity.end()

    bootstrapSpan.finish()

    report.log(``)
    report.info(`bootstrap finished - ${process.uptime()} s`)
    report.log(``)
    emitter.emit(`BOOTSTRAP_FINISHED`)
    return {
      graphqlRunner,
    }
  } else {
    return new Promise(resolve => {
      // Wait until all side effect jobs are finished.
      emitter.on(`END_JOB`, () => checkJobsDone(resolve))
    })
  }
}
<|endoftext|>


<commit_before>import { tree, render, element } from 'deku';

let Counter = {
  initialState () {
    return {
      secondsElapsed: 0
    }
  },

  render (component) {
    let { props, state } = component
    let { secondsElapsed } = state;
    return element('span', [ 'Seconds Elapsed: ' + secondsElapsed ]);
  },

  afterUpdate (component) {
    let { props, state } = component;
    if (state.secondsElapsed && state.secondsElapsed % 10 === 0) props.onAnEmittedEventFromCounter();
  },

  afterMount (component, el, setState) {
    var counter = 0;
    component.interval = setInterval(() => {
       setState({ secondsElapsed: counter++ })
    }, 1000);
  },

  beforeUnmount (component) {
    clearInterval(component.interval);
  }
}

function doSomething() {
  console.log('I did something.');
}

let counter = tree(
  <Counter onAnEmittedEventFromCounter={ doSomething }></Counter>
);

render(counter, document.body);
<commit_msg>Updating counter example to not use JSX<commit_after>import { tree, render, element } from 'deku';

let Counter = {
  initialState () {
    return {
      secondsElapsed: 0
    }
  },

  render (component) {
    let { props, state } = component
    let { secondsElapsed } = state;
    return element('span', [ 'Seconds Elapsed: ' + secondsElapsed ]);
  },

  afterUpdate (component) {
    let { props, state } = component;
    if (state.secondsElapsed && state.secondsElapsed % 10 === 0) props.onAnEmittedEventFromCounter();
  },

  afterMount (component, el, setState) {
    var counter = 0;
    component.interval = setInterval(() => {
       setState({ secondsElapsed: counter++ })
    }, 1000);
  },

  beforeUnmount (component) {
    clearInterval(component.interval);
  }
}

function doSomething() {
  console.log('I did something.');
}

let counter = tree(
  element(Counter, { onAnEmittedEventFromCounter: doSomething })
);

render(counter, document.body);
<|endoftext|>


<commit_before>import { observes } from 'ember-addons/ember-computed-decorators';
import { popupAjaxError } from 'discourse/lib/ajax-error';
import { withPluginApi } from 'discourse/lib/plugin-api';
import User from 'discourse/models/user';

function translatePost(post) {
  return Discourse.ajax('/translator/translate', {
    type: 'POST',
    data: { post_id: post.get('id') }
  }).then(function(res) {
    post.setProperties({
      "translated_text": res.translation,
      "detected_lang": res.detected_lang
    });
  });
}

function oldPluginCode() {
  const module = require('discourse/components/post-menu');
  const PostMenuComponent = module.default;
  const Button = module.Button;

  PostMenuComponent.registerButton(function(visibleButtons){
    if (!this.siteSettings.translator_enabled) return;
    if (!this.get('post.can_translate')) return;
    if (!User.current()) return;

    let [action, label, opts] = !this.get('isTranslated') ? ['translate', 'translator.view_translation'] : ['hideTranslation', 'translator.hide_translation', { className: 'translated' }];
    return visibleButtons.splice(0, 0, new Button(action, label, 'globe', opts));
  });

  PostMenuComponent.reopen({
    isTranslated: false,

    @observes('isTranslated', 'post.can_translate')
    toggleTranslation() {
      this.rerender();
    },

    clickTranslate(post) {
      const self = this;
      this.set('isTranslated', true);
      post.set("translated_text", true);

      translatePost(post).catch(function(error) {
        popupAjaxError(error);
        post.set("translated_text", null);
        self.set('isTranslated', false);
      });

      return false;
    },

    clickHideTranslation(post) {
      post.set("translated_text", null);
      this.set('isTranslated', false);
      return false;
    }
  });
}

function initializeTranslation(api) {
  const siteSettings = api.container.lookup('site-settings:main');
  const currentUser = api.getCurrentUser();

  if (!currentUser) { return; }
  if (!siteSettings.translator_enabled) { return; }

  api.includePostAttributes('can_translate', 'translated_text', 'detected_lang');

  api.decorateWidget('post-menu:before', dec => {
    if (!dec.state.isTranslated) { return; }

    if (dec.state.isTranslating) {
      return dec.h('div.spinner.small');
    }

    const language = dec.attrs.detected_lang;
    const translator = siteSettings.translator;

    return dec.h('div.post-translation',
                 [dec.h('hr'),
                  dec.h('div.post-attribution', I18n.t('translator.translated_from', { language, translator })),
                  dec.cooked(dec.attrs.translated_text)]);
  });

  api.attachWidgetAction('post-menu', 'translate', function() {
    const state = this.state;
    state.isTranslated = true;
    state.isTranslating = true;
    this.scheduleRerender();

    const post = this.findAncestorModel();

    if (post) {
      return translatePost(post).catch(error => {
        popupAjaxError(error);
        state.isTranslating = false;
        state.isTranslated = false;
      }).finally(() => state.isTranslating = false);
    }
  });

  api.attachWidgetAction('post-menu', 'hideTranslation', function() {
    this.state.isTranslated = false;
    const post = this.findAncestorModel();
    if (post) {
      post.set('translated_text', '');
    }
  });

  api.addPostMenuButton('translate', (attrs, state) => {
    if (!attrs.can_translate) { return; }

    const [action, title] = !state.isTranslated ? ['translate', 'translator.view_translation'] :
                                                  ['hideTranslation', 'translator.hide_translation'];

    return {
      action,
      title,
      icon: 'globe',
      position: 'first',
      className: state.isTranslated ? 'translated' : null
    };
  });
}

export default {
  name: 'extend-for-translate-button',
  initialize() {
    withPluginApi('0.1', api => initializeTranslation(api), { noApi: oldPluginCode });
  }
};
<commit_msg>Use ajax module<commit_after>import { observes } from 'ember-addons/ember-computed-decorators';
import { popupAjaxError } from 'discourse/lib/ajax-error';
import { withPluginApi } from 'discourse/lib/plugin-api';
import { ajax } from 'discourse/lib/ajax';
import User from 'discourse/models/user';

function translatePost(post) {
  return ajax('/translator/translate', {
    type: 'POST',
    data: { post_id: post.get('id') }
  }).then(function(res) {
    post.setProperties({
      "translated_text": res.translation,
      "detected_lang": res.detected_lang
    });
  });
}

function oldPluginCode() {
  const module = require('discourse/components/post-menu');
  const PostMenuComponent = module.default;
  const Button = module.Button;

  PostMenuComponent.registerButton(function(visibleButtons){
    if (!this.siteSettings.translator_enabled) return;
    if (!this.get('post.can_translate')) return;
    if (!User.current()) return;

    let [action, label, opts] = !this.get('isTranslated') ? ['translate', 'translator.view_translation'] : ['hideTranslation', 'translator.hide_translation', { className: 'translated' }];
    return visibleButtons.splice(0, 0, new Button(action, label, 'globe', opts));
  });

  PostMenuComponent.reopen({
    isTranslated: false,

    @observes('isTranslated', 'post.can_translate')
    toggleTranslation() {
      this.rerender();
    },

    clickTranslate(post) {
      const self = this;
      this.set('isTranslated', true);
      post.set("translated_text", true);

      translatePost(post).catch(function(error) {
        popupAjaxError(error);
        post.set("translated_text", null);
        self.set('isTranslated', false);
      });

      return false;
    },

    clickHideTranslation(post) {
      post.set("translated_text", null);
      this.set('isTranslated', false);
      return false;
    }
  });
}

function initializeTranslation(api) {
  const siteSettings = api.container.lookup('site-settings:main');
  const currentUser = api.getCurrentUser();

  if (!currentUser) { return; }
  if (!siteSettings.translator_enabled) { return; }

  api.includePostAttributes('can_translate', 'translated_text', 'detected_lang');

  api.decorateWidget('post-menu:before', dec => {
    if (!dec.state.isTranslated) { return; }

    if (dec.state.isTranslating) {
      return dec.h('div.spinner.small');
    }

    const language = dec.attrs.detected_lang;
    const translator = siteSettings.translator;

    return dec.h('div.post-translation',
                 [dec.h('hr'),
                  dec.h('div.post-attribution', I18n.t('translator.translated_from', { language, translator })),
                  dec.cooked(dec.attrs.translated_text)]);
  });

  api.attachWidgetAction('post-menu', 'translate', function() {
    const state = this.state;
    state.isTranslated = true;
    state.isTranslating = true;
    this.scheduleRerender();

    const post = this.findAncestorModel();

    if (post) {
      return translatePost(post).catch(error => {
        popupAjaxError(error);
        state.isTranslating = false;
        state.isTranslated = false;
      }).finally(() => state.isTranslating = false);
    }
  });

  api.attachWidgetAction('post-menu', 'hideTranslation', function() {
    this.state.isTranslated = false;
    const post = this.findAncestorModel();
    if (post) {
      post.set('translated_text', '');
    }
  });

  api.addPostMenuButton('translate', (attrs, state) => {
    if (!attrs.can_translate) { return; }

    const [action, title] = !state.isTranslated ? ['translate', 'translator.view_translation'] :
                                                  ['hideTranslation', 'translator.hide_translation'];

    return {
      action,
      title,
      icon: 'globe',
      position: 'first',
      className: state.isTranslated ? 'translated' : null
    };
  });
}

export default {
  name: 'extend-for-translate-button',
  initialize() {
    withPluginApi('0.1', api => initializeTranslation(api), { noApi: oldPluginCode });
  }
};
<|endoftext|>


<commit_before>var nimbuslabel = require('nimbus.label');

var win = Ti.UI.createWindow({
	backgroundColor:'#888'
});
win.open();

var text = '@ludolphus hello world emoji 😄 and #tagafteremoji other stuff € http://chimp.li/ work. And emoji on last line 😄😄😄😄😄';
var attr = [];
attr.push({type: 'font', value: {fontFamily: 'Times', fontSize: 10}, start: 0, length: text.length});
attr.push({type: 'link', value: 'mention://ludolphus', start: 0, length: 10});
attr.push({type: 'link', value: '#tagafteremoji', start: 36, length: 14});
attr.push({type: 'link', value: 'http://chimp.li/', start: 65, length: 16});

var l = nimbuslabel.createLabel({
	linkColor: '#ff8400',
	highlightedLinkBackgroundColor: '#007bff',
	attributedText: {text: text, attributes: attr},
	top:20,
	left:10,
	right:10,
	width:Ti.UI.FILL,
	height:Ti.UI.SIZE,
	touchEnable: true,
});

l.addEventListener('click', function(e) {
	Ti.API.log(e);
});

l.addEventListener('longpress', function(e) {
	Ti.API.log(e);
});

win.add(l);
<commit_msg>updated example to include setting text color<commit_after>var nimbuslabel = require('nimbus.label');

var win = Ti.UI.createWindow({
	backgroundColor:'#888'
});
win.open();

var text = '@ludolphus hello world emoji 😄 and #tagafteremoji other stuff € http://chimp.li/ work. And emoji on last line 😄😄😄😄😄';
var attr = [];
attr.push({type: 'font', value: {fontFamily: 'Times', fontSize: 10}, start: 0, length: text.length});
attr.push({type: 'color', value: '#ff0000', start: 0, length: text.length});
attr.push({type: 'link', value: 'mention://ludolphus', start: 0, length: 10});
attr.push({type: 'link', value: '#tagafteremoji', start: 36, length: 14});
attr.push({type: 'link', value: 'http://chimp.li/', start: 65, length: 16});

var l = nimbuslabel.createLabel({
	linkColor: '#ff8400',
	highlightedLinkBackgroundColor: '#007bff',
	attributedText: {text: text, attributes: attr},
	top:20,
	left:10,
	right:10,
	width:Ti.UI.FILL,
	height:Ti.UI.SIZE,
	touchEnable: true,
});

l.addEventListener('click', function(e) {
	Ti.API.log(e);
});

l.addEventListener('longpress', function(e) {
	Ti.API.log(e);
});

win.add(l);
<|endoftext|>


<commit_before>export default {
  baseUrl: window.ENV.uploadUrl + 'search/',

  search: function (query, page, typeName) {

    if (Ember.isNone(query)) {
      return Ember.RSVP.Promise.reject(new Ember.Error('Search query is required.'));
    }

    Ember.Logger.log('searchIndex::search::%@::%@'.fmt(query, typeName || 'all types'));

    var SearchIndex = this;

    return new Ember.RSVP.Promise(function (resolve, reject) {
      Ember.$.ajax({
        url: window.ENV.uploadUrl + 'search/',
        type: 'POST',
        data: Ember.$.extend(SearchIndex.siteAndToken(), {
          query: query,
          page: page || 1,
          typeName: typeName || null
        }),
        success: resolve,
        error: reject
      });
    }).then(function (data) {

      if (data.error) {
        return Ember.RSVP.reject(data.error);
      } else if (Ember.isEmpty(data.hits)) {
        return Ember.RSVP.reject('No results.');
      } else {

        var items = Ember.A([]);

        Ember.$.each(data.hits, function(index, value) {
          var highlights = Ember.A([]);

          var name = value.fields.name ? value.fields.name[0] : '';

          if (value.highlight) {
            for (var key in value.highlight) {
              if(key === 'name') {
                name = value.highlight[key][0];
              } else {
                highlights.push({
                  key: key,
                  highlight: value.highlight[key][0]
                });
              }
            }
          }

          items.push({
            name: name,
            oneOff: value.fields.__oneOff ? (value.fields.__oneOff[0] === "true" ? true : false ): false,
            id: value._id,
            type: value._type,
            highlights: highlights
          });
        });

        return Ember.RSVP.resolve(items);
      }
    });

  },

  indexItem: function (item) {

    if (Ember.isEmpty(item) || Ember.isEmpty(item.get('itemData')) || !Ember.keys(item.get('itemData')).get('length')) {
      return Ember.RSVP.reject('Cannot index without an item data.');
    }

    var typeKey = item.constructor.typeKey;

    // handle one offs
    if (typeKey === 'data') {
      typeKey = item.get('id');
    }

    var contentType = item.store.getById('content-type', typeKey);

    if (Ember.isEmpty(contentType)) {
      return Ember.RSVP.reject('Cannot index without a content type.');
    }

    var searchData = {};

    // Simplify search indexing by storing all objects as strings.
    Ember.$.each(item.get('itemData'), function (key, value) {
      if (value === null) {
        return;
      }
      if (item.get('itemData').hasOwnProperty(key)) {
        if (typeof value === 'object') {
          if (JSON.stringify(value) !== '{}') {
            searchData[key] = JSON.stringify(value);
          }
        } else {
          searchData[key] = value;
        }
      }
    });

    var ajaxData = Ember.$.extend(this.siteAndToken(), {
      id: item.get('id'),
      data: JSON.stringify(searchData),
      typeName: contentType.get('id'),
      oneOff: contentType.get('oneOff')
    });

    Ember.Logger.log("SearchIndex::indexItem::%@::%@".fmt(contentType.get('id'), item.get('itemData.name')));

    return Ember.$.ajax({
      url: this.baseUrl + 'index/',
      type: 'POST',
      data: ajaxData
    });

  },

  indexType: function (contentType) {

    Ember.Logger.log("SearchIndex::indexType::%@".fmt(contentType.get('id')));

    var SearchIndex = this;
    var modelName = contentType.get('itemModelName');
    var store = contentType.store;

    contentType.set('indexingComplete', 0);
    contentType.set('indexingTotal', Infinity);

    return SearchIndex.deleteType(contentType).then(function () {

      if (contentType.get('oneOff')) {

        return store.find(modelName, contentType.get('id')).then(function (item) {

          contentType.set('indexingTotal', 1);

          return SearchIndex.indexItem(item).then(function () {
            contentType.incrementProperty('indexingComplete');
          });

        }, function (error) {
          contentType.set('indexingTotal', 0);
          Ember.Logger.warn('SearchIndex::indexType::Could not find %@, continuing.'.fmt(contentType.get('id')));
        });

      } else {

        return store.find(modelName).then(function (items) {

          contentType.set('indexingTotal', items.get('length'));

          var indexItems = items.map(function (item) {
            return SearchIndex.indexItem(item).then(function () {
              contentType.incrementProperty('indexingComplete');
            });
          });

          return Ember.RSVP.allSettled(indexItems);

        });

      }

    });

  },

  indexSite: function () {

    Ember.Logger.log("SearchIndex::indexSite");

    var SearchIndex = this;
    var store = window.App.__container__.lookup('store:main');

    store.find('content-type').then(function (contentTypes) {

      var contentTypePromises = contentTypes.map(function (contentType) {
        return SearchIndex.indexType(contentType);
      });

      return Ember.RSVP.Promise.all(contentTypePromises);

    });

  },

  deleteItem: function (item, contentType) {

    Ember.Logger.log("SearchIndex::deleteItem::%@::%@".fmt(contentType.get('id'), item.get('itemData.name')));

    return Ember.$.ajax({
      url: this.baseUrl + 'delete/',
      type: 'POST',
      data: Ember.$.extend(this.siteAndToken(), {
        id: item.get('id'),
        typeName: contentType.get('id')
      })
    });
  },

  // contentType can be id or model
  deleteType: function (contentType) {

    var id = typeof contentType === 'string' ? contentType : contentType.get('id');

    Ember.Logger.log("SearchIndex::deleteType::%@".fmt(id));

    return Ember.$.ajax({
      url: this.baseUrl + 'delete/type/',
      type: 'POST',
      data: Ember.$.extend(this.siteAndToken(), {
        typeName: id
      })
    });
  },

  deleteSite: function () {
    Ember.Logger.log("SearchIndex::deleteSite");
    return Ember.$.ajax({
      url: this.baseUrl + 'delete/index/',
      type: 'POST',
      data: this.siteAndToken()
    });
  },

  reindex: function () {
    return this.indexSite();
  },

  siteAndToken: function () {
    var session = window.App.__container__.lookup('controller:application').get('session');

    return {
      site: session.get('site.name'),
      token: session.get('site.token')
    };
  }

};
<commit_msg>return promise<commit_after>export default {
  baseUrl: window.ENV.uploadUrl + 'search/',

  search: function (query, page, typeName) {

    if (Ember.isNone(query)) {
      return Ember.RSVP.Promise.reject(new Ember.Error('Search query is required.'));
    }

    Ember.Logger.log('searchIndex::search::%@::%@'.fmt(query, typeName || 'all types'));

    var SearchIndex = this;

    return new Ember.RSVP.Promise(function (resolve, reject) {
      Ember.$.ajax({
        url: window.ENV.uploadUrl + 'search/',
        type: 'POST',
        data: Ember.$.extend(SearchIndex.siteAndToken(), {
          query: query,
          page: page || 1,
          typeName: typeName || null
        }),
        success: resolve,
        error: reject
      });
    }).then(function (data) {

      if (data.error) {
        return Ember.RSVP.reject(data.error);
      } else if (Ember.isEmpty(data.hits)) {
        return Ember.RSVP.reject('No results.');
      } else {

        var items = Ember.A([]);

        Ember.$.each(data.hits, function(index, value) {
          var highlights = Ember.A([]);

          var name = value.fields.name ? value.fields.name[0] : '';

          if (value.highlight) {
            for (var key in value.highlight) {
              if(key === 'name') {
                name = value.highlight[key][0];
              } else {
                highlights.push({
                  key: key,
                  highlight: value.highlight[key][0]
                });
              }
            }
          }

          items.push({
            name: name,
            oneOff: value.fields.__oneOff ? (value.fields.__oneOff[0] === "true" ? true : false ): false,
            id: value._id,
            type: value._type,
            highlights: highlights
          });
        });

        return Ember.RSVP.resolve(items);
      }
    });

  },

  indexItem: function (item) {

    if (Ember.isEmpty(item) || Ember.isEmpty(item.get('itemData')) || !Ember.keys(item.get('itemData')).get('length')) {
      return Ember.RSVP.reject('Cannot index without an item data.');
    }

    var typeKey = item.constructor.typeKey;

    // handle one offs
    if (typeKey === 'data') {
      typeKey = item.get('id');
    }

    var contentType = item.store.getById('content-type', typeKey);

    if (Ember.isEmpty(contentType)) {
      return Ember.RSVP.reject('Cannot index without a content type.');
    }

    var searchData = {};

    // Simplify search indexing by storing all objects as strings.
    Ember.$.each(item.get('itemData'), function (key, value) {
      if (value === null) {
        return;
      }
      if (item.get('itemData').hasOwnProperty(key)) {
        if (typeof value === 'object') {
          if (JSON.stringify(value) !== '{}') {
            searchData[key] = JSON.stringify(value);
          }
        } else {
          searchData[key] = value;
        }
      }
    });

    var ajaxData = Ember.$.extend(this.siteAndToken(), {
      id: item.get('id'),
      data: JSON.stringify(searchData),
      typeName: contentType.get('id'),
      oneOff: contentType.get('oneOff')
    });

    Ember.Logger.log("SearchIndex::indexItem::%@::%@".fmt(contentType.get('id'), item.get('itemData.name')));

    return Ember.$.ajax({
      url: this.baseUrl + 'index/',
      type: 'POST',
      data: ajaxData
    });

  },

  indexType: function (contentType) {

    Ember.Logger.log("SearchIndex::indexType::%@".fmt(contentType.get('id')));

    var SearchIndex = this;
    var modelName = contentType.get('itemModelName');
    var store = contentType.store;

    contentType.set('indexingComplete', 0);
    contentType.set('indexingTotal', Infinity);

    return SearchIndex.deleteType(contentType).then(function () {

      if (contentType.get('oneOff')) {

        return store.find(modelName, contentType.get('id')).then(function (item) {

          contentType.set('indexingTotal', 1);

          return SearchIndex.indexItem(item).then(function () {
            contentType.incrementProperty('indexingComplete');
          });

        }, function (error) {
          contentType.set('indexingTotal', 0);
          Ember.Logger.warn('SearchIndex::indexType::Could not find %@, continuing.'.fmt(contentType.get('id')));
        });

      } else {

        return store.find(modelName).then(function (items) {

          contentType.set('indexingTotal', items.get('length'));

          var indexItems = items.map(function (item) {
            return SearchIndex.indexItem(item).then(function () {
              contentType.incrementProperty('indexingComplete');
            });
          });

          return Ember.RSVP.allSettled(indexItems);

        });

      }

    });

  },

  indexSite: function () {

    Ember.Logger.log("SearchIndex::indexSite");

    var SearchIndex = this;
    var store = window.App.__container__.lookup('store:main');

    return store.find('content-type').then(function (contentTypes) {

      var contentTypePromises = contentTypes.map(function (contentType) {
        return SearchIndex.indexType(contentType);
      });

      return Ember.RSVP.Promise.all(contentTypePromises);

    });

  },

  deleteItem: function (item, contentType) {

    Ember.Logger.log("SearchIndex::deleteItem::%@::%@".fmt(contentType.get('id'), item.get('itemData.name')));

    return Ember.$.ajax({
      url: this.baseUrl + 'delete/',
      type: 'POST',
      data: Ember.$.extend(this.siteAndToken(), {
        id: item.get('id'),
        typeName: contentType.get('id')
      })
    });
  },

  // contentType can be id or model
  deleteType: function (contentType) {

    var id = typeof contentType === 'string' ? contentType : contentType.get('id');

    Ember.Logger.log("SearchIndex::deleteType::%@".fmt(id));

    return Ember.$.ajax({
      url: this.baseUrl + 'delete/type/',
      type: 'POST',
      data: Ember.$.extend(this.siteAndToken(), {
        typeName: id
      })
    });
  },

  deleteSite: function () {
    Ember.Logger.log("SearchIndex::deleteSite");
    return Ember.$.ajax({
      url: this.baseUrl + 'delete/index/',
      type: 'POST',
      data: this.siteAndToken()
    });
  },

  reindex: function () {
    return this.indexSite();
  },

  siteAndToken: function () {
    var session = window.App.__container__.lookup('controller:application').get('session');

    return {
      site: session.get('site.name'),
      token: session.get('site.token')
    };
  }

};
<|endoftext|>


<commit_before>'use strict';

/**
 * Listens for the app launching then creates the window.
 *
 * @see http://developer.chrome.com/apps/app.runtime.html
 * @see http://developer.chrome.com/apps/app.window.html
 */
chrome.app.runtime.onLaunched.addListener(function(lunchData) {
  var url = 'index.html';
  if (lunchData && lunchData.id) {
    switch (lunchData.id) {
      case 'google_drive_open':
        let _url = lunchData.url;
        _url = _url.substr(_url.indexOf('state') + 6);
        let data = JSON.parse(decodeURIComponent(_url));
        let id = data.ids[0];
        url += '#!/request/drive/' + id;
      break;
    }
  }
  var all = chrome.app.window.getAll();
  var length = all.length;
  var id = 'arc-window-' + length;
  chrome.app.window.create(
    url, {
      id: id,
      bounds: {
        width: 800,
        height: 600
      }
    }
  );
});

/**
 * Called when user use one of the commands registered in the manifest file.
 */
chrome.commands.onCommand.addListener(function(command) {
  console.log('Command:', command);
});
<commit_msg>Added function in background page to open multiple windows of the app<commit_after>'use strict';

var lunch = (url) => {
  if (!url) {
    url = 'index.html';
  }
  var all = chrome.app.window.getAll();
  var length = all.length;
  var id = 'arc-window-' + length;
  chrome.app.window.create(
    url, {
      id: id,
      bounds: {
        width: 800,
        height: 600
      }
    }
  );
};

/**
 * Listens for the app launching then creates the window.
 *
 * @see http://developer.chrome.com/apps/app.runtime.html
 * @see http://developer.chrome.com/apps/app.window.html
 */
chrome.app.runtime.onLaunched.addListener(function(lunchData) {
  var url = 'index.html';
  if (lunchData && lunchData.id) {
    switch (lunchData.id) {
      case 'google_drive_open':
        let _url = lunchData.url;
        _url = _url.substr(_url.indexOf('state') + 6);
        let data = JSON.parse(decodeURIComponent(_url));
        let id = data.ids[0];
        url += '#!/request/drive/' + id;
      break;
    }
  }
  lunch(url);
});

/**
 * Called when user use one of the commands registered in the manifest file.
 */
// chrome.commands.onCommand.addListener(function(command) {
//   console.log('Command:', command);
// });
<|endoftext|>


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

/**
 * External dependencies
 */
import { map } from 'lodash';

/**
 * WordPress dependencies
 */
import { __ } from '@wordpress/i18n';

/**
 * Internal dependencies
 */
import Data from 'googlesitekit-data';
import { getTimeInSeconds, numberFormat, getModulesData } from '../../../util';
import withData from '../../../components/higherorder/withdata';
import { TYPE_MODULES } from '../../../components/data';
import { getDataTableFromData, TableOverflowContainer } from '../../../components/data-table';
import PreviewTable from '../../../components/preview-table';
import { STORE_NAME } from '../datastore/constants';

const SearchConsoleDashboardWidgetKeywordTable = ( props ) => {
	const { data } = props;
	const { useSelect } = Data;
	const headers = [
		{
			title: __( 'Keyword', 'google-site-kit' ),
			tooltip: __( 'Most searched for keywords related to your content', 'google-site-kit' ),
			primary: true,
		},
		{
			title: __( 'Clicks', 'google-site-kit' ),
			tooltip: __( 'Number of times users clicked on your content in search results', 'google-site-kit' ),
		},
		{
			title: __( 'Impressions', 'google-site-kit' ),
			tooltip: __( 'Counted each time your content appears in search results', 'google-site-kit' ),
		},
	];
	const domain = getModulesData()[ 'search-console' ].settings.propertyID;
	const links = [];

	const dataMapped = map( data, ( row, i ) => {
		const query = row.keys[ 0 ];
		// eslint-disable-next-line react-hooks/rules-of-hooks
		links[ i ] = useSelect( ( select ) => select( STORE_NAME ).getServiceBaseURL(
			{
				path: 'performance/search-analytics',
				query: {
					resource_id: domain,
					num_of_days: 28 },
			}
		) );
		return [
			query,
			numberFormat( row.clicks ),
			numberFormat( row.impressions ),
		];
	} );

	const options = {
		hideHeader: false,
		chartsEnabled: false,
		links,
	};

	const dataTable = getDataTableFromData( dataMapped, headers, options );

	return (
		<TableOverflowContainer>
			{ dataTable }
		</TableOverflowContainer>
	);
};

export default withData(
	SearchConsoleDashboardWidgetKeywordTable,
	[
		{
			type: TYPE_MODULES,
			identifier: 'search-console',
			datapoint: 'searchanalytics',
			data: {
				url: global._googlesitekitLegacyData.permaLink,
				dimensions: 'query',
				limit: 10,
			},
			priority: 1,
			maxAge: getTimeInSeconds( 'day' ),
			context: [ 'Single', 'Dashboard' ],
		},
	],
	<PreviewTable padding />,
	{ createGrid: true },
	( returnedData ) => ! returnedData.length
);
<commit_msg>Use addQueryArgs to append the dynamic data.<commit_after>/**
 * SearchConsoleDashboardWidgetKeywordTable component.
 *
 * Site Kit by Google, Copyright 2019 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * External dependencies
 */
import { map } from 'lodash';

/**
 * WordPress dependencies
 */
import { __ } from '@wordpress/i18n';
import { addQueryArgs } from '@wordpress/url';

/**
 * Internal dependencies
 */
import Data from 'googlesitekit-data';
import { getTimeInSeconds, numberFormat, getModulesData } from '../../../util';
import withData from '../../../components/higherorder/withdata';
import { TYPE_MODULES } from '../../../components/data';
import { getDataTableFromData, TableOverflowContainer } from '../../../components/data-table';
import PreviewTable from '../../../components/preview-table';
import { STORE_NAME } from '../datastore/constants';

const SearchConsoleDashboardWidgetKeywordTable = ( props ) => {
	const { data } = props;
	const { useSelect } = Data;
	const headers = [
		{
			title: __( 'Keyword', 'google-site-kit' ),
			tooltip: __( 'Most searched for keywords related to your content', 'google-site-kit' ),
			primary: true,
		},
		{
			title: __( 'Clicks', 'google-site-kit' ),
			tooltip: __( 'Number of times users clicked on your content in search results', 'google-site-kit' ),
		},
		{
			title: __( 'Impressions', 'google-site-kit' ),
			tooltip: __( 'Counted each time your content appears in search results', 'google-site-kit' ),
		},
	];
	const domain = getModulesData()[ 'search-console' ].settings.propertyID;
	const links = [];

	const baseServiceURL = useSelect( ( select ) => select( STORE_NAME ).getServiceBaseURL( { path: '/performance/search-analytics' } ) );
	const dataMapped = map( data, ( row, i ) => {
		const query = row.keys[ 0 ];
		links[ i ] = addQueryArgs( baseServiceURL, { query, resource_id: domain, num_of_days: 28 } );
		return [
			query,
			numberFormat( row.clicks ),
			numberFormat( row.impressions ),
		];
	} );

	const options = {
		hideHeader: false,
		chartsEnabled: false,
		links,
	};

	const dataTable = getDataTableFromData( dataMapped, headers, options );

	return (
		<TableOverflowContainer>
			{ dataTable }
		</TableOverflowContainer>
	);
};

export default withData(
	SearchConsoleDashboardWidgetKeywordTable,
	[
		{
			type: TYPE_MODULES,
			identifier: 'search-console',
			datapoint: 'searchanalytics',
			data: {
				url: global._googlesitekitLegacyData.permaLink,
				dimensions: 'query',
				limit: 10,
			},
			priority: 1,
			maxAge: getTimeInSeconds( 'day' ),
			context: [ 'Single', 'Dashboard' ],
		},
	],
	<PreviewTable padding />,
	{ createGrid: true },
	( returnedData ) => ! returnedData.length
);
<|endoftext|>


<commit_before>//==================================
//	Kyle Russell
//	github.com/denkers/GameTop100
//	main-controller
//==================================

(function()
{
})();
<commit_msg>Removed javascript/controllers/main-controller<commit_after><|endoftext|>


<commit_before>var irc = require('irc');
var c = require('./');

var channel = '#colortest1234';
var client = new irc.Client('irc.freenode.com', 'colorbot1234', {
  channels: [channel]
});

client.on('message' + channel, function (from, message) {
  client.say(channel, 'echo ' + c.underline(message));
});

<commit_msg>bot tests a few more things<commit_after>var irc = require('irc');
var c = require('../');

var channel = '#colortest';
var client = new irc.Client('chat.freenode.net', 'colorbot1234', {
  channels: [channel]
});

client.on('message' + channel, function (from, message) {
  client.say(channel, 'underline: ' + c.underline(message));
  client.say(channel, 'bold:      ' + c.bold(message));
  client.say(channel, 'italic:    ' + c.italic(message));
});

<|endoftext|>