<commit_before>var hostname, page, system, waitFor, webpage, _ref;

system = require('system');

webpage = require('webpage');

phantom.onError = function(message, stacktrace) {
  var stack, t;
  if (stacktrace != null ? stacktrace.length : void 0) {
    stack = (function() {
      var _i, _len, _results;
      _results = [];
      for (_i = 0, _len = stacktrace.length; _i < _len; _i++) {
        t = stacktrace[_i];
        _results.push(' -> ' + (t.file || t.sourceURL) + ': ' + t.line + (t["function"] ? ' (in function ' + t["function"] + ')' : ''));
      }
      return _results;
    })();
    console.log(("ERROR: " + message + "\n") + stack.join('\n'));
    return phantom.exit(1);
  }
};

hostname = (_ref = system.args[1]) != null ? _ref : 'localhost:54321';

page = webpage.create();

page.onResourceError = function(_arg) {
  var errorString, url;
  url = _arg.url, errorString = _arg.errorString;
  return console.log("ERROR: " + url + ": " + errorString);
};

page.onConsoleMessage = function(message) {
  return console.log(message);
};

waitFor = function(test, onReady, timeout) {
  var condition, interval, retest, startTime;
  if (timeout == null) {
    timeout = 3600000;
  }
  startTime = new Date().getTime();
  condition = false;
  retest = function() {
    if ((new Date().getTime() - startTime < timeout) && !condition) {
      console.log('Polling...');
      return condition = test();
    } else {
      if (condition) {
        onReady();
        return clearInterval(interval);
      } else {
        console.log('ERROR: Timeout exceeded');
        return phantom.exit(1);
      }
    }
  };
  return interval = setInterval(retest, 2000);
};

page.open("http://" + hostname + "/flow/index.html", function(status) {
  var test;
  if (status === 'success') {
    test = function() {
      return page.evaluate(function() {
        var context, runFlow, runPack, runPacks;
        context = window.flow.context;
        if (window._phantom_started_) {
          if (window._phantom_exit_) {
            return true;
          } else {
            return false;
          }
        } else {
          runPacks = function(go) {
            console.log('Fetching packs...');
            return context.requestPacks(function(error, packNames) {
              var tasks;
              if (error) {
                console.log('Failed fetching packs');
                return go(error);
              } else {
                console.log('Processing packs...');
                tasks = packNames.map(function(packName) {
                  return function(go) {
                    return runPack(packName, go);
                  };
                });
                return (Flow.Async.iterate(tasks))(go);
              }
            });
          };
          runPack = function(packName, go) {
            console.log("Fetching pack: " + packName);
            return context.requestPack(packName, function(error, flowNames) {
              var tasks;
              if (error) {
                console.log('Failed fetching pack');
                return go(error);
              } else {
                console.log('Processing pack...');
                tasks = flowNames.map(function(flowName) {
                  return function(go) {
                    return runFlow(packName, flowName, go);
                  };
                });
                return (Flow.Async.iterate(tasks))(go);
              }
            });
          };
          runFlow = function(packName, flowName, go) {
            console.log("Fetching flow: " + packName + " - " + flowName);
            return context.requestFlow(packName, flowName, function(error, flow) {
              var flowTitle, waitForFlow;
              if (error) {
                console.log('Failed fetching flow');
                return go(error);
              } else {
                flowTitle = "" + packName + " - " + flowName;
                console.log("Opening flow " + flowTitle);
                window._phantom_running_ = true;
                context.open(flowTitle, flow);
                waitForFlow = function() {
                  var errors;
                  if (window._phantom_running_) {
                    console.log('Flow still running...');
                    return setTimeout(waitForFlow, 2000);
                  } else {
                    console.log('Flow completed');
                    errors = window._phantom_errors_;
                    return context.requestRemoveAll(function() {
                      return go(errors ? errors : null);
                    });
                  }
                };
                console.log('Running flow...');
                context.executeAllCells(true, function(status, errors) {
                  console.log("Flow finished with status: " + status);
                  if (status === 'failed') {
                    window._phantom_errors_ = errors;
                  }
                  return window._phantom_running_ = false;
                });
                return setTimeout(waitForFlow, 2000);
              }
            });
          };
          console.log('Starting tests...');
          window._phantom_errors_ = null;
          window._phantom_started_ = true;
          runPacks(function(error) {
            if (error) {
              console.log('Error running packs');
              console.log(JSON.stringify(error, null, 2));
            } else {
              console.log('Finished running all packs');
            }
            return window._phantom_exit_ = true;
          });
          return false;
        }
      });
    };
    return waitFor(test, function() {
      var errors;
      errors = page.evaluate(function() {
        return window._phantom_errors_;
      });
      if (errors) {
        console.log(JSON.stringify(errors, null, 2));
        console.log('ERROR: One or more flows failed to complete');
        return phantom.exit(1);
      } else {
        console.log('Success! All flows ran to completion!');
        return phantom.exit(0);
      }
    });
  } else {
    console.log('ERROR: Unable to access network.');
    return phantom.exit(1);
  }
});
<commit_msg>More fixes to headless test output messages<commit_after>var hostname, page, system, waitFor, webpage, _ref;

system = require('system');

webpage = require('webpage');

phantom.onError = function(message, stacktrace) {
  var stack, t;
  if (stacktrace != null ? stacktrace.length : void 0) {
    stack = (function() {
      var _i, _len, _results;
      _results = [];
      for (_i = 0, _len = stacktrace.length; _i < _len; _i++) {
        t = stacktrace[_i];
        _results.push(' -> ' + (t.file || t.sourceURL) + ': ' + t.line + (t["function"] ? ' (in function ' + t["function"] + ')' : ''));
      }
      return _results;
    })();
    console.log(("PHANTOM: *** ERROR *** " + message + "\n") + stack.join('\n'));
    return phantom.exit(1);
  }
};

hostname = (_ref = system.args[1]) != null ? _ref : 'localhost:54321';

page = webpage.create();

page.onResourceError = function(_arg) {
  var errorString, url;
  url = _arg.url, errorString = _arg.errorString;
  return console.log("BROWSER: *** RESOURCE ERROR *** " + url + ": " + errorString);
};

page.onConsoleMessage = function(message) {
  return console.log("BROWSER: " + message);
};

waitFor = function(test, onReady, timeout) {
  var condition, interval, retest, startTime;
  if (timeout == null) {
    timeout = 3600000;
  }
  startTime = new Date().getTime();
  condition = false;
  retest = function() {
    if ((new Date().getTime() - startTime < timeout) && !condition) {
      console.log('PHANTOM: PING');
      return condition = test();
    } else {
      if (condition) {
        onReady();
        return clearInterval(interval);
      } else {
        console.log('PHANTOM: *** ERROR *** Timeout Exceeded');
        return phantom.exit(1);
      }
    }
  };
  return interval = setInterval(retest, 2000);
};

page.open("http://" + hostname + "/flow/index.html", function(status) {
  var test;
  if (status === 'success') {
    test = function() {
      return page.evaluate(function() {
        var context, runFlow, runPack, runPacks;
        context = window.flow.context;
        if (window._phantom_started_) {
          if (window._phantom_exit_) {
            return true;
          } else {
            return false;
          }
        } else {
          runPacks = function(go) {
            console.log('Fetching packs...');
            return context.requestPacks(function(error, packNames) {
              var tasks;
              if (error) {
                console.log('*** ERROR *** Failed fetching packs');
                return go(error);
              } else {
                console.log('Processing packs...');
                tasks = packNames.map(function(packName) {
                  return function(go) {
                    return runPack(packName, go);
                  };
                });
                return (Flow.Async.iterate(tasks))(go);
              }
            });
          };
          runPack = function(packName, go) {
            console.log("Fetching pack: " + packName);
            return context.requestPack(packName, function(error, flowNames) {
              var tasks;
              if (error) {
                console.log('*** ERROR *** Failed fetching pack');
                return go(error);
              } else {
                console.log('Processing pack...');
                tasks = flowNames.map(function(flowName) {
                  return function(go) {
                    return runFlow(packName, flowName, go);
                  };
                });
                return (Flow.Async.iterate(tasks))(go);
              }
            });
          };
          runFlow = function(packName, flowName, go) {
            console.log("Fetching flow document: " + packName + " - " + flowName);
            return context.requestFlow(packName, flowName, function(error, flow) {
              var flowTitle, waitForFlow;
              if (error) {
                console.log('*** ERROR *** Failed fetching flow document');
                return go(error);
              } else {
                flowTitle = "" + packName + " - " + flowName;
                console.log("Opening flow " + flowTitle);
                window._phantom_running_ = true;
                context.open(flowTitle, flow);
                waitForFlow = function() {
                  var errors;
                  if (window._phantom_running_) {
                    console.log('ACK');
                    return setTimeout(waitForFlow, 2000);
                  } else {
                    console.log('Flow completed!');
                    errors = window._phantom_errors_;
                    return context.requestRemoveAll(function() {
                      return go(errors ? errors : null);
                    });
                  }
                };
                console.log('Running flow...');
                context.executeAllCells(true, function(status, errors) {
                  console.log("Flow finished with status: " + status);
                  if (status === 'failed') {
                    window._phantom_errors_ = errors;
                  }
                  return window._phantom_running_ = false;
                });
                return setTimeout(waitForFlow, 2000);
              }
            });
          };
          console.log('Starting tests...');
          window._phantom_errors_ = null;
          window._phantom_started_ = true;
          runPacks(function(error) {
            if (error) {
              console.log('*** ERROR *** Error running packs: ' + JSON.stringify(error));
            } else {
              console.log('Finished running all packs!');
            }
            return window._phantom_exit_ = true;
          });
          return false;
        }
      });
    };
    return waitFor(test, function() {
      var errors;
      errors = page.evaluate(function() {
        return window._phantom_errors_;
      });
      if (errors) {
        console.log('PHANTOM: *** ERROR *** One or more flows failed to complete: ' + JSON.stringify(errors));
        return phantom.exit(1);
      } else {
        console.log('PHANTOM: Success! All flows ran to completion!');
        return phantom.exit(0);
      }
    });
  } else {
    console.log('PHANTOM: *** ERROR *** Unable to access network.');
    return phantom.exit(1);
  }
});
<|endoftext|>


<commit_before>module.exports = Messages

var h = require('virtual-dom/h')
var inherits = require('util').inherits
var BaseElement = require('./base-element')

var htmlToVDom = require('html-to-vdom')
var VNode = require('virtual-dom/vnode/vnode')
var VText = require('virtual-dom/vnode/vtext')

var convertHTML = htmlToVDom({
  VNode: VNode,
  VText: VText
})

