<commit_before>var fs = require('fs');
var _ = require('lodash');

// Split array to smaller arrays containing n elements at max
function groupToElements(array, n) {
  var lists = _.groupBy(array, function(element, index){
    return Math.floor(index / n);
  });

  return _.toArray(lists);
}

function endsWith(str, suffix) {
  return str.indexOf(suffix, str.length - suffix.length) !== -1;
}

// Setup karma configuration dynamically to run browsers sequentially
// https://github.com/karma-runner/karma-sauce-launcher/issues/8
var MAXIMUM_CONCURRENT_SAUCE = 3;
var sauceBrowsers = require('./saucelabs-browsers');
var browserGroups = groupToElements(Object.keys(sauceBrowsers), MAXIMUM_CONCURRENT_SAUCE);

var karmaConfig = {
  options: {
    configFile: 'karma.conf.js'
  }
};

_.each(browserGroups, function(group, index) {
  karmaConfig['sauce' + index] = {
    browsers: group
  }
});

module.exports = function(grunt) {
  grunt.initConfig({
    pkg: grunt.file.readJSON('package.json'),
    jshint: {
      files: ['src/*.js', 'test/**/*.js'],
        options: {
          globals: {
            jQuery: true,
            module: true
          }
        }
    },
    shell: {
      stageMinified: {
        options: {
            stdout: true,
            // If minified files do not change on release,
            // git command fails
            failOnError: false
        },
        command: 'git add dist/progressbar.js dist/progressbar.min.js dist/progressbar.min.js.map'
      },
      browserifyDevelopment: {
        options: {
          stdout: true
        },
        command: 'browserify src/progressbar.js -o dist/progressbar.js --standalone ProgressBar'
      },
      browserifyMinified: {
        options: {
          stdout: true
        },
        // The output file is minified by uglifyjs later.
        command: 'browserify src/progressbar.js -o dist/progressbar.min.js --standalone ProgressBar'
      },
      watchifyLocalDev: {
        options: {
          stdout: true
        },
        command: 'watchify local-dev/main.js -o local-dev/bundle.js --debug'
      },
      release: {
        options: {
          stdout: true
        },
        command: function(bump) {
          bump = bump || 'patch';
          return './scripts/release.js ' + bump;
        }
      },
      karma: {
        options: {
          stdout: true
        },
        // This will run tests in Sauce Lab
        command: './node_modules/karma/bin/karma start'
      },
      testem: {
        options: {
          stdout: true
        },
        // This will run tests in all local browsers available/detected
        command: 'testem ci -R dot -l chrome'
      }
    },
    // Uglify must be run after browserify
    uglify: {
      progressbar: {
        options: {
          sourceMap: true
        },
        files: {
          'dist/progressbar.min.js': ['dist/progressbar.min.js']
        }
      }
    },
    // Calculated dynamically above
    karma: karmaConfig
  });

  grunt.loadNpmTasks('grunt-contrib-jshint');
  grunt.loadNpmTasks('grunt-contrib-uglify');
  grunt.loadNpmTasks('grunt-shell');
  grunt.loadNpmTasks('grunt-karma');

  grunt.registerTask('watch', function() {
    grunt.task.run(['shell:watchifyLocalDev']);
  });

  grunt.registerTask('stageMinified', function() {
    grunt.task.run(['shell:stageMinified']);
  });

  // Build distributables to dist folder
  grunt.registerTask('build', [
    'shell:browserifyDevelopment',
    'shell:browserifyMinified',
    'uglify:progressbar'
  ]);

  grunt.registerTask('test', ['shell:testem']);

  // Run multiple tests serially, but continue if one of them fails.
  // Adapted from http://stackoverflow.com/questions/16487681/gruntfile-getting-error-codes-from-programs-serially
  grunt.registerTask('sauce', function() {
      var done = this.async();
      var tasks = {};
      _.each(browserGroups, function(group, index) {
        tasks['karma:sauce' + index] = 0;
      });

      var success = true;
      grunt.util.async.forEachSeries(Object.keys(tasks), function(task, next) {
          grunt.util.spawn({
              // Use grunt to spawn
              grunt: true,
              args: [task],
              // Print to the same stdout
              opts: { stdio: 'inherit' }
          }, function(err, result, code) {
              tasks[task] = code;
              if (code !== 0) {
                  success = false;
              }
              next();
          });
      }, function() {
          done(success);
      });
  });

  // Test, build, and release library to public
  grunt.registerTask('release', function(bump) {
    bump = bump || 'patch';

    grunt.task.run([
      'jshint',
      'test',
      'build',
      'stageMinified',
      'shell:release:' + bump
    ]);
  });
};
<commit_msg>Add verbose flag to local watchify task<commit_after>var fs = require('fs');
var _ = require('lodash');

// Split array to smaller arrays containing n elements at max
function groupToElements(array, n) {
  var lists = _.groupBy(array, function(element, index){
    return Math.floor(index / n);
  });

  return _.toArray(lists);
}

function endsWith(str, suffix) {
  return str.indexOf(suffix, str.length - suffix.length) !== -1;
}

// Setup karma configuration dynamically to run browsers sequentially
// https://github.com/karma-runner/karma-sauce-launcher/issues/8
var MAXIMUM_CONCURRENT_SAUCE = 3;
var sauceBrowsers = require('./saucelabs-browsers');
var browserGroups = groupToElements(Object.keys(sauceBrowsers), MAXIMUM_CONCURRENT_SAUCE);

var karmaConfig = {
  options: {
    configFile: 'karma.conf.js'
  }
};

_.each(browserGroups, function(group, index) {
  karmaConfig['sauce' + index] = {
    browsers: group
  }
});

module.exports = function(grunt) {
  grunt.initConfig({
    pkg: grunt.file.readJSON('package.json'),
    jshint: {
      files: ['src/*.js', 'test/**/*.js'],
        options: {
          globals: {
            jQuery: true,
            module: true
          }
        }
    },
    shell: {
      stageMinified: {
        options: {
            stdout: true,
            // If minified files do not change on release,
            // git command fails
            failOnError: false
        },
        command: 'git add dist/progressbar.js dist/progressbar.min.js dist/progressbar.min.js.map'
      },
      browserifyDevelopment: {
        options: {
          stdout: true
        },
        command: 'browserify src/progressbar.js -o dist/progressbar.js --standalone ProgressBar'
      },
      browserifyMinified: {
        options: {
          stdout: true
        },
        // The output file is minified by uglifyjs later.
        command: 'browserify src/progressbar.js -o dist/progressbar.min.js --standalone ProgressBar'
      },
      watchifyLocalDev: {
        options: {
          stdout: true
        },
        command: 'watchify local-dev/main.js -o local-dev/bundle.js --debug --verbose'
      },
      release: {
        options: {
          stdout: true
        },
        command: function(bump) {
          bump = bump || 'patch';
          return './scripts/release.js ' + bump;
        }
      },
      karma: {
        options: {
          stdout: true
        },
        // This will run tests in Sauce Lab
        command: './node_modules/karma/bin/karma start'
      },
      testem: {
        options: {
          stdout: true
        },
        // This will run tests in all local browsers available/detected
        command: 'testem ci -R dot -l chrome'
      }
    },
    // Uglify must be run after browserify
    uglify: {
      progressbar: {
        options: {
          sourceMap: true
        },
        files: {
          'dist/progressbar.min.js': ['dist/progressbar.min.js']
        }
      }
    },
    // Calculated dynamically above
    karma: karmaConfig
  });

  grunt.loadNpmTasks('grunt-contrib-jshint');
  grunt.loadNpmTasks('grunt-contrib-uglify');
  grunt.loadNpmTasks('grunt-shell');
  grunt.loadNpmTasks('grunt-karma');

  grunt.registerTask('watch', function() {
    grunt.task.run(['shell:watchifyLocalDev']);
  });

  grunt.registerTask('stageMinified', function() {
    grunt.task.run(['shell:stageMinified']);
  });

  // Build distributables to dist folder
  grunt.registerTask('build', [
    'shell:browserifyDevelopment',
    'shell:browserifyMinified',
    'uglify:progressbar'
  ]);

  grunt.registerTask('test', ['shell:testem']);

  // Run multiple tests serially, but continue if one of them fails.
  // Adapted from http://stackoverflow.com/questions/16487681/gruntfile-getting-error-codes-from-programs-serially
  grunt.registerTask('sauce', function() {
      var done = this.async();
      var tasks = {};
      _.each(browserGroups, function(group, index) {
        tasks['karma:sauce' + index] = 0;
      });

      var success = true;
      grunt.util.async.forEachSeries(Object.keys(tasks), function(task, next) {
          grunt.util.spawn({
              // Use grunt to spawn
              grunt: true,
              args: [task],
              // Print to the same stdout
              opts: { stdio: 'inherit' }
          }, function(err, result, code) {
              tasks[task] = code;
              if (code !== 0) {
                  success = false;
              }
              next();
          });
      }, function() {
          done(success);
      });
  });

  // Test, build, and release library to public
  grunt.registerTask('release', function(bump) {
    bump = bump || 'patch';

    grunt.task.run([
      'jshint',
      'test',
      'build',
      'stageMinified',
      'shell:release:' + bump
    ]);
  });
};
<|endoftext|>


<commit_before>var Logsene = require('../index.js')
var token = process.env.LOGSENE_TOKEN

describe('Logsene constructor', function() {
  it('should fail without a token', function(done) {
    var emptyTokens = [undefined, null, '']
    emptyTokens.forEach(function(token) {
      try {
        new Logsene(token)
        done(new Error('Should throw exception'))
      } catch(err) {
      }
    })
    done()
  })
})

describe('Logsene log ', function () {
  it('should not throw circular reference error', function(done) {
    var logsene = new Logsene(token, 'test')
    function Foo() {
      this.abc = 'Hello'
      this.circular = this
    }
    var foo = new Foo()
    try {
      logsene.log('info', 'circular test', foo)
      if (logsene.bulkReq.indexOf('[Circular') !== -1) {
        done();
      } else {
        done(new Error('The circular reference was not caught'))
      }
    } catch(err) {
      done(err);
    }
  });

  it('transmit', function (done) {
    this.timeout(20000)
    try {
      var logsene = new Logsene(token, 'test')
      logsene.once('log', function (event) {
        done()
      })
      logsene.once('error', function (event) {
        done(event)
      })
      logsene.on ('error', console.log)
      for (var i = 0; i <= 100; i++)
        logsene.log('info', 'test message ' + i, {testField: 'Test custom field ' + i, counter: i})
    } catch (err) {
      done(err)
    }
  })
})

describe('Logsene DiskBuffer ', function () {
  it('re-transmit', function (done) {
    this.timeout(50000)
    process.env.DEBUG_LOGSENE_DISK_BUFFER=true
    var DiskBuffer = require('../DiskBuffer.js')
    var db = DiskBuffer.createDiskBuffer({
      tmpDir: './tmp',
      interval: 1000
    })
    db.syncFileListFromDir()
    db.on('retransmit-req', function (event) {
        db.rmFile(event.fileName)
        db.retransmitNext()
    })
    db.once('removed', function () {
      done()
    })
    db.store('hello')
    db.retransmitNext()
  })
})

