<commit_before>/* globals define */
define(function(require, exports, module) {
  'use strict';

  var MoveableView = require('../base/MoveableView');
  var MoveableSurface = require('../base/MoveableSurface');
  var Transform = require('famous/core/Transform');
  var Utils = require('../base/Utils');

  function Layout (options) {
    MoveableView.apply(this, arguments);
    this._initialized = false;
    this._childSizes = [];
    this._children = this.options.children;
    this._activeLayout = this.options.layout;

    for (var i = 0; i < this._children.length; i++) {
      var child = this._children[i];
      this._hideChild(child);
      this.bindEvents(child);
      this.add(child);
    }

    this._listenForSize();
  }

  Layout.prototype = Object.create(MoveableView.prototype);
  Layout.prototype.constructor = Layout;

  Layout.prototype.destroy = function () {
    for (var i = 0; i < this._children.length; i++) {
      var child = this._children[i];
      this.unbindEvents(child);
    }
  }

  Layout.prototype.layout = function () {
    this._readSizes();
    if (this._activeLayout) {
      this._activeLayout.layout(this._children, this._childSizes);
    }
    return this;
  }

  Layout.prototype.bindEvents = function (elem) {};

  Layout.prototype.unbindEvents = function (elem) {};

  Layout.prototype.getSize = function () {
    if (this._initialized && this._activeLayout) {
      return this._activeLayout.getSize(
        this._children, this._childSizes);
    }
    else return undefined;
  }

  Layout.DEFAULT_OPTIONS = {
  };

  Layout.prototype._listenForSize = function (child, anim) {
    var self = this;
    Utils.when(function () {
      for (var i = 0; i < self._children.length; i++) {
        var child = self._children[i];
        var size = child.getSize();
        if (size[0] === true || size[1] === true || size[0] === 0 || size[1] === 0) {
          return false;
        }
        return true;
      }
    }, this._sizeSafe.bind(this));
  }

  Layout.prototype._sizeSafe = function (child, anim) {
    this._initialized = true;
    this.setSize(this.getSize.bind(this));
    this.layout();
  }

  Layout.prototype._readSizes = function () {
    for (var i = 0; i < this._children.length; i++) {
      var child = this._children[i];
      this._childSizes[i] = child.getSize().slice(0);
    }
  }

  Layout.prototype._hideChild = function (child, anim) {
    child.setOpacity(0, anim);
    child.setTransform(Transform.scale(0.001, 0.001), anim);
  }

  module.exports = Layout;
});
<commit_msg>size check<commit_after>/* globals define */
define(function(require, exports, module) {
  'use strict';

  var MoveableView = require('../base/MoveableView');
  var MoveableSurface = require('../base/MoveableSurface');
  var Transform = require('famous/core/Transform');
  var Utils = require('../base/Utils');

  function Layout (options) {
    MoveableView.apply(this, arguments);
    this._initialized = false;
    this._childSizes = [];
    this._children = this.options.children;
    this._activeLayout = this.options.layout;

    for (var i = 0; i < this._children.length; i++) {
      var child = this._children[i];
      this._hideChild(child);
      this.bindEvents(child);
      this.add(child);
    }

    this._listenForSize();
  }

  Layout.prototype = Object.create(MoveableView.prototype);
  Layout.prototype.constructor = Layout;

  Layout.prototype.destroy = function () {
    for (var i = 0; i < this._children.length; i++) {
      var child = this._children[i];
      this.unbindEvents(child);
    }
  }

  Layout.prototype.layout = function () {
    this._readSizes();
    if (this._activeLayout) {
      this._activeLayout.layout(this._children, this._childSizes);
    }
    return this;
  }

  Layout.prototype.bindEvents = function (elem) {};

  Layout.prototype.unbindEvents = function (elem) {};

  Layout.prototype.getSize = function () {
    if (this._initialized && this._activeLayout) {
      return this._activeLayout.getSize(
        this._children, this._childSizes);
    }
    else return undefined;
  }

  Layout.DEFAULT_OPTIONS = {
  };

  Layout.prototype._listenForSize = function (child, anim) {
    var self = this;
    Utils.when(function () {
      for (var i = 0; i < self._children.length; i++) {
        var child = self._children[i];
        var size = child.getSize();
        if (!size || size[0] === true || size[1] === true || size[0] === 0 || size[1] === 0) {
          return false;
        }
        return true;
      }
    }, this._sizeSafe.bind(this));
  }

  Layout.prototype._sizeSafe = function (child, anim) {
    this._initialized = true;
    this.setSize(this.getSize.bind(this));
    this.layout();
  }

  Layout.prototype._readSizes = function () {
    for (var i = 0; i < this._children.length; i++) {
      var child = this._children[i];
      this._childSizes[i] = child.getSize().slice(0);
    }
  }

  Layout.prototype._hideChild = function (child, anim) {
    child.setOpacity(0, anim);
    child.setTransform(Transform.scale(0.001, 0.001), anim);
  }

  module.exports = Layout;
});
<|endoftext|>


