center flex-end flex-start space-around space-between stretch

auto baseline center flex-end flex-start stretch

alternate alternate-reverse normal reverse

cubic-bezier() ease ease-in ease-in-out ease-out linear step-end step-start steps()

color color-burn color-dodge darken difference exclusion hard-light hue lighten luminosity normal multiply overlay saturation screen soft-light

border-box content-box padding-box inherit

image() linear-gradient() radial-gradient() repeating-linear-gradient() repeating-radial-gradient() url()

no-repeat repeat repeat-x repeat-y round space

dashed dotted double groove hidden inset none outset ridge solid inherit

always auto avoid avoid-column avoid-page avoid-region column left page region right

attr() close-quote no-close-quote no-open-quote normal none open-quote inherit

alias all-scroll auto cell col-resize context-menu copy crosshair default e-resize ew-resize grab grabbing help inherit move n-resize ne-resize nesw-resize no-drop none not-allowed ns-resize nw-resize nwse-resize pointer progress row-resize s-resize se-resize sw-resize text vertical-text w-resize wait zoom-in zoom-out

block flex grid inline inline-block inline-flex inline-grid inline-table list-item none run-in table table-caption table-cell table-column table-column-group table-footer-group table-header-group table-row table-row-group inherit

blur() brightness() contrast() custom() drop-shadow() grayscale() hue-rotate() invert() none opacity() sepia() saturate() url()

column column-reverse nowrap row row-reverse wrap wrap-reverse

cursive fantasy inherit monospace sans-serif serif

condensed expanded extra-condensed extra-expanded normal semi-condensed semi-expanded ultra-condensed ultra-expanded

normal small-caps all-small-caps petite-caps all-petite-caps unicase titling-caps

armenian circle decimal decimal-leading-zero disc georgian inherit inside lower-alpha lower-greek lower-latin lower-roman none outside square upper-alpha upper-latin upper-roman url()

armenian circle decimal decimal-leading-zero disc georgian lower-alpha lower-greek lower-latin lower-roman none square upper-alpha upper-latin upper-roman inherit

all auto fill inherit none painted stroke visible visibleFill visiblePainted visibleStroke

absolute fixed relative static sticky inherit

auto circle() ellipse() inherit outside-shape polygon() rectangle()

none inherit circle() ellipse() polygon() inset() margin-box border-box padding-box content-box url() image() linear-gradient() radial-gradient() repeating-linear-gradient() repeating-radial-gradient()

line-through none overline underline inherit

circle dot double-circle filled none open sesame triangle

auto geometricPrecision optimizeLegibility optimizeSpeed

capitalize full-width lowercase none uppercase inherit

matrix() matrix3d() none perspective() rotate() rotate3d() rotateX() rotateY() rotateZ() scale() scale3d() scaleX() scaleY() scaleZ() skewX() skewY() translate() translate3d() translateX() translateY() translateZ()

baseline bottom middle sub super text-bottom text-top top inherit

normal nowrap pre pre-line pre-wrap inherit


$('<span>' + " " + token.doc.trim() + '</span>').appendTo($hintObj).addClass("jshint-jsdoc");

keep keep keep keep keep replace keep keep

fs-extra

fs-extra contains methods that aren't included in the vanilla Node.js fs package. Such as mkdir -p, cp -r, and rm -rf.

fs
file
file system
copy
directory
extra
mkdirp
mkdir
mkdirs
recursive
json
read
write
extra
delete
remove
touch
create
text
output

Node.js: fs-extra
=================

