<commit_before>'use strict';

var Promise = require('bluebird');
var _       = require('lodash');
var Client  = require('./client');
var errors  = require('./errors');

function Producer(options) {
    this.options = _.defaultsDeep(options || {}, {
        requiredAcks: 1,
        timeout: 100
    });

    this.client = new Client(this.options);
}

module.exports = Producer;

/**
 * Initialize Producer
 *
 * @return {Promise}
 */
Producer.prototype.init = function () {
    return this.client.init();
};

Producer.prototype._prepareProduceRequest = function (data) {
    var self = this;

    return Promise.map(data, function (d) {
        return self.client.findLeader(d.topic, d.partition, true).then(function (leader) {
            d.leader = leader;
        });
    }, { concurrency: 10 })
    .then(function () {
        return _(data).groupBy('leader').mapValues(function (v) {
            return _(v)
                .groupBy('topic')
                .map(function (p, t) {
                    return {
                        topicName: t,
                        partitions: _(p).groupBy('partition').map(function (pv, pk) {
                            return {
                                partition: parseInt(pk),
                                messageSet: _.map(pv, function (mv) {
                                    return { offset: 0, message: mv.message };
                                })
                            };
                        }).value()
                    };
                })
                .value();
        }).value();
    });
};

/**
 * Send message or messages to Kafka
 *
 * @param  {Object|Array} data [{ topic, partition, message: {key, value, attributes} }]
 * @return {Promise}
 */
Producer.prototype.send = function (data) {
    var self = this, result = [];

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

    function _try(_data, attempt) {
        attempt = attempt || 0;

        return self._prepareProduceRequest(_data).then(function (requests) {
            return self.client.produceRequest(requests).then(function (response) {
                var toRetry = [];
                if (_.isEmpty(response)) { // if requiredAcks = 0
                    return response;
                }
                return Promise.map(response, function (p) {
                    if (p.error) {
                        if ((/UnknownTopicOrPartition|NotLeaderForPartition|LeaderNotAvailable/.test(p.error.code)
                                || p.error instanceof errors.NoKafkaConnectionError)
                            && attempt < 3) {
                            // self.client.debug('Received', p.error, 'for', p.topic + ':' + p.partition);
                            toRetry = toRetry.concat(_.filter(_data, { topic: p.topic, partition: p.partition }));
                        } else {
                            result.push(p);
                        }
                    } else {
                        result.push(p);
                    }
                })
                .then(function () {
                    if (toRetry.length) {
                        return Promise.delay(attempt * 1000).then(function () {
                            return self.client.updateMetadata().then(function () {
                                return _try(toRetry, ++attempt);
                            });
                        });
                    }
                }).return(result);
            });
        });
    }

    return _try(data);
};

/**
 * Close all connections
 *
 * @return {Promise}
 */
Producer.prototype.end = function () {
    var self = this;

    return self.client.end();
};
<commit_msg>Check topic/partitions fields<commit_after>'use strict';

var Promise = require('bluebird');
var _       = require('lodash');
var Client  = require('./client');
var errors  = require('./errors');

function Producer(options) {
    this.options = _.defaultsDeep(options || {}, {
        requiredAcks: 1,
        timeout: 100
    });

    this.client = new Client(this.options);
}

module.exports = Producer;

/**
 * Initialize Producer
 *
 * @return {Promise}
 */
Producer.prototype.init = function () {
    return this.client.init();
};

Producer.prototype._prepareProduceRequest = function (data) {
    var self = this;

    return Promise.map(data, function (d) {
        if (typeof d.topic !== 'string' || d.topic === '') {
            throw new Error('Missing or wrong topic field');
        }
        if (typeof d.partition !== 'number' || d.partition < 0) {
            throw new Error('Missing or wrong partition field');
        }
        return self.client.findLeader(d.topic, d.partition, true).then(function (leader) {
            d.leader = leader;
        });
    }, { concurrency: 10 })
    .then(function () {
        return _(data).groupBy('leader').mapValues(function (v) {
            return _(v)
                .groupBy('topic')
                .map(function (p, t) {
                    return {
                        topicName: t,
                        partitions: _(p).groupBy('partition').map(function (pv, pk) {
                            return {
                                partition: parseInt(pk),
                                messageSet: _.map(pv, function (mv) {
                                    return { offset: 0, message: mv.message };
                                })
                            };
                        }).value()
                    };
                })
                .value();
        }).value();
    });
};

/**
 * Send message or messages to Kafka
 *
 * @param  {Object|Array} data [{ topic, partition, message: {key, value, attributes} }]
 * @return {Promise}
 */
Producer.prototype.send = function (data) {
    var self = this, result = [];

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

    function _try(_data, attempt) {
        attempt = attempt || 0;

        return self._prepareProduceRequest(_data).then(function (requests) {
            return self.client.produceRequest(requests).then(function (response) {
                var toRetry = [];
                if (_.isEmpty(response)) { // if requiredAcks = 0
                    return response;
                }
                return Promise.map(response, function (p) {
                    if (p.error) {
                        if ((/UnknownTopicOrPartition|NotLeaderForPartition|LeaderNotAvailable/.test(p.error.code)
                                || p.error instanceof errors.NoKafkaConnectionError)
                            && attempt < 3) {
                            // self.client.debug('Received', p.error, 'for', p.topic + ':' + p.partition);
                            toRetry = toRetry.concat(_.filter(_data, { topic: p.topic, partition: p.partition }));
                        } else {
                            result.push(p);
                        }
                    } else {
                        result.push(p);
                    }
                })
                .then(function () {
                    if (toRetry.length) {
                        return Promise.delay(attempt * 1000).then(function () {
                            return self.client.updateMetadata().then(function () {
                                return _try(toRetry, ++attempt);
                            });
                        });
                    }
                }).return(result);
            });
        });
    }

    return _try(data);
};

/**
 * Close all connections
 *
 * @return {Promise}
 */
Producer.prototype.end = function () {
    var self = this;

    return self.client.end();
};
<|endoftext|>


<commit_before>'use babel'

/* @flow */

import {CompositeDisposable, Emitter} from 'atom'
import type {Disposable} from 'atom'

export class Projects {
  paths: Set<string>;
  emitter: Emitter;
  subscriptions: CompositeDisposable;

  constructor() {
    this.paths = new Set()
    this.emitter = new Emitter()
    this.subscriptions = new CompositeDisposable()

    this.subscriptions.add(this.emitter)
  }
  activate() {
    this.subscriptions.add(atom.project.onDidChangePaths(() => this.detectChanges()))
    this.detectChanges()
  }
  detectChanges() {
    const paths = new Set(atom.project.getPaths())
    for (const path of paths) {
      if (!this.paths.has(path)) {
        this.paths.add(path)
        this.emitter.emit('did-add-path', path)
      }
    }
    for (const path of this.paths) {
      if (!paths.has(path)) {
        this.paths.delete(path)
        this.emitter.emit('did-remove-path', path)
      }
    }
  }
  getPaths(): Set<string> {
    return this.paths
  }
  onDidAddPath(callback: ((path: string) => void)): Disposable {
    return this.emitter.on('did-add-path', callback)
  }
  onDidRemovePath(callback: ((path: string) => void)): Disposable {
    return this.emitter.on('did-remove-path', callback)
  }
  dispose() {
    this.subscriptions.dispose()
  }
}
<commit_msg>:shirt: Properly clear paths on dispose in projects<commit_after>'use babel'

/* @flow */

import {CompositeDisposable, Emitter} from 'atom'
import type {Disposable} from 'atom'

export class Projects {
  paths: Set<string>;
  emitter: Emitter;
  subscriptions: CompositeDisposable;

  constructor() {
    this.paths = new Set()
    this.emitter = new Emitter()
    this.subscriptions = new CompositeDisposable()

    this.subscriptions.add(this.emitter)
  }
  activate() {
    this.subscriptions.add(atom.project.onDidChangePaths(() => this.detectChanges()))
    this.detectChanges()
  }
  detectChanges() {
    const paths = new Set(atom.project.getPaths())
    for (const path of paths) {
      if (!this.paths.has(path)) {
        this.paths.add(path)
        this.emitter.emit('did-add-path', path)
      }
    }
    for (const path of this.paths) {
      if (!paths.has(path)) {
        this.paths.delete(path)
        this.emitter.emit('did-remove-path', path)
      }
    }
  }
  getPaths(): Set<string> {
    return this.paths
  }
  onDidAddPath(callback: ((path: string) => void)): Disposable {
    return this.emitter.on('did-add-path', callback)
  }
  onDidRemovePath(callback: ((path: string) => void)): Disposable {
    return this.emitter.on('did-remove-path', callback)
  }
  dispose() {
    this.paths.clear()
    this.subscriptions.dispose()
  }
}
<|endoftext|>


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

define(function(require, exports, module) {

'use strict';

/**
 * The chromeWindow as as required by Highlighter, so it knows where to
 * create temporary highlight nodes.
 */
exports.chromeWindow = undefined;

/**
 * See docs in lib/util/host.js:flashNodes
 */
exports.flashNodes = function(nodes, match) {
  // Commented out until Bug 653545 is completed
  /*
  if (exports.chromeWindow == null) {
    console.log('flashNodes has no chromeWindow. Skipping flash');
    return;
  }

  var imports = {};
  Components.utils.import("resource:///modules/highlighter.jsm", imports);

  imports.Highlighter.flashNodes(nodes, exports.chromeWindow, match);
  */
};

/**
 * See docs in lib/util/host.js:exec
 */
exports.exec = function(execSpec) {
  throw new Error('Not supported');
};

});
<commit_msg>nodeinout-796921: Update Highlighter for Firefox<commit_after>/*
 * Copyright 2012, Mozilla Foundation and contributors
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

define(function(require, exports, module) {

'use strict';

var util = require('util/util');

/**
 * The chromeWindow as as required by Highlighter, so it knows where to
 * create temporary highlight nodes.
 */
exports.chromeWindow = undefined;

function Highlighter(document) {
  this._document = document;
  this._nodes = util.createEmptyNodeList(this._document);
}

Object.defineProperty(Highlighter.prototype, 'nodelist', {
  set: function(nodes) {
    Array.prototype.forEach.call(this._nodes, this._unhighlightNode, this);
    this._nodes = (nodes == null) ?
        util.createEmptyNodeList(this._document) :
        nodes;
    Array.prototype.forEach.call(this._nodes, this._highlightNode, this);
  },
  get: function() {
    return this._nodes;
  },
  enumerable: true
});

Highlighter.prototype.destroy = function() {
  this.nodelist = null;
};

Highlighter.prototype._highlightNode = function(node) {
  // Enable when the highlighter rewrite is done
};

Highlighter.prototype._unhighlightNode = function(node) {
  // Enable when the highlighter rewrite is done
};

exports.Highlighter = Highlighter;

/**
 * See docs in lib/util/host.js:exec
 */
exports.exec = function(execSpec) {
  throw new Error('Not supported');
};

});
<|endoftext|>


