<commit_before>// ==========================================================================
// Project:   MySystem - mainPage
// Copyright: ©2010 Concord Consortium
// ==========================================================================
/*globals MySystem LinkIt SCUI */

sc_require('views/node');
sc_require('views/property_editor');
sc_require('views/node_palette');
sc_require('views/sentence');
sc_require('views/sentence_connect_pane');

// This page describes the main user interface for your application.
MySystem.mainPage = SC.Page.design({

  // The main pane is made visible on screen as soon as your app is loaded.
  // Add childViews to this pane for views to display immediately on page
  // load.
  mainPane: SC.MainPane.design({
    defaultResponder: 'MySystem.statechart',
    childViews: 'topView'.w(),
    topView: SC.SplitView.design({
      defaultThickness: 140,
      topLeftView: MySystem.NodePaletteView.design({ // Node Palette (left)
        layout: { top: 0, bottom: 0, left: 15 }
      }),
      dividerView: SC.SplitDividerView, // Divider for resizing right/left
      bottomRightView: SC.SplitView.design({ // Rest of app (right)
        defaultThickness: 150,
        layoutDirection: SC.LAYOUT_VERTICAL,
        topLeftView: MySystem.StoriesView, // Story section
        dividerView: SC.SplitDividerView, // Divider for resizing up/down
        bottomRightView: MySystem.CanvasView.design({
          layout: { top: 120, left: 0, right: 0, bottom: 0 },
          contentBinding: SC.Binding.from('MySystem.nodesController'),
          selectionBinding: 'MySystem.nodesController.selection',
          linkSelectionBinding: 'MySystem.nodesController.linkSelection',
          exampleView: MySystem.NodeView
        })
      })
    })
  }),

  propertyViewPane: MySystem.PropertyEditorPane,

  sentenceLinkPane: MySystem.SentenceConnectPane,

  transformationBuilderPane: MySystem.TransformationBuilderPane.design({}),

  transformationAnnotaterPane: MySystem.TransformationAnnotationPane.design({})
});
<commit_msg>make palette scrollable<commit_after>// ==========================================================================
// Project:   MySystem - mainPage
// Copyright: ©2010 Concord Consortium
// ==========================================================================
/*globals MySystem LinkIt SCUI */

sc_require('views/node');
sc_require('views/property_editor');
sc_require('views/node_palette');
sc_require('views/sentence');
sc_require('views/sentence_connect_pane');

// This page describes the main user interface for your application.
MySystem.mainPage = SC.Page.design({

  // The main pane is made visible on screen as soon as your app is loaded.
  // Add childViews to this pane for views to display immediately on page
  // load.
  mainPane: SC.MainPane.design({
    defaultResponder: 'MySystem.statechart',
    childViews: 'topView'.w(),
    topView: SC.SplitView.design({
      defaultThickness: 140,
      topLeftView: SC.ScrollView.design({
        contentView: MySystem.NodePaletteView.design({
          layout: { top: 0, bottom: 0, left: 0 }
        })
      }),
      dividerView: SC.SplitDividerView, // Divider for resizing right/left
      bottomRightView: SC.SplitView.design({ // Rest of app (right)
        defaultThickness: 150,
        layoutDirection: SC.LAYOUT_VERTICAL,
        topLeftView: MySystem.StoriesView, // Story section
        dividerView: SC.SplitDividerView, // Divider for resizing up/down
        bottomRightView: MySystem.CanvasView.design({
          layout: { top: 120, left: 0, right: 0, bottom: 0 },
          contentBinding: SC.Binding.from('MySystem.nodesController'),
          selectionBinding: 'MySystem.nodesController.selection',
          linkSelectionBinding: 'MySystem.nodesController.linkSelection',
          exampleView: MySystem.NodeView
        })
      })
    })
  }),

  propertyViewPane: MySystem.PropertyEditorPane,

  sentenceLinkPane: MySystem.SentenceConnectPane,

  transformationBuilderPane: MySystem.TransformationBuilderPane.design({}),

  transformationAnnotaterPane: MySystem.TransformationAnnotationPane.design({})
});
<|endoftext|>


<commit_before>if (typeof module !== "undefined") {
    let BoundingBox2D = require('./BoundingBox2D');
}

/**
 *  Polygon2D
 *
 *  @param {Array<Point2D>} points
 *  @returns {Polygon2D}
 */
function Polygon2D(points) {
    Object.defineProperties(this, {
        "points": {
            value: (points !== undefined) ? points : [],
            writable: false,
            enumerable: true,
            configurable: false
        }
    });
}

/**
 *  getBoundingBox
 *
 *  @returns {BoundingBox2D}
 */
Polygon2D.prototype.getBoundingBox = function() {
    if (this.points.length > 0) {
        var min = this.points[0];
        var max = this.points[0];

        for (var i = 1; i < this.points.length; i++) {
            let point = this.points[i];

            min = min.min(points);
            max = max.max(points);
        }

        return new BoundingBox2D(
            min.x,
            min.y,
            max.x - min.x,
            max.y - max.y
        );
    }
    else {
        return new BoundingBox2D(0, 0, 0, 0);
    }
};

/**
 *  tesselate
 *
 *  @returns {Polygon2D}
 */
Polygon2D.prototype.tesselate = function() {
    return this;
};

if (typeof module !== "undefined") {
    module.exports = Polygon2D;
}
<commit_msg>Add toString method<commit_after>if (typeof module !== "undefined") {
    let BoundingBox2D = require('./BoundingBox2D');
}

/**
 *  Polygon2D
 *
 *  @param {Array<Point2D>} points
 *  @returns {Polygon2D}
 */
function Polygon2D(points) {
    Object.defineProperties(this, {
        "points": {
            value: (points !== undefined) ? points : [],
            writable: false,
            enumerable: true,
            configurable: false
        }
    });
}

/**
 *  getBoundingBox
 *
 *  @returns {BoundingBox2D}
 */
Polygon2D.prototype.getBoundingBox = function() {
    if (this.points.length > 0) {
        var min = this.points[0];
        var max = this.points[0];

        for (var i = 1; i < this.points.length; i++) {
            let point = this.points[i];

            min = min.min(points);
            max = max.max(points);
        }

        return new BoundingBox2D(
            min.x,
            min.y,
            max.x - min.x,
            max.y - max.y
        );
    }
    else {
        return new BoundingBox2D(0, 0, 0, 0);
    }
};

/**
 *  tesselate
 *
 *  @returns {Polygon2D}
 */
Polygon2D.prototype.tesselate = function() {
    return this;
};

/**
 *  toString
 *
 *  @returns {String}
 */
Polygon2D.prototype.toString = function() {
    return this.points.map(p => {
        return `${p.x}, ${p.y}`;
    }).join(" ");
};

if (typeof module !== "undefined") {
    module.exports = Polygon2D;
}
<|endoftext|>


<commit_before>var EventEmitter = require('events').EventEmitter;
var util = require('util');
var contextify = require('contextify');
var mpath = require('mpath');

function PuzzleBox() {
  EventEmitter.call(this);
  this._code = '';
  this._calls = [];
}

util.inherits(PuzzleBox, EventEmitter);

// set the code
PuzzleBox.prototype.code = function(code) {
  this._code = code;
  return this;
};

// set the context object
PuzzleBox.prototype.context = function(context) {
  this.dispose();
  this._context = context;
  return this;
};

// spy on things in the context
// TODO: field accesses and sets
PuzzleBox.prototype.track = function(key, cb) {
  var newFn = this.createReplacement(key, mpath.get(key, this._context));
  mpath.set(key, newFn, this._context);
  return this;
};

// create the sandbox
PuzzleBox.prototype.build = function() {
  // create a global callback
  var that = this;
  this._context.finished = function(){
    process.nextTick(function(){
      that.emit('finished');
    });
  };

  this._sandbox = contextify(this._context);
  return this;
};

// get the sandbox data
PuzzleBox.prototype.sandbox = function(){
  return this._sandbox.getGlobal();
};

// get the call data
PuzzleBox.prototype.calls = function(){
  return this._calls;
};

// build and execute the code
PuzzleBox.prototype.run = function() {
  this.build();
  this.emit('started');
  this._sandbox.run(this._code);
  return this;
};

// clear the memory
PuzzleBox.prototype.dispose = function(){
  if (this._sandbox) {
    this._sandbox.dispose();
    delete this._sandbox;
  }
  return this;
};

// wrap a function
PuzzleBox.prototype.createReplacement = function(name, fn) {
  var that = this;
  var outFn = function(){
    var args = Array.prototype.slice.call(arguments);
    var scope = this;
    var result = fn.apply(scope, arguments);
    var call = {
      fn: name,
      args: args,
      result: result
    };
    that._calls.push(call);
    that.emit('call', call);
    return call.result;
  };
  return outFn;
};

module.exports = PuzzleBox;<commit_msg>notes<commit_after>var EventEmitter = require('events').EventEmitter;
var util = require('util');
var contextify = require('contextify');
var mpath = require('mpath');

function PuzzleBox() {
  EventEmitter.call(this);
  this._code = '';
  this._calls = [];
}

util.inherits(PuzzleBox, EventEmitter);

// set the code
PuzzleBox.prototype.code = function(code) {
  this._code = code;
  return this;
};

// set the context object
PuzzleBox.prototype.context = function(context) {
  this.dispose();
  this._context = context;
  return this;
};

// spy on things in the context
// TODO: field accesses and sets
PuzzleBox.prototype.track = function(key, cb) {
  var newFn = this.createReplacement(key, mpath.get(key, this._context));
  mpath.set(key, newFn, this._context);
  return this;
};

// create the sandbox
PuzzleBox.prototype.build = function() {
  // create a global callback
  var that = this;
  this._context.finished = function(){
    process.nextTick(function(){
      that.emit('finished');
    });
  };

  this._sandbox = contextify(this._context);
  return this;
};

// get the sandbox data
PuzzleBox.prototype.sandbox = function(){
  return this._sandbox.getGlobal();
};

// get the call data
PuzzleBox.prototype.calls = function(){
  return this._calls;
};

// build and execute the code
PuzzleBox.prototype.run = function() {
  this.build();
  this.emit('started');
  this._sandbox.run(this._code);
  return this;
};

// clear the memory
PuzzleBox.prototype.dispose = function(){
  if (this._sandbox) {
    this._sandbox.dispose();
    delete this._sandbox;
  }
  return this;
};

