<commit_before>/** @babel */

import {CompositeDisposable, Disposable, Directory} from 'atom';
import Repository from './models/repository';
import FileSystemChangeObserver from './models/file-system-change-observer';
import WorkspaceChangeObserver from './models/workspace-change-observer';
import FilePatchController from './controllers/file-patch-controller';
import GitController from './controllers/git-controller';

import React from 'react';
import ReactDom from 'react-dom';

export default class GithubPackage {
  constructor(workspace, project, commandRegistry, notificationManager) {
    this.workspace = workspace;
    this.project = project;
    this.commandRegistry = commandRegistry;
    this.notificationManager = notificationManager;
    this.changeObserver = process.platform === 'linux'
      ? new WorkspaceChangeObserver(window, this.workspace)
      : new FileSystemChangeObserver();
    this.activeRepository = null;
    this.repositoriesByProjectDirectory = new Map();
    this.subscriptions = new CompositeDisposable();
    this.savedState = {};
  }

  async activate(state = {}) {
    this.savedState = state;
    this.subscriptions = new CompositeDisposable();
    await this.updateActiveRepository();
    await this.changeObserver.start();
    this.subscriptions.add(
      new Disposable(() => this.changeObserver.stop()),
      this.project.onDidChangePaths(this.didChangeProjectPaths.bind(this)),
      this.workspace.onDidChangeActivePaneItem(this.didChangeActivePaneItem.bind(this)),
      this.changeObserver.onDidChange(this.refreshActiveRepository.bind(this)),
    );
    if (state.activeRepositoryDir) {
      const dir = new Directory(state.activeRepositoryDir);
      const repo = await this.repositoryForProjectDirectory(dir);
      if (repo) {
        await this.setActiveRepository(repo);
      }
    }
    this.rerender();
  }

  serialize() {
    const activeRepository = this.getActiveRepository();
    return {
      activeRepositoryDir: activeRepository ? activeRepository.getWorkingDirectoryPath() : null,
      gitController: this.controller.serialize(),
    };
  }

  rerender() {
    if (!this.element) {
      this.element = document.createElement('div');
      this.subscriptions.add(new Disposable(() => {
        ReactDom.unmountComponentAtNode(this.element);
        delete this.element;
      }));
    }

    ReactDom.render(
      <GitController
        ref={c => { this.controller = c; }}
        workspace={this.workspace}
        project={this.project}
        commandRegistry={this.commandRegistry}
        notificationManager={this.notificationManager}
        repository={this.getActiveRepository()}
        statusBar={this.statusBar}
        savedState={this.savedState.gitController}
      />, this.element,
    );
  }

  deactivate() {
    this.subscriptions.dispose();
    if (this.destroyedRepositorySubscription) { this.destroyedRepositorySubscription.dispose(); }
  }

  consumeStatusBar(statusBar) {
    this.statusBar = statusBar;
    this.rerender();
  }

  async didChangeProjectPaths() {
    await this.updateActiveRepository();
    this.destroyRepositoriesForRemovedProjectFolders();
  }

  async didChangeActivePaneItem() {
    await this.updateActiveRepository();
  }

  async refreshActiveRepository() {
    if (this.activeRepository) {
      await this.activeRepository.refresh();
    }
  }

  getActiveRepository() {
    return this.activeRepository;
  }

  async updateActiveRepository() {
    let nextActiveRepository;

    const activeItem = this.workspace.getActivePaneItem();
    if (activeItem && typeof activeItem.getPath === 'function') {
      const projectDirectory = this.projectDirectoryForPath(activeItem.getPath());
      if (projectDirectory) {
        nextActiveRepository = await this.repositoryForProjectDirectory(projectDirectory);
      }
    } else {
      nextActiveRepository = this.activeRepository;
    }

    if (activeItem instanceof FilePatchController) {
      if (!activeItem.props.repository.isDestroyed()) {
        nextActiveRepository = activeItem.props.repository;
      }
    }

    if (nextActiveRepository && nextActiveRepository !== this.activeRepository) {
      await this.setActiveRepository(nextActiveRepository);
      if (this.destroyedRepositorySubscription) { this.destroyedRepositorySubscription.dispose(); }
      this.destroyedRepositorySubscription = nextActiveRepository.onDidDestroy(() => {
        if (nextActiveRepository === this.activeRepository) {
          this.setActiveRepository(null);
        }
        this.destroyedRepositorySubscription.dispose();
      });
    }

    if (!nextActiveRepository) {
      await this.setActiveRepository(null);
    }
  }

  async setActiveRepository(repository) {
    this.activeRepository = repository;
    await this.changeObserver.setActiveRepository(repository);
    this.rerender();
  }

  projectDirectoryForPath(filePath) {
    return this.project.getDirectories().find(d => d.getPath() === filePath || d.contains(filePath));
  }

  async repositoryForProjectDirectory(projectDirectory) {
    const projectDirectoryPath = projectDirectory.getPath();
    let repository = this.repositoriesByProjectDirectory.get(projectDirectoryPath);
    if (!repository) {
      repository = await Repository.open(projectDirectory);
      if (this.repositoriesByProjectDirectory.has(projectDirectoryPath)) {
        // Someone else found and set the repo in the cache while we were nabbing it.
        // Defer to that repo.
        repository.destroy();
        repository = this.repositoriesByProjectDirectory.get(projectDirectoryPath);
      } else if (repository) {
        this.repositoriesByProjectDirectory.set(projectDirectoryPath, repository);
      }
    }
    return repository;
  }

  repositoryForWorkdirPath(workdirPath) {
    return this.repositoryForProjectDirectory(this.projectDirectoryForPath(workdirPath));
  }

  destroyRepositoriesForRemovedProjectFolders() {
    const projectDirectoryPaths = this.project.getDirectories().map(dir => dir.getPath());
    for (const [projectDirectoryPath, repository] of this.repositoriesByProjectDirectory) {
      if (projectDirectoryPaths.indexOf(projectDirectoryPath) === -1) {
        repository.destroy();
        this.repositoriesByProjectDirectory.delete(projectDirectoryPath);
      }
    }
  }
}
<commit_msg>:art: rename variable projectDirectoryForPath<commit_after>/** @babel */

import {CompositeDisposable, Disposable, Directory} from 'atom';
import Repository from './models/repository';
import FileSystemChangeObserver from './models/file-system-change-observer';
import WorkspaceChangeObserver from './models/workspace-change-observer';
import FilePatchController from './controllers/file-patch-controller';
import GitController from './controllers/git-controller';

import React from 'react';
import ReactDom from 'react-dom';

export default class GithubPackage {
  constructor(workspace, project, commandRegistry, notificationManager) {
    this.workspace = workspace;
    this.project = project;
    this.commandRegistry = commandRegistry;
    this.notificationManager = notificationManager;
    this.changeObserver = process.platform === 'linux'
      ? new WorkspaceChangeObserver(window, this.workspace)
      : new FileSystemChangeObserver();
    this.activeRepository = null;
    this.repositoriesByProjectDirectory = new Map();
    this.subscriptions = new CompositeDisposable();
    this.savedState = {};
  }

  async activate(state = {}) {
    this.savedState = state;
    this.subscriptions = new CompositeDisposable();
    await this.updateActiveRepository();
    await this.changeObserver.start();
    this.subscriptions.add(
      new Disposable(() => this.changeObserver.stop()),
      this.project.onDidChangePaths(this.didChangeProjectPaths.bind(this)),
      this.workspace.onDidChangeActivePaneItem(this.didChangeActivePaneItem.bind(this)),
      this.changeObserver.onDidChange(this.refreshActiveRepository.bind(this)),
    );
    if (state.activeRepositoryDir) {
      const dir = new Directory(state.activeRepositoryDir);
      const repo = await this.repositoryForProjectDirectory(dir);
      if (repo) {
        await this.setActiveRepository(repo);
      }
    }
    this.rerender();
  }

  serialize() {
    const activeRepository = this.getActiveRepository();
    return {
      activeRepositoryDir: activeRepository ? activeRepository.getWorkingDirectoryPath() : null,
      gitController: this.controller.serialize(),
    };
  }

  rerender() {
    if (!this.element) {
      this.element = document.createElement('div');
      this.subscriptions.add(new Disposable(() => {
        ReactDom.unmountComponentAtNode(this.element);
        delete this.element;
      }));
    }

    ReactDom.render(
      <GitController
        ref={c => { this.controller = c; }}
        workspace={this.workspace}
        project={this.project}
        commandRegistry={this.commandRegistry}
        notificationManager={this.notificationManager}
        repository={this.getActiveRepository()}
        statusBar={this.statusBar}
        savedState={this.savedState.gitController}
      />, this.element,
    );
  }

  deactivate() {
    this.subscriptions.dispose();
    if (this.destroyedRepositorySubscription) { this.destroyedRepositorySubscription.dispose(); }
  }

  consumeStatusBar(statusBar) {
    this.statusBar = statusBar;
    this.rerender();
  }

  async didChangeProjectPaths() {
    await this.updateActiveRepository();
    this.destroyRepositoriesForRemovedProjectFolders();
  }

  async didChangeActivePaneItem() {
    await this.updateActiveRepository();
  }

  async refreshActiveRepository() {
    if (this.activeRepository) {
      await this.activeRepository.refresh();
    }
  }

  getActiveRepository() {
    return this.activeRepository;
  }

  async updateActiveRepository() {
    let nextActiveRepository;

    const activeItem = this.workspace.getActivePaneItem();
    if (activeItem && typeof activeItem.getPath === 'function') {
      const projectDirectory = this.projectDirectoryForItemPath(activeItem.getPath());
      if (projectDirectory) {
        nextActiveRepository = await this.repositoryForProjectDirectory(projectDirectory);
      }
    } else {
      nextActiveRepository = this.activeRepository;
    }

    if (activeItem instanceof FilePatchController) {
      if (!activeItem.props.repository.isDestroyed()) {
        nextActiveRepository = activeItem.props.repository;
      }
    }

    if (nextActiveRepository && nextActiveRepository !== this.activeRepository) {
      await this.setActiveRepository(nextActiveRepository);
      if (this.destroyedRepositorySubscription) { this.destroyedRepositorySubscription.dispose(); }
      this.destroyedRepositorySubscription = nextActiveRepository.onDidDestroy(() => {
        if (nextActiveRepository === this.activeRepository) {
          this.setActiveRepository(null);
        }
        this.destroyedRepositorySubscription.dispose();
      });
    }

    if (!nextActiveRepository) {
      await this.setActiveRepository(null);
    }
  }

  async setActiveRepository(repository) {
    this.activeRepository = repository;
    await this.changeObserver.setActiveRepository(repository);
    this.rerender();
  }

  projectDirectoryForItemPath(filePath) {
    return this.project.getDirectories().find(d => d.getPath() === filePath || d.contains(filePath));
  }

  async repositoryForProjectDirectory(projectDirectory) {
    const projectDirectoryPath = projectDirectory.getPath();
    let repository = this.repositoriesByProjectDirectory.get(projectDirectoryPath);
    if (!repository) {
      repository = await Repository.open(projectDirectory);
      if (this.repositoriesByProjectDirectory.has(projectDirectoryPath)) {
        // Someone else found and set the repo in the cache while we were nabbing it.
        // Defer to that repo.
        repository.destroy();
        repository = this.repositoriesByProjectDirectory.get(projectDirectoryPath);
      } else if (repository) {
        this.repositoriesByProjectDirectory.set(projectDirectoryPath, repository);
      }
    }
    return repository;
  }

  repositoryForWorkdirPath(workdirPath) {
    return this.repositoryForProjectDirectory(this.projectDirectoryForItemPath(workdirPath));
  }