<commit_before>$(document).ready(function() {

    // Page load animation panel
    var $openPanel = $('header #collapseOne');
    if ($openPanel.length) {
        $(window).load(function() {
            setTimeout(function() {
                $openPanel.collapse('show');
            }, 1000);
        });
    }

    // Button close panel
    $('#home-accordion .close').on('click', function() {
        $('#collapseOne').collapse('hide');
        applyLayout();
        window.setTimeout(stopLayout, 5000);
    });

    $('#bionavist-top-bar').on('hidden.bs.collapse', function () {
        applyLayout();
        window.setTimeout(stopLayout, 5000);
    });

});<commit_msg>remove automatic forceatlas because we have clustering<commit_after>$(document).ready(function() {

    // Page load animation panel
    var $openPanel = $('header #collapseOne');
    if ($openPanel.length) {
        $(window).load(function() {
            setTimeout(function() {
                $openPanel.collapse('show');
            }, 1000);
        });
    }

    // Button close panel
    $('#home-accordion .close').on('click', function() {
        $('#collapseOne').collapse('hide');
        //applyLayout();
        //window.setTimeout(stopLayout, 5000);
    });

    $('#bionavist-top-bar').on('hidden.bs.collapse', function () {
        //applyLayout();
        //window.setTimeout(stopLayout, 5000);
    });

});<|endoftext|>


<commit_before>/*
 * Copyright (c) 2014, Groupon, Inc.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * Redistributions of source code must retain the above copyright notice,
 * this list of conditions and the following disclaimer.
 *
 * Redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the distribution.
 *
 * Neither the name of GROUPON nor the names of its contributors may be
 * used to endorse or promote products derived from this software without
 * specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
 * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
'use strict';
/* global URLSearchParams */
var Url = require('url');

var Bluebird = require('bluebird');
var assign = require('lodash/assign');
var noop = require('lodash/noop');
var partial = require('lodash/partial');
var qsParser = require('qs');

var StatusCodeError = require('./errors').StatusCodeError;
var urlUtils = require('./url');

var applyBaseUrl = urlUtils.applyBaseUrl;
var replacePathParams = urlUtils.replacePathParams;

var DEFAULT_TIMEOUT = 10 * 1000;

if (typeof fetch !== 'function') {
  throw new Error('Requires native fetch or polyfill');
}

function _callJSON(res) {
  return res.json();
}

function _callText(res) {
  return res.text();
}

var reqProperties = {
  json: {
    value: function json() {
      return this.then(_callJSON);
    },
  },

  text: {
    value: function text() {
      return this.then(_callText);
    },
  },
};

// Blob or BufferSource or FormData or URLSearchParams or USVString
function isValidBody(body) {
  return body === undefined ||
    typeof body === 'string' ||
    (typeof FormData !== 'undefined' && body instanceof FormData) ||
    (typeof URLSearchParams !== 'undefined' && body instanceof URLSearchParams);
}

function validateBody(body) {
  if (!isValidBody) {
    throw new TypeError('Invalid body ' + typeof body);
  }
  return body;
}

function generateSearch(queryString, qs) {
  var query = assign(qsParser.parse(queryString), qs || {});
  var filtered = {};
  var queryKeys = Object.keys(query)
    .filter(function ensureSet(key) {
      var value = query[key];
      var isSet = value !== null && value !== undefined;
      if (isSet) {
        filtered[key] = value;
      }
      return isSet;
    });

  if (queryKeys.length === 0) return '';
  return '?' + qsParser.stringify(filtered);
}

function filterHeaders(headers) {
  var filtered = {};
  Object.keys(headers).forEach(function ensureSet(name) {
    var value = headers[name];
    if (value !== null && value !== undefined) {
      filtered[name] = headers[name];
    }
  });
  return filtered;
}

function defaultStatusCode(value, defaultValue) {
  // Disable this check, e.g. minStatusCode = false => don't check for it.
  if (value === false) return false;

  if (value >= 0) {
    if (typeof value !== 'number') {
      throw new TypeError(
        'Invalid status code ' + JSON.stringify(value) + ', not a number');
    }
    return value;
  }
  return defaultValue;
}

function parseErrorBody(rawBody) {
  var source = '' + rawBody;
  try {
    return JSON.parse(source);
  } catch (anyError) {
    return source;
  }
}

function verifyAndExtendResponse(url, options, response) {
  var min = defaultStatusCode(options.minStatusCode, 200);
  var max = defaultStatusCode(options.maxStatusCode, 299);

  function isAcceptableStatus(code) {
    return (min === false || code >= min) &&
           (max === false || code <= max);
  }

  var originalHeaders = response.headers;
  var cachedHeaders;
  function getCachedHeaders() {
    if (!cachedHeaders) {
      cachedHeaders = {};
      originalHeaders.forEach(function addHeader(value, name) {
        if (name) {
          cachedHeaders[name] = value;
        }
      });
    }
    return cachedHeaders;
  }

  Object.defineProperties(response, {
    statusCode: { value: response.status },
    headers: { get: getCachedHeaders },
    url: { value: url },
  });

  function generateStatusCodeError(code) {
    var error = StatusCodeError.create(
      code, min, max, response.headers, options.method || 'GET', url);

    function rejectWithBody(body) {
      error.body = body;
      throw error;
    }

    return response.text()
      .then(parseErrorBody)
      .then(null, noop)
      .then(rejectWithBody);
  }

  if (!isAcceptableStatus(response.status)) {
    return generateStatusCodeError(response.status);
  }

  return response;
}

function defaultTimeout(value, defaultValue) {
  if (value >= 0) {
    if (typeof value !== 'number') {
      throw new TypeError(
        'Invalid timeout ' + JSON.stringify(value) + ', not a number');
    }
    return value;
  }
  return defaultValue;
}

function _fetch(url, options) {
  if (typeof url !== 'string') {
    throw new TypeError('url has to be a string');
  }

  options = options || {};
  var urlObj = Url.parse(url);
  if (options.baseUrl && typeof options.baseUrl === 'string') {
    urlObj = applyBaseUrl(urlObj, options.baseUrl);
  }

  var json = options.json;
  var form = options.form;
  var body = validateBody(options.body);

  var defaultHeaders = {};

  if (json !== undefined && json !== null) {
    defaultHeaders['Content-Type'] = 'application/json;charset=UTF-8';
    body = JSON.stringify(json);
  } else if (form !== undefined && form !== null) {
    if (typeof form !== 'object') {
      throw new TypeError(
        'Invalid form body (' + typeof form + ', expected object)');
    }
    defaultHeaders['Content-Type'] = 'application/x-www-form-urlencoded;charset=UTF-8';
    body = qsParser.stringify(form);
  }

  var auth = options.auth;
  if (typeof auth === 'string') {
    defaultHeaders.Authorization = 'Basic ' + btoa(auth);
  } else if (auth !== null && typeof auth === 'object') {
    defaultHeaders.Authorization = 'Basic ' + btoa(auth.username + ':' + auth.password);
  }

  var timeout = defaultTimeout(options.timeout, DEFAULT_TIMEOUT);

  var method = options.method || 'GET';
  var nativeOptions = {
    // All official fetch options:
    method: method,
    headers: filterHeaders(assign(defaultHeaders, options.headers)),
    body: body,
    redirect: options.redirect,
    // Some things we might want to expose for instrumentation to pick up:
    serviceName: options.serviceName,
    endpointName: options.endpointName,
    methodName: options.methodName || method.toLowerCase(),
    pathParams: options.pathParams,
  };
  var patchedPathname = replacePathParams(urlObj.pathname, options.pathParams);
  var patchedSearch = generateSearch(urlObj.query, options.qs);
  var patchedUrl = {
    protocol: urlObj.protocol,
    hostname: urlObj.hostname,
    port: urlObj.port,
    pathname: patchedPathname,
    search: patchedSearch,
    path: patchedPathname + patchedSearch,
  };
  var nativeUrl = Url.format(patchedUrl);
  var result = new Bluebird(function withResponseTimeout(resolve, reject) {
    function onTimedOut() {
      var error = new Error('Fetching from ' + urlObj.hostname + ' timed out');
      error.code = 'ETIMEDOUT';
      error.timeout = options.timeout;
      reject(error);
    }
    var timeoutHandle = setTimeout(onTimedOut, timeout);
    function killTimeout(response) {
      clearTimeout(timeoutHandle);
      return response;
    }
    Bluebird.resolve(fetch(nativeUrl, nativeOptions))
      .then(killTimeout)
      .then(partial(verifyAndExtendResponse, nativeUrl, options))
      .then(resolve, reject);
  });
  return Object.defineProperties(result, reqProperties);
}

module.exports = _fetch;
<commit_msg>fix: Support isomorphic-fetch<commit_after>/*
 * Copyright (c) 2014, Groupon, Inc.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * Redistributions of source code must retain the above copyright notice,
 * this list of conditions and the following disclaimer.
 *
 * Redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the distribution.
 *
 * Neither the name of GROUPON nor the names of its contributors may be
 * used to endorse or promote products derived from this software without
 * specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
 * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
'use strict';
/* global URLSearchParams */
var Url = require('url');

var Bluebird = require('bluebird');
var assign = require('lodash/assign');
var noop = require('lodash/noop');
var partial = require('lodash/partial');
var qsParser = require('qs');

var StatusCodeError = require('./errors').StatusCodeError;
var urlUtils = require('./url');

var applyBaseUrl = urlUtils.applyBaseUrl;
var replacePathParams = urlUtils.replacePathParams;

var DEFAULT_TIMEOUT = 10 * 1000;

if (typeof fetch !== 'function') {
  throw new Error('Requires native fetch or polyfill');
}

function _callJSON(res) {
  return res.json();
}

function _callText(res) {
  return res.text();
}

var reqProperties = {
  json: {
    value: function json() {
      return this.then(_callJSON);
    },
  },

  text: {
    value: function text() {
      return this.then(_callText);
    },
  },
};

// Blob or BufferSource or FormData or URLSearchParams or USVString
function isValidBody(body) {
  return body === undefined ||
    typeof body === 'string' ||
    (typeof FormData !== 'undefined' && body instanceof FormData) ||
    (typeof URLSearchParams !== 'undefined' && body instanceof URLSearchParams);
}

function validateBody(body) {
  if (!isValidBody) {
    throw new TypeError('Invalid body ' + typeof body);
  }
  return body;
}

function generateSearch(queryString, qs) {
  var query = assign(qsParser.parse(queryString), qs || {});
  var filtered = {};
  var queryKeys = Object.keys(query)
    .filter(function ensureSet(key) {
      var value = query[key];
      var isSet = value !== null && value !== undefined;
      if (isSet) {
        filtered[key] = value;
      }
      return isSet;
    });

  if (queryKeys.length === 0) return '';
  return '?' + qsParser.stringify(filtered);
}

function filterHeaders(headers) {
  var filtered = {};
  Object.keys(headers).forEach(function ensureSet(name) {
    var value = headers[name];
    if (value !== null && value !== undefined) {
      filtered[name] = headers[name];
    }
  });
  return filtered;
}

