<commit_before>/*!
 * jQuery Stepy - A Wizard Plugin
 *
 * The MIT License
 *
 * @author:  Washington Botelho
 * @doc:     wbotelhos.com/stepy
 * @version: 1.1.0
 *
 */

;(function($) {
  'use strict';

  var methods = {
    init: function(settings) {
      return this.each(function() {
        methods.destroy.call(this);

        this.opt = $.extend({}, $.fn.stepy.defaults, settings);

        var self = $(this);

        methods._generateId.call(this);

        // Remove Validator...
        if (this.opt.validate) {
          jQuery.validator.setDefaults({ ignore: this.opt.ignore });

          self.append($('<div />', { 'class': 'stepy-errors' }));
        }

        if (this.opt.header) {
          this.header = methods._header.call(this);
        }

        this.steps = self.children('fieldset');

        var that = this;

        this.steps.each(function(index) {
          $(this).addClass('stepy-step');

          if (that.opt.header) {
            methods._createHead.call(that, this, index);
          }

          methods._createButtons.call(that, this, index);
          methods._stateButton.call(that, index, that.steps);
        });

        methods._bindFinishButton.call(this);

        if (this.opt.header) {
          this.heads = this.header.children('li');

          this.heads.first().addClass('stepy-active');

          if (this.opt.titleClick) {
            this.heads.on('click', function() {
              var
                words   = that.heads.filter('.stepy-active').attr('id').split('-'), // TODO: try keep the number in an attribute.
                current = parseInt(words[words.length - 1], 10),
                clicked = $(this).index();

              if (clicked > current) {
                if (that.opt.next && !methods._execute.call(self, that.opt.next, clicked)) {
                  return false;
                }
              } else if (clicked < current) {
                if (that.opt.back && !methods._execute.call(self, that.opt.back, clicked)) {
                  return false;
                }
              }

              if (clicked != current) {
                methods.step.call(that, clicked);
              }
            });
          } else {
            that.heads.css('cursor', 'default');
          }
        }

        if (that.opt.enter) {
          methods._bindEnter.call(that);
        }

        that.steps.first().find(':input:visible:enabled').first().select().focus();

        methods._setState.call(this, { settings: this.opt, index: 0, stepy: true });
      });
    },

    _bindBackButton: function(step) {
      var button = $(step).find(this.opt.backButton);

      if (!button.length) {
        return;
      }

      button.on('click.stepy', function(e) {
        e.preventDefault();

        var index = $(this).data('index') - 1;

        if (!this.opt.back || methods._execute.call(this, this.opt.back, index, this.steps.length)) {
          methods.step.call(this, index);
        }
      }.bind(this));
    },

    _bindEnter: function() {
      var that = this;

      this.steps.delegate(':text, :password', 'keypress', function(evt) {
        var key = (evt.keyCode ? evt.keyCode : evt.which);

        if (key === 13) {
          evt.preventDefault();

          var
            step    = $(this).closest('fieldset'),
            hasNext = step.next('fieldset').length;

          if (hasNext) {
            step.find('.stepy-next').trigger('click');
          } else if (that.finishButton) {
            that.finishButton.trigger('click');
          }
        }
      });
    },

    _bindFinishButton: function() {
      this.finishButton = $(this).find('.stepy-finish');

      if (!this.finishButton.length) {
        return $.error('submit button ".stepy-finish" missing.');
      }

      this.finishButton.hide().on('click.stepy', methods._onFinishButton.bind(this));
    },

    _bindNextButton: function(step) {
      var button = $(step).find(this.opt.nextButton);

      if (!button.length) {
        return;
      }

      button.on('click.stepy', function(e) {
        e.preventDefault();

        var index = $(this).data('index') + 1;

        if (!this.opt.next || methods._execute.call(this, this.opt.next, index, this.steps.length)) {
          methods.step.call(this, index);
        }
      }.bind(this));
    },

    _createButtons: function(step, index) {
      if (index === 0) {
        if (this.steps.length > 1) {
          methods._bindNextButton.call(this, step);
        }
      } else {
        $(step).hide();

        methods._bindBackButton.call(this, step);

        if (index < this.steps.length - 1) {
          methods._bindNextButton.call(this, step);
        }
      }
    },

    _createHead: function(step, index) {
      var
        step = $(step).attr('id', this.id + '-step-' + index),
        head = methods._head.call(this, index);

      head.append(methods._title.call(this, step));

      if (this.opt.description) {
        head.append(methods._description.call(this, step));
      }

      this.header.append(head);
    },

    _description: function(step) {
      var legend = step.children('legend');

      if (!this.opt.legend) {
        legend.hide();
      }

      if (legend.length) {
        return $('<span />', { html: legend.html() });
      }

      methods._error.call(this, '<legend /> element missing!');
    },

    _error: function(message) {
      $(this).html(message);

      $.error(message);
    },

    _execute: function(callback, index, totalSteps) {
      if (callback === undefined) {
        return true;
      }

      var isValid = callback.call(this, index, totalSteps);

      return isValid || isValid === undefined;
    },

    _generateId: function() {
      if (this.id === undefined || this.id === '') {
        $(this).attr('id', 'stepy-' + Math.random().toString().substring(2));
      }
    },

    _head: function(index) {
      return $('<li />', { id: this.id + '-head-' + index });
    },

    _header: function() {
      var header = $('<ul />', { id: this.id + '-header', 'class': 'stepy-header' });

      if (this.opt.titleTarget) {
        header.appendTo(this.opt.titleTarget);
      } else {
        header.insertBefore(this);
      }

      return header;
    },

    _onFinishButton: function(evt) {
      var onSubmit = undefined;

      if (this.tagName === 'FORM') {
        onSubmit = this.getAttribute('onsubmit');

        this.setAttribute('onsubmit', 'return false;');
      }

      if (!methods._execute.call(this, this.opt.finish, this.steps.length - 1)) {
        evt.preventDefault();
      } else if (this.tagName === 'FORM') {
        if (onSubmit) {
          this.setAttribute('onsubmit', onSubmit);
        } else {
          this.removeAttribute('onsubmit');
        }

        var isSubmit = this.finishButton.attr('type') === 'submit';

        if (isSubmit && (!this.opt.validate || methods.validate.call(this, this.steps.length - 1))) {
          this.submit();
        }
      }
    },

    _setState: function(data) {
      var self = $(this);

      self.data($.extend({}, self.data(), data));
    },

    _stateButton: function(index, steps) {
      var
        self = $(this),
        step = steps.eq(index);

      if (index === 0) {
        step.find('.stepy-back').hide();
        step.find('.stepy-next').show();
        self.find('.stepy-finish').hide();
      } else if (index === steps.length - 1) {
        step.find('.stepy-back').show();
        step.find('.stepy-next').hide();
        self.find('.stepy-finish').show();
      } else {
        step.find('.stepy-back').show();
        step.find('.stepy-next').show();
        self.find('.stepy-finish').hide();
      }
    },

    _title: function(step) {
      return $('<div />', { html: step.attr('title') || '--' });
    },

    _transition: function(steps, max) {
      if (this.opt.transition === 'fade') {
        steps.fadeOut(this.opt.duration, function() {
          if (--steps.length > 0) {
            return;
          }

          steps.eq(max).fadeIn(this.opt.duration);
        });
      } else if (this.opt.transition === 'slide') {
        steps.slideUp(this.opt.duration, function() {
          if (--steps.length > 0) {
            return;
          }

          steps.eq(max).slideDown(this.opt.duration);
        });
      }
    },

    destroy: function() {
      return $(this).each(function() {
        var self = $(this);

        if (self.data('stepy')) {
          var steps = self.data('stepy', false).children('fieldset').css('display', '');

          self.children('.stepy-errors').remove();
        }
      });
    },

    step: function(index) {
      var
        max   = index,
        self  = $(this),
        steps = self.children('fieldset');

      if (index > steps.length - 1) {
        index = steps.length - 1;
      }

      if (this.opt.validate) {
        var isValid = true;

        for (var i = 0; i < index; i++) {
          isValid &= methods.validate.call(this, i);

          if (this.opt.block && !isValid) {
            max = i;
            break;
          }
        }
      }

      if (this.opt.transition) {
        methods._transition.call(this, steps, max);
      } else {
        steps.hide(this.opt.duration).eq(max).show(this.opt.duration);
      }

      if (this.opt.header) {
        this.heads.removeClass('stepy-active').eq(max).addClass('stepy-active');
      }

      if (this.tagName === 'FORM') {
        var fields = steps.eq(max);

        if (max === index) {
          fields = fields.find(':input:enabled:visible');
        } else {
          fields = fields.find('.error').trigger('select').trigger('focus');
        }

        fields.first().trigger('select').trigger('focus');
      }

      if (this.opt.select) {
        this.opt.select.call(this, max + 1, steps.length);
      }

      methods._stateButton.call(this, max, steps);
      methods._setState.call(this, { index: max });

      return self;
    },

    validate: function(index) {
      var self = $(this);

      if (!this.tagName === 'FORM') {
        return true;
      }

      var
        that      = this,
        step      = self.children('fieldset').eq(index),
        isValid   = true,
        $title    = $('#' + this.id + '-header').children().eq(index),
        $validate = self.validate();

      $(step.find(':input:enabled').get().reverse()).each(function() {
        var fieldIsValid = $validate.element($(this));

        if (fieldIsValid === undefined) {
          fieldIsValid = true;
        }

        isValid &= fieldIsValid;

        if (isValid) {
          if (that.opt.errorImage) {
            $title.removeClass('stepy-error');
          }
        } else {
          if (that.opt.errorImage) {
            $title.addClass('stepy-error');
          }

          $validate.focusInvalid();
        }
      });

      return isValid;
    }
  };

  $.fn.stepy = function(method) {
    if (methods[method]) {
      return methods[method].apply($(this)[0], Array.prototype.slice.call(arguments, 1));
    } else if (typeof method === 'object' || !method) {
      return methods.init.apply(this, arguments);
    } else {
      $.error('Method ' + method + ' does not exist!');
    }
  };

  $.fn.stepy.defaults = {
    back:          undefined,
    backButton:    '.stepy-back',
    block:         false,
    description:   true,
    duration:      0,
    enter:         true,
    errorImage:    false,
    finish:        undefined,
    finishButton:  undefined,
    globalButtons: false,
    header:        true,
    ignore:        '',
    legend:        true,
    next:          undefined,
    nextButton:    '.stepy-next',
    select:        undefined,
    titleClick:    false,
    titleTarget:   undefined,
    transition:    undefined,
    validate:      false
  };

})(jQuery);
<commit_msg>extract method<commit_after>/*!
 * jQuery Stepy - A Wizard Plugin
 *
 * The MIT License
 *
 * @author:  Washington Botelho
 * @doc:     wbotelhos.com/stepy
 * @version: 1.1.0
 *
 */

