<commit_before>var path = require('path');
var fs = require('fs');
var request = require('request');
var async = require('async');
var _ = require('lodash');
var Handlebars = require('handlebars');
var mainTmpl = Handlebars.compile(
    fs.readFileSync(
        path.join(__dirname, 'templates/main.hbt')
    ).toString()
);

// Users must set these environment variables.
var HOST_URL = process.env.HOST_URL;

var BMB_JSON_URL = 'https://ci.numenta.com/rest/api/latest/result';
var BMB_HTML_URL = 'https://ci.numenta.com/browse';
var BAMBOO_PLANS = {
    'NuPIC Bamboo Jobs': [
        'NUP-PY'
      , 'NUP-CORE'
      , 'NUP-REGR'
    ]
  , 'Doc Builds': [
        'NUP-NUPDOCS'
      , 'NUP-COREDOCS'
  ]
  , 'Web Builds': [
      'WEB-COM'
    , 'WEB-ORG'
  ]
};

function toBootStrapClass(status) {
    switch(status) {
        case 'success':
        case 'Successful':
            return 'success';
        case 'pending':
            return 'warning';
        case 'error':
            return 'error';
        default:
            return 'danger';
    }
}

function errorResponse(err, res) {
    res.end(mainTmpl({
        title: 'ERROR getting status!',
        reports: [{
            slug: err.message,
            builds: []
        }]
    }));
}

function getOverallStatus(reports) {
    var status = 'success';
    _.each(reports, function(report) {
        if (report.status !== 'success') {
            status = toBootStrapClass(report.status);
        }
    });
    return status;
}

function getOpenGraphImage(status) {
    return HOST_URL + '/static/img/' + status + '.png';
}

function getOpenGraphDescription(status) {
    return {
        'success': 'All Numenta services and pipelines are operational.'
      , 'failure': 'There is a test failure or non-operational service.'
      , 'error': 'Error running a service or pipeline job.'
      , 'pending': 'Jobs are currently running, awaiting results.'
    }[status];
}

function processBambooPayload(payload, group) {
    return {
        title: payload.buildResultKey
      , name: payload.planName
      , link: BMB_HTML_URL + '/' + payload.buildResultKey
      , rawStatus: payload.state
      , status: toBootStrapClass(payload.state)
      , description: payload.reasonSummary + ' (' + payload.state + ')'
      , category: group
    };
}

function requestHander(req, res) {
    var fetchers = [];

    // Add all the bamboo plans we want to monitor.
    _.each(BAMBOO_PLANS, function(plans, group) {
        _.each(plans, function(planKey) {
            var jsonUrl = BMB_JSON_URL + '/' + planKey + '/latest.json';
            fetchers.push(function(callback) {
                request.get(jsonUrl, function(err, response, body) {
                    var payload = undefined;
                    if (err || response.statusCode != 200) {
                        return errorResponse(
                            new Error(
                                'Bad response (' + response.statusCode + ') from '
                                + jsonUrl
                            ), res
                        );
                    }
                    try {
                        payload = JSON.parse(body)
                    } catch (parseError) {
                        return errorResponse(parseError, res);
                    }
                    callback(null, processBambooPayload(payload, group));
                });
            });
        });
    });

    // URLs we want to monitor.
    _.each([
       'http://numenta.com',
       'http://numenta.org',
       'http://data.numenta.org',
       'http://tooling.numenta.org/status/',
       'https://discourse.numenta.org/'
    ], function(url) {
       fetchers.push(function(callback) {
           request.get(url, function(err, response) {
               var rawStatus = 'up';
               var status = 'success';
               if (err || response.statusCode != 200) {
                   rawStatus = 'down';
                   if (response && response.statusCode) {
                       rawStatus += ' (' + response.statusCode + ')';
                   }
                   status = 'failure';
               }
               callback(null, {
                   title: url
                 , link: url
                 , description: rawStatus
                 , rawStatus: rawStatus
                 , status: status
                 , category: 'URL Checks'
               });
           });
       });
    });

    async.parallel(fetchers, function(err, statusReports) {
        if (err) return errorResponse(err, res);
        var overallStatus = getOverallStatus(statusReports);
        var groupedReports = {};

        _.each(statusReports, function(report) {
            var category = report.category;
            if (! groupedReports[category]) {
                groupedReports[category] = {
                    category: category
                  , reports: []
                  , status: undefined
                };
            }
            groupedReports[category].reports.push(report);
        });

        _.each(groupedReports, function(report) {
            report.status = getOverallStatus(report.reports)
        });

        res.end(mainTmpl({
            title: 'Numenta On-Call Status'
          , url: HOST_URL
          , imageUrl: getOpenGraphImage(overallStatus)
          , description: getOpenGraphDescription(overallStatus)
          , reports: groupedReports
        }));
    });

}

module.exports = function() {
    return requestHander;
};
<commit_msg>Better error handling<commit_after>var path = require('path');
var fs = require('fs');
var request = require('request');
var async = require('async');
var _ = require('lodash');
var Handlebars = require('handlebars');
var mainTmpl = Handlebars.compile(
    fs.readFileSync(
        path.join(__dirname, 'templates/main.hbt')
    ).toString()
);

// Users must set these environment variables.
var HOST_URL = process.env.HOST_URL;

var BMB_JSON_URL = 'https://ci.numenta.com/rest/api/latest/result';
var BMB_HTML_URL = 'https://ci.numenta.com/browse';
var BAMBOO_PLANS = {
    'NuPIC Bamboo Jobs': [
        'NUP-PY'
      , 'NUP-CORE'
      , 'NUP-REGR'
    ]
  , 'Doc Builds': [
        'NUP-NUPDOCS'
      , 'NUP-COREDOCS'
  ]
  , 'Web Builds': [
      'WEB-COM'
    , 'WEB-ORG'
  ]
};

function toBootStrapClass(status) {
    switch(status) {
        case 'success':
        case 'Successful':
            return 'success';
        case 'pending':
            return 'warning';
        case 'error':
            return 'error';
        default:
            return 'danger';
    }
}

function errorResponse(err, res) {
    res.end(mainTmpl({
        title: 'ERROR getting status!',
        reports: [{
            slug: err.message,
            builds: []
        }]
    }));
}

function getOverallStatus(reports) {
    var status = 'success';
    _.each(reports, function(report) {
        if (report.status !== 'success') {
            status = toBootStrapClass(report.status);
        }
    });
    return status;
}

function getOpenGraphImage(status) {
    return HOST_URL + '/static/img/' + status + '.png';
}

function getOpenGraphDescription(status) {
    return {
        'success': 'All Numenta services and pipelines are operational.'
      , 'failure': 'There is a test failure or non-operational service.'
      , 'error': 'Error running a service or pipeline job.'
      , 'pending': 'Jobs are currently running, awaiting results.'
    }[status];
}

function processBambooPayload(payload, group) {
    return {
        title: payload.buildResultKey
      , name: payload.planName
      , link: BMB_HTML_URL + '/' + payload.buildResultKey
      , rawStatus: payload.state
      , status: toBootStrapClass(payload.state)
      , description: payload.reasonSummary + ' (' + payload.state + ')'
      , category: group
    };
}

function requestHander(req, res) {
    var fetchers = [];

    // Add all the bamboo plans we want to monitor.
    _.each(BAMBOO_PLANS, function(plans, group) {
        _.each(plans, function(planKey) {
            var jsonUrl = BMB_JSON_URL + '/' + planKey + '/latest.json';
            fetchers.push(function(callback) {
                request.get(jsonUrl, function(err, response, body) {
                    var payload = undefined;
                    if (err || response.statusCode != 200) {
                        console.log(err);
                        console.log(jsonUrl);
                        return errorResponse(
                            new Error(
                                'Bad response (' + err + ') from '
                                + jsonUrl
                            ), res
                        );
                    }
                    try {
                        payload = JSON.parse(body)
                    } catch (parseError) {
                        return errorResponse(parseError, res);
                    }
                    callback(null, processBambooPayload(payload, group));
                });
            });
        });
    });

    // URLs we want to monitor.
    _.each([
       'http://numenta.com',
       'http://numenta.org',
       'http://data.numenta.org',
       'http://tooling.numenta.org/status/',
       'https://discourse.numenta.org/'
    ], function(url) {
       fetchers.push(function(callback) {
           request.get(url, function(err, response) {
               var rawStatus = 'up';
               var status = 'success';
               if (err || response.statusCode != 200) {
                   rawStatus = 'down';
                   if (response && response.statusCode) {
                       rawStatus += ' (' + response.statusCode + ')';
                   }
                   status = 'failure';
               }
               callback(null, {
                   title: url
                 , link: url
                 , description: rawStatus
                 , rawStatus: rawStatus
                 , status: status
                 , category: 'URL Checks'
               });
           });
       });
    });

    async.parallel(fetchers, function(err, statusReports) {
        if (err) return errorResponse(err, res);
        var overallStatus = getOverallStatus(statusReports);
        var groupedReports = {};

        _.each(statusReports, function(report) {
            var category = report.category;
            if (! groupedReports[category]) {
                groupedReports[category] = {
                    category: category
                  , reports: []
                  , status: undefined
                };
            }
            groupedReports[category].reports.push(report);
        });

        _.each(groupedReports, function(report) {
            report.status = getOverallStatus(report.reports)
        });

        res.end(mainTmpl({
            title: 'Numenta On-Call Status'
          , url: HOST_URL
          , imageUrl: getOpenGraphImage(overallStatus)
          , description: getOpenGraphDescription(overallStatus)
          , reports: groupedReports
        }));
    });

}

module.exports = function() {
    return requestHander;
};
<|endoftext|>


<commit_before>import superagent from 'superagent';

const methods = ['get', 'post', 'put', 'patch', 'del'];

class _ApiClient {
  constructor(req) {
    methods.forEach((method) => {
      this[method] = (path, { params, data } = {}) => new Promise((resolve, reject) => {
        const request = superagent[method](path);

        if (params) {
          request.query(params);
        }

        if (__SERVER__ && req.get('cookie')) {
          request.set('cookie', req.get('cookie'));
        }

        if (data) {
          request.send(data);
        }

        request.end((err, { body } = {}) => err ? reject(body || err) : resolve(body));
      });
    });
  }
}

const ApiClient = _ApiClient;

export default ApiClient;
<commit_msg>Fixed eslint error<commit_after>import superagent from 'superagent';

const methods = ['get', 'post', 'put', 'patch', 'del'];