function defaultStatusCode(value, defaultValue) {
  // Disable this check, e.g. minStatusCode = false => don't check for it.
  if (value === false) return false;

  if (value >= 0) {
    if (typeof value !== 'number') {
      throw new TypeError(
        'Invalid status code ' + JSON.stringify(value) + ', not a number');
    }
    return value;
  }
  return defaultValue;
}

function parseErrorBody(rawBody) {
  var source = '' + rawBody;
  try {
    return JSON.parse(source);
  } catch (anyError) {
    return source;
  }
}

function verifyAndExtendResponse(url, options, response) {
  var min = defaultStatusCode(options.minStatusCode, 200);
  var max = defaultStatusCode(options.maxStatusCode, 299);

  function isAcceptableStatus(code) {
    return (min === false || code >= min) &&
           (max === false || code <= max);
  }

  var originalHeaders = response.headers;
  var cachedHeaders;
  function getCachedHeaders() {
    if (!cachedHeaders) {
      cachedHeaders = Object.create(originalHeaders);
      originalHeaders.forEach(function addHeader(value, name) {
        if (name) {
          cachedHeaders[name] = value;
        }
      });
    }
    return cachedHeaders;
  }

  Object.defineProperties(response, {
    statusCode: { value: response.status },
    headers: { get: getCachedHeaders },
    url: { value: url },
  });

  function generateStatusCodeError(code) {
    var error = StatusCodeError.create(
      code, min, max, response.headers, options.method || 'GET', url);

    function rejectWithBody(body) {
      error.body = body;
      throw error;
    }

    return response.text()
      .then(parseErrorBody)
      .then(null, noop)
      .then(rejectWithBody);
  }

  if (!isAcceptableStatus(response.status)) {
    return generateStatusCodeError(response.status);
  }

  return response;
}

function defaultTimeout(value, defaultValue) {
  if (value >= 0) {
    if (typeof value !== 'number') {
      throw new TypeError(
        'Invalid timeout ' + JSON.stringify(value) + ', not a number');
    }
    return value;
  }
  return defaultValue;
}

function _fetch(url, options) {
  if (typeof url !== 'string') {
    throw new TypeError('url has to be a string');
  }

  options = options || {};
  var urlObj = Url.parse(url);
  if (options.baseUrl && typeof options.baseUrl === 'string') {
    urlObj = applyBaseUrl(urlObj, options.baseUrl);
  }

  var json = options.json;
  var form = options.form;
  var body = validateBody(options.body);

  var defaultHeaders = {};

  if (json !== undefined && json !== null) {
    defaultHeaders['Content-Type'] = 'application/json;charset=UTF-8';
    body = JSON.stringify(json);
  } else if (form !== undefined && form !== null) {
    if (typeof form !== 'object') {
      throw new TypeError(
        'Invalid form body (' + typeof form + ', expected object)');
    }
    defaultHeaders['Content-Type'] = 'application/x-www-form-urlencoded;charset=UTF-8';
    body = qsParser.stringify(form);
  }

  var auth = options.auth;
  if (typeof auth === 'string') {
    defaultHeaders.Authorization = 'Basic ' + btoa(auth);
  } else if (auth !== null && typeof auth === 'object') {
    defaultHeaders.Authorization = 'Basic ' + btoa(auth.username + ':' + auth.password);
  }

  var timeout = defaultTimeout(options.timeout, DEFAULT_TIMEOUT);

  var method = options.method || 'GET';
  var nativeOptions = {
    // All official fetch options:
    method: method,
    headers: filterHeaders(assign(defaultHeaders, options.headers)),
    body: body,
    redirect: options.redirect,
    // Some things we might want to expose for instrumentation to pick up:
    serviceName: options.serviceName,
    endpointName: options.endpointName,
    methodName: options.methodName || method.toLowerCase(),
    pathParams: options.pathParams,
  };
  var patchedPathname = replacePathParams(urlObj.pathname, options.pathParams);
  var patchedSearch = generateSearch(urlObj.query, options.qs);
  var patchedUrl = {
    protocol: urlObj.protocol,
    hostname: urlObj.hostname,
    port: urlObj.port,
    pathname: patchedPathname,
    search: patchedSearch,
    path: patchedPathname + patchedSearch,
  };
  var nativeUrl = Url.format(patchedUrl);
  var result = new Bluebird(function withResponseTimeout(resolve, reject) {
    function onTimedOut() {
      var error = new Error('Fetching from ' + urlObj.hostname + ' timed out');
      error.code = 'ETIMEDOUT';
      error.timeout = options.timeout;
      reject(error);
    }
    var timeoutHandle = setTimeout(onTimedOut, timeout);
    function killTimeout(response) {
      clearTimeout(timeoutHandle);
      return response;
    }
    Bluebird.resolve(fetch(nativeUrl, nativeOptions))
      .then(killTimeout)
      .then(partial(verifyAndExtendResponse, nativeUrl, options))
      .then(resolve, reject);
  });
  return Object.defineProperties(result, reqProperties);
}

module.exports = _fetch;
<|endoftext|>


<commit_before>/**
 * Created by jpi on 05.03.14.
 */

/*
 * jQuery stuff
 * Using jQuery 1.11.0
 */

var footerHeight;
var headerHeight;
var footerSwipeHeight;
var containerHeight;
var up = false;

/**
 * resizes the main element to the remaining browser height
 */
function resizeContainer() {
	headerHeight = $("header[role='banner']").css("height");
    var footer = $("section#article-section");
    var main = $("main");
    footerHeight = footer.css("height");
	main.css({
        paddingTop: headerHeight,
        marginTop: "-" + headerHeight,
        paddingBottom: "0px",
        marginBottom: "0px"
    });
    footer.css({
        height: "0"
    });
    containerHeight = main.height();
}

/**
 * Initializes the swipe ability on the footer.
 */
function initializeSwiping() {
    var footer = $("section#article-section");
    var footerHeading = $("div.article-heading");
    var container = $("main");

    var swipeThreshold = containerHeight * 0.3;
    var maxPadding = containerHeight + "px";

    footerHeading.swipe({
        swipeStatus: function(event, phase, direction, distance) {
            if (phase === "start") {
                var cssHeight = footer.css("height");
                footerSwipeHeight = parseInt(cssHeight.substring(0, cssHeight.length - 2));
            }
            // handles the current swipe
            if ((up && direction === "down") || (!up && direction === "up")) {
                if (phase === "cancel") {
                    var newPadding = (direction === "up" ? footerHeight : maxPadding);
                    var footerPadding = (direction === "up" ? "0.8rem 0.8rem 0 0.8rem" : "0.8rem");
                    footer.css("padding", footerPadding);
                    footer.transition({height: newPadding}, 200, "ease");
                    container.transition({paddingBottom: newPadding, marginBottom: "-" + newPadding}, 200, "ease");
                    footer.css("padding", "0.8rem 0.8rem 0 0.8rem");
                } else if (phase === "end") {
                    var newPadding = (direction === "up" ? maxPadding : footerHeight);
                    var footerPadding = (direction === "up" ? "0.8rem" : "0.8rem 0.8rem 0 0.8rem");
                    footer.css("padding", footerPadding);
                    footer.transition({height: newPadding}, 200, "ease");
                    container.transition({paddingBottom: newPadding, marginBottom: "-" + newPadding}, 200, "ease");
                    $("div.entry-list ul li").css("overflow-y", direction === "up" ? "auto" : "hidden");
                    up = (direction === "up" ? true : false);
                } else {
                    var newPadding = footerSwipeHeight + (direction === "up" ? distance : -distance);
                    container.css({
                        paddingBottom: newPadding + "px",
                        marginBottom: "-" + newPadding + "px"
                    });
                    footer.css({
                        height: newPadding + "px"
                    })
                }
            }
        },
        checkThresholds: true,
        maxTimeThreshold: 300,
        threshold: swipeThreshold
    });

    var slideWidth = $("div.entry-list ul li:first").width();
    var swipeLeftRightThreshold = slideWidth * 0.3;
    var slideList = $("section#article-section div.entry-list");

    $("section#article-section div.entry-list ul li").swipe({
       swipeStatus: function(event, phase, direction, distance) {
           if (direction === "left" || direction ==="right") {
               var unslider = slideList.data("unslider");
               var currentSlide = unslider.current;
               if (phase === "end") {
                   if ((direction === "left" && (currentSlide === unslider.items.length - 1)) || (direction === "right" && (currentSlide === 0))) {
                       return false;
                   } else {
                       unslider.move(currentSlide + (direction === "left" ? 1 : -1));
                   }
               } else if (phase === "cancel") {
                        unslider.move(currentSlide);
               } else {
                   if ((direction === "left" && (currentSlide === unslider.items.length - 1)) || (direction === "right" && (currentSlide === 0))) {
                       return false;
                   } else {
                       var percentMoved = (distance / slideWidth) * 100;
                       var newPercentage = currentSlide * 100 + (direction === "left" ? percentMoved : -percentMoved);
                       var newLeft = "-" + newPercentage + "%";
                       $("section#article-section div.entry-list ul").css("left", newLeft);
                   }
               }
           }
       },
       checkThresholds: true,
       maxTimeThreshold: 300,
       threshold: swipeLeftRightThreshold,
       allowPageScroll: "vertical"
    });
}

/**
 * $(document).ready
 *
 * initialize jQuery hooks
 */
$(function() {
	resizeContainer();
    initializeSwiping();
    $("img#load-more").hide();
});<commit_msg>Refactor sliding<commit_after>/**
 * Created by jpi on 05.03.14.
 */

/*
 * jQuery stuff
 * Using jQuery 1.11.0
 */

var footerHeight;
var headerHeight;
var footerSwipeHeight;
var containerHeight;
var up = false;

/**
 * resizes the main element to the remaining browser height
 */
function resizeContainer() {
	headerHeight = $("header[role='banner']").css("height");
    var footer = $("section#article-section");
    var main = $("main");
    footerHeight = footer.css("height");
	main.css({
        paddingTop: headerHeight,
        marginTop: "-" + headerHeight,
        paddingBottom: "0px",
        marginBottom: "0px"
    });
    footer.css({
        height: "0"
    });
    containerHeight = main.height();
}

/**
 * Slide an element to a given size
 * @param slidingElement
 * @param containerElement
 * @param newSize
 * @param [callback]
 */
function slideElement(slidingElement, containerElement, newSize, callback) {
    slidingElement.transition({height: newSize}, 200, "ease");
    containerElement.transition({paddingBottom: newSize, marginBottom: "-" + newSize}, 200, "ease", callback);
}

/**
 * Initializes the swipe ability on the footer.
 */