  destroyRepositoriesForRemovedProjectFolders() {
    const projectDirectoryPaths = this.project.getDirectories().map(dir => dir.getPath());
    for (const [projectDirectoryPath, repository] of this.repositoriesByProjectDirectory) {
      if (projectDirectoryPaths.indexOf(projectDirectoryPath) === -1) {
        repository.destroy();
        this.repositoriesByProjectDirectory.delete(projectDirectoryPath);
      }
    }
  }
}
<|endoftext|>


<commit_before>var mapLimit = require('async-collection/map-limit')
var explain = require('explain-error')
var concat = require('concat-stream')
var pump = require('pump')
var path = require('path')

var critical = require('inline-critical-css')
var documentify = require('documentify')
var hyperstream = require('hyperstream')

var serverRender = require('./server-render')
var utils = require('./utils')
var ttyError = require('./tty-error')

var WRITE_CONCURRENCY = 3

module.exports = node

function node (state, createEdge) {
  var entry = utils.basefile(state.metadata.entry)
  var self = this

  serverRender(entry, function (err, render) {
    if (err) {
      err = ttyError('documents', entry, err)
      return self.emit('error', 'documents', entry, err)
    }
    var fonts = extractFonts(state.assets)
    var list = render.list

    mapLimit(list, WRITE_CONCURRENCY, iterator, function (err) {
      if (err) return self.emit(err)
      createEdge('list', Buffer.from(list.join(',')))
    })

    function iterator (route, done) {
      var res = render(route) // TODO: allow passing in state as second arg

      var description = '' // TODO: extract from manifest
      var language = res.language
      var title = res.title
      var body = res.body

      var html = head(body, language)
      var d = documentify(entry, html)
      d.transform(polyfillTransform)
      d.transform(scriptTransform, { hash: state.scripts.bundle.hash })
      d.transform(styleTransform, { hash: state.style.bundle.hash })
      d.transform(preloadTransform)
      d.transform(loadFontsTransform, { fonts: fonts })
      d.transform(manifestTransform)
      d.transform(viewportTransform)
      d.transform(descriptionTransform, { description: description })
      d.transform(themeColorTransform, { color: String(state.manifest.color.buffer) })
      d.transform(titleTransform, { title: title })
      // TODO: twitter
      // TODO: facebook
      // TODO: apple touch icons
      // TODO: favicons
      d.transform(criticalTransform, { css: state.style.bundle.buffer })

      if (state.metadata.reload) {
        d.transform(reloadTransform, { bundle: state.reload.bundle.buffer })
      }

      var source = d.bundle()

      pump(source, concat({ encoding: 'buffer' }, sink), function (err) {
        if (err) return done(explain(err, 'Error in documentify while operating on ' + route))
        done()
      })

      function sink (buf) {
        var name = route
        if (name === '/') name = 'index'
        name = name + '.html'
        createEdge(name, buf)
      }
    }
  })
}

function head (body, lang) {
  var dir = 'ltr'
  return `<!DOCTYPE html><html lang="${lang}" dir="${dir}"><head></head>${body}</html>`
}

function polyfillTransform () {
  var link = 'https://cdn.polyfill.io/v2/polyfill.min.js'
  var header = `<script src="${link}" defer></script>`
  return addToHead(header)
}

// Make sure that rel=preload works in Safari. This should be part of
// polyfill.io, but isn't yet for whatever reason. Uses both
// loadCss and cssRelPreload from
// https://github.com/filamentgroup/loadCSS/releases.
function preloadTransform () {
  var content = ';(function(a){"use strict";var b=function(b,c,d){function e(a){return h.body?a():void setTimeout(function(){e(a)})}function f(){i.addEventListener&&i.removeEventListener("load",f),i.media=d||"all"}var g,h=a.document,i=h.createElement("link");if(c)g=c;else{var j=(h.body||h.getElementsByTagName("head")[0]).childNodes;g=j[j.length-1]}var k=h.styleSheets;i.rel="stylesheet",i.href=b,i.media="only x",e(function(){g.parentNode.insertBefore(i,c?g:g.nextSibling)});var l=function(a){for(var b=i.href,c=k.length;c--;)if(k[c].href===b)return a();setTimeout(function(){l(a)})};return i.addEventListener&&i.addEventListener("load",f),i.onloadcssdefined=l,l(f),i};"undefined"!=typeof exports?exports.loadCSS=b:a.loadCSS=b})("undefined"!=typeof global?global:this);'
  content += ';(function(a){if(a.loadCSS){var b=loadCSS.relpreload={};if(b.support=function(){try{return a.document.createElement("link").relList.supports("preload")}catch(b){return!1}},b.poly=function(){for(var b=a.document.getElementsByTagName("link"),c=0;c<b.length;c++){var d=b[c];"preload"===d.rel&&"style"===d.getAttribute("as")&&(a.loadCSS(d.href,d,d.getAttribute("media")),d.rel=null)}},!b.support()){b.poly();var c=a.setInterval(b.poly,300);a.addEventListener&&a.addEventListener("load",function(){b.poly(),a.clearInterval(c)}),a.attachEvent&&a.attachEvent("onload",function(){a.clearInterval(c)})}}})(this);'
  var header = `<script>${content}</script>`
  return addToHead(header)
}

function scriptTransform (opts) {
  var hash = opts.hash
  var link = `/${hash}/bundle.js`
  var header = `<script src="${link}" defer></script>`
  return addToHead(header)
}

// TODO: make sure this works on browsers that don't support it.
function styleTransform (opts) {
  var hash = opts.hash
  var link = `/${hash}/bundle.css`
  var header = `<link rel="preload" as="style" href="${link}" onload="this.rel='stylesheet'">`
  return addToHead(header)
}

function loadFontsTransform (opts) {
  var header = opts.fonts.reduce(function (header, font) {
    if (!path.isAbsolute(font)) font = '/' + font
    return header + `<link rel="preload" as="font" crossorigin href="${font}">`
  }, '')
  return addToHead(header)
}

function manifestTransform () {
  var header = `
    <link rel="manifest" href="/manifest.json">
  `.replace(/\n +/g, '')
  return addToHead(header)
}

function viewportTransform () {
  var header = `
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
  `.replace(/\n +/g, '')
  return addToHead(header)
}

function descriptionTransform (opts) {
  var header = `
    <meta name="description" content=${opts.description}>
  `.replace(/\n +/g, '')
  return addToHead(header)
}

function themeColorTransform (opts) {
  var header = `
    <meta name="theme-color" content=${opts.color}>
  `.replace(/\n +/g, '')
  return addToHead(header)
}

function titleTransform (opts) {
  var header = `
    <title>${opts.title}</title>
  `.replace(/\n +/g, '')
  return addToHead(header)
}

function criticalTransform (opts) {
  return critical(String(opts.css))
}

function reloadTransform (opts) {
  var header = `
    <script>${opts.bundle}</script>
  `.replace(/\n +/g, '')
  return addToHead(header)
}

function addToHead (str) {
  return hyperstream({
    head: {
      _appendHtml: str
    }
  })
}

