diff options
| author | Joel Kronqvist <joel.h.kronqvist@gmail.com> | 2022-03-05 19:02:27 +0200 | 
|---|---|---|
| committer | Joel Kronqvist <joel.h.kronqvist@gmail.com> | 2022-03-05 19:02:27 +0200 | 
| commit | 5d309ff52cd399a6b71968a6b9a70c8ac0b98981 (patch) | |
| tree | 360f7eb50f956e2367ef38fa1fc6ac7ac5258042 /node_modules/nwsapi | |
| parent | b500a50f1b97d93c98b36ed9a980f8188d648147 (diff) | |
| download | LYLLRuoka-5d309ff52cd399a6b71968a6b9a70c8ac0b98981.tar.gz LYLLRuoka-5d309ff52cd399a6b71968a6b9a70c8ac0b98981.zip  | |
Added node_modules for the updating to work properly.
Diffstat (limited to 'node_modules/nwsapi')
| -rw-r--r-- | node_modules/nwsapi/LICENSE | 22 | ||||
| -rw-r--r-- | node_modules/nwsapi/README.md | 132 | ||||
| -rw-r--r-- | node_modules/nwsapi/dist/lint.log | 0 | ||||
| -rw-r--r-- | node_modules/nwsapi/package.json | 38 | ||||
| -rw-r--r-- | node_modules/nwsapi/src/modules/nwsapi-jquery.js | 135 | ||||
| -rw-r--r-- | node_modules/nwsapi/src/modules/nwsapi-traversal.js | 90 | ||||
| -rw-r--r-- | node_modules/nwsapi/src/nwsapi.js | 1800 | 
7 files changed, 2217 insertions, 0 deletions
diff --git a/node_modules/nwsapi/LICENSE b/node_modules/nwsapi/LICENSE new file mode 100644 index 0000000..cc3621a --- /dev/null +++ b/node_modules/nwsapi/LICENSE @@ -0,0 +1,22 @@ +Copyright (c) 2007-2019 Diego Perini (http://www.iport.it/) + +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. diff --git a/node_modules/nwsapi/README.md b/node_modules/nwsapi/README.md new file mode 100644 index 0000000..f74b87d --- /dev/null +++ b/node_modules/nwsapi/README.md @@ -0,0 +1,132 @@ +# [NWSAPI](http://dperini.github.io/nwsapi/) + +Fast CSS Selectors API Engine + +    + +NWSAPI is the development progress of [NWMATCHER](https://github.com/dperini/nwmatcher) aiming at [Selectors Level 4](https://www.w3.org/TR/selectors-4/) conformance. It has been completely reworked to be easily extended and maintained. It is a right-to-left selector parser and compiler written in pure Javascript with no external dependencies. It was initially thought as a cross browser library to improve event delegation and web page scraping in various frameworks but it has become a popular replacement of the native CSS selection and matching functionality in newer browsers and headless environments. + +It uses [regular expressions](https://en.wikipedia.org/wiki/Regular_expression) to parse CSS selector strings and [metaprogramming](https://en.wikipedia.org/wiki/Metaprogramming) to transforms these selector strings into Javascript function resolvers. This process is executed only once for each selector string allowing memoization of the function resolvers and achieving unmatched performances. + +## Installation + +To include NWSAPI in a standard web page: + +```html +<script type="text/javascript" src="nwsapi.js"></script> +``` + +To include NWSAPI in a standard web page and automatically replace the native QSA: + +```html +<script type="text/javascript" src="nwsapi.js" onload="NW.Dom.install()"></script> +``` + +To use NWSAPI with Node.js: + +``` +$ npm install nwsapi +``` + +NWSAPI currently supports browsers (as a global, `NW.Dom`) and headless environments (as a CommonJS module). + + +## Supported Selectors + +Here is a list of all the CSS2/CSS3/CSS4 [Supported selectors](https://github.com/dperini/nwsapi/wiki/CSS-supported-selectors). + + +## Features and Compliance + +You can read more about NWSAPI [features and compliance](https://github.com/dperini/nwsapi/wiki/Features-and-compliance) on the wiki. + + +## API + +### DOM Selection + +#### `ancestor( selector, context, callback )` + +Returns a reference to the nearest ancestor element matching `selector`, starting at `context`. Returns `null` if no element is found. If `callback` is provided, it is invoked for the matched element. + +#### `first( selector, context, callback )` + +Returns a reference to the first element matching `selector`, starting at `context`. Returns `null` if no element matches. If `callback` is provided, it is invoked for the matched element. + +#### `match( selector, element, callback )` + +Returns `true` if `element` matches `selector`, starting at `context`; returns `false` otherwise. If `callback` is provided, it is invoked for the matched element. + +#### `select( selector, context, callback )` + +Returns an array of all the elements matching `selector`, starting at `context`; returns empty `Array` otherwise. If `callback` is provided, it is invoked for each matching element. + + +### DOM Helpers + +#### `byId( id, from )` + +Returns a reference to the first element with ID `id`, optionally filtered to descendants of the element `from`. + +#### `byTag( tag, from )` + +Returns an array of elements having the specified tag name `tag`, optionally filtered to descendants of the element `from`. + +#### `byClass( class, from )` + +Returns an array of elements having the specified class name `class`, optionally filtered to descendants of the element `from`. + + +### Engine Configuration + +#### `configure( options )` + +The following is the list of currently available configuration options, their default values and descriptions, they are boolean flags that can be set to `true` or `false`: + +* `IDS_DUPES`: true  - true to allow using multiple elements having the same id, false to disallow +* `LIVECACHE`: true  - true for caching both results and resolvers, false for caching only resolvers +* `MIXEDCASE`: true  - true to match tag names case insensitive, false to match using case sensitive +* `LOGERRORS`: true  - true to print errors and warnings to the console, false to mute both of them + + +### Examples on extending the basic functionalities + +#### `configure( { <configuration-flag>: [ true | false ] } )` + +Disable logging errors/warnings to console, disallow duplicate ids. Example: + +```js +NW.Dom.configure( { LOGERRORS: false, IDS_DUPES: false } ); +``` +NOTE: NW.Dom.configure() without parameters return the current configuration. + +#### `registerCombinator( symbol, resolver )` + +Registers a new symbol and its matching resolver in the combinators table. Example: + +```js +NW.Dom.registerCombinator( '^', 'e.parentElement' ); +``` + +#### `registerOperator( symbol, resolver )` + +Registers a new symbol and its matching resolver in the attribute operators table. Example: + +```js +NW.Dom.registerOperator( '!=', { p1: '^', p2: '$', p3: 'false' } ); +``` + +#### `registerSelector( name, rexp, func )` + +Registers a new selector, the matching RE and the resolver function, in the selectors table. Example: + +```js +NW.Dom.registerSelector('Controls', /^\:(control)(.*)/i, +  (function(global) { +    return function(match, source, mode, callback) { +      var status = true; +      source = 'if(/^(button|input|select|textarea)/i.test(e.nodeName)){' + source + '}'; +      return { 'source': source, 'status': status }; +    }; +  })(this)); +``` diff --git a/node_modules/nwsapi/dist/lint.log b/node_modules/nwsapi/dist/lint.log new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/node_modules/nwsapi/dist/lint.log diff --git a/node_modules/nwsapi/package.json b/node_modules/nwsapi/package.json new file mode 100644 index 0000000..33e4fca --- /dev/null +++ b/node_modules/nwsapi/package.json @@ -0,0 +1,38 @@ +{ +  "name": "nwsapi", +  "version": "2.2.0", +  "description": "Fast CSS Selectors API Engine", +  "homepage": "http://javascript.nwbox.com/nwsapi/", +  "main": "./src/nwsapi", +  "keywords": [ +    "css", +    "css3", +    "css4", +    "matcher", +    "selector" +  ], +  "licenses": [ +    { +      "type": "MIT", +      "url": "http://javascript.nwbox.com/nwsapi/MIT-LICENSE" +    } +  ], +  "license": "MIT", +  "author": "Diego Perini <diego.perini@gmail.com> (http://www.iport.it/)", +  "maintainers": [ +    "Diego Perini <diego.perini@gmail.com> (http://www.iport.it/)" +  ], +  "bugs": { +    "url": "http://github.com/dperini/nwsapi/issues" +  }, +  "repository": { +    "type": "git", +    "url": "git://github.com/dperini/nwsapi.git" +  }, +  "scripts": { +    "lint": "eslint ./src/nwsapi.js" +  }, +  "directories": { +    "test": "test" +  } +} diff --git a/node_modules/nwsapi/src/modules/nwsapi-jquery.js b/node_modules/nwsapi/src/modules/nwsapi-jquery.js new file mode 100644 index 0000000..961cb30 --- /dev/null +++ b/node_modules/nwsapi/src/modules/nwsapi-jquery.js @@ -0,0 +1,135 @@ +/* + * Copyright (C) 2007-2017 Diego Perini + * All rights reserved. + * + * this is just a small example to show + * how an extension for NWMatcher could be + * adapted to handle special jQuery selectors + * + * Child Selectors + * :even, :odd, :eq, :lt, :gt, :first, :last, :nth + * + * Pseudo Selectors + * :has, :button, :header, :input, :checkbox, :radio, :file, :image + * :password, :reset, :submit, :text, :hidden, :visible, :parent + * + */ + +// for structural pseudo-classes extensions +NW.Dom.registerSelector( +  'jquery:child', +  /^\:((?:(nth|eq|lt|gt)\(([^()]*)\))|(?:even|odd|first|last))(.*)/i, +  (function(global) { + +    return function(match, source, mode, callback) { + +      var status = true, +      macro = mode ? NW.Dom.S_BODY : NW.Dom.M_BODY; + +      macro = macro.replace('@', typeof callback == 'function' ? (mode ? NW.Dom.S_TEST : NW.Dom.M_TEST) : ''); + +      switch (match[1].toLowerCase()) { +        case 'odd': +          source = source.replace(macro, 'if((n=n^1)==0){' + macro + '}'); +          break; +        case 'even': +          source = source.replace(macro, 'if((n=n^1)==1){' + macro + '}'); +          break; +        case 'first': +          source = 'n=s.root.getElementsByTagName(e.nodeName);if(n.length&&n[0]===e){' + source + '}'; +          break; +        case 'last': +          source = 'n=s.root.getElementsByTagName(e.nodeName);if(n.length&&n[n.length-1]===e){' + source + '}'; +          break; +        default: +          switch (match[2].toLowerCase()) { +            case 'nth': +              source = 'n=s.root.getElementsByTagName(e.nodeName);if(n.length&&n[' + match[3] + ']===e){' + source + '}'; +              break; +            case 'eq': +              source = source.replace(macro, 'if(x++==' + match[3] + '){' + macro + '}'); +              break; +            case 'lt': +              source = source.replace(macro, 'if(x++<' + match[3] + '){' + macro + '}'); +              break; +            case 'gt': +              source = source.replace(macro, 'if(x++>' + match[3] + '){' + macro + '}'); +              break; +            default: +              status = false; +              break; +          } +          break; +      } + +      // compiler will add this to "source" +      return { +        'source': source, +        'status': status, +        'modvar': 'x=0' +      }; + +    }; + +  })(this)); + +// for element pseudo-classes extensions +NW.Dom.registerSelector( +  'jquery:pseudo', +  /^\:(has|checkbox|file|image|password|radio|reset|submit|text|button|input|header|hidden|visible|parent)(?:\(\s*(["']*)?([^'"()]*)\2\s*\))?(.*)/i, +  (function(global) { + +    return function(match, source, mode, callback) { + +      var status = true, +      macro = mode ? NW.Dom.S_BODY : NW.Dom.M_BODY; + +      macro = macro.replace('@', typeof callback == 'function' ? (mode ? NW.Dom.S_TEST : NW.Dom.M_TEST) : ''); + +      switch(match[1].toLowerCase()) { +        case 'has': +          source = source.replace(macro, 'if(e.getElementsByTagName("' + match[3].replace(/^\s|\s$/g, '') + '")[0]){' + macro + '}'); +          break; +        case 'checkbox': +        case 'file': +        case 'image': +        case 'password': +        case 'radio': +        case 'reset': +        case 'submit': +        case 'text': +          // :checkbox, :file, :image, :password, :radio, :reset, :submit, :text +          source = 'if(/^' + match[1] + '$/i.test(e.type)){' + source + '}'; +          break; +        case 'button': +          source = 'if(/^button$/i.test(e.nodeName)){' + source + '}'; +          break; +        case 'input': +          source = 'if(/^(?:button|input|select|textarea)$/i.test(e.nodeName)){' + source + '}'; +          break; +        case 'header': +          source = 'if(/^h[1-6]$/i.test(e.nodeName)){' + source + '}'; +          break; +        case 'hidden': +          source = 'if(!e.offsetWidth&&!e.offsetHeight){' + source + '}'; +          break; +        case 'visible': +          source = 'if(e.offsetWidth||e.offsetHeight){' + source + '}'; +          break; +        case 'parent': +          source = 'if(e.firstChild){' + source + '}'; +          break; +        default: +          status = false; +          break; +      } + +      // compiler will add this to "source" +      return { +        'source': source, +        'status': status +      }; + +    }; + +  })(this)); diff --git a/node_modules/nwsapi/src/modules/nwsapi-traversal.js b/node_modules/nwsapi/src/modules/nwsapi-traversal.js new file mode 100644 index 0000000..9d2b62f --- /dev/null +++ b/node_modules/nwsapi/src/modules/nwsapi-traversal.js @@ -0,0 +1,90 @@ +/* + * Element Traversal methods from Juriy Zaytsev (kangax) + * used to emulate Prototype up/down/previous/next methods + */ + +(function(D){ + +  // TODO: all of this needs tests +  var match = D.match, select = D.select, root = document.documentElement, + +  // Use the Element Traversal API if available. +  nextElement = 'nextElementSibling', +  previousElement = 'previousElementSibling', +  parentElement = 'parentElement'; + +  // Fall back to the DOM Level 1 API. +  if (!(nextElement in root)) nextElement = 'nextSibling'; +  if (!(previousElement in root)) previousElement = 'previousSibling'; +  if (!(parentElement in root)) parentElement = 'parentNode'; + +  function walkElements(property, element, expr) { +    var i = 0, isIndex = typeof expr == 'number'; +    if (typeof expr == 'undefined') { +      isIndex = true; +      expr = 0; +    } +    while ((element = element[property])) { +      if (element.nodeType != 1) continue; +      if (isIndex) { +        ++i; +        if (i == expr) return element; +      } else if (match(element, expr)) { +        return element; +      } +    } +    return null; +  } + +  /** +   * @method up +   * @param {HTMLElement} element element to walk from +   * @param {String | Number} expr CSS expression or an index +   * @return {HTMLElement | null} +   */ +  function up(element, expr) { +    return walkElements(parentElement, element, expr); +  } +  /** +   * @method next +   * @param {HTMLElement} element element to walk from +   * @param {String | Number} expr CSS expression or an index +   * @return {HTMLElement | null} +   */ +  function next(element, expr) { +    return walkElements(nextElement, element, expr); +  } +  /** +   * @method previous +   * @param {HTMLElement} element element to walk from +   * @param {String | Number} expr CSS expression or an index +   * @return {HTMLElement | null} +   */ +  function previous(element, expr) { +    return walkElements(previousElement, element, expr); +  } +  /** +   * @method down +   * @param {HTMLElement} element element to walk from +   * @param {String | Number} expr CSS expression or an index +   * @return {HTMLElement | null} +   */ +  function down(element, expr) { +    var isIndex = typeof expr == 'number', descendants, index, descendant; +    if (expr === null) { +      element = element.firstChild; +      while (element && element.nodeType != 1) element = element[nextElement]; +      return element; +    } +    if (!isIndex && match(element, expr) || isIndex && expr === 0) return element; +    descendants = select('*', element); +    if (isIndex) return descendants[expr] || null; +    index = 0; +    while ((descendant = descendants[index]) && !match(descendant, expr)) { ++index; } +    return descendant || null; +  } +  D.up = up; +  D.down = down; +  D.next = next; +  D.previous = previous; +})(NW.Dom); diff --git a/node_modules/nwsapi/src/nwsapi.js b/node_modules/nwsapi/src/nwsapi.js new file mode 100644 index 0000000..79e0eb7 --- /dev/null +++ b/node_modules/nwsapi/src/nwsapi.js @@ -0,0 +1,1800 @@ +/* + * Copyright (C) 2007-2019 Diego Perini + * All rights reserved. + * + * nwsapi.js - Fast CSS Selectors API Engine + * + * Author: Diego Perini <diego.perini at gmail com> + * Version: 2.2.0 + * Created: 20070722 + * Release: 20191102 + * + * License: + *  http://javascript.nwbox.com/nwsapi/MIT-LICENSE + * Download: + *  http://javascript.nwbox.com/nwsapi/nwsapi.js + */ + +(function Export(global, factory) { + +  'use strict'; + +  if (typeof module == 'object' && typeof exports == 'object') { +    module.exports = factory; +  } else if (typeof define == 'function' && define['amd']) { +    define(factory); +  } else { +    global.NW || (global.NW = { }); +    global.NW.Dom = factory(global, Export); +  } + +})(this, function Factory(global, Export) { + +  var version = 'nwsapi-2.2.0', + +  doc = global.document, +  root = doc.documentElement, +  slice = Array.prototype.slice, + +  WSP = '[\\x20\\t\\r\\n\\f]', + +  CFG = { +    // extensions +    operators: '[~*^$|]=|=', +    combinators: '[\\x20\\t>+~](?=[^>+~])' +  }, + +  NOT = { +    // not enclosed in double/single/parens/square +    double_enc: '(?=(?:[^"]*["][^"]*["])*[^"]*$)', +    single_enc: "(?=(?:[^']*['][^']*['])*[^']*$)", +    parens_enc: '(?![^\\x28]*\\x29)', +    square_enc: '(?![^\\x5b]*\\x5d)' +  }, + +  REX = { +    // regular expressions +    HasEscapes: RegExp('\\\\'), +    HexNumbers: RegExp('^[0-9a-fA-F]'), +    EscOrQuote: RegExp('^\\\\|[\\x22\\x27]'), +    RegExpChar: RegExp('(?:(?!\\\\)[\\\\^$.*+?()[\\]{}|\\/])', 'g'), +    TrimSpaces: RegExp('[\\r\\n\\f]|^' + WSP + '+|' + WSP + '+$', 'g'), +    CommaGroup: RegExp('(\\s*,\\s*)' + NOT.square_enc + NOT.parens_enc, 'g'), +    SplitGroup: RegExp('((?:\\x28[^\\x29]*\\x29|\\[[^\\]]*\\]|\\\\.|[^,])+)', 'g'), +    FixEscapes: RegExp('\\\\([0-9a-fA-F]{1,6}' + WSP + '?|.)|([\\x22\\x27])', 'g'), +    CombineWSP: RegExp('[\\n\\r\\f\\x20]+' + NOT.single_enc + NOT.double_enc, 'g'), +    TabCharWSP: RegExp('(\\x20?\\t+\\x20?)' + NOT.single_enc + NOT.double_enc, 'g'), +    PseudosWSP: RegExp('\\s+([-+])\\s+' + NOT.square_enc, 'g') +  }, + +  STD = { +    combinator: RegExp('\\s?([>+~])\\s?', 'g'), +    apimethods: RegExp('^(?:[a-z]+|\\*)\\|', 'i'), +    namespaces: RegExp('(\\*|[a-z]+)\\|[-a-z]+', 'i') +  }, + +  GROUPS = { +    // pseudo-classes requiring parameters +    linguistic: '(dir|lang)\\x28\\s?([-\\w]{2,})\\s?(?:\\x29|$)', +    logicalsel: '(matches|not)\\x28\\s?([^()]*|[^\\x28]*\\x28[^\\x29]*\\x29)\\s?(?:\\x29|$)', +    treestruct: '(nth(?:-last)?(?:-child|-of-type))(?:\\x28\\s?(even|odd|(?:[-+]?\\d*)(?:n\\s?[-+]?\\s?\\d*)?)\\s?(?:\\x29|$))', +    // pseudo-classes not requiring parameters +    locationpc: '(link|visited|target)\\b', +    useraction: '(hover|active|focus|focus-within)\\b', +    structural: '(root|empty|(?:(?:first|last|only)(?:-child|-of-type)))\\b', +    inputstate: '(enabled|disabled|read-only|read-write|placeholder-shown|default)\\b', +    inputvalue: '(checked|indeterminate|required|optional|valid|invalid|in-range|out-of-range)\\b', +    // pseudo-elements starting with single colon (:) +    pseudo_sng: '(after|before|first-letter|first-line)\\b', +    // pseudo-elements starting with double colon (::) +    pseudo_dbl: ':(after|before|first-letter|first-line|selection|placeholder|-webkit-[-a-zA-Z0-9]{2,})\\b' +  }, + +  Patterns = { +    // pseudo-classes +    treestruct: RegExp('^:(?:' + GROUPS.treestruct + ')(.*)', 'i'), +    structural: RegExp('^:(?:' + GROUPS.structural + ')(.*)', 'i'), +    linguistic: RegExp('^:(?:' + GROUPS.linguistic + ')(.*)', 'i'), +    useraction: RegExp('^:(?:' + GROUPS.useraction + ')(.*)', 'i'), +    inputstate: RegExp('^:(?:' + GROUPS.inputstate + ')(.*)', 'i'), +    inputvalue: RegExp('^:(?:' + GROUPS.inputvalue + ')(.*)', 'i'), +    locationpc: RegExp('^:(?:' + GROUPS.locationpc + ')(.*)', 'i'), +    logicalsel: RegExp('^:(?:' + GROUPS.logicalsel + ')(.*)', 'i'), +    pseudo_dbl: RegExp('^:(?:' + GROUPS.pseudo_dbl + ')(.*)', 'i'), +    pseudo_sng: RegExp('^:(?:' + GROUPS.pseudo_sng + ')(.*)', 'i'), +    // combinator symbols +    children: RegExp('^' + WSP + '?\\>' + WSP + '?(.*)'), +    adjacent: RegExp('^' + WSP + '?\\+' + WSP + '?(.*)'), +    relative: RegExp('^' + WSP + '?\\~' + WSP + '?(.*)'), +    ancestor: RegExp('^' + WSP + '+(.*)'), +   // universal & namespace +   universal: RegExp('^\\*(.*)'), +   namespace: RegExp('^(\\w+|\\*)?\\|(.*)') +  }, + +  // regexp to aproximate detection of RTL languages (Arabic) +  RTL = RegExp('^[\\u0591-\\u08ff\\ufb1d-\\ufdfd\\ufe70-\\ufefc ]+$'), + +  // emulate firefox error strings +  qsNotArgs = 'Not enough arguments', +  qsInvalid = ' is not a valid selector', + +  // detect structural pseudo-classes in selectors +  reNthElem = RegExp('(:nth(?:-last)?-child)', 'i'), +  reNthType = RegExp('(:nth(?:-last)?-of-type)', 'i'), + +  // placeholder for global regexp +  reOptimizer, +  reValidator, + +  // special handling configuration flags +  Config = { +    IDS_DUPES: true, +    MIXEDCASE: true, +    LOGERRORS: true, +    VERBOSITY: true +  }, + +  NAMESPACE, +  QUIRKS_MODE, +  HTML_DOCUMENT, + +  ATTR_STD_OPS = { +    '=': 1, '^=': 1, '$=': 1, '|=': 1, '*=': 1, '~=': 1 +  }, + +  HTML_TABLE = { +    'accept': 1, 'accept-charset': 1, 'align': 1, 'alink': 1, 'axis': 1, +    'bgcolor': 1, 'charset': 1, 'checked': 1, 'clear': 1, 'codetype': 1, 'color': 1, +    'compact': 1, 'declare': 1, 'defer': 1, 'dir': 1, 'direction': 1, 'disabled': 1, +    'enctype': 1, 'face': 1, 'frame': 1, 'hreflang': 1, 'http-equiv': 1, 'lang': 1, +    'language': 1, 'link': 1, 'media': 1, 'method': 1, 'multiple': 1, 'nohref': 1, +    'noresize': 1, 'noshade': 1, 'nowrap': 1, 'readonly': 1, 'rel': 1, 'rev': 1, +    'rules': 1, 'scope': 1, 'scrolling': 1, 'selected': 1, 'shape': 1, 'target': 1, +    'text': 1, 'type': 1, 'valign': 1, 'valuetype': 1, 'vlink': 1 +  }, + +  Combinators = { }, + +  Selectors = { }, + +  Operators = { +     '=': { p1: '^', +            p2: '$', +            p3: 'true' }, +    '^=': { p1: '^', +            p2: '', +            p3: 'true' }, +    '$=': { p1: '', +            p2: '$', +            p3: 'true' }, +    '*=': { p1: '', +            p2: '', +            p3: 'true' }, +    '|=': { p1: '^', +            p2: '(-|$)', +            p3: 'true' }, +    '~=': { p1: '(^|\\s)', +            p2: '(\\s|$)', +            p3: 'true' } +  }, + +  concatCall = +    function(nodes, callback) { +      var i = 0, l = nodes.length, list = Array(l); +      while (l > i) { +        if (false === callback(list[i] = nodes[i])) break; +        ++i; +      } +      return list; +    }, + +  concatList = +    function(list, nodes) { +      var i = -1, l = nodes.length; +      while (l--) { list[list.length] = nodes[++i]; } +      return list; +    }, + +  documentOrder = +    function(a, b) { +      if (!hasDupes && a === b) { +        hasDupes = true; +        return 0; +      } +      return a.compareDocumentPosition(b) & 4 ? -1 : 1; +    }, + +  hasDupes = false, + +  unique = +    function(nodes) { +      var i = 0, j = -1, l = nodes.length + 1, list = [ ]; +      while (--l) { +        if (nodes[i++] === nodes[i]) continue; +        list[++j] = nodes[i - 1]; +      } +      hasDupes = false; +      return list; +    }, + +  // check context for mixed content +  hasMixedCaseTagNames = +    function(context) { +      var ns, api = 'getElementsByTagNameNS'; + +      // current host context (ownerDocument) +      context = context.ownerDocument || context; + +      // documentElement (root) element namespace or default html/xhtml namespace +      ns = context.documentElement.namespaceURI || 'http://www.w3.org/1999/xhtml'; + +      // checking the number of non HTML nodes in the document +      return (context[api]('*', '*').length - context[api](ns, '*').length) > 0; +    }, + +  switchContext = +    function(context, force) { +      var oldDoc = doc; +      doc = context.ownerDocument || context; +      if (force || oldDoc !== doc) { +        // force a new check for each document change +        // performed before the next select operation +        root = doc.documentElement; +        HTML_DOCUMENT = isHTML(doc); +        QUIRKS_MODE = HTML_DOCUMENT && +          doc.compatMode.indexOf('CSS') < 0; +        NAMESPACE = root && root.namespaceURI; +        Snapshot.doc = doc; +        Snapshot.root = root; +      } +      return (Snapshot.from = context); +    }, + +  // convert single codepoint to UTF-16 encoding +  codePointToUTF16 = +    function(codePoint) { +      // out of range, use replacement character +      if (codePoint < 1 || codePoint > 0x10ffff || +        (codePoint > 0xd7ff && codePoint < 0xe000)) { +        return '\\ufffd'; +      } +      // javascript strings are UTF-16 encoded +      if (codePoint < 0x10000) { +        var lowHex = '000' + codePoint.toString(16); +        return '\\u' + lowHex.substr(lowHex.length - 4); +      } +      // supplementary high + low surrogates +      return '\\u' + (((codePoint - 0x10000) >> 0x0a) + 0xd800).toString(16) + +             '\\u' + (((codePoint - 0x10000) % 0x400) + 0xdc00).toString(16); +    }, + +  // convert single codepoint to string +  stringFromCodePoint = +    function(codePoint) { +      // out of range, use replacement character +      if (codePoint < 1 || codePoint > 0x10ffff || +        (codePoint > 0xd7ff && codePoint < 0xe000)) { +        return '\ufffd'; +      } +      if (codePoint < 0x10000) { +        return String.fromCharCode(codePoint); +      } +      return String.fromCodePoint ? +        String.fromCodePoint(codePoint) : +        String.fromCharCode( +          ((codePoint - 0x10000) >> 0x0a) + 0xd800, +          ((codePoint - 0x10000) % 0x400) + 0xdc00); +    }, + +  // convert escape sequence in a CSS string or identifier +  // to javascript string with javascript escape sequences +  convertEscapes = +    function(str) { +      return REX.HasEscapes.test(str) ? +        str.replace(REX.FixEscapes, +          function(substring, p1, p2) { +            // unescaped " or ' +            return p2 ? '\\' + p2 : +              // javascript strings are UTF-16 encoded +              REX.HexNumbers.test(p1) ? codePointToUTF16(parseInt(p1, 16)) : +              // \' \" +              REX.EscOrQuote.test(p1) ? substring : +              // \g \h \. \# etc +              p1; +          } +        ) : str; +    }, + +  // convert escape sequence in a CSS string or identifier +  // to javascript string with characters representations +  unescapeIdentifier = +    function(str) { +      return REX.HasEscapes.test(str) ? +        str.replace(REX.FixEscapes, +          function(substring, p1, p2) { +            // unescaped " or ' +            return p2 ? p2 : +              // javascript strings are UTF-16 encoded +              REX.HexNumbers.test(p1) ? stringFromCodePoint(parseInt(p1, 16)) : +              // \' \" +              REX.EscOrQuote.test(p1) ? substring : +              // \g \h \. \# etc +              p1; +          } +        ) : str; +    }, + +  method = { +    '#': 'getElementById', +    '*': 'getElementsByTagName', +    '.': 'getElementsByClassName' +    }, + +  compat = { +    '#': function(c, n) { REX.HasEscapes.test(n) && (n = unescapeIdentifier(n)); return function(e, f) { return byId(n, c); }; }, +    '*': function(c, n) { REX.HasEscapes.test(n) && (n = unescapeIdentifier(n)); return function(e, f) { return byTag(n, c); }; }, +    '.': function(c, n) { REX.HasEscapes.test(n) && (n = unescapeIdentifier(n)); return function(e, f) { return byClass(n, c); }; } +    }, + +  // find duplicate ids using iterative walk +  byIdRaw = +    function(id, context) { +      var node = context, nodes = [ ], next = node.firstElementChild; +      while ((node = next)) { +        node.id == id && (nodes[nodes.length] = node); +        if ((next = node.firstElementChild || node.nextElementSibling)) continue; +        while (!next && (node = node.parentElement) && node !== context) { +          next = node.nextElementSibling; +        } +      } +      return nodes; +    }, + +  // context agnostic getElementById +  byId = +    function(id, context) { +      var e, nodes, api = method['#']; + +      // duplicates id allowed +      if (Config.IDS_DUPES === false) { +        if (api in context) { +          return (e = context[api](id)) ? [ e ] : none; +        } +      } else { +        if ('all' in context) { +          if ((e = context.all[id])) { +            if (e.nodeType == 1) return e.getAttribute('id') != id ? [ ] : [ e ]; +            else if (id == 'length') return (e = context[api](id)) ? [ e ] : none; +            for (i = 0, l = e.length, nodes = [ ]; l > i; ++i) { +              if (e[i].id == id) nodes[nodes.length] = e[i]; +            } +            return nodes && nodes.length ? nodes : [ nodes ]; +          } else return none; +        } +      } + +      return byIdRaw(id, context); +    }, + +  // context agnostic getElementsByTagName +  byTag = +    function(tag, context) { +      var e, nodes, api = method['*']; +      // DOCUMENT_NODE (9) & ELEMENT_NODE (1) +      if (api in context) { +        return slice.call(context[api](tag)); +      } else { +        // DOCUMENT_FRAGMENT_NODE (11) +        if ((e = context.firstElementChild)) { +          tag = tag.toLowerCase(); +          if (!(e.nextElementSibling || tag == '*' || e.nodeName.toLowerCase() == tag)) { +            return slice.call(e[api](tag)); +          } else { +            nodes = [ ]; +            do { +              if (tag == '*' || e.nodeName.toLowerCase() == tag) nodes[nodes.length] = e; +              concatList(nodes, e[api](tag)); +            } while ((e = e.nextElementSibling)); +          } +        } else nodes = none; +      } +      return nodes; +    }, + +  // context agnostic getElementsByClassName +  byClass = +    function(cls, context) { +      var e, nodes, api = method['.'], reCls; +      // DOCUMENT_NODE (9) & ELEMENT_NODE (1) +      if (api in context) { +        return slice.call(context[api](cls)); +      } else { +        // DOCUMENT_FRAGMENT_NODE (11) +        if ((e = context.firstElementChild)) { +          reCls = RegExp('(^|\\s)' + cls + '(\\s|$)', QUIRKS_MODE ? 'i' : ''); +          if (!(e.nextElementSibling || reCls.test(e.className))) { +            return slice.call(e[api](cls)); +          } else { +            nodes = [ ]; +            do { +              if (reCls.test(e.className)) nodes[nodes.length] = e; +              concatList(nodes, e[api](cls)); +            } while ((e = e.nextElementSibling)); +          } +        } else nodes = none; +      } +      return nodes; +    }, + +  // namespace aware hasAttribute +  // helper for XML/XHTML documents +  hasAttributeNS = +    function(e, name) { +      var i, l, attr = e.getAttributeNames(); +      name = RegExp(':?' + name + '$', HTML_DOCUMENT ? 'i' : ''); +      for (i = 0, l = attr.length; l > i; ++i) { +        if (name.test(attr[i])) return true; +      } +      return false; +    }, + +  // fast resolver for the :nth-child() and :nth-last-child() pseudo-classes +  nthElement = (function() { +    var idx = 0, len = 0, set = 0, parent = undefined, parents = Array(), nodes = Array(); +    return function(element, dir) { +      // ensure caches are emptied after each run, invoking with dir = 2 +      if (dir == 2) { +        idx = 0; len = 0; set = 0; nodes.length = 0; +        parents.length = 0; parent = undefined; +        return -1; +      } +      var e, i, j, k, l; +      if (parent === element.parentElement) { +        i = set; j = idx; l = len; +      } else { +        l = parents.length; +        parent = element.parentElement; +        for (i = -1, j = 0, k = l - 1; l > j; ++j, --k) { +          if (parents[j] === parent) { i = j; break; } +          if (parents[k] === parent) { i = k; break; } +        } +        if (i < 0) { +          parents[i = l] = parent; +          l = 0; nodes[i] = Array(); +          e = parent && parent.firstElementChild || element; +          while (e) { nodes[i][l] = e; if (e === element) j = l; e = e.nextElementSibling; ++l; } +          set = i; idx = 0; len = l; +          if (l < 2) return l; +        } else { +          l = nodes[i].length; +          set = i; +        } +      } +      if (element !== nodes[i][j] && element !== nodes[i][j = 0]) { +        for (j = 0, e = nodes[i], k = l - 1; l > j; ++j, --k) { +          if (e[j] === element) { break; } +          if (e[k] === element) { j = k; break; } +        } +      } +      idx = j + 1; len = l; +      return dir ? l - j : idx; +    }; +  })(), + +  // fast resolver for the :nth-of-type() and :nth-last-of-type() pseudo-classes +  nthOfType = (function() { +    var idx = 0, len = 0, set = 0, parent = undefined, parents = Array(), nodes = Array(); +    return function(element, dir) { +      // ensure caches are emptied after each run, invoking with dir = 2 +      if (dir == 2) { +        idx = 0; len = 0; set = 0; nodes.length = 0; +        parents.length = 0; parent = undefined; +        return -1; +      } +      var e, i, j, k, l, name = element.nodeName; +      if (nodes[set] && nodes[set][name] && parent === element.parentElement) { +        i = set; j = idx; l = len; +      } else { +        l = parents.length; +        parent = element.parentElement; +        for (i = -1, j = 0, k = l - 1; l > j; ++j, --k) { +          if (parents[j] === parent) { i = j; break; } +          if (parents[k] === parent) { i = k; break; } +        } +        if (i < 0 || !nodes[i][name]) { +          parents[i = l] = parent; +          nodes[i] || (nodes[i] = Object()); +          l = 0; nodes[i][name] = Array(); +          e = parent && parent.firstElementChild || element; +          while (e) { if (e === element) j = l; if (e.nodeName == name) { nodes[i][name][l] = e; ++l; } e = e.nextElementSibling; } +          set = i; idx = j; len = l; +          if (l < 2) return l; +        } else { +          l = nodes[i][name].length; +          set = i; +        } +      } +      if (element !== nodes[i][name][j] && element !== nodes[i][name][j = 0]) { +        for (j = 0, e = nodes[i][name], k = l - 1; l > j; ++j, --k) { +          if (e[j] === element) { break; } +          if (e[k] === element) { j = k; break; } +        } +      } +      idx = j + 1; len = l; +      return dir ? l - j : idx; +    }; +  })(), + +  // check if the document type is HTML +  isHTML = +    function(node) { +      var doc = node.ownerDocument || node; +      return doc.nodeType == 9 && +        // contentType not in IE <= 11 +        'contentType' in doc ? +          doc.contentType.indexOf('/html') > 0 : +          doc.createElement('DiV').nodeName == 'DIV'; +    }, + +  // configure the engine to use special handling +  configure = +    function(option, clear) { +      if (typeof option == 'string') { return !!Config[option]; } +      if (typeof option != 'object') { return Config; } +      for (var i in option) { +        Config[i] = !!option[i]; +      } +      // clear lambda cache +      if (clear) { +        matchResolvers = { }; +        selectResolvers = { }; +      } +      setIdentifierSyntax(); +      return true; +    }, + +  // centralized error and exceptions handling +  emit = +    function(message, proto) { +      var err; +      if (Config.VERBOSITY) { +        if (proto) { +          err = new proto(message); +        } else { +          err = new global.DOMException(message, 'SyntaxError'); +        } +        throw err; +      } +      if (Config.LOGERRORS && console && console.log) { +        console.log(message); +      } +    }, + +  // execute the engine initialization code +  initialize = +    function(doc) { +      setIdentifierSyntax(); +      lastContext = switchContext(doc, true); +    }, + +  // build validation regexps used by the engine +  setIdentifierSyntax = +    function() { + +      // +      // NOTE: SPECIAL CASES IN CSS SYNTAX PARSING RULES +      // +      // The <EOF-token> https://drafts.csswg.org/css-syntax/#typedef-eof-token +      // allow mangled|unclosed selector syntax at the end of selectors strings +      // +      // Literal equivalent hex representations of the characters: " ' ` ] ) +      // +      //     \\x22 = " - double quotes    \\x5b = [ - open square bracket +      //     \\x27 = ' - single quote     \\x5d = ] - closed square bracket +      //     \\x60 = ` - back tick        \\x28 = ( - open round parens +      //     \\x5c = \ - back slash       \\x29 = ) - closed round parens +      // +      // using hex format prevents false matches of opened/closed instances +      // pairs, coloring breakage and other editors highlightning problems. +      // + +      var identifier = +        // doesn't start with a digit +        '(?=[^0-9])' + +        // can start with double dash +        '(?:-{2}' + +          // may include ascii chars +          '|[a-zA-Z0-9-_]' + +          // non-ascii chars +          '|[^\\x00-\\x9f]' + +          // escaped chars +          '|\\\\[^\\r\\n\\f0-9a-fA-F]' + +          // unicode chars +          '|\\\\[0-9a-fA-F]{1,6}(?:\\r\\n|\\s)?' + +          // any escaped chars +          '|\\\\.' + +        ')+', + +      pseudonames = '[-\\w]+', +      pseudoparms = '(?:[-+]?\\d*)(?:n\\s?[-+]?\\s?\\d*)', +      doublequote = '"[^"\\\\]*(?:\\\\.[^"\\\\]*)*(?:"|$)', +      singlequote = "'[^'\\\\]*(?:\\\\.[^'\\\\]*)*(?:'|$)", + +      attrparser = identifier + '|' + doublequote + '|' + singlequote, + +      attrvalues = '([\\x22\\x27]?)((?!\\3)*|(?:\\\\?.)*?)(?:\\3|$)', + +      attributes = +        '\\[' + +          // attribute presence +          '(?:\\*\\|)?' + +          WSP + '?' + +          '(' + identifier + '(?::' + identifier + ')?)' + +          WSP + '?' + +          '(?:' + +            '(' + CFG.operators + ')' + WSP + '?' + +            '(?:' + attrparser + ')' + +          ')?' + +          // attribute case sensitivity +          WSP + '?' + '(i)?' + WSP + '?' + +        '(?:\\]|$)', + +      attrmatcher = attributes.replace(attrparser, attrvalues), + +      pseudoclass = +        '(?:\\x28' + WSP + '*' + +          '(?:' + pseudoparms + '?)?|' + +          // universal * & +          // namespace *|* +          '(?:\\*|\\|)|' + +          '(?:' + +            '(?::' + pseudonames + +            '(?:\\x28' + pseudoparms + '?(?:\\x29|$))?|' + +          ')|' + +          '(?:[.#]?' + identifier + ')|' + +          '(?:' + attributes + ')' + +          ')+|' + +          '(?:' + WSP + '?,' + WSP + '?)|' + +          '(?:' + WSP + '?)|' + +          '(?:\\x29|$))*', + +      standardValidator = +        '(?=' + WSP + '?[^>+~(){}<>])' + +        '(?:' + +          // universal * & +          // namespace *|* +          '(?:\\*|\\|)|' + +          '(?:[.#]?' + identifier + ')+|' + +          '(?:' + attributes + ')+|' + +          '(?:::?' + pseudonames + pseudoclass + ')|' + +          '(?:' + WSP + '?' + CFG.combinators + WSP + '?)|' + +          '(?:' + WSP + '?,' + WSP + '?)|' + +          '(?:' + WSP + '?)' + +        ')+'; + +      // the following global RE is used to return the +      // deepest nodeName in selector strings and then +      // use it to retrieve all possible matching nodes +      // that will be filtered by compiled resolvers +      reOptimizer = RegExp( +        '(?:([.:#*]?)' + +        '(' + identifier + ')' + +        '(?:' + +          ':[-\\w]+|' + +          '\\[[^\\]]+(?:\\]|$)|' + +          '\\x28[^\\x29]+(?:\\x29|$)' + +        ')*)$'); + +      // global +      reValidator = RegExp(standardValidator, 'g'); + +      Patterns.id = RegExp('^#(' + identifier + ')(.*)'); +      Patterns.tagName = RegExp('^(' + identifier + ')(.*)'); +      Patterns.className = RegExp('^\\.(' + identifier + ')(.*)'); +      Patterns.attribute = RegExp('^(?:' + attrmatcher + ')(.*)'); +    }, + +  F_INIT = '"use strict";return function Resolver(c,f,x,r)', + +  S_HEAD = 'var e,n,o,j=r.length-1,k=-1', +  M_HEAD = 'var e,n,o', + +  S_LOOP = 'main:while((e=c[++k]))', +  N_LOOP = 'main:while((e=c.item(++k)))', +  M_LOOP = 'e=c;', + +  S_BODY = 'r[++j]=c[k];', +  N_BODY = 'r[++j]=c.item(k);', +  M_BODY = '', + +  S_TAIL = 'continue main;', +  M_TAIL = 'r=true;', + +  S_TEST = 'if(f(c[k])){break main;}', +  N_TEST = 'if(f(c.item(k))){break main;}', +  M_TEST = 'f(c);', + +  S_VARS = [ ], +  M_VARS = [ ], + +  // compile groups or single selector strings into +  // executable functions for matching or selecting +  compile = +    function(selector, mode, callback) { +      var factory, token, head = '', loop = '', macro = '', source = '', vars = ''; + +      // 'mode' can be boolean or null +      // true = select / false = match +      // null to use collection.item() +      switch (mode) { +        case true: +          if (selectLambdas[selector]) { return selectLambdas[selector]; } +          macro = S_BODY + (callback ? S_TEST : '') + S_TAIL; +          head = S_HEAD; +          loop = S_LOOP; +          break; +        case false: +          if (matchLambdas[selector]) { return matchLambdas[selector]; } +          macro = M_BODY + (callback ? M_TEST : '') + M_TAIL; +          head = M_HEAD; +          loop = M_LOOP; +          break; +        case null: +          if (selectLambdas[selector]) { return selectLambdas[selector]; } +          macro = N_BODY + (callback ? N_TEST : '') + S_TAIL; +          head = S_HEAD; +          loop = N_LOOP; +          break; +        default: +          break; +      } + +      source = compileSelector(selector, macro, mode, callback, false); + +      loop += mode || mode === null ? '{' + source + '}' : source; + +      if (mode || mode === null && selector.includes(':nth')) { +        loop += reNthElem.test(selector) ? 's.nthElement(null, 2);' : ''; +        loop += reNthType.test(selector) ? 's.nthOfType(null, 2);' : ''; +      } + +      if (S_VARS[0] || M_VARS[0]) { +        vars = ',' + (S_VARS.join(',') || M_VARS.join(',')); +        S_VARS.length = 0; +        M_VARS.length = 0; +      } + +      factory = Function('s', F_INIT + '{' + head + vars + ';' + loop + 'return r;}')(Snapshot); + +      return mode || mode === null ? (selectLambdas[selector] = factory) : (matchLambdas[selector] = factory); +    }, + +  // build conditional code to check components of selector strings +  compileSelector = +    function(expression, source, mode, callback, not) { + +      // N is the negation pseudo-class flag +      // D is the default inverted negation flag +      var a, b, n, f, i, l, name, nested, NS, +      N = not ? '!' : '', D = not ? '' : '!', +      compat, expr, match, result, status, symbol, test, +      type, selector = expression, selector_string, vars; + +      // original 'select' or 'match' selector string before normalization +      selector_string = mode ? lastSelected : lastMatched; + +      // isolate selector combinators/components and normalize whitespace +      selector = selector.replace(STD.combinator, '$1');//.replace(STD.whitespace, ' '); + +      while (selector) { + +        // get namespace prefix if present or get first char of selector +        symbol = STD.apimethods.test(selector) ? '|' : selector[0]; + +        switch (symbol) { + +          // universal resolver +          case '*': +            match = selector.match(Patterns.universal); +            if (N == '!') { +              source = 'if(' + N + 'true' + +                '){' + source + '}'; +            } +            break; + +          // id resolver +          case '#': +            match = selector.match(Patterns.id); +            source = 'if(' + N + '(/^' + match[1] + '$/.test(e.getAttribute("id"))' + +              ')){' + source + '}'; +            break; + +          // class name resolver +          case '.': +            match = selector.match(Patterns.className); +            compat = (QUIRKS_MODE ? 'i' : '') + '.test(e.getAttribute("class"))'; +            source = 'if(' + N + '(/(^|\\s)' + match[1] + '(\\s|$)/' + compat + +              ')){' + source + '}'; +            break; + +          // tag name resolver +          case (/[a-z]/i.test(symbol) ? symbol : undefined): +            match = selector.match(Patterns.tagName); +            source = 'if(' + N + '(e.nodeName' + +              (Config.MIXEDCASE || hasMixedCaseTagNames(doc) ? +                '.toLowerCase()=="' + match[1].toLowerCase() + '"' : +                '=="' + match[1].toUpperCase() + '"') + +              ')){' + source + '}'; +            break; + +          // namespace resolver +          case '|': +            match = selector.match(Patterns.namespace); +            if (match[1] == '*') { +              source = 'if(' + N + 'true){' + source + '}'; +            } else if (!match[1]) { +              source = 'if(' + N + '(!e.namespaceURI)){' + source + '}'; +            } else if (typeof match[1] == 'string' && root.prefix == match[1]) { +              source = 'if(' + N + '(e.namespaceURI=="' + NAMESPACE + '")){' + source + '}'; +            } else { +              emit('\'' + selector_string + '\'' + qsInvalid); +            } +            break; + +          // attributes resolver +          case '[': +            match = selector.match(Patterns.attribute); +            NS = match[0].match(STD.namespaces); +            name = match[1]; +            expr = name.split(':'); +            expr = expr.length == 2 ? expr[1] : expr[0]; +            if (match[2] && !(test = Operators[match[2]])) { +              emit('\'' + selector_string + '\'' + qsInvalid); +              return ''; +            } +            if (match[4] === '') { +              test = match[2] == '~=' ? +                { p1: '^\\s', p2: '+$', p3: 'true' } : +                  match[2] in ATTR_STD_OPS && match[2] != '~=' ? +                { p1: '^',    p2: '$',  p3: 'true' } : test; +            } else if (match[2] == '~=' && match[4].includes(' ')) { +              // whitespace separated list but value contains space +              source = 'if(' + N + 'false){' + source + '}'; +              break; +            } else if (match[4]) { +              match[4] = convertEscapes(match[4]).replace(REX.RegExpChar, '\\$&'); +            } +            type = match[5] == 'i' || (HTML_DOCUMENT && HTML_TABLE[expr.toLowerCase()]) ? 'i' : ''; +            source = 'if(' + N + '(' + +              (!match[2] ? (NS ? 's.hasAttributeNS(e,"' + name + '")' : 'e.hasAttribute("' + name + '")') : +              !match[4] && ATTR_STD_OPS[match[2]] && match[2] != '~=' ? 'e.getAttribute("' + name + '")==""' : +              '(/' + test.p1 + match[4] + test.p2 + '/' + type + ').test(e.getAttribute("' + name + '"))==' + test.p3) + +              ')){' + source + '}'; +            break; + +          // *** General sibling combinator +          // E ~ F (F relative sibling of E) +          case '~': +            match = selector.match(Patterns.relative); +            source = 'n=e;while((e=e.previousElementSibling)){' + source + '}e=n;'; +            break; +          // *** Adjacent sibling combinator +          // E + F (F adiacent sibling of E) +          case '+': +            match = selector.match(Patterns.adjacent); +            source = 'n=e;if((e=e.previousElementSibling)){' + source + '}e=n;'; +            break; +          // *** Descendant combinator +          // E F (E ancestor of F) +          case '\x09': +          case '\x20': +            match = selector.match(Patterns.ancestor); +            source = 'n=e;while((e=e.parentElement)){' + source + '}e=n;'; +            break; +          // *** Child combinator +          // E > F (F children of E) +          case '>': +            match = selector.match(Patterns.children); +            source = 'n=e;if((e=e.parentElement)){' + source + '}e=n;'; +            break; + +          // *** user supplied combinators extensions +          case (symbol in Combinators ? symbol : undefined): +            // for other registered combinators extensions +            match[match.length - 1] = '*'; +            source = Combinators[symbol](match) + source; +            break; + +          // *** tree-structural pseudo-classes +          // :root, :empty, :first-child, :last-child, :only-child, :first-of-type, :last-of-type, :only-of-type +          case ':': +            if ((match = selector.match(Patterns.structural))) { +              match[1] = match[1].toLowerCase(); +              switch (match[1]) { +                case 'root': +                  // there can only be one :root element, so exit the loop once found +                  source = 'if(' + N + '(e===s.root)){' + source + (mode ? 'break main;' : '') + '}'; +                  break; +                case 'empty': +                  // matches elements that don't contain elements or text nodes +                  source = 'n=e.firstChild;while(n&&!(/1|3/).test(n.nodeType)){n=n.nextSibling}if(' + D + 'n){' + source + '}'; +                  break; + +                // *** child-indexed pseudo-classes +                // :first-child, :last-child, :only-child +                case 'only-child': +                  source = 'if(' + N + '(!e.nextElementSibling&&!e.previousElementSibling)){' + source + '}'; +                  break; +                case 'last-child': +                  source = 'if(' + N + '(!e.nextElementSibling)){' + source + '}'; +                  break; +                case 'first-child': +                  source = 'if(' + N + '(!e.previousElementSibling)){' + source + '}'; +                  break; + +                // *** typed child-indexed pseudo-classes +                // :only-of-type, :last-of-type, :first-of-type +                case 'only-of-type': +                  source = 'o=e.nodeName;' + +                    'n=e;while((n=n.nextElementSibling)&&n.nodeName!=o);if(!n){' + +                    'n=e;while((n=n.previousElementSibling)&&n.nodeName!=o);}if(' + D + 'n){' + source + '}'; +                  break; +                case 'last-of-type': +                  source = 'n=e;o=e.nodeName;while((n=n.nextElementSibling)&&n.nodeName!=o);if(' + D + 'n){' + source + '}'; +                  break; +                case 'first-of-type': +                  source = 'n=e;o=e.nodeName;while((n=n.previousElementSibling)&&n.nodeName!=o);if(' + D + 'n){' + source + '}'; +                  break; +                default: +                  emit('\'' + selector_string + '\'' + qsInvalid); +                  break; +              } +            } + +            // *** child-indexed & typed child-indexed pseudo-classes +            // :nth-child, :nth-of-type, :nth-last-child, :nth-last-of-type +            else if ((match = selector.match(Patterns.treestruct))) { +              match[1] = match[1].toLowerCase(); +              switch (match[1]) { +                case 'nth-child': +                case 'nth-of-type': +                case 'nth-last-child': +                case 'nth-last-of-type': +                  expr = /-of-type/i.test(match[1]); +                  if (match[1] && match[2]) { +                    type = /last/i.test(match[1]); +                    if (match[2] == 'n') { +                      source = 'if(' + N + 'true){' + source + '}'; +                      break; +                    } else if (match[2] == '1') { +                      test = type ? 'next' : 'previous'; +                      source = expr ? 'n=e;o=e.nodeName;' + +                        'while((n=n.' + test + 'ElementSibling)&&n.nodeName!=o);if(' + D + 'n){' + source + '}' : +                        'if(' + N + '!e.' + test + 'ElementSibling){' + source + '}'; +                      break; +                    } else if (match[2] == 'even' || match[2] == '2n0' || match[2] == '2n+0' || match[2] == '2n') { +                      test = 'n%2==0'; +                    } else if (match[2] == 'odd'  || match[2] == '2n1' || match[2] == '2n+1') { +                      test = 'n%2==1'; +                    } else { +                      f = /n/i.test(match[2]); +                      n = match[2].split('n'); +                      a = parseInt(n[0], 10) || 0; +                      b = parseInt(n[1], 10) || 0; +                      if (n[0] == '-') { a = -1; } +                      if (n[0] == '+') { a = +1; } +                      test = (b ? '(n' + (b > 0 ? '-' : '+') + Math.abs(b) + ')' : 'n') + '%' + a + '==0' ; +                      test = +                        a >= +1 ? (f ? 'n>' + (b - 1) + (Math.abs(a) != 1 ? '&&' + test : '') : 'n==' + a) : +                        a <= -1 ? (f ? 'n<' + (b + 1) + (Math.abs(a) != 1 ? '&&' + test : '') : 'n==' + a) : +                        a === 0 ? (n[0] ? 'n==' + b : 'n>' + (b - 1)) : 'false'; +                    } +                    expr = expr ? 'OfType' : 'Element'; +                    type = type ? 'true' : 'false'; +                    source = 'n=s.nth' + expr + '(e,' + type + ');if(' + N + '(' + test + ')){' + source + '}'; +                  } else { +                    emit('\'' + selector_string + '\'' + qsInvalid); +                  } +                  break; +                default: +                  emit('\'' + selector_string + '\'' + qsInvalid); +                  break; +              } +            } + +            // *** logical combination pseudo-classes +            // :matches( s1, [ s2, ... ]), :not( s1, [ s2, ... ]) +            else if ((match = selector.match(Patterns.logicalsel))) { +              match[1] = match[1].toLowerCase(); +              switch (match[1]) { +                case 'matches': +                  if (not === true || nested === true) { +                    emit(':matches() pseudo-class cannot be nested'); +                  } +                  nested = true; +                  expr = match[2].replace(REX.CommaGroup, ',').replace(REX.TrimSpaces, ''); +                  // check nested compound selectors s1, s2 +                  expr = match[2].match(REX.SplitGroup); +                  for (i = 0, l = expr.length; l > i; ++i) { +                    expr[i] = expr[i].replace(REX.TrimSpaces, ''); +                    source = 'if(s.match("' + expr[i].replace(/\x22/g, '\\"') + '",e)){' + source + '}'; +                  } +                  break; +                case 'not': +                  if (not === true || nested === true) { +                    emit(':not() pseudo-class cannot be nested'); +                  } +                  expr = match[2].replace(REX.CommaGroup, ',').replace(REX.TrimSpaces, ''); +                  // check nested compound selectors s1, s2 +                  expr = match[2].match(REX.SplitGroup); +                  for (i = 0, l = expr.length; l > i; ++i) { +                    expr[i] = expr[i].replace(REX.TrimSpaces, ''); +                    source = compileSelector(expr[i], source, false, callback, true); +                  } +                  break; +                default: +                  emit('\'' + selector_string + '\'' + qsInvalid); +                  break; +              } +            } + +            // *** linguistic pseudo-classes +            // :dir( ltr / rtl ), :lang( en ) +            else if ((match = selector.match(Patterns.linguistic))) { +              match[1] = match[1].toLowerCase(); +              switch (match[1]) { +                case 'dir': +                  source = 'var p;if(' + N + '(' + +                    '(/' + match[2] + '/i.test(e.dir))||(p=s.ancestor("[dir]", e))&&' + +                    '(/' + match[2] + '/i.test(p.dir))||(e.dir==""||e.dir=="auto")&&' + +                    '(' + (match[2] == 'ltr' ? '!':'')+ RTL +'.test(e.textContent)))' + +                    '){' + source + '};'; +                  break; +                case 'lang': +                  expr = '(?:^|-)' + match[2] + '(?:-|$)'; +                  source = 'var p;if(' + N + '(' + +                    '(e.isConnected&&(e.lang==""&&(p=s.ancestor("[lang]",e)))&&' + +                    '(p.lang=="' + match[2] + '")||/'+ expr +'/i.test(e.lang)))' + +                    '){' + source + '};'; +                  break; +                default: +                  emit('\'' + selector_string + '\'' + qsInvalid); +                  break; +              } +            } + +            // *** location pseudo-classes +            // :link, :visited, :target +            else if ((match = selector.match(Patterns.locationpc))) { +              match[1] = match[1].toLowerCase(); +              switch (match[1]) { +                case 'link': +                  source = 'if(' + N + '(/^a|area|link$/i.test(e.nodeName)&&e.hasAttribute("href"))){' + source + '}'; +                  break; +                case 'visited': +                  source = 'if(' + N + '(/^a|area|link$/i.test(e.nodeName)&&e.hasAttribute("href")&&e.visited)){' + source + '}'; +                  break; +                case 'target': +                  source = 'if(' + N + '((s.doc.compareDocumentPosition(e)&16)&&s.doc.location.hash&&e.id==s.doc.location.hash.slice(1))){' + source + '}'; +                  break; +                default: +                  emit('\'' + selector_string + '\'' + qsInvalid); +                  break; +              } +            } + +            // *** user actions pseudo-classes +            // :hover, :active, :focus +            else if ((match = selector.match(Patterns.useraction))) { +              match[1] = match[1].toLowerCase(); +              switch (match[1]) { +                case 'hover': +                  source = 'hasFocus' in doc && doc.hasFocus() ? +                    'if(' + N + '(e===s.doc.hoverElement)){' + source + '}' : +                    'if(' + D + 'true){' + source + '}'; +                  break; +                case 'active': +                  source = 'hasFocus' in doc && doc.hasFocus() ? +                    'if(' + N + '(e===s.doc.activeElement)){' + source + '}' : +                    'if(' + D + 'true){' + source + '}'; +                  break; +                case 'focus': +                  source = 'hasFocus' in doc ? +                    'if(' + N + '(e===s.doc.activeElement&&s.doc.hasFocus()&&(e.type||e.href||typeof e.tabIndex=="number"))){' + source + '}' : +                    'if(' + N + '(e===s.doc.activeElement&&(e.type||e.href))){' + source + '}'; +                  break; +                case 'focus-within': +                  source = 'hasFocus' in doc ? +                    'n=s.doc.activeElement;while(e){if(e===n||e.parentNode===n)break;}' + +                    'if(' + N + '(e===n&&s.doc.hasFocus()&&(e.type||e.href||typeof e.tabIndex=="number"))){' + source + '}' : source; +                  break; +                default: +                  emit('\'' + selector_string + '\'' + qsInvalid); +                  break; +              } +            } + +            // *** user interface and form pseudo-classes +            // :enabled, :disabled, :read-only, :read-write, :placeholder-shown, :default +            else if ((match = selector.match(Patterns.inputstate))) { +              match[1] = match[1].toLowerCase(); +              switch (match[1]) { +                case 'enabled': +                  source = 'if(' + N + '(("form" in e||/^optgroup$/i.test(e.nodeName))&&"disabled" in e &&e.disabled===false' + +                    ')){' + source + '}'; +                  break; +                case 'disabled': +                  // https://www.w3.org/TR/html5/forms.html#enabling-and-disabling-form-controls:-the-disabled-attribute +                  source = 'if(' + N + '(("form" in e||/^optgroup$/i.test(e.nodeName))&&"disabled" in e&&' + +                    '(e.disabled===true||(n=s.ancestor("fieldset",e))&&(n=s.first("legend",n))&&!n.contains(e))' + +                    ')){' + source + '}'; +                  break; +                case 'read-only': +                  source = +                    'if(' + N + '(' + +                      '(/^textarea$/i.test(e.nodeName)&&(e.readOnly||e.disabled))||' + +                      '("|password|text|".includes("|"+e.type+"|")&&e.readOnly)' + +                    ')){' + source + '}'; +                  break; +                case 'read-write': +                  source = +                    'if(' + N + '(' + +                      '((/^textarea$/i.test(e.nodeName)&&!e.readOnly&&!e.disabled)||' + +                      '("|password|text|".includes("|"+e.type+"|")&&!e.readOnly&&!e.disabled))||' + +                      '(e.hasAttribute("contenteditable")||(s.doc.designMode=="on"))' + +                    ')){' + source + '}'; +                  break; +                case 'placeholder-shown': +                  source = +                    'if(' + N + '(' + +                      '(/^input|textarea$/i.test(e.nodeName))&&e.hasAttribute("placeholder")&&' + +                      '("|textarea|password|number|search|email|text|tel|url|".includes("|"+e.type+"|"))&&' + +                      '(!s.match(":focus",e))' + +                    ')){' + source + '}'; +                  break; +                case 'default': +                  source = +                    'if(' + N + '("form" in e && e.form)){' + +                      'var x=0;n=[];' + +                      'if(e.type=="image")n=e.form.getElementsByTagName("input");' + +                      'if(e.type=="submit")n=e.form.elements;' + +                      'while(n[x]&&e!==n[x]){' + +                        'if(n[x].type=="image")break;' + +                        'if(n[x].type=="submit")break;' + +                        'x++;' + +                      '}' + +                    '}' + +                    'if(' + N + '(e.form&&(e===n[x]&&"|image|submit|".includes("|"+e.type+"|"))||' + +                      '((/^option$/i.test(e.nodeName))&&e.defaultSelected)||' + +                      '(("|radio|checkbox|".includes("|"+e.type+"|"))&&e.defaultChecked)' + +                    ')){' + source + '}'; +                  break; +                default: +                  emit('\'' + selector_string + '\'' + qsInvalid); +                  break; +              } +            } + +            // *** input pseudo-classes (for form validation) +            // :checked, :indeterminate, :valid, :invalid, :in-range, :out-of-range, :required, :optional +            else if ((match = selector.match(Patterns.inputvalue))) { +              match[1] = match[1].toLowerCase(); +              switch (match[1]) { +                case 'checked': +                  source = 'if(' + N + '(/^input$/i.test(e.nodeName)&&' + +                    '("|radio|checkbox|".includes("|"+e.type+"|")&&e.checked)||' + +                    '(/^option$/i.test(e.nodeName)&&(e.selected||e.checked))' + +                    ')){' + source + '}'; +                  break; +                case 'indeterminate': +                  source = +                    'if(' + N + '(/^progress$/i.test(e.nodeName)&&!e.hasAttribute("value"))||' + +                      '(/^input$/i.test(e.nodeName)&&("checkbox"==e.type&&e.indeterminate)||' + +                      '("radio"==e.type&&e.name&&!s.first("input[name="+e.name+"]:checked",e.form))' + +                    ')){' + source + '}'; +                  break; +                case 'required': +                  source = +                    'if(' + N + +                      '(/^input|select|textarea$/i.test(e.nodeName)&&e.required)' + +                    '){' + source + '}'; +                  break; +                case 'optional': +                  source = +                    'if(' + N + +                      '(/^input|select|textarea$/i.test(e.nodeName)&&!e.required)' + +                    '){' + source + '}'; +                  break; +                case 'invalid': +                  source = +                    'if(' + N + '((' + +                      '(/^form$/i.test(e.nodeName)&&!e.noValidate)||' + +                      '(e.willValidate&&!e.formNoValidate))&&!e.checkValidity())||' + +                      '(/^fieldset$/i.test(e.nodeName)&&s.first(":invalid",e))' + +                    '){' + source + '}'; +                  break; +                case 'valid': +                  source = +                    'if(' + N + '((' + +                      '(/^form$/i.test(e.nodeName)&&!e.noValidate)||' + +                      '(e.willValidate&&!e.formNoValidate))&&e.checkValidity())||' + +                      '(/^fieldset$/i.test(e.nodeName)&&s.first(":valid",e))' + +                    '){' + source + '}'; +                  break; +                case 'in-range': +                  source = +                    'if(' + N + +                      '(/^input$/i.test(e.nodeName))&&' + +                      '(e.willValidate&&!e.formNoValidate)&&' + +                      '(!e.validity.rangeUnderflow&&!e.validity.rangeOverflow)&&' + +                      '("|date|datetime-local|month|number|range|time|week|".includes("|"+e.type+"|"))&&' + +                      '("range"==e.type||e.getAttribute("min")||e.getAttribute("max"))' + +                    '){' + source + '}'; +                  break; +                case 'out-of-range': +                  source = +                    'if(' + N + +                      '(/^input$/i.test(e.nodeName))&&' + +                      '(e.willValidate&&!e.formNoValidate)&&' + +                      '(e.validity.rangeUnderflow||e.validity.rangeOverflow)&&' + +                      '("|date|datetime-local|month|number|range|time|week|".includes("|"+e.type+"|"))&&' + +                      '("range"==e.type||e.getAttribute("min")||e.getAttribute("max"))' + +                    '){' + source + '}'; +                  break; +                default: +                  emit('\'' + selector_string + '\'' + qsInvalid); +                  break; +              } +            } + +            // allow pseudo-elements starting with single colon (:) +            // :after, :before, :first-letter, :first-line +            else if ((match = selector.match(Patterns.pseudo_sng))) { +              source = 'if(' + D + '(e.nodeType==1)){' + source + '}'; +            } + +            // allow pseudo-elements starting with double colon (::) +            // ::after, ::before, ::marker, ::placeholder, ::inactive-selection, ::selection, ::-webkit-<foo-bar> +            else if ((match = selector.match(Patterns.pseudo_dbl))) { +              source = 'if(' + D + '(e.nodeType==1)){' + source + '}'; +            } + +            else { + +              // reset +              expr = false; +              status = false; + +              // process registered selector extensions +              for (expr in Selectors) { +                if ((match = selector.match(Selectors[expr].Expression))) { +                  result = Selectors[expr].Callback(match, source, mode, callback); +                  if ('match' in result) { match = result.match; } +                  vars = result.modvar; +                  if (mode) { +                     // add extra select() vars +                     vars && S_VARS.indexOf(vars) < 0 && (S_VARS[S_VARS.length] = vars); +                  } else { +                     // add extra match() vars +                     vars && M_VARS.indexOf(vars) < 0 && (M_VARS[M_VARS.length] = vars); +                  } +                  // extension source code +                  source = result.source; +                  // extension status code +                  status = result.status; +                  // break on status error +                  if (status) { break; } +                } +              } + +              if (!status) { +                emit('unknown pseudo-class selector \'' + selector + '\''); +                return ''; +              } + +              if (!expr) { +                emit('unknown token in selector \'' + selector + '\''); +                return ''; +              } + +            } +            break; + +        default: +          emit('\'' + selector_string + '\'' + qsInvalid); +          break; + +        } +        // end of switch symbol + +        if (!match) { +          emit('\'' + selector_string + '\'' + qsInvalid); +          return ''; +        } + +        // pop last component +        selector = match.pop(); +      } +      // end of while selector + +      return source; +    }, + +  // replace ':scope' pseudo-class with element references +  makeref = +    function(selectors, element) { +      return selectors.replace(/:scope/i, +        element.nodeName.toLowerCase() + +        (element.id ? '#' + element.id : '') + +        (element.className ? '.' + element.classList[0] : '')); +    }, + +  // equivalent of w3c 'closest' method +  ancestor = +    function _closest(selectors, element, callback) { + +      if ((/:scope/i).test(selectors)) { +        selectors = makeref(selectors, element); +      } + +      while (element) { +        if (match(selectors, element, callback)) break; +        element = element.parentElement; +      } +      return element; +    }, + +  match_assert = +    function(f, element, callback) { +      for (var i = 0, l = f.length, r = false; l > i; ++i) +        f[i](element, callback, null, false) && (r = true); +      return r; +    }, + +  match_collect = +    function(selectors, callback) { +      for (var i = 0, l = selectors.length, f = [ ]; l > i; ++i) +        f[i] = compile(selectors[i], false, callback); +      return { factory: f }; +    }, + +  // equivalent of w3c 'matches' method +  match = +    function _matches(selectors, element, callback) { + +      var expressions, parsed; + +      if (element && matchResolvers[selectors]) { +        return match_assert(matchResolvers[selectors].factory, element, callback); +      } + +      lastMatched = selectors; + +      // arguments validation +      if (arguments.length === 0) { +        emit(qsNotArgs, TypeError); +        return Config.VERBOSITY ? undefined : false; +      } else if (arguments[0] === '') { +        emit('\'\'' + qsInvalid); +        return Config.VERBOSITY ? undefined : false; +      } + +      // input NULL or UNDEFINED +      if (typeof selectors != 'string') { +        selectors = '' + selectors; +      } + +      if ((/:scope/i).test(selectors)) { +        selectors = makeref(selectors, element); +      } + +      // normalize input string +      parsed = selectors. +        replace(/\x00|\\$/g, '\ufffd'). +        replace(REX.CombineWSP, '\x20'). +        replace(REX.PseudosWSP, '$1'). +        replace(REX.TabCharWSP, '\t'). +        replace(REX.CommaGroup, ','). +        replace(REX.TrimSpaces, ''); + +      // parse, validate and split possible compound selectors +      if ((expressions = parsed.match(reValidator)) && expressions.join('') == parsed) { +        expressions = parsed.match(REX.SplitGroup); +        if (parsed[parsed.length - 1] == ',') { +          emit(qsInvalid); +          return Config.VERBOSITY ? undefined : false; +        } +      } else { +        emit('\'' + selectors + '\'' + qsInvalid); +        return Config.VERBOSITY ? undefined : false; +      } + +      matchResolvers[selectors] = match_collect(expressions, callback); + +      return match_assert(matchResolvers[selectors].factory, element, callback); +    }, + +  // equivalent of w3c 'querySelector' method +  first = +    function _querySelector(selectors, context, callback) { +      if (arguments.length === 0) { +        emit(qsNotArgs, TypeError); +      } +      return select(selectors, context, +        typeof callback == 'function' ? +        function firstMatch(element) { +          callback(element); +          return false; +        } : +        function firstMatch() { +          return false; +        } +      )[0] || null; +    }, + +  // equivalent of w3c 'querySelectorAll' method +  select = +    function _querySelectorAll(selectors, context, callback) { + +      var expressions, nodes, parsed, resolver; + +      context || (context = doc); + +      if (selectors) { +        if ((resolver = selectResolvers[selectors])) { +          if (resolver.context === context && resolver.callback === callback) { +            var f = resolver.factory, h = resolver.htmlset, n = resolver.nodeset, nodes = [ ]; +            if (n.length > 1) { +              for (var i = 0, l = n.length, list; l > i; ++i) { +                list = compat[n[i][0]](context, n[i].slice(1))(); +                if (f[i] !== null) { +                  f[i](list, callback, context, nodes); +                } else { +                  nodes = nodes.concat(list); +                } +              } +              if (l > 1 && nodes.length > 1) { +                nodes.sort(documentOrder); +                hasDupes && (nodes = unique(nodes)); +              } +            } else { +              if (f[0]) { +                nodes = f[0](h[0](), callback, context, nodes); +              } else { +                nodes = h[0](); +              } +            } +            return typeof callback == 'function' ? +              concatCall(nodes, callback) : nodes; +          } +        } +      } + +      lastSelected = selectors; + +      // arguments validation +      if (arguments.length === 0) { +        emit(qsNotArgs, TypeError); +        return Config.VERBOSITY ? undefined : none; +      } else if (arguments[0] === '') { +        emit('\'\'' + qsInvalid); +        return Config.VERBOSITY ? undefined : none; +      } else if (lastContext !== context) { +        lastContext = switchContext(context); +      } + +      // input NULL or UNDEFINED +      if (typeof selectors != 'string') { +        selectors = '' + selectors; +      } + +      if ((/:scope/i).test(selectors)) { +        selectors = makeref(selectors, context); +      } + +      // normalize input string +      parsed = selectors. +        replace(/\x00|\\$/g, '\ufffd'). +        replace(REX.CombineWSP, '\x20'). +        replace(REX.PseudosWSP, '$1'). +        replace(REX.TabCharWSP, '\t'). +        replace(REX.CommaGroup, ','). +        replace(REX.TrimSpaces, ''); + +      // parse, validate and split possible compound selectors +      if ((expressions = parsed.match(reValidator)) && expressions.join('') == parsed) { +        expressions = parsed.match(REX.SplitGroup); +        if (parsed[parsed.length - 1] == ',') { +          emit(qsInvalid); +          return Config.VERBOSITY ? undefined : false; +        } +      } else { +        emit('\'' + selectors + '\'' + qsInvalid); +        return Config.VERBOSITY ? undefined : false; +      } + +      // save/reuse factory and closure collection +      selectResolvers[selectors] = collect(expressions, context, callback); + +      nodes = selectResolvers[selectors].results; + +      return typeof callback == 'function' ? +        concatCall(nodes, callback) : nodes; +    }, + +  // optimize selectors avoiding duplicated checks +  optimize = +    function(selector, token) { +      var index = token.index, +      length = token[1].length + token[2].length; +      return selector.slice(0, index) + +        (' >+~'.indexOf(selector.charAt(index - 1)) > -1 ? +          (':['.indexOf(selector.charAt(index + length + 1)) > -1 ? +          '*' : '') : '') + selector.slice(index + length - (token[1] == '*' ? 1 : 0)); +    }, + +  // prepare factory resolvers and closure collections +  collect = +    function(selectors, context, callback) { +      var i, l, token, seen = { }, factory = [ ], htmlset = [ ], nodeset = [ ], results = [ ]; +      for (i = 0, l = selectors.length; l > i; ++i) { +        if (!seen[selectors[i]] && (seen[selectors[i]] = true)) { + +          if ((token = selectors[i].match(reOptimizer)) && token[1] != ':') { +            token[1] || (token[1] = '*'); +            selectors[i] = optimize(selectors[i], token); +          } else { +            token = ['', '*', '*']; +          } + +          nodeset[i] = token[1] + token[2]; +          htmlset[i] = compat[token[1]](context, token[2]); +          factory[i] = compile(selectors[i], true, null); + +          if (factory[i]) { +            factory[i](htmlset[i](), callback, context, results); +          } else { +            results = results.concat(htmlset[i]()); +          } + +        } +      } + +      if (l > 1) { +        results.sort(documentOrder); +        hasDupes && (results = unique(results)); +      } + +      return { +        callback: callback, +        context: context, +        factory: factory, +        htmlset: htmlset, +        nodeset: nodeset, +        results: results +      }; +    }, + +  // QSA placeholders to native references +  _closest, _matches, _querySelector, _querySelectorAll, + +  // overrides QSA methods (only for browsers) +  install = +    function(all) { + +      // save native QSA references +      _closest = Element.prototype.closest; +      _matches = Element.prototype.matches; +      _querySelector = Document.prototype.querySelector; +      _querySelectorAll = Document.prototype.querySelectorAll; + +      Element.prototype.closest = +        function closest() { +          var ctor = Object.getPrototypeOf(this).__proto__.__proto__.constructor.name; +          if (!('nodeType' in this)) { emit('\'closest\' called on an object that does not implement interface ' + ctor + '.', TypeError); } +          return arguments.length < 1 ? ancestor.apply(this, [ ]) : +                 arguments.length < 2 ? ancestor.apply(this, [ arguments[0], this ]) : +                                        ancestor.apply(this, [ arguments[0], this, typeof arguments[1] == 'function' ? arguments[1] : undefined ]); +        }; + +      Element.prototype.matches = +        function matches() { +          var ctor = Object.getPrototypeOf(this).__proto__.__proto__.constructor.name; +          if (!('nodeType' in this)) { emit('\'matches\' called on an object that does not implement interface ' + ctor + '.', TypeError); } +          return arguments.length < 1 ? match.apply(this, [ ]) : +                 arguments.length < 2 ? match.apply(this, [ arguments[0], this ]) : +                                        match.apply(this, [ arguments[0], this, typeof arguments[1] == 'function' ? arguments[1] : undefined ]); +        }; + +      Element.prototype.querySelector = +      Document.prototype.querySelector = +      DocumentFragment.prototype.querySelector = +        function querySelector() { +          var ctor = Object.getPrototypeOf(this).__proto__.__proto__.constructor.name; +          if (!('nodeType' in this)) { emit('\'querySelector\' called on an object that does not implement interface ' + ctor + '.', TypeError); } +          return arguments.length < 1 ? first.apply(this, [ ]) : +                 arguments.length < 2 ? first.apply(this, [ arguments[0], this ]) : +                                        first.apply(this, [ arguments[0], this, typeof arguments[1] == 'function' ? arguments[1] : undefined ]); +        }; + +      Element.prototype.querySelectorAll = +      Document.prototype.querySelectorAll = +      DocumentFragment.prototype.querySelectorAll = +        function querySelectorAll() { +          var ctor = Object.getPrototypeOf(this).__proto__.__proto__.constructor.name; +          if (!('nodeType' in this)) { emit('\'querySelectorAll\' called on an object that does not implement interface ' + ctor + '.', TypeError); } +          return arguments.length < 1 ? select.apply(this, [ ]) : +                 arguments.length < 2 ? select.apply(this, [ arguments[0], this ]) : +                                        select.apply(this, [ arguments[0], this, typeof arguments[1] == 'function' ? arguments[1] : undefined ]); +        }; + +      if (all) { +        document.addEventListener('load', function(e) { +          var c, d, r, s, t = e.target; +          if (/iframe/i.test(t.nodeName)) { +            c = '(' + Export + ')(this, ' + Factory + ');'; d = t.contentDocument; +            s = d.createElement('script'); s.textContent = c + 'NW.Dom.install()'; +            r = d.documentElement; r.removeChild(r.insertBefore(s, r.firstChild)); +          } +        }, true); +      } + +    }, + +  // restore QSA methods (only for browsers) +  uninstall = +    function() { +      // reinstates QSA native references +      Element.prototype.closest = _closest; +      Element.prototype.matches = _matches; +      Element.prototype.querySelector = +      Document.prototype.querySelector = +      DocumentFragment.prototype.querySelector = _querySelector; +      Element.prototype.querySelectorAll = +      Document.prototype.querySelectorAll = +      DocumentFragment.prototype.querySelectorAll = _querySelectorAll; +    }, + +  // empty set +  none = Array(), + +  // context +  lastContext, + +  // selector +  lastMatched, +  lastSelected, + +  // cached lambdas +  matchLambdas = { }, +  selectLambdas = { }, + +  // cached resolvers +  matchResolvers = { }, +  selectResolvers = { }, + +  // passed to resolvers +  Snapshot = { + +    doc: doc, +    from: doc, +    root: root, + +    byTag: byTag, + +    first: first, +    match: match, + +    ancestor: ancestor, + +    nthOfType: nthOfType, +    nthElement: nthElement, + +    hasAttributeNS: hasAttributeNS +  }, + +  // public exported methods/objects +  Dom = { + +    // exported cache objects + +    lastMatched: lastMatched, +    lastSelected: lastSelected, + +    matchLambdas: matchLambdas, +    selectLambdas: selectLambdas, + +    matchResolvers: matchResolvers, +    selectResolvers: selectResolvers, + +    // exported compiler macros + +    CFG: CFG, + +    M_BODY: M_BODY, +    S_BODY: S_BODY, +    M_TEST: M_TEST, +    S_TEST: S_TEST, + +    // exported engine methods + +    byId: byId, +    byTag: byTag, +    byClass: byClass, + +    match: match, +    first: first, +    select: select, +    closest: ancestor, + +    compile: compile, +    configure: configure, + +    emit: emit, +    Config: Config, +    Snapshot: Snapshot, + +    Version: version, + +    install: install, +    uninstall: uninstall, + +    Operators: Operators, +    Selectors: Selectors, + +    // register a new selector combinator symbol and its related function resolver +    registerCombinator: +      function(combinator, resolver) { +        var i = 0, l = combinator.length, symbol; +        for (; l > i; ++i) { +          if (combinator[i] != '=') { +            symbol = combinator[i]; +            break; +          } +        } +        if (CFG.combinators.indexOf(symbol) < 0) { +          CFG.combinators = CFG.combinators.replace('](', symbol + ']('); +          CFG.combinators = CFG.combinators.replace('])', symbol + '])'); +          Combinators[combinator] = resolver; +          setIdentifierSyntax(); +        } else { +          console.warn('Warning: the \'' + combinator + '\' combinator is already registered.'); +        } +      }, + +    // register a new attribute operator symbol and its related function resolver +    registerOperator: +      function(operator, resolver) { +        var i = 0, l = operator.length, symbol; +        for (; l > i; ++i) { +          if (operator[i] != '=') { +            symbol = operator[i]; +            break; +          } +        } +        if (CFG.operators.indexOf(symbol) < 0 && !Operators[operator]) { +          CFG.operators = CFG.operators.replace(']=', symbol + ']='); +          Operators[operator] = resolver; +          setIdentifierSyntax(); +        } else { +          console.warn('Warning: the \'' + operator + '\' operator is already registered.'); +        } +      }, + +    // register a new selector symbol and its related function resolver +    registerSelector: +      function(name, rexp, func) { +        Selectors[name] || (Selectors[name] = { +          Expression: rexp, +          Callback: func +        }); +      } + +  }; + +  initialize(doc); + +  return Dom; + +});  | 
