<commit_before>ace.define("ace/mode/xml_highlight_rules",["require","exports","module","ace/lib/oop","ace/mode/text_highlight_rules"], function(require, exports, module) {
"use strict";

var oop = require("../lib/oop");
var TextHighlightRules = require("./text_highlight_rules").TextHighlightRules;

var XmlHighlightRules = function(normalize) {
    var tagRegex = "[_:a-zA-Z\xc0-\uffff][-_:.a-zA-Z0-9\xc0-\uffff]*";

    this.$rules = {
        start : [
            {token : "string.cdata.xml", regex : "<\\!\\[CDATA\\[", next : "cdata"},
            {
                token : ["punctuation.xml-decl.xml", "keyword.xml-decl.xml"],
                regex : "(<\\?)(xml)(?=[\\s])", next : "xml_decl", caseInsensitive: true
            },
            {
                token : ["punctuation.instruction.xml", "keyword.instruction.xml"],
                regex : "(<\\?)(" + tagRegex + ")", next : "processing_instruction"
            },
            {token : "comment.xml", regex : "<\\!--", next : "comment"},
            {
                token : ["xml-pe.doctype.xml", "xml-pe.doctype.xml"],
                regex : "(<\\!)(DOCTYPE)(?=[\\s])", next : "doctype", caseInsensitive: true
            },
            {include : "tag"},
            {token : "text.end-tag-open.xml", regex: "</"},
            {token : "text.tag-open.xml", regex: "<"},
            {include : "reference"},
            {defaultToken : "text.xml"}
        ],

        xml_decl : [{
            token : "entity.other.attribute-name.decl-attribute-name.xml",
            regex : "(?:" + tagRegex + ":)?" + tagRegex + ""
        }, {
            token : "keyword.operator.decl-attribute-equals.xml",
            regex : "="
        }, {
            include: "whitespace"
        }, {
            include: "string"
        }, {
            token : "punctuation.xml-decl.xml",
            regex : "\\?>",
            next : "start"
        }],

        processing_instruction : [
            {token : "punctuation.instruction.xml", regex : "\\?>", next : "start"},
            {defaultToken : "instruction.xml"}
        ],

        doctype : [
            {include : "whitespace"},
            {include : "string"},
            {token : "xml-pe.doctype.xml", regex : ">", next : "start"},
            {token : "xml-pe.xml", regex : "[-_a-zA-Z0-9:]+"},
            {token : "punctuation.int-subset", regex : "\\[", push : "int_subset"}
        ],

        int_subset : [{
            token : "text.xml",
            regex : "\\s+"
        }, {
            token: "punctuation.int-subset.xml",
            regex: "]",
            next: "pop"
        }, {
            token : ["punctuation.markup-decl.xml", "keyword.markup-decl.xml"],
            regex : "(<\\!)(" + tagRegex + ")",
            push : [{
                token : "text",
                regex : "\\s+"
            },
            {
                token : "punctuation.markup-decl.xml",
                regex : ">",
                next : "pop"
            },
            {include : "string"}]
        }],

        cdata : [
            {token : "string.cdata.xml", regex : "\\]\\]>", next : "start"},
            {token : "text.xml", regex : "\\s+"},
            {token : "text.xml", regex : "(?:[^\\]]|\\](?!\\]>))+"}
        ],

        comment : [
            {token : "comment.xml", regex : "-->", next : "start"},
            {defaultToken : "comment.xml"}
        ],

        reference : [{
            token : "constant.language.escape.reference.xml",
            regex : "(?:&#[0-9]+;)|(?:&#x[0-9a-fA-F]+;)|(?:&[a-zA-Z0-9_:\\.-]+;)"
        }],

        attr_reference : [{
            token : "constant.language.escape.reference.attribute-value.xml",
            regex : "(?:&#[0-9]+;)|(?:&#x[0-9a-fA-F]+;)|(?:&[a-zA-Z0-9_:\\.-]+;)"
        }],

        tag : [{
            token : ["meta.tag.punctuation.tag-open.xml", "meta.tag.punctuation.end-tag-open.xml", "meta.tag.tag-name.xml"],
            regex : "(?:(<)|(</))((?:" + tagRegex + ":)?" + tagRegex + ")",
            next: [
                {include : "attributes"},
                {token : "meta.tag.punctuation.tag-close.xml", regex : "/?>", next : "start"}
            ]
        }],

        tag_whitespace : [
            {token : "text.tag-whitespace.xml", regex : "\\s+"}
        ],
        whitespace : [
            {token : "text.whitespace.xml", regex : "\\s+"}
        ],
        string: [{
            token : "string.xml",
            regex : "'",
            push : [
                {token : "string.xml", regex: "'", next: "pop"},
                {defaultToken : "string.xml"}
            ]
        }, {
            token : "string.xml",
            regex : '"',
            push : [
                {token : "string.xml", regex: '"', next: "pop"},
                {defaultToken : "string.xml"}
            ]
        }],

        attributes: [{
            token : "entity.other.attribute-name.xml",
            regex : "(?:" + tagRegex + ":)?" + tagRegex + ""
        }, {
            token : "keyword.operator.attribute-equals.xml",
            regex : "="
        }, {
            include: "tag_whitespace"
        }, {
            include: "attribute_value"
        }],

        attribute_value: [{
            token : "string.attribute-value.xml",
            regex : "'",
            push : [
                {token : "string.attribute-value.xml", regex: "'", next: "pop"},
                {include : "attr_reference"},
                {defaultToken : "string.attribute-value.xml"}
            ]
        }, {
            token : "string.attribute-value.xml",
            regex : '"',
            push : [
                {token : "string.attribute-value.xml", regex: '"', next: "pop"},
                {include : "attr_reference"},
                {defaultToken : "string.attribute-value.xml"}
            ]
        }]
    };

    if (this.constructor === XmlHighlightRules)
        this.normalizeRules();
};

(function() {

    this.embedTagRules = function(HighlightRules, prefix, tag){
        this.$rules.tag.unshift({
            token : ["meta.tag.punctuation.tag-open.xml", "meta.tag." + tag + ".tag-name.xml"],
            regex : "(<)(" + tag + "(?=\\s|>|$))",
            next: [
                {include : "attributes"},
                {token : "meta.tag.punctuation.tag-close.xml", regex : "/?>", next : prefix + "start"}
            ]
        });

        this.$rules[tag + "-end"] = [
            {include : "attributes"},
            {token : "meta.tag.punctuation.tag-close.xml", regex : "/?>",  next: "start",
                onMatch : function(value, currentState, stack) {
                    stack.splice(0);
                    return this.token;
            }}
        ]

        this.embedRules(HighlightRules, prefix, [{
            token: ["meta.tag.punctuation.end-tag-open.xml", "meta.tag." + tag + ".tag-name.xml"],
            regex : "(</)(" + tag + "(?=\\s|>|$))",
            next: tag + "-end"
        }, {
            token: "string.cdata.xml",
            regex : "<\\!\\[CDATA\\["
        }, {
            token: "string.cdata.xml",
            regex : "\\]\\]>"
        }]);
    };

}).call(TextHighlightRules.prototype);

oop.inherits(XmlHighlightRules, TextHighlightRules);

exports.XmlHighlightRules = XmlHighlightRules;
});

ace.define("ace/mode/behaviour/xml",["require","exports","module","ace/lib/oop","ace/mode/behaviour","ace/token_iterator","ace/lib/lang"], function(require, exports, module) {
"use strict";

var oop = require("../../lib/oop");
var Behaviour = require("../behaviour").Behaviour;
var TokenIterator = require("../../token_iterator").TokenIterator;
var lang = require("../../lib/lang");

function is(token, type) {
    return token.type.lastIndexOf(type + ".xml") > -1;
}

var XmlBehaviour = function () {

    this.add("string_dquotes", "insertion", function (state, action, editor, session, text) {
        if (text == '"' || text == "'") {
            var quote = text;
            var selected = session.doc.getTextRange(editor.getSelectionRange());
            if (selected !== "" && selected !== "'" && selected != '"' && editor.getWrapBehavioursEnabled()) {
                return {
                    text: quote + selected + quote,
                    selection: false
                };
            }

            var cursor = editor.getCursorPosition();
            var line = session.doc.getLine(cursor.row);
            var rightChar = line.substring(cursor.column, cursor.column + 1);
            var iterator = new TokenIterator(session, cursor.row, cursor.column);
            var token = iterator.getCurrentToken();

            if (rightChar == quote && (is(token, "attribute-value") || is(token, "string"))) {
                return {
                    text: "",
                    selection: [1, 1]
                };
            }

            if (!token)
                token = iterator.stepBackward();

            if (!token)
                return;

            while (is(token, "tag-whitespace") || is(token, "whitespace")) {
                token = iterator.stepBackward();
            }
            var rightSpace = !rightChar || rightChar.match(/\s/);
            if (is(token, "attribute-equals") && (rightSpace || rightChar == '>') || (is(token, "decl-attribute-equals") && (rightSpace || rightChar == '?'))) {
                return {
                    text: quote + quote,
                    selection: [1, 1]
                };
            }
        }
    });

    this.add("string_dquotes", "deletion", function(state, action, editor, session, range) {
        var selected = session.doc.getTextRange(range);
        if (!range.isMultiLine() && (selected == '"' || selected == "'")) {
            var line = session.doc.getLine(range.start.row);
            var rightChar = line.substring(range.start.column + 1, range.start.column + 2);
            if (rightChar == selected) {
                range.end.column++;
                return range;
            }
        }
    });

    this.add("autoclosing", "insertion", function (state, action, editor, session, text) {
        if (text == '>') {
            var position = editor.getCursorPosition();
            var iterator = new TokenIterator(session, position.row, position.column);
            var token = iterator.getCurrentToken() || iterator.stepBackward();
            if (!token || !(is(token, "tag-name") || is(token, "tag-whitespace") || is(token, "attribute-name") || is(token, "attribute-equals") || is(token, "attribute-value")))
                return;
            if (is(token, "reference.attribute-value"))
                return;
            if (is(token, "attribute-value")) {
                var firstChar = token.value.charAt(0);
                if (firstChar == '"' || firstChar == "'") {
                    var lastChar = token.value.charAt(token.value.length - 1);
                    var tokenEnd = iterator.getCurrentTokenColumn() + token.value.length;
                    if (tokenEnd > position.column || tokenEnd == position.column && firstChar != lastChar)
                        return;
                }
            }
            while (!is(token, "tag-name")) {
                token = iterator.stepBackward();
            }

            var tokenRow = iterator.getCurrentTokenRow();
            var tokenColumn = iterator.getCurrentTokenColumn();
            if (is(iterator.stepBackward(), "end-tag-open"))
                return;

            var element = token.value;
            if (tokenRow == position.row)
                element = element.substring(0, position.column - tokenColumn);

            if (this.voidElements.hasOwnProperty(element.toLowerCase()))
                 return;

            return {
               text: ">" + "</" + element + ">",
               selection: [1, 1]
            };
        }
    });

    this.add("autoindent", "insertion", function (state, action, editor, session, text) {
        if (text == "\n") {
            var cursor = editor.getCursorPosition();
            var line = session.getLine(cursor.row);
            var iterator = new TokenIterator(session, cursor.row, cursor.column);
            var token = iterator.getCurrentToken();

            if (token && token.type.indexOf("tag-close") !== -1) {
                if (token.value == "/>")
                    return;
                while (token && token.type.indexOf("tag-name") === -1) {
                    token = iterator.stepBackward();
                }

                if (!token) {
                    return;
                }

                var tag = token.value;
                var row = iterator.getCurrentTokenRow();
                token = iterator.stepBackward();
                if (!token || token.type.indexOf("end-tag") !== -1) {
                    return;
                }

                if (this.voidElements && !this.voidElements[tag]) {
                    var nextToken = session.getTokenAt(cursor.row, cursor.column+1);
                    var line = session.getLine(row);
                    var nextIndent = this.$getIndent(line);
                    var indent = nextIndent + session.getTabString();

                    if (nextToken && nextToken.value === "</") {
                        return {
                            text: "\n" + indent + "\n" + nextIndent,
                            selection: [1, indent.length, 1, indent.length]
                        };
                    } else {
                        return {
                            text: "\n" + indent
                        };
                    }
                }
            }
        }
    });

};

oop.inherits(XmlBehaviour, Behaviour);

exports.XmlBehaviour = XmlBehaviour;
});