describe('Logsene persistance ', function () {
  it('re-transmit', function (done) {
    this.timeout(50000)
    try {

      var logsene = new Logsene(token, 'test')
      var url = logsene.url
      logsene.diskBuffer(true, '.')
      logsene.setUrl('http://notreachable.test')
      logsene.db.once('removed', function (event) {
        done()
      })
      //logsene.once('rt', function (event) {
      //  done()
      //})
      logsene.on ('error', function (err) {
        if (err) {
          logsene.setUrl(url)
        }
      })
      for (var i = 0; i <= 1000; i++) {
        logsene.log('info', 'test retransmit message ' + i, {_id: 'hey', testField: 'Test custom field ' + i, counter: i, _type: 'test_type', 'dot.sep.field': 34 })
      }
    } catch (err) {
      done(err)
    }
  })
})

<commit_msg>tuning timeouts in test<commit_after>var Logsene = require('../index.js')
var token = process.env.LOGSENE_TOKEN

describe('Logsene constructor', function() {
  it('should fail without a token', function(done) {
    var emptyTokens = [undefined, null, '']
    emptyTokens.forEach(function(token) {
      try {
        new Logsene(token)
        done(new Error('Should throw exception'))
      } catch(err) {
      }
    })
    done()
  })
})

describe('Logsene log ', function () {
  it('should not throw circular reference error', function(done) {
    var logsene = new Logsene(token, 'test')
    function Foo() {
      this.abc = 'Hello'
      this.circular = this
    }
    var foo = new Foo()
    try {
      logsene.log('info', 'circular test', foo)
      if (logsene.bulkReq.indexOf('[Circular') !== -1) {
        done();
      } else {
        done(new Error('The circular reference was not caught'))
      }
    } catch(err) {
      done(err);
    }
  });

  it('transmit', function (done) {
    this.timeout(20000)
    try {
      var logsene = new Logsene(token, 'test')
      logsene.once('log', function (event) {
        done()
      })
      logsene.once('error', function (event) {
        done(event)
      })
      logsene.on ('error', console.log)
      for (var i = 0; i <= 100; i++)
        logsene.log('info', 'test message ' + i, {testField: 'Test custom field ' + i, counter: i})
    } catch (err) {
      done(err)
    }
  })
})

describe('Logsene DiskBuffer ', function () {
  it('re-transmit', function (done) {
    this.timeout(50000)
    process.env.DEBUG_LOGSENE_DISK_BUFFER=true
    var DiskBuffer = require('../DiskBuffer.js')
    var db = DiskBuffer.createDiskBuffer({
      tmpDir: './tmp',
      interval: 1000
    })
    db.syncFileListFromDir()
    db.on('retransmit-req', function (event) {
        db.rmFile(event.fileName)
        db.retransmitNext()
    })
    db.once('removed', function () {
      done()
    })
    db.store('hello')
    db.retransmitNext()
  })
})

describe('Logsene persistance ', function () {
  it('re-transmit', function (done) {
    this.timeout(50000)
    try {
      process.env.LOGSENE_DISK_BUFFER_INTERVAL=500
      var logsene = new Logsene(token, 'test')
      var url = logsene.url
      logsene.diskBuffer(true, '.')
      logsene.setUrl('http://notreachable.test')
      logsene.db.once('removed', function (event) {
        done()
      })
      //logsene.once('rt', function (event) {
      //  done()
      //})
      logsene.on ('error', function (err) {
        if (err) {
          logsene.setUrl(url)
        }
      })
      for (var i = 0; i <= 1000; i++) {
        logsene.log('info', 'test retransmit message ' + i, {_id: 'hey', testField: 'Test custom field ' + i, counter: i, _type: 'test_type', 'dot.sep.field': 34 })
      }
    } catch (err) {
      done(err)
    }
  })
})

<|endoftext|>


<commit_before>const keyMirror = require('keymirror');
const defaults = require('lodash.defaults');
const get = require('lodash.get');

const {requestSession, requestSessionWithRetry} = require('../lib/session');
const messageCountActions = require('./message-count.js');
const permissionsActions = require('./permissions.js');

const Types = keyMirror({
    SET_SESSION: null,
    SET_SESSION_ERROR: null,
    SET_STATUS: null
});

const banWhitelistPaths = [
    '/accounts/banned-response/',
    '/community_guidelines/',
    '/community_guidelines'
];

module.exports.Status = keyMirror({
    FETCHED: null,
    NOT_FETCHED: null,
    FETCHING: null
});

module.exports.getInitialState = () => ({
    status: module.exports.Status.NOT_FETCHED,
    session: {}
});

module.exports.sessionReducer = (state, action) => {
    // Reducer for handling changes to session state
    if (typeof state === 'undefined') {
        state = module.exports.getInitialState();
    }
    switch (action.type) {
    case Types.SET_SESSION:
        return defaults({session: action.session}, state);
    case Types.SET_STATUS:
        return defaults({status: action.status}, state);
    case Types.SET_SESSION_ERROR:
        // TODO: do something with action.error
        return state;
    default:
        return state;
    }
};

module.exports.setSessionError = error => ({
    type: Types.SET_SESSION_ERROR,
    error: error
});

module.exports.setSession = session => ({
    type: Types.SET_SESSION,
    session: session
});

module.exports.setStatus = status => ({
    type: Types.SET_STATUS,
    status: status
});

const handleSessionResponse = (dispatch, body) => {
    if (typeof body === 'undefined') return dispatch(module.exports.setSessionError('No session content'));
    if (
        body.user &&
        body.user.banned &&
        banWhitelistPaths.indexOf(window.location.pathname) === -1
    ) {
        window.location = '/accounts/banned-response/';
        return;
    } else if (
        body.flags &&
        body.flags.must_complete_registration &&
        window.location.pathname !== '/classes/complete_registration'
    ) {
        window.location = '/classes/complete_registration';
        return;
    } else if (
        body.flags &&
        body.flags.must_reset_password &&
        !body.flags.must_complete_registration &&
        window.location.pathname !== '/classes/student_password_reset/'
    ) {
        window.location = '/classes/student_password_reset/';
        return;
    }
    dispatch(module.exports.setSession(body));
    dispatch(module.exports.setStatus(module.exports.Status.FETCHED));

    // get the permissions from the updated session
    dispatch(permissionsActions.storePermissions(body.permissions));
    if (typeof body.user !== 'undefined') {
        dispatch(messageCountActions.getCount(body.user.username));
    }
    return;
};

module.exports.refreshSession = () => (dispatch => {
    dispatch(module.exports.setStatus(module.exports.Status.FETCHING));
    return new Promise((resolve, reject) => {
        requestSession(resolve, reject);
    }).then(body => {
        handleSessionResponse(dispatch, body);
    }, err => {
        dispatch(module.exports.setSessionError(err));
    });
});

module.exports.refreshSessionWithRetry = () => (dispatch => {
    dispatch(module.exports.setStatus(module.exports.Status.FETCHING));
    return new Promise((resolve, reject) => {
        requestSessionWithRetry(resolve, reject, 4, 7500);
    }).then(body => {
        handleSessionResponse(dispatch, body);
    }, err => {
        dispatch(module.exports.setSessionError(err));
    });
});

// Selectors
module.exports.selectIsLoggedIn = state => !!get(state, ['session', 'session', 'user'], false);
module.exports.selectUsername = state => get(state, ['session', 'session', 'user', 'username'], null);
module.exports.selectToken = state => get(state, ['session', 'session', 'user', 'token'], null);
module.exports.selectIsAdmin = state => get(state, ['session', 'session', 'permissions', 'admin'], false);
module.exports.selectIsSocial = state => get(state, ['session', 'session', 'permissions', 'social'], false);

// NB logged out user id as NaN so that it can never be used in equality testing since NaN !== NaN
module.exports.selectUserId = state => get(state, ['session', 'session', 'user', 'id'], NaN);
<commit_msg>update method of checking goodlist of pages for banned user to see<commit_after>const keyMirror = require('keymirror');
const defaults = require('lodash.defaults');
const get = require('lodash.get');

const {requestSession, requestSessionWithRetry} = require('../lib/session');
const messageCountActions = require('./message-count.js');
const permissionsActions = require('./permissions.js');

const Types = keyMirror({
    SET_SESSION: null,
    SET_SESSION_ERROR: null,
    SET_STATUS: null
});

const banGoodListPaths = [
    '/accounts/banned-response',
    '/community_guidelines',
    '/privacy_policy',
    '/terms_of_use'
];

module.exports.Status = keyMirror({
    FETCHED: null,
    NOT_FETCHED: null,
    FETCHING: null
});

module.exports.getInitialState = () => ({
    status: module.exports.Status.NOT_FETCHED,
    session: {}
});

module.exports.sessionReducer = (state, action) => {
    // Reducer for handling changes to session state
    if (typeof state === 'undefined') {
        state = module.exports.getInitialState();
    }
    switch (action.type) {
    case Types.SET_SESSION:
        return defaults({session: action.session}, state);
    case Types.SET_STATUS:
        return defaults({status: action.status}, state);
    case Types.SET_SESSION_ERROR:
        // TODO: do something with action.error
        return state;
    default:
        return state;
    }
};

module.exports.setSessionError = error => ({
    type: Types.SET_SESSION_ERROR,
    error: error
});

module.exports.setSession = session => ({
    type: Types.SET_SESSION,
    session: session
});

module.exports.setStatus = status => ({
    type: Types.SET_STATUS,
    status: status
});

const handleSessionResponse = (dispatch, body) => {
    if (typeof body === 'undefined') return dispatch(module.exports.setSessionError('No session content'));
    if (
        body.user &&
        body.user.banned &&
        banGoodListPaths.every(goodPath => window.location.pathname.indexOf(goodPath) === -1)
    ) {
        window.location = '/accounts/banned-response/';
        return;
    } else if (
        body.flags &&
        body.flags.must_complete_registration &&
        window.location.pathname !== '/classes/complete_registration'
    ) {
        window.location = '/classes/complete_registration';
        return;
    } else if (
        body.flags &&
        body.flags.must_reset_password &&
        !body.flags.must_complete_registration &&
        window.location.pathname !== '/classes/student_password_reset/'
    ) {
        window.location = '/classes/student_password_reset/';
        return;
    }
    dispatch(module.exports.setSession(body));
    dispatch(module.exports.setStatus(module.exports.Status.FETCHED));

    // get the permissions from the updated session
    dispatch(permissionsActions.storePermissions(body.permissions));
    if (typeof body.user !== 'undefined') {
        dispatch(messageCountActions.getCount(body.user.username));
    }
    return;
};

module.exports.refreshSession = () => (dispatch => {
    dispatch(module.exports.setStatus(module.exports.Status.FETCHING));
    return new Promise((resolve, reject) => {
        requestSession(resolve, reject);
    }).then(body => {
        handleSessionResponse(dispatch, body);
    }, err => {
        dispatch(module.exports.setSessionError(err));
    });
});

module.exports.refreshSessionWithRetry = () => (dispatch => {
    dispatch(module.exports.setStatus(module.exports.Status.FETCHING));
    return new Promise((resolve, reject) => {
        requestSessionWithRetry(resolve, reject, 4, 7500);
    }).then(body => {
        handleSessionResponse(dispatch, body);
    }, err => {
        dispatch(module.exports.setSessionError(err));
    });
});

// Selectors
module.exports.selectIsLoggedIn = state => !!get(state, ['session', 'session', 'user'], false);
module.exports.selectUsername = state => get(state, ['session', 'session', 'user', 'username'], null);
module.exports.selectToken = state => get(state, ['session', 'session', 'user', 'token'], null);
module.exports.selectIsAdmin = state => get(state, ['session', 'session', 'permissions', 'admin'], false);
module.exports.selectIsSocial = state => get(state, ['session', 'session', 'permissions', 'social'], false);