// wrap a function
// TODO: also wrap this in a puzzle-box
PuzzleBox.prototype.createReplacement = function(name, fn) {
  var that = this;
  var outFn = function(){
    var args = Array.prototype.slice.call(arguments);
    var scope = this;
    var result = fn.apply(scope, arguments);
    var call = {
      fn: name,
      args: args,
      result: result
    };
    that._calls.push(call);
    that.emit('call', call);
    return call.result;
  };
  return outFn;
};

module.exports = PuzzleBox;<|endoftext|>


<commit_before>import React, { Component } from "react";
import ReactDOM from "react-dom";
import { DragDropContext } from "react-dnd";
import HTML5Backend from "react-dnd-html5-backend";
import Suggestions from "./Suggestions";
import PropTypes from "prop-types";
import Tag from "./Tag";

// Constants
const Keys = {
  ENTER: 13,
  TAB: 9,
  BACKSPACE: 8,
  UP_ARROW: 38,
  DOWN_ARROW: 40,
  ESCAPE: 27,
};

const DEFAULT_PLACEHOLDER = "Add new tag";

const DefaultClassNames = {
  tags: "ReactTags__tags",
  tagInput: "ReactTags__tagInput",
  tagInputField: "ReactTags__tagInputField",
  selected: "ReactTags__selected",
  tag: "ReactTags__tag",
  remove: "ReactTags__remove",
  suggestions: "ReactTags__suggestions",
  activeSuggestion: "ReactTags__activeSuggestion",
};

class ReactTags extends Component {
  constructor(props) {
    super(props);

    this.state = {
      suggestions: this.props.suggestions,
      query: "",
      isFocused: false,
      selectedIndex: -1,
      selectionMode: false,
    };

    this.handleFocus = this.handleFocus.bind(this);
    this.handleBlur = this.handleBlur.bind(this);
    this.handleKeyDown = this.handleKeyDown.bind(this);
    this.handleChange = this.handleChange.bind(this);
    this.moveTag = this.moveTag.bind(this);
    this.handlePaste = this.handlePaste.bind(this);
    this.resetAndFocusInput = this.resetAndFocusInput.bind(this);
    this.handleSuggestionHover = this.handleSuggestionHover.bind(this);
    this.handleSuggestionClick = this.handleSuggestionClick.bind(this);
  }

  componentWillMount() {
    this.setState({
      classNames: { ...DefaultClassNames, ...this.props.classNames },
    });
  }

  resetAndFocusInput() {
    this.textInput.value = "";
    this.textInput.focus();
  }

  componentDidMount() {
    const { autofocus, readOnly } = this.props;
    if (autofocus && !readOnly) {
      this.resetAndFocusInput();
    }
  }

  filteredSuggestions(query, suggestions) {
    if (this.props.handleFilterSuggestions) {
      return this.props.handleFilterSuggestions(query, suggestions);
    }

    return suggestions.filter(function(item) {
      return item.toLowerCase().indexOf(query.toLowerCase()) === 0;
    });
  }

  componentWillReceiveProps(props) {
    const suggestions = this.filteredSuggestions(
      this.state.query,
      props.suggestions
    );
    this.setState({
      suggestions: suggestions,
      classNames: { ...DefaultClassNames, ...props.classNames },
    });
  }

  handleDelete(i, e) {
    this.props.handleDelete(i, e);
    this.setState({ query: "" });
    this.resetAndFocusInput();
    e.stopPropagation();
  }

  handleTagClick(i, e) {
    if (this.props.handleTagClick) {
      this.props.handleTagClick(i, e);
    }

    this.setState({ query: "" });
    this.resetAndFocusInput();
  }

  handleChange(e) {
    if (this.props.handleInputChange) {
      this.props.handleInputChange(e.target.value.trim());
    }

    const query = e.target.value.trim();
    const suggestions = this.filteredSuggestions(query, this.props.suggestions);

    let selectedIndex = this.state.selectedIndex;
    if (selectedIndex >= suggestions.length) {
      selectedIndex = suggestions.length - 1;
    }

    this.setState({
      query: query,
      suggestions: suggestions,
      selectedIndex: selectedIndex,
    });
  }

  handleFocus() {
    this.setState({ isFocused: true });
  }

  handleBlur(e) {
    const value = e.target.value.trim();
    if (this.props.handleInputBlur) {
      this.props.handleInputBlur(value);
      this.textInput.value = "";
    }
    this.setState({ isFocused: false });
  }

  handleKeyDown(e) {
    let { query, selectedIndex, suggestions } = this.state;

    // hide suggestions menu on escape
    if (e.keyCode === Keys.ESCAPE) {
      e.preventDefault();
      e.stopPropagation();
      this.setState({
        selectedIndex: -1,
        selectionMode: false,
        suggestions: [],
      });
    }

    // When one of the terminating keys is pressed, add current query to the tags.
    // If no text is typed in so far, ignore the action - so we don't end up with a terminating
    // character typed in.
    if (this.props.delimiters.indexOf(e.keyCode) !== -1 && !e.shiftKey) {
      if (e.keyCode !== Keys.TAB || query !== "") {
        e.preventDefault();
      }

      if (this.state.selectionMode && this.state.selectedIndex != -1) {
        query = this.state.suggestions[this.state.selectedIndex];
      }
      if (query !== "") {
        this.addTag(query);
      }
    }

    // when backspace key is pressed and query is blank, delete tag
    if (
      e.keyCode === Keys.BACKSPACE &&
      query == "" &&
      this.props.allowDeleteFromEmptyInput
    ) {
      this.handleDelete(this.props.tags.length - 1, e);
    }

    // up arrow
    if (e.keyCode === Keys.UP_ARROW) {
      e.preventDefault();

      let { selectedIndex, suggestions } = this.state;

      selectedIndex =
        selectedIndex <= 0 ? suggestions.length - 1 : selectedIndex - 1;

      this.setState({
        selectedIndex: selectedIndex,
        selectionMode: true,
      });
    }

    // down arrow
    if (e.keyCode === Keys.DOWN_ARROW) {
      e.preventDefault();
      this.setState({
        selectedIndex: (this.state.selectedIndex + 1) % suggestions.length,
        selectionMode: true,
      });
    }
  }

  handlePaste(e) {
    if (!this.props.allowAdditionFromPaste) {
        return;
    }

    e.preventDefault();

    // See: http://stackoverflow.com/a/6969486/1463681
    const escapeRegex = str =>
      str.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&");

    // Used to determine how the pasted content is split.
    const delimiterChars = escapeRegex(
      this.props.delimiters
        .map(delimiter => {
          // See: http://stackoverflow.com/a/34711175/1463681
          const chrCode = delimiter - 48 * Math.floor(delimiter / 48);
          return String.fromCharCode(96 <= delimiter ? chrCode : delimiter);
        })
        .join("")
    );

    const clipboardData = e.clipboardData || window.clipboardData;
    const string = clipboardData.getData("text");
    const regExp = new RegExp(`[${delimiterChars}]+`);
    string.split(regExp).forEach(tag => this.props.handleAddition(tag));
  }

  addTag(tag) {
    if (this.props.autocomplete) {
      const possibleMatches = this.filteredSuggestions(
        tag,
        this.props.suggestions
      );

      if (
        (this.props.autocomplete === 1 && possibleMatches.length === 1) ||
        (this.props.autocomplete === true && possibleMatches.length)
      ) {
        tag = possibleMatches[0];
      }
    }

    // call method to add
    this.props.handleAddition(tag);

    // reset the state
    this.setState({
      query: "",
      selectionMode: false,
      selectedIndex: -1,
    });

    this.resetAndFocusInput();
  }

  handleSuggestionClick(i, e) {
    this.addTag(this.state.suggestions[i]);
  }

  handleSuggestionHover(i, e) {
    this.setState({
      selectedIndex: i,
      selectionMode: true,
    });
  }

  moveTag(dragIndex, hoverIndex) {
    const tags = this.props.tags;

    // locate tags
    const dragTag = tags[dragIndex];

    // call handler with the index of the dragged tag
    // and the tag that is hovered
    this.props.handleDrag(dragTag, dragIndex, hoverIndex);
  }

  render() {
    const moveTag = this.props.handleDrag ? this.moveTag : null;

    const tagItems = this.props.tags.map(
      function(tag, i) {
        return (
          <Tag
            key={tag.id ? tag.id : i}
            index={i}
            tag={tag}
            labelField={this.props.labelField}
            onDelete={this.handleDelete.bind(this, i)}
            moveTag={moveTag}
            removeComponent={this.props.removeComponent}
            onTagClicked={this.handleTagClick.bind(this, i)}
            readOnly={this.props.readOnly}
            classNames={this.state.classNames}
          />
        );
      }.bind(this)
    );

    // get the suggestions for the given query
    const query = this.state.query.trim(),
      selectedIndex = this.state.selectedIndex,
      suggestions = this.state.suggestions,
      placeholder = this.props.placeholder,
      inputName = this.props.name,
      inputId = this.props.id,
      maxLength = this.props.maxLength;

    const tagInput = !this.props.readOnly ? (

        <input
          ref={input => {
            this.textInput = input;
          }}
          className={this.state.classNames.tagInputField}
          type="text"
          placeholder={placeholder}
          aria-label={placeholder}
          onFocus={this.handleFocus}
          onBlur={this.handleBlur}
          onChange={this.handleChange}
          onKeyDown={this.handleKeyDown}
          onPaste={this.handlePaste}
          name={inputName}
          id={inputId}
          maxLength={maxLength}
          value={this.props.inputValue}
        />

        <Suggestions
          query={query}
          suggestions={suggestions}
          selectedIndex={selectedIndex}
          handleClick={this.handleSuggestionClick}
          handleHover={this.handleSuggestionHover}
          minQueryLength={this.props.minQueryLength}
          shouldRenderSuggestions={this.props.shouldRenderSuggestions}
          isFocused={this.state.isFocused}
          classNames={this.state.classNames}
        />

    ) : null;

    return (

          {tagItems}
          {this.props.inline && tagInput}

        {!this.props.inline && tagInput}

    );
  }
}