// Specific to the document node's layout
function extractFonts (state) {
  var list = String(state.list.buffer).split(',')

  var res = list.filter(function (font) {
    var extname = path.extname(font)

    return extname === '.woff' ||
      extname === '.woff2' ||
      extname === '.eot' ||
      extname === '.ttf'
  })

  return res
}
<commit_msg>fix document test (#261)<commit_after>var mapLimit = require('async-collection/map-limit')
var explain = require('explain-error')
var concat = require('concat-stream')
var pump = require('pump')
var path = require('path')

var critical = require('inline-critical-css')
var documentify = require('documentify')
var hyperstream = require('hyperstream')

var serverRender = require('./server-render')
var utils = require('./utils')
var ttyError = require('./tty-error')

var WRITE_CONCURRENCY = 3

module.exports = node

function node (state, createEdge) {
  var entry = utils.basefile(state.metadata.entry)
  var self = this

  serverRender(entry, function (err, render) {
    if (err) {
      err = ttyError('documents', entry, err)
      return self.emit('error', 'documents', entry, err)
    }
    var fonts = extractFonts(state.assets)
    var list = render.list

    mapLimit(list, WRITE_CONCURRENCY, iterator, function (err) {
      if (err) return self.emit(err)
      createEdge('list', Buffer.from(list.join(',')))
    })

    function iterator (route, done) {
      var res = render(route) // TODO: allow passing in state as second arg

      var description = '' // TODO: extract from manifest
      var language = res.language
      var title = res.title
      var body = res.body

      var html = head(body, language)
      var d = documentify(entry, html)
      d.transform(polyfillTransform)
      d.transform(scriptTransform, { hash: state.scripts.bundle.hash })
      d.transform(styleTransform, { hash: state.style.bundle.hash })
      d.transform(preloadTransform)
      d.transform(loadFontsTransform, { fonts: fonts })
      d.transform(manifestTransform)
      d.transform(viewportTransform)
      d.transform(descriptionTransform, { description: description })
      d.transform(themeColorTransform, { color: String(state.manifest.color.buffer) })
      d.transform(titleTransform, { title: title })
      // TODO: twitter
      // TODO: facebook
      // TODO: apple touch icons
      // TODO: favicons

      if (state.style.bundle.buffer.length) {
        d.transform(criticalTransform, { css: state.style.bundle.buffer })
      }

      if (state.metadata.reload) {
        d.transform(reloadTransform, { bundle: state.reload.bundle.buffer })
      }

      var source = d.bundle()

      pump(source, concat({ encoding: 'buffer' }, sink), function (err) {
        if (err) return done(explain(err, 'Error in documentify while operating on ' + route))
        done()
      })

      function sink (buf) {
        var name = route
        if (name === '/') name = 'index'
        name = name + '.html'
        createEdge(name, buf)
      }
    }
  })
}

function head (body, lang) {
  var dir = 'ltr'
  return `<!DOCTYPE html><html lang="${lang}" dir="${dir}"><head></head>${body}</html>`
}

function polyfillTransform () {
  var link = 'https://cdn.polyfill.io/v2/polyfill.min.js'
  var header = `<script src="${link}" defer></script>`
  return addToHead(header)
}

// Make sure that rel=preload works in Safari. This should be part of
// polyfill.io, but isn't yet for whatever reason. Uses both
// loadCss and cssRelPreload from
// https://github.com/filamentgroup/loadCSS/releases.
function preloadTransform () {
  var content = ';(function(a){"use strict";var b=function(b,c,d){function e(a){return h.body?a():void setTimeout(function(){e(a)})}function f(){i.addEventListener&&i.removeEventListener("load",f),i.media=d||"all"}var g,h=a.document,i=h.createElement("link");if(c)g=c;else{var j=(h.body||h.getElementsByTagName("head")[0]).childNodes;g=j[j.length-1]}var k=h.styleSheets;i.rel="stylesheet",i.href=b,i.media="only x",e(function(){g.parentNode.insertBefore(i,c?g:g.nextSibling)});var l=function(a){for(var b=i.href,c=k.length;c--;)if(k[c].href===b)return a();setTimeout(function(){l(a)})};return i.addEventListener&&i.addEventListener("load",f),i.onloadcssdefined=l,l(f),i};"undefined"!=typeof exports?exports.loadCSS=b:a.loadCSS=b})("undefined"!=typeof global?global:this);'
  content += ';(function(a){if(a.loadCSS){var b=loadCSS.relpreload={};if(b.support=function(){try{return a.document.createElement("link").relList.supports("preload")}catch(b){return!1}},b.poly=function(){for(var b=a.document.getElementsByTagName("link"),c=0;c<b.length;c++){var d=b[c];"preload"===d.rel&&"style"===d.getAttribute("as")&&(a.loadCSS(d.href,d,d.getAttribute("media")),d.rel=null)}},!b.support()){b.poly();var c=a.setInterval(b.poly,300);a.addEventListener&&a.addEventListener("load",function(){b.poly(),a.clearInterval(c)}),a.attachEvent&&a.attachEvent("onload",function(){a.clearInterval(c)})}}})(this);'
  var header = `<script>${content}</script>`
  return addToHead(header)
}

function scriptTransform (opts) {
  var hash = opts.hash
  var link = `/${hash}/bundle.js`
  var header = `<script src="${link}" defer></script>`
  return addToHead(header)
}

// TODO: make sure this works on browsers that don't support it.
function styleTransform (opts) {
  var hash = opts.hash
  var link = `/${hash}/bundle.css`
  var header = `<link rel="preload" as="style" href="${link}" onload="this.rel='stylesheet'">`
  return addToHead(header)
}

function loadFontsTransform (opts) {
  var header = opts.fonts.reduce(function (header, font) {
    if (!path.isAbsolute(font)) font = '/' + font
    return header + `<link rel="preload" as="font" crossorigin href="${font}">`
  }, '')
  return addToHead(header)
}

function manifestTransform () {
  var header = `
    <link rel="manifest" href="/manifest.json">
  `.replace(/\n +/g, '')
  return addToHead(header)
}

function viewportTransform () {
  var header = `
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
  `.replace(/\n +/g, '')
  return addToHead(header)
}

function descriptionTransform (opts) {
  var header = `
    <meta name="description" content=${opts.description}>
  `.replace(/\n +/g, '')
  return addToHead(header)
}

function themeColorTransform (opts) {
  var header = `
    <meta name="theme-color" content=${opts.color}>
  `.replace(/\n +/g, '')
  return addToHead(header)
}

function titleTransform (opts) {
  var header = `
    <title>${opts.title}</title>
  `.replace(/\n +/g, '')
  return addToHead(header)
}

function criticalTransform (opts) {
  return critical(String(opts.css))
}

function reloadTransform (opts) {
  var header = `
    <script>${opts.bundle}</script>
  `.replace(/\n +/g, '')
  return addToHead(header)
}

function addToHead (str) {
  return hyperstream({
    head: {
      _appendHtml: str
    }
  })
}

// Specific to the document node's layout
function extractFonts (state) {
  var list = String(state.list.buffer).split(',')

  var res = list.filter(function (font) {
    var extname = path.extname(font)

    return extname === '.woff' ||
      extname === '.woff2' ||
      extname === '.eot' ||
      extname === '.ttf'
  })

  return res
}
<|endoftext|>


<commit_before>/*
 * grunt-deploy-dump
 *
 * Copyright (c) 2014 Matthieu Lassalvy
 * Licensed under the MIT license.
 *
 * https://raw.githubusercontent.com/sequelize/sequelize-auto/master/lib/index.js
 * https://github.com/sequelize/sequelize/wiki/API-Reference-DataTypes
 * https://github.com/sequelize/sequelize/wiki/API-Reference
 * http://sequelizejs.com/docs/1.7.8/installation
 *
 */
/*jslint vars: true, plusplus: true, devel: true, nomen: true, indent: 4, maxerr: 50*/
/*global require, module, console, grunt*/
(function () {

    'use strict';

    var _ = require('lodash');

    var __privateMethods = {

        _headers: function (name) {

            var lines = [];
            lines.push('/*jslint vars: true, plusplus: true, devel: true, nomen: true, indent: 4, maxerr: 50*/');
            lines.push('/*global require, module */');
            lines.push('(function () {');
            lines.push('\'use strict\';');
            lines.push('/* imports */');
            lines.push('var _ = require(\'lodash\'),');
            lines.push('Class = require(\'smile/lib/core/class\');');
            lines.push('/* constructor */');
            lines.push('var ' + name + ' = Class.extend({');
            lines.push('_model: null,');
            lines.push('_sequelizer: null,');
            lines.push('constructor: function (sequelizer, model) {');
            lines.push('this._model = model;');
            lines.push('this._sequelizer = sequelizer;');
            lines.push('}');
            lines.push('});');
            lines.push('/* export */');
            lines.push('module.exports = ' + name + ';');
            lines.push('}());');
            return lines.join(this._.util.linefeed);

        }

    };

    var HelperBuilder = function (grunt) {
        this._ = grunt;
    };
    // @TODO remove lodash
    _.extend(HelperBuilder.prototype, __privateMethods);

    /**
     *
     */
    HelperBuilder.prototype.create = function (name) {
        return this._headers(name);
    };

    module.exports = HelperBuilder;

}());
<commit_msg>ajout du super<commit_after>/*
 * grunt-deploy-dump
 *
 * Copyright (c) 2014 Matthieu Lassalvy
 * Licensed under the MIT license.
 *
 * https://raw.githubusercontent.com/sequelize/sequelize-auto/master/lib/index.js
 * https://github.com/sequelize/sequelize/wiki/API-Reference-DataTypes
 * https://github.com/sequelize/sequelize/wiki/API-Reference
 * http://sequelizejs.com/docs/1.7.8/installation
 *
 */
/*jslint vars: true, plusplus: true, devel: true, nomen: true, indent: 4, maxerr: 50*/
/*global require, module, console, grunt*/
(function () {

    'use strict';

    var _ = require('lodash');

    var __privateMethods = {

        _headers: function (name) {

            var lines = [];
            lines.push('/*jslint vars: true, plusplus: true, devel: true, nomen: true, indent: 4, maxerr: 50*/');
            lines.push('/*global require, module */');
            lines.push('(function () {');
            lines.push('\'use strict\';');
            lines.push('/* imports */');
            lines.push('var _ = require(\'lodash\'),');
            lines.push('Class = require(\'smile/lib/core/class\');');
            lines.push('/* constructor */');
            lines.push('var ' + name + ' = Class.extend({');
            lines.push('_model: null,');
            lines.push('_sequelizer: null,');
            lines.push('constructor: function (sequelizer, model) {');
            lines.push('this._super();');
            lines.push('this._model = model;');
            lines.push('this._sequelizer = sequelizer;');
            lines.push('}');
            lines.push('});');
            lines.push('/* export */');
            lines.push('module.exports = ' + name + ';');
            lines.push('}());');
            return lines.join(this._.util.linefeed);

        }

    };

    var HelperBuilder = function (grunt) {
        this._ = grunt;
    };
    // @TODO remove lodash
    _.extend(HelperBuilder.prototype, __privateMethods);

    /**
     *
     */
    HelperBuilder.prototype.create = function (name) {
        return this._headers(name);
    };

    module.exports = HelperBuilder;

}());
<|endoftext|>


<commit_before>var logger = require( 'pelias-logger' ).get( 'openaddresses' );
var recordStream = require('./streams/recordStream');
var model = require( 'pelias-model' );
var peliasDbclient = require( 'pelias-dbclient' );
var isUSorCAHouseNumberZero = require( './streams/isUSorCAHouseNumberZero' );

/**
 * Import all OpenAddresses CSV files in a directory into Pelias elasticsearch.
 *
 * @param {array of string} files An array of the absolute file-paths to import.
 * @param {object} opts Options to configure the import. Supports the following
 *    keys:
 *
 *      deduplicate: Pass address object through `address-deduplicator-stream`
 *        to perform deduplication. See the documentation:
 *        https://github.com/pelias/address-deduplicator-stream
 *
 *      adminValues: Add admin values to each address object (since
 *        OpenAddresses doesn't contain any) using `admin-lookup`. See the
 *        documentation: https://github.com/pelias/admin-lookup
 */
function createFullImportPipeline( files, dirPath, deduplicatorStream, adminLookupStream, finalStream ){
  logger.info( 'Importing %s files.', files.length );

  finalStream = finalStream || peliasDbclient();

  recordStream.create(files, dirPath)
    .pipe(deduplicatorStream)
    .pipe(adminLookupStream)
    .pipe(isUSorCAHouseNumberZero.create())
    .pipe(model.createDocumentMapperStream())
    .pipe(finalStream);
}

module.exports = {
  create: createFullImportPipeline
};
<commit_msg>Tell jshint to ignore 5 parameter function<commit_after>var logger = require( 'pelias-logger' ).get( 'openaddresses' );
var recordStream = require('./streams/recordStream');
var model = require( 'pelias-model' );
var peliasDbclient = require( 'pelias-dbclient' );
var isUSorCAHouseNumberZero = require( './streams/isUSorCAHouseNumberZero' );

/**
 * Import all OpenAddresses CSV files in a directory into Pelias elasticsearch.
 *
 * @param {array of string} files An array of the absolute file-paths to import.
 * @param {object} opts Options to configure the import. Supports the following
 *    keys:
 *
 *      deduplicate: Pass address object through `address-deduplicator-stream`
 *        to perform deduplication. See the documentation:
 *        https://github.com/pelias/address-deduplicator-stream
 *
 *      adminValues: Add admin values to each address object (since
 *        OpenAddresses doesn't contain any) using `admin-lookup`. See the
 *        documentation: https://github.com/pelias/admin-lookup
 */
function createFullImportPipeline( files, dirPath, deduplicatorStream, adminLookupStream, finalStream ){ // jshint ignore:line
  logger.info( 'Importing %s files.', files.length );

  finalStream = finalStream || peliasDbclient();

  recordStream.create(files, dirPath)
    .pipe(deduplicatorStream)
    .pipe(adminLookupStream)
    .pipe(isUSorCAHouseNumberZero.create())
    .pipe(model.createDocumentMapperStream())
    .pipe(finalStream);
}

module.exports = {
  create: createFullImportPipeline
};
<|endoftext|>


<commit_before>var qs = require('querystring');
var iconv = require('iconv-lite');
var util = require('../util');
var extend = require('util')._extend;
var Transform = require('pipestream').Transform;
var WhistleTransform = util.WhistleTransform;
var ReplacePatternTransform = util.ReplacePatternTransform;
var ReplaceStringTransform = util.ReplaceStringTransform;
var FileWriterTransform = util.FileWriterTransform;
var MultiPartParser = util.MultiPartParser;
var MAX_REQ_SIZE = 256 * 1024;
var REQ_TYPE = {
		urlencoded: 'application/x-www-form-urlencoded',
		form: 'application/x-www-form-urlencoded',
		json: 'application/json',
		xml: 'text/xml',
		text: 'text/plain',
		upload: 'multipart/form-data',
		multipart: 'multipart/form-data',
		defaultType: 'application/octet-stream'
};

/**
 * 处理请求数据
 *
 * @param req：method、body、headers，top，bottom，speed、delay，charset,timeout
 * @param data
 */
function handleReq(req, data) {
	req.method = data.method || req.method;
	req.timeout = parseInt(data.timeout, 10);
	extend(req.headers, data.headers);
	if (typeof data.charset == 'string') {
		var type = req.headers['content-type'];
		var charset = '; charset=' + data.charset;
		if (typeof type == 'string') {
			req.headers['content-type'] = type.split(';')[0] + charset;
		} else {
			req.headers['content-type'] = charset;
		}
	} else {
		delete data.charset;
	}
	var method = req.method = typeof req.method != 'string' ? 'GET' : req.method.toUpperCase();
	if (!util.hasRequestBody(method)) {
		delete data.top;
		delete data.bottom;
		delete data.body;
	} else if (data.top || data.bottom || data.body) {
		delete req.headers['content-length'];
	}

	!util.isEmptyObject(data) && req.add(new WhistleTransform(data));
}

function handleCors(data, cors) {
	if (!cors) {
		return;
	}

	if (cors.origin !== undefined) {
		util.setHeader(data, 'origin', cors.origin);
	}

	if (cors.method !== undefined) {
		util.setHeader(data, 'access-control-request-method', cors.method);
	}

	if (cors.headers !== undefined) {
		util.setHeader(data, 'access-control-request-headers', cors.headers);
	}
}

function handleAuth(data, auth) {
	if (!auth) {
		return;
	}

	var basic = [];
	auth.username != null && basic.push(auth.username);
	auth.password != null && basic.push(auth.password);
	if (basic = basic.join(':')) {
		util.setHeader(data, 'authorization', 'Basic ' + new Buffer(basic).toString('base64'));
	}
}

function handleCookies(data, cookies, curCookies) {
	var list = cookies && Object.keys(cookies);
	if (list && list.length) {
		var result = {};
		if (curCookies && typeof curCookies == 'string') {
			curCookies.split(/;\s*/g)
					.forEach(function(cookie) {
						var index = cookie.indexOf('=');
						if (index == -1) {
							result[cookie] = null;
						} else {
							result[cookie.substring(0, index)] = cookie.substring(index + 1);
						}
					});
		}

		list.forEach(function(name) {
			var value = cookies[name];
			value = value && typeof value == 'object' ? value.value : value;
			result[util.encodeURIComponent(name)] = value ? util.encodeURIComponent(value) : value;
		});

		cookies = Object.keys(result).map(function(name) {
			var value = result[name];
			return name + (value == null ? '' : '=' + value);
		}).join('; ');
		util.setHeader(data, 'cookie', cookies);
	}
}

function handleParams(req, params) {
	var _params = params;
	if (!(params = params && qs.stringify(params))) {
		return;
	}

	if (!req.method || /^GET$/i.test(req.method)) {
		req.options.search = util.replaceUrlQueryString(req.options.search, params);
		req.options.path = util.replaceUrlQueryString(req.options.path, params);
		req.options.href = util.replaceUrlQueryString(req.options.href, params);
	} else if (util.isUrlEncoded(req)) {
		delete req.headers['content-length'];
		var transform = new Transform();
		var buffer, interrupt;
		transform._transform = function(chunk, encoding, callback) {
			if (chunk) {
				if (!interrupt) {
					buffer = buffer ? Buffer.concat([buffer, chunk]) : chunk;
					chunk = null;
					if (buffer.length > MAX_REQ_SIZE) {
						interrupt = true;
						chunk = buffer;
						buffer = null;
					}
				}
			} else if (buffer) {
				var body = buffer + '';
				var isGBK = body.indexOf('�') == -1;
				if (isGBK) {
					body = iconv.decode(buffer, 'GB18030');
					body = util.replaceQueryString(body, params);
					chunk = iconv.encode(body, 'GB18030');
				} else {
					chunk = new Buffer(body);
				}
				buffer = null;
			} else {
				chunk = new Buffer(params);
			}

			callback(null, chunk);
		};
		req.add(transform);
	} else if (util.isMultipart(req) &&
			/boundary=(?:"([^"]+)"|([^;]+))/i.test(req.headers['content-type'])) {
		delete req.headers['content-length'];
		var boundaryStr = '--' + (RegExp.$1 || RegExp.$2);
		var startBoundary = new Buffer(boundaryStr + '\r\n');
		var boundary = new Buffer('\r\n' + boundaryStr);
		var sepBoundary = new Buffer('\r\n' + boundaryStr + '\r\n');
		var endBoudary = new Buffer('\r\n' + boundaryStr + '--');
		var length = startBoundary.length;
		var sepLength = sepBoundary.length;
		var transform = new Transform();

		transform.parse = function(chunk) {
			var index, result, sep, data;
			while((index = util.indexOfList(chunk, boundary)) != -1
						&& ((sep = util.startWithList(chunk, sepBoundary, index))
								|| util.startWithList(chunk, endBoudary, index))) {
				data = this.parser.transform(chunk.slice(0, index));
				result = result && data ? Buffer.concat([result, data]) : (result || data);
				if (!sep) {
					data = util.toMultiparts(_params, boundaryStr);
					result = result ? Buffer.concat([result, data]) : data;
				}
				sep = sep ? sepBoundary : endBoudary;
				result = result ? Buffer.concat([result, sep]) : sep;
				chunk = chunk.slice(index + sepLength);
				this.parser = new MultiPartParser(_params);
			}

			var len = chunk.length;
			if (len >= sepLength) {
				var lastIndex = len - sepLength + 1;
				data = this.parser.transform(chunk.slice(0, lastIndex));
				chunk = chunk.slice(lastIndex);
				result = result && data ? Buffer.concat([result, data]) : (result || data);
			}
			this.buffer = chunk;

			return result;
		};
		transform._transform = function(chunk, encoding, callback) {
			if (this.badMultipart) {
				return callback(null, chunk);
			}

			var end;
			if (chunk) {
				chunk = this.buffer ? Buffer.concat([this.buffer, chunk]) : chunk;
			} else {
				end = true;
				chunk = this.buffer;
			}

			if (chunk) {
				this.buffer = null;
				if (!this.parser) {
					if (util.startWithList(chunk, startBoundary)) {
						this.parser = new MultiPartParser(_params);
						chunk = this.parse(chunk.slice(length));
						chunk = chunk ? Buffer.concat([startBoundary, chunk]) : startBoundary;
					} else if(end || chunk.length >= length) {
						this.badMultipart = true;
					} else {
						this.buffer = chunk;
						chunk = null;
					}
				} else {
					chunk = this.parse(chunk);
				}
			}

			if (end && this.buffer) {
				chunk = chunk ? Buffer.concat([chunk, this.buffer]) : this.buffer;
			}
			callback(null, chunk);
		};
		req.add(transform);
	}
}