;(function($) {
  'use strict';

  var methods = {
    init: function(settings) {
      return this.each(function() {
        methods.destroy.call(this);

        this.opt = $.extend({}, $.fn.stepy.defaults, settings);

        var self = $(this);

        methods._generateId.call(this);

        // Remove Validator...
        if (this.opt.validate) {
          jQuery.validator.setDefaults({ ignore: this.opt.ignore });

          self.append($('<div />', { 'class': 'stepy-errors' }));
        }

        if (this.opt.header) {
          this.header = methods._header.call(this);
        }

        this.steps = self.children('fieldset');

        var that = this;

        this.steps.each(function(index) {
          $(this).addClass('stepy-step');

          if (that.opt.header) {
            methods._createHead.call(that, this, index);
          }

          methods._createButtons.call(that, this, index);
          methods._stateButton.call(that, index, that.steps);
        });

        methods._bindFinishButton.call(this);

        if (this.opt.header) {
          methods._bindHeader.call(this);
        }

        if (that.opt.enter) {
          methods._bindEnter.call(that);
        }

        that.steps.first().find(':input:visible:enabled').first().select().focus();

        methods._setState.call(this, { settings: this.opt, index: 0, stepy: true });
      });
    },

    _bindBackButton: function(step) {
      var button = $(step).find(this.opt.backButton);

      if (!button.length) {
        return;
      }

      button.on('click.stepy', function(e) {
        e.preventDefault();

        var index = $(this).data('index') - 1;

        if (!this.opt.back || methods._execute.call(this, this.opt.back, index, this.steps.length)) {
          methods.step.call(this, index);
        }
      }.bind(this));
    },

    _bindEnter: function() {
      var that = this;

      this.steps.delegate(':text, :password', 'keypress', function(evt) {
        var key = (evt.keyCode ? evt.keyCode : evt.which);

        if (key === 13) {
          evt.preventDefault();

          var
            step    = $(this).closest('fieldset'),
            hasNext = step.next('fieldset').length;

          if (hasNext) {
            step.find('.stepy-next').trigger('click');
          } else if (that.finishButton) {
            that.finishButton.trigger('click');
          }
        }
      });
    },

    _bindFinishButton: function() {
      this.finishButton = $(this).find('.stepy-finish');

      if (!this.finishButton.length) {
        return $.error('submit button ".stepy-finish" missing.');
      }

      this.finishButton.hide().on('click.stepy', methods._onFinishButton.bind(this));
    },

    _bindHeader: function() {
      this.heads = this.header.children('li');

      this.heads.first().addClass('stepy-active');

      if (this.opt.titleClick) {
        this.heads.on('click', methods._bindHeaderHandler.bind(this));
      } else {
        this.heads.css('cursor', 'default');
      }
    },

    _bindHeaderHandler: function() {
      var
        words   = this.heads.filter('.stepy-active').attr('id').split('-'), // TODO: try keep the number in an attribute.
        current = parseInt(words[words.length - 1], 10),
        clicked = $(this).index();

      if (clicked > current) {
        if (this.opt.next && !methods._execute.call(self, this.opt.next, clicked)) {
          return false;
        }
      } else if (clicked < current) {
        if (this.opt.back && !methods._execute.call(self, this.opt.back, clicked)) {
          return false;
        }
      }

      if (clicked != current) {
        methods.step.call(this, clicked);
      }
    },

    _bindNextButton: function() {
      var button = $(this).find(this.opt.nextButton);

      if (!button.length) {
        return;
      }

      button.on('click.stepy', function(e) {
        e.preventDefault();

        var index = $(this).data('index') + 1;

        if (!this.opt.next || methods._execute.call(this, this.opt.next, index, this.steps.length)) {
          methods.step.call(this, index);
        }
      }.bind(this));
    },

    _createButtons: function(step, index) {
      if (index === 0) {
        if (this.steps.length > 1) {
          methods._bindNextButton.call(this, step);
        }
      } else {
        $(step).hide();

        methods._bindBackButton.call(this, step);

        if (index < this.steps.length - 1) {
          methods._bindNextButton.call(this, step);
        }
      }
    },

    _createHead: function(step, index) {
      var
        step = $(step).attr('id', this.id + '-step-' + index),
        head = methods._head.call(this, index);

      head.append(methods._title.call(this, step));

      if (this.opt.description) {
        head.append(methods._description.call(this, step));
      }

      this.header.append(head);
    },

    _description: function(step) {
      var legend = step.children('legend');

      if (!this.opt.legend) {
        legend.hide();
      }

      if (legend.length) {
        return $('<span />', { html: legend.html() });
      }

      methods._error.call(this, '<legend /> element missing!');
    },

    _error: function(message) {
      $(this).html(message);

      $.error(message);
    },

    _execute: function(callback, index, totalSteps) {
      if (callback === undefined) {
        return true;
      }

      var isValid = callback.call(this, index, totalSteps);

      return isValid || isValid === undefined;
    },

    _generateId: function() {
      if (this.id === undefined || this.id === '') {
        $(this).attr('id', 'stepy-' + Math.random().toString().substring(2));
      }
    },

    _head: function(index) {
      return $('<li />', { id: this.id + '-head-' + index });
    },

    _header: function() {
      var header = $('<ul />', { id: this.id + '-header', 'class': 'stepy-header' });

      if (this.opt.titleTarget) {
        header.appendTo(this.opt.titleTarget);
      } else {
        header.insertBefore(this);
      }

      return header;
    },

    _onFinishButton: function(evt) {
      var onSubmit = undefined;

      if (this.tagName === 'FORM') {
        onSubmit = this.getAttribute('onsubmit');

        this.setAttribute('onsubmit', 'return false;');
      }

      if (!methods._execute.call(this, this.opt.finish, this.steps.length - 1)) {
        evt.preventDefault();
      } else if (this.tagName === 'FORM') {
        if (onSubmit) {
          this.setAttribute('onsubmit', onSubmit);
        } else {
          this.removeAttribute('onsubmit');
        }

        var isSubmit = this.finishButton.attr('type') === 'submit';

        if (isSubmit && (!this.opt.validate || methods.validate.call(this, this.steps.length - 1))) {
          this.submit();
        }
      }
    },

    _setState: function(data) {
      var self = $(this);

      self.data($.extend({}, self.data(), data));
    },

    _stateButton: function(index, steps) {
      var
        self = $(this),
        step = steps.eq(index);

      if (index === 0) {
        step.find('.stepy-back').hide();
        step.find('.stepy-next').show();
        self.find('.stepy-finish').hide();
      } else if (index === steps.length - 1) {
        step.find('.stepy-back').show();
        step.find('.stepy-next').hide();
        self.find('.stepy-finish').show();
      } else {
        step.find('.stepy-back').show();
        step.find('.stepy-next').show();
        self.find('.stepy-finish').hide();
      }
    },

    _title: function(step) {
      return $('<div />', { html: step.attr('title') || '--' });
    },

    _transition: function(steps, max) {
      if (this.opt.transition === 'fade') {
        steps.fadeOut(this.opt.duration, function() {
          if (--steps.length > 0) {
            return;
          }

          steps.eq(max).fadeIn(this.opt.duration);
        });
      } else if (this.opt.transition === 'slide') {
        steps.slideUp(this.opt.duration, function() {
          if (--steps.length > 0) {
            return;
          }

          steps.eq(max).slideDown(this.opt.duration);
        });
      }
    },

    destroy: function() {
      return $(this).each(function() {
        var self = $(this);

        if (self.data('stepy')) {
          var steps = self.data('stepy', false).children('fieldset').css('display', '');

          self.children('.stepy-errors').remove();
        }
      });
    },

    step: function(index) {
      var
        max   = index,
        self  = $(this),
        steps = self.children('fieldset');

      if (index > steps.length - 1) {
        index = steps.length - 1;
      }

      if (this.opt.validate) {
        var isValid = true;

        for (var i = 0; i < index; i++) {
          isValid &= methods.validate.call(this, i);

          if (this.opt.block && !isValid) {
            max = i;
            break;
          }
        }
      }

      if (this.opt.transition) {
        methods._transition.call(this, steps, max);
      } else {
        steps.hide(this.opt.duration).eq(max).show(this.opt.duration);
      }

      if (this.opt.header) {
        this.heads.removeClass('stepy-active').eq(max).addClass('stepy-active');
      }

      if (this.tagName === 'FORM') {
        var fields = steps.eq(max);

        if (max === index) {
          fields = fields.find(':input:enabled:visible');
        } else {
          fields = fields.find('.error').trigger('select').trigger('focus');
        }

        fields.first().trigger('select').trigger('focus');
      }

      if (this.opt.select) {
        this.opt.select.call(this, max + 1, steps.length);
      }

      methods._stateButton.call(this, max, steps);
      methods._setState.call(this, { index: max });

      return self;
    },

    validate: function(index) {
      var self = $(this);

      if (!this.tagName === 'FORM') {
        return true;
      }

      var
        that      = this,
        step      = self.children('fieldset').eq(index),
        isValid   = true,
        $title    = $('#' + this.id + '-header').children().eq(index),
        $validate = self.validate();

      $(step.find(':input:enabled').get().reverse()).each(function() {
        var fieldIsValid = $validate.element($(this));

        if (fieldIsValid === undefined) {
          fieldIsValid = true;
        }

        isValid &= fieldIsValid;

        if (isValid) {
          if (that.opt.errorImage) {
            $title.removeClass('stepy-error');
          }
        } else {
          if (that.opt.errorImage) {
            $title.addClass('stepy-error');
          }

          $validate.focusInvalid();
        }
      });

      return isValid;
    }
  };

  $.fn.stepy = function(method) {
    if (methods[method]) {
      return methods[method].apply($(this)[0], Array.prototype.slice.call(arguments, 1));
    } else if (typeof method === 'object' || !method) {
      return methods.init.apply(this, arguments);
    } else {
      $.error('Method ' + method + ' does not exist!');
    }
  };

  $.fn.stepy.defaults = {
    back:          undefined,
    backButton:    '.stepy-back',
    block:         false,
    description:   true,
    duration:      0,
    enter:         true,
    errorImage:    false,
    finish:        undefined,
    finishButton:  undefined,
    globalButtons: false,
    header:        true,
    ignore:        '',
    legend:        true,
    next:          undefined,
    nextButton:    '.stepy-next',
    select:        undefined,
    titleClick:    false,
    titleTarget:   undefined,
    transition:    undefined,
    validate:      false
  };

})(jQuery);
<|endoftext|>