ace.define("ace/mode/folding/xml",["require","exports","module","ace/lib/oop","ace/lib/lang","ace/range","ace/mode/folding/fold_mode","ace/token_iterator"], function(require, exports, module) {
"use strict";

var oop = require("../../lib/oop");
var lang = require("../../lib/lang");
var Range = require("../../range").Range;
var BaseFoldMode = require("./fold_mode").FoldMode;
var TokenIterator = require("../../token_iterator").TokenIterator;

var FoldMode = exports.FoldMode = function(voidElements, optionalEndTags) {
    BaseFoldMode.call(this);
    this.voidElements = voidElements || {};
    this.optionalEndTags = oop.mixin({}, this.voidElements);
    if (optionalEndTags)
        oop.mixin(this.optionalEndTags, optionalEndTags);

};
oop.inherits(FoldMode, BaseFoldMode);

var Tag = function() {
    this.tagName = "";
    this.closing = false;
    this.selfClosing = false;
    this.start = {row: 0, column: 0};
    this.end = {row: 0, column: 0};
};

function is(token, type) {
    return token.type.lastIndexOf(type + ".xml") > -1;
}

(function() {

    this.getFoldWidget = function(session, foldStyle, row) {
        var tag = this._getFirstTagInLine(session, row);

        if (!tag)
            return "";

        if (tag.closing || (!tag.tagName && tag.selfClosing))
            return foldStyle == "markbeginend" ? "end" : "";

        if (!tag.tagName || tag.selfClosing || this.voidElements.hasOwnProperty(tag.tagName.toLowerCase()))
            return "";

        if (this._findEndTagInLine(session, row, tag.tagName, tag.end.column))
            return "";

        return "start";
    };
    this._getFirstTagInLine = function(session, row) {
        var tokens = session.getTokens(row);
        var tag = new Tag();

        for (var i = 0; i < tokens.length; i++) {
            var token = tokens[i];
            if (is(token, "tag-open")) {
                tag.end.column = tag.start.column + token.value.length;
                tag.closing = is(token, "end-tag-open");
                token = tokens[++i];
                if (!token)
                    return null;
                tag.tagName = token.value;
                tag.end.column += token.value.length;
                for (i++; i < tokens.length; i++) {
                    token = tokens[i];
                    tag.end.column += token.value.length;
                    if (is(token, "tag-close")) {
                        tag.selfClosing = token.value == '/>';
                        break;
                    }
                }
                return tag;
            } else if (is(token, "tag-close")) {
                tag.selfClosing = token.value == '/>';
                return tag;
            }
            tag.start.column += token.value.length;
        }

        return null;
    };

    this._findEndTagInLine = function(session, row, tagName, startColumn) {
        var tokens = session.getTokens(row);
        var column = 0;
        for (var i = 0; i < tokens.length; i++) {
            var token = tokens[i];
            column += token.value.length;
            if (column < startColumn)
                continue;
            if (is(token, "end-tag-open")) {
                token = tokens[i + 1];
                if (token && token.value == tagName)
                    return true;
            }
        }
        return false;
    };
    this._readTagForward = function(iterator) {
        var token = iterator.getCurrentToken();
        if (!token)
            return null;

        var tag = new Tag();
        do {
            if (is(token, "tag-open")) {
                tag.closing = is(token, "end-tag-open");
                tag.start.row = iterator.getCurrentTokenRow();
                tag.start.column = iterator.getCurrentTokenColumn();
            } else if (is(token, "tag-name")) {
                tag.tagName = token.value;
            } else if (is(token, "tag-close")) {
                tag.selfClosing = token.value == "/>";
                tag.end.row = iterator.getCurrentTokenRow();
                tag.end.column = iterator.getCurrentTokenColumn() + token.value.length;
                iterator.stepForward();
                return tag;
            }
        } while(token = iterator.stepForward());

        return null;
    };

    this._readTagBackward = function(iterator) {
        var token = iterator.getCurrentToken();
        if (!token)
            return null;

        var tag = new Tag();
        do {
            if (is(token, "tag-open")) {
                tag.closing = is(token, "end-tag-open");
                tag.start.row = iterator.getCurrentTokenRow();
                tag.start.column = iterator.getCurrentTokenColumn();
                iterator.stepBackward();
                return tag;
            } else if (is(token, "tag-name")) {
                tag.tagName = token.value;
            } else if (is(token, "tag-close")) {
                tag.selfClosing = token.value == "/>";
                tag.end.row = iterator.getCurrentTokenRow();
                tag.end.column = iterator.getCurrentTokenColumn() + token.value.length;
            }
        } while(token = iterator.stepBackward());

        return null;
    };

    this._pop = function(stack, tag) {
        while (stack.length) {

            var top = stack[stack.length-1];
            if (!tag || top.tagName == tag.tagName) {
                return stack.pop();
            }
            else if (this.optionalEndTags.hasOwnProperty(top.tagName)) {
                stack.pop();
                continue;
            } else {
                return null;
            }
        }
    };

    this.getFoldWidgetRange = function(session, foldStyle, row) {
        var firstTag = this._getFirstTagInLine(session, row);

        if (!firstTag)
            return null;

        var isBackward = firstTag.closing || firstTag.selfClosing;
        var stack = [];
        var tag;

        if (!isBackward) {
            var iterator = new TokenIterator(session, row, firstTag.start.column);
            var start = {
                row: row,
                column: firstTag.start.column + firstTag.tagName.length + 2
            };
            if (firstTag.start.row == firstTag.end.row)
                start.column = firstTag.end.column;
            while (tag = this._readTagForward(iterator)) {
                if (tag.selfClosing) {
                    if (!stack.length) {
                        tag.start.column += tag.tagName.length + 2;
                        tag.end.column -= 2;
                        return Range.fromPoints(tag.start, tag.end);
                    } else
                        continue;
                }

                if (tag.closing) {
                    this._pop(stack, tag);
                    if (stack.length == 0)
                        return Range.fromPoints(start, tag.start);
                }
                else {
                    stack.push(tag);
                }
            }
        }
        else {
            var iterator = new TokenIterator(session, row, firstTag.end.column);
            var end = {
                row: row,
                column: firstTag.start.column
            };

            while (tag = this._readTagBackward(iterator)) {
                if (tag.selfClosing) {
                    if (!stack.length) {
                        tag.start.column += tag.tagName.length + 2;
                        tag.end.column -= 2;
                        return Range.fromPoints(tag.start, tag.end);
                    } else
                        continue;
                }

                if (!tag.closing) {
                    this._pop(stack, tag);
                    if (stack.length == 0) {
                        tag.start.column += tag.tagName.length + 2;
                        if (tag.start.row == tag.end.row && tag.start.column < tag.end.column)
                            tag.start.column = tag.end.column;
                        return Range.fromPoints(tag.start, end);
                    }
                }
                else {
                    stack.push(tag);
                }
            }
        }

    };

}).call(FoldMode.prototype);

});

ace.define("ace/mode/xml",["require","exports","module","ace/lib/oop","ace/lib/lang","ace/mode/text","ace/mode/xml_highlight_rules","ace/mode/behaviour/xml","ace/mode/folding/xml","ace/worker/worker_client"], function(require, exports, module) {
"use strict";

var oop = require("../lib/oop");
var lang = require("../lib/lang");
var TextMode = require("./text").Mode;
var XmlHighlightRules = require("./xml_highlight_rules").XmlHighlightRules;
var XmlBehaviour = require("./behaviour/xml").XmlBehaviour;
var XmlFoldMode = require("./folding/xml").FoldMode;
var WorkerClient = require("../worker/worker_client").WorkerClient;

var Mode = function() {
   this.HighlightRules = XmlHighlightRules;
   this.$behaviour = new XmlBehaviour();
   this.foldingRules = new XmlFoldMode();
};

oop.inherits(Mode, TextMode);

(function() {

    this.voidElements = lang.arrayToMap([]);

    this.blockComment = {start: "<!--", end: "-->"};

    this.createWorker = function(session) {
        var worker = new WorkerClient(["ace"], "ace/mode/xml_worker", "Worker");
        worker.attachToDocument(session.getDocument());

        worker.on("error", function(e) {
            session.setAnnotations(e.data);
        });

        worker.on("terminate", function() {
            session.clearAnnotations();
        });

        return worker;
    };

    this.$id = "ace/mode/xml";
}).call(Mode.prototype);

exports.Mode = Mode;
});
<commit_msg>Update tmp/bower_components/ace-builds/src-noconflict/mode-xml.js<commit_after><|endoftext|>


<commit_before>function URLParser() {
  "use strict";
  this.plugins = {};
}
URLParser.prototype.parse = function (url) {
  "use strict";
  var th = this,
    match = url.match(/(?:(?:https?:)?\/\/)?(?:[^\.]+\.)?(\w+)\./i),
    provider = match ? match[1] : undefined,
    result;
  if (match && provider && th.plugins[provider] && th.plugins[provider].parse) {
    result = th.plugins[provider].parse.call(this, url, getQueryParams(url));
    if (result) {
      if (result.params && Object.keys(result.params).length === 0) {
        delete result.params;
      }
      result.provider = th.plugins[provider].provider;
      return result;
    }
  }
  return undefined;
};
URLParser.prototype.bind = function (plugin) {
  "use strict";
  var th = this;
  th.plugins[plugin.provider] = plugin;
  if (plugin.alternatives) {
    for (var i = 0; i < plugin.alternatives.length; i += 1) {
      th.plugins[plugin.alternatives[i]] = plugin;
    }
  }
};
URLParser.prototype.create = function (op) {
  "use strict";
  var th = this,
    vi = op.videoInfo,
    params = op.params,
    plugin = th.plugins[vi.provider];

  params = (params === 'internal') ? vi.params : params || {};

  if (plugin) {
    op.format = op.format || plugin.defaultFormat;
    if (plugin.formats.hasOwnProperty(op.format)) {
      return plugin.formats[op.format](vi, cloneObject(params));
    }
  }
  return undefined;
};
var urlParser = new URLParser();