function initializeFooterSwiping() {
    var footer = $("section#article-section");
    var footerHeading = $("div.article-heading");
    var container = $("main");

    var swipeThreshold = containerHeight * 0.3;
    var maxPadding = containerHeight + "px";

    footerHeading.swipe({
        swipeStatus: function(event, phase, direction, distance) {
            if (phase === "start") {
                footerSwipeHeight = footer.height();
            }
            // handles the current swipe
            if ((up && direction === "down") || (!up && direction === "up")) {
                if (phase === "cancel") {
                    var newPadding = (direction === "up" ? footerHeight : maxPadding);
                    var footerPadding = (direction === "up" ? "0.8rem 0.8rem 0 0.8rem" : "0.8rem");
                    footer.css("padding", footerPadding);
                    slideElement(footer, container, newPadding);
                    footer.css("padding", "0.8rem 0.8rem 0 0.8rem");
                } else if (phase === "end") {
                    var newPadding = (direction === "up" ? maxPadding : footerHeight);
                    var footerPadding = (direction === "up" ? "0.8rem" : "0.8rem 0.8rem 0 0.8rem");
                    footer.css("padding", footerPadding);
                    slideElement(footer, container, newPadding);
                    $("div.entry-list ul li").css("overflow-y", direction === "up" ? "auto" : "hidden");
                    up = (direction === "up");
                } else {
                    var newPadding = footerSwipeHeight + (direction === "up" ? distance : -distance);
                    container.css({
                        paddingBottom: newPadding + "px",
                        marginBottom: "-" + newPadding + "px"
                    });
                    footer.css({
                        height: newPadding + "px"
                    })
                }
            }
        },
        checkThresholds: true,
        maxTimeThreshold: 300,
        threshold: swipeThreshold
    });

    var slideWidth = $("div.entry-list ul li:first").width();
    var swipeLeftRightThreshold = slideWidth * 0.3;
    var slideList = $("section#article-section div.entry-list");

    $("section#article-section div.entry-list ul li").swipe({
       swipeStatus: function(event, phase, direction, distance) {
           if (direction === "left" || direction ==="right") {
               var unslider = slideList.data("unslider");
               var currentSlide = unslider.current;
               if (phase === "end") {
                   if ((direction === "left" && (currentSlide === unslider.items.length - 1)) || (direction === "right" && (currentSlide === 0))) {
                       return false;
                   } else {
                       unslider.move(currentSlide + (direction === "left" ? 1 : -1));
                   }
               } else if (phase === "cancel") {
                        unslider.move(currentSlide);
               } else {
                   if ((direction === "left" && (currentSlide === unslider.items.length - 1)) || (direction === "right" && (currentSlide === 0))) {
                       return false;
                   } else {
                       var percentMoved = (distance / slideWidth) * 100;
                       var newPercentage = currentSlide * 100 + (direction === "left" ? percentMoved : -percentMoved);
                       var newLeft = "-" + newPercentage + "%";
                       $("section#article-section div.entry-list ul").css("left", newLeft);
                   }
               }
           }
       },
       checkThresholds: true,
       maxTimeThreshold: 300,
       threshold: swipeLeftRightThreshold,
       allowPageScroll: "vertical"
    });
}

/**
 * $(document).ready
 *
 * initialize jQuery hooks
 */
$(function() {
	resizeContainer();
    initializeFooterSwiping();
    $("img#load-more").hide();
});<|endoftext|>


<commit_before>var toshihiko = require("lib/toshihiko");
var util = require("util");
var coordinator = require("lib/coodinator");

var PetCoordinate = toshihiko.define("pets_coordinate", [
    { name: "id", column: "id", type: toshihiko.TYPE.Integer, primaryKey: true },
    { name: "pet_id", column: "pet_id", type: toshihiko.TYPE.Integer },
    { name: "timestamp", column: "timestamp", type: toshihiko.TYPE.Integer },
    { name: "lng", column: "lng", type: toshihiko.TYPE.Float },
    { name: "lat", column: "lat", type: toshihiko.TYPE.Float }
]);

/**
 * calculateCoordinate
 * @param {Number} petId the pet id
 * @param {Number} timestamp the timestamp
 * @param {Function} callback the callback function
 */
PetCoordinate.calculateCoordinate = function(petId, timestamp, callback) {
    var self = this;
    var notFirstTime = !!arguments[3];

    var PetPosition = util.getModel("PetPosition");
    PetPosition.where({
        "pet_id": petId,
        timestamp: timestamp
    }).find(function(err, positions) {
        if(err) return callback(err);
        if(!positions || !positions.length) callback();

        var pos = coordinator.calculateViaSeveralCoordinate(positions);
        self.where({
            "pet_id": petId,
            timestamp: timestamp
        }).findOne(function(err, coor) {
            if(err) return callback(err);
            if(!coor) {
                coor = self.build({
                    "pet_id": petId,
                    timestamp: timestamp,
                    lng: pos.lng,
                    lat: pos.lat
                });
            } else {
                coor.lng = pos.lng;
                coor.lat = pos.lat;
            }

            coor.save(function(err, coor) {
                if(err) {
                    if(err.indexOf("Duplicate") > -1 && !notFirstTime) {
                        return self.calculateCoordinate(petId, timestamp, callback, true);
                    }

                    if(err.indexOf("No data changed") > -1) {
                        return callback(undefined, coor);
                    }

                    return callback(err);
                }

                callback(undefined, coor);
            });
        });
    });
};

module.exports = PetCoordinate;
<commit_msg>Update pet_coordinate.js<commit_after>var toshihiko = require("lib/toshihiko");
var util = require("util");
var coordinator = require("lib/coordinator");

var PetCoordinate = toshihiko.define("pets_coordinate", [
    { name: "id", column: "id", type: toshihiko.TYPE.Integer, primaryKey: true },
    { name: "pet_id", column: "pet_id", type: toshihiko.TYPE.Integer },
    { name: "timestamp", column: "timestamp", type: toshihiko.TYPE.Integer },
    { name: "lng", column: "lng", type: toshihiko.TYPE.Float },
    { name: "lat", column: "lat", type: toshihiko.TYPE.Float }
]);

/**
 * calculateCoordinate
 * @param {Number} petId the pet id
 * @param {Number} timestamp the timestamp
 * @param {Function} callback the callback function
 */
PetCoordinate.calculateCoordinate = function(petId, timestamp, callback) {
    var self = this;
    var notFirstTime = !!arguments[3];

    var PetPosition = util.getModel("PetPosition");
    PetPosition.where({
        "pet_id": petId,
        timestamp: timestamp
    }).find(function(err, positions) {
        if(err) return callback(err);
        if(!positions || !positions.length) callback();

        var pos = coordinator.calculateViaSeveralCoordinate(positions);
        self.where({
            "pet_id": petId,
            timestamp: timestamp
        }).findOne(function(err, coor) {
            if(err) return callback(err);
            if(!coor) {
                coor = self.build({
                    "pet_id": petId,
                    timestamp: timestamp,
                    lng: pos.lng,
                    lat: pos.lat
                });
            } else {
                coor.lng = pos.lng;
                coor.lat = pos.lat;
            }

            coor.save(function(err, coor) {
                if(err) {
                    if(err.indexOf("Duplicate") > -1 && !notFirstTime) {
                        return self.calculateCoordinate(petId, timestamp, callback, true);
                    }

                    if(err.indexOf("No data changed") > -1) {
                        return callback(undefined, coor);
                    }

                    return callback(err);
                }

                callback(undefined, coor);
            });
        });
    });
};

module.exports = PetCoordinate;
<|endoftext|>


<commit_before>'use strict';
var debug = require('debug')('fileprocessor');
var File = require('./file');
var _ = require('lodash');

