text: /**
   * @module Selector
   */
  
  'use strict';
  
  exports.__esModule = true;
  
  var _util = require('../util');
  
  var isPrototypeSet = false;
  
  var reFragment = /^\s*<(\w+|!)[^>]*>/;
  var reSingleTag = /^<(\w+)\s*\/?>(?:<\/\1>|)$/;
  var reSimpleSelector = /^[\.#]?[\w-]*$/;
  
  /*
   * Versatile wrapper for `querySelectorAll`.
   *
   * @param {String|Node|NodeList|Array} selector Query selector, `Node`, `NodeList`, array of elements, or HTML fragment string.
   * @param {String|Node|NodeList} context=document The context for the selector to query elements.
   * @return {Object} The wrapped collection
   * @chainable
   * @example
   *     var $items = $(.items');
   * @example
   *     var $element = $(domElement);
   * @example
   *     var $list = $(nodeList, document.body);
   * @example
   *     var $element = $('<p>evergreen</p>');
   */
  
  function $(selector) {
      var context = arguments.length <= 1 || arguments[1] === undefined ? document : arguments[1];
  
      var collection = undefined;
  
      if (!selector) {
  
          collection = document.querySelectorAll(null);
      } else if (selector instanceof Wrapper) {
  
          return selector;
      } else if (typeof selector !== 'string') {
  
          collection = selector.nodeType || selector === window ? [selector] : selector;
      } else if (reFragment.test(selector)) {
  
          collection = createFragment(selector);
      } else {
  
          context = typeof context === 'string' ? document.querySelector(context) : context.length ? context[0] : context;
  
          collection = querySelector(selector, context);
      }
  
      return wrap(collection);
  }
  
  /*
   * Find descendants matching the provided `selector` for each element in the collection.
   *
   * @param {String|Node|NodeList|Array} selector Query selector, `Node`, `NodeList`, array of elements, or HTML fragment string.
   * @return {Object} The wrapped collection
   * @example
   *     $('.selector').find('.deep').$('.deepest');
   */
  
  function find(selector) {
      var nodes = [];
      _util.each(this, function (node) {
          _util.each(querySelector(selector, node), function (child) {
              if (nodes.indexOf(child) === -1) {
                  nodes.push(child);
              }
          });
      });
      return $(nodes);
  }
  
  /*
   * Returns `true` if the element would be selected by the specified selector string; otherwise, returns `false`.
   *
   * @param {Node} element Element to test
   * @param {String} selector Selector to match against element
   * @return {Boolean}
   *
   * @example
   *     $.matches(element, '.match');
   */
  
  var matches = (function () {
      var context = typeof Element !== 'undefined' ? Element.prototype : _util.global,
          _matches = context.matches || context.matchesSelector || context.mozMatchesSelector || context.msMatchesSelector || context.oMatchesSelector || context.webkitMatchesSelector;
      return function (element, selector) {
          return _matches.call(element, selector);
      };
  })();
  
  /*
   * Use the faster `getElementById`, `getElementsByClassName` or `getElementsByTagName` over `querySelectorAll` if possible.
   *
   * @private
   * @param {String} selector Query selector.
   * @param {Node} context The context for the selector to query elements.
   * @return {Object} NodeList, HTMLCollection, or Array of matching elements (depending on method used).
   */
  
  function querySelector(selector, context) {
  
      var isSimpleSelector = reSimpleSelector.test(selector);
  
      if (isSimpleSelector) {
          if (selector[0] === '#') {
              var element = (context.getElementById ? context : document).getElementById(selector.slice(1));
              return element ? [element] : [];
          }
          if (selector[0] === '.') {
              return context.getElementsByClassName(selector.slice(1));
          }
          return context.getElementsByTagName(selector);
      }
  
      return context.querySelectorAll(selector);
  }
  
  /*
   * Create DOM fragment from an HTML string
   *
   * @private
   * @param {String} html String representing HTML.
   * @return {NodeList}
   */
  
  function createFragment(html) {
  
      if (reSingleTag.test(html)) {
          return [document.createElement(RegExp.$1)];
      }
  
      var elements = [],
          container = document.createElement('div'),
          children = container.childNodes;
  
      container.innerHTML = html;
  
      for (var i = 0, l = children.length; i < l; i++) {
          elements.push(children[i]);
      }
  
      return elements;
  }
  
  /*
   * Calling `$(selector)` returns a wrapped collection of elements.
   *
   * @private
   * @param {NodeList|Array} collection Element(s) to wrap.
   * @return (Object) The wrapped collection
   */
  
  function wrap(collection) {
  
      if (!isPrototypeSet) {
          Wrapper.prototype = $.fn;
          Wrapper.prototype.constructor = Wrapper;
          isPrototypeSet = true;
      }
  
      return new Wrapper(collection);
  }
  
  /*
   * Constructor for the Object.prototype strategy
   *
   * @constructor
   * @private
   * @param {NodeList|Array} collection Element(s) to wrap.
   */
  
  function Wrapper(collection) {
      var i = 0,
          length = collection.length;
      for (; i < length;) {
          this[i] = collection[i++];
      }
      this.length = length;
  }
  
  /*
   * Export interface
   */
  
  exports.$ = $;
  exports.find = find;
  exports.matches = matches;
  exports.Wrapper = Wrapper;