// NB logged out user id as NaN so that it can never be used in equality testing since NaN !== NaN
module.exports.selectUserId = state => get(state, ['session', 'session', 'user', 'id'], NaN);
<|endoftext|>


<commit_before>var Lab = require('lab');
var Template = require('../../lib/template');
var assert  = require('chai').assert;
var assertHtml = require('../helper').assertHtml;

var lab = exports.lab = Lab.script();

lab.experiment('Code structure', function() {
  var template;
  lab.before(function(done) {
    template = new Template(require('../../lib/vm_node'));
    done();
  });

  lab.test('render with conditional', function(done) {
    assertHtml(template, [
      'div',
      '  - if this.showFirst()',
      '      p The first paragraph',
      '  - else',
      '      p The second paragraph'
      ],
      '

The second paragraph

',
      {}, done);
  });

  lab.test('render with conditional else if', function(done) {
    assertHtml(template, [
      'div',
      '  - if this.showFirst()',
      '      p The first paragraph',
      '  - else if this.showFirst(true)',
      '      p The second paragraph',
      '  - else',
      '      p The third paragraph'
      ],
      '

The second paragraph

',
      {}, done);
  });

  lab.test('render with consecutive conditionals', function(done) {
    assertHtml(template, [
      'div',
      '  - if this.showFirst(true)',
      '      p The first paragraph',
      '  - if this.showFirst(true)',
      '      p The second paragraph'
      ],
      '

The first paragraph

The second paragraph

',
      {}, done);
  });

  lab.test('render with when string in condition', function(done) {
    assertHtml(template, [
      '- if true',
      '  | Hello',

      '- if "when" !== null',
      '  |  world'
      ],
      'Hello world',
      {}, done);
  });

  lab.test('render with conditional and following nonconditonal', function(done) {
    assertHtml(template, [
      'div',
      '  - if true',
      '      p The first paragraph',
      '  - var x = 42',
      '  = x'
      ],
      '

The first paragraph
42
',
      {}, done);
  });

  lab.test('render with case', function(done) {
    assertHtml(template, [
      '- var url = require("url")',
      'p',
      '  - switch(42)',
      '    - case 41:',
      '      | 41',
      '      - break',
      '    - case 42:',
      '      | 42',
      '      - break',
      '  |  is the answer',
      'p',
      '  - switch(41)',
      '    - case 41:',
      '      | 41',
      '      - break',
      '    - case 42:',
      '      | 42',
      '      - break',
      '  |  is the answer',
      'p',
      '  - switch(42)',
      '    - case 41:',
      '      | 41',
      '      - break',
      '    - case 42:',
      '      | 42',
      '      - break',
      '  |  is the answer',
      'p',
      '  - switch(41)',
      '    - case 41:',
      '      | 41',
      '      - break',
      '    - case 42:',
      '      | 42',
      '      - break',
      '  |  is the answer'
      ],
      '
42 is the answer

41 is the answer

42 is the answer

41 is the answer
',
      {}, done);
  });

  lab.test('render with slm comments', function(done) {
    assertHtml(template, [
      'p Hello',
      '/ This is a comment',
      '  Another comment',
      'p World'
      ],
      '
Hello

World
',
      {}, done);
  });

  lab.test('render with slm comments and empty line', function(done) {
    assertHtml(template, [
      'p Hello',
      '/ This is a comment',
      '',
      '  Another comment',
      'p World'
      ],
      '
Hello

World
',
      {}, done);
  });

  lab.test('render with try catch', function(done) {
    assertHtml(template, [
      '- try',
      '  p Try',
      '- catch error',
      '  p Catch',
      'p After'
      ],
      '
Try

After
',
      {}, done);
  });

  lab.test('render with try catch exception', function(done) {
    assertHtml(template, [
      '- try',
      '  p Try',
      '  - throw "Boom"',
      '  p After Boom',
      '- catch ex',
      '  p = ex',
      'p After'
      ],
      '
Try

Boom

After
',
      {}, done);
  });

  lab.test('render with try catch finally', function(done) {
    assertHtml(template, [
      '- try',
      '  p Try',
      '  - throw "Boom"',
      '  p After Boom',
      '- catch ex',
      '  p = ex',
      '- finally',
      '  p Finally',
      'p After'
      ],
      '
Try

Boom

Finally

After
',
      {}, done);
  });

  lab.test('injects callback arg', function(done) {
    assertHtml(template, [
      '= this.block()',
      '  p Block',
      'p After'
      ],
      '
Block

After
',
      {}, done);
  });

  lab.test('detects missing brace', function(done) {
    var src = [
      '= this.block)',
      '  p Block',
      'p After'
      ].join('\n');
    assert.throw(function() {
      template.render(src, {}, {});
    }, 'Missing open brace \"(\" in `this.block)`');

    done();
  });

  lab.test('content', function(done) {
    assertHtml(template, [
      '= content()',
      'p After 1',
      '= content("head")',
      'p After 2',
      '= content(false)',
        'title title1',
      'p After 3',
      '= content("head")',
        'title title2',
      'p After 4',
      '= content("head")',
      '= content(false)',
      '  p Not captured'
      ],
      '
After 1

After 2
<title>title1</title>
After 3
<title>title2</title>
After 4

Not captured
',
      {}, done);
  });

  lab.test('render with forEach', function(done) {
    assertHtml(template, [
      'div',
      '  - this.items.forEach(function(i))',
      '      p = i',
      ],
      '

1

2

3

',
      {}, done);
  });
});
<commit_msg>Code cleanup<commit_after>var Lab = require('lab');
var Template = require('../../lib/template');
var assert  = require('chai').assert;
var assertHtml = require('../helper').assertHtml;

var lab = exports.lab = Lab.script();

lab.experiment('Code structure', function() {
  var template;
  lab.before(function(done) {
    template = new Template(require('../../lib/vm_node'));
    done();
  });

  lab.test('render with conditional', function(done) {
    assertHtml(template, [
      'div',
      '  - if this.showFirst()',
      '      p The first paragraph',
      '  - else',
      '      p The second paragraph'
      ],
      '

The second paragraph

',
      {}, done);
  });

  lab.test('render with conditional else if', function(done) {
    assertHtml(template, [
      'div',
      '  - if this.showFirst()',
      '      p The first paragraph',
      '  - else if this.showFirst(true)',
      '      p The second paragraph',
      '  - else',
      '      p The third paragraph'
      ],
      '

The second paragraph

',
      {}, done);
  });

  lab.test('render with consecutive conditionals', function(done) {
    assertHtml(template, [
      'div',
      '  - if this.showFirst(true)',
      '      p The first paragraph',
      '  - if this.showFirst(true)',
      '      p The second paragraph'
      ],
      '

The first paragraph

The second paragraph

',
      {}, done);
  });

  lab.test('render with when string in condition', function(done) {
    assertHtml(template, [
      '- if true',
      '  | Hello',

      '- if "when" !== null',
      '  |  world'
      ],
      'Hello world',
      {}, done);
  });

  lab.test('render with conditional and following nonconditonal', function(done) {
    assertHtml(template, [
      'div',
      '  - if true',
      '      p The first paragraph',
      '  - var x = 42',
      '  = x'
      ],
      '

The first paragraph
42
',
      {}, done);
  });

  lab.test('render with case', function(done) {
    assertHtml(template, [
      '- var url = require("url")',
      'p',
      '  - switch(42)',
      '    - case 41:',
      '      | 41',
      '      - break',
      '    - case 42:',
      '      | 42',
      '      - break',
      '  |  is the answer',
      'p',
      '  - switch(41)',
      '    - case 41:',
      '      | 41',
      '      - break',
      '    - case 42:',
      '      | 42',
      '      - break',
      '  |  is the answer',
      'p',
      '  - switch(42)',
      '    - case 41:',
      '      | 41',
      '      - break',
      '    - case 42:',
      '      | 42',
      '      - break',
      '  |  is the answer',
      'p',
      '  - switch(41)',
      '    - case 41:',
      '      | 41',
      '      - break',
      '    - case 42:',
      '      | 42',
      '      - break',
      '  |  is the answer'
      ],
      '
42 is the answer

41 is the answer

42 is the answer

41 is the answer
',
      {}, done);
  });

  lab.test('render with slm comments', function(done) {
    assertHtml(template, [
      'p Hello',
      '/ This is a comment',
      '  Another comment',
      'p World'
      ],
      '
Hello

World
',
      {}, done);
  });

  lab.test('render with slm comments and empty line', function(done) {
    assertHtml(template, [
      'p Hello',
      '/ This is a comment',
      '',
      '  Another comment',
      'p World'
      ],
      '
Hello

World
',
      {}, done);
  });

  lab.test('render with try catch', function(done) {
    assertHtml(template, [
      '- try',
      '  p Try',
      '- catch error',
      '  p Catch',
      'p After'
      ],
      '
Try

After
',
      {}, done);
  });

  lab.test('render with try catch exception', function(done) {
    assertHtml(template, [
      '- try',
      '  p Try',
      '  - throw "Boom"',
      '  p After Boom',
      '- catch ex',
      '  p = ex',
      'p After'
      ],
      '
Try

Boom

After
',
      {}, done);
  });

  lab.test('render with try catch finally', function(done) {
    assertHtml(template, [
      '- try',
      '  p Try',
      '  - throw "Boom"',
      '  p After Boom',
      '- catch ex',
      '  p = ex',
      '- finally',
      '  p Finally',
      'p After'
      ],
      '
Try

Boom

Finally

After
',
      {}, done);
  });

  lab.test('injects callback arg', function(done) {
    assertHtml(template, [
      '= this.block()',
      '  p Block',
      'p After'
      ],
      '
Block

After
',
      {}, done);
  });

  lab.test('detects missing brace', function(done) {
    var src = [
      '= this.block)',
      '  p Block',
      'p After'
      ].join('\n');
    assert.throw(function() {
      template.render(src, {}, {});
    }, 'Missing open brace \"(\" in `this.block)`');

    done();
  });

  lab.test('content', function(done) {
    assertHtml(template, [
      '= content()',
      'p After 1',
      '= content("head")',
      'p After 2',
      '= content(false)',
        'title title1',
      'p After 3',
      '= content("head")',
        'title title2',
      'p After 4',
      '= content("head")',
      '= content(false)',
      '  p Not captured'
      ],
      '
After 1

After 2
<title>title1</title>
After 3
<title>title2</title>
After 4

Not captured
',
      {}, done);
  });

  lab.test('render with forEach', function(done) {
    assertHtml(template, [
      'div',
      '  - this.items.forEach(function(i))',
      '    p = i',
      ],
      '

1

2

3

',
      {}, done);
  });
});
<|endoftext|>


<commit_before>var exports, require, define, module;

exports = function(){};
module = { exports: null };

require = function (m) {
  return require.s.contexts._.defined[m] || (function (name, def) {

    if (!def) { return; }

    def.args.forEach(function (c, i, a) {
      if (c === undefined) {
        a[i] = require(def.deps[i]);
      }
    });

    var context = def.factory.apply(null, def.args);

    // resolve module.exports with module id
    if (def.deps[1] === 'module' && name !== '') {
      require.s.contexts._.defined[name] = module.exports;
      delete module['exports'];
      module.exports = null;
    }

    // resolve export when exports is an object,
    // iterate exported item and move them to context object.
    else if (def.deps[0] === 'exports') {
      // ditch context, it gets replaced here
      context = {};
      for (var item in exports) {
        context[item] = exports[item];
        delete exports[item];
      }
    }

    // resolve export when factory returns data and
    // module didn't use exports or module.exports
    // and module has module id
    if (context !== undefined && name !== '') {
      require.s.contexts._.defined[name] = context;
    }

    delete require.s.contexts._.registry[name];

    return require.s.contexts._.defined[name];
  })(m, require.s.contexts._.registry[m]) || window[m];
};