if (typeof module !== undefined && module.exports) {
  module.exports = urlParser;
}
<commit_msg>Properly checking for undefined on module Hotfix for issue #16<commit_after>function URLParser() {
  "use strict";
  this.plugins = {};
}
URLParser.prototype.parse = function (url) {
  "use strict";
  var th = this,
    match = url.match(/(?:(?:https?:)?\/\/)?(?:[^\.]+\.)?(\w+)\./i),
    provider = match ? match[1] : undefined,
    result;
  if (match && provider && th.plugins[provider] && th.plugins[provider].parse) {
    result = th.plugins[provider].parse.call(this, url, getQueryParams(url));
    if (result) {
      if (result.params && Object.keys(result.params).length === 0) {
        delete result.params;
      }
      result.provider = th.plugins[provider].provider;
      return result;
    }
  }
  return undefined;
};
URLParser.prototype.bind = function (plugin) {
  "use strict";
  var th = this;
  th.plugins[plugin.provider] = plugin;
  if (plugin.alternatives) {
    for (var i = 0; i < plugin.alternatives.length; i += 1) {
      th.plugins[plugin.alternatives[i]] = plugin;
    }
  }
};
URLParser.prototype.create = function (op) {
  "use strict";
  var th = this,
    vi = op.videoInfo,
    params = op.params,
    plugin = th.plugins[vi.provider];

  params = (params === 'internal') ? vi.params : params || {};

  if (plugin) {
    op.format = op.format || plugin.defaultFormat;
    if (plugin.formats.hasOwnProperty(op.format)) {
      return plugin.formats[op.format](vi, cloneObject(params));
    }
  }
  return undefined;
};
var urlParser = new URLParser();

if (typeof module !== 'undefined' && typeof module.exports !== 'undefined') {
  module.exports = urlParser;
}
<|endoftext|>


<commit_before>/**
 * Copyright (c) 2015-present, Facebook, Inc.
 * All rights reserved.
 *
 * This source code is licensed under the BSD-style license found in the
 * LICENSE file in the root directory of this source tree. An additional grant
 * of patent rights can be found in the PATENTS file in the same directory.
 *
 * @providesModule ActionSheetIOS
 * @flow
 */
'use strict';

var RCTActionSheetManager = require('NativeModules').ActionSheetManager;

var invariant = require('fbjs/lib/invariant');
var processColor = require('processColor');

var ActionSheetIOS = {
  /**
   * Display an iOS action sheet. The `options` object must contain one or more
   * of:
   *
   * - `options` (array of strings) - a list of button titles (required)
   * - `cancelButtonIndex` (int) - index of cancel button in `options`
   * - `destructiveButtonIndex` (int) - index of destructive button in `options`
   * - `title` (string) - a title to show above the action sheet
   * - `message` (string) - a message to show below the title
   */
  showActionSheetWithOptions(options: Object, callback: Function) {
    invariant(
      typeof options === 'object' && options !== null,
      'Options must be a valid object'
    );
    invariant(
      typeof callback === 'function',
      'Must provide a valid callback'
    );
    RCTActionSheetManager.showActionSheetWithOptions(
      {...options, tintColor: processColor(options.tintColor)},
      callback
    );
  },

  /**
   * Display the iOS share sheet. The `options` object should contain
   * one or both of:
   *
   * - `message` (string) - a message to share
   * - `url` (string) - a URL to share
   *
   * NOTE: if `url` points to a local file, or is a base64-encoded
   * uri, the file it points to will be loaded and shared directly.
   * In this way, you can share images, videos, PDF files, etc.
   */
  showShareActionSheetWithOptions(
    options: Object,
    failureCallback: Function,
    successCallback: Function
  ) {
    invariant(
      typeof options === 'object' && options !== null,
      'Options must be a valid object'
    );
    invariant(
      typeof failureCallback === 'function',
      'Must provide a valid failureCallback'
    );
    invariant(
      typeof successCallback === 'function',
      'Must provide a valid successCallback'
    );
    RCTActionSheetManager.showShareActionSheetWithOptions(
      {...options, tintColor: processColor(options.tintColor)},
      failureCallback,
      successCallback
    );
  }
};

module.exports = ActionSheetIOS;
<commit_msg>Update the documenation of ActionSheetIOS to include all possible options<commit_after>/**
 * Copyright (c) 2015-present, Facebook, Inc.
 * All rights reserved.
 *
 * This source code is licensed under the BSD-style license found in the
 * LICENSE file in the root directory of this source tree. An additional grant
 * of patent rights can be found in the PATENTS file in the same directory.
 *
 * @providesModule ActionSheetIOS
 * @flow
 */
'use strict';

var RCTActionSheetManager = require('NativeModules').ActionSheetManager;

var invariant = require('fbjs/lib/invariant');
var processColor = require('processColor');

var ActionSheetIOS = {
  /**
   * Display an iOS action sheet. The `options` object must contain one or more
   * of:
   *
   * - `options` (array of strings) - a list of button titles (required)
   * - `cancelButtonIndex` (int) - index of cancel button in `options`
   * - `destructiveButtonIndex` (int) - index of destructive button in `options`
   * - `title` (string) - a title to show above the action sheet
   * - `message` (string) - a message to show below the title
   */
  showActionSheetWithOptions(options: Object, callback: Function) {
    invariant(
      typeof options === 'object' && options !== null,
      'Options must be a valid object'
    );
    invariant(
      typeof callback === 'function',
      'Must provide a valid callback'
    );
    RCTActionSheetManager.showActionSheetWithOptions(
      {...options, tintColor: processColor(options.tintColor)},
      callback
    );
  },

  /**
   * Display the iOS share sheet. The `options` object should contain
   * one or both of `message` and `url` and can additionally have
   * a `subject` or `excludedActivityTypes`:
   *
   * - `url` (string) - a URL to share
   * - `message` (string) - a message to share
   * - `subject` (string) - a subject for the message
   * - `excludedActivityTypes` (array) - the activites to exclude from the ActionSheet
   *
   * NOTE: if `url` points to a local file, or is a base64-encoded
   * uri, the file it points to will be loaded and shared directly.
   * In this way, you can share images, videos, PDF files, etc.
   */
  showShareActionSheetWithOptions(
    options: Object,
    failureCallback: Function,
    successCallback: Function
  ) {
    invariant(
      typeof options === 'object' && options !== null,
      'Options must be a valid object'
    );
    invariant(
      typeof failureCallback === 'function',
      'Must provide a valid failureCallback'
    );
    invariant(
      typeof successCallback === 'function',
      'Must provide a valid successCallback'
    );
    RCTActionSheetManager.showShareActionSheetWithOptions(
      {...options, tintColor: processColor(options.tintColor)},
      failureCallback,
      successCallback
    );
  }
};

module.exports = ActionSheetIOS;
<|endoftext|>


<commit_before>/**
 * Overall game manager
 *
 * @class Game
 * @constructor
 * @param {Object} gamestate - Your first game state (an intro gamestate for example)
 * @param {Object} options - {backgroundColor : don't need to be a super hero to understand this one, view : If you don't want Fresh Flesh to create a default screen-sized renderer, give it your own (optional)}
 *
 * @example
 * var intro = {
 * 		isStarted : false,
 * 		setup : function(){ console.log("Setup"); },
 * 		update : function(){ console.log("Update"); },
 * 		draw : function(){ console.log("Draw"); }
 * };
 *
 * var game = new FF.Game(intro);
 * game.start();
 */
FF.Game = function(gamestate, options){
	var that = this;

	/**
	 * In case of calling to switchGameState(), we save the previous gamestate if we want to re-use it later (like showing a game pause menu, and go back to the main gamestate
	 * @property previousGameState
	 * @type Object
	 */
	this.previousGameState = null;

	/**
	 * The running game state of your game
	 * @property currentGameState
	 * @type Object
	 */
	this.currentGameState = gamestate;

	/**
	 * Hex background color of the game
	 * @property backgroundColor
	 * @type String
	 */
	this.backgroundColor = options.backgroundColor || "#FFF";

	/**
	 * Last time requestAnimationFrame was called
	 * @property lastCalledTime
	 * @type Date
	 */
	this.lastCalledTime = null;

	/**
	 * Current FPS count
	 * @property fps
	 * @type Integer
	 */
	this.fps = 0;

	/**
	 * Used to start the gamestate given to the FF.Game class constructor
	 * @method start
	 */
	this.launch = function(){
		if(this.currentGameState.isStarted == true) throw new Error("[FF.Game.Start] Your GameState is already started");
		if(this.currentGameState.setup === undefined) throw new Error("[FF.Game.Start] Your GameState have to contain a setup() function");

		if(FF.Render.canvas === undefined){
			FF.Render = FF.Util.createRender(options.view);
		}

		if(FF.InputManager.isSetup == false){
			FF.InputManager.setup();
		}

		this.currentGameState.setup();
		if(this.currentGameState.isStarted === undefined || this.currentGameState.isStarted == false) this.currentGameState.isStarted = true;

		requestAnimation();
	};

	/**
	 * Called by requestAnimationFrame to run your gameloops
	 * @method requestAnimation
	 * @private
	 */
	function requestAnimation(){
		if(that.currentGameState.update === undefined) throw new Error("[FF.Game.requestAnimationFrame] Your GameState have to contain an update() function (even if you let it empty)");
		if(that.currentGameState.draw === undefined) throw new Error("[FF.Game.requestAnimationFrame] Your GameState have to contain an draw() function (even if you let it empty)");

		if(that.currentGameState.isStarted){
			that.currentGameState.update();

			//Clearing
			FF.Render.clearRect(0,0,FF.Render.getWidth(),FF.Render.getHeight());

			//Setting the background color
			FF.Render.setBackgroundColor(that.backgroundColor);

			that.currentGameState.draw();
		}

		if(that.lastCalledTime == null) {
			that.lastCalledTime = new Date().getTime();
			that.fps = 0;
			requestAnimationFrame(requestAnimation);
			return;
		}
		var delta = (new Date().getTime() - that.lastCalledTime)/1000;
		that.lastCalledTime = new Date().getTime();
		that.fps = (1/delta).toFixed(1);

		requestAnimationFrame(requestAnimation);
	};
};

/**
 * Allows you to switch between different gamestates, already started or not
 * @method switchGameState
 * @param {Object} gamestate - The new or previous (use your_game.previousGameState) gamestate to use in the main game loop
 * @param {Boolean} reset - Wether system have to reset the given gamestate (usefull when user press "Retry" in a pause menu, for example
 */
FF.Game.prototype.switchGameState = function(gamestate, reset){
	if(gamestate === undefined) throw new Error("[FF.Game.switchGameState] Your gamestate is undefined (not instanciated, like gs = new Blablabla();)");

	this.previousGameState = this.currentGameState;
	this.currentGameState = (reset) ? new gamestate.constructor : gamestate;

	//if(this.currentGameState.isStarted === undefined) throw new Error("[FF.Game.switchGameState] Your GameState have to contain an isStarted public property");
	if(this.currentGameState.setup === undefined) throw new Error("[FF.Game.switchGameState] Your GameState have to contain a setup() function");

	if(this.currentGameState.isStarted == false){
		FF.InputManager.resetPressedKeys();
		this.currentGameState.setup();
		this.currentGameState.isStarted = true;
	}
};
<commit_msg>Updating game routine with Gamepad support<commit_after>/**
 * Overall game manager
 *
 * @class Game
 * @constructor
 * @param {Object} gamestate - Your first game state (an intro gamestate for example)
 * @param {Object} options - {backgroundColor : don't need to be a super hero to understand this one, view : If you don't want Fresh Flesh to create a default screen-sized renderer, give it your own (optional)}
 *
 * @example
 * var intro = {
 * 		isStarted : false,
 * 		setup : function(){ console.log("Setup"); },
 * 		update : function(){ console.log("Update"); },
 * 		draw : function(){ console.log("Draw"); }
 * };
 *
 * var game = new FF.Game(intro);
 * game.start();
 */
