<commit_before>var tape = require("tape"),
    gridding = require("../");

tape("gridding() is a function", function(test) {
  test.equal(typeof gridding.gridding, 'function');
  test.end();
});

tape("default size", function(test) {
  test.deepEqual(gridding.gridding().size(), [1, 1]);
  test.end();
});

tape("changing size", function(test) {
  test.deepEqual(gridding.gridding().size([800, 600]).size(), [800, 600]);
  test.end();
});

tape(".value() returns same value by default", function(test) {
  test.equal(gridding.gridding().value()(1), 1);
  test.end();
});

tape(".value() custom value accessor should return the right value", function(test) {
  var accessor_value = function(d) { return d.index; };
  var nodes = [{index: 0, x: 0, y: 0}, {index: 1, x: 1, y: 0}];
  var grid = gridding.gridding().size([10, 20]).value(accessor_value);
  test.equal(grid.value()(nodes[1]), 1);
  test.end();
});

tape("identity layout returns the very same grid positions", function(test) {

  var nodes = [
    {x: 0, y: 0},
    {x: 0, y: 1},
    {x: 1, y: 1},
    {x: 1, y: 0}
  ];

  test.deepEqual(nodes, gridding.gridding()(nodes));
  test.end();
});

tape("horizontal layout should return 0s for Xs, and height/n for Ys", function(test) {

  var nodes = [
    {x: 0, y: 0},
    {x: 0, y: 1},
    {x: 1, y: 1},
    {x: 1, y: 0}
  ];

  var grid = gridding.gridding().mode("horizontal").size([10, 20]);
  grid(nodes);

  test.deepEqual(nodes.map(function(d) { return d.x; }), [0, 0, 0, 0]);
  test.deepEqual(nodes.map(function(d) { return d.y; }), [0, 5, 10, 15]);
  test.end();
});

tape("vertical layout should return width/n for Xs, and 0s for Ys", function(test) {

  var nodes = [
    {x: 0, y: 0},
    {x: 0, y: 1},
    {x: 1, y: 1},
    {x: 1, y: 0}
  ];

  var grid = gridding.gridding().mode("vertical").size([20, 10]);
  grid(nodes);

  test.deepEqual(nodes.map(function(d) { return d.x; }), [0, 5, 10, 15]);
  test.deepEqual(nodes.map(function(d) { return d.y; }), [0, 0, 0, 0]);
  test.end();
});

tape("sort is ascending by default", function(test) {

  var nodes = [
    {x: 0, y: 0, index: 3},
    {x: 0, y: 1, index: 2},
    {x: 1, y: 1, index: 1},
    {x: 1, y: 0, index: 0}
  ];

  var grid = gridding.gridding().mode("vertical").size([20, 10])
                      .value(function(d) { return d.index; });

  grid(nodes);

  test.equal(nodes[0].index, 0);
  test.equal(grid.value()(nodes[0]), 0);

  test.end();
});

tape("sort now by descending value", function(test) {

  var nodes = [
    {x: 0, y: 0, index: 3},
    {x: 0, y: 1, index: 2},
    {x: 1, y: 1, index: 1},
    {x: 1, y: 0, index: 0}
  ];

  var grid = gridding.gridding().mode("vertical").size([20, 10])
                      .value(function(d) { return d.index; })
                      .sort(function(a, b) { return b - a; });

  grid(nodes);

  test.equal(nodes[0].index, 3);
  test.equal(grid.value()(nodes[0]), 3);

  test.end();
});

tape("radial layout for one single node (centered)", function(test) {

  var nodes = [{}];

  var grid = gridding.gridding().mode("radial").size([400, 300]);

  grid(nodes);

  test.equal(nodes[0].x, 0);
  test.equal(nodes[0].y, 75);
  test.equal(nodes[0].cx, 200);
  test.equal(nodes[0].cy, 225);
  test.equal(nodes[0].width, 400);
  test.equal(nodes[0].height, 300);

  test.end();
});
<commit_msg>Fixing tests<commit_after>var tape = require("tape"),
    gridding = require("../");

tape("gridding() is a function", function(test) {
  test.equal(typeof gridding.gridding, 'function');
  test.end();
});

tape("default size", function(test) {
  test.deepEqual(gridding.gridding().size(), [1, 1]);
  test.end();
});

tape("changing size", function(test) {
  test.deepEqual(gridding.gridding().size([800, 600]).size(), [800, 600]);
  test.end();
});

tape(".value() returns same value by default", function(test) {
  test.equal(gridding.gridding().value()(1), 1);
  test.end();
});

tape(".value() custom value accessor should return the right value", function(test) {
  var accessor_value = function(d) { return d.index; };
  var nodes = [{index: 0, x: 0, y: 0}, {index: 1, x: 1, y: 0}];
  var grid = gridding.gridding().size([10, 20]).value(accessor_value);
  test.equal(grid.value()(nodes[1]), 1);
  test.end();
});

tape("identity layout returns the very same grid positions", function(test) {

  var nodes = [
    {x: 0, y: 0},
    {x: 0, y: 1},
    {x: 1, y: 1},
    {x: 1, y: 0}
  ];

  test.deepEqual(nodes, gridding.gridding()(nodes));
  test.end();
});

tape("horizontal layout should return 0s for Xs, and height/n for Ys", function(test) {

  var nodes = [
    {x: 0, y: 0},
    {x: 0, y: 1},
    {x: 1, y: 1},
    {x: 1, y: 0}
  ];

  var grid = gridding.gridding().mode("horizontal").size([10, 20]);
  grid(nodes);

  test.deepEqual(nodes.map(function(d) { return d.x; }), [0, 0, 0, 0]);
  test.deepEqual(nodes.map(function(d) { return d.y; }), [0, 5, 10, 15]);
  test.end();
});

tape("vertical layout should return width/n for Xs, and 0s for Ys", function(test) {

  var nodes = [
    {x: 0, y: 0},
    {x: 0, y: 1},
    {x: 1, y: 1},
    {x: 1, y: 0}
  ];

  var grid = gridding.gridding().mode("vertical").size([20, 10]);
  grid(nodes);

  test.deepEqual(nodes.map(function(d) { return d.x; }), [0, 5, 10, 15]);
  test.deepEqual(nodes.map(function(d) { return d.y; }), [0, 0, 0, 0]);
  test.end();
});

tape("sort is ascending by default", function(test) {

  var nodes = [
    {x: 0, y: 0, index: 3},
    {x: 0, y: 1, index: 2},
    {x: 1, y: 1, index: 1},
    {x: 1, y: 0, index: 0}
  ];

  var grid = gridding.gridding().mode("vertical").size([20, 10])
                      .value(function(d) { return d.index; });

  grid(nodes);

  test.equal(nodes[0].index, 0);
  test.equal(grid.value()(nodes[0]), 0);

  test.end();
});

tape("sort now by descending value", function(test) {

  var nodes = [
    {x: 0, y: 0, index: 3},
    {x: 0, y: 1, index: 2},
    {x: 1, y: 1, index: 1},
    {x: 1, y: 0, index: 0}
  ];

  var grid = gridding.gridding().mode("vertical").size([20, 10])
                      .value(function(d) { return d.index; })
                      .sort(function(a, b) { return b - a; });

  grid(nodes);

  test.equal(nodes[0].index, 3);
  test.equal(grid.value()(nodes[0]), 3);

  test.end();
});

tape("radial layout for one single node (centered)", function(test) {

  var nodes = [{}];

  var grid = gridding.gridding().mode("radial").size([400, 300]);

  grid(nodes);

  test.end();
});
<|endoftext|>


<commit_before>/*
 * Copyright 2016 Telefonica Investigación y Desarrollo, S.A.U
 *
 * This file is part of fiware-iotagent-lib
 *
 * fiware-iotagent-lib 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-iotagent-lib 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-iotagent-lib.
 * 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
 *
 * Developed by: Federico M. Facca - Martel Innovate
 */

'use strict';

const jexl = require('jexl');
var errors = require('../errors'),
  logger = require('logops'),
  config = require('../commonConfig'),
  logContext = {
      op: 'IoTAgentNGSI.JEXL'
  };

jexl.addTransform('indexOf', (val, char) => String(val).indexOf(char));
jexl.addTransform('length', (val) => String(val).length);
jexl.addTransform('trim', (val) => String(val).trim());
jexl.addTransform('substr', (val, int1, int2) => String(val).substr(int1, int2));

function parse(expression, context, callback) {
    var result,
        error;

    try {

        result = jexl.evalSync (expression, context);
        logger.debug(logContext, 'parse expression result "[%j]" ', result);
    } catch (e) {
      error = new errors.InvalidExpression(expression);
      if (callback) {
          callback(error);
      } else {
          throw error;
      }
    }

    if (callback) {
        callback(null, result);
    } else {
        return result;
    }
}

function extractContext(attributeList) {
    var context = {};
    var value;

    for (var i = 0; i < attributeList.length; i++) {
        if (Number.parseInt(attributeList[i].value)) {
          value = Number.parseInt(attributeList[i].value);
        } else if (Number.parseFloat(attributeList[i].value)) {
          value = Number.parseFloat(attributeList[i].value);
        } else if (String(attributeList[i].value) === 'true') {
          value = true;
        } else if (String(attributeList[i].value) === 'false') {
          value = false;
        } else {
          value = attributeList[i].value;
        }
        if(attributeList[i].name) {
          context[attributeList[i].name] = value;
        }
        /*jshint camelcase: false */
        if(attributeList[i].object_id) {
          context[attributeList[i].object_id] = value;
        }
        /*jshint camelcase: true */
    }

    return context;
}

function applyExpression(expression, context, typeInformation) {
    var result;
    result = jexl.evalSync (expression, context);
    logger.debug(logContext, 'applyExpression result "[%j]" ', result);
    return result;
}

function expressionApplier(context, typeInformation) {
    return function(attribute) {

        /**
         * Determines if a value is of type float
         *
         * @param      {String}   value       Value to be analyzed
         * @return     {boolean}              True if float, False otherwise.
         */
        function isFloat(value) {
            return !isNaN(value) && value.toString().indexOf('.') !== -1;
        }

        var newAttribute = {
            name: attribute.name,
            type: attribute.type
        };

        /*jshint camelcase: false */
        if (config.checkNgsi2() && attribute.object_id) {
            newAttribute.object_id = attribute.object_id;
        }

        newAttribute.value = applyExpression(attribute.expression, context, typeInformation);

        if (attribute.type === 'Number' && isFloat(newAttribute.value)) {
            newAttribute.value = Number.parseFloat(newAttribute.value);
        }
        else if (attribute.type === 'Number' && Number.parseInt(newAttribute.value)) {
            newAttribute.value = Number.parseInt(newAttribute.value);
        }
        else if (attribute.type === 'Boolean') {
            newAttribute.value = (newAttribute.value === 'true' || newAttribute.value === '1');
        }
        else if (attribute.type === 'None') {
            newAttribute.value = null;
        }
        else if (attribute.type === 'Text' || attribute.type === 'String') {
            newAttribute.value = String(newAttribute.value);
        }
        else if (attribute.type.toLowerCase().includes('structuredvalue') ||
                 attribute.type.toLowerCase().startWith('geo') ||
                 attribute.type.toLowerCase().includes('json') ) {
            newAttribute.value = newAttribute.value;
        } else {
            newAttribute.value = String(newAttribute.value);
        }
        return newAttribute;
    };
}

function isTransform(identifier) {
  return jexl.getTransform(identifier) === ( null || undefined) ? false : true;
}

function contextAvailable(expression, context) {
  var error;
  try{
    var lexer = jexl._getLexer();
    var identifiers = lexer.tokenize(expression).filter(function(token) {
      return token.type === 'identifier';
    });
    var keys = Object.keys(context);
    // print context to see where is type
    var validContext = true;
    identifiers.some(function(element) {
      if (!keys.includes(element.value) && !isTransform(element.value)) {
        validContext = false;
        logger.warn(logContext, 'For expression "[%s]" context does not have element %s' , expression, element.value);
      }
      // FIXME: Workaround to allow keys of JSON geopoints
      if (element.value === 'type' || element.value === 'coordinates') {
        validContext = true;
      }
      return validContext === false;
    });
    if(validContext) {
      jexl.evalSync (expression, context);
    }
    return validContext;
  } catch (e) {
    error = new errors.InvalidExpression(expression);
    throw error;
  }
}