class _ApiClient {
  constructor(req) {
    methods.forEach((method) => {
      this[method] = (path, { params, data } = {}) => new Promise((resolve, reject) => {
        const request = superagent[method](path);

        if (params) {
          request.query(params);
        }

        if (__SERVER__ && req.get('cookie')) {
          request.set('cookie', req.get('cookie'));
        }

        if (data) {
          request.send(data);
        }

        request.end((err, { body } = {}) => (err ? reject(body || err) : resolve(body)));
      });
    });
  }
}

const ApiClient = _ApiClient;

export default ApiClient;
<|endoftext|>


<commit_before>import { createServices } from "./services";

export const pages = {
  home: {
    id: "Home",
    tab: "Home"
  },
  beer: {
    id: "Beer",
    tab: "Beer"
  },
  beerDetails: {
    id: "BeerDetails",
    tab: "Beer"
  },
  brewery: {
    id: "Brewery",
    tab: "Brewery"
  }
};

export const createNavigation = update => {
  const services = createServices();

  const navigate = (page, params = {}) =>
    update(model => Object.assign(model, ({ page, params })));

  const navigateTo = page => params => navigate(page, params);

  const navigateToBeer = () => {
    services.loadBeerList().then(beerList => {
      update(model => Object.assign(model, { beerList }));
      navigate(pages.beer);
    });
  };

  const navigateToBrewery = params => {
    services.loadBreweryList().then(breweryList => {
      update(model => Object.assign(model, {
        breweryList, brewery: { id: params.breweryId }, breweryBeerList: null }));
      navigate(pages.brewery, params);
    });
  };

  const navigateToBreweryBeerList = params => {
    services.loadBeerList(params.breweryId).then(beerList => {
      update(model => Object.assign(model, { brewery: { id: params.breweryId, beerList } }));
      navigate(pages.brewery, params);
    });
  };

  return {
    navigateToHome: navigateTo(pages.home),
    navigateToBeer,
    navigateToBeerDetails: navigateTo(pages.beerDetails),
    navigateToBrewery,
    navigateToBreweryBeerList
  };
};
<commit_msg>Advanced Routing example WIP<commit_after>import { createServices } from "./services";

export const pages = {
  home: {
    id: "Home",
    tab: "Home"
  },
  beer: {
    id: "Beer",
    tab: "Beer"
  },
  beerDetails: {
    id: "BeerDetails",
    tab: "Beer"
  },
  brewery: {
    id: "Brewery",
    tab: "Brewery"
  }
};