require.s = {
  contexts: {
    '_': {
      registry: {},
      defined: {
        'jquery': window.jQuery,
        'history': window.History,
        'babel-runtime/core-js': { default: window.core }
      }
    }
  }
};

/*
 * Totally not resolve in async.
 * */
define = function (name, deps, factory) {
  var resolved_deps, context;

  if (arguments.length === 2) {
    factory = deps;
    deps = name;
    name = '';
  } else if (arguments.length === 1) {
    factory = name;
    deps = [];
    name = '';
  }
  resolved_deps = deps.map(function (v) {
    return require(v);
  });

  if (name === '') {
    // throw "Can't resolve anonymous module";
    return;
  }

  require.s.contexts._.registry[name] = {
    factory: factory,
    deps: deps,
    args: resolved_deps
  };
}

define.amd = {};

module.loadNamespace = function (namespace, callback) {
  var
    modules = require.s.contexts._,
    rgx = new RegExp('^' + namespace + '/'),
    result = [];

  for (var k in modules.defined) {
    if (rgx.test(k)) {
      result.push({
        Name: k,
        Class: modules.defined[k]
      });
    }
  }

  for (var k in modules.registry) {
    if (rgx.test(k)) {
      result.push({
        Name: k,
        Class: require(k)
      });
    }
  }

  if (typeof(callback) === 'function') {
    callback(result);
  }
}
<commit_msg>semicolons<commit_after>var exports, require, define, module;

exports = function(){};
module = { exports: null };

require = function (m) {
  return require.s.contexts._.defined[m] || (function (name, def) {

    if (!def) { return; }

    def.args.forEach(function (c, i, a) {
      if (c === undefined) {
        a[i] = require(def.deps[i]);
      }
    });

    var context = def.factory.apply(null, def.args);

    // resolve module.exports with module id
    if (def.deps[1] === 'module' && name !== '') {
      require.s.contexts._.defined[name] = module.exports;
      delete module['exports'];
      module.exports = null;
    }

    // resolve export when exports is an object,
    // iterate exported item and move them to context object.
    else if (def.deps[0] === 'exports') {
      // ditch context, it gets replaced here
      context = {};
      for (var item in exports) {
        context[item] = exports[item];
        delete exports[item];
      }
    }

    // resolve export when factory returns data and
    // module didn't use exports or module.exports
    // and module has module id
    if (context !== undefined && name !== '') {
      require.s.contexts._.defined[name] = context;
    }

    delete require.s.contexts._.registry[name];

    return require.s.contexts._.defined[name];
  })(m, require.s.contexts._.registry[m]) || window[m];
};

require.s = {
  contexts: {
    '_': {
      registry: {},
      defined: {
        'jquery': window.jQuery,
        'history': window.History,
        'babel-runtime/core-js': { default: window.core }
      }
    }
  }
};

/*
 * Totally not resolve in async.
 * */
define = function (name, deps, factory) {
  var resolved_deps, context;

  if (arguments.length === 2) {
    factory = deps;
    deps = name;
    name = '';
  } else if (arguments.length === 1) {
    factory = name;
    deps = [];
    name = '';
  }
  resolved_deps = deps.map(function (v) {
    return require(v);
  });

  if (name === '') {
    // throw "Can't resolve anonymous module";
    return;
  }

  require.s.contexts._.registry[name] = {
    factory: factory,
    deps: deps,
    args: resolved_deps
  };
};

define.amd = {};

module.loadNamespace = function (namespace, callback) {
  var
    modules = require.s.contexts._,
    rgx = new RegExp('^' + namespace + '/'),
    result = [];

  for (var k in modules.defined) {
    if (rgx.test(k)) {
      result.push({
        Name: k,
        Class: modules.defined[k]
      });
    }
  }

  for (var k in modules.registry) {
    if (rgx.test(k)) {
      result.push({
        Name: k,
        Class: require(k)
      });
    }
  }

  if (typeof(callback) === 'function') {
    callback(result);
  }
};
<|endoftext|>


<commit_before>var _ = require("underscore");
var assert = require("assert");
var es = require("event-stream");
var fs = require("fs");
var File = require("vinyl");
var GulpFlow = require("../GulpFlow.js");
var PluginError = require("gulp-util").PluginError;

describe("buffer mode", function()
{
    it("should work", function(done)
    {
        var stringContents = fs.readFileSync("test/f.js", "utf-8");
        var contents = new Buffer(stringContents);

        var fakeFilePath = "test/f.js";
        var fakeFile = new File({
            contents: contents,
            path: fakeFilePath
        });
        var gulpFlow = new GulpFlow();
        var checker = gulpFlow.check();
        checker.write(fakeFile);
        checker.once("data", function(file)
        {
            assert(file.isBuffer());
            var contents = file.contents.toString("utf-8");
            var results = JSON.parse(contents);

            // check that we failed
            assert.ok(!results.passed);

            // check that the results are correct
            var errors = results.errors;
            assert.equal(errors.length, 1);
            // check that we got the errors we expected
            var expected = [
                "object literal This type is incompatible with number"
            ];
            var i = -1;
            _.forEach(errors, function(error)
            {
                i++;
                var text = _.pluck(error.message, "descr").join(" ");
                assert.equal(text, expected[i]);
            });
            done();
        });
    });
});

describe("stream mode", function()
{
    it("should NOT work (for now, anyhow)", function(done)
    {
        console.log("FIXME");
        done();
    });
});

describe("null", function()
{
    it("should not do anything", function(done)
    {
        var gulpFlowCheck = new GulpFlow().check();
        var nullFile = new File();
        gulpFlowCheck.pipe(es.through(function(file)
        {
            assert.equal(file.contents, null);
        }, done));
        gulpFlowCheck.write(nullFile);
        gulpFlowCheck.end();
    });
});

// FIXME: move to a separate test file for reporters
describe("reporters", function()
{
    describe("fail reporter", function()
    {
        var failReporter;
        beforeEach(function()
        {
            failReporter = new GulpFlow().failReporter();
        });

        it("should accept empty results", function(done)
        {
            var nullFile = new File();
            failReporter
                .pipe(es.through(function(file)
                {
                    assert.equal(file.contents, null);
                }, done))
                .on("error", function(error)
                {
                    throw error;
                });
            failReporter.write(nullFile);
            failReporter.end();
        });

        it("should throw on non-empty results", function(done)
        {
            var fakeFile = new File({
                contents: new Buffer("{\"passed\": false}")
            });
            failReporter.on("error", function(error)
            {
                assert(error instanceof PluginError);
                done();
            });
            failReporter.write(fakeFile);
            failReporter.end();
        });
    });
});
<commit_msg>add another test<commit_after>var _ = require("underscore");
var assert = require("assert");
var es = require("event-stream");
var fs = require("fs");
var File = require("vinyl");
var GulpFlow = require("../GulpFlow.js");
var PluginError = require("gulp-util").PluginError;

describe("buffer mode", function()
{
    it("should work", function(done)
    {
        var stringContents = fs.readFileSync("test/f.js", "utf-8");
        var contents = new Buffer(stringContents);

        var fakeFilePath = "test/f.js";
        var fakeFile = new File({
            contents: contents,
            path: fakeFilePath
        });
        var gulpFlow = new GulpFlow();
        var checker = gulpFlow.check();
        checker.write(fakeFile);
        checker.once("data", function(file)
        {
            assert(file.isBuffer());
            var contents = file.contents.toString("utf-8");
            var results = JSON.parse(contents);

            // check that we failed
            assert.ok(!results.passed);

            // check that the results are correct
            var errors = results.errors;
            assert.equal(errors.length, 1);
            // check that we got the errors we expected
            var expected = [
                "object literal This type is incompatible with number"
            ];
            var i = -1;
            _.forEach(errors, function(error)
            {
                i++;
                var text = _.pluck(error.message, "descr").join(" ");
                assert.equal(text, expected[i]);
            });
            done();
        });
    });
});

describe("stream mode", function()
{
    it("should NOT work (for now, anyhow)", function(done)
    {
        console.log("FIXME");
        done();
    });
});

describe("null", function()
{
    it("should not do anything", function(done)
    {
        var gulpFlowCheck = new GulpFlow().check();
        var nullFile = new File();
        gulpFlowCheck.pipe(es.through(function(file)
        {
            assert.equal(file.contents, null);
        }, done));
        gulpFlowCheck.write(nullFile);
        gulpFlowCheck.end();
    });
});

// FIXME: move to a separate test file for reporters
describe("reporters", function()
{
    describe("fail reporter", function()
    {
        var failReporter;
        beforeEach(function()
        {
            failReporter = new GulpFlow().failReporter();
        });

        it("should accept empty results", function(done)
        {
            var nullFile = new File();
            failReporter
                .pipe(es.through(function(file)
                {
                    assert.equal(file.contents, null);
                }, done))
                .on("error", function(error)
                {
                    throw error;
                });
            failReporter.write(nullFile);
            failReporter.end();
        });

        describe("json results", function()
        {
            function check(contents, result, done)
            {
                var fakeFile = new File({
                    contents: new Buffer(contents)
                });
                failReporter
                    .on("error", function(error)
                    {
                        assert(!result);
                        assert(error instanceof PluginError);
                        done();
                    })
                    .pipe(es.through(function(file)
                    {
                        assert(result);
                    }, done))
                failReporter.write(fakeFile);
                failReporter.end();
            }

            it("should throw if we don't pass", function(done)
            {
                check("{\"passed\": false}", false, done);
            });

            it("should not throw if we pass", function(done)
            {
                check("{\"passed\": true}", true, done);
            });
        });
    });
});
<|endoftext|>


<commit_before>/*
 * Copyright 2013 Telefonica Investigación y Desarrollo, S.A.U
 *
 * This file is part of fiware-orion-pep
 *
 * fiware-orion-pep is free software: you can redistribute it and/or
 * modify it under the terms of the GNU Affero General Public License as
 * published by the Free Software Foundation, either version 3 of the License,
 * or (at your option) any later version.
 *
 * fiware-orion-pep is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public
 * License along with fiware-orion-pep.
 * If not, seehttp://www.gnu.org/licenses/.
 *
 * For those usages not covered by the GNU Affero General Public License
 * please contact with::[daniel.moranjimenez@telefonica.com]
 */

'use strict';

var sax = require('sax'),
    logger = require('fiware-node-logger'),
    errors = require('../errors');

/**
 * Translates the updateAction value to the appropriate action name for the Access Control.
 *
 * @param {String} originalAction        String with the action name.
 * @return {String}                      The string representation of the action name for the Access Control.
 */
function translateAction(originalAction) {
    var action;

    switch (originalAction.toUpperCase()) {
        case 'APPEND':
            action = 'create';
            break;

        case 'UPDATE':
            action = 'update';
            break;

        case 'DELETE':
            action = 'delete';
            break;

        default:
            action = null;
    }

    logger.debug('Discovered action was: %s', action);

    return action;
}

/**
 * Extract the action from an XML body.
 *
 * @param {String} body          Raw string payload.
 */
