Compare commits

...

148 Commits
0.1.0 ... 0.2.1

Author SHA1 Message Date
John-David Dalton
f81ede2fd6 Update changelog with intersect removal.
Former-commit-id: 5902c720c1403b856ac213e293619c31ea6834f5
2012-05-24 18:02:35 -04:00
John-David Dalton
6f7df67ded Cleanup README.md.
Former-commit-id: 6ad747a8ae56f32fd558bd141af6fe95847569ad
2012-05-24 17:50:20 -04:00
John-David Dalton
bb9ad69219 Bump to v0.2.1.
Former-commit-id: d433d39ac7269479f1b9ac3803e62c5021f41e11
2012-05-24 17:08:26 -04:00
John-David Dalton
8f7667a524 Simplify _.max, _.min, and _.bind.
Former-commit-id: 1da0b013d0c47748d757e90248eebe9ed51918ae
2012-05-24 10:02:32 -04:00
John-David Dalton
86e125a6f3 Update minified build and docs.
Former-commit-id: 8c96c3812064f93d404e6d6dda68ab7a865d4228
2012-05-24 02:24:40 -04:00
John-David Dalton
8b3ba13ff0 Cleanup perf.js.
Former-commit-id: 8799b7d384cc48bc1c8ea3289aa12e021be2b97b
2012-05-24 02:23:55 -04:00
John-David Dalton
82f062caf2 Sync with Underscore.
Former-commit-id: 2e3aacd53fef6d22d830dbc2d6c220808aea8739
2012-05-24 02:06:10 -04:00
John-David Dalton
67303eb9fb Update Backbone and Underscore submodules.
Former-commit-id: 43178330e273531286982e34acf96dadf9586f03
2012-05-24 01:43:54 -04:00
John-David Dalton
af3ded68c4 Cleanup _.bind.
Former-commit-id: d974cdfa52c3f6c175e57f0970380bcc9276c35d
2012-05-24 01:40:24 -04:00
John-David Dalton
b94eb44e18 Update minified build and docs.
Former-commit-id: 525d891914a86b1f7167c9dd82b9deaaad453058
2012-05-24 01:30:48 -04:00
John-David Dalton
c62b24b024 Make _.bind follow ES5 spec so it will work with a common Backbone pattern. [closes #11]
Former-commit-id: 8d5e399ca9727a32604601f81fffd9134104c8f4
2012-05-24 01:25:08 -04:00
John-David Dalton
baa37450cc Tweak export order for r.js.
Former-commit-id: 81f8f3feae9228e99978710c0193a9d26bb9b519
2012-05-23 17:06:21 -04:00
John-David Dalton
231fd46cd2 Ensure applet is hidden in perf/index.html.
Former-commit-id: ee23b966eca9148bbecd8d0826d954e755d232fe
2012-05-23 17:00:49 -04:00
John-David Dalton
b2728d9902 Update docs.
Former-commit-id: 462a64eeb8f8afb0951d8449f0f7b766abbcf5cc
2012-05-23 14:52:15 -04:00
John-David Dalton
451a33f526 Add _.difference, _.pick, and _.union benchmarks.
Former-commit-id: 1dd1e577520dfc1a69876eeccadce871f1f05916
2012-05-23 14:30:45 -04:00
John-David Dalton
3670bce918 Add _.flatten test to ensure consistent behavior with sparse arrays.
Former-commit-id: 5505f4d0542596e4c6469aa038fa1bfecaa79800
2012-05-23 14:28:51 -04:00
John-David Dalton
afb041b23c Update docs and minified build.
Former-commit-id: 8ece30dc91c7cd9fe9f936fdf09e6d673566eaef
2012-05-23 02:20:25 -04:00
John-David Dalton
5315058e2d Simplify _.flatten and add benchmarks.
Former-commit-id: f541328bf680a75abea68bce813820def375f4a0
2012-05-23 02:19:35 -04:00
John-David Dalton
26d9cc972e Add unit test to test to ensure _.groupBy only adds elements to own, not inherited, properties of the result object.
Former-commit-id: 61dcdd0f6172db66d62e97873c1bc3053e339342
2012-05-23 01:25:34 -04:00
John-David Dalton
52ae87812e Update docs and minified build.
Former-commit-id: f019b90d5e866bf2a6da1c003001d0e9345bb0b1
2012-05-23 01:01:35 -04:00
John-David Dalton
f8af24b383 Remove unneeded variable references.
Former-commit-id: ab2f5f4408db25dc63b5d85b4adf156f9f978711
2012-05-23 00:52:39 -04:00
John-David Dalton
b38947146e Move _.groupBy and _.size to the "Objects" category and shuffle method order to avoid extra private variables.
Former-commit-id: 8dc89136a3bf2ed94f594f5c1c1f97a0dd7291c4
2012-05-23 00:43:23 -04:00
John-David Dalton
5c48abff4b Add links to relevant sections in the description.
Former-commit-id: da9e65fadae73792cfb2ec885318bc073d4468c3
2012-05-22 13:10:43 -04:00
John-David Dalton
3994c7fc2b Update docdown submodule and README.md.
Former-commit-id: 745eccb03a7eed1f3f2ef696002c57d6fcc44d25
2012-05-22 13:01:14 -04:00
John-David Dalton
859f2b2f3b Cleanup README.md.
Former-commit-id: 378c558d55f267b0469be8622881b1501c4907fc
2012-05-22 00:11:41 -04:00
John-David Dalton
f5040a7bec Cleanup .npmignore, and .gitignore.
Former-commit-id: 2309e25274dcceca8e05c2c570594d9adbe1c669
2012-05-22 00:11:27 -04:00
John-David Dalton
a604494aa9 Bump to v0.2.0.
Former-commit-id: 4b5cfd178edce968244a1fcad8c7b74e336e0f08
2012-05-21 15:55:52 -04:00
John-David Dalton
eaaef83ace Update README.md for version bump.
Former-commit-id: dceae7cfcfade966145032cbf1d787e309e529c2
2012-05-21 15:34:09 -04:00
John-David Dalton
9cf1424d8f Cleanup JSDoc comments.
Former-commit-id: ce8e7885528c1a7097cf6b73a713c960a20f85f6
2012-05-21 15:33:45 -04:00
John-David Dalton
cb74e45b89 Cleanup docs.
Former-commit-id: 346b2f7c55e3d0eb3b86f19c05fa9964f998b483
2012-05-21 12:26:53 -04:00
John-David Dalton
1da0498f74 Cleanup the README.md.
Former-commit-id: a01247eeb5c4602a3c209ed15753cbf2af32fdbf
2012-05-21 12:09:11 -04:00
John-David Dalton
754b1de597 Cleanup and prep for v0.2.0.
Former-commit-id: 27fb5b6ce649bedae9ba8127278322a037075e41
2012-05-21 11:32:43 -04:00
John-David Dalton
7e39941ad3 Reverse order of environments in run-perf.sh.
Former-commit-id: 8ee0ed5dd569c4e7dd32badd7aabe2e29b579b60
2012-05-21 10:05:08 -04:00
John-David Dalton
79a27b18ce Fix regression on adding the copyright comment header to minified builds.
Former-commit-id: b3ec50141716e9132ea629de3a14c22f718d25ab
2012-05-21 09:59:06 -04:00
John-David Dalton
194551fdbf Make build.js less picky about comma separated method names.
Former-commit-id: 8624cfaad62ddd4921baaea1ece20730ced680bf
2012-05-20 23:40:18 -04:00
John-David Dalton
5a82c8f89b Update minified build and docs.
Former-commit-id: 3aa2cb29b041c4031dd196d06c1914b42e4773c2
2012-05-20 23:18:09 -04:00
John-David Dalton
2e540368eb Fix _.extend regression in IE < 9.
Former-commit-id: 65632fbbf3aaba0d9cd8578300f8025e311faff0
2012-05-20 23:11:04 -04:00
John-David Dalton
d5966ae5db Update minified build and docs.
Former-commit-id: 4ad3460c6b1a518c5299a8d11fbd322705b3a963
2012-05-20 20:39:41 -04:00
John-David Dalton
97f4dfc089 Add comment explaining JavaScript engine's arguments.length limit and add shim file to underscore.html.
Former-commit-id: ace6dae609cab05b86ddc60a7f8c980447da2bdc
2012-05-20 20:38:32 -04:00
John-David Dalton
b03c2b3b8f Make custom build regexp less picky and fix typo in build.js.
Former-commit-id: 6be9d35758f5a3f82ff1a01d02d8a3f17e0d9a97
2012-05-20 20:37:13 -04:00
John-David Dalton
9a81df6d77 Hide unused element in backbone.html and make perf tests use the minified versions of each lib.
Former-commit-id: 45cfd91d41dc454399be35004ed8bcf5d6293554
2012-05-20 19:12:22 -04:00
John-David Dalton
a9d55121bb Fix regression in CLI test runner for Narwhal, Rhino, and RingoJS.
Former-commit-id: e58807535bc42f1922b4484caeb336d7a9da5aaf
2012-05-20 19:11:36 -04:00
John-David Dalton
88327aeba2 Use nano.jar in perf/index.html.
Former-commit-id: a5a3d79dd2c940dd654d2c91cf80665d72b22080
2012-05-20 05:26:39 -04:00
John-David Dalton
8e2d972281 Make indistinguishable results in perf.js the same score.
Former-commit-id: 550c42ba8d07bde5fe1cf57d5bd27df7bc42dd12
2012-05-20 04:46:18 -04:00
John-David Dalton
7b44ef1664 Cleanup pref.'s style and add comment.
Former-commit-id: ab01044b50ef4a6d447e3e937c31cf5747b3113b
2012-05-20 04:32:57 -04:00
John-David Dalton
5204fac055 Rename /benchmark to /perf.
Former-commit-id: 3688f3aeaf1e7d290d863cdba0d2277afcffa2e8
2012-05-20 04:25:19 -04:00
John-David Dalton
c2a1f50dc0 Cleanup benchmark/benchmark.js, add firebug-lite, and add support for Narwhal, Rhino, and Ringo.
Former-commit-id: e08ede5bee3fdfbeb648b855dfb3082e66e68c0b
2012-05-20 04:14:56 -04:00
John-David Dalton
c8f3b128cb Merge pull request #9 from sindresorhus/benchmark
Add Node.js benchmarks. [fixes #8]

Former-commit-id: 28c7f83738da1f34dfdf5c2f1998834d6c802d0f
2012-05-19 21:11:09 -07:00
John-David Dalton
b32ed95597 Update Benchmark.js submodule.
Former-commit-id: 884ce35aa3e829109be55f96fa796a2af37d97a4
2012-05-20 00:09:04 -04:00
John-David Dalton
57da1d3062 Update docs and builds.
Former-commit-id: 5cc75c2294af4022855c18a9f1e6d82a2e50c244
2012-05-19 23:56:29 -04:00
John-David Dalton
6dfe18fe18 Add custom build options to build.js.
Former-commit-id: 4df20584d5c8852caf0f123d618dbf61f18c220c
2012-05-19 23:54:07 -04:00
John-David Dalton
1dd9ee2397 Switch to non-deprecated fs.existsSync.
Former-commit-id: 616863cf7e7edfdf919750773a12e8cd2a42ddf1
2012-05-19 23:53:35 -04:00
John-David Dalton
d31471c6a1 Correct the minified AMD signature for AMD build optimizers and unescape whitelisted properties from Uglified source.
Former-commit-id: 93ccbb77d376b39a1b5dd38cbe74f9b4d4382e3f
2012-05-19 23:53:00 -04:00
John-David Dalton
930f04951f Add more properties to the pre-compile whitelist and cleanup regexps.
Former-commit-id: c2d557b7bfd882b3a3b1f75011c6f32de8058350
2012-05-19 23:51:40 -04:00
John-David Dalton
8846835ab8 Remove extend as a core dependency, and avoid uncatchable error in Java environments, and ensure templates are inlineable.
Former-commit-id: d7a4de60cf264893d9db68b97940744c6dd3cc3a
2012-05-19 23:50:47 -04:00
John-David Dalton
b080cc4d23 Update submodules and unit test setup.
Former-commit-id: 705059ee5d27e828cd216ecdd164c4c9bceae26c
2012-05-19 23:48:40 -04:00
Sindre Sorhus
c910a95ee4 Add Node.js benchmark. Fixes #8
Former-commit-id: b60a09b6f0ed1d0880fb83f519c3755fa14cd625
2012-05-15 21:43:48 +02:00
John-David Dalton
4601129fc7 Cleanup and comment lodash.js.
Former-commit-id: 468f9e107959c6d637a4acd0dea0cf8f4eb921c2
2012-05-15 11:52:22 -04:00
John-David Dalton
9c79259e9c Add JScript [[DontEnum]] _.size unit test.
Former-commit-id: 734b1943bb7c5f9111f170afccdf0b169fb2cca7
2012-05-15 11:26:56 -04:00
John-David Dalton
bdca0cf668 Update docdown/benchmark.js submodules.
Former-commit-id: 5945b39eb0fcde967c6747ba2c36e94072580805
2012-05-15 11:20:30 -04:00
John-David Dalton
628ad0fcb2 Add comment to _.escape.
Former-commit-id: bee148c238552d3cdb6bba3a3511f3d0c5484850
2012-05-15 02:16:50 -04:00
John-David Dalton
793332beb8 Further simplify _.forEach.
Former-commit-id: 0d6363219836706c411473187dbf6b5516f8574a
2012-05-15 01:58:31 -04:00
John-David Dalton
4e9688cc18 Cleanup build scripts.
Former-commit-id: 7b3bd75f3482297baacc60479579ff74c56e8966
2012-05-15 01:58:31 -04:00
John-David Dalton
ef9a6a0027 Update submodules and add Backbone.js tests.
Former-commit-id: ed8bf8bbaa9ecb268252c5d5b47de85282fb0ff4
2012-05-15 01:58:30 -04:00
John-David Dalton
9e9222c65d Change reported minified size from KB to bytes.
Former-commit-id: 35276bfeda03ca7158f19b265cc5d0863dd9286f
2012-05-15 01:58:30 -04:00
John-David Dalton
9ef0d9084f Optimize _.forEach, cleanup _.after and _.isArguments.
Former-commit-id: 3e3e9539ee6429a72f74f184f45f9c4c52bb621a
2012-05-14 18:48:53 -04:00
John-David Dalton
36df8f7828 Add custom build include and exclude options to build.js.
Former-commit-id: 5d61f47840e51937506d94f65bb55b4f97fe9f19
2012-05-14 18:47:11 -04:00
John-David Dalton
8ee1cc8d27 Minor cleanup in post-compile.js.
Former-commit-id: 94ec69e163de2874385e0a2abaa7ef62c075005e
2012-05-14 18:43:57 -04:00
John-David Dalton
e4e2658a3b Make pre-compile.js avoid erroring when lodash functions are missing.
Former-commit-id: 61f56f206225e1bb0232faea5624d541bc905aa0
2012-05-14 18:43:32 -04:00
John-David Dalton
ae8e7ae992 Rename Minify to minify.
Former-commit-id: 595b9dbeab4f2822626c74a18379262a8d583cfd
2012-05-14 18:38:42 -04:00
John-David Dalton
e0c936ba03 Update minified build and docs.
Former-commit-id: 37fc52f39bcdfdadb1cdbd49d9f8b2a70a134d5f
2012-05-13 17:53:42 -04:00
John-David Dalton
0297e31893 Simplify createIterator.
Former-commit-id: 3058b25bf7677a45261b640bd6ff6e1af1849c2c
2012-05-13 17:53:10 -04:00
John-David Dalton
5b975adc8e Cleanup build files.
Former-commit-id: eac9437648d2bb7260dba5eacfc7076867975134
2012-05-13 17:52:44 -04:00
John-David Dalton
12fc6b3a67 Update the build process.
Former-commit-id: bc80960e1608982354366a37813785c277868d52
2012-05-13 17:21:22 -04:00
John-David Dalton
cb4cc61c5b Update submodules.
Former-commit-id: 51c59d57252147d4af8049eeb5fa1325e747ab4d
2012-05-12 19:05:29 -04:00
John-David Dalton
9f4404628b Rename combine to hybrid.
Former-commit-id: 39180b07379581db688ddb066807dba1928cb27c
2012-05-12 01:41:51 -04:00
John-David Dalton
5441f6b55b Refresh docs and minified build.
Former-commit-id: e853a3363a8824eebbea69e0f16bfdb645619600
2012-05-12 01:12:53 -04:00
John-David Dalton
258fc518a6 Add _.isEmpty JScript [[DontEnum]] bug test.
Former-commit-id: 3815abeb1d802bd6fc2aada64f7a105aa77a6467
2012-05-12 01:11:54 -04:00
John-David Dalton
6a06bf5efa Optimize _.isObject. [ninjainvisible]
Former-commit-id: aa139d3eac1c9913ba6dc85c63145a121ab40cba
2012-05-12 01:11:25 -04:00
John-David Dalton
ff93f7cbb5 Add a default _.templateSettings.variable value.
Former-commit-id: 504aff143cd1dabdb7e8cd089ed3ed1bf9d8f896
2012-05-12 00:31:13 -04:00
John-David Dalton
2e291396bd Touch license and .gitignore.
Former-commit-id: d18484b4608c8514cee78ad699e6150c4cfb0c6c
2012-05-10 01:52:28 -04:00
John-David Dalton
b779f8b029 Optimize the [[DontEnum]] snippet of iteratorTemplate.
Former-commit-id: 23b2b27ee017092066526bba030f680d20bee211
2012-05-10 01:51:17 -04:00
John-David Dalton
04a05b4c02 Cleanup _.max and _.min unit tests.
Former-commit-id: 5bfdd6d441f20879f3352f260b9b08e714c7b836
2012-05-10 01:48:20 -04:00
John-David Dalton
90989a816d Detect the argument length limit instead of using a fixed limit.
Former-commit-id: 24875b0f67c7c92a37c315d3e8a33f23b5372119
2012-05-10 01:40:42 -04:00
John-David Dalton
9b26b96836 Implement a more robust native function detection. [Krinkle]
Former-commit-id: 8d915a0dd12f08e1860122189b57b12382efb144
2012-05-09 02:14:03 -04:00
John-David Dalton
972a716600 Small change to _.max.
Former-commit-id: ee7a5a78087ce8a92b06b7cd542903433053e649
2012-05-09 02:02:29 -04:00
John-David Dalton
b5c4a9241b Add instance pass through unit test, and ensure the pre-compile step escapes the "_wrapped" property for Closure Compiler.
Former-commit-id: 4bb8f77bacdafdd6822564c18751310235679476
2012-05-09 01:43:40 -04:00
John-David Dalton
45f9d80a81 Move _.max and _.min to the "Arrays" category and verify unit tests, rework _.isEqual [[DontEnum]] fix, and cleanup iteratorTemplate,
Former-commit-id: 9f4700b9db5767f314a44d6a83a3552d58ae6872
2012-05-09 01:05:47 -04:00
John-David Dalton
98435d2d92 Remove debug and tweak template whitespace for pretty printing.
Former-commit-id: 1f00899af1210dd367718aad4db38453509747c2
2012-05-08 17:34:13 -04:00
John-David Dalton
ccbf965bd9 Cleanup iterator template, make _.isEqual avoid the JScript [[DontEnum]] bug and add unit tests.
Former-commit-id: 1325f2184a8572ba688bcf697892782b8a0972e7
2012-05-08 17:11:32 -04:00
John-David Dalton
5c82104d7b Cleanup code and rework the pre-compile step.
Former-commit-id: cb62236ee0396e5e08defcbfee526265f9cf042e
2012-05-08 12:15:01 -04:00
John-David Dalton
4c29fbb36d lodash: Cleanup compilation. [jddalton]
Former-commit-id: e51b6742db1aeb103534d98c8354c65454d25a23
2012-05-08 10:29:36 -04:00
John-David Dalton
88e754850d lodash: Fix JSDoc entries, rename private constructor Lodash to LoDash, and optimize wrapper methods. [jddalton]
Former-commit-id: 1a2541900aa93c4c19c1eee12132bce89200b564
2012-05-07 13:58:51 -04:00
John-David Dalton
21b86980a7 lodash: Add a combined minified mode. [jddalton]
Former-commit-id: ba37c06ce553a2e8f366952432ad7fb9903ca577
2012-05-07 13:50:18 -04:00
John-David Dalton
98942c5e1a lodash: Simplify reUnescaped. [jddalton]
Former-commit-id: 5daf301fb60580248d765f5d3d49e10e9fa7104b
2012-05-07 00:47:27 -04:00
John-David Dalton
9c54df2de5 lodash: Add unit tests for buggy shift and splice in IE. [jddalton]
Former-commit-id: 574e4adcd024ef667302e97fffebc9bee5cbfacf
2012-05-06 22:40:58 -04:00
John-David Dalton
f31c2d24f9 lodash: Add the JScript [[DontEnum]] and Firefox, Opera, and Safari "prototype" property iteration fixes to iterationFactory. [jddalton]
Former-commit-id: f5be5c1e0828c3850936ba13ce19d0bfb8988d05
2012-05-06 22:16:03 -04:00
John-David Dalton
52cf17b24a lodash: Ensure max and min do not error when computing the result of massive arrays. [cederberg, jddalton, jeeyoungk]
Former-commit-id: af982790c3bb62777523f972a95b7115fb645180
2012-05-06 19:38:15 -04:00
John-David Dalton
d26fc7154c lodash: Add partial. [closes #5] [gf3, jddalton]
Former-commit-id: 7f95e60e93d463aeac936bcf0868fe2cb5494d6e
2012-05-06 19:17:13 -04:00
John-David Dalton
14c8863657 lodash: Add native method overwrite detection and optimize bind for native bind. [jddalton]
Former-commit-id: d968957e494fb828df155d2f9b0d3faf24e38b5e
2012-05-06 17:57:39 -04:00
John-David Dalton
6d3d5f77bc lodash: Add comments explaining the iterationFactory options object. [jddalton]
Former-commit-id: a5869f89b25b22b661c9f997dc96029ea0c82dbc
2012-05-06 00:05:04 -04:00
John-David Dalton
293fc695a4 lodash: Update documentation and submodules. [jddalton]
Former-commit-id: 9948b9ad5b2dc34a8f442e881f1d75178622364f
2012-05-03 14:28:13 -04:00
John-David Dalton
a317d2471f lodash: Add whitespace to strings. [jddalton]
Former-commit-id: ea4e6a6a894bb596be61df59239bc7f8c2ecd75d
2012-05-03 10:50:27 -04:00
John-David Dalton
afe7ff6d2c lodash: Tweak comment. [jddalton]
Former-commit-id: 309c501800ab2a6234992dafe629a6cd9f8f20ad
2012-05-03 10:42:28 -04:00
John-David Dalton
2f908870e7 lodash: Cleanup template. [jddalton]
Former-commit-id: 286af73ea3a4d798afd4baa01e586ada0305e66b
2012-05-03 10:12:45 -04:00
John-David Dalton
312f0310dc lodash: Update the minified build, README.md, and Benchmark.js submodule. [jddalton]
Former-commit-id: deb6bce113b8739f6f09462f3067263ac48a8f44
2012-05-03 00:46:41 -04:00
John-David Dalton
1a1bd5322c lodash: No longer have escape translate the ">" character. [jddalton, mathiasbynens]
Former-commit-id: 58d8ef98f3699a62b57a460b45921785fa2440b0
2012-05-03 00:45:21 -04:00
John-David Dalton
04ca0ae309 lodash: Cleanup code. [jddalton, mathiasbynens]
Former-commit-id: 639655426b7b928ca756993227bc6f80484deae2
2012-05-03 00:31:25 -04:00
John-David Dalton
221f70e609 lodash: Optimize template. [jddalton]
Former-commit-id: 2cd61549491714e6796308ec437fa8dff8fa9a1b
2012-05-03 00:23:57 -04:00
John-David Dalton
a426109c1c lodash: Update minified build, documentation, and Underscore submodule. [jddalton]
Former-commit-id: 35fb63c16127413ff283fcd3075e1dea38ebef8c
2012-05-01 21:14:30 -04:00
John-David Dalton
d5e2489cad lodash: Make deb ounce match throttle's return value behavior. [jddalton]
Former-commit-id: 2d4073c8a2ba20b98344c19cbfaf388a2683ef19
2012-05-01 21:13:02 -04:00
John-David Dalton
367f0bd6a9 lodash: Optimize and simplify throttle. [cowboy, jddalton]
Former-commit-id: 52e19aeb8671e86a13bf54876bf1f3f1b4644437
2012-05-01 21:11:40 -04:00
John-David Dalton
8396ed3167 lodash: Simplify first argument checks in "Collections" methods. [jddalton]
Former-commit-id: f3b658acccc20d864cf4987f2d2473453297a1c8
2012-05-01 10:47:15 -04:00
John-David Dalton
6cc360d613 lodash: Add @mathiasbynens as a contributor. [jddalton]
Former-commit-id: fd286bc6665ba819be5d4ce379fd0359559cc236
2012-05-01 00:37:25 -04:00
John-David Dalton
e86eef5905 lodash: Update documentation and lodash.min.js. [jddalton]
Former-commit-id: 0fa786b309e699dcf586e5606b7f3c82ac5e460f
2012-05-01 00:35:50 -04:00
John-David Dalton
24d5fbb595 lodash: Add support for "lazy" bind. [jddalton]
Former-commit-id: 472c0436f7de4e636dd878900119008bf39592fa
2012-05-01 00:34:40 -04:00
John-David Dalton
6fb7681a2d lodash: Reduce functions created in debounce and throttle and make each work when called recursively. [int3, jddalton]
Former-commit-id: 8d8d1966f7b8710d1bd51c830c4d3c08643ba21a
2012-05-01 00:05:26 -04:00
John-David Dalton
0b404d4bb1 lodash: Avoid extraneous empty array in pick. [jddalton]
Former-commit-id: 581eb1264aed6f0904d794cad53462ae80a1c3d0
2012-04-30 23:26:12 -04:00
John-David Dalton
464826e81d lodash: Move sortedIndex to the "Arrays" category. [jddalton]
Former-commit-id: fb9d6afc3c805ac25c8e6e7968fdcb4e8da93d30
2012-04-30 23:22:49 -04:00
John-David Dalton
e871ffeff0 lodash: Cleanup flatten avoiding the use of an extraneous empty array. [jddalton]
Former-commit-id: 6a1eebceb77dd59d34659a295c4a7a2dce92e8a9
2012-04-30 22:51:14 -04:00
John-David Dalton
2847b1f08e lodash: Move shuffle to the "Arrays" category and optimize. [jddalton]
Former-commit-id: 6f08cc15a5a1b0197e080d5fc21309b84cabaf6a
2012-04-30 22:49:29 -04:00
John-David Dalton
d702e00446 lodash: Optimize intersection. [jddalton]
Former-commit-id: f15eb7429ab4f14a4b096f5ba72f3662f9ed23d7
2012-04-30 22:32:07 -04:00
John-David Dalton
142ee20bca lodash: Fix post-compile.js VERSION detection to allow newlines. [jddalton]
Former-commit-id: 2e0d342cf66c4507a2956eeac912333cfdca5817
2012-04-30 22:16:21 -04:00
John-David Dalton
e3f03fa2ce lodash: Update Underscore submodule. [jddalton]
Former-commit-id: 98f22ee0e2d0b5d4908b3f8eaa929181e9167cb3
2012-04-30 22:15:28 -04:00
John-David Dalton
8dc3fb86db lodash: Tweak map's result assignment. [jddalton]
Former-commit-id: eb047e50e485fb1df387648fc1815e405b9d18ef
2012-04-27 01:11:48 -04:00
John-David Dalton
358ec3fb39 lodash: Inline isFunction calls. [jddalton]
Former-commit-id: d2929d4cbc1f2fb32dc94deba9dc44e5d51b4235
2012-04-27 00:43:42 -04:00
John-David Dalton
f4a38a25c8 lodash: Minor build.js cleanup. [jddalton]
Former-commit-id: ca0ba49f4e1670196912cbbd237a3a1a8f72e2a7
2012-04-26 23:38:42 -04:00
John-David Dalton
dcb62a3df5 Merge branch 'master' of github.com:bestiejs/lodash
Former-commit-id: 5a73314c99eb56eb4e2a13ff931e76db48c17f04
2012-04-26 23:34:10 -04:00
John-David Dalton
59c26957bb lodash: Optimize uniq and union, and inflate methods in the "Arrays" category. [jddalton]
Former-commit-id: b54d0bc2a77d1589d4b53b20a2f5ec175ab6c5cc
2012-04-26 23:33:53 -04:00
Kit Cambridge
09d8561b3c build.js: Merge invoke() into closureCompile().
Former-commit-id: 0fbdeffeba06c49db1d8b0801c8e3b721c3a5a43
2012-04-26 20:06:47 -06:00
Kit Cambridge
6246e71c87 Use the Node zlib module instead of shelling out to gzip.
Former-commit-id: f73339f6fd421ec4ddd1ec13ef13a18926419cdb
2012-04-26 19:56:31 -06:00
John-David Dalton
adcc2dd8d2 lodash: Simplify _.keys fallback. [jddalton]
Former-commit-id: 15d265f4f16ab2418bb5dcddf68a2fd43ebdf5b2
2012-04-26 15:46:47 -04:00
John-David Dalton
947fc9ce97 lodash: Fix syntax error in IE < 9 related to return throw …. [jddalton]
Former-commit-id: 8de2886801d447d6c0db119fe061d2fafd49958b
2012-04-26 11:29:13 -04:00
John-David Dalton
5caca9175d lodash: Update doc line numbers. [jddalton]
Former-commit-id: f7000abe7f38af81b54a277f54f1ebb6e7b37966
2012-04-26 09:18:11 -04:00
John-David Dalton
520d09e81e lodash: Avoid an extra callback call in the sortedIndex while loop. [jddalton, spadgos]
Former-commit-id: 87228c7308475f9430e5bcb0bc0d647b2210388f
2012-04-26 09:05:45 -04:00
John-David Dalton
7fa4304097 lodash: Change invoke's category to "Arrays". [jddalton]
Former-commit-id: e8e176bacf72f721fce62630984778e4d2ff08be
2012-04-26 01:27:50 -04:00
John-David Dalton
ceed641730 lodash: Update doc line numbers. [jddalton]
Former-commit-id: 765b1e55407c59bb76a7ec5af0c86bbd42156c23
2012-04-26 01:12:27 -04:00
John-David Dalton
1d4ce28b62 lodash: Remove unused afterLoop iterationFactory option, optimize sortedIndex, and optimize exiting early from compiled functions. [jddalton]
Former-commit-id: f56c93bfed623c5100d7cdf1c0d30b1e557d8a97
2012-04-26 01:10:45 -04:00
John-David Dalton
a551992c3f lodash: Remove unneeded slice call in pick. [jddalton, sindresorhus]
Former-commit-id: fbc5e2d918f31d2cd59bb9708c055c60592add10
2012-04-25 14:22:32 -04:00
John-David Dalton
23b8d083a4 lodash: Add spaces to compiled / template strings. [jddalton]
Former-commit-id: e28bb94dfb8f315f62dd942765752739f30950dc
2012-04-25 14:19:44 -04:00
John-David Dalton
b3d249f2ef lodash: Tweak bug fix link in README.md. [jddalton]
Former-commit-id: 383b811759e042cd93f6d852a0cda02a26af0de0
2012-04-25 14:05:47 -04:00
John-David Dalton
647633a1a0 lodash: Update doc line numbers. [jddalton]
Former-commit-id: 27edd51a81b000308128a097a024c81e5de2c773
2012-04-25 00:09:08 -04:00
John-David Dalton
313ffb8821 lodash: Add thisArg to groupBy and optimize invoke. [jddalton]
Former-commit-id: 74b0105af083471a56d60ac423409ae39e17d44a
2012-04-25 00:08:46 -04:00
John-David Dalton
774f159e67 lodash: Optimize groupBy, union, and pick. [jddalton]
Former-commit-id: 5109fd3868751f34f5a54ebafdbd43fa26f96754
2012-04-24 23:12:08 -04:00
John-David Dalton
f9358531ad lodash: Add support for more AMD build optimizers and allow aliasing as the "underscore" module. [jddalton]
Former-commit-id: 6b3fa45d19f6a55aa7565bcb4d9221f6f159e9c9
2012-04-24 18:15:47 -04:00
John-David Dalton
bb09d77eb5 lodash: Fix typo in build.js. [jddalton]
Former-commit-id: 1dce55619a345bec6c5ebda1490a1015bfb30210
2012-04-24 12:26:32 -04:00
John-David Dalton
ba8cc970d0 lodash: Move Underscore's unit tests to a submodule. [fat, jddalton]
Former-commit-id: c0518256e2ff02386452cd62c81964cc2a3da3cc
2012-04-24 09:03:03 -04:00
John-David Dalton
89c986d50f lodash: Move the screencast note higher in the README.md. [jddalton]
Former-commit-id: dc22ba34a0764add4871426c33ace76fea30bd1b
2012-04-24 03:13:28 -04:00
108 changed files with 41247 additions and 5862 deletions

2
.gitignore vendored
View File

@@ -1,2 +1,4 @@
*.custom.*
.DS_Store
dist/
node_modules/

6
.gitmodules vendored
View File

@@ -16,3 +16,9 @@
[submodule "vendor/uglifyjs"]
path = vendor/uglifyjs
url = git://github.com/mishoo/UglifyJS.git
[submodule "vendor/underscore"]
path = vendor/underscore
url = git://github.com/documentcloud/underscore.git
[submodule "vendor/backbone"]
path = vendor/backbone
url = git://github.com/documentcloud/backbone.git

View File

@@ -1,5 +1,19 @@
*.custom.*
*.min.*
.*
dist/*
build.*
build/
dist/
doc/*.php
node_modules/
perf/*.html
perf/*.sh
test/*.html
vendor/
test/*.sh
vendor/backbone/
vendor/closure-compiler/
vendor/docdown/
vendor/firebug-lite/
vendor/requirejs/
vendor/uglifyjs/
vendor/underscore/

176
README.md
View File

@@ -1,40 +1,66 @@
# Lo-Dash <sup>v0.1.0</sup>
# Lo-Dash <sup>v0.2.1</sup>
A drop-in replacement for [Underscore.js](https://github.com/documentcloud/underscore/) that delivers up to [8x performance improvements](http://jsperf.com/lodash-underscore#chart=bar), [bug fixes](https://github.com/bestiejs/lodash/blob/master/test/test.js#L71), and additional features.
A drop-in replacement for Underscore.js, from the devs behind [jsPerf.com](http://jsperf.com), that delivers [performance improvements](http://jsperf.com/lodash-underscore#filterby=family), [bug fixes](https://github.com/bestiejs/lodash#closed-underscorejs-issues), and [additional features](https://github.com/bestiejs/lodash#features).
## BestieJS
Lo-Dashs performance is gained by avoiding slower native methods, instead opting for simplified non-ES5 compliant methods optimized for common usage, and by leveraging function compilation to reduce the number of overall function calls.
Lo-Dash is part of the BestieJS *"Best in Class"* module collection. This means we promote solid browser/environment support, ES5 precedents, unit testing, and plenty of documentation.
## Dive in
## Documentation
The documentation for Lo-Dash can be viewed here: [/doc/README.md](https://github.com/bestiejs/lodash/blob/master/doc/README.md#readme)
Underscore's [documentation](http://documentcloud.github.com/underscore/) may also be used.
Weve got [API docs](http://lodash.com/docs) and [unit tests](http://lodash.com/tests).
For a list of upcoming features, check out our [roadmap](https://github.com/bestiejs/lodash/wiki/Roadmap).
## So What's The Secret?
## Screencasts
Lo-Dash's performance is gained by avoiding native methods, instead opting for simplified non-ES5 compliant methods optimized for common usage, and by leveraging function compilation to reduce the number of overall function calls.
For more information check out these screencasts over Lo-Dash:
## What else?
* [Introducing Lo-Dash](http://dl.dropbox.com/u/513327/allyoucanleet/post/20/file/screencast.mp4)
* [Optimizations and custom builds](http://dl.dropbox.com/u/513327/allyoucanleet/post/21/file/screencast.mp4)
Lo-Dash comes with AMD loader support baked in, chainable `_.each`, and will [soon address](https://github.com/bestiejs/lodash/wiki/Roadmap) cross-browser object iteration issues.
## Features
## Screencast
* AMD loader support
* [_.bind](http://lodash.com/docs#_bindfunc--arg1-arg2-) supports *"lazy"* binding
* [_.debounce](http://lodash.com/docs#_debouncefunc-wait-immediate)ed functions match [_.throttle](http://lodash.com/docs#_throttlefunc-wait)ed functions return value behavior
* [_.forEach](http://lodash.com/docs#_foreachcollection-callback--thisarg) is chainable
* [_.groupBy](http://lodash.com/docs#_groupbycollection-callback--thisarg) accepts a third, `thisArg`, argument
* [_.partial](http://lodash.com/docs#_partialfunc--arg1-arg2-) for more functional fun
* [_.size](http://lodash.com/docs#_sizecollection) supports returning the `length` of string values
For more information check out [this screencast](http://dl.dropbox.com/u/513327/allyoucanleet/post/20/file/screencast.mp4) over Lo-Dash.
## Support
Lo-Dash has been tested in at least Chrome 5-19, Firefox 1.5-12, IE 6-9, Opera 9.25-11.64, Safari 3.0.4-5.1.3, Node.js 0.4.8-0.6.18, Narwhal 0.3.2, RingoJS 0.8, and Rhino 1.7RC3.
## Custom builds
Custom builds make it easy to create lightweight versions of Lo-Dash containing only the methods you need.
We handle all the method dependency and alias mapping for you.
Custom builds may be created in two ways:
1. Use the`include` argument to pass the names of the methods to include in the build.
~~~ bash
node build include=each,filter,map,noConflict
node build include="each, filter, map, noConflict"
~~~
2. Use the `exclude` argument to pass the names of the methods to exclude from the build.
~~~ bash
node build exclude=isNaN,isUndefined,union,zip
node build exclude="isNaN, isUndefined, union, zip"
~~~
Custom builds are saved to `lodash.custom.js` and `lodash.custom.min.js`.
## Installation and usage
In a browser:
In browsers:
~~~ html
<script src="lodash.js"></script>
~~~
Via [npm](http://npmjs.org/):
Using [npm](http://npmjs.org/):
~~~ bash
npm install lodash
@@ -61,15 +87,12 @@ load('lodash.js');
In an AMD loader like [RequireJS](http://requirejs.org/):
~~~ js
// opt-in
define.amd.lodash = true;
require({
'paths': {
'lodash': 'path/to/lodash'
'underscore': 'path/to/lodash'
}
},
['lodash'], function(_) {
['underscore'], function(_) {
console.log(_.VERSION);
});
~~~
@@ -91,7 +114,112 @@ cd lodash
git submodule update --init
~~~
Feel free to fork and send pull requests if you see improvements!
## Closed Underscore.js issues
* Ensure `_.groupBy` adds values to own, not inherited, properties [[test](https://github.com/bestiejs/lodash/blob/32627f45072952df18a64cf5e9f2433d2d32730f/test/test.js#L229-236)]
* Ensure `_.throttle` works when called in tight loops [[#502](https://github.com/documentcloud/underscore/issues/502), [test](https://github.com/bestiejs/lodash/blob/32627f45072952df18a64cf5e9f2433d2d32730f/test/test.js#L436-446)]
* Fix Firefox, IE, Opera, and Safari object iteration bugs [[#376](https://github.com/documentcloud/underscore/issues/376), [test](https://github.com/bestiejs/lodash/blob/32627f45072952df18a64cf5e9f2433d2d32730f/test/test.js#L152-172), [test](https://github.com/bestiejs/lodash/blob/32627f45072952df18a64cf5e9f2433d2d32730f/test/test.js#L206-213), [test](https://github.com/bestiejs/lodash/blob/32627f45072952df18a64cf5e9f2433d2d32730f/test/test.js#L255-257), [test](https://github.com/bestiejs/lodash/blob/32627f45072952df18a64cf5e9f2433d2d32730f/test/test.js#L265-267), [test](https://github.com/bestiejs/lodash/blob/32627f45072952df18a64cf5e9f2433d2d32730f/test/test.js#L285-292), [test](https://github.com/bestiejs/lodash/blob/32627f45072952df18a64cf5e9f2433d2d32730f/test/test.js#L386-388)]
* Handle arrays with `undefined` values correctly in IE < 9 [[#601](https://github.com/documentcloud/underscore/issues/601)]
* Methods should work on pages with incorrectly shimmed native methods [[#7](https://github.com/documentcloud/underscore/issues/7), [test](https://github.com/bestiejs/lodash/blob/32627f45072952df18a64cf5e9f2433d2d32730f/test/test.js#L77-83)]
* Register as AMD module, but still export to global [[#431](https://github.com/documentcloud/underscore/pull/431), [test](https://github.com/bestiejs/lodash/blob/32627f45072952df18a64cf5e9f2433d2d32730f/test/test.js#L61-75)]
* `_.forEach` should be chainable [[#142](https://github.com/documentcloud/underscore/issues/142), [test](https://github.com/bestiejs/lodash/blob/5bcd444084c92b1753feeaf66c20323e57a2dac3/test/test.js#L74-77)]
* `_isNaN(new Number(NaN))` should return `true` [[test](https://github.com/bestiejs/lodash/blob/5bcd444084c92b1753feeaf66c20323e57a2dac3/test/test.js#L95-99)]
* `_.reduceRight` should pass correct callback arguments when iterating objects [[test](https://github.com/bestiejs/lodash/blob/5bcd444084c92b1753feeaf66c20323e57a2dac3/test/test.js#L106-116)]
* `_.size` should return the `length` of string values [[test](https://github.com/bestiejs/lodash/blob/5bcd444084c92b1753feeaf66c20323e57a2dac3/test/test.js#L121-127)]
## Optimized methods <sup>(50+)</sup>
* `_.bind`
* `_.bindAll`
* `_.clone`
* `_.compact`
* `_.contains`, `_.include`
* `_.defaults`
* `_.defer`
* `_.difference`
* `_.each`
* `_.escape`
* `_.every`, `_.all`
* `_.extend`
* `_.filter`, `_.select`
* `_.find`, `_.detect`
* `_.flatten`
* `_.forEach`, `_.each`
* `_.functions`, `_.methods`
* `_.groupBy`
* `_.indexOf`
* `_.intersection`
* `_.invoke`
* `_.isEmpty`
* `_.isEqual`
* `_.isFinite`
* `_.isObject`
* `_.isString`
* `_.keys`
* `_.lastIndexOf`
* `_.map`, `_.collect`
* `_.max`
* `_.memoize`
* `_.min`
* `_.mixin`
* `_.pick`
* `_.pluck`
* `_.reduce`, `_.foldl`, `_.inject`
* `_.reject`
* `_.result`
* `_.shuffle`
* `_.some`, `_.any`
* `_.sortBy`
* `_.sortedIndex`
* `_.template`
* `_.throttle`
* `_.toArray`
* `_.union`
* `_.uniq`, `_.unique`
* `_.values`
* `_.without`
* `_.wrap`
* `_.zip`
* plus all `_(...)` method wrappers
## Changelog
### <sup>v0.2.1</sup>
* Adjusted the Lo-Dash export order for r.js
* Ensured `_.groupBy` values are added to own, not inherited, properties
* Made `_.bind` follow ES5 spec to support a popular Backbone.js pattern
* Removed the alias `intersect`
* Simplified `_.bind`, `_.flatten`, `_.groupBy`, `_.max`, and `_.min`
### <sup>v0.2.0</sup>
* Added custom build options
* Added default `_.templateSettings.variable` value
* Added *"lazy bind"* support to `_.bind`
* Added native method overwrite detection to avoid bad native shims
* Added support for more AMD build optimizers and aliasing as the *"underscore"* module
* Added `thisArg` argument to `_.groupBy`
* Added whitespace to compiled strings
* Added `_.partial` method
* Commented the `iterationFactory` options object
* Ensured `_.max` and `_.min` support extremely large arrays
* Ensured `_.throttle` works in tight loops
* Fixed IE < 9 `[DontEnum]` bug and Firefox < 3.6, Opera > 9.50 - Opera < 11.60, and Safari < 5.1s prototype property iteration bug
* Inlined `_.isFunction` calls.
* Made `_.debounce`ed functions match `_.throttle`ed functions return value behavior
* Made `_.escape` no longer translate the *">"* character
* Fixed `clearTimeout` typo
* Simplified all methods in the *"Arrays"* category
* Optimized `_.debounce`, `_.escape`, `_.flatten`, `_.forEach`, `_.groupBy`, `_.intersection`, `_.invoke`, `_.isObject`, `_.max`, `_.min`, `_.pick`, `_.shuffle`, `_.sortedIndex`, `_.template`, `_.throttle`, `_.union`, `_.uniq`
### <sup>v0.1.0</sup>
* Initial release
## BestieJS
Lo-Dash is part of the BestieJS *"Best in Class"* module collection. This means we promote solid browser/environment support, ES5 precedents, unit testing, and plenty of documentation.
## Author
@@ -102,3 +230,5 @@ Feel free to fork and send pull requests if you see improvements!
* [Kit Cambridge](http://kitcambridge.github.com/)
[![twitter/kitcambridge](http://gravatar.com/avatar/6662a1d02f351b5ef2f8b4d815804661?s=70)](https://twitter.com/kitcambridge "Follow @kitcambridge on Twitter")
* [Mathias Bynens](http://mathiasbynens.be/)
[![twitter/mathias](http://gravatar.com/avatar/24e08a9ea84deb17ae121074d0f17125?s=70)](https://twitter.com/mathias "Follow @mathias on Twitter")

623
build.js
View File

@@ -2,253 +2,450 @@
;(function() {
'use strict';
/** The Node filesystem, path, and child process modules */
/** The Node filesystem and path modules */
var fs = require('fs'),
path = require('path'),
spawn = require('child_process').spawn;
/** The build directory containing the build scripts */
var buildPath = path.join(__dirname, 'build');
/** The directory where the Closure Compiler is located */
var closurePath = path.join(__dirname, 'vendor', 'closure-compiler', 'compiler.jar');
/** The distribution directory */
var distPath = path.join(__dirname, 'dist');
path = require('path');
/** Load other modules */
var preprocess = require(path.join(buildPath, 'pre-compile')),
postprocess = require(path.join(buildPath, 'post-compile')),
uglifyJS = require(path.join(__dirname, 'vendor', 'uglifyjs', 'uglify-js'));
var lodash = require(path.join(__dirname, 'lodash')),
minify = require(path.join(__dirname, 'build', 'minify'));
/** Used to shares values between multiple callbacks */
var accumulator = {
'compiled': {},
'uglified': {}
/** Flag used to specify a custom build */
var isCustom = false;
/** Shortcut used to convert array-like objects to arrays */
var slice = [].slice;
/** The lodash.js source */
var source = fs.readFileSync(path.join(__dirname, 'lodash.js'), 'utf8');
/** Used to associate aliases with their real names */
var aliasToRealMap = {
'all': 'every',
'any': 'some',
'collect': 'map',
'detect': 'find',
'each': 'forEach',
'foldl': 'reduce',
'foldr': 'reduceRight',
'head': 'first',
'include': 'contains',
'inject': 'reduce',
'methods': 'functions',
'select': 'filter',
'tail': 'rest',
'take': 'first',
'unique': 'uniq'
};
/** Closure Compiler command-line options */
var closureOptions = [
'--compilation_level=ADVANCED_OPTIMIZATIONS',
'--language_in=ECMASCRIPT5_STRICT',
'--warning_level=QUIET'
];
/** Used to associate real names with their aliases */
var realToAliasMap = {
'contains': ['include'],
'every': ['all'],
'filter': ['select'],
'find': ['detect'],
'first': ['head', 'take'],
'forEach': ['each'],
'functions': ['methods'],
'map': ['collect'],
'reduce': ['foldl', 'inject'],
'reduceRight': ['foldr'],
'rest': ['tail'],
'some': ['any'],
'uniq': ['unique']
};
/** Gzip command-line options */
var gzipOptions = ['-9f', '-c'];
/** The pre-processed Lo-Dash source */
var source = preprocess(fs.readFileSync(path.join(__dirname, 'lodash.js'), 'utf8'));
/** Used to track function dependencies */
var dependencyMap = {
'after': [],
'bind': [],
'bindAll': ['bind'],
'chain': [],
'clone': ['extend', 'isArray'],
'compact': [],
'compose': [],
'contains': ['createIterator'],
'createIterator': [],
'debounce': [],
'defaults': ['createIterator'],
'defer': [],
'delay': [],
'difference': ['indexOf'],
'escape': [],
'every': ['bind', 'createIterator', 'identity'],
'extend': ['createIterator'],
'filter': ['bind', 'createIterator', 'identity'],
'find': ['createIterator'],
'first': [],
'flatten': ['isArray'],
'forEach': ['bind', 'createIterator'],
'functions': ['createIterator'],
'groupBy': ['bind', 'createIterator'],
'has': [],
'identity': [],
'indexOf': ['sortedIndex'],
'initial': [],
'intersection': ['every', 'indexOf'],
'invoke': [],
'isArguments': [],
'isArray': [],
'isBoolean': [],
'isDate': [],
'isElement': [],
'isEmpty': ['createIterator'],
'isEqual': [],
'isFinite': [],
'isFunction': [],
'isNaN': [],
'isNull': [],
'isNumber': [],
'isObject': [],
'isRegExp': [],
'isString': [],
'isUndefined': [],
'keys': ['createIterator'],
'last': [],
'lastIndexOf': [],
'map': ['bind', 'createIterator', 'identity'],
'max': ['bind'],
'memoize': [],
'min': ['bind'],
'mixin': ['forEach'],
'noConflict': [],
'once': [],
'partial': [],
'pick': [],
'pluck': ['createIterator'],
'range': [],
'reduce': ['bind', 'createIterator'],
'reduceRight': ['bind', 'keys'],
'reject': ['bind', 'createIterator', 'identity'],
'rest': [],
'result': [],
'shuffle': [],
'size': ['keys'],
'some': ['bind', 'createIterator', 'identity'],
'sortBy': ['bind', 'map', 'pluck'],
'sortedIndex': [],
'tap': [],
'template': ['escape'],
'throttle': [],
'times': ['bind'],
'toArray': ['values'],
'union': ['indexOf'],
'uniq': ['indexOf'],
'uniqueId': [],
'values': ['createIterator'],
'without': ['indexOf'],
'wrap': [],
'zip': ['max', 'pluck']
};
/*--------------------------------------------------------------------------*/
/**
* Invokes a process with the given `name`, `parameters`, and `source` (used as
* the standard input). Yields the result to a `callback` function. The optional
* `encoding` argument specifies the output stream encoding.
* Gets the aliases associated with a given `funcName`.
*
* @private
* @param {String} name The name of the process.
* @param {Array} parameters An array of arguments to proxy to the process.
* @param {String} source The standard input to proxy to the process.
* @param {String} [encoding] The expected encoding of the output stream.
* @param {Function} callback The function to call once the process completes.
* @param {String} funcName The name of the function to get aliases for.
* @returns {Array} Returns an array of aliases.
*/
function invoke(name, parameters, source, encoding, callback) {
// the standard error stream, standard output stream, and process instance
var error = '',
output = '',
process = spawn(name, parameters);
function getAliases(funcName) {
return realToAliasMap[funcName] || [];
}
// juggle arguments
if (typeof encoding == 'string' && callback != null) {
// explicitly set the encoding of the output stream if one is specified
process.stdout.setEncoding(encoding);
} else {
callback = encoding;
encoding = null;
}
process.stdout.on('data', function(data) {
// append the data to the output stream
output += data;
});
process.stderr.on('data', function(data) {
// append the error message to the error stream
error += data;
});
process.on('exit', function(status) {
var exception = null;
// `status` contains the process exit code
if (status) {
exception = new Error(error);
exception.status = status;
/**
* Gets an array of depenants for a function by the given `funcName`.
*
* @private
* @param {String} funcName The name of the function to query.
* @returns {Array} Returns an array of function dependants.
*/
function getDependants(funcName) {
// iterate over `dependencyMap`, adding the names of functions that
// have `funcName` as a dependency
return lodash.reduce(dependencyMap, function(result, dependencies, otherName) {
if (dependencies.indexOf(funcName) > -1) {
result.push(otherName);
}
callback(exception, output);
return result;
}, []);
}
/**
* Gets an array of dependencies for a function of the given `funcName`.
*
* @private
* @param {String} funcName The name of the function to query.
* @returns {Array} Returns an array of function dependencies.
*/
function getDependencies(funcName) {
var dependencies = dependencyMap[funcName],
result = [];
if (!dependencies) {
return result;
}
// recursively accumulate the dependencies of the `funcName` function, and
// the dependencies of its dependencies, and so on.
return dependencies.reduce(function(result, otherName) {
result.push.apply(result, getDependencies(otherName).concat(otherName));
return result;
}, result);
}
/**
* Gets the real name, not alias, of a given `funcName`.
*
* @private
* @param {String} funcName The name of the function to resolve.
* @returns {String} Returns the real name.
*/
function getRealName(funcName) {
return aliasToRealMap[funcName] || funcName;
}
/**
* Determines if all functions of the given names have been removed from the `source`.
*
* @private
* @param {String} source The source to inspect.
* @param {String} [funcName1, funcName2, ...] The names of functions to check.
* @returns {Boolean} Returns `true` if all functions have been removed, else `false`.
*/
function isRemoved(source) {
return slice.call(arguments, 1).every(function(funcName) {
return !matchFunction(source, funcName);
});
}
/**
* Searches the `source` for a `funcName` function declaration, expression, or
* assignment and returns the matched snippet.
*
* @private
* @param {String} source The source to inspect.
* @param {String} funcName The name of the function to match.
* @returns {String} Returns the matched function snippet.
*/
function matchFunction(source, funcName) {
var result = source.match(RegExp(
// match multi-line comment block (could be on a single line)
'\\n +/\\*[^*]*\\*+(?:[^/][^*]*\\*+)*/\\n' +
// begin non-capturing group
'(?:' +
// match a function declaration
'( +)function ' + funcName + '\\b[\\s\\S]+?\\n\\1}|' +
// match a variable declaration with `createIterator`
' +var ' + funcName + ' *= *(?:[a-zA-Z]+ *\\|\\| *)?createIterator\\((?:{|[a-zA-Z])[\\s\\S]+?\\);|' +
// match a variable declaration with function expression
'( +)var ' + funcName + ' *= *(?:[a-zA-Z]+ *\\|\\| *)?function[\\s\\S]+?\\n\\2};' +
// end non-capturing group
')\\n'
));
return result ? result[0] : '';
}
/**
* Removes the all references to `refName` from the `createIterator` source.
*
* @private
* @param {String} source The source to process.
* @param {String} refName The name of the reference to remove.
* @returns {String} Returns the modified source.
*/
function removeFromCreateIterator(source, refName) {
var snippet = matchFunction(source, 'createIterator'),
modified = snippet.replace(RegExp('\\b' + refName + '\\b,? *', 'g'), '');
return source.replace(snippet, modified);
}
/**
* Removes the `funcName` function declaration, expression, or assignment and
* associated code from the `source`.
*
* @private
* @param {String} source The source to process.
* @param {String} funcName The name of the function to remove.
* @returns {String} Returns the source with the function removed.
*/
function removeFunction(source, funcName) {
var modified,
snippet = matchFunction(source, funcName);
// exit early if function is not found
if (!snippet) {
return source;
}
// remove function
source = source.replace(matchFunction(source, funcName), '');
// grab the method assignments snippet
snippet = source.match(/lodash\.VERSION *= *[\s\S]+?\/\*-+\*\/\n/)[0];
// remove assignment and aliases
modified = getAliases(funcName).concat(funcName).reduce(function(result, otherName) {
return result.replace(RegExp('(?:\\n *//.*\\s*)* *lodash\\.' + otherName + ' *= *.+\\n'), '');
}, snippet);
// replace with the modified snippet
source = source.replace(snippet, modified);
return removeFromCreateIterator(source, funcName);
}
/**
* Removes a given variable from the `source`.
*
* @private
* @param {String} source The source to process.
* @param {String} varName The name of the variable to remove.
* @returns {String} Returns the source with the variable removed.
*/
function removeVar(source, varName) {
source = source.replace(RegExp(
// begin non-capturing group
'(?:' +
// match multi-line comment block
'(?:\\n +/\\*[^*]*\\*+(?:[^/][^*]*\\*+)*/)?\\n' +
// match a variable declaration that's not part of a declaration list
'( +)var ' + varName + ' *= *(?:.*?;|(?:Function\\(.+?|.*?[^,])\\n[\\s\\S]+?\\n\\1.+?;)\\n|' +
// match a variable in a declaration list
'\\n +' + varName + ' *=.*?,' +
// end non-capturing group
')'
), '');
// remove a varaible at the start of a variable declaration list
source = source.replace(RegExp('(var +)' + varName + ' *=.+?,\\s+'), '$1');
// remove a variable at the end of a variable declaration list
source = source.replace(RegExp(',\\s*' + varName + ' *=.*?;'), ';');
return removeFromCreateIterator(source, varName);
}
/*--------------------------------------------------------------------------*/
// inline `iteratorTemplate`
(function() {
var iteratorTemplate = lodash._iteratorTemplate,
code = /^function[^{]+{([\s\S]+?)}$/.exec(iteratorTemplate)[1];
// remove whitespace from template
code = code.replace(/\[object |else if|function | in |return\s+[\w']|throw |typeof |var |\\\\n|\\n|\s+/g, function(match) {
return match == false || match == '\\n' ? '' : match;
});
// proxy the standard input to the process
process.stdin.end(source);
}
// remove unnecessary code
code = code
.replace(/\|\|\{\}|,__t,__j=Array.prototype.join|function print[^}]+}|\+''/g, '')
.replace(/(\{);|;(\})/g, '$1$2')
.replace(/\(\(__t=\(([^)]+)\)\)==null\?'':__t\)/g, '$1');
// ensure escaped characters are interpreted correctly inside the `Function()` string
code = code.replace(/\\/g, '\\\\');
// add `code` to `Function()`
code = '$1Function(\'object\',\n$2 "' + code + '"\n$2);\n';
// replace `template()` with `Function()`
source = source.replace(/(( +)var iteratorTemplate *= *)([\s\S]+?\n\2.+?);\n/, code);
// remove pseudo private property `_iteratorTemplate`
source = source.replace(/(?:\s*\/\/.*)*\s*lodash\._iteratorTemplate\b.+\n/, '\n');
}());
/*--------------------------------------------------------------------------*/
/**
* Compresses a `source` string using the Closure Compiler. Yields the
* minified result, and any exceptions encountered, to a `callback` function.
*
* @private
* @param {String} source The JavaScript source to minify.
* @param {Function} callback The function to call once the process completes.
*/
function closureCompile(source, callback) {
console.log('Compressing lodash.js using the Closure Compiler...');
invoke('java', ['-jar', closurePath].concat(closureOptions), source, callback);
}
// custom build
process.argv.some(function(arg) {
// exit early if not the "exclude" or "include" command option
var pair = arg.match(/^(exclude|include)=(.*)$/);
if (!pair) {
return false;
}
/**
* Compresses a `source` string using UglifyJS. Yields the result to a
* `callback` function. This function is synchronous; the `callback` is used
* for symmetry.
*
* @private
* @param {String} source The JavaScript source to minify.
* @param {Function} callback The function to call once the process completes.
*/
function uglify(source, callback) {
var exception,
result,
ugly = uglifyJS.uglify;
var filterType = pair[1],
filterNames = lodash.intersection(Object.keys(dependencyMap), pair[2].split(/, */).map(getRealName));
console.log('Compressing lodash.js using UglifyJS...');
// set custom build flag
isCustom = true;
try {
result = ugly.gen_code(
// enable unsafe transformations
ugly.ast_squeeze_more(
ugly.ast_squeeze(
// munge variable and function names, excluding the special `define`
// function exposed by AMD loaders
ugly.ast_mangle(uglifyJS.parser.parse(source), {
'except': ['define']
}
))), {
'ascii_only': true
// remove the specified functions and their dependants
if (filterType == 'exclude') {
filterNames.forEach(function(funcName) {
getDependants(funcName).concat(funcName).forEach(function(otherName) {
source = removeFunction(source, otherName);
});
});
} catch(e) {
exception = e;
}
// lines are restricted to 500 characters for consistency with the Closure Compiler
callback(exception, result && ugly.split_lines(result, 500));
}
// else remove all but the specified functions and their dependencies
else {
filterNames = lodash.uniq(filterNames.reduce(function(result, funcName) {
result.push.apply(result, getDependencies(funcName).concat(funcName));
return result;
}, []));
/*--------------------------------------------------------------------------*/
/**
* The `closureCompile()` callback.
*
* @private
* @param {Object|Undefined} exception The error object.
* @param {String} result The resulting minified source.
*/
function onClosureCompile(exception, result) {
if (exception) {
throw exception;
lodash.each(dependencyMap, function(dependencies, otherName) {
if (filterNames.indexOf(otherName) < 0) {
source = removeFunction(source, otherName);
}
});
}
// store the post-processed Closure Compiler result and gzip it
accumulator.compiled.source = result = postprocess(result);
invoke('gzip', gzipOptions, result, 'binary', onClosureGzip);
}
/**
* The Closure Compiler `gzip` callback.
*
* @private
* @param {Object|Undefined} exception The error object.
* @param {String} result The resulting gzipped source.
*/
function onClosureGzip(exception, result) {
if (exception) {
throw exception;
// remove associated functions, variables and code snippets
if (isRemoved(source, 'isArguments')) {
// remove `isArguments` if-statement
source = source.replace(/(?:\s*\/\/.*)*\s*if *\(!isArguments[^)]+\)[\s\S]+?};?\s*}\n/, '');
}
// store the gzipped result and report the size
accumulator.compiled.gzip = result;
console.log('Done. Size: %d KB.', result.length);
// next, minify using UglifyJS
uglify(source, onUglify);
}
/**
* The `uglify()` callback.
*
* @private
* @param {Object|Undefined} exception The error object.
* @param {String} result The resulting minified source.
*/
function onUglify(exception, result) {
if (exception) {
throw exception;
if (isRemoved(source, 'mixin')) {
// remove `LoDash` constructor
source = removeFunction(source, 'LoDash');
// remove `LoDash` calls
source = source.replace(/(?:new +LoDash(?!\()|(?:new +)?LoDash\([^)]*\));?/g, '');
// remove `LoDash.prototype` additions
source = source.replace(/(?:\s*\/\/.*)*\s*LoDash.prototype *=[\s\S]+?\/\*-+\*\//, '');
}
// store the post-processed Uglified result and gzip it
accumulator.uglified.source = postprocess(result);
invoke('gzip', gzipOptions, result, 'binary', onUglifyGzip);
}
/**
* The UglifyJS `gzip` callback.
*
* @private
* @param {Object|Undefined} exception The error object.
* @param {String} result The resulting gzipped source.
*/
function onUglifyGzip(exception, result) {
if (exception) {
throw exception;
if (isRemoved(source, 'template')) {
// remove `templateSettings` assignment
source = source.replace(/(?:\n +\/\*[^*]*\*+(?:[^\/][^*]*\*+)*\/)?\n *lodash\.templateSettings[\s\S]+?};\n/, '');
}
if (isRemoved(source, 'isArray', 'isEmpty', 'isEqual', 'size')) {
source = removeVar(source, 'arrayClass');
}
if (isRemoved(source, 'bind', 'functions', 'groupBy', 'invoke', 'isEqual', 'isFunction', 'result', 'sortBy', 'toArray')) {
source = removeVar(source, 'funcClass');
}
if (isRemoved(source, 'clone', 'isObject', 'keys')) {
source = removeVar(source, 'objectTypes');
source = removeFromCreateIterator(source, 'objectTypes');
}
if (isRemoved(source, 'isEmpty', 'isEqual', 'isString', 'size')) {
source = removeVar(source, 'stringClass');
}
// store the gzipped result and report the size
accumulator.uglified.gzip = result;
console.log('Done. Size: %d KB.', result.length);
// finish by choosing the smallest compressed file
onComplete();
}
// consolidate consecutive horizontal rule comment separators
source = source.replace(/(?:\s*\/\*-+\*\/\s*){2,}/g, function(separators) {
return separators.match(/^\s*/)[0] + separators.slice(separators.lastIndexOf('/*'));
});
/**
* The callback executed after JavaScript source is minified and gzipped.
*
* @private
*/
function onComplete() {
var compiled = accumulator.compiled,
uglified = accumulator.uglified;
return true;
});
// save the Closure Compiled version to disk
fs.writeFileSync(path.join(distPath, 'lodash.compiler.js'), compiled.source);
// explicit 'binary' is necessary to ensure the stream is written correctly
fs.writeFileSync(path.join(distPath, 'lodash.compiler.js.gz'), compiled.gzip, 'binary');
// save the Uglified version to disk
fs.writeFileSync(path.join(distPath, 'lodash.uglify.js'), uglified.source);
fs.writeFileSync(path.join(distPath, 'lodash.uglify.js.gz'), uglified.gzip, 'binary');
// select the smallest gzipped file and use its minified form as the
// official minified release (ties go to Closure Compiler)
fs.writeFileSync(path.join(__dirname, 'lodash.min.js'),
uglified.gzip.length < compiled.gzip.length
? uglified.source
: compiled.source
);
}
/*--------------------------------------------------------------------------*/
// create the destination directory if it doesn't exist
if (!path.existsSync(distPath)) {
fs.mkdirSync(distPath);
}
// begin the minification process
closureCompile(source, onClosureCompile);
if (isCustom) {
fs.writeFileSync(path.join(__dirname, 'lodash.custom.js'), source);
minify(source, 'lodash.custom.min', function(result) {
fs.writeFileSync(path.join(__dirname, 'lodash.custom.min.js'), result);
});
}
else {
minify(source, 'lodash.min', function(result) {
fs.writeFileSync(path.join(__dirname, 'lodash.min.js'), result);
});
}
}());

341
build/minify.js Executable file
View File

@@ -0,0 +1,341 @@
#!/usr/bin/env node
;(function() {
'use strict';
/** The Node filesystem, path, `zlib`, and child process modules */
var fs = require('fs'),
gzip = require('zlib').gzip,
path = require('path'),
spawn = require('child_process').spawn;
/** The directory that is the base of the repository */
var basePath = path.join(__dirname, '../');
/** The directory where the Closure Compiler is located */
var closurePath = path.join(basePath, 'vendor', 'closure-compiler', 'compiler.jar');
/** The distribution directory */
var distPath = path.join(basePath, 'dist');
/** Load other modules */
var preprocess = require(path.join(__dirname, 'pre-compile')),
postprocess = require(path.join(__dirname, 'post-compile')),
uglifyJS = require(path.join(basePath, 'vendor', 'uglifyjs', 'uglify-js'));
/** Closure Compiler command-line options */
var closureOptions = [
'--compilation_level=ADVANCED_OPTIMIZATIONS',
'--language_in=ECMASCRIPT5_STRICT',
'--warning_level=QUIET'
];
/** Reassign `existsSync` for older versions of Node */
fs.existsSync || (fs.existsSync = path.existsSync);
/*--------------------------------------------------------------------------*/
/**
* The exposed `minify` function minifies a given `source` and invokes the
* `onComplete` callback when finished.
*
* @param {String} source The source to minify.
* @param {String} workingName The name to give temporary files creates during the minification process.
* @param {Function} onComplete A function called when minification has completed.
*/
function minify(source, workingName, onComplete) {
new Minify(source, workingName, onComplete);
}
/**
* The Minify constructor used to keep state of each `minify` invocation.
*
* @private
* @constructor
* @param {String} source The source to minify.
* @param {String} workingName The name to give temporary files creates during the minification process.
* @param {Function} onComplete A function called when minification has completed.
*/
function Minify(source, workingName, onComplete) {
// create the destination directory if it doesn't exist
if (!fs.existsSync(distPath)) {
fs.mkdirSync(distPath);
}
this.compiled = {};
this.hybrid = {};
this.uglified = {};
this.onComplete = onComplete;
this.source = source = preprocess(source);
this.workingName = workingName;
// begin the minification process
closureCompile.call(this, source, onClosureCompile.bind(this));
}
/*--------------------------------------------------------------------------*/
/**
* Compresses a `source` string using the Closure Compiler. Yields the
* minified result, and any exceptions encountered, to a `callback` function.
*
* @private
* @param {String} source The JavaScript source to minify.
* @param {String} [message] The message to log.
* @param {Function} callback The function to call once the process completes.
*/
function closureCompile(source, message, callback) {
// the standard error stream, standard output stream, and Closure Compiler process
var error = '',
output = '',
compiler = spawn('java', ['-jar', closurePath].concat(closureOptions));
// juggle arguments
if (typeof message == 'function') {
callback = message;
message = null;
}
console.log(message == null
? 'Compressing ' + this.workingName + ' using the Closure Compiler...'
: message
);
compiler.stdout.on('data', function(data) {
// append the data to the output stream
output += data;
});
compiler.stderr.on('data', function(data) {
// append the error message to the error stream
error += data;
});
compiler.on('exit', function(status) {
var exception = null;
// `status` contains the process exit code
if (status) {
exception = new Error(error);
exception.status = status;
}
callback(exception, output);
});
// proxy the standard input to the Closure Compiler
compiler.stdin.end(source);
}
/**
* Compresses a `source` string using UglifyJS. Yields the result to a
* `callback` function. This function is synchronous; the `callback` is used
* for symmetry.
*
* @private
* @param {String} source The JavaScript source to minify.
* @param {String} [message] The message to log.
* @param {Function} callback The function to call once the process completes.
*/
function uglify(source, message, callback) {
var exception,
result,
ugly = uglifyJS.uglify;
// juggle arguments
if (typeof message == 'function') {
callback = message;
message = null;
}
console.log(message == null
? 'Compressing ' + this.workingName + ' using UglifyJS...'
: message
);
try {
result = ugly.gen_code(
// enable unsafe transformations
ugly.ast_squeeze_more(
ugly.ast_squeeze(
// munge variable and function names, excluding the special `define`
// function exposed by AMD loaders
ugly.ast_mangle(uglifyJS.parser.parse(source), {
'except': ['define']
}
))), {
'ascii_only': true
});
} catch(e) {
exception = e;
}
// lines are restricted to 500 characters for consistency with the Closure Compiler
callback(exception, result && ugly.split_lines(result, 500));
}
/*--------------------------------------------------------------------------*/
/**
* The `closureCompile()` callback.
*
* @private
* @param {Object|Undefined} exception The error object.
* @param {String} result The resulting minified source.
*/
function onClosureCompile(exception, result) {
if (exception) {
throw exception;
}
// store the post-processed Closure Compiler result and gzip it
this.compiled.source = result = postprocess(result);
gzip(result, onClosureGzip.bind(this));
}
/**
* The Closure Compiler `gzip` callback.
*
* @private
* @param {Object|Undefined} exception The error object.
* @param {Buffer} result The resulting gzipped source.
*/
function onClosureGzip(exception, result) {
if (exception) {
throw exception;
}
// store the gzipped result and report the size
this.compiled.gzip = result;
console.log('Done. Size: %d bytes.', result.length);
// next, minify the source using only UglifyJS
uglify.call(this, this.source, onUglify.bind(this));
}
/**
* The `uglify()` callback.
*
* @private
* @param {Object|Undefined} exception The error object.
* @param {String} result The resulting minified source.
*/
function onUglify(exception, result) {
if (exception) {
throw exception;
}
// store the post-processed Uglified result and gzip it
this.uglified.source = result = postprocess(result);
gzip(result, onUglifyGzip.bind(this));
}
/**
* The UglifyJS `gzip` callback.
*
* @private
* @param {Object|Undefined} exception The error object.
* @param {Buffer} result The resulting gzipped source.
*/
function onUglifyGzip(exception, result) {
if (exception) {
throw exception;
}
var message = 'Compressing ' + this.workingName + ' using hybrid minification...';
// store the gzipped result and report the size
this.uglified.gzip = result;
console.log('Done. Size: %d bytes.', result.length);
// next, minify the Closure Compiler minified source using UglifyJS
uglify.call(this, this.compiled.source, message, onHybrid.bind(this));
}
/**
* The hybrid `uglify()` callback.
*
* @private
* @param {Object|Undefined} exception The error object.
* @param {String} result The resulting minified source.
*/
function onHybrid(exception, result) {
if (exception) {
throw exception;
}
// store the post-processed Uglified result and gzip it
this.hybrid.source = result = postprocess(result);
gzip(result, onHybridGzip.bind(this));
}
/**
* The hybrid `gzip` callback.
*
* @private
* @param {Object|Undefined} exception The error object.
* @param {Buffer} result The resulting gzipped source.
*/
function onHybridGzip(exception, result) {
if (exception) {
throw exception;
}
// store the gzipped result and report the size
this.hybrid.gzip = result;
console.log('Done. Size: %d bytes.', result.length);
// finish by choosing the smallest compressed file
onComplete.call(this);
}
/**
* The callback executed after JavaScript source is minified and gzipped.
*
* @private
*/
function onComplete() {
var compiled = this.compiled,
hybrid = this.hybrid,
name = this.workingName,
uglified = this.uglified;
// save the Closure Compiled version to disk
fs.writeFileSync(path.join(distPath, name + '.compiler.js'), compiled.source);
fs.writeFileSync(path.join(distPath, name + '.compiler.js.gz'), compiled.gzip);
// save the Uglified version to disk
fs.writeFileSync(path.join(distPath, name + '.uglify.js'), uglified.source);
fs.writeFileSync(path.join(distPath, name + '.uglify.js.gz'), uglified.gzip);
// save the hybrid minified version to disk
fs.writeFileSync(path.join(distPath, name + '.hybrid.js'), hybrid.source);
fs.writeFileSync(path.join(distPath, name + '.hybrid.js.gz'), hybrid.gzip);
// select the smallest gzipped file and use its minified counterpart as the
// official minified release (ties go to Closure Compiler)
var min = Math.min(compiled.gzip.length, hybrid.gzip.length, uglified.gzip.length);
// pass the minified source to the minify instances "onComplete" callback
this.onComplete(
compiled.gzip.length == min
? compiled.source
: uglified.gzip.length == min
? uglified.source
: hybrid.source
);
}
/*--------------------------------------------------------------------------*/
// expose `minify`
if (module != require.main) {
module.exports = minify;
}
else {
// read the JavaScript source file from the first argument if the script
// was invoked directly (e.g. `node minify.js source.js`) and write to
// the same file
(function() {
var filePath = process.argv[2],
dirPath = path.dirname(filePath),
source = fs.readFileSync(filePath, 'utf8'),
workingName = path.basename(filePath, '.js') + '.min';
minify(source, workingName, function(result) {
fs.writeFileSync(path.join(dirPath, workingName + '.js'), result);
});
}());
}
}());

View File

@@ -8,7 +8,7 @@
/** The minimal license/copyright template */
var licenseTemplate =
'/*!\n' +
' Lo-Dash @VERSION github.com/bestiejs/lodash/blob/master/LICENSE.txt\n' +
' Lo-Dash @VERSION lodash.com/license\n' +
' Underscore.js 1.3.3 github.com/documentcloud/underscore/blob/master/LICENSE\n' +
'*/';
@@ -18,19 +18,36 @@
* Post-process a given minified JavaScript `source`, preparing it for
* deployment.
*
* @private
* @param {String} source The source to process.
* @returns {String} Returns the processed source.
*/
function postprocess(source) {
// exit early if snippet isn't found
var snippet = /VERSION\s*[=:]\s*([\'"])(.*?)\1/.exec(source);
if (!snippet) {
return source;
}
// set the version
var license = licenseTemplate.replace('@VERSION', (/VERSION:([\'"])(.*?)\1/).exec(source).pop());
var license = licenseTemplate.replace('@VERSION', snippet[2]);
// move vars exposed by Closure Compiler into the IIFE
source = source.replace(/^([^(\n]+)\s*(\(function[^)]+\){)/, '$2$1');
// use double quotes consistently
source = source.replace(/'use strict'/, '"use strict"');
// unescape properties (i.e. foo["bar"] => foo.bar)
source = source.replace(/(\w)\["([^."]+)"\]/g, '$1.$2');
// correct AMD module definition for AMD build optimizers
source = source.replace(/("function")==(typeof define)&&\(?("object")==(typeof define\.amd)(&&define\.amd)\)?/, '$2==$1&&$4==$3$5');
// add license
return license + '\n;' + source;
source = license + '\n;' + source;
// add trailing semicolon
return source.replace(/[\s;]*$/, ';');
}
/*--------------------------------------------------------------------------*/

View File

@@ -5,65 +5,56 @@
/** The Node filesystem module */
var fs = require('fs');
/** Used to minify string values embedded in compiled strings */
var compiledValues = [
'arrays',
'objects'
];
/** Used to minify variables embedded in compiled strings */
var compiledVars = [
'accumulator',
'array',
'arrayClass',
'bind',
'callback',
'className',
'collection',
'computed',
'concat',
'current',
'ctor',
'false',
'funcClass',
'hasOwnProperty',
'identity',
'index',
'indexOf',
'Infinity',
'initial',
'isArray',
'isEmpty',
'length',
'object',
'Math',
'objectTypes',
'noaccum',
'property',
'result',
'slice',
'skipProto',
'source',
'sourceIndex',
'stringClass',
'target',
'thisArg',
'toString',
'true',
'undefined',
'value',
'values'
'value'
];
/** Used to minify `iterationFactory` option properties */
var iterationFactoryOptions = [
'afterLoop',
/** Used to minify `compileIterator` option properties */
var iteratorOptions = [
'args',
'array',
'arrayBranch',
'beforeLoop',
'bottom',
'exits',
'exit',
'firstArg',
'hasExp',
'hasDontEnumBug',
'inLoop',
'init',
'iterate',
'iteratedObject',
'loopExp',
'object',
'returns',
'objectBranch',
'shadowed',
'top',
'useHas'
];
@@ -74,21 +65,119 @@
/** Used protect the specified properties from getting minified */
var propWhitelist = [
'_',
'_wrapped',
'after',
'all',
'amd',
'any',
'bind',
'bindAll',
'chain',
'clearTimeout',
'clone',
'collect',
'compact',
'compose',
'contains',
'criteria',
'debounce',
'defaults',
'defer',
'delay',
'detect',
'difference',
'each',
'environment',
'escape',
'escape',
'evaluate',
'every',
'extend',
'filter',
'find',
'first',
'flatten',
'foldl',
'foldr',
'forEach',
'functions',
'groupBy',
'has',
'head',
'identity',
'include',
'indexOf',
'initial',
'inject',
'interpolate',
'intersection',
'invoke',
'isArguments',
'isArray',
'isBoolean',
'isDate',
'isElement',
'isEmpty',
'isEqual',
'isEqual',
'isFinite',
'lodash',
'isFinite',
'isFunction',
'isNaN',
'isNull',
'isNumber',
'isObject',
'isRegExp',
'isString',
'isUndefined',
'keys',
'last',
'lastIndexOf',
'map',
'max',
'memoize',
'methods',
'min',
'mixin',
'noConflict',
'once',
'opera',
'partial',
'pick',
'pluck',
'range',
'reduce',
'reduceRight',
'reject',
'rest',
'result',
'select',
'setTimeout',
'shuffle',
'size',
'some',
'sortBy',
'sortedIndex',
'source',
'tail',
'take',
'tap',
'template',
'templateSettings',
'throttle',
'times',
'toArray',
'union',
'uniq',
'unique',
'uniqueId',
'value',
'variable'
'values',
'variable',
'VERSION',
'without',
'wrap',
'zip'
];
/*--------------------------------------------------------------------------*/
@@ -96,7 +185,6 @@
/**
* Pre-process a given JavaScript `source`, preparing it for minification.
*
* @private
* @param {String} source The source to process.
* @returns {String} Returns the processed source.
*/
@@ -105,87 +193,115 @@
source = source.replace(/\/\*![\s\S]+?\*\//, '');
// correct JSDoc tags for Closure Compiler
source = source.replace(/@(?:alias|category)[^\n]*/g, '');
source = source.replace(/@(?:alias|category)\b.*/g, '');
// add brackets to whitelisted properties so Closure Compiler won't mung them.
// add brackets to whitelisted properties so Closure Compiler won't mung them
// http://code.google.com/closure/compiler/docs/api-tutorial3.html#export
source = source.replace(RegExp('\\.(' + iterationFactoryOptions.concat(propWhitelist).join('|') + ')\\b', 'g'), "['$1']");
source = source.replace(RegExp('\\.(' + propWhitelist.join('|') + ')\\b', 'g'), "['$1']");
// minify `sortBy` and `template` methods
['sortBy', 'template'].forEach(function(methodName) {
var properties = ['criteria', 'value'],
snippet = source.match(RegExp('(\\n\\s*)function ' + methodName + '[\\s\\S]+?\\1}'))[0],
result = snippet;
// minify property strings
properties.forEach(function(property, index) {
result = result.replace(RegExp("'" + property + "'", 'g'), "'" + minNames[index] + "'");
// remove whitespace from string literals
source = source.replace(/'(?:(?=(\\?))\1.)*?'/g, function(string) {
// avoids removing the '\n' of the `escapes` object
return string.replace(/\[object |else if|function | in |return\s+[\w']|throw |typeof |use strict|var |'\\n'|\\\\n|\\n|\s+/g, function(match) {
return match == false || match == '\\n' ? '' : match;
});
// remove escaped newlines in strings
result = result.replace(/\\n/g, '');
// replace with modified snippet
source = source.replace(snippet, result);
});
// minify all `iterationFactory` related snippets
source.match(
RegExp([
// match variables storing `iterationFactory` options
'var [a-zA-Z]+FactoryOptions\\s*=\\s*\\{[\\s\\S]+?};\\n',
// match the the `iterationFactory` function
'(\\n\\s*)function iterationFactory[\\s\\S]+?\\1}',
// match methods created by `iterationFactor` calls
'iterationFactory\\((?:[\'{]|[a-zA-Z]+,)[\\s\\S]+?\\);\\n'
].join('|'), 'g')
)
.forEach(function(snippet, index) {
var result = snippet;
// minify `_.sortBy` internal properties
(function() {
var properties = ['criteria', 'value'],
snippet = (source.match(/( +)function sortBy\b[\s\S]+?\n\1}/) || 0)[0],
result = snippet;
// add `true` and `false` arguments to be minified
if (/function iterationFactory/.test(snippet)) {
result = result
.replace(/(Function\('[\s\S]+?)undefined/, '$1true,false,undefined')
.replace(/\)\([^)]+/, '$&,true,false');
// replace with modified snippet early and clip snippet
if (snippet) {
// minify property strings
properties.forEach(function(property, index) {
result = result.replace(RegExp("'" + property + "'", 'g'), "'" + minNames[index] + "'");
});
// replace with modified snippet
source = source.replace(snippet, result);
snippet = result = result.replace(/\)\([\s\S]+$/, '');
}
}());
// minify all compilable snippets
var snippets = source.match(
RegExp([
// match the `iteratorTemplate`
'var iteratorTemplate\\b[\\s\\S]+?\\);\\n',
// match methods created by `createIterator` calls
'createIterator\\((?:{|[a-zA-Z]+)[\\s\\S]+?\\);\\n',
// match variables storing `createIterator` options
'( +)var [a-zA-Z]+IteratorOptions\\b[\\s\\S]+?\\n\\1}',
// match the the `createIterator` function
'( +)function createIterator\\b[\\s\\S]+?\\n\\2}'
].join('|'), 'g')
);
// exit early if no compilable snippets
if (!snippets) {
return source;
}
snippets.forEach(function(snippet, index) {
var isCreateIterator = /function createIterator\b/.test(snippet),
isIteratorTemplate = /var iteratorTemplate\b/.test(snippet),
result = snippet;
// add brackets to whitelisted properties so Closure Compiler won't mung them
result = result.replace(RegExp('\\.(' + iteratorOptions.join('|') + ')\\b', 'g'), "['$1']");
if (isCreateIterator) {
// add `true` and `false` arguments to be minified
result = result
.replace(/(Function\(\s*'[\s\S]+?)undefined/, '$1true,false,undefined')
.replace(/factory\([^)]+/, '$&,true,false');
// replace with modified snippet early and clip snippet so other arguments
// aren't minified
source = source.replace(snippet, result);
snippet = result = result.replace(/factory\([\s\S]+$/, '');
}
// minify snippet variables/arguments
// minify snippet variables / arguments
compiledVars.forEach(function(variable, index) {
result = result.replace(RegExp('([^.]\\b|\\\\n)' + variable + '\\b(?!\'\\s*[\\]:])', 'g'), '$1' + minNames[index]);
// ensure properties in compiled strings aren't minified
result = result.replace(RegExp('([^.]\\b)' + variable + '\\b(?!\' *[\\]:])', 'g'), '$1' + minNames[index]);
// correct `typeof x == 'object'`
if (variable == 'object') {
result = result.replace(RegExp("(typeof [^']+')" + minNames[index] + "'", 'g'), "$1object'");
}
// correct boolean literals
if (variable == 'true' || variable == 'false') {
// correct external boolean literals
else if (variable == 'true' || variable == 'false') {
result = result
.replace(RegExp(':\\s*' + minNames[index] + '\\s*,', 'g'), ':' + variable + ',')
.replace(RegExp('\\s*' + minNames[index] + '\\s*;', 'g'), variable + ';');
.replace(RegExp(': *' + minNames[index] + ',', 'g'), ':' + variable + ',')
.replace(RegExp('\\b' + minNames[index] + ';', 'g'), variable + ';');
}
});
// minify snippet values
compiledValues.forEach(function(value, index) {
result = result.replace(RegExp("'" + value + "'", 'g'), "'" + minNames[index] + "'");
});
// minify iterationFactory option property strings
iterationFactoryOptions.forEach(function(property, index) {
if (property == 'array' || property == 'object') {
result = result.replace(RegExp("'" + property + "'(\\s*[\\]:])", 'g'), "'" + minNames[index] + "'$1");
} else {
result = result.replace(RegExp("'" + property + "'", 'g'), "'" + minNames[index] + "'");
// minify `createIterator` option property names
iteratorOptions.forEach(function(property, index) {
if (isIteratorTemplate) {
// minify property names as interpolated template variables
result = result.replace(RegExp('\\b' + property + '\\b', 'g'), minNames[index]);
}
else {
if (property == 'array' || property == 'object') {
// minify "array" and "object" sub property names
result = result.replace(RegExp("'" + property + "'( *[\\]:])", 'g'), "'" + minNames[index] + "'$1");
}
else {
// minify property name strings
result = result.replace(RegExp("'" + property + "'", 'g'), "'" + minNames[index] + "'");
// minify property names in regexps and accessors
if (isCreateIterator) {
result = result.replace(RegExp('([\\.|/])' + property + '\\b' , 'g'), '$1' + minNames[index]);
}
}
}
});
// remove escaped newlines in strings
result = result.replace(/\\n/g, '');
// replace with modified snippet
source = source.replace(snippet, result);
});
@@ -198,7 +314,8 @@
// expose `preprocess`
if (module != require.main) {
module.exports = preprocess;
} else {
}
else {
// read the JavaScript source file from the first argument if the script
// was invoked directly (e.g. `node pre-compile.js source.js`) and write to
// the same file

File diff suppressed because it is too large Load Diff

View File

@@ -21,7 +21,7 @@
// generate Markdown
$markdown = docdown(array(
'path' => '../' . $file,
'title' => 'Lo-Dash <sup>v0.1.0</sup>',
'title' => 'Lo-Dash <sup>v0.2.1</sup>',
'url' => 'https://github.com/bestiejs/lodash/blob/master/lodash.js'
));

2380
lodash.js

File diff suppressed because it is too large Load Diff

50
lodash.min.js vendored
View File

@@ -1,26 +1,30 @@
/*!
Lo-Dash 0.1.0 github.com/bestiejs/lodash/blob/master/LICENSE.txt
Lo-Dash 0.2.1 lodash.com/license
Underscore.js 1.3.3 github.com/documentcloud/underscore/blob/master/LICENSE
*/
;(function(r,h){"use strict";var n=!0,o=!1;function Q(a){return"[object Arguments]"==k.call(a)}function i(a){return new p(a)}function p(a){this.o=a}function g(){for(var a,b=-1,c={},d={},f={},e=["d","j","g","a"];++b<arguments.length;)for(a in arguments[b])f[a]=arguments[b][a];for(;a=e.pop();)"object"==typeof f[a]?(c[a]=f[a].c,d[a]=f[a].k):c[a]=d[a]=f[a]||"";a=f.b;var b=/^[^,]+/.exec(a)[0],e=f.h,j=f.i,g=!("v"==a||"b"==j),j=!("b"==a||"a"==j),h=f.n!==o;return Function("c,d,i,l,m,n,p,q,s,t,w,z,B,E,F,k,G",'"use strict";return function('+
a+"){"+(f.m||"")+";"+("var o, y"+(e?"="+e:""))+";if("+b+"==G)return "+(f.f||"y")+";"+(g?"var u="+b+".length;o=-1;"+((j?"if(u===+u){":"")+(c.d||"")+";while("+(c.j||"++o<u")+"){"+c.g+"}"+(c.a||"")+";"+(j?"}":"")):"")+(j?(g?"else{":"")+(d.d||"")+";for("+(d.j||"o in "+b)+"){"+(h?"if(m.call("+/\S+$/.exec(d.j||b)[0]+",o)){":"")+d.g+(h?"}":"")+"}"+(d.a||"")+";"+(g?"}":""):"")+(f.e||"")+";return "+(f.l||"y")+"}")(D,u,ba,ca,s,R,E,Infinity,F,da,Math,l,G,k,n,o)}function S(a){return a.replace(ua,function(a,c){return y[c]})}
function ea(a,b,c,d){var f=2<arguments.length;if(a==h)return c;d&&(b=u(b,d));var e=a.length;if(e===+e){for(e&&!f&&(c=a[--e]);e--;)c=b(c,a[e],e,a);return c}var j=T(a);for((e=j.length)&&!f&&(c=a[j[--e]]);e--;)f=j[e],c=b(c,a[f],f,a);return c}function fa(a,b,c){var d=0,f=a.length;for(c||(c=R);d<f;){var e=d+f>>1;c(a[e])<c(b)?d=e+1:f=e}return d}function U(a,b,c){return b==h||c?a[0]:l.call(a,0,b)}function H(a,b){return b?ba.apply([],a):z(a,function(a,b){if(F(b))return V.apply(a,H(b)),a;a.push(b);return a},
[])}function E(a,b,c){var d;if(a==h)return-1;if(c)return c=fa(a,b),a[c]===b?c:-1;c=0;for(d=a.length;c<d;c++)if(a[c]===b)return c;return-1}function ga(a){var b=l.call(arguments,1);return W(I(a),function(a){return X(b,function(b){return 0<=E(b,a)})})}function ha(a,b,c){var d=a.length;return b==h||c?a[d-1]:l.call(a,-b||d)}function ia(a,b,c){return l.call(a,b==h||c?1:b)}function I(a,b,c){var c=c?A(a,c):a,d=[];3>a.length&&(b=n);z(c,function(c,e,j){if(b?ha(c)!==e||!c.length:0>E(c,e))c.push(e),d.push(a[j]);
return c},[]);return d}function u(a,b){var c=l.call(arguments,2),d=c.length;return function(){c.length=d;V.apply(c,arguments);return a.apply(b,c)}}function ja(a,b,c){var d;return function(){var f=arguments,e=this;c&&!d&&a.apply(e,f);va(d);d=J(function(){d=h;c||a.apply(e,f)},b)}}function Y(a,b,c){c||(c=[]);if(a===b)return 0!==a||1/a==1/b;if(a==h||b==h)return a===b;a.p&&(a=a.o);b.p&&(b=b.o);if(a.isEqual&&q(a.isEqual))return a.isEqual(b);if(b.isEqual&&q(b.isEqual))return b.isEqual(a);var d=k.call(a);
if(d!=k.call(b))return o;switch(d){case G:return a==""+b;case K:return a!=+a?b!=+b:0==a?1/a==1/b:a==+b;case ka:case la:return+a==+b;case ma:return a.source==b.source&&a.global==b.global&&a.multiline==b.multiline&&a.ignoreCase==b.ignoreCase}if("object"!=typeof a||"object"!=typeof b)return o;for(var f=c.length;f--;)if(c[f]==a)return n;var f=n,e=0;c.push(a);if(d==D){if(e=a.length,f=e==b.length)for(;e--&&(f=e in a==e in b&&Y(a[e],b[e],c)););}else{if("constructor"in a!="constructor"in b||a.constructor!=
b.constructor)return o;for(var j in a)if(s.call(a,j)&&(e++,!(f=s.call(b,j)&&Y(a[j],b[j],c))))break;if(f){for(j in b)if(s.call(b,j)&&!e--)break;f=!e}}c.pop();return f}function q(a){return k.call(a)==ca}function R(a){return a}function na(a){t(L(a),function(b){var c=i[b]=a[b];i.prototype[b]=function(){var a=l.call(arguments);wa.call(a,this.o);a=c.apply(i,a);return this.p?(new p(a)).chain():a}})}var y={"\\":"\\","'":"'",r:"\r",n:"\n",t:"\t",u2028:"\u2028",u2029:"\u2029"};(function(){for(var a in y)y[y[a]]=
a})();var Z="object"==typeof exports&&exports&&("object"==typeof global&&global&&global==global.global&&(r=global),exports),xa=0,ya=r._,za=/\\|'|\r|\n|\t|\u2028|\u2029/g,$=/.^/,ua=/\\(\\|'|r|n|t|u2028|u2029)/g,D="[object Array]",ka="[object Boolean]",la="[object Date]",ca="[object Function]",K="[object Number]",ma="[object RegExp]",G="[object String]",v=Array.prototype,M=Object.prototype,ba=v.concat,s=M.hasOwnProperty,V=v.push,l=v.slice,k=M.toString,wa=v.unshift,Aa=r.isFinite,M=Object.keys,va=r.clearTimeout,
J=r.setTimeout,N={b:"b",m:"var I=i.apply([],z.call(arguments,1))",h:"[]",g:"if(p(I,b[o])<0)y.push(b[o])"},w={h:"F",g:"if(!e(g[o],o,g))return !y"},aa={b:"v",h:"v",d:"for(var A,j=1,u=arguments.length;j<u;j++){A=arguments[j]",j:"o in A",g:"v[o]=A[o]",n:o,a:"}"},B={h:"[]",g:"e(g[o],o,g)&&y.push(g[o])"},m={b:"g,e,D",m:"if(!e){e=n}else if(D){e=d(e,D)}",h:"g",g:"e(g[o],o,g)"},oa={b:"v",m:"if(v!==Object(v))throw TypeError()",h:"[]",g:"y.push(o)"},C={h:"",f:"[]",d:{c:"y=Array(u)",k:"y=[]"},g:{c:"y[o]=e(g[o],o,g)",
k:"y[y.length]=e(g[o],o,g)"}},x={m:"var j,y=-q,h=y;if(!e){if(s(g)&&g[0]===+g[0])return w.max.apply(w,g);if(t(g))return y;}else if(D)e=d(e,D)",g:"j=e?e(g[o],o,g):g[o];if(j>=h)h=j,y=g[o]"},F=Array.isArray||function(a){return k.call(a)==D},da=g({b:"H",i:"b",m:"var f=E.call(H)",h:"F",d:"if(f==c||f==B)return !H.length",g:"return k"}),pa=g({b:"g,C",h:"k",g:"if(g[o]===C)return F"}),X=g(m,w),W=g(m,B),qa=g(m,{g:"if(e(g[o],o,g))return g[o]"}),t=g(m),A=g(m,C),ra=g(m,x),x=g(m,x,{m:x.m.replace("-","").replace("max",
"min"),g:x.g.replace(">=","<")}),O=g(C,{b:"g,x",g:{c:"y[o]=g[o][x]",k:"y[y.length]=g[o][x]"}}),z=g({b:"g,e,a,D",m:"var r=arguments.length>2;if(D)e=d(e,D)",h:"a",d:{c:"if(!r)y=g[++o]"},g:{c:"y=e(y,g[o],o,g)",k:"y=r?e(y,g[o],o,g):(r=F,g[o])"}}),B=g(m,B,{g:"!"+B.g}),w=g(m,w,{h:"k",g:w.g.replace("!","")}),sa=g(C,{b:"g",g:{c:"y[o]=g[o]",k:"y[y.length]=g[o]"}}),C=g({b:"b",h:"[]",g:"if(b[o])y.push(b[o])"}),m=g(N),N=g(N,{m:"var I=z.call(arguments,1)",h:"[]"}),ta=g(aa,{g:"if(v[o]==G)"+aa.g}),P=g(aa),L=g(oa,
{m:"",n:o,g:"if(E.call(v[o])==l)y.push(o)",l:"y.sort()"});Q(arguments)||(Q=function(a){return!(!a||!s.call(a,"callee"))});var T=M||g(oa);P(i,{VERSION:"0.1.0",templateSettings:{escape:/<%-([\s\S]+?)%>/g,evaluate:/<%([\s\S]+?)%>/g,interpolate:/<%=([\s\S]+?)%>/g},after:function(a,b){return 1>a?b():function(){if(1>--a)return b.apply(this,arguments)}},bind:u,bindAll:function(a){var b=arguments,c=1;1==b.length&&(c=0,b=L(a));for(var d=b.length;c<d;c++)a[b[c]]=u(a[b[c]],a);return a},chain:function(a){return(new p(a)).chain()},
clone:function(a){return a!==Object(a)?a:F(a)?a.slice():P({},a)},compact:C,compose:function(){var a=arguments;return function(){for(var b=arguments,c=a.length;c--;)b=[a[c].apply(this,b)];return b[0]}},contains:pa,debounce:ja,defaults:ta,defer:function(a){var b=l.call(arguments,1);return J(function(){return a.apply(h,b)},1)},delay:function(a,b){var c=l.call(arguments,2);return J(function(){return a.apply(h,c)},b)},difference:m,escape:function(a){return(a+"").replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,
"&gt;").replace(/"/g,"&quot;").replace(/'/g,"&#x27;").replace(/\//g,"&#x2F;")},every:X,extend:P,filter:W,find:qa,first:U,flatten:H,forEach:t,functions:L,groupBy:function(a,b){var c={};if(!q(b))var d=b,b=function(a){return a[d]};t(a,function(a,e,d){e=b(a,e,d);(c[e]||(c[e]=[])).push(a)});return c},has:function(a,b){return s.call(a,b)},identity:R,indexOf:E,initial:function(a,b,c){return l.call(a,0,-(b==h||c?1:b))},intersection:ga,invoke:function(a,b){var c=l.call(arguments,2),d=q(b);return A(a,function(a){return(d?
b||a:a[b]).apply(a,c)})},isArguments:Q,isArray:F,isBoolean:function(a){return a===n||a===o||k.call(a)==ka},isDate:function(a){return k.call(a)==la},isElement:function(a){return!!(a&&1==a.nodeType)},isEmpty:da,isEqual:Y,isFinite:function(a){return Aa(a)&&k.call(a)==K},isFunction:q,isNaN:function(a){return k.call(a)==K&&a!=+a},isNull:function(a){return null===a},isNumber:function(a){return k.call(a)==K},isObject:function(a){return a===Object(a)},isRegExp:function(a){return k.call(a)==ma},isString:function(a){return k.call(a)==
G},isUndefined:function(a){return a===h},keys:T,last:ha,lastIndexOf:function(a,b){if(a==h)return-1;for(var c=a.length;c--;)if(a[c]===b)return c;return-1},map:A,max:ra,memoize:function(a,b){var c={};return function(){var d=b?b.apply(this,arguments):arguments[0];return s.call(c,d)?c[d]:c[d]=a.apply(this,arguments)}},min:x,mixin:na,noConflict:function(){r._=ya;return this},once:function(a){var b,c=o;return function(){if(c)return b;c=n;return b=a.apply(this,arguments)}},pick:function(a){for(var b,c=-1,
d=H(l.call(arguments,1)),f=d.length,e={};++c<f;)b=d[c],b in a&&(e[b]=a[b]);return e},pluck:O,range:function(a,b,c){c||(c=1);2>arguments.length&&(b=a||0,a=0);for(var d=-1,f=Math.max(Math.ceil((b-a)/c),0),e=Array(f);++d<f;)e[d]=a,a+=c;return e},reduce:z,reduceRight:ea,reject:B,rest:ia,result:function(a,b){if(a==h)return null;var c=a[b];return q(c)?a[b]():c},shuffle:function(a){var b,c=[];t(a,function(a,f){b=Math.floor(Math.random()*(f+1));c[f]=c[b];c[b]=a});return c},size:function(a){var b=k.call(a);
return b==D||b==G?a.length:T(a).length},some:w,sortBy:function(a,b,c){if(q(b))c&&(b=u(b,c));else var d=b,b=function(a){return a[d]};return O(A(a,function(c,e){return{a:b(c,e,a),b:c}}).sort(function(a,b){var c=a.a,d=b.a;return c===h?1:d===h?-1:c<d?-1:c>d?1:0}),"b")},sortedIndex:fa,tap:function(a,b){b(a);return a},template:function(a,b,c){function d(a){return f.call(this,a,i)}c=ta(c||{},i.templateSettings);a="__p+='"+a.replace(za,function(a){return"\\"+y[a]}).replace(c.escape||$,function(a,b){return"'+((__t=("+
S(b)+"))==null?'':_['escape'](__t))+'"}).replace(c.interpolate||$,function(a,b){return"'+((__t=("+S(b)+"))==null?'':__t)+'"}).replace(c.evaluate||$,function(a,b){return"';"+S(b)+";__p+='"})+"';";c.variable||(a="with(object||{}){"+a+"}");var a='var __t,__j=Array.prototype.join,__p="";function print(){__p+=__j.call(arguments,"")}'+a+"return __p",f=Function(c.variable||"object","_",a);if(b)return f(b,i);d.source="function("+(c.variable||"object")+"){"+a+"}";return d},throttle:function(a,b){var c,d,f,
e,g,i,k=ja(function(){d=g=o},b);return function(){c=arguments;e=this;i||(i=J(function(){i=h;d&&a.apply(e,c);k()},b));g?d=n:f=a.apply(e,c);k();g=n;return f}},times:function(a,b,c){c&&(b=u(b,c));for(c=0;c<a;c++)b(c)},toArray:function(a){if(!a)return[];if(q(a.toArray))return a.toArray();var b=a.length;return b===+b?l.call(a):sa(a)},union:function(){return I(H(arguments,n))},uniq:I,uniqueId:function(a){var b=xa++;return a?a+b:b},values:sa,without:N,wrap:function(a,b){return function(){var c=[a];V.apply(c,
arguments);return b.apply(this,c)}},zip:function(){for(var a=-1,b=ra(O(arguments,"length")),c=Array(b);++a<b;)c[a]=O(arguments,a);return c},all:X,any:w,collect:A,detect:qa,each:t,foldl:z,foldr:ea,head:U,include:pa,inject:z,intersect:ga,methods:L,select:W,tail:ia,take:U,unique:I});p.prototype=i.prototype;na(i);t("pop,push,reverse,shift,sort,splice,unshift".split(","),function(a){var b=v[a];i.prototype[a]=function(){var a=this.o;b.apply(a,arguments);a.length===0&&delete a[0];return this.p?(new p(a)).chain():
a}});t(["concat","join","slice"],function(a){var b=v[a];p.prototype[a]=function(){var a=b.apply(this.o,arguments);return this.p?(new p(a)).chain():a}});P(p.prototype,{chain:function(){this.p=n;return this},value:function(){return this.o}});Z?"object"==typeof module&&module&&module.q==Z?(module.q=i)._=i:Z._=i:(r._=i,"function"==typeof define&&"object"==typeof define.amd&&define.amd&&define.amd.lodash&&define("lodash",function(){return i}))})(this);
;(function(u,n){"use strict";function R(a){return"[object Arguments]"==i.call(a)}function b(a){return new p(a)}function p(a){if(a&&a._wrapped)return a;this._wrapped=a}function k(){for(var a,c,d,j=-1,b=arguments.length,e={e:"",f:"",k:"",q:"",c:{d:"",m:"++l<m"},o:{d:""}};++j<b;)for(c in a=arguments[j],a)d=(d=a[c])==o?"":d,/d|m|j/.test(c)?("string"==typeof d&&(d={b:d,n:d}),e.c[c]=d.b,e.o[c]=d.n):e[c]=d;a=e.a,c=e.c,d=e.o;var j=/^[^,]+/.exec(a)[0],b=d.m,g=/\S+$/.exec(b||j)[0];e.g=j,e.i=G,e.h="j.call("+
g+",l)",e.l=g,e.p=ca,e.r=e.r!==q,e.f||(e.f="if(!"+j+")return r");if("n"==j||!c.j)e.c=o;return b||(d.m="l in "+g),Function("b,c,i,j,k,o,v,y,z,h,A",'"use strict";return function('+a+"){"+sa(e)+"}")(H,v,r,s,da,I,J,i,m,q)}function ta(a,c){return w[c]}function ua(a){return"\\"+va[a]}function ea(){}function wa(a,c){var d=w.length;return w[d]="'+((__t=("+c+"))==null?'':_['escape'](__t))+'",S+d}function xa(a,c){var d=w.length;return w[d]="'+((__t=("+c+"))==null?'':__t)+'",S+d}function ya(a,c){var d=w.length
;return w[d]="';"+c+";__p+='",S+d}function fa(a,c,d,j){if(!a)return d;var b=a.length,e=3>arguments.length;j&&(c=v(c,j));if(b===+b){for(b&&e&&(d=a[--b]);b--;)d=c(d,a[b],b,a);return d}var g=T(a);for((b=g.length)&&e&&(d=a[g[--b]]);b--;)e=g[b],d=c(d,a[e],e,a);return d}function U(a,c,d){return c==n||d?a[0]:l.call(a,0,c)}function ga(a,c){for(var d,b=-1,f=a.length,e=[];++b<f;)d=a[b],V(d)?K.apply(e,c?d:ga(d)):e.push(d);return e}function x(a,c,d){var b;if(!a)return-1;if(d)return d=ha(a,c),a[d]===c?d:-1;d=0
;for(b=a.length;d<b;d++)if(a[d]===c)return d;return-1}function ia(a,c,d){var b=-Infinity,f=-1,e=a.length,g=b;if(!c){for(;++f<e;)a[f]>g&&(g=a[f]);return g}for(d&&(c=v(c,d));++f<e;)d=c(a[f],f,a),d>b&&(b=d,g=a[f]);return g}function ja(a,c,d){return l.call(a,c==n||d?1:c)}function ha(a,c,d){var b,f=0,e=a.length;for(d&&(c=d(c));f<e;)b=f+e>>1,(d?d(a[b]):a[b])<c?f=b+1:e=b;return f}function ka(a,c,d){for(var b,f=-1,e=a.length,g=[],h=[];++f<e;)if(b=d?d(a[f]):a[f],c?!f||h[h.length-1]!==b:0>x(h,b))h.push(b),
g.push(a[f]);return g}function v(a,c){function d(){var g=arguments,h=c;return f||(a=c[b]),e.length&&(g=g.length?L.apply(e,g):e),this instanceof d?(ea.prototype=a.prototype,h=new ea,g=a.apply(h,g),I[typeof g]&&g!==o?g:h):a.apply(h,g)}var b,f=i.call(a)==r;if(f){if(y)return y.call.apply(y,arguments)}else b=c,c=a;var e=l.call(arguments,2);return d}function M(a,c,d){d||(d=[]);if(a===c)return 0!==a||1/a==1/c;if(a==n||c==n)return a===c;a.s&&(a=a._wrapped),c.s&&(c=c._wrapped);if(a.isEqual&&i.call(a.isEqual
)==r)return a.isEqual(c);if(c.isEqual&&i.call(c.isEqual)==r)return c.isEqual(a);var b=i.call(a);if(b!=i.call(c))return q;switch(b){case J:return a==""+c;case N:return a!=+a?c!=+c:0==a?1/a==1/c:a==+c;case la:case ma:return+a==+c;case na:return a.source==c.source&&a.global==c.global&&a.multiline==c.multiline&&a.ignoreCase==c.ignoreCase}if("object"!=typeof a||"object"!=typeof c)return q;for(var f=d.length;f--;)if(d[f]==a)return m;var f=-1,e=m,g=0;d.push(a);if(b==H){if(g=a.length,e=g==c.length)for(;g--&&
(e=M(a[g],c[g],d)););}else{if("constructor"in a!="constructor"in c||a.constructor!=c.constructor)return q;for(var h in a)if(s.call(a,h)&&(g++,!(e=s.call(c,h)&&M(a[h],c[h],d))))break;if(e){for(h in c)if(s.call(c,h)&&!(g--))break;e=!g}if(e&&G)for(;7>++f&&(h=ca[f],!s.call(a,h)||!!(e=s.call(c,h)&&M(a[h],c[h],d))););}return d.pop(),e}function da(a){return a}function oa(a){B(O(a),function(c){var d=b[c]=a[c];p.prototype[c]=function(){var a=[this._wrapped];return arguments.length&&K.apply(a,arguments),a=1==
a.length?d.call(b,a[0]):d.apply(b,a),this.s&&(a=new p(a),a.s=m),a}})}var m=!0,o=null,q=!1,W="object"==typeof exports&&exports&&("object"==typeof global&&global&&global==global.global&&(u=global),exports),va={"\\":"\\","'":"'","\n":"n","\r":"r"," ":"t","\u2028":"u2028","\u2029":"u2029"},G=!{valueOf:0}.propertyIsEnumerable("valueOf"),za=0,I={"boolean":q,"function":m,object:m,number:q,string:q,"undefined":q},Aa=u._,z=RegExp("^"+({}.valueOf+"").replace(/[.*+?^=!:${}()|[\]\/\\]/g,"\\$&").replace(/valueOf|for [^\]]+/g
,".+?")+"$"),Ba=/__token__(\d+)/g,Ca=/['\n\r\t\u2028\u2029\\]/g,ca="constructor hasOwnProperty isPrototypeOf propertyIsEnumerable toLocaleString toString valueOf".split(" "),S="__token__",w=[],H="[object Array]",la="[object Boolean]",ma="[object Date]",r="[object Function]",N="[object Number]",na="[object RegExp]",J="[object String]",A=Array.prototype,C=Object.prototype,L=A.concat,s=C.hasOwnProperty,K=A.push,l=A.slice,i=C.toString,y=z.test(y=l.bind)&&/\n|Opera/.test(y+i.call(u.opera))&&y,D=z.test
(D=Array.isArray)&&D,Da=u.isFinite,X=z.test(X=Object.keys)&&X,Ea=u.clearTimeout,P=u.setTimeout;b.templateSettings={escape:/<%-([\s\S]+?)%>/g,evaluate:/<%([\s\S]+?)%>/g,interpolate:/<%=([\s\S]+?)%>/g,variable:"object"};var sa=Function("n","var __p;with(n){__p='var l,r';if(k){__p+='='+k};__p+=';'+f+';'+q+';';if(c){__p+='var m='+g+'.length;l=-1;';if(o){__p+='if(m===+m){'};__p+=''+c['d']+';while('+c['m']+'){'+c['j']+'}';if(o){__p+='}'}}if(o){if(c){__p+='else{'}if(!i){__p+='var s=typeof '+l+'==\\'function\\';'};__p+=''+o['d']+';for('+o['m']+'){';if(i){if(r){__p+='if('+h+'){'};__p+=''+o['j']+';';if(r){__p+='}'}}else{__p+='if(!(s&&l==\\'prototype\\')';if(r){__p+='&&'+h};__p+='){'+o['j']+'}'};__p+='}';if(i){__p+='var g='+l+'.constructor;';for(var k=0;k<7;k++){__p+='l=\\''+p[k]+'\\';if(';if(p[k]=='constructor'){__p+='!(g&&g.prototype==='+l+')&&'};__p+=''+h+'){'+o['j']+'}'}}if(c){__p+='}'}};__p+=''+e+';return r'}return __p"
),t={a:"f,d,x",k:"f",q:"if(!d){d=k}else if(x){d=c(d,x)}",j:"d(f[l],l,f)"},Y={k:"z",j:"if(!d(f[l],l,f))return!r"},Z={a:"n",k:"n",q:"for(var t,u=1,m=arguments.length;u<m;u++){t=arguments[u];"+(G?"if(t){":""),m:"l in t",r:q,j:"n[l]=t[l]",e:(G?"}":"")+"}"},E={k:"[]",j:"d(f[l],l,f)&&r.push(f[l])"},F={k:"",f:"if(!f)return[]",d:{b:"r=Array(m)",n:"r=[]"},j:{b:"r[l]=d(f[l],l,f)",n:"r.push(d(f[l],l,f))"}},z=k({a:"f,w",k:"h",j:"if(f[l]===w)return z"}),$=k(t,Y),C=k(t,E),pa=k(t,{j:"if(d(f[l],l,f))return f[l]"
}),B=k(t,{q:"if(x)d=c(d,x)"}),aa=k(t,F),Q=k(F,{a:"f,q",j:{b:"r[l]=f[l][q]",n:"r.push(f[l][q])"}}),ba=k({a:"f,d,a,x",k:"a",q:"var p=arguments.length<3;if(x)d=c(d,x)",d:{b:"if(p)r=f[++l]"},j:{b:"r=d(r,f[l],l,f)",n:"r=p?(p=h,f[l]):d(r,f[l],l,f)"}}),E=k(t,E,{j:"!"+E.j}),t=k(t,Y,{k:"h",j:Y.j.replace("!","")}),qa=k(F,{a:"f",j:{b:"r[l]=f[l]",n:"r.push(f[l])"}}),F=k(Z,{j:"if(n[l]==A)"+Z.j}),ra=k(Z),O=k({a:"n",k:"[]",r:q,j:"if(y.call(n[l])==i)r.push(l)",e:"r.sort()"});R(arguments)||(R=function(a){return!!
a&&!!s.call(a,"callee")});var V=D||function(a){return i.call(a)==H},D=k({a:"B",k:"z",q:"var e=y.call(B);if(e==b||e==v)return!B.length",j:{n:"return h"}}),T=X||k({a:"n",f:"if(!o[typeof n]||n===null)throw TypeError()",k:"[]",j:"r.push(l)"});b.VERSION="0.2.1",b.after=function(a,c){return 1>a?c():function(){if(1>--a)return c.apply(this,arguments)}},b.bind=v,b.bindAll=function(a){var c=arguments,d=1;1==c.length&&(d=0,c=O(a));for(var b=c.length;d<b;d++)a[c[d]]=v(a[c[d]],a);return a},b.chain=function(a)
{return a=new p(a),a.s=m,a},b.clone=function(a){return I[typeof a]&&a!==o?V(a)?a.slice():ra({},a):a},b.compact=function(a){for(var c=-1,d=a.length,b=[];++c<d;)a[c]&&b.push(a[c]);return b},b.compose=function(){var a=arguments;return function(){for(var c=arguments,d=a.length;d--;)c=[a[d].apply(this,c)];return c[0]}},b.contains=z,b.debounce=function(a,c,d){function b(){h=n,d||a.apply(g,f)}var f,e,g,h;return function(){var i=d&&!h;return f=arguments,g=this,Ea(h),h=P(b,c),i&&(e=a.apply(g,f)),e}},b.defaults=
F,b.defer=function(a){var c=l.call(arguments,1);return P(function(){return a.apply(n,c)},1)},b.delay=function(a,c){var d=l.call(arguments,2);return P(function(){return a.apply(n,d)},c)},b.difference=function(a){for(var c=-1,d=a.length,b=[],f=L.apply(b,l.call(arguments,1));++c<d;)0>x(f,a[c])&&b.push(a[c]);return b},b.escape=function(a){return(a+"").replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/"/g,"&quot;").replace(/'/g,"&#x27;").replace(/\//g,"&#x2F;")},b.every=$,b.extend=ra,b.filter=C,b.find=
pa,b.first=U,b.flatten=ga,b.forEach=B,b.functions=O,b.groupBy=function(a,c,d){var b,f=-1,e=i.call(c)==r,g=a.length,h={};for(e&&d&&(c=v(c,d));++f<g;)b=a[f],d=e?c(b,f,a):b[c],(s.call(h,d)?h[d]:h[d]=[]).push(b);return h},b.has=function(a,c){return s.call(a,c)},b.identity=da,b.indexOf=x,b.initial=function(a,c,d){return l.call(a,0,-(c==n||d?1:c))},b.intersection=function(a){for(var c,d=-1,b=a.length,f=l.call(arguments,1),e=[];++d<b;)c=a[d],0>x(e,c)&&$(f,function(a){return-1<x(a,c)})&&e.push(c);return e
},b.invoke=function(a,c){for(var d=l.call(arguments,2),b=-1,f=a.length,e=i.call(c)==r,g=[];++b<f;)g[b]=(e?c:a[b][c]).apply(a[b],d);return g},b.isArguments=R,b.isArray=V,b.isBoolean=function(a){return a===m||a===q||i.call(a)==la},b.isDate=function(a){return i.call(a)==ma},b.isElement=function(a){return!!a&&1==a.nodeType},b.isEmpty=D,b.isEqual=M,b.isFinite=function(a){return Da(a)&&i.call(a)==N},b.isFunction=function(a){return i.call(a)==r},b.isNaN=function(a){return i.call(a)==N&&a!=+a},b.isNull=function(
a){return a===o},b.isNumber=function(a){return i.call(a)==N},b.isObject=function(a){return I[typeof a]&&a!==o},b.isRegExp=function(a){return i.call(a)==na},b.isString=function(a){return i.call(a)==J},b.isUndefined=function(a){return a===n},b.keys=T,b.last=function(a,c,d){var b=a.length;return c==n||d?a[b-1]:l.call(a,-c||b)},b.lastIndexOf=function(a,c){if(!a)return-1;for(var d=a.length;d--;)if(a[d]===c)return d;return-1},b.map=aa,b.max=ia,b.memoize=function(a,c){var d={};return function(){var b=c?
c.apply(this,arguments):arguments[0];return s.call(d,b)?d[b]:d[b]=a.apply(this,arguments)}},b.min=function(a,c,d){var b=Infinity,f=-1,e=a.length,g=b;if(!c){for(;++f<e;)a[f]<g&&(g=a[f]);return g}for(d&&(c=v(c,d));++f<e;)d=c(a[f],f,a),d<b&&(b=d,g=a[f]);return g},b.mixin=oa,b.noConflict=function(){return u._=Aa,this},b.once=function(a){var c,d=q;return function(){return d?c:(d=m,c=a.apply(this,arguments))}},b.partial=function(a){var c=l.call(arguments,1),d=c.length;return function(){var b;return b=arguments
,b.length&&(c.length=d,K.apply(c,b)),b=1==c.length?a.call(this,c[0]):a.apply(this,c),c.length=d,b}},b.pick=function(a){for(var c,d=0,b=L.apply(A,arguments),f=b.length,e={};++d<f;)c=b[d],c in a&&(e[c]=a[c]);return e},b.pluck=Q,b.range=function(a,c,d){d||(d=1),2>arguments.length&&(c=a||0,a=0);for(var b=-1,f=Math.max(Math.ceil((c-a)/d),0),e=Array(f);++b<f;)e[b]=a,a+=d;return e},b.reduce=ba,b.reduceRight=fa,b.reject=E,b.rest=ja,b.result=function(a,c){if(!a)return o;var d=a[c];return i.call(d)==r?a[c]
():d},b.shuffle=function(a){for(var c,d=-1,b=a.length,f=Array(b);++d<b;)c=Math.floor(Math.random()*(d+1)),f[d]=f[c],f[c]=a[d];return f},b.size=function(a){var c=i.call(a);return c==H||c==J?a.length:T(a).length},b.some=t,b.sortBy=function(a,c,d){if(i.call(c)!=r)var b=c,c=function(a){return a[b]};else d&&(c=v(c,d));return Q(aa(a,function(b,d){return{a:c(b,d,a),b:b}}).sort(function(a,c){var b=a.a,d=c.a;return b===n?1:d===n?-1:b<d?-1:b>d?1:0}),"b")},b.sortedIndex=ha,b.tap=function(a,c){return c(a),a}
,b.template=function(a,c,d){d||(d={});var j;j=b.templateSettings;var f=d.escape,e=d.evaluate,g=d.interpolate,d=d.variable;return f==o&&(f=j.escape),e==o&&(e=j.evaluate),g==o&&(g=j.interpolate),f&&(a=a.replace(f,wa)),g&&(a=a.replace(g,xa)),e&&(a=a.replace(e,ya)),a="__p='"+a.replace(Ca,ua).replace(Ba,ta)+"';\n",w.length=0,d||(d=j.variable,a="with("+d+"||{}){"+a+"}"),a="function("+d+"){var __p,__t,__j=Array.prototype.join;function print(){__p+=__j.call(arguments,'')}"+a+"return __p}",j=Function("_","return "+
a)(b),c?j(c):(j.source=a,j)},b.throttle=function(a,c){function b(){h=new Date,g=n,a.apply(e,j)}var j,f,e,g,h=0;return function(){var i=new Date,k=c-(i-h);return j=arguments,e=this,0>=k?(h=i,f=a.apply(e,j)):g||(g=P(b,k)),f}},b.times=function(a,c,b){b&&(c=v(c,b));for(b=0;b<a;b++)c(b)},b.toArray=function(a){if(!a)return[];if(i.call(a.toArray)==r)return a.toArray();var b=a.length;return b===+b?l.call(a):qa(a)},b.union=function(){for(var a=-1,b=[],d=L.apply(b,arguments),i=d.length;++a<i;)0>x(b,d[a])&&
b.push(d[a]);return b},b.uniq=ka,b.uniqueId=function(a){var b=za++;return a?a+b:b},b.values=qa,b.without=function(a){for(var b=l.call(arguments,1),d=-1,i=a.length,f=[];++d<i;)0>x(b,a[d])&&f.push(a[d]);return f},b.wrap=function(a,b){return function(){var d=[a];return arguments.length&&K.apply(d,arguments),b.apply(this,d)}},b.zip=function(){for(var a=-1,b=ia(Q(arguments,"length")),d=Array(b);++a<b;)d[a]=Q(arguments,a);return d},b.all=$,b.any=t,b.collect=aa,b.detect=pa,b.each=B,b.foldl=ba,b.foldr=fa
,b.head=U,b.include=z,b.inject=ba,b.methods=O,b.select=C,b.tail=ja,b.take=U,b.unique=ka,p.prototype=b.prototype,oa(b),p.prototype.chain=function(){return this.s=m,this},p.prototype.value=function(){return this._wrapped},B("pop push reverse shift sort splice unshift".split(" "),function(a){var b=A[a];p.prototype[a]=function(){var a=this._wrapped;return arguments.length?b.apply(a,arguments):b.call(a),a.length===0&&delete a[0],this.s&&(a=new p(a),a.s=m),a}}),B(["concat","join","slice"],function(a){var b=
A[a];p.prototype[a]=function(){var a=this._wrapped,a=arguments.length?b.apply(a,arguments):b.call(a);return this.s&&(a=new p(a),a.s=m),a}}),typeof define=="function"&&typeof define.amd=="object"&&define.amd?(u._=b,define(function(){return b})):W?"object"==typeof module&&module&&module.t==W?(module.t=b)._=b:W._=b:u._=b})(this);

View File

@@ -1,8 +1,8 @@
{
"name": "lodash",
"version": "0.1.0",
"description": "A drop-in replacement for Underscore.js that delivers up to 8x performance improvements, bug fixes, and additional features.",
"homepage": "https://github.com/bestiejs/lodash",
"version": "0.2.1",
"description": "A drop-in replacement for Underscore.js that delivers performance improvements, bug fixes, and additional features.",
"homepage": "http://lodash.com",
"main": "lodash",
"keywords": [
"browser",
@@ -16,7 +16,7 @@
"licenses": [
{
"type": "MIT",
"url": "http://mths.be/mit"
"url": "http://lodash.com/license"
}
],
"author": {

46
perf/index.html Normal file
View File

@@ -0,0 +1,46 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Lo-Dash Performance Suite</title>
<style>
html, body {
margin: 0;
padding: 0;
height: 100%;
}
applet {
position: absolute;
left: -9999em;
}
</style>
</head>
<body>
<script src="../lodash.js"></script>
<script>
var lodash = _.noConflict();
</script>
<script src="../vendor/underscore/underscore.js"></script>
<script src="../vendor/benchmark.js/benchmark.js"></script>
<script src="../vendor/firebug-lite/src/firebug-lite-debug.js"></script>
<script>
(function() {
if (!/[?&]nojava=true(?:&|$)/.test(location.search)) {
// using innerHTML avoids an alert in some versions of IE6
var div = document.createElement('div');
div.innerHTML = '<applet code=nano archive="../vendor/benchmark.js/nano.jar">';
document.body.insertBefore(div.lastChild, document.body.firstChild);
}
}());
window.onload = function() {
var sibling = document.getElementsByTagName('script')[0],
script = document.createElement('script');
document.getElementById('FirebugUI').style.height = '100%';
script.src = 'perf.js';
sibling.parentNode.insertBefore(script, sibling);
};
</script>
</body>
</html>

382
perf/perf.js Normal file
View File

@@ -0,0 +1,382 @@
(function(window) {
/** Use a single load function */
var load = typeof require == 'function' ? require : window.load;
/** Load Benchmark.js */
var Benchmark =
window.Benchmark || (
Benchmark = load('../vendor/benchmark.js/benchmark.js') || window.Benchmark,
Benchmark.Benchmark || Benchmark
);
/** Load Lo-Dash */
var lodash =
window.lodash || (
lodash = load('../lodash.js') || window._,
lodash = lodash._ || lodash,
lodash.noConflict()
);
/** Load Underscore */
var _ =
window._ || (
_ = load('../vendor/underscore/underscore.js') || window._,
_._ || _
);
/** Used to score Lo-Dash and Underscore performance */
var score = { 'lodash': 0, 'underscore': 0 };
/** Used to queue benchmark suites */
var suites = [];
/** Add `console.log()` support for Narwhal and RingoJS */
window.console || (window.console = { 'log': window.print });
/** Expose functions to the global object */
window._ = _;
window.Benchmark = Benchmark;
window.lodash = lodash;
/*--------------------------------------------------------------------------*/
lodash.extend(Benchmark.options, {
'async': true,
'setup': function() {
var window = Function('return this || global')(),
_ = window._,
lodash = window.lodash;
var numbers = [],
object = {},
fourNumbers = [5, 25, 10, 30],
nestedNumbers = [1, [2], [3, [[4]]]],
twoNumbers = [12, 21],
words = [
'one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight', 'nine',
'ten', 'eleven', 'twelve', 'thirteen', 'fourteen', 'fifteen', 'sixteen',
'seventeen', 'eighteen', 'nineteen', 'twenty'
];
var ctor = function() { },
func = function(greeting) { return greeting + ': ' + this.name; };
var lodashBoundNormal = lodash.bind(func, { 'name': 'moe' }),
lodashBoundCtor = lodash.bind(ctor, { 'name': 'moe' }),
lodashBoundPartial = lodash.bind(func, { 'name': 'moe' }, 'hi');
var _boundNormal = _.bind(func, { 'name': 'moe' }),
_boundCtor = _.bind(ctor, { 'name': 'moe' }),
_boundPartial = _.bind(func, { 'name': 'moe' }, 'hi');
for (var index = 0; index < 20; index++) {
numbers[index] = index;
object['key' + index] = index;
}
var objects = lodash.map(numbers, function(n) {
return { 'num': n };
});
}
});
lodash.extend(Benchmark.Suite.options, {
'onStart': function() {
console.log('\n' + this.name + ':');
},
'onCycle': function(event) {
console.log(event.target + '');
},
'onComplete': function() {
var fastest = this.filter('fastest'),
slowest = this.filter('slowest'),
lodashHz = 1 / (this[0].stats.mean + this[0].stats.moe),
underscoreHz = 1 / (this[1].stats.mean + this[1].stats.moe);
if (fastest.length > 1) {
console.log('It\'s too close to call.');
lodashHz = underscoreHz = Math.min(lodashHz, underscoreHz);
}
else {
var slowestHz = slowest[0] == this[0] ? lodashHz : underscoreHz,
fastestHz = fastest[0] == this[0] ? lodashHz : underscoreHz,
percent = Math.round(((fastestHz / slowestHz) - 1) * 100);
console.log(fastest[0].name + ' is ' + percent + '% faster.');
}
// add score adjusted for margin of error
score.lodash += lodashHz;
score.underscore += underscoreHz;
// remove current suite from queue
suites.shift();
if (suites.length) {
// run next suite
suites[0].run();
}
else {
// report results
if (score.lodash >= score.underscore) {
console.log('\nLo-Dash is ' + (score.lodash / score.underscore).toFixed(2) + 'x faster than Underscore.');
} else {
console.log('\nUnderscore is ' + (score.underscore / score.lodash).toFixed(2) + 'x faster than Lo-Dash.');
}
}
}
});
/*--------------------------------------------------------------------------*/
suites.push(
Benchmark.Suite('bind call')
.add('Lo-Dash', function() {
lodash.bind(func, { 'name': 'moe' }, 'hi');
})
.add('Underscore', function() {
_.bind(func, { 'name': 'moe' }, 'hi');
})
);
suites.push(
Benchmark.Suite('bound normal')
.add('Lo-Dash', function() {
lodashBoundNormal();
})
.add('Underscore', function() {
_boundNormal();
})
);
suites.push(
Benchmark.Suite('bound partial')
.add('Lo-Dash', function() {
lodashBoundPartial();
})
.add('Underscore', function() {
_boundPartial();
})
);
suites.push(
Benchmark.Suite('bound constructor')
.add('Lo-Dash', function() {
new lodashBoundCtor();
})
.add('Underscore', function() {
new _boundCtor();
})
);
/*--------------------------------------------------------------------------*/
suites.push(
Benchmark.Suite('each array')
.add('Lo-Dash', function() {
var timesTwo = [];
lodash.each(numbers, function(num) {
timesTwo.push(num * 2);
});
})
.add('Underscore', function() {
var timesTwo = [];
_.each(numbers, function(num) {
timesTwo.push(num * 2);
});
})
);
suites.push(
Benchmark.Suite('each object')
.add('Lo-Dash', function() {
var timesTwo = [];
lodash.each(object, function(num) {
timesTwo.push(num * 2);
});
})
.add('Underscore', function() {
var timesTwo = [];
_.each(object, function(num) {
timesTwo.push(num * 2);
});
})
);
/*--------------------------------------------------------------------------*/
suites.push(
Benchmark.Suite('flatten deep')
.add('Lo-Dash', function() {
lodash.flatten(nestedNumbers);
})
.add('Underscore', function() {
_.flatten(nestedNumbers);
})
);
suites.push(
Benchmark.Suite('flatten shallow')
.add('Lo-Dash', function() {
lodash.flatten(nestedNumbers, true);
})
.add('Underscore', function() {
_.flatten(nestedNumbers, true);
})
);
/*--------------------------------------------------------------------------*/
suites.push(
Benchmark.Suite('difference')
.add('Lo-Dash', function() {
lodash.difference(numbers, fourNumbers);
})
.add('Underscore', function() {
_.difference(numbers, fourNumbers);
})
);
/*--------------------------------------------------------------------------*/
suites.push(
Benchmark.Suite('groupBy callback')
.add('Lo-Dash', function() {
lodash.groupBy(numbers, function(num) { return Math.floor(num); });
})
.add('Underscore', function() {
_.groupBy(numbers, function(num) { return Math.floor(num); });
})
);
suites.push(
Benchmark.Suite('groupBy property name')
.add('Lo-Dash', function() {
lodash.groupBy(words, 'length');
})
.add('Underscore', function() {
_.groupBy(words, 'length');
})
);
/*--------------------------------------------------------------------------*/
suites.push(
Benchmark.Suite('intersection')
.add('Lo-Dash', function() {
lodash.intersection(numbers, fourNumbers, twoNumbers);
})
.add('Underscore', function() {
_.intersection(numbers, fourNumbers, twoNumbers);
})
);
/*--------------------------------------------------------------------------*/
suites.push(
Benchmark.Suite('keys')
.add('Lo-Dash', function() {
lodash.keys(object);
})
.add('Underscore', function() {
_.keys(object);
})
);
/*--------------------------------------------------------------------------*/
suites.push(
Benchmark.Suite('map')
.add('Lo-Dash', function() {
lodash.map(objects, function(obj) {
return obj.num;
});
})
.add('Underscore', function() {
_.map(objects, function(obj) {
return obj.num;
});
})
);
/*--------------------------------------------------------------------------*/
suites.push(
Benchmark.Suite('max')
.add('Lo-Dash', function() {
lodash.max(numbers);
})
.add('Underscore', function() {
_.max(numbers);
})
);
/*--------------------------------------------------------------------------*/
suites.push(
Benchmark.Suite('min')
.add('Lo-Dash', function() {
lodash.min(numbers);
})
.add('Underscore', function() {
_.min(numbers);
})
);
/*--------------------------------------------------------------------------*/
suites.push(
Benchmark.Suite('pick')
.add('Lo-Dash', function() {
lodash.pick(object, 'key6', 'key13');
})
.add('Underscore', function() {
_.pick(object, 'key6', 'key13');
})
);
/*--------------------------------------------------------------------------*/
suites.push(
Benchmark.Suite('pluck')
.add('Lo-Dash', function() {
lodash.pluck(objects, 'num');
})
.add('Underscore', function() {
_.pluck(objects, 'num');
})
);
/*--------------------------------------------------------------------------*/
suites.push(
Benchmark.Suite('union')
.add('Lo-Dash', function() {
lodash.union(numbers, fourNumbers, twoNumbers);
})
.add('Underscore', function() {
_.union(numbers, fourNumbers, twoNumbers);
})
);
/*--------------------------------------------------------------------------*/
suites.push(
Benchmark.Suite('values')
.add('Lo-Dash', function() {
lodash.values(objects);
})
.add('Underscore', function() {
_.values(objects);
})
);
/*--------------------------------------------------------------------------*/
if (Benchmark.platform + '') {
console.log(Benchmark.platform + '');
}
// start suites
suites[0].run();
}(typeof global == 'object' && global || this));

9
perf/run-perf.sh Executable file
View File

@@ -0,0 +1,9 @@
cd "$(dirname "$0")"
for cmd in node narwhal ringo rhino; do
echo ""
echo "Running performance suite in $cmd..."
$cmd perf.js
done
echo ""
echo "Running performance suite in a browser..."
open index.html

39
test/backbone.html Normal file
View File

@@ -0,0 +1,39 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Backbone Test Suite</title>
<link rel="stylesheet" href="../vendor/backbone/test/vendor/qunit.css">
<style>
body > #qunit-header {
display: none;
}
#jslitmus {
display: none;
}
</style>
</head>
<body>
<div id="qunit"></div>
<h1 id="qunit-header"><a href="#">Backbone Speed Suite</a></h1>
<div id="qunit-fixture">
<div id='testElement'>
<h1>Test</h1>
</div>
</div>
<script src="../vendor/backbone/test/vendor/json2.js"></script>
<script src="../vendor/backbone/test/vendor/jquery-1.7.1.js"></script>
<script src="../vendor/backbone/test/vendor/qunit.js"></script>
<script src="../vendor/backbone/test/vendor/jslitmus.js"></script>
<script src="../lodash.js"></script>
<script src="../vendor/backbone/backbone.js"></script>
<script src="../vendor/backbone/test/noconflict.js"></script>
<script src="../vendor/backbone/test/events.js"></script>
<script src="../vendor/backbone/test/model.js"></script>
<script src="../vendor/backbone/test/collection.js"></script>
<script src="../vendor/backbone/test/router.js"></script>
<script src="../vendor/backbone/test/view.js"></script>
<script src="../vendor/backbone/test/sync.js"></script>
<script src="../vendor/backbone/test/setdomlibrary.js"></script>
</body>
</html>

View File

@@ -6,13 +6,22 @@
<link rel="stylesheet" href="../vendor/qunit/qunit/qunit.css">
</head>
<body>
<h1 id="qunit-header">Lo-Dash Test Suite</h1>
<h2 id="qunit-banner"></h2>
<div id="qunit-testrunner-toolbar"></div>
<h2 id="qunit-userAgent"></h2>
<ol id="qunit-tests"></ol>
<div id="qunit"></div>
<script src="../vendor/qunit/qunit/qunit.js"></script>
<script>var _2, _ = 1;</script>
<script>
var _2,
_3 = Object.keys;
Object.keys = function() { return []; };
</script>
<script src="../lodash.js"></script>
<script>
var lodashBadKeys = _,
_ = 1;
Object.keys = _3;
_3 = void 0;
</script>
<script src="../lodash.js"></script>
<script src="../vendor/requirejs/require.js"></script>
<script>
@@ -21,16 +30,21 @@
document.write('<script src="test.js"><\/script>');
}
else {
define.amd.lodash = true;
require({
'baseUrl': '../vendor/requirejs/',
'urlArgs': 't=' + (+new Date),
'paths': {
'lodash': '../../lodash'
'lodash': '../../lodash',
'underscore': './../../lodash'
}
},
['lodash'], function(_) {
_2 = _.noConflict();
['lodash', 'underscore'], function(lodash, lodashAsUnderscore) {
_2 = lodash.noConflict();
_2.moduleName = 'lodash';
_3 = lodashAsUnderscore.noConflict();
_3.moduleName = 'underscore';
require(['test.js']);
});
}

View File

@@ -1,7 +1,9 @@
cd "$(dirname "$0")"
for cmd in rhino ringo narwhal node; do
echo ""
echo "Testing in $cmd..."
$cmd test.js
done
echo ""
echo "Testing in a browser..."
open index.html

View File

@@ -26,6 +26,17 @@
/** Used to resolve a value's internal [[Class]] */
var toString = {}.toString;
/** Used to check problem JScript properties (a.k.a. the [[DontEnum]] bug) */
var shadowed = {
'constructor': 1,
'hasOwnProperty': 2,
'isPrototypeOf': 3,
'propertyIsEnumerable': 4,
'toLocaleString': 5,
'toString': 6,
'valueOf': 7
};
/*--------------------------------------------------------------------------*/
/**
@@ -42,18 +53,34 @@
/*--------------------------------------------------------------------------*/
// must explicitly use `QUnit.module` instead of `module()`
// explicitly call `QUnit.module()` instead of `module()`
// in case we are in a CLI environment
QUnit.module('lodash');
(function() {
test('supports loading lodash.js as a module', function() {
test('supports loading lodash.js as the "lodash" module', function() {
if (window.document && window.require) {
equal((_2 || {}).VERSION, _.VERSION);
equal((_2 || {}).moduleName, 'lodash');
} else {
skipTest(1)
}
});
test('supports loading lodash.js as the "underscore" module', function() {
if (window.document && window.require) {
equal((_3 || {}).moduleName, 'underscore');
} else {
skipTest(1)
}
});
test('avoids overwritten native methods', function() {
if (window.lodashBadKeys) {
notDeepEqual(lodashBadKeys.keys({ 'a': 1 }), []);
} else {
skipTest(1);
}
});
}());
/*--------------------------------------------------------------------------*/
@@ -64,6 +91,106 @@
test('creates a new instance when called without the `new` operator', function() {
ok(_() instanceof _);
});
test('should pass through LoDash instances', function() {
var wrapped = _([]);
equal(_(wrapped), wrapped);
});
}());
/*--------------------------------------------------------------------------*/
QUnit.module('lodash.bind');
(function() {
test('supports lazy bind', function() {
var object = {
'name': 'moe',
'greet': function(greeting) {
return greeting + ': ' + this.name;
}
};
var func = _.bind(object, 'greet', 'hi');
equal(func(), 'hi: moe');
object.greet = function(greeting) {
return greeting + ' ' + this.name + '!';
};
equal(func(), 'hi moe!');
});
}());
/*--------------------------------------------------------------------------*/
QUnit.module('lodash.debounce');
(function() {
test('subsequent "immediate" debounced calls should return the result of the first call', function() {
var debounced = _.debounce(function(value) { return value; }, 100, true),
result = [debounced('x'), debounced('y')];
deepEqual(result, ['x', 'x']);
});
}());
/*--------------------------------------------------------------------------*/
QUnit.module('lodash.escape');
(function() {
test('should not escape the ">" character', function() {
equal(_.escape('>'), '>');
});
}());
/*--------------------------------------------------------------------------*/
QUnit.module('lodash.extend');
(function() {
test('should not error on `null` or `undefined` sources (test in IE < 9)', function() {
try {
deepEqual(_.extend({}, null, undefined, { 'a': 1 }), { 'a': 1 });
} catch(e) {
ok(false);
}
});
test('skips the prototype property of functions (test in Firefox < 3.6, Opera > 9.50 - Opera < 11.60, and Safari < 5.1)', function() {
function Foo() {}
Foo.prototype.c = 3;
Foo.a = 1;
Foo.b = 2;
var expected = { 'a': 1, 'b': 2 };
deepEqual(_.extend({}, Foo), expected);
Foo.prototype = { 'c': 3 };
deepEqual(_.extend({}, Foo), expected);
});
}());
/*--------------------------------------------------------------------------*/
QUnit.module('lodash.flatten');
(function() {
test('should treat sparse arrays as dense', function() {
var array = [[1, 2, 3], Array(3)],
expected = [1, 2, 3],
actual1 = _.flatten(array),
actual2 = _.flatten(array, true);
expected.push(undefined, undefined, undefined);
deepEqual(actual1, expected);
ok('4' in actual1);
deepEqual(actual2, expected);
ok('4' in actual2);
});
}());
/*--------------------------------------------------------------------------*/
@@ -75,6 +202,38 @@
var collection = [1, 2, 3, 4];
equal(_.forEach(collection, Boolean), collection);
});
test('fixes the JScript [[DontEnum]] bug (test in IE < 9)', function() {
var object = {};
_.forEach(shadowed, function(value, key) {
object[key] = value;
});
deepEqual(object, shadowed);
});
}());
/*--------------------------------------------------------------------------*/
QUnit.module('lodash.groupBy');
(function() {
test('supports the `thisArg` argument', function() {
var actual = _.groupBy([1.3, 2.1, 2.4], function(num) {
return this.floor(num);
}, Math);
deepEqual(actual, { '1': [1.3], '2': [2.1, 2.4] });
});
test('should only add elements to own, not inherited, properties', function() {
var actual = _.groupBy([1.3, 2.1, 2.4], function(num) {
return Math.floor(num) > 1 ? 'hasOwnProperty' : 'constructor';
});
deepEqual(actual.constructor, [1.3]);
deepEqual(actual.hasOwnProperty, [2.1, 2.4]);
});
}());
/*--------------------------------------------------------------------------*/
@@ -90,6 +249,26 @@
/*--------------------------------------------------------------------------*/
QUnit.module('lodash.isEmpty');
(function() {
test('fixes the JScript [[DontEnum]] bug (test in IE < 9)', function() {
equal(_.isEmpty(shadowed), false);
});
}());
/*--------------------------------------------------------------------------*/
QUnit.module('lodash.isEqual');
(function() {
test('fixes the JScript [[DontEnum]] bug (test in IE < 9)', function() {
equal(_.isEqual(shadowed, {}), false);
});
}());
/*--------------------------------------------------------------------------*/
QUnit.module('lodash.isNaN');
(function() {
@@ -100,6 +279,63 @@
/*--------------------------------------------------------------------------*/
QUnit.module('lodash.keys');
(function() {
test('fixes the JScript [[DontEnum]] bug (test in IE < 9)', function() {
function Foo() {}
Foo.prototype.a = 1;
deepEqual(_.keys(Foo.prototype), ['a']);
deepEqual(_.keys(shadowed).sort(),
'constructor hasOwnProperty isPrototypeOf propertyIsEnumerable toLocaleString toString valueOf'.split(' '));
});
}());
/*--------------------------------------------------------------------------*/
QUnit.module('lodash.partial');
(function() {
test('partially applies an argument, without additional arguments', function() {
var arg = 'catnip',
func = function(x) { return x; };
equal(_.partial(func, arg)(), arg);
});
test('partially applies an argument, with additional arguments', function() {
var arg1 = 'catnip',
arg2 = 'cheese',
func = function(x, y) { return [x, y]; };
deepEqual(_.partial(func, arg1)(arg2), [arg1, arg2]);
});
test('works without partially applying arguments, without additional arguments', function() {
var func = function() { return arguments.length; };
equal(_.partial(func)(), 0);
});
test('works without partially applying arguments, with additional arguments', function() {
var arg = 'catnip',
func = function(x) { return x; };
equal(_.partial(func)(arg), arg);
});
test('should not alter the `this` binding of either function', function() {
var o = { 'cat': 'nip' },
func = function() { return this.cat; };
equal(_.partial(_.bind(func, o))(), o.cat);
equal(_.bind(_.partial(func), o)(), o.cat);
});
}());
/*--------------------------------------------------------------------------*/
QUnit.module('lodash.reduceRight');
(function() {
@@ -124,6 +360,68 @@
test('should detect the size of a string value', function() {
equal(_.size('abc'), 3);
});
test('fixes the JScript [[DontEnum]] bug (test in IE < 9)', function() {
equal(_.size(shadowed), 7);
});
}());
/*--------------------------------------------------------------------------*/
QUnit.module('lodash.sortBy');
(function() {
test('supports the `thisArg` argument', function() {
var actual = _.sortBy([1, 2, 3, 4], function(num) {
return this.sin(num);
}, Math);
deepEqual(actual, [4, 3, 1, 2]);
});
}());
/*--------------------------------------------------------------------------*/
QUnit.module('lodash.template');
(function() {
test('supports recursive calls', function() {
var compiled = _.template('<%= a %><% a = _.template(c, object) %><%= a %>'),
data = { 'a': 'A', 'b': 'B', 'c': '<%= b %>' };
equal(compiled(data), 'AB');
});
test('should not augment the `options` object', function() {
var options = {};
_.template('', null, options);
deepEqual(options, {});
});
}());
/*--------------------------------------------------------------------------*/
QUnit.module('lodash.throttle');
(function() {
test('subsequent calls should return the result of the first call', function() {
var throttled = _.throttle(function(value) { return value; }, 100),
result = [throttled('x'), throttled('y')];
deepEqual(result, ['x', 'x']);
});
test('supports calls in a loop', function() {
var counter = 0,
throttled = _.throttle(function() { counter++; }, 100),
start = new Date,
limit = 220;
while ((new Date - start) < limit) {
throttled();
}
ok(counter > 1);
});
}());
/*--------------------------------------------------------------------------*/
@@ -148,8 +446,35 @@
/*--------------------------------------------------------------------------*/
// explicitly call `QUnit.start()` in a CLI environment
if (!window.document) {
QUnit.start();
}
}(typeof global == 'object' && global || this));
QUnit.module('lodash(...).shift');
(function() {
test('should remove the value at index `0` when length is `0` (test in IE 8 compatibility mode)', function() {
var wrapped = _({ '0': 1, 'length': 1 });
wrapped.shift();
deepEqual(wrapped.keys(), ['length']);
equal(wrapped.first(), undefined);
});
}());
/*--------------------------------------------------------------------------*/
QUnit.module('lodash(...).splice');
(function() {
test('should remove the value at index `0` when length is `0` (test in IE < 9, and in compatibility mode for IE9)', function() {
var wrapped = _({ '0': 1, 'length': 1 });
wrapped.splice(0, 1);
deepEqual(wrapped.keys(), ['length']);
equal(wrapped.first(), undefined);
});
}());
/*--------------------------------------------------------------------------*/
// explicitly call `QUnit.start()` for Narwhal, Rhino, and RingoJS
QUnit.start();
}(typeof global == 'object' && global || this));

39
test/underscore.html Normal file
View File

@@ -0,0 +1,39 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Underscore Test Suite</title>
<link rel="stylesheet" href="../vendor/underscore/test/vendor/qunit.css">
<style>
#jslitmus, iframe {
display: none;
}
</style>
</head>
<body>
<div id="qunit"></div>
<div id="qunit-fixture">
<div id="map-test">
<div id="id1"></div>
<div id="id2"></div>
</div>
</div>
<script src="../vendor/backbone/test/vendor/json2.js"></script>
<script src="../vendor/underscore/test/vendor/jquery.js"></script>
<script src="../vendor/underscore/test/vendor/qunit.js"></script>
<script src="../vendor/underscore/test/vendor/jslitmus.js"></script>
<script src="../lodash.js"></script>
<script src="../vendor/underscore/test/collections.js"></script>
<script src="../vendor/underscore/test/arrays.js"></script>
<script src="../vendor/underscore/test/functions.js"></script>
<script src="../vendor/underscore/test/objects.js"></script>
<script src="../vendor/underscore/test/utility.js"></script>
<script src="../vendor/underscore/test/chaining.js"></script>
<script type="text/html" id="template">
<%
// a comment
if (data) { data += 12345; }; %>
<li><%= data %></li>
</script>
</body>
</html>

View File

@@ -1,190 +0,0 @@
$(document).ready(function() {
module("Arrays");
test("arrays: first", function() {
equal(_.first([1,2,3]), 1, 'can pull out the first element of an array');
equal(_([1, 2, 3]).first(), 1, 'can perform OO-style "first()"');
equal(_.first([1,2,3], 0).join(', '), "", 'can pass an index to first');
equal(_.first([1,2,3], 2).join(', '), '1, 2', 'can pass an index to first');
equal(_.first([1,2,3], 5).join(', '), '1, 2, 3', 'can pass an index to first');
var result = (function(){ return _.first(arguments); })(4, 3, 2, 1);
equal(result, 4, 'works on an arguments object.');
result = _.map([[1,2,3],[1,2,3]], _.first);
equal(result.join(','), '1,1', 'works well with _.map');
result = (function() { return _.take([1,2,3], 2); })();
equal(result.join(','), '1,2', 'aliased as take');
});
test("arrays: rest", function() {
var numbers = [1, 2, 3, 4];
equal(_.rest(numbers).join(", "), "2, 3, 4", 'working rest()');
equal(_.rest(numbers, 0).join(", "), "1, 2, 3, 4", 'working rest(0)');
equal(_.rest(numbers, 2).join(', '), '3, 4', 'rest can take an index');
var result = (function(){ return _(arguments).tail(); })(1, 2, 3, 4);
equal(result.join(', '), '2, 3, 4', 'aliased as tail and works on arguments object');
result = _.map([[1,2,3],[1,2,3]], _.rest);
equal(_.flatten(result).join(','), '2,3,2,3', 'works well with _.map');
});
test("arrays: initial", function() {
equal(_.initial([1,2,3,4,5]).join(", "), "1, 2, 3, 4", 'working initial()');
equal(_.initial([1,2,3,4],2).join(", "), "1, 2", 'initial can take an index');
var result = (function(){ return _(arguments).initial(); })(1, 2, 3, 4);
equal(result.join(", "), "1, 2, 3", 'initial works on arguments object');
result = _.map([[1,2,3],[1,2,3]], _.initial);
equal(_.flatten(result).join(','), '1,2,1,2', 'initial works with _.map');
});
test("arrays: last", function() {
equal(_.last([1,2,3]), 3, 'can pull out the last element of an array');
equal(_.last([1,2,3], 0).join(', '), "", 'can pass an index to last');
equal(_.last([1,2,3], 2).join(', '), '2, 3', 'can pass an index to last');
equal(_.last([1,2,3], 5).join(', '), '1, 2, 3', 'can pass an index to last');
var result = (function(){ return _(arguments).last(); })(1, 2, 3, 4);
equal(result, 4, 'works on an arguments object');
result = _.map([[1,2,3],[1,2,3]], _.last);
equal(result.join(','), '3,3', 'works well with _.map');
});
test("arrays: compact", function() {
equal(_.compact([0, 1, false, 2, false, 3]).length, 3, 'can trim out all falsy values');
var result = (function(){ return _(arguments).compact().length; })(0, 1, false, 2, false, 3);
equal(result, 3, 'works on an arguments object');
});
test("arrays: flatten", function() {
if (window.JSON) {
var list = [1, [2], [3, [[[4]]]]];
equal(JSON.stringify(_.flatten(list)), '[1,2,3,4]', 'can flatten nested arrays');
equal(JSON.stringify(_.flatten(list, true)), '[1,2,3,[[[4]]]]', 'can shallowly flatten nested arrays');
var result = (function(){ return _.flatten(arguments); })(1, [2], [3, [[[4]]]]);
equal(JSON.stringify(result), '[1,2,3,4]', 'works on an arguments object');
}
});
test("arrays: without", function() {
var list = [1, 2, 1, 0, 3, 1, 4];
equal(_.without(list, 0, 1).join(', '), '2, 3, 4', 'can remove all instances of an object');
var result = (function(){ return _.without(arguments, 0, 1); })(1, 2, 1, 0, 3, 1, 4);
equal(result.join(', '), '2, 3, 4', 'works on an arguments object');
var list = [{one : 1}, {two : 2}];
ok(_.without(list, {one : 1}).length == 2, 'uses real object identity for comparisons.');
ok(_.without(list, list[0]).length == 1, 'ditto.');
});
test("arrays: uniq", function() {
var list = [1, 2, 1, 3, 1, 4];
equal(_.uniq(list).join(', '), '1, 2, 3, 4', 'can find the unique values of an unsorted array');
var list = [1, 1, 1, 2, 2, 3];
equal(_.uniq(list, true).join(', '), '1, 2, 3', 'can find the unique values of a sorted array faster');
var list = [{name:'moe'}, {name:'curly'}, {name:'larry'}, {name:'curly'}];
var iterator = function(value) { return value.name; };
equal(_.map(_.uniq(list, false, iterator), iterator).join(', '), 'moe, curly, larry', 'can find the unique values of an array using a custom iterator');
var iterator = function(value) { return value +1; };
var list = [1, 2, 2, 3, 4, 4];
equal(_.uniq(list, true, iterator).join(', '), '1, 2, 3, 4', 'iterator works with sorted array');
var result = (function(){ return _.uniq(arguments); })(1, 2, 1, 3, 1, 4);
equal(result.join(', '), '1, 2, 3, 4', 'works on an arguments object');
var list = [];
list[2] = list[3] = null;
list[8] = 2;
list[10] = 2;
list[11] = 5;
list[14] = 5;
list[16] = 8;
list[19] = 8;
list[26] = list[29] = undefined;
list[33] = "hi";
var result = _.uniq(list, true);
if (0 in [undefined]) {
// According to the JScript ES 3 spec, section 2.1.26, JScript 5.x (IE <=
// 8) treats `undefined` elements in arrays as elisions.
deepEqual(result, [null, 2, 5, 8, undefined, "hi"], "Works with sorted sparse arrays");
equal(result.length, 6, "The resulting array should not be sparse");
} else {
deepEqual(result, [null, 2, 5, 8, "hi"], "Works with sorted sparse arrays where `undefined` elements are elided");
equal(result.length, 5, "The resulting array should not be sparse");
}
});
test("arrays: intersection", function() {
var stooges = ['moe', 'curly', 'larry'], leaders = ['moe', 'groucho'];
equal(_.intersection(stooges, leaders).join(''), 'moe', 'can take the set intersection of two arrays');
equal(_(stooges).intersection(leaders).join(''), 'moe', 'can perform an OO-style intersection');
var result = (function(){ return _.intersection(arguments, leaders); })('moe', 'curly', 'larry');
equal(result.join(''), 'moe', 'works on an arguments object');
});
test("arrays: union", function() {
var result = _.union([1, 2, 3], [2, 30, 1], [1, 40]);
equal(result.join(' '), '1 2 3 30 40', 'takes the union of a list of arrays');
var result = _.union([1, 2, 3], [2, 30, 1], [1, 40, [1]]);
equal(result.join(' '), '1 2 3 30 40 1', 'takes the union of a list of nested arrays');
});
test("arrays: difference", function() {
var result = _.difference([1, 2, 3], [2, 30, 40]);
equal(result.join(' '), '1 3', 'takes the difference of two arrays');
var result = _.difference([1, 2, 3, 4], [2, 30, 40], [1, 11, 111]);
equal(result.join(' '), '3 4', 'takes the difference of three arrays');
});
test('arrays: zip', function() {
var names = ['moe', 'larry', 'curly'], ages = [30, 40, 50], leaders = [true];
var stooges = _.zip(names, ages, leaders);
equal(String(stooges), 'moe,30,true,larry,40,,curly,50,', 'zipped together arrays of different lengths');
});
test("arrays: indexOf", function() {
var numbers = [1, 2, 3];
numbers.indexOf = null;
equal(_.indexOf(numbers, 2), 1, 'can compute indexOf, even without the native function');
var result = (function(){ return _.indexOf(arguments, 2); })(1, 2, 3);
equal(result, 1, 'works on an arguments object');
equal(_.indexOf(null, 2), -1, 'handles nulls properly');
var numbers = [10, 20, 30, 40, 50], num = 35;
var index = _.indexOf(numbers, num, true);
equal(index, -1, '35 is not in the list');
numbers = [10, 20, 30, 40, 50]; num = 40;
index = _.indexOf(numbers, num, true);
equal(index, 3, '40 is in the list');
numbers = [1, 40, 40, 40, 40, 40, 40, 40, 50, 60, 70]; num = 40;
index = _.indexOf(numbers, num, true);
equal(index, 1, '40 is in the list');
});
test("arrays: lastIndexOf", function() {
var numbers = [1, 0, 1, 0, 0, 1, 0, 0, 0];
numbers.lastIndexOf = null;
equal(_.lastIndexOf(numbers, 1), 5, 'can compute lastIndexOf, even without the native function');
equal(_.lastIndexOf(numbers, 0), 8, 'lastIndexOf the other element');
var result = (function(){ return _.lastIndexOf(arguments, 1); })(1, 0, 1, 0, 0, 1, 0, 0, 0);
equal(result, 5, 'works on an arguments object');
equal(_.indexOf(null, 2), -1, 'handles nulls properly');
});
test("arrays: range", function() {
equal(_.range(0).join(''), '', 'range with 0 as a first argument generates an empty array');
equal(_.range(4).join(' '), '0 1 2 3', 'range with a single positive argument generates an array of elements 0,1,2,...,n-1');
equal(_.range(5, 8).join(' '), '5 6 7', 'range with two arguments a &amp; b, a&lt;b generates an array of elements a,a+1,a+2,...,b-2,b-1');
equal(_.range(8, 5).join(''), '', 'range with two arguments a &amp; b, b&lt;a generates an empty array');
equal(_.range(3, 10, 3).join(' '), '3 6 9', 'range with three arguments a &amp; b &amp; c, c &lt; b-a, a &lt; b generates an array of elements a,a+c,a+2c,...,b - (multiplier of a) &lt; c');
equal(_.range(3, 10, 15).join(''), '3', 'range with three arguments a &amp; b &amp; c, c &gt; b-a, a &lt; b generates an array with a single element, equal to a');
equal(_.range(12, 7, -2).join(' '), '12 10 8', 'range with three arguments a &amp; b &amp; c, a &gt; b, c &lt; 0 generates an array of elements a,a-c,a-2c and ends with the number not less than b');
equal(_.range(0, -10, -1).join(' '), '0 -1 -2 -3 -4 -5 -6 -7 -8 -9', 'final example in the Python docs');
});
});

View File

@@ -1,59 +0,0 @@
$(document).ready(function() {
module("Chaining");
test("chaining: map/flatten/reduce", function() {
var lyrics = [
"I'm a lumberjack and I'm okay",
"I sleep all night and I work all day",
"He's a lumberjack and he's okay",
"He sleeps all night and he works all day"
];
var counts = _(lyrics).chain()
.map(function(line) { return line.split(''); })
.flatten()
.reduce(function(hash, l) {
hash[l] = hash[l] || 0;
hash[l]++;
return hash;
}, {}).value();
ok(counts['a'] == 16 && counts['e'] == 10, 'counted all the letters in the song');
});
test("chaining: select/reject/sortBy", function() {
var numbers = [1,2,3,4,5,6,7,8,9,10];
numbers = _(numbers).chain().select(function(n) {
return n % 2 == 0;
}).reject(function(n) {
return n % 4 == 0;
}).sortBy(function(n) {
return -n;
}).value();
equal(numbers.join(', '), "10, 6, 2", "filtered and reversed the numbers");
});
test("chaining: select/reject/sortBy in functional style", function() {
var numbers = [1,2,3,4,5,6,7,8,9,10];
numbers = _.chain(numbers).select(function(n) {
return n % 2 == 0;
}).reject(function(n) {
return n % 4 == 0;
}).sortBy(function(n) {
return -n;
}).value();
equal(numbers.join(', '), "10, 6, 2", "filtered and reversed the numbers");
});
test("chaining: reverse/concat/unshift/pop/map", function() {
var numbers = [1,2,3,4,5];
numbers = _(numbers).chain()
.reverse()
.concat([5, 5, 5])
.unshift(17)
.pop()
.map(function(n){ return n * 2; })
.value();
equal(numbers.join(', '), "34, 10, 8, 6, 4, 2, 10, 10", 'can chain together array functions.');
});
});

View File

@@ -1,299 +0,0 @@
$(document).ready(function() {
module("Collections");
test("collections: each", function() {
_.each([1, 2, 3], function(num, i) {
equal(num, i + 1, 'each iterators provide value and iteration count');
});
var answers = [];
_.each([1, 2, 3], function(num){ answers.push(num * this.multiplier);}, {multiplier : 5});
equal(answers.join(', '), '5, 10, 15', 'context object property accessed');
answers = [];
_.forEach([1, 2, 3], function(num){ answers.push(num); });
equal(answers.join(', '), '1, 2, 3', 'aliased as "forEach"');
answers = [];
var obj = {one : 1, two : 2, three : 3};
obj.constructor.prototype.four = 4;
_.each(obj, function(value, key){ answers.push(key); });
equal(answers.join(", "), 'one, two, three', 'iterating over objects works, and ignores the object prototype.');
delete obj.constructor.prototype.four;
answer = null;
_.each([1, 2, 3], function(num, index, arr){ if (_.include(arr, num)) answer = true; });
ok(answer, 'can reference the original collection from inside the iterator');
answers = 0;
_.each(null, function(){ ++answers; });
equal(answers, 0, 'handles a null properly');
});
test('collections: map', function() {
var doubled = _.map([1, 2, 3], function(num){ return num * 2; });
equal(doubled.join(', '), '2, 4, 6', 'doubled numbers');
doubled = _.collect([1, 2, 3], function(num){ return num * 2; });
equal(doubled.join(', '), '2, 4, 6', 'aliased as "collect"');
var tripled = _.map([1, 2, 3], function(num){ return num * this.multiplier; }, {multiplier : 3});
equal(tripled.join(', '), '3, 6, 9', 'tripled numbers with context');
var doubled = _([1, 2, 3]).map(function(num){ return num * 2; });
equal(doubled.join(', '), '2, 4, 6', 'OO-style doubled numbers');
var ids = _.map($('div.underscore-test').children(), function(n){ return n.id; });
ok(_.include(ids, 'qunit-header'), 'can use collection methods on NodeLists');
var ids = _.map(document.images, function(n){ return n.id; });
ok(ids[0] == 'chart_image', 'can use collection methods on HTMLCollections');
var ifnull = _.map(null, function(){});
ok(_.isArray(ifnull) && ifnull.length === 0, 'handles a null properly');
var length = _.map(Array(2), function(v) { return v; }).length;
equal(length, 2, "can preserve a sparse array's length");
});
test('collections: reduce', function() {
var sum = _.reduce([1, 2, 3], function(sum, num){ return sum + num; }, 0);
equal(sum, 6, 'can sum up an array');
var context = {multiplier : 3};
sum = _.reduce([1, 2, 3], function(sum, num){ return sum + num * this.multiplier; }, 0, context);
equal(sum, 18, 'can reduce with a context object');
sum = _.inject([1, 2, 3], function(sum, num){ return sum + num; }, 0);
equal(sum, 6, 'aliased as "inject"');
sum = _([1, 2, 3]).reduce(function(sum, num){ return sum + num; }, 0);
equal(sum, 6, 'OO-style reduce');
var sum = _.reduce([1, 2, 3], function(sum, num){ return sum + num; });
equal(sum, 6, 'default initial value');
var ifnull;
try {
_.reduce(null, function(){});
} catch (ex) {
ifnull = ex;
}
ok(ifnull instanceof TypeError, 'handles a null (without inital value) properly');
ok(_.reduce(null, function(){}, 138) === 138, 'handles a null (with initial value) properly');
equal(_.reduce([], function(){}, undefined), undefined, 'undefined can be passed as a special case');
raises(function() { _.reduce([], function(){}); }, TypeError, 'throws an error for empty arrays with no initial value');
var sparseArray = [];
sparseArray[0] = 20;
sparseArray[2] = -5;
equal(_.reduce(sparseArray, function(a, b){ return a - b; }), 25, 'initially-sparse arrays with no memo');
});
test('collections: reduceRight', function() {
var list = _.reduceRight(["foo", "bar", "baz"], function(memo, str){ return memo + str; }, '');
equal(list, 'bazbarfoo', 'can perform right folds');
var list = _.foldr(["foo", "bar", "baz"], function(memo, str){ return memo + str; }, '');
equal(list, 'bazbarfoo', 'aliased as "foldr"');
var list = _.foldr(["foo", "bar", "baz"], function(memo, str){ return memo + str; });
equal(list, 'bazbarfoo', 'default initial value');
var ifnull;
try {
_.reduceRight(null, function(){});
} catch (ex) {
ifnull = ex;
}
ok(ifnull instanceof TypeError, 'handles a null (without inital value) properly');
ok(_.reduceRight(null, function(){}, 138) === 138, 'handles a null (with initial value) properly');
equal(_.reduceRight([], function(){}, undefined), undefined, 'undefined can be passed as a special case');
raises(function() { _.reduceRight([], function(){}); }, TypeError, 'throws an error for empty arrays with no initial value');
var sparseArray = [];
sparseArray[0] = 20;
sparseArray[2] = -5;
equal(_.reduceRight(sparseArray, function(a, b){ return a - b; }), -25, 'initially-sparse arrays with no memo');
});
test('collections: detect', function() {
var result = _.detect([1, 2, 3], function(num){ return num * 2 == 4; });
equal(result, 2, 'found the first "2" and broke the loop');
});
test('collections: select', function() {
var evens = _.select([1, 2, 3, 4, 5, 6], function(num){ return num % 2 == 0; });
equal(evens.join(', '), '2, 4, 6', 'selected each even number');
evens = _.filter([1, 2, 3, 4, 5, 6], function(num){ return num % 2 == 0; });
equal(evens.join(', '), '2, 4, 6', 'aliased as "filter"');
});
test('collections: reject', function() {
var odds = _.reject([1, 2, 3, 4, 5, 6], function(num){ return num % 2 == 0; });
equal(odds.join(', '), '1, 3, 5', 'rejected each even number');
});
test('collections: all', function() {
ok(_.all([], _.identity), 'the empty set');
ok(_.all([true, true, true], _.identity), 'all true values');
ok(!_.all([true, false, true], _.identity), 'one false value');
ok(_.all([0, 10, 28], function(num){ return num % 2 == 0; }), 'even numbers');
ok(!_.all([0, 11, 28], function(num){ return num % 2 == 0; }), 'an odd number');
ok(_.all([1], _.identity) === true, 'cast to boolean - true');
ok(_.all([0], _.identity) === false, 'cast to boolean - false');
ok(_.every([true, true, true], _.identity), 'aliased as "every"');
});
test('collections: any', function() {
var nativeSome = Array.prototype.some;
Array.prototype.some = null;
ok(!_.any([]), 'the empty set');
ok(!_.any([false, false, false]), 'all false values');
ok(_.any([false, false, true]), 'one true value');
ok(_.any([null, 0, 'yes', false]), 'a string');
ok(!_.any([null, 0, '', false]), 'falsy values');
ok(!_.any([1, 11, 29], function(num){ return num % 2 == 0; }), 'all odd numbers');
ok(_.any([1, 10, 29], function(num){ return num % 2 == 0; }), 'an even number');
ok(_.any([1], _.identity) === true, 'cast to boolean - true');
ok(_.any([0], _.identity) === false, 'cast to boolean - false');
ok(_.some([false, false, true]), 'aliased as "some"');
Array.prototype.some = nativeSome;
});
test('collections: include', function() {
ok(_.include([1,2,3], 2), 'two is in the array');
ok(!_.include([1,3,9], 2), 'two is not in the array');
ok(_.contains({moe:1, larry:3, curly:9}, 3) === true, '_.include on objects checks their values');
ok(_([1,2,3]).include(2), 'OO-style include');
});
test('collections: invoke', function() {
var list = [[5, 1, 7], [3, 2, 1]];
var result = _.invoke(list, 'sort');
equal(result[0].join(', '), '1, 5, 7', 'first array sorted');
equal(result[1].join(', '), '1, 2, 3', 'second array sorted');
});
test('collections: invoke w/ function reference', function() {
var list = [[5, 1, 7], [3, 2, 1]];
var result = _.invoke(list, Array.prototype.sort);
equal(result[0].join(', '), '1, 5, 7', 'first array sorted');
equal(result[1].join(', '), '1, 2, 3', 'second array sorted');
});
// Relevant when using ClojureScript
test('collections: invoke when strings have a call method', function() {
String.prototype.call = function() {
return 42;
};
var list = [[5, 1, 7], [3, 2, 1]];
var s = "foo";
equal(s.call(), 42, "call function exists");
var result = _.invoke(list, 'sort');
equal(result[0].join(', '), '1, 5, 7', 'first array sorted');
equal(result[1].join(', '), '1, 2, 3', 'second array sorted');
delete String.prototype.call;
equal(s.call, undefined, "call function removed");
});
test('collections: pluck', function() {
var people = [{name : 'moe', age : 30}, {name : 'curly', age : 50}];
equal(_.pluck(people, 'name').join(', '), 'moe, curly', 'pulls names out of objects');
});
test('collections: max', function() {
equal(3, _.max([1, 2, 3]), 'can perform a regular Math.max');
var neg = _.max([1, 2, 3], function(num){ return -num; });
equal(neg, 1, 'can perform a computation-based max');
equal(-Infinity, _.max({}), 'Maximum value of an empty object');
equal(-Infinity, _.max([]), 'Maximum value of an empty array');
});
test('collections: min', function() {
equal(1, _.min([1, 2, 3]), 'can perform a regular Math.min');
var neg = _.min([1, 2, 3], function(num){ return -num; });
equal(neg, 3, 'can perform a computation-based min');
equal(Infinity, _.min({}), 'Minimum value of an empty object');
equal(Infinity, _.min([]), 'Minimum value of an empty array');
var now = new Date(9999999999);
var then = new Date(0);
equal(_.min([now, then]), then);
});
test('collections: sortBy', function() {
var people = [{name : 'curly', age : 50}, {name : 'moe', age : 30}];
people = _.sortBy(people, function(person){ return person.age; });
equal(_.pluck(people, 'name').join(', '), 'moe, curly', 'stooges sorted by age');
var list = [undefined, 4, 1, undefined, 3, 2];
equal(_.sortBy(list, _.identity).join(','), '1,2,3,4,,', 'sortBy with undefined values');
var list = ["one", "two", "three", "four", "five"];
var sorted = _.sortBy(list, 'length');
equal(sorted.join(' '), 'one two four five three', 'sorted by length');
});
test('collections: groupBy', function() {
var parity = _.groupBy([1, 2, 3, 4, 5, 6], function(num){ return num % 2; });
ok('0' in parity && '1' in parity, 'created a group for each value');
equal(parity[0].join(', '), '2, 4, 6', 'put each even number in the right group');
var list = ["one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "ten"];
var grouped = _.groupBy(list, 'length');
equal(grouped['3'].join(' '), 'one two six ten');
equal(grouped['4'].join(' '), 'four five nine');
equal(grouped['5'].join(' '), 'three seven eight');
});
test('collections: sortedIndex', function() {
var numbers = [10, 20, 30, 40, 50], num = 35;
var indexForNum = _.sortedIndex(numbers, num);
equal(indexForNum, 3, '35 should be inserted at index 3');
var indexFor30 = _.sortedIndex(numbers, 30);
equal(indexFor30, 2, '30 should be inserted at index 2');
});
test('collections: shuffle', function() {
var numbers = _.range(10);
var shuffled = _.shuffle(numbers).sort();
notStrictEqual(numbers, shuffled, 'original object is unmodified');
equal(shuffled.join(','), numbers.join(','), 'contains the same members before and after shuffle');
});
test('collections: toArray', function() {
ok(!_.isArray(arguments), 'arguments object is not an array');
ok(_.isArray(_.toArray(arguments)), 'arguments object converted into array');
var a = [1,2,3];
ok(_.toArray(a) !== a, 'array is cloned');
equal(_.toArray(a).join(', '), '1, 2, 3', 'cloned array contains same elements');
var numbers = _.toArray({one : 1, two : 2, three : 3});
equal(numbers.join(', '), '1, 2, 3', 'object flattened into array');
var objectWithToArrayFunction = {toArray: function() {
return [1, 2, 3];
}};
equal(_.toArray(objectWithToArrayFunction).join(', '), '1, 2, 3', 'toArray method used if present');
var objectWithToArrayValue = {toArray: 1};
equal(_.toArray(objectWithToArrayValue).join(', '), '1', 'toArray property ignored if not a function');
});
test('collections: size', function() {
equal(_.size({one : 1, two : 2, three : 3}), 3, 'can compute the size of an object');
equal(_.size([1, 2, 3]), 3, 'can compute the size of an array');
});
});

View File

@@ -1,215 +0,0 @@
$(document).ready(function() {
module("Functions");
test("functions: bind", function() {
var context = {name : 'moe'};
var func = function(arg) { return "name: " + (this.name || arg); };
var bound = _.bind(func, context);
equal(bound(), 'name: moe', 'can bind a function to a context');
bound = _(func).bind(context);
equal(bound(), 'name: moe', 'can do OO-style binding');
bound = _.bind(func, null, 'curly');
equal(bound(), 'name: curly', 'can bind without specifying a context');
func = function(salutation, name) { return salutation + ': ' + name; };
func = _.bind(func, this, 'hello');
equal(func('moe'), 'hello: moe', 'the function was partially applied in advance');
var func = _.bind(func, this, 'curly');
equal(func(), 'hello: curly', 'the function was completely applied in advance');
var func = function(salutation, firstname, lastname) { return salutation + ': ' + firstname + ' ' + lastname; };
func = _.bind(func, this, 'hello', 'moe', 'curly');
equal(func(), 'hello: moe curly', 'the function was partially applied in advance and can accept multiple arguments');
func = function(context, message) { equal(this, context, message); };
_.bind(func, 0, 0, 'can bind a function to `0`')();
_.bind(func, '', '', 'can bind a function to an empty string')();
_.bind(func, false, false, 'can bind a function to `false`')();
// These tests are only meaningful when using a browser without a native bind function
// To test this with a modern browser, set underscore's nativeBind to undefined
var F = function () { return this; };
var Boundf = _.bind(F, {hello: "moe curly"});
equal(new Boundf().hello, undefined, "function should not be bound to the context, to comply with ECMAScript 5");
equal(Boundf().hello, "moe curly", "When called without the new operator, it's OK to be bound to the context");
});
test("functions: bindAll", function() {
var curly = {name : 'curly'}, moe = {
name : 'moe',
getName : function() { return 'name: ' + this.name; },
sayHi : function() { return 'hi: ' + this.name; }
};
curly.getName = moe.getName;
_.bindAll(moe, 'getName', 'sayHi');
curly.sayHi = moe.sayHi;
equal(curly.getName(), 'name: curly', 'unbound function is bound to current object');
equal(curly.sayHi(), 'hi: moe', 'bound function is still bound to original object');
curly = {name : 'curly'};
moe = {
name : 'moe',
getName : function() { return 'name: ' + this.name; },
sayHi : function() { return 'hi: ' + this.name; }
};
_.bindAll(moe);
curly.sayHi = moe.sayHi;
equal(curly.sayHi(), 'hi: moe', 'calling bindAll with no arguments binds all functions to the object');
});
test("functions: memoize", function() {
var fib = function(n) {
return n < 2 ? n : fib(n - 1) + fib(n - 2);
};
var fastFib = _.memoize(fib);
equal(fib(10), 55, 'a memoized version of fibonacci produces identical results');
equal(fastFib(10), 55, 'a memoized version of fibonacci produces identical results');
var o = function(str) {
return str;
};
var fastO = _.memoize(o);
equal(o('toString'), 'toString', 'checks hasOwnProperty');
equal(fastO('toString'), 'toString', 'checks hasOwnProperty');
});
asyncTest("functions: delay", 2, function() {
var delayed = false;
_.delay(function(){ delayed = true; }, 100);
setTimeout(function(){ ok(!delayed, "didn't delay the function quite yet"); }, 50);
setTimeout(function(){ ok(delayed, 'delayed the function'); start(); }, 150);
});
asyncTest("functions: defer", 1, function() {
var deferred = false;
_.defer(function(bool){ deferred = bool; }, true);
_.delay(function(){ ok(deferred, "deferred the function"); start(); }, 50);
});
asyncTest("functions: throttle", 2, function() {
var counter = 0;
var incr = function(){ counter++; };
var throttledIncr = _.throttle(incr, 100);
throttledIncr(); throttledIncr(); throttledIncr();
setTimeout(throttledIncr, 70);
setTimeout(throttledIncr, 120);
setTimeout(throttledIncr, 140);
setTimeout(throttledIncr, 190);
setTimeout(throttledIncr, 220);
setTimeout(throttledIncr, 240);
_.delay(function(){ equal(counter, 1, "incr was called immediately"); }, 30);
_.delay(function(){ equal(counter, 4, "incr was throttled"); start(); }, 400);
});
asyncTest("functions: throttle arguments", 2, function() {
var value = 0;
var update = function(val){ value = val; };
var throttledUpdate = _.throttle(update, 100);
throttledUpdate(1); throttledUpdate(2); throttledUpdate(3);
setTimeout(function(){ throttledUpdate(4); }, 120);
setTimeout(function(){ throttledUpdate(5); }, 140);
setTimeout(function(){ throttledUpdate(6); }, 250);
_.delay(function(){ equal(value, 1, "updated to latest value"); }, 40);
_.delay(function(){ equal(value, 6, "updated to latest value"); start(); }, 400);
});
asyncTest("functions: throttle once", 2, function() {
var counter = 0;
var incr = function(){ return ++counter; };
var throttledIncr = _.throttle(incr, 100);
var result = throttledIncr();
_.delay(function(){
equal(result, 1, "throttled functions return their value");
equal(counter, 1, "incr was called once"); start();
}, 220);
});
asyncTest("functions: throttle twice", 1, function() {
var counter = 0;
var incr = function(){ counter++; };
var throttledIncr = _.throttle(incr, 100);
throttledIncr(); throttledIncr();
_.delay(function(){ equal(counter, 2, "incr was called twice"); start(); }, 220);
});
asyncTest("functions: debounce", 1, function() {
var counter = 0;
var incr = function(){ counter++; };
var debouncedIncr = _.debounce(incr, 50);
debouncedIncr(); debouncedIncr(); debouncedIncr();
setTimeout(debouncedIncr, 30);
setTimeout(debouncedIncr, 60);
setTimeout(debouncedIncr, 90);
setTimeout(debouncedIncr, 120);
setTimeout(debouncedIncr, 150);
_.delay(function(){ equal(counter, 1, "incr was debounced"); start(); }, 220);
});
asyncTest("functions: debounce asap", 2, function() {
var counter = 0;
var incr = function(){ counter++; };
var debouncedIncr = _.debounce(incr, 50, true);
debouncedIncr(); debouncedIncr(); debouncedIncr();
equal(counter, 1, 'incr was called immediately');
setTimeout(debouncedIncr, 30);
setTimeout(debouncedIncr, 60);
setTimeout(debouncedIncr, 90);
setTimeout(debouncedIncr, 120);
setTimeout(debouncedIncr, 150);
_.delay(function(){ equal(counter, 1, "incr was debounced"); start(); }, 220);
});
test("functions: once", function() {
var num = 0;
var increment = _.once(function(){ num++; });
increment();
increment();
equal(num, 1);
});
test("functions: wrap", function() {
var greet = function(name){ return "hi: " + name; };
var backwards = _.wrap(greet, function(func, name){ return func(name) + ' ' + name.split('').reverse().join(''); });
equal(backwards('moe'), 'hi: moe eom', 'wrapped the saluation function');
var inner = function(){ return "Hello "; };
var obj = {name : "Moe"};
obj.hi = _.wrap(inner, function(fn){ return fn() + this.name; });
equal(obj.hi(), "Hello Moe");
var noop = function(){};
var wrapped = _.wrap(noop, function(fn){ return Array.prototype.slice.call(arguments, 0); });
var ret = wrapped(['whats', 'your'], 'vector', 'victor');
same(ret, [noop, ['whats', 'your'], 'vector', 'victor']);
});
test("functions: compose", function() {
var greet = function(name){ return "hi: " + name; };
var exclaim = function(sentence){ return sentence + '!'; };
var composed = _.compose(exclaim, greet);
equal(composed('moe'), 'hi: moe!', 'can compose a function that takes another');
composed = _.compose(greet, exclaim);
equal(composed('moe'), 'hi: moe!', 'in this case, the functions are also commutative');
});
test("functions: after", function() {
var testAfter = function(afterAmount, timesCalled) {
var afterCalled = 0;
var after = _.after(afterAmount, function() {
afterCalled++;
});
while (timesCalled--) after();
return afterCalled;
};
equal(testAfter(5, 5), 1, "after(N) should fire after being called N times");
equal(testAfter(5, 4), 0, "after(N) should not fire unless called N times");
equal(testAfter(0, 0), 1, "after(0) should fire immediately");
});
});

View File

@@ -1,44 +0,0 @@
<!DOCTYPE HTML>
<html>
<head>
<title>Underscore Test Suite</title>
<link rel="stylesheet" href="vendor/qunit.css" type="text/css" media="screen" />
<script type="text/javascript" src="vendor/jquery.js"></script>
<script type="text/javascript" src="vendor/qunit.js"></script>
<script type="text/javascript" src="vendor/jslitmus.js"></script>
<script type="text/javascript" src="../../lodash.js"></script>
<script type="text/javascript" src="collections.js"></script>
<script type="text/javascript" src="arrays.js"></script>
<script type="text/javascript" src="functions.js"></script>
<script type="text/javascript" src="objects.js"></script>
<script type="text/javascript" src="utility.js"></script>
<script type="text/javascript" src="chaining.js"></script>
<script type="text/javascript" src="speed.js"></script>
</head>
<body>
<div class="underscore-test">
<h1 id="qunit-header">Underscore Test Suite</h1>
<div id="qunit-testrunner-toolbar"></div>
<h2 id="qunit-banner"></h2>
<h2 id="qunit-userAgent"></h2>
<ol id="qunit-tests"></ol>
<br />
<h1 class="qunit-header">Underscore Speed Suite</h1>
<p>
A representative sample of the functions are benchmarked here, to provide
a sense of how fast they might run in different browsers.
Each iteration runs on an array of 1000 elements.<br /><br />
For example, the 'intersect' test measures the number of times you can
find the intersection of two thousand-element arrays in one second.
</p>
<br />
<script type="text/html" id="template">
<%
// a comment
if (data) { data += 12345; }; %>
<li><%= data %></li>
</script>
</div>
</body>
</html>

View File

@@ -1,558 +0,0 @@
$(document).ready(function() {
module("Objects");
test("objects: keys", function() {
equal(_.keys({one : 1, two : 2}).join(', '), 'one, two', 'can extract the keys from an object');
// the test above is not safe because it relies on for-in enumeration order
var a = []; a[1] = 0;
equal(_.keys(a).join(', '), '1', 'is not fooled by sparse arrays; see issue #95');
raises(function() { _.keys(null); }, TypeError, 'throws an error for `null` values');
raises(function() { _.keys(void 0); }, TypeError, 'throws an error for `undefined` values');
raises(function() { _.keys(1); }, TypeError, 'throws an error for number primitives');
raises(function() { _.keys('a'); }, TypeError, 'throws an error for string primitives');
raises(function() { _.keys(true); }, TypeError, 'throws an error for boolean primitives');
});
test("objects: values", function() {
equal(_.values({one : 1, two : 2}).join(', '), '1, 2', 'can extract the values from an object');
});
test("objects: functions", function() {
var obj = {a : 'dash', b : _.map, c : (/yo/), d : _.reduce};
ok(_.isEqual(['b', 'd'], _.functions(obj)), 'can grab the function names of any passed-in object');
var Animal = function(){};
Animal.prototype.run = function(){};
equal(_.functions(new Animal).join(''), 'run', 'also looks up functions on the prototype');
});
test("objects: extend", function() {
var result;
equal(_.extend({}, {a:'b'}).a, 'b', 'can extend an object with the attributes of another');
equal(_.extend({a:'x'}, {a:'b'}).a, 'b', 'properties in source override destination');
equal(_.extend({x:'x'}, {a:'b'}).x, 'x', 'properties not in source dont get overriden');
result = _.extend({x:'x'}, {a:'a'}, {b:'b'});
ok(_.isEqual(result, {x:'x', a:'a', b:'b'}), 'can extend from multiple source objects');
result = _.extend({x:'x'}, {a:'a', x:2}, {a:'b'});
ok(_.isEqual(result, {x:2, a:'b'}), 'extending from multiple source objects last property trumps');
result = _.extend({}, {a: void 0, b: null});
equal(_.keys(result).join(''), 'ab', 'extend does not copy undefined values');
});
test("objects: pick", function() {
var result;
result = _.pick({a:1, b:2, c:3}, 'a', 'c');
ok(_.isEqual(result, {a:1, c:3}), 'can restrict properties to those named');
result = _.pick({a:1, b:2, c:3}, ['b', 'c']);
ok(_.isEqual(result, {b:2, c:3}), 'can restrict properties to those named in an array');
result = _.pick({a:1, b:2, c:3}, ['a'], 'b');
ok(_.isEqual(result, {a:1, b:2}), 'can restrict properties to those named in mixed args');
});
test("objects: defaults", function() {
var result;
var options = {zero: 0, one: 1, empty: "", nan: NaN, string: "string"};
_.defaults(options, {zero: 1, one: 10, twenty: 20});
equal(options.zero, 0, 'value exists');
equal(options.one, 1, 'value exists');
equal(options.twenty, 20, 'default applied');
_.defaults(options, {empty: "full"}, {nan: "nan"}, {word: "word"}, {word: "dog"});
equal(options.empty, "", 'value exists');
ok(_.isNaN(options.nan), "NaN isn't overridden");
equal(options.word, "word", 'new value is added, first one wins');
});
test("objects: clone", function() {
var moe = {name : 'moe', lucky : [13, 27, 34]};
var clone = _.clone(moe);
equal(clone.name, 'moe', 'the clone as the attributes of the original');
clone.name = 'curly';
ok(clone.name == 'curly' && moe.name == 'moe', 'clones can change shallow attributes without affecting the original');
clone.lucky.push(101);
equal(_.last(moe.lucky), 101, 'changes to deep attributes are shared with the original');
equal(_.clone(undefined), void 0, 'non objects should not be changed by clone');
equal(_.clone(1), 1, 'non objects should not be changed by clone');
equal(_.clone(null), null, 'non objects should not be changed by clone');
});
test("objects: isEqual", function() {
function First() {
this.value = 1;
}
First.prototype.value = 1;
function Second() {
this.value = 1;
}
Second.prototype.value = 2;
// Basic equality and identity comparisons.
ok(_.isEqual(null, null), "`null` is equal to `null`");
ok(_.isEqual(), "`undefined` is equal to `undefined`");
ok(!_.isEqual(0, -0), "`0` is not equal to `-0`");
ok(!_.isEqual(-0, 0), "Commutative equality is implemented for `0` and `-0`");
ok(!_.isEqual(null, undefined), "`null` is not equal to `undefined`");
ok(!_.isEqual(undefined, null), "Commutative equality is implemented for `null` and `undefined`");
// String object and primitive comparisons.
ok(_.isEqual("Curly", "Curly"), "Identical string primitives are equal");
ok(_.isEqual(new String("Curly"), new String("Curly")), "String objects with identical primitive values are equal");
ok(_.isEqual(new String("Curly"), "Curly"), "String primitives and their corresponding object wrappers are equal");
ok(_.isEqual("Curly", new String("Curly")), "Commutative equality is implemented for string objects and primitives");
ok(!_.isEqual("Curly", "Larry"), "String primitives with different values are not equal");
ok(!_.isEqual(new String("Curly"), new String("Larry")), "String objects with different primitive values are not equal");
ok(!_.isEqual(new String("Curly"), {toString: function(){ return "Curly"; }}), "String objects and objects with a custom `toString` method are not equal");
// Number object and primitive comparisons.
ok(_.isEqual(75, 75), "Identical number primitives are equal");
ok(_.isEqual(new Number(75), new Number(75)), "Number objects with identical primitive values are equal");
ok(_.isEqual(75, new Number(75)), "Number primitives and their corresponding object wrappers are equal");
ok(_.isEqual(new Number(75), 75), "Commutative equality is implemented for number objects and primitives");
ok(!_.isEqual(new Number(0), -0), "`new Number(0)` and `-0` are not equal");
ok(!_.isEqual(0, new Number(-0)), "Commutative equality is implemented for `new Number(0)` and `-0`");
ok(!_.isEqual(new Number(75), new Number(63)), "Number objects with different primitive values are not equal");
ok(!_.isEqual(new Number(63), {valueOf: function(){ return 63; }}), "Number objects and objects with a `valueOf` method are not equal");
// Comparisons involving `NaN`.
ok(_.isEqual(NaN, NaN), "`NaN` is equal to `NaN`");
ok(!_.isEqual(61, NaN), "A number primitive is not equal to `NaN`");
ok(!_.isEqual(new Number(79), NaN), "A number object is not equal to `NaN`");
ok(!_.isEqual(Infinity, NaN), "`Infinity` is not equal to `NaN`");
// Boolean object and primitive comparisons.
ok(_.isEqual(true, true), "Identical boolean primitives are equal");
ok(_.isEqual(new Boolean, new Boolean), "Boolean objects with identical primitive values are equal");
ok(_.isEqual(true, new Boolean(true)), "Boolean primitives and their corresponding object wrappers are equal");
ok(_.isEqual(new Boolean(true), true), "Commutative equality is implemented for booleans");
ok(!_.isEqual(new Boolean(true), new Boolean), "Boolean objects with different primitive values are not equal");
// Common type coercions.
ok(!_.isEqual(true, new Boolean(false)), "Boolean objects are not equal to the boolean primitive `true`");
ok(!_.isEqual("75", 75), "String and number primitives with like values are not equal");
ok(!_.isEqual(new Number(63), new String(63)), "String and number objects with like values are not equal");
ok(!_.isEqual(75, "75"), "Commutative equality is implemented for like string and number values");
ok(!_.isEqual(0, ""), "Number and string primitives with like values are not equal");
ok(!_.isEqual(1, true), "Number and boolean primitives with like values are not equal");
ok(!_.isEqual(new Boolean(false), new Number(0)), "Boolean and number objects with like values are not equal");
ok(!_.isEqual(false, new String("")), "Boolean primitives and string objects with like values are not equal");
ok(!_.isEqual(12564504e5, new Date(2009, 9, 25)), "Dates and their corresponding numeric primitive values are not equal");
// Dates.
ok(_.isEqual(new Date(2009, 9, 25), new Date(2009, 9, 25)), "Date objects referencing identical times are equal");
ok(!_.isEqual(new Date(2009, 9, 25), new Date(2009, 11, 13)), "Date objects referencing different times are not equal");
ok(!_.isEqual(new Date(2009, 11, 13), {
getTime: function(){
return 12606876e5;
}
}), "Date objects and objects with a `getTime` method are not equal");
ok(!_.isEqual(new Date("Curly"), new Date("Curly")), "Invalid dates are not equal");
// Functions.
ok(!_.isEqual(First, Second), "Different functions with identical bodies and source code representations are not equal");
// RegExps.
ok(_.isEqual(/(?:)/gim, /(?:)/gim), "RegExps with equivalent patterns and flags are equal");
ok(!_.isEqual(/(?:)/g, /(?:)/gi), "RegExps with equivalent patterns and different flags are not equal");
ok(!_.isEqual(/Moe/gim, /Curly/gim), "RegExps with different patterns and equivalent flags are not equal");
ok(!_.isEqual(/(?:)/gi, /(?:)/g), "Commutative equality is implemented for RegExps");
ok(!_.isEqual(/Curly/g, {source: "Larry", global: true, ignoreCase: false, multiline: false}), "RegExps and RegExp-like objects are not equal");
// Empty arrays, array-like objects, and object literals.
ok(_.isEqual({}, {}), "Empty object literals are equal");
ok(_.isEqual([], []), "Empty array literals are equal");
ok(_.isEqual([{}], [{}]), "Empty nested arrays and objects are equal");
ok(!_.isEqual({length: 0}, []), "Array-like objects and arrays are not equal.");
ok(!_.isEqual([], {length: 0}), "Commutative equality is implemented for array-like objects");
ok(!_.isEqual({}, []), "Object literals and array literals are not equal");
ok(!_.isEqual([], {}), "Commutative equality is implemented for objects and arrays");
// Arrays with primitive and object values.
ok(_.isEqual([1, "Larry", true], [1, "Larry", true]), "Arrays containing identical primitives are equal");
ok(_.isEqual([(/Moe/g), new Date(2009, 9, 25)], [(/Moe/g), new Date(2009, 9, 25)]), "Arrays containing equivalent elements are equal");
// Multi-dimensional arrays.
var a = [new Number(47), false, "Larry", /Moe/, new Date(2009, 11, 13), ['running', 'biking', new String('programming')], {a: 47}];
var b = [new Number(47), false, "Larry", /Moe/, new Date(2009, 11, 13), ['running', 'biking', new String('programming')], {a: 47}];
ok(_.isEqual(a, b), "Arrays containing nested arrays and objects are recursively compared");
// Overwrite the methods defined in ES 5.1 section 15.4.4.
a.forEach = a.map = a.filter = a.every = a.indexOf = a.lastIndexOf = a.some = a.reduce = a.reduceRight = null;
b.join = b.pop = b.reverse = b.shift = b.slice = b.splice = b.concat = b.sort = b.unshift = null;
// Array elements and properties.
ok(_.isEqual(a, b), "Arrays containing equivalent elements and different non-numeric properties are equal");
a.push("White Rocks");
ok(!_.isEqual(a, b), "Arrays of different lengths are not equal");
a.push("East Boulder");
b.push("Gunbarrel Ranch", "Teller Farm");
ok(!_.isEqual(a, b), "Arrays of identical lengths containing different elements are not equal");
// Sparse arrays.
ok(_.isEqual(Array(3), Array(3)), "Sparse arrays of identical lengths are equal");
ok(!_.isEqual(Array(3), Array(6)), "Sparse arrays of different lengths are not equal when both are empty");
// According to the Microsoft deviations spec, section 2.1.26, JScript 5.x treats `undefined`
// elements in arrays as elisions. Thus, sparse arrays and dense arrays containing `undefined`
// values are equivalent.
if (0 in [undefined]) {
ok(!_.isEqual(Array(3), [undefined, undefined, undefined]), "Sparse and dense arrays are not equal");
ok(!_.isEqual([undefined, undefined, undefined], Array(3)), "Commutative equality is implemented for sparse and dense arrays");
}
// Simple objects.
ok(_.isEqual({a: "Curly", b: 1, c: true}, {a: "Curly", b: 1, c: true}), "Objects containing identical primitives are equal");
ok(_.isEqual({a: /Curly/g, b: new Date(2009, 11, 13)}, {a: /Curly/g, b: new Date(2009, 11, 13)}), "Objects containing equivalent members are equal");
ok(!_.isEqual({a: 63, b: 75}, {a: 61, b: 55}), "Objects of identical sizes with different values are not equal");
ok(!_.isEqual({a: 63, b: 75}, {a: 61, c: 55}), "Objects of identical sizes with different property names are not equal");
ok(!_.isEqual({a: 1, b: 2}, {a: 1}), "Objects of different sizes are not equal");
ok(!_.isEqual({a: 1}, {a: 1, b: 2}), "Commutative equality is implemented for objects");
ok(!_.isEqual({x: 1, y: undefined}, {x: 1, z: 2}), "Objects with identical keys and different values are not equivalent");
// `A` contains nested objects and arrays.
a = {
name: new String("Moe Howard"),
age: new Number(77),
stooge: true,
hobbies: ["acting"],
film: {
name: "Sing a Song of Six Pants",
release: new Date(1947, 9, 30),
stars: [new String("Larry Fine"), "Shemp Howard"],
minutes: new Number(16),
seconds: 54
}
};
// `B` contains equivalent nested objects and arrays.
b = {
name: new String("Moe Howard"),
age: new Number(77),
stooge: true,
hobbies: ["acting"],
film: {
name: "Sing a Song of Six Pants",
release: new Date(1947, 9, 30),
stars: [new String("Larry Fine"), "Shemp Howard"],
minutes: new Number(16),
seconds: 54
}
};
ok(_.isEqual(a, b), "Objects with nested equivalent members are recursively compared");
// Instances.
ok(_.isEqual(new First, new First), "Object instances are equal");
ok(!_.isEqual(new First, new Second), "Objects with different constructors and identical own properties are not equal");
ok(!_.isEqual({value: 1}, new First), "Object instances and objects sharing equivalent properties are not equal");
ok(!_.isEqual({value: 2}, new Second), "The prototype chain of objects should not be examined");
// Circular Arrays.
(a = []).push(a);
(b = []).push(b);
ok(_.isEqual(a, b), "Arrays containing circular references are equal");
a.push(new String("Larry"));
b.push(new String("Larry"));
ok(_.isEqual(a, b), "Arrays containing circular references and equivalent properties are equal");
a.push("Shemp");
b.push("Curly");
ok(!_.isEqual(a, b), "Arrays containing circular references and different properties are not equal");
// Circular Objects.
a = {abc: null};
b = {abc: null};
a.abc = a;
b.abc = b;
ok(_.isEqual(a, b), "Objects containing circular references are equal");
a.def = 75;
b.def = 75;
ok(_.isEqual(a, b), "Objects containing circular references and equivalent properties are equal");
a.def = new Number(75);
b.def = new Number(63);
ok(!_.isEqual(a, b), "Objects containing circular references and different properties are not equal");
// Cyclic Structures.
a = [{abc: null}];
b = [{abc: null}];
(a[0].abc = a).push(a);
(b[0].abc = b).push(b);
ok(_.isEqual(a, b), "Cyclic structures are equal");
a[0].def = "Larry";
b[0].def = "Larry";
ok(_.isEqual(a, b), "Cyclic structures containing equivalent properties are equal");
a[0].def = new String("Larry");
b[0].def = new String("Curly");
ok(!_.isEqual(a, b), "Cyclic structures containing different properties are not equal");
// Complex Circular References.
a = {foo: {b: {foo: {c: {foo: null}}}}};
b = {foo: {b: {foo: {c: {foo: null}}}}};
a.foo.b.foo.c.foo = a;
b.foo.b.foo.c.foo = b;
ok(_.isEqual(a, b), "Cyclic structures with nested and identically-named properties are equal");
// Chaining.
ok(!_.isEqual(_({x: 1, y: undefined}).chain(), _({x: 1, z: 2}).chain()), 'Chained objects containing different values are not equal');
equal(_({x: 1, y: 2}).chain().isEqual(_({x: 1, y: 2}).chain()).value(), true, '`isEqual` can be chained');
// Custom `isEqual` methods.
var isEqualObj = {isEqual: function (o) { return o.isEqual == this.isEqual; }, unique: {}};
var isEqualObjClone = {isEqual: isEqualObj.isEqual, unique: {}};
ok(_.isEqual(isEqualObj, isEqualObjClone), 'Both objects implement identical `isEqual` methods');
ok(_.isEqual(isEqualObjClone, isEqualObj), 'Commutative equality is implemented for objects with custom `isEqual` methods');
ok(!_.isEqual(isEqualObj, {}), 'Objects that do not implement equivalent `isEqual` methods are not equal');
ok(!_.isEqual({}, isEqualObj), 'Commutative equality is implemented for objects with different `isEqual` methods');
// Custom `isEqual` methods - comparing different types
LocalizedString = (function() {
function LocalizedString(id) { this.id = id; this.string = (this.id===10)? 'Bonjour': ''; }
LocalizedString.prototype.isEqual = function(that) {
if (_.isString(that)) return this.string == that;
else if (that instanceof LocalizedString) return this.id == that.id;
return false;
};
return LocalizedString;
})();
var localized_string1 = new LocalizedString(10), localized_string2 = new LocalizedString(10), localized_string3 = new LocalizedString(11);
ok(_.isEqual(localized_string1, localized_string2), 'comparing same typed instances with same ids');
ok(!_.isEqual(localized_string1, localized_string3), 'comparing same typed instances with different ids');
ok(_.isEqual(localized_string1, 'Bonjour'), 'comparing different typed instances with same values');
ok(_.isEqual('Bonjour', localized_string1), 'comparing different typed instances with same values');
ok(!_.isEqual('Bonjour', localized_string3), 'comparing two localized strings with different ids');
ok(!_.isEqual(localized_string1, 'Au revoir'), 'comparing different typed instances with different values');
ok(!_.isEqual('Au revoir', localized_string1), 'comparing different typed instances with different values');
// Custom `isEqual` methods - comparing with serialized data
Date.prototype.toJSON = function() {
return {
_type:'Date',
year:this.getUTCFullYear(),
month:this.getUTCMonth(),
day:this.getUTCDate(),
hours:this.getUTCHours(),
minutes:this.getUTCMinutes(),
seconds:this.getUTCSeconds()
};
};
Date.prototype.isEqual = function(that) {
var this_date_components = this.toJSON();
var that_date_components = (that instanceof Date) ? that.toJSON() : that;
delete this_date_components['_type']; delete that_date_components['_type'];
return _.isEqual(this_date_components, that_date_components);
};
var date = new Date();
var date_json = {
_type:'Date',
year:date.getUTCFullYear(),
month:date.getUTCMonth(),
day:date.getUTCDate(),
hours:date.getUTCHours(),
minutes:date.getUTCMinutes(),
seconds:date.getUTCSeconds()
};
ok(_.isEqual(date_json, date), 'serialized date matches date');
ok(_.isEqual(date, date_json), 'date matches serialized date');
});
test("objects: isEmpty", function() {
ok(!_([1]).isEmpty(), '[1] is not empty');
ok(_.isEmpty([]), '[] is empty');
ok(!_.isEmpty({one : 1}), '{one : 1} is not empty');
ok(_.isEmpty({}), '{} is empty');
ok(_.isEmpty(new RegExp('')), 'objects with prototype properties are empty');
ok(_.isEmpty(null), 'null is empty');
ok(_.isEmpty(), 'undefined is empty');
ok(_.isEmpty(''), 'the empty string is empty');
ok(!_.isEmpty('moe'), 'but other strings are not');
var obj = {one : 1};
delete obj.one;
ok(_.isEmpty(obj), 'deleting all the keys from an object empties it');
});
// Setup remote variables for iFrame tests.
var iframe = document.createElement('iframe');
jQuery(iframe).appendTo(document.body);
var iDoc = iframe.contentDocument || iframe.contentWindow.document;
iDoc.write(
"<script>\
parent.iElement = document.createElement('div');\
parent.iArguments = (function(){ return arguments; })(1, 2, 3);\
parent.iArray = [1, 2, 3];\
parent.iString = new String('hello');\
parent.iNumber = new Number(100);\
parent.iFunction = (function(){});\
parent.iDate = new Date();\
parent.iRegExp = /hi/;\
parent.iNaN = NaN;\
parent.iNull = null;\
parent.iBoolean = new Boolean(false);\
parent.iUndefined = undefined;\
</script>"
);
iDoc.close();
test("objects: isElement", function() {
ok(!_.isElement('div'), 'strings are not dom elements');
ok(_.isElement($('html')[0]), 'the html tag is a DOM element');
ok(_.isElement(iElement), 'even from another frame');
});
test("objects: isArguments", function() {
var args = (function(){ return arguments; })(1, 2, 3);
ok(!_.isArguments('string'), 'a string is not an arguments object');
ok(!_.isArguments(_.isArguments), 'a function is not an arguments object');
ok(_.isArguments(args), 'but the arguments object is an arguments object');
ok(!_.isArguments(_.toArray(args)), 'but not when it\'s converted into an array');
ok(!_.isArguments([1,2,3]), 'and not vanilla arrays.');
ok(_.isArguments(iArguments), 'even from another frame');
});
test("objects: isObject", function() {
ok(_.isObject(arguments), 'the arguments object is object');
ok(_.isObject([1, 2, 3]), 'and arrays');
ok(_.isObject($('html')[0]), 'and DOM element');
ok(_.isObject(iElement), 'even from another frame');
ok(_.isObject(function () {}), 'and functions');
ok(_.isObject(iFunction), 'even from another frame');
ok(!_.isObject(null), 'but not null');
ok(!_.isObject(undefined), 'and not undefined');
ok(!_.isObject('string'), 'and not string');
ok(!_.isObject(12), 'and not number');
ok(!_.isObject(true), 'and not boolean');
ok(_.isObject(new String('string')), 'but new String()');
});
test("objects: isArray", function() {
ok(!_.isArray(arguments), 'the arguments object is not an array');
ok(_.isArray([1, 2, 3]), 'but arrays are');
ok(_.isArray(iArray), 'even from another frame');
});
test("objects: isString", function() {
ok(!_.isString(document.body), 'the document body is not a string');
ok(_.isString([1, 2, 3].join(', ')), 'but strings are');
ok(_.isString(iString), 'even from another frame');
});
test("objects: isNumber", function() {
ok(!_.isNumber('string'), 'a string is not a number');
ok(!_.isNumber(arguments), 'the arguments object is not a number');
ok(!_.isNumber(undefined), 'undefined is not a number');
ok(_.isNumber(3 * 4 - 7 / 10), 'but numbers are');
ok(_.isNumber(NaN), 'NaN *is* a number');
ok(_.isNumber(Infinity), 'Infinity is a number');
ok(_.isNumber(iNumber), 'even from another frame');
ok(!_.isNumber('1'), 'numeric strings are not numbers');
});
test("objects: isBoolean", function() {
ok(!_.isBoolean(2), 'a number is not a boolean');
ok(!_.isBoolean("string"), 'a string is not a boolean');
ok(!_.isBoolean("false"), 'the string "false" is not a boolean');
ok(!_.isBoolean("true"), 'the string "true" is not a boolean');
ok(!_.isBoolean(arguments), 'the arguments object is not a boolean');
ok(!_.isBoolean(undefined), 'undefined is not a boolean');
ok(!_.isBoolean(NaN), 'NaN is not a boolean');
ok(!_.isBoolean(null), 'null is not a boolean');
ok(_.isBoolean(true), 'but true is');
ok(_.isBoolean(false), 'and so is false');
ok(_.isBoolean(iBoolean), 'even from another frame');
});
test("objects: isFunction", function() {
ok(!_.isFunction([1, 2, 3]), 'arrays are not functions');
ok(!_.isFunction('moe'), 'strings are not functions');
ok(_.isFunction(_.isFunction), 'but functions are');
ok(_.isFunction(iFunction), 'even from another frame');
});
test("objects: isDate", function() {
ok(!_.isDate(100), 'numbers are not dates');
ok(!_.isDate({}), 'objects are not dates');
ok(_.isDate(new Date()), 'but dates are');
ok(_.isDate(iDate), 'even from another frame');
});
test("objects: isRegExp", function() {
ok(!_.isRegExp(_.identity), 'functions are not RegExps');
ok(_.isRegExp(/identity/), 'but RegExps are');
ok(_.isRegExp(iRegExp), 'even from another frame');
});
test("objects: isFinite", function() {
ok(!_.isFinite(undefined), 'undefined is not Finite');
ok(!_.isFinite(null), 'null is not Finite');
ok(!_.isFinite(NaN), 'NaN is not Finite');
ok(!_.isFinite(Infinity), 'Infinity is not Finite');
ok(!_.isFinite(-Infinity), '-Infinity is not Finite');
ok(!_.isFinite('12'), 'Strings are not numbers');
var obj = new Number(5);
ok(_.isFinite(obj), 'Number instances can be finite');
ok(_.isFinite(0), '0 is Finite');
ok(_.isFinite(123), 'Ints are Finite');
ok(_.isFinite(-12.44), 'Floats are Finite');
});
test("objects: isNaN", function() {
ok(!_.isNaN(undefined), 'undefined is not NaN');
ok(!_.isNaN(null), 'null is not NaN');
ok(!_.isNaN(0), '0 is not NaN');
ok(_.isNaN(NaN), 'but NaN is');
ok(_.isNaN(iNaN), 'even from another frame');
});
test("objects: isNull", function() {
ok(!_.isNull(undefined), 'undefined is not null');
ok(!_.isNull(NaN), 'NaN is not null');
ok(_.isNull(null), 'but null is');
ok(_.isNull(iNull), 'even from another frame');
});
test("objects: isUndefined", function() {
ok(!_.isUndefined(1), 'numbers are defined');
ok(!_.isUndefined(null), 'null is defined');
ok(!_.isUndefined(false), 'false is defined');
ok(!_.isUndefined(NaN), 'NaN is defined');
ok(_.isUndefined(), 'nothing is undefined');
ok(_.isUndefined(undefined), 'undefined is undefined');
ok(_.isUndefined(iUndefined), 'even from another frame');
});
if (window.ActiveXObject) {
test("objects: IE host objects", function() {
var xml = new ActiveXObject("Msxml2.DOMDocument.3.0");
ok(!_.isNumber(xml));
ok(!_.isBoolean(xml));
ok(!_.isNaN(xml));
ok(!_.isFunction(xml));
ok(!_.isNull(xml));
ok(!_.isUndefined(xml));
});
}
test("objects: tap", function() {
var intercepted = null;
var interceptor = function(obj) { intercepted = obj; };
var returned = _.tap(1, interceptor);
equal(intercepted, 1, "passes tapped object to interceptor");
equal(returned, 1, "returns tapped object");
returned = _([1,2,3]).chain().
map(function(n){ return n * 2; }).
max().
tap(interceptor).
value();
ok(returned == 6 && intercepted == 6, 'can use tapped objects in a chain');
});
});

View File

@@ -1,70 +0,0 @@
(function() {
var numbers = [];
for (var i=0; i<1000; i++) numbers.push(i);
var objects = _.map(numbers, function(n){ return {num : n}; });
var randomized = _.sortBy(numbers, function(){ return Math.random(); });
JSLitmus.test('_.each()', function() {
var timesTwo = [];
_.each(numbers, function(num){ timesTwo.push(num * 2); });
return timesTwo;
});
JSLitmus.test('_(list).each()', function() {
var timesTwo = [];
_(numbers).each(function(num){ timesTwo.push(num * 2); });
return timesTwo;
});
JSLitmus.test('jQuery.each()', function() {
var timesTwo = [];
jQuery.each(numbers, function(){ timesTwo.push(this * 2); });
return timesTwo;
});
JSLitmus.test('_.map()', function() {
return _.map(objects, function(obj){ return obj.num; });
});
JSLitmus.test('jQuery.map()', function() {
return jQuery.map(objects, function(obj){ return obj.num; });
});
JSLitmus.test('_.pluck()', function() {
return _.pluck(objects, 'num');
});
JSLitmus.test('_.uniq()', function() {
return _.uniq(randomized);
});
JSLitmus.test('_.uniq() (sorted)', function() {
return _.uniq(numbers, true);
});
JSLitmus.test('_.sortBy()', function() {
return _.sortBy(numbers, function(num){ return -num; });
});
JSLitmus.test('_.isEqual()', function() {
return _.isEqual(numbers, randomized);
});
JSLitmus.test('_.keys()', function() {
return _.keys(objects);
});
JSLitmus.test('_.values()', function() {
return _.values(objects);
});
JSLitmus.test('_.intersect()', function() {
return _.intersect(numbers, randomized);
});
JSLitmus.test('_.range()', function() {
return _.range(1000);
});
})();

View File

@@ -1,223 +0,0 @@
$(document).ready(function() {
var templateSettings;
module("Utility", {
setup: function() {
templateSettings = _.clone(_.templateSettings);
},
teardown: function() {
_.templateSettings = templateSettings;
}
});
test("utility: noConflict", function() {
var underscore = _.noConflict();
ok(underscore.isUndefined(_), "The '_' variable has been returned to its previous state.");
var intersection = underscore.intersect([-1, 0, 1, 2], [1, 2, 3, 4]);
equal(intersection.join(', '), '1, 2', 'but the intersection function still works');
window._ = underscore;
});
test("utility: identity", function() {
var moe = {name : 'moe'};
equal(_.identity(moe), moe, 'moe is the same as his identity');
});
test("utility: uniqueId", function() {
var ids = [], i = 0;
while(i++ < 100) ids.push(_.uniqueId());
equal(_.uniq(ids).length, ids.length, 'can generate a globally-unique stream of ids');
});
test("utility: times", function() {
var vals = [];
_.times(3, function (i) { vals.push(i); });
ok(_.isEqual(vals, [0,1,2]), "is 0 indexed");
//
vals = [];
_(3).times(function (i) { vals.push(i); });
ok(_.isEqual(vals, [0,1,2]), "works as a wrapper");
});
test("utility: mixin", function() {
_.mixin({
myReverse: function(string) {
return string.split('').reverse().join('');
}
});
equal(_.myReverse('panacea'), 'aecanap', 'mixed in a function to _');
equal(_('champ').myReverse(), 'pmahc', 'mixed in a function to the OOP wrapper');
});
test("utility: _.escape", function() {
equal(_.escape("Curly & Moe"), "Curly &amp; Moe");
equal(_.escape("Curly &amp; Moe"), "Curly &amp;amp; Moe");
});
test("utility: template", function() {
var basicTemplate = _.template("<%= thing %> is gettin' on my noives!");
var result = basicTemplate({thing : 'This'});
equal(result, "This is gettin' on my noives!", 'can do basic attribute interpolation');
var sansSemicolonTemplate = _.template("A <% this %> B");
equal(sansSemicolonTemplate(), "A B");
var backslashTemplate = _.template("<%= thing %> is \\ridanculous");
equal(backslashTemplate({thing: 'This'}), "This is \\ridanculous");
var escapeTemplate = _.template('<%= a ? "checked=\\"checked\\"" : "" %>');
equal(escapeTemplate({a: true}), 'checked="checked"', 'can handle slash escapes in interpolations.');
var fancyTemplate = _.template("<ul><% \
for (key in people) { \
%><li><%= people[key] %></li><% } %></ul>");
result = fancyTemplate({people : {moe : "Moe", larry : "Larry", curly : "Curly"}});
equal(result, "<ul><li>Moe</li><li>Larry</li><li>Curly</li></ul>", 'can run arbitrary javascript in templates');
var escapedCharsInJavascriptTemplate = _.template("<ul><% _.each(numbers.split('\\n'), function(item) { %><li><%= item %></li><% }) %></ul>");
result = escapedCharsInJavascriptTemplate({numbers: "one\ntwo\nthree\nfour"});
equal(result, "<ul><li>one</li><li>two</li><li>three</li><li>four</li></ul>", 'Can use escaped characters (e.g. \\n) in Javascript');
var namespaceCollisionTemplate = _.template("<%= pageCount %> <%= thumbnails[pageCount] %> <% _.each(thumbnails, function(p) { %><div class=\"thumbnail\" rel=\"<%= p %>\"></div><% }); %>");
result = namespaceCollisionTemplate({
pageCount: 3,
thumbnails: {
1: "p1-thumbnail.gif",
2: "p2-thumbnail.gif",
3: "p3-thumbnail.gif"
}
});
equal(result, "3 p3-thumbnail.gif <div class=\"thumbnail\" rel=\"p1-thumbnail.gif\"></div><div class=\"thumbnail\" rel=\"p2-thumbnail.gif\"></div><div class=\"thumbnail\" rel=\"p3-thumbnail.gif\"></div>");
var noInterpolateTemplate = _.template("<div><p>Just some text. Hey, I know this is silly but it aids consistency.</p></div>");
result = noInterpolateTemplate();
equal(result, "<div><p>Just some text. Hey, I know this is silly but it aids consistency.</p></div>");
var quoteTemplate = _.template("It's its, not it's");
equal(quoteTemplate({}), "It's its, not it's");
var quoteInStatementAndBody = _.template("<%\
if(foo == 'bar'){ \
%>Statement quotes and 'quotes'.<% } %>");
equal(quoteInStatementAndBody({foo: "bar"}), "Statement quotes and 'quotes'.");
var withNewlinesAndTabs = _.template('This\n\t\tis: <%= x %>.\n\tok.\nend.');
equal(withNewlinesAndTabs({x: 'that'}), 'This\n\t\tis: that.\n\tok.\nend.');
var template = _.template("<i><%- value %></i>");
var result = template({value: "<script>"});
equal(result, '<i>&lt;script&gt;</i>');
var stooge = {
name: "Moe",
template: _.template("I'm <%= this.name %>")
};
equal(stooge.template(), "I'm Moe");
if (!$.browser.msie) {
var fromHTML = _.template($('#template').html());
equal(fromHTML({data : 12345}).replace(/\s/g, ''), '<li>24690</li>');
}
_.templateSettings = {
evaluate : /\{\{([\s\S]+?)\}\}/g,
interpolate : /\{\{=([\s\S]+?)\}\}/g
};
var custom = _.template("<ul>{{ for (key in people) { }}<li>{{= people[key] }}</li>{{ } }}</ul>");
result = custom({people : {moe : "Moe", larry : "Larry", curly : "Curly"}});
equal(result, "<ul><li>Moe</li><li>Larry</li><li>Curly</li></ul>", 'can run arbitrary javascript in templates');
var customQuote = _.template("It's its, not it's");
equal(customQuote({}), "It's its, not it's");
var quoteInStatementAndBody = _.template("{{ if(foo == 'bar'){ }}Statement quotes and 'quotes'.{{ } }}");
equal(quoteInStatementAndBody({foo: "bar"}), "Statement quotes and 'quotes'.");
_.templateSettings = {
evaluate : /<\?([\s\S]+?)\?>/g,
interpolate : /<\?=([\s\S]+?)\?>/g
};
var customWithSpecialChars = _.template("<ul><? for (key in people) { ?><li><?= people[key] ?></li><? } ?></ul>");
result = customWithSpecialChars({people : {moe : "Moe", larry : "Larry", curly : "Curly"}});
equal(result, "<ul><li>Moe</li><li>Larry</li><li>Curly</li></ul>", 'can run arbitrary javascript in templates');
var customWithSpecialCharsQuote = _.template("It's its, not it's");
equal(customWithSpecialCharsQuote({}), "It's its, not it's");
var quoteInStatementAndBody = _.template("<? if(foo == 'bar'){ ?>Statement quotes and 'quotes'.<? } ?>");
equal(quoteInStatementAndBody({foo: "bar"}), "Statement quotes and 'quotes'.");
_.templateSettings = {
interpolate : /\{\{(.+?)\}\}/g
};
var mustache = _.template("Hello {{planet}}!");
equal(mustache({planet : "World"}), "Hello World!", "can mimic mustache.js");
var templateWithNull = _.template("a null undefined {{planet}}");
equal(templateWithNull({planet : "world"}), "a null undefined world", "can handle missing escape and evaluate settings");
});
test('_.template handles \\u2028 & \\u2029', function() {
var tmpl = _.template('<p>\u2028<%= "\\u2028\\u2029" %>\u2029</p>');
strictEqual(tmpl(), '<p>\u2028\u2028\u2029\u2029</p>');
});
test('result calls functions and returns primitives', function() {
var obj = {w: '', x: 'x', y: function(){ return this.x; }};
strictEqual(_.result(obj, 'w'), '');
strictEqual(_.result(obj, 'x'), 'x');
strictEqual(_.result(obj, 'y'), 'x');
strictEqual(_.result(obj, 'z'), undefined);
strictEqual(_.result(null, 'x'), null);
});
test('_.templateSettings.variable', function() {
var s = '<%=data.x%>';
var data = {x: 'x'};
strictEqual(_.template(s, data, {variable: 'data'}), 'x')
_.templateSettings.variable = 'data';
strictEqual(_.template(s)(data), 'x')
});
test('#547 - _.templateSettings is unchanged by custom settings.', function() {
ok(!_.templateSettings.variable);
_.template('', {}, {variable: 'x'});
ok(!_.templateSettings.variable);
});
test('#556 - undefined template variables.', function() {
var template = _.template('<%=x%>');
strictEqual(template({x: null}), '');
strictEqual(template({x: undefined}), '');
var templateEscaped = _.template('<%-x%>');
strictEqual(templateEscaped({x: null}), '');
strictEqual(templateEscaped({x: undefined}), '');
var templateWithProperty = _.template('<%=x.foo%>');
strictEqual(templateWithProperty({x: {} }), '');
strictEqual(templateWithProperty({x: {} }), '');
var templateWithPropertyEscaped = _.template('<%-x.foo%>');
strictEqual(templateWithPropertyEscaped({x: {} }), '');
strictEqual(templateWithPropertyEscaped({x: {} }), '');
});
test('interpolate evaluates code only once.', 2, function() {
var count = 0;
var template = _.template('<%= f() %>');
template({f: function(){ ok(!(count++)); }});
var countEscaped = 0;
var templateEscaped = _.template('<%- f() %>');
templateEscaped({f: function(){ ok(!(countEscaped++)); }});
});
});

File diff suppressed because one or more lines are too long

View File

@@ -1,670 +0,0 @@
// JSLitmus.js
//
// History:
// 2008-10-27: Initial release
// 2008-11-09: Account for iteration loop overhead
// 2008-11-13: Added OS detection
// 2009-02-25: Create tinyURL automatically, shift-click runs tests in reverse
//
// Copyright (c) 2008-2009, Robert Kieffer
// All Rights Reserved
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the
// Software), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to permit
// persons to whom the Software is furnished to do so, subject to the
// following conditions:
//
// THE SOFTWARE IS PROVIDED AS IS, WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
// USE OR OTHER DEALINGS IN THE SOFTWARE.
(function() {
// Private methods and state
// Get platform info but don't go crazy trying to recognize everything
// that's out there. This is just for the major platforms and OSes.
var platform = 'unknown platform', ua = navigator.userAgent;
// Detect OS
var oses = ['Windows','iPhone OS','(Intel |PPC )?Mac OS X','Linux'].join('|');
var pOS = new RegExp('((' + oses + ') [^ \);]*)').test(ua) ? RegExp.$1 : null;
if (!pOS) pOS = new RegExp('((' + oses + ')[^ \);]*)').test(ua) ? RegExp.$1 : null;
// Detect browser
var pName = /(Chrome|MSIE|Safari|Opera|Firefox)/.test(ua) ? RegExp.$1 : null;
// Detect version
var vre = new RegExp('(Version|' + pName + ')[ \/]([^ ;]*)');
var pVersion = (pName && vre.test(ua)) ? RegExp.$2 : null;
var platform = (pOS && pName && pVersion) ? pName + ' ' + pVersion + ' on ' + pOS : 'unknown platform';
/**
* A smattering of methods that are needed to implement the JSLitmus testbed.
*/
var jsl = {
/**
* Enhanced version of escape()
*/
escape: function(s) {
s = s.replace(/,/g, '\\,');
s = escape(s);
s = s.replace(/\+/g, '%2b');
s = s.replace(/ /g, '+');
return s;
},
/**
* Get an element by ID.
*/
$: function(id) {
return document.getElementById(id);
},
/**
* Null function
*/
F: function() {},
/**
* Set the status shown in the UI
*/
status: function(msg) {
var el = jsl.$('jsl_status');
if (el) el.innerHTML = msg || '';
},
/**
* Convert a number to an abbreviated string like, "15K" or "10M"
*/
toLabel: function(n) {
if (n == Infinity) {
return 'Infinity';
} else if (n > 1e9) {
n = Math.round(n/1e8);
return n/10 + 'B';
} else if (n > 1e6) {
n = Math.round(n/1e5);
return n/10 + 'M';
} else if (n > 1e3) {
n = Math.round(n/1e2);
return n/10 + 'K';
}
return n;
},
/**
* Copy properties from src to dst
*/
extend: function(dst, src) {
for (var k in src) dst[k] = src[k]; return dst;
},
/**
* Like Array.join(), but for the key-value pairs in an object
*/
join: function(o, delimit1, delimit2) {
if (o.join) return o.join(delimit1); // If it's an array
var pairs = [];
for (var k in o) pairs.push(k + delimit1 + o[k]);
return pairs.join(delimit2);
},
/**
* Array#indexOf isn't supported in IE, so we use this as a cross-browser solution
*/
indexOf: function(arr, o) {
if (arr.indexOf) return arr.indexOf(o);
for (var i = 0; i < this.length; i++) if (arr[i] === o) return i;
return -1;
}
};
/**
* Test manages a single test (created with
* JSLitmus.test())
*
* @private
*/
var Test = function (name, f) {
if (!f) throw new Error('Undefined test function');
if (!(/function[^\(]*\(([^,\)]*)/).test(f.toString())) {
throw new Error('"' + name + '" test: Test is not a valid Function object');
}
this.loopArg = RegExp.$1;
this.name = name;
this.f = f;
};
jsl.extend(Test, /** @lends Test */ {
/** Calibration tests for establishing iteration loop overhead */
CALIBRATIONS: [
new Test('calibrating loop', function(count) {while (count--);}),
new Test('calibrating function', jsl.F)
],
/**
* Run calibration tests. Returns true if calibrations are not yet
* complete (in which case calling code should run the tests yet again).
* onCalibrated - Callback to invoke when calibrations have finished
*/
calibrate: function(onCalibrated) {
for (var i = 0; i < Test.CALIBRATIONS.length; i++) {
var cal = Test.CALIBRATIONS[i];
if (cal.running) return true;
if (!cal.count) {
cal.isCalibration = true;
cal.onStop = onCalibrated;
//cal.MIN_TIME = .1; // Do calibrations quickly
cal.run(2e4);
return true;
}
}
return false;
}
});
jsl.extend(Test.prototype, {/** @lends Test.prototype */
/** Initial number of iterations */
INIT_COUNT: 10,
/** Max iterations allowed (i.e. used to detect bad looping functions) */
MAX_COUNT: 1e9,
/** Minimum time a test should take to get valid results (secs) */
MIN_TIME: .5,
/** Callback invoked when test state changes */
onChange: jsl.F,
/** Callback invoked when test is finished */
onStop: jsl.F,
/**
* Reset test state
*/
reset: function() {
delete this.count;
delete this.time;
delete this.running;
delete this.error;
},
/**
* Run the test (in a timeout). We use a timeout to make sure the browser
* has a chance to finish rendering any UI changes we've made, like
* updating the status message.
*/
run: function(count) {
count = count || this.INIT_COUNT;
jsl.status(this.name + ' x ' + count);
this.running = true;
var me = this;
setTimeout(function() {me._run(count);}, 200);
},
/**
* The nuts and bolts code that actually runs a test
*/
_run: function(count) {
var me = this;
// Make sure calibration tests have run
if (!me.isCalibration && Test.calibrate(function() {me.run(count);})) return;
this.error = null;
try {
var start, f = this.f, now, i = count;
// Start the timer
start = new Date();
// Now for the money shot. If this is a looping function ...
if (this.loopArg) {
// ... let it do the iteration itself
f(count);
} else {
// ... otherwise do the iteration for it
while (i--) f();
}
// Get time test took (in secs)
this.time = Math.max(1,new Date() - start)/1000;
// Store iteration count and per-operation time taken
this.count = count;
this.period = this.time/count;
// Do we need to do another run?
this.running = this.time <= this.MIN_TIME;
// ... if so, compute how many times we should iterate
if (this.running) {
// Bump the count to the nearest power of 2
var x = this.MIN_TIME/this.time;
var pow = Math.pow(2, Math.max(1, Math.ceil(Math.log(x)/Math.log(2))));
count *= pow;
if (count > this.MAX_COUNT) {
throw new Error('Max count exceeded. If this test uses a looping function, make sure the iteration loop is working properly.');
}
}
} catch (e) {
// Exceptions are caught and displayed in the test UI
this.reset();
this.error = e;
}
// Figure out what to do next
if (this.running) {
me.run(count);
} else {
jsl.status('');
me.onStop(me);
}
// Finish up
this.onChange(this);
},
/**
* Get the number of operations per second for this test.
*
* @param normalize if true, iteration loop overhead taken into account
*/
getHz: function(/**Boolean*/ normalize) {
var p = this.period;
// Adjust period based on the calibration test time
if (normalize && !this.isCalibration) {
var cal = Test.CALIBRATIONS[this.loopArg ? 0 : 1];
// If the period is within 20% of the calibration time, then zero the
// it out
p = p < cal.period*1.2 ? 0 : p - cal.period;
}
return Math.round(1/p);
},
/**
* Get a friendly string describing the test
*/
toString: function() {
return this.name + ' - ' + this.time/this.count + ' secs';
}
});
// CSS we need for the UI
var STYLESHEET = '<style> \
#jslitmus {font-family:sans-serif; font-size: 12px;} \
#jslitmus a {text-decoration: none;} \
#jslitmus a:hover {text-decoration: underline;} \
#jsl_status { \
margin-top: 10px; \
font-size: 10px; \
color: #888; \
} \
A IMG {border:none} \
#test_results { \
margin-top: 10px; \
font-size: 12px; \
font-family: sans-serif; \
border-collapse: collapse; \
border-spacing: 0px; \
} \
#test_results th, #test_results td { \
border: solid 1px #ccc; \
vertical-align: top; \
padding: 3px; \
} \
#test_results th { \
vertical-align: bottom; \
background-color: #ccc; \
padding: 1px; \
font-size: 10px; \
} \
#test_results #test_platform { \
color: #444; \
text-align:center; \
} \
#test_results .test_row { \
color: #006; \
cursor: pointer; \
} \
#test_results .test_nonlooping { \
border-left-style: dotted; \
border-left-width: 2px; \
} \
#test_results .test_looping { \
border-left-style: solid; \
border-left-width: 2px; \
} \
#test_results .test_name {white-space: nowrap;} \
#test_results .test_pending { \
} \
#test_results .test_running { \
font-style: italic; \
} \
#test_results .test_done {} \
#test_results .test_done { \
text-align: right; \
font-family: monospace; \
} \
#test_results .test_error {color: #600;} \
#test_results .test_error .error_head {font-weight:bold;} \
#test_results .test_error .error_body {font-size:85%;} \
#test_results .test_row:hover td { \
background-color: #ffc; \
text-decoration: underline; \
} \
#chart { \
margin: 10px 0px; \
width: 250px; \
} \
#chart img { \
border: solid 1px #ccc; \
margin-bottom: 5px; \
} \
#chart #tiny_url { \
height: 40px; \
width: 250px; \
} \
#jslitmus_credit { \
font-size: 10px; \
color: #888; \
margin-top: 8px; \
} \
</style>';
// HTML markup for the UI
var MARKUP = '<div id="jslitmus"> \
<button onclick="JSLitmus.runAll(event)">Run Tests</button> \
<button id="stop_button" disabled="disabled" onclick="JSLitmus.stop()">Stop Tests</button> \
<br \> \
<br \> \
<input type="checkbox" style="vertical-align: middle" id="test_normalize" checked="checked" onchange="JSLitmus.renderAll()""> Normalize results \
<table id="test_results"> \
<colgroup> \
<col /> \
<col width="100" /> \
</colgroup> \
<tr><th id="test_platform" colspan="2">' + platform + '</th></tr> \
<tr><th>Test</th><th>Ops/sec</th></tr> \
<tr id="test_row_template" class="test_row" style="display:none"> \
<td class="test_name"></td> \
<td class="test_result">Ready</td> \
</tr> \
</table> \
<div id="jsl_status"></div> \
<div id="chart" style="display:none"> \
<a id="chart_link" target="_blank"><img id="chart_image"></a> \
TinyURL (for chart): \
<iframe id="tiny_url" frameBorder="0" scrolling="no" src=""></iframe> \
</div> \
<a id="jslitmus_credit" title="JSLitmus home page" href="http://code.google.com/p/jslitmus" target="_blank">Powered by JSLitmus</a> \
</div>';
/**
* The public API for creating and running tests
*/
window.JSLitmus = {
/** The list of all tests that have been registered with JSLitmus.test */
_tests: [],
/** The queue of tests that need to be run */
_queue: [],
/**
* The parsed query parameters the current page URL. This is provided as a
* convenience for test functions - it's not used by JSLitmus proper
*/
params: {},
/**
* Initialize
*/
_init: function() {
// Parse query params into JSLitmus.params[] hash
var match = (location + '').match(/([^?#]*)(#.*)?$/);
if (match) {
var pairs = match[1].split('&');
for (var i = 0; i < pairs.length; i++) {
var pair = pairs[i].split('=');
if (pair.length > 1) {
var key = pair.shift();
var value = pair.length > 1 ? pair.join('=') : pair[0];
this.params[key] = value;
}
}
}
// Write out the stylesheet. We have to do this here because IE
// doesn't honor sheets written after the document has loaded.
document.write(STYLESHEET);
// Setup the rest of the UI once the document is loaded
if (window.addEventListener) {
window.addEventListener('load', this._setup, false);
} else if (document.addEventListener) {
document.addEventListener('load', this._setup, false);
} else if (window.attachEvent) {
window.attachEvent('onload', this._setup);
}
return this;
},
/**
* Set up the UI
*/
_setup: function() {
var el = jsl.$('jslitmus_container');
if (!el) document.body.appendChild(el = document.createElement('div'));
el.innerHTML = MARKUP;
// Render the UI for all our tests
for (var i=0; i < JSLitmus._tests.length; i++)
JSLitmus.renderTest(JSLitmus._tests[i]);
},
/**
* (Re)render all the test results
*/
renderAll: function() {
for (var i = 0; i < JSLitmus._tests.length; i++)
JSLitmus.renderTest(JSLitmus._tests[i]);
JSLitmus.renderChart();
},
/**
* (Re)render the chart graphics
*/
renderChart: function() {
var url = JSLitmus.chartUrl();
jsl.$('chart_link').href = url;
jsl.$('chart_image').src = url;
jsl.$('chart').style.display = '';
// Update the tiny URL
jsl.$('tiny_url').src = 'http://tinyurl.com/api-create.php?url='+escape(url);
},
/**
* (Re)render the results for a specific test
*/
renderTest: function(test) {
// Make a new row if needed
if (!test._row) {
var trow = jsl.$('test_row_template');
if (!trow) return;
test._row = trow.cloneNode(true);
test._row.style.display = '';
test._row.id = '';
test._row.onclick = function() {JSLitmus._queueTest(test);};
test._row.title = 'Run ' + test.name + ' test';
trow.parentNode.appendChild(test._row);
test._row.cells[0].innerHTML = test.name;
}
var cell = test._row.cells[1];
var cns = [test.loopArg ? 'test_looping' : 'test_nonlooping'];
if (test.error) {
cns.push('test_error');
cell.innerHTML =
'<div class="error_head">' + test.error + '</div>' +
'<ul class="error_body"><li>' +
jsl.join(test.error, ': ', '</li><li>') +
'</li></ul>';
} else {
if (test.running) {
cns.push('test_running');
cell.innerHTML = 'running';
} else if (jsl.indexOf(JSLitmus._queue, test) >= 0) {
cns.push('test_pending');
cell.innerHTML = 'pending';
} else if (test.count) {
cns.push('test_done');
var hz = test.getHz(jsl.$('test_normalize').checked);
cell.innerHTML = hz != Infinity ? hz : '&infin;';
} else {
cell.innerHTML = 'ready';
}
}
cell.className = cns.join(' ');
},
/**
* Create a new test
*/
test: function(name, f) {
// Create the Test object
var test = new Test(name, f);
JSLitmus._tests.push(test);
// Re-render if the test state changes
test.onChange = JSLitmus.renderTest;
// Run the next test if this one finished
test.onStop = function(test) {
if (JSLitmus.onTestFinish) JSLitmus.onTestFinish(test);
JSLitmus.currentTest = null;
JSLitmus._nextTest();
};
// Render the new test
this.renderTest(test);
},
/**
* Add all tests to the run queue
*/
runAll: function(e) {
e = e || window.event;
var reverse = e && e.shiftKey, len = JSLitmus._tests.length;
for (var i = 0; i < len; i++) {
JSLitmus._queueTest(JSLitmus._tests[!reverse ? i : (len - i - 1)]);
}
},
/**
* Remove all tests from the run queue. The current test has to finish on
* it's own though
*/
stop: function() {
while (JSLitmus._queue.length) {
var test = JSLitmus._queue.shift();
JSLitmus.renderTest(test);
}
},
/**
* Run the next test in the run queue
*/
_nextTest: function() {
if (!JSLitmus.currentTest) {
var test = JSLitmus._queue.shift();
if (test) {
jsl.$('stop_button').disabled = false;
JSLitmus.currentTest = test;
test.run();
JSLitmus.renderTest(test);
if (JSLitmus.onTestStart) JSLitmus.onTestStart(test);
} else {
jsl.$('stop_button').disabled = true;
JSLitmus.renderChart();
}
}
},
/**
* Add a test to the run queue
*/
_queueTest: function(test) {
if (jsl.indexOf(JSLitmus._queue, test) >= 0) return;
JSLitmus._queue.push(test);
JSLitmus.renderTest(test);
JSLitmus._nextTest();
},
/**
* Generate a Google Chart URL that shows the data for all tests
*/
chartUrl: function() {
var n = JSLitmus._tests.length, markers = [], data = [];
var d, min = 0, max = -1e10;
var normalize = jsl.$('test_normalize').checked;
// Gather test data
for (var i=0; i < JSLitmus._tests.length; i++) {
var test = JSLitmus._tests[i];
if (test.count) {
var hz = test.getHz(normalize);
var v = hz != Infinity ? hz : 0;
data.push(v);
markers.push('t' + jsl.escape(test.name + '(' + jsl.toLabel(hz)+ ')') + ',000000,0,' +
markers.length + ',10');
max = Math.max(v, max);
}
}
if (markers.length <= 0) return null;
// Build chart title
var title = document.getElementsByTagName('title');
title = (title && title.length) ? title[0].innerHTML : null;
var chart_title = [];
if (title) chart_title.push(title);
chart_title.push('Ops/sec (' + platform + ')');
// Build labels
var labels = [jsl.toLabel(min), jsl.toLabel(max)];
var w = 250, bw = 15;
var bs = 5;
var h = markers.length*(bw + bs) + 30 + chart_title.length*20;
var params = {
chtt: escape(chart_title.join('|')),
chts: '000000,10',
cht: 'bhg', // chart type
chd: 't:' + data.join(','), // data set
chds: min + ',' + max, // max/min of data
chxt: 'x', // label axes
chxl: '0:|' + labels.join('|'), // labels
chsp: '0,1',
chm: markers.join('|'), // test names
chbh: [bw, 0, bs].join(','), // bar widths
// chf: 'bg,lg,0,eeeeee,0,eeeeee,.5,ffffff,1', // gradient
chs: w + 'x' + h
};
return 'http://chart.apis.google.com/chart?' + jsl.join(params, '=', '&');
}
};
JSLitmus._init();
})();

View File

@@ -1,226 +0,0 @@
/**
* QUnit v1.2.0 - A JavaScript Unit Testing Framework
*
* http://docs.jquery.com/QUnit
*
* Copyright (c) 2011 John Resig, Jörn Zaefferer
* Dual licensed under the MIT (MIT-LICENSE.txt)
* or GPL (GPL-LICENSE.txt) licenses.
*/
/** Font Family and Sizes */
#qunit-tests, #qunit-header, #qunit-banner, #qunit-testrunner-toolbar, #qunit-userAgent, #qunit-testresult {
font-family: "Helvetica Neue Light", "HelveticaNeue-Light", "Helvetica Neue", Calibri, Helvetica, Arial, sans-serif;
}
#qunit-testrunner-toolbar, #qunit-userAgent, #qunit-testresult, #qunit-tests li { font-size: small; }
#qunit-tests { font-size: smaller; }
/** Resets */
#qunit-tests, #qunit-tests ol, #qunit-header, #qunit-banner, #qunit-userAgent, #qunit-testresult {
margin: 0;
padding: 0;
}
/** Header */
#qunit-header {
padding: 0.5em 0 0.5em 1em;
color: #8699a4;
background-color: #0d3349;
font-size: 1.5em;
line-height: 1em;
font-weight: normal;
border-radius: 15px 15px 0 0;
-moz-border-radius: 15px 15px 0 0;
-webkit-border-top-right-radius: 15px;
-webkit-border-top-left-radius: 15px;
}
#qunit-header a {
text-decoration: none;
color: #c2ccd1;
}
#qunit-header a:hover,
#qunit-header a:focus {
color: #fff;
}
#qunit-banner {
height: 5px;
}
#qunit-testrunner-toolbar {
padding: 0.5em 0 0.5em 2em;
color: #5E740B;
background-color: #eee;
}
#qunit-userAgent {
padding: 0.5em 0 0.5em 2.5em;
background-color: #2b81af;
color: #fff;
text-shadow: rgba(0, 0, 0, 0.5) 2px 2px 1px;
}
/** Tests: Pass/Fail */
#qunit-tests {
list-style-position: inside;
}
#qunit-tests li {
padding: 0.4em 0.5em 0.4em 2.5em;
border-bottom: 1px solid #fff;
list-style-position: inside;
}
#qunit-tests.hidepass li.pass, #qunit-tests.hidepass li.running {
display: none;
}
#qunit-tests li strong {
cursor: pointer;
}
#qunit-tests li a {
padding: 0.5em;
color: #c2ccd1;
text-decoration: none;
}
#qunit-tests li a:hover,
#qunit-tests li a:focus {
color: #000;
}
#qunit-tests ol {
margin-top: 0.5em;
padding: 0.5em;
background-color: #fff;
border-radius: 15px;
-moz-border-radius: 15px;
-webkit-border-radius: 15px;
box-shadow: inset 0px 2px 13px #999;
-moz-box-shadow: inset 0px 2px 13px #999;
-webkit-box-shadow: inset 0px 2px 13px #999;
}
#qunit-tests table {
border-collapse: collapse;
margin-top: .2em;
}
#qunit-tests th {
text-align: right;
vertical-align: top;
padding: 0 .5em 0 0;
}
#qunit-tests td {
vertical-align: top;
}
#qunit-tests pre {
margin: 0;
white-space: pre-wrap;
word-wrap: break-word;
}
#qunit-tests del {
background-color: #e0f2be;
color: #374e0c;
text-decoration: none;
}
#qunit-tests ins {
background-color: #ffcaca;
color: #500;
text-decoration: none;
}
/*** Test Counts */
#qunit-tests b.counts { color: black; }
#qunit-tests b.passed { color: #5E740B; }
#qunit-tests b.failed { color: #710909; }
#qunit-tests li li {
margin: 0.5em;
padding: 0.4em 0.5em 0.4em 0.5em;
background-color: #fff;
border-bottom: none;
list-style-position: inside;
}
/*** Passing Styles */
#qunit-tests li li.pass {
color: #5E740B;
background-color: #fff;
border-left: 26px solid #C6E746;
}
#qunit-tests .pass { color: #528CE0; background-color: #D2E0E6; }
#qunit-tests .pass .test-name { color: #366097; }
#qunit-tests .pass .test-actual,
#qunit-tests .pass .test-expected { color: #999999; }
#qunit-banner.qunit-pass { background-color: #C6E746; }
/*** Failing Styles */
#qunit-tests li li.fail {
color: #710909;
background-color: #fff;
border-left: 26px solid #EE5757;
white-space: pre;
}
#qunit-tests > li:last-child {
border-radius: 0 0 15px 15px;
-moz-border-radius: 0 0 15px 15px;
-webkit-border-bottom-right-radius: 15px;
-webkit-border-bottom-left-radius: 15px;
}
#qunit-tests .fail { color: #000000; background-color: #EE5757; }
#qunit-tests .fail .test-name,
#qunit-tests .fail .module-name { color: #000000; }
#qunit-tests .fail .test-actual { color: #EE5757; }
#qunit-tests .fail .test-expected { color: green; }
#qunit-banner.qunit-fail { background-color: #EE5757; }
/** Result */
#qunit-testresult {
padding: 0.5em 0.5em 0.5em 2.5em;
color: #2b81af;
background-color: #D2E0E6;
border-bottom: 1px solid white;
}
/** Fixture */
#qunit-fixture {
position: absolute;
top: -10000px;
left: -10000px;
}

File diff suppressed because it is too large Load Diff

1
vendor/backbone vendored Submodule

Submodule vendor/backbone added at 3c7c8d2f1a

2
vendor/docdown vendored

1049
vendor/firebug-lite/changelog.txt vendored Normal file

File diff suppressed because it is too large Load Diff

30
vendor/firebug-lite/license.txt vendored Normal file
View File

@@ -0,0 +1,30 @@
Software License Agreement (BSD License)
Copyright (c) 2007, Parakey Inc.
All rights reserved.
Redistribution and use of this software in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above
copyright notice, this list of conditions and the
following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the
following disclaimer in the documentation and/or other
materials provided with the distribution.
* Neither the name of Parakey Inc. nor the names of its
contributors may be used to endorse or promote products
derived from this software without specific prior
written permission of Parakey Inc.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

BIN
vendor/firebug-lite/skin/xp/blank.gif vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 43 B

BIN
vendor/firebug-lite/skin/xp/buttonBg.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 167 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 171 B

331
vendor/firebug-lite/skin/xp/debugger.css vendored Normal file
View File

@@ -0,0 +1,331 @@
/* See license.txt for terms of usage */
.panelNode-script {
overflow: hidden;
font-family: monospace;
}
/************************************************************************************************/
.scriptTooltip {
position: fixed;
z-index: 2147483647;
padding: 2px 3px;
border: 1px solid #CBE087;
background: LightYellow;
font-family: monospace;
color: #000000;
}
/************************************************************************************************/
.sourceBox {
/* TODO: xxxpedro problem with sourceBox and scrolling elements */
/*overflow: scroll; /* see issue 1479 */
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 100%;
}
.sourceRow {
white-space: nowrap;
-moz-user-select: text;
}
.sourceRow.hovered {
background-color: #EEEEEE;
}
/************************************************************************************************/
.sourceLine {
-moz-user-select: none;
margin-right: 10px;
border-right: 1px solid #CCCCCC;
padding: 0px 4px 0 20px;
background: #EEEEEE no-repeat 2px 0px;
color: #888888;
white-space: pre;
font-family: monospace; /* see issue 2953 */
}
.noteInToolTip { /* below sourceLine, so it overrides it */
background-color: #FFD472;
}
.useA11y .sourceBox .sourceViewport:focus .sourceLine {
background-color: #FFFFC0;
color: navy;
border-right: 1px solid black;
}
.useA11y .sourceBox .sourceViewport:focus {
outline: none;
}
.a11y1emSize {
width: 1em;
height: 1em;
position: absolute;
}
.useA11y .panelStatusLabel:focus {
outline-offset: -2px !important;
}
.sourceBox > .sourceRow > .sourceLine {
cursor: pointer;
}
.sourceLine:hover {
text-decoration: none;
}
.sourceRowText {
white-space: pre;
}
.sourceRow[exe_line="true"] {
outline: 1px solid #D9D9B6;
margin-right: 1px;
background-color: lightgoldenrodyellow;
}
.sourceRow[executable="true"] > .sourceLine {
content: "-";
color: #4AA02C; /* Spring Green */
font-weight: bold;
}
.sourceRow[exe_line="true"] > .sourceLine {
background-image: url(chrome://firebug/skin/exe.png);
color: #000000;
}
.sourceRow[breakpoint="true"] > .sourceLine {
background-image: url(chrome://firebug/skin/breakpoint.png);
}
.sourceRow[breakpoint="true"][condition="true"] > .sourceLine {
background-image: url(chrome://firebug/skin/breakpointCondition.png);
}
.sourceRow[breakpoint="true"][disabledBreakpoint="true"] > .sourceLine {
background-image: url(chrome://firebug/skin/breakpointDisabled.png);
}
.sourceRow[breakpoint="true"][exe_line="true"] > .sourceLine {
background-image: url(chrome://firebug/skin/breakpointExe.png);
}
.sourceRow[breakpoint="true"][exe_line="true"][disabledBreakpoint="true"] > .sourceLine {
background-image: url(chrome://firebug/skin/breakpointDisabledExe.png);
}
.sourceLine.editing {
background-image: url(chrome://firebug/skin/breakpoint.png);
}
/************************************************************************************************/
.conditionEditor {
z-index: 2147483647;
position: absolute;
margin-top: 0;
left: 2px;
width: 90%;
}
.conditionEditorInner {
position: relative;
top: -26px;
height: 0;
}
.conditionCaption {
margin-bottom: 2px;
font-family: Lucida Grande, sans-serif;
font-weight: bold;
font-size: 11px;
color: #226679;
}
.conditionInput {
width: 100%;
border: 1px solid #0096C0;
font-family: monospace;
font-size: inherit;
}
.conditionEditorInner1 {
padding-left: 37px;
background: url(condBorders.png) repeat-y;
}
.conditionEditorInner2 {
padding-right: 25px;
background: url(condBorders.png) repeat-y 100% 0;
}
.conditionEditorTop1 {
background: url(condCorners.png) no-repeat 100% 0;
margin-left: 37px;
height: 35px;
}
.conditionEditorTop2 {
position: relative;
left: -37px;
width: 37px;
height: 35px;
background: url(condCorners.png) no-repeat;
}
.conditionEditorBottom1 {
background: url(condCorners.png) no-repeat 100% 100%;
margin-left: 37px;
height: 33px;
}
.conditionEditorBottom2 {
position: relative; left: -37px;
width: 37px;
height: 33px;
background: url(condCorners.png) no-repeat 0 100%;
}
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
.upsideDown {
margin-top: 2px;
}
.upsideDown .conditionEditorInner {
top: -8px;
}
.upsideDown .conditionEditorInner1 {
padding-left: 33px;
background: url(condBordersUps.png) repeat-y;
}
.upsideDown .conditionEditorInner2 {
padding-right: 25px;
background: url(condBordersUps.png) repeat-y 100% 0;
}
.upsideDown .conditionEditorTop1 {
background: url(condCornersUps.png) no-repeat 100% 0;
margin-left: 33px;
height: 25px;
}
.upsideDown .conditionEditorTop2 {
position: relative;
left: -33px;
width: 33px;
height: 25px;
background: url(condCornersUps.png) no-repeat;
}
.upsideDown .conditionEditorBottom1 {
background: url(condCornersUps.png) no-repeat 100% 100%;
margin-left: 33px;
height: 43px;
}
.upsideDown .conditionEditorBottom2 {
position: relative;
left: -33px;
width: 33px;
height: 43px;
background: url(condCornersUps.png) no-repeat 0 100%;
}
/************************************************************************************************/
.breakpointsGroupListBox {
overflow: hidden;
}
.breakpointBlockHead {
position: relative;
padding-top: 4px;
}
.breakpointBlockHead > .checkbox {
margin-right: 4px;
}
.breakpointBlockHead > .objectLink-sourceLink {
top: 4px;
right: 20px;
background-color: #FFFFFF; /* issue 3308 */
}
.breakpointBlockHead > .closeButton {
position: absolute;
top: 2px;
right: 2px;
}
.breakpointCheckbox {
margin-top: 0;
vertical-align: top;
}
.breakpointName {
margin-left: 4px;
font-weight: bold;
}
.breakpointRow[aria-checked="false"] > .breakpointBlockHead > *,
.breakpointRow[aria-checked="false"] > .breakpointCode {
opacity: 0.5;
}
.breakpointRow[aria-checked="false"] .breakpointCheckbox,
.breakpointRow[aria-checked="false"] .objectLink-sourceLink,
.breakpointRow[aria-checked="false"] .closeButton,
.breakpointRow[aria-checked="false"] .breakpointMutationType {
opacity: 1.0 !important;
}
.breakpointCode {
overflow: hidden;
white-space: nowrap;
padding-left: 24px;
padding-bottom: 2px;
border-bottom: 1px solid #D7D7D7;
font-family: monospace;
color: DarkGreen;
}
.breakpointCondition {
white-space: nowrap;
padding-left: 24px;
padding-bottom: 2px;
border-bottom: 1px solid #D7D7D7;
font-family: monospace;
color: Gray;
}
.breakpointBlock-breakpoints > .groupHeader {
display: none;
}
.breakpointBlock-monitors > .breakpointCode {
padding: 0;
}
.breakpointBlock-errorBreakpoints .breakpointCheckbox,
.breakpointBlock-monitors .breakpointCheckbox {
display: none;
}
.breakpointHeader {
margin: 0 !important;
border-top: none !important;
}

BIN
vendor/firebug-lite/skin/xp/detach.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 655 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 586 B

BIN
vendor/firebug-lite/skin/xp/disable.gif vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 340 B

BIN
vendor/firebug-lite/skin/xp/disable.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 543 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 344 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 512 B

BIN
vendor/firebug-lite/skin/xp/down.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 637 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 543 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 526 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 447 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 365 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 457 B

View File

@@ -0,0 +1,817 @@
.fbBtnPressed {
background: #ECEBE3;
padding: 3px 6px 2px 7px !important;
margin: 1px 0 0 1px;
_margin: 1px -1px 0 1px;
border: 1px solid #ACA899 !important;
border-color: #ACA899 #ECEBE3 #ECEBE3 #ACA899 !important;
}
.fbToolbarButtons {
display: none;
}
#fbStatusBarBox {
display: none;
}
/************************************************************************************************
Error Popup
*************************************************************************************************/
#fbErrorPopup {
position: absolute;
right: 0;
bottom: 0;
height: 19px;
width: 75px;
background: url(sprite.png) #f1f2ee 0 0;
z-index: 999;
}
#fbErrorPopupContent {
position: absolute;
right: 0;
top: 1px;
height: 18px;
width: 75px;
_width: 74px;
border-left: 1px solid #aca899;
}
#fbErrorIndicator {
position: absolute;
top: 2px;
right: 5px;
}
.fbBtnInspectActive {
background: #aaa;
color: #fff !important;
}
/************************************************************************************************
General
*************************************************************************************************/
html, body {
margin: 0;
padding: 0;
overflow: hidden;
}
body {
font-family: Lucida Grande, Tahoma, sans-serif;
font-size: 11px;
background: #fff;
}
.clear {
clear: both;
}
/************************************************************************************************
Mini Chrome
*************************************************************************************************/
#fbMiniChrome {
display: none;
right: 0;
height: 27px;
background: url(sprite.png) #f1f2ee 0 0;
margin-left: 1px;
}
#fbMiniContent {
display: block;
position: relative;
left: -1px;
right: 0;
top: 1px;
height: 25px;
border-left: 1px solid #aca899;
}
#fbToolbarSearch {
float: right;
border: 1px solid #ccc;
margin: 0 5px 0 0;
background: #fff url(search.png) no-repeat 4px 2px;
padding-left: 20px;
font-size: 11px;
}
#fbToolbarErrors {
float: right;
margin: 1px 4px 0 0;
font-size: 11px;
}
#fbLeftToolbarErrors {
float: left;
margin: 7px 0px 0 5px;
font-size: 11px;
}
.fbErrors {
padding-left: 20px;
height: 14px;
background: url(errorIcon.png) no-repeat;
color: #f00;
font-weight: bold;
}
#fbMiniErrors {
display: inline;
display: none;
float: right;
margin: 5px 2px 0 5px;
}
#fbMiniIcon {
float: right;
margin: 3px 4px 0;
height: 20px;
width: 20px;
float: right;
background: url(sprite.png) 0 -135px;
cursor: pointer;
}
/************************************************************************************************
Master Layout
*************************************************************************************************/
#fbChrome {
position: fixed;
overflow: hidden;
height: 100%;
width: 100%;
border-collapse: collapse;
background: #fff;
}
#fbTop {
height: 49px;
}
#fbToolbar {
position: absolute;
z-index: 5;
width: 100%;
top: 0;
background: url(sprite.png) #f1f2ee 0 0;
height: 27px;
font-size: 11px;
overflow: hidden;
}
#fbPanelBarBox {
top: 27px;
position: absolute;
z-index: 8;
width: 100%;
background: url(sprite.png) #dbd9c9 0 -27px;
height: 22px;
}
#fbContent {
height: 100%;
vertical-align: top;
}
#fbBottom {
height: 18px;
background: #fff;
}
/************************************************************************************************
Sub-Layout
*************************************************************************************************/
/* fbToolbar
*************************************************************************************************/
#fbToolbarIcon {
float: left;
padding: 4px 5px 0;
}
#fbToolbarIcon a {
display: block;
height: 20px;
width: 20px;
background: url(sprite.png) 0 -135px;
text-decoration: none;
cursor: default;
}
#fbToolbarButtons {
float: left;
padding: 4px 2px 0 5px;
}
#fbToolbarButtons a {
text-decoration: none;
display: block;
float: left;
color: #000;
padding: 4px 8px 4px;
cursor: default;
}
#fbToolbarButtons a:hover {
color: #333;
padding: 3px 7px 3px;
border: 1px solid #fff;
border-bottom: 1px solid #bbb;
border-right: 1px solid #bbb;
}
#fbStatusBarBox {
position: relative;
top: 5px;
line-height: 19px;
cursor: default;
}
.fbToolbarSeparator{
overflow: hidden;
border: 1px solid;
border-color: transparent #fff transparent #777;
_border-color: #eee #fff #eee #777;
height: 7px;
margin: 10px 6px 0 0;
float: left;
}
.fbStatusBar span {
color: #808080;
padding: 0 4px 0 0;
}
.fbStatusBar span a {
text-decoration: none;
color: black;
}
.fbStatusBar span a:hover {
color: blue;
cursor: pointer;
}
#fbWindowButtons {
position: absolute;
white-space: nowrap;
right: 0;
top: 0;
height: 17px;
_width: 50px;
padding: 5px 0 5px 5px;
z-index: 6;
background: url(sprite.png) #f1f2ee 0 0;
}
/* fbPanelBarBox
*************************************************************************************************/
#fbPanelBar1 {
width: 255px; /* fixed width to avoid tabs breaking line */
z-index: 8;
left: 0;
white-space: nowrap;
background: url(sprite.png) #dbd9c9 0 -27px;
position: absolute;
left: 4px;
}
#fbPanelBar2Box {
background: url(sprite.png) #dbd9c9 0 -27px;
position: absolute;
height: 22px;
width: 300px; /* fixed width to avoid tabs breaking line */
z-index: 9;
right: 0;
}
#fbPanelBar2 {
position: absolute;
width: 290px; /* fixed width to avoid tabs breaking line */
height: 22px;
padding-left: 10px;
}
/* body
*************************************************************************************************/
.fbPanel {
display: none;
}
#fbPanelBox1, #fbPanelBox2 {
max-height: inherit;
height: 100%;
font-size: 11px;
}
#fbPanelBox2 {
background: #fff;
}
#fbPanelBox2 {
width: 300px;
background: #fff;
}
#fbPanel2 {
padding-left: 6px;
background: #fff;
}
.hide {
overflow: hidden !important;
position: fixed !important;
display: none !important;
visibility: hidden !important;
}
/* fbBottom
*************************************************************************************************/
#fbCommand {
height: 18px;
}
#fbCommandBox {
position: absolute;
width: 100%;
height: 18px;
bottom: 0;
overflow: hidden;
z-index: 9;
background: #fff;
border: 0;
border-top: 1px solid #ccc;
}
#fbCommandIcon {
position: absolute;
color: #00f;
top: 2px;
left: 7px;
display: inline;
font: 11px Monaco, monospace;
z-index: 10;
}
#fbCommandLine {
position: absolute;
width: 100%;
top: 0;
left: 0;
border: 0;
margin: 0;
padding: 2px 0 2px 32px;
font: 11px Monaco, monospace;
z-index: 9;
}
div.fbFitHeight {
overflow: auto;
_position: absolute;
}
/************************************************************************************************
Layout Controls
*************************************************************************************************/
/* fbToolbar buttons
*************************************************************************************************/
#fbWindowButtons a {
font-size: 1px;
width: 16px;
height: 16px;
display: block;
float: right;
margin-right: 4px;
text-decoration: none;
cursor: default;
}
#fbWindow_btClose {
background: url(sprite.png) 0 -119px;
}
#fbWindow_btClose:hover {
background: url(sprite.png) -16px -119px;
}
#fbWindow_btDetach {
background: url(sprite.png) -32px -119px;
}
#fbWindow_btDetach:hover {
background: url(sprite.png) -48px -119px;
}
/* fbPanelBarBox tabs
*************************************************************************************************/
.fbTab {
text-decoration: none;
display: none;
float: left;
width: auto;
float: left;
cursor: default;
font-family: Lucida Grande, Tahoma, sans-serif;
font-size: 11px;
font-weight: bold;
height: 22px;
color: #565656;
}
.fbPanelBar span {
display: block;
float: left;
}
.fbPanelBar .fbTabL,.fbPanelBar .fbTabR {
height: 22px;
width: 8px;
}
.fbPanelBar .fbTabText {
padding: 4px 1px 0;
}
a.fbTab:hover {
background: url(sprite.png) 0 -73px;
}
a.fbTab:hover .fbTabL {
background: url(sprite.png) -16px -96px;
}
a.fbTab:hover .fbTabR {
background: url(sprite.png) -24px -96px;
}
.fbSelectedTab {
background: url(sprite.png) #f1f2ee 0 -50px !important;
color: #000;
}
.fbSelectedTab .fbTabL {
background: url(sprite.png) 0 -96px !important;
}
.fbSelectedTab .fbTabR {
background: url(sprite.png) -8px -96px !important;
}
/* splitters
*************************************************************************************************/
#fbHSplitter {
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 5px;
overflow: hidden;
cursor: n-resize !important;
background: url(pixel_transparent.gif);
z-index: 9;
}
#fbHSplitter.fbOnMovingHSplitter {
height: 100%;
z-index: 100;
}
.fbVSplitter {
background: #ece9d8;
color: #000;
border: 1px solid #716f64;
border-width: 0 1px;
border-left-color: #aca899;
width: 4px;
cursor: e-resize;
overflow: hidden;
right: 294px;
text-decoration: none;
z-index: 9;
position: absolute;
height: 100%;
top: 27px;
_width: 6px;
}
/************************************************************************************************/
div.lineNo {
font: 11px Monaco, monospace;
float: left;
display: inline;
position: relative;
margin: 0;
padding: 0 5px 0 20px;
background: #eee;
color: #888;
border-right: 1px solid #ccc;
text-align: right;
}
pre.nodeCode {
font: 11px Monaco, monospace;
margin: 0;
padding-left: 10px;
overflow: hidden;
/*
_width: 100%;
/**/
}
/************************************************************************************************/
.nodeControl {
margin-top: 3px;
margin-left: -14px;
float: left;
width: 9px;
height: 9px;
overflow: hidden;
cursor: default;
background: url(tree_open.gif);
_float: none;
_display: inline;
_position: absolute;
}
div.nodeMaximized {
background: url(tree_close.gif);
}
div.objectBox-element {
padding: 1px 3px;
}
.objectBox-selector{
cursor: default;
}
.selectedElement{
background: highlight;
/* background: url(roundCorner.svg); Opera */
color: #fff !important;
}
.selectedElement span{
color: #fff !important;
}
/* Webkit CSS Hack - bug in "highlight" named color */
@media screen and (-webkit-min-device-pixel-ratio:0) {
.selectedElement{
background: #316AC5;
color: #fff !important;
}
}
/************************************************************************************************/
/************************************************************************************************/
.logRow * {
font-size: 11px;
}
.logRow {
position: relative;
border-bottom: 1px solid #D7D7D7;
padding: 2px 4px 1px 6px;
background-color: #FFFFFF;
}
.logRow-command {
font-family: Monaco, monospace;
color: blue;
}
.objectBox-string,
.objectBox-text,
.objectBox-number,
.objectBox-function,
.objectLink-element,
.objectLink-textNode,
.objectLink-function,
.objectBox-stackTrace,
.objectLink-profile {
font-family: Monaco, monospace;
}
.objectBox-null {
padding: 0 2px;
border: 1px solid #666666;
background-color: #888888;
color: #FFFFFF;
}
.objectBox-string {
color: red;
white-space: pre;
}
.objectBox-number {
color: #000088;
}
.objectBox-function {
color: DarkGreen;
}
.objectBox-object {
color: DarkGreen;
font-weight: bold;
font-family: Lucida Grande, sans-serif;
}
.objectBox-array {
color: #000;
}
/************************************************************************************************/
.logRow-info,.logRow-error,.logRow-warning {
background: #fff no-repeat 2px 2px;
padding-left: 20px;
padding-bottom: 3px;
}
.logRow-info {
background-image: url(infoIcon.png);
}
.logRow-warning {
background-color: cyan;
background-image: url(warningIcon.png);
}
.logRow-error {
background-color: LightYellow;
background-image: url(errorIcon.png);
color: #f00;
}
.errorMessage {
vertical-align: top;
color: #f00;
}
.objectBox-sourceLink {
position: absolute;
right: 4px;
top: 2px;
padding-left: 8px;
font-family: Lucida Grande, sans-serif;
font-weight: bold;
color: #0000FF;
}
/************************************************************************************************/
.logRow-group {
background: #EEEEEE;
border-bottom: none;
}
.logGroup {
background: #EEEEEE;
}
.logGroupBox {
margin-left: 24px;
border-top: 1px solid #D7D7D7;
border-left: 1px solid #D7D7D7;
}
/************************************************************************************************/
.selectorTag,.selectorId,.selectorClass {
font-family: Monaco, monospace;
font-weight: normal;
}
.selectorTag {
color: #0000FF;
}
.selectorId {
color: DarkBlue;
}
.selectorClass {
color: red;
}
/************************************************************************************************/
.objectBox-element {
font-family: Monaco, monospace;
color: #000088;
}
.nodeChildren {
padding-left: 26px;
}
.nodeTag {
color: blue;
cursor: pointer;
}
.nodeValue {
color: #FF0000;
font-weight: normal;
}
.nodeText,.nodeComment {
margin: 0 2px;
vertical-align: top;
}
.nodeText {
color: #333333;
font-family: Monaco, monospace;
}
.nodeComment {
color: DarkGreen;
}
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
.nodeHidden, .nodeHidden * {
color: #888888;
}
.nodeHidden .nodeTag {
color: #5F82D9;
}
.nodeHidden .nodeValue {
color: #D86060;
}
.selectedElement .nodeHidden, .selectedElement .nodeHidden * {
color: SkyBlue !important;
}
/************************************************************************************************/
.log-object {
/*
_position: relative;
_height: 100%;
/**/
}
.property {
position: relative;
clear: both;
height: 15px;
}
.propertyNameCell {
vertical-align: top;
float: left;
width: 28%;
position: absolute;
left: 0;
z-index: 0;
}
.propertyValueCell {
float: right;
width: 68%;
background: #fff;
position: absolute;
padding-left: 5px;
display: table-cell;
right: 0;
z-index: 1;
/*
_position: relative;
/**/
}
.propertyName {
font-weight: bold;
}
.FirebugPopup {
height: 100% !important;
}
.FirebugPopup #fbWindowButtons {
display: none !important;
}
.FirebugPopup #fbHSplitter {
display: none !important;
}