<commit_before>const io = function () {
    'use_strict';
    const exports = {

        'format': function () {
            let args = [...arguments].map(arg => jrts.jsToErlang(arg));
            switch (arguments.length) {
                case 1:
                    if (Process.isProcess(this)) {
                        return functions['format/1'].bind(this)(...args);
                    } else {
                        return jrts.spawn(function() {
                            return functions['format/1'].bind(this)(...args);
                        });
                    }
                    break;
                case 2:
                    if (Process.isProcess(this)) {
                        return functions['format/2'].bind(this)(...args);
                    } else {
                        return jrts.spawn(function() {
                            return functions['format/2'].bind(this)(...args);
                        });
                    }
            }
            throw '** exception error: undefined function' + ('format' + ('/' + arguments.length));
        },

        'module_info': function () {
            let args = [...arguments].map(arg => jrts.jsToErlang(arg));
            switch (arguments.length) {
                case 0:
                    if (Process.isProcess(this)) {
                        return functions['module_info/0'].bind(this)(...args);
                    } else {
                        return jrts.spawn(function() {
                            return functions['module_info/0'].bind(this)(...args);
                        });
                    }
                    break;
                case 1:
                    if (Process.isProcess(this)) {
                        return functions['module_info/1'].bind(this)(...args);
                    } else {
                        return jrts.spawn(function() {
                            return functions['module_info/1'].bind(this)(...args);
                        });
                    }
            }
            throw '** exception error: undefined function' + ('module_info' + ('/' + arguments.length));
        }
    };

    const functions = {
        'columns/0': function () {
            var cols = 1;

            if (typeof process == "object" && process.stdout) {
                cols = process.stdout.columns;
            }

            return new Tuple(new Atom("ok"), new Int(cols));
        },
        'columns/1': function (_cor0) {
            return this['columns/0']();
        },

        'format/1': function (_cor0) {
            console.log(_cor0.toString());
            return new Atom("ok");
        },
        'format/2': function (_cor1, _cor0) {
            console.log(formatErlangString(_cor1, _cor0).toString());
            return new Atom("ok");
        },
        'format/3': function (_cor2, _cor1, _cor0) {
            this['format/2'](_cor1, _cor0);
        },

        'fread/2': function (_cor1, _cor0) {
        },
        'fread/3': function (_cor2, _cor1, _cor0) {
            return this['fread/2'](_cor1, _cor0);
        },

        'fwrite/1': function (_cor0) {
            return this['format/1'](_cor0);
        },
        'fwrite/2': function (_cor1, _cor0) {
            return this['format/2'](_cor1, _cor0);
        },
        'fwrite/3': function (_cor2, _cor1, _cor0) {
            return this['format/2'](_cor1, _cor0);
        },

        'get_chars/2': function (_cor1, _cor0) {
        },
        'get_chars/3': function (_cor2, _cor1, _cor0) {
            return this['get_chars/2'](_cor1, _cor0);
        },

        'get_line/1': function (_cor0) {
        },
        'get_line/2': function (_cor1, _cor0) {
            return this['get_line/1'](_cor0);
        },

        'getopts/0': function () {
        },
        'getopts/1': function (_cor0) {
            return this['getopts/0']();
        },

        'module_info/0': function () {
        },
        'module_info/1': function (_cor0) {
        },

        'nl/0': function () {
            console.log("\n");
            return new Atom("ok");
        },
        'nl/1': function (_cor0) {
            return this['nl/0']();
        },

        'parse_erl_exprs/1': function (_cor0) {
        },
        'parse_erl_exprs/2': function (_cor1, _cor0) {
        },
        'parse_erl_exprs/3': function (_cor2, _cor1, _cor0) {
        },
        'parse_erl_exprs/4': function (_cor3, _cor2, _cor1, _cor0) {
        },

        'parse_erl_form/1': function (_cor0) {
        },
        'parse_erl_form/2': function (_cor1, _cor0) {
        },
        'parse_erl_form/3': function (_cor2, _cor1, _cor0) {
        },
        'parse_erl_form/4': function (_cor3, _cor2, _cor1, _cor0) {
        },

        'printable_range/0': function () {
        },

        'put_chars/1': function (_cor0) {
        },
        'put_chars/2': function (_cor1, _cor0) {
            return this['put_chars/1'](_cor0);
        },

        'read/1': function (_cor0) {
        },
        'read/2': function (_cor1, _cor0) {
        },
        'read/3': function (_cor2, _cor1, _cor0) {
        },
        'read/4': function (_cor3, _cor2, _cor1, cor0) {
        },

        'rows/0': function () {
            var rows = 1;

            if (typeof process == "object" && process.stdout) {
                rows = process.stdout.rows;
            }

            return new Tuple(new Atom("ok"), new Int(rows));
        },
        'rows/1': function (_cor0) {
            return this['rows/0']();
        },

        'scan_erl_exprs/1': function (_cor0) {
        },
        'scan_erl_exprs/2': function (_cor1, _cor0) {
        },
        'scan_erl_exprs/3': function (_cor2, _cor1, _cor0) {
        },
        'scan_erl_exprs/4': function (_cor3, _cor2, _cor1, _cor0) {
        },

        'scan_erl_form/1': function (_cor0) {
        },
        'scan_erl_form/2': function (_cor1, _cor0) {
        },
        'scan_erl_form/3': function (_cor2, _cor1, _cor0) {
        },
        'scan_erl_form/4': function (_cor3, _cor2, _cor1, _cor0) {
        },

        'setopts/1': function (_cor0) {
        },
        'setopts/2': function (_cor1, _cor0) {
            return this['setopts/1'](_cor0);
        },

        'write/1': function (_cor0) {
        },
        'write/2': function (_cor1, _cor0) {
            return this['write/1'](_cor0);
        }
    };

    // Private Methods
    function formatErlangString(str, data) {
        var isErlList = str instanceof List, fstr = "";
        str = isErlList ? str.toString() : str;

        for (var i = 0; i < str.length; i++) {
            var ch = str.charAt(i);

            if (ch == "~") {
                i++;

                switch (str.charAt(i)) {
                    case "~":
                        fstr += "~";
                        break;
                    case "c":
                        fstr += String.fromCharCode(data.shift());
                        break;
                    case "f":
                        break;
                    case "e":
                        break;
                    case "g":
                        break;
                    case "s":
                        fstr += data.shift();
                        break;
                    case "w":
                        break;
                    case "p":
                        break;
                    case "W":
                        break;
                    case "P":
                        break;
                    case "B":
                        break;
                    case "X":
                        break;
                    case "#":
                        break;
                    case "b":
                        break;
                    case "x":
                        break;
                    case "+":
                        break;
                    case "n":
                        fstr += "\n";
                        break;
                    case "i":
                        data.shift();
                        break;
                    default:
                        throw "bad argument";
                }
            }
            else {
                fstr += ch;
            }
        }

        return isErlList ? new List(...fstr.split("")) : fstr;
    }

    return exports;
}();
<commit_msg>io:format now supports a very basic level of all flags, all option flags now work but we don't currently support flag options yet.<commit_after>const io = function () {
    'use_strict';
    const exports = {

        'format': function () {
            let args = [...arguments].map(arg => jrts.jsToErlang(arg));
            switch (arguments.length) {
                case 1:
                    if (Process.isProcess(this)) {
                        return functions['format/1'].bind(this)(...args);
                    } else {
                        return jrts.spawn(function() {
                            return functions['format/1'].bind(this)(...args);
                        });
                    }
                    break;
                case 2:
                    if (Process.isProcess(this)) {
                        return functions['format/2'].bind(this)(...args);
                    } else {
                        return jrts.spawn(function() {
                            return functions['format/2'].bind(this)(...args);
                        });
                    }
            }
            throw '** exception error: undefined function' + ('format' + ('/' + arguments.length));
        },

        'module_info': function () {
            let args = [...arguments].map(arg => jrts.jsToErlang(arg));
            switch (arguments.length) {
                case 0:
                    if (Process.isProcess(this)) {
                        return functions['module_info/0'].bind(this)(...args);
                    } else {
                        return jrts.spawn(function() {
                            return functions['module_info/0'].bind(this)(...args);
                        });
                    }
                    break;
                case 1:
                    if (Process.isProcess(this)) {
                        return functions['module_info/1'].bind(this)(...args);
                    } else {
                        return jrts.spawn(function() {
                            return functions['module_info/1'].bind(this)(...args);
                        });
                    }
            }
            throw '** exception error: undefined function' + ('module_info' + ('/' + arguments.length));
        }
    };

    const functions = {
        'columns/0': function () {
            var cols = 1;

            if (typeof process == "object" && process.stdout) {
                cols = process.stdout.columns;
            }

            return new Tuple(new Atom("ok"), new Int(cols));
        },
        'columns/1': function (_cor0) {
            return this['columns/0']();
        },

        'format/1': function (_cor0) {
            console.log(_cor0.toString());
            return new Atom("ok");
        },
        'format/2': function (_cor1, _cor0) {
            console.log(formatErlangString(_cor1, _cor0).toString());
            return new Atom("ok");
        },
        'format/3': function (_cor2, _cor1, _cor0) {
            this['format/2'](_cor1, _cor0);
        },

        'fread/2': function (_cor1, _cor0) {
        },
        'fread/3': function (_cor2, _cor1, _cor0) {
            return this['fread/2'](_cor1, _cor0);
        },

        'fwrite/1': function (_cor0) {
            return this['format/1'](_cor0);
        },
        'fwrite/2': function (_cor1, _cor0) {
            return this['format/2'](_cor1, _cor0);
        },
        'fwrite/3': function (_cor2, _cor1, _cor0) {
            return this['format/2'](_cor1, _cor0);
        },

        'get_chars/2': function (_cor1, _cor0) {
        },
        'get_chars/3': function (_cor2, _cor1, _cor0) {
            return this['get_chars/2'](_cor1, _cor0);
        },

        'get_line/1': function (_cor0) {
        },
        'get_line/2': function (_cor1, _cor0) {
            return this['get_line/1'](_cor0);
        },

        'getopts/0': function () {
        },
        'getopts/1': function (_cor0) {
            return this['getopts/0']();
        },

        'module_info/0': function () {
        },
        'module_info/1': function (_cor0) {
        },

        'nl/0': function () {
            console.log("\n");
            return new Atom("ok");
        },
        'nl/1': function (_cor0) {
            return this['nl/0']();
        },

        'parse_erl_exprs/1': function (_cor0) {
        },
        'parse_erl_exprs/2': function (_cor1, _cor0) {
        },
        'parse_erl_exprs/3': function (_cor2, _cor1, _cor0) {
        },
        'parse_erl_exprs/4': function (_cor3, _cor2, _cor1, _cor0) {
        },

        'parse_erl_form/1': function (_cor0) {
        },
        'parse_erl_form/2': function (_cor1, _cor0) {
        },
        'parse_erl_form/3': function (_cor2, _cor1, _cor0) {
        },
        'parse_erl_form/4': function (_cor3, _cor2, _cor1, _cor0) {
        },

        'printable_range/0': function () {
        },

        'put_chars/1': function (_cor0) {
        },
        'put_chars/2': function (_cor1, _cor0) {
            return this['put_chars/1'](_cor0);
        },

        'read/1': function (_cor0) {
        },
        'read/2': function (_cor1, _cor0) {
        },
        'read/3': function (_cor2, _cor1, _cor0) {
        },
        'read/4': function (_cor3, _cor2, _cor1, cor0) {
        },

        'rows/0': function () {
            var rows = 1;

            if (typeof process == "object" && process.stdout) {
                rows = process.stdout.rows;
            }

            return new Tuple(new Atom("ok"), new Int(rows));
        },
        'rows/1': function (_cor0) {
            return this['rows/0']();
        },

        'scan_erl_exprs/1': function (_cor0) {
        },
        'scan_erl_exprs/2': function (_cor1, _cor0) {
        },
        'scan_erl_exprs/3': function (_cor2, _cor1, _cor0) {
        },
        'scan_erl_exprs/4': function (_cor3, _cor2, _cor1, _cor0) {
        },

        'scan_erl_form/1': function (_cor0) {
        },
        'scan_erl_form/2': function (_cor1, _cor0) {
        },
        'scan_erl_form/3': function (_cor2, _cor1, _cor0) {
        },
        'scan_erl_form/4': function (_cor3, _cor2, _cor1, _cor0) {
        },

        'setopts/1': function (_cor0) {
        },
        'setopts/2': function (_cor1, _cor0) {
            return this['setopts/1'](_cor0);
        },

        'write/1': function (_cor0) {
        },
        'write/2': function (_cor1, _cor0) {
            return this['write/1'](_cor0);
        }
    };

    // Private Methods
    function formatErlangString(str, data) {
        var isErlList = str instanceof List, fstr = "";
        str = isErlList ? str.toString() : str;
        data = isErlList ? [...data] : data;

        for (var i = 0; i < str.length; i++) {
            var ch = str.charAt(i);
            var d = null;
            if (ch == "~") {
                i++;
                let cur = str.charAt(i);
                switch (cur) {
                    case "~":
                        fstr += "~";
                        break;

                    case "c":
                        fstr += String.fromCharCode(data.shift());
                        break;

                    case "g":
                    case "f":
                        d = data.shift();
                        var isIntOrFloat = (Int.isInt(d) || Float.isFloat(d));
                        if (isIntOrFloat) {
                            var dval = d.getValue().toNumber();
                            var flagTestF  = (cur === "f");
                            var rangeTestG = (dval >= 0.1 && dval < 10000);
                            var flagTestG  = (cur === "g" && rangeTestG);
                            if (flagTestF || flagTestG) {
                                fstr += dval.toFixed(6);
                                break;
                            }
                            else {
                                data.unshift(d);
                                // fall through to case e
                            }
                        }
                        else {
                            throw `** format error: type ${d.constructor.name} cannot be coerced into type Float ("~f", [${d}])`;
                            break;
                        }
                    case "e":
                        d = data.shift();
                        var dval = d.getValue().toNumber();
                        if (Int.isInt(d) || Float.isFloat(d) || (cur === "g")) {
                            fstr += dval.toExponential(6);
                        }
                        else {
                            throw `** format error: type ${d.constructor.name} cannot be coerced into type Float ("~f", [${d}])`;
                        }
                        break;

                    case "s":
                        d = data.shift();
                        if (List.isList(d) || BitString.isBitString(d)) {
                            fstr += [...d].map((c) => {
                                return String.fromCharCode(c.getValue());
                            }).join("");
                        }
                        else if (Atom.isAtom(d)) {
                            fstr += d.getValue();
                        }
                        else {
                            throw `** format error: type ${d.constructor.name} cannot be coerced into type String ("~s", [${d}])`;
                        }
                        break;

                    case "W":
                    case "w":
                    case "P":
                    case "p":
                        fstr += data.shift().toString();
                        break;

                    case "#":
                    case "+":
                    case "b":
                    case "x":
                    case "X":
                    case "B":
                        d = data.shift();
                        if (Int.isInt(d) || Float.isFloat(d)) {
                            var dval = d.getValue().toNumber();
                            fstr += "#" + Number(dval).toString(16);
                        }
                        else {
                            throw `** format error: type ${d.constructor.name} cannot be coerced into type Base N Number ("~f", [${d}])`;
                        }
                        break;

                    case "n":
                        fstr += "\n";
                        break;

                    case "i":
                        data.shift();
                        break;

                    default:
                        throw "** bad argument: unknown flag ~" + cur;
                }
            }
            else {
                fstr += ch;
            }
        }

        //console.log("raw: ", fstr.split(""));
        return isErlList ? jrts.jsToErlang(fstr) : fstr;
    }

    return exports;
}();
<|endoftext|>


<commit_before>var Fs = require('fs');
var Handlebars = require('handlebars');

// Partials
Handlebars.registerPartial(
  'global/icon',
  Fs.readFileSync('./templates/partials/global/icon.html', 'utf8')
);

Handlebars.registerPartial(
  'global/search-nav',
  Fs.readFileSync('./templates/partials/global/search-nav.html', 'utf8')
);

Handlebars.registerPartial(
  'global/search-main',
  Fs.readFileSync('./templates/partials/global/search-main.html', 'utf8')
);

Handlebars.registerPartial(
  'global/searchbox',
  Fs.readFileSync('./templates/partials/global/searchbox.html', 'utf8')
);

Handlebars.registerPartial(
  'global/global-header',
  Fs.readFileSync('./templates/partials/global/global-header.html', 'utf8')
);

Handlebars.registerPartial(
  'global/internal-header',
  Fs.readFileSync('./templates/partials/global/internal-header.html', 'utf8')
);

Handlebars.registerPartial(
  'global/logo-panel',
  Fs.readFileSync('./templates/partials/global/logo-panel.html', 'utf8')
);

Handlebars.registerPartial(
  'global/menu',
  Fs.readFileSync('./templates/partials/global/menu.html', 'utf8')
);

Handlebars.registerPartial(
  'search/results-page',
  Fs.readFileSync('./templates/partials/search/results-page.html', 'utf8')
);

Handlebars.registerPartial(
  'search/filters-people',
  Fs.readFileSync('./templates/partials/search/filters-people.html', 'utf8')
);

Handlebars.registerPartial(
  'search/filters-objects',
  Fs.readFileSync('./templates/partials/search/filters-objects.html', 'utf8')
);

Handlebars.registerPartial(
  'search/filters-all',
  Fs.readFileSync('./templates/partials/search/filters-all.html', 'utf8')
);

Handlebars.registerPartial(
  'search/filters-documents',
  Fs.readFileSync('./templates/partials/search/filters-documents.html', 'utf8')
);