<commit_before>var
  http = require("http"),
  fs = require('fs'),
  url = require('url'),
  querystring = require('querystring');

var
	UglifyJS = require('uglify-js'),
	upgrade = require('../converter'),
	analyzer = require('../util/analyzer'),
	wrapdefine = require('./wrapdefine');

var server = http.createServer(function(req,response){
		 var queryObject = querystring.parse(url.parse(req.url).query),
		 // 	file_content = require(file['url'] || "");
				 urlReg = /((?:http|https):\/\/[^\/]+)(.+)/ig,

				 file =  queryObject.url || "",

				 urlA;

				if(!file){
					console.log("请求文件地址不存在")
					return ;
				}

				urlA = urlReg.exec(file);

				var content = "";

				http.get(urlA[1]+urlA[2], function(res) {

						res.setEncoding('utf8');

						res.on('data',function(chunk){

									 content+=chunk;

						});

						res.on('end',function(){

							     ast = upgrade.parse(content);

						  		 ast = upgrade.convert(ast);

						  	   analyzer(ast);

						  		 code = upgrade.printCode(ast);

						  		 response.writeHead(200);

						  		 response.write(wrapdefine(code, req.url));

						  		 response.end();

						});

						res.on('error',function(chunk){

								console.log("文件加载失败");

						})

				}).end();

 }).listen(2000);

console.log('Server was started!');
<commit_msg>upgrade/filtration/app.js: fix code indent<commit_after>var
  http = require("http"),
  fs = require('fs'),
  url = require('url'),
  querystring = require('querystring');

var
	UglifyJS = require('uglify-js'),
	upgrade = require('../converter'),
	analyzer = require('../util/analyzer'),
	wrapdefine = require('./wrapdefine');

var server = http.createServer(function(req,response){
	var queryObject = querystring.parse(url.parse(req.url).query),

		// 	file_content = require(file['url'] || "");
		urlReg = /((?:http|https):\/\/[^\/]+)(.+)/ig,

		file =  queryObject.url || "",

		urlA;

	if(!file){
		console.log("请求文件地址不存在")
		return ;
	}

	urlA = urlReg.exec(file);

	var content = "";

	http.get(urlA[1]+urlA[2], function(res) {

		res.setEncoding('utf8');

		res.on('data',function(chunk){

			content+=chunk;

		});

		res.on('end',function(){

			     ast = upgrade.parse(content);

		  		 ast = upgrade.convert(ast);

		  	   analyzer(ast);

		  		 code = upgrade.printCode(ast);

		  		 response.writeHead(200);

		  		 response.write(wrapdefine(code, req.url));

		  		 response.end();

		});

		res.on('error',function(chunk){

				console.log("文件加载失败");

		});

	}).end();

 }).listen(2000);

console.log('Server was started!');
<|endoftext|>


<commit_before>/**
 * @license
 * Copyright 2012 Google Inc. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
var fs = require('fs');
var vm = require('vm');
var path = require('path');

// Initializing FOAM_BOOT_DIR.
var FOAM_BOOT_DIR = '';
if (process.argv[2]) {
  FOAM_BOOT_DIR = path.normalize(process.argv[2]);
}

global.window = global;
global.document = {
  window: global
};

// Loading all FOAM models.
var modelsfiles = fs.readFileSync(path.join(FOAM_BOOT_DIR, 'FOAMmodels.js'));
vm.runInThisContext(modelsfiles);

for (var i = 0; i < files.length; i++) {
  var filename = files[i] + '.js';
  var filedata = fs.readFileSync(path.join(FOAM_BOOT_DIR, filename));
  vm.runInThisContext(filedata, filename);
}

// Needed so that scripts can require other nodejs modules.
global.require = require;

// For command line processing, run as
// $ node bootFOAMnode.js <FOAM_BOOT_DIR> <script> <script args>
// Arguments are passed to the script as a global.argv array.
if (process.argv[3]) {
  var scriptPathname = path.normalize(process.argv[3]);
  global.argv = process.argv.slice(4);
  filedata = fs.readFileSync(scriptPathname);
  vm.runInThisContext(filedata, scriptPathname);
}
<commit_msg>Fix bootFOAMnode.js failing to load StackView.js.<commit_after>/**
 * @license
 * Copyright 2012 Google Inc. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
var fs = require('fs');
var vm = require('vm');
var path = require('path');

global.window = global;
global.document = {
  window: global
};

// Initializing FOAM_BOOT_DIR.
global.FOAM_BOOT_DIR = '';
if (process.argv[2]) {
  global.FOAM_BOOT_DIR = path.normalize(process.argv[2]);
}

// Loading all FOAM models.
var modelsfiles = fs.readFileSync(path.join(FOAM_BOOT_DIR, 'FOAMmodels.js'));
vm.runInThisContext(modelsfiles);

for (var i = 0; i < files.length; i++) {
  var filename = files[i] + '.js';
  var filedata = fs.readFileSync(path.join(FOAM_BOOT_DIR, filename));
  vm.runInThisContext(filedata, filename);
}

// Needed so that scripts can require other nodejs modules.
global.require = require;

// For command line processing, run as
// $ node bootFOAMnode.js <FOAM_BOOT_DIR> <script> <script args>
// Arguments are passed to the script as a global.argv array.
if (process.argv[3]) {
  var scriptPathname = path.normalize(process.argv[3]);
  global.argv = process.argv.slice(4);
  filedata = fs.readFileSync(scriptPathname);
  vm.runInThisContext(filedata, scriptPathname);
}
<|endoftext|>


<commit_before>'use strict';

var fs = require('fs');
var ejs = require('ejs');

exports.getHeaderAndFooter = function () {
    var defaultTemplatePath = global.pathToApp + '/assets/templates/';
    var userTemplatePath = global.app.get('user') + '/assets/templates/';
    var headerFile = 'header.inc.html';
    var footerFile = 'footer.inc.html';

    var output = {};

    var userHeaderTplPath = userTemplatePath + headerFile;
    var headerTplPath = fs.existsSync(userHeaderTplPath) ? userHeaderTplPath : defaultTemplatePath + headerFile;

    var userFooterTplPath = userTemplatePath + footerFile;
    var footerTplPath = fs.existsSync(userFooterTplPath) ? userFooterTplPath : defaultTemplatePath + footerFile;

    output.header = ejs.render(fs.readFileSync(headerTplPath, 'utf-8'));
    output.footer = ejs.render(fs.readFileSync(footerTplPath, 'utf-8'), {
        engineVersion: global.engineVersion
    });

    return output;
};<commit_msg>use path.join in headerFooter.js<commit_after>'use strict';

var fs = require('fs');
var ejs = require('ejs');
var path = require('path');

exports.getHeaderAndFooter = function () {
    var defaultTemplatePath = path.join(global.pathToApp, 'assets/templates');
    var userTemplatePath = path.join(global.app.get('user'), 'assets/templates');
    var headerFile = 'header.inc.html';
    var footerFile = 'footer.inc.html';

    var output = {};

    var userHeaderTplPath = path.join(userTemplatePath, headerFile);
    var headerTplPath = fs.existsSync(userHeaderTplPath) ? userHeaderTplPath : path.join(defaultTemplatePath, headerFile);

    var userFooterTplPath = path.join(userTemplatePath, footerFile);
    var footerTplPath = fs.existsSync(userFooterTplPath) ? userFooterTplPath : path.join(defaultTemplatePath, footerFile);

    output.header = ejs.render(fs.readFileSync(headerTplPath, 'utf-8'));
    output.footer = ejs.render(fs.readFileSync(footerTplPath, 'utf-8'), {
        engineVersion: global.engineVersion
    });

    return output;
};<|endoftext|>


<commit_before>var template = require('./template');
var View = require('view');
var laws = require('laws');
var List = require('list.js');
var t = require('t');
var dropdown = require('dropdown');

/**
 * Expose LandingView.
 */

module.exports = LandingView;

/**
 * Signin LandingView
 *
 * @return {LandingView} `LandingView` instance.
 * @api public
 */