function makeVDom (html) {
  return convertHTML('
' + html + '
')
}

function Messages (target) {
  BaseElement.call(this, target)
  this.shouldAutoScroll = true
  // keep track of the scrollTop property here to avoid odd behavior when
  // changing scrollHeight while rerendering
  this.scrollTop = 0
  this.composerHeight = 48
}
inherits(Messages, BaseElement)

Messages.prototype.render = function (channel, users) {
  var self = this
  var childViews

  if (channel && channel.messages.length === 0) {
    var starterMessage = 'This is new channel. Send a message to start things off!'
    childViews = h('.messages.starterMessage', starterMessage)
  } else {
    var messages = (channel ? channel.messages : []).map(function (msg) {
      var user = users[msg.username]
      if (user && user.blocked) return null

      var verified = !/Anonymous/i.test(msg.username) && msg.valid
      return h('li.message.clearfix', [
        h('img.avatar', { src: msg.avatar }),
        h('.username', msg.username),
        verified ? h('.verified') : null,
        h('.timestamp', msg.timeago),
        makeVDom(msg.html) || h('.text', msg.text)
      ])
    })
    childViews = h('.messages', {
      onscroll: function () {
        if (this.scrollHeight <= this.clientHeight + this.scrollTop) self.shouldAutoScroll = true
        else self.shouldAutoScroll = false
      },
      style: {
        paddingBottom: this.composerHeight
      },
      scrollTop: this.scrollTop
    }, messages)
  }

  var onleave = function () {
    if (!channel || channel.name === 'friends') return
    self.send('leaveChannel', channel.name)
  }

  var leavableChannel = channel.name !== 'friends'

  return h('.messages-container', [
    h('div', { className: 'top-bar' }, [
      h('.channelName', '#' + (channel ? channel.name : 'friends') + ' (' + channel.peers + ' peer' + (channel.peers === 1 ? '' : 's') + ')'),
      leavableChannel ? h('button.button.leaveButton', {onclick: onleave}, 'Leave') : null
    ]),
    childViews
  ])
}

Messages.prototype.scrollToBottom = function (force) {
  if (!force && !this.shouldAutoScroll) return
  var messagesDiv = document.querySelector('.messages')
  if (messagesDiv) messagesDiv.scrollTop = messagesDiv.scrollHeight
}

Messages.prototype.notifyComposerHeight = function (height) {
  var messagesDiv = document.querySelector('.messages')
  if (messagesDiv) {
    var heightChange = height - this.composerHeight
    this.scrollTop = messagesDiv.scrollTop + heightChange
  }

  this.composerHeight = height
}
<commit_msg>Fix grammar in "new channel" message<commit_after>module.exports = Messages

var h = require('virtual-dom/h')
var inherits = require('util').inherits
var BaseElement = require('./base-element')

var htmlToVDom = require('html-to-vdom')
var VNode = require('virtual-dom/vnode/vnode')
var VText = require('virtual-dom/vnode/vtext')

var convertHTML = htmlToVDom({
  VNode: VNode,
  VText: VText
})

function makeVDom (html) {
  return convertHTML('
' + html + '
')
}

function Messages (target) {
  BaseElement.call(this, target)
  this.shouldAutoScroll = true
  // keep track of the scrollTop property here to avoid odd behavior when
  // changing scrollHeight while rerendering
  this.scrollTop = 0
  this.composerHeight = 48
}
inherits(Messages, BaseElement)

Messages.prototype.render = function (channel, users) {
  var self = this
  var childViews

  if (channel && channel.messages.length === 0) {
    var starterMessage = 'This is a new channel. Send a message to start things off!'
    childViews = h('.messages.starterMessage', starterMessage)
  } else {
    var messages = (channel ? channel.messages : []).map(function (msg) {
      var user = users[msg.username]
      if (user && user.blocked) return null

      var verified = !/Anonymous/i.test(msg.username) && msg.valid
      return h('li.message.clearfix', [
        h('img.avatar', { src: msg.avatar }),
        h('.username', msg.username),
        verified ? h('.verified') : null,
        h('.timestamp', msg.timeago),
        makeVDom(msg.html) || h('.text', msg.text)
      ])
    })
    childViews = h('.messages', {
      onscroll: function () {
        if (this.scrollHeight <= this.clientHeight + this.scrollTop) self.shouldAutoScroll = true
        else self.shouldAutoScroll = false
      },
      style: {
        paddingBottom: this.composerHeight
      },
      scrollTop: this.scrollTop
    }, messages)
  }

  var onleave = function () {
    if (!channel || channel.name === 'friends') return
    self.send('leaveChannel', channel.name)
  }

  var leavableChannel = channel.name !== 'friends'

  return h('.messages-container', [
    h('div', { className: 'top-bar' }, [
      h('.channelName', '#' + (channel ? channel.name : 'friends') + ' (' + channel.peers + ' peer' + (channel.peers === 1 ? '' : 's') + ')'),
      leavableChannel ? h('button.button.leaveButton', {onclick: onleave}, 'Leave') : null
    ]),
    childViews
  ])
}

Messages.prototype.scrollToBottom = function (force) {
  if (!force && !this.shouldAutoScroll) return
  var messagesDiv = document.querySelector('.messages')
  if (messagesDiv) messagesDiv.scrollTop = messagesDiv.scrollHeight
}

Messages.prototype.notifyComposerHeight = function (height) {
  var messagesDiv = document.querySelector('.messages')
  if (messagesDiv) {
    var heightChange = height - this.composerHeight
    this.scrollTop = messagesDiv.scrollTop + heightChange
  }

  this.composerHeight = height
}
<|endoftext|>


<commit_before>mini.Module(
	"engine/core/bloob"
)
.requires(

)
.defines(function() {
	window.Bloob = {};

	var Bloob = window.Bloob;

	return Bloob;
});
<commit_msg>added stubs of debug methods for secure call if no debugging is active<commit_after>mini.Module(
	"engine/core/bloob"
)
.requires(

)
.defines(function() {
	window.Bloob = {
		log: function() {},
		mark: function() {},
		show: function() {},
		assert: function() {}
	};

	var Bloob = window.Bloob;

	return Bloob;
});
<|endoftext|>


<commit_before>var validator = require('validator');
var _ = require('lodash');
var Promise = require('bluebird');

// validators and sanitizers not prefixed with is/to
var additionalValidators = ['contains', 'equals', 'matches'];
var additionalSanitizers = ['trim', 'ltrim', 'rtrim', 'escape', 'stripLow', 'whitelist', 'blacklist', 'normalizeEmail'];

/**
 * Initializes a chain of validators
 *
 * @class
 * @param  {(string|string[])}  param         path to property to validate
 * @param  {string}             failMsg       validation failure message
 * @param  {Request}            req           request to attach validation errors
 * @param  {string}             location      request property to find value (body, params, query, etc.)
 * @param  {object}             options       options containing error formatter
 */

function ValidatorChain(param, failMsg, req, location, options) {
  this.errorFormatter = options.errorFormatter;
  this.param = param;
  this.value = location ? _.get(req[location], param) : undefined;
  this.validationErrors = [];
  this.failMsg = failMsg;
  this.req = req;
  this.lastError = null; // used by withMessage to get the values of the last error
  return this;
}

/**
 * Initializes a sanitizer
 *
 * @class
 * @param  {(string|string[])}  param    path to property to sanitize
 * @param  {[type]}             req             request to sanitize
 * @param  {[type]}             location        request property to find value
 */

function Sanitizer(param, req, locations) {
  this.values = locations.map(function(location) {
    return _.get(req[location], param);
  });

  this.req = req;
  this.param = param;
  this.locations = locations;
  return this;
}

/**
 * Adds validation methods to request object via express middleware
 *
 * @method expressValidator
 * @param  {object}         options
 * @return {function}       middleware
 */

var expressValidator = function(options) {
  options = options || {};
  var defaults = {
    customValidators: {},
    customSanitizers: {},
    errorFormatter: function(param, msg, value) {
      return {
        param: param,
        msg: msg,
        value: value
      };
    }
  };

  _.defaults(options, defaults);

  // _.set validators and sanitizers as prototype methods on corresponding chains
  _.forEach(validator, function(method, methodName) {
    if (methodName.match(/^is/) || _.contains(additionalValidators, methodName)) {
      ValidatorChain.prototype[methodName] = makeValidator(methodName, validator);
    }

    if (methodName.match(/^to/) || _.contains(additionalSanitizers, methodName)) {
      Sanitizer.prototype[methodName] = makeSanitizer(methodName, validator);
    }
  });

  ValidatorChain.prototype.notEmpty = function() {
    return this.isLength(1);
  };

  ValidatorChain.prototype.len = function() {
    return this.isLength.apply(this, arguments);
  };

  ValidatorChain.prototype.optional = function() {
    if (this.value === undefined) {
      this.skipValidating = true;
    }

    return this;
  };

  ValidatorChain.prototype.withMessage = function(message) {
    if (this.lastError) {
      this.validationErrors.pop();
      this.req._validationErrors.pop();
      var error = this.errorFormatter(this.lastError.param, message, this.lastError.value);
      this.validationErrors.push(error);
      this.req._validationErrors.push(error);
      this.lastError = null;
    }

    return this;
  };

  _.forEach(options.customValidators, function(method, customValidatorName) {
    ValidatorChain.prototype[customValidatorName] = makeValidator(customValidatorName, options.customValidators);
  });

  _.forEach(options.customSanitizers, function(method, customSanitizerName) {
    Sanitizer.prototype[customSanitizerName] = makeSanitizer(customSanitizerName, options.customSanitizers);
  });

  return function(req, res, next) {
    var locations = ['body', 'params', 'query'];

    req._validationErrors = [];
    req._asyncValidationErrors = [];
    req.validationErrors = function(mapped, promisesResolved) {
      if (!promisesResolved && req._asyncValidationErrors.length > 0) {
        console.warn('WARNING: You have asynchronus validators but you have not used asyncValidateErrors to check for errors.');
      }

      if (mapped && req._validationErrors.length > 0) {
        var errors = {};
        req._validationErrors.forEach(function(err) {
          errors[err.param] = err;
        });

        return errors;
      }

      return req._validationErrors.length > 0 ? req._validationErrors : false;
    };

    req.asyncValidationErrors = function(mapped) {
      return new Promise(function(resolve, reject) {
        var promises = req._asyncValidationErrors;
        Promise.settle(promises).then(function(results) {

          results.forEach(function(result) {
             if (result.isRejected()) { req._validationErrors.push(result.reason()); }
          });

          if (req._validationErrors.length > 0) {
            return reject(req.validationErrors(mapped, true));
          }
          resolve();
        });
      });
    };

    locations.forEach(function(location) {
      req['sanitize' + _.capitalize(location)] = function(param) {
        return new Sanitizer(param, req, [location]);
      };
    });

    req.sanitize = function(param) {
      return new Sanitizer(param, req, locations);
    };

    locations.forEach(function(location) {
      req['check' + _.capitalize(location)] = function(param, failMsg) {
        if (_.isPlainObject(param)) {
          return validateSchema(param, req, location, options);
        }
        return new ValidatorChain(param, failMsg, req, location, options);
      };
    });

    req.checkFiles = function(param, failMsg) {
      return new ValidatorChain(param, failMsg, req, 'files', options);
    };

    req.checkHeaders = function(param, failMsg) {
      if (param === 'referrer') {
        param = 'referer';
      }

      return new ValidatorChain(param, failMsg, req, 'headers', options);
    };

    req.check = function(param, failMsg) {
      if (_.isPlainObject(param)) {
        return validateSchema(param, req, 'any', options);
      }
      return new ValidatorChain(param, failMsg, req, locate(req, param), options);
    };

    req.filter = req.sanitize;
    req.assert = req.check;
    req.validate = req.check;

    next();
  };
};

/**
 * validate an object using a schema, using following format:
 *
 * {
 *   paramName: {
 *     validatorName: true,
 *     validator2Name: true
 *   }
 * }
 *
 * Pass options or a custom error message:
 *
 * {
 *   paramName: {
 *     validatorName: {
 *       options: ['', ''],
 *       errorMessage: 'An Error Message'
 *     }
 *   }
 * }
 *
 * @method validateSchema
 * @param  {Object}       schema    schema of validations
 * @param  {Request}      req       request to attach validation errors
 * @param  {string}       location  request property to find value (body, params, query, etc.)
 * @param  {Object}       options   options containing custom validators & errorFormatter
 * @return {object[]}               array of errors
 */

function validateSchema(schema, req, loc, options) {
  for (var param in schema) {
    loc = loc === 'any' ? locate(req, param) : loc;
    var validator = new ValidatorChain(param, null, req, loc, options);
    var paramErrorMessage = schema[param].errorMessage;
    delete schema[param].errorMessage;

    for (var methodName in schema[param]) {
      validator.failMsg = schema[param][methodName].errorMessage || paramErrorMessage || 'Invalid param';
      validator[methodName].apply(validator, schema[param][methodName].options);
    }
  }
}

/**
 * Validates and handles errors, return instance of itself to allow for chaining
 *
 * @method makeValidator
 * @param  {string}          methodName
 * @param  {object}          container
 * @return {function}
 */

function makeValidator(methodName, container) {
  return function() {
    if (this.skipValidating) {
      return this;
    }

    var args = [];
    args.push(this.value);
    args = args.concat(Array.prototype.slice.call(arguments));

    var isValid = container[methodName].apply(container, args);

    var error = this.errorFormatter(this.param, this.failMsg || 'Invalid value', this.value);

    if (isValid.then) {
      var promise = isValid.catch(function() {
        return Promise.reject(error);
      });
      this.req._asyncValidationErrors.push(promise);
    }

    if (!isValid) {
      this.validationErrors.push(error);
      this.req._validationErrors.push(error);
      this.lastError = { param: this.param, value: this.value };
    } else {
      this.lastError = null;
    }

    return this;
  };
}

/**
 * Sanitizes and sets sanitized value on the request, then return instance of itself to allow for chaining
 *
 * @method makeSanitizer
 * @param  {string}          methodName
 * @param  {object}          container
 * @return {function}
 */

function makeSanitizer(methodName, container) {
  return function() {
    var _arguments = arguments;
    var result;
    this.values.forEach(function(value, i) {
      if (value != null) {
        var args = [value];
        args = args.concat(Array.prototype.slice.call(_arguments));
        result = container[methodName].apply(container, args);

        _.set(this.req[this.locations[i]], this.param, result);
        this.values[i] = result;
      }
    }.bind(this));

    return result;
  };
}

/**
 * find location of param
 *
 * @method param
 * @param  {Request} req       express request object
 * @param  {(string|string[])} name [description]
 * @return {string}
 */

function locate(req, name) {
  if (_.get(req.params, name)) {
    return 'params';
  } else if (_.has(req.query, name)) {
    return 'query';
  } else if (_.has(req.body, name)) {
    return 'body';
  }

  return undefined;
}

module.exports = expressValidator;
module.exports.validator = validator;
<commit_msg>Typo fix.<commit_after>var validator = require('validator');
var _ = require('lodash');
var Promise = require('bluebird');

// validators and sanitizers not prefixed with is/to
var additionalValidators = ['contains', 'equals', 'matches'];
var additionalSanitizers = ['trim', 'ltrim', 'rtrim', 'escape', 'stripLow', 'whitelist', 'blacklist', 'normalizeEmail'];

/**
 * Initializes a chain of validators
 *
 * @class
 * @param  {(string|string[])}  param         path to property to validate
 * @param  {string}             failMsg       validation failure message
 * @param  {Request}            req           request to attach validation errors
 * @param  {string}             location      request property to find value (body, params, query, etc.)
 * @param  {object}             options       options containing error formatter
 */

function ValidatorChain(param, failMsg, req, location, options) {
  this.errorFormatter = options.errorFormatter;
  this.param = param;
  this.value = location ? _.get(req[location], param) : undefined;
  this.validationErrors = [];
  this.failMsg = failMsg;
  this.req = req;
  this.lastError = null; // used by withMessage to get the values of the last error
  return this;
}

/**
 * Initializes a sanitizer
 *
 * @class
 * @param  {(string|string[])}  param    path to property to sanitize
 * @param  {[type]}             req             request to sanitize
 * @param  {[type]}             location        request property to find value
 */

function Sanitizer(param, req, locations) {
  this.values = locations.map(function(location) {
    return _.get(req[location], param);
  });

  this.req = req;
  this.param = param;
  this.locations = locations;
  return this;
}

/**
 * Adds validation methods to request object via express middleware
 *
 * @method expressValidator
 * @param  {object}         options
 * @return {function}       middleware
 */

var expressValidator = function(options) {
  options = options || {};
  var defaults = {
    customValidators: {},
    customSanitizers: {},
    errorFormatter: function(param, msg, value) {
      return {
        param: param,
        msg: msg,
        value: value
      };
    }
  };

  _.defaults(options, defaults);

  // _.set validators and sanitizers as prototype methods on corresponding chains
  _.forEach(validator, function(method, methodName) {
    if (methodName.match(/^is/) || _.contains(additionalValidators, methodName)) {
      ValidatorChain.prototype[methodName] = makeValidator(methodName, validator);
    }

    if (methodName.match(/^to/) || _.contains(additionalSanitizers, methodName)) {
      Sanitizer.prototype[methodName] = makeSanitizer(methodName, validator);
    }
  });

  ValidatorChain.prototype.notEmpty = function() {
    return this.isLength(1);
  };

  ValidatorChain.prototype.len = function() {
    return this.isLength.apply(this, arguments);
  };

  ValidatorChain.prototype.optional = function() {
    if (this.value === undefined) {
      this.skipValidating = true;
    }

    return this;
  };

  ValidatorChain.prototype.withMessage = function(message) {
    if (this.lastError) {
      this.validationErrors.pop();
      this.req._validationErrors.pop();
      var error = this.errorFormatter(this.lastError.param, message, this.lastError.value);
      this.validationErrors.push(error);
      this.req._validationErrors.push(error);
      this.lastError = null;
    }

    return this;
  };

  _.forEach(options.customValidators, function(method, customValidatorName) {
    ValidatorChain.prototype[customValidatorName] = makeValidator(customValidatorName, options.customValidators);
  });

  _.forEach(options.customSanitizers, function(method, customSanitizerName) {
    Sanitizer.prototype[customSanitizerName] = makeSanitizer(customSanitizerName, options.customSanitizers);
  });

  return function(req, res, next) {
    var locations = ['body', 'params', 'query'];

    req._validationErrors = [];
    req._asyncValidationErrors = [];
    req.validationErrors = function(mapped, promisesResolved) {
      if (!promisesResolved && req._asyncValidationErrors.length > 0) {
        console.warn('WARNING: You have asynchronous validators but you have not used asyncValidateErrors to check for errors.');
      }

      if (mapped && req._validationErrors.length > 0) {
        var errors = {};
        req._validationErrors.forEach(function(err) {
          errors[err.param] = err;
        });

        return errors;
      }

      return req._validationErrors.length > 0 ? req._validationErrors : false;
    };

    req.asyncValidationErrors = function(mapped) {
      return new Promise(function(resolve, reject) {
        var promises = req._asyncValidationErrors;
        Promise.settle(promises).then(function(results) {

          results.forEach(function(result) {
             if (result.isRejected()) { req._validationErrors.push(result.reason()); }
          });

          if (req._validationErrors.length > 0) {
            return reject(req.validationErrors(mapped, true));
          }
          resolve();
        });
      });
    };

    locations.forEach(function(location) {
      req['sanitize' + _.capitalize(location)] = function(param) {
        return new Sanitizer(param, req, [location]);
      };
    });

    req.sanitize = function(param) {
      return new Sanitizer(param, req, locations);
    };

    locations.forEach(function(location) {
      req['check' + _.capitalize(location)] = function(param, failMsg) {
        if (_.isPlainObject(param)) {
          return validateSchema(param, req, location, options);
        }
        return new ValidatorChain(param, failMsg, req, location, options);
      };
    });

    req.checkFiles = function(param, failMsg) {
      return new ValidatorChain(param, failMsg, req, 'files', options);
    };

    req.checkHeaders = function(param, failMsg) {
      if (param === 'referrer') {
        param = 'referer';
      }

      return new ValidatorChain(param, failMsg, req, 'headers', options);
    };

    req.check = function(param, failMsg) {
      if (_.isPlainObject(param)) {
        return validateSchema(param, req, 'any', options);
      }
      return new ValidatorChain(param, failMsg, req, locate(req, param), options);
    };

    req.filter = req.sanitize;
    req.assert = req.check;
    req.validate = req.check;

    next();
  };
};

/**
 * validate an object using a schema, using following format:
 *
 * {
 *   paramName: {
 *     validatorName: true,
 *     validator2Name: true
 *   }
 * }
 *
 * Pass options or a custom error message:
 *
 * {
 *   paramName: {
 *     validatorName: {
 *       options: ['', ''],
 *       errorMessage: 'An Error Message'
 *     }
 *   }
 * }
 *
 * @method validateSchema
 * @param  {Object}       schema    schema of validations
 * @param  {Request}      req       request to attach validation errors
 * @param  {string}       location  request property to find value (body, params, query, etc.)
 * @param  {Object}       options   options containing custom validators & errorFormatter
 * @return {object[]}               array of errors
 */

function validateSchema(schema, req, loc, options) {
  for (var param in schema) {
    loc = loc === 'any' ? locate(req, param) : loc;
    var validator = new ValidatorChain(param, null, req, loc, options);
    var paramErrorMessage = schema[param].errorMessage;
    delete schema[param].errorMessage;

    for (var methodName in schema[param]) {
      validator.failMsg = schema[param][methodName].errorMessage || paramErrorMessage || 'Invalid param';
      validator[methodName].apply(validator, schema[param][methodName].options);
    }
  }
}

/**
 * Validates and handles errors, return instance of itself to allow for chaining
 *
 * @method makeValidator
 * @param  {string}          methodName
 * @param  {object}          container
 * @return {function}
 */

function makeValidator(methodName, container) {
  return function() {
    if (this.skipValidating) {
      return this;
    }

    var args = [];
    args.push(this.value);
    args = args.concat(Array.prototype.slice.call(arguments));

    var isValid = container[methodName].apply(container, args);

    var error = this.errorFormatter(this.param, this.failMsg || 'Invalid value', this.value);

    if (isValid.then) {
      var promise = isValid.catch(function() {
        return Promise.reject(error);
      });
      this.req._asyncValidationErrors.push(promise);
    }

    if (!isValid) {
      this.validationErrors.push(error);
      this.req._validationErrors.push(error);
      this.lastError = { param: this.param, value: this.value };
    } else {
      this.lastError = null;
    }

    return this;
  };
}

/**
 * Sanitizes and sets sanitized value on the request, then return instance of itself to allow for chaining
 *
 * @method makeSanitizer
 * @param  {string}          methodName
 * @param  {object}          container
 * @return {function}
 */

function makeSanitizer(methodName, container) {
  return function() {
    var _arguments = arguments;
    var result;
    this.values.forEach(function(value, i) {
      if (value != null) {
        var args = [value];
        args = args.concat(Array.prototype.slice.call(_arguments));
        result = container[methodName].apply(container, args);

        _.set(this.req[this.locations[i]], this.param, result);
        this.values[i] = result;
      }
    }.bind(this));

    return result;
  };
}

/**
 * find location of param
 *
 * @method param
 * @param  {Request} req       express request object
 * @param  {(string|string[])} name [description]
 * @return {string}
 */

function locate(req, name) {
  if (_.get(req.params, name)) {
    return 'params';
  } else if (_.has(req.query, name)) {
    return 'query';
  } else if (_.has(req.body, name)) {
    return 'body';
  }

  return undefined;
}

module.exports = expressValidator;
module.exports.validator = validator;
<|endoftext|>


<commit_before>const _ = require('underscore')

module.exports = function ($metaTags) {
  var extractedMetaTags = {}
  if ($metaTags) {
    _.each($metaTags, function ($meta) {
      if ($meta.attribs && $meta.attribs.name && $meta.attribs.content) {
        extractedMetaTags[$meta.attribs.name] = $meta.attribs.content
      }
      if ($meta.attribs && $meta.attribs.property && $meta.attribs.content) {
        extractedMetaTags[$meta.attribs.property] = $meta.attribs.content
      }
    })
  }
  return extractedMetaTags
}
<commit_msg>refactor underscore out of extract-meta-tags<commit_after>module.exports = function ($metaTags) {
  var extracted = {}
  if ($metaTags) {
    Object.keys($metaTags).forEach(function (key, index) {
      if ($metaTags[key].attribs && $metaTags[key].attribs.name && $metaTags[key].attribs.content) {
        extracted[$metaTags[key].attribs.name] = $metaTags[key].attribs.content
      }
      if ($metaTags[key].attribs && $metaTags[key].attribs.property && $metaTags[key].attribs.content) {
        extracted[$metaTags[key].attribs.property] = $metaTags[key].attribs.content
      }
    })
  }
  return extracted
}
<|endoftext|>


<commit_before>import isBinaryFile from 'isbinaryfile';
import path from 'path';
import _ from 'lodash';
import fs from 'fs';
import stylelint from 'stylelint';
import autoprefixer from 'autoprefixer';
import postcss from 'postcss';
import { setQueueAsset } from '../request/assetManager';
import { updateteAssets } from '../request/asset';
import { writeFile,
         fileMissing} from '../file-system/file';
import { getAssetPath } from '../paths';
import chokidar from 'chokidar';
import delay from 'delay';
import cpFile from 'cp-file';
const jsdiff = require('diff');
import clc from 'cli-color';

const log_error = clc.xterm(9);
const log_warn = clc.xterm(221);
const log_notice = clc.xterm(33);
const log_remove = clc.xterm(196);
const log_edit = clc.xterm(40);
const log_white = clc.xterm(254);

/**
 * Получаем событие файловой системы и путь к файлу, собираем информацию о файле и отправляем в менеджер задач
 */
export function _watch(conf, state, event, _path, _debugMode) {
  const paths = conf.get('paths');
  const options = conf.get('options');
  const eventEmitter = conf.get('eventEmitter');
  let pathNormal = path.normalize(_path);
  let pathParse = path.parse(pathNormal);
  let _fileName = pathParse.base;
  let debugMode = _debugMode || false;

  if (/\s/g.test(_fileName)) {
    eventEmitter.emit('file:error', {
      message: `Недопустимое имя файла - ${_path}`
    });
    throw new Error('Удалите пробелы в названии файла.');
  }
  if (!_.includes(['add', 'change', 'unlink'], event)) {
    return;
  }

  getFileInfo(_path, paths, event).then(fileInfo => {
    if (debugMode) {
      let _fileInfo = _.cloneDeep(fileInfo);
      console.log(log_notice('\nEvent: ') + `${event}`)
      console.log( log_notice('File info: ') );
      console.log(_.omit(_fileInfo, ['data']));
    }

    let _content = getContent(fileInfo);
    fileInfo.content = _content;
    fileInfo.event = event;

    if (_.eq(fileInfo.type, 'Asset::Media')) {
      // сравнить файлы и скопировать ассет в папку media если нужно
      if (fileInfo.synchronizePath !== '') {
        syncFile(fileInfo.path, fileInfo.synchronizePath, fileInfo.encode, event, debugMode)
      }

      if (fileInfo.isMediaFile) {

        let isStyleLintUse = (_.indexOf(['.scss', '.css'], fileInfo.pathParse.ext) > -1) && options.tools.stylelint.use;

        if (isStyleLintUse) {
            stylelint.lint({
              code: fileInfo.content.asset.content,
              config: options.tools.stylelint.config,
              formatter: "string",
              syntax: "scss"
            }).then((data)  => {
              if (data.errored && data.output) {
                eventEmitter.emit('css:error', {
                  message: data.output
                });
                if (!options.tools.stylelint.stopOnFail) {
                  setQueueAsset(conf, state, fileInfo, {},debugMode);
                }
              }else{
                setQueueAsset(conf, state, fileInfo, {},debugMode);
              }
            })
        }else{
          setQueueAsset(conf, state, fileInfo, {},debugMode);
        }

      }
    }

    if(! _.eq(fileInfo.type, 'Asset::Media')){
      setQueueAsset(conf, state, fileInfo, {},debugMode);
    }

  });
}

/**
 * Сравнивает два файла, возваращает true если они разные
 */
function syncFile(file1, file2, encode, event, debugMode = false) {

  if (_.isEqual(event, 'unlink')) {
    fileMissing(file2).then(()=>{
      return;
    }).catch(()=>{
      fs.unlink(file2, function(err){
        if (debugMode) {
          console.log(`${file2} удален`)
        }
        if(err) return console.log(err);
      });
      return
    })
  }else{

  fs.readFile(file2,  (err2, data2) => {
    if (err2){
      cpFile.sync(file1, file2);
      if (debugMode) {
        console.log(`${file1} синхронизирован с ${file2}\n`)
      }
      return;
    }else{
      let stats1 = fs.statSync(file1)
      let stats2 = fs.statSync(file2)
      let fileSizeInBytes1 = _.toNumber(stats1["size"]);
      let fileSizeInBytes2 = _.toNumber(stats2["size"]);

      if (_.isEqual(fileSizeInBytes1, fileSizeInBytes2)) {

        fs.readFile(file1,  (err1, data1) => {
          if (err1) {
            console.log(`Невозможно прочитать файл ${file1}`)
            return;
          }else{
            let difa = jsdiff.diffChars(data2.toString(encode), data1.toString(encode));
            let difSize = _.size(difa);
            if (difSize > 1) {
              if (debugMode) {
                console.log(`${file1} синхронизирован с ${file2}\n`);
              }
              cpFile.sync(file1, file2);
            }else{
              if (debugMode) {
                console.log(`Нет причин для синхронизации`)
                console.log(`${file1} идентичен ${file2}\n`);
              }
            }
          }
        });
      }else{
        if (debugMode) {
          console.log(`${file1} синхронизирован с ${file2}\n`)
        }
        cpFile.sync(file1, file2);
      }
    }
  })
}
}

export function triggerFile(conf, state, event, _path) {
  return new Promise(function (resolve, reject) {
    _watch(conf, state, event, _path);
    resolve();
  });
}

export function closeWatcher(conf, state) {
  const options = conf.get('options');
  const eventEmitter = conf.get('eventEmitter');

  eventEmitter.emit('theme:stream:stop', {
    message: `Stop watcher`
  });
}
export function watcher(conf, state) {
  const paths = conf.get('paths');
  const options = conf.get('options');
  const eventEmitter = conf.get('eventEmitter');
  let debugMode = options.tools.debugMode || false;

  var _options = {
    ignored: /[\/\\]\./,
    ignoreInitial: true,
    followSymlinks: true,
    usePolling: true,
    interval: 200,
    binaryInterval: 300,
    alwaysStat: true,
    depth: 99,
    awaitWriteFinish: {
      stabilityThreshold: 100,
      pollInterval: 100
    },
    ignorePermissionErrors: true
  }

  var watcherInstance = chokidar.watch(paths.toWatch, _options).on('all', (event, _path) => {
    _watch(conf, state, event, _path, debugMode);
  });

  eventEmitter.on('theme:stream:stop', function (data) {
    watcherInstance.close();
  });

}

/**
 * @return
 * {
 *   name: 'test.js',
 *   type: 'Asset::Media',
 *   path: 'root/assets/js/test.js',
 *   synchronizePath: '' || 'root/media/test.js',
 *   encode: 'utf8',
 *   isBinary: false,
 *   data: 'console.log("My test file")'
 * }
 */
export function getFileInfo(_path, paths, event = 'add') {
  return new Promise(function (resolve, reject) {
  let fileInfo = {};
  fileInfo.path = path.normalize(_path);
  fileInfo.pathParse = path.parse(_path);
  fileInfo.encode = 'utf8';
  fileInfo.isBinary = false;
  fileInfo.data = '';

  let assetInfo = getAssetInfo(_path, paths)
  fileInfo = _.merge(fileInfo, assetInfo)
  if (event === 'unlink') {
    resolve(fileInfo);
  }else{
    if (isBinaryFile.sync(_path)) {
      fileInfo.encode = 'base64';
      fileInfo.isBinary = true;
    }
    fs.readFile(_path, (err, data) => {
      if (err) throw err;
      var _data = data.toString(fileInfo.encode)
      fileInfo.data = _data
      resolve(fileInfo);
    })
  }
  })
}

/**
 * @return
 * {
 *   name: 'test.js',
 *   type: 'Asset::Media',
 *   isMediaFile: true,
 *   synchronizePath: '' || 'root/media/test.js'
 * }
 */
export function getAssetInfo(_path, paths) {
  let assetInfo = {};
  assetInfo.synchronizePath = '';

  let pathMedia = paths.folders.media_root;
  let pathNormal = path.normalize(_path);
  let pathParse = path.parse(pathNormal);
  let _fileName = pathParse.base;
  let _dirPath = pathParse.dir;
  var _ext = pathParse.ext;
  let _folderParent = _.last(_dirPath.split(path.sep));
  let _assetType = _.findKey(paths.assets, function(o) {
    return _.includes(o.folder, _dirPath);
  })

  if (!_assetType) {
    _assetType = 'Asset::Media';
  }

  assetInfo.name = _fileName;
  assetInfo.type = _assetType;
  assetInfo.isMediaFile = false;;

  if (_assetType === 'Asset::Media') {
    if (pathMedia.indexOf(_dirPath) < 0 ) {
      assetInfo.synchronizePath = path.normalize(pathMedia + '/' + _fileName);
    }else{
      assetInfo.isMediaFile = true;
      assetInfo.synchronizePath = getAssetPath(paths, _assetType, _fileName, _ext, { isAssetsPath: true });
    }
  }

  return assetInfo;
}

/**
 * Получить объект в нужном для insalesApi виде
 * @param  {object} fileInfo информация о файле
 * {
 *   name: 'test.js',
 *   type: 'Asset::Media',
 *   synchronizePath: '' || 'root/media/test.js',
 *   encode: 'utf8',
 *   isBinary: false,
 *   data: 'console.log("My test file")'
 * }
 */
export function getContent(fileInfo, event = 'add') {
  let _content = {}
  if (_.eq(event, 'unlink')) {
    return _content;
  }

  _content.asset = {};
  _content.upload = {
    'name': fileInfo.name,
    'type': fileInfo.type
  }

  if (fileInfo.isBinary) {
    _content.asset['attachment'] = fileInfo.data;
    _content.upload['attachment'] = fileInfo.data;
  }else{
    let dataReplace = remove_etx(fileInfo.data, fileInfo.name);
    _content.asset['content'] = dataReplace
    _content.upload['content'] = dataReplace;
  }

  return _content;
}

function remove_etx(str, name) {

  if ((str===null) || (str===''))
       return '';
 else
   str = str.toString();
   let searchRegExp = /\x03/g;
   if (searchRegExp.test(str)) {
     console.log(log_warn(`Удалите спецсимвол \\u0003 из файла ${name}`));
     str = str.replace(/\x03/g, '');
   }
  return str;
}

export function uploadAssets(conf, state, param) {
  const options = conf.get('options');
  const paths = conf.get('paths');

  if (!param) {
    var param = {
      update: false
    }
  }else{
    if (!param.update) {
      param.update = false
    }
  }
  updateteAssets(conf, state).then(function () {
  const assets = conf.get('assets');
  var _folders = paths.foldersDefaults;
  var _folderSize = _.size(_folders);
  var _count = 0;
  _.forEach(_folders, function (folder) {
    fs.readdir(folder, function(err, list) {
      var _listSize = list.length - 1;
      if (err) {
        console.log(err);
      }
      if (list.length > 0) {
        _.forEach(list, function (_name, index) {
          var _fullPath = path.normalize(folder + _name);
          if ( _.isUndefined(assets[_fullPath]) || param.update ) {

            getFileInfo(_fullPath, paths, 'add').then(fileInfo => {
              let _content = getContent(fileInfo);
              fileInfo.content = _content;
              fileInfo.event = 'add';
              setQueueAsset(conf, state, fileInfo)
              if (index === _listSize) {
                _count++
              }
            })
          }else{
            if (index === _listSize) {
              _count++
            }
          }
        })
      }else{
        _count++
      }
    })
  })
  })
}
<commit_msg>Update watch.js<commit_after>import isBinaryFile from 'isbinaryfile';
import path from 'path';
import _ from 'lodash';
import fs from 'fs';
import stylelint from 'stylelint';
import autoprefixer from 'autoprefixer';
import postcss from 'postcss';
import { setQueueAsset } from '../request/assetManager';
import { updateteAssets } from '../request/asset';
import { writeFile,
         fileMissing} from '../file-system/file';
import { getAssetPath } from '../paths';
import chokidar from 'chokidar';
import delay from 'delay';
import cpFile from 'cp-file';
const jsdiff = require('diff');
import clc from 'cli-color';

const log_error = clc.xterm(9);
const log_warn = clc.xterm(221);
const log_notice = clc.xterm(33);
const log_remove = clc.xterm(196);
const log_edit = clc.xterm(40);
const log_white = clc.xterm(254);

/**
 * Получаем событие файловой системы и путь к файлу, собираем информацию о файле и отправляем в менеджер задач
 */
export function _watch(conf, state, event, _path, _debugMode) {
  const paths = conf.get('paths');
  const options = conf.get('options');
  const eventEmitter = conf.get('eventEmitter');
  let pathNormal = path.normalize(_path);
  let pathParse = path.parse(pathNormal);
  let _fileName = pathParse.base;
  let debugMode = _debugMode || false;

  if (/\s/g.test(_fileName)) {
    eventEmitter.emit('file:error', {
      message: `Недопустимое имя файла - ${_path}`
    });
    throw new Error('Удалите пробелы в названии файла.');
  }
  if (!_.includes(['add', 'change', 'unlink'], event)) {
    return;
  }

  getFileInfo(_path, paths, event).then(fileInfo => {
    if (debugMode) {
      let _fileInfo = _.cloneDeep(fileInfo);
      console.log(log_notice('\nEvent: ') + `${event}`)
      console.log( log_notice('File info: ') );
      console.log(_.omit(_fileInfo, ['data']));
    }

    let _content = getContent(fileInfo);
    fileInfo.content = _content;
    fileInfo.event = event;

    if (_.eq(fileInfo.type, 'Asset::Media')) {
      // сравнить файлы и скопировать ассет в папку media если нужно
      if (fileInfo.synchronizePath !== '') {
        syncFile(fileInfo.path, fileInfo.synchronizePath, fileInfo.encode, event, debugMode)
      }

      if (fileInfo.isMediaFile) {

        let isStyle = (_.indexOf(['.scss', '.css'], fileInfo.pathParse.ext) > -1);
        let isStyleLintUse = (_.indexOf(['.scss', '.css'], fileInfo.pathParse.ext) > -1) && options.tools.stylelint.use;

        if (isStyleLintUse) {
          if (options.tools.autoprefixer.use) {
            postcss([ autoprefixer(options.tools.autoprefixer.config) ]).process(fileInfo.content.asset.content).then(function (result) {
              result.warnings().forEach(function (warn) {
                  console.warn(warn.toString());
              });
              fileInfo.content.asset.content = result.css;
              stylelint.lint({
                code: fileInfo.content.asset.content,
                config: options.tools.stylelint.config,
                formatter: "string",
                syntax: "scss"
              }).then((data)  => {
                if (data.errored && data.output) {
                  eventEmitter.emit('css:error', {
                    message: data.output
                  });
                  if (!options.tools.stylelint.stopOnFail) {
                    setQueueAsset(conf, state, fileInfo, {},debugMode);
                  }
                }else{
                  setQueueAsset(conf, state, fileInfo, {},debugMode);
                }
              })
            })
          }else{
            stylelint.lint({
              code: fileInfo.content.asset.content,
              config: options.tools.stylelint.config,
              formatter: "string",
              syntax: "scss"
            }).then((data)  => {
              if (data.errored && data.output) {
                eventEmitter.emit('css:error', {
                  message: data.output
                });
                if (!options.tools.stylelint.stopOnFail) {
                  setQueueAsset(conf, state, fileInfo, {},debugMode);
                }
              }else{
                setQueueAsset(conf, state, fileInfo, {},debugMode);
              }
            })
          }

        }else{
          if (options.tools.autoprefixer.use) {
            postcss([ autoprefixer(options.tools.autoprefixer.config) ]).process(fileInfo.content.asset.content).then(function (result) {
              result.warnings().forEach(function (warn) {
                  console.warn(warn.toString());
              });
              fileInfo.content.asset.content = result.css;
              setQueueAsset(conf, state, fileInfo, {},debugMode);
          })
        }else{
          setQueueAsset(conf, state, fileInfo, {},debugMode);
        }

      }
    }

    if(! _.eq(fileInfo.type, 'Asset::Media')){
      setQueueAsset(conf, state, fileInfo, {},debugMode);
    }

  });
}

/**
 * Сравнивает два файла, возваращает true если они разные
 */
function syncFile(file1, file2, encode, event, debugMode = false) {

  if (_.isEqual(event, 'unlink')) {
    fileMissing(file2).then(()=>{
      return;
    }).catch(()=>{
      fs.unlink(file2, function(err){
        if (debugMode) {
          console.log(`${file2} удален`)
        }
        if(err) return console.log(err);
      });
      return
    })
  }else{

  fs.readFile(file2,  (err2, data2) => {
    if (err2){
      cpFile.sync(file1, file2);
      if (debugMode) {
        console.log(`${file1} синхронизирован с ${file2}\n`)
      }
      return;
    }else{
      let stats1 = fs.statSync(file1)
      let stats2 = fs.statSync(file2)
      let fileSizeInBytes1 = _.toNumber(stats1["size"]);
      let fileSizeInBytes2 = _.toNumber(stats2["size"]);

      if (_.isEqual(fileSizeInBytes1, fileSizeInBytes2)) {

        fs.readFile(file1,  (err1, data1) => {
          if (err1) {
            console.log(`Невозможно прочитать файл ${file1}`)
            return;
          }else{
            let difa = jsdiff.diffChars(data2.toString(encode), data1.toString(encode));
            let difSize = _.size(difa);
            if (difSize > 1) {
              if (debugMode) {
                console.log(`${file1} синхронизирован с ${file2}\n`);
              }
              cpFile.sync(file1, file2);
            }else{
              if (debugMode) {
                console.log(`Нет причин для синхронизации`)
                console.log(`${file1} идентичен ${file2}\n`);
              }
            }
          }
        });
      }else{
        if (debugMode) {
          console.log(`${file1} синхронизирован с ${file2}\n`)
        }
        cpFile.sync(file1, file2);
      }
    }
  })
}
}

export function triggerFile(conf, state, event, _path) {
  return new Promise(function (resolve, reject) {
    _watch(conf, state, event, _path);
    resolve();
  });
}

export function closeWatcher(conf, state) {
  const options = conf.get('options');
  const eventEmitter = conf.get('eventEmitter');

  eventEmitter.emit('theme:stream:stop', {
    message: `Stop watcher`
  });
}
export function watcher(conf, state) {
  const paths = conf.get('paths');
  const options = conf.get('options');
  const eventEmitter = conf.get('eventEmitter');
  let debugMode = options.tools.debugMode || false;

  var _options = {
    ignored: /[\/\\]\./,
    ignoreInitial: true,
    followSymlinks: true,
    usePolling: true,
    interval: 200,
    binaryInterval: 300,
    alwaysStat: true,
    depth: 99,
    awaitWriteFinish: {
      stabilityThreshold: 100,
      pollInterval: 100
    },
    ignorePermissionErrors: true
  }

  var watcherInstance = chokidar.watch(paths.toWatch, _options).on('all', (event, _path) => {
    _watch(conf, state, event, _path, debugMode);
  });

  eventEmitter.on('theme:stream:stop', function (data) {
    watcherInstance.close();
  });

}

/**
 * @return
 * {
 *   name: 'test.js',
 *   type: 'Asset::Media',
 *   path: 'root/assets/js/test.js',
 *   synchronizePath: '' || 'root/media/test.js',
 *   encode: 'utf8',
 *   isBinary: false,
 *   data: 'console.log("My test file")'
 * }
 */
export function getFileInfo(_path, paths, event = 'add') {
  return new Promise(function (resolve, reject) {
  let fileInfo = {};
  fileInfo.path = path.normalize(_path);
  fileInfo.pathParse = path.parse(_path);
  fileInfo.encode = 'utf8';
  fileInfo.isBinary = false;
  fileInfo.data = '';

  let assetInfo = getAssetInfo(_path, paths)
  fileInfo = _.merge(fileInfo, assetInfo)
  if (event === 'unlink') {
    resolve(fileInfo);
  }else{
    if (isBinaryFile.sync(_path)) {
      fileInfo.encode = 'base64';
      fileInfo.isBinary = true;
    }
    fs.readFile(_path, (err, data) => {
      if (err) throw err;
      var _data = data.toString(fileInfo.encode)
      fileInfo.data = _data
      resolve(fileInfo);
    })
  }
  })
}

/**
 * @return
 * {
 *   name: 'test.js',
 *   type: 'Asset::Media',
 *   isMediaFile: true,
 *   synchronizePath: '' || 'root/media/test.js'
 * }
 */
export function getAssetInfo(_path, paths) {
  let assetInfo = {};
  assetInfo.synchronizePath = '';

  let pathMedia = paths.folders.media_root;
  let pathNormal = path.normalize(_path);
  let pathParse = path.parse(pathNormal);
  let _fileName = pathParse.base;
  let _dirPath = pathParse.dir;
  var _ext = pathParse.ext;
  let _folderParent = _.last(_dirPath.split(path.sep));
  let _assetType = _.findKey(paths.assets, function(o) {
    return _.includes(o.folder, _dirPath);
  })

  if (!_assetType) {
    _assetType = 'Asset::Media';
  }

  assetInfo.name = _fileName;
  assetInfo.type = _assetType;
  assetInfo.isMediaFile = false;;

  if (_assetType === 'Asset::Media') {
    if (pathMedia.indexOf(_dirPath) < 0 ) {
      assetInfo.synchronizePath = path.normalize(pathMedia + '/' + _fileName);
    }else{
      assetInfo.isMediaFile = true;
      assetInfo.synchronizePath = getAssetPath(paths, _assetType, _fileName, _ext, { isAssetsPath: true });
    }
  }

  return assetInfo;
}

/**
 * Получить объект в нужном для insalesApi виде
 * @param  {object} fileInfo информация о файле
 * {
 *   name: 'test.js',
 *   type: 'Asset::Media',
 *   synchronizePath: '' || 'root/media/test.js',
 *   encode: 'utf8',
 *   isBinary: false,
 *   data: 'console.log("My test file")'
 * }
 */
export function getContent(fileInfo, event = 'add') {
  let _content = {}
  if (_.eq(event, 'unlink')) {
    return _content;
  }

  _content.asset = {};
  _content.upload = {
    'name': fileInfo.name,
    'type': fileInfo.type
  }

  if (fileInfo.isBinary) {
    _content.asset['attachment'] = fileInfo.data;
    _content.upload['attachment'] = fileInfo.data;
  }else{
    let dataReplace = remove_etx(fileInfo.data, fileInfo.name);
    _content.asset['content'] = dataReplace
    _content.upload['content'] = dataReplace;
  }

  return _content;
}

function remove_etx(str, name) {

  if ((str===null) || (str===''))
       return '';
 else
   str = str.toString();
   let searchRegExp = /\x03/g;
   if (searchRegExp.test(str)) {
     console.log(log_warn(`Удалите спецсимвол \\u0003 из файла ${name}`));
     str = str.replace(/\x03/g, '');
   }
  return str;
}

export function uploadAssets(conf, state, param) {
  const options = conf.get('options');
  const paths = conf.get('paths');

  if (!param) {
    var param = {
      update: false
    }
  }else{
    if (!param.update) {
      param.update = false
    }
  }
  updateteAssets(conf, state).then(function () {
  const assets = conf.get('assets');
  var _folders = paths.foldersDefaults;
  var _folderSize = _.size(_folders);
  var _count = 0;
  _.forEach(_folders, function (folder) {
    fs.readdir(folder, function(err, list) {
      var _listSize = list.length - 1;
      if (err) {
        console.log(err);
      }
      if (list.length > 0) {
        _.forEach(list, function (_name, index) {
          var _fullPath = path.normalize(folder + _name);
          if ( _.isUndefined(assets[_fullPath]) || param.update ) {

            getFileInfo(_fullPath, paths, 'add').then(fileInfo => {
              let _content = getContent(fileInfo);
              fileInfo.content = _content;
              fileInfo.event = 'add';
              setQueueAsset(conf, state, fileInfo)
              if (index === _listSize) {
                _count++
              }
            })
          }else{
            if (index === _listSize) {
              _count++
            }
          }
        })
      }else{
        _count++
      }
    })
  })
  })
}
<|endoftext|>


<commit_before>'use strict';

var debug = require('debug')('pipes:fittings');
var path = require('path');
var util = require('util');
var assert = require('assert');

module.exports = function createFitting(pipes, fittingDef) {

  assert(fittingDef.name, util.format('name is required on fitting: %j', fittingDef));
  if (!pipes.config.userFittingsDirs) { return null; }

  for (var i = 0; i < pipes.config.userFittingsDirs.length; i++) {
    var dir = pipes.config.userFittingsDirs[i];

    var modulePath = path.resolve(dir, fittingDef.name);
    try {
      var module = require(modulePath);
      var fitting = module(fittingDef, pipes);
      debug('loaded user fitting %s from %s', fittingDef.name, dir);
      return fitting;
    } catch (err) {
      if (err.code !== 'MODULE_NOT_FOUND') { throw err; }
      var pathFromError = err.message.match(/'.*?'/)[0];
      var split = pathFromError.split(path.sep);
      if (split[split.length - 1] === fittingDef.name + "'") {
        debug('no user fitting %s in %s', fittingDef.name, dir);
      } else {
        throw err;
      }
    }
  }

  if (fittingDef.type !== 'user') {
    return null;
  }

  throw new Error('user fitting %s not found in %s', fittingDef, pipes.config.userFittingsDirs);
};
<commit_msg>fix bagpipies for jest<commit_after>'use strict';

var debug = require('debug')('pipes:fittings');
var path = require('path');
var util = require('util');
var assert = require('assert');

module.exports = function createFitting(pipes, fittingDef) {

  assert(fittingDef.name, util.format('name is required on fitting: %j', fittingDef));
  if (!pipes.config.userFittingsDirs) { return null; }

  for (var i = 0; i < pipes.config.userFittingsDirs.length; i++) {
    var dir = pipes.config.userFittingsDirs[i];

    var modulePath = path.resolve(dir, fittingDef.name);
    try {
      var module = require(modulePath);
      var fitting = module(fittingDef, pipes);
      debug('loaded user fitting %s from %s', fittingDef.name, dir);
      return fitting;
    } catch (err) {
      if (err.code !== 'MODULE_NOT_FOUND') { throw err; }
      var pathFromError = err.message.match(/'.*?'/)[0];
      var fittingIndex = err.message.indexOf(fittingDef.name);
      if (err.message[fittingIndex - 1] === path.sep && err.message[fittingDef.name.length] !== path.sep) {
        debug('no user fitting %s in %s', fittingDef.name, dir);
      } else {
        throw err;
      }
    }
  }

  if (fittingDef.type !== 'user') {
    return null;
  }

  throw new Error('user fitting %s not found in %s', fittingDef, pipes.config.userFittingsDirs);
};
<|endoftext|>


<commit_before>/*
 * grunt-version-file
 * https://github.com/cfogelberg/grunt-version-file
 *
 * Copyright (c) 2014 Christo Fogelberg
 * Licensed under the MIT license.
 *
 * Class SRP: Abstract prototype for generator plugins
 */
<commit_msg>GeneratorFactory impl<commit_after>/*
 * grunt-version-file
 * https://github.com/cfogelberg/grunt-version-file
 *
 * Copyright (c) 2014 Christo Fogelberg
 * Licensed under the MIT license.
 *
 * Class SRP: Abstract prototype for generator plugins
 */

var GeneratorFactory = function() {
};

var default_generator_init = function() {
};

var validate_generator_config = function(gc) {
  if(!(gc && gc.value && typeof(gc.value) === "function" && gc.label && typeof(gc.label) === "function")) {
    return false;
  }
  else {
    var fields = Object.keys(gc);
    return fields.length === 2 || (fields.length === 3 && fields.indexOf("init") !== -1);
  }
};

GeneratorFactory.prototype.create = function(generator_config) {
  if(validate_generator_config(generator_config)) {
    var gen = {};
    gen.value = generator_config.value;
    gen.label = generator_config.label;
    gen.init = generator_config.init ? generator_config.init : default_generator_init;
    return gen;
  }
  else {
    throw new Error("Error in configuration supplied to GeneratorFactory.create");
  }
};

module.exports = GeneratorFactory;
<|endoftext|>


<commit_before>setLabels = function () {
  // name Session.prototype.send
  var originalSend = MeteorX.Session.prototype.send;
  MeteorX.Session.prototype.send = function kadira_Session_send (msg) {
    return originalSend.call(this, msg);
  }

  // name mongodb.Connection.createDataHandler
  var mongodb = MongoInternals.NpmModule;
  var originalCreateDataHandler = mongodb.Connection.createDataHandler;
  mongodb.Connection.createDataHandler = function (self) {
    var originalHandler = originalCreateDataHandler.call(this, self);
    return function kadira_MongoDB_dataHandler (data) {
      return originalHandler.call(this, data);
    }
  }

  // name Multiplexer initial adds
  var originalSendAdds = MeteorX.Multiplexer.prototype._sendAdds;
  MeteorX.Multiplexer.prototype._sendAdds = function kadira_Multiplexer_sendAdds (handle) {
    return originalSendAdds.call(this, handle);
  }

  // name MongoConnection insert
  var originalMongoInsert = MeteorX.MongoConnection.prototype._insert;
  MeteorX.MongoConnection.prototype._insert = function kadira_MongoConnection_insert (coll, doc, cb) {
    return originalMongoInsert.call(this, coll, doc, cb);
  }

  // name MongoConnection update
  var originalMongoUpdate = MeteorX.MongoConnection.prototype._update;
  MeteorX.MongoConnection.prototype._update = function kadira_MongoConnection_update (coll, selector, mod, options, cb) {
    return originalMongoUpdate.call(this, coll, selector, mod, options, cb);
  }

  // name MongoConnection remove
  var originalMongoRemove = MeteorX.MongoConnection.prototype._remove;
  MeteorX.MongoConnection.prototype._remove = function kadira_MongoConnection_remove (coll, selector, cb) {
    return originalMongoRemove.call(this, coll, selector, cb);
  }

  // name Pubsub added
  var originalPubsubAdded = MeteorX.Session.prototype.sendAdded;
  MeteorX.Session.prototype.sendAdded = function kadira_Session_sendAdded (coll, id, fields) {
    return originalPubsubAdded.call(this, coll, id, fields);
  }

  // name Pubsub changed
  var originalPubsubChanged = MeteorX.Session.prototype.sendChanged;
  MeteorX.Session.prototype.sendChanged = function kadira_Session_sendChanged (coll, id, fields) {
    return originalPubsubChanged.call(this, coll, id, fields);
  }

  // name Pubsub removed
  var originalPubsubRemoved = MeteorX.Session.prototype.sendRemoved;
  MeteorX.Session.prototype.sendRemoved = function kadira_Session_sendRemoved (coll, id) {
    return originalPubsubRemoved.call(this, coll, id);
  }

  // name MongoCursor forEach
  var originalCursorForEach = MeteorX.MongoCursor.prototype.forEach;
  MeteorX.MongoCursor.prototype.forEach = function kadira_Cursor_forEach () {
    return originalCursorForEach.apply(this, arguments);
  }

  // name MongoCursor map
  var originalCursorMap = MeteorX.MongoCursor.prototype.map;
  MeteorX.MongoCursor.prototype.map = function kadira_Cursor_map () {
    return originalCursorMap.apply(this, arguments);
  }

  // name MongoCursor fetch
  var originalCursorFetch = MeteorX.MongoCursor.prototype.fetch;
  MeteorX.MongoCursor.prototype.fetch = function kadira_Cursor_fetch () {
    return originalCursorFetch.apply(this, arguments);
  }

  // name MongoCursor count
  var originalCursorCount = MeteorX.MongoCursor.prototype.count;
  MeteorX.MongoCursor.prototype.count = function kadira_Cursor_count () {
    return originalCursorCount.apply(this, arguments);
  }

  // name MongoCursor observeChanges
  var originalCursorObserveChanges = MeteorX.MongoCursor.prototype.observeChanges;
  MeteorX.MongoCursor.prototype.observeChanges = function kadira_Cursor_observeChanges () {
    return originalCursorObserveChanges.apply(this, arguments);
  }

  // name MongoCursor observe
  var originalCursorObserve = MeteorX.MongoCursor.prototype.observe;
  MeteorX.MongoCursor.prototype.observe = function kadira_Cursor_observe () {
    return originalCursorObserve.apply(this, arguments);
  }

  // name MongoCursor rewind
  var originalCursorRewind = MeteorX.MongoCursor.prototype.rewind;
  MeteorX.MongoCursor.prototype.rewind = function kadira_Cursor_rewind () {
    return originalCursorRewind.apply(this, arguments);
  }

  // name CrossBar listen
  var originalCrossbarListen = DDPServer._Crossbar.prototype.listen;
  DDPServer._Crossbar.prototype.listen = function kadira_Crossbar_listen (trigger, callback) {
    return originalCrossbarListen.call(this, trigger, callback);
  }

  // name CrossBar fire
  var originalCrossbarFire = DDPServer._Crossbar.prototype.fire;
  DDPServer._Crossbar.prototype.fire = function kadira_Crossbar_fire (notification) {
    return originalCrossbarFire.call(this, notification);
  }
}
<commit_msg>Fix potential crash issue due to CPU labeling.<commit_after>setLabels = function () {
  // name Session.prototype.send
  var originalSend = MeteorX.Session.prototype.send;
  MeteorX.Session.prototype.send = function kadira_Session_send (msg) {
    return originalSend.call(this, msg);
  }

  // name mongodb.Connection.createDataHandler
  var mongodb = MongoInternals.NpmModule;
  // Sometimes, createDataHandler is not there. In that case, we don't need
  // to crash the app.
  if (mongodb.Connection.createDataHandler) {
    var originalCreateDataHandler = mongodb.Connection.createDataHandler;
    mongodb.Connection.createDataHandler = function (self) {
      var originalHandler = originalCreateDataHandler.call(this, self);
      return function kadira_MongoDB_dataHandler (data) {
        return originalHandler.call(this, data);
      }
    }
  }

  // name Multiplexer initial adds
  var originalSendAdds = MeteorX.Multiplexer.prototype._sendAdds;
  MeteorX.Multiplexer.prototype._sendAdds = function kadira_Multiplexer_sendAdds (handle) {
    return originalSendAdds.call(this, handle);
  }

  // name MongoConnection insert
  var originalMongoInsert = MeteorX.MongoConnection.prototype._insert;
  MeteorX.MongoConnection.prototype._insert = function kadira_MongoConnection_insert (coll, doc, cb) {
    return originalMongoInsert.call(this, coll, doc, cb);
  }

  // name MongoConnection update
  var originalMongoUpdate = MeteorX.MongoConnection.prototype._update;
  MeteorX.MongoConnection.prototype._update = function kadira_MongoConnection_update (coll, selector, mod, options, cb) {
    return originalMongoUpdate.call(this, coll, selector, mod, options, cb);
  }

  // name MongoConnection remove
  var originalMongoRemove = MeteorX.MongoConnection.prototype._remove;
  MeteorX.MongoConnection.prototype._remove = function kadira_MongoConnection_remove (coll, selector, cb) {
    return originalMongoRemove.call(this, coll, selector, cb);
  }

  // name Pubsub added
  var originalPubsubAdded = MeteorX.Session.prototype.sendAdded;
  MeteorX.Session.prototype.sendAdded = function kadira_Session_sendAdded (coll, id, fields) {
    return originalPubsubAdded.call(this, coll, id, fields);
  }

  // name Pubsub changed
  var originalPubsubChanged = MeteorX.Session.prototype.sendChanged;
  MeteorX.Session.prototype.sendChanged = function kadira_Session_sendChanged (coll, id, fields) {
    return originalPubsubChanged.call(this, coll, id, fields);
  }

  // name Pubsub removed
  var originalPubsubRemoved = MeteorX.Session.prototype.sendRemoved;
  MeteorX.Session.prototype.sendRemoved = function kadira_Session_sendRemoved (coll, id) {
    return originalPubsubRemoved.call(this, coll, id);
  }

  // name MongoCursor forEach
  var originalCursorForEach = MeteorX.MongoCursor.prototype.forEach;
  MeteorX.MongoCursor.prototype.forEach = function kadira_Cursor_forEach () {
    return originalCursorForEach.apply(this, arguments);
  }

  // name MongoCursor map
  var originalCursorMap = MeteorX.MongoCursor.prototype.map;
  MeteorX.MongoCursor.prototype.map = function kadira_Cursor_map () {
    return originalCursorMap.apply(this, arguments);
  }

  // name MongoCursor fetch
  var originalCursorFetch = MeteorX.MongoCursor.prototype.fetch;
  MeteorX.MongoCursor.prototype.fetch = function kadira_Cursor_fetch () {
    return originalCursorFetch.apply(this, arguments);
  }

  // name MongoCursor count
  var originalCursorCount = MeteorX.MongoCursor.prototype.count;
  MeteorX.MongoCursor.prototype.count = function kadira_Cursor_count () {
    return originalCursorCount.apply(this, arguments);
  }

  // name MongoCursor observeChanges
  var originalCursorObserveChanges = MeteorX.MongoCursor.prototype.observeChanges;
  MeteorX.MongoCursor.prototype.observeChanges = function kadira_Cursor_observeChanges () {
    return originalCursorObserveChanges.apply(this, arguments);
  }

  // name MongoCursor observe
  var originalCursorObserve = MeteorX.MongoCursor.prototype.observe;
  MeteorX.MongoCursor.prototype.observe = function kadira_Cursor_observe () {
    return originalCursorObserve.apply(this, arguments);
  }

  // name MongoCursor rewind
  var originalCursorRewind = MeteorX.MongoCursor.prototype.rewind;
  MeteorX.MongoCursor.prototype.rewind = function kadira_Cursor_rewind () {
    return originalCursorRewind.apply(this, arguments);
  }

  // name CrossBar listen
  var originalCrossbarListen = DDPServer._Crossbar.prototype.listen;
  DDPServer._Crossbar.prototype.listen = function kadira_Crossbar_listen (trigger, callback) {
    return originalCrossbarListen.call(this, trigger, callback);
  }

  // name CrossBar fire
  var originalCrossbarFire = DDPServer._Crossbar.prototype.fire;
  DDPServer._Crossbar.prototype.fire = function kadira_Crossbar_fire (notification) {
    return originalCrossbarFire.call(this, notification);
  }
}
<|endoftext|>


<commit_before>require('core-upgrade');
var HTML5 = require('html5');
var sys = require('sys');
var assert = require('assert');
var DOM = require('dom'); // Use env-js dom

HTML5.TreeBuilder = b = function TreeBuilder() {
	this.open_elements = [];
	this.document = new DOM.Document(DOM.DOMImplementation);
	this.activeFormattingElements = [];
}

b.prototype.reset = function() {

}

b.prototype.createElement = function (name, attributes, namespace) {
	var el = this.document.createElement(name)
	if(attributes) for(var i = 0; i < attributes.length; i++) {
		el.setAttribute(attributes[i].nodeName, attributes[i].nodeValue);
	}
	return el;
}

b.prototype.insert_element = function(name, attributes, namespace) {
	HTML5.debug('treebuilder.insert_element', name)
	if(this.insert_from_table) {
		return this.insert_element_from_table(name, attributes, namespace)
	} else {
		return this.insert_element_normal(name, attributes, namespace)
	}
}

b.prototype.insert_element_normal = function(name, attributes, namespace) {
	HTML5.debug('treebuilder.insert_element_normal', name)
	var element = this.createElement(name, attributes, namespace);
	this.open_elements.last().appendChild(element);
	this.open_elements.push(element);
	return element;
}

b.prototype.insert_element_from_table = function(name, attributes, namespace) {
	HTML5.debug('treebuilder.insert_element_from_table', name)
	var element = this.document.createElement(name, attributes, namespace)
	if(HTML5.TABLE_INSERT_MODE_ELEMENTS.indexOf(this.open_elements.last().tagName) != -1) {
		// We should be in the InTable mode. This means we want to do
		// special magic element rearranging
		var t = this.getTableMisnestedNodePosition()
		if(!t.insertBefore) {
			t.parent.appendChild(element)
		} else {
			t.parent.insertBefore(element, t.insertBefore)
		}
		this.open_elements.push(element)
	} else {
		return this.insert_element_normal(name, attributes, namespace);
	}
	return element;
}

b.prototype.insert_comment = function(data, parent) {
	var c = this.document.createComment(data);
	HTML5.debug('treebuilder', 'open elements at insert_comment are: ' + require('sys').inspect(this.open_elements.map(function(e) { return e.nodeName })));
	if(!parent) parent = this.open_elements.last();
	parent.appendChild(c);
}

b.prototype.insert_doctype = function (name, publicId, systemId) {
	// var dt = this.document.implementation.createDocumentType(name, publicId, systemId);
	var doctype = new DOM.DocumentType();
        doctype.nodeName = name?name:'';
        doctype.publicId = publicId?publicId:null;
        doctype.systemId = systemId?systemId:null;
	this.document.appendChild(doctype);
}

b.prototype.insert_text = function(data, parent) {
	HTML5.debug('treebuilder.insert_text', data)
	if(!parent) parent = this.open_elements.last();
	if(!this.insert_from_table || HTML5.TABLE_INSERT_MODE_ELEMENTS.indexOf(this.open_elements.last().tagName) == -1) {
		if(parent.lastChild && parent.lastChild.nodeType == DOM.Node.TEXT_NODE) {
			parent.lastChild.appendData(data);
		} else {
			var tn = this.document.createTextNode(data);
			parent.appendChild(tn);
		}
	} else {
		HTML5.debug('treebuilder.insert_text', 'voodoo invoked')
		// We should be in the inTable phase. This means we want to do special
		// magic element rearranging.
		var t = this.getTableMisnestedNodePosition();
		HTML5.debug('treebuilder.insert_text', t.insertBefore)
		insertText(t.parent, data, t.insertBefore)
	}
}

function insertText(node, data, before) {
	var t = node.ownerDocument.createTextNode(data)
	if(before) {
		node.insertBefore(t, before)
	} else {
		node.appendChild(t)
	}
}

b.prototype.getTableMisnestedNodePosition = function() {
	// The foster parent element is the one which comes before the most
	// recently opened table element
	// XXX - this is really inelegant
	var lastTable, fosterParent, insertBefore

	for(var i = this.open_elements.length - 1; i >= 0; i--) {
		var element = this.open_elements[i]
		if(element.tagName == 'table') {
			lastTable = element
			break
		}
	}

	if(lastTable) {
		// XXX - we should check that the parent really is a node here
		if(lastTable.parentNode) {
			fosterParent = lastTable.parentNode
			insertBefore = lastTable
		} else {
			fosterParent = this.open_elements[this.open_elements.indexOf(lastTable) - 1]
		}
	} else {
		fosterParent = this.open_elements[0]
	}

	return {parent: fosterParent, insertBefore: insertBefore}
}

b.prototype.elementInScope = function(name, tableVariant) {
	HTML5.debug('treebuilder.elementInScope', name, tableVariant)
	if(this.open_elements.length == 0) return false
	if(this.open_elements.last().tagName == name) return true
	for(var i = this.open_elements.length - 1; i >= 0; i--) {
		if(this.open_elements[i].tagName == name) return true
		else if(this.open_elements[i].tagName == 'table') return false
		else if(!tableVariant && HTML5.SCOPING_ELEMENTS.indexOf(this.open_elements[i].tagName) != -1) return false
		else if(this.open_elements[i].tagName == 'html') return false;
	}
	return false;
}

b.prototype.generateImpliedEndTags = function (exclude) {
	//HTML5.debug('implied end tags with ' + sys.inspect(this.open_elements.map(function(el) { return el.tagName })));
	var name = this.open_elements.last().tagName;
	if(['dd', 'dt', 'li', 'p', 'td', 'th', 'tr'].indexOf(name) != -1 && name != exclude) {
		var p  = this.open_elements.pop();
		this.generateImpliedEndTags(exclude);
	}
}

b.prototype.reconstructActiveFormattingElements = function() {
	HTML5.debug('treebuilder.reconstructActiveFormattingElements', 'before', HTML5.dumpTagStack(this.activeFormattingElements))
	// Within this algorithm the order of steps decribed in the specification
	// is not quite the same as the order of steps in the code. It should still
	// do the same though.

	// Step 1: stop if there's nothing to do
	if(this.activeFormattingElements.length == 0) return;

	// Step 2 and 3: start with the last element
	var i = this.activeFormattingElements.length - 1;
	var entry = this.activeFormattingElements[i];
	if(entry == HTML5.Marker || this.open_elements.indexOf(entry) != -1) return;

	while(entry != HTML5.Marker && this.open_elements.indexOf(entry) == -1) {
		i -= 1;
		entry = this.activeFormattingElements[i];
		if(!entry) break;
	}

	while(true) {
		i += 1;
		var clone = this.activeFormattingElements[i].cloneNode();
		HTML5.debug('treebuilder.reconstructActiveFormattingElements', 'cloneNode', clone.tagName)

		var element = this.insert_element(clone.tagName, clone.attributes);

		this.activeFormattingElements[i] = element;

		if(element == this.activeFormattingElements.last()) break;
	}

	HTML5.debug('treebuilder.reconstructActiveFormattingElements', 'open tags are ' + HTML5.dumpTagStack(this.open_elements));
}

b.prototype.elementInActiveFormattingElements = function(name) {
	var els = this.activeFormattingElements;
	for(var i = els.length - 1; i >= 0; i--) {
		if(els[i] == HTML5.Marker) break;
		if(els[i].tagName == name) return els[i];
	}
	return false;
}

b.prototype.reparentChildren = function(o, n) {
	while(o.childNodes.length > 0) {
		var el = o.removeChild(o.childNodes[0]);
		n.appendChild(el);
	}
}

b.prototype.clearActiveFormattingElements = function() {
	HTML5.debug('treebuilder.clearActiveFormattingElements', 'before', HTML5.dumpTagStack(this.activeFormattingElements))
	while(!(this.activeFormattingElements.length == 0 || this.activeFormattingElements.pop() == HTML5.Marker));
	HTML5.debug('treebuilder.clearActiveFormattingElements', 'after', HTML5.dumpTagStack(this.activeFormattingElements))
}

b.prototype.getFragment = function() {
	// assert.ok(this.parser.inner_html)
	var fragment = this.document.createDocumentFragment()
	this.reparentChildren(this.open_elements[0], fragment)
	return fragment
}
<commit_msg>- remove a debug<commit_after>require('core-upgrade');
var HTML5 = require('html5');
var sys = require('sys');
var assert = require('assert');
var DOM = require('dom'); // Use env-js dom

HTML5.TreeBuilder = b = function TreeBuilder() {
	this.open_elements = [];
	this.document = new DOM.Document(DOM.DOMImplementation);
	this.activeFormattingElements = [];
}

b.prototype.reset = function() {

}

b.prototype.createElement = function (name, attributes, namespace) {
	var el = this.document.createElement(name)
	if(attributes) for(var i = 0; i < attributes.length; i++) {
		el.setAttribute(attributes[i].nodeName, attributes[i].nodeValue);
	}
	return el;
}

b.prototype.insert_element = function(name, attributes, namespace) {
	HTML5.debug('treebuilder.insert_element', name)
	if(this.insert_from_table) {
		return this.insert_element_from_table(name, attributes, namespace)
	} else {
		return this.insert_element_normal(name, attributes, namespace)
	}
}

b.prototype.insert_element_normal = function(name, attributes, namespace) {
	HTML5.debug('treebuilder.insert_element_normal', name)
	var element = this.createElement(name, attributes, namespace);
	this.open_elements.last().appendChild(element);
	this.open_elements.push(element);
	return element;
}

b.prototype.insert_element_from_table = function(name, attributes, namespace) {
	HTML5.debug('treebuilder.insert_element_from_table', name)
	var element = this.document.createElement(name, attributes, namespace)
	if(HTML5.TABLE_INSERT_MODE_ELEMENTS.indexOf(this.open_elements.last().tagName) != -1) {
		// We should be in the InTable mode. This means we want to do
		// special magic element rearranging
		var t = this.getTableMisnestedNodePosition()
		if(!t.insertBefore) {
			t.parent.appendChild(element)
		} else {
			t.parent.insertBefore(element, t.insertBefore)
		}
		this.open_elements.push(element)
	} else {
		return this.insert_element_normal(name, attributes, namespace);
	}
	return element;
}

b.prototype.insert_comment = function(data, parent) {
	var c = this.document.createComment(data);
	HTML5.debug('treebuilder', 'open elements at insert_comment are: ' + require('sys').inspect(this.open_elements.map(function(e) { return e.nodeName })));
	if(!parent) parent = this.open_elements.last();
	parent.appendChild(c);
}

b.prototype.insert_doctype = function (name, publicId, systemId) {
	// var dt = this.document.implementation.createDocumentType(name, publicId, systemId);
	var doctype = new DOM.DocumentType();
        doctype.nodeName = name?name:'';
        doctype.publicId = publicId?publicId:null;
        doctype.systemId = systemId?systemId:null;
	this.document.appendChild(doctype);
}

b.prototype.insert_text = function(data, parent) {
	HTML5.debug('treebuilder.insert_text', data)
	if(!parent) parent = this.open_elements.last();
	if(!this.insert_from_table || HTML5.TABLE_INSERT_MODE_ELEMENTS.indexOf(this.open_elements.last().tagName) == -1) {
		if(parent.lastChild && parent.lastChild.nodeType == DOM.Node.TEXT_NODE) {
			parent.lastChild.appendData(data);
		} else {
			var tn = this.document.createTextNode(data);
			parent.appendChild(tn);
		}
	} else {
		HTML5.debug('treebuilder.insert_text', 'voodoo invoked')
		// We should be in the inTable phase. This means we want to do special
		// magic element rearranging.
		var t = this.getTableMisnestedNodePosition();
		insertText(t.parent, data, t.insertBefore)
	}
}

function insertText(node, data, before) {
	var t = node.ownerDocument.createTextNode(data)
	if(before) {
		node.insertBefore(t, before)
	} else {
		node.appendChild(t)
	}
}

b.prototype.getTableMisnestedNodePosition = function() {
	// The foster parent element is the one which comes before the most
	// recently opened table element
	// XXX - this is really inelegant
	var lastTable, fosterParent, insertBefore

	for(var i = this.open_elements.length - 1; i >= 0; i--) {
		var element = this.open_elements[i]
		if(element.tagName == 'table') {
			lastTable = element
			break
		}
	}

	if(lastTable) {
		// XXX - we should check that the parent really is a node here
		if(lastTable.parentNode) {
			fosterParent = lastTable.parentNode
			insertBefore = lastTable
		} else {
			fosterParent = this.open_elements[this.open_elements.indexOf(lastTable) - 1]
		}
	} else {
		fosterParent = this.open_elements[0]
	}

	return {parent: fosterParent, insertBefore: insertBefore}
}

b.prototype.elementInScope = function(name, tableVariant) {
	HTML5.debug('treebuilder.elementInScope', name, tableVariant)
	if(this.open_elements.length == 0) return false
	if(this.open_elements.last().tagName == name) return true
	for(var i = this.open_elements.length - 1; i >= 0; i--) {
		if(this.open_elements[i].tagName == name) return true
		else if(this.open_elements[i].tagName == 'table') return false
		else if(!tableVariant && HTML5.SCOPING_ELEMENTS.indexOf(this.open_elements[i].tagName) != -1) return false
		else if(this.open_elements[i].tagName == 'html') return false;
	}
	return false;
}

b.prototype.generateImpliedEndTags = function (exclude) {
	//HTML5.debug('implied end tags with ' + sys.inspect(this.open_elements.map(function(el) { return el.tagName })));
	var name = this.open_elements.last().tagName;
	if(['dd', 'dt', 'li', 'p', 'td', 'th', 'tr'].indexOf(name) != -1 && name != exclude) {
		var p  = this.open_elements.pop();
		this.generateImpliedEndTags(exclude);
	}
}

b.prototype.reconstructActiveFormattingElements = function() {
	HTML5.debug('treebuilder.reconstructActiveFormattingElements', 'before', HTML5.dumpTagStack(this.activeFormattingElements))
	// Within this algorithm the order of steps decribed in the specification
	// is not quite the same as the order of steps in the code. It should still
	// do the same though.

	// Step 1: stop if there's nothing to do
	if(this.activeFormattingElements.length == 0) return;

	// Step 2 and 3: start with the last element
	var i = this.activeFormattingElements.length - 1;
	var entry = this.activeFormattingElements[i];
	if(entry == HTML5.Marker || this.open_elements.indexOf(entry) != -1) return;

	while(entry != HTML5.Marker && this.open_elements.indexOf(entry) == -1) {
		i -= 1;
		entry = this.activeFormattingElements[i];
		if(!entry) break;
	}

	while(true) {
		i += 1;
		var clone = this.activeFormattingElements[i].cloneNode();
		HTML5.debug('treebuilder.reconstructActiveFormattingElements', 'cloneNode', clone.tagName)

		var element = this.insert_element(clone.tagName, clone.attributes);

		this.activeFormattingElements[i] = element;

		if(element == this.activeFormattingElements.last()) break;
	}

	HTML5.debug('treebuilder.reconstructActiveFormattingElements', 'open tags are ' + HTML5.dumpTagStack(this.open_elements));
}

b.prototype.elementInActiveFormattingElements = function(name) {
	var els = this.activeFormattingElements;
	for(var i = els.length - 1; i >= 0; i--) {
		if(els[i] == HTML5.Marker) break;
		if(els[i].tagName == name) return els[i];
	}
	return false;
}

b.prototype.reparentChildren = function(o, n) {
	while(o.childNodes.length > 0) {
		var el = o.removeChild(o.childNodes[0]);
		n.appendChild(el);
	}
}

b.prototype.clearActiveFormattingElements = function() {
	HTML5.debug('treebuilder.clearActiveFormattingElements', 'before', HTML5.dumpTagStack(this.activeFormattingElements))
	while(!(this.activeFormattingElements.length == 0 || this.activeFormattingElements.pop() == HTML5.Marker));
	HTML5.debug('treebuilder.clearActiveFormattingElements', 'after', HTML5.dumpTagStack(this.activeFormattingElements))
}

b.prototype.getFragment = function() {
	// assert.ok(this.parser.inner_html)
	var fragment = this.document.createDocumentFragment()
	this.reparentChildren(this.open_elements[0], fragment)
	return fragment
}
<|endoftext|>