Full Code of pzavolinsky/react-unit for AI

master 37ea35d6cacf cached
58 files
280.8 KB
78.5k tokens
163 symbols
1 requests
Download .txt
Showing preview only (297K chars total). Download the full file or copy to clipboard to get everything.
Repository: pzavolinsky/react-unit
Branch: master
Commit: 37ea35d6cacf
Files: 58
Total size: 280.8 KB

Directory structure:
gitextract_ljpf4nw2/

├── .gitignore
├── .npmignore
├── LICENSE
├── README.md
├── dist/
│   ├── add-ons/
│   │   ├── debug.js
│   │   ├── exclude.js
│   │   ├── index.js
│   │   ├── mock.js
│   │   └── with-context.js
│   ├── internal/
│   │   └── test-render-instance.js
│   ├── pipeline.js
│   ├── react-unit.js
│   ├── render-instance.js
│   ├── resolver.js
│   ├── sizzle-bundle.js
│   ├── types.js
│   ├── unit-component.js
│   ├── utils.js
│   └── wrapper.js
├── gulpfile.js
├── lib/
│   ├── sizzle-bundle.js
│   └── sizzle.js
├── package.json
├── src/
│   ├── add-ons/
│   │   ├── debug.ts
│   │   ├── exclude.ts
│   │   ├── index.ts
│   │   ├── mock.ts
│   │   └── with-context.ts
│   ├── defs.d.ts
│   ├── pipeline.ts
│   ├── react-unit.ts
│   ├── render-instance.ts
│   ├── resolver.ts
│   ├── sizzle-bundle.d.ts
│   ├── sizzle-bundle.js
│   ├── types.ts
│   ├── unit-component.ts
│   ├── utils.ts
│   └── wrapper.ts
├── test/
│   ├── create-component-interleaved.jsx
│   ├── create-component-shallow.jsx
│   ├── create-component.jsx
│   ├── events.jsx
│   ├── exclude.jsx
│   ├── find-by-component.jsx
│   ├── find-by-query.jsx
│   ├── find-by-ref.jsx
│   ├── find-by.jsx
│   ├── internal/
│   │   └── render-instance.jsx
│   ├── mock.jsx
│   ├── render-new.jsx
│   ├── stateful.jsx
│   ├── stateless.jsx
│   ├── text.jsx
│   └── with-context.jsx
├── tsconfig.json
├── tslint.json
└── typings.json

================================================
FILE CONTENTS
================================================

================================================
FILE: .gitignore
================================================
node_modules
dist/test*
*.tgz


================================================
FILE: .npmignore
================================================
dist/test*
lib
src
test
*.tgz
typings
gulpfile.js
*.json


================================================
FILE: LICENSE
================================================
The MIT License (MIT)

Copyright (c) 2015 Patricio Zavolinsky

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.


================================================
FILE: README.md
================================================
react-unit
==========

React Unit is a lightweight unit test library for ReactJS with very few (js-only) dependencies.

By using `react-unit` you can run your ReactJS unit tests directly from node or gulp without having to install any heavyweight external dependencies (such as `jsdom`, `phantomjs`, the python runtime, etc.).