export const createNavigation = update => {
  const services = createServices();

  const navigate = (page, params = {}) =>
    update(model => Object.assign(model, ({ page, params })));

  const navigateTo = page => params => navigate(page, params);

  const navigateToBeer = () => {
    services.loadBeerList().then(beerList => {
      update(model => Object.assign(model, { beerList }));
      navigate(pages.beer);
    });
  };

  const navigateToBrewery = params => {
    if (params && params.breweryId) {
      update(model => Object.assign(model, { brewery: { id: params.breweryId } }));
      navigate(pages.brewery, params);
    }
    else {
      services.loadBreweryList().then(breweryList => {
        update(model => Object.assign(model, { breweryList }));
        navigate(pages.brewery, params);
      });
    }
  };

  const navigateToBreweryBeerList = params => {
    services.loadBeerList(params.breweryId).then(beerList => {
      update(model => Object.assign(model, { brewery: { id: params.breweryId, beerList } }));
      navigate(pages.brewery, params);
    });
  };

  return {
    navigateToHome: navigateTo(pages.home),
    navigateToBeer,
    navigateToBeerDetails: navigateTo(pages.beerDetails),
    navigateToBrewery,
    navigateToBreweryBeerList
  };
};
<|endoftext|>


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

  // Default task.
  grunt.registerTask('default', ['jshint:dev','build','karma:unit']);
  grunt.registerTask('dev', ['jshint:dev', 'build', 'webserver', 'open:dev', 'watch']);

  //run by the watch task
  grunt.registerTask('watch-js', ['jshint:dev','concat','copy:app','copy:mocks','copy:packages','copy:tuning','copy:vs','karma:unit']);
  grunt.registerTask('watch-less', ['recess:build', 'recess:installer', 'recess:tuning','copy:tuning', 'copy:assets', 'copy:vs']);
  grunt.registerTask('watch-html', ['copy:views', 'copy:vs']);
  grunt.registerTask('watch-packages', ['copy:packages']);
  grunt.registerTask('watch-installer', ['concat:install', 'concat:installJs', 'copy:installer', 'copy:vs']);
  grunt.registerTask('watch-tuning', ['copy:tuning', 'concat:tuningJs', 'copy:vs']);
  grunt.registerTask('watch-test', ['jshint:dev', 'karma:unit']);

  //triggered from grunt dev or grunt
  grunt.registerTask('build', ['clean', 'concat', 'recess:min', 'recess:installer', 'recess:tuning', 'bower', 'copy']);

  //utillity tasks
  grunt.registerTask('docs', ['ngdocs']);
  grunt.registerTask('webserver', ['connect:devserver']);

  // Print a timestamp (useful for when watching)
  grunt.registerTask('timestamp', function() {
    grunt.log.subhead(Date());
  });

    // Custom task to run the bower dependency installer
    // tried, a few other things but this seems to work the best.
    // https://coderwall.com/p/xnkdqw
  grunt.registerTask('bower', 'Get js packages listed in bower.json',
      function () {
          var bower = require('bower');
          var done = this.async();

          bower.commands.install(undefined, { }, { interactive: false })
              .on('log', function (data) {
                  grunt.log.write(data.message + "\n");
              })
              .on('error', function (data) {
                  grunt.log.write(data.message + "\n");
                  done(false);
              })
              .on('end', function (data) {
                  done();
              });
      }
    );

  // Project configuration.
  grunt.initConfig({
    buildVersion: grunt.option('buildversion') || '7',
    connect: {
             devserver: {
               options: {
                 port: 9990,
                 hostname: '0.0.0.0',
                 base: './build',
                 middleware: function(connect, options){
                   return [
                     //uncomment to enable CSP
                     // util.csp(),
                     //util.rewrite(),
                     connect.favicon('images/favicon.ico'),
                     connect.static(options.base),
                     connect.directory(options.base)
                   ];
                 }
               }
             },
             testserver: {}
           },

    open : {
      dev : {
          path: 'http://localhost:9990/belle/'
      }
    },

    distdir: 'build/belle',
    bowerfiles: 'bower_components',
    vsdir: '../Umbraco.Web.UI/umbraco',
    pkg: grunt.file.readJSON('package.json'),
    banner:
    '/*! <%= pkg.title || pkg.name %> - v<%= buildVersion %> - <%= grunt.template.today("yyyy-mm-dd") %>\n' +
    '<%= pkg.homepage ? " * " + pkg.homepage + "\\n" : "" %>' +
    ' * Copyright (c) <%= grunt.template.today("yyyy") %> <%= pkg.author %>;\n' +
    ' * Licensed <%= _.pluck(pkg.licenses, "type").join(", ") %>\n */\n',
    src: {
      js: ['src/**/*.js', 'src/*.js'],
      common: ['src/common/**/*.js'],
      specs: ['test/**/*.spec.js'],
      scenarios: ['test/**/*.scenario.js'],
      samples: ['sample files/*.js'],
      html: ['src/index.html','src/install.html'],

      everything:['src/**/*.*', 'test/**/*.*', 'docs/**/*.*'],

      tpl: {
        app: ['src/views/**/*.html'],
        common: ['src/common/**/*.tpl.html']
      },
      less: ['src/less/belle.less'], // recess:build doesn't accept ** in its file patterns
      prod: ['<%= distdir %>/js/*.js']
    },

    clean: ['<%= distdir %>/*'],

    copy: {
      assets: {
        files: [{ dest: '<%= distdir %>/assets', src : '**', expand: true, cwd: 'src/assets/' }]
      },

      // Copies over the files downloaded by bower
      bower: {
        files: [
                {
                  dest: '<%= distdir %>/lib/typeahead/typeahead.bundle.min.js',
                  src: 'bower_components/typeahead.js/dist/typeahead.bundle.min.js'
                },
                {
                  dest: '<%= distdir %>/lib/lazyload/lazyload.min.js',
                  src: 'bower_components/rgrove-lazyload/lazyload.js'
                },
                {
                  dest: '<%= distdir %>/lib/ace/',
                  src: '**',
                  expand: true,
                  cwd: 'bower_components/ace-builds/src-min-noconflict/'
                }
              ]
      },

      installer: {
        files: [{ dest: '<%= distdir %>/views/install', src : '**/*.html', expand: true, cwd: 'src/installer/steps' }]
      },

      tuning: {
          files: [
              { dest: '<%= distdir %>/preview', src: '**/*.html', expand: true, cwd: 'src/tuning' },
              { dest: '<%= distdir %>/assets/css', src: 'tuning.defaultStyle.css', expand: true, cwd: 'src/tuning' },
              { dest: '<%= distdir %>/assets/less', src: 'tuning.defaultStyle.less', expand: true, cwd: 'src/tuning' },
              { dest: '<%= distdir %>/assets/less', src: 'tuning.gridRowStyle.less', expand: true, cwd: 'src/tuning' },
              { dest: '<%= distdir %>/js', src: 'tuning.config.js', expand: true, cwd: 'src/tuning/config' },
              { dest: '<%= distdir %>/js', src: 'tuning.palettes.js', expand: true, cwd: 'src/tuning/config' },
              { dest: '<%= distdir %>/js', src: 'tuning.front.js', expand: true, cwd: 'src/tuning' }
          ]
      },

      vendor: {
        files: [{ dest: '<%= distdir %>/lib', src : '**', expand: true, cwd: 'lib/' }]
      },
      views: {
        files: [{ dest: '<%= distdir %>/views', src : ['**/*.*', '!**/*.controller.js'], expand: true, cwd: 'src/views/' }]
      },
      app: {
        files: [
            { dest: '<%= distdir %>/js', src : '*.js', expand: true, cwd: 'src/' }
            ]
      },
      mocks: {
        files: [{ dest: '<%= distdir %>/js', src : '*.js', expand: true, cwd: 'src/common/mocks/' }]
      },
      vs: {
          files: [
              //everything except the index.html root file!
              //then we need to figure out how to not copy all the test stuff either!?
              { dest: '<%= vsdir %>/assets', src: '**', expand: true, cwd: '<%= distdir %>/assets' },
              { dest: '<%= vsdir %>/js', src: '**', expand: true, cwd: '<%= distdir %>/js' },
              { dest: '<%= vsdir %>/lib', src: '**', expand: true, cwd: '<%= distdir %>/lib' },
              { dest: '<%= vsdir %>/views', src: '**', expand: true, cwd: '<%= distdir %>/views' },
              { dest: '<%= vsdir %>/preview', src: '**', expand: true, cwd: '<%= distdir %>/preview' }
          ]
      },

      packages: {
        files: [{ dest: '<%= vsdir %>/../App_Plugins', src : '**', expand: true, cwd: 'src/packages/' }]
      }
    },

    karma: {
      unit: { configFile: 'test/config/karma.conf.js', keepalive: true },
      e2e: { configFile: 'test/config/e2e.js', keepalive: true },
      watch: { configFile: 'test/config/unit.js', singleRun:false, autoWatch: true, keepalive: true }
    },

    concat:{
        index: {
          src: ['src/index.html'],
          dest: '<%= distdir %>/index.html',
          options: {
            process: true
          }
        },
        install: {
          src: ['src/installer/installer.html'],
          dest: '<%= distdir %>/installer.html',
          options: {
            process: true
          }
        },

        installJs: {
          src: ['src/installer/**/*.js'],
          dest: '<%= distdir %>/js/umbraco.installer.js',
          options: {
              banner: "<%= banner %>\n(function() { \n\n angular.module('umbraco.install', []); \n",
              footer: "\n\n})();"
          }
        },
        tuningJs: {
            src: ['src/tuning/tuning.global.js', 'src/tuning/tuning.controller.js', 'src/tuning/lib/slider.directive.js', 'src/tuning/lib/spectrum.directive.js'],
            dest: '<%= distdir %>/js/tuning.panel.js'
        },
        controllers: {
          src:['src/controllers/**/*.controller.js','src/views/**/*.controller.js'],
          dest: '<%= distdir %>/js/umbraco.controllers.js',
          options: {
              banner: "<%= banner %>\n(function() { \n\n",
              footer: "\n\n})();"
          }
        },
        services: {
          src:['src/common/services/*.js'],
          dest: '<%= distdir %>/js/umbraco.services.js',
          options: {
              banner: "<%= banner %>\n(function() { \n\n",
              footer: "\n\n})();"
          }
        },
        security: {
          src:['src/common/security/*.js'],
          dest: '<%= distdir %>/js/umbraco.security.js',
          options: {
              banner: "<%= banner %>\n(function() { \n\n",
              footer: "\n\n})();"
          }
        },
        resources: {
          src:['src/common/resources/*.js'],
          dest: '<%= distdir %>/js/umbraco.resources.js',
          options: {
              banner: "<%= banner %>\n(function() { \n\n",
              footer: "\n\n})();"
          }
        },
        testing: {
          src:['src/common/mocks/*/*.js'],
          dest: '<%= distdir %>/js/umbraco.testing.js',
          options: {
              banner: "<%= banner %>\n(function() { \n\n",
              footer: "\n\n})();"
          }
        },
        directives: {
          src:['src/common/directives/**/*.js'],
          dest: '<%= distdir %>/js/umbraco.directives.js',
          options: {
              banner: "<%= banner %>\n(function() { \n\n",
              footer: "\n\n})();"
          }
        },
        filters: {
          src:['src/common/filters/*.js'],
          dest: '<%= distdir %>/js/umbraco.filters.js',
          options: {
              banner: "<%= banner %>\n(function() { \n\n",
              footer: "\n\n})();"
          }
        }
    },

    uglify: {
      options: {
        mangle: true
      },
      combine: {
        files: {
          '<%= distdir %>/js/umbraco.min.js': ['<%= distdir %>/js/umbraco.*.js']
        }
      }
    },

    recess: {
      build: {
        files: {
          '<%= distdir %>/assets/css/<%= pkg.name %>.css':
          ['<%= src.less %>'] },
        options: {
          compile: true
        }
      },
      installer: {
        files: {
          '<%= distdir %>/assets/css/installer.css':
          ['src/less/installer.less'] },
        options: {
          compile: true
        }
      },
      tuning: {
          files: {
              '<%= distdir %>/assets/css/tuning.panelStyles.css':
              ['src/less/tuning.panelStyles.less', 'src/less/helveticons.less']
          },
          options: {
              compile: true
          }
      },
      min: {
        files: {
          '<%= distdir %>/assets/css/<%= pkg.name %>.css': ['<%= src.less %>']
        },
        options: {
          compile: true,
          compress: true
        }
      }
    },

    watch:{
      css: {
          files: '**/*.less',
          tasks: ['watch-less', 'timestamp'],
          options: {
            livereload: true,
          },
      },
      js: {
          files: ['src/**/*.js', 'src/*.js'],
          tasks: ['watch-js', 'timestamp'],
      },
      test: {
          files: ['test/**/*.js'],
          tasks: ['watch-test', 'timestamp'],
      },
      installer: {
          files: ['src/installer/**/*.*'],
          tasks: ['watch-installer', 'timestamp'],
      },
      tuning: {
          files: ['src/tuning/**/*.*'],
          tasks: ['watch-tuning', 'timestamp'],
      },
      html: {
        files: ['src/views/**/*.html', 'src/*.html'],
        tasks:['watch-html','timestamp']
      },

      packages: {
          files: 'src/packages/**/*.*',
          tasks: ['watch-packages', 'timestamp'],
      }
    },

    ngdocs: {
      options: {
        dest: 'docs/api',
        startPage: '/api',
        title: "Umbraco 7",
        html5Mode: false,
      },
      api: {
        src: ['src/common/**/*.js', 'docs/src/api/**/*.ngdoc'],
        title: 'API Documentation'
      },
      tutorials: {
        src: ['docs/src/tutorials/**/*.ngdoc'],
        title: 'Tutorials'
      }
    },

    jshint:{
      dev:{
         files: {
            src: ['<%= src.common %>', '<%= src.specs %>', '<%= src.scenarios %>', '<%= src.samples %>']
         },
         options:{
           curly:true,
           eqeqeq:true,
           immed:true,
           latedef:true,
           newcap:true,
           noarg:true,
           sub:true,
           boss: true,
             //NOTE: This is required so it doesn't barf on reserved words like delete when doing $http.delete
           es5: true,
           eqnull: true,
             //NOTE: we need to use eval sometimes so ignore it
           evil: true,
             //NOTE: we need to check for strings such as "javascript:" so don't throw errors regarding those
           scripturl: true,
             //NOTE: we ignore tabs vs spaces because enforcing that causes lots of errors depending on the text editor being used
           smarttabs: true,
           globals:{}
         }
      },
      build:{
         files: {
          src: ['<%= src.prod %>']
          },
          options:{
           curly:true,
           eqeqeq:true,
           immed:true,
           latedef:true,
           newcap:true,
           noarg:true,
           sub:true,
           boss: true,
            //NOTE: This is required so it doesn't barf on reserved words like delete when doing $http.delete
           es5: true,
           eqnull: true,
             //NOTE: we need to use eval sometimes so ignore it
           evil: true,
            //NOTE: we need to check for strings such as "javascript:" so don't throw errors regarding those
           scripturl: true,
            //NOTE: we ignore tabs vs spaces because enforcing that causes lots of errors depending on the text editor being used
           smarttabs: true,
           globalstrict:true,
           globals:{$:false, jQuery:false,define:false,require:false,window:false}
         }
      }
    }
  });

  grunt.loadNpmTasks('grunt-contrib-concat');
  grunt.loadNpmTasks('grunt-contrib-jshint');
  grunt.loadNpmTasks('grunt-contrib-clean');
  grunt.loadNpmTasks('grunt-contrib-copy');
  grunt.loadNpmTasks('grunt-contrib-uglify');
  grunt.loadNpmTasks('grunt-contrib-watch');
  grunt.loadNpmTasks('grunt-recess');

  grunt.loadNpmTasks('grunt-karma');

  grunt.loadNpmTasks('grunt-open');
  grunt.loadNpmTasks('grunt-contrib-connect');

  grunt.loadNpmTasks('grunt-ngdocs');

};
<commit_msg>More efficient grunt execution<commit_after>module.exports = function (grunt) {

  // Default task.
  grunt.registerTask('default', ['jshint:dev','build','karma:unit']);
  grunt.registerTask('dev', ['jshint:dev', 'build', 'webserver', 'open:dev', 'watch']);

  //run by the watch task
  grunt.registerTask('watch-js', ['jshint:dev','concat','copy:app','copy:mocks','copy:packages','copy:tuning','copy:vs']);
  grunt.registerTask('watch-less', ['recess:build', 'recess:installer', 'recess:tuning','copy:tuning', 'copy:assets', 'copy:vs']);
  grunt.registerTask('watch-html', ['copy:views', 'copy:vs']);
  grunt.registerTask('watch-packages', ['copy:packages']);
  grunt.registerTask('watch-installer', ['concat:install', 'concat:installJs', 'copy:installer', 'copy:vs']);
  grunt.registerTask('watch-tuning', ['copy:tuning', 'concat:tuningJs', 'copy:vs']);
  grunt.registerTask('watch-test', ['jshint:dev', 'karma:unit']);

  //triggered from grunt dev or grunt
  grunt.registerTask('build', ['clean', 'concat', 'recess:min', 'recess:installer', 'recess:tuning', 'bower', 'copy']);

  //utillity tasks
  grunt.registerTask('docs', ['ngdocs']);
  grunt.registerTask('webserver', ['connect:devserver']);

  // Print a timestamp (useful for when watching)
  grunt.registerTask('timestamp', function() {
    grunt.log.subhead(Date());
  });

    // Custom task to run the bower dependency installer
    // tried, a few other things but this seems to work the best.
    // https://coderwall.com/p/xnkdqw
  grunt.registerTask('bower', 'Get js packages listed in bower.json',
      function () {
          var bower = require('bower');
          var done = this.async();

          bower.commands.install(undefined, { }, { interactive: false })
              .on('log', function (data) {
                  grunt.log.write(data.message + "\n");
              })
              .on('error', function (data) {
                  grunt.log.write(data.message + "\n");
                  done(false);
              })
              .on('end', function (data) {
                  done();
              });
      }
    );

  // Project configuration.
  grunt.initConfig({
    buildVersion: grunt.option('buildversion') || '7',
    connect: {
             devserver: {
               options: {
                 port: 9990,
                 hostname: '0.0.0.0',
                 base: './build',
                 middleware: function(connect, options){
                   return [
                     //uncomment to enable CSP
                     // util.csp(),
                     //util.rewrite(),
                     connect.favicon('images/favicon.ico'),
                     connect.static(options.base),
                     connect.directory(options.base)
                   ];
                 }
               }
             },
             testserver: {}
           },

    open : {
      dev : {
          path: 'http://localhost:9990/belle/'
      }
    },

    distdir: 'build/belle',
    bowerfiles: 'bower_components',
    vsdir: '../Umbraco.Web.UI/umbraco',
    pkg: grunt.file.readJSON('package.json'),
    banner:
    '/*! <%= pkg.title || pkg.name %> - v<%= buildVersion %> - <%= grunt.template.today("yyyy-mm-dd") %>\n' +
    '<%= pkg.homepage ? " * " + pkg.homepage + "\\n" : "" %>' +
    ' * Copyright (c) <%= grunt.template.today("yyyy") %> <%= pkg.author %>;\n' +
    ' * Licensed <%= _.pluck(pkg.licenses, "type").join(", ") %>\n */\n',
    src: {
      js: ['src/**/*.js', 'src/*.js'],
      common: ['src/common/**/*.js'],
      specs: ['test/**/*.spec.js'],
      scenarios: ['test/**/*.scenario.js'],
      samples: ['sample files/*.js'],
      html: ['src/index.html','src/install.html'],

      everything:['src/**/*.*', 'test/**/*.*', 'docs/**/*.*'],

      tpl: {
        app: ['src/views/**/*.html'],
        common: ['src/common/**/*.tpl.html']
      },
      less: ['src/less/belle.less'], // recess:build doesn't accept ** in its file patterns
      prod: ['<%= distdir %>/js/*.js']
    },

    clean: ['<%= distdir %>/*'],

    copy: {
      assets: {
        files: [{ dest: '<%= distdir %>/assets', src : '**', expand: true, cwd: 'src/assets/' }]
      },

      // Copies over the files downloaded by bower
      bower: {
        files: [
                {
                  dest: '<%= distdir %>/lib/typeahead/typeahead.bundle.min.js',
                  src: 'bower_components/typeahead.js/dist/typeahead.bundle.min.js'
                },
                {
                  dest: '<%= distdir %>/lib/lazyload/lazyload.min.js',
                  src: 'bower_components/rgrove-lazyload/lazyload.js'
                }
              ]
      },

      installer: {
        files: [{ dest: '<%= distdir %>/views/install', src : '**/*.html', expand: true, cwd: 'src/installer/steps' }]
      },

      tuning: {
          files: [
              { dest: '<%= distdir %>/preview', src: '**/*.html', expand: true, cwd: 'src/tuning' },
              { dest: '<%= distdir %>/assets/css', src: 'tuning.defaultStyle.css', expand: true, cwd: 'src/tuning' },
              { dest: '<%= distdir %>/assets/less', src: 'tuning.defaultStyle.less', expand: true, cwd: 'src/tuning' },
              { dest: '<%= distdir %>/assets/less', src: 'tuning.gridRowStyle.less', expand: true, cwd: 'src/tuning' },
              { dest: '<%= distdir %>/js', src: 'tuning.config.js', expand: true, cwd: 'src/tuning/config' },
              { dest: '<%= distdir %>/js', src: 'tuning.palettes.js', expand: true, cwd: 'src/tuning/config' },
              { dest: '<%= distdir %>/js', src: 'tuning.front.js', expand: true, cwd: 'src/tuning' }
          ]
      },

      vendor: {
        files: [{ dest: '<%= distdir %>/lib', src : '**', expand: true, cwd: 'lib/' }]
      },
      views: {
        files: [{ dest: '<%= distdir %>/views', src : ['**/*.*', '!**/*.controller.js'], expand: true, cwd: 'src/views/' }]
      },
      app: {
        files: [
            { dest: '<%= distdir %>/js', src : '*.js', expand: true, cwd: 'src/' }
            ]
      },
      mocks: {
        files: [{ dest: '<%= distdir %>/js', src : '*.js', expand: true, cwd: 'src/common/mocks/' }]
      },
      vs: {
          files: [
              //everything except the index.html root file!
              //then we need to figure out how to not copy all the test stuff either!?
              { dest: '<%= vsdir %>/assets', src: '**', expand: true, cwd: '<%= distdir %>/assets' },
              { dest: '<%= vsdir %>/js', src: '**', expand: true, cwd: '<%= distdir %>/js' },
              { dest: '<%= vsdir %>/views', src: '**', expand: true, cwd: '<%= distdir %>/views' },
              { dest: '<%= vsdir %>/preview', src: '**', expand: true, cwd: '<%= distdir %>/preview' }
          ]
      },
      vsLibs: {
          files: [
              { dest: '<%= vsdir %>/lib', src: '**', expand: true, cwd: '<%= distdir %>/lib' }
          ]
      },
      packages: {
        files: [{ dest: '<%= vsdir %>/../App_Plugins', src : '**', expand: true, cwd: 'src/packages/' }]
      }
    },

    karma: {
      unit: { configFile: 'test/config/karma.conf.js', keepalive: true },
      e2e: { configFile: 'test/config/e2e.js', keepalive: true },
      watch: { configFile: 'test/config/unit.js', singleRun:false, autoWatch: true, keepalive: true }
    },

    concat:{
        index: {
          src: ['src/index.html'],
          dest: '<%= distdir %>/index.html',
          options: {
            process: true
          }
        },
        install: {
          src: ['src/installer/installer.html'],
          dest: '<%= distdir %>/installer.html',
          options: {
            process: true
          }
        },

        installJs: {
          src: ['src/installer/**/*.js'],
          dest: '<%= distdir %>/js/umbraco.installer.js',
          options: {
              banner: "<%= banner %>\n(function() { \n\n angular.module('umbraco.install', []); \n",
              footer: "\n\n})();"
          }
        },
        tuningJs: {
            src: ['src/tuning/tuning.global.js', 'src/tuning/tuning.controller.js', 'src/tuning/lib/slider.directive.js', 'src/tuning/lib/spectrum.directive.js'],
            dest: '<%= distdir %>/js/tuning.panel.js'
        },
        controllers: {
          src:['src/controllers/**/*.controller.js','src/views/**/*.controller.js'],
          dest: '<%= distdir %>/js/umbraco.controllers.js',
          options: {
              banner: "<%= banner %>\n(function() { \n\n",
              footer: "\n\n})();"
          }
        },
        services: {
          src:['src/common/services/*.js'],
          dest: '<%= distdir %>/js/umbraco.services.js',
          options: {
              banner: "<%= banner %>\n(function() { \n\n",
              footer: "\n\n})();"
          }
        },
        security: {
          src:['src/common/security/*.js'],
          dest: '<%= distdir %>/js/umbraco.security.js',
          options: {
              banner: "<%= banner %>\n(function() { \n\n",
              footer: "\n\n})();"
          }
        },
        resources: {
          src:['src/common/resources/*.js'],
          dest: '<%= distdir %>/js/umbraco.resources.js',
          options: {
              banner: "<%= banner %>\n(function() { \n\n",
              footer: "\n\n})();"
          }
        },
        testing: {
          src:['src/common/mocks/*/*.js'],
          dest: '<%= distdir %>/js/umbraco.testing.js',
          options: {
              banner: "<%= banner %>\n(function() { \n\n",
              footer: "\n\n})();"
          }
        },
        directives: {
          src:['src/common/directives/**/*.js'],
          dest: '<%= distdir %>/js/umbraco.directives.js',
          options: {
              banner: "<%= banner %>\n(function() { \n\n",
              footer: "\n\n})();"
          }
        },
        filters: {
          src:['src/common/filters/*.js'],
          dest: '<%= distdir %>/js/umbraco.filters.js',
          options: {
              banner: "<%= banner %>\n(function() { \n\n",
              footer: "\n\n})();"
          }
        }
    },

    uglify: {
      options: {
        mangle: true
      },
      combine: {
        files: {
          '<%= distdir %>/js/umbraco.min.js': ['<%= distdir %>/js/umbraco.*.js']
        }
      }
    },

    recess: {
      build: {
        files: {
          '<%= distdir %>/assets/css/<%= pkg.name %>.css':
          ['<%= src.less %>'] },
        options: {
          compile: true
        }
      },
      installer: {
        files: {
          '<%= distdir %>/assets/css/installer.css':
          ['src/less/installer.less'] },
        options: {
          compile: true
        }
      },
      tuning: {
          files: {
              '<%= distdir %>/assets/css/tuning.panelStyles.css':
              ['src/less/tuning.panelStyles.less', 'src/less/helveticons.less']
          },
          options: {
              compile: true
          }
      },
      min: {
        files: {
          '<%= distdir %>/assets/css/<%= pkg.name %>.css': ['<%= src.less %>']
        },
        options: {
          compile: true,
          compress: true
        }
      }
    },

    watch:{
      css: {
          files: '**/*.less',
          tasks: ['watch-less', 'timestamp'],
          options: {
            livereload: true,
          },
      },
      js: {
          files: ['src/**/*.js', 'src/*.js'],
          tasks: ['watch-js', 'timestamp'],
      },
      test: {
          files: ['test/**/*.js'],
          tasks: ['watch-test', 'timestamp'],
      },
      installer: {
          files: ['src/installer/**/*.*'],
          tasks: ['watch-installer', 'timestamp'],
      },
      tuning: {
          files: ['src/tuning/**/*.*'],
          tasks: ['watch-tuning', 'timestamp'],
      },
      html: {
        files: ['src/views/**/*.html', 'src/*.html'],
        tasks:['watch-html','timestamp']
      },

      packages: {
          files: 'src/packages/**/*.*',
          tasks: ['watch-packages', 'timestamp'],
      }
    },

    ngdocs: {
      options: {
        dest: 'docs/api',
        startPage: '/api',
        title: "Umbraco 7",
        html5Mode: false,
      },
      api: {
        src: ['src/common/**/*.js', 'docs/src/api/**/*.ngdoc'],
        title: 'API Documentation'
      },
      tutorials: {
        src: ['docs/src/tutorials/**/*.ngdoc'],
        title: 'Tutorials'
      }
    },

    jshint:{
      dev:{
         files: {
            src: ['<%= src.common %>', '<%= src.specs %>', '<%= src.scenarios %>', '<%= src.samples %>']
         },
         options:{
           curly:true,
           eqeqeq:true,
           immed:true,
           latedef:true,
           newcap:true,
           noarg:true,
           sub:true,
           boss: true,
             //NOTE: This is required so it doesn't barf on reserved words like delete when doing $http.delete
           es5: true,
           eqnull: true,
             //NOTE: we need to use eval sometimes so ignore it
           evil: true,
             //NOTE: we need to check for strings such as "javascript:" so don't throw errors regarding those
           scripturl: true,
             //NOTE: we ignore tabs vs spaces because enforcing that causes lots of errors depending on the text editor being used
           smarttabs: true,
           globals:{}
         }
      },
      build:{
         files: {
          src: ['<%= src.prod %>']
          },
          options:{
           curly:true,
           eqeqeq:true,
           immed:true,
           latedef:true,
           newcap:true,
           noarg:true,
           sub:true,
           boss: true,
            //NOTE: This is required so it doesn't barf on reserved words like delete when doing $http.delete
           es5: true,
           eqnull: true,
             //NOTE: we need to use eval sometimes so ignore it
           evil: true,
            //NOTE: we need to check for strings such as "javascript:" so don't throw errors regarding those
           scripturl: true,
            //NOTE: we ignore tabs vs spaces because enforcing that causes lots of errors depending on the text editor being used
           smarttabs: true,
           globalstrict:true,
           globals:{$:false, jQuery:false,define:false,require:false,window:false}
         }
      }
    }
  });

  grunt.loadNpmTasks('grunt-contrib-concat');
  grunt.loadNpmTasks('grunt-contrib-jshint');
  grunt.loadNpmTasks('grunt-contrib-clean');
  grunt.loadNpmTasks('grunt-contrib-copy');
  grunt.loadNpmTasks('grunt-contrib-uglify');
  grunt.loadNpmTasks('grunt-contrib-watch');
  grunt.loadNpmTasks('grunt-recess');

  grunt.loadNpmTasks('grunt-karma');

  grunt.loadNpmTasks('grunt-open');
  grunt.loadNpmTasks('grunt-contrib-connect');

  grunt.loadNpmTasks('grunt-ngdocs');

};
<|endoftext|>