function removeDisableProps(req) {
	var disable = req.disable;
	var headers = req.headers;

	if (disable.ua) {
		delete headers['user-agent'];
	}

	if (disable.cookie || disable.cookies ||
			disable.reqCookie || disable.reqCookies) {
		delete headers.cookie;
	}

	if (disable.referer) {
		delete headers.referer;
	}

	if (disable.ajax) {
		delete headers['x-requested-with'];
	}

	if (disable.cache) {
		util.disableReqCache(headers);
	}
}

function handleReplace(req, replacement) {
	if (!util.hasRequestBody(req) || !replacement) {
		return;
	}

	var type = req.headers['content-type'];
	type = util.isUrlEncoded(req) ? 'FORM' : util.getContentType(type);
	if (!type || type == 'IMG') {
		return;
	}

	Object.keys(replacement).forEach(function(pattern) {
		var value = replacement[pattern];
		if (util.isOriginalRegExp(pattern) && (pattern = util.toOriginalRegExp(pattern))) {
			req.addTextTransform(new ReplacePatternTransform(pattern, value));
		} else if (pattern) {
			req.addTextTransform(new ReplaceStringTransform(pattern, value));
		}
	});
}

module.exports = function(req, res, next) {
	var reqRules = req.rules;
	util.parseRuleJson([reqRules.req, reqRules.reqHeaders, reqRules.reqCookies,
	                    reqRules.auth, reqRules.params, reqRules.reqCors, reqRules.reqReplace],
			function(data, headers, cookies, auth, params, cors, replacement) {
		if (reqRules.head && reqRules.head.req) {
			data = extend(reqRules.head.req, data);
		}
		data = data || {};
		if (headers) {
			data.headers =  extend(data.headers || {}, headers);
		}

		if (data.headers) {
			data.headers = util.lowerCaseify(data.headers);
		}

		if (reqRules.method) {
			var method = util.getMatcherValue(reqRules.method);
			data.method = method;
		}

		if (reqRules.reqType) {
			var newType = util.getMatcherValue(reqRules.reqType).split(';');
			var type = newType[0];
			newType[0] = (!type || type.indexOf('/') != -1) ? type : (REQ_TYPE[type] || REQ_TYPE.defaultType);
			type = newType.join(';');
			if (type.indexOf(';') == -1) {
				var origType = req.headers['content-type'];
				if (typeof origType == 'string' && origType.indexOf(';') != -1) {
					origType = origType.split(';');
					origType[0] = type;
					type = origType.join(';');
				}
			}
			util.setHeader(data, 'content-type', type);
		}

		if (reqRules.reqCharset) {
			data.charset = util.getMatcherValue(reqRules.reqCharset);
		}

		if (reqRules.referer) {
			var referer = util.getMatcherValue(reqRules.referer);
			util.setHeader(data, 'referer', referer);
		}

		if (reqRules.accept) {
			var accept = util.getMatcherValue(reqRules.accept);
			util.setHeader(data, 'accept', accept);
		}

		if (reqRules.ua) {
			var ua = util.getMatcherValue(reqRules.ua);
			util.setHeader(data, 'user-agent', ua);
		}

		if (reqRules.etag) {
			var etag = util.getMatcherValue(reqRules.etag);
			util.setHeader(data, 'etag', etag);
		}

		var reqDelay = util.getMatcherValue(reqRules.reqDelay);
		reqDelay = reqDelay && parseInt(reqDelay, 10);
		if (reqDelay > 0) {
			data.delay = reqDelay;
		}

		var reqSpeed = util.getMatcherValue(reqRules.reqSpeed);
		reqSpeed = reqSpeed && parseFloat(reqSpeed);
		if (reqSpeed > 0) {
			data.speed = reqSpeed;
		}

		handleCookies(data, cookies, req.headers.cookie);
		handleAuth(data, auth);
		handleCors(data, cors);

		util.readInjectFiles(data, function(data) {
			util.getRuleValue([reqRules.reqBody, reqRules.reqPrepend, reqRules.reqAppend],
				function(reqBody, reqPrepend, reqAppend) {
					if (reqBody) {
						data.body = reqBody;
					}

					if (reqPrepend) {
						data.top = reqPrepend;
					}

					if (reqAppend) {
						data.append = reqAppend;
					}

					handleReq(req, data);
					handleParams(req, params);
					util.removeUnsupportsHeaders(req.headers);
					removeDisableProps(req);
					handleReplace(req, replacement);
					util.getFileWriters([util.hasRequestBody(req) ? util.getRuleFile(reqRules.reqWrite) : null, util.getRuleFile(reqRules.reqWriteRaw)], function(writer, rawWriter) {
						if (writer) {
							req.add(new FileWriterTransform(writer, req));
						}

						if (rawWriter) {
							req.add(new FileWriterTransform(rawWriter, req, true));
						}

						next();
					});
				});
		});
	});
};<commit_msg>fix: req.bottom instead of req.append<commit_after>var qs = require('querystring');
var iconv = require('iconv-lite');
var util = require('../util');
var extend = require('util')._extend;
var Transform = require('pipestream').Transform;
var WhistleTransform = util.WhistleTransform;
var ReplacePatternTransform = util.ReplacePatternTransform;
var ReplaceStringTransform = util.ReplaceStringTransform;
var FileWriterTransform = util.FileWriterTransform;
var MultiPartParser = util.MultiPartParser;
var MAX_REQ_SIZE = 256 * 1024;
var REQ_TYPE = {
		urlencoded: 'application/x-www-form-urlencoded',
		form: 'application/x-www-form-urlencoded',
		json: 'application/json',
		xml: 'text/xml',
		text: 'text/plain',
		upload: 'multipart/form-data',
		multipart: 'multipart/form-data',
		defaultType: 'application/octet-stream'
};

/**
 * 处理请求数据
 *
 * @param req：method、body、headers，top，bottom，speed、delay，charset,timeout
 * @param data
 */
function handleReq(req, data) {
	req.method = data.method || req.method;
	req.timeout = parseInt(data.timeout, 10);
	extend(req.headers, data.headers);
	if (typeof data.charset == 'string') {
		var type = req.headers['content-type'];
		var charset = '; charset=' + data.charset;
		if (typeof type == 'string') {
			req.headers['content-type'] = type.split(';')[0] + charset;
		} else {
			req.headers['content-type'] = charset;
		}
	} else {
		delete data.charset;
	}
	var method = req.method = typeof req.method != 'string' ? 'GET' : req.method.toUpperCase();
	if (!util.hasRequestBody(method)) {
		delete data.top;
		delete data.bottom;
		delete data.body;
	} else if (data.top || data.bottom || data.body) {
		delete req.headers['content-length'];
	}

	!util.isEmptyObject(data) && req.add(new WhistleTransform(data));
}