var _defaultPatterns = {
	'html': [
      /*jshint regexp:false */
      [ /<script.+src=['"]([^"']+)["']/gm,
      'Update the HTML to reference our concat/min/revved script files'
      ],
      [ /<link[^\>]+href=['"]([^"']+)["']/gm,
      'Update the HTML with the new css filenames'
      ],
      [ /<img[^\>]+src=['"]([^"']+)["']/gm,
      'Update the HTML with the new img filenames'
      ],
      [ /data-main\s*=['"]([^"']+)['"]/gm,
      'Update the HTML with data-main tags',
      function (m) { return m.match(/\.js$/) ? m : m + '.js'; },
      function (m) { return m.replace('.js', ''); }
      ],
      [ /data-(?!main).[^=]+=['"]([^'"]+)['"]/gm,
      'Update the HTML with data-* tags'
      ],
      [ /url\(\s*['"]([^"']+)["']\s*\)/gm,
      'Update the HTML with background imgs, case there is some inline style'
      ],
      [ /<a[^\>]+href=['"]([^"']+)["']/gm,
      'Update the HTML with anchors images'
      ],
      [/<input[^\>]+src=['"]([^"']+)["']/gm,
      'Update the HTML with reference in input'
      ]
    ],
	  'css': [
      /*jshint regexp:false */
      [ /(?:src=|url\(\s*)['"]?([^'"\)\?]+)['"]?\s*\)?/gm,
      'Update the CSS to reference our revved images'
      ]
    ]
  };

_defaultPatterns.jade = require('usemin-patters').jade;

var FileProcessor = module.exports = function(patterns, finder, logcb) {
	if (!patterns) {
		throw new Error('No pattern given');
	}

	if (typeof patterns  === 'string' || patterns instanceof String) {
		if (!_.contains(_.keys(_defaultPatterns), patterns)) {
			throw new Error('Unsupported pattern: ' + patterns);
		}
		this.patterns = _defaultPatterns[patterns];
	}else {
		// FIXME: check the pattern format
		this.patterns = patterns;
	}

	this.log = logcb || function(){};

	if (!finder) {
		throw new Error('Missing parameter: finder');
	}
	this.finder = finder;
};

//
// Replace blocks by their target
//
FileProcessor.prototype.replaceBlocks = function replaceBlocks(file) {
  var result = file.content;
  var linefeed = /\r\n/g.test(result) ? '\r\n' : '\n';
  file.blocks.forEach(function (block) {
    var blockLine = block.raw.join(linefeed);
    result = result.replace(blockLine, this.replaceWith(block));
  }, this);
  return result;
};

FileProcessor.prototype.replaceWith = function replaceWith(block) {
  var result;
  var dest = block.dest;
  var conditionalStart = block.conditionalStart ? block.conditionalStart + '\n' + block.indent : '';
  var conditionalEnd = block.conditionalEnd ? '\n' + block.indent + block.conditionalEnd : '';
  if (block.type === 'css') {
    var media = block.media ? ' media="' + block.media + '"' : '';
    result = block.indent + conditionalStart + 'link(rel=\'stylesheet\', href=\'' + dest + '\'' + media + ')' + conditionalEnd;
  } else if (block.defer || block.type === 'js') {
    result = block.indent + conditionalStart + 'script(src=\'' + dest + '\')' + conditionalEnd;
  } /*else {
    result = '';
  }*/
  return result;
};

//
// Replace reference to scripts, css, images, .. in +lines+ with their revved version
// If +lines+ is not furnished used instead the cached version (i.e. stored at constructor time)
//
FileProcessor.prototype.replaceWithRevved = function replaceWithRevved(lines, assetSearchPath) {
    // Replace script sources
    var self = this;
    var content = lines;
    var regexps = this.patterns;
    var identity = function (m) { return m; };

    // Replace reference to script with the actual name of the revved script
    regexps.forEach(function (rxl) {
      var filterIn = rxl[2] || identity;
      var filterOut = rxl[3] || identity;

      self.log(rxl[1]);
      content = content.replace(rxl[0], function (match, src) {
        // Consider reference from site root
        var srcfile = filterIn(src);

        debug('Let\'s replace ' + src);

        debug('Looking for revved version of ' + srcfile + ' in ', assetSearchPath);

        var file = self.finder.find(srcfile, assetSearchPath);

        debug('Found file \'%s\'', file);

        var res = match.replace(src, filterOut(file));
        if (srcfile !== file) {
          self.log(match + ' changed to ' + res);
        }
        return res;
      });
    });

    return content;
  };

FileProcessor.prototype.process = function(filename, assetSearchPath) {
  debug('processing file %s', filename, assetSearchPath);

  if (typeof filename  === 'string' || filename instanceof String) {
    this.file = new File(filename);
  } else {
    // filename is an object and should conform to lib/file.js API
    this.file = filename;
  }

  if (assetSearchPath && assetSearchPath.length !== 0) {
    this.file.searchPath = assetSearchPath;
  }

	var content = this.replaceWithRevved(this.replaceBlocks(this.file), this.file.searchPath);

	return content;
};
<commit_msg>fixed typo<commit_after>'use strict';
var debug = require('debug')('fileprocessor');
var File = require('./file');
var _ = require('lodash');

var _defaultPatterns = {
	'html': [
      /*jshint regexp:false */
      [ /<script.+src=['"]([^"']+)["']/gm,
      'Update the HTML to reference our concat/min/revved script files'
      ],
      [ /<link[^\>]+href=['"]([^"']+)["']/gm,
      'Update the HTML with the new css filenames'
      ],
      [ /<img[^\>]+src=['"]([^"']+)["']/gm,
      'Update the HTML with the new img filenames'
      ],
      [ /data-main\s*=['"]([^"']+)['"]/gm,
      'Update the HTML with data-main tags',
      function (m) { return m.match(/\.js$/) ? m : m + '.js'; },
      function (m) { return m.replace('.js', ''); }
      ],
      [ /data-(?!main).[^=]+=['"]([^'"]+)['"]/gm,
      'Update the HTML with data-* tags'
      ],
      [ /url\(\s*['"]([^"']+)["']\s*\)/gm,
      'Update the HTML with background imgs, case there is some inline style'
      ],
      [ /<a[^\>]+href=['"]([^"']+)["']/gm,
      'Update the HTML with anchors images'
      ],
      [/<input[^\>]+src=['"]([^"']+)["']/gm,
      'Update the HTML with reference in input'
      ]
    ],
	  'css': [
      /*jshint regexp:false */
      [ /(?:src=|url\(\s*)['"]?([^'"\)\?]+)['"]?\s*\)?/gm,
      'Update the CSS to reference our revved images'
      ]
    ]
  };

_defaultPatterns.jade = require('usemin-patterns').jade;

var FileProcessor = module.exports = function(patterns, finder, logcb) {
	if (!patterns) {
		throw new Error('No pattern given');
	}

	if (typeof patterns  === 'string' || patterns instanceof String) {
		if (!_.contains(_.keys(_defaultPatterns), patterns)) {
			throw new Error('Unsupported pattern: ' + patterns);
		}
		this.patterns = _defaultPatterns[patterns];
	}else {
		// FIXME: check the pattern format
		this.patterns = patterns;
	}

	this.log = logcb || function(){};

	if (!finder) {
		throw new Error('Missing parameter: finder');
	}
	this.finder = finder;
};

//
// Replace blocks by their target
//
FileProcessor.prototype.replaceBlocks = function replaceBlocks(file) {
  var result = file.content;
  var linefeed = /\r\n/g.test(result) ? '\r\n' : '\n';
  file.blocks.forEach(function (block) {
    var blockLine = block.raw.join(linefeed);
    result = result.replace(blockLine, this.replaceWith(block));
  }, this);
  return result;
};

FileProcessor.prototype.replaceWith = function replaceWith(block) {
  var result;
  var dest = block.dest;
  var conditionalStart = block.conditionalStart ? block.conditionalStart + '\n' + block.indent : '';
  var conditionalEnd = block.conditionalEnd ? '\n' + block.indent + block.conditionalEnd : '';
  if (block.type === 'css') {
    var media = block.media ? ' media="' + block.media + '"' : '';
    result = block.indent + conditionalStart + 'link(rel=\'stylesheet\', href=\'' + dest + '\'' + media + ')' + conditionalEnd;
  } else if (block.defer || block.type === 'js') {
    result = block.indent + conditionalStart + 'script(src=\'' + dest + '\')' + conditionalEnd;
  } /*else {
    result = '';
  }*/
  return result;
};

//
// Replace reference to scripts, css, images, .. in +lines+ with their revved version
// If +lines+ is not furnished used instead the cached version (i.e. stored at constructor time)
//
FileProcessor.prototype.replaceWithRevved = function replaceWithRevved(lines, assetSearchPath) {
    // Replace script sources
    var self = this;
    var content = lines;
    var regexps = this.patterns;
    var identity = function (m) { return m; };

    // Replace reference to script with the actual name of the revved script
    regexps.forEach(function (rxl) {
      var filterIn = rxl[2] || identity;
      var filterOut = rxl[3] || identity;

      self.log(rxl[1]);
      content = content.replace(rxl[0], function (match, src) {
        // Consider reference from site root
        var srcfile = filterIn(src);

        debug('Let\'s replace ' + src);

        debug('Looking for revved version of ' + srcfile + ' in ', assetSearchPath);

        var file = self.finder.find(srcfile, assetSearchPath);

        debug('Found file \'%s\'', file);

        var res = match.replace(src, filterOut(file));
        if (srcfile !== file) {
          self.log(match + ' changed to ' + res);
        }
        return res;
      });
    });

    return content;
  };

FileProcessor.prototype.process = function(filename, assetSearchPath) {
  debug('processing file %s', filename, assetSearchPath);

  if (typeof filename  === 'string' || filename instanceof String) {
    this.file = new File(filename);
  } else {
    // filename is an object and should conform to lib/file.js API
    this.file = filename;
  }

  if (assetSearchPath && assetSearchPath.length !== 0) {
    this.file.searchPath = assetSearchPath;
  }

	var content = this.replaceWithRevved(this.replaceBlocks(this.file), this.file.searchPath);

	return content;
};
<|endoftext|>


<commit_before>var runSequence    = require('run-sequence');
var handleErrors   = require('../util/handleErrors');
var mainBowerFiles = require('main-bower-files');

module.exports = function (gulp, $, config) {

  var paths           = config.paths;
  var bootSnippet     = config.bootSnippet;
  var appcacheOptions = config.appcacheOptions;

  gulp.task('build:templates', [ 'compile:templates' ], function () {
    return gulp.src(paths['temp'] + '/*.html')
      .pipe(handleErrors())
      .pipe($.processhtml())
      .pipe(gulp.dest(paths['dist']));
  });

  gulp.task('build:css', [ 'compile:css' ], function () {
    return gulp.src(paths['temp'] + '/style.css')
      .pipe(handleErrors())
      .pipe($.minifyCss({
        keepSpecialComments: false,
        removeEmpty: true
      }))
      .pipe($.rename('style.min.css'))
      .pipe(gulp.dest(paths['dist']));
  });

  gulp.task('build:js', [ 'compile:js' ], function () {
    var files = mainBowerFiles().concat(paths['temp'] + '/game.js');

    return gulp.src(files)
      .pipe($.sourcemaps.init())
      .pipe($.concat('game.min.js'))
      .pipe($.uglify())
      .pipe($.sourcemaps.write('.'))
      .pipe(gulp.dest(paths['dist']));
  });

  gulp.task('build:assets', function () {
    return gulp.src(paths['assets'])
      .pipe(handleErrors())
      .pipe(gulp.dest(paths['dist']))
      .pipe($.manifest(appcacheOptions))
      .pipe(gulp.dest(paths['dist']));
  });

  gulp.task('build', function (done) {
    runSequence('clean', [
      'build:templates',
      'build:css',
      'build:js',
      'build:assets'
    ], done);
  });

};
<commit_msg>Removing forgotten variable declaration<commit_after>var runSequence    = require('run-sequence');
var handleErrors   = require('../util/handleErrors');
var mainBowerFiles = require('main-bower-files');

module.exports = function (gulp, $, config) {

  var paths           = config.paths;
  var appcacheOptions = config.appcacheOptions;

  gulp.task('build:templates', [ 'compile:templates' ], function () {
    return gulp.src(paths['temp'] + '/*.html')
      .pipe(handleErrors())
      .pipe($.processhtml())
      .pipe(gulp.dest(paths['dist']));
  });

  gulp.task('build:css', [ 'compile:css' ], function () {
    return gulp.src(paths['temp'] + '/style.css')
      .pipe(handleErrors())
      .pipe($.minifyCss({
        keepSpecialComments: false,
        removeEmpty: true
      }))
      .pipe($.rename('style.min.css'))
      .pipe(gulp.dest(paths['dist']));
  });

  gulp.task('build:js', [ 'compile:js' ], function () {
    var files = mainBowerFiles().concat(paths['temp'] + '/game.js');

    return gulp.src(files)
      .pipe($.sourcemaps.init())
      .pipe($.concat('game.min.js'))
      .pipe($.uglify())
      .pipe($.sourcemaps.write('.'))
      .pipe(gulp.dest(paths['dist']));
  });

  gulp.task('build:assets', function () {
    return gulp.src(paths['assets'])
      .pipe(handleErrors())
      .pipe(gulp.dest(paths['dist']))
      .pipe($.manifest(appcacheOptions))
      .pipe(gulp.dest(paths['dist']));
  });

  gulp.task('build', function (done) {
    runSequence('clean', [
      'build:templates',
      'build:css',
      'build:js',
      'build:assets'
    ], done);
  });

};
<|endoftext|>


<commit_before>'use strict'

const log = require('util').debuglog('cloudfoundry-actuator-middleware');

const DiscoveryEndpoint = require('./endpoints/discovery')
const HealthEndpoint = require('./endpoints/health')
const InfoEndpoint = require('./endpoints/info')

/**
 *
 */
class Registry {

    constructor(options) {
        this._endpoints = {}
        this._addEndpoint(new DiscoveryEndpoint({
            contributors: this._endpoints
        }))
        this._addEndpoint(new HealthEndpoint())
        this._addEndpoint(new InfoEndpoint())
    }

    /**
     *
     * @private
     * @param {Endpoint} endpoint
     */
    _addEndpoint(endpoint) {
        this._endpoints[endpoint.getPath()] = endpoint
    }

    /**
     *
     * @param {http.ClientRequest} req
     * @returns {Endpoint} the endpoint, that is registered to handle the incoming request
     */
    getEndpoint(req) {
        let path = req.path
        if (!path.endsWith('/')) {
            path += '/'
        }

        log('getEndpoint %s', path)

        return this._endpoints[path]
    }
}

module.exports = Registry<commit_msg>chore: rm registry<commit_after><|endoftext|>


<commit_before>var gulp = require('gulp'),
    svg2png = require('gulp-svg2png'),
    del = require('del'),
    svgSprite = require('gulp-svg-sprite'),
    runSequence = require('run-sequence');

config = {
  mode: {
    css: {
      variables: {
        fallback: function() {
          return function (sprite, render) {
            return render(sprite).split('.svg').join('.png');
          };
        },
        removePath: function () {
          return function (sprite, render) {
            var fileRegex = /sprite-.{8}.{4}/g;
            var spriteFile = fileRegex.exec(render(sprite));
            return spriteFile;
          };
        }
      },
      dest: '/_tmp/styles',
      sprite: '/assets/images/sprites/sprite.svg',
      render: {
        css: {
          template: './gulp/templates/sprite.css',
          css: '../../sprite.css'
        }
      }
    }
  }
};

gulp.task('cleanSprite', function () {
  return del('./app/assets/images/sprites/');
});

gulp.task('createSprite', ['cleanSprite'], function () {
  return gulp.src('./app/assets/images/icons/**/*.svg')
    .pipe(svgSprite(config))
    .pipe(gulp.dest('./app/assets/images/icons/sprite/'));
});

gulp.task('spritePNG', ['createSprite'], function () {
  return gulp.src('./app/assets/images/sprites/*.svg')
    .pipe(svg2png())
    .pipe(gulp.dest('./app/assets/images/sprites/'));
});

gulp.task('icons', ['cleanSprite', 'createSprite', 'spritePNG']);
<commit_msg>Revise icons to work in multiple environments<commit_after>var gulp = require('gulp'),
    svg2png = require('gulp-svg2png'),
    del = require('del'),
    svgSprite = require('gulp-svg-sprite'),
    runSequence = require('run-sequence');

config = {
  mode: {
    css: {
      variables: {
        fallback: function() {
          return function (sprite, render) {
            return render(sprite).split('.svg').join('.png');
          };
        },
        removePath: function () {
          return function (sprite, render) {
            var fileRegex = /sprite.{8}.{5}/g;
            var spriteFile = fileRegex.exec(render(sprite));
            return spriteFile;
          };
        }
      },
      sprite: 'svg/sprite.svg',
      render: {
        css: {
          template: './gulp/templates/sprite.css'
        }
      }
    }
  }
};

gulp.task('cleanSprite', function () {
  return del(['./app/_tmp/sprites/', './app/assets/images/sprites/']);
});

gulp.task('createSprite', ['cleanSprite'], function () {
  return gulp.src('./app/assets/images/icons/**/*.svg')
    .pipe(svgSprite(config))
    .pipe(gulp.dest('./app/_tmp/sprites/'));
});

gulp.task('spritePNG', ['createSprite'], function () {
  return gulp.src('./app/_tmp/sprites/css/svg/*.svg')
    .pipe(svg2png())
    .pipe(gulp.dest('./app/_tmp/sprites/css/svg/'));
});

gulp.task('copySprites', ['spritePNG'], function () {
  var copyPaths = [
    './app/_tmp/sprites/css/svg/**'
  ];

  return gulp.src(copyPaths).pipe(gulp.dest('./app/assets/images/sprites/'));
});

gulp.task('copyStyles', ['copySprites'], function () {
  var copyPaths = [
    './app/_tmp/sprites/css/*.css'
  ];

  return gulp.src(copyPaths).pipe(gulp.dest('./app/_tmp/styles/'));
});

gulp.task('deleteTmpSprites', ['copyStyles'], function () {
  return del('./app/_tmp/sprites/');
});

gulp.task('icons', ['cleanSprite', 'createSprite', 'spritePNG', 'copySprites', 'copyStyles', 'deleteTmpSprites']);
<|endoftext|>


<commit_before>import ansiHTML from 'ansi-html'
import serialize from 'serialize-javascript'
import generateETag from 'etag'
import fresh from 'fresh'
import Tapable from 'tappable'
import pify from 'pify'
import serveStatic from 'serve-static'
import compression from 'compression'
import _ from 'lodash'
import { resolve, join } from 'path'
import fs from 'fs-extra'
import { createBundleRenderer } from 'vue-server-renderer'
import { getContext, setAnsiColors, encodeHtml } from './utils'

const debug = require('debug')('nuxt:render')
debug.color = 4 // Force blue color
setAnsiColors(ansiHTML)

let jsdom = null

const parseTemplate = templateStr => _.template(templateStr, {
  interpolate: /{{([\s\S]+?)}}/g
})

export default class Renderer extends Tapable {
  constructor (nuxt) {
    super()
    this.nuxt = nuxt
    this.options = nuxt.options

    // Will be set by createRenderer
    this.bundleRenderer = null

    // Renderer runtime resources
    this.resources = {
      clientManifest: null,
      serverBundle: null,
      appTemplate: null,
      errorTemplate: parseTemplate(fs.readFileSync(resolve(__dirname, 'views', 'error.html'), 'utf8'))
    }

    // Initialize
    if (nuxt.initialized) {
      // If nuxt already initialized
      this._ready = this.ready().catch(this.nuxt.errorHandler)
    } else {
      // Wait for hook
      this.nuxt.plugin('afterInit', () => {
        this._ready = this.ready()
        return this._ready
      })
    }
  }

  async ready () {
    if (this._ready) {
      return this._ready
    }

    // For serving static/ files to /
    this.serveStatic = pify(serveStatic(resolve(this.options.srcDir, 'static'), this.options.render.static))

    // For serving .nuxt/dist/ files (only when build.publicPath is not an URL)
    this.serveStaticNuxt = pify(serveStatic(resolve(this.options.buildDir, 'dist'), {
      maxAge: (this.options.dev ? 0 : '1y') // 1 year in production
    }))

    // gzip middleware for production
    if (!this.options.dev && this.options.render.gzip) {
      this.gzipMiddleware = pify(compression(this.options.render.gzip))
    }

    // Load resources from fs
    if (!this.options.dev) {
      await this.loadResources()
    }

    return this
  }

  async loadResources (_fs = fs, isServer) {
    let distPath = resolve(this.options.buildDir, 'dist')

    const resourceMap = {
      clientManifest: {
        path: join(distPath, 'vue-ssr-client-manifest.json'),
        transform: JSON.parse
      },
      serverBundle: {
        path: join(distPath, 'server-bundle.json'),
        transform: JSON.parse
      },
      appTemplate: {
        path: join(distPath, 'index.html'),
        transform: parseTemplate
      }
    }

    let updated = []

    Object.keys(resourceMap).forEach(resourceKey => {
      let { path, transform } = resourceMap[resourceKey]
      let rawKey = '$$' + resourceKey
      let rawData, data
      if (!_fs.existsSync(path)) {
        return // Resource not exists
      }
      rawData = _fs.readFileSync(path, 'utf8')
      if (!rawData || rawData === this.resources[rawKey]) {
        return // No changes
      }
      this.resources[rawKey] = rawData
      data = transform(rawData)
      if (!data) {
        return // Invalid data ?
      }
      this.resources[resourceKey] = data
      updated.push(resourceKey)
    })

    if (updated.length > 0) {
      // debug('Updated', updated.join(', '), isServer)
      this.createRenderer()
    }
  }

  createRenderer () {
    // If resources are not yet provided
    if (!this.resources.serverBundle || !this.resources.clientManifest) {
      return
    }

    // Create bundle renderer for SSR
    this.bundleRenderer = createBundleRenderer(this.resources.serverBundle, Object.assign({
      clientManifest: this.resources.clientManifest,
      runInNewContext: false,
      basedir: this.options.rootDir
    }, this.options.render.ssr))

    // Promisify renderToString
    this.bundleRenderer.renderToString = pify(this.bundleRenderer.renderToString)

    this.nuxt.serverReady()
  }

  async render (req, res) {
    // Get context
    const context = getContext(req, res)
    res.statusCode = 200

    try {
      // Call webpack middleware only in development
      if (this.options.dev && this.nuxt.builder && this.nuxt.builder.webpackDevMiddleware) {
        await this.nuxt.builder.webpackDevMiddleware(req, res)
        await this.nuxt.builder.webpackHotMiddleware(req, res)
      }

      // Gzip middleware for production
      if (this.gzipMiddleware) {
        await this.gzipMiddleware(req, res)
      }

      // If base in req.url, remove it for the middleware and vue-router
      if (this.options.router.base !== '/' && req.url.indexOf(this.options.router.base) === 0) {
        // Compatibility with base url for dev server
        req.url = req.url.replace(this.options.router.base, '/')
      }

      // Serve static/ files
      await this.serveStatic(req, res)

      // Serve .nuxt/dist/ files (only for production)
      if (!this.options.dev && req.url.indexOf(this.options.build.publicPath) === 0) {
        const url = req.url
        req.url = req.url.replace(this.options.build.publicPath, '/')
        await this.serveStaticNuxt(req, res)
        /* istanbul ignore next */
        req.url = url
      }

      if (this.options.dev && req.url.indexOf(this.options.build.publicPath) === 0 && req.url.includes('.hot-update.json')) {
        res.statusCode = 404
        return res.end()
      }

      const { html, error, redirected, resourceHints } = await this.renderRoute(req.url, context)

      if (redirected) {
        return html
      }

      if (error) {
        res.statusCode = context.nuxt.error.statusCode || 500
      }

      // ETag header
      if (!error && this.options.render.etag) {
        const etag = generateETag(html, this.options.render.etag)
        if (fresh(req.headers, { etag })) {
          res.statusCode = 304
          res.end()
          return
        }
        res.setHeader('ETag', etag)
      }

      // HTTP2 push headers
      if (!error && this.options.render.http2.push) {
        // Parse resourceHints to extract HTTP.2 prefetch/push headers
        // https://w3c.github.io/preload/#server-push-http-2
        const regex = /link rel="([^"]*)" href="([^"]*)" as="([^"]*)"/g
        const pushAssets = []
        let m
        while (m = regex.exec(resourceHints)) { // eslint-disable-line no-cond-assign
          const [_, rel, href, as] = m // eslint-disable-line no-unused-vars
          if (rel === 'preload') {
            pushAssets.push(`<${href}>; rel=${rel}; as=${as}`)
          }
        }
        // Pass with single Link header
        // https://blog.cloudflare.com/http-2-server-push-with-multiple-assets-per-link-header
        res.setHeader('Link', pushAssets.join(','))
      }

      // Send response
      res.setHeader('Content-Type', 'text/html; charset=utf-8')
      res.setHeader('Content-Length', Buffer.byteLength(html))
      res.end(html, 'utf8')
      return html
    } catch (err) {
      if (context.redirected) {
        console.error(err) // eslint-disable-line no-console
        return err
      }
      // Render error template
      const html = this.resources.errorTemplate({
        /* istanbul ignore if */
        error: err,
        stack: ansiHTML(encodeHtml(err.stack))
      })
      // Send response
      res.statusCode = 500
      res.setHeader('Content-Type', 'text/html; charset=utf-8')
      res.setHeader('Content-Length', Buffer.byteLength(html))
      res.end(html, 'utf8')
      return err
    }
  }

  async renderRoute (url, context = {}) {
    /* istanbul ignore if */
    if (!this.bundleRenderer || !this.resources.appTemplate) {
      return new Promise(resolve => {
        setTimeout(() => resolve(this.renderRoute(url, context)), 1000)
      })
    }

    // Log rendered url
    debug(`Rendering url ${url}`)

    // Add url and isSever to the context
    context.url = url
    context.isServer = true

    // Call renderToString from the bundleRenderer and generate the HTML (will update the context as well)
    let APP = await this.bundleRenderer.renderToString(context)

    if (!context.nuxt.serverRendered) {
      APP = '

'
    }
    const m = context.meta.inject()
    let HEAD = m.meta.text() + m.title.text() + m.link.text() + m.style.text() + m.script.text() + m.noscript.text()
    if (this.options._routerBaseSpecified) {
      HEAD += `<base href="${this.options.router.base}">`
    }
    const resourceHints = context.renderResourceHints()
    HEAD += resourceHints + context.renderStyles()
    APP += `<script type="text/javascript">window.__NUXT__=${serialize(context.nuxt, { isJSON: true })}</script>`
    APP += context.renderScripts()

    const html = this.resources.appTemplate({
      HTML_ATTRS: 'data-n-head-ssr ' + m.htmlAttrs.text(),
      BODY_ATTRS: m.bodyAttrs.text(),
      HEAD,
      APP
    })

    return {
      html,
      resourceHints,
      error: context.nuxt.error,
      redirected: context.redirected
    }
  }

  async renderAndGetWindow (url, opts = {}) {
    /* istanbul ignore if */
    if (!jsdom) {
      try {
        jsdom = require('jsdom')
      } catch (e) {
        console.error('Fail when calling nuxt.renderAndGetWindow(url)') // eslint-disable-line no-console
        console.error('jsdom module is not installed') // eslint-disable-line no-console
        console.error('Please install jsdom with: npm install --save-dev jsdom') // eslint-disable-line no-console
        throw e
      }
    }
    let options = {
      resources: 'usable', // load subresources (https://github.com/tmpvar/jsdom#loading-subresources)
      runScripts: 'dangerously',
      beforeParse (window) {
        // Mock window.scrollTo
        window.scrollTo = () => {
        }
      }
    }
    if (opts.virtualConsole !== false) {
      options.virtualConsole = new jsdom.VirtualConsole().sendTo(console)
    }
    url = url || 'http://localhost:3000'
    const { window } = await jsdom.JSDOM.fromURL(url, options)
    // If Nuxt could not be loaded (error from the server-side)
    const nuxtExists = window.document.body.innerHTML.includes('window.__NUXT__')
    if (!nuxtExists) {
      /* istanbul ignore next */
      let error = new Error('Could not load the nuxt app')
      /* istanbul ignore next */
      error.body = window.document.body.innerHTML
      throw error
    }
    // Used by nuxt.js to say when the components are loaded and the app ready
    await new Promise((resolve) => {
      window._onNuxtLoaded = () => resolve(window)
    })
    // Send back window object
    return window
  }
}
<commit_msg>fix devMiddleware with baseUrl<commit_after>import ansiHTML from 'ansi-html'
import serialize from 'serialize-javascript'
import generateETag from 'etag'
import fresh from 'fresh'
import Tapable from 'tappable'
import pify from 'pify'
import serveStatic from 'serve-static'
import compression from 'compression'
import _ from 'lodash'
import { resolve, join } from 'path'
import fs from 'fs-extra'
import { createBundleRenderer } from 'vue-server-renderer'
import { getContext, setAnsiColors, encodeHtml } from './utils'