FF.Game = function(gamestate, options){
	var that = this;

	/**
	 * In case of calling to switchGameState(), we save the previous gamestate if we want to re-use it later (like showing a game pause menu, and go back to the main gamestate
	 * @property previousGameState
	 * @type Object
	 */
	this.previousGameState = null;

	/**
	 * The running game state of your game
	 * @property currentGameState
	 * @type Object
	 */
	this.currentGameState = gamestate;

	/**
	 * Hex background color of the game
	 * @property backgroundColor
	 * @type String
	 */
	this.backgroundColor = options.backgroundColor || "#FFF";

	/**
	 * Last time requestAnimationFrame was called
	 * @property lastCalledTime
	 * @type Date
	 */
	this.lastCalledTime = null;

	/**
	 * Current FPS count
	 * @property fps
	 * @type Integer
	 */
	this.fps = 0;

	/**
	 * Used to start the gamestate given to the FF.Game class constructor
	 * @method start
	 */
	this.launch = function(){
		if(this.currentGameState.isStarted == true) throw new Error("[FF.Game.Start] Your GameState is already started");
		if(this.currentGameState.setup === undefined) throw new Error("[FF.Game.Start] Your GameState have to contain a setup() function");

		if(FF.Render.canvas === undefined){
			FF.Render = FF.Util.createRender(options.view);
		}

		if(FF.InputManager.isSetup == false){
			FF.InputManager.setup();
		}

		this.currentGameState.setup();
		if(this.currentGameState.isStarted === undefined || this.currentGameState.isStarted == false) this.currentGameState.isStarted = true;

		requestAnimation();
	};

	/**
	 * Called by requestAnimationFrame to run your gameloops
	 * @method requestAnimation
	 * @private
	 */
	function requestAnimation(){
		if(that.currentGameState.update === undefined) throw new Error("[FF.Game.requestAnimationFrame] Your GameState have to contain an update() function (even if you let it empty)");
		if(that.currentGameState.draw === undefined) throw new Error("[FF.Game.requestAnimationFrame] Your GameState have to contain an draw() function (even if you let it empty)");

		//From v0.3_alpha - Added support for Gamepad API
		FF.InputManager.getGamepads();

		if(that.currentGameState.isStarted){
			that.currentGameState.update();

			//Clearing
			FF.Render.clearRect(0,0,FF.Render.getWidth(),FF.Render.getHeight());

			//Setting the background color
			FF.Render.setBackgroundColor(that.backgroundColor);

			that.currentGameState.draw();
		}

		if(that.lastCalledTime == null) {
			that.lastCalledTime = new Date().getTime();
			that.fps = 0;
			requestAnimationFrame(requestAnimation);
			return;
		}
		var delta = (new Date().getTime() - that.lastCalledTime)/1000;
		that.lastCalledTime = new Date().getTime();
		that.fps = (1/delta).toFixed(1);

		requestAnimationFrame(requestAnimation);
	};
};

/**
 * Allows you to switch between different gamestates, already started or not
 * @method switchGameState
 * @param {Object} gamestate - The new or previous (use your_game.previousGameState) gamestate to use in the main game loop
 * @param {Boolean} reset - Wether system have to reset the given gamestate (usefull when user press "Retry" in a pause menu, for example
 */
FF.Game.prototype.switchGameState = function(gamestate, reset){
	if(gamestate === undefined) throw new Error("[FF.Game.switchGameState] Your gamestate is undefined (not instanciated, like gs = new Blablabla();)");

	this.previousGameState = this.currentGameState;
	this.currentGameState = (reset) ? new gamestate.constructor : gamestate;

	//if(this.currentGameState.isStarted === undefined) throw new Error("[FF.Game.switchGameState] Your GameState have to contain an isStarted public property");
	if(this.currentGameState.setup === undefined) throw new Error("[FF.Game.switchGameState] Your GameState have to contain a setup() function");

	if(this.currentGameState.isStarted == false){
		FF.InputManager.resetPressedKeys();
		this.currentGameState.setup();
		this.currentGameState.isStarted = true;
	}
};
<|endoftext|>


<commit_before>var assert = require('assert')
var ObservVarlist = require('observ-varlist')
var dotProp = require('dot-prop')
var extend = require('xtend')
var assign = require('xtend/mutable')
// var ListMethods = require('./methods')
var joinPaths = require('../util/join-paths')

function getPathProp (obj, path) {
  return dotProp.get(obj, path.join('.'))
}

function noop () {}

module.exports = function FalcorList (model, options) {
  options = options || {}
  var store = options.store
  var prefix = options.prefix

  assert.ok(store && typeof store.put === 'function', 'options.store required')

  var state = ObservVarlist([])

  // All the other properties can be given through assign
  return assign(
    state,
    // ListMethods(model, prefix),
    {
      // saveRange: saveRange,
      fetchData: fetchData,
      fetchRange: fetchRange,
      fetchRangeAndData: fetchRangeAndData
    }
  )

  // function saveRange (values, callback) {
  //   if (arguments.length === 1) {
  //     callback = values
  //     values = state()
  //   }

  //   model.setLocal([
  //     {path: prefix.concat('from'), value: values.from},
  //     {path: prefix.concat('length'), value: values.count}
  //   ], callback)
  // }

  function fetchRangeAndData (callback) {
    callback = callback || noop

    fetchRange(function (error) {
      if (error) return callback(error)
      fetchData(callback)
    })
  }

  function fetchRange (callback) {
    callback = callback || noop

    model.invalidate(prefix.concat('from'), prefix.concat('length'), onInvalidate)

    function onInvalidate () {
      model.get(prefix.concat('from'), prefix.concat('length'), onRange)
    }

    function onRange (error, graph) {
      if (error || !graph) {
        return callback(error || new TypeError('fetchRange: No data at ' + JSON.stringify(prefix)))
      }

      var rangeData = getPathProp(graph.json, prefix)
      state.from.set(rangeData.from || 0)
      state.count.set(rangeData.length || 0)

      callback(null, state())
    }
  }

  function fetchData (callback) {
    callback = callback || noop

    var listPrefix = prefix.concat({
      from: state.from(),
      length: state.count()
    })
    model.invalidate(listPrefix, function () {
      model.get(joinPaths(listPrefix, store.paths()), onData)
    })

    function onData (error, graph) {
      if (error || !graph) {
        return callback(error || new TypeError('fetchData: No data at ' + JSON.stringify(prefix)))
      }

      var list = getPathProp(graph.json, prefix)
      state.reset(extend(list, {
        from: state.from(),
        length: state.count()
      }))

      callback(null, state())
    }
  }
}
<commit_msg>fix: wrap list items in obs<commit_after>var assert = require('assert')
var ObservVarlist = require('observ-varlist')
var dotProp = require('dot-prop')

var extend = require('xtend')
var assign = require('xtend/mutable')
var partialRight = require('ap').partialRight
// var ListMethods = require('./methods')
var joinPaths = require('../util/join-paths')

function getPathProp (obj, path) {
  return dotProp.get(obj, path.join('.'))
}

function noop () {}

module.exports = function FalcorList (model, options) {
  options = options || {}
  var store = options.store
  var prefix = options.prefix
  var keyPath = options.keyPath || ['id']
  var keyGetter = partialRight(getPathProp, keyPath)

  assert.ok(store && typeof store.put === 'function', 'options.store required')

  var state = ObservVarlist([])

  // All the other properties can be given through assign
  return assign(
    state,
    // ListMethods(model, prefix),
    {
      // saveRange: saveRange,
      fetchData: fetchData,
      fetchRange: fetchRange,
      fetchRangeAndData: fetchRangeAndData
    }
  )

  // function saveRange (values, callback) {
  //   if (arguments.length === 1) {
  //     callback = values
  //     values = state()
  //   }

  //   model.setLocal([
  //     {path: prefix.concat('from'), value: values.from},
  //     {path: prefix.concat('length'), value: values.count}
  //   ], callback)
  // }

  function fetchRangeAndData (callback) {
    callback = callback || noop

    fetchRange(function (error) {
      if (error) return callback(error)
      fetchData(callback)
    })
  }

  function fetchRange (callback) {
    callback = callback || noop

    model.invalidate(prefix.concat('from'), prefix.concat('length'), onInvalidate)

    function onInvalidate () {
      model.get(prefix.concat('from'), prefix.concat('length'), onRange)
    }

    function onRange (error, graph) {
      if (error || !graph) {
        return callback(error || new TypeError('fetchRange: No data at ' + JSON.stringify(prefix)))
      }

      var rangeData = getPathProp(graph.json, prefix)
      state.from.set(rangeData.from || 0)
      state.count.set(rangeData.length || 0)

      callback(null, state())
    }
  }

  function fetchData (callback) {
    callback = callback || noop

    var listPrefix = prefix.concat({
      from: state.from(),
      length: state.count()
    })

    model.invalidate(listPrefix, function () {
      model.get(joinPaths(listPrefix, store.paths()), onData)
    })

    function onData (error, graph) {
      if (error || !graph) {
        return callback(error || new TypeError('fetchData: No data at ' + JSON.stringify(prefix)))
      }

      var graphData = getPathProp(graph.json, prefix)
      var result = {}

      for (var i = state.from(), ii = state.from() + state.count(); i < ii; i++) {
        var data = graphData[i]
        var id = getId(data)
        var value = store.put(id, data)
        result[i] = value
      }

      state.reset(extend(result, {
        from: state.from(),
        length: state.count()
      }))

      callback(null, state())
    }
  }

  function getId (data) {
    var id = keyGetter(data)
    if (id == null) {
      throw new TypeError('Key path ' + JSON.stringify(keyPath) +
                          ' is empty for data at ' + JSON.stringify(prefix))
    }
    return id
  }
}
<|endoftext|>


<commit_before>const snekfetch = require('snekfetch');
const { Colors, DefaultOptions, Endpoints } = require('./Constants');
const { Error: DiscordError, RangeError, TypeError } = require('../errors');
const has = (o, k) => Object.prototype.hasOwnProperty.call(o, k);
const splitPathRe = /^(\/?|)([\s\S]*?)((?:\.{1,2}|[^/]+?|)(\.[^./]*|))(?:[/]*)$/;

/**
 * Contains various general-purpose utility methods. These functions are also available on the base `Discord` object.
 */
class Util {
  constructor() {
    throw new Error(`The ${this.constructor.name} class may not be instantiated.`);
  }

  /**
   * Splits a string into multiple chunks at a designated character that do not exceed a specific length.
   * @param {string} text Content to split
   * @param {SplitOptions} [options] Options controlling the behaviour of the split
   * @returns {string|string[]}
   */
  static splitMessage(text, { maxLength = 1950, char = '\n', prepend = '', append = '' } = {}) {
    if (text.length <= maxLength) return text;
    const splitText = text.split(char);
    if (splitText.length === 1) throw new RangeError('SPLIT_MAX_LEN');
    const messages = [''];
    let msg = 0;
    for (let i = 0; i < splitText.length; i++) {
      if (messages[msg].length + splitText[i].length + 1 > maxLength) {
        messages[msg] += append;
        messages.push(prepend);
        msg++;
      }
      messages[msg] += (messages[msg].length > 0 && messages[msg] !== prepend ? char : '') + splitText[i];
    }
    return messages.filter(m => m);
  }