function inspectBodyXML(body, callback) {
    var parser = sax.parser(true),
        readingAction = false,
        errorRaised = false,
        action;

    parser.onerror = function(e) {
        var error = new errors.WrongXmlPayload();

        logger.error('[ORION-PLUGIN-006] Wrong XML Payload. Parsing error: %s', e.message);

        if (!errorRaised) {
            errorRaised = true;
            error.moreInfo = e;
            callback(error);
        }
    };

    parser.ontext = function(t) {
        if (readingAction) {
            if (!action) {
                action = t;
            } else {
                action = action + t;
            }
        }
    };

    parser.onopentag = function(node) {
        if (node.name === 'updateAction') {
            readingAction = true;
        } else {
            readingAction = false;
        }
    };

    parser.onend = function() {
        if (action) {
            var translatedAction = translateAction(action.trim());

            if (translatedAction) {
                callback(null, translatedAction);
            } else {
                callback(new errors.WrongXmlPayload());
            }

        } else {
            logger.error('[ORION-PLUGIN-001] Wrong XML Payload. Action not found');

            callback(new errors.WrongXmlPayload());
        }
    };

    try {
        parser.write(body).close();
    } catch (e) {
        var error = new errors.WrongXmlPayload();

        logger.error('[ORION-PLUGIN-002] Wrong XML Payload. Parsing error: %s', e.message);
        callback(error);
    }
}

/**
 * Extract the action from a JSON body.
 *
 * @param {Object} body          Javascript Object with the parsed payload.
 */
function inspectBodyJSON(body, callback) {
    if (body && body.updateAction) {
        var translatedAction = translateAction(body.updateAction);

        if (translatedAction) {
            callback(null, translatedAction);
        } else {
            callback(new errors.WrongJsonPayload());
        }
    } else {
        logger.error('[ORION-PLUGIN-003] Wrong JSON Payload: updateAction element not found');

        callback(new errors.WrongJsonPayload());
    }
}

/**
 * Determines what kind of body to parse to calculate the action, and invoke the appropriate function.
 *
 * @param {Object} req           Incoming request.
 * @param {Object} res           Outgoing response.
 */
function inspectBody(req, res, callback) {
    var actionHandler = function actionHandler(error, action) {
        req.action = action;
        callback(error, req, res);
    };

    if (req.headers['content-type'] === 'application/json') {
        logger.debug('Inspecting JSON body to discover action: \n%s\n\n', JSON.stringify(req.body, null, 4));
        inspectBodyJSON(req.body, actionHandler);
    } else if (req.headers['content-type'] === 'application/xml' || req.headers['content-type'] === 'text/xml') {
        logger.debug('Inspecting XML body to discover action: \n%s\n\n', req.rawBody);
        inspectBodyXML(req.rawBody, actionHandler);
    } else {
        // TODO: raise error if the type is not recognized.
        logger.error('[ORION-PLUGIN-004] Unknown content type: %s', req.headers['content-type']);

        actionHandler(new errors.UnexpectedContentType(req.headers['content-type']));
    }
}

/**
 * Determines what is the requested action based on the URL.
 *
 * @param {Object}   req           Incoming request.
 * @param {Object}   res           Outgoing response.
 * @param {Function} callback      Callback for calling the next middleware. This callback should adhere to the
 *                                 following signature: callback(error, req, res) where req and res are the received
 *                                 parameters and error is an Error object in case the request should be rejected
 *                                 or null otherwise.
 */
function inspectUrl(req, res, callback) {
    var error = null;

    logger.debug('Extracting action from the URL "%s"', req.url);

    if (req.url.toLowerCase().indexOf('/ngsi10/querycontext') >= 0) {
        req.action = 'read';
    } else if (req.url.toLowerCase().indexOf('/ngsi10/subscribecontext') >= 0) {
        req.action = 'subscribe';
    } else if (req.url.toLowerCase().indexOf('/ngsi9/registercontext') >= 0) {
        req.action = 'register';
    } else if (req.url.toLowerCase().indexOf('/nsgi9/discovercontextavailability') >= 0) {
        req.action = 'discover';
    } else if (req.url.toLowerCase().indexOf('/ngsi9/subscribecontextavailability') >= 0) {
        req.action = 'subscribe-availability';
    } else {
        logger.error('[ORION-PLUGIN-005] Action not found');

        error = new errors.ActionNotFound();
    }

    callback(error, req, res);
}

/**
 * Contenienve operation identification table. Each row of the table contains a convenience operation with three fields:
 * the method of the operation, a regular expression to identify the URL, and the action that operation should be
 * assigned.
 */
var convenienceOperations = [
    /* "Classic" NGSI9 operations */
    ['GET', /^\/(ngsi9|v1\/registry)\/contextEntities\/.+\/attributes$/, 'N/A'],
    ['POST', /^\/(ngsi9|v1\/registry)\/contextEntities\/.+\/attributes$/, 'N/A'],
    ['GET', /^\/(ngsi9|v1\/registry)\/contextEntities\/.+\/attributes\/.+/, 'discover'],
    ['POST', /^\/(ngsi9|v1\/registry)\/contextEntities\/.+\/attributes\/.+/, 'register'],
    ['GET', /^\/(ngsi9|v1\/registry)\/contextEntities\/.+\/attributeDomains\/.+/, 'discover'],
    ['POST', /^\/(ngsi9|v1\/registry)\/contextEntities\/.+\/attributeDomains\/.+/, 'register'],
    ['GET', /^\/(ngsi9|v1\/registry)\/contextEntities\/.+/, 'discover'],
    ['POST', /^\/(ngsi9|v1\/registry)\/contextEntities\/.+/, 'register'],
    ['GET', /^\/(ngsi9|v1\/registry)\/contextEntityTypes\/.+\/attributes$/, 'N/A'],
    ['POST', /^\/(ngsi9|v1\/registry)\/contextEntityTypes\/.+\/attributes$/, 'N/A'],
    ['GET', /^\/(ngsi9|v1\/registry)\/contextEntityTypes\/.+\/attributes\/.+/, 'discover'],
    ['POST', /^\/(ngsi9|v1\/registry)\/contextEntityTypes\/.+\/attributes\/.+/, 'register'],
    ['GET', /^\/(ngsi9|v1\/registry)\/contextEntityTypes\/.+\/attributeDomains\/.+/, 'discover'],
    ['POST', /^\/(ngsi9|v1\/registry)\/contextEntityTypes\/.+\/attributeDomains\/.+/, 'register'],
    ['GET', /^\/(ngsi9|v1\/registry)\/contextEntityTypes\/.+/, 'discover'],
    ['POST', /^\/(ngsi9|v1\/registry)\/contextEntityTypes\/.+/, 'register'],
    ['POST', /^\/(ngsi9|v1\/registry)\/contextAvailabilitySubscriptions$/, 'subscribe-availability'],
    ['PUT', /^\/(ngsi9|v1\/registry)\/contextAvailabilitySubscriptions\/.+/, 'subscribe-availability'],
    ['DELETE', /^\/(ngsi9|v1\/registry)\/contextAvailabilitySubscriptions\/.+/, 'subscribe-availability'],
    /* "Classic" NGSI10 operations */
    ['GET', /^\/(ngsi10|v1)\/contextEntities\/.+\/attributes$/, 'N/A'],
    ['PUT', /^\/(ngsi10|v1)\/contextEntities\/.+\/attributes$/, 'N/A'],
    ['POST', /^\/(ngsi10|v1)\/contextEntities\/.+\/attributes$/, 'N/A'],
    ['DELETE', /^\/(ngsi10|v1)\/contextEntities\/.+\/attributes$/, 'N/A'],
    ['GET', /^\/(ngsi10|v1)\/contextEntities\/.+\/attributes\/.+/, 'read'],
    ['POST', /^\/(ngsi10|v1)\/contextEntities\/.+\/attributes\/.+/, 'create'],
    ['PUT', /^\/(ngsi10|v1)\/contextEntities\/.+\/attributes\/.+/, 'update'],
    ['DELETE', /^\/(ngsi10|v1)\/contextEntities\/.+\/attributes\/.+/, 'delete'],
    ['GET', /^\/(ngsi10|v1)\/contextEntities\/.+\/attributes\/.+\/.+/, 'read'],
    ['PUT', /^\/(ngsi10|v1)\/contextEntities\/.+\/attributes\/.+\/.+/, 'update'],
    ['DELETE', /^\/(ngsi10|v1)\/contextEntities\/.+\/attributes\/.+\/.+/, 'delete'],
    ['GET', /^\/(ngsi10|v1)\/contextEntities\/.+\/attributeDomains\/.+/, 'read'],
    ['GET', /^\/(ngsi10|v1)\/contextEntities\/.+/, 'read'],
    ['PUT', /^\/(ngsi10|v1)\/contextEntities\/.+/, 'update'],
    ['POST', /^\/(ngsi10|v1)\/contextEntities\/.+/, 'create'],
    ['DELETE', /^\/(ngsi10|v1)\/contextEntities\/.+/, 'delete'],
    ['GET', /^\/(ngsi10|v1)\/contextEntityTypes\/.+\/attributes$/, 'N/A'],
    ['GET', /^\/(ngsi10|v1)\/contextEntityTypes\/.+\/attributes\/.+/, 'read'],
    ['GET', /^\/(ngsi10|v1)\/contextEntityTypes\/.+/, 'read'],
    ['GET', /^\/(ngsi10|v1)\/contextEntityTypes\/.+\/attributeDomains\/.+/, 'read'],
    ['POST', /^\/(ngsi10|v1)\/contextSubscriptions$/, 'suscribe'],
    ['PUT', /^\/(ngsi10|v1)\/contextSubscriptions\/.+/, 'suscribe'],
    ['DELETE', /^\/(ngsi10|v1)\/contextSubscriptions\/.+/, 'suscribe'],
    /* New operations in v1/ */
    ['GET', /^\/(ngsi10|v1)\/contextEntities/, 'read'],
    ['POST', /^\/(ngsi10|v1)\/contextEntities/, 'create'],
    ['GET', /^\/(ngsi10|v1)\/contextSubscriptions/, 'read'],
    ['GET', /^\/(ngsi10|v1)\/contextSubscriptions\/.+/, 'read'],
    ['GET', /^\/(ngsi10|v1)\/contextTypes/, 'read'],
    ['GET', /^\/(ngsi10|v1)\/contextTypes\/.+/, 'read']
];

/**
 * Determines what is the requested action based on the request information, knowing that it is a convenience operation.
 *
 * @param {Object} req           Incoming request.
 * @param {Object} res           Outgoing response.
 */
function inspectConvenience(req, res, callback) {
    for (var i = 0; i < convenienceOperations.length; i++) {
        if (req.method === convenienceOperations[i][0] &&
            req.url.match(convenienceOperations[i][1])) {
            req.action = convenienceOperations[i][2];
            callback(null, req, res);
            return;
        }
    }

    callback(new errors.ActionNotFound(), req, res);
}

/**
 * Determines if the request is a convenience operation.
 *
 * @param {Object} request          Incoming request.
 * @return {Boolean}                True if the request is a convenience operation and false otherwise.
 */
function isConvenienceOperation(request) {
    return request.url.toLowerCase().match(
            /^\/(ngsi9|ngsi10|v1|v1\/registry)\/(contextentities|contextentitytypes|contexttypes)/) ||
        request.url.toLowerCase().match(/\/(ngsi9|v1\/registry)\/contextavailabilitysubscriptions/) ||
        request.url.toLowerCase().match(/\/(ngsi10|v1)\/contextsubscriptions/);
}

/**
 * Middleware to calculate what Context Broker action has been received based on the path and the request payload.
 *
 * @param {Object} req           Incoming request.
 * @param {Object} res           Outgoing response.
 */