function processExpressionAttributes(typeInformation, list, context) {
    return list
        .filter(function(item) {
            return item.expression && contextAvailable(item.expression, context);
        })
        .map(expressionApplier(context, typeInformation));
}

exports.extractContext = extractContext;
exports.processExpressionAttributes = processExpressionAttributes;
exports.applyExpression = applyExpression;
exports.parse = parse;
<commit_msg>fix typo<commit_after>/*
 * Copyright 2016 Telefonica Investigación y Desarrollo, S.A.U
 *
 * This file is part of fiware-iotagent-lib
 *
 * fiware-iotagent-lib 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-iotagent-lib 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-iotagent-lib.
 * 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
 *
 * Developed by: Federico M. Facca - Martel Innovate
 */

'use strict';

const jexl = require('jexl');
var errors = require('../errors'),
  logger = require('logops'),
  config = require('../commonConfig'),
  logContext = {
      op: 'IoTAgentNGSI.JEXL'
  };

jexl.addTransform('indexOf', (val, char) => String(val).indexOf(char));
jexl.addTransform('length', (val) => String(val).length);
jexl.addTransform('trim', (val) => String(val).trim());
jexl.addTransform('substr', (val, int1, int2) => String(val).substr(int1, int2));

function parse(expression, context, callback) {
    var result,
        error;

    try {

        result = jexl.evalSync (expression, context);
        logger.debug(logContext, 'parse expression result "[%j]" ', result);
    } catch (e) {
      error = new errors.InvalidExpression(expression);
      if (callback) {
          callback(error);
      } else {
          throw error;
      }
    }

    if (callback) {
        callback(null, result);
    } else {
        return result;
    }
}

function extractContext(attributeList) {
    var context = {};
    var value;

    for (var i = 0; i < attributeList.length; i++) {
        if (Number.parseInt(attributeList[i].value)) {
          value = Number.parseInt(attributeList[i].value);
        } else if (Number.parseFloat(attributeList[i].value)) {
          value = Number.parseFloat(attributeList[i].value);
        } else if (String(attributeList[i].value) === 'true') {
          value = true;
        } else if (String(attributeList[i].value) === 'false') {
          value = false;
        } else {
          value = attributeList[i].value;
        }
        if(attributeList[i].name) {
          context[attributeList[i].name] = value;
        }
        /*jshint camelcase: false */
        if(attributeList[i].object_id) {
          context[attributeList[i].object_id] = value;
        }
        /*jshint camelcase: true */
    }

    return context;
}

function applyExpression(expression, context, typeInformation) {
    var result;
    result = jexl.evalSync (expression, context);
    logger.debug(logContext, 'applyExpression result "[%j]" ', result);
    return result;
}

function expressionApplier(context, typeInformation) {
    return function(attribute) {

        /**
         * Determines if a value is of type float
         *
         * @param      {String}   value       Value to be analyzed
         * @return     {boolean}              True if float, False otherwise.
         */
        function isFloat(value) {
            return !isNaN(value) && value.toString().indexOf('.') !== -1;
        }

        var newAttribute = {
            name: attribute.name,
            type: attribute.type
        };

        /*jshint camelcase: false */
        if (config.checkNgsi2() && attribute.object_id) {
            newAttribute.object_id = attribute.object_id;
        }

        newAttribute.value = applyExpression(attribute.expression, context, typeInformation);

        if (attribute.type === 'Number' && isFloat(newAttribute.value)) {
            newAttribute.value = Number.parseFloat(newAttribute.value);
        }
        else if (attribute.type === 'Number' && Number.parseInt(newAttribute.value)) {
            newAttribute.value = Number.parseInt(newAttribute.value);
        }
        else if (attribute.type === 'Boolean') {
            newAttribute.value = (newAttribute.value === 'true' || newAttribute.value === '1');
        }
        else if (attribute.type === 'None') {
            newAttribute.value = null;
        }
        else if (attribute.type === 'Text' || attribute.type === 'String') {
            newAttribute.value = String(newAttribute.value);
        }
        else if (attribute.type.toLowerCase().includes('structuredvalue') ||
                 attribute.type.toLowerCase().startsWith('geo') ||
                 attribute.type.toLowerCase().includes('json') ) {
            newAttribute.value = newAttribute.value;
        } else {
            newAttribute.value = String(newAttribute.value);
        }
        return newAttribute;
    };
}

function isTransform(identifier) {
  return jexl.getTransform(identifier) === ( null || undefined) ? false : true;
}

function contextAvailable(expression, context) {
  var error;
  try{
    var lexer = jexl._getLexer();
    var identifiers = lexer.tokenize(expression).filter(function(token) {
      return token.type === 'identifier';
    });
    var keys = Object.keys(context);
    // print context to see where is type
    var validContext = true;
    identifiers.some(function(element) {
      if (!keys.includes(element.value) && !isTransform(element.value)) {
        validContext = false;
        logger.warn(logContext, 'For expression "[%s]" context does not have element %s' , expression, element.value);
      }
      // FIXME: Workaround to allow keys of JSON geopoints
      if (element.value === 'type' || element.value === 'coordinates') {
        validContext = true;
      }
      return validContext === false;
    });
    if(validContext) {
      jexl.evalSync (expression, context);
    }
    return validContext;
  } catch (e) {
    error = new errors.InvalidExpression(expression);
    throw error;
  }
}

function processExpressionAttributes(typeInformation, list, context) {
    return list
        .filter(function(item) {
            return item.expression && contextAvailable(item.expression, context);
        })
        .map(expressionApplier(context, typeInformation));
}

exports.extractContext = extractContext;
exports.processExpressionAttributes = processExpressionAttributes;
exports.applyExpression = applyExpression;
exports.parse = parse;
<|endoftext|>


<commit_before>'use strict';

require('chai').should();

