├── engines
└── rhino
│ ├── jars
│ └── htmlparser-1.2.1.jar
│ └── lib
│ └── htmlparser.js
├── package.json
├── example.js
├── README.md
└── lib
└── sizzle.js
/engines/rhino/jars/htmlparser-1.2.1.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/subtleGradient/htmlparser/master/engines/rhino/jars/htmlparser-1.2.1.jar
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "htmlparser",
3 | "description": "An HTML parser",
4 | "keywords": ["html", "parser", "dom"],
5 | "author": "George Moschovitis (http://www.gmosx.com/)",
6 | "contributors": [],
7 | "lib": ["lib"],
8 | "jars": ["engines/rhino/jars/htmlparser-1.2.1.jar"],
9 | "lean": ["lib", "engines"]
10 | }
11 |
--------------------------------------------------------------------------------
/example.js:
--------------------------------------------------------------------------------
1 | var HTMLParser = require("htmlparser").HTMLParser,
2 | sizzle = require("sizzle").sizzle;
3 |
4 | var html = '
hello
second
',
5 | parser = new HTMLParser(),
6 | document = parser.parse(html),
7 | $ = sizzle(document);
8 |
9 | $("div").forEach(function(el) {
10 | print(el.innerHTML);
11 | });
12 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | HTML Parser
2 | ===========
3 |
4 | The HTML Parser is an implementation of the HTML5 parsing algorithm packaged for [CommonJS](http://www.commonjs.org). It is based on the excellent [Validator.nu HTML parser](http://about.validator.nu/htmlparser/).
5 |
6 | The parser is compatible with [Sizzle](http://sizzlejs.com/) which is included in the distribution for convenience.
7 |
8 | This is part of the [Nitro](http://www.nitrojs.org/) ecosystem of Web Application development tools.
9 |
10 |
11 | Usage
12 | -----
13 |
14 | var HTMLParser = require("htmlparser").HTMLParser,
15 | sizzle = require("sizzle").sizzle;
16 |
17 | var html = 'hello
second
',
18 | parser = new HTMLParser(),
19 | document = parser.parse(html),
20 | $ = sizzle(document);
21 |
22 | $("div").forEach(function(el) {
23 | print(el.innerHTML);
24 | });
25 |
26 | print(document.toHTML());
27 | print(document);
28 |
29 |
30 | Credits
31 | -------
32 |
33 | * George Moschovitis
34 | * Bryan Berry
35 |
36 | Java HTML Parser
37 |
38 | * Copyright (c) 2005, 2006, 2007 Henri Sivonen
39 | * Copyright (c) 2007-2008 Mozilla Foundation
40 | * Portions of comments Copyright 2004-2007 Apple Computer, Inc., Mozilla Foundation, and Opera Software ASA.
41 |
42 |
43 | License
44 | -------
45 |
46 | Copyright (c) 2009-2010 George Moschovitis, [http://www.gmosx.com](http://www.gmosx.com)
47 |
48 | Permission is hereby granted, free of charge, to any person obtaining a copy
49 | of this software and associated documentation files (the "Software"), to
50 | deal in the Software without restriction, including without limitation the
51 | rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
52 | sell copies of the Software, and to permit persons to whom the Software is
53 | furnished to do so, subject to the following conditions:
54 |
55 | The above copyright notice and this permission notice shall be included in
56 | all copies or substantial portions of the Software.
57 |
58 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
59 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
60 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
61 | THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
62 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
63 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
64 |
--------------------------------------------------------------------------------
/engines/rhino/lib/htmlparser.js:
--------------------------------------------------------------------------------
1 | var JInputSource = Packages.org.xml.sax.InputSource,
2 | JStringReader = Packages.java.io.StringReader,
3 | JHtmlDocumentBuilder = Packages.nu.validator.htmlparser.dom.HtmlDocumentBuilder;
4 |
5 | var jparser = new JHtmlDocumentBuilder();
6 |
7 | var extend = function(Klass, Zuper) {
8 | Klass.prototype = Object.create(Zuper.prototype);
9 | Klass.prototype.constructor = Klass;
10 | }
11 |
12 | /**
13 | */
14 | exports.parse = function(html, options) {
15 | return (new HTMLParser(options)).parse(html);
16 | }
17 |
18 | /**
19 | * A HTML5 parser.
20 | *
21 | * Based on:
22 | * http://about.validator.nu/htmlparser/
23 | */
24 | var HTMLParser = exports.HTMLParser = function(options) {
25 | }
26 |
27 | HTMLParser.prototype.parseRaw = function(html) {
28 | var source = new JInputSource(new JStringReader(html));
29 | // source.setEncoding("UTF-8");
30 | return jparser.parse(source);
31 | }
32 |
33 | HTMLParser.prototype.parse = function(html) {
34 | return new HTMLDocument(this.parseRaw(html));
35 | }
36 |
37 | /**
38 | * An HTML Node.
39 | */
40 | var HTMLNode = function(jnode) {
41 | this._raw = jnode;
42 | }
43 |
44 | HTMLNode.prototype.getChildNodes = function() {
45 | return _nodelistToArray(this._raw.getChildNodes());
46 | }
47 |
48 | Object.defineProperty(HTMLNode.prototype, "nodeName", {
49 | get: function() {
50 | return String(this._raw.getNodeName());
51 | }
52 | });
53 |
54 | Object.defineProperty(HTMLNode.prototype, "nodeType", {
55 | get: function() {
56 | return Number(this._raw.getNodeType());
57 | }
58 | });
59 |
60 | Object.defineProperty(HTMLNode.prototype, "nodeValue", {
61 | get: function() {
62 | return String(this._raw.getNodeValue());
63 | }
64 | });
65 |
66 | HTMLNode.prototype.toString = function() {
67 | return this.nodeName;
68 | }
69 |
70 | var JDom2Sax = Packages.nu.validator.htmlparser.dom.Dom2Sax,
71 | JHtmlSerializer = Packages.nu.validator.htmlparser.sax.HtmlSerializer,
72 | JStringWriter = Packages.java.io.StringWriter;
73 |
74 | HTMLNode.prototype.toHTML = function() {
75 | var w = new JStringWriter(),
76 | s = new JHtmlSerializer(w);
77 |
78 | new JDom2Sax(s, s).parse(this._raw);
79 |
80 | return String(w.toString());
81 | }
82 |
83 | /**
84 | * HTML Document.
85 | */
86 | var HTMLDocument = function(jdocument) {
87 | this._raw = jdocument;
88 | }
89 |
90 | extend(HTMLDocument, HTMLNode);
91 |
92 | HTMLDocument.prototype.createElement = function(tagName) {
93 | return new HTMLElement(this._raw.createElement(tagName));
94 | }
95 |
96 | HTMLDocument.prototype.createComment = function(data) {
97 | return new HTMLElement(this._raw.createComment(data));
98 | }
99 |
100 | HTMLDocument.prototype.getElementById = function(id) {
101 | return new HTMLElement(this._raw.getElementById(id));
102 | }
103 |
104 | HTMLDocument.prototype.getElementsByTagName = function(tagname) {
105 | return _nodelistToArray(this._raw.getElementsByTagName(tagname));
106 | }
107 |
108 | Object.defineProperty(HTMLDocument.prototype, "documentElement", {
109 | get: function() {
110 | return new HTMLElement(this._raw.getDocumentElement());
111 | }
112 | });
113 |
114 | /**
115 | * HTML Element.
116 | */
117 | var HTMLElement = function(jelement) {
118 | this._raw = jelement;
119 | }
120 |
121 | extend(HTMLElement, HTMLNode);
122 |
123 | HTMLElement.prototype.appendChild = function(newChild) {
124 | return new HTMLElement(this._raw.appendChild(newChild._raw));
125 | }
126 |
127 | Object.defineProperty(HTMLElement.prototype, "checked", {
128 | get: function() {
129 | return this.hasAttribute("checked");
130 | }
131 | });
132 |
133 | Object.defineProperty(HTMLElement.prototype, "childNodes", {
134 | get: function() {
135 | return _nodelistToArray(this._raw.getChildNodes());
136 | }
137 | });
138 |
139 | Object.defineProperty(HTMLElement.prototype, "className", {
140 | get: function() {
141 | return this.getAttribute("class");
142 | }
143 | });
144 |
145 | HTMLElement.prototype.compareDocumentPosition = function(other) {
146 | return Number(this._raw.compareDocumentPosition(other));
147 | }
148 |
149 | Object.defineProperty(HTMLElement.prototype, "disabled", {
150 | get: function() {
151 | return this.hasAttribute("disabled");
152 | }
153 | });
154 |
155 | Object.defineProperty(HTMLElement.prototype, "firstChild", {
156 | get: function() {
157 | var n = this._raw.getFirstChild();
158 | return n ? new HTMLElement(n) : null;
159 | }
160 | });
161 |
162 | HTMLElement.prototype.getAttribute = function(name) {
163 | return String(this._raw.getAttribute(name));
164 | }
165 |
166 | HTMLElement.prototype.getAttributeNode = function(name) {
167 | var n = this._raw.getAttributeNode(name);
168 | return n ? new HTMLElement(n) : null;
169 | }
170 |
171 | HTMLElement.prototype.getElementsByTagName = function(tagname) {
172 | return _nodelistToArray(this._raw.getElementsByTagName(tagname));
173 | }
174 |
175 | HTMLElement.prototype.hasAttribute = function(name) {
176 | return this._raw.hasAttribute(name);
177 | }
178 |
179 | Object.defineProperty(HTMLElement.prototype, "href", {
180 | get: function() {
181 | return String(this.getAttribute("href"));
182 | }
183 | });
184 |
185 | Object.defineProperty(HTMLElement.prototype, "innerHTML", {
186 | get: function() {
187 | return String(this._raw.getTextContent());
188 | },
189 | set: function(content) {
190 | return String(this._raw.setTextContent(content));
191 | }
192 | });
193 |
194 | HTMLElement.prototype.insertBefore = function(newChild, refChild) {
195 | return new HTMLElement(this._raw.insertBefore(newChild._raw, refChild._raw));
196 | }
197 |
198 | Object.defineProperty(HTMLElement.prototype, "lastChild", {
199 | get: function() {
200 | var n = this._raw.getLastChild();
201 | return n ? new HTMLElement(n) : null;
202 | }
203 | });
204 |
205 | Object.defineProperty(HTMLElement.prototype, "nextSibling", {
206 | get: function() {
207 | var n = this._raw.getNextSibling();
208 | return n ? new HTMLElement(n) : null;
209 | }
210 | });
211 |
212 | Object.defineProperty(HTMLElement.prototype, "ownerDocument", {
213 | get: function() {
214 | return new HTMLElement(this._raw.getOwnerDocument());
215 | }
216 | });
217 |
218 | Object.defineProperty(HTMLElement.prototype, "parentNode", {
219 | get: function() {
220 | var n = this._raw.getParentNode();
221 | return n ? new HTMLElement(n) : null;
222 | }
223 | });
224 |
225 | Object.defineProperty(HTMLElement.prototype, "previousSibling", {
226 | get: function() {
227 | var n = this._raw.getPreviousSibling();
228 | return n ? new HTMLElement(n) : null;
229 | }
230 | });
231 |
232 | HTMLElement.prototype.removeChild = function(oldChild) {
233 | return new HTMLElement(this._raw.removeChild(oldChild._raw));
234 | }
235 |
236 | Object.defineProperty(HTMLElement.prototype, "selected", {
237 | get: function() {
238 | return this.hasAttribute("selected");
239 | }
240 | });
241 |
242 | Object.defineProperty(HTMLElement.prototype, "textContent", {
243 | get: function() {
244 | return String(this._raw.getTextContent());
245 | }
246 | });
247 |
248 | Object.defineProperty(HTMLElement.prototype, "type", {
249 | get: function() {
250 | return String(this.getAttribute("type"));
251 | }
252 | });
253 |
254 | var _nodelistToArray = function(nodelist) {
255 | var arr = [];
256 |
257 | for (var i = 0; i < nodelist.getLength(); i++) {
258 | arr.push(new HTMLElement(nodelist.item(i)));
259 | }
260 |
261 | return arr;
262 | }
263 |
--------------------------------------------------------------------------------
/lib/sizzle.js:
--------------------------------------------------------------------------------
1 | exports.sizzle = function(document) {
2 | var window = exports;
3 |
4 |
5 | /*!
6 | * Sizzle CSS Selector Engine - v1.0
7 | * Copyright 2009, The Dojo Foundation
8 | * Released under the MIT, BSD, and GPL Licenses.
9 | * More information: http://sizzlejs.com/
10 | */
11 | (function(){
12 |
13 | var chunker = /((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^[\]]*\]|['"][^'"]*['"]|[^[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g,
14 | done = 0,
15 | toString = Object.prototype.toString,
16 | hasDuplicate = false,
17 | baseHasDuplicate = true;
18 |
19 | // Here we check if the JavaScript engine is using some sort of
20 | // optimization where it does not always call our comparision
21 | // function. If that is the case, discard the hasDuplicate value.
22 | // Thus far that includes Google Chrome.
23 | [0, 0].sort(function(){
24 | baseHasDuplicate = false;
25 | return 0;
26 | });
27 |
28 | var Sizzle = function(selector, context, results, seed) {
29 | results = results || [];
30 | var origContext = context = context || document;
31 |
32 | if ( context.nodeType !== 1 && context.nodeType !== 9 ) {
33 | return [];
34 | }
35 |
36 | if ( !selector || typeof selector !== "string" ) {
37 | return results;
38 | }
39 |
40 | var parts = [], m, set, checkSet, check, mode, extra, prune = true, contextXML = isXML(context),
41 | soFar = selector;
42 |
43 | // Reset the position of the chunker regexp (start from head)
44 | while ( (chunker.exec(""), m = chunker.exec(soFar)) !== null ) {
45 | soFar = m[3];
46 |
47 | parts.push( m[1] );
48 |
49 | if ( m[2] ) {
50 | extra = m[3];
51 | break;
52 | }
53 | }
54 |
55 | if ( parts.length > 1 && origPOS.exec( selector ) ) {
56 | if ( parts.length === 2 && Expr.relative[ parts[0] ] ) {
57 | set = posProcess( parts[0] + parts[1], context );
58 | } else {
59 | set = Expr.relative[ parts[0] ] ?
60 | [ context ] :
61 | Sizzle( parts.shift(), context );
62 |
63 | while ( parts.length ) {
64 | selector = parts.shift();
65 |
66 | if ( Expr.relative[ selector ] )
67 | selector += parts.shift();
68 |
69 | set = posProcess( selector, set );
70 | }
71 | }
72 | } else {
73 | // Take a shortcut and set the context if the root selector is an ID
74 | // (but not if it'll be faster if the inner selector is an ID)
75 | if ( !seed && parts.length > 1 && context.nodeType === 9 && !contextXML &&
76 | Expr.match.ID.test(parts[0]) && !Expr.match.ID.test(parts[parts.length - 1]) ) {
77 | var ret = Sizzle.find( parts.shift(), context, contextXML );
78 | context = ret.expr ? Sizzle.filter( ret.expr, ret.set )[0] : ret.set[0];
79 | }
80 |
81 | if ( context ) {
82 | var ret = seed ?
83 | { expr: parts.pop(), set: makeArray(seed) } :
84 | Sizzle.find( parts.pop(), parts.length === 1 && (parts[0] === "~" || parts[0] === "+") && context.parentNode ? context.parentNode : context, contextXML );
85 | set = ret.expr ? Sizzle.filter( ret.expr, ret.set ) : ret.set;
86 |
87 | if ( parts.length > 0 ) {
88 | checkSet = makeArray(set);
89 | } else {
90 | prune = false;
91 | }
92 |
93 | while ( parts.length ) {
94 | var cur = parts.pop(), pop = cur;
95 |
96 | if ( !Expr.relative[ cur ] ) {
97 | cur = "";
98 | } else {
99 | pop = parts.pop();
100 | }
101 |
102 | if ( pop == null ) {
103 | pop = context;
104 | }
105 |
106 | Expr.relative[ cur ]( checkSet, pop, contextXML );
107 | }
108 | } else {
109 | checkSet = parts = [];
110 | }
111 | }
112 |
113 | if ( !checkSet ) {
114 | checkSet = set;
115 | }
116 |
117 | if ( !checkSet ) {
118 | throw "Syntax error, unrecognized expression: " + (cur || selector);
119 | }
120 |
121 | if ( toString.call(checkSet) === "[object Array]" ) {
122 | if ( !prune ) {
123 | results.push.apply( results, checkSet );
124 | } else if ( context && context.nodeType === 1 ) {
125 | for ( var i = 0; checkSet[i] != null; i++ ) {
126 | if ( checkSet[i] && (checkSet[i] === true || checkSet[i].nodeType === 1 && contains(context, checkSet[i])) ) {
127 | results.push( set[i] );
128 | }
129 | }
130 | } else {
131 | for ( var i = 0; checkSet[i] != null; i++ ) {
132 | if ( checkSet[i] && checkSet[i].nodeType === 1 ) {
133 | results.push( set[i] );
134 | }
135 | }
136 | }
137 | } else {
138 | makeArray( checkSet, results );
139 | }
140 |
141 | if ( extra ) {
142 | Sizzle( extra, origContext, results, seed );
143 | Sizzle.uniqueSort( results );
144 | }
145 |
146 | return results;
147 | };
148 |
149 | Sizzle.uniqueSort = function(results){
150 | if ( sortOrder ) {
151 | hasDuplicate = baseHasDuplicate;
152 | results.sort(sortOrder);
153 |
154 | if ( hasDuplicate ) {
155 | for ( var i = 1; i < results.length; i++ ) {
156 | if ( results[i] === results[i-1] ) {
157 | results.splice(i--, 1);
158 | }
159 | }
160 | }
161 | }
162 |
163 | return results;
164 | };
165 |
166 | Sizzle.matches = function(expr, set){
167 | return Sizzle(expr, null, null, set);
168 | };
169 |
170 | Sizzle.find = function(expr, context, isXML){
171 | var set, match;
172 |
173 | if ( !expr ) {
174 | return [];
175 | }
176 |
177 | for ( var i = 0, l = Expr.order.length; i < l; i++ ) {
178 | var type = Expr.order[i], match;
179 |
180 | if ( (match = Expr.leftMatch[ type ].exec( expr )) ) {
181 | var left = match[1];
182 | match.splice(1,1);
183 |
184 | if ( left.substr( left.length - 1 ) !== "\\" ) {
185 | match[1] = (match[1] || "").replace(/\\/g, "");
186 | set = Expr.find[ type ]( match, context, isXML );
187 | if ( set != null ) {
188 | expr = expr.replace( Expr.match[ type ], "" );
189 | break;
190 | }
191 | }
192 | }
193 | }
194 |
195 | if ( !set ) {
196 | set = context.getElementsByTagName("*");
197 | }
198 |
199 | return {set: set, expr: expr};
200 | };
201 |
202 | Sizzle.filter = function(expr, set, inplace, not){
203 | var old = expr, result = [], curLoop = set, match, anyFound,
204 | isXMLFilter = set && set[0] && isXML(set[0]);
205 |
206 | while ( expr && set.length ) {
207 | for ( var type in Expr.filter ) {
208 | if ( (match = Expr.match[ type ].exec( expr )) != null ) {
209 | var filter = Expr.filter[ type ], found, item;
210 | anyFound = false;
211 |
212 | if ( curLoop == result ) {
213 | result = [];
214 | }
215 |
216 | if ( Expr.preFilter[ type ] ) {
217 | match = Expr.preFilter[ type ]( match, curLoop, inplace, result, not, isXMLFilter );
218 |
219 | if ( !match ) {
220 | anyFound = found = true;
221 | } else if ( match === true ) {
222 | continue;
223 | }
224 | }
225 |
226 | if ( match ) {
227 | for ( var i = 0; (item = curLoop[i]) != null; i++ ) {
228 | if ( item ) {
229 | found = filter( item, match, i, curLoop );
230 | var pass = not ^ !!found;
231 |
232 | if ( inplace && found != null ) {
233 | if ( pass ) {
234 | anyFound = true;
235 | } else {
236 | curLoop[i] = false;
237 | }
238 | } else if ( pass ) {
239 | result.push( item );
240 | anyFound = true;
241 | }
242 | }
243 | }
244 | }
245 |
246 | if ( found !== undefined ) {
247 | if ( !inplace ) {
248 | curLoop = result;
249 | }
250 |
251 | expr = expr.replace( Expr.match[ type ], "" );
252 |
253 | if ( !anyFound ) {
254 | return [];
255 | }
256 |
257 | break;
258 | }
259 | }
260 | }
261 |
262 | // Improper expression
263 | if ( expr == old ) {
264 | if ( anyFound == null ) {
265 | throw "Syntax error, unrecognized expression: " + expr;
266 | } else {
267 | break;
268 | }
269 | }
270 |
271 | old = expr;
272 | }
273 |
274 | return curLoop;
275 | };
276 |
277 | var Expr = Sizzle.selectors = {
278 | order: [ "ID", "NAME", "TAG" ],
279 | match: {
280 | ID: /#((?:[\w\u00c0-\uFFFF-]|\\.)+)/,
281 | CLASS: /\.((?:[\w\u00c0-\uFFFF-]|\\.)+)/,
282 | NAME: /\[name=['"]*((?:[\w\u00c0-\uFFFF-]|\\.)+)['"]*\]/,
283 | ATTR: /\[\s*((?:[\w\u00c0-\uFFFF-]|\\.)+)\s*(?:(\S?=)\s*(['"]*)(.*?)\3|)\s*\]/,
284 | TAG: /^((?:[\w\u00c0-\uFFFF\*-]|\\.)+)/,
285 | CHILD: /:(only|nth|last|first)-child(?:\((even|odd|[\dn+-]*)\))?/,
286 | POS: /:(nth|eq|gt|lt|first|last|even|odd)(?:\((\d*)\))?(?=[^-]|$)/,
287 | PSEUDO: /:((?:[\w\u00c0-\uFFFF-]|\\.)+)(?:\((['"]*)((?:\([^\)]+\)|[^\2\(\)]*)+)\2\))?/
288 | },
289 | leftMatch: {},
290 | attrMap: {
291 | "class": "className",
292 | "for": "htmlFor"
293 | },
294 | attrHandle: {
295 | href: function(elem){
296 | return elem.getAttribute("href");
297 | }
298 | },
299 | relative: {
300 | "+": function(checkSet, part, isXML){
301 | var isPartStr = typeof part === "string",
302 | isTag = isPartStr && !/\W/.test(part),
303 | isPartStrNotTag = isPartStr && !isTag;
304 |
305 | if ( isTag && !isXML ) {
306 | part = part.toUpperCase();
307 | }
308 |
309 | for ( var i = 0, l = checkSet.length, elem; i < l; i++ ) {
310 | if ( (elem = checkSet[i]) ) {
311 | while ( (elem = elem.previousSibling) && elem.nodeType !== 1 ) {}
312 |
313 | checkSet[i] = isPartStrNotTag || elem && elem.nodeName === part ?
314 | elem || false :
315 | elem === part;
316 | }
317 | }
318 |
319 | if ( isPartStrNotTag ) {
320 | Sizzle.filter( part, checkSet, true );
321 | }
322 | },
323 | ">": function(checkSet, part, isXML){
324 | var isPartStr = typeof part === "string";
325 |
326 | if ( isPartStr && !/\W/.test(part) ) {
327 | part = isXML ? part : part.toUpperCase();
328 |
329 | for ( var i = 0, l = checkSet.length; i < l; i++ ) {
330 | var elem = checkSet[i];
331 | if ( elem ) {
332 | var parent = elem.parentNode;
333 | checkSet[i] = parent.nodeName === part ? parent : false;
334 | }
335 | }
336 | } else {
337 | for ( var i = 0, l = checkSet.length; i < l; i++ ) {
338 | var elem = checkSet[i];
339 | if ( elem ) {
340 | checkSet[i] = isPartStr ?
341 | elem.parentNode :
342 | elem.parentNode === part;
343 | }
344 | }
345 |
346 | if ( isPartStr ) {
347 | Sizzle.filter( part, checkSet, true );
348 | }
349 | }
350 | },
351 | "": function(checkSet, part, isXML){
352 | var doneName = done++, checkFn = dirCheck;
353 |
354 | if ( !/\W/.test(part) ) {
355 | var nodeCheck = part = isXML ? part : part.toUpperCase();
356 | checkFn = dirNodeCheck;
357 | }
358 |
359 | checkFn("parentNode", part, doneName, checkSet, nodeCheck, isXML);
360 | },
361 | "~": function(checkSet, part, isXML){
362 | var doneName = done++, checkFn = dirCheck;
363 |
364 | if ( typeof part === "string" && !/\W/.test(part) ) {
365 | var nodeCheck = part = isXML ? part : part.toUpperCase();
366 | checkFn = dirNodeCheck;
367 | }
368 |
369 | checkFn("previousSibling", part, doneName, checkSet, nodeCheck, isXML);
370 | }
371 | },
372 | find: {
373 | ID: function(match, context, isXML){
374 | if ( typeof context.getElementById !== "undefined" && !isXML ) {
375 | var m = context.getElementById(match[1]);
376 | return m ? [m] : [];
377 | }
378 | },
379 | NAME: function(match, context, isXML){
380 | if ( typeof context.getElementsByName !== "undefined" ) {
381 | var ret = [], results = context.getElementsByName(match[1]);
382 |
383 | for ( var i = 0, l = results.length; i < l; i++ ) {
384 | if ( results[i].getAttribute("name") === match[1] ) {
385 | ret.push( results[i] );
386 | }
387 | }
388 |
389 | return ret.length === 0 ? null : ret;
390 | }
391 | },
392 | TAG: function(match, context){
393 | return context.getElementsByTagName(match[1]);
394 | }
395 | },
396 | preFilter: {
397 | CLASS: function(match, curLoop, inplace, result, not, isXML){
398 | match = " " + match[1].replace(/\\/g, "") + " ";
399 |
400 | if ( isXML ) {
401 | return match;
402 | }
403 |
404 | for ( var i = 0, elem; (elem = curLoop[i]) != null; i++ ) {
405 | if ( elem ) {
406 | if ( not ^ (elem.className && (" " + elem.className + " ").indexOf(match) >= 0) ) {
407 | if ( !inplace )
408 | result.push( elem );
409 | } else if ( inplace ) {
410 | curLoop[i] = false;
411 | }
412 | }
413 | }
414 |
415 | return false;
416 | },
417 | ID: function(match){
418 | return match[1].replace(/\\/g, "");
419 | },
420 | TAG: function(match, curLoop){
421 | for ( var i = 0; curLoop[i] === false; i++ ){}
422 | return curLoop[i] && isXML(curLoop[i]) ? match[1] : match[1].toUpperCase();
423 | },
424 | CHILD: function(match){
425 | if ( match[1] == "nth" ) {
426 | // parse equations like 'even', 'odd', '5', '2n', '3n+2', '4n-1', '-n+6'
427 | var test = /(-?)(\d*)n((?:\+|-)?\d*)/.exec(
428 | match[2] == "even" && "2n" || match[2] == "odd" && "2n+1" ||
429 | !/\D/.test( match[2] ) && "0n+" + match[2] || match[2]);
430 |
431 | // calculate the numbers (first)n+(last) including if they are negative
432 | match[2] = (test[1] + (test[2] || 1)) - 0;
433 | match[3] = test[3] - 0;
434 | }
435 |
436 | // TODO: Move to normal caching system
437 | match[0] = done++;
438 |
439 | return match;
440 | },
441 | ATTR: function(match, curLoop, inplace, result, not, isXML){
442 | var name = match[1].replace(/\\/g, "");
443 |
444 | if ( !isXML && Expr.attrMap[name] ) {
445 | match[1] = Expr.attrMap[name];
446 | }
447 |
448 | if ( match[2] === "~=" ) {
449 | match[4] = " " + match[4] + " ";
450 | }
451 |
452 | return match;
453 | },
454 | PSEUDO: function(match, curLoop, inplace, result, not){
455 | if ( match[1] === "not" ) {
456 | // If we're dealing with a complex expression, or a simple one
457 | if ( ( chunker.exec(match[3]) || "" ).length > 1 || /^\w/.test(match[3]) ) {
458 | match[3] = Sizzle(match[3], null, null, curLoop);
459 | } else {
460 | var ret = Sizzle.filter(match[3], curLoop, inplace, true ^ not);
461 | if ( !inplace ) {
462 | result.push.apply( result, ret );
463 | }
464 | return false;
465 | }
466 | } else if ( Expr.match.POS.test( match[0] ) || Expr.match.CHILD.test( match[0] ) ) {
467 | return true;
468 | }
469 |
470 | return match;
471 | },
472 | POS: function(match){
473 | match.unshift( true );
474 | return match;
475 | }
476 | },
477 | filters: {
478 | enabled: function(elem){
479 | return elem.disabled === false && elem.type !== "hidden";
480 | },
481 | disabled: function(elem){
482 | return elem.disabled === true;
483 | },
484 | checked: function(elem){
485 | return elem.checked === true;
486 | },
487 | selected: function(elem){
488 | // Accessing this property makes selected-by-default
489 | // options in Safari work properly
490 | elem.parentNode.selectedIndex;
491 | return elem.selected === true;
492 | },
493 | parent: function(elem){
494 | return !!elem.firstChild;
495 | },
496 | empty: function(elem){
497 | return !elem.firstChild;
498 | },
499 | has: function(elem, i, match){
500 | return !!Sizzle( match[3], elem ).length;
501 | },
502 | header: function(elem){
503 | return /h\d/i.test( elem.nodeName );
504 | },
505 | text: function(elem){
506 | return "text" === elem.type;
507 | },
508 | radio: function(elem){
509 | return "radio" === elem.type;
510 | },
511 | checkbox: function(elem){
512 | return "checkbox" === elem.type;
513 | },
514 | file: function(elem){
515 | return "file" === elem.type;
516 | },
517 | password: function(elem){
518 | return "password" === elem.type;
519 | },
520 | submit: function(elem){
521 | return "submit" === elem.type;
522 | },
523 | image: function(elem){
524 | return "image" === elem.type;
525 | },
526 | reset: function(elem){
527 | return "reset" === elem.type;
528 | },
529 | button: function(elem){
530 | return "button" === elem.type || elem.nodeName.toUpperCase() === "BUTTON";
531 | },
532 | input: function(elem){
533 | return /input|select|textarea|button/i.test(elem.nodeName);
534 | }
535 | },
536 | setFilters: {
537 | first: function(elem, i){
538 | return i === 0;
539 | },
540 | last: function(elem, i, match, array){
541 | return i === array.length - 1;
542 | },
543 | even: function(elem, i){
544 | return i % 2 === 0;
545 | },
546 | odd: function(elem, i){
547 | return i % 2 === 1;
548 | },
549 | lt: function(elem, i, match){
550 | return i < match[3] - 0;
551 | },
552 | gt: function(elem, i, match){
553 | return i > match[3] - 0;
554 | },
555 | nth: function(elem, i, match){
556 | return match[3] - 0 == i;
557 | },
558 | eq: function(elem, i, match){
559 | return match[3] - 0 == i;
560 | }
561 | },
562 | filter: {
563 | PSEUDO: function(elem, match, i, array){
564 | var name = match[1], filter = Expr.filters[ name ];
565 |
566 | if ( filter ) {
567 | return filter( elem, i, match, array );
568 | } else if ( name === "contains" ) {
569 | return (elem.textContent || elem.innerText || "").indexOf(match[3]) >= 0;
570 | } else if ( name === "not" ) {
571 | var not = match[3];
572 |
573 | for ( var i = 0, l = not.length; i < l; i++ ) {
574 | if ( not[i] === elem ) {
575 | return false;
576 | }
577 | }
578 |
579 | return true;
580 | }
581 | },
582 | CHILD: function(elem, match){
583 | var type = match[1], node = elem;
584 | switch (type) {
585 | case 'only':
586 | case 'first':
587 | while ( (node = node.previousSibling) ) {
588 | if ( node.nodeType === 1 ) return false;
589 | }
590 | if ( type == 'first') return true;
591 | node = elem;
592 | case 'last':
593 | while ( (node = node.nextSibling) ) {
594 | if ( node.nodeType === 1 ) return false;
595 | }
596 | return true;
597 | case 'nth':
598 | var first = match[2], last = match[3];
599 |
600 | if ( first == 1 && last == 0 ) {
601 | return true;
602 | }
603 |
604 | var doneName = match[0],
605 | parent = elem.parentNode;
606 |
607 | if ( parent && (parent.sizcache !== doneName || !elem.nodeIndex) ) {
608 | var count = 0;
609 | for ( node = parent.firstChild; node; node = node.nextSibling ) {
610 | if ( node.nodeType === 1 ) {
611 | node.nodeIndex = ++count;
612 | }
613 | }
614 | parent.sizcache = doneName;
615 | }
616 |
617 | var diff = elem.nodeIndex - last;
618 | if ( first == 0 ) {
619 | return diff == 0;
620 | } else {
621 | return ( diff % first == 0 && diff / first >= 0 );
622 | }
623 | }
624 | },
625 | ID: function(elem, match){
626 | return elem.nodeType === 1 && elem.getAttribute("id") === match;
627 | },
628 | TAG: function(elem, match){
629 | return (match === "*" && elem.nodeType === 1) || elem.nodeName === match;
630 | },
631 | CLASS: function(elem, match){
632 | return (" " + (elem.className || elem.getAttribute("class")) + " ")
633 | .indexOf( match ) > -1;
634 | },
635 | ATTR: function(elem, match){
636 | var name = match[1],
637 | result = Expr.attrHandle[ name ] ?
638 | Expr.attrHandle[ name ]( elem ) :
639 | elem[ name ] != null ?
640 | elem[ name ] :
641 | elem.getAttribute( name ),
642 | value = result + "",
643 | type = match[2],
644 | check = match[4];
645 |
646 | return result == null ?
647 | type === "!=" :
648 | type === "=" ?
649 | value === check :
650 | type === "*=" ?
651 | value.indexOf(check) >= 0 :
652 | type === "~=" ?
653 | (" " + value + " ").indexOf(check) >= 0 :
654 | !check ?
655 | value && result !== false :
656 | type === "!=" ?
657 | value != check :
658 | type === "^=" ?
659 | value.indexOf(check) === 0 :
660 | type === "$=" ?
661 | value.substr(value.length - check.length) === check :
662 | type === "|=" ?
663 | value === check || value.substr(0, check.length + 1) === check + "-" :
664 | false;
665 | },
666 | POS: function(elem, match, i, array){
667 | var name = match[2], filter = Expr.setFilters[ name ];
668 |
669 | if ( filter ) {
670 | return filter( elem, i, match, array );
671 | }
672 | }
673 | }
674 | };
675 |
676 | var origPOS = Expr.match.POS;
677 |
678 | for ( var type in Expr.match ) {
679 | Expr.match[ type ] = new RegExp( Expr.match[ type ].source + /(?![^\[]*\])(?![^\(]*\))/.source );
680 | Expr.leftMatch[ type ] = new RegExp( /(^(?:.|\r|\n)*?)/.source + Expr.match[ type ].source );
681 | }
682 |
683 | var makeArray = function(array, results) {
684 | array = Array.prototype.slice.call( array, 0 );
685 |
686 | if ( results ) {
687 | results.push.apply( results, array );
688 | return results;
689 | }
690 |
691 | return array;
692 | };
693 |
694 | // Perform a simple check to determine if the browser is capable of
695 | // converting a NodeList to an array using builtin methods.
696 | try {
697 | Array.prototype.slice.call( document.documentElement.childNodes, 0 );
698 |
699 | // Provide a fallback method if it does not work
700 | } catch(e){
701 | makeArray = function(array, results) {
702 | var ret = results || [];
703 |
704 | if ( toString.call(array) === "[object Array]" ) {
705 | Array.prototype.push.apply( ret, array );
706 | } else {
707 | if ( typeof array.length === "number" ) {
708 | for ( var i = 0, l = array.length; i < l; i++ ) {
709 | ret.push( array[i] );
710 | }
711 | } else {
712 | for ( var i = 0; array[i]; i++ ) {
713 | ret.push( array[i] );
714 | }
715 | }
716 | }
717 |
718 | return ret;
719 | };
720 | }
721 |
722 | var sortOrder;
723 |
724 | if ( document.documentElement.compareDocumentPosition ) {
725 | sortOrder = function( a, b ) {
726 | if ( !a.compareDocumentPosition || !b.compareDocumentPosition ) {
727 | if ( a == b ) {
728 | hasDuplicate = true;
729 | }
730 | return 0;
731 | }
732 |
733 | var ret = a.compareDocumentPosition(b) & 4 ? -1 : a === b ? 0 : 1;
734 | if ( ret === 0 ) {
735 | hasDuplicate = true;
736 | }
737 | return ret;
738 | };
739 | } else if ( "sourceIndex" in document.documentElement ) {
740 | sortOrder = function( a, b ) {
741 | if ( !a.sourceIndex || !b.sourceIndex ) {
742 | if ( a == b ) {
743 | hasDuplicate = true;
744 | }
745 | return 0;
746 | }
747 |
748 | var ret = a.sourceIndex - b.sourceIndex;
749 | if ( ret === 0 ) {
750 | hasDuplicate = true;
751 | }
752 | return ret;
753 | };
754 | } else if ( document.createRange ) {
755 | sortOrder = function( a, b ) {
756 | if ( !a.ownerDocument || !b.ownerDocument ) {
757 | if ( a == b ) {
758 | hasDuplicate = true;
759 | }
760 | return 0;
761 | }
762 |
763 | var aRange = a.ownerDocument.createRange(), bRange = b.ownerDocument.createRange();
764 | aRange.setStart(a, 0);
765 | aRange.setEnd(a, 0);
766 | bRange.setStart(b, 0);
767 | bRange.setEnd(b, 0);
768 | var ret = aRange.compareBoundaryPoints(Range.START_TO_END, bRange);
769 | if ( ret === 0 ) {
770 | hasDuplicate = true;
771 | }
772 | return ret;
773 | };
774 | }
775 |
776 | // Check to see if the browser returns elements by name when
777 | // querying by getElementById (and provide a workaround)
778 | (function(){
779 | // We're going to inject a fake input element with a specified name
780 | var form = document.createElement("div"),
781 | id = "script" + (new Date).getTime();
782 | form.innerHTML = "";
783 |
784 | // Inject it into the root element, check its status, and remove it quickly
785 | var root = document.documentElement;
786 | root.insertBefore( form, root.firstChild );
787 |
788 | // The workaround has to do additional checks after a getElementById
789 | // Which slows things down for other browsers (hence the branching)
790 | if ( !!document.getElementById( id ) ) {
791 | Expr.find.ID = function(match, context, isXML){
792 | if ( typeof context.getElementById !== "undefined" && !isXML ) {
793 | var m = context.getElementById(match[1]);
794 | return m ? m.id === match[1] || typeof m.getAttributeNode !== "undefined" && m.getAttributeNode("id").nodeValue === match[1] ? [m] : undefined : [];
795 | }
796 | };
797 |
798 | Expr.filter.ID = function(elem, match){
799 | var node = typeof elem.getAttributeNode !== "undefined" && elem.getAttributeNode("id");
800 | return elem.nodeType === 1 && node && node.nodeValue === match;
801 | };
802 | }
803 |
804 | root.removeChild( form );
805 | root = form = null; // release memory in IE
806 | })();
807 |
808 | (function(){
809 | // Check to see if the browser returns only elements
810 | // when doing getElementsByTagName("*")
811 |
812 | // Create a fake element
813 | var div = document.createElement("div");
814 | div.appendChild( document.createComment("") );
815 |
816 | // Make sure no comments are found
817 | if ( div.getElementsByTagName("*").length > 0 ) {
818 | Expr.find.TAG = function(match, context){
819 | var results = context.getElementsByTagName(match[1]);
820 |
821 | // Filter out possible comments
822 | if ( match[1] === "*" ) {
823 | var tmp = [];
824 |
825 | for ( var i = 0; results[i]; i++ ) {
826 | if ( results[i].nodeType === 1 ) {
827 | tmp.push( results[i] );
828 | }
829 | }
830 |
831 | results = tmp;
832 | }
833 |
834 | return results;
835 | };
836 | }
837 |
838 | // Check to see if an attribute returns normalized href attributes
839 | div.innerHTML = "";
840 | if (false) {
841 | // if ( div.firstChild && typeof div.firstChild.getAttribute !== "undefined" &&
842 | // div.firstChild.getAttribute("href") !== "#" ) {
843 | Expr.attrHandle.href = function(elem){
844 | return elem.getAttribute("href", 2);
845 | };
846 | }
847 |
848 | div = null; // release memory in IE
849 | })();
850 |
851 | if ( document.querySelectorAll ) (function(){
852 | var oldSizzle = Sizzle, div = document.createElement("div");
853 | div.innerHTML = "";
854 |
855 | // Safari can't handle uppercase or unicode characters when
856 | // in quirks mode.
857 | if ( div.querySelectorAll && div.querySelectorAll(".TEST").length === 0 ) {
858 | return;
859 | }
860 |
861 | Sizzle = function(query, context, extra, seed){
862 | context = context || document;
863 |
864 | // Only use querySelectorAll on non-XML documents
865 | // (ID selectors don't work in non-HTML documents)
866 | if ( !seed && context.nodeType === 9 && !isXML(context) ) {
867 | try {
868 | return makeArray( context.querySelectorAll(query), extra );
869 | } catch(e){}
870 | }
871 |
872 | return oldSizzle(query, context, extra, seed);
873 | };
874 |
875 | for ( var prop in oldSizzle ) {
876 | Sizzle[ prop ] = oldSizzle[ prop ];
877 | }
878 |
879 | div = null; // release memory in IE
880 | })();
881 |
882 | if ( document.getElementsByClassName && document.documentElement.getElementsByClassName ) (function(){
883 | var div = document.createElement("div");
884 | div.innerHTML = "";
885 |
886 | // Opera can't find a second classname (in 9.6)
887 | if ( div.getElementsByClassName("e").length === 0 )
888 | return;
889 |
890 | // Safari caches class attributes, doesn't catch changes (in 3.2)
891 | div.lastChild.className = "e";
892 |
893 | if ( div.getElementsByClassName("e").length === 1 )
894 | return;
895 |
896 | Expr.order.splice(1, 0, "CLASS");
897 | Expr.find.CLASS = function(match, context, isXML) {
898 | if ( typeof context.getElementsByClassName !== "undefined" && !isXML ) {
899 | return context.getElementsByClassName(match[1]);
900 | }
901 | };
902 |
903 | div = null; // release memory in IE
904 | })();
905 |
906 | function dirNodeCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) {
907 | var sibDir = dir == "previousSibling" && !isXML;
908 | for ( var i = 0, l = checkSet.length; i < l; i++ ) {
909 | var elem = checkSet[i];
910 | if ( elem ) {
911 | if ( sibDir && elem.nodeType === 1 ){
912 | elem.sizcache = doneName;
913 | elem.sizset = i;
914 | }
915 | elem = elem[dir];
916 | var match = false;
917 |
918 | while ( elem ) {
919 | if ( elem.sizcache === doneName ) {
920 | match = checkSet[elem.sizset];
921 | break;
922 | }
923 |
924 | if ( elem.nodeType === 1 && !isXML ){
925 | elem.sizcache = doneName;
926 | elem.sizset = i;
927 | }
928 |
929 | if ( elem.nodeName === cur ) {
930 | match = elem;
931 | break;
932 | }
933 |
934 | elem = elem[dir];
935 | }
936 |
937 | checkSet[i] = match;
938 | }
939 | }
940 | }
941 |
942 | function dirCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) {
943 | var sibDir = dir == "previousSibling" && !isXML;
944 | for ( var i = 0, l = checkSet.length; i < l; i++ ) {
945 | var elem = checkSet[i];
946 | if ( elem ) {
947 | if ( sibDir && elem.nodeType === 1 ) {
948 | elem.sizcache = doneName;
949 | elem.sizset = i;
950 | }
951 | elem = elem[dir];
952 | var match = false;
953 |
954 | while ( elem ) {
955 | if ( elem.sizcache === doneName ) {
956 | match = checkSet[elem.sizset];
957 | break;
958 | }
959 |
960 | if ( elem.nodeType === 1 ) {
961 | if ( !isXML ) {
962 | elem.sizcache = doneName;
963 | elem.sizset = i;
964 | }
965 | if ( typeof cur !== "string" ) {
966 | if ( elem === cur ) {
967 | match = true;
968 | break;
969 | }
970 |
971 | } else if ( Sizzle.filter( cur, [elem] ).length > 0 ) {
972 | match = elem;
973 | break;
974 | }
975 | }
976 |
977 | elem = elem[dir];
978 | }
979 |
980 | checkSet[i] = match;
981 | }
982 | }
983 | }
984 |
985 | var contains = document.compareDocumentPosition ? function(a, b){
986 | return a.compareDocumentPosition(b) & 16;
987 | } : function(a, b){
988 | return a !== b && (a.contains ? a.contains(b) : true);
989 | };
990 |
991 | var isXML = function(elem){
992 | return elem.nodeType === 9;
993 | return elem.nodeType === 9 && elem.documentElement.nodeName !== "HTML" ||
994 | !!elem.ownerDocument && elem.ownerDocument.documentElement.nodeName !== "HTML";
995 | };
996 |
997 | var posProcess = function(selector, context){
998 | var tmpSet = [], later = "", match,
999 | root = context.nodeType ? [context] : context;
1000 |
1001 | // Position selectors must be done after the filter
1002 | // And so must :not(positional) so we move all PSEUDOs to the end
1003 | while ( (match = Expr.match.PSEUDO.exec( selector )) ) {
1004 | later += match[0];
1005 | selector = selector.replace( Expr.match.PSEUDO, "" );
1006 | }
1007 |
1008 | selector = Expr.relative[selector] ? selector + "*" : selector;
1009 |
1010 | for ( var i = 0, l = root.length; i < l; i++ ) {
1011 | Sizzle( selector, root[i], tmpSet );
1012 | }
1013 |
1014 | return Sizzle.filter( later, tmpSet );
1015 | };
1016 |
1017 | // EXPOSE
1018 | window.Sizzle = Sizzle;
1019 |
1020 | })();
1021 |
1022 |
1023 |
1024 | return exports.Sizzle;
1025 | }
1026 |
--------------------------------------------------------------------------------