  /**
   * Escapes any Discord-flavour markdown in a string.
   * @param {string} text Content to escape
   * @param {boolean} [onlyCodeBlock=false] Whether to only escape codeblocks (takes priority)
   * @param {boolean} [onlyInlineCode=false] Whether to only escape inline code
   * @returns {string}
   */
  static escapeMarkdown(text, onlyCodeBlock = false, onlyInlineCode = false) {
    if (onlyCodeBlock) return text.replace(/```/g, '`\u200b``');
    if (onlyInlineCode) return text.replace(/\\(`|\\)/g, '$1').replace(/(`|\\)/g, '\\$1');
    return text.replace(/\\(\*|_|`|~|\\)/g, '$1').replace(/(\*|_|`|~|\\)/g, '\\$1');
  }

  /**
   * Gets the recommended shard count from Discord.
   * @param {string} token Discord auth token
   * @param {number} [guildsPerShard=1000] Number of guilds per shard
   * @returns {Promise<number>} The recommended number of shards
   */
  static fetchRecommendedShards(token, guildsPerShard = 1000) {
    return new Promise((resolve, reject) => {
      if (!token) throw new DiscordError('TOKEN_MISSING');
      snekfetch.get(`${DefaultOptions.http.api}/v${DefaultOptions.http.version}${Endpoints.botGateway}`)
        .set('Authorization', `Bot ${token.replace(/^Bot\s*/i, '')}`)
        .end((err, res) => {
          if (err) reject(err);
          resolve(res.body.shards * (1000 / guildsPerShard));
        });
    });
  }

  /**
   * Parses emoji info out of a string. The string must be one of:
   * * A UTF-8 emoji (no ID)
   * * A URL-encoded UTF-8 emoji (no ID)
   * * A Discord custom emoji (`<:name:id>` or `<a:name:id>`)
   * @param {string} text Emoji string to parse
   * @returns {Object} Object with `animated`, `name`, and `id` properties
   * @private
   */
  static parseEmoji(text) {
    if (text.includes('%')) text = decodeURIComponent(text);
    if (!text.includes(':')) return { animated: false, name: text, id: null };
    const m = text.match(/<?(a)?:?(\w{2,32}):(\d{17,19})>?/);
    if (!m) return null;
    return { animated: Boolean(m[1]), name: m[2], id: m[3] };
  }

  /**
   * Checks whether the arrays are equal, also removes duplicated entries from b.
   * @param {Array<*>} a Array which will not be modified.
   * @param {Array<*>} b Array to remove duplicated entries from.
   * @returns {boolean} Whether the arrays are equal.
   * @private
   */
  static arraysEqual(a, b) {
    if (a === b) return true;
    if (a.length !== b.length) return false;

    for (const item of a) {
      const ind = b.indexOf(item);
      if (ind !== -1) b.splice(ind, 1);
    }

    return b.length === 0;
  }

  /**
   * Shallow-copies an object with its class/prototype intact.
   * @param {Object} obj Object to clone
   * @returns {Object}
   * @private
   */
  static cloneObject(obj) {
    return Object.assign(Object.create(obj), obj);
  }

  /**
   * Sets default properties on an object that aren't already specified.
   * @param {Object} def Default properties
   * @param {Object} given Object to assign defaults to
   * @returns {Object}
   * @private
   */
  static mergeDefault(def, given) {
    if (!given) return def;
    for (const key in def) {
      if (!has(given, key) || given[key] === undefined) {
        given[key] = def[key];
      } else if (given[key] === Object(given[key])) {
        given[key] = Util.mergeDefault(def[key], given[key]);
      }
    }

    return given;
  }

  /**
   * Converts an ArrayBuffer or string to a Buffer.
   * @param {ArrayBuffer|string} ab ArrayBuffer to convert
   * @returns {Buffer}
   * @private
   */
  static convertToBuffer(ab) {
    if (typeof ab === 'string') ab = Util.str2ab(ab);
    return Buffer.from(ab);
  }

  /**
   * Converts a string to an ArrayBuffer.
   * @param {string} str String to convert
   * @returns {ArrayBuffer}
   * @private
   */
  static str2ab(str) {
    const buffer = new ArrayBuffer(str.length * 2);
    const view = new Uint16Array(buffer);
    for (var i = 0, strLen = str.length; i < strLen; i++) view[i] = str.charCodeAt(i);
    return buffer;
  }

  /**
   * Makes an Error from a plain info object.
   * @param {Object} obj Error info
   * @param {string} obj.name Error type
   * @param {string} obj.message Message for the error
   * @param {string} obj.stack Stack for the error
   * @returns {Error}
   * @private
   */
  static makeError(obj) {
    const err = new Error(obj.message);
    err.name = obj.name;
    err.stack = obj.stack;
    return err;
  }

  /**
   * Makes a plain error info object from an Error.
   * @param {Error} err Error to get info from
   * @returns {Object}
   * @private
   */
  static makePlainError(err) {
    return {
      name: err.name,
      message: err.message,
      stack: err.stack,
    };
  }

  /**
   * Moves an element in an array *in place*.
   * @param {Array<*>} array Array to modify
   * @param {*} element Element to move
   * @param {number} newIndex Index or offset to move the element to
   * @param {boolean} [offset=false] Move the element by an offset amount rather than to a set index
   * @returns {number}
   * @private
   */
  static moveElementInArray(array, element, newIndex, offset = false) {
    const index = array.indexOf(element);
    newIndex = (offset ? index : 0) + newIndex;
    if (newIndex > -1 && newIndex < array.length) {
      const removedElement = array.splice(index, 1)[0];
      array.splice(newIndex, 0, removedElement);
    }
    return array.indexOf(element);
  }

  /**
   * Data that can be resolved to give a string. This can be:
   * * A string
   * * An array (joined with a new line delimiter to give a string)
   * * Any value
   * @typedef {string|Array|*} StringResolvable
   */

  /**
   * Resolves a StringResolvable to a string.
   * @param {StringResolvable} data The string resolvable to resolve
   * @returns {string}
   */
  static resolveString(data) {
    if (typeof data === 'string') return data;
    if (data instanceof Array) return data.join('\n');
    return String(data);
  }

  /**
   * Can be a number, hex string, an RGB array like:
   * ```js
   * [255, 0, 255] // purple
   * ```
   * or one of the following strings:
   * - `DEFAULT`
   * - `AQUA`
   * - `GREEN`
   * - `BLUE`
   * - `PURPLE`
   * - `GOLD`
   * - `ORANGE`
   * - `RED`
   * - `GREY`
   * - `DARKER_GREY`
   * - `NAVY`
   * - `DARK_AQUA`
   * - `DARK_GREEN`
   * - `DARK_BLUE`
   * - `DARK_PURPLE`
   * - `DARK_GOLD`
   * - `DARK_ORANGE`
   * - `DARK_RED`
   * - `DARK_GREY`
   * - `LIGHT_GREY`
   * - `DARK_NAVY`
   * - `RANDOM`
   * @typedef {string|number|number[]} ColorResolvable
   */

  /**
   * Resolves a ColorResolvable into a color number.
   * @param {ColorResolvable} color Color to resolve
   * @returns {number} A color
   */
  static resolveColor(color) {
    if (typeof color === 'string') {
      if (color === 'RANDOM') return Math.floor(Math.random() * (0xFFFFFF + 1));
      color = Colors[color] || parseInt(color.replace('#', ''), 16);
    } else if (color instanceof Array) {
      color = (color[0] << 16) + (color[1] << 8) + color[2];
    }

    if (color < 0 || color > 0xFFFFFF) throw new RangeError('COLOR_RANGE');
    else if (color && isNaN(color)) throw new TypeError('COLOR_CONVERT');

    return color;
  }

  /**
   * Sorts by Discord's position and ID.
   * @param  {Collection} collection Collection of objects to sort
   * @returns {Collection}
   */
  static discordSort(collection) {
    return collection.sort((a, b) =>
      a.rawPosition - b.rawPosition ||
      parseInt(a.id.slice(0, -10)) - parseInt(b.id.slice(0, -10)) ||
      parseInt(a.id.slice(10)) - parseInt(b.id.slice(10))
    );
  }

  /**
   * Sets the position of a Channel or Role.
   * @param {Channel|Role} item Object to set the position of
   * @param {number} position New position for the object
   * @param {boolean} relative Whether `position` is relative to its current position
   * @param {Collection<string, Channel|Role>} sorted A collection of the objects sorted properly
   * @param {APIRouter} route Route to call PATCH on
   * @param {string} [reason] Reason for the change
   * @returns {Promise<Object[]>} Updated item list, with `id` and `position` properties
   * @private
   */
  static setPosition(item, position, relative, sorted, route, reason) {
    let updatedItems = sorted.array();
    Util.moveElementInArray(updatedItems, item, position, relative);
    updatedItems = updatedItems.map((r, i) => ({ id: r.id, position: i }));
    return route.patch({ data: updatedItems, reason }).then(() => updatedItems);
  }

  /**
   * Alternative to Node's `path.basename` that we have for some (probably stupid) reason.
   * @param {string} path Path to get the basename of
   * @param {string} [ext] File extension to remove
   * @returns {string} Basename of the path
   * @private
   */
  static basename(path, ext) {
    let f = splitPathRe.exec(path)[3];
    if (ext && f.endsWith(ext)) f = f.slice(0, -ext.length);
    return f;
  }

  /**
   * Transforms a snowflake from a decimal string to a bit string.
   * @param  {Snowflake} num Snowflake to be transformed
   * @returns {string}
   * @private
   */
  static idToBinary(num) {
    let bin = '';
    let high = parseInt(num.slice(0, -10)) || 0;
    let low = parseInt(num.slice(-10));
    while (low > 0 || high > 0) {
      bin = String(low & 1) + bin;
      low = Math.floor(low / 2);
      if (high > 0) {
        low += 5000000000 * (high % 2);
        high = Math.floor(high / 2);
      }
    }
    return bin;
  }

  /**
   * Transforms a snowflake from a bit string to a decimal string.
   * @param  {string} num Bit string to be transformed
   * @returns {Snowflake}
   * @private
   */
  static binaryToID(num) {
    let dec = '';

    while (num.length > 50) {
      const high = parseInt(num.slice(0, -32), 2);
      const low = parseInt((high % 10).toString(2) + num.slice(-32), 2);

      dec = (low % 10).toString() + dec;
      num = Math.floor(high / 10).toString(2) + Math.floor(low / 10).toString(2).padStart(32, '0');
    }

    num = parseInt(num, 2);
    while (num > 0) {
      dec = (num % 10).toString() + dec;
      num = Math.floor(num / 10);
    }

    return dec;
  }

  /**
   * Creates a Promise that resolves after a specified duration.
   * @param {number} ms How long to wait before resolving (in milliseconds)
   * @returns {Promise<void>}
   * @private
   */
  static delayFor(ms) {
    return new Promise(resolve => {
      setTimeout(resolve, ms);
    });
  }
}

module.exports = Util;
<commit_msg>Make Util#splitMessage handle edge cases properly (#2212)<commit_after>const snekfetch = require('snekfetch');
const { Colors, DefaultOptions, Endpoints } = require('./Constants');
const { Error: DiscordError, RangeError, TypeError } = require('../errors');
const has = (o, k) => Object.prototype.hasOwnProperty.call(o, k);
const splitPathRe = /^(\/?|)([\s\S]*?)((?:\.{1,2}|[^/]+?|)(\.[^./]*|))(?:[/]*)$/;

/**
 * Contains various general-purpose utility methods. These functions are also available on the base `Discord` object.
 */
class Util {
  constructor() {
    throw new Error(`The ${this.constructor.name} class may not be instantiated.`);
  }