ReactTags.propTypes = {
  placeholder: PropTypes.string,
  labelField: PropTypes.string,
  suggestions: PropTypes.array,
  delimiters: PropTypes.array,
  autofocus: PropTypes.bool,
  inline: PropTypes.bool,
  handleDelete: PropTypes.func.isRequired,
  handleAddition: PropTypes.func.isRequired,
  handleDrag: PropTypes.func,
  handleFilterSuggestions: PropTypes.func,
  handleTagClick: PropTypes.func,
  allowDeleteFromEmptyInput: PropTypes.bool,
  allowAdditionFromPaste: PropTypes.bool,
  handleInputChange: PropTypes.func,
  handleInputBlur: PropTypes.func,
  minQueryLength: PropTypes.number,
  shouldRenderSuggestions: PropTypes.func,
  removeComponent: PropTypes.func,
  autocomplete: PropTypes.oneOfType([PropTypes.bool, PropTypes.number]),
  readOnly: PropTypes.bool,
  classNames: PropTypes.object,
  name: PropTypes.string,
  id: PropTypes.string,
  maxLength: PropTypes.string,
  inputValue: PropTypes.string,
};

ReactTags.defaultProps = {
  placeholder: DEFAULT_PLACEHOLDER,
  tags: [],
  suggestions: [],
  delimiters: [Keys.ENTER, Keys.TAB],
  autofocus: true,
  inline: true,
  allowDeleteFromEmptyInput: true,
  allowAdditionFromPaste: true,
  minQueryLength: 2,
  autocomplete: false,
  readOnly: false,
};