function handleCors(data, cors) {
	if (!cors) {
		return;
	}

	if (cors.origin !== undefined) {
		util.setHeader(data, 'origin', cors.origin);
	}

	if (cors.method !== undefined) {
		util.setHeader(data, 'access-control-request-method', cors.method);
	}

	if (cors.headers !== undefined) {
		util.setHeader(data, 'access-control-request-headers', cors.headers);
	}
}

function handleAuth(data, auth) {
	if (!auth) {
		return;
	}

	var basic = [];
	auth.username != null && basic.push(auth.username);
	auth.password != null && basic.push(auth.password);
	if (basic = basic.join(':')) {
		util.setHeader(data, 'authorization', 'Basic ' + new Buffer(basic).toString('base64'));
	}
}

function handleCookies(data, cookies, curCookies) {
	var list = cookies && Object.keys(cookies);
	if (list && list.length) {
		var result = {};
		if (curCookies && typeof curCookies == 'string') {
			curCookies.split(/;\s*/g)
					.forEach(function(cookie) {
						var index = cookie.indexOf('=');
						if (index == -1) {
							result[cookie] = null;
						} else {
							result[cookie.substring(0, index)] = cookie.substring(index + 1);
						}
					});
		}

		list.forEach(function(name) {
			var value = cookies[name];
			value = value && typeof value == 'object' ? value.value : value;
			result[util.encodeURIComponent(name)] = value ? util.encodeURIComponent(value) : value;
		});

		cookies = Object.keys(result).map(function(name) {
			var value = result[name];
			return name + (value == null ? '' : '=' + value);
		}).join('; ');
		util.setHeader(data, 'cookie', cookies);
	}
}

function handleParams(req, params) {
	var _params = params;
	if (!(params = params && qs.stringify(params))) {
		return;
	}

	if (!req.method || /^GET$/i.test(req.method)) {
		req.options.search = util.replaceUrlQueryString(req.options.search, params);
		req.options.path = util.replaceUrlQueryString(req.options.path, params);
		req.options.href = util.replaceUrlQueryString(req.options.href, params);
	} else if (util.isUrlEncoded(req)) {
		delete req.headers['content-length'];
		var transform = new Transform();
		var buffer, interrupt;
		transform._transform = function(chunk, encoding, callback) {
			if (chunk) {
				if (!interrupt) {
					buffer = buffer ? Buffer.concat([buffer, chunk]) : chunk;
					chunk = null;
					if (buffer.length > MAX_REQ_SIZE) {
						interrupt = true;
						chunk = buffer;
						buffer = null;
					}
				}
			} else if (buffer) {
				var body = buffer + '';
				var isGBK = body.indexOf('�') == -1;
				if (isGBK) {
					body = iconv.decode(buffer, 'GB18030');
					body = util.replaceQueryString(body, params);
					chunk = iconv.encode(body, 'GB18030');
				} else {
					chunk = new Buffer(body);
				}
				buffer = null;
			} else {
				chunk = new Buffer(params);
			}

			callback(null, chunk);
		};
		req.add(transform);
	} else if (util.isMultipart(req) &&
			/boundary=(?:"([^"]+)"|([^;]+))/i.test(req.headers['content-type'])) {
		delete req.headers['content-length'];
		var boundaryStr = '--' + (RegExp.$1 || RegExp.$2);
		var startBoundary = new Buffer(boundaryStr + '\r\n');
		var boundary = new Buffer('\r\n' + boundaryStr);
		var sepBoundary = new Buffer('\r\n' + boundaryStr + '\r\n');
		var endBoudary = new Buffer('\r\n' + boundaryStr + '--');
		var length = startBoundary.length;
		var sepLength = sepBoundary.length;
		var transform = new Transform();

		transform.parse = function(chunk) {
			var index, result, sep, data;
			while((index = util.indexOfList(chunk, boundary)) != -1
						&& ((sep = util.startWithList(chunk, sepBoundary, index))
								|| util.startWithList(chunk, endBoudary, index))) {
				data = this.parser.transform(chunk.slice(0, index));
				result = result && data ? Buffer.concat([result, data]) : (result || data);
				if (!sep) {
					data = util.toMultiparts(_params, boundaryStr);
					result = result ? Buffer.concat([result, data]) : data;
				}
				sep = sep ? sepBoundary : endBoudary;
				result = result ? Buffer.concat([result, sep]) : sep;
				chunk = chunk.slice(index + sepLength);
				this.parser = new MultiPartParser(_params);
			}

			var len = chunk.length;
			if (len >= sepLength) {
				var lastIndex = len - sepLength + 1;
				data = this.parser.transform(chunk.slice(0, lastIndex));
				chunk = chunk.slice(lastIndex);
				result = result && data ? Buffer.concat([result, data]) : (result || data);
			}
			this.buffer = chunk;

			return result;
		};
		transform._transform = function(chunk, encoding, callback) {
			if (this.badMultipart) {
				return callback(null, chunk);
			}

			var end;
			if (chunk) {
				chunk = this.buffer ? Buffer.concat([this.buffer, chunk]) : chunk;
			} else {
				end = true;
				chunk = this.buffer;
			}

			if (chunk) {
				this.buffer = null;
				if (!this.parser) {
					if (util.startWithList(chunk, startBoundary)) {
						this.parser = new MultiPartParser(_params);
						chunk = this.parse(chunk.slice(length));
						chunk = chunk ? Buffer.concat([startBoundary, chunk]) : startBoundary;
					} else if(end || chunk.length >= length) {
						this.badMultipart = true;
					} else {
						this.buffer = chunk;
						chunk = null;
					}
				} else {
					chunk = this.parse(chunk);
				}
			}

			if (end && this.buffer) {
				chunk = chunk ? Buffer.concat([chunk, this.buffer]) : this.buffer;
			}
			callback(null, chunk);
		};
		req.add(transform);
	}
}

function removeDisableProps(req) {
	var disable = req.disable;
	var headers = req.headers;

	if (disable.ua) {
		delete headers['user-agent'];
	}

	if (disable.cookie || disable.cookies ||
			disable.reqCookie || disable.reqCookies) {
		delete headers.cookie;
	}

	if (disable.referer) {
		delete headers.referer;
	}

	if (disable.ajax) {
		delete headers['x-requested-with'];
	}

	if (disable.cache) {
		util.disableReqCache(headers);
	}
}

function handleReplace(req, replacement) {
	if (!util.hasRequestBody(req) || !replacement) {
		return;
	}

	var type = req.headers['content-type'];
	type = util.isUrlEncoded(req) ? 'FORM' : util.getContentType(type);
	if (!type || type == 'IMG') {
		return;
	}

	Object.keys(replacement).forEach(function(pattern) {
		var value = replacement[pattern];
		if (util.isOriginalRegExp(pattern) && (pattern = util.toOriginalRegExp(pattern))) {
			req.addTextTransform(new ReplacePatternTransform(pattern, value));
		} else if (pattern) {
			req.addTextTransform(new ReplaceStringTransform(pattern, value));
		}
	});
}

module.exports = function(req, res, next) {
	var reqRules = req.rules;
	util.parseRuleJson([reqRules.req, reqRules.reqHeaders, reqRules.reqCookies,
	                    reqRules.auth, reqRules.params, reqRules.reqCors, reqRules.reqReplace],
			function(data, headers, cookies, auth, params, cors, replacement) {
		if (reqRules.head && reqRules.head.req) {
			data = extend(reqRules.head.req, data);
		}
		data = data || {};
		if (headers) {
			data.headers =  extend(data.headers || {}, headers);
		}

		if (data.headers) {
			data.headers = util.lowerCaseify(data.headers);
		}

		if (reqRules.method) {
			var method = util.getMatcherValue(reqRules.method);
			data.method = method;
		}

		if (reqRules.reqType) {
			var newType = util.getMatcherValue(reqRules.reqType).split(';');
			var type = newType[0];
			newType[0] = (!type || type.indexOf('/') != -1) ? type : (REQ_TYPE[type] || REQ_TYPE.defaultType);
			type = newType.join(';');
			if (type.indexOf(';') == -1) {
				var origType = req.headers['content-type'];
				if (typeof origType == 'string' && origType.indexOf(';') != -1) {
					origType = origType.split(';');
					origType[0] = type;
					type = origType.join(';');
				}
			}
			util.setHeader(data, 'content-type', type);
		}

		if (reqRules.reqCharset) {
			data.charset = util.getMatcherValue(reqRules.reqCharset);
		}

		if (reqRules.referer) {
			var referer = util.getMatcherValue(reqRules.referer);
			util.setHeader(data, 'referer', referer);
		}

		if (reqRules.accept) {
			var accept = util.getMatcherValue(reqRules.accept);
			util.setHeader(data, 'accept', accept);
		}

		if (reqRules.ua) {
			var ua = util.getMatcherValue(reqRules.ua);
			util.setHeader(data, 'user-agent', ua);
		}

		if (reqRules.etag) {
			var etag = util.getMatcherValue(reqRules.etag);
			util.setHeader(data, 'etag', etag);
		}

		var reqDelay = util.getMatcherValue(reqRules.reqDelay);
		reqDelay = reqDelay && parseInt(reqDelay, 10);
		if (reqDelay > 0) {
			data.delay = reqDelay;
		}

		var reqSpeed = util.getMatcherValue(reqRules.reqSpeed);
		reqSpeed = reqSpeed && parseFloat(reqSpeed);
		if (reqSpeed > 0) {
			data.speed = reqSpeed;
		}

		handleCookies(data, cookies, req.headers.cookie);
		handleAuth(data, auth);
		handleCors(data, cors);

		util.readInjectFiles(data, function(data) {
			util.getRuleValue([reqRules.reqBody, reqRules.reqPrepend, reqRules.reqAppend],
				function(reqBody, reqPrepend, reqAppend) {
					if (reqBody) {
						data.body = reqBody;
					}

					if (reqPrepend) {
						data.top = reqPrepend;
					}

					if (reqAppend) {
						data.bottom = reqAppend;
					}

					handleReq(req, data);
					handleParams(req, params);
					util.removeUnsupportsHeaders(req.headers);
					removeDisableProps(req);
					handleReplace(req, replacement);
					util.getFileWriters([util.hasRequestBody(req) ? util.getRuleFile(reqRules.reqWrite) : null, util.getRuleFile(reqRules.reqWriteRaw)], function(writer, rawWriter) {
						if (writer) {
							req.add(new FileWriterTransform(writer, req));
						}

						if (rawWriter) {
							req.add(new FileWriterTransform(rawWriter, req, true));
						}

						next();
					});
				});
		});
	});
};<|endoftext|>


<commit_before>var util = require('../../util');
var extend = require('util')._extend;
var WhistleTransform = util.WhistleTransform;

function removeUnsupportsHeaders(headers) {//只保留支持的zip格式：gzip、deflate
	if (!headers || !headers['accept-encoding']) {
		return;
	}
	var list = headers['accept-encoding'].split(/\s*,\s*/g);
	var acceptEncoding = [];
	for (var i = 0, len = list.length; i < len; i++) {
		var ae = list[i].toLowerCase();
		if (ae && ae == 'gzip') {
			acceptEncoding.push(ae);
		}
	}

	if (acceptEncoding = acceptEncoding.join(', ')) {
		headers['accept-encoding'] = acceptEncoding;
	} else {
		delete headers['accept-encoding'];
	}
}

/**
 * 处理请求数据
 *
 * @param req：method、body、headers，top，bottom，speed、delay，charset,timeout
 * @param data
 */
