<commit_before>/* eslint-disable new-cap */

import Exception from '../exception';
import {isArray, indexOf, extend} from '../utils';
import AST from './ast';

const slice = [].slice;

export function Compiler() {}

// the foundHelper register will disambiguate helper lookup from finding a
// function in a context. This is necessary for mustache compatibility, which
// requires that context functions in blocks are evaluated by blockHelperMissing,
// and then proceed as if the resulting value was provided to blockHelperMissing.

Compiler.prototype = {
  compiler: Compiler,

  equals: function(other) {
    let len = this.opcodes.length;
    if (other.opcodes.length !== len) {
      return false;
    }

    for (let i = 0; i < len; i++) {
      let opcode = this.opcodes[i],
          otherOpcode = other.opcodes[i];
      if (opcode.opcode !== otherOpcode.opcode || !argEquals(opcode.args, otherOpcode.args)) {
        return false;
      }
    }

    // We know that length is the same between the two arrays because they are directly tied
    // to the opcode behavior above.
    len = this.children.length;
    for (let i = 0; i < len; i++) {
      if (!this.children[i].equals(other.children[i])) {
        return false;
      }
    }

    return true;
  },

  guid: 0,

  compile: function(program, options) {
    this.sourceNode = [];
    this.opcodes = [];
    this.children = [];
    this.options = options;
    this.stringParams = options.stringParams;
    this.trackIds = options.trackIds;

    options.blockParams = options.blockParams || [];

    // These changes will propagate to the other compiler components
    let knownHelpers = options.knownHelpers;
    options.knownHelpers = {
      'helperMissing': true,
      'blockHelperMissing': true,
      'each': true,
      'if': true,
      'unless': true,
      'with': true,
      'log': true,
      'lookup': true
    };
    if (knownHelpers) {
      for (let name in knownHelpers) {
        /* istanbul ignore else */
        if (name in knownHelpers) {
          this.options.knownHelpers[name] = knownHelpers[name];
        }
      }
    }

    return this.accept(program);
  },

  compileProgram: function(program) {
    let childCompiler = new this.compiler(), // eslint-disable-line new-cap
        result = childCompiler.compile(program, this.options),
        guid = this.guid++;

    this.usePartial = this.usePartial || result.usePartial;

    this.children[guid] = result;
    this.useDepths = this.useDepths || result.useDepths;

    return guid;
  },

  accept: function(node) {
    /* istanbul ignore next: Sanity code */
    if (!this[node.type]) {
      throw new Exception('Unknown type: ' + node.type, node);
    }

    this.sourceNode.unshift(node);
    let ret = this[node.type](node);
    this.sourceNode.shift();
    return ret;
  },

  Program: function(program) {
    this.options.blockParams.unshift(program.blockParams);

    let body = program.body,
        bodyLength = body.length;
    for (let i = 0; i < bodyLength; i++) {
      this.accept(body[i]);
    }

    this.options.blockParams.shift();

    this.isSimple = bodyLength === 1;
    this.blockParams = program.blockParams ? program.blockParams.length : 0;

    return this;
  },

  BlockStatement: function(block) {
    transformLiteralToPath(block);

    let program = block.program,
        inverse = block.inverse;

    program = program && this.compileProgram(program);
    inverse = inverse && this.compileProgram(inverse);

    let type = this.classifySexpr(block);

    if (type === 'helper') {
      this.helperSexpr(block, program, inverse);
    } else if (type === 'simple') {
      this.simpleSexpr(block);

      // now that the simple mustache is resolved, we need to
      // evaluate it by executing `blockHelperMissing`
      this.opcode('pushProgram', program);
      this.opcode('pushProgram', inverse);
      this.opcode('emptyHash');
      this.opcode('blockValue', block.path.original);
    } else {
      this.ambiguousSexpr(block, program, inverse);

      // now that the simple mustache is resolved, we need to
      // evaluate it by executing `blockHelperMissing`
      this.opcode('pushProgram', program);
      this.opcode('pushProgram', inverse);
      this.opcode('emptyHash');
      this.opcode('ambiguousBlockValue');
    }

    this.opcode('append');
  },

  DecoratorBlock(decorator) {
    let program = decorator.program && this.compileProgram(decorator.program);
    let params = this.setupFullMustacheParams(decorator, program, undefined),
        path = decorator.path;

    this.useDecorators = true;
    this.opcode('registerDecorator', params.length, path.original);
  },

  PartialStatement: function(partial) {
    this.usePartial = true;

    let program = partial.program;
    if (program) {
      program = this.compileProgram(partial.program);
    }

    let params = partial.params;
    if (params.length > 1) {
      throw new Exception('Unsupported number of partial arguments: ' + params.length, partial);
    } else if (!params.length) {
      if (this.options.explicitPartialContext) {
        this.opcode('pushLiteral', 'undefined');
      } else {
        params.push({type: 'PathExpression', parts: [], depth: 0});
      }
    }

    let partialName = partial.name.original,
        isDynamic = partial.name.type === 'SubExpression';
    if (isDynamic) {
      this.accept(partial.name);
    }

    this.setupFullMustacheParams(partial, program, undefined, true);

    let indent = partial.indent || '';
    if (this.options.preventIndent && indent) {
      this.opcode('appendContent', indent);
      indent = '';
    }

    this.opcode('invokePartial', isDynamic, partialName, indent);
    this.opcode('append');
  },
  PartialBlockStatement: function(partialBlock) {
    this.PartialStatement(partialBlock);
  },

  MustacheStatement: function(mustache) {
    this.SubExpression(mustache);

    if (mustache.escaped && !this.options.noEscape) {
      this.opcode('appendEscaped');
    } else {
      this.opcode('append');
    }
  },
  Decorator(decorator) {
    this.DecoratorBlock(decorator);
  },

  ContentStatement: function(content) {
    if (content.value) {
      this.opcode('appendContent', content.value);
    }
  },

  CommentStatement: function() {},

  SubExpression: function(sexpr) {
    transformLiteralToPath(sexpr);
    let type = this.classifySexpr(sexpr);

    if (type === 'simple') {
      this.simpleSexpr(sexpr);
    } else if (type === 'helper') {
      this.helperSexpr(sexpr);
    } else {
      this.ambiguousSexpr(sexpr);
    }
  },
  ambiguousSexpr: function(sexpr, program, inverse) {
    let path = sexpr.path,
        name = path.parts[0],
        isBlock = program != null || inverse != null;

    this.opcode('getContext', path.depth);

    this.opcode('pushProgram', program);
    this.opcode('pushProgram', inverse);

    path.strict = true;
    this.accept(path);

    this.opcode('invokeAmbiguous', name, isBlock);
  },

  simpleSexpr: function(sexpr) {
    let path = sexpr.path;
    path.strict = true;
    this.accept(path);
    this.opcode('resolvePossibleLambda');
  },

  helperSexpr: function(sexpr, program, inverse) {
    let params = this.setupFullMustacheParams(sexpr, program, inverse),
        path = sexpr.path,
        name = path.parts[0];

    if (this.options.knownHelpers[name]) {
      this.opcode('invokeKnownHelper', params.length, name);
    } else if (this.options.knownHelpersOnly) {
      throw new Exception('You specified knownHelpersOnly, but used the unknown helper ' + name, sexpr);
    } else {
      path.strict = true;
      path.falsy = true;

      this.accept(path);
      this.opcode('invokeHelper', params.length, path.original, AST.helpers.simpleId(path));
    }
  },

  PathExpression: function(path) {
    this.addDepth(path.depth);
    this.opcode('getContext', path.depth);

    let name = path.parts[0],
        scoped = AST.helpers.scopedId(path),
        blockParamId = !path.depth && !scoped && this.blockParamIndex(name);

    if (blockParamId) {
      this.opcode('lookupBlockParam', blockParamId, path.parts);
    } else if (!name) {
      // Context reference, i.e. `{{foo .}}` or `{{foo ..}}`
      this.opcode('pushContext');
    } else if (path.data) {
      this.options.data = true;
      this.opcode('lookupData', path.depth, path.parts, path.strict);
    } else {
      this.opcode('lookupOnContext', path.parts, path.falsy, path.strict, scoped);
    }
  },

  StringLiteral: function(string) {
    this.opcode('pushString', string.value);
  },

  NumberLiteral: function(number) {
    this.opcode('pushLiteral', number.value);
  },

  BooleanLiteral: function(bool) {
    this.opcode('pushLiteral', bool.value);
  },

  UndefinedLiteral: function() {
    this.opcode('pushLiteral', 'undefined');
  },

  NullLiteral: function() {
    this.opcode('pushLiteral', 'null');
  },

  Hash: function(hash) {
    let pairs = hash.pairs,
        i = 0,
        l = pairs.length;

    this.opcode('pushHash');

    for (; i < l; i++) {
      this.pushParam(pairs[i].value);
    }
    while (i--) {
      this.opcode('assignToHash', pairs[i].key);
    }
    this.opcode('popHash');
  },

  // HELPERS
  opcode: function(name) {
    this.opcodes.push({ opcode: name, args: slice.call(arguments, 1), loc: this.sourceNode[0].loc });
  },

  addDepth: function(depth) {
    if (!depth) {
      return;
    }

    this.useDepths = true;
  },

  classifySexpr: function(sexpr) {
    let isSimple = AST.helpers.simpleId(sexpr.path);

    let isBlockParam = isSimple && !!this.blockParamIndex(sexpr.path.parts[0]);

    // a mustache is an eligible helper if:
    // * its id is simple (a single part, not `this` or `..`)
    let isHelper = !isBlockParam && AST.helpers.helperExpression(sexpr);

    // if a mustache is an eligible helper but not a definite
    // helper, it is ambiguous, and will be resolved in a later
    // pass or at runtime.
    let isEligible = !isBlockParam && (isHelper || isSimple);

    // if ambiguous, we can possibly resolve the ambiguity now
    // An eligible helper is one that does not have a complex path, i.e. `this.foo`, `../foo` etc.
    if (isEligible && !isHelper) {
      let name = sexpr.path.parts[0],
          options = this.options;

      if (options.knownHelpers[name]) {
        isHelper = true;
      } else if (options.knownHelpersOnly) {
        isEligible = false;
      }
    }

    if (isHelper) {
      return 'helper';
    } else if (isEligible) {
      return 'ambiguous';
    } else {
      return 'simple';
    }
  },

  pushParams: function(params) {
    for (let i = 0, l = params.length; i < l; i++) {
      this.pushParam(params[i]);
    }
  },

  pushParam: function(val) {
    let value = val.value != null ? val.value : val.original || '';

    if (this.stringParams) {
      if (value.replace) {
        value = value
            .replace(/^(\.?\.\/)*/g, '')
            .replace(/\//g, '.');
      }

      if (val.depth) {
        this.addDepth(val.depth);
      }
      this.opcode('getContext', val.depth || 0);
      this.opcode('pushStringParam', value, val.type);

      if (val.type === 'SubExpression') {
        // SubExpressions get evaluated and passed in
        // in string params mode.
        this.accept(val);
      }
    } else {
      if (this.trackIds) {
        let blockParamIndex;
        if (val.parts && !AST.helpers.scopedId(val) && !val.depth) {
           blockParamIndex = this.blockParamIndex(val.parts[0]);
        }
        if (blockParamIndex) {
          let blockParamChild = val.parts.slice(1).join('.');
          this.opcode('pushId', 'BlockParam', blockParamIndex, blockParamChild);
        } else {
          value = val.original || value;
          if (value.replace) {
            value = value
                .replace(/^this(?:\.|$)/, '')
                .replace(/^\.\//, '')
                .replace(/^\.$/, '');
          }

          this.opcode('pushId', val.type, value);
        }
      }
      this.accept(val);
    }
  },

  setupFullMustacheParams: function(sexpr, program, inverse, omitEmpty) {
    let params = sexpr.params;
    this.pushParams(params);

    this.opcode('pushProgram', program);
    this.opcode('pushProgram', inverse);

    if (sexpr.hash) {
      this.accept(sexpr.hash);
    } else {
      this.opcode('emptyHash', omitEmpty);
    }

    return params;
  },

  blockParamIndex: function(name) {
    for (let depth = 0, len = this.options.blockParams.length; depth < len; depth++) {
      let blockParams = this.options.blockParams[depth],
          param = blockParams && indexOf(blockParams, name);
      if (blockParams && param >= 0) {
        return [depth, param];
      }
    }
  }
};

export function precompile(input, options, env) {
  if (input == null || (typeof input !== 'string' && input.type !== 'Program')) {
    throw new Exception('You must pass a string or Handlebars AST to Handlebars.precompile. You passed ' + input);
  }

  options = options || {};
  if (!('data' in options)) {
    options.data = true;
  }
  if (options.compat) {
    options.useDepths = true;
  }

  let ast = env.parse(input, options),
      environment = new env.Compiler().compile(ast, options);
  return new env.JavaScriptCompiler().compile(environment, options);
}

export function compile(input, options = {}, env) {
  if (input == null || (typeof input !== 'string' && input.type !== 'Program')) {
    throw new Exception('You must pass a string or Handlebars AST to Handlebars.compile. You passed ' + input);
  }

  options = extend({}, options);
  if (!('data' in options)) {
    options.data = true;
  }
  if (options.compat) {
    options.useDepths = true;
  }

  let compiled;

  function compileInput() {
    let ast = env.parse(input, options),
        environment = new env.Compiler().compile(ast, options),
        templateSpec = new env.JavaScriptCompiler().compile(environment, options, undefined, true);
    return env.template(templateSpec);
  }

  // Template is only compiled on first use and cached after that point.
  function ret(context, execOptions) {
    if (!compiled) {
      compiled = compileInput();
    }
    return compiled.call(this, context, execOptions);
  }
  ret._setup = function(setupOptions) {
    if (!compiled) {
      compiled = compileInput();
    }
    return compiled._setup(setupOptions);
  };
  ret._child = function(i, data, blockParams, depths) {
    if (!compiled) {
      compiled = compileInput();
    }
    return compiled._child(i, data, blockParams, depths);
  };
  return ret;
}

function argEquals(a, b) {
  if (a === b) {
    return true;
  }

  if (isArray(a) && isArray(b) && a.length === b.length) {
    for (let i = 0; i < a.length; i++) {
      if (!argEquals(a[i], b[i])) {
        return false;
      }
    }
    return true;
  }
}

function transformLiteralToPath(sexpr) {
  if (!sexpr.path.parts) {
    let literal = sexpr.path;
    // Casting to string here to make false and 0 literal values play nicely with the rest
    // of the system.
    sexpr.path = {
      type: 'PathExpression',
      data: false,
      depth: 0,
      parts: [literal.original + ''],
      original: literal.original + '',
      loc: literal.loc
    };
  }
}
<commit_msg>unnecessary check<commit_after>/* eslint-disable new-cap */

import Exception from '../exception';
import {isArray, indexOf, extend} from '../utils';
import AST from './ast';

const slice = [].slice;

export function Compiler() {}

// the foundHelper register will disambiguate helper lookup from finding a
// function in a context. This is necessary for mustache compatibility, which
// requires that context functions in blocks are evaluated by blockHelperMissing,
// and then proceed as if the resulting value was provided to blockHelperMissing.

Compiler.prototype = {
  compiler: Compiler,

  equals: function(other) {
    let len = this.opcodes.length;
    if (other.opcodes.length !== len) {
      return false;
    }

    for (let i = 0; i < len; i++) {
      let opcode = this.opcodes[i],
          otherOpcode = other.opcodes[i];
      if (opcode.opcode !== otherOpcode.opcode || !argEquals(opcode.args, otherOpcode.args)) {
        return false;
      }
    }

    // We know that length is the same between the two arrays because they are directly tied
    // to the opcode behavior above.
    len = this.children.length;
    for (let i = 0; i < len; i++) {
      if (!this.children[i].equals(other.children[i])) {
        return false;
      }
    }

    return true;
  },

  guid: 0,

  compile: function(program, options) {
    this.sourceNode = [];
    this.opcodes = [];
    this.children = [];
    this.options = options;
    this.stringParams = options.stringParams;
    this.trackIds = options.trackIds;

    options.blockParams = options.blockParams || [];

    // These changes will propagate to the other compiler components
    let knownHelpers = options.knownHelpers;
    options.knownHelpers = {
      'helperMissing': true,
      'blockHelperMissing': true,
      'each': true,
      'if': true,
      'unless': true,
      'with': true,
      'log': true,
      'lookup': true
    };
    if (knownHelpers) {
      for (let name in knownHelpers) {
          this.options.knownHelpers[name] = knownHelpers[name];
      }
    }

    return this.accept(program);
  },

  compileProgram: function(program) {
    let childCompiler = new this.compiler(), // eslint-disable-line new-cap
        result = childCompiler.compile(program, this.options),
        guid = this.guid++;

    this.usePartial = this.usePartial || result.usePartial;

    this.children[guid] = result;
    this.useDepths = this.useDepths || result.useDepths;

    return guid;
  },

  accept: function(node) {
    /* istanbul ignore next: Sanity code */
    if (!this[node.type]) {
      throw new Exception('Unknown type: ' + node.type, node);
    }

    this.sourceNode.unshift(node);
    let ret = this[node.type](node);
    this.sourceNode.shift();
    return ret;
  },

  Program: function(program) {
    this.options.blockParams.unshift(program.blockParams);

    let body = program.body,
        bodyLength = body.length;
    for (let i = 0; i < bodyLength; i++) {
      this.accept(body[i]);
    }

    this.options.blockParams.shift();

    this.isSimple = bodyLength === 1;
    this.blockParams = program.blockParams ? program.blockParams.length : 0;

    return this;
  },

  BlockStatement: function(block) {
    transformLiteralToPath(block);

    let program = block.program,
        inverse = block.inverse;

    program = program && this.compileProgram(program);
    inverse = inverse && this.compileProgram(inverse);

    let type = this.classifySexpr(block);

    if (type === 'helper') {
      this.helperSexpr(block, program, inverse);
    } else if (type === 'simple') {
      this.simpleSexpr(block);

      // now that the simple mustache is resolved, we need to
      // evaluate it by executing `blockHelperMissing`
      this.opcode('pushProgram', program);
      this.opcode('pushProgram', inverse);
      this.opcode('emptyHash');
      this.opcode('blockValue', block.path.original);
    } else {
      this.ambiguousSexpr(block, program, inverse);

      // now that the simple mustache is resolved, we need to
      // evaluate it by executing `blockHelperMissing`
      this.opcode('pushProgram', program);
      this.opcode('pushProgram', inverse);
      this.opcode('emptyHash');
      this.opcode('ambiguousBlockValue');
    }

    this.opcode('append');
  },

  DecoratorBlock(decorator) {
    let program = decorator.program && this.compileProgram(decorator.program);
    let params = this.setupFullMustacheParams(decorator, program, undefined),
        path = decorator.path;

    this.useDecorators = true;
    this.opcode('registerDecorator', params.length, path.original);
  },

  PartialStatement: function(partial) {
    this.usePartial = true;

    let program = partial.program;
    if (program) {
      program = this.compileProgram(partial.program);
    }

    let params = partial.params;
    if (params.length > 1) {
      throw new Exception('Unsupported number of partial arguments: ' + params.length, partial);
    } else if (!params.length) {
      if (this.options.explicitPartialContext) {
        this.opcode('pushLiteral', 'undefined');
      } else {
        params.push({type: 'PathExpression', parts: [], depth: 0});
      }
    }

    let partialName = partial.name.original,
        isDynamic = partial.name.type === 'SubExpression';
    if (isDynamic) {
      this.accept(partial.name);
    }

    this.setupFullMustacheParams(partial, program, undefined, true);

    let indent = partial.indent || '';
    if (this.options.preventIndent && indent) {
      this.opcode('appendContent', indent);
      indent = '';
    }

    this.opcode('invokePartial', isDynamic, partialName, indent);
    this.opcode('append');
  },
  PartialBlockStatement: function(partialBlock) {
    this.PartialStatement(partialBlock);
  },

  MustacheStatement: function(mustache) {
    this.SubExpression(mustache);

    if (mustache.escaped && !this.options.noEscape) {
      this.opcode('appendEscaped');
    } else {
      this.opcode('append');
    }
  },
  Decorator(decorator) {
    this.DecoratorBlock(decorator);
  },

  ContentStatement: function(content) {
    if (content.value) {
      this.opcode('appendContent', content.value);
    }
  },

  CommentStatement: function() {},

  SubExpression: function(sexpr) {
    transformLiteralToPath(sexpr);
    let type = this.classifySexpr(sexpr);

    if (type === 'simple') {
      this.simpleSexpr(sexpr);
    } else if (type === 'helper') {
      this.helperSexpr(sexpr);
    } else {
      this.ambiguousSexpr(sexpr);
    }
  },
  ambiguousSexpr: function(sexpr, program, inverse) {
    let path = sexpr.path,
        name = path.parts[0],
        isBlock = program != null || inverse != null;

    this.opcode('getContext', path.depth);

    this.opcode('pushProgram', program);
    this.opcode('pushProgram', inverse);

    path.strict = true;
    this.accept(path);

    this.opcode('invokeAmbiguous', name, isBlock);
  },

  simpleSexpr: function(sexpr) {
    let path = sexpr.path;
    path.strict = true;
    this.accept(path);
    this.opcode('resolvePossibleLambda');
  },

  helperSexpr: function(sexpr, program, inverse) {
    let params = this.setupFullMustacheParams(sexpr, program, inverse),
        path = sexpr.path,
        name = path.parts[0];

    if (this.options.knownHelpers[name]) {
      this.opcode('invokeKnownHelper', params.length, name);
    } else if (this.options.knownHelpersOnly) {
      throw new Exception('You specified knownHelpersOnly, but used the unknown helper ' + name, sexpr);
    } else {
      path.strict = true;
      path.falsy = true;

      this.accept(path);
      this.opcode('invokeHelper', params.length, path.original, AST.helpers.simpleId(path));
    }
  },

  PathExpression: function(path) {
    this.addDepth(path.depth);
    this.opcode('getContext', path.depth);

    let name = path.parts[0],
        scoped = AST.helpers.scopedId(path),
        blockParamId = !path.depth && !scoped && this.blockParamIndex(name);

    if (blockParamId) {
      this.opcode('lookupBlockParam', blockParamId, path.parts);
    } else if (!name) {
      // Context reference, i.e. `{{foo .}}` or `{{foo ..}}`
      this.opcode('pushContext');
    } else if (path.data) {
      this.options.data = true;
      this.opcode('lookupData', path.depth, path.parts, path.strict);
    } else {
      this.opcode('lookupOnContext', path.parts, path.falsy, path.strict, scoped);
    }
  },

  StringLiteral: function(string) {
    this.opcode('pushString', string.value);
  },

  NumberLiteral: function(number) {
    this.opcode('pushLiteral', number.value);
  },

  BooleanLiteral: function(bool) {
    this.opcode('pushLiteral', bool.value);
  },

  UndefinedLiteral: function() {
    this.opcode('pushLiteral', 'undefined');
  },

  NullLiteral: function() {
    this.opcode('pushLiteral', 'null');
  },

  Hash: function(hash) {
    let pairs = hash.pairs,
        i = 0,
        l = pairs.length;

    this.opcode('pushHash');

    for (; i < l; i++) {
      this.pushParam(pairs[i].value);
    }
    while (i--) {
      this.opcode('assignToHash', pairs[i].key);
    }
    this.opcode('popHash');
  },

  // HELPERS
  opcode: function(name) {
    this.opcodes.push({ opcode: name, args: slice.call(arguments, 1), loc: this.sourceNode[0].loc });
  },

  addDepth: function(depth) {
    if (!depth) {
      return;
    }

    this.useDepths = true;
  },

  classifySexpr: function(sexpr) {
    let isSimple = AST.helpers.simpleId(sexpr.path);

    let isBlockParam = isSimple && !!this.blockParamIndex(sexpr.path.parts[0]);

    // a mustache is an eligible helper if:
    // * its id is simple (a single part, not `this` or `..`)
    let isHelper = !isBlockParam && AST.helpers.helperExpression(sexpr);

    // if a mustache is an eligible helper but not a definite
    // helper, it is ambiguous, and will be resolved in a later
    // pass or at runtime.
    let isEligible = !isBlockParam && (isHelper || isSimple);

    // if ambiguous, we can possibly resolve the ambiguity now
    // An eligible helper is one that does not have a complex path, i.e. `this.foo`, `../foo` etc.
    if (isEligible && !isHelper) {
      let name = sexpr.path.parts[0],
          options = this.options;

      if (options.knownHelpers[name]) {
        isHelper = true;
      } else if (options.knownHelpersOnly) {
        isEligible = false;
      }
    }

    if (isHelper) {
      return 'helper';
    } else if (isEligible) {
      return 'ambiguous';
    } else {
      return 'simple';
    }
  },

  pushParams: function(params) {
    for (let i = 0, l = params.length; i < l; i++) {
      this.pushParam(params[i]);
    }
  },

  pushParam: function(val) {
    let value = val.value != null ? val.value : val.original || '';

    if (this.stringParams) {
      if (value.replace) {
        value = value
            .replace(/^(\.?\.\/)*/g, '')
            .replace(/\//g, '.');
      }

      if (val.depth) {
        this.addDepth(val.depth);
      }
      this.opcode('getContext', val.depth || 0);
      this.opcode('pushStringParam', value, val.type);

      if (val.type === 'SubExpression') {
        // SubExpressions get evaluated and passed in
        // in string params mode.
        this.accept(val);
      }
    } else {
      if (this.trackIds) {
        let blockParamIndex;
        if (val.parts && !AST.helpers.scopedId(val) && !val.depth) {
           blockParamIndex = this.blockParamIndex(val.parts[0]);
        }
        if (blockParamIndex) {
          let blockParamChild = val.parts.slice(1).join('.');
          this.opcode('pushId', 'BlockParam', blockParamIndex, blockParamChild);
        } else {
          value = val.original || value;
          if (value.replace) {
            value = value
                .replace(/^this(?:\.|$)/, '')
                .replace(/^\.\//, '')
                .replace(/^\.$/, '');
          }

          this.opcode('pushId', val.type, value);
        }
      }
      this.accept(val);
    }
  },

  setupFullMustacheParams: function(sexpr, program, inverse, omitEmpty) {
    let params = sexpr.params;
    this.pushParams(params);

    this.opcode('pushProgram', program);
    this.opcode('pushProgram', inverse);

    if (sexpr.hash) {
      this.accept(sexpr.hash);
    } else {
      this.opcode('emptyHash', omitEmpty);
    }

    return params;
  },

  blockParamIndex: function(name) {
    for (let depth = 0, len = this.options.blockParams.length; depth < len; depth++) {
      let blockParams = this.options.blockParams[depth],
          param = blockParams && indexOf(blockParams, name);
      if (blockParams && param >= 0) {
        return [depth, param];
      }
    }
  }
};

export function precompile(input, options, env) {
  if (input == null || (typeof input !== 'string' && input.type !== 'Program')) {
    throw new Exception('You must pass a string or Handlebars AST to Handlebars.precompile. You passed ' + input);
  }

  options = options || {};
  if (!('data' in options)) {
    options.data = true;
  }
  if (options.compat) {
    options.useDepths = true;
  }

  let ast = env.parse(input, options),
      environment = new env.Compiler().compile(ast, options);
  return new env.JavaScriptCompiler().compile(environment, options);
}

export function compile(input, options = {}, env) {
  if (input == null || (typeof input !== 'string' && input.type !== 'Program')) {
    throw new Exception('You must pass a string or Handlebars AST to Handlebars.compile. You passed ' + input);
  }

  options = extend({}, options);
  if (!('data' in options)) {
    options.data = true;
  }
  if (options.compat) {
    options.useDepths = true;
  }

  let compiled;

  function compileInput() {
    let ast = env.parse(input, options),
        environment = new env.Compiler().compile(ast, options),
        templateSpec = new env.JavaScriptCompiler().compile(environment, options, undefined, true);
    return env.template(templateSpec);
  }

  // Template is only compiled on first use and cached after that point.
  function ret(context, execOptions) {
    if (!compiled) {
      compiled = compileInput();
    }
    return compiled.call(this, context, execOptions);
  }
  ret._setup = function(setupOptions) {
    if (!compiled) {
      compiled = compileInput();
    }
    return compiled._setup(setupOptions);
  };
  ret._child = function(i, data, blockParams, depths) {
    if (!compiled) {
      compiled = compileInput();
    }
    return compiled._child(i, data, blockParams, depths);
  };
  return ret;
}

function argEquals(a, b) {
  if (a === b) {
    return true;
  }

  if (isArray(a) && isArray(b) && a.length === b.length) {
    for (let i = 0; i < a.length; i++) {
      if (!argEquals(a[i], b[i])) {
        return false;
      }
    }
    return true;
  }
}

function transformLiteralToPath(sexpr) {
  if (!sexpr.path.parts) {
    let literal = sexpr.path;
    // Casting to string here to make false and 0 literal values play nicely with the rest
    // of the system.
    sexpr.path = {
      type: 'PathExpression',
      data: false,
      depth: 0,
      parts: [literal.original + ''],
      original: literal.original + '',
      loc: literal.loc
    };
  }
}
<|endoftext|>


<commit_before>(function(angular){
    'use strict';

    var module = angular.module('messages.controllers', []);

    // Service to share data across the controllers
    module.factory('messages_list', function() {
        return {
            messages : []
        };
    });

    module.controller('NewMessageController', ['$scope', '$modal', '$window', 'Message', 'Student', 'StudentSearch', 'Class', 'messages_list', '$rootScope',
            function($scope, $modal, $window, Message, Student, StudentSearch, Class, messages_list, $rootScope) {
                $scope.course_id = parseInt($window.course_id, 10);
                $scope.messages = messages_list.messages;
                $scope.new_message = function () {
                    var modalInstance = $modal.open({
                        templateUrl: 'newMessageModal.html',
                        controller: ['$scope', '$modalInstance', 'course_id', SendMessageModalInstanceCtrl],
                        resolve: {
                            course_id: function () {
                                return $scope.course_id;
                            }
                        }
                    });
                    modalInstance.result.then(function (new_message) {
                        new_message.$save({}, function(new_message){
                            messages_list.messages.unshift(new_message);
                            $rootScope.$broadcast('newMessage');
                        });

                    });
                };
                var SendMessageModalInstanceCtrl = function ($scope, $modalInstance, course_id) {

                    $scope.new_message = new Message();
                    $scope.new_message.course = course_id;
                    $scope.new_message.users = [];
                    $scope.recipient_list = [];
                    $scope.empty_msg_subject_error = false;
                    $scope.empty_msg_body_error = false;

                    $scope.classes = Class.query({course: course_id}, function(classes){
                        classes.checked = [];
                        return classes;
                    });

                    // trick to user modal.all_checked in ng-model html tag
                    $scope.modal = {};
                    $scope.modal.all_checked = true;

                    $scope.send = function () {
                        // TODO validação dos campo: títle e message não podem ser vazios
                        if ($scope.modal.all_checked) {
                            $scope.new_message.users = [];
                            angular.forEach($scope.classes, function(klass) {
                                $scope.new_message.users = $scope.new_message.users.concat(klass.students);
                            });
                        } else if ($scope.classes.checked) {
                            angular.forEach($scope.classes.checked, function(klass) {
                                $scope.new_message.users = $scope.new_message.users.concat(klass);
                            });
                        }
                        if ($scope.new_message.message && $scope.new_message.subject) {
                            $modalInstance.close($scope.new_message);
                            $scope.empty_msg_subject_error = false;
                            $scope.empty_msg_body_error = false;
                        }
                        if (!$scope.new_message.message) {
                            $scope.empty_msg_body_error = true;
                        } else {
                            $scope.empty_msg_body_error = false;
                        }
                        if (!$scope.new_message.subject) {
                            $scope.empty_msg_subject_error = true;
                        } else {
                            $scope.empty_msg_subject_error = false;
                        }
                    };

                    $scope.cancel = function () {
                        $modalInstance.dismiss();
                    };
                    $scope.getUsers = function(val) {
                        return new StudentSearch(val, course_id);
                    };

                    $scope.on_select_student = function(model) {
                        $scope.new_message.users.unshift(model.id);
                        $scope.recipient_list.unshift(model);
                        $scope.asyncSelected = '';
                    };

                    $scope.remove_student = function(index) {
                        $scope.new_message.users.splice(index, 1);
                        $scope.recipient_list.splice(index, 1);
                };

                };
            }
        ]);

    module.controller('MessagesListController', ['$scope', '$modal', '$window', 'Message', 'messages_list',
        function($scope, $modal, $window, Message, messages_list) {
            $scope.course_id = parseInt($window.course_id, 10);
            $scope.course_slug = $window.course_slug;
            messages_list.messages = Message.query({course: $scope.course_id});
            $scope.messages = messages_list.messages;
            $scope.$on('newMessage', function() {
                $scope.messages = messages_list.messages;
            });
        }
    ]);

    module.controller('MessageController', ['$scope', '$window', 'Message',
        function($scope, $window, Message) {
            $scope.course_id = parseInt($window.course_id, 10);
            $scope.message_id = document.location.href.match(/message\/([0-9]+)/)[1];
            $scope.message = Message.get({messageId: $scope.message_id}, function(message) {
            });
        }
    ]);
})(angular);
<commit_msg>fix identation<commit_after>(function(angular){
    'use strict';

    var module = angular.module('messages.controllers', []);

    // Service to share data across the controllers
    module.factory('messages_list', function() {
        return {
            messages : []
        };
    });

    module.controller('NewMessageController', ['$scope', '$modal', '$window', 'Message', 'Student', 'StudentSearch', 'Class', 'messages_list', '$rootScope',
            function($scope, $modal, $window, Message, Student, StudentSearch, Class, messages_list, $rootScope) {
                $scope.course_id = parseInt($window.course_id, 10);
                $scope.messages = messages_list.messages;
                $scope.new_message = function () {
                    var modalInstance = $modal.open({
                        templateUrl: 'newMessageModal.html',
                        controller: ['$scope', '$modalInstance', 'course_id', SendMessageModalInstanceCtrl],
                        resolve: {
                            course_id: function () {
                                return $scope.course_id;
                            }
                        }
                    });
                    modalInstance.result.then(function (new_message) {
                        new_message.$save({}, function(new_message){
                            messages_list.messages.unshift(new_message);
                            $rootScope.$broadcast('newMessage');
                        });

                    });
                };
                var SendMessageModalInstanceCtrl = function ($scope, $modalInstance, course_id) {

                    $scope.new_message = new Message();
                    $scope.new_message.course = course_id;
                    $scope.new_message.users = [];
                    $scope.recipient_list = [];
                    $scope.empty_msg_subject_error = false;
                    $scope.empty_msg_body_error = false;

                    $scope.classes = Class.query({course: course_id}, function(classes){
                        classes.checked = [];
                        return classes;
                    });

                    // trick to user modal.all_checked in ng-model html tag
                    $scope.modal = {};
                    $scope.modal.all_checked = true;

                    $scope.send = function () {
                        // TODO validação dos campo: títle e message não podem ser vazios
                        if ($scope.modal.all_checked) {
                            $scope.new_message.users = [];
                            angular.forEach($scope.classes, function(klass) {
                                $scope.new_message.users = $scope.new_message.users.concat(klass.students);
                            });
                        } else if ($scope.classes.checked) {
                            angular.forEach($scope.classes.checked, function(klass) {
                                $scope.new_message.users = $scope.new_message.users.concat(klass);
                            });
                        }
                        if ($scope.new_message.message && $scope.new_message.subject) {
                            $modalInstance.close($scope.new_message);
                            $scope.empty_msg_subject_error = false;
                            $scope.empty_msg_body_error = false;
                        }
                        if (!$scope.new_message.message) {
                            $scope.empty_msg_body_error = true;
                        } else {
                            $scope.empty_msg_body_error = false;
                        }
                        if (!$scope.new_message.subject) {
                            $scope.empty_msg_subject_error = true;
                        } else {
                            $scope.empty_msg_subject_error = false;
                        }
                    };

                    $scope.cancel = function () {
                        $modalInstance.dismiss();
                    };
                    $scope.getUsers = function(val) {
                        return new StudentSearch(val, course_id);
                    };

                    $scope.on_select_student = function(model) {
                        $scope.new_message.users.unshift(model.id);
                        $scope.recipient_list.unshift(model);
                        $scope.asyncSelected = '';
                    };

                    $scope.remove_student = function(index) {
                        $scope.new_message.users.splice(index, 1);
                        $scope.recipient_list.splice(index, 1);
                    };

                };
            }
        ]);

    module.controller('MessagesListController', ['$scope', '$modal', '$window', 'Message', 'messages_list',
        function($scope, $modal, $window, Message, messages_list) {
            $scope.course_id = parseInt($window.course_id, 10);
            $scope.course_slug = $window.course_slug;
            messages_list.messages = Message.query({course: $scope.course_id});
            $scope.messages = messages_list.messages;
            $scope.$on('newMessage', function() {
                $scope.messages = messages_list.messages;
            });
        }
    ]);

    module.controller('MessageController', ['$scope', '$window', 'Message',
        function($scope, $window, Message) {
            $scope.course_id = parseInt($window.course_id, 10);
            $scope.message_id = document.location.href.match(/message\/([0-9]+)/)[1];
            $scope.message = Message.get({messageId: $scope.message_id}, function(message) {
            });
        }
    ]);
})(angular);
<|endoftext|>


<commit_before>import PropTypes from "prop-types";
import React from "react";
import styled from "styled-components";

import { timeAgo } from "@agir/lib/utils/time";

import Card from "@agir/front/genericComponents/Card";
import FeatherIcon from "@agir/front/genericComponents/FeatherIcon";

const StyledCard = styled(Card)`
  padding-top: 1.5rem;
  padding-bottom: 1.5rem;

  & > * {
    margin-left: 0.5rem;
    margin-right: 0.5rem;
  }
  h4 {
    font-size: 1rem;
    font-weight: 600;
    margin-bottom: 1rem;
  }

  ul {
    display: inline-flex;
    flex-flow: column wrap;
    align-items: flex-start;
    justify-content: flex-start;
    list-style: none;
    padding: 0;
    font-size: 14px;
    font-weight: 400;
    max-height: 78px;

    @media (max-width: 352px) {
      flex-wrap: nowrap;
      max-height: none;
    }
  }

  li {
    display: inline-flex;
    width: 160px;
    align-items: baseline;
    min-height: 26px;

    span + span {
      padding-left: 0.5rem;
    }
  }
`;

const GroupFacts = (props) => {
  const { facts } = props;

  if (!facts || Object.values(facts).filter(Boolean).length === 0) {
    return null;
  }
  const {
    eventCount,
    memberCount,
    isCertified,
    creationDate,
    lastActivityDate,
  } = facts;

  return (

  );
};

GroupFacts.propTypes = {
  facts: PropTypes.shape({
    eventCount: PropTypes.number,
    memberCount: PropTypes.number,
    isCertified: PropTypes.bool,
    creationDate: PropTypes.string,
    lastActivityDate: PropTypes.string,
  }),
};
export default GroupFacts;
<commit_msg>fix: GroupFacts component height<commit_after>import PropTypes from "prop-types";
import React from "react";
import styled from "styled-components";

import { timeAgo } from "@agir/lib/utils/time";

import Card from "@agir/front/genericComponents/Card";
import FeatherIcon from "@agir/front/genericComponents/FeatherIcon";

const StyledCard = styled(Card)`
  padding-top: 1.5rem;
  padding-bottom: 1.5rem;

  & > * {
    margin-left: 0.5rem;
    margin-right: 0.5rem;
  }
  h4 {
    font-size: 1rem;
    font-weight: 600;
    margin-bottom: 1rem;
  }

  ul {
    display: inline-flex;
    flex-flow: column wrap;
    align-items: flex-start;
    justify-content: flex-start;
    list-style: none;
    padding: 0;
    font-size: 14px;
    font-weight: 400;
    max-height: 6rem;

    @media (max-width: 352px) {
      flex-wrap: nowrap;
      max-height: none;
    }
  }

  li {
    display: inline-flex;
    width: 160px;
    align-items: baseline;
    min-height: 26px;

    span + span {
      padding-left: 0.5rem;
    }
  }
`;

const GroupFacts = (props) => {
  const { facts } = props;

  if (!facts || Object.values(facts).filter(Boolean).length === 0) {
    return null;
  }
  const {
    eventCount,
    memberCount,
    isCertified,
    creationDate,
    lastActivityDate,
  } = facts;

  return (

  );
};

GroupFacts.propTypes = {
  facts: PropTypes.shape({
    eventCount: PropTypes.number,
    memberCount: PropTypes.number,
    isCertified: PropTypes.bool,
    creationDate: PropTypes.string,
    lastActivityDate: PropTypes.string,
  }),
};
export default GroupFacts;
<|endoftext|>


<commit_before>/*
 * L.TileLayer is used for standard xyz-numbered tile layers.
 */

L.TileLayer = L.GridLayer.extend({

	options: {
		minZoom: 0,
		maxZoom: 18,

		subdomains: 'abc',
		// errorTileUrl: '',
		zoomOffset: 0

		/*
		maxNativeZoom: <Number>,
		tms: <Boolean>,
		zoomReverse: <Number>,
		detectRetina: <Number>,
		crossOrigin: <Boolean>,
		*/
	},

	initialize: function (url, options) {

		this._url = url;

		options = L.setOptions(this, options);

		// detecting retina displays, adjusting tileSize and zoom levels
		if (options.detectRetina && L.Browser.retina && options.maxZoom > 0) {

			options.tileSize = Math.floor(options.tileSize / 2);
			options.zoomOffset++;

			options.minZoom = Math.max(0, options.minZoom);
			options.maxZoom--;
		}

		if (typeof options.subdomains === 'string') {
			options.subdomains = options.subdomains.split('');
		}
	},

	setUrl: function (url, noRedraw) {
		this._url = url;

		if (!noRedraw) {
			this.redraw();
		}
		return this;
	},

	createTile: function (coords, done) {
		var tile = document.createElement('img');

		tile.onload = L.bind(this._tileOnLoad, this, done, tile);
		tile.onerror = L.bind(this._tileOnError, this, done, tile);

		if (this.options.crossOrigin) {
			tile.crossOrigin = '';
		}

		/*
		 Alt tag is set to empty string to keep screen readers from reading URL and for compliance reasons
		 http://www.w3.org/TR/WCAG20-TECHS/H67
		*/
		tile.alt = '';

		tile.src = this.getTileUrl(coords);

		return tile;
	},

	getTileUrl: function (coords) {
		return L.Util.template(this._url, L.extend({
			r: this.options.detectRetina && L.Browser.retina && this.options.maxZoom > 0 ? '@2x' : '',
			s: this._getSubdomain(coords),
			x: coords.x,
			y: this.options.tms ? this._tileNumBounds.max.y - coords.y : coords.y,
			z: this._getZoomForUrl()
		}, this.options));
	},

	_tileOnLoad: function (done, tile) {
		done(null, tile);
	},

	_tileOnError: function (done, tile, e) {
		var errorUrl = this.options.errorTileUrl;
		if (errorUrl) {
			tile.src = errorUrl;
		}
		done(e, tile);
	},

	_getTileSize: function () {
		var map = this._map,
		    options = this.options,
		    zoom = map.getZoom() + options.zoomOffset,
		    zoomN = options.maxNativeZoom;

		// increase tile size when overscaling
		return zoomN && zoom > zoomN ?
				Math.round(map.getZoomScale(zoom) / map.getZoomScale(zoomN) * options.tileSize) :
				options.tileSize;
	},

	_removeTile: function (key) {
		var tile = this._tiles[key];

		L.GridLayer.prototype._removeTile.call(this, key);

		// for https://github.com/Leaflet/Leaflet/issues/137
		if (!L.Browser.android) {
			tile.onload = null;
			tile.src = L.Util.emptyImageUrl;
		}
	},

	_getZoomForUrl: function () {

		var options = this.options,
		    zoom = this._map.getZoom();

		if (options.zoomReverse) {
			zoom = options.maxZoom - zoom;
		}

		zoom += options.zoomOffset;

		return options.maxNativeZoom ? Math.min(zoom, options.maxNativeZoom) : zoom;
	},

	_getSubdomain: function (tilePoint) {
		var index = Math.abs(tilePoint.x + tilePoint.y) % this.options.subdomains.length;
		return this.options.subdomains[index];
	},

	// stops loading all tiles in the background layer
	_abortLoading: function () {
		var i, tile;
		for (i in this._tiles) {
			tile = this._tiles[i];

			if (!tile.complete) {
				tile.onload = L.Util.falseFn;
				tile.onerror = L.Util.falseFn;
				tile.src = L.Util.emptyImageUrl;

				L.DomUtil.remove(tile);
			}
		}
	}
});

L.tileLayer = function (url, options) {
	return new L.TileLayer(url, options);
};
<commit_msg>Set detectRetina's expected type as Boolean at code level to match documentation and usage<commit_after>/*
 * L.TileLayer is used for standard xyz-numbered tile layers.
 */

L.TileLayer = L.GridLayer.extend({

	options: {
		minZoom: 0,
		maxZoom: 18,

		subdomains: 'abc',
		// errorTileUrl: '',
		zoomOffset: 0

		/*
		maxNativeZoom: <Number>,
		tms: <Boolean>,
		zoomReverse: <Number>,
		detectRetina: <Boolean>,
		crossOrigin: <Boolean>,
		*/
	},

	initialize: function (url, options) {

		this._url = url;

		options = L.setOptions(this, options);

		// detecting retina displays, adjusting tileSize and zoom levels
		if (options.detectRetina && L.Browser.retina && options.maxZoom > 0) {

			options.tileSize = Math.floor(options.tileSize / 2);
			options.zoomOffset++;

			options.minZoom = Math.max(0, options.minZoom);
			options.maxZoom--;
		}

		if (typeof options.subdomains === 'string') {
			options.subdomains = options.subdomains.split('');
		}
	},

	setUrl: function (url, noRedraw) {
		this._url = url;

		if (!noRedraw) {
			this.redraw();
		}
		return this;
	},

	createTile: function (coords, done) {
		var tile = document.createElement('img');

		tile.onload = L.bind(this._tileOnLoad, this, done, tile);
		tile.onerror = L.bind(this._tileOnError, this, done, tile);

		if (this.options.crossOrigin) {
			tile.crossOrigin = '';
		}

		/*
		 Alt tag is set to empty string to keep screen readers from reading URL and for compliance reasons
		 http://www.w3.org/TR/WCAG20-TECHS/H67
		*/
		tile.alt = '';

		tile.src = this.getTileUrl(coords);

		return tile;
	},

	getTileUrl: function (coords) {
		return L.Util.template(this._url, L.extend({
			r: this.options.detectRetina && L.Browser.retina && this.options.maxZoom > 0 ? '@2x' : '',
			s: this._getSubdomain(coords),
			x: coords.x,
			y: this.options.tms ? this._tileNumBounds.max.y - coords.y : coords.y,
			z: this._getZoomForUrl()
		}, this.options));
	},

	_tileOnLoad: function (done, tile) {
		done(null, tile);
	},

	_tileOnError: function (done, tile, e) {
		var errorUrl = this.options.errorTileUrl;
		if (errorUrl) {
			tile.src = errorUrl;
		}
		done(e, tile);
	},

	_getTileSize: function () {
		var map = this._map,
		    options = this.options,
		    zoom = map.getZoom() + options.zoomOffset,
		    zoomN = options.maxNativeZoom;

		// increase tile size when overscaling
		return zoomN && zoom > zoomN ?
				Math.round(map.getZoomScale(zoom) / map.getZoomScale(zoomN) * options.tileSize) :
				options.tileSize;
	},

	_removeTile: function (key) {
		var tile = this._tiles[key];

		L.GridLayer.prototype._removeTile.call(this, key);

		// for https://github.com/Leaflet/Leaflet/issues/137
		if (!L.Browser.android) {
			tile.onload = null;
			tile.src = L.Util.emptyImageUrl;
		}
	},

	_getZoomForUrl: function () {

		var options = this.options,
		    zoom = this._map.getZoom();

		if (options.zoomReverse) {
			zoom = options.maxZoom - zoom;
		}

		zoom += options.zoomOffset;

		return options.maxNativeZoom ? Math.min(zoom, options.maxNativeZoom) : zoom;
	},

	_getSubdomain: function (tilePoint) {
		var index = Math.abs(tilePoint.x + tilePoint.y) % this.options.subdomains.length;
		return this.options.subdomains[index];
	},

	// stops loading all tiles in the background layer
	_abortLoading: function () {
		var i, tile;
		for (i in this._tiles) {
			tile = this._tiles[i];

			if (!tile.complete) {
				tile.onload = L.Util.falseFn;
				tile.onerror = L.Util.falseFn;
				tile.src = L.Util.emptyImageUrl;

				L.DomUtil.remove(tile);
			}
		}
	}
});

L.tileLayer = function (url, options) {
	return new L.TileLayer(url, options);
};
<|endoftext|>


<commit_before>import React from 'react'
import { translate } from 'react-i18next'
import PropTypes from 'prop-types'

import Filter from 'components/Filter'

import styles from './FiltersSummary.scss'

const FiltersSummary = ({ filters, removeFilter, t }) => (

      {filters.length
        ? t('FiltersSummary.activeFilters', { count: filters.length })
        : t('FiltersSummary.noFilters')}

    {filters.map((filter, idx) => (
      <Filter
        key={idx}
        detail
        remove
        filter={filter}
        onClick={filter => removeFilter(filter)}
      />
    ))}

)

FiltersSummary.propTypes = {
  filters: PropTypes.array.isRequired,
  removeFilter: PropTypes.func.isRequired,
  t: PropTypes.func.isRequired
}

export default translate('Search')(FiltersSummary)
<commit_msg>Fix broken Filter import in FilterSummary<commit_after>import React from 'react'
import { translate } from 'react-i18next'
import PropTypes from 'prop-types'

import Filter from 'common/components/Filter'

import styles from './FiltersSummary.scss'

const FiltersSummary = ({ filters, removeFilter, t }) => (

      {filters.length
        ? t('FiltersSummary.activeFilters', { count: filters.length })
        : t('FiltersSummary.noFilters')}

    {filters.map((filter, idx) => (
      <Filter
        key={idx}
        detail
        remove
        filter={filter}
        onClick={filter => removeFilter(filter)}
      />
    ))}

)

FiltersSummary.propTypes = {
  filters: PropTypes.array.isRequired,
  removeFilter: PropTypes.func.isRequired,
  t: PropTypes.func.isRequired
}

export default translate('Search')(FiltersSummary)
<|endoftext|>


<commit_before>var contexts = require("../contexts"),
    Visitor = require("./visitor"),
    ImportSequencer = require("./import-sequencer");

var ImportVisitor = function(importer, finish) {

    this._visitor = new Visitor(this);
    this._importer = importer;
    this._finish = finish;
    this.context = new contexts.Eval();
    this.importCount = 0;
    this.onceFileDetectionMap = {};
    this.recursionDetector = {};
    this._sequencer = new ImportSequencer();
};

ImportVisitor.prototype = {
    isReplacing: false,
    run: function (root) {
        var error;
        try {
            // process the contents
            this._visitor.visit(root);
        }
        catch(e) {
            error = e;
        }

        this.isFinished = true;
        if (this.importCount === 0) {
            this._finish(error || this.error);
        }
    },
    visitImport: function (importNode, visitArgs) {
        var inlineCSS = importNode.options.inline;

        if (!importNode.css || inlineCSS) {

            // TODO - process this type of imports *last*
            //if (importNode.isVariableImport()) {
            //    console.log("variable import detected");
            //}
            var context = new contexts.Eval(this.context, this.context.frames.slice(0));

            var importParent = context.frames[0];
            var newImportNode = this.processImportNode(importNode, context);
            for(var i = 0; i < importParent.rules.length; i++) {
                if (importParent.rules[i] === importNode) {
                    importParent.rules[i] = newImportNode;
                    break;
                }
            }
        }
        visitArgs.visitDeeper = false;
        return importNode;
    },
    processImportNode: function(importNode, context) {
        var evaldImportNode,
            inlineCSS = importNode.options.inline;

        try {
            evaldImportNode = importNode.evalForImport(context);
        } catch(e){
            if (!e.filename) { e.index = importNode.index; e.filename = importNode.currentFileInfo.filename; }
            // attempt to eval properly and treat as css
            importNode.css = true;
            // if that fails, this error will be thrown
            importNode.error = e;
        }

        if (evaldImportNode && (!evaldImportNode.css || inlineCSS)) {
            importNode = evaldImportNode;
            this.importCount++;

            if (importNode.options.multiple) {
                context.importMultiple = true;
            }

            // try appending if we haven't determined if it is css or not
            var tryAppendLessExtension = importNode.css === undefined;

            var onImported = this.onImported.bind(this, importNode, context),
                sequencedOnImported = this._sequencer.addImport(onImported);

            this._importer.push(importNode.getPath(), tryAppendLessExtension, importNode.currentFileInfo, importNode.options, sequencedOnImported);
        }
        return importNode;
    },
    onImported: function (importNode, context, e, root, importedAtRoot, fullPath) {
        if (e && !e.filename) {
            e.index = importNode.index; e.filename = importNode.currentFileInfo.filename;
        }

        var importVisitor = this,
            inlineCSS = importNode.options.inline,
            duplicateImport = importedAtRoot || fullPath in importVisitor.recursionDetector;

        if (!context.importMultiple) {
            if (duplicateImport) {
                importNode.skip = true;
            } else {
                importNode.skip = function() {
                    if (fullPath in importVisitor.onceFileDetectionMap) {
                        return true;
                    }
                    importVisitor.onceFileDetectionMap[fullPath] = true;
                    return false;
                };
            }
        }

        var subFinish = function(e) {
            importVisitor.importCount--;

            if (importVisitor.importCount === 0 && importVisitor.isFinished) {
                importVisitor._finish(e || importVisitor.error);
            } else if (e) {
                importVisitor.error = e;
            }
        };

        if (root) {
            importNode.root = root;
            importNode.importedFilename = fullPath;

            if (!inlineCSS && (context.importMultiple || !duplicateImport)) {
                importVisitor.recursionDetector[fullPath] = true;

                var oldContext = this.context;
                this.context = context;
                try {
                    this._visitor.visit(root);
                } catch (e) {
                    this.error = e;
                }
                this.context = oldContext;
            }
        }

        subFinish();
    },
    visitRule: function (ruleNode, visitArgs) {
        visitArgs.visitDeeper = false;
        return ruleNode;
    },
    visitDirective: function (directiveNode, visitArgs) {
        this.context.frames.unshift(directiveNode);
        return directiveNode;
    },
    visitDirectiveOut: function (directiveNode) {
        this.context.frames.shift();
    },
    visitMixinDefinition: function (mixinDefinitionNode, visitArgs) {
        this.context.frames.unshift(mixinDefinitionNode);
        return mixinDefinitionNode;
    },
    visitMixinDefinitionOut: function (mixinDefinitionNode) {
        this.context.frames.shift();
    },
    visitRuleset: function (rulesetNode, visitArgs) {
        this.context.frames.unshift(rulesetNode);
        return rulesetNode;
    },
    visitRulesetOut: function (rulesetNode) {
        this.context.frames.shift();
    },
    visitMedia: function (mediaNode, visitArgs) {
        this.context.frames.unshift(mediaNode.rules[0]);
        return mediaNode;
    },
    visitMediaOut: function (mediaNode) {
        this.context.frames.shift();
    }
};
module.exports = ImportVisitor;
<commit_msg>Fix - for some reason the flattening done by the import visitor is required<commit_after>var contexts = require("../contexts"),
    Visitor = require("./visitor"),
    ImportSequencer = require("./import-sequencer");

var ImportVisitor = function(importer, finish) {

    this._visitor = new Visitor(this);
    this._importer = importer;
    this._finish = finish;
    this.context = new contexts.Eval();
    this.importCount = 0;
    this.onceFileDetectionMap = {};
    this.recursionDetector = {};
    this._sequencer = new ImportSequencer();
};

ImportVisitor.prototype = {
    isReplacing: true,
    run: function (root) {
        var error;
        try {
            // process the contents
            this._visitor.visit(root);
        }
        catch(e) {
            error = e;
        }

        this.isFinished = true;
        if (this.importCount === 0) {
            this._finish(error || this.error);
        }
    },
    visitImport: function (importNode, visitArgs) {
        var inlineCSS = importNode.options.inline;

        if (!importNode.css || inlineCSS) {

            var context = new contexts.Eval(this.context, this.context.frames.slice(0));
            var importParent = context.frames[0];

            // TODO - process this type of imports *last*
            //if (importNode.isVariableImport()) {
            //    console.log("variable import detected");
            //}
            importNode = this.processImportNode(importNode, context, importParent);
        }
        visitArgs.visitDeeper = false;
        return importNode;
    },
    processImportNode: function(importNode, context, importParent) {
        var evaldImportNode,
            inlineCSS = importNode.options.inline;

        try {
            evaldImportNode = importNode.evalForImport(context);
        } catch(e){
            if (!e.filename) { e.index = importNode.index; e.filename = importNode.currentFileInfo.filename; }
            // attempt to eval properly and treat as css
            importNode.css = true;
            // if that fails, this error will be thrown
            importNode.error = e;
        }

        if (evaldImportNode && (!evaldImportNode.css || inlineCSS)) {
            this.importCount++;

            if (evaldImportNode.options.multiple) {
                context.importMultiple = true;
            }

            // try appending if we haven't determined if it is css or not
            var tryAppendLessExtension = evaldImportNode.css === undefined;

            var onImported = this.onImported.bind(this, evaldImportNode, context),
                sequencedOnImported = this._sequencer.addImport(onImported);

            this._importer.push(evaldImportNode.getPath(), tryAppendLessExtension, evaldImportNode.currentFileInfo, evaldImportNode.options, sequencedOnImported);

            for(var i = 0; i < importParent.rules.length; i++) {
                if (importParent.rules[i] === importNode) {
                    importParent.rules[i] = evaldImportNode;
                    break;
                }
            }
            importNode = evaldImportNode;
        }
        return importNode;
    },
    onImported: function (importNode, context, e, root, importedAtRoot, fullPath) {
        if (e && !e.filename) {
            e.index = importNode.index; e.filename = importNode.currentFileInfo.filename;
        }

        var importVisitor = this,
            inlineCSS = importNode.options.inline,
            duplicateImport = importedAtRoot || fullPath in importVisitor.recursionDetector;

        if (!context.importMultiple) {
            if (duplicateImport) {
                importNode.skip = true;
            } else {
                importNode.skip = function() {
                    if (fullPath in importVisitor.onceFileDetectionMap) {
                        return true;
                    }
                    importVisitor.onceFileDetectionMap[fullPath] = true;
                    return false;
                };
            }
        }

        var subFinish = function(e) {
            importVisitor.importCount--;

            if (importVisitor.importCount === 0 && importVisitor.isFinished) {
                importVisitor._finish(e || importVisitor.error);
            } else if (e) {
                importVisitor.error = e;
            }
        };

        if (root) {
            importNode.root = root;
            importNode.importedFilename = fullPath;

            if (!inlineCSS && (context.importMultiple || !duplicateImport)) {
                importVisitor.recursionDetector[fullPath] = true;

                var oldContext = this.context;
                this.context = context;
                try {
                    this._visitor.visit(root);
                } catch (e) {
                    this.error = e;
                }
                this.context = oldContext;
            }
        }

        subFinish();
    },
    visitRule: function (ruleNode, visitArgs) {
        visitArgs.visitDeeper = false;
        return ruleNode;
    },
    visitDirective: function (directiveNode, visitArgs) {
        this.context.frames.unshift(directiveNode);
        return directiveNode;
    },
    visitDirectiveOut: function (directiveNode) {
        this.context.frames.shift();
    },
    visitMixinDefinition: function (mixinDefinitionNode, visitArgs) {
        this.context.frames.unshift(mixinDefinitionNode);
        return mixinDefinitionNode;
    },
    visitMixinDefinitionOut: function (mixinDefinitionNode) {
        this.context.frames.shift();
    },
    visitRuleset: function (rulesetNode, visitArgs) {
        this.context.frames.unshift(rulesetNode);
        return rulesetNode;
    },
    visitRulesetOut: function (rulesetNode) {
        this.context.frames.shift();
    },
    visitMedia: function (mediaNode, visitArgs) {
        this.context.frames.unshift(mediaNode.rules[0]);
        return mediaNode;
    },
    visitMediaOut: function (mediaNode) {
        this.context.frames.shift();
    }
};
module.exports = ImportVisitor;
<|endoftext|>


<commit_before>import React, { Component } from 'react';
import PropTypes from 'prop-types';

import block from '../../../helpers/bem-cn';

import SelectPlugin from '../../selects/SelectPlugin/SelectPlugin';
import Row from '../../Layout/Row/Row';
import Button from '../../buttons/Button';

import CorsPlugin from './Cors/CorsPlugin';
import RateLimitPlugin from './RateLimit/RateLimitPlugin';
import AuthPlugin from './oAuth/AuthPlugin';
import CompressionPlugin from './Compression/CompressionPlugin';
import RequestTransformerPlugin from './RequestTransformer/RequestTransformerPlugin';

const propTypes = {
    className: PropTypes.string,
    plugins: PropTypes.arrayOf(PropTypes.object.isRequired),
    handlePluginExclude: PropTypes.func.isRequired,
    handlePluginInclude: PropTypes.func.isRequired,
    selectedPlugins: PropTypes.arrayOf(PropTypes.string).isRequired,
};

class RenderPlugin extends Component {
    state = {
        visiblePlugins: false,
    }

    showPlugins = () => {
        this.setState({ visiblePlugins: true });
    }

    getPluginIndex = (plugins, pluginName) => {
        const pluginIndex = plugins.findIndex(plugin => {
            return plugin.name === pluginName;
        });

        return pluginIndex;
    }

    render() {
        const { className, plugins, selectedPlugins, handlePluginExclude, handlePluginInclude, initialValues } = this.props;
        const b = block(className);
        const names = plugins.map(plugin => ({
            label: plugin.name,
            value: plugin.name,
        }));

        return (

                {
                    selectedPlugins.map(pluginName => {
                        const opts = {
                            className: b(),
                            key: pluginName,
                            name: `plugins[${this.getPluginIndex(plugins, pluginName)}]`,
                            handlePluginExclude,
                            plugin: initialValues.plugins[this.getPluginIndex(plugins, pluginName)],
                            pluginFromValues: plugins[this.getPluginIndex(plugins, pluginName)],
                            pluginName,
                        };

                        switch (pluginName) {
                            case 'cors':
                                return (
                                    <CorsPlugin
                                        {...opts}
                                    />
                                );
                            case 'rate_limit':
                                return (
                                    <RateLimitPlugin
                                        {...opts}
                                    />
                                );
                            case 'oauth2':
                                return (
                                    <AuthPlugin
                                        {...opts}
                                    />
                                );
                            case 'compression':
                                return (
                                    <CompressionPlugin
                                        {...opts}
                                    />
                                );
                            case 'request_transformer':
                                return (
                                    <RequestTransformerPlugin
                                        {...opts}
                                    />
                                );
                            default:
                                return null;
                        }
                    })
                }

                {
                    this.state.visiblePlugins &&
                        <Row className={b('row')()}>
                            <SelectPlugin
                                name="form-field-name"
                                options={names}
                                onChange={handlePluginInclude}
                            />
                        </Row>
                }

                <Row className={b('row')()}>
                    <Button
                        type="button"
                        mod="primary"
                        onClick={this.showPlugins}
                    >
                        + Add Plugin
                    </Button>
                </Row>

        );
    };
};

RenderPlugin.propTypes = propTypes;

export default RenderPlugin;
<commit_msg>add missing property to proptypes<commit_after>import React, { Component } from 'react';
import PropTypes from 'prop-types';

import block from '../../../helpers/bem-cn';

import SelectPlugin from '../../selects/SelectPlugin/SelectPlugin';
import Row from '../../Layout/Row/Row';
import Button from '../../buttons/Button';

import CorsPlugin from './Cors/CorsPlugin';
import RateLimitPlugin from './RateLimit/RateLimitPlugin';
import AuthPlugin from './oAuth/AuthPlugin';
import CompressionPlugin from './Compression/CompressionPlugin';
import RequestTransformerPlugin from './RequestTransformer/RequestTransformerPlugin';

const propTypes = {
    className: PropTypes.string,
    initialValues: PropTypes.object,
    plugins: PropTypes.arrayOf(PropTypes.object.isRequired),
    handlePluginExclude: PropTypes.func.isRequired,
    handlePluginInclude: PropTypes.func.isRequired,
    selectedPlugins: PropTypes.arrayOf(PropTypes.string).isRequired,
};

class RenderPlugin extends Component {
    state = {
        visiblePlugins: false,
    }

    showPlugins = () => {
        this.setState({ visiblePlugins: true });
    }

    getPluginIndex = (plugins, pluginName) => {
        const pluginIndex = plugins.findIndex(plugin => {
            return plugin.name === pluginName;
        });

        return pluginIndex;
    }

    render() {
        const { className, plugins, selectedPlugins, handlePluginExclude, handlePluginInclude, initialValues } = this.props;
        const b = block(className);
        const names = plugins.map(plugin => ({
            label: plugin.name,
            value: plugin.name,
        }));

        return (

                {
                    selectedPlugins.map(pluginName => {
                        const opts = {
                            className: b(),
                            key: pluginName,
                            name: `plugins[${this.getPluginIndex(plugins, pluginName)}]`,
                            handlePluginExclude,
                            plugin: initialValues.plugins[this.getPluginIndex(plugins, pluginName)],
                            pluginFromValues: plugins[this.getPluginIndex(plugins, pluginName)],
                            pluginName,
                        };

                        switch (pluginName) {
                            case 'cors':
                                return (
                                    <CorsPlugin
                                        {...opts}
                                    />
                                );
                            case 'rate_limit':
                                return (
                                    <RateLimitPlugin
                                        {...opts}
                                    />
                                );
                            case 'oauth2':
                                return (
                                    <AuthPlugin
                                        {...opts}
                                    />
                                );
                            case 'compression':
                                return (
                                    <CompressionPlugin
                                        {...opts}
                                    />
                                );
                            case 'request_transformer':
                                return (
                                    <RequestTransformerPlugin
                                        {...opts}
                                    />
                                );
                            default:
                                return null;
                        }
                    })
                }

                {
                    this.state.visiblePlugins &&
                        <Row className={b('row')()}>
                            <SelectPlugin
                                name="form-field-name"
                                options={names}
                                onChange={handlePluginInclude}
                            />
                        </Row>
                }

                <Row className={b('row')()}>
                    <Button
                        type="button"
                        mod="primary"
                        onClick={this.showPlugins}
                    >
                        + Add Plugin
                    </Button>
                </Row>

        );
    };
};

RenderPlugin.propTypes = propTypes;

export default RenderPlugin;
<|endoftext|>


<commit_before>/*
 * grunt-csscomb
 * https://github.com/csscomb/grunt-csscomb
 *
 * Copyright (c) 2013 Koji Ishimoto, contributors
 * Licensed under the MIT license.
 */
'use strict';

var path = require('path');

module.exports = function (grunt) {

    grunt.registerMultiTask('csscomb', 'Sorting CSS properties in specific order.', function () {

        var Comb = require('csscomb'),
            comb = new Comb();

        function getConfigPath(configPath) {
            var HOME = process.env.HOME || process.env.HOMEPATH || process.env.USERPROFILE;

            configPath = configPath || process.cwd() + '/.csscomb.json';

            // If we've finally found a config, return its path:
            if (grunt.file.exists(configPath)) {
                return configPath;
            }
            // If we are in HOME dir already and yet no config file, quit:
            if (path.dirname(configPath) === HOME) {
                return;
            }

            // If there is no config in this directory, go one level up and look for
            // a config there:
            configPath = path.dirname(path.dirname(configPath)) + '/.csscomb.json';
            return getConfigPath(configPath);
        }

        // Get config file from task's options:
        var config = grunt.task.current.options().config || getConfigPath();

        // Check if config file is set and exists. If not, use default one:
        if (config && grunt.file.exists(config)) {
            grunt.log.ok('Using custom config file "' + config + '"...');
            config = grunt.file.readJSON(config);
        } else {
            grunt.log.ok('Using default config file...');
            config = comb.getConfig('csscomb');
        }

        // Configure csscomb:
        comb.configure(config);

        this.files.forEach(function (f) {

            f.src.filter(function (filepath) {
                // Warn on and remove invalid source files (if nonull was set).
                if (!grunt.file.exists(filepath)) {
                    grunt.log.warn('Source file "' + filepath + '" not found.');
                    return false;
                } else {
                    return true;
                }
            }).forEach(function (src) {

                    // Get CSS from a source file:
                    var css = grunt.file.read(src);

                    // Comb it:
                    grunt.log.ok('Sorting file "' + src + '"...');
                    var syntax = src.split('.').pop();
                    var combed = comb.processString(css, syntax);
                    grunt.file.write(f.dest, combed);
                });
        });
    });
};<commit_msg>Stop searching config if we reach root directory<commit_after>/*
 * grunt-csscomb
 * https://github.com/csscomb/grunt-csscomb
 *
 * Copyright (c) 2013 Koji Ishimoto, contributors
 * Licensed under the MIT license.
 */
'use strict';

var path = require('path');

module.exports = function (grunt) {

    grunt.registerMultiTask('csscomb', 'Sorting CSS properties in specific order.', function () {

        var Comb = require('csscomb'),
            comb = new Comb(),
            HOME = process.env.HOME || process.env.HOMEPATH || process.env.USERPROFILE;

        function getConfigPath(configPath) {
            var dirname, parentDirname;

            configPath = configPath || process.cwd() + '/.csscomb.json';

            // If we've finally found a config, return its path:
            if (grunt.file.exists(configPath)) {
                return configPath;
            }

            dirname = path.dirname(configPath);
            parentDirname = path.dirname(dirname);

            // If we are in HOME dir already and yet no config file, quit.
            // If project is located not under HOME, compare to root instead.
            // Since there appears to be no good way to get root path in
            // Windows, assume that if current dir has no parent dir, we're in
            // root.
            if (dirname === HOME || dirname === parentDirname) {
                return;
            }

            // If there is no config in this directory, go one level up and look for
            // a config there:
            configPath = parentDirname + '/.csscomb.json';
            return getConfigPath(configPath);
        }

        // Get config file from task's options:
        var config = grunt.task.current.options().config || getConfigPath();

        // Check if config file is set and exists. If not, use default one:
        if (config && grunt.file.exists(config)) {
            grunt.log.ok('Using custom config file "' + config + '"...');
            config = grunt.file.readJSON(config);
        } else {
            grunt.log.ok('Using default config file...');
            config = comb.getConfig('csscomb');
        }

        // Configure csscomb:
        comb.configure(config);

        this.files.forEach(function (f) {

            f.src.filter(function (filepath) {
                // Warn on and remove invalid source files (if nonull was set).
                if (!grunt.file.exists(filepath)) {
                    grunt.log.warn('Source file "' + filepath + '" not found.');
                    return false;
                } else {
                    return true;
                }
            }).forEach(function (src) {

                    // Get CSS from a source file:
                    var css = grunt.file.read(src);

                    // Comb it:
                    grunt.log.ok('Sorting file "' + src + '"...');
                    var syntax = src.split('.').pop();
                    var combed = comb.processString(css, syntax);
                    grunt.file.write(f.dest, combed);
                });
        });
    });
};
<|endoftext|>


<commit_before>var slidedelay = 6000;
var fadedelay = 2000;

$(document).ready(function() {
    if ($('#imageContainer').children().length > 1) {
        $('#imageContainer').children(':first-child').addClass("showbanner");
        setTimeout(nextSlide, slidedelay);
    }
});

function nextSlide() {
    var images = $('#imageContainer').children();
    $(images).each( function(i) {
            if ($(this).hasClass("showbanner")) {
                $(this).fadeOut(fadedelay).removeClass("showbanner");
                var nextIndex = (i == (images.length - 1)) ? 0 : i+1;
                $(images[nextIndex]).fadeIn(fadedelay).addClass("showbanner");
                $('#caption').html($(images[nextIndex]).attr("title"));
                setTimeout(nextSlide, slidedelay);
                return false
            }
    });
}<commit_msg>smooth caption transitions a bit and allow for classing the continer div to prevent slideshow (if you want multiple bannerimages to display at the same time rather than slideshowing)<commit_after>var slidedelay = 6000;
var fadedelay = 2000;

$(document).ready(function() {
    if ($('#imageContainer').children().length > 1 && !$('#imageContainer').hasClass("no-slide") ) {
        $('#imageContainer').children(':first-child').addClass("showbanner");
        setTimeout(nextSlide, slidedelay);
    }
});

function nextSlide() {
    var images = $('#imageContainer').children();
    $(images).each( function(i) {
            if ($(this).hasClass("showbanner")) {
                $(this).fadeOut(fadedelay).removeClass("showbanner");
                var nextIndex = (i == (images.length - 1)) ? 0 : i+1;
                $('#caption').hide().html($(images[nextIndex]).attr("title"));
                $(images[nextIndex]).fadeIn(fadedelay).addClass("showbanner");
                $('#caption').fadeIn(1000);
                setTimeout(nextSlide, slidedelay);
                return false
            }
    });
}<|endoftext|>