function LandingView () {
  if (!(this instanceof LandingView)) {
    return new LandingView();
  }

  View.call(this, template, {
    laws: laws.getParents()
  });

  var view = this;

  // Author filter
  this.authorFilter = dropdown({
    caption: t('landing.filter.author.filterby') + ': %s',
    all: true,
    style: 'primary',
    items: laws.getAuthors().map(function(author) {
      return { id: author.id, text: author.name };
    })
  })
  .on('change', function(value) {
    view.applyFilters();
  })
  .appendTo(this.find('#author-filter')[0]);

  // Tag filter
  this.tagFilter = dropdown({
    caption: t('landing.filter.tag.filterby') + ': %s',
    all: true,
    style: 'primary',
    items: laws.getTags().map(function(tag) {
      return { id: tag.id, text: tag.name };
    })
  })
  .on('change', function(value) {
    view.applyFilters();
  })
  .appendTo(this.find('#tag-filter')[0]);
}

/**
 * Inherit from `FormView`
 */

View(LandingView);

LandingView.prototype.switchOn = function() {
  this.list = new List('landing', { valueNames: ['law-title', 'law-closing-date', 'law-author', 'law-tag'] });
};

LandingView.prototype.applyFilters = function() {
  var view = this;

  if ('0' === this.tagFilter.selectedValue() && '0' === this.authorFilter.selectedValue()) {
    this.list.filter();
  } else if ('0' === this.tagFilter.selectedValue()) {
    this.list.filter(function(item) {
      var val = item.values();
      return val['law-author'] === view.authorFilter.selectedValue();
    });
  } else if ('0' === this.authorFilter.selectedValue()) {
    this.list.filter(function(item) {
      var val = item.values();
      return val['law-tag'] === view.tagFilter.selectedValue();
    });
  } else {
    this.list.filter(function(item) {
      var val = item.values();
      return val['law-tag'] === view.tagFilter.selectedValue() && val['law-author'] === view.authorFilter.selectedValue();
    });
  }
};
<commit_msg>[landing] Links in summary text opens in new tab. Closes #15<commit_after>var template = require('./template');
var View = require('view');
var laws = require('laws');
var List = require('list.js');
var t = require('t');
var dropdown = require('dropdown');
var o = require('dom');

/**
 * Expose LandingView.
 */

module.exports = LandingView;

/**
 * Signin LandingView
 *
 * @return {LandingView} `LandingView` instance.
 * @api public
 */

function LandingView () {
  if (!(this instanceof LandingView)) {
    return new LandingView();
  }

  this.laws = laws.getParents();

  // Modifies the summary HTML so that the `a` elements
  // are targeted to `_blank`
  this.laws.forEach(function(law) {
    var html = law.summary;
    var div = document.createElement('div');
    var el = o(html);
    el.find('a').attr('target', '_blank');
    el.appendTo(div);
    law.summary = div.innerHTML;
  });

  View.call(this, template, {
    laws: this.laws
  });

  var view = this;

  // Author filter
  this.authorFilter = dropdown({
    caption: t('landing.filter.author.filterby') + ': %s',
    all: true,
    style: 'primary',
    items: laws.getAuthors().map(function(author) {
      return { id: author.id, text: author.name };
    })
  })
  .on('change', function(value) {
    view.applyFilters();
  })
  .appendTo(this.find('#author-filter')[0]);

  // Tag filter
  this.tagFilter = dropdown({
    caption: t('landing.filter.tag.filterby') + ': %s',
    all: true,
    style: 'primary',
    items: laws.getTags().map(function(tag) {
      return { id: tag.id, text: tag.name };
    })
  })
  .on('change', function(value) {
    view.applyFilters();
  })
  .appendTo(this.find('#tag-filter')[0]);
}

/**
 * Inherit from `FormView`
 */

View(LandingView);

LandingView.prototype.switchOn = function() {
  this.list = new List('landing', { valueNames: ['law-title', 'law-closing-date', 'law-author', 'law-tag'] });
};

LandingView.prototype.applyFilters = function() {
  var view = this;

  if ('0' === this.tagFilter.selectedValue() && '0' === this.authorFilter.selectedValue()) {
    this.list.filter();
  } else if ('0' === this.tagFilter.selectedValue()) {
    this.list.filter(function(item) {
      var val = item.values();
      return val['law-author'] === view.authorFilter.selectedValue();
    });
  } else if ('0' === this.authorFilter.selectedValue()) {
    this.list.filter(function(item) {
      var val = item.values();
      return val['law-tag'] === view.tagFilter.selectedValue();
    });
  } else {
    this.list.filter(function(item) {
      var val = item.values();
      return val['law-tag'] === view.tagFilter.selectedValue() && val['law-author'] === view.authorFilter.selectedValue();
    });
  }
};
<|endoftext|>


<commit_before>var _curry2 = require('./internal/_curry2');
var clone = require('./clone');

/**
 * Returns a copy of the list, sorted according to the comparator function, which should accept two values at a
 * time and return a negative number if the first value is smaller, a positive number if it's larger, and zero
 * if they are equal.  Please note that this is a **copy** of the list.  It does not modify the original.
 *
 * @func
 * @memberOf R
 * @category List
 * @sig (a,a -> Number) -> [a] -> [a]
 * @param {Function} comparator A sorting function :: a -> b -> Int
 * @param {Array} list The list to sort
 * @return {Array} a new array with its elements sorted by the comparator function.
 * @example
 *
 *      var diff = function(a, b) { return a - b; };
 *      R.sort(diff, [4,2,7,5]); //=> [2, 4, 5, 7]
 */
module.exports = _curry2(function sort(comparator, list) {
  return clone(list).sort(comparator);
});
<commit_msg>Don't clone in sort<commit_after>var _curry2 = require('./internal/_curry2');
var _slice = require('./internal/_slice');

/**
 * Returns a copy of the list, sorted according to the comparator function, which should accept two values at a
 * time and return a negative number if the first value is smaller, a positive number if it's larger, and zero
 * if they are equal.  Please note that this is a **copy** of the list.  It does not modify the original.
 *
 * @func
 * @memberOf R
 * @category List
 * @sig (a,a -> Number) -> [a] -> [a]
 * @param {Function} comparator A sorting function :: a -> b -> Int
 * @param {Array} list The list to sort
 * @return {Array} a new array with its elements sorted by the comparator function.
 * @example
 *
 *      var diff = function(a, b) { return a - b; };
 *      R.sort(diff, [4,2,7,5]); //=> [2, 4, 5, 7]
 */
module.exports = _curry2(function sort(comparator, list) {
  return _slice(list).sort(comparator);
});
<|endoftext|>


<commit_before>
var Parser = require("./parser"),
    path = require("path");

// cli -g file -i file :)
// cli -i file (g = std) :)
// cli -g file (i x) :)
// cli -g file -i -
// cli x

exports.main = function(args)
{
    var options = parseOptions(),
        grammar = options.grammar,
        input = options.input,
        output = options.output;

    if (!grammar || !grammar.length)
    {
        console.log('Grammar via stdin:');
    }

    read(grammar, function(err, data) {
        if (err)
        {
            console.error("The Grammar file '"+grammar+"' could not be read.");
            process.exit(1);
        }
        var parser = new Parser(data);

        if (input !== undefined)
        {
            if (!input.length)
            {
                console.log('Input via stdin:');
            }

            read(input, function(err, data) {
                if (err)
                {
                    console.error("The input file '"+input+"' could not be read.");
                    process.exit(1);
                }
                var result = parser.parse(data).toString();
                write(output, result);
            });
        }
        else
        {
            var json = JSON.stringify(parser.compiledGrammar).toUnicodeEscapedString();

            if (options.table)
                write(output, json);

            else
            {
                var directory = path.dirname(module.filename),
                    templatename = (options.browser) ? path.join(directory, "templates", "browser.js") : path.join(directory, "templates", "node.js");

                read(templatename, function(err, templatedata) {
                    if (options.browser)
                        templatedata = templatedata.replace(/%{NAMESPACE}/g, options.browser);

                    read(path.join(directory, "parser.js"), function(err, parserjsdata) {
                        templatedata = templatedata.replace(/%{PARSER}/g, parserjsdata)
                        templatedata = templatedata.replace(/%{COMPILED_GRAMMAR}/g, json);
                        write(output, templatedata);
                    });
                });
            }
        }
    });
}

function parseOptions()
{
    return require("./utilities/nomnom").opts(
    {
        grammar:{
                    string: '-g PATH, --grammar=PATH',
                    help:"A Language grammar file. Omit for input via stdin."
                },

        input:  {
                    string:"-i, --input=PATH",
                    help:"An input file to parse. Omit for input via stdin."
                },

        output: {
                    string:"-o, --output=PATH",
                    help:"An output file to save the result. If omitted stdout is used."
                },

        table:  {
                    string:"-t, --table",
                    help:"Only output the parser table, not the entire generated parser."
                }

    }).parseArgs();
}

function read(filename, callback)
{
    if (!filename || !filename.length)
    {
        var stdin = process.stdin,
            lines = "";
        process.stdout.write('Use Ctrl-D to stop input:\n> ');
        stdin.resume();
        stdin.on('data', function(chunk) {
            lines += chunk.toString();
            process.stdout.write('> ');
        }).on('end',function() {
            process.stdout.write('\n');
            callback(false, lines);
        }).on('error', function() {
            console.error("There was an error while taking input data from stdin.");
            process.exit(1);
        });
    }
    else
        require("fs").readFile(filename, "utf8", callback);
}

function write(filename, contents)
{
    if (!filename || !filename.length)
        console.log("%s", contents);
    else
        require("fs").writeFile(filename, contents, function(err) {
            if (err)
            {
                console.error("There was an error writing to file '"+filename+"'.");
                process.exit(1);
            }
        });
}

String.prototype.toUnicodeEscapedString = function()
{
    var index = 0,
        count = this.length,
        characters = [];

    for (; index < count; ++index)
    {
        var code = this.charCodeAt(index);

        if (this.charCodeAt(index) <= 255)
        {
            characters.push(this.charAt(index));
            continue;
        }

        var escape = code.toString(16).toUpperCase();

        while (escape.length < 4)
            escape = '0' + escape;

        characters.push("\\u" + escape);
    }

    return characters.join("");
}