function extractCBAction(req, res, callback) {
    if (isConvenienceOperation(req)) {
        inspectConvenience(req, res, callback);
    } else if (req.url.toLowerCase().indexOf('/ngsi10/updatecontext') >= 0) {
        inspectBody(req, res, callback);
    } else {
        inspectUrl(req, res, callback);
    }
}

exports.extractCBAction = extractCBAction;
<commit_msg>FIX removing ngsi10 alternative for "pure" v1 operations<commit_after>/*
 * Copyright 2013 Telefonica Investigación y Desarrollo, S.A.U
 *
 * This file is part of fiware-orion-pep
 *
 * fiware-orion-pep is free software: you can redistribute it and/or
 * modify it under the terms of the GNU Affero General Public License as
 * published by the Free Software Foundation, either version 3 of the License,
 * or (at your option) any later version.
 *
 * fiware-orion-pep is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public
 * License along with fiware-orion-pep.
 * If not, seehttp://www.gnu.org/licenses/.
 *
 * For those usages not covered by the GNU Affero General Public License
 * please contact with::[daniel.moranjimenez@telefonica.com]
 */

'use strict';

var sax = require('sax'),
    logger = require('fiware-node-logger'),
    errors = require('../errors');

/**
 * Translates the updateAction value to the appropriate action name for the Access Control.
 *
 * @param {String} originalAction        String with the action name.
 * @return {String}                      The string representation of the action name for the Access Control.
 */
function translateAction(originalAction) {
    var action;

    switch (originalAction.toUpperCase()) {
        case 'APPEND':
            action = 'create';
            break;

        case 'UPDATE':
            action = 'update';
            break;

        case 'DELETE':
            action = 'delete';
            break;

        default:
            action = null;
    }

    logger.debug('Discovered action was: %s', action);

    return action;
}

/**
 * Extract the action from an XML body.
 *
 * @param {String} body          Raw string payload.
 */
function inspectBodyXML(body, callback) {
    var parser = sax.parser(true),
        readingAction = false,
        errorRaised = false,
        action;

    parser.onerror = function(e) {
        var error = new errors.WrongXmlPayload();

        logger.error('[ORION-PLUGIN-006] Wrong XML Payload. Parsing error: %s', e.message);

        if (!errorRaised) {
            errorRaised = true;
            error.moreInfo = e;
            callback(error);
        }
    };

    parser.ontext = function(t) {
        if (readingAction) {
            if (!action) {
                action = t;
            } else {
                action = action + t;
            }
        }
    };

    parser.onopentag = function(node) {
        if (node.name === 'updateAction') {
            readingAction = true;
        } else {
            readingAction = false;
        }
    };

    parser.onend = function() {
        if (action) {
            var translatedAction = translateAction(action.trim());

            if (translatedAction) {
                callback(null, translatedAction);
            } else {
                callback(new errors.WrongXmlPayload());
            }

        } else {
            logger.error('[ORION-PLUGIN-001] Wrong XML Payload. Action not found');

            callback(new errors.WrongXmlPayload());
        }
    };

    try {
        parser.write(body).close();
    } catch (e) {
        var error = new errors.WrongXmlPayload();

        logger.error('[ORION-PLUGIN-002] Wrong XML Payload. Parsing error: %s', e.message);
        callback(error);
    }
}

/**
 * Extract the action from a JSON body.
 *
 * @param {Object} body          Javascript Object with the parsed payload.
 */
function inspectBodyJSON(body, callback) {
    if (body && body.updateAction) {
        var translatedAction = translateAction(body.updateAction);

        if (translatedAction) {
            callback(null, translatedAction);
        } else {
            callback(new errors.WrongJsonPayload());
        }
    } else {
        logger.error('[ORION-PLUGIN-003] Wrong JSON Payload: updateAction element not found');

        callback(new errors.WrongJsonPayload());
    }
}

/**
 * Determines what kind of body to parse to calculate the action, and invoke the appropriate function.
 *
 * @param {Object} req           Incoming request.
 * @param {Object} res           Outgoing response.
 */
function inspectBody(req, res, callback) {
    var actionHandler = function actionHandler(error, action) {
        req.action = action;
        callback(error, req, res);
    };

    if (req.headers['content-type'] === 'application/json') {
        logger.debug('Inspecting JSON body to discover action: \n%s\n\n', JSON.stringify(req.body, null, 4));
        inspectBodyJSON(req.body, actionHandler);
    } else if (req.headers['content-type'] === 'application/xml' || req.headers['content-type'] === 'text/xml') {
        logger.debug('Inspecting XML body to discover action: \n%s\n\n', req.rawBody);
        inspectBodyXML(req.rawBody, actionHandler);
    } else {
        // TODO: raise error if the type is not recognized.
        logger.error('[ORION-PLUGIN-004] Unknown content type: %s', req.headers['content-type']);

        actionHandler(new errors.UnexpectedContentType(req.headers['content-type']));
    }
}

/**
 * Determines what is the requested action based on the URL.
 *
 * @param {Object}   req           Incoming request.
 * @param {Object}   res           Outgoing response.
 * @param {Function} callback      Callback for calling the next middleware. This callback should adhere to the
 *                                 following signature: callback(error, req, res) where req and res are the received
 *                                 parameters and error is an Error object in case the request should be rejected
 *                                 or null otherwise.
 */
function inspectUrl(req, res, callback) {
    var error = null;

    logger.debug('Extracting action from the URL "%s"', req.url);

    if (req.url.toLowerCase().indexOf('/ngsi10/querycontext') >= 0) {
        req.action = 'read';
    } else if (req.url.toLowerCase().indexOf('/ngsi10/subscribecontext') >= 0) {
        req.action = 'subscribe';
    } else if (req.url.toLowerCase().indexOf('/ngsi9/registercontext') >= 0) {
        req.action = 'register';
    } else if (req.url.toLowerCase().indexOf('/nsgi9/discovercontextavailability') >= 0) {
        req.action = 'discover';
    } else if (req.url.toLowerCase().indexOf('/ngsi9/subscribecontextavailability') >= 0) {
        req.action = 'subscribe-availability';
    } else {
        logger.error('[ORION-PLUGIN-005] Action not found');

        error = new errors.ActionNotFound();
    }

    callback(error, req, res);
}

/**
 * Contenienve operation identification table. Each row of the table contains a convenience operation with three fields:
 * the method of the operation, a regular expression to identify the URL, and the action that operation should be
 * assigned.
 */
var convenienceOperations = [
    /* "Classic" NGSI9 operations */
    ['GET', /^\/(ngsi9|v1\/registry)\/contextEntities\/.+\/attributes$/, 'N/A'],
    ['POST', /^\/(ngsi9|v1\/registry)\/contextEntities\/.+\/attributes$/, 'N/A'],
    ['GET', /^\/(ngsi9|v1\/registry)\/contextEntities\/.+\/attributes\/.+/, 'discover'],
    ['POST', /^\/(ngsi9|v1\/registry)\/contextEntities\/.+\/attributes\/.+/, 'register'],
    ['GET', /^\/(ngsi9|v1\/registry)\/contextEntities\/.+\/attributeDomains\/.+/, 'discover'],
    ['POST', /^\/(ngsi9|v1\/registry)\/contextEntities\/.+\/attributeDomains\/.+/, 'register'],
    ['GET', /^\/(ngsi9|v1\/registry)\/contextEntities\/.+/, 'discover'],
    ['POST', /^\/(ngsi9|v1\/registry)\/contextEntities\/.+/, 'register'],
    ['GET', /^\/(ngsi9|v1\/registry)\/contextEntityTypes\/.+\/attributes$/, 'N/A'],
    ['POST', /^\/(ngsi9|v1\/registry)\/contextEntityTypes\/.+\/attributes$/, 'N/A'],
    ['GET', /^\/(ngsi9|v1\/registry)\/contextEntityTypes\/.+\/attributes\/.+/, 'discover'],
    ['POST', /^\/(ngsi9|v1\/registry)\/contextEntityTypes\/.+\/attributes\/.+/, 'register'],
    ['GET', /^\/(ngsi9|v1\/registry)\/contextEntityTypes\/.+\/attributeDomains\/.+/, 'discover'],
    ['POST', /^\/(ngsi9|v1\/registry)\/contextEntityTypes\/.+\/attributeDomains\/.+/, 'register'],
    ['GET', /^\/(ngsi9|v1\/registry)\/contextEntityTypes\/.+/, 'discover'],
    ['POST', /^\/(ngsi9|v1\/registry)\/contextEntityTypes\/.+/, 'register'],
    ['POST', /^\/(ngsi9|v1\/registry)\/contextAvailabilitySubscriptions$/, 'subscribe-availability'],
    ['PUT', /^\/(ngsi9|v1\/registry)\/contextAvailabilitySubscriptions\/.+/, 'subscribe-availability'],
    ['DELETE', /^\/(ngsi9|v1\/registry)\/contextAvailabilitySubscriptions\/.+/, 'subscribe-availability'],
    /* "Classic" NGSI10 operations */
    ['GET', /^\/(ngsi10|v1)\/contextEntities\/.+\/attributes$/, 'N/A'],
    ['PUT', /^\/(ngsi10|v1)\/contextEntities\/.+\/attributes$/, 'N/A'],
    ['POST', /^\/(ngsi10|v1)\/contextEntities\/.+\/attributes$/, 'N/A'],
    ['DELETE', /^\/(ngsi10|v1)\/contextEntities\/.+\/attributes$/, 'N/A'],
    ['GET', /^\/(ngsi10|v1)\/contextEntities\/.+\/attributes\/.+/, 'read'],
    ['POST', /^\/(ngsi10|v1)\/contextEntities\/.+\/attributes\/.+/, 'create'],
    ['PUT', /^\/(ngsi10|v1)\/contextEntities\/.+\/attributes\/.+/, 'update'],
    ['DELETE', /^\/(ngsi10|v1)\/contextEntities\/.+\/attributes\/.+/, 'delete'],
    ['GET', /^\/(ngsi10|v1)\/contextEntities\/.+\/attributes\/.+\/.+/, 'read'],
    ['PUT', /^\/(ngsi10|v1)\/contextEntities\/.+\/attributes\/.+\/.+/, 'update'],
    ['DELETE', /^\/(ngsi10|v1)\/contextEntities\/.+\/attributes\/.+\/.+/, 'delete'],
    ['GET', /^\/(ngsi10|v1)\/contextEntities\/.+\/attributeDomains\/.+/, 'read'],
    ['GET', /^\/(ngsi10|v1)\/contextEntities\/.+/, 'read'],
    ['PUT', /^\/(ngsi10|v1)\/contextEntities\/.+/, 'update'],
    ['POST', /^\/(ngsi10|v1)\/contextEntities\/.+/, 'create'],
    ['DELETE', /^\/(ngsi10|v1)\/contextEntities\/.+/, 'delete'],
    ['GET', /^\/(ngsi10|v1)\/contextEntityTypes\/.+\/attributes$/, 'N/A'],
    ['GET', /^\/(ngsi10|v1)\/contextEntityTypes\/.+\/attributes\/.+/, 'read'],
    ['GET', /^\/(ngsi10|v1)\/contextEntityTypes\/.+/, 'read'],
    ['GET', /^\/(ngsi10|v1)\/contextEntityTypes\/.+\/attributeDomains\/.+/, 'read'],
    ['POST', /^\/(ngsi10|v1)\/contextSubscriptions$/, 'suscribe'],
    ['PUT', /^\/(ngsi10|v1)\/contextSubscriptions\/.+/, 'suscribe'],
    ['DELETE', /^\/(ngsi10|v1)\/contextSubscriptions\/.+/, 'suscribe'],
    /* New operations in v1/ (note that they don't use the "ngsi10" alternative in the pattern) */
    ['GET', /^\/v1\/contextEntities/, 'read'],
    ['POST', /^\/v1\/contextEntities/, 'create'],
    ['GET', /^\/v1\/contextSubscriptions/, 'read'],
    ['GET', /^\/v1\/contextSubscriptions\/.+/, 'read'],
    ['GET', /^\/v1\/contextTypes/, 'read'],
    ['GET', /^\/v1\/contextTypes\/.+/, 'read']
];