Handlebars.registerPartial(
  'search/filters',
  Fs.readFileSync('./templates/partials/search/filters.html', 'utf8')
);

Handlebars.registerPartial(
  'search/pagination',
  Fs.readFileSync('./templates/partials/search/pagination.html', 'utf8')
);

Handlebars.registerPartial(
  'search/results-grid',
  Fs.readFileSync('./templates/partials/search/results-grid.html', 'utf8')
);

Handlebars.registerPartial(
  'search/results-list',
  Fs.readFileSync('./templates/partials/search/results-list.html', 'utf8')
);

Handlebars.registerPartial(
  'search/noresults',
  Fs.readFileSync('./templates/partials/search/noresults.html', 'utf8')
);

Handlebars.registerPartial(
  'records/record-top',
  Fs.readFileSync('./templates/partials/records/record-top.html', 'utf8')
);

Handlebars.registerPartial(
  'records/record-description',
  Fs.readFileSync(
    './templates/partials/records/record-description.html',
    'utf8'
  )
);

Handlebars.registerPartial(
  'records/record-related-people',
  Fs.readFileSync(
    './templates/partials/records/record-related-people.html',
    'utf8'
  )
);

Handlebars.registerPartial(
  'records/record-related-organisations',
  Fs.readFileSync(
    './templates/partials/records/record-related-organisations.html',
    'utf8'
  )
);

Handlebars.registerPartial(
  'records/record-details',
  Fs.readFileSync('./templates/partials/records/record-details.html', 'utf8')
);

Handlebars.registerPartial(
  'records/record-related-objects',
  Fs.readFileSync(
    './templates/partials/records/record-related-objects.html',
    'utf8'
  )
);

Handlebars.registerPartial(
  'records/panel-cite',
  Fs.readFileSync('./templates/partials/records/panel-cite.html', 'utf8')
);

Handlebars.registerPartial(
  'records/record-imgpanel__controlbar',
  Fs.readFileSync(
    './templates/partials/records/record-imgpanel__controlbar.html',
    'utf8'
  )
);

Handlebars.registerPartial(
  'records/record-related-documents',
  Fs.readFileSync(
    './templates/partials/records/record-related-documents.html',
    'utf8'
  )
);

Handlebars.registerPartial(
  'records/record-related-documents-primary',
  Fs.readFileSync(
    './templates/partials/records/record-related-documents-primary.html',
    'utf8'
  )
);

Handlebars.registerPartial(
  'records/record-related-articles',
  Fs.readFileSync(
    './templates/partials/records/record-related-articles.html',
    'utf8'
  )
);

Handlebars.registerPartial(
  'records/archive-tree',
  Fs.readFileSync('./templates/partials/records/archive-tree.html', 'utf8')
);

Handlebars.registerPartial(
  'records/archive-tree-browser',
  Fs.readFileSync(
    './templates/partials/records/archive-tree-browser.html',
    'utf8'
  )
);

Handlebars.registerPartial(
  'records/archive-tree-children',
  Fs.readFileSync(
    './templates/partials/records/archive-tree-children.html',
    'utf8'
  )
);

Handlebars.registerPartial(
  'records/record-system',
  Fs.readFileSync('./templates/partials/records/record-system.html', 'utf8')
);

Handlebars.registerPartial(
  'records/ondisplay',
  Fs.readFileSync('./templates/partials/records/ondisplay.html', 'utf8')
);

Handlebars.registerPartial(
  'records/carousel',
  Fs.readFileSync('./templates/partials/records/carousel.html', 'utf8')
);

Handlebars.registerPartial(
  'records/single-image',
  Fs.readFileSync('./templates/partials/records/single-image.html', 'utf8')
);

Handlebars.registerPartial(
  'records/mediaplayer',
  Fs.readFileSync('./templates/partials/records/mediaplayer.html', 'utf8')
);

Handlebars.registerPartial(
  'records/audioplayer',
  Fs.readFileSync('./templates/partials/records/audioplayer.html', 'utf8')
);

Handlebars.registerPartial(
  'records/mediaplayer__listitem',
  Fs.readFileSync(
    './templates/partials/records/mediaplayer__listitem.html',
    'utf8'
  )
);

Handlebars.registerPartial(
  'global/smg-map',
  Fs.readFileSync('./templates/partials/global/smg-map.html', 'utf8')
);

// Helpers
Handlebars.registerHelper(
  'classname',
  require('../templates/helpers/classname.js')
);

Handlebars.registerHelper('ifpage', require('../templates/helpers/ifpage.js'));

Handlebars.registerHelper(
  'isselected',
  require('../templates/helpers/isselected.js')
);

Handlebars.registerHelper(
  'getinventorynumber',
  require('../templates/helpers/getinventorynumber.js')
);

Handlebars.registerHelper(
  'geturlsafeinventorynumber',
  require('../templates/helpers/geturlsafeinventorynumber.js')
);

Handlebars.registerHelper(
  'gettodaysdate',
  require('../templates/helpers/gettodaysdate.js')
);

Handlebars.registerHelper(
  'ifmultiple',
  require('../templates/helpers/ifmultiple.js')
);

Handlebars.registerHelper(
  'current',
  require('../templates/helpers/current.js')
);

Handlebars.registerHelper(
  'getlink',
  require('../templates/helpers/getlink.js')
);

Handlebars.registerHelper(
  'displayFilters',
  require('../templates/helpers/displayFilters.js')
);

Handlebars.registerHelper(
  'ifsmgrights',
  require('../templates/helpers/ifsmgrights.js')
);

Handlebars.registerHelper(
  'ifsmgorccrights',
  require('../templates/helpers/ifsmgorccrights.js')
);

Handlebars.registerHelper(
  'taxonomy',
  require('../templates/helpers/taxonomy.js')
);

Handlebars.registerHelper(
  'activeFacet',
  require('../templates/helpers/activeFacet.js')
);

Handlebars.registerHelper('comma', require('../templates/helpers/comma.js'));

Handlebars.registerHelper(
  'filtersSelected',
  require('../templates/helpers/filtersSelected.js')
);

Handlebars.registerHelper(
  'clearAllFilters',
  require('../templates/helpers/clearAllFilters.js')
);

Handlebars.registerHelper(
  'formatrelated',
  require('../templates/helpers/formatrelated.js')
);

Handlebars.registerHelper(
  'seemore',
  require('../templates/helpers/seemore.js')
);

Handlebars.registerHelper(
  'normalise',
  require('../templates/helpers/normalise.js')
);

Handlebars.registerHelper(
  'truncate',
  require('../templates/helpers/truncate.js')
);

Handlebars.registerHelper('or', require('../templates/helpers/or.js'));

Handlebars.registerHelper(
  'isequal',
  require('../templates/helpers/isequal.js')
);

Handlebars.registerHelper(
  'formatnumber',
  require('../templates/helpers/formatnumber.js')
);

Handlebars.registerHelper(
  'toggleDetail',
  require('../templates/helpers/toggleDetail.js')
);

Handlebars.registerHelper(
  'isResourcePage',
  require('../templates/helpers/isResourcePage.js')
);
Handlebars.registerHelper('concat', require('../templates/helpers/concat.js'));

Handlebars.registerHelper(
  'ifcreator',
  require('../templates/helpers/ifcreator.js')
);

// Routes
module.exports = {
  '404': Handlebars.compile(
    Fs.readFileSync('./templates/pages/404.html', 'utf8')
  ),
  home: Handlebars.compile(
    Fs.readFileSync('./templates/pages/home.html', 'utf8')
  ),
  search: Handlebars.compile(
    Fs.readFileSync('./templates/pages/search.html', 'utf8')
  ),
  'results-grid': Handlebars.compile(
    Fs.readFileSync('./templates/partials/search/results-grid.html', 'utf8')
  ),
  people: Handlebars.compile(
    Fs.readFileSync('./templates/pages/person.html', 'utf8')
  ),
  documents: Handlebars.compile(
    Fs.readFileSync('./templates/pages/archive.html', 'utf8')
  ),
  objects: Handlebars.compile(
    Fs.readFileSync('./templates/pages/object.html', 'utf8')
  ),
  searchnav: Handlebars.compile(
    Fs.readFileSync('./templates/partials/global/search-nav.html', 'utf8')
  ),
  error: Handlebars.compile(
    Fs.readFileSync('./templates/pages/error.html', 'utf8')
  ),
  rotational: Handlebars.compile(
    Fs.readFileSync('./templates/pages/rotational.html', 'utf8')
  ),
  archiveTree: Handlebars.compile(
    Fs.readFileSync('./templates/partials/records/archive-tree.html', 'utf8')
  ),
  'search-results': Handlebars.compile(
    Fs.readFileSync('./templates/partials/search/results-page.html', 'utf8')
  ),
  'search-main': Handlebars.compile(
    Fs.readFileSync('./templates/partials/global/search-main.html', 'utf8')
  ),
  api: Handlebars.compile(
    Fs.readFileSync('./templates/pages/api.html', 'utf8')
  ),
  articles: Handlebars.compile(
    Fs.readFileSync(
      './templates/partials/records/record-related-articles.html',
      'utf8'
    )
  ),
  wikiImage: Handlebars.compile(
    Fs.readFileSync('./templates/partials/records/wiki-image.html', 'utf8')
  ),
  wikiInfo: Handlebars.compile(
    Fs.readFileSync('./templates/partials/records/wiki-info.html', 'utf8')
  ),
  wikiSummary: Handlebars.compile(
    Fs.readFileSync('./templates/partials/records/wiki-summary.html', 'utf8')
  ),
  about: Handlebars.compile(
    Fs.readFileSync('./templates/pages/about.html', 'utf8')
  )
};
<commit_msg>Updates merge<commit_after>var Fs = require('fs');
var Handlebars = require('handlebars');

// Partials
Handlebars.registerPartial(
  'global/icon',
  Fs.readFileSync('./templates/partials/global/icon.html', 'utf8')
);

Handlebars.registerPartial(
  'global/search-nav',
  Fs.readFileSync('./templates/partials/global/search-nav.html', 'utf8')
);

Handlebars.registerPartial(
  'global/search-main',
  Fs.readFileSync('./templates/partials/global/search-main.html', 'utf8')
);

Handlebars.registerPartial(
  'global/searchbox',
  Fs.readFileSync('./templates/partials/global/searchbox.html', 'utf8')
);

Handlebars.registerPartial(
  'global/global-header',
  Fs.readFileSync('./templates/partials/global/global-header.html', 'utf8')
);

Handlebars.registerPartial(
  'global/global-footer',
   Fs.readFileSync('./templates/partials/global/global-footer.html', 'utf8')
);

Handlebars.registerPartial(
  'global/internal-header',
  Fs.readFileSync('./templates/partials/global/internal-header.html', 'utf8')
);

Handlebars.registerPartial(
  'global/logo-panel',
  Fs.readFileSync('./templates/partials/global/logo-panel.html', 'utf8')
);

Handlebars.registerPartial(
  'global/menu',
  Fs.readFileSync('./templates/partials/global/menu.html', 'utf8')
);

Handlebars.registerPartial(
  'search/results-page',
  Fs.readFileSync('./templates/partials/search/results-page.html', 'utf8')
);