describe('htmlTag', () => {
  const htmlTag = require('../lib/html_tag');

  it('tag', () => {
    htmlTag('hr').should.eql('
');
  });

  it('tag + attrs', () => {
    htmlTag('img', {
      src: 'http://placekitten.com/200/300'
    }).should.eql('');

    htmlTag('img', {
      src: 'http://placekitten.com/200/300',
      width: 200,
      height: 300
    }).should.eql('');
  });

  it('tag + attrs + text', () => {
    htmlTag('a', {
      href: 'http://zespia.tw'
    }, 'My blog').should.eql('My blog');
  });

  it('tag + empty ALT attr', () => {
    htmlTag('img', {
      src: 'http://placekitten.com/200/300',
      alt: ''
    }).should.eql('');
  });

  it('passing a zero as attribute', () => {
    htmlTag('a', {
      href: 'http://zespia.tw',
      tabindex: 0
    }, 'My blog').should.eql('My blog');
  });

  it('passing a null alt attribute', () => {
    htmlTag('a', {
      href: 'http://zespia.tw',
      alt: null
    }, 'My blog').should.eql('My blog');
  });

  it('passing a undefined alt attribute', () => {
    htmlTag('a', {
      href: 'http://zespia.tw',
      alt: undefined
    }, 'My blog').should.eql('My blog');
  });

  it('tag is required', () => {
    try {
      htmlTag();
    } catch (err) {
      err.should.have.property('message', 'tag is required!');
    }
  });

  it('encode url', () => {
    htmlTag('img', {
      src: 'http://foo.com/bár.jpg'
    }).should.eql('');
  });

  it('escape html tag', () => {
    htmlTag('foo', {
      bar: ''
    }, '<baz>').should.eql('<foo bar="<b>"><baz></foo>');
  });

  it('escape html tag (escape off)', () => {
    htmlTag('foo', {
      bar: ''
    }, '<baz>', false).should.eql('<foo bar="<b>"><baz></foo>');
  });

});
<commit_msg>test(html_tag): handle srcset<commit_after>'use strict';

require('chai').should();

describe('htmlTag', () => {
  const htmlTag = require('../lib/html_tag');

  it('tag', () => {
    htmlTag('hr').should.eql('
');
  });

  it('tag + attrs', () => {
    htmlTag('img', {
      src: 'http://placekitten.com/200/300'
    }).should.eql('');

    htmlTag('img', {
      src: 'http://placekitten.com/200/300',
      width: 200,
      height: 300
    }).should.eql('');
  });

  it('tag + attrs + text', () => {
    htmlTag('a', {
      href: 'http://zespia.tw'
    }, 'My blog').should.eql('My blog');
  });

  it('tag + empty ALT attr', () => {
    htmlTag('img', {
      src: 'http://placekitten.com/200/300',
      alt: ''
    }).should.eql('');
  });

  it('passing a zero as attribute', () => {
    htmlTag('a', {
      href: 'http://zespia.tw',
      tabindex: 0
    }, 'My blog').should.eql('My blog');
  });

  it('passing a null alt attribute', () => {
    htmlTag('a', {
      href: 'http://zespia.tw',
      alt: null
    }, 'My blog').should.eql('My blog');
  });

  it('passing a undefined alt attribute', () => {
    htmlTag('a', {
      href: 'http://zespia.tw',
      alt: undefined
    }, 'My blog').should.eql('My blog');
  });

  it('tag is required', () => {
    try {
      htmlTag();
    } catch (err) {
      err.should.have.property('message', 'tag is required!');
    }
  });

  it('encode url', () => {
    htmlTag('img', {
      src: 'http://foo.com/bár.jpg'
    }).should.eql('');
  });

  it('escape html tag', () => {
    htmlTag('foo', {
      bar: ''
    }, '<baz>').should.eql('<foo bar="<b>"><baz></foo>');
  });

  it('escape html tag (escape off)', () => {
    htmlTag('foo', {
      bar: ''
    }, '<baz>', false).should.eql('<foo bar="<b>"><baz></foo>');
  });

  it('srcset', () => {
    htmlTag('img', {
      srcset: 'fóo.jpg 320w,/foo/bár.jpeg 480w,default.png'
    }).should.eql('');
  });

  it('srcset with whitespace', () => {
    htmlTag('img', {
      srcset: `fóo.jpg 320w,
        /foo/bár.jpeg 480w,
        default.png`
    }).should.eql(``);
  });
});
<|endoftext|>


<commit_before>/*
	MIT License http://www.opensource.org/licenses/mit-license.php
	Author Tobias Koppers @sokra
*/
"use strict";

const ConstDependency = require("./dependencies/ConstDependency");
const BasicEvaluatedExpression = require("./BasicEvaluatedExpression");
const ParserHelpers = require("./ParserHelpers");
const NullFactory = require("./NullFactory");

/** @typedef {import("./Compiler")} Compiler */
/** @typedef {import("./Parser")} Parser */
/** @typedef {null|undefined|RegExp|Function|string|number} CodeValuePrimitive */
/** @typedef {CodeValuePrimitive|Record<string, CodeValuePrimitive>|RuntimeValue} CodeValue */

class RuntimeValue {
	constructor(fn, fileDependencies) {
		this.fn = fn;
		this.fileDependencies = fileDependencies || [];
	}

	exec(parser) {
		if (this.fileDependencies === true) {
			parser.state.module.buildInfo.cacheable = false;
		} else {
			for (const fileDependency of this.fileDependencies) {
				parser.state.module.buildInfo.fileDependencies.add(fileDependency);
			}
		}

		return this.fn(parser.state.module);
	}
}

const stringifyObj = (obj, parser) => {
	return (
		"Object({" +
		Object.keys(obj)
			.map(key => {
				const code = obj[key];
				return JSON.stringify(key) + ":" + toCode(code, parser);
			})
			.join(",") +
		"})"
	);
};

/**
 * Convert code to a string that evaluates
 * @param {CodeValue} code Code to evaluate
 * @param {Parser} parser Parser
 * @returns {string} code converted to string that evaluates
 */
const toCode = (code, parser) => {
	if (code === null) {
		return "null";
	}
	if (code === undefined) {
		return "undefined";
	}
	if (code instanceof RuntimeValue) {
		return toCode(code.exec(parser), parser);
	}
	if (code instanceof RegExp && code.toString) {
		return code.toString();
	}
	if (typeof code === "function" && code.toString) {
		return "(" + code.toString() + ")";
	}
	if (typeof code === "object") {
		return stringifyObj(code, parser);
	}
	return code + "";
};

class DefinePlugin {
	/**
	 * Create a new define plugin
	 * @param {Record<string, CodeValue>} definitions A map of global object definitions
	 */
	constructor(definitions) {
		this.definitions = definitions;
	}

	static runtimeValue(fn, fileDependencies) {
		return new RuntimeValue(fn, fileDependencies);
	}

	/**
	 * Apply the plugin
	 * @param {Compiler} compiler Webpack compiler
	 * @returns {void}
	 */
	apply(compiler) {
		const definitions = this.definitions;
		compiler.hooks.compilation.tap(
			"DefinePlugin",
			(compilation, { normalModuleFactory }) => {
				compilation.dependencyFactories.set(ConstDependency, new NullFactory());
				compilation.dependencyTemplates.set(
					ConstDependency,
					new ConstDependency.Template()
				);

				/**
				 * Handler
				 * @param {Parser} parser Parser
				 * @returns {void}
				 */
				const handler = parser => {
					/**
					 * Walk definitions
					 * @param {Object} definitions Definitions map
					 * @param {string} prefix Prefix string
					 * @returns {void}
					 */
					const walkDefinitions = (definitions, prefix) => {
						Object.keys(definitions).forEach(key => {
							const code = definitions[key];
							if (
								code &&
								typeof code === "object" &&
								!(code instanceof RuntimeValue) &&
								!(code instanceof RegExp)
							) {
								walkDefinitions(code, prefix + key + ".");
								applyObjectDefine(prefix + key, code);
								return;
							}
							applyDefineKey(prefix, key);
							applyDefine(prefix + key, code);
						});
					};

					/**
					 * Apply define key
					 * @param {string} prefix Prefix
					 * @param {string} key Key
					 * @returns {void}
					 */
					const applyDefineKey = (prefix, key) => {
						const splittedKey = key.split(".");
						splittedKey.slice(1).forEach((_, i) => {
							const fullKey = prefix + splittedKey.slice(0, i + 1).join(".");
							parser.hooks.canRename
								.for(fullKey)
								.tap("DefinePlugin", ParserHelpers.approve);
						});
					};

					/**
					 * Apply Code
					 * @param {string} key Key
					 * @param {CodeValue} code Code
					 * @returns {void}
					 */
					const applyDefine = (key, code) => {
						const isTypeof = /^typeof\s+/.test(key);
						if (isTypeof) key = key.replace(/^typeof\s+/, "");
						let recurse = false;
						let recurseTypeof = false;
						if (!isTypeof) {
							parser.hooks.canRename
								.for(key)
								.tap("DefinePlugin", ParserHelpers.approve);
							parser.hooks.evaluateIdentifier
								.for(key)
								.tap("DefinePlugin", expr => {
									/**
									 * this is needed in case there is a recursion in the DefinePlugin
									 * to prevent an endless recursion
									 * e.g.: new DefinePlugin({
									 * "a": "b",
									 * "b": "a"
									 * });
									 */
									if (recurse) return;
									recurse = true;
									const res = parser.evaluate(toCode(code, parser));
									recurse = false;
									res.setRange(expr.range);
									return res;
								});
							parser.hooks.expression.for(key).tap("DefinePlugin", expr => {
								const strCode = toCode(code, parser);
								if (/__webpack_require__/.test(strCode)) {
									return ParserHelpers.toConstantDependencyWithWebpackRequire(
										parser,
										strCode
									)(expr);
								} else {
									return ParserHelpers.toConstantDependency(parser, strCode)(
										expr
									);
								}
							});
						}
						parser.hooks.evaluateTypeof.for(key).tap("DefinePlugin", expr => {
							/**
							 * this is needed in case there is a recursion in the DefinePlugin
							 * to prevent an endless recursion
							 * e.g.: new DefinePlugin({
							 * "typeof a": "typeof b",
							 * "typeof b": "typeof a"
							 * });
							 */
							if (recurseTypeof) return;
							recurseTypeof = true;
							const typeofCode = isTypeof
								? toCode(code, parser)
								: "typeof (" + toCode(code, parser) + ")";
							const res = parser.evaluate(typeofCode);
							recurseTypeof = false;
							res.setRange(expr.range);
							return res;
						});
						parser.hooks.typeof.for(key).tap("DefinePlugin", expr => {
							const typeofCode = isTypeof
								? toCode(code, parser)
								: "typeof (" + toCode(code, parser) + ")";
							const res = parser.evaluate(typeofCode);
							if (!res.isString()) return;
							return ParserHelpers.toConstantDependency(
								parser,
								JSON.stringify(res.string)
							).bind(parser)(expr);
						});
					};

					/**
					 * Apply Object
					 * @param {string} key Key
					 * @param {Object} obj Object
					 * @returns {void}
					 */
					const applyObjectDefine = (key, obj) => {
						parser.hooks.canRename
							.for(key)
							.tap("DefinePlugin", ParserHelpers.approve);
						parser.hooks.evaluateIdentifier
							.for(key)
							.tap("DefinePlugin", expr =>
								new BasicEvaluatedExpression().setTruthy().setRange(expr.range)
							);
						parser.hooks.evaluateTypeof.for(key).tap("DefinePlugin", expr => {
							return ParserHelpers.evaluateToString("object")(expr);
						});
						parser.hooks.expression.for(key).tap("DefinePlugin", expr => {
							const strCode = stringifyObj(obj, parser);

							if (/__webpack_require__/.test(strCode)) {
								return ParserHelpers.toConstantDependencyWithWebpackRequire(
									parser,
									strCode
								)(expr);
							} else {
								return ParserHelpers.toConstantDependency(parser, strCode)(
									expr
								);
							}
						});
						parser.hooks.typeof.for(key).tap("DefinePlugin", expr => {
							return ParserHelpers.toConstantDependency(
								parser,
								JSON.stringify("object")
							)(expr);
						});
					};

					walkDefinitions(definitions, "");
				};

				normalModuleFactory.hooks.parser
					.for("javascript/auto")
					.tap("DefinePlugin", handler);
				normalModuleFactory.hooks.parser
					.for("javascript/dynamic")
					.tap("DefinePlugin", handler);
				normalModuleFactory.hooks.parser
					.for("javascript/esm")
					.tap("DefinePlugin", handler);
			}
		);
	}
}
module.exports = DefinePlugin;
<commit_msg>pass { module } instead of module<commit_after>/*
	MIT License http://www.opensource.org/licenses/mit-license.php
	Author Tobias Koppers @sokra
*/
"use strict";

const ConstDependency = require("./dependencies/ConstDependency");
const BasicEvaluatedExpression = require("./BasicEvaluatedExpression");
const ParserHelpers = require("./ParserHelpers");
const NullFactory = require("./NullFactory");

/** @typedef {import("./Compiler")} Compiler */
/** @typedef {import("./Parser")} Parser */
/** @typedef {null|undefined|RegExp|Function|string|number} CodeValuePrimitive */
/** @typedef {CodeValuePrimitive|Record<string, CodeValuePrimitive>|RuntimeValue} CodeValue */

class RuntimeValue {
	constructor(fn, fileDependencies) {
		this.fn = fn;
		this.fileDependencies = fileDependencies || [];
	}

	exec(parser) {
		if (this.fileDependencies === true) {
			parser.state.module.buildInfo.cacheable = false;
		} else {
			for (const fileDependency of this.fileDependencies) {
				parser.state.module.buildInfo.fileDependencies.add(fileDependency);
			}
		}

		return this.fn({ module: parser.state.module });
	}
}

const stringifyObj = (obj, parser) => {
	return (
		"Object({" +
		Object.keys(obj)
			.map(key => {
				const code = obj[key];
				return JSON.stringify(key) + ":" + toCode(code, parser);
			})
			.join(",") +
		"})"
	);
};

/**
 * Convert code to a string that evaluates
 * @param {CodeValue} code Code to evaluate
 * @param {Parser} parser Parser
 * @returns {string} code converted to string that evaluates
 */
const toCode = (code, parser) => {
	if (code === null) {
		return "null";
	}
	if (code === undefined) {
		return "undefined";
	}
	if (code instanceof RuntimeValue) {
		return toCode(code.exec(parser), parser);
	}
	if (code instanceof RegExp && code.toString) {
		return code.toString();
	}
	if (typeof code === "function" && code.toString) {
		return "(" + code.toString() + ")";
	}
	if (typeof code === "object") {
		return stringifyObj(code, parser);
	}
	return code + "";
};

class DefinePlugin {
	/**
	 * Create a new define plugin
	 * @param {Record<string, CodeValue>} definitions A map of global object definitions
	 */
	constructor(definitions) {
		this.definitions = definitions;
	}

	static runtimeValue(fn, fileDependencies) {
		return new RuntimeValue(fn, fileDependencies);
	}

	/**
	 * Apply the plugin
	 * @param {Compiler} compiler Webpack compiler
	 * @returns {void}
	 */
	apply(compiler) {
		const definitions = this.definitions;
		compiler.hooks.compilation.tap(
			"DefinePlugin",
			(compilation, { normalModuleFactory }) => {
				compilation.dependencyFactories.set(ConstDependency, new NullFactory());
				compilation.dependencyTemplates.set(
					ConstDependency,
					new ConstDependency.Template()
				);

				/**
				 * Handler
				 * @param {Parser} parser Parser
				 * @returns {void}
				 */
				const handler = parser => {
					/**
					 * Walk definitions
					 * @param {Object} definitions Definitions map
					 * @param {string} prefix Prefix string
					 * @returns {void}
					 */
					const walkDefinitions = (definitions, prefix) => {
						Object.keys(definitions).forEach(key => {
							const code = definitions[key];
							if (
								code &&
								typeof code === "object" &&
								!(code instanceof RuntimeValue) &&
								!(code instanceof RegExp)
							) {
								walkDefinitions(code, prefix + key + ".");
								applyObjectDefine(prefix + key, code);
								return;
							}
							applyDefineKey(prefix, key);
							applyDefine(prefix + key, code);
						});
					};

					/**
					 * Apply define key
					 * @param {string} prefix Prefix
					 * @param {string} key Key
					 * @returns {void}
					 */
					const applyDefineKey = (prefix, key) => {
						const splittedKey = key.split(".");
						splittedKey.slice(1).forEach((_, i) => {
							const fullKey = prefix + splittedKey.slice(0, i + 1).join(".");
							parser.hooks.canRename
								.for(fullKey)
								.tap("DefinePlugin", ParserHelpers.approve);
						});
					};

					/**
					 * Apply Code
					 * @param {string} key Key
					 * @param {CodeValue} code Code
					 * @returns {void}
					 */
					const applyDefine = (key, code) => {
						const isTypeof = /^typeof\s+/.test(key);
						if (isTypeof) key = key.replace(/^typeof\s+/, "");
						let recurse = false;
						let recurseTypeof = false;
						if (!isTypeof) {
							parser.hooks.canRename
								.for(key)
								.tap("DefinePlugin", ParserHelpers.approve);
							parser.hooks.evaluateIdentifier
								.for(key)
								.tap("DefinePlugin", expr => {
									/**
									 * this is needed in case there is a recursion in the DefinePlugin
									 * to prevent an endless recursion
									 * e.g.: new DefinePlugin({
									 * "a": "b",
									 * "b": "a"
									 * });
									 */
									if (recurse) return;
									recurse = true;
									const res = parser.evaluate(toCode(code, parser));
									recurse = false;
									res.setRange(expr.range);
									return res;
								});
							parser.hooks.expression.for(key).tap("DefinePlugin", expr => {
								const strCode = toCode(code, parser);
								if (/__webpack_require__/.test(strCode)) {
									return ParserHelpers.toConstantDependencyWithWebpackRequire(
										parser,
										strCode
									)(expr);
								} else {
									return ParserHelpers.toConstantDependency(parser, strCode)(
										expr
									);
								}
							});
						}
						parser.hooks.evaluateTypeof.for(key).tap("DefinePlugin", expr => {
							/**
							 * this is needed in case there is a recursion in the DefinePlugin
							 * to prevent an endless recursion
							 * e.g.: new DefinePlugin({
							 * "typeof a": "typeof b",
							 * "typeof b": "typeof a"
							 * });
							 */
							if (recurseTypeof) return;
							recurseTypeof = true;
							const typeofCode = isTypeof
								? toCode(code, parser)
								: "typeof (" + toCode(code, parser) + ")";
							const res = parser.evaluate(typeofCode);
							recurseTypeof = false;
							res.setRange(expr.range);
							return res;
						});
						parser.hooks.typeof.for(key).tap("DefinePlugin", expr => {
							const typeofCode = isTypeof
								? toCode(code, parser)
								: "typeof (" + toCode(code, parser) + ")";
							const res = parser.evaluate(typeofCode);
							if (!res.isString()) return;
							return ParserHelpers.toConstantDependency(
								parser,
								JSON.stringify(res.string)
							).bind(parser)(expr);
						});
					};

					/**
					 * Apply Object
					 * @param {string} key Key
					 * @param {Object} obj Object
					 * @returns {void}
					 */
					const applyObjectDefine = (key, obj) => {
						parser.hooks.canRename
							.for(key)
							.tap("DefinePlugin", ParserHelpers.approve);
						parser.hooks.evaluateIdentifier
							.for(key)
							.tap("DefinePlugin", expr =>
								new BasicEvaluatedExpression().setTruthy().setRange(expr.range)
							);
						parser.hooks.evaluateTypeof.for(key).tap("DefinePlugin", expr => {
							return ParserHelpers.evaluateToString("object")(expr);
						});
						parser.hooks.expression.for(key).tap("DefinePlugin", expr => {
							const strCode = stringifyObj(obj, parser);

							if (/__webpack_require__/.test(strCode)) {
								return ParserHelpers.toConstantDependencyWithWebpackRequire(
									parser,
									strCode
								)(expr);
							} else {
								return ParserHelpers.toConstantDependency(parser, strCode)(
									expr
								);
							}
						});
						parser.hooks.typeof.for(key).tap("DefinePlugin", expr => {
							return ParserHelpers.toConstantDependency(
								parser,
								JSON.stringify("object")
							)(expr);
						});
					};

					walkDefinitions(definitions, "");
				};

				normalModuleFactory.hooks.parser
					.for("javascript/auto")
					.tap("DefinePlugin", handler);
				normalModuleFactory.hooks.parser
					.for("javascript/dynamic")
					.tap("DefinePlugin", handler);
				normalModuleFactory.hooks.parser
					.for("javascript/esm")
					.tap("DefinePlugin", handler);
			}
		);
	}
}
module.exports = DefinePlugin;
<|endoftext|>


<commit_before>// Removing query parameters specific to prerendering
// so that cached values can be shared

const omitParameters = [
  '__nojs',
  '__refresh',
]

// Keep in sync with keys from https://raw.githubusercontent.com/inventaire/inventaire-i18n/dist/dist/languages_data.js
const  supportedLanguages = new Set([ 'ar', 'bn', 'ca', 'cs', 'da', 'de', 'el', 'en', 'eo', 'es', 'fr', 'hu', 'id', 'it', 'ja', 'nb', 'nl', 'pa', 'pl', 'pt', 'ro', 'ru', 'sk', 'sv', 'tr', 'uk' ])

module.exports = {
  init: () => console.log('using rewrite url plugin'),

  requestReceived: (req, res, next) => {
    console.log('initial url:', req.prerender.url)
    req.prerender.url = rewriteUrl(req, req.prerender.url)
    console.log('final url  :', req.prerender.url)
    next()
  }
}

const rewriteUrl = (req, url) => {
  const [ path, queryString ] = Array.from(url.split('?'))

  query = new URLSearchParams(queryString)
  for (const parameter of omitParameters) {
    query.delete(parameter)
  }

  if (!query.has('lang')) {
    const headersLang = getLangFromHeaders(req.get('accept-language'))
    if (headersLang) query.set('lang', headersLang)
    else query.set('lang', 'en')
  }

  const updatedQueryString = query.toString()

  if (updatedQueryString.length === 0) return path
  else return `${path}?${updatedQueryString}`
}

const getLangFromHeaders = acceptedLanguages => {
  if (!acceptedLanguages || acceptedLanguages.length === 0) return

  const preferredLangs = acceptedLanguages
    .replace(/q=\d(\.\d)?,?/g, '')
    .split(';')
    .map(lang => lang.split(/\W/)[0])
    .filter(lang => supportedLanguages.has(lang))

  return preferredLangs[0]
}
<commit_msg>rewriteUrl: omit agent parameter<commit_after>// Removing query parameters specific to prerendering
// so that cached values can be shared

const omitParameters = [
  '__nojs',
  '__refresh',
  // Used by agent=sentinel
  'agent',
]

// Keep in sync with keys from https://raw.githubusercontent.com/inventaire/inventaire-i18n/dist/dist/languages_data.js
const  supportedLanguages = new Set([ 'ar', 'bn', 'ca', 'cs', 'da', 'de', 'el', 'en', 'eo', 'es', 'fr', 'hu', 'id', 'it', 'ja', 'nb', 'nl', 'pa', 'pl', 'pt', 'ro', 'ru', 'sk', 'sv', 'tr', 'uk' ])

module.exports = {
  init: () => console.log('using rewrite url plugin'),

  requestReceived: (req, res, next) => {
    console.log('initial url:', req.prerender.url)
    req.prerender.url = rewriteUrl(req, req.prerender.url)
    console.log('final url  :', req.prerender.url)
    next()
  }
}

const rewriteUrl = (req, url) => {
  const [ path, queryString ] = Array.from(url.split('?'))

  query = new URLSearchParams(queryString)
  for (const parameter of omitParameters) {
    query.delete(parameter)
  }

  if (!query.has('lang')) {
    const headersLang = getLangFromHeaders(req.get('accept-language'))
    if (headersLang) query.set('lang', headersLang)
    else query.set('lang', 'en')
  }

  const updatedQueryString = query.toString()

  if (updatedQueryString.length === 0) return path
  else return `${path}?${updatedQueryString}`
}

const getLangFromHeaders = acceptedLanguages => {
  if (!acceptedLanguages || acceptedLanguages.length === 0) return

  const preferredLangs = acceptedLanguages
    .replace(/q=\d(\.\d)?,?/g, '')
    .split(';')
    .map(lang => lang.split(/\W/)[0])
    .filter(lang => supportedLanguages.has(lang))

  return preferredLangs[0]
}
<|endoftext|>


<commit_before><commit_msg>Tests added for isHexadecimal validation API<commit_after>var isHexadecimal   = require('../validate.js').isHexadecimal,
    expect          = require('chai').expect;

describe('isHexadecimal API Tests', function () {
    describe('Valid tests for isHexadecimal API', function () {
        it('1F is a valid hexdecimal value', function () {
            expect(isHexadecimal('1F')).to.be.true;
        });

        it('af is a valid hexdecimal value', function () {
            expect(isHexadecimal('af')).to.be.true;
        });

        it('1234bef is a valid hexdecimal value', function () {
            expect(isHexadecimal('1234bef')).to.be.true;
        });

        it('0x1f is not a valid hexdecimal value', function () {
            expect(isHexadecimal('0x1f')).to.be.false;
        });

        it('0x1F is not a valid hexdecimal value', function () {
            expect(isHexadecimal('0x1F')).to.be.false;
        });

        it('asdfg is not a valid hexdecimal value', function () {
            expect(isHexadecimal('asdfg')).to.be.false;
        });

        it('hellow is not a valid hexdecimal value', function () {
            expect(isHexadecimal('hellow')).to.be.false;
        });
    });

    describe('Invalid tests for isHexadecimal API', function () {
        it('null is not a valid hexadecimal value', function () {
            expect(isHexadecimal(null)).to.be.false;
        });

        it('undefined is not a valid hexadecimal value', function () {
            expect(isHexadecimal(undefined)).to.be.false;
        });

        it('empty string is not a hexadecimal value', function () {
            expect(isHexadecimal('')).to.be.false;
        });

        it('ᴁᴪᴙݝۺ contains invalid hexadecimal value', function () {
            expect(isHexadecimal('ᴁᴪᴙݝۺ')).to.be.false;
        });

        it('247238 does not contain valid hexadecimal value', function () {
            expect(isHexadecimal(247238)).to.be.false;
        });

        it('new Object() is not a hexadecimal value', function () {
            expect(isHexadecimal(new Object())).to.be.false;
        });

        it('Infinity is not a hexadecimal value', function () {
            expect(isHexadecimal(Infinity)).to.be.false;
        });
    });
});<|endoftext|>


<commit_before>'use babel';

import {Point, Range} from 'atom';

export default class EventHandler {
  constructor(socket, editor, doc, subscriptions) {
    this.socket = socket;
    this.editor = editor;
    this.doc = doc;
    this.subscriptions = subscriptions;
    this.push = true;
    this.buffer = editor.getBuffer();
  }

  listen() {
    let disposables = [];

    // local events
    disposables.push(this.editor.onDidSave( (event) => {
      if (!this.push) {
        return;
      }
      let saveData = {
        a: 'meta',
        type: 'save',
        path: atom.project.relativizePath(event.path)[1]
      };
      setTimeout( () => {
        this.sendSocketMsg( () => {
          this.socket.send(JSON.stringify(saveData));
        });
      }, 0);
    }));

    disposables.push(this.editor.onDidChangeSelectionRange( (event) => {

      let data = {
        a: 'meta',
        type: 'cursorMoved',
        newRange: event.newBufferRange
      };
      setTimeout( () => {
        this.sendSocketMsg( () => {
          this.socket.send(JSON.stringify(data));
        });
      }, 0);
    }));

    disposables.push(this.buffer.onDidChange((event) => {
      if (!this.push) {
        return;
      }
      // remove text event
      if (event['oldText'].length !== 0) {
        let startPoint = event['oldRange'].start;
        let position = this.buffer.characterIndexForPosition(startPoint);
        let op = [position, {d: event['oldText'].length}];
        this.doc.submitOp(op);
      }
      // insert text event
      if (event['newText'].length !== 0) {
        let startPoint = event['newRange'].start;
        let position = this.buffer.characterIndexForPosition(startPoint);
        let op = [position, event['newText']];
        this.doc.submitOp(op);
      }
    }));
    this.subscriptions.add(...disposables);

    // remote events
    this.listenToServerChanges();
  }

  listenToServerChanges() {
    this.socket.on('message', (msg) => {
      let data = JSON.parse(msg);
      console.log(data);
      if (data.a !== 'meta') {
        return;
      }
      switch (data.type) {
        case 'cursorMoved':
          this.onCursorMoved(data.newRange);
          break;
        case 'select':
          // this.onSelect(data.newRange);
          break;
        case 'save':
          this.onSave(data.path);
          break;
        case 'close':
          this.onClose();
          break;
        case 'socketClose':
          this.onSocketClose(data.clientId);
          break;
        default:
      }
    });

    this.doc.on('op', (op, source) => {
      if (source) {
        console.log('Got your own changes, I am not doing anything...');
        return;
      }
      console.log('changing...');
      console.log(op);

      var pos = 0;
      for (var i = 0; i < op.length; i++) {
        var component = op[i];
        switch (typeof component) {
          case 'number':
            pos += component;
            break;
          case 'string':
            this.onInsert(pos, component);
            pos += component.length;
            break;
          case 'object':
            this.onRemove(pos, component.d);
            break;
          default:
            break;
        }
      }
    });
  }

  onCursorMoved(rangeObj) {
    // type = overlay
    if (typeof this.overlayMarker !== 'undefined') {
      this.overlayMarker.destroy();
    }

    this.overlayMarker = this.editor.markBufferRange(Range.fromObject(rangeObj), {
      'invalidate': 'never'
    });
    let element = document.createElement('div');
    element.textContent = 'Overlay decorations!';
    let style = {
      transform: 'translate(0, -100%)',
      backgroundColor: 'rgba(31, 161, 93, 1)',
      padding: '4px',
      fontFamily: 'comic sans, comic sans ms, cursive, verdana, arial, sans-serif'
    }

    Object.assign(element.style, style);
    this.editor.decorateMarker(this.overlayMarker, {
      type: 'overlay',
      position: 'head',
      item: element
    });
  }

  onSelect(rangeObj) {
    if (typeof this.marker !== 'undefined') {
      this.marker.destroy();
    }
    if (Point.fromObject(rangeObj.start).isEqual(Point.fromObject(rangeObj.end))) {
      return;
    }
    this.marker = this.editor.markBufferRange(Range.fromObject(rangeObj), {
      invalidate: 'never'
    });
    this.editor.decorateMarker(this.marker, {
      type: 'highlight',
      class: 'coeditor-selection'
    });
  }

  onSave(relativePath) {
    // atom.workspace.getActivePane().saveItem(atom.workspace.getActivePaneItem());
    this.push = false;
    console.log(atom.project.getPaths());
    if (typeof this.editor.getPath() !== 'undefined') {
      this.editor.save();
    }
    this.push = true;
    // if (typeof this.editor.getPath() !== 'undefined') {
    //   this.editor.save();
    // } else {
    //   let absolutePath = path.join(atom.project.getPaths()[0], relativePath);
    //   this.editor.saveAs(absolutePath);
    // }
  }

  onClose() {
    atom.workspace.getActivePaneItem().destroy();
  }

  onSocketClose(clientId) {
    atom.notifications.addInfo(clientId + ' left.');
  }

  onInsert(position, text) {
    this.doBufferChange( () => {
      let from = this.buffer.positionForCharacterIndex(position);
      this.buffer.insert(from, text);
    })
  }

  onRemove(position, length) {
    this.doBufferChange( () => {
      let from = this.buffer.positionForCharacterIndex(position);
      let to = this.buffer.positionForCharacterIndex(position + length);
      this.buffer.delete([from.toArray(), to.toArray()]);
    })
  }

  doBufferChange(callback) {
    this.push = false;
    callback();
    this.push = true;
  }

  sendSocketMsg(callback) {
    if (this.socket) {
      callback();
    }
  }
}
<commit_msg>change indicator style<commit_after>'use babel';

import {Point, Range} from 'atom';

export default class EventHandler {
  constructor(socket, editor, doc, subscriptions) {
    this.socket = socket;
    this.editor = editor;
    this.doc = doc;
    this.subscriptions = subscriptions;
    this.push = true;
    this.buffer = editor.getBuffer();
  }

  listen() {
    let disposables = [];

    // local events
    disposables.push(this.editor.onDidSave( (event) => {
      if (!this.push) {
        return;
      }
      let saveData = {
        a: 'meta',
        type: 'save',
        path: atom.project.relativizePath(event.path)[1]
      };
      setTimeout( () => {
        this.sendSocketMsg( () => {
          this.socket.send(JSON.stringify(saveData));
        });
      }, 0);
    }));

    disposables.push(this.editor.onDidChangeSelectionRange( (event) => {

      let data = {
        a: 'meta',
        type: 'cursorMoved',
        newRange: event.newBufferRange
      };
      setTimeout( () => {
        this.sendSocketMsg( () => {
          this.socket.send(JSON.stringify(data));
        });
      }, 0);
    }));

    disposables.push(this.buffer.onDidChange((event) => {
      if (!this.push) {
        return;
      }
      // remove text event
      if (event['oldText'].length !== 0) {
        let startPoint = event['oldRange'].start;
        let position = this.buffer.characterIndexForPosition(startPoint);
        let op = [position, {d: event['oldText'].length}];
        this.doc.submitOp(op);
      }
      // insert text event
      if (event['newText'].length !== 0) {
        let startPoint = event['newRange'].start;
        let position = this.buffer.characterIndexForPosition(startPoint);
        let op = [position, event['newText']];
        this.doc.submitOp(op);
      }
    }));
    this.subscriptions.add(...disposables);

    // remote events
    this.listenToServerChanges();
  }

  listenToServerChanges() {
    this.socket.on('message', (msg) => {
      let data = JSON.parse(msg);
      console.log(data);
      if (data.a !== 'meta') {
        return;
      }
      switch (data.type) {
        case 'cursorMoved':
          this.onCursorMoved(data.newRange);
          break;
        case 'select':
          // this.onSelect(data.newRange);
          break;
        case 'save':
          this.onSave(data.path);
          break;
        case 'close':
          this.onClose();
          break;
        case 'socketClose':
          this.onSocketClose(data.clientId);
          break;
        default:
      }
    });

    this.doc.on('op', (op, source) => {
      if (source) {
        console.log('Got your own changes, I am not doing anything...');
        return;
      }
      console.log('changing...');
      console.log(op);

      var pos = 0;
      for (var i = 0; i < op.length; i++) {
        var component = op[i];
        switch (typeof component) {
          case 'number':
            pos += component;
            break;
          case 'string':
            this.onInsert(pos, component);
            pos += component.length;
            break;
          case 'object':
            this.onRemove(pos, component.d);
            break;
          default:
            break;
        }
      }
    });
  }

  onCursorMoved(rangeObj) {
    // type = overlay
    if (typeof this.overlayMarker !== 'undefined') {
      this.overlayMarker.destroy();
    }

    this.overlayMarker = this.editor.markBufferRange(Range.fromObject(rangeObj), {
      'invalidate': 'never'
    });
    let element = document.createElement('div');
    element.textContent = 'Overlay decorations!';
    let style = {
      transform: 'translate(0, -100%)',
      backgroundColor: 'rgba(31, 161, 93, 1)',
      paddingLeft: '1px',
      marginLeft: '1px',
      fontFamily: 'comic sans, comic sans ms, cursive, verdana, arial, sans-serif'
    }

    Object.assign(element.style, style);
    this.editor.decorateMarker(this.overlayMarker, {
      type: 'overlay',
      position: 'head',
      item: element
    });
  }

  onSelect(rangeObj) {
    if (typeof this.marker !== 'undefined') {
      this.marker.destroy();
    }
    if (Point.fromObject(rangeObj.start).isEqual(Point.fromObject(rangeObj.end))) {
      return;
    }
    this.marker = this.editor.markBufferRange(Range.fromObject(rangeObj), {
      invalidate: 'never'
    });
    this.editor.decorateMarker(this.marker, {
      type: 'highlight',
      class: 'coeditor-selection'
    });
  }

  onSave(relativePath) {
    // atom.workspace.getActivePane().saveItem(atom.workspace.getActivePaneItem());
    this.push = false;
    console.log(atom.project.getPaths());
    if (typeof this.editor.getPath() !== 'undefined') {
      this.editor.save();
    }
    this.push = true;
    // if (typeof this.editor.getPath() !== 'undefined') {
    //   this.editor.save();
    // } else {
    //   let absolutePath = path.join(atom.project.getPaths()[0], relativePath);
    //   this.editor.saveAs(absolutePath);
    // }
  }

  onClose() {
    atom.workspace.getActivePaneItem().destroy();
  }

  onSocketClose(clientId) {
    atom.notifications.addInfo(clientId + ' left.');
  }

  onInsert(position, text) {
    this.doBufferChange( () => {
      let from = this.buffer.positionForCharacterIndex(position);
      this.buffer.insert(from, text);
    })
  }

  onRemove(position, length) {
    this.doBufferChange( () => {
      let from = this.buffer.positionForCharacterIndex(position);
      let to = this.buffer.positionForCharacterIndex(position + length);
      this.buffer.delete([from.toArray(), to.toArray()]);
    })
  }

  doBufferChange(callback) {
    this.push = false;
    callback();
    this.push = true;
  }

  sendSocketMsg(callback) {
    if (this.socket) {
      callback();
    }
  }
}
<|endoftext|>


<commit_before>import React from "react";
import injectSheet from "react-jss";
import { formatDate } from "../../../utils";

const styles = {
  Dateline: {
    color: "#888888",
    fontFamily: "Circular Std",
    fontSize: "12px",
    fontWeight: "300",
    marginBottom: 0,
  },
};

// TODO: format dates
const Dateline = ({ classes, article }) => {
  return (

  	{formatDate(article.createdAt)}

);
};

export default injectSheet(styles)(Dateline);
<commit_msg>fixed style changes<commit_after>import React from "react";
import injectSheet from "react-jss";
import { formatDate } from "../../../utils";

const styles = {
  Dateline: {
    color: "#888888",
    fontFamily: "Circular Std",
    fontSize: "12px",
    fontWeight: "300",
    marginBottom: 0,
  },
};

// TODO: format dates
const Dateline = ({ classes, article }) => {
  return (

  	{formatDate(article.createdAt)}

  );
};

export default injectSheet(styles)(Dateline);
<|endoftext|>


<commit_before>// MODULES ------------------------------------

express = require('express');
colors = require('colors');

// SETUP ------------------------------------

app = express();

server = require('http').createServer(app);
io = require('socket.io').listen(server);

logger = function(req, res, next) {
    console.log("   info (backend) - ".cyan+req.method+" "+req.url);
    next();
}

app.configure(function () {
	app.set('views', __dirname + '/client/views');
	app.set('view engine', 'jade');
	app.use(express.cookieParser());
	app.use(express.json());
	app.use(express.urlencoded());
	app.use(express.methodOverride());
	app.use(logger);
	app.use(app.router);
	app.use(express.static(__dirname + '/client'));
	app.use(function (req,res) {
		res.send('404 - Not found');
		console.log('   error (backend) - '.red+'client requested an undefined route :(');
	});
});

io.configure(function () {
	io.set("transports", ["xhr-polling"]);
	io.set("polling duration", 10);
});

app.configure('development', function () {
	app.use(express.errorHandler({ dumpExceptions: true, showStack: true }));
});

onlineUsers = [];

// PAGE ROUTES ------------------------------------

app.get('/', function (req,res) {
	res.render("index", {
		title: 'index'
	});
});

server.listen(process.env.PORT || 5000);g<commit_msg>Fixed typo<commit_after>// MODULES ------------------------------------

express = require('express');
colors = require('colors');

// SETUP ------------------------------------

app = express();

server = require('http').createServer(app);
io = require('socket.io').listen(server);

logger = function(req, res, next) {
    console.log("   info (backend) - ".cyan+req.method+" "+req.url);
    next();
}

app.configure(function () {
	app.set('views', __dirname + '/client/views');
	app.set('view engine', 'jade');
	app.use(express.cookieParser());
	app.use(express.json());
	app.use(express.urlencoded());
	app.use(express.methodOverride());
	app.use(logger);
	app.use(app.router);
	app.use(express.static(__dirname + '/client'));
	app.use(function (req,res) {
		res.send('404 - Not found');
		console.log('   error (backend) - '.red+'client requested an undefined route :(');
	});
});

io.configure(function () {
	io.set("transports", ["xhr-polling"]);
	io.set("polling duration", 10);
});

app.configure('development', function () {
	app.use(express.errorHandler({ dumpExceptions: true, showStack: true }));
});

onlineUsers = [];

// PAGE ROUTES ------------------------------------

app.get('/', function (req,res) {
	res.render("index", {
		title: 'index'
	});
});

server.listen(process.env.PORT || 5000);<|endoftext|>


<commit_before>
var compare = require( 'aureooms-js-compare' ) ;
var itertools = require( 'aureooms-js-itertools' ) ;

var lex = compare.lexicographical( compare.increasing ) ;
var list = itertools.list ;

function T ( name , satisfiable ) {

	test( name , function ( assert ) {

		var fs = require( 'fs' ) ;

		var filename = './test/js/data/' + name + '.cnf' ;
		var stream = fs.createReadStream( filename , { encoding : 'utf8' } ) ;

		var iterable = {
			[Symbol.iterator] : function ( ) {
				return {
					next : function ( ) {
						var buf = stream.read( 1 ) ;
						if ( buf === null ) return { done : true } ;
						return { done : false , value : buf } ;
					}
				} ;
			}
		} ;

		expect( satisfiable ? 2 : 1 ) ;
		stop( ) ;

		stream.once( 'readable' , function ( ) {

			var instance = sat.from.dcnf( iterable ) ;

			if ( !satisfiable ) {
				assert.ok( !sat.decide( instance ) ) ;
			}

			else {
				assert.ok( sat.decide( instance ) ) ;
				var certificate = sat.solve( instance ).next( ).value ;
				if ( !certificate ) assert.ok( false , 'missing certificate' ) ;
				else assert.ok( sat.verify( instance , certificate ) ) ;
			}

			start( ) ;

		} ) ;

	} ) ;
}

T( 'uf20-01' , 1 ) ;
T( 'uf20-02' , 1 ) ;
T( 'uf20-03' , 1 ) ;
T( 'uf20-04' , 1 ) ;
T( 'uf20-05' , 1 ) ;
T( 'uf20-06' , 1 ) ;
T( 'uf20-07' , 1 ) ;
T( 'uf20-08' , 1 ) ;
T( 'uf20-09' , 1 ) ;
T( 'uf20-010' , 1 ) ;
<commit_msg>remove incorrect use of streams<commit_after>
var compare = require( 'aureooms-js-compare' ) ;
var itertools = require( 'aureooms-js-itertools' ) ;

var lex = compare.lexicographical( compare.increasing ) ;
var list = itertools.list ;

function T ( name , satisfiable ) {

	test( name , function ( assert ) {

		var fs = require( 'fs' ) ;

		var filename = './test/js/data/' + name + '.cnf' ;
		var iterable = fs.readFileSync( filename , { encoding : 'utf8' } ) ;

		var instance = sat.from.dcnf( iterable ) ;

		if ( !satisfiable ) {
			assert.ok( !sat.decide( instance ) ) ;
		}

		else {
			assert.ok( sat.decide( instance ) ) ;
			var certificate = sat.solve( instance ).next( ).value ;
			if ( !certificate ) assert.ok( false , 'missing certificate' ) ;
			else assert.ok( sat.verify( instance , certificate ) ) ;
		}

	} ) ;
}

T( 'uf20-01' , 1 ) ;
T( 'uf20-02' , 1 ) ;
T( 'uf20-03' , 1 ) ;
T( 'uf20-04' , 1 ) ;
T( 'uf20-05' , 1 ) ;
T( 'uf20-06' , 1 ) ;
T( 'uf20-07' , 1 ) ;
T( 'uf20-08' , 1 ) ;
T( 'uf20-09' , 1 ) ;
T( 'uf20-010' , 1 ) ;
<|endoftext|>


<commit_before>var SqlString = exports;

SqlString.escape = function(val, stringifyObjects) {
  if (val === undefined || val === null) {
    return 'NULL';
  }

  switch (typeof val) {
    case 'boolean': return (val) ? 'true' : 'false';
    case 'number': return val+'';
  }

  if (val instanceof Date) {
    val = SqlString.dateToString(val);
  }

  if (Buffer.isBuffer(val)) {
    return SqlString.bufferToString(val);
  }

  if (Array.isArray(val)) {
    return val.map(SqlString.escape).join(', ');
  }

  if (typeof val === 'object') {
    if (stringifyObjects) {
      val = val.toString();
    } else {
      return SqlString.objectToValues(val);
    }
  }

  val = val.replace(/[\0\n\r\b\t\\\'\"\x1a]/g, function(s) {
    switch(s) {
      case "\0": return "\\0";
      case "\n": return "\\n";
      case "\r": return "\\r";
      case "\b": return "\\b";
      case "\t": return "\\t";
      case "\x1a": return "\\Z";
      default: return "\\"+s;
    }
  });
  return "'"+val+"'";
};

function zeroPad(number) {
  return (number < 10)
    ? '0' + number
    : number;
}

SqlString.format = function(sql, values) {
  values = [].concat(values);

  return sql.replace(/\?/g, function(match) {
    if (!values.length) {
      return match;
    }

    return SqlString.escape(values.shift());
  });
};

SqlString.dateToString = function(date) {
  var year   = date.getFullYear();
  var month  = zeroPad(date.getMonth() + 1);
  var day    = zeroPad(date.getDate());
  var hour   = zeroPad(date.getHours());
  var minute = zeroPad(date.getMinutes());
  var second = zeroPad(date.getSeconds());

  return year + '-' + month + '-' + day + ' ' + hour + ':' + minute + ':' + second;
};

SqlString.bufferToString = function(buffer) {
  var hex = '';
  try {
    hex = buffer.toString('hex');
  } catch (err) {
    // node v0.4.x does not support hex / throws unknown encoding error
    for (var i = 0; i < buffer.length; i++) {
      var byte = buffer[i];
      hex += zeroPad(byte.toString(16));
    }
  }

  return "X'" + hex+ "'";
};

SqlString.objectToValues = function(object) {
  var values = [];
  for (var key in object) {
    var value = object[key];
    if(typeof value !== 'function')
      values.push('`' + key + '` = ' + SqlString.escape(value, true));
  }

  return values.join(', ');
};
<commit_msg>Adjust patch to my coding style<commit_after>var SqlString = exports;

SqlString.escape = function(val, stringifyObjects) {
  if (val === undefined || val === null) {
    return 'NULL';
  }

  switch (typeof val) {
    case 'boolean': return (val) ? 'true' : 'false';
    case 'number': return val+'';
  }

  if (val instanceof Date) {
    val = SqlString.dateToString(val);
  }

  if (Buffer.isBuffer(val)) {
    return SqlString.bufferToString(val);
  }

  if (Array.isArray(val)) {
    return val.map(SqlString.escape).join(', ');
  }

  if (typeof val === 'object') {
    if (stringifyObjects) {
      val = val.toString();
    } else {
      return SqlString.objectToValues(val);
    }
  }

  val = val.replace(/[\0\n\r\b\t\\\'\"\x1a]/g, function(s) {
    switch(s) {
      case "\0": return "\\0";
      case "\n": return "\\n";
      case "\r": return "\\r";
      case "\b": return "\\b";
      case "\t": return "\\t";
      case "\x1a": return "\\Z";
      default: return "\\"+s;
    }
  });
  return "'"+val+"'";
};

function zeroPad(number) {
  return (number < 10)
    ? '0' + number
    : number;
}

SqlString.format = function(sql, values) {
  values = [].concat(values);

  return sql.replace(/\?/g, function(match) {
    if (!values.length) {
      return match;
    }

    return SqlString.escape(values.shift());
  });
};

SqlString.dateToString = function(date) {
  var year   = date.getFullYear();
  var month  = zeroPad(date.getMonth() + 1);
  var day    = zeroPad(date.getDate());
  var hour   = zeroPad(date.getHours());
  var minute = zeroPad(date.getMinutes());
  var second = zeroPad(date.getSeconds());

  return year + '-' + month + '-' + day + ' ' + hour + ':' + minute + ':' + second;
};

SqlString.bufferToString = function(buffer) {
  var hex = '';
  try {
    hex = buffer.toString('hex');
  } catch (err) {
    // node v0.4.x does not support hex / throws unknown encoding error
    for (var i = 0; i < buffer.length; i++) {
      var byte = buffer[i];
      hex += zeroPad(byte.toString(16));
    }
  }

  return "X'" + hex+ "'";
};

SqlString.objectToValues = function(object) {
  var values = [];
  for (var key in object) {
    var value = object[key];
    if(typeof value === 'function') {
      continue;
    }

    values.push('`' + key + '` = ' + SqlString.escape(value, true));
  }

  return values.join(', ');
};
<|endoftext|>


<commit_before>var debug    = require('debug')('socializr:provider:facebook')
  , stream   = require('stream')
  , util     = require('util')
  , request  = require('superagent')
  , uuid     = require('node-uuid')
  , _        = require('underscore')
  , oauth1a  = require('../auth/oauth1a')
  , PubSubConnection  = require('../auth/pubsub')
  , Message = require('../message')

  , Transform = stream.Transform

  , FB_GRAPH_URL = 'https://graph.facebook.com/v2.2/'

  , FB_DEFAULT_PAGE_SUBSCRIBED_FIELDS = [
    'feed'
  ]
;

function Facebook(options){

  options = _.extend({
    filters: []
  },options);

  Transform.call(this, {
    objectMode: true
  });

  this.appId          = options.appId;
  this.appSecret      = options.appSecret;
  this.appAccessToken = this.getApplicationToken();
  this.subscriptionCallbackURL = options.subscriptionCallbackURL;
  this.pubsub         = options.pubsub || new PubSubConnection( this.appSecret, this);
  this.uuid           = uuid.v1();

  this._filters = options.filters;
  this._pages = [];
};
util.inherits(Facebook, Transform);

Facebook.prototype.stream = function(request, auth, socializr){
  if( !this._piped){
    this._piped = true;
    this.pubsub
    .pipe( this)
    .pipe( socializr);
    this.on('warning', socializr._onError.bind(socializr));
    var data, i;
    this._pages = this._pages.concat( request.pages);
    for( i=0; i<request.pages.length; i++){
      data = request.pages[i];
      debug('Subscribing to [ %s ]',data.name);
      this.subscribeTo( data.page, data.access_token, function(res){
        debug('Subscription responded %s',res.error||res.text);
      });
    }
  }
  return this;
};

Facebook.prototype.unstream = function(request, auth, socializr){

  return this;
};

Facebook.prototype.auth = function(auth){
  auth._provider = this;
  return auth;
};

Facebook.prototype.getApplicationToken = function(cb){
  if( cb){
    this._graphRequest( 'oauth/access_token', 'GET', {
      client_id:      this.appId,
      client_secret:  this.appSecret,
      grant_type:     'client_credentials'
    }, function(res){
      cb&&cb(res);
    });
  }
  return [
    this.appId,
    this.appSecret
  ].join('|');
};

Facebook.prototype.getTokenInfo = function(token, cb){
  this._graphRequest( 'debug_token', 'GET', {
    input_token:  token,
    access_token: this.appAccessToken
  }, function(res){
    cb&&cb(res);
  });
};

Facebook.prototype.exchangeToken = function(token, cb){
  this._graphRequest( 'oauth/access_token', 'GET', {
    grant_type:         'fb_exchange_token',
    client_id:          this.appId,
    client_secret:      this.appSecret,
    fb_exchange_token:  token
  }, function(res){
    cb&&cb(res);
  });
};

Facebook.prototype.subscribeTo = function(id,token,cb){
  this._graphRequest( id + '/subscribed_apps', 'POST', {
    access_token: token
  },function(res){
    cb&&cb(res);
  });
};

Facebook.prototype.unsubscribe = function(id,token,cb){
  this._graphRequest( id + '/subscribed_apps', 'DELETE', {
    access_token: token
  },function(res){
    cb&&cb(res);
  });
};

Facebook.prototype.subscribe = function(type,cb){
  this.subscribedFields = FB_DEFAULT_PAGE_SUBSCRIBED_FIELDS;

  var verify_token = this.pubsub.verifyToken();

  this._graphRequest( this.appId + '/subscriptions', 'POST', {
    object:       type || 'page',
    callback_url: this.subscriptionCallbackURL,
    fields:       this.subscribedFields.join(','),
    verify_token: verify_token,
    access_token: this.appAccessToken
  },function(res){
    cb&&cb(res);
  });
};

Facebook.prototype.getUserAccounts = function(user, token, cb){
  this._graphRequest( user + '/accounts', 'GET', {
    access_token: token
  }, function(res){
    cb&&cb(res);
  });
};

Facebook.prototype.install = function(pageId, token, cb){
  this._graphRequest( pageId + '/tabs', 'POST', {
    app_id:       this.appId,
    access_token: token
  }, function(res){
    cb&&cb(res);
  });
};

Facebook.prototype.uninstall = function(pageId, token, cb){
  var self = this;
  this._graphRequest( pageId + '/tabs/app_' + this.appId, 'DELETE', {
    access_token: token
  }, function(res){
    cb&&cb(res);
  });
};

Facebook.prototype._transform = function(chunk, encoding, done){
  var expected = 0
    , stream = this
  ;
  for( var i in chunk.entry){
    for( var j in chunk.entry[i].changes){
      expected++;
      this._graphRequest( chunk.entry[i].changes[j].value.post_id, 'GET', {}, function(res){
        expected--;

        if( res.error){
          debug('Error requesting data. Server responded %s', res.error);
        }else{

          try {
            var data = JSON.parse(res.text);
            if( this.include(data)) {
              stream.push(
                new Message( stream, data )
              );
            }
          }catch(err){
            debug('Data parse error. Error parsing chunk. Parser trew %j',err);
          }
        }

        if( !expected){
          done();
        }
      })
    }
  }
};

Facebook.prototype.include = function(data){
  var pass = true;
  this._filters.forEach( function(cb){
    if( !cb(data)){
      pass = false;
      return false;
    }
  });
  return pass;
};

Facebook.prototype._graphRequest = function(endpoint, method, data, cb){

  var url = FB_GRAPH_URL + endpoint
    , req
  ;

  if( !data.hasOwnProperty('access_token')){
    data.access_token = this.appAccessToken;
  }

  switch( method.toUpperCase()){

    case 'GET':

      req = request.get(url)
              .query(data)
              .end( function(res){
                cb&&cb( res);
              })
      break;

    case 'POST':

      req = request.post(url)
              .send(data)
              .end( function(res){
                cb&&cb( res);
              })
      break;

    case 'DELETE':

      req = request.del(url)
              .query(data)
              .send(data)
              .end( function(res){
                cb&&cb( res);
              })
      break;

  }

};

module.exports = Facebook;
<commit_msg>Fixed syntax errors and refactored for better error checking<commit_after>var debug    = require('debug')('socializr:provider:facebook')
  , stream   = require('stream')
  , util     = require('util')
  , request  = require('superagent')
  , uuid     = require('node-uuid')
  , _        = require('underscore')
  , oauth1a  = require('../auth/oauth1a')
  , PubSubConnection  = require('../auth/pubsub')
  , Message = require('../message')

  , Transform = stream.Transform

  , FB_GRAPH_URL = 'https://graph.facebook.com/v2.2/'

  , FB_DEFAULT_PAGE_SUBSCRIBED_FIELDS = [
    'feed'
  ]
;

function Facebook(options){

  options = _.extend({
    filters: []
  },options);

  Transform.call(this, {
    objectMode: true
  });

  this.appId          = options.appId;
  this.appSecret      = options.appSecret;
  this.appAccessToken = this.getApplicationToken();
  this.subscriptionCallbackURL = options.subscriptionCallbackURL;
  this.pubsub         = options.pubsub || new PubSubConnection( this.appSecret, this);
  this.uuid           = uuid.v1();

  this._filters = options.filters or [];
  this._pages = [];
};
util.inherits(Facebook, Transform);

Facebook.prototype.stream = function(request, auth, socializr){
  if( !this._piped){
    this._piped = true;
    this.pubsub
    .pipe( this)
    .pipe( socializr);
    this.on('warning', socializr._onError.bind(socializr));
    var data, i;
    this._pages = this._pages.concat( request.pages);
    for( i=0; i<request.pages.length; i++){
      data = request.pages[i];
      debug('Subscribing to [ %s ]',data.name);
      this.subscribeTo( data.page, data.access_token, function(res){
        debug('Subscription responded %s',res.error||res.text);
      });
    }
  }
  return this;
};

Facebook.prototype.unstream = function(request, auth, socializr){

  return this;
};

Facebook.prototype.auth = function(auth){
  auth._provider = this;
  return auth;
};

Facebook.prototype.getApplicationToken = function(cb){
  if( cb){
    this._graphRequest( 'oauth/access_token', 'GET', {
      client_id:      this.appId,
      client_secret:  this.appSecret,
      grant_type:     'client_credentials'
    }, function(res){
      cb&&cb(res);
    });
  }
  return [
    this.appId,
    this.appSecret
  ].join('|');
};

Facebook.prototype.getTokenInfo = function(token, cb){
  this._graphRequest( 'debug_token', 'GET', {
    input_token:  token,
    access_token: this.appAccessToken
  }, function(res){
    cb&&cb(res);
  });
};

Facebook.prototype.exchangeToken = function(token, cb){
  this._graphRequest( 'oauth/access_token', 'GET', {
    grant_type:         'fb_exchange_token',
    client_id:          this.appId,
    client_secret:      this.appSecret,
    fb_exchange_token:  token
  }, function(res){
    cb&&cb(res);
  });
};

Facebook.prototype.subscribeTo = function(id,token,cb){
  this._graphRequest( id + '/subscribed_apps', 'POST', {
    access_token: token
  },function(res){
    cb&&cb(res);
  });
};

Facebook.prototype.unsubscribe = function(id,token,cb){
  this._graphRequest( id + '/subscribed_apps', 'DELETE', {
    access_token: token
  },function(res){
    cb&&cb(res);
  });
};

Facebook.prototype.subscribe = function(type,cb){
  this.subscribedFields = FB_DEFAULT_PAGE_SUBSCRIBED_FIELDS;

  var verify_token = this.pubsub.verifyToken();

  this._graphRequest( this.appId + '/subscriptions', 'POST', {
    object:       type || 'page',
    callback_url: this.subscriptionCallbackURL,
    fields:       this.subscribedFields.join(','),
    verify_token: verify_token,
    access_token: this.appAccessToken
  },function(res){
    cb&&cb(res);
  });
};

Facebook.prototype.getUserAccounts = function(user, token, cb){
  this._graphRequest( user + '/accounts', 'GET', {
    access_token: token
  }, function(res){
    cb&&cb(res);
  });
};

Facebook.prototype.install = function(pageId, token, cb){
  this._graphRequest( pageId + '/tabs', 'POST', {
    app_id:       this.appId,
    access_token: token
  }, function(res){
    cb&&cb(res);
  });
};

Facebook.prototype.uninstall = function(pageId, token, cb){
  var self = this;
  this._graphRequest( pageId + '/tabs/app_' + this.appId, 'DELETE', {
    access_token: token
  }, function(res){
    cb&&cb(res);
  });
};

Facebook.prototype._transform = function(chunk, encoding, done){
  var expected = 0
    , stream = this
  ;
  for( var i in chunk.entry){
    for( var j in chunk.entry[i].changes){
      expected++;
      this._graphRequest( chunk.entry[i].changes[j].value.post_id, 'GET', {}, function(res){
        expected--;

        if( res.error){
          debug('Error requesting data. Server responded %s', res.error);
        }else{

          try {
            var data = JSON.parse(res.text);
          }catch(err){
            debug('Error parsing chunk. Parser threw error %j',err);
          }
          if( data && stream.include(data)) {
            stream.push(
              new Message( stream, data )
            );
          }
        }

        if( !expected){
          done();
        }
      })
    }
  }
};

Facebook.prototype.include = function(data){
  if(this._filters){
    var pass = true;
    this._filters.forEach( function(cb){
      if( !cb(data)){
        pass = false;
        return false;
      }
    });
    return pass;
  }
  return true;
};

Facebook.prototype._graphRequest = function(endpoint, method, data, cb){

  var url = FB_GRAPH_URL + endpoint
    , req
  ;

  if( !data.hasOwnProperty('access_token')){
    data.access_token = this.appAccessToken;
  }

  switch( method.toUpperCase()){

    case 'GET':

      req = request.get(url)
              .query(data)
              .end( function(res){
                cb&&cb( res);
              })
      break;

    case 'POST':

      req = request.post(url)
              .send(data)
              .end( function(res){
                cb&&cb( res);
              })
      break;

    case 'DELETE':

      req = request.del(url)
              .query(data)
              .send(data)
              .end( function(res){
                cb&&cb( res);
              })
      break;

  }

};

module.exports = Facebook;
<|endoftext|>


<commit_before>module.exports = Module;

function Module() {}

Module.prototype.start = function() {
  console.log('start', this.$happn);
}

Module.prototype.stop = function() {
  // console.log('stop', this.$happn.config);
}

Module.prototype.getThingFromConfig = function(callback) {
  callback(null, this.$happn.config.configThing);
}
<commit_msg>sssht<commit_after>module.exports = Module;

function Module() {}

Module.prototype.start = function() {
  // console.log('start', this.$happn);
}

Module.prototype.stop = function() {
  // console.log('stop', this.$happn.config);
}

Module.prototype.getThingFromConfig = function(callback) {
  callback(null, this.$happn.config.configThing);
}
<|endoftext|>


<commit_before>import Miox from 'miox';
import Engine from 'miox-vue2x';
import Router from 'miox-router';
import Animate from 'miox-animation';

// webviews
import A from './webviews/A.vue';
import B from './webviews/B.vue';
import C from './webviews/C.vue';
import D from './webviews/D.vue';
import E from './webviews/E.vue';

let switcher = false, listener;

describe('app test:', () => {
    beforeEach(removeAll, 1000);

    it('normal', cb => progress({ max: 2 }, cb, async app => expect(app.webView.$el.innerHTML).toEqual('A')), 2000);

    it('push 3 steps', cb => {
        progress({ max: 3 }, cb, async app => {
            expect(app.webView.text).toEqual('A');
            expect(getPool(app)).toEqual('A');
            app.push('/b');
            await delay(300);
            expect(app.webView.text).toEqual('B');
            expect(getPool(app)).toEqual('A.B');
            app.push('/c');
            await delay(300);
            expect(app.webView.text).toEqual('C');
            expect(getPool(app)).toEqual('A.B.C');
        });
    }, 10000);

    it('change switcher', cb => {
        progress({ max: 3, session: false }, cb, async app => {
            expect(app.webView.text).toEqual('A');
            expect(getPool(app)).toEqual('A');
            app.push('/b');
            await delay(300);
            expect(app.webView.text).toEqual('B');
            expect(getPool(app)).toEqual('A.B');
            app.push('/c');
            await delay(300);
            expect(app.webView.text).toEqual('C');
            expect(getPool(app)).toEqual('A.B.C');
            switcher = true;
            app.go(-1);
            await delay(300);
            expect(app.webView.text).toEqual('E');
            expect(getPool(app)).toEqual('A.E.C');
        });
    }, 10000);

    it('session change switcher', cb => {
        progress({ max: 3, session: true }, cb, async app => {
            expect(app.webView.text).toEqual('A');
            expect(getPool(app)).toEqual('A');
            app.push('/b');
            await delay(300);
            expect(app.webView.text).toEqual('B');
            expect(getPool(app)).toEqual('A.B');
            app.push('/c');
            await delay(300);
            expect(app.webView.text).toEqual('C');
            expect(getPool(app)).toEqual('A.B.C');
            switcher = true;
            app.go(-1);
            await delay(300);
            expect(app.webView.text).toEqual('E');
            expect(getPool(app)).toEqual('A.E.C');
        });
    }, 10000);

    it('empty pool and backward + no animate', cb => {
        progress({ max: 3, session: true }, cb, async app => {
            expect(app.webView.text).toEqual('A');
            expect(getPool(app)).toEqual('A');
            app.push('/b');
            await delay(300);
            expect(app.webView.text).toEqual('B');
            expect(getPool(app)).toEqual('A.B');
            app.push('/c');
            await delay(300);
            expect(app.webView.text).toEqual('C');
            expect(getPool(app)).toEqual('A.B.C');
            app.history.stacks = [];
            app.go(-1);
            await delay(300);
            expect(app.webView.text).toEqual('B');
            expect(getPool(app)).toEqual('B');
            app.go(-1);
            await delay(300);
            expect(app.webView.text).toEqual('A');
            expect(getPool(app)).toEqual('B.A');
        });
    }, 10000);

    it('empty pool and backward + animate', cb => {
        progress({ max: 3, session: true, animate: true }, cb, async app => {
            expect(app.webView.text).toEqual('A');
            expect(getPool(app)).toEqual('A');
            app.push('/b');
            await delay(1000);
            expect(app.webView.text).toEqual('B');
            expect(getPool(app)).toEqual('A.B');
            app.push('/c');
            await delay(1000);
            expect(app.webView.text).toEqual('C');
            expect(getPool(app)).toEqual('A.B.C');
            app.history.stacks = [];
            app.go(-1);
            await delay(1000);
            expect(app.webView.text).toEqual('B');
            expect(getPool(app)).toEqual('B');
            app.go(-1);
            await delay(1000);
            expect(app.webView.text).toEqual('A');
            expect(getPool(app)).toEqual('A.B');
        });
    }, 10000);

});

function removeAll() {
    document
        .querySelectorAll('.mx-app')
        .forEach(child => child.parentNode.removeChild(child));

    global.history.pushState(null, document.title, '/');

    [A, B, C, D, E].forEach(cmp => {
        delete cmp.dic;
    });

    switcher = false;

    if (typeof listener === 'function') {
        listener();
    }
}

async function delay(time = 0) {
    await new Promise(resolve => setTimeout(resolve, time));
}

function progress(options, cb, fn) {
    const app = new Miox(options);
    const route = new Router();

    app.on('app:end', () => fn(app).then(cb).catch(e => fail(e)));

    route.patch('/', async ctx => await ctx.render(A));
    route.patch('/c', async ctx => await ctx.render(C));
    route.patch('/d', async ctx => await ctx.render(D));
    route.patch('/b', async ctx => {
        if (switcher) {
            await ctx.render(E)
        } else {
            await ctx.render(B)
        }
    });

    app.set('engine', Engine);
    if (options.animate) {
        app.set('animate', Animate('slide'));
    }
    app.use(route.routes());
    listener = app.listen();
}

function getPool(app) {
    return app.history.stacks.map(v => v.text).join('.');
}<commit_msg>test more stage<commit_after>import Miox from 'miox';
import Engine from 'miox-vue2x';
import Router from 'miox-router';
import Animate from 'miox-animation';

// webviews
import A from './webviews/A.vue';
import B from './webviews/B.vue';
import C from './webviews/C.vue';
import D from './webviews/D.vue';
import E from './webviews/E.vue';

let switcher = false, listener;

describe('Miox全场景测试:', () => {
    beforeEach(removeAll, 1000);

    it('简单场景', cb => {
        progress({ max: 2 }, cb, async app => {
            expect(app.webView.$el.innerHTML).toEqual('A');
            expect(getPool(app)).toEqual('A');
        })
    }, 2000);

    it('插入3个地址:不带session:最大1个页面', cb => {
        progress({ max: 1 }, cb, async app => {
            expect(app.webView.text).toEqual('A');
            expect(getPool(app)).toEqual('A');
            app.push('/b');
            await delay(300);
            expect(app.webView.text).toEqual('B');
            expect(getPool(app)).toEqual('B');
            app.push('/c');
            await delay(300);
            expect(app.webView.text).toEqual('C');
            expect(getPool(app)).toEqual('C');
        });
    }, 10000);

    it('插入3个地址:带session:最大1个页面', cb => {
        progress({ max: 1, session: true, animate: true }, cb, async app => {
            expect(app.webView.text).toEqual('A');
            expect(getPool(app)).toEqual('A');
            app.push('/b');
            await delay(1000);
            expect(app.webView.text).toEqual('B');
            expect(getPool(app)).toEqual('B');
            app.push('/c');
            await delay(1000);
            expect(app.webView.text).toEqual('C');
            expect(getPool(app)).toEqual('C');
        });
    }, 10000);

    it('插入3个地址:不带session:最大3个页面', cb => {
        progress({ max: 3 }, cb, async app => {
            expect(app.webView.text).toEqual('A');
            expect(getPool(app)).toEqual('A');
            app.push('/b');
            await delay(300);
            expect(app.webView.text).toEqual('B');
            expect(getPool(app)).toEqual('A.B');
            app.push('/c');
            await delay(300);
            expect(app.webView.text).toEqual('C');
            expect(getPool(app)).toEqual('A.B.C');
        });
    }, 10000);

    it('插入3个地址:带session:最大3个页面', cb => {
        progress({ max: 3, session: true, animate: true }, cb, async app => {
            expect(app.webView.text).toEqual('A');
            expect(getPool(app)).toEqual('A');
            app.push('/b');
            await delay(1000);
            expect(app.webView.text).toEqual('B');
            expect(getPool(app)).toEqual('A.B');
            app.push('/c');
            await delay(1000);
            expect(app.webView.text).toEqual('C');
            expect(getPool(app)).toEqual('A.B.C');
        });
    }, 10000);

    it('回退场景:改变渲染变量:不带session:最大1个页面', cb => {
        progress({ max: 1 }, cb, async app => {
            expect(app.webView.text).toEqual('A');
            expect(getPool(app)).toEqual('A');
            app.push('/b');
            await delay(300);
            expect(app.webView.text).toEqual('B');
            expect(getPool(app)).toEqual('B');
            app.push('/c');
            await delay(300);
            expect(app.webView.text).toEqual('C');
            expect(getPool(app)).toEqual('C');
            switcher = true;
            app.go(-1);
            await delay(300);
            expect(app.webView.text).toEqual('E');
            expect(getPool(app)).toEqual('E');
        });
    }, 10000);

    it('回退场景:改变渲染变量:带session:最大1个页面', cb => {
        progress({ max: 1, session: true, animate: true }, cb, async app => {
            expect(app.webView.text).toEqual('A');
            expect(getPool(app)).toEqual('A');
            app.push('/b');
            await delay(1000);
            expect(app.webView.text).toEqual('B');
            expect(getPool(app)).toEqual('B');
            app.push('/c');
            await delay(1000);
            expect(app.webView.text).toEqual('C');
            expect(getPool(app)).toEqual('C');
            switcher = true;
            app.go(-1);
            await delay(1000);
            expect(app.webView.text).toEqual('E');
            expect(getPool(app)).toEqual('E');
        });
    }, 10000);

    it('回退场景:改变渲染变量:不带session:最大3个页面', cb => {
        progress({ max: 3 }, cb, async app => {
            expect(app.webView.text).toEqual('A');
            expect(getPool(app)).toEqual('A');
            app.push('/b');
            await delay(300);
            expect(app.webView.text).toEqual('B');
            expect(getPool(app)).toEqual('A.B');
            app.push('/c');
            await delay(300);
            expect(app.webView.text).toEqual('C');
            expect(getPool(app)).toEqual('A.B.C');
            switcher = true;
            app.go(-1);
            await delay(300);
            expect(app.webView.text).toEqual('E');
            expect(getPool(app)).toEqual('A.E.C');
        });
    }, 10000);

    it('回退场景:改变渲染变量:带session:最大3个页面', cb => {
        progress({ max: 3, session: true, animate: true }, cb, async app => {
            expect(app.webView.text).toEqual('A');
            expect(getPool(app)).toEqual('A');
            app.push('/b');
            await delay(1000);
            expect(app.webView.text).toEqual('B');
            expect(getPool(app)).toEqual('A.B');
            app.push('/c');
            await delay(1000);
            expect(app.webView.text).toEqual('C');
            expect(getPool(app)).toEqual('A.B.C');
            switcher = true;
            app.go(-1);
            await delay(1000);
            expect(app.webView.text).toEqual('E');
            expect(getPool(app)).toEqual('A.E.C');
        });
    }, 10000);

    it('中途刷新场景:不带session:最大1个页面', cb => {
        progress({ max: 1 }, cb, async app => {
            expect(app.webView.text).toEqual('A');
            expect(getPool(app)).toEqual('A');
            app.push('/b');
            await delay(300);
            expect(app.webView.text).toEqual('B');
            expect(getPool(app)).toEqual('B');
            app.push('/c');
            await delay(300);
            expect(app.webView.text).toEqual('C');
            expect(getPool(app)).toEqual('C');
            app.history.stacks = [];
            app.go(-1);
            await delay(300);
            expect(app.webView.text).toEqual('B');
            expect(getPool(app)).toEqual('B');
            app.go(-1);
            await delay(300);
            expect(app.webView.text).toEqual('A');
            expect(getPool(app)).toEqual('A');
        });
    }, 10000);

    it('中途刷新场景:带session:最大1个页面', cb => {
        progress({ max: 1, session: true, animate: true }, cb, async app => {
            expect(app.webView.text).toEqual('A');
            expect(getPool(app)).toEqual('A');
            app.push('/b');
            await delay(1000);
            expect(app.webView.text).toEqual('B');
            expect(getPool(app)).toEqual('B');
            app.push('/c');
            await delay(1000);
            expect(app.webView.text).toEqual('C');
            expect(getPool(app)).toEqual('C');
            app.history.stacks = [];
            app.go(-1);
            await delay(1000);
            expect(app.webView.text).toEqual('B');
            expect(getPool(app)).toEqual('B');
            app.go(-1);
            await delay(1000);
            expect(app.webView.text).toEqual('A');
            expect(getPool(app)).toEqual('A');
        });
    }, 10000);

    it('中途刷新场景:不带session:最大3个页面', cb => {
        progress({ max: 3 }, cb, async app => {
            expect(app.webView.text).toEqual('A');
            expect(getPool(app)).toEqual('A');
            app.push('/b');
            await delay(300);
            expect(app.webView.text).toEqual('B');
            expect(getPool(app)).toEqual('A.B');
            app.push('/c');
            await delay(300);
            expect(app.webView.text).toEqual('C');
            expect(getPool(app)).toEqual('A.B.C');
            app.history.stacks = [];
            app.go(-1);
            await delay(300);
            expect(app.webView.text).toEqual('B');
            expect(getPool(app)).toEqual('B');
            app.go(-1);
            await delay(300);
            expect(app.webView.text).toEqual('A');
            expect(getPool(app)).toEqual('B.A');
        });
    }, 10000);

    it('中途刷新场景:带session:最大3个页面', cb => {
        progress({ max: 3, session: true, animate: true }, cb, async app => {
            expect(app.webView.text).toEqual('A');
            expect(getPool(app)).toEqual('A');
            app.push('/b');
            await delay(1000);
            expect(app.webView.text).toEqual('B');
            expect(getPool(app)).toEqual('A.B');
            app.push('/c');
            await delay(1000);
            expect(app.webView.text).toEqual('C');
            expect(getPool(app)).toEqual('A.B.C');
            app.history.stacks = [];
            app.go(-1);
            await delay(1000);
            expect(app.webView.text).toEqual('B');
            expect(getPool(app)).toEqual('B');
            app.go(-1);
            await delay(1000);
            expect(app.webView.text).toEqual('A');
            expect(getPool(app)).toEqual('A.B');
        });
    }, 10000);

});

function removeAll() {
    document
        .querySelectorAll('.mx-app')
        .forEach(child => child.parentNode.removeChild(child));

    global.history.pushState(null, document.title, '/');

    [A, B, C, D, E].forEach(cmp => {
        delete cmp.dic;
    });

    switcher = false;

    if (typeof listener === 'function') {
        listener();
    }
}

async function delay(time = 0) {
    await new Promise(resolve => setTimeout(resolve, time));
}

function progress(options, cb, fn) {
    const app = new Miox(options);
    const route = new Router();

    app.on('app:end', () => fn(app).then(cb).catch(e => fail(e)));

    route.patch('/', async ctx => await ctx.render(A));
    route.patch('/c', async ctx => await ctx.render(C));
    route.patch('/d', async ctx => await ctx.render(D));
    route.patch('/b', async ctx => {
        if (switcher) {
            await ctx.render(E)
        } else {
            await ctx.render(B)
        }
    });

    app.set('engine', Engine);
    if (options.animate) {
        app.set('animate', Animate('slide'));
    }
    app.use(route.routes());
    listener = app.listen();
}

function getPool(app) {
    return app.history.stacks.map(v => v.text).join('.');
}<|endoftext|>