Note: for testing simple components you might also be interested in [react-cucumber](https://github.com/pzavolinsky/react-cucumber).

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

```
npm install --save-dev react-unit
```

and then, in your tests:
```javascript
var React = require('react');
var createComponent = require('react-unit');

describe('MyComponent', () => {
  it('should echo the value', () => {
    var component = createComponent(<MyComponent value="hello, world!" />);

    var input = component.findByQuery('input')[0];

    expect(input.props.value).toBe('hello, world!');
  });

  it('should trigger events', () => {
    var changedValue;
    function onChange(e) { changedValue = e.target.value; }

    var component = createComponent(<MyComponent onChange={onChange} />);
    var input = component.findByQuery('input')[0];

    input.onChange({target:{value: 'hi, everyone!'}});

    expect(changedValue).toBe('hi, everyone!');
  });
});
```

Note that, while this example is using Jasmine, `react-unit` should work with any other test language of your choice.


Usage
-----

To use `react-unit` just require the `createComponent` function:

```javascript
var createComponent = require('react-unit');
```

Then use it to create your component:

```javascript
var component = createComponent(<MyComponent value="hello, world!" />);
```

or (if, for some reason you are not into JSX):

```javascript
var component = createComponent(React.createElement(MyComponent, { value: "hello, world!" }));
```

Now that you have a representation of your component you can use it to find actual HTML elements calling `findByQuery`:

```javascript
var allInputs     = component.findByQuery('input');
var allRows       = component.findByQuery('.row');
var allFirstNames = component.findByQuery('[name=firstName]');
```

By now you probably noted that `findByQuery` takes something suspiciously similar to jQuery selectors. This is not an innocent coincidence, `react-unit` is bundled with the amazing [jQuery Sizzle](https://github.com/jquery/sizzle) to allow you to search your react DOM using query selectors.

In addition to `findByQuery` you can use `findBy` to test every element using a custom function:

```javascript
var all = component.findBy(function() { return true; }); // () => true
var moreThanTwo = component.findBy(function(c) { return c.props.value > 2 });
```

To find elements by their `ref` attribute, you can use the `findByRef` method:

```javascript
var allMyRefs = component.findByRef('myRef');
```

If you want to find a component using a component variable instead of a string expression, you can use `findByComponent`:

```javascript
var component = createComponent.shallow(<CompositeComponent />); // Note: the .shallow!
// or var component = createComponent.interleaved(<CompositeComponent />);

var children = component.findByComponent(ChildComponent);
```
Note that `findByComponent` only works with `shallow` and `interleaved` rendering modes. See [Rendering Modes](#rendering-modes) below for more details.

If you want to test event handling, you can bind a handler to your component:

```javascript
var changeEvent;
function handler(e) { changeEvent = e; }
var component = createComponent(<MyComponent onChange={handler} />);
```

Then find and interact with any element in the component:

```javascript
component.findByQuery('some selector')[0].onChange('some event');
```

Finally assert the event:

```javascript
expect(changeEvent).toBe('some event');
```

If at any point you want to inspect the rendered component you can use:

```javascript
console.log(component.dump());
```

API Reference
-------------

#### Creating components

```javascript
// createComponent :: ReactElement -> Component
createComponent = (reactElement) => Component
```
Renders `reactElement` using the deep rendering strategy (see [Rendering Modes](#rendering-modes) for more details). Returns the rendered `Component`.

This method produces a component tree that is somewhat similar to applying `ReactDOM.render`.

For example:
```javascript
var createComponent = require('react-unit');
var component = createComponent(<MyComponent />);
```
More examples in [test/create-component.jsx](https://github.com/pzavolinsky/react-unit/blob/master/test/create-component.jsx).

---
<br>

```javascript
// createComponent.shallow :: ReactElement -> Component
createComponent.shallow = (reactElement) => Component
```
Renders `reactElement` using the shallow rendering strategy (see [Rendering Modes](#rendering-modes) for more details). Returns the rendered `Component`.

This method produces a shallow component tree. That is, it renders the root component and all the children HTML nodes, stopping at the first child component level.

For example:
```javascript
var createComponent = require('react-unit');
var component = createComponent.shallow(<MyComponent />);
```
More examples in [test/create-component-shallow.jsx](https://github.com/pzavolinsky/react-unit/blob/master/test/create-component-shallow.jsx).

---
<br>

```javascript
// createComponent.interleaved :: ReactElement -> Component
createComponent.interleaved = (reactElement) => Component
```
Renders `reactElement` using the interleaved rendering strategy (see [Rendering Modes](#rendering-modes) for more details). Returns the rendered `Component`.

This method produces a component tree that interleaves react components and actual rendered components.

For example:
```javascript
var createComponent = require('react-unit');
var component = createComponent.interleaved(<MyComponent />);
```
More examples in [test/create-component-interleaved.jsx](https://github.com/pzavolinsky/react-unit/blob/master/test/create-component-interleaved.jsx).

---
<br>

#### Finding components

```javascript
// findByQuery :: String -> [Component]
component.findByQuery => (sizzleExpression) => [Components]
```
Returns all the descendant elements of `component` matching `sizzleExpression`.

For example:
```javascript
var inputs = component.findByQuery('input');
```
More examples in [test/find-by-query.jsx](https://github.com/pzavolinsky/react-unit/blob/master/test/find-by-query.jsx).

---
<br>

```javascript
// findByComponent :: ReactElement -> [Component]
component.findByComponent => (reactElement) => [Components]
```
Returns all the descendant elements of `component` of type `reactElement`. Note that `findByComponent` only works with `shallow` and `interleaved` rendering modes. See [Rendering Modes](#rendering-modes) below for more details.

For example:
```javascript
// assuming: var MyItem = React.createClass({ ... });
var items = component.findByComponent(MyItem);
```
More examples in [test/find-by-component.jsx](https://github.com/pzavolinsky/react-unit/blob/master/test/find-by-component.jsx).

---
<br>

```javascript
// findBy :: (Component -> bool) -> [Component]
component.findBy => (fn) => [Components]
```
Returns all the descendant elements of `component` for whom `fn` returns `true`.

For example:
```javascript
var moreThanTwos = component.findBy(c => c.props.value > 2);
```
More examples in [test/find-by.jsx](https://github.com/pzavolinsky/react-unit/blob/master/test/find-by.jsx).

---
<br>

```javascript
// findByRef :: String -> [Component]
component.findBy => (ref) => [Components]
```
Returns all the descendant elements of `component` matching the `ref` attribute.

For example:
```javascript
var allMyRefs = component.findByRef('myRef');
```
More examples in [test/find-by-ref.jsx](https://github.com/pzavolinsky/react-unit/blob/master/test/find-by-ref.jsx).

---
<br>

#### Inspecting components

```javascript
// dump :: () -> String
component.dump => () => String
```
Returns a string representation of the pseudo-HTML of the component. This method is very useful for troubleshooting broken tests.

For example:
```javascript
var html = component.dump();
// or
console.log(component.dump());
```

---
<br>

```javascript
component.texts // :: [String]
component.text  // :: String
```
Return the text of all the descendant elements of `component`. `texts` is a flat array containing the texts of every descendant element in depth order. `text` behaves like `DOMNode.textContent` (i.e. `component.texts.join('')`).

Some examples in [test/text.jsx](https://github.com/pzavolinsky/react-unit/blob/master/test/text.jsx).

---
<br>

```javascript
// key :: Object
component.props
```
The `props` object of `component`.

---
<br>

```javascript
// key :: String
component.key
```
The `key` of `component`.

---
<br>

```javascript
// ref :: String
component.ref
```
The `ref` of `component`.

---
<br>


Rendering Modes
---------------

#### Deep rendering (default behavior)

By default `react-unit` will use a deep (recursive) rendering strategy. This produces an output that is very similar to that of `ReactDOM.render`.

For example, given:

```jsx
var Person = React.createClass({
  render: function() {
    var children = React.Children.map(this.props.children, (c,i) => <li key={i}>{c}</li>);
    return <div><h1>{this.props.name}</h1><ul>{children}</ul></div>
  }
});
```

Calling `createComponent` in a composite component:

```jsx
var component = createComponent(
  <Person name="Homer">
    <Person name="Bart"/>
    <Person name="Lisa" />
    <Person name="Maggie" />
  </Person>);
```

Results in a representation of the following HTML:

```html
<div>
  <h1>Homer</h1>
  <ul>
    <li>
      <div><h1>Bart</h1><ul></ul></div>
    </li>
    <li>
      <div><h1>Lisa</h1><ul></ul></div>
    </li>
    <li>
      <div><h1>Maggie</h1><ul></ul></div>
    </li>
  </ul>
</div>
```

In other words, the output is the HTML that results of calling the render method of every component. Note that, as a side-effect of deep rendering, component tags (e.g. `<Person/>`) were erased from the HTML representation.

In the example above you find `Lisa` with:

```jsx
var lisa = component.findByQuery('div > ul > li > div > h1')[1];
```

On the flip side, you cannot use `findByQuery` to find your components because, after rendering, they were replaced by the HTML they generate in their `render` method:

```jsx
var persons = component.findByQuery('Person');
expect(persons.length).toEqual(0);
```

#### Shallow rendering

Sometimes you might want to stop rendering after the first level of components. In true unit test spirit you would like to just test a component assuming the components it depends upon are working.

To achieve this you can use `createComponent.shallow` as follows:

```jsx
var component = createComponent.shallow(
  <Person name="Homer">
    <Person name="Bart"/>
    <Person name="Lisa" />
    <Person name="Maggie" />
  </Person>);
```

And the result would be a representation of the following pseudo-HTML:

```html
<div>
  <h1>Homer</h1>
  <ul>
    <li>
      <Person name="Bart"/>
    </li>
    <li>
      <Person name="Lisa"/>
    </li>
    <li>
      <Person name="Maggie"/>
    </li>
  </ul>
</div>
```

To find `Lisa` you could use any of the following:

```jsx
var lisaByAttr         = component.findByQuery('Person[name=Lisa]')[0];
var lisaByTagAndOrder  = component.findByQuery('Person')[1];
var lisaByCompAndOrder = component.findByComponent(Person)[1];
```

And access the properties as usual:

```jsx
expect(lisaByAttr.prop('name')).toEqual('Lisa');
```

#### Interleaved rendering

This rendering mode is similar to the deep mode above with the exception that components are NOT erased form the HTML representation. This means that you can mix and match HTML tags and react components in your `findByQuery` selectors.

To use interleaved rendering call `createComponent.interleaved` as follows:

```jsx
var component = createComponent.interleaved(
  <Person name="Homer">
    <Person name="Bart"/>
    <Person name="Lisa" />
    <Person name="Maggie" />
  </Person>);
```

The result would be a representation of the following pseudo-HTML:

```html
<Person name="Homer">
  <div>
    <h1>Homer</h1>
    <ul>
      <li>
        <Person name="Bart">
          <div><h1>Bart</h1><ul></ul></div>
        </Person>
      </li>
      <li>
        <Person name="Lisa">
          <div><h1>Lisa</h1><ul></ul></div>
        </Person>
      </li>
      <li>
        <Person name="Maggie">
          <div><h1>Maggie</h1><ul></ul></div>
        </Person>
      </li>
    </ul>
  </div>
</Person>
```

And you can find components with:

```jsx
var lisaComp    = component.findByQuery('Person[name=Lisa]')[0];
var lisaCompAlt = component.findByComponent(Person)[2];

var lisaName    = component.findByQuery('Person[name=Lisa] h1')[0];
var lisaNameAlt = lisaComp.findByQuery('h1')[0];
```

Excluding components
--------------------

Using `exclude` you can now leave a component out of test as if it didn't exist.

```jsx
//single component
createComponent.exclude(ChildComponent)(ParentComponent);
createComponent.exclude(ChildComponent).shallow(ParentComponent);
createComponent.exclude(ChildComponent).interleaved(ParentComponent);

//multi components
createComponent.exclude([ChildComponent1, ChildComponent2])(ParentComponent);
createComponent.exclude([ChildComponent1, ChildComponent2]).shallow(ParentComponent);
createComponent.exclude([ChildComponent1, ChildComponent2]).interleaved(ParentComponent);
```

Mocking components
------------------

Using `mock` you can now replace a component with another

```jsx
//single mock
createComponent.mock(Actual, Mock)(ParentComponent);

//multi mock
createComponent
  .mock(Actual1, Mock1)
  .mock(Actual2, Mock2)(ParentComponent);
```

Implicit context
----------------

If you want to test components that use React's implicit [context](https://facebook.github.io/react/docs/context.html) you can pass the context to the rendered components by calling `withContext`:

```jsx
createComponent.withContext({ key: value})(<MyComponentWithContext />);
```


More info
---------


Note that testing **stateful** components require additional effort. See [test/stateful.jsx](https://github.com/pzavolinsky/react-unit/blob/master/test/stateful.jsx) for more details.

For more examples on how to test **events** refer to [test/events.jsx](https://github.com/pzavolinsky/react-unit/blob/master/test/events.jsx).

For more examples on finding elements by **query selectors** refer to [test/find-by-query.jsx](https://github.com/pzavolinsky/react-unit/blob/master/test/find-by-query.jsx).

For more examples on finding element using a **custom function** refer to [test/find-by.jsx](https://github.com/pzavolinsky/react-unit/blob/master/test/find-by.jsx).


================================================
FILE: dist/add-ons/debug.js
================================================
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var ramda_1 = require("ramda");
var instanceLogger = function (instance) {
    console.log('[instance]', instance);
    return instance;
};
var componentLogger = function (comp) {
    console.log('[component]', comp);
    return comp;
};
var resolveLogger = function (comp) {
    console.log('[resolved]', comp);
    return comp;
};
var debug = function (ctx) { return function () {
    return ramda_1.merge(ctx, {
        instanceMapper: ramda_1.compose(instanceLogger, ctx.instanceMapper),
        componentMapper: ramda_1.compose(componentLogger, ctx.componentMapper),
        resolveMapper: ramda_1.compose(resolveLogger, ctx.resolveMapper)
    });
}; };
exports.default = debug;


================================================
FILE: dist/add-ons/exclude.js
================================================
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var ramda_1 = require("ramda");
var utils_1 = require("../utils");
var excludeMapper = function (exclude) {
    var allowed = exclude.constructor === Array
        ? function (comp) { return !ramda_1.any(function (t) { return utils_1.isOfType(t, comp); }, exclude); }
        : function (comp) { return !utils_1.isOfType(exclude, comp); };
    return function (comp) { return utils_1.filterChildren(allowed, comp); };
};
var exclude = function (ctx) {
    return function (exclude) { return ramda_1.merge(ctx, {
        componentMapper: ramda_1.compose(excludeMapper(exclude), ctx.componentMapper)
    }); };
};
exports.default = exclude;


================================================
FILE: dist/add-ons/index.js
================================================
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var exclude_1 = require("./exclude");
var mock_1 = require("./mock");
var with_context_1 = require("./with-context");
var debug_1 = require("./debug");
var addOns = {
    exclude: exclude_1.default,
    mock: mock_1.default,
    withContext: with_context_1.default,
    debug: debug_1.default
};
exports.default = addOns;


================================================
FILE: dist/add-ons/mock.js
================================================
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var ramda_1 = require("ramda");
var types_1 = require("../types");
var utils_1 = require("../utils");
var mockMapper = function (actual, mock) {
    return function (comp) {
        return types_1.isShallow(comp) && utils_1.isOfType(actual, comp)
            ? { type: 'shallow',
                tagName: utils_1.getTagNameForType(mock),
                instance: ramda_1.merge(comp.instance, { type: mock })
            }
            : comp;
    };
};
var mock = function (ctx) {
    return function (actual, mock) { return ramda_1.merge(ctx, {
        componentMapper: ramda_1.compose(mockMapper(actual, mock), ctx.componentMapper)
    }); };
};
exports.default = mock;


================================================
FILE: dist/add-ons/with-context.js
================================================
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var ramda_1 = require("ramda");
var withContextMapper = function (context) {
    return function (instance) { return ramda_1.merge(instance, { context: context }); };
};
var withContext = function (ctx) {
    return function (context) { return ramda_1.merge(ctx, {
        instanceMapper: ramda_1.compose(withContextMapper(context), ctx.instanceMapper)
    }); };
};
exports.default = withContext;


================================================
FILE: dist/internal/test-render-instance.js
================================================
'use strict';

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }

var _renderInstance = require('../render-instance');

var _renderInstance2 = _interopRequireDefault(_renderInstance);

var _types = require('../types');

var React = require('react');

var WithChildren = function WithChildren(_ref) {
  var child = _ref.child;
  return React.createElement(
    'div',
    null,
    child
  );
};

describe('createComponent', function () {
  it('should load numeric children', function () {
    var renderedComponent = (0, _renderInstance2['default'])(React.createElement(WithChildren, { child: 1 }));
    expect((0, _types.isHtml)(renderedComponent)).toBe(true);

    var children = renderedComponent.children;

    expect(children.length).toBe(1);

    expect((0, _types.isUnknown)(children[0])).toBe(true);
  });
});

================================================
FILE: dist/pipeline.js
================================================
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var ramda_1 = require("ramda");
var render_instance_1 = require("./render-instance");
var resolveAndMap = function (ctx, resolver) {
    var mapAndRender = ramda_1.compose(render_instance_1.default, ctx.instanceMapper);
    var resolve = resolver(ctx.componentMapper, mapAndRender);
    return ramda_1.compose(
    // 4) MAP the ResolvedComponent (optional).
    ctx.resolveMapper, 
    // 3) RESOLVE the RenderedComponent into ResolvedComponent by applying a
    //    resolve strategy (deep, shallow, interleaved). The result replaces
    //    ShallowReactComponents with either a unknown components or HTML
    //    components. The resolution process applies a ComponentMapper to each
    //    RenderedComponent before resolving.
    resolve);
};
exports.applyRootPipeline = function (ctx, resolver) {
    return ramda_1.compose(resolveAndMap(ctx, resolver), 
    // 2) RENDER the React INSTANCE into a RenderedComponent (renderInstance)
    //    Note: at this stage, the RenderedComponent tree includes
    //    not-yet-rendered ShallowReactComponents.
    render_instance_1.default, 
    // 1) MAP the React INSTANCE (optional).
    ctx.instanceMapper);
};
var failShallowArtificial = function (comp) {
    return function (_) {
        throw "\n      Cannot call renderNew on shallow rendered component " + comp.tagName + ".\n\n      Looks like you are trying test <Parent><Stateful /></Parent> using\n      shallow render.\n\n      Consider using another rendering mode (e.g. interleaved) or refactoring\n      the test to do a shallow stateless test of <Parent /> and a shallow\n      stateful test of <Stateful />;\n    ";
    };
};
exports.applyComponentPipeline = function (ctx, resolver) {
    return function (comp) {
        return ramda_1.compose(resolveAndMap(ctx, resolver), 
        // 2) RE-RENDER the React INSTANCE into a RenderedComponent (renderNew)
        //    Note: at this stage, the RenderedComponent tree includes
        //    not-yet-rendered ShallowReactComponents.
        comp.renderNew || failShallowArtificial(comp), 
        // 1) MAP the React INSTANCE (optional).
        ctx.instanceMapper);
    };
};


================================================
FILE: dist/react-unit.js
================================================
"use strict";
var R = require("ramda");
var types_1 = require("./types");
var resolver_1 = require("./resolver");
var pipeline_1 = require("./pipeline");
var wrapper_1 = require("./wrapper");
var add_ons_1 = require("./add-ons");
var createComponent = function (ctx, resolver) {
    var rootPipeline = pipeline_1.applyRootPipeline(ctx, resolver);
    var componentPipeline = pipeline_1.applyComponentPipeline(ctx, resolver);
    function wrap(resolved) {
        return types_1.isUnknown(resolved)
            ? resolved.unknown
            : wrapper_1.default(undefined, resolved, function (c) { return function (i) { return wrap(componentPipeline(c)(i)); }; });
    }
    return R.compose(wrap, rootPipeline);
};
var makeCreateComponent = function (ctx) {
    var fn = createComponent(ctx, resolver_1.deepResolver);
    fn.shallow = createComponent(ctx, resolver_1.shallowResolver);
    fn.interleaved = createComponent(ctx, resolver_1.interleavedResolver);
    fn.ctx = ctx;
    return fn;
};
function applyAddons(fn) {
    R.toPairs(add_ons_1.default).forEach(function (_a) {
        var name = _a[0], addOn = _a[1];
        fn[name] =
            R.compose(applyAddons, makeCreateComponent, addOn(fn.ctx));
    });
    return fn;
}
;
module.exports = applyAddons(makeCreateComponent(types_1.defaultRenderContext));


================================================
FILE: dist/render-instance.js
================================================
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var react_1 = require("react");
var ramda_1 = require("ramda");
var ReactShallowRenderer = require("react-test-renderer/shallow");
var types_1 = require("./types");
var utils_1 = require("./utils");
// --- Rendered Component Wrapper Functions --------------------------------- //
function wrapShallowReactComponent(renderOutput) {
    var type = renderOutput.type;
    var tagName = utils_1.getTagNameForType(type);
    return {
        type: 'shallow',
        tagName: tagName,
        instance: renderOutput
    };
}
;
var getPropsForOutput = function (_a) {
    var key = _a.key, ref = _a.ref, props = _a.props, _store = _a._store // tslint:disable-line
    ;
    return ramda_1.mergeAll([
        _store && _store.props,
        props,
        { key: key, ref: ref }
    ]);
};
function wrapHtmlComponent(renderNew, renderOutput, instance) {
    var type = renderOutput.type, key = renderOutput.key, ref = renderOutput.ref;
    var props = getPropsForOutput(renderOutput);
    var children = props.children
        ? react_1.Children.map(props.children, function (c) { return processRenderOutput(renderNew, c, c); })
        : [];
    return {
        type: 'html',
        tagName: type,
        key: key,
        ref: ref,
        props: props,
        renderOutput: renderOutput,
        instance: instance,
        children: children,
        renderNew: renderNew
    };
}
;
function wrapUnknownComponent(renderOutput) {
    return {
        type: 'unknown',
        unknown: renderOutput
    };
}
function processRenderOutput(renderNew, renderOutput, instance) {
    if (!renderOutput) {
        // e.g. render() { return undefined; }
        return wrapUnknownComponent(renderOutput);
    }
    if (typeof renderOutput.type === 'function') {
        // shallowRender reached another React component and stopped
        // renderOutput is the spec for that (child) component
        return wrapShallowReactComponent(renderOutput);
    }
    if (renderOutput.type && renderOutput.props) {
        // shallowRender returned an HTML component
        return wrapHtmlComponent(renderNew, renderOutput, instance);
    }
    return wrapUnknownComponent(renderOutput);
}
// --- Public API ----------------------------------------------------------- //
exports.toArtificialHtml = function (comp, child) { return ({
    type: 'artificial',
    tagName: utils_1.getTagNameForType(comp.instance.type),
    props: getPropsForOutput(comp.instance),
    renderOutput: comp.instance,
    instance: comp.instance,
    children: child ? [child] : [],
    renderNew: child && types_1.isHtml(child) ? child.renderNew : undefined
}); };
var renderInstance = function (instance) {
    var shallowRenderer = new ReactShallowRenderer();
    function create(componentInstance) {
        shallowRenderer.render(componentInstance, componentInstance.context);
        var renderOutput = shallowRenderer.getRenderOutput();
        var renderNew = function (newInstance) {
            return create(newInstance || componentInstance);
        };
        return processRenderOutput(renderNew, renderOutput, componentInstance);
    }
    return create(instance);
};
exports.default = renderInstance;


================================================
FILE: dist/resolver.js
================================================
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var ramda_1 = require("ramda");
var render_instance_1 = require("./render-instance");
var types_1 = require("./types");
function deepResolver(mapper, renderer) {
    return function (comp) {
        var resolve = deepResolver(mapper, renderer);
        var mapped = mapper(comp);
        if (types_1.isShallow(mapped)) {
            var newComp = renderer(mapped.instance);
            // note that newComp might be shallow again, so we need to call
            // deepResolver on it to resolve the whole the tree
            return resolve(newComp);
        }
        if (types_1.isHtml(mapped))
            return ramda_1.merge(mapped, {
                children: mapped.children.map(resolve)
            });
        return mapped;
    };
}
exports.deepResolver = deepResolver;
function shallowResolver(mapper, _) {
    return function (comp) {
        var resolve = shallowResolver(mapper, _);
        var mapped = mapper(comp);
        if (types_1.isShallow(mapped)) {
            return render_instance_1.toArtificialHtml(mapped);
        }
        if (types_1.isHtml(mapped)) {
            return ramda_1.merge(mapped, {
                children: mapped.children.map(resolve)
            });
        }
        return mapped;
    };
}
exports.shallowResolver = shallowResolver;
function interleavedResolver(mapper, renderer, nonRoot) {
    return function (comp) {
        var resolve = interleavedResolver(mapper, renderer, true);
        var mapped = mapper(comp);
        if (types_1.isShallow(mapped)) {
            var newComp = renderer(mapped.instance);
            // note that newComp might be shallow again, so we need to call
            // interleavedResolver on it to render the whole the tree
            var renderedComp = resolve(newComp);
            return render_instance_1.toArtificialHtml(mapped, renderedComp);
        }
        if (types_1.isHtml(mapped)) {
            var mappedWithChildren = ramda_1.merge(mapped, {
                children: mapped.children.map(resolve)
            });
            return nonRoot
                ? mappedWithChildren
                : render_instance_1.toArtificialHtml(mappedWithChildren, mappedWithChildren);
        }
        return mapped;
    };
}
exports.interleavedResolver = interleavedResolver;


================================================
FILE: dist/sizzle-bundle.js
================================================

var document = {
	createElement: function(tag) {
		return {
			appendChild: function() {},
			getElementsByTagName: function() { return []; },
			getAttribute: function() {}
		}
	},
	createComment: function(s) { return s; },
	getElementsByClassName: ' { [native code] }',
	nodeType: 9,
	documentElement: { nodeName: 'HTML' }
};
document.ownerDocument = document;
var window = { document: document };

var _ = (function() {
	/*!
 * Sizzle CSS Selector Engine v2.2.1-pre
 * http://sizzlejs.com/
 *
 * Copyright jQuery Foundation and other contributors
 * Released under the MIT license
 * http://jquery.org/license
 *
 * Date: 2015-08-17
 */
(function( window ) {

var i,
	support,
	Expr,
	getText,
	isXML,
	tokenize,
	compile,
	select,
	outermostContext,
	sortInput,
	hasDuplicate,

	// Local document vars
	setDocument,
	document,
	docElem,
	documentIsHTML,
	rbuggyQSA,
	rbuggyMatches,
	matches,
	contains,

	// Instance-specific data
	expando = "sizzle" + 1 * new Date(),
	preferredDoc = window.document,
	dirruns = 0,
	done = 0,
	classCache = createCache(),
	tokenCache = createCache(),
	compilerCache = createCache(),
	sortOrder = function( a, b ) {
		if ( a === b ) {
			hasDuplicate = true;
		}
		return 0;
	},

	// General-purpose constants
	MAX_NEGATIVE = 1 << 31,

	// Instance methods
	hasOwn = ({}).hasOwnProperty,
	arr = [],
	pop = arr.pop,
	push_native = arr.push,
	push = arr.push,
	slice = arr.slice,
	// Use a stripped-down indexOf as it's faster than native
	// http://jsperf.com/thor-indexof-vs-for/5
	indexOf = function( list, elem ) {
		var i = 0,
			len = list.length;
		for ( ; i < len; i++ ) {
			if ( list[i] === elem ) {
				return i;
			}
		}
		return -1;
	},

	booleans = "checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped",

	// Regular expressions

	// http://www.w3.org/TR/css3-selectors/#whitespace
	whitespace = "[\\x20\\t\\r\\n\\f]",

	// http://www.w3.org/TR/CSS21/syndata.html#value-def-identifier
	identifier = "(?:\\\\.|[\\w-]|[^\\x00-\\xa0])+",

	// Attribute selectors: http://www.w3.org/TR/selectors/#attribute-selectors
	attributes = "\\[" + whitespace + "*(" + identifier + ")(?:" + whitespace +
		// Operator (capture 2)
		"*([*^$|!~]?=)" + whitespace +
		// "Attribute values must be CSS identifiers [capture 5] or strings [capture 3 or capture 4]"
		"*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|(" + identifier + "))|)" + whitespace +
		"*\\]",

	pseudos = ":(" + identifier + ")(?:\\((" +
		// To reduce the number of selectors needing tokenize in the preFilter, prefer arguments:
		// 1. quoted (capture 3; capture 4 or capture 5)
		"('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|" +
		// 2. simple (capture 6)
		"((?:\\\\.|[^\\\\()[\\]]|" + attributes + ")*)|" +
		// 3. anything else (capture 2)
		".*" +
		")\\)|)",

	// Leading and non-escaped trailing whitespace, capturing some non-whitespace characters preceding the latter
	rwhitespace = new RegExp( whitespace + "+", "g" ),
	rtrim = new RegExp( "^" + whitespace + "+|((?:^|[^\\\\])(?:\\\\.)*)" + whitespace + "+$", "g" ),

	rcomma = new RegExp( "^" + whitespace + "*," + whitespace + "*" ),
	rcombinators = new RegExp( "^" + whitespace + "*([>+~]|" + whitespace + ")" + whitespace + "*" ),

	rattributeQuotes = new RegExp( "=" + whitespace + "*([^\\]'\"]*?)" + whitespace + "*\\]", "g" ),

	rpseudo = new RegExp( pseudos ),
	ridentifier = new RegExp( "^" + identifier + "$" ),

	matchExpr = {
		"ID": new RegExp( "^#(" + identifier + ")" ),
		"CLASS": new RegExp( "^\\.(" + identifier + ")" ),
		"TAG": new RegExp( "^(" + identifier + "|[*])" ),
		"ATTR": new RegExp( "^" + attributes ),
		"PSEUDO": new RegExp( "^" + pseudos ),
		"CHILD": new RegExp( "^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\(" + whitespace +
			"*(even|odd|(([+-]|)(\\d*)n|)" + whitespace + "*(?:([+-]|)" + whitespace +
			"*(\\d+)|))" + whitespace + "*\\)|)", "i" ),
		"bool": new RegExp( "^(?:" + booleans + ")$", "i" ),
		// For use in libraries implementing .is()
		// We use this for POS matching in `select`
		"needsContext": new RegExp( "^" + whitespace + "*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\(" +
			whitespace + "*((?:-\\d)?\\d*)" + whitespace + "*\\)|)(?=[^-]|$)", "i" )
	},

	rinputs = /^(?:input|select|textarea|button)$/i,
	rheader = /^h\d$/i,

	rnative = /^[^{]+\{\s*\[native \w/,

	// Easily-parseable/retrievable ID or TAG or CLASS selectors
	rquickExpr = /^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,

	rsibling = /[+~]/,
	rescape = /'|\\/g,

	// CSS escapes http://www.w3.org/TR/CSS21/syndata.html#escaped-characters
	runescape = new RegExp( "\\\\([\\da-f]{1,6}" + whitespace + "?|(" + whitespace + ")|.)", "ig" ),
	funescape = function( _, escaped, escapedWhitespace ) {
		var high = "0x" + escaped - 0x10000;
		// NaN means non-codepoint
		// Support: Firefox<24
		// Workaround erroneous numeric interpretation of +"0x"
		return high !== high || escapedWhitespace ?
			escaped :
			high < 0 ?
				// BMP codepoint
				String.fromCharCode( high + 0x10000 ) :
				// Supplemental Plane codepoint (surrogate pair)
				String.fromCharCode( high >> 10 | 0xD800, high & 0x3FF | 0xDC00 );
	},

	// Used for iframes
	// See setDocument()
	// Removing the function wrapper causes a "Permission Denied"
	// error in IE
	unloadHandler = function() {
		setDocument();
	};

// Optimize for push.apply( _, NodeList )
try {
	push.apply(
		(arr = slice.call( preferredDoc.childNodes )),
		preferredDoc.childNodes
	);
	// Support: Android<4.0
	// Detect silently failing push.apply
	arr[ preferredDoc.childNodes.length ].nodeType;
} catch ( e ) {
	push = { apply: arr.length ?

		// Leverage slice if possible
		function( target, els ) {
			push_native.apply( target, slice.call(els) );
		} :

		// Support: IE<9
		// Otherwise append directly
		function( target, els ) {
			var j = target.length,
				i = 0;
			// Can't trust NodeList.length
			while ( (target[j++] = els[i++]) ) {}
			target.length = j - 1;
		}
	};
}

function Sizzle( selector, context, results, seed ) {
	var m, i, elem, nid, match, groups, newSelector,
		newContext = context && context.ownerDocument,

		// nodeType defaults to 9, since context defaults to document
		nodeType = context ? context.nodeType : 9;

	results = results || [];

	// Return early from calls with invalid selector or context
	if ( typeof selector !== "string" || !selector ||
		nodeType !== 1 && nodeType !== 9 && nodeType !== 11 ) {

		return results;
	}

	// Try to shortcut find operations (as opposed to filters) in HTML documents
	if ( !seed ) {

		if ( ( context ? context.ownerDocument || context : preferredDoc ) !== document ) {
			setDocument( context );
		}
		context = context || document;

		if ( documentIsHTML ) {

			// If the selector is sufficiently simple, try using a "get*By*" DOM method
			// (excepting DocumentFragment context, where the methods don't exist)
			if ( nodeType !== 11 && (match = rquickExpr.exec( selector )) ) {

				// ID selector
				if ( (m = match[1]) ) {

					// Document context
					if ( nodeType === 9 ) {
						if ( (elem = context.getElementById( m )) ) {

							// Support: IE, Opera, Webkit
							// TODO: identify versions
							// getElementById can match elements by name instead of ID
							if ( elem.id === m ) {
								results.push( elem );
								return results;
							}
						} else {
							return results;
						}

					// Element context
					} else {

						// Support: IE, Opera, Webkit
						// TODO: identify versions
						// getElementById can match elements by name instead of ID
						if ( newContext && (elem = newContext.getElementById( m )) &&
							contains( context, elem ) &&
							elem.id === m ) {

							results.push( elem );
							return results;
						}
					}

				// Type selector
				} else if ( match[2] ) {
					push.apply( results, context.getElementsByTagName( selector ) );
					return results;

				// Class selector
				} else if ( (m = match[3]) && support.getElementsByClassName &&
					context.getElementsByClassName ) {

					push.apply( results, context.getElementsByClassName( m ) );
					return results;
				}
			}

			// Take advantage of querySelectorAll
			if ( support.qsa &&
				!compilerCache[ selector + " " ] &&
				(!rbuggyQSA || !rbuggyQSA.test( selector )) ) {

				if ( nodeType !== 1 ) {
					newContext = context;
					newSelector = selector;

				// qSA looks outside Element context, which is not what we want
				// Thanks to Andrew Dupont for this workaround technique
				// Support: IE <=8
				// Exclude object elements
				} else if ( context.nodeName.toLowerCase() !== "object" ) {

					// Capture the context ID, setting it first if necessary
					if ( (nid = context.getAttribute( "id" )) ) {
						nid = nid.replace( rescape, "\\CONTENT" );
					} else {
						context.setAttribute( "id", (nid = expando) );
					}

					// Prefix every selector in the list
					groups = tokenize( selector );
					i = groups.length;
					while ( i-- ) {
						groups[i] = "[id='" + nid + "'] " + toSelector( groups[i] );
					}
					newSelector = groups.join( "," );

					// Expand context for sibling selectors
					newContext = rsibling.test( selector ) && testContext( context.parentNode ) ||
						context;
				}

				if ( newSelector ) {
					try {
						push.apply( results,
							newContext.querySelectorAll( newSelector )
						);
						return results;
					} catch ( qsaError ) {
					} finally {
						if ( nid === expando ) {
							context.removeAttribute( "id" );
						}
					}
				}
			}
		}
	}

	// All others
	return select( selector.replace( rtrim, "$1" ), context, results, seed );
}

/**
 * Create key-value caches of limited size
 * @returns {function(string, object)} Returns the Object data after storing it on itself with
 *	property name the (space-suffixed) string and (if the cache is larger than Expr.cacheLength)
 *	deleting the oldest entry
 */
function createCache() {
	var keys = [];

	function cache( key, value ) {
		// Use (key + " ") to avoid collision with native prototype properties (see Issue #157)
		if ( keys.push( key + " " ) > Expr.cacheLength ) {
			// Only keep the most recent entries
			delete cache[ keys.shift() ];
		}
		return (cache[ key + " " ] = value);
	}
	return cache;
}

/**
 * Mark a function for special use by Sizzle
 * @param {Function} fn The function to mark
 */
function markFunction( fn ) {
	fn[ expando ] = true;
	return fn;
}

/**
 * Support testing using an element
 * @param {Function} fn Passed the created div and expects a boolean result
 */
function assert( fn ) {
	var div = document.createElement("div");

	try {
		return !!fn( div );
	} catch (e) {
		return false;
	} finally {
		// Remove from its parent by default
		if ( div.parentNode ) {
			div.parentNode.removeChild( div );
		}
		// release memory in IE
		div = null;
	}
}

/**
 * Adds the same handler for all of the specified attrs
 * @param {String} attrs Pipe-separated list of attributes
 * @param {Function} handler The method that will be applied
 */
function addHandle( attrs, handler ) {
	var arr = attrs.split("|"),
		i = attrs.length;

	while ( i-- ) {
		Expr.attrHandle[ arr[i] ] = handler;
	}
}

/**
 * Checks document order of two siblings
 * @param {Element} a
 * @param {Element} b
 * @returns {Number} Returns less than 0 if a precedes b, greater than 0 if a follows b
 */
function siblingCheck( a, b ) {
	var cur = b && a,
		diff = cur && a.nodeType === 1 && b.nodeType === 1 &&
			( ~b.sourceIndex || MAX_NEGATIVE ) -
			( ~a.sourceIndex || MAX_NEGATIVE );

	// Use IE sourceIndex if available on both nodes
	if ( diff ) {
		return diff;
	}

	// Check if b follows a
	if ( cur ) {
		while ( (cur = cur.nextSibling) ) {
			if ( cur === b ) {
				return -1;
			}
		}
	}

	return a ? 1 : -1;
}

/**
 * Returns a function to use in pseudos for input types
 * @param {String} type
 */
function createInputPseudo( type ) {
	return function( elem ) {
		var name = elem.nodeName.toLowerCase();
		return name === "input" && elem.type === type;
	};
}

/**
 * Returns a function to use in pseudos for buttons
 * @param {String} type
 */
function createButtonPseudo( type ) {
	return function( elem ) {
		var name = elem.nodeName.toLowerCase();
		return (name === "input" || name === "button") && elem.type === type;
	};
}

/**
 * Returns a function to use in pseudos for positionals
 * @param {Function} fn
 */
function createPositionalPseudo( fn ) {
	return markFunction(function( argument ) {
		argument = +argument;
		return markFunction(function( seed, matches ) {
			var j,
				matchIndexes = fn( [], seed.length, argument ),
				i = matchIndexes.length;

			// Match elements found at the specified indexes
			while ( i-- ) {
				if ( seed[ (j = matchIndexes[i]) ] ) {
					seed[j] = !(matches[j] = seed[j]);
				}
			}
		});
	});
}

/**
 * Checks a node for validity as a Sizzle context
 * @param {Element|Object=} context
 * @returns {Element|Object|Boolean} The input node if acceptable, otherwise a falsy value
 */
function testContext( context ) {
	return context && typeof context.getElementsByTagName !== "undefined" && context;
}

// Expose support vars for convenience
support = Sizzle.support = {};

/**
 * Detects XML nodes
 * @param {Element|Object} elem An element or a document
 * @returns {Boolean} True iff elem is a non-HTML XML node
 */
isXML = Sizzle.isXML = function( elem ) {
	// documentElement is verified for cases where it doesn't yet exist
	// (such as loading iframes in IE - #4833)
	var documentElement = elem && (elem.ownerDocument || elem).documentElement;
	return documentElement ? documentElement.nodeName !== "HTML" : false;
};

/**
 * Sets document-related variables once based on the current document
 * @param {Element|Object} [doc] An element or document object to use to set the document
 * @returns {Object} Returns the current document
 */
setDocument = Sizzle.setDocument = function( node ) {
	var hasCompare, parent,
		doc = node ? node.ownerDocument || node : preferredDoc;

	// Return early if doc is invalid or already selected
	if ( doc === document || doc.nodeType !== 9 || !doc.documentElement ) {
		return document;
	}

	// Update global variables
	document = doc;
	docElem = document.documentElement;
	documentIsHTML = !isXML( document );

	// Support: IE 9-11, Edge
	// Accessing iframe documents after unload throws "permission denied" errors (jQuery #13936)
	if ( (parent = document.defaultView) && parent.top !== parent ) {
		// Support: IE 11
		if ( parent.addEventListener ) {
			parent.addEventListener( "unload", unloadHandler, false );

		// Support: IE 9 - 10 only
		} else if ( parent.attachEvent ) {
			parent.attachEvent( "onunload", unloadHandler );
		}
	}

	/* Attributes
	---------------------------------------------------------------------- */

	// Support: IE<8
	// Verify that getAttribute really returns attributes and not properties
	// (excepting IE8 booleans)
	support.attributes = assert(function( div ) {
		div.className = "i";
		return !div.getAttribute("className");
	});

	/* getElement(s)By*
	---------------------------------------------------------------------- */

	// Check if getElementsByTagName("*") returns only elements
	support.getElementsByTagName = assert(function( div ) {
		div.appendChild( document.createComment("") );
		return !div.getElementsByTagName("*").length;
	});

	// Support: IE<9
	support.getElementsByClassName = rnative.test( document.getElementsByClassName );

	// Support: IE<10
	// Check if getElementById returns elements by name
	// The broken getElementById methods don't pick up programatically-set names,
	// so use a roundabout getElementsByName test
	support.getById = assert(function( div ) {
		docElem.appendChild( div ).id = expando;
		return !document.getElementsByName || !document.getElementsByName( expando ).length;
	});

	// ID find and filter
	if ( support.getById ) {
		Expr.find["ID"] = function( id, context ) {
			if ( typeof context.getElementById !== "undefined" && documentIsHTML ) {
				var m = context.getElementById( id );
				return m ? [ m ] : [];
			}
		};
		Expr.filter["ID"] = function( id ) {
			var attrId = id.replace( runescape, funescape );
			return function( elem ) {
				return elem.getAttribute("id") === attrId;
			};
		};
	} else {
		// Support: IE6/7
		// getElementById is not reliable as a find shortcut
		delete Expr.find["ID"];

		Expr.filter["ID"] =  function( id ) {
			var attrId = id.replace( runescape, funescape );
			return function( elem ) {
				var node = typeof elem.getAttributeNode !== "undefined" &&
					elem.getAttributeNode("id");
				return node && node.value === attrId;
			};
		};
	}

	// Tag
	Expr.find["TAG"] = support.getElementsByTagName ?
		function( tag, context ) {
			if ( typeof context.getElementsByTagName !== "undefined" ) {
				return context.getElementsByTagName( tag );

			// DocumentFragment nodes don't have gEBTN
			} else if ( support.qsa ) {
				return context.querySelectorAll( tag );
			}
		} :

		function( tag, context ) {
			var elem,
				tmp = [],
				i = 0,
				// By happy coincidence, a (broken) gEBTN appears on DocumentFragment nodes too
				results = context.getElementsByTagName( tag );

			// Filter out possible comments
			if ( tag === "*" ) {
				while ( (elem = results[i++]) ) {
					if ( elem.nodeType === 1 ) {
						tmp.push( elem );
					}
				}

				return tmp;
			}
			return results;
		};

	// Class
	Expr.find["CLASS"] = support.getElementsByClassName && function( className, context ) {
		if ( typeof context.getElementsByClassName !== "undefined" && documentIsHTML ) {
			return context.getElementsByClassName( className );
		}
	};

	/* QSA/matchesSelector
	---------------------------------------------------------------------- */

	// QSA and matchesSelector support

	// matchesSelector(:active) reports false when true (IE9/Opera 11.5)
	rbuggyMatches = [];

	// qSa(:focus) reports false when true (Chrome 21)
	// We allow this because of a bug in IE8/9 that throws an error
	// whenever `document.activeElement` is accessed on an iframe
	// So, we allow :focus to pass through QSA all the time to avoid the IE error
	// See http://bugs.jquery.com/ticket/13378
	rbuggyQSA = [];

	if ( (support.qsa = rnative.test( document.querySelectorAll )) ) {
		// Build QSA regex
		// Regex strategy adopted from Diego Perini
		assert(function( div ) {
			// Select is set to empty string on purpose
			// This is to test IE's treatment of not explicitly
			// setting a boolean content attribute,
			// since its presence should be enough
			// http://bugs.jquery.com/ticket/12359
			docElem.appendChild( div ).innerHTML = "<a id='" + expando + "'></a>" +
				"<select id='" + expando + "-\r\\' msallowcapture=''>" +
				"<option selected=''></option></select>";

			// Support: IE8, Opera 11-12.16
			// Nothing should be selected when empty strings follow ^= or $= or *=
			// The test attribute must be unknown in Opera but "safe" for WinRT
			// http://msdn.microsoft.com/en-us/library/ie/hh465388.aspx#attribute_section
			if ( div.querySelectorAll("[msallowcapture^='']").length ) {
				rbuggyQSA.push( "[*^$]=" + whitespace + "*(?:''|\"\")" );
			}

			// Support: IE8
			// Boolean attributes and "value" are not treated correctly
			if ( !div.querySelectorAll("[selected]").length ) {
				rbuggyQSA.push( "\\[" + whitespace + "*(?:value|" + booleans + ")" );
			}

			// Support: Chrome<29, Android<4.4, Safari<7.0+, iOS<7.0+, PhantomJS<1.9.8+
			if ( !div.querySelectorAll( "[id~=" + expando + "-]" ).length ) {
				rbuggyQSA.push("~=");
			}

			// Webkit/Opera - :checked should return selected option elements
			// http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked
			// IE8 throws error here and will not see later tests
			if ( !div.querySelectorAll(":checked").length ) {
				rbuggyQSA.push(":checked");
			}

			// Support: Safari 8+, iOS 8+
			// https://bugs.webkit.org/show_bug.cgi?id=136851
			// In-page `selector#id sibing-combinator selector` fails
			if ( !div.querySelectorAll( "a#" + expando + "+*" ).length ) {
				rbuggyQSA.push(".#.+[+~]");
			}
		});

		assert(function( div ) {
			// Support: Windows 8 Native Apps
			// The type and name attributes are restricted during .innerHTML assignment
			var input = document.createElement("input");
			input.setAttribute( "type", "hidden" );
			div.appendChild( input ).setAttribute( "name", "D" );

			// Support: IE8
			// Enforce case-sensitivity of name attribute
			if ( div.querySelectorAll("[name=d]").length ) {
				rbuggyQSA.push( "name" + whitespace + "*[*^$|!~]?=" );
			}

			// FF 3.5 - :enabled/:disabled and hidden elements (hidden elements are still enabled)
			// IE8 throws error here and will not see later tests
			if ( !div.querySelectorAll(":enabled").length ) {
				rbuggyQSA.push( ":enabled", ":disabled" );
			}

			// Opera 10-11 does not throw on post-comma invalid pseudos
			div.querySelectorAll("*,:x");
			rbuggyQSA.push(",.*:");
		});
	}

	if ( (support.matchesSelector = rnative.test( (matches = docElem.matches ||
		docElem.webkitMatchesSelector ||
		docElem.mozMatchesSelector ||
		docElem.oMatchesSelector ||
		docElem.msMatchesSelector) )) ) {

		assert(function( div ) {
			// Check to see if it's possible to do matchesSelector
			// on a disconnected node (IE 9)
			support.disconnectedMatch = matches.call( div, "div" );

			// This should fail with an exception
			// Gecko does not error, returns false instead
			matches.call( div, "[s!='']:x" );
			rbuggyMatches.push( "!=", pseudos );
		});
	}

	rbuggyQSA = rbuggyQSA.length && new RegExp( rbuggyQSA.join("|") );
	rbuggyMatches = rbuggyMatches.length && new RegExp( rbuggyMatches.join("|") );

	/* Contains
	---------------------------------------------------------------------- */
	hasCompare = rnative.test( docElem.compareDocumentPosition );

	// Element contains another
	// Purposefully self-exclusive
	// As in, an element does not contain itself
	contains = hasCompare || rnative.test( docElem.contains ) ?
		function( a, b ) {
			var adown = a.nodeType === 9 ? a.documentElement : a,
				bup = b && b.parentNode;
			return a === bup || !!( bup && bup.nodeType === 1 && (
				adown.contains ?
					adown.contains( bup ) :
					a.compareDocumentPosition && a.compareDocumentPosition( bup ) & 16
			));
		} :
		function( a, b ) {
			if ( b ) {
				while ( (b = b.parentNode) ) {
					if ( b === a ) {
						return true;
					}
				}
			}
			return false;
		};

	/* Sorting
	---------------------------------------------------------------------- */

	// Document order sorting
	sortOrder = hasCompare ?
	function( a, b ) {

		// Flag for duplicate removal
		if ( a === b ) {
			hasDuplicate = true;
			return 0;
		}

		// Sort on method existence if only one input has compareDocumentPosition
		var compare = !a.compareDocumentPosition - !b.compareDocumentPosition;
		if ( compare ) {
			return compare;
		}

		// Calculate position if both inputs belong to the same document
		compare = ( a.ownerDocument || a ) === ( b.ownerDocument || b ) ?
			a.compareDocumentPosition( b ) :

			// Otherwise we know they are disconnected
			1;

		// Disconnected nodes
		if ( compare & 1 ||
			(!support.sortDetached && b.compareDocumentPosition( a ) === compare) ) {

			// Choose the first element that is related to our preferred document
			if ( a === document || a.ownerDocument === preferredDoc && contains(preferredDoc, a) ) {
				return -1;
			}
			if ( b === document || b.ownerDocument === preferredDoc && contains(preferredDoc, b) ) {
				return 1;
			}

			// Maintain original order
			return sortInput ?
				( indexOf( sortInput, a ) - indexOf( sortInput, b ) ) :
				0;
		}

		return compare & 4 ? -1 : 1;
	} :
	function( a, b ) {
		// Exit early if the nodes are identical
		if ( a === b ) {
			hasDuplicate = true;
			return 0;
		}

		var cur,
			i = 0,
			aup = a.parentNode,
			bup = b.parentNode,
			ap = [ a ],
			bp = [ b ];

		// Parentless nodes are either documents or disconnected
		if ( !aup || !bup ) {
			return a === document ? -1 :
				b === document ? 1 :
				aup ? -1 :
				bup ? 1 :
				sortInput ?
				( indexOf( sortInput, a ) - indexOf( sortInput, b ) ) :
				0;

		// If the nodes are siblings, we can do a quick check
		} else if ( aup === bup ) {
			return siblingCheck( a, b );
		}

		// Otherwise we need full lists of their ancestors for comparison
		cur = a;
		while ( (cur = cur.parentNode) ) {
			ap.unshift( cur );
		}
		cur = b;
		while ( (cur = cur.parentNode) ) {
			bp.unshift( cur );
		}

		// Walk down the tree looking for a discrepancy
		while ( ap[i] === bp[i] ) {
			i++;
		}

		return i ?
			// Do a sibling check if the nodes have a common ancestor
			siblingCheck( ap[i], bp[i] ) :

			// Otherwise nodes in our document sort first
			ap[i] === preferredDoc ? -1 :
			bp[i] === preferredDoc ? 1 :
			0;
	};

	return document;
};

Sizzle.matches = function( expr, elements ) {
	return Sizzle( expr, null, null, elements );
};

Sizzle.matchesSelector = function( elem, expr ) {
	// Set document vars if needed
	if ( ( elem.ownerDocument || elem ) !== document ) {
		setDocument( elem );
	}

	// Make sure that attribute selectors are quoted
	expr = expr.replace( rattributeQuotes, "='$1']" );

	if ( support.matchesSelector && documentIsHTML &&
		!compilerCache[ expr + " " ] &&
		( !rbuggyMatches || !rbuggyMatches.test( expr ) ) &&
		( !rbuggyQSA     || !rbuggyQSA.test( expr ) ) ) {

		try {
			var ret = matches.call( elem, expr );

			// IE 9's matchesSelector returns false on disconnected nodes
			if ( ret || support.disconnectedMatch ||
					// As well, disconnected nodes are said to be in a document
					// fragment in IE 9
					elem.document && elem.document.nodeType !== 11 ) {
				return ret;
			}
		} catch (e) {}
	}

	return Sizzle( expr, document, null, [ elem ] ).length > 0;
};

Sizzle.contains = function( context, elem ) {
	// Set document vars if needed
	if ( ( context.ownerDocument || context ) !== document ) {
		setDocument( context );
	}
	return contains( context, elem );
};

Sizzle.attr = function( elem, name ) {
	// Set document vars if needed
	if ( ( elem.ownerDocument || elem ) !== document ) {
		setDocument( elem );
	}

	var fn = Expr.attrHandle[ name.toLowerCase() ],
		// Don't get fooled by Object.prototype properties (jQuery #13807)
		val = fn && hasOwn.call( Expr.attrHandle, name.toLowerCase() ) ?
			fn( elem, name, !documentIsHTML ) :
			undefined;

	return val !== undefined ?
		val :
		support.attributes || !documentIsHTML ?
			elem.getAttribute( name ) :
			(val = elem.getAttributeNode(name)) && val.specified ?
				val.value :
				null;
};

Sizzle.error = function( msg ) {
	throw new Error( "Syntax error, unrecognized expression: " + msg );
};

/**
 * Document sorting and removing duplicates
 * @param {ArrayLike} results
 */
Sizzle.uniqueSort = function( results ) {
	var elem,
		duplicates = [],
		j = 0,
		i = 0;

	// Unless we *know* we can detect duplicates, assume their presence
	hasDuplicate = !support.detectDuplicates;
	sortInput = !support.sortStable && results.slice( 0 );
	results.sort( sortOrder );

	if ( hasDuplicate ) {
		while ( (elem = results[i++]) ) {
			if ( elem === results[ i ] ) {
				j = duplicates.push( i );
			}
		}
		while ( j-- ) {
			results.splice( duplicates[ j ], 1 );
		}
	}

	// Clear input after sorting to release objects
	// See https://github.com/jquery/sizzle/pull/225
	sortInput = null;

	return results;
};

/**
 * Utility function for retrieving the text value of an array of DOM nodes
 * @param {Array|Element} elem
 */
getText = Sizzle.getText = function( elem ) {
	var node,
		ret = "",
		i = 0,
		nodeType = elem.nodeType;

	if ( !nodeType ) {
		// If no nodeType, this is expected to be an array
		while ( (node = elem[i++]) ) {
			// Do not traverse comment nodes
			ret += getText( node );
		}
	} else if ( nodeType === 1 || nodeType === 9 || nodeType === 11 ) {
		// Use textContent for elements
		// innerText usage removed for consistency of new lines (jQuery #11153)
		if ( typeof elem.textContent === "string" ) {
			return elem.textContent;
		} else {
			// Traverse its children
			for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) {
				ret += getText( elem );
			}
		}
	} else if ( nodeType === 3 || nodeType === 4 ) {
		return elem.nodeValue;
	}
	// Do not include comment or processing instruction nodes

	return ret;
};

Expr = Sizzle.selectors = {

	// Can be adjusted by the user
	cacheLength: 50,

	createPseudo: markFunction,

	match: matchExpr,

	attrHandle: {},

	find: {},

	relative: {
		">": { dir: "parentNode", first: true },
		" ": { dir: "parentNode" },
		"+": { dir: "previousSibling", first: true },
		"~": { dir: "previousSibling" }
	},

	preFilter: {
		"ATTR": function( match ) {
			match[1] = match[1].replace( runescape, funescape );

			// Move the given value to match[3] whether quoted or unquoted
			match[3] = ( match[3] || match[4] || match[5] || "" ).replace( runescape, funescape );

			if ( match[2] === "~=" ) {
				match[3] = " " + match[3] + " ";
			}

			return match.slice( 0, 4 );
		},

		"CHILD": function( match ) {
			/* matches from matchExpr["CHILD"]
				1 type (only|nth|...)
				2 what (child|of-type)
				3 argument (even|odd|\d*|\d*n([+-]\d+)?|...)
				4 xn-component of xn+y argument ([+-]?\d*n|)
				5 sign of xn-component
				6 x of xn-component
				7 sign of y-component
				8 y of y-component
			*/
			match[1] = match[1].toLowerCase();

			if ( match[1].slice( 0, 3 ) === "nth" ) {
				// nth-* requires argument
				if ( !match[3] ) {
					Sizzle.error( match[0] );
				}

				// numeric x and y parameters for Expr.filter.CHILD
				// remember that false/true cast respectively to 0/1
				match[4] = +( match[4] ? match[5] + (match[6] || 1) : 2 * ( match[3] === "even" || match[3] === "odd" ) );
				match[5] = +( ( match[7] + match[8] ) || match[3] === "odd" );

			// other types prohibit arguments
			} else if ( match[3] ) {
				Sizzle.error( match[0] );
			}

			return match;
		},

		"PSEUDO": function( match ) {
			var excess,
				unquoted = !match[6] && match[2];

			if ( matchExpr["CHILD"].test( match[0] ) ) {
				return null;
			}

			// Accept quoted arguments as-is
			if ( match[3] ) {
				match[2] = match[4] || match[5] || "";

			// Strip excess characters from unquoted arguments
			} else if ( unquoted && rpseudo.test( unquoted ) &&
				// Get excess from tokenize (recursively)
				(excess = tokenize( unquoted, true )) &&
				// advance to the next closing parenthesis
				(excess = unquoted.indexOf( ")", unquoted.length - excess ) - unquoted.length) ) {

				// excess is a negative index
				match[0] = match[0].slice( 0, excess );
				match[2] = unquoted.slice( 0, excess );
			}

			// Return only captures needed by the pseudo filter method (type and argument)
			return match.slice( 0, 3 );
		}
	},

	filter: {

		"TAG": function( nodeNameSelector ) {
			var nodeName = nodeNameSelector.replace( runescape, funescape ).toLowerCase();
			return nodeNameSelector === "*" ?
				function() { return true; } :
				function( elem ) {
					return elem.nodeName && elem.nodeName.toLowerCase() === nodeName;
				};
		},

		"CLASS": function( className ) {
			var pattern = classCache[ className + " " ];

			return pattern ||
				(pattern = new RegExp( "(^|" + whitespace + ")" + className + "(" + whitespace + "|$)" )) &&
				classCache( className, function( elem ) {
					return pattern.test( typeof elem.className === "string" && elem.className || typeof elem.getAttribute !== "undefined" && elem.getAttribute("class") || "" );
				});
		},

		"ATTR": function( name, operator, check ) {
			return function( elem ) {
				var result = Sizzle.attr( elem, name );

				if ( result == null ) {
					return operator === "!=";
				}
				if ( !operator ) {
					return true;
				}

				result += "";

				return operator === "=" ? result === check :
					operator === "!=" ? result !== check :
					operator === "^=" ? check && result.indexOf( check ) === 0 :
					operator === "*=" ? check && result.indexOf( check ) > -1 :
					operator === "$=" ? check && result.slice( -check.length ) === check :
					operator === "~=" ? ( " " + result.replace( rwhitespace, " " ) + " " ).indexOf( check ) > -1 :
					operator === "|=" ? result === check || result.slice( 0, check.length + 1 ) === check + "-" :
					false;
			};
		},

		"CHILD": function( type, what, argument, first, last ) {
			var simple = type.slice( 0, 3 ) !== "nth",
				forward = type.slice( -4 ) !== "last",
				ofType = what === "of-type";

			return first === 1 && last === 0 ?

				// Shortcut for :nth-*(n)
				function( elem ) {
					return !!elem.parentNode;
				} :

				function( elem, context, xml ) {
					var cache, uniqueCache, outerCache, node, nodeIndex, start,
						dir = simple !== forward ? "nextSibling" : "previousSibling",
						parent = elem.parentNode,
						name = ofType && elem.nodeName.toLowerCase(),
						useCache = !xml && !ofType,
						diff = false;

					if ( parent ) {

						// :(first|last|only)-(child|of-type)
						if ( simple ) {
							while ( dir ) {
								node = elem;
								while ( (node = node[ dir ]) ) {
									if ( ofType ?
										node.nodeName.toLowerCase() === name :
										node.nodeType === 1 ) {

										return false;
									}
								}
								// Reverse direction for :only-* (if we haven't yet done so)
								start = dir = type === "only" && !start && "nextSibling";
							}
							return true;
						}

						start = [ forward ? parent.firstChild : parent.lastChild ];

						// non-xml :nth-child(...) stores cache data on `parent`
						if ( forward && useCache ) {

							// Seek `elem` from a previously-cached index

							// ...in a gzip-friendly way
							node = parent;
							outerCache = node[ expando ] || (node[ expando ] = {});

							// Support: IE <9 only
							// Defend against cloned attroperties (jQuery gh-1709)
							uniqueCache = outerCache[ node.uniqueID ] ||
								(outerCache[ node.uniqueID ] = {});

							cache = uniqueCache[ type ] || [];
							nodeIndex = cache[ 0 ] === dirruns && cache[ 1 ];
							diff = nodeIndex && cache[ 2 ];
							node = nodeIndex && parent.childNodes[ nodeIndex ];

							while ( (node = ++nodeIndex && node && node[ dir ] ||

								// Fallback to seeking `elem` from the start
								(diff = nodeIndex = 0) || start.pop()) ) {

								// When found, cache indexes on `parent` and break
								if ( node.nodeType === 1 && ++diff && node === elem ) {
									uniqueCache[ type ] = [ dirruns, nodeIndex, diff ];
									break;
								}
							}

						} else {
							// Use previously-cached element index if available
							if ( useCache ) {
								// ...in a gzip-friendly way
								node = elem;
								outerCache = node[ expando ] || (node[ expando ] = {});

								// Support: IE <9 only
								// Defend against cloned attroperties (jQuery gh-1709)
								uniqueCache = outerCache[ node.uniqueID ] ||
									(outerCache[ node.uniqueID ] = {});

								cache = uniqueCache[ type ] || [];
								nodeIndex = cache[ 0 ] === dirruns && cache[ 1 ];
								diff = nodeIndex;
							}

							// xml :nth-child(...)
							// or :nth-last-child(...) or :nth(-last)?-of-type(...)
							if ( diff === false ) {
								// Use the same loop as above to seek `elem` from the start
								while ( (node = ++nodeIndex && node && node[ dir ] ||
									(diff = nodeIndex = 0) || start.pop()) ) {

									if ( ( ofType ?
										node.nodeName.toLowerCase() === name :
										node.nodeType === 1 ) &&
										++diff ) {

										// Cache the index of each encountered element
										if ( useCache ) {
											outerCache = node[ expando ] || (node[ expando ] = {});

											// Support: IE <9 only
											// Defend against cloned attroperties (jQuery gh-1709)
											uniqueCache = outerCache[ node.uniqueID ] ||
												(outerCache[ node.uniqueID ] = {});

											uniqueCache[ type ] = [ dirruns, diff ];
										}

										if ( node === elem ) {
											break;
										}
									}
								}
							}
						}

						// Incorporate the offset, then check against cycle size
						diff -= last;
						return diff === first || ( diff % first === 0 && diff / first >= 0 );
					}
				};
		},

		"PSEUDO": function( pseudo, argument ) {
			// pseudo-class names are case-insensitive
			// http://www.w3.org/TR/selectors/#pseudo-classes
			// Prioritize by case sensitivity in case custom pseudos are added with uppercase letters
			// Remember that setFilters inherits from pseudos
			var args,
				fn = Expr.pseudos[ pseudo ] || Expr.setFilters[ pseudo.toLowerCase() ] ||
					Sizzle.error( "unsupported pseudo: " + pseudo );

			// The user may use createPseudo to indicate that
			// arguments are needed to create the filter function
			// just as Sizzle does
			if ( fn[ expando ] ) {
				return fn( argument );
			}

			// But maintain support for old signatures
			if ( fn.length > 1 ) {
				args = [ pseudo, pseudo, "", argument ];
				return Expr.setFilters.hasOwnProperty( pseudo.toLowerCase() ) ?
					markFunction(function( seed, matches ) {
						var idx,
							matched = fn( seed, argument ),
							i = matched.length;
						while ( i-- ) {
							idx = indexOf( seed, matched[i] );
							seed[ idx ] = !( matches[ idx ] = matched[i] );
						}
					}) :
					function( elem ) {
						return fn( elem, 0, args );
					};
			}

			return fn;
		}
	},

	pseudos: {
		// Potentially complex pseudos
		"not": markFunction(function( selector ) {
			// Trim the selector passed to compile
			// to avoid treating leading and trailing
			// spaces as combinators
			var input = [],
				results = [],
				matcher = compile( selector.replace( rtrim, "$1" ) );

			return matcher[ expando ] ?
				markFunction(function( seed, matches, context, xml ) {
					var elem,
						unmatched = matcher( seed, null, xml, [] ),
						i = seed.length;

					// Match elements unmatched by `matcher`
					while ( i-- ) {
						if ( (elem = unmatched[i]) ) {
							seed[i] = !(matches[i] = elem);
						}
					}
				}) :
				function( elem, context, xml ) {
					input[0] = elem;
					matcher( input, null, xml, results );
					// Don't keep the element (issue #299)
					input[0] = null;
					return !results.pop();
				};
		}),

		"has": markFunction(function( selector ) {
			return function( elem ) {
				return Sizzle( selector, elem ).length > 0;
			};
		}),

		"contains": markFunction(function( text ) {
			text = text.replace( runescape, funescape );
			return function( elem ) {
				return ( elem.textContent || elem.innerText || getText( elem ) ).indexOf( text ) > -1;
			};
		}),

		// "Whether an element is represented by a :lang() selector
		// is based solely on the element's language value
		// being equal to the identifier C,
		// or beginning with the identifier C immediately followed by "-".
		// The matching of C against the element's language value is performed case-insensitively.
		// The identifier C does not have to be a valid language name."
		// http://www.w3.org/TR/selectors/#lang-pseudo
		"lang": markFunction( function( lang ) {
			// lang value must be a valid identifier
			if ( !ridentifier.test(lang || "") ) {
				Sizzle.error( "unsupported lang: " + lang );
			}
			lang = lang.replace( runescape, funescape ).toLowerCase();
			return function( elem ) {
				var elemLang;
				do {
					if ( (elemLang = documentIsHTML ?
						elem.lang :
						elem.getAttribute("xml:lang") || elem.getAttribute("lang")) ) {

						elemLang = elemLang.toLowerCase();
						return elemLang === lang || elemLang.indexOf( lang + "-" ) === 0;
					}
				} while ( (elem = elem.parentNode) && elem.nodeType === 1 );
				return false;
			};
		}),

		// Miscellaneous
		"target": function( elem ) {
			var hash = window.location && window.location.hash;
			return hash && hash.slice( 1 ) === elem.id;
		},

		"root": function( elem ) {
			return elem === docElem;
		},

		"focus": function( elem ) {
			return elem === document.activeElement && (!document.hasFocus || document.hasFocus()) && !!(elem.type || elem.href || ~elem.tabIndex);
		},

		// Boolean properties
		"enabled": function( elem ) {
			return elem.disabled === false;
		},

		"disabled": function( elem ) {
			return elem.disabled === true;
		},

		"checked": function( elem ) {
			// In CSS3, :checked should return both checked and selected elements
			// http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked
			var nodeName = elem.nodeName.toLowerCase();
			return (nodeName === "input" && !!elem.checked) || (nodeName === "option" && !!elem.selected);
		},

		"selected": function( elem ) {
			// Accessing this property makes selected-by-default
			// options in Safari work properly
			if ( elem.parentNode ) {
				elem.parentNode.selectedIndex;
			}

			return elem.selected === true;
		},

		// Contents
		"empty": function( elem ) {
			// http://www.w3.org/TR/selectors/#empty-pseudo
			// :empty is negated by element (1) or content nodes (text: 3; cdata: 4; entity ref: 5),
			//   but not by others (comment: 8; processing instruction: 7; etc.)
			// nodeType < 6 works because attributes (2) do not appear as children
			for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) {
				if ( elem.nodeType < 6 ) {
					return false;
				}
			}
			return true;
		},

		"parent": function( elem ) {
			return !Expr.pseudos["empty"]( elem );
		},

		// Element/input types
		"header": function( elem ) {
			return rheader.test( elem.nodeName );
		},

		"input": function( elem ) {
			return rinputs.test( elem.nodeName );
		},

		"button": function( elem ) {
			var name = elem.nodeName.toLowerCase();
			return name === "input" && elem.type === "button" || name === "button";
		},

		"text": function( elem ) {
			var attr;
			return elem.nodeName.toLowerCase() === "input" &&
				elem.type === "text" &&

				// Support: IE<8
				// New HTML5 attribute values (e.g., "search") appear with elem.type === "text"
				( (attr = elem.getAttribute("type")) == null || attr.toLowerCase() === "text" );
		},

		// Position-in-collection
		"first": createPositionalPseudo(function() {
			return [ 0 ];
		}),

		"last": createPositionalPseudo(function( matchIndexes, length ) {
			return [ length - 1 ];
		}),

		"eq": createPositionalPseudo(function( matchIndexes, length, argument ) {
			return [ argument < 0 ? argument + length : argument ];
		}),

		"even": createPositionalPseudo(function( matchIndexes, length ) {
			var i = 0;
			for ( ; i < length; i += 2 ) {
				matchIndexes.push( i );
			}
			return matchIndexes;
		}),

		"odd": createPositionalPseudo(function( matchIndexes, length ) {
			var i = 1;
			for ( ; i < length; i += 2 ) {
				matchIndexes.push( i );
			}
			return matchIndexes;
		}),

		"lt": createPositionalPseudo(function( matchIndexes, length, argument ) {
			var i = argument < 0 ? argument + length : argument;
			for ( ; --i >= 0; ) {
				matchIndexes.push( i );
			}
			return matchIndexes;
		}),

		"gt": createPositionalPseudo(function( matchIndexes, length, argument ) {
			var i = argument < 0 ? argument + length : argument;
			for ( ; ++i < length; ) {
				matchIndexes.push( i );
			}
			return matchIndexes;
		})
	}
};

Expr.pseudos["nth"] = Expr.pseudos["eq"];

// Add button/input type pseudos
for ( i in { radio: true, checkbox: true, file: true, password: true, image: true } ) {
	Expr.pseudos[ i ] = createInputPseudo( i );
}
for ( i in { submit: true, reset: true } ) {
	Expr.pseudos[ i ] = createButtonPseudo( i );
}

// Easy API for creating new setFilters
function setFilters() {}
setFilters.prototype = Expr.filters = Expr.pseudos;
Expr.setFilters = new setFilters();

tokenize = Sizzle.tokenize = function( selector, parseOnly ) {
	var matched, match, tokens, type,
		soFar, groups, preFilters,
		cached = tokenCache[ selector + " " ];

	if ( cached ) {
		return parseOnly ? 0 : cached.slice( 0 );
	}

	soFar = selector;
	groups = [];
	preFilters = Expr.preFilter;

	while ( soFar ) {

		// Comma and first run
		if ( !matched || (match = rcomma.exec( soFar )) ) {
			if ( match ) {
				// Don't consume trailing commas as valid
				soFar = soFar.slice( match[0].length ) || soFar;
			}
			groups.push( (tokens = []) );
		}

		matched = false;

		// Combinators
		if ( (match = rcombinators.exec( soFar )) ) {
			matched = match.shift();
			tokens.push({
				value: matched,
				// Cast descendant combinators to space
				type: match[0].replace( rtrim, " " )
			});
			soFar = soFar.slice( matched.length );
		}

		// Filters
		for ( type in Expr.filter ) {
			if ( (match = matchExpr[ type ].exec( soFar )) && (!preFilters[ type ] ||
				(match = preFilters[ type ]( match ))) ) {
				matched = match.shift();
				tokens.push({
					value: matched,
					type: type,
					matches: match
				});
				soFar = soFar.slice( matched.length );
			}
		}

		if ( !matched ) {
			break;
		}
	}

	// Return the length of the invalid excess
	// if we're just parsing
	// Otherwise, throw an error or return tokens
	return parseOnly ?
		soFar.length :
		soFar ?
			Sizzle.error( selector ) :
			// Cache the tokens
			tokenCache( selector, groups ).slice( 0 );
};

function toSelector( tokens ) {
	var i = 0,
		len = tokens.length,
		selector = "";
	for ( ; i < len; i++ ) {
		selector += tokens[i].value;
	}
	return selector;
}

function addCombinator( matcher, combinator, base ) {
	var dir = combinator.dir,
		checkNonElements = base && dir === "parentNode",
		doneName = done++;

	return combinator.first ?
		// Check against closest ancestor/preceding element
		function( elem, context, xml ) {
			while ( (elem = elem[ dir ]) ) {
				if ( elem.nodeType === 1 || checkNonElements ) {
					return matcher( elem, context, xml );
				}
			}
		} :

		// Check against all ancestor/preceding elements
		function( elem, context, xml ) {
			var oldCache, uniqueCache, outerCache,
				newCache = [ dirruns, doneName ];

			// We can't set arbitrary data on XML nodes, so they don't benefit from combinator caching
			if ( xml ) {
				while ( (elem = elem[ dir ]) ) {
					if ( elem.nodeType === 1 || checkNonElements ) {
						if ( matcher( elem, context, xml ) ) {
							return true;
						}
					}
				}
			} else {
				while ( (elem = elem[ dir ]) ) {
					if ( elem.nodeType === 1 || checkNonElements ) {
						outerCache = elem[ expando ] || (elem[ expando ] = {});

						// Support: IE <9 only
						// Defend against cloned attroperties (jQuery gh-1709)
						uniqueCache = outerCache[ elem.uniqueID ] || (outerCache[ elem.uniqueID ] = {});

						if ( (oldCache = uniqueCache[ dir ]) &&
							oldCache[ 0 ] === dirruns && oldCache[ 1 ] === doneName ) {

							// Assign to newCache so results back-propagate to previous elements
							return (newCache[ 2 ] = oldCache[ 2 ]);
						} else {
							// Reuse newcache so results back-propagate to previous elements
							uniqueCache[ dir ] = newCache;

							// A match means we're done; a fail means we have to keep checking
							if ( (newCache[ 2 ] = matcher( elem, context, xml )) ) {
								return true;
							}
						}
					}
				}
			}
		};
}

function elementMatcher( matchers ) {
	return matchers.length > 1 ?
		function( elem, context, xml ) {
			var i = matchers.length;
			while ( i-- ) {
				if ( !matchers[i]( elem, context, xml ) ) {
					return false;
				}
			}
			return true;
		} :
		matchers[0];
}

function multipleContexts( selector, contexts, results ) {
	var i = 0,
		len = contexts.length;
	for ( ; i < len; i++ ) {
		Sizzle( selector, contexts[i], results );
	}
	return results;
}

function condense( unmatched, map, filter, context, xml ) {
	var elem,
		newUnmatched = [],
		i = 0,
		len = unmatched.length,
		mapped = map != null;

	for ( ; i < len; i++ ) {
		if ( (elem = unmatched[i]) ) {
			if ( !filter || filter( elem, context, xml ) ) {
				newUnmatched.push( elem );
				if ( mapped ) {
					map.push( i );
				}
			}
		}
	}

	return newUnmatched;
}

function setMatcher( preFilter, selector, matcher, postFilter, postFinder, postSelector ) {
	if ( postFilter && !postFilter[ expando ] ) {
		postFilter = setMatcher( postFilter );
	}
	if ( postFinder && !postFinder[ expando ] ) {
		postFinder = setMatcher( postFinder, postSelector );
	}
	return markFunction(function( seed, results, context, xml ) {
		var temp, i, elem,
			preMap = [],
			postMap = [],
			preexisting = results.length,

			// Get initial elements from seed or context
			elems = seed || multipleContexts( selector || "*", context.nodeType ? [ context ] : context, [] ),

			// Prefilter to get matcher input, preserving a map for seed-results synchronization
			matcherIn = preFilter && ( seed || !selector ) ?
				condense( elems, preMap, preFilter, context, xml ) :
				elems,

			matcherOut = matcher ?
				// If we have a postFinder, or filtered seed, or non-seed postFilter or preexisting results,
				postFinder || ( seed ? preFilter : preexisting || postFilter ) ?

					// ...intermediate processing is necessary
					[] :

					// ...otherwise use results directly
					results :
				matcherIn;

		// Find primary matches
		if ( matcher ) {
			matcher( matcherIn, matcherOut, context, xml );
		}

		// Apply postFilter
		if ( postFilter ) {
			temp = condense( matcherOut, postMap );
			postFilter( temp, [], context, xml );

			// Un-match failing elements by moving them back to matcherIn
			i = temp.length;
			while ( i-- ) {
				if ( (elem = temp[i]) ) {
					matcherOut[ postMap[i] ] = !(matcherIn[ postMap[i] ] = elem);
				}
			}
		}

		if ( seed ) {
			if ( postFinder || preFilter ) {
				if ( postFinder ) {
					// Get the final matcherOut by condensing this intermediate into postFinder contexts
					temp = [];
					i = matcherOut.length;
					while ( i-- ) {
						if ( (elem = matcherOut[i]) ) {
							// Restore matcherIn since elem is not yet a final match
							temp.push( (matcherIn[i] = elem) );
						}
					}
					postFinder( null, (matcherOut = []), temp, xml );
				}

				// Move matched elements from seed to results to keep them synchronized
				i = matcherOut.length;
				while ( i-- ) {
					if ( (elem = matcherOut[i]) &&
						(temp = postFinder ? indexOf( seed, elem ) : preMap[i]) > -1 ) {

						seed[temp] = !(results[temp] = elem);
					}
				}
			}

		// Add elements to results, through postFinder if defined
		} else {
			matcherOut = condense(
				matcherOut === results ?
					matcherOut.splice( preexisting, matcherOut.length ) :
					matcherOut
			);
			if ( postFinder ) {
				postFinder( null, results, matcherOut, xml );
			} else {
				push.apply( results, matcherOut );
			}
		}
	});
}

function matcherFromTokens( tokens ) {
	var checkContext, matcher, j,
		len = tokens.length,
		leadingRelative = Expr.relative[ tokens[0].type ],
		implicitRelative = leadingRelative || Expr.relative[" "],
		i = leadingRelative ? 1 : 0,

		// The foundational matcher ensures that elements are reachable from top-level context(s)
		matchContext = addCombinator( function( elem ) {
			return elem === checkContext;
		}, implicitRelative, true ),
		matchAnyContext = addCombinator( function( elem ) {
			return indexOf( checkContext, elem ) > -1;
		}, implicitRelative, true ),
		matchers = [ function( elem, context, xml ) {
			var ret = ( !leadingRelative && ( xml || context !== outermostContext ) ) || (
				(checkContext = context).nodeType ?
					matchContext( elem, context, xml ) :
					matchAnyContext( elem, context, xml ) );
			// Avoid hanging onto element (issue #299)
			checkContext = null;
			return ret;
		} ];

	for ( ; i < len; i++ ) {
		if ( (matcher = Expr.relative[ tokens[i].type ]) ) {
			matchers = [ addCombinator(elementMatcher( matchers ), matcher) ];
		} else {
			matcher = Expr.filter[ tokens[i].type ].apply( null, tokens[i].matches );

			// Return special upon seeing a positional matcher
			if ( matcher[ expando ] ) {
				// Find the next relative operator (if any) for proper handling
				j = ++i;
				for ( ; j < len; j++ ) {
					if ( Expr.relative[ tokens[j].type ] ) {
						break;
					}
				}
				return setMatcher(
					i > 1 && elementMatcher( matchers ),
					i > 1 && toSelector(
						// If the preceding token was a descendant combinator, insert an implicit any-element `*`
						tokens.slice( 0, i - 1 ).concat({ value: tokens[ i - 2 ].type === " " ? "*" : "" })
					).replace( rtrim, "$1" ),
					matcher,
					i < j && matcherFromTokens( tokens.slice( i, j ) ),
					j < len && matcherFromTokens( (tokens = tokens.slice( j )) ),
					j < len && toSelector( tokens )
				);
			}
			matchers.push( matcher );
		}
	}

	return elementMatcher( matchers );
}

function matcherFromGroupMatchers( elementMatchers, setMatchers ) {
	var bySet = setMatchers.length > 0,
		byElement = elementMatchers.length > 0,
		superMatcher = function( seed, context, xml, results, outermost ) {
			var elem, j, matcher,
				matchedCount = 0,
				i = "0",
				unmatched = seed && [],
				setMatched = [],
				contextBackup = outermostContext,
				// We must always have either seed elements or outermost context
				elems = seed || byElement && Expr.find["TAG"]( "*", outermost ),
				// Use integer dirruns iff this is the outermost matcher
				dirrunsUnique = (dirruns += contextBackup == null ? 1 : Math.random() || 0.1),
				len = elems.length;

			if ( outermost ) {
				outermostContext = context === document || context || outermost;
			}

			// Add elements passing elementMatchers directly to results
			// Support: IE<9, Safari
			// Tolerate NodeList properties (IE: "length"; Safari: <number>) matching elements by id
			for ( ; i !== len && (elem = elems[i]) != null; i++ ) {
				if ( byElement && elem ) {
					j = 0;
					if ( !context && elem.ownerDocument !== document ) {
						setDocument( elem );
						xml = !documentIsHTML;
					}
					while ( (matcher = elementMatchers[j++]) ) {
						if ( matcher( elem, context || document, xml) ) {
							results.push( elem );
							break;
						}
					}
					if ( outermost ) {
						dirruns = dirrunsUnique;
					}
				}

				// Track unmatched elements for set filters
				if ( bySet ) {
					// They will have gone through all possible matchers
					if ( (elem = !matcher && elem) ) {
						matchedCount--;
					}

					// Lengthen the array for every element, matched or not
					if ( seed ) {
						unmatched.push( elem );
					}
				}
			}

			// `i` is now the count of elements visited above, and adding it to `matchedCount`
			// makes the latter nonnegative.
			matchedCount += i;

			// Apply set filters to unmatched elements
			// NOTE: This can be skipped if there are no unmatched elements (i.e., `matchedCount`
			// equals `i`), unless we didn't visit _any_ elements in the above loop because we have
			// no element matchers and no seed.
			// Incrementing an initially-string "0" `i` allows `i` to remain a string only in that
			// case, which will result in a "00" `matchedCount` that differs from `i` but is also
			// numerically zero.
			if ( bySet && i !== matchedCount ) {
				j = 0;
				while ( (matcher = setMatchers[j++]) ) {
					matcher( unmatched, setMatched, context, xml );
				}

				if ( seed ) {
					// Reintegrate element matches to eliminate the need for sorting
					if ( matchedCount > 0 ) {
						while ( i-- ) {
							if ( !(unmatched[i] || setMatched[i]) ) {
								setMatched[i] = pop.call( results );
							}
						}
					}

					// Discard index placeholder values to get only actual matches
					setMatched = condense( setMatched );
				}

				// Add matches to results
				push.apply( results, setMatched );

				// Seedless set matches succeeding multiple successful matchers stipulate sorting
				if ( outermost && !seed && setMatched.length > 0 &&
					( matchedCount + setMatchers.length ) > 1 ) {

					Sizzle.uniqueSort( results );
				}
			}

			// Override manipulation of globals by nested matchers
			if ( outermost ) {
				dirruns = dirrunsUnique;
				outermostContext = contextBackup;
			}

			return unmatched;
		};

	return bySet ?
		markFunction( superMatcher ) :
		superMatcher;
}

compile = Sizzle.compile = function( selector, match /* Internal Use Only */ ) {
	var i,
		setMatchers = [],
		elementMatchers = [],
		cached = compilerCache[ selector + " " ];

	if ( !cached ) {
		// Generate a function of recursive functions that can be used to check each element
		if ( !match ) {
			match = tokenize( selector );
		}
		i = match.length;
		while ( i-- ) {
			cached = matcherFromTokens( match[i] );
			if ( cached[ expando ] ) {
				setMatchers.push( cached );
			} else {
				elementMatchers.push( cached );
			}
		}

		// Cache the compiled function
		cached = compilerCache( selector, matcherFromGroupMatchers( elementMatchers, setMatchers ) );

		// Save selector and tokenization
		cached.selector = selector;
	}
	return cached;
};

/**
 * A low-level selection function that works with Sizzle's compiled
 *  selector functions
 * @param {String|Function} selector A selector or a pre-compiled
 *  selector function built with Sizzle.compile
 * @param {Element} context
 * @param {Array} [results]
 * @param {Array} [seed] A set of elements to match against
 */
select = Sizzle.select = function( selector, context, results, seed ) {
	var i, tokens, token, type, find,
		compiled = typeof selector === "function" && selector,
		match = !seed && tokenize( (selector = compiled.selector || selector) );

	results = results || [];

	// Try to minimize operations if there is only one selector in the list and no seed
	// (the latter of which guarantees us context)
	if ( match.length === 1 ) {

		// Reduce context if the leading compound selector is an ID
		tokens = match[0] = match[0].slice( 0 );
		if ( tokens.length > 2 && (token = tokens[0]).type === "ID" &&
				support.getById && context.nodeType === 9 && documentIsHTML &&
				Expr.relative[ tokens[1].type ] ) {

			context = ( Expr.find["ID"]( token.matches[0].replace(runescape, funescape), context ) || [] )[0];
			if ( !context ) {
				return results;

			// Precompiled matchers will still verify ancestry, so step up a level
			} else if ( compiled ) {
				context = context.parentNode;
			}

			selector = selector.slice( tokens.shift().value.length );
		}

		// Fetch a seed set for right-to-left matching
		i = matchExpr["needsContext"].test( selector ) ? 0 : tokens.length;
		while ( i-- ) {
			token = tokens[i];

			// Abort if we hit a combinator
			if ( Expr.relative[ (type = token.type) ] ) {
				break;
			}
			if ( (find = Expr.find[ type ]) ) {
				// Search, expanding context for leading sibling combinators
				if ( (seed = find(
					token.matches[0].replace( runescape, funescape ),
					rsibling.test( tokens[0].type ) && testContext( context.parentNode ) || context
				)) ) {

					// If seed is empty or no tokens remain, we can return early
					tokens.splice( i, 1 );
					selector = seed.length && toSelector( tokens );
					if ( !selector ) {
						push.apply( results, seed );
						return results;
					}

					break;
				}
			}
		}
	}

	// Compile and execute a filtering function if one is not provided
	// Provide `match` to avoid retokenization if we modified the selector above
	( compiled || compile( selector, match ) )(
		seed,
		context,
		!documentIsHTML,
		results,
		!context || rsibling.test( selector ) && testContext( context.parentNode ) || context
	);
	return results;
};

// One-time assignments

// Sort stability
support.sortStable = expando.split("").sort( sortOrder ).join("") === expando;

// Support: Chrome 14-35+
// Always assume duplicates if they aren't passed to the comparison function
support.detectDuplicates = !!hasDuplicate;

// Initialize against the default document
setDocument();

// Support: Webkit<537.32 - Safari 6.0.3/Chrome 25 (fixed in Chrome 27)
// Detached nodes confoundingly follow *each other*
support.sortDetached = assert(function( div1 ) {
	// Should return 1, but returns 4 (following)
	return div1.compareDocumentPosition( document.createElement("div") ) & 1;
});

// Support: IE<8
// Prevent attribute/property "interpolation"
// http://msdn.microsoft.com/en-us/library/ms536429%28VS.85%29.aspx
if ( !assert(function( div ) {
	div.innerHTML = "<a href='#'></a>";
	return div.firstChild.getAttribute("href") === "#" ;
}) ) {
	addHandle( "type|href|height|width", function( elem, name, isXML ) {
		if ( !isXML ) {
			return elem.getAttribute( name, name.toLowerCase() === "type" ? 1 : 2 );
		}
	});
}

// Support: IE<9
// Use defaultValue in place of getAttribute("value")
if ( !support.attributes || !assert(function( div ) {
	div.innerHTML = "<input/>";
	div.firstChild.setAttribute( "value", "" );
	return div.firstChild.getAttribute( "value" ) === "";
}) ) {
	addHandle( "value", function( elem, name, isXML ) {
		if ( !isXML && elem.nodeName.toLowerCase() === "input" ) {
			return elem.defaultValue;
		}
	});
}

// Support: IE<9
// Use getAttributeNode to fetch booleans when getAttribute lies
if ( !assert(function( div ) {
	return div.getAttribute("disabled") == null;
}) ) {
	addHandle( booleans, function( elem, name, isXML ) {
		var val;
		if ( !isXML ) {
			return elem[ name ] === true ? name.toLowerCase() :
					(val = elem.getAttributeNode( name )) && val.specified ?
					val.value :
				null;
		}
	});
}

// EXPOSE
if ( typeof define === "function" && define.amd ) {
	define(function() { return Sizzle; });
// Sizzle requires that there be a global window in Common-JS like environments
} else if ( typeof module !== "undefined" && module.exports ) {
	module.exports = Sizzle;
} else {
	window.Sizzle = Sizzle;
}
// EXPOSE

})( window );
;
})(window);


================================================
FILE: dist/types.js
================================================
"use strict";
// The goal of react-unit is to process react `instances` and turn them into
// `UnitComponents`. So, when all is said and done,react-unit looks like:
//
// function createComponent(instance:ReactInstance):UnitComponent;
//
// UnitComponent is a bit complex and deserves a whole file, see
// `unit-component.ts`.
Object.defineProperty(exports, "__esModule", { value: true });
exports.defaultRenderContext = ({
    instanceMapper: function (i) { return i; },
    componentMapper: function (c) { return c; },
    resolveMapper: function (r) { return r; }
});
// === Type guards ========================================================== //
exports.isShallow = function (c) {
    return c.type === 'shallow';
};
exports.isHtml = function (c) {
    return c.type === 'html' || c.type === 'artificial';
};
exports.isArtificialHtml = function (c) {
    return c.type === 'artificial';
};
exports.isUnknown = function (c) {
    return c.type === 'unknown';
};


================================================
FILE: dist/unit-component.js
================================================
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var R = require("ramda");
var types_1 = require("./types");
var utils_1 = require("./utils");
var sizzle = require("./sizzle-bundle");
var ROOT = 'root';
var isNotRoot = function (c) { return c !== ROOT; };
// Component wrapper
var UnitComponent = /** @class */ (function () {
    function UnitComponent(comp, parent, renderNew) {
        this.nodeType = 1;
        this.type = comp.tagName;
        this.key = comp.key;
        this.ref = comp.ref;
        this.props = comp.props;
        this.texts = [];
        this.comp = comp;
        this.renderNew = renderNew;
        // Mock root parent (to enable top-level "[attr=value]")
        if (!parent) {
            this.root = new UnitComponent({}, ROOT, undefined);
            this.root.props = { children: this };
            this.parentNode = this.root;
        }
        else if (isNotRoot(parent)) {
            this.parentNode = parent;
        }
        // Mock DOM
        this.ownerDocument = global.document;
        this.nodeName = this.type;
    }
    UnitComponent.prototype.prop = function (name) { return (this.props || {})[name]; };
    UnitComponent.prototype.findBy = function (fn) {
        var ret = [];
        if (fn(this))
            ret.push(this);
        var children = this.prop('children');
        if (!children || utils_1.isText(children))
            return ret;
        if (children.length === undefined)
            children = [children];
        return R.compose(R.concat(ret), R.filter(function (c) { return !!c; }), R.flatten, R.map(function (c) { return c.findBy && c.findBy(fn); }))(children);
    };
    UnitComponent.prototype.findByRef = function (ref) {
        return this.findBy(function (c) { return c.ref == ref; });
    };
    UnitComponent.prototype.findByTag = function (type) {
        return this.findBy(type == '*' ? (function (c) { return true; }) : (function (c) { return c.type == type; }));
    };
    UnitComponent.prototype.findByClassName = function (search) {
        var pattern = new RegExp('(^|\\s)' + search + '(\\s|$)');
        return this.findBy(function (e) { return pattern.test(e.prop('className')); });
    };
    UnitComponent.prototype.findByComponent = function (componentClass) {
        return this.findBy(function (e) {
            return types_1.isArtificialHtml(e.comp) && utils_1.isOfType(componentClass, e.comp);
        });
    };
    UnitComponent.prototype.on = function (event, e) {
        event = "on" + (event[0].toUpperCase() + event.slice(1));
        var handler = this.props[event];
        if (!handler)
            throw "Triggered unhandled " + event + " event: " + new Error().stack;
        return handler(e);
    };
    UnitComponent.prototype.onChange = function (e) { this.on('change', e); };
    UnitComponent.prototype.onClick = function (e) { this.on('click', e); };
    UnitComponent.prototype.setValueKey = function (n, v) {
        this.onChange({ target: R.merge(this.props, (_a = {}, _a[n] = v, _a)) });
        var _a;
    };
    UnitComponent.prototype.setValue = function (v) { this.setValueKey('value', v); };
    UnitComponent.prototype.setChecked = function (v) { this.setValueKey('checked', v); };
    UnitComponent.prototype.findByQuery = function (s) {
        try {
            return sizzle(s, this.root || this);
        }
        catch (e) {
            console.log('Sizzle error', e.stack);
            throw e;
        }
    };
    UnitComponent.prototype.dump = function (padd) {
        if (!padd)
            padd = '';
        var children = this.prop('children');
        var tag = this.type + R.compose(R.join(''), R.map(function (_a) {
            var k = _a[0], v = _a[1];
            return " " + k + "='" + v + "'";
        }), R.filter(function (_a) {
            var _ = _a[0], v = _a[1];
            return utils_1.isText(v) && (!!v || v === 0);
        }), R.toPairs, R.merge({ key: this.key, ref: this.ref }), R.omit(['children']))(this.props);
        if (!children || children.length === 0) {
            return this.text
                ? padd + "<" + tag + ">" + this.text + "</" + this.type + ">\n"
                : padd + "<" + tag + " />\n";
        }
        if (utils_1.isText(children)) {
            return padd + "<" + tag + ">" + children + "</" + this.type + ">\n";
        }
        if (children.length === undefined)
            children = [children];
        var texts = children
            .map(function (c) { return c.dump(padd + '  '); })
            .join('');
        return padd + "<" + tag + ">\n" + texts + padd + "</" + this.type + ">\n";
    };
    Object.defineProperty(UnitComponent.prototype, "children", {
        get: function () {
            return this.props.children;
        },
        enumerable: true,
        configurable: true
    });
    Object.defineProperty(UnitComponent.prototype, "textContent", {
        get: function () {
            return this.text;
        },
        enumerable: true,
        configurable: true
    });
    UnitComponent.prototype.getElementsByTagName = function (tagName) {
        return this.findByTag(tagName);
    };
    UnitComponent.prototype.getElementsByClassName = function (className) {
        return this.findByClassName(className);
    };
    ;
    UnitComponent.prototype.getAttribute = function (name) {
        return this.prop(name == 'class' ? 'className' : name);
    };
    UnitComponent.prototype.getAttributeNode = function (name) {
        var prop = this.prop(name);
        return { value: prop, specified: prop !== undefined };
    };
    ;
    return UnitComponent;
}());
exports.UnitComponent = UnitComponent;


================================================
FILE: dist/utils.js
================================================
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var ramda_1 = require("ramda");
var test_utils_1 = require("react-dom/test-utils");
var types_1 = require("./types");
var notText = ['object', 'function'];
exports.isText = function (v) { return !ramda_1.contains(typeof v, notText); };
exports.isOfType = function (type, comp) {
    return (types_1.isHtml(comp) || types_1.isShallow(comp)) && test_utils_1.isElementOfType(comp.instance, type);
};
exports.getTagNameForType = function (type) {
    return type.displayName || type.name || 'anonymous-component';
};
function filterChildren(fn, comp) {
    return types_1.isHtml(comp)
        ? ramda_1.merge(comp, {
            children: comp.children.filter(fn).map(function (c) { return filterChildren(fn, c); })
        })
        : comp;
}
exports.filterChildren = filterChildren;


================================================
FILE: dist/wrapper.js
================================================
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var types_1 = require("./types");
var unit_component_1 = require("./unit-component");
function wrapRenderedIntoUnitComponent(parent, htmlComponent, componentPipeline) {
    var unitComponent = new unit_component_1.UnitComponent(htmlComponent, parent, componentPipeline(htmlComponent));
    var children = [];
    var texts = [];
    htmlComponent.children.forEach(function (c) {
        if (types_1.isUnknown(c)) {
            var unknown = c.unknown;
            if (unknown !== undefined && unknown !== null) {
                texts.push(unknown.toString());
            }
        }
        else if (types_1.isHtml(c)) {
            var child = wrapRenderedIntoUnitComponent(unitComponent, c, componentPipeline);
            children.push(child);
            texts = texts.concat(child.texts);
        }
        // we ignore NotRenderedReactComponents
    });
    unitComponent.props.children = children;
    unitComponent.texts = texts;
    unitComponent.text = texts.join('');
    return unitComponent;
}
exports.default = wrapRenderedIntoUnitComponent;


================================================
FILE: gulpfile.js
================================================
"use strict"

var gulp        = require('gulp');
var babel       = require('gulp-babel');
var insert      = require('gulp-insert');
var rename      = require('gulp-rename');
var jasmine     = require('gulp-jasmine');
var runSequence = require('run-sequence');
var fs          = require('fs');
var path        = require('path');
var del         = require('del');
var ts          = require("gulp-typescript");

gulp.task('default', ['test']);

gulp.task('clean', function(cb) { del('./dist', cb); });

gulp.task('build', function(cb) {
  runSequence(
    'clean',
    ['build-sizzle', 'build-ts'],
    cb
  );
});

gulp.task('build-ts', function() {
  var tsconfig = JSON.parse(
    fs.readFileSync(path.join(__dirname, 'tsconfig.json'))
  );
  var opts = tsconfig.compilerOptions;
  opts.typescript = require('typescript');

  return gulp.src(tsconfig.filesGlob)
     .pipe(ts(opts))
     .pipe(gulp.dest("./dist"));
});

gulp.task('build-sizzle', function () {
  var content = fs.readFileSync('./lib/sizzle.js');
  return gulp.src('./lib/sizzle-bundle.js')
    .pipe(insert.transform(function(s) {return s.replace('CONTENT', content)}))
    .pipe(gulp.dest('./src'))
    .pipe(gulp.dest('./dist'));
});

gulp.task('build-test', ['build'], function() {
  return gulp.src('./test/**/*.jsx')
    .pipe(babel())
    .pipe(rename({prefix: 'test-'}))
    .pipe(gulp.dest('./dist'));
});

gulp.task('test', ['build-test'], function () {
  return gulp.src('dist/**/test-*.js')
    .pipe(jasmine({verbose: true, includeStackTrace: true}));
});


================================================
FILE: lib/sizzle-bundle.js
================================================

var document = {
	createElement: function(tag) {
		return {
			appendChild: function() {},
			getElementsByTagName: function() { return []; },
			getAttribute: function() {}
		}
	},
	createComment: function(s) { return s; },
	getElementsByClassName: ' { [native code] }',
	nodeType: 9,
	documentElement: { nodeName: 'HTML' }
};
document.ownerDocument = document;
var window = { document: document };

var _ = (function() {
	CONTENT;
})(window);


================================================
FILE: lib/sizzle.js
================================================
/*!
 * Sizzle CSS Selector Engine v2.2.1-pre
 * http://sizzlejs.com/
 *
 * Copyright jQuery Foundation and other contributors
 * Released under the MIT license
 * http://jquery.org/license
 *
 * Date: 2015-08-17
 */
(function( window ) {

var i,
	support,
	Expr,
	getText,
	isXML,
	tokenize,
	compile,
	select,
	outermostContext,
	sortInput,
	hasDuplicate,

	// Local document vars
	setDocument,
	document,
	docElem,
	documentIsHTML,
	rbuggyQSA,
	rbuggyMatches,
	matches,
	contains,

	// Instance-specific data
	expando = "sizzle" + 1 * new Date(),
	preferredDoc = window.document,
	dirruns = 0,
	done = 0,
	classCache = createCache(),
	tokenCache = createCache(),
	compilerCache = createCache(),
	sortOrder = function( a, b ) {
		if ( a === b ) {
			hasDuplicate = true;
		}
		return 0;
	},

	// General-purpose constants
	MAX_NEGATIVE = 1 << 31,

	// Instance methods
	hasOwn = ({}).hasOwnProperty,
	arr = [],
	pop = arr.pop,
	push_native = arr.push,
	push = arr.push,
	slice = arr.slice,
	// Use a stripped-down indexOf as it's faster than native
	// http://jsperf.com/thor-indexof-vs-for/5
	indexOf = function( list, elem ) {
		var i = 0,
			len = list.length;
		for ( ; i < len; i++ ) {
			if ( list[i] === elem ) {
				return i;
			}
		}
		return -1;
	},

	booleans = "checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped",

	// Regular expressions

	// http://www.w3.org/TR/css3-selectors/#whitespace
	whitespace = "[\\x20\\t\\r\\n\\f]",

	// http://www.w3.org/TR/CSS21/syndata.html#value-def-identifier
	identifier = "(?:\\\\.|[\\w-]|[^\\x00-\\xa0])+",

	// Attribute selectors: http://www.w3.org/TR/selectors/#attribute-selectors
	attributes = "\\[" + whitespace + "*(" + identifier + ")(?:" + whitespace +
		// Operator (capture 2)
		"*([*^$|!~]?=)" + whitespace +
		// "Attribute values must be CSS identifiers [capture 5] or strings [capture 3 or capture 4]"
		"*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|(" + identifier + "))|)" + whitespace +
		"*\\]",

	pseudos = ":(" + identifier + ")(?:\\((" +
		// To reduce the number of selectors needing tokenize in the preFilter, prefer arguments:
		// 1. quoted (capture 3; capture 4 or capture 5)
		"('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|" +
		// 2. simple (capture 6)
		"((?:\\\\.|[^\\\\()[\\]]|" + attributes + ")*)|" +
		// 3. anything else (capture 2)
		".*" +
		")\\)|)",

	// Leading and non-escaped trailing whitespace, capturing some non-whitespace characters preceding the latter
	rwhitespace = new RegExp( whitespace + "+", "g" ),
	rtrim = new RegExp( "^" + whitespace + "+|((?:^|[^\\\\])(?:\\\\.)*)" + whitespace + "+$", "g" ),

	rcomma = new RegExp( "^" + whitespace + "*," + whitespace + "*" ),
	rcombinators = new RegExp( "^" + whitespace + "*([>+~]|" + whitespace + ")" + whitespace + "*" ),

	rattributeQuotes = new RegExp( "=" + whitespace + "*([^\\]'\"]*?)" + whitespace + "*\\]", "g" ),

	rpseudo = new RegExp( pseudos ),
	ridentifier = new RegExp( "^" + identifier + "$" ),

	matchExpr = {
		"ID": new RegExp( "^#(" + identifier + ")" ),
		"CLASS": new RegExp( "^\\.(" + identifier + ")" ),
		"TAG": new RegExp( "^(" + identifier + "|[*])" ),
		"ATTR": new RegExp( "^" + attributes ),
		"PSEUDO": new RegExp( "^" + pseudos ),
		"CHILD": new RegExp( "^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\(" + whitespace +
			"*(even|odd|(([+-]|)(\\d*)n|)" + whitespace + "*(?:([+-]|)" + whitespace +
			"*(\\d+)|))" + whitespace + "*\\)|)", "i" ),
		"bool": new RegExp( "^(?:" + booleans + ")$", "i" ),
		// For use in libraries implementing .is()
		// We use this for POS matching in `select`
		"needsContext": new RegExp( "^" + whitespace + "*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\(" +
			whitespace + "*((?:-\\d)?\\d*)" + whitespace + "*\\)|)(?=[^-]|$)", "i" )
	},

	rinputs = /^(?:input|select|textarea|button)$/i,
	rheader = /^h\d$/i,

	rnative = /^[^{]+\{\s*\[native \w/,

	// Easily-parseable/retrievable ID or TAG or CLASS selectors
	rquickExpr = /^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,

	rsibling = /[+~]/,
	rescape = /'|\\/g,

	// CSS escapes http://www.w3.org/TR/CSS21/syndata.html#escaped-characters
	runescape = new RegExp( "\\\\([\\da-f]{1,6}" + whitespace + "?|(" + whitespace + ")|.)", "ig" ),
	funescape = function( _, escaped, escapedWhitespace ) {
		var high = "0x" + escaped - 0x10000;
		// NaN means non-codepoint
		// Support: Firefox<24
		// Workaround erroneous numeric interpretation of +"0x"
		return high !== high || escapedWhitespace ?
			escaped :
			high < 0 ?
				// BMP codepoint
				String.fromCharCode( high + 0x10000 ) :
				// Supplemental Plane codepoint (surrogate pair)
				String.fromCharCode( high >> 10 | 0xD800, high & 0x3FF | 0xDC00 );
	},

	// Used for iframes
	// See setDocument()
	// Removing the function wrapper causes a "Permission Denied"
	// error in IE
	unloadHandler = function() {
		setDocument();
	};

// Optimize for push.apply( _, NodeList )
try {
	push.apply(
		(arr = slice.call( preferredDoc.childNodes )),
		preferredDoc.childNodes
	);
	// Support: Android<4.0
	// Detect silently failing push.apply
	arr[ preferredDoc.childNodes.length ].nodeType;
} catch ( e ) {
	push = { apply: arr.length ?

		// Leverage slice if possible
		function( target, els ) {
			push_native.apply( target, slice.call(els) );
		} :

		// Support: IE<9
		// Otherwise append directly
		function( target, els ) {
			var j = target.length,
				i = 0;
			// Can't trust NodeList.length
			while ( (target[j++] = els[i++]) ) {}
			target.length = j - 1;
		}
	};
}

function Sizzle( selector, context, results, seed ) {
	var m, i, elem, nid, match, groups, newSelector,
		newContext = context && context.ownerDocument,

		// nodeType defaults to 9, since context defaults to document
		nodeType = context ? context.nodeType : 9;

	results = results || [];

	// Return early from calls with invalid selector or context
	if ( typeof selector !== "string" || !selector ||
		nodeType !== 1 && nodeType !== 9 && nodeType !== 11 ) {

		return results;
	}

	// Try to shortcut find operations (as opposed to filters) in HTML documents
	if ( !seed ) {

		if ( ( context ? context.ownerDocument || context : preferredDoc ) !== document ) {
			setDocument( context );
		}
		context = context || document;

		if ( documentIsHTML ) {

			// If the selector is sufficiently simple, try using a "get*By*" DOM method
			// (excepting DocumentFragment context, where the methods don't exist)
			if ( nodeType !== 11 && (match = rquickExpr.exec( selector )) ) {

				// ID selector
				if ( (m = match[1]) ) {

					// Document context
					if ( nodeType === 9 ) {
						if ( (elem = context.getElementById( m )) ) {

							// Support: IE, Opera, Webkit
							// TODO: identify versions
							// getElementById can match elements by name instead of ID
							if ( elem.id === m ) {
								results.push( elem );
								return results;
							}
						} else {
							return results;
						}

					// Element context
					} else {

						// Support: IE, Opera, Webkit
						// TODO: identify versions
						// getElementById can match elements by name instead of ID
						if ( newContext && (elem = newContext.getElementById( m )) &&
							contains( context, elem ) &&
							elem.id === m ) {

							results.push( elem );
							return results;
						}
					}

				// Type selector
				} else if ( match[2] ) {
					push.apply( results, context.getElementsByTagName( selector ) );
					return results;

				// Class selector
				} else if ( (m = match[3]) && support.getElementsByClassName &&
					context.getElementsByClassName ) {

					push.apply( results, context.getElementsByClassName( m ) );
					return results;
				}
			}

			// Take advantage of querySelectorAll
			if ( support.qsa &&
				!compilerCache[ selector + " " ] &&
				(!rbuggyQSA || !rbuggyQSA.test( selector )) ) {

				if ( nodeType !== 1 ) {
					newContext = context;
					newSelector = selector;

				// qSA looks outside Element context, which is not what we want
				// Thanks to Andrew Dupont for this workaround technique
				// Support: IE <=8
				// Exclude object elements
				} else if ( context.nodeName.toLowerCase() !== "object" ) {

					// Capture the context ID, setting it first if necessary
					if ( (nid = context.getAttribute( "id" )) ) {
						nid = nid.replace( rescape, "\\$&" );
					} else {
						context.setAttribute( "id", (nid = expando) );
					}

					// Prefix every selector in the list
					groups = tokenize( selector );
					i = groups.length;
					while ( i-- ) {
						groups[i] = "[id='" + nid + "'] " + toSelector( groups[i] );
					}
					newSelector = groups.join( "," );

					// Expand context for sibling selectors
					newContext = rsibling.test( selector ) && testContext( context.parentNode ) ||
						context;
				}

				if ( newSelector ) {
					try {
						push.apply( results,
							newContext.querySelectorAll( newSelector )
						);
						return results;
					} catch ( qsaError ) {
					} finally {
						if ( nid === expando ) {
							context.removeAttribute( "id" );
						}
					}
				}
			}
		}
	}

	// All others
	return select( selector.replace( rtrim, "$1" ), context, results, seed );
}

/**
 * Create key-value caches of limited size
 * @returns {function(string, object)} Returns the Object data after storing it on itself with
 *	property name the (space-suffixed) string and (if the cache is larger than Expr.cacheLength)
 *	deleting the oldest entry
 */
function createCache() {
	var keys = [];

	function cache( key, value ) {
		// Use (key + " ") to avoid collision with native prototype properties (see Issue #157)
		if ( keys.push( key + " " ) > Expr.cacheLength ) {
			// Only keep the most recent entries
			delete cache[ keys.shift() ];
		}
		return (cache[ key + " " ] = value);
	}
	return cache;
}

/**
 * Mark a function for special use by Sizzle
 * @param {Function} fn The function to mark
 */
function markFunction( fn ) {
	fn[ expando ] = true;
	return fn;
}

/**
 * Support testing using an element
 * @param {Function} fn Passed the created div and expects a boolean result
 */
function assert( fn ) {
	var div = document.createElement("div");

	try {
		return !!fn( div );
	} catch (e) {
		return false;
	} finally {
		// Remove from its parent by default
		if ( div.parentNode ) {
			div.parentNode.removeChild( div );
		}
		// release memory in IE
		div = null;
	}
}

/**
 * Adds the same handler for all of the specified attrs
 * @param {String} attrs Pipe-separated list of attributes
 * @param {Function} handler The method that will be applied
 */
function addHandle( attrs, handler ) {
	var arr = attrs.split("|"),
		i = attrs.length;

	while ( i-- ) {
		Expr.attrHandle[ arr[i] ] = handler;
	}
}

/**
 * Checks document order of two siblings
 * @param {Element} a
 * @param {Element} b
 * @returns {Number} Returns less than 0 if a precedes b, greater than 0 if a follows b
 */
function siblingCheck( a, b ) {
	var cur = b && a,
		diff = cur && a.nodeType === 1 && b.nodeType === 1 &&
			( ~b.sourceIndex || MAX_NEGATIVE ) -
			( ~a.sourceIndex || MAX_NEGATIVE );

	// Use IE sourceIndex if available on both nodes
	if ( diff ) {
		return diff;
	}

	// Check if b follows a
	if ( cur ) {
		while ( (cur = cur.nextSibling) ) {
			if ( cur === b ) {
				return -1;
			}
		}
	}

	return a ? 1 : -1;
}

/**
 * Returns a function to use in pseudos for input types
 * @param {String} type
 */
function createInputPseudo( type ) {
	return function( elem ) {
		var name = elem.nodeName.toLowerCase();
		return name === "input" && elem.type === type;
	};
}

/**
 * Returns a function to use in pseudos for buttons
 * @param {String} type
 */
function createButtonPseudo( type ) {
	return function( elem ) {
		var name = elem.nodeName.toLowerCase();
		return (name === "input" || name === "button") && elem.type === type;
	};
}

/**
 * Returns a function to use in pseudos for positionals
 * @param {Function} fn
 */
function createPositionalPseudo( fn ) {
	return markFunction(function( argument ) {
		argument = +argument;
		return markFunction(function( seed, matches ) {
			var j,
				matchIndexes = fn( [], seed.length, argument ),
				i = matchIndexes.length;

			// Match elements found at the specified indexes
			while ( i-- ) {
				if ( seed[ (j = matchIndexes[i]) ] ) {
					seed[j] = !(matches[j] = seed[j]);
				}
			}
		});
	});
}

/**
 * Checks a node for validity as a Sizzle context
 * @param {Element|Object=} context
 * @returns {Element|Object|Boolean} The input node if acceptable, otherwise a falsy value
 */
function testContext( context ) {
	return context && typeof context.getElementsByTagName !== "undefined" && context;
}

// Expose support vars for convenience
support = Sizzle.support = {};

/**
 * Detects XML nodes
 * @param {Element|Object} elem An element or a document
 * @returns {Boolean} True iff elem is a non-HTML XML node
 */
isXML = Sizzle.isXML = function( elem ) {
	// documentElement is verified for cases where it doesn't yet exist
	// (such as loading iframes in IE - #4833)
	var documentElement = elem && (elem.ownerDocument || elem).documentElement;
	return documentElement ? documentElement.nodeName !== "HTML" : false;
};

/**
 * Sets document-related variables once based on the current document
 * @param {Element|Object} [doc] An element or document object to use to set the document
 * @returns {Object} Returns the current document
 */
setDocument = Sizzle.setDocument = function( node ) {
	var hasCompare, parent,
		doc = node ? node.ownerDocument || node : preferredDoc;

	// Return early if doc is invalid or already selected
	if ( doc === document || doc.nodeType !== 9 || !doc.documentElement ) {
		return document;
	}

	// Update global variables
	document = doc;
	docElem = document.documentElement;
	documentIsHTML = !isXML( document );

	// Support: IE 9-11, Edge
	// Accessing iframe documents after unload throws "permission denied" errors (jQuery #13936)
	if ( (parent = document.defaultView) && parent.top !== parent ) {
		// Support: IE 11
		if ( parent.addEventListener ) {
			parent.addEventListener( "unload", unloadHandler, false );

		// Support: IE 9 - 10 only
		} else if ( parent.attachEvent ) {
			parent.attachEvent( "onunload", unloadHandler );
		}
	}

	/* Attributes
	---------------------------------------------------------------------- */

	// Support: IE<8
	// Verify that getAttribute really returns attributes and not properties
	// (excepting IE8 booleans)
	support.attributes = assert(function( div ) {
		div.className = "i";
		return !div.getAttribute("className");
	});

	/* getElement(s)By*
	---------------------------------------------------------------------- */

	// Check if getElementsByTagName("*") returns only elements
	support.getElementsByTagName = assert(function( div ) {
		div.appendChild( document.createComment("") );
		return !div.getElementsByTagName("*").length;
	});

	// Support: IE<9
	support.getElementsByClassName = rnative.test( document.getElementsByClassName );

	// Support: IE<10
	// Check if getElementById returns elements by name
	// The broken getElementById methods don't pick up programatically-set names,
	// so use a roundabout getElementsByName test
	support.getById = assert(function( div ) {
		docElem.appendChild( div ).id = expando;
		return !document.getElementsByName || !document.getElementsByName( expando ).length;
	});

	// ID find and filter
	if ( support.getById ) {
		Expr.find["ID"] = function( id, context ) {
			if ( typeof context.getElementById !== "undefined" && documentIsHTML ) {
				var m = context.getElementById( id );
				return m ? [ m ] : [];
			}
		};
		Expr.filter["ID"] = function( id ) {
			var attrId = id.replace( runescape, funescape );
			return function( elem ) {
				return elem.getAttribute("id") === attrId;
			};
		};
	} else {
		// Support: IE6/7
		// getElementById is not reliable as a find shortcut
		delete Expr.find["ID"];

		Expr.filter["ID"] =  function( id ) {
			var attrId = id.replace( runescape, funescape );
			return function( elem ) {
				var node = typeof elem.getAttributeNode !== "undefined" &&
					elem.getAttributeNode("id");
				return node && node.value === attrId;
			};
		};
	}

	// Tag
	Expr.find["TAG"] = support.getElementsByTagName ?
		function( tag, context ) {
			if ( typeof context.getElementsByTagName !== "undefined" ) {
				return context.getElementsByTagName( tag );

			// DocumentFragment nodes don't have gEBTN
			} else if ( support.qsa ) {
				return context.querySelectorAll( tag );
			}
		} :

		function( tag, context ) {
			var elem,
				tmp = [],
				i = 0,
				// By happy coincidence, a (broken) gEBTN appears on DocumentFragment nodes too
				results = context.getElementsByTagName( tag );

			// Filter out possible comments
			if ( tag === "*" ) {
				while ( (elem = results[i++]) ) {
					if ( elem.nodeType === 1 ) {
						tmp.push( elem );
					}
				}

				return tmp;
			}
			return results;
		};

	// Class
	Expr.find["CLASS"] = support.getElementsByClassName && function( className, context ) {
		if ( typeof context.getElementsByClassName !== "undefined" && documentIsHTML ) {
			return context.getElementsByClassName( className );
		}
	};

	/* QSA/matchesSelector
	---------------------------------------------------------------------- */

	// QSA and matchesSelector support

	// matchesSelector(:active) reports false when true (IE9/Opera 11.5)
	rbuggyMatches = [];

	// qSa(:focus) reports false when true (Chrome 21)
	// We allow this because of a bug in IE8/9 that throws an error
	// whenever `document.activeElement` is accessed on an iframe
	// So, we allow :focus to pass through QSA all the time to avoid the IE error
	// See http://bugs.jquery.com/ticket/13378
	rbuggyQSA = [];

	if ( (support.qsa = rnative.test( document.querySelectorAll )) ) {
		// Build QSA regex
		// Regex strategy adopted from Diego Perini
		assert(function( div ) {
			// Select is set to empty string on purpose
			// This is to test IE's treatment of not explicitly
			// setting a boolean content attribute,
			// since its presence should be enough
			// http://bugs.jquery.com/ticket/12359
			docElem.appendChild( div ).innerHTML = "<a id='" + expando + "'></a>" +
				"<select id='" + expando + "-\r\\' msallowcapture=''>" +
				"<option selected=''></option></select>";

			// Support: IE8, Opera 11-12.16
			// Nothing should be selected when empty strings follow ^= or $= or *=
			// The test attribute must be unknown in Opera but "safe" for WinRT
			// http://msdn.microsoft.com/en-us/library/ie/hh465388.aspx#attribute_section
			if ( div.querySelectorAll("[msallowcapture^='']").length ) {
				rbuggyQSA.push( "[*^$]=" + whitespace + "*(?:''|\"\")" );
			}

			// Support: IE8
			// Boolean attributes and "value" are not treated correctly
			if ( !div.querySelectorAll("[selected]").length ) {
				rbuggyQSA.push( "\\[" + whitespace + "*(?:value|" + booleans + ")" );
			}

			// Support: Chrome<29, Android<4.4, Safari<7.0+, iOS<7.0+, PhantomJS<1.9.8+
			if ( !div.querySelectorAll( "[id~=" + expando + "-]" ).length ) {
				rbuggyQSA.push("~=");
			}

			// Webkit/Opera - :checked should return selected option elements
			// http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked
			// IE8 throws error here and will not see later tests
			if ( !div.querySelectorAll(":checked").length ) {
				rbuggyQSA.push(":checked");
			}

			// Support: Safari 8+, iOS 8+
			// https://bugs.webkit.org/show_bug.cgi?id=136851
			// In-page `selector#id sibing-combinator selector` fails
			if ( !div.querySelectorAll( "a#" + expando + "+*" ).length ) {
				rbuggyQSA.push(".#.+[+~]");
			}
		});

		assert(function( div ) {
			// Support: Windows 8 Native Apps
			// The type and name attributes are restricted during .innerHTML assignment
			var input = document.createElement("input");
			input.setAttribute( "type", "hidden" );
			div.appendChild( input ).setAttribute( "name", "D" );

			// Support: IE8
			// Enforce case-sensitivity of name attribute
			if ( div.querySelectorAll("[name=d]").length ) {
				rbuggyQSA.push( "name" + whitespace + "*[*^$|!~]?=" );
			}

			// FF 3.5 - :enabled/:disabled and hidden elements (hidden elements are still enabled)
			// IE8 throws error here and will not see later tests
			if ( !div.querySelectorAll(":enabled").length ) {
				rbuggyQSA.push( ":enabled", ":disabled" );
			}

			// Opera 10-11 does not throw on post-comma invalid pseudos
			div.querySelectorAll("*,:x");
			rbuggyQSA.push(",.*:");
		});
	}

	if ( (support.matchesSelector = rnative.test( (matches = docElem.matches ||
		docElem.webkitMatchesSelector ||
		docElem.mozMatchesSelector ||
		docElem.oMatchesSelector ||
		docElem.msMatchesSelector) )) ) {

		assert(function( div ) {
			// Check to see if it's possible to do matchesSelector
			// on a disconnected node (IE 9)
			support.disconnectedMatch = matches.call( div, "div" );

			// This should fail with an exception
			// Gecko does not error, returns false instead
			matches.call( div, "[s!='']:x" );
			rbuggyMatches.push( "!=", pseudos );
		});
	}

	rbuggyQSA = rbuggyQSA.length && new RegExp( rbuggyQSA.join("|") );
	rbuggyMatches = rbuggyMatches.length && new RegExp( rbuggyMatches.join("|") );

	/* Contains
	---------------------------------------------------------------------- */
	hasCompare = rnative.test( docElem.compareDocumentPosition );

	// Element contains another
	// Purposefully self-exclusive
	// As in, an element does not contain itself
	contains = hasCompare || rnative.test( docElem.contains ) ?
		function( a, b ) {
			var adown = a.nodeType === 9 ? a.documentElement : a,
				bup = b && b.parentNode;
			return a === bup || !!( bup && bup.nodeType === 1 && (
				adown.contains ?
					adown.contains( bup ) :
					a.compareDocumentPosition && a.compareDocumentPosition( bup ) & 16
			));
		} :
		function( a, b ) {
			if ( b ) {
				while ( (b = b.parentNode) ) {
					if ( b === a ) {
						return true;
					}
				}
			}
			return false;
		};

	/* Sorting
	---------------------------------------------------------------------- */

	// Document order sorting
	sortOrder = hasCompare ?
	function( a, b ) {

		// Flag for duplicate removal
		if ( a === b ) {
			hasDuplicate = true;
			return 0;
		}

		// Sort on method existence if only one input has compareDocumentPosition
		var compare = !a.compareDocumentPosition - !b.compareDocumentPosition;
		if ( compare ) {
			return compare;
		}

		// Calculate position if both inputs belong to the same document
		compare = ( a.ownerDocument || a ) === ( b.ownerDocument || b ) ?
			a.compareDocumentPosition( b ) :

			// Otherwise we know they are disconnected
			1;

		// Disconnected nodes
		if ( compare & 1 ||
			(!support.sortDetached && b.compareDocumentPosition( a ) === compare) ) {

			// Choose the first element that is related to our preferred document
			if ( a === document || a.ownerDocument === preferredDoc && contains(preferredDoc, a) ) {
				return -1;
			}
			if ( b === document || b.ownerDocument === preferredDoc && contains(preferredDoc, b) ) {
				return 1;
			}

			// Maintain original order
			return sortInput ?
				( indexOf( sortInput, a ) - indexOf( sortInput, b ) ) :
				0;
		}

		return compare & 4 ? -1 : 1;
	} :
	function( a, b ) {
		// Exit early if the nodes are identical
		if ( a === b ) {
			hasDuplicate = true;
			return 0;
		}

		var cur,
			i = 0,
			aup = a.parentNode,
			bup = b.parentNode,
			ap = [ a ],
			bp = [ b ];

		// Parentless nodes are either documents or disconnected
		if ( !aup || !bup ) {
			return a === document ? -1 :
				b === document ? 1 :
				aup ? -1 :
				bup ? 1 :
				sortInput ?
				( indexOf( sortInput, a ) - indexOf( sortInput, b ) ) :
				0;

		// If the nodes are siblings, we can do a quick check
		} else if ( aup === bup ) {
			return siblingCheck( a, b );
		}

		// Otherwise we need full lists of their ancestors for comparison
		cur = a;
		while ( (cur = cur.parentNode) ) {
			ap.unshift( cur );
		}
		cur = b;
		while ( (cur = cur.parentNode) ) {
			bp.unshift( cur );
		}

		// Walk down the tree looking for a discrepancy
		while ( ap[i] === bp[i] ) {
			i++;
		}

		return i ?
			// Do a sibling check if the nodes have a common ancestor
			siblingCheck( ap[i], bp[i] ) :

			// Otherwise nodes in our document sort first
			ap[i] === preferredDoc ? -1 :
			bp[i] === preferredDoc ? 1 :
			0;
	};

	return document;
};

Sizzle.matches = function( expr, elements ) {
	return Sizzle( expr, null, null, elements );
};

Sizzle.matchesSelector = function( elem, expr ) {
	// Set document vars if needed
	if ( ( elem.ownerDocument || elem ) !== document ) {
		setDocument( elem );
	}

	// Make sure that attribute selectors are quoted
	expr = expr.replace( rattributeQuotes, "='$1']" );

	if ( support.matchesSelector && documentIsHTML &&
		!compilerCache[ expr + " " ] &&
		( !rbuggyMatches || !rbuggyMatches.test( expr ) ) &&
		( !rbuggyQSA     || !rbuggyQSA.test( expr ) ) ) {

		try {
			var ret = matches.call( elem, expr );

			// IE 9's matchesSelector returns false on disconnected nodes
			if ( ret || support.disconnectedMatch ||
					// As well, disconnected nodes are said to be in a document
					// fragment in IE 9
					elem.document && elem.document.nodeType !== 11 ) {
				return ret;
			}
		} catch (e) {}
	}

	return Sizzle( expr, document, null, [ elem ] ).length > 0;
};

Sizzle.contains = function( context, elem ) {
	// Set document vars if needed
	if ( ( context.ownerDocument || context ) !== document ) {
		setDocument( context );
	}
	return contains( context, elem );
};

Sizzle.attr = function( elem, name ) {
	// Set document vars if needed
	if ( ( elem.ownerDocument || elem ) !== document ) {
		setDocument( elem );
	}

	var fn = Expr.attrHandle[ name.toLowerCase() ],
		// Don't get fooled by Object.prototype properties (jQuery #13807)
		val = fn && hasOwn.call( Expr.attrHandle, name.toLowerCase() ) ?
			fn( elem, name, !documentIsHTML ) :
			undefined;

	return val !== undefined ?
		val :
		support.attributes || !documentIsHTML ?
			elem.getAttribute( name ) :
			(val = elem.getAttributeNode(name)) && val.specified ?
				val.value :
				null;
};

Sizzle.error = function( msg ) {
	throw new Error( "Syntax error, unrecognized expression: " + msg );
};

/**
 * Document sorting and removing duplicates
 * @param {ArrayLike} results
 */
Sizzle.uniqueSort = function( results ) {
	var elem,
		duplicates = [],
		j = 0,
		i = 0;

	// Unless we *know* we can detect duplicates, assume their presence
	hasDuplicate = !support.detectDuplicates;
	sortInput = !support.sortStable && results.slice( 0 );
	results.sort( sortOrder );

	if ( hasDuplicate ) {
		while ( (elem = results[i++]) ) {
			if ( elem === results[ i ] ) {
				j = duplicates.push( i );
			}
		}
		while ( j-- ) {
			results.splice( duplicates[ j ], 1 );
		}
	}

	// Clear input after sorting to release objects
	// See https://github.com/jquery/sizzle/pull/225
	sortInput = null;

	return results;
};

/**
 * Utility function for retrieving the text value of an array of DOM nodes
 * @param {Array|Element} elem
 */
getText = Sizzle.getText = function( elem ) {
	var node,
		ret = "",
		i = 0,
		nodeType = elem.nodeType;

	if ( !nodeType ) {
		// If no nodeType, this is expected to be an array
		while ( (node = elem[i++]) ) {
			// Do not traverse comment nodes
			ret += getText( node );
		}
	} else if ( nodeType === 1 || nodeType === 9 || nodeType === 11 ) {
		// Use textContent for elements
		// innerText usage removed for consistency of new lines (jQuery #11153)
		if ( typeof elem.textContent === "string" ) {
			return elem.textContent;
		} else {
			// Traverse its children
			for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) {
				ret += getText( elem );
			}
		}
	} else if ( nodeType === 3 || nodeType === 4 ) {
		return elem.nodeValue;
	}
	// Do not include comment or processing instruction nodes

	return ret;
};

Expr = Sizzle.selectors = {

	// Can be adjusted by the user
	cacheLength: 50,

	createPseudo: markFunction,

	match: matchExpr,

	attrHandle: {},

	find: {},

	relative: {
		">": { dir: "parentNode", first: true },
		" ": { dir: "parentNode" },
		"+": { dir: "previousSibling", first: true },
		"~": { dir: "previousSibling" }
	},

	preFilter: {
		"ATTR": function( match ) {
			match[1] = match[1].replace( runescape, funescape );

			// Move the given value to match[3] whether quoted or unquoted
			match[3] = ( match[3] || match[4] || match[5] || "" ).replace( runescape, funescape );

			if ( match[2] === "~=" ) {
				match[3] = " " + match[3] + " ";
			}

			return match.slice( 0, 4 );
		},

		"CHILD": function( match ) {
			/* matches from matchExpr["CHILD"]
				1 type (only|nth|...)
				2 what (child|of-type)
				3 argument (even|odd|\d*|\d*n([+-]\d+)?|...)
				4 xn-component of xn+y argument ([+-]?\d*n|)
				5 sign of xn-component
				6 x of xn-component
				7 sign of y-component
				8 y of y-component
			*/
			match[1] = match[1].toLowerCase();

			if ( match[1].slice( 0, 3 ) === "nth" ) {
				// nth-* requires argument
				if ( !match[3] ) {
					Sizzle.error( match[0] );
				}

				// numeric x and y parameters for Expr.filter.CHILD
				// remember that false/true cast respectively to 0/1
				match[4] = +( match[4] ? match[5] + (match[6] || 1) : 2 * ( match[3] === "even" || match[3] === "odd" ) );
				match[5] = +( ( match[7] + match[8] ) || match[3] === "odd" );

			// other types prohibit arguments
			} else if ( match[3] ) {
				Sizzle.error( match[0] );
			}

			return match;
		},

		"PSEUDO": function( match ) {
			var excess,
				unquoted = !match[6] && match[2];

			if ( matchExpr["CHILD"].test( match[0] ) ) {
				return null;
			}

			// Accept quoted arguments as-is
			if ( match[3] ) {
				match[2] = match[4] || match[5] || "";

			// Strip excess characters from unquoted arguments
			} else if ( unquoted && rpseudo.test( unquoted ) &&
				// Get excess from tokenize (recursively)
				(excess = tokenize( unquoted, true )) &&
				// advance to the next closing parenthesis
				(excess = unquoted.indexOf( ")", unquoted.length - excess ) - unquoted.length) ) {

				// excess is a negative index
				match[0] = match[0].slice( 0, excess );
				match[2] = unquoted.slice( 0, excess );
			}

			// Return only captures needed by the pseudo filter method (type and argument)
			return match.slice( 0, 3 );
		}
	},

	filter: {

		"TAG": function( nodeNameSelector ) {
			var nodeName = nodeNameSelector.replace( runescape, funescape ).toLowerCase();
			return nodeNameSelector === "*" ?
				function() { return true; } :
				function( elem ) {
					return elem.nodeName && elem.nodeName.toLowerCase() === nodeName;
				};
		},

		"CLASS": function( className ) {
			var pattern = classCache[ className + " " ];

			return pattern ||
				(pattern = new RegExp( "(^|" + whitespace + ")" + className + "(" + whitespace + "|$)" )) &&
				classCache( className, function( elem ) {
					return pattern.test( typeof elem.className === "string" && elem.className || typeof elem.getAttribute !== "undefined" && elem.getAttribute("class") || "" );
				});
		},

		"ATTR": function( name, operator, check ) {
			return function( elem ) {
				var result = Sizzle.attr( elem, name );

				if ( result == null ) {
					return operator === "!=";
				}
				if ( !operator ) {
					return true;
				}

				result += "";

				return operator === "=" ? result === check :
					operator === "!=" ? result !== check :
					operator === "^=" ? check && result.indexOf( check ) === 0 :
					operator === "*=" ? check && result.indexOf( check ) > -1 :
					operator === "$=" ? check && result.slice( -check.length ) === check :
					operator === "~=" ? ( " " + result.replace( rwhitespace, " " ) + " " ).indexOf( check ) > -1 :
					operator === "|=" ? result === check || result.slice( 0, check.length + 1 ) === check + "-" :
					false;
			};
		},

		"CHILD": function( type, what, argument, first, last ) {
			var simple = type.slice( 0, 3 ) !== "nth",
				forward = type.slice( -4 ) !== "last",
				ofType = what === "of-type";

			return first === 1 && last === 0 ?

				// Shortcut for :nth-*(n)
				function( elem ) {
					return !!elem.parentNode;
				} :

				function( elem, context, xml ) {
					var cache, uniqueCache, outerCache, node, nodeIndex, start,
						dir = simple !== forward ? "nextSibling" : "previousSibling",
						parent = elem.parentNode,
						name = ofType && elem.nodeName.toLowerCase(),
						useCache = !xml && !ofType,
						diff = false;

					if ( parent ) {

						// :(first|last|only)-(child|of-type)
						if ( simple ) {
							while ( dir ) {
								node = elem;
								while ( (node = node[ dir ]) ) {
									if ( ofType ?
										node.nodeName.toLowerCase() === name :
										node.nodeType === 1 ) {

										return false;
									}
								}
								// Reverse direction for :only-* (if we haven't yet done so)
								start = dir = type === "only" && !start && "nextSibling";
							}
							return true;
						}

						start = [ forward ? parent.firstChild : parent.lastChild ];

						// non-xml :nth-child(...) stores cache data on `parent`
						if ( forward && useCache ) {

							// Seek `elem` from a previously-cached index

							// ...in a gzip-friendly way
							node = parent;
							outerCache = node[ expando ] || (node[ expando ] = {});

							// Support: IE <9 only
							// Defend against cloned attroperties (jQuery gh-1709)
							uniqueCache = outerCache[ node.uniqueID ] ||
								(outerCache[ node.uniqueID ] = {});

							cache = uniqueCache[ type ] || [];
							nodeIndex = cache[ 0 ] === dirruns && cache[ 1 ];
							diff = nodeIndex && cache[ 2 ];
							node = nodeIndex && parent.childNodes[ nodeIndex ];

							while ( (node = ++nodeIndex && node && node[ dir ] ||

								// Fallback to seeking `elem` from the start
								(diff = nodeIndex = 0) || start.pop()) ) {

								// When found, cache indexes on `parent` and break
								if ( node.nodeType === 1 && ++diff && node === elem ) {
									uniqueCache[ type ] = [ dirruns, nodeIndex, diff ];
									break;
								}
							}

						} else {
							// Use previously-cached element index if available
							if ( useCache ) {
								// ...in a gzip-friendly way
								node = elem;
								outerCache = node[ expando ] || (node[ expando ] = {});

								// Support: IE <9 only
								// Defend against cloned attroperties (jQuery gh-1709)
								uniqueCache = outerCache[ node.uniqueID ] ||
									(outerCache[ node.uniqueID ] = {});

								cache = uniqueCache[ type ] || [];
								nodeIndex = cache[ 0 ] === dirruns && cache[ 1 ];
								diff = nodeIndex;
							}

							// xml :nth-child(...)
							// or :nth-last-child(...) or :nth(-last)?-of-type(...)
							if ( diff === false ) {
								// Use the same loop as above to seek `elem` from the start
								while ( (node = ++nodeIndex && node && node[ dir ] ||
									(diff = nodeIndex = 0) || start.pop()) ) {

									if ( ( ofType ?
										node.nodeName.toLowerCase() === name :
										node.nodeType === 1 ) &&
										++diff ) {

										// Cache the index of each encountered element
										if ( useCache ) {
											outerCache = node[ expando ] || (node[ expando ] = {});

											// Support: IE <9 only
											// Defend against cloned attroperties (jQuery gh-1709)
											uniqueCache = outerCache[ node.uniqueID ] ||
												(outerCache[ node.uniqueID ] = {});

											uniqueCache[ type ] = [ dirruns, diff ];
										}

										if ( node === elem ) {
											break;
										}
									}
								}
							}
						}

						// Incorporate the offset, then check against cycle size
						diff -= last;
						return diff === first || ( diff % first === 0 && diff / first >= 0 );
					}
				};
		},

		"PSEUDO": function( pseudo, argument ) {
			// pseudo-class names are case-insensitive
			// http://www.w3.org/TR/selectors/#pseudo-classes
			// Prioritize by case sensitivity in case custom pseudos are added with uppercase letters
			// Remember that setFilters inherits from pseudos
			var args,
				fn = Expr.pseudos[ pseudo ] || Expr.setFilters[ pseudo.toLowerCase() ] ||
					Sizzle.error( "unsupported pseudo: " + pseudo );

			// The user may use createPseudo to indicate that
			// arguments are needed to create the filter function
			// just as Sizzle does
			if ( fn[ expando ] ) {
				return fn( argument );
			}

			// But maintain support for old signatures
			if ( fn.length > 1 ) {
				args = [ pseudo, pseudo, "", argument ];
				return Expr.setFilters.hasOwnProperty( pseudo.toLowerCase() ) ?
					markFunction(function( seed, matches ) {
						var idx,
							matched = fn( seed, argument ),
							i = matched.length;
						while ( i-- ) {
							idx = indexOf( seed, matched[i] );
							seed[ idx ] = !( matches[ idx ] = matched[i] );
						}
					}) :
					function( elem ) {
						return fn( elem, 0, args );
					};
			}

			return fn;
		}
	},

	pseudos: {
		// Potentially complex pseudos
		"not": markFunction(function( selector ) {
			// Trim the selector passed to compile
			// to avoid treating leading and trailing
			// spaces as combinators
			var input = [],
				results = [],
				matcher = compile( selector.replace( rtrim, "$1" ) );

			return matcher[ expando ] ?
				markFunction(function( seed, matches, context, xml ) {
					var elem,
						unmatched = matcher( seed, null, xml, [] ),
						i = seed.length;

					// Match elements unmatched by `matcher`
					while ( i-- ) {
						if ( (elem = unmatched[i]) ) {
							seed[i] = !(matches[i] = elem);
						}
					}
				}) :
				function( elem, context, xml ) {
					input[0] = elem;
					matcher( input, null, xml, results );
					// Don't keep the element (issue #299)
					input[0] = null;
					return !results.pop();
				};
		}),

		"has": markFunction(function( selector ) {
			return function( elem ) {
				return Sizzle( selector, elem ).length > 0;
			};
		}),

		"contains": markFunction(function( text ) {
			text = text.replace( runescape, funescape );
			return function( elem ) {
				return ( elem.textContent || elem.innerText || getText( elem ) ).indexOf( text ) > -1;
			};
		}),

		// "Whether an element is represented by a :lang() selector
		// is based solely on the element's language value
		// being equal to the identifier C,
		// or beginning with the identifier C immediately followed by "-".
		// The matching of C against the element's language value is performed case-insensitively.
		// The identifier C does not have to be a valid language name."
		// http://www.w3.org/TR/selectors/#lang-pseudo
		"lang": markFunction( function( lang ) {
			// lang value must be a valid identifier
			if ( !ridentifier.test(lang || "") ) {
				Sizzle.error( "unsupported lang: " + lang );
			}
			lang = lang.replace( runescape, funescape ).toLowerCase();
			return function( elem ) {
				var elemLang;
				do {
					if ( (elemLang = documentIsHTML ?
						elem.lang :
						elem.getAttribute("xml:lang") || elem.getAttribute("lang")) ) {

						elemLang = elemLang.toLowerCase();
						return elemLang === lang || elemLang.indexOf( lang + "-" ) === 0;
					}
				} while ( (elem = elem.parentNode) && elem.nodeType === 1 );
				return false;
			};
		}),

		// Miscellaneous
		"target": function( elem ) {
			var hash = window.location && window.location.hash;
			return hash && hash.slice( 1 ) === elem.id;
		},

		"root": function( elem ) {
			return elem === docElem;
		},

		"focus": function( elem ) {
			return elem === document.activeElement && (!document.hasFocus || document.hasFocus()) && !!(elem.type || elem.href || ~elem.tabIndex);
		},

		// Boolean properties
		"enabled": function( elem ) {
			return elem.disabled === false;
		},

		"disabled": function( elem ) {
			return elem.disabled === true;
		},

		"checked": function( elem ) {
			// In CSS3, :checked should return both checked and selected elements
			// http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked
			var nodeName = elem.nodeName.toLowerCase();
			return (nodeName === "input" && !!elem.checked) || (nodeName === "option" && !!elem.selected);
		},

		"selected": function( elem ) {
			// Accessing this property makes selected-by-default
			// options in Safari work properly
			if ( elem.parentNode ) {
				elem.parentNode.selectedIndex;
			}

			return elem.selected === true;
		},

		// Contents
		"empty": function( elem ) {
			// http://www.w3.org/TR/selectors/#empty-pseudo
			// :empty is negated by element (1) or content nodes (text: 3; cdata: 4; entity ref: 5),
			//   but not by others (comment: 8; processing instruction: 7; etc.)
			// nodeType < 6 works because attributes (2) do not appear as children
			for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) {
				if ( elem.nodeType < 6 ) {
					return false;
				}
			}
			return true;
		},

		"parent": function( elem ) {
			return !Expr.pseudos["empty"]( elem );
		},

		// Element/input types
		"header": function( elem ) {
			return rheader.test( elem.nodeName );
		},

		"input": function( elem ) {
			return rinputs.test( elem.nodeName );
		},

		"button": function( elem ) {
			var name = elem.nodeName.toLowerCase();
			return name === "input" && elem.type === "button" || name === "button";
		},

		"text": function( elem ) {
			var attr;
			return elem.nodeName.toLowerCase() === "input" &&
				elem.type === "text" &&

				// Support: IE<8
				// New HTML5 attribute values (e.g., "search") appear with elem.type === "text"
				( (attr = elem.getAttribute("type")) == null || attr.toLowerCase() === "text" );
		},

		// Position-in-collection
		"first": createPositionalPseudo(function() {
			return [ 0 ];
		}),

		"last": createPositionalPseudo(function( matchIndexes, length ) {
			return [ length - 1 ];
		}),

		"eq": createPositionalPseudo(function( matchIndexes, length, argument ) {
			return [ argument < 0 ? argument + length : argument ];
		}),

		"even": createPositionalPseudo(function( matchIndexes, length ) {
			var i = 0;
			for ( ; i < length; i += 2 ) {
				matchIndexes.push( i );
			}
			return matchIndexes;
		}),

		"odd": createPositionalPseudo(function( matchIndexes, length ) {
			var i = 1;
			for ( ; i < length; i += 2 ) {
				matchIndexes.push( i );
			}
			return matchIndexes;
		}),

		"lt": createPositionalPseudo(function( matchIndexes, length, argument ) {
			var i = argument < 0 ? argument + length : argument;
			for ( ; --i >= 0; ) {
				matchIndexes.push( i );
			}
			return matchIndexes;
		}),

		"gt": createPositionalPseudo(function( matchIndexes, length, argument ) {
			var i = argument < 0 ? argument + length : argument;
			for ( ; ++i < length; ) {
				matchIndexes.push( i );
			}
			return matchIndexes;
		})
	}
};

Expr.pseudos["nth"] = Expr.pseudos["eq"];

// Add button/input type pseudos
for ( i in { radio: true, checkbox: true, file: true, password: true, image: true } ) {
	Expr.pseudos[ i ] = createInputPseudo( i );
}
for ( i in { submit: true, reset: true } ) {
	Expr.pseudos[ i ] = createButtonPseudo( i );
}

// Easy API for creating new setFilters
function setFilters() {}
setFilters.prototype = Expr.filters = Expr.pseudos;
Expr.setFilters = new setFilters();

tokenize = Sizzle.tokenize = function( selector, parseOnly ) {
	var matched, match, tokens, type,
		soFar, groups, preFilters,
		cached = tokenCache[ selector + " " ];

	if ( cached ) {
		return parseOnly ? 0 : cached.slice( 0 );
	}

	soFar = selector;
	groups = [];
	preFilters = Expr.preFilter;

	while ( soFar ) {

		// Comma and first run
		if ( !matched || (match = rcomma.exec( soFar )) ) {
			if ( match ) {
				// Don't consume trailing commas as valid
				soFar = soFar.slice( match[0].length ) || soFar;
			}
			groups.push( (tokens = []) );
		}

		matched = false;

		// Combinators
		if ( (match = rcombinators.exec( soFar )) ) {
			matched = match.shift();
			tokens.push({
				value: matched,
				// Cast descendant combinators to space
				type: match[0].replace( rtrim, " " )
			});
			soFar = soFar.slice( matched.length );
		}

		// Filters
		for ( type in Expr.filter ) {
			if ( (match = matchExpr[ type ].exec( soFar )) && (!preFilters[ type ] ||
				(match = preFilters[ type ]( match ))) ) {
				matched = match.shift();
				tokens.push({
					value: matched,
					type: type,
					matches: match
				});
				soFar = soFar.slice( matched.length );
			}
		}

		if ( !matched ) {
			break;
		}
	}

	// Return the length of the invalid excess
	// if we're just parsing
	// Otherwise, throw an error or return tokens
	return parseOnly ?
		soFar.length :
		soFar ?
			Sizzle.error( selector ) :
			// Cache the tokens
			tokenCache( selector, groups ).slice( 0 );
};

function toSelector( tokens ) {
	var i = 0,
		len = tokens.length,
		selector = "";
	for ( ; i < len; i++ ) {
		selector += tokens[i].value;
	}
	return selector;
}

function addCombinator( matcher, combinator, base ) {
	var dir = combinator.dir,
		checkNonElements = base && dir === "parentNode",
		doneName = done++;

	return combinator.first ?
		// Check against closest ancestor/preceding element
		function( elem, context, xml ) {
			while ( (elem = elem[ dir ]) ) {
				if ( elem.nodeType === 1 || checkNonElements ) {
					return matcher( elem, context, xml );
				}
			}
		} :

		// Check against all ancestor/preceding elements
		function( elem, context, xml ) {
			var oldCache, uniqueCache, outerCache,
				newCache = [ dirruns, doneName ];

			// We can't set arbitrary data on XML nodes, so they don't benefit from combinator caching
			if ( xml ) {
				while ( (elem = elem[ dir ]) ) {
					if ( elem.nodeType === 1 || checkNonElements ) {
						if ( matcher( elem, context, xml ) ) {
							return true;
						}
					}
				}
			} else {
				while ( (elem = elem[ dir ]) ) {
					if ( elem.nodeType === 1 || checkNonElements ) {
						outerCache = elem[ expando ] || (elem[ expando ] = {});

						// Support: IE <9 only
						// Defend against cloned attroperties (jQuery gh-1709)
						uniqueCache = outerCache[ elem.uniqueID ] || (outerCache[ elem.uniqueID ] = {});

						if ( (oldCache = uniqueCache[ dir ]) &&
							oldCache[ 0 ] === dirruns && oldCache[ 1 ] === doneName ) {

							// Assign to newCache so results back-propagate to previous elements
							return (newCache[ 2 ] = oldCache[ 2 ]);
						} else {
							// Reuse newcache so results back-propagate to previous elements
							uniqueCache[ dir ] = newCache;

							// A match means we're done; a fail means we have to keep checking
							if ( (newCache[ 2 ] = matcher( elem, context, xml )) ) {
								return true;
							}
						}
					}
				}
			}
		};
}

function elementMatcher( matchers ) {
	return matchers.length > 1 ?
		function( elem, context, xml ) {
			var i = matchers.length;
			while ( i-- ) {
				if ( !matchers[i]( elem, context, xml ) ) {
					return false;
				}
			}
			return true;
		} :
		matchers[0];
}

function multipleContexts( selector, contexts, results ) {
	var i = 0,
		len = contexts.length;
	for ( ; i < len; i++ ) {
		Sizzle( selector, contexts[i], results );
	}
	return results;
}

function condense( unmatched, map, filter, context, xml ) {
	var elem,
		newUnmatched = [],
		i = 0,
		len = unmatched.length,
		mapped = map != null;

	for ( ; i < len; i++ ) {
		if ( (elem = unmatched[i]) ) {
			if ( !filter || filter( elem, context, xml ) ) {
				newUnmatched.push( elem );
				if ( mapped ) {
					map.push( i );
				}
			}
		}
	}

	return newUnmatched;
}

function setMatcher( preFilter, selector, matcher, postFilter, postFinder, postSelector ) {
	if ( postFilter && !postFilter[ expando ] ) {
		postFilter = setMatcher( postFilter );
	}
	if ( postFinder && !postFinder[ expando ] ) {
		postFinder = setMatcher( postFinder, postSelector );
	}
	return markFunction(function( seed, results, context, xml ) {
		var temp, i, elem,
			preMap = [],
			postMap = [],
			preexisting = results.length,

			// Get initial elements from seed or context
			elems = seed || multipleContexts( selector || "*", context.nodeType ? [ context ] : context, [] ),

			// Prefilter to get matcher input, preserving a map for seed-results synchronization
			matcherIn = preFilter && ( seed || !selector ) ?
				condense( elems, preMap, preFilter, context, xml ) :
				elems,

			matcherOut = matcher ?
				// If we have a postFinder, or filtered seed, or non-seed postFilter or preexisting results,
				postFinder || ( seed ? preFilter : preexisting || postFilter ) ?

					// ...intermediate processing is necessary
					[] :

					// ...otherwise use results directly
					results :
				matcherIn;

		// Find primary matches
		if ( matcher ) {
			matcher( matcherIn, matcherOut, context, xml );
		}

		// Apply postFilter
		if ( postFilter ) {
			temp = condense( matcherOut, postMap );
			postFilter( temp, [], context, xml );

			// Un-match failing elements by moving them back to matcherIn
			i = temp.length;
			while ( i-- ) {
				if ( (elem = temp[i]) ) {
					matcherOut[ postMap[i] ] = !(matcherIn[ postMap[i] ] = elem);
				}
			}
		}

		if ( seed ) {
			if ( postFinder || preFilter ) {
				if ( postFinder ) {
					// Get the final matcherOut by condensing this intermediate into postFinder contexts
					temp = [];
					i = matcherOut.length;
					while ( i-- ) {
						if ( (elem = matcherOut[i]) ) {
							// Restore matcherIn since elem is not yet a final match
							temp.push( (matcherIn[i] = elem) );
						}
					}
					postFinder( null, (matcherOut = []), temp, xml );
				}

				// Move matched elements from seed to results to keep them synchronized
				i = matcherOut.length;
				while ( i-- ) {
					if ( (elem = matcherOut[i]) &&
						(temp = postFinder ? indexOf( seed, elem ) : preMap[i]) > -1 ) {

						seed[temp] = !(results[temp] = elem);
					}
				}
			}

		// Add elements to results, through postFinder if defined
		} else {
			matcherOut = condense(
				matcherOut === results ?
					matcherOut.splice( preexisting, matcherOut.length ) :
					matcherOut
			);
			if ( postFinder ) {
				postFinder( null, results, matcherOut, xml );
			} else {
				push.apply( results, matcherOut );
			}
		}
	});
}

function matcherFromTokens( tokens ) {
	var checkContext, matcher, j,
		len = tokens.length,
		leadingRelative = Expr.relative[ tokens[0].type ],
		implicitRelative = leadingRelative || Expr.relative[" "],
		i = leadingRelative ? 1 : 0,

		// The foundational matcher ensures that elements are reachable from top-level context(s)
		matchContext = addCombinator( function( elem ) {
			return elem === checkContext;
		}, implicitRelative, true ),
		matchAnyContext = addCombinator( function( elem ) {
			return indexOf( checkContext, elem ) > -1;
		}, implicitRelative, true ),
		matchers = [ function( elem, context, xml ) {
			var ret = ( !leadingRelative && ( xml || context !== outermostContext ) ) || (
				(checkContext = context).nodeType ?
					matchContext( elem, context, xml ) :
					matchAnyContext( elem, context, xml ) );
			// Avoid hanging onto element (issue #299)
			checkContext = null;
			return ret;
		} ];

	for ( ; i < len; i++ ) {
		if ( (matcher = Expr.relative[ tokens[i].type ]) ) {
			matchers = [ addCombinator(elementMatcher( matchers ), matcher) ];
		} else {
			matcher = Expr.filter[ tokens[i].type ].apply( null, tokens[i].matches );

			// Return special upon seeing a positional matcher
			if ( matcher[ expando ] ) {
				// Find the next relative operator (if any) for proper handling
				j = ++i;
				for ( ; j < len; j++ ) {
					if ( Expr.relative[ tokens[j].type ] ) {
						break;
					}
				}
				return setMatcher(
					i > 1 && elementMatcher( matchers ),
					i > 1 && toSelector(
						// If the preceding token was a descendant combinator, insert an implicit any-element `*`
						tokens.slice( 0, i - 1 ).concat({ value: tokens[ i - 2 ].type === " " ? "*" : "" })
					).replace( rtrim, "$1" ),
					matcher,
					i < j && matcherFromTokens( tokens.slice( i, j ) ),
					j < len && matcherFromTokens( (tokens = tokens.slice( j )) ),
					j < len && toSelector( tokens )
				);
			}
			matchers.push( matcher );
		}
	}

	return elementMatcher( matchers );
}

function matcherFromGroupMatchers( elementMatchers, setMatchers ) {
	var bySet = setMatchers.length > 0,
		byElement = elementMatchers.length > 0,
		superMatcher = function( seed, context, xml, results, outermost ) {
			var elem, j, matcher,
				matchedCount = 0,
				i = "0",
				unmatched = seed && [],
				setMatched = [],
				contextBackup = outermostContext,
				// We must always have either seed elements or outermost context
				elems = seed || byElement && Expr.find["TAG"]( "*", outermost ),
				// Use integer dirruns iff this is the outermost matcher
				dirrunsUnique = (dirruns += contextBackup == null ? 1 : Math.random() || 0.1),
				len = elems.length;

			if ( outermost ) {
				outermostContext = context === document || context || outermost;
			}

			// Add elements passing elementMatchers directly to results
			// Support: IE<9, Safari
			// Tolerate NodeList properties (IE: "length"; Safari: <number>) matching elements by id
			for ( ; i !== len && (elem = elems[i]) != null; i++ ) {
				if ( byElement && elem ) {
					j = 0;
					if ( !context && elem.ownerDocument !== document ) {
						setDocument( elem );
						xml = !documentIsHTML;
					}
					while ( (matcher = elementMatchers[j++]) ) {
						if ( matcher( elem, context || document, xml) ) {
							results.push( elem );
							break;
						}
					}
					if ( outermost ) {
						dirruns = dirrunsUnique;
					}
				}

				// Track unmatched elements for set filters
				if ( bySet ) {
					// They will have gone through all possible matchers
					if ( (elem = !matcher && elem) ) {
						matchedCount--;
					}

					// Lengthen the array for every element, matched or not
					if ( seed ) {
						unmatched.push( elem );
					}
				}
			}

			// `i` is now the count of elements visited above, and adding it to `matchedCount`
			// makes the latter nonnegative.
			matchedCount += i;

			// Apply set filters to unmatched elements
			// NOTE: This can be skipped if there are no unmatched elements (i.e., `matchedCount`
			// equals `i`), unless we didn't visit _any_ elements in the above loop because we have
			// no element matchers and no seed.
			// Incrementing an initially-string "0" `i` allows `i` to remain a string only in that
			// case, which will result in a "00" `matchedCount` that differs from `i` but is also
			// numerically zero.
			if ( bySet && i !== matchedCount ) {
				j = 0;
				while ( (matcher = setMatchers[j++]) ) {
					matcher( unmatched, setMatched, context, xml );
				}

				if ( seed ) {
					// Reintegrate element matches to eliminate the need for sorting
					if ( matchedCount > 0 ) {
						while ( i-- ) {
							if ( !(unmatched[i] || setMatched[i]) ) {
								setMatched[i] = pop.call( results );
							}
						}
					}

					// Discard index placeholder values to get only actual matches
					setMatched = condense( setMatched );
				}

				// Add matches to results
				push.apply( results, setMatched );

				// Seedless set matches succeeding multiple successful matchers stipulate sorting
				if ( outermost && !seed && setMatched.length > 0 &&
					( matchedCount + setMatchers.length ) > 1 ) {

					Sizzle.uniqueSort( results );
				}
			}

			// Override manipulation of globals by nested matchers
			if ( outermost ) {
				dirruns = dirrunsUnique;
				outermostContext = contextBackup;
			}

			return unmatched;
		};

	return bySet ?
		markFunction( superMatcher ) :
		superMatcher;
}

compile = Sizzle.compile = function( selector, match /* Internal Use Only */ ) {
	var i,
		setMatchers = [],
		elementMatchers = [],
		cached = compilerCache[ selector + " " ];

	if ( !cached ) {
		// Generate a function of recursive functions that can be used to check each element
		if ( !match ) {
			match = tokenize( selector );
		}
		i = match.length;
		while ( i-- ) {
			cached = matcherFromTokens( match[i] );
			if ( cached[ expando ] ) {
				setMatchers.push( cached );
			} else {
				elementMatchers.push( cached );
			}
		}

		// Cache the compiled function
		cached = compilerCache( selector, matcherFromGroupMatchers( elementMatchers, setMatchers ) );

		// Save selector and tokenization
		cached.selector = selector;
	}
	return cached;
};

/**
 * A low-level selection function that works with Sizzle's compiled
 *  selector functions
 * @param {String|Function} selector A selector or a pre-compiled
 *  selector function built with Sizzle.compile
 * @param {Element} context
 * @param {Array} [results]
 * @param {Array} [seed] A set of elements to match against
 */
select = Sizzle.select = function( selector, context, results, seed ) {
	var i, tokens, token, type, find,
		compiled = typeof selector === "function" && selector,
		match = !seed && tokenize( (selector = compiled.selector || selector) );

	results = results || [];

	// Try to minimize operations if there is only one selector in the list and no seed
	// (the latter of which guarantees us context)
	if ( match.length === 1 ) {

		// Reduce context if the leading compound selector is an ID
		tokens = match[0] = match[0].slice( 0 );
		if ( tokens.length > 2 && (token = tokens[0]).type === "ID" &&
				support.getById && context.nodeType === 9 && documentIsHTML &&
				Expr.relative[ tokens[1].type ] ) {

			context = ( Expr.find["ID"]( token.matches[0].replace(runescape, funescape), context ) || [] )[0];
			if ( !context ) {
				return results;

			// Precompiled matchers will still verify ancestry, so step up a level
			} else if ( compiled ) {
				context = context.parentNode;
			}

			selector = selector.slice( tokens.shift().value.length );
		}

		// Fetch a seed set for right-to-left matching
		i = matchExpr["needsContext"].test( selector ) ? 0 : tokens.length;
		while ( i-- ) {
			token = tokens[i];

			// Abort if we hit a combinator
			if ( Expr.relative[ (type = token.type) ] ) {
				break;
			}
			if ( (find = Expr.find[ type ]) ) {
				// Search, expanding context for leading sibling combinators
				if ( (seed = find(
					token.matches[0].replace( runescape, funescape ),
					rsibling.test( tokens[0].type ) && testContext( context.parentNode ) || context
				)) ) {

					// If seed is empty or no tokens remain, we can return early
					tokens.splice( i, 1 );
					selector = seed.length && toSelector( tokens );
					if ( !selector ) {
						push.apply( results, seed );
						return results;
					}

					break;
				}
			}
		}
	}

	// Compile and execute a filtering function if one is not provided
	// Provide `match` to avoid retokenization if we modified the selector above
	( compiled || compile( selector, match ) )(
		seed,
		context,
		!documentIsHTML,
		results,
		!context || rsibling.test( selector ) && testContext( context.parentNode ) || context
	);
	return results;
};

// One-time assignments

// Sort stability
support.sortStable = expando.split("").sort( sortOrder ).join("") === expando;

// Support: Chrome 14-35+
// Always assume duplicates if they aren't passed to the comparison function
support.detectDuplicates = !!hasDuplicate;

// Initialize against the default document
setDocument();

// Support: Webkit<537.32 - Safari 6.0.3/Chrome 25 (fixed in Chrome 27)
// Detached nodes confoundingly follow *each other*
support.sortDetached = assert(function( div1 ) {
	// Should return 1, but returns 4 (following)
	return div1.compareDocumentPosition( document.createElement("div") ) & 1;
});

// Support: IE<8
// Prevent attribute/property "interpolation"
// http://msdn.microsoft.com/en-us/library/ms536429%28VS.85%29.aspx
if ( !assert(function( div ) {
	div.innerHTML = "<a href='#'></a>";
	return div.firstChild.getAttribute("href") === "#" ;
}) ) {
	addHandle( "type|href|height|width", function( elem, name, isXML ) {
		if ( !isXML ) {
			return elem.getAttribute( name, name.toLowerCase() === "type" ? 1 : 2 );
		}
	});
}

// Support: IE<9
// Use defaultValue in place of getAttribute("value")
if ( !support.attributes || !assert(function( div ) {
	div.innerHTML = "<input/>";
	div.firstChild.setAttribute( "value", "" );
	return div.firstChild.getAttribute( "value" ) === "";
}) ) {
	addHandle( "value", function( elem, name, isXML ) {
		if ( !isXML && elem.nodeName.toLowerCase() === "input" ) {
			return elem.defaultValue;
		}
	});
}

// Support: IE<9
// Use getAttributeNode to fetch booleans when getAttribute lies
if ( !assert(function( div ) {
	return div.getAttribute("disabled") == null;
}) ) {
	addHandle( booleans, function( elem, name, isXML ) {
		var val;
		if ( !isXML ) {
			return elem[ name ] === true ? name.toLowerCase() :
					(val = elem.getAttributeNode( name )) && val.specified ?
					val.value :
				null;
		}
	});
}

// EXPOSE
if ( typeof define === "function" && define.amd ) {
	define(function() { return Sizzle; });
// Sizzle requires that there be a global window in Common-JS like environments
} else if ( typeof module !== "undefined" && module.exports ) {
	module.exports = Sizzle;
} else {
	window.Sizzle = Sizzle;
}
// EXPOSE

})( window );


================================================
FILE: package.json
================================================
{
  "name": "react-unit",
  "version": "3.0.3",
  "description": "Lightweight unit test library for ReactJS.",
  "main": "dist/react-unit.js",
  "scripts": {
    "test": "node_modules/.bin/gulp test"
  },
  "repository": {
    "type": "git",
    "url": "https://github.com/pzavolinsky/react-unit.git"
  },
  "keywords": [
    "react-component",
    "unit test",
    "test",
    "react",
    "jasmine"
  ],
  "author": "Patricio Zavolinsky",
  "license": "MIT",
  "bugs": {
    "url": "https://github.com/pzavolinsky/react-unit/issues"
  },
  "homepage": "https://github.com/pzavolinsky/react-unit",
  "devDependencies": {
    "@types/ramda": "0.0.5",
    "@types/react-dom": "^0.14.23",
    "@types/react-test-renderer": "^16.0.1",
    "del": "^1.2.1",
    "gulp": "^3.9.0",
    "gulp-babel": "^5.2.1",
    "gulp-insert": "^0.5.0",
    "gulp-jasmine": "^2.0.1",
    "gulp-rename": "^1.2.2",
    "gulp-typescript": "^2.13.6",
    "prop-types": "^15.5.6",
    "run-sequence": "^1.1.2",
    "tslint": "^5.0.0",
    "typescript": "^2.2.2"
  },
  "dependencies": {
    "ramda": "^0.17.1",
    "react": ">=15.5.3 <17.0.0",
    "react-dom": ">=15.5.3 <17.0.0",
    "react-test-renderer": ">=15.5.3 <17.0.0"
  }
}


================================================
FILE: src/add-ons/debug.ts
================================================
import { compose, merge } from 'ramda';
import
  { AddOn
  , InstanceMapper
  , ComponentMapper
  , ResolvedMapper
  , RenderContext
  } from '../types';

const instanceLogger:InstanceMapper = instance => {
  console.log('[instance]', instance);
  return instance;
};

const componentLogger:ComponentMapper = comp => {
  console.log('[component]', comp);
  return comp;
};

const resolveLogger:ResolvedMapper = comp => {
  console.log('[resolved]', comp);
  return comp;
};

const debug:AddOn = (ctx:RenderContext) => ():RenderContext =>
  merge(ctx, {
    instanceMapper: compose(instanceLogger, ctx.instanceMapper),
    componentMapper: compose(componentLogger, ctx.componentMapper),
    resolveMapper: compose(resolveLogger, ctx.resolveMapper)
  });

export default debug;


================================================
FILE: src/add-ons/exclude.ts
================================================
import { compose, merge, any } from 'ramda';
import
  { AddOn
  , RenderedComponent
  , RenderContext
  , ComponentMapper
  } from '../types';
import { isOfType, filterChildren } from '../utils';

const excludeMapper = (exclude:any[]|any):ComponentMapper => {
  const allowed:(comp:RenderedComponent) => boolean =
    exclude.constructor === Array
    ? comp => !any(t => isOfType(t, comp), exclude)
    : comp => !isOfType(exclude, comp);
  return comp => filterChildren(allowed, comp);
};

const exclude:AddOn = (ctx:RenderContext) =>
  (exclude:any[]|any):RenderContext => merge(ctx, {
    componentMapper: compose(excludeMapper(exclude), ctx.componentMapper)
  });

export default exclude;


================================================
FILE: src/add-ons/index.ts
================================================
import { AddOn } from '../types';
import exclude from './exclude';
import mock from './mock';
import withContext from './with-context';
import debug from './debug';

interface AddOnMap {
  [name:string]:AddOn
}

const addOns:AddOnMap = {
  exclude,
  mock,
  withContext,
  debug
};

export default addOns;


================================================
FILE: src/add-ons/mock.ts
================================================
import { compose, merge } from 'ramda';
import
  { AddOn
  , ComponentMapper
  , RenderContext
  , RenderedComponent
  , isShallow
  } from '../types';
import { isOfType, getTagNameForType } from '../utils';

const mockMapper = (actual:any, mock:any):ComponentMapper =>
  (comp:RenderedComponent) =>
    isShallow(comp) && isOfType(actual, comp)
    ? { type: 'shallow'
      , tagName: getTagNameForType(mock)
      , instance: merge(comp.instance, { type: mock })
      }
    : comp;

const mock:AddOn = (ctx:RenderContext) =>
  (actual:any, mock:any):RenderContext => merge(ctx, {
    componentMapper: compose(mockMapper(actual, mock), ctx.componentMapper)
  });

export default mock;


================================================
FILE: src/add-ons/with-context.ts
================================================
import { compose, merge } from 'ramda';
import { AddOn, InstanceMapper, RenderContext } from '../types';

const withContextMapper = (context:any):InstanceMapper =>
  instance => merge(instance, { context });

const withContext:AddOn = (ctx:RenderContext) =>
  (context:any):RenderContext => merge(ctx, {
    instanceMapper: compose(withContextMapper(context), ctx.instanceMapper)
  });

export default withContext;


================================================
FILE: src/defs.d.ts
================================================
declare module "react-test-renderer/shallow" {
  class ReactShallowRenderer {
    render(instance:any, ctx:any) : void;
    getRenderOutput() : any;
  }

  export = ReactShallowRenderer;
}

declare module "react-dom/test-utils" {
  export function isElementOfType(instance:any, type:any) : boolean;
}

interface Array<T> {
    filter<U extends T>(pred:(a:T) => a is U):U[];
}


================================================
FILE: src/pipeline.ts
================================================
import { compose } from 'ramda';
import
  { RenderContext
  , Resolver
  , HtmlComponent
  , ReactInstance
  } from './types';
import renderInstance from './render-instance';

const resolveAndMap = (ctx:RenderContext, resolver:Resolver) =>  {
  const mapAndRender = compose(renderInstance, ctx.instanceMapper);
  const resolve = resolver(ctx.componentMapper, mapAndRender);
  return compose(
    // 4) MAP the ResolvedComponent (optional).
    ctx.resolveMapper,

    // 3) RESOLVE the RenderedComponent into ResolvedComponent by applying a
    //    resolve strategy (deep, shallow, interleaved). The result replaces
    //    ShallowReactComponents with either a unknown components or HTML
    //    components. The resolution process applies a ComponentMapper to each
    //    RenderedComponent before resolving.
    resolve
  );
};

export const applyRootPipeline = (ctx:RenderContext, resolver:Resolver) =>
  compose(
    resolveAndMap(ctx, resolver),

    // 2) RENDER the React INSTANCE into a RenderedComponent (renderInstance)
    //    Note: at this stage, the RenderedComponent tree includes
    //    not-yet-rendered ShallowReactComponents.
    renderInstance,

    // 1) MAP the React INSTANCE (optional).
    ctx.instanceMapper
  );

const failShallowArtificial = (comp:HtmlComponent) =>
  (_:ReactInstance) => {
    throw `
      Cannot call renderNew on shallow rendered component ${comp.tagName}.

      Looks like you are trying test <Parent><Stateful /></Parent> using
      shallow render.

      Consider using another rendering mode (e.g. interleaved) or refactoring
      the test to do a shallow stateless test of <Parent /> and a shallow
      stateful test of <Stateful />;
    `;
  };

export const applyComponentPipeline = (ctx:RenderContext, resolver:Resolver) =>
  (comp:HtmlComponent) =>
    compose(
      resolveAndMap(ctx, resolver),

      // 2) RE-RENDER the React INSTANCE into a RenderedComponent (renderNew)
      //    Note: at this stage, the RenderedComponent tree includes
      //    not-yet-rendered ShallowReactComponents.
      comp.renderNew  || failShallowArtificial(comp),

      // 1) MAP the React INSTANCE (optional).
      ctx.instanceMapper
    );


================================================
FILE: src/react-unit.ts
================================================
import * as R from 'ramda';
import { UnitComponent } from './unit-component';
import
  { ReactInstance
  , RenderContext
  , Resolver
  , ResolvedComponent
  , AddOn
  , defaultRenderContext
  , isUnknown
  } from './types';
import
  { deepResolver
  , shallowResolver
  , interleavedResolver
  } from './resolver';
import { applyRootPipeline, applyComponentPipeline } from './pipeline';
import wrapper from './wrapper';
import addOns from './add-ons';

interface CreateComponentFn {
  (instance:ReactInstance):UnitComponent|any
}

interface CreateComponent extends CreateComponentFn {
  shallow: CreateComponentFn
  interleaved: CreateComponentFn
  ctx: RenderContext
}

const createComponent = (
  ctx:RenderContext,
  resolver:Resolver
):(instance:ReactInstance) => UnitComponent|any => {

  const rootPipeline = applyRootPipeline(ctx, resolver);
  const componentPipeline = applyComponentPipeline(ctx, resolver);

  function wrap(resolved:ResolvedComponent):UnitComponent|any {
    return isUnknown(resolved)
      ?  resolved.unknown
      :  wrapper(undefined, resolved, c => i => wrap(componentPipeline(c)(i)));
  }

  return R.compose(wrap, rootPipeline);
};

const makeCreateComponent = (ctx:RenderContext) => {
  const fn:CreateComponent = createComponent(ctx, deepResolver) as any;
  fn.shallow = createComponent(ctx, shallowResolver);
  fn.interleaved = createComponent(ctx, interleavedResolver);
  fn.ctx = ctx;
  return fn;
};

function applyAddons(fn:CreateComponent) {
  R.toPairs<string, AddOn>(addOns).forEach(([name, addOn]) => {
    (fn as any)[name] =
      R.compose(applyAddons, makeCreateComponent, addOn(fn.ctx));
  });
  return fn;
};

export = applyAddons(makeCreateComponent(defaultRenderContext));


================================================
FILE: src/render-instance.ts
================================================
import { Children } from 'react';
import { mergeAll } from 'ramda';
import ReactShallowRenderer = require('react-test-renderer/shallow');
import
  { ReactInstance
  , RenderedComponent
  , ShallowReactComponent
  , RenderedHtmlComponent
  , ArtificialHtmlComponent
  , RenderedUnknownComponent
  , RenderNew
  , isHtml
  } from './types';
import { getTagNameForType } from './utils';

// --- Rendered Component Wrapper Functions --------------------------------- //
function wrapShallowReactComponent(
  renderOutput:any
):ShallowReactComponent {
  const { type } = renderOutput;
  const tagName = getTagNameForType(type);
  return {
    type: 'shallow',
    tagName,
    instance: renderOutput
  };
};

const getPropsForOutput = (
  { key
  , ref
  , props
  , _store // tslint:disable-line
  }:any
) => mergeAll([
  _store && _store.props,
  props,
  { key, ref }
]) as any;

function wrapHtmlComponent(
  renderNew:RenderNew,
  renderOutput:any,
  instance:ReactInstance
):RenderedHtmlComponent {
  const { type, key, ref } = renderOutput;
  const props = getPropsForOutput(renderOutput);

  const children:RenderedComponent[] =
    props.children
    ? Children.map(
        props.children,
        c => processRenderOutput(renderNew, c, c)
      )
    : [];

  return {
    type: 'html',
    tagName: type,
    key,
    ref,
    props: props,
    renderOutput,
    instance,
    children,
    renderNew
  };
};

function wrapUnknownComponent(
  renderOutput:any
):RenderedUnknownComponent {
  return {
    type: 'unknown',
    unknown: renderOutput
  };
}

function processRenderOutput(
  renderNew:RenderNew,
  renderOutput:any,
  instance:any
):RenderedComponent {
  if (!renderOutput) {
    // e.g. render() { return undefined; }
    return wrapUnknownComponent(renderOutput);
  }

  if (typeof renderOutput.type === 'function') {
    // shallowRender reached another React component and stopped
    // renderOutput is the spec for that (child) component
    return wrapShallowReactComponent(renderOutput);
  }

  if (renderOutput.type && renderOutput.props) {
    // shallowRender returned an HTML component
    return wrapHtmlComponent(renderNew, renderOutput, instance);
  }

  return wrapUnknownComponent(renderOutput);
}

// --- Public API ----------------------------------------------------------- //
export const toArtificialHtml = (
  comp:ShallowReactComponent|RenderedHtmlComponent,
  child?:RenderedComponent
):ArtificialHtmlComponent => ({
  type:         'artificial',
  tagName:      getTagNameForType(comp.instance.type),
  props:        getPropsForOutput(comp.instance),
  renderOutput: comp.instance,
  instance:     comp.instance,
  children:     child ? [child] : [],
  renderNew:    child && isHtml(child) ? child.renderNew : undefined
});

const renderInstance = (instance:ReactInstance):RenderedComponent => {

  const shallowRenderer = new ReactShallowRenderer();

  function create(componentInstance:ReactInstance):RenderedComponent {

    shallowRenderer.render(componentInstance, componentInstance.context);

    const renderOutput = shallowRenderer.getRenderOutput();
    const renderNew = (newInstance?:ReactInstance) =>
      create(newInstance || componentInstance);

    return processRenderOutput(renderNew, renderOutput, componentInstance);
  }
  return create(instance);
};

export default renderInstance;


================================================
FILE: src/resolver.ts
================================================
import { merge } from 'ramda';
import { toArtificialHtml } from './render-instance';
import
  { ComponentMapper
  , InstanceRenderer
  , RenderedComponent
  , ResolvedComponent
  , isHtml
  , isShallow
  } from './types';

export function deepResolver(
  mapper:ComponentMapper,
  renderer:InstanceRenderer
) {
  return (comp:RenderedComponent):ResolvedComponent => {
    const resolve = deepResolver(mapper, renderer);
    const mapped = mapper(comp);
    if (isShallow(mapped)) {
      const newComp = renderer(mapped.instance);
      // note that newComp might be shallow again, so we need to call
      // deepResolver on it to resolve the whole the tree
      return resolve(newComp);
    }
    if (isHtml(mapped)) return merge(mapped, {
      children: mapped.children.map(resolve)
    });
    return mapped;
  };
}

export function shallowResolver(
  mapper:ComponentMapper,
  _:InstanceRenderer
) {
  return (comp:RenderedComponent):ResolvedComponent => {
    const resolve = shallowResolver(mapper, _);
    const mapped = mapper(comp);
    if (isShallow(mapped)) {
      return toArtificialHtml(mapped);
    }
    if (isHtml(mapped)) {
      return merge(mapped, {
        children: mapped.children.map(resolve)
      });
    }
    return mapped;
  };
}

export function interleavedResolver(
  mapper:ComponentMapper,
  renderer:InstanceRenderer,
  nonRoot?:boolean
) {
  return (comp:RenderedComponent):ResolvedComponent => {
    const resolve = interleavedResolver(mapper, renderer, true);
    const mapped = mapper(comp);
    if (isShallow(mapped)) {
      const newComp = renderer(mapped.instance);
      // note that newComp might be shallow again, so we need to call
      // interleavedResolver on it to render the whole the tree
      const renderedComp = resolve(newComp);
      return toArtificialHtml(mapped, renderedComp);
    }

    if (isHtml(mapped)) {
      const mappedWithChildren = merge(mapped, {
        children: mapped.children.map(resolve)
      });

      return nonRoot
        ? mappedWithChildren
        : toArtificialHtml(mappedWithChildren, mappedWithChildren);
    }

    return mapped;
  };
}


================================================
FILE: src/sizzle-bundle.d.ts
================================================
declare function lookup(s:string, comp:any):any[];
export = lookup;


================================================
FILE: src/sizzle-bundle.js
================================================

var document = {
	createElement: function(tag) {
		return {
			appendChild: function() {},
			getElementsByTagName: function() { return []; },
			getAttribute: function() {}
		}
	},
	createComment: function(s) { return s; },
	getElementsByClassName: ' { [native code] }',
	nodeType: 9,
	documentElement: { nodeName: 'HTML' }
};
document.ownerDocument = document;
var window = { document: document };

var _ = (function() {
	/*!
 * Sizzle CSS Selector Engine v2.2.1-pre
 * http://sizzlejs.com/
 *
 * Copyright jQuery Foundation and other contributors
 * Released under the MIT license
 * http://jquery.org/license
 *
 * Date: 2015-08-17
 */
(function( window ) {

var i,
	support,
	Expr,
	getText,
	isXML,
	tokenize,
	compile,
	select,
	outermostContext,
	sortInput,
	hasDuplicate,

	// Local document vars
	setDocument,
	document,
	docElem,
	documentIsHTML,
	rbuggyQSA,
	rbuggyMatches,
	matches,
	contains,

	// Instance-specific data
	expando = "sizzle" + 1 * new Date(),
	preferredDoc = window.document,
	dirruns = 0,
	done = 0,
	classCache = createCache(),
	tokenCache = createCache(),
	compilerCache = createCache(),
	sortOrder = function( a, b ) {
		if ( a === b ) {
			hasDuplicate = true;
		}
		return 0;
	},

	// General-purpose constants
	MAX_NEGATIVE = 1 << 31,

	// Instance methods
	hasOwn = ({}).hasOwnProperty,
	arr = [],
	pop = arr.pop,
	push_native = arr.push,
	push = arr.push,
	slice = arr.slice,
	// Use a stripped-down indexOf as it's faster than native
	// http://jsperf.com/thor-indexof-vs-for/5
	indexOf = function( list, elem ) {
		var i = 0,
			len = list.length;
		for ( ; i < len; i++ ) {
			if ( list[i] === elem ) {
				return i;
			}
		}
		return -1;
	},

	booleans = "checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped",

	// Regular expressions

	// http://www.w3.org/TR/css3-selectors/#whitespace
	whitespace = "[\\x20\\t\\r\\n\\f]",

	// http://www.w3.org/TR/CSS21/syndata.html#value-def-identifier
	identifier = "(?:\\\\.|[\\w-]|[^\\x00-\\xa0])+",

	// Attribute selectors: http://www.w3.org/TR/selectors/#attribute-selectors
	attributes = "\\[" + whitespace + "*(" + identifier + ")(?:" + whitespace +
		// Operator (capture 2)
		"*([*^$|!~]?=)" + whitespace +
		// "Attribute values must be CSS identifiers [capture 5] or strings [capture 3 or capture 4]"
		"*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|(" + identifier + "))|)" + whitespace +
		"*\\]",

	pseudos = ":(" + identifier + ")(?:\\((" +
		// To reduce the number of selectors needing tokenize in the preFilter, prefer arguments:
		// 1. quoted (capture 3; capture 4 or capture 5)
		"('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|" +
		// 2. simple (capture 6)
		"((?:\\\\.|[^\\\\()[\\]]|" + attributes + ")*)|" +
		// 3. anything else (capture 2)
		".*" +
		")\\)|)",

	// Leading and non-escaped trailing whitespace, capturing some non-whitespace characters preceding the latter
	rwhitespace = new RegExp( whitespace + "+", "g" ),
	rtrim = new RegExp( "^" + whitespace + "+|((?:^|[^\\\\])(?:\\\\.)*)" + whitespace + "+$", "g" ),

	rcomma = new RegExp( "^" + whitespace + "*," + whitespace + "*" ),
	rcombinators = new RegExp( "^" + whitespace + "*([>+~]|" + whitespace + ")" + whitespace + "*" ),

	rattributeQuotes = new RegExp( "=" + whitespace + "*([^\\]'\"]*?)" + whitespace + "*\\]", "g" ),

	rpseudo = new RegExp( pseudos ),
	ridentifier = new RegExp( "^" + identifier + "$" ),

	matchExpr = {
		"ID": new RegExp( "^#(" + identifier + ")" ),
		"CLASS": new RegExp( "^\\.(" + identifier + ")" ),
		"TAG": new RegExp( "^(" + identifier + "|[*])" ),
		"ATTR": new RegExp( "^" + attributes ),
		"PSEUDO": new RegExp( "^" + pseudos ),
		"CHILD": new RegExp( "^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\(" + whitespace +
			"*(even|odd|(([+-]|)(\\d*)n|)" + whitespace + "*(?:([+-]|)" + whitespace +
			"*(\\d+)|))" + whitespace + "*\\)|)", "i" ),
		"bool": new RegExp( "^(?:" + booleans + ")$", "i" ),
		// For use in libraries implementing .is()
		// We use this for POS matching in `select`
		"needsContext": new RegExp( "^" + whitespace + "*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\(" +
			whitespace + "*((?:-\\d)?\\d*)" + whitespace + "*\\)|)(?=[^-]|$)", "i" )
	},

	rinputs = /^(?:input|select|textarea|button)$/i,
	rheader = /^h\d$/i,

	rnative = /^[^{]+\{\s*\[native \w/,

	// Easily-parseable/retrievable ID or TAG or CLASS selectors
	rquickExpr = /^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,

	rsibling = /[+~]/,
	rescape = /'|\\/g,

	// CSS escapes http://www.w3.org/TR/CSS21/syndata.html#escaped-characters
	runescape = new RegExp( "\\\\([\\da-f]{1,6}" + whitespace + "?|(" + whitespace + ")|.)", "ig" ),
	funescape = function( _, escaped, escapedWhitespace ) {
		var high = "0x" + escaped - 0x10000;
		// NaN means non-codepoint
		// Support: Firefox<24
		// Workaround erroneous numeric interpretation of +"0x"
		return high !== high || escapedWhitespace ?
			escaped :
			high < 0 ?
				// BMP codepoint
				String.fromCharCode( high + 0x10000 ) :
				// Supplemental Plane codepoint (surrogate pair)
				String.fromCharCode( high >> 10 | 0xD800, high & 0x3FF | 0xDC00 );
	},

	// Used for iframes
	// See setDocument()
	// Removing the function wrapper causes a "Permission Denied"
	// error in IE
	unloadHandler = function() {
		setDocument();
	};

// Optimize for push.apply( _, NodeList )
try {
	push.apply(
		(arr = slice.call( preferredDoc.childNodes )),
		preferredDoc.childNodes
	);
	// Support: Android<4.0
	// Detect silently failing push.apply
	arr[ preferredDoc.childNodes.length ].nodeType;
} catch ( e ) {
	push = { apply: arr.length ?

		// Leverage slice if possible
		function( target, els ) {
			push_native.apply( target, slice.call(els) );
		} :

		// Support: IE<9
		// Otherwise append directly
		function( target, els ) {
			var j = target.length,
				i = 0;
			// Can't trust NodeList.length
			while ( (target[j++] = els[i++]) ) {}
			target.length = j - 1;
		}
	};
}

function Sizzle( selector, context, results, seed ) {
	var m, i, elem, nid, match, groups, newSelector,
		newContext = context && context.ownerDocument,

		// nodeType defaults to 9, since context defaults to document
		nodeType = context ? context.nodeType : 9;

	results = results || [];

	// Return early from calls with invalid selector or context
	if ( typeof selector !== "string" || !selector ||
		nodeType !== 1 && nodeType !== 9 && nodeType !== 11 ) {

		return results;
	}

	// Try to shortcut find operations (as opposed to filters) in HTML documents
	if ( !seed ) {

		if ( ( context ? context.ownerDocument || context : preferredDoc ) !== document ) {
			setDocument( context );
		}
		context = context || document;

		if ( documentIsHTML ) {

			// If the selector is sufficiently simple, try using a "get*By*" DOM method
			// (excepting DocumentFragment context, where the methods don't exist)
			if ( nodeType !== 11 && (match = rquickExpr.exec( selector )) ) {

				// ID selector
				if ( (m = match[1]) ) {

					// Document context
					if ( nodeType === 9 ) {
						if ( (elem = context.getElementById( m )) ) {

							// Support: IE, Opera, Webkit
							// TODO: identify versions
							// getElementById can match elements by name instead of ID
							if ( elem.id === m ) {
								results.push( elem );
								return results;
							}
						} else {
							return results;
						}

					// Element context
					} else {

						// Support: IE, Opera, Webkit
						// TODO: identify versions
						// getElementById can match elements by name instead of ID
						if ( newContext && (elem = newContext.getElementById( m )) &&
							contains( context, elem ) &&
							elem.id === m ) {

							results.push( elem );
							return results;
						}
					}

				// Type selector
				} else if ( match[2] ) {
					push.apply( results, context.getElementsByTagName( selector ) );
					return results;

				// Class selector
				} else if ( (m = match[3]) && support.getElementsByClassName &&
					context.getElementsByClassName ) {

					push.apply( results, context.getElementsByClassName( m ) );
					return results;
				}
			}

			// Take advantage of querySelectorAll
			if ( support.qsa &&
				!compilerCache[ selector + " " ] &&
				(!rbuggyQSA || !rbuggyQSA.test( selector )) ) {

				if ( nodeType !== 1 ) {
					newContext = context;
					newSelector = selector;

				// qSA looks outside Element context, which is not what we want
				// Thanks to Andrew Dupont for this workaround technique
				// Support: IE <=8
				// Exclude object elements
				} else if ( context.nodeName.toLowerCase() !== "object" ) {

					// Capture the context ID, setting it first if necessary
					if ( (nid = context.getAttribute( "id" )) ) {
						nid = nid.replace( rescape, "\\CONTENT" );
					} else {
						context.setAttribute( "id", (nid = expando) );
					}

					// Prefix every selector in the list
					groups = tokenize( selector );
					i = groups.length;
					while ( i-- ) {
						groups[i] = "[id='" + nid + "'] " + toSelector( groups[i] );
					}
					newSelector = groups.join( "," );

					// Expand context for sibling selectors
					newContext = rsibling.test( selector ) && testContext( context.parentNode ) ||
						context;
				}

				if ( newSelector ) {
					try {
						push.apply( results,
							newContext.querySelectorAll( newSelector )
						);
						return results;
					} catch ( qsaError ) {
					} finally {
						if ( nid === expando ) {
							context.removeAttribute( "id" );
						}
					}
				}
			}
		}
	}

	// All others
	return select( selector.replace( rtrim, "$1" ), context, results, seed );
}

/**
 * Create key-value caches of limited size
 * @returns {function(string, object)} Returns the Object data after storing it on itself with
 *	property name the (space-suffixed) string and (if the cache is larger than Expr.cacheLength)
 *	deleting the oldest entry
 */
function createCache() {
	var keys = [];

	function cache( key, value ) {
		// Use (key + " ") to avoid collision with native prototype properties (see Issue #157)
		if ( keys.push( key + " " ) > Expr.cacheLength ) {
			// Only keep the most recent entries
			delete cache[ keys.shift() ];
		}
		return (cache[ key + " " ] = value);
	}
	return cache;
}

/**
 * Mark a function for special use by Sizzle
 * @param {Function} fn The function to mark
 */
function markFunction( fn ) {
	fn[ expando ] = true;
	return fn;
}

/**
 * Support testing using an element
 * @param {Function} fn Passed the created div and expects a boolean result
 */
function assert( fn ) {
	var div = document.createElement("div");

	try {
		return !!fn( div );
	} catch (e) {
		return false;
	} finally {
		// Remove from its parent by default
		if ( div.parentNode ) {
			div.parentNode.removeChild( div );
		}
		// release memory in IE
		div = null;
	}
}

/**
 * Adds the same handler for all of the specified attrs
 * @param {String} attrs Pipe-separated list of attributes
 * @param {Function} handler The method that will be applied
 */
function addHandle( attrs, handler ) {
	var arr = attrs.split("|"),
		i = attrs.length;

	while ( i-- ) {
		Expr.attrHandle[ arr[i] ] = handler;
	}
}

/**
 * Checks document order of two siblings
 * @param {Element} a
 * @param {Element} b
 * @returns {Number} Returns less than 0 if a precedes b, greater than 0 if a follows b
 */
function siblingCheck( a, b ) {
	var cur = b && a,
		diff = cur && a.nodeType === 1 && b.nodeType === 1 &&
			( ~b.sourceIndex || MAX_NEGATIVE ) -
			( ~a.sourceIndex || MAX_NEGATIVE );

	// Use IE sourceIndex if available on both nodes
	if ( diff ) {
		return diff;
	}

	// Check if b follows a
	if ( cur ) {
		while ( (cur = cur.nextSibling) ) {
			if ( cur === b ) {
				return -1;
			}
		}
	}

	return a ? 1 : -1;
}

/**
 * Returns a function to use in pseudos for input types
 * @param {String} type
 */
function createInputPseudo( type ) {
	return function( elem ) {
		var name = elem.nodeName.toLowerCase();
		return name === "input" && elem.type === type;
	};
}

/**
 * Returns a function to use in pseudos for buttons
 * @param {String} type
 */
function createButtonPseudo( type ) {
	return function( elem ) {
		var name = elem.nodeName.toLowerCase();
		return (name === "input" || name === "button") && elem.type === type;
	};
}

/**
 * Returns a function to use in pseudos for positionals
 * @param {Function} fn
 */
function createPositionalPseudo( fn ) {
	return markFunction(function( argument ) {
		argument = +argument;
		return markFunction(function( seed, matches ) {
			var j,
				matchIndexes = fn( [], seed.length, argument ),
				i = matchIndexes.length;

			// Match elements found at the specified indexes
			while ( i-- ) {
				if ( seed[ (j = matchIndexes[i]) ] ) {
					seed[j] = !(matches[j] = seed[j]);
				}
			}
		});
	});
}

/**
 * Checks a node for validity as a Sizzle context
 * @param {Element|Object=} context
 * @returns {Element|Object|Boolean} The input node if acceptable, otherwise a falsy value
 */
function testContext( context ) {
	return context && typeof context.getElementsByTagName !== "undefined" && context;
}

// Expose support vars for convenience
support = Sizzle.support = {};

/**
 * Detects XML nodes
 * @param {Element|Object} elem An element or a document
 * @returns {Boolean} True iff elem is a non-HTML XML node
 */
isXML = Sizzle.isXML = function( elem ) {
	// documentElement is verified for cases where it doesn't yet exist
	// (such as loading iframes in IE - #4833)
	var documentElement = elem && (elem.ownerDocument || elem).documentElement;
	return documentElement ? documentElement.nodeName !== "HTML" : false;
};

/**
 * Sets document-related variables once based on the current document
 * @param {Element|Object} [doc] An element or document object to use to set the document
 * @returns {Object} Returns the current document
 */
setDocument = Sizzle.setDocument = function( node ) {
	var hasCompare, parent,
		doc = node ? node.ownerDocument || node : preferredDoc;

	// Return early if doc is invalid or already selected
	if ( doc === document || doc.nodeType !== 9 || !doc.documentElement ) {
		return document;
	}

	// Update global variables
	document = doc;
	docElem = document.documentElement;
	documentIsHTML = !isXML( document );

	// Support: IE 9-11, Edge
	// Accessing iframe documents after unload throws "permission denied" errors (jQuery #13936)
	if ( (parent = document.defaultView) && parent.top !== parent ) {
		// Support: IE 11
		if ( parent.addEventListener ) {
			parent.addEventListener( "unload", unloadHandler, false );

		// Support: IE 9 - 10 only
		} else if ( parent.attachEvent ) {
			parent.attachEvent( "onunload", unloadHandler );
		}
	}

	/* Attributes
	---------------------------------------------------------------------- */

	// Support: IE<8
	// Verify that getAttribute really returns attributes and not properties
	// (excepting IE8 booleans)
	support.attributes = assert(function( div ) {
		div.className = "i";
		return !div.getAttribute("className");
	});

	/* getElement(s)By*
	---------------------------------------------------------------------- */

	// Check if getElementsByTagName("*") returns only elements
	support.getElementsByTagName = assert(function( div ) {
		div.appendChild( document.createComment("") );
		return !div.getElementsByTagName("*").length;
	});

	// Support: IE<9
	support.getElementsByClassName = rnative.test( document.getElementsByClassName );

	// Support: IE<10
	// Check if getElementById returns elements by name
	// The broken getElementById methods don't pick up programatically-set names,
	// so use a roundabout getElementsByName test
	support.getById = assert(function( div ) {
		docElem.appendChild( div ).id = expando;
		return !document.getElementsByName || !document.getElementsByName( expando ).length;
	});

	// ID find and filter
	if ( support.getById ) {
		Expr.find["ID"] = function( id, context ) {
			if ( typeof context.getElementById !== "undefined" && documentIsHTML ) {
				var m = context.getElementById( id );
				return m ? [ m ] : [];
			}
		};
		Expr.filter["ID"] = function( id ) {
			var attrId = id.replace( runescape, funescape );
			return function( elem ) {
				return elem.getAttribute("id") === attrId;
			};
		};
	} else {
		// Support: IE6/7
		// getElementById is not reliable as a find shortcut
		delete Expr.find["ID"];

		Expr.filter["ID"] =  function( id ) {
			var attrId = id.replace( runescape, funescape );
			return function( elem ) {
				var node = typeof elem.getAttributeNode !== "undefined" &&
					elem.getAttributeNode("id");
				return node && node.value === attrId;
			};
		};
	}

	// Tag
	Expr.find["TAG"] = support.getElementsByTagName ?
		function( tag, context ) {
			if ( typeof context.getElementsByTagName !== "undefined" ) {
				return context.getElementsByTagName( tag );

			// DocumentFragment nodes don't have gEBTN
			} else if ( support.qsa ) {
				return context.querySelectorAll( tag );
			}
		} :

		function( tag, context ) {
			var elem,
				tmp = [],
				i = 0,
				// By happy coincidence, a (broken) gEBTN appears on DocumentFragment nodes too
				results = context.getElementsByTagName( tag );

			// Filter out possible comments
			if ( tag === "*" ) {
				while ( (elem = results[i++]) ) {
					if ( elem.nodeType === 1 ) {
						tmp.push( elem );
					}
				}

				return tmp;
			}
			return results;
		};

	// Class
	Expr.find["CLASS"] = support.getElementsByClassName && function( className, context ) {
		if ( typeof context.getElementsByClassName !== "undefined" && documentIsHTML ) {
			return context.getElementsByClassName( className );
		}
	};

	/* QSA/matchesSelector
	---------------------------------------------------------------------- */

	// QSA and matchesSelector support

	// matchesSelector(:active) reports false when true (IE9/Opera 11.5)
	rbuggyMatches = [];

	// qSa(:focus) reports false when true (Chrome 21)
	// We allow this because of a bug in IE8/9 that throws an error
	// whenever `document.activeElement` is accessed on an iframe
	// So, we allow :focus to pass through QSA all the time to avoid the IE error
	// See http://bugs.jquery.com/ticket/13378
	rbuggyQSA = [];

	if ( (support.qsa = rnative.test( document.querySelectorAll )) ) {
		// Build QSA regex
		// Regex strategy adopted from Diego Perini
		assert(function( div ) {
			// Select is set to empty string on purpose
			// This is to test IE's treatment of not explicitly
			// setting a boolean content attribute,
			// since its presence should be enough
			// http://bugs.jquery.com/ticket/12359
			docElem.appendChild( div ).innerHTML = "<a id='" + expando + "'></a>" +
				"<select id='" + expando + "-\r\\' msallowcapture=''>" +
				"<option selected=''></option></select>";

			// Support: IE8, Opera 11-12.16
			// Nothing should be selected when empty strings follow ^= or $= or *=
			// The test attribute must be unknown in Opera but "safe" for WinRT
			// http://msdn.microsoft.com/en-us/library/ie/hh465388.aspx#attribute_section
			if ( div.
Download .txt
gitextract_ljpf4nw2/

├── .gitignore
├── .npmignore
├── LICENSE
├── README.md
├── dist/
│   ├── add-ons/
│   │   ├── debug.js
│   │   ├── exclude.js
│   │   ├── index.js
│   │   ├── mock.js
│   │   └── with-context.js
│   ├── internal/
│   │   └── test-render-instance.js
│   ├── pipeline.js
│   ├── react-unit.js
│   ├── render-instance.js
│   ├── resolver.js
│   ├── sizzle-bundle.js
│   ├── types.js
│   ├── unit-component.js
│   ├── utils.js
│   └── wrapper.js
├── gulpfile.js
├── lib/
│   ├── sizzle-bundle.js
│   └── sizzle.js
├── package.json
├── src/
│   ├── add-ons/
│   │   ├── debug.ts
│   │   ├── exclude.ts
│   │   ├── index.ts
│   │   ├── mock.ts
│   │   └── with-context.ts
│   ├── defs.d.ts
│   ├── pipeline.ts
│   ├── react-unit.ts
│   ├── render-instance.ts
│   ├── resolver.ts
│   ├── sizzle-bundle.d.ts
│   ├── sizzle-bundle.js
│   ├── types.ts
│   ├── unit-component.ts
│   ├── utils.ts
│   └── wrapper.ts
├── test/
│   ├── create-component-interleaved.jsx
│   ├── create-component-shallow.jsx
│   ├── create-component.jsx
│   ├── events.jsx
│   ├── exclude.jsx
│   ├── find-by-component.jsx
│   ├── find-by-query.jsx
│   ├── find-by-ref.jsx
│   ├── find-by.jsx
│   ├── internal/
│   │   └── render-instance.jsx
│   ├── mock.jsx
│   ├── render-new.jsx
│   ├── stateful.jsx
│   ├── stateless.jsx
│   ├── text.jsx
│   └── with-context.jsx
├── tsconfig.json
├── tslint.json
└── typings.json
Download .txt
SYMBOL INDEX (163 symbols across 23 files)

FILE: dist/internal/test-render-instance.js
  function _interopRequireDefault (line 3) | function _interopRequireDefault(obj) { return obj && obj.__esModule ? ob...

FILE: dist/react-unit.js
  function wrap (line 11) | function wrap(resolved) {
  function applyAddons (line 25) | function applyAddons(fn) {

FILE: dist/render-instance.js
  function wrapShallowReactComponent (line 9) | function wrapShallowReactComponent(renderOutput) {
  function wrapHtmlComponent (line 28) | function wrapHtmlComponent(renderNew, renderOutput, instance) {
  function wrapUnknownComponent (line 47) | function wrapUnknownComponent(renderOutput) {
  function processRenderOutput (line 53) | function processRenderOutput(renderNew, renderOutput, instance) {
  function create (line 81) | function create(componentInstance) {

FILE: dist/resolver.js
  function deepResolver (line 6) | function deepResolver(mapper, renderer) {
  function shallowResolver (line 24) | function shallowResolver(mapper, _) {
  function interleavedResolver (line 40) | function interleavedResolver(mapper, renderer, nonRoot) {

FILE: dist/sizzle-bundle.js
  function Sizzle (line 211) | function Sizzle( selector, context, results, seed ) {
  function createCache (line 350) | function createCache() {
  function markFunction (line 368) | function markFunction( fn ) {
  function assert (line 377) | function assert( fn ) {
  function addHandle (line 399) | function addHandle( attrs, handler ) {
  function siblingCheck (line 414) | function siblingCheck( a, b ) {
  function createInputPseudo (line 441) | function createInputPseudo( type ) {
  function createButtonPseudo (line 452) | function createButtonPseudo( type ) {
  function createPositionalPseudo (line 463) | function createPositionalPseudo( fn ) {
  function testContext (line 486) | function testContext( context ) {
  function setFilters (line 1531) | function setFilters() {}
  function toSelector (line 1602) | function toSelector( tokens ) {
  function addCombinator (line 1612) | function addCombinator( matcher, combinator, base ) {
  function elementMatcher (line 1670) | function elementMatcher( matchers ) {
  function multipleContexts (line 1684) | function multipleContexts( selector, contexts, results ) {
  function condense (line 1693) | function condense( unmatched, map, filter, context, xml ) {
  function setMatcher (line 1714) | function setMatcher( preFilter, selector, matcher, postFilter, postFinde...
  function matcherFromTokens (line 1807) | function matcherFromTokens( tokens ) {
  function matcherFromGroupMatchers (line 1865) | function matcherFromGroupMatchers( elementMatchers, setMatchers ) {

FILE: dist/unit-component.js
  function UnitComponent (line 11) | function UnitComponent(comp, parent, renderNew) {

FILE: dist/utils.js
  function filterChildren (line 14) | function filterChildren(fn, comp) {

FILE: dist/wrapper.js
  function wrapRenderedIntoUnitComponent (line 5) | function wrapRenderedIntoUnitComponent(parent, htmlComponent, componentP...

FILE: lib/sizzle.js
  function Sizzle (line 193) | function Sizzle( selector, context, results, seed ) {
  function createCache (line 332) | function createCache() {
  function markFunction (line 350) | function markFunction( fn ) {
  function assert (line 359) | function assert( fn ) {
  function addHandle (line 381) | function addHandle( attrs, handler ) {
  function siblingCheck (line 396) | function siblingCheck( a, b ) {
  function createInputPseudo (line 423) | function createInputPseudo( type ) {
  function createButtonPseudo (line 434) | function createButtonPseudo( type ) {
  function createPositionalPseudo (line 445) | function createPositionalPseudo( fn ) {
  function testContext (line 468) | function testContext( context ) {
  function setFilters (line 1513) | function setFilters() {}
  function toSelector (line 1584) | function toSelector( tokens ) {
  function addCombinator (line 1594) | function addCombinator( matcher, combinator, base ) {
  function elementMatcher (line 1652) | function elementMatcher( matchers ) {
  function multipleContexts (line 1666) | function multipleContexts( selector, contexts, results ) {
  function condense (line 1675) | function condense( unmatched, map, filter, context, xml ) {
  function setMatcher (line 1696) | function setMatcher( preFilter, selector, matcher, postFilter, postFinde...
  function matcherFromTokens (line 1789) | function matcherFromTokens( tokens ) {
  function matcherFromGroupMatchers (line 1847) | function matcherFromGroupMatchers( elementMatchers, setMatchers ) {

FILE: src/add-ons/index.ts
  type AddOnMap (line 7) | interface AddOnMap {

FILE: src/defs.d.ts
  class ReactShallowRenderer (line 2) | class ReactShallowRenderer {
  type Array (line 14) | interface Array<T> {

FILE: src/react-unit.ts
  type CreateComponentFn (line 21) | interface CreateComponentFn {
  type CreateComponent (line 25) | interface CreateComponent extends CreateComponentFn {
  function wrap (line 39) | function wrap(resolved:ResolvedComponent):UnitComponent|any {
  function applyAddons (line 56) | function applyAddons(fn:CreateComponent) {

FILE: src/render-instance.ts
  function wrapShallowReactComponent (line 17) | function wrapShallowReactComponent(
  function wrapHtmlComponent (line 41) | function wrapHtmlComponent(
  function wrapUnknownComponent (line 70) | function wrapUnknownComponent(
  function processRenderOutput (line 79) | function processRenderOutput(
  function create (line 121) | function create(componentInstance:ReactInstance):RenderedComponent {

FILE: src/resolver.ts
  function deepResolver (line 12) | function deepResolver(
  function shallowResolver (line 32) | function shallowResolver(
  function interleavedResolver (line 51) | function interleavedResolver(

FILE: src/sizzle-bundle.js
  function Sizzle (line 211) | function Sizzle( selector, context, results, seed ) {
  function createCache (line 350) | function createCache() {
  function markFunction (line 368) | function markFunction( fn ) {
  function assert (line 377) | function assert( fn ) {
  function addHandle (line 399) | function addHandle( attrs, handler ) {
  function siblingCheck (line 414) | function siblingCheck( a, b ) {
  function createInputPseudo (line 441) | function createInputPseudo( type ) {
  function createButtonPseudo (line 452) | function createButtonPseudo( type ) {
  function createPositionalPseudo (line 463) | function createPositionalPseudo( fn ) {
  function testContext (line 486) | function testContext( context ) {
  function setFilters (line 1531) | function setFilters() {}
  function toSelector (line 1602) | function toSelector( tokens ) {
  function addCombinator (line 1612) | function addCombinator( matcher, combinator, base ) {
  function elementMatcher (line 1670) | function elementMatcher( matchers ) {
  function multipleContexts (line 1684) | function multipleContexts( selector, contexts, results ) {
  function condense (line 1693) | function condense( unmatched, map, filter, context, xml ) {
  function setMatcher (line 1714) | function setMatcher( preFilter, selector, matcher, postFilter, postFinde...
  function matcherFromTokens (line 1807) | function matcherFromTokens( tokens ) {
  function matcherFromGroupMatchers (line 1865) | function matcherFromGroupMatchers( elementMatchers, setMatchers ) {

FILE: src/types.ts
  type ReactInstance (line 13) | interface ReactInstance {
  type InstanceMapper (line 24) | interface InstanceMapper {
  type InstanceRenderer (line 29) | interface InstanceRenderer {
  type RenderedComponent (line 32) | type RenderedComponent
  type ComponentMapper (line 39) | interface ComponentMapper {
  type Resolver (line 46) | interface Resolver {
  type ResolvedComponent (line 51) | type ResolvedComponent
  type ResolvedMapper (line 57) | interface ResolvedMapper {
  type RenderContext (line 62) | interface RenderContext {
  type AddOn (line 76) | interface AddOn {
  type ShallowReactComponent (line 86) | interface ShallowReactComponent {
  type HtmlComponentBase (line 93) | interface HtmlComponentBase {
  type RenderedHtmlComponent (line 102) | interface RenderedHtmlComponent extends HtmlComponentBase {
  type ArtificialHtmlComponent (line 107) | interface ArtificialHtmlComponent extends HtmlComponentBase {
  type RenderedUnknownComponent (line 113) | interface RenderedUnknownComponent {
  type HtmlComponent (line 118) | type HtmlComponent
  type RenderNew (line 122) | interface RenderNew {

FILE: src/unit-component.ts
  type Root (line 8) | type Root = 'root';
  constant ROOT (line 9) | const ROOT:Root = 'root';
  type RenderNewUnit (line 12) | interface RenderNewUnit {
  class UnitComponent (line 17) | class UnitComponent {
    method constructor (line 32) | constructor(
    method prop (line 59) | prop(name:string) { return (this.props || {})[name]; }
    method findBy (line 61) | findBy(fn:(c:UnitComponent) => boolean):UnitComponent[] {
    method findByRef (line 75) | findByRef(ref:any) {
    method findByTag (line 78) | findByTag(type:string) {
    method findByClassName (line 81) | findByClassName(search:string) {
    method findByComponent (line 85) | findByComponent(componentClass:any) {
    method on (line 90) | on(event:string, e:any) {
    method onChange (line 97) | onChange(e:any) { this.on('change', e); }
    method onClick (line 98) | onClick(e:any) { this.on('click', e); }
    method setValueKey (line 99) | setValueKey(n:string, v:any ) {
    method setValue (line 102) | setValue(v:any) { this.setValueKey('value', v); }
    method setChecked (line 103) | setChecked(v:boolean) { this.setValueKey('checked', v); }
    method findByQuery (line 105) | findByQuery(s:string):UnitComponent[] {
    method dump (line 111) | dump(padd:string|undefined) {
    method children (line 139) | get children() {
    method textContent (line 143) | get textContent() {
    method getElementsByTagName (line 147) | getElementsByTagName(tagName:string) {
    method getElementsByClassName (line 151) | getElementsByClassName(className:string) {
    method getAttribute (line 155) | getAttribute(name:string) {
    method getAttributeNode (line 159) | getAttributeNode(name:string) {
  type OptionalUnitComponent (line 165) | type OptionalUnitComponent = UnitComponent | undefined;

FILE: src/utils.ts
  function filterChildren (line 18) | function filterChildren(

FILE: src/wrapper.ts
  function wrapRenderedIntoUnitComponent (line 12) | function wrapRenderedIntoUnitComponent(

FILE: test/events.jsx
  class ToUppercaseInput (line 5) | class ToUppercaseInput extends React.Component {
    method constructor (line 6) | constructor(props, ctx) {
    method onChange (line 10) | onChange(e) {
    method render (line 15) | render() {
  class OnlyUppercaseInput (line 21) | class OnlyUppercaseInput extends React.Component {
    method constructor (line 22) | constructor(props, ctx) {
    method onChange (line 26) | onChange(e) {
    method render (line 30) | render() {
  class SimpleButton (line 36) | class SimpleButton extends React.Component {
    method constructor (line 37) | constructor(props, ctx) {
    method onClick (line 41) | onClick(e) {
    method render (line 45) | render() {

FILE: test/render-new.jsx
  class ChangeAtoB (line 6) | class ChangeAtoB extends React.Component {
    method componentWillReceiveProps (line 7) | componentWillReceiveProps(newProps) {
    method render (line 10) | render() {
  class Stateful (line 15) | class Stateful extends React.Component {
    method constructor (line 16) | constructor(props, ctx) {
    method onChange (line 21) | onChange(e) {
    method render (line 24) | render() {

FILE: test/stateful.jsx
  class Stateful (line 5) | class Stateful extends React.Component {
    method constructor (line 6) | constructor(props, ctx) {
    method onChange (line 11) | onChange(e) {
    method render (line 14) | render() {
  class SetStateBeforeMount (line 20) | class SetStateBeforeMount extends React.Component {
    method constructor (line 21) | constructor(props, ctx) {
    method componentWillMount (line 25) | componentWillMount() {
    method render (line 28) | render() {

FILE: test/with-context.jsx
  class Echo (line 6) | class Echo extends React.Component {
    method constructor (line 7) | constructor(props, ctx) {
    method render (line 10) | render() {
  class Child (line 18) | class Child extends React.Component {
    method render (line 19) | render() {
Condensed preview — 58 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (319K chars).
[
  {
    "path": ".gitignore",
    "chars": 30,
    "preview": "node_modules\ndist/test*\n*.tgz\n"
  },
  {
    "path": ".npmignore",
    "chars": 57,
    "preview": "dist/test*\nlib\nsrc\ntest\n*.tgz\ntypings\ngulpfile.js\n*.json\n"
  },
  {
    "path": "LICENSE",
    "chars": 1087,
    "preview": "The MIT License (MIT)\n\nCopyright (c) 2015 Patricio Zavolinsky\n\nPermission is hereby granted, free of charge, to any pers"
  },
  {
    "path": "README.md",
    "chars": 14838,
    "preview": "react-unit\n==========\n\nReact Unit is a lightweight unit test library for ReactJS with very few (js-only) dependencies.\n\n"
  },
  {
    "path": "dist/add-ons/debug.js",
    "chars": 761,
    "preview": "\"use strict\";\nObject.defineProperty(exports, \"__esModule\", { value: true });\nvar ramda_1 = require(\"ramda\");\nvar instanc"
  },
  {
    "path": "dist/add-ons/exclude.js",
    "chars": 716,
    "preview": "\"use strict\";\nObject.defineProperty(exports, \"__esModule\", { value: true });\nvar ramda_1 = require(\"ramda\");\nvar utils_1"
  },
  {
    "path": "dist/add-ons/index.js",
    "chars": 399,
    "preview": "\"use strict\";\nObject.defineProperty(exports, \"__esModule\", { value: true });\nvar exclude_1 = require(\"./exclude\");\nvar m"
  },
  {
    "path": "dist/add-ons/mock.js",
    "chars": 749,
    "preview": "\"use strict\";\nObject.defineProperty(exports, \"__esModule\", { value: true });\nvar ramda_1 = require(\"ramda\");\nvar types_1"
  },
  {
    "path": "dist/add-ons/with-context.js",
    "chars": 475,
    "preview": "\"use strict\";\nObject.defineProperty(exports, \"__esModule\", { value: true });\nvar ramda_1 = require(\"ramda\");\nvar withCon"
  },
  {
    "path": "dist/internal/test-render-instance.js",
    "chars": 865,
    "preview": "'use strict';\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }\n\nvar _r"
  },
  {
    "path": "dist/pipeline.js",
    "chars": 2225,
    "preview": "\"use strict\";\nObject.defineProperty(exports, \"__esModule\", { value: true });\nvar ramda_1 = require(\"ramda\");\nvar render_"
  },
  {
    "path": "dist/react-unit.js",
    "chars": 1320,
    "preview": "\"use strict\";\nvar R = require(\"ramda\");\nvar types_1 = require(\"./types\");\nvar resolver_1 = require(\"./resolver\");\nvar pi"
  },
  {
    "path": "dist/render-instance.js",
    "chars": 3255,
    "preview": "\"use strict\";\nObject.defineProperty(exports, \"__esModule\", { value: true });\nvar react_1 = require(\"react\");\nvar ramda_1"
  },
  {
    "path": "dist/resolver.js",
    "chars": 2346,
    "preview": "\"use strict\";\nObject.defineProperty(exports, \"__esModule\", { value: true });\nvar ramda_1 = require(\"ramda\");\nvar render_"
  },
  {
    "path": "dist/sizzle-bundle.js",
    "chars": 61656,
    "preview": "\nvar document = {\n\tcreateElement: function(tag) {\n\t\treturn {\n\t\t\tappendChild: function() {},\n\t\t\tgetElementsByTagName: fun"
  },
  {
    "path": "dist/types.js",
    "chars": 967,
    "preview": "\"use strict\";\n// The goal of react-unit is to process react `instances` and turn them into\n// `UnitComponents`. So, when"
  },
  {
    "path": "dist/unit-component.js",
    "chars": 5683,
    "preview": "\"use strict\";\nObject.defineProperty(exports, \"__esModule\", { value: true });\nvar R = require(\"ramda\");\nvar types_1 = req"
  },
  {
    "path": "dist/utils.js",
    "chars": 859,
    "preview": "\"use strict\";\nObject.defineProperty(exports, \"__esModule\", { value: true });\nvar ramda_1 = require(\"ramda\");\nvar test_ut"
  },
  {
    "path": "dist/wrapper.js",
    "chars": 1135,
    "preview": "\"use strict\";\nObject.defineProperty(exports, \"__esModule\", { value: true });\nvar types_1 = require(\"./types\");\nvar unit_"
  },
  {
    "path": "gulpfile.js",
    "chars": 1535,
    "preview": "\"use strict\"\n\nvar gulp        = require('gulp');\nvar babel       = require('gulp-babel');\nvar insert      = require('gul"
  },
  {
    "path": "lib/sizzle-bundle.js",
    "chars": 446,
    "preview": "\nvar document = {\n\tcreateElement: function(tag) {\n\t\treturn {\n\t\t\tappendChild: function() {},\n\t\t\tgetElementsByTagName: fun"
  },
  {
    "path": "lib/sizzle.js",
    "chars": 61212,
    "preview": "/*!\n * Sizzle CSS Selector Engine v2.2.1-pre\n * http://sizzlejs.com/\n *\n * Copyright jQuery Foundation and other contrib"
  },
  {
    "path": "package.json",
    "chars": 1206,
    "preview": "{\n  \"name\": \"react-unit\",\n  \"version\": \"3.0.3\",\n  \"description\": \"Lightweight unit test library for ReactJS.\",\n  \"main\":"
  },
  {
    "path": "src/add-ons/debug.ts",
    "chars": 776,
    "preview": "import { compose, merge } from 'ramda';\nimport\n  { AddOn\n  , InstanceMapper\n  , ComponentMapper\n  , ResolvedMapper\n  , R"
  },
  {
    "path": "src/add-ons/exclude.ts",
    "chars": 694,
    "preview": "import { compose, merge, any } from 'ramda';\nimport\n  { AddOn\n  , RenderedComponent\n  , RenderContext\n  , ComponentMappe"
  },
  {
    "path": "src/add-ons/index.ts",
    "chars": 307,
    "preview": "import { AddOn } from '../types';\nimport exclude from './exclude';\nimport mock from './mock';\nimport withContext from '."
  },
  {
    "path": "src/add-ons/mock.ts",
    "chars": 688,
    "preview": "import { compose, merge } from 'ramda';\nimport\n  { AddOn\n  , ComponentMapper\n  , RenderContext\n  , RenderedComponent\n  ,"
  },
  {
    "path": "src/add-ons/with-context.ts",
    "chars": 415,
    "preview": "import { compose, merge } from 'ramda';\nimport { AddOn, InstanceMapper, RenderContext } from '../types';\n\nconst withCont"
  },
  {
    "path": "src/defs.d.ts",
    "chars": 376,
    "preview": "declare module \"react-test-renderer/shallow\" {\n  class ReactShallowRenderer {\n    render(instance:any, ctx:any) : void;\n"
  },
  {
    "path": "src/pipeline.ts",
    "chars": 2205,
    "preview": "import { compose } from 'ramda';\nimport\n  { RenderContext\n  , Resolver\n  , HtmlComponent\n  , ReactInstance\n  } from './t"
  },
  {
    "path": "src/react-unit.ts",
    "chars": 1727,
    "preview": "import * as R from 'ramda';\nimport { UnitComponent } from './unit-component';\nimport\n  { ReactInstance\n  , RenderContext"
  },
  {
    "path": "src/render-instance.ts",
    "chars": 3349,
    "preview": "import { Children } from 'react';\nimport { mergeAll } from 'ramda';\nimport ReactShallowRenderer = require('react-test-re"
  },
  {
    "path": "src/resolver.ts",
    "chars": 2135,
    "preview": "import { merge } from 'ramda';\nimport { toArtificialHtml } from './render-instance';\nimport\n  { ComponentMapper\n  , Inst"
  },
  {
    "path": "src/sizzle-bundle.d.ts",
    "chars": 68,
    "preview": "declare function lookup(s:string, comp:any):any[];\nexport = lookup;\n"
  },
  {
    "path": "src/sizzle-bundle.js",
    "chars": 61656,
    "preview": "\nvar document = {\n\tcreateElement: function(tag) {\n\t\treturn {\n\t\t\tappendChild: function() {},\n\t\t\tgetElementsByTagName: fun"
  },
  {
    "path": "src/types.ts",
    "chars": 4502,
    "preview": "// The goal of react-unit is to process react `instances` and turn them into\n// `UnitComponents`. So, when all is said a"
  },
  {
    "path": "src/unit-component.ts",
    "chars": 4656,
    "preview": "import * as R from 'ramda';\nimport { ReactInstance, HtmlComponent, isArtificialHtml } from './types';\nimport { isText, i"
  },
  {
    "path": "src/utils.ts",
    "chars": 800,
    "preview": "import { contains, merge } from 'ramda';\nimport { isElementOfType } from 'react-dom/test-utils';\nimport\n  { RenderedComp"
  },
  {
    "path": "src/wrapper.ts",
    "chars": 1186,
    "preview": "import\n  { HtmlComponent\n  , isHtml\n  , isUnknown\n  } from './types';\nimport\n  { UnitComponent\n  , OptionalUnitComponent"
  },
  {
    "path": "test/create-component-interleaved.jsx",
    "chars": 2608,
    "preview": "// Note: you should use const createComponent = require('react-unit');\nconst createComponent = require('./react-unit');\n"
  },
  {
    "path": "test/create-component-shallow.jsx",
    "chars": 3526,
    "preview": "const createComponent = require('./react-unit');\nconst React = require('react');\nconst R = require('ramda');\n\nconst Chil"
  },
  {
    "path": "test/create-component.jsx",
    "chars": 1684,
    "preview": "// Note: you should use const createComponent = require('react-unit');\nconst createComponent = require('./react-unit');\n"
  },
  {
    "path": "test/events.jsx",
    "chars": 3142,
    "preview": "// Note: you should use const createComponent = require('react-unit');\nconst createComponent = require('./react-unit');\n"
  },
  {
    "path": "test/exclude.jsx",
    "chars": 3067,
    "preview": "// Note: you should use const createComponent = require('react-unit');\nconst createComponent = require('./react-unit');\n"
  },
  {
    "path": "test/find-by-component.jsx",
    "chars": 1331,
    "preview": "// Note: you should use const createComponent = require('react-unit');\nconst createComponent = require('./react-unit');\n"
  },
  {
    "path": "test/find-by-query.jsx",
    "chars": 3806,
    "preview": "// Note: you should use const createComponent = require('react-unit');\nconst createComponent = require('./react-unit');\n"
  },
  {
    "path": "test/find-by-ref.jsx",
    "chars": 993,
    "preview": "// Note: you should use const createComponent = require('react-unit');\nconst createComponent = require('./react-unit');\n"
  },
  {
    "path": "test/find-by.jsx",
    "chars": 1335,
    "preview": "// Note: you should use const createComponent = require('react-unit');\nconst createComponent = require('./react-unit');\n"
  },
  {
    "path": "test/internal/render-instance.jsx",
    "chars": 529,
    "preview": "const React = require('react');\nimport renderInstance from '../render-instance';\nimport { isHtml, isUnknown } from '../t"
  },
  {
    "path": "test/mock.jsx",
    "chars": 2674,
    "preview": "// Note: you should use const createComponent = require('react-unit');\nconst createComponent = require('./react-unit');\n"
  },
  {
    "path": "test/render-new.jsx",
    "chars": 2794,
    "preview": "// Note: you should use const createComponent = require('react-unit');\nconst createComponent = require('./react-unit');\n"
  },
  {
    "path": "test/stateful.jsx",
    "chars": 2955,
    "preview": "// Note: you should use const createComponent = require('react-unit');\nconst createComponent = require('./react-unit');\n"
  },
  {
    "path": "test/stateless.jsx",
    "chars": 1851,
    "preview": "// Note: you should use const createComponent = require('react-unit');\nconst createComponent = require('./react-unit');\n"
  },
  {
    "path": "test/text.jsx",
    "chars": 1525,
    "preview": "// Note: you should use const createComponent = require('react-unit');\nconst createComponent = require('./react-unit');\n"
  },
  {
    "path": "test/with-context.jsx",
    "chars": 2043,
    "preview": "// Note: you should use: import createComponent from 'react-unit';\nimport createComponent from './react-unit';\nconst Rea"
  },
  {
    "path": "tsconfig.json",
    "chars": 707,
    "preview": "{\n  \"compilerOptions\": {\n    \"target\": \"ES5\",\n    \"module\": \"commonjs\",\n    \"outDir\": \"./dist\",\n    \"sourceMap\": false,\n"
  },
  {
    "path": "tslint.json",
    "chars": 1362,
    "preview": "{\n  \"extends\": \"tslint:recommended\",\n  \"rules\": {\n    \"curly\": false,\n    \"interface-name\": [true, \"never-prefix\"],\n    "
  },
  {
    "path": "typings.json",
    "chars": 263,
    "preview": "{\n  \"dependencies\": {\n    \"ramda\": \"registry:npm/ramda#0.21.0+20160531162943\",\n    \"react\": \"registry:npm/react#15.0.1+2"
  }
]

About this extraction

This page contains the full source code of the pzavolinsky/react-unit GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 58 files (280.8 KB), approximately 78.5k tokens, and a symbol index with 163 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!