  /**
   * Splits a string into multiple chunks at a designated character that do not exceed a specific length.
   * @param {string} text Content to split
   * @param {SplitOptions} [options] Options controlling the behaviour of the split
   * @returns {string|string[]}
   */
  static splitMessage(text, { maxLength = 2000, char = '\n', prepend = '', append = '' } = {}) {
    if (text.length <= maxLength) return text;
    const splitText = text.split(char);
    if (splitText.length === 1) throw new RangeError('SPLIT_MAX_LEN');
    const messages = [];
    let msg = '';
    for (const chunk of splitText) {
      if (msg && (msg + char + chunk + append).length > maxLength) {
        messages.push(msg + append);
        msg = prepend;
      }
      msg += (msg && msg !== prepend ? char : '') + chunk;
    }
    return messages.concat(msg).filter(m => m);
  }

  /**
   * Escapes any Discord-flavour markdown in a string.
   * @param {string} text Content to escape
   * @param {boolean} [onlyCodeBlock=false] Whether to only escape codeblocks (takes priority)
   * @param {boolean} [onlyInlineCode=false] Whether to only escape inline code
   * @returns {string}
   */
  static escapeMarkdown(text, onlyCodeBlock = false, onlyInlineCode = false) {
    if (onlyCodeBlock) return text.replace(/```/g, '`\u200b``');
    if (onlyInlineCode) return text.replace(/\\(`|\\)/g, '$1').replace(/(`|\\)/g, '\\$1');
    return text.replace(/\\(\*|_|`|~|\\)/g, '$1').replace(/(\*|_|`|~|\\)/g, '\\$1');
  }

  /**
   * Gets the recommended shard count from Discord.
   * @param {string} token Discord auth token
   * @param {number} [guildsPerShard=1000] Number of guilds per shard
   * @returns {Promise<number>} The recommended number of shards
   */
  static fetchRecommendedShards(token, guildsPerShard = 1000) {
    return new Promise((resolve, reject) => {
      if (!token) throw new DiscordError('TOKEN_MISSING');
      snekfetch.get(`${DefaultOptions.http.api}/v${DefaultOptions.http.version}${Endpoints.botGateway}`)
        .set('Authorization', `Bot ${token.replace(/^Bot\s*/i, '')}`)
        .end((err, res) => {
          if (err) reject(err);
          resolve(res.body.shards * (1000 / guildsPerShard));
        });
    });
  }

  /**
   * Parses emoji info out of a string. The string must be one of:
   * * A UTF-8 emoji (no ID)
   * * A URL-encoded UTF-8 emoji (no ID)
   * * A Discord custom emoji (`<:name:id>` or `<a:name:id>`)
   * @param {string} text Emoji string to parse
   * @returns {Object} Object with `animated`, `name`, and `id` properties
   * @private
   */
  static parseEmoji(text) {
    if (text.includes('%')) text = decodeURIComponent(text);
    if (!text.includes(':')) return { animated: false, name: text, id: null };
    const m = text.match(/<?(a)?:?(\w{2,32}):(\d{17,19})>?/);
    if (!m) return null;
    return { animated: Boolean(m[1]), name: m[2], id: m[3] };
  }

  /**
   * Checks whether the arrays are equal, also removes duplicated entries from b.
   * @param {Array<*>} a Array which will not be modified.
   * @param {Array<*>} b Array to remove duplicated entries from.
   * @returns {boolean} Whether the arrays are equal.
   * @private
   */
  static arraysEqual(a, b) {
    if (a === b) return true;
    if (a.length !== b.length) return false;

    for (const item of a) {
      const ind = b.indexOf(item);
      if (ind !== -1) b.splice(ind, 1);
    }

    return b.length === 0;
  }

  /**
   * Shallow-copies an object with its class/prototype intact.
   * @param {Object} obj Object to clone
   * @returns {Object}
   * @private
   */
  static cloneObject(obj) {
    return Object.assign(Object.create(obj), obj);
  }

  /**
   * Sets default properties on an object that aren't already specified.
   * @param {Object} def Default properties
   * @param {Object} given Object to assign defaults to
   * @returns {Object}
   * @private
   */
  static mergeDefault(def, given) {
    if (!given) return def;
    for (const key in def) {
      if (!has(given, key) || given[key] === undefined) {
        given[key] = def[key];
      } else if (given[key] === Object(given[key])) {
        given[key] = Util.mergeDefault(def[key], given[key]);
      }
    }

    return given;
  }

  /**
   * Converts an ArrayBuffer or string to a Buffer.
   * @param {ArrayBuffer|string} ab ArrayBuffer to convert
   * @returns {Buffer}
   * @private
   */
  static convertToBuffer(ab) {
    if (typeof ab === 'string') ab = Util.str2ab(ab);
    return Buffer.from(ab);
  }

  /**
   * Converts a string to an ArrayBuffer.
   * @param {string} str String to convert
   * @returns {ArrayBuffer}
   * @private
   */
  static str2ab(str) {
    const buffer = new ArrayBuffer(str.length * 2);
    const view = new Uint16Array(buffer);
    for (var i = 0, strLen = str.length; i < strLen; i++) view[i] = str.charCodeAt(i);
    return buffer;
  }

  /**
   * Makes an Error from a plain info object.
   * @param {Object} obj Error info
   * @param {string} obj.name Error type
   * @param {string} obj.message Message for the error
   * @param {string} obj.stack Stack for the error
   * @returns {Error}
   * @private
   */
  static makeError(obj) {
    const err = new Error(obj.message);
    err.name = obj.name;
    err.stack = obj.stack;
    return err;
  }

  /**
   * Makes a plain error info object from an Error.
   * @param {Error} err Error to get info from
   * @returns {Object}
   * @private
   */
  static makePlainError(err) {
    return {
      name: err.name,
      message: err.message,
      stack: err.stack,
    };
  }

  /**
   * Moves an element in an array *in place*.
   * @param {Array<*>} array Array to modify
   * @param {*} element Element to move
   * @param {number} newIndex Index or offset to move the element to
   * @param {boolean} [offset=false] Move the element by an offset amount rather than to a set index
   * @returns {number}
   * @private
   */
  static moveElementInArray(array, element, newIndex, offset = false) {
    const index = array.indexOf(element);
    newIndex = (offset ? index : 0) + newIndex;
    if (newIndex > -1 && newIndex < array.length) {
      const removedElement = array.splice(index, 1)[0];
      array.splice(newIndex, 0, removedElement);
    }
    return array.indexOf(element);
  }

  /**
   * Data that can be resolved to give a string. This can be:
   * * A string
   * * An array (joined with a new line delimiter to give a string)
   * * Any value
   * @typedef {string|Array|*} StringResolvable
   */

  /**
   * Resolves a StringResolvable to a string.
   * @param {StringResolvable} data The string resolvable to resolve
   * @returns {string}
   */
  static resolveString(data) {
    if (typeof data === 'string') return data;
    if (data instanceof Array) return data.join('\n');
    return String(data);
  }

  /**
   * Can be a number, hex string, an RGB array like:
   * ```js
   * [255, 0, 255] // purple
   * ```
   * or one of the following strings:
   * - `DEFAULT`
   * - `AQUA`
   * - `GREEN`
   * - `BLUE`
   * - `PURPLE`
   * - `GOLD`
   * - `ORANGE`
   * - `RED`
   * - `GREY`
   * - `DARKER_GREY`
   * - `NAVY`
   * - `DARK_AQUA`
   * - `DARK_GREEN`
   * - `DARK_BLUE`
   * - `DARK_PURPLE`
   * - `DARK_GOLD`
   * - `DARK_ORANGE`
   * - `DARK_RED`
   * - `DARK_GREY`
   * - `LIGHT_GREY`
   * - `DARK_NAVY`
   * - `RANDOM`
   * @typedef {string|number|number[]} ColorResolvable
   */

  /**
   * Resolves a ColorResolvable into a color number.
   * @param {ColorResolvable} color Color to resolve
   * @returns {number} A color
   */
  static resolveColor(color) {
    if (typeof color === 'string') {
      if (color === 'RANDOM') return Math.floor(Math.random() * (0xFFFFFF + 1));
      color = Colors[color] || parseInt(color.replace('#', ''), 16);
    } else if (color instanceof Array) {
      color = (color[0] << 16) + (color[1] << 8) + color[2];
    }

    if (color < 0 || color > 0xFFFFFF) throw new RangeError('COLOR_RANGE');
    else if (color && isNaN(color)) throw new TypeError('COLOR_CONVERT');

    return color;
  }

  /**
   * Sorts by Discord's position and ID.
   * @param  {Collection} collection Collection of objects to sort
   * @returns {Collection}
   */
  static discordSort(collection) {
    return collection.sort((a, b) =>
      a.rawPosition - b.rawPosition ||
      parseInt(a.id.slice(0, -10)) - parseInt(b.id.slice(0, -10)) ||
      parseInt(a.id.slice(10)) - parseInt(b.id.slice(10))
    );
  }

  /**
   * Sets the position of a Channel or Role.
   * @param {Channel|Role} item Object to set the position of
   * @param {number} position New position for the object
   * @param {boolean} relative Whether `position` is relative to its current position
   * @param {Collection<string, Channel|Role>} sorted A collection of the objects sorted properly
   * @param {APIRouter} route Route to call PATCH on
   * @param {string} [reason] Reason for the change
   * @returns {Promise<Object[]>} Updated item list, with `id` and `position` properties
   * @private
   */
  static setPosition(item, position, relative, sorted, route, reason) {
    let updatedItems = sorted.array();
    Util.moveElementInArray(updatedItems, item, position, relative);
    updatedItems = updatedItems.map((r, i) => ({ id: r.id, position: i }));
    return route.patch({ data: updatedItems, reason }).then(() => updatedItems);
  }

  /**
   * Alternative to Node's `path.basename` that we have for some (probably stupid) reason.
   * @param {string} path Path to get the basename of
   * @param {string} [ext] File extension to remove
   * @returns {string} Basename of the path
   * @private
   */
  static basename(path, ext) {
    let f = splitPathRe.exec(path)[3];
    if (ext && f.endsWith(ext)) f = f.slice(0, -ext.length);
    return f;
  }

  /**
   * Transforms a snowflake from a decimal string to a bit string.
   * @param  {Snowflake} num Snowflake to be transformed
   * @returns {string}
   * @private
   */
  static idToBinary(num) {
    let bin = '';
    let high = parseInt(num.slice(0, -10)) || 0;
    let low = parseInt(num.slice(-10));
    while (low > 0 || high > 0) {
      bin = String(low & 1) + bin;
      low = Math.floor(low / 2);
      if (high > 0) {
        low += 5000000000 * (high % 2);
        high = Math.floor(high / 2);
      }
    }
    return bin;
  }

  /**
   * Transforms a snowflake from a bit string to a decimal string.
   * @param  {string} num Bit string to be transformed
   * @returns {Snowflake}
   * @private
   */
  static binaryToID(num) {
    let dec = '';

    while (num.length > 50) {
      const high = parseInt(num.slice(0, -32), 2);
      const low = parseInt((high % 10).toString(2) + num.slice(-32), 2);

      dec = (low % 10).toString() + dec;
      num = Math.floor(high / 10).toString(2) + Math.floor(low / 10).toString(2).padStart(32, '0');
    }

    num = parseInt(num, 2);
    while (num > 0) {
      dec = (num % 10).toString() + dec;
      num = Math.floor(num / 10);
    }

    return dec;
  }

  /**
   * Creates a Promise that resolves after a specified duration.
   * @param {number} ms How long to wait before resolving (in milliseconds)
   * @returns {Promise<void>}
   * @private
   */
  static delayFor(ms) {
    return new Promise(resolve => {
      setTimeout(resolve, ms);
    });
  }
}

module.exports = Util;
<|endoftext|>


<commit_before>import { React, PropTypes, withRouter, action, observer }  from 'vendor';
import { Button } from 'react-bootstrap';
import { OnboardingNag, GotItOnboardingNag, Body, Footer } from './onboarding-nag';

export default
@withRouter
@observer
class DisplayPreviewMessage extends React.Component {