Handlebars.registerPartial(
  'search/filters-people',
  Fs.readFileSync('./templates/partials/search/filters-people.html', 'utf8')
);

Handlebars.registerPartial(
  'search/filters-objects',
  Fs.readFileSync('./templates/partials/search/filters-objects.html', 'utf8')
);

Handlebars.registerPartial(
  'search/filters-all',
  Fs.readFileSync('./templates/partials/search/filters-all.html', 'utf8')
);

Handlebars.registerPartial(
  'search/filters-documents',
  Fs.readFileSync('./templates/partials/search/filters-documents.html', 'utf8')
);

Handlebars.registerPartial(
  'search/filters',
  Fs.readFileSync('./templates/partials/search/filters.html', 'utf8')
);

Handlebars.registerPartial(
  'search/pagination',
  Fs.readFileSync('./templates/partials/search/pagination.html', 'utf8')
);

Handlebars.registerPartial(
  'search/results-grid',
  Fs.readFileSync('./templates/partials/search/results-grid.html', 'utf8')
);

Handlebars.registerPartial(
  'search/results-list',
  Fs.readFileSync('./templates/partials/search/results-list.html', 'utf8')
);

Handlebars.registerPartial(
  'search/noresults',
  Fs.readFileSync('./templates/partials/search/noresults.html', 'utf8')
);

Handlebars.registerPartial(
  'records/record-top',
  Fs.readFileSync('./templates/partials/records/record-top.html', 'utf8')
);

Handlebars.registerPartial(
  'records/record-description',
  Fs.readFileSync(
    './templates/partials/records/record-description.html',
    'utf8'
  )
);

Handlebars.registerPartial(
  'records/record-related-people',
  Fs.readFileSync(
    './templates/partials/records/record-related-people.html',
    'utf8'
  )
);

Handlebars.registerPartial(
  'records/record-related-organisations',
  Fs.readFileSync(
    './templates/partials/records/record-related-organisations.html',
    'utf8'
  )
);

Handlebars.registerPartial(
  'records/record-details',
  Fs.readFileSync('./templates/partials/records/record-details.html', 'utf8')
);

Handlebars.registerPartial(
  'records/record-related-objects',
  Fs.readFileSync(
    './templates/partials/records/record-related-objects.html',
    'utf8'
  )
);

Handlebars.registerPartial(
  'records/panel-cite',
  Fs.readFileSync('./templates/partials/records/panel-cite.html', 'utf8')
);

Handlebars.registerPartial(
  'records/record-imgpanel__controlbar',
  Fs.readFileSync(
    './templates/partials/records/record-imgpanel__controlbar.html',
    'utf8'
  )
);

Handlebars.registerPartial(
  'records/record-related-documents',
  Fs.readFileSync(
    './templates/partials/records/record-related-documents.html',
    'utf8'
  )
);

Handlebars.registerPartial(
  'records/record-related-documents-primary',
  Fs.readFileSync(
    './templates/partials/records/record-related-documents-primary.html',
    'utf8'
  )
);

Handlebars.registerPartial(
  'records/record-related-articles',
  Fs.readFileSync(
    './templates/partials/records/record-related-articles.html',
    'utf8'
  )
);

Handlebars.registerPartial(
  'records/archive-tree',
  Fs.readFileSync('./templates/partials/records/archive-tree.html', 'utf8')
);

Handlebars.registerPartial(
  'records/archive-tree-browser',
  Fs.readFileSync(
    './templates/partials/records/archive-tree-browser.html',
    'utf8'
  )
);

Handlebars.registerPartial(
  'records/archive-tree-children',
  Fs.readFileSync(
    './templates/partials/records/archive-tree-children.html',
    'utf8'
  )
);

Handlebars.registerPartial(
  'records/record-system',
  Fs.readFileSync('./templates/partials/records/record-system.html', 'utf8')
);

Handlebars.registerPartial(
  'records/ondisplay',
  Fs.readFileSync('./templates/partials/records/ondisplay.html', 'utf8')
);

Handlebars.registerPartial(
  'records/carousel',
  Fs.readFileSync('./templates/partials/records/carousel.html', 'utf8')
);

Handlebars.registerPartial(
  'records/single-image',
  Fs.readFileSync('./templates/partials/records/single-image.html', 'utf8')
);

Handlebars.registerPartial(
  'records/mediaplayer',
  Fs.readFileSync('./templates/partials/records/mediaplayer.html', 'utf8')
);

Handlebars.registerPartial(
  'records/audioplayer',
  Fs.readFileSync('./templates/partials/records/audioplayer.html', 'utf8')
);

Handlebars.registerPartial(
  'records/mediaplayer__listitem',
  Fs.readFileSync(
    './templates/partials/records/mediaplayer__listitem.html',
    'utf8'
  )
);

Handlebars.registerPartial(
  'global/smg-map',
  Fs.readFileSync('./templates/partials/global/smg-map.html', 'utf8')
);

// Helpers
Handlebars.registerHelper(
  'classname',
  require('../templates/helpers/classname.js')
);

Handlebars.registerHelper('ifpage', require('../templates/helpers/ifpage.js'));

Handlebars.registerHelper(
  'isselected',
  require('../templates/helpers/isselected.js')
);

Handlebars.registerHelper(
  'getinventorynumber',
  require('../templates/helpers/getinventorynumber.js')
);

Handlebars.registerHelper(
  'geturlsafeinventorynumber',
  require('../templates/helpers/geturlsafeinventorynumber.js')
);

Handlebars.registerHelper(
  'gettodaysdate',
  require('../templates/helpers/gettodaysdate.js')
);

Handlebars.registerHelper(
  'ifmultiple',
  require('../templates/helpers/ifmultiple.js')
);

Handlebars.registerHelper(
  'current',
  require('../templates/helpers/current.js')
);

Handlebars.registerHelper(
  'getlink',
  require('../templates/helpers/getlink.js')
);

Handlebars.registerHelper(
  'displayFilters',
  require('../templates/helpers/displayFilters.js')
);

Handlebars.registerHelper(
  'ifsmgrights',
  require('../templates/helpers/ifsmgrights.js')
);

Handlebars.registerHelper(
  'ifsmgorccrights',
  require('../templates/helpers/ifsmgorccrights.js')
);

Handlebars.registerHelper(
  'taxonomy',
  require('../templates/helpers/taxonomy.js')
);

Handlebars.registerHelper(
  'activeFacet',
  require('../templates/helpers/activeFacet.js')
);

Handlebars.registerHelper('comma', require('../templates/helpers/comma.js'));

Handlebars.registerHelper(
  'filtersSelected',
  require('../templates/helpers/filtersSelected.js')
);

Handlebars.registerHelper(
  'clearAllFilters',
  require('../templates/helpers/clearAllFilters.js')
);

Handlebars.registerHelper(
  'formatrelated',
  require('../templates/helpers/formatrelated.js')
);

Handlebars.registerHelper(
  'seemore',
  require('../templates/helpers/seemore.js')
);

Handlebars.registerHelper(
  'normalise',
  require('../templates/helpers/normalise.js')
);

Handlebars.registerHelper(
  'truncate',
  require('../templates/helpers/truncate.js')
);

Handlebars.registerHelper('or', require('../templates/helpers/or.js'));

Handlebars.registerHelper(
  'isequal',
  require('../templates/helpers/isequal.js')
);

Handlebars.registerHelper(
  'formatnumber',
  require('../templates/helpers/formatnumber.js')
);

Handlebars.registerHelper(
  'toggleDetail',
  require('../templates/helpers/toggleDetail.js')
);

Handlebars.registerHelper(
  'isResourcePage',
  require('../templates/helpers/isResourcePage.js')
);
Handlebars.registerHelper('concat', require('../templates/helpers/concat.js'));

Handlebars.registerHelper(
  'ifcreator',
  require('../templates/helpers/ifcreator.js')
);

// Routes
module.exports = {
  '404': Handlebars.compile(
    Fs.readFileSync('./templates/pages/404.html', 'utf8')
  ),
  home: Handlebars.compile(
    Fs.readFileSync('./templates/pages/home.html', 'utf8')
  ),
  search: Handlebars.compile(
    Fs.readFileSync('./templates/pages/search.html', 'utf8')
  ),
  'results-grid': Handlebars.compile(
    Fs.readFileSync('./templates/partials/search/results-grid.html', 'utf8')
  ),
  people: Handlebars.compile(
    Fs.readFileSync('./templates/pages/person.html', 'utf8')
  ),
  documents: Handlebars.compile(
    Fs.readFileSync('./templates/pages/archive.html', 'utf8')
  ),
  objects: Handlebars.compile(
    Fs.readFileSync('./templates/pages/object.html', 'utf8')
  ),
  searchnav: Handlebars.compile(
    Fs.readFileSync('./templates/partials/global/search-nav.html', 'utf8')
  ),
  error: Handlebars.compile(
    Fs.readFileSync('./templates/pages/error.html', 'utf8')
  ),
  rotational: Handlebars.compile(
    Fs.readFileSync('./templates/pages/rotational.html', 'utf8')
  ),
  archiveTree: Handlebars.compile(
    Fs.readFileSync('./templates/partials/records/archive-tree.html', 'utf8')
  ),
  'search-results': Handlebars.compile(
    Fs.readFileSync('./templates/partials/search/results-page.html', 'utf8')
  ),
  'search-main': Handlebars.compile(
    Fs.readFileSync('./templates/partials/global/search-main.html', 'utf8')
  ),
  api: Handlebars.compile(
    Fs.readFileSync('./templates/pages/api.html', 'utf8')
  ),
  articles: Handlebars.compile(
    Fs.readFileSync(
      './templates/partials/records/record-related-articles.html',
      'utf8'
    )
  ),
  wikiImage: Handlebars.compile(
    Fs.readFileSync('./templates/partials/records/wiki-image.html', 'utf8')
  ),
  wikiInfo: Handlebars.compile(
    Fs.readFileSync('./templates/partials/records/wiki-info.html', 'utf8')
  ),
  wikiSummary: Handlebars.compile(
    Fs.readFileSync('./templates/partials/records/wiki-summary.html', 'utf8')
  ),
  about: Handlebars.compile(
    Fs.readFileSync('./templates/pages/about.html', 'utf8')
  )
};
<|endoftext|>


<commit_before>import {TextRenderer} from './textrenderer';