function handleReq(req, data) {
	if (!data) {
		return;
	}
	data.headers = util.lowerCaseify(data.headers);
	req.method = data.method || req.method;
	req.timeout = parseInt(data.timeout, 10);
	extend(req.headers, data.headers);
	if (data.top || data.bottom || data.body) {
		delete req.headers['content-length'];
	}
	req.add(new WhistleTransform(data));
}

module.exports = function(req, res, next) {
	util.parseRuleToJson(req.rules.req,
			function(err, data) {
		if (req.rules.head && req.rules.head.req) {
			data = extend(req.rules.head.req, data);
		}

		handleReq(req, data);
		removeUnsupportsHeaders(req.headers);
		next();
	});
};<commit_msg>removeUnsupportsHeaders(req.headers);<commit_after>var util = require('../../util');
var extend = require('util')._extend;
var WhistleTransform = util.WhistleTransform;

function removeUnsupportsHeaders(headers) {//只保留支持的zip格式：gzip、deflate
	if (!headers || !headers['accept-encoding']) {
		return;
	}
	var list = headers['accept-encoding'].split(/\s*,\s*/g);
	var acceptEncoding = [];
	for (var i = 0, len = list.length; i < len; i++) {
		var ae = list[i].toLowerCase();
		if (ae && ae == 'gzip') {
			acceptEncoding.push(ae);
		}
	}

	if (acceptEncoding = acceptEncoding.join(', ')) {
		headers['accept-encoding'] = acceptEncoding;
	} else {
		delete headers['accept-encoding'];
	}
}

/**
 * 处理请求数据
 *
 * @param req：method、body、headers，top，bottom，speed、delay，charset,timeout
 * @param data
 */
function handleReq(req, data) {
	if (!data) {
		return;
	}
	data.headers = util.lowerCaseify(data.headers);
	req.method = data.method || req.method;
	req.timeout = parseInt(data.timeout, 10);
	extend(req.headers, data.headers);
	if (data.top || data.bottom || data.body) {
		removeUnsupportsHeaders(req.headers);
		delete req.headers['content-length'];
	}
	req.add(new WhistleTransform(data));
}

module.exports = function(req, res, next) {
	util.parseRuleToJson(req.rules.req,
			function(err, data) {
		if (req.rules.head && req.rules.head.req) {
			data = extend(req.rules.head.req, data);
		}

		handleReq(req, data);
		next();
	});
};<|endoftext|>


<commit_before>/**
 * Returns true if value is +0, false otherwise
 * @param {Number} value Value to be checked for +0.
 */

function isPositiveZero(value) {
  // TODO: Your code goes here
}

module.exports = isPositiveZero;<commit_msg>implement isPositiveZero method #134<commit_after>/**
 * Returns true if value is +0, false otherwise
 * @param {Number} value Value to be checked for +0.
 */

function isPositiveZero(value) {
  return 1 / value === Infinity;
}

module.exports = isPositiveZero;<|endoftext|>


<commit_before>var readFixtures = function() {
  return jasmine.getFixtures().proxyCallTo_('read', arguments)
}

var preloadFixtures = function() {
  jasmine.getFixtures().proxyCallTo_('preload', arguments)
}

var loadFixtures = function() {
  jasmine.getFixtures().proxyCallTo_('load', arguments)
}

var appendLoadFixtures = function() {
  jasmine.getFixtures().proxyCallTo_('appendLoad', arguments)
}

var setFixtures = function(html) {
  jasmine.getFixtures().proxyCallTo_('set', arguments)
}

var appendSetFixtures = function() {
  jasmine.getFixtures().proxyCallTo_('appendSet', arguments)
}

var sandbox = function(attributes) {
  return jasmine.getFixtures().sandbox(attributes)
}

var spyOnEvent = function(selector, eventName) {
  return jasmine.JQuery.events.spyOn(selector, eventName)
}

var preloadStyleFixtures = function() {
  jasmine.getStyleFixtures().proxyCallTo_('preload', arguments)
}

var loadStyleFixtures = function() {
  jasmine.getStyleFixtures().proxyCallTo_('load', arguments)
}

var appendLoadStyleFixtures = function() {
  jasmine.getStyleFixtures().proxyCallTo_('appendLoad', arguments)
}

var setStyleFixtures = function(html) {
  jasmine.getStyleFixtures().proxyCallTo_('set', arguments)
}

var appendSetStyleFixtures = function(html) {
  jasmine.getStyleFixtures().proxyCallTo_('appendSet', arguments)
}

var loadJSONFixtures = function() {
  return jasmine.getJSONFixtures().proxyCallTo_('load', arguments)
}

var getJSONFixture = function(url) {
  return jasmine.getJSONFixtures().proxyCallTo_('read', arguments)[url]
}

jasmine.spiedEventsKey = function (selector, eventName) {
  return [$(selector).selector, eventName].toString()
}

jasmine.getFixtures = function() {
  return jasmine.currentFixtures_ = jasmine.currentFixtures_ || new jasmine.Fixtures()
}

jasmine.getStyleFixtures = function() {
  return jasmine.currentStyleFixtures_ = jasmine.currentStyleFixtures_ || new jasmine.StyleFixtures()
}

jasmine.Fixtures = function() {
  this.containerId = 'jasmine-fixtures'
  this.fixturesCache_ = {}
  this.fixturesPath = 'spec/javascripts/fixtures'
}

jasmine.Fixtures.prototype.set = function(html) {
  this.cleanUp()
  this.createContainer_(html)
}

jasmine.Fixtures.prototype.appendSet= function(html) {
  this.addToContainer_(html)
}

jasmine.Fixtures.prototype.preload = function() {
  this.read.apply(this, arguments)
}

jasmine.Fixtures.prototype.load = function() {
  this.cleanUp()
  this.createContainer_(this.read.apply(this, arguments))
}

jasmine.Fixtures.prototype.appendLoad = function() {
  this.addToContainer_(this.read.apply(this, arguments))
}

jasmine.Fixtures.prototype.read = function() {
  var htmlChunks = []

  var fixtureUrls = arguments
  for(var urlCount = fixtureUrls.length, urlIndex = 0; urlIndex < urlCount; urlIndex++) {
    htmlChunks.push(this.getFixtureHtml_(fixtureUrls[urlIndex]))
  }

  return htmlChunks.join('')
}

jasmine.Fixtures.prototype.clearCache = function() {
  this.fixturesCache_ = {}
}

jasmine.Fixtures.prototype.cleanUp = function() {
  jQuery('#' + this.containerId).remove()
}

