")
- .html(html)
- .appendTo($entry)
-
- $entry.height(height + $readme.outerHeight())
-
- transitionComplete(function() {
- $entry.css('height', 'auto')
- })
- }
- })
- }
- })
-})
-
-},{"onclick":25,"transition-complete":26,"unopinionate":27}],4:[function(require,module,exports){
-// twitter bootstrap stuff;
-// not in static 'cause I want it to be bundled with the rest of javascripts
-require('./bootstrap-modal')
-
-// our own files
-require('./search')
-require('./entry')
-
-var $ = require('unopinionate').selector
-$(document).on('click', '.js-userLogoutBtn', function() {
- $('#userLogoutForm').submit()
- return false
-})
-
-},{"./bootstrap-modal":2,"./entry":3,"./search":5,"unopinionate":27}],5:[function(require,module,exports){
-var $ = require('unopinionate').selector
-var template = require('../entry.hbs')
-
-$(function() {
- ;(function(window, document) {
- var $form = $('#search-form')
- var $input = $form.find('input')
- var $searchResults = $('#search-results')
- var $pkgListing = $('#all-packages')
- var $searchBtn = $('.js-search-btn')
- var request
- var lastQuery = ''
-
- var toggle = function(validQuery) {
- $searchResults.toggleClass('show', validQuery)
- $pkgListing.toggleClass('hide', validQuery)
-
- $searchBtn.find('i').toggleClass('icon-cancel', validQuery)
- $searchBtn.find('i').toggleClass('icon-search', !validQuery)
- }
-
- $form.bind('submit keyup', function(e) {
- var query, isValidQuery
-
- e.preventDefault()
-
- query = $input.val()
- isValidQuery = (query !== '')
-
- toggle(isValidQuery)
-
- if (!isValidQuery) {
- if (request && typeof request.abort === 'function') {
- request.abort()
- }
-
- $searchResults.html('')
- return
- }
-
- if (request && typeof request.abort === 'function') {
- request.abort()
- }
-
- if (query !== lastQuery) {
- lastQuery = query
- $searchResults.html(
- "
")
- }
-
- request = $.getJSON('-/search/' + query, function( results ) {
- if (results.length > 0) {
- var html = ''
-
- $.each(results, function(i, entry) {
- html += template(entry)
- })
-
- $searchResults.html(html)
- } else {
- $searchResults.html(
- "
No Results
")
- }
- }).fail(function () {
- $searchResults.html(
- "
No Results
")
- })
- })
-
- $(document).on('click', '.icon-cancel', function(e) {
- e.preventDefault()
- $input.val('')
- $form.keyup()
- })
-
- })(window, window.document)
-})
-
-},{"../entry.hbs":1,"unopinionate":27}],6:[function(require,module,exports){
-'use strict';
-
-exports.__esModule = true;
-// istanbul ignore next
-
-function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
-
-// istanbul ignore next
-
-function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj['default'] = obj; return newObj; } }
-
-var _handlebarsBase = require('./handlebars/base');
-
-var base = _interopRequireWildcard(_handlebarsBase);
-
-// Each of these augment the Handlebars object. No need to setup here.
-// (This is done to easily share code between commonjs and browse envs)
-
-var _handlebarsSafeString = require('./handlebars/safe-string');
-
-var _handlebarsSafeString2 = _interopRequireDefault(_handlebarsSafeString);
-
-var _handlebarsException = require('./handlebars/exception');
-
-var _handlebarsException2 = _interopRequireDefault(_handlebarsException);
-
-var _handlebarsUtils = require('./handlebars/utils');
-
-var Utils = _interopRequireWildcard(_handlebarsUtils);
-
-var _handlebarsRuntime = require('./handlebars/runtime');
-
-var runtime = _interopRequireWildcard(_handlebarsRuntime);
-
-var _handlebarsNoConflict = require('./handlebars/no-conflict');
-
-var _handlebarsNoConflict2 = _interopRequireDefault(_handlebarsNoConflict);
-
-// For compatibility and usage outside of module systems, make the Handlebars object a namespace
-function create() {
- var hb = new base.HandlebarsEnvironment();
-
- Utils.extend(hb, base);
- hb.SafeString = _handlebarsSafeString2['default'];
- hb.Exception = _handlebarsException2['default'];
- hb.Utils = Utils;
- hb.escapeExpression = Utils.escapeExpression;
-
- hb.VM = runtime;
- hb.template = function (spec) {
- return runtime.template(spec, hb);
- };
-
- return hb;
-}
-
-var inst = create();
-inst.create = create;
-
-_handlebarsNoConflict2['default'](inst);
-
-inst['default'] = inst;
-
-exports['default'] = inst;
-module.exports = exports['default'];
-
-
-},{"./handlebars/base":7,"./handlebars/exception":10,"./handlebars/no-conflict":20,"./handlebars/runtime":21,"./handlebars/safe-string":22,"./handlebars/utils":23}],7:[function(require,module,exports){
-'use strict';
-
-exports.__esModule = true;
-exports.HandlebarsEnvironment = HandlebarsEnvironment;
-// istanbul ignore next
-
-function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
-
-var _utils = require('./utils');
-
-var _exception = require('./exception');
-
-var _exception2 = _interopRequireDefault(_exception);
-
-var _helpers = require('./helpers');
-
-var _decorators = require('./decorators');
-
-var _logger = require('./logger');
-
-var _logger2 = _interopRequireDefault(_logger);
-
-var VERSION = '4.0.5';
-exports.VERSION = VERSION;
-var COMPILER_REVISION = 7;
-
-exports.COMPILER_REVISION = COMPILER_REVISION;
-var REVISION_CHANGES = {
- 1: '<= 1.0.rc.2', // 1.0.rc.2 is actually rev2 but doesn't report it
- 2: '== 1.0.0-rc.3',
- 3: '== 1.0.0-rc.4',
- 4: '== 1.x.x',
- 5: '== 2.0.0-alpha.x',
- 6: '>= 2.0.0-beta.1',
- 7: '>= 4.0.0'
-};
-
-exports.REVISION_CHANGES = REVISION_CHANGES;
-var objectType = '[object Object]';
-
-function HandlebarsEnvironment(helpers, partials, decorators) {
- this.helpers = helpers || {};
- this.partials = partials || {};
- this.decorators = decorators || {};
-
- _helpers.registerDefaultHelpers(this);
- _decorators.registerDefaultDecorators(this);
-}
-
-HandlebarsEnvironment.prototype = {
- constructor: HandlebarsEnvironment,
-
- logger: _logger2['default'],
- log: _logger2['default'].log,
-
- registerHelper: function registerHelper(name, fn) {
- if (_utils.toString.call(name) === objectType) {
- if (fn) {
- throw new _exception2['default']('Arg not supported with multiple helpers');
- }
- _utils.extend(this.helpers, name);
- } else {
- this.helpers[name] = fn;
- }
- },
- unregisterHelper: function unregisterHelper(name) {
- delete this.helpers[name];
- },
-
- registerPartial: function registerPartial(name, partial) {
- if (_utils.toString.call(name) === objectType) {
- _utils.extend(this.partials, name);
- } else {
- if (typeof partial === 'undefined') {
- throw new _exception2['default']('Attempting to register a partial called "' + name + '" as undefined');
- }
- this.partials[name] = partial;
- }
- },
- unregisterPartial: function unregisterPartial(name) {
- delete this.partials[name];
- },
-
- registerDecorator: function registerDecorator(name, fn) {
- if (_utils.toString.call(name) === objectType) {
- if (fn) {
- throw new _exception2['default']('Arg not supported with multiple decorators');
- }
- _utils.extend(this.decorators, name);
- } else {
- this.decorators[name] = fn;
- }
- },
- unregisterDecorator: function unregisterDecorator(name) {
- delete this.decorators[name];
- }
-};
-
-var log = _logger2['default'].log;
-
-exports.log = log;
-exports.createFrame = _utils.createFrame;
-exports.logger = _logger2['default'];
-
-
-},{"./decorators":8,"./exception":10,"./helpers":11,"./logger":19,"./utils":23}],8:[function(require,module,exports){
-'use strict';
-
-exports.__esModule = true;
-exports.registerDefaultDecorators = registerDefaultDecorators;
-// istanbul ignore next
-
-function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
-
-var _decoratorsInline = require('./decorators/inline');
-
-var _decoratorsInline2 = _interopRequireDefault(_decoratorsInline);
-
-function registerDefaultDecorators(instance) {
- _decoratorsInline2['default'](instance);
-}
-
-
-},{"./decorators/inline":9}],9:[function(require,module,exports){
-'use strict';
-
-exports.__esModule = true;
-
-var _utils = require('../../utils');
-
-exports['default'] = function (instance) {
- instance.registerDecorator('inline', function (fn, props, container, options) {
- var ret = fn;
- if (!props.partials) {
- props.partials = {};
- ret = function (context, options) {
- // Create a new partials stack frame prior to exec.
- var original = container.partials;
- container.partials = _utils.extend({}, original, props.partials);
- var ret = fn(context, options);
- container.partials = original;
- return ret;
- };
- }
-
- props.partials[options.args[0]] = options.fn;
-
- return ret;
- });
-};
-
-module.exports = exports['default'];
-
-
-},{"../utils":23}],10:[function(require,module,exports){
-'use strict';
-
-exports.__esModule = true;
-
-var errorProps = ['description', 'fileName', 'lineNumber', 'message', 'name', 'number', 'stack'];
-
-function Exception(message, node) {
- var loc = node && node.loc,
- line = undefined,
- column = undefined;
- if (loc) {
- line = loc.start.line;
- column = loc.start.column;
-
- message += ' - ' + line + ':' + column;
- }
-
- var tmp = Error.prototype.constructor.call(this, message);
-
- // Unfortunately errors are not enumerable in Chrome (at least), so `for prop in tmp` doesn't work.
- for (var idx = 0; idx < errorProps.length; idx++) {
- this[errorProps[idx]] = tmp[errorProps[idx]];
- }
-
- /* istanbul ignore else */
- if (Error.captureStackTrace) {
- Error.captureStackTrace(this, Exception);
- }
-
- try {
- if (loc) {
- this.lineNumber = line;
-
- // Work around issue under safari where we can't directly set the column value
- /* istanbul ignore next */
- if (Object.defineProperty) {
- Object.defineProperty(this, 'column', { value: column });
- } else {
- this.column = column;
- }
- }
- } catch (nop) {
- /* Ignore if the browser is very particular */
- }
-}
-
-Exception.prototype = new Error();
-
-exports['default'] = Exception;
-module.exports = exports['default'];
-
-
-},{}],11:[function(require,module,exports){
-'use strict';
-
-exports.__esModule = true;
-exports.registerDefaultHelpers = registerDefaultHelpers;
-// istanbul ignore next
-
-function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
-
-var _helpersBlockHelperMissing = require('./helpers/block-helper-missing');
-
-var _helpersBlockHelperMissing2 = _interopRequireDefault(_helpersBlockHelperMissing);
-
-var _helpersEach = require('./helpers/each');
-
-var _helpersEach2 = _interopRequireDefault(_helpersEach);
-
-var _helpersHelperMissing = require('./helpers/helper-missing');
-
-var _helpersHelperMissing2 = _interopRequireDefault(_helpersHelperMissing);
-
-var _helpersIf = require('./helpers/if');
-
-var _helpersIf2 = _interopRequireDefault(_helpersIf);
-
-var _helpersLog = require('./helpers/log');
-
-var _helpersLog2 = _interopRequireDefault(_helpersLog);
-
-var _helpersLookup = require('./helpers/lookup');
-
-var _helpersLookup2 = _interopRequireDefault(_helpersLookup);
-
-var _helpersWith = require('./helpers/with');
-
-var _helpersWith2 = _interopRequireDefault(_helpersWith);
-
-function registerDefaultHelpers(instance) {
- _helpersBlockHelperMissing2['default'](instance);
- _helpersEach2['default'](instance);
- _helpersHelperMissing2['default'](instance);
- _helpersIf2['default'](instance);
- _helpersLog2['default'](instance);
- _helpersLookup2['default'](instance);
- _helpersWith2['default'](instance);
-}
-
-
-},{"./helpers/block-helper-missing":12,"./helpers/each":13,"./helpers/helper-missing":14,"./helpers/if":15,"./helpers/log":16,"./helpers/lookup":17,"./helpers/with":18}],12:[function(require,module,exports){
-'use strict';
-
-exports.__esModule = true;
-
-var _utils = require('../../utils');
-
-exports['default'] = function (instance) {
- instance.registerHelper('blockHelperMissing', function (context, options) {
- var inverse = options.inverse,
- fn = options.fn;
-
- if (context === true) {
- return fn(this);
- } else if (context === false || context == null) {
- return inverse(this);
- } else if (_utils.isArray(context)) {
- if (context.length > 0) {
- if (options.ids) {
- options.ids = [options.name];
- }
-
- return instance.helpers.each(context, options);
- } else {
- return inverse(this);
- }
- } else {
- if (options.data && options.ids) {
- var data = _utils.createFrame(options.data);
- data.contextPath = _utils.appendContextPath(options.data.contextPath, options.name);
- options = { data: data };
- }
-
- return fn(context, options);
- }
- });
-};
-
-module.exports = exports['default'];
-
-
-},{"../utils":23}],13:[function(require,module,exports){
-'use strict';
-
-exports.__esModule = true;
-// istanbul ignore next
-
-function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
-
-var _utils = require('../../utils');
-
-var _exception = require('../exception');
-
-var _exception2 = _interopRequireDefault(_exception);
-
-exports['default'] = function (instance) {
- instance.registerHelper('each', function (context, options) {
- if (!options) {
- throw new _exception2['default']('Must pass iterator to #each');
- }
-
- var fn = options.fn,
- inverse = options.inverse,
- i = 0,
- ret = '',
- data = undefined,
- contextPath = undefined;
-
- if (options.data && options.ids) {
- contextPath = _utils.appendContextPath(options.data.contextPath, options.ids[0]) + '.';
- }
-
- if (_utils.isFunction(context)) {
- context = context.call(this);
- }
-
- if (options.data) {
- data = _utils.createFrame(options.data);
- }
-
- function execIteration(field, index, last) {
- if (data) {
- data.key = field;
- data.index = index;
- data.first = index === 0;
- data.last = !!last;
-
- if (contextPath) {
- data.contextPath = contextPath + field;
- }
- }
-
- ret = ret + fn(context[field], {
- data: data,
- blockParams: _utils.blockParams([context[field], field], [contextPath + field, null])
- });
- }
-
- if (context && typeof context === 'object') {
- if (_utils.isArray(context)) {
- for (var j = context.length; i < j; i++) {
- if (i in context) {
- execIteration(i, i, i === context.length - 1);
- }
- }
- } else {
- var priorKey = undefined;
-
- for (var key in context) {
- if (context.hasOwnProperty(key)) {
- // We're running the iterations one step out of sync so we can detect
- // the last iteration without have to scan the object twice and create
- // an itermediate keys array.
- if (priorKey !== undefined) {
- execIteration(priorKey, i - 1);
- }
- priorKey = key;
- i++;
- }
- }
- if (priorKey !== undefined) {
- execIteration(priorKey, i - 1, true);
- }
- }
- }
-
- if (i === 0) {
- ret = inverse(this);
- }
-
- return ret;
- });
-};
-
-module.exports = exports['default'];
-
-
-},{"../exception":10,"../utils":23}],14:[function(require,module,exports){
-'use strict';
-
-exports.__esModule = true;
-// istanbul ignore next
-
-function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
-
-var _exception = require('../exception');
-
-var _exception2 = _interopRequireDefault(_exception);
-
-exports['default'] = function (instance) {
- instance.registerHelper('helperMissing', function () /* [args, ]options */{
- if (arguments.length === 1) {
- // A missing field in a {{foo}} construct.
- return undefined;
- } else {
- // Someone is actually trying to call something, blow up.
- throw new _exception2['default']('Missing helper: "' + arguments[arguments.length - 1].name + '"');
- }
- });
-};
-
-module.exports = exports['default'];
-
-
-},{"../exception":10}],15:[function(require,module,exports){
-'use strict';
-
-exports.__esModule = true;
-
-var _utils = require('../../utils');
-
-exports['default'] = function (instance) {
- instance.registerHelper('if', function (conditional, options) {
- if (_utils.isFunction(conditional)) {
- conditional = conditional.call(this);
- }
-
- // Default behavior is to render the positive path if the value is truthy and not empty.
- // The `includeZero` option may be set to treat the condtional as purely not empty based on the
- // behavior of isEmpty. Effectively this determines if 0 is handled by the positive path or negative.
- if (!options.hash.includeZero && !conditional || _utils.isEmpty(conditional)) {
- return options.inverse(this);
- } else {
- return options.fn(this);
- }
- });
-
- instance.registerHelper('unless', function (conditional, options) {
- return instance.helpers['if'].call(this, conditional, { fn: options.inverse, inverse: options.fn, hash: options.hash });
- });
-};
-
-module.exports = exports['default'];
-
-
-},{"../utils":23}],16:[function(require,module,exports){
-'use strict';
-
-exports.__esModule = true;
-
-exports['default'] = function (instance) {
- instance.registerHelper('log', function () /* message, options */{
- var args = [undefined],
- options = arguments[arguments.length - 1];
- for (var i = 0; i < arguments.length - 1; i++) {
- args.push(arguments[i]);
- }
-
- var level = 1;
- if (options.hash.level != null) {
- level = options.hash.level;
- } else if (options.data && options.data.level != null) {
- level = options.data.level;
- }
- args[0] = level;
-
- instance.log.apply(instance, args);
- });
-};
-
-module.exports = exports['default'];
-
-
-},{}],17:[function(require,module,exports){
-'use strict';
-
-exports.__esModule = true;
-
-exports['default'] = function (instance) {
- instance.registerHelper('lookup', function (obj, field) {
- return obj && obj[field];
- });
-};
-
-module.exports = exports['default'];
-
-
-},{}],18:[function(require,module,exports){
-'use strict';
-
-exports.__esModule = true;
-
-var _utils = require('../../utils');
-
-exports['default'] = function (instance) {
- instance.registerHelper('with', function (context, options) {
- if (_utils.isFunction(context)) {
- context = context.call(this);
- }
-
- var fn = options.fn;
-
- if (!_utils.isEmpty(context)) {
- var data = options.data;
- if (options.data && options.ids) {
- data = _utils.createFrame(options.data);
- data.contextPath = _utils.appendContextPath(options.data.contextPath, options.ids[0]);
- }
-
- return fn(context, {
- data: data,
- blockParams: _utils.blockParams([context], [data && data.contextPath])
- });
- } else {
- return options.inverse(this);
- }
- });
-};
-
-module.exports = exports['default'];
-
-
-},{"../utils":23}],19:[function(require,module,exports){
-'use strict';
-
-exports.__esModule = true;
-
-var _utils = require('./utils');
-
-var logger = {
- methodMap: ['debug', 'info', 'warn', 'error'],
- level: 'info',
-
- // Maps a given level value to the `methodMap` indexes above.
- lookupLevel: function lookupLevel(level) {
- if (typeof level === 'string') {
- var levelMap = _utils.indexOf(logger.methodMap, level.toLowerCase());
- if (levelMap >= 0) {
- level = levelMap;
- } else {
- level = parseInt(level, 10);
- }
- }
-
- return level;
- },
-
- // Can be overridden in the host environment
- log: function log(level) {
- level = logger.lookupLevel(level);
-
- if (typeof console !== 'undefined' && logger.lookupLevel(logger.level) <= level) {
- var method = logger.methodMap[level];
- if (!console[method]) {
- // eslint-disable-line no-console
- method = 'log';
- }
-
- for (var _len = arguments.length, message = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
- message[_key - 1] = arguments[_key];
- }
-
- console[method].apply(console, message); // eslint-disable-line no-console
- }
- }
-};
-
-exports['default'] = logger;
-module.exports = exports['default'];
-
-
-},{"./utils":23}],20:[function(require,module,exports){
-(function (global){
-/* global window */
-'use strict';
-
-exports.__esModule = true;
-
-exports['default'] = function (Handlebars) {
- /* istanbul ignore next */
- var root = typeof global !== 'undefined' ? global : window,
- $Handlebars = root.Handlebars;
- /* istanbul ignore next */
- Handlebars.noConflict = function () {
- if (root.Handlebars === Handlebars) {
- root.Handlebars = $Handlebars;
- }
- return Handlebars;
- };
-};
-
-module.exports = exports['default'];
-
-
-}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
-},{}],21:[function(require,module,exports){
-'use strict';
-
-exports.__esModule = true;
-exports.checkRevision = checkRevision;
-exports.template = template;
-exports.wrapProgram = wrapProgram;
-exports.resolvePartial = resolvePartial;
-exports.invokePartial = invokePartial;
-exports.noop = noop;
-// istanbul ignore next
-
-function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
-
-// istanbul ignore next
-
-function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj['default'] = obj; return newObj; } }
-
-var _utils = require('./utils');
-
-var Utils = _interopRequireWildcard(_utils);
-
-var _exception = require('./exception');
-
-var _exception2 = _interopRequireDefault(_exception);
-
-var _base = require('./base');
-
-function checkRevision(compilerInfo) {
- var compilerRevision = compilerInfo && compilerInfo[0] || 1,
- currentRevision = _base.COMPILER_REVISION;
-
- if (compilerRevision !== currentRevision) {
- if (compilerRevision < currentRevision) {
- var runtimeVersions = _base.REVISION_CHANGES[currentRevision],
- compilerVersions = _base.REVISION_CHANGES[compilerRevision];
- throw new _exception2['default']('Template was precompiled with an older version of Handlebars than the current runtime. ' + 'Please update your precompiler to a newer version (' + runtimeVersions + ') or downgrade your runtime to an older version (' + compilerVersions + ').');
- } else {
- // Use the embedded version info since the runtime doesn't know about this revision yet
- throw new _exception2['default']('Template was precompiled with a newer version of Handlebars than the current runtime. ' + 'Please update your runtime to a newer version (' + compilerInfo[1] + ').');
- }
- }
-}
-
-function template(templateSpec, env) {
- /* istanbul ignore next */
- if (!env) {
- throw new _exception2['default']('No environment passed to template');
- }
- if (!templateSpec || !templateSpec.main) {
- throw new _exception2['default']('Unknown template object: ' + typeof templateSpec);
- }
-
- templateSpec.main.decorator = templateSpec.main_d;
-
- // Note: Using env.VM references rather than local var references throughout this section to allow
- // for external users to override these as psuedo-supported APIs.
- env.VM.checkRevision(templateSpec.compiler);
-
- function invokePartialWrapper(partial, context, options) {
- if (options.hash) {
- context = Utils.extend({}, context, options.hash);
- if (options.ids) {
- options.ids[0] = true;
- }
- }
-
- partial = env.VM.resolvePartial.call(this, partial, context, options);
- var result = env.VM.invokePartial.call(this, partial, context, options);
-
- if (result == null && env.compile) {
- options.partials[options.name] = env.compile(partial, templateSpec.compilerOptions, env);
- result = options.partials[options.name](context, options);
- }
- if (result != null) {
- if (options.indent) {
- var lines = result.split('\n');
- for (var i = 0, l = lines.length; i < l; i++) {
- if (!lines[i] && i + 1 === l) {
- break;
- }
-
- lines[i] = options.indent + lines[i];
- }
- result = lines.join('\n');
- }
- return result;
- } else {
- throw new _exception2['default']('The partial ' + options.name + ' could not be compiled when running in runtime-only mode');
- }
- }
-
- // Just add water
- var container = {
- strict: function strict(obj, name) {
- if (!(name in obj)) {
- throw new _exception2['default']('"' + name + '" not defined in ' + obj);
- }
- return obj[name];
- },
- lookup: function lookup(depths, name) {
- var len = depths.length;
- for (var i = 0; i < len; i++) {
- if (depths[i] && depths[i][name] != null) {
- return depths[i][name];
- }
- }
- },
- lambda: function lambda(current, context) {
- return typeof current === 'function' ? current.call(context) : current;
- },
-
- escapeExpression: Utils.escapeExpression,
- invokePartial: invokePartialWrapper,
-
- fn: function fn(i) {
- var ret = templateSpec[i];
- ret.decorator = templateSpec[i + '_d'];
- return ret;
- },
-
- programs: [],
- program: function program(i, data, declaredBlockParams, blockParams, depths) {
- var programWrapper = this.programs[i],
- fn = this.fn(i);
- if (data || depths || blockParams || declaredBlockParams) {
- programWrapper = wrapProgram(this, i, fn, data, declaredBlockParams, blockParams, depths);
- } else if (!programWrapper) {
- programWrapper = this.programs[i] = wrapProgram(this, i, fn);
- }
- return programWrapper;
- },
-
- data: function data(value, depth) {
- while (value && depth--) {
- value = value._parent;
- }
- return value;
- },
- merge: function merge(param, common) {
- var obj = param || common;
-
- if (param && common && param !== common) {
- obj = Utils.extend({}, common, param);
- }
-
- return obj;
- },
-
- noop: env.VM.noop,
- compilerInfo: templateSpec.compiler
- };
-
- function ret(context) {
- var options = arguments.length <= 1 || arguments[1] === undefined ? {} : arguments[1];
-
- var data = options.data;
-
- ret._setup(options);
- if (!options.partial && templateSpec.useData) {
- data = initData(context, data);
- }
- var depths = undefined,
- blockParams = templateSpec.useBlockParams ? [] : undefined;
- if (templateSpec.useDepths) {
- if (options.depths) {
- depths = context != options.depths[0] ? [context].concat(options.depths) : options.depths;
- } else {
- depths = [context];
- }
- }
-
- function main(context /*, options*/) {
- return '' + templateSpec.main(container, context, container.helpers, container.partials, data, blockParams, depths);
- }
- main = executeDecorators(templateSpec.main, main, container, options.depths || [], data, blockParams);
- return main(context, options);
- }
- ret.isTop = true;
-
- ret._setup = function (options) {
- if (!options.partial) {
- container.helpers = container.merge(options.helpers, env.helpers);
-
- if (templateSpec.usePartial) {
- container.partials = container.merge(options.partials, env.partials);
- }
- if (templateSpec.usePartial || templateSpec.useDecorators) {
- container.decorators = container.merge(options.decorators, env.decorators);
- }
- } else {
- container.helpers = options.helpers;
- container.partials = options.partials;
- container.decorators = options.decorators;
- }
- };
-
- ret._child = function (i, data, blockParams, depths) {
- if (templateSpec.useBlockParams && !blockParams) {
- throw new _exception2['default']('must pass block params');
- }
- if (templateSpec.useDepths && !depths) {
- throw new _exception2['default']('must pass parent depths');
- }
-
- return wrapProgram(container, i, templateSpec[i], data, 0, blockParams, depths);
- };
- return ret;
-}
-
-function wrapProgram(container, i, fn, data, declaredBlockParams, blockParams, depths) {
- function prog(context) {
- var options = arguments.length <= 1 || arguments[1] === undefined ? {} : arguments[1];
-
- var currentDepths = depths;
- if (depths && context != depths[0]) {
- currentDepths = [context].concat(depths);
- }
-
- return fn(container, context, container.helpers, container.partials, options.data || data, blockParams && [options.blockParams].concat(blockParams), currentDepths);
- }
-
- prog = executeDecorators(fn, prog, container, depths, data, blockParams);
-
- prog.program = i;
- prog.depth = depths ? depths.length : 0;
- prog.blockParams = declaredBlockParams || 0;
- return prog;
-}
-
-function resolvePartial(partial, context, options) {
- if (!partial) {
- if (options.name === '@partial-block') {
- var data = options.data;
- while (data['partial-block'] === noop) {
- data = data._parent;
- }
- partial = data['partial-block'];
- data['partial-block'] = noop;
- } else {
- partial = options.partials[options.name];
- }
- } else if (!partial.call && !options.name) {
- // This is a dynamic partial that returned a string
- options.name = partial;
- partial = options.partials[partial];
- }
- return partial;
-}
-
-function invokePartial(partial, context, options) {
- options.partial = true;
- if (options.ids) {
- options.data.contextPath = options.ids[0] || options.data.contextPath;
- }
-
- var partialBlock = undefined;
- if (options.fn && options.fn !== noop) {
- options.data = _base.createFrame(options.data);
- partialBlock = options.data['partial-block'] = options.fn;
-
- if (partialBlock.partials) {
- options.partials = Utils.extend({}, options.partials, partialBlock.partials);
- }
- }
-
- if (partial === undefined && partialBlock) {
- partial = partialBlock;
- }
-
- if (partial === undefined) {
- throw new _exception2['default']('The partial ' + options.name + ' could not be found');
- } else if (partial instanceof Function) {
- return partial(context, options);
- }
-}
-
-function noop() {
- return '';
-}
-
-function initData(context, data) {
- if (!data || !('root' in data)) {
- data = data ? _base.createFrame(data) : {};
- data.root = context;
- }
- return data;
-}
-
-function executeDecorators(fn, prog, container, depths, data, blockParams) {
- if (fn.decorator) {
- var props = {};
- prog = fn.decorator(prog, props, container, depths && depths[0], data, blockParams, depths);
- Utils.extend(prog, props);
- }
- return prog;
-}
-
-
-},{"./base":7,"./exception":10,"./utils":23}],22:[function(require,module,exports){
-// Build out our basic SafeString type
-'use strict';
-
-exports.__esModule = true;
-function SafeString(string) {
- this.string = string;
-}
-
-SafeString.prototype.toString = SafeString.prototype.toHTML = function () {
- return '' + this.string;
-};
-
-exports['default'] = SafeString;
-module.exports = exports['default'];
-
-
-},{}],23:[function(require,module,exports){
-'use strict';
-
-exports.__esModule = true;
-exports.extend = extend;
-exports.indexOf = indexOf;
-exports.escapeExpression = escapeExpression;
-exports.isEmpty = isEmpty;
-exports.createFrame = createFrame;
-exports.blockParams = blockParams;
-exports.appendContextPath = appendContextPath;
-var escape = {
- '&': '&',
- '<': '<',
- '>': '>',
- '"': '"',
- "'": ''',
- '`': '`',
- '=': '='
-};
-
-var badChars = /[&<>"'`=]/g,
- possible = /[&<>"'`=]/;
-
-function escapeChar(chr) {
- return escape[chr];
-}
-
-function extend(obj /* , ...source */) {
- for (var i = 1; i < arguments.length; i++) {
- for (var key in arguments[i]) {
- if (Object.prototype.hasOwnProperty.call(arguments[i], key)) {
- obj[key] = arguments[i][key];
- }
- }
- }
-
- return obj;
-}
-
-var toString = Object.prototype.toString;
-
-exports.toString = toString;
-// Sourced from lodash
-// https://github.com/bestiejs/lodash/blob/master/LICENSE.txt
-/* eslint-disable func-style */
-var isFunction = function isFunction(value) {
- return typeof value === 'function';
-};
-// fallback for older versions of Chrome and Safari
-/* istanbul ignore next */
-if (isFunction(/x/)) {
- exports.isFunction = isFunction = function (value) {
- return typeof value === 'function' && toString.call(value) === '[object Function]';
- };
-}
-exports.isFunction = isFunction;
-
-/* eslint-enable func-style */
-
-/* istanbul ignore next */
-var isArray = Array.isArray || function (value) {
- return value && typeof value === 'object' ? toString.call(value) === '[object Array]' : false;
-};
-
-exports.isArray = isArray;
-// Older IE versions do not directly support indexOf so we must implement our own, sadly.
-
-function indexOf(array, value) {
- for (var i = 0, len = array.length; i < len; i++) {
- if (array[i] === value) {
- return i;
- }
- }
- return -1;
-}
-
-function escapeExpression(string) {
- if (typeof string !== 'string') {
- // don't escape SafeStrings, since they're already safe
- if (string && string.toHTML) {
- return string.toHTML();
- } else if (string == null) {
- return '';
- } else if (!string) {
- return string + '';
- }
-
- // Force a string conversion as this will be done by the append regardless and
- // the regex test will do this transparently behind the scenes, causing issues if
- // an object's to string has escaped characters in it.
- string = '' + string;
- }
-
- if (!possible.test(string)) {
- return string;
- }
- return string.replace(badChars, escapeChar);
-}
-
-function isEmpty(value) {
- if (!value && value !== 0) {
- return true;
- } else if (isArray(value) && value.length === 0) {
- return true;
- } else {
- return false;
- }
-}
-
-function createFrame(object) {
- var frame = extend({}, object);
- frame._parent = object;
- return frame;
-}
-
-function blockParams(params, ids) {
- params.path = ids;
- return params;
-}
-
-function appendContextPath(contextPath, id) {
- return (contextPath ? contextPath + '.' : '') + id;
-}
-
-
-},{}],24:[function(require,module,exports){
-// Create a simple path alias to allow browserify to resolve
-// the runtime on a supported path.
-module.exports = require('./dist/cjs/handlebars.runtime')['default'];
-
-},{"./dist/cjs/handlebars.runtime":6}],25:[function(require,module,exports){
-var $ = require('unopinionate').selector;
-
-var $document = $(document),
- bindings = {};
-
-var click = function(events) {
- click.bind.apply(click, arguments);
- return click;
-};
-
-/*** Configuration Options ***/
-click.distanceLimit = 10;
-click.timeLimit = 140;
-
-/*** Useful Properties ***/
-click.isTouch = ('ontouchstart' in window) ||
- window.DocumentTouch &&
- document instanceof DocumentTouch;
-
-/*** Cached Functions ***/
-var onTouchstart = function(e) {
- e.stopPropagation(); //Prevents multiple click events from happening
-
- click._doAnywheres(e);
-
- var $this = $(this),
- startTime = new Date().getTime(),
- startPos = click._getPos(e);
-
- $this.one('touchend', function(e) {
- e.preventDefault(); //Prevents click event from firing
-
- var time = new Date().getTime() - startTime,
- endPos = click._getPos(e),
- distance = Math.sqrt(
- Math.pow(endPos.x - startPos.x, 2) +
- Math.pow(endPos.y - startPos.y, 2)
- );
-
- if(time < click.timeLimit && distance < click.distanceLimit) {
- //Find the correct callback
- $.each(bindings, function(selector, callback) {
- if($this.is(selector)) {
- callback.apply(e.target, [e]);
- return false;
- }
- });
- }
- });
-};
-
-/*** API ***/
-click.bind = function(events) {
-
- //Argument Surgery
- if(!$.isPlainObject(events)) {
- newEvents = {};
- newEvents[arguments[0]] = arguments[1];
- events = newEvents;
- }
-
- $.each(events, function(selector, callback) {
-
- /*** Register Binding ***/
- if(typeof bindings[selector] != 'undefined') {
- click.unbind(selector); //Ensure no duplicates
- }
-
- bindings[selector] = callback;
-
- /*** Touch Support ***/
- if(click.isTouch) {
- $document.delegate(selector, 'touchstart', onTouchstart);
- }
-
- /*** Mouse Support ***/
- $document.delegate(selector, 'click', function(e) {
- e.stopPropagation(); //Prevents multiple click events from happening
- //click._doAnywheres(e); //Do anywheres first to be consistent with touch order
- callback.apply(this, [e]);
- });
- });
-
- return this;
-};
-
-click.unbind = function(selector) {
- $document
- .undelegate(selector, 'touchstart')
- .undelegate(selector, 'click');
-
- delete bindings[selector];
-
- return this;
-};
-
-click.unbindAll = function() {
- $.each(bindings, function(selector, callback) {
- $document
- .undelegate(selector, 'touchstart')
- .undelegate(selector, 'click');
- });
-
- bindings = {};
-
- return this;
-};
-
-click.trigger = function(selector, e) {
- e = e || $.Event('click');
-
- if(typeof bindings[selector] != 'undefined') {
- bindings[selector](e);
- }
- else {
- console.error("No click events bound for selector '"+selector+"'.");
- }
-
- return this;
-};
-
-click.anywhere = function(callback) {
- click._anywheres.push(callback);
- return this;
-};
-
-/*** Internal (but useful) Methods ***/
-click._getPos = function(e) {
- e = e.originalEvent;
-
- if(e.pageX || e.pageY) {
- return {
- x: e.pageX,
- y: e.pageY
- };
- }
- else if(e.changedTouches) {
- return {
- x: e.changedTouches[0].clientX,
- y: e.changedTouches[0].clientY
- };
- }
- else {
- return {
- x: e.clientX + document.body.scrollLeft + document.documentElement.scrollLeft,
- y: e.clientY + document.body.scrollTop + document.documentElement.scrollTop
- };
- }
-};
-
-click._anywheres = [];
-
-click._doAnywheres = function(e) {
- var i = click._anywheres.length;
- while(i--) {
- click._anywheres[i](e);
- }
-};
-
-$(document).bind('mousedown', click._doAnywheres);
-
-module.exports = click;
-
-
-},{"unopinionate":27}],26:[function(require,module,exports){
-(function(root) {
- var callbacks = [];
-
- var transitionComplete = function(callback) {
- if(callbacks.length === 0) {
- setEvent();
- }
-
- callbacks.push(callback);
- };
-
- function setEvent() {
- document.addEventListener(eventName(), function() {
- var i = callbacks.length;
- while(i--) {
- callbacks[i]();
- }
-
- callbacks = [];
- });
- }
-
- var _eventName;
-
- function eventName() {
- if(!_eventName) {
- // Sourced from: http://stackoverflow.com/questions/5023514/how-do-i-normalize-css3-transition-functions-across-browsers
- var el = document.createElement('fakeelement');
- transitions = {
- transition: 'transitionend',
- OTransition: 'oTransitionEnd',
- MozTransition: 'transitionend',
- WebkitTransition: 'webkitTransitionEnd'
- };
-
- for(var t in transitions) {
- if(el.style[t] !== undefined) {
- _eventName = transitions[t];
- }
- }
- }
-
- return _eventName;
- }
-
- /*** Export ***/
-
- // AMD
- if(typeof define === 'function' && define.amd) {
- define([], function() {
- return transitionComplete;
- });
- }
- // CommonJS
- else if(typeof exports !== 'undefined') {
- module.exports = transitionComplete;
- }
- // Browser Global
- else {
- root.transitionComplete = transitionComplete;
- }
-})(this);
-
-},{}],27:[function(require,module,exports){
-(function (global){
-(function(root) {
- var unopinionate = {
- selector: root.jQuery || root.Zepto || root.ender || root.$,
- template: root.Handlebars || root.Mustache
- };
-
- /*** Export ***/
-
- //AMD
- if(typeof define === 'function' && define.amd) {
- define([], function() {
- return unopinionate;
- });
- }
- //CommonJS
- else if(typeof module.exports !== 'undefined') {
- module.exports = unopinionate;
- }
- //Global
- else {
- root.unopinionate = unopinionate;
- }
-})(typeof window != 'undefined' ? window : global);
-
-}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
-},{}]},{},[4]);
diff --git a/lib/web/static/styles.css b/lib/web/static/styles.css
new file mode 100644
index 000000000..b05a6cb9f
--- /dev/null
+++ b/lib/web/static/styles.css
@@ -0,0 +1,511 @@
+/*! normalize.css v5.0.0 | MIT License | github.com/necolas/normalize.css */
+
+/**
+ * 1. Change the default font family in all browsers (opinionated).
+ * 2. Correct the line height in all browsers.
+ * 3. Prevent adjustments of font size after orientation changes in
+ * IE on Windows Phone and in iOS.
+ */
+
+/* Document
+ ========================================================================== */
+
+html {
+ font-family: sans-serif; /* 1 */
+ line-height: 1.15; /* 2 */
+ -ms-text-size-adjust: 100%; /* 3 */
+ -webkit-text-size-adjust: 100%; /* 3 */
+}
+
+/* Sections
+ ========================================================================== */
+
+/**
+ * Remove the margin in all browsers (opinionated).
+ */
+
+body {
+ margin: 0;
+}
+
+/**
+ * Add the correct display in IE 9-.
+ */
+
+article,
+aside,
+footer,
+header,
+nav,
+section {
+ display: block;
+}
+
+/**
+ * Correct the font size and margin on `h1` elements within `section` and
+ * `article` contexts in Chrome, Firefox, and Safari.
+ */
+
+h1 {
+ font-size: 2em;
+ margin: 0.67em 0;
+}
+
+/* Grouping content
+ ========================================================================== */
+
+/**
+ * Add the correct display in IE 9-.
+ * 1. Add the correct display in IE.
+ */
+
+figcaption,
+figure,
+main { /* 1 */
+ display: block;
+}
+
+/**
+ * Add the correct margin in IE 8.
+ */
+
+figure {
+ margin: 1em 40px;
+}
+
+/**
+ * 1. Add the correct box sizing in Firefox.
+ * 2. Show the overflow in Edge and IE.
+ */
+
+hr {
+ box-sizing: content-box; /* 1 */
+ height: 0; /* 1 */
+ overflow: visible; /* 2 */
+}
+
+/**
+ * 1. Correct the inheritance and scaling of font size in all browsers.
+ * 2. Correct the odd `em` font sizing in all browsers.
+ */
+
+pre {
+ font-family: monospace, monospace; /* 1 */
+ font-size: 1em; /* 2 */
+}
+
+/* Text-level semantics
+ ========================================================================== */
+
+/**
+ * 1. Remove the gray background on active links in IE 10.
+ * 2. Remove gaps in links underline in iOS 8+ and Safari 8+.
+ */
+
+a {
+ background-color: transparent; /* 1 */
+ -webkit-text-decoration-skip: objects; /* 2 */
+}
+
+/**
+ * Remove the outline on focused links when they are also active or hovered
+ * in all browsers (opinionated).
+ */
+
+a:active,
+a:hover {
+ outline-width: 0;
+}
+
+/**
+ * 1. Remove the bottom border in Firefox 39-.
+ * 2. Add the correct text decoration in Chrome, Edge, IE, Opera, and Safari.
+ */
+
+abbr[title] {
+ border-bottom: none; /* 1 */
+ text-decoration: underline; /* 2 */
+ text-decoration: underline dotted; /* 2 */
+}
+
+/**
+ * Prevent the duplicate application of `bolder` by the next rule in Safari 6.
+ */
+
+b,
+strong {
+ font-weight: inherit;
+}
+
+/**
+ * Add the correct font weight in Chrome, Edge, and Safari.
+ */
+
+b,
+strong {
+ font-weight: bolder;
+}
+
+/**
+ * 1. Correct the inheritance and scaling of font size in all browsers.
+ * 2. Correct the odd `em` font sizing in all browsers.
+ */
+
+code,
+kbd,
+samp {
+ font-family: monospace, monospace; /* 1 */
+ font-size: 1em; /* 2 */
+}
+
+/**
+ * Add the correct font style in Android 4.3-.
+ */
+
+dfn {
+ font-style: italic;
+}
+
+/**
+ * Add the correct background and color in IE 9-.
+ */
+
+mark {
+ background-color: #ff0;
+ color: #000;
+}
+
+/**
+ * Add the correct font size in all browsers.
+ */
+
+small {
+ font-size: 80%;
+}
+
+/**
+ * Prevent `sub` and `sup` elements from affecting the line height in
+ * all browsers.
+ */
+
+sub,
+sup {
+ font-size: 75%;
+ line-height: 0;
+ position: relative;
+ vertical-align: baseline;
+}
+
+sub {
+ bottom: -0.25em;
+}
+
+sup {
+ top: -0.5em;
+}
+
+/* Embedded content
+ ========================================================================== */
+
+/**
+ * Add the correct display in IE 9-.
+ */
+
+audio,
+video {
+ display: inline-block;
+}
+
+/**
+ * Add the correct display in iOS 4-7.
+ */
+
+audio:not([controls]) {
+ display: none;
+ height: 0;
+}
+
+/**
+ * Remove the border on images inside links in IE 10-.
+ */
+
+img {
+ border-style: none;
+}
+
+/**
+ * Hide the overflow in IE.
+ */
+
+svg:not(:root) {
+ overflow: hidden;
+}
+
+/* Forms
+ ========================================================================== */
+
+/**
+ * 1. Change the font styles in all browsers (opinionated).
+ * 2. Remove the margin in Firefox and Safari.
+ */
+
+button,
+input,
+optgroup,
+select,
+textarea {
+ font-family: sans-serif; /* 1 */
+ font-size: 100%; /* 1 */
+ line-height: 1.15; /* 1 */
+ margin: 0; /* 2 */
+}
+
+/**
+ * Show the overflow in IE.
+ * 1. Show the overflow in Edge.
+ */
+
+button,
+input { /* 1 */
+ overflow: visible;
+}
+
+/**
+ * Remove the inheritance of text transform in Edge, Firefox, and IE.
+ * 1. Remove the inheritance of text transform in Firefox.
+ */
+
+button,
+select { /* 1 */
+ text-transform: none;
+}
+
+/**
+ * 1. Prevent a WebKit bug where (2) destroys native `audio` and `video`
+ * controls in Android 4.
+ * 2. Correct the inability to style clickable types in iOS and Safari.
+ */
+
+button,
+html [type="button"], /* 1 */
+[type="reset"],
+[type="submit"] {
+ -webkit-appearance: button; /* 2 */
+}
+
+/**
+ * Remove the inner border and padding in Firefox.
+ */
+
+button::-moz-focus-inner,
+[type="button"]::-moz-focus-inner,
+[type="reset"]::-moz-focus-inner,
+[type="submit"]::-moz-focus-inner {
+ border-style: none;
+ padding: 0;
+}
+
+/**
+ * Restore the focus styles unset by the previous rule.
+ */
+
+button:-moz-focusring,
+[type="button"]:-moz-focusring,
+[type="reset"]:-moz-focusring,
+[type="submit"]:-moz-focusring {
+ outline: 1px dotted ButtonText;
+}
+
+/**
+ * Change the border, margin, and padding in all browsers (opinionated).
+ */
+
+fieldset {
+ border: 1px solid #c0c0c0;
+ margin: 0 2px;
+ padding: 0.35em 0.625em 0.75em;
+}
+
+/**
+ * 1. Correct the text wrapping in Edge and IE.
+ * 2. Correct the color inheritance from `fieldset` elements in IE.
+ * 3. Remove the padding so developers are not caught out when they zero out
+ * `fieldset` elements in all browsers.
+ */
+
+legend {
+ box-sizing: border-box; /* 1 */
+ color: inherit; /* 2 */
+ display: table; /* 1 */
+ max-width: 100%; /* 1 */
+ padding: 0; /* 3 */
+ white-space: normal; /* 1 */
+}
+
+/**
+ * 1. Add the correct display in IE 9-.
+ * 2. Add the correct vertical alignment in Chrome, Firefox, and Opera.
+ */
+
+progress {
+ display: inline-block; /* 1 */
+ vertical-align: baseline; /* 2 */
+}
+
+/**
+ * Remove the default vertical scrollbar in IE.
+ */
+
+textarea {
+ overflow: auto;
+}
+
+/**
+ * 1. Add the correct box sizing in IE 10-.
+ * 2. Remove the padding in IE 10-.
+ */
+
+[type="checkbox"],
+[type="radio"] {
+ box-sizing: border-box; /* 1 */
+ padding: 0; /* 2 */
+}
+
+/**
+ * Correct the cursor style of increment and decrement buttons in Chrome.
+ */
+
+[type="number"]::-webkit-inner-spin-button,
+[type="number"]::-webkit-outer-spin-button {
+ height: auto;
+}
+
+/**
+ * 1. Correct the odd appearance in Chrome and Safari.
+ * 2. Correct the outline style in Safari.
+ */
+
+[type="search"] {
+ -webkit-appearance: textfield; /* 1 */
+ outline-offset: -2px; /* 2 */
+}
+
+/**
+ * Remove the inner padding and cancel buttons in Chrome and Safari on macOS.
+ */
+
+[type="search"]::-webkit-search-cancel-button,
+[type="search"]::-webkit-search-decoration {
+ -webkit-appearance: none;
+}
+
+/**
+ * 1. Correct the inability to style clickable types in iOS and Safari.
+ * 2. Change font properties to `inherit` in Safari.
+ */
+
+::-webkit-file-upload-button {
+ -webkit-appearance: button; /* 1 */
+ font: inherit; /* 2 */
+}
+
+/* Interactive
+ ========================================================================== */
+
+/*
+ * Add the correct display in IE 9-.
+ * 1. Add the correct display in Edge, IE, and Firefox.
+ */
+
+details, /* 1 */
+menu {
+ display: block;
+}
+
+/*
+ * Add the correct display in all browsers.
+ */
+
+summary {
+ display: list-item;
+}
+
+/* Scripting
+ ========================================================================== */
+
+/**
+ * Add the correct display in IE 9-.
+ */
+
+canvas {
+ display: inline-block;
+}
+
+/**
+ * Add the correct display in IE.
+ */
+
+template {
+ display: none;
+}
+
+/* Hidden
+ ========================================================================== */
+
+/**
+ * Add the correct display in IE 10-.
+ */
+
+[hidden] {
+ display: none;
+}
+body {
+ font-family: "Roboto","Helvetica","Arial",sans-serif;
+}
+
+.body {
+ margin: 0;
+ padding: 0;
+}
+
+.list-container {
+ padding-top: 20px;
+}
+
+.wrapper {
+ padding-right: 15px;
+ padding-left: 15px;
+ margin-right: auto;
+ margin-left: auto;
+}
+
+@media (min-width: 768px) {
+ .wrapper {
+ width: 750px;
+ }
+}
+
+@media (max-width: 992px) {
+ .npm-logo {
+ width: 100px;
+ float: left;
+ }
+
+ .packages-header {
+ border-bottom: none;
+ }
+}
+
+@media (max-width: 768px) {
+ .navbar {
+ border-radius: 4px;
+ }
+ .wrapper {
+ width: 755px;
+ }
+ .list-container {
+ padding-top: 20px;
+ }
+}
+
+/*# sourceMappingURL=styles.css.map*/
\ No newline at end of file
diff --git a/lib/web/static/styles.css.map b/lib/web/static/styles.css.map
new file mode 100644
index 000000000..d8dd896ff
Binary files /dev/null and b/lib/web/static/styles.css.map differ
diff --git a/lib/web/ui/.eslintrc b/lib/web/ui/.eslintrc
deleted file mode 100644
index 13f1b4940..000000000
--- a/lib/web/ui/.eslintrc
+++ /dev/null
@@ -1,8 +0,0 @@
-
-env:
- node: true
- browser: true
-
-globals:
- jQuery: true
-
diff --git a/lib/web/ui/.eslintrc.yml b/lib/web/ui/.eslintrc.yml
new file mode 100644
index 000000000..00bc05b7b
--- /dev/null
+++ b/lib/web/ui/.eslintrc.yml
@@ -0,0 +1,23 @@
+# vim: syntax=yaml
+
+
+## rules for react components
+
+extends: ["eslint:recommended", "google", "plugin:react/recommended", "plugin:flowtype/recommended", "prettier", "prettier/react"]
+
+plugins: ["flowtype", "prettier"]
+
+parser: babel-eslint
+
+env:
+ node: true
+ browser: true
+ jest: true
+
+rules:
+ # jsdoc is mandatory
+ require-jsdoc: 0
+ # jsx rules
+ react/no-danger-with-children: 0
+ react/no-string-refs: 0
+
diff --git a/lib/web/ui/components/App.js b/lib/web/ui/components/App.js
new file mode 100644
index 000000000..d068b4e59
--- /dev/null
+++ b/lib/web/ui/components/App.js
@@ -0,0 +1,93 @@
+import React from 'react';
+import PropTypes from 'prop-types';
+import _ from 'lodash';
+import injectTapEventPlugin from 'react-tap-event-plugin';
+import request from 'superagent';
+import getMuiTheme from 'material-ui/styles/getMuiTheme';
+import MuiThemeProvider from 'material-ui/styles/MuiThemeProvider';
+import {green100, green500, green700} from 'material-ui/styles/colors';
+
+import Header from './Header/Header';
+import Search from './Search/Search';
+import List from './List/List';
+
+injectTapEventPlugin();
+
+if (process.env.BROWSER) {
+ require('./browser.css');
+}
+
+const muiTheme = getMuiTheme({
+ palette: {
+ primary1Color: green500,
+ primary2Color: green700,
+ primary3Color: green100,
+ },
+}, {
+ avatar: {
+ borderColor: null,
+ },
+ userAgent: false,
+});
+
+class App extends React.Component {
+
+ constructor(props) {
+ super();
+ this.state = {
+ packages: props.packages,
+ frontPackages: props.packages,
+ req: null,
+ };
+ this.updatePackages = this.updatePackages.bind(this);
+ }
+
+ updatePackages(keyword) {
+ if (keyword !== '') {
+ if (this.req) {
+ this.req.abort();
+ }
+ this.req = request.get(`/-/search/${keyword}`)
+ .end((err, res) => {
+ if(_.isNil(err) === false) {
+ this.setState({
+ packages: [],
+ });
+ } else {
+ this.setState({
+ packages: res.body,
+ });
+ }
+ });
+ } else {
+ if (this.req) {
+ this.req.abort();
+ }
+ this.setState({
+ packages: this.state.frontPackages,
+ });
+ }
+ }
+
+ render() {
+ return (
+
+
+
+
+ );
+ }
+}
+
+App.propTypes = {
+ packages: PropTypes.array.isRequired,
+ baseUrl: PropTypes.string.isRequired,
+ username: PropTypes.string,
+};
+
+export default App;
diff --git a/lib/web/ui/components/Header/Header.js b/lib/web/ui/components/Header/Header.js
new file mode 100644
index 000000000..e002073eb
--- /dev/null
+++ b/lib/web/ui/components/Header/Header.js
@@ -0,0 +1,144 @@
+import React from 'react';
+import PropTypes from 'prop-types';
+import RaisedButton from 'material-ui/RaisedButton';
+import TextField from 'material-ui/TextField';
+import IconPerson from 'material-ui/svg-icons/social/person';
+import Lock from 'material-ui/svg-icons/action/lock';
+import {List, ListItem} from 'material-ui/List';
+import Dialog from 'material-ui/Dialog';
+
+import {HeaderNav,
+ MenuGroup,
+ MenuItem,
+ Code,
+ CodeGroup,
+ LogoImage,
+ LogoItem, Navigation} from '../styled';
+
+let logo = '/header.png';
+if (process.env.BROWSER) {
+ logo = require('./header.png');
+}
+
+const styles = {
+ flex: {
+ display: 'flex',
+ },
+ red: {
+ backgroundColor: '#cc3d33',
+ },
+ fullWidth: {
+ width: '100%',
+ },
+ spaceItems: {
+ marginRight: 20,
+ },
+};
+
+class Header extends React.Component {
+ constructor() {
+ super();
+ this.state = {
+ open: false,
+ };
+ this.handleRequestClose = this.handleRequestClose.bind(this);
+ this.handleTouchTap = this.handleTouchTap.bind(this);
+ this.handleLogIn = this.handleLogIn.bind(this);
+ }
+
+ handleRequestClose() {
+ this.setState({
+ open: false,
+ });
+ }
+
+ handleTouchTap() {
+ this.setState({
+ open: true,
+ });
+ }
+
+ handleLogIn() {
+ this.refs.form.submit();
+ }
+
+ render() {
+ const standardActions = process.env.BROWSER ? [
+
,
+
,
+ ] : [];
+ return (
+
+
+
+
+
+
+
+
+
+
+
+ );
+ }
+}
+
+Header.propTypes = {
+ baseUrl: PropTypes.string.isRequired,
+};
+
+
+export default Header;
diff --git a/lib/web/ui/components/Header/header.png b/lib/web/ui/components/Header/header.png
new file mode 100644
index 000000000..c26b6c0ff
Binary files /dev/null and b/lib/web/ui/components/Header/header.png differ
diff --git a/lib/web/ui/components/Item/Item.js b/lib/web/ui/components/Item/Item.js
new file mode 100644
index 000000000..a1a13fe37
--- /dev/null
+++ b/lib/web/ui/components/Item/Item.js
@@ -0,0 +1,143 @@
+import React from 'react';
+import PropTypes from 'prop-types';
+import styled from 'styled-components';
+import request from 'superagent';
+import _ from 'lodash';
+import ArrowRight from 'material-ui/svg-icons/hardware/keyboard-arrow-right';
+import ArrowDown from 'material-ui/svg-icons/hardware/keyboard-arrow-down';
+
+import Readme from '../Readme/Readme';
+
+const ItemWrap = styled.li`
+ padding: 9px 10px;
+ border-bottom: 1px solid #E7E7E7;
+ list-style-type: none;
+ &:nth-child(even) {
+ background: #f3f3f3;
+ }
+`;
+
+const Description = styled.p`
+ margin: 0 0 0 18px;
+ font-size: 13px;
+`;
+
+const Group = styled.div`
+ display: flex;
+ align-items: center;
+ line-height: 10px;
+`;
+
+const GroupTitle = styled.div`
+ margin: 0 5px;
+ flex-basis: 85%;
+`;
+
+const Author = styled.div`
+ flex-basis: 15%;
+ text-align: center;
+ padding: 5px 0;
+`;
+
+const Small = styled.small`
+ color: #666;
+`;
+
+const Title = styled.h4`
+ margin: 0px;
+ margin-right: 10px;
+`;
+
+const Link = styled.a`
+ color: #cc3d33;
+ fill: currentColor;
+ text-decoration: none;
+`;
+
+class Item extends React.Component {
+
+ constructor() {
+ super();
+ this.state = {
+ open: false,
+ };
+ this.displayReadme = this.displayReadme.bind(this);
+ }
+
+ /**
+ *
+ * @param {*} event
+ */
+ displayReadme(event) {
+ event.preventDefault();
+ if (!this.state.open) {
+ this.req = request
+ .get(this._buildUrl())
+ .set('Content-Type', 'text/html; charset=utf8')
+ .end((err, res) => {
+ if (_.isNil(err) === false) {
+ this.setState({
+ open: true,
+ readme: 'No readme available',
+ });
+ } else {
+ this.setState({
+ open: true,
+ readme: res.text,
+ });
+ }
+ });
+ } else {
+ this.setState({
+ open: false,
+ });
+ }
+ }
+
+ _buildUrl() {
+ return `/-/readme/${encodeURIComponent(this.props.pkg.name)}/${encodeURIComponent(this.props.pkg.version)}`;
+ }
+
+ render() {
+ const author = this.props.pkg.author ? this.props.pkg.author.name : '';
+ return (
+
+
+
+
+
+
+
+ { this.state.open ? : }
+
+
+ {this.props.pkg.name}
+
+
+ { `v${this.props.pkg.version}` }
+
+
+
+
+
+
+ { `By: ${_.isNil(author) ? 'Not available' : author}` }
+
+
+
+
+
+ {this.props.pkg.description}
+
+ { this.state.open ? : '' }
+
+ );
+ }
+}
+
+Item.propTypes = {
+ pkg: PropTypes.object.isRequired,
+};
+
+
+export default Item;
diff --git a/lib/web/ui/components/List/List.js b/lib/web/ui/components/List/List.js
new file mode 100644
index 000000000..21216d8a3
--- /dev/null
+++ b/lib/web/ui/components/List/List.js
@@ -0,0 +1,29 @@
+import React from 'react';
+import PropTypes from 'prop-types';
+import styled from 'styled-components';
+
+import Item from '../Item/Item';
+
+const ListItems = styled.ul`
+ margin: 0px;
+ padding: 0px;
+`;
+
+class List extends React.Component {
+
+ render() {
+ return (
+
+ { this.props.packages.map((item)=> {
+ return (- );
+ })}
+
+ );
+ }
+}
+
+List.propTypes = {
+ packages: PropTypes.array.isRequired,
+};
+
+export default List;
diff --git a/lib/web/ui/components/Readme/Readme.js b/lib/web/ui/components/Readme/Readme.js
new file mode 100644
index 000000000..273b0a425
--- /dev/null
+++ b/lib/web/ui/components/Readme/Readme.js
@@ -0,0 +1,30 @@
+import React from 'react';
+import PropTypes from 'prop-types';
+import styled from 'styled-components';
+
+const ReadmeStyle = styled.div`
+ margin-top: 10px;
+ background: #ffffff;
+ padding: 10px 12px;
+ border-radius: 3px;
+ border: 1px solid #dadada;
+ color: #333;
+ overflow: hidden;
+ font-family: "Helvetica Neue", Helvetica, "Segoe UI", Arial, freesans, sans-serif;
+ font-size: 16px;
+ line-height: 1.6;
+ word-wrap: break-word;
+`;
+
+const Readme = (props) => {
+ return (
+
+ );
+};
+
+Readme.propTypes = {
+ html: PropTypes.string.isRequired,
+};
+
+export default Readme;
diff --git a/lib/web/ui/components/Search/Search.js b/lib/web/ui/components/Search/Search.js
new file mode 100644
index 000000000..039fc146f
--- /dev/null
+++ b/lib/web/ui/components/Search/Search.js
@@ -0,0 +1,57 @@
+import React from 'react';
+import PropTypes from 'prop-types';
+import styled from 'styled-components';
+import TextField from 'material-ui/TextField';
+
+const SearchContainer = styled.div`
+ margin-top: 20px;
+`;
+
+const styles = {
+ flex: {
+ display: 'flex',
+ },
+ fullWidth: {
+ width: '100%',
+ },
+};
+
+class Search extends React.Component {
+
+ constructor() {
+ super();
+ this.state = {
+ value: '',
+ };
+ this.handleChange = this.handleChange.bind(this);
+ }
+
+ handleChange(event) {
+ const keyword = event.target.value.trim();
+ this.setState({
+ value: keyword,
+ });
+ this.props.updatePackages(keyword);
+ }
+
+ render() {
+ return (
+
+
+
+ );
+ }
+}
+
+Search.propTypes = {
+ updatePackages: PropTypes.func.isRequired,
+};
+
+export default Search;
+
diff --git a/lib/web/ui/components/browser.css b/lib/web/ui/components/browser.css
new file mode 100644
index 000000000..7d03e041d
--- /dev/null
+++ b/lib/web/ui/components/browser.css
@@ -0,0 +1,50 @@
+@import '../../../../node_modules/normalize.css/normalize.css';
+
+body {
+ font-family: "Roboto","Helvetica","Arial",sans-serif;
+}
+
+.body {
+ margin: 0;
+ padding: 0;
+}
+
+.list-container {
+ padding-top: 20px;
+}
+
+.wrapper {
+ padding-right: 15px;
+ padding-left: 15px;
+ margin-right: auto;
+ margin-left: auto;
+}
+
+@media (min-width: 768px) {
+ .wrapper {
+ width: 750px;
+ }
+}
+
+@media (max-width: 992px) {
+ .npm-logo {
+ width: 100px;
+ float: left;
+ }
+
+ .packages-header {
+ border-bottom: none;
+ }
+}
+
+@media (max-width: 768px) {
+ .navbar {
+ border-radius: 4px;
+ }
+ .wrapper {
+ width: 755px;
+ }
+ .list-container {
+ padding-top: 20px;
+ }
+}
diff --git a/lib/web/ui/components/packages/Detail.js b/lib/web/ui/components/packages/Detail.js
new file mode 100644
index 000000000..419bd55f4
--- /dev/null
+++ b/lib/web/ui/components/packages/Detail.js
@@ -0,0 +1,13 @@
+import React from 'react';
+
+class Detail extends React.Component {
+ render() {
+ return (
+
+ );
+ }
+}
+
+export default Detail;
diff --git a/lib/web/ui/components/styled/index.js b/lib/web/ui/components/styled/index.js
new file mode 100644
index 000000000..38eaad850
--- /dev/null
+++ b/lib/web/ui/components/styled/index.js
@@ -0,0 +1,49 @@
+import styled from 'styled-components';
+
+const MenuItem = styled.li``;
+
+const HeaderNav = styled.header`
+ background: #cc3d33;
+ margin: 0px;
+`;
+
+const Navigation = styled.nav`
+ margin-bottom: 0px;
+ border-radius: 0px;
+ position: relative;
+ min-height: 50px;
+ font-size: 14px;
+ border: none;
+ color: white;
+`;
+
+const MenuGroup = styled.ul`
+ display: flex;
+ margin: 0;
+ align-items: center;
+ padding: 0;
+ list-style-type: none;
+`;
+
+const LogoItem = styled(MenuItem)`
+ width: 100px;
+ height: 50px;
+ padding: 5px;
+`;
+
+const Code = styled.code`
+ background: none;
+ color: white;
+`;
+
+const LogoImage = styled.img`
+ padding-top: 5px;
+ width: 85%;
+ height: 85%;
+`;
+
+const CodeGroup = styled.div`
+ line-height: 1.5em;
+`;
+
+export { Code, LogoImage, CodeGroup, MenuGroup, Navigation, HeaderNav, MenuItem, LogoItem }
diff --git a/lib/web/ui/index.hbs b/lib/web/ui/index.hbs
index 4c47d7bbf..8b0a95cf3 100644
--- a/lib/web/ui/index.hbs
+++ b/lib/web/ui/index.hbs
@@ -3,132 +3,15 @@
{{ name }}
-
-
+
-
-
-
-
-
-
-
- {{#each packages}}
- {{> entry}}
- {{/each}}
-
- {{#unless packages.length}}
-
- No Packages
- Use npm publish
-
- {{/unless}}
-
-
-
-
-
-
-
-
-
-
+
+
+