View File

@@ -0,0 +1,20 @@
/************************************************************************************************/
#fbToolbarSearch {
background-image: url(search.gif) !important;
}
/************************************************************************************************/
.fbErrors {
background-image: url(errorIcon.gif) !important;
}
/************************************************************************************************/
.logRow-info {
background-image: url(infoIcon.gif) !important;
}
.logRow-warning {
background-image: url(warningIcon.gif) !important;
}
.logRow-error {
background-image: url(errorIcon.gif) !important;
}

3147
vendor/firebug-lite/skin/xp/firebug.css vendored Normal file

File diff suppressed because it is too large Load Diff

215
vendor/firebug-lite/skin/xp/firebug.html vendored Normal file
View File

@@ -0,0 +1,215 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/DTD/strict.dtd">
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8">
<title>Firebug Lite</title>
<!-- An empty script to avoid FOUC when loading the stylesheet -->
<script type="text/javascript"></script>
<style type="text/css" media="screen">@import "firebug.css";</style>
<style>html,body{margin:0;padding:0;overflow:hidden;}</style>
</head>
<body class="fbBody">
<table id="fbChrome" cellpadding="0" cellspacing="0" border="0">
<tbody>
<tr>
<!-- Interface - Top Area -->
<td id="fbTop" colspan="2">
<!--
<div>
--><!-- <span id="fbToolbarErrors" class="fbErrors">2 errors</span> --><!--
<input type="text" id="fbToolbarSearch" />
</div>
-->
<!-- Window Buttons -->
<div id="fbWindowButtons">
<a id="fbWindow_btDeactivate" class="fbSmallButton fbHover" title="Deactivate Firebug for this web page">&nbsp;</a>
<a id="fbWindow_btDetach" class="fbSmallButton fbHover" title="Open Firebug in popup window">&nbsp;</a>
<a id="fbWindow_btClose" class="fbSmallButton fbHover" title="Minimize Firebug">&nbsp;</a>
</div>
<!-- Toolbar buttons and Status Bar -->
<div id="fbToolbar">
<div id="fbToolbarContent">
<!-- Firebug Button -->
<span id="fbToolbarIcon">
<a id="fbFirebugButton" class="fbIconButton" class="fbHover" target="_blank">&nbsp;</a>
</span>
<!--
<span id="fbLeftToolbarErrors" class="fbErrors">2 errors</span>
-->
<!-- Toolbar Buttons -->
<span id="fbToolbarButtons">
<!-- Fixed Toolbar Buttons -->
<span id="fbFixedButtons">
<a id="fbChrome_btInspect" class="fbButton fbHover" title="Click an element in the page to inspect">Inspect</a>
</span>
<!-- Console Panel Toolbar Buttons -->
<span id="fbConsoleButtons" class="fbToolbarButtons">
<a id="fbConsole_btClear" class="fbButton fbHover" title="Clear the console">Clear</a>
</span>
<!-- HTML Panel Toolbar Buttons -->
<!--
<span id="fbHTMLButtons" class="fbToolbarButtons">
<a id="fbHTML_btEdit" class="fbHover" title="Edit this HTML">Edit</a>
</span>
-->
</span>
<!-- Status Bar -->
<span id="fbStatusBarBox">
<span class="fbToolbarSeparator"></span>
<!-- HTML Panel Status Bar -->
<!--
<span id="fbHTMLStatusBar" class="fbStatusBar fbToolbarButtons">
</span>
-->
</span>
</div>
</div>
<!-- PanelBars -->
<div id="fbPanelBarBox">
<!-- Main PanelBar -->
<div id="fbPanelBar1" class="fbPanelBar">
<a id="fbConsoleTab" class="fbTab fbHover">
<span class="fbTabL"></span>
<span class="fbTabText">Console</span>
<span class="fbTabMenuTarget"></span>
<span class="fbTabR"></span>
</a>
<a id="fbHTMLTab" class="fbTab fbHover">
<span class="fbTabL"></span>
<span class="fbTabText">HTML</span>
<span class="fbTabR"></span>
</a>
<a class="fbTab fbHover">
<span class="fbTabL"></span>
<span class="fbTabText">CSS</span>
<span class="fbTabR"></span>
</a>
<a class="fbTab fbHover">
<span class="fbTabL"></span>
<span class="fbTabText">Script</span>
<span class="fbTabR"></span>
</a>
<a class="fbTab fbHover">
<span class="fbTabL"></span>
<span class="fbTabText">DOM</span>
<span class="fbTabR"></span>
</a>
</div>
<!-- Side PanelBars -->
<div id="fbPanelBar2Box" class="hide">
<div id="fbPanelBar2" class="fbPanelBar">
<!--
<a class="fbTab fbHover">
<span class="fbTabL"></span>
<span class="fbTabText">Style</span>
<span class="fbTabR"></span>
</a>
<a class="fbTab fbHover">
<span class="fbTabL"></span>
<span class="fbTabText">Layout</span>
<span class="fbTabR"></span>
</a>
<a class="fbTab fbHover">
<span class="fbTabL"></span>
<span class="fbTabText">DOM</span>
<span class="fbTabR"></span>
</a>
-->
</div>
</div>
</div>
<!-- Horizontal Splitter -->
<div id="fbHSplitter">&nbsp;</div>
</td>
</tr>
<!-- Interface - Main Area -->
<tr id="fbContent">
<!-- Panels -->
<td id="fbPanelBox1">
<div id="fbPanel1" class="fbFitHeight">
<div id="fbConsole" class="fbPanel"></div>
<div id="fbHTML" class="fbPanel"></div>
</div>
</td>
<!-- Side Panel Box -->
<td id="fbPanelBox2" class="hide">
<!-- VerticalSplitter -->
<div id="fbVSplitter" class="fbVSplitter">&nbsp;</div>
<!-- Side Panels -->
<div id="fbPanel2" class="fbFitHeight">
<!-- HTML Side Panels -->
<div id="fbHTML_Style" class="fbPanel"></div>
<div id="fbHTML_Layout" class="fbPanel"></div>
<div id="fbHTML_DOM" class="fbPanel"></div>
</div>
<!-- Large Command Line -->
<textarea id="fbLargeCommandLine" class="fbFitHeight"></textarea>
<!-- Large Command Line Buttons -->
<div id="fbLargeCommandButtons">
<a id="fbCommand_btRun" class="fbButton fbHover">Run</a>
<a id="fbCommand_btClear" class="fbButton fbHover">Clear</a>
<a id="fbSmallCommandLineIcon" class="fbSmallButton fbHover"></a>
</div>
</td>
</tr>
<!-- Interface - Bottom Area -->
<tr id="fbBottom" class="hide">
<!-- Command Line -->
<td id="fbCommand" colspan="2">
<div id="fbCommandBox">
<div id="fbCommandIcon">&gt;&gt;&gt;</div>
<input id="fbCommandLine" name="fbCommandLine" type="text" />
<a id="fbLargeCommandLineIcon" class="fbSmallButton fbHover"></a>
</div>
</td>
</tr>
</tbody>
</table>
<span id="fbMiniChrome">
<span id="fbMiniContent">
<span id="fbMiniIcon" title="Open Firebug Lite"></span>
<span id="fbMiniErrors" class="fbErrors"><!-- 2 errors --></span>
</span>
</span>
<!--
<div id="fbErrorPopup">
<div id="fbErrorPopupContent">
<div id="fbErrorIndicator" class="fbErrors">2 errors</div>
</div>
</div>
-->
</body>
</html>