jasmine.Fixtures.prototype.sandbox = function(attributes) {
  var attributesToSet = attributes || {}
  return jQuery('
').attr(attributesToSet)
}

jasmine.Fixtures.prototype.createContainer_ = function(html) {
  var container
  if(html instanceof jQuery) {
    container = jQuery('
')
    container.html(html)
  } else {
    container = '
' + html + '
'
  }
  jQuery('body').append(container)
}

jasmine.Fixtures.prototype.addToContainer_ = function(html){
  var container = jQuery('body').find('#'+this.containerId).append(html)
  if(!container.length){
    this.createContainer_(html)
  }
}

jasmine.Fixtures.prototype.getFixtureHtml_ = function(url) {
  if (typeof this.fixturesCache_[url] === 'undefined') {
    this.loadFixtureIntoCache_(url)
  }
  return this.fixturesCache_[url]
}

jasmine.Fixtures.prototype.loadFixtureIntoCache_ = function(relativeUrl) {
  var url = this.makeFixtureUrl_(relativeUrl)
  var request = jQuery.ajax({
    type: "GET",
    url: url + "?" + new Date().getTime(),
    async: false
  })
  this.fixturesCache_[relativeUrl] = request.responseText
}

jasmine.Fixtures.prototype.makeFixtureUrl_ = function(relativeUrl){
  return this.fixturesPath.match('/$') ? this.fixturesPath + relativeUrl : this.fixturesPath + '/' + relativeUrl
}

jasmine.Fixtures.prototype.proxyCallTo_ = function(methodName, passedArguments) {
  return this[methodName].apply(this, passedArguments)
}

jasmine.StyleFixtures = function() {
  this.fixturesCache_ = {}
  this.fixturesNodes_ = []
  this.fixturesPath = 'spec/javascripts/fixtures'
}

jasmine.StyleFixtures.prototype.set = function(css) {
  this.cleanUp()
  this.createStyle_(css)
}

jasmine.StyleFixtures.prototype.appendSet = function(css) {
  this.createStyle_(css)
}

jasmine.StyleFixtures.prototype.preload = function() {
  this.read_.apply(this, arguments)
}

jasmine.StyleFixtures.prototype.load = function() {
  this.cleanUp()
  this.createStyle_(this.read_.apply(this, arguments))
}

jasmine.StyleFixtures.prototype.appendLoad = function() {
  this.createStyle_(this.read_.apply(this, arguments))
}

jasmine.StyleFixtures.prototype.cleanUp = function() {
  while(this.fixturesNodes_.length) {
    this.fixturesNodes_.pop().remove()
  }
}

jasmine.StyleFixtures.prototype.createStyle_ = function(html) {
  var styleText = $('

').html(html).text()

  var style = jQuery('')

  this.fixturesNodes_.push(style)

  jQuery('head').append(style)
}

jasmine.StyleFixtures.prototype.clearCache = jasmine.Fixtures.prototype.clearCache

jasmine.StyleFixtures.prototype.read_ = jasmine.Fixtures.prototype.read

jasmine.StyleFixtures.prototype.getFixtureHtml_ = jasmine.Fixtures.prototype.getFixtureHtml_

jasmine.StyleFixtures.prototype.loadFixtureIntoCache_ = jasmine.Fixtures.prototype.loadFixtureIntoCache_

jasmine.StyleFixtures.prototype.makeFixtureUrl_ = jasmine.Fixtures.prototype.makeFixtureUrl_

jasmine.StyleFixtures.prototype.proxyCallTo_ = jasmine.Fixtures.prototype.proxyCallTo_

/** jasmine json fixtures */

jasmine.getJSONFixtures = function() {
  return jasmine.currentJSONFixtures_ = jasmine.currentJSONFixtures_ || new jasmine.JSONFixtures()
}

jasmine.JSONFixtures = function() {
  this.fixturesCache_ = {}
  this.fixturesPath = 'spec/javascripts/fixtures/json'
}

jasmine.JSONFixtures.prototype.load = function() {
  this.read.apply(this, arguments)
  return this.fixturesCache_
}

jasmine.JSONFixtures.prototype.read = function() {
  var fixtureUrls = arguments
  for(var urlCount = fixtureUrls.length, urlIndex = 0; urlIndex < urlCount; urlIndex++) {
    this.getFixtureData_(fixtureUrls[urlIndex])
  }
  return this.fixturesCache_
}

jasmine.JSONFixtures.prototype.clearCache = function() {
  this.fixturesCache_ = {}
}

jasmine.JSONFixtures.prototype.getFixtureData_ = function(url) {
  this.loadFixtureIntoCache_(url)
  return this.fixturesCache_[url]
}

jasmine.JSONFixtures.prototype.loadFixtureIntoCache_ = function(relativeUrl) {
  var self = this
  var url = this.fixturesPath.match('/$') ? this.fixturesPath + relativeUrl : this.fixturesPath + '/' + relativeUrl
  jQuery.ajax({
    async: false, // must be synchronous to guarantee that no tests are run before fixture is loaded
    cache: false,
    dataType: 'json',
    url: url,
    success: function(data) {
      self.fixturesCache_[relativeUrl] = data
    },
    error: function(jqXHR, status, errorThrown) {
        throw Error('JSONFixture could not be loaded: ' + url + ' (status: ' + status + ', message: ' + errorThrown.message + ')')
    }
  })
}

jasmine.JSONFixtures.prototype.proxyCallTo_ = function(methodName, passedArguments) {
  return this[methodName].apply(this, passedArguments)
}

jasmine.JQuery = function() {}

jasmine.JQuery.browserTagCaseIndependentHtml = function(html) {
  return jQuery('
').append(html).html()
}

jasmine.JQuery.elementToString = function(element) {
  var domEl = $(element).get(0)
  if (domEl == undefined || domEl.cloneNode)
    return jQuery('
').append($(element).clone()).html()
  else
    return element.toString()
}

jasmine.JQuery.matchersClass = {}

!function(namespace) {
  var data = {
    spiedEvents: {},
    handlers:    []
  }

  namespace.events = {
    spyOn: function(selector, eventName) {
      var handler = function(e) {
        data.spiedEvents[jasmine.spiedEventsKey(selector, eventName)] = e
      }
      jQuery(selector).bind(eventName, handler)
      data.handlers.push(handler)
      return {
        selector: selector,
        eventName: eventName,
        handler: handler,
        reset: function(){
          delete data.spiedEvents[jasmine.spiedEventsKey(selector, eventName)]
        }
      }
    },

    wasTriggered: function(selector, eventName) {
      return !!(data.spiedEvents[jasmine.spiedEventsKey(selector, eventName)])
    },

    wasPrevented: function(selector, eventName) {
      return data.spiedEvents[jasmine.spiedEventsKey(selector, eventName)].isDefaultPrevented()
    },

    cleanUp: function() {
      data.spiedEvents = {}
      data.handlers    = []
    }
  }
}(jasmine.JQuery)

!function(){
  var jQueryMatchers = {
    toHaveClass: function(className) {
      return this.actual.hasClass(className)
    },

    toHaveCss: function(css){
      for (var prop in css){
        if (this.actual.css(prop) !== css[prop]) return false
      }
      return true
    },

    toBeVisible: function() {
      return this.actual.is(':visible')
    },

    toBeHidden: function() {
      return this.actual.is(':hidden')
    },

    toBeSelected: function() {
      return this.actual.is(':selected')
    },

    toBeChecked: function() {
      return this.actual.is(':checked')
    },

    toBeEmpty: function() {
      return this.actual.is(':empty')
    },

    toExist: function() {
      return $(document).find(this.actual).length
    },

    toHaveAttr: function(attributeName, expectedAttributeValue) {
      return hasProperty(this.actual.attr(attributeName), expectedAttributeValue)
    },

    toHaveProp: function(propertyName, expectedPropertyValue) {
      return hasProperty(this.actual.prop(propertyName), expectedPropertyValue)
    },

    toHaveId: function(id) {
      return this.actual.attr('id') == id
    },

    toHaveHtml: function(html) {
      return this.actual.html() == jasmine.JQuery.browserTagCaseIndependentHtml(html)
    },

    toContainHtml: function(html){
      var actualHtml = this.actual.html()
      var expectedHtml = jasmine.JQuery.browserTagCaseIndependentHtml(html)
      return (actualHtml.indexOf(expectedHtml) >= 0)
    },

    toHaveText: function(text) {
      var trimmedText = $.trim(this.actual.text())
      if (text && jQuery.isFunction(text.test)) {
        return text.test(trimmedText)
      } else {
        return trimmedText == text
      }
    },

    toHaveValue: function(value) {
      return this.actual.val() == value
    },

    toHaveData: function(key, expectedValue) {
      return hasProperty(this.actual.data(key), expectedValue)
    },

    toBe: function(selector) {
      return this.actual.is(selector)
    },

    toContain: function(selector) {
      return this.actual.find(selector).length
    },

    toBeDisabled: function(selector){
      return this.actual.is(':disabled')
    },

    toBeFocused: function(selector) {
      return this.actual.is(':focus')
    },

    toHandle: function(event) {

      var events = $._data(this.actual.get(0), "events")

      if(!events || !event || typeof event !== "string") {
        return false
      }

      var namespaces = event.split(".")
      var eventType = namespaces.shift()
      var sortedNamespaces = namespaces.slice(0).sort()
      var namespaceRegExp = new RegExp("(^|\\.)" + sortedNamespaces.join("\\.(?:.*\\.)?") + "(\\.|$)")

      if(events[eventType] && namespaces.length) {
        for(var i = 0; i < events[eventType].length; i++) {
          var namespace = events[eventType][i].namespace
          if(namespaceRegExp.test(namespace)) {
            return true
          }
        }
      } else {
        return events[eventType] && events[eventType].length > 0
      }
    },

    // tests the existence of a specific event binding + handler
    toHandleWith: function(eventName, eventHandler) {
      var stack = $._data(this.actual.get(0), "events")[eventName]
      for (var i = 0; i < stack.length; i++) {
        if (stack[i].handler == eventHandler) return true
      }
      return false
    }
  }

  var hasProperty = function(actualValue, expectedValue) {
    if (expectedValue === undefined) return actualValue !== undefined
    return actualValue == expectedValue
  }

  var bindMatcher = function(methodName) {
    var builtInMatcher = jasmine.Matchers.prototype[methodName]

    jasmine.JQuery.matchersClass[methodName] = function() {
      if (this.actual
        && (this.actual instanceof jQuery
          || jasmine.isDomNode(this.actual))) {
            this.actual = $(this.actual)
            var result = jQueryMatchers[methodName].apply(this, arguments)
            var element
            if (this.actual.get && (element = this.actual.get()[0]) && !$.isWindow(element) && element.tagName !== "HTML")
              this.actual = jasmine.JQuery.elementToString(this.actual)
            return result
          }

          if (builtInMatcher) {
            return builtInMatcher.apply(this, arguments)
          }

          return false
    }
  }

  for(var methodName in jQueryMatchers) {
    bindMatcher(methodName)
  }
}()

beforeEach(function() {
  this.addMatchers(jasmine.JQuery.matchersClass)
  this.addMatchers({
    toHaveBeenTriggeredOn: function(selector) {
      this.message = function() {
        return [
          "Expected event " + this.actual + " to have been triggered on " + selector,
          "Expected event " + this.actual + " not to have been triggered on " + selector
        ]
      }
      return jasmine.JQuery.events.wasTriggered(selector, this.actual)
    }
  })
  this.addMatchers({
    toHaveBeenTriggered: function(){
      var eventName = this.actual.eventName,
          selector = this.actual.selector
      this.message = function() {
        return [
          "Expected event " + eventName + " to have been triggered on " + selector,
          "Expected event " + eventName + " not to have been triggered on " + selector
        ]
      }
      return jasmine.JQuery.events.wasTriggered(selector, eventName)
     }
  })
  this.addMatchers({
    toHaveBeenPreventedOn: function(selector) {
      this.message = function() {
        return [
          "Expected event " + this.actual + " to have been prevented on " + selector,
          "Expected event " + this.actual + " not to have been prevented on " + selector
        ]
      }
      return jasmine.JQuery.events.wasPrevented(selector, this.actual)
    }
  })
  this.addMatchers({
    toHaveBeenPrevented: function() {
      var eventName = this.actual.eventName,
          selector = this.actual.selector
      this.message = function() {
        return [
          "Expected event " + eventName + " to have been prevented on " + selector,
          "Expected event " + eventName + " not to have been prevented on " + selector
        ]
      }
      return jasmine.JQuery.events.wasPrevented(selector, eventName)
    }
  })
})

afterEach(function() {
  jasmine.getFixtures().cleanUp()
  jasmine.getStyleFixtures().cleanUp()
  jasmine.JQuery.events.cleanUp()
})
<commit_msg>s/jQuery\>/$/g<commit_after>var readFixtures = function() {
  return jasmine.getFixtures().proxyCallTo_('read', arguments)
}

var preloadFixtures = function() {
  jasmine.getFixtures().proxyCallTo_('preload', arguments)
}

var loadFixtures = function() {
  jasmine.getFixtures().proxyCallTo_('load', arguments)
}

var appendLoadFixtures = function() {
  jasmine.getFixtures().proxyCallTo_('appendLoad', arguments)
}

var setFixtures = function(html) {
  jasmine.getFixtures().proxyCallTo_('set', arguments)
}

var appendSetFixtures = function() {
  jasmine.getFixtures().proxyCallTo_('appendSet', arguments)
}

var sandbox = function(attributes) {
  return jasmine.getFixtures().sandbox(attributes)
}

var spyOnEvent = function(selector, eventName) {
  return jasmine.JQuery.events.spyOn(selector, eventName)
}

var preloadStyleFixtures = function() {
  jasmine.getStyleFixtures().proxyCallTo_('preload', arguments)
}

var loadStyleFixtures = function() {
  jasmine.getStyleFixtures().proxyCallTo_('load', arguments)
}

var appendLoadStyleFixtures = function() {
  jasmine.getStyleFixtures().proxyCallTo_('appendLoad', arguments)
}

var setStyleFixtures = function(html) {
  jasmine.getStyleFixtures().proxyCallTo_('set', arguments)
}

var appendSetStyleFixtures = function(html) {
  jasmine.getStyleFixtures().proxyCallTo_('appendSet', arguments)
}

var loadJSONFixtures = function() {
  return jasmine.getJSONFixtures().proxyCallTo_('load', arguments)
}

var getJSONFixture = function(url) {
  return jasmine.getJSONFixtures().proxyCallTo_('read', arguments)[url]
}

jasmine.spiedEventsKey = function (selector, eventName) {
  return [$(selector).selector, eventName].toString()
}

jasmine.getFixtures = function() {
  return jasmine.currentFixtures_ = jasmine.currentFixtures_ || new jasmine.Fixtures()
}

jasmine.getStyleFixtures = function() {
  return jasmine.currentStyleFixtures_ = jasmine.currentStyleFixtures_ || new jasmine.StyleFixtures()
}

jasmine.Fixtures = function() {
  this.containerId = 'jasmine-fixtures'
  this.fixturesCache_ = {}
  this.fixturesPath = 'spec/javascripts/fixtures'
}

jasmine.Fixtures.prototype.set = function(html) {
  this.cleanUp()
  this.createContainer_(html)
}

jasmine.Fixtures.prototype.appendSet= function(html) {
  this.addToContainer_(html)
}

jasmine.Fixtures.prototype.preload = function() {
  this.read.apply(this, arguments)
}

jasmine.Fixtures.prototype.load = function() {
  this.cleanUp()
  this.createContainer_(this.read.apply(this, arguments))
}

jasmine.Fixtures.prototype.appendLoad = function() {
  this.addToContainer_(this.read.apply(this, arguments))
}

jasmine.Fixtures.prototype.read = function() {
  var htmlChunks = []

  var fixtureUrls = arguments
  for(var urlCount = fixtureUrls.length, urlIndex = 0; urlIndex < urlCount; urlIndex++) {
    htmlChunks.push(this.getFixtureHtml_(fixtureUrls[urlIndex]))
  }

  return htmlChunks.join('')
}

jasmine.Fixtures.prototype.clearCache = function() {
  this.fixturesCache_ = {}
}

jasmine.Fixtures.prototype.cleanUp = function() {
  $('#' + this.containerId).remove()
}

jasmine.Fixtures.prototype.sandbox = function(attributes) {
  var attributesToSet = attributes || {}
  return $('
').attr(attributesToSet)
}

jasmine.Fixtures.prototype.createContainer_ = function(html) {
  var container
  if(html instanceof $) {
    container = $('
')
    container.html(html)
  } else {
    container = '
' + html + '
'
  }
  $('body').append(container)
}

jasmine.Fixtures.prototype.addToContainer_ = function(html){
  var container = $('body').find('#'+this.containerId).append(html)
  if(!container.length){
    this.createContainer_(html)
  }
}

jasmine.Fixtures.prototype.getFixtureHtml_ = function(url) {
  if (typeof this.fixturesCache_[url] === 'undefined') {
    this.loadFixtureIntoCache_(url)
  }
  return this.fixturesCache_[url]
}

jasmine.Fixtures.prototype.loadFixtureIntoCache_ = function(relativeUrl) {
  var url = this.makeFixtureUrl_(relativeUrl)
  var request = $.ajax({
    type: "GET",
    url: url + "?" + new Date().getTime(),
    async: false
  })
  this.fixturesCache_[relativeUrl] = request.responseText
}

jasmine.Fixtures.prototype.makeFixtureUrl_ = function(relativeUrl){
  return this.fixturesPath.match('/$') ? this.fixturesPath + relativeUrl : this.fixturesPath + '/' + relativeUrl
}

jasmine.Fixtures.prototype.proxyCallTo_ = function(methodName, passedArguments) {
  return this[methodName].apply(this, passedArguments)
}

jasmine.StyleFixtures = function() {
  this.fixturesCache_ = {}
  this.fixturesNodes_ = []
  this.fixturesPath = 'spec/javascripts/fixtures'
}

jasmine.StyleFixtures.prototype.set = function(css) {
  this.cleanUp()
  this.createStyle_(css)
}

jasmine.StyleFixtures.prototype.appendSet = function(css) {
  this.createStyle_(css)
}

jasmine.StyleFixtures.prototype.preload = function() {
  this.read_.apply(this, arguments)
}

jasmine.StyleFixtures.prototype.load = function() {
  this.cleanUp()
  this.createStyle_(this.read_.apply(this, arguments))
}

jasmine.StyleFixtures.prototype.appendLoad = function() {
  this.createStyle_(this.read_.apply(this, arguments))
}

jasmine.StyleFixtures.prototype.cleanUp = function() {
  while(this.fixturesNodes_.length) {
    this.fixturesNodes_.pop().remove()
  }
}

jasmine.StyleFixtures.prototype.createStyle_ = function(html) {
  var styleText = $('

').html(html).text()

  var style = $('')

  this.fixturesNodes_.push(style)

  $('head').append(style)
}

jasmine.StyleFixtures.prototype.clearCache = jasmine.Fixtures.prototype.clearCache

jasmine.StyleFixtures.prototype.read_ = jasmine.Fixtures.prototype.read

jasmine.StyleFixtures.prototype.getFixtureHtml_ = jasmine.Fixtures.prototype.getFixtureHtml_

jasmine.StyleFixtures.prototype.loadFixtureIntoCache_ = jasmine.Fixtures.prototype.loadFixtureIntoCache_

jasmine.StyleFixtures.prototype.makeFixtureUrl_ = jasmine.Fixtures.prototype.makeFixtureUrl_

jasmine.StyleFixtures.prototype.proxyCallTo_ = jasmine.Fixtures.prototype.proxyCallTo_

/** jasmine json fixtures */

jasmine.getJSONFixtures = function() {
  return jasmine.currentJSONFixtures_ = jasmine.currentJSONFixtures_ || new jasmine.JSONFixtures()
}

jasmine.JSONFixtures = function() {
  this.fixturesCache_ = {}
  this.fixturesPath = 'spec/javascripts/fixtures/json'
}

jasmine.JSONFixtures.prototype.load = function() {
  this.read.apply(this, arguments)
  return this.fixturesCache_
}

jasmine.JSONFixtures.prototype.read = function() {
  var fixtureUrls = arguments
  for(var urlCount = fixtureUrls.length, urlIndex = 0; urlIndex < urlCount; urlIndex++) {
    this.getFixtureData_(fixtureUrls[urlIndex])
  }
  return this.fixturesCache_
}

jasmine.JSONFixtures.prototype.clearCache = function() {
  this.fixturesCache_ = {}
}

jasmine.JSONFixtures.prototype.getFixtureData_ = function(url) {
  this.loadFixtureIntoCache_(url)
  return this.fixturesCache_[url]
}

jasmine.JSONFixtures.prototype.loadFixtureIntoCache_ = function(relativeUrl) {
  var self = this
  var url = this.fixturesPath.match('/$') ? this.fixturesPath + relativeUrl : this.fixturesPath + '/' + relativeUrl
  $.ajax({
    async: false, // must be synchronous to guarantee that no tests are run before fixture is loaded
    cache: false,
    dataType: 'json',
    url: url,
    success: function(data) {
      self.fixturesCache_[relativeUrl] = data
    },
    error: function(jqXHR, status, errorThrown) {
        throw Error('JSONFixture could not be loaded: ' + url + ' (status: ' + status + ', message: ' + errorThrown.message + ')')
    }
  })
}

jasmine.JSONFixtures.prototype.proxyCallTo_ = function(methodName, passedArguments) {
  return this[methodName].apply(this, passedArguments)
}

jasmine.JQuery = function() {}

jasmine.JQuery.browserTagCaseIndependentHtml = function(html) {
  return $('
').append(html).html()
}

jasmine.JQuery.elementToString = function(element) {
  var domEl = $(element).get(0)
  if (domEl == undefined || domEl.cloneNode)
    return $('
').append($(element).clone()).html()
  else
    return element.toString()
}

jasmine.JQuery.matchersClass = {}

!function(namespace) {
  var data = {
    spiedEvents: {},
    handlers:    []
  }

  namespace.events = {
    spyOn: function(selector, eventName) {
      var handler = function(e) {
        data.spiedEvents[jasmine.spiedEventsKey(selector, eventName)] = e
      }
      $(selector).bind(eventName, handler)
      data.handlers.push(handler)
      return {
        selector: selector,
        eventName: eventName,
        handler: handler,
        reset: function(){
          delete data.spiedEvents[jasmine.spiedEventsKey(selector, eventName)]
        }
      }
    },

    wasTriggered: function(selector, eventName) {
      return !!(data.spiedEvents[jasmine.spiedEventsKey(selector, eventName)])
    },

    wasPrevented: function(selector, eventName) {
      return data.spiedEvents[jasmine.spiedEventsKey(selector, eventName)].isDefaultPrevented()
    },

    cleanUp: function() {
      data.spiedEvents = {}
      data.handlers    = []
    }
  }
}(jasmine.JQuery)

!function(){
  var jQueryMatchers = {
    toHaveClass: function(className) {
      return this.actual.hasClass(className)
    },

    toHaveCss: function(css){
      for (var prop in css){
        if (this.actual.css(prop) !== css[prop]) return false
      }
      return true
    },

    toBeVisible: function() {
      return this.actual.is(':visible')
    },

    toBeHidden: function() {
      return this.actual.is(':hidden')
    },

    toBeSelected: function() {
      return this.actual.is(':selected')
    },

    toBeChecked: function() {
      return this.actual.is(':checked')
    },

    toBeEmpty: function() {
      return this.actual.is(':empty')
    },

    toExist: function() {
      return $(document).find(this.actual).length
    },

    toHaveAttr: function(attributeName, expectedAttributeValue) {
      return hasProperty(this.actual.attr(attributeName), expectedAttributeValue)
    },

    toHaveProp: function(propertyName, expectedPropertyValue) {
      return hasProperty(this.actual.prop(propertyName), expectedPropertyValue)
    },

    toHaveId: function(id) {
      return this.actual.attr('id') == id
    },

    toHaveHtml: function(html) {
      return this.actual.html() == jasmine.JQuery.browserTagCaseIndependentHtml(html)
    },

    toContainHtml: function(html){
      var actualHtml = this.actual.html()
      var expectedHtml = jasmine.JQuery.browserTagCaseIndependentHtml(html)
      return (actualHtml.indexOf(expectedHtml) >= 0)
    },

    toHaveText: function(text) {
      var trimmedText = $.trim(this.actual.text())
      if (text && $.isFunction(text.test)) {
        return text.test(trimmedText)
      } else {
        return trimmedText == text
      }
    },

    toHaveValue: function(value) {
      return this.actual.val() == value
    },

    toHaveData: function(key, expectedValue) {
      return hasProperty(this.actual.data(key), expectedValue)
    },

    toBe: function(selector) {
      return this.actual.is(selector)
    },

    toContain: function(selector) {
      return this.actual.find(selector).length
    },

    toBeDisabled: function(selector){
      return this.actual.is(':disabled')
    },

    toBeFocused: function(selector) {
      return this.actual.is(':focus')
    },

    toHandle: function(event) {

      var events = $._data(this.actual.get(0), "events")

      if(!events || !event || typeof event !== "string") {
        return false
      }

      var namespaces = event.split(".")
      var eventType = namespaces.shift()
      var sortedNamespaces = namespaces.slice(0).sort()
      var namespaceRegExp = new RegExp("(^|\\.)" + sortedNamespaces.join("\\.(?:.*\\.)?") + "(\\.|$)")

      if(events[eventType] && namespaces.length) {
        for(var i = 0; i < events[eventType].length; i++) {
          var namespace = events[eventType][i].namespace
          if(namespaceRegExp.test(namespace)) {
            return true
          }
        }
      } else {
        return events[eventType] && events[eventType].length > 0
      }
    },

    // tests the existence of a specific event binding + handler
    toHandleWith: function(eventName, eventHandler) {
      var stack = $._data(this.actual.get(0), "events")[eventName]
      for (var i = 0; i < stack.length; i++) {
        if (stack[i].handler == eventHandler) return true
      }
      return false
    }
  }

  var hasProperty = function(actualValue, expectedValue) {
    if (expectedValue === undefined) return actualValue !== undefined
    return actualValue == expectedValue
  }

  var bindMatcher = function(methodName) {
    var builtInMatcher = jasmine.Matchers.prototype[methodName]

    jasmine.JQuery.matchersClass[methodName] = function() {
      if (this.actual
        && (this.actual instanceof $
          || jasmine.isDomNode(this.actual))) {
            this.actual = $(this.actual)
            var result = jQueryMatchers[methodName].apply(this, arguments)
            var element
            if (this.actual.get && (element = this.actual.get()[0]) && !$.isWindow(element) && element.tagName !== "HTML")
              this.actual = jasmine.JQuery.elementToString(this.actual)
            return result
          }

          if (builtInMatcher) {
            return builtInMatcher.apply(this, arguments)
          }

          return false
    }
  }

  for(var methodName in jQueryMatchers) {
    bindMatcher(methodName)
  }
}()

beforeEach(function() {
  this.addMatchers(jasmine.JQuery.matchersClass)
  this.addMatchers({
    toHaveBeenTriggeredOn: function(selector) {
      this.message = function() {
        return [
          "Expected event " + this.actual + " to have been triggered on " + selector,
          "Expected event " + this.actual + " not to have been triggered on " + selector
        ]
      }
      return jasmine.JQuery.events.wasTriggered(selector, this.actual)
    }
  })
  this.addMatchers({
    toHaveBeenTriggered: function(){
      var eventName = this.actual.eventName,
          selector = this.actual.selector
      this.message = function() {
        return [
          "Expected event " + eventName + " to have been triggered on " + selector,
          "Expected event " + eventName + " not to have been triggered on " + selector
        ]
      }
      return jasmine.JQuery.events.wasTriggered(selector, eventName)
     }
  })
  this.addMatchers({
    toHaveBeenPreventedOn: function(selector) {
      this.message = function() {
        return [
          "Expected event " + this.actual + " to have been prevented on " + selector,
          "Expected event " + this.actual + " not to have been prevented on " + selector
        ]
      }
      return jasmine.JQuery.events.wasPrevented(selector, this.actual)
    }
  })
  this.addMatchers({
    toHaveBeenPrevented: function() {
      var eventName = this.actual.eventName,
          selector = this.actual.selector
      this.message = function() {
        return [
          "Expected event " + eventName + " to have been prevented on " + selector,
          "Expected event " + eventName + " not to have been prevented on " + selector
        ]
      }
      return jasmine.JQuery.events.wasPrevented(selector, eventName)
    }
  })
})

afterEach(function() {
  jasmine.getFixtures().cleanUp()
  jasmine.getStyleFixtures().cleanUp()
  jasmine.JQuery.events.cleanUp()
})
<|endoftext|>