const debug = require('debug')('nuxt:render')
debug.color = 4 // Force blue color
setAnsiColors(ansiHTML)

let jsdom = null

const parseTemplate = templateStr => _.template(templateStr, {
  interpolate: /{{([\s\S]+?)}}/g
})

export default class Renderer extends Tapable {
  constructor (nuxt) {
    super()
    this.nuxt = nuxt
    this.options = nuxt.options

    // Will be set by createRenderer
    this.bundleRenderer = null

    // Renderer runtime resources
    this.resources = {
      clientManifest: null,
      serverBundle: null,
      appTemplate: null,
      errorTemplate: parseTemplate(fs.readFileSync(resolve(__dirname, 'views', 'error.html'), 'utf8'))
    }

    // Initialize
    if (nuxt.initialized) {
      // If nuxt already initialized
      this._ready = this.ready().catch(this.nuxt.errorHandler)
    } else {
      // Wait for hook
      this.nuxt.plugin('afterInit', () => {
        this._ready = this.ready()
        return this._ready
      })
    }
  }

  async ready () {
    if (this._ready) {
      return this._ready
    }

    // For serving static/ files to /
    this.serveStatic = pify(serveStatic(resolve(this.options.srcDir, 'static'), this.options.render.static))

    // For serving .nuxt/dist/ files (only when build.publicPath is not an URL)
    this.serveStaticNuxt = pify(serveStatic(resolve(this.options.buildDir, 'dist'), {
      maxAge: (this.options.dev ? 0 : '1y') // 1 year in production
    }))

    // gzip middleware for production
    if (!this.options.dev && this.options.render.gzip) {
      this.gzipMiddleware = pify(compression(this.options.render.gzip))
    }

    // Load resources from fs
    if (!this.options.dev) {
      await this.loadResources()
    }

    return this
  }