BIN
vendor/firebug-lite/skin/xp/firebug.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

BIN
vendor/firebug-lite/skin/xp/group.gif vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 158 B

272
vendor/firebug-lite/skin/xp/html.css vendored Normal file
View File

@@ -0,0 +1,272 @@
/* See license.txt for terms of usage */
.panelNode-html {
-moz-box-sizing: padding-box;
padding: 4px 0 0 2px;
}
.nodeBox {
position: relative;
font-family: Monaco, monospace;
padding-left: 13px;
-moz-user-select: -moz-none;
}
.nodeBox.search-selection {
-moz-user-select: text;
}
.twisty {
position: absolute;
left: 0px;
top: 0px;
width: 14px;
height: 14px;
}
.nodeChildBox {
margin-left: 12px;
display: none;
}
.nodeLabel,
.nodeCloseLabel {
margin: -2px 2px 0 2px;
border: 2px solid transparent;
-moz-border-radius: 3px;
padding: 0 2px;
color: #000088;
}
.nodeCloseLabel {
display: none;
}
.nodeTag {
cursor: pointer;
color: blue;
}
.nodeValue {
color: #FF0000;
font-weight: normal;
}
.nodeText,
.nodeComment {
margin: 0 2px;
vertical-align: top;
}
.nodeText {
color: #333333;
}
.nodeWhiteSpace {
border: 1px solid LightGray;
white-space: pre; /* otherwise the border will be collapsed around zero pixels */
margin-left: 1px;
color: gray;
}
.nodeWhiteSpace_Space {
border: 1px solid #ddd;
}
.nodeTextEntity {
border: 1px solid gray;
white-space: pre; /* otherwise the border will be collapsed around zero pixels */
margin-left: 1px;
}
.nodeComment {
color: DarkGreen;
}
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
.nodeBox.highlightOpen > .nodeLabel {
background-color: #EEEEEE;
}
.nodeBox.highlightOpen > .nodeCloseLabel,
.nodeBox.highlightOpen > .nodeChildBox,
.nodeBox.open > .nodeCloseLabel,
.nodeBox.open > .nodeChildBox {
display: block;
}
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
.nodeBox.selected > .nodeLabel > .nodeLabelBox,
.nodeBox.selected > .nodeLabel {
border-color: Highlight;
background-color: Highlight;
color: HighlightText !important;
}
.nodeBox.selected > .nodeLabel > .nodeLabelBox,
.nodeBox.selected > .nodeLabel > .nodeLabelBox > .nodeTag,
.nodeBox.selected > .nodeLabel > .nodeLabelBox > .nodeAttr > .nodeValue,
.nodeBox.selected > .nodeLabel > .nodeLabelBox > .nodeText {
color: inherit !important;
}
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
.nodeBox.highlighted > .nodeLabel {
border-color: Highlight !important;
background-color: cyan !important;
color: #000000 !important;
}
.nodeBox.highlighted > .nodeLabel > .nodeLabelBox,
.nodeBox.highlighted > .nodeLabel > .nodeLabelBox > .nodeTag,
.nodeBox.highlighted > .nodeLabel > .nodeLabelBox > .nodeAttr > .nodeValue,
.nodeBox.highlighted > .nodeLabel > .nodeLabelBox > .nodeText {
color: #000000 !important;
}
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
.nodeBox.nodeHidden .nodeLabel > .nodeLabelBox,
.nodeBox.nodeHidden .nodeCloseLabel,
.nodeBox.nodeHidden .nodeLabel > .nodeLabelBox > .nodeText,
.nodeBox.nodeHidden .nodeText {
color: #888888;
}
.nodeBox.nodeHidden .nodeLabel > .nodeLabelBox > .nodeTag,
.nodeBox.nodeHidden .nodeCloseLabel > .nodeCloseLabelBox > .nodeTag {
color: #5F82D9;
}
.nodeBox.nodeHidden .nodeLabel > .nodeLabelBox > .nodeAttr > .nodeValue {
color: #D86060;
}
.nodeBox.nodeHidden.selected > .nodeLabel > .nodeLabelBox,
.nodeBox.nodeHidden.selected > .nodeLabel > .nodeLabelBox > .nodeTag,
.nodeBox.nodeHidden.selected > .nodeLabel > .nodeLabelBox > .nodeAttr > .nodeValue,
.nodeBox.nodeHidden.selected > .nodeLabel > .nodeLabelBox > .nodeText {
color: SkyBlue !important;
}
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
.nodeBox.mutated > .nodeLabel,
.nodeAttr.mutated,
.nodeValue.mutated,
.nodeText.mutated,
.nodeBox.mutated > .nodeText {
background-color: #EFFF79;
color: #FF0000 !important;
}
.nodeBox.selected.mutated > .nodeLabel,
.nodeBox.selected.mutated > .nodeLabel > .nodeLabelBox,
.nodeBox.selected > .nodeLabel > .nodeLabelBox > .nodeAttr.mutated > .nodeValue,
.nodeBox.selected > .nodeLabel > .nodeLabelBox > .nodeAttr > .nodeValue.mutated,
.nodeBox.selected > .nodeLabel > .nodeLabelBox > .nodeText.mutated {
background-color: #EFFF79;
border-color: #EFFF79;
color: #FF0000 !important;
}
/************************************************************************************************/
.logRow-dirxml {
padding-left: 0;
}
.soloElement > .nodeBox {
padding-left: 0;
}
.useA11y .nodeLabel.focused {
outline: 2px solid #FF9933;
-moz-outline-radius: 3px;
outline-offset: -2px;
}
.useA11y .nodeLabelBox:focus {
outline: none;
}
/************************************************************************************************/
.breakpointCode .twisty {
display: none;
}
.breakpointCode .nodeBox.containerNodeBox,
.breakpointCode .nodeLabel {
padding-left: 0px;
margin-left: 0px;
font-family: Monaco, monospace !important;
}
.breakpointCode .nodeTag,
.breakpointCode .nodeAttr,
.breakpointCode .nodeText,
.breakpointCode .nodeValue,
.breakpointCode .nodeLabel {
color: DarkGreen !important;
}
.breakpointMutationType {
position: absolute;
top: 4px;
right: 20px;
color: gray;
}
/************************************************************************************************/
/************************************************************************************************/
/************************************************************************************************/
/************************************************************************************************/
/************************************************************************************************/
/************************************************************************************************/
/************************************************************************************************/
/************************************************************************************************/
/************************************************************************************************/
/************************************************************************************************/
/************************************************************************************************/
/* Twisties */
.twisty,
.logRow-errorMessage > .hasTwisty > .errorTitle,
.logRow-log > .objectBox-array.hasTwisty,
.logRow-spy .spyHead .spyTitle,
.logGroup > .logRow,
.memberRow.hasChildren > .memberLabelCell > .memberLabel,
.hasHeaders .netHrefLabel,
.netPageRow > .netCol > .netPageTitle {
background-image: url(twistyClosed.png);
background-repeat: no-repeat;
background-position: 2px 2px;
min-height: 12px;
}
.logRow-errorMessage > .hasTwisty.opened > .errorTitle,
.logRow-log > .objectBox-array.hasTwisty.opened,
.logRow-spy.opened .spyHead .spyTitle,
.logGroup.opened > .logRow,
.memberRow.hasChildren.opened > .memberLabelCell > .memberLabel,
.nodeBox.highlightOpen > .nodeLabel > .twisty,
.nodeBox.open > .nodeLabel > .twisty,
.netRow.opened > .netCol > .netHrefLabel,
.netPageRow.opened > .netCol > .netPageTitle {
background-image: url(twistyOpen.png);
}
.twisty {
background-position: 4px 4px;
}