/**
 * Determines what is the requested action based on the request information, knowing that it is a convenience operation.
 *
 * @param {Object} req           Incoming request.
 * @param {Object} res           Outgoing response.
 */
function inspectConvenience(req, res, callback) {
    for (var i = 0; i < convenienceOperations.length; i++) {
        if (req.method === convenienceOperations[i][0] &&
            req.url.match(convenienceOperations[i][1])) {
            req.action = convenienceOperations[i][2];
            callback(null, req, res);
            return;
        }
    }

    callback(new errors.ActionNotFound(), req, res);
}

/**
 * Determines if the request is a convenience operation.
 *
 * @param {Object} request          Incoming request.
 * @return {Boolean}                True if the request is a convenience operation and false otherwise.
 */
function isConvenienceOperation(request) {
    return request.url.toLowerCase().match(
            /^\/(ngsi9|ngsi10|v1|v1\/registry)\/(contextentities|contextentitytypes|contexttypes)/) ||
        request.url.toLowerCase().match(/\/(ngsi9|v1\/registry)\/contextavailabilitysubscriptions/) ||
        request.url.toLowerCase().match(/\/(ngsi10|v1)\/contextsubscriptions/);
}

/**
 * Middleware to calculate what Context Broker action has been received based on the path and the request payload.
 *
 * @param {Object} req           Incoming request.
 * @param {Object} res           Outgoing response.
 */
function extractCBAction(req, res, callback) {
    if (isConvenienceOperation(req)) {
        inspectConvenience(req, res, callback);
    } else if (req.url.toLowerCase().indexOf('/ngsi10/updatecontext') >= 0) {
        inspectBody(req, res, callback);
    } else {
        inspectUrl(req, res, callback);
    }
}

exports.extractCBAction = extractCBAction;
<|endoftext|>


<commit_before>/**
 * <TextareaAutosize />
 */

import React from 'react';
import calculateNodeHeight from './calculateNodeHeight';

const emptyFunction = function() {};

export default class TextareaAutosize extends React.Component {

  static propTypes = {
    /**
     * Current textarea value.
     */
    value: React.PropTypes.string,

    /**
     * Callback on value change.
     */
    onChange: React.PropTypes.func,

    /**
     * Callback on height changes.
     */
    onHeightChange: React.PropTypes.func,

    /**
     * Try to cache DOM measurements performed by component so that we don't
     * touch DOM when it's not needed.
     *
     * This optimization doesn't work if we dynamically style <textarea />
     * component.
     */
    useCacheForDOMMeasurements: React.PropTypes.bool,

    /**
     * Minimal numbder of rows to show.
     */
    rows: React.PropTypes.number,

    /**
     * Alias for `rows`.
     */
    minRows: React.PropTypes.number,

    /**
     * Maximum number of rows to show.
     */
    maxRows: React.PropTypes.number
  }

  static defaultProps = {
    onChange: emptyFunction,
    onHeightChange: emptyFunction,
    useCacheForDOMMeasurements: false
  }

  constructor(props) {
    super(props);
    this.state = {
      height: null,
      minHeight: -Infinity,
      maxHeight: Infinity
    };
    this._onNextFrameActionId = null;
    this._rootDOMNode = null;
    this._onChange = this._onChange.bind(this);
    this._resizeComponent = this._resizeComponent.bind(this);
    this._onRootDOMNode = this._onRootDOMNode.bind(this);
  }

  render() {
    let {valueLink, onChange, ...props} = this.props;
    props = {...props};
    if (typeof valueLink === 'object') {
      props.value = this.props.valueLink.value;
    }
    props.style = {
      ...props.style,
      height: this.state.height
    };
    let maxHeight = Math.max(
      props.style.maxHeight ? props.style.maxHeight : Infinity,
      this.state.maxHeight);
    if (maxHeight < this.state.height) {
      props.style.overflow = 'hidden';
    }
    return (
      <textarea
        {...props}
        onChange={this._onChange}
        ref={this._onRootDOMNode}
        />
    );
  }

  componentDidMount() {
    this._resizeComponent();
    window.addEventListener('resize', this._resizeComponent);
  }

  componentWillReceiveProps() {
    // Re-render with the new content then recalculate the height as required.
    this._clearNextFrame();
    this._onNextFrameActionId = onNextFrame(this._resizeComponent);
  }

  componentDidUpdate(prevProps, prevState) {
    // Invoke callback when old height does not equal to new one.
    if (this.state.height !== prevState.height) {
      this.props.onHeightChange(this.state.height);
    }
  }

  componentWillUnmount() {
    // Remove any scheduled events to prevent manipulating the node after it's
    // been unmounted.
    this._clearNextFrame();
    window.removeEventListener('resize', this._resizeComponent);
  }

  _clearNextFrame() {
    if (this._onNextFrameActionId) {
      clearNextFrameAction(this._onNextFrameActionId);
    }
  }

  _onRootDOMNode(node) {
    this._rootDOMNode = node;
  }

  _onChange(e) {
    this._resizeComponent();
    let {valueLink, onChange} = this.props;
    if (valueLink) {
      valueLink.requestChange(e.target.value);
    } else {
      onChange(e);
    }
  }

  _resizeComponent() {
    let {useCacheForDOMMeasurements} = this.props;
    this.setState(calculateNodeHeight(
      this._rootDOMNode,
      useCacheForDOMMeasurements,
      this.props.rows || this.props.minRows,
      this.props.maxRows));
  }

  /**
   * Read the current value of <textarea /> from DOM.
   */
  get value(): string {
    return this._rootDOMNode.value;
  }

  /**
   * Set the current value of <textarea /> DOM node.
   */
  set value(val) {
    this._rootDOMNode.value = val;
  }

  /**
   * Put focus on a <textarea /> DOM element.
   */
  focus() {
    this._rootDOMNode.focus();
  }

  /**
   * Shifts focus away from a <textarea /> DOM element.
   */
  blur() {
    this._rootDOMNode.blur();
  }

}

function onNextFrame(cb) {
  if (window.requestAnimationFrame) {
    return window.requestAnimationFrame(cb);
  }
  return window.setTimeout(cb, 1);
}

function clearNextFrameAction(nextFrameId) {
  if (window.cancelAnimationFrame) {
    window.cancelAnimationFrame(nextFrameId);
  } else {
    window.clearTimeout(nextFrameId);
  }
}
<commit_msg>Update TextareaAutosize.js<commit_after>/**
 * <TextareaAutosize />
 */

import React from 'react';
import calculateNodeHeight from './calculateNodeHeight';

const emptyFunction = function() {};

export default class TextareaAutosize extends React.Component {

  static propTypes = {
    /**
     * Current textarea value.
     */
    value: React.PropTypes.string,

    /**
     * Callback on value change.
     */
    onChange: React.PropTypes.func,

    /**
     * Callback on height changes.
     */
    onHeightChange: React.PropTypes.func,

    /**
     * Try to cache DOM measurements performed by component so that we don't
     * touch DOM when it's not needed.
     *
     * This optimization doesn't work if we dynamically style <textarea />
     * component.
     */
    useCacheForDOMMeasurements: React.PropTypes.bool,

    /**
     * Minimal numbder of rows to show.
     */
    rows: React.PropTypes.number,

    /**
     * Alias for `rows`.
     */
    minRows: React.PropTypes.number,

    /**
     * Maximum number of rows to show.
     */
    maxRows: React.PropTypes.number
  }

  static defaultProps = {
    onChange: emptyFunction,
    onHeightChange: emptyFunction,
    useCacheForDOMMeasurements: false
  }

  constructor(props) {
    super(props);
    this.state = {
      height: null,
      minHeight: -Infinity,
      maxHeight: Infinity
    };
    this._onNextFrameActionId = null;
    this._rootDOMNode = null;
    this._onChange = this._onChange.bind(this);
    this._resizeComponent = this._resizeComponent.bind(this);
    this._onRootDOMNode = this._onRootDOMNode.bind(this);
  }

  render() {
    let {valueLink, onChange, ...props} = this.props;
    props = {...props};
    if (typeof valueLink === 'object') {
      props.value = this.props.valueLink.value;
    }
    props.style = {
      ...props.style,
      height: this.state.height
    };
    let maxHeight = Math.max(
      props.style.maxHeight ? props.style.maxHeight : Infinity,
      this.state.maxHeight);
    if (maxHeight < this.state.height) {
      props.style.overflow = 'hidden';
    }
    return (
      <textarea
        {...props}
        onChange={this._onChange}
        ref={this._onRootDOMNode}
        />
    );
  }

  componentDidMount() {
    this._resizeComponent();
    window.addEventListener('resize', this._resizeComponent);
  }

  componentWillReceiveProps() {
    // Re-render with the new content then recalculate the height as required.
    this._clearNextFrame();
    this._onNextFrameActionId = onNextFrame(this._resizeComponent);
  }

  componentDidUpdate(prevProps, prevState) {
    // Invoke callback when old height does not equal to new one.
    if (this.state.height !== prevState.height) {
      this.props.onHeightChange(this.state.height);
    }
  }

  componentWillUnmount() {
    // Remove any scheduled events to prevent manipulating the node after it's
    // been unmounted.
    this._clearNextFrame();
    window.removeEventListener('resize', this._resizeComponent);
  }

  _clearNextFrame() {
    if (this._onNextFrameActionId) {
      clearNextFrameAction(this._onNextFrameActionId);
    }
  }

  _onRootDOMNode(node) {
    this._rootDOMNode = node;
  }

  _onChange(e) {
    this._resizeComponent();
    let {valueLink, onChange} = this.props;
    if (valueLink) {
      valueLink.requestChange(e.target.value);
    } else {
      onChange(e);
    }
  }

  _resizeComponent() {
    let {useCacheForDOMMeasurements} = this.props;
    this.setState(calculateNodeHeight(
      this._rootDOMNode,
      useCacheForDOMMeasurements,
      this.props.rows || this.props.minRows,
      this.props.maxRows));
  }

  /**
   * Read the current value of <textarea /> from DOM.
   */
  get value(): string {
    return this._rootDOMNode.value;
  }

  /**
   * Set the current value of <textarea /> DOM node.
   */
  set value(val) {
    this._rootDOMNode.value = val;
  }

  /**
   * Read the current selectionStart of <textarea /> from DOM.
   */
  get selectionStart(): string {
    return this._rootDOMNode.selectionStart;
  }

  /**
   * Set the current selectionStart of <textarea /> DOM node.
   */
  set selectionStart(val) {
    this._rootDOMNode.selectionStart = val;
  }

  /**
   * Read the current selectionEnd of <textarea /> from DOM.
   */
  get selectionEnd(): string {
    return this._rootDOMNode.selectionEnd;
  }

  /**
   * Set the current selectionEnd of <textarea /> DOM node.
   */
  set selectionEnd(val) {
    this._rootDOMNode.selectionEnd = val;
  }

  /**
   * Put focus on a <textarea /> DOM element.
   */
  focus() {
    this._rootDOMNode.focus();
  }