  async loadResources (_fs = fs, isServer) {
    let distPath = resolve(this.options.buildDir, 'dist')

    const resourceMap = {
      clientManifest: {
        path: join(distPath, 'vue-ssr-client-manifest.json'),
        transform: JSON.parse
      },
      serverBundle: {
        path: join(distPath, 'server-bundle.json'),
        transform: JSON.parse
      },
      appTemplate: {
        path: join(distPath, 'index.html'),
        transform: parseTemplate
      }
    }

    let updated = []

    Object.keys(resourceMap).forEach(resourceKey => {
      let { path, transform } = resourceMap[resourceKey]
      let rawKey = '$$' + resourceKey
      let rawData, data
      if (!_fs.existsSync(path)) {
        return // Resource not exists
      }
      rawData = _fs.readFileSync(path, 'utf8')
      if (!rawData || rawData === this.resources[rawKey]) {
        return // No changes
      }
      this.resources[rawKey] = rawData
      data = transform(rawData)
      if (!data) {
        return // Invalid data ?
      }
      this.resources[resourceKey] = data
      updated.push(resourceKey)
    })

    if (updated.length > 0) {
      // debug('Updated', updated.join(', '), isServer)
      this.createRenderer()
    }
  }

  createRenderer () {
    // If resources are not yet provided
    if (!this.resources.serverBundle || !this.resources.clientManifest) {
      return
    }

    // Create bundle renderer for SSR
    this.bundleRenderer = createBundleRenderer(this.resources.serverBundle, Object.assign({
      clientManifest: this.resources.clientManifest,
      runInNewContext: false,
      basedir: this.options.rootDir
    }, this.options.render.ssr))

    // Promisify renderToString
    this.bundleRenderer.renderToString = pify(this.bundleRenderer.renderToString)

    this.nuxt.serverReady()
  }

  async render (req, res) {
    // Get context
    const context = getContext(req, res)
    res.statusCode = 200

    try {
      // Gzip middleware for production
      if (this.gzipMiddleware) {
        await this.gzipMiddleware(req, res)
      }

      // If base in req.url, remove it for the middleware and vue-router
      if (this.options.router.base !== '/' && req.url.indexOf(this.options.router.base) === 0) {
        // Compatibility with base url for dev server
        req.url = req.url.replace(this.options.router.base, '/')
      }

      // Call webpack middleware only in development
      if (this.options.dev && this.nuxt.builder && this.nuxt.builder.webpackDevMiddleware) {
        await this.nuxt.builder.webpackDevMiddleware(req, res)
        await this.nuxt.builder.webpackHotMiddleware(req, res)
      }

      // Serve static/ files
      await this.serveStatic(req, res)

      // Serve .nuxt/dist/ files (only for production)
      if (!this.options.dev && req.url.indexOf(this.options.build.publicPath) === 0) {
        const url = req.url
        req.url = req.url.replace(this.options.build.publicPath, '/')
        await this.serveStaticNuxt(req, res)
        /* istanbul ignore next */
        req.url = url
      }

      if (this.options.dev && req.url.indexOf(this.options.build.publicPath) === 0 && req.url.includes('.hot-update.json')) {
        res.statusCode = 404
        return res.end()
      }

      const { html, error, redirected, resourceHints } = await this.renderRoute(req.url, context)

      if (redirected) {
        return html
      }

      if (error) {
        res.statusCode = context.nuxt.error.statusCode || 500
      }

      // ETag header
      if (!error && this.options.render.etag) {
        const etag = generateETag(html, this.options.render.etag)
        if (fresh(req.headers, { etag })) {
          res.statusCode = 304
          res.end()
          return
        }
        res.setHeader('ETag', etag)
      }

      // HTTP2 push headers
      if (!error && this.options.render.http2.push) {
        // Parse resourceHints to extract HTTP.2 prefetch/push headers
        // https://w3c.github.io/preload/#server-push-http-2
        const regex = /link rel="([^"]*)" href="([^"]*)" as="([^"]*)"/g
        const pushAssets = []
        let m
        while (m = regex.exec(resourceHints)) { // eslint-disable-line no-cond-assign
          const [_, rel, href, as] = m // eslint-disable-line no-unused-vars
          if (rel === 'preload') {
            pushAssets.push(`<${href}>; rel=${rel}; as=${as}`)
          }
        }
        // Pass with single Link header
        // https://blog.cloudflare.com/http-2-server-push-with-multiple-assets-per-link-header
        res.setHeader('Link', pushAssets.join(','))
      }