[![build status](https://secure.travis-ci.org/jprichardson/node-fs-extra.png)](http://travis-ci.org/jprichardson/node-fs-extra)

This module adds a few extra file system methods that aren't included in the native `fs` module. It is a drop in replacement for `fs`.

Why?
----

I got tired of including `mkdirp`, `rimraf`, and `cp -r` in most of my projects.

Installation
------------

    npm install --save fs-extra

Usage
-----

Drop in replacement for native `fs`.

```javascript
var fs = require('fs-extra');
```

Methods
-------

**NOTE:** You can still use the native Node.js methods. They are copied over to `fs-extra`.

### copy(src, dest, callback)

Copy a file or directory. The directory can have contents. Like `cp -r`. There isn't a synchronous version implemented yet.

Sync: (none)

Examples:

```javascript
var fs = require('fs-extra');

fs.copy('/tmp/myfile', '/tmp/mynewfile', function(err){
  if (err) {
    console.error(err);
  }
  else {
    console.log("success!")
  }
}); //copies file

fs.copy('/tmp/mydir', '/tmp/mynewdir', function(err){
  if (err) {
    console.error(err);
  }
  else {
    console.log("success!")
  }
}); //copies directory, even if it has subdirectories or files
```

### createFile(file, callback)

Creates a file. If the file that is requested to be created is in directories that do not exist, these directories are created. If the file already exists, it is **NOT MODIFIED**.

Sync: `createFileSync()`

Example:

```javascript
var fs = require('fs-extra')
  , file = '/tmp/this/path/does/not/exist/file.txt'

fs.createFile(file, function(err) {
  console.log(err); //null

  //file has now been created, including the directory it is to be placed in
})
```

### mkdirs(dir, callback)

Creates a directory. If the parent hierarchy doesn't exist, it's created. Like `mkdir -p`.

Alias: `mkdirp()`

Sync: `mkdirsSync()` / `mkdirpSync()`

Examples:

```javascript
var fs = require('fs-extra');

fs.mkdirs('/tmp/some/long/path/that/prob/doesnt/exist', function(err){
  if (err) {
    console.error(err);
  }
  else {
    console.log("success!")
  }
});

fs.mkdirsSync('/tmp/another/path');
```

### outputFile(file, data, callback)

Almost the same as `writeFile`, except that if the directory does not exist, it's created.

Sync: `outputFileSync()`

Example:

```javascript
var fs = require('fs-extra')
  , file = '/tmp/this/path/does/not/exist/file.txt'

fs.outputFile(file, 'hello!', function(err) {
  console.log(err); //null

  fs.readFile(file, 'utf8', function(err, data) {
    console.log(data); //hello!
  })
})
```

### outputJson(file, data, callback)

Almost the same as `writeJson`, except that if the directory does not exist, it's created.

Alias: `outputJSON()

Sync: `outputJsonSync()`, `outputJSONSync()`

Example:

```javascript
var fs = require('fs-extra')
  , file = '/tmp/this/path/does/not/exist/file.txt'

fs.outputJson(file, {name: 'JP'}, function(err) {
  console.log(err); //null

  fs.readJson(file, function(err, data) {
    console.log(data.name); //'JP
  })
})
```

### readJson(file, callback)

Reads a JSON file and then parses it into an object.

Alias: `readJSON()`

Sync: `readJsonSync()`, `readJSONSync()`

Example:

```javascript
var fs = require('fs-extra');

fs.readJson('./package.json', function(err, packageObj) {
  console.log(packageObj.version); //0.1.3
});
```

### remove(dir, callback)

Removes a file or directory. The directory can have contents. Like `rm -rf`.

Alias: `delete()`

Sync: `removeSync()` / `deleteSync()`

Examples:

```javascript
var fs = require('fs-extra');

fs.remove('/tmp/myfile', function(err){
  if (err) {
    console.error(err);
  }
  else {
    console.log("success!")
  }
});

fs.removeSync('/home/jprichardson'); //I just deleted my entire HOME directory.
```

### writeJson(file, object, callback)

Writes an object to a JSON file.

Alias: `writeJSON()`

Sync: `writeJsonSync()`, `writeJSONSync()`

Example:

```javascript
var fs = require('fs-extra');
fs.writeJson('./package.json', {name: 'fs-extra'}, function(err){
  console.log(err);
});
```

Roadmap to 1.0.0
-----------------

This contains items that I'm considering doing. I'd love community feedback.

* File system walker. I really like this one: https://github.com/daaku/nodejs-walker ... this might be adding too much. Thoughts?
* File/directory tree watcher. There are quite a few. ... this also might be adding too much. Thoughts?
* Method to move files.
* Copy sync.
* Thinking about moving `rimraf`, `ncp`, and `mkdirps` code into this library. I'd like fs-extra to be a stable library that module authors
can depend upon. A bunch of other dependencies kinda sucks for modules/libraries. (I'm leaning against this now.)
* Change documentation to use the `fse` prefix instead of `fs`. This may encourage people to start using `fse` as a prefix and hence make their code clearer that they're not using the native `fs`. I'm very undecided on this one since `fs-extra` is a drop in replacement for the native `fs`. (I'm leaning against this now.)

Naming
------

I put a lot of thought into the naming of these function. Inspired by @coolaj86's request. So he deserves much of the credit for raising the issue. See discussion(s) here:

* https://github.com/jprichardson/node-fs-extra/issues/2
* https://github.com/flatiron/utile/issues/11
* https://github.com/ryanmcgrath/wrench-js/issues/29
* https://github.com/substack/node-mkdirp/issues/17

First, I believe that in as many cases as possible, the [Node.js naming schemes](http://nodejs.org/api/fs.html) should be chosen. However, there are problems with the Node.js own naming schemes.

For example, `fs.readFile()` and `fs.readdir()`: the **F** is capitalized in *File* and the **d** is not capitalized in *dir*. Perhaps a bit pedantic, but they should still be consistent. Also, Node.js has chosen a lot of POSIX naming schemes, which I believe is great. See: `fs.mkdir()`, `fs.rmdir()`, `fs.chown()`, etc.

We have a dilemma though. How do you consistently name methods that perform the following POSIX commands: `cp`, `cp -r`, `mkdir -p`, and `rm -rf`?

My perspective: when in doubt, err on the side of simplicity. Consider that for a moment. A directory is just a hierarchical grouping of directories and files. So when you want to copy it or remove it, in most cases you'll want to copy or remove all of its contents. When you want to create a directory, if the directory that it's suppose to be contained in does not exist, then in most cases you'll want to create that too.

So, if you want to remove a file or a directory regardless of whether it has contents, just call `fs.remove(path)` or its alias `fs.delete(path)`. If you want to copy a file or a directory whether it has contents, just call `fs.copy(source, destination)`. If you want to create a directory regardless of whether its parent directories exist, just call `fs.mkdirs(path)` or `fs.mkdirp(path)`.

Contributors
-------------
- [JP Richardson](https://github.com/jprichardson)
- [Mike McNeil](https://github.com/mikermcneil)
- [Ian Crowther](https://github.com/iancrowther)
- [Stephen Mathieson](https://github.com/stephenmathieson)
- `<your name here>`

License
-------

Licensed under MIT

Copyright (c) 2011-2013 JP Richardson

[1]: http://nodejs.org/docs/latest/api/fs.html

[jsonfile]: https://github.com/jprichardson/node-jsonfile

[aboutjp]: http://about.me/jprichardson
[twitter]: http://twitter.com/jprichardson
[procbits]: http://procbits.com
[gitpilot]: http://gitpilot.com


keep keep replace replace keep keep keep

/*
 * Copyright (c) 2013 Adobe Systems Incorporated. All rights reserved.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
 * to deal in the Software without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 * and/or sell copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 * DEALINGS IN THE SOFTWARE.
 *
 */

/*jslint vars: true, plusplus: true, devel: true, nomen: true, indent: 4, maxerr: 50 */
/*global define, brackets, $ */

define(function (require, exports, module) {
    "use strict";

    var _ = brackets.getModule("thirdparty/lodash");

    var CodeHintManager      = brackets.getModule("editor/CodeHintManager"),
        EditorManager        = brackets.getModule("editor/EditorManager"),
        Commands             = brackets.getModule("command/Commands"),
        CommandManager       = brackets.getModule("command/CommandManager"),
        LanguageManager      = brackets.getModule("language/LanguageManager"),
        AppInit              = brackets.getModule("utils/AppInit"),
        ExtensionUtils       = brackets.getModule("utils/ExtensionUtils"),
        StringMatch          = brackets.getModule("utils/StringMatch"),
        ProjectManager       = brackets.getModule("project/ProjectManager"),
        PreferencesManager   = brackets.getModule("preferences/PreferencesManager"),
        Strings              = brackets.getModule("strings"),
        ParameterHintManager = require("ParameterHintManager"),
        HintUtils            = require("HintUtils"),
        ScopeManager         = require("ScopeManager"),
        Session              = require("Session"),
        Acorn                = require("thirdparty/acorn/acorn");

    var session        = null,  // object that encapsulates the current session state
        cachedCursor   = null,  // last cursor of the current hinting session
        cachedHints    = null,  // sorted hints for the current hinting session
        cachedType     = null,  // describes the lookup type and the object context
        cachedToken    = null,  // the token used in the current hinting session
        matcher        = null,  // string matcher for hints
        jsHintsEnabled = true,  // preference setting to enable/disable the hint session
        noHintsOnDot   = false, // preference setting to prevent hints on dot
        ignoreChange;           // can ignore next "change" event if true;

    // Languages that support inline JavaScript
    var _inlineScriptLanguages = ["html", "php"];

    // Define the detectedExclusions which are files that have been detected to cause Tern to run out of control.
    PreferencesManager.definePreference("jscodehints.detectedExclusions", "array", [], {
        description: Strings.DESCRIPTION_DETECTED_EXCLUSIONS
    });

    // This preference controls when Tern will time out when trying to understand files
    PreferencesManager.definePreference("jscodehints.inferenceTimeout", "number", 30000, {
        description: Strings.DESCRIPTION_INFERENCE_TIMEOUT
    });

    // This preference controls whether to prevent hints from being displayed when dot is typed
    PreferencesManager.definePreference("jscodehints.noHintsOnDot", "boolean", false, {
        description: Strings.DESCRIPTION_NO_HINTS_ON_DOT
    });

    // This preference controls whether to create a session and process all JS files or not.
    PreferencesManager.definePreference("codehint.JSHints", "boolean", true, {
        description: Strings.DESCRIPTION_JS_HINTS
    });

    /**
     * Check whether any of code hints preferences for JS Code Hints is disabled
     * @return {boolean} enabled/disabled
     */
    function _areHintsEnabled() {
        return (PreferencesManager.get("codehint.JSHints") !== false) &&
            (PreferencesManager.get("showCodeHints") !== false);
    }

    PreferencesManager.on("change", "codehint.JSHints", function () {
        jsHintsEnabled = _areHintsEnabled();
    });

    PreferencesManager.on("change", "showCodeHints", function () {
        jsHintsEnabled = _areHintsEnabled();
    });

    PreferencesManager.on("change", "jscodehints.noHintsOnDot", function () {
        noHintsOnDot = !!PreferencesManager.get("jscodehints.noHintsOnDot");
    });

    /**
     * Sets the configuration, generally for testing/debugging use.
     * Configuration keys are merged into the current configuration.
     * The Tern worker is automatically updated to the new config as well.
     *
     * * debug: Set to true if you want verbose logging
     * * noReset: Set to true if you don't want the worker to restart periodically
     *
     * @param {Object} configUpdate keys/values to merge into the config
     */
    function setConfig(configUpdate) {
        var config = setConfig.config;
        Object.keys(configUpdate).forEach(function (key) {
            config[key] = configUpdate[key];
        });

        ScopeManager._setConfig(configUpdate);
    }

    setConfig.config = {};

    /**
     *  Get the value of current session.
     *  Used for unit testing.
     * @return {Session} - the current session.
     */
    function getSession() {
        return session;
    }

    /**
     * Creates a hint response object. Filters the hint list using the query
     * string, formats the hints for display, and returns a hint response
     * object according to the CodeHintManager's API for code hint providers.
     *
     * @param {Array.<Object>} hints - hints to be included in the response
     * @param {string} query - querystring with which to filter the hint list
     * @param {Object} type - the type of query, property vs. identifier
     * @return {Object} - hint response as defined by the CodeHintManager API
     */
    function getHintResponse(hints, query, type) {

        var trimmedQuery,
            formattedHints;

        if (setConfig.config.debug) {
            console.debug("Hints", _.pluck(hints, "label"));
        }

        var _infered = true;

        function getInferHelper(type) {
            return function (element, index, array) {
                if (element === type && _infered) {
                    _infered = true;
                } else {
                    _infered = false;
                }
            };
        }

        function inferArrayTypeClass(typeExpr) {
            var type = "type-array";
            var types = typeExpr.split('[')[1].split(']')[0].split(',');

            _infered = true;

            types.every(getInferHelper('string'));
            if (_infered) {
                type = 'type-string-array';
            } else {
                _infered = true;
                types.every(getInferHelper('number'));
                if (_infered) {
                    type = 'type-num-array';
                } else {
                    _infered = true;
                    types.every(getInferHelper('Object'));
                    if (_infered) {
                        type = 'type-object-array';
                    }
                }
            }
            return type;
        }

        function getRenderTypeClass(type) {
            var typeClass = 'type-undetermined';
            if (type) {
                if (type.indexOf('Object') === 0) {
                    typeClass = 'type-object';
                } else if (type.indexOf('[') === 0) {
                    typeClass = inferArrayTypeClass(type);
                } else if (type.indexOf('fn') === 0) {
                    typeClass = 'type-function';
                } else if (type.indexOf('string') === 0) {
                    typeClass = "type-string";
                } else if (type.indexOf('number') === 0) {
                    typeClass = 'type-number';
                } else if (type.indexOf('bool') === 0) {
                    typeClass = 'type-boolean';
                }
            }
            return typeClass;
        }

        /*
         * Returns a formatted list of hints with the query substring
         * highlighted.
         *
         * @param {Array.<Object>} hints - the list of hints to format
         * @param {string} query - querystring used for highlighting matched
         *      poritions of each hint
         * @return {jQuery.Deferred|{
         *              hints: Array.<string|jQueryObject>,
         *              match: string,
         *              selectInitial: boolean,
         *              handleWideResults: boolean}}
         */
        function formatHints(hints, query) {
            return hints.map(function (token) {
                var $hintObj    = $("").addClass("brackets-js-hints");
                ($hintObj).addClass(getRenderTypeClass(token.type));
                //$('' + getRenderType(token.type) + '').appendTo($hintObj).addClass("brackets-js-hints-type");
                // level indicates either variable scope or property confidence
                if (!type.property && !token.builtin && token.depth !== undefined) {
                    switch (token.depth) {
                    case 0:
                        $hintObj.addClass("priority-high");
                        break;
                    case 1:
                        $hintObj.addClass("priority-medium");
                        break;
                    case 2:
                        $hintObj.addClass("priority-low");
                        break;
                    default:
                        $hintObj.addClass("priority-lowest");
                        break;
                    }
                }

                if (token.guess) {
                    $hintObj.addClass("guess-hint");
                }

                // is the token a keyword?
                if (token.keyword) {
                    $hintObj.addClass("keyword-hint");
                }

                if (token.literal) {
                    $hintObj.addClass("literal-hint");
                }

                // highlight the matched portion of each hint
                if (token.stringRanges) {
                    token.stringRanges.forEach(function (item) {
                        if (item.matched) {
                            $hintObj.append($("")
                                .append(_.escape(item.text))
                                .addClass("matched-hint"));
                        } else {
                            $hintObj.append(_.escape(item.text));
                        }
                    });
                } else {
                    $hintObj.text(token.value);
                }

                $hintObj.data("token", token);

                function _appendLink() {
                    if (token.url) {
                        $('< >').appendTo($hintObj).addClass("jshint-link").attr('href', token.url).on("click", function (event) {
                            event.stopImmediatePropagation();
                            event.stopPropagation();
                        });
                    }
                }

                if (token.type) {
                    if (token.type.length > 40) {
                        _appendLink();
                        $('' + " " + token.type.split('->').join(':').trim() + '').appendTo($hintObj).addClass("jshint-description");
                    } else {
                        $('' + " " + token.type.split('->').join(':').trim() + '').appendTo($hintObj).addClass("brackets-js-hints-type-details");
                        _appendLink();
                    }
                } else {
                    if (token.keyword) {
                        $('' + " " + "keyword" + '').appendTo($hintObj).addClass("brackets-js-hints-type-details").addClass("keyword");
                    }
                }

                if (token.doc) {
                    $hintObj.attr('title', token.doc);
                    $('' + " " + token.doc.trim() + '').appendTo($hintObj).addClass("jshint-jsdoc");
                }

                $('

').appendTo($hintObj);

                return $hintObj;
            });
        }

        // trim leading and trailing string literal delimiters from the query
        trimmedQuery = _.trim(query, HintUtils.SINGLE_QUOTE + HintUtils.DOUBLE_QUOTE);

        if (hints) {
            formattedHints = formatHints(hints, trimmedQuery);
        } else {
            formattedHints = [];
        }

        return {
            hints: formattedHints,
            match: null, // the CodeHintManager should not format the results
            selectInitial: true,
            handleWideResults: hints.handleWideResults
        };
    }

    /**
     * @constructor
     */
    function JSHints() {
    }

    /**
     * determine if the cached hint information should be invalidated and re-calculated
     *
     * @param {Session} session - the active hinting session
     * @return {boolean} - true if the hints should be recalculated
     */
    JSHints.prototype.needNewHints = function (session) {
        var cursor  = session.getCursor(),
            type    = session.getType();

        return !cachedHints || !cachedCursor || !cachedType ||
            cachedCursor.line !== cursor.line ||
            type.property !== cachedType.property ||
            type.context !== cachedType.context ||
            type.showFunctionType !== cachedType.showFunctionType ||
            (type.functionCallPos && cachedType.functionCallPos &&
            type.functionCallPos.ch !== cachedType.functionCallPos.ch);
    };

    /**
     *  Cache the hints and the hint's context.
     *
     *  @param {Array.<string>} hints - array of hints
     *  @param {{line:number, ch:number}} cursor - the location where the hints
     *  were created.
     * @param {{property: boolean,
                showFunctionType:boolean,
                context: string,
                functionCallPos: {line:number, ch:number}}} type -
     *  type information about the hints
     *  @param {Object} token - CodeMirror token
     */
    function setCachedHintContext(hints, cursor, type, token) {
        cachedHints = hints;
        cachedCursor = cursor;
        cachedType = type;
        cachedToken = token;
    }

    /**
     *  Reset cached hint context.
     */
    function resetCachedHintContext() {
        cachedHints = null;
        cachedCursor = null;
        cachedType = null;
        cachedToken =  null;
    }

    /**
     *  Have conditions have changed enough to justify closing the hints popup?
     *
     * @param {Session} session - the active hinting session
     * @return {boolean} - true if the hints popup should be closed.
     */
    JSHints.prototype.shouldCloseHints = function (session) {

        // close if the token className has changed then close the hints.
        var cursor = session.getCursor(),
            token = session.getToken(cursor),
            lastToken = cachedToken;

        // if the line has changed, then close the hints
        if (!cachedCursor || cursor.line !== cachedCursor.line) {
            return true;
        }

        if (token.type === null) {
            token = session.getNextTokenOnLine(cursor);
        }

        if (lastToken && lastToken.type === null) {
            lastToken = session.getNextTokenOnLine(cachedCursor);
        }

        // Both of the tokens should never be null (happens when token is off
        // the end of the line), so one is null then close the hints.
        if (!lastToken || !token ||
                token.type !== lastToken.type) {
            return true;
        }

        // Test if one token string is a prefix of the other.
        // If one is a prefix of the other then consider it the
        // same token and don't close the hints.
        if (token.string.length >= lastToken.string.length) {
            return token.string.indexOf(lastToken.string) !== 0;
        } else {
            return lastToken.string.indexOf(token.string) !== 0;
        }
    };

    /**
     * @return {boolean} - true if the document supports inline JavaScript
     */
    function isInlineScriptSupported(document) {
        var language = LanguageManager.getLanguageForPath(document.file.fullPath).getId();
        return _inlineScriptLanguages.indexOf(language) !== -1;
    }

    function isInlineScript(editor) {
        return editor.getModeForSelection() === "javascript";
    }

    /**
     *  Create a new StringMatcher instance, if needed.
     *
     * @return {StringMatcher} - a StringMatcher instance.
     */
    function getStringMatcher() {
        if (!matcher) {
            matcher = new StringMatch.StringMatcher({
                preferPrefixMatches: true
            });
        }

        return matcher;
    }

    /**
     *  Check if a hint response is pending.
     *
     * @param {jQuery.Deferred} deferredHints - deferred hint response
     * @return {boolean} - true if deferred hints are pending, false otherwise.
     */
    function hintsArePending(deferredHints) {
        return (deferredHints && !deferredHints.hasOwnProperty("hints") &&
            deferredHints.state() === "pending");
    }

    /**
     *  Common code to get the session hints. Will get guesses if there were
     *  no completions for the query.
     *
     * @param {string} query - user text to search hints with
     *  @param {{line:number, ch:number}} cursor - the location where the hints
     *  were created.
     * @param {{property: boolean,
                 showFunctionType:boolean,
                 context: string,
                 functionCallPos: {line:number, ch:number}}} type -
     *  type information about the hints
     *  @param {Object} token - CodeMirror token
     * @param {jQuery.Deferred=} $deferredHints - existing Deferred we need to
     * resolve (optional). If not supplied a new Deferred will be created if
     * needed.
     * @return {Object + jQuery.Deferred} - hint response (immediate or
     *     deferred) as defined by the CodeHintManager API
     */
    function getSessionHints(query, cursor, type, token, $deferredHints) {

        var hintResults = session.getHints(query, getStringMatcher());
        if (hintResults.needGuesses) {
            var guessesResponse = ScopeManager.requestGuesses(session,
                session.editor.document);

            if (!$deferredHints) {
                $deferredHints = $.Deferred();
            }

            guessesResponse.done(function () {
                if (hintsArePending($deferredHints)) {
                    hintResults = session.getHints(query, getStringMatcher());
                    setCachedHintContext(hintResults.hints, cursor, type, token);
                    var hintResponse = getHintResponse(cachedHints, query, type);
                    $deferredHints.resolveWith(null, [hintResponse]);
                }
            }).fail(function () {
                if (hintsArePending($deferredHints)) {
                    $deferredHints.reject();
                }
            });

            return $deferredHints;
        } else if (hintsArePending($deferredHints)) {
            setCachedHintContext(hintResults.hints, cursor, type, token);
            var hintResponse    = getHintResponse(cachedHints, query, type);
            $deferredHints.resolveWith(null, [hintResponse]);
            return null;
        } else {
            setCachedHintContext(hintResults.hints, cursor, type, token);
            return getHintResponse(cachedHints, query, type);
        }
    }

    /**
     * Determine whether hints are available for a given editor context
     *
     * @param {Editor} editor - the current editor context
     * @param {string} key - charCode of the last pressed key
     * @return {boolean} - can the provider provide hints for this session?
     */
    JSHints.prototype.hasHints = function (editor, key) {
        if (session && HintUtils.hintableKey(key, !noHintsOnDot)) {

            if (isInlineScriptSupported(session.editor.document)) {
                if (!isInlineScript(session.editor)) {
                    return false;
                }
            }
            var cursor  = session.getCursor(),
                token   = session.getToken(cursor);

            // don't autocomplete within strings or comments, etc.
            if (token && HintUtils.hintable(token)) {
                if (session.isFunctionName()) {
                    return false;
                }

                if (this.needNewHints(session)) {
                    resetCachedHintContext();
                    matcher = null;
                }
                return true;
            }
        }
        return false;
    };

    /**
      * Return a list of hints, possibly deferred, for the current editor
      * context
      *
      * @param {string} key - charCode of the last pressed key
      * @return {Object + jQuery.Deferred} - hint response (immediate or
      *     deferred) as defined by the CodeHintManager API
      */
    JSHints.prototype.getHints = function (key) {
        var cursor = session.getCursor(),
            token = session.getToken(cursor);

        if (token && HintUtils.hintableKey(key, !noHintsOnDot) && HintUtils.hintable(token)) {
            var type    = session.getType(),
                query   = session.getQuery();

            // If the hint context is changed and the hints are open, then
            // close the hints by returning null;
            if (CodeHintManager.isOpen() && this.shouldCloseHints(session)) {
                return null;
            }

            // Compute fresh hints if none exist, or if the session
            // type has changed since the last hint computation
            if (this.needNewHints(session)) {
                if (key) {
                    ScopeManager.handleFileChange([{from: cursor, to: cursor, text: [key]}]);
                    ignoreChange = true;
                }

                var scopeResponse   = ScopeManager.requestHints(session, session.editor.document),
                    $deferredHints  = $.Deferred(),
                    scopeSession    = session;

                scopeResponse.done(function () {
                    if (hintsArePending($deferredHints)) {
                        // Verify we are still in same session
                        if (scopeSession === session) {
                            getSessionHints(query, cursor, type, token, $deferredHints);
                        } else {
                            $deferredHints.reject();
                        }
                    }
                    scopeSession = null;
                }).fail(function () {
                    if (hintsArePending($deferredHints)) {
                        $deferredHints.reject();
                    }
                    scopeSession = null;
                });

                return $deferredHints;
            }

            if (cachedHints) {
                return getSessionHints(query, cursor, type, token);
            }
        }

        return null;
    };

    /**
     * Inserts the hint selected by the user into the current editor.
     *
     * @param {jQuery.Object} $hintObj - hint object to insert into current editor
     * @return {boolean} - should a new hinting session be requested
     *      immediately after insertion?
     */
    JSHints.prototype.insertHint = function ($hintObj) {
        var hint        = $hintObj.data("token"),
            completion  = hint.value,
            cursor      = session.getCursor(),
            query       = session.getQuery(),
            start       = {line: cursor.line, ch: cursor.ch - query.length},
            end         = {line: cursor.line, ch: cursor.ch},
            invalidPropertyName = false;

        if (session.getType().property) {
            // if we're inserting a property name, we need to make sure the
            // hint is a valid property name.
            // to check this, run the hint through Acorns tokenizer
            // it should result in one token, and that token should either be
            // a 'name' or a 'keyword', as javascript allows keywords as property names
            var tokenizer = Acorn.tokenize(completion);
            var currentToken = tokenizer();

            // the name is invalid if the hint is not a 'name' or 'keyword' token
            if (currentToken.type !== Acorn.tokTypes.name && !currentToken.type.keyword) {
                invalidPropertyName = true;
            } else {
                // check for a second token - if there is one (other than 'eof')
                // then the hint isn't a valid property name either
                currentToken = tokenizer();
                if (currentToken.type !== Acorn.tokTypes.eof) {
                    invalidPropertyName = true;
                }
            }

            if (invalidPropertyName) {
                // need to walk back to the '.' and replace
                // with '["<hint>"]
                var dotCursor = session.findPreviousDot();
                if (dotCursor) {
                    completion = "[\"" + completion + "\"]";
                    start.line = dotCursor.line;
                    start.ch = dotCursor.ch - 1;
                }
            }
        }

        // Replace the current token with the completion
        // HACK (tracking adobe/brackets#1688): We talk to the private CodeMirror instance
        // directly to replace the range instead of using the Document, as we should. The
        // reason is due to a flaw in our current document synchronization architecture when
        // inline editors are open.
        session.editor._codeMirror.replaceRange(completion, start, end);

        // Return false to indicate that another hinting session is not needed
        return false;
    };

    // load the extension
    AppInit.appReady(function () {

        /*
         * When the editor is changed, reset the hinting session and cached
         * information, and reject any pending deferred requests.
         *
         * @param {!Editor} editor - editor context to be initialized.
         * @param {?Editor} previousEditor - the previous editor.
         */
        function initializeSession(editor, previousEditor) {
            session = new Session(editor);
            ScopeManager.handleEditorChange(session, editor.document,
                previousEditor ? previousEditor.document : null);
            ParameterHintManager.setSession(session);
            cachedHints = null;
        }

        /*
         * Connects to the given editor, creating a new Session & adding listeners
         *
         * @param {?Editor} editor - editor context on which to listen for
         *      changes. If null, 'session' is cleared.
         * @param {?Editor} previousEditor - the previous editor
         */
        function installEditorListeners(editor, previousEditor) {
            // always clean up cached scope and hint info
            resetCachedHintContext();

            if (!jsHintsEnabled) {
                return;
            }

            if (editor && HintUtils.isSupportedLanguage(LanguageManager.getLanguageForPath(editor.document.file.fullPath).getId())) {
                initializeSession(editor, previousEditor);
                editor
                    .on(HintUtils.eventName("change"), function (event, editor, changeList) {
                        if (!ignoreChange) {
                            ScopeManager.handleFileChange(changeList);
                            ParameterHintManager.popUpHintAtOpenParen();
                        }
                        ignoreChange = false;
                    });
                ParameterHintManager.installListeners(editor);
            } else {
                session = null;
            }
        }

        /*
         * Uninstall editor change listeners
         *
         * @param {Editor} editor - editor context on which to stop listening
         *      for changes
         */
        function uninstallEditorListeners(editor) {
            if (editor) {
                editor.off(HintUtils.eventName("change"));
                ParameterHintManager.uninstallListeners(editor);
            }
        }

        /*
         * Handle the activeEditorChange event fired by EditorManager.
         * Uninstalls the change listener on the previous editor
         * and installs a change listener on the new editor.
         *
         * @param {Event} event - editor change event (ignored)
         * @param {Editor} current - the new current editor context
         * @param {Editor} previous - the previous editor context
         */
        function handleActiveEditorChange(event, current, previous) {
            // Uninstall "languageChanged" event listeners on previous editor's document & put them on current editor's doc
            if (previous) {
                previous.document
                    .off(HintUtils.eventName("languageChanged"));
            }
            if (current) {
                current.document
                    .on(HintUtils.eventName("languageChanged"), function () {
                        // If current doc's language changed, reset our state by treating it as if the user switched to a
                        // different document altogether
                        uninstallEditorListeners(current);
                        installEditorListeners(current);
                    });
            }

            uninstallEditorListeners(previous);
            installEditorListeners(current, previous);
        }

        /*
         * Handle JumptoDefiniton menu/keyboard command.
         */
        function handleJumpToDefinition() {
            var offset,
                handleJumpResponse;

            // Only provide jump-to-definition results when cursor is in JavaScript content
            if (!session || session.editor.getModeForSelection() !== "javascript") {
                return null;
            }

            var result = new $.Deferred();

            /**
             * Make a jump-to-def request based on the session and offset passed in.
             * @param {Session} session - the session
             * @param {number} offset - the offset of where to jump from
             */
            function requestJumpToDef(session, offset) {
                var response = ScopeManager.requestJumptoDef(session, session.editor.document, offset);

                if (response.hasOwnProperty("promise")) {
                    response.promise.done(handleJumpResponse).fail(function () {
                        result.reject();
                    });
                }
            }

            /**
             * Sets the selection to move the cursor to the result position.
             * Assumes that the editor has already changed files, if necessary.
             *
             * Additionally, this will check to see if the selection looks like an
             * assignment to a member expression - if it is, and the type is a function,
             * then we will attempt to jump to the RHS of the expression.
             *
             * 'exports.foo = foo'
             *
             * if the selection is 'foo' in 'exports.foo', then we will attempt to jump to def
             * on the rhs of the assignment.
             *
             * @param {number} start - the start of the selection
             * @param {number} end - the end of the selection
             * @param {boolean} isFunction - true if we are jumping to the source of a function def
             */
            function setJumpSelection(start, end, isFunction) {

                /**
                 * helper function to decide if the tokens on the RHS of an assignment
                 * look like an identifier, or member expr.
                 */
                function validIdOrProp(token) {
                    if (!token) {
                        return false;
                    }
                    if (token.string === ".") {
                        return true;
                    }
                    var type = token.type;
                    if (type === "variable-2" || type === "variable" || type === "property") {
                        return true;
                    }

                    return false;
                }

                var madeNewRequest = false;

                if (isFunction) {
                    // When jumping to function defs, follow the chain back
                    // to get to the original function def
                    var cursor = {line: end.line, ch: end.ch},
                        prev = session._getPreviousToken(cursor),
                        next,
                        offset;

                    // see if the selection is preceded by a '.', indicating we're in a member expr
                    if (prev.string === ".") {
                        cursor = {line: end.line, ch: end.ch};
                        next = session.getNextToken(cursor, true);
                        // check if the next token indicates an assignment
                        if (next && next.string === "=") {
                            next = session.getNextToken(cursor, true);
                            // find the last token of the identifier, or member expr
                            while (validIdOrProp(next)) {
                                offset = session.getOffsetFromCursor({line: cursor.line, ch: next.end});
                                next = session.getNextToken(cursor, false);
                            }
                            if (offset) {
                                // trigger another jump to def based on the offset of the RHS
                                requestJumpToDef(session, offset);
                                madeNewRequest = true;
                            }
                        }
                    }
                }
                // We didn't make a new jump-to-def request, so we can resolve the promise
                // and set the selection
                if (!madeNewRequest) {
                    // set the selection
                    session.editor.setSelection(start, end, true);
                    result.resolve(true);
                }
            }

            /**
             * handle processing of the completed jump-to-def request.
             * will open the appropriate file, and set the selection based
             * on the response.
             */
            handleJumpResponse = function (jumpResp) {

                if (jumpResp.resultFile) {
                    if (jumpResp.resultFile !== jumpResp.file) {
                        var resolvedPath = ScopeManager.getResolvedPath(jumpResp.resultFile);
                        if (resolvedPath) {
                            CommandManager.execute(Commands.FILE_OPEN, {fullPath: resolvedPath})
                                .done(function () {
                                    setJumpSelection(jumpResp.start, jumpResp.end, jumpResp.isFunction);
                                });
                        }
                    } else {
                        setJumpSelection(jumpResp.start, jumpResp.end, jumpResp.isFunction);
                    }
                } else {
                    result.reject();
                }
            };

            offset = session.getOffset();
            // request a jump-to-def
            requestJumpToDef(session, offset);

            return result.promise();
        }

        /*
         * Helper for QuickEdit jump-to-definition request.
         */
        function quickEditHelper() {
            var offset     = session.getCursor(),
                response   = ScopeManager.requestJumptoDef(session, session.editor.document, offset);

            return response;
        }

        // Register quickEditHelper.
        brackets._jsCodeHintsHelper = quickEditHelper;

        // Configuration function used for debugging
        brackets._configureJSCodeHints = setConfig;

        ExtensionUtils.loadStyleSheet(module, "styles/brackets-js-hints.css");

        // uninstall/install change listener as the active editor changes
        EditorManager.on(HintUtils.eventName("activeEditorChange"),
                handleActiveEditorChange);

        ProjectManager.on("beforeProjectClose", function () {
            ScopeManager.handleProjectClose();
        });

        ProjectManager.on("projectOpen", function () {
            ScopeManager.handleProjectOpen();
        });

        // immediately install the current editor
        installEditorListeners(EditorManager.getActiveEditor());

        // init
        EditorManager.registerJumpToDefProvider(handleJumpToDefinition);

        var jsHints = new JSHints();
        CodeHintManager.registerHintProvider(jsHints, HintUtils.SUPPORTED_LANGUAGES, 0);

        ParameterHintManager.addCommands();

        // for unit testing
        exports.getSession = getSession;
        exports.jsHintProvider = jsHints;
        exports.initializeSession = initializeSession;
        exports.handleJumpToDefinition = handleJumpToDefinition;
    });
});


/*!
 * Connect - bodyParser
 * Copyright(c) 2010 Sencha Inc.
 * Copyright(c) 2011 TJ Holowaychuk
 * MIT Licensed
 */

/**
 * Module dependencies.
 */

var multipart = require('./multipart')
  , urlencoded = require('./urlencoded')
  , json = require('./json');

/**
 * Body parser:
 *
 *   Parse request bodies, supports _application/json_,
 *   _application/x-www-form-urlencoded_, and _multipart/form-data_.
 *
 *   This is equivalent to:
 *
 *     app.use(connect.json());
 *     app.use(connect.urlencoded());
 *     app.use(connect.multipart());
 *
 * Examples:
 *
 *      connect()
 *        .use(connect.bodyParser())
 *        .use(function(req, res) {
 *          res.end('viewing user ' + req.body.user.name);
 *        });
 *
 *      $ curl -d 'user[name]=tj' http://local/
 *      $ curl -d '{"user":{"name":"tj"}}' -H "Content-Type: application/json" http://local/
 *
 *  View [json](json.html), [urlencoded](urlencoded.html), and [multipart](multipart.html) for more info.
 *
 * @param {Object} options
 * @return {Function}
 * @api public
 */

exports = module.exports = function bodyParser(options){
  var _urlencoded = urlencoded(options)
    , _multipart = multipart(options)
    , _json = json(options);

  return function bodyParser(req, res, next) {
    _json(req, res, function(err){
      if (err) return next(err);
      _urlencoded(req, res, function(err){
        if (err) return next(err);
        _multipart(req, res, next);
      });
    });
  }
};


exports = module.exports = require('./lib/_stream_readable.js');
exports.Readable = exports;
exports.Writable = require('./lib/_stream_writable.js');
exports.Duplex = require('./lib/_stream_duplex.js');
exports.Transform = require('./lib/_stream_transform.js');
exports.PassThrough = require('./lib/_stream_passthrough.js');


var rimraf = require("../rimraf")
  , path = require("path")
rimraf(path.join(__dirname, "target"), function (er) {
  if (er) throw er
})


keep keep keep keep replace replace replace keep keep keep keep

/*
 * Copyright (c) 2013 Adobe Systems Incorporated. All rights reserved.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
 * to deal in the Software without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 * and/or sell copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 * DEALINGS IN THE SOFTWARE.
 *
 */

.hint-width-limiter {
    width:400px;
}

span.brackets-js-hints {
    width: 400px;
    display: inline-block;
}

.brackets-js-hints.type-undetermined:before {
    color: cornflowerblue;
    content: '12';
    border: 1px cornflowerblue solid;
    float:left;
    width:25px;
    text-align: center;
    margin-left:-5px;
    margin-right:5px;
    visibility: hidden;
    line-height: 1.2em;
}

.brackets-js-hints.type-number:before {
    color: cornflowerblue;
    content: '12';
    border: 1px cornflowerblue solid;
    float:left;
    width:25px;
    text-align: center;
    margin-left:-5px;
    margin-right:5px;
    line-height: 1.2em;
}

.brackets-js-hints.type-string:before {
    color: cornflowerblue;
    content: 'ab';
    border: 1px cornflowerblue solid;
    float:left;
    width:25px;
    text-align: center;
    margin-left:-5px;
    margin-right:5px;
    line-height: 1.2em;
}

.brackets-js-hints.type-function:before {
    color: cornflowerblue;
    content: 'fn( )';
    border: 1px cornflowerblue solid;
    float:left;
    width:25px;
    text-align: center;
    margin-left:-5px;
    margin-right:5px;
    line-height: 1.2em;
}

.brackets-js-hints.type-array:before {
    color: cornflowerblue;
    content: '[  ]';
    border: 1px cornflowerblue solid;
    float:left;
    width:25px;
    text-align: center;
    margin-left:-5px;
    margin-right:5px;
    line-height: 1.2em;
}

.brackets-js-hints.type-object:before {
    color: cornflowerblue;
    content: '{ :}';
    border: 1px cornflowerblue solid;
    float:left;
    width:25px;
    text-align: center;
    margin-left:-5px;
    margin-right:5px;
    line-height: 1.2em;
}

.brackets-js-hints.type-num-array:before {
    color: cornflowerblue;
    content: '[12]';
    border: 1px cornflowerblue solid;
    float:left;
    width:25px;
    text-align: center;
    margin-left:-5px;
    margin-right:5px;
    line-height: 1.2em;
}

.brackets-js-hints.type-string-array:before {
    color: cornflowerblue;
    content: '[ab]';
    border: 1px cornflowerblue solid;
    float:left;
    width:25px;
    text-align: center;
    margin-left:-5px;
    margin-right:5px;
    line-height: 1.2em;
}

.brackets-js-hints.type-boolean:before {
    color: cornflowerblue;
    content: 'bool';
    border: 1px cornflowerblue solid;
    float:left;
    width:25px;
    text-align: center;
    margin-left:-5px;
    margin-right:5px;
    line-height: 1.2em;
}

.brackets-js-hints-type-details {
    color: #d3d3d3 !important;
    font-weight: 100;
    font-style: italic !important;
    margin-right: 5px;
    float:right;
}

.jshint-description {
    display: none;
    padding-left: 35px !important;
    padding-right:10px !important;
    color: #d4d4d4;
    word-wrap: break-word;
    white-space: normal;
    width:400px;
    box-sizing: border-box;
}

.dark .jshint-description {
    color: #ccc;
}

.jshint-jsdoc {
    display: none;
    padding-left: 28px !important;
    padding-right: 10px !important;
    color: grey;
    word-wrap: break-word;
    white-space: normal;
    width: 400px;
    box-sizing: border-box;
    float: left;
    clear: left;
    max-height: 3em;
    overflow: hidden;
}

.dark .jshint-jsdoc {
    color: #ccc;
}

.jshint-link {
    float:right;
    display:none;
    color:orangered !important;
    margin:0px !important;
    margin-right: 10px !important;
    padding:0px !important;
    font-weight: 900 !important;
}

.highlight .jshint-link {
    display:block;
}

.highlight .jshint-description {
    display: block;
    color: #6495ed !important;
}

.highlight .jshint-jsdoc {
    display: block;
}

.dark .brackets-js-hints-type-details {
    color: #696969 !important;
}

.highlight .brackets-js-hints-type-details {
    color: #6495ed !important;
    display: inline-block;
}

.brackets-js-hints-type-details.keyword {
    color: #6495ed !important;
}

.brackets-js-hints.priority-high {
    color: #486c00; /* green */
}

.brackets-js-hints.priority-medium {
    color: #0c50af; /* blue */
}

.brackets-js-hints.priority-low {
    color: #6b24bd; /* violet */
}

.brackets-js-hints.priority-lowest {
    color: #444; /* dark grey */
}

.brackets-js-hints.variable-hint {
}

.brackets-js-hints.property-hint {
}

.brackets-js-hints.literal-hint {
    color: #444; /* dark grey */
    font-family: SourceCodePro;
}

.brackets-js-hints.keyword-hint {
    font-family: SourceCodePro;
}

.brackets-js-hints.keyword-hint .matched-hint {
    font-family: SourceCodePro-Medium;
    font-weight: 500;
}

.brackets-js-hints .matched-hint {
    font-weight: 500;
}

.brackets-js-hints.guess-hint {
    font-style: italic;
}

#function-hint-container {
    display: none;

    background: #fff;
    position: absolute;
    z-index: 15;
    left: 200px;
    top: 40px;
    pointer-events: none;

    padding: 1px 6px;
    text-align: center;

    border-radius: 3px;
    box-shadow: 0 3px 9px rgba(0, 0, 0, 0.24);
}

#function-hint-container .function-hint-content {
}

.brackets-js-hints .current-parameter {
    font-weight: 500;
}

/* Dark Styles */

.dark .brackets-js-hints.priority-high {
    color: #a1f200; /* green */
}

.dark .brackets-js-hints.priority-medium {
    color: #3ff8ff; /* blue */
}

.dark .brackets-js-hints.priority-low {
    color: #e6adff; /* violet */
}

.dark .brackets-js-hints.priority-lowest {
    color: #bbb; /* dark grey */
}

.dark .brackets-js-hints.literal-hint {
    color: #bbb; /* dark grey */
    font-family: SourceCodePro;
}

.dark #function-hint-container {
    background: #000;
    border: 1px solid rgba(255,255,255,0.15);
    color: #fff;
    box-shadow: 0 3px 9px rgba(0, 0, 0, 0.24);
}


var common = require('../common');
var assert = common.assert;
var fake = common.fake.create();
var DelayedStream = common.DelayedStream;
var Stream = require('stream').Stream;

(function testAutoPause() {
  var source = new Stream();

  fake.expect(source, 'pause', 1);
  var delayedStream = DelayedStream.create(source);
  fake.verify();
})();

(function testDisableAutoPause() {
  var source = new Stream();
  fake.expect(source, 'pause', 0);

  var delayedStream = DelayedStream.create(source, {pauseStream: false});
  fake.verify();
})();