<commit_before>'use strict';

const logger       = require('../logger');
const tls_socket   = require('../tls_socket');
const config       = require('haraka-config');
const hkredis      = require('haraka-plugin-redis');

const inheritable_opts = [
    'key', 'cert', 'ciphers', 'dhparam',
    'requestCert', 'honorCipherOrder', 'rejectUnauthorized'
];

class OutboundTLS {
    constructor () {
        this.config = config;
        this.name = "OutboundTLS";
        logger.add_log_methods(this);
    }

    test_config (tls_config, our_config) {
        tls_socket.config = tls_config;
        this.config = our_config;
    }

    load_config () {
        const tls_cfg = tls_socket.load_tls_ini({role: 'client'});
        const cfg = JSON.parse(JSON.stringify(tls_cfg.outbound || {}));
        cfg.redis = tls_cfg.redis; // Don't clone - contains methods

        for (const opt of inheritable_opts) {
            if (cfg[opt] === undefined) {
                // not declared in tls.ini[section]
                if (tls_cfg.main[opt] !== undefined) {
                    // use value from [main] section
                    cfg[opt] = tls_cfg.main[opt];
                }
            }
        }

        if (cfg.key) {
            if (Array.isArray(cfg.key)) {
                cfg.key = cfg.key[0];
            }
            cfg.key = this.config.get(cfg.key, 'binary');
        }

        if (cfg.dhparam) {
            cfg.dhparam = this.config.get(cfg.dhparam, 'binary');
        }

        if (cfg.cert) {
            if (Array.isArray(cfg.cert)) {
                cfg.cert = cfg.cert[0];
            }
            cfg.cert = this.config.get(cfg.cert, 'binary');
        }

        if (!cfg.no_tls_hosts) cfg.no_tls_hosts = [];

        this.cfg = cfg;
    }