BIN
vendor/firebug-lite/skin/xp/infoIcon.gif vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 359 B

BIN
vendor/firebug-lite/skin/xp/infoIcon.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 524 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

BIN
vendor/firebug-lite/skin/xp/min.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 552 B

BIN
vendor/firebug-lite/skin/xp/minHover.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 485 B

BIN
vendor/firebug-lite/skin/xp/off.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 742 B

BIN
vendor/firebug-lite/skin/xp/offHover.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 680 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 43 B

View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg">
<rect fill="white" x="0" y="0" width="100%" height="100%" />
<rect fill="highlight" x="0" y="0" width="100%" height="100%" rx="2px"/>
</svg>

After

Width:  |  Height:  |  Size: 234 B

BIN
vendor/firebug-lite/skin/xp/search.gif vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 550 B

BIN
vendor/firebug-lite/skin/xp/search.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 685 B

BIN
vendor/firebug-lite/skin/xp/shadow.gif vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.3 KiB

BIN
vendor/firebug-lite/skin/xp/shadow2.gif vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

BIN
vendor/firebug-lite/skin/xp/sprite.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 39 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 438 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 261 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 436 B

BIN
vendor/firebug-lite/skin/xp/tabLeft.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 449 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 220 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 207 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 192 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 142 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 148 B

BIN
vendor/firebug-lite/skin/xp/tabMid.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 262 B

BIN
vendor/firebug-lite/skin/xp/tabRight.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 448 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 117 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 273 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 242 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 300 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 202 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 334 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 309 B

BIN
vendor/firebug-lite/skin/xp/up.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 619 B

BIN
vendor/firebug-lite/skin/xp/upActive.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 551 B

BIN
vendor/firebug-lite/skin/xp/upHover.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 526 B

Some files were not shown because too many files have changed in this diff Show More