(function() {

// Shim & native-safe ownerDocument lookup
var owner = (document._currentScript || document.currentScript).ownerDocument;

/**
 * Jupyter display area.
 *
 * Used to dsiplay output from Jupyter kernels.
 */
class JupyterDisplayArea extends HTMLElement {

    /**
     * When element is created, browser calls this.
     */
    createdCallback() {
        let template = owner.querySelector('#tmpl-jupyter-display-area');
        let node = owner.importNode(template.content, true);

        this.shadow = this.createShadowRoot();
        this.shadow.appendChild(node);
        this.el = this.shadow.getElementById('outputs');

        // Initialize instance variables.
        this.renderers = [new TextRenderer()];
        this.fallback_renderer = new TextRenderer();

        // 'Private'
        this._outputs = [];
        this._clear_queued = false;
    }

    /**
     * Deserialize, filling the output area.
     * @param  {object} outputs - See nbformat
     */
    fromJSON(outputs) {
        outputs.map(this.append_output.bind(this));
    }

    /**
     * Serialize the contents of the output area.
     * @return {object} See nbformat.
     */
    toJSON() {
        return this._outputs;
    }

    /**
     * Handle a Jupyter message.
     *
     * Only handles display related messages, including clear output.
     * @param  {object} msg - See Jupyter msgspec.
     */
    handle(msg) {
        var json = {};
        var msg_type = json.output_type = msg.header.msg_type;
        var content = msg.content;
        switch (msg_type) {
            case 'clear_output':
                // msg spec v4 had stdout, stderr, display keys
                // v4.1 replaced these with just wait
                // The default behavior is the same (stdout=stderr=display=True, wait=False),
                // so v4 messages will still be properly handled,
                // except for the rarely used clearing less than all output.
                this.clear_output(msg.content.wait || false);
                return;
            case 'stream':
                json.text = content.text;
                json.name = content.name;
                break;
            case 'display_data':
                json.data = content.data;
                json.metadata = content.metadata;
                break;
            case 'execute_result':
                json.data = content.data;
                json.metadata = content.metadata;
                json.execution_count = content.execution_count;
                break;
            case 'error':
                json.ename = content.ename;
                json.evalue = content.evalue;
                json.traceback = content.traceback;
                break;
            default:
                console.log('unhandled output message', msg);
                return;
        }
        this.append_output(json);
    }

    /**
     * Remove all elements from the display area.
     * @param  {boolean} wait - wait until the next display message before clearing.
     */
    clear_output(wait) {
        if (wait) {

            // If a clear is queued, clear before adding another to the queue.
            if (this._clear_queued) {
                this.clear_output(false);
            }

            this._clear_queued = true;
        } else {

            // Fix the output div's height if the clear_output is waiting for
            // new output (it is being used in an animation).
            if (this._clear_queued) {
                this._clear_queued = false;
            }

            // Clear all
            // Remove load event handlers from img tags because we don't want
            // them to fire if the image is never added to the page.
            let o = this.el;
            while(o.firstChild) { o.removeChild(o.firstChild); }

            this._outputs = [];
            return;
        }
    }

    /**
     * Append output to the output area.
     * @param  {object} json - output json.  See nbformat.
     */
    append_output(json) {

        // Clear the output if clear is queued.
        if (this._clear_queued) {
            this.clear_output(false);
        }

        var record_output = true;
        switch(json.output_type) {
            case 'execute_result':
                json = this._validate_mimebundle(json);
                this._append_mime_bundle(json);
                break;
            case 'stream':
                // append_stream might have merged the output with earlier stream output
                record_output = this._append_stream(json);
                break;
            case 'error':
                this._append_error(json);
                break;
            case 'display_data':
                // append handled below
                json = this._validate_mimebundle(json);
                this._append_mime_bundle(json.data, json.metadata);
                break;
            default:
                console.warn('Unrecognized output type: ' + json.output_type);
                this._append_unrecognized(json);
        }

        if (record_output) {
            this._outputs.push(json);
        }
    }

    get_renderer(mimetype) {
        for (let renderer of this.renderers) {
            if (mimetype === renderer.mimetype) {
                return renderer;
            }
        }
        return null;
    }

    /**
     * Appends stream data to the output area.
     * @param  {object} json - see nbformat
     */
    _append_stream(json) {
        var text = json.text;
        if (typeof text !== 'string') {
            console.error('Stream output is invalid (missing text)', json);
            return;
        }
        if (!text.replace('\r', '')) {
            return;
        }

        this._append_mimetype(text, 'text/plain');
    }

    _append_error(json) {
        var traceback = json.traceback;
        if (traceback !== undefined && traceback.length > 0) {
            var text = '';
            var len = traceback.length;
            for (var i=0; i<len; i++) {
                text = text + traceback[i] + '\n';
            }
            text = text + '\n';

            this._append_mimetype(text, 'text/plain');
        }
    }

    _append_unrecognized(json) {
        this._append_mimetype('Unrecognized output: ' + json.output_type, 'text/plain');
    }

    _append_mime_bundle(json, metadata) {
        let element;
        for (let renderer of this.renderers) {
            //TODO: Priority order
            let data = json.data[renderer.mimetype];
            if (data) {
                element = renderer.render(data, metadata);
            }
        }

        if (!element && this.fallback_renderer) {
            console.warn('Fallback renderer used');
            element = this.fallback_renderer.render(JSON.stringify(json));
        }

        if (element) {
            this.el.appendChild(element);
            return element;
        } else {
            throw new Error('Renderer for mimetypes ' + Object.keys(json).join(', ') + ' not found.');
        }
    }

    _append_mimetype(data, mimetype, metadata) {
        var renderer = this.get_renderer(mimetype);
        if (renderer) {
            let element = renderer.render(data, metadata);
            this.el.appendChild(element);
            return element;
        }

        throw new Error('Renderer for mimetype ' + mimetype + ' not found.');
    }

    /**
     * Validate a mime bundle.
     * @param  {object} bundle
     * @return {object} bundle
     */
    _validate_mimebundle(bundle) {
        if (typeof bundle.data !== 'object') {
            console.warn('Mimebundle missing data', bundle);
            bundle.data = {};
        }

        if (typeof bundle.metadata !== 'object') {
            console.warn('Mimebundle missing metadata', bundle);
            bundle.metadata = {};
        }

        return bundle;
    }
}

// Register jupyter-display-area with the document
document.registerElement('jupyter-display-area', JupyterDisplayArea);

})();
<commit_msg>Create an HTML Renderer and Default<commit_after>import {TextRenderer} from './textrenderer';
import {DefaultRenderer} from './defaultrenderer';
import {HTMLRenderer} from './htmlrenderer';

(function() {

// Shim & native-safe ownerDocument lookup
var owner = (document._currentScript || document.currentScript).ownerDocument;

/**
 * Jupyter display area.
 *
 * Used to dsiplay output from Jupyter kernels.
 */
class JupyterDisplayArea extends HTMLElement {

    /**
     * When element is created, browser calls this.
     */
    createdCallback() {
        let template = owner.querySelector('#tmpl-jupyter-display-area');
        let node = owner.importNode(template.content, true);

        this.shadow = this.createShadowRoot();
        this.shadow.appendChild(node);
        this.el = this.shadow.getElementById('outputs');

        // Initialize instance variables.
        this.renderers = [
            new TextRenderer(),
            new HTMLRenderer()
        ];
        this.fallbackRenderer = new DefaultRenderer();

        // 'Private'
        this._outputs = [];
        this._clear_queued = false;
    }

    /**
     * Deserialize, filling the output area.
     * @param  {object} outputs - See nbformat
     */
    fromJSON(outputs) {
        outputs.map(this.append_output.bind(this));
    }

    /**
     * Serialize the contents of the output area.
     * @return {object} See nbformat.
     */
    toJSON() {
        return this._outputs;
    }

    /**
     * Handle a Jupyter message.
     *
     * Only handles display related messages, including clear output.
     * @param  {object} msg - See Jupyter msgspec.
     */
    handle(msg) {
        var json = {};
        var msg_type = json.output_type = msg.header.msg_type;
        var content = msg.content;
        switch (msg_type) {
            case 'clear_output':
                // msg spec v4 had stdout, stderr, display keys
                // v4.1 replaced these with just wait
                // The default behavior is the same (stdout=stderr=display=True, wait=False),
                // so v4 messages will still be properly handled,
                // except for the rarely used clearing less than all output.
                this.clear_output(msg.content.wait || false);
                return;
            case 'stream':
                json.text = content.text;
                json.name = content.name;
                break;
            case 'display_data':
                json.data = content.data;
                json.metadata = content.metadata;
                break;
            case 'execute_result':
                json.data = content.data;
                json.metadata = content.metadata;
                json.execution_count = content.execution_count;
                break;
            case 'error':
                json.ename = content.ename;
                json.evalue = content.evalue;
                json.traceback = content.traceback;
                break;
            default:
                console.log('unhandled output message', msg);
                return;
        }
        this.append_output(json);
    }

    /**
     * Remove all elements from the display area.
     * @param  {boolean} wait - wait until the next display message before clearing.
     */
    clear_output(wait) {
        if (wait) {

            // If a clear is queued, clear before adding another to the queue.
            if (this._clear_queued) {
                this.clear_output(false);
            }

            this._clear_queued = true;
        } else {

            // Fix the output div's height if the clear_output is waiting for
            // new output (it is being used in an animation).
            if (this._clear_queued) {
                this._clear_queued = false;
            }

            // Clear all
            // Remove load event handlers from img tags because we don't want
            // them to fire if the image is never added to the page.
            let o = this.el;
            while(o.firstChild) { o.removeChild(o.firstChild); }

            this._outputs = [];
            return;
        }
    }

    /**
     * Append output to the output area.
     * @param  {object} json - output json.  See nbformat.
     */
    append_output(json) {

        // Clear the output if clear is queued.
        if (this._clear_queued) {
            this.clear_output(false);
        }

        var record_output = true;
        switch(json.output_type) {
            case 'execute_result':
                json = this._validate_mimebundle(json);
                this._append_mime_bundle(json);
                break;
            case 'stream':
                // append_stream might have merged the output with earlier stream output
                record_output = this._append_stream(json);
                break;
            case 'error':
                this._append_error(json);
                break;
            case 'display_data':
                // append handled below
                json = this._validate_mimebundle(json);
                this._append_mime_bundle(json.data, json.metadata);
                break;
            default:
                console.warn('Unrecognized output type: ' + json.output_type);
                this._append_unrecognized(json);
        }

        if (record_output) {
            this._outputs.push(json);
        }
    }

    get_renderer(mimetype) {
        for (let renderer of this.renderers) {
            if (mimetype === renderer.mimetype) {
                return renderer;
            }
        }
        return null;
    }

    /**
     * Appends stream data to the output area.
     * @param  {object} json - see nbformat
     */
    _append_stream(json) {
        var text = json.text;
        if (typeof text !== 'string') {
            console.error('Stream output is invalid (missing text)', json);
            return;
        }
        if (!text.replace('\r', '')) {
            return;
        }

        this._append_mimetype(text, 'text/plain');
    }

    _append_error(json) {
        var traceback = json.traceback;
        if (traceback !== undefined && traceback.length > 0) {
            var text = '';
            var len = traceback.length;
            for (var i=0; i<len; i++) {
                text = text + traceback[i] + '\n';
            }
            text = text + '\n';

            this._append_mimetype(text, 'text/plain');
        }
    }

    _append_unrecognized(json) {
        this._append_mimetype('Unrecognized output: ' + json.output_type, 'text/plain');
    }

    _append_mime_bundle(json, metadata) {
        let element;
        let richRenderer = this.fallbackRenderer;

        // Choose the last renderer as the most rich
        for (let renderer of this.renderers) {
            if (json.data && renderer.mimetype in json.data) {
                richRenderer = renderer;
            }
        }

        if (json.data){
            let data = json.data[richRenderer.mimetype];
            element = richRenderer.render(data, metadata);
            this.el.appendChild(element);
            return element;
        }

        throw new Error('Renderer for ' + Object.keys(json).join(', ') + ' not found.');
    }

    _append_mimetype(data, mimetype, metadata) {
        var renderer = this.get_renderer(mimetype);
        if (renderer) {
            let element = renderer.render(data, metadata);
            this.el.appendChild(element);
            return element;
        }

        throw new Error('Renderer for mimetype ' + mimetype + ' not found.');
    }

    /**
     * Validate a mime bundle.
     * @param  {object} bundle
     * @return {object} bundle
     */
    _validate_mimebundle(bundle) {
        if (typeof bundle.data !== 'object') {
            console.warn('Mimebundle missing data', bundle);
            bundle.data = {};
        }

        if (typeof bundle.metadata !== 'object') {
            console.warn('Mimebundle missing metadata', bundle);
            bundle.metadata = {};
        }

        return bundle;
    }
}

// Register jupyter-display-area with the document
document.registerElement('jupyter-display-area', JupyterDisplayArea);

})();
<|endoftext|>