  static propTypes = {
    ux: PropTypes.object.isRequired,
    history: PropTypes.object.isRequired,
  }

  @action.bound onContinue(cb) {
    this.props.ux.hasViewedDisplayPreviewMessage();
    cb();
  }

  render() {
    return (
      <GotItOnboardingNag {...this.props} promptRenderer={this.renderPrompt} />
    );
  }

  renderPrompt = (onAddCourse, onContinue) => {
    return (
      <OnboardingNag className="only-preview">

{this.props.ux.course.offering.preview_message}

          <Button onClick={() => this.onContinue(onContinue)} className="continue">Ok</Button>

      </OnboardingNag>
    );
  }
}
<commit_msg>support using html formatting<commit_after>import { React, PropTypes, withRouter, action, observer }  from 'vendor';
import { Button } from 'react-bootstrap';
import { OnboardingNag, GotItOnboardingNag, Body, Footer } from './onboarding-nag';

export default
@withRouter
@observer
class DisplayPreviewMessage extends React.Component {

  static propTypes = {
    ux: PropTypes.object.isRequired,
    history: PropTypes.object.isRequired,
  }

  @action.bound onContinue(cb) {
    this.props.ux.hasViewedDisplayPreviewMessage();
    cb();
  }

  render() {
    return (
      <GotItOnboardingNag {...this.props} promptRenderer={this.renderPrompt} />
    );
  }