Array.prototype.toSource = function()
{
    var index = 0,
        count = this.length,
        sources = [];

    for (; index < count; ++index)
        sources.push(this[index].toSource());

    return "[" + sources.join(", ") + "]";
}

Number.prototype.toSource = function()
{
    return this + "";
}

String.prototype.toSource = function()
{
    return JSON.stringify(this.toUnicodeEscapedString());
}

RegExp.prototype.toSource = function()
{
    return this + "";
}

exports.main(process.argv);
//3 things: grammar, input, output
// table
// file
// cli
// browser
// full blown
// json?
<commit_msg>Reapply original options logic<commit_after>
var Parser = require("./parser"),
    path = require("path");

// cli -g file -i file :)
// cli -i file (g = std) :)
// cli -g file (i x) :)
// cli -g file -i -
// cli x

exports.main = function(args)
{
    var options = parseOptions(),
        grammar = options.grammar,
        input = options.input,
        output = options.output;

    if ((!grammar || !grammar.length) && (input !== undefined && !input.length))
    {
        console.error("The grammar and input can not both come from stdin.");
        process.exit(1);
    }

    read(grammar, function(err, data) {
        if (err)
        {
            console.error("The Grammar file '"+grammar+"' could not be read.");
            process.exit(1);
        }
        var parser = new Parser(data);

        if (input !== undefined)
        {
            read(input, function(err, data) {
                if (err)
                {
                    console.error("The input file '"+input+"' could not be read.");
                    process.exit(1);
                }
                var result = parser.parse(data).toString();
                write(output, result);
            });
        }
        else
        {
            var json = JSON.stringify(parser.compiledGrammar).toUnicodeEscapedString();

            if (options.table)
                write(output, json);

            else
            {
                var directory = path.dirname(module.filename),
                    templatename = (options.browser) ? path.join(directory, "templates", "browser.js") : path.join(directory, "templates", "node.js");

                read(templatename, function(err, templatedata) {
                    if (options.browser)
                        templatedata = templatedata.replace(/%{NAMESPACE}/g, options.browser);

                    read(path.join(directory, "parser.js"), function(err, parserjsdata) {
                        templatedata = templatedata.replace(/%{PARSER}/g, parserjsdata)
                        templatedata = templatedata.replace(/%{COMPILED_GRAMMAR}/g, json);
                        write(output, templatedata);
                    });
                });
            }
        }
    });
}

function parseOptions()
{
    return require("./utilities/nomnom").opts(
    {
        grammar:{
                    string: '-g PATH, --grammar=PATH',
                    help:"A Language grammar file. Omit for input via stdin."
                },

        input:  {
                    string:"-i, --input=PATH",
                    help:"An input file to parse. Omit for input via stdin."
                },

        output: {
                    string:"-o, --output=PATH",
                    help:"An output file to save the result. If omitted stdout is used."
                },

        table:  {
                    string:"-t, --table",
                    help:"Only output the parser table, not the entire generated parser."
                }

    }).parseArgs();
}

function read(filename, callback)
{
    if (!filename || !filename.length)
    {
        var stdin = process.stdin,
            lines = "";
        process.stdout.write('Use Ctrl-D to stop input:\n> ');
        stdin.resume();
        stdin.on('data', function(chunk) {
            lines += chunk.toString();
        }).on('end',function() {
            callback(false, lines);
        }).on('error', function() {
            console.error("There was an error while taking input data from stdin.");
            process.exit(1);
        });
    }
    else
        require("fs").readFile(filename, "utf8", callback);
}

function write(filename, contents)
{
    if (!filename || !filename.length)
        console.log("%s", contents);
    else
        require("fs").writeFile(filename, contents, function(err) {
            if (err)
            {
                console.error("There was an error writing to file '"+filename+"'.");
                process.exit(1);
            }
        });
}

String.prototype.toUnicodeEscapedString = function()
{
    var index = 0,
        count = this.length,
        characters = [];

    for (; index < count; ++index)
    {
        var code = this.charCodeAt(index);

        if (this.charCodeAt(index) <= 255)
        {
            characters.push(this.charAt(index));
            continue;
        }

        var escape = code.toString(16).toUpperCase();

        while (escape.length < 4)
            escape = '0' + escape;

        characters.push("\\u" + escape);
    }

    return characters.join("");
}

Array.prototype.toSource = function()
{
    var index = 0,
        count = this.length,
        sources = [];

    for (; index < count; ++index)
        sources.push(this[index].toSource());

    return "[" + sources.join(", ") + "]";
}

Number.prototype.toSource = function()
{
    return this + "";
}

String.prototype.toSource = function()
{
    return JSON.stringify(this.toUnicodeEscapedString());
}

RegExp.prototype.toSource = function()
{
    return this + "";
}

exports.main(process.argv);
//3 things: grammar, input, output
// table
// file
// cli
// browser
// full blown
// json?
<|endoftext|>


<commit_before>import { isStr, flattenToObj, hasOwn, empty } from './utils'

const URIComponentBlacklist = `([^\s#$&+,/:;=?@]*)`
const identifierx = /(:[A-Za-z0-9_:]+)/
const trailingSlashx = /\/$/

function substitute(literals, values) {
  return String.raw({ raw: literals }, ...values)
}

function getMatchX(identifiers, literals) {
  let subs = new Array(identifiers.length).fill(URIComponentBlacklist)
  return new RegExp(`^${substitute(literals, subs)}`, 'i')
}

let parsePathKey = pathKey => {
  let key = isStr(pathKey) ? pathKey.replace(trailingSlashx, '') : ''
  let fragments = key.split(identifierx)
  let identifiers = []
  let literals = fragments.reduce((acc, f) => {
    if (f.indexOf(':') === 0) identifiers.push(f)
    else acc.push(f)
    return acc
  }, [])
  let matchx = key == '' ? new RegExp('') : getMatchX(identifiers, literals)
  return { key: pathKey, identifiers, literals, matchx }
}

function assignValues(pathKey, values = []) {
  let { identifiers } = isStr(pathKey) ? parsePathKey(pathKey) : pathKey
  let res = identifiers.map((id, key) => ({ [id]: values[key] }))
  return flattenToObj(res)
}

class Path {
  constructor(key) {
    Object.assign(this, parsePathKey(key))
  }
  findInvalid(validator, values) {
    let ids = this.identifiers, check = hasOwn.bind(validator)
    return empty(validator)
      ? -1
      : values.findIndex((val, i) => check(ids[i]) && !validator[ids[i]](values))
  }
  validate(validator, values) {
    let invalid = this.findInvalid(validator, values)
    return invalid === -1 ? { values, passed: true } : { values: values.slice(0, invalid) }
  }
  match(validator, pathname) {
    pathname = pathname.replace(trailingSlashx, '')
    let matches = this.matchx.exec(pathname)
    if (!matches) return {}
    let match = matches[0], values = matches.slice(1).map(decodeURIComponent)
    let exact = match.length === pathname.length
    return Object.assign(this.validate(validator, values), { match, exact })
  }
  makeLink(values) {
    return substitute(this.literals, values)
  }
}

class PathSpec {
  constructor(pathKeys, next, err) {
    if (!Array.isArray(pathKeys) || !pathKeys.length) pathKeys = [isStr(pathKeys) ? pathKeys : '']
    let paths = pathKeys.map(k => new Path(k))
    Object.assign(this, { pathKeys, paths, next, err })
  }
  find(pathKey) {
    let idx = this.pathKeys.indexOf(pathKey)
    return idx > -1 && this.paths[idx]
  }
  match(validator, pathname) {
    let [primary, ...subs] = this.paths
    let result, matches = primary.match(validator, pathname)
    if (matches.passed) {
      result = { [primary.key]: matches }
      subs.some(sub => {
        let submatches = sub.match(validator, pathname)
        if (submatches.passed) result[sub.key] = submatches
        return submatches.exact
      })
    }
    return result
  }
  success(result) {
    return result && Object.keys(result).some(k => result[k].exact)
  }
  resolve(result, success = this.success(result)) {
    return !this.err || success ? this.next(result) : this.err(result)
  }
}

export function spec(...pathKeys) {
  return (next, err) => new PathSpec(pathKeys, next, err)
}

class PrefixSpec extends PathSpec {
  static strip(prefix, path) {
    return path.replace(prefix, '/').replace('//', '/')
  }
  get prefix() {
    return this.pathKeys[0]
  }
  match(validator, loc) {
    let { ultra, pathname } = loc, result = { ultra, success: false }
    if (super.match(validator, pathname))
      result = super.resolve({ ultra, pathname: PrefixSpec.strip(this.prefix, pathname) }, true)
    return result
  }
}

export function prefixSpec(prefix, next) {
  return new PrefixSpec(prefix, next)
}

function rxToFn(rx) {
  return values => !empty(values.filter(rx.test.bind(rx)))
}

function validator(id, rx) {
  return { [id]: rxToFn(rx) }
}

function rx(ids, rx) {
  return ids.map(id => validator(id, rx))
}

export function checks(...ids) {
  return rx.bind(null, ids)
}
<commit_msg>move path manipulation to match in PathSpec before matching<commit_after>import { isStr, flattenToObj, hasOwn, empty } from './utils'

const URIComponentBlacklist = `([^\s#$&+,/:;=?@]*)`
const identifierx = /(:[A-Za-z0-9_:]+)/
const trailingSlashx = /\/$/

function substitute(literals, values) {
  return String.raw({ raw: literals }, ...values)
}

function getMatchX(identifiers, literals) {
  let subs = new Array(identifiers.length).fill(URIComponentBlacklist)
  return new RegExp(`^${substitute(literals, subs)}`, 'i')
}