<commit_before>'use strict';

var superagent = require('superagent'),
    winston = require('winston'),
    logger = winston.loggers.get('authentication');

/**
 * Server-side implementation of Oauth-2
 * {
 *   # server url that validates the token and returns json with userdata
 *   server: "http://example.com/user"
 * }
 */
function OAUTH2(settings) {
    this.settings = settings;
}

OAUTH2.prototype.name = 'OAUTH2';

OAUTH2.prototype.match = function (method) {
    if (method === 'X-OAUTH2') {
        return true;
    }
    return false;
};

OAUTH2.prototype.authenticate = function (opts, cb) {
    logger.info("OAUTH2 authenticate ", opts.oauth_token);

    // load user details
    superagent
        .post(this.settings.server)
        .send({})
        .set('content-type', "application/json")
        .set('Authorization', "Bearer " + opts.oauth_token)
        .end(function (error, res) {
            if (error) {
                cb(error);
            } else {

                // TODO check login with user in jid
                // verify the username from json with requested username
                // console.log(res.body.login);

                var user = opts;
                user.email = res.body.login;

                // TODO merge properties properly
                console.log(JSON.stringify(opts.jid));
                cb(null, user);
            }
        });
};

module.exports = OAUTH2;<commit_msg>externalize oauth token handling because this differs for each implementation<commit_after>'use strict';

var winston = require('winston'),
    logger = winston.loggers.get('authentication');

/**
 * Server-side implementation of Oauth-2
 */
function OAUTH2(handler, settings) {
    this.settings = settings;
    this.handler = handler ||   function (settings, opts, cb) {
        cb('Authentication not possible');
    };
}

OAUTH2.prototype.name = 'OAUTH2';

OAUTH2.prototype.match = function (method) {
    if (method === 'X-OAUTH2') {
        return true;
    }
    return false;
};

OAUTH2.prototype.authenticate = function (opts, cb) {
    logger.info("OAUTH2 authenticate ", opts.oauth_token);
    this.handler(this.settings, opts, cb);
};

module.exports = OAUTH2;<|endoftext|>


<commit_before><commit_msg>npm auto-update: show msg for a lib ver before processing it<commit_after><|endoftext|>


<commit_before><commit_msg>npm auto-update: enhance error detect on downloading<commit_after><|endoftext|>


<commit_before>/*
 * @class TileLayer
 * @inherits GridLayer
 * @aka L.TileLayer
 * Used to load and display tile layers on the map. Extends `GridLayer`.
 *
 * @example
 *
 * ```js
 * L.tileLayer('http://{s}.tile.osm.org/{z}/{x}/{y}.png?{foo}', {foo: 'bar'}).addTo(map);
 * ```
 *
 * @section URL template
 * @example
 *
 * A string of the following form:
 *
 * ```
 * 'http://{s}.somedomain.com/blabla/{z}/{x}/{y}{r}.png'
 * ```
 *
 * `{s}` means one of the available subdomains (used sequentially to help with browser parallel requests per domain limitation; subdomain values are specified in options; `a`, `b` or `c` by default, can be omitted), `{z}` — zoom level, `{x}` and `{y}` — tile coordinates. `{r}` can be used to add @2x to the URL to load retina tiles.
 *
 * You can use custom keys in the template, which will be [evaluated](#util-template) from TileLayer options, like this:
 *
 * ```
 * L.tileLayer('http://{s}.somedomain.com/{foo}/{z}/{x}/{y}.png', {foo: 'bar'});
 * ```
 */

L.TileLayer = L.GridLayer.extend({

	// @section
	// @aka TileLayer options
	options: {
		// @option minZoom: Number = 0
		// Minimum zoom number.
		minZoom: 0,

		// @option maxZoom: Number = 18
		// Maximum zoom number.
		maxZoom: 18,

		// @option maxNativeZoom: Number = null
		// Maximum zoom number the tile source has available. If it is specified,
		// the tiles on all zoom levels higher than `maxNativeZoom` will be loaded
		// from `maxNativeZoom` level and auto-scaled.
		maxNativeZoom: null,

		// @option minNativeZoom: Number = null
		// Minimum zoom number the tile source has available. If it is specified,
		// the tiles on all zoom levels lower than `minNativeZoom` will be loaded
		// from `minNativeZoom` level and auto-scaled.
		minNativeZoom: null,

		// @option subdomains: String|String[] = 'abc'
		// Subdomains of the tile service. Can be passed in the form of one string (where each letter is a subdomain name) or an array of strings.
		subdomains: 'abc',

		// @option errorTileUrl: String = ''
		// URL to the tile image to show in place of the tile that failed to load.
		errorTileUrl: '',

		// @option zoomOffset: Number = 0
		// The zoom number used in tile URLs will be offset with this value.
		zoomOffset: 0,

		// @option tms: Boolean = false
		// If `true`, inverses Y axis numbering for tiles (turn this on for [TMS](https://en.wikipedia.org/wiki/Tile_Map_Service) services).
		tms: false,

		// @option zoomReverse: Boolean = false
		// If set to true, the zoom number used in tile URLs will be reversed (`maxZoom - zoom` instead of `zoom`)
		zoomReverse: false,

		// @option detectRetina: Boolean = false
		// If `true` and user is on a retina display, it will request four tiles of half the specified size and a bigger zoom level in place of one to utilize the high resolution.
		detectRetina: false,

		// @option crossOrigin: Boolean = false
		// If true, all tiles will have their crossOrigin attribute set to ''. This is needed if you want to access tile pixel data.
		crossOrigin: false
	},

	initialize: function (url, options) {

		this._url = url;

		options = L.setOptions(this, options);

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

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

			if (!options.zoomReverse) {
				options.zoomOffset++;
				options.maxZoom--;
			} else {
				options.zoomOffset--;
				options.minZoom++;
			}

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

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

		// for https://github.com/Leaflet/Leaflet/issues/137
		if (!L.Browser.android) {
			this.on('tileunload', this._onTileRemove);
		}
	},

	// @method setUrl(url: String, noRedraw?: Boolean): this
	// Updates the layer's URL template and redraws it (unless `noRedraw` is set to `true`).
	setUrl: function (url, noRedraw) {
		this._url = url;

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

	// @method createTile(coords: Object, done?: Function): HTMLElement
	// Called only internally, overrides GridLayer's [`createTile()`](#gridlayer-createtile)
	// to return an `<img>` HTML element with the appropiate image URL given `coords`. The `done`
	// callback is called when the tile has been loaded.
	createTile: function (coords, done) {
		var tile = document.createElement('img');

		L.DomEvent.on(tile, 'load', L.bind(this._tileOnLoad, this, done, tile));
		L.DomEvent.on(tile, 'error', L.bind(this._tileOnError, this, done, tile));

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

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

		/*
		 Set role="presentation" to force screen readers to ignore this
		 https://www.w3.org/TR/wai-aria/roles#textalternativecomputation
		*/
		tile.setAttribute('role', 'presentation');

		tile.src = this.getTileUrl(coords);

		return tile;
	},

	// @section Extension methods
	// @uninheritable
	// Layers extending `TileLayer` might reimplement the following method.
	// @method getTileUrl(coords: Object): String
	// Called only internally, returns the URL for a tile given its coordinates.
	// Classes extending `TileLayer` can override this function to provide custom tile URL naming schemes.
	getTileUrl: function (coords) {
		var data = {
			r: L.Browser.retina ? '@2x' : '',
			s: this._getSubdomain(coords),
			x: coords.x,
			y: coords.y,
			z: this._getZoomForUrl()
		};
		if (this._map && !this._map.options.crs.infinite) {
			var invertedY = this._globalTileRange.max.y - coords.y;
			if (this.options.tms) {
				data['y'] = invertedY;
			}
			data['-y'] = invertedY;
		}

		return L.Util.template(this._url, L.extend(data, this.options));
	},

	_tileOnLoad: function (done, tile) {
		// For https://github.com/Leaflet/Leaflet/issues/3332
		if (L.Browser.ielt9) {
			setTimeout(L.bind(done, this, null, tile), 0);
		} else {
			done(null, tile);
		}
	},

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

	getTileSize: function () {
		var map = this._map,
		    tileSize = L.GridLayer.prototype.getTileSize.call(this),
		    zoom = this._tileZoom + this.options.zoomOffset,
			minNativeZoom = this.options.minNativeZoom,
		    maxNativeZoom = this.options.maxNativeZoom;

		// decrease tile size when scaling below minNativeZoom
		if (minNativeZoom !== null && zoom < minNativeZoom) {
			return tileSize.divideBy(map.getZoomScale(minNativeZoom, zoom)).round();
		}

		// increase tile size when scaling above maxNativeZoom
		if(maxNativeZoom !== null && zoom > maxNativeZoom){
			return tileSize.divideBy(map.getZoomScale(maxNativeZoom, zoom)).round();
		}

		return tileSize;
	},

	_onTileRemove: function (e) {
		e.tile.onload = null;
	},

	_getZoomForUrl: function () {
		var zoom = this._tileZoom,
			maxZoom = this.options.maxZoom,
			zoomReverse = this.options.zoomReverse,
			zoomOffset = this.options.zoomOffset,
			minNativeZoom = this.options.minNativeZoom,
			maxNativeZoom = this.options.maxNativeZoom;

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

		zoom += zoomOffset;

		if (minNativeZoom !== null && zoom < minNativeZoom) {
			return minNativeZoom;
		}

		// increase tile size when scaling above maxNativeZoom
		if(maxNativeZoom !== null && zoom > maxNativeZoom) {
			return maxNativeZoom;
		}

		return zoom;
	},

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

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

				tile.onload = L.Util.falseFn;
				tile.onerror = L.Util.falseFn;

				if (!tile.complete) {
					tile.src = L.Util.emptyImageUrl;
					L.DomUtil.remove(tile);
				}
			}
		}
	}
});

// @factory L.tilelayer(urlTemplate: String, options?: TileLayer options)
// Instantiates a tile layer object given a `URL template` and optionally an options object.