    init (cb) {
        this.load_config();
        // changing this var in-flight won't work
        if (this.cfg.redis && !this.cfg.redis.disable_for_failed_hosts) return cb();
        logger.logdebug(this, 'Will disable outbound TLS for failing TLS hosts');
        Object.assign(this, hkredis);
        this.merge_redis_ini();
        this.init_redis_plugin(cb);
    }

    get_tls_options (mx) {
        return Object.assign(this.cfg, {servername: mx.exchange});
    }

    // Check for if host is prohibited from TLS negotiation
    check_tls_nogo (host, cb_ok, cb_nogo) {
        const plugin = this;
        if (!plugin.cfg.redis.disable_for_failed_hosts) return cb_ok();

        const dbkey = `no_tls|${host}`;
        plugin.db.get(dbkey, (err, dbr) => {
            if (err) {
                logger.logdebug(plugin, `Redis returned error: ${err}`);
                return cb_ok();
            }

            return dbr ? cb_nogo(dbr) : cb_ok();
        });
    }

    mark_tls_nogo (host, cb) {
        const plugin = this;
        const dbkey = `no_tls|${host}`;
        const expiry = plugin.cfg.redis.disable_expiry || 604800;

        if (!plugin.cfg.redis.disable_for_failed_hosts) return cb();

        logger.lognotice(plugin, `TLS connection failed. Marking ${host} as non-TLS for ${expiry} seconds`);

        plugin.db.setex(dbkey, expiry, new Date(), (err, dbr) => {
            if (err) logger.logerror(plugin, `Redis returned error: ${err}`);
            cb();
        });
    }
}