let parsePathKey = pathKey => {
  let key = isStr(pathKey) ? pathKey.replace(trailingSlashx, '') : ''
  let fragments = key.split(identifierx)
  let identifiers = []
  let literals = fragments.reduce((acc, f) => {
    if (f.indexOf(':') === 0) identifiers.push(f)
    else acc.push(f)
    return acc
  }, [])
  let matchx = key == '' ? new RegExp('') : getMatchX(identifiers, literals)
  return { key: pathKey, identifiers, literals, matchx }
}

function assignValues(pathKey, values = []) {
  let { identifiers } = isStr(pathKey) ? parsePathKey(pathKey) : pathKey
  let res = identifiers.map((id, key) => ({ [id]: values[key] }))
  return flattenToObj(res)
}

function makeMatchPath(path) {
  return path.replace(trailingSlashx, '')
}

class Path {
  constructor(key) {
    Object.assign(this, parsePathKey(key))
  }
  findInvalid(validator, values) {
    let ids = this.identifiers, check = hasOwn.bind(validator)
    return empty(validator)
      ? -1
      : values.findIndex((val, i) => check(ids[i]) && !validator[ids[i]](values))
  }
  validate(validator, values) {
    let invalid = this.findInvalid(validator, values)
    return invalid === -1 ? { values, passed: true } : { values: values.slice(0, invalid) }
  }
  match(validator, pathname) {
    let matches = this.matchx.exec(pathname)
    if (!matches) return {}
    let match = matches[0], values = matches.slice(1).map(decodeURIComponent)
    let exact = match.length === pathname.length
    return Object.assign(this.validate(validator, values), { match, exact })
  }
  makeLink(values) {
    return substitute(this.literals, values)
  }
}

class PathSpec {
  constructor(pathKeys, next, err) {
    if (!Array.isArray(pathKeys) || !pathKeys.length) pathKeys = [isStr(pathKeys) ? pathKeys : '']
    let paths = pathKeys.map(k => new Path(k))
    Object.assign(this, { pathKeys, paths, next, err })
  }
  find(pathKey) {
    let idx = this.pathKeys.indexOf(pathKey)
    return idx > -1 && this.paths[idx]
  }
  match(validator, pathname) {
    let matchPath = makeMatchPath(pathname)
    let [primary, ...subs] = this.paths
    let result, matches = primary.match(validator, matchPath)
    if (matches.passed) {
      result = { [primary.key]: matches }
      subs.some(sub => {
        let submatches = sub.match(validator, matchPath)
        if (submatches.passed) result[sub.key] = submatches
        return submatches.exact
      })
    }
    return result
  }
  success(result) {
    return result && Object.keys(result).some(k => result[k].exact)
  }
  resolve(result, success = this.success(result)) {
    return !this.err || success ? this.next(result) : this.err(result)
  }
}

export function spec(...pathKeys) {
  return (next, err) => new PathSpec(pathKeys, next, err)
}

class PrefixSpec extends PathSpec {
  static strip(prefix, path) {
    return path.replace(prefix, '/').replace('//', '/')
  }
  get prefix() {
    return this.pathKeys[0]
  }
  match(validator, loc) {
    let { ultra, pathname } = loc, result = { ultra, success: false }
    if (super.match(validator, pathname))
      result = super.resolve({ ultra, pathname: PrefixSpec.strip(this.prefix, pathname) }, true)
    return result
  }
}

export function prefixSpec(prefix, next) {
  return new PrefixSpec(prefix, next)
}

function rxToFn(rx) {
  return values => !empty(values.filter(rx.test.bind(rx)))
}

function validator(id, rx) {
  return { [id]: rxToFn(rx) }
}

function rx(ids, rx) {
  return ids.map(id => validator(id, rx))
}

export function checks(...ids) {
  return rx.bind(null, ids)
}
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2014 Adobe Systems Incorporated. All rights reserved.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
 * to deal in the Software without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 * and/or sell copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 * DEALINGS IN THE SOFTWARE.
 *
 */

define(function (require, exports, module) {
    "use strict";

    var EventEmitter = require("eventEmitter"),
        adapter = require("./adapter"),
        util = require("./util"),
        Promise = require("bluebird");

    /**
     * The LayerManager provides an API for dealing with the layers of the
     * currently active document
     *
     * Right now, this is purely demonstration code. This will need to be elaborated
     * to deal with all documents (or changed to be document specific / not a singleton).
     *
     * Emits "selectionChanged" event whenever the currently selected layer changes
     * with the following parameters
     *    1. @param {String} the selected layer name
     *
     * @extends EventEmitter
     * @constructor
     * @private
     */
    var LayerManager = function () {
        EventEmitter.call(this);

        adapter.on("select", this._handleSelect.bind(this));
        adapter.on("make", this._handleSelect.bind(this));
    };
    util.inherits(LayerManager, EventEmitter);

    /**
     * Holds the currently selected layer indices
     */
    LayerManager.prototype._currentSelection = [];

    /**
     * Event handler for low level select and make events
     * "Make" layer may cause selection to change as well
     * Grabs the current selected layer indices, saves them in _currentSelection
     * and emits a "selectionChanged" event with the current Selection array
     *
     */
    LayerManager.prototype._handleSelect = function () {
        this.getSelectedLayerIndices().bind(this).then(function (layers) {
            this._currentSelection = layers;
            this.emit("selectionChanged", this._currentSelection);
        });

    };

    LayerManager.prototype.getLayerAtIndex = function (index) {
        return adapter.getProperty("document", "numberOfLayers").then(function (layerCount) {
            if (typeof index === undefined || index < 0 || index > layerCount) {
                throw new Error("Invalid layer index");
            }

            // If only background layer, count is 0, and background layer cannot be unselected
            if (layerCount === 0) {
                return adapter.get({ref: "$Lyr", value: "$Trgt", enum: "$Ordn"});
            } else {
                return adapter.get({ref: "$Lyr", "index": index});
            }
        });
    };

    /**
     * Gets an array of layer references for all selected layers in the current document
     *
     * @return {Promise.<Array.<Object>>} Resolves to an array of layers with index and ref(:layer) keys
     */
    LayerManager.prototype.getSelectedLayers = function () {
        return adapter.get("document").then(function (document) {
            return document.targetLayers || [];
        });
    };

    /**
     * Gets an array of layer indices for all selected layers in the current document
     *
     * @return {Promise.<Array.<Number>>} Resolves to an array of numbers for each index of layers
     */
    LayerManager.prototype.getSelectedLayerIndices = function () {
        return this.getSelectedLayers().then(function (layers) {
            return layers.map(function (layer) {
                return layer.index;
            });
        });
    };

    LayerManager.prototype.getSelectedLayerDescriptors = function () {
        return this.getSelectedLayerIndices().then(function (indices) {
            var layerGets = [];
            indices.map(function (index) {
                layerGets.push(adapter.get({ref: "layer", index: index}));
            });
            return Promise.all(layerGets);
        });
    };

    /**
     * Creates a new layer in the currently active document.
     * The returned promise resolves/rejects when the operation is complete/has an error
     *
     * @return {Promise.<Object>} Result of the layer creation call
     */
    LayerManager.prototype.createNewLayer = function () {
        return adapter.call("$Mk", {"null" : { "ref" : "$Lyr " }});
    };

    /**
     * Gets all layers in the document with their properties
     *
     * @return {Promise.<ActionDescriptor>} Result of the layer creation call
     */
    LayerManager.prototype.getAllLayers = function () {
        return adapter.getProperty("document", "numberOfLayers").then(function (layerCount) {
            return adapter.getProperty("document", "hasBackgroundLayer").then(function (hasBackground) {
                var layerGets = [];
                var startIndex = hasBackground ? 0 : 1;

                for (var i = startIndex; i <= layerCount; i++) {
                    layerGets.push(adapter.get({ref: "layer", index: i}));
                }
                return Promise.all(layerGets);
            });
        });
    };

    /**
     * Duplicates layers.
     * If index is supplied, will only duplicate the indexed layer
     *
     * If only one layer is selected, and newLayerName is not null, copy will be renamed
     * Otherwise layers get copied with their original names
     * The returned promise resolves to the dupeArgs object.
     *
     * @param {?number} index Index of the layer to duplicate, default is currently selected layer(s)
     * @param {?string} newLayerName If supplied, renames the new layer, only applies when a single layer is selected
     * @return {Promise.<Object>} Promise that resolves to a reference to currently selected layer
     */
    LayerManager.prototype.duplicateLayer = function (index, newLayerName) {
        var nullArgs = { "ref": "$Lyr" };

        // This way we can either choose the current layer or a layer by index
        if (typeof index !== undefined) {
            nullArgs.index = index;
        } else {
            nullArgs.enum = "$Ordn";
            nullArgs.value = "$Trgt";
        }

        var dupeArgs = { "null" : nullArgs };
        dupeArgs.$Vrsn = 5;

        if (newLayerName) {
            dupeArgs["$Nm  "] = newLayerName;
        }

        return adapter.call("$Dplc", dupeArgs);
    };

    /**
     * Moves a layer
     * If index is null, will move the selected layer
     *
     * @param {?number} index Index of the layer to move, default is currently selected layer
     * @param {?number} dx Pixel value to move the layer horizontally (Default 0)
     * @param {?number} dy Pixel value to move the layer vertically (Default 0)
     * @return {Promise.<Object>} Promise that resolves to empty object
     */
    LayerManager.prototype.moveLayer = function (index, dx, dy) {
        var nullArgs = { "ref": "$Lyr" };

        if (typeof index !== undefined) {
            nullArgs.index = index;
        } else {
            nullArgs.enum = "$Ordn";
            nullArgs.value = "$Trgt";
        }

        var selectArgs = {"null": nullArgs};

        // If index is given, this ensures that the layer with given index is selected first
        // Otherwise, is a no-op and will move on to copying the layer
        return adapter.call("$slct", selectArgs).then(function () {
            var moveArgs = { "null": nullArgs };

            moveArgs.to = {
                "obj": "Offset",
                "value": {
                    "horizontal": {
                        "unit": "pixelsUnit",
                        "value": dx || 0
                    },
                    "vertical": {
                        "unit": "pixelsUnit",
                        "value": dy || 0
                    }
                }
            };

            return adapter.call("move", moveArgs);
        });
    };

    /**
     * Copies a layer and moves it
     * If index is null, will copy the selected layer
     *
     * @param {?number=} index Index of the layer to copy, default is currently selected layer
     * @param {?number} dx Pixel value to move the copied layer horizontally (Default 0)
     * @param {?number} dy Pixel value to move the copied layer vertically (Default 0)
     * @return {Promise.<Object>} Promise that resolves to empty object
     */
    LayerManager.prototype.copyLayer = function (index, dx, dy) {
        var nullArgs = { "ref": "$Lyr" };

        if (typeof index !== undefined) {
            nullArgs.index = index;
        } else {
            nullArgs.enum = "$Ordn";
            nullArgs.value = "$Trgt";
        }

        var selectArgs = {"null": nullArgs};

        // If index is given, this ensures that the layer with given index is selected first
        // Otherwise, is a no-op and will move on to copying the layer
        return adapter.call("$slct", selectArgs).then(function () {
            var copyArgs = { "null": nullArgs };

            copyArgs.to = {
                "obj": "Offset",
                "value": {
                    "horizontal": {
                        "unit": "pixelsUnit",
                        "value": dx || 0
                    },
                    "vertical": {
                        "unit": "pixelsUnit",
                        "value": dy || 0
                    }
                }
            };

            return adapter.call("copyEvent", copyArgs);
        });
    };

    /** @type {LayerManager} The LayerManager singleton */
    var theLayerManager = new LayerManager();

    module.exports = theLayerManager;

});
<commit_msg>Change param checks to not null checks<commit_after>/*
 * Copyright (c) 2014 Adobe Systems Incorporated. All rights reserved.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
 * to deal in the Software without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 * and/or sell copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 * DEALINGS IN THE SOFTWARE.
 *
 */