L.tileLayer = function (url, options) {
	return new L.TileLayer(url, options);
};
<commit_msg>Fixing linting errors<commit_after>/*
 * @class TileLayer
 * @inherits GridLayer
 * @aka L.TileLayer
 * Used to load and display tile layers on the map. Extends `GridLayer`.
 *
 * @example
 *
 * ```js
 * L.tileLayer('http://{s}.tile.osm.org/{z}/{x}/{y}.png?{foo}', {foo: 'bar'}).addTo(map);
 * ```
 *
 * @section URL template
 * @example
 *
 * A string of the following form:
 *
 * ```
 * 'http://{s}.somedomain.com/blabla/{z}/{x}/{y}{r}.png'
 * ```
 *
 * `{s}` means one of the available subdomains (used sequentially to help with browser parallel requests per domain limitation; subdomain values are specified in options; `a`, `b` or `c` by default, can be omitted), `{z}` — zoom level, `{x}` and `{y}` — tile coordinates. `{r}` can be used to add @2x to the URL to load retina tiles.
 *
 * You can use custom keys in the template, which will be [evaluated](#util-template) from TileLayer options, like this:
 *
 * ```
 * L.tileLayer('http://{s}.somedomain.com/{foo}/{z}/{x}/{y}.png', {foo: 'bar'});
 * ```
 */

L.TileLayer = L.GridLayer.extend({

	// @section
	// @aka TileLayer options
	options: {
		// @option minZoom: Number = 0
		// Minimum zoom number.
		minZoom: 0,

		// @option maxZoom: Number = 18
		// Maximum zoom number.
		maxZoom: 18,

		// @option maxNativeZoom: Number = null
		// Maximum zoom number the tile source has available. If it is specified,
		// the tiles on all zoom levels higher than `maxNativeZoom` will be loaded
		// from `maxNativeZoom` level and auto-scaled.
		maxNativeZoom: null,

		// @option minNativeZoom: Number = null
		// Minimum zoom number the tile source has available. If it is specified,
		// the tiles on all zoom levels lower than `minNativeZoom` will be loaded
		// from `minNativeZoom` level and auto-scaled.
		minNativeZoom: null,

		// @option subdomains: String|String[] = 'abc'
		// Subdomains of the tile service. Can be passed in the form of one string (where each letter is a subdomain name) or an array of strings.
		subdomains: 'abc',

		// @option errorTileUrl: String = ''
		// URL to the tile image to show in place of the tile that failed to load.
		errorTileUrl: '',

		// @option zoomOffset: Number = 0
		// The zoom number used in tile URLs will be offset with this value.
		zoomOffset: 0,

		// @option tms: Boolean = false
		// If `true`, inverses Y axis numbering for tiles (turn this on for [TMS](https://en.wikipedia.org/wiki/Tile_Map_Service) services).
		tms: false,

		// @option zoomReverse: Boolean = false
		// If set to true, the zoom number used in tile URLs will be reversed (`maxZoom - zoom` instead of `zoom`)
		zoomReverse: false,

		// @option detectRetina: Boolean = false
		// If `true` and user is on a retina display, it will request four tiles of half the specified size and a bigger zoom level in place of one to utilize the high resolution.
		detectRetina: false,

		// @option crossOrigin: Boolean = false
		// If true, all tiles will have their crossOrigin attribute set to ''. This is needed if you want to access tile pixel data.
		crossOrigin: false
	},

	initialize: function (url, options) {

		this._url = url;

		options = L.setOptions(this, options);

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

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

			if (!options.zoomReverse) {
				options.zoomOffset++;
				options.maxZoom--;
			} else {
				options.zoomOffset--;
				options.minZoom++;
			}

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

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

		// for https://github.com/Leaflet/Leaflet/issues/137
		if (!L.Browser.android) {
			this.on('tileunload', this._onTileRemove);
		}
	},

	// @method setUrl(url: String, noRedraw?: Boolean): this
	// Updates the layer's URL template and redraws it (unless `noRedraw` is set to `true`).
	setUrl: function (url, noRedraw) {
		this._url = url;

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

	// @method createTile(coords: Object, done?: Function): HTMLElement
	// Called only internally, overrides GridLayer's [`createTile()`](#gridlayer-createtile)
	// to return an `<img>` HTML element with the appropiate image URL given `coords`. The `done`
	// callback is called when the tile has been loaded.
	createTile: function (coords, done) {
		var tile = document.createElement('img');

		L.DomEvent.on(tile, 'load', L.bind(this._tileOnLoad, this, done, tile));
		L.DomEvent.on(tile, 'error', L.bind(this._tileOnError, this, done, tile));

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

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

		/*
		 Set role="presentation" to force screen readers to ignore this
		 https://www.w3.org/TR/wai-aria/roles#textalternativecomputation
		*/
		tile.setAttribute('role', 'presentation');

		tile.src = this.getTileUrl(coords);

		return tile;
	},

	// @section Extension methods
	// @uninheritable
	// Layers extending `TileLayer` might reimplement the following method.
	// @method getTileUrl(coords: Object): String
	// Called only internally, returns the URL for a tile given its coordinates.
	// Classes extending `TileLayer` can override this function to provide custom tile URL naming schemes.
	getTileUrl: function (coords) {
		var data = {
			r: L.Browser.retina ? '@2x' : '',
			s: this._getSubdomain(coords),
			x: coords.x,
			y: coords.y,
			z: this._getZoomForUrl()
		};
		if (this._map && !this._map.options.crs.infinite) {
			var invertedY = this._globalTileRange.max.y - coords.y;
			if (this.options.tms) {
				data['y'] = invertedY;
			}
			data['-y'] = invertedY;
		}

		return L.Util.template(this._url, L.extend(data, this.options));
	},

	_tileOnLoad: function (done, tile) {
		// For https://github.com/Leaflet/Leaflet/issues/3332
		if (L.Browser.ielt9) {
			setTimeout(L.bind(done, this, null, tile), 0);
		} else {
			done(null, tile);
		}
	},

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

	getTileSize: function () {
		var map = this._map,
		tileSize = L.GridLayer.prototype.getTileSize.call(this),
		zoom = this._tileZoom + this.options.zoomOffset,
		minNativeZoom = this.options.minNativeZoom,
		maxNativeZoom = this.options.maxNativeZoom;

		// decrease tile size when scaling below minNativeZoom
		if (minNativeZoom !== null && zoom < minNativeZoom) {
			return tileSize.divideBy(map.getZoomScale(minNativeZoom, zoom)).round();
		}

		// increase tile size when scaling above maxNativeZoom
		if (maxNativeZoom !== null && zoom > maxNativeZoom) {
			return tileSize.divideBy(map.getZoomScale(maxNativeZoom, zoom)).round();
		}

		return tileSize;
	},

	_onTileRemove: function (e) {
		e.tile.onload = null;
	},

	_getZoomForUrl: function () {
		var zoom = this._tileZoom,
		maxZoom = this.options.maxZoom,
		zoomReverse = this.options.zoomReverse,
		zoomOffset = this.options.zoomOffset,
		minNativeZoom = this.options.minNativeZoom,
		maxNativeZoom = this.options.maxNativeZoom;

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

		zoom += zoomOffset;

		if (minNativeZoom !== null && zoom < minNativeZoom) {
			return minNativeZoom;
		}

		// increase tile size when scaling above maxNativeZoom
		if (maxNativeZoom !== null && zoom > maxNativeZoom) {
			return maxNativeZoom;
		}

		return zoom;
	},

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

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

				tile.onload = L.Util.falseFn;
				tile.onerror = L.Util.falseFn;

				if (!tile.complete) {
					tile.src = L.Util.emptyImageUrl;
					L.DomUtil.remove(tile);
				}
			}
		}
	}
});

// @factory L.tilelayer(urlTemplate: String, options?: TileLayer options)
// Instantiates a tile layer object given a `URL template` and optionally an options object.

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


<commit_before>/*
 * @class TileLayer
 * @inherits GridLayer
 * @aka L.TileLayer
 * Used to load and display tile layers on the map. Extends `GridLayer`.
 *
 * @example
 *
 * ```js
 * L.tileLayer('http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png?{foo}', {foo: 'bar'}).addTo(map);
 * ```
 *
 * @section URL template
 * @example
 *
 * A string of the following form:
 *
 * ```
 * 'http://{s}.somedomain.com/blabla/{z}/{x}/{y}{r}.png'
 * ```
 *
 * `{s}` means one of the available subdomains (used sequentially to help with browser parallel requests per domain limitation; subdomain values are specified in options; `a`, `b` or `c` by default, can be omitted), `{z}` — zoom level, `{x}` and `{y}` — tile coordinates. `{r}` can be used to add @2x to the URL to load retina tiles.
 *
 * You can use custom keys in the template, which will be [evaluated](#util-template) from TileLayer options, like this:
 *
 * ```
 * L.tileLayer('http://{s}.somedomain.com/{foo}/{z}/{x}/{y}.png', {foo: 'bar'});
 * ```
 */