      // Send response
      res.setHeader('Content-Type', 'text/html; charset=utf-8')
      res.setHeader('Content-Length', Buffer.byteLength(html))
      res.end(html, 'utf8')
      return html
    } catch (err) {
      if (context.redirected) {
        console.error(err) // eslint-disable-line no-console
        return err
      }
      // Render error template
      const html = this.resources.errorTemplate({
        /* istanbul ignore if */
        error: err,
        stack: ansiHTML(encodeHtml(err.stack))
      })
      // Send response
      res.statusCode = 500
      res.setHeader('Content-Type', 'text/html; charset=utf-8')
      res.setHeader('Content-Length', Buffer.byteLength(html))
      res.end(html, 'utf8')
      return err
    }
  }

  async renderRoute (url, context = {}) {
    /* istanbul ignore if */
    if (!this.bundleRenderer || !this.resources.appTemplate) {
      return new Promise(resolve => {
        setTimeout(() => resolve(this.renderRoute(url, context)), 1000)
      })
    }

    // Log rendered url
    debug(`Rendering url ${url}`)

    // Add url and isSever to the context
    context.url = url
    context.isServer = true

    // Call renderToString from the bundleRenderer and generate the HTML (will update the context as well)
    let APP = await this.bundleRenderer.renderToString(context)

    if (!context.nuxt.serverRendered) {
      APP = '

'
    }
    const m = context.meta.inject()
    let HEAD = m.meta.text() + m.title.text() + m.link.text() + m.style.text() + m.script.text() + m.noscript.text()
    if (this.options._routerBaseSpecified) {
      HEAD += `<base href="${this.options.router.base}">`
    }
    const resourceHints = context.renderResourceHints()
    HEAD += resourceHints + context.renderStyles()
    APP += `<script type="text/javascript">window.__NUXT__=${serialize(context.nuxt, { isJSON: true })}</script>`
    APP += context.renderScripts()

    const html = this.resources.appTemplate({
      HTML_ATTRS: 'data-n-head-ssr ' + m.htmlAttrs.text(),
      BODY_ATTRS: m.bodyAttrs.text(),
      HEAD,
      APP
    })

    return {
      html,
      resourceHints,
      error: context.nuxt.error,
      redirected: context.redirected
    }
  }

  async renderAndGetWindow (url, opts = {}) {
    /* istanbul ignore if */
    if (!jsdom) {
      try {
        jsdom = require('jsdom')
      } catch (e) {
        console.error('Fail when calling nuxt.renderAndGetWindow(url)') // eslint-disable-line no-console
        console.error('jsdom module is not installed') // eslint-disable-line no-console
        console.error('Please install jsdom with: npm install --save-dev jsdom') // eslint-disable-line no-console
        throw e
      }
    }
    let options = {
      resources: 'usable', // load subresources (https://github.com/tmpvar/jsdom#loading-subresources)
      runScripts: 'dangerously',
      beforeParse (window) {
        // Mock window.scrollTo
        window.scrollTo = () => {
        }
      }
    }
    if (opts.virtualConsole !== false) {
      options.virtualConsole = new jsdom.VirtualConsole().sendTo(console)
    }
    url = url || 'http://localhost:3000'
    const { window } = await jsdom.JSDOM.fromURL(url, options)
    // If Nuxt could not be loaded (error from the server-side)
    const nuxtExists = window.document.body.innerHTML.includes('window.__NUXT__')
    if (!nuxtExists) {
      /* istanbul ignore next */
      let error = new Error('Could not load the nuxt app')
      /* istanbul ignore next */
      error.body = window.document.body.innerHTML
      throw error
    }
    // Used by nuxt.js to say when the components are loaded and the app ready
    await new Promise((resolve) => {
      window._onNuxtLoaded = () => resolve(window)
    })
    // Send back window object
    return window
  }
}
<|endoftext|>


<commit_before>// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Node dependencies

var fs = require('fs');
var fspath = require('path');
var mkdirp = require('mkdirp');
var util = require('util');

// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Mocha dependencies

var mocha = require('mocha');
var Base = mocha.reporters.Base,
    cursor = Base.cursor,
    color = Base.color;

// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Library dependencies

var ms = require('./ms');

module.exports = Reporter;

function Suite(suite) {
    if (suite) {
        this.title = suite.title;
        this.timeout = suite._timeout;
        this.slow = suite._slow;
    }
    this.suites = [];
    this.tests = [];
}

function Test(test) {
    this.title = test.title;
    this.fullTitle = test.fullTitle();
    this.timedOut = test.timedOut;
    this.duration = test.duration;
    this.speed = test.speed;
    this.file = test.file;
    this.state = test.state;
}

function top(array) {
    return array[array.length - 1];
}

/**
 * Initialize a new `JSON` reporter.
 *
 * @param {Runner} runner
 * @api public
 */

function Reporter(runner) {
    Base.call(this, runner);

    var self = this;
    var stats = this.stats;
    var indents = 0;
    var n = 0;

    var root = new Suite();
    var stack = [root];

    var options = {
        dest: './'
    };
    for (var p in options) {
        if (typeof process.env['mocha-json-spec-' + p] === 'string') {
            options[p] = process.env['mocha-json-spec-' + p];
        } else if (typeof process.env['MOCHA_JSON_SPEC_' + p.toUpperCase()] === 'string') {
            options[p] = process.env['MOCHA_JSON_SPEC_' + p.toUpperCase()];
        }
    }

    function indent() {
        return Array(indents).join('  ')
    }

    runner.on('start', function() {
        console.log();
    });

    runner.on('suite', function(suite) {
        ++indents;
        console.log(color('suite', '%s%s'), indent(), suite.title);
        if (suite.root) {
            return;
        }
        var parent = top(stack);
        var child = new Suite(suite);
        parent.suites.push(child);
        stack.push(child);
    });

    runner.on('suite end', function(suite) {
        --indents;
        if (1 == indents) {
            console.log();
        }
        stack.pop();
    });

    runner.on('test end', function(test) {
        top(stack).tests.push(new Test(test));
    });

    runner.on('pending', function(test) {
        var fmt = indent() + color('pending', '  - %s');
        console.log(fmt, test.title);
    });

    runner.on('pass', function(test) {
        if ('fast' == test.speed) {
            var fmt = indent() + color('checkmark', '  ' + Base.symbols.ok) + color('pass', ' %s ');
            cursor.CR();
            console.log(fmt, test.title);
        } else {
            var fmt = indent() + color('checkmark', '  ' + Base.symbols.ok) + color('pass', ' %s ') + color(test.speed, '(%dms)');
            cursor.CR();
            console.log(fmt, test.title, test.duration);
        }
        var current = top(stack);
    });

    runner.on('fail', function(test) {
        cursor.CR();
        console.log(indent() + color('fail', '  %d) %s'), ++n, test.title);
    });

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

        // Epilogue
        var fmt;
        try {
            console.log(color('bright yellow', '  Summary'));

            // Passes
            fmt = color('bright pass', ' ');
            fmt += color('green', ' %d passing');
            fmt += color('light', ' (%s)');
            console.log(fmt, stats.passes || 0, ms(stats.duration));

            // Pending
            if (stats.pending) {
                fmt = color('pending', ' ');
                fmt += color('pending', ' %d pending');
                console.log(fmt, stats.pending);
            }

            // Failures
            if (stats.failures) {
                fmt = color('fail', '  %d failing');
                console.error(fmt, stats.failures);
                Base.list(self.failures);
                console.error();
            } else {
                console.log();
            }
        } catch (error) {
            console.log(color('fail', 'Error occurred when generating epilogue'));
            console.log(error);
        }

        // Json
        var obj = {
            stats: self.stats,
            results: root
        };

        //process.stdout.write(jsonOutput);
        console.log(color('bright yellow', '  Export'));
        try {
            var dir = fspath.dirname(options.dest);
            var str = JSON.stringify(obj, null, 2);
            mkdirp.sync(dir);
            fs.writeFileSync(options.dest, str);
            console.log(color('green', '  Successfully written to %s'), options.dest);
        } catch (error) {
            console.log(color('fail', '  Failed to export to %s'), options.dest);
            console.log(error);
        }
    });
}<commit_msg>Added line break.<commit_after>// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Node dependencies

var fs = require('fs');
var fspath = require('path');
var mkdirp = require('mkdirp');
var util = require('util');

// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Mocha dependencies

var mocha = require('mocha');
var Base = mocha.reporters.Base,
    cursor = Base.cursor,
    color = Base.color;

// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Library dependencies

var ms = require('./ms');

module.exports = Reporter;

function Suite(suite) {
    if (suite) {
        this.title = suite.title;
        this.timeout = suite._timeout;
        this.slow = suite._slow;
    }
    this.suites = [];
    this.tests = [];
}

function Test(test) {
    this.title = test.title;
    this.fullTitle = test.fullTitle();
    this.timedOut = test.timedOut;
    this.duration = test.duration;
    this.speed = test.speed;
    this.file = test.file;
    this.state = test.state;
}

function top(array) {
    return array[array.length - 1];
}

/**
 * Initialize a new `JSON` reporter.
 *
 * @param {Runner} runner
 * @api public
 */

function Reporter(runner) {
    Base.call(this, runner);

    var self = this;
    var stats = this.stats;
    var indents = 0;
    var n = 0;

    var root = new Suite();
    var stack = [root];

    var options = {
        dest: './'
    };
    for (var p in options) {
        if (typeof process.env['mocha-json-spec-' + p] === 'string') {
            options[p] = process.env['mocha-json-spec-' + p];
        } else if (typeof process.env['MOCHA_JSON_SPEC_' + p.toUpperCase()] === 'string') {
            options[p] = process.env['MOCHA_JSON_SPEC_' + p.toUpperCase()];
        }
    }

    function indent() {
        return Array(indents).join('  ')
    }

    runner.on('start', function() {
        console.log();
    });

    runner.on('suite', function(suite) {
        ++indents;
        console.log(color('suite', '%s%s'), indent(), suite.title);
        if (suite.root) {
            return;
        }
        var parent = top(stack);
        var child = new Suite(suite);
        parent.suites.push(child);
        stack.push(child);
    });

    runner.on('suite end', function(suite) {
        --indents;
        if (1 == indents) {
            console.log();
        }
        stack.pop();
    });

    runner.on('test end', function(test) {
        top(stack).tests.push(new Test(test));
    });

    runner.on('pending', function(test) {
        var fmt = indent() + color('pending', '  - %s');
        console.log(fmt, test.title);
    });

    runner.on('pass', function(test) {
        if ('fast' == test.speed) {
            var fmt = indent() + color('checkmark', '  ' + Base.symbols.ok) + color('pass', ' %s ');
            cursor.CR();
            console.log(fmt, test.title);
        } else {
            var fmt = indent() + color('checkmark', '  ' + Base.symbols.ok) + color('pass', ' %s ') + color(test.speed, '(%dms)');
            cursor.CR();
            console.log(fmt, test.title, test.duration);
        }
        var current = top(stack);
    });

    runner.on('fail', function(test) {
        cursor.CR();
        console.log(indent() + color('fail', '  %d) %s'), ++n, test.title);
    });

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

        // Epilogue
        var fmt;
        try {
            console.log(color('bright yellow', '  Summary'));

            // Passes
            fmt = color('bright pass', ' ');
            fmt += color('green', ' %d passing');
            fmt += color('light', ' (%s)');
            console.log(fmt, stats.passes || 0, ms(stats.duration));

            // Pending
            if (stats.pending) {
                fmt = color('pending', ' ');
                fmt += color('pending', ' %d pending');
                console.log(fmt, stats.pending);
            }

            // Failures
            if (stats.failures) {
                fmt = color('fail', '  %d failing');
                console.error(fmt, stats.failures);
                Base.list(self.failures);
                console.error();
            } else {
                console.log();
            }
        } catch (error) {
            console.log(color('fail', 'Error occurred when generating epilogue'));
            console.log(error);
        }

        // Json
        var obj = {
            stats: self.stats,
            results: root
        };
        try {
            console.log(color('bright yellow', '  Export'));
            var dir = fspath.dirname(options.dest);
            var str = JSON.stringify(obj, null, 2);
            mkdirp.sync(dir);
            fs.writeFileSync(options.dest, str);
            console.log(color('green', '  Successfully written to %s'), options.dest);
        } catch (error) {
            console.log(color('fail', '  Failed to export to %s'), options.dest);
            console.log(error);
        }

        // Add extra space
        console.log();
    });
}<|endoftext|>