define(function (require, exports, module) {
    "use strict";

    var EventEmitter = require("eventEmitter"),
        adapter = require("./adapter"),
        util = require("./util"),
        Promise = require("bluebird");

    /**
     * The LayerManager provides an API for dealing with the layers of the
     * currently active document
     *
     * Right now, this is purely demonstration code. This will need to be elaborated
     * to deal with all documents (or changed to be document specific / not a singleton).
     *
     * Emits "selectionChanged" event whenever the currently selected layer changes
     * with the following parameters
     *    1. @param {String} the selected layer name
     *
     * @extends EventEmitter
     * @constructor
     * @private
     */
    var LayerManager = function () {
        EventEmitter.call(this);

        adapter.on("select", this._handleSelect.bind(this));
        adapter.on("make", this._handleSelect.bind(this));
    };
    util.inherits(LayerManager, EventEmitter);

    /**
     * Holds the currently selected layer indices
     */
    LayerManager.prototype._currentSelection = [];

    /**
     * Event handler for low level select and make events
     * "Make" layer may cause selection to change as well
     * Grabs the current selected layer indices, saves them in _currentSelection
     * and emits a "selectionChanged" event with the current Selection array
     *
     */
    LayerManager.prototype._handleSelect = function () {
        this.getSelectedLayerIndices().bind(this).then(function (layers) {
            this._currentSelection = layers;
            this.emit("selectionChanged", this._currentSelection);
        });

    };

    LayerManager.prototype.getLayerAtIndex = function (index) {
        return adapter.getProperty("document", "numberOfLayers").then(function (layerCount) {
            if (typeof index === undefined || index < 0 || index > layerCount) {
                throw new Error("Invalid layer index");
            }

            // If only background layer, count is 0, and background layer cannot be unselected
            if (layerCount === 0) {
                return adapter.get({ref: "$Lyr", value: "$Trgt", enum: "$Ordn"});
            } else {
                return adapter.get({ref: "$Lyr", "index": index});
            }
        });
    };

    /**
     * Gets an array of layer references for all selected layers in the current document
     *
     * @return {Promise.<Array.<Object>>} Resolves to an array of layers with index and ref(:layer) keys
     */
    LayerManager.prototype.getSelectedLayers = function () {
        return adapter.get("document").then(function (document) {
            return document.targetLayers || [];
        });
    };

    /**
     * Gets an array of layer indices for all selected layers in the current document
     *
     * @return {Promise.<Array.<Number>>} Resolves to an array of numbers for each index of layers
     */
    LayerManager.prototype.getSelectedLayerIndices = function () {
        return this.getSelectedLayers().then(function (layers) {
            return layers.map(function (layer) {
                return layer.index;
            });
        });
    };

    LayerManager.prototype.getSelectedLayerDescriptors = function () {
        return this.getSelectedLayerIndices().then(function (indices) {
            var layerGets = [];
            indices.map(function (index) {
                layerGets.push(adapter.get({ref: "layer", index: index}));
            });
            return Promise.all(layerGets);
        });
    };

    /**
     * Creates a new layer in the currently active document.
     * The returned promise resolves/rejects when the operation is complete/has an error
     *
     * @return {Promise.<Object>} Result of the layer creation call
     */
    LayerManager.prototype.createNewLayer = function () {
        return adapter.call("$Mk", {"null" : { "ref" : "$Lyr " }});
    };

    /**
     * Gets all layers in the document with their properties
     *
     * @return {Promise.<ActionDescriptor>} Result of the layer creation call
     */
    LayerManager.prototype.getAllLayers = function () {
        return adapter.getProperty("document", "numberOfLayers").then(function (layerCount) {
            return adapter.getProperty("document", "hasBackgroundLayer").then(function (hasBackground) {
                var layerGets = [];
                var startIndex = hasBackground ? 0 : 1;

                for (var i = startIndex; i <= layerCount; i++) {
                    layerGets.push(adapter.get({ref: "layer", index: i}));
                }
                return Promise.all(layerGets);
            });
        });
    };

    /**
     * Duplicates layers.
     * If index is supplied, will only duplicate the indexed layer
     *
     * If only one layer is selected, and newLayerName is not null, copy will be renamed
     * Otherwise layers get copied with their original names
     * The returned promise resolves to the dupeArgs object.
     *
     * @param {?number} index Index of the layer to duplicate, default is currently selected layer(s)
     * @param {?string} newLayerName If supplied, renames the new layer, only applies when a single layer is selected
     * @return {Promise.<Object>} Promise that resolves to a reference to currently selected layer
     */
    LayerManager.prototype.duplicateLayer = function (index, newLayerName) {
        var nullArgs = { "ref": "$Lyr" };

        // This way we can either choose the current layer or a layer by index
        if (index !== null) {
            nullArgs.index = index;
        } else {
            nullArgs.enum = "$Ordn";
            nullArgs.value = "$Trgt";
        }

        var dupeArgs = { "null" : nullArgs };
        dupeArgs.$Vrsn = 5;

        if (newLayerName) {
            dupeArgs["$Nm  "] = newLayerName;
        }

        return adapter.call("$Dplc", dupeArgs);
    };

    /**
     * Moves a layer
     * If index is null, will move the selected layer
     *
     * @param {?number} index Index of the layer to move, default is currently selected layer
     * @param {?number} dx Pixel value to move the layer horizontally (Default 0)
     * @param {?number} dy Pixel value to move the layer vertically (Default 0)
     * @return {Promise.<Object>} Promise that resolves to empty object
     */
    LayerManager.prototype.moveLayer = function (index, dx, dy) {
        var nullArgs = { "ref": "$Lyr" };

        if (index !== null) {
            nullArgs.index = index;
        } else {
            nullArgs.enum = "$Ordn";
            nullArgs.value = "$Trgt";
        }

        var selectArgs = {"null": nullArgs};

        // If index is given, this ensures that the layer with given index is selected first
        // Otherwise, is a no-op and will move on to copying the layer
        return adapter.call("$slct", selectArgs).then(function () {
            var moveArgs = { "null": nullArgs };

            moveArgs.to = {
                "obj": "Offset",
                "value": {
                    "horizontal": {
                        "unit": "pixelsUnit",
                        "value": dx || 0
                    },
                    "vertical": {
                        "unit": "pixelsUnit",
                        "value": dy || 0
                    }
                }
            };

            return adapter.call("move", moveArgs);
        });
    };

    /**
     * Copies a layer and moves it
     * If index is null, will copy the selected layer
     *
     * @param {?number=} index Index of the layer to copy, default is currently selected layer
     * @param {?number} dx Pixel value to move the copied layer horizontally (Default 0)
     * @param {?number} dy Pixel value to move the copied layer vertically (Default 0)
     * @return {Promise.<Object>} Promise that resolves to empty object
     */
    LayerManager.prototype.copyLayer = function (index, dx, dy) {
        var nullArgs = { "ref": "$Lyr" };

        if (index !== null) {
            nullArgs.index = index;
        } else {
            nullArgs.enum = "$Ordn";
            nullArgs.value = "$Trgt";
        }

        var selectArgs = {"null": nullArgs};

        // If index is given, this ensures that the layer with given index is selected first
        // Otherwise, is a no-op and will move on to copying the layer
        return adapter.call("$slct", selectArgs).then(function () {
            var copyArgs = { "null": nullArgs };

            copyArgs.to = {
                "obj": "Offset",
                "value": {
                    "horizontal": {
                        "unit": "pixelsUnit",
                        "value": dx || 0
                    },
                    "vertical": {
                        "unit": "pixelsUnit",
                        "value": dy || 0
                    }
                }
            };

            return adapter.call("copyEvent", copyArgs);
        });
    };

    /** @type {LayerManager} The LayerManager singleton */
    var theLayerManager = new LayerManager();

    module.exports = theLayerManager;

});
<|endoftext|>


