nwmatcher/ 0000755 0001750 0001750 00000000000 12316015515 011201 5 ustar wmb wmb nwmatcher/.npmignore 0000644 0001750 0001750 00000000113 12316015515 013173 0 ustar wmb wmb bin/
build/
dist/
lib/
test/
.gitattributes
.gitignore
.npmignore
Makefile
nwmatcher/bin/ 0000755 0001750 0001750 00000000000 12407423423 011753 5 ustar wmb wmb nwmatcher/build/ 0000755 0001750 0001750 00000000000 12316015515 012300 5 ustar wmb wmb nwmatcher/build/HEADER 0000644 0001750 0001750 00000000177 12316015515 013160 0 ustar wmb wmb /*!
* NWMatcher 1.3.3 - Fast CSS3 Selector Engine
* Copyright (C) 2007-2014 Diego Perini
* See http://nwbox.com/license
*/
nwmatcher/build/conf/ 0000755 0001750 0001750 00000000000 12316015515 013225 5 ustar wmb wmb nwmatcher/build/conf/jsl.default.conf 0000755 0001750 0001750 00000013547 12316015515 016324 0 ustar wmb wmb #
# Configuration File for JavaScript Lint 0.3.0
# Developed by Matthias Miller (http://www.JavaScriptLint.com)
#
# This configuration file can be used to lint a collection of scripts, or to enable
# or disable warnings for scripts that are linted via the command line.
#
### Warnings
# Enable or disable warnings based on requirements.
# Use "+WarningName" to display or "-WarningName" to suppress.
#
+no_return_value # function {0} does not always return a value
+duplicate_formal # duplicate formal argument {0}
+equal_as_assign # test for equality (==) mistyped as assignment (=)?{0}
+var_hides_arg # variable {0} hides argument
+redeclared_var # redeclaration of {0} {1}
+anon_no_return_value # anonymous function does not always return a value
+missing_semicolon # missing semicolon
+meaningless_block # meaningless block; curly braces have no impact
+comma_separated_stmts # multiple statements separated by commas (use semicolons?)
+unreachable_code # unreachable code
+missing_break # missing break statement
+missing_break_for_last_case # missing break statement for last case in switch
+comparison_type_conv # comparisons against null, 0, true, false, or an empty string allowing implicit type conversion (use === or !==)
+inc_dec_within_stmt # increment (++) and decrement (--) operators used as part of greater statement
+useless_void # use of the void type may be unnecessary (void is always undefined)
+multiple_plus_minus # unknown order of operations for successive plus (e.g. x+++y) or minus (e.g. x---y) signs
+use_of_label # use of label
-block_without_braces # block statement without curly braces
+leading_decimal_point # leading decimal point may indicate a number or an object member
+trailing_decimal_point # trailing decimal point may indicate a number or an object member
+octal_number # leading zeros make an octal number
+nested_comment # nested comment
+misplaced_regex # regular expressions should be preceded by a left parenthesis, assignment, colon, or comma
+ambiguous_newline # unexpected end of line; it is ambiguous whether these lines are part of the same statement
+empty_statement # empty statement or extra semicolon
-missing_option_explicit # the "option explicit" control comment is missing
+partial_option_explicit # the "option explicit" control comment, if used, must be in the first script tag
+dup_option_explicit # duplicate "option explicit" control comment
+useless_assign # useless assignment
+ambiguous_nested_stmt # block statements containing block statements should use curly braces to resolve ambiguity
+ambiguous_else_stmt # the else statement could be matched with one of multiple if statements (use curly braces to indicate intent)
+missing_default_case # missing default case in switch statement
+duplicate_case_in_switch # duplicate case in switch statements
+default_not_at_end # the default case is not at the end of the switch statement
+legacy_cc_not_understood # couldn't understand control comment using /*@keyword@*/ syntax
+jsl_cc_not_understood # couldn't understand control comment using /*jsl:keyword*/ syntax
+useless_comparison # useless comparison; comparing identical expressions
+with_statement # with statement hides undeclared variables; use temporary variable instead
+trailing_comma_in_array # extra comma is not recommended in array initializers
+assign_to_function_call # assignment to a function call
+parseint_missing_radix # parseInt missing radix parameter
### Output format
# Customize the format of the error message.
# __FILE__ indicates current file path
# __FILENAME__ indicates current file name
# __LINE__ indicates current line
# __ERROR__ indicates error message
#
# Visual Studio syntax (default):
+output-format __FILE__(__LINE__): __ERROR__
# Alternative syntax:
#+output-format __FILE__:__LINE__: __ERROR__
### Context
# Show the in-line position of the error.
# Use "+context" to display or "-context" to suppress.
#
+context
### Semicolons
# By default, assignments of an anonymous function to a variable or
# property (such as a function prototype) must be followed by a semicolon.
#
+lambda_assign_requires_semicolon
### Control Comments
# Both JavaScript Lint and the JScript interpreter confuse each other with the syntax for
# the /*@keyword@*/ control comments and JScript conditional comments. (The latter is
# enabled in JScript with @cc_on@). The /*jsl:keyword*/ syntax is preferred for this reason,
# although legacy control comments are enabled by default for backward compatibility.
#
+legacy_control_comments
### JScript Function Extensions
# JScript allows member functions to be defined like this:
# function MyObj() { /*constructor*/ }
# function MyObj.prototype.go() { /*member function*/ }
#
# It also allows events to be attached like this:
# function window::onload() { /*init page*/ }
#
# This is a Microsoft-only JavaScript extension. Enable this setting to allow them.
#
-jscript_function_extensions
### Defining identifiers
# By default, "option explicit" is enabled on a per-file basis.
# To enable this for all files, use "+always_use_option_explicit"
-always_use_option_explicit
# Define certain identifiers of which the lint is not aware.
# (Use this in conjunction with the "undeclared identifier" warning.)
#
# Common uses for webpages might be:
#+define window
#+define document
### Files
# Specify which files to lint
# Use "+recurse" to enable recursion (disabled by default).
# To add a set of files, use "+process FileName", "+process Folder\Path\*.js",
# or "+process Folder\Path\*.htm".
#
#+process jsl-test.js
nwmatcher/build/conf/jsl.conf 0000755 0001750 0001750 00000013547 12316015515 014701 0 ustar wmb wmb #
# Configuration File for JavaScript Lint 0.3.0
# Developed by Matthias Miller (http://www.JavaScriptLint.com)
#
# This configuration file can be used to lint a collection of scripts, or to enable
# or disable warnings for scripts that are linted via the command line.
#
### Warnings
# Enable or disable warnings based on requirements.
# Use "+WarningName" to display or "-WarningName" to suppress.
#
-no_return_value # function {0} does not always return a value
+duplicate_formal # duplicate formal argument {0}
-equal_as_assign # test for equality (==) mistyped as assignment (=)?{0}
+var_hides_arg # variable {0} hides argument
+redeclared_var # redeclaration of {0} {1}
-anon_no_return_value # anonymous function does not always return a value
-missing_semicolon # missing semicolon
+meaningless_block # meaningless block; curly braces have no impact
+comma_separated_stmts # multiple statements separated by commas (use semicolons?)
+unreachable_code # unreachable code
+missing_break # missing break statement
+missing_break_for_last_case # missing break statement for last case in switch
-comparison_type_conv # comparisons against null, 0, true, false, or an empty string allowing implicit type conversion (use === or !==)
-inc_dec_within_stmt # increment (++) and decrement (--) operators used as part of greater statement
+useless_void # use of the void type may be unnecessary (void is always undefined)
+multiple_plus_minus # unknown order of operations for successive plus (e.g. x+++y) or minus (e.g. x---y) signs
+use_of_label # use of label
-block_without_braces # block statement without curly braces
+leading_decimal_point # leading decimal point may indicate a number or an object member
+trailing_decimal_point # trailing decimal point may indicate a number or an object member
+octal_number # leading zeros make an octal number
+nested_comment # nested comment
+misplaced_regex # regular expressions should be preceded by a left parenthesis, assignment, colon, or comma
-ambiguous_newline # unexpected end of line; it is ambiguous whether these lines are part of the same statement
+empty_statement # empty statement or extra semicolon
-missing_option_explicit # the "option explicit" control comment is missing
+partial_option_explicit # the "option explicit" control comment, if used, must be in the first script tag
+dup_option_explicit # duplicate "option explicit" control comment
+useless_assign # useless assignment
-ambiguous_nested_stmt # block statements containing block statements should use curly braces to resolve ambiguity
+ambiguous_else_stmt # the else statement could be matched with one of multiple if statements (use curly braces to indicate intent)
+missing_default_case # missing default case in switch statement
+duplicate_case_in_switch # duplicate case in switch statements
+default_not_at_end # the default case is not at the end of the switch statement
+legacy_cc_not_understood # couldn't understand control comment using /*@keyword@*/ syntax
+jsl_cc_not_understood # couldn't understand control comment using /*jsl:keyword*/ syntax
+useless_comparison # useless comparison; comparing identical expressions
+with_statement # with statement hides undeclared variables; use temporary variable instead
+trailing_comma_in_array # extra comma is not recommended in array initializers
+assign_to_function_call # assignment to a function call
+parseint_missing_radix # parseInt missing radix parameter
### Output format
# Customize the format of the error message.
# __FILE__ indicates current file path
# __FILENAME__ indicates current file name
# __LINE__ indicates current line
# __ERROR__ indicates error message
#
# Visual Studio syntax (default):
+output-format __FILE__(__LINE__): __ERROR__
# Alternative syntax:
#+output-format __FILE__:__LINE__: __ERROR__
### Context
# Show the in-line position of the error.
# Use "+context" to display or "-context" to suppress.
#
+context
### Semicolons
# By default, assignments of an anonymous function to a variable or
# property (such as a function prototype) must be followed by a semicolon.
#
+lambda_assign_requires_semicolon
### Control Comments
# Both JavaScript Lint and the JScript interpreter confuse each other with the syntax for
# the /*@keyword@*/ control comments and JScript conditional comments. (The latter is
# enabled in JScript with @cc_on@). The /*jsl:keyword*/ syntax is preferred for this reason,
# although legacy control comments are enabled by default for backward compatibility.
#
+legacy_control_comments
### JScript Function Extensions
# JScript allows member functions to be defined like this:
# function MyObj() { /*constructor*/ }
# function MyObj.prototype.go() { /*member function*/ }
#
# It also allows events to be attached like this:
# function window::onload() { /*init page*/ }
#
# This is a Microsoft-only JavaScript extension. Enable this setting to allow them.
#
-jscript_function_extensions
### Defining identifiers
# By default, "option explicit" is enabled on a per-file basis.
# To enable this for all files, use "+always_use_option_explicit"
-always_use_option_explicit
# Define certain identifiers of which the lint is not aware.
# (Use this in conjunction with the "undeclared identifier" warning.)
#
# Common uses for webpages might be:
#+define window
#+define document
### Files
# Specify which files to lint
# Use "+recurse" to enable recursion (disabled by default).
# To add a set of files, use "+process FileName", "+process Folder\Path\*.js",
# or "+process Folder\Path\*.htm".
#
#+process jsl-test.js
nwmatcher/build/scripts/ 0000755 0001750 0001750 00000000000 12316015515 013767 5 ustar wmb wmb nwmatcher/build/scripts/nwpacker.js 0000755 0001750 0001750 00000001544 12316015515 016146 0 ustar wmb wmb /*
* SpiderMonkey wrapper to compress Javascript source files,
* uses Dean Edwards (http://dean.edwards.name/packer/)
*
* Author: Diego Perini
*
* Usage: fusecomp.js < input > output (uses stdin/stdout)
*
* Depends on correctly installed SpiderMonkey executable (js)
*
* Released under the Creative Commons license:
* http://creativecommons.org/licenses/by/3.0/
*/
// import Dean Edwards project files
load("build/packer/base2.js");
load("build/packer/packer.js");
// read file from stdin
function _readFile(from) {
var outstr = '', line = '';
while ((line = readline()) != null) {
outstr += line + '\x0a';
}
return outstr;
}
// read from input pack and send to output
(function minify() {
// create new packer instance
var packer = new Packer();
// shrink!
print(packer.pack(_readFile(), 0, 1, 1));
})();
nwmatcher/build/scripts/nwtestjs.sh 0000755 0001750 0001750 00000001353 12316015515 016211 0 ustar wmb wmb #!/bin/bash
echo -ne "NW: VM loading test, building test units..."
# retrieve build infos
VERSION=`cat ${SOURCES}build/VERSION`
REVISION=1
# set used variables
BASEDIR=`pwd`
PKGNAME="nwmatcher"
RELEASE=`date +%Y%m%d%H%M%S`
# set source
SOURCES=${1}
if [ "${SOURCES}x" == 'x' ]; then
pushd . &> /dev/null
cd ..; SOURCES=`pwd`
popd &> /dev/null
fi
# check platform
PLATFORM=`uname -s`
if [ $PLATFORM == 'Darwin' ]; then
JS=bin/js_macos
elif [ $PLATFORM == 'Linux' ]; then
JS=bin/js_linux
elif [ $PLATFORM == 'Windows' ]; then
JS=bin/js.exe
fi
pusdh . &> /dev/null
$JS test/jsvm/load_test.js < test/jsvm/load_test.html
if [ $? == '0' ]; then
echo 'PASSED'
elif [ $? != '0' ]; then
echo 'FAILED'
fi
popd &> /dev/null
exit 0
nwmatcher/build/scripts/nwjslint.sh 0000755 0001750 0001750 00000001510 12316015515 016173 0 ustar wmb wmb #!/bin/bash
echo -ne "NW: running javascript lint on sources"
# set sources
SOURCES=${1}
if [ "${SOURCES}x" == 'x' ]; then
pushd . &> /dev/null
cd ..; SOURCES=`pwd`
popd &> /dev/null
fi
# check platform
PLATFORM=`uname -s`
# set platform specifick executables
if [ $PLATFORM == 'Darwin' ]; then
JSL=bin/jsl_macos
elif [ $PLATFORM == 'Linux' ]; then
JSL=bin/jsl_linux
elif [ $PLATFORM == 'Windows' ]; then
JSL=bin/jsl.exe
fi
# save current working path
pusdh . &> /dev/null
# enter root path
cd $SOURCES
> $SOURCES/dist/lint.log
for item in `find $SOURCES/src -type d`
do {
sources=`ls $item/*.js 2>/dev/null`
for file in $sources
do {
$JSL -conf build/conf/jsl.conf -nologo -nofilelisting -nosummary -process $file >> $SOURCES/dist/lint.log
echo -ne "."
} done
} done
echo ""
popd &> /dev/null
exit 0
nwmatcher/build/scripts/nwpackjs.sh 0000755 0001750 0001750 00000003030 12316015515 016142 0 ustar wmb wmb #!/bin/bash
echo -ne "NW: building distribution from sources"
# retrieve build infos
VERSION=`cat ${SOURCES}build/VERSION`
REVISION=1
# set used variables
BASEDIR=`pwd`
PKGNAME="nwmatcher"
RELEASE=`date +%Y%m%d%H%M%S`
# set sources
SOURCES=${1}
if [ "${SOURCES}x" == 'x' ]; then
pushd . &> /dev/null
cd ..; SOURCES=`pwd`
popd &> /dev/null
fi
# check working platform
PLATFORM=`uname -s`
# set platform specifick executables
if [ $PLATFORM == 'Darwin' ]; then
JSMIN=bin/jsmin_macos
JSVM=bin/js_macos
elif [ $PLATFORM == 'Linux' ]; then
JSMIN=bin/jsmin_linux
JSVM=bin/js_linux
elif [ $PLATFORM == 'Windows' ]; then
JSMIN=bin/jsmin.exe
JSVM=bin/js.exe
fi
pushd . &> /dev/null
cd $SOURCES
# ensure empty
> dist/$PKGNAME-src.js
> dist/$PKGNAME-min.js
cat build/HEADER >> dist/$PKGNAME-pac.js
# add selector engine to source file
cat src/nwmatcher.js >> dist/$PKGNAME-src.js
# add selector engine to minified file
cat src/nwmatcher.js | $JSMIN | tr -d "\n" >> dist/$PKGNAME-min.js
# minification of variables and privates
echo ""
echo -ne "NW: starting minification, takes time please wait, "
$JSVM build/scripts/nwpacker.js < dist/nwmatcher-src.js >> dist/nwmatcher-pac.js
echo -ne "complete..."
echo ""
# build a compressed version of the minified file
gzip -c -n9 dist/$PKGNAME-pac.js > dist/$PKGNAME-zip.js
# build a versioned file name of the minified file
#cp dist/$PKGNAME-pac.js dist/$PKGNAME-$RELEASE.js
# now copy packed file to the real nwmatcher.js
cp dist/nwmatcher-pac.js dist/nwmatcher.js
popd &> /dev/null
exit 0
nwmatcher/build/packer/ 0000755 0001750 0001750 00000000000 12316015515 013545 5 ustar wmb wmb nwmatcher/build/packer/packer.js 0000644 0001750 0001750 00000040776 12316015515 015366 0 ustar wmb wmb /*
Packer version 3.1 - copyright 2004-2008, Dean Edwards
http://www.opensource.org/licenses/mit-license.php
*/
// timestamp: Mon, 30 Mar 2009 18:26:18
new function() { /////////////// BEGIN: CLOSURE ///////////////
new base2.Package(this, {
imports: "Function2,Enumerable"
});
eval(this.imports);
var IGNORE = RegGrp.IGNORE;
var KEYS = "~";
var REMOVE = "";
var SPACE = " ";
// =========================================================================
// packer/Parser.js
// =========================================================================
var Parser = RegGrp.extend({
put: function(expression, replacement) {
if (typeOf(expression) == "string") {
expression = Parser.dictionary.exec(expression);
}
this.base(expression, replacement);
}
}, {
dictionary: new RegGrp({
OPERATOR: /return|typeof|[\[(\^=,{}:;&|!*?]/.source,
CONDITIONAL: /\/\*@\w*|\w*@\*\/|\/\/@\w*|@\w+/.source,
COMMENT1: /\/\/[^\n]*/.source,
COMMENT2: /\/\*[^*]*\*+([^\/][^*]*\*+)*\//.source,
REGEXP: /\/(\\[\/\\]|[^*\/])(\\.|[^\/\n\\])*\/[gim]*/.source,
STRING1: /'(\\.|[^'\\])*'/.source,
STRING2: /"(\\.|[^"\\])*"/.source
})
});
// =========================================================================
// packer/Words.js
// =========================================================================
var Words = Collection.extend({
add: function(word) {
if (!this.has(word)) this.base(word);
word = this.get(word);
if (!word.index) {
word.index = this.size();
}
word.count++;
return word;
},
sort: function(sorter) {
return this.base(sorter || function(word1, word2) {
// sort by frequency
return (word2.count - word1.count) || (word1.index - word2.index);
});
}
}, {
Item: {
constructor: function(word) {
this.toString = K(word);
},
index: 0,
count: 0,
encoded: ""
}
});
// =========================================================================
// packer/Encoder.js
// =========================================================================
var Encoder = Base.extend({
constructor: function(pattern, encoder, ignore) {
this.parser = new Parser(ignore);
if (pattern) this.parser.put(pattern, "");
this.encoder = encoder;
},
parser: null,
encoder: Undefined,
search: function(script) {
var words = new Words;
this.parser.putAt(-1, function(word) {
words.add(word);
});
this.parser.exec(script);
return words;
},
encode: function(script) {
var words = this.search(script);
words.sort();
var index = 0;
forEach (words, function(word) {
word.encoded = this.encoder(index++);
}, this);
this.parser.putAt(-1, function(word) {
return words.get(word).encoded;
});
return this.parser.exec(script);
}
});
// =========================================================================
// packer/Privates.js
// =========================================================================
var Privates = Encoder.extend({
constructor: function() {
return this.base(Privates.PATTERN, function(index) {
return "_" + Packer.encode62(index);
}, Privates.IGNORE);
}
}, {
IGNORE: {
CONDITIONAL: IGNORE,
"(OPERATOR)(REGEXP)": IGNORE
},
PATTERN: /\b_[\da-zA-Z$][\w$]*\b/g
});
// =========================================================================
// packer/Base62.js
// =========================================================================
var Base62 = Encoder.extend({
encode: function(script) {
var words = this.search(script);
words.sort();
var encoded = new Collection; // a dictionary of base62 -> base10
var size = words.size();
for (var i = 0; i < size; i++) {
encoded.put(Packer.encode62(i), i);
}
function replacement(word) {
return words["#" + word].replacement;
};
var empty = K("");
var index = 0;
forEach (words, function(word) {
if (encoded.has(word)) {
word.index = encoded.get(word);
word.toString = empty;
} else {
while (words.has(Packer.encode62(index))) index++;
word.index = index++;
if (word.count == 1) {
word.toString = empty;
}
}
word.replacement = Packer.encode62(word.index);
if (word.replacement.length == word.toString().length) {
word.toString = empty;
}
});
// sort by encoding
words.sort(function(word1, word2) {
return word1.index - word2.index;
});
// trim unencoded words
words = words.slice(0, this.getKeyWords(words).split("|").length);
script = script.replace(this.getPattern(words), replacement);
/* build the packed script */
var p = this.escape(script);
var a = "[]";
var c = this.getCount(words);
var k = this.getKeyWords(words);
var e = this.getEncoder(words);
var d = this.getDecoder(words);
// the whole thing
return format(Base62.UNPACK, p,a,c,k,e,d);
},
search: function(script) {
var words = new Words;
forEach (script.match(Base62.WORDS), words.add, words);
return words;
},
escape: function(script) {
// Single quotes wrap the final string so escape them.
// Also, escape new lines (required by conditional comments).
return script.replace(/([\\'])/g, "\\$1").replace(/[\r\n]+/g, "\\n");
},
getCount: function(words) {
return words.size() || 1;
},
getDecoder: function(words) {
// returns a pattern used for fast decoding of the packed script
var trim = new RegGrp({
"(\\d)(\\|\\d)+\\|(\\d)": "$1-$3",
"([a-z])(\\|[a-z])+\\|([a-z])": "$1-$3",
"([A-Z])(\\|[A-Z])+\\|([A-Z])": "$1-$3",
"\\|": ""
});
var pattern = trim.exec(words.map(function(word) {
if (word.toString()) return word.replacement;
return "";
}).slice(0, 62).join("|"));
if (!pattern) return "^$";
pattern = "[" + pattern + "]";
var size = words.size();
if (size > 62) {
pattern = "(" + pattern + "|";
var c = Packer.encode62(size).charAt(0);
if (c > "9") {
pattern += "[\\\\d";
if (c >= "a") {
pattern += "a";
if (c >= "z") {
pattern += "-z";
if (c >= "A") {
pattern += "A";
if (c > "A") pattern += "-" + c;
}
} else if (c == "b") {
pattern += "-" + c;
}
}
pattern += "]";
} else if (c == 9) {
pattern += "\\\\d";
} else if (c == 2) {
pattern += "[12]";
} else if (c == 1) {
pattern += "1";
} else {
pattern += "[1-" + c + "]";
}
pattern += "\\\\w)";
}
return pattern;
},
getEncoder: function(words) {
var size = words.size();
return Base62["ENCODE" + (size > 10 ? size > 36 ? 62 : 36 : 10)];
},
getKeyWords: function(words) {
return words.map(String).join("|").replace(/\|+$/, "");
},
getPattern: function(words) {
words = words.map(String).join("|").replace(/\|{2,}/g, "|").replace(/^\|+|\|+$/g, "") || "\\x0";
return new RegExp("\\b(" + words + ")\\b", "g");
}
}, {
WORDS: /\b[\da-zA-Z]\b|\w{2,}/g,
ENCODE10: "String",
ENCODE36: "function(c){return c.toString(36)}",
ENCODE62: "function(c){return(c<62?'':e(parseInt(c/62)))+((c=c%62)>35?String.fromCharCode(c+29):c.toString(36))}",
UNPACK: "eval(function(p,a,c,k,e,r){e=%5;if('0'.replace(0,e)==0){while(c--)r[e(c)]=k[c];" +
"k=[function(e){return r[e]||e}];e=function(){return'%6'};c=1};while(c--)if(k[c])p=p." +
"replace(new RegExp('\\\\b'+e(c)+'\\\\b','g'),k[c]);return p}('%1',%2,%3,'%4'.split('|'),0,{}))"
});
// =========================================================================
// packer/Packer.js
// =========================================================================
global.Packer = Base.extend({
constructor: function() {
this.minifier = new Minifier;
this.shrinker = new Shrinker;
this.privates = new Privates;
this.base62 = new Base62;
},
minifier: null,
shrinker: null,
privates: null,
base62: null,
pack: function(script, base62, shrink, privates) {
script = this.minifier.minify(script);
if (shrink) script = this.shrinker.shrink(script);
if (privates) script = this.privates.encode(script);
if (base62) script = this.base62.encode(script);
return script;
}
}, {
version: "3.1",
init: function() {
eval("var e=this.encode62=" + Base62.ENCODE62);
},
data: new Parser({
"STRING1": IGNORE,
'STRING2': IGNORE,
"CONDITIONAL": IGNORE, // conditional comments
"(OPERATOR)\\s*(REGEXP)": "$1$2"
}),
encode52: function(c) {
// Base52 encoding (a-Z)
function encode(c) {
return (c < 52 ? '' : encode(parseInt(c / 52))) +
((c = c % 52) > 25 ? String.fromCharCode(c + 39) : String.fromCharCode(c + 97));
};
var encoded = encode(c);
if (/^(do|if|in)$/.test(encoded)) encoded = encoded.slice(1) + 0;
return encoded;
}
});
// =========================================================================
// packer/Minifier.js
// =========================================================================
var Minifier = Base.extend({
minify: function(script) {
// packing with no additional options
script += "\n";
script = script.replace(Minifier.CONTINUE, "");
script = Minifier.comments.exec(script);
script = Minifier.clean.exec(script);
script = Minifier.whitespace.exec(script);
script = Minifier.concat.exec(script);
return script;
}
}, {
CONTINUE: /\\\r?\n/g,
init: function() {
this.concat = new Parser(this.concat).merge(Packer.data);
extend(this.concat, "exec", function(script) {
var parsed = this.base(script);
while (parsed != script) {
script = parsed;
parsed = this.base(script);
}
return parsed;
});
forEach.csv("comments,clean,whitespace", function(name) {
this[name] = Packer.data.union(new Parser(this[name]));
}, this);
this.conditionalComments = this.comments.copy();
this.conditionalComments.putAt(-1, " $3");
this.whitespace.removeAt(2); // conditional comments
this.comments.removeAt(2);
},
clean: {
"\\(\\s*([^;)]*)\\s*;\\s*([^;)]*)\\s*;\\s*([^;)]*)\\)": "($1;$2;$3)", // for (;;) loops
"throw[^};]+[};]": IGNORE, // a safari 1.3 bug
";+\\s*([};])": "$1"
},
comments: {
";;;[^\\n]*\\n": REMOVE,
"(COMMENT1)\\n\\s*(REGEXP)?": "\n$3",
"(COMMENT2)\\s*(REGEXP)?": function(match, comment, $2, regexp) {
if (/^\/\*@/.test(comment) && /@\*\/$/.test(comment)) {
comment = Minifier.conditionalComments.exec(comment);
} else {
comment = "";
}
return comment + " " + (regexp || "");
}
},
concat: {
"(STRING1)\\+(STRING1)": function(match, a, $2, b) {
return a.slice(0, -1) + b.slice(1);
},
"(STRING2)\\+(STRING2)": function(match, a, $2, b) {
return a.slice(0, -1) + b.slice(1);
}
},
whitespace: {
"\\/\\/@[^\\n]*\\n": IGNORE,
"@\\s+\\b": "@ ", // protect conditional comments
"\\b\\s+@": " @",
"(\\d)\\s+(\\.\\s*[a-z\\$_\\[(])": "$1 $2", // http://dean.edwards.name/weblog/2007/04/packer3/#comment84066
"([+-])\\s+([+-])": "$1 $2", // c = a++ +b;
"(\\w)\\s+([\\u0080-\\uffff])": "$1 $2", // http://code.google.com/p/base2/issues/detail?id=78
"\\b\\s+\\$\\s+\\b": " $ ", // var $ in
"\\$\\s+\\b": "$ ", // object$ in
"\\b\\s+\\$": " $", // return $object
// "\\b\\s+#": " #", // CSS
"\\b\\s+\\b": SPACE,
"\\s+": REMOVE
}
});
// =========================================================================
// packer/Shrinker.js
// =========================================================================
var Shrinker = Base.extend({
decodeData: function(script) {
// put strings and regular expressions back
var data = this._data; // encoded strings and regular expressions
delete this._data;
return script.replace(Shrinker.ENCODED_DATA, function(match, index) {
return data[index];
});
},
encodeData: function(script) {
// encode strings and regular expressions
var data = this._data = []; // encoded strings and regular expressions
return Packer.data.exec(script, function(match, operator, regexp) {
var replacement = "\x01" + data.length + "\x01";
if (regexp) {
replacement = operator + replacement;
match = regexp;
}
data.push(match);
return replacement;
});
},
shrink: function(script) {
script = this.encodeData(script);
// Windows Scripting Host cannot do regexp.test() on global regexps.
function global(regexp) {
// This function creates a global version of the passed regexp.
return new RegExp(regexp.source, "g");
};
// identify blocks, particularly identify function blocks (which define scope)
var BLOCK = /((catch|do|if|while|with|function)\b[^~{};]*(\(\s*[^{};]*\s*\))\s*)?(\{[^{}]*\})/;
var BLOCK_g = global(BLOCK);
var BRACKETS = /\{[^{}]*\}|\[[^\[\]]*\]|\([^\(\)]*\)|~[^~]+~/;
var BRACKETS_g = global(BRACKETS);
var ENCODED_BLOCK = /~#?(\d+)~/;
var IDENTIFIER = /[a-zA-Z_$][\w\$]*/g;
var SCOPED = /~#(\d+)~/;
var VAR_g = /\bvar\b/g;
var VARS = /\bvar\s+[\w$]+[^;#]*|\bfunction\s+[\w$]+/g;
var VAR_TIDY = /\b(var|function)\b|\sin\s+[^;]+/g;
var VAR_EQUAL = /\s*=[^,;]*/g;
var blocks = []; // store program blocks (anything between braces {})
var total = 0;
// encoder for program blocks
function encodeBlocks($, prefix, blockType, args, block) {
if (!prefix) prefix = "";
if (blockType == "function") {
// decode the function block (THIS IS THE IMPORTANT BIT)
// We are retrieving all sub-blocks and will re-parse them in light
// of newly shrunk variables
block = args + decodeBlocks(block, SCOPED);
prefix = prefix.replace(BRACKETS, "");
// create the list of variable and argument names
args = args.slice(1, -1);
if (args != "_no_shrink_") {
var vars = match(block, VARS).join(";").replace(VAR_g, ";var");
while (BRACKETS.test(vars)) {
vars = vars.replace(BRACKETS_g, "");
}
vars = vars.replace(VAR_TIDY, "").replace(VAR_EQUAL, "");
}
block = decodeBlocks(block, ENCODED_BLOCK);
// process each identifier
if (args != "_no_shrink_") {
var count = 0, shortId;
var ids = match([args, vars], IDENTIFIER);
var processed = {};
for (var i = 0; i < ids.length; i++) {
id = ids[i];
if (!processed["#" + id]) {
processed["#" + id] = true;
id = rescape(id);
// encode variable names
while (new RegExp(Shrinker.PREFIX + count + "\\b").test(block)) count++;
var reg = new RegExp("([^\\w$.])" + id + "([^\\w$:])");
while (reg.test(block)) {
block = block.replace(global(reg), "$1" + Shrinker.PREFIX + count + "$2");
}
var reg = new RegExp("([^{,\\w$.])" + id + ":", "g");
block = block.replace(reg, "$1" + Shrinker.PREFIX + count + ":");
count++;
}
}
total = Math.max(total, count);
}
var replacement = prefix + "~" + blocks.length + "~";
blocks.push(block);
} else {
var replacement = "~#" + blocks.length + "~";
blocks.push(prefix + block);
}
return replacement;
};
// decoder for program blocks
function decodeBlocks(script, encoded) {
while (encoded.test(script)) {
script = script.replace(global(encoded), function(match, index) {
return blocks[index];
});
}
return script;
};
// encode blocks, as we encode we replace variable and argument names
while (BLOCK.test(script)) {
script = script.replace(BLOCK_g, encodeBlocks);
}
// put the blocks back
script = decodeBlocks(script, ENCODED_BLOCK);
var shortId, count = 0;
var shrunk = new Encoder(Shrinker.SHRUNK, function() {
// find the next free short name
do shortId = Packer.encode52(count++);
while (new RegExp("[^\\w$.]" + shortId + "[^\\w$:]").test(script));
return shortId;
});
script = shrunk.encode(script);
return this.decodeData(script);
}
}, {
ENCODED_DATA: /\x01(\d+)\x01/g,
PREFIX: "\x02",
SHRUNK: /\x02\d+\b/g
});
}; //////////////////// END: CLOSURE /////////////////////////////////////
nwmatcher/build/packer/base2.js 0000644 0001750 0001750 00000142354 12316015515 015110 0 ustar wmb wmb /*
base2 - copyright 2007-2008, Dean Edwards
http://code.google.com/p/base2/
http://www.opensource.org/licenses/mit-license.php
Contributors:
Doeke Zanstra
*/
// timestamp: Sat, 06 Sep 2008 16:52:32
var base2 = {
name: "base2",
version: "1.0",
exports:
"Base,Package,Abstract,Module,Enumerable,Map,Collection,RegGrp," +
"Undefined,Null,This,True,False,assignID,detect,global",
namespace: ""
};
new function(_no_shrink_) { /////////////// BEGIN: CLOSURE ///////////////
// =========================================================================
// base2/header.js
// =========================================================================
var Undefined = K(), Null = K(null), True = K(true), False = K(false), This = function(){return this};
var global = This();
var base2 = global.base2;
// private
var _FORMAT = /%([1-9])/g;
var _LTRIM = /^\s\s*/;
var _RTRIM = /\s\s*$/;
var _RESCAPE = /([\/()[\]{}|*+-.,^$?\\])/g; // safe regular expressions
var _BASE = /try/.test(detect) ? /\bbase\b/ : /.*/; // some platforms don't allow decompilation
var _HIDDEN = ["constructor", "toString", "valueOf"]; // only override these when prototyping
var _MSIE_NATIVE_FUNCTION = detect("(jscript)") ?
new RegExp("^" + rescape(isNaN).replace(/isNaN/, "\\w+") + "$") : {test: False};
var _counter = 1;
var _slice = Array.prototype.slice;
_Function_forEach(); // make sure this is initialised
function assignID(object) {
// Assign a unique ID to an object.
if (!object.base2ID) object.base2ID = "b2_" + _counter++;
return object.base2ID;
};
// =========================================================================
// base2/Base.js
// =========================================================================
// http://dean.edwards.name/weblog/2006/03/base/
var _subclass = function(_instance, _static) {
// Build the prototype.
base2.__prototyping = this.prototype;
var _prototype = new this;
if (_instance) extend(_prototype, _instance);
delete base2.__prototyping;
// Create the wrapper for the constructor function.
var _constructor = _prototype.constructor;
function _class() {
// Don't call the constructor function when prototyping.
if (!base2.__prototyping) {
if (this.constructor == arguments.callee || this.__constructing) {
// Instantiation.
this.__constructing = true;
_constructor.apply(this, arguments);
delete this.__constructing;
} else {
// Casting.
return extend(arguments[0], _prototype);
}
}
return this;
};
_prototype.constructor = _class;
// Build the static interface.
for (var i in Base) _class[i] = this[i];
_class.ancestor = this;
_class.base = Undefined;
//_class.init = Undefined;
if (_static) extend(_class, _static);
_class.prototype = _prototype;
if (_class.init) _class.init();
// introspection (removed when packed)
;;; _class["#implements"] = [];
;;; _class["#implemented_by"] = [];
return _class;
};
var Base = _subclass.call(Object, {
constructor: function() {
if (arguments.length > 0) {
this.extend(arguments[0]);
}
},
base: function() {
// Call this method from any other method to invoke the current method's ancestor (super).
},
extend: delegate(extend)
}, Base = {
ancestorOf: function(klass) {
return _ancestorOf(this, klass);
},
extend: _subclass,
forEach: function(object, block, context) {
_Function_forEach(this, object, block, context);
},
implement: function(source) {
if (typeof source == "function") {
;;; if (_ancestorOf(Base, source)) {
// introspection (removed when packed)
;;; this["#implements"].push(source);
;;; source["#implemented_by"].push(this);
;;; }
source = source.prototype;
}
// Add the interface using the extend() function.
extend(this.prototype, source);
return this;
}
});
// =========================================================================
// base2/Package.js
// =========================================================================
var Package = Base.extend({
constructor: function(_private, _public) {
this.extend(_public);
if (this.init) this.init();
if (this.name && this.name != "base2") {
if (!this.parent) this.parent = base2;
this.parent.addName(this.name, this);
this.namespace = format("var %1=%2;", this.name, String2.slice(this, 1, -1));
}
if (_private) {
// This next line gets round a bug in old Mozilla browsers
var JSNamespace = base2.JavaScript ? base2.JavaScript.namespace : "";
// This string should be evaluated immediately after creating a Package object.
_private.imports = Array2.reduce(csv(this.imports), function(namespace, name) {
var ns = lookup(name) || lookup("JavaScript." + name);
;;; assert(ns, format("Object not found: '%1'.", name), ReferenceError);
return namespace += ns.namespace;
}, "var base2=(function(){return this.base2})();" + base2.namespace + JSNamespace) + lang.namespace;
// This string should be evaluated after you have created all of the objects
// that are being exported.
_private.exports = Array2.reduce(csv(this.exports), function(namespace, name) {
var fullName = this.name + "." + name;
this.namespace += "var " + name + "=" + fullName + ";";
return namespace += "if(!" + fullName + ")" + fullName + "=" + name + ";";
}, "", this) + "this._label_" + this.name + "();";
var pkg = this;
var packageName = String2.slice(this, 1, -1);
_private["_label_" + this.name] = function() {
Package.forEach (pkg, function(object, name) {
if (object && object.ancestorOf == Base.ancestorOf) {
object.toString = K(format("[%1.%2]", packageName, name));
if (object.prototype.toString == Base.prototype.toString) {
object.prototype.toString = K(format("[object %1.%2]", packageName, name));
}
}
});
};
}
function lookup(names) {
names = names.split(".");
var value = base2, i = 0;
while (value && names[i] != null) {
value = value[names[i++]];
}
return value;
};
},
exports: "",
imports: "",
name: "",
namespace: "",
parent: null,
addName: function(name, value) {
if (!this[name]) {
this[name] = value;
this.exports += "," + name;
this.namespace += format("var %1=%2.%1;", name, this.name);
}
},
addPackage: function(name) {
this.addName(name, new Package(null, {name: name, parent: this}));
},
toString: function() {
return format("[%1]", this.parent ? String2.slice(this.parent, 1, -1) + "." + this.name : this.name);
}
});
// =========================================================================
// base2/Abstract.js
// =========================================================================
var Abstract = Base.extend({
constructor: function() {
throw new TypeError("Abstract class cannot be instantiated.");
}
});
// =========================================================================
// base2/Module.js
// =========================================================================
var _moduleCount = 0;
var Module = Abstract.extend(null, {
namespace: "",
extend: function(_interface, _static) {
// Extend a module to create a new module.
var module = this.base();
var index = _moduleCount++;
module.namespace = "";
module.partial = this.partial;
module.toString = K("[base2.Module[" + index + "]]");
Module[index] = module;
// Inherit class methods.
module.implement(this);
// Implement module (instance AND static) methods.
if (_interface) module.implement(_interface);
// Implement static properties and methods.
if (_static) {
extend(module, _static);
if (module.init) module.init();
}
return module;
},
forEach: function(block, context) {
_Function_forEach (Module, this.prototype, function(method, name) {
if (typeOf(method) == "function") {
block.call(context, this[name], name, this);
}
}, this);
},
implement: function(_interface) {
var module = this;
var id = module.toString().slice(1, -1);
if (typeof _interface == "function") {
if (!_ancestorOf(_interface, module)) {
this.base(_interface);
}
if (_ancestorOf(Module, _interface)) {
// Implement static methods.
for (var name in _interface) {
if (module[name] === undefined) {
var property = _interface[name];
if (typeof property == "function" && property.call && _interface.prototype[name]) {
property = _staticModuleMethod(_interface, name);
}
module[name] = property;
}
}
module.namespace += _interface.namespace.replace(/base2\.Module\[\d+\]/g, id);
}
} else {
// Add static interface.
extend(module, _interface);
// Add instance interface.
_extendModule(module, _interface);
}
return module;
},
partial: function() {
var module = Module.extend();
var id = module.toString().slice(1, -1);
// partial methods are already bound so remove the binding to speed things up
module.namespace = this.namespace.replace(/(\w+)=b[^\)]+\)/g, "$1=" + id + ".$1");
this.forEach(function(method, name) {
module[name] = partial(bind(method, module));
});
return module;
}
});
function _extendModule(module, _interface) {
var proto = module.prototype;
var id = module.toString().slice(1, -1);
for (var name in _interface) {
var property = _interface[name], namespace = "";
if (name.charAt(0) == "@") { // object detection
if (detect(name.slice(1))) _extendModule(module, property);
} else if (!proto[name]) {
if (name == name.toUpperCase()) {
namespace = "var " + name + "=" + id + "." + name + ";";
} else if (typeof property == "function" && property.call) {
namespace = "var " + name + "=base2.lang.bind('" + name + "'," + id + ");";
proto[name] = _moduleMethod(module, name);
;;; proto[name]._module = module; // introspection
}
if (module.namespace.indexOf(namespace) == -1) {
module.namespace += namespace;
}
}
}
};
function _staticModuleMethod(module, name) {
return function() {
return module[name].apply(module, arguments);
};
};
function _moduleMethod(module, name) {
return function() {
var args = _slice.call(arguments);
args.unshift(this);
return module[name].apply(module, args);
};
};
// =========================================================================
// base2/Enumerable.js
// =========================================================================
var Enumerable = Module.extend({
every: function(object, test, context) {
var result = true;
try {
forEach (object, function(value, key) {
result = test.call(context, value, key, object);
if (!result) throw StopIteration;
});
} catch (error) {
if (error != StopIteration) throw error;
}
return !!result; // cast to boolean
},
filter: function(object, test, context) {
var i = 0;
return this.reduce(object, function(result, value, key) {
if (test.call(context, value, key, object)) {
result[i++] = value;
}
return result;
}, []);
},
invoke: function(object, method) {
// Apply a method to each item in the enumerated object.
var args = _slice.call(arguments, 2);
return this.map(object, (typeof method == "function") ? function(item) {
return item == null ? undefined : method.apply(item, args);
} : function(item) {
return item == null ? undefined : item[method].apply(item, args);
});
},
map: function(object, block, context) {
var result = [], i = 0;
forEach (object, function(value, key) {
result[i++] = block.call(context, value, key, object);
});
return result;
},
pluck: function(object, key) {
return this.map(object, function(item) {
return item == null ? undefined : item[key];
});
},
reduce: function(object, block, result, context) {
var initialised = arguments.length > 2;
forEach (object, function(value, key) {
if (initialised) {
result = block.call(context, result, value, key, object);
} else {
result = value;
initialised = true;
}
});
return result;
},
some: function(object, test, context) {
return !this.every(object, not(test), context);
}
});
// =========================================================================
// base2/Map.js
// =========================================================================
// http://wiki.ecmascript.org/doku.php?id=proposals:dictionary
var _HASH = "#";
var Map = Base.extend({
constructor: function(values) {
if (values) this.merge(values);
},
clear: function() {
for (var key in this) if (key.indexOf(_HASH) == 0) {
delete this[key];
}
},
copy: function() {
base2.__prototyping = true; // not really prototyping but it stops [[construct]] being called
var copy = new this.constructor;
delete base2.__prototyping;
for (var i in this) if (this[i] !== copy[i]) {
copy[i] = this[i];
}
return copy;
},
forEach: function(block, context) {
for (var key in this) if (key.indexOf(_HASH) == 0) {
block.call(context, this[key], key.slice(1), this);
}
},
get: function(key) {
return this[_HASH + key];
},
getKeys: function() {
return this.map(II);
},
getValues: function() {
return this.map(I);
},
// Ancient browsers throw an error if we use "in" as an operator.
has: function(key) {
/*@cc_on @*/
/*@if (@_jscript_version < 5.5)
return $Legacy.has(this, _HASH + key);
@else @*/
return _HASH + key in this;
/*@end @*/
},
merge: function(values) {
var put = flip(this.put);
forEach (arguments, function(values) {
forEach (values, put, this);
}, this);
return this;
},
put: function(key, value) {
// create the new entry (or overwrite the old entry).
this[_HASH + key] = value;
},
remove: function(key) {
delete this[_HASH + key];
},
size: function() {
// this is expensive because we are not storing the keys
var size = 0;
for (var key in this) if (key.indexOf(_HASH) == 0) size++;
return size;
},
union: function(values) {
return this.merge.apply(this.copy(), arguments);
}
});
Map.implement(Enumerable);
Map.prototype.filter = function(test, context) {
return this.reduce(function(result, value, key) {
if (!test.call(context, value, key, this)) {
result.remove(key);
}
return result;
}, this.copy(), this);
};
// =========================================================================
// base2/Collection.js
// =========================================================================
// A Map that is more array-like (accessible by index).
// Collection classes have a special (optional) property: Item
// The Item property points to a constructor function.
// Members of the collection must be an instance of Item.
// The static create() method is responsible for all construction of collection items.
// Instance methods that add new items (add, put, insertAt, putAt) pass *all* of their arguments
// to the static create() method. If you want to modify the way collection items are
// created then you only need to override this method for custom collections.
var _KEYS = "~";
var Collection = Map.extend({
constructor: function(values) {
this[_KEYS] = new Array2;
this.base(values);
},
add: function(key, item) {
// Duplicates not allowed using add().
// But you can still overwrite entries using put().
assert(!this.has(key), "Duplicate key '" + key + "'.");
this.put.apply(this, arguments);
},
clear: function() {
this.base();
this[_KEYS].length = 0;
},
copy: function() {
var copy = this.base();
copy[_KEYS] = this[_KEYS].copy();
return copy;
},
forEach: function(block, context) {
var keys = this[_KEYS];
var length = keys.length;
for (var i = 0; i < length; i++) {
block.call(context, this[_HASH + keys[i]], keys[i], this);
}
},
getAt: function(index) {
var key = this[_KEYS].item(index);
return (key === undefined) ? undefined : this[_HASH + key];
},
getKeys: function() {
return this[_KEYS].copy();
},
indexOf: function(key) {
return this[_KEYS].indexOf(String(key));
},
insertAt: function(index, key, item) {
assert(this[_KEYS].item(index) !== undefined, "Index out of bounds.");
assert(!this.has(key), "Duplicate key '" + key + "'.");
this[_KEYS].insertAt(index, String(key));
this[_HASH + key] = null; // placeholder
this.put.apply(this, _slice.call(arguments, 1));
},
item: function(keyOrIndex) {
return this[typeof keyOrIndex == "number" ? "getAt" : "get"](keyOrIndex);
},
put: function(key, item) {
if (!this.has(key)) {
this[_KEYS].push(String(key));
}
var klass = this.constructor;
if (klass.Item && !instanceOf(item, klass.Item)) {
item = klass.create.apply(klass, arguments);
}
this[_HASH + key] = item;
},
putAt: function(index, item) {
arguments[0] = this[_KEYS].item(index);
assert(arguments[0] !== undefined, "Index out of bounds.");
this.put.apply(this, arguments);
},
remove: function(key) {
// The remove() method of the Array object can be slow so check if the key exists first.
if (this.has(key)) {
this[_KEYS].remove(String(key));
delete this[_HASH + key];
}
},
removeAt: function(index) {
var key = this[_KEYS].item(index);
if (key !== undefined) {
this[_KEYS].removeAt(index);
delete this[_HASH + key];
}
},
reverse: function() {
this[_KEYS].reverse();
return this;
},
size: function() {
return this[_KEYS].length;
},
slice: function(start, end) {
var sliced = this.copy();
if (arguments.length > 0) {
var keys = this[_KEYS], removed = keys;
sliced[_KEYS] = Array2(_slice.apply(keys, arguments));
if (sliced[_KEYS].length) {
removed = removed.slice(0, start);
if (arguments.length > 1) {
removed = removed.concat(keys.slice(end));
}
}
for (var i = 0; i < removed.length; i++) {
delete sliced[_HASH + removed[i]];
}
}
return sliced;
},
sort: function(compare) { // optimised (refers to _HASH)
if (compare) {
this[_KEYS].sort(bind(function(key1, key2) {
return compare(this[_HASH + key1], this[_HASH + key2], key1, key2);
}, this));
} else this[_KEYS].sort();
return this;
},
toString: function() {
return "(" + (this[_KEYS] || "") + ")";
}
}, {
Item: null, // If specified, all members of the collection must be instances of Item.
create: function(key, item) {
return this.Item ? new this.Item(key, item) : item;
},
extend: function(_instance, _static) {
var klass = this.base(_instance);
klass.create = this.create;
if (_static) extend(klass, _static);
if (!klass.Item) {
klass.Item = this.Item;
} else if (typeof klass.Item != "function") {
klass.Item = (this.Item || Base).extend(klass.Item);
}
if (klass.init) klass.init();
return klass;
}
});
// =========================================================================
// base2/RegGrp.js
// =========================================================================
// A collection of regular expressions and their associated replacement values.
// A Base class for creating parsers.
var _RG_BACK_REF = /\\(\d+)/g,
_RG_ESCAPE_CHARS = /\\./g,
_RG_ESCAPE_BRACKETS = /\(\?[:=!]|\[[^\]]+\]/g,
_RG_BRACKETS = /\(/g,
_RG_LOOKUP = /\$(\d+)/,
_RG_LOOKUP_SIMPLE = /^\$\d+$/;
var RegGrp = Collection.extend({
constructor: function(values, ignoreCase) {
this.base(values);
this.ignoreCase = !!ignoreCase;
},
ignoreCase: false,
exec: function(string, override) { // optimised (refers to _HASH/_KEYS)
string += ""; // type-safe
var items = this, keys = this[_KEYS];
if (!keys.length) return string;
if (override == RegGrp.IGNORE) override = 0;
return string.replace(new RegExp(this, this.ignoreCase ? "gi" : "g"), function(match) {
var item, offset = 1, i = 0;
// Loop through the RegGrp items.
while ((item = items[_HASH + keys[i++]])) {
var next = offset + item.length + 1;
if (arguments[offset]) { // do we have a result?
var replacement = override == null ? item.replacement : override;
switch (typeof replacement) {
case "function":
return replacement.apply(items, _slice.call(arguments, offset, next));
case "number":
return arguments[offset + replacement];
default:
return replacement;
}
}
offset = next;
}
return match;
});
},
insertAt: function(index, expression, replacement) {
if (instanceOf(expression, RegExp)) {
arguments[1] = expression.source;
}
return base(this, arguments);
},
test: function(string) {
// The slow way to do it. Hopefully, this isn't called too often. :-)
return this.exec(string) != string;
},
toString: function() {
var offset = 1;
return "(" + this.map(function(item) {
// Fix back references.
var expression = (item + "").replace(_RG_BACK_REF, function(match, index) {
return "\\" + (offset + Number(index));
});
offset += item.length + 1;
return expression;
}).join(")|(") + ")";
}
}, {
IGNORE: "$0",
init: function() {
forEach ("add,get,has,put,remove".split(","), function(name) {
_override(this, name, function(expression) {
if (instanceOf(expression, RegExp)) {
arguments[0] = expression.source;
}
return base(this, arguments);
});
}, this.prototype);
},
Item: {
constructor: function(expression, replacement) {
if (replacement == null) replacement = RegGrp.IGNORE;
else if (replacement.replacement != null) replacement = replacement.replacement;
else if (typeof replacement != "function") replacement = String(replacement);
// does the pattern use sub-expressions?
if (typeof replacement == "string" && _RG_LOOKUP.test(replacement)) {
// a simple lookup? (e.g. "$2")
if (_RG_LOOKUP_SIMPLE.test(replacement)) {
// store the index (used for fast retrieval of matched strings)
replacement = parseInt(replacement.slice(1));
} else { // a complicated lookup (e.g. "Hello $2 $1")
// build a function to do the lookup
// Improved version by Alexei Gorkov:
var Q = '"';
replacement = replacement
.replace(/\\/g, "\\\\")
.replace(/"/g, "\\x22")
.replace(/\n/g, "\\n")
.replace(/\r/g, "\\r")
.replace(/\$(\d+)/g, Q + "+(arguments[$1]||" + Q+Q + ")+" + Q)
.replace(/(['"])\1\+(.*)\+\1\1$/, "$1");
replacement = new Function("return " + Q + replacement + Q);
}
}
this.length = RegGrp.count(expression);
this.replacement = replacement;
this.toString = K(expression + "");
},
length: 0,
replacement: ""
},
count: function(expression) {
// Count the number of sub-expressions in a RegExp/RegGrp.Item.
expression = (expression + "").replace(_RG_ESCAPE_CHARS, "").replace(_RG_ESCAPE_BRACKETS, "");
return match(expression, _RG_BRACKETS).length;
}
});
// =========================================================================
// lang/package.js
// =========================================================================
var lang = {
name: "lang",
version: base2.version,
exports: "assert,assertArity,assertType,base,bind,copy,extend,forEach,format,instanceOf,match,pcopy,rescape,trim,typeOf",
namespace: "" // fixed later
};
// =========================================================================
// lang/assert.js
// =========================================================================
function assert(condition, message, ErrorClass) {
if (!condition) {
throw new (ErrorClass || Error)(message || "Assertion failed.");
}
};
function assertArity(args, arity, message) {
if (arity == null) arity = args.callee.length;
if (args.length < arity) {
throw new SyntaxError(message || "Not enough arguments.");
}
};
function assertType(object, type, message) {
if (type && (typeof type == "function" ? !instanceOf(object, type) : typeOf(object) != type)) {
throw new TypeError(message || "Invalid type.");
}
};
// =========================================================================
// lang/copy.js
// =========================================================================
function copy(object) {
// a quick copy
var copy = {};
for (var i in object) {
copy[i] = object[i];
}
return copy;
};
function pcopy(object) {
// Doug Crockford / Richard Cornford
_dummy.prototype = object;
return new _dummy;
};
function _dummy(){};
// =========================================================================
// lang/extend.js
// =========================================================================
function base(object, args) {
return object.base.apply(object, args);
};
function extend(object, source) { // or extend(object, key, value)
if (object && source) {
if (arguments.length > 2) { // Extending with a key/value pair.
var key = source;
source = {};
source[key] = arguments[2];
}
var proto = global[(typeof source == "function" ? "Function" : "Object")].prototype;
// Add constructor, toString etc
if (base2.__prototyping) {
var i = _HIDDEN.length, key;
while ((key = _HIDDEN[--i])) {
var value = source[key];
if (value != proto[key]) {
if (_BASE.test(value)) {
_override(object, key, value)
} else {
object[key] = value;
}
}
}
}
// Copy each of the source object's properties to the target object.
for (key in source) {
if (proto[key] === undefined) {
var value = source[key];
// Object detection.
if (key.charAt(0) == "@") {
if (detect(key.slice(1))) extend(object, value);
} else {
// Check for method overriding.
var ancestor = object[key];
if (ancestor && typeof value == "function") {
if (value != ancestor) {
if (_BASE.test(value)) {
_override(object, key, value);
} else {
value.ancestor = ancestor;
object[key] = value;
}
}
} else {
object[key] = value;
}
}
}
}
}
return object;
};
function _ancestorOf(ancestor, fn) {
// Check if a function is in another function's inheritance chain.
while (fn) {
if (!fn.ancestor) return false;
fn = fn.ancestor;
if (fn == ancestor) return true;
}
return false;
};
function _override(object, name, method) {
// Override an existing method.
var ancestor = object[name];
var superObject = base2.__prototyping; // late binding for prototypes
if (superObject && ancestor != superObject[name]) superObject = null;
function _base() {
var previous = this.base;
this.base = superObject ? superObject[name] : ancestor;
var returnValue = method.apply(this, arguments);
this.base = previous;
return returnValue;
};
_base.method = method;
_base.ancestor = ancestor;
object[name] = _base;
// introspection (removed when packed)
;;; _base.toString = K(method + "");
};
// =========================================================================
// lang/forEach.js
// =========================================================================
// http://dean.edwards.name/weblog/2006/07/enum/
if (typeof StopIteration == "undefined") {
StopIteration = new Error("StopIteration");
}
function forEach(object, block, context, fn) {
if (object == null) return;
if (!fn) {
if (typeof object == "function" && object.call) {
// Functions are a special case.
fn = Function;
} else if (typeof object.forEach == "function" && object.forEach != arguments.callee) {
// The object implements a custom forEach method.
object.forEach(block, context);
return;
} else if (typeof object.length == "number") {
// The object is array-like.
_Array_forEach(object, block, context);
return;
}
}
_Function_forEach(fn || Object, object, block, context);
};
forEach.csv = function(string, block, context) {
forEach (csv(string), block, context);
};
forEach.detect = function(object, block, context) {
forEach (object, function(value, key) {
if (key.charAt(0) == "@") { // object detection
if (detect(key.slice(1))) forEach (value, arguments.callee);
} else block.call(context, value, key, object);
});
};
// These are the two core enumeration methods. All other forEach methods
// eventually call one of these two.
function _Array_forEach(array, block, context) {
if (array == null) array = global;
var length = array.length || 0, i; // preserve length
if (typeof array == "string") {
for (i = 0; i < length; i++) {
block.call(context, array.charAt(i), i, array);
}
} else { // Cater for sparse arrays.
for (i = 0; i < length; i++) {
/*@cc_on @*/
/*@if (@_jscript_version < 5.2)
if ($Legacy.has(array, i))
@else @*/
if (i in array)
/*@end @*/
block.call(context, array[i], i, array);
}
}
};
function _Function_forEach(fn, object, block, context) {
// http://code.google.com/p/base2/issues/detail?id=10
// Run the test for Safari's buggy enumeration.
var Temp = function(){this.i=1};
Temp.prototype = {i:1};
var count = 0;
for (var i in new Temp) count++;
// Overwrite the main function the first time it is called.
_Function_forEach = (count > 1) ? function(fn, object, block, context) {
// Safari fix (pre version 3)
var processed = {};
for (var key in object) {
if (!processed[key] && fn.prototype[key] === undefined) {
processed[key] = true;
block.call(context, object[key], key, object);
}
}
} : function(fn, object, block, context) {
// Enumerate an object and compare its keys with fn's prototype.
for (var key in object) {
if (fn.prototype[key] === undefined) {
block.call(context, object[key], key, object);
}
}
};
_Function_forEach(fn, object, block, context);
};
// =========================================================================
// lang/instanceOf.js
// =========================================================================
function instanceOf(object, klass) {
// Handle exceptions where the target object originates from another frame.
// This is handy for JSON parsing (amongst other things).
if (typeof klass != "function") {
throw new TypeError("Invalid 'instanceOf' operand.");
}
if (object == null) return false;
/*@cc_on
// COM objects don't have a constructor
if (typeof object.constructor != "function") {
return typeOf(object) == typeof klass.prototype.valueOf();
}
@*/
if (object.constructor == klass) return true;
if (klass.ancestorOf) return klass.ancestorOf(object.constructor);
/*@if (@_jscript_version < 5.1)
// do nothing
@else @*/
if (object instanceof klass) return true;
/*@end @*/
// If the class is a base2 class then it would have passed the test above.
if (Base.ancestorOf == klass.ancestorOf) return false;
// base2 objects can only be instances of Object.
if (Base.ancestorOf == object.constructor.ancestorOf) return klass == Object;
switch (klass) {
case Array: // This is the only troublesome one.
return !!(typeof object == "object" && object.join && object.splice);
case Function:
return typeOf(object) == "function";
case RegExp:
return typeof object.constructor.$1 == "string";
case Date:
return !!object.getTimezoneOffset;
case String:
case Number:
case Boolean:
return typeOf(object) == typeof klass.prototype.valueOf();
case Object:
return true;
}
return false;
};
// =========================================================================
// lang/typeOf.js
// =========================================================================
// http://wiki.ecmascript.org/doku.php?id=proposals:typeof
function typeOf(object) {
var type = typeof object;
switch (type) {
case "object":
return object == null
? "null"
: typeof object.constructor == "undefined" // COM object
? _MSIE_NATIVE_FUNCTION.test(object)
? "function"
: type
: typeof object.constructor.prototype.valueOf(); // underlying type
case "function":
return typeof object.call == "function" ? type : "object";
default:
return type;
}
};
// =========================================================================
// JavaScript/package.js
// =========================================================================
var JavaScript = {
name: "JavaScript",
version: base2.version,
exports: "Array2,Date2,Function2,String2",
namespace: "", // fixed later
bind: function(host) {
var top = global;
global = host;
forEach.csv(this.exports, function(name2) {
var name = name2.slice(0, -1);
extend(host[name], this[name2]);
this[name2](host[name].prototype); // cast
}, this);
global = top;
return host;
}
};
function _createObject2(Native, constructor, generics, extensions) {
// Clone native objects and extend them.
// Create a Module that will contain all the new methods.
var INative = Module.extend();
var id = INative.toString().slice(1, -1);
// http://developer.mozilla.org/en/docs/New_in_JavaScript_1.6#Array_and_String_generics
forEach.csv(generics, function(name) {
INative[name] = unbind(Native.prototype[name]);
INative.namespace += format("var %1=%2.%1;", name, id);
});
forEach (_slice.call(arguments, 3), INative.implement, INative);
// create a faux constructor that augments the native object
var Native2 = function() {
return INative(this.constructor == INative ? constructor.apply(null, arguments) : arguments[0]);
};
Native2.prototype = INative.prototype;
// Remove methods that are already implemented.
for (var name in INative) {
if (name != "prototype" && Native[name]) {
INative[name] = Native[name];
delete INative.prototype[name];
}
Native2[name] = INative[name];
}
Native2.ancestor = Object;
delete Native2.extend;
// remove "lang.bind.."
Native2.namespace = Native2.namespace.replace(/(var (\w+)=)[^,;]+,([^\)]+)\)/g, "$1$3.$2");
return Native2;
};
// =========================================================================
// JavaScript/~/Date.js
// =========================================================================
// Fix Date.get/setYear() (IE5-7)
if ((new Date).getYear() > 1900) {
Date.prototype.getYear = function() {
return this.getFullYear() - 1900;
};
Date.prototype.setYear = function(year) {
return this.setFullYear(year + 1900);
};
}
// https://bugs.webkit.org/show_bug.cgi?id=9532
var _testDate = new Date(Date.UTC(2006, 1, 20));
_testDate.setUTCDate(15);
if (_testDate.getUTCHours() != 0) {
forEach.csv("FullYear,Month,Date,Hours,Minutes,Seconds,Milliseconds", function(type) {
extend(Date.prototype, "setUTC" + type, function() {
var value = base(this, arguments);
if (value >= 57722401000) {
value -= 3600000;
this.setTime(value);
}
return value;
});
});
}
// =========================================================================
// JavaScript/~/Function.js
// =========================================================================
// Some browsers don't define this.
Function.prototype.prototype = {};
// =========================================================================
// JavaScript/~/String.js
// =========================================================================
// A KHTML bug.
if ("".replace(/^/, K("$$")) == "$") {
extend(String.prototype, "replace", function(expression, replacement) {
if (typeof replacement == "function") {
var fn = replacement;
replacement = function() {
return String(fn.apply(null, arguments)).split("$").join("$$");
};
}
return this.base(expression, replacement);
});
}
// =========================================================================
// JavaScript/Array2.js
// =========================================================================
var Array2 = _createObject2(
Array,
Array,
"concat,join,pop,push,reverse,shift,slice,sort,splice,unshift", // generics
Enumerable, {
combine: function(keys, values) {
// Combine two arrays to make a hash.
if (!values) values = keys;
return Array2.reduce(keys, function(hash, key, index) {
hash[key] = values[index];
return hash;
}, {});
},
contains: function(array, item) {
return Array2.indexOf(array, item) != -1;
},
copy: function(array) {
var copy = _slice.call(array);
if (!copy.swap) Array2(copy); // cast to Array2
return copy;
},
flatten: function(array) {
var i = 0;
return Array2.reduce(array, function(result, item) {
if (Array2.like(item)) {
Array2.reduce(item, arguments.callee, result);
} else {
result[i++] = item;
}
return result;
}, []);
},
forEach: _Array_forEach,
indexOf: function(array, item, fromIndex) {
var length = array.length;
if (fromIndex == null) {
fromIndex = 0;
} else if (fromIndex < 0) {
fromIndex = Math.max(0, length + fromIndex);
}
for (var i = fromIndex; i < length; i++) {
if (array[i] === item) return i;
}
return -1;
},
insertAt: function(array, index, item) {
Array2.splice(array, index, 0, item);
return item;
},
item: function(array, index) {
if (index < 0) index += array.length; // starting from the end
return array[index];
},
lastIndexOf: function(array, item, fromIndex) {
var length = array.length;
if (fromIndex == null) {
fromIndex = length - 1;
} else if (fromIndex < 0) {
fromIndex = Math.max(0, length + fromIndex);
}
for (var i = fromIndex; i >= 0; i--) {
if (array[i] === item) return i;
}
return -1;
},
map: function(array, block, context) {
var result = [];
Array2.forEach (array, function(item, index) {
result[index] = block.call(context, item, index, array);
});
return result;
},
remove: function(array, item) {
var index = Array2.indexOf(array, item);
if (index != -1) Array2.removeAt(array, index);
},
removeAt: function(array, index) {
Array2.splice(array, index, 1);
},
swap: function(array, index1, index2) {
if (index1 < 0) index1 += array.length; // starting from the end
if (index2 < 0) index2 += array.length;
var temp = array[index1];
array[index1] = array[index2];
array[index2] = temp;
return array;
}
}
);
Array2.reduce = Enumerable.reduce; // Mozilla does not implement the thisObj argument
Array2.like = function(object) {
// is the object like an array?
return typeOf(object) == "object" && typeof object.length == "number";
};
// introspection (removed when packed)
;;; Enumerable["#implemented_by"].pop();
;;; Enumerable["#implemented_by"].push(Array2);
// =========================================================================
// JavaScript/Date2.js
// =========================================================================
// http://developer.mozilla.org/es4/proposals/date_and_time.html
// big, ugly, regular expression
var _DATE_PATTERN = /^((-\d+|\d{4,})(-(\d{2})(-(\d{2}))?)?)?T((\d{2})(:(\d{2})(:(\d{2})(\.(\d{1,3})(\d)?\d*)?)?)?)?(([+-])(\d{2})(:(\d{2}))?|Z)?$/;
var _DATE_PARTS = { // indexes to the sub-expressions of the RegExp above
FullYear: 2,
Month: 4,
Date: 6,
Hours: 8,
Minutes: 10,
Seconds: 12,
Milliseconds: 14
};
var _TIMEZONE_PARTS = { // idem, but without the getter/setter usage on Date object
Hectomicroseconds: 15, // :-P
UTC: 16,
Sign: 17,
Hours: 18,
Minutes: 20
};
var _TRIM_ZEROES = /(((00)?:0+)?:0+)?\.0+$/;
var _TRIM_TIMEZONE = /(T[0-9:.]+)$/;
var Date2 = _createObject2(
Date,
function(yy, mm, dd, h, m, s, ms) {
switch (arguments.length) {
case 0: return new Date;
case 1: return typeof yy == "number" ? new Date(yy) : Date2.parse(yy);
default: return new Date(yy, mm, arguments.length == 2 ? 1 : dd, h || 0, m || 0, s || 0, ms || 0);
}
}, "", {
toISOString: function(date) {
var string = "####-##-##T##:##:##.###";
for (var part in _DATE_PARTS) {
string = string.replace(/#+/, function(digits) {
var value = date["getUTC" + part]();
if (part == "Month") value++; // js month starts at zero
return ("000" + value).slice(-digits.length); // pad
});
}
// remove trailing zeroes, and remove UTC timezone, when time's absent
return string.replace(_TRIM_ZEROES, "").replace(_TRIM_TIMEZONE, "$1Z");
}
}
);
delete Date2.forEach;
Date2.now = function() {
return (new Date).valueOf(); // milliseconds since the epoch
};
Date2.parse = function(string, defaultDate) {
if (arguments.length > 1) {
assertType(defaultDate, "number", "default date should be of type 'number'.")
}
// parse ISO date
var parts = match(string, _DATE_PATTERN);
if (parts.length) {
if (parts[_DATE_PARTS.Month]) parts[_DATE_PARTS.Month]--; // js months start at zero
// round milliseconds on 3 digits
if (parts[_TIMEZONE_PARTS.Hectomicroseconds] >= 5) parts[_DATE_PARTS.Milliseconds]++;
var date = new Date(defaultDate || 0);
var prefix = parts[_TIMEZONE_PARTS.UTC] || parts[_TIMEZONE_PARTS.Hours] ? "UTC" : "";
for (var part in _DATE_PARTS) {
var value = parts[_DATE_PARTS[part]];
if (!value) continue; // empty value
// set a date part
date["set" + prefix + part](value);
// make sure that this setting does not overflow
if (date["get" + prefix + part]() != parts[_DATE_PARTS[part]]) {
return NaN;
}
}
// timezone can be set, without time being available
// without a timezone, local timezone is respected
if (parts[_TIMEZONE_PARTS.Hours]) {
var hours = Number(parts[_TIMEZONE_PARTS.Sign] + parts[_TIMEZONE_PARTS.Hours]);
var minutes = Number(parts[_TIMEZONE_PARTS.Sign] + (parts[_TIMEZONE_PARTS.Minutes] || 0));
date.setUTCMinutes(date.getUTCMinutes() + (hours * 60) + minutes);
}
return date.valueOf();
} else {
return Date.parse(string);
}
};
// =========================================================================
// JavaScript/String2.js
// =========================================================================
var String2 = _createObject2(
String,
function(string) {
return new String(arguments.length == 0 ? "" : string);
},
"charAt,charCodeAt,concat,indexOf,lastIndexOf,match,replace,search,slice,split,substr,substring,toLowerCase,toUpperCase",
{
csv: csv,
format: format,
rescape: rescape,
trim: trim
}
);
delete String2.forEach;
// http://blog.stevenlevithan.com/archives/faster-trim-javascript
function trim(string) {
return String(string).replace(_LTRIM, "").replace(_RTRIM, "");
};
function csv(string) {
return string ? (string + "").split(/\s*,\s*/) : [];
};
function format(string) {
// Replace %n with arguments[n].
// e.g. format("%1 %2%3 %2a %1%3", "she", "se", "lls");
// ==> "she sells sea shells"
// Only %1 - %9 supported.
var args = arguments;
var pattern = new RegExp("%([1-" + (arguments.length - 1) + "])", "g");
return (string + "").replace(pattern, function(match, index) {
return args[index];
});
};
function match(string, expression) {
// Same as String.match() except that this function will return an empty
// array if there is no match.
return (string + "").match(expression) || [];
};
function rescape(string) {
// Make a string safe for creating a RegExp.
return (string + "").replace(_RESCAPE, "\\$1");
};
// =========================================================================
// JavaScript/Function2.js
// =========================================================================
var Function2 = _createObject2(
Function,
Function,
"", {
I: I,
II: II,
K: K,
bind: bind,
compose: compose,
delegate: delegate,
flip: flip,
not: not,
partial: partial,
unbind: unbind
}
);
function I(i) { // return first argument
return i;
};
function II(i, ii) { // return second argument
return ii;
};
function K(k) {
return function() {
return k;
};
};
function bind(fn, context) {
var lateBound = typeof fn != "function";
if (arguments.length > 2) {
var args = _slice.call(arguments, 2);
return function() {
return (lateBound ? context[fn] : fn).apply(context, args.concat.apply(args, arguments));
};
} else { // faster if there are no additional arguments
return function() {
return (lateBound ? context[fn] : fn).apply(context, arguments);
};
}
};
function compose() {
var fns = _slice.call(arguments);
return function() {
var i = fns.length, result = fns[--i].apply(this, arguments);
while (i--) result = fns[i].call(this, result);
return result;
};
};
function delegate(fn, context) {
return function() {
var args = _slice.call(arguments);
args.unshift(this);
return fn.apply(context, args);
};
};
function flip(fn) {
return function() {
return fn.apply(this, Array2.swap(arguments, 0, 1));
};
};
function not(fn) {
return function() {
return !fn.apply(this, arguments);
};
};
function partial(fn) {
var args = _slice.call(arguments, 1);
// based on Oliver Steele's version
return function() {
var specialised = args.concat(), i = 0, j = 0;
while (i < args.length && j < arguments.length) {
if (specialised[i] === undefined) specialised[i] = arguments[j++];
i++;
}
while (j < arguments.length) {
specialised[i++] = arguments[j++];
}
if (Array2.contains(specialised, undefined)) {
specialised.unshift(fn);
return partial.apply(null, specialised);
}
return fn.apply(this, specialised);
};
};
function unbind(fn) {
return function(context) {
return fn.apply(context, _slice.call(arguments, 1));
};
};
// =========================================================================
// base2/detect.js
// =========================================================================
function detect() {
// Two types of detection:
// 1. Object detection
// e.g. detect("(java)");
// e.g. detect("!(document.addEventListener)");
// 2. Platform detection (browser sniffing)
// e.g. detect("MSIE");
// e.g. detect("MSIE|opera");
var jscript = NaN/*@cc_on||@_jscript_version@*/; // http://dean.edwards.name/weblog/2007/03/sniff/#comment85164
var javaEnabled = global.java ? true : false;
if (global.navigator) { // browser
var MSIE = /MSIE[\d.]+/g;
var element = document.createElement("span");
// Close up the space between name and version number.
// e.g. MSIE 6 -> MSIE6
var userAgent = navigator.userAgent.replace(/([a-z])[\s\/](\d)/gi, "$1$2");
// Fix opera's (and others) user agent string.
if (!jscript) userAgent = userAgent.replace(MSIE, "");
if (MSIE.test(userAgent)) userAgent = userAgent.match(MSIE)[0] + " " + userAgent.replace(MSIE, "");
base2.userAgent = navigator.platform + " " + userAgent.replace(/like \w+/gi, "");
javaEnabled &= navigator.javaEnabled();
//} else if (java) { // rhino
// var System = java.lang.System;
// base2.userAgent = "Rhino " + System.getProperty("os.arch") + " " + System.getProperty("os.name") + " " + System.getProperty("os.version");
//} else if (jscript) { // Windows Scripting Host
// base2.userAgent = "WSH";
}
var _cache = {};
detect = function(expression) {
if (_cache[expression] == null) {
var returnValue = false, test = expression;
var not = test.charAt(0) == "!";
if (not) test = test.slice(1);
if (test.charAt(0) == "(") {
try {
returnValue = new Function("element,jscript,java,global", "return !!" + test)(element, jscript, javaEnabled, global);
} catch (ex) {
// the test failed
}
} else {
// Browser sniffing.
returnValue = new RegExp("(" + test + ")", "i").test(base2.userAgent);
}
_cache[expression] = !!(not ^ returnValue);
}
return _cache[expression];
};
return detect(arguments[0]);
};
// =========================================================================
// base2/init.js
// =========================================================================
base2 = global.base2 = new Package(this, base2);
var exports = this.exports;
lang = new Package(this, lang);
exports += this.exports;
JavaScript = new Package(this, JavaScript);
eval(exports + this.exports);
lang.base = base;
lang.extend = extend;
}; //////////////////// END: CLOSURE /////////////////////////////////////
nwmatcher/build/VERSION 0000644 0001750 0001750 00000000006 12316015515 013344 0 ustar wmb wmb 1.3.3
nwmatcher/.gitignore 0000644 0001750 0001750 00000000011 12316015515 013161 0 ustar wmb wmb .DS_Store nwmatcher/README.md 0000644 0001750 0001750 00000006071 12316015515 012464 0 ustar wmb wmb # [NWMatcher](http://dperini.github.io/nwmatcher/)
A fast CSS selector engine and matcher.
## Installation
To include NWMatcher in a standard web page:
```html
```
To use it with Node.js:
```
$ npm install nwmatcher.js
```
NWMatcher 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 [Supported selectors](https://github.com/dperini/nwmatcher/wiki/CSS-supported-selectors).
## Features and Compliance
You can read more about NWMatcher [features and compliance](https://github.com/dperini/nwmatcher/wiki/Features-and-compliance) on the wiki.
## API
### DOM Selection
#### `first( selector, context )`
Returns a reference to the first element matching `selector`, starting at `context`.
#### `match( element, selector, context )`
Returns `true` if `element` matches `selector`, starting at `context`; returns `false` otherwise.
#### `select( selector, context, callback )`
Returns an array of all the elements matching `selector`, starting at `context`. 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`.
#### `byName( name, from )`
Returns an array of elements having the specified value `name` for their name attribute, optionally filtered to descendants of the element `from`.
#### `getAttribute( element, attribute )`
Return the value read from the attribute of `element` with name `attribute`, as a string.
#### `hasAttribute( element, attribute )`
Returns true `element` has an attribute with name `attribute` set; returns `false` otherwise.
### Engine Configuration
#### `configure( options )`
The following options exist and can be set to `true` or `false`:
* `CACHING`: enable caching of results
* `SHORTCUTS`: allow accepting mangled selectors
* `SIMPLENOT`: disallow nested complex `:not()` selectors
* `UNIQUE_ID`: disallow multiple elements with same ID
* `USE_QSAPI`: enable native `querySelectorAll` if available
* `USE_HTML5`: enable special HTML5 rules, related to the relationship between `:checked` and `:selected`
* `VERBOSITY`: choose between throwing errors or just console warnings
Example:
```js
NW.Dom.configure( { USE_QSAPI: false, VERBOSITY: false } );
```
#### `registerOperator( symbol, resolver )`
Registers a new symbol and its matching resolver in the operators table. Example:
```js
NW.Dom.registerOperator( '!=', 'n!="%m"' );
```
#### `registerSelector( name, rexp, func )`
Registers a new selector, with the matching regular expression and the appropriate resolver function, in the selectors table.
nwmatcher/test/ 0000755 0001750 0001750 00000000000 12316015515 012160 5 ustar wmb wmb nwmatcher/test/ender/ 0000755 0001750 0001750 00000000000 12316015515 013255 5 ustar wmb wmb nwmatcher/test/ender/.gitignore 0000644 0001750 0001750 00000000032 12316015515 015240 0 ustar wmb wmb node_modules
ender.min.js
nwmatcher/test/ender/integration.html 0000644 0001750 0001750 00000005365 12316015515 016477 0 ustar wmb wmb
Simple NWMatcher Ender Integration Tests
nwmatcher/test/ender/sink-test/ 0000755 0001750 0001750 00000000000 12316015515 015176 5 ustar wmb wmb nwmatcher/test/ender/sink-test/sink.js 0000644 0001750 0001750 00000013041 12316015515 016477 0 ustar wmb wmb /*!
* Sink - Browser & Headless JavaScript Unit Tester
* copyright Dustin Diaz & Jacob Thornton
* https://github.com/ded/sink-test
* License MIT
*/
!function(context) {
var total = 0
, logKey = ''
, fail = false
, modules = []
, tests = []
, item
, setPasses = true
, allPass = true
, beforeMethods = []
, afterMethods = []
, currentSetName
, isHeadless = (typeof module !== 'undefined' && module.exports)
isHeadless ? (require('colors')) : String.prototype.__defineGetter__ && !function () {
each(['red', 'green', 'magenta', 'rainbow', 'yellow'], function (color) {
String.prototype.__defineGetter__(color, function () {
return this.replace(/( )/, '$1') // stupid workaround to not log an object
})
String.prototype.__defineSetter__(color, function (v) {})
})
}()
!isHeadless && window && !('console' in window) && !function () {
context.console = {log: function () {}}
}()
function reset() {
total = 0
fail = false
init()
}
function failure(li, check) {
setPasses = false
allPass = false
if (!isHeadless) {
check.innerHTML = '✗'
li.className = 'fail'
}
reset()
}
function each(items, fn) {
for (var i = 0; i < items.length; i++) fn(items[i])
}
function pass(li, check) {
if (!isHeadless) {
check.innerHTML = '✓'
li.className = 'pass'
}
reset()
}
function before(fn) {
fn ? beforeMethods.push(fn) : each(beforeMethods, function (f) {
f()
})
}
function after(fn) {
fn ? afterMethods.push(fn) : each(afterMethods, function (f) {
f()
})
}
function bind(li) {
li.onclick = function() {
var ul = this.getElementsByTagName('ul')[0]
ul.className = (ul.className) ? '' : 'show'
}
}
function _test(name, expect, fn) {
before()
total = expect
var li, check, start = +new Date
if (!isHeadless) {
li = document.createElement('li')
li.innerHTML = name + ' ... o
'
item = li.getElementsByTagName('ul')[0]
bind(li)
check = li.getElementsByTagName('span')[0]
document.getElementById('tests').appendChild(li)
} else {
console.log(logKey + (name + '...').yellow)
}
fn()
setTimeout(function() {
if (sink.timeout && (+new Date - start > sink.timeout)) {
failure(li, check)
after()
} else {
if (fail) {
failure(li, check)
after()
} else if (!total) {
after()
pass(li, check)
} else {
setTimeout(arguments.callee, 10)
}
}
}, 10)
}
function test(name, expect, fn) {
tests.push({
name: name,
expect: expect,
fn: fn
})
}
function init() {
if (tests.length) {
var o = tests.shift()
_test(o.name, o.expect, o.fn)
} else {
setPasses = true
start()
}
}
function assert(actual, expected, msg) {
var b = actual === expected
, message = b ? '' : 'actual: ' + actual.toString() + 'expected: ' + expected.toString() + ''
if (isHeadless) {
message = b ? '' : '\n\tactual: ' + actual.toString() + '\n\texpected: ' + expected.toString()
if (b) console.log(logKey + msg + (message + ' ✓').green)
else console.log(logKey + msg + (message + ' ✗').red)
} else {
var li = document.createElement('li')
li.className = b ? 'pass' : 'fail'
li.innerHTML = msg + ' ' + message + ' ' + '' + (b ? '✓' : '✗') + ''
item.appendChild(li)
}
if (b) total--
else fail = true
}
function ok(b, message) {
if (isHeadless) {
if (b) console.log(logKey + (message + ' ✓').green)
else console.log(logKey + (message + ' ✗').red)
} else {
var li = document.createElement('li')
li.className = b ? 'pass' : 'fail'
li.innerHTML = message + ' ' + (b ? '✓' : '✗')
item.appendChild(li)
}
if (b) total--
else fail = true
}
function sink(name, fn) {
modules.push({
name: name,
fn: fn
})
}
function nextGroup(name, fn) {
beforeMethods = []
afterMethods = []
var mod = ('MODULE: ' + name)
if (isHeadless) {
console.log(logKey + mod.magenta)
} else {
var li = document.createElement('li')
li.innerHTML = mod
document.getElementById('tests').appendChild(li)
li.className = 'mod'
}
fn(test, ok, before, after, assert)
currentSetName = name
init()
}
function start() {
var current = modules.shift()
current ? nextGroup(current.name, current.fn) : !function () {
var message = [
'Congratulations! All tests have passed!'
, 'There were some errors! The suite has failed.'
]
, color = allPass ? 'rainbow' : 'red'
, status = allPass ? 'sink-pass' : 'sink-failure'
message = message[allPass ? 0 : 1].toUpperCase()
isHeadless ?
console.log(logKey + message[color]) :
(document.getElementById('tests').className = status)
}()
}
function setLogKey (key) {
var log = console.log
logKey = key || '$__sinkTest::'
console.log = function (msg) {
if (~(''+msg).indexOf(logKey)) {
log(msg.replace(logKey, ''))
}
}
}
if (isHeadless) {
exports.sink = sink
exports.start = start
exports.sink.timeout = 10000
exports.setLogKey = setLogKey
} else {
context.sink = sink
context.start = start
context.sink.timeout = 10000
}
}(this)
nwmatcher/test/ender/sink-test/sink.css 0000644 0001750 0001750 00000003262 12316015515 016657 0 ustar wmb wmb body {
width: 650px;
margin: 20px auto;
font: 300 16px 'helvetica neue', helvetica, arial;
text-shadow: 0 2px 2px #ccc;
}
h1 {
font-size: 30px;
font-weight: 300;
}
ol,li {
list-style: none;
}
ol {
-moz-box-shadow: 0 0 5px #ccc;
-moz-border-radius: 5px;
-webkit-box-shadow: 0 0 5px #ccc;
-webkit-border-radius: 5px;
box-shadow: 0 0 5px #ccc;
border-radius: 5px;
padding: 10px;
}
ol.sink-pass {
background-color: lightgreen;
}
ol.sink-failure {
background-color: lightpink;
}
li {
margin: 3px 5px;
padding: 5px;
-webkit-border-radius: 5px;
-moz-border-radius: 5px;
border-radius: 5px;
overflow: hidden;
cursor: pointer;
}
ol > li {
opacity: 0;
background-color: lightblue;
color: #000;
}
li span {
color: #aaa;
text-align: right;
display: inline-block;
float: right;
}
li.fail span {
color: red;
}
li.pass span {
color: green;
}
li.fail {
background-color: #eed5d2;
}
li.pass {
background-color: #bdfcc9;
}
li.pass, li.fail, li.mod {
-webkit-transition: opacity .5s linear;
opacity: 1;
}
li ul {
height: 0;
overflow: hidden;
margin: 0;
padding: 0;
list-style: none;
position: relative; /*early IE overflow bug*/
}
li ul.show {
position: static; /*early IE overflow bug*/
}
li.pass ul.show {
background-color: #8fffa3;
}
li.fail ul.show {
background-color: #efada4;
}
li ul.show {
height: auto;
padding: 5px;
-webkit-border-radius: 5px;
-moz-border-radius: 5px;
border-radius: 5px;
margin: 5px;
}
li ul li {
padding: 3px 6px;
margin: 2px 0;
list-style: none;
font-size: 15px;
}
li b {
display: block;
margin-left: 40px;
}
li em.marker {
display: block;
position: absolute;
right: 5px;
top: 0;
}
nwmatcher/test/ender/tests.js 0000644 0001750 0001750 00000056313 12316015515 014765 0 ustar wmb wmb var Q = $
sink('Contexts', function (test, ok) {
test('should be able to pass optional context', 2, function () {
ok(Q('.a').length === 3, 'no context found 3 elements (.a)');
ok(Q('.a', Q('#boosh')).length === 2, 'context found 2 elements (#boosh .a)');
});
test('should be able to pass string as context', 5, function() {
ok(Q('.a', '#boosh').length == 2, 'context found 2 elements(.a, #boosh)');
ok(Q('.a', '.a').length == 0, 'context found 0 elements(.a, .a)');
ok(Q('.a', '.b').length == 1, 'context found 1 elements(.a, .b)');
ok(Q('.a', '#boosh .b').length == 1, 'context found 1 elements(.a, #boosh .b)');
ok(Q('.b', '#boosh .b').length == 0, 'context found 0 elements(.b, #boosh .b)');
});
test('should be able to pass qwery result as context', 5, function() {
ok(Q('.a', Q('#boosh')).length == 2, 'context found 2 elements(.a, #boosh)');
ok(Q('.a', Q('.a')).length == 0, 'context found 0 elements(.a, .a)');
ok(Q('.a', Q('.b')).length == 1, 'context found 1 elements(.a, .b)');
ok(Q('.a', Q('#boosh .b')).length == 1, 'context found 1 elements(.a, #boosh .b)');
ok(Q('.b', Q('#boosh .b')).length == 0, 'context found 0 elements(.b, #boosh .b)');
});
test('should not return duplicates from combinators', 2, function () {
ok(Q('#boosh,#boosh').length == 1, 'two booshes dont make a thing go right');
ok(Q('#boosh,.apples,#boosh').length == 1, 'two booshes and an apple dont make a thing go right');
});
test('byId sub-queries within context', 5, function() {
ok(Q('#booshTest', Q('#boosh')).length == 1, 'found "#id #id"')
ok(Q('.a.b #booshTest', Q('#boosh')).length == 1, 'found ".class.class #id"')
ok(Q('.a>#booshTest', Q('#boosh')).length == 1, 'found ".class>#id"')
ok(!Q('#boosh', Q('#booshTest')).length, 'shouldn\'t find #boosh (ancestor) within #booshTest (descendent)')
ok(!Q('#boosh', Q('#lonelyBoosh')).length, 'shouldn\'t find #boosh within #lonelyBoosh (unrelated)')
})
});
sink('CSS 1', function (test, ok) {
test('get element by id', 2, function () {
var result = Q('#boosh');
ok(!!result[0], 'found element with id=boosh');
ok(!!Q('h1')[0], 'found 1 h1');
});
test('byId sub-queries', 4, function() {
ok(Q('#boosh #booshTest').length == 1, 'found "#id #id"')
ok(Q('.a.b #booshTest').length == 1, 'found ".class.class #id"')
ok(Q('#boosh>.a>#booshTest').length == 1, 'found "#id>.class>#id"')
ok(Q('.a>#booshTest').length == 1, 'found ".class>#id"')
})
test('get elements by class', 6, function () {
ok(Q('#boosh .a').length == 2, 'found two elements');
ok(!!Q('#boosh div.a')[0], 'found one element');
ok(Q('#boosh div').length == 2, 'found two {div} elements');
ok(!!Q('#boosh span')[0], 'found one {span} element');
ok(!!Q('#boosh div div')[0], 'found a single div');
ok(Q('a.odd').length == 1, 'found single a');
});
test('combos', 1, function () {
ok(Q('#boosh div,#boosh span').length == 3, 'found 2 divs and 1 span');
});
test('class with dashes', 1, function() {
ok(Q('.class-with-dashes').length == 1, 'found something');
});
test('should ignore comment nodes', 1, function() {
ok(Q('#boosh *').length === 4, 'found only 4 elements under #boosh')
});
test('deep messy relationships', 6, function() {
// these are mostly characterised by a combination of tight relationships and loose relationships
// on the right side of the query it's easy to find matches but they tighten up quickly as you
// go to the left
// they are useful for making sure the dom crawler doesn't stop short or over-extend as it works
// up the tree the crawl needs to be comprehensive
ok(Q('div#fixtures > div a').length == 5, 'found four results for "div#fixtures > div a"')
ok(Q('.direct-descend > .direct-descend .lvl2').length == 1, 'found one result for ".direct-descend > .direct-descend .lvl2"')
ok(Q('.direct-descend > .direct-descend div').length == 1, 'found one result for ".direct-descend > .direct-descend div"')
ok(Q('.direct-descend > .direct-descend div').length == 1, 'found one result for ".direct-descend > .direct-descend div"')
ok(Q('div#fixtures div ~ a div').length == 0, 'found no results for odd query')
ok(Q('.direct-descend > .direct-descend > .direct-descend ~ .lvl2').length == 0, 'found no results for another odd query')
});
});
sink('CSS 2', function (test, ok) {
test('get elements by attribute', 4, function () {
var wanted = Q('#boosh div[test]')[0];
var expected = document.getElementById('booshTest');
ok(wanted == expected, 'found attribute');
ok(Q('#boosh div[test=fg]')[0] == expected, 'found attribute with value');
ok(Q('em[rel~="copyright"]').length == 1, 'found em[rel~="copyright"]');
ok(Q('em[nopass~="copyright"]').length == 0, 'found em[nopass~="copyright"]');
});
test('should not throw error by attribute selector', 1, function () {
ok(Q('[foo^="bar"]').length === 1, 'found 1 element');
});
test('crazy town', 1, function () {
var el = document.getElementById('attr-test3');
ok(Q('div#attr-test3.found.you[title="whatup duders"]')[0] == el, 'found the right element');
});
});
sink('CSS 2 identification', function (test, ok) {
// cases that we should be able to pass through to native non-CSS3 qSA where present (IE8)
// we get to ignore grouping here since selectors are split up for this case anyway
// we also get to work with normalized selectors
// this regex must be kept in sync with the one in src/qwery.js for the test to make sense
var css2 = /^(([\w\-]*[#\.]?[\w\-]+|\*)?(\[[\w\-]+([\~\|]?=['"][ \w\-\/\?\&\=\:\.\(\)\!,@#%<>\{\}\$\*\^]+["'])?\])?(\:(link|visited|active|hover))?([\s>+~\.,]|(?:$)))+$/
, css2Selectors = [
'*',
, 'DIV',
, 'e1 e2',
, 'parent>child'
, 'parent+child'
, 'parent~child' // CSS3 but IE8 supports ~
, '#id'
, 'el#id'
, 'el #id'
, 'el>#id'
, '#id>#id2'
, '.class'
, 'div.class'
, '#id.class'
, 'element.with.multiple.classes>bam'
//, 'el:first-child' -> IE8 buggy, don't do native
, 'a:link'
, 'a#id:link'
, '.class:visited'
, '#boo:active'
, 'div.class:hover'
//, '*:focus' -> IE8 doesn't support, don't do native
, 'hoo[foo]'
, '#hah[boo="moo"]'
, '.claz[attrib~=\'nooooooo!\']'
, 'ele[prop|="huh?"]'
, '.direct-descend>.direct-descend>.direct-descend'
, '.direct-descend>.direct-descend>.direct-descend~.lvl2'
]
, nonCSS2Selectors = [
'p:empty'
, 'hoo:enabled'
, 'haa:disabled'
, '#bing:checked'
, '*:first-of-type'
, '*:last-of-type'
, '.class:last-child'
, 'yes:not'
, 'p:nth-child(2n+1)'
, 'p:nth-last-child(1n+2)'
, 'p:nth-last-of-type(3n+3)'
, 'p:nth-of-type(4n+2)'
, '*:only-child'
, '*:only-of-type'
, 'p#id:root'
, '#gak::selection'
, 'body:target'
// CSS2 buggy
, 'el:first-child'
, '*:focus'
]
test('CSS2 selectors', css2Selectors.length, function() {
for (var i = 0; i < css2Selectors.length; i++) {
ok(css2.test(css2Selectors[i]), 'matched ' + css2Selectors[i])
}
})
test('CSS2 selectors grouped', 1, function() {
ok(css2.test(css2Selectors.join(',')), 'matched grouped CSS2 selectors')
})
test('non-CSS2 selectors', nonCSS2Selectors.length, function() {
for (var i = 0; i < nonCSS2Selectors.length; i++) {
ok(!css2.test(nonCSS2Selectors[i]), 'did not matche ' + nonCSS2Selectors[i])
}
})
});
sink('attribute selectors', function (test, ok, b, a, assert) {
/* CSS 2 SPEC */
test('[attr]', 1, function () {
var expected = document.getElementById('attr-test-1');
ok(Q('#attributes div[unique-test]')[0] == expected, 'found attribute with [attr]');
});
test('[attr=val]', 3, function () {
var expected = document.getElementById('attr-test-2');
ok(Q('#attributes div[test="two-foo"]')[0] == expected, 'found attribute with =');
ok(Q("#attributes div[test='two-foo']")[0] == expected, 'found attribute with =');
ok(Q('#attributes div[test=two-foo]')[0] == expected, 'found attribute with =');
});
test('[attr~=val]', 1, function () {
var expected = document.getElementById('attr-test-3');
ok(Q('#attributes div[test~=three]')[0] == expected, 'found attribute with ~=');
});
test('[attr|=val]', 2, function () {
var expected = document.getElementById('attr-test-2');
ok(Q('#attributes div[test|="two-foo"]')[0] == expected, 'found attribute with |=');
ok(Q('#attributes div[test|=two]')[0] == expected, 'found attribute with |=');
});
test('[href=#x] special case', 1, function () {
var expected = document.getElementById('attr-test-4');
ok(Q('#attributes a[href="#aname"]')[0] == expected, 'found attribute with href=#x');
});
/* CSS 3 SPEC */
test('[attr^=val]', 1, function () {
var expected = document.getElementById('attr-test-2');
ok(Q('#attributes div[test^=two]')[0] == expected, 'found attribute with ^=');
});
test('[attr$=val]', 1, function () {
var expected = document.getElementById('attr-test-2');
ok(Q('#attributes div[test$=foo]')[0] == expected, 'found attribute with $=');
});
test('[attr*=val]', 1, function () {
var expected = document.getElementById('attr-test-3');
ok(Q('#attributes div[test*=hree]')[0] == expected, 'found attribute with *=');
});
test('direct descendants', 2, function () {
ok(Q('#direct-descend > .direct-descend').length == 2, 'found two direct descendents');
ok(Q('#direct-descend > .direct-descend > .lvl2').length == 3, 'found three second-level direct descendents');
});
test('sibling elements', 17, function () {
assert(Q('#sibling-selector ~ .sibling-selector').length, 2, 'found two siblings')
assert(Q('#sibling-selector ~ div.sibling-selector').length, 2, 'found two siblings')
assert(Q('#sibling-selector + div.sibling-selector').length, 1, 'found one sibling')
assert(Q('#sibling-selector + .sibling-selector').length, 1, 'found one sibling')
assert(Q('.parent .oldest ~ .sibling').length, 4, 'found four younger siblings')
assert(Q('.parent .middle ~ .sibling').length, 2, 'found two younger siblings')
assert(Q('.parent .middle ~ h4').length, 1, 'found next sibling by tag')
assert(Q('.parent .middle ~ h4.younger').length, 1, 'found next sibling by tag and class')
assert(Q('.parent .middle ~ h3').length, 0, 'an element can\'t be its own sibling')
assert(Q('.parent .middle ~ h2').length, 0, 'didn\'t find an older sibling')
assert(Q('.parent .youngest ~ .sibling').length, 0, 'found no younger siblings')
assert(Q('.parent .oldest + .sibling').length, 1, 'found next sibling')
assert(Q('.parent .middle + .sibling').length, 1, 'found next sibling')
assert(Q('.parent .middle + h4').length, 1, 'found next sibling by tag')
assert(Q('.parent .middle + h3').length, 0, 'an element can\'t be its own sibling')
assert(Q('.parent .middle + h2').length, 0, 'didn\'t find an older sibling')
assert(Q('.parent .youngest + .sibling').length, 0, 'found no younger siblings')
});
});
sink('element-context queries', function(test, ok) {
// should be able to query on an element that hasn't been inserted into the dom
var frag = document.createElement('div')
frag.innerHTML = '
'
test('detached fragments', 1, function() {
ok(Q('.a span', frag).length == 1, 'should find child elements of fragment')
})
test('byId sub-queries within detached fragment', 5, function () {
ok(Q('#emem', frag).length == 1, 'found "#id" in fragment')
ok(Q('.d.i #emem', frag).length == 1, 'found ".class.class #id" in fragment')
ok(Q('.d #oooo #emem', frag).length == 1, 'found ".class #id #id" in fragment')
ok(!Q('#oooo', Q('#emem', frag)).length, 'shouldn\'t find #oooo (ancestor) within #emem (descendent)')
ok(!Q('#sep', Q('#emem', frag)).length, 'shouldn\'t find #sep within #emem (unrelated)')
})
test('exclude self in match', 1, function() {
ok(Q('.order-matters', Q('#order-matters')).length == 4, 'should not include self in element-context queries')
});
// because form's have .length
test('forms can be used as contexts', 1, function() {
ok(Q('*', Q('form')[0]).length === 3, 'found 3 elements under <form>')
})
})
sink('tokenizer', function (test, ok) {
test('should not get weird tokens', 5, function () {
ok(Q('div .tokens[title="one"]')[0] == document.getElementById('token-one'), 'found div .tokens[title="one"]');
ok(Q('div .tokens[title="one two"]')[0] == document.getElementById('token-two'), 'found div .tokens[title="one two"]');
ok(Q('div .tokens[title="one two three #%"]')[0] == document.getElementById('token-three'), 'found div .tokens[title="one two three #%"]');
ok(Q("div .tokens[title='one two three #%'] a")[0] == document.getElementById('token-four'), 'found div .tokens[title=\'one two three #%\'] a');
ok(Q('div .tokens[title="one two three #%"] a[href$=foo] div')[0] == document.getElementById('token-five'), 'found div .tokens[title="one two three #%"] a[href=foo] div');
});
});
sink('interesting syntaxes', function (test, ok) {
test('should parse bad selectors', 1, function () {
ok(Q('#spaced-tokens p em a').length, 'found element with funny tokens')
});
});
sink('order matters', function (test, ok) {
function tag(el) {
return el.tagName.toLowerCase();
}
//