  renderPrompt = (onAddCourse, onContinue) => {
    return (
      <OnboardingNag className="only-preview">

          <Button onClick={() => this.onContinue(onContinue)} className="continue">Ok</Button>

      </OnboardingNag>
    );
  }
}
<|endoftext|>


<commit_before>'use strict';

var sharp = require('sharp');
var map   = require('map-stream');
var env   = require('../config/environment_vars');
var dims  = require('../lib/dimensions');

module.exports = function () {

  return map( function(image, callback) {

    // do nothing if there is an error on the image object
    if (image.isError()){
      return callback(null, image);
    }

    // let this pass through if we are requesting the metadata as JSON
    if (image.modifiers.action === 'json'){
      image.log.log('resize: json metadata call');
      return callback(null, image);
    }

    if (image.modifiers.action === 'original' && env.RESIZE_PROCESS_ORIGINAL === false){
      image.log.log('resize: original no resize');
      return callback(null, image);
    }

    image.log.time('resize');

    var resizeResponse = function (err, buffer) {
      if (err) {
        image.log.error('resize error', err);
        image.error = new Error(err);
      }
      else {
        image.contents = buffer;
      }

      image.log.timeEnd('resize');
      callback(null, image);
    };

    var r = sharp(image.contents);

    // never enlarge an image beyonds its original size
    r.withoutEnlargement();

    // if allowed auto rotate images, very helpful for photos off of an iphone
    // which are landscape by default and the metadata tells them what to show.
    if (env.AUTO_ORIENT) {
      r.rotate();
    }

    // by default we remove the metadata from resized images, setting the env
    // var to false can retain it.
    if (!env.REMOVE_METADATA) {
      r.withMetadata();
    }

    var d, wd, ht;

    switch(image.modifiers.action){
    case 'original' :
      r.toBuffer(resizeResponse);
      break;

    case 'resize':
      r.resize(image.modifiers.width, image.modifiers.height);
      r.max();
      r.toBuffer(resizeResponse);
      break;

    case 'square':
      r.metadata(function(err, metadata){
        if (err){
          image.error = new Error(err);
          callback(null, image);
          return;
        }

        d = dims.cropFill(image.modifiers, metadata);

        // resize then crop the image
        r.resize(
            d.resize.width,
            d.resize.height
          ).extract({
            left: d.crop.x,
            top: d.crop.y,
            width: d.crop.width,
            height: d.crop.height
          });

        r.toBuffer(resizeResponse);
      });

      break;

    case 'crop':
      r.metadata(function(err, size){
        if (err){
          image.error = new Error(err);
          callback(null, image);
          return;
        }

        switch(image.modifiers.crop){
        case 'fit':
          r.resize(image.modifiers.width, image.modifiers.height);
          r.max();
          break;
        case 'fill':
          d = dims.cropFill(image.modifiers, size);

          r.resize(
              d.resize.width,
              d.resize.height
            ).extract({
              left: d.crop.x,
              top: d.crop.y,
              width: d.crop.width,
              height: d.crop.height
            });
          break;
        case 'cut':
          wd = image.modifiers.width || image.modifiers.height;
          ht = image.modifiers.height || image.modifiers.width;

          d = dims.gravity(
            image.modifiers.gravity,
            size.width,
            size.height,
            wd,
            ht
          );
          r.extract({
            left: d.x,
            top: d.y,
            width: wd,
            height: ht
          });
          break;
        case 'scale':
          // TODO: deal with scale
          r.resize(image.modifiers.width, image.modifiers.height);
          break;
        case 'pad':
          r.resize(
            image.modifiers.width,
            image.modifiers.height
          ).background(env.IMAGE_PADDING_COLOR || 'white').embed();
        }

        r.toBuffer(resizeResponse);
      });

      break;
    }
  });

};
<commit_msg>Fix scale (ignore aspect ratio)<commit_after>'use strict';

var sharp = require('sharp');
var map   = require('map-stream');
var env   = require('../config/environment_vars');
var dims  = require('../lib/dimensions');

module.exports = function () {

  return map( function(image, callback) {

    // do nothing if there is an error on the image object
    if (image.isError()){
      return callback(null, image);
    }

    // let this pass through if we are requesting the metadata as JSON
    if (image.modifiers.action === 'json'){
      image.log.log('resize: json metadata call');
      return callback(null, image);
    }

    if (image.modifiers.action === 'original' && env.RESIZE_PROCESS_ORIGINAL === false){
      image.log.log('resize: original no resize');
      return callback(null, image);
    }

    image.log.time('resize');

    var resizeResponse = function (err, buffer) {
      if (err) {
        image.log.error('resize error', err);
        image.error = new Error(err);
      }
      else {
        image.contents = buffer;
      }

      image.log.timeEnd('resize');
      callback(null, image);
    };

    var r = sharp(image.contents);

    // never enlarge an image beyonds its original size
    r.withoutEnlargement();

    // if allowed auto rotate images, very helpful for photos off of an iphone
    // which are landscape by default and the metadata tells them what to show.
    if (env.AUTO_ORIENT) {
      r.rotate();
    }

    // by default we remove the metadata from resized images, setting the env
    // var to false can retain it.
    if (!env.REMOVE_METADATA) {
      r.withMetadata();
    }

    var d, wd, ht;

    switch(image.modifiers.action){
    case 'original' :
      r.toBuffer(resizeResponse);
      break;

    case 'resize':
      r.resize(image.modifiers.width, image.modifiers.height);
      r.max();
      r.toBuffer(resizeResponse);
      break;

    case 'square':
      r.metadata(function(err, metadata){
        if (err){
          image.error = new Error(err);
          callback(null, image);
          return;
        }

        d = dims.cropFill(image.modifiers, metadata);

        // resize then crop the image
        r.resize(
            d.resize.width,
            d.resize.height
          ).extract({
            left: d.crop.x,
            top: d.crop.y,
            width: d.crop.width,
            height: d.crop.height
          });

        r.toBuffer(resizeResponse);
      });

      break;

    case 'crop':
      r.metadata(function(err, size){
        if (err){
          image.error = new Error(err);
          callback(null, image);
          return;
        }

        switch(image.modifiers.crop){
        case 'fit':
          r.resize(image.modifiers.width, image.modifiers.height);
          r.max();
          break;
        case 'fill':
          d = dims.cropFill(image.modifiers, size);

          r.resize(
              d.resize.width,
              d.resize.height
            ).extract({
              left: d.crop.x,
              top: d.crop.y,
              width: d.crop.width,
              height: d.crop.height
            });
          break;
        case 'cut':
          wd = image.modifiers.width || image.modifiers.height;
          ht = image.modifiers.height || image.modifiers.width;

          d = dims.gravity(
            image.modifiers.gravity,
            size.width,
            size.height,
            wd,
            ht
          );
          r.extract({
            left: d.x,
            top: d.y,
            width: wd,
            height: ht
          });
          break;
        case 'scale':
          r.resize(image.modifiers.width, image.modifiers.height);
          r.ignoreAspectRatio();
          break;
        case 'pad':
          r.resize(
            image.modifiers.width,
            image.modifiers.height
          ).background(env.IMAGE_PADDING_COLOR || 'white').embed();
        }

        r.toBuffer(resizeResponse);
      });

      break;
    }
  });

};
<|endoftext|>


<commit_before>var debug = require("debug")("litesocket");
var version = require(__dirname+'/package.json').version;

litesocket = module.exports = function(req, res, next){
	debug("connection opened");
	res.useChunkedEncodingByDefault = false;
	res.writeHead(200, litesocket.headers(req));
	["sendRetry","sendComment","sendData"].forEach(function(name){
		var fn = litesocket[name];
		res[name] = function(val){
			fn(res, val);
		};
	});
	res.send = function(data, options){
		litesocket.send(res, data, options);
	};

	//send something or the browser gets mad!
	res.send(litesocket.welcome, {comment:litesocket.banner});

	//very important to remove it from the pool and kill off the default 2 minute timeout
	res.socket.setTimeout(0);
	res.socket.emit("agentRemove");

	if(debug.enabled){
		res.on('end', function closed(){
			debug("response closed");
		});
	}

	if(next) next();
};
litesocket.handler = function(url, callback){
	this.get(url, litesocket, callback);
};

litesocket.banner = "Connected via litesocket v"+ version +"\nhttp://npmjs.org/package/litesocket";
litesocket.welcome = '{"connected":true}';
litesocket.headers = function(res){
	return {
		"Access-Control-Allow-Origin": "*",
		"Content-Type":"text/event-stream",
		"Cache-Control":"no-cache"
	};
}
litesocket.sendId = function(stream, id){
	debug("id: ", id);
	stream.write("id:");
	stream.write(String(id));
	stream.write('\n');
};
litesocket.sendEvent = function(stream, name){
	debug("event:", name);
	stream.write("event:");
	stream.write(String(name));
	stream.write('\n');
};
litesocket.sendRetry = function(stream, ms){
	debug("retry:", ms);
	stream.write("retry:");
	stream.write(String(ms));
	stream.write('\n');
};
litesocket.sendComment = function(stream, comment){
	debug(":", comment);
	stream.write(":");
	stream.write(String(comment).replace(/\n(?=.)/g, '\n:'));
	stream.write('\n');
};
litesocket.sendData = function(stream, data){
	stream.write("data:");
	data = String(data).replace(/\n(?=.)/g, '\ndata: ');
	debug("data", data);
	stream.write(data);
	stream.write('\n');
};
litesocket.send = function(stream, data, options){
	if(options){
		if(options.comment){
			litesocket.sendComment(stream, options.comment);
		}
		if(options.retry){
			litesocket.sendRetry(stream, options.retry);
		}
		if(options.event){
			litesocket.sendEvent(stream, options.event);
		}
	}
	litesocket.sendData(stream, data);
	if(options && options.id){
		litesocket.sendId(stream, options.id);
	}
	stream.write('\n\n');
};
<commit_msg>remove global variable goof<commit_after>var debug = require("debug")("litesocket");
var version = require(__dirname+'/package.json').version;

var litesocket = module.exports = function(req, res, next){
	debug("connection opened");
	res.useChunkedEncodingByDefault = false;
	res.writeHead(200, litesocket.headers(req));
	["sendRetry","sendComment","sendData"].forEach(function(name){
		var fn = litesocket[name];
		res[name] = function(val){
			fn(res, val);
		};
	});
	res.send = function(data, options){
		litesocket.send(res, data, options);
	};

	//send something or the browser gets mad!
	res.send(litesocket.welcome, {comment:litesocket.banner});

	//very important to remove it from the pool and kill off the default 2 minute timeout
	res.socket.setTimeout(0);
	res.socket.emit("agentRemove");

	if(debug.enabled){
		res.on('end', function closed(){
			debug("response closed");
		});
	}

	if(next) next();
};
litesocket.handler = function(url, callback){
	this.get(url, litesocket, callback);
};

litesocket.banner = "Connected via litesocket v"+ version +"\nhttp://npmjs.org/package/litesocket";
litesocket.welcome = '{"connected":true}';
litesocket.headers = function(res){
	return {
		"Access-Control-Allow-Origin": "*",
		"Content-Type":"text/event-stream",
		"Cache-Control":"no-cache"
	};
}
litesocket.sendId = function(stream, id){
	debug("id: ", id);
	stream.write("id:");
	stream.write(String(id));
	stream.write('\n');
};
litesocket.sendEvent = function(stream, name){
	debug("event:", name);
	stream.write("event:");
	stream.write(String(name));
	stream.write('\n');
};
litesocket.sendRetry = function(stream, ms){
	debug("retry:", ms);
	stream.write("retry:");
	stream.write(String(ms));
	stream.write('\n');
};
litesocket.sendComment = function(stream, comment){
	debug(":", comment);
	stream.write(":");
	stream.write(String(comment).replace(/\n(?=.)/g, '\n:'));
	stream.write('\n');
};
litesocket.sendData = function(stream, data){
	stream.write("data:");
	data = String(data).replace(/\n(?=.)/g, '\ndata: ');
	debug("data", data);
	stream.write(data);
	stream.write('\n');
};
litesocket.send = function(stream, data, options){
	if(options){
		if(options.comment){
			litesocket.sendComment(stream, options.comment);
		}
		if(options.retry){
			litesocket.sendRetry(stream, options.retry);
		}
		if(options.event){
			litesocket.sendEvent(stream, options.event);
		}
	}
	litesocket.sendData(stream, data);
	if(options && options.id){
		litesocket.sendId(stream, options.id);
	}
	stream.write('\n\n');
};
<|endoftext|>


<commit_before>/* ======= Global Utilities ======= */

/**
* Compiles a template with given data
* @param {String} template
* @param {Object} data
* @return {String} Template with data rendered
*/
var compileTemplate = function(template) {
  var code = template;
  var templateRe = /{{([A-Za-z0-9_.()\[\]]+)}}/gi;
  code.replace(templateRe, function(match, key) {
    code = code.replace(match, "' + data['" + key + "'] + '");
  });
  code = code.replace(/\n/g, "' + \n'");
  var compile = new Function("data", "var out = '" + code + "'; return out");
  return compile;
}

/**
* Converts attributes into key-value pairs
* @param {Node} node
* @return {Object} Key-Value pairs of Attributes
*/
var extractAttrs = function(node) {
  var attrs = {};
  if(!node.attributes) return attrs;
  var rawAttrs = node.attributes;
  for(var i = 0; i < rawAttrs.length; i++) {
    attrs[rawAttrs[i].name] = compileTemplate(rawAttrs[i].value);
  }

  return attrs;
}

/**
* Creates a Virtual DOM Node
* @param {String} type
* @param {Array} children
* @param {Object} props
* @return {Object} Node For Virtual DOM
*/
var createElement = function(type, val, props, children, meta, node) {
  return {type: type, val: val, props: props, children: children, meta: meta, node: node};
}

/**
* Creates Virtual DOM
* @param {Node} node
* @return {Object} Virtual DOM
*/
var createVirtualDOM = function(node) {
  var tag = node.nodeName;
  var content = "";
  var attrs = extractAttrs(node);
  var defaultMeta = {
    once: false,
    shouldRender: false
  }
  var children = [];

  if(tag === "#text") {
    content = compileTemplate(node.textContent);
  } else {
    content = node.textContent;
  }

  for(var i = 0; i < node.childNodes.length; i++) {
    children.push(createVirtualDOM(node.childNodes[i]));
  }

  return createElement(tag, content, attrs, children, defaultMeta, node);
}

/**
* Gets Root Element
* @param {String} html
* @return {Node} Root Element
*/
var getRootElement = function(html) {
  var dummy = document.createElement('div');
  dummy.innerHTML = html;
  return dummy.firstChild;
}

/**
* Merges two Objects
* @param {Object} obj
* @param {Object} obj2
* @return {Object} Merged Objects
*/
function merge(obj, obj2) {
  for (var key in obj2) {
    if (obj2.hasOwnProperty(key)) obj[key] = obj2[key];
  }
  return obj;
}

/**
 * Compiles JSX to Virtual DOM
 * @param {String} tag
 * @param {Object} attrs
 * @param {Array} children
 * @return {String} Object usable in Virtual DOM
 */
var h = function() {
  var args = Array.prototype.slice.call(arguments);
  var tag = args.shift();
  var attrs = args.shift() || {};
  var children = args;
  return createElement(tag, children.join(""), attrs, children);
};

/**
 * Sets the Elements Initial Value
 * @param {Node} el
 * @param {String} value
 */
var setInitialElementValue = function(el, value) {
  el.innerHTML = value;
}

/**
 * Does No Operation
 */
var noop = function() {

}
<commit_msg>default rendering<commit_after>/* ======= Global Utilities ======= */

/**
* Compiles a template with given data
* @param {String} template
* @param {Object} data
* @return {String} Template with data rendered
*/
var compileTemplate = function(template) {
  var code = template;
  var templateRe = /{{([A-Za-z0-9_.()\[\]]+)}}/gi;
  code.replace(templateRe, function(match, key) {
    code = code.replace(match, "' + data['" + key + "'] + '");
  });
  code = code.replace(/\n/g, "' + \n'");
  var compile = new Function("data", "var out = '" + code + "'; return out");
  return compile;
}

/**
* Converts attributes into key-value pairs
* @param {Node} node
* @return {Object} Key-Value pairs of Attributes
*/
var extractAttrs = function(node) {
  var attrs = {};
  if(!node.attributes) return attrs;
  var rawAttrs = node.attributes;
  for(var i = 0; i < rawAttrs.length; i++) {
    attrs[rawAttrs[i].name] = compileTemplate(rawAttrs[i].value);
  }

  return attrs;
}

/**
* Creates a Virtual DOM Node
* @param {String} type
* @param {Array} children
* @param {Object} props
* @return {Object} Node For Virtual DOM
*/
var createElement = function(type, val, props, children, meta, node) {
  return {type: type, val: val, props: props, children: children, meta: meta, node: node};
}

/**
* Creates Virtual DOM
* @param {Node} node
* @return {Object} Virtual DOM
*/
var createVirtualDOM = function(node) {
  var tag = node.nodeName;
  var content = "";
  var attrs = extractAttrs(node);
  var defaultMeta = {
    once: false,
    shouldRender: true
  }
  var children = [];

  if(tag === "#text") {
    content = compileTemplate(node.textContent);
  } else {
    content = node.textContent;
  }

  for(var i = 0; i < node.childNodes.length; i++) {
    children.push(createVirtualDOM(node.childNodes[i]));
  }

  return createElement(tag, content, attrs, children, defaultMeta, node);
}

/**
* Gets Root Element
* @param {String} html
* @return {Node} Root Element
*/
var getRootElement = function(html) {
  var dummy = document.createElement('div');
  dummy.innerHTML = html;
  return dummy.firstChild;
}

/**
* Merges two Objects
* @param {Object} obj
* @param {Object} obj2
* @return {Object} Merged Objects
*/
function merge(obj, obj2) {
  for (var key in obj2) {
    if (obj2.hasOwnProperty(key)) obj[key] = obj2[key];
  }
  return obj;
}

/**
 * Compiles JSX to Virtual DOM
 * @param {String} tag
 * @param {Object} attrs
 * @param {Array} children
 * @return {String} Object usable in Virtual DOM
 */
var h = function() {
  var args = Array.prototype.slice.call(arguments);
  var tag = args.shift();
  var attrs = args.shift() || {};
  var children = args;
  return createElement(tag, children.join(""), attrs, children);
};

/**
 * Sets the Elements Initial Value
 * @param {Node} el
 * @param {String} value
 */
var setInitialElementValue = function(el, value) {
  el.innerHTML = value;
}

/**
 * Does No Operation
 */
var noop = function() {

}
<|endoftext|>


<commit_before>// Load module dependencies
var http = require('http'),
    fs = require('fs');

http.createServer(function(request, response) {

    // TODO: Find the ASYNCHRONOUS, NON-BLOCKING API for reading in a file.
    fs.CHANGE_ME('./data.csv', 'utf-8', function(err, data) {
        var responseData = {};

        // Basic JS: Work with the data in the file, and create the response
        var lines = data.split('\n');

        // Note the native forEach support in Arrays in node.js!
        lines.forEach(function(line) {
            var parts = line.split(',');
            responseData[parts[0]] = parts[1];
        });

        // TODO: How do we set the content type we're sending back?
        response.writeHead(200, {
            'CHANGEME':'CHANGEME'
        });

        // TODO: How do we serialize responseData to a JSON string?
        response.end(CHANGE_ME.CHANGE_ME(responseData));

    });

}).listen(3000);

console.log('node server running on port 3000');<commit_msg>Completed first challenge, with annotations.<commit_after>// Load module dependencies
var http = require('http'),
    fs = require('fs');

http.createServer(function(request, response) {

    // TODO: Find the ASYNCHRONOUS, NON-BLOCKING API for reading in a file.
    // http://nodejs.org/api/fs.html#fs_fs_readfile_filename_options_callback
    fs.readFile('./data.csv', 'utf-8', function(err, data) {
        var responseData = {};

        // Basic JS: Work with the data in the file, and create the response
        var lines = data.split('\n');

        // Note the native forEach support in Arrays in node.js!
        lines.forEach(function(line) {
            var parts = line.split(',');
            responseData[parts[0]] = parts[1];
        });

        // TODO: How do we set the content type we're sending back?
        // http://nodejs.org/api/http.html#http_response_writehead_statuscode_reasonphrase_headers
        // http://www.ietf.org/rfc/rfc4627.txt
        response.writeHead(200, {
            'Content-Type': 'application/json'
        });

        // TODO: How do we serialize responseData to a JSON string?
        // http://ecma-international.org/ecma-262/5.1/#sec-15.12.3
        response.end(JSON.stringify(responseData));
    });

// NOTE: Cloud9 IDE requires using the PORT and IP environment variables.
// https://docs.c9.io/writing_nodejs_hello_world.html
}).listen(process.env.PORT || 3000, process.env.IP || '0.0.0.0');

console.log('node server running on port 3000');<|endoftext|>