// this is a singleton
module.exports = new OutboundTLS();
<commit_msg>ob/tls: use obtls (vs plugin) for "this" name (#2524)<commit_after>'use strict';

const logger       = require('../logger');
const tls_socket   = require('../tls_socket');
const config       = require('haraka-config');
const hkredis      = require('haraka-plugin-redis');

const inheritable_opts = [
    'key', 'cert', 'ciphers', 'dhparam',
    'requestCert', 'honorCipherOrder', 'rejectUnauthorized'
];

class OutboundTLS {
    constructor () {
        this.config = config;
        this.name = 'OutboundTLS';
        logger.add_log_methods(this);
    }

    test_config (tls_config, our_config) {
        tls_socket.config = tls_config;
        this.config = our_config;
    }

    load_config () {
        const tls_cfg = tls_socket.load_tls_ini({role: 'client'});
        const cfg = JSON.parse(JSON.stringify(tls_cfg.outbound || {}));
        cfg.redis = tls_cfg.redis; // Don't clone - contains methods

        for (const opt of inheritable_opts) {
            if (cfg[opt] !== undefined) continue;          // option set in [outbound]
            if (tls_cfg.main[opt] === undefined) continue; // opt unset in tls.ini[main]
            cfg[opt] = tls_cfg.main[opt];                  // use value from [main] section
        }

        if (cfg.key) {
            if (Array.isArray(cfg.key)) {
                cfg.key = cfg.key[0];
            }
            cfg.key = this.config.get(cfg.key, 'binary');
        }

        if (cfg.dhparam) {
            cfg.dhparam = this.config.get(cfg.dhparam, 'binary');
        }

        if (cfg.cert) {
            if (Array.isArray(cfg.cert)) {
                cfg.cert = cfg.cert[0];
            }
            cfg.cert = this.config.get(cfg.cert, 'binary');
        }

        if (!cfg.no_tls_hosts) cfg.no_tls_hosts = [];

        this.cfg = cfg;
    }

    init (cb) {
        this.load_config();
        // changing this var in-flight won't work
        if (this.cfg.redis && !this.cfg.redis.disable_for_failed_hosts) return cb();
        logger.logdebug(this, 'Will disable outbound TLS for failing TLS hosts');
        Object.assign(this, hkredis);
        this.merge_redis_ini();
        this.init_redis_plugin(cb);
    }

    get_tls_options (mx) {
        return Object.assign(this.cfg, {servername: mx.exchange});
    }

    // Check for if host is prohibited from TLS negotiation
    check_tls_nogo (host, cb_ok, cb_nogo) {
        const obtls = this;
        if (!obtls.cfg.redis.disable_for_failed_hosts) return cb_ok();

        const dbkey = `no_tls|${host}`;
        obtls.db.get(dbkey, (err, dbr) => {
            if (err) {
                obtls.logdebug(obtls, `Redis returned error: ${err}`);
                return cb_ok();
            }

            return dbr ? cb_nogo(dbr) : cb_ok();
        });
    }

    mark_tls_nogo (host, cb) {
        const obtls = this;
        const dbkey = `no_tls|${host}`;
        const expiry = obtls.cfg.redis.disable_expiry || 604800;

        if (!obtls.cfg.redis.disable_for_failed_hosts) return cb();

        logger.lognotice(obtls, `TLS connection failed. Marking ${host} as non-TLS for ${expiry} seconds`);

        obtls.db.setex(dbkey, expiry, new Date(), (err, dbr) => {
            if (err) logger.logerror(obtls, `Redis returned error: ${err}`);
            cb();
        });
    }
}

// this is a singleton
module.exports = new OutboundTLS();
<|endoftext|>


<commit_before>define(['require-css/css-builder', './lessc-server', 'require'], function(css, lessc, req) {
  var less = {};

  var baseParts = req.toUrl('base_url').split('/');
  baseParts.pop();
  var baseUrl = baseParts.join('/');

  // include the base url as a path
  var parser = new lessc.Parser({
    paths: [baseUrl + '/']
  });

  var parseLess = function(less) {
    var CSS;
    parser.parse(less, function(err, tree) {
      if (err)
        throw err;
      CSS = tree.toCSS();
    });
    return CSS;
  }

  less.normalize = function(name, normalize) {
    if (name.substr(name.length - 5, 5) == '.less')
      name = name.substr(0, name.length - 5);
    return normalize(name);
  }

  less.load = function(name, req, load, config) {
    css.load(name, req, load, config, parseLess);
  }

  less.write = function(pluginName, moduleName, write) {
    css.write(pluginName, moduleName, write, parseLess);
  }

  less.onLayerEnd = function(write, data) {
    css.onLayerEnd(write, data, true);
  }

  return less;
});
<commit_msg>css path adjustment<commit_after>define(['css/css-builder', './lessc-server', 'require'], function(css, lessc, req) {
  var less = {};

  var baseParts = req.toUrl('base_url').split('/');
  baseParts.pop();
  var baseUrl = baseParts.join('/');

  // include the base url as a path
  var parser = new lessc.Parser({
    paths: [baseUrl + '/']
  });

  var parseLess = function(less) {
    var CSS;
    parser.parse(less, function(err, tree) {
      if (err)
        throw err;
      CSS = tree.toCSS();
    });
    return CSS;
  }

  less.normalize = function(name, normalize) {
    if (name.substr(name.length - 5, 5) == '.less')
      name = name.substr(0, name.length - 5);
    return normalize(name);
  }

  less.load = function(name, req, load, config) {
    css.load(name, req, load, config, parseLess);
  }

  less.write = function(pluginName, moduleName, write) {
    css.write(pluginName, moduleName, write, parseLess);
  }

  less.onLayerEnd = function(write, data) {
    css.onLayerEnd(write, data, true);
  }

  return less;
});
<|endoftext|>


<commit_before>Zepto(function($) {
  // a jQuery.getScript() equivalent to asyncronously load javascript files
  // credits to http://stackoverflow.com/a/8812950/1597388
  var getScript = function(src, func) {
    var script = document.createElement('script');
    script.async = 'async';
    script.src = src;
    if (func) {
      script.onload = func;
    }
    document.getElementsByTagName('head')[0].appendChild( script );
  };

  // load prettify asyncronously to speedup page rendering
  getScript('//cdnjs.cloudflare.com/ajax/libs/prettify/r224/prettify.js', function() {
    prettyPrint();
  });

  var $leftPanel      = $('.left-panel');
  var $frameContainer = $('.frames-container');
  var $container      = $('.details-container');
  var $activeLine     = $frameContainer.find('.frame.active');
  var $activeFrame    = $container.find('.frame-code.active');
  var $ajaxEditors    = $('.editor-link[data-ajax]');
  var $header         = $('header');

  $header.on('mouseenter', function () {
    if ($header.find('.exception').height() >= 145) {
      $header.addClass('header-expand');
    }
  });
  $header.on('mouseleave', function () {
    $header.removeClass('header-expand');
  });

  var highlightCurrentLine = function() {
    // Highlight the active and neighboring lines for this frame:
    var activeLineNumber = +($activeLine.find('.frame-line').text());
    var $lines           = $activeFrame.find('.linenums li');
    var firstLine        = +($lines.first().val());

    $($lines[activeLineNumber - firstLine - 1]).addClass('current');
    $($lines[activeLineNumber - firstLine]).addClass('current active');
    $($lines[activeLineNumber - firstLine + 1]).addClass('current');
  }

  // Highlight the active for the first frame:
  highlightCurrentLine();

  $frameContainer.on('click', '.frame', function() {
    var $this  = $(this);
    var id     = /frame\-line\-([\d]*)/.exec($this.attr('id'))[1];
    var $codeFrame = $('#frame-code-' + id);

    if ($codeFrame) {
      $activeLine.removeClass('active');
      $activeFrame.removeClass('active');

      $this.addClass('active');
      $codeFrame.addClass('active');

      $activeLine  = $this;
      $activeFrame = $codeFrame;

      highlightCurrentLine();

      $container.scrollTop(0);
    }
  });

  var clipboard = new Clipboard('.clipboard');
  var showTooltip = function(elem, msg) {
    elem.setAttribute('class', 'clipboard tooltipped tooltipped-s');
    elem.setAttribute('aria-label', msg);
  };

  clipboard.on('success', function(e) {
      e.clearSelection();

      showTooltip(e.trigger, 'Copied!');
  });

  clipboard.on('error', function(e) {
      showTooltip(e.trigger, fallbackMessage(e.action));
  });

  var btn = document.querySelector('.clipboard');

  btn.addEventListener('mouseleave', function(e) {
    e.currentTarget.setAttribute('class', 'clipboard');
    e.currentTarget.removeAttribute('aria-label');
  });

  function fallbackMessage(action) {
    var actionMsg = '';
    var actionKey = (action === 'cut' ? 'X' : 'C');

    if (/Mac/i.test(navigator.userAgent)) {
        actionMsg = 'Press ⌘-' + actionKey + ' to ' + action;
    } else {
        actionMsg = 'Press Ctrl-' + actionKey + ' to ' + action;
    }

    return actionMsg;
  }

  function scrollIntoView($node, $parent) {
    var nodeOffset = $node.offset();
    var nodeTop = nodeOffset.top;
    var nodeBottom = nodeTop + nodeOffset.height;
    var parentScrollTop = $parent.scrollTop();
    var parentHeight = $parent.height();

    if (nodeTop < 0) {
      $parent.scrollTop(parentScrollTop + nodeTop);
    } else if (nodeBottom > parentHeight) {
      $parent.scrollTop(parentScrollTop + nodeBottom - parentHeight);
    }
  }

  $(document).on('keydown', function(e) {
	  if(e.ctrlKey) {
		  // CTRL+Arrow-UP/Arrow-Down support:
		  // 1) select the next/prev element
		  // 2) make sure the newly selected element is within the view-scope
		  // 3) focus the (right) container, so arrow-up/down (without ctrl) scroll the details
		  if (e.which === 38 /* arrow up */) {
			  $activeLine.prev('.frame').click();
			  scrollIntoView($activeLine, $leftPanel);
			  $container.focus();
			  e.preventDefault();
		  } else if (e.which === 40 /* arrow down */) {
			  $activeLine.next('.frame').click();
			  scrollIntoView($activeLine, $leftPanel);
			  $container.focus();
			  e.preventDefault();
		  }
	  }
  });

  // Avoid to quit the page with some protocol (e.g. IntelliJ Platform REST API)
  $ajaxEditors.on('click', function(e){
    e.preventDefault();
    $.get(this.href);
  });

  // Symfony VarDumper: Close the by default expanded objects
  $('.sf-dump-expanded')
    .removeClass('sf-dump-expanded')
    .addClass('sf-dump-compact');
  $('.sf-dump-toggle span').html('▶');
});
<commit_msg>Add `j` and `k` shortcuts<commit_after>Zepto(function($) {
  // a jQuery.getScript() equivalent to asyncronously load javascript files
  // credits to http://stackoverflow.com/a/8812950/1597388
  var getScript = function(src, func) {
    var script = document.createElement('script');
    script.async = 'async';
    script.src = src;
    if (func) {
      script.onload = func;
    }
    document.getElementsByTagName('head')[0].appendChild( script );
  };

  // load prettify asyncronously to speedup page rendering
  getScript('//cdnjs.cloudflare.com/ajax/libs/prettify/r224/prettify.js', function() {
    prettyPrint();
  });

  var $leftPanel      = $('.left-panel');
  var $frameContainer = $('.frames-container');
  var $container      = $('.details-container');
  var $activeLine     = $frameContainer.find('.frame.active');
  var $activeFrame    = $container.find('.frame-code.active');
  var $ajaxEditors    = $('.editor-link[data-ajax]');
  var $header         = $('header');

  $header.on('mouseenter', function () {
    if ($header.find('.exception').height() >= 145) {
      $header.addClass('header-expand');
    }
  });
  $header.on('mouseleave', function () {
    $header.removeClass('header-expand');
  });

  var highlightCurrentLine = function() {
    // Highlight the active and neighboring lines for this frame:
    var activeLineNumber = +($activeLine.find('.frame-line').text());
    var $lines           = $activeFrame.find('.linenums li');
    var firstLine        = +($lines.first().val());

    $($lines[activeLineNumber - firstLine - 1]).addClass('current');
    $($lines[activeLineNumber - firstLine]).addClass('current active');
    $($lines[activeLineNumber - firstLine + 1]).addClass('current');
  }

  // Highlight the active for the first frame:
  highlightCurrentLine();

  $frameContainer.on('click', '.frame', function() {
    var $this  = $(this);
    var id     = /frame\-line\-([\d]*)/.exec($this.attr('id'))[1];
    var $codeFrame = $('#frame-code-' + id);

    if ($codeFrame) {
      $activeLine.removeClass('active');
      $activeFrame.removeClass('active');

      $this.addClass('active');
      $codeFrame.addClass('active');

      $activeLine  = $this;
      $activeFrame = $codeFrame;

      highlightCurrentLine();

      $container.scrollTop(0);
    }
  });

  var clipboard = new Clipboard('.clipboard');
  var showTooltip = function(elem, msg) {
    elem.setAttribute('class', 'clipboard tooltipped tooltipped-s');
    elem.setAttribute('aria-label', msg);
  };

  clipboard.on('success', function(e) {
      e.clearSelection();

      showTooltip(e.trigger, 'Copied!');
  });

  clipboard.on('error', function(e) {
      showTooltip(e.trigger, fallbackMessage(e.action));
  });

  var btn = document.querySelector('.clipboard');

  btn.addEventListener('mouseleave', function(e) {
    e.currentTarget.setAttribute('class', 'clipboard');
    e.currentTarget.removeAttribute('aria-label');
  });

  function fallbackMessage(action) {
    var actionMsg = '';
    var actionKey = (action === 'cut' ? 'X' : 'C');

    if (/Mac/i.test(navigator.userAgent)) {
        actionMsg = 'Press ⌘-' + actionKey + ' to ' + action;
    } else {
        actionMsg = 'Press Ctrl-' + actionKey + ' to ' + action;
    }

    return actionMsg;
  }

  function scrollIntoView($node, $parent) {
    var nodeOffset = $node.offset();
    var nodeTop = nodeOffset.top;
    var nodeBottom = nodeTop + nodeOffset.height;
    var parentScrollTop = $parent.scrollTop();
    var parentHeight = $parent.height();

    if (nodeTop < 0) {
      $parent.scrollTop(parentScrollTop + nodeTop);
    } else if (nodeBottom > parentHeight) {
      $parent.scrollTop(parentScrollTop + nodeBottom - parentHeight);
    }
  }

  $(document).on('keydown', function(e) {
	  if(e.ctrlKey || e.which === 74  || e.which === 75) {
		  // CTRL+Arrow-UP/k and Arrow-Down/j support:
		  // 1) select the next/prev element
		  // 2) make sure the newly selected element is within the view-scope
		  // 3) focus the (right) container, so arrow-up/down (without ctrl) scroll the details
		  if (e.which === 38 /* arrow up */ || e.which === 75 /* k */) {
			  $activeLine.prev('.frame').click();
			  scrollIntoView($activeLine, $leftPanel);
			  $container.focus();
			  e.preventDefault();
		  } else if (e.which === 40 /* arrow down */ || e.which === 74 /* j */) {
			  $activeLine.next('.frame').click();
			  scrollIntoView($activeLine, $leftPanel);
			  $container.focus();
			  e.preventDefault();
		  }
	  }
  });

  // Avoid to quit the page with some protocol (e.g. IntelliJ Platform REST API)
  $ajaxEditors.on('click', function(e){
    e.preventDefault();
    $.get(this.href);
  });

  // Symfony VarDumper: Close the by default expanded objects
  $('.sf-dump-expanded')
    .removeClass('sf-dump-expanded')
    .addClass('sf-dump-compact');
  $('.sf-dump-toggle span').html('▶');
});
<|endoftext|>


<commit_before>var Accents = new Backbone.Marionette.Application();

// pluggible regions
Accents.addRegions({
    navbar: 'header',
    main: '#maincontent',
    footer: 'footer'
});

Accents.navigate = function(route, options){
  console.log("Navigate ");
  console.log(route);
  console.log(options);
  var options = options || {};
  Backbone.history.navigate(route, options);
};

Accents.getCurrentRoute = function(){
  return Backbone.history.fragment;
};

// wire up application
var onCompleteSync = function(){
  // console.log("Trigger list:term due to onCompleteSync call");
  Accents.trigger("list:term")
  console.log("sync called every 10 seconds timer");
  setTimeout(sync,10000);
};

Accents.addInitializer(function () {
  Accents.db = new PouchDB('accents');
  Accents.remoteDb = 'accents';
  //Accents.domainRemoteDb = 'localhost:5984';
  Accents.domainRemoteDb = 'diacritics.iriscouch.com';
  //Accents.domainRemoteDb = 'accents.couchappy.com'; // backup db

  Accents.db.changes({live: true, onChange: function(change){ /*console.log(change); */} });

  sync();

  var user = {};
  if(typeof(Storage)!=="undefined"){
    var userSession = sessionStorage.getItem( "session-user" );
    if(userSession){
      user = $.parseJSON(userSession);
    }
  }
  Accents.user = new Accents.Entities.Login(user);
});

Accents.on("sync", function(){
  console.log("triggering list:term");
  Accents.trigger("list:term")
});

var sync = function(){
  console.log("sync called");
  var opts = {continuous: true, complete: onCompleteSync, batch_size: 500};
  var urlConnection = "http://" + Accents.domainRemoteDb + "/" + Accents.remoteDb;
  PouchDB.replicate('accents', urlConnection, opts, function(err, data){ console.log("replicating local to remote");/*console.log(err); console.log(data); */});
  PouchDB.replicate(urlConnection, 'accents', opts, function(err, data){ console.log("replicating remote to local");/*console.log(err); console.log(data);*/ });
};

Accents.on("initialize:after", function(){
  console.log("initialize:after called");
  if(Backbone.history){
    Backbone.history.start();
    if( !Accents.user.isLoggedIn() ){
      Accents.trigger("login");
    }else if( Accents.getCurrentRoute() == "" ){
      Accents.trigger("list:term");
    }
  }
});
<commit_msg>removing the onCompleteSync since it didn't help the FireFox problem<commit_after>var Accents = new Backbone.Marionette.Application();

// pluggible regions
Accents.addRegions({
    navbar: 'header',
    main: '#maincontent',
    footer: 'footer'
});

Accents.navigate = function(route, options){
  console.log("Navigate ");
  console.log(route);
  console.log(options);
  var options = options || {};
  Backbone.history.navigate(route, options);
};

Accents.getCurrentRoute = function(){
  return Backbone.history.fragment;
};

// wire up application
var onCompleteSync = function(){
  // console.log("Trigger list:term due to onCompleteSync call");
  // Accents.trigger("list:term")
  // console.log("sync called every 10 seconds timer");
  // setTimeout(sync,10000);
};

Accents.addInitializer(function () {
  Accents.db = new PouchDB('accents');
  Accents.remoteDb = 'accents';
  //Accents.domainRemoteDb = 'localhost:5984';
  Accents.domainRemoteDb = 'diacritics.iriscouch.com';
  //Accents.domainRemoteDb = 'accents.couchappy.com'; // backup db

  Accents.db.changes({live: true, onChange: function(change){ /*console.log(change); */} });

  sync();

  var user = {};
  if(typeof(Storage)!=="undefined"){
    var userSession = sessionStorage.getItem( "session-user" );
    if(userSession){
      user = $.parseJSON(userSession);
    }
  }
  Accents.user = new Accents.Entities.Login(user);
});

Accents.on("sync", function(){
  console.log("triggering list:term");
  Accents.trigger("list:term")
});

var sync = function(){
  console.log("sync called");
  var opts = {continuous: true, complete: onCompleteSync, batch_size: 500};
  var urlConnection = "http://" + Accents.domainRemoteDb + "/" + Accents.remoteDb;
  PouchDB.replicate('accents', urlConnection, opts, function(err, data){ console.log("replicating local to remote");/*console.log(err); console.log(data); */});
  PouchDB.replicate(urlConnection, 'accents', opts, function(err, data){ console.log("replicating remote to local");/*console.log(err); console.log(data);*/ });
};

Accents.on("initialize:after", function(){
  console.log("initialize:after called");
  if(Backbone.history){
    Backbone.history.start();
    if( !Accents.user.isLoggedIn() ){
      Accents.trigger("login");
    }else if( Accents.getCurrentRoute() == "" ){
      Accents.trigger("list:term");
    }
  }
});
<|endoftext|>


<commit_before>(function (oScope, enyo) {

	var aQueue          = [],
		bFlushScheduled = false;

	var fFlush = function () {
			while (aQueue.length) {
				fRun.apply(oScope, aQueue.shift());
			}
			bFlushScheduled = false;
		},
		fRun = function (f, oContext) {
			f.call(oContext || enyo.global);
		};

	/*********** ENYO PUBLIC **********/

	enyo.rendered = function (f, oContext) {
		aQueue.push([f, oContext]);
		if (!bFlushScheduled) {
			enyo.asyncMethod(oScope, fFlush);
			bFlushScheduled = true;
		}
	};

	//* Adds control to enyo.roots; called from write(), renderInto(), ViewController.renderInto()
	enyo.addToRoots = function(oRoot) {
		if (!enyo.exists(enyo.roots)) {
			enyo.roots = [ oRoot ];
		} else {
			enyo.roots.push(oRoot);
		}

		var fRendered = oRoot.rendered;
		oRoot.rendered = function() {
			fRendered.apply(oRoot, []);
			fFlush();
		};
		oRoot._isRoot = true;
	};

})(window, enyo);
<commit_msg>Making enyo.rendered fire callbacks on every root rendered<commit_after>(function (enyo) {

	var aCallbacks = [];

	var fInvoke = function (oRoot) {
			var nLength = aCallbacks.length,
				a,
				n;

			for (n=0; n<nLength; n++) {
				a = aCallbacks[n];
				a[0].apply(a[1] || enyo.global, [oRoot]);
			}
		};

	/*********** ENYO PUBLIC **********/

	enyo.rendered = function (f, oContext) {
		aCallbacks.push([f, oContext]);
	};

	//* Adds control to enyo.roots; renderInto()
	enyo.addToRoots = function(oRoot) {
		if (!enyo.exists(enyo.roots)) {
			enyo.roots = [ oRoot ];
		} else {
			enyo.roots.push(oRoot);
		}

		var fRendered = oRoot.rendered;
		oRoot.rendered = function() {
			fRendered.apply(oRoot, []);
			fInvoke(oRoot);
		};
		oRoot._isRoot = true;
	};

})(enyo);
<|endoftext|>


<commit_before>define(['./lessc'], function(less) {

    var readFile = (function() {
    	if (less.mode === 'node') {
    		var fs = require.nodeRequire('fs');
    		var path = require.nodeRequire('path');
    		return function(pathname) {
    			return fs.readFileSync(pathname, 'utf-8');
    		};
    	} else if (less.mode === 'rhino') {
    		return function(pathname) {
    			return readFile(pathname, 'UTF-8');
    		};
    	}
    }());

    var checkPath = (function() {
    	if (less.mode === 'node') {
    		var fs = require.nodeRequire('fs');
    		var path = require.nodeRequire('path');
    		return function(pathname, file) {
    			try {
    				pathname = path.join(pathname, file);
    				fs.statSync(pathname);
    				return pathname;
    			} catch (e) {
    				return null;
    			}
    		};
    	} else if (less.mode === 'rhino') {
    		return function(pathname, file) {
    			var f = new java.io.File(pathname, file);
    			if (f.isFile()) {
    				return f.getPath();
    			} else {
    				return null;
    			}
    		};
    	}
    }());

    less.Parser.importer = function (file, paths, callback, env) {
        var pathname, data;

        // TODO: Undo this at some point,
        // or use different approach.
        var paths = [].concat(paths);
        paths.push('.');

        for (var i = 0; i < paths.length; i++) {
        	pathname = checkPath(paths[i], file);
        	if (pathname != null) {
        		break;
        	}
        }

        paths = paths.slice(0, paths.length - 1);

        if (!pathname) {
            if (typeof(env.errback) === "function") {
                env.errback(file, paths, callback);
            } else {
                callback({ type: 'File', message: "'" + file + "' wasn't found.\n" });
            }
            return;
        }

        function parseFile(e, data) {
            if (e) return callback(e);
                env.contents = env.contents || {};
                env.contents[pathname] = data;      // Updating top importing parser content cache.
            new(less.Parser)({
                    paths: [path.dirname(pathname)].concat(paths),
                    filename: pathname,
                    contents: env.contents,
                    files: env.files,
                    syncImport: env.syncImport,
                    dumpLineNumbers: env.dumpLineNumbers
            }).parse(data, function (e, root) {
                    callback(e, root, pathname);
            });
        };

        try {
        	readFile(pathname);
            parseFile(null, data);
        } catch (e) {
            parseFile(e);
        }
    }
    return less;
});<commit_msg>throw when running in an unsupported environment<commit_after>define(['./lessc'], function(less) {

	if (['node', 'rhino'].indexOf(less.mode) == -1) {
		throw new Error('Environment not supported by require-less builder: ' + less.mode);
	}

    var readFile = (function() {
    	if (less.mode === 'node') {
    		var fs = require.nodeRequire('fs');
    		var path = require.nodeRequire('path');
    		return function(pathname) {
    			return fs.readFileSync(pathname, 'utf-8');
    		};
    	} else if (less.mode === 'rhino') {
    		return function(pathname) {
    			return readFile(pathname, 'UTF-8');
    		};
    	}
    }());

    var checkPath = (function() {
    	if (less.mode === 'node') {
    		var fs = require.nodeRequire('fs');
    		var path = require.nodeRequire('path');
    		return function(pathname, file) {
    			try {
    				pathname = path.join(pathname, file);
    				fs.statSync(pathname);
    				return pathname;
    			} catch (e) {
    				return null;
    			}
    		};
    	} else if (less.mode === 'rhino') {
    		return function(pathname, file) {
    			var f = new java.io.File(pathname, file);
    			if (f.isFile()) {
    				return f.getPath();
    			} else {
    				return null;
    			}
    		};
    	}
    }());

    less.Parser.importer = function (file, paths, callback, env) {
        var pathname, data;

        // TODO: Undo this at some point,
        // or use different approach.
        var paths = [].concat(paths);
        paths.push('.');

        for (var i = 0; i < paths.length; i++) {
        	pathname = checkPath(paths[i], file);
        	if (pathname != null) {
        		break;
        	}
        }

        paths = paths.slice(0, paths.length - 1);

        if (!pathname) {
            if (typeof(env.errback) === "function") {
                env.errback(file, paths, callback);
            } else {
                callback({ type: 'File', message: "'" + file + "' wasn't found.\n" });
            }
            return;
        }

        function parseFile(e, data) {
            if (e) return callback(e);
                env.contents = env.contents || {};
                env.contents[pathname] = data;      // Updating top importing parser content cache.
            new(less.Parser)({
                    paths: [path.dirname(pathname)].concat(paths),
                    filename: pathname,
                    contents: env.contents,
                    files: env.files,
                    syncImport: env.syncImport,
                    dumpLineNumbers: env.dumpLineNumbers
            }).parse(data, function (e, root) {
                    callback(e, root, pathname);
            });
        };

        try {
        	readFile(pathname);
            parseFile(null, data);
        } catch (e) {
            parseFile(e);
        }
    }
    return less;
});<|endoftext|>


<commit_before>//* @protected
(function() {
	enyo.dom.calcCanAccelerate = function() {
		/* Android 2 is a liar: it does NOT support 3D transforms, even though Perspective is the best check */
		if (enyo.platform.android <= 2) {
			return false;
		}
		var p$ = ["perspective", "WebkitPerspective", "MozPerspective", "msPerspective", "OPerspective"];
		for (var i=0, p; (p=p$[i]); i++) {
			if (typeof document.body.style[p] != "undefined") {
				return true;
			}
		}
		return false;
	};
	var cssTransformProps = ["transform", "-webkit-transform", "-moz-transform", "-ms-transform", "-o-transform"];
	var styleTransformProps = ["transform", "webkitTransform", "MozTransform", "msTransform", "OTransform"];
	enyo.dom.getCssTransformProp = function() {
		if (this._cssTransformProp) {
			return this._cssTransformProp;
		}
		var i = enyo.indexOf(this.getStyleTransformProp(), styleTransformProps);
		this._cssTransformProp = cssTransformProps[i];
		return this._cssTransformProp;
	};
	enyo.dom.getStyleTransformProp = function() {
		if (this._styleTransformProp || !document.body) {
			return this._styleTransformProp;
		}
		for (var i = 0, p; (p = styleTransformProps[i]); i++) {
			if (typeof document.body.style[p] != "undefined") {
				this._styleTransformProp = p;
				return this._styleTransformProp;
			}
		}
	};
	enyo.dom.domTransformsToCss = function(inTransforms) {
		var n, v, text = '';
		for (n in inTransforms) {
			v = inTransforms[n];
			if ((v !== null) && (v !== undefined) && (v !== "")) {
				text +=  n + '(' + v + ') ';
			}
		}
		return text;
	};
	enyo.dom.transformsToDom = function(inControl) {
		var css = this.domTransformsToCss(inControl.domTransforms),
			styleProp = this.getStyleTransformProp();

		if (styleProp) inControl.applyStyle(styleProp, css);
	};
	//* @public
	/**
		Returns true if the platform supports CSS3 Transforms
	*/
	enyo.dom.canTransform = function() {
		return Boolean(this.getStyleTransformProp());
	};
	/**
		Returns true if platform supports CSS3 3D Transforms.

		Typically used like this:

			if (enyo.dom.canAccelerate()) {
				enyo.dom.transformValue(this.$.slidingThing, "translate3d", x + "," + y + "," + "0")
			} else {
				enyo.dom.transformValue(this.$.slidingThing, "translate", x + "," + y);
			}

	*/
	enyo.dom.canAccelerate = function() {
		return this.accelerando !== undefined ? this.accelerando: document.body && (this.accelerando = this.calcCanAccelerate());
	};
	/**
		Applies a series of transforms to _inControl_, using the platform's prefixed transform property.

		**Note:** Transforms are not commutative, so order is important

		Transform values are updated by successive calls:

			enyo.dom.transform(control, {translate: "30px, 40px", scale: 2, rotate: "20deg"});
			enyo.dom.transform(control, {scale: 3, skewX: "-30deg"});

		is equivalent to:

			enyo.dom.transform(control, {translate: "30px, 40px", scale: 3, rotate: "20deg", skewX: "-30deg"});

		When applying these transforms in webkit browser, this is equivalent to:

			control.applyStyle("-webkit-transform", "translate(30px, 40px) scale(3) rotate(20deg) skewX(-30deg)");

		And in firefox, this is equivalent to:

			control.applyStyle("-moz-transform", "translate(30px, 40px) scale(3) rotate(20deg) skewX(-30deg)");

	*/
	enyo.dom.transform = function(inControl, inTransforms) {
		var d = inControl.domTransforms = inControl.domTransforms || {};
		enyo.mixin(d, inTransforms);
		this.transformsToDom(inControl);
	};

	/**
		Apply a single transform to _inControl_.

		Example:

			tap: function(inSender, inEvent) {
				var c = inEvent.originator;
				var r = c.rotation || 0;
				r = (r + 45) % 360;
				c.rotation = r;
				enyo.dom.transformValue(c, "rotate", r);
			}

		This will rotate the tapped control by 45 degrees clockwise.
	*/
	enyo.dom.transformValue = function(inControl, inTransform, inValue) {
		var d = inControl.domTransforms = inControl.domTransforms || {};
		d[inTransform] = inValue;
		this.transformsToDom(inControl);
	};
	//* @protected
	/**
		Applies a transform that should trigger GPU compositing for _inControl_
	*/
	enyo.dom.accelerate = function(inControl, inValue) {
		var v = inValue == "auto" ? this.canAccelerate() : inValue;
		this.transformValue(inControl, "translateZ", v ? 0 : null);
	};
})();
<commit_msg>BHV-8486: Set the correct style property when control does not yet have DOM node.<commit_after>//* @protected
(function() {
	enyo.dom.calcCanAccelerate = function() {
		/* Android 2 is a liar: it does NOT support 3D transforms, even though Perspective is the best check */
		if (enyo.platform.android <= 2) {
			return false;
		}
		var p$ = ["perspective", "WebkitPerspective", "MozPerspective", "msPerspective", "OPerspective"];
		for (var i=0, p; (p=p$[i]); i++) {
			if (typeof document.body.style[p] != "undefined") {
				return true;
			}
		}
		return false;
	};
	var cssTransformProps = ["transform", "-webkit-transform", "-moz-transform", "-ms-transform", "-o-transform"];
	var styleTransformProps = ["transform", "webkitTransform", "MozTransform", "msTransform", "OTransform"];
	enyo.dom.getCssTransformProp = function() {
		if (this._cssTransformProp) {
			return this._cssTransformProp;
		}
		var i = enyo.indexOf(this.getStyleTransformProp(), styleTransformProps);
		this._cssTransformProp = cssTransformProps[i];
		return this._cssTransformProp;
	};
	enyo.dom.getStyleTransformProp = function() {
		if (this._styleTransformProp || !document.body) {
			return this._styleTransformProp;
		}
		for (var i = 0, p; (p = styleTransformProps[i]); i++) {
			if (typeof document.body.style[p] != "undefined") {
				this._styleTransformProp = p;
				return this._styleTransformProp;
			}
		}
	};
	enyo.dom.domTransformsToCss = function(inTransforms) {
		var n, v, text = '';
		for (n in inTransforms) {
			v = inTransforms[n];
			if ((v !== null) && (v !== undefined) && (v !== "")) {
				text +=  n + '(' + v + ') ';
			}
		}
		return text;
	};
	enyo.dom.transformsToDom = function(inControl) {
		var css = this.domTransformsToCss(inControl.domTransforms),
			styleProp;

		if (inControl.hasNode()) {
			styleProp = this.getStyleTransformProp();
		} else {
			styleProp = this.getCssTransformProp();
		}

		if (styleProp) inControl.applyStyle(styleProp, css);
	};
	//* @public
	/**
		Returns true if the platform supports CSS3 Transforms
	*/
	enyo.dom.canTransform = function() {
		return Boolean(this.getStyleTransformProp());
	};
	/**
		Returns true if platform supports CSS3 3D Transforms.

		Typically used like this:

			if (enyo.dom.canAccelerate()) {
				enyo.dom.transformValue(this.$.slidingThing, "translate3d", x + "," + y + "," + "0")
			} else {
				enyo.dom.transformValue(this.$.slidingThing, "translate", x + "," + y);
			}

	*/
	enyo.dom.canAccelerate = function() {
		return this.accelerando !== undefined ? this.accelerando: document.body && (this.accelerando = this.calcCanAccelerate());
	};
	/**
		Applies a series of transforms to _inControl_, using the platform's prefixed transform property.

		**Note:** Transforms are not commutative, so order is important

		Transform values are updated by successive calls:

			enyo.dom.transform(control, {translate: "30px, 40px", scale: 2, rotate: "20deg"});
			enyo.dom.transform(control, {scale: 3, skewX: "-30deg"});

		is equivalent to:

			enyo.dom.transform(control, {translate: "30px, 40px", scale: 3, rotate: "20deg", skewX: "-30deg"});

		When applying these transforms in webkit browser, this is equivalent to:

			control.applyStyle("-webkit-transform", "translate(30px, 40px) scale(3) rotate(20deg) skewX(-30deg)");

		And in firefox, this is equivalent to:

			control.applyStyle("-moz-transform", "translate(30px, 40px) scale(3) rotate(20deg) skewX(-30deg)");

	*/
	enyo.dom.transform = function(inControl, inTransforms) {
		var d = inControl.domTransforms = inControl.domTransforms || {};
		enyo.mixin(d, inTransforms);
		this.transformsToDom(inControl);
	};

	/**
		Apply a single transform to _inControl_.

		Example:

			tap: function(inSender, inEvent) {
				var c = inEvent.originator;
				var r = c.rotation || 0;
				r = (r + 45) % 360;
				c.rotation = r;
				enyo.dom.transformValue(c, "rotate", r);
			}

		This will rotate the tapped control by 45 degrees clockwise.
	*/
	enyo.dom.transformValue = function(inControl, inTransform, inValue) {
		var d = inControl.domTransforms = inControl.domTransforms || {};
		d[inTransform] = inValue;
		this.transformsToDom(inControl);
	};
	//* @protected
	/**
		Applies a transform that should trigger GPU compositing for _inControl_
	*/
	enyo.dom.accelerate = function(inControl, inValue) {
		var v = inValue == "auto" ? this.canAccelerate() : inValue;
		this.transformValue(inControl, "translateZ", v ? 0 : null);
	};
})();
<|endoftext|>