  /**
   * Shifts focus away from a <textarea /> DOM element.
   */
  blur() {
    this._rootDOMNode.blur();
  }

}

function onNextFrame(cb) {
  if (window.requestAnimationFrame) {
    return window.requestAnimationFrame(cb);
  }
  return window.setTimeout(cb, 1);
}

function clearNextFrameAction(nextFrameId) {
  if (window.cancelAnimationFrame) {
    window.cancelAnimationFrame(nextFrameId);
  } else {
    window.clearTimeout(nextFrameId);
  }
}
<|endoftext|>


<commit_before>"use strict";
/**
 * Storm Ajax Json Communicator
 * Client-side code
 */

var Comm_ServerSide = {
    busy: false,
    currentURL: null,
    staticData: {},
    history: (window.History.Adapter === undefined ?window.history:window.History),
    /* Define hook bind posts */
    hooks: {
        /* Called when busy gets set to true */
        'onBusy': [],
        /* Called when busy gets set to false */
        'onNotBusy': [],
        /* Called after an successful AJAX call, data is passed */
        'onSuccess': [],
        /* Called after an unsuccessful ajax call, data is passed */
        'onError': [],
        /* Called when the load method was successful, data is passed */
        'onLoad': [],
        /* Called when the load method was unsuccessful, data is passed */
        'onLoadError': [],
        /* Called when the form method was successful, form object and data passed */
        'onFormSuccess': [],
        /* Called when the form method was unsuccessful, form object and data passed */
        'onFormUnsuccessful': [],
        /* Called when one or more flash objects have been received, an array of flash(s) is passed */
        'onFlash': []
    }
};

Comm_ServerSide.setBusy = function (busy) {
    if (this.busy !== busy) {
        this.busy = busy;
        this.apply((busy ?'onBusy':'onNotBusy'));
    }

};

/**
 *
 * @param string|jqueryObject form Provide the forms name if passing a string
 * @param string url
 * @param object data
 * @param callable callback
 * @returns undefined
 */
Comm_ServerSide.form = function (form, url, data, callback) {
    var ctx = this;
    if (form !== null && typeof form !== 'object') {
        form = $('form[name=\''+form.replace('\'', '\\\'')+'\']');
    }
    if (url === undefined || url === null) {
        url = form.attr('action');
    }
    if (data === null || data === undefined) {
        data = {};
    }

    var fields = form.serializeArray();
    $.each(fields, function (ix, ob) {
        data[ob.name] = ob.value;
    });

    this.ajax(
        url,
        data,
        function (data) {
            if (callback !== undefined) {
                callback(data);
            }
            ctx.apply('onFormSuccess', [ form, data ]);
        },
        function (data) {
            ctx.apply('onFormError', [ form, data ]);
        }
    );
};

/**
 *
 * @param string url
 * @param object data
 * @param callable callback
 * @returns undefined
 */
Comm_ServerSide.load = function (url, data, callback) {
    this.currentURL = url;
    this.history.pushState(null, null, url);
    var ctx = this;
    this.ajax(
        url,
        data,
        function (data) {
            if (callback !== undefined) {
                callback(data);
            }
            ctx.apply('onLoad', [ data ]);
        },
        function (data) {
            ctx.apply('onLoadError', [ data ]);
        }
    );
};

/**
 *
 * @param callable callback
 * @returns undefined
 */
Comm_ServerSide.reload = function (callback) {
    this.load(this.currentURL, null, callback);
};

/**
 *
 * @param object callback
 * @returns undefined
 */
Comm_ServerSide.findFlash = function (data) {
    if (data.flash !== undefined && data.flash.length > 0) {
        this.apply('onFlash', [ data.flash ]);
    }
};

/**
 *
 * @param object callback
 * @returns undefined
 */
Comm_ServerSide.findRedirect = function (data) {
    if (data.redirect !== undefined && data.redirect.length > 0) {
        this.load(data.redirect);
    }
};

/**
 *
 * @param string url
 * @param object data
 * @param callable successCallback
 * @param callable errorCallback
 * @returns undefined
 */
Comm_ServerSide.ajax = function (url, data, successCallback, errorCallback) {
    if (this.busy === true) {
        return null;
    }
    this.setBusy(true);
    var ctx = this;
    if (data === undefined || data === null) {
        data = this.staticData;
    } else {
        data = $.extend({}, this.staticData, data);
    }
    $.ajax({
        url: url,
        type: 'POST',
        data: JSON.stringify(data),
        contentType: 'application/json; charset=utf-8',
        dataType: 'json',
        context: ctx,
        success: function (data) {
            this.setBusy(false);
            successCallback(data);
            this.findFlash(data);
            this.findRedirect(data);
            this.apply('onSuccess', [ data ]);
        },
        error: function (data) {
            this.setBusy(false);
            errorCallback(data);
            this.findFlash(data);
            this.findRedirect(data);
            this.apply('onError', [ data ]);
        }
    });
};

/**
 *
 * @param string event
 * @param array param
 * @returns undefined
 */
Comm_ServerSide.apply = function (event, args) {
    if (args === undefined || args === null) {
        args = [];
    }
    if (this.hooks[event+''] !== undefined) {
        var funcs = this.hooks[event+''];
        for(var i = 0;i < funcs.length;i++) {
            funcs[i].apply(null, args);
        }
    }
};

/**
 *
 * @param string event
 * @param callable callback
 * @returns undefined
 */
Comm_ServerSide.hook = function (event, callback) {
    if (this.hooks[event+''] !== undefined) {
        this.hooks[event+''].push(callback);
    }
};

(function(window,undefined){
    if (window.History.Adapter !== undefined) {
        History.Adapter.bind(window,'statechange',function () {
            var url = History.getState().hash;
            if (Comm_ServerSide.currentURL !== url) {
               Comm_ServerSide.load(url);
            }
        });
    } else {
        window.onpopstate = function (event) {
            var hostname = document.location.protocol + '//' + document.location.hostname;
            var url = document.location.href.replace(hostname, '');
            if (Comm_ServerSide.currentURL !== url) {
               Comm_ServerSide.load(url);
            }
        };
    }
})(window);<commit_msg>Fixed redirect is null error<commit_after>"use strict";
/**
 * Storm Ajax Json Communicator
 * Client-side code
 */

var Comm_ServerSide = {
    busy: false,
    currentURL: null,
    staticData: {},
    history: (window.History.Adapter === undefined ?window.history:window.History),
    /* Define hook bind posts */
    hooks: {
        /* Called when busy gets set to true */
        'onBusy': [],
        /* Called when busy gets set to false */
        'onNotBusy': [],
        /* Called after an successful AJAX call, data is passed */
        'onSuccess': [],
        /* Called after an unsuccessful ajax call, data is passed */
        'onError': [],
        /* Called when the load method was successful, data is passed */
        'onLoad': [],
        /* Called when the load method was unsuccessful, data is passed */
        'onLoadError': [],
        /* Called when the form method was successful, form object and data passed */
        'onFormSuccess': [],
        /* Called when the form method was unsuccessful, form object and data passed */
        'onFormUnsuccessful': [],
        /* Called when one or more flash objects have been received, an array of flash(s) is passed */
        'onFlash': []
    }
};

Comm_ServerSide.setBusy = function (busy) {
    if (this.busy !== busy) {
        this.busy = busy;
        this.apply((busy ?'onBusy':'onNotBusy'));
    }

};

/**
 *
 * @param string|jqueryObject form Provide the forms name if passing a string
 * @param string url
 * @param object data
 * @param callable callback
 * @returns undefined
 */
Comm_ServerSide.form = function (form, url, data, callback) {
    var ctx = this;
    if (form !== null && typeof form !== 'object') {
        form = $('form[name=\''+form.replace('\'', '\\\'')+'\']');
    }
    if (url === undefined || url === null) {
        url = form.attr('action');
    }
    if (data === null || data === undefined) {
        data = {};
    }

    var fields = form.serializeArray();
    $.each(fields, function (ix, ob) {
        data[ob.name] = ob.value;
    });

    this.ajax(
        url,
        data,
        function (data) {
            if (callback !== undefined) {
                callback(data);
            }
            ctx.apply('onFormSuccess', [ form, data ]);
        },
        function (data) {
            ctx.apply('onFormError', [ form, data ]);
        }
    );
};

/**
 *
 * @param string url
 * @param object data
 * @param callable callback
 * @returns undefined
 */
Comm_ServerSide.load = function (url, data, callback) {
    this.currentURL = url;
    this.history.pushState(null, null, url);
    var ctx = this;
    this.ajax(
        url,
        data,
        function (data) {
            if (callback !== undefined) {
                callback(data);
            }
            ctx.apply('onLoad', [ data ]);
        },
        function (data) {
            ctx.apply('onLoadError', [ data ]);
        }
    );
};

/**
 *
 * @param callable callback
 * @returns undefined
 */
Comm_ServerSide.reload = function (callback) {
    this.load(this.currentURL, null, callback);
};

/**
 *
 * @param object callback
 * @returns undefined
 */
Comm_ServerSide.findFlash = function (data) {
    if (data.flash !== undefined && data.flash.length > 0) {
        this.apply('onFlash', [ data.flash ]);
    }
};

/**
 *
 * @param object callback
 * @returns undefined
 */
Comm_ServerSide.findRedirect = function (data) {
    if (data.redirect !== undefined && data.redirect !== null) {
        this.load(data.redirect);
    }
};

/**
 *
 * @param string url
 * @param object data
 * @param callable successCallback
 * @param callable errorCallback
 * @returns undefined
 */
Comm_ServerSide.ajax = function (url, data, successCallback, errorCallback) {
    if (this.busy === true) {
        return null;
    }
    this.setBusy(true);
    var ctx = this;
    if (data === undefined || data === null) {
        data = this.staticData;
    } else {
        data = $.extend({}, this.staticData, data);
    }
    $.ajax({
        url: url,
        type: 'POST',
        data: JSON.stringify(data),
        contentType: 'application/json; charset=utf-8',
        dataType: 'json',
        context: ctx,
        success: function (data) {
            this.setBusy(false);
            successCallback(data);
            this.findFlash(data);
            this.findRedirect(data);
            this.apply('onSuccess', [ data ]);
        },
        error: function (data) {
            this.setBusy(false);
            errorCallback(data);
            this.findFlash(data);
            this.findRedirect(data);
            this.apply('onError', [ data ]);
        }
    });
};

/**
 *
 * @param string event
 * @param array param
 * @returns undefined
 */
Comm_ServerSide.apply = function (event, args) {
    if (args === undefined || args === null) {
        args = [];
    }
    if (this.hooks[event+''] !== undefined) {
        var funcs = this.hooks[event+''];
        for(var i = 0;i < funcs.length;i++) {
            funcs[i].apply(null, args);
        }
    }
};

/**
 *
 * @param string event
 * @param callable callback
 * @returns undefined
 */
Comm_ServerSide.hook = function (event, callback) {
    if (this.hooks[event+''] !== undefined) {
        this.hooks[event+''].push(callback);
    }
};

(function(window,undefined){
    if (window.History.Adapter !== undefined) {
        History.Adapter.bind(window,'statechange',function () {
            var url = History.getState().hash;
            if (Comm_ServerSide.currentURL !== url) {
               Comm_ServerSide.load(url);
            }
        });
    } else {
        window.onpopstate = function (event) {
            var hostname = document.location.protocol + '//' + document.location.hostname;
            var url = document.location.href.replace(hostname, '');
            if (Comm_ServerSide.currentURL !== url) {
               Comm_ServerSide.load(url);
            }
        };
    }
})(window);<|endoftext|>