<commit_before>import MapGenerator from './map-generator';
import stringify    from './stringify';
import warnOnce     from './warn-once';
import Result       from './result';
import parse        from './parse';
import Root         from './root';

function isPromise(obj) {
    return typeof obj === 'object' && typeof obj.then === 'function';
}

export default class LazyResult {

    constructor(processor, css, opts) {
        this.stringified = false;
        this.processed   = false;

        let root;
        if ( css instanceof Root ) {
            root = css;
        } else if ( css instanceof LazyResult || css instanceof Result ) {
            root = css.root;
            if ( css.map && typeof opts.map === 'undefined' ) {
                opts.map = { prev: css.map };
            }
        } else {
            let parser = parse;
            if ( opts.syntax )  parser = opts.syntax.parser;
            if ( opts.parser )   parser = opts.parser;
            if ( parser.parser ) parser = parser.parser;

            try {
                root = parser(css, opts);
            } catch (error) {
                this.error = error;
            }
        }

        this.result = new Result(processor, root, opts);
    }

    get processor() {
        return this.result.processor;
    }

    get opts() {
        return this.result.opts;
    }

    get css() {
        return this.stringify().css;
    }

    get content() {
        return this.stringify().content;
    }

    get map() {
        return this.stringify().map;
    }

    get root() {
        return this.sync().root;
    }

    get messages() {
        return this.sync().messages;
    }

    warnings() {
        return this.sync().warnings();
    }

    toString() {
        return this.css;
    }

    then(onFulfilled, onRejected) {
        return this.async().then(onFulfilled, onRejected);
    }

    catch(onRejected) {
        return this.async().catch(onRejected);
    }

    handleError(error, plugin) {
        try {
            this.error = error;
            if ( error.name === 'CssSyntaxError' && !error.plugin ) {
                error.plugin = plugin.postcssPlugin;
                error.setMessage();
            } else if ( plugin.postcssVersion ) {
                let pluginName = plugin.postcssPlugin;
                let pluginVer  = plugin.postcssVersion;
                let runtimeVer = this.result.processor.version;
                let a = pluginVer.split('.');
                let b = runtimeVer.split('.');

                if ( a[0] !== b[0] || parseInt(a[1]) > parseInt(b[1]) ) {
                    warnOnce(`Your current PostCSS version is ${runtimeVer}, ` +
                             `but ${pluginName} uses ${pluginVer}. Perhaps ` +
                             `this is the source of the error below.`);
                }
            }
        } catch (err) {
            if ( console && console.error ) console.error(err);
        }
    }

    asyncTick(resolve, reject) {
        if (this.plugin >= this.processor.plugins.length) {
            this.processed = true;
            return resolve();
        }

        try {
            let plugin  = this.processor.plugins[this.plugin];
            let promise = this.run(plugin);
            this.plugin += 1;

            if ( isPromise(promise) ) {
                promise.then( () => {
                    this.asyncTick(resolve, reject);
                }).catch( (error) => {
                    this.handleError(error, plugin);
                    this.processed = true;
                    reject(error);
                });
            } else {
                this.asyncTick(resolve, reject);
            }

        } catch (error) {
            this.processed = true;
            reject(error);
        }
    }

    async() {
        if ( this.processed ) {
            return new Promise( (resolve, reject) => {
                if ( this.error ) {
                    reject(this.error);
                } else {
                    resolve(this.stringify());
                }
            });
        }
        if ( this.processing ) {
            return this.processing;
        }

        this.processing = new Promise( (resolve, reject) => {
            if ( this.error ) return reject(this.error);
            this.plugin = 0;
            this.asyncTick(resolve, reject);
        }).then( () => {
            this.processed = true;
            return this.stringify();
        });

        return this.processing;
    }

    sync() {
        if ( this.processed ) return this.result;
        this.processed = true;

        if ( this.processing ) {
            throw new Error(
                'Use process(css).then(cb) to work with async plugins');
        }

        if ( this.error ) throw this.error;

        for ( let plugin of this.result.processor.plugins ) {
            let promise = this.run(plugin);
            if ( isPromise(promise) ) {
                throw new Error(
                    'Use process(css).then(cb) to work with async plugins');
            }
        }

        return this.result;
    }

    run(plugin) {
        this.result.lastPlugin = plugin;

        try {
            return plugin(this.result.root, this.result);
        } catch (error) {
            this.handleError(error, plugin);
            throw error;
        }
    }

    stringify() {
        if ( this.stringified ) return this.result;
        this.stringified = true;

        this.sync();

        let opts = this.result.opts;
        let str  = stringify;
        if ( opts.syntax )    str = opts.syntax.stringifier;
        if ( opts.stringifier ) str = opts.stringifier;
        if ( str.stringifier )  str = str.stringifier;

        let map  = new MapGenerator(str, this.result.root, this.result.opts);
        let data = map.generate();
        this.result.css = data[0];
        this.result.map = data[1];

        return this.result;
    }

}
<commit_msg>Better check for Root<commit_after>import MapGenerator from './map-generator';
import stringify    from './stringify';
import warnOnce     from './warn-once';
import Result       from './result';
import parse        from './parse';

function isPromise(obj) {
    return typeof obj === 'object' && typeof obj.then === 'function';
}

export default class LazyResult {

    constructor(processor, css, opts) {
        this.stringified = false;
        this.processed   = false;

        let root;
        if ( typeof css === 'object' && css.type === 'root' ) {
            root = css;
        } else if ( css instanceof LazyResult || css instanceof Result ) {
            root = css.root;
            if ( css.map && typeof opts.map === 'undefined' ) {
                opts.map = { prev: css.map };
            }
        } else {
            let parser = parse;
            if ( opts.syntax )  parser = opts.syntax.parser;
            if ( opts.parser )   parser = opts.parser;
            if ( parser.parser ) parser = parser.parser;

            try {
                root = parser(css, opts);
            } catch (error) {
                this.error = error;
            }
        }

        this.result = new Result(processor, root, opts);
    }

    get processor() {
        return this.result.processor;
    }

    get opts() {
        return this.result.opts;
    }

    get css() {
        return this.stringify().css;
    }

    get content() {
        return this.stringify().content;
    }

    get map() {
        return this.stringify().map;
    }

    get root() {
        return this.sync().root;
    }

    get messages() {
        return this.sync().messages;
    }

    warnings() {
        return this.sync().warnings();
    }

    toString() {
        return this.css;
    }

    then(onFulfilled, onRejected) {
        return this.async().then(onFulfilled, onRejected);
    }

    catch(onRejected) {
        return this.async().catch(onRejected);
    }

    handleError(error, plugin) {
        try {
            this.error = error;
            if ( error.name === 'CssSyntaxError' && !error.plugin ) {
                error.plugin = plugin.postcssPlugin;
                error.setMessage();
            } else if ( plugin.postcssVersion ) {
                let pluginName = plugin.postcssPlugin;
                let pluginVer  = plugin.postcssVersion;
                let runtimeVer = this.result.processor.version;
                let a = pluginVer.split('.');
                let b = runtimeVer.split('.');

                if ( a[0] !== b[0] || parseInt(a[1]) > parseInt(b[1]) ) {
                    warnOnce(`Your current PostCSS version is ${runtimeVer}, ` +
                             `but ${pluginName} uses ${pluginVer}. Perhaps ` +
                             `this is the source of the error below.`);
                }
            }
        } catch (err) {
            if ( console && console.error ) console.error(err);
        }
    }

    asyncTick(resolve, reject) {
        if (this.plugin >= this.processor.plugins.length) {
            this.processed = true;
            return resolve();
        }

        try {
            let plugin  = this.processor.plugins[this.plugin];
            let promise = this.run(plugin);
            this.plugin += 1;

            if ( isPromise(promise) ) {
                promise.then( () => {
                    this.asyncTick(resolve, reject);
                }).catch( (error) => {
                    this.handleError(error, plugin);
                    this.processed = true;
                    reject(error);
                });
            } else {
                this.asyncTick(resolve, reject);
            }

        } catch (error) {
            this.processed = true;
            reject(error);
        }
    }

    async() {
        if ( this.processed ) {
            return new Promise( (resolve, reject) => {
                if ( this.error ) {
                    reject(this.error);
                } else {
                    resolve(this.stringify());
                }
            });
        }
        if ( this.processing ) {
            return this.processing;
        }

        this.processing = new Promise( (resolve, reject) => {
            if ( this.error ) return reject(this.error);
            this.plugin = 0;
            this.asyncTick(resolve, reject);
        }).then( () => {
            this.processed = true;
            return this.stringify();
        });

        return this.processing;
    }

    sync() {
        if ( this.processed ) return this.result;
        this.processed = true;

        if ( this.processing ) {
            throw new Error(
                'Use process(css).then(cb) to work with async plugins');
        }

        if ( this.error ) throw this.error;

        for ( let plugin of this.result.processor.plugins ) {
            let promise = this.run(plugin);
            if ( isPromise(promise) ) {
                throw new Error(
                    'Use process(css).then(cb) to work with async plugins');
            }
        }

        return this.result;
    }

    run(plugin) {
        this.result.lastPlugin = plugin;

        try {
            return plugin(this.result.root, this.result);
        } catch (error) {
            this.handleError(error, plugin);
            throw error;
        }
    }

    stringify() {
        if ( this.stringified ) return this.result;
        this.stringified = true;

        this.sync();

        let opts = this.result.opts;
        let str  = stringify;
        if ( opts.syntax )    str = opts.syntax.stringifier;
        if ( opts.stringifier ) str = opts.stringifier;
        if ( str.stringifier )  str = str.stringifier;

        let map  = new MapGenerator(str, this.result.root, this.result.opts);
        let data = map.generate();
        this.result.css = data[0];
        this.result.map = data[1];

        return this.result;
    }

}
<|endoftext|>