L.TileLayer = L.GridLayer.extend({

	// @section
	// @aka TileLayer options
	options: {
		// @option minZoom: Number = 0
		// Minimum zoom number.
		minZoom: 0,

		// @option maxZoom: Number = 18
		// Maximum zoom number.
		maxZoom: 18,

		// @option maxNativeZoom: Number = null
		// Maximum zoom number the tile source has available. If it is specified,
		// the tiles on all zoom levels higher than `maxNativeZoom` will be loaded
		// from `maxNativeZoom` level and auto-scaled.
		maxNativeZoom: null,

		// @option minNativeZoom: Number = null
		// Minimum zoom number the tile source has available. If it is specified,
		// the tiles on all zoom levels lower than `minNativeZoom` will be loaded
		// from `minNativeZoom` level and auto-scaled.
		minNativeZoom: null,

		// @option subdomains: String|String[] = 'abc'
		// Subdomains of the tile service. Can be passed in the form of one string (where each letter is a subdomain name) or an array of strings.
		subdomains: 'abc',

		// @option errorTileUrl: String = ''
		// URL to the tile image to show in place of the tile that failed to load.
		errorTileUrl: '',

		// @option zoomOffset: Number = 0
		// The zoom number used in tile URLs will be offset with this value.
		zoomOffset: 0,

		// @option tms: Boolean = false
		// If `true`, inverses Y axis numbering for tiles (turn this on for [TMS](https://en.wikipedia.org/wiki/Tile_Map_Service) services).
		tms: false,

		// @option zoomReverse: Boolean = false
		// If set to true, the zoom number used in tile URLs will be reversed (`maxZoom - zoom` instead of `zoom`)
		zoomReverse: false,

		// @option detectRetina: Boolean = false
		// If `true` and user is on a retina display, it will request four tiles of half the specified size and a bigger zoom level in place of one to utilize the high resolution.
		detectRetina: false,

		// @option crossOrigin: Boolean = false
		// If true, all tiles will have their crossOrigin attribute set to ''. This is needed if you want to access tile pixel data.
		crossOrigin: false
	},

	initialize: function (url, options) {

		this._url = url;

		options = L.setOptions(this, options);

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

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

			if (!options.zoomReverse) {
				options.zoomOffset++;
				options.maxZoom--;
			} else {
				options.zoomOffset--;
				options.minZoom++;
			}

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

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

		// for https://github.com/Leaflet/Leaflet/issues/137
		if (!L.Browser.android) {
			this.on('tileunload', this._onTileRemove);
		}
	},

	// @method setUrl(url: String, noRedraw?: Boolean): this
	// Updates the layer's URL template and redraws it (unless `noRedraw` is set to `true`).
	setUrl: function (url, noRedraw) {
		this._url = url;

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

	// @method createTile(coords: Object, done?: Function): HTMLElement
	// Called only internally, overrides GridLayer's [`createTile()`](#gridlayer-createtile)
	// to return an `<img>` HTML element with the appropiate image URL given `coords`. The `done`
	// callback is called when the tile has been loaded.
	createTile: function (coords, done) {
		var tile = document.createElement('img');

		L.DomEvent.on(tile, 'load', L.bind(this._tileOnLoad, this, done, tile));
		L.DomEvent.on(tile, 'error', L.bind(this._tileOnError, this, done, tile));

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

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

		/*
		 Set role="presentation" to force screen readers to ignore this
		 https://www.w3.org/TR/wai-aria/roles#textalternativecomputation
		*/
		tile.setAttribute('role', 'presentation');

		tile.src = this.getTileUrl(coords);

		return tile;
	},

	// @section Extension methods
	// @uninheritable
	// Layers extending `TileLayer` might reimplement the following method.
	// @method getTileUrl(coords: Object): String
	// Called only internally, returns the URL for a tile given its coordinates.
	// Classes extending `TileLayer` can override this function to provide custom tile URL naming schemes.
	getTileUrl: function (coords) {
		var data = {
			r: L.Browser.retina ? '@2x' : '',
			s: this._getSubdomain(coords),
			x: coords.x,
			y: coords.y,
			z: this._getZoomForUrl()
		};
		if (this._map && !this._map.options.crs.infinite) {
			var invertedY = this._globalTileRange.max.y - coords.y;
			if (this.options.tms) {
				data['y'] = invertedY;
			}
			data['-y'] = invertedY;
		}

		return L.Util.template(this._url, L.extend(data, this.options));
	},

	_tileOnLoad: function (done, tile) {
		// For https://github.com/Leaflet/Leaflet/issues/3332
		if (L.Browser.ielt9) {
			setTimeout(L.bind(done, this, null, tile), 0);
		} else {
			done(null, tile);
		}
	},

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

	getTileSize: function () {
		var map = this._map,
		tileSize = L.GridLayer.prototype.getTileSize.call(this),
		zoom = this._tileZoom + this.options.zoomOffset,
		minNativeZoom = this.options.minNativeZoom,
		maxNativeZoom = this.options.maxNativeZoom;

		// decrease tile size when scaling below minNativeZoom
		if (minNativeZoom !== null && zoom < minNativeZoom) {
			return tileSize.divideBy(map.getZoomScale(minNativeZoom, zoom)).round();
		}

		// increase tile size when scaling above maxNativeZoom
		if (maxNativeZoom !== null && zoom > maxNativeZoom) {
			return tileSize.divideBy(map.getZoomScale(maxNativeZoom, zoom)).round();
		}

		return tileSize;
	},

	_onTileRemove: function (e) {
		e.tile.onload = null;
	},

	_getZoomForUrl: function () {
		var zoom = this._tileZoom,
		maxZoom = this.options.maxZoom,
		zoomReverse = this.options.zoomReverse,
		zoomOffset = this.options.zoomOffset,
		minNativeZoom = this.options.minNativeZoom,
		maxNativeZoom = this.options.maxNativeZoom;

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

		zoom += zoomOffset;

		if (minNativeZoom !== null && zoom < minNativeZoom) {
			return minNativeZoom;
		}

		if (maxNativeZoom !== null && zoom > maxNativeZoom) {
			return maxNativeZoom;
		}

		return zoom;
	},

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

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

				tile.onload = L.Util.falseFn;
				tile.onerror = L.Util.falseFn;

				if (!tile.complete) {
					tile.src = L.Util.emptyImageUrl;
					L.DomUtil.remove(tile);
				}
			}
		}
	}
});

// @factory L.tilelayer(urlTemplate: String, options?: TileLayer options)
// Instantiates a tile layer object given a `URL template` and optionally an options object.

L.tileLayer = function (url, options) {
	return new L.TileLayer(url, options);
};
<commit_msg>Prevent infinite loop on failing errorTileUrls (fixes #5176) (#5177)<commit_after>/*
 * @class TileLayer
 * @inherits GridLayer
 * @aka L.TileLayer
 * Used to load and display tile layers on the map. Extends `GridLayer`.
 *
 * @example
 *
 * ```js
 * L.tileLayer('http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png?{foo}', {foo: 'bar'}).addTo(map);
 * ```
 *
 * @section URL template
 * @example
 *
 * A string of the following form:
 *
 * ```
 * 'http://{s}.somedomain.com/blabla/{z}/{x}/{y}{r}.png'
 * ```
 *
 * `{s}` means one of the available subdomains (used sequentially to help with browser parallel requests per domain limitation; subdomain values are specified in options; `a`, `b` or `c` by default, can be omitted), `{z}` — zoom level, `{x}` and `{y}` — tile coordinates. `{r}` can be used to add @2x to the URL to load retina tiles.
 *
 * You can use custom keys in the template, which will be [evaluated](#util-template) from TileLayer options, like this:
 *
 * ```
 * L.tileLayer('http://{s}.somedomain.com/{foo}/{z}/{x}/{y}.png', {foo: 'bar'});
 * ```
 */

L.TileLayer = L.GridLayer.extend({

	// @section
	// @aka TileLayer options
	options: {
		// @option minZoom: Number = 0
		// Minimum zoom number.
		minZoom: 0,

		// @option maxZoom: Number = 18
		// Maximum zoom number.
		maxZoom: 18,

		// @option maxNativeZoom: Number = null
		// Maximum zoom number the tile source has available. If it is specified,
		// the tiles on all zoom levels higher than `maxNativeZoom` will be loaded
		// from `maxNativeZoom` level and auto-scaled.
		maxNativeZoom: null,

		// @option minNativeZoom: Number = null
		// Minimum zoom number the tile source has available. If it is specified,
		// the tiles on all zoom levels lower than `minNativeZoom` will be loaded
		// from `minNativeZoom` level and auto-scaled.
		minNativeZoom: null,

		// @option subdomains: String|String[] = 'abc'
		// Subdomains of the tile service. Can be passed in the form of one string (where each letter is a subdomain name) or an array of strings.
		subdomains: 'abc',

		// @option errorTileUrl: String = ''
		// URL to the tile image to show in place of the tile that failed to load.
		errorTileUrl: '',

		// @option zoomOffset: Number = 0
		// The zoom number used in tile URLs will be offset with this value.
		zoomOffset: 0,

		// @option tms: Boolean = false
		// If `true`, inverses Y axis numbering for tiles (turn this on for [TMS](https://en.wikipedia.org/wiki/Tile_Map_Service) services).
		tms: false,

		// @option zoomReverse: Boolean = false
		// If set to true, the zoom number used in tile URLs will be reversed (`maxZoom - zoom` instead of `zoom`)
		zoomReverse: false,

		// @option detectRetina: Boolean = false
		// If `true` and user is on a retina display, it will request four tiles of half the specified size and a bigger zoom level in place of one to utilize the high resolution.
		detectRetina: false,

		// @option crossOrigin: Boolean = false
		// If true, all tiles will have their crossOrigin attribute set to ''. This is needed if you want to access tile pixel data.
		crossOrigin: false
	},

	initialize: function (url, options) {

		this._url = url;

		options = L.setOptions(this, options);

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

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

			if (!options.zoomReverse) {
				options.zoomOffset++;
				options.maxZoom--;
			} else {
				options.zoomOffset--;
				options.minZoom++;
			}

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

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

		// for https://github.com/Leaflet/Leaflet/issues/137
		if (!L.Browser.android) {
			this.on('tileunload', this._onTileRemove);
		}
	},

	// @method setUrl(url: String, noRedraw?: Boolean): this
	// Updates the layer's URL template and redraws it (unless `noRedraw` is set to `true`).
	setUrl: function (url, noRedraw) {
		this._url = url;

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

	// @method createTile(coords: Object, done?: Function): HTMLElement
	// Called only internally, overrides GridLayer's [`createTile()`](#gridlayer-createtile)
	// to return an `<img>` HTML element with the appropiate image URL given `coords`. The `done`
	// callback is called when the tile has been loaded.
	createTile: function (coords, done) {
		var tile = document.createElement('img');

		L.DomEvent.on(tile, 'load', L.bind(this._tileOnLoad, this, done, tile));
		L.DomEvent.on(tile, 'error', L.bind(this._tileOnError, this, done, tile));

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

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

		/*
		 Set role="presentation" to force screen readers to ignore this
		 https://www.w3.org/TR/wai-aria/roles#textalternativecomputation
		*/
		tile.setAttribute('role', 'presentation');

		tile.src = this.getTileUrl(coords);

		return tile;
	},

	// @section Extension methods
	// @uninheritable
	// Layers extending `TileLayer` might reimplement the following method.
	// @method getTileUrl(coords: Object): String
	// Called only internally, returns the URL for a tile given its coordinates.
	// Classes extending `TileLayer` can override this function to provide custom tile URL naming schemes.
	getTileUrl: function (coords) {
		var data = {
			r: L.Browser.retina ? '@2x' : '',
			s: this._getSubdomain(coords),
			x: coords.x,
			y: coords.y,
			z: this._getZoomForUrl()
		};
		if (this._map && !this._map.options.crs.infinite) {
			var invertedY = this._globalTileRange.max.y - coords.y;
			if (this.options.tms) {
				data['y'] = invertedY;
			}
			data['-y'] = invertedY;
		}

		return L.Util.template(this._url, L.extend(data, this.options));
	},

	_tileOnLoad: function (done, tile) {
		// For https://github.com/Leaflet/Leaflet/issues/3332
		if (L.Browser.ielt9) {
			setTimeout(L.bind(done, this, null, tile), 0);
		} else {
			done(null, tile);
		}
	},

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

	getTileSize: function () {
		var map = this._map,
		tileSize = L.GridLayer.prototype.getTileSize.call(this),
		zoom = this._tileZoom + this.options.zoomOffset,
		minNativeZoom = this.options.minNativeZoom,
		maxNativeZoom = this.options.maxNativeZoom;

		// decrease tile size when scaling below minNativeZoom
		if (minNativeZoom !== null && zoom < minNativeZoom) {
			return tileSize.divideBy(map.getZoomScale(minNativeZoom, zoom)).round();
		}

		// increase tile size when scaling above maxNativeZoom
		if (maxNativeZoom !== null && zoom > maxNativeZoom) {
			return tileSize.divideBy(map.getZoomScale(maxNativeZoom, zoom)).round();
		}

		return tileSize;
	},

	_onTileRemove: function (e) {
		e.tile.onload = null;
	},

	_getZoomForUrl: function () {
		var zoom = this._tileZoom,
		maxZoom = this.options.maxZoom,
		zoomReverse = this.options.zoomReverse,
		zoomOffset = this.options.zoomOffset,
		minNativeZoom = this.options.minNativeZoom,
		maxNativeZoom = this.options.maxNativeZoom;

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

		zoom += zoomOffset;

		if (minNativeZoom !== null && zoom < minNativeZoom) {
			return minNativeZoom;
		}

		if (maxNativeZoom !== null && zoom > maxNativeZoom) {
			return maxNativeZoom;
		}

		return zoom;
	},

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

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

				tile.onload = L.Util.falseFn;
				tile.onerror = L.Util.falseFn;

				if (!tile.complete) {
					tile.src = L.Util.emptyImageUrl;
					L.DomUtil.remove(tile);
				}
			}
		}
	}
});

// @factory L.tilelayer(urlTemplate: String, options?: TileLayer options)
// Instantiates a tile layer object given a `URL template` and optionally an options object.

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