module.exports = {
  WithContext: DragDropContext(HTML5Backend)(ReactTags),
  WithOutContext: ReactTags,
  Keys: Keys,
};
<commit_msg>new prop: resetInputOnDelete (#135)<commit_after>import React, { Component } from "react";
import ReactDOM from "react-dom";
import { DragDropContext } from "react-dnd";
import HTML5Backend from "react-dnd-html5-backend";
import Suggestions from "./Suggestions";
import PropTypes from "prop-types";
import Tag from "./Tag";

// Constants
const Keys = {
  ENTER: 13,
  TAB: 9,
  BACKSPACE: 8,
  UP_ARROW: 38,
  DOWN_ARROW: 40,
  ESCAPE: 27,
};

const DEFAULT_PLACEHOLDER = "Add new tag";

const DefaultClassNames = {
  tags: "ReactTags__tags",
  tagInput: "ReactTags__tagInput",
  tagInputField: "ReactTags__tagInputField",
  selected: "ReactTags__selected",
  tag: "ReactTags__tag",
  remove: "ReactTags__remove",
  suggestions: "ReactTags__suggestions",
  activeSuggestion: "ReactTags__activeSuggestion",
};

class ReactTags extends Component {
  constructor(props) {
    super(props);

    this.state = {
      suggestions: this.props.suggestions,
      query: "",
      isFocused: false,
      selectedIndex: -1,
      selectionMode: false,
    };

    this.handleFocus = this.handleFocus.bind(this);
    this.handleBlur = this.handleBlur.bind(this);
    this.handleKeyDown = this.handleKeyDown.bind(this);
    this.handleChange = this.handleChange.bind(this);
    this.moveTag = this.moveTag.bind(this);
    this.handlePaste = this.handlePaste.bind(this);
    this.resetAndFocusInput = this.resetAndFocusInput.bind(this);
    this.handleSuggestionHover = this.handleSuggestionHover.bind(this);
    this.handleSuggestionClick = this.handleSuggestionClick.bind(this);
  }

  componentWillMount() {
    this.setState({
      classNames: { ...DefaultClassNames, ...this.props.classNames },
    });
  }

  resetAndFocusInput() {
    this.setState({ query: "" });
    this.textInput.value = "";
    this.textInput.focus();
  }

  componentDidMount() {
    const { autofocus, readOnly } = this.props;
    if (autofocus && !readOnly) {
      this.resetAndFocusInput();
    }
  }

  filteredSuggestions(query, suggestions) {
    if (this.props.handleFilterSuggestions) {
      return this.props.handleFilterSuggestions(query, suggestions);
    }

    return suggestions.filter(function(item) {
      return item.toLowerCase().indexOf(query.toLowerCase()) === 0;
    });
  }

  componentWillReceiveProps(props) {
    const suggestions = this.filteredSuggestions(
      this.state.query,
      props.suggestions
    );
    this.setState({
      suggestions: suggestions,
      classNames: { ...DefaultClassNames, ...props.classNames },
    });
  }

  handleDelete(i, e) {
    this.props.handleDelete(i, e);
    if (!this.props.resetInputOnDelete) {
        this.textInput.focus();
    } else {
        this.resetAndFocusInput();
    }
    e.stopPropagation();
  }

  handleTagClick(i, e) {
    if (this.props.handleTagClick) {
      this.props.handleTagClick(i, e);
    }

    if (!this.props.resetInputOnDelete) {
        this.textInput.focus();
    } else {
        this.resetAndFocusInput();
    }
  }

  handleChange(e) {
    if (this.props.handleInputChange) {
      this.props.handleInputChange(e.target.value.trim());
    }

    const query = e.target.value.trim();
    const suggestions = this.filteredSuggestions(query, this.props.suggestions);

    let selectedIndex = this.state.selectedIndex;
    if (selectedIndex >= suggestions.length) {
      selectedIndex = suggestions.length - 1;
    }

    this.setState({
      query: query,
      suggestions: suggestions,
      selectedIndex: selectedIndex,
    });
  }

  handleFocus() {
    this.setState({ isFocused: true });
  }

  handleBlur(e) {
    const value = e.target.value.trim();
    if (this.props.handleInputBlur) {
      this.props.handleInputBlur(value);
      this.textInput.value = "";
    }
    this.setState({ isFocused: false });
  }

  handleKeyDown(e) {
    let { query, selectedIndex, suggestions } = this.state;

    // hide suggestions menu on escape
    if (e.keyCode === Keys.ESCAPE) {
      e.preventDefault();
      e.stopPropagation();
      this.setState({
        selectedIndex: -1,
        selectionMode: false,
        suggestions: [],
      });
    }

    // When one of the terminating keys is pressed, add current query to the tags.
    // If no text is typed in so far, ignore the action - so we don't end up with a terminating
    // character typed in.
    if (this.props.delimiters.indexOf(e.keyCode) !== -1 && !e.shiftKey) {
      if (e.keyCode !== Keys.TAB || query !== "") {
        e.preventDefault();
      }

      if (this.state.selectionMode && this.state.selectedIndex != -1) {
        query = this.state.suggestions[this.state.selectedIndex];
      }
      if (query !== "") {
        this.addTag(query);
      }
    }

    // when backspace key is pressed and query is blank, delete tag
    if (
      e.keyCode === Keys.BACKSPACE &&
      query == "" &&
      this.props.allowDeleteFromEmptyInput
    ) {
      this.handleDelete(this.props.tags.length - 1, e);
    }

    // up arrow
    if (e.keyCode === Keys.UP_ARROW) {
      e.preventDefault();

      let { selectedIndex, suggestions } = this.state;

      selectedIndex =
        selectedIndex <= 0 ? suggestions.length - 1 : selectedIndex - 1;

      this.setState({
        selectedIndex: selectedIndex,
        selectionMode: true,
      });
    }

    // down arrow
    if (e.keyCode === Keys.DOWN_ARROW) {
      e.preventDefault();
      this.setState({
        selectedIndex: (this.state.selectedIndex + 1) % suggestions.length,
        selectionMode: true,
      });
    }
  }

  handlePaste(e) {
    if (!this.props.allowAdditionFromPaste) {
        return;
    }

    e.preventDefault();

    // See: http://stackoverflow.com/a/6969486/1463681
    const escapeRegex = str =>
      str.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&");

    // Used to determine how the pasted content is split.
    const delimiterChars = escapeRegex(
      this.props.delimiters
        .map(delimiter => {
          // See: http://stackoverflow.com/a/34711175/1463681
          const chrCode = delimiter - 48 * Math.floor(delimiter / 48);
          return String.fromCharCode(96 <= delimiter ? chrCode : delimiter);
        })
        .join("")
    );

    const clipboardData = e.clipboardData || window.clipboardData;
    const string = clipboardData.getData("text");
    const regExp = new RegExp(`[${delimiterChars}]+`);
    string.split(regExp).forEach(tag => this.props.handleAddition(tag));
  }

  addTag(tag) {
    if (this.props.autocomplete) {
      const possibleMatches = this.filteredSuggestions(
        tag,
        this.props.suggestions
      );

      if (
        (this.props.autocomplete === 1 && possibleMatches.length === 1) ||
        (this.props.autocomplete === true && possibleMatches.length)
      ) {
        tag = possibleMatches[0];
      }
    }

    // call method to add
    this.props.handleAddition(tag);

    // reset the state
    this.setState({
      query: "",
      selectionMode: false,
      selectedIndex: -1,
    });

    this.resetAndFocusInput();
  }

  handleSuggestionClick(i, e) {
    this.addTag(this.state.suggestions[i]);
  }

  handleSuggestionHover(i, e) {
    this.setState({
      selectedIndex: i,
      selectionMode: true,
    });
  }

  moveTag(dragIndex, hoverIndex) {
    const tags = this.props.tags;

    // locate tags
    const dragTag = tags[dragIndex];

    // call handler with the index of the dragged tag
    // and the tag that is hovered
    this.props.handleDrag(dragTag, dragIndex, hoverIndex);
  }

  render() {
    const moveTag = this.props.handleDrag ? this.moveTag : null;

    const tagItems = this.props.tags.map(
      function(tag, i) {
        return (
          <Tag
            key={tag.id ? tag.id : i}
            index={i}
            tag={tag}
            labelField={this.props.labelField}
            onDelete={this.handleDelete.bind(this, i)}
            moveTag={moveTag}
            removeComponent={this.props.removeComponent}
            onTagClicked={this.handleTagClick.bind(this, i)}
            readOnly={this.props.readOnly}
            classNames={this.state.classNames}
          />
        );
      }.bind(this)
    );

    // get the suggestions for the given query
    const query = this.state.query.trim(),
      selectedIndex = this.state.selectedIndex,
      suggestions = this.state.suggestions,
      placeholder = this.props.placeholder,
      inputName = this.props.name,
      inputId = this.props.id,
      maxLength = this.props.maxLength;

    const tagInput = !this.props.readOnly ? (

        <input
          ref={input => {
            this.textInput = input;
          }}
          className={this.state.classNames.tagInputField}
          type="text"
          placeholder={placeholder}
          aria-label={placeholder}
          onFocus={this.handleFocus}
          onBlur={this.handleBlur}
          onChange={this.handleChange}
          onKeyDown={this.handleKeyDown}
          onPaste={this.handlePaste}
          name={inputName}
          id={inputId}
          maxLength={maxLength}
          value={this.props.inputValue}
        />

        <Suggestions
          query={query}
          suggestions={suggestions}
          selectedIndex={selectedIndex}
          handleClick={this.handleSuggestionClick}
          handleHover={this.handleSuggestionHover}
          minQueryLength={this.props.minQueryLength}
          shouldRenderSuggestions={this.props.shouldRenderSuggestions}
          isFocused={this.state.isFocused}
          classNames={this.state.classNames}
        />

    ) : null;

    return (

          {tagItems}
          {this.props.inline && tagInput}

        {!this.props.inline && tagInput}

    );
  }
}

ReactTags.propTypes = {
  placeholder: PropTypes.string,
  labelField: PropTypes.string,
  suggestions: PropTypes.array,
  delimiters: PropTypes.array,
  autofocus: PropTypes.bool,
  inline: PropTypes.bool,
  handleDelete: PropTypes.func.isRequired,
  handleAddition: PropTypes.func.isRequired,
  handleDrag: PropTypes.func,
  handleFilterSuggestions: PropTypes.func,
  handleTagClick: PropTypes.func,
  allowDeleteFromEmptyInput: PropTypes.bool,
  allowAdditionFromPaste: PropTypes.bool,
  resetInputOnDelete: PropTypes.bool,
  handleInputChange: PropTypes.func,
  handleInputBlur: PropTypes.func,
  minQueryLength: PropTypes.number,
  shouldRenderSuggestions: PropTypes.func,
  removeComponent: PropTypes.func,
  autocomplete: PropTypes.oneOfType([PropTypes.bool, PropTypes.number]),
  readOnly: PropTypes.bool,
  classNames: PropTypes.object,
  name: PropTypes.string,
  id: PropTypes.string,
  maxLength: PropTypes.string,
  inputValue: PropTypes.string,
};

ReactTags.defaultProps = {
  placeholder: DEFAULT_PLACEHOLDER,
  tags: [],
  suggestions: [],
  delimiters: [Keys.ENTER, Keys.TAB],
  autofocus: true,
  inline: true,
  allowDeleteFromEmptyInput: true,
  allowAdditionFromPaste: true,
  resetInputOnDelete: true,
  minQueryLength: 2,
  autocomplete: false,
  readOnly: false,
};

module.exports = {
  WithContext: DragDropContext(HTML5Backend)(ReactTags),
  WithOutContext: ReactTags,
  Keys: Keys,
};
<|endoftext|>


<commit_before>const path = require('path')

module.exports = {
  appenders: {
    // HTTP日志，请求日志
    http: {
      type: 'dateFile',
      filename: `${path.resolve(__dirname, '../logs/httpLogs/logs')}Http.log`,
      maxLogSize: 102400,
      backups: 1024,
    },

    // 系统日志，如：程序启动和db链接日志，框架错误，catch框架错误，db连接错误等
    sys: {
      type: 'dateFile',
      filename: `${path.resolve(__dirname, '../logs/sysLogs/logs')}Sys.log`,
      maxLogSize: 102400,
      backups: 1024,
    },

    // 登陆日志，所有登录登出等的日志
    login: {
      type: 'dateFile',
      filename: `${path.resolve(__dirname, '../logs/loginLogs/logs')}Login.log`,
      maxLogSize: 102400,
      backups: 1024,
    },

    // APIERROR日志，所有API请求产生的错误日志
    apiError: {
      type: 'dateFile',
      filename: `${path.resolve(__dirname, '../logs/apiErrorLogs/logs')}apiError.log`,
      maxLogSize: 102400,
      backups: 1024,
    },

    // 错误日志，所有的错误日志
    errorsFile: {
      type: 'dateFile',
      filename: `${path.resolve(__dirname, '../logs/errorsFileLogs/logs')}ErrorsFile.log`,
      maxLogSize: 102400,
      backups: 1024,
    },

    errors: {
      type: 'logLevelFilter',
      appender: 'errorsFile',
      level: 'error',
    },
    console: { type: 'console' },
  },
  categories: {
    default: { appenders: ['console'], level: 'info' },
    http: { appenders: ['http', 'errors'], level: 'info' },
    sys: { appenders: ['sys', 'console', 'errors'], level: 'info' },

    login: { appenders: ['login', 'errors'], level: 'info' },
    apiError: { appenders: ['apiError', 'errors'], level: 'info' },
  },
}
<commit_msg>日志注释修改<commit_after>const path = require('path')

module.exports = {
  appenders: {
    // HTTP日志，请求日志
    http: {
      type: 'dateFile',
      filename: `${path.resolve(__dirname, '../logs/httpLogs/logs')}Http.log`,
      maxLogSize: 102400,
      backups: 1024,
    },

    // 系统日志，如：程序启动和db链接日志，框架错误，catch框架错误，db连接错误等
    sys: {
      type: 'dateFile',
      filename: `${path.resolve(__dirname, '../logs/sysLogs/logs')}Sys.log`,
      maxLogSize: 102400,
      backups: 1024,
    },

    // 登陆日志，所有登录登出等的日志
    login: {
      type: 'dateFile',
      filename: `${path.resolve(__dirname, '../logs/loginLogs/logs')}Login.log`,
      maxLogSize: 102400,
      backups: 1024,
    },

    // APIERROR日志，所有API请求产生的程序错误日志
    apiError: {
      type: 'dateFile',
      filename: `${path.resolve(__dirname, '../logs/apiErrorLogs/logs')}apiError.log`,
      maxLogSize: 102400,
      backups: 1024,
    },

    // 错误日志，所有的错误日志
    errorsFile: {
      type: 'dateFile',
      filename: `${path.resolve(__dirname, '../logs/errorsFileLogs/logs')}ErrorsFile.log`,
      maxLogSize: 102400,
      backups: 1024,
    },
    errors: {
      type: 'logLevelFilter',
      appender: 'errorsFile',
      level: 'error',
    },

    console: { type: 'console' },
  },
  categories: {
    default: { appenders: ['console'], level: 'info' },
    http: { appenders: ['http', 'errors'], level: 'info' },
    sys: { appenders: ['sys', 'console', 'errors'], level: 'info' },

    login: { appenders: ['login'], level: 'info' },
    apiError: { appenders: ['apiError', 'errors'], level: 'info' },
  },
}
<|endoftext|>


<commit_before>var jp = require('jsonpath');
var Card = require('../domain/cds/Card');
var OperationOutcome = require('../domain/fhir/OperationOutcome');
var Parameters = require('../domain/fhir/Parameters');

var service = {

    transform: function(ebmedsResponse, context) {

        if (context.requestParams.debug) {

            var exceptions = jp.query(ebmedsResponse, '$..Exceptions[*].Exception[*]');

            if (exceptions.length > 0) {
                return OperationOutcome.create(exceptions.map(function(exception) {
                    return {
                        severity: "error",
                        code: "exception",
                        diagnostics: exception
                    };
                }));
            }
        }

        return service._createResponse(ebmedsResponse, context);
    },

    _createResponse: function(ebmedsResponse, context) {

        var cards = [];

        if (context.cards.indexOf("reminders") > -1) { service._addReminders(ebmedsResponse, cards, context); }
        if (context.cards.indexOf("guidelink") > -1) { service._addGuideLink(ebmedsResponse, cards); }
        if (context.cards.indexOf("finrisklink") > -1) { service._addFinriskLink(ebmedsResponse, cards); }

        return Parameters.create(cards);
    },

    _addReminders: function(ebmedsResponse, cards, context) {

        var reminders = jp.query(ebmedsResponse, '$..Reminders[*].Reminder[*]');

        reminders.forEach(function(reminder) {
            cards.push(Card.create({
                summary: service._getReminderText(reminder, context.parameters.user.startsWith("Patient") ? "ReminderPatient" : "ReminderShort"),
                detail: service._getReminderText(reminder, context.parameters.user.startsWith("Patient") ? "ReminderPatient" : "ReminderLong"),
                sourceLabel: reminder.ScriptID[0],
                sourceUrl: "http://www.ebmeds.org/web/guest/scripts?id=" + reminder.ScriptID[0] + "&lang=fi",
                indicator: service._mapReminderLevel(reminder.ReminderLevel[0]),
                links: service._getReminderLinks(reminder)
            }));
        });
    },

    _getReminderText: function(reminder, property) {

        var text = service._parseReminderText(reminder, property);

        return text ? text : null;
    },

    _parseReminderText: function(reminder, property) {

        var rm = reminder[property][0];

        // Reminder is object or plain string
        return rm && rm._ ? rm._ : rm ? rm : null;
    },

    _getReminderLinks: function(reminder) {

        return ['ReminderShort', 'ReminderLong', 'ReminderPatient'].reduce(function(links, reminderType) {

            var rm = reminder[reminderType][0];

            if (rm.a) {
                rm.a.forEach(function(link) {
                    links.push({ label: link._, url: link.$.href });
                });
            }

            return links;

        }, []);
    },

    _addGuideLink: function(ebmedsResponse, cards) {

        var links = jp.query(ebmedsResponse, '$..GuidelineLinks[*].GuidelineLink[*]');

        if (links.length > 0) {
            cards.push(Card.create({
                summary: "Hoitosuositukset",
                detail: null,
                sourceLabel: "Lisätietoja",
                sourceUrl: "http://www.terveyskirjasto.fi",
                indicator: "info",
                links: links.map(function(link) {
                    return { label: link.GuidelineTitle[0], url: link.GuidelineURL[0] };
                })
            }));
        }
    },

    _addFinriskLink: function(ebmedsResponse, cards) {

        var finriskDataset = jp.query(ebmedsResponse, '$..ExperimentalDataSet[?(@.DataSetName=="calculatorFinrisk")]')[0];

        if (finriskDataset) {
            cards.push(Card.create({
                summary: "FINRISK calculator",
                detail: "With the FINRISK calculator you can calculate your risk of acute myocardial infarction or acute disorder of the cerebral circulation within the next ten years. The calculator gives your disease risk as a percentage.",
                sourceLabel: "FINRISK calculator - Instructions and interpretation",
                sourceUrl: "https://www.thl.fi/en/web/chronic-diseases/cardiovascular-diseases/finrisk-calculator/instructions",
                indicator: "info",
                links: [{ label: "FINRISK calculator", url: finriskDataset.DataSetText[0] }]
            }));
        }
    },

    _mapReminderLevel: function(reminderLevel) {
        switch (reminderLevel) {
            case "0":
                return "info";
            case "1":
                return "warning";
            case "2":
                return "hard-stop";
            default:
                return "unknown " + "(" + reminderLevel + ")";
        }
    }
};

module.exports = service.transform;<commit_msg>Fixed reminder source url to use language parameter from context<commit_after>var jp = require('jsonpath');
var Card = require('../domain/cds/Card');
var OperationOutcome = require('../domain/fhir/OperationOutcome');
var Parameters = require('../domain/fhir/Parameters');

var service = {

    transform: function(ebmedsResponse, context) {

        if (context.requestParams.debug) {

            var exceptions = jp.query(ebmedsResponse, '$..Exceptions[*].Exception[*]');

            if (exceptions.length > 0) {
                return OperationOutcome.create(exceptions.map(function(exception) {
                    return {
                        severity: "error",
                        code: "exception",
                        diagnostics: exception
                    };
                }));
            }
        }

        return service._createResponse(ebmedsResponse, context);
    },

    _createResponse: function(ebmedsResponse, context) {

        var cards = [];

        if (context.cards.indexOf("reminders") > -1) { service._addReminders(ebmedsResponse, cards, context); }
        if (context.cards.indexOf("guidelink") > -1) { service._addGuideLink(ebmedsResponse, cards); }
        if (context.cards.indexOf("finrisklink") > -1) { service._addFinriskLink(ebmedsResponse, cards); }

        return Parameters.create(cards);
    },

    _addReminders: function(ebmedsResponse, cards, context) {

        var reminders = jp.query(ebmedsResponse, '$..Reminders[*].Reminder[*]');

        reminders.forEach(function(reminder) {
            cards.push(Card.create({
                summary: service._getReminderText(reminder, context.parameters.user.startsWith("Patient") ? "ReminderPatient" : "ReminderShort"),
                detail: service._getReminderText(reminder, context.parameters.user.startsWith("Patient") ? "ReminderPatient" : "ReminderLong"),
                sourceLabel: reminder.ScriptID[0],
                sourceUrl: "http://www.ebmeds.org/web/guest/scripts?id=" + reminder.ScriptID[0] + "&lang=" + context.language,
                indicator: service._mapReminderLevel(reminder.ReminderLevel[0]),
                links: service._getReminderLinks(reminder)
            }));
        });
    },

    _getReminderText: function(reminder, property) {

        var text = service._parseReminderText(reminder, property);

        return text ? text : null;
    },

    _parseReminderText: function(reminder, property) {

        var rm = reminder[property][0];

        // Reminder is object or plain string
        return rm && rm._ ? rm._ : rm ? rm : null;
    },

    _getReminderLinks: function(reminder) {

        return ['ReminderShort', 'ReminderLong', 'ReminderPatient'].reduce(function(links, reminderType) {

            var rm = reminder[reminderType][0];

            if (rm.a) {
                rm.a.forEach(function(link) {
                    links.push({ label: link._, url: link.$.href });
                });
            }

            return links;

        }, []);
    },

    _addGuideLink: function(ebmedsResponse, cards) {

        var links = jp.query(ebmedsResponse, '$..GuidelineLinks[*].GuidelineLink[*]');

        if (links.length > 0) {
            cards.push(Card.create({
                summary: "Hoitosuositukset",
                detail: null,
                sourceLabel: "Lisätietoja",
                sourceUrl: "http://www.terveyskirjasto.fi",
                indicator: "info",
                links: links.map(function(link) {
                    return { label: link.GuidelineTitle[0], url: link.GuidelineURL[0] };
                })
            }));
        }
    },

    _addFinriskLink: function(ebmedsResponse, cards) {

        var finriskDataset = jp.query(ebmedsResponse, '$..ExperimentalDataSet[?(@.DataSetName=="calculatorFinrisk")]')[0];

        if (finriskDataset) {
            cards.push(Card.create({
                summary: "FINRISK calculator",
                detail: "With the FINRISK calculator you can calculate your risk of acute myocardial infarction or acute disorder of the cerebral circulation within the next ten years. The calculator gives your disease risk as a percentage.",
                sourceLabel: "FINRISK calculator - Instructions and interpretation",
                sourceUrl: "https://www.thl.fi/en/web/chronic-diseases/cardiovascular-diseases/finrisk-calculator/instructions",
                indicator: "info",
                links: [{ label: "FINRISK calculator", url: finriskDataset.DataSetText[0] }]
            }));
        }
    },

    _mapReminderLevel: function(reminderLevel) {
        switch (reminderLevel) {
            case "0":
                return "info";
            case "1":
                return "warning";
            case "2":
                return "hard-stop";
            default:
                return "unknown " + "(" + reminderLevel + ")";
        }
    }
};

module.exports = service.transform;<|endoftext|>


<commit_before>'use strict';

function create (env, entries, settings, treatments, devicestatus) {
  var express = require('express'),
      app = express( )
  ;

  var wares = require('../middleware/')(env);

  // set up express app with our options
  app.set('name', env.name);
  app.set('version', env.version);
  app.set('units', env.DISPLAY_UNITS);
  // Only allow access to the API if API_SECRET is set on the server.
  app.disable('api');
  if (env.api_secret) {
    console.log("API_SECRET", env.api_secret);
    app.enable('api');
  }

  env.enable.split(' ').forEach(function(value) {
    var enable = value.trim();
    console.info("enabling feature:", enable);
    app.enable(enable);
  });

  app.set('title', [app.get('name'),  'API', app.get('version')].join(' '));

 // Start setting up routes
  if (app.enabled('api')) {
    // experiments
    app.use('/experiments', require('./experiments/')(app, wares));
  }

  // Entries and settings
  app.use('/', require('./entries/')(app, wares, entries));
  app.use('/', require('./settings/')(app, wares, settings));
  app.use('/', require('./treatments/')(app, wares, treatments));
  app.use('/', require('./devicestatus/')(app, wares, devicestatus));

  // Status
  app.use('/', require('./status')(app, wares));
  return app;
}

module.exports = create;
<commit_msg>lower case the ENABLE env var value to prevent support pain<commit_after>'use strict';

function create (env, entries, settings, treatments, devicestatus) {
  var express = require('express'),
      app = express( )
  ;

  var wares = require('../middleware/')(env);

  // set up express app with our options
  app.set('name', env.name);
  app.set('version', env.version);
  app.set('units', env.DISPLAY_UNITS);
  // Only allow access to the API if API_SECRET is set on the server.
  app.disable('api');
  if (env.api_secret) {
    console.log("API_SECRET", env.api_secret);
    app.enable('api');
  }

  env.enable.toLowerCase().split(' ').forEach(function(value) {
    var enable = value.trim();
    console.info("enabling feature:", enable);
    app.enable(enable);
  });

  app.set('title', [app.get('name'),  'API', app.get('version')].join(' '));

 // Start setting up routes
  if (app.enabled('api')) {
    // experiments
    app.use('/experiments', require('./experiments/')(app, wares));
  }

  // Entries and settings
  app.use('/', require('./entries/')(app, wares, entries));
  app.use('/', require('./settings/')(app, wares, settings));
  app.use('/', require('./treatments/')(app, wares, treatments));
  app.use('/', require('./devicestatus/')(app, wares, devicestatus));

  // Status
  app.use('/', require('./status')(app, wares));
  return app;
}

module.exports = create;
<|endoftext|>


<commit_before>'use strict';

const _ = require('lodash');

const database = require('../database');
const schemas = require('../database/schemas');
const utils = require('../utils');

const liveSchema = utils.singleItem('name', 'live', schemas).fields.map(field => {
  return field.name;
});

/**
 * Convert value to a reference value
 *
 * @param {string} val - content of input
 * @param {object} input - input object from content model
 * @param {string} location - The location of the reference
 * @param {object} references - All references
 *
 * @returns {string|object} either the original value or an object for a reference value
 */
const reference = (val, input, location, references) => {
  const value = val;
  const refs = references;

  if (input.hasOwnProperty('reference') && input.reference === true) {
    const type = _.get(input, 'settings.contentType', null);

    // add content type information to value
    if (type !== null) {
      if (!refs.hasOwnProperty(value)) {
        refs[value] = {
          paths: [],
          type,
        };
      }

      refs[value].paths.push(location);

      return refs;
    }
  }

  return false;
};

/*
 * Formats raw attributes in to API output
 *
 * @param {array} attrs - Array of objects representing the raw attribute content
 * @param {array} model - Array of objects representing the content type's attribute model
 */
const attributes = (attrs, model, models, query, trx) => {
  const params = _.cloneDeep(query) || {};
  const result = {};
  let references = {};

  // check that query has depth property
  if (!params.hasOwnProperty('depth') || isNaN(parseInt(params.depth, 10))) {
    params.depth = 0;
  }

  model.forEach(attr => {
    if (!attr.hasOwnProperty('repeatable')) {
      const inputs = Object.keys(attr.inputs);
      const total = Object.keys(inputs).length;

      // one input, not repeatable
      if (total === 1) {
        const value = _.get(attrs, `${attr.id}.${inputs[0]}.value`, null);

        // add value to result
        result[attr.id] = value;

        // add reference object, if there is one
        const ref = reference(value, attr.inputs[inputs[0]], `${attr.id}`, references);

        if (ref) {
          references = ref;
        }
      }
      else {
        result[attr.id] = {};

        inputs.forEach(inp => {
          const value = _.get(attrs, `${attr.id}.${inp}.value`, null);

          // add value to result
          result[attr.id][inp] = value;

          // add reference object, if there is one
          const ref = reference(value, attr.inputs[inp], `${attr.id}.${inp}`, references);

          if (ref) {
            references = ref;
          }
        });
      }
    }
    else {
      let inputs;
      let input;

      // compensates for array of inputs, this is a bug: https://github.com/punchcard-cms/content-types/issues/133
      //  content-types adds inputs according the the `min` config attribute
      if (Array.isArray(attr.inputs)) {
        // will get the 1st input in a repeatable with a `min` config
        inputs = Object.keys(attr.inputs[0]);
        input = attr.inputs[0][inputs[0]];
      }
      else {
        inputs = Object.keys(attr.inputs);
        input = attr.inputs[inputs[0]];
      }

      if (_.has(attrs, attr.id)) {
        // items is the repeated content for this attribute
        let items = _.get(attrs, attr.id, []);

        if (!Array.isArray(items)) {
          items = [items];
        }

        result[attr.id] = items.map((item, index) => {
          if (Object.keys(items[0]).length === 1) {
            const value = _.get(item, `${inputs[0]}.value`, null);

            // add reference object, if there is one
            const ref = reference(value, input, `${attr.id}[${index}].${inputs[0]}`, references);

            if (ref) {
              references = ref;
            }

            // add value to result
            return _.get(item, `${inputs[0]}.value`, null);
          }

          const repeat = {};

          inputs.forEach((inp) => {
            const value = _.get(item, `${inp}.value`, null);

            // add reference object, if there is one
            const ref = reference(value, attr.inputs[inp], `${attr.id}[${index}].${inp}`, references);

            if (ref) {
              references = ref;
            }

            // add value to result
            repeat[inp] = value;
          });

          return repeat;
        });
      }
      else {
        result[attr.id] = null;
      }
    }
  });

  if (Object.keys(references).length > 0) {
    params.depth--;

    // we've reached our depth, follow no more
    if (params.depth <= 0) {
      params.follow = false;
    }

    const items = Object.keys(references).map(id => {
      const mod = models.find(type => {
        return type.id === references[id].type;
      });

      // eslint will loop on this, so hiding
      return one(params, id, mod.attributes, models, trx); // eslint-disable-line no-use-before-define
    });

    return Promise.all(items).then(row => {
      if (row.length > 0 && row[0] !== null) {
        row.forEach(rw => {
          if (references[rw.id] && Array.isArray(references[rw.id].paths)) {
            references[rw.id].paths.forEach(path => {
              _.set(result, path, rw);
            });
          }
        });
      }

      return result;
    }).catch(e => {
      console.log(e); // eslint-disable-line no-console
    });
  }

  return new Promise(res => {
    res(result);
  });
};

/*
 * Formats raw live data in to consumable returns
 *
 * @param {array} content - Array of objects representing the raw DB query of content
 * @param {array} attrs - If included, will include attributes of the content model
 * @param {array} models - If included, will include all content type models
 * @param {object} query - If included, will include query parameters
 *
 * @returns {array} - formatted object of content
 */
const format = (content, attrs, models, query, trx) => {
  const params = _.cloneDeep(query) || {};
  let atrs = attrs || [];
  const mods = _.cloneDeep(models) || [];

  if (!params.hasOwnProperty('depth') || isNaN(parseInt(params.depth, 10))) {
    params.depth = 0;
  }

  if (!Array.isArray(atrs)) {
    return new Promise((res, rej) => {
      rej('Content model attributes must be an array');
    });
  }

  if (!Array.isArray(mods)) {
    return new Promise((res, rej) => {
      rej('Content models parameter must be an array');
    });
  }

  const formatted = content.map(item => {
    const result = {
      id: item.id,
      type: item.type,
      type_slug: item['type-slug'], // eslint-disable-line camelcase
      key: item.key,
      key_slug: item['key-slug'], // eslint-disable-line camelcase
    };

    // get the attributes model for this piece of content
    if (mods.length > 1) {
      const type = mods.find(typ => {
        return typ.id === item['type-slug'];
      });

      atrs = type.attributes;
    }

    if (atrs.length > 0 && params.follow) {
      return attributes(item.attributes, atrs, mods, params, trx).then(rattrs => {
        result.attributes = rattrs;

        return result;
      });
    }

    result.meta = {
      url: `/api/types/${item['type-slug']}/${item.id}`,
    };

    return new Promise(res => {
      res(result);
    });
  });

  return Promise.all(formatted);
};

/*
 * Determines raw live data organization
 *
 * @param {object} query - Request query params
 * @param {array} custom - A custom array of keys to use
 *
 * @returns {object} - Object with sort key, sort direction, pagination count and offset
 */
const organize = (query, custom) => {
  const params = query || {};
  let lookup = custom;

  if (lookup && !Array.isArray(lookup)) {
    lookup = false;
  }

  let sort = params.sort || 'key';
  let sortDir = params.sort_dir || 'asc';
  let sortKeys = lookup || liveSchema;

  let page = parseInt(params.page, 10) || 1;
  let perPage = parseInt(params.per_page, 10) || 30;
  let count = 0;

  //////////////////////////////
  // Sorting
  //////////////////////////////
  // Ensure sort is an available key
  sortKeys = sortKeys.filter(key => {
    if (key === 'attributes') {
      return false;
    }

    return true;
  });
  if (sortKeys.indexOf(sort) < 0) {
    if (lookup) {
      sort = lookup[0];
    }
    else {
      sort = 'key';
    }
  }

  // Ensure sorting is either ascending or descending
  if (sortDir !== 'asc' && sortDir !== 'desc') {
    sortDir = 'asc';
  }

  //////////////////////////////
  // Pagination
  //////////////////////////////
  // Ensure there is at least one page returned
  if (page < 1) {
    page = 1;
  }

  // Ensure pagination fits within parameters
  if (perPage < 1) {
    perPage = 1;
  }
  else if (perPage > 100) {
    perPage = 100;
  }

  // Calculate offset
  count = (page - 1) * perPage;

  return {
    sort: {
      by: sort,
      dir: sortDir,
    },
    page: {
      offset: count,
      limit: perPage,
      page,
    },
  };
};

/*
 * Build Pagination Links
 *
 * @param {string} base - Base URL
 * @param {object} organized - Organized sort and pagination
 * @param {number} count - Total number of items
 */
const page = (base, organized, count) => {
  const baseURL = `/${base}?sort=${organized.sort.by}&sort_dir=${organized.sort.dir}&per_page=${organized.page.limit}`;
  const pages = {
    first: `${baseURL}&page=1`,
  };
  let total = Math.floor(count / organized.page.limit);
  if (count % organized.page.limit !== 0) {
    total += 1;
  }

  // If not the first page, add a previous link
  if (organized.page.page !== 1 && organized.page.page <= total) {
    pages.prev = `${baseURL}&page=${organized.page.page - 1}`;
  }
  else {
    pages.prev = false;
  }

  // Add next link if not on the last page
  if (organized.page.page + 1 <= total) {
    pages.next = `${baseURL}&page=${organized.page.page + 1}`;
  }
  else {
    pages.next = false;
  }

  // Add last page
  pages.last = `${baseURL}&page=${total}`;

  // If first and last are the same, set them to false
  if (pages.first === pages.last) {
    pages.first = false;
    pages.last = false;
  }

  // If there are no items, set everything to false
  if (total === 0) {
    pages.next = false;
    pages.prev = false;
    pages.first = false;
    pages.last = false;
  }

  return pages;
};

/*
 *  A Specific Piece of Content
 *
 * @param {object} query - Request queries
 * @param {string} id - The GUID to search
 * @param {array} model - Array of content type attributes
 * @param {function} trx - Database transaction object
 *
 * @returns {object} - All items and the pagination for the items
 */
// TODO: Return error if no items are found
const one = (query, id, model, models, trx) => {
  const db = trx || database;
  const params = _.cloneDeep(query) || {};

  // check that query has depth property
  if (!params.hasOwnProperty('depth') || isNaN(parseInt(params.depth, 10))) {
    params.depth = 0;
  }

  return db('live').select('*').where({
    id,
  }).then(rows => {
    return format(rows, model, models, params, db).then(fmtd => {
      const formatted = fmtd[0];

      if (formatted) {
        const type = {
          name: formatted.type,
          slug: formatted.type_slug,
          url: `/api/types/${formatted.type_slug}`,
        };

        formatted.type = type;
        delete formatted.type_slug;

        return formatted;
      }

      return {};
    });
  });
};

module.exports = {
  attributes,
  format,
  organize,
  page,
  one,
};
<commit_msg>:bug: check for type<commit_after>'use strict';

const _ = require('lodash');

const database = require('../database');
const schemas = require('../database/schemas');
const utils = require('../utils');

const liveSchema = utils.singleItem('name', 'live', schemas).fields.map(field => {
  return field.name;
});

/**
 * Convert value to a reference value
 *
 * @param {string} val - content of input
 * @param {object} input - input object from content model
 * @param {string} location - The location of the reference
 * @param {object} references - All references
 *
 * @returns {string|object} either the original value or an object for a reference value
 */
const reference = (val, input, location, references) => {
  const value = val;
  const refs = references;

  if (input.hasOwnProperty('reference') && input.reference === true) {
    const type = _.get(input, 'settings.contentType', null);

    // add content type information to value
    if (type !== null) {
      if (!refs.hasOwnProperty(value)) {
        refs[value] = {
          paths: [],
          type,
        };
      }

      refs[value].paths.push(location);

      return refs;
    }
  }

  return false;
};

/*
 * Formats raw attributes in to API output
 *
 * @param {array} attrs - Array of objects representing the raw attribute content
 * @param {array} model - Array of objects representing the content type's attribute model
 */
const attributes = (attrs, model, models, query, trx) => {
  const params = _.cloneDeep(query) || {};
  const result = {};
  let references = {};

  // check that query has depth property
  if (!params.hasOwnProperty('depth') || isNaN(parseInt(params.depth, 10))) {
    params.depth = 0;
  }

  model.forEach(attr => {
    if (!attr.hasOwnProperty('repeatable')) {
      const inputs = Object.keys(attr.inputs);
      const total = Object.keys(inputs).length;

      // one input, not repeatable
      if (total === 1) {
        const value = _.get(attrs, `${attr.id}.${inputs[0]}.value`, null);

        // add value to result
        result[attr.id] = value;

        // add reference object, if there is one
        const ref = reference(value, attr.inputs[inputs[0]], `${attr.id}`, references);

        if (ref) {
          references = ref;
        }
      }
      else {
        result[attr.id] = {};

        inputs.forEach(inp => {
          const value = _.get(attrs, `${attr.id}.${inp}.value`, null);

          // add value to result
          result[attr.id][inp] = value;

          // add reference object, if there is one
          const ref = reference(value, attr.inputs[inp], `${attr.id}.${inp}`, references);

          if (ref) {
            references = ref;
          }
        });
      }
    }
    else {
      let inputs;
      let input;

      // compensates for array of inputs, this is a bug: https://github.com/punchcard-cms/content-types/issues/133
      //  content-types adds inputs according the the `min` config attribute
      if (Array.isArray(attr.inputs)) {
        // will get the 1st input in a repeatable with a `min` config
        inputs = Object.keys(attr.inputs[0]);
        input = attr.inputs[0][inputs[0]];
      }
      else {
        inputs = Object.keys(attr.inputs);
        input = attr.inputs[inputs[0]];
      }

      if (_.has(attrs, attr.id)) {
        // items is the repeated content for this attribute
        let items = _.get(attrs, attr.id, []);

        if (!Array.isArray(items)) {
          items = [items];
        }

        result[attr.id] = items.map((item, index) => {
          if (Object.keys(items[0]).length === 1) {
            const value = _.get(item, `${inputs[0]}.value`, null);

            // add reference object, if there is one
            const ref = reference(value, input, `${attr.id}[${index}].${inputs[0]}`, references);

            if (ref) {
              references = ref;
            }

            // add value to result
            return _.get(item, `${inputs[0]}.value`, null);
          }

          const repeat = {};

          inputs.forEach((inp) => {
            const value = _.get(item, `${inp}.value`, null);

            // add reference object, if there is one
            const ref = reference(value, attr.inputs[inp], `${attr.id}[${index}].${inp}`, references);

            if (ref) {
              references = ref;
            }

            // add value to result
            repeat[inp] = value;
          });

          return repeat;
        });
      }
      else {
        result[attr.id] = null;
      }
    }
  });

  if (Object.keys(references).length > 0) {
    params.depth--;

    // we've reached our depth, follow no more
    if (params.depth <= 0) {
      params.follow = false;
    }

    const items = Object.keys(references).map(id => {
      const mod = models.find(type => {
        return type.id === references[id].type;
      });

      // eslint will loop on this, so hiding
      return one(params, id, mod.attributes, models, trx); // eslint-disable-line no-use-before-define
    });

    return Promise.all(items).then(row => {
      if (row.length > 0 && row[0] !== null) {
        row.forEach(rw => {
          if (references[rw.id] && Array.isArray(references[rw.id].paths)) {
            references[rw.id].paths.forEach(path => {
              _.set(result, path, rw);
            });
          }
        });
      }

      return result;
    }).catch(e => {
      console.log(e); // eslint-disable-line no-console
    });
  }

  return new Promise(res => {
    res(result);
  });
};

/*
 * Formats raw live data in to consumable returns
 *
 * @param {array} content - Array of objects representing the raw DB query of content
 * @param {array} attrs - If included, will include attributes of the content model
 * @param {array} models - If included, will include all content type models
 * @param {object} query - If included, will include query parameters
 *
 * @returns {array} - formatted object of content
 */
const format = (content, attrs, models, query, trx) => {
  const params = _.cloneDeep(query) || {};
  let atrs = attrs || [];
  const mods = _.cloneDeep(models) || [];

  if (!params.hasOwnProperty('depth') || isNaN(parseInt(params.depth, 10))) {
    params.depth = 0;
  }

  if (!Array.isArray(atrs)) {
    return new Promise((res, rej) => {
      rej('Content model attributes must be an array');
    });
  }

  if (!Array.isArray(mods)) {
    return new Promise((res, rej) => {
      rej('Content models parameter must be an array');
    });
  }

  const formatted = content.map(item => {
    const result = {
      id: item.id,
      type: item.type,
      type_slug: item['type-slug'], // eslint-disable-line camelcase
      key: item.key,
      key_slug: item['key-slug'], // eslint-disable-line camelcase
    };

    // get the attributes model for this piece of content
    if (mods.length > 1) {
      const type = mods.find(typ => {
        return typ.id === item['type-slug'];
      });

      if (type && type.hasOwnProperty('attributes')) {
        atrs = type.attributes;
      }
    }

    if (atrs.length > 0 && params.follow) {
      return attributes(item.attributes, atrs, mods, params, trx).then(rattrs => {
        result.attributes = rattrs;

        return result;
      });
    }

    result.meta = {
      url: `/api/types/${item['type-slug']}/${item.id}`,
    };

    return new Promise(res => {
      res(result);
    });
  });

  return Promise.all(formatted);
};

/*
 * Determines raw live data organization
 *
 * @param {object} query - Request query params
 * @param {array} custom - A custom array of keys to use
 *
 * @returns {object} - Object with sort key, sort direction, pagination count and offset
 */
const organize = (query, custom) => {
  const params = query || {};
  let lookup = custom;

  if (lookup && !Array.isArray(lookup)) {
    lookup = false;
  }

  let sort = params.sort || 'key';
  let sortDir = params.sort_dir || 'asc';
  let sortKeys = lookup || liveSchema;

  let page = parseInt(params.page, 10) || 1;
  let perPage = parseInt(params.per_page, 10) || 30;
  let count = 0;

  //////////////////////////////
  // Sorting
  //////////////////////////////
  // Ensure sort is an available key
  sortKeys = sortKeys.filter(key => {
    if (key === 'attributes') {
      return false;
    }

    return true;
  });
  if (sortKeys.indexOf(sort) < 0) {
    if (lookup) {
      sort = lookup[0];
    }
    else {
      sort = 'key';
    }
  }

  // Ensure sorting is either ascending or descending
  if (sortDir !== 'asc' && sortDir !== 'desc') {
    sortDir = 'asc';
  }

  //////////////////////////////
  // Pagination
  //////////////////////////////
  // Ensure there is at least one page returned
  if (page < 1) {
    page = 1;
  }

  // Ensure pagination fits within parameters
  if (perPage < 1) {
    perPage = 1;
  }
  else if (perPage > 100) {
    perPage = 100;
  }

  // Calculate offset
  count = (page - 1) * perPage;

  return {
    sort: {
      by: sort,
      dir: sortDir,
    },
    page: {
      offset: count,
      limit: perPage,
      page,
    },
  };
};

/*
 * Build Pagination Links
 *
 * @param {string} base - Base URL
 * @param {object} organized - Organized sort and pagination
 * @param {number} count - Total number of items
 */
const page = (base, organized, count) => {
  const baseURL = `/${base}?sort=${organized.sort.by}&sort_dir=${organized.sort.dir}&per_page=${organized.page.limit}`;
  const pages = {
    first: `${baseURL}&page=1`,
  };
  let total = Math.floor(count / organized.page.limit);
  if (count % organized.page.limit !== 0) {
    total += 1;
  }

  // If not the first page, add a previous link
  if (organized.page.page !== 1 && organized.page.page <= total) {
    pages.prev = `${baseURL}&page=${organized.page.page - 1}`;
  }
  else {
    pages.prev = false;
  }

  // Add next link if not on the last page
  if (organized.page.page + 1 <= total) {
    pages.next = `${baseURL}&page=${organized.page.page + 1}`;
  }
  else {
    pages.next = false;
  }

  // Add last page
  pages.last = `${baseURL}&page=${total}`;

  // If first and last are the same, set them to false
  if (pages.first === pages.last) {
    pages.first = false;
    pages.last = false;
  }

  // If there are no items, set everything to false
  if (total === 0) {
    pages.next = false;
    pages.prev = false;
    pages.first = false;
    pages.last = false;
  }

  return pages;
};

/*
 *  A Specific Piece of Content
 *
 * @param {object} query - Request queries
 * @param {string} id - The GUID to search
 * @param {array} model - Array of content type attributes
 * @param {function} trx - Database transaction object
 *
 * @returns {object} - All items and the pagination for the items
 */
// TODO: Return error if no items are found
const one = (query, id, model, models, trx) => {
  const db = trx || database;
  const params = _.cloneDeep(query) || {};

  // check that query has depth property
  if (!params.hasOwnProperty('depth') || isNaN(parseInt(params.depth, 10))) {
    params.depth = 0;
  }

  return db('live').select('*').where({
    id,
  }).then(rows => {
    return format(rows, model, models, params, db).then(fmtd => {
      const formatted = fmtd[0];

      if (formatted) {
        const type = {
          name: formatted.type,
          slug: formatted.type_slug,
          url: `/api/types/${formatted.type_slug}`,
        };

        formatted.type = type;
        delete formatted.type_slug;

        return formatted;
      }

      return {};
    });
  });
};

module.exports = {
  attributes,
  format,
  organize,
  page,
  one,
};
<|endoftext|>


<commit_before>'use strict';

const linz = require('../../');
const path = require('path');
const utils = require('../utils');
const clone = require('clone');

/**
 * Return the path to Linz's view directory, appending the specific view if passed in.
 * @param {String} view The view to append to the view directory path (a Linz specific view).
 * @return {String}     A path to a particular view file.
 * @api public
 */
const viewPath = view => path.resolve(__dirname, '..', '..', 'views', (view || ''));

/**
 * Render a template in the context of Linz.
 * @param  {Object}   data     Data and options to pass to the template.
 * @param  {Function} callback Optional callback function.
 * @return {String}            Renders and returns the template HTML.
 */
const render = (data, callback) => {

    const appLocals = {
        linzNavigation: linz.get('navigation'),
        template: 'wrapper'
    };

    const locals = utils.merge(appLocals, clone(data) || {});
    const view = viewPath(locals.template + '.jade');

    if (!view) {
        return callback(new Error('Could not find template.'));
    }

    // If a callback function is provided, render the view and return the results.
    if (typeof callback === 'function') {
        return linz.app.render(view, locals, callback);
    }

    // If we get to this point, assume callback is a res object.
    return callback.render(view, locals);

};

module.exports = { render, viewPath };
<commit_msg>Fixed an issue with the linz.api.views.render method.<commit_after>'use strict';

const linz = require('../../');
const path = require('path');
const utils = require('../utils');
const clone = require('clone');
const namespaceMiddleware = require('../../middleware/linz');

/**
 * Return the path to Linz's view directory, appending the specific view if passed in.
 * @param {String} view The view to append to the view directory path (a Linz specific view).
 * @return {String}     A path to a particular view file.
 * @api public
 */
const viewPath = view => path.resolve(__dirname, '..', '..', 'views', (view || ''));

/**
 * Render a template in the context of Linz.
 * @param  {Object}   data     Data and options to pass to the template.
 * @param  {Function} callback Optional callback function.
 * @return {String}            Renders and returns the template HTML.
 */
const render = (data, req, callback) => {

    // Namespace this request object.
    namespaceMiddleware(req, {}, () => {

        // Retrieve navigation suitable for the user.
        linz.api.navigation.get(req, (err, navigation) => {

            if (err) {
                return callback(err);
            }

            const appLocals = {
                linzNavigation: navigation,
                template: 'wrapper'
            };

            const locals = utils.merge(appLocals, clone(data) || {});
            const view = viewPath(locals.template + '.jade');

            if (!view) {
                return callback(new Error('Could not find template.'));
            }

            // If a callback function is provided, render the view and return the results.
            if (typeof callback === 'function') {
                return linz.app.render(view, locals, callback);
            }

            // If we get to this point, assume callback is a res object.
            return callback.render(view, locals);

        });

    });

};

module.exports = { render, viewPath };
<|endoftext|>


<commit_before>process.bin = process.title = 'bower';

var Q = require('q');
var mout = require('mout');
var Logger = require('bower-logger');
var userHome = require('user-home');
var bower = require('../');
var version = require('../version');
var cli = require('../util/cli');
var rootCheck = require('../util/rootCheck');

var options;
var renderer;
var loglevel;
var command;
var commandFunc;
var logger;
var levels = Logger.LEVELS;

options = cli.readOptions({
    'version': { type: Boolean, shorthand: 'v' },
    'help': { type: Boolean, shorthand: 'h' },
    'allow-root': { type: Boolean }
});

// Handle print of version
if (options.version) {
    process.stdout.write(version + '\n');
    process.exit();
}

// Root check
rootCheck(options, bower.config);

// Set loglevel
if (bower.config.silent) {
    loglevel = levels.error;
} else if (bower.config.verbose) {
    loglevel = -Infinity;
    Q.longStackSupport = true;
} else if (bower.config.quiet) {
    loglevel = levels.warn;
} else {
    loglevel = levels[bower.config.loglevel] || levels.info;
}

// Get the command to execute
while (options.argv.remain.length) {
    command = options.argv.remain.join(' ');

    // Alias lookup
    if (bower.abbreviations[command]) {
        command = bower.abbreviations[command].replace(/\s/g, '.');
        break;
    }

    command = command.replace(/\s/g, '.');

    // Direct lookup
    if (mout.object.has(bower.commands, command)) {
        break;
    }

    options.argv.remain.pop();
}

// Execute the command
commandFunc = command && mout.object.get(bower.commands, command);
command = command && command.replace(/\./g, ' ');

// If no command was specified, show bower help
// Do the same if the command is unknown
if (!commandFunc) {
    logger = bower.commands.help();
    command = 'help';
// If the user requested help, show the command's help
// Do the same if the actual command is a group of other commands (e.g.: cache)
} else if (options.help || !commandFunc.line) {
    logger = bower.commands.help(command);
    command = 'help';
// Call the line method
} else {
    logger = commandFunc.line(process.argv);

    // If the method failed to interpret the process arguments
    // show the command help
    if (!logger) {
        logger = bower.commands.help(command);
        command = 'help';
    }
}

// Get the renderer and configure it with the executed command
renderer = cli.getRenderer(command, logger.json, bower.config);

function handleLogger(logger, renderer) {
    logger
    .on('end', function (data) {
        if (!bower.config.silent && !bower.config.quiet) {
            renderer.end(data);
        }
    })
    .on('error', function (err)  {
        if (command !== 'help' && err.code === 'EREADOPTIONS') {
            logger = bower.commands.help(command);
            renderer = cli.getRenderer('help', logger.json, bower.config);
            handleLogger(logger, renderer);
        } else {
            if (levels.error >= loglevel) {
                renderer.error(err);
            }

            process.exit(1);
        }
    })
    .on('log', function (log) {
        if (levels[log.level] >= loglevel) {
            renderer.log(log);
        }
    })
    .on('prompt', function (prompt, callback) {
        renderer.prompt(prompt)
        .then(function (answer) {
            callback(answer);
        });
    });
}

handleLogger(logger, renderer);

// Warn if HOME is not SET
if (!userHome) {
    logger.warn('no-home', 'HOME environment variable not set. User config will not be loaded.');
}

if (bower.config.interactive) {
    var updateNotifier = require('update-notifier');

    // Check for newer version of Bower
    var notifier = updateNotifier({ pkg: { name: 'bower', version: version } });

    if (notifier.update && levels.info >= loglevel) {
        notifier.notify();
    }
}
<commit_msg>info message added for bower register<commit_after>process.bin = process.title = 'bower';

var Q = require('q');
var mout = require('mout');
var Logger = require('bower-logger');
var userHome = require('user-home');
var bower = require('../');
var version = require('../version');
var cli = require('../util/cli');
var rootCheck = require('../util/rootCheck');

var options;
var renderer;
var loglevel;
var command;
var commandFunc;
var logger;
var levels = Logger.LEVELS;

options = cli.readOptions({
    'version': { type: Boolean, shorthand: 'v' },
    'help': { type: Boolean, shorthand: 'h' },
    'allow-root': { type: Boolean }
});

// Handle print of version
if (options.version) {
    process.stdout.write(version + '\n');
    process.exit();
}

// Root check
rootCheck(options, bower.config);

// Set loglevel
if (bower.config.silent) {
    loglevel = levels.error;
} else if (bower.config.verbose) {
    loglevel = -Infinity;
    Q.longStackSupport = true;
} else if (bower.config.quiet) {
    loglevel = levels.warn;
} else {
    loglevel = levels[bower.config.loglevel] || levels.info;
}

// Get the command to execute
while (options.argv.remain.length) {
    command = options.argv.remain.join(' ');

    // Alias lookup
    if (bower.abbreviations[command]) {
        command = bower.abbreviations[command].replace(/\s/g, '.');
        break;
    }

    command = command.replace(/\s/g, '.');

    // Direct lookup
    if (mout.object.has(bower.commands, command)) {
        break;
    }

    options.argv.remain.pop();
}

// Execute the command
commandFunc = command && mout.object.get(bower.commands, command);
command = command && command.replace(/\./g, ' ');

// If no command was specified, show bower help
// Do the same if the command is unknown
if (!commandFunc) {
    logger = bower.commands.help();
    command = 'help';
// If the user requested help, show the command's help
// Do the same if the actual command is a group of other commands (e.g.: cache)
} else if (options.help || !commandFunc.line) {
    logger = bower.commands.help(command);
    command = 'help';
// Call the line method
} else {
    logger = commandFunc.line(process.argv);

    // If the method failed to interpret the process arguments
    // show the command help
    if (!logger) {
        logger = bower.commands.help(command);
        command = 'help';
    }
}

// Get the renderer and configure it with the executed command
renderer = cli.getRenderer(command, logger.json, bower.config);

function handleLogger(logger, renderer) {
    logger
    .on('end', function (data) {
        if (!bower.config.silent && !bower.config.quiet) {
            renderer.end(data);
        }
    })
    .on('error', function (err)  {
        if (command !== 'help' && (err.code === 'EREADOPTIONS' || err.code === 'EINVFORMAT')) {
            logger = bower.commands.help(command);
            renderer = cli.getRenderer('help', logger.json, bower.config);
            handleLogger(logger, renderer);
        } else {
            if (levels.error >= loglevel) {
                renderer.error(err);
            }

            process.exit(1);
        }
    })
    .on('log', function (log) {
        if (levels[log.level] >= loglevel) {
            renderer.log(log);
        }
    })
    .on('prompt', function (prompt, callback) {
        renderer.prompt(prompt)
        .then(function (answer) {
            callback(answer);
        });
    });
}

handleLogger(logger, renderer);

// Warn if HOME is not SET
if (!userHome) {
    logger.warn('no-home', 'HOME environment variable not set. User config will not be loaded.');
}

if (bower.config.interactive) {
    var updateNotifier = require('update-notifier');

    // Check for newer version of Bower
    var notifier = updateNotifier({ pkg: { name: 'bower', version: version } });

    if (notifier.update && levels.info >= loglevel) {
        notifier.notify();
    }
}
<|endoftext|>


<commit_before>const { Cc, Ci } = require('chrome'),
      data = require('self').data,
      timer = require('timer'),
      windowutils = require('sdk/window/utils');

const addon_name = 'ImageTwist',
      addon_icon = data.url('img/logo64.png');

/** Notify via notification box. */
function notify(txt) {
    console.log(txt);
    let nb = getNotificationBox();
    let notification = nb.appendNotification(
        txt,
        'jetpack-notification-box',
        addon_icon || 'chrome://browser/skin/Info.png',
        nb.PRIORITY_INFO_MEDIUM,
        []
    );

    timer.setTimeout(function() {
        notification.close();
    }, 5 * 1000);
}

/**
 * Get notification box ("yellow bar").
 * Courtesy of bug 533649.
 */
function getNotificationBox() {
    let browser = windowutils.getMostRecentBrowserWindow().gBrowser,
        notificationBox = browser.getNotificationBox();
    return notificationBox;
}

/** Exports */
exports.notify = notify;
<commit_msg>Removed leftover console.log. Fix #11.<commit_after>const { Cc, Ci } = require('chrome'),
      data = require('self').data,
      timer = require('timer'),
      windowutils = require('sdk/window/utils');

const addon_name = 'ImageTwist',
      addon_icon = data.url('img/logo64.png');

/** Notify via notification box. */
function notify(txt) {
    let nb = getNotificationBox();
    let notification = nb.appendNotification(
        txt,
        'jetpack-notification-box',
        addon_icon || 'chrome://browser/skin/Info.png',
        nb.PRIORITY_INFO_MEDIUM,
        []
    );

    timer.setTimeout(function() {
        notification.close();
    }, 5 * 1000);
}

/**
 * Get notification box ("yellow bar").
 * Courtesy of bug 533649.
 */
function getNotificationBox() {
    let browser = windowutils.getMostRecentBrowserWindow().gBrowser,
        notificationBox = browser.getNotificationBox();
    return notificationBox;
}

/** Exports */
exports.notify = notify;
<|endoftext|>